86 lines
2.2 KiB
GDScript
86 lines
2.2 KiB
GDScript
extends Node3D
|
|
|
|
signal matador_killed
|
|
signal wave_changed(wave: int)
|
|
|
|
const MATADOR := preload("res://Matador.tscn")
|
|
const RESPAWN_COOLDOWN := 8.0
|
|
|
|
var _respawn_cooldown: float = 0.0
|
|
var _spawn_count: int = 1 # matadors in the current wave — doubles on each clear
|
|
var _wave: int = 1 # wave number, surfaced on the HUD
|
|
var _alive: int = 0
|
|
|
|
|
|
func _ready() -> void:
|
|
add_to_group(&"matador_spawn")
|
|
_spawn_count = maxi(1, int(DP.f("mat_spawn_count")))
|
|
_start_wave(1)
|
|
|
|
|
|
# Latest wave number, for a HUD that connects after the first wave has begun.
|
|
func current_wave() -> int:
|
|
return _wave
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
_respawn_cooldown = maxf(0.0, _respawn_cooldown - delta)
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event is InputEventKey and event.pressed and not event.echo:
|
|
if event.physical_keycode == KEY_R and _respawn_cooldown <= 0.0:
|
|
_respawn_cooldown = RESPAWN_COOLDOWN
|
|
reset_spawn()
|
|
|
|
|
|
# Announce a wave and spawn its matadors. Deferred spawn keeps it safe to call
|
|
# from _ready and from inside a kill handler mid-signal.
|
|
func _start_wave(number: int) -> void:
|
|
_wave = number
|
|
wave_changed.emit(_wave)
|
|
_spawn.call_deferred()
|
|
|
|
|
|
func _spawn() -> void:
|
|
var positions := _spread_positions(_spawn_count)
|
|
for pos: Vector3 in positions:
|
|
_spawn_at(pos)
|
|
|
|
|
|
func _spread_positions(count: int) -> Array[Vector3]:
|
|
var positions: Array[Vector3] = []
|
|
var arena_r := DP.f("mat_wander_radius") * 0.72
|
|
var min_r := 5.0
|
|
for i: int in count:
|
|
var sector := TAU / count
|
|
var angle := sector * i + randf_range(-sector * 0.35, sector * 0.35)
|
|
var radius := randf_range(min_r, arena_r)
|
|
positions.append(Vector3(cos(angle) * radius, 1.0, sin(angle) * radius))
|
|
return positions
|
|
|
|
|
|
func _spawn_at(pos: Vector3) -> void:
|
|
var m: Node3D = MATADOR.instantiate()
|
|
m.position = pos
|
|
get_parent().add_child(m)
|
|
m.killed.connect(_on_matador_killed)
|
|
_alive += 1
|
|
|
|
|
|
func _on_matador_killed() -> void:
|
|
matador_killed.emit()
|
|
_alive -= 1
|
|
if _alive <= 0:
|
|
_spawn_count *= 2
|
|
_start_wave(_wave + 1)
|
|
|
|
|
|
func reset_spawn() -> void:
|
|
for m: Node in get_tree().get_nodes_in_group(&"matador"):
|
|
m.queue_free()
|
|
await get_tree().process_frame
|
|
_spawn_count = maxi(1, int(DP.f("mat_spawn_count")))
|
|
_alive = 0
|
|
_start_wave(1)
|