Plugins
Bundle fields, hooks and dials into a system you can switch off, share and reuse.
A plugin bundles fields, dials, hooks and events into one system you can switch off, edit, share, and add to other games.
Hunger, rest, stamina, mana, encumbrance and NPC bonds are all plugins. None of them are engine code. Open one in code view for a complete working example.
The rule
Deleting a plugin must leave a working game.
If your system can't be switched off cleanly, it's engine code in disguise. Design for it from the start: what does a game without your plugin look like? That's the same question as what happens when someone uninstalls it.
What a plugin can declare
| Part | What it is |
|---|---|
| Fields | Values that live on things: a meter with tiers and a HUD bar, or a plain number. |
| Dials | Tuning numbers, editable in the plugin's panel. |
| Tables | Lists of records your rules read with $.table() and $.row(). |
| Hooks | The behavior. |
| Events | Moments you let other plugins veto. |
| Sections | A question the plugin adds to the model's turn, or prose it contributes. |
| Seams | The one thing that replaces an engine calculation instead of adding to it. |
| Scene layers | What the plugin draws over the location: particles, fog, a color grade, a wash, a sound. |
| Tools | Generators that create new content during play. |
Drawing on the scene
A scene layer puts something on screen. It names a world-state key your hooks write and one of your tables. The value at that key picks a row, and the row's presentation columns are what the scene shows:
| Column type | What it draws |
|---|---|
| Particles | Something falling or drifting, tuned against a live preview. |
| Grade | How the scene is colored: dimmer, drained, warmer, hazier. |
| Wash | Water streaking down the view. |
| Fog | Drifting fog, how thick and how much it veils. |
A row can also carry label and icon (shown in the scene's readout), sound and soundVolume
(an ambient loop), and overcast (dims the sky). A row leaves out whatever it doesn't draw.
Weather is two layers: the sky reads WEATHER from its conditions table, and fog reads
WEATHER_FOG from its fog table. Open it in code view to see them:
scene([
{ stateKey: "WEATHER", table: "conditions", outdoor: true },
{ stateKey: "WEATHER_FOG", table: "fog", outdoor: true }
])
Mark a layer outdoor when a roof should keep it out: in a location tagged indoor it isn't drawn,
and its sound is heard muffled. A value with no row draws nothing, so "none" needs no row.
Asking the narrator
A question (a section, in the plugin panel) adds something to the model's turn. After the
turn is narrated, for example, it can ask "did the player accept the bargain?", offer fixed
Choices, and run statements on the answer as $.answer.<key>.
Act on the answer with plain branches, one per choice, such as
if ($.answer.choice === 'accepted') { $.setWorld({ key: 'bargain', value: 'accepted' }) }.
Give every question an Only ask when gate. An ungated question is asked on every turn of every session, so it costs tokens everywhere. A gated one is asked only while its gate holds: while a choice is still open, while the person who offers it is present.
Your first plugin
- Open Plugins and create one.
- Declare a field. It shows up on the character sheet.
- Add a hook that changes it.
- Add something that changes it back.
- Play a few turns.
Then read Designing a plugin.
Sharing
Publish from your library. Other authors add it from the Assets step, which makes a copy. They can edit freely without affecting you, and name clashes are handled for you.