A player briefing, and the historical range

The generator was already writing the timeline, the cast and the texture and
filing all of it behind the GM screen. New PLAYERS page: a read-aloud opening,
what it is like there, what is known so far, who is there and what they want —
but never what they lie about. Page ownership is now declared by the page rather
than guessed from its index, which would have hidden any second player page.

Historical range: 38 weapons (from 6) and 14 armours (from 2), each with its
period stated, from arming swords and longbows through matchlocks and Brown Bess
to the Lee-Enfield and a trench club. Five new skills to hang them on, including
Firearm (Muzzle-loader), because a muzzle-loader is not a rifle.

275 icons; every weapon maps to a real skill and every item has art. Catalogue is
206 items across four eras.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
slaguru666
2026-08-10 23:02:20 +01:00
co-authored by Claude Opus 5
parent 22a5067153
commit e2d0ed5bb2
90 changed files with 685 additions and 83 deletions
+73 -2
View File
@@ -27,6 +27,10 @@ export const SKILL_CATALOGUE = [
// The boarding axe and the entrenching tool both declare spec "axe" and the
// catalogue had no such skill, so neither could ever be rated above zero.
["melee_weapon", "axe", "melee", 5, "Melee Weapon (Axe)"],
// The historical range needs somewhere to hang a halberd and a flail. Everything
// else fits an existing specialisation: a mace is a club, a dirk is a knife.
["melee_weapon", "polearm", "melee", 5, "Melee Weapon (Polearm)"],
["melee_weapon", "flail", "melee", 5, "Melee Weapon (Flail)"],
["variable_sword", "", "melee", 5, "Variable Sword"],
// ranged
["firearm", "pistol", "ranged", 5, "Firearm (Pistol)"],
@@ -35,6 +39,10 @@ export const SKILL_CATALOGUE = [
["energy_weapon", "rifle", "ranged", 5, "Energy Weapon (Rifle)"],
["flashlight_laser", "", "ranged", 5, "Flashlight Laser"],
["missile_weapon", "bow", "ranged", 5, "Missile Weapon (Bow)"],
["missile_weapon", "sling", "ranged", 5, "Missile Weapon (Sling)"],
["missile_weapon", "thrown", "ranged", 15, "Missile Weapon (Thrown)"],
// A muzzle-loader is not a rifle. Loading is the skill and it is a different one.
["firearm", "muzzleloader", "ranged", 5, "Firearm (Muzzle-loader)"],
["heavy_weapon", "", "ranged", 5, "Heavy Weapon"],
// communication
["bargain", "", "comm", 5, "Bargain"],
@@ -120,7 +128,55 @@ export const WEAPONS = [
/* ---------- FUTURE. Recovered from somewhere ahead. ---------- */
{ key: "gauss_pistol",name: "Gauss sidearm", cls: "energy", fam: "energy_weapon", spec: "pistol", dmg: "1d8+4", wound: "piercing", mod: false, ranges: [15,45,120], fire: "single", cap: 24, mass: 0.9, era: "future", trad: "tradition_transposed", energy: 4, desc: "No propellant and no report — a tap, and a hole. Ammunition is not manufacturable here." },
{ key: "gauss_rifle", name: "Gauss lance-rifle", cls: "energy", fam: "energy_weapon", spec: "rifle", dmg: "1d12+4", wound: "piercing", mod: false, ranges: [40,120,300], fire: "single", cap: 12, mass: 3.8, era: "future", trad: "tradition_transposed", energy: 8, desc: "Punches an entry wound and an exit wound and very little between them." },
{ key: "monoblade", name: "Monofilament blade",cls: "melee", fam: "melee_weapon", spec: "knife", dmg: "1d10+2", wound: "edged", mod: false, mono: true, ranges: [0,0,0], fire: "", cap: 0, mass: 0.4, era: "future", trad: "tradition_transposed", desc: "Cuts armour as though it were not there. Handle with the sheath on." }
{ key: "monoblade", name: "Monofilament blade",cls: "melee", fam: "melee_weapon", spec: "knife", dmg: "1d10+2", wound: "edged", mod: false, mono: true, ranges: [0,0,0], fire: "", cap: 0, mass: 0.4, era: "future", trad: "tradition_transposed", desc: "Cuts armour as though it were not there. Handle with the sheath on." },
/* ==================================================================
THE HISTORICAL RANGE
The department has been running since before it had a name, and it
has never thrown anything away. Everything below is either still in
a store somewhere in the building, or came back through a crossing
with somebody. The period note is not decoration — a GM handing out
a matchlock should know it is a matchlock.
================================================================== */
/* --- medieval --- */
{ key: "arming_sword", name: "Arming sword", cls: "melee", fam: "melee_weapon", spec: "sword", dmg: "1d8+1", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.2, era: "antique", trad: "tradition_local", desc: "Medieval. A yard of cross-hilted steel. The plain, correct answer to most of the fifteenth century." },
{ key: "longsword", name: "Longsword", cls: "melee", fam: "melee_weapon", spec: "sword", dmg: "1d10+1", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.6, era: "antique", trad: "tradition_local", desc: "Medieval. Hand and a half. Wants room and rewards someone who has been taught." },
{ key: "falchion", name: "Falchion", cls: "melee", fam: "melee_weapon", spec: "sword", dmg: "1d8+2", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.5, era: "antique", trad: "tradition_local", desc: "Medieval. Heavy at the tip and unsubtle. A cleaver that got above itself." },
{ key: "war_hammer", name: "War hammer", cls: "melee", fam: "melee_weapon", spec: "club", dmg: "1d8+2", wound: "blunt", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.7, era: "antique", trad: "tradition_local", desc: "Medieval. For plate, which it does not cut so much as dent inwards." },
{ key: "mace", name: "Mace", cls: "melee", fam: "melee_weapon", spec: "club", dmg: "1d8+1", wound: "blunt", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.4, era: "antique", trad: "tradition_local", desc: "Medieval. Flanged. Requires no skill worth the name and never breaks." },
{ key: "flail", name: "Military flail", cls: "melee", fam: "melee_weapon", spec: "flail", dmg: "1d10", wound: "blunt", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 2.0, era: "antique", trad: "tradition_local", desc: "Medieval. Goes round a shield and is nearly as dangerous behind you as in front." },
{ key: "poleaxe", name: "Poleaxe", cls: "melee", fam: "melee_weapon", spec: "polearm", dmg: "1d10+2", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 3.0, era: "antique", trad: "tradition_local", desc: "Medieval. Axe, hammer and spike on six feet of ash. The best answer to armour anyone found before gunpowder." },
{ key: "halberd", name: "Halberd", cls: "melee", fam: "melee_weapon", spec: "polearm", dmg: "1d10+2", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 3.2, era: "antique", trad: "tradition_local", desc: "Medieval. Cut, thrust or pull a rider off a horse. Useless indoors and the department keeps eleven." },
{ key: "billhook", name: "Billhook", cls: "melee", fam: "melee_weapon", spec: "polearm", dmg: "1d8+2", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 2.6, era: "antique", trad: "tradition_local", desc: "Medieval. A hedging tool with ambitions. Every parish had a rack of them." },
{ key: "pike", name: "Pike", cls: "melee", fam: "melee_weapon", spec: "spear", dmg: "1d10+1", wound: "piercing", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 4.5, era: "antique", trad: "tradition_local", desc: "Medieval to Civil War. Sixteen feet. Magnificent in a field, absurd in a corridor." },
{ key: "quarterstaff", name: "Quarterstaff", cls: "melee", fam: "melee_weapon", spec: "club", dmg: "1d8", wound: "blunt", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.8, era: "antique", trad: "tradition_local", desc: "Medieval. Six foot of ash. Legal to carry, which is most of the point." },
{ key: "dirk", name: "Dirk", cls: "melee", fam: "melee_weapon", spec: "knife", dmg: "1d4+2", wound: "piercing", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 0.4, era: "antique", trad: "tradition_local", desc: "Medieval onward. Long in the blade for a knife and worn where a knife is not expected." },
{ key: "longbow", name: "Longbow", cls: "bow", fam: "missile_weapon", spec: "bow", dmg: "1d10+1", wound: "piercing", mod: false, ranges: [30,90,180], fire: "fast", cap: 1, mass: 1.0, era: "antique", trad: "tradition_local", desc: "Medieval. Yew, and a draw weight that deforms the man who uses it. Faster than any firearm here." },
{ key: "arbalest", name: "Arbalest", cls: "bow", fam: "missile_weapon", spec: "bow", dmg: "1d12", wound: "piercing", mod: false, ranges: [25,60,130], fire: "slow", cap: 1, mass: 5.0, era: "antique", trad: "tradition_local", desc: "Medieval. Steel prod, windlass span. One shot, and it goes through what it hits." },
{ key: "sling", name: "Sling", cls: "bow", fam: "missile_weapon", spec: "sling", dmg: "1d8", wound: "blunt", mod: false, ranges: [20,50,110], fire: "fast", cap: 1, mass: 0.1, era: "antique", trad: "tradition_local", desc: "Ancient, and never actually obsolete. Ammunition is whatever is on the ground." },
{ key: "javelin", name: "Javelin", cls: "thrown", fam: "missile_weapon", spec: "thrown", dmg: "1d8+1", wound: "piercing", mod: true, ranges: [10,20,40], fire: "fast", cap: 1, mass: 0.9, era: "antique", trad: "tradition_local", desc: "Ancient. Thrown, and then it is on the ground and somebody else has it." },
/* --- early modern --- */
{ key: "rapier", name: "Rapier", cls: "melee", fam: "melee_weapon", spec: "sword", dmg: "1d8+1", wound: "piercing", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.1, era: "antique", trad: "tradition_local", desc: "Early modern. A yard and a half of point. For duels and for men who expect to be attacked in a street." },
{ key: "main_gauche", name: "Main gauche", cls: "melee", fam: "melee_weapon", spec: "knife", dmg: "1d4+1", wound: "piercing", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 0.5, era: "antique", trad: "tradition_local", desc: "Early modern. The left-hand dagger. Its real job is catching the other man's blade." },
{ key: "matchlock", name: "Matchlock musket", cls: "firearm", fam: "firearm", spec: "muzzleloader", dmg: "1d10+2", wound: "piercing", mod: false, ranges: [15,40,90], fire: "slow", cap: 1, mass: 4.8, era: "antique", trad: "tradition_local", desc: "Early modern. A burning cord and a prayer. Announces itself for a hundred yards before it fires." },
{ key: "wheellock", name: "Wheellock pistol", cls: "firearm", fam: "firearm", spec: "muzzleloader", dmg: "1d8+1", wound: "piercing", mod: false, ranges: [8,18,35], fire: "slow", cap: 1, mass: 1.6, era: "antique", trad: "tradition_local", desc: "Early modern. Clockwork ignition, ruinously expensive, and it works in the rain." },
{ key: "blunderbuss", name: "Blunderbuss", cls: "firearm", fam: "firearm", spec: "muzzleloader", dmg: "2d6+2", wound: "piercing", mod: false, ranges: [5,12,25], fire: "slow", cap: 1, mass: 4.0, era: "antique", trad: "tradition_local", desc: "Early modern. Load it with whatever is to hand. Terrible past twenty feet and decisive within it." },
{ key: "boarding_pike", name: "Boarding pike", cls: "melee", fam: "melee_weapon", spec: "spear", dmg: "1d8+2", wound: "piercing", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 2.4, era: "antique", trad: "tradition_local", desc: "Early modern. Short enough for a deck. The department has them because the department used to have ships." },
/* --- Napoleonic and Victorian --- */
{ key: "sabre", name: "Cavalry sabre", cls: "melee", fam: "melee_weapon", spec: "sword", dmg: "1d8+2", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.3, era: "antique", trad: "tradition_local", desc: "Napoleonic. Curved, and meant to be used going past somebody at speed." },
{ key: "smallsword", name: "Smallsword", cls: "melee", fam: "melee_weapon", spec: "sword", dmg: "1d6+1", wound: "piercing", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 0.6, era: "antique", trad: "tradition_local", desc: "Georgian. Worn with a coat, not with armour. Kills quietly and leaves very little to see." },
{ key: "cutlass", name: "Cutlass", cls: "melee", fam: "melee_weapon", spec: "sword", dmg: "1d8+1", wound: "edged", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.1, era: "antique", trad: "tradition_local", desc: "Georgian. Short, heavy, and it does not care what it hits on the backswing." },
{ key: "brown_bess", name: "Brown Bess", cls: "firearm", fam: "firearm", spec: "muzzleloader", dmg: "1d10+3", wound: "piercing", mod: false, ranges: [20,50,100], fire: "slow", cap: 1, mass: 4.4, era: "antique", trad: "tradition_local", desc: "Napoleonic. Smoothbore, inaccurate, and it will take an arm off at fifty yards." },
{ key: "baker_rifle", name: "Baker rifle", cls: "firearm", fam: "firearm", spec: "muzzleloader", dmg: "1d10+2", wound: "piercing", mod: false, ranges: [40,110,250], fire: "slow", cap: 1, mass: 4.2, era: "antique", trad: "tradition_local", desc: "Napoleonic. Rifled, and slow to load precisely because it is. The first weapon here that rewards patience." },
{ key: "bayonet", name: "Socket bayonet", cls: "melee", fam: "melee_weapon", spec: "knife", dmg: "1d6+1", wound: "piercing", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 0.5, era: "antique", trad: "tradition_local", desc: "Napoleonic onward. On the end of a musket it is a spear; off it, an awkward knife." },
{ key: "martini", name: "Martini-Henry", cls: "firearm", fam: "firearm", spec: "rifle", dmg: "2d6+2", wound: "piercing", mod: false, ranges: [50,150,350], fire: "slow", cap: 1, mass: 4.0, era: "antique", trad: "tradition_local", desc: "Victorian. Single shot, falling block, and a recoil that has bruised generations." },
{ key: "webley", name: "Webley revolver", cls: "firearm", fam: "firearm", spec: "pistol", dmg: "1d10", wound: "piercing", mod: false, ranges: [10,25,50], fire: "fast", cap: 6, mass: 1.1, era: "antique", trad: "tradition_local", desc: "Victorian to the Great War. Breaks open, ejects all six at once, and is still in a drawer upstairs." },
{ key: "lee_enfield", name: "Lee-Enfield", cls: "firearm", fam: "firearm", spec: "rifle", dmg: "2d6+2", wound: "piercing", mod: false, ranges: [60,200,500], fire: "fast", cap: 10, mass: 4.0, era: "antique", trad: "tradition_local", desc: "Great War. Ten rounds and a bolt a trained man works without looking. The best rifle in this list." },
{ key: "trench_club", name: "Trench club", cls: "melee", fam: "melee_weapon", spec: "club", dmg: "1d8+1", wound: "blunt", mod: true, ranges: [0,0,0], fire: "", cap: 0, mass: 1.2, era: "antique", trad: "tradition_local", desc: "Great War. Made in the line out of a table leg and some nails. Quiet, which was the point." }
];
/* ---------- armour (v0.5 §4.8) ---------- */
@@ -138,7 +194,22 @@ export const ARMOURS = [
{ key: "oilcloth_coat", name: "Oilcloth coat", points: 1, mass: 3.0, era: "antique", trad: "tradition_local", desc: "Keeps the weather out and very little else." },
{ key: "brigandine", name: "Brigandine", points: 4, mass: 9.0, era: "antique", trad: "tradition_local", desc: "Plates riveted between cloth. Heavy, quiet, and older than the agency." },
{ key: "hardsuit", name: "Sealed hardsuit", points: 9, mass: 12.0, era: "future", trad: "tradition_transposed", desc: "Sealed, powered and not from here. Also a breathing set — see Gear." }
{ key: "hardsuit", name: "Sealed hardsuit", points: 9, mass: 12.0, era: "future", trad: "tradition_transposed", desc: "Sealed, powered and not from here. Also a breathing set — see Gear." },
/* --- the historical range. Weight is the point: everything here protects
well and costs you the ability to run in it. --- */
{ key: "gambeson", name: "Gambeson", points: 2, mass: 4.5, era: "antique", trad: "tradition_local", desc: "Medieval. Quilted linen, thirty layers. Worn alone by the poor and under everything by everyone else." },
{ key: "maille_shirt", name: "Maille shirt", points: 4, mass: 7.5, era: "antique", trad: "tradition_local", desc: "Medieval. Stops a cut completely and a spike not at all. Wear it over the gambeson or regret it." },
{ key: "coat_of_plates", name: "Coat of plates", points: 6, mass: 11, era: "antique", trad: "tradition_local", desc: "Medieval. Iron plates riveted inside a fabric coat. The compromise that held for a century." },
{ key: "cuirass", name: "Cuirass", points: 6, mass: 9, era: "antique", trad: "tradition_local", desc: "Early modern. Breast and back. Proof against a pistol at any sensible distance, and stated so by the armourer." },
{ key: "harness", name: "Full harness", points: 9, mass: 25, era: "antique", trad: "tradition_local", desc: "Medieval. Head to foot, articulated, and far more wearable than people think — until the third hour." },
{ key: "buff_coat", name: "Buff coat", points: 3, mass: 5, era: "antique", trad: "tradition_local", desc: "Civil War. Thick ox hide to the knee. Turns a sword, ignores a ball, and never dries out." },
{ key: "sallet", name: "Sallet and bevor", points: 5, mass: 3.2, era: "antique", trad: "tradition_local", desc: "Medieval. Covers the head and the throat and takes most of your hearing with it." },
{ key: "lobster_pot", name: "Lobster-tail helmet", points: 4, mass: 2.6, era: "antique", trad: "tradition_local", desc: "Civil War. Three bars across the face. You can see out; that is all that can be said for it." },
{ key: "jack_of_plate", name: "Jack of plate", points: 4, mass: 6, era: "antique", trad: "tradition_local", desc: "Tudor. Small iron plates stitched between canvas. Looks like a coat until somebody hits it." },
{ key: "cuirassier", name: "Cuirassier armour", points: 8, mass: 18, era: "antique", trad: "tradition_local", desc: "Early modern. Three-quarter plate for a man on a horse. On foot it is a punishment." },
{ key: "brodie", name: "Brodie helmet", points: 3, mass: 1.3, era: "antique", trad: "tradition_local", desc: "Great War. A steel plate on a strap. Designed against shrapnel from above and honest about it." },
{ key: "flak_jacket", name: "Flak jacket", points: 4, mass: 8.5, era: "antique", trad: "tradition_local", desc: "Second War. Manganese plates in a waistcoat. Heavy, hot, and it has saved a great many people." }
];
/* ---------- gear ---------- */
+30 -1
View File
@@ -147,7 +147,36 @@ export const ICON_MAP = {
/* ---- borrowed authority ---- */
authority:["folder","device",0], authority_flagged:["folder","device",26],
authority_burned:["folder","device",-26]
authority_burned:["folder","device",-26],
/* ---- the historical range: medieval ---- */
arming_sword:["sword","melee",-4,"antique"], longsword:["sword","melee",-12,"antique"],
falchion:["sword","melee",20,"antique"], war_hammer:["club","melee",-30,"antique"],
mace:["club","melee",30,"antique"], flail:["club","melee",-36,"antique"],
poleaxe:["axe","melee",-18,"antique"], halberd:["spear","melee",-26,"antique"],
billhook:["axe","melee",26,"antique"], pike:["spear","melee",34,"antique"],
quarterstaff:["bar","melee",-22,"antique"], dirk:["blade","melee",-16,"antique"],
longbow:["bow","weapon",-30,"antique"], arbalest:["crossbow","weapon",-24,"antique"],
sling:["rope","weapon",38,"antique"], javelin:["spear","weapon",18,"antique"],
/* ---- early modern ---- */
rapier:["sword","melee",-40,"antique"], main_gauche:["blade","melee",40,"antique"],
matchlock:["musket","weapon",-34,"antique"], wheellock:["flintlock","weapon",28,"antique"],
blunderbuss:["shotgun","weapon",-44,"antique"], boarding_pike:["spear","melee",-32,"antique"],
/* ---- Napoleonic, Victorian, and the Great War ---- */
sabre:["sword","melee",44,"antique"], smallsword:["sword","melee",-48,"antique"],
cutlass:["sword","melee",48,"antique"], brown_bess:["musket","weapon",36,"antique"],
baker_rifle:["musket","weapon",-38,"antique"], bayonet:["blade","melee",32,"antique"],
martini:["rifle","weapon",-42,"antique"], webley:["revolver","weapon",42,"antique"],
lee_enfield:["rifle","weapon",46,"antique"], trench_club:["club","melee",22,"antique"],
/* ---- historical armour ---- */
gambeson:["jacket","armour",-16,"antique"], maille_shirt:["mail","armour",-22,"antique"],
coat_of_plates:["vest","armour",-30,"antique"], cuirass:["plate","armour",16,"antique"],
harness:["plate","armour",-36,"antique"], buff_coat:["jacket","armour",34,"antique"],
sallet:["mask","armour",-42,"antique"], lobster_pot:["mask","armour",42,"antique"],
jack_of_plate:["vest","armour",24,"antique"], cuirassier:["plate","armour",-48,"antique"],
brodie:["mask","armour",30,"antique"], flak_jacket:["vest","armour",-24,"antique"]
};
/** Skill category -> icon key. */
+58 -1
View File
@@ -244,8 +244,64 @@ export function generateMission({ seed = null, rnd = null, ...opts } = {}) {
const esc = s => String(s ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;");
const ul = xs => `<ul>${xs.map(x => `<li>${esc(x)}</li>`).join("")}</ul>`;
/** A table, escaped. Cells may carry markup only when the caller has escaped it. */
const table = (head, rows) =>
`<table><thead><tr>${head.map(h => `<th>${h}</th>`).join("")}</tr></thead><tbody>`
+ rows.map(r => `<tr>${r.map(c => `<td>${c}</td>`).join("")}</tr>`).join("")
+ `</tbody></table>`;
/** The player-facing brief. Everything here is true as far as the agency knows. */
/**
* The players' page. Everything on it is something an agent would be told, or would
* see on arrival — the cast's names and what they want, but never what they lie
* about; the texture of the place, but never why it is like that.
*
* The generator was already writing all of this and filing every word of it behind
* the GM screen: the timeline, the people, and the two lines of texture that are the
* best writing in the whole document. A player brief that opens on a classification
* note is a memo. This is a briefing.
*/
export function introPage(m) {
const first = m.timeline[0];
// The LAST timeline entry is the team's own arrival — "today: the team crosses" —
// which makes nonsense of "since then, ...". Use the last thing that happened
// before they did.
const prior = m.timeline.filter(t => !/team crosses/i.test(t.what));
const recent = prior[prior.length - 1] ?? first;
return `
<h2>Read this out</h2>
<p><em>${esc(m.classification.note)}</em></p>
<p>It is <strong>${esc(m.place)}</strong>. You have <strong>${esc(m.duration)}</strong>,
and the department has been clear that this is the window and not an estimate.
${esc(first.when.charAt(0).toUpperCase() + first.when.slice(1))}, ${esc(first.what.toLowerCase())}
Since then it has not stopped. Most recently, ${esc(recent.what.toLowerCase())}</p>
<p>You are going because ${esc(m.anomaly.containment.toLowerCase().replace(/\.$/, ""))},
and because somebody has to be able to say afterwards that a department attended.</p>
<h2>What it is like there</h2>
${ul(m.texture)}
<p>None of that is in the file. It is what you will notice in the first ten minutes,
and the file was written by somebody who was not there.</p>
<h2>What is known so far</h2>
${table(["When", "What"], m.timeline.map(t => [esc(t.when), esc(t.what)]))}
<h2>Who is there</h2>
${table(["Name", "Who they are", "What they want from you"],
m.cast.map(c => [`<strong>${esc(c.name)}</strong>`, esc(c.role), esc(c.wants)]))}
<p>They are not adversaries. Two of them will be helpful and at least one of them is
not telling you everything, which is ordinary and is not the same as lying.</p>
<h2>Before you go</h2>
<ul>
<li>Draw your kit. What you do not sign for, you do not have.</li>
<li>Somebody had better be able to make an arrangement, because most cases close that
way and this one is no exception.</li>
<li>Your anchor stays on you. It is the way back and it is the reason you are still
you when you get there.</li>
</ul>`;
}
export function briefPage(m) {
// The brief used to open on a classification note and never say where the site
// was, how long the team had, what was likely to be in the way, or how they were
@@ -368,7 +424,8 @@ ${m.timeline.map(t => `<tr><td><strong>${esc(t.when)}</strong></td><td>${esc(t.w
/** The whole case as journal pages, ready to be written into a compendium. */
export function missionPages(m) {
return [
{ name: `${m.codename} · Brief`, content: briefPage(m) },
{ name: `${m.codename} · Briefing`, content: introPage(m), players: true },
{ name: `${m.codename} · Orders`, content: briefPage(m), players: true },
{ name: `${m.codename} · The truth`, content: truthPage(m) },
{ name: `${m.codename} · Opposition`, content: castPage(m) },
{ name: `${m.codename} · Phases`, content: phasesPage(m) },