rules
The system. What a character is made of, what dice decide, and how levels work.
Everything a character is made of is declared here. Required: attributes, resources, progression, and vitalResource. Everything else is optional.
Death
Reaching a resource floor runs its
onDepleted effects. Death follows only if the creature is still at the floor afterwards and the resource is vitalResource."onDepleted": [ { "heal": { "target": { "ref": "actor.id" }, "amount": 1 } },
{ "applyCondition": { "target": { "ref": "actor.id" },
"condition": "downed" } } ]means stabilised, not killed.The order stats are worked out in
Attributes, then modifiers, then resource limits, then derived stats. Each step sees the ones before it. Modifiers see only their own attribute value. Derived stats also see equipment and active conditions. A resource limit cannot reference a derived stat.
Getting allies
dispositionBands maps a disposition number onto a stance, highest matching band first. The default has only neutral and hostile. Add a band above zero for an NPC to fight on your side.rulesrules
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
attributes | object[] | yes | What a character is made of. At least one is required. | |
resources | object[] | yes | Pools that go up and down. Hit points and focus are both just resources. | |
derivedStats | object[] | [] | Numbers computed from attributes, gear, and conditions. | |
damageTypes | object[] | [] | The kinds of damage that exist. Resistance and immunity are written against these. | |
conditions | object[] | [] | States a creature can be in, with what they do while they last. | |
actionTypes | object[] | [] | The action economy. Each type declares how many a creature gets per turn. | |
equipmentSlots | object[] | [] | Where gear goes, and how many items each place holds. | |
itemProperties | object[] | [] | Reusable tags on items that carry stat modifiers. | |
masteryTiers | object[] | [] | Named skill bands, so a requirement can ask for adept rather than rank 5. | |
rests | object[] | [] | The ways a party recovers, and what each costs in time. | |
resolution | object | {} | The dice convention. What a check rolls, what crits, how results round. | |
progression | object | yes | The level curve and what each level grants. Required. | |
savingThrows | object[] | [] | The saves that exist, each governed by an attribute. | |
sizes | object[] | [] | Creature sizes, with the space they take and how far they reach. | |
creatureTypes | object[] | [] | Broad kinds of creature, for gating and description. | |
senses | object[] | [] | How creatures notice each other. Sight, scent, hearing, or anything you invent. | |
stances | object[] | [] | Postures a creature can take, trading speed for concealment or the reverse. | |
movementModes | object[] | [] | Ways of moving, each with a base speed and a terrain multiplier. | |
languages | object[] | [] | Languages that exist. Creatures list which they speak. | |
alignments | object[] | [] | Moral or factional labels. Carried and gateable, never enforced. | |
opportunities | object[] | [] | Reactions the rules grant everyone, such as a parting blow. | |
coverTypes | object[] | [] | Degrees of cover and what each is worth on defence. | |
spellcasting | object | {} | Slots or points, concentration, components, and rituals. | |
perception | object | {} | Which sense counts as sight, and the defaults perception runs on. | |
temperament | object | {} | What creatures do unprompted: wandering, giving chase, and giving up. | |
currency | object | {} | What money is called and whether it can go negative. | |
vitalResource | rules.resources | yes | The resource whose floor means death. Required. | |
initiativeStat | rules.derivedStats | Derived stat rolled for turn order. Without one, order is by id. | ||
defaultSize | rules.sizes | Size given to a creature that names none. | ||
defaultMovementMode | rules.movementModes | Movement mode used when a creature names none. | ||
interactionRange | object | {} | How close you must be to talk to someone or reach a thing. | |
search | object | {} | How far a search finds traps and how close disarming needs you. | |
dispositionBands | object[] | [{"id":"neutral","atLeast":0,"stance":"ne… | Disposition numbers to stances. A band above 0 is the only way to get allies. | |
extra | { string: any } | {} | Open bag of your own data on the ruleset. Read it back with a ref path. |
attributesrules.attributes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the attribute, used as actor.attr.<id>. | |
name | string | yes | Display name. | |
abbrev | string | yes | Short form for tight displays, one to six characters. | |
description | string | "" | What this attribute covers. Author and player facing. | |
min | number | 1 | Lowest value character creation and effects may take it to. | |
max | number | 20 | Highest value it may reach. | |
default | number | 10 | Starting value before creation spends any points. | |
modifier | expression | yes | Formula turning the raw value into a modifier. Sees only value. |
resourcesrules.resources
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the resource, used as actor.res.<id>. | |
name | string | yes | Display name. | |
description | string | "" | What the pool represents. | |
max | expression | yes | Formula for the ceiling. May read attributes, modifiers, and level. | |
min | expression | 0 | Formula for the floor. Reaching it runs onDepleted. | |
initial | expression | Formula for the starting value. Defaults to the maximum. | ||
restoreOnShortRest | number | 0 | Fraction of the maximum a short rest returns, 0 to 1. | |
restoreOnLongRest | number | 1 | Fraction of the maximum a long rest returns, 0 to 1. | |
onDepleted | effect[] | [] | What happens at the floor. Death is these effects on the vital resource. |
derivedStatsrules.derivedStats
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the stat, used as actor.derived.<id>. | |
name | string | yes | Display name. | |
description | string | "" | What the number means. | |
formula | expression | yes | Expression over attributes, modifiers, level, and resources. |
damageTypesrules.damageTypes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the damage type. | |
name | string | yes | Display name. | |
description | string | "" | What this kind of harm is. | |
tags | id[] | [] | Labels a damage interaction can except on, such as silvered. |
conditionsrules.conditions
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the condition, used as actor.conditions.<id>. | |
name | string | yes | Display name. | |
description | string | "" | What being in this state means. | |
tags | id[] | [] | Free labels for grouping and gating. | |
stacking | refreshextendstackignore | "refresh" | What a second application does. Refresh, extend, stack, or ignore. | |
defaultDuration | expression | Rounds it lasts when the applying effect names no duration. | ||
onApply | effect[] | [] | Effects run once, when it lands. | |
onTick | effect[] | [] | Effects run at the start of each of the sufferer's turns. | |
onExpire | effect[] | [] | Effects run once, when it ends. | |
modifiers | { id: expression } | {} | Derived stat adjustments while it holds. Magnitude is in scope. | |
prevents | id[] | [] | Action type ids this forbids. A bare id, not a checked reference. | |
suppressesSenses | id[] | Senses this shuts off, unless the sense itself ignores this condition. | ||
swings | object | Which way the dice lean while this is on you. Prefer it or modifiers, not both. | ||
concealsIdentity | boolean | false | Makes a witness less able to name who did the deed. | |
savingThrow | object | A save to shrug it off, and when that save is offered. | ||
implies | id[] | [] | Condition ids that come with this one. A bare id, not a checked reference. | |
extra | { string: any } | {} | Open bag of your own data on this condition. |
conditions → swingsrules.conditions.swings
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
ownAttacks | advantagedisadvantage | How attack rolls made by the afflicted creature lean. | ||
attacksAgainstSelf | advantagedisadvantage | How attack rolls made against the afflicted creature lean. | ||
checks | advantagedisadvantage | How the afflicted creature's ability checks lean. | ||
saves | advantagedisadvantage | How the afflicted creature's saving throws lean. |
conditions → savingThrowrules.conditions.savingThrow
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
save | rules.savingThrows | yes | Which saving throw resists it. | |
difficulty | expression | yes | Difficulty of that save, as an expression. | |
timing | onApplyendOfTurnstartOfTurnboth | "endOfTurn" | When the save is offered. On landing, on turn ends, or both. |
actionTypesrules.actionTypes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the action type, such as action or bonus. | |
name | string | yes | Display name. | |
description | string | "" | What this slice of a turn is for. | |
perTurn | number | 1 | How many a creature gets each turn. |
equipmentSlotsrules.equipmentSlots
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the slot, named by an item's slot field. | |
name | string | yes | Display name. | |
capacity | number | 1 | How many items fit here at once. |
itemPropertiesrules.itemProperties
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the property, named by an item's properties list. | |
name | string | yes | Display name. | |
description | string | "" | What carrying this property means. | |
modifiers | { id: expression } | {} | Derived stat adjustments an item with this property grants. | |
attackStats | rules.attributes[] | Attributes a weapon with this may also attack with. The best is used, for damage too. | ||
extra | { string: any } | {} | Open bag of your own data on this property. |
masteryTiersrules.masteryTiers
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the tier, asked for by a requirement as minTier. | |
name | string | yes | Display name. | |
description | string | "" | What this level of skill means. | |
atRank | number | yes | Skill rank at which the tier is reached. |
restsrules.rests
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the rest, named by a rest action and by spellcasting recovery. | |
name | string | yes | Display name. | |
description | string | "" | What this kind of rest is. | |
duration | number | 60 | Minutes of world time it consumes. | |
kind | shortlong | "short" | Whether resources use their short rest or long rest fraction. | |
effects | effect[] | [] | Extra effects run on finishing, beyond resource restoration. | |
interruptChance | number | 0 | Chance per rest that something interrupts it, 0 to 1. |
resolutionrules.resolution
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
checkDice | dice | "1d20" | The notation every check rolls. | |
advantageDice | dice | "2d20kh1" | Notation rolled instead when a check has advantage. | |
disadvantageDice | dice | "2d20kl1" | Notation rolled instead when a check has disadvantage. | |
swingStacking | cancelnet | "cancel" | What a roll does with more than one swing: cancel them out, or go by the count. | |
criticalSuccessAt | number | 20 | Natural roll at or above which a check crits. Null for no crits. | |
criticalFailureAt | number | 1 | Natural roll at or below which a check fumbles. Null for no fumbles. | |
criticalScope | attacksavecheck[] | ["attack","save","check"] | Which kinds of roll can crit or fumble: attack, save, check. | |
criticalDamageMultiplier | number | 2 | What a critical hit multiplies damage by. | |
saveSuccessMultiplier | number | 0.5 | Damage kept on a successful save when the ability says half. | |
passiveBase | number | 10 | Number a passive score adds its modifier to instead of rolling. | |
opposedMode | passivecontested | "passive" | Whether an opposed check rolls both sides or rolls against a passive score. | |
damageRounding | floorroundceil | "round" | How fractional damage resolves to a whole number. | |
reputationRounding | floorroundceiltrunc | "trunc" | How fractional reputation change resolves to a whole number. | |
attackBonus | expression | What a weapon attack adds. Omitted, just the attribute modifier, which never grows. | ||
defaultDifficulty | number | 12 | Difficulty used when a check names none. | |
difficulties | { id: number } | {} | Named difficulties, so content can ask for hard rather than 18. |
progressionrules.progression
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
maxLevel | number | 20 | Level the curve stops at. Experience past it is kept but grants nothing. | |
levels | object[] | yes | One entry per level, in order, with its cost and what it gives. | |
proficiency | expression | Formula for the proficiency bonus over actor.level. | ||
proficiencyRank | number | 1 | Skill rank a proficiency counts as when a requirement asks. | |
levelVitality | object | {} | How the vital resource grows on gaining a level. |
progression → levelsrules.progression.levels
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
level | number | yes | Which level this entry describes. | |
xpRequired | number | yes | Total experience needed to reach it. | |
grants | effect[] | [] | Effects run on each character crossing this level. |
progression → levelVitalityrules.progression.levelVitality
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
policy | rollaveragemaxnone | "roll" | Roll the die, take its average, take its maximum, or grant nothing. | |
die | classsize | "class" | Whether the die comes from the character's class or their size. | |
bonus | expression | 0 | Expression added on top of the die, per level. |
savingThrowsrules.savingThrows
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the save, named by abilities and conditions. | |
name | string | yes | Display name. | |
description | string | "" | What this save resists. | |
attribute | rules.attributes | yes | Attribute whose modifier the save adds. | |
defaultDifficulty | expression | Difficulty used when the thing calling for the save names none. | ||
extra | { string: any } | {} | Open bag of your own data on this save. |
sizesrules.sizes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the size. | |
name | string | yes | Display name. | |
space | number | 5 | Distance units the creature occupies. Converted to tiles by the engine. | |
reach | number | 5 | Distance units the creature can reach to strike. | |
carryMultiplier | number | 1 | Not read by the engine. Build encumbrance from actor.carried and a derived stat. | |
hitDie | dice | Vitality die for creatures of this size, when levelVitality takes its die from size. | ||
extra | { string: any } | {} | Open bag of your own data on this size. |
creatureTypesrules.creatureTypes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the creature type. | |
name | string | yes | Display name. | |
description | string | "" | What this kind of creature is. | |
tags | id[] | [] | Free labels for grouping and gating. | |
extra | { string: any } | {} | Open bag of your own data on this creature type. |
sensesrules.senses
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the sense, used as a key in emits and in a creature's senses. | |
name | string | yes | Display name. | |
description | string | "" | What this sense picks up. | |
defaultRange | number | 60 | Distance units a creature perceives with it unless it says otherwise. | |
ignores | id[] | [] | Not read by the engine yet. No condition currently suppresses a sense. | |
propagation | linefield | "line" | Whether the signal travels in a straight line or fills the space. | |
blockedBy | opaqueimpassablenothing | "opaque" | What stops it. Opaque terrain, anything impassable, or nothing. | |
falloff | clifflinear | "cliff" | Whether strength drops off a cliff at range or fades with distance. | |
lingerMinutes | number | 0 | How long a trace stays after whatever left it has gone. Scent, not sight. | |
spreadPerMinute | number | 0 | How fast it travels, in tiles a minute. Zero arrives at once. | |
spreadRetention | number | 0.5 | Signal left at the far edge of reach once it has spread that far. | |
rememberMinutes | number | 0 | How long a creature holds on to something it noticed with this sense. | |
impressionTextKey | narrative.textGrammar | Text pool for a clear impression. | ||
faintImpressionTextKey | narrative.textGrammar | Text pool for a weak impression. | ||
emptyTextKey | narrative.textGrammar | Text pool for sensing and finding nothing. | ||
thresholds | object | {} | Signal strengths at which noticing turns into investigating and then attacking. | |
extra | { string: any } | {} | Open bag of your own data on this sense. |
senses → thresholdsrules.senses.thresholds
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
detect | number | 0 | Strength at which the creature knows something is there, 0 to 1. | |
investigate | number | 0 | Strength at which it goes to look, 0 to 1. | |
aggro | number | 0 | Strength at which it treats the source as a target, 0 to 1. |
stancesrules.stances
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the stance. | |
name | string | yes | Display name. | |
description | string | "" | What moving this way means. | |
speedMultiplier | number | 1 | What it does to movement speed. | |
emits | { rules.senses: number } | {} | Signal strength this stance gives off, per sense. | |
concealedBy | content.skills | Skill whose rank makes this stance quieter. | ||
concealmentPerPoint | number | 0 | Signal removed per rank of that skill. | |
extra | { string: any } | {} | Open bag of your own data on this stance. |
movementModesrules.movementModes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the mode, such as walk, swim, or fly. | |
name | string | yes | Display name. | |
defaultSpeed | number | 30 | Distance units per turn for a creature that names no speed of its own. | |
terrainMultiplier | number | 1 | What this mode does to terrain movement costs. | |
fallsWhenDisabled | boolean | false | Not read by the engine yet. Nothing takes a movement mode away. | |
extra | { string: any } | {} | Open bag of your own data on this mode. |
languagesrules.languages
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the language. | |
name | string | yes | Display name. | |
description | string | "" | Who speaks it and where. | |
script | string | "" | Not read by the engine. The writing system, for flavour. | |
exotic | boolean | false | Not read by the engine. Dialogue and readable content are not language gated. | |
extra | { string: any } | {} | Open bag of your own data on this language. |
alignmentsrules.alignments
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the alignment. | |
name | string | yes | Display name. | |
abbrev | string | "" | Short form for tight displays. | |
extra | { string: any } | {} | Open bag of your own data on this alignment. |
opportunitiesrules.opportunities
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the opportunity. | |
name | string | yes | Display name. | |
description | string | "" | What this reaction is and why everyone has it. | |
on | moveAwaycastSpellrangedAttackstandUpbeHitallyHitcustom | "moveAway" | What provokes it. Leaving reach, casting, shooting, standing, being hit, or custom. | |
event | string | Event name to watch, when on is custom. | ||
actionType | rules.actionTypes | Action type it spends. Without one it is free. | ||
use | content.abilities | Ability the reacting creature uses. Without one, only effects run. | ||
requires | predicate | Predicate that must hold for it to trigger. Not the requirement object. | ||
effects | effect[] | [] | Effects run when it triggers. | |
usesPerRound | number | 1 | How many times one creature may take it each round. | |
extra | { string: any } | {} | Open bag of your own data on this opportunity. |
coverTypesrules.coverTypes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the cover type. | |
name | string | yes | Display name. | |
defenceBonus | number | 0 | Added to the defended stat when the target has this cover. | |
blocksTargeting | boolean | false | True when the target cannot be picked at all, not merely harder to hit. | |
extra | { string: any } | {} | Open bag of your own data on this cover type. |
spellcastingrules.spellcasting
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
mode | noneslotspointsboth | "none" | Whether casting spends slots, spends points, both, or is off. | |
maxSpellLevel | number | 9 | Highest spell level the game has. | |
slotTable | { string: number[] } | {} | Slots per spell level, keyed by caster level. | |
pointResource | rules.resources | Resource points are drawn from, when the mode uses points. | ||
pointCosts | { string: number } | {} | Point cost per spell level. | |
saveDifficulty | expression | Formula for the difficulty of a save against a caster's spell. | ||
attackBonus | expression | Formula for a spell attack bonus, overriding the ordinary attack stat. | ||
concentration | object | {} | Whether holding a spell can be broken, and by what. | |
recoverOn | rules.rests[] | [] | Which rests give slots back. | |
ritualCasting | boolean | false | Whether spells marked ritual can be cast without spending a slot. | |
componentActionTypes | object | {} | Action types verbal and somatic components need free. | |
extra | { string: any } | {} | Open bag of your own data on spellcasting. |
spellcasting → concentrationrules.spellcasting.concentration
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
enabled | boolean | true | Whether concentration exists at all. | |
savingThrow | rules.savingThrows | Save rolled to keep concentration on taking damage. | ||
difficulty | expression | Difficulty of that save, as an expression. | ||
maxConcurrent | number | 1 | How many concentration spells one caster may hold. |
spellcasting → componentActionTypesrules.spellcasting.componentActionTypes
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
verbal | rules.actionTypes | Action type a verbal component occupies. | ||
somatic | rules.actionTypes | Action type a somatic component occupies. |
perceptionrules.perception
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
sightSense | rules.senses | Which sense counts as sight, and so decides what the map shows as explored. | ||
curiosityMinutes | number | 10 | How long a creature keeps walking toward something it noticed. | |
defaultStance | rules.stances | Stance a creature is in when it names none. | ||
minimumEmission | number | 0.01 | Signal below this is treated as nothing, 0 to 1. | |
maxMarksPerTile | number | 4 | How many traces one tile keeps per sense. The oldest fall off. | |
extra | { string: any } | {} | Open bag of your own data on perception. |
temperamentrules.temperament
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
roamRadius | number | 0 | How far from where it was placed it will wander. Zero stands still. | |
investigateRadius | number | How far from that spot a lead may pull it. Absent is no limit. | ||
leashRadius | number | How far it chases before turning for home. Absent is no limit. | ||
wanderChance | number | 0 | Odds it moves at all on a given idle step, 0 to 1. | |
disengageTurns | number | 0 | Rounds it stays in a fight after nobody can perceive anybody. | |
speeds | object | {} | How fast it moves for each reason it moves, as multipliers. | |
investigates | rules.senses[] | Senses it acts on, best first. Absent means all of them. | ||
followsTrails | boolean | true | Whether a trace on the ground is worth following at all. | |
notices | hostileneutralally[] | ["hostile"] | Whose presence it registers: hostile, neutral, ally. | |
extra | { string: any } | {} | Open bag of your own data on temperament. |
temperament → speedsrules.temperament.speeds
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
wander | number | 1 | Pace while wandering its own ground. Zero never wanders. | |
investigate | number | 1 | Pace while walking toward something it noticed. | |
engage | number | 1 | Pace while closing on something it means to fight. | |
returning | number | 1 | Pace while heading back to where it was placed. |
currencyrules.currency
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
name | string | "coins" | What money is called in the plural. | |
abbrev | string | "c" | Short form for tight displays. | |
allowNegative | boolean | false | Whether the purse may go into debt. |
interactionRangerules.interactionRange
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
talk | number | 2 | How many tiles away you can start a conversation. | |
reach | number | 1 | How many tiles away you can take, open, or otherwise handle a thing. |
searchrules.search
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
trapRadius | number | 2 | How many tiles a search sweeps for traps. | |
disarmReach | number | 1 | How many tiles away a trap can be disarmed from. |
dispositionBandsrules.dispositionBands
| Field | Type | Req | Default | What it does |
|---|---|---|---|---|
id | id | yes | Id of the band. | |
atLeast | number | Lowest disposition in this band. The highest matching band wins. | ||
stance | allyneutralhostile | yes | How a creature in this band treats the party. |