No active sessions yet.

No games yet.

No conversations yet.

No characters yet.

Rule bodies

A rule body is steps and ifs, with plain JavaScript where you need it.

A rule body is a list of steps, with if where you need to branch.

if ($.player.fields.satiety <= 0) {
  if ($.dial('starvationDamagePerHour') > 0) {
    $.damage({ amount: $.dial('starvationDamagePerHour') })
  }
}

The editor shows this as visual steps or as code. They're the same rule, and editing either one edits it.

Plain JavaScript works too

Variables, loops and helper logic are fine. The editor keeps them as a block of code and runs them in the sandbox:

var starving = []
for (var i = 0; i < $.party.length; i++) {
  if ($.party[i].fields.satiety <= 0) starving.push($.party[i].name)
}
if (starving.length > 0) {
  $.narrate(starving.join(' and ') + ' can barely keep their feet')
}

There's a trade-off, and it's the one rule on this page to remember:

Inside code, only these steps exist:

  • $.damage(...)
  • $.heal(...)
  • $.adjustField(...)
  • $.setField(...)
  • $.narrate(...)
  • $.recap(...)
  • $.refuse(...)
  • $.giveItem(...)
  • $.setWorldState(...)
  • $.passTime(...)
  • $.adjustCooldown(...)

Plus $.tool(), and every read on $.

Everything else ($.applyEffect, $.spawnItem, $.veto, $.give, $.startQuest and the rest) only works as a visual step. Once a body drops into code, the rest of that block stays code, so a $.veto(...) below a var line can't run. The editor refuses the body and tells you which line.

To fix it:

  • Put steps like these above any variables or loops, or
  • Avoid the variable. Write the expression straight into the argument. Amounts (amount, by, to) and names ending in Expr (itemExpr, mobExpr) take expressions and stay steps. A conditional is fine there too:
$.adjustField({ field: 'satiety', by: -($.timed
  ? ($.event.minutes / 60) * $.dial('foodDrainPerHour')
  : $.dial('foodDrainPerTurn')) })

Inside code, setWorldState(key, value) and giveItem(name, quantity) take plain arguments; they're the code versions of $.setWorld and $.give.

Roll tables

A roll table runs one of its entries, picked by weight. Each entry's run is a body of its own, so it can hold ifs, chances and other tables:

if ($.chance(0.75)) {
  $.rollTable([
    { weight: 60, run: () => {
      $.give({ item: "Silverfin Trout" })
    } },
    { weight: 15, run: () => {
      $.give({ item: "Emerald Glimmerfish" })
    } },
  ])
}

Limits

  • A body can record at most 200 steps. Real rules record one or two; the cap exists to stop a runaway loop.
  • return ends the body early and keeps what it already did.

Next

Hooks: when a body runs.