No active sessions yet.

No games yet.

No conversations yet.

No characters yet.

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

  1. Open Plugins and create one.
  2. Declare a field. It shows up on the character sheet.
  3. Add a hook that changes it.
  4. Add something that changes it back.
  5. 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.