aboutsummaryrefslogtreecommitdiff
path: root/building_guide/behaviors.md
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-24 20:58:25 -0400
committerhistoria <[not public]>2026-06-24 20:58:25 -0400
commit9d4b799db4868bcab291b83599ff088763cd4ed6 (patch)
tree252f0fcc779acf35243983d643d6399ee2e0cd0b /building_guide/behaviors.md
parentd25638d98fe63efdeab570ef77e6a6a97f2d7a60 (diff)
downloadthehouseoficarus-9d4b799db4868bcab291b83599ff088763cd4ed6.tar.gz
feat: new type of non-violent 'combat': work
Diffstat (limited to 'building_guide/behaviors.md')
-rw-r--r--building_guide/behaviors.md402
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
+```
+
+---