Day 46
parent
129d7f1a06
commit
6322307525
104
arena.lua
104
arena.lua
|
@ -74,6 +74,36 @@ function Arena:on_enter(from, level, units)
|
|||
-- self.level_1000_text2 = Text2{group = self.ui, x = gw/2, y = gh/2 + 64, lines = {{text = '[fg, wavy_mid]SNKRX', font = pixul_font, alignment = 'center'}}}
|
||||
-- Wall{group = self.main, vertices = math.to_rectangle_vertices(gw/2 - 0.45*self.level_1000_text.w, gh/2 - 0.3*self.level_1000_text.h, gw/2 + 0.45*self.level_1000_text.w, gh/2 - 3), snkrx = true, color = bg[-1]}
|
||||
|
||||
elseif self.level == 6 or self.level == 12 or self.level == 18 or self.level == 24 or self.level == 25 then
|
||||
self.boss_level = true
|
||||
self.start_time = 3
|
||||
self.t:after(1, function()
|
||||
self.t:every(1, function()
|
||||
if self.start_time > 1 then alert1:play{volume = 0.5} end
|
||||
self.start_time = self.start_time - 1
|
||||
self.hfx:use('condition1', 0.25, 200, 10)
|
||||
end, 3, function()
|
||||
alert1:play{pitch = 1.2, volume = 0.5}
|
||||
camera:shake(4, 0.25)
|
||||
SpawnEffect{group = self.effects, x = gw/2, y = gh/2 - 48}
|
||||
SpawnEffect{group = self.effects, x = gw/2, y = gh/2, action = function(x, y)
|
||||
spawn1:play{pitch = random:float(0.8, 1.2), volume = 0.15}
|
||||
self.boss = Seeker{group = self.main, x = x, y = y, character = 'seeker', level = self.level, boss = boss_by_level[self.level]}
|
||||
end}
|
||||
self.t:every(function() return #self.main:get_objects_by_classes(self.enemies) <= 1 end, function()
|
||||
self.hfx:use('condition1', 0.25, 200, 10)
|
||||
self.hfx:pull('condition2', 0.0625)
|
||||
self.t:after(0.5, function()
|
||||
local spawn_type = random:table{'left', 'middle', 'right'}
|
||||
local spawn_points = {left = {x = self.x1 + 32, y = gh/2}, middle = {x = gw/2, y = gh/2}, right = {x = self.x2 - 32, y = gh/2}}
|
||||
local p = spawn_points[spawn_type]
|
||||
SpawnMarker{group = self.effects, x = p.x, y = p.y}
|
||||
self.t:after(0.75, function() self:spawn_n_enemies(p, nil, 8 + math.floor(self.level/2)) end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
self.t:every(function() return #self.main:get_objects_by_classes(self.enemies) <= 0 end, function() self.can_quit = true end)
|
||||
end)
|
||||
else
|
||||
-- Set win condition and enemy spawns
|
||||
self.win_condition = random:table{'time', 'enemy_kill', 'wave'}
|
||||
|
@ -254,6 +284,13 @@ end
|
|||
|
||||
|
||||
function Arena:update(dt)
|
||||
if input.k.pressed then
|
||||
SpawnEffect{group = self.effects, x = gw/2, y = gh/2, action = function(x, y)
|
||||
spawn1:play{pitch = random:float(0.8, 1.2), volume = 0.15}
|
||||
Seeker{group = self.main, x = x, y = y, character = 'seeker', level = self.level, boss = 'forcer'}
|
||||
end}
|
||||
end
|
||||
|
||||
if input.escape.pressed and not self.transitioning then
|
||||
if not self.paused then
|
||||
trigger:tween(0.25, _G, {slow_amount = 0}, math.linear, function()
|
||||
|
@ -320,11 +357,6 @@ function Arena:update(dt)
|
|||
self:update_game_object(dt*slow_amount)
|
||||
-- cascade_instance.pitch = math.clamp(slow_amount*self.main_slow_amount, 0.05, 1)
|
||||
|
||||
if input.k.pressed then
|
||||
local enemies = self.main:get_objects_by_classes(self.enemies)
|
||||
for _, enemy in ipairs(enemies) do enemy:hit(1000000000000) end
|
||||
end
|
||||
|
||||
if self.enchanter_level == 1 then self.enchanter_dmg_m = 1.25
|
||||
else self.enchanter_dmg_m = 1 end
|
||||
|
||||
|
@ -413,33 +445,41 @@ function Arena:draw()
|
|||
graphics.pop()
|
||||
end
|
||||
|
||||
if self.win_condition then
|
||||
if self.win_condition == 'time' then
|
||||
if self.start_time <= 0 then
|
||||
graphics.push(self.x2 - 66, self.y1 - 9, 0, self.hfx.condition2.x, self.hfx.condition2.x)
|
||||
graphics.print_centered('time left:', fat_font, self.x2 - 66, self.y1 - 9, 0, 0.6, 0.6, nil, nil, fg[0])
|
||||
graphics.pop()
|
||||
graphics.push(self.x2 - 18 + fat_font:get_text_width(tostring(self.time_left))/2, self.y1 - 8, 0, self.hfx.condition1.x, self.hfx.condition1.x)
|
||||
graphics.print(tostring(self.time_left), fat_font, self.x2 - 18, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
|
||||
graphics.pop()
|
||||
end
|
||||
elseif self.win_condition == 'wave' then
|
||||
if self.start_time <= 0 then
|
||||
graphics.push(self.x2 - 50, self.y1 - 10, 0, self.hfx.condition2.x, self.hfx.condition2.x)
|
||||
graphics.print_centered('wave:', fat_font, self.x2 - 50, self.y1 - 10, 0, 0.6, 0.6, nil, nil, fg[0])
|
||||
graphics.pop()
|
||||
graphics.push(self.x2 - 25 + fat_font:get_text_width(self.wave .. '/' .. self.max_waves)/2, self.y1 - 8, 0, self.hfx.condition1.x, self.hfx.condition1.x)
|
||||
graphics.print(self.wave .. '/' .. self.max_waves, fat_font, self.x2 - 25, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
|
||||
graphics.pop()
|
||||
end
|
||||
elseif self.win_condition == 'enemy_kill' then
|
||||
if self.start_time <= 0 then
|
||||
graphics.push(self.x2 - 106, self.y1 - 10, 0, self.hfx.condition2.x, self.hfx.condition2.x)
|
||||
graphics.print_centered('enemies killed:', fat_font, self.x2 - 106, self.y1 - 10, 0, 0.6, 0.6, nil, nil, fg[0])
|
||||
graphics.pop()
|
||||
graphics.push(self.x2 - 41 + fat_font:get_text_width(self.enemies_killed .. '/' .. self.enemies_to_kill)/2, self.y1 - 8, 0, self.hfx.condition1.x, self.hfx.condition1.x)
|
||||
graphics.print(self.enemies_killed .. '/' .. self.enemies_to_kill, fat_font, self.x2 - 41, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
|
||||
graphics.pop()
|
||||
if self.boss_level then
|
||||
if self.start_time <= 0 then
|
||||
graphics.push(self.x2 - 106, self.y1 - 10, 0, self.hfx.condition2.x, self.hfx.condition2.x)
|
||||
graphics.print_centered('kill the elite', fat_font, self.x2 - 106, self.y1 - 10, 0, 0.6, 0.6, nil, nil, fg[0])
|
||||
graphics.pop()
|
||||
end
|
||||
else
|
||||
if self.win_condition then
|
||||
if self.win_condition == 'time' then
|
||||
if self.start_time <= 0 then
|
||||
graphics.push(self.x2 - 66, self.y1 - 9, 0, self.hfx.condition2.x, self.hfx.condition2.x)
|
||||
graphics.print_centered('time left:', fat_font, self.x2 - 66, self.y1 - 9, 0, 0.6, 0.6, nil, nil, fg[0])
|
||||
graphics.pop()
|
||||
graphics.push(self.x2 - 18 + fat_font:get_text_width(tostring(self.time_left))/2, self.y1 - 8, 0, self.hfx.condition1.x, self.hfx.condition1.x)
|
||||
graphics.print(tostring(self.time_left), fat_font, self.x2 - 18, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
|
||||
graphics.pop()
|
||||
end
|
||||
elseif self.win_condition == 'wave' then
|
||||
if self.start_time <= 0 then
|
||||
graphics.push(self.x2 - 50, self.y1 - 10, 0, self.hfx.condition2.x, self.hfx.condition2.x)
|
||||
graphics.print_centered('wave:', fat_font, self.x2 - 50, self.y1 - 10, 0, 0.6, 0.6, nil, nil, fg[0])
|
||||
graphics.pop()
|
||||
graphics.push(self.x2 - 25 + fat_font:get_text_width(self.wave .. '/' .. self.max_waves)/2, self.y1 - 8, 0, self.hfx.condition1.x, self.hfx.condition1.x)
|
||||
graphics.print(self.wave .. '/' .. self.max_waves, fat_font, self.x2 - 25, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
|
||||
graphics.pop()
|
||||
end
|
||||
elseif self.win_condition == 'enemy_kill' then
|
||||
if self.start_time <= 0 then
|
||||
graphics.push(self.x2 - 106, self.y1 - 10, 0, self.hfx.condition2.x, self.hfx.condition2.x)
|
||||
graphics.print_centered('enemies killed:', fat_font, self.x2 - 106, self.y1 - 10, 0, 0.6, 0.6, nil, nil, fg[0])
|
||||
graphics.pop()
|
||||
graphics.push(self.x2 - 41 + fat_font:get_text_width(self.enemies_killed .. '/' .. self.enemies_to_kill)/2, self.y1 - 8, 0, self.hfx.condition1.x, self.hfx.condition1.x)
|
||||
graphics.print(self.enemies_killed .. '/' .. self.enemies_to_kill, fat_font, self.x2 - 41, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
|
||||
graphics.pop()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Binary file not shown.
|
@ -780,3 +780,9 @@ Added a spawn marker so that it's easier for the player to tell where enemies ar
|
|||
* yellow - Resistance to knockback and increased HP
|
||||
* white - Remain static and shoot projectiles
|
||||
* purple - Explodes into critters on death
|
||||
|
||||
# Day 46 - 03/04/21
|
||||
|
||||
* Adding mini bosses
|
||||
* Speed Booster - grants speed boost to nearby enemies
|
||||
* Forcer - pulls enemies together into a point and pushes them out
|
||||
|
|
122
enemies.lua
122
enemies.lua
|
@ -5,15 +5,80 @@ Seeker:implement(Unit)
|
|||
function Seeker:init(args)
|
||||
self:init_game_object(args)
|
||||
self:init_unit()
|
||||
self:set_as_rectangle(14, 6, 'dynamic', 'enemy')
|
||||
self:set_restitution(0.5)
|
||||
|
||||
self.color = red[0]:clone()
|
||||
self.classes = {'seeker'}
|
||||
self:calculate_stats(true)
|
||||
self:set_as_steerable(self.v, 2000, 4*math.pi, 4)
|
||||
if self.boss then
|
||||
self:set_as_rectangle(18, 7, 'dynamic', 'enemy')
|
||||
self:set_restitution(0.5)
|
||||
self.classes = {'mini_boss'}
|
||||
self:calculate_stats(true)
|
||||
self:set_as_steerable(self.v, 1000, 2*math.pi, 2)
|
||||
|
||||
self.spawner = random:bool(25)
|
||||
if self.boss == 'speed_booster' then
|
||||
self.color = green[0]:clone()
|
||||
self.t:every(5, function()
|
||||
local enemies = self:get_objects_in_shape(Circle(self.x, self.y, 128), main.current.enemies)
|
||||
if #enemies > 0 then
|
||||
buff1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 6, color = green[0], duration = 0.1}
|
||||
for _, enemy in ipairs(enemies) do
|
||||
LightningLine{group = main.current.effects, src = self, dst = enemy, color = green[0]}
|
||||
enemy:speed_boost(3 + self.level*0.1)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
elseif self.boss == 'forcer' then
|
||||
self.color = yellow[0]:clone()
|
||||
self.t:every(6, function()
|
||||
local enemies = main.current.main:get_objects_by_classes(main.current.enemies)
|
||||
local x, y = 0, 0
|
||||
if #enemies > 0 then
|
||||
for _, enemy in ipairs(enemies) do
|
||||
x = x + enemy.x
|
||||
y = y + enemy.y
|
||||
end
|
||||
x = x/#enemies
|
||||
y = y/#enemies
|
||||
else
|
||||
x, y = player.x, player.y
|
||||
end
|
||||
self.px, self.py = x + random:float(-16, 16), y + random:float(-16, 16)
|
||||
self.pull_sensor = Circle(self.px, self.py, 160)
|
||||
self.prs = 0
|
||||
self.t:tween(0.05, self, {prs = 4}, math.cubic_in_out, function() self.spring:pull(0.15) end)
|
||||
self.t:after(2 - 0.05*7, function()
|
||||
self.t:every_immediate(0.05, function() self.phidden = not self.phidden end, 7)
|
||||
end)
|
||||
self.color_transparent = Color(yellow[0].r, yellow[0].g, yellow[0].b, 0.08)
|
||||
self.t:every(0.08, function() HitParticle{group = main.current.effects, x = self.px, y = self.py, color = yellow[0]} end, math.floor(2/0.08))
|
||||
self.vr = 0
|
||||
self.dvr = random:float(-math.pi/4, math.pi/4)
|
||||
|
||||
force1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
self.t:during(2, function(dt)
|
||||
local enemies = self:get_objects_in_shape(self.pull_sensor, main.current.enemies)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
enemy:apply_steering_force(math.remap(enemy:distance_to_point(self.px, self.py), 0, 160, 400, 200), enemy:angle_to_point(self.px, self.py))
|
||||
end
|
||||
self.vr = self.vr + self.dvr*dt
|
||||
end, function()
|
||||
wizard1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
local enemies = self:get_objects_in_shape(self.pull_sensor, main.current.enemies)
|
||||
for _, enemy in ipairs(enemies) do
|
||||
enemy:push(random:float(40, 80), enemy:angle_to_object(main.current.player), true)
|
||||
end
|
||||
self.px, self.py = nil, nil
|
||||
end)
|
||||
end)
|
||||
end
|
||||
else
|
||||
self:set_as_rectangle(14, 6, 'dynamic', 'enemy')
|
||||
self:set_restitution(0.5)
|
||||
self.color = red[0]:clone()
|
||||
self.classes = {'seeker'}
|
||||
self:calculate_stats(true)
|
||||
self:set_as_steerable(self.v, 2000, 4*math.pi, 4)
|
||||
end
|
||||
|
||||
--[[
|
||||
if random:bool(35) then
|
||||
|
@ -99,6 +164,7 @@ function Seeker:update(dt)
|
|||
if self.being_pushed then
|
||||
local v = math.length(self:get_velocity())
|
||||
if v < 25 then
|
||||
if self.push_invulnerable then self.push_invulnerable = false end
|
||||
self.being_pushed = false
|
||||
self.steering_enabled = true
|
||||
self:set_damping(0)
|
||||
|
@ -110,8 +176,25 @@ function Seeker:update(dt)
|
|||
self:rotate_towards_object(main.current.player, 0.5)
|
||||
elseif not self.headbutting then
|
||||
local player = main.current.player
|
||||
self:seek_point(player.x, player.y)
|
||||
self:wander(50, 100, 20)
|
||||
if self.boss then
|
||||
local enemies = main.current.main:get_objects_by_classes(main.current.enemies)
|
||||
local x, y = 0, 0
|
||||
if #enemies > 0 then
|
||||
for _, enemy in ipairs(enemies) do
|
||||
x = x + enemy.x
|
||||
y = y + enemy.y
|
||||
end
|
||||
x = x/#enemies
|
||||
y = y/#enemies
|
||||
else
|
||||
x, y = player.x, player.y
|
||||
end
|
||||
self:seek_point(x, y)
|
||||
self:wander(10, 250, 3)
|
||||
else
|
||||
self:seek_point(player.x, player.y)
|
||||
self:wander(50, 100, 20)
|
||||
end
|
||||
self:steering_separate(16, main.current.enemies)
|
||||
self:rotate_towards_velocity(0.5)
|
||||
end
|
||||
|
@ -124,8 +207,22 @@ end
|
|||
|
||||
function Seeker:draw()
|
||||
graphics.push(self.x, self.y, self.r, self.hfx.hit.x, self.hfx.hit.x)
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 3, 3, self.hfx.hit.f and fg[0] or self.color)
|
||||
if self.boss then
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 4, 4, self.hfx.hit.f and fg[0] or self.color)
|
||||
else
|
||||
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 3, 3, self.hfx.hit.f and fg[0] or self.color)
|
||||
end
|
||||
graphics.pop()
|
||||
|
||||
if self.px and self.py then
|
||||
if self.phidden then return end
|
||||
graphics.push(self.px, self.py, self.vr, self.spring.x, self.spring.x)
|
||||
graphics.circle(self.px, self.py, self.prs + random:float(-1, 1), yellow[0])
|
||||
graphics.circle(self.px, self.py, self.pull_sensor.rs, self.color_transparent)
|
||||
local lw = math.remap(self.pull_sensor.rs, 32, 256, 2, 4)
|
||||
for i = 1, 4 do graphics.arc('open', self.px, self.py, 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, yellow[0], lw) end
|
||||
graphics.pop()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -163,6 +260,7 @@ end
|
|||
function Seeker:hit(damage, projectile)
|
||||
if self.dead then return end
|
||||
self.hfx:use('hit', 0.25, 200, 10)
|
||||
if self.push_invulnerable then return end
|
||||
self:show_hp()
|
||||
|
||||
local actual_damage = self:calculate_damage(damage)
|
||||
|
@ -208,9 +306,11 @@ function Seeker:hit(damage, projectile)
|
|||
end
|
||||
|
||||
|
||||
function Seeker:push(f, r)
|
||||
function Seeker:push(f, r, push_invulnerable)
|
||||
local n = 1
|
||||
if self.tank then n = 0.4 - 0.01*self.level end
|
||||
if self.boss then n = 0.1 end
|
||||
self.push_invulnerable = push_invulnerable
|
||||
self.push_force = n*f
|
||||
self.being_pushed = true
|
||||
self.steering_enabled = false
|
||||
|
|
|
@ -231,8 +231,9 @@ function Trigger:update(dt)
|
|||
trigger.last_condition = condition
|
||||
|
||||
elseif trigger.type == "during" then
|
||||
trigger.action()
|
||||
trigger.action(dt)
|
||||
if trigger.timer > trigger.delay then
|
||||
trigger.after()
|
||||
self.triggers[tag] = nil
|
||||
end
|
||||
|
||||
|
|
17
main.lua
17
main.lua
|
@ -27,6 +27,7 @@ function init()
|
|||
headbutt1 = Sound('Wind Bolt 14.ogg', s)
|
||||
critter1 = Sound('Critters eating 2.ogg', s)
|
||||
critter2 = Sound('Crickets Chirping 4.ogg', s)
|
||||
force1 = Sound('Magical Impact 18.ogg', s)
|
||||
error1 = Sound('Error 2.ogg', s)
|
||||
coins1 = Sound('Coins 7.ogg', s)
|
||||
coins2 = Sound('Coins 8.ogg', s)
|
||||
|
@ -263,6 +264,7 @@ function init()
|
|||
['enchanter'] = {hp = 1.2, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1.2, mvspd = 1.2},
|
||||
['psy'] = {hp = 1.5, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 0.5, mvspd = 1},
|
||||
['seeker'] = {hp = 0.5, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.3},
|
||||
['mini_boss'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.3},
|
||||
['enemy_critter'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 0.5},
|
||||
['saboteur'] = {hp = 1, dmg = 1, aspd = 1, area_dmg = 1, area_size = 1, def = 1, mvspd = 1.4},
|
||||
}
|
||||
|
@ -414,6 +416,14 @@ function init()
|
|||
[25] = {100, 100},
|
||||
}
|
||||
|
||||
boss_by_level = {
|
||||
[6] = 'speed_booster',
|
||||
[12] = 'exploder',
|
||||
[18] = 'swarmer',
|
||||
[24] = 'bouncer',
|
||||
[25] = 'orbitter',
|
||||
}
|
||||
|
||||
gold = 2
|
||||
|
||||
main = Main()
|
||||
|
@ -453,13 +463,6 @@ function update(dt)
|
|||
music.volume = 0.5
|
||||
end
|
||||
end
|
||||
|
||||
if input.k.pressed then
|
||||
print(steam.user.getPlayerSteamLevel())
|
||||
print(steam.user.getSteamID())
|
||||
print(steam.friends.getFriendPersonaName(steam.user.getSteamID()))
|
||||
print(steam.utils.getAppID())
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
18
objects.lua
18
objects.lua
|
@ -227,11 +227,19 @@ function Unit:calculate_stats(first_run)
|
|||
self.base_dmg = 10*math.pow(2, self.level-1)
|
||||
self.base_mvspd = 75
|
||||
elseif self:is(Seeker) then
|
||||
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}
|
||||
self.base_hp = 50 + 55*y[x]
|
||||
self.base_dmg = 10 + 3*y[x]
|
||||
self.base_mvspd = 70 + 3*y[x]
|
||||
if self.boss then
|
||||
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}
|
||||
self.base_hp = 250 + 275*y[x]
|
||||
self.base_dmg = 50 + 15*y[x]
|
||||
self.base_mvspd = 35 + 1.5*y[x]
|
||||
else
|
||||
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}
|
||||
self.base_hp = 50 + 55*y[x]
|
||||
self.base_dmg = 10 + 3*y[x]
|
||||
self.base_mvspd = 70 + 3*y[x]
|
||||
end
|
||||
elseif self:is(Saboteur) then
|
||||
self.base_hp = 100*math.pow(2, self.level-1)
|
||||
self.base_dmg = 10*math.pow(2, self.level-1)
|
||||
|
|
9
todo
9
todo
|
@ -7,7 +7,7 @@
|
|||
* Psykeeper: stores damage taken by all allies up to 50% its max HP and redistributes it as healing
|
||||
* Squire: +5%/10%/15% damage and defense to all allies
|
||||
|
||||
7. Enemy modifiers
|
||||
* 7. Enemy modifiers
|
||||
* green - Grant nearby enemies a speed boost on death
|
||||
* blue - Explode into projectiles on death
|
||||
* orange - Charge up and headbutt towards the player at increased speed and damage
|
||||
|
@ -16,8 +16,11 @@
|
|||
* purple - Explodes into critters on death
|
||||
|
||||
6. Mini boss every 3rd level
|
||||
This is just a special enemy with more HP and ability to buff nearby enemies with modifiers, no additional AI or attack patterns
|
||||
... aiming for ~5 different modifier combos that the boss uses
|
||||
* Speed Booster - grants speed boost to nearby enemies
|
||||
Swarmer - explodes enemies into a swarm of critters
|
||||
Exploder - explodes enemies into projectiles
|
||||
* Forcer - pulls enemies together into a point and pushes them out
|
||||
Orbitter - spawns shooters that orbit the boss
|
||||
|
||||
8. Additional characters and classes
|
||||
9. Lv.3 effects for every character
|
||||
|
|
Loading…
Reference in New Issue