diff --git a/devlog.md b/devlog.md index f7c6a2e..e2487e8 100644 --- a/devlog.md +++ b/devlog.md @@ -970,3 +970,30 @@ than the characters since I made sure to pick types of passives that were alread Finished literally everything needed to make passives work, now I only need to actually make them. The more I work on this the clearer the parts that slow me down because they're annoying to work with become. Generally it's higher level "glue" type of code, rather than the code that actually makes the thing work as a unit. So the node refactor for instance is addressing a lot of this glue code by making it conceptually the same thing, which should make it easier to work with. The rect cutting UI idea does something similar the high level part of UI, which tends to be mostly layouting. And so on. + +# Day 62 - 19/04/21 + +20 out of 40 passives done today. + +| Name | Description | +| --- | --- | +| Ouroboros Technique R | rotating around yourself to the right makes units release projectiles | +| Ouroboros Technique L | rotating around yourself to the left grants +25% defense to all units | +| Wall Echo | hitting walls has a 34% chance of releasing 2 projectiles | +| Wall Rider | hitting walls grants a 25% movement speed buff for 1 second | +| Centipede | +20% movement speed | +| Intimidation | enemies spawn with -20% max HP | +| Vulnerability | enemies take +20% damage | +| Temporal Chains | all enemies move 20% slower | +| Amplify | +25% AoE damage | +| Amplify X | +50% AoE damage | +| Resonance | all AoE attacks deal +5% damage per enemy hit | +| Ballista | +25% damage to rangers and rogues | +| Ballista X | +50% damage to rangers and rogues | +| Point Blank | projectiles deal up to +100% damage up close and down to -50% damage far away | +| Longshot | projectiles deal up to +100% damage far away and down to -50% damage up close | +| Blunt Arrow | all arrows fired by rangers have a 20% chance to knockback | +| Explosive Arrow | all arrows fired by rangers have a 30% chance to explode, dealing 20% AoE damage | +| Divine Machine Arrow | all arrows fired by rangers have a 40% chance to seek enemies and pierce 5 times | +| Chronomancy | all mages cast their spells 25% faster | +| Awakening | every round 1 mage is granted +100% cast speed and damage for that round | diff --git a/enemies.lua b/enemies.lua index 9ba005a..dd30f1f 100644 --- a/enemies.lua +++ b/enemies.lua @@ -216,6 +216,21 @@ function Seeker:init(args) elseif self.spawner then self.color = purple[0]:clone() end + + local player = main.current.player + if player and player.intimidation and not self.boss and not self.tank then + self.buff_hp_m = 0.8 + self:calculate_stats() + self.hp = self.max_hp + end + + if player and player.vulnerability then + self.vulnerable = true + end + + if player and player.temporal_chains then + self.temporal_chains_mvspd_m = 0.8 + end end @@ -239,7 +254,7 @@ function Seeker:update(dt) if self.slowed then self.slow_mvspd_m = self.slowed else self.slow_mvspd_m = 1 end - self.buff_mvspd_m = (self.speed_boosting_mvspd_m or 1)*(self.slow_mvspd_m or 1) + self.buff_mvspd_m = (self.speed_boosting_mvspd_m or 1)*(self.slow_mvspd_m or 1)*(self.temporal_chains_mvspd_m or 1) self:calculate_stats() @@ -366,7 +381,9 @@ function Seeker:hit(damage, projectile) self:show_hp() local actual_damage = self:calculate_damage(damage)*self.stun_dmg_m*self.bane_dmg_m + if self.vulnerable then actual_damage = actual_damage*1.2 end self.hp = self.hp - actual_damage + print(actual_damage) main.current.damage_dealt = main.current.damage_dealt + actual_damage if projectile and projectile.spawn_critters_on_hit then diff --git a/main.lua b/main.lua index 004ad37..4fc26ab 100644 --- a/main.lua +++ b/main.lua @@ -938,22 +938,22 @@ function init() passive_descriptions = { ['ouroboros_technique_r'] = '[fg]rotating around yourself to the right makes units release projectiles', ['ouroboros_technique_l'] = '[fg]rotating around yourself to the left grants [yellow]+25%[fg] defense to all units', - ['wall_echo'] = '[fg]hitting walls has a [yellow]25%[fg] chance of releasing [yellow]2[fg] projectiles', + ['wall_echo'] = '[fg]hitting walls has a [yellow]34%[fg] chance of releasing [yellow]2[fg] projectiles', ['wall_rider'] = '[fg]hitting walls grants a [yellow]25%[fg] movement speed buff to your snake for [yellow]1[fg] second', ['centipede'] = '[yellow]+20%[fg] movement speed', ['intimidation'] = '[fg]enemies spawn with [yellow]-20%[fg] max HP', ['vulnerability'] = '[fg]all enemies take [yellow]+20%[fg] damage', ['temporal_chains'] = '[fg]all enemies move [yellow]20%[fg] slower', - ['amplify'] = '[fg]all units that deal AoE damage gain [yellow]+25%[fg] AoE damage', - ['amplify_x'] = '[yellow]+25%[fg] AoE damage if all your units only deal AoE damage', + ['amplify'] = '[yellow]+25%[fg] AoE damage', + ['amplify_x'] = '[yellow]+50%[fg] AoE damage', ['resonance'] = '[fg]all AoE attacks deal [yellow]+5%[fg] damage per unit hit', - ['ballista'] = "[fg]all units that release projectiles and don't deal AoE damage gain [yellow]+25%[fg] damage", - ['ballista_x'] = "[yellow]+25%[fg] damage if all your units only release projectiles and don't deal AoE damage", + ['ballista'] = '[yellow]+25%[fg] damage to rangers and rogues ', + ['ballista_x'] = '[yellow]+50%[fg] damage to rangers and rogues', ['point_blank'] = '[fg]projectiles deal up to [yellow]+100%[fg] damage up close and down to [yellow]-50%[fg] damage far away', ['longshot'] = '[fg]projectiles deal up to [yellow]+100%[fg] damage far away and down to [yellow]-50%[fg] up close', ['blunt_arrow'] = '[fg]all arrows fired by rangers have a [yellow]20%[fg] chance to knockback', - ['explosive_arrow'] = '[fg]arrows fired by rangers have a [yellow]20%[fg] chance to explode, dealing [yellow]20%[fg] AoE damage', - ['divine_machine_arrow'] = '[fg]arrows fired by rangers have a [yellow]20%[fg] chance to seek enemies and pierce [yellow]5[fg] times', + ['explosive_arrow'] = '[fg]arrows fired by rangers have a [yellow]30%[fg] chance to explode, dealing [yellow]20%[fg] AoE damage', + ['divine_machine_arrow'] = '[fg]arrows fired by rangers have a [yellow]40%[fg] chance to seek enemies and pierce [yellow]5[fg] times', ['chronomancy'] = '[fg]all mages cast their spells [yellow]25%[fg] faster', ['awakening'] = '[fg]every round [yellow]1[fg] mage is granted [yellow]+100%[fg] attack speed and damage for that round', ['divine_punishment'] = '[fg]periodically deal [yellow]10X[fg] damage to all enemies, where [yellow]X[fg] is how many mages you have', @@ -990,10 +990,10 @@ function init() ['vulnerability'] = 2, ['temporal_chains'] = 1, ['amplify'] = 1, - ['amplify_x'] = 1, - ['resonance'] = 2, + ['amplify_x'] = 2, + ['resonance'] = 3, ['ballista'] = 1, - ['ballista_x'] = 1, + ['ballista_x'] = 2, ['point_blank'] = 2, ['longshot'] = 2, ['blunt_arrow'] = 1, @@ -1044,12 +1044,59 @@ function init() [24] = {20, 30, 50}, } + --[[ + * ['ouroboros_technique_r'] = 2, + * ['ouroboros_technique_l'] = 2, + * ['wall_echo'] = 1, + * ['wall_rider'] = 1, + * ['centipede'] = 1, + * ['intimidation'] = 2, + * ['vulnerability'] = 2, + * ['temporal_chains'] = 1, + * ['amplify'] = 1, + * ['amplify_x'] = 1, + * ['resonance'] = 2, + * ['ballista'] = 1, + * ['ballista_x'] = 1, + * ['point_blank'] = 2, + * ['longshot'] = 2, + * ['blunt_arrow'] = 1, + * ['explosive_arrow'] = 2, + * ['divine_machine_arrow'] = 3, + * ['chronomancy'] = 2, + * ['awakening'] = 2, + ['divine_punishment'] = 3, + ['berserking'] = 1, + ['unwavering_stance'] = 1, + ['ultimatum'] = 2, + ['flying_daggers'] = 3, + ['assassination'] = 1, + ['magnify'] = 1, + ['concentrated_fire'] = 2, + ['unleash'] = 1, + ['reinforce'] = 2, + ['payback'] = 2, + ['blessing'] = 1, + ['hex_master'] = 1, + ['whispers_of_doom'] = 2, + ['force_push'] = 1, + ['heavy_impact'] = 2, + ['crucio'] = 3, + ['immolation'] = 2, + ['call_of_the_void'] = 2, + ['spawning_pool'] = 1, + ['hive'] = 3, + ]]-- + gold = 2 - passives = {'ouroboros_technique_r'} + passives = {'awakening'} main = Main() main:add(BuyScreen'buy_screen') main:go_to('buy_screen', 2, { + {character = 'wizard', level = 1}, + {character = 'spellblade', level = 1}, + --[[ {character = 'swordsman', level = 3}, {character = 'wizard', level = 3}, {character = 'scout', level = 3}, @@ -1062,6 +1109,7 @@ function init() {character = 'juggernaut', level = 3}, {character = 'vagrant', level = 3}, {character = 'stormweaver', level = 3}, + ]]-- }, passives) --[[ main:add(Arena'arena') diff --git a/player.lua b/player.lua index b32e7c3..9ca8dba 100644 --- a/player.lua +++ b/player.lua @@ -6,7 +6,7 @@ function Player:init(args) self:init_game_object(args) self:init_unit() - for k, v in pairs(self.passives) do self[v] = true end + if self.passives then for k, v in pairs(self.passives) do self[v] = true end end self.color = character_colors[self.character] self:set_as_rectangle(9, 9, 'dynamic', 'player') @@ -439,21 +439,61 @@ function Player:init(args) if self.ouroboros_technique_r then self.t:every(0.1, function() if self.move_right_pressed and love.timer.getTime() - self.move_right_pressed > 1 then - local units = self:get_all_units() - local cx, cy = 0, 0 - for _, unit in ipairs(units) do - cx = cx + unit.x - cy = cy + unit.y + local target = self:get_closest_object_in_shape(Circle(self.x, self.y, 96), main.current.enemies) + if target then + local units = self:get_all_units() + local unit = random:table(units) + unit:barrage(unit:angle_to_object(target), 1) + else + local units = self:get_all_units() + local cx, cy = 0, 0 + for _, unit in ipairs(units) do + cx = cx + unit.x + cy = cy + unit.y + end + cx = cx/#units + cy = cy/#units + local unit = random:table(units) + unit:barrage(unit:angle_from_point(cx, cy), 1) end - cx = cx/#units - cy = cy/#units - local unit = random:table(units) - unit:barrage(unit:angle_from_point(cx, cy), 1) end end) end - self.first_frame_calculate_stats = true + if self.centipede then self.centipede_mvspd_m = 1.2 end + if self.amplify then self.amplify_area_dmg_m = 1.25 end + if self.amplify_x then self.amplify_x_area_dmg_m = 1.5 end + + if self.ballista then + if table.any(self.classes, function(v) return v == 'ranger' end) or table.any(self.classes, function(v) return v == 'rogue' end) then + self.ballista_dmg_m = 1.25 + end + end + + if self.ballista_x then + if table.any(self.classes, function(v) return v == 'ranger' end) or table.any(self.classes, function(v) return v == 'rogue' end) then + self.ballista_x_dmg_m = 1.5 + end + end + + if self.chronomancy then + if table.any(self.classes, function(v) return v == 'mage' end) then + self.chronomancy_aspd_m = 1.25 + end + end + + if self.leader and self.awakening then + local units = self:get_all_units() + local mages = {} + for _, unit in ipairs(units) do + if table.any(unit.classes, function(v) return v == 'mage' end) then + table.insert(mages, unit) + end + end + local mage = random:table(mages) + mage.awakening_aspd_m = 2 + mage.awakening_dmg_m = 2 + end end @@ -573,12 +613,26 @@ function Player:update(dt) else self.dot_dmg_m = 1 end end + if self.ouroboros_technique_l and self.leader then + local units = self:get_all_units() + if self.move_left_pressed and love.timer.getTime() - self.move_left_pressed > 1 then + for _, unit in ipairs(units) do + unit.ouroboros_def_m = 1.25 + end + else + for _, unit in ipairs(units) do + unit.ouroboros_def_m = 1 + end + end + end + self.buff_def_a = (self.warrior_def_a or 0) - self.buff_aspd_m = (self.chronomancer_aspd_m or 1)*(self.vagrant_aspd_m or 1)*(self.outlaw_aspd_m or 1)*(self.fairy_aspd_m or 1)*(self.psyker_aspd_m or 1) - self.buff_dmg_m = (self.squire_dmg_m or 1)*(self.vagrant_dmg_m or 1)*(self.enchanter_dmg_m or 1)*(self.swordsman_dmg_m or 1)*(self.flagellant_dmg_m or 1)*(self.psyker_dmg_m or 1) - self.buff_def_m = (self.squire_def_m or 1) + self.buff_aspd_m = (self.chronomancer_aspd_m or 1)*(self.vagrant_aspd_m or 1)*(self.outlaw_aspd_m or 1)*(self.fairy_aspd_m or 1)*(self.psyker_aspd_m or 1)*(self.chronomancy_aspd_m or 1)*(self.awakening_aspd_m or 1) + self.buff_dmg_m = (self.squire_dmg_m or 1)*(self.vagrant_dmg_m or 1)*(self.enchanter_dmg_m or 1)*(self.swordsman_dmg_m or 1)*(self.flagellant_dmg_m or 1)*(self.psyker_dmg_m or 1)*(self.ballista_dmg_m or 1)*(self.ballista_x_dmg_m or 1)*(self.awakening_dmg_m or 1) + self.buff_def_m = (self.squire_def_m or 1)*(self.ouroboros_def_m or 1) self.buff_area_size_m = (self.nuker_area_size_m or 1) - self.buff_area_dmg_m = (self.nuker_area_dmg_m or 1) + self.buff_area_dmg_m = (self.nuker_area_dmg_m or 1)*(self.amplify_area_dmg_m or 1)*(self.amplify_x_area_dmg_m or 1) + self.buff_mvspd_m = (self.wall_rider_mvspd_m or 1)*(self.centipede_mvspd_m or 1) self:calculate_stats() if self.attack_sensor then self.attack_sensor:move_to(self.x, self.y) end @@ -593,7 +647,15 @@ function Player:update(dt) if input.move_right.released then self.move_right_pressed = nil end if input.move_left.down then self.r = self.r - 1.66*math.pi*dt end if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end - self:set_velocity(self.v*math.cos(self.r), self.v*math.sin(self.r)) + + local total_v = 0 + local units = self:get_all_units() + for _, unit in ipairs(units) do + total_v = total_v + unit.max_v + end + total_v = total_v/#units + + self:set_velocity(total_v*math.cos(self.r), total_v*math.sin(self.r)) if not main.current.won and not main.current.choosing_passives then local vx, vy = self:get_velocity() @@ -672,6 +734,26 @@ function Player:on_collision_enter(other, contact) pop1:play{pitch = r + 0.05*i, volume = 0.2} end) end + + if self.wall_echo then + if random:bool(34) then + local target = self:get_closest_object_in_shape(Circle(self.x, self.y, 96), main.current.enemies) + if target then + self:barrage(self:angle_to_object(target), 2) + else + local r = Vector(contact:getNormal()):angle() + self:barrage(r, 2) + end + end + end + + if self.wall_rider then + local units = self:get_all_units() + for _, unit in ipairs(units) do unit.wall_rider_mvspd_m = 1.25 end + trigger:after(1, function() + for _, unit in ipairs(units) do unit.wall_rider_mvspd_m = 1 end + end, 'wall_rider') + end end elseif table.any(main.current.enemies, function(v) return other:is(v) end) then @@ -1065,6 +1147,13 @@ function Projectile:init(args) end) end + if self.parent.divine_machine_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then + if random:bool(40) then + self.homing = true + self.pierce = 5 + end + end + if self.homing then self.homing = false self.t:after(0.1, function() @@ -1072,6 +1161,15 @@ function Projectile:init(args) self.closest_sensor = Circle(self.x, self.y, 64) end) end + + self.distance_travelled = 0 + self.distance_dmg_m = 1 + + if self.parent.blunt_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then + if random:bool(20) then + self.knockback = 10 + end + end end @@ -1098,7 +1196,6 @@ function Projectile:update(dt) self:move_along_angle(self.v, self.r + (self.orbit_r or 0)) end - if self.character == 'sage' then self.pull_sensor:move_to(self.x, self.y) local enemies = self:get_objects_in_shape(self.pull_sensor, main.current.enemies) @@ -1107,6 +1204,17 @@ function Projectile:update(dt) end self.vr = self.vr + self.dvr*dt end + + if self.parent.point_blank or self.parent.longshot then + self.distance_travelled = self.distance_travelled + math.length(self:get_velocity()) + if self.parent.point_blank and self.parent.longshot then + self.distance_dmg_m = 1 + elseif self.parent.point_blank then + self.distance_dmg_m = math.remap(self.distance_travelled, 0, 15000, 2, 0.75) + elseif self.parent.longshot then + self.distance_dmg_m = math.remap(self.distance_travelled, 0, 15000, 0.75, 2) + end + end end @@ -1144,16 +1252,18 @@ function Projectile:die(x, y, r, n) self.dead = true if self.character == 'wizard' then - Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*32, color = self.color, dmg = self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level} + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*32, color = self.color, dmg = self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self} elseif self.character == 'blade' then - Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*64, color = self.color, dmg = self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level} + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*64, color = self.color, dmg = self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self} elseif self.character == 'cannoneer' then - Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*96, color = self.color, dmg = 2*self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level} - self.parent.t:every(0.2, function() - _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} - Area{group = main.current.effects, x = self.x + random:float(-32, 32), y = self.y + random:float(-32, 32), r = self.r + random:float(0, 2*math.pi), w = self.parent.area_size_m*48, color = self.color, - dmg = 0.5*self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level} - end, 5) + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*96, color = self.color, dmg = 2*self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self} + if self.level == 3 then + self.parent.t:every(0.2, function() + _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} + Area{group = main.current.effects, x = self.x + random:float(-32, 32), y = self.y + random:float(-32, 32), r = self.r + random:float(0, 2*math.pi), w = self.parent.area_size_m*48, color = self.color, + dmg = 0.5*self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self} + end, 5) + end end end @@ -1251,10 +1361,10 @@ function Projectile:on_trigger_enter(other, contact) hit3:play{pitch = random:float(0.95, 1.05), volume = 0.35} end - other:hit(self.dmg, self) + other:hit(self.dmg*(self.distance_dmg_m or 1), self) if self.character == 'wizard' and self.level == 3 then - Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*32, color = self.color, dmg = self.parent.area_dmg_m*self.dmg, character = self.character} + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r, w = self.parent.area_size_m*32, color = self.color, dmg = self.parent.area_dmg_m*self.dmg, character = self.character, parent = self} end if self.character == 'hunter' and random:bool(40) then @@ -1297,7 +1407,7 @@ function Projectile:on_trigger_enter(other, contact) table.insert(self.infused_enemies_hit, src) local dst = src:get_random_object_in_shape(Circle(src.x, src.y, (stormweaver_level == 3 and 128 or 64)), main.current.enemies, self.infused_enemies_hit) if dst then - dst:hit(0.2*self.dmg) + dst:hit(0.2*self.dmg*(self.distance_dmg_m or 1)) LightningLine{group = main.current.effects, src = src, dst = dst} src = dst end @@ -1316,6 +1426,14 @@ function Projectile:on_trigger_enter(other, contact) if self.knockback then other:push(self.knockback*(self.knockback_m or 1), self.r) end + + if self.parent.explosive_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then + if random:bool(30) then + _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} + Area{group = main.current.effects, x = self.x, y = self.y, r = self.r + random:float(0, 2*math.pi), w = self.parent.area_size_m*32, color = self.color, + dmg = 0.2*self.parent.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self} + end + end end end @@ -1329,21 +1447,28 @@ function Area:init(args) self.shape = Rectangle(self.x, self.y, 1.5*self.w, 1.5*self.w, self.r) local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies) for _, enemy in ipairs(enemies) do + local resonance_dmg = 0 if self.character == 'elementor' then - enemy:hit(2*self.dmg) + if self.parent.resonance then resonance_dmg = 2*self.dmg*0.05*#enemies end + enemy:hit(2*self.dmg + resonance_dmg) if self.level == 3 then enemy:slow(0.4, 6) end elseif self.character == 'swordsman' then - enemy:hit(self.dmg + self.dmg*0.33*#enemies) + if self.parent.resonance then resonance_dmg = (self.dmg + self.dmg*0.33*#enemies)*0.05*#enemies end + enemy:hit(self.dmg + self.dmg*0.33*#enemies + resonance_dmg) elseif self.character == 'blade' and self.level == 3 then - enemy:hit(self.dmg + self.dmg*0.5*#enemies) + if self.parent.resonance then resonance_dmg = (self.dmg + self.dmg*0.5*#enemies)*0.05*#enemies end + enemy:hit(self.dmg + self.dmg*0.5*#enemies + resonance_dmg) elseif self.character == 'highlander' then - enemy:hit(6*self.dmg) + if self.parent.resonance then resonance_dmg = 6*self.dmg*0.05*#enemies end + enemy:hit(6*self.dmg + resonance_dmg) elseif self.character == 'launcher' then - enemy:curse('launcher', 4, (self.level == 3 and 6*self.dmg or 2*self.dmg), self.parent) + if self.parent.resonance then resonance_dmg = (self.level == 3 and 6*self.dmg*0.05*#enemies or 2*self.dmg*0.05*#enemies) end + enemy:curse('launcher', 4, (self.level == 3 and 6*self.dmg or 2*self.dmg) + resonance_dmg, self.parent) else - enemy:hit(self.dmg) + if self.parent.resonance then resonance_dmg = self.dmg*0.05*#enemies end + enemy:hit(self.dmg + resonance_dmg) end HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1} for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = self.color} end