# 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 | | `fail_message` | string | Failure message | | `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. ### 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 stim potion." ``` ### 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 bronze bar." ``` ```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: "You hammer out a bronze dagger." ``` 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: "You hammer out some bronze nails." ``` ### 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 water into the 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 ancient map." ``` ### 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: "You clean the grimy guam leaf." ``` ### 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