Builder's Manual · Chapter 2

How the Character Sheet Thinks

The character schema has one design rule: store decisions; derive everything else. A sheet stores the six base ability scores, level and experience, references to species, class, subclass, background, feats, and gear, current-state counters (hit points, slots used, conditions, exhaustionLevel) — and computes the other 114 fields.

The derivation chain

  • Each final ability score is min(20, base + feat increases + attuned-item overrides) — in this revision the background's increases arrive via its Origin-feat pipeline and the ASI feats, so base means the raw rolled score. Modifiers, saves, and all 18 skills derive from there, reading skillProficiencies for proficiency and Expertise.
  • armorClass reads the equipped armor file's acBase, addDexterity, and dexterityCap, adds shield, magic bonuses, and miscArmorBonus, and falls back to unarmored math — including class unarmored defenses.
  • Attack linesmainHandAttackBonus, mainHandDamageDice, and the off-hand set — key off the weapon file's finesse and ranged flags and magic bonus. The weapon's mastery property rides along for the GM to apply.
  • Spell slots derive from casterLevelceil(level × casterProgression − 0.01) so 2024 half-casters round up (a level 5 Paladin has 2nd-level slots) — with Warlock Pact Magic on its own computed track.
  • Level gating is a formula idiom: classFeaturesLevel120 and the subclass fields (levels 3–20 — nothing earlier exists in this revision) read featuresLevelN off the linked files; the layout shows each block only when level qualifies. A character levels up by changing one number.

Aggregation by shared field names

The sheet never knows which feat or relic you took — it sums every instance of shared field names across the feats array and three guarded attunedItem slots: strengthIncreasecharismaIncrease, acBonus, initiativeBonus, speedBonus, hpBonus, hpBonusPerLevel, saveBonusAll, plus score-override fields for Ogre-Power-style items. Give any feat or magic item those fields and it wires itself into every derived number. That is the whole integration contract — @Missing file and @Missing file are the worked examples.

The creation flow

The character type also carries the guided creation flow — 68 screens walking a player from biography through class, subclass, fighting styles, spell picks, background, and equipment to a finished level-5 hero. Its option screens hold references into the content folders, which is the sharpest gotcha in the project: if you copy this project's types into another project, every option's referenceId still points at this project's files and must be remapped. Edit the flow in the app or with care; it is data on the type, pushed with the type.

Platform limits that shaped this type

A type holds at most 200 top-level fields (this one sits at 195 — nest display-only fields into objects, as coins, deathSaves, personality, and skillProficiencies already are); formula nesting caps at depth 64 (split ternary tables into tier formulas); reference-picker filters only work on top-level fields — which is why preparedSpellsLevel19 live at the top, each filtered to spells of its level on the character's class. Schema edits push with craft push --include-types (unscoped) after craft check; the server validates against every existing file and names each record a change would break.

Manual updated Jul 29, 2026.