diff options
| author | historia <[not public]> | 2026-06-24 20:58:25 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-24 20:58:25 -0400 |
| commit | 9d4b799db4868bcab291b83599ff088763cd4ed6 (patch) | |
| tree | 252f0fcc779acf35243983d643d6399ee2e0cd0b /building_guide/behaviors.md | |
| parent | d25638d98fe63efdeab570ef77e6a6a97f2d7a60 (diff) | |
| download | thehouseoficarus-9d4b799db4868bcab291b83599ff088763cd4ed6.tar.gz | |
feat: new type of non-violent 'combat': work
Diffstat (limited to 'building_guide/behaviors.md')
| -rw-r--r-- | building_guide/behaviors.md | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/building_guide/behaviors.md b/building_guide/behaviors.md new file mode 100644 index 0000000..22e97fe --- /dev/null +++ b/building_guide/behaviors.md @@ -0,0 +1,402 @@ +## Behaviors + +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. + +### Gather (mining, fishing, woodcutting) + +Mining — per-drop depletion on a rock object: +```yaml +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{/}`. + +Non-depleting gather (fishing on a fishing spot object): +```yaml +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: 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: 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: +- 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) + +Talk configs go under the `talk:` key on objects or mobs. Full conversation with +conditions, actions, and player flag tracking: + +```yaml +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 + +| 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: +```yaml +action: + 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) + +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: + 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 | +|---|---| +| `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. + +Full example — General Store: +```yaml +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. + +### 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": + +```yaml +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 +``` + +Item-specific interaction: +```yaml +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: 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 +``` + +--- |
