orbit/data/sidequests.json

611 lines
44 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"_comment": "SIDE QUESTS — the contracts posted on the JOB BOARD (the Explore drawer's Job Board slot — every system EXCEPT the home system, data/actionbar.json → surface.explore.items). The board is a VIEW over js/quests/SideQuests.js: `sideQuestPostingsFor(seed, record)` derives 3–4 deterministic postings from the galaxy seed + the system record (same seed + system ⇒ same contracts, across visits, scene restarts, and saves), and the run's accepted/completed set rides the saves as the SideQuestState ledger (registry 'sidequests', record.sidequests). CATEGORIES — the four job types (→ categories): patrol / delivery / bounty / escort. Every category is ACCOUNTED FOR (its slot machinery, its description pool below, its reward band, the window's row + contract readout, the ledger, the accept seam) behind its OWN `enabled` gate. PATROL is the first live type (enabled:true — its rules: → patrol below, js/quests/SideQuests.js → buildPatrolRoute + patrolTargetSystem, the scene's updatePatrol); the other three stay OFFLINE until their objective/completion rule sets land. The gate is the contract: a category's jobs appear on the board ONLY when its rules land and its flag flips (flip enabled:true in this file — the board's standby plate lifts and its postings stand). FLAVOR — the variant pools split by SYSTEM CONTEXT (→ descriptions): NEUTRAL systems post about keeping their system safe from PIRATES; a FACTION's systems post about pushing the OTHER factions out of their space (the pools carry {faction}/{issuer}/{enemies} placeholders — {enemies} resolves to the other two factions' labels; {issuer} to the faction's board name below; {system} to the system's name — resolved at generation, js/quests/SideQuests.js → resolveSideQuestText). Each pool holds 3+ variants so different systems read different contracts.",
"enabled": true,
"board": {
"_comment": "perSystem = the postings-per-system roll [min,max] (seeded per system — Rng.derive(seed, seedLabel, <sysId>); the roll itself is stable for the run). seedLabel = the Rng fork label under the galaxy seed (the worldgen determinism contract: a labelled fork, independent of call order).",
"perSystem": [
3,
4
],
"seedLabel": "sidequests"
},
"categories": {
"_comment": "The four job types. ORDER = the canonical slot order (patrol, delivery, bounty, escort). `enabled` is the per-type availability gate — OFFLINE until that type's objective + completion logic is built (patrol and BOUNTY HUNT are live — their rules under → patrol / → bounty; delivery and escort are stubs); flip a category to true and its jobs stand on the board with their pool + reward band already wired. `accent` = the row's category chip + the contract title (data colors, js/quests/SideQuests.js reads them through). A category may carry TWO MORE GATES beyond `enabled`: `minLevel` (the combat level the board demands — under it the posting still stands, but as a greyed LOCKED row whose accept is refused) and `contexts` (the boards that post it at all — ['neutral'] keeps a pirate-voice contract off the faction boards entirely; an omitted list means every context posts it).",
"patrol": {
"enabled": true,
"label": "PATROL",
"accent": "#00e5ff"
},
"delivery": {
"enabled": false,
"label": "DELIVERY",
"accent": "#ffc94d"
},
"bounty": {
"enabled": true,
"label": "BOUNTY HUNT",
"accent": "#ff2d6f",
"minLevel": 2,
"contexts": [
"neutral"
]
},
"escort": {
"enabled": false,
"label": "ESCORT",
"accent": "#7ce8a4"
}
},
"rewards": {
"_comment": "The per-category CREDITS band [min,max] at the home rim — the base payout; it scales OUT with the system's home→far diagonal d (record.d) as (1 + d * distanceScale) — the economy's 'a hop is a hop, and danger pays' rule (the far systems' boards pay more for the same risk). The band is rolled seeded per posting (round to 5 CR, floor 5 CR). The XP payout rides beside the credits: it is NOT a band — it is the contract's combat's WORTH, fixed on the route record at the accept (route.xp — js/quests/SideQuests.js → patrolEncounterXp: the patrol's defeated contacts × the wave's total × the band's roster xp, data/combat.json → enemy.xp / enemyTypes), and the claim (GameScene.claimSideQuest) grants it into the run's XP bank (js/combat/XpManager.js — the 'sidequest' source, beside the kills' 'kill' grants) in addition to paying the credits. A category without a route pays credits-only (its XP payout is 0 — the old saves' shape). Tune per category as the types' rules land; a category with no band here falls back to [40,80] in code.",
"distanceScale": 0.75,
"patrol": [
40,
70
],
"delivery": [
50,
90
],
"bounty": [
80,
140
],
"escort": [
70,
110
]
},
"factions": {
"_comment": "The faction boards' ISSUER names (the {issuer} placeholder in the faction pools — data/factions.json's faction ids: apex / mindweave / zenith).",
"apex": "Apex War Ministry",
"mindweave": "MindWeave Chorus",
"zenith": "Zenith Concord"
},
"patrol": {
"_comment": "The PATROL category's rules (the first live type — js/quests/SideQuests.js → buildPatrolRoute + patrolTargetSystem; the scene's updatePatrol/check-ins read visitRadius). ACCEPT builds the patrol's ROUTE in the posting's target system: waypoints [min,max] of plain coordinates, inside the system's UNLOCKED tether regions (the live tether field's union, the player's range there) when the target is the system the player stands in, and inside ONE tether region (a level-1 radius, tether.level1Radius) of any of the target's planets / space stations / jump gates when it is a system the player hasn't unlocked yet (a NEIGHBOR — below). Placement keeps the points ISOLATED: anchorClearance px clear of every anchor (planet/station/gate center) and minSeparation px apart, retrying seeded, relaxing the clearance and separation (never the region) if the field is tight. visitRadius = the ship is this far from a waypoint when it counts as REACHED (checked off, in any order). neighborMinD = the '40% mark diagonally from home' (the system record's d — the home→far diagonal, 0 at the home corner): in a FACTION system at d ≥ neighborMinD, a patrol may instead be assigned to a NEIGHBORING system (a jump-gate link) controlled by ANOTHER faction — the push-them-out voice made a route; neighborChance is the per-posting seeded odds of the neighbor draw (the posting's target stands stable for the run). compass + marker = the in-game face of the active patrol: the yellow next-waypoint arrow on the off-screen compass (js/ui/DiscoveryCompass's color override — the route gate's orange precedent) and the in-world waypoint beacons (unvisited = pulsing, visited = the dimmed done mark).",
"waypoints": [
3,
5
],
"visitRadius": 420,
"anchorClearance": 1100,
"minSeparation": 1500,
"regionInset": 96,
"neighborMinD": 0.4,
"neighborChance": 0.5,
"encounters": {
"_comment": "The patrol's ENEMY ENCOUNTERS — the contract's hostile CONTACTS standing on route waypoints (the data contract: data/sidequests.json → patrol.encounters; the logic: js/quests/SideQuests.js → derivePatrolEncounters + patrolEncounterScript; the firing: the scene's updatePatrol → _firePatrolContact — the wave starts when the ship checks in at a CONTACT's waypoint, and the cleared mark lands on the wave run's COMPLETION — the witness is the completion, not the attempt: a mid-fight quit re-arms the contact on return, the combatDone precedent — and the route's completion, with the reward's door, waits for every contact). COUNTS — the odds of how many CONTACTS a patrol carries (1 contact on 20% of patrols, 2 on 20%, 3 on 60%): [count, odds] pairs, drawn SEED-STABLE at the accept from the labelled fork (seed, 'sidequests', <targetSystemId>, 'patrol', <jobId>, 'encounters') and fixed on the route record — a signed contract is a signed contract: a later re-tune of the odds can't re-roll a standing contract's combat. WAVE — each contact's fight: ONE rolling wave of the band's roster (equal weights — a single-type band is a pure type + total), the data's shape — six hostiles, three at a time, each kill replaced — the combat.waves rolling mechanic (js/combat/Waves.js); the script is built by patrolEncounterScript (no named entry in data/combat.json — the roster comes from the band below). BANDS — the difficulty's first axis (the player's COMBAT level × the target system's HOPS from home — the jump network's tree depth, galaxy.jumpNetwork.depth — the 'systems 1–2 hops out' rule): the FIRST band in list order whose levels AND hops windows both contain the player stands, and its enemyTypes are the hostiles its contacts fly (validated against combat.enemyTypes — js/combat/EnemyTypes.js — an unknown id never ships). No band stands, or a roster empties, → fallbackEnemyTypes. TODAY the low band — levels 1–5 at 1–2 hops from home — flies the ESTABLISHED type only (raider — the base craft's named id, the 'Pirate Problems' wave's own type); the farther/higher bands — with the enemy types they introduce — append to this list when those types land, and the other difficulty axes (the distance's own scaling, the level's bonus) wire onto this same seam. POSITIONING — the contacts stand on route waypoints SPREAD evenly across the route (patrolEncounterPositions): for ≥ 2 contacts, the most evenly spread subset of the route's waypoints (scored by its MINIMUM pairwise separation — maximin — then its total: on a near-linear route that's the ends and the middle; a 3–5-point route's contacts never cluster); a single contact stands on the waypoint nearest the route's centroid (the patrol's middle). Deterministic — a pure function of the seed, the contract, and the route's geometry. XP REWARD — beside the credits, the claim pays the XP these defeated contacts are WORTH (js/quests/SideQuests.js → patrolEncounterXp: the contacts × the wave's total × the roster's type xp, data/combat.json → enemy.xp / enemyTypes): fixed on the route record at the accept (route.xp, beside route.credits — a signed contract is a signed contract) and granted into the run's XP bank on the claim (XpManager's 'sidequest' source — the kills' 'kill' grants' sibling).",
"enabled": true,
"counts": [
[1, 0.2],
[2, 0.2],
[3, 0.6]
],
"wave": {
"kind": "rolling",
"total": 6,
"maxConcurrent": 3,
"replacePerKill": 1
},
"bands": [
{
"levels": [
1,
5
],
"hops": [
1,
2
],
"enemyTypes": [
"raider"
]
}
],
"fallbackEnemyTypes": [
"raider"
]
},
"compass": {
"color": "#ffd60a",
"typeLabel": "Patrol"
},
"marker": {
"color": "#ffd60a",
"doneColor": "#67e863",
"contactColor": "#ff5c77"
}
},
"bounty": {
"_comment": "The BOUNTY HUNT category's rules (the second live type — the model: js/quests/SideQuests.js → deriveBountyPlan / bountyEngagements / bountyHuntXp / bountyRouteComplete / nextBountyWaypoint; the scene: GameScene._establishBountyHunt + updateBountyHunt). A hunt is a PATROL WITH A NAME ON IT: three waypoints along one pirate leader's recent travel lanes, flown STRICTLY IN ORDER (the chain's odds need a first, second and third leg — patrol's any-order check-ins do not apply here), with the ending hidden from the player: the mark stands on ONE of the legs and the fight around them IS the contract. minLevel = the combat level the board demands before the contract can be taken (js/combat/XpManager.js's level; under it the row is LOCKED and GameScene.acceptSideQuest refuses it). contexts = the boards that post it — ['neutral'], because the 20 dossiers below are the neutral pirate-hunt voice and the faction pool is a documented empty stub (→ descriptions.faction.bounty). waypoints = the leg count [min,max]: the design is exactly three, and the chain's guarantee reads the LENGTH (the LAST leg always holds the mark), so raising the max lengthens the hunt without touching code. Route placement reuses patrol's anchorClearance / minSeparation / regionInset unless this block overrides them; visitRadius = how close the ship must come for a leg to LOG.",
"minLevel": 2,
"contexts": [
"neutral"
],
"waypoints": [
3,
3
],
"visitRadius": 420,
"encounters": {
"_comment": "The hunt's CHAIN — rolled ONCE at the accept on the labelled fork (seed,'sidequests',<targetSystemId>,'bounty',<jobId>,'chain') and FIXED on the route record: a signed contract is a signed contract, so re-tuning these odds never re-rolls a standing hunt (and the plan is invisible until it fires — no UI, marker, compass entry or toast names the leg that holds anything). LEGS — every leg but the last rolls bountyChance for the mark; the LAST leg stands it at 100%. With bountyChance 0.2 and three legs that reads 20% on leg 1, 20% of what missed on leg 2 (16% overall), everything left on leg 3 (64%). A leg that does NOT hold the mark rolls skirmishChance for a pirate wave of its own — the leader's pickets working their own lane; the bounty leg never rolls pickets (the mark IS the fight), and once the mark is down no later leg owes anything. SKIRMISH — one rolling wave of the frame-0 established type, three at a time, each kill replaced: the patrol contact's shape with no elite in it. BOUNTY — one rolling wave of `total` NINE, three at a time: `raiders` frame-0 fighters plus ONE elite, the mark itself, flying the craft its own dossier names (→ descriptions.neutral.bounty[].craft, an id from data/combat.json → enemyTypes), buffed by healthScale × hull+shields and damageScale × its weapon's damage, deployed WITH the opening group (never buried at the back of the queue) and tagged `elite` so a kill that MATTERED is recognizable. An elite id that isn't in combat.enemyTypes (a data typo) falls back to a seeded pick from eliteFrames. TERMINATION — killing the mark halts every further deployment and replacement of that fight (js/combat/CombatSystem.js → haltWaves: the survivors already on the field stay hostile and must be put down); when the last of them drops the hunt is COMPLETE, every leg checks off at once, no further wave fires, and the reward stands ready to claim.",
"enabled": true,
"bountyChance": 0.2,
"skirmishChance": 0.5,
"skirmishWave": {
"kind": "rolling",
"total": 6,
"maxConcurrent": 3,
"replacePerKill": 1,
"roster": [
"raider"
]
},
"bountyWave": {
"kind": "rolling",
"total": 9,
"raiders": 8,
"maxConcurrent": 3,
"replacePerKill": 1,
"raiderType": "raider",
"eliteFrames": [
"bomber",
"spitter",
"stinger",
"hunter",
"gunner",
"barrage",
"warden"
],
"elite": {
"healthScale": 2,
"damageScale": 2
}
},
"bands": [
{
"id": "hunter",
"levels": [
2,
5
],
"_comment": "THE LIVE BAND — the level 2–5 bounty hunt this pass tunes: three legs, the chain's odds above, frame-0 pickets and a dossier-named mark at double armor and double damage. No wave overrides here (the band inherits the encounter block above); a band MAY carry its own skirmishWave / bountyWave / bountyChance / skirmishChance to retune a level window without touching the others."
},
{
"id": "marksman",
"levels": [
6,
10
],
"inherits": "hunter",
"stub": true,
"_comment": "STUB — the level 6+ bounty hunt, not yet tuned. `inherits` points it at the hunter band so a player who outruns level 5 keeps getting hunts (a hunt never vanishes mid-run), and `stub` marks the debt: replace the inheritance with real numbers — heavier pickets, more legs, tougher marks, a fatter band under → rewards.bounty — when levels 6+ get their pass."
}
],
"fallbackBand": "hunter"
},
"compass": {
"color": "#ff2d6f",
"typeLabel": "Hunt"
},
"marker": {
"color": "#ff2d6f",
"doneColor": "#67e863",
"_comment": "NO contact color, deliberately: a patrol paints its contact waypoints red (→ patrol.marker.contactColor) because those contacts are the job; a hunt's legs must look IDENTICAL until something shoots at you, so only the NEXT leg in sequence lights and nothing marks where the mark is."
}
},
"descriptions": {
"_comment": "The variant pools: context (neutral | faction) × category. The generator picks ONE variant per posting, seeded on (galaxy seed, system id, category, slot) — a system's contract is STABLE (the board doesn't reshuffle between visits or saves), and different systems draw different ones (3+ variants per pool keeps the galaxy's boards from reading as one repeated ad). Placeholders (resolved at generation, never stored): {system} = the system's name; in the faction pools {faction} = the system's faction label (data/factions.json), {issuer} = that faction's board name (→ factions above), {enemies} = the OTHER two factions ('MindWeave and Zenith'). The NEUTRAL pools are the pirate-safety voice; the FACTION pools are the push-the-other-factions-out voice. THE BOUNTY POOLS ARE DIFFERENT — descriptions.neutral.bounty is the BOUNTY HUNT's WANTED LIST: 20 dossiers, each a named pirate leader with an epithet, a crime, and the craft it flies (`craft` = a data/combat.json → enemyTypes id, spread across all seven frames, so the copy and the fight agree; `craftLabel` is the readout's plain words for it). descriptions.faction.bounty is deliberately EMPTY — a documented stub: categories.bounty.contexts is ['neutral'], so a faction board never draws a hunt, and the pool stays empty until a faction author posts its own wanted list (the generator would otherwise fall back to the neutral list and post pirate-hunt copy on a faction board).",
"neutral": {
"patrol": [
{
"title": "Lane Watch",
"issuer": "The Harbormaster",
"body": "Three raiders keep running the outer gate at night, and the toll keepers are done pretending they aren't there. Work the lane, keep your lights up, and make the run a bad idea. We don't want their bodies, we want them gone — the board pays for the silence, and the board pays on time."
},
{
"title": "Quiet the Field",
"issuer": "The Warden Guild",
"body": "The {system} belt is a graveyard with a population. Something in the debris has been firing at passing hulls, and the Guild is paying for a field where the wrecks are the only thing that shoots. Work the rocks until they're quiet — and mind your hull out here, the field is as honest as the rest of this system."
},
{
"title": "The Lighthouse Run",
"issuer": "The Station Keeper",
"body": "The buoy out past the ice line keeps going dark, and it isn't breaking — someone is cutting its fuel line. Find out who and convince them to stop, in whatever order you like. That light runs every safe lane in the system, and the pirates out here only like it for one reason: it's on. Keep it on."
}
],
"delivery": [
{
"title": "Dead Freight",
"issuer": "The Tally",
"body": "A sealed crate for the keeper at the edge of the system. It isn't marked, and that isn't an accident. The raiders who want it are already circling the lane, and they're better funded than they look. Get it there before they get to you — or get it there through them. The Tally pays either way the crate arrives."
},
{
"title": "The Long Way Home",
"issuer": "The Harbormaster",
"body": "Supply drops for the outer watch posts. The direct lane has been a pirate kill-box for a week, so you take the long way, fly slow, and keep your engines quiet. Nobody asks what's in the crates, and nobody asks what the watch posts are for either. That's the whole job — the cargo moves, the posts stay lit."
},
{
"title": "Fuel for the Wards",
"issuer": "The Warden Guild",
"body": "Two drums of fuel for the sentinel posts, and the posts need them before the moon turns. A raider skiff was seen nosing around the fuel depot an hour ago — assume it was a scout and move the fuel like it was. The Guild's accounts are open and the Guild's patience isn't. Get the drums there and the wardens keep the lanes honest."
}
],
"bounty": [
{
"title": "The Ninth Bell",
"issuer": "The Fuel Wardens",
"name": "Ilse Vanturi",
"epithet": "Ninth Bell",
"crime": "Taxing the halcyon run at cannon point",
"craft": "bomber",
"craftLabel": "salvade heavy bomber, one long lance",
"body": "Ilse Vanturi rang the chapel bell nine times for every ship she let through, and when the chapel burned she kept the bell. Now the fuel tanker crews count nine chimes on the emergency band before a single heavy bolt walks the length of their hull — that lance reaches further than our wardens' radios, and she knows it. Six tankers have paid her toll and two of them are still burning. The Wardens pay for the pirate who invented the bell to stop ringing. Bring her down and we'll ring it once more for you."
},
{
"title": "Nine Winters",
"issuer": "The Salvage Court",
"name": "Ostvik Halvardson",
"epithet": "Nine Winters",
"crime": "Shelling the Kite Line harvest",
"craft": "bomber",
"craftLabel": "icebreak-turned gun platform, slow and patient",
"body": "Nine winters Ostvik Halvardson has sat his patched icebreaker off the Kite Line, patient as weather, dropping one enormous bolt into whatever the haulers thought was cover. The Court has written off nine salvage claims and eleven bodies. He is not a pirate with a conscience — he is an icebreaker with a grudge. He will not maneuver with you. He will not outrun you. He will sit exactly where he is and make you come into a lance that has been aiming at the same spot since the last moon. End the count at nine."
},
{
"title": "Protection Money",
"issuer": "The Pilots' Guild",
"name": "Berta Ondaine",
"epithet": "The Slow Smile",
"crime": "Selling insurance nobody agreed to buy",
"craft": "bomber",
"craftLabel": "bulk-bodied bomber with a fuse like a eulogy",
"body": "Berta Ondaine delivers her quotes in person: a fat hull on your wing, a smile on the open channel, and a bolt already cook-off on the long lance if you decline. Three Guild pilots took the quote anyway and are now part of the belt. The Guild has paid off raiders before; it refuses to start with her. We want the collection stopped, and we want it stopped in the order she prefers — nobody quoting our members ever again."
},
{
"title": "Two Of A Kind",
"issuer": "The Ledger House",
"name": "Sable & Rue Spidleau",
"epithet": "the sisters who finish each other's sentences",
"crime": "Strafing the passenger ferry lane for sport",
"craft": "spitter",
"craftLabel": "twin-seat skiff, a fan of bolts per sentence",
"body": "One steers, one shoots, and neither stops talking. The Spidleau sisters cross the ferry lane screaming and open up with a fan of cheap bolts wide enough that dodging is a rumour — they've never hit anything worth hitting, which the Ledger House considers a moral emergency rather than luck. Two ferry hulls are patched so full of bolt-holes they fly in daylight. Take the pirate sisters off the lane before arithmetic does it for us."
},
{
"title": "The Firefight",
"issuer": "The Station Keeper",
"name": "Cassia Drumm",
"epithet": "Firehose",
"crime": "Putting out a depot fire by spraying the depot",
"craft": "spitter",
"craftLabel": "pump-rigged skiff throwing a wide cone",
"body": "Cassia Drumm was the best fire response on this station until she answered her own alarm with her ship's pump and a bad idea. Now she works the lane for the same instinct: get close, open a cone across everything you see, call it done. The keeper who let her keep the rig is the keeper who owes us a barge, and every hauler on the lane now pays a raider's rate in delay. Put the fire out for good."
},
{
"title": "Fan Favourite",
"issuer": "The Tally",
"name": "Havelock Vane",
"epithet": "Nine-Finger",
"crime": "Point-blank shakedown at the ore moorings",
"craft": "spitter",
"craftLabel": "ore-hauler refit, spray bars welded on",
"body": "Havelock Vane lost four fingers to his own spray rig and wears the rest as a threat — he'll show you the hand on the channel while the fan warms up. He shakes the ore moorings for whatever the crews have on them and paints the bulkheads when they don't. The Tally counts his takings in scraped hull plate and has decided that the count of this pirate is finished."
},
{
"title": "Three For The Road",
"issuer": "The Relay Masters",
"name": "Aruna Sekh",
"epithet": "Needle",
"crime": "Sprint-killing light freight above the relay field",
"craft": "stinger",
"craftLabel": "courier-racer hull, a tight three-shot burst",
"body": "Aruna Sekh used to fly mail for us and knew every relay gate in this system by sound. Now she comes off the relay field at racing speed, puts three bolts into your engine block in about a heartbeat, and is gone before your gunner has picked a side of the ship. The Masters pay for the pilot who taught them this lane to stop teaching it."
},
{
"title": "The Dark Side Visit",
"issuer": "The Warden Guild",
"name": "Ketch Marlowe",
"epithet": "Get-Dark",
"crime": "Ambush from moon-shadow with no running lights",
"craft": "stinger",
"craftLabel": "stripped scout, burst cannon and no transponder",
"body": "Ketch Marlowe flies dark on the shadow side of this system's moons and reads your approach like a menu — the burst lands while you're still calling out on an honest channel. Two wardens have gone chasing the dark and come back with fewer hulls than they left with. The Guild wants the dark side of these moons to be empty again, and it wants Marlowe to be the reason."
},
{
"title": "The Long Sting",
"issuer": "The Harbormaster",
"name": "Vessa Nkemdi",
"epithet": "Stingtail",
"crime": "Running the toll on the ice road",
"craft": "stinger",
"craftLabel": "fast picket with a burst tail-gun",
"body": "Vessa Nkemdi works the ice road alone and calls it a toll booth; harbor law says pirate, she says independent traffic warden. She hangs off your stern where your cameras are worst, stings three bolts into your drive every time you slow for the ice, and invoices the wrecks she makes. The harbor has paid her invoice twice. It would prefer to pay you instead."
},
{
"title": "He Never Loses A Scent",
"issuer": "The Remand Office",
"name": "Aurelian Costa",
"epithet": "The Bloodhound",
"crime": "Killing bond-jumpers who owed him nothing",
"craft": "hunter",
"craftLabel": "hunting craft with a heat-seeker on a long leash",
"body": "Aurelian Costa was a bounty hunter before he was a pirate and never saw the difference. His missile finds whatever is running, and it does not get bored — out-turn it if you can, but he has watched a lot of people try. He has been collecting people the Remand Office owed nobody. Bring him in and the Office stops apologising for what its own paperwork caused."
},
{
"title": "Last Confession",
"issuer": "The Longshore Chapel",
"name": "Marilou Dax",
"epithet": "The Confessor",
"crime": "Absolving nine crews from the inside of their own ships",
"craft": "hunter",
"craftLabel": "chapel-hulled hunter, one missile per blessing",
"body": "Sister Marilou opens a channel, asks for the truth of your voyage, hears it all the way down, and then launches a seeker she calls absolution. Nine crews have been absolved. The Chapel that unfrocked her is paying from its own box, which tells you how seriously it takes the habit. Make her finish her own penance."
},
{
"title": "Toll Hound",
"issuer": "The Tally",
"name": "Baz Ferreira",
"epithet": "Foxhound",
"crime": "Hunting smugglers who skipped his toll",
"craft": "hunter",
"craftLabel": "tracker with a missile and infinite patience",
"body": "Baz Ferreira charges smugglers for the privilege of being robbed by him, and his seeker is how he audits. The trouble is he has begun auditing honest traffic too, on the theory that anyone flying this lane owes somebody. The Tally finds the reasoning unsound and pays for a correction."
},
{
"title": "Collect In Full",
"issuer": "The Ledger House",
"name": "Sefane Adu",
"epithet": "Two Ledgers",
"crime": "Debt collection with a machine gun",
"craft": "gunner",
"craftLabel": "fast interceptor, rapid cannon, no patience for instalments",
"body": "Sefane Adu keeps two ledgers: one for what you owe, one for what the interest costs. When the second one opens she walks a stream of bolts down your spine until something gives, and she has never once lost a balance. The Ledger House disowned her paperwork and would like the collection agency retired."
},
{
"title": "Dead Air",
"issuer": "The Relay Masters",
"name": "Moira Bellamy",
"epithet": "Static",
"crime": "Jamming distress, then finishing the job",
"craft": "gunner",
"craftLabel": "jam-topped interceptor, rapid bolts on a short cooldown",
"body": "Moira Bellamy kills your radio before she kills anything else — static first, then a machine gun while you're still trying to raise somebody. Two wrecks in this system died calling into dead air. The Masters built the relay network and are paying for the one voice on it that ought to be silenced forever."
},
{
"title": "The Mill",
"issuer": "The Warden Guild",
"name": "Isaac Vowell",
"epithet": "The Miller",
"crime": "Grinding convoys down until something breaks",
"craft": "gunner",
"craftLabel": "long-burn interceptor that never lifts off the trigger",
"body": "Isaac Vowell does not ambush, taunt, or bargain. He gets on your wing and pours bolts at you for as long as either ship lasts, which he has calculated will always be him. Three convoy escorts have run out of shields before he ran out of ammunition. The Guild would like his arithmetic tested by somebody with better armor."
},
{
"title": "Do Not Approach",
"issuer": "The Salvage Court",
"name": "Gwendolane Fisk",
"epithet": "Hedge",
"crime": "Ring-fire at a salvage crew that came alongside",
"craft": "barrage",
"craftLabel": "armored barge that answers boarding with a full ring",
"body": "Gwendolane Fisk welded armor to an already slow hull and solved the problem of close-quarters combat by firing outward in every direction at once. A salvage crew went alongside to cut her loose and did not come back. The Court would like a ruling that nothing may be approached at point-blank, and this is the only way it gets one."
},
{
"title": "The Halo",
"issuer": "The Longshore Chapel",
"name": "Kaleo Tui",
"epithet": "Sunburst",
"crime": "Claiming a pilgrimage lane and everything on it",
"craft": "barrage",
"craftLabel": "armored pilgrim craft that blooms into a ring of bolts",
"body": "Brother Kaleo declared the pilgrimage lane his own diocese, and every ship that uses it pays tithe or eats a halo of bolts fired in every direction at once. He broadcasts hymns while he does it, which the Chapel says is not what hymns are for. Take his little kingdom apart and take the sound off the air."
},
{
"title": "The Widow's Claim",
"issuer": "The Pilots' Guild",
"name": "Dorra Vance",
"epithet": "Anvil",
"crime": "Claiming the belt on behalf of a dead husband",
"craft": "barrage",
"craftLabel": "heavy barge, ring gun, unbothered by return fire",
"body": "Dorra Vance says the belt belonged to her husband and that his death transferred the deed to anyone stubborn enough to collect it. She collects in bolts — a full ring each time, since she stopped bothering to aim at anything so small as a ship. The Guild has never once seen a title this thick, and would like it voided with extreme prejudice."
},
{
"title": "The Meridian Line",
"issuer": "The Warden Guild",
"name": "Kazimir Vohl",
"epithet": "Black Meridian",
"crime": "The Sable Convoy massacre",
"craft": "warden",
"craftLabel": "warden-class heavy — a lance and a seeker on every volley",
"body": "Admiral Vohl, self-appointed, commanded the escort that let the Sable Convoy burn and then wrote the report blaming the convoy. He flies like a man with a warship's patience: a heavy lance to hold you in place and a seeker to follow wherever you dodge. The Guild has buried four of its own who went after him. This contract is written by people who are done burying anybody else."
},
{
"title": "Grey Judgement",
"issuer": "The Harbormaster",
"name": "Sera Alkantari",
"epithet": "Grey Judgement",
"crime": "Executing three launch marshals on the pad",
"craft": "warden",
"craftLabel": "judicial warden, lance and missile fired like a sentence",
"body": "Sera Alkantari holds court in open space: she reads the charge, gives you one channel to answer, and then fires a heavy lance and a seeker whether your defence was good or not. Three launch marshals were executed for calling her hull unsafe. The harbor she served is paying for the last word on this one to be somebody else's."
}
],
"escort": [
{
"title": "See Her Home",
"issuer": "The Station Keeper",
"body": "A refugger out of the outer belt is asking for a pilot who can outrun pirates, and the lane is theirs right now. She's carrying people, not cargo, and the keeper is paying in gratitude first and credits after. Fly her through to the gate, keep her hull in one piece, and stay on her wing long enough that she forgets to be afraid. That's the job."
},
{
"title": "Convoy Night",
"issuer": "The Tally",
"body": "Three lighters move out of the debris line tonight, and every pirate in the system knows it — they've heard it the way you hear a storm. Fly the point, hold the line, and put them through the far gate. The Tally pays for hulls that arrive, and the Tally counts them at the gate. Count them yourself too."
},
{
"title": "The Long Dark",
"issuer": "The Warden Guild",
"body": "A courier ship has a sealed manifest and a hard deadline, and the lane she has to cross is pirate country. Escort her to the system edge and stay on her wing until the gate swallows her. Whatever she's carrying, it's worth more than your ship — that's probably why the Guild wants you, not their own pilots."
}
]
},
"faction": {
"patrol": [
{
"title": "Sweep the Lanes",
"body": "A foreign surveyor has been working the outer gate for a week, and it doesn't belong here. {enemies} think this system is a neutral route — it isn't. Sweep the lane until there's nothing left on it but our own flag. Report the wrecks to the {issuer} and leave the survivors to them. That's the whole job."
},
{
"title": "No Foreign Lights",
"body": "We've logged foreign transponders on the approach lanes since the last moon. {enemies} are running their people through our space like it's a corridor they paid for. It isn't, and it won't stay that way. Show them the difference, one hull at a time, until the lanes run clean under {faction} lights again."
},
{
"title": "The Gate Watch",
"body": "The gate is the only honest road in this system, and foreign traffic keeps trying to use it. Keep the approach lanes free of {enemies} flags — the {issuer} is paying for the lesson, and it would rather never have to teach it. If you meet them out there, remember which side of the line you're on."
}
],
"delivery": [
{
"title": "Flagged Cargo",
"body": "Parts for the gate works, under full {faction} flag. {enemies} runners will smell it and come for it, because that's what they do. Fly the direct lane, keep the flag on the hull, and don't let it off your wing. The works don't wait for delays, the {issuer} doesn't wait for excuses, and neither does the flag."
},
{
"title": "The Wrong Kind of Freight",
"body": "The crate is sealed and the manifest is sealed, and that's the whole job. {enemies} have two scouts in the system and they're bad at this — that's the good news. Deliver the crate to the depot before the scouts find out what it is. After that the crate belongs to them, and the job belongs to you. The {issuer} is paying for the order of operations."
},
{
"title": "Supply Run, War Terms",
"body": "The outer posts run on our rations and your nerve. {enemies} want the lane to starve them out, and they've said so in the intercepts. Run the lane anyway. Put the posts in the dark they wanted or in the light we pay for — the {issuer} is paying for the light, and only the light."
}
],
"bounty": [],
"escort": [
{
"title": "Convoy Under Flag",
"body": "A convoy moves through the system under {faction} colors, and {enemies} scouts have been seen in the approach lanes. Fly the point, hold the line, and keep the colors in the lead. The {issuer} pays for the convoy that arrives — not for the story of the one that didn't. The story is for the dead, and we can afford the convoy."
},
{
"title": "The Minister's Courier",
"body": "The courier carries a seal, not cargo, and the lane is foreign country tonight. {enemies} will know the moment it launches, because they've been watching our docks since the last moon. Stay on the wing, keep the seal aboard, and put the courier through. What's in the case is the difference between a system and a battlefield — deliver it and keep the system a system."
},
{
"title": "Long Haul, Short Fuse",
"body": "Three lighters, one lane, and {enemies} scouts already circling the fuel line. Escort them to the gate and keep the line intact — no drops, no detours, no negotiations. The {issuer} counts hulls at the gate and pays per hull that arrives. Count them yourself too, and keep the extra for your nerve."
}
]
}
},
"ui": {
"_comment": "The board's contract copy (js/ui/JobBoardWindow.js). standby* = the state where NO category is live (the current one — the board's face until the first type flips on). accept* = the ACCEPT action's button + the scene's toasts (SurfaceScene.acceptSurfaceJob — the claimSurfaceQuest precedent: the ledger + sfx are the GameScene's, the note is the surface's).",
"standbyMain": "NO CONTRACTS ON FILE",
"standbySub": "THE BOARD’S POSTINGS LAND HERE",
"selectMain": "SELECT A JOB",
"selectSub": "PICK A LISTING TO READ ITS CONTRACT",
"statusStandby": "BOARD STANDBY — NO CONTRACTS ON FILE",
"statusLive": "{n} CONTRACTS ON FILE",
"rewardUnit": "CR",
"payout": "PAYOUT — {reward} CR",
"payoutXp": "PAYOUT — {reward} CR · +{xp} XP",
"accept": "ACCEPT CONTRACT",
"accepted": "CONTRACT ACCEPTED",
"active": "PATROL ACTIVE",
"activate": "SET PATROL ACTIVE",
"bountyActive": "HUNT ACTIVE",
"bountyActivate": "SET HUNT ACTIVE",
"complete": "CONTRACT COMPLETE",
"claim": "CLAIM REWARD — {reward} CR",
"claimXp": "CLAIM REWARD — {reward} CR · +{xp} XP",
"claimed": "REWARD CLAIMED",
"destination": "DESTINATION — {name}",
"routeProgress": "ROUTE — {visited}/{total} WAYPOINTS LOGGED",
"contactProgress": "CONTACTS — {cleared}/{total} CLEARED",
"patrolContactToast": {
"glyph": "⚔",
"color": "#ff5c77",
"text": "HOSTILE CONTACT — {n} ENEMIES INBOUND"
},
"patrolContactClearedToast": {
"glyph": "✓",
"color": "#67e863",
"text": "CONTACT CLEARED — {i} OF {n}"
},
"acceptToast": {
"glyph": "◆",
"color": "#ffc94d",
"text": "CONTRACT ACCEPTED — {title}"
},
"acceptDenyToast": {
"glyph": "✗",
"color": "#ff5c77",
"text": "COMMISSION DENIED — CONTRACT NOT ON FILE"
},
"activateToast": {
"glyph": "▸",
"color": "#ffd60a",
"text": "PATROL ACTIVE — {title}"
},
"claimToast": {
"glyph": "✓",
"color": "#67e863",
"text": "REWARD CLAIMED — +{reward} CR",
"textXp": "REWARD CLAIMED — +{reward} CR · +{xp} XP"
},
"claimDenyToast": {
"glyph": "✗",
"color": "#ff5c77",
"text": "NOTHING TO CLAIM — ROUTE NOT COMPLETE"
},
"patrolWaypointToast": {
"glyph": "◈",
"color": "#ffd60a",
"text": "WAYPOINT {i} OF {n} LOGGED"
},
"patrolCompleteToast": {
"glyph": "✓",
"color": "#67e863",
"text": "PATROL ROUTE COMPLETE — ITS REWARD IS READY TO CLAIM"
},
"_commentBounty": "The BOUNTY HUNT's face (js/ui/JobBoardWindow.js + GameScene.updateBountyHunt). NOTE THE SILENCE: nothing here names the leg that holds the mark or a picket wave — the chain is hidden until it fires, so these lines only ever speak of what the player has already flown into. bountyLockBadge = the greyed row's plate (and the detail's lock line) under categories.bounty.minLevel; bountyAcceptDenyToast = the scene's refusal when a locked contract is pressed anyway.",
"bountyLockBadge": "LOCKED — REQUIRES LEVEL {level}",
"bountyLockSub": "BRING YOUR RECORD UP TO LEVEL {level} AND THE BOARD WILL LIST YOU",
"bountyAcceptDenyToast": {
"glyph": "✗",
"color": "#ff5c77",
"text": "COMMISSION REFUSED — BOUNTY HUNTS STAND AT LEVEL {level}"
},
"dossierWanted": "WANTED — {name}",
"dossierEpithet": "{epithet}",
"dossierCrime": "CHARGES — {crime}",
"dossierCraft": "CRAFT — {craft}",
"bountyRouteProgress": "TRAVEL LANE — WAYPOINT {visited} OF {total} LOGGED",
"bountyLegToast": {
"glyph": "◈",
"color": "#ff2d6f",
"text": "WAYPOINT {i} OF {n} LOGGED — NOTHING ON THE LANE"
},
"bountySkirmishToast": {
"glyph": "⚔",
"color": "#ff5c77",
"text": "PIRATE PICKETS — {n} HOSTILES INBOUND"
},
"bountySightedToast": {
"glyph": "☠",
"color": "#ff2d6f",
"text": "THE MARK IS HERE — {name}, {epithet} · {n} HOSTILES INBOUND"
},
"bountyBroughtToBookToast": {
"glyph": "✓",
"color": "#67e863",
"text": "{name} BROUGHT TO BOOK — PUT DOWN THE LAST OF THE ESCORT"
},
"bountyCompleteToast": {
"glyph": "✓",
"color": "#67e863",
"text": "BOUNTY HUNT COMPLETE — {name} IS DOWN, ITS REWARD IS READY TO CLAIM"
}
}
}