extends Node2D ## Keeps a floor count of grunts alive, spawning at the arena's inset ## edges. Endless trickle — the tracer needs targets, not waves. signal grunt_spawned(grunt: Node) const GRUNT := preload("res://scenes/grunt.tscn") @export var target_count := 8 @export var spawn_interval := 0.8 @export var spawn_rect := Rect2(32, 32, 576, 296) @export var min_dist_from_mech := 120.0 var _timer := 0.0 func _physics_process(delta: float) -> void: _timer -= delta if _timer > 0.0: return _timer = spawn_interval if get_tree().get_nodes_in_group("enemies").size() < target_count: _spawn() func _spawn() -> void: var g := GRUNT.instantiate() g.position = _pick_point() add_child(g) grunt_spawned.emit(g) func _pick_point() -> Vector2: var mech := get_tree().get_first_node_in_group("mech") as Node2D var p := Vector2.ZERO for i in 12: match randi() % 4: 0: p = Vector2(randf_range(spawn_rect.position.x, spawn_rect.end.x), spawn_rect.position.y) 1: p = Vector2(randf_range(spawn_rect.position.x, spawn_rect.end.x), spawn_rect.end.y) 2: p = Vector2(spawn_rect.position.x, randf_range(spawn_rect.position.y, spawn_rect.end.y)) 3: p = Vector2(spawn_rect.end.x, randf_range(spawn_rect.position.y, spawn_rect.end.y)) if mech == null or p.distance_to(mech.global_position) >= min_dist_from_mech: return p return p