Skip to content

Timers

WAGE has two timing tools: the tick condition (periodic) and set_state_delayed (a one-shot delay). Combined with a counter in state, they cover most timed mechanics.

Bomb Tag counts seconds the bomb has been held, then explodes. Increment on a tick, then react when the counter crosses a threshold.

# +1 every second while a player holds the bomb and is alive.
- id: bomb_tick
when:
kind: and
children:
- { kind: state_equals, who: any, key: hasBomb, value: true }
- { kind: state_equals, who: same, key: alive, value: true }
- { kind: tick, everyMs: 1000 }
do:
- { kind: increment_state, target: same, key: bombTick, by: 1 }
# At 15 seconds it explodes — eliminate the holder, pass the bomb on.
- id: bomb_explodes
when:
kind: and
children:
- { kind: state_equals, who: any, key: hasBomb, value: true }
- { kind: state_equals, who: same, key: alive, value: true }
- { kind: compare, who: same, op: gte, left: { ref: same.state.bombTick }, right: 15 }
do:
- { kind: set_state, target: same, key: alive, value: false }
- { kind: set_state, target: same, key: hasBomb, value: false }
- kind: assign_state_random # hand the bomb to a random survivor
assigns: [{ key: hasBomb, value: true }, { key: bombTick, value: 0 }]
filters: [{ key: alive, value: true }, { key: it, value: false }]
notify: { type: toast, text: "You have the bomb!" }

Source: apps/wage-engine/src/games/bomb_tag/game.json. Reset the counter to 0 whenever the bomb changes hands so each holder gets a full clock.

set_state_delayed flips a key after a wait — great for a grace period or a timed unlock. Run it from onStart for an opening delay, or from a rule.

# Release everyone from a locked start 3 seconds in.
onStart:
- { kind: set_state_delayed, who: any, key: locked, value: false, delayMs: 3000 }
# In a rule: re-arm an ability 5 seconds after use.
do:
- { kind: set_state, target: same, key: ready, value: false }
- { kind: set_state_delayed, target: same, key: ready, value: true, delayMs: 5000 }

Send a countdown event at start so phones show “3… 2… 1… Go!”:

onStart:
- { kind: send_event, to: any, event: { type: countdown, from: 3 } }

For a fixed match length, don’t build it from ticks — set countdownSeconds and the engine ends the game when it expires.