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.