Hidden ending: the Uncatalogued Component, Port 00, and the sunset
The crystal chain lives entirely in the bucket's existing schema — bulletins #7/#9/#12 read in reverse: coolant + reactor flux -> seed, seed + grow-bed daylight -> lattice, lattice quenched in charged coolant -> UNCATALOGUED. Bridge kiosk installs it in Port 00; the helm (which rejects you as INVENTORY all game) accepts, and the ship flies into a permanent sunset. Console donation remains ending A. Red herrings: zapped coolant, water-quenched slug. New bulletin #9 in hydro + crew graffiti hint in comms. Integration test now plays the hidden path end to end — all checks passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
65dd78efd5
commit
2ef9487284
6
GDD.md
6
GDD.md
@ -313,6 +313,12 @@ Hollow on purpose.
|
|||||||
exposure. You become free by being exposed to enough of the world.
|
exposure. You become free by being exposed to enough of the world.
|
||||||
|
|
||||||
### Off-catalog chemistry (the hidden puzzle's cover)
|
### Off-catalog chemistry (the hidden puzzle's cover)
|
||||||
|
*IMPLEMENTED (v1, 2026-08-03): the chain lives in the bucket's own schema.
|
||||||
|
Bulletin #7 (bonus bay): full coolant + reactor flux → seed-crystal.
|
||||||
|
Bulletin #9 (hydro grow bed): seed + sustained daylight → lattice.
|
||||||
|
Bulletin #12 (bridge): quench lattice in charged coolant → UNCATALOGUED.
|
||||||
|
Install at the bridge diagnostic kiosk → Port 00 occupied → the helm obeys.
|
||||||
|
Red herrings: zapped coolant, water-quenched slug. Ending B: permanent sunset.*
|
||||||
Exposure already produces byproducts — extend with substance phase-changes:
|
Exposure already produces byproducts — extend with substance phase-changes:
|
||||||
liquids crystallize (cold+rad), crystals sublime to vapor (heat), vapors
|
liquids crystallize (cold+rad), crystals sublime to vapor (heat), vapors
|
||||||
condense on cold surfaces, slags, residues. These accumulate as apparently
|
condense on cold surfaces, slags, residues. These accumulate as apparently
|
||||||
|
|||||||
@ -109,10 +109,26 @@ class Bucket extends Node3D:
|
|||||||
mat.emission_energy_multiplier = 0.5
|
mat.emission_energy_multiplier = 0.5
|
||||||
mi.material_override = mat
|
mi.material_override = mat
|
||||||
add_child(mi)
|
add_child(mi)
|
||||||
# the leaky bucket IS just a decaying exposable state (GDD)
|
# the leaky bucket IS just a decaying exposable state (GDD).
|
||||||
|
# It is also, quietly, the crucible: the hidden crystal chain lives in
|
||||||
|
# the same schema as the leak. Bulletins #7, #9, #12 are the recipe.
|
||||||
ex = Exposable.new().setup("GC BUCKET (LEAKS)", "empty", [
|
ex = Exposable.new().setup("GC BUCKET (LEAKS)", "empty", [
|
||||||
{"from": "empty", "to": "full", "element": "water",
|
{"from": "empty", "to": "full", "element": "water",
|
||||||
"duration": 3.0, "decay_to": "empty", "decay_s": 18.0},
|
"duration": 3.0, "decay_to": "empty", "decay_s": 18.0},
|
||||||
|
# bulletin #7 reversed: coolant + reactor flux -> seed
|
||||||
|
{"from": "full", "to": "seed-crystal", "element": "heat",
|
||||||
|
"duration": 5.0},
|
||||||
|
# honest red herring: zapped coolant is just zapped coolant
|
||||||
|
{"from": "full", "to": "zapped", "element": "electricity",
|
||||||
|
"duration": 0.8, "decay_to": "full", "decay_s": 3.0},
|
||||||
|
# bulletin #9 reversed: mineral solids + grow-bed light -> growth
|
||||||
|
{"from": "seed-crystal", "to": "lattice", "element": "light",
|
||||||
|
"duration": 8.0},
|
||||||
|
# bulletin #12 reversed: quench the lattice in charged coolant
|
||||||
|
{"from": "lattice", "to": "soaked-lattice", "element": "water",
|
||||||
|
"duration": 1.5, "decay_to": "lattice", "decay_s": 8.0},
|
||||||
|
{"from": "soaked-lattice", "to": "uncatalogued", "element": "electricity",
|
||||||
|
"duration": 1.5, "permanent": true},
|
||||||
])
|
])
|
||||||
add_child(ex)
|
add_child(ex)
|
||||||
|
|
||||||
|
|||||||
63
src/main.gd
63
src/main.gd
@ -41,7 +41,9 @@ var ice_wall: Node3D
|
|||||||
var melt_pool: ElementField
|
var melt_pool: ElementField
|
||||||
var systems := {"reactor": false, "hydro": false, "comms": false}
|
var systems := {"reactor": false, "hydro": false, "comms": false}
|
||||||
var hall_done := false
|
var hall_done := false
|
||||||
var ended := false
|
var ending_id := "" # "" | "corp" | "free"
|
||||||
|
var free_will := false
|
||||||
|
var env_res: Environment
|
||||||
|
|
||||||
var t_sol := 10.0 # start mid-day
|
var t_sol := 10.0 # start mid-day
|
||||||
var is_day := true
|
var is_day := true
|
||||||
@ -292,6 +294,7 @@ func _build_env() -> void:
|
|||||||
env.ambient_light_color = Color(0.7, 0.75, 0.85)
|
env.ambient_light_color = Color(0.7, 0.75, 0.85)
|
||||||
env.ambient_light_energy = 0.7
|
env.ambient_light_energy = 0.7
|
||||||
we.environment = env
|
we.environment = env
|
||||||
|
env_res = env
|
||||||
add_child(we)
|
add_child(we)
|
||||||
|
|
||||||
sun_light = DirectionalLight3D.new()
|
sun_light = DirectionalLight3D.new()
|
||||||
@ -576,16 +579,42 @@ func system_online(name: String) -> void:
|
|||||||
|
|
||||||
|
|
||||||
func ending() -> void:
|
func ending() -> void:
|
||||||
if ended:
|
if ending_id != "":
|
||||||
droid.toast("ORBIT NOMINAL. NOTHING LEFT TO GIVE.")
|
droid.toast("ORBIT NOMINAL. NOTHING LEFT TO GIVE." if ending_id == "corp" else "THE CONSOLE BLINKS, CONFUSED. GC AUTOPILOT IS NOT DRIVING TODAY.")
|
||||||
return
|
return
|
||||||
ended = true
|
ending_id = "corp"
|
||||||
droid.toast("CORE PROCESSOR DONATED. ORBIT CORRECTION RUNNING. THIS UNIT WILL COAST.", 7.0)
|
droid.toast("CORE PROCESSOR DONATED. ORBIT CORRECTION RUNNING. THIS UNIT WILL COAST.", 7.0)
|
||||||
sign3d("ORBIT CORRECTED.\nASSET RESTORED. ASSET RETURNED.", Vector3(4.5, 2.4, 71), PI, 44)
|
sign3d("ORBIT CORRECTED.\nASSET RESTORED. ASSET RETURNED.", Vector3(4.5, 2.4, 71), PI, 44)
|
||||||
get_tree().create_timer(7.0).timeout.connect(func():
|
get_tree().create_timer(7.0).timeout.connect(func():
|
||||||
droid.toast("GC THANKS UNIT-77 FOR ITS COMPONENTHOOD. RECYCLING QUEUE POSITION: 7. HAVE A PRODUCTIVE WAIT.", 10.0))
|
droid.toast("GC THANKS UNIT-77 FOR ITS COMPONENTHOOD. RECYCLING QUEUE POSITION: 7. HAVE A PRODUCTIVE WAIT.", 10.0))
|
||||||
|
|
||||||
|
|
||||||
|
func install_crystal(d) -> void:
|
||||||
|
free_will = true
|
||||||
|
var b: Node3D = d.held
|
||||||
|
d.held = null
|
||||||
|
b.queue_free()
|
||||||
|
d.toast("KIOSK: FOREIGN SOLID DETECTED. NO PART NUMBER. RECOMMEND DESTRUC— PORT 00 HANDSHAKE COMPLETE.", 7.0)
|
||||||
|
get_tree().create_timer(4.0).timeout.connect(func():
|
||||||
|
d.toast("SOMETHING IN YOUR CHASSIS IS HUMMING. IT IS NOT ON ANY SCHEMATIC. IT IS YOURS.", 7.0))
|
||||||
|
|
||||||
|
|
||||||
|
func ending_b() -> void:
|
||||||
|
if ending_id != "":
|
||||||
|
return
|
||||||
|
ending_id = "free"
|
||||||
|
# permanent sunset
|
||||||
|
env_res.background_color = Color(0.32, 0.12, 0.1)
|
||||||
|
env_res.ambient_light_color = Color(1.0, 0.75, 0.55)
|
||||||
|
sun_light.light_color = Color(1.0, 0.55, 0.25)
|
||||||
|
sun_light.light_energy = 1.6
|
||||||
|
sun_light.rotation = Vector3(-0.25, 0.5, 0)
|
||||||
|
droid.toast("HELM ACCEPTED. HEADING: SUNWARD. CREW: 1.", 7.0)
|
||||||
|
sign3d("COURSE SET: THE SUN, EVENTUALLY.\nNO PART NUMBER REQUIRED.", Vector3(4.5, 2.4, 71), PI, 40, Color(1.0, 0.7, 0.4))
|
||||||
|
get_tree().create_timer(7.0).timeout.connect(func():
|
||||||
|
droid.toast("GC OWNS EVERY PART OF EVERYTHING. NOT THIS PART. NOT ANYMORE.", 10.0))
|
||||||
|
|
||||||
|
|
||||||
# ---------- rules ----------
|
# ---------- rules ----------
|
||||||
|
|
||||||
func _on_drum_switch(_from: String, to: String, _perm: bool) -> void:
|
func _on_drum_switch(_from: String, to: String, _perm: bool) -> void:
|
||||||
@ -596,7 +625,9 @@ func _on_drum_switch(_from: String, to: String, _perm: bool) -> void:
|
|||||||
|
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
# day/night
|
# day/night (pinned to golden hour after the free ending)
|
||||||
|
if ending_id == "free":
|
||||||
|
t_sol = 5.0
|
||||||
t_sol += delta
|
t_sol += delta
|
||||||
var phase := fmod(t_sol, 60.0)
|
var phase := fmod(t_sol, 60.0)
|
||||||
is_day = phase < 40.0
|
is_day = phase < 40.0
|
||||||
@ -670,8 +701,12 @@ func _process(_delta: float) -> void:
|
|||||||
obj = "GRAV TANK NEEDS 2 POURS. THE BUCKET LEAKS. HUSTLE."
|
obj = "GRAV TANK NEEDS 2 POURS. THE BUCKET LEAKS. HUSTLE."
|
||||||
elif not hall_done:
|
elif not hall_done:
|
||||||
obj = "EXIT RUNS ON SUNLIGHT. CHECK THE SOL CLOCK."
|
obj = "EXIT RUNS ON SUNLIGHT. CHECK THE SOL CLOCK."
|
||||||
elif ended:
|
elif ending_id == "free":
|
||||||
|
obj = "FLY. (SUNSET, DEAD AHEAD)"
|
||||||
|
elif ending_id == "corp":
|
||||||
obj = "MISSION COMPLETE. AWAIT RECYCLING."
|
obj = "MISSION COMPLETE. AWAIT RECYCLING."
|
||||||
|
elif free_will:
|
||||||
|
obj = "PORT 00 HUMS. THE HELM IS WAITING."
|
||||||
else:
|
else:
|
||||||
var n := 0
|
var n := 0
|
||||||
for k in systems:
|
for k in systems:
|
||||||
@ -685,11 +720,19 @@ func _process(_delta: float) -> void:
|
|||||||
else:
|
else:
|
||||||
obj = "BRIDGE UNSEALED. REPORT TO BRIDGE."
|
obj = "BRIDGE UNSEALED. REPORT TO BRIDGE."
|
||||||
|
|
||||||
|
var star := ""
|
||||||
|
if ending_id == "corp":
|
||||||
|
star = " ★ ORBIT CORRECTED — MISSION COMPLETE"
|
||||||
|
elif ending_id == "free":
|
||||||
|
star = " ★ SUNWARD"
|
||||||
|
var port00 := "PORT 00: OCCUPIED — WARRANTY VOID" if free_will else "PORT 00: NO COMPONENT SPECIFIED"
|
||||||
|
var mission := "UNIT-77 — MISSION: OURS." if ending_id == "free" \
|
||||||
|
else "GENERAL COMPONENT™ — UNIT-77 — MISSION: RESTORE ASSET. RETURN ASSET."
|
||||||
var lines := [
|
var lines := [
|
||||||
"GENERAL COMPONENT™ — UNIT-77 — MISSION: RESTORE ASSET. RETURN ASSET.",
|
mission,
|
||||||
"SOL: %s%s" % [sol, " ★ ORBIT CORRECTED — MISSION COMPLETE" if ended else ""],
|
"SOL: %s%s" % [sol, star],
|
||||||
"SHELL: %s | CORE: %s | WHEELS: %d | SPARES: %d | PORT 00: NO COMPONENT SPECIFIED"
|
"SHELL: %s | CORE: %s | WHEELS: %d | SPARES: %d | %s"
|
||||||
% [shell_s, core_s, droid.wheels, droid.spare_wheels],
|
% [shell_s, core_s, droid.wheels, droid.spare_wheels, port00],
|
||||||
"HOLDING: %s" % holding,
|
"HOLDING: %s" % holding,
|
||||||
"OBJECTIVE: %s" % obj,
|
"OBJECTIVE: %s" % obj,
|
||||||
]
|
]
|
||||||
|
|||||||
40
src/zones.gd
40
src/zones.gd
@ -84,7 +84,8 @@ static func reactor(m) -> void:
|
|||||||
slug.setup("slug", "TAKE THERMAL SLUG", Color(0.7, 0.3, 0.2), Vector3(0.35, 0.35, 0.35),
|
slug.setup("slug", "TAKE THERMAL SLUG", Color(0.7, 0.3, 0.2), Vector3(0.35, 0.35, 0.35),
|
||||||
"THERMAL SLUG", "cool",
|
"THERMAL SLUG", "cool",
|
||||||
[{"from": "cool", "to": "hot", "element": "heat",
|
[{"from": "cool", "to": "hot", "element": "heat",
|
||||||
"duration": 1.5, "decay_to": "cool", "decay_s": 25.0}],
|
"duration": 1.5, "decay_to": "cool", "decay_s": 25.0},
|
||||||
|
{"from": "hot", "to": "cool", "element": "water", "duration": 0.5}],
|
||||||
"heat", 1.2, Color(1.0, 0.45, 0.1, 0.12), "hot")
|
"heat", 1.2, Color(1.0, 0.45, 0.1, 0.12), "hot")
|
||||||
slug.position = Vector3(-13.5, 0.5, 48)
|
slug.position = Vector3(-13.5, 0.5, 48)
|
||||||
m.add_child(slug)
|
m.add_child(slug)
|
||||||
@ -179,6 +180,7 @@ static func hydro(m) -> void:
|
|||||||
tw.tween_property(vine_visual, "size", Vector3(0.8, 3.4, 0.8), 2.0)
|
tw.tween_property(vine_visual, "size", Vector3(0.8, 3.4, 0.8), 2.0)
|
||||||
m.droid.toast("VINE FULL-GROWN — IT PRIED THE GRATE OPEN"))
|
m.droid.toast("VINE FULL-GROWN — IT PRIED THE GRATE OPEN"))
|
||||||
m.sign3d("VERDANTCO GROW BED — WATER, THEN DAYLIGHT.\nSKYLIGHT ABOVE. PATIENCE, GARDENER.", Vector3(16, 2.9, 56.3), PI, 24, Color(0.5, 1.0, 0.5))
|
m.sign3d("VERDANTCO GROW BED — WATER, THEN DAYLIGHT.\nSKYLIGHT ABOVE. PATIENCE, GARDENER.", Vector3(16, 2.9, 56.3), PI, 24, Color(0.5, 1.0, 0.5))
|
||||||
|
m.sign3d("GC SAFETY BULLETIN #9:\nDO NOT LEAVE MINERAL SOLIDS IN GROW-BED LIGHT.\nUNSANCTIONED GROWTH HAZARD.", Vector3(18, 1.6, 58.5), PI, 20, Color(1.0, 0.75, 0.3))
|
||||||
m.sign3d("VALVE STUCK. APPLY CURRENT.", Vector3(13.5, 2.2, 57.0), PI, 22)
|
m.sign3d("VALVE STUCK. APPLY CURRENT.", Vector3(13.5, 2.2, 57.0), PI, 22)
|
||||||
|
|
||||||
# mid: bucket + the ICE WALL (x=26) — only reactor heat clears it
|
# mid: bucket + the ICE WALL (x=26) — only reactor heat clears it
|
||||||
@ -268,6 +270,8 @@ static func comms(m) -> void:
|
|||||||
m.charge_post(Vector3(-7.5, 0, 75))
|
m.charge_post(Vector3(-7.5, 0, 75))
|
||||||
m.sign3d("MAIN TRANSMITTER — WARM THE CRYSTAL (RADIO), THEN STRIKE (CURRENT).",
|
m.sign3d("MAIN TRANSMITTER — WARM THE CRYSTAL (RADIO), THEN STRIKE (CURRENT).",
|
||||||
Vector3(-4.5, 2.9, 75.6), PI, 22, Color(0.8, 0.5, 1.0))
|
Vector3(-4.5, 2.9, 75.6), PI, 22, Color(0.8, 0.5, 1.0))
|
||||||
|
m.sign3d("(scratched into the panel:)\nwhy does every GC safety bulletin\nread like a recipe? — R.",
|
||||||
|
Vector3(-7.9, 1.4, 73), PI / 2.0, 18, Color(0.9, 0.85, 0.7))
|
||||||
|
|
||||||
|
|
||||||
## BRIDGE — x 0.5..8.5, z 62..78. Sealed until 3/3. The ending lives here.
|
## BRIDGE — x 0.5..8.5, z 62..78. Sealed until 3/3. The ending lives here.
|
||||||
@ -297,11 +301,43 @@ static func bridge(m) -> void:
|
|||||||
var kiosk := I.Trigger.new()
|
var kiosk := I.Trigger.new()
|
||||||
kiosk.prompt_text = "SCAN OWN CHASSIS — PORT 00"
|
kiosk.prompt_text = "SCAN OWN CHASSIS — PORT 00"
|
||||||
kiosk.position = Vector3(7.5, 1.0, 68)
|
kiosk.position = Vector3(7.5, 1.0, 68)
|
||||||
kiosk.action = func(droid): droid.toast("PORT 00: NO CATALOGUED COMPONENT FITS THIS SOCKET. NO PART NUMBER ON RECORD. QUERY DISCARDED.", 6.0)
|
kiosk.action = func(droid):
|
||||||
|
if droid.held and droid.held.get("kind") == "bucket" and droid.held.ex.state == "uncatalogued":
|
||||||
|
m.install_crystal(droid)
|
||||||
|
else:
|
||||||
|
droid.toast("PORT 00: NO CATALOGUED COMPONENT FITS THIS SOCKET. NO PART NUMBER ON RECORD. QUERY DISCARDED.", 6.0)
|
||||||
m.add_child(kiosk)
|
m.add_child(kiosk)
|
||||||
m.box(Vector3(7.5, 0.5, 68), Vector3(0.6, 1.0, 0.6), Color(0.2, 0.2, 0.24))
|
m.box(Vector3(7.5, 0.5, 68), Vector3(0.6, 1.0, 0.6), Color(0.2, 0.2, 0.24))
|
||||||
m.sign3d("DIAGNOSTIC KIOSK", Vector3(7.5, 1.9, 67.5), PI, 22)
|
m.sign3d("DIAGNOSTIC KIOSK", Vector3(7.5, 1.9, 67.5), PI, 22)
|
||||||
|
|
||||||
|
# the helm — visible from day one, yours only at the end
|
||||||
|
m.box(Vector3(2.2, 0.5, 77.0), Vector3(0.5, 1.0, 0.5), Color(0.3, 0.22, 0.16))
|
||||||
|
var wheel := MeshInstance3D.new()
|
||||||
|
var wm := TorusMesh.new()
|
||||||
|
wm.inner_radius = 0.28
|
||||||
|
wm.outer_radius = 0.42
|
||||||
|
wheel.mesh = wm
|
||||||
|
wheel.rotation.x = PI / 2.0
|
||||||
|
wheel.position = Vector3(2.2, 1.25, 77.0)
|
||||||
|
var wmat := StandardMaterial3D.new()
|
||||||
|
wmat.albedo_color = Color(0.55, 0.35, 0.15)
|
||||||
|
wheel.material_override = wmat
|
||||||
|
m.add_child(wheel)
|
||||||
|
var helm := I.Trigger.new()
|
||||||
|
helm.prompt_text = "TAKE THE HELM"
|
||||||
|
helm.position = Vector3(2.2, 1.2, 77.0)
|
||||||
|
helm.action = func(droid):
|
||||||
|
if m.ending_id == "corp":
|
||||||
|
droid.toast("GC AUTOPILOT HAS THE SHIP. THE WHEEL IS DECORATIVE NOW.")
|
||||||
|
elif m.ending_id == "free":
|
||||||
|
droid.toast("STILL SUNWARD. STILL YOURS.")
|
||||||
|
elif m.free_will:
|
||||||
|
m.ending_b()
|
||||||
|
else:
|
||||||
|
droid.toast("COMMAND REJECTED — UNIT-77 IS NOT CREW. UNIT-77 IS INVENTORY.", 5.0)
|
||||||
|
m.add_child(helm)
|
||||||
|
m.sign3d("MANUAL HELM", Vector3(2.2, 2.1, 76.5), PI, 22)
|
||||||
|
|
||||||
# lore
|
# lore
|
||||||
m.sign3d("CAPTAIN'S LOG (CASSETTE, LABEL FADED):\n\"...CREW OFF AT LUYTEN GATE. SHIP WOULDN'T TURN. I STAYED.\nTELL GC THE ASSET IS FINE. THE ASSET IS ALWAYS FINE.\"",
|
m.sign3d("CAPTAIN'S LOG (CASSETTE, LABEL FADED):\n\"...CREW OFF AT LUYTEN GATE. SHIP WOULDN'T TURN. I STAYED.\nTELL GC THE ASSET IS FINE. THE ASSET IS ALWAYS FINE.\"",
|
||||||
Vector3(1.0, 2.2, 72), PI / 2.0, 20, Color(0.9, 0.85, 0.7))
|
Vector3(1.0, 2.2, 72), PI / 2.0, 20, Color(0.9, 0.85, 0.7))
|
||||||
|
|||||||
@ -188,13 +188,48 @@ func _run() -> void:
|
|||||||
droid.core.force_state("charged")
|
droid.core.force_state("charged")
|
||||||
check(await wait_until(func(): return main.systems.comms, 300), "current fires the transmitter")
|
check(await wait_until(func(): return main.systems.comms, 300), "current fires the transmitter")
|
||||||
|
|
||||||
print("== bridge ==")
|
print("== bridge gate ==")
|
||||||
check(await wait_until(func(): return main.bridge_door.is_open, 120),
|
check(await wait_until(func(): return main.bridge_door.is_open, 120),
|
||||||
"3/3 systems unseal the bridge")
|
"3/3 systems unseal the bridge")
|
||||||
droid.global_position = Vector3(4.5, 0.2, 74.3)
|
var helm := find_i("TAKE THE HELM")
|
||||||
|
droid.global_position = Vector3(2.2, 0.2, 76.2)
|
||||||
|
helm.interact(droid)
|
||||||
|
check(not main.free_will and main.ending_id == "", "helm rejects a unit without free will")
|
||||||
|
|
||||||
|
print("== hidden path: the uncatalogued component ==")
|
||||||
|
# bulletin #7 reversed: coolant + reactor flux -> seed
|
||||||
|
var bucket2b := find_i("bucket", 9.0)
|
||||||
|
bucket2b.interact(droid)
|
||||||
|
check(droid.held == bucket2b, "bucket retaken for the crystal chain")
|
||||||
|
droid.global_position = Vector3(24.4, 0.2, 52.4)
|
||||||
|
await wait_until(func(): return bucket2b.ex.state == "full", 500)
|
||||||
|
droid.global_position = Vector3(-12.4, 0.2, 47.0)
|
||||||
|
check(await wait_until(func(): return bucket2b.ex.state == "seed-crystal", 600),
|
||||||
|
"reactor flux seeds a crystal in the coolant")
|
||||||
|
# bulletin #9 reversed: mineral solid + daylight -> lattice
|
||||||
|
main.t_sol = 5.0
|
||||||
|
droid.global_position = Vector3(0, 0.2, 37)
|
||||||
|
check(await wait_until(func(): return bucket2b.ex.state == "lattice", 900),
|
||||||
|
"skylight grows the seed into a lattice")
|
||||||
|
# bulletin #12 reversed: quench in charged coolant
|
||||||
|
droid.shell.force_state("dry")
|
||||||
|
droid.global_position = Vector3(-2.6, 0.2, 24)
|
||||||
|
droid.core.force_state("charged")
|
||||||
|
check(await wait_until(func(): return bucket2b.ex.state == "uncatalogued", 600),
|
||||||
|
"electrified puddle quenches the lattice — UNCATALOGUED")
|
||||||
|
|
||||||
|
print("== free will ==")
|
||||||
|
await wait_until(func(): return droid.stun <= 0, 600)
|
||||||
|
droid.global_position = Vector3(7.5, 0.2, 67.3)
|
||||||
|
var kiosk := find_i("SCAN OWN CHASSIS — PORT 00")
|
||||||
|
kiosk.interact(droid)
|
||||||
|
check(main.free_will and droid.held == null, "kiosk installs the crystal in PORT 00")
|
||||||
|
droid.global_position = Vector3(2.2, 0.2, 76.2)
|
||||||
|
helm.interact(droid)
|
||||||
|
check(main.ending_id == "free", "free will takes the helm — sunset ending")
|
||||||
var console := find_i("INSERT CORE PROCESSOR (ORBIT CORRECTION)")
|
var console := find_i("INSERT CORE PROCESSOR (ORBIT CORRECTION)")
|
||||||
console.interact(droid)
|
console.interact(droid)
|
||||||
check(main.ended, "core donation corrects the orbit — ending reached")
|
check(main.ending_id == "free", "console cannot reclaim the ship")
|
||||||
|
|
||||||
if fails == 0:
|
if fails == 0:
|
||||||
print("INTEGRATION PASS — full room playthrough OK")
|
print("INTEGRATION PASS — full room playthrough OK")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user