2021-02-18 05:11:25 +01:00
Arena = Object : extend ( )
Arena : implement ( State )
Arena : implement ( GameObject )
function Arena : init ( name )
self : init_state ( name )
self : init_game_object ( )
2021-02-20 02:54:54 +01:00
end
2021-07-01 03:34:48 +02:00
function Arena : on_enter ( from , level , loop , units , passives , shop_level , shop_xp , lock )
2021-02-21 06:47:59 +01:00
self.hfx : add ( ' condition1 ' , 1 )
self.hfx : add ( ' condition2 ' , 1 )
self.level = level or 1
2021-07-01 03:34:48 +02:00
self.loop = loop or 0
2021-03-10 06:47:27 +01:00
self.units = units
2021-04-19 05:31:47 +02:00
self.passives = passives
2021-06-11 06:44:06 +02:00
self.shop_level = shop_level or 1
self.shop_xp = shop_xp or 0
2021-06-14 06:59:16 +02:00
self.lock = lock
self.starting_units = table.copy ( units )
2021-03-29 20:26:10 +02:00
2021-06-09 06:35:57 +02:00
if not state.mouse_control then
input : set_mouse_visible ( false )
end
2021-05-17 10:05:48 +02:00
trigger : tween ( 2 , main_song_instance , { volume = 0.5 , pitch = 1 } , math.linear )
2021-03-29 20:26:10 +02:00
steam.friends . setRichPresence ( ' steam_display ' , ' #StatusFull ' )
steam.friends . setRichPresence ( ' text ' , ' Arena - Level ' .. self.level )
2021-02-21 06:47:59 +01:00
2021-03-08 05:33:01 +01:00
self.floor = Group ( )
2021-06-10 19:39:40 +02:00
self.main = Group ( ) : set_as_physics_world ( 32 , 0 , 0 , { ' player ' , ' enemy ' , ' projectile ' , ' enemy_projectile ' , ' force_field ' , ' ghost ' } )
2021-02-22 03:54:50 +01:00
self.post_main = Group ( )
2021-02-18 05:11:25 +01:00
self.effects = Group ( )
2021-03-05 08:29:19 +01:00
self.ui = Group ( )
2021-05-17 10:05:48 +02:00
self.credits = Group ( )
2021-02-18 05:11:25 +01:00
self.main : disable_collision_between ( ' player ' , ' player ' )
2021-02-20 02:54:54 +01:00
self.main : disable_collision_between ( ' player ' , ' projectile ' )
self.main : disable_collision_between ( ' player ' , ' enemy_projectile ' )
self.main : disable_collision_between ( ' projectile ' , ' projectile ' )
self.main : disable_collision_between ( ' projectile ' , ' enemy_projectile ' )
self.main : disable_collision_between ( ' projectile ' , ' enemy ' )
self.main : disable_collision_between ( ' enemy_projectile ' , ' enemy ' )
self.main : disable_collision_between ( ' enemy_projectile ' , ' enemy_projectile ' )
2021-06-03 22:02:04 +02:00
self.main : disable_collision_between ( ' player ' , ' force_field ' )
self.main : disable_collision_between ( ' projectile ' , ' force_field ' )
2021-06-10 19:39:40 +02:00
self.main : disable_collision_between ( ' ghost ' , ' player ' )
self.main : disable_collision_between ( ' ghost ' , ' projectile ' )
self.main : disable_collision_between ( ' ghost ' , ' enemy ' )
self.main : disable_collision_between ( ' ghost ' , ' enemy_projectile ' )
self.main : disable_collision_between ( ' ghost ' , ' ghost ' )
self.main : disable_collision_between ( ' ghost ' , ' force_field ' )
2021-02-20 02:54:54 +01:00
self.main : enable_trigger_between ( ' projectile ' , ' enemy ' )
self.main : enable_trigger_between ( ' enemy_projectile ' , ' player ' )
2021-04-02 03:59:26 +02:00
self.main : enable_trigger_between ( ' player ' , ' enemy_projectile ' )
2021-06-18 23:36:00 +02:00
self.main : enable_trigger_between ( ' enemy_projectile ' , ' enemy ' )
2021-06-10 19:39:40 +02:00
self.main : enable_trigger_between ( ' player ' , ' ghost ' )
self.main : enable_trigger_between ( ' ghost ' , ' player ' )
2021-02-19 04:50:27 +01:00
2021-06-10 19:39:40 +02:00
self.gold_picked_up = 0
2021-03-15 05:01:04 +01:00
self.damage_dealt = 0
self.damage_taken = 0
self.main_slow_amount = 1
2021-04-03 04:53:12 +02:00
self.enemies = { Seeker , EnemyCritter }
2021-03-05 08:29:19 +01:00
self.color = self.color or fg [ 0 ]
2021-02-18 05:11:25 +01:00
2021-03-05 08:29:19 +01:00
-- Spawn solids and player
2021-02-18 05:11:25 +01:00
self.x1 , self.y1 = gw / 2 - 0.8 * gw / 2 , gh / 2 - 0.8 * gh / 2
self.x2 , self.y2 = gw / 2 + 0.8 * gw / 2 , gh / 2 + 0.8 * gh / 2
2021-04-24 05:19:22 +02:00
self.w , self.h = self.x2 - self.x1 , self.y2 - self.y1
2021-02-19 04:50:27 +01:00
self.spawn_points = {
{ x = self.x1 + 32 , y = self.y1 + 32 , r = math.pi / 4 } ,
{ x = self.x1 + 32 , y = self.y2 - 32 , r = - math.pi / 4 } ,
{ x = self.x2 - 32 , y = self.y1 + 32 , r = 3 * math.pi / 4 } ,
{ x = self.x2 - 32 , y = self.y2 - 32 , r = - 3 * math.pi / 4 } ,
{ x = gw / 2 , y = gh / 2 , r = random : float ( 0 , 2 * math.pi ) }
}
2021-02-18 19:28:40 +01:00
self.spawn_offsets = { { x = - 12 , y = - 12 } , { x = 12 , y = - 12 } , { x = 12 , y = 12 } , { x = - 12 , y = 12 } , { x = 0 , y = 0 } }
2021-02-21 06:47:59 +01:00
self.last_spawn_enemy_time = love.timer . getTime ( )
2021-02-18 05:11:25 +01:00
Wall { group = self.main , vertices = math.to_rectangle_vertices ( - 40 , - 40 , self.x1 , gh + 40 ) , color = bg [ - 1 ] }
Wall { group = self.main , vertices = math.to_rectangle_vertices ( self.x2 , - 40 , gw + 40 , gh + 40 ) , color = bg [ - 1 ] }
Wall { group = self.main , vertices = math.to_rectangle_vertices ( self.x1 , - 40 , self.x2 , self.y1 ) , color = bg [ - 1 ] }
Wall { group = self.main , vertices = math.to_rectangle_vertices ( self.x1 , self.y2 , self.x2 , gh + 40 ) , color = bg [ - 1 ] }
2021-02-22 03:54:50 +01:00
WallCover { group = self.post_main , vertices = math.to_rectangle_vertices ( - 40 , - 40 , self.x1 , gh + 40 ) , color = bg [ - 1 ] }
WallCover { group = self.post_main , vertices = math.to_rectangle_vertices ( self.x2 , - 40 , gw + 40 , gh + 40 ) , color = bg [ - 1 ] }
WallCover { group = self.post_main , vertices = math.to_rectangle_vertices ( self.x1 , - 40 , self.x2 , self.y1 ) , color = bg [ - 1 ] }
WallCover { group = self.post_main , vertices = math.to_rectangle_vertices ( self.x1 , self.y2 , self.x2 , gh + 40 ) , color = bg [ - 1 ] }
2021-02-21 06:47:59 +01:00
2021-03-02 06:27:15 +01:00
for i , unit in ipairs ( units ) do
if i == 1 then
2021-04-30 01:38:36 +02:00
self.player = Player { group = self.main , x = gw / 2 , y = gh / 2 + 16 , leader = true , character = unit.character , level = unit.level , passives = self.passives , ii = i }
2021-03-02 06:27:15 +01:00
else
2021-04-30 01:38:36 +02:00
self.player : add_follower ( Player { group = self.main , character = unit.character , level = unit.level , passives = self.passives , ii = i } )
2021-03-02 06:27:15 +01:00
end
end
2021-02-21 06:47:59 +01:00
2021-04-30 01:38:36 +02:00
local units = self.player : get_all_units ( )
for _ , unit in ipairs ( units ) do
local chp = CharacterHP { group = self.effects , x = self.x1 + 8 + ( unit.ii - 1 ) * 22 , y = self.y2 + 14 , parent = unit }
unit.character_hp = chp
end
2021-03-24 06:57:26 +01:00
if self.level == 1000 then
self.level_1000_text = Text2 { group = self.ui , x = gw / 2 , y = gh / 2 , lines = { { text = ' [fg, wavy_mid]SNKRX ' , font = fat_font , alignment = ' center ' } } }
-- 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]}
2021-04-04 01:49:54 +02:00
2021-07-04 20:13:19 +02:00
elseif ( self.level - ( 25 * self.loop ) ) % 6 == 0 or self.level % 25 == 0 then
2021-04-04 01:49:54 +02:00
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 }
2021-05-17 10:05:48 +02:00
SpawnMarker { group = self.effects , x = x , y = y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( )
2021-05-17 10:05:48 +02:00
self.boss = Seeker { group = self.main , x = x , y = y , character = ' seeker ' , level = self.level , boss = level_to_boss [ self.level ] }
end )
2021-04-04 01:49:54 +02:00
end }
2021-05-17 10:05:48 +02:00
self.t : every ( function ( )
if self.boss and not self.boss . dead then
return ( # self.main : get_objects_by_classes ( self.enemies ) <= 1 ) and not self.spawning_enemies
elseif self.boss and self.boss . dead then
return ( # self.main : get_objects_by_classes ( self.enemies ) <= 0 ) and not self.spawning_enemies
end
end , function ( )
2021-04-04 01:49:54 +02:00
self.hfx : use ( ' condition1 ' , 0.25 , 200 , 10 )
self.hfx : pull ( ' condition2 ' , 0.0625 )
self.t : after ( 0.5 , function ( )
2021-05-17 10:05:48 +02:00
self.spawning_enemies = true
self.t : after ( ( 8 + math.floor ( self.level / 2 ) ) * 0.1 + 0.5 + 0.75 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-04-04 01:49:54 +02:00
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 }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , nil , 8 + math.floor ( self.level / 2 ) ) end )
2021-04-04 01:49:54 +02:00
end )
end )
end )
2021-05-03 07:04:40 +02:00
self.t : every ( function ( ) return self.start_time <= 0 and ( self.boss and self.boss . dead ) and # self.main : get_objects_by_classes ( self.enemies ) <= 0 and not self.spawning_enemies and not self.quitting end , function ( )
2021-05-17 10:05:48 +02:00
self : quit ( )
2021-04-30 01:38:36 +02:00
if self.level == 6 then
state.achievement_speed_booster = true
system.save_state ( )
steam.userStats . setAchievement ( ' SPEED_BOOSTER ' )
steam.userStats . storeStats ( )
elseif self.level == 12 then
state.achievement_exploder = true
system.save_state ( )
steam.userStats . setAchievement ( ' EXPLODER ' )
steam.userStats . storeStats ( )
elseif self.level == 18 then
state.achievement_swarmer = true
system.save_state ( )
steam.userStats . setAchievement ( ' SWARMER ' )
steam.userStats . storeStats ( )
elseif self.level == 24 then
state.achievement_forcer = true
system.save_state ( )
steam.userStats . setAchievement ( ' FORCER ' )
steam.userStats . storeStats ( )
elseif self.level == 25 then
state.achievement_cluster = true
system.save_state ( )
steam.userStats . setAchievement ( ' CLUSTER ' )
steam.userStats . storeStats ( )
end
end )
2021-04-04 01:49:54 +02:00
end )
2021-03-24 06:57:26 +01:00
else
-- Set win condition and enemy spawns
2021-05-03 07:04:40 +02:00
self.win_condition = ' wave '
self.level_to_max_waves = {
2 , 3 , 4 ,
3 , 4 , 4 , 5 ,
5 , 5 , 5 , 5 , 7 ,
2021-06-25 18:25:13 +02:00
6 , 6 , 7 , 7 , 8 , 10 ,
8 , 8 , 10 , 12 , 14 , 16 , 25 ,
2021-05-03 07:04:40 +02:00
}
2021-07-01 03:34:48 +02:00
for i = 26 , 5000 do
local n = i % 25
if n == 0 then n = 25 end
self.level_to_max_waves [ i ] = self.level_to_max_waves [ n ]
end
2021-05-03 07:04:40 +02:00
self.level_to_distributed_enemies_chance = {
0 , 5 , 10 ,
10 , 15 , 15 , 20 ,
20 , 20 , 20 , 20 , 25 ,
25 , 25 , 25 , 25 , 25 , 30 ,
20 , 25 , 30 , 35 , 40 , 45 , 50 ,
}
2021-07-01 03:34:48 +02:00
for i = 26 , 5000 do
local n = i % 25
if n == 0 then n = 25 end
self.level_to_distributed_enemies_chance [ i ] = self.level_to_distributed_enemies_chance [ n ]
end
2021-05-03 07:04:40 +02:00
self.max_waves = self.level_to_max_waves [ self.level ]
self.wave = 0
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 }
2021-05-17 10:05:48 +02:00
self.t : every ( function ( ) return # self.main : get_objects_by_classes ( self.enemies ) <= 0 and not self.spawning_enemies end , function ( )
2021-05-03 07:04:40 +02:00
self.wave = self.wave + 1
if self.wave > self.max_waves then return end
2021-02-21 06:47:59 +01:00
self.hfx : use ( ' condition1 ' , 0.25 , 200 , 10 )
2021-05-03 07:04:40 +02:00
self.hfx : pull ( ' condition2 ' , 0.0625 )
self.t : after ( 0.5 , function ( )
if random : bool ( self.level_to_distributed_enemies_chance [ self.level ] ) then
2021-07-04 20:13:19 +02:00
local n = math.ceil ( ( 8 + ( self.wave + math.min ( self.loop * 6 , 60 ) - 1 ) * 2 ) / 7 )
2021-05-03 07:04:40 +02:00
for i = 1 , n do
self.t : after ( ( i - 1 ) * 2 , function ( )
self : spawn_distributed_enemies ( )
end )
end
else
2021-05-17 10:05:48 +02:00
self.spawning_enemies = true
self.t : after ( ( 8 + ( self.wave - 1 ) * 2 ) * 0.1 + 0.5 + 0.75 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-03-24 06:57:26 +01:00
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 } }
2021-03-31 00:46:27 +02:00
local p = spawn_points [ spawn_type ]
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-07-04 20:13:19 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , nil , 8 + ( self.wave + math.min ( self.loop * 12 , 200 ) - 1 ) * 2 ) end )
2021-03-24 06:57:26 +01:00
end
2021-05-03 07:04:40 +02:00
end )
end , self.max_waves + 1 )
2021-02-21 06:47:59 +01:00
end )
2021-05-17 10:05:48 +02:00
self.t : every ( function ( ) return # self.main : get_objects_by_classes ( self.enemies ) <= 0 and self.wave > self.max_waves and not self.quitting and not self.spawning_enemies end , function ( ) self : quit ( ) end )
2021-05-03 07:04:40 +02:00
end )
2021-03-24 06:57:26 +01:00
2021-05-17 10:05:48 +02:00
if self.level == 20 and self.trailer then
2021-03-24 06:57:26 +01:00
Text2 { group = self.ui , x = gw / 2 , y = gh / 2 - 24 , lines = { { text = ' [fg, wavy]SNKRX ' , font = fat_font , alignment = ' center ' } } }
2021-05-17 10:05:48 +02:00
Text2 { group = self.ui , x = gw / 2 , y = gh / 2 , sx = 0.5 , sy = 0.5 , lines = { { text = ' [fg, wavy_mid]play now! ' , font = fat_font , alignment = ' center ' } } }
2021-03-24 06:57:26 +01:00
Text2 { group = self.ui , x = gw / 2 , y = gh / 2 + 24 , sx = 0.5 , sy = 0.5 , lines = { { text = ' [light_bg, wavy_mid]music: kubbi - ember ' , font = fat_font , alignment = ' center ' } } }
end
2021-03-08 05:33:01 +01:00
end
if self.level == 1 then
2021-03-10 06:47:27 +01:00
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 ' } } }
2021-05-17 19:27:01 +02:00
local t3 = Text2 { group = self.floor , x = gw / 2 , y = gh / 2 + 46 , sx = 0.6 , sy = 0.6 , lines = { { text = ' [light_bg]esc - options ' , font = fat_font , alignment = ' center ' } } }
2021-06-24 17:09:29 +02:00
--[[
2021-05-17 19:27:01 +02:00
local t4 = Text2 { group = self.floor , x = gw / 2 , y = gh / 2 + 68 , sx = 0.6 , sy = 0.6 , lines = { { text = ' [light_bg]n - mute sfx ' , font = fat_font , alignment = ' center ' } } }
local t5 = Text2 { group = self.floor , x = gw / 2 , y = gh / 2 + 90 , sx = 0.6 , sy = 0.6 , lines = { { text = ' [light_bg]m - mute music ' , font = fat_font , alignment = ' center ' } } }
2021-06-24 17:09:29 +02:00
] ] --
2021-03-08 05:33:01 +01:00
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 )
t3.t : after ( 8 , function ( ) t3.t : tween ( 0.2 , t3 , { sy = 0 } , math.linear , function ( ) t3.sy = 0 end ) end )
2021-06-24 17:09:29 +02:00
--[[
2021-03-08 05:33:01 +01:00
t4.t : after ( 8 , function ( ) t4.t : tween ( 0.2 , t4 , { sy = 0 } , math.linear , function ( ) t4.sy = 0 end ) end )
2021-05-17 19:27:01 +02:00
t5.t : after ( 8 , function ( ) t4.t : tween ( 0.2 , t5 , { sy = 0 } , math.linear , function ( ) t5.sy = 0 end ) end )
2021-06-24 17:09:29 +02:00
] ] --
2021-02-21 06:47:59 +01:00
end
2021-02-27 05:28:00 +01:00
2021-03-05 08:29:19 +01:00
-- Calculate class levels
2021-02-27 05:28:00 +01:00
local units = { }
table.insert ( units , self.player )
for _ , f in ipairs ( self.player . followers ) do table.insert ( units , f ) end
2021-04-12 04:51:34 +02:00
local class_levels = get_class_levels ( units )
2021-04-10 00:46:49 +02:00
self.ranger_level = class_levels.ranger
self.warrior_level = class_levels.warrior
self.mage_level = class_levels.mage
self.rogue_level = class_levels.rogue
self.nuker_level = class_levels.nuker
2021-04-12 04:51:34 +02:00
self.curser_level = class_levels.curser
2021-04-10 00:46:49 +02:00
self.forcer_level = class_levels.forcer
self.swarmer_level = class_levels.swarmer
self.voider_level = class_levels.voider
self.enchanter_level = class_levels.enchanter
self.healer_level = class_levels.healer
self.psyker_level = class_levels.psyker
self.conjurer_level = class_levels.conjurer
2021-06-02 07:43:03 +02:00
self.sorcerer_level = class_levels.sorcerer
2021-06-10 19:39:40 +02:00
self.mercenary_level = class_levels.mercenary
2021-05-03 07:04:40 +02:00
2021-05-17 10:05:48 +02:00
self.t : every ( 0.375 , function ( )
local p = random : table ( star_positions )
Star { group = star_group , x = p.x , y = p.y }
end )
2021-05-29 10:10:52 +02:00
self.enemy_spawns_prevented = 0
self.t : every ( 8 , function ( )
if self.died then return end
if self.arena_clear_text then return end
if self.quitting then return end
if self.spawning_enemies then return end
2021-06-04 06:05:59 +02:00
if self.won then return end
if self.choosing_passives then return end
2021-05-29 10:10:52 +02:00
local n = self.enemy_spawns_prevented
if math.floor ( n / 4 ) <= 0 then return end
self.spawning_enemies = true
local spawn_points = table.copy ( self.spawn_points )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 1 , math.floor ( n / 4 ) , true ) end )
2021-05-29 10:10:52 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 2 , math.floor ( n / 4 ) , true ) end )
2021-05-29 10:10:52 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 3 , math.floor ( n / 4 ) , true ) end )
2021-05-29 10:10:52 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 4 , math.floor ( n / 4 ) , true ) end )
2021-05-29 10:10:52 +02:00
end )
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 + math.floor ( n / 4 ) * 0.25 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-05-29 10:10:52 +02:00
self.enemy_spawns_prevented = 0
end )
2021-05-17 10:05:48 +02:00
end
function Arena : on_exit ( )
self.floor : destroy ( )
self.main : destroy ( )
self.post_main : destroy ( )
self.effects : destroy ( )
self.ui : destroy ( )
self.credits : destroy ( )
self.t : destroy ( )
self.floor = nil
self.main = nil
self.post_main = nil
self.effects = nil
self.ui = nil
self.credits = nil
self.units = nil
self.passives = nil
self.player = nil
self.t = nil
self.springs = nil
self.flashes = nil
self.hfx = nil
2021-02-18 05:11:25 +01:00
end
function Arena : update ( dt )
2021-05-17 10:05:48 +02:00
if main_song_instance : isStopped ( ) then
main_song_instance = _G [ random : table { ' song1 ' , ' song2 ' , ' song3 ' , ' song4 ' , ' song5 ' } ] : play { volume = 0.5 }
2021-04-04 01:49:54 +02:00
end
2021-06-05 08:11:23 +02:00
if self.shop_text then self.shop_text : update ( dt ) end
2021-05-29 10:10:52 +02:00
2021-06-04 06:05:59 +02:00
if input.escape . pressed and not self.transitioning and not self.in_credits and not self.choosing_passives then
2021-03-17 10:30:20 +01:00
if not self.paused then
2021-06-23 05:53:37 +02:00
open_options ( self )
2021-03-17 10:30:20 +01:00
else
2021-06-23 05:53:37 +02:00
close_options ( self )
2021-03-17 10:30:20 +01:00
end
end
2021-05-17 10:05:48 +02:00
if self.paused or self.died or self.won and not self.transitioning then
2021-03-17 10:30:20 +01:00
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 }
2021-06-16 07:37:40 +02:00
TransitionEffect { group = main.transitions , x = gw / 2 , y = gh / 2 , color = state.dark_transitions and bg [ - 2 ] or fg [ 0 ] , transition_action = function ( )
2021-03-17 10:30:20 +01:00
slow_amount = 1
2021-07-04 06:50:31 +02:00
music_slow_amount = 1
2021-06-11 14:07:27 +02:00
gold = 3
2021-04-24 05:19:22 +02:00
passives = { }
2021-05-17 10:05:48 +02:00
main_song_instance : stop ( )
2021-06-16 07:37:40 +02:00
run_passive_pool = {
2021-06-17 07:45:14 +02:00
' centipede ' , ' ouroboros_technique_r ' , ' ouroboros_technique_l ' , ' amplify ' , ' resonance ' , ' ballista ' , ' call_of_the_void ' , ' crucio ' , ' speed_3 ' , ' damage_4 ' , ' shoot_5 ' , ' death_6 ' , ' lasting_7 ' ,
2021-06-18 07:32:19 +02:00
' defensive_stance ' , ' offensive_stance ' , ' kinetic_bomb ' , ' porcupine_technique ' , ' last_stand ' , ' seeping ' , ' deceleration ' , ' annihilation ' , ' malediction ' , ' hextouch ' , ' whispers_of_doom ' ,
2021-06-16 07:37:40 +02:00
' tremor ' , ' heavy_impact ' , ' fracture ' , ' meat_shield ' , ' hive ' , ' baneling_burst ' , ' blunt_arrow ' , ' explosive_arrow ' , ' divine_machine_arrow ' , ' chronomancy ' , ' awakening ' , ' divine_punishment ' ,
' assassination ' , ' flying_daggers ' , ' ultimatum ' , ' magnify ' , ' echo_barrage ' , ' unleash ' , ' reinforce ' , ' payback ' , ' enchanted ' , ' freezing_field ' , ' burning_field ' , ' gravity_field ' , ' magnetism ' ,
2021-07-04 06:50:31 +02:00
' insurance ' , ' dividends ' , ' berserking ' , ' unwavering_stance ' , ' unrelenting_stance ' , ' blessing ' , ' haste ' , ' divine_barrage ' , ' orbitism ' , ' psyker_orbs ' , ' psychosink ' , ' rearm ' , ' taunt ' , ' construct_instability ' ,
2021-07-03 07:08:35 +02:00
' intimidation ' , ' vulnerability ' , ' temporal_chains ' , ' ceremonial_dagger ' , ' homing_barrage ' , ' critical_strike ' , ' noxious_strike ' , ' infesting_strike ' , ' burning_strike ' , ' lucky_strike ' , ' healing_strike ' , ' stunning_strike ' ,
2021-07-04 06:50:31 +02:00
' silencing_strike ' , ' culling_strike ' , ' lightning_strike ' , ' psycholeak ' , ' divine_blessing ' , ' hardening ' ,
2021-05-03 07:04:40 +02:00
}
2021-07-01 03:34:48 +02:00
max_units = math.clamp ( 7 + current_new_game_plus + self.loop , 7 , 12 )
2021-03-17 10:30:20 +01:00
main : add ( BuyScreen ' buy_screen ' )
2021-06-04 06:05:59 +02:00
locked_state = nil
2021-05-29 10:10:52 +02:00
system.save_run ( )
2021-07-01 03:34:48 +02:00
main : go_to ( ' buy_screen ' , 1 , 0 , { } , passives , 1 , 0 )
2021-06-16 07:37:40 +02:00
end , text = Text ( { { text = ' [wavy, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]restarting... ' , font = pixul_font , alignment = ' center ' } } , global_text_tags ) }
2021-03-17 10:30:20 +01:00
end
2021-05-17 10:05:48 +02:00
if input.escape . pressed then
self.in_credits = false
if self.credits_button then self.credits_button : on_mouse_exit ( ) end
for _ , object in ipairs ( self.credits . objects ) do
object.dead = true
end
self.credits : update ( 0 )
end
2021-03-17 10:30:20 +01:00
end
2021-02-18 05:11:25 +01:00
self : update_game_object ( dt * slow_amount )
2021-07-04 06:50:31 +02:00
main_song_instance.pitch = math.clamp ( slow_amount * music_slow_amount , 0.05 , 1 )
2021-03-17 10:30:20 +01:00
2021-05-17 10:05:48 +02:00
star_group : update ( dt * slow_amount )
2021-03-08 05:33:01 +01:00
self.floor : update ( dt * slow_amount )
2021-03-15 05:01:04 +01:00
self.main : update ( dt * slow_amount * self.main_slow_amount )
2021-02-22 03:54:50 +01:00
self.post_main : update ( dt * slow_amount )
2021-02-18 05:11:25 +01:00
self.effects : update ( dt * slow_amount )
self.ui : update ( dt * slow_amount )
2021-05-17 10:05:48 +02:00
self.credits : update ( dt )
end
2021-02-18 19:28:40 +01:00
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
function Arena : quit ( )
2021-06-04 06:05:59 +02:00
if self.died then return end
2021-05-17 10:05:48 +02:00
self.quitting = true
2021-07-01 03:34:48 +02:00
if self.level % 25 == 0 then
self : gain_gold ( )
2021-05-17 10:05:48 +02:00
if not self.win_text and not self.win_text2 then
2021-06-10 19:39:40 +02:00
input : set_mouse_visible ( true )
2021-05-17 10:05:48 +02:00
self.won = true
2021-06-04 06:05:59 +02:00
locked_state = nil
2021-06-14 06:59:16 +02:00
if current_new_game_plus == new_game_plus then
new_game_plus = new_game_plus + 1
state.new_game_plus = new_game_plus
end
current_new_game_plus = current_new_game_plus + 1
state.current_new_game_plus = current_new_game_plus
2021-07-01 03:34:48 +02:00
max_units = math.clamp ( 7 + current_new_game_plus + self.loop , 7 , 12 )
2021-06-14 06:59:16 +02:00
2021-05-29 10:10:52 +02:00
system.save_run ( )
2021-05-21 08:17:31 +02:00
trigger : tween ( 1 , _G , { slow_amount = 0 } , math.linear , function ( ) slow_amount = 0 end , ' slow_amount ' )
2021-07-04 06:50:31 +02:00
trigger : tween ( 1 , _G , { music_slow_amount = 0 } , math.linear , function ( ) music_slow_amount = 0 end , ' music_slow_amount ' )
2021-05-17 10:05:48 +02:00
trigger : tween ( 4 , camera , { x = gw / 2 , y = gh / 2 , r = 0 } , math.linear , function ( ) camera.x , camera.y , camera.r = gw / 2 , gh / 2 , 0 end )
2021-07-01 03:34:48 +02:00
self.win_text = Text2 { group = self.ui , x = gw / 2 + 40 , y = gh / 2 - 69 , force_update = true , lines = { { text = ' [wavy_mid, cbyc2]congratulations! ' , font = fat_font , alignment = ' center ' } } }
2021-05-17 10:05:48 +02:00
trigger : after ( 2.5 , function ( )
2021-05-29 10:10:52 +02:00
self.build_text = Text2 { group = self.ui , x = 40 , y = 20 , force_update = true , lines = { { text = " [wavy_mid, fg]your build " , font = pixul_font , alignment = ' center ' } } }
for i , unit in ipairs ( self.units ) do
2021-06-14 06:59:16 +02:00
CharacterPart { group = self.ui , x = 20 , y = 40 + ( i - 1 ) * 19 , character = unit.character , level = unit.level , force_update = true , cant_click = true , parent = self }
Text2 { group = self.ui , x = 20 + 14 + pixul_font : get_text_width ( unit.character ) / 2 , y = 40 + ( i - 1 ) * 19 , force_update = true , lines = {
{ text = ' [ ' .. character_color_strings [ unit.character ] .. ' ] ' .. unit.character , font = pixul_font , alignment = ' left ' }
} }
2021-05-29 10:10:52 +02:00
end
2021-07-01 03:34:48 +02:00
for i , passive in ipairs ( self.passives ) do
ItemCard { group = self.ui , x = 120 + ( i - 1 ) * 30 , y = 20 , w = 30 , h = 45 , sx = 0.75 , sy = 0.75 , force_update = true , passive = passive.passive , level = passive.level , xp = passive.xp , parent = self }
end
2021-05-29 10:10:52 +02:00
2021-06-14 06:59:16 +02:00
if current_new_game_plus == 6 then
if current_new_game_plus == new_game_plus then
new_game_plus = 5
state.new_game_plus = new_game_plus
end
current_new_game_plus = 5
state.current_new_game_plus = current_new_game_plus
max_units = 12
2021-07-01 03:34:48 +02:00
self.win_text2 = Text2 { group = self.ui , x = gw / 2 + 40 , y = gh / 2 + 20 , force_update = true , lines = {
2021-05-17 10:05:48 +02:00
{ text = " [fg]now you've really beaten the game! " , font = pixul_font , alignment = ' center ' , height_multiplier = 1.24 } ,
{ text = " [fg]thanks a lot for playing it and completing it entirely! " , font = pixul_font , alignment = ' center ' , height_multiplier = 1.24 } ,
2021-07-01 03:34:48 +02:00
{ text = " [fg]this game was inspired by: " , font = pixul_font , alignment = ' center ' , height_multiplier = 3.5 } ,
{ text = " [fg]so check them out! and to get more games like this: " , font = pixul_font , alignment = ' center ' , height_multiplier = 3.5 } ,
2021-05-17 10:05:48 +02:00
{ text = " [wavy_mid, yellow]thanks for playing! " , font = pixul_font , alignment = ' center ' } ,
} }
2021-07-01 03:34:48 +02:00
SteamFollowButton { group = self.ui , x = gw / 2 + 40 , y = gh / 2 + 58 , force_update = true }
2021-05-17 10:05:48 +02:00
Button { group = self.ui , x = gw - 40 , y = gh - 44 , force_update = true , button_text = ' credits ' , fg_color = ' bg10 ' , bg_color = ' bg ' , action = function ( ) self : create_credits ( ) end }
2021-07-01 03:34:48 +02:00
Button { group = self.ui , x = gw - 39 , y = gh - 20 , force_update = true , button_text = ' loop ' , fg_color = ' bg10 ' , bg_color = ' bg ' , action = function ( ) self : endless ( ) end }
self.try_loop_text = Text2 { group = self.ui , x = gw - 144 , y = gh - 20 , force_update = true , lines = {
{ text = ' [bg10]continue run (+difficulty): ' , font = pixul_font } ,
} }
2021-05-17 10:05:48 +02:00
local open_url = function ( b , url )
ui_switch2 : play { pitch = random : float ( 0.95 , 1.05 ) , volume = 0.5 }
b.spring : pull ( 0.2 , 200 , 10 )
b.selected = true
ui_switch1 : play { pitch = random : float ( 0.95 , 1.05 ) , volume = 0.5 }
system.open_url ( url )
end
2021-06-14 06:59:16 +02:00
Button { group = self.ui , x = gw / 2 - 50 + 40 , y = gh / 2 + 12 , force_update = true , button_text = ' nimble quest ' , fg_color = ' bluem5 ' , bg_color = ' blue ' , action = function ( b ) open_url ( b , ' https://store.steampowered.com/app/259780/Nimble_Quest/ ' ) end }
Button { group = self.ui , x = gw / 2 + 50 + 40 , y = gh / 2 + 12 , force_update = true , button_text = ' dota underlords ' , fg_color = ' bluem5 ' , bg_color = ' blue ' , action = function ( b ) open_url ( b , ' https://store.steampowered.com/app/1046930/Dota_Underlords/ ' ) end }
2021-07-01 03:34:48 +02:00
2021-05-17 10:05:48 +02:00
else
2021-07-01 03:34:48 +02:00
self.win_text2 = Text2 { group = self.ui , x = gw / 2 + 40 , y = gh / 2 + 5 , force_update = true , lines = {
{ text = " [fg]you've beaten the game! " , font = pixul_font , alignment = ' center ' , height_multiplier = 1.24 } ,
{ text = " [fg]if you liked it: " , font = pixul_font , alignment = ' center ' , height_multiplier = 3.5 } ,
{ text = " [fg]and if you liked the music: " , font = pixul_font , alignment = ' center ' , height_multiplier = 3.5 } ,
{ text = " [wavy_mid, yellow]thanks for playing! " , font = pixul_font , alignment = ' center ' } ,
} }
--[[
2021-06-14 06:59:16 +02:00
self.win_text2 = Text2 { group = self.ui , x = gw / 2 + 40 , y = gh / 2 + 20 , force_update = true , lines = {
2021-05-17 10:05:48 +02:00
{ text = " [fg]you've beaten the game! " , font = pixul_font , alignment = ' center ' , height_multiplier = 1.24 } ,
{ text = " [fg]i made this game in 3 months as a dev challenge " , font = pixul_font , alignment = ' center ' , height_multiplier = 1.24 } ,
{ text = " [fg]and i'm happy with how it turned out! " , font = pixul_font , alignment = ' center ' , height_multiplier = 1.24 } ,
{ text = " [fg]if you liked it too and want to play more games like this: " , font = pixul_font , alignment = ' center ' , height_multiplier = 4 } ,
{ text = " [fg]i will release more games this year, so stay tuned! " , font = pixul_font , alignment = ' center ' , height_multiplier = 1.4 } ,
{ text = " [wavy_mid, yellow]thanks for playing! " , font = pixul_font , alignment = ' center ' } ,
} }
2021-07-01 03:34:48 +02:00
] ] --
SteamFollowButton { group = self.ui , x = gw / 2 + 40 , y = gh / 2 - 10 , force_update = true }
Button { group = self.ui , x = gw / 2 + 40 , y = gh / 2 + 33 , force_update = true , button_text = ' buy the soundtrack! ' , fg_color = ' greenm5 ' , bg_color = ' green ' , action = function ( ) open_url ( b , ' https://kubbimusic.com/album/ember ' ) end }
Button { group = self.ui , x = gw - 40 , y = gh - 44 , force_update = true , button_text = ' loop ' , fg_color = ' bg10 ' , bg_color = ' bg ' , action = function ( ) self : endless ( ) end }
2021-05-17 10:05:48 +02:00
RestartButton { group = self.ui , x = gw - 40 , y = gh - 20 , force_update = true }
2021-07-01 03:34:48 +02:00
self.try_loop_text = Text2 { group = self.ui , x = gw - 200 , y = gh - 44 , force_update = true , lines = {
{ text = ' [bg10]continue run (+difficulty, +1 max snake size): ' , font = pixul_font } ,
} }
self.try_ng_text = Text2 { group = self.ui , x = gw - 187 , y = gh - 20 , force_update = true , lines = {
{ text = ' [bg10]new run (+difficulty, +1 max snake size): ' , font = pixul_font } ,
} }
self.credits_button = Button { group = self.ui , x = gw - 40 , y = gh - 68 , force_update = true , button_text = ' credits ' , fg_color = ' bg10 ' , bg_color = ' bg ' , action = function ( ) self : create_credits ( ) end }
2021-04-30 01:38:36 +02:00
end
2021-05-17 10:05:48 +02:00
end )
2021-04-30 01:38:36 +02:00
2021-06-16 07:37:40 +02:00
if current_new_game_plus == 2 then
2021-05-17 10:05:48 +02:00
state.achievement_new_game_1 = true
system.save_state ( )
steam.userStats . setAchievement ( ' NEW_GAME_1 ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-06-16 07:37:40 +02:00
if current_new_game_plus == 6 then
2021-05-17 10:05:48 +02:00
state.achievement_new_game_5 = true
system.save_state ( )
steam.userStats . setAchievement ( ' GAME_COMPLETE ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.ranger_level >= 2 then
state.achievement_rangers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' RANGERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.warrior_level >= 2 then
state.achievement_warriors_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' WARRIORS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.mage_level >= 2 then
state.achievement_mages_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' MAGES_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.rogue_level >= 2 then
state.achievement_rogues_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' ROGUES_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.healer_level >= 2 then
state.achievement_healers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' HEALERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.enchanter_level >= 2 then
state.achievement_enchanters_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' ENCHANTERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.nuker_level >= 2 then
state.achievement_nukers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' NUKERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.conjurer_level >= 2 then
state.achievement_conjurers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' CONJURERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-07-04 06:50:31 +02:00
if self.psyker_level >= 2 then
2021-05-17 10:05:48 +02:00
state.achievement_psykers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' PSYKERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.curser_level >= 2 then
state.achievement_cursers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' CURSERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.forcer_level >= 2 then
state.achievement_forcers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' FORCERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.swarmer_level >= 2 then
state.achievement_swarmers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' SWARMERS_WIN ' )
steam.userStats . storeStats ( )
2021-03-17 10:30:20 +01:00
end
2021-05-17 10:05:48 +02:00
if self.voider_level >= 2 then
state.achievement_voiders_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' VOIDERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-05-18 05:38:51 +02:00
2021-06-02 07:43:03 +02:00
if self.sorcerer_level >= 3 then
state.achievement_sorcerers_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' SORCERERS_WIN ' )
steam.userStats . storeStats ( )
end
2021-06-10 19:39:40 +02:00
if self.mercenary_level >= 2 then
state.achievement_mercenaries_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' MERCENARIES_WIN ' )
steam.userStats . storeStats ( )
end
2021-05-18 05:38:51 +02:00
local all_units_level_2 = true
2021-06-14 06:59:16 +02:00
for _ , unit in ipairs ( self.starting_units ) do
2021-05-18 05:38:51 +02:00
if unit.level ~= 2 then
all_units_level_2 = false
break
end
end
if all_units_level_2 then
state.achievement_level_2_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' LEVEL_2_WIN ' )
steam.userStats . storeStats ( )
end
local units = self.player : get_all_units ( )
local all_units_level_3 = true
2021-06-14 06:59:16 +02:00
for _ , unit in ipairs ( self.starting_units ) do
2021-05-18 05:38:51 +02:00
if unit.level ~= 3 then
all_units_level_3 = false
break
end
end
if all_units_level_3 then
state.achievement_level_3_win = true
system.save_state ( )
steam.userStats . setAchievement ( ' LEVEL_3_WIN ' )
steam.userStats . storeStats ( )
end
2021-03-17 10:30:20 +01:00
end
2021-05-17 10:05:48 +02:00
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
2021-06-09 06:35:57 +02:00
self : gain_gold ( )
2021-06-29 07:08:51 +02:00
self.t : after ( 2 , function ( )
2021-06-29 18:27:04 +02:00
self.slow_transitioning = true
2021-06-29 07:08:51 +02:00
self.t : tween ( 0.7 , self , { main_slow_amount = 0 } , math.linear , function ( ) self.main_slow_amount = 0 end )
end )
2021-05-17 10:05:48 +02:00
self.t : after ( 3 , function ( )
2021-07-01 03:34:48 +02:00
if ( self.level - ( 25 * self.loop ) ) % 3 == 0 and # self.passives < 8 then
2021-06-10 19:39:40 +02:00
input : set_mouse_visible ( true )
2021-05-17 10:05:48 +02:00
self.arena_clear_text . dead = true
2021-05-21 08:17:31 +02:00
trigger : tween ( 1 , _G , { slow_amount = 0 } , math.linear , function ( ) slow_amount = 0 end , ' slow_amount ' )
2021-07-04 06:50:31 +02:00
trigger : tween ( 1 , _G , { music_slow_amount = 0 } , math.linear , function ( ) music_slow_amount = 0 end , ' music_slow_amount ' )
2021-05-17 10:05:48 +02:00
trigger : tween ( 4 , camera , { x = gw / 2 , y = gh / 2 , r = 0 } , math.linear , function ( ) camera.x , camera.y , camera.r = gw / 2 , gh / 2 , 0 end )
2021-06-05 08:11:23 +02:00
self : set_passives ( )
2021-06-24 17:09:29 +02:00
RerollButton { group = main.current . ui , x = gw - 40 , y = gh - 40 , parent = self , force_update = true }
2021-06-05 08:11:23 +02:00
self.shop_text = Text ( { { text = ' [wavy_mid, fg]gold: [yellow] ' .. gold , font = pixul_font , alignment = ' center ' } } , global_text_tags )
2021-06-18 23:36:00 +02:00
self.build_text = Text2 { group = self.ui , x = 40 , y = 20 , force_update = true , lines = { { text = " [wavy_mid, fg]your build " , font = pixul_font , alignment = ' center ' } } }
for i , unit in ipairs ( self.units ) do
CharacterPart { group = self.ui , x = 20 , y = 40 + ( i - 1 ) * 19 , character = unit.character , level = unit.level , force_update = true , cant_click = true , parent = self }
Text2 { group = self.ui , x = 20 + 14 + pixul_font : get_text_width ( unit.character ) / 2 , y = 40 + ( i - 1 ) * 19 , force_update = true , lines = {
{ text = ' [ ' .. character_color_strings [ unit.character ] .. ' ] ' .. unit.character , font = pixul_font , alignment = ' left ' }
} }
end
2021-06-29 07:08:51 +02:00
for i , passive in ipairs ( self.passives ) do
ItemCard { group = self.ui , x = 120 + ( i - 1 ) * 30 , y = gh - 30 , w = 30 , h = 45 , sx = 0.75 , sy = 0.75 , force_update = true , passive = passive.passive , level = passive.level , xp = passive.xp , parent = self }
end
2021-05-17 10:05:48 +02:00
else
self : transition ( )
end
end , ' transition ' )
2021-02-18 19:28:40 +01:00
end
2021-02-18 05:11:25 +01:00
end
2021-06-05 08:11:23 +02:00
function Arena : set_passives ( from_reroll )
if from_reroll then
self : restore_passives_to_pool ( 0 )
2021-06-14 06:59:16 +02:00
if self.cards [ 1 ] then self.cards [ 1 ] . dead = true end
if self.cards [ 2 ] then self.cards [ 2 ] . dead = true end
if self.cards [ 3 ] then self.cards [ 3 ] . dead = true end
2021-07-04 06:50:31 +02:00
if self.cards [ 4 ] then self.cards [ 4 ] . dead = true end
2021-06-05 08:11:23 +02:00
self.cards = { }
end
2021-07-04 06:50:31 +02:00
local card_w , card_h = 70 , 100
local w = 4 * card_w + 3 * 20
2021-06-05 08:11:23 +02:00
self.choosing_passives = true
self.cards = { }
2021-06-16 07:37:40 +02:00
local passive_1 = random : table_remove ( run_passive_pool )
local passive_2 = random : table_remove ( run_passive_pool )
local passive_3 = random : table_remove ( run_passive_pool )
2021-07-04 06:50:31 +02:00
local passive_4 = random : table_remove ( run_passive_pool )
2021-06-05 08:11:23 +02:00
if passive_1 then
2021-06-24 17:09:29 +02:00
table.insert ( self.cards , PassiveCard { group = main.current . ui , x = gw / 2 - w / 2 + 0 * ( card_w + 20 ) + card_w / 2 + 45 , y = gh / 2 - 20 , w = card_w , h = card_h , card_i = 1 , arena = self , passive = passive_1 , force_update = true } )
2021-06-05 08:11:23 +02:00
end
if passive_2 then
2021-07-04 06:50:31 +02:00
table.insert ( self.cards , PassiveCard { group = main.current . ui , x = gw / 2 - w / 2 + 1 * ( card_w + 20 ) + card_w / 2 + 45 , y = gh / 2 , w = card_w , h = card_h , card_i = 2 , arena = self , passive = passive_2 , force_update = true } )
2021-06-05 08:11:23 +02:00
end
if passive_3 then
2021-06-24 17:09:29 +02:00
table.insert ( self.cards , PassiveCard { group = main.current . ui , x = gw / 2 - w / 2 + 2 * ( card_w + 20 ) + card_w / 2 + 45 , y = gh / 2 - 20 , w = card_w , h = card_h , card_i = 3 , arena = self , passive = passive_3 , force_update = true } )
2021-06-05 08:11:23 +02:00
end
2021-07-04 06:50:31 +02:00
if passive_4 then
table.insert ( self.cards , PassiveCard { group = main.current . ui , x = gw / 2 - w / 2 + 3 * ( card_w + 20 ) + card_w / 2 + 45 , y = gh / 2 , w = card_w , h = card_h , card_i = 4 , arena = self , passive = passive_4 , force_update = true } )
end
2021-06-24 17:09:29 +02:00
self.passive_text = Text2 { group = self.ui , x = gw / 2 + 45 , y = gh / 2 - 75 , lines = { { text = ' [fg, wavy]choose one ' , font = fat_font , alignment = ' center ' } } }
2021-07-04 06:50:31 +02:00
if not passive_1 and not passive_2 and not passive_3 and not passive_4 then
2021-06-05 08:11:23 +02:00
self : transition ( )
end
end
2021-05-21 08:17:31 +02:00
function Arena : restore_passives_to_pool ( j )
2021-07-04 06:50:31 +02:00
for i = 1 , 4 do
2021-05-21 08:17:31 +02:00
if i ~= j then
2021-06-16 07:37:40 +02:00
if self.cards [ i ] then
table.insert ( run_passive_pool , self.cards [ i ] . passive )
2021-05-29 10:10:52 +02:00
end
2021-05-21 08:17:31 +02:00
end
end
end
2021-02-18 05:11:25 +01:00
function Arena : draw ( )
2021-03-08 05:33:01 +01:00
self.floor : draw ( )
2021-02-18 05:11:25 +01:00
self.main : draw ( )
2021-02-22 03:54:50 +01:00
self.post_main : draw ( )
2021-02-18 05:11:25 +01:00
self.effects : draw ( )
2021-02-21 06:47:59 +01:00
2021-04-24 05:19:22 +02:00
graphics.draw_with_mask ( function ( )
star_canvas : draw ( 0 , 0 , 0 , 1 , 1 )
end , function ( )
camera : attach ( )
graphics.rectangle ( gw / 2 , gh / 2 , self.w , self.h , nil , nil , fg [ 0 ] )
camera : detach ( )
end , true )
2021-02-21 06:47:59 +01:00
camera : attach ( )
2021-04-17 05:30:34 +02:00
if self.start_time and self.start_time > 0 and not self.choosing_passives then
2021-02-21 06:47:59 +01:00
graphics.push ( gw / 2 , gh / 2 - 48 , 0 , self.hfx . condition1.x , self.hfx . condition1.x )
graphics.print_centered ( tostring ( self.start_time ) , fat_font , gw / 2 , gh / 2 - 48 , 0 , 1 , 1 , nil , nil , self.hfx . condition1.f and fg [ 0 ] or red [ 0 ] )
graphics.pop ( )
end
2021-04-04 01:49:54 +02:00
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
2021-05-03 07:04:40 +02:00
if self.win_condition == ' wave ' then
2021-04-04 01:49:54 +02:00
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 ( )
2021-05-03 07:04:40 +02:00
local wave = self.wave
if wave > self.max_waves then wave = self.max_waves end
graphics.push ( self.x2 - 25 + fat_font : get_text_width ( wave .. ' / ' .. self.max_waves ) / 2 , self.y1 - 8 , 0 , self.hfx . condition1.x , self.hfx . condition1.x )
graphics.print ( 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 ] )
2021-04-04 01:49:54 +02:00
graphics.pop ( )
end
2021-02-21 06:47:59 +01:00
end
end
end
camera : detach ( )
2021-04-30 01:38:36 +02:00
2021-05-17 10:05:48 +02:00
if self.level == 20 and self.trailer then graphics.rectangle ( gw / 2 , gh / 2 , 2 * gw , 2 * gh , nil , nil , modal_transparent ) end
2021-04-30 01:38:36 +02:00
if self.choosing_passives or self.won or self.paused or self.died then graphics.rectangle ( gw / 2 , gh / 2 , 2 * gw , 2 * gh , nil , nil , modal_transparent ) end
self.ui : draw ( )
2021-05-17 10:05:48 +02:00
2021-06-24 17:09:29 +02:00
if self.shop_text then self.shop_text : draw ( gw - 40 , gh - 17 ) end
2021-06-05 08:11:23 +02:00
2021-05-17 10:05:48 +02:00
if self.in_credits then graphics.rectangle ( gw / 2 , gh / 2 , 2 * gw , 2 * gh , nil , nil , modal_transparent_2 ) end
self.credits : draw ( )
2021-02-18 05:11:25 +01:00
end
2021-02-18 19:28:40 +01:00
2021-03-15 05:01:04 +01:00
function Arena : die ( )
2021-06-04 06:05:59 +02:00
if not self.died_text and not self.won and not self.arena_clear_text then
2021-06-16 07:37:40 +02:00
input : set_mouse_visible ( true )
2021-05-30 17:00:03 +02:00
self.t : cancel ( ' divine_punishment ' )
2021-03-15 05:01:04 +01:00
self.died = true
2021-06-04 06:05:59 +02:00
locked_state = nil
2021-05-29 10:10:52 +02:00
system.save_run ( )
2021-03-15 05:01:04 +01:00
self.t : tween ( 2 , self , { main_slow_amount = 0 } , math.linear , function ( ) self.main_slow_amount = 0 end )
2021-07-04 06:50:31 +02:00
self.t : tween ( 2 , _G , { music_slow_amount = 0 } , math.linear , function ( ) music_slow_amount = 0 end )
2021-03-15 05:01:04 +01:00
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 } ,
} }
2021-07-04 06:50:31 +02:00
trigger : tween ( 2 , camera , { x = gw / 2 , y = gh / 2 , r = 0 } , math.linear , function ( ) camera.x , camera.y , camera.r = gw / 2 , gh / 2 , 0 end )
2021-03-15 05:01:04 +01:00
self.t : after ( 2 , function ( )
2021-07-04 06:50:31 +02:00
self.build_text = Text2 { group = self.ui , x = 40 , y = 20 , force_update = true , lines = { { text = " [wavy_mid, fg]your build " , font = pixul_font , alignment = ' center ' } } }
for i , unit in ipairs ( self.units ) do
CharacterPart { group = self.ui , x = 20 , y = 40 + ( i - 1 ) * 19 , character = unit.character , level = unit.level , force_update = true , cant_click = true , parent = self }
Text2 { group = self.ui , x = 20 + 14 + pixul_font : get_text_width ( unit.character ) / 2 , y = 40 + ( i - 1 ) * 19 , force_update = true , lines = {
{ text = ' [ ' .. character_color_strings [ unit.character ] .. ' ] ' .. unit.character , font = pixul_font , alignment = ' left ' }
} }
end
for i , passive in ipairs ( self.passives ) do
ItemCard { group = self.ui , x = 120 + ( i - 1 ) * 30 , y = 30 , w = 30 , h = 45 , sx = 0.75 , sy = 0.75 , force_update = true , passive = passive.passive , level = passive.level , xp = passive.xp , parent = self }
end
2021-05-17 10:05:48 +02:00
self.death_info_text = Text2 { group = self.ui , x = gw / 2 , y = gh / 2 , sx = 0.7 , sy = 0.7 , lines = {
2021-04-26 03:17:31 +02:00
{ text = ' [wavy_mid, fg]level reached: [wavy_mid, yellow] ' .. self.level , font = fat_font , alignment = ' center ' } ,
2021-03-15 05:01:04 +01:00
} }
2021-05-17 10:05:48 +02:00
self.restart_button = Button { group = self.ui , x = gw / 2 , y = gh / 2 + 24 , force_update = true , button_text = ' restart run (r) ' , fg_color = ' bg10 ' , bg_color = ' bg ' , action = function ( b )
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 }
2021-06-16 07:37:40 +02:00
TransitionEffect { group = main.transitions , x = gw / 2 , y = gh / 2 , color = state.dark_transitions and bg [ - 2 ] or fg [ 0 ] , transition_action = function ( )
2021-05-17 10:05:48 +02:00
slow_amount = 1
2021-07-04 06:50:31 +02:00
music_slow_amount = 1
2021-06-11 14:07:27 +02:00
gold = 3
2021-05-17 10:05:48 +02:00
passives = { }
main_song_instance : stop ( )
2021-06-16 07:37:40 +02:00
run_passive_pool = {
2021-06-17 07:45:14 +02:00
' centipede ' , ' ouroboros_technique_r ' , ' ouroboros_technique_l ' , ' amplify ' , ' resonance ' , ' ballista ' , ' call_of_the_void ' , ' crucio ' , ' speed_3 ' , ' damage_4 ' , ' shoot_5 ' , ' death_6 ' , ' lasting_7 ' ,
2021-06-18 07:32:19 +02:00
' defensive_stance ' , ' offensive_stance ' , ' kinetic_bomb ' , ' porcupine_technique ' , ' last_stand ' , ' seeping ' , ' deceleration ' , ' annihilation ' , ' malediction ' , ' hextouch ' , ' whispers_of_doom ' ,
2021-06-16 07:37:40 +02:00
' tremor ' , ' heavy_impact ' , ' fracture ' , ' meat_shield ' , ' hive ' , ' baneling_burst ' , ' blunt_arrow ' , ' explosive_arrow ' , ' divine_machine_arrow ' , ' chronomancy ' , ' awakening ' , ' divine_punishment ' ,
' assassination ' , ' flying_daggers ' , ' ultimatum ' , ' magnify ' , ' echo_barrage ' , ' unleash ' , ' reinforce ' , ' payback ' , ' enchanted ' , ' freezing_field ' , ' burning_field ' , ' gravity_field ' , ' magnetism ' ,
2021-07-04 06:50:31 +02:00
' insurance ' , ' dividends ' , ' berserking ' , ' unwavering_stance ' , ' unrelenting_stance ' , ' blessing ' , ' haste ' , ' divine_barrage ' , ' orbitism ' , ' psyker_orbs ' , ' psychosink ' , ' rearm ' , ' taunt ' , ' construct_instability ' ,
2021-07-03 07:08:35 +02:00
' intimidation ' , ' vulnerability ' , ' temporal_chains ' , ' ceremonial_dagger ' , ' homing_barrage ' , ' critical_strike ' , ' noxious_strike ' , ' infesting_strike ' , ' burning_strike ' , ' lucky_strike ' , ' healing_strike ' , ' stunning_strike ' ,
2021-07-04 06:50:31 +02:00
' silencing_strike ' , ' culling_strike ' , ' lightning_strike ' , ' psycholeak ' , ' divine_blessing ' , ' hardening ' ,
2021-05-17 10:05:48 +02:00
}
2021-07-01 03:34:48 +02:00
max_units = math.clamp ( 7 + current_new_game_plus + self.loop , 7 , 12 )
2021-05-17 10:05:48 +02:00
main : add ( BuyScreen ' buy_screen ' )
2021-05-29 10:10:52 +02:00
system.save_run ( )
2021-07-01 03:34:48 +02:00
main : go_to ( ' buy_screen ' , 1 , 0 , { } , passives , 1 , 0 )
2021-06-16 07:37:40 +02:00
end , text = Text ( { { text = ' [wavy, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]restarting... ' , font = pixul_font , alignment = ' center ' } } , global_text_tags ) }
2021-05-17 10:05:48 +02:00
end }
2021-03-15 05:01:04 +01:00
end )
2021-06-04 06:05:59 +02:00
return true
2021-03-15 05:01:04 +01:00
end
end
2021-07-01 03:34:48 +02:00
function Arena : endless ( )
current_new_game_plus = current_new_game_plus - 1
self.loop = self.loop + 1
self : transition ( )
end
2021-05-17 10:05:48 +02:00
function Arena : create_credits ( )
local open_url = function ( b , url )
ui_switch2 : play { pitch = random : float ( 0.95 , 1.05 ) , volume = 0.5 }
b.spring : pull ( 0.2 , 200 , 10 )
b.selected = true
ui_switch1 : play { pitch = random : float ( 0.95 , 1.05 ) , volume = 0.5 }
system.open_url ( url )
end
2021-06-28 06:47:57 +02:00
self.close_button = Button { group = self.credits , x = gw - 20 , y = 20 , button_text = ' x ' , bg_color = ' bg ' , fg_color = ' bg10 ' , credits_button = true , action = function ( )
trigger : after ( 0.01 , function ( )
self.in_credits = false
if self.credits_button then self.credits_button : on_mouse_exit ( ) end
for _ , object in ipairs ( self.credits . objects ) do
object.dead = true
end
self.credits : update ( 0 )
end )
end }
2021-05-17 10:05:48 +02:00
self.in_credits = true
Text2 { group = self.credits , x = 60 , y = 20 , lines = { { text = ' [bg10]main dev: ' , font = pixul_font } } }
Button { group = self.credits , x = 117 , y = 20 , button_text = ' a327ex ' , fg_color = ' bg10 ' , bg_color = ' bg ' , credits_button = true , action = function ( b ) open_url ( b , ' https://store.steampowered.com/dev/a327ex/ ' ) end }
2021-06-28 06:47:57 +02:00
Text2 { group = self.credits , x = 60 , y = 50 , lines = { { text = ' [bg10]mobile: ' , font = pixul_font } } }
Button { group = self.credits , x = 144 , y = 50 , button_text = ' David Khachaturov ' , fg_color = ' bg10 ' , bg_color = ' bg ' , credits_button = true , action = function ( b ) open_url ( b , ' https://davidobot.net/ ' ) end }
Text2 { group = self.credits , x = 60 , y = 80 , lines = { { text = ' [blue]libraries: ' , font = pixul_font } } }
Button { group = self.credits , x = 113 , y = 80 , button_text = ' love2d ' , fg_color = ' bluem5 ' , bg_color = ' blue ' , credits_button = true , action = function ( b ) open_url ( b , ' https://love2d.org ' ) end }
Button { group = self.credits , x = 170 , y = 80 , button_text = ' bakpakin ' , fg_color = ' bluem5 ' , bg_color = ' blue ' , credits_button = true , action = function ( b ) open_url ( b , ' https://github.com/bakpakin/binser ' ) end }
Button { group = self.credits , x = 237 , y = 80 , button_text = ' davisdude ' , fg_color = ' bluem5 ' , bg_color = ' blue ' , credits_button = true , action = function ( b ) open_url ( b , ' https://github.com/davisdude/mlib ' ) end }
Button { group = self.credits , x = 306 , y = 80 , button_text = ' tesselode ' , fg_color = ' bluem5 ' , bg_color = ' blue ' , credits_button = true , action = function ( b ) open_url ( b , ' https://github.com/tesselode/ripple ' ) end }
Text2 { group = self.credits , x = 60 , y = 110 , lines = { { text = ' [green]music: ' , font = pixul_font } } }
Button { group = self.credits , x = 100 , y = 110 , button_text = ' kubbi ' , fg_color = ' greenm5 ' , bg_color = ' green ' , credits_button = true , action = function ( b ) open_url ( b , ' https://kubbimusic.com/album/ember ' ) end }
Text2 { group = self.credits , x = 60 , y = 140 , lines = { { text = ' [yellow]sounds: ' , font = pixul_font } } }
Button { group = self.credits , x = 135 , y = 140 , button_text = ' sidearm studios ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://sidearm-studios.itch.io/ultimate-sound-fx-bundle ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 217 , y = 140 , button_text = ' justinbw ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://freesound.org/people/JustinBW/sounds/80921/ ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 279 , y = 140 , button_text = ' jcallison ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://freesound.org/people/jcallison/sounds/258269/ ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 342 , y = 140 , button_text = ' hybrid_v ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://freesound.org/people/Hybrid_V/sounds/321215/ ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 427 , y = 140 , button_text = ' womb_affliction ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://freesound.org/people/womb_affliction/sounds/376532/ ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 106 , y = 160 , button_text = ' bajko ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://freesound.org/people/bajko/sounds/399656/ ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 157 , y = 160 , button_text = ' benzix2 ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://freesound.org/people/benzix2/sounds/467951/ ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 204 , y = 160 , button_text = ' lord ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://store.steampowered.com/developer/T_TGames ' ) end }
2021-07-03 07:08:35 +02:00
Button { group = self.credits , x = 254 , y = 160 , button_text = ' InspectorJ ' , fg_color = ' yellowm5 ' , bg_color = ' yellow ' , credits_button = true , action = function ( b )
open_url ( b , ' https://freesound.org/people/InspectorJ/sounds/458586/ ' ) end }
2021-06-28 06:47:57 +02:00
Text2 { group = self.credits , x = 70 , y = 190 , lines = { { text = ' [red]playtesters: ' , font = pixul_font } } }
Button { group = self.credits , x = 130 , y = 190 , button_text = ' Jofer ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/JofersGames ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 172 , y = 190 , button_text = ' ekun ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/ekunenuke ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 224 , y = 190 , button_text = ' cvisy_GN ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/cvisy_GN ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 292 , y = 190 , button_text = ' Blue Fairy ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/blue9fairy ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 362 , y = 190 , button_text = ' Phil Blank ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/PhilBlankGames ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 440 , y = 190 , button_text = ' DefineDoddy ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/DefineDoddy ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 140 , y = 210 , button_text = ' Ge0force ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/Ge0forceBE ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 193 , y = 210 , button_text = ' Vlad ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/thecryru ' ) end }
2021-06-28 06:47:57 +02:00
Button { group = self.credits , x = 223 , y = 210 , button_text = ' F ' , fg_color = ' redm5 ' , bg_color = ' red ' , credits_button = true , action = function ( b )
2021-05-17 10:05:48 +02:00
open_url ( b , ' https://twitter.com/notyps ' ) end }
end
2021-06-09 06:35:57 +02:00
function Arena : gain_gold ( )
2021-06-29 07:08:51 +02:00
local merchant
for _ , unit in ipairs ( self.starting_units ) do
if unit.character == ' merchant ' then
merchant = true
break
end
end
2021-06-09 06:35:57 +02:00
self.gold_gained = random : int ( level_to_gold_gained [ self.level ] [ 1 ] , level_to_gold_gained [ self.level ] [ 2 ] )
2021-06-18 23:36:00 +02:00
self.interest = math.min ( math.floor ( gold / 5 ) , 5 ) + math.min ( ( merchant and math.floor ( gold / 10 ) or 0 ) , 10 )
2021-06-10 19:39:40 +02:00
gold = gold + self.gold_gained + self.gold_picked_up + self.interest
2021-06-09 06:35:57 +02:00
end
2021-04-19 05:31:47 +02:00
function Arena : transition ( )
self.transitioning = true
2021-06-14 06:59:16 +02:00
if not self.lock then locked_state = nil end
2021-04-19 05:31:47 +02:00
ui_transition2 : play { pitch = random : float ( 0.95 , 1.05 ) , volume = 0.5 }
2021-06-16 07:37:40 +02:00
TransitionEffect { group = main.transitions , x = self.player . x , y = self.player . y , color = state.dark_transitions and bg [ - 2 ] or self.color , transition_action = function ( t )
2021-06-11 06:44:06 +02:00
if self.level % 2 == 0 and self.shop_level < 5 then
self.shop_xp = self.shop_xp + 1
local max_xp = 0
if self.shop_level == 1 then max_xp = 3
elseif self.shop_level == 2 then max_xp = 4
elseif self.shop_level == 3 then max_xp = 5
elseif self.shop_level == 4 then max_xp = 6
elseif self.shop_level == 5 then max_xp = 0 end
if self.shop_xp >= max_xp then
self.shop_xp = 0
self.shop_level = self.shop_level + 1
end
2021-07-04 20:13:19 +02:00
if self.shop_level > 5 then self.shop_level = 5 end
2021-06-11 06:44:06 +02:00
end
2021-05-21 08:17:31 +02:00
slow_amount = 1
2021-07-04 06:50:31 +02:00
music_slow_amount = 1
2021-04-19 05:31:47 +02:00
main : add ( BuyScreen ' buy_screen ' )
2021-07-01 03:34:48 +02:00
system.save_run ( self.level + 1 , self.loop , gold , self.units , self.passives , self.shop_level , self.shop_xp , run_passive_pool , locked_state )
main : go_to ( ' buy_screen ' , self.level + 1 , self.loop , self.units , self.passives , self.shop_level , self.shop_xp )
2021-04-19 05:31:47 +02:00
t.t : after ( 0.1 , function ( )
t.text : set_text ( {
2021-06-16 07:37:40 +02:00
{ text = ' [nudge_down, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]gold gained: ' .. tostring ( self.gold_gained or 0 ) .. ' + ' .. tostring ( self.gold_picked_up or 0 ) , font = pixul_font ,
alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]interest: 0 ' , font = pixul_font , alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]total: 0 ' , font = pixul_font , alignment = ' center ' }
2021-04-19 05:31:47 +02:00
} )
_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 ( {
2021-06-16 07:37:40 +02:00
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]gold gained: ' .. tostring ( self.gold_gained or 0 ) .. ' + ' .. tostring ( self.gold_picked_up or 0 ) , font = pixul_font ,
alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [nudge_down, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]interest: ' .. tostring ( self.interest or 0 ) , font = pixul_font , alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]total: 0 ' , font = pixul_font , alignment = ' center ' }
2021-04-19 05:31:47 +02:00
} )
_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 ( {
2021-06-16 07:37:40 +02:00
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]gold gained: ' .. tostring ( self.gold_gained or 0 ) .. ' + ' .. tostring ( self.gold_picked_up or 0 ) , font = pixul_font ,
alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]interest: ' .. tostring ( self.interest or 0 ) , font = pixul_font , alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [nudge_down, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]total: ' .. tostring ( ( self.gold_gained or 0 ) + ( self.interest or 0 ) + ( self.gold_picked_up or 0 ) ) , font = pixul_font , alignment = ' center ' }
2021-04-19 05:31:47 +02:00
} )
_G [ random : table { ' coins1 ' , ' coins2 ' , ' coins3 ' } ] : play { pitch = random : float ( 0.95 , 1.05 ) , volume = 0.5 }
end )
end )
end )
end , text = Text ( {
2021-06-16 07:37:40 +02:00
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]gold gained: 0 + 0 ' , font = pixul_font , alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]interest: 0 ' , font = pixul_font , alignment = ' center ' , height_multiplier = 1.5 } ,
{ text = ' [wavy_lower, ' .. tostring ( state.dark_transitions and ' fg ' or ' bg ' ) .. ' ]total: 0 ' , font = pixul_font , alignment = ' center ' }
2021-04-19 05:31:47 +02:00
} , global_text_tags ) }
end
2021-02-21 06:47:59 +01:00
function Arena : spawn_distributed_enemies ( )
2021-05-03 07:04:40 +02:00
self.spawning_enemies = true
2021-02-21 06:47:59 +01:00
local t = { ' 4 ' , ' 4+4 ' , ' 4+4+4 ' , ' 2x4 ' , ' 3x4 ' , ' 4x2 ' }
2021-05-03 07:04:40 +02:00
local spawn_type = t [ random : weighted_pick ( 20 , 20 , 10 , 15 , 10 , 15 ) ]
2021-02-21 06:47:59 +01:00
local spawn_points = table.copy ( self.spawn_points )
if spawn_type == ' 4 ' then
2021-03-31 00:46:27 +02:00
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( )
2021-03-31 00:46:27 +02:00
self : spawn_n_enemies ( p )
end )
2021-06-25 18:25:13 +02:00
self.t : after ( 2.25 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-02-21 06:47:59 +01:00
elseif spawn_type == ' 4+4 ' then
local p = random : table_remove ( spawn_points )
2021-03-31 00:46:27 +02:00
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( )
2021-03-31 00:46:27 +02:00
self : spawn_n_enemies ( p )
self.t : after ( 2 , function ( ) self : spawn_n_enemies ( p ) end )
end )
2021-06-25 18:25:13 +02:00
self.t : after ( 4.25 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-02-21 06:47:59 +01:00
elseif spawn_type == ' 4+4+4 ' then
local p = random : table_remove ( spawn_points )
2021-03-31 00:46:27 +02:00
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( )
2021-02-21 06:47:59 +01:00
self : spawn_n_enemies ( p )
self.t : after ( 1 , function ( )
self : spawn_n_enemies ( p )
2021-03-31 00:46:27 +02:00
self.t : after ( 1 , function ( )
self : spawn_n_enemies ( p )
end )
2021-02-21 06:47:59 +01:00
end )
2021-02-19 04:50:27 +01:00
end )
2021-06-25 18:25:13 +02:00
self.t : after ( 4.25 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-02-21 06:47:59 +01:00
elseif spawn_type == ' 2x4 ' then
2021-05-03 07:04:40 +02:00
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 1 ) end )
2021-05-03 07:04:40 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 2 ) end )
2021-05-03 07:04:40 +02:00
end )
2021-06-25 18:25:13 +02:00
self.t : after ( 2.25 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-02-21 06:47:59 +01:00
elseif spawn_type == ' 3x4 ' then
2021-05-03 07:04:40 +02:00
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 1 ) end )
2021-05-03 07:04:40 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 2 ) end )
2021-05-03 07:04:40 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 3 ) end )
2021-05-03 07:04:40 +02:00
end )
2021-06-25 18:25:13 +02:00
self.t : after ( 2.25 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-02-21 06:47:59 +01:00
elseif spawn_type == ' 4x2 ' then
2021-05-03 07:04:40 +02:00
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 1 , 2 ) end )
2021-05-03 07:04:40 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 2 , 2 ) end )
2021-05-03 07:04:40 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 3 , 2 ) end )
2021-05-03 07:04:40 +02:00
end )
self.t : after ( { 0 , 0.2 } , function ( )
local p = random : table_remove ( spawn_points )
SpawnMarker { group = self.effects , x = p.x , y = p.y }
2021-06-25 18:25:13 +02:00
self.t : after ( 1.125 , function ( ) self : spawn_n_enemies ( p , 4 , 2 ) end )
2021-05-03 07:04:40 +02:00
end )
2021-06-25 18:25:13 +02:00
self.t : after ( 2.25 , function ( ) self.spawning_enemies = false end , ' spawning_enemies ' )
2021-02-19 04:50:27 +01:00
end
2021-02-18 19:28:40 +01:00
end
2021-02-21 06:47:59 +01:00
2021-05-29 10:10:52 +02:00
function Arena : spawn_n_enemies ( p , j , n , pass )
2021-03-15 05:01:04 +01:00
if self.died then return end
2021-05-17 10:05:48 +02:00
if self.arena_clear_text then return end
if self.quitting then return end
2021-06-04 06:05:59 +02:00
if self.won then return end
if self.choosing_passives then return end
2021-05-29 10:10:52 +02:00
if n and n <= 0 then return end
2021-05-17 10:05:48 +02:00
2021-02-21 06:47:59 +01:00
j = j or 1
n = n or 4
self.last_spawn_enemy_time = love.timer . getTime ( )
2021-05-29 10:10:52 +02:00
local check_circle = Circle ( 0 , 0 , 2 )
2021-02-21 06:47:59 +01:00
self.t : every ( 0.1 , function ( )
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 )
2021-02-22 03:54:50 +01:00
spawn1 : play { pitch = random : float ( 0.8 , 1.2 ) , volume = 0.15 }
2021-05-29 10:10:52 +02:00
if not pass then
check_circle : move_to ( x , y )
2021-07-03 07:08:35 +02:00
local objects = self.main : get_objects_in_shape ( check_circle , { Seeker , EnemyCritter , Critter , Player , Sentry , Automaton , Bomb , Volcano , Saboteur , Pet , Turret } )
2021-05-29 10:10:52 +02:00
if # objects > 0 then self.enemy_spawns_prevented = self.enemy_spawns_prevented + 1 ; return end
end
2021-04-26 03:17:31 +02:00
if random : bool ( table.reduce ( level_to_elite_spawn_weights [ self.level ] , function ( memo , v ) return memo + v end ) ) then
local elite_type = level_to_elite_spawn_types [ self.level ] [ random : weighted_pick ( unpack ( level_to_elite_spawn_weights [ self.level ] ) ) ]
Seeker { group = self.main , x = x , y = y , character = ' seeker ' , level = self.level ,
speed_booster = elite_type == ' speed_booster ' , exploder = elite_type == ' exploder ' , shooter = elite_type == ' shooter ' , headbutter = elite_type == ' headbutter ' , tank = elite_type == ' tank ' , spawner = elite_type == ' spawner ' }
else
Seeker { group = self.main , x = x , y = y , character = ' seeker ' , level = self.level }
end
2021-02-21 06:47:59 +01:00
end }
end , n , nil , ' spawn_enemies_ ' .. j )
end
2021-04-30 01:38:36 +02:00
CharacterHP = Object : extend ( )
CharacterHP : implement ( GameObject )
function CharacterHP : init ( args )
self : init_game_object ( args )
self.hfx : add ( ' hit ' , 1 )
self.cooldown_ratio = 0
end
function CharacterHP : update ( dt )
self : update_game_object ( dt )
local t , d = self.parent . t : get_timer_and_delay ' shoot '
if t and d then
local m = self.parent . t : get_every_multiplier ' shoot '
self.cooldown_ratio = math.min ( t / ( d * m ) , 1 )
end
local t , d = self.parent . t : get_timer_and_delay ' attack '
if t and d then
local m = self.parent . t : get_every_multiplier ' attack '
self.cooldown_ratio = math.min ( t / ( d * m ) , 1 )
end
local t , d = self.parent . t : get_timer_and_delay ' heal '
if t and d then self.cooldown_ratio = math.min ( t / d , 1 ) end
local t , d = self.parent . t : get_timer_and_delay ' buff '
if t and d then self.cooldown_ratio = math.min ( t / d , 1 ) end
local t , d = self.parent . t : get_timer_and_delay ' spawn '
if t and d then self.cooldown_ratio = math.min ( t / d , 1 ) end
end
function CharacterHP : draw ( )
graphics.push ( self.x , self.y , 0 , self.hfx . hit.x , self.hfx . hit.x )
graphics.rectangle ( self.x , self.y - 2 , 14 , 4 , 2 , 2 , self.parent . dead and bg [ 5 ] or ( self.hfx . hit.f and fg [ 0 ] or _G [ character_color_strings [ self.parent . character ] ] [ - 2 ] ) , 2 )
if self.parent . hp > 0 then
graphics.rectangle2 ( self.x - 7 , self.y - 4 , 14 * ( self.parent . hp / self.parent . max_hp ) , 4 , nil , nil , self.parent . dead and bg [ 5 ] or ( self.hfx . hit.f and fg [ 0 ] or _G [ character_color_strings [ self.parent . character ] ] [ - 2 ] ) )
end
if not self.parent . dead then
graphics.line ( self.x - 8 , self.y + 5 , self.x - 8 + 15.5 * self.cooldown_ratio , self.y + 5 , self.hfx . hit.f and fg [ 0 ] or _G [ character_color_strings [ self.parent . character ] ] [ - 2 ] , 2 )
end
graphics.pop ( )
2021-05-29 10:10:52 +02:00
if state.cooldown_snake then
2021-05-30 17:00:03 +02:00
if table.any ( non_cooldown_characters , function ( v ) return v == self.parent . character end ) then return end
2021-05-29 10:10:52 +02:00
local p = self.parent
graphics.push ( p.x , p.y , 0 , self.hfx . hit.x , self.hfx . hit.y )
if not p.dead then
graphics.line ( p.x - 4 , p.y + 8 , p.x - 4 + 8 , p.y + 8 , self.hfx . hit.f and fg [ 0 ] or bg [ - 2 ] , 2 )
graphics.line ( p.x - 4 , p.y + 8 , p.x - 4 + 8 * self.cooldown_ratio , p.y + 8 , self.hfx . hit.f and fg [ 0 ] or _G [ character_color_strings [ p.character ] ] [ - 2 ] , 2 )
end
graphics.pop ( )
end
2021-04-30 01:38:36 +02:00
end
function CharacterHP : change_hp ( )
self.hfx : use ( ' hit ' , 0.5 )
end