Day 44
parent
a766914dc7
commit
32cb666cd3
|
@ -31,6 +31,7 @@ function Arena:on_enter(from, level, units)
|
|||
self.main:disable_collision_between('enemy_projectile', 'enemy_projectile')
|
||||
self.main:enable_trigger_between('projectile', 'enemy')
|
||||
self.main:enable_trigger_between('enemy_projectile', 'player')
|
||||
self.main:enable_trigger_between('player', 'enemy_projectile')
|
||||
|
||||
self.damage_dealt = 0
|
||||
self.damage_taken = 0
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -31,15 +31,15 @@ function BuyScreen:on_enter(from, level, units)
|
|||
self.units = units
|
||||
camera.x, camera.y = gw/2, gh/2
|
||||
|
||||
steam.friends.setRichPresence('steam_display', '#StatusFull')
|
||||
steam.friends.setRichPresence('text', 'Shop - Level ' .. self.level)
|
||||
|
||||
if self.level == 0 then
|
||||
cascade_instance = cascade:play{volume = 0.5, loop = true}
|
||||
self.level = 1
|
||||
self.first_screen = true
|
||||
end
|
||||
|
||||
steam.friends.setRichPresence('steam_display', '#StatusFull')
|
||||
steam.friends.setRichPresence('text', 'Shop - Level ' .. self.level)
|
||||
|
||||
self.main = Group()
|
||||
self.effects = Group()
|
||||
self.ui = Group()
|
||||
|
@ -153,9 +153,19 @@ end
|
|||
function BuyScreen:set_cards(level, dont_spawn_effect)
|
||||
if self.cards then for i = 1, 3 do if self.cards[i] then self.cards[i]:die(dont_spawn_effect) end end end
|
||||
self.cards = {}
|
||||
self.cards[1] = ShopCard{group = self.main, x = 60, y = 75, w = 80, h = 90, unit = random:table(tier_to_characters[random:weighted_pick(unpack(level_to_tier_weights[level or self.level]))]), parent = self, i = 1}
|
||||
self.cards[2] = ShopCard{group = self.main, x = 140, y = 75, w = 80, h = 90, unit = random:table(tier_to_characters[random:weighted_pick(unpack(level_to_tier_weights[level or self.level]))]), parent = self, i = 2}
|
||||
self.cards[3] = ShopCard{group = self.main, x = 220, y = 75, w = 80, h = 90, unit = random:table(tier_to_characters[random:weighted_pick(unpack(level_to_tier_weights[level or self.level]))]), parent = self, i = 3}
|
||||
local all_units = {}
|
||||
local unit_1
|
||||
local unit_2
|
||||
local unit_3
|
||||
repeat
|
||||
unit_1 = random:table(tier_to_characters[random:weighted_pick(unpack(level_to_tier_weights[level or self.level]))])
|
||||
unit_2 = random:table(tier_to_characters[random:weighted_pick(unpack(level_to_tier_weights[level or self.level]))])
|
||||
unit_3 = random:table(tier_to_characters[random:weighted_pick(unpack(level_to_tier_weights[level or self.level]))])
|
||||
all_units = {unit_1, unit_2, unit_3}
|
||||
until not table.all(all_units, function(v) return table.any(non_attacking_characters, function(u) return v == u end) end)
|
||||
self.cards[1] = ShopCard{group = self.main, x = 60, y = 75, w = 80, h = 90, unit = unit_1, parent = self, i = 1}
|
||||
self.cards[2] = ShopCard{group = self.main, x = 140, y = 75, w = 80, h = 90, unit = unit_2, parent = self, i = 2}
|
||||
self.cards[3] = ShopCard{group = self.main, x = 220, y = 75, w = 80, h = 90, unit = unit_3, parent = self, i = 3}
|
||||
end
|
||||
|
||||
|
||||
|
|
14
devlog.md
14
devlog.md
|
@ -759,3 +759,17 @@ objects and the last thing I need is random bugs because a function or variable
|
|||
# Day 42 - 30/03/21
|
||||
|
||||
Added a spawn marker so that it's easier for the player to tell where enemies are spawning and to give a chance to avoid unfair deaths. Slowly getting back into it now...
|
||||
|
||||
# Day 44 - 01/04/21
|
||||
|
||||
* Added a spawn marker before enemies spawn to help with avoiding enemies spawning on top of the player
|
||||
* Prevent spawning of units that cost 3 or more gold on the first level
|
||||
* Prevent spawning of only units that don't attack on the first level
|
||||
* Reworked position based units so that position in the snake doesn't matter anymore
|
||||
* Chronomancer now gives +10/20/30% attack speed to all allies
|
||||
* Psykeeper now stores damage taken by all allies up to 10/20/30% its max HP and redistributes it as healing
|
||||
* Squire now gives +5/10/15% damage and defense to all allies
|
||||
* Added 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
|
||||
|
|
101
enemies.lua
101
enemies.lua
|
@ -8,10 +8,49 @@ function Seeker:init(args)
|
|||
self:set_as_rectangle(14, 6, 'dynamic', 'enemy')
|
||||
self:set_restitution(0.5)
|
||||
|
||||
self.color = red[0]
|
||||
self.color = red[0]:clone()
|
||||
self.classes = {'seeker'}
|
||||
self:calculate_stats(true)
|
||||
self:set_as_steerable(self.v, 2000, 4*math.pi, 4)
|
||||
|
||||
if random:bool(35) then
|
||||
local n = random:int(1, 3)
|
||||
self.speed_booster = n == 1
|
||||
self.exploder = n == 2
|
||||
self.headbutter = n == 3
|
||||
end
|
||||
|
||||
if self.speed_booster then
|
||||
self.color = green[0]:clone()
|
||||
self.area_sensor = Circle(self.x, self.y, 128)
|
||||
elseif self.exploder then
|
||||
self.color = blue[0]:clone()
|
||||
elseif self.headbutter then
|
||||
self.color = orange[0]:clone()
|
||||
self.last_headbutt_time = 0
|
||||
self.t:every(function() return math.distance(self.x, self.y, main.current.player.x, main.current.player.y) < 64 and love.timer.getTime() - self.last_headbutt_time > 10 end, function()
|
||||
if self.headbutt_charging or self.headbutting then return end
|
||||
self.headbutt_charging = true
|
||||
self.t:tween(2, self.color, {r = fg[0].r, b = fg[0].b, g = fg[0].g}, math.cubic_in_out, function()
|
||||
self.t:tween(0.25, self.color, {r = orange[0].r, b = orange[0].b, g = orange[0].g}, math.linear)
|
||||
self.headbutt_charging = false
|
||||
headbutt1:play{pitch = random:float(0.95, 1.05), volume = 0.2}
|
||||
self.headbutting = true
|
||||
self.last_headbutt_time = love.timer.getTime()
|
||||
self:set_damping(0)
|
||||
self:apply_steering_impulse(300, self:angle_to_object(main.current.player), 0.75)
|
||||
self.t:after(0.75, function()
|
||||
self.headbutting = false
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
elseif self.tank then
|
||||
self.color = yellow[0]:clone()
|
||||
elseif self.shooter then
|
||||
self.color = white[0]:clone()
|
||||
elseif self.spawner then
|
||||
self.color = purple[0]:clone()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -21,6 +60,15 @@ function Seeker:update(dt)
|
|||
if main.current.mage_level == 2 then self.buff_def_a = -30
|
||||
elseif main.current.mage_level == 1 then self.buff_def_a = -15
|
||||
else self.buff_def_a = 0 end
|
||||
if self.speed_boosting then
|
||||
local n = math.remap(love.timer.getTime() - self.speed_boosting, 0, 3, 1, 0.5)
|
||||
self.buff_mvspd_m = (3 + 0.1*self.level)*n
|
||||
if not self.speed_booster and not self.exploder and not self.headbutter and not self.tank and not self.shooter and not self.spawner then
|
||||
self.color.r = math.remap(n, 1, 0.5, green[0].r, red[0].r)
|
||||
self.color.g = math.remap(n, 1, 0.5, green[0].g, red[0].g)
|
||||
self.color.b = math.remap(n, 1, 0.5, green[0].b, red[0].b)
|
||||
end
|
||||
end
|
||||
self:calculate_stats()
|
||||
|
||||
if self.being_pushed then
|
||||
|
@ -32,13 +80,20 @@ function Seeker:update(dt)
|
|||
self:set_angular_damping(0)
|
||||
end
|
||||
else
|
||||
local player = main.current.player
|
||||
self:seek_point(player.x, player.y)
|
||||
self:wander(50, 100, 20)
|
||||
self:steering_separate(16, main.current.enemies)
|
||||
self:rotate_towards_velocity(0.5)
|
||||
if self.headbutt_charging then
|
||||
self:set_damping(10)
|
||||
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)
|
||||
self:steering_separate(16, main.current.enemies)
|
||||
self:rotate_towards_velocity(0.5)
|
||||
end
|
||||
end
|
||||
self.r = self:get_angle()
|
||||
|
||||
if self.area_sensor then self.area_sensor:move_to(self.x, self.y) end
|
||||
end
|
||||
|
||||
|
||||
|
@ -64,6 +119,12 @@ function Seeker:on_collision_enter(other, contact)
|
|||
HitCircle{group = main.current.effects, x = x, y = y, rs = 6, color = fg[0], duration = 0.1}
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = x, y = y, color = self.color} end
|
||||
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
|
||||
elseif self.headbutting then
|
||||
other:push(math.length(self:get_velocity())/4, other:angle_to_object(self))
|
||||
HitCircle{group = main.current.effects, x = x, y = y, rs = 6, color = fg[0], duration = 0.1}
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = x, y = y, color = self.color} end
|
||||
hit2:play{pitch = random:float(0.95, 1.05), volume = 0.35}
|
||||
end
|
||||
|
||||
elseif other:is(Turret) then
|
||||
|
@ -88,6 +149,27 @@ function Seeker:hit(damage)
|
|||
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 12}:scale_down(0.3):change_color(0.5, self.color)
|
||||
main.current:enemy_killed()
|
||||
_G[random:table{'enemy_die1', 'enemy_die2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.5}
|
||||
|
||||
if self.speed_booster then
|
||||
local enemies = self:get_objects_in_shape(self.area_sensor, 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)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.exploder then
|
||||
shoot1:play{pitch = random:float(0.95, 1.05), volume = 0.4}
|
||||
trigger:after(0.01, function()
|
||||
for i = 1, 16 do
|
||||
EnemyProjectile{group = main.current.main, x = self.x, y = self.y, color = blue[0], r = (i-1)*math.pi/8, v = 150 + 5*self.level, dmg = 2*self.dmg}
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -103,6 +185,12 @@ function Seeker:push(f, r)
|
|||
end
|
||||
|
||||
|
||||
function Seeker:speed_boost(duration)
|
||||
self.speed_boosting = love.timer.getTime()
|
||||
self.t:after(duration, function() self.speed_boosting = false end, 'speed_boost')
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
EnemyProjectile = Object:extend()
|
||||
|
@ -137,6 +225,7 @@ function EnemyProjectile:die(x, y, r, n)
|
|||
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
|
||||
proj_hit_wall1:play{pitch = random:float(0.9, 1.1), volume = 0.05}
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ function Physics:steering_update(dt)
|
|||
self.side = self.heading:perpendicular()
|
||||
end
|
||||
self.apply_force_f:set(0, 0)
|
||||
self.apply_impulse_f:set(0, 0)
|
||||
-- self.apply_impulse_f:set(0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
6
main.lua
6
main.lua
|
@ -24,6 +24,7 @@ function init()
|
|||
ui_switch2 = Sound('Switch 3.ogg', s)
|
||||
ui_transition1 = Sound('Wind Bolt 8.ogg', s)
|
||||
ui_transition2 = Sound('Wind Bolt 12.ogg', s)
|
||||
headbutt1 = Sound('Wind Bolt 14.ogg', s)
|
||||
error1 = Sound('Error 2.ogg', s)
|
||||
coins1 = Sound('Coins 7.ogg', s)
|
||||
coins2 = Sound('Coins 8.ogg', s)
|
||||
|
@ -58,6 +59,7 @@ function init()
|
|||
confirm1 = Sound('80921__justinbw__buttonchime02up.ogg', s)
|
||||
heal1 = Sound('Buff 3.ogg', s)
|
||||
spawn1 = Sound('Buff 13.ogg', s)
|
||||
buff1 = Sound('Buff 14.ogg', s)
|
||||
spawn_mark1 = Sound('Bonus 2.ogg', s)
|
||||
spawn_mark2 = Sound('Bonus.ogg', s)
|
||||
alert1 = Sound('Click.ogg', s)
|
||||
|
@ -282,6 +284,8 @@ function init()
|
|||
[3] = {'blade', 'outlaw', 'elementor', 'psykeeper', 'spellblade', 'engineer'},
|
||||
}
|
||||
|
||||
non_attacking_characters = {'cleric', 'stormweaver', 'squire', 'chronomancer', 'sage'}
|
||||
|
||||
character_tiers = {
|
||||
['vagrant'] = 1,
|
||||
['swordsman'] = 1,
|
||||
|
@ -352,7 +356,7 @@ function init()
|
|||
}
|
||||
|
||||
level_to_tier_weights = {
|
||||
[1] = {85, 10, 5},
|
||||
[1] = {90, 10, 0},
|
||||
[2] = {80, 15, 5},
|
||||
[3] = {75, 20, 5},
|
||||
[4] = {70, 20, 10},
|
||||
|
|
21
objects.lua
21
objects.lua
|
@ -48,11 +48,11 @@ function LightningLine:init(args)
|
|||
self.max_offset = 8
|
||||
self:generate()
|
||||
self.t:tween(0.1, self, {w = 1}, math.linear, function() self.dead = true end)
|
||||
self.color = blue[0]
|
||||
self.color = args.color or blue[0]
|
||||
HitCircle{group = main.current.effects, x = self.src.x, y = self.src.y, rs = 6, color = fg[0], duration = 0.1}
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = self.src.x, y = self.src.y, color = blue[0]} end
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = self.src.x, y = self.src.y, color = self.color} end
|
||||
HitCircle{group = main.current.effects, x = self.dst.x, y = self.dst.y, rs = 6, color = fg[0], duration = 0.1}
|
||||
HitParticle{group = main.current.effects, x = self.dst.x, y = self.dst.y, color = blue[0]}
|
||||
HitParticle{group = main.current.effects, x = self.dst.x, y = self.dst.y, color = self.color}
|
||||
end
|
||||
|
||||
|
||||
|
@ -214,20 +214,6 @@ function Unit:show_infused(n)
|
|||
end
|
||||
|
||||
|
||||
function Unit:show_squire(n)
|
||||
self.effect_bar.hidden = false
|
||||
self.effect_bar.color = purple[0]
|
||||
self.t:after(n or 4, function() self.effect_bar.hidden = false end, 'effect_bar')
|
||||
end
|
||||
|
||||
|
||||
function Unit:show_chronomancer(n)
|
||||
self.effect_bar.hidden = false
|
||||
self.effect_bar.color = purple[0]
|
||||
self.t:after(n or 2, function() self.effect_bar.hidden = false end, 'effect_bar')
|
||||
end
|
||||
|
||||
|
||||
function Unit:calculate_damage(dmg)
|
||||
if self.def >= 0 then dmg = dmg*(100/(100+self.def))
|
||||
else dmg = dmg*(2 - 100/(100+self.def)) end
|
||||
|
@ -300,6 +286,7 @@ function Unit:calculate_stats(first_run)
|
|||
self.def = (self.base_def + self.class_def_a + self.buff_def_a)*self.class_def_m*self.buff_def_m
|
||||
|
||||
for _, class in ipairs(self.classes) do self.class_mvspd_m = self.class_mvspd_m*class_stat_multipliers[class].mvspd end
|
||||
self.max_v = (self.base_mvspd + self.class_mvspd_a + self.buff_mvspd_a)*self.class_mvspd_m*self.buff_mvspd_m
|
||||
self.v = (self.base_mvspd + self.class_mvspd_a + self.buff_mvspd_a)*self.class_mvspd_m*self.buff_mvspd_m
|
||||
end
|
||||
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
Release Patch Notes
|
||||
|
||||
Added a spawn marker before enemies spawn to help with avoiding enemies spawning on top of the player
|
||||
Prevent spawning of units that cost 3 or more gold on the first level
|
||||
Prevent spawning of only units that don't attack on the first level
|
||||
Reworked position based units so that position in the snake doesn't matter anymore
|
||||
Chronomancer now gives +10/20/30% attack speed to all allies
|
||||
Psykeeper now stores damage taken by all allies up to 10/20/30% its max HP and redistributes it as healing
|
||||
Squire now gives +5/10/15% damage and defense to all allies
|
||||
Added 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
|
||||
|
|
126
player.lua
126
player.lua
|
@ -81,13 +81,10 @@ function Player:init(args)
|
|||
|
||||
self.last_heal_time = love.timer.getTime()
|
||||
self.t:every(2, function()
|
||||
local followers
|
||||
local leader = (self.leader and self) or self.parent
|
||||
if self.leader then followers = self.followers else followers = self.parent.followers end
|
||||
if (table.any(followers, function(v) return v.hp <= 0.5*v.max_hp end) or (leader.hp <= 0.5*leader.max_hp)) and love.timer.getTime() - self.last_heal_time > 6 then
|
||||
local all_units = self:get_all_units()
|
||||
if table.any(all_units, function(v) return v.hp <= 0.5*v.max_hp end) and love.timer.getTime() - self.last_heal_time > 6 then
|
||||
self.last_heal_time = love.timer.getTime()
|
||||
if self.leader then self:heal(0.1*self.max_hp*(self.heal_effect_m or 1)) else self.parent:heal(0.1*self.parent.max_hp*(self.heal_effect_m or 1)) end
|
||||
for _, f in ipairs(followers) do f:heal(0.1*f.max_hp*(self.heal_effect_m or 1)) end
|
||||
for _, unit in ipairs(all_units) do unit:heal(0.1*unit.max_hp*(self.heal_effect_m or 1)) end
|
||||
heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
end
|
||||
end)
|
||||
|
@ -183,21 +180,6 @@ function Player:init(args)
|
|||
self.visual_shape = 'rectangle'
|
||||
self.classes = character_classes.squire
|
||||
|
||||
self.t:every(8, function()
|
||||
self.applying_buff = true
|
||||
local followers
|
||||
local leader = (self.leader and self) or self.parent
|
||||
if self.leader then followers = self.followers else followers = self.parent.followers end
|
||||
local next_character = followers[(self.follower_index or 0) + 1]
|
||||
local previous_character = followers[(self.follower_index or 0) - 1]
|
||||
if next_character then next_character:squire_buff(8) end
|
||||
if previous_character then previous_character:squire_buff(8) end
|
||||
self.t:after(8, function() self.applying_buff = false end, 'squire_buff_apply')
|
||||
heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
if next_character then next_character:heal(0.1*next_character.max_hp*(self.heal_effect_m or 1)) end
|
||||
if previous_character then previous_character:heal(0.1*previous_character.max_hp*(self.heal_effect_m or 1)) end
|
||||
end)
|
||||
|
||||
elseif self.character == 'cannoneer' then
|
||||
self.color = character_colors.cannoneer
|
||||
self:set_as_rectangle(9, 9, 'dynamic', 'player')
|
||||
|
@ -246,16 +228,6 @@ function Player:init(args)
|
|||
self.visual_shape = 'rectangle'
|
||||
self.classes = character_classes.chronomancer
|
||||
|
||||
self.t:every(2, function()
|
||||
local followers
|
||||
local leader = (self.leader and self) or self.parent
|
||||
if self.leader then followers = self.followers else followers = self.parent.followers end
|
||||
local next_character = followers[(self.follower_index or 0) + 1]
|
||||
local previous_character = followers[(self.follower_index or 0) - 1]
|
||||
if next_character then next_character:chronomancer_buff(2) end
|
||||
if previous_character then previous_character:chronomancer_buff(2) end
|
||||
end)
|
||||
|
||||
elseif self.character == 'spellblade' then
|
||||
self.color = character_colors.spellblade
|
||||
self:set_as_rectangle(9, 9, 'dynamic', 'player')
|
||||
|
@ -272,21 +244,6 @@ function Player:init(args)
|
|||
self.visual_shape = 'rectangle'
|
||||
self.classes = character_classes.psykeeper
|
||||
|
||||
self.psykeeper_heal = 0
|
||||
self.t:every(8, function()
|
||||
local followers
|
||||
local leader = (self.leader and self) or self.parent
|
||||
if self.leader then followers = self.followers else followers = self.parent.followers end
|
||||
|
||||
if self.psykeeper_heal > 0 then
|
||||
local heal_amount = math.floor(self.psykeeper_heal/(#followers+1))
|
||||
if self.leader then self:heal(heal_amount*(self.heal_effect_m or 1)) else self.parent:heal(heal_amount*(self.heal_effect_m or 1)) end
|
||||
for _, f in ipairs(followers) do f:heal(heal_amount*(self.heal_effect_m or 1)) end
|
||||
heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
self.psykeeper_heal = 0
|
||||
end
|
||||
end)
|
||||
|
||||
elseif self.character == 'engineer' then
|
||||
self.color = character_colors.engineer
|
||||
self:set_as_rectangle(9, 9, 'dynamic', 'player')
|
||||
|
@ -317,39 +274,16 @@ function Player:update(dt)
|
|||
self:update_game_object(dt)
|
||||
|
||||
if self.character == 'squire' then
|
||||
local followers
|
||||
local leader = (self.leader and self) or self.parent
|
||||
if self.leader then followers = self.followers else followers = self.parent.followers end
|
||||
local next_character = followers[(self.follower_index or 0) + 1]
|
||||
local previous_character = followers[(self.follower_index or 0) - 1]
|
||||
if self.applying_buff then
|
||||
if next_character then
|
||||
next_character.squire_dmg_a = 10
|
||||
next_character.squire_def_a = 25
|
||||
end
|
||||
if previous_character then
|
||||
previous_character.squire_dmg_a = 10
|
||||
previous_character.squire_def_a = 25
|
||||
end
|
||||
else
|
||||
if next_character then
|
||||
next_character.squire_dmg_a = 0
|
||||
next_character.squire_def_a = 0
|
||||
end
|
||||
if previous_character then
|
||||
previous_character.squire_dmg_a = 0
|
||||
previous_character.squire_def_a = 0
|
||||
end
|
||||
local all_units = self:get_all_units()
|
||||
for _, unit in ipairs(all_units) do
|
||||
unit.squire_dmg_m = 1 + 0.05*self.level
|
||||
unit.squire_def_m = 1 + 0.05*self.level
|
||||
end
|
||||
|
||||
elseif self.character == 'chronomancer' then
|
||||
local followers
|
||||
local leader = (self.leader and self) or self.parent
|
||||
if self.leader then followers = self.followers else followers = self.parent.followers end
|
||||
local next_character = followers[(self.follower_index or 0) + 1]
|
||||
local previous_character = followers[(self.follower_index or 0) - 1]
|
||||
if next_character then next_character.chronomancer_aspd_m = 1.25 end
|
||||
if previous_character then previous_character.chronomancer_aspd_m = 1.25 end
|
||||
local all_units = self:get_all_units()
|
||||
for _, unit in ipairs(all_units) do
|
||||
unit.chronomancer_aspd_m = 1 + 0.10*self.level
|
||||
end
|
||||
end
|
||||
|
||||
if table.any(self.classes, function(v) return v == 'ranger' end) then
|
||||
|
@ -391,10 +325,10 @@ function Player:update(dt)
|
|||
else self.enchanter_dmg_m = 1 end
|
||||
end
|
||||
|
||||
self.buff_dmg_a = (self.squire_dmg_a or 0)
|
||||
self.buff_def_a = (self.squire_def_a or 0) + (self.warrior_def_a or 0)
|
||||
self.buff_def_a = (self.warrior_def_a or 0)
|
||||
self.buff_aspd_m = (self.chronomancer_aspd_m or 1)
|
||||
self.buff_dmg_m = (main.current.enchanter_dmg_m or 1)
|
||||
self.buff_dmg_m = (self.squire_dmg_m or 1)*(main.current.enchanter_dmg_m or 1)
|
||||
self.buff_def_m = (self.squire_def_m or 1)
|
||||
self.buff_area_size_m = (self.nuker_area_size_m or 1)
|
||||
self.buff_area_dmg_m = (self.nuker_area_dmg_m or 1)
|
||||
self:calculate_stats()
|
||||
|
@ -492,7 +426,9 @@ function Player:on_collision_enter(other, contact)
|
|||
other:push(random:float(25, 35), self:angle_to_object(other))
|
||||
if self.character == 'vagrant' or self.character == 'psykeeper' then other:hit(2*self.dmg)
|
||||
else other:hit(self.dmg) end
|
||||
self:hit(other.dmg)
|
||||
if other.headbutting then
|
||||
self:hit((4 + math.floor(other.level/3))*other.dmg)
|
||||
else self:hit(other.dmg) end
|
||||
HitCircle{group = main.current.effects, x = x, y = y, rs = 6, color = fg[0], duration = 0.1}
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = x, y = y, color = self.color} end
|
||||
for i = 1, 2 do HitParticle{group = main.current.effects, x = x, y = y, color = other.color} end
|
||||
|
@ -511,7 +447,18 @@ function Player:hit(damage)
|
|||
camera:shake(4, 0.5)
|
||||
main.current.damage_taken = main.current.damage_taken + actual_damage
|
||||
|
||||
if self.character == 'psykeeper' then self.psykeeper_heal = self.psykeeper_heal + actual_damage end
|
||||
local psykeeper = self:get_unit'psykeeper'
|
||||
if psykeeper then
|
||||
psykeeper.stored_heal = psykeeper.stored_heal + actual_damage
|
||||
if psykeeper.stored_heal > (0.1*self.level*psykeeper.max_hp) then
|
||||
local all_units = self:get_all_units()
|
||||
for _, unit in ipairs(all_units) do
|
||||
unit:heal(psykeeper.stored_heal*(self.heal_effect_m or 1))
|
||||
end
|
||||
psykeeper.stored_heal = 0
|
||||
heal1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
end
|
||||
end
|
||||
|
||||
if self.hp <= 0 then
|
||||
hit4:play{pitch = random:float(0.95, 1.05), volume = 0.5}
|
||||
|
@ -542,18 +489,23 @@ end
|
|||
|
||||
function Player:chain_infuse(duration)
|
||||
self.chain_infused = true
|
||||
self:show_infused(duration or 2)
|
||||
self.t:after(duration or 2, function() self.chain_infused = false end, 'chain_infuse')
|
||||
end
|
||||
|
||||
|
||||
function Player:squire_buff(duration)
|
||||
self:show_squire(duration or 2)
|
||||
function Player:get_all_units()
|
||||
local followers
|
||||
local leader = (self.leader and self) or self.parent
|
||||
if self.leader then followers = self.followers else followers = self.parent.followers end
|
||||
return {leader, unpack(followers)}
|
||||
end
|
||||
|
||||
|
||||
function Player:chronomancer_buff(duration)
|
||||
self:show_chronomancer(duration or 2)
|
||||
function Player:get_unit(character)
|
||||
local all_units = self:get_all_units()
|
||||
for _, unit in ipairs(all_units) do
|
||||
if unit.character == character then return unit end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
32
todo
32
todo
|
@ -1,26 +1,24 @@
|
|||
* 1. Enemy spawn points should have some markers before enemy spawns, or should avoid spawning near the player at all
|
||||
2. Prevent spawning of units that cost 3 on first level
|
||||
3. Prevent spawning of units that don't attack on first level
|
||||
* 2. Prevent spawning of units that cost 3 on first level
|
||||
* 3. Prevent spawning of units that don't attack on first level
|
||||
|
||||
4. Rework position based units so that position in the snake doesn't matter
|
||||
Chronomancer: +10%/20%/30% attack speed to all allies
|
||||
Psykeeper: stores damage taken by all allies up to 20% max HP and redistributes it as healing
|
||||
Squire: +5%/10%/15% damage and defense to all allies
|
||||
* 4. Rework position based units so that position in the snake doesn't matter
|
||||
* Chronomancer: +10%/20%/30% attack speed to all allies
|
||||
* 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
|
||||
|
||||
5. Stat details to each unit when hovering over it in the party section
|
||||
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
|
||||
yellow - Resistance to knockback
|
||||
white - Remain static and shoot projectiles
|
||||
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
|
||||
|
||||
7. Enemy modifiers
|
||||
Grant nearby enemies a speed boost on death
|
||||
Grant nearby enemies a damage boost on death
|
||||
Explode into projectiles on death
|
||||
Charge up and headbutt towards the player at increased speed and damage
|
||||
Resistance to knockback
|
||||
... aiming for about 8-10 of these
|
||||
|
||||
8. Additional characters and classes
|
||||
9. Lv.3 effects for every character
|
||||
Classes
|
||||
|
@ -114,6 +112,9 @@
|
|||
Call of the Void: +25% DoT damage
|
||||
... more ideas will come later I'm sure, aiming for 30 total items
|
||||
|
||||
5. Stat and description details to each unit when hovering over it in the party section
|
||||
6. Classes line on each unit's shop card, as well as on party section
|
||||
|
||||
11. Steam integration: achievements, etc
|
||||
12. Hovering over a party member should show which set they belong to and vice-versa
|
||||
13. Show a unit DPS list like Underlord's to the right side of the screen
|
||||
|
@ -128,6 +129,7 @@
|
|||
|
||||
Boss ideas
|
||||
Pretends to be dead, grants speed buffs to enemies after death, especially if the round has gone on for too long which means the player is surviving with 1 unit
|
||||
Uses Psykino's tech to pull enemies together into a point and have that point move around and bounce on edges, thus having a ball of enemies moving around that occasionally explodes
|
||||
|
||||
Map modifiers
|
||||
Wall spikes: walls damage you when you hit it
|
||||
|
|
Loading…
Reference in New Issue