diff --git a/arena.lua b/arena.lua index 8c867b7..77a58ed 100644 --- a/arena.lua +++ b/arena.lua @@ -369,6 +369,7 @@ function Arena:update(dt) if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end + if self.dark_transition_button then self.dark_transition_button.dead = true; self.dark_transition_button = nil end if self.sfx_button then self.sfx_button.dead = true; self.sfx_button = nil end if self.music_button then self.music_button.dead = true; self.music_button = nil end if self.video_button_1 then self.video_button_1.dead = true; self.video_button_1 = nil end @@ -390,27 +391,27 @@ function Arena:update(dt) 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} ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function() + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() slow_amount = 1 gold = 3 passives = {} main_song_instance:stop() - run_passive_pool_by_tiers = { - [1] = { 'wall_echo', 'wall_rider', 'centipede', 'temporal_chains', 'amplify', 'amplify_x', 'ballista', 'ballista_x', 'blunt_arrow', 'berserking', 'unwavering_stance', 'assassination', 'unleash', 'blessing', - 'hex_master', 'force_push', 'spawning_pool'}, - [2] = {'ouroboros_technique_r', 'ouroboros_technique_l', 'intimidation', 'vulnerability', 'resonance', 'point_blank', 'longshot', 'explosive_arrow', 'chronomancy', 'awakening', 'ultimatum', 'echo_barrage', - 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, - [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, + run_passive_pool = { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'level_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') locked_state = nil system.save_run() main:go_to('buy_screen', 0, {}, passives, 1, 0) - end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end} - self.mouse_button = Button{group = self.ui, x = gw/2, y = gh - 150, force_update = true, button_text = 'mouse control: ' .. tostring(state.mouse_control and 'yes' or 'no'), fg_color = 'bg10', bg_color = 'bg', + self.mouse_button = Button{group = self.ui, x = gw/2 - 57, y = gh - 150, force_update = true, button_text = 'mouse control: ' .. tostring(state.mouse_control and 'yes' or 'no'), fg_color = 'bg10', bg_color = 'bg', action = function(b) ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} state.mouse_control = not state.mouse_control @@ -418,6 +419,13 @@ function Arena:update(dt) input:set_mouse_visible(state.mouse_control) end} + self.dark_transition_button = Button{group = self.ui, x = gw/2 + 64, y = gh - 150, force_update = true, button_text = 'dark transitions: ' .. tostring(state.dark_transitions and 'yes' or 'no'), + fg_color = 'bg10', bg_color = 'bg', action = function(b) + ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + state.dark_transitions = not state.dark_transitions + b:set_text('dark transitions: ' .. tostring(state.dark_transitions and 'yes' or 'no')) + end} + self.sfx_button = Button{group = self.ui, x = gw/2 - 46, y = gh - 175, force_update = true, button_text = 'sounds (n): ' .. tostring(state.volume_muted and 'no' or 'yes'), fg_color = 'bg10', bg_color = 'bg', action = function(b) ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} @@ -547,6 +555,7 @@ function Arena:update(dt) if self.resume_button then self.resume_button.dead = true; self.resume_button = nil end if self.restart_button then self.restart_button.dead = true; self.restart_button = nil end if self.mouse_button then self.mouse_button.dead = true; self.mouse_button = nil end + if self.dark_transition_button then self.dark_transition_button.dead = true; self.dark_transition_button = nil end if self.sfx_button then self.sfx_button.dead = true; self.sfx_button = nil end if self.music_button then self.music_button.dead = true; self.music_button = nil end if self.video_button_1 then self.video_button_1.dead = true; self.video_button_1 = nil end @@ -570,24 +579,24 @@ function Arena:update(dt) 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} ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function() + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() slow_amount = 1 gold = 3 passives = {} main_song_instance:stop() - run_passive_pool_by_tiers = { - [1] = { 'wall_echo', 'wall_rider', 'centipede', 'temporal_chains', 'amplify', 'amplify_x', 'ballista', 'ballista_x', 'blunt_arrow', 'berserking', 'unwavering_stance', 'assassination', 'unleash', 'blessing', - 'hex_master', 'force_push', 'spawning_pool'}, - [2] = {'ouroboros_technique_r', 'ouroboros_technique_l', 'intimidation', 'vulnerability', 'resonance', 'point_blank', 'longshot', 'explosive_arrow', 'chronomancy', 'awakening', 'ultimatum', 'echo_barrage', - 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, - [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, + run_passive_pool = { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'level_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') locked_state = nil system.save_run() main:go_to('buy_screen', 0, {}, passives, 1, 0) - end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end if input.escape.pressed then @@ -695,14 +704,14 @@ function Arena:quit() end end) - if current_new_game_plus == 1 then + if current_new_game_plus == 2 then state.achievement_new_game_1 = true system.save_state() steam.userStats.setAchievement('NEW_GAME_1') steam.userStats.storeStats() end - if current_new_game_plus == 5 then + if current_new_game_plus == 6 then state.achievement_new_game_5 = true system.save_state() steam.userStats.setAchievement('GAME_COMPLETE') @@ -877,23 +886,17 @@ function Arena:set_passives(from_reroll) local w = 3*card_w + 2*20 self.choosing_passives = true self.cards = {} - local tier_1 = random:weighted_pick(unpack(level_to_passive_tier_weights[level or self.level])) - local tier_2 = random:weighted_pick(unpack(level_to_passive_tier_weights[level or self.level])) - local tier_3 = random:weighted_pick(unpack(level_to_passive_tier_weights[level or self.level])) - local passive_1 = random:table_remove(run_passive_pool_by_tiers[tier_1]) - local passive_2 = random:table_remove(run_passive_pool_by_tiers[tier_2]) - local passive_3 = random:table_remove(run_passive_pool_by_tiers[tier_3]) + local passive_1 = random:table_remove(run_passive_pool) + 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, tier = tier_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, y = gh/2 - 6, 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, tier = tier_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, y = gh/2 - 6, 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, tier = tier_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, y = gh/2 - 6, 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'}}} if not passive_1 and not passive_2 and not passive_3 then @@ -905,8 +908,8 @@ end function Arena:restore_passives_to_pool(j) for i = 1, 3 do if i ~= j then - if self.cards[i] and run_passive_pool_by_tiers[self.cards[i].tier] then - table.insert(run_passive_pool_by_tiers[self.cards[i].tier], self.cards[i].passive) + if self.cards[i] then + table.insert(run_passive_pool, self.cards[i].passive) end end end @@ -971,7 +974,7 @@ end function Arena:die() if not self.died_text and not self.won and not self.arena_clear_text then - input:set_mouse_visible(false) + input:set_mouse_visible(true) self.t:cancel('divine_punishment') self.died = true locked_state = nil @@ -989,23 +992,23 @@ function Arena:die() 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} ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function() + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() slow_amount = 1 gold = 3 passives = {} main_song_instance:stop() - run_passive_pool_by_tiers = { - [1] = { 'wall_echo', 'wall_rider', 'centipede', 'temporal_chains', 'amplify', 'amplify_x', 'ballista', 'ballista_x', 'blunt_arrow', 'berserking', 'unwavering_stance', 'assassination', 'unleash', 'blessing', - 'hex_master', 'force_push', 'spawning_pool'}, - [2] = {'ouroboros_technique_r', 'ouroboros_technique_l', 'intimidation', 'vulnerability', 'resonance', 'point_blank', 'longshot', 'explosive_arrow', 'chronomancy', 'awakening', 'ultimatum', 'echo_barrage', - 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, - [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, + run_passive_pool = { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'level_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives, 1, 0) - end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end} end) return true @@ -1084,7 +1087,7 @@ function Arena:transition() self.transitioning = true if not self.lock then locked_state = nil end ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5} - TransitionEffect{group = main.transitions, x = self.player.x, y = self.player.y, color = self.color, transition_action = function(t) + TransitionEffect{group = main.transitions, x = self.player.x, y = self.player.y, color = state.dark_transitions and bg[-2] or self.color, transition_action = function(t) if self.level % 2 == 0 and self.shop_level < 5 then self.shop_xp = self.shop_xp + 1 local max_xp = 0 @@ -1100,36 +1103,39 @@ 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_by_tiers, locked_state) + 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) t.t:after(0.1, function() t.text:set_text({ - {text = '[nudge_down, bg]gold gained: ' .. tostring(self.gold_gained or 0) .. ' + ' .. tostring(self.gold_picked_up or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[wavy_lower, bg]interest: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[wavy_lower, bg]total: 0', font = pixul_font, alignment = 'center'} + {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, + alignment = 'center', height_multiplier = 1.5}, + {text = '[wavy_lower, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']interest: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, + {text = '[wavy_lower, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']total: 0', font = pixul_font, alignment = 'center'} }) _G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} t.t:after(0.2, function() t.text:set_text({ - {text = '[wavy_lower, bg]gold gained: ' .. tostring(self.gold_gained or 0) .. ' + ' .. tostring(self.gold_picked_up or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[nudge_down, bg]interest: ' .. tostring(self.interest or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[wavy_lower, bg]total: 0', font = pixul_font, alignment = 'center'} + {text = '[wavy_lower, ' .. 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, + alignment = 'center', height_multiplier = 1.5}, + {text = '[nudge_down, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']interest: ' .. tostring(self.interest or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, + {text = '[wavy_lower, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']total: 0', font = pixul_font, alignment = 'center'} }) _G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} t.t:after(0.2, function() t.text:set_text({ - {text = '[wavy_lower, bg]gold gained: ' .. tostring(self.gold_gained or 0) .. ' + ' .. tostring(self.gold_picked_up or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[wavy_lower, bg]interest: ' .. tostring(self.interest or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[nudge_down, bg]total: ' .. tostring((self.gold_gained or 0) + (self.interest or 0) + (self.gold_picked_up or 0)), font = pixul_font, alignment = 'center'} + {text = '[wavy_lower, ' .. 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, + alignment = 'center', height_multiplier = 1.5}, + {text = '[wavy_lower, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']interest: ' .. tostring(self.interest or 0), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, + {text = '[nudge_down, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']total: ' .. tostring((self.gold_gained or 0) + (self.interest or 0) + (self.gold_picked_up or 0)), font = pixul_font, alignment = 'center'} }) _G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} end) end) end) end, text = Text({ - {text = '[wavy_lower, bg]gold gained: 0 + 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[wavy_lower, bg]interest: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, - {text = '[wavy_lower, bg]total: 0', font = pixul_font, alignment = 'center'} + {text = '[wavy_lower, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']gold gained: 0 + 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, + {text = '[wavy_lower, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']interest: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, + {text = '[wavy_lower, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']total: 0', font = pixul_font, alignment = 'center'} }, global_text_tags)} end diff --git a/assets/images/annihilation.png b/assets/images/annihilation.png new file mode 100644 index 0000000..ce10f44 Binary files /dev/null and b/assets/images/annihilation.png differ diff --git a/assets/images/baneling_burst.png b/assets/images/baneling_burst.png new file mode 100644 index 0000000..0432bf9 Binary files /dev/null and b/assets/images/baneling_burst.png differ diff --git a/assets/images/burning_field.png b/assets/images/burning_field.png new file mode 100644 index 0000000..8050ad4 Binary files /dev/null and b/assets/images/burning_field.png differ diff --git a/assets/images/damage_4.png b/assets/images/damage_4.png new file mode 100644 index 0000000..fab26de Binary files /dev/null and b/assets/images/damage_4.png differ diff --git a/assets/images/death_6.png b/assets/images/death_6.png new file mode 100644 index 0000000..b778496 Binary files /dev/null and b/assets/images/death_6.png differ diff --git a/assets/images/deceleration.png b/assets/images/deceleration.png new file mode 100644 index 0000000..539f73c Binary files /dev/null and b/assets/images/deceleration.png differ diff --git a/assets/images/point_blank.png b/assets/images/defensive_stance.png similarity index 100% rename from assets/images/point_blank.png rename to assets/images/defensive_stance.png diff --git a/assets/images/dividends.png b/assets/images/dividends.png new file mode 100644 index 0000000..ae7e373 Binary files /dev/null and b/assets/images/dividends.png differ diff --git a/assets/images/force_push.png b/assets/images/enchanted.png similarity index 100% rename from assets/images/force_push.png rename to assets/images/enchanted.png diff --git a/assets/images/wall_echo.png b/assets/images/fracture.png similarity index 100% rename from assets/images/wall_echo.png rename to assets/images/fracture.png diff --git a/assets/images/freezing_field.png b/assets/images/freezing_field.png new file mode 100644 index 0000000..70afeec Binary files /dev/null and b/assets/images/freezing_field.png differ diff --git a/assets/images/gravity_field.png b/assets/images/gravity_field.png new file mode 100644 index 0000000..e02bd7e Binary files /dev/null and b/assets/images/gravity_field.png differ diff --git a/assets/images/insurance.png b/assets/images/insurance.png new file mode 100644 index 0000000..b53f0bf Binary files /dev/null and b/assets/images/insurance.png differ diff --git a/assets/images/amplify_x.png b/assets/images/kinetic_bomb.png similarity index 100% rename from assets/images/amplify_x.png rename to assets/images/kinetic_bomb.png diff --git a/assets/images/blessing.png b/assets/images/last_stand.png similarity index 100% rename from assets/images/blessing.png rename to assets/images/last_stand.png diff --git a/assets/images/lasting_7.png b/assets/images/lasting_7.png new file mode 100644 index 0000000..d4496b1 Binary files /dev/null and b/assets/images/lasting_7.png differ diff --git a/assets/images/level_5.png b/assets/images/level_5.png new file mode 100644 index 0000000..c671eb3 Binary files /dev/null and b/assets/images/level_5.png differ diff --git a/assets/images/magnetism.png b/assets/images/magnetism.png new file mode 100644 index 0000000..2568739 Binary files /dev/null and b/assets/images/magnetism.png differ diff --git a/assets/images/hex_master.png b/assets/images/malediction.png similarity index 100% rename from assets/images/hex_master.png rename to assets/images/malediction.png diff --git a/assets/images/spawning_pool.png b/assets/images/meat_shield.png similarity index 100% rename from assets/images/spawning_pool.png rename to assets/images/meat_shield.png diff --git a/assets/images/longshot.png b/assets/images/offensive_stance.png similarity index 100% rename from assets/images/longshot.png rename to assets/images/offensive_stance.png diff --git a/assets/images/pandemic.png b/assets/images/pandemic.png new file mode 100644 index 0000000..d68bafb Binary files /dev/null and b/assets/images/pandemic.png differ diff --git a/assets/images/void_rift.png b/assets/images/porcupine_technique.png similarity index 100% rename from assets/images/void_rift.png rename to assets/images/porcupine_technique.png diff --git a/assets/images/seeping.png b/assets/images/seeping.png new file mode 100644 index 0000000..38100ca Binary files /dev/null and b/assets/images/seeping.png differ diff --git a/assets/images/speed_3.png b/assets/images/speed_3.png new file mode 100644 index 0000000..a9a6274 Binary files /dev/null and b/assets/images/speed_3.png differ diff --git a/assets/images/wall_rider.png b/assets/images/tremor.png similarity index 100% rename from assets/images/wall_rider.png rename to assets/images/tremor.png diff --git a/assets/images/immolation.png b/assets/images/unrelenting_stance.png similarity index 100% rename from assets/images/immolation.png rename to assets/images/unrelenting_stance.png diff --git a/buy_screen.lua b/buy_screen.lua index e6e3675..55b0ea6 100644 --- a/buy_screen.lua +++ b/buy_screen.lua @@ -137,23 +137,23 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp) ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} locked_state = nil - TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function() + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() slow_amount = 1 gold = 3 passives = {} main_song_instance:stop() - run_passive_pool_by_tiers = { - [1] = {'wall_echo', 'wall_rider', 'centipede', 'temporal_chains', 'amplify', 'amplify_x', 'ballista', 'ballista_x', 'blunt_arrow', 'berserking', 'unwavering_stance', 'assassination', 'unleash', 'blessing', - 'hex_master', 'force_push', 'spawning_pool'}, - [2] = {'ouroboros_technique_r', 'ouroboros_technique_l', 'intimidation', 'vulnerability', 'resonance', 'point_blank', 'longshot', 'explosive_arrow', 'chronomancy', 'awakening', 'ultimatum', 'echo_barrage', - 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, - [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, + run_passive_pool = { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'level_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' } max_units = 7 + current_new_game_plus main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives, 1, 0) - end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end, mouse_enter = function(b) b.info_text = InfoText{group = main.current.ui, force_update = true} b.info_text:activate({ @@ -169,7 +169,10 @@ function BuyScreen:on_enter(from, level, units, passives, shop_level, shop_xp) trigger:tween(1, main_song_instance, {volume = 0.2}, math.linear) if self.level == 1 then - self.screen_text = Text2{group = self.ui, x = gw/2, y = gh/2, lines = {{text = '[bg3]press K if screen is too large', font = pixul_font, alignment = 'center'}}} + self.screen_text = Text2{group = self.ui, x = gw/2, y = gh/2, lines = { + {text = '[bg3]press K if screen is too large', font = pixul_font, alignment = 'center'}, + {text = '[bg3]press L if screen is too small', font = pixul_font, alignment = 'center'}, + }} self.t:after(8, function() self.t:tween(0.2, self.screen_text, {sy = 0}, math.linear, function() self.screen_text.sy = 0 end) end) @@ -335,7 +338,7 @@ function BuyScreen:set_cards(shop_level, dont_spawn_effect, first_call) local unit_2 local unit_3 local shop_level = shop_level or 1 - local tier_weights = get_shop_odds_by_level(shop_level) + local tier_weights = level_to_shop_odds[shop_level] repeat unit_1 = random:table(tier_to_characters[random:weighted_pick(unpack(tier_weights))]) unit_2 = random:table(tier_to_characters[random:weighted_pick(unpack(tier_weights))]) @@ -379,9 +382,9 @@ function BuyScreen:set_items() if self.items then for _, item in ipairs(self.items) do item:die() end end self.items = {} local y = 182 - for k, item in ipairs(self.passives) do + for k, passive in ipairs(self.passives) do local i, j = math.index_to_coordinates(k, 4) - table.insert(self.items, ItemCard{group = self.main, x = 45 + (i-1)*60, y = y + (j-1)*50, w = 40, h = 50, passive = item}) + table.insert(self.items, ItemCard{group = self.main, x = 45 + (i-1)*60, y = y + (j-1)*50, w = 40, h = 50, passive = passive.passive , level = passive.level, xp = passive.xp}) end end @@ -521,23 +524,23 @@ function RestartButton:update(dt) 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} ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function() + TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() slow_amount = 1 gold = 3 passives = {} main_song_instance:stop() - run_passive_pool_by_tiers = { - [1] = { 'wall_echo', 'wall_rider', 'centipede', 'temporal_chains', 'amplify', 'amplify_x', 'ballista', 'ballista_x', 'blunt_arrow', 'berserking', 'unwavering_stance', 'assassination', 'unleash', 'blessing', - 'hex_master', 'force_push', 'spawning_pool'}, - [2] = {'ouroboros_technique_r', 'ouroboros_technique_l', 'intimidation', 'vulnerability', 'resonance', 'point_blank', 'longshot', 'explosive_arrow', 'chronomancy', 'awakening', 'ultimatum', 'echo_barrage', - 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, - [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, + run_passive_pool = { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'level_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' } system.save_state() main:add(BuyScreen'buy_screen') system.save_run() main:go_to('buy_screen', 0, {}, passives, 1, 0) - end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)} end end @@ -682,11 +685,11 @@ function GoButton:update(dt) ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} ui_transition1:play{pitch = random:float(0.95, 1.05), volume = 0.5} self.transitioning = true - system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state) - TransitionEffect{group = main.transitions, x = self.x, y = self.y, color = character_colors[random:table(self.parent.units).character], transition_action = function() + system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool, locked_state) + TransitionEffect{group = main.transitions, x = self.x, y = self.y, color = state.dark_transitions and bg[-2] or character_colors[random:table(self.parent.units).character], transition_action = function() main:add(Arena'arena') main:go_to('arena', ((self.parent.first_screen and 1) or (self.parent.level + 1)), self.parent.units, self.parent.passives, self.parent.shop_level, self.parent.shop_xp, self.parent.locked) - end, text = Text({{text = '[wavy, bg]level ' .. ((self.parent.first_screen and 1) or (self.parent.level + 1)) .. '/25', font = pixul_font, alignment = 'center'}}, global_text_tags)} + end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']level ' .. ((self.parent.first_screen and 1) or (self.parent.level + 1)) .. '/25', font = pixul_font, alignment = 'center'}}, global_text_tags)} end end end @@ -736,7 +739,7 @@ function LockButton:update(dt) if not self.parent.locked then locked_state = nil end if self.parent.locked then locked_state = {locked = true, cards = {self.parent.cards[1] and self.parent.cards[1].unit, self.parent.cards[2] and self.parent.cards[2].unit, self.parent.cards[3] and self.parent.cards[3].unit}} - system.save_run(self.parent.level == 1 and 0 or self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state) + system.save_run(self.parent.level == 1 and 0 or self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool, locked_state) end ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5} self.selected = true @@ -817,7 +820,7 @@ function LevelButton:update(dt) gold = gold - 5 self.parent.shop_text:set_text{{text = '[wavy_mid, fg]shop [fg]- [fg, nudge_down]gold: [yellow, nudge_down]' .. gold, font = pixul_font, alignment = 'center'}} self.text = Text({{text = '[bg10]' .. tostring(self.parent.shop_level), font = pixul_font, alignment = 'center'}}, global_text_tags) - system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state) + system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool, locked_state) end end end @@ -947,7 +950,7 @@ function RerollButton:update(dt) self.spring:pull(0.2, 200, 10) gold = gold - 2 self.parent.shop_text:set_text{{text = '[wavy_mid, fg]shop [fg]- [fg, nudge_down]gold: [yellow, nudge_down]' .. gold, font = pixul_font, alignment = 'center'}} - system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state) + system.save_run(self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool, locked_state) end elseif self.parent:is(Arena) then if gold < 10 and not self.free_reroll then @@ -1289,6 +1292,7 @@ function PassiveCard:init(args) self.interact_with_mouse = true self.passive_name = Text({{text = '[fg, wavy_mid]' .. passive_names[self.passive], font = pixul_font, alignment = 'center'}}, global_text_tags) self.passive_description = passive_descriptions[self.passive] + self.spring:pull(0.2, 200, 10) end @@ -1298,7 +1302,7 @@ function PassiveCard:update(dt) if self.selected and input.m1.pressed and self.arena.choosing_passives then self.arena.choosing_passives = false - table.insert(self.arena.passives, self.passive) + table.insert(self.arena.passives, {passive = self.passive, level = 1, xp = 0}) self.arena:restore_passives_to_pool(self.card_i) trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() slow_amount = 1 @@ -1381,7 +1385,7 @@ function ItemCard:on_mouse_enter() self.info_text = InfoText{group = main.current.ui, force_update = true} self.info_text:activate({ {text = '[fg]' .. passive_names[self.passive], font = pixul_font, alignment = 'center', height_multiplier = 1.25}, - {text = passive_descriptions[self.passive], font = pixul_font, alignment = 'center', height_multiplier = 1.25}, + {text = passive_descriptions_level[self.passive](self.level), font = pixul_font, alignment = 'center', height_multiplier = 1.25}, }, nil, nil, nil, nil, 16, 4, nil, 2) self.info_text.x, self.info_text.y = gw/2, gh/2 + 10 end @@ -1462,7 +1466,7 @@ function ShopCard:update(dt) self:die() self.parent.cards[self.i] = nil self.parent:refresh_cards() - system.save_run(self.parent.level == 1 and 0 or self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool_by_tiers, locked_state) + system.save_run(self.parent.level == 1 and 0 or self.parent.level, gold, self.parent.units, passives, self.parent.shop_level, self.parent.shop_xp, run_passive_pool, locked_state) else error1:play{pitch = random:float(0.95, 1.05), volume = 0.5} self.spring:pull(0.2, 200, 10) diff --git a/engine/system.lua b/engine/system.lua index 3467b6c..cf218be 100644 --- a/engine/system.lua +++ b/engine/system.lua @@ -137,15 +137,15 @@ function system.load_state() end -function system.save_run(level, gold, units, passives, shop_level, shop_xp, run_passive_pool_by_tiers, locked_state) - local run = {level = level, gold = gold, units = units, passives = passives, shop_level = shop_level, shop_xp = shop_xp, run_passive_pool_by_tiers = run_passive_pool_by_tiers, locked_state = locked_state} +function system.save_run(level, gold, units, passives, shop_level, shop_xp, run_passive_pool, locked_state) + local run = {level = level, gold = gold, units = units, passives = passives, shop_level = shop_level, shop_xp = shop_xp, run_passive_pool= run_passive_pool, locked_state = locked_state} local str = "return " .. table.tostring(run) - love.filesystem.write("run_v2.txt", str) + love.filesystem.write("run_v3.txt", str) end function system.load_run() - local chunk = love.filesystem.load("run_v2.txt") + local chunk = love.filesystem.load("run_v3.txt") if chunk then return chunk() else return {} end end diff --git a/main.lua b/main.lua index 7c2cb2c..054c0e5 100644 --- a/main.lua +++ b/main.lua @@ -141,50 +141,62 @@ function init() voider = Image('voider') sorcerer = Image('sorcerer') mercenary = Image('mercenary') + star = Image('star') + arrow = Image('arrow') + centipede = Image('centipede') ouroboros_technique_r = Image('ouroboros_technique_r') ouroboros_technique_l = Image('ouroboros_technique_l') - wall_echo = Image('wall_echo') - wall_rider = Image('wall_rider') - centipede = Image('centipede') - intimidation = Image('intimidation') - vulnerability = Image('vulnerability') - temporal_chains = Image('temporal_chains') amplify = Image('amplify') - amplify_x = Image('amplify_x') resonance = Image('resonance') ballista = Image('ballista') - ballista_x = Image('ballista_x') - point_blank = Image('point_blank') - longshot = Image('longshot') + call_of_the_void = Image('call_of_the_void') + crucio = Image('crucio') + speed_3 = Image('speed_3') + damage_4 = Image('damage_4') + level_5 = Image('level_5') + death_6 = Image('death_6') + lasting_7 = Image('lasting_7') + defensive_stance = Image('defensive_stance') + offensive_stance = Image('offensive_stance') + kinetic_bomb = Image('kinetic_bomb') + porcupine_technique = Image('porcupine_technique') + last_stand = Image('last_stand') + seeping = Image('seeping') + deceleration = Image('deceleration') + annihilation = Image('annihilation') + malediction = Image('malediction') + pandemic = Image('pandemic') + whispers_of_doom = Image('whispers_of_doom') + tremor = Image('tremor') + heavy_impact = Image('heavy_impact') + fracture = Image('fracture') + meat_shield = Image('meat_shield') + hive = Image('hive') + baneling_burst = Image('baneling_burst') blunt_arrow = Image('blunt_arrow') explosive_arrow = Image('explosive_arrow') divine_machine_arrow = Image('divine_machine_arrow') chronomancy = Image('chronomancy') awakening = Image('awakening') divine_punishment = Image('divine_punishment') - berserking = Image('berserking') - unwavering_stance = Image('unwavering_stance') - ultimatum = Image('ultimatum') - flying_daggers = Image('flying_daggers') assassination = Image('assassination') + flying_daggers = Image('flying_daggers') + ultimatum = Image('ultimatum') magnify = Image('magnify') echo_barrage = Image('echo_barrage') unleash = Image('unleash') reinforce = Image('reinforce') payback = Image('payback') - blessing = Image('blessing') - hex_master = Image('hex_master') - whispers_of_doom = Image('whispers_of_doom') - force_push = Image('force_push') - heavy_impact = Image('heavy_impact') - crucio = Image('crucio') - immolation = Image('immolation') - call_of_the_void = Image('call_of_the_void') - spawning_pool = Image('spawning_pool') - hive = Image('hive') - void_rift = Image('void_rift') - star = Image('star') - arrow = Image('arrow') + enchanted = Image('enchanted') + freezing_field = Image('freezing_field') + burning_field = Image('burning_field') + gravity_field = Image('gravity_field') + magnetism = Image('magnetism') + insurance = Image('insurance') + dividends = Image('dividends') + berserking = Image('berserking') + unwavering_stance = Image('unwavering_stance') + unrelenting_stance = Image('unrelenting_stance') class_colors = { ['warrior'] = yellow[0], @@ -904,23 +916,24 @@ function init() else return 'light_bg' end end class_descriptions = { - ['ranger'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[' .. ylb2(lvl) .. ']/6 [fg]- [' .. ylb1(lvl) .. ']8%[' .. ylb2(lvl) .. ']/16% [fg]chance to release a barrage on attack to allied rangers' end, - ['warrior'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[' .. ylb2(lvl) .. ']/6 [fg]- [' .. ylb1(lvl) .. ']+25[' .. ylb2(lvl) .. ']/+50 [fg]defense to allied warriors' end, - ['mage'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[' .. ylb2(lvl) .. ']/6 [fg]- [' .. ylb1(lvl) .. ']-15[' .. ylb2(lvl) .. ']/-30 [fg]enemy defense' end, - ['rogue'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[' .. ylb2(lvl) .. ']/6 [fg]- [' .. ylb1(lvl) .. ']15%[' .. ylb2(lvl) .. ']/30% [fg]chance to crit to allied rogues, dealing [yellow]4x[] damage' end, - ['healer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+15%[' .. ylb2(lvl) .. ']/+30% [fg]healing effectiveness' end, - ['enchanter'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+15%[' .. ylb2(lvl) .. ']/+25% [fg]damage to all allies' end, - ['nuker'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[' .. ylb2(lvl) .. ']/6 [fg]- [' .. ylb1(lvl) .. ']+15%[' .. ylb2(lvl) .. ']/+25% [fg]area damage and size to allied nukers' end, - ['conjurer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+25%[' .. ylb2(lvl) .. ']/+50% [fg]summon damage and duration' end, - ['psyker'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+10%[' .. ylb2(lvl) .. ']/+20% [fg]damage and attack speed per active set to allied psykers' end, - ['curser'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+25%[' .. ylb2(lvl) .. ']/+50% [fg]curse duration' end, - ['forcer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+25%[' .. ylb2(lvl) .. ']/+50% [fg]knockback force to all allies' end, - ['swarmer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+1[' .. ylb2(lvl) .. ']/+3 [fg]hits to critters' end, - ['voider'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+15%[' .. ylb2(lvl) .. ']/+25% [fg]damage over time to allied voiders' end, + ['ranger'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[light_bg]/[' .. ylb2(lvl) .. ']6 [fg]- [' .. ylb1(lvl) .. ']8%[light_bg]/[' .. ylb2(lvl) .. ']16% [fg]chance to release a barrage on attack to allied rangers' end, + ['warrior'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[light_bg]/[' .. ylb2(lvl) .. ']6 [fg]- [' .. ylb1(lvl) .. ']+25[light_bg]/[' .. ylb2(lvl) .. ']+50 [fg]defense to allied warriors' end, + ['mage'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[light_bg]/[' .. ylb2(lvl) .. ']6 [fg]- [' .. ylb1(lvl) .. ']-15[light_bg]/[' .. ylb2(lvl) .. ']-30 [fg]enemy defense' end, + ['rogue'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[light_bg]/[' .. ylb2(lvl) .. ']6 [fg]- [' .. ylb1(lvl) .. ']15%[light_bg]/[' .. ylb2(lvl) .. ']30% [fg]chance to crit to allied rogues, dealing [yellow]4x[] damage' end, + ['healer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+15%[light_bg]/[' .. ylb2(lvl) .. ']+30% [fg]healing effectiveness' end, + ['enchanter'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+15%[light_bg]/[' .. ylb2(lvl) .. ']+25% [fg]damage to all allies' end, + ['nuker'] = function(lvl) return '[' .. ylb1(lvl) .. ']3[light_bg]/[' .. ylb2(lvl) .. ']6 [fg]- [' .. ylb1(lvl) .. ']+15%[light_bg]/[' .. ylb2(lvl) .. ']+25% [fg]area damage and size to allied nukers' end, + ['conjurer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+25%[light_bg]/[' .. ylb2(lvl) .. ']+50% [fg]summon damage and duration' end, + ['psyker'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+10%[light_bg]/[' .. ylb2(lvl) .. ']+20% [fg]damage and attack speed per active set to allied psykers' end, + ['curser'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+25%[light_bg]/[' .. ylb2(lvl) .. ']+50% [fg]curse duration' end, + ['forcer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+25%[light_bg]/[' .. ylb2(lvl) .. ']+50% [fg]knockback force to all allies' end, + ['swarmer'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+1[light_bg]/[' .. ylb2(lvl) .. ']+3 [fg]hits to critters' end, + ['voider'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[light_bg]/[' .. ylb2(lvl) .. ']4 [fg]- [' .. ylb1(lvl) .. ']+15%[light_bg]/[' .. ylb2(lvl) .. ']+25% [fg]damage over time to allied voiders' end, ['sorcerer'] = function(lvl) - return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4[' .. ylb3(lvl) .. ']/6 [fg]- sorcerers repeat their attacks once every [' .. ylb1(lvl) .. ']4/[' .. ylb2(lvl) .. ']3/[' .. ylb3(lvl) .. ']2[fg] attacks' + 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[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+10%[' .. 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) .. ']+10%[light_bg]/[' .. ylb2(lvl) .. ']+20% [fg]chance for enemies to drop gold on death' end, } tier_to_characters = { @@ -1093,146 +1106,175 @@ function init() } passive_names = { + ['centipede'] = 'Centipede', ['ouroboros_technique_r'] = 'Ouroboros Technique R', ['ouroboros_technique_l'] = 'Ouroboros Technique L', - ['wall_echo'] = 'Wall Echo', - ['wall_rider'] = 'Wall Rider', - ['centipede'] = 'Centipede', - ['intimidation'] = 'Intimidation', - ['vulnerability'] = 'Vulnerability', - ['temporal_chains'] = 'Temporal Chains', ['amplify'] = 'Amplify', - ['amplify_x'] = 'Amplify X', ['resonance'] = 'Resonance', ['ballista'] = 'Ballista', - ['ballista_x'] = 'Ballista X', - ['point_blank'] = 'Point Blank', - ['longshot'] = 'Longshot', + ['call_of_the_void'] = 'Call of the Void', + ['crucio'] = 'Crucio', + ['speed_3'] = 'Speed 3', + ['damage_4'] = 'Damage 4', + ['level_5'] = 'Level 5', + ['death_6'] = 'Death 6', + ['lasting_7'] = 'Lasting 7', + ['defensive_stance'] = 'Defensive Stance', + ['offensive_stance'] = 'Offensive Stance', + ['kinetic_bomb'] = 'Kinetic Bomb', + ['porcupine_technique'] = 'Porcupine Technique', + ['last_stand'] = 'Last Stand', + ['seeping'] = 'Seeping', + ['deceleration'] = 'Deceleration', + ['annihilation'] = 'Annihilation', + ['malediction'] = 'Malediction', + ['pandemic'] = 'Pandemic', + ['whispers_of_doom'] = 'Whispers of Doom', + ['tremor'] = 'Tremor', + ['heavy_impact'] = 'Heavy Impact', + ['fracture'] = 'Fracture', + ['meat_shield'] = 'Meat Shield', + ['hive'] = 'Hive', + ['baneling_burst'] = 'Baneling Burst', ['blunt_arrow'] = 'Blunt Arrow', ['explosive_arrow'] = 'Explosive Arrow', ['divine_machine_arrow'] = 'Divine Machine Arrow', ['chronomancy'] = 'Chronomancy', ['awakening'] = 'Awakening', ['divine_punishment'] = 'Divine Punishment', - ['berserking'] = 'Berserking', - ['unwavering_stance'] = 'Unwavering Stance', - ['ultimatum'] = 'Ultimatum', - ['flying_daggers'] = 'Flying Daggers', ['assassination'] = 'Assassination', + ['flying_daggers'] = 'Flying Daggers', + ['ultimatum'] = 'Ultimatum', ['magnify'] = 'Magnify', ['echo_barrage'] = 'Echo Barrage', ['unleash'] = 'Unleash', ['reinforce'] = 'Reinforce', ['payback'] = 'Payback', - ['blessing'] = 'Blessing', - ['hex_master'] = 'Hex Master', - ['whispers_of_doom'] = 'Whispers of Doom', - ['force_push'] = 'Force Push', - ['heavy_impact'] = 'Heavy Impact', - ['crucio'] = 'Crucio', - ['immolation'] = 'Immolation', - ['call_of_the_void'] = 'Call of the Void', - ['spawning_pool'] = 'Spawning Pool', - ['hive'] = 'Hive', - ['void_rift'] = 'Void Rift', + ['enchanted'] = 'Enchanted', + ['freezing_field'] = 'Freezing Field', + ['burning_field'] = 'Burning Field', + ['gravity_field'] = 'Gravity Field', + ['magnetism'] = 'Magnetism', + ['insurance'] = 'Insurance', + ['dividends'] = 'Dividends', + ['berserking'] = 'Berserking', + ['unwavering_stance'] = 'Unwavering Stance', + ['unrelenting_stance'] = 'Unrelenting Stance', } 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]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'] = '[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'] = '[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]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]4[fg] times', - ['chronomancy'] = '[fg]all mages and sorcerers cast their spells [yellow]25%[fg] faster', - ['awakening'] = '[yellow]+100%[fg] aspd and damage to [yellow]1[fg] mage or sorcerer every round for that round', - ['divine_punishment'] = '[fg]repeatedly deal damage to all enemies based on how many mages or sorcerers you have', - ['berserking'] = '[fg]all warriors have up to [yellow]+50%[fg] attack speed based on missing HP', - ['unwavering_stance'] = '[fg]all warriors gain [yellow]+5%[fg] defense every [yellow]5[fg] seconds', - ['ultimatum'] = '[fg]projectiles that chain gain [yellow]+25%[fg] damage with each chain', - ['flying_daggers'] = '[fg]all knives thrown by rogues chain [yellow]+2[fg] times', - ['assassination'] = '[fg]crits from rogues deal [yellow]8x[fg] damage but normal attacks deal [yellow]half[fg] damage', - ['magnify'] = '[yellow]+25%[fg] area size', - ['echo_barrage'] = '[yellow]20%[fg] chance to create [yellow]3[fg] secondary AoEs on AoE hit', - ['unleash'] = '[yellow]+1%[fg] area size and damage per second', - ['reinforce'] = '[yellow]+10%[fg] damage, defense and attack speed to all allies with at least one enchanter', - ['payback'] = '[yellow]+5%[fg] damage to all allies whenever an enchanter is hit', - ['blessing'] = '[yellow]+20%[fg] healing effectiveness', - ['hex_master'] = '[yellow]+25%[fg] curse duration', - ['whispers_of_doom'] = '[fg]curses apply doom, when [yellow]4[fg] doom instances are reached they deal [yellow]200[fg] damage', - ['force_push'] = '[yellow]+25%[fg] knockback force', - ['heavy_impact'] = '[fg]when enemies hit walls they take damage according to the knockback force', - ['crucio'] = '[fg]taking damage also shares that across all enemies at [yellow]25%[fg] its value', - ['immolation'] = '[yellow]3[fg] units will periodically take damage, all your allies gain [yellow]+8%[fg] damage per tick', - ['call_of_the_void'] = '[yellow]+25%[fg] damage over time', - ['spawning_pool'] = '[yellow]+1[fg] critter health', - ['hive'] = '[yellow]+2[fg] critter health', - ['void_rift'] = '[fg]attacks by mages, nukers or voiders have a [yellow]20%[fg] chance to create a void rift on hit', + ['centipede'] = '[yellow]+10/20/30%[fg] movement speed', + ['ouroboros_technique_r'] = '[fg]rotating around yourself to the right releases [yellow]2/3/4[fg] projectiles per second', + ['ouroboros_technique_l'] = '[fg]rotating around yourself to the left grants [yellow]+15/25/35%[fg] defense to all units', + ['amplify'] = '[yellow]+20/35/50%[fg] AoE damage', + ['resonance'] = '[fg]all AoE attacks deal [yellow]+3/5/7%[fg] damage per unit hit', + ['ballista'] = '[yellow]+20/35/50%[fg] projectile damage', + ['call_of_the_void'] = '[yellow]+30/60/90%[fg] DoT damage', + ['crucio'] = '[fg]taking damage also shares that across all enemies at [yellow]20/30/40%[fg] its value', + ['speed_3'] = '[fg]position [yellow]3[fg] has [yellow]+50%[fg] attack speed', + ['damage_4'] = '[fg]position [yellow]4[fg] has [yellow]+30%[fg] damage', + ['level_5'] = '[fg]position [yellow]5[fg] is [yellow]1[fg] level higher', + ['death_6'] = '[fg]position [yellow]6[fg] takes [yellow]10%[fg] of its health as damage every [yellow]3[fg] seconds', + ['lasting_7'] = '[fg]position [yellow]7[fg] will stay alive for [yellow]10[fg] seconds after dying', + ['defensive_stance'] = '[fg]first and last positions have [yellow]+10/20/30%[fg] defense', + ['offensive_stance'] = '[fg]first and last positions have [yellow]+10/20/30%[fg] damage', + ['kinetic_bomb'] = '[fg]when a unit dies it explodes, launching enemies away', + ['porcupine_technique'] = '[fg]when a unit dies it explodes, releasing piercing projectiles', + ['last_stand'] = '[fg]the last unit alive is fully healed and receives a [yellow]+20%[fg] bonus to all stats', + ['seeping'] = '[fg]enemies taking DoT damage take [yellow]+15/20/25%[fg] damage for [yellow]6[fg] seconds', + ['deceleration'] = '[fg]enemies damaged by voiders have their movement speed reduced by [yellow]15/20/25%', + ['annihilation'] = '[fg]when a voider dies deal its DoT damage to all enemies for [yellow]3[fg] seconds', + ['malediction'] = '[fg]cursed enemies take [yellow]+15/25/35%[fg] damage and deal [yellow]-15/25/35%[fg] damage', + ['pandemic'] = '[fg]when a cursed enemy dies its curse spreads', + ['whispers_of_doom'] = '[fg]curses apply doom, deal [yellow]100/150/200[fg] damage every [yellow]4/3/2[fg] doom instances', + ['tremor'] = '[fg]when enemies die from hitting walls they create an area based on the knockback force', + ['heavy_impact'] = '[fg]when enemies hit walls they take damage based on the knockback force', + ['fracture'] = '[fg]when enemies die from hitting walls they explode into projectiles', + ['meat_shield'] = '[fg]critters [yellow]block[fg] enemy projectiles', + ['hive'] = '[fg]critters have [yellow]+1/2/3[fg] HP', + ['baneling_burst'] = '[fg]critters die immediately on contact but also deal [yellow]50/100/150[fg] AoE damage', + ['blunt_arrow'] = '[fg]ranger arrows have [yellow]+10/20/30%[fg] chance to knockback', + ['explosive_arrow'] = '[fg]ranger arrows have [yellow]+10/20/30%[fg] chance to deal [yellow]10/20/30%[fg] AoE damage', + ['divine_machine_arrow'] = '[fg]ranger arrows have a [yellow]10/20/30%[fg] chance to seek and pierce [yellow]1/2/3[fg] times', + ['chronomancy'] = '[fg]mages cast their spells [yellow]15/25/35%[fg] faster', + ['awakening'] = '[yellow]+50/75/100%[fg] attack speed and damage to [yellow]1[fg] mage every round for that round', + ['divine_punishment'] = '[fg]deal damage to all enemies based on how many mages you have', + ['assassination'] = '[fg]crits from rogues deal [yellow]8/10/12x[fg] damage but normal attacks deal [yellow]half[fg] damage', + ['flying_daggers'] = '[fg]all projectiles thrown by rogues chain [yellow]+2/3/4[fg] times', + ['ultimatum'] = '[fg]projectiles that chain gain [yellow]+10/20/30%[fg] damage with each chain', + ['magnify'] = '[yellow]+20/35/50%[fg] area size', + ['echo_barrage'] = '[yellow]10/20/30%[fg] chance to create [yellow]1/2/3[fg] secondary AoEs on AoE hit', + ['unleash'] = '[fg]all nukers gain [yellow]+1%[fg] area size and damage every second', + ['reinforce'] = '[yellow]+10/20/30%[fg] damage, defense and aspd to all allies with at least one enchanter', + ['payback'] = '[yellow]+2/5/8%[fg] damage to all allies whenever an enchanter is hit', + ['enchanted'] = '[yellow]+10/20/30%[fg] attack speed to a random unit with at least two enchanters', + ['freezing_field'] = '[fg]creates an area that slows enemies by [yellow]50%[fg] for [yellow]2[fg] seconds on sorcerer spell repeat', + ['burning_field'] = '[fg]creates an area that deals [yellow]30[fg] dps for [yellow]2[fg] seconds on sorcerer spell repeat', + ['gravity_field'] = '[fg]creates an area that pulls enemies in for [yellow]2[fg] seconds on sorcerer spell repeat', + ['magnetism'] = '[fg]gold coins are attracted to the snake', + ['insurance'] = "[fg]heroes have [yellow]4[fg] times the chance of mercenary's bonus to drop [yellow]2[fg] gold on death", + ['dividends'] = '[fg]mercenaries deal [yellow]+X%[fg] damage, where X is how much gold you have', + ['berserking'] = '[fg]all warriors have up to [yellow]+50/75/100%[fg] attack speed based on missing HP', + ['unwavering_stance'] = '[fg]all warriors gain [yellow]+4/8/12%[fg] defense every [yellow]5[fg] seconds', + ['unrelenting_stance'] = '[yellow]+2/5/8%[fg] defense to all allies whenever a warrior is hit', } - passive_tiers = { - ['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'] = 2, - ['resonance'] = 3, - ['ballista'] = 1, - ['ballista_x'] = 2, - ['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, - ['echo_barrage'] = 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, - ['void_rift'] = 3, - } - - tier_to_passives = { - [1] = {'wall_echo', 'wall_rider', 'centipede', 'temporal_chains', 'amplify', 'amplify_x', 'ballista', 'ballista_x', 'blunt_arrow', 'berserking', 'unwavering_stance', 'assassination', 'unleash', 'blessing', - 'hex_master', 'force_push', 'spawning_pool'}, - [2] = {'ouroboros_technique_r', 'ouroboros_technique_l', 'intimidation', 'vulnerability', 'resonance', 'point_blank', 'longshot', 'explosive_arrow', 'chronomancy', 'awakening', 'ultimatum', 'echo_barrage', - 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, - [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, + local ts = function(lvl, a, b, c) return '[' .. ylb1(lvl) .. ']' .. tostring(a) .. '[light_bg]/[' .. ylb2(lvl) .. ']' .. tostring(b) .. '[light_bg]/[' .. ylb3(lvl) .. ']' .. tostring(c) .. '[fg]' end + passive_descriptions_level = { + ['centipede'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' movement speed' end, + ['ouroboros_technique_r'] = function(lvl) return '[fg]rotating around yourself to the right releases ' .. ts(lvl, '2', '3', '4') .. ' projectiles per second' end, + ['ouroboros_technique_l'] = function(lvl) return '[fg]rotating around yourself to the left grants ' .. ts(lvl, '+15%', '25%', '35%') .. ' defense to all units' end, + ['amplify'] = function(lvl) return ts(lvl, '+20%', '35%', '50%') .. ' AoE damage' end, + ['resonance'] = function(lvl) return '[fg]all AoE attacks deal ' .. ts(lvl, '+3%', '5%', '7%') .. ' damage per unit hit' end, + ['ballista'] = function(lvl) return ts(lvl, '+20%', '35%', '50%') .. ' projectile damage' end, + ['call_of_the_void'] = function(lvl) return ts(lvl, '+30%', '60%', '90%') .. ' DoT damage' end, + ['crucio'] = function(lvl) return '[fg]taking damage also shares that across all enemies at ' .. ts(lvl, '20%', '30%', '40%') .. ' its value' end, + ['speed_3'] = function(lvl) return '[fg]position [yellow]3[fg] has [yellow]+50%[fg] attack speed' end, + ['damage_4'] = function(lvl) return '[fg]position [yellow]4[fg] has [yellow]+30%[fg] damage' end, + ['level_5'] = function(lvl) return '[fg]position [yellow]5[fg] is [yellow]1[fg] level higher' end, + ['death_6'] = function(lvl) return '[fg]position [yellow]6[fg] takes [yellow]10%[fg] of its health as damage every [yellow]3[fg] seconds' end, + ['lasting_7'] = function(lvl) return '[fg]position [yellow]7[fg] will stay alive for [yellow]10[fg] seconds after dying' end, + ['defensive_stance'] = function(lvl) return '[fg]first and last positions have ' .. ts(lvl, '+10%', '20%', '30%') .. ' defense' end, + ['offensive_stance'] = function(lvl) return '[fg]first and last positions have ' .. ts(lvl, '+10%', '20%', '30%') .. ' damage' end, + ['kinetic_bomb'] = function(lvl) return '[fg]when a unit dies it explodes, launching enemies away' end, + ['porcupine_technique'] = function(lvl) return '[fg]when a unit dies it explodes, releasing piercing projectiles' end, + ['last_stand'] = function(lvl) return '[fg]the last unit alive is fully healed and receives a [yellow]+20%[fg] bonus to all stats' end, + ['seeping'] = function(lvl) return '[fg]enemies taking DoT damage take ' .. ts(lvl, '+15%', '20%', '25%') .. ' damage for [yellow]6[fg] seconds' end, + ['deceleration'] = function(lvl) return '[fg]enemies damaged by voiders have their movement speed reduced by ' .. ts(lvl, '15%', '20%', '25%') end, + ['annihilation'] = function(lvl) return '[fg]when a voider dies deal its DoT damage to all enemies for [yellow]3[fg] seconds' end, + ['malediction'] = function(lvl) return '[fg]cursed enemies take ' .. ts(lvl, '+15%', '25%', '35%') .. ' damage and deal ' .. ts(lvl, '-15%', '25%', '35%') .. ' damage' end, + ['pandemic'] = function(lvl) return '[fg]when a cursed enemy dies its curse spreads' end, + ['whispers_of_doom'] = function(lvl) return '[fg]curses apply doom, deal ' .. ts(lvl, '100', '150', '200') .. ' every ' .. ts(lvl, '4', '3', '2') .. ' doom instances' end, + ['tremor'] = function(lvl) return '[fg]when enemies die from hitting walls they create an area based to the knockback force' end, + ['heavy_impact'] = function(lvl) return '[fg]when enemies hit walls they take damage based on the knockback force' end, + ['fracture'] = function(lvl) return '[fg]when enemies die from hitting walls they explode into projectiles' end, + ['meat_shield'] = function(lvl) return '[fg]critters [yellow]block[fg] enemy projectiles' end, + ['hive'] = function(lvl) return '[fg]critters have ' .. ts(lvl, '+1', '2', '3') .. ' HP' end, + ['baneling_burst'] = function(lvl) return '[fg]critters die immediately on contact but also deal ' .. ts(lvl, '50', '100', '150') .. ' AoE damage' end, + ['blunt_arrow'] = function(lvl) return '[fg]ranger arrows have ' .. ts(lvl, '+10%', '20%', '30%') .. ' chance to knockback' end, + ['explosive_arrow'] = function(lvl) return '[fg]ranger arrows have ' .. ts(lvl, '+10%', '20%', '30%') .. ' chance to deal ' .. ts(lvl, '10%', '20%', '30%') .. ' AoE damage' end, + ['divine_machine_arrow'] = function(lvl) return '[fg]ranger arrows have a ' .. ts(lvl, '10%', '20%', '30%') .. ' chance to seek and pierce ' .. ts(lvl, '1', '2', '3') .. ' times' end, + ['chronomancy'] = function(lvl) return '[fg]mages cast their spells ' .. ts(lvl, '15%', '25%', '35%') .. ' faster' end, + ['awakening'] = function(lvl) return ts(lvl, '+50%', '75%', '100%') .. ' attack speed and damage to [yellow]1[fg] mage every round for that round' end, + ['divine_punishment'] = function(lvl) return '[fg]deal damage to all enemies based on how many mages you have' end, + ['assassination'] = function(lvl) return '[fg]crits from rogues deal ' .. ts(lvl, '8x', '10x', '12x') .. ' damage but normal attacks deal [yellow]half[fg] damage' end, + ['flying_daggers'] = function(lvl) return '[fg]all projectiles thrown by rogues chain ' .. ts(lvl, '+2', '3', '4') .. ' times' end, + ['ultimatum'] = function(lvl) return '[fg]projectiles that chain gain ' .. ts(lvl, '+10%', '20%', '30%') .. ' damage with each chain' end, + ['magnify'] = function(lvl) return ts(lvl, '+20%', '35%', '50%') .. ' area size' end, + ['echo_barrage'] = function(lvl) return ts(lvl, '10%', '20%', '30%') .. ' chance to create ' .. ts(lvl, '1', '2', '3') .. ' secondary AoEs on AoE hit' end, + ['unleash'] = function(lvl) return '[fg]all nukers gain [yellow]+1%[fg] area size and damage every second' end, + ['reinforce'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' damage, defense and aspd to all allies with at least one enchanter' end, + ['payback'] = function(lvl) return ts(lvl, '+2%', '5%', '8%') .. ' damage to all allies whenever an enchanter is hit' end, + ['enchanted'] = function(lvl) return ts(lvl, '+10%', '20%', '30%') .. ' attack speed to a random unit with at least two enchanters' end, + ['freezing_field'] = function(lvl) return '[fg]creates an area that slows enemies by [yellow]50%[fg] for [yellow]2[fg] seconds on sorcerer spell repeat' end, + ['burning_field'] = function(lvl) return '[fg]creates an area that deals [yellow]30[fg] dps for [yellow]2[fg] seconds on sorcerer spell repeat' end, + ['gravity_field'] = function(lvl) return '[fg]creates an area that pulls enemies in for [yellow]2[fg] seconds on sorcerer spell repeat' end, + ['magnetism'] = function(lvl) return '[fg]gold coins are attracted to the snake' end, + ['insurance'] = function(lvl) return "[fg]heroes have [yellow]4[fg] times the chance of mercenary's bonus to drop [yellow]2[fg] gold on death" end, + ['dividends'] = function(lvl) return '[fg]mercenaries deal [yellow]+X%[fg] damage, where X is how much gold you have' end, + ['berserking'] = function(lvl) return '[fg]all warriors have up to ' .. ts(lvl, '+50%', '75%', '100%') .. ' attack speed based on missing HP' end, + ['unwavering_stance'] = function(lvl) return '[fg]all warriors gain ' .. ts(lvl, '+4%', '8%', '12%') .. ' defense every [yellow]5[fg] seconds' end, + ['unrelenting_stance'] = function(lvl) return ts(lvl, '+2%', '5%', '8%') .. ' defense to all allies whenever a warrior is hit' end, } level_to_tier_weights = { @@ -1291,17 +1333,6 @@ function init() [25] = {100, 100}, } - level_to_passive_tier_weights = { - [3] = {70, 20, 10}, - [6] = {60, 25, 15}, - [9] = {50, 30, 20}, - [12] = {40, 40, 20}, - [15] = {30, 45, 25}, - [18] = {20, 50, 30}, - [21] = {20, 40, 40}, - [24] = {20, 30, 50}, - } - level_to_elite_spawn_weights = { [1] = {0}, [2] = {4, 2}, @@ -1366,19 +1397,13 @@ function init() [25] = {'speed_booster', 'exploder', 'headbutter', 'tank', 'shooter', 'spawner'}, } - get_shop_odds_by_level = function(lvl) - if lvl == 1 then - return {70, 20, 10, 0} - elseif lvl == 2 then - return {50, 30, 15, 5} - elseif lvl == 3 then - return {25, 45, 20, 10} - elseif lvl == 4 then - return {10, 25, 45, 20} - elseif lvl == 5 then - return {5, 15, 30, 50} - end - end + level_to_shop_odds = { + [1] = {70, 20, 10, 0}, + [2] = {50, 30, 15, 5}, + [3] = {25, 45, 20, 10}, + [4] = {10, 25, 45, 20}, + [5] = {5, 15, 30, 50}, + } get_shop_odds = function(lvl, tier) if lvl == 1 then @@ -1435,12 +1460,12 @@ function init() end local run = system.load_run() - run_passive_pool_by_tiers = run.run_passive_pool_by_tiers or { - [1] = { 'wall_echo', 'wall_rider', 'centipede', 'temporal_chains', 'amplify', 'amplify_x', 'ballista', 'ballista_x', 'blunt_arrow', 'berserking', 'unwavering_stance', 'assassination', 'unleash', 'blessing', - 'hex_master', 'force_push', 'spawning_pool'}, - [2] = {'ouroboros_technique_r', 'ouroboros_technique_l', 'intimidation', 'vulnerability', 'resonance', 'point_blank', 'longshot', 'explosive_arrow', 'chronomancy', 'awakening', 'ultimatum', 'echo_barrage', - 'reinforce', 'payback', 'whispers_of_doom', 'heavy_impact', 'immolation', 'call_of_the_void'}, - [3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'}, + run_passive_pool = run.run_passive_pool or { + 'centipede', 'ouroboros_technique_r', 'ouroboros_technique_l', 'amplify', 'resonance', 'ballista', 'call_of_the_void', 'crucio', 'speed_3', 'damage_4', 'level_5', 'death_6', 'lasting_7', + 'defensive_stance', 'offensive_stance', 'kinetic_bomb', 'porcupine_technique', 'last_stand', 'seeping', 'deceleration', 'annihilation', 'malediction', 'pandemic', 'whispers_of_doom', + 'tremor', 'heavy_impact', 'fracture', 'meat_shield', 'hive', 'baneling_burst', 'blunt_arrow', 'explosive_arrow', 'divine_machine_arrow', 'chronomancy', 'awakening', 'divine_punishment', + 'assassination', 'flying_daggers', 'ultimatum', 'magnify', 'echo_barrage', 'unleash', 'reinforce', 'payback', 'enchanted', 'freezing_field', 'burning_field', 'gravity_field', 'magnetism', + 'insurance', 'dividends', 'berserking', 'unwavering_stance', 'unrelenting_stance' } gold = run.gold or 3 passives = run.passives or {} @@ -1467,16 +1492,16 @@ function init() main:add(Arena'arena') main:go_to('arena', 25, { {character = 'swordsman', level = 3}, - {character = 'plague_doctor', level = 3}, - {character = 'pyromancer', level = 3}, - {character = 'witch', level = 3}, - {character = 'arcanist', level = 3}, - {character = 'usurer', level = 3}, - {character = 'warden', level = 3}, - {character = 'silencer', level = 3}, - {character = 'vulcanist', level = 3}, - {character = 'bane', level = 3}, - {character = 'illusionist', level = 3}, + {character = 'scout', level = 3}, + {character = 'thief', level = 3}, + {character = 'blade', level = 3}, + {character = 'dual_gunner', level = 3}, + {character = 'saboteur', level = 3}, + {character = 'spellblade', level = 3}, + {character = 'jester', level = 3}, + {character = 'assassin', level = 3}, + {character = 'barrager', level = 3}, + {character = 'cannoneer', level = 3}, }, passives) ]]-- diff --git a/player.lua b/player.lua index e412649..8dce4f8 100644 --- a/player.lua +++ b/player.lua @@ -6,7 +6,7 @@ function Player:init(args) self:init_game_object(args) self:init_unit() - if self.passives then for k, v in pairs(self.passives) do self[v] = true end end + if self.passives then for k, v in pairs(self.passives) do self[v.passive] = v.level end end self.color = character_colors[self.character] self:set_as_rectangle(9, 9, 'dynamic', 'player') @@ -992,6 +992,7 @@ function Player:update(dt) if class_levels.conjurer >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.enchanter >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.psyker >= 1 then number_of_active_sets = number_of_active_sets + 1 end + if class_levels.nuker >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.curser >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.forcer >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.swarmer >= 1 then number_of_active_sets = number_of_active_sets + 1 end @@ -1058,6 +1059,7 @@ function Player:update(dt) if class_levels.conjurer >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.enchanter >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.psyker >= 1 then number_of_active_sets = number_of_active_sets + 1 end + if class_levels.nuker >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.curser >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.forcer >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.swarmer >= 1 then number_of_active_sets = number_of_active_sets + 1 end diff --git a/todo b/todo index 5f430d1..5959f7d 100644 --- a/todo +++ b/todo @@ -1,23 +1,88 @@ Item Update New mechanics - Sacrifice units to level items up + Spend gold to level items up Items - New items - Position X has +Y% attack speed - Position X has +Y% damage - Position X is 1 tier higher - Position X is also class Y - When a unit dies it explodes, launching enemies away - When a unit dies it explodes, releasing piercing projectiles - Reworked items - Items shouldn't just be more powerful versions of other items - Items should have drawbacks - Items that apply to a position on the snake (a good middle step between applying them to individual units like in Underlords) - Item discussions - https://steamcommunity.com/app/915310/discussions/0/3106901028662504698/ - https://steamcommunity.com/app/915310/discussions/0/3106901665846294204/ - https://steamcommunity.com/app/915310/discussions/0/4658391921151238820/ - https://i.imgur.com/cfIyMBL.png + General: + vt Centipede - +10/20/30% movement speed + vt Ouroboros Technique R - rotating around yourself to the right releases 2/3/4 projectiles per second + vt Ouroboros Technique L - rotating around yourself to the left grants +15/25/35% defense to all units + vt Amplify - +20/35/50% AoE damage + vt Resonance - all AoE attacks deal +3/5/7% damage per unit hit + vt Ballista - +20/35/50% projectile damage + vt Call of the Void - +30/60/90% DoT damage + vt Crucio - taking damage also shares that damage across all enemies at 20/30/40% its value + Position: + vt Speed 3 - position 3 has +20/35/50% attack speed + vt Damage 4 - position 4 has +20/30/40% damage + vt Level 5 - position 5 is 1 level higher + vt Death 6 - position 6 takes 15% of its health as damage every 3 seconds + vt Lasting 7 - position 7 will stay alive for 10 seconds after dying + vt Defense Stance - first and last positions have +10/20/30% defense + vt Offensive Stance - first and last positions have +10/20/30% damage + Death: + vt Kinetic Bomb - when a unit dies it explodes, launching enemies away + vt Porcupine Technique - when a unit dies it explodes, releasing piercing projectiles + vt Last Stand - the last unit alive is fully healed and receives a +20/30/40% bonus to all stats + Voider: + vt Seeping - enemies taking DoT damage take +15/20/25% damage from all sources for 6 seconds + vt Deceleration - enemies damaged by voiders have their movement speed reduced by 15/20/25% + vt Annihilation - when a voider dies deal its DoT damage to all enemies for 3 seconds + Curser: + vt Malediction - cursed enemies take 15/25/35% more damage and deal 15/25/35% less damage + vt Pandemic - when a cursed enemy dies its curse spreads + vt Whispers of Doom - curses apply doom, when 4/3/2 doom instances are reached they deal 100/150/200 + Forcer: + vt Tremor - when enemies die from hitting walls they create a damaging area with size according to the knockback force + vt Heavy Impact - when enemies hit walls they take damage according to the knockback force + vt Fracture - when enemies die from hitting walls explode into projectiles + Swarmer: + vt Meat Shield - critters block enemy projectiles + vt Hive - critters have +1/2/3 HP + vt Baneling Burst - critters die immediately on contact but also deal AoE damage + Ranger: + vt Blunt Arrow - arrows fired by rangers have a 10/20/30% chance to knockback + vt Explosive Arrow - arrows fired by rangers have a 10/20/30% chance to explode, dealing 10/20/30% AoE damage + vt Divine Machine Arrow - arrows fired by rangers have a 10/20/30% chance to seek enemies and pierce 1/2/3 times + Mage: + vt Chronomancy - mages cast their spells 15/25/35% faster + vt Awakening - +50/75/100% attack speed and damage to 1 mage every round for that round + vt Divine Punishment - repeatedly deal damage to all enemies based on how many mages you have + Rogue: + vt Assassination - crits from rogues deal 8/10/12x damage but normal attacks deal half damage + vt Flying Daggers - all projectiles thrown by rogues chain +2/3/4 times + vt Ultimatum - projectiles that chain gain +10/20/30% damage with each chain + Nuker: + vt Magnify - +20/35/50% area size + vt Echo Barrage - 10/20/30% chance to create 1/2/3 secondary AoEs on AoE hit + vt Unleash - all nukers gain +1% area size and damage every second + Enchanter: + vt Reinforce - +10/20/30% damage, defense and attack speed to all allies with at leats one enchanter + vt Payback - +2/5/8% damage to all allies whenever an enchanter is hit + vt Enchanted - when enemies die they have a 10/20/30% release X homing projectiles, where X is how many enchanters you have + Sorcerer: + vt Freezing Field - Create an area that slows enemies by 50% for 2 seconds whenever a sorcerer repeats a spell + vt Burning Field - Create an area that deals 30 damage per second for 2 seconds whenever a sorcerer repeats a spell + vt Gravity Field - Create an area that sucks enemies in for 2 seconds whenever a sorcerer repeats a spell + Mercenary: + vt Magnetism - Gold coins are attracted to the snake + vt Insurance - Dying heroes have 4 times the chance of mercenary's bonus to drop 2 gold on death + vt Dividends - Mercenaries deal +X% extra damage, where X is how much gold you have + Warrior: + vt Berserking - all warriors have up to +50/75/100% attack speed based on missing HP + vt Unwavering Stance - all warriors gain +4/8/12% defense every 5 seconds + vt Unrelenting Stance - +2/5/8% defense to all allies whenever a warrior is hit + Removed items + * Wall Echo + * Wall Rider + * Point Blank + * Longshot + * Hex Master + * Force Push + * Call of the Void + * Spawning Pool + * Void Rift + * Blessing + * Immolation Balance * Decreased shop reroll cost to 10 Decrease mercenary gold drop chance to 8/16% (from 10/20%) @@ -31,10 +96,10 @@ Item Update Add option for mouse cursor to always be visible Add main menu Soundtrack button - Discord button Arena run button Options button Quit button + * 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 @@ -42,6 +107,13 @@ Item Update 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 + Ouroboros doesn't work 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) + * Fixed a bug where the nuker class was not counting towards Vagrant's and Psyker's active set bonus * Fixed a bug where passives would sometimes disappear from a run? * Fixed a bug where clicking "window size-" too many times could bug out the game * Fixed a bug where the shop would be rerolled after quitting in the arena @@ -58,8 +130,13 @@ Item Update * Fixed a crash involving broken state for Pets, Critters or Volcanos * Fixed a crash that happened after rerolling items too many times - Endless Update + Healer rework: + Enemies have an X/Y% chance to create healing cells on death + Cleric: creates a healing cell at a random position + Priest: creates multiple healing cells at a random position + Psyker rework: + Create orbitting damaging balls equal to the number of psykers (similar to those balls in Nova Drift) Endless mode Units die permanently when they die Slower scaling with less individually threatening units @@ -88,6 +165,8 @@ Bench? - https://i.imgur.com/B1gNVKk.png Balance option for when there are more sets - https://i.imgur.com/JMynwbL.png Negative effect: colliding with yourself kills one of your units https://i.imgur.com/bxfvA7g.png +https://steamcommunity.com/app/915310/discussions/0/4658391921156086711/ - general feedback +https://steamcommunity.com/app/915310/discussions/0/4658391921156325745/ - math on gold, rerolls and units Roguelite update: