No active sessions yet.

No games yet.

No conversations yet.

No characters yet.

Steps

Reads are expressions; writes are steps. The verbs that change the world.

Reading the world is an expression. Changing it is a step, and a rule body is a list of steps.

$.adjustField({ field: "satiety", by: -1 })
$.damage({ amount: 3 })
$.narrate("the wound closes over")

The vocabulary

Step What it does
$.adjustField({ field, by }) Move a field by an amount
$.setField({ field, to }) Set a field to a value
$.adjustStat({ stat, by }) Move a stat by an amount
$.setStat({ stat, to }) Set a stat to a value
$.damage({ amount }) Deal damage
$.heal({ amount }) Heal
$.applyEffect({ effect }) Apply a status effect by name
$.give({ item, quantity }) Give an item
$.grantXp(n) Award experience
$.setWorldState({ key, value }) Write a world flag
$.passTime(minutes) Advance the clock
$.narrate(text) Tell the narrator something happened
$.refuse(reason) Stop the player's action
$.veto(reason) Stop one proposed event

Most steps take an optional target"subject", "player", "target" — defaulting to whoever the rule is about.

by vs to

adjustField moves a value by an amount. setField sets it to one.

$.adjustField({ field: "fever", by: 1 })   // one worse than before
$.setField({ field: "fever", to: 1 })      // exactly 1, whatever it was

Same pair for stats: adjustStat / setStat. Getting these backwards is a quiet bug — a fever that never climbs past 1 rather than one that never stops climbing.

refuse vs veto

refuse stops the action the player attempted. veto stops one specific event that was proposed.

If you are answering another plugin's event — rest:sleep, say — use veto. Using refuse there tells a player standing still that hunger clawed them out of a sleep they never started.

Narration never sees numbers

$.narrate("the fever's grip loosens")   // good
$.narrate("fever reduced by 2")         // wrong shape

The narrator is told what happened in prose, never the mechanics. Numbers, cooldowns and turn counts do not reach it — that is deliberate, and it is why the writing stays in voice. Write the sentence you want a player to read.

Zero-rate damage still costs a point

$.damage({ amount: 0 }) does not do nothing — damage floors at 1. If a dial can legitimately be tuned to zero, branch around the step rather than passing zero into it:

if ($.dial('starvationDamagePerHour') > 0) {
  $.damage({ amount: $.dial('starvationDamagePerHour') })
}

Next

Rule bodies — the syntax rules a body must obey, which are stricter than they look.