aboutsummaryrefslogtreecommitdiff
path: root/building_guide
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-25 19:37:20 -0400
committerhistoria <[not public]>2026-06-25 19:37:20 -0400
commitc55d0e4150b23f2c5c9f96bbc3d4dc2fc6dbaa36 (patch)
treed1c02acea2b4c8d0f672c1539cfdb373b6272ed0 /building_guide
parent068ce514ea3eebdc42b595c631b4b00ce4594577 (diff)
downloadthehouseoficarus-c55d0e4150b23f2c5c9f96bbc3d4dc2fc6dbaa36.tar.gz
feat: yaml conversation trees more robust
Diffstat (limited to 'building_guide')
-rw-r--r--building_guide/behaviors.md170
-rw-r--r--building_guide/construction.md2
-rw-r--r--building_guide/mobs.md39
-rw-r--r--building_guide/objects.md15
-rw-r--r--building_guide/quests.md3
5 files changed, 176 insertions, 53 deletions
diff --git a/building_guide/behaviors.md b/building_guide/behaviors.md
index 438e859..a2c1f89 100644
--- a/building_guide/behaviors.md
+++ b/building_guide/behaviors.md
@@ -3,7 +3,7 @@
Behaviors are **inline configs** placed directly inside object YAML (`gather:`, `talk:`,
`use:`, `safespot:`) or mob YAML (`talk:`). Each section below shows the keys you can use under each behavior type.
-The examples below are object/mob files; remember **the filename is the ID** — don't include an `id:` field (see `objects.md` / `mobs.md`).
+The examples below are object/mob files; remember the filename is the ID for these.
### Gather (mining, fishing, woodcutting)
@@ -183,15 +183,16 @@ toggle is on, the output includes the XP gain: `(+37xp wct)`.
### Talk (dialog trees)
-Talk configs go under the `talk:` key on objects or mobs. Full conversation with
-conditions, actions, and player flag tracking:
+Talk configs go under the `talk:` key on objects or mobs. A conversation is a set of named
+**nodes**, each with a message, optional action, optional auto-advance target, and choices
+for the player.
```yaml
name: Guard
talk:
nodes:
start:
- message: "\"Halt! This area is restricted.\""
+ message: "\"Halt! This area is restricted.\" The guard eyes you suspiciously."
options:
- text: "\"What's behind that gate?\""
goto: about_gate
@@ -205,16 +206,15 @@ talk:
player_flag: got_pass
value: true
- text: "\"Goodbye.\""
- end: true
+ # no goto = end conversation
about_gate:
- message: "\"Bring me some copper ore and I'll stamp you a pass.\""
+ message: "\"Supplies. Weapons.\" He shifts his weight. \"Bring me some copper ore and I'll stamp you a pass.\""
action:
set_player_flags:
talked_to_guard: true
options:
- text: "\"I'll be back.\""
- end: true
- text: "\"I have some right here.\""
goto: trade_ore
condition:
@@ -229,40 +229,57 @@ talk:
got_pass: true
options:
- text: "\"Thanks.\""
- end: true
has_pass:
- message: "\"Alright, I'll open the gate for you.\""
+ message: "\"Alright, I'll open the gate.\""
action:
set_flags:
gate_open: true
options:
- text: "\"Thanks.\""
- end: true
```
+#### TalkNode fields
+
+| Field | Type | Description |
+|---|---|---|
+| `message` | string or list | NPC dialogue. May be a single string or a list of strings (pick one at random). |
+| `action` | NodeAction | Fires when the node is entered (give items, set flags, etc). |
+| `options` | []TalkOption | Player choices. If empty and `next` is set, auto-advances. |
+| `next` | string | Node ID to auto-advance to when there are no visible options. |
+
+#### TalkOption fields
+
+| Field | Type | Description |
+|---|---|---|
+| `text` | string | Player-facing choice text. |
+| `goto` | string | Node ID to navigate to if this choice is selected. Omit to end the conversation. |
+| `condition` | Condition | Only show this option if the condition passes. |
+| `action` | NodeAction | Fires when this option is selected, BEFORE navigating to `goto`. |
+
#### Node action reference
| Field | Effect |
|---|---|
-| `set_flags` | Sets world flags (global, shared by all players) |
-| `set_player_flags` | Sets player-local flags (per-character, quest progress) |
-| `give_item` | Gives an item to the player's inventory |
-| `take_item` | Removes an item from the player's inventory |
-| `teleport` | Moves the player to a room ID |
-| `heal` | Restores that many hitpoints |
-| `cost` | Credits charged for the action |
-| `shop` | Opens a buy/sell shop interface (see Shop section below) |
-| `assign_task` | Assigns a random assassin task to the player based on their assassin level |
-| `skip_task` | Cancels current assassin task, costs 30 reputation, resets streak |
-| `extend_task` | Adds 50% more kills to current task, costs 30 reputation |
-| `reputation_cost` | Deducts reputation from the player's `assassin_reputation` flag (fails node if insufficient) |
-| `sawmill` | Opens sawmill plank conversion interface |
-
-All fields in a single action are processed together — you can give an item, take an item,
-set flags, and heal all in one node.
-
-Example — quest completion:
+| `set_flags` | Sets world flags (global, shared by all players). |
+| `set_player_flags` | Sets player-local flags (per-character, quest progress). |
+| `give_item` | Gives an item to the player's inventory. |
+| `take_item` | Removes an item from the player's inventory. |
+| `teleport` | Moves the player to a room ID. |
+| `heal` | Restores that many hitpoints. |
+| `cost` | Credits charged for the action. |
+| `shop` | Opens a buy/sell shop interface. See Shop section below. |
+| `assign_task` | Assigns a random assassin task based on assassin level. |
+| `skip_task` | Cancels current assassin task, costs 30 reputation, resets streak. |
+| `extend_task` | Adds 50% more kills to current task, costs 30 reputation. |
+| `reputation_cost` | Deducts reputation from `assassin_reputation` flag before other actions. |
+| `sawmill` | Opens sawmill plank conversion interface. |
+| `aps_node` | Marks this room's APS node as unlocked. |
+
+All fields in a single action are processed together — give an item, take an item, set flags,
+and heal in one node.
+
+Example — quest completion with multiple actions:
```yaml
action:
take_item: dragon_head
@@ -274,10 +291,85 @@ action:
teleport: 1
```
+#### Option-level actions
+
+Actions can be placed directly on options. The action fires when the player selects that
+choice, BEFORE navigating to `goto`. This eliminates needing a separate "action node" for
+simple transactions:
+
+```yaml
+nodes:
+ start:
+ message: "Welcome! Houses are 10 credits. Interested?"
+ options:
+ - text: "Yes, I'll buy one."
+ action:
+ cost: 10
+ set_player_flags:
+ owns_house: true
+ goto: purchased
+ condition:
+ player_flag: owns_house
+ not: true
+ - text: "No thanks."
+ purchased:
+ message: "Excellent! The plot is yours."
+ options:
+ - text: "Thanks!"
+ goto: start
+```
+
+If an option has both an `action` and a `goto`, the action runs first, then the player
+navigates to the target node (which may also have its own action, fired on entry).
+
+#### Randomized messages
+
+`message` accepts either a plain string or a list. A list picks one entry at random each
+time the node is visited:
+
+```yaml
+nodes:
+ greeting:
+ message:
+ - "\"Hello, traveller.\""
+ - "\"Ah, you again.\""
+ - "\"A visitor! Pull up a chair.\""
+ - "\"Back so soon?\""
+ options:
+ - text: "\"Hello.\""
+```
+
+#### Linear auto-advance
+
+When a node has no options (or all its options are hidden by conditions) and `next` is set,
+the conversation automatically advances to the target node. This creates dialogue chains
+without prompting the player:
+
+```yaml
+nodes:
+ monologue_1:
+ message: "The elder clears his throat and begins..."
+ next: monologue_2
+ monologue_2:
+ message: "\"Long ago, before the asteroid was settled...\""
+ next: monologue_3
+ monologue_3:
+ message: "\"...a great darkness fell upon these halls.\" He pauses."
+ next: choice_point
+ choice_point:
+ message: "\"Do you understand the weight of what I'm telling you?\""
+ options:
+ - text: "\"I think so.\""
+ - text: "\"Not really.\""
+```
+
+If a node has both `next` and options, the options take priority — `next` is only used
+when no options are visible. A node with a shop action ignores `next` entirely.
+
#### Shop (buy/sell interface)
-The `shop` node action opens a dedicated buy/sell interface. The player can browse
-items, buy with credits, and sell items back. Define a shop on a talk node:
+The `shop` node action opens a dedicated buy/sell interface. The player can browse items, buy
+with credits, and sell items back. Define a shop on a talk node:
```yaml
action:
@@ -294,14 +386,11 @@ action:
| Field | Description |
|---|---|
-| `shop.message` | Greeting shown when entering the shop |
-| `shop.items` | List of items for sale |
-| `item_id` | Item definition ID |
-| `buy_price` | Credits to buy from shop |
-| `sell_price` | Credits shop pays (0 = won't buy) |
-
-Typical shop flow: a talk node with a "Browse" option leads to a `shop` node.
-When the player leaves the shop, they return to the talk node's options.
+| `shop.message` | Greeting shown when entering the shop. |
+| `shop.items` | List of items for sale. |
+| `item_id` | Item definition ID. |
+| `buy_price` | Credits to buy from shop. |
+| `sell_price` | Credits shop pays (0 = won't buy). |
Full example — General Store:
```yaml
@@ -314,7 +403,6 @@ talk:
- text: "\"I'd like to browse.\""
goto: shop
- text: "\"Goodbye.\""
- end: true
shop:
message: "\"Take your time.\""
action:
@@ -332,8 +420,8 @@ talk:
goto: start
```
-Node options on the shop node are shown when the player leaves the shop.
-Use `goto: start` to loop back to the main greeting.
+When the player leaves the shop, the current node's options are shown (or auto-advance
+fires if no options are visible). Use `goto: start` to loop back to the main greeting.
### Object Interactions (levers, switches, gates)
diff --git a/building_guide/construction.md b/building_guide/construction.md
index 81e4249..40e4b9f 100644
--- a/building_guide/construction.md
+++ b/building_guide/construction.md
@@ -129,7 +129,6 @@ talk:
- text: "\"How much?\""
goto: offer
- text: "\"No thanks.\""
- end: true
offer:
message: "\"10 credits for a plot.\""
action:
@@ -138,7 +137,6 @@ talk:
owns_house_local_neighborhood: "local_neighborhood"
options:
- text: "\"Deal!\""
- end: true
unique: true
```
diff --git a/building_guide/mobs.md b/building_guide/mobs.md
index d10f685..32ee408 100644
--- a/building_guide/mobs.md
+++ b/building_guide/mobs.md
@@ -77,18 +77,46 @@ ranged_defense: 3
### Protected/Unique Mobs
-Mob with talk behavior — can be talked to via `talk:` inline config:
+Protected mobs cannot be attacked. All combat and stat fields (`attack`, `strength`,
+`defense`, `hp`, `speed`, `attack_type`, `attack_bonus`, `strength_bonus`,
+`*_defense`, `weakness`, `size`, `drops`, `aggressive`, `respawn_ticks`) are
+**optional for protected mobs** — omit them entirely. Protected mobs don't show
+a combat level in room listings or when examined.
+
+Minimal protected mob (shopkeeper, quest giver, NPC):
+```yaml
+name: flight attendant
+description: A smiling flight attendant in a crisp uniform.
+unique: true # displays as "Flight attendant" not "a flight attendant"
+protected: true # cannot be attacked, combat stats are optional
+idle_descriptions:
+ - adjusts her name badge
+ - smiles politely at passengers
+talk: # inline talk config
+ nodes:
+ start:
+ message: "\"Welcome aboard!\""
+ options:
+ - text: "\"What should I do?\""
+ goto: check_sign
+ - text: "\"Goodbye.\""
+ check_sign:
+ message: "\"Review the safety information.\""
+ options:
+ - text: "\"Will do.\""
+```
+
+Protected mob with combat stats (for internal testing or debug purposes):
```yaml
name: "Guard"
-talk: # inline talk config (no separate behavior file)
+unique: true
+protected: true
+talk:
nodes:
start:
message: "\"Halt! Who goes there?\""
options:
- text: "\"Just passing through.\""
- end: true
-unique: true # displays as "Guard" not "a guard"
-protected: true # cannot be attacked
attack: 5
strength: 5
defense: 5
@@ -106,7 +134,6 @@ science_defense: -5
ranged_defense: 12
idle_descriptions:
- "scans the area with a watchful eye"
- - "adjusts the grip on his weapon"
```
Note: `wander_rooms` and `wander_interval` are NOT set on the mob definition. Wander config
diff --git a/building_guide/objects.md b/building_guide/objects.md
index 110eb56..87b9710 100644
--- a/building_guide/objects.md
+++ b/building_guide/objects.md
@@ -120,9 +120,22 @@ talk:
- text: "\"What do you have?\""
goto: shop
- text: "\"Goodbye.\""
- end: true
```
+On-look action (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:
+ 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_flags`,
+`give_item`, `take_item`, `teleport`, `heal`, `cost`, and everything else in the
+[node action reference](behaviors.md#node-action-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.
diff --git a/building_guide/quests.md b/building_guide/quests.md
index a764f8e..b9556dc 100644
--- a/building_guide/quests.md
+++ b/building_guide/quests.md
@@ -23,7 +23,6 @@ talk:
player_flag: rat_quest
value: started
- text: "\"Goodbye.\""
- end: true
accept_quest:
message: "\"Good lad. The cellar is west of here. Come back when they're dead.\""
@@ -32,7 +31,6 @@ talk:
rat_quest: started
options:
- text: "\"On my way.\""
- end: true
turn_in:
message: "\"You did it! The village owes you a debt. Here — take this.\""
@@ -43,7 +41,6 @@ talk:
heal: 10
options:
- text: "\"Thanks!\""
- end: true
attack: 1
strength: 1
defense: 1