aboutsummaryrefslogtreecommitdiff
path: root/building_guide/behaviors.md
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/behaviors.md
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/behaviors.md')
-rw-r--r--building_guide/behaviors.md147
1 files changed, 139 insertions, 8 deletions
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`) |
+
---