aboutsummaryrefslogtreecommitdiff
path: root/worldbuilding_guide
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-19 18:20:26 -0400
committerhistoria <[not public]>2026-06-19 18:20:26 -0400
commit0ea4eec5dd2122c6704216971eb1249276297867 (patch)
tree430fbbef04e837820f1d031c190f52ecd6112e25 /worldbuilding_guide
parent3a58125d14bb307f861b38c6c5b0a63babde7e08 (diff)
downloadthehouseoficarus-0ea4eec5dd2122c6704216971eb1249276297867.tar.gz
shop fixes, 'toggle' completely removed, movement speed increased
Diffstat (limited to 'worldbuilding_guide')
-rw-r--r--worldbuilding_guide/README.md3
-rw-r--r--worldbuilding_guide/behaviors.md518
-rw-r--r--worldbuilding_guide/conditions.md2
-rw-r--r--worldbuilding_guide/construction.md25
-rw-r--r--worldbuilding_guide/doors.md21
-rw-r--r--worldbuilding_guide/hidden_objects.md10
-rw-r--r--worldbuilding_guide/index.md5
-rw-r--r--worldbuilding_guide/mobs.md14
-rw-r--r--worldbuilding_guide/objects.md95
-rw-r--r--worldbuilding_guide/quests.md88
-rw-r--r--worldbuilding_guide/recipes.md4
-rw-r--r--worldbuilding_guide/tips.md2
-rw-r--r--worldbuilding_guide/wandering_objects.md18
13 files changed, 495 insertions, 310 deletions
diff --git a/worldbuilding_guide/README.md b/worldbuilding_guide/README.md
index 97cf43b..0bea82c 100644
--- a/worldbuilding_guide/README.md
+++ b/worldbuilding_guide/README.md
@@ -10,7 +10,7 @@ The House of Icarus is data-driven. Everything — rooms, items, mobs, objects,
| [Items](items.md) | Item definitions, stats, equip slots, weapon types, tool types, firemaking, food/healing |
| [Mobs](mobs.md) | Mob definitions, combat stats, drops, behavior, idle descriptions |
| [Objects](objects.md) | Interactive objects, behaviors, hidden objects, in-room descriptions |
-| [Behaviors](behaviors.md) | Gather, use, talk, toggle behaviors with full YAML reference |
+| [Behaviors](behaviors.md) | Gather, use, talk behaviors with full YAML reference |
| [Recipes](recipes.md) | Recipe system for cooking, crafting, smithing — station and item-on-item |
| [Conditions](conditions.md) | All condition types: flag, player_flag, has_item, all_of, any_of, not |
| [Drop Tables](drops.md) | Shared weighted drop tables for mob loot and search tables |
@@ -19,7 +19,6 @@ The House of Icarus is data-driven. Everything — rooms, items, mobs, objects,
| [Quests](quests.md) | Complete multi-room quest example with talk behaviors |
| [Wandering Objects](wandering_objects.md) | Objects that teleport between rooms on a timer |
| [Wandering Mobs](wandering_mobs.md) | Mobs that wander through legal exits |
-| [Toggles](toggles.md) | Player toggle options (tiny_map, xp_drops, automap, etc.) |
| [Search](search.md) | The search command and searchable items |
| [Hidden Objects](hidden_objects.md) | Hidden interactive objects |
| [Bank](bank.md) | Bank system — deposit, withdraw, browse, bank booth placement |
diff --git a/worldbuilding_guide/behaviors.md b/worldbuilding_guide/behaviors.md
index aa46073..1934f5b 100644
--- a/worldbuilding_guide/behaviors.md
+++ b/worldbuilding_guide/behaviors.md
@@ -1,112 +1,167 @@
## Behaviors
+Behaviors are **inline configs** placed directly inside object YAML (`gather:`, `talk:`,
+`use:`) or mob YAML (`talk:`). There is no separate `data/behaviors/`
+directory. Each section below shows the keys you can use under each behavior type.
+
### Gather (mining, fishing, woodcutting)
-Mining — per-drop depletion:
+Mining — per-drop depletion on a rock object:
```yaml
-id: mine_copper
-type: gather
-skill: mining
-level: 1
-xp: 17 # XP awarded per successful gather
-base_wait: 8 # ticks between attempts
-tool: pickaxe # requires item with tool_type: pickaxe
-success:
- base: 0.40 # 40% base chance
- per_level: 0.01 # +1% per level above requirement
- cap: 0.95 # 95% max
-gather_message: "You swing your pickaxe at the rock..."
-fail_message: "You chip away but get nothing useful."
-drops:
- - item_id: copper_ore
- weight: 90 # 90% chance when roll succeeds
- depletes: true # rock becomes depleted after this drop
- message: "You manage to mine some {178}copper ore{/}."
- - table: gem_table # reference a shared drop table
- weight: 10
- depletes: false # gem drops don't deplete the rock
- message: "You spot a glint of something valuable!"
-respawn_timer: 50 # ticks until rock respawns
-respawn_message: "You see more ore in the rock."
-respawn_broadcast: "A glint of copper catches your eye from some {name}."
+id: copper_rock
+name: copper rock
+color: "178"
+gather:
+ skill: mining
+ level: 1
+ xp: 17 # XP awarded per successful gather
+ base_wait: 8 # ticks between attempts
+ tools: # requires item with matching tool_type
+ - pickaxe
+ success:
+ base: 0.40 # 40% base chance
+ per_level: 0.01 # +1% per level above requirement
+ cap: 0.95 # 95% max
+ gather_message: "You swing your pickaxe at the rock..."
+ fail_message: "You chip away but get nothing useful."
+ drops:
+ - item_id: copper_ore
+ weight: 90 # 90% chance when roll succeeds
+ depletes: true # rock becomes depleted after this drop
+ message: "You manage to mine some {178}copper ore{/}."
+ - table: gem_table # reference a shared drop table
+ weight: 10
+ depletes: false # gem drops don't deplete the rock
+ message: "You spot a glint of something valuable!"
+ respawn_timer: 50 # ticks until rock respawns
+ respawn_broadcast: "A glint of copper catches your eye from some {name}."
```
-Drop messages support inline color tags: `{<0-255>}text{/}`. Use the item's color index to match its display color. Gradients also work: `{g:196,82}text{/}`.
+Drop messages support inline color tags: `{<0-255>}text{/}`. Use the item's color
+index to match its display color. Gradients also work: `{g:196,82}text{/}`.
-Non-depleting gather (fishing):
+Non-depleting gather (fishing on a fishing spot object):
```yaml
-id: fish_trout
-type: gather
-skill: fishing
-level: 1
-xp: 10
-base_wait: 4
-tool: fishing_rod
-success:
- base: 0.30
- per_level: 0.01
- cap: 0.90
-gather_message: "You cast your line into the water..."
-fail_message: "Nothing seems to bite."
-drops:
- - item_id: raw_trout
- weight: 100
- depletes: false # never depletes
- message: "You catch a {69}raw trout{/}!"
+id: bait_fishing_spot
+name: fishing spot
+gather:
+ skill: fishing
+ level: 1
+ xp: 10
+ base_wait: 4
+ tools:
+ - fishing_rod
+ bait: fishing_bait
+ success:
+ base: 0.30
+ per_level: 0.01
+ cap: 0.90
+ gather_message: "You cast your line into the water..."
+ fail_message: "Nothing seems to bite."
+ drops:
+ - item_id: raw_trout
+ weight: 100
+ depletes: false # never depletes
+ message: "You catch a {69}raw trout{/}!"
```
Woodcutting with shared depletion and bird's nests:
```yaml
-id: chop_oak
-type: gather
-skill: woodcutting
-level: 15
-xp: 37
-base_wait: 6
-tool: axe
-success:
- base: 0.40
- per_level: 0.01
- cap: 0.90
-gather_message: "You swing your axe at the oak tree..."
-fail_message: "You swing but get no logs."
-drops:
- - item_id: oak_logs
- weight: 100
- depletes: false # depletion is timer-based (deplete_timer)
- message: "You get some {113}oak logs{/}."
-respawn_timer: 14 # ticks until tree respawns after being cut down
-deplete_timer: 45 # max ticks before next gather depletes (counts down while chopping)
-nest_chance: 256 # 1/256 chance for a bird's nest on each successful gather
-respawn_message: "A new oak sapling grows in its place."
-respawn_broadcast: "An {name} grows back."
+id: oak_tree
+name: oak tree
+color: "113"
+gather:
+ skill: woodcutting
+ level: 15
+ xp: 37
+ base_wait: 6
+ tools:
+ - axe
+ success:
+ base: 0.40
+ per_level: 0.01
+ cap: 0.90
+ gather_message: "You swing your axe at the oak tree..."
+ fail_message: "You swing but get no logs."
+ drops:
+ - item_id: oak_logs
+ weight: 100
+ depletes: false # depletion is timer-based (deplete_timer)
+ message: "You get some {113}oak logs{/}."
+ respawn_timer: 14 # ticks until tree respawns after being cut down
+ deplete_timer: 45 # max ticks before next gather depletes (counts down while chopping)
+ nest_chance: 256 # 1/256 chance for a bird's nest on each successful gather
+ respawn_broadcast: "An {name} grows back."
```
Regular tree — always depletes on first gather, no shared timer, no nests:
```yaml
-id: chop_tree
-type: gather
-skill: woodcutting
-level: 1
-xp: 25
-base_wait: 4
-tool: axe
-success:
- base: 0.50
- per_level: 0.01
- cap: 0.95
-gather_message: "You swing your axe at the tree..."
-fail_message: "You swing but get no logs."
-drops:
- - item_id: logs
- weight: 100
- depletes: true # regular tree depletes on first successful gather
- message: "You get some {107}logs{/}."
-respawn_timer: 80
-respawn_message: "A new tree grows in its place."
-respawn_broadcast: "A {name} grows back."
+id: tree
+name: tree
+gather:
+ skill: woodcutting
+ level: 1
+ xp: 25
+ base_wait: 4
+ tools:
+ - axe
+ success:
+ base: 0.50
+ per_level: 0.01
+ cap: 0.95
+ gather_message: "You swing your axe at the tree..."
+ fail_message: "You swing but get no logs."
+ drops:
+ - item_id: logs
+ weight: 100
+ depletes: true # regular tree depletes on first successful gather
+ message: "You get some {107}logs{/}."
+ respawn_timer: 80
+ respawn_broadcast: "A {name} grows back."
```
+#### GatherConfig Fields
+
+| Field | Type | Description |
+|---|---|---|
+| `skill` | string | Skill name for level check |
+| `level` | int | Required level to gather |
+| `xp` | int | XP per successful gather |
+| `base_wait` | float64 | Base ticks per action cycle |
+| `tools` | []string | Required tool_type list (e.g. `[pickaxe]`) |
+| `bait` | string | Required bait item (for fishing) |
+| `success` | SuccessFormula | Base + per_level, capped |
+| `gather_message` | string | Custom "You gather..." message |
+| `depleted_message` | string | Custom "The rock is depleted" message |
+| `exhausted_message` | string | Custom "The tree falls" message |
+| `fail_message` | string | Custom failure message |
+| `drops` | []DropEntry | Weighted drop entries |
+| `respawn_timer` | float64 | Ticks until depleted object respawns |
+| `respawn_broadcast` | string | Broadcast message when object respawns |
+| `deplete_timer` | float64 | Ticks for shared depletion (trees) |
+| `nest_chance` | int | 1/N chance for bird's nest alongside normal drop |
+
+#### SuccessFormula
+
+| Field | Type | Description |
+|---|---|---|
+| `base` | float64 | Base success chance (0.0-1.0) |
+| `per_level` | float64 | Chance increase per level above requirement |
+| `cap` | float64 | Maximum success chance |
+
+#### DropEntry
+
+| Field | Type | Description |
+|---|---|---|
+| `item_id` | string | Item ID to drop |
+| `table` | string | Reference to a shared drop table in `data/drops/` |
+| `weight` | int | Relative drop weight |
+| `depletes` | bool | Resource depletes on this drop |
+| `quantity` | int | Amount to drop (1-3 for random) |
+| `message` | string | Player message on drop |
+| `level` | int | Skill level required for this drop |
+| `xp` | int | Bonus XP on this drop |
+
#### Shared depletion explained
When `deplete_timer > 0`, the tree has a shared despawn timer:
@@ -131,60 +186,63 @@ toggle is on, the output includes the XP gain: `(+37xp wct)`.
### Talk (dialog trees)
-Full conversation with conditions, actions, and player flag tracking:
+Talk configs go under the `talk:` key on objects or mobs. Full conversation with
+conditions, actions, and player flag tracking:
+
```yaml
-id: guard_talk
-type: talk
-nodes:
- start:
- message: "\"Halt! This area is restricted.\""
- options:
- - text: "\"What's behind that gate?\""
- goto: about_gate
- - text: "\"I have copper ore.\"" # only shows if player has ore
- goto: trade_ore
- condition:
- has_item: copper_ore
- - text: "\"I have a pass.\"" # only shows if player earned a pass
- goto: has_pass
- condition:
- player_flag: got_pass
- value: true
- - text: "\"Goodbye.\""
- end: true
-
- about_gate:
- message: "\"Bring me some copper ore and I'll stamp you a pass.\""
- action:
- set_player_flags: # player-local: only this player
- talked_to_guard: true
- options:
- - text: "\"I'll be back.\""
- end: true
- - text: "\"I have some right here.\""
- goto: trade_ore
- condition:
- has_item: copper_ore
-
- trade_ore:
- message: "\"Good quality ore.\" He stamps a pass and hands it to you."
- action:
- take_item: copper_ore # removes 1 copper ore
- give_item: pass_stub # gives pass stub
- set_player_flags:
- got_pass: true # player now "has a pass"
- options:
- - text: "\"Thanks.\""
- end: true
-
- has_pass:
- message: "\"Alright, I'll open the gate for you.\""
- action:
- set_flags: # WORLD flag: gate opens for everyone
- gate_open: true
- options:
- - text: "\"Thanks.\""
- end: true
+id: guard
+name: Guard
+talk:
+ nodes:
+ start:
+ message: "\"Halt! This area is restricted.\""
+ options:
+ - text: "\"What's behind that gate?\""
+ goto: about_gate
+ - text: "\"I have copper ore.\""
+ goto: trade_ore
+ condition:
+ has_item: copper_ore
+ - text: "\"I have a pass.\""
+ goto: has_pass
+ condition:
+ player_flag: got_pass
+ value: true
+ - text: "\"Goodbye.\""
+ end: true
+
+ about_gate:
+ message: "\"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:
+ has_item: copper_ore
+
+ trade_ore:
+ message: "\"Good quality ore.\" He stamps a pass and hands it to you."
+ action:
+ take_item: copper_ore
+ give_item: pass_stub
+ set_player_flags:
+ got_pass: true
+ options:
+ - text: "\"Thanks.\""
+ end: true
+
+ has_pass:
+ message: "\"Alright, I'll open the gate for you.\""
+ action:
+ set_flags:
+ gate_open: true
+ options:
+ - text: "\"Thanks.\""
+ end: true
```
#### Node action reference
@@ -203,19 +261,21 @@ nodes:
| `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.
+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:
```yaml
action:
- take_item: dragon_head
- give_item: dragon_slayer_medal
- set_player_flags:
- dragon_quest: complete
- dragon_slain: true
- heal: 99
- teleport: 1 # return to town
+ take_item: dragon_head
+ give_item: dragon_slayer_medal
+ set_player_flags:
+ dragon_quest: complete
+ dragon_slain: true
+ heal: 99
+ teleport: 1
```
#### Shop (buy/sell interface)
@@ -225,15 +285,15 @@ items, buy with credits, and sell items back. Define a shop on a talk node:
```yaml
action:
- shop:
- message: "What would you like to buy or sell?"
- items:
- - item_id: fishing_rod
- buy_price: 10
- sell_price: 2
- - item_id: fishing_bait
- buy_price: 2
- sell_price: 0
+ shop:
+ message: "What would you like to buy or sell?"
+ items:
+ - item_id: fishing_rod
+ buy_price: 10
+ sell_price: 2
+ - item_id: fishing_bait
+ buy_price: 2
+ sell_price: 0
```
| Field | Description |
@@ -249,85 +309,95 @@ When the player leaves the shop, they return to the talk node's options.
Full example — General Store:
```yaml
-id: general_store
-type: talk
-nodes:
- start:
- message: "\"Welcome to the General Store!\""
- options:
- - text: "\"I'd like to browse.\""
- goto: shop
- - text: "\"Goodbye.\""
- end: true
- shop:
- message: "\"Take your time.\""
- action:
- shop:
- message: "What would you like to buy or sell?"
- items:
- - item_id: fishing_rod
- buy_price: 10
- sell_price: 2
- - item_id: hammer
- buy_price: 20
- sell_price: 5
- options:
- - text: "\"I'm done.\""
- goto: start
+id: general_store_clerk
+name: General Store Clerk
+talk:
+ nodes:
+ start:
+ message: "\"Welcome to the General Store!\""
+ options:
+ - text: "\"I'd like to browse.\""
+ goto: shop
+ - text: "\"Goodbye.\""
+ end: true
+ shop:
+ message: "\"Take your time.\""
+ action:
+ shop:
+ message: "What would you like to buy or sell?"
+ items:
+ - item_id: fishing_rod
+ buy_price: 10
+ sell_price: 2
+ - item_id: hammer
+ buy_price: 20
+ sell_price: 5
+ options:
+ - text: "\"I'm done.\""
+ 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.
-### Toggle (levers, switches, gates)
+### Object Interactions (levers, switches, gates)
+
+Interaction configs go under the `use_interactions:` key on objects.
+Entries with no `item` field are bare interactions triggered by "use"
+or "push"/"pull":
-Simple toggle that sets a world flag:
```yaml
-id: iron_gate_toggle
-type: toggle
-message: "You push the heavy iron gate open."
-set_flags:
- gate_open: true
-check: # only works when gate is closed
- flag: gate_open
- value: true
- not: true
+id: iron_gate
+name: iron gate
+hidden: true
+description: "A heavy iron gate set into the north wall."
+use_interactions:
+ - condition:
+ flag: gate_open
+ value: true
+ not: true
+ message: "You push the heavy iron gate open."
+ action:
+ set_flags:
+ gate_open: true
```
-Lever that toggles between two states:
+Item-specific interaction:
```yaml
-id: bridge_lever
-type: toggle
-message: "You pull the lever. Mechanisms groan somewhere in the distance."
-set_flags:
- bridge_extended: true
-check:
- flag: bridge_extended
- value: true
- not: true
+id: bookshelf
+name: bookshelf
+use_interactions:
+ - item: dusty_tome
+ message: "The bookshelf slides aside, revealing a secret passage!"
+ action:
+ set_flags:
+ secret_passage_open: true
```
### Use (crafting stations)
+Use configs go under the `use:` key on objects (e.g. furnaces, ranges):
+
```yaml
-id: smelt_copper
-type: use
-message: "You place the ore in the furnace..."
-wait: 4 # ticks between crafts
-consume: # items consumed per craft
- copper_ore: 1
-reward: # item produced
- item_id: copper_bar
- quantity: 1
-fail_message: "The ore crumbles to dust."
-success:
- base: 0.60
- per_level: 0.01
- cap: 0.95
-skill: smithing
-level: 1
-xp: 15 # XP awarded per successful craft
+id: furnace
+name: furnace
+color: "208"
+use:
+ message: "You place the ore in the furnace..."
+ wait: 4
+ consume:
+ copper_ore: 1
+ reward:
+ item_id: copper_bar
+ quantity: 1
+ fail_message: "The ore crumbles to dust."
+ success:
+ base: 0.60
+ per_level: 0.01
+ cap: 0.95
+ skill: smithing
+ level: 1
+ xp: 15
```
---
-
diff --git a/worldbuilding_guide/conditions.md b/worldbuilding_guide/conditions.md
index 773230b..972dadc 100644
--- a/worldbuilding_guide/conditions.md
+++ b/worldbuilding_guide/conditions.md
@@ -1,6 +1,6 @@
## Conditions Reference
-Conditions are used in talk options, exit gates, on-enter scripts, and toggle checks.
+Conditions are used in talk options, exit gates, on-enter scripts, and use_interactions checks.
### Simple conditions
diff --git a/worldbuilding_guide/construction.md b/worldbuilding_guide/construction.md
index 799057a..d4ba840 100644
--- a/worldbuilding_guide/construction.md
+++ b/worldbuilding_guide/construction.md
@@ -125,7 +125,24 @@ Located in room 16 (Construction Site). Talk behavior sells a house plot for 10
```yaml
id: estate_broker
name: estate broker
-behavior: estate_broker_talk
+talk:
+ nodes:
+ start:
+ message: "\"Interested in a house?\""
+ options:
+ - text: "\"How much?\""
+ goto: offer
+ - text: "\"No thanks.\""
+ end: true
+ offer:
+ message: "\"10 credits for a plot.\""
+ action:
+ cost: 10
+ set_player_flags:
+ owns_house_local_neighborhood: "local_neighborhood"
+ options:
+ - text: "\"Deal!\""
+ end: true
unique: true
```
@@ -196,10 +213,8 @@ This enables automatic support through the unified production system (`advancePr
| `data/items/planks.yaml` - `mahogany_planks.yaml` | Plank items (4 tiers) |
| `data/items/wooden_shelf.yaml` - `mahogany_table.yaml` | Furniture items (7 items) |
| `data/recipes/construct_planks.yaml` - `construct_mahogany_table.yaml` | Construction recipes (11 recipes) |
-| `data/mobs/estate_broker.yaml` | Estate broker mob |
-| `data/mobs/sawmill_operator.yaml` | Sawmill operator mob |
-| `data/behaviors/estate_broker_talk.yaml` | Broker talk behavior |
-| `data/behaviors/sawmill_operator_talk.yaml` | Sawmill operator talk behavior |
+| `data/mobs/estate_broker.yaml` | Estate broker mob (talk inline) |
+| `data/mobs/sawmill_operator.yaml` | Sawmill operator mob (talk inline) |
| `data/rooms/16.yaml` | Construction Site (updated) |
| `data/rooms/170.yaml` | Local Neighborhood |
| `data/rooms/171.yaml` | Lumberyard |
diff --git a/worldbuilding_guide/doors.md b/worldbuilding_guide/doors.md
index afe4556..1e9fb7a 100644
--- a/worldbuilding_guide/doors.md
+++ b/worldbuilding_guide/doors.md
@@ -8,20 +8,15 @@ A button in room 3 opens a door in room 7. Anyone can press it. Once pressed, th
```yaml
id: door_button
name: stone button
-behavior: button_toggle
hidden: true
-```
-
-**Button behavior** (`data/behaviors/button_toggle.yaml`):
-```yaml
-id: button_toggle
-type: toggle
-message: "You press the stone button. You hear grinding stone in the distance."
-set_flags:
- secret_door_open: true # WORLD flag
-check:
- flag: secret_door_open
- not: true # only works when door is closed
+use_interactions:
+ - condition:
+ flag: secret_door_open
+ not: true
+ message: "You press the stone button. You hear grinding stone in the distance."
+ action:
+ set_flags:
+ secret_door_open: true
```
**Room 3** — contains the button:
diff --git a/worldbuilding_guide/hidden_objects.md b/worldbuilding_guide/hidden_objects.md
index a191051..39030d8 100644
--- a/worldbuilding_guide/hidden_objects.md
+++ b/worldbuilding_guide/hidden_objects.md
@@ -6,9 +6,17 @@ Objects with `hidden: true` don't appear in the room's object listing. Players d
# data/objects/secret_lever.yaml
id: secret_lever
name: stone lever
-behavior: secret_toggle
hidden: true
description: "A cleverly concealed lever behind a loose stone."
+use_interactions:
+ - condition:
+ flag: secret_passage_open
+ value: true
+ not: true
+ message: "You pull the lever. A grinding sound echoes from the east."
+ action:
+ set_flags:
+ secret_passage_open: true
```
Room description hints at it:
diff --git a/worldbuilding_guide/index.md b/worldbuilding_guide/index.md
index 9f721cb..83b3782 100644
--- a/worldbuilding_guide/index.md
+++ b/worldbuilding_guide/index.md
@@ -6,9 +6,12 @@
| An item (sword, ore, key) | `data/items/<id>.yaml` |
| A mob (NPC, monster) | `data/mobs/<id>.yaml` |
| An interactive object (rock, lever, door) | `data/objects/<id>.yaml` |
-| A behavior (mining, dialog, toggle) | `data/behaviors/<id>.yaml` |
| A shared drop table | `data/drops/<id>.yaml` |
| A crafting recipe | `data/recipes/<id>.yaml` |
| A help topic | `data/help/<id>.yaml` |
+| A science module | `data/modules/<id>.yaml` |
| An agility course | `data/courses/<id>.yaml` |
| A player house | `data/rooms/player_housing/<id>.yaml` |
+
+Behaviors (gather, talk, use) are defined **inline** in object and mob YAML
+under `gather:`, `talk:`, or `use:` keys. There is no separate behavior directory.
diff --git a/worldbuilding_guide/mobs.md b/worldbuilding_guide/mobs.md
index 3826dda..70afa6a 100644
--- a/worldbuilding_guide/mobs.md
+++ b/worldbuilding_guide/mobs.md
@@ -74,13 +74,19 @@ ranged_defense: 3
### Protected/Unique Mobs
-Mob with a behavior — can be talked to, toggled, etc:
+Mob with talk behavior — can be talked to via `talk:` inline config:
```yaml
id: "guard"
name: "Guard"
-behavior: guard_talk # links to data/behaviors/guard_talk.yaml
-unique: true # displays as "Guard" not "a guard"
-protected: true # cannot be attacked
+talk: # inline talk config (no separate behavior file)
+ 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
diff --git a/worldbuilding_guide/objects.md b/worldbuilding_guide/objects.md
index 1c1aebb..a7da5e6 100644
--- a/worldbuilding_guide/objects.md
+++ b/worldbuilding_guide/objects.md
@@ -1,39 +1,116 @@
## Objects
-Object defined — links to a behavior:
+Objects interact with the world through **inline behavior configs** under
+`gather:`, `talk:`, or `use:` keys. There is no separate behavior
+directory — everything goes directly in the object's YAML.
+
+Gathering object (mining):
```yaml
id: copper_rock
name: copper rock
color: "178" # xterm-256 color index (0-255)
-behavior: mine_copper
+gather:
+ skill: mining
+ level: 1
+ xp: 17
+ base_wait: 8
+ tools:
+ - pickaxe
+ success:
+ base: 0.40
+ per_level: 0.01
+ cap: 0.95
+ gather_message: "You swing your pickaxe at the rock..."
+ fail_message: "You chip away but get nothing useful."
+ drops:
+ - item_id: copper_ore
+ weight: 90
+ depletes: true
+ message: "You manage to mine some {178}copper ore{/}."
+ - table: gem_table
+ weight: 10
+ depletes: false
+ message: "You spot a glint of something valuable!"
+ respawn_timer: 50
+ respawn_broadcast: "A glint of copper catches your eye from some {name}."
```
-Tree object:
+Tree object (woodcutting with shared depletion):
```yaml
id: oak_tree
name: oak tree
color: "113"
-behavior: chop_oak
+gather:
+ skill: woodcutting
+ level: 15
+ xp: 37
+ base_wait: 6
+ tools:
+ - axe
+ success:
+ base: 0.40
+ per_level: 0.01
+ cap: 0.90
+ gather_message: "You swing your axe at the oak tree..."
+ fail_message: "You swing but get no logs."
+ drops:
+ - item_id: oak_logs
+ weight: 100
+ depletes: false
+ message: "You get some {113}oak logs{/}."
+ respawn_timer: 14
+ deplete_timer: 45
+ nest_chance: 256
+ respawn_broadcast: "An {name} grows back."
```
-Color accepts xterm-256 indices with optional modifiers (`bold`, `dim`, `underline`) and gradients (`g:196,82`). In ANSI mode, extended colors downgrade to the nearest ANSI color.
+Color accepts xterm-256 indices with optional modifiers (`bold`, `dim`, `underline`)
+and gradients (`g:196,82`). In ANSI mode, extended colors downgrade to the nearest
+ANSI color.
-Hidden object — doesn't appear in room's object list, only discoverable via description or experimentation:
+Object interaction (gate, lever — uses `use_interactions:` key):
```yaml
id: iron_gate
name: iron gate
-behavior: iron_gate_toggle
hidden: true
description: "A heavy iron gate set into the north wall."
+use_interactions:
+ - condition:
+ flag: gate_open
+ value: true
+ not: true
+ message: "You push the heavy iron gate open."
+ action:
+ set_flags:
+ gate_open: true
```
-Decorative object (no behavior):
+Decorative object (no behavior keys — just a name/description):
```yaml
id: lumby_fountain
name: town fountain
description: "Clear water sparkles in the sunlight."
```
+Talk object (NPC conversations — uses `talk:` key):
+```yaml
+id: tool_shed
+name: Tool Shed
+description: "A small shed with an open window."
+talk:
+ nodes:
+ start:
+ message: "\"Welcome to the tool shed!\""
+ options:
+ - text: "\"What do you have?\""
+ goto: shop
+ - text: "\"Goodbye.\""
+ end: true
+```
+
+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
@@ -90,7 +167,7 @@ use_interactions:
| Field | Type | Description |
| ----------- | ---------- | ------------------------------------------------ |
| `item` | string | Item ID that triggers this interaction |
-| `condition` | Condition | Optional condition (same as exits/talk/toggle) |
+| `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) |
diff --git a/worldbuilding_guide/quests.md b/worldbuilding_guide/quests.md
index 443aa6b..b5f18fa 100644
--- a/worldbuilding_guide/quests.md
+++ b/worldbuilding_guide/quests.md
@@ -4,9 +4,45 @@
```yaml
id: "quest_giver"
name: "Elder"
-behavior: rat_quest_talk
unique: true
protected: true
+talk:
+ nodes:
+ start:
+ message: "\"Rats! Rats everywhere in the cellar. Clear them out and I'll reward you.\""
+ options:
+ - text: "\"I'll handle it.\""
+ goto: accept_quest
+ condition:
+ player_flag: rat_quest
+ not: true
+ - text: "\"I killed the rats.\""
+ goto: turn_in
+ condition:
+ 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.\""
+ action:
+ set_player_flags:
+ 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.\""
+ action:
+ give_item: rusty_sword
+ set_player_flags:
+ rat_quest: complete
+ heal: 10
+ options:
+ - text: "\"Thanks!\""
+ end: true
attack: 1
strength: 1
defense: 1
@@ -14,52 +50,12 @@ hp: 20
speed: 5
aggressive: false
idle_descriptions:
- - "mutters about the rat infestation"
+ - "mutters about the rat infestation"
```
-### 2. Dialog behavior (`data/behaviors/rat_quest_talk.yaml`)
-```yaml
-id: rat_quest_talk
-type: talk
-nodes:
- start:
- message: "\"Rats! Rats everywhere in the cellar. Clear them out and I'll reward you.\""
- options:
- - text: "\"I'll handle it.\""
- goto: accept_quest
- condition:
- player_flag: rat_quest
- not: true
- - text: "\"I killed the rats.\""
- goto: turn_in
- condition:
- 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.\""
- action:
- set_player_flags:
- 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.\""
- action:
- give_item: rusty_sword
- set_player_flags:
- rat_quest: complete
- heal: 10
- options:
- - text: "\"Thanks!\""
- end: true
-```
+Talk configs are inline on the mob under the `talk:` key. No separate behavior file needed.
-### 3. Rat mobs (`data/mobs/rat.yaml`)
+### 2. Rat mobs (`data/mobs/rat.yaml`)
```yaml
id: "rat"
name: "giant rat"
@@ -74,7 +70,7 @@ drops:
remains: "rat bones"
```
-### 4. Cellar room (`data/rooms/20.yaml`)
+### 3. Cellar room (`data/rooms/20.yaml`)
```yaml
id: 20
name: "Cellar"
@@ -89,7 +85,7 @@ mobs:
- "rat"
```
-### 5. Room 1 with quest giver (`data/rooms/1.yaml`)
+### 4. Room 1 with quest giver (`data/rooms/1.yaml`)
```yaml
id: 1
name: "Town Square"
diff --git a/worldbuilding_guide/recipes.md b/worldbuilding_guide/recipes.md
index 799dab0..81a1240 100644
--- a/worldbuilding_guide/recipes.md
+++ b/worldbuilding_guide/recipes.md
@@ -168,7 +168,7 @@ Item-on-item combinations are defined directly on the output item via the `made_
# data/items/bread_dough.yaml
id: bread_dough
name: bread dough
-color: "fg=bright_yellow"
+color: "222"
made_from:
- items: [pot_of_flour]
qty: 1
@@ -185,7 +185,7 @@ Items with `heal_value` and `eat_message` can be consumed via the `eat` command.
```yaml
id: bread
name: bread
-color: "fg=bright_yellow"
+color: "222"
description: "A fresh loaf of bread, still warm from the oven."
value: 5
heal_value: 5
diff --git a/worldbuilding_guide/tips.md b/worldbuilding_guide/tips.md
index 451b9bc..307ea1e 100644
--- a/worldbuilding_guide/tips.md
+++ b/worldbuilding_guide/tips.md
@@ -10,7 +10,7 @@
5. **Objects are for fixtures, mobs are for living things.** If it has HP and can die, it's a mob. If it's a rock, lever, door, or crafting station, it's an object. Both can have behaviors.
-6. **The `behavior` field on mobs** lets you talk to them directly — `talk guard` finds the guard mob, no duplicate object entry needed.
+6. **The `talk` field on mobs** lets you talk to them directly — `talk guard` finds the guard mob, no duplicate object entry needed.
7. **Exits accept both `int` and `map` formats.** `north: 2` is shorthand for `north: {room: 2}`. Add `condition` and `blocked_message` only when needed. Mob room entries accept both `"man"` and `{id: man, ...}`.
diff --git a/worldbuilding_guide/wandering_objects.md b/worldbuilding_guide/wandering_objects.md
index 9a47ed2..f1f91c5 100644
--- a/worldbuilding_guide/wandering_objects.md
+++ b/worldbuilding_guide/wandering_objects.md
@@ -5,7 +5,23 @@ Fishing spots that move between rooms:
# data/objects/fishing_spot.yaml
id: fishing_spot
name: fishing spot
-behavior: fish_trout
+gather:
+ skill: fishing
+ level: 1
+ xp: 10
+ base_wait: 4
+ tools:
+ - fishing_rod
+ bait: fishing_bait
+ success:
+ base: 0.30
+ per_level: 0.01
+ cap: 0.90
+ gather_message: "You cast your line into the water..."
+ drops:
+ - item_id: raw_trout
+ weight: 100
+ message: "You catch a raw trout!"
```
```yaml