No active sessions yet.

No games yet.

No conversations yet.

No characters yet.

Reading values

Paths and readers that give you a number or a name: $.subject, $.stat(), $.field().

These give you a value to compare, add up, or pass to a step.

Stats: by role, not by name

$.stat('might')

Stats are read by role. A game can call its strength stat "Might", "Brawn" or "Thew", and $.stat('might') reads it in all three. Reading by display name ($.stat('brawn')) breaks the day someone renames it.

A stat the subject doesn't have reads 0.

5 + $.stat('might') * 1.5    // a heavy weapon that hits harder in strong hands

Fields

A field is a value a plugin declared on something: satiety, infection, mana.

$.field('satiety')               // on the subject
$.field('satiety', 'player')     // on the host player
$.field('infection', 'target')   // on whoever was aimed at
$.field('corruption', 'location')  // on the place itself

A field nobody has reads null, not 0. That difference decides whether your rule fires. See Missing values.

Carried totals

$.carried('weight')

Adds up a field across everything the subject carries. This is how encumbrance works.

Dials: your tuning numbers

$.dial('foodDrainPerHour')

Reads one of your plugin's dials, the numbers an author can tune in your plugin's panel.

Never copy a dial's value into your code as a number. 0.4 works until someone changes the dial, and then two numbers disagree and nothing errors. See Formulas and dials.

Tables: your plugin's own rows

When your plugin owns a list (tiers, a roster, a matchup chart), declare a table and read it through $:

$.table('conditions')                 // every row, as an array
$.row('conditions', 'snow')           // the row whose first column is 'snow', or null
$.row('conditions', 'snow').tempBand  // one cell

A misspelled table name reads as an empty table, so a loop over it silently does nothing.

Table or field?

  • A field lives on the entity and is edited on that entity's sheet. A location added later gets it automatically. Use it when the value belongs to the thing.
  • A table lives in your plugin's panel. A location added later is missing from it until someone adds a row. Use it for your system's own vocabulary.

Whichever you pick, read from where you wrote. Filling in a table and then reading $.location.fields.something gives you a system that's fully set up and does nothing.

Time

$.event.minutes   // how long this stretch took
$.timed           // whether the world has a clock

In a game without a clock, minutes is the narrator's guess and swings from 3 to 22 for similar turns. Price by the hour only when there's a real clock:

$.timed ? $.dial('drainPerHour') * ($.event.minutes / 60) : $.dial('drainPerTurn')

See Minutes are not time.

Everything you can read

Path Answers
$.subject The entity this rule is about.
$.subject.name The subject's name.
$.subject.kind What the subject is: 'player', 'npc', 'creature' or 'object'.
$.subject.location Where the subject is.
$.subject.health Current health.
$.subject.maxHealth Maximum health.
$.subject.dead Whether the subject is dead.
$.subject.fields The subject's declared fields, by key.
$.subject.bonds The subject's NPC bonds.
$.source Who caused it - attacker, user, emitter.
$.player The acting player: whoever uses the item or casts, or the subject when it is a player, else the host. Use $.party for everyone.
$.player.name The acting player's name: whoever uses the item or casts, the host when nobody in particular acts.
$.player.health The acting player's health.
$.player.fields The acting player's declared fields.
$.party Every player - host and guests.
$.location The place this is happening in. Printing it gives the name, so "at " + $.location still reads as the place.
$.location.name The place's name.
$.location.fields The place's declared number fields, by key - everything a plugin declared with trait "location". A place nobody has written to reads empty, never zero.
$.location.tags The place's declared text fields, by key.
$.world World flags.
$.here What is in the current location.
$.exits Where you can go from here in ONE hop, as { name: distance }. Undirected, so an edge drawn either way appears. Object.keys($.exits).length === 0 is how a rule asks "is this the edge of the map" - which is what a generator watches for. Empty in a game that never drew a map.
$.items Everything the subject is carrying, as name -> how many. Use it when the NAMES matter rather than one you already know: Object.keys($.items) lists them, $.items["Rope"] is how many of that one.
$.equipped What the wearer has in each slot, by the slot names THIS game declares. Null means the slot is empty; a slot this body does not have is absent entirely, so ask with $.slotEmpty rather than testing for null yourself.
$.mobs Creatures present.
$.game Every item, character, location, mob, ability and effect in the game, full authored records included, populated only inside a declared action's afterRoll body. Search it by name: $.game.filter(e => e.name === 'Rusty Key')[0]. Each entry has name, kind, description, mechanics (compiled item rules), quests (an NPC's authored steps), costs (an ability's resource costs) and refs (every other name this one references - search every OTHER entry's refs for a name to find what points AT it).
$.turn The turn number.
$.combat.active Whether a fight is running right now.
$.combat.round Which round the fight is on, counting from 1. Zero when no fight is running.
$.combat.allies How many on the player's side are still standing. Zero outside a fight.
$.combat.enemies How many on the enemy side are still standing. Zero outside a fight.
$.quests Every quest by name. Each holds status ("inactive", "active", "completed" or "failed"), step (which step they are ON, counting from 0) and steps (how many the quest has). Ask about being DONE with status === "completed" rather than by comparing the numbers: a finished quest advances step past the last index, so step equals steps there rather than steps - 1. To ask whether they are on the final step of an active quest, step === steps - 1.
$.visited Names of every location the party has been to. $.visited.indexOf($.location) === -1 is how a rule asks "is this their first time here".
$.timeMinutes Minutes on the world clock. Advances once per tick.
$.minutesPassed Minutes on the world clock since the game began.
$.minutesPerDay Minutes in one day under this world's calendar (Earth: 1440).
$.timed Whether this world has a clock. Charge per hour where true, per turn where false - in a clockless game $.event.minutes is the narrator's estimate, not a measurement.
$.setting The game's setting.
$.killCount Kills so far.
$.minted What the tool just made, inside that tool's own body. {} everywhere else, so a read there is undefined rather than an error.
$.minted.name The name of the thing just minted. A mint invents the name, so this is the only way a body can place, spawn or grant what it made - $.spawnItem({ itemExpr: $.minted.name }).
$.event What the firing trigger carried. {} outside a hook, so a read there is undefined rather than an error.
$.item The item in play. Null outside the item-use path.
$.item.name The item's name.
$.item.state The item's state.
$.item.fields The item's declared fields.
$.target The aimed-at entity.
$.target.name The target's name.
$.target.state The target's state.
$.target.fields The target's declared fields.

What's on $.event depends on the trigger. See Hooks.