190 lines
8.5 KiB
GDScript3
190 lines
8.5 KiB
GDScript3
|
|
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"
|
||
|
|
|
||
|
|
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.",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"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.",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "crafter",
|
||
|
|
"title": "A YARD OF OUR OWN",
|
||
|
|
"objective": "Build a ship crafter",
|
||
|
|
"goal": {"kind": GOAL_BUILDING, "building": "ship_crafter"},
|
||
|
|
"brief": "One hull will not chart a sky. Spend ore on the Shipyards doctrine, then put a ship crafter down: ore goes in, vessels come out.",
|
||
|
|
"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.",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"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.",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"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 {}
|