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

FieldTypeReqDefaultWhat it does
attributesobject[]yesWhat a character is made of. At least one is required.
resourcesobject[]yesPools that go up and down. Hit points and focus are both just resources.
derivedStatsobject[][]Numbers computed from attributes, gear, and conditions.
damageTypesobject[][]The kinds of damage that exist. Resistance and immunity are written against these.
conditionsobject[][]States a creature can be in, with what they do while they last.
actionTypesobject[][]The action economy. Each type declares how many a creature gets per turn.
equipmentSlotsobject[][]Where gear goes, and how many items each place holds.
itemPropertiesobject[][]Reusable tags on items that carry stat modifiers.
masteryTiersobject[][]Named skill bands, so a requirement can ask for adept rather than rank 5.
restsobject[][]The ways a party recovers, and what each costs in time.
resolutionobject{}The dice convention. What a check rolls, what crits, how results round.
progressionobjectyesThe level curve and what each level grants. Required.
savingThrowsobject[][]The saves that exist, each governed by an attribute.
sizesobject[][]Creature sizes, with the space they take and how far they reach.
creatureTypesobject[][]Broad kinds of creature, for gating and description.
sensesobject[][]How creatures notice each other. Sight, scent, hearing, or anything you invent.
stancesobject[][]Postures a creature can take, trading speed for concealment or the reverse.
movementModesobject[][]Ways of moving, each with a base speed and a terrain multiplier.
languagesobject[][]Languages that exist. Creatures list which they speak.
alignmentsobject[][]Moral or factional labels. Carried and gateable, never enforced.
opportunitiesobject[][]Reactions the rules grant everyone, such as a parting blow.
coverTypesobject[][]Degrees of cover and what each is worth on defence.
spellcastingobject{}Slots or points, concentration, components, and rituals.
perceptionobject{}Which sense counts as sight, and the defaults perception runs on.
temperamentobject{}What creatures do unprompted: wandering, giving chase, and giving up.
currencyobject{}What money is called and whether it can go negative.
vitalResourcerules.resourcesyesThe resource whose floor means death. Required.
initiativeStatrules.derivedStatsDerived stat rolled for turn order. Without one, order is by id.
defaultSizerules.sizesSize given to a creature that names none.
defaultMovementModerules.movementModesMovement mode used when a creature names none.
interactionRangeobject{}How close you must be to talk to someone or reach a thing.
searchobject{}How far a search finds traps and how close disarming needs you.
dispositionBandsobject[][{"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

FieldTypeReqDefaultWhat it does
ididyesId of the attribute, used as actor.attr.<id>.
namestringyesDisplay name.
abbrevstringyesShort form for tight displays, one to six characters.
descriptionstring""What this attribute covers. Author and player facing.
minnumber1Lowest value character creation and effects may take it to.
maxnumber20Highest value it may reach.
defaultnumber10Starting value before creation spends any points.
modifierexpressionyesFormula turning the raw value into a modifier. Sees only value.

resourcesrules.resources

FieldTypeReqDefaultWhat it does
ididyesId of the resource, used as actor.res.<id>.
namestringyesDisplay name.
descriptionstring""What the pool represents.
maxexpressionyesFormula for the ceiling. May read attributes, modifiers, and level.
minexpression0Formula for the floor. Reaching it runs onDepleted.
initialexpressionFormula for the starting value. Defaults to the maximum.
restoreOnShortRestnumber0Fraction of the maximum a short rest returns, 0 to 1.
restoreOnLongRestnumber1Fraction of the maximum a long rest returns, 0 to 1.
onDepletedeffect[][]What happens at the floor. Death is these effects on the vital resource.

derivedStatsrules.derivedStats

FieldTypeReqDefaultWhat it does
ididyesId of the stat, used as actor.derived.<id>.
namestringyesDisplay name.
descriptionstring""What the number means.
formulaexpressionyesExpression over attributes, modifiers, level, and resources.

damageTypesrules.damageTypes

FieldTypeReqDefaultWhat it does
ididyesId of the damage type.
namestringyesDisplay name.
descriptionstring""What this kind of harm is.
tagsid[][]Labels a damage interaction can except on, such as silvered.

conditionsrules.conditions

FieldTypeReqDefaultWhat it does
ididyesId of the condition, used as actor.conditions.<id>.
namestringyesDisplay name.
descriptionstring""What being in this state means.
tagsid[][]Free labels for grouping and gating.
stackingrefreshextendstackignore"refresh"What a second application does. Refresh, extend, stack, or ignore.
defaultDurationexpressionRounds it lasts when the applying effect names no duration.
onApplyeffect[][]Effects run once, when it lands.
onTickeffect[][]Effects run at the start of each of the sufferer's turns.
onExpireeffect[][]Effects run once, when it ends.
modifiers{ id: expression }{}Derived stat adjustments while it holds. Magnitude is in scope.
preventsid[][]Action type ids this forbids. A bare id, not a checked reference.
suppressesSensesid[]Senses this shuts off, unless the sense itself ignores this condition.
swingsobjectWhich way the dice lean while this is on you. Prefer it or modifiers, not both.
concealsIdentitybooleanfalseMakes a witness less able to name who did the deed.
savingThrowobjectA save to shrug it off, and when that save is offered.
impliesid[][]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

FieldTypeReqDefaultWhat it does
ownAttacksadvantagedisadvantageHow attack rolls made by the afflicted creature lean.
attacksAgainstSelfadvantagedisadvantageHow attack rolls made against the afflicted creature lean.
checksadvantagedisadvantageHow the afflicted creature's ability checks lean.
savesadvantagedisadvantageHow the afflicted creature's saving throws lean.

conditions → savingThrowrules.conditions.savingThrow

FieldTypeReqDefaultWhat it does
saverules.savingThrowsyesWhich saving throw resists it.
difficultyexpressionyesDifficulty of that save, as an expression.
timingonApplyendOfTurnstartOfTurnboth"endOfTurn"When the save is offered. On landing, on turn ends, or both.

actionTypesrules.actionTypes

FieldTypeReqDefaultWhat it does
ididyesId of the action type, such as action or bonus.
namestringyesDisplay name.
descriptionstring""What this slice of a turn is for.
perTurnnumber1How many a creature gets each turn.

equipmentSlotsrules.equipmentSlots

FieldTypeReqDefaultWhat it does
ididyesId of the slot, named by an item's slot field.
namestringyesDisplay name.
capacitynumber1How many items fit here at once.

itemPropertiesrules.itemProperties

FieldTypeReqDefaultWhat it does
ididyesId of the property, named by an item's properties list.
namestringyesDisplay name.
descriptionstring""What carrying this property means.
modifiers{ id: expression }{}Derived stat adjustments an item with this property grants.
attackStatsrules.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

FieldTypeReqDefaultWhat it does
ididyesId of the tier, asked for by a requirement as minTier.
namestringyesDisplay name.
descriptionstring""What this level of skill means.
atRanknumberyesSkill rank at which the tier is reached.

restsrules.rests

FieldTypeReqDefaultWhat it does
ididyesId of the rest, named by a rest action and by spellcasting recovery.
namestringyesDisplay name.
descriptionstring""What this kind of rest is.
durationnumber60Minutes of world time it consumes.
kindshortlong"short"Whether resources use their short rest or long rest fraction.
effectseffect[][]Extra effects run on finishing, beyond resource restoration.
interruptChancenumber0Chance per rest that something interrupts it, 0 to 1.

resolutionrules.resolution

FieldTypeReqDefaultWhat it does
checkDicedice"1d20"The notation every check rolls.
advantageDicedice"2d20kh1"Notation rolled instead when a check has advantage.
disadvantageDicedice"2d20kl1"Notation rolled instead when a check has disadvantage.
swingStackingcancelnet"cancel"What a roll does with more than one swing: cancel them out, or go by the count.
criticalSuccessAtnumber20Natural roll at or above which a check crits. Null for no crits.
criticalFailureAtnumber1Natural roll at or below which a check fumbles. Null for no fumbles.
criticalScopeattacksavecheck[]["attack","save","check"]Which kinds of roll can crit or fumble: attack, save, check.
criticalDamageMultipliernumber2What a critical hit multiplies damage by.
saveSuccessMultipliernumber0.5Damage kept on a successful save when the ability says half.
passiveBasenumber10Number a passive score adds its modifier to instead of rolling.
opposedModepassivecontested"passive"Whether an opposed check rolls both sides or rolls against a passive score.
damageRoundingfloorroundceil"round"How fractional damage resolves to a whole number.
reputationRoundingfloorroundceiltrunc"trunc"How fractional reputation change resolves to a whole number.
attackBonusexpressionWhat a weapon attack adds. Omitted, just the attribute modifier, which never grows.
defaultDifficultynumber12Difficulty used when a check names none.
difficulties{ id: number }{}Named difficulties, so content can ask for hard rather than 18.

progressionrules.progression

FieldTypeReqDefaultWhat it does
maxLevelnumber20Level the curve stops at. Experience past it is kept but grants nothing.
levelsobject[]yesOne entry per level, in order, with its cost and what it gives.
proficiencyexpressionFormula for the proficiency bonus over actor.level.
proficiencyRanknumber1Skill rank a proficiency counts as when a requirement asks.
levelVitalityobject{}How the vital resource grows on gaining a level.

progression → levelsrules.progression.levels

FieldTypeReqDefaultWhat it does
levelnumberyesWhich level this entry describes.
xpRequirednumberyesTotal experience needed to reach it.
grantseffect[][]Effects run on each character crossing this level.

progression → levelVitalityrules.progression.levelVitality

FieldTypeReqDefaultWhat it does
policyrollaveragemaxnone"roll"Roll the die, take its average, take its maximum, or grant nothing.
dieclasssize"class"Whether the die comes from the character's class or their size.
bonusexpression0Expression added on top of the die, per level.

savingThrowsrules.savingThrows

FieldTypeReqDefaultWhat it does
ididyesId of the save, named by abilities and conditions.
namestringyesDisplay name.
descriptionstring""What this save resists.
attributerules.attributesyesAttribute whose modifier the save adds.
defaultDifficultyexpressionDifficulty used when the thing calling for the save names none.
extra{ string: any }{}Open bag of your own data on this save.

sizesrules.sizes

FieldTypeReqDefaultWhat it does
ididyesId of the size.
namestringyesDisplay name.
spacenumber5Distance units the creature occupies. Converted to tiles by the engine.
reachnumber5Distance units the creature can reach to strike.
carryMultipliernumber1Not read by the engine. Build encumbrance from actor.carried and a derived stat.
hitDiediceVitality 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

FieldTypeReqDefaultWhat it does
ididyesId of the creature type.
namestringyesDisplay name.
descriptionstring""What this kind of creature is.
tagsid[][]Free labels for grouping and gating.
extra{ string: any }{}Open bag of your own data on this creature type.

sensesrules.senses

FieldTypeReqDefaultWhat it does
ididyesId of the sense, used as a key in emits and in a creature's senses.
namestringyesDisplay name.
descriptionstring""What this sense picks up.
defaultRangenumber60Distance units a creature perceives with it unless it says otherwise.
ignoresid[][]Not read by the engine yet. No condition currently suppresses a sense.
propagationlinefield"line"Whether the signal travels in a straight line or fills the space.
blockedByopaqueimpassablenothing"opaque"What stops it. Opaque terrain, anything impassable, or nothing.
falloffclifflinear"cliff"Whether strength drops off a cliff at range or fades with distance.
lingerMinutesnumber0How long a trace stays after whatever left it has gone. Scent, not sight.
spreadPerMinutenumber0How fast it travels, in tiles a minute. Zero arrives at once.
spreadRetentionnumber0.5Signal left at the far edge of reach once it has spread that far.
rememberMinutesnumber0How long a creature holds on to something it noticed with this sense.
impressionTextKeynarrative.textGrammarText pool for a clear impression.
faintImpressionTextKeynarrative.textGrammarText pool for a weak impression.
emptyTextKeynarrative.textGrammarText pool for sensing and finding nothing.
thresholdsobject{}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

FieldTypeReqDefaultWhat it does
detectnumber0Strength at which the creature knows something is there, 0 to 1.
investigatenumber0Strength at which it goes to look, 0 to 1.
aggronumber0Strength at which it treats the source as a target, 0 to 1.

stancesrules.stances

FieldTypeReqDefaultWhat it does
ididyesId of the stance.
namestringyesDisplay name.
descriptionstring""What moving this way means.
speedMultipliernumber1What it does to movement speed.
emits{ rules.senses: number }{}Signal strength this stance gives off, per sense.
concealedBycontent.skillsSkill whose rank makes this stance quieter.
concealmentPerPointnumber0Signal removed per rank of that skill.
extra{ string: any }{}Open bag of your own data on this stance.

movementModesrules.movementModes

FieldTypeReqDefaultWhat it does
ididyesId of the mode, such as walk, swim, or fly.
namestringyesDisplay name.
defaultSpeednumber30Distance units per turn for a creature that names no speed of its own.
terrainMultipliernumber1What this mode does to terrain movement costs.
fallsWhenDisabledbooleanfalseNot 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

FieldTypeReqDefaultWhat it does
ididyesId of the language.
namestringyesDisplay name.
descriptionstring""Who speaks it and where.
scriptstring""Not read by the engine. The writing system, for flavour.
exoticbooleanfalseNot 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

FieldTypeReqDefaultWhat it does
ididyesId of the alignment.
namestringyesDisplay name.
abbrevstring""Short form for tight displays.
extra{ string: any }{}Open bag of your own data on this alignment.

opportunitiesrules.opportunities

FieldTypeReqDefaultWhat it does
ididyesId of the opportunity.
namestringyesDisplay name.
descriptionstring""What this reaction is and why everyone has it.
onmoveAwaycastSpellrangedAttackstandUpbeHitallyHitcustom"moveAway"What provokes it. Leaving reach, casting, shooting, standing, being hit, or custom.
eventstringEvent name to watch, when on is custom.
actionTyperules.actionTypesAction type it spends. Without one it is free.
usecontent.abilitiesAbility the reacting creature uses. Without one, only effects run.
requirespredicatePredicate that must hold for it to trigger. Not the requirement object.
effectseffect[][]Effects run when it triggers.
usesPerRoundnumber1How many times one creature may take it each round.
extra{ string: any }{}Open bag of your own data on this opportunity.

coverTypesrules.coverTypes

FieldTypeReqDefaultWhat it does
ididyesId of the cover type.
namestringyesDisplay name.
defenceBonusnumber0Added to the defended stat when the target has this cover.
blocksTargetingbooleanfalseTrue 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

FieldTypeReqDefaultWhat it does
modenoneslotspointsboth"none"Whether casting spends slots, spends points, both, or is off.
maxSpellLevelnumber9Highest spell level the game has.
slotTable{ string: number[] }{}Slots per spell level, keyed by caster level.
pointResourcerules.resourcesResource points are drawn from, when the mode uses points.
pointCosts{ string: number }{}Point cost per spell level.
saveDifficultyexpressionFormula for the difficulty of a save against a caster's spell.
attackBonusexpressionFormula for a spell attack bonus, overriding the ordinary attack stat.
concentrationobject{}Whether holding a spell can be broken, and by what.
recoverOnrules.rests[][]Which rests give slots back.
ritualCastingbooleanfalseWhether spells marked ritual can be cast without spending a slot.
componentActionTypesobject{}Action types verbal and somatic components need free.
extra{ string: any }{}Open bag of your own data on spellcasting.

spellcasting → concentrationrules.spellcasting.concentration

FieldTypeReqDefaultWhat it does
enabledbooleantrueWhether concentration exists at all.
savingThrowrules.savingThrowsSave rolled to keep concentration on taking damage.
difficultyexpressionDifficulty of that save, as an expression.
maxConcurrentnumber1How many concentration spells one caster may hold.

spellcasting → componentActionTypesrules.spellcasting.componentActionTypes

FieldTypeReqDefaultWhat it does
verbalrules.actionTypesAction type a verbal component occupies.
somaticrules.actionTypesAction type a somatic component occupies.

perceptionrules.perception

FieldTypeReqDefaultWhat it does
sightSenserules.sensesWhich sense counts as sight, and so decides what the map shows as explored.
curiosityMinutesnumber10How long a creature keeps walking toward something it noticed.
defaultStancerules.stancesStance a creature is in when it names none.
minimumEmissionnumber0.01Signal below this is treated as nothing, 0 to 1.
maxMarksPerTilenumber4How many traces one tile keeps per sense. The oldest fall off.
extra{ string: any }{}Open bag of your own data on perception.

temperamentrules.temperament

FieldTypeReqDefaultWhat it does
roamRadiusnumber0How far from where it was placed it will wander. Zero stands still.
investigateRadiusnumberHow far from that spot a lead may pull it. Absent is no limit.
leashRadiusnumberHow far it chases before turning for home. Absent is no limit.
wanderChancenumber0Odds it moves at all on a given idle step, 0 to 1.
disengageTurnsnumber0Rounds it stays in a fight after nobody can perceive anybody.
speedsobject{}How fast it moves for each reason it moves, as multipliers.
investigatesrules.senses[]Senses it acts on, best first. Absent means all of them.
followsTrailsbooleantrueWhether a trace on the ground is worth following at all.
noticeshostileneutralally[]["hostile"]Whose presence it registers: hostile, neutral, ally.
extra{ string: any }{}Open bag of your own data on temperament.

temperament → speedsrules.temperament.speeds

FieldTypeReqDefaultWhat it does
wandernumber1Pace while wandering its own ground. Zero never wanders.
investigatenumber1Pace while walking toward something it noticed.
engagenumber1Pace while closing on something it means to fight.
returningnumber1Pace while heading back to where it was placed.

currencyrules.currency

FieldTypeReqDefaultWhat it does
namestring"coins"What money is called in the plural.
abbrevstring"c"Short form for tight displays.
allowNegativebooleanfalseWhether the purse may go into debt.

interactionRangerules.interactionRange

FieldTypeReqDefaultWhat it does
talknumber2How many tiles away you can start a conversation.
reachnumber1How many tiles away you can take, open, or otherwise handle a thing.

dispositionBandsrules.dispositionBands

FieldTypeReqDefaultWhat it does
ididyesId of the band.
atLeastnumberLowest disposition in this band. The highest matching band wins.
stanceallyneutralhostileyesHow a creature in this band treats the party.