Build the logistics crews, and let them burn energy
#216: transport hubs and spacial workshops no longer conjure their crews. Transporters and repair drones are ordered at a ship crafter, assigned per building through a new Station menu, flown out from the mothership hangar, and spent by the work they do - 20 runs, 12 repairs, counted where the run ENDS so nothing retires with cargo in the air or a building half repaired. A spent vessel is gone, so the structure is short again and the player has to build another. The menu shows what each one has left, worst first. Craftability needed its own flag: "the crafter can make it" and "it can take a berth in the fleet" stopped being the same question. #217: transporters crawl at 120 rather than 150, and a Burn Drive lets them carry energy and spend it to travel far faster. Fetching it is a leg of its own, to the nearest store that has any - so a refuelling transporter cannot be dispatched mid-errand - and the leg flown to COLLECT fuel is not charged for it. Unresearched, nothing detours and nothing changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
This commit is contained in:
parent
1f5fecd371
commit
265e121cb0
31 changed files with 1180 additions and 141 deletions
|
|
@ -695,10 +695,6 @@ func unlock(id: String, payment_position: Variant = null) -> bool:
|
|||
research_points -= points_needed
|
||||
research_points_changed.emit(research_points)
|
||||
unlocked.append(id)
|
||||
if int(node.get("hub_bonus", 0)) > 0:
|
||||
_sync_hub_transporters()
|
||||
if int(node.get("workshop_bonus", 0)) > 0:
|
||||
_sync_workshop_drones()
|
||||
return true
|
||||
|
||||
|
||||
|
|
@ -1084,10 +1080,6 @@ func dev_unlock_all_skills() -> int:
|
|||
continue
|
||||
unlocked.append(id)
|
||||
added += 1
|
||||
# These permanent doctrines affect structures which may already exist.
|
||||
# Sync once after the batch instead of once per node.
|
||||
_sync_hub_transporters()
|
||||
_sync_workshop_drones()
|
||||
return added
|
||||
|
||||
|
||||
|
|
@ -1134,11 +1126,6 @@ func add_building(type: String, at_position: Vector2) -> int:
|
|||
"inventory": INVENTORY.new(), "orders": [],
|
||||
"hp": building_max_hp(type),
|
||||
})
|
||||
var building: Dictionary = buildings[-1]
|
||||
if building_has_capability(building, "transport_hub"):
|
||||
_provision_hub_transporters(building)
|
||||
if building_has_capability(building, "repair"):
|
||||
_provision_workshop_drones(building)
|
||||
return id
|
||||
|
||||
|
||||
|
|
@ -1736,6 +1723,32 @@ func transporter_speed() -> float:
|
|||
return vessel_stat(definition.definition_id, "transport_speed")
|
||||
|
||||
|
||||
# #217: what a Burn Drive multiplies that by while there is energy aboard.
|
||||
# 1.0 until the upgrade is researched, which is also the flag for whether a
|
||||
# transporter should go looking for fuel at all - an unupgraded one has no
|
||||
# use for it and must never detour.
|
||||
func transporter_fuel_boost() -> float:
|
||||
var definition: Resource = VESSEL_DEFINITIONS.with_capability("transport")
|
||||
return maxf(vessel_stat(definition.definition_id, "fuel_boost"), 1.0)
|
||||
|
||||
|
||||
func transporter_fuel_capacity() -> int:
|
||||
var definition: Resource = VESSEL_DEFINITIONS.with_capability("transport")
|
||||
return int(vessel_stat(definition.definition_id, "fuel_capacity"))
|
||||
|
||||
|
||||
func transporter_burns_energy() -> bool:
|
||||
return transporter_fuel_boost() > 1.0 and transporter_fuel_capacity() > 0
|
||||
|
||||
|
||||
# The speed THIS transporter is making: the base crawl, multiplied while it
|
||||
# still has something in the tank.
|
||||
func transporter_leg_speed(t: Dictionary) -> float:
|
||||
if int(t.get("fuel", 0)) > 0:
|
||||
return transporter_speed() * transporter_fuel_boost()
|
||||
return transporter_speed()
|
||||
|
||||
|
||||
const PRODUCT_SHIP: String = "interceptor"
|
||||
|
||||
|
||||
|
|
@ -1859,8 +1872,10 @@ func queue_order(id: int, product: String = PRODUCT_SHIP) -> bool:
|
|||
if b.is_empty() or not can_produce(b.type):
|
||||
return false
|
||||
var definition: Resource = vessel_definition(product)
|
||||
if definition == null or not definition.fleet_eligible \
|
||||
or not vessel_is_unlocked(product):
|
||||
# #216: support craft are orderable here too. They never join the fleet,
|
||||
# so "can the crafter make it" is its own question now.
|
||||
if definition == null or not vessel_is_unlocked(product) \
|
||||
or not (definition.fleet_eligible or definition.support_craftable):
|
||||
return false
|
||||
(b.orders as Array).append({"product": product, "elapsed": 0.0, "started": false})
|
||||
return true
|
||||
|
|
@ -1962,9 +1977,10 @@ func _advance_production(delta: float) -> void:
|
|||
continue
|
||||
|
||||
orders.pop_front()
|
||||
# A finished combat hull launches from the crafter and physically flies
|
||||
# to the mothership hangar. Hub transporters are provisioned by hubs and
|
||||
# never enter this production path.
|
||||
# A finished hull launches from the crafter and physically flies to the
|
||||
# mothership hangar - support craft included since #216, which is what
|
||||
# _advance_station_dispatch() then draws on to staff a hub or a
|
||||
# workshop.
|
||||
var mothership: Variant = get_mothership_position()
|
||||
if mothership == null:
|
||||
stored_vessels.append(product)
|
||||
|
|
@ -2319,24 +2335,12 @@ func workshop_ore_demand(id: int) -> int:
|
|||
const WORKSHOP_ORE_BUFFER: int = 120
|
||||
|
||||
|
||||
func _provision_workshop_drones(workshop: Dictionary) -> void:
|
||||
var stationed: int = 0
|
||||
for drone in repair_drones:
|
||||
if int(drone.get("workshop_id", 0)) == int(workshop.id):
|
||||
stationed += 1
|
||||
while stationed < workshop_drone_capacity():
|
||||
repair_drones.append({
|
||||
"workshop_id": int(workshop.id), "state": DRONE_IDLE, "target_id": 0,
|
||||
"from": workshop.position, "to": workshop.position, "progress": 1.0,
|
||||
"carrying": 0,
|
||||
})
|
||||
stationed += 1
|
||||
|
||||
|
||||
func _sync_workshop_drones() -> void:
|
||||
for workshop in buildings:
|
||||
if building_has_capability(workshop, "repair"):
|
||||
_provision_workshop_drones(workshop)
|
||||
func _add_workshop_drone(workshop: Dictionary) -> void:
|
||||
repair_drones.append({
|
||||
"workshop_id": int(workshop.id), "state": DRONE_IDLE, "target_id": 0,
|
||||
"from": workshop.position, "to": workshop.position, "progress": 1.0,
|
||||
"carrying": 0, "repairs_left": DRONE_REPAIRS,
|
||||
})
|
||||
|
||||
|
||||
func repair_drone_position(drone: Dictionary) -> Vector2:
|
||||
|
|
@ -2355,7 +2359,9 @@ func _advance_repairs(delta: float) -> void:
|
|||
if repair_drones.is_empty():
|
||||
return
|
||||
var speed: float = vessel_stat(REPAIR_DRONE, "transport_speed")
|
||||
for drone in repair_drones:
|
||||
# Duplicated because a drone that runs out of work is removed from the
|
||||
# list below, and #216 made that reachable from inside this loop.
|
||||
for drone in repair_drones.duplicate():
|
||||
var workshop: Dictionary = find_building(int(drone.workshop_id))
|
||||
if workshop.is_empty():
|
||||
continue
|
||||
|
|
@ -2382,6 +2388,11 @@ func _advance_repairs(delta: float) -> void:
|
|||
_send_drone(drone, workshop.position, DRONE_RETURNING)
|
||||
else:
|
||||
drone.state = DRONE_IDLE
|
||||
# #216: counted where the run ENDS, so a drone is never retired
|
||||
# with a building half repaired behind it.
|
||||
drone.repairs_left = int(drone.get("repairs_left", DRONE_REPAIRS)) - 1
|
||||
if int(drone.repairs_left) <= 0:
|
||||
_retire_drone(drone)
|
||||
|
||||
|
||||
func _dispatch_drone(drone: Dictionary, workshop: Dictionary) -> void:
|
||||
|
|
@ -3095,6 +3106,7 @@ func _process(delta: float) -> void:
|
|||
_advance_lab_research(delta)
|
||||
_advance_vessel_deliveries(delta)
|
||||
_advance_garrison_dispatch()
|
||||
_advance_station_dispatch()
|
||||
_advance_planning()
|
||||
_advance_repairs(delta)
|
||||
_advance_resource_converters(delta)
|
||||
|
|
@ -3132,8 +3144,14 @@ func _advance_vessel_deliveries(delta: float) -> void:
|
|||
# destroyed by its destination going away, the same rule a
|
||||
# transporter mid-delivery follows with its cargo.
|
||||
var outpost_id: int = int(delivery.get("to_outpost", 0))
|
||||
var station_id: int = int(delivery.get("to_station", 0))
|
||||
if outpost_id != 0 and _garrison_still_wants(outpost_id, String(delivery.type)):
|
||||
garrison_crew(outpost_id).append(String(delivery.type))
|
||||
elif station_id != 0 and _station_still_wants(station_id):
|
||||
# #216: same rule as an outpost's - a hub levelled or an order
|
||||
# cancelled while the vessel was in the air lands it in the
|
||||
# hangar rather than destroying it.
|
||||
_station_arrived(station_id)
|
||||
else:
|
||||
stored_vessels.append(String(delivery.type))
|
||||
|
||||
|
|
@ -3165,6 +3183,10 @@ const TRANSPORTER_TO_MOTHERSHIP_FROM_EXTRACTOR: String = "extractor_to_mothershi
|
|||
# `target_id` exactly like the ordinary supply path does, rather than
|
||||
# `extractor_index`: the source is a building, already addressable that way.
|
||||
const TRANSPORTER_TO_BUILDING_PICKUP: String = "to_building_pickup"
|
||||
# #217: fetching its own fuel. A leg of its own rather than a flag on the
|
||||
# others, so a transporter that is refuelling is visibly doing that and can
|
||||
# never be dispatched onto a cargo run halfway there.
|
||||
const TRANSPORTER_TO_FUEL: String = "to_fuel"
|
||||
const TRANSPORTER_TO_MOTHERSHIP_FROM_BUILDING: String = "building_to_mothership"
|
||||
|
||||
var transporters: Array = []
|
||||
|
|
@ -3186,30 +3208,19 @@ func hub_count() -> int:
|
|||
return n
|
||||
|
||||
|
||||
# #216: a hub used to conjure its own transporters, up to capacity, for free
|
||||
# and forever. They are BUILT now - ordered at a ship crafter, flown out from
|
||||
# the mothership, and worn out by the work they do - so this only ever adds
|
||||
# one that has actually arrived.
|
||||
func _add_hub_transporter(hub: Dictionary) -> void:
|
||||
transporters.append({
|
||||
"hub_id": int(hub.id), "state": TRANSPORTER_IDLE, "target_id": 0,
|
||||
"extractor_index": -1, "carrying": 0, "resource_type": RESOURCE_ORE,
|
||||
"progress": 1.0, "from": hub.position, "to": hub.position,
|
||||
"trips_left": TRANSPORTER_TRIPS, "fuel": 0, "fuel_source_id": 0,
|
||||
})
|
||||
|
||||
|
||||
func _provision_hub_transporters(hub: Dictionary) -> void:
|
||||
var stationed: int = 0
|
||||
for transporter in transporters:
|
||||
if int(transporter.get("hub_id", 0)) == int(hub.id):
|
||||
stationed += 1
|
||||
while stationed < hub_capacity():
|
||||
_add_hub_transporter(hub)
|
||||
stationed += 1
|
||||
|
||||
|
||||
func _sync_hub_transporters() -> void:
|
||||
for hub in buildings:
|
||||
if building_has_capability(hub, "transport_hub"):
|
||||
_provision_hub_transporters(hub)
|
||||
|
||||
|
||||
func transporter_position(t: Dictionary) -> Vector2:
|
||||
return (t.from as Vector2).lerp(t.to as Vector2, clampf(t.progress, 0.0, 1.0))
|
||||
|
||||
|
|
@ -3257,10 +3268,50 @@ func _transporter_inbound_to_extractor(index: int) -> bool:
|
|||
return false
|
||||
|
||||
|
||||
# #217: the nearest place with energy in it, as {position, id} - id 0 meaning
|
||||
# the bank at the mothership, which is where most of it sits. Nearest to the
|
||||
# transporter itself rather than to its hub: it is the one making the trip.
|
||||
func _nearest_energy_source(from: Vector2) -> Dictionary:
|
||||
var best: Dictionary = {}
|
||||
var best_distance: float = INF
|
||||
var mothership: Variant = get_mothership_position()
|
||||
if mothership != null and bank_inventory.amount(RESOURCE_ENERGY) > 0:
|
||||
best = {"position": mothership, "id": 0}
|
||||
best_distance = from.distance_squared_to(mothership)
|
||||
for b in buildings:
|
||||
if building_has_capability(b, "bank"):
|
||||
continue # already considered, as the bank above
|
||||
if building_resource(int(b.id), RESOURCE_ENERGY) <= 0:
|
||||
continue
|
||||
var distance: float = from.distance_squared_to(b.position)
|
||||
if distance < best_distance:
|
||||
best_distance = distance
|
||||
best = {"position": b.position, "id": int(b.id)}
|
||||
return best
|
||||
|
||||
|
||||
# An empty tank is worth a detour only once a Burn Drive is researched, and
|
||||
# only while something has energy to give. Runs before ordinary dispatch so a
|
||||
# transporter tops up between jobs rather than crawling through the next one.
|
||||
func _refuel_idle_transporters() -> void:
|
||||
if not transporter_burns_energy():
|
||||
return
|
||||
for t in transporters:
|
||||
if t.state != TRANSPORTER_IDLE or int(t.get("fuel", 0)) > 0:
|
||||
continue
|
||||
var here: Vector2 = transporter_position(t)
|
||||
var source: Dictionary = _nearest_energy_source(here)
|
||||
if source.is_empty():
|
||||
continue
|
||||
t.fuel_source_id = int(source.id)
|
||||
_begin_leg(t, here, Vector2(source.position), TRANSPORTER_TO_FUEL)
|
||||
|
||||
|
||||
func _dispatch_transporters() -> void:
|
||||
var mothership: Variant = get_mothership_position()
|
||||
if mothership == null:
|
||||
return # nowhere to load from
|
||||
_refuel_idle_transporters()
|
||||
# Supply already-queued production and research before collecting passive
|
||||
# extractor output. Extractors can refill forever, so servicing them first
|
||||
# can otherwise consume every transporter each time one becomes idle and
|
||||
|
|
@ -3346,19 +3397,26 @@ func _dispatch_transporters() -> void:
|
|||
|
||||
|
||||
func _advance_transporters(delta: float) -> void:
|
||||
_sync_hub_transporters()
|
||||
if transporters.is_empty():
|
||||
return
|
||||
_dispatch_transporters()
|
||||
for t in transporters:
|
||||
# Duplicated for the same reason as the drones: a spent transporter is
|
||||
# removed from this list on arrival.
|
||||
for t in transporters.duplicate():
|
||||
if t.state == TRANSPORTER_IDLE:
|
||||
continue
|
||||
var distance: float = (t.from as Vector2).distance_to(t.to as Vector2)
|
||||
var leg: float = maxf(distance / transporter_speed(), 0.0001)
|
||||
var leg: float = maxf(distance / transporter_leg_speed(t), 0.0001)
|
||||
t.progress += delta / leg
|
||||
if t.progress < 1.0:
|
||||
continue
|
||||
t.progress = 1.0
|
||||
# #217: a unit of energy per leg flown under boost, spent on arrival
|
||||
# so a leg is either paid for in full or not flown under boost at all.
|
||||
# Refuelling legs are not charged - a transporter would otherwise burn
|
||||
# the fuel it is on its way to collect.
|
||||
if int(t.get("fuel", 0)) > 0 and String(t.state) != TRANSPORTER_TO_FUEL:
|
||||
t.fuel = int(t.fuel) - 1
|
||||
_arrive(t)
|
||||
|
||||
|
||||
|
|
@ -3429,9 +3487,187 @@ func _arrive(t: Dictionary) -> void:
|
|||
t.carrying = 0
|
||||
t.target_id = 0
|
||||
_begin_leg(t, here, hub_pos if hub_pos != null else here, TRANSPORTER_RETURNING)
|
||||
TRANSPORTER_TO_FUEL:
|
||||
# Whatever is actually there, up to the tank. A store drained by
|
||||
# something else while this was in the air simply means a shorter
|
||||
# fill, not a wasted trip.
|
||||
var tank: int = transporter_fuel_capacity() - int(t.get("fuel", 0))
|
||||
var source_id: int = int(t.get("fuel_source_id", 0))
|
||||
var drawn: int = 0
|
||||
if source_id == 0:
|
||||
drawn = mini(tank, bank_inventory.amount(RESOURCE_ENERGY))
|
||||
bank_inventory.withdraw(RESOURCE_ENERGY, drawn)
|
||||
else:
|
||||
drawn = mini(tank, building_resource(source_id, RESOURCE_ENERGY))
|
||||
var store: RefCounted = building_inventory(source_id)
|
||||
if store != null:
|
||||
store.withdraw(RESOURCE_ENERGY, drawn)
|
||||
else:
|
||||
drawn = 0
|
||||
t.fuel = int(t.get("fuel", 0)) + drawn
|
||||
t.fuel_source_id = 0
|
||||
_begin_leg(t, here, hub_pos if hub_pos != null else here, TRANSPORTER_RETURNING)
|
||||
TRANSPORTER_RETURNING:
|
||||
t.state = TRANSPORTER_IDLE
|
||||
t.progress = 1.0
|
||||
# #216: a round trip is what wears one out, counted where the trip
|
||||
# ENDS. Counting at dispatch would retire a vessel with its cargo
|
||||
# still in the air.
|
||||
t.trips_left = int(t.get("trips_left", TRANSPORTER_TRIPS)) - 1
|
||||
if int(t.trips_left) <= 0:
|
||||
_retire_transporter(t)
|
||||
|
||||
|
||||
# --- staffing hubs and workshops (#216) ------------------------------------
|
||||
#
|
||||
# Transporters and repair drones used to appear with their building, free and
|
||||
# permanent. They are ordinary craft now: ordered at a ship crafter, parked in
|
||||
# the mothership hangar, flown out to whichever structure asked for them, and
|
||||
# worn out by the work they do. What a structure HAS and what it was ASKED to
|
||||
# have are separate, exactly as they are for an outpost garrison (#104), so a
|
||||
# hub waiting on a hull it has not built yet reads as waiting rather than as
|
||||
# broken.
|
||||
#
|
||||
# How much work one has in it before it is spent. Round numbers rather than a
|
||||
# curve: the point the ticket makes is that they run out and have to be
|
||||
# replaced, and a player has to be able to hold "about twenty runs" in their
|
||||
# head while deciding whether to build another.
|
||||
const TRANSPORTER_TRIPS: int = 20
|
||||
const DRONE_REPAIRS: int = 12
|
||||
|
||||
# Both already exist above - VESSEL_TRANSPORTER with the other vessel ids,
|
||||
# REPAIR_DRONE with the workshop - so they are used rather than redeclared.
|
||||
|
||||
|
||||
# Which vessel staffs this structure, or "" for one that is not staffed.
|
||||
func station_vessel_type(building: Dictionary) -> String:
|
||||
if building_has_capability(building, "transport_hub"):
|
||||
return VESSEL_TRANSPORTER
|
||||
if building_has_capability(building, "repair"):
|
||||
return REPAIR_DRONE
|
||||
return ""
|
||||
|
||||
|
||||
func station_capacity(building: Dictionary) -> int:
|
||||
match station_vessel_type(building):
|
||||
VESSEL_TRANSPORTER: return hub_capacity()
|
||||
REPAIR_DRONE: return workshop_drone_capacity()
|
||||
return 0
|
||||
|
||||
|
||||
func station_desired(id: int) -> int:
|
||||
var building: Dictionary = find_building(id)
|
||||
if building.is_empty():
|
||||
return 0
|
||||
return mini(int(building.get("staff_desired", 0)), station_capacity(building))
|
||||
|
||||
|
||||
# Returns what was actually set, so a caller can show a clamped request rather
|
||||
# than silently doing something else - same contract as set_garrison_desired.
|
||||
func set_station_desired(id: int, count: int) -> int:
|
||||
var building: Dictionary = find_building(id)
|
||||
if building.is_empty() or station_vessel_type(building) == "":
|
||||
return 0
|
||||
building.staff_desired = clampi(count, 0, station_capacity(building))
|
||||
return int(building.staff_desired)
|
||||
|
||||
|
||||
# How many are actually standing there. Counts the crew, not the order: one
|
||||
# still in the air has not started working yet.
|
||||
func station_crew(id: int) -> int:
|
||||
var building: Dictionary = find_building(id)
|
||||
var n: int = 0
|
||||
match station_vessel_type(building):
|
||||
VESSEL_TRANSPORTER:
|
||||
for transporter in transporters:
|
||||
if int(transporter.get("hub_id", 0)) == id:
|
||||
n += 1
|
||||
REPAIR_DRONE:
|
||||
for drone in repair_drones:
|
||||
if int(drone.get("workshop_id", 0)) == id:
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
# What is left in each of them, worst first, for the readout in the building.
|
||||
# A structure whose crew is nearly spent should look nearly spent.
|
||||
func station_condition(id: int) -> Array:
|
||||
var building: Dictionary = find_building(id)
|
||||
var left: Array = []
|
||||
match station_vessel_type(building):
|
||||
VESSEL_TRANSPORTER:
|
||||
for transporter in transporters:
|
||||
if int(transporter.get("hub_id", 0)) == id:
|
||||
left.append(int(transporter.get("trips_left", TRANSPORTER_TRIPS)))
|
||||
REPAIR_DRONE:
|
||||
for drone in repair_drones:
|
||||
if int(drone.get("workshop_id", 0)) == id:
|
||||
left.append(int(drone.get("repairs_left", DRONE_REPAIRS)))
|
||||
left.sort()
|
||||
return left
|
||||
|
||||
|
||||
func station_work_capacity(id: int) -> int:
|
||||
var building: Dictionary = find_building(id)
|
||||
match station_vessel_type(building):
|
||||
VESSEL_TRANSPORTER: return TRANSPORTER_TRIPS
|
||||
REPAIR_DRONE: return DRONE_REPAIRS
|
||||
return 0
|
||||
|
||||
|
||||
# One in the air, so a structure short of crew does not order a second hull
|
||||
# for the same berth while the first is still on its way.
|
||||
func _station_inbound(id: int) -> int:
|
||||
var n: int = 0
|
||||
for delivery in vessel_deliveries:
|
||||
if int(delivery.get("to_station", 0)) == id:
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
func _advance_station_dispatch() -> void:
|
||||
var mothership: Variant = get_mothership_position()
|
||||
if mothership == null:
|
||||
return
|
||||
for building in buildings:
|
||||
var vessel_type: String = station_vessel_type(building)
|
||||
if vessel_type == "":
|
||||
continue
|
||||
var id: int = int(building.id)
|
||||
var short: int = station_desired(id) - station_crew(id) - _station_inbound(id)
|
||||
while short > 0 and _take_stored_vessel(vessel_type):
|
||||
vessel_deliveries.append({"type": vessel_type, "from": mothership,
|
||||
"to": building.position, "progress": 0.0, "to_station": id})
|
||||
short -= 1
|
||||
|
||||
|
||||
func _station_still_wants(id: int) -> bool:
|
||||
var building: Dictionary = find_building(id)
|
||||
if building.is_empty() or station_vessel_type(building) == "":
|
||||
return false
|
||||
return station_crew(id) < station_desired(id)
|
||||
|
||||
|
||||
func _station_arrived(id: int) -> void:
|
||||
var building: Dictionary = find_building(id)
|
||||
match station_vessel_type(building):
|
||||
VESSEL_TRANSPORTER: _add_hub_transporter(building)
|
||||
REPAIR_DRONE: _add_workshop_drone(building)
|
||||
|
||||
|
||||
# A spent vessel is GONE, not returned to the hangar: it was used up. The
|
||||
# structure is short again, and the dispatch above will send another as soon
|
||||
# as the player has built one.
|
||||
func _retire_transporter(t: Dictionary) -> void:
|
||||
var index: int = transporters.find(t)
|
||||
if index >= 0:
|
||||
transporters.remove_at(index)
|
||||
|
||||
|
||||
func _retire_drone(drone: Dictionary) -> void:
|
||||
var index: int = repair_drones.find(drone)
|
||||
if index >= 0:
|
||||
repair_drones.remove_at(index)
|
||||
|
||||
|
||||
# --- quests (#129, #131) ---------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in a new issue