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 it
npc.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 check
option.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 calculated
Nothing records it. It is the first stage still holding an unfinished objective that is not optional.
Lore is only taught by an effect
A learnLore effect is the only thing that grants it. Lore no effect names can never be known, and is reported.

narrativenarrative

FieldTypeReqDefaultWhat it does
maxDialogueHopsnumber8How many redirects a conversation may follow before it stops.
textGrammarobject[][]Weighted pools of phrasing. Where variety in the prose comes from.
systemTextobject{}Every sentence the engine itself produces. It holds no prose of its own.
dialoguesobject[][]Conversation graphs. An NPC points at one; the dialogue does not name its owner.
questsobject[][]Jobs, their objectives, and what finishing them is worth.
arcsobject[][]Groups of quests read as one story. One of them may end the game.
loreobject[]Things that can be known. Taught only by a learnLore effect.
loreThreadsobject[]Lore grouped into a mystery, so a journal can say three of five.
deedKindsobject[][]The kinds of thing the party can be remembered for.
memoryobject{}How people witness, forget, gossip, and learn. A settings block, not a collection.

textGrammarnarrative.textGrammar

FieldTypeReqDefaultWhat it does
ididyesId of the pool, named wherever prose is wanted.
descriptionstring""What this pool is for.
variantsobject[]yesThe phrasings. At least one is required.

textGrammar → variantsnarrative.textGrammar.variants

FieldTypeReqDefaultWhat it does
textstringyesThe sentence. Placeholders in braces are filled from the facts in scope.
whenpredicatePredicate gating this phrasing, so prose can react to world state.
requiresobjectGate on this phrasing, in the requirement vocabulary.
weightnumber1Relative likelihood against the other phrasings.
tagsid[][]Free labels for grouping.

dialoguesnarrative.dialogues

FieldTypeReqDefaultWhat it does
ididyesId of the dialogue. An NPC names it to own it.
startidyesNode the conversation opens on. Must be one of the nodes below.
nodesobject[]yesThe nodes. Navigation between them is by node id inside this dialogue only.

dialogues → nodesnarrative.dialogues.nodes

FieldTypeReqDefaultWhat it does
ididyesId of the node, unique inside this dialogue.
saysobject[]yesWhat the speaker says. Weighted phrasings, picked on entering.
onEntereffect[][]Effects run on entering. Where a checked payoff belongs.
remembersnarrative.deedKindsDeed kind recorded when this node is reached.
redirectWhenobject[][]Send the player elsewhere before speaking. First match wins.
optionsobject[][]Replies offered. A node with none ends the conversation.

dialogues → nodes → redirectWhennarrative.dialogues.nodes.redirectWhen

FieldTypeReqDefaultWhat it does
requiresobjectyesGate on taking this redirect.
gotoidyesNode to jump to instead.

dialogues → nodes → optionsnarrative.dialogues.nodes.options

FieldTypeReqDefaultWhat it does
ididyesId of the option. Also the key under which taking it is remembered.
textstringyesWhat the player says.
requiresobjectGate on the option, measured against what the speaker knows.
whenpredicatePredicate checked on top of requires.
showWhenLockedbooleanfalseShow it greyed out when gated, rather than hiding it.
lockedHintstring""What to say about why it is closed.
checkobjectA roll that decides where the option leads.
effectseffect[][]Effects run on choosing it, before and regardless of any check.
onceOnlybooleanfalseWhether it may be taken only once, remembered across conversations.
gotoidNode it leads to. Omit to end the conversation.

questsnarrative.quests

FieldTypeReqDefaultWhat it does
ididyesId of the quest, used as quests.<id>.status.
namestringyesDisplay name.
descriptionstring""What the job is.
tagsid[][]Free labels for grouping and gating.
availablepredicatePredicate deciding whether it can be offered yet.
autoStartbooleanfalseWhether it begins on its own when play starts.
givercontent.npcsA label. What actually puts the job in front of a player is that NPC's offersQuests.
requiresobjectGate on taking it.
stagesobject[][]Ordered chapters, each holding its own objectives. The current one is derived.
objectivesobject[][]Objectives held directly on the quest rather than in a stage.
orderedbooleantrueWhether objectives must be finished in order.
onStarteffect[][]Effects run when it begins.
onCompleteeffect[][]Effects run when it is finished.
onFaileffect[][]Effects run when it fails.
failWhenpredicatePredicate that fails the quest once it holds.
rewardsobject{}Experience, items, and standing paid on completion.
unlocksnarrative.quests[][]Quests marked available when this one finishes. How a chain is wired.
remembersAsnarrative.deedKindsDeed kind recorded when it is finished, so people can hear about it.
repeatablebooleanfalseWhether it can be taken again after finishing.
timeLimitDaysnumberDays before it fails on its own.

quests → stagesnarrative.quests.stages

FieldTypeReqDefaultWhat it does
ididyesId of the stage.
namestringDisplay name.
descriptionstring""What this chapter is.
objectivesobject[][]What must be done to move past it.
onStarteffect[][]Effects run when the stage becomes current.
onCompleteeffect[][]Effects run when the stage is finished.
journalKeynarrative.textGrammarText pool for the journal entry while this stage is current.

quests → objectivesnarrative.quests.objectives

FieldTypeReqDefaultWhat it does
ididyesId of the objective, used as quests.<quest>.objectives.<id>.
descriptionstring""What to do, as the journal puts it.
kindcustomkillcollectreachtalk"custom"What kind of event finishes it. Custom watches your own predicate.
targetidWhat to kill, collect, reach, or talk to. A bare id, not a checked reference.
countnumber1How many times it must happen.
whenpredicateRequired for custom. On other kinds, an extra gate the event must also pass.
requiresobjectGate on the objective accepting progress at all.
hiddenbooleanfalseWhether it is kept out of the journal until finished.
optionalbooleanfalseWhether the quest can finish without it.
onCompleteeffect[][]Effects run when it is finished.

quests → rewardsnarrative.quests.rewards

FieldTypeReqDefaultWhat it does
xpexpression0Experience paid, as an expression. Awarded to the whole party.
itemsobject[][]Items handed over.
reputation{ content.factions: expression }{}Standing change per faction, each as an expression.

quests → rewards → itemsnarrative.quests.rewards.items

FieldTypeReqDefaultWhat it does
itemcontent.itemsyesWhich item.
quantityexpression1How many, as an expression.

arcsnarrative.arcs

FieldTypeReqDefaultWhat it does
ididyesId of the arc, read as arcs.<id>.
namestringyesDisplay name.
descriptionstring""What this story is.
questsnarrative.quests[]yesThe quests it is made of. At least one is required.
isEndingbooleanfalseFinishing it ends the run, unless start.postVictory says continue.

lorenarrative.lore

FieldTypeReqDefaultWhat it does
ididyesId of the entry, read as lore.<id>.
namestringyesDisplay name.
descriptionstring""What is known.
tagsid[][]Free labels for grouping and gating.
textKeynarrative.textGrammarText pool for how it reads when learned.
sourcestring""Where it came from, for the journal.

loreThreadsnarrative.loreThreads

FieldTypeReqDefaultWhat it does
ididyesId of the thread, read as threads.<id>.known.
namestringyesDisplay name.
descriptionstring""What the mystery is.
entriesnarrative.lore[]yesThe lore that makes it up. At least one is required.

deedKindsnarrative.deedKinds

FieldTypeReqDefaultWhat it does
ididyesId of the deed kind, read as memory.<who>.<id>.
namestringyesDisplay name.
tagsid[][]Free labels for grouping and gating.
severitynumber0How bad it is. Gossip below the minimum severity never travels.
factioncontent.factionsWho takes it personally. Without one, derived from the victim.
memorabilitynumber1How strongly it lodges. Multiplies against the forgetting curve.
distortionnumber0.2How much the story changes as it is retold, 0 to 1.

memorynarrative.memory

FieldTypeReqDefaultWhat it does
modesimulatedmanualhybrid"hybrid"Whether the engine drives memory, your content drives it, or both.
forgettingobject{}How a memory fades.
gossipobject{}How news travels between people.
witnessobject{}Who sees a deed and whether they can name who did it.
learningobject{}Whether creatures adapt to how the party fights.
rulesobject[][]Per deed kind overrides and hand placed knowledge.
extra{ string: any }{}Open bag of your own data on the memory model.

memory → forgettingnarrative.memory.forgetting

FieldTypeReqDefaultWhat it does
curvenonelinearexponentialthreshold"exponential"Shape of the fade. None keeps a memory forever.
halfLifeDaysnumber30Days for a memory to lose half its strength.
floornumber0.05Strength it never fades below, 0 to 1.
reinforceOnRecallnumber0.25Strength returned each time the memory comes up.
memorabilityWeightnumber1How much a deed kind's memorability slows the fade.
caresAboutMultipliernumber2How much slower it fades for someone who cares about it.
linearSpanMultipliernumber2Half lives a linear curve takes to reach nothing.
neverForgetnarrative.deedKinds[][]Deed kinds that never fade at all.
extra{ string: any }{}Open bag of your own data on forgetting.

memory → gossipnarrative.memory.gossip

FieldTypeReqDefaultWhat it does
enabledbooleantrueWhether news travels at all.
spreadPerDaynumber0.25Chance per day that a knower tells someone, 0 to 1.
maxHopsnumber4How far from the witness a story can travel.
hopRetentionnumber0.75Strength kept per hop, 0 to 1.
distortionPerHopnumber0.15How much the story changes per hop, 0 to 1.
requiresTravelbooleantrueWhether news needs someone to actually go there.
crossFactionRatenumber0.4How readily it crosses between factions, 0 to 1.
minimumSeveritynumber1Deeds below this are not worth repeating.
gullibilityScalenumber2How much a listener's gullibility decides whether they believe it.
garbledRetentionnumber0.5Strength kept once a story has become distorted, 0 to 1.
spreadsWithoutWitnessbooleanfalseWhether a deed nobody saw can still become a rumour.
extra{ string: any }{}Open bag of your own data on gossip.

memory → witnessnarrative.memory.witness

FieldTypeReqDefaultWhat it does
radiusnumber0Tiles within which a deed is seen. 0 uses the perception model instead.
requiresLineOfSightbooleantrueWhether a witness must be able to see it.
deadMenTellNoTalesbooleantrueWhether killing the witnesses stops the news.
identificationChancenumber0.8Chance a witness can name who did it, 0 to 1.
disguiseReductionnumber0.5How much a concealing condition cuts that chance, 0 to 1.
factionAlwaysLearnsbooleanfalseWhether the victim's faction hears regardless of witnesses.
extra{ string: any }{}Open bag of your own data on witnessing.

memory → learningnarrative.memory.learning

FieldTypeReqDefaultWhat it does
enabledbooleantrueWhether creatures adapt to the party at all.
encountersBeforeAdaptingnumber3Fights needed before anything changes.
adaptationStrengthnumber0.5How far behaviour shifts once it does, 0 to 1.
sharedWithinFactionbooleantrueWhether what one learns the rest know.
minimumIntellectnumberAttribute value below which a creature cannot learn.
tracksdamageTypesabilitiestacticspartyComposition[]["damageTypes","abilities"]What is noticed about the party.
forgetAfterDaysnumber90Days before what was learned is lost.
extra{ string: any }{}Open bag of your own data on learning.

memory → rulesnarrative.memory.rules

FieldTypeReqDefaultWhat it does
ididyesId of the rule.
namestringDisplay name.
descriptionstring""What this rule is for.
deedKindsnarrative.deedKinds[][]Deed kinds it applies to. Empty means all of them.
whenpredicatePredicate gating the rule.
alwaysKnownBycontent.npcs[][]People who know regardless of witnesses or gossip.
neverKnownBycontent.npcs[][]People who never find out.
spreadPerDaynumberGossip rate for these deeds, overriding the global one.
halfLifeDaysnumberForgetting half life for these deeds, overriding the global one.
distortionPerHopnumberDistortion for these deeds, overriding the global one.
manualOnlybooleanfalseWhether the simulation leaves these deeds entirely to your content.
extra{ string: any }{}Open bag of your own data on this rule.