139 lines
5.2 KiB
GDScript3
139 lines
5.2 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
# Forgejo #216, the workshop half. A spacial workshop used to conjure its own
|
||
|
|
# repair drones, free and permanent. They are built at a ship crafter now,
|
||
|
|
# flown out from the mothership hangar to whichever workshop asked for them,
|
||
|
|
# and spent by the repairs they make.
|
||
|
|
#
|
||
|
|
# test_transporter_supply.gd covers the same rules on the hub side. The two
|
||
|
|
# share a model but not their wear paths - a transporter spends a run getting
|
||
|
|
# home, a drone spends a repair getting home - so the drone's own path is
|
||
|
|
# exercised here rather than assumed from the transporter's.
|
||
|
|
#
|
||
|
|
# Covers:
|
||
|
|
# A. a new workshop stands empty, and takes nothing until it is asked to
|
||
|
|
# B. the crafter accepts a repair drone order, which it used to refuse
|
||
|
|
# C. an assigned workshop is sent one from the hangar
|
||
|
|
# D. it repairs a damaged structure and is worn by doing so
|
||
|
|
# E. its last repair uses it up, and the workshop is short again
|
||
|
|
|
||
|
|
var state: Node
|
||
|
|
var workshop_id: int
|
||
|
|
var damaged_id: int
|
||
|
|
var elapsed: float = 0.0
|
||
|
|
var stage: int = 0
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
state = root.get_node("GameState")
|
||
|
|
state.buildings.clear()
|
||
|
|
state.extractors.clear()
|
||
|
|
state.transporters.clear()
|
||
|
|
state.repair_drones.clear()
|
||
|
|
state.stored_vessels.clear()
|
||
|
|
state.vessel_deliveries.clear()
|
||
|
|
state.reset_progression()
|
||
|
|
state.rocks = 600
|
||
|
|
state.unlocked = ["shipyards", "logistics"]
|
||
|
|
state.add_building(state.BUILDING_MOTHERSHIP, Vector2.ZERO)
|
||
|
|
workshop_id = state.add_building(GameState.BUILDING_WORKSHOP, Vector2(700.0, 0.0))
|
||
|
|
damaged_id = state.add_building(state.BUILDING_SHIP_CRAFTER, Vector2(900.0, 200.0))
|
||
|
|
state.deposit_resource_to_building(workshop_id, GameState.RESOURCE_ORE, 400)
|
||
|
|
|
||
|
|
|
||
|
|
func _drones() -> int:
|
||
|
|
return state.station_crew(workshop_id)
|
||
|
|
|
||
|
|
|
||
|
|
func _process(delta: float) -> bool:
|
||
|
|
elapsed += delta
|
||
|
|
match stage:
|
||
|
|
0:
|
||
|
|
# --- A. nothing comes with the structure ---------------------
|
||
|
|
if not state.repair_drones.is_empty():
|
||
|
|
return _fail("a new workshop arrived with %d drones" % state.repair_drones.size())
|
||
|
|
state.stored_vessels.append(GameState.REPAIR_DRONE)
|
||
|
|
state._advance_station_dispatch()
|
||
|
|
if _drones() != 0:
|
||
|
|
return _fail("a workshop that asked for nothing took a drone anyway")
|
||
|
|
print("a new workshop stands empty, and takes nothing unasked")
|
||
|
|
|
||
|
|
# --- B. the crafter takes the order --------------------------
|
||
|
|
var crafter_id: int = state.add_building(state.BUILDING_SHIP_CRAFTER, Vector2(-900.0, 0.0))
|
||
|
|
if not state.queue_order(crafter_id, GameState.REPAIR_DRONE):
|
||
|
|
return _fail("the crafter refused a repair drone order")
|
||
|
|
state.find_building(crafter_id).orders.clear()
|
||
|
|
|
||
|
|
# --- C. assigned, then sent ----------------------------------
|
||
|
|
if state.set_station_desired(workshop_id, 1) != 1:
|
||
|
|
return _fail("the workshop refused an order for one drone")
|
||
|
|
state._advance_station_dispatch()
|
||
|
|
if state.vessel_deliveries.is_empty():
|
||
|
|
return _fail("nothing was sent to the workshop")
|
||
|
|
elapsed = 0.0
|
||
|
|
stage = 1
|
||
|
|
return false
|
||
|
|
1:
|
||
|
|
if _drones() < 1:
|
||
|
|
if elapsed > 25.0:
|
||
|
|
return _fail("the drone never reached the workshop")
|
||
|
|
return false
|
||
|
|
var fresh: Array = state.station_condition(workshop_id)
|
||
|
|
if fresh.size() != 1 or int(fresh[0]) != GameState.DRONE_REPAIRS:
|
||
|
|
return _fail("the arrived drone reports %s, expected [%d]" \
|
||
|
|
% [fresh, GameState.DRONE_REPAIRS])
|
||
|
|
print("ordered and flown out: 1 drone with %d repairs in it" % GameState.DRONE_REPAIRS)
|
||
|
|
|
||
|
|
# --- D. it does the work, and is worn by it ------------------
|
||
|
|
state.damage_building(damaged_id, state.building_max_hp(state.BUILDING_SHIP_CRAFTER) / 2)
|
||
|
|
elapsed = 0.0
|
||
|
|
stage = 2
|
||
|
|
return false
|
||
|
|
2:
|
||
|
|
if state.building_health_fraction(damaged_id) >= 0.999:
|
||
|
|
print("the workshop's own drone repaired the structure")
|
||
|
|
elapsed = 0.0
|
||
|
|
stage = 3
|
||
|
|
return false
|
||
|
|
if elapsed > 40.0:
|
||
|
|
return _fail("the drone never repaired the damaged structure")
|
||
|
|
return false
|
||
|
|
3:
|
||
|
|
# Spent on getting HOME, so this waits for it to be idle again.
|
||
|
|
if state.repair_drones.is_empty():
|
||
|
|
return _fail("the drone vanished mid-run")
|
||
|
|
if String(state.repair_drones[0].state) != GameState.DRONE_IDLE:
|
||
|
|
if elapsed > 25.0:
|
||
|
|
return _fail("the drone never got home")
|
||
|
|
return false
|
||
|
|
var worn: Array = state.station_condition(workshop_id)
|
||
|
|
if worn.is_empty() or int(worn[0]) >= GameState.DRONE_REPAIRS:
|
||
|
|
return _fail("a drone that ran a repair is still unworn (%s)" % [worn])
|
||
|
|
print("a completed repair wore it to %d" % int(worn[0]))
|
||
|
|
|
||
|
|
# --- E. and its last one uses it up --------------------------
|
||
|
|
state.repair_drones[0].repairs_left = 1
|
||
|
|
state.damage_building(damaged_id, state.building_max_hp(state.BUILDING_SHIP_CRAFTER) / 2)
|
||
|
|
elapsed = 0.0
|
||
|
|
stage = 4
|
||
|
|
return false
|
||
|
|
4:
|
||
|
|
if not state.repair_drones.is_empty():
|
||
|
|
if elapsed > 40.0:
|
||
|
|
return _fail("a drone on its last repair was never retired")
|
||
|
|
return false
|
||
|
|
if state.stored_vessels.has(GameState.REPAIR_DRONE):
|
||
|
|
return _fail("a spent drone went back to the hangar instead of being used up")
|
||
|
|
if _drones() != 0:
|
||
|
|
return _fail("the workshop still counts a retired drone")
|
||
|
|
print("spent after its last repair: gone, and the workshop is short again")
|
||
|
|
print("TEST_WORKSHOP_STAFFING: PASS")
|
||
|
|
quit(0)
|
||
|
|
return true
|
||
|
|
return false
|
||
|
|
|
||
|
|
|
||
|
|
func _fail(message: String) -> bool:
|
||
|
|
print("TEST_WORKSHOP_STAFFING: FAIL (%s)" % message)
|
||
|
|
quit(1)
|
||
|
|
return true
|