extends Node2D # #116: draws the repair drones GameState is simulating, and only while they # are somewhere the player could see them. # # Same arrangement as TransporterField, and for the same reason: the # simulation is authoritative and the visuals are optional, so a repair run # happening far away costs nothing but still puts the building back together. # Position comes from the very same `progress` that decides when the repair # actually lands. @export var visible_radius: float = 2600.0 @onready var fleet: Node2D = get_node("../Fleet") var drone_scene: PackedScene = preload("res://logistics/RepairDrone.tscn") # index into GameState.repair_drones -> live node var active: Dictionary = {} func _process(_delta: float) -> void: var centre: Vector2 = fleet.get_centroid() for i in range(GameState.repair_drones.size()): var drone: Dictionary = GameState.repair_drones[i] # An idle drone is parked inside its workshop's own art; drawing it # there adds a dot sitting on a building rather than a vessel doing # something. if String(drone.state) == GameState.DRONE_IDLE: _despawn(i) continue var pos: Vector2 = GameState.repair_drone_position(drone) if pos.distance_to(centre) > visible_radius: _despawn(i) continue var node: Node2D = active.get(i) if node == null or not is_instance_valid(node): node = drone_scene.instantiate() get_parent().add_child(node) active[i] = node var previous: Vector2 = node.position node.position = pos node.set_laden(int(drone.carrying) > 0) var travel: Vector2 = pos - previous if travel.length() > 0.5: node.rotation = travel.angle() + PI / 2.0 for key in active.keys(): if key >= GameState.repair_drones.size(): _despawn(key) func _despawn(index: int) -> void: var node: Node2D = active.get(index) if node != null and is_instance_valid(node): node.queue_free() active.erase(index)