master
a327ex 2021-04-11 23:51:34 -03:00
parent f3c1475e37
commit d006dd3782
11 changed files with 485 additions and 188 deletions

View File

@ -235,13 +235,13 @@ function Arena:on_enter(from, level, units)
table.insert(units, self.player) table.insert(units, self.player)
for _, f in ipairs(self.player.followers) do table.insert(units, f) end for _, f in ipairs(self.player.followers) do table.insert(units, f) end
local class_levels = get_class_levels(get_number_of_units_per_class(units)) local class_levels = get_class_levels(units)
self.ranger_level = class_levels.ranger self.ranger_level = class_levels.ranger
self.warrior_level = class_levels.warrior self.warrior_level = class_levels.warrior
self.mage_level = class_levels.mage self.mage_level = class_levels.mage
self.rogue_level = class_levels.rogue self.rogue_level = class_levels.rogue
self.nuker_level = class_levels.nuker self.nuker_level = class_levels.nuker
self.trapper_level = class_levels.trapper self.curser_level = class_levels.curser
self.forcer_level = class_levels.forcer self.forcer_level = class_levels.forcer
self.swarmer_level = class_levels.swarmer self.swarmer_level = class_levels.swarmer
self.voider_level = class_levels.voider self.voider_level = class_levels.voider

View File

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -863,3 +863,27 @@ Either way, 21 out of 40 characters 100% done is still good.
| Psykeeper | Crucio | also redistributes damage taken as damage to all enemies at double value | | Psykeeper | Crucio | also redistributes damage taken as damage to all enemies at double value |
| Engineer | Upgrade | every 3rd sentry dropped upgrade all sentries with +100% damage and attack speed | | Engineer | Upgrade | every 3rd sentry dropped upgrade all sentries with +100% damage and attack speed |
| Plague Doctor | Black Death Steam | nearby enemies take an additional X damage per second | | Plague Doctor | Black Death Steam | nearby enemies take an additional X damage per second |
# Day 54 - 11/04/21
Implemented more 7 units fully. Today was slower because these were all new units that also were the first units for the new 4 classes, so I had to do some more work to get it going. The rest should go faster tomorrow.
| Character | Classes | Description |
| --- | --- | --- |
| Barbarian | curser, warrior | deals X AoE damage and stuns enemies hit for 4 seconds |
| Juggernaut | forcer, warrior | deals X AoE damage and pushes enemies away with a strong force |
| Lich | mage | launches a slow projectilt that jumps 7 times, dealing 2X damage per hit |
| Cryomancer | mage, voider | nearby enemies take X damage per second |
| Pyromancer | mage, nuker, voider | nearby enemies take X damage per second |
| Corruptor | ranger, swarmer | spawn 3 small critters if the corruptor kills an enemy |
| Beastmaster | rogue, swarmer | spawn 2 small critters if the beastmaster crits |
| Character | Lv.3 Effect Name | Lv.3 Effect Description |
| --- | --- | --- |
| Barbarian | Seism | stunned enemies also take +100% damage |
| Juggernaut | Brutal Impact | enemies pushed by the juggernaut take 4X damage if they hit a wall |
| Lich | Chain Frost | chain frost slows enemies hit by 80% for 2 seconds and chains +7 times |
| Cryomancer | Frostbite | enemies are also slowed by 60% while in the area |
| Pyromancer | Ignite | enemies killed by the pyromancer explode, dealing X AoE damage |
| Corruptor | Corruption | spawn 3 small critters if the corruptor hits an enemy |
| Beastmaster | Call of the Wild | spawn 2 small critters if the beastmaster gets hit |

View File

@ -243,6 +243,8 @@ function Seeker:update(dt)
self:calculate_stats() self:calculate_stats()
self.stun_dmg_m = (self.barbarian_stunned and 2 or 1)
if self.shooter then if self.shooter then
self.t:set_every_multiplier('shooter', (1 - self.level*0.02)) self.t:set_every_multiplier('shooter', (1 - self.level*0.02))
end end
@ -253,6 +255,7 @@ function Seeker:update(dt)
if self.push_invulnerable then self.push_invulnerable = false end if self.push_invulnerable then self.push_invulnerable = false end
self.being_pushed = false self.being_pushed = false
self.steering_enabled = true self.steering_enabled = true
self.juggernaut_push = false
self:set_damping(0) self:set_damping(0)
self:set_angular_damping(0) self:set_angular_damping(0)
end end
@ -318,6 +321,10 @@ function Seeker:on_collision_enter(other, contact)
if other:is(Wall) then if other:is(Wall) then
self.hfx:use('hit', 0.15, 200, 10, 0.1) self.hfx:use('hit', 0.15, 200, 10, 0.1)
self:bounce(contact:getNormal()) self:bounce(contact:getNormal())
if self.juggernaut_push then
self:hit(self.juggernaut_push)
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
end
elseif table.any(main.current.enemies, function(v) return other:is(v) end) then elseif table.any(main.current.enemies, function(v) return other:is(v) end) then
if self.being_pushed and math.length(self:get_velocity()) > 60 then if self.being_pushed and math.length(self:get_velocity()) > 60 then
@ -344,14 +351,26 @@ end
function Seeker:hit(damage, projectile) function Seeker:hit(damage, projectile)
local pyrod = self.pyrod
self.pyrod = false
if self.dead then return end if self.dead then return end
self.hfx:use('hit', 0.25, 200, 10) self.hfx:use('hit', 0.25, 200, 10)
if self.push_invulnerable then return end if self.push_invulnerable then return end
self:show_hp() self:show_hp()
local actual_damage = self:calculate_damage(damage) local actual_damage = self:calculate_damage(damage)*self.stun_dmg_m
self.hp = self.hp - actual_damage self.hp = self.hp - actual_damage
main.current.damage_dealt = main.current.damage_dealt + actual_damage main.current.damage_dealt = main.current.damage_dealt + actual_damage
if projectile and projectile.spawn_critters_on_hit then
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
trigger:after(0.01, function()
for i = 1, projectile.spawn_critters_on_hit do
Critter{group = main.current.main, x = self.x, y = self.y, color = orange[0], r = random:float(0, 2*math.pi), v = 10, dmg = projectile.parent.dmg}
end
end)
end
if self.hp <= 0 then if self.hp <= 0 then
self.dead = true self.dead = true
for i = 1, random:int(4, 6) do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color} end for i = 1, random:int(4, 6) do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color} end
@ -388,6 +407,22 @@ function Seeker:hit(damage, projectile)
end end
end) end)
end end
if pyrod then
trigger:after(0.01, function()
Area{group = main.current.main, x = self.x, y = self.y, color = red[0], w = 32*pyrod.parent.area_size_m, r = random:float(0, 2*math.pi), dmg = pyrod.parent.area_dmg_m*pyrod.dmg,
character = pyrod.character, level = pyrod.level, parent = pyrod.parent}
end)
end
if projectile and projectile.spawn_critters_on_kill then
trigger:after(0.01, function()
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
for i = 1, projectile.spawn_critters_on_kill do
Critter{group = main.current.main, x = self.x, y = self.y, color = orange[0], r = random:float(0, 2*math.pi), v = 5, dmg = projectile.parent.dmg}
end
end)
end
end end
end end

182
main.lua
View File

@ -19,6 +19,9 @@ function init()
music.volume = 0 music.volume = 0
local s = {tags = {sfx}} local s = {tags = {sfx}}
frost1 = Sound('Frost Bolt 20.ogg', s)
pyro1 = Sound('Fire bolt 5.ogg', s)
pyro2 = Sound('Explosion Fireworks_01.ogg', s)
dot1 = Sound('Magical Swoosh 18.ogg', s) dot1 = Sound('Magical Swoosh 18.ogg', s)
gun_kata1 = Sound('Pistol Shot_07.ogg', s) gun_kata1 = Sound('Pistol Shot_07.ogg', s)
gun_kata2 = Sound('Pistol Shot_08.ogg', s) gun_kata2 = Sound('Pistol Shot_08.ogg', s)
@ -104,7 +107,7 @@ function init()
conjurer = Image('conjurer') conjurer = Image('conjurer')
enchanter = Image('enchanter') enchanter = Image('enchanter')
psyker = Image('psyker') psyker = Image('psyker')
trapper = Image('trapper') curser = Image('curser')
forcer = Image('forcer') forcer = Image('forcer')
swarmer = Image('swarmer') swarmer = Image('swarmer')
voider = Image('voider') voider = Image('voider')
@ -119,9 +122,9 @@ function init()
['rogue'] = red[0], ['rogue'] = red[0],
['enchanter'] = blue[0], ['enchanter'] = blue[0],
['psyker'] = fg[0], ['psyker'] = fg[0],
['trapper'] = orange[0], ['curser'] = purple[0],
['forcer'] = yellow[0], ['forcer'] = yellow[0],
['swarmer'] = purple[0], ['swarmer'] = orange[0],
['voider'] = purple[0], ['voider'] = purple[0],
} }
@ -135,9 +138,9 @@ function init()
['rogue'] = 'red', ['rogue'] = 'red',
['enchanter'] = 'blue', ['enchanter'] = 'blue',
['psyker'] = 'fg', ['psyker'] = 'fg',
['trapper'] = 'orange', ['curser'] = 'purple',
['forcer'] = 'yellow', ['forcer'] = 'yellow',
['swarmer'] = 'purple', ['swarmer'] = 'orange',
['voider'] = 'purple', ['voider'] = 'purple',
} }
@ -163,25 +166,25 @@ function init()
['psykeeper'] = fg[0], ['psykeeper'] = fg[0],
['engineer'] = orange[0], ['engineer'] = orange[0],
['plague_doctor'] = purple[0], ['plague_doctor'] = purple[0],
['fisherman'] = yellow[0], ['barbarian'] = yellow[0],
['juggernaut'] = yellow[0], ['juggernaut'] = yellow[0],
['lich'] = blue[0], ['lich'] = blue[0],
['cryomancer'] = blue[0], ['cryomancer'] = blue[0],
['pyromancer'] = red[0], ['pyromancer'] = red[0],
['corruptor'] = purple[0], ['corruptor'] = orange[0],
['beastmaster'] = red[0], ['beastmaster'] = red[0],
['launcher'] = orange[0], ['launcher'] = orange[0],
['spiker'] = orange[0], ['bard'] = red[0],
['assassin'] = purple[0], ['assassin'] = purple[0],
['host'] = purple[0], ['host'] = orange[0],
['carver'] = green[0], ['carver'] = green[0],
['bane'] = purple[0], ['bane'] = purple[0],
['psykino'] = fg[0], ['psykino'] = fg[0],
['arbalester'] = green[0], ['arbalester'] = green[0],
['barbarian'] = yellow[0], ['highlander'] = yellow[0],
['sapper'] = blue[0], ['sapper'] = blue[0],
['priest'] = green[0], ['priest'] = green[0],
['burrower'] = orange[0], ['infestor'] = orange[0],
['flagellant'] = fg[0], ['flagellant'] = fg[0],
} }
@ -207,25 +210,25 @@ function init()
['psykeeper'] = 'fg', ['psykeeper'] = 'fg',
['engineer'] = 'orange', ['engineer'] = 'orange',
['plague_doctor'] = 'purple', ['plague_doctor'] = 'purple',
['fisherman'] = 'yellow', ['barbarian'] = 'yellow',
['juggernaut'] = 'yellow', ['juggernaut'] = 'yellow',
['lich'] = 'blue', ['lich'] = 'blue',
['cryomancer'] = 'blue', ['cryomancer'] = 'blue',
['pyromancer'] = 'red', ['pyromancer'] = 'red',
['corruptor'] = 'purple', ['corruptor'] = 'orange',
['beastmaster'] = 'red', ['beastmaster'] = 'red',
['launcher'] = 'orange', ['launcher'] = 'orange',
['spiker'] = 'orange', ['bard'] = 'red',
['assassin'] = 'purple', ['assassin'] = 'purple',
['host'] = 'purple', ['host'] = 'orange',
['carver'] = 'green', ['carver'] = 'green',
['bane'] = 'purple', ['bane'] = 'purple',
['psykino'] = 'fg', ['psykino'] = 'fg',
['arbalester'] = 'green', ['arbalester'] = 'green',
['barbarian'] = 'yellow', ['highlander'] = 'yellow',
['sapper'] = 'blue', ['sapper'] = 'blue',
['priest'] = 'green', ['priest'] = 'green',
['burrower'] = 'orange', ['infestor'] = 'orange',
['flagellant'] = 'fg', ['flagellant'] = 'fg',
} }
@ -251,25 +254,25 @@ function init()
['psykeeper'] = {'healer', 'psyker'}, ['psykeeper'] = {'healer', 'psyker'},
['engineer'] = {'conjurer'}, ['engineer'] = {'conjurer'},
['plague_doctor'] = {'nuker', 'voider'}, ['plague_doctor'] = {'nuker', 'voider'},
['fisherman'] = {'trapper', 'warrior'}, ['barbarian'] = {'curser', 'warrior'},
['juggernaut'] = {'forcer', 'warrior'}, ['juggernaut'] = {'forcer', 'warrior'},
['lich'] = {'mage'}, ['lich'] = {'mage'},
['cryomancer'] = {'mage', 'voider'}, ['cryomancer'] = {'mage', 'voider'},
['pyromancer'] = {'mage', 'nuker', 'voider'}, ['pyromancer'] = {'mage', 'nuker', 'voider'},
['corruptor'] = {'ranger', 'swarmer'}, ['corruptor'] = {'ranger', 'swarmer'},
['beastmaster'] = {'rogue', 'swarmer'}, ['beastmaster'] = {'rogue', 'swarmer'},
['launcher'] = {'trapper', 'forcer'}, ['launcher'] = {'curser', 'forcer'},
['spiker'] = {'trapper', 'rogue'}, ['bard'] = {'curser', 'rogue'},
['assassin'] = {'rogue', 'voider'}, ['assassin'] = {'rogue', 'voider'},
['host'] = {'conjurer', 'swarmer'}, ['host'] = {'conjurer', 'swarmer'},
['carver'] = {'conjurer', 'healer'}, ['carver'] = {'conjurer', 'curser', 'healer'},
['bane'] = {'swarmer', 'voider'}, ['bane'] = {'curser', 'voider'},
['psykino'] = {'mage', 'psyker', 'forcer'}, ['psykino'] = {'mage', 'psyker', 'forcer'},
['arbalester'] = {'ranger', 'forcer'}, ['arbalester'] = {'ranger', 'forcer'},
['barbarian'] = {'warrior'}, ['highlander'] = {'warrior'},
['sapper'] = {'trapper', 'enchanter', 'healer'}, ['sapper'] = {'enchanter', 'voider', 'healer'},
['priest'] = {'healer'}, ['priest'] = {'healer'},
['burrower'] = {'trapper', 'swarmer'}, ['infestor'] = {'curser', 'swarmer'},
['flagellant'] = {'psyker', 'enchanter'}, ['flagellant'] = {'psyker', 'enchanter'},
} }
@ -295,25 +298,25 @@ function init()
['psykeeper'] = '[green]Healer, [fg]Psyker', ['psykeeper'] = '[green]Healer, [fg]Psyker',
['engineer'] = '[orange]Conjurer', ['engineer'] = '[orange]Conjurer',
['plague_doctor'] = '[red]Nuker, [purple]Voider', ['plague_doctor'] = '[red]Nuker, [purple]Voider',
['fisherman'] = '[orange]Trapper, [yellow]Warrior', ['barbarian'] = '[purple]Curser, [yellow]Warrior',
['juggernaut'] = '[yellow]Forcer, Warrior', ['juggernaut'] = '[yellow]Forcer, Warrior',
['lich'] = '[blue]Mage', ['lich'] = '[blue]Mage',
['cryomancer'] = '[blue]Mage, [purple]Voider', ['cryomancer'] = '[blue]Mage, [purple]Voider',
['pyromancer'] = '[blue]Mage, [red]Nuker, [purple]Voider', ['pyromancer'] = '[blue]Mage, [red]Nuker, [purple]Voider',
['corruptor'] = '[green]Ranger, [purple]Swarmer', ['corruptor'] = '[green]Ranger, [orange]Swarmer',
['beastmaster'] = '[red]Rogue, [purple]Swarmer', ['beastmaster'] = '[red]Rogue, [orange]Swarmer',
['launcher'] = '[orange]Trapper, [yellow]Forcer', ['launcher'] = '[purple]Curser, [yellow]Forcer',
['spiker'] = '[orange]Trapper, [red]Rogue', ['bard'] = '[purple]Curser, [red]Rogue',
['assassin'] = '[red]Rogue, [purple]Voider', ['assassin'] = '[red]Rogue, [purple]Voider',
['host'] = '[orange]Conjurer, [purple]Swarmer', ['host'] = '[orange]Conjurer, [orange]Swarmer',
['carver'] = '[orange]Conjurer, [green]Healer', ['carver'] = '[orange]Conjurer, [purple]Curser, [green]Healer',
['bane'] = '[purple]Swarmer, Voider', ['bane'] = '[purple]Curser, Voider',
['psykino'] = '[blue]Mage, [fg]Psyker, [yellow]Forcer', ['psykino'] = '[blue]Mage, [fg]Psyker, [yellow]Forcer',
['arbalester'] = '[green]Ranger, [yellow]Forcer', ['arbalester'] = '[green]Ranger, [yellow]Forcer',
['barbarian'] = '[yellow]Warrior', ['highlander'] = '[yellow]Warrior',
['sapper'] = '[orange]Trapper, [blue]Enchanter, [green]Healer', ['sapper'] = '[blue]Enchanter, [purple]Voider, [green]Healer',
['priest'] = '[green]Healer', ['priest'] = '[green]Healer',
['burrower'] = '[orange]Trapper, [purple]Swarmer', ['infestor'] = '[purple]Curser, [orange]Swarmer',
['flagellant'] = '[fg]Psyker, [blue]Enchanter', ['flagellant'] = '[fg]Psyker, [blue]Enchanter',
} }
@ -355,27 +358,26 @@ function init()
['psykeeper'] = function(lvl) return '[fg]all damage taken is stored up to [yellow]50%[fg] max HP and distributed as healing to all allies' end, ['psykeeper'] = function(lvl) return '[fg]all damage taken is stored up to [yellow]50%[fg] max HP and distributed as healing to all allies' end,
['engineer'] = function(lvl) return '[fg]drops sentries that shoot bursts of projectiles, each dealing [yellow]' .. get_character_stat('engineer', lvl, 'dmg') .. '[fg] damage' end, ['engineer'] = function(lvl) return '[fg]drops sentries that shoot bursts of projectiles, each dealing [yellow]' .. get_character_stat('engineer', lvl, 'dmg') .. '[fg] damage' end,
['plague_doctor'] = function(lvl) return '[fg]creates an area that deals [yellow]' .. get_character_stat('plague_doctor', lvl, 'dmg') .. '[fg] damage per second' end, ['plague_doctor'] = function(lvl) return '[fg]creates an area that deals [yellow]' .. get_character_stat('plague_doctor', lvl, 'dmg') .. '[fg] damage per second' end,
['fisherman'] = function(lvl) return '[fg]throws a net that entangles enemies and prevents them from moving for [yellow]4[fg] seconds' end, ['barbarian'] = function(lvl) return '[fg]deals [yellow]' .. get_character_stat('barbarian', lvl, 'dmg') .. '[fg] AoE damage and stuns enemies hit for [yellow]4[fg] seconds' end,
['juggernaut'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. get_character_stat('juggernaut', lvl, 'dmg') .. '[fg] damage and pushes enemies away with a strong force' end, ['juggernaut'] = function(lvl) return '[fg]deals [yellow]' .. get_character_stat('juggernaut', lvl, 'dmg') .. '[fg] AoE damage and pushes enemies away with a strong force' end,
['lich'] = function(lvl) return '[fg]launches a chain frost that jumps [yellow]7[fg] times, dealing [yellow]' .. ['lich'] = function(lvl) return '[fg]launches a slow projectile that jumps [yellow]7[fg] times, dealing [yellow]' .. 2*get_character_stat('lich', lvl, 'dmg') .. '[fg] damage per hit' end,
get_character_stat('lich', lvl, 'dmg') .. '[fg] damage and slowing enemies by [yellow]50%[fg] for [yellow]2[fg] seconds on hit' end, ['cryomancer'] = function(lvl) return '[fg]nearby enemies take [yellow]' .. get_character_stat('cryomancer', lvl, 'dmg') .. '[fg] damage per second' end,
['cryomancer'] = function(lvl) return '[fg]nearby enemies take [yellow]' .. get_character_stat('cryomancer', lvl, 'dmg') .. '[fg] damage per second and have [yellow]25%[fg] decreased movement speed' end, ['pyromancer'] = function(lvl) return '[fg]nearby enemies take [yellow]' .. get_character_stat('pyromancer', lvl, 'dmg') .. '[fg] damage per second' end,
['pyromancer'] = function(lvl) return '[fg]nearby enemies take [yellow]' .. get_character_stat('pyromancer', lvl, 'dmg') .. '[fg] damage per second and deal [yellow]25%[fg] decreased damage' end,
['corruptor'] = function(lvl) return '[fg]spawn [yellow]3[fg] small critters if the corruptor kills an enemy' end, ['corruptor'] = function(lvl) return '[fg]spawn [yellow]3[fg] small critters if the corruptor kills an enemy' end,
['beastmaster'] = function(lvl) return '[fg]spawn [yellow]2[fg] small critters if the beastmaster crits' end, ['beastmaster'] = function(lvl) return '[fg]spawn [yellow]2[fg] small critters if the beastmaster crits' end,
['launcher'] = function(lvl) return '[fg]creates a trap that launches enemies that trigger it' end, ['launcher'] = function(lvl) return '[fg]nearby enemies are afflicted with a kinetic curse that triggers after [yellow]4[fg] seconds' end,
['spiker'] = function(lvl) return '[fg]creates a trap that crits when triggered, dealing [yellow]' .. 4*get_character_stat('spiker', lvl, 'dmg') .. '[fg] damage' end, ['bard'] = function(lvl) return "[fg]shoots a projectile that inflicts enemies hit with the bard's curse" end,
['assassin'] = function(lvl) return '[fg]throws a piercing knife that deals [yellow]' .. get_character_stat('assassin', lvl, 'dmg') .. '[fg] damage and inflicts poison that deals [yellow]' .. ['assassin'] = function(lvl) return '[fg]throws a piercing knife that deals [yellow]' .. get_character_stat('assassin', lvl, 'dmg') .. '[fg] damage and inflicts poison that deals [yellow]' ..
get_character_stat('assassin', lvl, 'dmg')/2 .. '[fg] damage per second for [yellow]4[fg] seconds' end, get_character_stat('assassin', lvl, 'dmg')/2 .. '[fg] damage per second for [yellow]4[fg] seconds' end,
['host'] = function(lvl) return '[fg]creates [yellow]2[fg] overlords that periodically spawn small critters' end, ['host'] = function(lvl) return '[fg]creates [yellow]2[fg] overlords that periodically spawn small critters' end,
['carver'] = function(lvl) return '[fg]carves a statue that periodically heals for [yellow]20%[fg] max HP in an area around it' end, ['carver'] = function(lvl) return '[fg]carves a statue that periodically heals for [yellow]20%[fg] max HP in an area around it' end,
['bane'] = function(lvl) return '[fg]spawn a small critter that explodes and deals [yellow]' .. get_character_stat('bane', lvl, 'dmg') .. '[fg] damage per second in an area' end, ['bane'] = function(lvl) return '[fg]creates a large area that curses enemies to take [yellow]50%[fg] increased damage over time' end,
['psykino'] = function(lvl) return '[fg]quickly pulls enemies together and then release them with a force' end, ['psykino'] = function(lvl) return '[fg]quickly pulls enemies together and then release them with a force' end,
['arbalester'] = function(lvl) return '[fg]launches a massive arrow that deals [yellow]' .. get_character_stat('arbalester', lvl, 'dmg') .. '[fg] damage and pushes enemies back, ignoring knockback resistances' end, ['arbalester'] = function(lvl) return '[fg]launches a massive arrow that deals [yellow]' .. get_character_stat('arbalester', lvl, 'dmg') .. '[fg] damage and pushes enemies back, ignoring knockback resistances' end,
['barbarian'] = function(lvl) return '[fg]creates a small area that deals [yellow]' .. 4*get_character_stat('barbarian', lvl, 'dmg') .. '[fg] damage and stuns for [yellow]2[fg] seconds' end, ['highlander'] = function(lvl) return '[fg]deals [yellow]' .. 6*get_character_stat('highlander', lvl, 'dmg') .. '[fg] AoE damage' end,
['sapper'] = function(lvl) return '[fg]creates a trap that steals [yellow]10%[fg] enemy HP and grants you [yellow]+25%[fg] movement speed' end, ['sapper'] = function(lvl) return '[fg]periodically steals [yellow]5%[fg] max HP per second from nearby enemies and gain 25% increased movement speed' end,
['priest'] = function(lvl) return '[fg]heals all allies for [yellow]20%[fg] their max HP' end, ['priest'] = function(lvl) return '[fg]heals all allies for [yellow]20%[fg] their max HP' end,
['burrower'] = function(lvl) return '[fg]creates a trap that contains [yellow]6[fg] small critters' end, ['infestor'] = function(lvl) return '[fg]curses enemies in an area for [yellow]6[fg] seconds, they will release multiple critters on death' end,
['flagellant'] = function(lvl) return '[fg]deals damage to self and grants [yellow]+4%[fg] damage to all allies per cast' end, ['flagellant'] = function(lvl) return '[fg]deals damage to self and grants [yellow]+4%[fg] damage to all allies per cast' end,
} }
@ -401,25 +403,25 @@ function init()
['psykeeper'] = '[fg]Crucio', ['psykeeper'] = '[fg]Crucio',
['engineer'] = '[orange]Upgrade', ['engineer'] = '[orange]Upgrade',
['plague_doctor'] = '[purple]Black Death Steam', ['plague_doctor'] = '[purple]Black Death Steam',
['fisherman'] = '[yellow]Electric Net', ['barbarian'] = '[yellow]Seism',
['juggernaut'] = '[yellow]Brutal Impact', ['juggernaut'] = '[yellow]Brutal Impact',
['lich'] = '[blue]Piercing Frost', ['lich'] = '[blue]Chain Frost',
['cryomancer'] = '[blue]Frostbite', ['cryomancer'] = '[blue]Frostbite',
['pyromancer'] = '[red]Ignite', ['pyromancer'] = '[red]Ignite',
['corruptor'] = '[purple]Infestation', ['corruptor'] = '[orange]Corruption',
['beastmaster'] = '[red]Call of the Wild', ['beastmaster'] = '[red]Call of the Wild',
['launcher'] = '[orange]Kineticism', ['launcher'] = '[orange]Kineticism',
['spiker'] = '[orange]Caltrops', ['bard'] = "[orange]The Bard's Song",
['assassin'] = '[purple]Toxic Delivery', ['assassin'] = '[purple]Toxic Delivery',
['host'] = '[purple]Invasion', ['host'] = '[orange]Invasion',
['carver'] = '[green]World Tree', ['carver'] = '[green]World Tree',
['bane'] = '[purple]Baneling Swarm', ['bane'] = '[purple]Nightmare',
['psykino'] = '[fg]Magnetic Force', ['psykino'] = '[fg]Magnetic Force',
['arbalester'] = '[green]Ballista Sinitra', ['arbalester'] = '[green]Ballista Sinitra',
['barbarian'] = '[yellow]Berserk', ['highlander'] = '[yellow]Crosscut',
['sapper'] = '[blue]Chain Reaction', ['sapper'] = '[blue]Enduring Sap',
['priest'] = '[green]Divine Intervention', ['priest'] = '[green]Divine Intervention',
['burrower'] = '[orange]Zergling Rush', ['infestor'] = '[orange]Infestation',
['flagellant'] = '[red]Zealotry', ['flagellant'] = '[red]Zealotry',
} }
@ -450,7 +452,7 @@ function init()
['lich'] = '[light_bg]Piercing Frost', ['lich'] = '[light_bg]Piercing Frost',
['cryomancer'] = '[light_bg]Frostbite', ['cryomancer'] = '[light_bg]Frostbite',
['pyromancer'] = '[light_bg]Ignite', ['pyromancer'] = '[light_bg]Ignite',
['corruptor'] = '[light_bg]Infestation', ['corruptor'] = '[light_bg]Corruption',
['beastmaster'] = '[light_bg]Call of the Wild', ['beastmaster'] = '[light_bg]Call of the Wild',
['launcher'] = '[light_bg]Kineticism', ['launcher'] = '[light_bg]Kineticism',
['spiker'] = '[light_bg]Caltrops', ['spiker'] = '[light_bg]Caltrops',
@ -463,7 +465,7 @@ function init()
['barbarian'] = '[light_bg]Berserk', ['barbarian'] = '[light_bg]Berserk',
['sapper'] = '[light_bg]Chain Reaction', ['sapper'] = '[light_bg]Chain Reaction',
['priest'] = '[light_bg]Divine Intervention', ['priest'] = '[light_bg]Divine Intervention',
['burrower'] = '[light_bg]Zergling Rush', ['infestor'] = '[light_bg]Infestation',
['flagellant'] = '[light_bg]Zealotry', ['flagellant'] = '[light_bg]Zealotry',
} }
@ -489,26 +491,26 @@ function init()
['psykeeper'] = function() return '[fg]also redistributes damage taken as damage to all enemies at [yellow]double[fg] value' end, ['psykeeper'] = function() return '[fg]also redistributes damage taken as damage to all enemies at [yellow]double[fg] value' end,
['engineer'] = function() return '[fg]every 3rd sentry dropped upgrade all sentries with [yellow]+100%[fg] damage and attack speed' end, ['engineer'] = function() return '[fg]every 3rd sentry dropped upgrade all sentries with [yellow]+100%[fg] damage and attack speed' end,
['plague_doctor'] = function() return '[fg]nearby enemies take an additional [yellow]' .. get_character_stat('plague_doctor', 3, 'dmg') .. '[fg] damage per second' end, ['plague_doctor'] = function() return '[fg]nearby enemies take an additional [yellow]' .. get_character_stat('plague_doctor', 3, 'dmg') .. '[fg] damage per second' end,
['fisherman'] = function() return '[fg]enemies caught take [yellow]' .. get_character_stat('fisherman', 3, 'dmg')/4 .. '[fg] damage per second' end, ['barbarian'] = function() return '[fg]stunned enemies also take [yellow]100%[fg] increased damage' end,
['juggernaut'] = function() return '[fg]enemies pushed away by the juggernaut are instantly killed if they hit a wall' end, ['juggernaut'] = function() return '[fg]enemies pushed by the juggernaut take [yellow]' .. 4*get_character_stat('juggernaut', 3, 'dmg') .. '[fg] damage if they hit a wall' end,
['lich'] = function() return '[fg]chain frost decreases enemy defenses by [yellow]30[fg] for [yellow]4[fg] seconds' end, ['lich'] = function() return '[fg]chain frost slows enemies hit by [yellow]80%[fg] for [yellow]2[fg] seconds and chains [yellow]+7[fg] times' end,
['cryomancer'] = function() return '[fg]enemies killed by the cryomancer freeze nearby enemies, frozen enemies take increased damage and do not move' end, ['cryomancer'] = function() return '[fg]enemies are also slowed by [yellow]60%[fg] while in the area' end,
['pyromancer'] = function() return '[fg]enemies killed by the pyromancer explode, dealing [yellow]' .. get_character_stat('pyromancer', 3, 'dmg') .. '[fg] AoE damage' end, ['pyromancer'] = function() return '[fg]enemies killed by the pyromancer explode, dealing [yellow]' .. get_character_stat('pyromancer', 3, 'dmg') .. '[fg] AoE damage' end,
['corruptor'] = function() return '[fg]spawn [yellow]3[fg] small critters if the corruptor hits an enemy' end, ['corruptor'] = function() return '[fg]spawn [yellow]3[fg] small critters if the corruptor hits an enemy' end,
['beastmaster'] = function() return '[fg]spawn [yellow]2[fg] small critters if the beastmaster gets hit' end, ['beastmaster'] = function() return '[fg]spawn [yellow]2[fg] small critters if the beastmaster gets hit' end,
['launcher'] = function() return '[fg]enemies launched that hit other enemies push those enemies at double the force they were pushed' end, ['launcher'] = function() return '[fg]enemies launched that hit other enemies push those enemies at double the force they were pushed' end,
['spiker'] = function() return '[fg]slows enemies hit by [yellow]50%[fg] for [yellow]2[fg] seconds and deals [yellow]' .. get_character_stat('spiker', 3, 'dmg') .. '[fg] damage per second' end, ['bard'] = function() return '[fg] every 5th attack consume the curse to deal [yellow]' .. 3*get_character_stat('bard', 3, 'dmg') .. '[fg] damage to affected enemies' end,
['assassin'] = function() return '[fg]poison inflicted from crits deals [yellow]8x[fg] damage' end, ['assassin'] = function() return '[fg]poison inflicted from crits deals [yellow]8x[fg] damage' end,
['host'] = function() return '[fg][yellow]+50%[fg] critter spawn rate' end, ['host'] = function() return '[fg][yellow]+50%[fg] critter spawn rate' end,
['carver'] = function() return '[fg]carves a tree that heals in a bigger area and removes all buffs from enemies' end, ['carver'] = function() return '[fg]carves a tree that heals in a bigger area and removes all buffs from enemies' end,
['bane'] = function() return '[fg]spawn [yellow]4[fg] banelings' end, ['bane'] = function() return '[fg]the area also deals [yellow]' .. get_character_stat('bane', 3, 'dmg') .. '[fg] damage per second and slows enemies by [yellow]50%[fg]' end,
['psykino'] = function() return '[fg]enemies pulled together are forced to collide with each other multiple times' end, ['psykino'] = function() return '[fg]enemies pulled together are forced to collide with each other multiple times' end,
['arbalester'] = function() return '[fg]enemies hit by the arrow have defense decreased by [yellow]100[fg] for [yellow]4[fg] seconds' end, ['arbalester'] = function() return '[fg]enemies hit by the arrow have defense decreased by [yellow]100[fg] for [yellow]4[fg] seconds' end,
['barbarian'] = function() return '[fg][yellow]+50%[fg] attack speed' end, ['crosscut'] = function() return '[fg]two crosscutting areas of +100% size are created instead' end,
['sapper'] = function() return '[fg]when a sapper trap is triggered other nearby traps are also triggered' end, ['sapper'] = function() return '[fg]sapped enemies permanently take [yellow]' .. get_character_stat('sapper', 3, 'dmg') .. '[fg] damage per second' end,
['priest'] = function() return '[fg]at the start of the round pick [yellow]3[fg] units at random and grants them a buff that prevents death once' end, ['priest'] = function() return '[fg]at the start of the round pick [yellow]3[fg] units at random and grants them a buff that prevents death once' end,
['burrower'] = function() return '[fg][yellow]triples[fg] the number of critters released' end, ['infestor'] = function() return '[fg][yellow]triples[fg] the number of critters released' end,
['flagellant'] = function() return '[fg]deals damage to all allies instead and grants [yellow]+10%[fg] damage to all allies per cast' end, ['flagellant'] = function() return '[fg]deals damage to all allies instead and grants stacking [yellow]+10%[fg] damage to all allies per cast' end,
} }
character_stats = { character_stats = {
@ -533,7 +535,7 @@ function init()
['psykeeper'] = function(lvl) return get_character_stat_string('psykeeper', lvl) end, ['psykeeper'] = function(lvl) return get_character_stat_string('psykeeper', lvl) end,
['engineer'] = function(lvl) return get_character_stat_string('engineer', lvl) end, ['engineer'] = function(lvl) return get_character_stat_string('engineer', lvl) end,
['plague_doctor'] = function(lvl) return get_character_stat_string('plague_doctor', lvl) end, ['plague_doctor'] = function(lvl) return get_character_stat_string('plague_doctor', lvl) end,
['fisherman'] = function(lvl) return get_character_stat_string('fisherman', lvl) end, ['barbarian'] = function(lvl) return get_character_stat_string('barbarian', lvl) end,
['juggernaut'] = function(lvl) return get_character_stat_string('juggernaut', lvl) end, ['juggernaut'] = function(lvl) return get_character_stat_string('juggernaut', lvl) end,
['lich'] = function(lvl) return get_character_stat_string('lich', lvl) end, ['lich'] = function(lvl) return get_character_stat_string('lich', lvl) end,
['cryomancer'] = function(lvl) return get_character_stat_string('cryomancer', lvl) end, ['cryomancer'] = function(lvl) return get_character_stat_string('cryomancer', lvl) end,
@ -541,17 +543,17 @@ function init()
['corruptor'] = function(lvl) return get_character_stat_string('corruptor', lvl) end, ['corruptor'] = function(lvl) return get_character_stat_string('corruptor', lvl) end,
['beastmaster'] = function(lvl) return get_character_stat_string('beastmaster', lvl) end, ['beastmaster'] = function(lvl) return get_character_stat_string('beastmaster', lvl) end,
['launcher'] = function(lvl) return get_character_stat_string('launcher', lvl) end, ['launcher'] = function(lvl) return get_character_stat_string('launcher', lvl) end,
['spiker'] = function(lvl) return get_character_stat_string('spiker', lvl) end, ['bard'] = function(lvl) return get_character_stat_string('bard', lvl) end,
['assassin'] = function(lvl) return get_character_stat_string('assassin', lvl) end, ['assassin'] = function(lvl) return get_character_stat_string('assassin', lvl) end,
['host'] = function(lvl) return get_character_stat_string('host', lvl) end, ['host'] = function(lvl) return get_character_stat_string('host', lvl) end,
['carver'] = function(lvl) return get_character_stat_string('carver', lvl) end, ['carver'] = function(lvl) return get_character_stat_string('carver', lvl) end,
['bane'] = function(lvl) return get_character_stat_string('bane', lvl) end, ['bane'] = function(lvl) return get_character_stat_string('bane', lvl) end,
['psykino'] = function(lvl) return get_character_stat_string('psykino', lvl) end, ['psykino'] = function(lvl) return get_character_stat_string('psykino', lvl) end,
['arbalester'] = function(lvl) return get_character_stat_string('arbalester', lvl) end, ['arbalester'] = function(lvl) return get_character_stat_string('arbalester', lvl) end,
['barbarian'] = function(lvl) return get_character_stat_string('barbarian', lvl) end, ['highlander'] = function(lvl) return get_character_stat_string('highlander', lvl) end,
['sapper'] = function(lvl) return get_character_stat_string('sapper', lvl) end, ['sapper'] = function(lvl) return get_character_stat_string('sapper', lvl) end,
['priest'] = function(lvl) return get_character_stat_string('priest', lvl) end, ['priest'] = function(lvl) return get_character_stat_string('priest', lvl) end,
['burrower'] = function(lvl) return get_character_stat_string('burrower', lvl) end, ['infestor'] = function(lvl) return get_character_stat_string('infestor', lvl) end,
['flagellant'] = function(lvl) return get_character_stat_string('flagellant', lvl) end, ['flagellant'] = function(lvl) return get_character_stat_string('flagellant', lvl) end,
} }
@ -565,7 +567,7 @@ function init()
['nuker'] = {hp = 0.9, dmg = 1, aspd = 0.75, area_dmg = 1.5, area_size = 1.5, def = 1, mvspd = 1}, ['nuker'] = {hp = 0.9, dmg = 1, aspd = 0.75, area_dmg = 1.5, area_size = 1.5, def = 1, mvspd = 1},
['conjurer'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 1}, ['conjurer'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 1},
['psyker'] = {hp = 1.5, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 0.5, mvspd = 1}, ['psyker'] = {hp = 1.5, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 0.5, mvspd = 1},
['trapper'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 0.75, mvspd = 1}, ['curser'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 0.75, mvspd = 1},
['forcer'] = {hp = 1.25, dmg = 1.1, aspd = 0.9, area_dmg = 0.75, area_size = 0.75, def = 1.2, mvspd = 1}, ['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}, ['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}, ['voider'] = {hp = 0.75, dmg = 1.3, aspd = 1, area_dmg = 0.8, area_size = 0.75, def = 0.6, mvspd = 0.8},
@ -587,7 +589,7 @@ function init()
['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, ['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, ['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) .. ']+5%[' .. ylb2(lvl) .. ']/+10% [fg]damage and health per active set to allied psykers' end, ['psyker'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+5%[' .. ylb2(lvl) .. ']/+10% [fg]damage and health per active set to allied psykers' end,
['trapper'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+1[' .. ylb2(lvl) .. ']/+2 [fg]extra traps released' end, ['curser'] = function(lvl) return '[' .. ylb1(lvl) .. ']2[' .. ylb2(lvl) .. ']/4 [fg]- [' .. ylb1(lvl) .. ']+25%[' .. ylb2(lvl) .. ']/+50% [fg]curse effectiveness and 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, ['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, ['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, ['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,
@ -595,9 +597,9 @@ function init()
tier_to_characters = { tier_to_characters = {
[1] = {'vagrant', 'swordsman', 'wizard', 'archer', 'scout', 'cleric'}, [1] = {'vagrant', 'swordsman', 'wizard', 'archer', 'scout', 'cleric'},
[2] = {'saboteur', 'sage', 'squire', 'dual_gunner', 'hunter', 'chronomancer', 'fisherman', 'cryomancer', 'beastmaster', 'launcher', 'spiker', 'carver'}, [2] = {'saboteur', 'sage', 'squire', 'dual_gunner', 'hunter', 'chronomancer', 'barbarian', 'cryomancer', 'beastmaster', 'launcher', 'bard', 'carver'},
[3] = {'outlaw', 'elementor', 'stormweaver', 'spellblade', 'psykeeper', 'engineer', 'juggernaut', 'pyromancer', 'corruptor', 'assassin', 'bane', 'arbalester', 'burrower', 'flagellant'}, [3] = {'outlaw', 'elementor', 'stormweaver', 'spellblade', 'psykeeper', 'engineer', 'juggernaut', 'pyromancer', 'corruptor', 'assassin', 'bane', 'arbalester', 'infestor', 'flagellant'},
[4] = {'priest', 'barbarian', 'psykino', 'lich', 'host', 'sapper', 'blade', 'plague_doctor', 'cannoneer'}, [4] = {'priest', 'highlander', 'psykino', 'lich', 'host', 'sapper', 'blade', 'plague_doctor', 'cannoneer'},
} }
non_attacking_characters = {'cleric', 'stormweaver', 'squire', 'chronomancer', 'sage'} non_attacking_characters = {'cleric', 'stormweaver', 'squire', 'chronomancer', 'sage'}
@ -624,7 +626,7 @@ function init()
['psykeeper'] = 3, ['psykeeper'] = 3,
['engineer'] = 3, ['engineer'] = 3,
['plague_doctor'] = 4, ['plague_doctor'] = 4,
['fisherman'] = 2, ['barbarian'] = 2,
['juggernaut'] = 3, ['juggernaut'] = 3,
['lich'] = 4, ['lich'] = 4,
['cryomancer'] = 2, ['cryomancer'] = 2,
@ -632,17 +634,17 @@ function init()
['corruptor'] = 3, ['corruptor'] = 3,
['beastmaster'] = 2, ['beastmaster'] = 2,
['launcher'] = 2, ['launcher'] = 2,
['spiker'] = 2, ['bard'] = 2,
['assassin'] = 3, ['assassin'] = 3,
['host'] = 4, ['host'] = 4,
['carver'] = 2, ['carver'] = 2,
['bane'] = 3, ['bane'] = 3,
['psykino'] = 4, ['psykino'] = 4,
['arbalester'] = 3, ['arbalester'] = 3,
['barbarian'] = 4, ['highlander'] = 4,
['sapper'] = 4, ['sapper'] = 4,
['priest'] = 4, ['priest'] = 4,
['burrower'] = 3, ['infestor'] = 3,
['flagellant'] = 3, ['flagellant'] = 3,
} }
@ -656,7 +658,7 @@ function init()
local rogues = 0 local rogues = 0
local enchanters = 0 local enchanters = 0
local psykers = 0 local psykers = 0
local trappers = 0 local cursers = 0
local forcers = 0 local forcers = 0
local swarmers = 0 local swarmers = 0
local voiders = 0 local voiders = 0
@ -671,14 +673,14 @@ function init()
if unit_class == 'rogue' then rogues = rogues + 1 end if unit_class == 'rogue' then rogues = rogues + 1 end
if unit_class == 'enchanter' then enchanters = enchanters + 1 end if unit_class == 'enchanter' then enchanters = enchanters + 1 end
if unit_class == 'psyker' then psykers = psykers + 1 end if unit_class == 'psyker' then psykers = psykers + 1 end
if unit_class == 'trapper' then trappers = trappers + 1 end if unit_class == 'curser' then cursers = cursers + 1 end
if unit_class == 'forcer' then forcers = forcers + 1 end if unit_class == 'forcer' then forcers = forcers + 1 end
if unit_class == 'swarmer' then swarmers = swarmers + 1 end if unit_class == 'swarmer' then swarmers = swarmers + 1 end
if unit_class == 'voider' then voiders = voiders + 1 end if unit_class == 'voider' then voiders = voiders + 1 end
end end
end end
return {ranger = rangers, warrior = warriors, healer = healers, mage = mages, nuker = nukers, conjurer = conjurers, rogue = rogues, return {ranger = rangers, warrior = warriors, healer = healers, mage = mages, nuker = nukers, conjurer = conjurers, rogue = rogues,
enchanter = enchanters, psyker = psykers, trapper = trappers, forcer = forcers, swarmer = swarmers, voider = voiders} enchanter = enchanters, psyker = psykers, curser = cursers, forcer = forcers, swarmer = swarmers, voider = voiders}
end end
get_class_levels = function(units) get_class_levels = function(units)
@ -688,7 +690,7 @@ function init()
if number_of_units >= 6 then return 2 if number_of_units >= 6 then return 2
elseif number_of_units >= 3 then return 1 elseif number_of_units >= 3 then return 1
else return 0 end else return 0 end
elseif class == 'healer' or class == 'conjurer' or class == 'enchanter' or class == 'psyker' or class == 'trapper' or class == 'forcer' or class == 'swarmer' or class == 'voider' then elseif class == 'healer' or class == 'conjurer' or class == 'enchanter' or class == 'psyker' or class == 'curser' or class == 'forcer' or class == 'swarmer' or class == 'voider' then
if number_of_units >= 4 then return 2 if number_of_units >= 4 then return 2
elseif number_of_units >= 2 then return 1 elseif number_of_units >= 2 then return 1
else return 0 end else return 0 end
@ -704,7 +706,7 @@ function init()
conjurer = units_to_class_level(units_per_class.conjurer, 'conjurer'), conjurer = units_to_class_level(units_per_class.conjurer, 'conjurer'),
enchanter = units_to_class_level(units_per_class.enchanter, 'enchanter'), enchanter = units_to_class_level(units_per_class.enchanter, 'enchanter'),
psyker = units_to_class_level(units_per_class.psyker, 'psyker'), psyker = units_to_class_level(units_per_class.psyker, 'psyker'),
trapper = units_to_class_level(units_per_class.trapper, 'trapper'), curser = units_to_class_level(units_per_class.curser, 'curser'),
forcer = units_to_class_level(units_per_class.forcer, 'forcer'), forcer = units_to_class_level(units_per_class.forcer, 'forcer'),
swarmer = units_to_class_level(units_per_class.swarmer, 'swarmer'), swarmer = units_to_class_level(units_per_class.swarmer, 'swarmer'),
voider = units_to_class_level(units_per_class.voider, 'voider'), voider = units_to_class_level(units_per_class.voider, 'voider'),
@ -729,7 +731,7 @@ function init()
['conjurer'] = function(units) return 2, 4, get_number_of_units_per_class(units).conjurer end, ['conjurer'] = function(units) return 2, 4, get_number_of_units_per_class(units).conjurer end,
['enchanter'] = function(units) return 2, 4, get_number_of_units_per_class(units).enchanter end, ['enchanter'] = function(units) return 2, 4, get_number_of_units_per_class(units).enchanter end,
['psyker'] = function(units) return 2, 4, get_number_of_units_per_class(units).psyker end, ['psyker'] = function(units) return 2, 4, get_number_of_units_per_class(units).psyker end,
['trapper'] = function(units) return 2, 4, get_number_of_units_per_class(units).trapper end, ['curser'] = function(units) return 2, 4, get_number_of_units_per_class(units).curser end,
['forcer'] = function(units) return 2, 4, get_number_of_units_per_class(units).forcer end, ['forcer'] = function(units) return 2, 4, get_number_of_units_per_class(units).forcer end,
['swarmer'] = function(units) return 2, 4, get_number_of_units_per_class(units).swarmer end, ['swarmer'] = function(units) return 2, 4, get_number_of_units_per_class(units).swarmer end,
['voider'] = function(units) return 2, 4, get_number_of_units_per_class(units).voider end, ['voider'] = function(units) return 2, 4, get_number_of_units_per_class(units).voider end,
@ -804,7 +806,9 @@ function init()
main = Main() main = Main()
main:add(BuyScreen'buy_screen') main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', 22, { main:go_to('buy_screen', 22, {
{character = 'fisherman', level = 3}, {character = 'beastmaster', level = 3},
{character = 'scout', level = 3},
{character = 'outlaw', level = 3},
}) })
--[[ --[[
main:add(Arena'arena') main:add(Arena'arena')

View File

@ -244,7 +244,7 @@ function Unit:calculate_stats(first_run)
self.base_hp = 100*math.pow(2, self.level-1) self.base_hp = 100*math.pow(2, self.level-1)
self.base_dmg = 10*math.pow(2, self.level-1) self.base_dmg = 10*math.pow(2, self.level-1)
self.base_mvspd = 75 self.base_mvspd = 75
elseif self:is(EnemyCritter) then elseif self:is(EnemyCritter) or self:is(Critter) then
local x = self.level local x = self.level
local y = {0, 1, 4, 2, 3, 6, 3, 5, 9, 4, 6, 11, 7, 9, 15, 8, 10, 18, 9, 11, 21, 14, 15, 24, 25} local y = {0, 1, 4, 2, 3, 6, 3, 5, 9, 4, 6, 11, 7, 9, 15, 8, 10, 18, 9, 11, 21, 14, 15, 24, 25}
self.base_hp = 25 + 30*y[x] self.base_hp = 25 + 30*y[x]

View File

@ -294,15 +294,87 @@ function Player:init(args)
end) end)
end end
elseif self.character == 'fisherman' then elseif self.character == 'barbarian' then
self.color = character_colors.fisherman self.color = character_colors.barbarian
self:set_as_rectangle(9, 9, 'dynamic', 'player') self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle' self.visual_shape = 'rectangle'
self.classes = character_classes.fisherman self.classes = character_classes.barbarian
self.t:every(10, function() self.t:every(8, function()
Trap{group = main.current.main, x = self.x, y = self.y, color = self.color, v = 50, r = random:float(0, 2*math.pi), dmg = self.dmg, character = self.character, level = self.level, parent = self} self:attack(96, {stun = 4})
end) end)
elseif self.character == 'juggernaut' then
self.color = character_colors.juggernaut
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.juggernaut
self.t:every(8, function()
self:attack(64, {juggernaut_push = true})
end)
elseif self.character == 'lich' then
self.color = character_colors.lich
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.lich
self.attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(4, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
if closest_enemy then
self:shoot(self:angle_to_object(closest_enemy), {chain = (self.level == 3 and 14 or 7), v = 70})
end
end, nil, nil, 'shoot')
elseif self.character == 'cryomancer' then
self.color = character_colors.cryomancer
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.cryomancer
self.t:after(0.01, function()
self.dot_area = DotArea{group = main.current.effects, x = self.x, y = self.y, rs = self.area_size_m*48, color = self.color, dmg = self.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self}
end)
elseif self.character == 'pyromancer' then
self.color = character_colors.pyromancer
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.pyromancer
self.t:after(0.01, function()
self.dot_area = DotArea{group = main.current.effects, x = self.x, y = self.y, rs = self.area_size_m*48, color = self.color, dmg = self.area_dmg_m*self.dmg, character = self.character, level = self.level, parent = self}
end)
elseif self.character == 'corruptor' then
self.color = character_colors.corruptor
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.corruptor
self.attack_sensor = Circle(self.x, self.y, 160)
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
if closest_enemy then
self:shoot(self:angle_to_object(closest_enemy), {spawn_critters_on_kill = 3, spawn_critters_on_hit = (self.level == 3 and 3 or 0)})
end
end, nil, nil, 'shoot')
elseif self.character == 'beastmaster' then
self.color = character_colors.beastmaster
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.beastmaster
self.attack_sensor = Circle(self.x, self.y, 160)
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
if closest_enemy then
self:shoot(self:angle_to_object(closest_enemy), {spawn_critters_on_crit = 2})
end
end, nil, nil, 'shoot')
end end
self:calculate_stats(true) self:calculate_stats(true)
@ -345,7 +417,7 @@ function Player:update(dt)
if class_levels.conjurer >= 1 then number_of_active_sets = number_of_active_sets + 1 end 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.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.psyker >= 1 then number_of_active_sets = number_of_active_sets + 1 end
if class_levels.trapper >= 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.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 if class_levels.swarmer >= 1 then number_of_active_sets = number_of_active_sets + 1 end
if class_levels.voider >= 1 then number_of_active_sets = number_of_active_sets + 1 end if class_levels.voider >= 1 then number_of_active_sets = number_of_active_sets + 1 end
@ -522,6 +594,15 @@ function Player:hit(damage)
camera:shake(4, 0.5) camera:shake(4, 0.5)
main.current.damage_taken = main.current.damage_taken + actual_damage main.current.damage_taken = main.current.damage_taken + actual_damage
if self.character == 'beastmaster' and self.level == 3 then
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
trigger:after(0.01, function()
for i = 1, 2 do
Critter{group = main.current.main, x = self.x, y = self.y, color = orange[0], r = random:float(0, 2*math.pi), v = 20, dmg = self.dmg}
end
end)
end
local psykeeper = self:get_unit'psykeeper' local psykeeper = self:get_unit'psykeeper'
if psykeeper then if psykeeper then
psykeeper.stored_heal = psykeeper.stored_heal + actual_damage psykeeper.stored_heal = psykeeper.stored_heal + actual_damage
@ -557,6 +638,8 @@ function Player:hit(damage)
if self.leader then self:recalculate_followers() if self.leader then self:recalculate_followers()
else self.parent:recalculate_followers() end else self.parent:recalculate_followers() end
end end
if self.dot_area then self.dot_area.dead = true; self.dot_area = nil end
end end
end end
@ -638,6 +721,16 @@ function Player:shoot(r, mods)
local dmg_m = 1 local dmg_m = 1
local crit = false local crit = false
if self.chance_to_crit and random:bool(self.chance_to_crit) then dmg_m = 4; crit = true end if self.chance_to_crit and random:bool(self.chance_to_crit) then dmg_m = 4; crit = true end
print(crit, mods.spawn_critters_on_crit, self.chance_to_crit)
if crit and mods.spawn_critters_on_crit then
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
trigger:after(0.01, function()
for i = 1, mods.spawn_critters_on_crit do
Critter{group = main.current.main, x = self.x, y = self.y, color = orange[0], r = random:float(0, 2*math.pi), v = 10, dmg = self.dmg}
end
end)
end
if self.character == 'outlaw' then if self.character == 'outlaw' then
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} 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}
@ -707,7 +800,7 @@ function Player:shoot(r, mods)
dual_gunner2:play{pitch = random:float(0.95, 1.05), volume = 0.3} dual_gunner2:play{pitch = random:float(0.95, 1.05), volume = 0.3}
elseif self.character == 'archer' or self.character == 'hunter' then elseif self.character == 'archer' or self.character == 'hunter' then
archer1:play{pitch = random:float(0.95, 1.05), volume = 0.35} archer1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
elseif self.character == 'wizard' then elseif self.character == 'wizard' or self.character == 'lich' then
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.15} 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' then elseif self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'spellblade' then
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35} _G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
@ -718,6 +811,10 @@ function Player:shoot(r, mods)
_G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} _G[random:table{'cannoneer1', 'cannoneer2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
end end
if self.character == 'lich' then
frost1: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 if self.chance_to_barrage and random:bool(self.chance_to_barrage) then
self:barrage(r, 4) self:barrage(r, 4)
end end
@ -728,14 +825,19 @@ function Player:attack(area, mods)
mods = mods or {} mods = mods or {}
camera:shake(2, 0.5) camera:shake(2, 0.5)
self.hfx:use('shoot', 0.25) 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, w = 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, w = 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}
Area(table.merge(t, mods)) Area(table.merge(t, mods))
if self.character == 'swordsman' then if self.character == 'swordsman' or self.character == 'barbarian' or self.character == 'juggernaut' then
_G[random:table{'swordsman1', 'swordsman2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.75} _G[random:table{'swordsman1', 'swordsman2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.75}
elseif self.character == 'elementor' then elseif self.character == 'elementor' then
elementor1:play{pitch = random:float(0.9, 1.1), volume = 0.5} elementor1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
end end
if self.character == 'juggernaut' then
elementor1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
end
end end
@ -823,6 +925,12 @@ function Projectile:init(args)
self.t:tween(12.25, self, {orbit_vr = 0}, math.linear) self.t:tween(12.25, self, {orbit_vr = 0}, math.linear)
end) end)
end end
elseif self.character == 'lich' then
self.spring:pull(0.15)
self.t:every(0.08, function()
HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color}
end)
end end
if self.homing then if self.homing then
@ -881,6 +989,11 @@ function Projectile:draw()
for i = 1, 4 do graphics.arc('open', self.x, self.y, self.pull_sensor.rs, (i-1)*math.pi/2 + math.pi/4 - math.pi/8, (i-1)*math.pi/2 + math.pi/4 + math.pi/8, self.color, lw) end for i = 1, 4 do graphics.arc('open', self.x, self.y, self.pull_sensor.rs, (i-1)*math.pi/2 + math.pi/4 - math.pi/8, (i-1)*math.pi/2 + math.pi/4 + math.pi/8, self.color, lw) end
graphics.pop() graphics.pop()
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.pop()
else else
graphics.push(self.x, self.y, self.r + (self.orbit_r or 0)) 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) graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 2, 2, self.color)
@ -943,7 +1056,7 @@ function Projectile:on_collision_enter(other, contact)
if self.character == 'spellblade' then if self.character == 'spellblade' then
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075} magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075}
end end
elseif self.character == 'wizard' then elseif self.character == 'wizard' or self.character == 'lich' then
self:die(x, y, r, random:int(2, 3)) self:die(x, y, r, random:int(2, 3))
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075} magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.075}
elseif self.character == 'cannoneer' then elseif self.character == 'cannoneer' then
@ -973,10 +1086,17 @@ function Projectile:on_trigger_enter(other, contact)
if self.chain > 0 then if self.chain > 0 then
self.chain = self.chain - 1 self.chain = self.chain - 1
table.insert(self.chain_enemies_hit, other) table.insert(self.chain_enemies_hit, other)
local object = self:get_random_object_in_shape(Circle(self.x, self.y, 160), main.current.enemies, self.chain_enemies_hit) local object = self:get_random_object_in_shape(Circle(self.x, self.y, 48), main.current.enemies, self.chain_enemies_hit)
if object then if object then
self.r = self:angle_to_object(object) self.r = self:angle_to_object(object)
if self.character == 'lich' then
self.v = self.v*1.1
if self.level == 3 then
object:slow(0.2, 2)
end
else
self.v = self.v*1.25 self.v = self.v*1.25
end
if self.level == 3 and self.character == 'scout' then if self.level == 3 and self.character == 'scout' then
self.dmg = self.dmg*1.25 self.dmg = self.dmg*1.25
end end
@ -992,7 +1112,7 @@ function Projectile:on_trigger_enter(other, contact)
if self.character == 'spellblade' then if self.character == 'spellblade' then
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15} magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
end end
elseif self.character == 'wizard' then elseif self.character == 'wizard' or self.character == 'lich' then
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15} magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
else else
hit3:play{pitch = random:float(0.95, 1.05), volume = 0.35} hit3:play{pitch = random:float(0.95, 1.05), volume = 0.35}
@ -1063,7 +1183,6 @@ function Area:init(args)
self:init_game_object(args) self:init_game_object(args)
self.shape = Rectangle(self.x, self.y, 1.5*self.w, 1.5*self.w, self.r) self.shape = Rectangle(self.x, self.y, 1.5*self.w, 1.5*self.w, self.r)
local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies) local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies)
if self.character == 'saboteur' then print(self.dmg) end
for _, enemy in ipairs(enemies) do for _, enemy in ipairs(enemies) do
if self.character == 'elementor' then if self.character == 'elementor' then
enemy:hit(2*self.dmg) enemy:hit(2*self.dmg)
@ -1082,16 +1201,29 @@ function Area:init(args)
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end
if self.character == 'wizard' or self.character == 'elementor' then if self.character == 'wizard' or self.character == 'elementor' then
magic_hit1:play{pitch = random:float(0.95, 1.05), volume = 0.5} magic_hit1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
elseif self.character == 'swordsman' then elseif self.character == 'swordsman' or self.character == 'barbarian' or self.character == 'juggernaut' then
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35} hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
elseif self.character == 'blade' then elseif self.character == 'blade' then
blade_hit1:play{pitch = random:float(0.9, 1.1), volume = 0.35} blade_hit1:play{pitch = random:float(0.9, 1.1), volume = 0.35}
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.2} hit2:play{pitch = random:float(0.95, 1.05), volume = 0.2}
elseif self.character == 'saboteur' then elseif self.character == 'saboteur' or self.character == 'pyromancer' then
if self.character == 'pyromancer' then pyro2:play{pitch = random:float(0.95, 1.05), volume = 0.4} end
_G[random:table{'saboteur_hit1', 'saboteur_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.2} _G[random:table{'saboteur_hit1', 'saboteur_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.2}
elseif self.character == 'cannoneer' then elseif self.character == 'cannoneer' then
_G[random:table{'saboteur_hit1', 'saboteur_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.075} _G[random:table{'saboteur_hit1', 'saboteur_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.075}
end end
if self.stun then
enemy:slow(0.1, self.stun)
enemy.barbarian_stunned = true
enemy.t:after(self.stun, function() enemy.barbarian_stunned = false end)
end
if self.juggernaut_push then
local r = self.parent:angle_to_object(enemy)
enemy:push(random:float(75, 100), r)
enemy.juggernaut_push = 3*self.dmg
end
end end
self.color = fg[0] self.color = fg[0]
@ -1136,16 +1268,40 @@ function DotArea:init(args)
self:init_game_object(args) self:init_game_object(args)
self.shape = Circle(self.x, self.y, self.rs) self.shape = Circle(self.x, self.y, self.rs)
if self.character == 'plague_doctor' or self.character == 'pyromancer' then
self.t:every(0.2, function() self.t:every(0.2, function()
local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies) 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
for _, enemy in ipairs(enemies) do for _, enemy in ipairs(enemies) do
hit2:play{pitch = random:float(0.8, 1.2), volume = 0.2} hit2:play{pitch = random:float(0.8, 1.2), volume = 0.2}
if self.character == 'pyromancer' then
pyro1:play{pitch = random:float(1.5, 1.8), volume = 0.1}
enemy.pyrod = self
end
enemy:hit(self.dmg/5) enemy:hit(self.dmg/5)
HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1} HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1}
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = self.color} end for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = self.color} end
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end
end end
end, nil, nil, 'dot') end, nil, nil, 'dot')
elseif self.character == 'cryomancer' then
self.t:every(2, function()
local enemies = main.current.main:get_objects_in_shape(self.shape, main.current.enemies)
if #enemies > 0 then
self.spring:pull(0.15, 200, 10)
frost1:play{pitch = random:float(0.8, 1.2), volume = 0.4}
end
for _, enemy in ipairs(enemies) do
if self.level == 3 then
enemy:slow(0.4, 4)
end
enemy:hit(2*self.dmg)
HitCircle{group = main.current.effects, x = enemy.x, y = enemy.y, rs = 6, color = fg[0], duration = 0.1}
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = self.color} end
for i = 1, 1 do HitParticle{group = main.current.effects, x = enemy.x, y = enemy.y, color = enemy.color} end
end
end, nil, nil, 'dot')
end
self.color = fg[0] self.color = fg[0]
self.color_transparent = Color(args.color.r, args.color.g, args.color.b, 0.08) self.color_transparent = Color(args.color.r, args.color.g, args.color.b, 0.08)
@ -1170,7 +1326,7 @@ function DotArea:update(dt)
self.vr = self.vr + self.dvr*dt self.vr = self.vr + self.dvr*dt
if self.parent then if self.parent then
if self.character == 'plague_doctor' and self.level == 3 then if (self.character == 'plague_doctor' and self.level == 3) or self.character == 'cryomancer' or self.character == 'pyromancer' then
self.x, self.y = self.parent.x, self.parent.y self.x, self.y = self.parent.x, self.parent.y
self.shape:move_to(self.x, self.y) self.shape:move_to(self.x, self.y)
end end
@ -1192,49 +1348,6 @@ end
--[[
Trap = Object:extend()
Trap:implement(GameObject)
Trap:implement(Physics)
function Trap:init(args)
self:init_game_object(args)
self.shape = Rectangle(self.x, self.y, 6, 6)
self.spring:pull(0.15, 200, 20)
self.vr = 0
self.dvr = random:float(-2*math.pi, 2*math.pi)
self.t:tween(1, self, {v = 0, dvr = 0}, math.linear)
end
function Trap:update(dt)
self:update_game_object(dt)
self:move_along_angle(self.v, self.r)
self.vr = self.vr + self.dvr*dt
self.shape:move_to(self.x, self.y)
local enemies = self:get_objects_in_shape(self.shape, main.current.enemies)
if #enemies > 0 then
self.dead = true
local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 24), main.current.enemies)
for _, enemy in ipairs(enemies) do
enemy:slow(0.1, 4)
end
end
end
function Trap:draw()
graphics.push(self.x, self.y, self.r + self.vr, self.spring.x, self.spring.x)
graphics.line(self.x - 6, self.y, self.x + 6, self.y, self.color, 3)
graphics.line(self.x, self.y - 6, self.x, self.y + 6, self.color, 3)
graphics.pop()
end
]]--
Turret = Object:extend() Turret = Object:extend()
Turret:implement(GameObject) Turret:implement(GameObject)
Turret:implement(Physics) Turret:implement(Physics)
@ -1413,14 +1526,17 @@ function Saboteur:update(dt)
self:calculate_stats() self:calculate_stats()
if not self.target then self.target = random:table(self.group:get_objects_by_classes(main.current.enemies)) end if not self.target then self.target = random:table(self.group:get_objects_by_classes(main.current.enemies)) end
if not self.target then return end if self.target and self.target.dead then self.target = random:table(self.group:get_objects_by_classes(main.current.enemies)) end
if self.target.dead then self.target = random:table(self.group:get_objects_by_classes(main.current.enemies)) end if not self.target then
if not self.target then return end self:seek_point(gw/2, gh/2)
self:rotate_towards_velocity(0.5)
self.r = self:get_angle()
else
self:seek_point(self.target.x, self.target.y) self:seek_point(self.target.x, self.target.y)
self:rotate_towards_velocity(0.5) self:rotate_towards_velocity(0.5)
self.r = self:get_angle() self.r = self:get_angle()
end end
end
function Saboteur:draw() function Saboteur:draw()
@ -1439,3 +1555,121 @@ function Saboteur:on_collision_enter(other, contact)
self.dead = true self.dead = true
end end
end end
Critter = Object:extend()
Critter:implement(GameObject)
Critter:implement(Physics)
Critter:implement(Unit)
function Critter:init(args)
self:init_game_object(args)
self:init_unit()
self:set_as_rectangle(7, 4, 'dynamic', 'player')
self:set_restitution(0.5)
self.classes = {'enemy_critter'}
self.color = orange[0]
self:calculate_stats(true)
self:set_as_steerable(self.v, 400, math.pi, 1)
self:push(args.v, args.r)
self.invulnerable = true
self.t:after(0.5, function() self.invulnerable = false end)
self.hp = 1
end
function Critter:update(dt)
self:update_game_object(dt)
if self.being_pushed then
local v = math.length(self:get_velocity())
if v < 50 then
self.being_pushed = false
self.steering_enabled = true
self:set_damping(0)
self:set_angular_damping(0)
end
else
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.target then
self:seek_point(gw/2, gh/2)
self:wander(50, 200, 50)
self:rotate_towards_velocity(1)
self:steering_separate(8, {Critter})
else
self:seek_point(self.target.x, self.target.y)
self:wander(50, 200, 50)
self:rotate_towards_velocity(1)
self:steering_separate(8, {Critter})
end
end
self.r = self:get_angle()
end
function Critter: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, 2, 2, self.hfx.hit.f and fg[0] or self.color)
graphics.pop()
end
function Critter:hit(damage)
if self.dead or self.invulnerable then return end
self.hfx:use('hit', 0.25, 200, 10)
self.hp = self.hp - damage
-- self:show_hp()
if self.hp <= 0 then self:die() end
end
function Critter:push(f, r)
self.push_force = f
self.being_pushed = true
self.steering_enabled = false
self:apply_impulse(f*math.cos(r), f*math.sin(r))
self:apply_angular_impulse(random:table{random:float(-12*math.pi, -4*math.pi), random:float(4*math.pi, 12*math.pi)})
self:set_damping(1.5)
self:set_angular_damping(1.5)
end
function Critter:die(x, y, r, n)
if self.dead then return end
x = x or self.x
y = y or self.y
n = n or random:int(2, 3)
for i = 1, n do HitParticle{group = main.current.effects, x = x, y = y, r = random:float(0, 2*math.pi), color = self.color} end
HitCircle{group = main.current.effects, x = x, y = y}:scale_down()
self.dead = true
_G[random:table{'enemy_die1', 'enemy_die2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.5}
critter2:play{pitch = random:float(0.95, 1.05), volume = 0.2}
end
function Critter:on_collision_enter(other, contact)
local x, y = contact:getPositions()
local nx, ny = contact:getNormal()
local r = 0
if nx == 0 and ny == -1 then r = -math.pi/2
elseif nx == 0 and ny == 1 then r = math.pi/2
elseif nx == -1 and ny == 0 then r = math.pi
else r = 0 end
if other:is(Wall) then
self.hfx:use('hit', 0.15, 200, 10, 0.1)
self:bounce(contact:getNormal())
end
end
function Critter:on_trigger_enter(other, contact)
if other:is(Seeker) then
self:hit(1)
other:hit(self.dmg)
end
end

36
todo
View File

@ -35,7 +35,7 @@
Enchanter: increased damage Enchanter: increased damage
Conjurer: increased summon damage and duration Conjurer: increased summon damage and duration
Psyker: increased damage and health based on number of active sets Psyker: increased damage and health based on number of active sets
Trapper: release extra traps Curser: increased curse effect and duration
Forcer: increased knockback force Forcer: increased knockback force
Swarmer: increased critter health Swarmer: increased critter health
Voider: increased damage over time Voider: increased damage over time
@ -56,30 +56,30 @@
* Cannoneer [ranger, nuker]: shoots a projectile that deals AoE damage - Lv.3: Cannon Barrage - showers the hit area in additional cannon shots that deal AoE damage * Cannoneer [ranger, nuker]: shoots a projectile that deals AoE damage - Lv.3: Cannon Barrage - showers the hit area in additional cannon shots that deal AoE damage
* Dual Gunner [ranger, rogue]: shoots two parallel projectiles - Lv.3: Gun Kata - every 5th attack shoots projectiles in a rapid succession for a duration, targetting all nearby enemies * Dual Gunner [ranger, rogue]: shoots two parallel projectiles - Lv.3: Gun Kata - every 5th attack shoots projectiles in a rapid succession for a duration, targetting all nearby enemies
* Hunter [ranger, conjurer]: shoots an arrow that summons a pet - Lv.3: Feral Pack - summons 3 pets * Hunter [ranger, conjurer]: shoots an arrow that summons a pet - Lv.3: Feral Pack - summons 3 pets
(Apply arena.chronomancer_dot when damage over time is implemented) * Chronomancer [mage, enchanter]: increased attack speed to all allies - Lv.3: Quicken - enemies take DoT faster * (Apply arena.chronomancer_dot when damage over time is implemented) * Chronomancer [mage, enchanter]: increased attack speed to all allies - Lv.3: Quicken - enemies take DoT faster
* Spellblade [mage, rogue]: throws knives that spiral outwards and pierce - Lv.3: Spiralism - faster projectile speed and tighter turns * Spellblade [mage, rogue]: throws knives that spiral outwards and pierce - Lv.3: Spiralism - faster projectile speed and tighter turns
* Psykeeper [healer, psyker]: stores damage taken by all allies and redistributes it as healing - Lv.3: Crucio - also redistributes it as damage to all enemies * Psykeeper [healer, psyker]: stores damage taken by all allies and redistributes it as healing - Lv.3: Crucio - also redistributes it as damage to all enemies
* Engineer [conjurer]: drops sentries that shoot bursts of projectils - Lv.3: Upgrade - every 3rd sentry dropped, upgrade all sentries temporarily, giving increased damage and attack speed * Engineer [conjurer]: drops sentries that shoot bursts of projectils - Lv.3: Upgrade - every 3rd sentry dropped, upgrade all sentries temporarily, giving increased damage and attack speed
* Plague Doctor [nuker, voider]: creates an area that deals DoT - Lv.3: Pandemic - inflicts enemies with a contagion that deals additional DoT, if they die from it it passes to a nearby enemy * Plague Doctor [nuker, voider]: creates an area that deals DoT - Lv.3: Pandemic - inflicts enemies with a contagion that deals additional DoT, if they die from it it passes to a nearby enemy
Fisherman [trapper, warrior]: throws a net that entangles enemies and prevents them from moving - Lv.3: Electric Net - enemies caught take DoT * Barbarian [curser, warrior]: deals AoE damage and stuns enemies hit for 4 seconds - Lv.3: Seism - stunned enemies also take 100% increased damage
Juggernaut [forcer, warrior]: creates a small area that deals AoE damage and pushes enemies away - Lv.3: Brutal Impact - enemies pushed away are instantly killed if they hit a wall * Juggernaut [forcer, warrior]: creates a small area that deals AoE damage and pushes enemies away - Lv.3: Brutal Impact - enemies pushed away are instantly killed if they hit a wall
Lich [mage]: launches a chain frost that chains 7 times, dealing damage and slowing enemies it hits - Lv.3: Piercing Frost - chain frost ignores enemy defenses * Lich [mage]: launches a chain frost that chains 7 times, dealing damage and slowing enemies it hits - Lv.3: Piercing Frost - chain frost ignores enemy defenses
Cryomancer [mage, voider]: nearby enemies take damage over time and have decreased movement speed - Lv.3: Frostbite - enemies killed by the cryomancer freeze nearby enemies, frozen enemies can't move and take increased damage * Cryomancer [mage, voider]: nearby enemies take damage over time and have decreased movement speed - Lv.3: Frostbite - enemies killed by the cryomancer freeze nearby enemies, frozen enemies can't move and take increased damage
Pyromancer [mage, nuker, voider]: nearby enemies take damage over time and deal decreased damage - Lv.3: Ignite - enemies killed by the pyromancer explode, dealing AoE damage * Pyromancer [mage, nuker, voider]: nearby enemies take damage over time and deal decreased damage - Lv.3: Ignite - enemies killed by the pyromancer explode, dealing AoE damage
Corruptor [ranger, swarmer]: spawn 3 small critters if the corruptor kills an enemy - Lv.3: Infestation - spawn 3 small critters if the corruptor hits an enemy * Corruptor [ranger, swarmer]: spawn 3 small critters if the corruptor kills an enemy - Lv.3: Corruption - spawn 3 small critters if the corruptor hits an enemy
Beastmaster [rogue, swarmer]: spawn 2 small critters if the beastmaster crits - Lv.3: Call of the Wild - spawn 2 small critters if the beastmaster gets hit * Beastmaster [rogue, swarmer]: spawn 2 small critters if the beastmaster crits - Lv.3: Call of the Wild - spawn 2 small critters if the beastmaster gets hit
Launcher [trapper, forcer]: creates a trap that launches enemies that trigger it - Lv.3: Kineticism - enemies launched that hit other enemies transfer their kinetic energy Launcher [curser, forcer]: curses nearby enemies with a kinetic curse that triggers after 4 seconds - Lv.3: Kineticism - enemies launched that hit other enemies transfer their kinetic energy at double value
Spiker [trapper, rogue]: creates a trap that crits when triggered - Lv.3: Caltrops - slows enemies hit and deals DoT Bard [curser, rogue]: shoots a projectile that inflicts enemies hit with the bard's curse - Lv.3: The Bard's Song - every 5th attack consume the curse to deal massive damage to enemies affected
Assassin [rogue, voider]: throws a piercing knife that inflicts poison - Lv.3: Toxic Delivery - poison inflicted from crits deals more damage Assassin [rogue, voider]: throws a piercing knife that inflicts poison - Lv.3: Toxic Delivery - poison inflicted from crits deals more damage
Host [conjurer, swarmer]: creates overlords that periodically spawn small critters - Lv.3: Invasion - increased critter spawn rate Host [conjurer, swarmer]: creates overlords that periodically spawn small critters - Lv.3: Invasion - increased critter spawn rate
Carver [conjurer, healer]: carves a statue that periodically heals in an area - Lv.3: World Tree - carves a tree that heals in a bigger area and removes all buffs from enemies Carver [conjurer, curser, healer]: carves a statue that periodically heals in an area - Lv.3: World Tree - carves a tree that heals in a bigger area and removes all buffs from enemies
Bane [swarmer, voider]: spawn a small critter periodically that explodes and deals DoT - Lv.3: Baneling Swarm - spawn 4 banelings instead Bane [curser, voider]: creates a large area that curses enemies to take increased DoT - Lv.3: Nightmare - the area also deals DoT and slows enemies
Psykino [mage, psyker, forcer]: quickly pulls enemies together and then releases them with a force - Lv.3: Magnetic Force - enemies pulled together are forced to collide with each other before being released Psykino [mage, psyker, forcer]: quickly pulls enemies together and then releases them with a force - Lv.3: Magnetic Force - enemies pulled together are forced to collide with each other before being released
Arbalester [ranger, forcer]: launches a massive arrow that pushes enemies back, ignoring knockback resistances - Lv.3: Ballista Sinistra - enemies hit by the arrow have massively decreased defense Arbalester [ranger, forcer]: launches a massive arrow that pushes enemies back, ignoring knockback resistances - Lv.3: Ballista Sinistra - enemies hit by the arrow have massively decreased defense
Pirate [warrior, forcer]: launches a hook that captures nearby enemies and pulls them towards you - Lv.3: Jolly Roger - place a flag that grants gold based on number of enemies killed under its effect Highlander [warrior]: creates a small area that deals massive damage - Lv.3: Crosscut - two crosscutting areas of larger size are created instead
Sapper [trapper, enchanter, healer]: creates a trap that steals health from enemies that trigger it and grants increased movement speed - Lv.3: when a sapper trap is triggered other nearby traps are triggered Sapper [enchanter, voider, healer]: periodically steals health from nearby enemies and gain increased movement speed - Lv.3: Enduring Sap - sapped enemies permanently take damage over time, even outside the sapper's area of effect
Priest [healer]: heals all units periodically - Lv.3: Divine Intervention - at the start of the round pick 3 units at random and grants them a buff that prevents them from dying once Priest [healer]: heals all units periodically - Lv.3: Divine Intervention - at the start of the round pick 3 units at random and grants them a buff that prevents them from dying once
Burrower [trapper, swarmer]: creates a trap that contains 6 small critters which are released when triggered - Lv.3: Zergling Rush - triples the number of critters released Infestor [curser, swarmer]: curses enemies in an area for 6 seconds, they will release multiple critters on death - Lv.3: Infestation - triples the number of critters released
Flagellant [psyker, enchanter]: periodically deals damage to self and grants a damage buff to all allies - Lv.3: Zealotry - deals damage to all allies instead and also grants a massive damage buff Flagellant [psyker, enchanter]: periodically deals damage to self and grants a damage buff to all allies - Lv.3: Zealotry - deals damage to all allies instead and also grants a massive damage buff
Sets Sets
Ranger = 8/8 Ranger = 8/8
@ -93,8 +93,8 @@
Psyker = 4/4 Psyker = 4/4
Healer = 5/5 Healer = 5/5
Enchanter = 5/5 Enchanter = 5/5
Trapper = 5/5 Curser = 6/6
Swarmer = 5/5 Swarmer = 4/4
10. Items 10. Items
Ouroboros Technique R: rotating around yourself to the right makes every unit periodically release projectiles Ouroboros Technique R: rotating around yourself to the right makes every unit periodically release projectiles