aboutsummaryrefslogtreecommitdiff
path: root/building_guide/recipes.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/recipes.md
parentd25638d98fe63efdeab570ef77e6a6a97f2d7a60 (diff)
downloadthehouseoficarus-9d4b799db4868bcab291b83599ff088763cd4ed6.tar.gz
feat: new type of non-violent 'combat': work
Diffstat (limited to 'building_guide/recipes.md')
-rw-r--r--building_guide/recipes.md277
1 files changed, 277 insertions, 0 deletions
diff --git a/building_guide/recipes.md b/building_guide/recipes.md
new file mode 100644
index 0000000..450ded9
--- /dev/null
+++ b/building_guide/recipes.md
@@ -0,0 +1,277 @@
+# The House of Icarus - World Building Guide
+
+## Crafting
+
+Crafting information lives on the **output item's YAML file** via the `craft:` block. There is no separate recipe directory. To find out how to make `bronze_dagger`, open `data/items/equipment/bronze_dagger.yaml` and look for the `craft:` block.
+
+### Craft YAML Reference
+
+| Field | Type | Description |
+| -------------- | -------------- | ----------------------------------------------- |
+| `type` | string | Craft type (pharmacy, smithing, cooking, smelting, crafting, fletching, construction, clean, or "" for skill-less) |
+| `skill` | string | Skill checked (defaults to type if omitted) |
+| `level` | int | Required skill level |
+| `xp` | int | XP awarded on success |
+| `wait` | float64 | Ticks per craft cycle |
+| `station` | []string | Station object IDs required (optional) |
+| `tool` | string | Required tool_type (optional) |
+| `consume` | []ConsumeEntry | Ingredients consumed (see below) |
+| `output_qty` | int | Quantity produced (default 1, for stackables) |
+| `fail` | string | ItemID produced on failure (optional) |
+| `message` | string | Success message per cycle (optional, see message defaults) |
+| `fail_message` | string | Failure message (optional, empty = silent fail) |
+| `start_message`| string | Message when action begins (optional, see message defaults) |
+| `end_message` | string | Message when action completes (optional, see message defaults) |
+| `steps` | []CraftStep | Multi-step messages at tick intervals (optional)|
+| `success` | SuccessFormula | Optional skill check formula (see Behaviors) |
+
+The output is the item itself — no `output` field needed. The item ID IS the craft ID.
+
+### Message Variables
+
+All message fields (`message`, `fail_message`, `start_message`, `end_message`, and `steps[].message`) support variables that expand to colorized item names:
+
+| Variable | Expands to |
+| -------- | ----------------------------------------------- |
+| `%n` | Output item name (colored, e.g. "stim potion") |
+| `%i1` | 1st consume entry's matched item (colored) |
+| `%i2` | 2nd consume entry's matched item (colored) |
+| `%b1` | 1st byproduct item name (colored, success only) |
+| `%b2` | 2nd byproduct item name (colored, success only) |
+
+Numbering follows YAML consume/byproduct order. If a consume entry has multiple alternative items (`items: [a, b]`), the variable expands to whichever the player actually possesses, colored with that item's `color:` field.
+
+Variables work alongside inline color tags (`{196}text{/}`) which are expanded after variable substitution.
+
+### Message Defaults
+
+If a message field is omitted from the YAML, the game uses a skill-level default based on the craft `type`:
+
+| Type | Default `message` | Default `start_message` |
+|------|-------------------|------------------------|
+| `cooking` | `"Cooked to perfection. %n looks great!"` | `"You start cooking %i1."` |
+| `smelting` | `"You remove a white hot %n!"` | `"You place the %i1 into the furnace."` |
+| `smithing` | `"You smith a %n."` | `"You begin smithing %i1."` |
+| `crafting` | `"You craft a %n."` | `"You begin crafting %i1."` |
+| `fletching` | `"You fletch a %n."` | `"You begin fletching %i1."` |
+| `pharmacy` | `"You mix a %n."` | `"You start mixing %i1."` |
+| `construction` | `"You construct a %n."` | `"You begin constructing %i1."` |
+| `clean` | `"You clean the %i1."` | `"You begin cleaning herbs."` |
+| (unset) | `"You produce %n."` | `"You start <verb> %i1."` |
+
+Any of these can be overridden per-item by setting the field in YAML. For skills that never fail (smithing, crafting, fletching, pharmacy, construction), `fail_message` defaults to empty — no message is shown on failure.
+
+### CraftStep — Multi-Step Messages
+
+Optional interim messages fired at specific tick offsets during the craft cycle. The `tick` is the number of ticks elapsed since the start of the cycle.
+
+```yaml
+craft:
+ type: ""
+ wait: 6
+ consume:
+ - items: [map_piece_1]
+ quantity: 1
+ - items: [map_piece_2]
+ quantity: 1
+ - items: [map_piece_3]
+ quantity: 1
+ steps:
+ - tick: 1
+ message: "You try to puzzle how the pieces fit together."
+ - tick: 3
+ message: "Aha, this edge lines up here!"
+ message: "You assemble the map!"
+```
+
+### 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, ...]
+ quantity: 1
+ byproducts: [byproduct_for_item, byproduct_for_alt, ...]
+```
+
+`byproducts` is optional. When present, it matches the `items` list by index — consuming `items[0]` returns `byproducts[0]` to inventory. Use `""` for items with no byproduct:
+
+```yaml
+consume:
+ - items: [bucket_of_water, vial_of_water]
+ quantity: 1
+ byproducts: [empty_bucket, ""] # bucket returns empty, vial is consumed entirely
+ - items: [herb]
+ quantity: 1 # no byproducts — herb is consumed entirely
+```
+
+### Skill-Based Production
+
+```yaml
+# data/items/consumables/stim_potion.yaml
+craft:
+ type: pharmacy
+ skill: pharmacy
+ level: 3
+ xp: 25
+ wait: 4
+ consume:
+ - items: [guam_potion_unf]
+ quantity: 1
+ - items: [eye_of_newt]
+ quantity: 1
+ message: "You mix a %n." # %n expands to "stim potion" colored
+```
+
+### Station-Based Production
+
+```yaml
+# data/items/materials/bronze_bar.yaml
+craft:
+ type: smelting
+ skill: smithing
+ level: 1
+ xp: 6
+ wait: 4
+ station: [furnace]
+ consume:
+ - items: [copper_ore]
+ quantity: 1
+ - items: [tin_ore]
+ quantity: 1
+ message: "You smelt a %n." # default is "You remove a white hot %n!"
+ # overridden here for simpler flavor
+```
+
+```yaml
+# data/items/equipment/bronze_dagger.yaml
+craft:
+ type: smithing
+ skill: smithing
+ level: 1
+ xp: 12
+ wait: 4
+ station: [anvil]
+ consume:
+ - items: [bronze_bar]
+ quantity: 1
+ # message omitted — uses default "You smith a %n."
+```
+
+For stackable outputs, use `output_qty`:
+
+```yaml
+# data/items/ammo/bronze_nails.yaml
+craft:
+ type: smithing
+ skill: smithing
+ level: 4
+ xp: 12
+ wait: 4
+ station: [anvil]
+ consume:
+ - items: [bronze_bar]
+ quantity: 1
+ output_qty: 15
+ # message omitted — uses default "You smith a %n."
+```
+
+### Tool-Based Production
+
+```yaml
+# data/items/ammo/arrow_shafts.yaml
+craft:
+ type: fletching
+ level: 1
+ xp: 5
+ wait: 3
+ tool: knife
+ consume:
+ - items: [logs, oak_logs, willow_logs]
+ quantity: 1
+ output_qty: 15
+```
+
+The `tool` field requires the player to have an item with that `tool_type` equipped or in inventory. The tool is NOT consumed.
+
+### Skill-Less Combinations (Item-on-Item)
+
+Omit `type` (or leave it empty) for combinations with no skill check, no XP, and 100% success:
+
+```yaml
+# data/items/consumables/bucket_of_water.yaml
+craft:
+ wait: 0
+ consume:
+ - items: [vial_of_water, jug_of_water]
+ quantity: 1
+ byproducts: [empty_vial, empty_jug]
+ - items: [empty_bucket]
+ quantity: 1
+ message: "You pour the %i1 into the %i2." # %i1 = water source, %i2 = bucket
+```
+
+### Multi-Piece Assembly (3+ items → 1)
+
+```yaml
+# data/items/quest/ancient_map.yaml
+craft:
+ wait: 0
+ consume:
+ - items: [torn_page_1]
+ quantity: 1
+ - items: [torn_page_2]
+ quantity: 1
+ - items: [torn_page_3]
+ quantity: 1
+ steps:
+ - tick: 1
+ message: "You try to puzzle how the pieces fit together."
+ - tick: 3
+ message: "Aha, this edge lines up here!"
+ message: "You assemble the %n."
+```
+
+### Clean Recipes
+
+Clean herb recipes use `type: clean` and are handled as background actions (one herb per cycle, directly mutating inventory):
+
+```yaml
+# data/items/materials/guam.yaml (clean guam)
+craft:
+ type: clean
+ skill: pharmacy
+ level: 3
+ xp: 3
+ wait: 2
+ consume:
+ - items: [grimy_guam]
+ quantity: 1
+ # message omitted — uses default "You clean the %i1."
+ # %i1 expands to the grimy herb name with its color
+```
+
+### Food/Healing Items
+
+Items with `heal_value` and `eat_message` can be consumed via the `eat` command.
+
+```yaml
+id: bread
+name: bread
+color: "222"
+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."
+```
+
+### Architecture
+
+The `CraftIndex` (`internal/game/craft_index.go`) is built once at startup from all item YAMLs that have a `craft:` block. It provides `O(1)` lookups by type, input item, and station. All crafting commands query the CraftIndex — no runtime file scanning.
+
+**Indexes:**
+- `byType["pharmacy"]` → all pharmacy-craftable items (used by `mix`)
+- `byInput["guam"]` → all items that consume guam (used by `use` to find combinations)
+- `byStation["anvil"]` → all items craftable at an anvil (used by `use bar on anvil`)
+- `FindByTwoInputs(a, b)` → items consuming both inputs in different consume entries