Building an app with OCF
These guides are for people building apps that use OCF characters: a VTT, a character builder, a campaign manager, a Discord bot, a game server. They explain how to load packs, store a character, show a sheet, change it, roll for it and upgrade it, using the reference engine.
The specification defines the formats and the engine calls for people implementing them. These guides cover using them. When a guide and the spec disagree, the spec wins.
Parts of the engine interface marked PROVISIONAL in the spec may still change.
Your app doesn’t implement the rules
Section titled “Your app doesn’t implement the rules”The most important idea in OCF is the split between the engine and your app:
The engine knows the rules. The app owns the experience.
You never write a game’s math. Your app doesn’t know that a 5E Strength modifier is
floor((score - 10) / 2), that Mage Armor competes with Unarmored Defense, or that a FitD
roll of 6 is a full success. The packs say that, and the engine works it out. Your app asks the
engine questions and shows the answers.
| The engine does | Your app does |
|---|---|
| Computes every value, with a breakdown of where it came from | Stores characters, however it likes |
| Says which choices are pending and which options are eligible | Decides whether to ask the player or pick the recommended one |
| Applies changes, checking them against the rules | Decides who may change what, and when |
| Builds rolls, does the dice math, proposes the resulting changes | Decides who rolls the dice and how they look, and applies the changes |
| Upgrades saved characters to new pack versions | Decides when to upgrade, and shows the player what changed |
| Returns keys, codes and data | Turns them into text in the player’s language |
| Never tracks time | Turns temporary effects (Bless, Poisoned) on and off |
So “implementing characters” in your app means four things: storing a file, calling the engine, rendering what it returns, and routing changes back through it.
The loop
Section titled “The loop”Almost every OCF app runs the same loop:
- Load the packs a character uses into a ruleset, once.
- Call
computeSheetand render the result. - When the player does something, turn it into changes (or run an action, which
proposes changes) and call
applyChanges. - Save the new character file and go back to step 2.
The character file only ever holds base state: the inputs, owned items and picks. Everything
your UI shows comes from computeSheet, so the sheet can never disagree with the rules.
The guides
Section titled “The guides”Read them in order the first time.
Start here
Section titled “Start here”- Quick start: load a pack, compute a sheet, apply a change, in about twenty lines.
- Implementing OCF: the view from above: how much of OCF your app needs, level by level, and where the engine runs, with Realms of Shod as a worked example.
- Apps not written in JavaScript: ports, the test suite, and running the reference engine from another language.
Showing characters
Section titled “Showing characters”- Packs and rulesets: where packs come from, load order, homebrew, pinned versions and caching.
- Storing characters: the character file, IDs, your own data in
extensions, change logs, undo and sync. - Showing a sheet: reading
computeSheet, breakdowns, display hints, competing options and rules issues. - Text and translation: turning keys and codes into text in the player’s language.
- Showing text: a helper that turns engine output into finished text: prompts, options, issues, rolls and dice.
Changing characters
Section titled “Changing characters”- Changing characters: the change types, errors and rules issues, strict mode, damage and resistance.
- Building characters: character creation, choices,
listOptions, level-ups and items. - Upgrading characters: moving a character to a new pack version and showing what changed.
Playing
Section titled “Playing”- Rolling dice: actions, checkpoint policies, your own dice, paused actions and logs.
- Other characters: attacks on a target, monsters and NPCs, effects cast by one character on another, linked sheets such as a FitD crew.
Two kinds of app
Section titled “Two kinds of app”- A game-specific app (a 5E builder) can refer to fields and content by ID:
5e-srd-5.1:combat.ac,5e-srd-5.1:classes.fighter. IDs are permanent and never reused, so this is safe. Hand-design the sheet and let the engine fill it in. - An any-game app (a VTT) can’t know any IDs ahead of time. It builds its sheet from the
pack’s display hints and its actions and choices
from what
computeSheetlists. This is more work up front, and any pack works afterwards, homebrew included.
Most apps end up in between: a hand-designed sheet for the games they care about most, and a generic one for the rest.