123 lines
3.1 KiB
GDScript
123 lines
3.1 KiB
GDScript
extends Node3D
|
|
class_name WorldManager
|
|
|
|
|
|
enum STATE { INIT, IDLE, SPAWN, SPAWNING, FIGHT, WAVE_END, LEVEL_END }
|
|
|
|
|
|
var level : Level
|
|
var paths : Array[Node]
|
|
var state : STATE = STATE.INIT
|
|
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
|
|
|
|
|
|
func _ready() -> void:
|
|
$SFX/SFXPrepareYourself.play()
|
|
EventBus.projectile_shooted.connect(onProjectileShooted)
|
|
EventBus.lauch_next_wave.connect(changeState.bind(STATE.SPAWN))
|
|
troopTimer.timeout.connect(spawnTroop)
|
|
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if event.is_action_pressed("spawn_next_wave"):
|
|
changeState(STATE.SPAWN)
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
if state == STATE.INIT:
|
|
return
|
|
|
|
match state:
|
|
STATE.SPAWN:
|
|
spawnNextWave()
|
|
state = STATE.SPAWNING
|
|
STATE.SPAWNING when troopTimer.is_stopped():
|
|
state = STATE.FIGHT
|
|
STATE.FIGHT when enemiesAlive == 0:
|
|
if wave != level.waves.size():
|
|
$SFX/SFXWinner.play()
|
|
EventBus.wave_finished.emit()
|
|
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
|
|
|
|
|
|
func changeState(newState: STATE) -> void:
|
|
match newState:
|
|
STATE.SPAWN when [STATE.IDLE, STATE.WAVE_END].has(state):
|
|
state = newState
|
|
|
|
|
|
func spawnNextWave() -> void:
|
|
currentTroopIdx = 0
|
|
wave += 1
|
|
if wave == level.waves.size():
|
|
$SFX/SFXFinalRound.play()
|
|
else:
|
|
$SFX/SFXFight.play()
|
|
EventBus.wave_has_change.emit(wave, level.waves[wave - 1].troops[0].spawn_delay)
|
|
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)
|
|
|
|
|
|
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()
|
|
|
|
|
|
func spawnEnemy(enemyScene: PackedScene, laneToSpawn: int, delay: float) -> void:
|
|
var enemy : PathFollow3D = createEnemy(enemyScene)
|
|
|
|
if delay > 0:
|
|
await get_tree().create_timer(delay, false).timeout
|
|
|
|
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 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.maxTier = level.tier_max
|
|
Game.initTowers(level.allowedTowers)
|
|
state = STATE.SPAWN if level.auto_start else STATE.IDLE
|
|
|
|
|
|
func onProjectileShooted(projectile: Projectile, _transform: Transform3D) -> void:
|
|
add_child(projectile)
|
|
projectile.transform = _transform
|