From 0496138d700b67a3f4845a3423785967581caa65 Mon Sep 17 00:00:00 2001 From: a327ex Date: Fri, 18 Jun 2021 18:36:00 -0300 Subject: [PATCH] Item update 5/5 --- arena.lua | 34 ++++++++++------ assets/sounds/Weapon Swap 2.ogg | Bin 0 -> 18561 bytes buy_screen.lua | 41 ++++++++++--------- enemies.lua | 70 +++++++++++++++++++++++++++----- main.lua | 48 ++++++++++++---------- media.lua | 4 +- objects.lua | 2 +- player.lua | 17 ++++---- todo | 62 ++++++++++++++++------------ 9 files changed, 178 insertions(+), 100 deletions(-) create mode 100644 assets/sounds/Weapon Swap 2.ogg diff --git a/arena.lua b/arena.lua index 2b74564..e0cb96d 100644 --- a/arena.lua +++ b/arena.lua @@ -53,6 +53,8 @@ function Arena:on_enter(from, level, units, passives, shop_level, shop_xp, lock) self.main:enable_trigger_between('projectile', 'enemy') self.main:enable_trigger_between('enemy_projectile', 'player') self.main:enable_trigger_between('player', 'enemy_projectile') + self.main:enable_trigger_between('enemy_projectile', 'enemy') + self.main:enable_trigger_between('enemy', 'enemy_projectile') self.main:enable_trigger_between('player', 'ghost') self.main:enable_trigger_between('ghost', 'player') @@ -407,7 +409,7 @@ function Arena:update(dt) main:add(BuyScreen'buy_screen') locked_state = nil system.save_run() - main:go_to('buy_screen', 0, {}, passives, 1, 0) + main:go_to('buy_screen', 1, {}, passives, 1, 0) end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end} @@ -595,7 +597,7 @@ function Arena:update(dt) main:add(BuyScreen'buy_screen') locked_state = nil system.save_run() - main:go_to('buy_screen', 0, {}, passives, 1, 0) + main:go_to('buy_screen', 1, {}, passives, 1, 0) end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end @@ -863,8 +865,16 @@ function Arena:quit() trigger:tween(1, _G, {slow_amount = 0}, math.linear, function() slow_amount = 0 end, 'slow_amount') trigger:tween(4, camera, {x = gw/2, y = gh/2, r = 0}, math.linear, function() camera.x, camera.y, camera.r = gw/2, gh/2, 0 end) self:set_passives() - RerollButton{group = main.current.ui, x = 40, y = 40, parent = self, force_update = true} + RerollButton{group = main.current.ui, x = gw - 40, y = 40, parent = self, force_update = true} self.shop_text = Text({{text = '[wavy_mid, fg]gold: [yellow]' .. gold, font = pixul_font, alignment = 'center'}}, global_text_tags) + + self.build_text = Text2{group = self.ui, x = 40, y = 20, force_update = true, lines = {{text = "[wavy_mid, fg]your build", font = pixul_font, alignment = 'center'}}} + for i, unit in ipairs(self.units) do + CharacterPart{group = self.ui, x = 20, y = 40 + (i-1)*19, character = unit.character, level = unit.level, force_update = true, cant_click = true, parent = self} + Text2{group = self.ui, x = 20 + 14 + pixul_font:get_text_width(unit.character)/2, y = 40 + (i-1)*19, force_update = true, lines = { + {text = '[' .. character_color_strings[unit.character] .. ']' .. unit.character, font = pixul_font, alignment = 'left'} + }} + end else self:transition() end @@ -890,15 +900,15 @@ function Arena:set_passives(from_reroll) local passive_2 = random:table_remove(run_passive_pool) local passive_3 = random:table_remove(run_passive_pool) if passive_1 then - table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 0*(card_w + 20) + card_w/2, y = gh/2 - 6, w = card_w, h = card_h, card_i = 1, arena = self, passive = passive_1, force_update = true}) + table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 0*(card_w + 20) + card_w/2 + 45, y = gh/2 - 6 + 10, w = card_w, h = card_h, card_i = 1, arena = self, passive = passive_1, force_update = true}) end if passive_2 then - table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 1*(card_w + 20) + card_w/2, y = gh/2 - 6, w = card_w, h = card_h, card_i = 2, arena = self, passive = passive_2, force_update = true}) + table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 1*(card_w + 20) + card_w/2 + 45, y = gh/2 - 6 + 10, w = card_w, h = card_h, card_i = 2, arena = self, passive = passive_2, force_update = true}) end if passive_3 then - table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 2*(card_w + 20) + card_w/2, y = gh/2 - 6, w = card_w, h = card_h, card_i = 3, arena = self, passive = passive_3, force_update = true}) + table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 2*(card_w + 20) + card_w/2 + 45, y = gh/2 - 6 + 10, w = card_w, h = card_h, card_i = 3, arena = self, passive = passive_3, force_update = true}) end - self.passive_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 65, lines = {{text = '[fg, wavy]choose one', font = fat_font, alignment = 'center'}}} + self.passive_text = Text2{group = self.ui, x = gw/2 + 45, y = gh/2 - 65 + 10, lines = {{text = '[fg, wavy]choose one', font = fat_font, alignment = 'center'}}} if not passive_1 and not passive_2 and not passive_3 then self:transition() end @@ -965,7 +975,7 @@ function Arena:draw() if self.choosing_passives or self.won or self.paused or self.died then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end self.ui:draw() - if self.shop_text then self.shop_text:draw(40, 20) end + if self.shop_text then self.shop_text:draw(gw - 40, 20) end if self.in_credits then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent_2) end self.credits:draw() @@ -1007,7 +1017,7 @@ function Arena:die() max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() - main:go_to('buy_screen', 0, {}, passives, 1, 0) + main:go_to('buy_screen', 1, {}, passives, 1, 0) end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end} end) @@ -1078,7 +1088,7 @@ end function Arena:gain_gold() local merchant = self.player:get_unit'merchant' self.gold_gained = random:int(level_to_gold_gained[self.level][1], level_to_gold_gained[self.level][2]) - self.interest = math.min(math.floor(gold/5), 5) + (merchant and math.floor(gold/10) or 0) + self.interest = math.min(math.floor(gold/5), 5) + math.min((merchant and math.floor(gold/10) or 0), 10) gold = gold + self.gold_gained + self.gold_picked_up + self.interest end @@ -1103,8 +1113,8 @@ function Arena:transition() end slow_amount = 1 main:add(BuyScreen'buy_screen') - system.save_run(self.level, gold, self.units, self.passives, self.shop_level, self.shop_xp, run_passive_pool, locked_state) - main:go_to('buy_screen', self.level, self.units, self.passives, self.shop_level, self.shop_xp) + system.save_run(self.level+1, gold, self.units, self.passives, self.shop_level, self.shop_xp, run_passive_pool, locked_state) + main:go_to('buy_screen', self.level+1, self.units, self.passives, self.shop_level, self.shop_xp) t.t:after(0.1, function() t.text:set_text({ {text = '[nudge_down, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']gold gained: ' .. tostring(self.gold_gained or 0) .. ' + ' .. tostring(self.gold_picked_up or 0), font = pixul_font, diff --git a/assets/sounds/Weapon Swap 2.ogg b/assets/sounds/Weapon Swap 2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..37ab3b815206de52b2ea15aa5b4bddc73c7680c5 GIT binary patch literal 18561 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 >&!Ve_jbGh=0kE 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 ln3w>dwY7F9+FOsNaGlo=F$QD9Xfzr 0 then - if random:bool((main.current.mercenary_level == 2 and 20) or (main.current.mercenary_level == 1 and 10) or 0) then + if random:bool((main.current.mercenary_level == 2 and 16) or (main.current.mercenary_level == 1 and 8) or 0) then trigger:after(0.01, function() Gold{group = main.current.main, x = self.x, y = self.y} end) @@ -500,12 +500,9 @@ function Seeker:hit(damage, projectile, dot) if self.exploder then if self.silenced then return end - shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4} + mine1:play{pitch = random:float(0.95, 1.05), volume = 0.5} trigger:after(0.01, function() - local n = math.floor(8 + current_new_game_plus*1.5) - for i = 1, n do - EnemyProjectile{group = main.current.main, x = self.x, y = self.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*self.level, dmg = 1.5*self.dmg} - end + ExploderMine{group = main.current.main, x = self.x, y = self.y, color = blue[0], parent = self} end) end @@ -573,8 +570,9 @@ end function Seeker:push(f, r, push_invulnerable) local n = 1 - if self.tank then n = 0.4 - 0.01*self.level end - if self.boss then n = 0.1 end + if self.tank then n = 0.7 end + if self.boss then n = 0.2 end + if self.level == 25 and self.boss then n = 0.7 end self.push_invulnerable = push_invulnerable self.push_force = n*f self.being_pushed = true @@ -672,6 +670,50 @@ function Seeker:apply_dot(dmg, duration) end +ExploderMine = Object:extend() +ExploderMine:implement(GameObject) +function ExploderMine:init(args) + self:init_game_object(args) + self.hfx:add('hit', 1) + self.vr = 0 + self.dvr = random:float(-math.pi/4, math.pi/4) + self.rs = 0 + self.t:tween(0.05, self, {rs = args.rs}, math.cubic_in_out, function() + self.spring:pull(0.15) + self.t:every(0.8 - current_new_game_plus*0.1, function() + mine1:play{pitch = 1 + self.t:get_every_iteration'mine_count'*0.1, volume = 0.5} + self.spring:pull(0.5, 200, 10) + self.hfx:use('hit', 0.5, 200, 10, 0.2) + end, 3, function() + shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4} + cannoneer1:play{pitch = random:float(0.95, 1.05), volume = 0.4} + for i = 1, 4 do HitParticle{group = main.current.effects, x = self.x, y = self.y, r = random:float(0, 2*math.pi), color = self.color} end + HitCircle{group = main.current.effects, x = self.x, y = self.y} + local n = math.floor(8 + current_new_game_plus*1.5) + for i = 1, n do + EnemyProjectile{group = main.current.main, x = self.x, y = self.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*self.parent.level, dmg = 1.5*self.parent.dmg} + end + self.dead = true + end, 'mine_count') + end) + --[[ + ]]-- +end + + +function ExploderMine:update(dt) + self:update_game_object(dt) + self.vr = self.vr + self.dvr*dt +end + + +function ExploderMine:draw() + graphics.push(self.x, self.y, 0, self.spring.x, self.spring.x) + graphics.circle(self.x, self.y, 2.5, self.hfx.hit.f and fg[0] or self.color) + graphics.pop() +end + + EnemyCritter = Object:extend() @@ -930,5 +972,11 @@ function EnemyProjectile:on_trigger_enter(other, contact) self:die(self.x, self.y, nil, random:int(2, 3)) other:hit(1000) end + + elseif other:is(Seeker) or other:is(EnemyCritter) then + if self.source == 'shooter' then + self:die(self.x, self.y, nil, random:int(2, 3)) + other:hit(0.5*self.dmg) + end end end diff --git a/main.lua b/main.lua index 96bd7bc..4cd504a 100644 --- a/main.lua +++ b/main.lua @@ -18,6 +18,7 @@ function init() input:bind('enter', {'space', 'return', 'fleft', 'fdown', 'fright'}) local s = {tags = {sfx}} + mine1 = Sound('Weapon Swap 2.ogg', s) level_up1 = Sound('Buff 4.ogg', s) unlock1 = Sound('Unlock 3.ogg', s) gambler1 = Sound('Collect 5.ogg', s) @@ -565,8 +566,8 @@ function init() ['lich'] = function(lvl) return '[fg]launches a slow projectile that jumps [yellow]7[fg] times, dealing [yellow]' .. 2*get_character_stat('lich', lvl, 'dmg') .. '[fg] damage per hit' end, ['cryomancer'] = function(lvl) return '[fg]nearby enemies take [yellow]' .. get_character_stat('cryomancer', lvl, 'dmg') .. '[fg] damage per second' end, ['pyromancer'] = function(lvl) return '[fg]nearby enemies take [yellow]' .. get_character_stat('pyromancer', lvl, 'dmg') .. '[fg] damage per second' end, - ['corruptor'] = function(lvl) return '[fg]spawn [yellow]3[fg] small critters if the corruptor kills an enemy' end, - ['beastmaster'] = function(lvl) return '[fg]spawn [yellow]2[fg] small critters if the beastmaster crits' end, + ['corruptor'] = function(lvl) return '[fg]shoots an arrow that deals [yellow]' .. get_character_stat('corruptor', lvl, 'dmg') .. '[fg] damage, spawn [yellow]3[fg] critters if it kills' end, + ['beastmaster'] = function(lvl) return '[fg]throws a knife that deals [yellow]' .. get_character_stat('beastmaster', lvl, 'dmg') .. '[fg] damage, spawn [yellow]2[fg] critters if it crits' end, ['launcher'] = function(lvl) return '[fg]all nearby enemies are pushed after [yellow]4[fg] seconds, taking [yellow]' .. 2*get_character_stat('launcher', lvl, 'dmg') .. '[fg] damage on wall hit' end, ['jester'] = function(lvl) return "[fg]curses [yellow]6[fg] nearby enemies for [yellow]6[fg] seconds, they will explode into [yellow]4[fg] knives on death" end, ['assassin'] = function(lvl) return '[fg]throws a piercing knife that deals [yellow]' .. get_character_stat('assassin', lvl, 'dmg') .. '[fg] damage + [yellow]' .. @@ -589,7 +590,7 @@ function init() ['warden'] = function(lvl) return '[fg]creates a force field around a random unit that prevents enemies from entering' end, ['psychic'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('psychic', lvl, 'dmg') .. ' AoE[fg] damage' end, ['miner'] = function(lvl) return '[fg]picking up gold releases [yellow]4[fg] homing projectiles that each deal [yellow]' .. get_character_stat('miner', lvl, 'dmg') .. ' [fg]damage' end, - ['merchant'] = function(lvl) return '[fg]gain [yellow]+1[fg] interest for every [yellow]10[fg] gold' end, + ['merchant'] = function(lvl) return '[fg]gain [yellow]+1[fg] interest for every [yellow]10[fg] gold, up to a max of [yellow]+10[fg] from the merchant' end, ['usurer'] = function(lvl) return '[fg]curses [yellow]3[fg] nearby enemies indefinitely with debt, dealing [yellow]' .. get_character_stat('usurer', lvl, 'dmg') .. '[fg] damage per second' end, ['gambler'] = function(lvl) return '[fg]deal [yellow]2X[fg] damage to a single random enemy where X is how much gold you have' end, ['thief'] = function(lvl) return '[fg]throws a knife that deals [yellow]' .. 2*get_character_stat('thief', lvl, 'dmg') .. '[fg] damage and chains [yellow]5[fg] times' end, @@ -737,8 +738,8 @@ function init() ['lich'] = function() return '[fg]chain frost slows enemies hit by [yellow]80%[fg] for [yellow]2[fg] seconds and chains [yellow]+7[fg] times' end, ['cryomancer'] = function() return '[fg]enemies are also slowed by [yellow]60%[fg] while in the area' end, ['pyromancer'] = function() return '[fg]enemies killed by the pyromancer explode, dealing [yellow]' .. get_character_stat('pyromancer', 3, 'dmg') .. '[fg] AoE damage' end, - ['corruptor'] = function() return '[fg]spawn [yellow]3[fg] small critters if the corruptor hits an enemy' end, - ['beastmaster'] = function() return '[fg]spawn [yellow]2[fg] small critters if the beastmaster gets hit' end, + ['corruptor'] = function() return '[fg]spawn [yellow]2[fg] small critters if the corruptor hits an enemy' end, + ['beastmaster'] = function() return '[fg]spawn [yellow]4[fg] small critters if the beastmaster gets hit' end, ['launcher'] = function() return '[fg]enemies launched take [yellow]300%[fg] more damage when they hit walls' end, ['jester'] = function() return '[fg]all knives seek enemies and pierce [yellow]2[fg] times' end, ['assassin'] = function() return '[fg]poison inflicted from crits deals [yellow]8x[fg] damage' end, @@ -794,8 +795,8 @@ function init() ['lich'] = function() return '[light_bg]chain frost slows enemies hit by 80% for 2 seconds and chains +7 times' end, ['cryomancer'] = function() return '[light_bg]enemies are also slowed by 60% while in the area' end, ['pyromancer'] = function() return '[light_bg]enemies killed by the pyromancer explode, dealing ' .. get_character_stat('pyromancer', 3, 'dmg') .. ' AoE damage' end, - ['corruptor'] = function() return '[light_bg]spawn 3 small critters if the corruptor hits an enemy' end, - ['beastmaster'] = function() return '[light_bg]spawn 2 small critters if the beastmaster gets hit' end, + ['corruptor'] = function() return '[light_bg]spawn 2 small critters if the corruptor hits an enemy' end, + ['beastmaster'] = function() return '[light_bg]spawn 4 small critters if the beastmaster gets hit' end, ['launcher'] = function() return '[light_bg]enemies launched take 300% more damage when they hit walls' end, ['jester'] = function() return '[light_bg]curses 6 enemies and all knives seek enemies and pierce 2 times' end, ['assassin'] = function() return '[light_bg]poison inflicted from crits deals 8x damage' end, @@ -935,12 +936,12 @@ function init() return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4[light_bg]/[' .. ylb3(lvl) .. ']6 [fg]- sorcerers repeat their attacks once every [' .. ylb1(lvl) .. ']4[light_bg]/[' .. ylb2(lvl) .. ']3[light_bg]/[' .. ylb3(lvl) .. ']2[fg] attacks' end, - ['mercenary'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+10%[light_bg]/[' .. ylb2(lvl) .. ']+20% [fg]chance for enemies to drop gold on death' end, + ['mercenary'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+8%[light_bg]/[' .. ylb2(lvl) .. ']+16% [fg]chance for enemies to drop gold on death' end, } tier_to_characters = { - [1] = {'vagrant', 'swordsman', 'magician', 'archer', 'scout', 'cleric', 'arcanist', 'miner'}, - [2] = {'wizard', 'saboteur', 'sage', 'squire', 'dual_gunner', 'hunter', 'chronomancer', 'barbarian', 'cryomancer', 'beastmaster', 'jester', 'carver', 'psychic', 'witch', 'silencer', 'outlaw', 'merchant'}, + [1] = {'vagrant', 'swordsman', 'magician', 'archer', 'scout', 'cleric', 'arcanist', 'merchant'}, + [2] = {'wizard', 'saboteur', 'sage', 'squire', 'dual_gunner', 'hunter', 'chronomancer', 'barbarian', 'cryomancer', 'beastmaster', 'jester', 'carver', 'psychic', 'witch', 'silencer', 'outlaw', 'miner'}, [3] = {'elementor', 'stormweaver', 'spellblade', 'psykeeper', 'engineer', 'juggernaut', 'pyromancer', 'host', 'assassin', 'bane', 'barrager', 'infestor', 'flagellant', 'illusionist', 'usurer', 'gambler'}, [4] = {'priest', 'highlander', 'psykino', 'fairy', 'blade', 'plague_doctor', 'cannoneer', 'vulcanist', 'warden', 'corruptor', 'thief'}, } @@ -998,8 +999,8 @@ function init() ['vulcanist'] = 4, ['warden'] = 4, ['psychic'] = 2, - ['miner'] = 1, - ['merchant'] = 2, + ['miner'] = 2, + ['merchant'] = 1, ['usurer'] = 3, ['gambler'] = 3, ['thief'] = 4, @@ -1493,22 +1494,27 @@ function init() main = Main() - if run.level and run.level > 0 then - main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5} - end - -- main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5} + main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5} main:add(BuyScreen'buy_screen') - main:go_to('buy_screen', run.level or 0, run.units or {}, passives, run.shop_level or 1, run.shop_xp or 0) + main:go_to('buy_screen', run.level or 1, run.units or {}, passives, run.shop_level or 1, run.shop_xp or 0) -- main:go_to('buy_screen', 7, run.units or {}, {'unleash'}) --[[ main:add(Arena'arena') main:go_to('arena', 3, { - {character = 'merchant', level = 1}, - {character = 'miner', level = 1}, - {character = 'thief', level = 1}, - {character = 'gambler', level = 1}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, + {character = 'vulcanist', level = 3}, }, passives) ]]-- diff --git a/media.lua b/media.lua index 1d52128..4948673 100644 --- a/media.lua +++ b/media.lua @@ -11,10 +11,10 @@ function Media:on_enter(from) self.effects = Group() self.ui = Group() - graphics.set_background_color(yellow2[0]) + graphics.set_background_color(blue[0]) Text2{group = self.ui, x = gw/2, y = gh/2, lines = { {text = '[fg]SNKRX', font = fat_font, alignment = 'center', height_offset = -15}, - {text = '[fg]mercenary update', font = pixul_font, alignment = 'center'}, + {text = '[fg]item update', font = pixul_font, alignment = 'center'}, }} end diff --git a/objects.lua b/objects.lua index 3fe99ee..81b45ed 100644 --- a/objects.lua +++ b/objects.lua @@ -250,7 +250,7 @@ function Unit:calculate_stats(first_run) else if self.boss then local x = self.level - local y = {0, 0, 3, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 18, 0, 0, 40, 0, 0, 32, 0, 0, 64, 84} + local y = {0, 0, 3, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 18, 0, 0, 40, 0, 0, 32, 0, 0, 64, 90} self.base_hp = 100 + (current_new_game_plus*5) + (90 + current_new_game_plus*10)*y[x] self.base_dmg = (12 + current_new_game_plus*2) + (2 + current_new_game_plus)*y[x] self.base_mvspd = 35 + 1.5*y[x] diff --git a/player.lua b/player.lua index 258f531..07dda38 100644 --- a/player.lua +++ b/player.lua @@ -158,14 +158,14 @@ function Player:init(args) self.t:cooldown(4, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function() local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies) if closest_enemy then - self:shoot(self:angle_to_object(closest_enemy), {pierce = 1000, v = 40}) + self:shoot(self:angle_to_object(closest_enemy), {pierce = 10000, v = 40}) if main.current.sorcerer_level > 0 then self.sorcerer_count = self.sorcerer_count + 1 if self.sorcerer_count >= ((main.current.sorcerer_level == 3 and 2) or (main.current.sorcerer_level == 2 and 3) or (main.current.sorcerer_level == 1 and 4)) then self:sorcerer_repeat() self.sorcerer_count = 0 self.t:after(0.25, function() - self:shoot(self:angle_to_object(closest_enemy), {pierce = 1000, v = 40}) + self:shoot(self:angle_to_object(closest_enemy), {pierce = 10000, v = 40}) end) end end @@ -469,7 +469,7 @@ function Player:init(args) self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function() local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies) if closest_enemy then - self:shoot(self:angle_to_object(closest_enemy), {spawn_critters_on_kill = 3, spawn_critters_on_hit = (self.level == 3 and 3 or nil)}) + self:shoot(self:angle_to_object(closest_enemy), {spawn_critters_on_kill = 3, spawn_critters_on_hit = (self.level == 3 and 2 or nil)}) end end, nil, nil, 'shoot') @@ -1404,7 +1404,7 @@ function Player:hit(damage, from_undead) if self.character == 'beastmaster' and self.level == 3 then critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5} trigger:after(0.01, function() - for i = 1, 2 do + for i = 1, 4 do Critter{group = main.current.main, x = self.x, y = self.y, color = orange[0], r = random:float(0, 2*math.pi), v = 20, dmg = self.dmg, parent = self} end end) @@ -1508,7 +1508,7 @@ function Player:hit(damage, from_undead) end if self.insurance then - if random:bool(4*((main.current.mercenary_level == 2 and 20) or (main.current.mercenary_level == 1 and 10) or 0)) then + if random:bool(4*((main.current.mercenary_level == 2 and 16) or (main.current.mercenary_level == 1 and 8) or 0)) then main.current.t:after(0.01, function() Gold{group = main.current.main, x = self.x, y = self.y} Gold{group = main.current.main, x = self.x, y = self.y} @@ -1879,7 +1879,7 @@ function Projectile:init(args) arcane2:play{pitch = random:float(0.7, 1.3), volume = 0.15} self.hfx:use('hit', 0.5) local r = self:angle_to_object(enemy) - local t = {group = main.current.main, x = self.x + 8*math.cos(r), y = self.y + 8*math.sin(r), v = 250, r = r, color = self.parent.color, dmg = self.parent.dmg, pierce = 1000, character = 'arcanist_projectile', + local t = {group = main.current.main, x = self.x + 8*math.cos(r), y = self.y + 8*math.sin(r), v = 250, r = r, color = self.parent.color, dmg = self.parent.dmg, pierce = 2, character = 'arcanist_projectile', parent = self.parent, level = self.parent.level} local check_circle = Circle(t.x, t.y, 2) local objects = main.current.main:get_objects_in_shape(check_circle, {Player, Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) @@ -2778,9 +2778,8 @@ function Volcano:draw() if self.hidden then return end if not self.hfx.hit then return end - graphics.push(self.x, self.y, math.pi/4, self.spring.x, self.spring.x) - graphics.rectangle(self.x, self.y, 1.5*self.shape.w, 4, 2, 2, self.hfx.hit.f and fg[0] or self.color) - graphics.rectangle(self.x, self.y, 4, 1.5*self.shape.h, 2, 2, self.hfx.hit.f and fg[0] or self.color) + graphics.push(self.x, self.y, -math.pi/2, self.spring.x, self.spring.x) + graphics.triangle_equilateral(self.x, self.y, 1.5*self.shape.w, self.hfx.hit.f and fg[0] or self.color, 3) graphics.pop() graphics.push(self.x, self.y, self.r + self.vr, self.spring.x, self.spring.x) diff --git a/todo b/todo index 4708c52..620a64e 100644 --- a/todo +++ b/todo @@ -1,7 +1,7 @@ Item Update New mechanics * Spend gold to level items up - Block levelling for unlevellable items + * Block levelling for unlevellable items Items General: * Centipede - +10/20/30% movement speed @@ -84,37 +84,29 @@ Item Update * Blessing * Immolation Balance - * Changed voider DoT damage bonus to 20/40% (from 15/25%) + * Increased voider DoT damage bonus to 20/40% (from 15/25%) * Decreased shop reroll cost to 10 - Decrease mercenary gold drop chance to 8/16% (from 10/20%) + * Decreased mercenary gold drop chance to 8/16% (from 10/20%) + * Changed Merchant to tier 1 + * Changed Merchant interest to cap at 10 (having more than 100 gold won't generate more interest from the merchant) + * Changed Miner to tier 2 + * Changed Arcanist projectiles to pierce once (from infinite) + * Changed Exploder to create a mine on death, it will explode into projectiles after a delay (this delay is smaller on higher NG+ difficulties) + * Decreased Shooter projectile fire rate, speed, and now the projectiles can also be blocked by enemies + * Decreased Tank knockback resistance + * Decreased level 25 elite knockback resistance + * Changed Beastmaster's Lv.3 effect to spawn 4 small critters when it gets hit (from 2) + * Changed Corruptor's Lv.3 effect to spawn 2 small critters on hit (from 3) QoL - Current snake/items visible on item selection screen - Volume slider - Add visuals for defensive ouroboros, divine intervention, fairy buff - Options menu from buy screen - https://i.imgur.com/JJUddT3.png - https://i.imgur.com/R3YgUqk.png - Improve volcano to not look like spawn marker - https://i.imgur.com/HuS15HG.png - Add option for mouse cursor to always be visible - Add main menu - Soundtrack button - Arena run button - Options button - Quit button + * Added snake to the passive selection screen + * Changed Volcano's icon to be a triangle instead of X so it isn't confused with a spawn marker + * Improved Beastmaster and Corruptor description with text describing their attack and how much damage it deals + * Added visual effect for when defensive ouroboros is active * Added an option to force all screen transitions to be dark * Added tier text to characters on the shop screen * Added shop unit highlights/markers to make it easier to tell when you already own something * Added unit names to the "your build" section of the end game screen - Bug fixes - Fix fullscreen with different resolutions that don't scale properly - https://steamcommunity.com/app/915310/discussions/0/3106901665841020282/ - Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier) - Kill enemies that go outside play area - https://i.imgur.com/QPgZbve.png - https://i.imgur.com/lCdPFZx.png - https://i.imgur.com/1CwmFYX.png - https://i.imgur.com/qrExpq5.png - https://i.imgur.com/DNHUST1.png - Fixed multiple bugs related to locking the shop and quitting * Fixed ouroboros technique passives not working with mouse controls * Fixed mouse not showing up on death * Fixed NG+5 achievement not triggering (this happened only between last Sunday night and Monday morning due to a small update I pushed breaking it) @@ -124,6 +116,7 @@ Item Update * Fixed a bug where the shop would be rerolled after quitting in the arena * Fixed a bug where units could be duplicated in the shop by locking and quitting the game at certain steps * Fixed a bug where quitting on level 2 would go back to level 1 shop (again) + * Fixed multiple bugs related to locking the shop and quitting * Fixed a bug where mouse cursor wasn't visible on death * Fixed a bug where NG+ level wasn't increased when the game is beaten but only when the NG+ button was clicked * Fixed a bug where level 2 and level 3 achievements (win with only level 2/3 units) were not triggering correctly sometimes @@ -145,6 +138,23 @@ Endless Update Units die permanently when they die Slower scaling with less individually threatening units Max snake size goes up every 10 levels + QoL + Volume slider + Add visuals divine intervention, fairy buff + Options menu from buy screen + https://i.imgur.com/JJUddT3.png + Add option for mouse cursor to always be visible + Add main menu + Soundtrack button + Arena run button + Options button + Quit button + Bug fixes + Fix fullscreen with different resolutions that don't scale properly - https://steamcommunity.com/app/915310/discussions/0/3106901665841020282/ + Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier) + Kill enemies that go outside play area - https://i.imgur.com/QPgZbve.png + https://i.imgur.com/lCdPFZx.png + https://i.imgur.com/qrExpq5.png --- @@ -152,6 +162,8 @@ Future updates: Chaos related classes Invoker - shoots a projectile with random properties, Lv.3 effect - ??? Trappers: + Traps - map modifier + turrets attached to walls shoot single, slow moving projectiles in a predictable pattern that deal lots of damage Triangler - drops a trap and the 3rd trap will trigger the area, dealing X AoE damage 2-3 times Brawlers: units focused on crashing on enemies https://i.imgur.com/5YubukS.png - unit idea