narrative
The story. Text pools, dialogue, quests, arcs, lore, deeds, and the memory model.
Prose lives in weighted pools, not single strings. A place described twice reads differently. Every sentence the engine produces lives in systemText.
A dialogue does not know who owns itnpc.dialogue names a dialogue. The dialogue never names the NPC. A dialogue nothing points at can never be opened. The studio has a rule for it.
Option effects run before the checkoption.effects run on choosing the option, whatever option.check rolls. A reward that depends on the roll belongs on the success node's onEnter.
The current quest stage is calculatedNothing records it. It is the first stage still holding an unfinished objective that is not optional.
Lore is only taught by an effectA learnLore effect is the only thing that grants it. Lore no effect names can never be known, and is reported.
| Field | Type | Req | Default | What it does |
|---|
maxDialogueHops | number | | 8 | How many redirects a conversation may follow before it stops. |
textGrammar | object[] | | [] | Weighted pools of phrasing. Where variety in the prose comes from. |
systemText | object | | {} | Every sentence the engine itself produces. It holds no prose of its own. |
dialogues | object[] | | [] | Conversation graphs. An NPC points at one; the dialogue does not name its owner. |
quests | object[] | | [] | Jobs, their objectives, and what finishing them is worth. |
arcs | object[] | | [] | Groups of quests read as one story. One of them may end the game. |
lore | object[] | | | Things that can be known. Taught only by a learnLore effect. |
loreThreads | object[] | | | Lore grouped into a mystery, so a journal can say three of five. |
deedKinds | object[] | | [] | The kinds of thing the party can be remembered for. |
memory | object | | {} | How people witness, forget, gossip, and learn. A settings block, not a collection. |
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the pool, named wherever prose is wanted. |
description | string | | "" | What this pool is for. |
variants | object[] | yes | | The phrasings. At least one is required. |
| Field | Type | Req | Default | What it does |
|---|
text | string | yes | | The sentence. Placeholders in braces are filled from the facts in scope. |
when | predicate | | | Predicate gating this phrasing, so prose can react to world state. |
requires | object | | | Gate on this phrasing, in the requirement vocabulary. |
weight | number | | 1 | Relative likelihood against the other phrasings. |
tags | id[] | | [] | Free labels for grouping. |
dialoguesnarrative.dialogues
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the dialogue. An NPC names it to own it. |
start | id | yes | | Node the conversation opens on. Must be one of the nodes below. |
nodes | object[] | yes | | The nodes. Navigation between them is by node id inside this dialogue only. |
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the node, unique inside this dialogue. |
says | object[] | yes | | What the speaker says. Weighted phrasings, picked on entering. |
onEnter | effect[] | | [] | Effects run on entering. Where a checked payoff belongs. |
remembers | narrative.deedKinds | | | Deed kind recorded when this node is reached. |
redirectWhen | object[] | | [] | Send the player elsewhere before speaking. First match wins. |
options | object[] | | [] | Replies offered. A node with none ends the conversation. |
| Field | Type | Req | Default | What it does |
|---|
requires | object | yes | | Gate on taking this redirect. |
goto | id | yes | | Node to jump to instead. |
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the option. Also the key under which taking it is remembered. |
text | string | yes | | What the player says. |
requires | object | | | Gate on the option, measured against what the speaker knows. |
when | predicate | | | Predicate checked on top of requires. |
showWhenLocked | boolean | | false | Show it greyed out when gated, rather than hiding it. |
lockedHint | string | | "" | What to say about why it is closed. |
check | object | | | A roll that decides where the option leads. |
effects | effect[] | | [] | Effects run on choosing it, before and regardless of any check. |
onceOnly | boolean | | false | Whether it may be taken only once, remembered across conversations. |
goto | id | | | Node it leads to. Omit to end the conversation. |
questsnarrative.quests
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the quest, used as quests.<id>.status. |
name | string | yes | | Display name. |
description | string | | "" | What the job is. |
tags | id[] | | [] | Free labels for grouping and gating. |
available | predicate | | | Predicate deciding whether it can be offered yet. |
autoStart | boolean | | false | Whether it begins on its own when play starts. |
giver | content.npcs | | | A label. What actually puts the job in front of a player is that NPC's offersQuests. |
requires | object | | | Gate on taking it. |
stages | object[] | | [] | Ordered chapters, each holding its own objectives. The current one is derived. |
objectives | object[] | | [] | Objectives held directly on the quest rather than in a stage. |
ordered | boolean | | true | Whether objectives must be finished in order. |
onStart | effect[] | | [] | Effects run when it begins. |
onComplete | effect[] | | [] | Effects run when it is finished. |
onFail | effect[] | | [] | Effects run when it fails. |
failWhen | predicate | | | Predicate that fails the quest once it holds. |
rewards | object | | {} | Experience, items, and standing paid on completion. |
unlocks | narrative.quests[] | | [] | Quests marked available when this one finishes. How a chain is wired. |
remembersAs | narrative.deedKinds | | | Deed kind recorded when it is finished, so people can hear about it. |
repeatable | boolean | | false | Whether it can be taken again after finishing. |
timeLimitDays | number | | | Days before it fails on its own. |
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the stage. |
name | string | | | Display name. |
description | string | | "" | What this chapter is. |
objectives | object[] | | [] | What must be done to move past it. |
onStart | effect[] | | [] | Effects run when the stage becomes current. |
onComplete | effect[] | | [] | Effects run when the stage is finished. |
journalKey | narrative.textGrammar | | | Text pool for the journal entry while this stage is current. |
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the objective, used as quests.<quest>.objectives.<id>. |
description | string | | "" | What to do, as the journal puts it. |
kind | customkillcollectreachtalk | | "custom" | What kind of event finishes it. Custom watches your own predicate. |
target | id | | | What to kill, collect, reach, or talk to. A bare id, not a checked reference. |
count | number | | 1 | How many times it must happen. |
when | predicate | | | Required for custom. On other kinds, an extra gate the event must also pass. |
requires | object | | | Gate on the objective accepting progress at all. |
hidden | boolean | | false | Whether it is kept out of the journal until finished. |
optional | boolean | | false | Whether the quest can finish without it. |
onComplete | effect[] | | [] | Effects run when it is finished. |
| Field | Type | Req | Default | What it does |
|---|
xp | expression | | 0 | Experience paid, as an expression. Awarded to the whole party. |
items | object[] | | [] | Items handed over. |
reputation | { content.factions: expression } | | {} | Standing change per faction, each as an expression. |
arcsnarrative.arcs
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the arc, read as arcs.<id>. |
name | string | yes | | Display name. |
description | string | | "" | What this story is. |
quests | narrative.quests[] | yes | | The quests it is made of. At least one is required. |
isEnding | boolean | | false | Finishing it ends the run, unless start.postVictory says continue. |
lorenarrative.lore
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the entry, read as lore.<id>. |
name | string | yes | | Display name. |
description | string | | "" | What is known. |
tags | id[] | | [] | Free labels for grouping and gating. |
textKey | narrative.textGrammar | | | Text pool for how it reads when learned. |
source | string | | "" | Where it came from, for the journal. |
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the thread, read as threads.<id>.known. |
name | string | yes | | Display name. |
description | string | | "" | What the mystery is. |
entries | narrative.lore[] | yes | | The lore that makes it up. At least one is required. |
deedKindsnarrative.deedKinds
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the deed kind, read as memory.<who>.<id>. |
name | string | yes | | Display name. |
tags | id[] | | [] | Free labels for grouping and gating. |
severity | number | | 0 | How bad it is. Gossip below the minimum severity never travels. |
faction | content.factions | | | Who takes it personally. Without one, derived from the victim. |
memorability | number | | 1 | How strongly it lodges. Multiplies against the forgetting curve. |
distortion | number | | 0.2 | How much the story changes as it is retold, 0 to 1. |
memorynarrative.memory
| Field | Type | Req | Default | What it does |
|---|
mode | simulatedmanualhybrid | | "hybrid" | Whether the engine drives memory, your content drives it, or both. |
forgetting | object | | {} | How a memory fades. |
gossip | object | | {} | How news travels between people. |
witness | object | | {} | Who sees a deed and whether they can name who did it. |
learning | object | | {} | Whether creatures adapt to how the party fights. |
rules | object[] | | [] | Per deed kind overrides and hand placed knowledge. |
extra | { string: any } | | {} | Open bag of your own data on the memory model. |
| Field | Type | Req | Default | What it does |
|---|
curve | nonelinearexponentialthreshold | | "exponential" | Shape of the fade. None keeps a memory forever. |
halfLifeDays | number | | 30 | Days for a memory to lose half its strength. |
floor | number | | 0.05 | Strength it never fades below, 0 to 1. |
reinforceOnRecall | number | | 0.25 | Strength returned each time the memory comes up. |
memorabilityWeight | number | | 1 | How much a deed kind's memorability slows the fade. |
caresAboutMultiplier | number | | 2 | How much slower it fades for someone who cares about it. |
linearSpanMultiplier | number | | 2 | Half lives a linear curve takes to reach nothing. |
neverForget | narrative.deedKinds[] | | [] | Deed kinds that never fade at all. |
extra | { string: any } | | {} | Open bag of your own data on forgetting. |
| Field | Type | Req | Default | What it does |
|---|
enabled | boolean | | true | Whether news travels at all. |
spreadPerDay | number | | 0.25 | Chance per day that a knower tells someone, 0 to 1. |
maxHops | number | | 4 | How far from the witness a story can travel. |
hopRetention | number | | 0.75 | Strength kept per hop, 0 to 1. |
distortionPerHop | number | | 0.15 | How much the story changes per hop, 0 to 1. |
requiresTravel | boolean | | true | Whether news needs someone to actually go there. |
crossFactionRate | number | | 0.4 | How readily it crosses between factions, 0 to 1. |
minimumSeverity | number | | 1 | Deeds below this are not worth repeating. |
gullibilityScale | number | | 2 | How much a listener's gullibility decides whether they believe it. |
garbledRetention | number | | 0.5 | Strength kept once a story has become distorted, 0 to 1. |
spreadsWithoutWitness | boolean | | false | Whether a deed nobody saw can still become a rumour. |
extra | { string: any } | | {} | Open bag of your own data on gossip. |
| Field | Type | Req | Default | What it does |
|---|
radius | number | | 0 | Tiles within which a deed is seen. 0 uses the perception model instead. |
requiresLineOfSight | boolean | | true | Whether a witness must be able to see it. |
deadMenTellNoTales | boolean | | true | Whether killing the witnesses stops the news. |
identificationChance | number | | 0.8 | Chance a witness can name who did it, 0 to 1. |
disguiseReduction | number | | 0.5 | How much a concealing condition cuts that chance, 0 to 1. |
factionAlwaysLearns | boolean | | false | Whether the victim's faction hears regardless of witnesses. |
extra | { string: any } | | {} | Open bag of your own data on witnessing. |
| Field | Type | Req | Default | What it does |
|---|
enabled | boolean | | true | Whether creatures adapt to the party at all. |
encountersBeforeAdapting | number | | 3 | Fights needed before anything changes. |
adaptationStrength | number | | 0.5 | How far behaviour shifts once it does, 0 to 1. |
sharedWithinFaction | boolean | | true | Whether what one learns the rest know. |
minimumIntellect | number | | | Attribute value below which a creature cannot learn. |
tracks | damageTypesabilitiestacticspartyComposition[] | | ["damageTypes","abilities"] | What is noticed about the party. |
forgetAfterDays | number | | 90 | Days before what was learned is lost. |
extra | { string: any } | | {} | Open bag of your own data on learning. |
| Field | Type | Req | Default | What it does |
|---|
id | id | yes | | Id of the rule. |
name | string | | | Display name. |
description | string | | "" | What this rule is for. |
deedKinds | narrative.deedKinds[] | | [] | Deed kinds it applies to. Empty means all of them. |
when | predicate | | | Predicate gating the rule. |
alwaysKnownBy | content.npcs[] | | [] | People who know regardless of witnesses or gossip. |
neverKnownBy | content.npcs[] | | [] | People who never find out. |
spreadPerDay | number | | | Gossip rate for these deeds, overriding the global one. |
halfLifeDays | number | | | Forgetting half life for these deeds, overriding the global one. |
distortionPerHop | number | | | Distortion for these deeds, overriding the global one. |
manualOnly | boolean | | false | Whether the simulation leaves these deeds entirely to your content. |
extra | { string: any } | | {} | Open bag of your own data on this rule. |