extends Node3D class_name WorldManager const PACK_DELAY : float = .15 var level : Level var paths : Array[Node] var current_wave : Wave var current_troop : Troop var enemies_to_spawn : int = 0 var wave : int = 0 var enemies_alive : int = 0 var selected_collider : CollisionObject3D var troopTimer : Timer = Timer.new() func _ready() -> void: EventBus.projectile_shooted.connect(onProjectileShooted) troopTimer.one_shot = true troopTimer.timeout.connect(spawn_troop) add_child(troopTimer) EventBus.player_defeated.connect(queue_free) func onProjectileShooted(projectile : Projectile) -> void: add_child(projectile) func _process(delta: float) -> void: if wave > 0 || level && level.auto_start: spawn_manager() func spawn_next_wave() -> void: if level.waves.is_empty(): EventBus.player_has_won.emit() queue_free.call_deferred() return current_wave = level.waves.pop_front() wave += 1 EventBus.waveHasChange.emit(wave) func spawn_troop() -> void: for n in current_troop.number_to_spawn: spawnEnemy(n * PACK_DELAY) func spawnEnemy(delay : float) -> void: var enemy : PathFollow3D = createEnemy() if delay > 0: var enemyTimer : Timer = createTimer(delay) enemyTimer.timeout.connect( func(): paths[current_troop.lane_to_spawn].add_child(enemy) enemyTimer.queue_free() ) paths[current_troop.lane_to_spawn].add_child(enemyTimer) else: paths[current_troop.lane_to_spawn].add_child(enemy) enemies_alive += 1 func createEnemy() -> PathFollow3D : var PF3D : PathFollow3D = load(current_troop.enemy).instantiate() var enemy : Enemy = PF3D.find_children("*", "Enemy")[0] enemy.died.connect(func(): enemies_alive -= 1) return PF3D func spawn_manager() -> void: if not troopTimer.is_stopped(): return if not current_wave || enemies_alive == 0 && current_wave.troops.is_empty(): spawn_next_wave() return current_troop = current_wave.troops.pop_front() if not current_troop: return if current_troop.spawn_delay == 0: spawn_troop() else: troopTimer.start(current_troop.spawn_delay) func createTimer(delay : float, oneShot = true, autoStart = true) -> Timer : var timer : Timer = Timer.new() timer.wait_time = delay timer.one_shot = oneShot timer.autostart = autoStart 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.call_deferred(level.allowedTowers) spawn_next_wave()