Asking questions
The true/false half of the API: $.hasItem, $.alive, $.hasPlugin and friends.
These answer yes or no. Conditions are built from them.
Inventory
$.hasItem('Rope') // any at all?
$.hasItem('Rope', 3) // at least three?
People and places
$.alive('Ironjaw') // is this NPC alive?
$.at('Ironjaw', 'the mill') // is this NPC here?
$.location.name === 'the mill' // is this happening at the mill?
$.location is the place the rule is running in: where the player is standing for an item
they use, where the event fired for an event. It is a read, so it
compares with === rather than being asked.
Names are as they appear in your game. A name that doesn't exist answers false, so a typo
reads as "no" rather than as an error. Use editor completion.
Abilities and gear
$.hasAbility('secondwind')
$.slotEmpty('offhand') // false if the body has no offhand at all
$.slotHolds('weapon', 'Iron Sword')
Other plugins
$.hasPlugin('hunger') // is that plugin installed?
$.hasField('infection', 'target') // does this entity have that field?
Any plugin can read any field, so ask first. Without the check, $.field('satiety') in a game
with no hunger plugin reads null, and your rule acts as if everyone is always starving or
never hungry, depending on which way the comparison points.
$.hasPlugin('hunger') && $.field('satiety') < 20 ? 2 : 1 // hits harder if also hungry
Time windows
$.timeBetween('20:00', '04:00') // handles midnight
An operator chosen at runtime
$.compare(actual, op, target)
For when the operator comes from data, like a quest that stores '>=' next to its threshold.
Every question
| Call | Answers |
|---|---|
$.hasItem('rope', 2) |
Whether the subject carries at least that many. |
$.delivered('Raw Copper Ore', 1) |
Quest steps only: whether the party has put at least that many in the quest-giver's hands. The giver keeps them when the step completes. |
$.carried('weight') |
The total of a field across everything carried. |
$.stats.luck |
Every stat this character has, as a map of name to value - including stats this game DECLARED itself, not just the built-in five. Read it when a rule must treat all of them alike; use $.stat(name) when you know which one you mean. It also carries each engine ROLE as an alias (might, engine:might) pointing at whichever stat claims it, so a loop over the keys sees the same value more than once. |
$.stat('might') |
A stat on the subject, read by ROLE - never by the display name, which an author can rename. |
4 + $.skill('Healing') * 3 |
A rank in a skill the game declares, 0 when untrained: the player's, or the subject's when who is "target". Damage and heal steps on a skill-tagged ability or item already scale by the user's rank; use this for an exact formula of your own. |
$.field('satiety', 'player') |
One declared field, on the subject or whoever who names - "player", "target", or "location" for the place this is happening in. |
$.compare(actual, op, target) |
Compare two values with an operator chosen at runtime. |
$.alive('Ironjaw') |
Whether a named entity is alive. |
$.at('Ironjaw', 'the mill') |
Whether a named entity is at a location. |
$.itemAt('House Fire', 'the mill') |
Whether an item is lying at a location - on the ground or fixed in place, not carried. |
$.timeBetween(from, to) |
Whether the clock now reads between two times. |
$.hasAbility('secondwind') |
Whether the subject has an ability. |
$.slotEmpty('offhand') |
Whether a slot exists on this body AND is empty. False for a slot the body does not have, since a missing hand cannot be freed up. |
$.slotHolds('weapon', 'Iron Sword') |
Whether one named item is worn in a particular slot. |
$.hasPlugin('hunger') |
Whether another plugin is installed - ask before reading its fields. |
$.hasField('infection', 'target') |
Whether a field exists, so a missing one is not read as a real zero. |
$.dial('foodDrainPerHour') |
One of your own plugin's dials. Never freeze a dial's value as a literal. |
$.table('conditions') |
Every row of one of your own plugin's tables, as an array. An undeclared name reads as an empty table, so a loop over it does nothing. |
$.row('conditions', 'snow').becomes |
One row from your own table, found by its first column, or null when nothing matches. Read a cell off it by column key. |
$.random() < 0.25 |
A random number from 0 up to (but not including) 1. ONLY inside a script body - in a condition or an amount expression it answers null, because those are cached and a cached roll is the same roll every time. Roll in the body and pass the result to a step. |
$.rollDie(6) |
A whole number from 1 to faces, like one die. Script bodies only, for the reason $.random() gives. Null if faces is not at least 1. |
$.pick($.row('seasons', 'winter').weights) |
Choose one at random. Given a weights map - the shape a table's weights column holds - each key's odds are its number over the total, and a key weighted zero or below is never chosen. Given a plain array, picks one evenly. Returns the chosen KEY (or array entry), or null when nothing can be chosen. Script bodies only. Prefer picking over a table's rows rather than over names typed into the code: the table's rows are validated and a typo in a literal is not. |