52 lines
1.3 KiB
GDScript
52 lines
1.3 KiB
GDScript
extends Node3D
|
|
|
|
signal matador_killed
|
|
signal all_defeated
|
|
|
|
const MATADOR := preload("res://Matador.tscn")
|
|
|
|
var _spawn_count: int = 1
|
|
var _alive: int = 0
|
|
var _resolved: bool = false
|
|
|
|
|
|
func _ready() -> void:
|
|
add_to_group(&"matador_spawn")
|
|
_spawn_count = maxi(1, int(DP.f("mat_spawn_count")))
|
|
# Deferred so it's safe from _ready and matches the previous spawn timing.
|
|
_spawn.call_deferred()
|
|
|
|
|
|
func _spawn() -> void:
|
|
for pos: Vector3 in _spread_positions(_spawn_count):
|
|
_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
|
|
|
|
|
|
# Every matador down = the bull wins. No waves, no respawns — one clean arena.
|
|
func _on_matador_killed() -> void:
|
|
matador_killed.emit()
|
|
_alive -= 1
|
|
if _alive <= 0 and not _resolved:
|
|
_resolved = true
|
|
all_defeated.emit()
|