master
a327ex 2021-03-17 06:30:20 -03:00
parent 4ddee5119c
commit bafd765ab3
12 changed files with 247 additions and 79 deletions

150
arena.lua
View File

@ -113,6 +113,7 @@ function Arena:on_enter(from, level, units)
self.enemies_killed = 0 self.enemies_killed = 0
self.enemies_to_kill = self.level_to_enemies_to_kill[self.level] self.enemies_to_kill = self.level_to_enemies_to_kill[self.level]
self.enemy_spawn_delay = 8 self.enemy_spawn_delay = 8
self.enemies_spawned = 0
self.start_time = 3 self.start_time = 3
self.t:after(1, function() self.t:after(1, function()
self.t:every(1, function() self.t:every(1, function()
@ -171,7 +172,7 @@ function Arena:on_enter(from, level, units)
if self.level == 1 then if self.level == 1 then
local t1 = Text2{group = self.floor, x = gw/2, y = gh/2 + 2, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]<- or a -> or d', font = fat_font, alignment = 'center'}}} local t1 = Text2{group = self.floor, x = gw/2, y = gh/2 + 2, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]<- or a -> or d', font = fat_font, alignment = 'center'}}}
local t2 = Text2{group = self.floor, x = gw/2, y = gh/2 + 18, lines = {{text = '[light_bg]turn left turn right', font = pixul_font, alignment = 'center'}}} local t2 = Text2{group = self.floor, x = gw/2, y = gh/2 + 18, lines = {{text = '[light_bg]turn left turn right', font = pixul_font, alignment = 'center'}}}
local t3 = Text2{group = self.floor, x = gw/2, y = gh/2 + 46, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]n - mute sfx', font = fat_font, alignment = 'center'}}} local t3 = Text2{group = self.floor, x = gw/2, y = gh/2 + 46, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]s - mute sfx', font = fat_font, alignment = 'center'}}}
local t4 = Text2{group = self.floor, x = gw/2, y = gh/2 + 68, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]m - mute music', font = fat_font, alignment = 'center'}}} local t4 = Text2{group = self.floor, x = gw/2, y = gh/2 + 68, sx = 0.6, sy = 0.6, lines = {{text = '[light_bg]m - mute music', font = fat_font, alignment = 'center'}}}
t1.t:after(8, function() t1.t:tween(0.2, t1, {sy = 0}, math.linear, function() t1.sy = 0 end) end) t1.t:after(8, function() t1.t:tween(0.2, t1, {sy = 0}, math.linear, function() t1.sy = 0 end) end)
t2.t:after(8, function() t2.t:tween(0.2, t2, {sy = 0}, math.linear, function() t2.sy = 0 end) end) t2.t:after(8, function() t2.t:tween(0.2, t2, {sy = 0}, math.linear, function() t2.sy = 0 end) end)
@ -233,7 +234,76 @@ end
function Arena:update(dt) function Arena:update(dt)
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()
slow_amount = 0
self.paused = true
self.paused_t1 = Text2{group = self.ui, x = gw/2, y = gh/2 - 68, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]<- or a -> or d', font = fat_font, alignment = 'center'}}}
self.paused_t2 = Text2{group = self.ui, x = gw/2, y = gh/2 - 52, lines = {{text = '[bg10]turn left turn right', font = pixul_font, alignment = 'center'}}}
self.paused_t3 = Text2{group = self.ui, x = gw/2, y = gh/2 - 22, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]s - mute sfx', font = fat_font, alignment = 'center'}}}
self.paused_t4 = Text2{group = self.ui, x = gw/2, y = gh/2 + 0, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]m - mute music', font = fat_font, alignment = 'center'}}}
self.paused_t5 = Text2{group = self.ui, x = gw/2, y = gh/2 + 22, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]esc - resume game', font = fat_font, alignment = 'center'}}}
self.paused_t6 = Text2{group = self.ui, x = gw/2, y = gh/2 + 44, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]r - restart run', font = fat_font, alignment = 'center'}}}
self.paused_t7 = Text2{group = self.ui, x = gw/2, y = gh/2 + 68, sx = 0.6, sy = 0.6, lines = {{text = '[bg10]w - wishlist on steam', font = fat_font, alignment = 'center'}}}
end, 'pause')
else
trigger:tween(0.25, _G, {slow_amount = 1}, math.linear, function()
slow_amount = 1
self.paused = false
self.paused_t1.dead = true
self.paused_t2.dead = true
self.paused_t3.dead = true
self.paused_t4.dead = true
self.paused_t5.dead = true
self.paused_t6.dead = true
self.paused_t7.dead = true
self.paused_t1 = nil
self.paused_t2 = nil
self.paused_t3 = nil
self.paused_t4 = nil
self.paused_t5 = nil
self.paused_t6 = nil
self.paused_t7 = nil
end, 'pause')
end
end
if self.paused or self.died and not self.transitioning then
if input.r.pressed then
self.transitioning = true
ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function()
slow_amount = 1
gold = 2
cascade_instance:stop()
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', 0, {})
end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)}
end
if input.w.pressed then
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
system.open_url'https://store.steampowered.com/app/915310/SNKRX/'
end
end
if input.w.pressed and self.won then
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
system.open_url'https://store.steampowered.com/app/915310/SNKRX/'
end
self:update_game_object(dt*slow_amount) 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 if self.enchanter_level == 1 then self.enchanter_dmg_m = 1.25
else self.enchanter_dmg_m = 1 end else self.enchanter_dmg_m = 1 end
@ -248,44 +318,62 @@ function Arena:update(dt)
self.can_quit = false self.can_quit = false
self.transitioning = true self.transitioning = true
local gold_gained = random:int(level_to_gold_gained[self.level][1], level_to_gold_gained[self.level][2]) local gold_gained = random:int(level_to_gold_gained[self.level][1], level_to_gold_gained[self.level][2])
print(gold_gained)
gold = gold + gold_gained gold = gold + gold_gained
if not self.arena_clear_text then self.arena_clear_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 48, lines = {{text = '[wavy_mid, cbyc]arena clear!', font = fat_font, alignment = 'center'}}} end
self.t:after(3, function() if self.level == 25 then
ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5} if not self.win_text and not self.win_text2 then
TransitionEffect{group = main.transitions, x = self.player.x, y = self.player.y, color = self.color, transition_action = function(t) self.won = true
main:add(BuyScreen'buy_screen') camera.x, camera.y = gw/2, gh/2
main:go_to('buy_screen', self.level, self.units) self.win_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 64, lines = {{text = '[wavy_mid, cbyc2]congratulations!', font = fat_font, alignment = 'center'}}}
t.t:after(0.1, function() self.t:after(2.5, function()
t.text:set_text({ self.win_text2 = Text2{group = self.ui, x = gw/2, y = gh/2 + 16, lines = {
{text = '[nudge_down, bg]gold gained: ' .. tostring(gold_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = "[fg]you've beaten the demo!", font = pixul_font, alignment = 'center', height_multiplier = 1.2},
{text = '[wavy_lower, bg]damage taken: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = "[fg]the game's full version is coming in a few weeks,", font = pixul_font, alignment = 'center', height_multiplier = 1.2},
{text = '[wavy_lower, bg]damage dealt: 0', font = pixul_font, alignment = 'center'} {text = "[fg]so if you liked the game, make sure to wishlist it!", font = pixul_font, alignment = 'center', height_multiplier = 5},
}) {text = "[wavy_mid, fg]thanks for playing!", font = pixul_font, alignment = 'center'},
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} }}
t.t:after(0.2, function() WishlistButton{group = self.ui, x = gw/2, y = gh/2 + 30, w_to_wishlist = true}
end)
end
else
if not self.arena_clear_text then self.arena_clear_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 48, lines = {{text = '[wavy_mid, cbyc]arena clear!', font = fat_font, alignment = 'center'}}} end
self.t:after(3, function()
ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
TransitionEffect{group = main.transitions, x = self.player.x, y = self.player.y, color = self.color, transition_action = function(t)
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', self.level, self.units)
t.t:after(0.1, function()
t.text:set_text({ t.text:set_text({
{text = '[wavy_lower, bg]gold gained: ' .. tostring(gold_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = '[nudge_down, bg]gold gained: ' .. tostring(gold_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[nudge_down, bg]damage taken: ' .. tostring(math.round(self.damage_taken, 0)), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = '[wavy_lower, bg]damage taken: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy_lower, bg]damage dealt: 0', font = pixul_font, alignment = 'center'} {text = '[wavy_lower, bg]damage dealt: 0', font = pixul_font, alignment = 'center'}
}) })
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} _G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
t.t:after(0.2, function() t.t:after(0.2, function()
t.text:set_text({ t.text:set_text({
{text = '[wavy_lower, bg]gold gained: ' .. tostring(gold_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = '[wavy_lower, bg]gold gained: ' .. tostring(gold_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy_lower, bg]damage taken: ' .. tostring(math.round(self.damage_taken, 0)), font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = '[nudge_down, bg]damage taken: ' .. tostring(math.round(self.damage_taken, 0)), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[nudge_down, bg]damage dealt: ' .. tostring(math.round(self.damage_dealt, 0)), font = pixul_font, alignment = 'center'} {text = '[wavy_lower, bg]damage dealt: 0', font = pixul_font, alignment = 'center'}
}) })
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} _G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
t.t:after(0.2, function()
t.text:set_text({
{text = '[wavy_lower, bg]gold gained: ' .. tostring(gold_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy_lower, bg]damage taken: ' .. tostring(math.round(self.damage_taken, 0)), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[nudge_down, bg]damage dealt: ' .. tostring(math.round(self.damage_dealt, 0)), font = pixul_font, alignment = 'center'}
})
_G[random:table{'coins1', 'coins2', 'coins3'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
end)
end) end)
end) end)
end) end, text = Text({
end, text = Text({ {text = '[wavy_lower, bg]gold gained: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy_lower, bg]gold gained: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = '[wavy_lower, bg]damage taken: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy_lower, bg]damage taken: 0', font = pixul_font, alignment = 'center', height_multiplier = 1.5}, {text = '[wavy_lower, bg]damage dealt: 0', font = pixul_font, alignment = 'center'}
{text = '[wavy_lower, bg]damage dealt: 0', font = pixul_font, alignment = 'center'} }, global_text_tags)}
}, global_text_tags)} end, 'transition')
end, 'transition') end
end end
end end
@ -339,14 +427,14 @@ end
function Arena:die() function Arena:die()
if not self.died_text then if not self.died_text and not self.won then
self.died = true self.died = true
self.t:tween(2, self, {main_slow_amount = 0}, math.linear, function() self.main_slow_amount = 0 end) self.t:tween(2, self, {main_slow_amount = 0}, math.linear, function() self.main_slow_amount = 0 end)
self.died_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 32, lines = { self.died_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 32, lines = {
{text = '[wavy_mid, cbyc]you died...', font = fat_font, alignment = 'center', height_multiplier = 1.25}, {text = '[wavy_mid, cbyc]you died...', font = fat_font, alignment = 'center', height_multiplier = 1.25},
}} }}
self.t:after(2, function() self.t:after(2, function()
self.death_info_text = Text2{group = self.ui, x = gw/2, y = gh/2 + 16, sx = 0.7, sy = 0.7, lines = { self.death_info_text = Text2{group = self.ui, x = gw/2, y = gh/2 + 24, sx = 0.7, sy = 0.7, lines = {
{text = '[wavy_mid, light_bg]level reached: [wavy_mid, yellow]' .. self.level, font = fat_font, alignment = 'center'}, {text = '[wavy_mid, light_bg]level reached: [wavy_mid, yellow]' .. self.level, font = fat_font, alignment = 'center'},
{text = '[wavy_mid, light_bg]r - start new run', font = fat_font, alignment = 'center'}, {text = '[wavy_mid, light_bg]r - start new run', font = fat_font, alignment = 'center'},
{text = '[wavy_mid, light_bg]w - wishlist on steam', font = fat_font, alignment = 'center'}, {text = '[wavy_mid, light_bg]w - wishlist on steam', font = fat_font, alignment = 'center'},
@ -411,6 +499,10 @@ function Arena:spawn_n_enemies(p, j, n)
n = n or 4 n = n or 4
self.last_spawn_enemy_time = love.timer.getTime() self.last_spawn_enemy_time = love.timer.getTime()
self.t:every(0.1, function() self.t:every(0.1, function()
if self.win_condition == 'enemy_kill' then
if self.enemies_spawned >= math.floor(1.4*self.enemies_to_kill) then return end
self.enemies_spawned = self.enemies_spawned + 1
end
local o = self.spawn_offsets[(self.t:get_every_iteration('spawn_enemies_' .. j) % 5) + 1] local o = self.spawn_offsets[(self.t:get_every_iteration('spawn_enemies_' .. j) % 5) + 1]
SpawnEffect{group = self.effects, x = p.x + o.x, y = p.y + o.y, action = function(x, y) SpawnEffect{group = self.effects, x = p.x + o.x, y = p.y + o.y, action = function(x, y)
spawn1:play{pitch = random:float(0.8, 1.2), volume = 0.15} spawn1:play{pitch = random:float(0.8, 1.2), volume = 0.15}

Binary file not shown.

Binary file not shown.

View File

@ -32,6 +32,7 @@ function BuyScreen:on_enter(from, level, units)
camera.x, camera.y = gw/2, gh/2 camera.x, camera.y = gw/2, gh/2
if self.level == 0 then if self.level == 0 then
cascade_instance = cascade:play{volume = 0.5, loop = true}
self.level = 1 self.level = 1
self.first_screen = true self.first_screen = true
end end
@ -60,6 +61,8 @@ end
function BuyScreen:update(dt) function BuyScreen:update(dt)
self:update_game_object(dt*slow_amount) self:update_game_object(dt*slow_amount)
cascade_instance.pitch = 1
self.main:update(dt*slow_amount) self.main:update(dt*slow_amount)
self.effects:update(dt*slow_amount) self.effects:update(dt*slow_amount)
self.ui:update(dt*slow_amount) self.ui:update(dt*slow_amount)
@ -180,9 +183,14 @@ WishlistButton = Object:extend()
WishlistButton:implement(GameObject) WishlistButton:implement(GameObject)
function WishlistButton:init(args) function WishlistButton:init(args)
self:init_game_object(args) self:init_game_object(args)
self.shape = Rectangle(self.x, self.y, 110, 18)
self.interact_with_mouse = true self.interact_with_mouse = true
self.text = Text({{text = '[bg10]wishlist on steam', font = pixul_font, alignment = 'center'}}, global_text_tags) if self.w_to_wishlist then
self.shape = Rectangle(self.x, self.y, 85, 18)
self.text = Text({{text = '[bg10]w to wishlist', font = pixul_font, alignment = 'center'}}, global_text_tags)
else
self.shape = Rectangle(self.x, self.y, 110, 18)
self.text = Text({{text = '[bg10]wishlist on steam', font = pixul_font, alignment = 'center'}}, global_text_tags)
end
end end
@ -194,7 +202,7 @@ function WishlistButton:update(dt)
self.spring:pull(0.2, 200, 10) self.spring:pull(0.2, 200, 10)
self.selected = true self.selected = true
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5} ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
system.open_url'https://store.steampowered.com/app/760330/BYTEPATH/' system.open_url'https://store.steampowered.com/app/915310/SNKRX/'
end end
end end
@ -211,13 +219,21 @@ function WishlistButton:on_mouse_enter()
ui_hover1:play{pitch = random:float(1.3, 1.5), volume = 0.5} ui_hover1:play{pitch = random:float(1.3, 1.5), volume = 0.5}
pop2:play{pitch = random:float(0.95, 1.05), volume = 0.5} pop2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.selected = true self.selected = true
self.text:set_text{{text = '[fgm5]wishlist on steam', font = pixul_font, alignment = 'center'}} if self.w_to_wishlist then
self.text:set_text{{text = '[fgm5]w to wishlist', font = pixul_font, alignment = 'center'}}
else
self.text:set_text{{text = '[fgm5]wishlist on steam', font = pixul_font, alignment = 'center'}}
end
self.spring:pull(0.2, 200, 10) self.spring:pull(0.2, 200, 10)
end end
function WishlistButton:on_mouse_exit() function WishlistButton:on_mouse_exit()
self.text:set_text{{text = '[bg10]wishlist on steam', font = pixul_font, alignment = 'center'}} if self.w_to_wishlist then
self.text:set_text{{text = '[bg10]w to wishlist', font = pixul_font, alignment = 'center'}}
else
self.text:set_text{{text = '[bg10]wishlist on steam', font = pixul_font, alignment = 'center'}}
end
self.selected = false self.selected = false
end end

View File

@ -406,4 +406,10 @@ Mostly done with balance tuning. Now all that's left are some final details:
* Win screen * Win screen
* W to wishlist * W to wishlist
* R to restart * R to restart
* Unit death sound * Allied unit death sound
# Day 28 - 16/03/21
The demo is finally 100% complete. Now tomorrow I'll spend some time recording gameplay and hopefully finishing the trailer. After that I can start working on the steam page.
If I have it done by tomorrow and Valve takes 5 business days to approve the store page I should have everything ready by the 25th. And then I can release the game 14 days after that, which would be the 8th of April.
I definitely want to release it around that time, before the 15th because then I will have completed the game in less than 60 days which is my limit, although I should probably aim for 40 days going forward.

View File

@ -58,8 +58,8 @@ function Seeker:on_collision_enter(other, contact)
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
other:hit(5) other:hit(math.floor(self.dmg/2))
self:hit(10) self:hit(self.dmg)
other:push(random:float(10, 15), other:angle_to_object(self)) other:push(random:float(10, 15), other:angle_to_object(self))
HitCircle{group = main.current.effects, x = x, y = y, rs = 6, color = fg[0], duration = 0.1} 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 = self.color} end

View File

@ -37,7 +37,8 @@ function init()
arrow_hit_wall2 = Sound('Arrow Impact wood 1.ogg', s) arrow_hit_wall2 = Sound('Arrow Impact wood 1.ogg', s)
hit1 = Sound('Player Takes Damage 17.ogg', s) hit1 = Sound('Player Takes Damage 17.ogg', s)
hit2 = Sound('Body Head (Headshot) 1.ogg', s) hit2 = Sound('Body Head (Headshot) 1.ogg', s)
hit3 = Sound('Kick 16.ogg', s) hit3 = Sound('Kick 16_1.ogg', s)
hit4 = Sound('Kick 16_2.ogg', s)
proj_hit_wall1 = Sound('Player Takes Damage 2.ogg', s) proj_hit_wall1 = Sound('Player Takes Damage 2.ogg', s)
enemy_die1 = Sound('Bloody punches 7.ogg', s) enemy_die1 = Sound('Bloody punches 7.ogg', s)
enemy_die2 = Sound('Bloody punches 10.ogg', s) enemy_die2 = Sound('Bloody punches 10.ogg', s)
@ -77,6 +78,7 @@ function init()
turret_deploy = Sound('321215__hybrid-v__sci-fi-weapons-deploy.ogg', s) turret_deploy = Sound('321215__hybrid-v__sci-fi-weapons-deploy.ogg', s)
rogue_crit1 = Sound('Dagger Stab (Flesh) 4.ogg', s) rogue_crit1 = Sound('Dagger Stab (Flesh) 4.ogg', s)
rogue_crit2 = Sound('Sword hits another sword 6.ogg', s) rogue_crit2 = Sound('Sword hits another sword 6.ogg', s)
cascade = Sound('Kubbi - Ember - 04 Cascade.ogg', {tags = {music}})
warrior = Image('warrior') warrior = Image('warrior')
ranger = Image('ranger') ranger = Image('ranger')
@ -376,29 +378,29 @@ function init()
level_to_gold_gained = { level_to_gold_gained = {
[1] = {2, 2}, [1] = {2, 2},
[2] = {2, 2}, [2] = {2, 2},
[3] = {2, 3}, [3] = {4, 6},
[4] = {2, 3}, [4] = {2, 3},
[5] = {3, 5}, [5] = {3, 5},
[6] = {3, 5}, [6] = {6, 10},
[7] = {4, 7}, [7] = {4, 7},
[8] = {4, 7}, [8] = {4, 7},
[9] = {5, 8}, [9] = {10, 16},
[10] = {5, 8}, [10] = {5, 8},
[11] = {5, 8}, [11] = {5, 8},
[12] = {6, 10}, [12] = {12, 20},
[13] = {6, 10}, [13] = {6, 10},
[14] = {6, 10}, [14] = {6, 10},
[15] = {7, 11}, [15] = {14, 22},
[16] = {8, 12}, [16] = {8, 12},
[17] = {8, 12}, [17] = {8, 12},
[18] = {8, 12}, [18] = {16, 24},
[19] = {8, 12}, [19] = {8, 12},
[20] = {10, 14}, [20] = {10, 14},
[21] = {10, 14}, [21] = {20, 28},
[22] = {11, 15}, [22] = {11, 15},
[23] = {11, 15}, [23] = {11, 15},
[24] = {12, 18}, [24] = {24, 36},
[25] = {12, 18}, [25] = {100, 100},
} }
gold = 2 gold = 2
@ -411,6 +413,23 @@ end
function update(dt) function update(dt)
main:update(dt) main:update(dt)
if input.s.pressed then
if sfx.volume == 0.5 then
sfx.volume = 0
elseif sfx.volume == 0 then
sfx.volume = 0.5
end
end
if input.m.pressed then
print(music.volume)
if music.volume == 0.5 then
music.volume = 0
elseif music.volume == 0 then
music.volume = 0.5
end
end
end end

View File

@ -204,9 +204,9 @@ function Unit:calculate_stats(first_run)
elseif self:is(Seeker) then elseif self:is(Seeker) 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 = 50 + 60*y[x] self.base_hp = 50 + 55*y[x]
self.base_dmg = 10 + 40*y[x] self.base_dmg = 10 + 3*y[x]
self.base_mvspd = 70 + 10*y[x] self.base_mvspd = 70 + 3*y[x]
elseif self:is(Saboteur) then elseif self:is(Saboteur) then
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)

View File

@ -188,8 +188,8 @@ function Player:init(args)
local followers local followers
local leader = (self.leader and self) or self.parent local leader = (self.leader and self) or self.parent
if self.leader then followers = self.followers else followers = self.parent.followers end if self.leader then followers = self.followers else followers = self.parent.followers end
local next_character = followers[self.follower_index + 1] local next_character = followers[(self.follower_index or 0) + 1]
local previous_character = followers[self.follower_index - 1] local previous_character = followers[(self.follower_index or 0) - 1]
if next_character then next_character:squire_buff(8) end if next_character then next_character:squire_buff(8) end
if previous_character then previous_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') self.t:after(8, function() self.applying_buff = false end, 'squire_buff_apply')
@ -250,8 +250,8 @@ function Player:init(args)
local followers local followers
local leader = (self.leader and self) or self.parent local leader = (self.leader and self) or self.parent
if self.leader then followers = self.followers else followers = self.parent.followers end if self.leader then followers = self.followers else followers = self.parent.followers end
local next_character = followers[self.follower_index + 1] local next_character = followers[(self.follower_index or 0) + 1]
local previous_character = followers[self.follower_index - 1] local previous_character = followers[(self.follower_index or 0) - 1]
if next_character then next_character:chronomancer_buff(2) end if next_character then next_character:chronomancer_buff(2) end
if previous_character then previous_character:chronomancer_buff(2) end if previous_character then previous_character:chronomancer_buff(2) end
end) end)
@ -320,8 +320,8 @@ function Player:update(dt)
local followers local followers
local leader = (self.leader and self) or self.parent local leader = (self.leader and self) or self.parent
if self.leader then followers = self.followers else followers = self.parent.followers end if self.leader then followers = self.followers else followers = self.parent.followers end
local next_character = followers[self.follower_index + 1] local next_character = followers[(self.follower_index or 0) + 1]
local previous_character = followers[self.follower_index - 1] local previous_character = followers[(self.follower_index or 0) - 1]
if self.applying_buff then if self.applying_buff then
if next_character then if next_character then
next_character.squire_dmg_a = 10 next_character.squire_dmg_a = 10
@ -346,8 +346,8 @@ function Player:update(dt)
local followers local followers
local leader = (self.leader and self) or self.parent local leader = (self.leader and self) or self.parent
if self.leader then followers = self.followers else followers = self.parent.followers end if self.leader then followers = self.followers else followers = self.parent.followers end
local next_character = followers[self.follower_index + 1] local next_character = followers[(self.follower_index or 0) + 1]
local previous_character = followers[self.follower_index - 1] local previous_character = followers[(self.follower_index or 0) - 1]
if next_character then next_character.chronomancer_aspd_m = 1.25 end if next_character then next_character.chronomancer_aspd_m = 1.25 end
if previous_character then previous_character.chronomancer_aspd_m = 1.25 end if previous_character then previous_character.chronomancer_aspd_m = 1.25 end
end end
@ -409,21 +409,23 @@ function Player:update(dt)
if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end if input.move_right.down then self.r = self.r + 1.66*math.pi*dt end
self:set_velocity(self.v*math.cos(self.r), self.v*math.sin(self.r)) self:set_velocity(self.v*math.cos(self.r), self.v*math.sin(self.r))
local vx, vy = self:get_velocity() if not main.current.won then
local hd = math.remap(math.abs(self.x - gw/2), 0, 192, 1, 0) local vx, vy = self:get_velocity()
local vd = math.remap(math.abs(self.y - gh/2), 0, 108, 1, 0) local hd = math.remap(math.abs(self.x - gw/2), 0, 192, 1, 0)
camera.x = camera.x + math.remap(vx, -100, 100, -24*hd, 24*hd)*dt local vd = math.remap(math.abs(self.y - gh/2), 0, 108, 1, 0)
camera.y = camera.y + math.remap(vy, -100, 100, -8*vd, 8*vd)*dt camera.x = camera.x + math.remap(vx, -100, 100, -24*hd, 24*hd)*dt
if input.move_right.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, math.pi/256) camera.y = camera.y + math.remap(vy, -100, 100, -8*vd, 8*vd)*dt
elseif input.move_left.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, -math.pi/256) if input.move_right.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, math.pi/256)
elseif input.move_down.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, math.pi/256) elseif input.move_left.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, -math.pi/256)
elseif input.move_up.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, -math.pi/256) elseif input.move_down.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, math.pi/256)
else camera.r = math.lerp_angle_dt(0.005, dt, camera.r, 0) end elseif input.move_up.down then camera.r = math.lerp_angle_dt(0.01, dt, camera.r, -math.pi/256)
else camera.r = math.lerp_angle_dt(0.005, dt, camera.r, 0) end
end
self:set_angle(self.r) self:set_angle(self.r)
else else
local target_distance = 10.4*self.follower_index local target_distance = 10.4*(self.follower_index or 0)
local distance_sum = 0 local distance_sum = 0
local p local p
local previous = self.parent local previous = self.parent
@ -485,9 +487,9 @@ function Player:on_collision_enter(other, contact)
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
other:push(random:float(25, 35), self:angle_to_object(other)) other:push(random:float(25, 35), self:angle_to_object(other))
if self.character == 'vagrant' or self.character == 'psykeeper' then other:hit(40) if self.character == 'vagrant' or self.character == 'psykeeper' then other:hit(2*self.dmg)
else other:hit(20) end else other:hit(self.dmg) end
self:hit(20) self:hit(other.dmg)
HitCircle{group = main.current.effects, x = x, y = y, rs = 6, color = fg[0], duration = 0.1} 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 = self.color} end
for i = 1, 2 do HitParticle{group = main.current.effects, x = x, y = y, color = other.color} end for i = 1, 2 do HitParticle{group = main.current.effects, x = x, y = y, color = other.color} end
@ -500,7 +502,6 @@ function Player:hit(damage)
self.hfx:use('hit', 0.25, 200, 10) self.hfx:use('hit', 0.25, 200, 10)
self:show_hp() self:show_hp()
local actual_damage = self:calculate_damage(damage) local actual_damage = self:calculate_damage(damage)
self.hp = self.hp - actual_damage self.hp = self.hp - actual_damage
_G[random:table{'player_hit1', 'player_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5} _G[random:table{'player_hit1', 'player_hit2'}]:play{pitch = random:float(0.95, 1.05), volume = 0.5}
@ -510,6 +511,7 @@ function Player:hit(damage)
if self.character == 'psykeeper' then self.psykeeper_heal = self.psykeeper_heal + actual_damage end if self.character == 'psykeeper' then self.psykeeper_heal = self.psykeeper_heal + actual_damage end
if self.hp <= 0 then if self.hp <= 0 then
hit4:play{pitch = random:float(0.95, 1.05), volume = 0.5}
slow(0.25, 1) slow(0.25, 1)
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
@ -978,7 +980,7 @@ function Turret:init(args)
self:set_restitution(0.5) self:set_restitution(0.5)
self.hfx:add('hit', 1) self.hfx:add('hit', 1)
self.color = orange[0] self.color = orange[0]
self.attack_sensor = Circle(self.x, self.y, 96) self.attack_sensor = Circle(self.x, self.y, 256)
turret_deploy:play{pitch = 1.2, volume = 0.2} turret_deploy:play{pitch = 1.2, volume = 0.2}
self.t:every({3.5, 4.5}, function() self.t:every({3.5, 4.5}, function()

View File

@ -449,6 +449,17 @@ global_text_tags = {
graphics.set_color(c.color) graphics.set_color(c.color)
end}, end},
cbyc2 = TextTag{init = function(c, i, text)
c.color = invisible
text.t:after((i-1)*0.15, function()
c.color = yellow[0]
camera:shake(3, 0.075)
pop1:play{pitch = random:float(0.95, 1.05), volume = 0.35}
end)
end, draw = function(c, i, text)
graphics.set_color(c.color)
end},
nudge_down = TextTag{init = function(c, i, text) nudge_down = TextTag{init = function(c, i, text)
c.oy = -4 c.oy = -4
text.t:tween(0.1, c, {oy = 0}, math.linear) text.t:tween(0.1, c, {oy = 0}, math.linear)

32
todo
View File

@ -1,17 +1,26 @@
-- POST DEMO --
Mini Boss every 3rd level Mini Boss every 3rd level
Show a unit DPS list like Underlord's to the right side of the screen Show a unit DPS list like Underlord's to the right side of the screen
About 20-30 passive items that can be collected every 3 levels About 20-30 passive items that can be collected every 3 levels
Lv.3 effects for every character Lv.3 effects for every character
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
Classes and characters Classes and characters
Trapper: releases +1 trap Trapper: releases +1 trap
Plague Doctor [trapper, nuker]: releases an area that deals 6 AoE DoT Plague Doctor [trapper, nuker]: releases an area that deals 6 AoE DoT
Fisherman [trapper, warrior]: throws a net that entangles enemies and prevents them from moving Fisherman [trapper, warrior]: throws a net that entangles enemies and prevents them from moving
Lich [mage, enchanter]: nearby enemies have decreased movement speed
Items
Resonance: hitting walls has a chance of releasing projectiles
Ouroboros Technique: rotating around yourself makes every unit release projectiles
AoE 1: all units that deal AoE damage have increased stat
AoE 2: increased stat if all your units that deal damage deal AoE damage
Proj 1: all units that release projectiles have increased stat
Proj 2: increased stat if all your units that deal damage release projectiles
Wallrider: hitting walls grants a speed buff for a small duration
Enemy modifiers Enemy modifiers
Grant nearby enemies a speed boost on death Grant nearby enemies a speed boost on death
@ -20,3 +29,16 @@ Enemy modifiers
Charge up and headbutt towards the player at increased speed and damage Charge up and headbutt towards the player at increased speed and damage
Immune to knockback Immune to knockback
UI
Highlight units of a class when hovering over the class icon in the "sets" section
Add stat details to each unit when hovering over it in the "party" section
Balance
More damage to AoE units with big cooldowns
Warriors that deal AoE damage should deal extra damage based on number of enemies hit
Bugs
Squire and Chronomancer don't affect leader
Sage's pull force doesn't increase with unit level
Cleric's healing amount doesn't increase with unit level
Squire and Chronomancer's buffs don't increase with unit level