extends Node3D @export var batch_duration: float = 16.0 @export var lateral_variance: float = 1.5 var _active_walkers: Array[Node] = [] var _batch_generation: int = 0 @onready var survivor = preload("res://scenes/survivor.tscn") @export var survivor_spawn: Node3D func _enter_tree() -> void: EventBus.floor_started.connect(_on_floor_started, CONNECT_DEFERRED) EventBus.doors_closed.connect(_on_doors_closed) EventBus.doors_fully_closed.connect(_clear_active_walkers) func _on_floor_started(count: int) -> void: _batch_generation += 1 _clear_active_walkers() if count <= 0: return _run_batch(count, _batch_generation) func _on_doors_closed(_fast: bool) -> void: _batch_generation += 1 func _clear_active_walkers() -> void: for w in _active_walkers: if is_instance_valid(w): w.queue_free() _active_walkers.clear() func _run_batch(count: int, generation: int) -> void: var gap: float = batch_duration / float(count) for i in range(count): if generation != _batch_generation: return _spawn_one() var jitter: float = randf_range(-gap * 0.25, gap * 0.25) await get_tree().create_timer(max(0.05, gap + jitter), false).timeout func _spawn_one() -> void: var s = survivor.instantiate() var offset := Vector3(randf_range(-lateral_variance, lateral_variance), 0, 0) add_child.call_deferred(s) s.position = survivor_spawn.global_position + offset _active_walkers.append(s)