aboutsummaryrefslogtreecommitdiff
path: root/building_guide
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-08 19:59:14 -0400
committerhistoria <[not public]>2026-07-08 19:59:14 -0400
commit09d325dcf5e779eab5550d3fd3377bde50101428 (patch)
treea433be903aabbf1d2eadce2aacdac12a9eb8dde0 /building_guide
parent9184377301c2604e003f36426788c032fb0ca524 (diff)
downloadthehouseoficarus-09d325dcf5e779eab5550d3fd3377bde50101428.tar.gz
feat: unify on use, on look, and on kill. all support same conditions/actions now.
Diffstat (limited to 'building_guide')
-rw-r--r--building_guide/admin.md4
-rw-r--r--building_guide/behaviors.md147
-rw-r--r--building_guide/conditions.md5
-rw-r--r--building_guide/doors.md4
-rw-r--r--building_guide/hidden_objects.md4
-rw-r--r--building_guide/objects.md116
-rw-r--r--building_guide/triggers.md18
7 files changed, 222 insertions, 76 deletions
diff --git a/building_guide/admin.md b/building_guide/admin.md
index af2184c..d66aabe 100644
--- a/building_guide/admin.md
+++ b/building_guide/admin.md
@@ -251,8 +251,8 @@ the game server and is configured in `config.yaml` under `admin_http` (plain HTT
|------|-----|-------------|
| Map | `/` | Interactive SVG map showing rooms on a 3D grid. Zoom/pan, click rooms to edit, create/delete rooms and exits, relink exits. Up/down links shown alongside horizontal connections. |
| Items | `/editor/items` | Full CRUD editor with sections for equipment (type/slot/attack/defense/other), tool, craft (type/level/XP/ingredients/stations/tool/steps), firemaking, farming, potions, and requirements. Undo/redo supported. |
-| Objects | `/editor/objects` | CRUD editor with sections for gather (tools/drops/success formula), use (message/wait/consumes), talk (visual talk tree editor), safespot, steal, use_interactions, and on_look. |
-| Mobs | `/editor/mobs` | CRUD for mob definitions — stats, drops, talk, behavior, assassin/steal/task fields. |
+| Objects | `/editor/objects` | CRUD editor with sections for gather (tools/drops/success formula), use (message/wait/consumes), talk (visual talk tree editor), safespot, steal, on_use (interactions — see Effects help in-card), on_look (interactions, same row UI), and the raw-file editor covers on_use/on_look + on_kill on mobs. |
+| Mobs | `/editor/mobs` | CRUD for mob definitions — stats, drops, talk, shop, behavior, assassin/steal/task fields, plus on_kill interaction cards. |
| Drops | `/editor/drops` | CRUD for shared drop tables (gem tables, bird's nests, etc.). |
| Hazards | `/editor/hazards` | CRUD for hazard definitions. |
| Techs | `/editor/techs` | CRUD for technology definitions (buffs, drain rates, categories). |
diff --git a/building_guide/behaviors.md b/building_guide/behaviors.md
index 1857681..3b7d769 100644
--- a/building_guide/behaviors.md
+++ b/building_guide/behaviors.md
@@ -266,9 +266,13 @@ talk:
| `teleport` | Moves the player to a room ID. |
| `heal` | Restores that many hitpoints. |
| `credits` | Credits charged (negative) or awarded (positive). |
-| `reputation_cost` | Deducts reputation from `assassin_reputation` flag before other actions. |
| `aps_node` | Marks this room's APS node as unlocked. |
+The full effect vocabulary (used by all interaction types and on_enter/trigger
+steps) additionally includes `message`, `broadcast`, `broadcast_global`,
+`spawn_mob`, `despawn_mob`, and `delay` — see [interaction
+reference](#interaction-reference) below.
+
> **Planned (not yet implemented):** `assign_task`, `skip_task`, `extend_task`, and `sawmill` are under design and will be added in a future update.
All fields in a single action are processed together — give an item, take an item, set flags,
@@ -521,19 +525,26 @@ talk:
A specialty shop that only buys back its own stock sets `buys_anything: false`.
-### Object Interactions (levers, switches, gates)
+### Object Interactions (levers, switches, gates) — `on_use` and `on_look`
+
+Interactions are the unified, conditional action system shared by objects
+(`on_use`, `on_look`), mobs (`on_kill`), exit traversal
+(`on_traverse`), on_enter steps, room/global triggers, talk nodes, and talk
+options. Each interaction has an optional condition, an optional message,
+and an optional `action` (the full effect vocabulary). When a list of
+interactions is evaluated, the first whose condition passes wins and fires.
-Interaction configs go under the `use_interactions:` key on objects.
-Entries with no `item` field are bare interactions triggered by "use"
-or "push"/"pull":
+On objects, `on_use` runs when the player types `use <obj>` (bare) or
+`use <item> on <obj>` (item-specific). Entries with no `item_id` are bare (fire when `use <obj>` is typed) —
+triggered by `use <obj>`:
```yaml
name: iron gate
hidden: true
description: "A heavy iron gate set into the north wall."
-use_interactions:
+on_use:
- condition:
- flag: gate_open
+ global_flag: gate_open
value: true
not: true
message: "You push the heavy iron gate open."
@@ -545,7 +556,7 @@ use_interactions:
Item-specific interaction:
```yaml
name: bookshelf
-use_interactions:
+on_use:
- item_id: dusty_tome
message: "The bookshelf slides aside, revealing a secret passage!"
action:
@@ -553,4 +564,124 @@ use_interactions:
secret_passage_open: true
```
+`on_look` runs after the description is shown when the player types
+`look <obj>`. It is a list of interactions (same shape), with `item_id`
+acting as a *has_item* gate: an entry with an `item_id` only fires if the
+player currently carries that item in their inventory (empty = always fires
+on look).
+typically empty:
+
+```yaml
+name: sign
+on_look:
+ - set_player_flags:
+ read_sign: true
+```
+
+---
+
+### Interaction Reference
+
+The `Interaction` struct is the shared per-entry shape:
+
+| Field | Type | Description |
+| ----------- | ---------- | --------------------------------------------------------------- |
+| `item_id` | string | `on_use`: required item id (empty = bare `use <object>`). `on_look`: only fires if you carry this item. `on_kill`: only fires if you wield this weapon (main_hand or off_hand) when the mob is defeated. |
+| `condition` | Condition | Optional gate (see [conditions](conditions.md)) |
+| `message` | string | Message shown to the player when this entry fires |
+| `action` | StepAction | Optional effects — the full superset below |
+
+The `StepAction` superset is the universal effect container used by every
+interaction type, talk node actions, on_enter steps, and trigger steps. The
+inline-only `NodeAction` fields are the subset historically used by talk
+nodes; the additional sequence-only fields (`message`, `broadcast`,
+`broadcast_global`, `spawn_mob`, `despawn_mob`, `delay`) are available on
+all of them but primarily meaningful for on_enter/triggers (inline callers
+may use `broadcast` to announce to the room — handy for `on_kill`
+announcements).
+
+| Field | Type | Description |
+| ------------------ | -------------- | -------------------------------------------------------------------- |
+| `set_global_flags` | map[string]any | Set global flags (shared by all players; cascades other triggers) |
+| `set_player_flags` | map[string]any | Set player flags (per-character, saved to YAML; cascades) |
+| `give_item` | string | Give one unit of an item to inventory |
+| `take_item` | string | Remove one unit of an item from inventory |
+| `teleport` | int | Move player to a room ID; runs `look` + `on_enter` of the destination |
+| `heal` | int | Restore hitpoints (clamped to MaxHP) |
+| `credits` | int | Add (positive) or deduct (negative) credits (gated by affordability) |
+| `aps_node` | bool | Mark the current room as a discovered APS node on the datapad |
+| `message` | string | Direct message to the player (template vars `%p`/`%v` supported) |
+| `broadcast` | string | Announce to all in the room (`%p`/`%v` substituted per recipient) |
+| `broadcast_global` | string | Announce to all online (`%p`/`%v` substituted per recipient) |
+| `spawn_mob` | string/map | Spawn a transient mob — bare string (id) or full [config](#spawn-mob-config) |
+| `despawn_mob` | string | Despawn all transient mobs of this id (optionally owner-filtered) |
+| `delay` | int | Ticks to wait before this step fires (on_enter/triggers only) |
+| `condition` | Condition | Per-step gate (on_enter steps and trigger steps; evaluated before firing) |
+
+### Mob Interactions (On Kill)
+
+Mobs can define `on_kill` (fires when this mob is defeated — either by a
+combat kill or by a `kind: task` mob's HP draining to zero, the
+"completion" of the work). It is additive — standard loot `drops` still
+hit the ground first, then the first matching interaction fires. An
+entry with an `item_id` only fires if the player is wielding that item
+in a weapon-hand slot (main_hand or off_hand) at the moment of the kill.
+
+```yaml
+name: boss
+combat: ...
+on_kill:
+ - condition:
+ global_flag: boss_quest_active
+ message: "The boss crumbles to dust. The Guardian Stone reverberates!"
+ action:
+ set_global_flags:
+ boss_slain: true
+ broadcast_global: "%p has slain the World Boss!"
+ spawn_mob: boss_add
+ - item_id: dragon_slayer
+ action:
+ give_item: boss_heart
+ set_global_flags:
+ dragon_slain: true
+```
+
+```yaml
+name: reactor panel
+task: ...
+on_kill:
+ - message: "With a final burst of effort, the panel snaps into place."
+ action:
+ set_global_flags:
+ reactor_repaired: true
+ set_player_flags:
+ repaired_reactor: true
+```
+
+### Spawn Mob Config
+
+For transient mob spawning (in `spawn_mob:` fields), pass either a bare
+string (the mob ID) or a map with these fields:
+
+```yaml
+spawn_mob: rat
+```
+
+```yaml
+spawn_mob:
+ id: boss_add
+ owner_only: true
+ despawn_on_leave: true
+ despawn_rooms: [100, 101]
+ despawn_ticks: 30.0
+```
+
+| Field | Description |
+| ----------------- | ------------------------------------------------------------------------ |
+| `id` | Mob ID to spawn (required when a map) |
+| `owner_only` | If true, the spawn is private to the triggering player |
+| `despawn_on_leave`| Trigger-spawned mob fades after leaving the owner's room (grace window) |
+| `despawn_rooms` | List of rooms where the spawn survives without ticking the despawn timer |
+| `despawn_ticks` | Despawn countdown in ticks (float OK; rounded probabilistically via `engine.ToTicks`) |
+
---
diff --git a/building_guide/conditions.md b/building_guide/conditions.md
index acfdf57..2fb3d7a 100644
--- a/building_guide/conditions.md
+++ b/building_guide/conditions.md
@@ -1,8 +1,9 @@
## Conditions Reference
Conditions are used in talk option guards, talk node conditions, exit gates,
-on-enter scripts, use_interactions checks, room descriptions, object
-descriptions, and trigger value matching.
+on-enter scripts, on_use / on_look / on_kill interactions,
+exit on_traverse interactions, room descriptions, object descriptions, and
+trigger value matching.
### Simple conditions
diff --git a/building_guide/doors.md b/building_guide/doors.md
index 358001f..c987d0f 100644
--- a/building_guide/doors.md
+++ b/building_guide/doors.md
@@ -10,9 +10,9 @@ A button in room 3 opens a door in room 7. Anyone can press it. Once pressed, th
```yaml
name: stone button
hidden: true
-use_interactions:
+on_use:
- condition:
- flag: secret_door_open
+ global_flag: secret_door_open
not: true
message: "You press the stone button. You hear grinding stone in the distance."
action:
diff --git a/building_guide/hidden_objects.md b/building_guide/hidden_objects.md
index b1ed7b4..1866d67 100644
--- a/building_guide/hidden_objects.md
+++ b/building_guide/hidden_objects.md
@@ -9,9 +9,9 @@ Objects with `hidden: true` don't appear in the room's object listing. Players d
name: stone lever
hidden: true
description: "A cleverly concealed lever behind a loose stone."
-use_interactions:
+on_use:
- condition:
- flag: secret_passage_open
+ global_flag: secret_passage_open
value: true
not: true
message: "You pull the lever. A grinding sound echoes from the east."
diff --git a/building_guide/objects.md b/building_guide/objects.md
index a8877a7..db72cf3 100644
--- a/building_guide/objects.md
+++ b/building_guide/objects.md
@@ -49,8 +49,8 @@ objects:
description: |-
Conditional or multi-line descriptions work exactly like file objects.
on_look:
- set_player_flags:
- 1001_look_sign: true
+ - set_player_flags:
+ 1001_look_sign: true
```
- **Identity comes from `name`.** Internally the object's id is the name, normalized
@@ -69,7 +69,7 @@ objects:
- Local objects support only the **passive subset**: `name`, `aliases`, `color`, `hidden`,
`inroom_description`, `description` (including conditional variants), and `on_look`.
- Interactable / stateful behavior (`gather`, `talk`, `use`, `safespot`, `steal`, `guard_mob`,
- `removal_item`, `use_interactions`, craft stations) **must** be a standalone object file;
+ `removal_item`, `on_use`, craft stations) **must** be a standalone object file;
startup validation errors if those appear locally.
- Local objects are re-read from the room file on every access, so edits take effect
immediately (file objects are cached after first load).
@@ -137,14 +137,14 @@ Color accepts xterm-256 indices with optional modifiers (`bold`, `dim`, `underli
and gradients (`g:C4,52`). In ANSI mode, extended colors downgrade to the nearest
ANSI color.
-Object interaction (gate, lever — uses `use_interactions:` key):
+Object interaction (gate, lever — uses `on_use:` key):
```yaml
name: iron gate
hidden: true
description: "A heavy iron gate set into the north wall."
-use_interactions:
+on_use:
- condition:
- flag: gate_open
+ global_flag: gate_open
value: true
not: true
message: "You push the heavy iron gate open."
@@ -173,35 +173,40 @@ talk:
- text: "\"Goodbye.\""
```
-On-look action (runs when a player examines an object with `look <name>`):
+On-look interaction (runs when a player examines an object with `look <name>`):
```yaml
name: sign
aliases: [notice, board]
description: "A wooden signpost with faded writing."
on_look:
- set_player_flags:
+ - set_player_flags:
read_sign: true
```
-`on_look` fires the action AFTER showing the object's description. It uses the same
-`NodeAction` type as talk nodes — supports `set_player_flags`, `set_global_flags`,
-`give_item`, `take_item`, `teleport`, `heal`, `cost`, and everything else in the
-[node action reference](behaviors.md#node-action-reference).
+`on_look` is a list of interactions (same shape as `on_use`). The first entry
+whose `item_id` and `condition` pass wins, and fires AFTER the object's
+description is shown. An entry with an `item_id` only fires if the player
+currently carries that item in their inventory (empty `item_id` = always
+fires on look). It uses the same `interaction` shape as `on_use` — supports
+`condition`, `message`, and a full `action` (`set_global_flags`,
+`set_player_flags`, `give_item`, `take_item`, `teleport`, `heal`, `credits`,
+`aps_node`, `broadcast`, `broadcast_global`, `spawn_mob`, `despawn_mob`,
+`delay`), per the [interaction reference](behaviors.md#interaction-reference).
See the [Talk section of behaviors](behaviors.md#talk-dialog-trees) for the full
dialog tree format. See [Stealable Objects](#stealable-objects) for theft mechanics.
---
-## Use Interactions
-
-Objects can define `use_interactions` to handle when a player uses a specific item on the object. Each interaction can check conditions, show a message, and execute actions — using the same condition and action primitives as the talk system.
+## Interactions (On Use / On Look)
-Entries are checked top-to-bottom; the first match with a passing condition wins.
+Objects can define `on_use` and/or `on_look` to react to player actions. Both take a
+list of interactions (entries are checked top-to-bottom; the first whose
+`condition` passes wins — one fires per use/look).
Simple message (no action):
```yaml
name: anvil
-use_interactions:
+on_use:
- item_id: silver_bar
message: "You should use this with a mold at a furnace."
- item_id: gold_bar
@@ -211,10 +216,10 @@ use_interactions:
Puzzle interaction (take item, set flag):
```yaml
name: crystal slot
-use_interactions:
+on_use:
- item_id: crystal_key
condition:
- flag: crystal_inserted
+ global_flag: crystal_inserted
message: "The crystal key is already in the slot."
- item_id: crystal_key
message: "You insert the crystal key into the slot. It clicks into place."
@@ -226,7 +231,7 @@ use_interactions:
Quest item exchange:
```yaml
-use_interactions:
+on_use:
- item_id: ancient_scroll
condition:
player_flag: quest_started
@@ -239,37 +244,46 @@ use_interactions:
temple_door_open: true
```
-### UseInteraction Fields
-
-| Field | Type | Description |
-| ----------- | ---------- | ------------------------------------------------ |
-| `item_id` | string | Item ID that triggers this interaction |
-| `condition` | Condition | Optional condition (same as exits/talk/use_interactions) |
-| `message` | string | Message shown to the player |
-| `action` | NodeAction | Optional actions (same as talk node actions) |
-
-### Available Actions (same as talk)
-
-| Field | Type | Description |
-| ------------------ | -------------- | ---------------------------------- |
-| `set_global_flags` | map[string]any | Set global flags (shared) |
-| `set_player_flags` | map[string]any | Set player flags (per-character) |
-| `give_item` | string | Give an item to inventory |
-| `take_item` | string | Remove an item from inventory |
-| `teleport` | int | Move player to a room ID |
-| `heal` | int | Restore hitpoints |
-
-### Available Conditions (same as exits/talk)
-
-| Field | Description |
-| ------------- | -------------------------------- |
-| `global_flag` | Global flag check |
-| `player_flag` | Per-character flag check |
-| `has_item` | Inventory item check |
-| `value` | Expected value for flag checks |
-| `not` | Invert the condition |
-| `all_of` | All sub-conditions must pass |
-| `any_of` | Any sub-condition must pass |
+### Interaction Fields
+
+| Field | Type | Description |
+| ----------- | ---------- | --------------------------------------------------------------- |
+| `item_id` | string | `on_use`: required item id (empty = bare `use <object>`). `on_look`: only fires if you carry this item. (Mobs' `on_kill`: only fires if you wield this weapon in main_hand or off_hand.) |
+| `condition` | Condition | Optional condition (same as exits/talk/on_enter/triggers) |
+| `message` | string | Message shown to the player when this entry fires |
+| `action` | StepAction | Optional actions (see [interaction reference](behaviors.md#interaction-reference)) |
+
+### Available Actions (same superset as on_enter steps/triggers/talk)
+
+| Field | Type | Description |
+| ------------------ | -------------- | ----------------------------------------------------- |
+| `set_global_flags` | map[string]any | Set global flags (shared by all players) |
+| `set_player_flags` | map[string]any | Set player flags (per-character, saved to YAML) |
+| `give_item` | string | Give an item to inventory (1 unit) |
+| `take_item` | string | Remove an item from inventory (1 unit) |
+| `teleport` | int | Move player to a room ID |
+| `heal` | int | Restore hitpoints (clamped to MaxHP) |
+| `credits` | int | Add (positive) or deduct (negative) credits |
+| `aps_node` | bool | Mark current room as a discovered APS node |
+| `broadcast` | string | Announce to all in the room (uses `%p`, `%v`) |
+| `broadcast_global` | string | Announce to all online (uses `%p`, `%v`) |
+| `spawn_mob` | string/map | Spawn a transient mob (`id` or full [config](behaviors.md#spawn-mob-config)) |
+| `despawn_mob` | string | Despawn all transient mobs of this id |
+| `message` | string | Direct message to the player (also valid here) |
+| `delay` | int | Ticks to wait before this step (only meaningful in on_enter/triggers) |
+
+### Available Conditions (same as exits/talk/on_enter/triggers)
+
+| Field | Description |
+| ------------- | ------------------------------------------------------- |
+| `global_flag` | Global flag check |
+| `player_flag` | Per-character flag check |
+| `has_item` | Inventory item check |
+| `min_credits` | Minimum credits |
+| `value` | Expected value for flag checks |
+| `not` | Invert the condition |
+| `all_of` | All sub-conditions must pass |
+| `any_of` | Any sub-condition must pass |
---
diff --git a/building_guide/triggers.md b/building_guide/triggers.md
index 0d227bd..69cd3d1 100644
--- a/building_guide/triggers.md
+++ b/building_guide/triggers.md
@@ -39,13 +39,13 @@ and the object are cleanly separated. The sign is a local object in room `1001`:
objects:
- name: sign
on_look:
- set_player_flags:
- 1001_look_sign: true
+ - set_player_flags:
+ 1001_look_sign: true
```
This separation is deliberate. The object sets flags. The trigger watches flags.
-Any system that sets a player flag (`on_look`, talk nodes, on-enter steps, exits,
-use interactions) can activate a trigger watching that flag.
+Any system that sets a player flag (`on_look`, `on_use`, `on_kill`, talk nodes,
+on-enter steps, exit `on_traverse`) can activate a trigger watching that flag.
---
@@ -396,8 +396,8 @@ advances a numeric flag through stages. The last stage spawns a boss.
# data/objects/unique/5001_body.yaml
name: body
on_look:
- set_player_flags:
- investigation: 1
+ - set_player_flags:
+ investigation: 1
```
**Step 2: Blood trail in room 5002** — room trigger fires on value 1
@@ -504,12 +504,12 @@ All of these paths activate triggers:
| Source | Example |
|---|---|
-| Object `on_look` | `look sign` sets `1001_look_sign: true` |
+| Object `on_look` / `on_use` | `look sign` sets `1001_look_sign: true` |
+| Mob `on_kill` | Killing a boss sets `boss_slain: true` |
| Talk node actions | NPC sets `quest_started: true` after accepting |
| Talk option actions | Player selects a choice that sets a flag |
| On-enter steps | Room entry sets `1001_welcome: true` |
-| Exit traversal | Walking through an exit sets `boarded_shuttle: true` |
-| Use interactions | `push button` sets `gate_open: true` |
+| Exit `on_traverse` | Walking through an exit sets `boarded_shuttle: true` |
| Trigger steps | One trigger chain-sets a flag for another trigger |
---