TowerDefense/Levels/Scripts/WorldManager.gd

131 lines
3.1 KiB
GDScript3
Raw Normal View History

2025-09-01 13:52:14 +02:00
extends Node3D
class_name WorldManager
2025-08-27 01:40:22 +02:00
enum STATE { INIT, IDLE, SPAWN, SPAWNING, FIGHT, WAVE_END, LEVEL_END }
2025-09-01 13:52:14 +02:00
var level : Level
var paths : Array[Node]
var state : STATE = STATE.INIT
2025-08-30 15:46:36 +02:00
var wave : int = 0
var currentTroop : Troop :
get(): return level.waves[wave - 1].troops[currentTroopIdx]
var currentTroopIdx : int = 0
var enemiesAlive : int = 0
@onready var troopTimer : Timer = $TroopTimer
2025-08-29 12:11:51 +02:00
func _ready() -> void:
2025-09-01 13:52:14 +02:00
EventBus.projectile_shooted.connect(onProjectileShooted)
EventBus.lauch_next_wave.connect(changeState.bind(STATE.SPAWN))
troopTimer.timeout.connect(spawnTroop)
2025-09-01 13:52:14 +02:00
2025-09-05 19:33:56 +02:00
func _input(event: InputEvent) -> void:
if event.is_action_pressed("spawn_next_wave"):
changeState(STATE.SPAWN)
2025-08-27 01:40:22 +02:00
func _process(_delta: float) -> void:
if state == STATE.INIT:
2025-08-27 01:40:22 +02:00
return
match state:
STATE.SPAWN:
spawnNextWave()
state = STATE.SPAWNING
STATE.SPAWNING when troopTimer.is_stopped():
state = STATE.FIGHT
STATE.FIGHT when enemiesAlive == 0:
state = STATE.WAVE_END
STATE.WAVE_END when wave == level.waves.size():
EventBus.player_has_won.emit()
state = STATE.LEVEL_END
STATE.WAVE_END when level.auto_launch_wave:
state = STATE.SPAWN
2025-09-05 19:33:56 +02:00
func changeState(newState: STATE) -> void:
match newState:
STATE.SPAWN when [STATE.IDLE, STATE.WAVE_END].has(state):
state = newState
func spawnNextWave() -> void:
currentTroopIdx = 0
2025-08-30 15:46:36 +02:00
wave += 1
EventBus.wave_has_change.emit(wave)
spawnNextTroop()
func spawnNextTroop() -> void:
# Wave spawning is finished
if currentTroopIdx == level.waves[wave - 1].troops.size():
return
if currentTroop.spawn_delay == 0:
spawnTroop()
else:
troopTimer.start(currentTroop.spawn_delay)
2025-08-27 01:40:22 +02:00
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 += currentTroop.pack_delay
currentTroopIdx += 1
spawnNextTroop()
2025-08-30 15:46:36 +02:00
func spawnEnemy(enemyScene: PackedScene, laneToSpawn: int, delay: float) -> void:
var enemy : PathFollow3D = createEnemy(enemyScene)
2025-08-30 15:46:36 +02:00
if delay > 0:
2025-08-31 23:07:55 +02:00
var enemyTimer : Timer = createTimer(delay)
2025-08-30 15:46:36 +02:00
enemyTimer.timeout.connect(
func():
paths[laneToSpawn].add_child(enemy)
2025-08-30 15:46:36 +02:00
enemyTimer.queue_free()
)
add_child(enemyTimer)
2025-08-30 15:46:36 +02:00
else:
paths[laneToSpawn].add_child(enemy)
2025-08-30 15:46:36 +02:00
enemiesAlive += 1
2025-08-30 15:46:36 +02:00
func createEnemy(enemyScene: PackedScene) -> PathFollow3D :
var PF3D : PathFollow3D = enemyScene.instantiate()
2025-08-30 20:08:12 +02:00
var enemy : Enemy = PF3D.find_children("*", "Enemy")[0]
enemy.died.connect(func(): enemiesAlive -= 1)
2025-08-30 15:46:36 +02:00
2025-08-30 20:08:12 +02:00
return PF3D
2025-08-27 01:40:22 +02:00
func createTimer(delay: float) -> Timer :
2025-08-31 23:07:55 +02:00
var timer : Timer = Timer.new()
2025-08-30 15:46:36 +02:00
timer.wait_time = delay
timer.one_shot = true
timer.autostart = true
2025-08-30 15:46:36 +02:00
return timer
2025-09-01 13:52:14 +02:00
func addMap(mapScene : PackedScene) -> void:
var map : Map = mapScene.instantiate()
add_child(map)
level = map.level
paths = map.paths.get_children()
Game.money = level.startingMoney
Game.allowedTowers = level.allowedTowers
state = STATE.SPAWN if level.auto_start else STATE.IDLE
2025-09-05 19:33:56 +02:00
func onProjectileShooted(projectile: Projectile, startPosition: Vector3) -> void:
add_child(projectile)
projectile.global_position = startPosition