No active sessions yet.

No games yet.

No conversations yet.

No characters yet.

Expressions

The $ object, and how a rule reads the world before it decides anything.

An expression is a small piece of JavaScript that reads the game and gives back a value. You'll use them anywhere the editor shows a formula box: a quest condition, a damage amount, a field's maximum, a hook body.

$.stat('might') * 2 + 5

That's a complete expression. No return, no function wrapper.

Everything is on $

$ is the only thing in scope:

$.subject.name            // who this rule is about
$.subject.health          // their current hit points
$.player.fields.satiety   // a field on the host player
$.turn                    // the turn number
$.timed                   // does this world have a clock?

Reads come in two kinds:

  • Values: $.subject.health, $.stat(), $.field(), $.dial().
  • Questions: $.hasItem(), $.alive(), $.hasPlugin(). True or false.

Reading something that doesn't exist gives you undefined or null, not an error. That's the number one reason a rule silently never fires. Read Missing values.

The sandbox

Expressions run in a sandbox with a time budget:

  • An infinite loop is stopped, not hung. The turn carries on; your rule doesn't.
  • Expressions can't talk to each other. No variable survives from one rule to the next. If two rules need to share something, put it in a field.
  • An expression that throws gives nothing back, and the engine uses its default. So a broken rule looks like a rule that didn't fire, not an error message.

Dice

$.random(), $.rollDie(6) and $.pick(weights) only work in a rule body (a hook, an item rule). In a condition or an amount they return null.

The reason: conditions and amounts are worked out once per turn and reused. A roll there would be the same roll every time it was read. A body runs when things actually happen, so a roll there is a real roll.

Roll in the body, then act on it:

var rows = $.table('affixes')
var weights = {}
for (var i = 0; i < rows.length; i++) weights[rows[i].key] = rows[i].weight
var picked = $.pick(weights)
if (picked !== null) {
  $.setField({ field: 'edge', to: $.row('affixes', picked).power })
}

$.pick takes a map of key to weight (zero or less is never picked), or a plain array to pick from evenly.

A target that needs a random number, like "kill three to seven of them", should roll once when the quest opens and store the result. A gate that re-rolled every turn would never be reachable.

Next

Reading values. If you're writing hook bodies, read Rule bodies too.