diff options
| author | historia <[not public]> | 2026-06-16 04:17:43 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-16 04:17:43 -0400 |
| commit | 085e728d22a3369bd110b77409914cfbe9ebe611 (patch) | |
| tree | eeb88cb1ceb91cc9ea2b5a1877c3c66328fab503 /worldbuilding_guide | |
| parent | 43f21aabae8924f35c12c8485e690aeefe0089fb (diff) | |
| download | thehouseoficarus-085e728d22a3369bd110b77409914cfbe9ebe611.tar.gz | |
feat: recipe system, combining items, cooking skill
Diffstat (limited to 'worldbuilding_guide')
| -rw-r--r-- | worldbuilding_guide/README.md | 25 | ||||
| -rw-r--r-- | worldbuilding_guide/behaviors.md | 264 | ||||
| -rw-r--r-- | worldbuilding_guide/conditions.md | 66 | ||||
| -rw-r--r-- | worldbuilding_guide/doors.md | 102 | ||||
| -rw-r--r-- | worldbuilding_guide/drops.md | 52 | ||||
| -rw-r--r-- | worldbuilding_guide/hidden_objects.md | 21 | ||||
| -rw-r--r-- | worldbuilding_guide/index.md | 10 | ||||
| -rw-r--r-- | worldbuilding_guide/items.md | 68 | ||||
| -rw-r--r-- | worldbuilding_guide/mobs.md | 54 | ||||
| -rw-r--r-- | worldbuilding_guide/objects.md | 37 | ||||
| -rw-r--r-- | worldbuilding_guide/quests.md | 107 | ||||
| -rw-r--r-- | worldbuilding_guide/recipes.md | 112 | ||||
| -rw-r--r-- | worldbuilding_guide/rooms.md | 122 | ||||
| -rw-r--r-- | worldbuilding_guide/search.md | 15 | ||||
| -rw-r--r-- | worldbuilding_guide/state.md | 8 | ||||
| -rw-r--r-- | worldbuilding_guide/tips.md | 21 | ||||
| -rw-r--r-- | worldbuilding_guide/toggles.md | 18 | ||||
| -rw-r--r-- | worldbuilding_guide/wandering_mobs.md | 20 | ||||
| -rw-r--r-- | worldbuilding_guide/wandering_objects.md | 23 |
19 files changed, 1145 insertions, 0 deletions
diff --git a/worldbuilding_guide/README.md b/worldbuilding_guide/README.md new file mode 100644 index 0000000..8555e49 --- /dev/null +++ b/worldbuilding_guide/README.md @@ -0,0 +1,25 @@ +# World Building Guide + +Third Collapse is data-driven. Everything — rooms, items, mobs, objects, behaviors, drop tables, and recipes — is defined in YAML files under `data/`. No code changes needed to build a world. + +## Files + +| Document | Covers | +|----------|--------| +| [Rooms](rooms.md) | Room definitions, exits (simple and conditional), spawns, placed objects and mobs, on_enter scripts | +| [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 | +| [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 | +| [State](state.md) | World flags vs player flags — global vs per-character state | +| [Doors](doors.md) | Door examples with world flags and player flags | +| [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 | +| [Tips](tips.md) | Practical tips for building a world | diff --git a/worldbuilding_guide/behaviors.md b/worldbuilding_guide/behaviors.md new file mode 100644 index 0000000..a275c60 --- /dev/null +++ b/worldbuilding_guide/behaviors.md @@ -0,0 +1,264 @@ +## Behaviors + +### Gather (mining, fishing, woodcutting) + +Mining — per-drop depletion: +```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 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}." +``` + +Non-depleting gather (fishing): +```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 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 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." +``` + +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 logs." +respawn_timer: 80 +respawn_message: "A new tree grows in its place." +respawn_broadcast: "A {name} grows back." +``` + +#### Shared depletion explained + +When `deplete_timer > 0`, the tree has a shared despawn timer: +- The timer starts at `deplete_timer` max when the first player begins chopping. +- Each tick, if anyone is chopping, the timer counts down. +- When the timer reaches 0, the NEXT successful gather depletes the tree. +- If no one is chopping and the tree isn't depleted, the timer ticks back UP. +- All players chopping the same tree are interrupted when it depletes. + +Use `deplete_timer` for trees. Use `depletes: true` on individual drops for rocks. + +#### Bird's nests + +When `nest_chance > 0`, each successful gather has a 1/N independent chance to also drop +a bird's nest. The nest goes to inventory (or to the ground if inventory is full). +Use the `search` command to open nests — they roll on the `birds_nest_drop` table. + +#### XP drops + +When `xp > 0`, the gather awards XP on each successful drop. If the player's `xpdrops` +toggle is on, the output includes the XP gain: `(+37xp wct)`. + +### Talk (dialog trees) + +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 +``` + +#### 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 | + +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 +``` + +### Toggle (levers, switches, gates) + +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 +``` + +Lever that toggles between two states: +```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 +``` + +### Use (crafting stations) + +```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 +``` + +--- + diff --git a/worldbuilding_guide/conditions.md b/worldbuilding_guide/conditions.md new file mode 100644 index 0000000..ce9f74c --- /dev/null +++ b/worldbuilding_guide/conditions.md @@ -0,0 +1,66 @@ +## Conditions Reference + +Conditions are used in talk options, exit gates, on-enter scripts, and toggle checks. + +### Simple conditions + +```yaml +# Check a world flag +condition: + flag: gate_open + value: true + +# Check a world flag is NOT set +condition: + flag: gate_open + not: true + +# Check a player flag +condition: + player_flag: finished_tutorial + value: true + +# Check if player has an item +condition: + has_item: bronze_key + +# Check if player does NOT have an item +condition: + has_item: bronze_key + not: true +``` + +### Compound conditions + +All must pass: +```yaml +condition: + all_of: + - flag: gate_open + value: true + - has_item: pass_stub +``` + +Any one must pass: +```yaml +condition: + any_of: + - has_item: bronze_key + - has_item: iron_key + - player_flag: master_of_unlocking + value: true +``` + +Nested compounds: +```yaml +condition: + all_of: + - player_flag: quest_started + value: true + - any_of: + - has_item: wolf_pelt + - has_item: bear_pelt +``` + +--- + diff --git a/worldbuilding_guide/doors.md b/worldbuilding_guide/doors.md new file mode 100644 index 0000000..afe4556 --- /dev/null +++ b/worldbuilding_guide/doors.md @@ -0,0 +1,102 @@ +## Global vs Player State: Door Examples + +### Example A: Door with a button in another room (GLOBAL) + +A button in room 3 opens a door in room 7. Anyone can press it. Once pressed, the door is open for everyone. + +**Button object** (`data/objects/door_button.yaml`): +```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 +``` + +**Room 3** — contains the button: +```yaml +id: 3 +name: "Button Chamber" +description: "A small stone chamber. A button protrudes from the east wall." +exits: + south: 1 +objects: + - id: door_button +``` + +**Room 7** — contains the door: +```yaml +id: 7 +name: "Hidden Passage" +description: "A dusty corridor. A heavy stone door blocks the way north." +exits: + south: 2 + north: + room: 8 + condition: + flag: secret_door_open # checks WORLD flag + value: true + blocked_message: "A heavy stone door blocks the way." +objects: + - id: stone_door + hidden: true +``` + +### Example B: Key-locked door (PLAYER-LOCAL) + +A locked door that only opens for a player carrying the key. Each player must find their own key. + +**Key item** (`data/items/rusty_key.yaml`): +```yaml +id: rusty_key +name: rusty key +description: "An old iron key, still functional." +value: 0 +stackable: false +``` + +**Room 5** — locked door: +```yaml +id: 5 +name: "Locked Storage" +description: "A small storage room. The way east is blocked by a locked iron door." +exits: + west: 2 + east: + room: 6 + condition: + has_item: rusty_key # checks PLAYER inventory + blocked_message: "The iron door is locked. You need a key." +objects: + - id: iron_door + hidden: true +``` + +**Room 6** — the other side (no key needed to exit): +```yaml +id: 6 +name: "Storage Closet" +description: "Shelves of dusty crates." +exits: + west: 5 # exit back — no condition +spawns: + - item_id: uncut_ruby + quantity: 1 + respawn_ticks: 500 +``` + +Key difference: the button door uses `flag` (shared state — one player presses, everyone benefits), the key door uses `has_item` (per-player inventory check — each player needs their own key). + +--- + diff --git a/worldbuilding_guide/drops.md b/worldbuilding_guide/drops.md new file mode 100644 index 0000000..e5a17ff --- /dev/null +++ b/worldbuilding_guide/drops.md @@ -0,0 +1,52 @@ +## Drop Tables + +Shared drop tables can be referenced by multiple behaviors: +```yaml +# data/drops/gem_table.yaml +id: gem_table +drops: + - item_id: uncut_sapphire + weight: 47 + - item_id: uncut_emerald + weight: 16 + - item_id: uncut_ruby + weight: 4 + - item_id: uncut_diamond + weight: 1 +``` + +Bird's nest drop table: +```yaml +# data/drops/birds_nest_drop.yaml +id: birds_nest_drop +drops: + - item_id: credits + weight: 50 + quantity: 200 + - item_id: credits + weight: 30 + quantity: 500 + - item_id: credits + weight: 15 + quantity: 1000 + - item_id: credits + weight: 4 + quantity: 3000 + - item_id: credits + weight: 1 + quantity: 10000 +``` + +Referenced from a gather behavior: +```yaml +drops: + - item_id: copper_ore + weight: 90 + depletes: true + - table: gem_table # pulls from data/drops/gem_table.yaml + weight: 10 + depletes: false +``` + +--- + diff --git a/worldbuilding_guide/hidden_objects.md b/worldbuilding_guide/hidden_objects.md new file mode 100644 index 0000000..3cb8a1e --- /dev/null +++ b/worldbuilding_guide/hidden_objects.md @@ -0,0 +1,21 @@ +## Hidden Objects + +Objects with `hidden: true` don't appear in the room's object listing. Players discover them by reading room descriptions or trying commands. The object is still fully interactable — `push gate`, `look gate`, etc. + +```yaml +# data/objects/secret_lever.yaml +id: secret_lever +name: stone lever +behavior: secret_toggle +hidden: true +props: + description: "A cleverly concealed lever behind a loose stone." +``` + +Room description hints at it: +```yaml +description: "A dusty corridor. One of the wall stones looks slightly out of place." +``` + +--- + diff --git a/worldbuilding_guide/index.md b/worldbuilding_guide/index.md new file mode 100644 index 0000000..e19c207 --- /dev/null +++ b/worldbuilding_guide/index.md @@ -0,0 +1,10 @@ +## Quick Reference + +| What you want | Where to put it | +|---|---| +| A room | `data/rooms/<id>.yaml` | +| 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` | diff --git a/worldbuilding_guide/items.md b/worldbuilding_guide/items.md new file mode 100644 index 0000000..73f497b --- /dev/null +++ b/worldbuilding_guide/items.md @@ -0,0 +1,68 @@ +## Items + +```yaml +id: bronze_pickaxe +name: bronze pickaxe +aliases: ["pick", "pickaxe"] +description: "A sturdy bronze pickaxe." +value: 10 +stackable: false +equip_slot: main_hand # optional — where it equips +weapon_type: melee # optional — melee or ranged +stats: # optional — combat bonuses + attack_bonus: 2 + strength_bonus: 1 +speed: 5 # ticks between attacks +tool_type: pickaxe # used by gather behaviors that require "tool: pickaxe" +tool_speed: 2 # reduces gather wait time +``` + +Key item (quest token, not equippable): +```yaml +id: pass_stub +name: pass stub +description: "A crumpled slip of paper stamped with the guard's seal." +value: 0 +stackable: false +``` + +--- + +## Firemaking + +```yaml +id: logs +name: logs +fire_level: 1 # firemaking level required +fire_xp: 40 # XP for burning/stoking +burn_ticks: 24 # how long the fire burns +``` + +## Food / Healing + +```yaml +id: bread +name: bread +color: "fg=bright_yellow" +description: "A fresh loaf of bread, still warm from the oven." +value: 5 +heal_value: 5 # positive = heal, negative = damage +eat_message: "You eat the bread. Warm and satisfying." +``` + +## MadeFrom — Item Combinations + +Define what items combine to make this item. Used by the `use` command. + +```yaml +id: bread_dough +name: bread dough +color: "fg=bright_yellow" +made_from: + - items: [pot_of_flour] + qty: 1 + - items: [bucket_of_water, pitcher_of_water] + qty: 1 +``` + +Each entry is an ingredient slot. Multiple `items` means any of them works. The first matching item found in inventory is consumed. See also `recipes.md` for station-based recipes. diff --git a/worldbuilding_guide/mobs.md b/worldbuilding_guide/mobs.md new file mode 100644 index 0000000..a025e86 --- /dev/null +++ b/worldbuilding_guide/mobs.md @@ -0,0 +1,54 @@ +## Mobs + +Basic combat mob: +```yaml +id: "man" +name: "man" +description: "A shabby-looking man." +attack: 1 +strength: 1 +defense: 1 +hp: 7 +speed: 5 +aggressive: false +respawn_ticks: 30 +drops: + remains: "bones" # always dropped on death + loot: + - item_id: "credits" + weight: 98 + quantity: 10 + - item_id: "credits" + weight: 2 + quantity: 150 +idle_descriptions: + - "scribbles something in a small notebook" + - "gazes skyward at the clouds" +combat_descriptions: + - "is engaged in a fight to the death with %s" +``` + +Mob with a behavior — can be talked to, toggled, etc: +```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 +attack: 5 +strength: 5 +defense: 5 +hp: 30 +speed: 5 +aggressive: false +respawn_ticks: 60 +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 +is per-instance in the room YAML (see Rooms > Mobs section above). + +--- + diff --git a/worldbuilding_guide/objects.md b/worldbuilding_guide/objects.md new file mode 100644 index 0000000..94aead7 --- /dev/null +++ b/worldbuilding_guide/objects.md @@ -0,0 +1,37 @@ +## Objects + +Object defined — links to a behavior: +```yaml +id: copper_rock +name: copper rock +behavior: mine_copper +``` + +Tree object: +```yaml +id: oak_tree +name: oak tree +behavior: chop_oak +``` + +Hidden object — doesn't appear in room's object list, only discoverable via description or experimentation: +```yaml +id: iron_gate +name: iron gate +behavior: iron_gate_toggle +hidden: true +props: + description: "A heavy iron gate set into the north wall." +``` + +Decorative object (no behavior): +```yaml +id: lumby_fountain +name: town fountain +behavior: "" +props: + description: "Clear water sparkles in the sunlight." +``` + +--- + diff --git a/worldbuilding_guide/quests.md b/worldbuilding_guide/quests.md new file mode 100644 index 0000000..443aa6b --- /dev/null +++ b/worldbuilding_guide/quests.md @@ -0,0 +1,107 @@ +## Complete Quest Example: "Clear the Rats" + +### 1. Quest giver mob (`data/mobs/quest_giver.yaml`) +```yaml +id: "quest_giver" +name: "Elder" +behavior: rat_quest_talk +unique: true +protected: true +attack: 1 +strength: 1 +defense: 1 +hp: 20 +speed: 5 +aggressive: false +idle_descriptions: + - "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 +``` + +### 3. Rat mobs (`data/mobs/rat.yaml`) +```yaml +id: "rat" +name: "giant rat" +attack: 2 +strength: 1 +defense: 1 +hp: 3 +speed: 4 +aggressive: true +respawn_ticks: 60 +drops: + remains: "rat bones" +``` + +### 4. Cellar room (`data/rooms/20.yaml`) +```yaml +id: 20 +name: "Cellar" +description: "A damp, dark cellar. The floor scuttles with movement." +exits: + east: 1 +mobs: + - "rat" + - "rat" + - "rat" + - "rat" + - "rat" +``` + +### 5. Room 1 with quest giver (`data/rooms/1.yaml`) +```yaml +id: 1 +name: "Town Square" +description: "Cobblestone paths lead in all directions. The Elder stands near the fountain." +exits: + west: 20 + north: 2 +mobs: + - "quest_giver" +objects: + - id: lumby_fountain +``` + +--- + diff --git a/worldbuilding_guide/recipes.md b/worldbuilding_guide/recipes.md new file mode 100644 index 0000000..f40a9a7 --- /dev/null +++ b/worldbuilding_guide/recipes.md @@ -0,0 +1,112 @@ +# Third Collapse - World Building Guide + +## Recipes + +Recipes define how items are processed on stations to produce new items. They are the foundation for cooking, smithing, crafting, and fletching. + +Recipe files live in `data/recipes/<id>.yaml`. + +### Recipe vs MadeFrom + +- **Recipes** (`data/recipes/`) use a station (fire, range, furnace, anvil, etc.). The player must be near the station object. +- **MadeFrom** (on the item YAML directly) is for item-on-item combinations that need no station. The player combines ingredients from their inventory. + +### Recipe YAML Reference + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Unique recipe identifier | +| `type` | string | Recipe type (cooking, smithing, crafting, etc.) | +| `skill` | string | Skill checked for success | +| `level` | int | Required skill level | +| `xp` | int | XP awarded on success | +| `wait` | float64 | Ticks per craft cycle (default 6) | +| `station` | []string | Station object IDs required | +| `consume` | []ConsumeEntry | Ingredients consumed (see below) | +| `output` | string | ItemID produced on success | +| `fail` | string | ItemID produced on failure (optional) | +| `message` | string | Success message | +| `fail_message` | string | Failure message | +| `success` | SuccessFormula | Optional skill check formula (see Behaviors) | + +The recipe's name in menus comes from the output item's `name` field, colored using the output item's `color`. + +### ConsumeEntry — Multi-Item Ingredient Slots + +Each consume entry defines an ingredient slot with multiple valid items. The first matching item found in the player's inventory is consumed. + +```yaml +consume: + - items: [item_id, alternative_id, ...] + qty: 1 +``` + +### Station-based recipe (cooking on a fire) + +```yaml +id: cook_trout +type: cooking +skill: cooking +level: 15 +xp: 70 +wait: 6 +station: [fire, cooking_range] +consume: + - items: [raw_trout] + qty: 1 +output: trout +fail: burnt_fish +message: "Cooked to perfection. It looks great!" +fail_message: "You accidentally burn the trout." +``` + +### Station-specific recipe (range only, not fire) + +```yaml +id: cook_bread +type: cooking +skill: cooking +level: 1 +xp: 40 +wait: 6 +station: [cooking_range] +consume: + - items: [bread_dough] + qty: 1 +output: bread +fail: burnt_meat +message: "You bake the dough into a fresh loaf of bread." +fail_message: "You burn the bread to a crisp." +``` + +### MadeFrom — Item-on-item combinations + +Item-on-item combinations are defined directly on the output item via the `made_from` field. No recipe file needed. + +```yaml +# data/items/bread_dough.yaml +id: bread_dough +name: bread dough +color: "fg=bright_yellow" +made_from: + - items: [pot_of_flour] + qty: 1 + - items: [bucket_of_water, pitcher_of_water, vial_of_water] + qty: 1 +``` + +The player uses `use flour on water` to combine them. The system finds that `bread_dough` can be made from these ingredients and produces it. + +### Food/Healing Items + +Items with `heal_value` and `eat_message` can be consumed via the `eat` command. + +```yaml +id: bread +name: bread +color: "fg=bright_yellow" +description: "A fresh loaf of bread, still warm from the oven." +value: 5 +heal_value: 5 +eat_message: "You eat the bread. Warm and satisfying." +``` diff --git a/worldbuilding_guide/rooms.md b/worldbuilding_guide/rooms.md new file mode 100644 index 0000000..95e1972 --- /dev/null +++ b/worldbuilding_guide/rooms.md @@ -0,0 +1,122 @@ +## Rooms + +Minimal room: +```yaml +id: 1 +name: "Town Square" +description: "Cobblestone paths lead in all directions. A fountain gurgles peacefully." +exits: + north: 2 + west: 7 + east: 3 +``` + +### Exits — simple vs conditional + +Simple exit — always passable: +```yaml +exits: + north: 2 +``` + +Conditional exit — blocked until a world flag is set: +```yaml +exits: + north: + room: 11 + condition: + flag: gate_open + value: true + blocked_message: "A heavy iron gate blocks the way north." +``` + +Conditional exit — blocked unless the PLAYER has a flag (key, permission, quest state): +```yaml +exits: + east: + room: 12 + condition: + player_flag: has_vault_key + value: true + blocked_message: "The vault door is locked. You need a key." +``` + +Conditional exit with compound condition — requires both a world flag AND a player flag: +```yaml +exits: + north: + room: 20 + condition: + all_of: + - flag: bridge_repaired + value: true + - player_flag: paid_toll + value: true + blocked_message: "The bridge is out, and the toll collector blocks the path." +``` + +### Spawns — ground items that respawn + +```yaml +spawns: + - item_id: bronze_pickaxe + quantity: 1 + respawn_ticks: 30 # reappears 30 ticks (18 seconds) after being picked up + - item_id: copper_ore + quantity: 3 + respawn_ticks: 50 +``` + +### Mobs — NPCs placed in the room + +Simple string (no wandering): +```yaml +mobs: + - "newbie_trainer" + - "man" +``` + +With wander config per-instance: +```yaml +mobs: + - id: man + wander_interval: 10 # attempts to wander every 10 ticks + - id: man + wander_interval: 15 + wander_rooms: [1, 4, 5] # optional — only exit to these rooms +``` + +Mob wander config lives in the room YAML, not in the mob definition. This keeps mobs generic +so the same `man` can wander differently depending on where it's placed. Mobs wander through +legal (unconditioned) room exits. If no legal exits exist, the mob stays still. Mobs with +no `wander_interval` never wander. + +### Objects — interactive fixtures + +```yaml +objects: + - id: copper_rock # simple placement + - id: copper_rock # second instance + - id: fishing_spot + wander_rooms: [7, 8, 9] # teleports between these rooms + wander_interval: 12 # every 12 ticks + - id: iron_gate # hidden object (see below) +``` + +### On-enter scripts — messages when a player arrives + +```yaml +on_enter: + - message: "The guard barks: \"State your business!\"" + condition: + player_flag: talked_to_guard + not: true # only first visit + + - message: "The guard nods. \"Back again?\"" + condition: + player_flag: talked_to_guard + value: true # subsequent visits +``` + +--- + diff --git a/worldbuilding_guide/search.md b/worldbuilding_guide/search.md new file mode 100644 index 0000000..e6e2a14 --- /dev/null +++ b/worldbuilding_guide/search.md @@ -0,0 +1,15 @@ +## The `search` Command + +Used to open searchable items in your inventory (bird's nests, etc.): +``` +Usage: search <item> + +Example: search nest + search birds nest +``` + +Searches your inventory for the named item. If found, removes it and rolls on a drop table. +Currently only bird's nests are searchable. + +--- + diff --git a/worldbuilding_guide/state.md b/worldbuilding_guide/state.md new file mode 100644 index 0000000..2eefcc4 --- /dev/null +++ b/worldbuilding_guide/state.md @@ -0,0 +1,8 @@ +## State: World vs Player + +**World flags** (`set_flags`, checked with `flag`) are shared by every player on the server. A door opened by one player is open for everyone. A lever pulled once changes the world for all. + +**Player flags** (`set_player_flags`, checked with `player_flag`) are per-character. Quest progress, "has read the sign," "paid the toll" — these are different for each player. Saved to the character YAML and persist across logins. + +--- + diff --git a/worldbuilding_guide/tips.md b/worldbuilding_guide/tips.md new file mode 100644 index 0000000..451b9bc --- /dev/null +++ b/worldbuilding_guide/tips.md @@ -0,0 +1,21 @@ +## Tips + +1. **Use player flags for quest progress, world flags for environmental state.** If a bridge is repaired, that's world state. If a player has read a sign, that's player state. + +2. **Conditions on enter scripts** make rooms feel alive. A guard who only barks the first time, a room that changes after a quest completes. + +3. **Hidden objects** keep room descriptions clean. Mention them in the room's description text instead of auto-listing them. + +4. **Drop tables** are shareable. The `gem_table` is used by copper rocks AND mob loot. Define once, reference everywhere. + +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. + +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, ...}`. + +8. **Live editing works.** Room, item, mob, object, and behavior YAML files are read from disk on each access. Change a room description or dialog and it takes effect immediately — no restart needed. + +9. **Shared depletion vs per-drop depletion.** Use `deplete_timer` for trees — the timer counts down while being chopped and regens when left alone. Use `depletes: true` on individual drops for rocks — they deplete on first successful gather. + +10. **Mob wander config goes in the room YAML**, not the mob definition. This lets the same `man` wander differently in different rooms. diff --git a/worldbuilding_guide/toggles.md b/worldbuilding_guide/toggles.md new file mode 100644 index 0000000..00b48ba --- /dev/null +++ b/worldbuilding_guide/toggles.md @@ -0,0 +1,18 @@ +## Player Toggles + +Players can toggle personal settings with the `toggle` command: + +| Toggle | Effect | +|---|---| +| `description` | Show full room description when moving | +| `tiny_map` | Mini-map display: `off`/`right`/`left` | +| `xp_drops` | Show XP gained in gather/craft/combat messages | +| `exits` | Show exit destinations inline in look output | +| `mob_enter` | Notify when a mob enters the room | +| `mob_leave` | Notify when a mob leaves the room | +| `mob_spawn` | Notify when a mob spawns in the area | +| `reserve` | Show full reserved item details in look | +| `depletion` | Show depletion and despawn timers on objects | + +--- + diff --git a/worldbuilding_guide/wandering_mobs.md b/worldbuilding_guide/wandering_mobs.md new file mode 100644 index 0000000..8d49ed9 --- /dev/null +++ b/worldbuilding_guide/wandering_mobs.md @@ -0,0 +1,20 @@ +## Wandering Mobs + +Mob wandering is configured per-instance in the room YAML, not on the mob definition: +```yaml +# In a room: +mobs: + - id: man + wander_interval: 10 # attempt to wander every 10 ticks + - id: man + wander_interval: 15 + wander_rooms: [5, 6, 7] # optional — restrict which rooms via exits +``` + +Mobs wander through legal (unconditioned) room exits. When the wander interval expires, +the mob picks a random exit with no conditions and moves through it. If `wander_rooms` +is set, only exits leading to those room IDs are legal. Mobs without `wander_interval` +never wander. Mobs stop wandering while in combat. Dead mobs respawn at their home room. + +--- + diff --git a/worldbuilding_guide/wandering_objects.md b/worldbuilding_guide/wandering_objects.md new file mode 100644 index 0000000..9a47ed2 --- /dev/null +++ b/worldbuilding_guide/wandering_objects.md @@ -0,0 +1,23 @@ +## Wandering Objects + +Fishing spots that move between rooms: +```yaml +# data/objects/fishing_spot.yaml +id: fishing_spot +name: fishing spot +behavior: fish_trout +``` + +```yaml +# In a room: +objects: + - id: fishing_spot + wander_rooms: [7, 8, 9] + wander_interval: 12 +``` + +Objects teleport between rooms in their `wander_rooms` list. Players gathering from a +wandering object are silently interrupted when it moves. + +--- + |
