No active sessions yet.

No games yet.

No conversations yet.

No characters yet.

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.