spaceship/core/Quests.gd

248 lines
12 KiB
GDScript3
Raw Normal View History

#129 (#131, #132, #133): a quest chain, and a World Ship out of reach Sixteen quests that walk a new game through the things it contains: ore, the mothership, exploration, a yard and a second hull, planetfall and conquest, extractors, gas, freight, power, the lab, a new vessel type, an outpost, and a survey. The chain turns on the second quest. The fleet builds the mothership to call the World Ship and hears nothing - and the array is not at fault. The breach put them further out than that signal will carry, so every quest after it is a search that has to be flown rather than transmitted. Three pieces: Quests.gd the chain, as data and nothing else. Two rules it obeys: nothing may ask for something unreachable - research points come only from conquering a planet, so every doctrine that costs them sits after the conquest quest - and a quest names one goal, with the research it implies said in the brief rather than split into an errand of its own. GameState how far along the chain the player is, and the answer to each goal kind. Progress latches for free: the chain is walked one quest at a time, so collecting five ore and spending it cannot un-complete the quest that asked for five - by then nothing is asking. It lives here so a quest finished on a planet surface is still finished after take-off. the HUD QuestTracker, the standing objective, in the wave alert's idiom; QuestDirector, which reads the lines out. Lines are QUEUED by GameState and drained by the director rather than emitted at a banner, because quests advance in the autoload, which runs on a planet surface too - where a line emitted straight at a banner would be lost. Both scenes now carry a banner, a tracker and a director, so a quest finished underground is announced underground. The chain is armed by reset_new_game(), the same gate the prologue uses - the only door into a real game - so instantiating a scene is not by itself a reason to start briefing somebody.
2026-08-28 14:41:03 +02:00
extends RefCounted
# Forgejo #129 / #133: the quest chain.
#
# One place, in order, and nothing but data. GameState answers each goal and
# QuestDirector reads each line out; neither of them knows what the quests
# ARE, so adding one here is the whole job of adding one.
#
# Two rules the chain obeys, both learned from the game rather than chosen:
#
# 1. Nothing here may ask for something the player cannot yet reach. The
# sharp edge is RESEARCH POINTS - they come only from conquering a
# planet (GameState.mark_point_captured), so every node with a
# research_points cost sits after `conquest` below. Ore-only nodes -
# Shipyards, Logistics - may come before it.
# 2. A quest names ONE goal, and the brief says what it will take. Asking
# for a gas burner is asking for the Power Systems research too; that
# belongs in the sentence, not in a second entry, or the chain turns
# into a list of errands.
#
# The whole story turns on `mothership`: the fleet builds a transmitter,
# calls the World Ship, and hears nothing - not because the array is weak
# but because the breach put them further out than anyone has been. Every
# quest after it is a search.
# There is nobody left to talk to, so the quests are the ship talking to
# itself - the same voice the prologue ends on (IntroDirector.SHIP_LOG).
const SPEAKER: String = "KESTREL - LOG"
# Goal kinds. Each is one line in GameState.quest_progress().
const GOAL_RESOURCE: String = "resource"
const GOAL_BUILDING: String = "building"
const GOAL_FLEET_VESSEL: String = "fleet_vessel"
const GOAL_VESSEL_UNLOCKED: String = "vessel_unlocked"
const GOAL_EXPLORE: String = "explore"
const GOAL_PLANET_VISITS: String = "planet_visits"
const GOAL_PLANET_KINDS: String = "planet_kinds"
const GOAL_CONQUERED: String = "conquered"
#141, #142: the chain teaches research, and asks for the pile before the build Two gaps between the first quests, both of the same kind: a step the chain assumed rather than asked for. #142 - "collect 5 ore" was followed straight by "build the mothership", which costs twenty. The first thing the chain ever asked for was four times what it had just taught, with nothing in between saying so. A stockpile quest sits between them now. #141 - the crafter quest's brief said "spend ore on the Shipyards doctrine, then put a ship crafter down", which is two unrelated things off one line: open a menu the player has never opened, and place a structure. Researching Shipyards is its own quest now, and it is the one that says where the research tree lives. Every later quest that needs a doctrine still only mentions it in passing - once is enough. That needed a goal kind for researching a doctrine, which the model did not have. Both are pinned as properties rather than as positions in a list. The chain must ask for at least as much ore as the first structure it wants costs; and the first structure that is gated behind a doctrine must have that doctrine as a quest of its own. Only the first - demanding one per building would double the chain for no teaching. One thing that fell out of writing those: the pile is exactly the starting fleet's hold. An interceptor carries 20 and the mothership costs 20, and before the mothership exists there is nowhere to bank anything, so the hold is the only store there is. It fits with no slack at all, so there is now an assertion saying so - a pile larger than the hold would be a quest that cannot be finished, and nothing else would have caught it.
2026-08-28 15:47:38 +02:00
# #141: researching a doctrine, as a step of its own. The chain used to fold
# it into the brief of the thing it unlocks ("spend ore on Shipyards, then
# put a crafter down"), which asks the player to do two unrelated things -
# open a menu they have never opened, and place a structure - off one line.
const GOAL_RESEARCH: String = "research"
# #156: what is in the BANK, which is a different question from what the
# player can lay hands on. GOAL_RESOURCE counts the hold as well, and the
# hold is exactly what this quest is about being too small.
const GOAL_BANKED: String = "banked"
Implement #160, #161, #162, #163, #164 and #165 #162 - a single tap bought a research node outright. One physical tap arrives TWICE: Godot emulates a mouse button from every touch AND a touch from every mouse button, both project settings are on, and the menu's dispatcher routes InputEventScreenTouch and InputEventMouseButton alike to the tree. The second arrival found the node already selected and took itself for the confirming tap. Measured, not reasoned about - one tap produced two picks and two confirms. What is ignored is specifically the TWIN: same frame, same place, arriving through the other input kind. Deduping on frame and position alone also swallowed two genuine taps in one frame, which the test caught. #164 - the build menu predicted a caption's height from the COLUMN WIDTH: wide column, assume one line. Right for most names and wrong for the long ones, so "Spacial Workshop" wrapped onto the price beneath it. Captions are now measured against the font that draws them, and prices sized from PriceTag.wanted_height(), which existed for exactly this and was not being asked. Prices are set before anything is measured, because the old order laid out first and priced afterwards. The ship lab: its buy button is gone and a second tap on an option buys it, the same rule as the research tree; the explanation drops into the room that freed; research points move up into the resource table, where everything else being spent already is; the second row of options is placed from the first row's measured bottom rather than a constant; and the vessel strip is spaced from the panel's own width, so the eighth vessel is no longer half off the right edge. #160 - the quest panel was drawn BEFORE the sticks and the pivot pair, so they sat on top of it. Moved after them, under the narration banner. Its title rule ran straight through the close button; the header band is now as tall as that button. #161 - the prologue widens the formation into a freight convoy by writing over GameState.formation, and nothing put it back. The player flew the convoy's 600-unit spread for the rest of the game - a shape nobody chose, which reads as the fleet having drifted apart. #163 - a quest to station a vessel at the outpost, after the one that asks for the outpost. Building one and crewing it are different acts, and an empty outpost holds nothing. #165 - the gas bomb's blast and a vessel arriving fast both damage a structure. The blast used to stop politely at anything the player owned, which made a bomb dropped on a besieged mothership a free way to sweep the attackers off it. Collisions are caught on ENTRY, not on the 0.7s strike tick: a vessel is only moving fast for the instant it arrives, and a ship sent in at 900 did no damage at all until this moved. Docking is free - the fleet sits on its own mothership constantly to bank ore - and garrison vessels are exempt outright, because they launch from their outpost and re-dock with it at speed. The suite caught that one: the ram rule was destroying the garrison as it launched. Suite 153/153. Four tests changed because what they pinned moved: the lab's buy button, the intro's formation, the research tree's tap delivery, and the build menu's own preview. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 02:27:44 +02:00
# #163: a vessel actually STATIONED at an outpost. Building one and crewing it
# are two different acts - the chain teaches the second, because an empty
# outpost holds nothing and the player has no reason to discover the hangar
# that fills it.
const GOAL_GARRISONED: String = "garrisoned"
#129 (#131, #132, #133): a quest chain, and a World Ship out of reach Sixteen quests that walk a new game through the things it contains: ore, the mothership, exploration, a yard and a second hull, planetfall and conquest, extractors, gas, freight, power, the lab, a new vessel type, an outpost, and a survey. The chain turns on the second quest. The fleet builds the mothership to call the World Ship and hears nothing - and the array is not at fault. The breach put them further out than that signal will carry, so every quest after it is a search that has to be flown rather than transmitted. Three pieces: Quests.gd the chain, as data and nothing else. Two rules it obeys: nothing may ask for something unreachable - research points come only from conquering a planet, so every doctrine that costs them sits after the conquest quest - and a quest names one goal, with the research it implies said in the brief rather than split into an errand of its own. GameState how far along the chain the player is, and the answer to each goal kind. Progress latches for free: the chain is walked one quest at a time, so collecting five ore and spending it cannot un-complete the quest that asked for five - by then nothing is asking. It lives here so a quest finished on a planet surface is still finished after take-off. the HUD QuestTracker, the standing objective, in the wave alert's idiom; QuestDirector, which reads the lines out. Lines are QUEUED by GameState and drained by the director rather than emitted at a banner, because quests advance in the autoload, which runs on a planet surface too - where a line emitted straight at a banner would be lost. Both scenes now carry a banner, a tracker and a director, so a quest finished underground is announced underground. The chain is armed by reset_new_game(), the same gate the prologue uses - the only door into a real game - so instantiating a scene is not by itself a reason to start briefing somebody.
2026-08-28 14:41:03 +02:00
const CHAIN: Array = [
{
"id": "first_ore",
"title": "SALVAGE",
"objective": "Break asteroids for 5 ore",
"goal": {"kind": GOAL_RESOURCE, "resource": "ore", "amount": 5},
"brief": "Hull intact. Reactor holding. Everything else we had is on the other side of that hole. There is ore in the rocks out here - break some, and we can start again.",
"done": "Five ore in the hold. It is not much. It is a beginning.",
},
#141, #142: the chain teaches research, and asks for the pile before the build Two gaps between the first quests, both of the same kind: a step the chain assumed rather than asked for. #142 - "collect 5 ore" was followed straight by "build the mothership", which costs twenty. The first thing the chain ever asked for was four times what it had just taught, with nothing in between saying so. A stockpile quest sits between them now. #141 - the crafter quest's brief said "spend ore on the Shipyards doctrine, then put a ship crafter down", which is two unrelated things off one line: open a menu the player has never opened, and place a structure. Researching Shipyards is its own quest now, and it is the one that says where the research tree lives. Every later quest that needs a doctrine still only mentions it in passing - once is enough. That needed a goal kind for researching a doctrine, which the model did not have. Both are pinned as properties rather than as positions in a list. The chain must ask for at least as much ore as the first structure it wants costs; and the first structure that is gated behind a doctrine must have that doctrine as a quest of its own. Only the first - demanding one per building would double the chain for no teaching. One thing that fell out of writing those: the pile is exactly the starting fleet's hold. An interceptor carries 20 and the mothership costs 20, and before the mothership exists there is nowhere to bank anything, so the hold is the only store there is. It fits with no slack at all, so there is now an assertion saying so - a pile larger than the hold would be a quest that cannot be finished, and nothing else would have caught it.
2026-08-28 15:47:38 +02:00
{
# #142: the gap this fills was a real one. "Collect 5 ore" was
# followed straight by "build the mothership", which costs twenty -
# so the first thing the chain ever asked for was four times what it
# had just taught, with nothing saying so.
"id": "stockpile",
"title": "THE PILE",
"objective": "Break asteroids for 20 ore",
"goal": {"kind": GOAL_RESOURCE, "resource": "ore", "amount": 20},
"brief": "Now do that four times over. Nothing permanent gets built out of five ore, and there is nothing else out here to spend it on yet.",
"done": "Twenty in the hold. That is a foundation.",
},
#129 (#131, #132, #133): a quest chain, and a World Ship out of reach Sixteen quests that walk a new game through the things it contains: ore, the mothership, exploration, a yard and a second hull, planetfall and conquest, extractors, gas, freight, power, the lab, a new vessel type, an outpost, and a survey. The chain turns on the second quest. The fleet builds the mothership to call the World Ship and hears nothing - and the array is not at fault. The breach put them further out than that signal will carry, so every quest after it is a search that has to be flown rather than transmitted. Three pieces: Quests.gd the chain, as data and nothing else. Two rules it obeys: nothing may ask for something unreachable - research points come only from conquering a planet, so every doctrine that costs them sits after the conquest quest - and a quest names one goal, with the research it implies said in the brief rather than split into an errand of its own. GameState how far along the chain the player is, and the answer to each goal kind. Progress latches for free: the chain is walked one quest at a time, so collecting five ore and spending it cannot un-complete the quest that asked for five - by then nothing is asking. It lives here so a quest finished on a planet surface is still finished after take-off. the HUD QuestTracker, the standing objective, in the wave alert's idiom; QuestDirector, which reads the lines out. Lines are QUEUED by GameState and drained by the director rather than emitted at a banner, because quests advance in the autoload, which runs on a planet surface too - where a line emitted straight at a banner would be lost. Both scenes now carry a banner, a tracker and a director, so a quest finished underground is announced underground. The chain is armed by reset_new_game(), the same gate the prologue uses - the only door into a real game - so instantiating a scene is not by itself a reason to start briefing somebody.
2026-08-28 14:41:03 +02:00
{
"id": "mothership",
"title": "A PLACE TO STAND",
"objective": "Build the mothership",
"goal": {"kind": GOAL_BUILDING, "building": "mothership"},
"brief": "A hull is not a base. Build the mothership - it is the only thing in the plans with a transmitter big enough to call the World Ship.",
# The hinge of the whole chain (#129): the answer to "we built the
# transmitter" is that the transmitter was never the problem.
"done": "Mothership online. Calling the World Ship. Calling. Nothing comes back - and the array is not at fault. Wherever the breach put us, it is further out than that signal will ever carry. We find their trail ourselves, or we do not find them.",
},
{
"id": "chart",
"title": "DEAD RECKONING",
"objective": "Chart 30 sectors",
"goal": {"kind": GOAL_EXPLORE, "sectors": 30},
"brief": "So we search. Fly, and let the map fill in behind us - whatever is left of their course is somewhere in it.",
"done": "Thirty sectors charted. No sign of the World Ship, but the sky behind us is no longer blank.",
},
#141, #142: the chain teaches research, and asks for the pile before the build Two gaps between the first quests, both of the same kind: a step the chain assumed rather than asked for. #142 - "collect 5 ore" was followed straight by "build the mothership", which costs twenty. The first thing the chain ever asked for was four times what it had just taught, with nothing in between saying so. A stockpile quest sits between them now. #141 - the crafter quest's brief said "spend ore on the Shipyards doctrine, then put a ship crafter down", which is two unrelated things off one line: open a menu the player has never opened, and place a structure. Researching Shipyards is its own quest now, and it is the one that says where the research tree lives. Every later quest that needs a doctrine still only mentions it in passing - once is enough. That needed a goal kind for researching a doctrine, which the model did not have. Both are pinned as properties rather than as positions in a list. The chain must ask for at least as much ore as the first structure it wants costs; and the first structure that is gated behind a doctrine must have that doctrine as a quest of its own. Only the first - demanding one per building would double the chain for no teaching. One thing that fell out of writing those: the pile is exactly the starting fleet's hold. An interceptor carries 20 and the mothership costs 20, and before the mothership exists there is nowhere to bank anything, so the hold is the only store there is. It fits with no slack at all, so there is now an assertion saying so - a pile larger than the hold would be a quest that cannot be finished, and nothing else would have caught it.
2026-08-28 15:47:38 +02:00
{
# #141: its own step, and the first time the chain sends anyone into
# the research tree at all - so the brief says where the tree IS.
# Every later quest that needs a doctrine only mentions it in
# passing, which is enough once the player has been there once.
"id": "shipyards",
"title": "SHIPYARDS",
"objective": "Research the Shipyards doctrine",
"goal": {"kind": GOAL_RESEARCH, "node": "shipyards"},
"brief": "One hull will not chart a sky, and we cannot build what we have not remembered how to build. The mothership holds the archive - go aboard it and research Shipyards.",
"done": "Shipyard plans recovered. Everything else worth having is in that archive too.",
},
#129 (#131, #132, #133): a quest chain, and a World Ship out of reach Sixteen quests that walk a new game through the things it contains: ore, the mothership, exploration, a yard and a second hull, planetfall and conquest, extractors, gas, freight, power, the lab, a new vessel type, an outpost, and a survey. The chain turns on the second quest. The fleet builds the mothership to call the World Ship and hears nothing - and the array is not at fault. The breach put them further out than that signal will carry, so every quest after it is a search that has to be flown rather than transmitted. Three pieces: Quests.gd the chain, as data and nothing else. Two rules it obeys: nothing may ask for something unreachable - research points come only from conquering a planet, so every doctrine that costs them sits after the conquest quest - and a quest names one goal, with the research it implies said in the brief rather than split into an errand of its own. GameState how far along the chain the player is, and the answer to each goal kind. Progress latches for free: the chain is walked one quest at a time, so collecting five ore and spending it cannot un-complete the quest that asked for five - by then nothing is asking. It lives here so a quest finished on a planet surface is still finished after take-off. the HUD QuestTracker, the standing objective, in the wave alert's idiom; QuestDirector, which reads the lines out. Lines are QUEUED by GameState and drained by the director rather than emitted at a banner, because quests advance in the autoload, which runs on a planet surface too - where a line emitted straight at a banner would be lost. Both scenes now carry a banner, a tracker and a director, so a quest finished underground is announced underground. The chain is armed by reset_new_game(), the same gate the prologue uses - the only door into a real game - so instantiating a scene is not by itself a reason to start briefing somebody.
2026-08-28 14:41:03 +02:00
{
"id": "crafter",
"title": "A YARD OF OUR OWN",
"objective": "Build a ship crafter",
"goal": {"kind": GOAL_BUILDING, "building": "ship_crafter"},
#141, #142: the chain teaches research, and asks for the pile before the build Two gaps between the first quests, both of the same kind: a step the chain assumed rather than asked for. #142 - "collect 5 ore" was followed straight by "build the mothership", which costs twenty. The first thing the chain ever asked for was four times what it had just taught, with nothing in between saying so. A stockpile quest sits between them now. #141 - the crafter quest's brief said "spend ore on the Shipyards doctrine, then put a ship crafter down", which is two unrelated things off one line: open a menu the player has never opened, and place a structure. Researching Shipyards is its own quest now, and it is the one that says where the research tree lives. Every later quest that needs a doctrine still only mentions it in passing - once is enough. That needed a goal kind for researching a doctrine, which the model did not have. Both are pinned as properties rather than as positions in a list. The chain must ask for at least as much ore as the first structure it wants costs; and the first structure that is gated behind a doctrine must have that doctrine as a quest of its own. Only the first - demanding one per building would double the chain for no teaching. One thing that fell out of writing those: the pile is exactly the starting fleet's hold. An interceptor carries 20 and the mothership costs 20, and before the mothership exists there is nowhere to bank anything, so the hold is the only store there is. It fits with no slack at all, so there is now an assertion saying so - a pile larger than the hold would be a quest that cannot be finished, and nothing else would have caught it.
2026-08-28 15:47:38 +02:00
"brief": "Now put a ship crafter down. Ore goes in, vessels come out - it is the only way this fleet grows past the one hull that came through the breach.",
#129 (#131, #132, #133): a quest chain, and a World Ship out of reach Sixteen quests that walk a new game through the things it contains: ore, the mothership, exploration, a yard and a second hull, planetfall and conquest, extractors, gas, freight, power, the lab, a new vessel type, an outpost, and a survey. The chain turns on the second quest. The fleet builds the mothership to call the World Ship and hears nothing - and the array is not at fault. The breach put them further out than that signal will carry, so every quest after it is a search that has to be flown rather than transmitted. Three pieces: Quests.gd the chain, as data and nothing else. Two rules it obeys: nothing may ask for something unreachable - research points come only from conquering a planet, so every doctrine that costs them sits after the conquest quest - and a quest names one goal, with the research it implies said in the brief rather than split into an errand of its own. GameState how far along the chain the player is, and the answer to each goal kind. Progress latches for free: the chain is walked one quest at a time, so collecting five ore and spending it cannot un-complete the quest that asked for five - by then nothing is asking. It lives here so a quest finished on a planet surface is still finished after take-off. the HUD QuestTracker, the standing objective, in the wave alert's idiom; QuestDirector, which reads the lines out. Lines are QUEUED by GameState and drained by the director rather than emitted at a banner, because quests advance in the autoload, which runs on a planet surface too - where a line emitted straight at a banner would be lost. Both scenes now carry a banner, a tracker and a director, so a quest finished underground is announced underground. The chain is armed by reset_new_game(), the same gate the prologue uses - the only door into a real game - so instantiating a scene is not by itself a reason to start briefing somebody.
2026-08-28 14:41:03 +02:00
"done": "The yard is live. We can build our own now.",
},
{
"id": "second_hull",
"title": "A SECOND HULL",
"objective": "Fly two vessels at once",
"goal": {"kind": GOAL_FLEET_VESSEL, "vessel": "interceptor", "count": 2},
"brief": "Order an interceptor at the yard and crew it. Two guns is not a fleet, but it is twice what we flew out of the breach with.",
"done": "Two hulls in formation. It has been a while since this ship flew with company.",
},
{
"id": "planetfall",
"title": "PLANETFALL",
"objective": "Land on a planet",
"goal": {"kind": GOAL_PLANET_VISITS, "count": 1},
"brief": "There are worlds out here. Bring the fleet in close to one and take it down - there is more on a surface than there is in all this dark.",
"done": "Down on solid ground. Whatever else this place is, it is somewhere.",
},
{
"id": "conquest",
"title": "GROUND HELD",
"objective": "Take every capture point on one planet",
"goal": {"kind": GOAL_CONQUERED, "count": 1},
"brief": "Something got to this surface before us and it is still holding it. Take every point on the planet - what we pull out of their positions is worth more than the ore is.",
# Says out loud where research points come from, because nothing
# else in the game does.
"done": "Planet secured. Their equipment reads out as research data - the first we have had. Every doctrine worth having is going to cost some.",
},
{
# #156: the extractor is the first thing the chain asks for that
# cannot be paid for out of a single hold. An interceptor carries 20
# and the fleet is small; the mothership is where anything larger
# than one trip has to accumulate, and nothing had ever said so.
"id": "deposit",
"title": "THE HOLD IS SMALL",
"objective": "Bank 60 ore at the mothership",
"goal": {"kind": GOAL_BANKED, "resource": "ore", "amount": 60},
"brief": "Every hull out here carries twenty and no more, and we are going to need more than twenty. Fly what we have back to the mothership and unload it - what is stored there is not carried by anyone.",
"done": "Sixty banked. The hold empties, the vault does not - that is the difference, and everything from here on depends on it.",
},
#129 (#131, #132, #133): a quest chain, and a World Ship out of reach Sixteen quests that walk a new game through the things it contains: ore, the mothership, exploration, a yard and a second hull, planetfall and conquest, extractors, gas, freight, power, the lab, a new vessel type, an outpost, and a survey. The chain turns on the second quest. The fleet builds the mothership to call the World Ship and hears nothing - and the array is not at fault. The breach put them further out than that signal will carry, so every quest after it is a search that has to be flown rather than transmitted. Three pieces: Quests.gd the chain, as data and nothing else. Two rules it obeys: nothing may ask for something unreachable - research points come only from conquering a planet, so every doctrine that costs them sits after the conquest quest - and a quest names one goal, with the research it implies said in the brief rather than split into an errand of its own. GameState how far along the chain the player is, and the answer to each goal kind. Progress latches for free: the chain is walked one quest at a time, so collecting five ore and spending it cannot un-complete the quest that asked for five - by then nothing is asking. It lives here so a quest finished on a planet surface is still finished after take-off. the HUD QuestTracker, the standing objective, in the wave alert's idiom; QuestDirector, which reads the lines out. Lines are QUEUED by GameState and drained by the director rather than emitted at a banner, because quests advance in the autoload, which runs on a planet surface too - where a line emitted straight at a banner would be lost. Both scenes now carry a banner, a tracker and a director, so a quest finished underground is announced underground. The chain is armed by reset_new_game(), the same gate the prologue uses - the only door into a real game - so instantiating a scene is not by itself a reason to start briefing somebody.
2026-08-28 14:41:03 +02:00
{
"id": "extractor",
"title": "STANDING MINE",
"objective": "Build an extractor on a planet",
"goal": {"kind": GOAL_BUILDING, "building": "extractor"},
"brief": "Research Logistics and put an extractor down on a surface. It keeps digging whether we are standing over it or not.",
"done": "The extractor is cutting. Ore will be there when we come back for it.",
},
{
"id": "gas",
"title": "THE HEAVY AIR",
"objective": "Bring back 25 gas",
"goal": {"kind": GOAL_RESOURCE, "resource": "gas", "amount": 25},
"brief": "The banded worlds are full of gas, and gas is the only thing out here that burns. Take the fleet into one and fill the tanks.",
"done": "Twenty-five units of gas aboard. Now we need something that can burn it.",
},
{
"id": "hub",
"title": "FREIGHT",
"objective": "Build a transport hub",
"goal": {"kind": GOAL_BUILDING, "building": "transport_hub"},
"brief": "Carrying every load by hand does not scale. Research Freight Handling and build a hub - its transporters run the routes without us.",
"done": "The hub is running its own traffic. That is our hands back.",
},
{
"id": "burner",
"title": "POWER",
"objective": "Build a gas burner",
"goal": {"kind": GOAL_BUILDING, "building": "gas_burner"},
"brief": "Research Power Systems and build a gas burner. Gas in, energy out - and energy is what the better weapons run on.",
"done": "The burner is lit. There is power on this fleet for the first time since the breach.",
},
{
"id": "lab",
"title": "SHIP SCIENCE",
"objective": "Build a ship lab",
"goal": {"kind": GOAL_BUILDING, "building": "ship_lab"},
"brief": "Research Vessel Science and build a ship lab. Every hull we fly can be made better there, and there are hulls in the archive we have never built.",
"done": "The lab is open.",
},
{
"id": "shield",
"title": "A NEW HULL",
"objective": "Unlock the shield vessel",
"goal": {"kind": GOAL_VESSEL_UNLOCKED, "vessel": "shield"},
"brief": "The archive has a shield hull in it. Unlock it at the lab - the fleet has been taking every hit on the paint so far.",
"done": "Shield hull unlocked. There is more than one design in that archive.",
},
{
"id": "outpost",
"title": "FORWARD BASES",
"objective": "Build an outpost",
"goal": {"kind": GOAL_BUILDING, "building": "outpost"},
"brief": "We cannot be everywhere. Research Forward Bases and build an outpost - vessels stationed there hold ground we are not standing on.",
"done": "The outpost is crewed. That is one place we no longer have to fly back to.",
},
Implement #160, #161, #162, #163, #164 and #165 #162 - a single tap bought a research node outright. One physical tap arrives TWICE: Godot emulates a mouse button from every touch AND a touch from every mouse button, both project settings are on, and the menu's dispatcher routes InputEventScreenTouch and InputEventMouseButton alike to the tree. The second arrival found the node already selected and took itself for the confirming tap. Measured, not reasoned about - one tap produced two picks and two confirms. What is ignored is specifically the TWIN: same frame, same place, arriving through the other input kind. Deduping on frame and position alone also swallowed two genuine taps in one frame, which the test caught. #164 - the build menu predicted a caption's height from the COLUMN WIDTH: wide column, assume one line. Right for most names and wrong for the long ones, so "Spacial Workshop" wrapped onto the price beneath it. Captions are now measured against the font that draws them, and prices sized from PriceTag.wanted_height(), which existed for exactly this and was not being asked. Prices are set before anything is measured, because the old order laid out first and priced afterwards. The ship lab: its buy button is gone and a second tap on an option buys it, the same rule as the research tree; the explanation drops into the room that freed; research points move up into the resource table, where everything else being spent already is; the second row of options is placed from the first row's measured bottom rather than a constant; and the vessel strip is spaced from the panel's own width, so the eighth vessel is no longer half off the right edge. #160 - the quest panel was drawn BEFORE the sticks and the pivot pair, so they sat on top of it. Moved after them, under the narration banner. Its title rule ran straight through the close button; the header band is now as tall as that button. #161 - the prologue widens the formation into a freight convoy by writing over GameState.formation, and nothing put it back. The player flew the convoy's 600-unit spread for the rest of the game - a shape nobody chose, which reads as the fleet having drifted apart. #163 - a quest to station a vessel at the outpost, after the one that asks for the outpost. Building one and crewing it are different acts, and an empty outpost holds nothing. #165 - the gas bomb's blast and a vessel arriving fast both damage a structure. The blast used to stop politely at anything the player owned, which made a bomb dropped on a besieged mothership a free way to sweep the attackers off it. Collisions are caught on ENTRY, not on the 0.7s strike tick: a vessel is only moving fast for the instant it arrives, and a ship sent in at 900 did no damage at all until this moved. Docking is free - the fleet sits on its own mothership constantly to bank ore - and garrison vessels are exempt outright, because they launch from their outpost and re-dock with it at speed. The suite caught that one: the ram rule was destroying the garrison as it launched. Suite 153/153. Four tests changed because what they pinned moved: the lab's buy button, the intro's formation, the research tree's tap delivery, and the build menu's own preview. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 02:27:44 +02:00
{
"id": "garrison",
"title": "STANDING WATCH",
"objective": "Station a vessel at the outpost",
"goal": {"kind": GOAL_GARRISONED, "count": 1},
"brief": "An empty outpost is a building. Open its hangar and station a vessel there - it holds that ground whether we are there or not.",
"done": "The outpost has a crew. It watches that approach now, and we do not have to.",
},
#129 (#131, #132, #133): a quest chain, and a World Ship out of reach Sixteen quests that walk a new game through the things it contains: ore, the mothership, exploration, a yard and a second hull, planetfall and conquest, extractors, gas, freight, power, the lab, a new vessel type, an outpost, and a survey. The chain turns on the second quest. The fleet builds the mothership to call the World Ship and hears nothing - and the array is not at fault. The breach put them further out than that signal will carry, so every quest after it is a search that has to be flown rather than transmitted. Three pieces: Quests.gd the chain, as data and nothing else. Two rules it obeys: nothing may ask for something unreachable - research points come only from conquering a planet, so every doctrine that costs them sits after the conquest quest - and a quest names one goal, with the research it implies said in the brief rather than split into an errand of its own. GameState how far along the chain the player is, and the answer to each goal kind. Progress latches for free: the chain is walked one quest at a time, so collecting five ore and spending it cannot un-complete the quest that asked for five - by then nothing is asking. It lives here so a quest finished on a planet surface is still finished after take-off. the HUD QuestTracker, the standing objective, in the wave alert's idiom; QuestDirector, which reads the lines out. Lines are QUEUED by GameState and drained by the director rather than emitted at a banner, because quests advance in the autoload, which runs on a planet surface too - where a line emitted straight at a banner would be lost. Both scenes now carry a banner, a tracker and a director, so a quest finished underground is announced underground. The chain is armed by reset_new_game(), the same gate the prologue uses - the only door into a real game - so instantiating a scene is not by itself a reason to start briefing somebody.
2026-08-28 14:41:03 +02:00
{
"id": "worlds",
"title": "THE SURVEY",
"objective": "Land on three different kinds of world",
"goal": {"kind": GOAL_PLANET_KINDS, "count": 3},
"brief": "Rock, gas, and whatever else is out here. Set down on three different kinds of world - if the World Ship passed this way, it passed something.",
"done": "Three kinds of world surveyed. Every one of them empty of anything that came through with us.",
},
{
"id": "trail",
"title": "THE TRAIL",
"objective": "Chart 150 sectors",
"goal": {"kind": GOAL_EXPLORE, "sectors": 150},
"brief": "Then we widen it. A hundred and fifty sectors, and every one of them looked at properly. They are out there.",
"done": "A hundred and fifty sectors charted, and no trail. The search does not stop because the list ran out.",
},
]
static func count() -> int:
return CHAIN.size()
static func at(index: int) -> Dictionary:
if index < 0 or index >= CHAIN.size():
return {}
return CHAIN[index]
static func by_id(id: String) -> Dictionary:
for quest in CHAIN:
if String(quest.id) == id:
return quest
return {}