diff --git a/arena.lua b/arena.lua index f1b0890..25b32d4 100644 --- a/arena.lua +++ b/arena.lua @@ -243,13 +243,17 @@ function Arena:on_enter(from, level, units, passives, shop_level, shop_xp, lock) local t1 = Text2{group = self.floor, x = gw/2, y = gh/2 + 2, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]<- or a -> or d', font = fat_font, alignment = 'center'}}} local t2 = Text2{group = self.floor, x = gw/2, y = gh/2 + 18, lines = {{text = '[light_bg]turn left turn right', font = pixul_font, alignment = 'center'}}} local t3 = Text2{group = self.floor, x = gw/2, y = gh/2 + 46, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]esc - options', font = fat_font, alignment = 'center'}}} + --[[ local t4 = Text2{group = self.floor, x = gw/2, y = gh/2 + 68, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]n - mute sfx', font = fat_font, alignment = 'center'}}} local t5 = Text2{group = self.floor, x = gw/2, y = gh/2 + 90, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]m - mute music', font = fat_font, alignment = 'center'}}} + ]]-- t1.t:after(8, function() t1.t:tween(0.2, t1, {sy = 0}, math.linear, function() t1.sy = 0 end) end) t2.t:after(8, function() t2.t:tween(0.2, t2, {sy = 0}, math.linear, function() t2.sy = 0 end) end) t3.t:after(8, function() t3.t:tween(0.2, t3, {sy = 0}, math.linear, function() t3.sy = 0 end) end) + --[[ t4.t:after(8, function() t4.t:tween(0.2, t4, {sy = 0}, math.linear, function() t4.sy = 0 end) end) t5.t:after(8, function() t4.t:tween(0.2, t5, {sy = 0}, math.linear, function() t5.sy = 0 end) end) + ]]-- end -- Calculate class levels @@ -647,7 +651,7 @@ function Arena:quit() trigger:tween(1, _G, {slow_amount = 0}, math.linear, function() slow_amount = 0 end, 'slow_amount') trigger:tween(4, camera, {x = gw/2, y = gh/2, r = 0}, math.linear, function() camera.x, camera.y, camera.r = gw/2, gh/2, 0 end) self:set_passives() - RerollButton{group = main.current.ui, x = gw - 40, y = 40, parent = self, force_update = true} + RerollButton{group = main.current.ui, x = gw - 40, y = gh - 40, parent = self, force_update = true} self.shop_text = Text({{text = '[wavy_mid, fg]gold: [yellow]' .. gold, font = pixul_font, alignment = 'center'}}, global_text_tags) self.build_text = Text2{group = self.ui, x = 40, y = 20, force_update = true, lines = {{text = "[wavy_mid, fg]your build", font = pixul_font, alignment = 'center'}}} @@ -682,15 +686,15 @@ function Arena:set_passives(from_reroll) local passive_2 = random:table_remove(run_passive_pool) local passive_3 = random:table_remove(run_passive_pool) if passive_1 then - table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 0*(card_w + 20) + card_w/2 + 45, y = gh/2 - 6 + 10, w = card_w, h = card_h, card_i = 1, arena = self, passive = passive_1, force_update = true}) + table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 0*(card_w + 20) + card_w/2 + 45, y = gh/2 - 20, 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 + 45, y = gh/2 - 6 + 10, w = card_w, h = card_h, card_i = 2, arena = self, passive = passive_2, force_update = true}) + table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 1*(card_w + 20) + card_w/2 + 45, y = gh/2 - 20, 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 + 45, y = gh/2 - 6 + 10, w = card_w, h = card_h, card_i = 3, arena = self, passive = passive_3, force_update = true}) + table.insert(self.cards, PassiveCard{group = main.current.ui, x = gw/2 - w/2 + 2*(card_w + 20) + card_w/2 + 45, y = gh/2 - 20, 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 + 45, y = gh/2 - 65 + 10, lines = {{text = '[fg, wavy]choose one', font = fat_font, alignment = 'center'}}} + self.passive_text = Text2{group = self.ui, x = gw/2 + 45, y = gh/2 - 75, lines = {{text = '[fg, wavy]choose one', font = fat_font, alignment = 'center'}}} if not passive_1 and not passive_2 and not passive_3 then self:transition() end @@ -757,7 +761,7 @@ function Arena:draw() if self.choosing_passives or self.won or self.paused or self.died then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end self.ui:draw() - if self.shop_text then self.shop_text:draw(gw - 40, 20) end + if self.shop_text then self.shop_text:draw(gw - 40, gh - 17) end if self.in_credits then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent_2) end self.credits:draw() diff --git a/buy_screen.lua b/buy_screen.lua index 7182279..ea90511 100644 --- a/buy_screen.lua +++ b/buy_screen.lua @@ -241,8 +241,6 @@ function BuyScreen:draw() self.effects:draw() if self.items_text then self.items_text:draw(32, 145) end if self.level_text then self.level_text:draw(265, gh - 20) end - if self.paused then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end - self.ui:draw() if self.unit_grabbed then local x, y = camera:get_mouse_position() @@ -261,13 +259,15 @@ function BuyScreen:draw() if self.party_text then self.party_text:draw(440, 20) end if current_new_game_plus > 0 then self.ng_text:draw(265, gh - 40) end + if self.paused then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end + self.ui:draw() + if self.in_tutorial then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent_2) arrow:draw(gw/2 + 93, gh/2 - 30, 0, 0.4, 0.35) arrow:draw(gw/2 + 93, gh/2 - 10, 0, 0.4, 0.35) end self.tutorial:draw() - end @@ -1345,7 +1345,7 @@ function PassiveCard:on_mouse_enter() self.info_text:activate({ {text = self.passive_description, 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 + gh/4 + 22 + self.info_text.x, self.info_text.y = gw/2, gh/2 + gh/4 - 6 end diff --git a/enemies.lua b/enemies.lua index dda6222..5b09a6a 100644 --- a/enemies.lua +++ b/enemies.lua @@ -482,6 +482,14 @@ function Seeker:hit(damage, projectile, dot) end end + if main.current.healer_level > 0 then + if random:bool((main.current.healer_level == 2 and 16) or (main.current.healer_level == 1 and 8) or 0) then + trigger:after(0.01, function() + HealingOrb{group = main.current.main, x = self.x, y = self.y} + end) + end + end + if self.boss then slow(0.25, 1) magic_die1:play{pitch = random:float(0.95, 1.05), volume = 0.5} diff --git a/main.lua b/main.lua index eb2b7d8..2d55e73 100644 --- a/main.lua +++ b/main.lua @@ -24,6 +24,7 @@ function init() unlock1 = Sound('Unlock 3.ogg', s) gambler1 = Sound('Collect 5.ogg', s) usurer1 = Sound('Shadow Punch 2.ogg', s) + orb1 = Sound('Collect 2.ogg', s) gold1 = Sound('Collect 5.ogg', s) gold2 = Sound('Coins - Gears - Slot.ogg', s) psychic1 = Sound('Magical Impact 13.ogg', s) @@ -546,7 +547,7 @@ function init() ['magician'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('magician', lvl, 'dmg') .. ' AoE[fg] damage' end, ['archer'] = function(lvl) return '[fg]shoots an arrow that deals [yellow]' .. get_character_stat('archer', lvl, 'dmg') .. '[fg] damage and pierces' end, ['scout'] = function(lvl) return '[fg]throws a knife that deals [yellow]' .. get_character_stat('scout', lvl, 'dmg') .. '[fg] damage and chains [yellow]3[fg] times' end, - ['cleric'] = function(lvl) return '[fg]heals a unit for [yellow]20%[fg] of its max hp when it drops below [yellow]50%[fg] max hp' end, + ['cleric'] = function(lvl) return '[fg]creates [yellow]1[fg] healing orb' end, ['outlaw'] = function(lvl) return '[fg]throws a fan of [yellow]5[fg] knives, each dealing [yellow]' .. get_character_stat('outlaw', lvl, 'dmg') .. '[fg] damage' end, ['blade'] = function(lvl) return '[fg]throws multiple blades that deal [yellow]' .. get_character_stat('blade', lvl, 'dmg') .. ' AoE[fg] damage' end, ['elementor'] = function(lvl) return '[fg]deals [yellow]' .. get_character_stat('elementor', lvl, 'dmg') .. ' AoE[fg] damage in a large area centered on a random target' end, @@ -579,8 +580,8 @@ function init() ['psykino'] = function(lvl) return '[fg]pulls enemies together for [yellow]2[fg] seconds' end, ['barrager'] = function(lvl) return '[fg]shoots a barrage of [yellow]3[fg] arrows, each dealing [yellow]' .. get_character_stat('barrager', lvl, 'dmg') .. '[fg] damage and pushing enemies' end, ['highlander'] = function(lvl) return '[fg]deals [yellow]' .. 5*get_character_stat('highlander', lvl, 'dmg') .. '[fg] AoE damage' end, - ['fairy'] = function(lvl) return '[fg]periodically heals [yellow]1[fg] unit at random and grants it [yellow]+100%[fg] attack speed for [yellow]6[fg] seconds' end, - ['priest'] = function(lvl) return '[fg]heals all allies for [yellow]20%[fg] their max HP' end, + ['fairy'] = function(lvl) return '[fg]creates [yellow]1[fg] healing orb and grants [yellow]1[fg] unit [yellow]+100%[fg] attack speed for [yellow]6[fg] seconds' end, + ['priest'] = function(lvl) return '[fg]creates [yellow]5[fg] healing orbs' end, ['infestor'] = function(lvl) return '[fg]curses [yellow]8[fg] nearby enemies for [yellow]6[fg] seconds, they will release [yellow]2[fg] critters on death' end, ['flagellant'] = function(lvl) return '[fg]deals [yellow]' .. 2*get_character_stat('flagellant', lvl, 'dmg') .. '[fg] damage to self and grants [yellow]+4%[fg] damage to all allies per cast' end, ['arcanist'] = function(lvl) return '[fg]launches a slow moving orb that launches projectiles, each dealing [yellow]' .. get_character_stat('arcanist', lvl, 'dmg') .. '[fg] damage' end, @@ -718,7 +719,7 @@ function init() ['magician'] = function() return '[fg]the magician becomes invulnerable for [yellow]6[fg] seconds but also cannot attack' end, ['archer'] = function() return '[fg]the arrow ricochets off walls [yellow]3[fg] times' end, ['scout'] = function() return '[yellow]+25%[fg] damage per chain and [yellow]+3[fg] chains' end, - ['cleric'] = function() return '[fg]heals all units' end, + ['cleric'] = function() return '[fg]creates [yellow]4[fg] healing orbs' end, ['outlaw'] = function() return "[yellow]+50%[fg] outlaw attack speed and his knives seek enemies" end, ['blade'] = function() return '[fg]deal additional [yellow]' .. math.round(get_character_stat('blade', 3, 'dmg')/3, 2) .. '[fg] damage per enemy hit' end, ['elementor'] = function() return '[fg]slows enemies by [yellow]60%[fg] for [yellow]6[fg] seconds on hit' end, @@ -750,10 +751,10 @@ function init() ['psykino'] = function() return '[fg]enemies take [yellow]' .. 4*get_character_stat('psykino', 3, 'dmg') .. '[fg] damage and are pushed away when the area expires' end, ['barrager'] = function() return '[fg]every 3rd attack the barrage shoots [yellow]15[fg] projectiles and they push harder' end, ['highlander'] = function() return '[fg]quickly repeats the attack [yellow]3[fg] times' end, - ['fairy'] = function() return '[fg]heals [yellow]2[fg] units instead and grants them an additional [yellow]100%[fg] attack speed' end, + ['fairy'] = function() return '[fg]creates [yellow]2[fg] healing orbs and grants [yellow]2[fg] units [yellow]+100%[fg] attack speed' end, ['priest'] = function() return '[fg]picks [yellow]3[fg] units at random and grants them a buff that prevents death once' end, ['infestor'] = function() return '[fg][yellow]triples[fg] the number of critters released' end, - ['flagellant'] = function() return '[fg]deals [yellow]' .. 2*get_character_stat('flagellant', 3, 'dmg') .. '[fg] damage to all allies and grants [yellow]+12%[fg] damage to all allies per cast' end, + ['flagellant'] = function() return '[yellow]2X[fg] flagellant max HP and grants [yellow]+12%[fg] damage to all allies per cast instead' end, ['arcanist'] = function() return '[yellow]+50%[fg] attack speed for the orb and [yellow]2[fg] projectiles are released per cast' end, ['illusionist'] = function() return '[yellow]doubles[fg] the number of copies created and they release [yellow]12[fg] projectiles on death' end, ['witch'] = function() return '[fg]the area releases projectiles, each dealing [yellow]' .. get_character_stat('witch', 3, 'dmg') .. '[fg] damage and chaining once' end, @@ -775,7 +776,7 @@ function init() ['magician'] = function() return '[light_bg]the magician becomes invulnerable for 6 seconds but also cannot attack' end, ['archer'] = function() return '[light_bg]the arrow ricochets off walls 3 times' end, ['scout'] = function() return '[light_bg]+25% damage per chain and +3 chains' end, - ['cleric'] = function() return '[light_bg]heals all units' end, + ['cleric'] = function() return '[light_bg]creates 4 healing orbs' end, ['outlaw'] = function() return "[light_bg]+50% outlaw attack speed and his knives seek enemies" end, ['blade'] = function() return '[light_bg]deal additional ' .. math.round(get_character_stat('blade', 3, 'dmg')/2, 2) .. ' damage per enemy hit' end, ['elementor'] = function() return '[light_bg]slows enemies by 60% for 6 seconds on hit' end, @@ -807,10 +808,10 @@ function init() ['psykino'] = function() return '[light_bg]enemies take ' .. 4*get_character_stat('psykino', 3, 'dmg') .. ' damage and are pushed away when the area expires' end, ['barrager'] = function() return '[light_bg]every 3rd attack the barrage shoots 15 projectiles and they push harder' end, ['highlander'] = function() return '[light_bg]quickly repeats the attack 3 times' end, - ['fairy'] = function() return '[light_bg]heals 2 units instead and grants them an additional 100% attack speed' end, + ['fairy'] = function() return '[light_bg]creates 2 healing orbs and grants 2 units +100% attack speed' end, ['priest'] = function() return '[light_bg]picks 3 units at random and grants them a buff that prevents death once' end, ['infestor'] = function() return '[light_bg]triples the number of critters released' end, - ['flagellant'] = function() return '[light_bg]deals ' .. 2*get_character_stat('flagellant', 3, 'dmg') .. ' damage to all allies and grants +12% damage to all allies per cast' end, + ['flagellant'] = function() return '[light_bg]2X flagellant max HP and grants +12% damage to all allies per cast instead' end, ['arcanist'] = function() return '[light_bg]+50% attack speed for the orb and 2 projectiles are released per cast' end, ['illusionist'] = function() return '[light_bg]doubles the number of copies created and they release 12 projectiles on death' end, ['witch'] = function() return '[light_bg]the area periodically releases projectiles, each dealing ' .. get_character_stat('witch', 3, 'dmg') .. ' damage and chaining once' end, @@ -928,7 +929,7 @@ function init() ['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, + ['psyker'] = function(lvl) return '[fg]create a piercing, damaging orb around each psyker, it inherits damage from its target' 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, @@ -1484,8 +1485,11 @@ function init() main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5} main = Main() + + --[[ main:add(MainMenu'mainmenu') main:go_to('mainmenu') + ]]-- --[[ main:add(BuyScreen'buy_screen') @@ -1493,15 +1497,18 @@ function init() ]]-- -- main:go_to('buy_screen', 7, run.units or {}, {'unleash'}) - --[[ main:add(Arena'arena') main:go_to('arena', 4, { - {character = 'arcanist', level = 1}, - {character = 'witch', level = 1}, - {character = 'gambler', level = 1}, - {character = 'illusionist', level = 1}, - }, {{passive = 'freezing_field', level = 1}}) - ]]-- + {character = 'psykeeper', level = 3}, + {character = 'vagrant', level = 1}, + {character = 'psychic', level = 1}, + {character = 'flagellant', level = 1}, + --[[ + {character = 'priest', level = 1}, + {character = 'cleric', level = 1}, + {character = 'fairy', level = 1}, + ]]-- + }, {}) --[[ main:add(Media'media') @@ -1624,7 +1631,7 @@ function open_options(self) 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'}}} end - self.resume_button = Button{group = self.ui, x = gw/2, y = gh - 225, force_update = true, button_text = 'resume game (esc)', fg_color = 'bg10', bg_color = 'bg', action = function(b) + self.resume_button = Button{group = self.ui, x = gw/2, y = gh - 225, force_update = true, button_text = self:is(MainMenu) and 'main menu (esc)' or 'resume game (esc)', fg_color = 'bg10', bg_color = 'bg', action = function(b) trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() slow_amount = 1 self.paused = false @@ -1648,7 +1655,10 @@ function open_options(self) if self.arrow_snake_button then self.arrow_snake_button.dead = true; self.arrow_snake_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 + if self.main_menu_button then self.main_menu_button.dead = true; self.main_menu_button = nil end system.save_state() + if self:is(MainMenu) or self:is(BuyScreen) then input:set_mouse_visible(true) + elseif self:is(Arena) then input:set_mouse_visible(state.mouse_control or false) end end, 'pause') end} @@ -1815,7 +1825,6 @@ function open_options(self) 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 = state.dark_transitions and bg[-2] or fg[0], transition_action = function() - system.save_run() main:add(MainMenu'main_menu') main:go_to('main_menu') end, text = Text({{text = '[wavy, ' .. tostring(state.dark_transitions and 'fg' or 'bg') .. ']..', font = pixul_font, alignment = 'center'}}, global_text_tags)} @@ -1832,12 +1841,6 @@ end function close_options(self) - if not state.mouse_control then - input:set_mouse_visible(false) - end - if self:is(Arena) then - input:set_mouse_visible(state.mouse_control or false) - end trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function() slow_amount = 1 self.paused = false @@ -1863,6 +1866,8 @@ function close_options(self) if self.ng_plus_minus_button then self.ng_plus_minus_button.dead = true; self.ng_plus_minus_button = nil end if self.main_menu_button then self.main_menu_button.dead = true; self.main_menu_button = nil end system.save_state() + if self:is(MainMenu) or self:is(BuyScreen) then input:set_mouse_visible(true) + elseif self:is(Arena) then input:set_mouse_visible(state.mouse_control or false) end end, 'pause') end diff --git a/mainmenu.lua b/mainmenu.lua index d068597..8429d0e 100644 --- a/mainmenu.lua +++ b/mainmenu.lua @@ -83,11 +83,11 @@ function MainMenu:on_enter(from) self.title_text = Text({{text = '[wavy_mid, fg]SNKRX', font = fat_font, alignment = 'center'}}, global_text_tags) self.arena_run_button = Button{group = self.main_ui, x = 55, y = gh/2 - 10, force_update = true, button_text = 'arena run', 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} ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = state.dark_transitions and bg[-2] or fg[0], transition_action = function() + self.transitioning = true slow_amount = 1 local run = system.load_run() run_passive_pool = run.run_passive_pool or { diff --git a/player.lua b/player.lua index 13b4ce4..7008da7 100644 --- a/player.lua +++ b/player.lua @@ -137,7 +137,39 @@ function Player:init(args) end, nil, nil, 'shoot') elseif self.character == 'cleric' then - self.t:every(6, function() + self.t:every(8, function() + if self.level == 3 then + for i = 1, 4 do + local check_circle = Circle(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16), 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + while #objects > 0 do + check_circle:move_to(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16)) + objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + end + SpawnEffect{group = main.current.effects, x = check_circle.x, y = check_circle.y, color = green[0], action = function(x, y) + local check_circle = Circle(x, y, 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + if #objects == 0 then + HealingOrb{group = main.current.main, x = x, y = y} + end + end} + end + else + local check_circle = Circle(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16), 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + while #objects > 0 do + check_circle:move_to(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16)) + objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + end + SpawnEffect{group = main.current.effects, x = check_circle.x, y = check_circle.y, color = green[0], action = function(x, y) + local check_circle = Circle(x, y, 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + if #objects == 0 then + HealingOrb{group = main.current.main, x = x, y = y} + end + end} + end + --[[ local all_units = self:get_all_units() local unit_index = table.contains(all_units, function(v) return v.hp <= 0.5*v.max_hp end) if unit_index then @@ -150,6 +182,7 @@ function Player:init(args) end heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} end + ]]-- end, nil, nil, 'heal') elseif self.character == 'arcanist' then @@ -653,26 +686,52 @@ function Player:init(args) local unit_1 = random:table_remove(units) local unit_2 = random:table_remove(units) if unit_1 then - unit_1:heal(0.2*unit_1.max_hp*(self.heal_effect_m or 1)) unit_1.fairy_aspd_m = 3 unit_1.t:after(5.98, function() unit_1.fairy_aspd_m = 1 end) end if unit_2 then - unit_2:heal(0.2*unit_2.max_hp*(self.heal_effect_m or 1)) unit_2.fairy_aspd_m = 3 unit_2.t:after(5.98, function() unit_2.fairy_aspd_m = 1 end) end heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} buff1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + for i = 1, 2 do + local check_circle = Circle(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16), 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + while #objects > 0 do + check_circle:move_to(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16)) + objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + end + SpawnEffect{group = main.current.effects, x = check_circle.x, y = check_circle.y, color = green[0], action = function(x, y) + local check_circle = Circle(x, y, 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + if #objects == 0 then + HealingOrb{group = main.current.main, x = x, y = y} + end + end} + end + else local unit = random:table(self:get_all_units()) if unit then - unit:heal(0.2*unit.max_hp*(self.heal_effect_m or 1)) unit.fairy_aspd_m = 2 unit.t:after(5.98, function() unit.fairy_aspd_m = 1 end) end heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} buff1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + local check_circle = Circle(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16), 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + while #objects > 0 do + check_circle:move_to(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16)) + objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + end + SpawnEffect{group = main.current.effects, x = check_circle.x, y = check_circle.y, color = green[0], action = function(x, y) + local check_circle = Circle(x, y, 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + if #objects == 0 then + HealingOrb{group = main.current.main, x = x, y = y} + end + end} end end, nil, nil, 'heal') @@ -748,10 +807,20 @@ function Player:init(args) end) end - self.t:every(10, function() + self.t:every(15, function() + local x, y = random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16) + for i = 1, 5 do + SpawnEffect{group = main.current.effects, x = x, y = y, color = green[0], action = function(x, y) + local check_circle = Circle(x, y, 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + if #objects == 0 then HealingOrb{group = main.current.main, x = x, y = y} end + end} + end + --[[ local all_units = self:get_all_units() for _, unit in ipairs(all_units) do unit:heal(0.2*unit.max_hp*(self.heal_effect_m or 1)) end heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + ]]-- end, nil, nil, 'heal') elseif self.character == 'infestor' then @@ -769,32 +838,20 @@ function Player:init(args) elseif self.character == 'flagellant' then self.t:every(8, function() - if self.level == 3 then - flagellant1:play{pitch = random:float(0.95, 1.05), volume = 0.4} - buff1:play{pitch = random:float(0.95, 1.05), volume = 0.3} - local all_units = self:get_all_units() - local dmg = self.dmg - for _, unit in ipairs(all_units) do + buff1:play{pitch = random:float(0.95, 1.05), volume = 0.3} + flagellant1:play{pitch = random:float(0.95, 1.05), volume = 0.4} + local all_units = self:get_all_units() + for _, unit in ipairs(all_units) do + if unit.character == 'flagellant' then hit2:play{pitch = random:float(0.95, 1.05), volume = 0.4} - unit:hit(2*dmg) - if not unit.flagellant_dmg_m then - unit.flagellant_dmg_m = 1 - end - unit.flagellant_dmg_m = unit.flagellant_dmg_m + 0.12 + unit:hit(self.level == unit.dmg or 2*unit.dmg) end - - else - buff1:play{pitch = random:float(0.95, 1.05), volume = 0.3} - flagellant1:play{pitch = random:float(0.95, 1.05), volume = 0.4} - local all_units = self:get_all_units() - for _, unit in ipairs(all_units) do - if unit.character == 'flagellant' then - hit2:play{pitch = random:float(0.95, 1.05), volume = 0.4} - unit:hit(2*unit.dmg) - end - if not unit.flagellant_dmg_m then - unit.flagellant_dmg_m = 1 - end + if not unit.flagellant_dmg_m then + unit.flagellant_dmg_m = 1 + end + if self.level == 3 then + unit.flagellant_dmg_m = unit.flagellant_dmg_m + 0.12 + else unit.flagellant_dmg_m = unit.flagellant_dmg_m + 0.04 end end @@ -1011,6 +1068,21 @@ function Player:init(args) end) end + if self.character == 'flagellant' and self.level == 3 then + self.hp = 2*self.max_hp + end + + if self.leader then + self.t:after(0.5, function() + local units = self:get_all_units() + for _, unit in ipairs(units) do + if table.any(self.classes, function(v) return v == 'psyker' end) then + Projectile{group = main.current.main, x = unit.x + 24*math.cos(unit.r), y = unit.y + 24*math.sin(unit.r), color = fg[0], v = 200, dmg = unit.dmg, character = 'psyker', parent = unit} + end + end + end) + end + self.mouse_control_v_buffer = {} if main.current:is(MainMenu) then @@ -1109,6 +1181,7 @@ function Player:update(dt) elseif main.current.enchanter_level == 1 then self.enchanter_dmg_m = 1.15 else self.enchanter_dmg_m = 1 end + --[[ if table.any(self.classes, function(v) return v == 'psyker' end) then local class_levels = get_class_levels(self:get_all_units()) local number_of_active_sets = 0 @@ -1138,6 +1211,7 @@ function Player:update(dt) self.psyker_aspd_m = 1 end end + ]]-- if main.current.forcer_level == 2 then self.knockback_m = 1.5 elseif main.current.forcer_level == 1 then self.knockback_m = 1.25 @@ -1205,6 +1279,10 @@ function Player:update(dt) self.dividends_dmg_m = (1 + gold/100) end + if self.character == 'flagellant' and self.level == 3 then + self.flagellant_hp_m = 2 + end + self.buff_def_a = (self.warrior_def_a or 0) self.buff_aspd_m = (self.chronomancer_aspd_m or 1)*(self.vagrant_aspd_m or 1)*(self.outlaw_aspd_m or 1)*(self.fairy_aspd_m or 1)*(self.psyker_aspd_m or 1)*(self.chronomancy_aspd_m or 1)*(self.awakening_aspd_m or 1)*(self.berserking_aspd_m or 1)*(self.reinforce_aspd_m or 1)*(self.squire_aspd_m or 1)*(self.speed_3_aspd_m or 1)*(self.last_stand_aspd_m or 1)*(self.enchanted_aspd_m or 1) self.buff_dmg_m = (self.squire_dmg_m or 1)*(self.vagrant_dmg_m or 1)*(self.enchanter_dmg_m or 1)*(self.swordsman_dmg_m or 1)*(self.flagellant_dmg_m or 1)*(self.psyker_dmg_m or 1)*(self.ballista_dmg_m or 1)*(self.awakening_dmg_m or 1)*(self.reinforce_dmg_m or 1)*(self.payback_dmg_m or 1)*(self.immolation_dmg_m or 1)*(self.damage_4_dmg_m or 1)*(self.offensive_stance_dmg_m or 1)*(self.last_stand_dmg_m or 1)*(self.dividends_dmg_m or 1) @@ -1212,6 +1290,7 @@ function Player:update(dt) self.buff_area_size_m = (self.nuker_area_size_m or 1)*(self.magnify_area_size_m or 1)*(self.unleash_area_size_m or 1)*(self.last_stand_area_size_m or 1) self.buff_area_dmg_m = (self.nuker_area_dmg_m or 1)*(self.amplify_area_dmg_m or 1)*(self.unleash_area_dmg_m or 1)*(self.last_stand_area_dmg_m or 1) self.buff_mvspd_m = (self.wall_rider_mvspd_m or 1)*(self.centipede_mvspd_m or 1)*(self.squire_mvspd_m or 1)*(self.last_stand_mvspd_m or 1) + self.buff_hp_m = (self.flagellant_hp_m or 1) self:calculate_stats() if self.attack_sensor then self.attack_sensor:move_to(self.x, self.y) end @@ -1425,26 +1504,30 @@ function Player:hit(damage, from_undead) end end - local psykeeper = self:get_unit'psykeeper' - if psykeeper then - psykeeper.stored_heal = psykeeper.stored_heal + actual_damage - if psykeeper.stored_heal > (0.5*psykeeper.max_hp) and love.timer.getTime() - psykeeper.last_heal_time > 6 then - psykeeper.last_heal_time = love.timer.getTime() - local all_units = self:get_all_units() - for _, unit in ipairs(all_units) do - unit:heal(psykeeper.stored_heal*(self.heal_effect_m or 1)/#all_units) + if self.character == 'psykeeper' then + self.stored_heal = self.stored_heal + actual_damage + if self.stored_heal > (0.2*self.max_hp) then + self.stored_heal = 0 + local check_circle = Circle(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16), 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + while #objects > 0 do + check_circle:move_to(random:float(main.current.x1 + 16, main.current.x2 - 16), random:float(main.current.y1 + 16, main.current.y2 - 16)) + objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) end - if self.level == 3 then - buff1:play{pitch = random:float(0.95, 1.05), volume = 0.5} - local enemies = main.current.main:get_objects_by_classes(main.current.enemies) - for _, enemy in ipairs(enemies) do - enemy:hit(2*psykeeper.stored_heal/#enemies) - HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = fg[0], duration = 0.1} - LightningLine{group = main.current.effects, src = self, dst = enemy, color = fg[0]} + SpawnEffect{group = main.current.effects, x = check_circle.x, y = check_circle.y, color = green[0], action = function(x, y) + local check_circle = Circle(x, y, 2) + local objects = main.current.main:get_objects_in_shape(check_circle, {Seeker, EnemyCritter, Critter, Illusion, Volcano, Saboteur, Pet, Turret}) + if #objects == 0 then + HealingOrb{group = main.current.main, x = x, y = y} end + end} + end + + if self.level == 3 then + local enemies = main.current.main:get_objects_by_classes(main.current.enemies) + for _, enemy in ipairs(enemies) do + enemy:hit(2*actual_damage/#enemies) end - psykeeper.stored_heal = 0 - heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} end end @@ -1871,6 +1954,12 @@ function Projectile:init(args) end) end + elseif self.character == 'psyker' then + self.pierce = 10000 + self.orbit_distance = random:float(28, 36) + self.orbit_speed = random:float(4, 6) + self.orbit_offset = random:float(0, 2*math.pi) + elseif self.character == 'lich' then self.spring:pull(0.15) self.t:every(0.08, function() @@ -1937,6 +2026,16 @@ end function Projectile:update(dt) self:update_game_object(dt) + if self.character == 'psyker' then + if self.parent.dead then self.dead = true; self.parent = nil; return end + self:set_position(self.parent.x + self.orbit_distance*math.cos(self.orbit_speed*time + self.orbit_offset), self.parent.y + self.orbit_distance*math.sin(self.orbit_speed*time + self.orbit_offset)) + local dx, dy = self.x - (self.previous_x or 0), self.y - (self.previous_y or 0) + self.r = Vector(dx, dy):angle() + self:set_angle(self.r) + self.previous_x, self.previous_y = self.x, self.y + return + end + if self.character == 'spellblade' then self.orbit_r = self.orbit_r + self.orbit_vr*dt end @@ -1966,6 +2065,7 @@ function Projectile:update(dt) self.vr = self.vr + self.dvr*dt end + --[[ if self.parent.point_blank or self.parent.longshot then self.distance_travelled = self.distance_travelled + math.length(self:get_velocity()) if self.parent.point_blank and self.parent.longshot then @@ -1976,6 +2076,7 @@ function Projectile:update(dt) self.distance_dmg_m = math.remap(self.distance_travelled, 0, 15000, 0.75, 2) end end + ]]-- end @@ -2000,6 +2101,11 @@ function Projectile:draw() graphics.circle(self.x, self.y, 4, self.hfx.hit.f and fg[0] or self.color) graphics.pop() + elseif self.character == 'psyker' then + graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x) + graphics.circle(self.x, self.y, 2.5, self.hfx.hit.f and fg[0] or self.color) + graphics.pop() + else graphics.push(self.x, self.y, self.r + (self.orbit_r or 0)) graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 2, 2, self.color) @@ -2086,6 +2192,7 @@ function Projectile:on_collision_enter(other, contact) elseif self.character == 'engineer' or self.character == 'dual_gunner' or self.character == 'miner' then self:die(x, y, r, random:int(2, 3)) _G[random:table{'turret_hit_wall1', 'turret_hit_wall2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.2} + elseif self.character == 'psyker' then else self:die(x, y, r, random:int(2, 3)) proj_hit_wall1:play{pitch = random:float(0.9, 1.1), volume = 0.2} @@ -2132,9 +2239,10 @@ function Projectile:on_trigger_enter(other, contact) end if self.character == 'archer' or self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'hunter' or self.character == 'spellblade' or self.character == 'engineer' or - self.character == 'jester' or self.character == 'assassin' or self.character == 'barrager' or self.character == 'beastmaster' or self.character == 'witch' or self.character == 'miner' or self.character == 'thief' then + self.character == 'jester' or self.character == 'assassin' or self.character == 'barrager' or self.character == 'beastmaster' or self.character == 'witch' or self.character == 'miner' or self.character == 'thief' or + self.character == 'psyker' then hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35} - if self.character == 'spellblade' then + if self.character == 'spellblade' or self.character == 'psyker' then magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15} end elseif self.character == 'wizard' or self.character == 'lich' or self.character == 'arcanist' then @@ -3145,6 +3253,7 @@ function Gold:draw() graphics.pop() end + function Gold:on_trigger_enter(other, contact) if self.cant_be_picked_up then return end @@ -3195,6 +3304,92 @@ end +HealingOrb = Object:extend() +HealingOrb:implement(GameObject) +HealingOrb:implement(Physics) +function HealingOrb:init(args) + self:init_game_object(args) + self:init_game_object(args) + if tostring(self.x) == tostring(0/0) or tostring(self.y) == tostring(0/0) then self.dead = true; return end + self:set_as_rectangle(4, 4, 'dynamic', 'ghost') + self:set_restitution(0.5) + local r = random:float(0, 2*math.pi) + local f = random:float(2, 4) + self:apply_impulse(f*math.cos(r), f*math.sin(r)) + self:apply_angular_impulse(random:table{random:float(-6*math.pi, -2*math.pi), random:float(2*math.pi, 6*math.pi)}) + self:set_damping(2.5) + self:set_angular_damping(5) + self.color = yellow2[0] + self.hfx:add('hit', 1) + self.cant_be_picked_up = true + self.t:after(0.5, function() self.cant_be_picked_up = false end) + illusion1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + self.magnet_sensor = Circle(self.x, self.y, 32) +end + + +function HealingOrb:update(dt) + self:update_game_object(dt) + self.r = self:get_angle() + + if main.current.player.magnetism then + local players = self:get_objects_in_shape(self.magnet_sensor, {Player}) + if players and #players > 0 then + local x, y = 0, 0 + for _, p in ipairs(players) do + x = x + p.x + y = y + p.y + end + x = x/#players + y = y/#players + local r = self:angle_to_point(x, y) + self:apply_force(20*math.cos(r), 20*math.sin(r)) + end + end + if self.magnet_sensor then self.magnet_sensor:move_to(self.x, self.y) end +end + + +function HealingOrb:draw() + if not self.hfx.hit then return end + local sr = random:float(-0.1, 0.1) + graphics.push(self.x, self.y, self.r, self.hfx.hit.x + sr, self.hfx.hit.x + sr) + graphics.circle(self.x, self.y, 1.2*self.shape.w, self.hfx.hit.f and fg[0] or green_transparent_weak) + graphics.circle(self.x, self.y, 0.5*self.shape.w, self.hfx.hit.f and fg[0] or green[0]) + graphics.pop() +end + + +function HealingOrb:on_trigger_enter(other, contact) + if self.cant_be_picked_up then return end + + if other:is(Player) then + self.dead = true + HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 4, color = fg[0], duration = 0.1} + for i = 1, 2 do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = green[0]} end + orb1:play{pitch = random:float(0.95, 1.05), volume = 1} + heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5} + + local units = other:get_all_units() + local lowest_hp = 10000 + local lowest_unit + for _, unit in ipairs(units) do + if unit.hp < lowest_hp and unit.hp < unit.max_hp then + lowest_hp = unit.hp + lowest_unit = unit + end + end + if lowest_unit then + lowest_unit:heal(0.1*lowest_unit.max_hp*(lowest_unit.heal_effect_m or 1)) + else + + end + end +end + + + + Critter = Object:extend() Critter:implement(GameObject) Critter:implement(Physics) diff --git a/shared.lua b/shared.lua index 7d90846..2b08f59 100644 --- a/shared.lua +++ b/shared.lua @@ -31,9 +31,9 @@ function shared_init() slow_amount = 1 sfx = SoundTag() - sfx.volume = 0.5 + sfx.volume = state.sfx_volume or 0.5 music = SoundTag() - music.volume = 0.5 + music.volume = state.music_volume or 0.5 if state.volume_muted then sfx.volume = 0 end if state.music_muted then music.volume = 0 end diff --git a/todo b/todo index a6d3cfb..b51954e 100644 --- a/todo +++ b/todo @@ -1,4 +1,4 @@ -Looping Update +Healer & Psyker Update New items: General: Intimidation - enemies spawn with -10/20/30% max HP @@ -10,7 +10,7 @@ Looping Update Infesting Strike - X/Y/Z% chance for attacks to spawn 2 critters on kill Kinetic Strike - X/Y/Z% chance for attacks to push enemies away with high force Burning Strike - X% chance for attacks to ignite, dealing 20% dps for 3 seconds, ignited enemies ignite nearby enemies on death - Lucky Strike - X% chance for attacks to cause enemies to drop gold + Lucky Strike - X% chance for attacks to cause enemies to drop gold on death Healing Strike - X% chance for attacks to spawn a healing orb on kill Stunning Strike - X/Y/Z% chance for attacks to stun for 2 seconds Silencing Strike - X/Y/Z% chance for attacks to silence on hit @@ -23,26 +23,25 @@ Looping Update Divine Barrage - 10/20/30% chance to release a homing barrage when picking up a healing orb Psyker: Orbitism - 33/66/99% faster orb speed - Psychic Leak - orbs deal extra damage based on the amount of damage all psykers have taken recently - Psychokinesis - + Psychosink - orbs move faster based on the amount of damage all psykers have taken recently + Psychosense - 20/40/60% increased orb range Conjurer: Rearm - summons repeat their attacks once Taunt - 10/20/30% chance for summons to taunt nearby enemies on attack Summon Instability - summons explode when disappearing, dealing 100/150/200% damage + https://i.imgur.com/yzCVMah.png Changes: - Magnetism - also attracts healing orbs - Enchanted - 30/60/90% + * Magnetism - also attracts healing orbs + Enchanted - 33/66/99% Healer rework: - Enemies have a 8/16% chance to spawn healing orbs on death, orbs prioritize healing low health allies - Cleric: creates 1 healing orb, Lv.3: creates 4 healing orbs and grants +20% healing effectiveness - Priest: creates 6 healing orbs - Fairy: grants a random unit 100% attack speed for 6 seconds and creates 1 healing orb + * Enemies have a 8/16% chance to spawn healing orbs on death, orbs prioritize healing low health allies + * Cleric: creates 1 healing orb, Lv.3: creates 4 healing orbs + * Priest: creates 5 healing orbs + * Fairy: grants a random unit 100% attack speed for 6 seconds and creates 1 healing orb Psyker rework: - Create orbitting, damaging balls at the head of the snake equal to the number of psykers - Flagellant - Lv.3: 2X flagellant max HP and grants +10% damage to all allies per cast - Psychic - Lv.3: gains up to 300% damage the less HP the psychic has - Psykino - Lv.3: gains up to 100% attack speed the less HP the psykino has - Psykeeper - creates a healing orb every time the psykeeper takes 30% of its max HP in damage, Lv.3: deal double the damage taken by the psykeeper to all enemies + * Create a piercing, damaging orb around each psyker, it inherits damage from its target + * Flagellant - Lv.3: 4X flagellant max HP and +12% damage to all allies per cast + * Psykeeper - creates a healing orb every time the psykeeper takes 20% of its max HP in damage, Lv.3: deal double the damage taken by the psykeeper to all enemies Looping Change end screen Loop button on end screen @@ -50,9 +49,16 @@ Looping Update Difficulty is increased according to the formula for levels 25+ Snake size goes up by 1 every loop, up to 12 Balance - * Decreased reroll cost to 8 + Change cursers to add more curse targets as set bonuses + Decrease reroll cost to 5 * Increased sage's attack speed + Increase spawn marker time + Decrease range and thrown speed for forcers + Decrease damage for blue and white on higher NG + Increase gold rewards at higher NG QoL + Lowered sound effect for gambler + Selling items Show cooldown on elite attack * Options menu from buy screen * Add main menu @@ -70,6 +76,7 @@ Looping Update Add visuals divine intervention, fairy buff Change text for enchanted to "if you have >= 2 enchanters" and change text for reinforce to "if you have >= 1 enchanter" Bug fixes + Fix barbarian stun just slowing and not stunning * Fixed fullscreen button and general resolution issues Fixed a series of crashes that happened rarely right before changing from the arena back to the shop https://i.imgur.com/Rk6qbDD.png - merchant doesnt give reroll if dies @@ -81,6 +88,7 @@ Looping Update --- +30 refresh rate makes enemies faster?!?! Future ideas: Chaos related classes