diff --git a/arena.lua b/arena.lua index c953130..992f9ca 100644 --- a/arena.lua +++ b/arena.lua @@ -331,7 +331,7 @@ function Arena:update(dt) self.paused = true self.paused_t1 = Text2{group = self.ui, x = gw/2, y = gh/2 - 108, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]<-, a or m1 ->, d or m2', font = fat_font, alignment = 'center'}}} self.paused_t2 = Text2{group = self.ui, x = gw/2, y = gh/2 - 92, lines = {{text = '[bg10]turn left turn right', font = pixul_font, alignment = 'center'}}} - self.ng_t = Text2{group = self.ui, x = gw/2 + 33, y = gh - 50, lines = {{text = '[bg10]current: ' .. new_game_plus, font = pixul_font, alignment = 'center'}}} + self.ng_t = Text2{group = self.ui, x = gw/2 + 63, y = gh - 50, lines = {{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}} self.resume_button = Button{group = self.ui, x = gw/2, y = gh - 200, force_update = true, button_text = 'resume game (esc)', fg_color = 'bg10', bg_color = 'bg', action = function(b) trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() @@ -353,7 +353,8 @@ function Arena:update(dt) if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end - if self.ng_plus_button then self.ng_plus_button.dead = true; self.ng_plus_button = nil end + if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end + if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end system.save_state() end, 'pause') end} @@ -375,7 +376,7 @@ function Arena:update(dt) 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, } - max_units = 7 + new_game_plus + max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives) @@ -446,11 +447,22 @@ function Arena:update(dt) b:set_text('cooldowns on snake: ' .. tostring(state.cooldown_snake and 'yes' or 'no')) end} - self.ng_plus_button = Button{group = self.ui, x = gw/2 - 53, y = gh - 50, force_update = true, button_text = 'NG+ difficulty-', fg_color = 'bg10', bg_color = 'bg', action = function() + self.ng_plus_minus_button = Button{group = self.ui, x = gw/2 - 58, y = gh - 50, force_update = true, button_text = 'NG+ down', fg_color = 'bg10', bg_color = 'bg', action = function(b) ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - new_game_plus = math.clamp(new_game_plus - 1, 0, 5) - state.new_game_plus = new_game_plus - self.ng_t.text:set_text({{text = '[bg10]current: ' .. new_game_plus, font = pixul_font, alignment = 'center'}}) + b.spring:pull(0.2, 200, 10) + b.selected = true + current_new_game_plus = math.clamp(current_new_game_plus - 1, 0, 5) + state.current_new_game_plus = current_new_game_plus + self.ng_t.text:set_text({{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}) + end} + + self.ng_plus_plus_button = Button{group = self.ui, x = gw/2 + 5, y = gh - 50, force_update = true, button_text = 'NG+ up', fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + b.spring:pull(0.2, 200, 10) + b.selected = true + current_new_game_plus = math.clamp(current_new_game_plus + 1, 0, new_game_plus) + state.current_new_game_plus = current_new_game_plus + self.ng_t.text:set_text({{text = '[bg10]current: ' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}) end} self.quit_button = Button{group = self.ui, x = gw/2, y = gh - 25, force_update = true, button_text = 'quit', fg_color = 'bg10', bg_color = 'bg', action = function() @@ -479,7 +491,8 @@ function Arena:update(dt) if self.screen_shake_button then self.screen_shake_button.dead = true; self.screen_shake_button = nil end if self.cooldown_snake_button then self.cooldown_snake_button.dead = true; self.cooldown_snake_button = nil end if self.quit_button then self.quit_button.dead = true; self.quit_button = nil end - if self.ng_plus_button then self.ng_plus_button.dead = true; self.ng_plus_button = nil end + if self.ng_plus_plus_button then self.ng_plus_plus_button.dead = true; self.ng_plus_plus_button = nil end + if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end system.save_state() end, 'pause') end @@ -503,7 +516,7 @@ function Arena:update(dt) 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, } - max_units = 7 + new_game_plus + max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives) @@ -548,7 +561,7 @@ function Arena:quit() CharacterPart{group = self.ui, x = 40, y = 40 + (i-1)*19, character = unit.character, level = unit.level, force_update = true, cant_click = true, parent = self} end - if new_game_plus == 5 then + if current_new_game_plus == 5 then self.win_text2 = Text2{group = self.ui, x = gw/2, y = gh/2 + 30, force_update = true, lines = { {text = "[fg]now you've really beaten the game!", font = pixul_font, alignment = 'center', height_multiplier = 1.24}, {text = "[fg]thanks a lot for playing it and completing it entirely!", font = pixul_font, alignment = 'center', height_multiplier = 1.24}, @@ -605,7 +618,7 @@ function Arena:quit() 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, } - max_units = 7 + new_game_plus + max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives) @@ -614,14 +627,14 @@ function Arena:quit() end end) - if new_game_plus == 1 then + if current_new_game_plus == 1 then state.achievement_new_game_1 = true system.save_state() steam.userStats.setAchievement('NEW_GAME_1') steam.userStats.storeStats() end - if new_game_plus == 5 then + if current_new_game_plus == 5 then state.achievement_new_game_5 = true system.save_state() steam.userStats.setAchievement('GAME_COMPLETE') @@ -886,7 +899,7 @@ function Arena:die() 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, } - max_units = 7 + new_game_plus + max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives) diff --git a/buy_screen.lua b/buy_screen.lua index 8b59385..80eee09 100644 --- a/buy_screen.lua +++ b/buy_screen.lua @@ -68,7 +68,7 @@ function BuyScreen:on_enter(from, level, units, passives) self.party_text = Text({{text = '[wavy_mid, fg]party', font = pixul_font, alignment = 'center'}}, global_text_tags) self.sets_text = Text({{text = '[wavy_mid, fg]classes', font = pixul_font, alignment = 'center'}}, global_text_tags) self.items_text = Text({{text = '[wavy_mid, fg]items', font = pixul_font, alignment = 'center'}}, global_text_tags) - self.ng_text = Text({{text = '[fg]NG+' .. new_game_plus, font = pixul_font, alignment = 'center'}}, global_text_tags) + self.ng_text = Text({{text = '[fg]NG+' .. current_new_game_plus, font = pixul_font, alignment = 'center'}}, global_text_tags) local get_elite_str = function(lvl) if lvl == 6 or lvl == 12 or lvl == 18 or lvl == 24 or lvl == 25 then return ' (elite)' elseif lvl % 3 == 0 then return ' (hard)' @@ -125,7 +125,7 @@ function BuyScreen:on_enter(from, level, units, passives) b.info_text = nil end} - self.restart_button = Button{group = self.ui, x = gw/2 + 156, y = 18, force_update = true, hold_button = 1, button_text = 'R', fg_color = 'bg10', bg_color = 'bg', action = function(b) + self.restart_button = Button{group = self.ui, x = gw/2 + 156, y = 18, force_update = true, button_text = 'R', fg_color = 'bg10', bg_color = 'bg', action = function(b) self.transitioning = true ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5} ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} @@ -142,7 +142,7 @@ function BuyScreen:on_enter(from, level, units, passives) 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, } - max_units = 7 + new_game_plus + max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives) @@ -237,7 +237,7 @@ function BuyScreen:draw() if self.shop_text then self.shop_text:draw(64, 20) end if self.sets_text then self.sets_text:draw(328, 20) end if self.party_text then self.party_text:draw(440, 20) end - if new_game_plus > 0 then self.ng_text:draw(260, 20) end + if current_new_game_plus > 0 then self.ng_text:draw(260, 20) end if self.in_tutorial then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent_2) @@ -499,7 +499,7 @@ function RestartButton:init(args) self:init_game_object(args) self.shape = Rectangle(self.x, self.y, pixul_font:get_text_width('restart') + 4, pixul_font.h + 4) self.interact_with_mouse = true - self.text = Text({{text = '[bg10]NG+' .. tostring(new_game_plus+1), font = pixul_font, alignment = 'center'}}, global_text_tags) + self.text = Text({{text = '[bg10]NG+' .. tostring(current_new_game_plus+1), font = pixul_font, alignment = 'center'}}, global_text_tags) end @@ -524,9 +524,13 @@ function RestartButton:update(dt) 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, } - new_game_plus = new_game_plus + 1 - state.new_game_plus = new_game_plus - max_units = 7 + new_game_plus + if current_new_game_plus == new_game_plus then + new_game_plus = new_game_plus + 1 + state.new_game_plus = new_game_plus + end + current_new_game_plus = current_new_game_plus + 1 + state.current_new_game_plus = current_new_game_plus + max_units = 7 + current_new_game_plus system.save_state() main:add(BuyScreen'buy_screen') system.save_run() @@ -549,14 +553,14 @@ function RestartButton:on_mouse_enter() ui_hover1:play{pitch = random:float(1.3, 1.5), volume = 0.5} pop2:play{pitch = random:float(0.95, 1.05), volume = 0.5} self.selected = true - self.text:set_text{{text = '[fgm5]NG+' .. tostring(new_game_plus+1), font = pixul_font, alignment = 'center'}} + self.text:set_text{{text = '[fgm5]NG+' .. tostring(current_new_game_plus+1), font = pixul_font, alignment = 'center'}} self.spring:pull(0.2, 200, 10) end function RestartButton:on_mouse_exit() if main.current.in_credits then return end - self.text:set_text{{text = '[bg10]NG+' .. tostring(new_game_plus+1), font = pixul_font, alignment = 'center'}} + self.text:set_text{{text = '[bg10]NG+' .. tostring(current_new_game_plus+1), font = pixul_font, alignment = 'center'}} self.selected = false end diff --git a/enemies.lua b/enemies.lua index d34cf4a..d02d97e 100644 --- a/enemies.lua +++ b/enemies.lua @@ -22,7 +22,7 @@ function Seeker:init(args) HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1} for _, enemy in ipairs(enemies) do LightningLine{group = main.current.effects, src = self, dst = enemy, color = green[0]} - enemy:speed_boost(3 + self.level*0.05 + new_game_plus*0.2) + enemy:speed_boost(3 + self.level*0.05 + current_new_game_plus*0.2) end end end) @@ -96,8 +96,8 @@ function Seeker:init(args) LightningLine{group = main.current.effects, src = self, dst = enemy, color = blue[0]} enemy:hit(10000) shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4} - local n = 8 + new_game_plus*2 - for i = 1, n do EnemyProjectile{group = main.current.main, x = enemy.x, y = enemy.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*enemy.level, dmg = (1 + 0.1*new_game_plus)*enemy.dmg} end + local n = 8 + current_new_game_plus*2 + for i = 1, n do EnemyProjectile{group = main.current.main, x = enemy.x, y = enemy.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*enemy.level, dmg = (1 + 0.1*current_new_game_plus)*enemy.dmg} end end end) @@ -113,8 +113,8 @@ function Seeker:init(args) LightningLine{group = main.current.effects, src = self, dst = enemy, color = blue[0]} enemy:hit(10000) shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4} - local n = 8 + new_game_plus*2 - for i = 1, n do EnemyProjectile{group = main.current.main, x = enemy.x, y = enemy.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 150 + 5*enemy.level, dmg = (1 + 0.2*new_game_plus)*enemy.dmg} end + local n = 8 + current_new_game_plus*2 + for i = 1, n do EnemyProjectile{group = main.current.main, x = enemy.x, y = enemy.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 150 + 5*enemy.level, dmg = (1 + 0.2*current_new_game_plus)*enemy.dmg} end end elseif attack == 'swarm' then local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 128), {Seeker}) @@ -145,7 +145,7 @@ function Seeker:init(args) HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1} for _, enemy in ipairs(enemies) do LightningLine{group = main.current.effects, src = self, dst = enemy, color = green[0]} - enemy:speed_boost(3 + self.level*0.05 + new_game_plus*0.2) + enemy:speed_boost(3 + self.level*0.05 + current_new_game_plus*0.2) end end end @@ -212,8 +212,8 @@ function Seeker:init(args) self.hfx:use('hit', 0.25, 200, 10, 0.1) local r = self.r HitCircle{group = main.current.effects, x = self.x + 0.8*self.shape.w*math.cos(r), y = self.y + 0.8*self.shape.w*math.sin(r), rs = 6} - EnemyProjectile{group = main.current.main, x = self.x + 1.6*self.shape.w*math.cos(r), y = self.y + 1.6*self.shape.w*math.sin(r), color = fg[0], r = r, v = 150 + 5*self.level + 8*new_game_plus, - dmg = (new_game_plus*0.1 + 1)*self.dmg} + EnemyProjectile{group = main.current.main, x = self.x + 1.6*self.shape.w*math.cos(r), y = self.y + 1.6*self.shape.w*math.sin(r), color = fg[0], r = r, v = 150 + 5*self.level + 8*current_new_game_plus, + dmg = (current_new_game_plus*0.1 + 1)*self.dmg} end) end end, nil, nil, 'shooter') @@ -248,8 +248,8 @@ function Seeker:update(dt) if self.headbutt_charging or self.headbutting then self.buff_def_m = 3 end if self.speed_boosting then - local n = math.remap(love.timer.getTime() - self.speed_boosting, 0, (3 + 0.05*self.level + new_game_plus*0.2), 1, 0.5) - self.speed_boosting_mvspd_m = (3 + 0.05*self.level + 0.2*new_game_plus)*n + local n = math.remap(love.timer.getTime() - self.speed_boosting, 0, (3 + 0.05*self.level + current_new_game_plus*0.2), 1, 0.5) + self.speed_boosting_mvspd_m = (3 + 0.05*self.level + 0.2*current_new_game_plus)*n if not self.speed_booster and not self.exploder and not self.headbutter and not self.tank and not self.shooter and not self.spawner then self.color.r = math.remap(n, 1, 0.5, green[0].r, red[0].r) self.color.g = math.remap(n, 1, 0.5, green[0].g, red[0].g) @@ -432,7 +432,7 @@ function Seeker:hit(damage, projectile) if self.exploder then shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4} trigger:after(0.01, function() - local n = 8 + new_game_plus*2 + local n = 8 + current_new_game_plus*2 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 = 150 + 5*self.level, dmg = 2*self.dmg} end diff --git a/main.lua b/main.lua index 9e7b846..8d6ef09 100644 --- a/main.lua +++ b/main.lua @@ -1172,6 +1172,8 @@ function init() steam.userStats.requestCurrentStats() new_game_plus = state.new_game_plus or 0 if not state.new_game_plus then state.new_game_plus = new_game_plus end + current_new_game_plus = state.current_new_game_plus or new_game_plus + if not state.current_new_game_plus then state.current_new_game_plus = current_new_game_plus end max_units = 7 + new_game_plus main = Main() diff --git a/objects.lua b/objects.lua index 6484f19..eb5c042 100644 --- a/objects.lua +++ b/objects.lua @@ -229,12 +229,12 @@ function Unit:calculate_stats(first_run) self.base_dmg = 10*math.pow(2, self.level-1) self.base_mvspd = 75 elseif self:is(Seeker) then - if new_game_plus == 0 then + if current_new_game_plus == 0 then 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, 24, 0, 0, 32, 0, 0, 40, 48} - self.base_hp = 100 + (new_game_plus*5) + (90 + new_game_plus*10)*y[x] - self.base_dmg = (12 + new_game_plus*2) + (2 + new_game_plus)*y[x] + 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] else local x = self.level @@ -247,14 +247,14 @@ function Unit:calculate_stats(first_run) 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, 24, 0, 0, 32, 0, 0, 40, 48} - self.base_hp = 100 + (new_game_plus*5) + (90 + new_game_plus*10)*y[x] - self.base_dmg = (12 + new_game_plus*2) + (2 + new_game_plus)*y[x] + 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] else local x = self.level local y = {0, 1, 3, 3, 4, 6, 5, 6, 9, 7, 8, 12, 10, 11, 15, 12, 13, 18, 16, 17, 21, 17, 20, 24, 25} - self.base_hp = 22 + (new_game_plus*3) + (15 + new_game_plus*2.7)*y[x] - self.base_dmg = (4 + new_game_plus*1.25) + (2 + new_game_plus*1.2)*y[x] + self.base_hp = 22 + (current_new_game_plus*3) + (15 + current_new_game_plus*2.7)*y[x] + self.base_dmg = (4 + current_new_game_plus*1.25) + (2 + current_new_game_plus*1.2)*y[x] self.base_mvspd = 70 + 3*y[x] end end diff --git a/todo b/todo index 1688947..a8553c5 100644 --- a/todo +++ b/todo @@ -2,14 +2,36 @@ Hide cursor during waves Mouse follow control? Item reroll for 15 gold Option to have an arrow at the head of the snake - https://imgur.com/a/poXVsoN -Balance option for when there are more sets - https://i.imgur.com/JMynwbL.png -Bench? - https://i.imgur.com/B1gNVKk.png +Option to turn off camera movement +Headbutter damage should falloff faster after it strikes +https://i.imgur.com/QN0Ntq2.png +https://i.imgur.com/YfhqDYr.png +https://i.imgur.com/ps4OA7o.png +Remove level 3 units from rotation +Fix highlight colors and highlight reserve +Fix bug where quitting on level 1 jumps to level 2 +Fix lock bug after death/win - https://i.imgur.com/iUyOtLk.png +Options menu from buy screen +Fix fullscreen with different resolutions that don't scale properly +Volume slider + +Sorcerer = sorcerers repeat their attacks once every 3/2 attacks +Sorcerer + Conjurer = Illusionist - launches a projectile that deals X damage and creates copies that do the same, Lv.3 effect - doubles the number of copies created and they release additional projectiles on death +Sorcerer + Voider = Witch - creates an area that deals X damage over time and seeks nearby enemies, Lv.3 effect - the area periodically releases homing projectiles that pierce 2 times +Sorcerer + Curser = Linker - links 3 enemies together, they share damage taken, Lv.3 effect - link 6 enemies instead and damage shared is doubled +Sorcerer + Nuker = Vulcanist - creates a volcano that explodes the nearby area 5 times, Lv.3 effect - the volcano spawn also deals damage and doubles the number of explosions +Sorcerer + Forcer = Warden - creates a force field around a random unit that prevents enemies from entering, Lv.3 effect - creates the force field around 2 other random units Patch Notes: Decreased projectile speed for the exploder (blue enemy) Added tooltips for "restart run" and "tutorial" buttons on the shop -Added a hold mechanism to the restart button, now it will only trigger a restart if you hold the button down for 1 second Fixed text that was going outside the screen for the Priest and the Assassin Fixed bug where Divine Punishment would continue triggering after death Removed cooldown visuals on snake for units that don't have cooldowns (Squire, Chronomancer and Psykeeper) Slightly decreased base game's difficulty +Fixed NG+ difficulty only being able to be lowered, now you can lower or increase it (up to your maximum acquired value) + +Future ideas: +Chaos related class = Invoker - shoots a projectile with random properties, Lv.3 effect - ??? +Bench? - https://i.imgur.com/B1gNVKk.png +Balance option for when there are more sets - https://i.imgur.com/JMynwbL.png