#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
127 lines
5.2 KiB
GDScript
127 lines
5.2 KiB
GDScript
extends SceneTree
|
|
|
|
# Forgejo #217: transporters crawl by default, and a Burn Drive lets them
|
|
# carry energy and spend it to go far faster. The energy is theirs to find -
|
|
# they fetch it from the nearest store that has any - and it runs out, so the
|
|
# speed is something the player's energy supply pays for continuously rather
|
|
# than a one-off purchase.
|
|
#
|
|
# Covers:
|
|
# A. unresearched, a transporter never detours for fuel however much energy
|
|
# is lying about, and makes the base speed
|
|
# B. researched and empty, an idle one goes for the NEAREST store with
|
|
# energy in it, and takes what is there
|
|
# C. a fuelled transporter is measurably faster than an unfuelled one
|
|
# D. a leg burns a unit, and an empty tank drops it back to the crawl
|
|
# E. the leg it flies to collect fuel is not itself charged
|
|
|
|
const HUB_AT: Vector2 = Vector2(0.0, 0.0)
|
|
const NEAR_ENERGY_AT: Vector2 = Vector2(400.0, 0.0)
|
|
const FAR_ENERGY_AT: Vector2 = Vector2(-3000.0, 0.0)
|
|
|
|
var state: Node
|
|
var hub_id: int
|
|
var near_id: int
|
|
var far_id: int
|
|
|
|
|
|
func _initialize() -> void:
|
|
state = root.get_node("GameState")
|
|
state.buildings.clear()
|
|
state.extractors.clear()
|
|
state.transporters.clear()
|
|
state.stored_vessels.clear()
|
|
state.vessel_deliveries.clear()
|
|
state.reset_progression()
|
|
state.rocks = 500
|
|
state.unlocked = ["shipyards", "logistics", "freight"]
|
|
state.add_building(state.BUILDING_MOTHERSHIP, Vector2(0.0, 4000.0))
|
|
hub_id = state.add_building(state.BUILDING_TRANSPORT_HUB, HUB_AT)
|
|
near_id = state.add_building(state.BUILDING_SHIP_CRAFTER, NEAR_ENERGY_AT)
|
|
far_id = state.add_building(state.BUILDING_SHIP_LAB, FAR_ENERGY_AT)
|
|
load("res://tests/_staff.gd").staff(state, hub_id, 1)
|
|
|
|
|
|
func _initialize_done() -> void:
|
|
pass
|
|
|
|
|
|
func _process(_delta: float) -> bool:
|
|
# The bank is deliberately empty of energy, so the only sources are the
|
|
# two structures below and "nearest" is a real choice.
|
|
state.bank_inventory.set_amount(GameState.RESOURCE_ENERGY, 0)
|
|
state.deposit_resource_to_building(near_id, GameState.RESOURCE_ENERGY, 4)
|
|
state.deposit_resource_to_building(far_id, GameState.RESOURCE_ENERGY, 50)
|
|
|
|
var t: Dictionary = state.transporters[0]
|
|
|
|
# --- A. unresearched: no tank, no detour, base speed ----------------
|
|
if state.transporter_burns_energy():
|
|
return _fail("an unresearched transporter already burns energy")
|
|
var crawl: float = state.transporter_leg_speed(t)
|
|
if not is_equal_approx(crawl, state.transporter_speed()):
|
|
return _fail("an unfuelled transporter makes %.1f, expected the base %.1f" \
|
|
% [crawl, state.transporter_speed()])
|
|
state._refuel_idle_transporters()
|
|
if String(t.state) != state.TRANSPORTER_IDLE:
|
|
return _fail("an unresearched transporter went looking for fuel")
|
|
print("unresearched: no detour, %.0f base speed" % crawl)
|
|
|
|
# --- B. researched and empty: to the NEAREST store ------------------
|
|
state.vessel_levels["trn_burn"] = 1
|
|
if not state.transporter_burns_energy():
|
|
return _fail("a researched Burn Drive did not enable energy burning")
|
|
state._refuel_idle_transporters()
|
|
if String(t.state) != state.TRANSPORTER_TO_FUEL:
|
|
return _fail("an empty transporter did not go for fuel (state %s)" % t.state)
|
|
if not Vector2(t.to).is_equal_approx(NEAR_ENERGY_AT):
|
|
return _fail("it flew to %s, not the nearer store at %s" % [t.to, NEAR_ENERGY_AT])
|
|
print("researched and empty: flies to the nearest store, not the fullest")
|
|
|
|
# --- E. and the trip to collect is not itself charged ---------------
|
|
var before_fuel: int = int(t.get("fuel", 0))
|
|
state._advance_transporters(600.0)
|
|
if int(t.get("fuel", 0)) <= before_fuel:
|
|
return _fail("the transporter came back from the fuel store with nothing")
|
|
# The near store held 4, which is under the tank, so it took all of it.
|
|
if int(t.fuel) != 4:
|
|
return _fail("it drew %d energy, expected the 4 that were there" % int(t.fuel))
|
|
if state.building_resource(near_id, GameState.RESOURCE_ENERGY) != 0:
|
|
return _fail("the store it drew from still holds energy")
|
|
print("collected 4 - all the near store had - and was not charged for the trip")
|
|
|
|
# --- C. fuelled is faster -------------------------------------------
|
|
var boosted: float = state.transporter_leg_speed(t)
|
|
if boosted <= crawl:
|
|
return _fail("a fuelled transporter makes %.1f, no better than the crawl %.1f" \
|
|
% [boosted, crawl])
|
|
if not is_equal_approx(boosted, crawl * state.transporter_fuel_boost()):
|
|
return _fail("a fuelled transporter makes %.1f, expected %.1f" \
|
|
% [boosted, crawl * state.transporter_fuel_boost()])
|
|
print("fuelled: %.0f against %.0f, a %.1fx difference" \
|
|
% [boosted, crawl, state.transporter_fuel_boost()])
|
|
|
|
# --- D. and it burns down to the crawl ------------------------------
|
|
var tank: int = int(t.fuel)
|
|
for leg in range(tank):
|
|
t.state = state.TRANSPORTER_RETURNING
|
|
t.progress = 0.0
|
|
t.from = HUB_AT
|
|
t.to = NEAR_ENERGY_AT
|
|
state._advance_transporters(600.0)
|
|
if int(t.get("fuel", 0)) != 0:
|
|
return _fail("%d legs left %d energy aboard, expected an empty tank" \
|
|
% [tank, int(t.fuel)])
|
|
if not is_equal_approx(state.transporter_leg_speed(t), crawl):
|
|
return _fail("an emptied transporter did not drop back to the crawl")
|
|
print("%d legs emptied the tank and it is back to %.0f" % [tank, crawl])
|
|
|
|
print("TEST_TRANSPORTER_BURN: PASS")
|
|
quit(0)
|
|
return true
|
|
|
|
|
|
func _fail(message: String) -> bool:
|
|
print("TEST_TRANSPORTER_BURN: FAIL (%s)" % message)
|
|
quit(1)
|
|
return true
|