2025-08-27 01:40:22 +02:00
|
|
|
extends Path3D
|
|
|
|
|
class_name WaveManager
|
|
|
|
|
|
2025-08-30 15:46:36 +02:00
|
|
|
const PACK_DELAY : float = .15
|
|
|
|
|
|
2025-08-29 12:11:51 +02:00
|
|
|
@export var level : Level
|
2025-08-27 01:40:22 +02:00
|
|
|
var current_wave : Wave
|
|
|
|
|
var current_troop : Troop
|
|
|
|
|
|
|
|
|
|
var enemies_to_spawn : int = 0
|
2025-08-30 15:46:36 +02:00
|
|
|
var wave : int = 0
|
|
|
|
|
var enemies_alive : int = 0
|
2025-08-27 01:40:22 +02:00
|
|
|
var wave_on_going : bool = false
|
2025-08-29 12:11:51 +02:00
|
|
|
|
2025-08-30 15:46:36 +02:00
|
|
|
|
2025-08-29 12:11:51 +02:00
|
|
|
@onready var troopTimer := $TroopTimer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ready() -> void:
|
|
|
|
|
troopTimer.timeout.connect(spawn_troop)
|
|
|
|
|
EventBus.player_defeated.connect(clearLevel)
|
2025-08-30 00:46:34 +02:00
|
|
|
EventBus.allowedTowerHasChange.emit.call_deferred(level.allowedTowers)
|
2025-08-27 01:40:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func _process(delta: float) -> void:
|
2025-08-30 15:46:36 +02:00
|
|
|
if wave > 0 || level.auto_start:
|
2025-08-27 01:40:22 +02:00
|
|
|
spawn_manager()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func spawn_next_wave() -> void:
|
2025-08-29 12:11:51 +02:00
|
|
|
if level.waves.is_empty():
|
2025-08-27 01:40:22 +02:00
|
|
|
EventBus.player_has_won.emit()
|
|
|
|
|
return
|
|
|
|
|
|
2025-08-29 12:11:51 +02:00
|
|
|
current_wave = level.waves.pop_front()
|
2025-08-30 15:46:36 +02:00
|
|
|
wave += 1
|
|
|
|
|
EventBus.waveHasChange.emit(wave)
|
2025-08-27 01:40:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func spawn_troop() -> void:
|
|
|
|
|
for n in current_troop.number_to_spawn:
|
2025-08-30 15:46:36 +02:00
|
|
|
spawnEnemy(n * PACK_DELAY)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func spawnEnemy(delay : float) -> void:
|
|
|
|
|
var enemy := createEnemy()
|
|
|
|
|
|
|
|
|
|
if delay > 0:
|
|
|
|
|
var enemyTimer := createTimer(delay)
|
|
|
|
|
enemyTimer.timeout.connect(
|
|
|
|
|
func():
|
|
|
|
|
add_child(enemy)
|
|
|
|
|
enemyTimer.queue_free()
|
|
|
|
|
)
|
|
|
|
|
add_child(enemyTimer)
|
|
|
|
|
else:
|
|
|
|
|
add_child(enemy)
|
|
|
|
|
|
|
|
|
|
enemies_alive += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func createEnemy() -> PathFollow3D :
|
|
|
|
|
var fp3D : PathFollow3D = current_troop.enemy.instantiate()
|
|
|
|
|
var enemy : Enemy = fp3D.find_children("*", "Enemy")[0]
|
|
|
|
|
enemy.died.connect(func(): enemies_alive -= 1)
|
|
|
|
|
|
|
|
|
|
return fp3D
|
2025-08-27 01:40:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func spawn_manager() -> void:
|
|
|
|
|
#Send next troop
|
2025-08-30 15:46:36 +02:00
|
|
|
if !troopTimer.is_stopped():
|
2025-08-29 12:11:51 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if !current_wave:
|
|
|
|
|
spawn_next_wave()
|
2025-08-27 01:40:22 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if !current_wave.troops.is_empty():
|
|
|
|
|
current_troop = current_wave.troops.pop_front()
|
|
|
|
|
if (current_troop.spawn_delay == 0):
|
|
|
|
|
spawn_troop()
|
|
|
|
|
else:
|
2025-08-29 12:11:51 +02:00
|
|
|
troopTimer.start(current_troop.spawn_delay)
|
2025-08-27 01:40:22 +02:00
|
|
|
|
|
|
|
|
wave_on_going = true
|
2025-08-30 15:46:36 +02:00
|
|
|
if enemies_alive == 0 && current_wave.troops.is_empty():
|
2025-08-27 01:40:22 +02:00
|
|
|
wave_on_going = false
|
|
|
|
|
spawn_next_wave()
|
|
|
|
|
elif !current_wave.wait_for_enemy_kills:
|
|
|
|
|
spawn_next_wave()
|
|
|
|
|
|
|
|
|
|
|
2025-08-29 12:11:51 +02:00
|
|
|
func clearLevel() -> void:
|
|
|
|
|
queue_free()
|
2025-08-30 15:46:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func createTimer(delay : float, oneShot = true, autoStart = true) -> Timer :
|
|
|
|
|
var timer := Timer.new()
|
|
|
|
|
timer.wait_time = delay
|
|
|
|
|
timer.one_shot = oneShot
|
|
|
|
|
timer.autostart = autoStart
|
|
|
|
|
|
|
|
|
|
return timer
|