Find the planet setups in an exported build

The registry scanned res://PlanetSetups for names ending ".tres". An export
does not ship those: text resources are converted to binary and the pack
carries "<name>.tres.remap", which ResourceLoader follows when asked for the
original path. So the scan found nothing in the web build, every planet drew
no setup, and since #211 the setup IS the garrison - every world in the
deployed game was deserted, with nothing logged to say why. Confirmed by
reading index.pck, which holds rocky_default.tres.remap and no .tres.

The suite runs from source, where the bug cannot occur, so the name
resolution is its own function and tested against the exact strings the pack
contains.

Also: the planning centre listed transporters and repair drones but
set_vessel_target() still refused anything not fleet-eligible, so both rows
had buttons that did nothing - the worst shape a refusal can take. Listing
and setting read the same rule now, and a standing order is only offered to
a crafter that can actually take it.

And two quests close the chain: the tentacle world, which the scanner will
not offer until the story hands it over, and the Warden itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
This commit is contained in:
Loïc Wisniewski 2026-09-07 13:55:41 +02:00
commit df4d5e35f9
6 changed files with 179 additions and 8 deletions

View file

@ -61,6 +61,10 @@ const GOAL_STATION_CREW: String = "station_crew"
# expensive way. This goal is "there are resources sitting in the thing",
# which is the step to teach before the berth is ever crewed.
const GOAL_BUILDING_STOCK: String = "building_stock"
# One NAMED world, rather than "four different kinds". The tentacle world is
# a place the story sends the player to, so the chain has to be able to say
# "go there" and know when they have.
const GOAL_WORLD_VISITED: String = "world_visited"
# #167: which quests carry the STORY, marked `"important": true` below.
#
@ -368,7 +372,28 @@ const CHAIN: Array = [
"objective": "Chart 150 sectors",
"goal": {"kind": GOAL_EXPLORE, "sectors": 150},
"brief": "Then we search wider. A hundred and fifty sectors, and every one of them looked at properly. They are out there somewhere.",
"done": "A hundred and fifty sectors charted, and still no trail. The search does not stop just because the list ran out.",
"done": "A hundred and fifty sectors charted, and still no trail - but the scanner has been carrying a signature it could not place, and now there is enough of the map behind us to place it.",
"important": true,
},
{
# The scanner will not offer this world until this quest is live: it
# is a destination the story hands over, not something to stumble
# into while looking for ore. See GameState.scanner_can_find_boss().
"id": "tentacles",
"title": "THE SIGNATURE",
"objective": "Land on the tentacle world",
"goal": {"kind": GOAL_WORLD_VISITED, "definition": "boss"},
"brief": "One signature on the scanner matches nothing we have charted, and everything near it is dead. Scan for it and go down there. Whatever is holding that world is what has been out here with us the whole time.",
"done": "We are on the surface, and it is awake. It has been waiting a long time for someone to come down.",
"important": true,
},
{
"id": "warden",
"title": "THE WARDEN",
"objective": "Destroy the Warden",
"goal": {"kind": GOAL_CONQUERED, "definition": "boss", "count": 1},
"brief": "It is between us and everything past this place. Bring what the fleet has - the beam reaches furthest, the bomb hits hardest - and take its world off it.",
"done": "The Warden is dead and its world is ours. Whatever it was keeping out there, nothing is keeping it any more.",
"important": true,
},
]
@ -378,6 +403,16 @@ static func count() -> int:
return CHAIN.size()
# Where a quest sits in the chain, or -1 for an id that is not in it. Used to
# gate world state on the story having reached a point (#: the tentacle world
# is hidden from the scanner until the chain sends the player after it).
static func index_of(quest_id: String) -> int:
for i in range(CHAIN.size()):
if String(CHAIN[i].id) == quest_id:
return i
return -1
static func at(index: int) -> Dictionary:
if index < 0 or index >= CHAIN.size():
return {}