Scripted Room Hooks
Status: Implemented Date: 2026-03-29
Hooks are scripted triggers attached to rooms. When a player performs an action in a room (entering, looking, killing a mob), hooks fire automatically, checking conditions and executing actions. They enable one-time discoveries, conditional messages, rewards, traps, and dynamic world events without writing Hoon.
Structure
Each hook has three parts:
{
"trigger": "on-enter",
"conditions": [ ... ],
"actions": [ ... ]
}
A room can have up to 20 hooks. Each hook can have up to 5 conditions and 10 actions. Conditions are AND’d together – all must pass for actions to fire.
Triggers
| Trigger | Fires when… |
|---|---|
on-enter | Player moves into the room (any direction, recall) |
on-look | Player types look with no arguments |
on-kill | Player kills a mob in the room |
on-use | (reserved, not yet wired) |
on-talk | (reserved, not yet wired) |
Conditions
All conditions must be true for the hook to fire. If a hook has no conditions, it always fires.
| Type | Fields | Description |
|---|---|---|
flag | flag, op | Check if a player flag is set or not-set |
has-item | item-id | Player has an item with this template ID |
level-gte | value | Player level >= value |
level-lte | value | Player level <= value |
kills-gte | value | Player total kills >= value |
random | chance | Random chance out of 100 (e.g. 25 = 25%) |
room-flag | flag | A room flag matches (e.g. dark, safe) |
Player Flags
Flags are per-player, per-session strings stored in a set. They persist for the session and reset on disconnect. Use them for one-time events:
{
"conditions": [{"type": "flag", "flag": "saw-ghost", "op": "not-set"}],
"actions": [
{"type": "message", "text": "A spectral figure materializes before you..."},
{"type": "set-flag", "flag": "saw-ghost"}
]
}
The player sees the ghost once. On subsequent visits, the saw-ghost flag is set, so the hook doesn’t fire.
Actions
Actions execute in order when all conditions pass.
| Type | Fields | Description |
|---|---|---|
message | text | Send a system message to the triggering player |
broadcast | text | Send a message to everyone in the room |
set-flag | flag | Set a player flag |
clear-flag | flag | Remove a player flag |
give-gold | amount | Give gold to the player |
take-gold | amount | Remove gold (floors at 0) |
give-xp | amount | Award XP |
give-item | item-id | Create an item instance and add to inventory |
take-item | item-id | Remove first item matching template ID |
teleport | room | Move the player to a different room |
spawn-mob | mob-id, room | Spawn a mob (room 0 = current room) |
heal | hp, mana, moves | Restore vitals (capped at max) |
damage | amount | Deal damage (floors at 1 HP) |
add-effect | name, duration | Apply a named status effect to the player (e.g. “wet”, “burning”). Duration is in regen ticks. |
transform-items | effect | Transform inventory items that have a matching transforms entry on their template for this effect |
Examples
One-time discovery with gold reward
{
"trigger": "on-enter",
"conditions": [
{"type": "flag", "flag": "crypt-looted", "op": "not-set"}
],
"actions": [
{"type": "message", "text": "Beneath a loose stone you find a pouch of coins."},
{"type": "give-gold", "amount": 50},
{"type": "set-flag", "flag": "crypt-looted"}
]
}
Level-gated area message
{
"trigger": "on-enter",
"conditions": [
{"type": "level-gte", "value": 10}
],
"actions": [
{"type": "message", "text": "The runes on the archway glow, acknowledging your power."}
]
}
Random ambush on entry
{
"trigger": "on-enter",
"conditions": [
{"type": "random", "chance": 30}
],
"actions": [
{"type": "broadcast", "text": "Shadows coalesce into a dark figure!"},
{"type": "spawn-mob", "mob-id": 15, "room": 0}
]
}
Kill reward with item
{
"trigger": "on-kill",
"conditions": [
{"type": "kills-gte", "value": 5},
{"type": "flag", "flag": "wolf-hunter", "op": "not-set"}
],
"actions": [
{"type": "message", "text": "The wolves fear you now. You find a fang amulet among the remains."},
{"type": "give-item", "item-id": 42},
{"type": "set-flag", "flag": "wolf-hunter"}
]
}
Trap room with healing fountain
[
{
"trigger": "on-enter",
"conditions": [],
"actions": [
{"type": "damage", "amount": 10},
{"type": "message", "text": "Poison gas seeps from the walls! You take damage."}
]
},
{
"trigger": "on-look",
"conditions": [{"type": "flag", "flag": "found-fountain", "op": "not-set"}],
"actions": [
{"type": "message", "text": "You notice a small fountain of clear water hidden in an alcove."},
{"type": "heal", "hp": 30, "mana": 20, "moves": 0},
{"type": "set-flag", "flag": "found-fountain"}
]
}
]
Environmental effect with item transformation
A waterfall room that makes the player wet and transforms items:
{
"trigger": "on-enter",
"conditions": [],
"actions": [
{"type": "message", "text": "You pass through the cascading waterfall. You're soaked to the bone."},
{"type": "add-effect", "name": "wet", "duration": 10},
{"type": "transform-items", "effect": "wet"}
]
}
This requires item templates to have a transforms field. For example, crackers (template 42) with "transforms": {"wet": 43} become soggy crackers (template 43) when the player walks through the waterfall. The “wet” effect lasts 10 regen ticks. Items without a “wet” transform entry are unaffected.
The item templates would look like:
{"id": 42, "name": "Crackers", "transforms": {"wet": 43}, ...}
{"id": 43, "name": "Soggy Crackers", ...}
Burning hallway with damage-over-time effect
{
"trigger": "on-enter",
"conditions": [],
"actions": [
{"type": "message", "text": "Flames lick at you from vents in the walls!"},
{"type": "damage", "amount": 15},
{"type": "add-effect", "name": "burning", "duration": 3}
]
}
Adding Hooks to Rooms
Hooks are defined in the hooks array on each room in the JSON area file:
{
"id": 6,
"name": "Dead Garden",
"description": "Withered plants and cracked soil...",
"sector": "field",
"exits": {"south": 1},
"flags": [],
"hooks": [
{
"trigger": "on-enter",
"conditions": [{"type": "flag", "flag": "garden-visited", "op": "not-set"}],
"actions": [
{"type": "message", "text": "The dead vines shudder as you enter..."},
{"type": "set-flag", "flag": "garden-visited"}
]
}
]
}
Rooms without hooks use an empty array: "hooks": []
Hooks can also be edited via the level editor’s admin API (/mud/api/admin/save-room).