extends Node3D class_name WorldManager const PACK_DELAY : float = .15 var level : Level var paths : Array[Node] var wave : int = 0 var currentTroopIdx : int = 0 var currentTroop : Troop : get(): return level.waves[wave - 1].troops[currentTroopIdx] var enemiesAlive : int = 0 @onready var troopTimer : Timer = $TroopTimer func _ready() -> void: EventBus.projectile_shooted.connect(onProjectileShooted) EventBus.player_defeated.connect(queue_free) func onProjectileShooted(projectile: Projectile, startPosition: Vector3) -> void: add_child(projectile) projectile.global_position = startPosition func _process(_delta: float) -> void: if wave > 0 || level && level.auto_start: spawnManager() func spawnNextWave() -> void: if wave == level.waves.size() && currentTroopIdx == level.waves[wave - 1].troops.size(): EventBus.player_has_won.emit() queue_free.call_deferred() return currentTroopIdx = 0 wave += 1 EventBus.waveHasChange.emit(wave) func spawnTroop() -> void: var enemyScene : PackedScene = load(currentTroop.enemy) var totalDelay : float = 0 for n in currentTroop.number_to_spawn: spawnEnemy(enemyScene, currentTroop.lane_to_spawn, totalDelay) totalDelay += PACK_DELAY currentTroopIdx += 1 func spawnEnemy(enemyScene: PackedScene, laneToSpawn: int, delay: float) -> void: var enemy : PathFollow3D = createEnemy(enemyScene) if delay > 0: var enemyTimer : Timer = createTimer(delay) enemyTimer.timeout.connect( func(): paths[laneToSpawn].add_child(enemy) enemyTimer.queue_free() ) add_child(enemyTimer) else: paths[laneToSpawn].add_child(enemy) enemiesAlive += 1 func createEnemy(enemyScene: PackedScene) -> PathFollow3D : var PF3D : PathFollow3D = enemyScene.instantiate() var enemy : Enemy = PF3D.find_children("*", "Enemy")[0] enemy.died.connect(func(): enemiesAlive -= 1) return PF3D func spawnManager() -> void: if not troopTimer.is_stopped(): return var current_wave : Wave = level.waves[wave - 1] if current_wave.troops.size() < currentTroopIdx + 1: if enemiesAlive == 0: spawnNextWave() return if currentTroop.spawn_delay == 0: spawnTroop() else: troopTimer.start(currentTroop.spawn_delay) func createTimer(delay: float) -> Timer : var timer : Timer = Timer.new() timer.wait_time = delay timer.one_shot = true timer.autostart = true return timer func addMap(mapScene : PackedScene) -> void: var map : Map = mapScene.instantiate() add_child(map) level = map.level paths = map.paths.get_children() EventBus.allowedTowerHasChange.emit(level.allowedTowers) spawnNextWave()