TowerDefense/Levels/Scripts/WorldManager.gd

114 lines
2.6 KiB
GDScript

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:
var enemyScene : PackedScene = load(current_troop.enemy)
for n in current_troop.number_to_spawn:
spawnEnemy(enemyScene, n * PACK_DELAY)
func spawnEnemy(enemyScene : PackedScene, delay : float) -> void:
var enemy : PathFollow3D = createEnemy(enemyScene)
# DANGER this var is needed for timer callback
var laneToSpawn : int = current_troop.lane_to_spawn
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)
enemies_alive += 1
func createEnemy(enemyScene : PackedScene) -> PathFollow3D :
var PF3D : PathFollow3D = enemyScene.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.call_deferred()