master
a327ex 2021-04-12 22:23:53 -03:00
parent d006dd3782
commit dd8540de54
8 changed files with 152 additions and 167 deletions

Binary file not shown.

View File

@ -887,3 +887,21 @@ Implemented more 7 units fully. Today was slower because these were all new unit
| 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 |
# Day 55 - 12/04/21
Even slower day today, but I managed to get something done. I'm hoping I can finish the other 9 characters tomorrow but it might go slow too...
| Character | Classes | Description |
| --- | --- | --- |
| Launcher | forcer, warrior | nearby enemies are pushed after 4 seconds, taking 2X damage on wall hit |
| Bard | curser, rogue | throws a knife that deals X damage and inflicts enemies hit with the bard's curse |
| Assassin | voider, rogue | throws a piercing knife that deals X damage and inflicts poison that deals X/2 damage per second for 3 seconds |
| Host | swarmer | periodically spawn 1 small critter |
| Character | Lv.3 Effect Name | Lv.3 Effect Description |
| --- | --- | --- |
| Launcher | Kineticism | enemies launched take 300% more damage when they hit walls |
| Bard | The Bard's Song | every 8th attack consume the curse to deal 4X damage to affected enemies |
| Assassin | Toxic Delivery | poison inflicted from crits deals 8X damage |
| Host | Invasion | +100% critter spawn rate and spawn 2 critters instead |

View File

@ -256,6 +256,7 @@ function Seeker:update(dt)
self.being_pushed = false
self.steering_enabled = true
self.juggernaut_push = false
self.launcher_push = false
self:set_damping(0)
self:set_angular_damping(0)
end
@ -326,6 +327,11 @@ function Seeker:on_collision_enter(other, contact)
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
end
if self.launcher_push then
self:hit(self.launcher_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
if self.being_pushed and math.length(self:get_velocity()) > 60 then
other:hit(math.floor(self.push_force/4))
@ -454,6 +460,29 @@ function Seeker:slow(amount, duration)
end
function Seeker:curse(curse, duration, arg1)
if curse == 'launcher' then
self.t:after(duration, function()
self.launcher_push = arg1
self:push(random:float(50, 75), random:table{0, math.pi, math.pi/2, -math.pi/2})
end, 'launcher_curse')
elseif curse == 'bard' then
self.bard_cursed = true
end
end
function Seeker:apply_dot(dmg, duration)
self.t:every(0.25, function()
hit2:play{pitch = random:float(0.8, 1.2), volume = 0.2}
self:hit(dmg/4)
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = fg[0], duration = 0.1}
for i = 1, 1 do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color} end
for i = 1, 1 do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = purple[0]} end
end, math.floor(duration/0.2))
end
EnemyCritter = Object:extend()

View File

@ -19,6 +19,8 @@ function init()
music.volume = 0
local s = {tags = {sfx}}
bard2 = Sound('376532__womb-affliction__flute-trill.ogg', s)
bard1 = Sound('Magical Impact 12.ogg', s)
frost1 = Sound('Frost Bolt 20.ogg', s)
pyro1 = Sound('Fire bolt 5.ogg', s)
pyro2 = Sound('Explosion Fireworks_01.ogg', s)
@ -173,7 +175,7 @@ function init()
['pyromancer'] = red[0],
['corruptor'] = orange[0],
['beastmaster'] = red[0],
['launcher'] = orange[0],
['launcher'] = yellow[0],
['bard'] = red[0],
['assassin'] = purple[0],
['host'] = orange[0],
@ -217,7 +219,7 @@ function init()
['pyromancer'] = 'red',
['corruptor'] = 'orange',
['beastmaster'] = 'red',
['launcher'] = 'orange',
['launcher'] = 'yellow',
['bard'] = 'red',
['assassin'] = 'purple',
['host'] = 'orange',
@ -264,7 +266,7 @@ function init()
['launcher'] = {'curser', 'forcer'},
['bard'] = {'curser', 'rogue'},
['assassin'] = {'rogue', 'voider'},
['host'] = {'conjurer', 'swarmer'},
['host'] = {'swarmer'},
['carver'] = {'conjurer', 'curser', 'healer'},
['bane'] = {'curser', 'voider'},
['psykino'] = {'mage', 'psyker', 'forcer'},
@ -305,10 +307,10 @@ function init()
['pyromancer'] = '[blue]Mage, [red]Nuker, [purple]Voider',
['corruptor'] = '[green]Ranger, [orange]Swarmer',
['beastmaster'] = '[red]Rogue, [orange]Swarmer',
['launcher'] = '[purple]Curser, [yellow]Forcer',
['launcher'] = '[yellow]Forcer, [purple]Curser',
['bard'] = '[purple]Curser, [red]Rogue',
['assassin'] = '[red]Rogue, [purple]Voider',
['host'] = '[orange]Conjurer, [orange]Swarmer',
['host'] = '[orange]Swarmer',
['carver'] = '[orange]Conjurer, [purple]Curser, [green]Healer',
['bane'] = '[purple]Curser, Voider',
['psykino'] = '[blue]Mage, [fg]Psyker, [yellow]Forcer',
@ -365,11 +367,11 @@ function init()
['pyromancer'] = function(lvl) return '[fg]nearby enemies take [yellow]' .. get_character_stat('pyromancer', lvl, 'dmg') .. '[fg] damage per second' 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,
['launcher'] = function(lvl) return '[fg]nearby enemies are afflicted with a kinetic curse that triggers after [yellow]4[fg] seconds' end,
['bard'] = function(lvl) return "[fg]shoots a projectile that inflicts enemies hit with the bard's curse" end,
['launcher'] = function(lvl) return '[fg]nearby enemies are pushed after [yellow]4[fg] seconds, taking [yellow]' .. 2*get_character_stat('launcher', lvl, 'dmg') .. '[fg] damage on wall hit' end,
['bard'] = function(lvl) return "[fg]throws a knife that deals [yellow]" .. get_character_stat('bard', lvl, 'dmg') .. "[fg] damage and 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]' ..
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,
get_character_stat('assassin', lvl, 'dmg')/2 .. '[fg] damage per second for [yellow]3[fg] seconds' end,
['host'] = function(lvl) return '[fg]periodically spawn [yellow]1[fg] small critter' 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]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,
@ -411,7 +413,7 @@ function init()
['corruptor'] = '[orange]Corruption',
['beastmaster'] = '[red]Call of the Wild',
['launcher'] = '[orange]Kineticism',
['bard'] = "[orange]The Bard's Song",
['bard'] = "[red]The Bard's Song",
['assassin'] = '[purple]Toxic Delivery',
['host'] = '[orange]Invasion',
['carver'] = '[green]World Tree',
@ -498,10 +500,10 @@ function init()
['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,
['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,
['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,
['launcher'] = function() return '[fg]enemies launched take [yellow]300%[fg] more damage when they hit walls' end,
['bard'] = function() return '[fg]every 8th attack consume the curse to deal [yellow]' .. 4*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,
['host'] = function() return '[fg][yellow]+50%[fg] critter spawn rate' end,
['host'] = function() return '[fg][yellow]+100%[fg] critter spawn rate and spawn [yellow]2[fg] critters instead' 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]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,
@ -575,6 +577,7 @@ function init()
['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},
['overlord'] = {hp = 1.5, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.5},
}
local ylb1 = function(lvl) return lvl >= 2 and 'fg' or (lvl >= 1 and 'yellow' or 'light_bg') end
@ -806,9 +809,7 @@ function init()
main = Main()
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', 22, {
{character = 'beastmaster', level = 3},
{character = 'scout', level = 3},
{character = 'outlaw', level = 3},
{character = 'host', level = 3},
})
--[[
main:add(Arena'arena')

View File

@ -250,6 +250,10 @@ function Unit:calculate_stats(first_run)
self.base_hp = 25 + 30*y[x]
self.base_dmg = 10 + 3*y[x]
self.base_mvspd = 60 + 3*y[x]
elseif self:is(Overlord) then
self.base_hp = 50*math.pow(2, self.level-1)
self.base_dmg = 10*math.pow(2, self.level-1)
self.base_mvspd = 40
end
self.base_aspd_m = 1
self.base_area_dmg_m = 1

View File

@ -6,12 +6,12 @@ function Player:init(args)
self:init_game_object(args)
self:init_unit()
if self.character == 'vagrant' then
self.color = character_colors.vagrant
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.vagrant
self.color = character_colors[self.character]
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes[self.character]
if self.character == 'vagrant' 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)
@ -21,22 +21,12 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'swordsman' then
self.color = character_colors.swordsman
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.swordsman
self.attack_sensor = Circle(self.x, self.y, 64)
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()
self:attack(96)
end, nil, nil, 'attack')
elseif self.character == 'wizard' then
self.color = character_colors.wizard
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.wizard
self.attack_sensor = Circle(self.x, self.y, 128)
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)
@ -46,11 +36,6 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'archer' then
self.color = character_colors.archer
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.archer
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)
@ -60,11 +45,6 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'scout' then
self.color = character_colors.scout
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.scout
self.attack_sensor = Circle(self.x, self.y, 64)
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)
@ -74,11 +54,6 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'cleric' then
self.color = character_colors.cleric
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.cleric
self.last_heal_time = love.timer.getTime()
self.t:every(2, function()
local all_units = self:get_all_units()
@ -96,11 +71,6 @@ function Player:init(args)
end)
elseif self.character == 'outlaw' then
self.color = character_colors.outlaw
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.outlaw
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()
local closest_enemy = self:get_closest_object_in_shape(self.attack_sensor, main.current.enemies)
@ -110,22 +80,12 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'blade' then
self.color = character_colors.blade
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.blade
self.attack_sensor = Circle(self.x, self.y, 64)
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()
self:shoot()
end, nil, nil, 'shoot')
elseif self.character == 'elementor' then
self.color = character_colors.elementor
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.elementor
self.attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(7, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
local enemy = self:get_random_object_in_shape(self.attack_sensor, main.current.enemies)
@ -135,11 +95,6 @@ function Player:init(args)
end, nil, nil, 'attack')
elseif self.character == 'saboteur' then
self.color = character_colors.saboteur
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.saboteur
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)
@ -149,11 +104,6 @@ function Player:init(args)
end)
elseif self.character == 'stormweaver' then
self.color = character_colors.stormweaver
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.stormweaver
self.t:every(8, function()
stormweaver1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
local units = self:get_all_units()
@ -163,11 +113,6 @@ function Player:init(args)
end)
elseif self.character == 'sage' then
self.color = character_colors.sage
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.sage
self.attack_sensor = Circle(self.x, self.y, 96)
self.t:cooldown(12, 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)
@ -176,18 +121,7 @@ function Player:init(args)
end
end)
elseif self.character == 'squire' then
self.color = character_colors.squire
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.squire
elseif self.character == 'cannoneer' then
self.color = character_colors.cannoneer
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.cannoneer
self.attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(6, 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)
@ -197,11 +131,6 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'dual_gunner' then
self.color = character_colors.dual_gunner
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.dual_gunner
self.dg_counter = 0
self.attack_sensor = Circle(self.x, self.y, 96)
self.gun_kata_sensor = Circle(self.x, self.y, 160)
@ -213,11 +142,6 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'hunter' then
self.color = character_colors.hunter
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.hunter
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)
@ -227,39 +151,20 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'chronomancer' then
self.color = character_colors.chronomancer
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.chronomancer
if self.level == 3 then
main.current.chronomancer_dot = 0.5
end
elseif self.character == 'spellblade' then
self.color = character_colors.spellblade
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.spellblade
self.t:every(2, function()
self:shoot(random:float(0, 2*math.pi))
end, nil, nil, 'shoot')
elseif self.character == 'psykeeper' then
self.color = character_colors.psykeeper
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.psykeeper
self.stored_heal = 0
self.last_heal_time = love.timer.getTime()
elseif self.character == 'engineer' then
self.color = character_colors.engineer
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.engineer
self.turret_counter = 0
self.t:every(8, function()
SpawnEffect{group = main.current.effects, x = self.x, y = self.y, color = orange[0], action = function(x, y)
@ -279,11 +184,6 @@ function Player:init(args)
end)
elseif self.character == 'plague_doctor' then
self.color = character_colors.plague_doctor
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.plague_doctor
self.t:every(5, function()
self:dot_attack(24, {duration = 12})
end)
@ -295,31 +195,16 @@ function Player:init(args)
end
elseif self.character == 'barbarian' then
self.color = character_colors.barbarian
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = character_classes.barbarian
self.t:every(8, function()
self:attack(96, {stun = 4})
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)
@ -329,31 +214,16 @@ function Player:init(args)
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)
@ -363,11 +233,6 @@ function Player:init(args)
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)
@ -375,6 +240,45 @@ function Player:init(args)
self:shoot(self:angle_to_object(closest_enemy), {spawn_critters_on_crit = 2})
end
end, nil, nil, 'shoot')
elseif self.character == 'launcher' then
self.t:every(8, function()
self:attack(128)
end)
elseif self.character == 'bard' then
self.bard_counter = 0
self.attack_sensor = Circle(self.x, self.y, 64)
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')
elseif self.character == 'assassin' then
self.attack_sensor = Circle(self.x, self.y, 64)
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), {pierce = 1000})
end
end, nil, nil, 'shoot')
elseif self.character == 'host' then
if self.level == 3 then
self.t:every(1, function()
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
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 = 10, dmg = self.dmg, parent = self}
end
end)
else
self.t:every(2, function()
critter1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
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, parent = self}
end)
end
end
self:calculate_stats(true)
@ -598,7 +502,7 @@ function Player:hit(damage)
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}
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, parent = self}
end
end)
end
@ -721,13 +625,12 @@ function Player:shoot(r, mods)
local dmg_m = 1
local crit = false
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}
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, parent = self}
end
end)
end
@ -793,6 +696,22 @@ function Player:shoot(r, mods)
Projectile(table.merge(t, mods or {}))
end
if self.character == 'bard' then
self.bard_counter = self.bard_counter + 1
if self.bard_counter == 8 then
self.bard_counter = 0
bard2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.t:after(3, function()
bard1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
local enemies = main.current.main:get_objects_by_classes(main.current.enemies)
for _, enemy in ipairs(enemies) do
enemy:hit(4*self.dmg)
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.2}
end
end)
end
end
if self.character == 'vagrant' then
shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.2}
elseif self.character == 'dual_gunner' then
@ -802,7 +721,7 @@ function Player:shoot(r, mods)
archer1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
elseif self.character == 'wizard' or self.character == 'lich' 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' then
elseif self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'spellblade' or self.character == 'bard' or self.character == 'assassin' then
_G[random:table{'scout1', 'scout2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.35}
if self.character == 'spellblade' then
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
@ -833,6 +752,8 @@ function Player:attack(area, mods)
_G[random:table{'swordsman1', 'swordsman2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.75}
elseif self.character == 'elementor' then
elementor1:play{pitch = random:float(0.9, 1.1), volume = 0.5}
elseif self.character == 'launcher' then
buff1:play{pitch == random:float(0.9, 1.1), volume = 0.5}
end
if self.character == 'juggernaut' then
@ -1046,7 +967,7 @@ function Projectile:on_collision_enter(other, contact)
self.ricochet = self.ricochet - 1
end
_G[random:table{'arrow_hit_wall1', 'arrow_hit_wall2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.2}
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' or self.character == 'bard' then
self:die(x, y, r, 0)
knife_hit_wall1:play{pitch = random:float(0.9, 1.1), volume = 0.2}
local r = Unit.bounce(self, nx, ny)
@ -1107,7 +1028,8 @@ function Projectile:on_trigger_enter(other, contact)
HitParticle{group = main.current.effects, x = self.x, y = self.y, color = other.color}
end
if self.character == 'archer' or self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'hunter' or self.character == 'spellblade' or self.character == 'engineer' then
if self.character == 'archer' or self.character == 'scout' or self.character == 'outlaw' or self.character == 'blade' or self.character == 'hunter' or self.character == 'spellblade' or self.character == 'engineer' or
self.character == 'bard' or self.character == 'assassin' then
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
if self.character == 'spellblade' then
magic_area1:play{pitch = random:float(0.95, 1.05), volume = 0.15}
@ -1141,6 +1063,14 @@ function Projectile:on_trigger_enter(other, contact)
end)
end
if self.character == 'bard' then
other:curse('bard')
end
if self.character == 'assassin' then
other:apply_dot(self.crit and 4*self.dmg or self.dmg/2, 3)
end
if self.parent.chain_infused then
local units = self.parent:get_all_units()
local stormweaver_level = 0
@ -1193,6 +1123,8 @@ function Area:init(args)
enemy:hit(self.dmg + self.dmg*0.33*#enemies)
elseif self.character == 'blade' and self.level == 3 then
enemy:hit(self.dmg + self.dmg*0.5*#enemies)
elseif self.character == 'launcher' then
enemy:curse('launcher', 4, (self.level == 3 and 6*self.dmg or 2*self.dmg))
else
enemy:hit(self.dmg)
end
@ -1577,6 +1509,7 @@ function Critter:init(args)
self.invulnerable = true
self.t:after(0.5, function() self.invulnerable = false end)
self.dmg = self.parent.dmg
self.hp = 1
end

10
todo
View File

@ -68,12 +68,12 @@
* 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: 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
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
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
Host [conjurer, swarmer]: creates overlords that periodically spawn small critters - Lv.3: Invasion - increased critter spawn rate
* 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
* 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
* Host [swarmer]: creates overlords that periodically spawn small critters - Lv.3: Invasion - increased critter spawn rate
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 [curser, voider]: creates a large area that curses enemies to take increased DoT - Lv.3: Nightmare - the area also deals DoT and slows enemies
Bane [curser, voider]: creates a large area that curses enemies to take increased damage - 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
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
Highlander [warrior]: creates a small area that deals massive damage - Lv.3: Crosscut - two crosscutting areas of larger size are created instead