68 lines
2.2 KiB
GDScript
68 lines
2.2 KiB
GDScript
## WaveManager.gd
|
|
## Loads wave definitions and orchestrates creep spawning along the lane path.
|
|
extends Node
|
|
|
|
const WAVE_DATA_PATH := "res://data/waves.json"
|
|
const TOTAL_WAVES := 31
|
|
|
|
var _waves: Array = []
|
|
var _active_creeps: int = 0
|
|
|
|
func _ready() -> void:
|
|
_load_waves()
|
|
EventBus.creep_died.connect(_on_creep_removed)
|
|
EventBus.creep_reached_exit.connect(_on_creep_removed)
|
|
|
|
func _load_waves() -> void:
|
|
_waves = DataLoader.load_waves()
|
|
if _waves.is_empty():
|
|
push_error("WaveManager: waves.json failed to load or is empty")
|
|
|
|
func start_wave(wave_number: int, lane: Node) -> void:
|
|
if wave_number < 1 or wave_number > _waves.size():
|
|
push_error("WaveManager: invalid wave number %d" % wave_number)
|
|
return
|
|
|
|
var wave_data: Dictionary = _waves[wave_number - 1]
|
|
GameState.advance_wave()
|
|
GameState.set_phase(GameState.Phase.COMBAT)
|
|
EventBus.wave_started.emit(wave_number)
|
|
|
|
var count: int = wave_data.get("creep_count", 1)
|
|
_active_creeps += count
|
|
|
|
var path_pts: PackedVector2Array = lane.get_path_points() if lane.has_method("get_path_points") else PackedVector2Array()
|
|
|
|
# Spawn creeps spaced 0.5 s apart
|
|
for i in range(count):
|
|
await get_tree().create_timer(0.5 * i).timeout
|
|
_spawn_creep(wave_data, lane, path_pts)
|
|
|
|
func _spawn_creep(wave_data: Dictionary, lane: Node, path_pts: PackedVector2Array) -> void:
|
|
var creep_scene := load("res://scenes/gameplay/Creep.tscn") as PackedScene
|
|
if not creep_scene:
|
|
push_error("WaveManager: Creep.tscn not found")
|
|
_active_creeps -= 1
|
|
return
|
|
var creep: Node = creep_scene.instantiate()
|
|
lane.add_child(creep)
|
|
creep.setup(wave_data)
|
|
if path_pts.size() > 0:
|
|
# Convert lane-local path to global coords for the creep
|
|
var global_pts := PackedVector2Array()
|
|
for pt in path_pts:
|
|
global_pts.append(lane.to_global(pt))
|
|
creep.assign_path(global_pts)
|
|
|
|
func _on_creep_removed(_creep: Node, _value) -> void:
|
|
_active_creeps = max(0, _active_creeps - 1)
|
|
if _active_creeps == 0:
|
|
_wave_complete()
|
|
|
|
func _wave_complete() -> void:
|
|
var wn := GameState.wave_number
|
|
EventBus.wave_completed.emit(wn)
|
|
Economy.process_income_phase()
|
|
if wn < TOTAL_WAVES:
|
|
GameState.set_phase(GameState.Phase.BUILD)
|
|
# If wave 31, GameOver.gd listens to wave_completed and handles victory
|