Hooks
The moments a rule can attach to, and what each one carries.
A hook is a rule that runs when the engine does something anywhere in the world. An item rule, by contrast, runs when a player uses one specific object.
A hook has a trigger, an optional condition, and a body.
Triggers
| Trigger | Fires when | $.event carries |
|---|---|---|
onSpawnCreature |
a creature enters the world | |
onSpawnItem |
an item enters the world; the item is the subject | |
onDamage |
hit points actually drop, from any source | amount killed |
onHeal |
hit points actually rise | amount |
onDeath |
someone dies (players too), after loot and XP | |
onCombatStart |
a fight begins; subject is the location | |
onCombatRoundEnd |
a combat round closes; subject is the location | |
onEffectApplied |
an effect lands on someone | |
onAttack |
every swing, misses included | weapon weaponKey ranged ammo attacking |
onLocationEnter |
the party arrives; subject is the new location | |
onMapEdge |
the party reaches a dead end, every exit already visited | exits |
onItemUse |
an item rule runs | |
onRoll |
a skill check resolves; observe-only | passed total dc margin crit botch stat note abilityName reason |
onTurnStart |
once per actor per turn | |
onTurnEnd |
once per actor per turn | inCombat |
onTimePasses |
in-game time moves: a turn, travel, sleep | minutes resting |
onTravel |
the party covers ground | distance |
onBeforeAction |
a player tries something, before it happens | attack ranged combatAction swings stat note actionOrdinal |
A hook can also answer another plugin's event, written pluginId:eventKey, like rest:sleep.
See Cooperation.
Picking one
- Trying vs hurting.
onAttackfires on every swing.onDamagefires only when hit points move. Stamina per swing goes on the first; bleeding goes on the second. - Per turn vs per minute. For anything that ticks per character per turn, use
onTurnEnd.onTimePassesminutes can be the narrator's guess; see Minutes are not time. - The creature vs its gear. A hook writes to its subject.
onSpawnCreaturewrites to the bandit;onSpawnItemwrites to the bandit's sword. A rolled modifier or a curse on an object goes on the second. - Round vs turn. A turn is one actor; a round is everybody. Things that last "a round",
like a brace or a mark, expire on
onCombatRoundEnd. - Swinging vs swung at. A plugin's
onAttackhook runs once per swing, about the target. A character's, creature's or effect's own hook runs for whichever side it's on, and$.event.attackingsays which: true when they swung, false when they were swung at. weaponvsweaponKey.weaponis the item's name.weaponKeyis that exact object. Wear and tear goes on the key, or it lands on the spare in the pack instead of the blade in hand.ammois the ammunition the swing spent, such asArrow, and empty when it spent none.$.spawnItem({ itemExpr: $.event.ammo, at: "self" })drops the loosed arrow where the target stands.
onBeforeAction says no
It's the trigger for refusing. A refuse in it stops the action and says why.
if ($.event.attack && $.field('stamina') < 5) {
$.refuse('their arms are too heavy to lift the blade again')
}
$.event.actionOrdinal is which action this is in the turn (0 for the first), so
$.event.actionOrdinal > 0 limits a turn to one action.
onRoll only watches
An onRoll hook can write fields and nothing else. If a hook could change the roll, the roll
card couldn't explain its own number.
It's how you make something improve with use:
if ($.event.passed && $.event.margin > 5 && $.event.note === 'read') {
$.adjustField({ field: 'insight', by: 1 })
}
margin is total minus DC, negative on a failure. crit and botch read the natural die,
which is a different question from passed.
Example: a fever, in three hooks
onTimePasses: it climbs.
if ($.field('fever') > 0) {
$.adjustField({ field: 'fever', by: $.timed
? ($.event.minutes / 60) * $.dial('feverPerHour')
: $.dial('feverPerTurn') })
}
onTurnEnd: a high fever hurts.
if ($.field('fever') >= 10) {
$.damage({ amount: 1 })
}
onBeforeAction: too sick to fight.
if ($.event.attack && $.field('fever') >= 15) {
$.refuse('the fever has taken their balance; the blade will not answer')
}
Next
Conditions: gating when a hook may run.