Sorcerer update 1/4
parent
aa598914ac
commit
cea71538b2
|
@ -250,6 +250,7 @@ function Arena:on_enter(from, level, units, passives)
|
|||
self.healer_level = class_levels.healer
|
||||
self.psyker_level = class_levels.psyker
|
||||
self.conjurer_level = class_levels.conjurer
|
||||
self.sorcerer_level = class_levels.sorcerer
|
||||
|
||||
self.t:every(0.375, function()
|
||||
local p = random:table(star_positions)
|
||||
|
@ -732,6 +733,13 @@ function Arena:quit()
|
|||
steam.userStats.storeStats()
|
||||
end
|
||||
|
||||
if self.sorcerer_level >= 3 then
|
||||
state.achievement_sorcerers_win = true
|
||||
system.save_state()
|
||||
steam.userStats.setAchievement('SORCERERS_WIN')
|
||||
steam.userStats.storeStats()
|
||||
end
|
||||
|
||||
local units = self.player:get_all_units()
|
||||
local all_units_level_2 = true
|
||||
for _, unit in ipairs(units) do
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 336 B |
Binary file not shown.
Binary file not shown.
16
enemies.lua
16
enemies.lua
|
@ -180,7 +180,8 @@ function Seeker:init(args)
|
|||
elseif self.headbutter then
|
||||
self.color = orange[0]:clone()
|
||||
self.last_headbutt_time = 0
|
||||
self.t:every(function() return math.distance(self.x, self.y, main.current.player.x, main.current.player.y) < 64 and love.timer.getTime() - self.last_headbutt_time > 10 end, function()
|
||||
local n = math.remap(current_new_game_plus, 0, 5, 1, 0.5)
|
||||
self.t:every(function() return math.distance(self.x, self.y, main.current.player.x, main.current.player.y) < 64 and love.timer.getTime() - self.last_headbutt_time > 10*n end, function()
|
||||
if self.headbutt_charging or self.headbutting then return end
|
||||
self.headbutt_charging = true
|
||||
self.t:tween(2, self.color, {r = fg[0].r, b = fg[0].b, g = fg[0].g}, math.cubic_in_out, function()
|
||||
|
@ -191,19 +192,20 @@ function Seeker:init(args)
|
|||
self.last_headbutt_time = love.timer.getTime()
|
||||
self:set_damping(0)
|
||||
self:apply_steering_impulse(300, self:angle_to_object(main.current.player), 0.75)
|
||||
self.t:after(0.75, function()
|
||||
self.t:after(0.5, function()
|
||||
self.headbutting = false
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
elseif self.tank then
|
||||
self.color = yellow[0]:clone()
|
||||
self.buff_hp_m = 1.25 + (0.025*self.level)
|
||||
self.buff_hp_m = 1.25 + (0.025*self.level) + (0.2*current_new_game_plus)
|
||||
self:calculate_stats()
|
||||
self.hp = self.max_hp
|
||||
elseif self.shooter then
|
||||
self.color = fg[0]:clone()
|
||||
self.t:after({2, 4}, function()
|
||||
local n = math.remap(current_new_game_plus, 0, 5, 1, 0.5)
|
||||
self.t:after({2*n, 4*n}, function()
|
||||
self.shooting = true
|
||||
self.t:every({3, 5}, function()
|
||||
for i = 1, 3 do
|
||||
|
@ -434,7 +436,7 @@ function Seeker:hit(damage, projectile)
|
|||
trigger:after(0.01, function()
|
||||
local n = 8 + current_new_game_plus*2
|
||||
for i = 1, n do
|
||||
EnemyProjectile{group = main.current.main, x = self.x, y = self.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 150 + 5*self.level, dmg = 2*self.dmg}
|
||||
EnemyProjectile{group = main.current.main, x = self.x, y = self.y, color = blue[0], r = (i-1)*math.pi/(n/2), v = 120 + 5*self.level, dmg = 2*self.dmg}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
@ -442,8 +444,8 @@ function Seeker:hit(damage, projectile)
|
|||
if self.spawner then
|
||||
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
trigger:after(0.01, function()
|
||||
for i = 1, random:int(3, 6) do
|
||||
EnemyCritter{group = main.current.main, x = self.x, y = self.y, color = purple[0], r = random:float(0, 2*math.pi), v = 5 + 0.1*self.level, dmg = self.dmg, projectile = projectile}
|
||||
for i = 1, random:int(5, 8) do
|
||||
EnemyCritter{group = main.current.main, x = self.x, y = self.y, color = purple[0], r = random:float(0, 2*math.pi), v = 10 + 0.1*self.level, dmg = 2*self.dmg, projectile = projectile}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
134
main.lua
134
main.lua
|
@ -18,11 +18,13 @@ function init()
|
|||
input:bind('enter', {'space', 'return', 'fleft', 'fdown', 'fright'})
|
||||
|
||||
local s = {tags = {sfx}}
|
||||
illusion1 = Sound('Buff 5.ogg', s)
|
||||
thunder1 = Sound('399656__bajko__sfx-thunder-blast.ogg', s)
|
||||
flagellant1 = Sound('Whipping Horse 3.ogg', s)
|
||||
bard2 = Sound('376532__womb-affliction__flute-trill.ogg', s)
|
||||
bard1 = Sound('Magical Impact 12.ogg', s)
|
||||
frost1 = Sound('Frost Bolt 20.ogg', s)
|
||||
arcane1 = Sound('Magical Impact 26.ogg', s)
|
||||
pyro1 = Sound('Fire bolt 5.ogg', s)
|
||||
pyro2 = Sound('Explosion Fireworks_01.ogg', s)
|
||||
dot1 = Sound('Magical Swoosh 18.ogg', s)
|
||||
|
@ -125,6 +127,7 @@ function init()
|
|||
forcer = Image('forcer')
|
||||
swarmer = Image('swarmer')
|
||||
voider = Image('voider')
|
||||
sorcerer = Image('sorcerer')
|
||||
ouroboros_technique_r = Image('ouroboros_technique_r')
|
||||
ouroboros_technique_l = Image('ouroboros_technique_l')
|
||||
wall_echo = Image('wall_echo')
|
||||
|
@ -184,6 +187,7 @@ function init()
|
|||
['forcer'] = yellow[0],
|
||||
['swarmer'] = orange[0],
|
||||
['voider'] = purple[0],
|
||||
['sorcerer'] = blue2[0],
|
||||
}
|
||||
|
||||
class_color_strings = {
|
||||
|
@ -200,6 +204,7 @@ function init()
|
|||
['forcer'] = 'yellow',
|
||||
['swarmer'] = 'orange',
|
||||
['voider'] = 'purple',
|
||||
['sorcerer'] = 'blue2',
|
||||
}
|
||||
|
||||
character_names = {
|
||||
|
@ -244,6 +249,13 @@ function init()
|
|||
['priest'] = 'Priest',
|
||||
['infestor'] = 'Infestor',
|
||||
['flagellant'] = 'Flagellant',
|
||||
['arcanist'] = 'Arcanist',
|
||||
['illusionist'] = 'Illusionist',
|
||||
['witch'] = 'Witch',
|
||||
['silencer'] = 'Silencer',
|
||||
['vulcanist'] = 'Vulcanist',
|
||||
['warden'] = 'Warden',
|
||||
['psychic'] = 'Psychic',
|
||||
}
|
||||
|
||||
character_colors = {
|
||||
|
@ -288,6 +300,13 @@ function init()
|
|||
['priest'] = green[0],
|
||||
['infestor'] = orange[0],
|
||||
['flagellant'] = fg[0],
|
||||
['arcanist'] = blue2[0],
|
||||
['illusionist'] = blue2[0],
|
||||
['witch'] = purple[0],
|
||||
['silencer'] = blue2[0],
|
||||
['vulcanist'] = red[0],
|
||||
['warden'] = yellow[0],
|
||||
['psychic'] = fg[0],
|
||||
}
|
||||
|
||||
character_color_strings = {
|
||||
|
@ -332,6 +351,13 @@ function init()
|
|||
['priest'] = 'green',
|
||||
['infestor'] = 'orange',
|
||||
['flagellant'] = 'fg',
|
||||
['arcanist'] = 'blue2',
|
||||
['illusionist'] = 'blue2',
|
||||
['witch'] = 'purple',
|
||||
['silencer'] = 'blue2',
|
||||
['vulcanist'] = 'red',
|
||||
['warden'] = 'yellow',
|
||||
['psychic'] = 'fg',
|
||||
}
|
||||
|
||||
character_classes = {
|
||||
|
@ -376,6 +402,13 @@ function init()
|
|||
['priest'] = {'healer'},
|
||||
['infestor'] = {'curser', 'swarmer'},
|
||||
['flagellant'] = {'psyker', 'enchanter'},
|
||||
['arcanist'] = {'sorcerer'},
|
||||
['illusionist'] = {'sorcerer', 'conjurer'},
|
||||
['witch'] = {'sorcerer', 'voider'},
|
||||
['silencer'] = {'sorcerer', 'curser'},
|
||||
['vulcanist'] = {'sorcerer', 'nuker'},
|
||||
['warden'] = {'sorcerer', 'forcer'},
|
||||
['psychic'] = {'sorcerer', 'psyker'},
|
||||
}
|
||||
|
||||
character_class_strings = {
|
||||
|
@ -420,6 +453,13 @@ function init()
|
|||
['priest'] = '[green]Healer',
|
||||
['infestor'] = '[purple]Curser, [orange]Swarmer',
|
||||
['flagellant'] = '[fg]Psyker, [blue]Enchanter',
|
||||
['arcanist'] = '[blue2]Sorcerer',
|
||||
['illusionist'] = '[blue2]Sorcerer, [orange]Conjurer',
|
||||
['witch'] = '[blue2]Sorcerer, [purple]Voider',
|
||||
['silencer'] = '[blue2]Sorcerer, [purple]Curser',
|
||||
['vulcanist'] = '[blue2]Sorcerer, [red]Nuker',
|
||||
['warden'] = '[blue2]Sorcerer, [yellow]Forcer',
|
||||
['psychic'] = '[blue2]Sorcerer, [fg]Psyker',
|
||||
}
|
||||
|
||||
get_character_stat_string = function(character, level)
|
||||
|
@ -468,7 +508,7 @@ function init()
|
|||
['corruptor'] = function(lvl) return '[fg]spawn [yellow]3[fg] small critters if the corruptor kills an enemy' end,
|
||||
['beastmaster'] = function(lvl) return '[fg]spawn [yellow]2[fg] small critters if the beastmaster crits' end,
|
||||
['launcher'] = function(lvl) return '[fg]all nearby enemies are pushed after [yellow]4[fg] seconds, taking [yellow]' .. 2*get_character_stat('launcher', lvl, 'dmg') .. '[fg] damage on wall hit' end,
|
||||
['jester'] = function(lvl) return "[fg]curses [yellow]5[fg] nearby enemies for [yellow]6[fg] seconds, they will explode into [yellow]3[fg] knives on death" end,
|
||||
['jester'] = function(lvl) return "[fg]curses [yellow]4[fg] nearby enemies for [yellow]6[fg] seconds, they will explode into [yellow]3[fg] knives on death" end,
|
||||
['assassin'] = function(lvl) return '[fg]throws a piercing knife that deals [yellow]' .. get_character_stat('assassin', lvl, 'dmg') .. '[fg] damage + [yellow]' ..
|
||||
get_character_stat('assassin', lvl, 'dmg')/2 .. '[fg] damage per second' end,
|
||||
['host'] = function(lvl) return '[fg]periodically spawn [yellow]1[fg] small critter' end,
|
||||
|
@ -481,6 +521,13 @@ function init()
|
|||
['priest'] = function(lvl) return '[fg]heals all allies for [yellow]20%[fg] their max HP' end,
|
||||
['infestor'] = function(lvl) return '[fg]curses all 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,
|
||||
['illusionist'] = function(lvl) return '[fg]launches a projectile that deals [yellow]' .. get_character_stat('illusionist', lvl, 'dmg') .. '[fg] damage and creates copies that do the same' end,
|
||||
['witch'] = function(lvl) return '[fg]creates an area that ricochets around the arena and deals [yellow]' .. get_character_stat('witch', lvl, 'dmg') .. '[fg] damage per second' end,
|
||||
['silencer'] = function(lvl) return '[fg]curses [yellow]5[fg] nearby enemies for [yellow]6[fg] seconds, preventing them from using special attacks' end,
|
||||
['vulcanist'] = function(lvl) return '[fg]creates a volcano that explodes the nearby area [yellow]5[fg] times, dealing [yellow]' .. get_character_stat('vulcanist', lvl, 'dmg') .. 'AoE [fg]damage' end,
|
||||
['warden'] = function(lvl) return '[fg]creates a force field around a random unit that prevents enemies from entering' end,
|
||||
['psychic'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('psychic', lvl, 'dmg') .. '[fg] damage' end,
|
||||
}
|
||||
|
||||
character_effect_names = {
|
||||
|
@ -525,6 +572,13 @@ function init()
|
|||
['priest'] = '[green]Divine Intervention',
|
||||
['infestor'] = '[orange]Infestation',
|
||||
['flagellant'] = '[red]Zealotry',
|
||||
['arcanist'] = '[blue2]Arcane Orb',
|
||||
['illusionist'] = '[blue2]Mirror Image',
|
||||
['witch'] = '[purple]Death Pool',
|
||||
['silencer'] = '[blue2]Arcane Curse',
|
||||
['vulcanist'] = '[red]Lava Burst',
|
||||
['warden'] = '[yellow]Magnetic Field',
|
||||
['psychic'] = '[fg]Mental Strike'
|
||||
}
|
||||
|
||||
character_effect_names_gray = {
|
||||
|
@ -569,6 +623,13 @@ function init()
|
|||
['priest'] = '[light_bg]Divine Intervention',
|
||||
['infestor'] = '[light_bg]Infestation',
|
||||
['flagellant'] = '[light_bg]Zealotry',
|
||||
['arcanist'] = '[light_bg]Arcane Orb',
|
||||
['illusionist'] = '[light_bg]Mirror Image',
|
||||
['witch'] = '[light_bg]Death Pool',
|
||||
['silencer'] = '[light_bg]Arcane Curse',
|
||||
['vulcanist'] = '[light_bg]Lava Burst',
|
||||
['warden'] = '[light_bg]Magnetic Field',
|
||||
['psychic'] = '[light_bg]Mental Strike'
|
||||
}
|
||||
|
||||
character_effect_descriptions = {
|
||||
|
@ -613,6 +674,13 @@ function init()
|
|||
['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,
|
||||
['arcanist'] = function() return '[yellow]100%[fg] increased 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 that pierce and ricochet once' end,
|
||||
['witch'] = function() return '[fg]the area periodically releases projectiles, each dealing [yellow]' .. get_character_stat('witch', 3, 'dmg') .. '[fg] damage and chaining once' end,
|
||||
['silencer'] = function() return '[fg]the curse also deals [yellow]' .. get_character_stat('silencer', 3, 'dmg') .. '[fg] damage per second' end,
|
||||
['vulcanist'] = function() return '[fg]the volcano spawn also deals [yellow]' .. get_character_stat('vulcanist', 3, 'dmg') .. 'AoE [fg] damage and [yellow]doubles[fg] the number of explosions' end,
|
||||
['warden'] = function() return '[fg]creates the force field around [yellow]2[fg] additional random units' end,
|
||||
['psychic'] = function() return '[fg]the attack can happen from any distance and deals [yellow]double[fg] damage' end,
|
||||
}
|
||||
|
||||
character_effect_descriptions_gray = {
|
||||
|
@ -657,6 +725,13 @@ function init()
|
|||
['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,
|
||||
['arcanist'] = function() return '[light_bg]100% increased 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,
|
||||
['silencer'] = function() return '[light_bg]the curse also deals ' .. get_character_stat('silencer', 3, 'dmg') .. ' damage per second' end,
|
||||
['vulcanist'] = function() return '[light_bg]the volcano spawn also deals ' .. get_character_stat('vulcanist', 3, 'dmg') .. 'AoE damage and doubles the number of explosions' end,
|
||||
['warden'] = function() return '[light_bg]creates the force field around 2 additional random units' end,
|
||||
['psychic'] = function() return '[light_bg]the attack can happen from any distance and deals double damage' end,
|
||||
}
|
||||
|
||||
character_stats = {
|
||||
|
@ -701,6 +776,13 @@ function init()
|
|||
['priest'] = function(lvl) return get_character_stat_string('priest', lvl) end,
|
||||
['infestor'] = function(lvl) return get_character_stat_string('infestor', lvl) end,
|
||||
['flagellant'] = function(lvl) return get_character_stat_string('flagellant', lvl) end,
|
||||
['arcanist'] = function(lvl) return get_character_stat_string('arcanist', lvl) end,
|
||||
['illusionist'] = function(lvl) return get_character_stat_string('illusionist', lvl) end,
|
||||
['witch'] = function(lvl) return get_character_stat_string('witch', lvl) end,
|
||||
['silencer'] = function(lvl) return get_character_stat_string('silencer', lvl) end,
|
||||
['vulcanist'] = function(lvl) return get_character_stat_string('vulcanist', lvl) end,
|
||||
['warden'] = function(lvl) return get_character_stat_string('warden', lvl) end,
|
||||
['psychic'] = function(lvl) return get_character_stat_string('psychic', lvl) end,
|
||||
}
|
||||
|
||||
class_stat_multipliers = {
|
||||
|
@ -717,14 +799,28 @@ function init()
|
|||
['forcer'] = {hp = 1.25, dmg = 1.1, aspd = 0.9, area_dmg = 0.75, area_size = 0.75, def = 1.2, mvspd = 1},
|
||||
['swarmer'] = {hp = 1.2, dmg = 1, aspd = 1.25, area_dmg = 1, area_size = 1, def = 0.75, mvspd = 0.5},
|
||||
['voider'] = {hp = 0.75, dmg = 1.3, aspd = 1, area_dmg = 0.8, area_size = 0.75, def = 0.6, mvspd = 0.8},
|
||||
['sorcerer'] = {hp = 0.8, dmg = 1.3, aspd = 1, area_dmg = 1.2, area_size = 1, def = 0.8, mvspd = 1},
|
||||
['seeker'] = {hp = 0.5, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.3},
|
||||
['mini_boss'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.3},
|
||||
['enemy_critter'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.5},
|
||||
['saboteur'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 1.4},
|
||||
}
|
||||
|
||||
local ylb1 = function(lvl) return lvl >= 2 and 'fg' or (lvl >= 1 and 'yellow' or 'light_bg') end
|
||||
local ylb2 = function(lvl) return (lvl >= 2 and 'yellow' or 'light_bg') end
|
||||
local ylb1 = function(lvl)
|
||||
if lvl == 3 then return 'fg'
|
||||
elseif lvl == 2 then return 'fg'
|
||||
elseif lvl == 1 then return 'yellow'
|
||||
else return 'light_bg' end
|
||||
end
|
||||
local ylb2 = function(lvl)
|
||||
if lvl == 3 then return 'fg'
|
||||
elseif lvl == 2 then return 'yellow'
|
||||
else return 'light_bg' end
|
||||
end
|
||||
local ylb3 = function(lvl)
|
||||
if lvl == 3 then return 'yellow'
|
||||
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,
|
||||
|
@ -739,6 +835,9 @@ function init()
|
|||
['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,
|
||||
['sorcerer'] = function(lvl)
|
||||
return '[' .. ybl1(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'
|
||||
end,
|
||||
}
|
||||
|
||||
tier_to_characters = {
|
||||
|
@ -809,6 +908,7 @@ function init()
|
|||
local forcers = 0
|
||||
local swarmers = 0
|
||||
local voiders = 0
|
||||
local sorcerers = 0
|
||||
for _, unit in ipairs(units) do
|
||||
for _, unit_class in ipairs(character_classes[unit.character]) do
|
||||
if unit_class == 'ranger' then rangers = rangers + 1 end
|
||||
|
@ -824,10 +924,11 @@ function init()
|
|||
if unit_class == 'forcer' then forcers = forcers + 1 end
|
||||
if unit_class == 'swarmer' then swarmers = swarmers + 1 end
|
||||
if unit_class == 'voider' then voiders = voiders + 1 end
|
||||
if unit_class == 'sorcerer' then sorcerers = sorcerers + 1 end
|
||||
end
|
||||
end
|
||||
return {ranger = rangers, warrior = warriors, healer = healers, mage = mages, nuker = nukers, conjurer = conjurers, rogue = rogues,
|
||||
enchanter = enchanters, psyker = psykers, curser = cursers, forcer = forcers, swarmer = swarmers, voider = voiders}
|
||||
enchanter = enchanters, psyker = psykers, curser = cursers, forcer = forcers, swarmer = swarmers, voider = voiders, sorcerer = sorcerers}
|
||||
end
|
||||
|
||||
get_class_levels = function(units)
|
||||
|
@ -841,6 +942,11 @@ function init()
|
|||
if number_of_units >= 4 then return 2
|
||||
elseif number_of_units >= 2 then return 1
|
||||
else return 0 end
|
||||
elseif class == 'sorcerer' then
|
||||
if number_of_units >= 6 then return 3
|
||||
elseif number_of_units >= 4 then return 2
|
||||
elseif number_of_units >= 2 then return 1
|
||||
else return 0 end
|
||||
end
|
||||
end
|
||||
return {
|
||||
|
@ -857,6 +963,7 @@ function init()
|
|||
forcer = units_to_class_level(units_per_class.forcer, 'forcer'),
|
||||
swarmer = units_to_class_level(units_per_class.swarmer, 'swarmer'),
|
||||
voider = units_to_class_level(units_per_class.voider, 'voider'),
|
||||
sorcerer = units_to_class_level(units_per_class.sorcerer, 'sorcerer'),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -1181,21 +1288,18 @@ function init()
|
|||
if run.level and run.level > 0 then
|
||||
main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5}
|
||||
end
|
||||
|
||||
main:add(BuyScreen'buy_screen')
|
||||
main:go_to('buy_screen', run.level or 0, run.units or {}, passives)
|
||||
main_song_instance = _G[random:table{'song1', 'song2', 'song3', 'song4', 'song5'}]:play{volume = 0.5}
|
||||
|
||||
--[[
|
||||
main:add(Arena'arena')
|
||||
main:go_to('arena', 23, {
|
||||
{character = 'wizard', level = 1},
|
||||
{character = 'spellblade', level = 1},
|
||||
{character = 'chronomancer', level = 1},
|
||||
{character = 'lich', level = 1},
|
||||
{character = 'psykino', level = 1},
|
||||
}, passives)
|
||||
main:add(BuyScreen'buy_screen')
|
||||
main:go_to('buy_screen', run.level or 0, run.units or {}, passives)
|
||||
]]--
|
||||
|
||||
main:add(Arena'arena')
|
||||
main:go_to('arena', 16, {
|
||||
{character = 'witch', level = 3},
|
||||
}, passives)
|
||||
|
||||
trigger:every(2, function()
|
||||
if debugging_memory then
|
||||
for k, v in pairs(system.type_count()) do
|
||||
|
|
|
@ -262,6 +262,10 @@ function Unit:calculate_stats(first_run)
|
|||
self.base_hp = 100*math.pow(2, self.level-1)
|
||||
self.base_dmg = 10*math.pow(2, self.level-1)
|
||||
self.base_mvspd = 75
|
||||
elseif self:is(Illusion) then
|
||||
self.base_hp = 100*math.pow(2, self.level-1)
|
||||
self.base_dmg = 10*math.pow(2, self.level-1)
|
||||
self.base_mvspd = 15
|
||||
elseif self:is(EnemyCritter) or self:is(Critter) then
|
||||
local x = self.level
|
||||
local y = {0, 1, 3, 3, 4, 6, 5, 6, 9, 7, 8, 12, 10, 11, 15, 12, 13, 18, 16, 17, 21, 17, 20, 24, 25}
|
||||
|
|
195
player.lua
195
player.lua
|
@ -73,6 +73,32 @@ function Player:init(args)
|
|||
end
|
||||
end, nil, nil, 'heal')
|
||||
|
||||
elseif self.character == 'arcanist' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 128)
|
||||
self.t:cooldown(3, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
|
||||
if closest_enemy then
|
||||
self:shoot(self:angle_to_object(closest_enemy), {pierce = 1000, v = 40})
|
||||
end
|
||||
end, nil, nil, 'shoot')
|
||||
|
||||
elseif self.character == 'illusionist' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
|
||||
if closest_enemy then
|
||||
self:shoot(self:angle_to_object(closest_enemy))
|
||||
end
|
||||
end, nil, nil, 'shoot')
|
||||
self.t:every(8, function()
|
||||
self.t:every(0.25, function()
|
||||
SpawnEffect{group = main.current.effects, x = self.x, y = self.y, color = self.color, action = function(x, y)
|
||||
illusion1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
Illusion{group = main.current.main, x = x, y = y, parent = self, level = self.level, conjurer_buff_m = self.conjurer_buff_m or 1, crit = (self.level == 3) and random:bool(50)}
|
||||
end}
|
||||
end, self.level == 3 and 2 or 1)
|
||||
end)
|
||||
|
||||
elseif self.character == 'outlaw' then
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
self.t:cooldown(3, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
|
@ -100,7 +126,7 @@ function Player:init(args)
|
|||
elseif self.character == 'saboteur' then
|
||||
self.t:every(8, function()
|
||||
self.t:every(0.25, function()
|
||||
SpawnEffect{group = main.current.effects, x = self.x, y = self.y, action = function(x, y)
|
||||
SpawnEffect{group = main.current.effects, x = self.x, y = self.y, color = self.color, action = function(x, y)
|
||||
Saboteur{group = main.current.main, x = x, y = y, parent = self, level = self.level, conjurer_buff_m = self.conjurer_buff_m or 1, crit = (self.level == 3) and random:bool(50)}
|
||||
end}
|
||||
end, 2)
|
||||
|
@ -202,6 +228,11 @@ function Player:init(args)
|
|||
end)
|
||||
end
|
||||
|
||||
elseif self.character == 'witch' then
|
||||
self.t:every(6, function()
|
||||
self:dot_attack(24, {duration = random:float(12, 16), homing = true})
|
||||
end, nil, nil, 'attack')
|
||||
|
||||
elseif self.character == 'barbarian' then
|
||||
self.t:every(8, function()
|
||||
self:attack(96, {stun = 4})
|
||||
|
@ -267,7 +298,7 @@ function Player:init(args)
|
|||
elseif self.character == 'jester' then
|
||||
self.t:every({6, 10}, function()
|
||||
buff1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
|
||||
local enemies = table.first(table.shuffle(main.current.main:get_objects_by_classes(main.current.enemies)), 5)
|
||||
local enemies = table.first(table.shuffle(main.current.main:get_objects_by_classes(main.current.enemies)), self.level == 3 and 8 or 4)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
if self:distance_to_object(enemy) < 128 then
|
||||
enemy:curse('jester', 6*(self.hex_duration_m or 1), self.level == 3, self)
|
||||
|
@ -1158,7 +1189,7 @@ function Player:shoot(r, mods)
|
|||
dual_gunner2:play{pitch = random:float(0.95, 1.05), volume = 0.3}
|
||||
elseif self.character == 'archer' or self.character == 'hunter' or self.character == 'barrager' or self.character == 'corruptor' then
|
||||
archer1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
elseif self.character == 'wizard' or self.character == 'lich' then
|
||||
elseif self.character == 'wizard' or self.character == 'lich' or self.character == 'arcanist' or self.character == 'illusionist' then
|
||||
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
|
||||
elseif self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'spellblade' or self.character == 'jester' or self.character == 'assassin' or self.character == 'beastmaster' then
|
||||
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
|
@ -1173,6 +1204,10 @@ function Player:shoot(r, mods)
|
|||
frost1:play{pitch = random:float(0.95, 1.05), volume = 0.3}
|
||||
end
|
||||
|
||||
if self.character == 'arcanist' then
|
||||
arcane1:play{pitch = random:float(0.95, 1.05), volume = 0.3}
|
||||
end
|
||||
|
||||
if self.chance_to_barrage and random:bool(self.chance_to_barrage) then
|
||||
self:barrage(r, 3)
|
||||
end
|
||||
|
@ -1205,7 +1240,8 @@ function Player:dot_attack(area, mods)
|
|||
mods = mods or {}
|
||||
camera:shake(2, 0.5)
|
||||
self.hfx:use('shoot', 0.25)
|
||||
local t = {group = main.current.effects, x = mods.x or self.x, y = mods.y or self.y, r = self.r, rs = self.area_size_m*(area or 64), color = self.color, dmg = self.area_dmg_m*self.dmg, character = self.character, level = self.level}
|
||||
local t = {group = main.current.effects, x = mods.x or self.x, y = mods.y or self.y, r = self.r, rs = self.area_size_m*(area or 64), color = self.color, dmg = self.area_dmg_m*self.dmg,
|
||||
character = self.character, level = self.level, parent = self}
|
||||
DotArea(table.merge(t, mods))
|
||||
|
||||
dot1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
|
||||
|
@ -1233,6 +1269,7 @@ Projectile:implement(GameObject)
|
|||
Projectile:implement(Physics)
|
||||
function Projectile:init(args)
|
||||
self:init_game_object(args)
|
||||
self.hfx:add('hit', 1)
|
||||
self:set_as_rectangle(10, 4, 'dynamic', 'projectile')
|
||||
self.pierce = args.pierce or 0
|
||||
self.chain = args.chain or 0
|
||||
|
@ -1291,6 +1328,23 @@ function Projectile:init(args)
|
|||
self.t:every(0.08, function()
|
||||
HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color}
|
||||
end)
|
||||
|
||||
elseif self.character == 'arcanist' then
|
||||
self.dmg = 0.2*self.dmg
|
||||
self.t:every(0.08, function() HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color, r = self.r + math.pi + random:float(-math.pi/6, math.pi/6), v = random:float(10, 25), parent = self} end)
|
||||
self.t:every(self.parent.level == 3 and 0.54 or 0.8, function()
|
||||
local enemies = table.head(self:get_objects_in_shape(Circle(self.x, self.y, 128), main.current.enemies), self.level == 3 and 2 or 1)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
self.hfx:use('hit', 0.5)
|
||||
local r = self:angle_to_object(enemy)
|
||||
local t = {group = main.current.main, x = self.x + 8*math.cos(r), y = self.y + 8*math.sin(r), v = 250, r = r, color = self.parent.color, dmg = self.parent.dmg, pierce = 1000, character = 'arcanist_projectile',
|
||||
parent = self.parent, level = self.parent.level}
|
||||
Projectile(table.merge(t, mods or {}))
|
||||
end
|
||||
end)
|
||||
|
||||
elseif self.character == 'witch' and self.level == 3 then
|
||||
self.chain = 1
|
||||
end
|
||||
|
||||
if self.parent.divine_machine_arrow and table.any(self.parent.classes, function(v) return v == 'ranger' end) then
|
||||
|
@ -1381,7 +1435,12 @@ function Projectile:draw()
|
|||
|
||||
elseif self.character == 'lich' then
|
||||
graphics.push(self.x, self.y, self.r, self.spring.x, self.spring.x)
|
||||
graphics.circle(self.x, self.y, 4 + random:float(-1, 1), self.color)
|
||||
graphics.circle(self.x, self.y, 3 + random:float(-1, 1), self.color)
|
||||
graphics.pop()
|
||||
|
||||
elseif self.character == 'arcanist' then
|
||||
graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x)
|
||||
graphics.circle(self.x, self.y, 4, self.hfx.hit.f and fg[0] or self.color)
|
||||
graphics.pop()
|
||||
|
||||
else
|
||||
|
@ -1451,7 +1510,16 @@ function Projectile:on_collision_enter(other, contact)
|
|||
if self.character == 'spellblade' then
|
||||
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075}
|
||||
end
|
||||
elseif self.character == 'wizard' or self.character == 'lich' then
|
||||
elseif self.character == 'illusionist_death' then
|
||||
if self.ricochet <= 0 then
|
||||
self:die(x, y, r, random:int(2, 3))
|
||||
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075}
|
||||
else
|
||||
local r = Unit.bounce(self, nx, ny)
|
||||
self.r = r
|
||||
self.ricochet = self.ricochet - 1
|
||||
end
|
||||
elseif self.character == 'wizard' or self.character == 'lich' or self.character == 'arcanist' or self.character == 'arcanist_projectile' or self.character == 'illusionist' or self.character == 'witch' then
|
||||
self:die(x, y, r, random:int(2, 3))
|
||||
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075}
|
||||
elseif self.character == 'cannoneer' then
|
||||
|
@ -1511,8 +1579,10 @@ function Projectile:on_trigger_enter(other, contact)
|
|||
if self.character == 'spellblade' then
|
||||
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
|
||||
end
|
||||
elseif self.character == 'wizard' or self.character == 'lich' then
|
||||
elseif self.character == 'wizard' or self.character == 'lich' or self.character == 'arcanist' or self.character == 'illusionist' or self.character == 'illusionist_death' or self.character == 'witch' then
|
||||
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
|
||||
elseif self.character == 'arcanist_projectile' then
|
||||
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075}
|
||||
else
|
||||
hit3:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
end
|
||||
|
@ -1732,11 +1802,13 @@ end
|
|||
|
||||
DotArea = Object:extend()
|
||||
DotArea:implement(GameObject)
|
||||
DotArea:implement(Physics)
|
||||
function DotArea:init(args)
|
||||
self:init_game_object(args)
|
||||
self.shape = Circle(self.x, self.y, self.rs)
|
||||
self.closest_sensor = Circle(self.x, self.y, 128)
|
||||
|
||||
if self.character == 'plague_doctor' or self.character == 'pyromancer' then
|
||||
if self.character == 'plague_doctor' or self.character == 'pyromancer' or self.character == 'witch' then
|
||||
self.t:every(0.2, function()
|
||||
local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies)
|
||||
if #enemies > 0 then self.spring:pull(0.05, 200, 10) end
|
||||
|
@ -1810,6 +1882,23 @@ function DotArea:init(args)
|
|||
end, nil, nil, 'dot')
|
||||
end
|
||||
|
||||
if self.character == 'witch' then
|
||||
self.v = random:float(40, 80)
|
||||
self.r = random:table{math.pi/4, 3*math.pi/4, -math.pi/4, -3*math.pi/4}
|
||||
if self.level == 3 then
|
||||
self.t:every(1, function()
|
||||
local enemies = main.current.main:get_objects_in_shape(self.closest_sensor, main.current.enemies)
|
||||
if enemies and #enemies > 0 then
|
||||
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.05}
|
||||
local r = self:angle_to_object(enemies[1])
|
||||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6}
|
||||
local t = {group = main.current.main, x = self.x, y = self.y, v = 250, r = r, color = self.parent.color, dmg = self.parent.dmg, character = 'witch', parent = self.parent, level = self.parent.level}
|
||||
Projectile(table.merge(t, mods or {}))
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
self.color = fg[0]
|
||||
self.color_transparent = Color(args.color.r, args.color.g, args.color.b, 0.08)
|
||||
self.rs = 0
|
||||
|
@ -1842,6 +1931,17 @@ function DotArea:update(dt)
|
|||
self.shape:move_to(self.x, self.y)
|
||||
end
|
||||
end
|
||||
|
||||
if self.character == 'witch' then
|
||||
self.x, self.y = self.x + self.v*math.cos(self.r)*dt, self.y + self.v*math.sin(self.r)*dt
|
||||
if self.x >= main.current.x2 - self.shape.rs/2 or self.x <= main.current.x1 + self.shape.rs/2 then
|
||||
self.r = math.pi - self.r
|
||||
end
|
||||
if self.y >= main.current.y2 - self.shape.rs/2 or self.y <= main.current.y1 + self.shape.rs/2 then
|
||||
self.r = 2*math.pi - self.r
|
||||
end
|
||||
self.shape:move_to(self.x, self.y)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -2217,6 +2317,85 @@ end
|
|||
|
||||
|
||||
|
||||
Illusion = Object:extend()
|
||||
Illusion:implement(GameObject)
|
||||
Illusion:implement(Physics)
|
||||
Illusion:implement(Unit)
|
||||
function Illusion:init(args)
|
||||
self:init_game_object(args)
|
||||
self:init_unit()
|
||||
self:set_as_rectangle(8, 8, 'dynamic', 'player')
|
||||
self:set_restitution(0.5)
|
||||
|
||||
self.color = character_colors.illusionist
|
||||
self.character = 'illusionist'
|
||||
self.classes = {'sorcerer', 'conjurer'}
|
||||
self:calculate_stats(true)
|
||||
self:set_as_steerable(self.v, 2000, 4*math.pi, 4)
|
||||
|
||||
self.attack_sensor = Circle(self.x, self.y, 96)
|
||||
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
|
||||
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
|
||||
if closest_enemy then
|
||||
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.05}
|
||||
local r = self:angle_to_object(closest_enemy)
|
||||
HitCircle{group = main.current.effects, x = self.x + 0.8*self.shape.w*math.cos(r), y = self.y + 0.8*self.shape.w*math.sin(r), rs = 6}
|
||||
local t = {group = main.current.main, x = self.x + 1.6*self.shape.w*math.cos(r), y = self.y + 1.6*self.shape.w*math.sin(r), v = 250, r = r, color = self.parent.color, dmg = self.parent.dmg, character = 'illusionist',
|
||||
parent = self.parent, level = self.parent.level}
|
||||
Projectile(table.merge(t, mods or {}))
|
||||
end
|
||||
end, nil, nil, 'shoot')
|
||||
|
||||
self.t:after(12*(self.parent.conjurer_buff_m or 1), function()
|
||||
local n = n or random:int(3, 4)
|
||||
for i = 1, n do HitParticle{group = main.current.effects, x = self.x, y = self.y, r = random:float(0, 2*math.pi), color = self.color} end
|
||||
HitCircle{group = main.current.effects, x = self.x, y = self.y}:scale_down()
|
||||
self.dead = true
|
||||
|
||||
if self.parent.level == 3 then
|
||||
shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.2}
|
||||
for i = 1, 12 do
|
||||
Projectile{group = main.current.main, x = self.x, y = self.y, color = self.color, r = (i-1)*math.pi/6, v = 200, dmg = self.parent.dmg, character = 'illusionist_death',
|
||||
parent = self.parent, level = self.parent.level, pierce = 1, ricochet = 1}
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
function Illusion:update(dt)
|
||||
self:update_game_object(dt)
|
||||
|
||||
self:calculate_stats()
|
||||
|
||||
if not self.target then self.target = random:table(self.group:get_objects_by_classes(main.current.enemies)) end
|
||||
if self.target and self.target.dead then self.target = random:table(self.group:get_objects_by_classes(main.current.enemies)) end
|
||||
if not self.seek_f then return end
|
||||
if not self.target then
|
||||
self:seek_point(gw/2, gh/2)
|
||||
self:wander(50, 200, 50)
|
||||
self:rotate_towards_velocity(1)
|
||||
self:steering_separate(32, {Illusion, Seeker, Player})
|
||||
else
|
||||
self:seek_point(self.target.x, self.target.y)
|
||||
self:wander(50, 200, 50)
|
||||
self:rotate_towards_velocity(1)
|
||||
self:steering_separate(32, {Illusion, Seeker, Player})
|
||||
end
|
||||
self.r = self:get_angle()
|
||||
|
||||
self.attack_sensor:move_to(self.x, self.y)
|
||||
end
|
||||
|
||||
|
||||
function Illusion:draw()
|
||||
graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x)
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 3, 3, self.hfx.hit.f and fg[0] or self.color)
|
||||
graphics.pop()
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
Critter = Object:extend()
|
||||
Critter:implement(GameObject)
|
||||
|
|
|
@ -12,6 +12,7 @@ function shared_init()
|
|||
green = ColorRamp(Color'#8bbf40', 0.025),
|
||||
red = ColorRamp(Color'#e91d39', 0.025),
|
||||
purple = ColorRamp(Color'#8e559e', 0.025),
|
||||
blue2 = ColorRamp(Color'#4778ba', 0.025),
|
||||
}
|
||||
for name, color in pairs(colors) do
|
||||
_G[name] = color
|
||||
|
@ -765,7 +766,11 @@ end
|
|||
|
||||
function HitParticle:draw()
|
||||
graphics.push(self.x, self.y, self.r)
|
||||
graphics.rectangle(self.x, self.y, self.w, self.h, 2, 2, self.color)
|
||||
if self.parent and not self.parent.dead then
|
||||
graphics.rectangle(self.x, self.y, self.w, self.h, 2, 2, self.parent.hfx.hit.f and fg[0] or self.color)
|
||||
else
|
||||
graphics.rectangle(self.x, self.y, self.w, self.h, 2, 2, self.color)
|
||||
end
|
||||
graphics.pop()
|
||||
end
|
||||
|
||||
|
|
93
todo
93
todo
|
@ -1,37 +1,68 @@
|
|||
Hide cursor during waves
|
||||
Mouse follow control?
|
||||
Item reroll for 15 gold
|
||||
Option to have an arrow at the head of the snake - https://imgur.com/a/poXVsoN
|
||||
Option to turn off camera movement
|
||||
Headbutter damage should falloff faster after it strikes
|
||||
https://i.imgur.com/QN0Ntq2.png
|
||||
https://i.imgur.com/YfhqDYr.png
|
||||
https://i.imgur.com/ps4OA7o.png
|
||||
Remove level 3 units from rotation
|
||||
Fix highlight colors and highlight reserve
|
||||
Fix bug where quitting on level 1 jumps to level 2
|
||||
Fix lock bug after death/win - https://i.imgur.com/iUyOtLk.png
|
||||
Options menu from buy screen
|
||||
Fix fullscreen with different resolutions that don't scale properly
|
||||
Volume slider
|
||||
Sorcerer update
|
||||
Options
|
||||
Option to have an arrow at the head of the snake - https://imgur.com/a/poXVsoN
|
||||
Option to turn off camera movement
|
||||
Options menu from buy screen
|
||||
Volume slider
|
||||
Fix fullscreen with different resolutions that don't scale properly
|
||||
QoL
|
||||
Item reroll for 15 gold
|
||||
Fix highlight colors and highlight reserve
|
||||
Change cursers to trigger only near enemies
|
||||
Rename tutorial to guide or manual
|
||||
Add visuals for defensive ouroboros
|
||||
Unlock automatically on shop enter
|
||||
Bug fixes
|
||||
Headbutter damage should falloff faster after it strikes
|
||||
https://i.imgur.com/QN0Ntq2.png
|
||||
https://i.imgur.com/YfhqDYr.png
|
||||
https://i.imgur.com/ps4OA7o.png
|
||||
https://i.imgur.com/j1LS3zt.png
|
||||
https://i.imgur.com/XXJn4uW.png
|
||||
Fix bug where quitting on level 1 jumps to level 2
|
||||
Fix lock bug after death/win - https://i.imgur.com/iUyOtLk.png
|
||||
Fix enemies still spawning after arena clear (this happens with the extra enemy spawns that were blocked earlier)
|
||||
Fix death + win at the same time bug
|
||||
Balance
|
||||
Buff tanks, maybe add a simple forcer ability to them
|
||||
Buff 24/25 HP again
|
||||
Buff headbutter (+ trigger range)
|
||||
New
|
||||
Sorcerer = sorcerers repeat their attacks once every 4/3/2 attacks
|
||||
* Arcanist (tier 1 sorcerer) - launches a slow piercing orb that launches other piercing projectiles, Lv.3 effect - 50% increased attack speed for the orb and 2 projectiles are released per cast
|
||||
* Sorcerer + Conjurer = Illusionist - launches a projectile that deals X damage and creates copies that do the same, Lv.3 effect - doubles the number of copies created and they release additional projectiles on death
|
||||
* Sorcerer + Voider = Witch - creates an area that ricochets around the arena and deals X damage over time, Lv.3 effect - the area periodically releases projectiles that chains once
|
||||
Sorcerer + Curser = Silencer - curses 5 nearby enemies for 6 seconds, preventing them from using special attacks, Lv.3 effect - the curse also deals X damage over time
|
||||
Sorcerer + Nuker = Vulcanist - creates a volcano that explodes the nearby area 5 times, Lv.3 effect - the volcano spawn also deals damage and doubles the number of explosions
|
||||
Sorcerer + Forcer = Warden - creates a force field around a random unit that prevents enemies from entering, Lv.3 effect - creates the force field around 2 other random units
|
||||
Sorcerer + Psyker = Psychic - creates a small area that deals X damage, Lv.3 effect - the attack can happen from any distance and repeats twice
|
||||
|
||||
Sorcerer = sorcerers repeat their attacks once every 3/2 attacks
|
||||
Sorcerer + Conjurer = Illusionist - launches a projectile that deals X damage and creates copies that do the same, Lv.3 effect - doubles the number of copies created and they release additional projectiles on death
|
||||
Sorcerer + Voider = Witch - creates an area that deals X damage over time and seeks nearby enemies, Lv.3 effect - the area periodically releases homing projectiles that pierce 2 times
|
||||
Sorcerer + Curser = Linker - links 3 enemies together, they share damage taken, Lv.3 effect - link 6 enemies instead and damage shared is doubled
|
||||
Sorcerer + Nuker = Vulcanist - creates a volcano that explodes the nearby area 5 times, Lv.3 effect - the volcano spawn also deals damage and doubles the number of explosions
|
||||
Sorcerer + Forcer = Warden - creates a force field around a random unit that prevents enemies from entering, Lv.3 effect - creates the force field around 2 other random units
|
||||
Sorcerer update patch notes
|
||||
Decreased projectile speed for the exploder (blue enemy)
|
||||
Changed shooters (white enemy) to scale with NG+ difficulty
|
||||
Increased damage and movement speed for enemy swarmers (small purple enemies)
|
||||
Added tooltips for "restart run" and "tutorial" buttons on the shop
|
||||
Fixed text that was going outside the screen for the Priest and the Assassin
|
||||
Fixed bug where Divine Punishment would continue triggering after death
|
||||
Removed cooldown visuals on snake for units that don't have cooldowns (Squire, Chronomancer and Psykeeper)
|
||||
Slightly decreased base game's difficulty
|
||||
Fixed NG+ difficulty only being able to be lowered, now you can lower or increase it (up to your maximum acquired value)
|
||||
|
||||
Patch Notes:
|
||||
Decreased projectile speed for the exploder (blue enemy)
|
||||
Added tooltips for "restart run" and "tutorial" buttons on the shop
|
||||
Fixed text that was going outside the screen for the Priest and the Assassin
|
||||
Fixed bug where Divine Punishment would continue triggering after death
|
||||
Removed cooldown visuals on snake for units that don't have cooldowns (Squire, Chronomancer and Psykeeper)
|
||||
Slightly decreased base game's difficulty
|
||||
Fixed NG+ difficulty only being able to be lowered, now you can lower or increase it (up to your maximum acquired value)
|
||||
---
|
||||
|
||||
Future ideas:
|
||||
Chaos related class = Invoker - shoots a projectile with random properties, Lv.3 effect - ???
|
||||
Chaos related classes
|
||||
Invoker - shoots a projectile with random properties, Lv.3 effect - ???
|
||||
Trappers:
|
||||
Triangler - drops a trap and the 3rd trap will trigger the area, dealing X AoE damage 2-3 times
|
||||
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
|
||||
Go through this later https://i.imgur.com/4t7NA32.png <- lots of good improvements
|
||||
Remove level 3 units from rotation
|
||||
Hide cursor during waves
|
||||
Mouse follow control?
|
||||
|
||||
Roguelite update:
|
||||
Slay the Spire-like node selection map (copy code from SHOOTRX repo as this is already implemented there)
|
||||
Units die permanently when they die
|
||||
|
|
Loading…
Reference in New Issue