class_name RecipeCatalog ## Static registry of all recipes. Each method returns a fresh Recipe instance ## configured for that product. Extend here as new workbenches land. ## ## Phase 6 — two recipes: ## plank() — wood → plank (Carpenter's bench, Crafting) ## stone_block() — stone → stone_block (Smelter, Crafting) ## ## Phase 7 — cooking chain (grain → flour → bread, vegetable → meal): ## flour() — grain → flour (Millstone, Crafting) ## bread() — flour → bread (Hearth, Cooking) ## meal_from_vegetables() — vegetable → meal (Hearth, Cooking) ## ## The full ~22-recipe list per docs/design.md continues in Phase 8+. static func plank() -> Recipe: var r := Recipe.new() r.id = &"plank" r.label = "Wood plank" r.ingredient_type = Item.TYPE_WOOD r.output_type = Item.TYPE_PLANK r.work_ticks = 60 # ~3 sim seconds at 1× (20 Hz × 3 s = 60 ticks) r.required_skill = Recipe.SKILL_CRAFTING r.skill_threshold = 0 r.target_workbench = &"carpenter" return r static func stone_block() -> Recipe: var r := Recipe.new() r.id = &"stone_block" r.label = "Stone block" r.ingredient_type = Item.TYPE_STONE r.output_type = Item.TYPE_STONE_BLOCK r.work_ticks = 80 # ~4 sim seconds at 1× r.required_skill = Recipe.SKILL_CRAFTING r.skill_threshold = 0 r.target_workbench = &"smelter" return r # ── Phase 7 — cooking chain ─────────────────────────────────────────────────── static func flour() -> Recipe: ## Step 1 of the grain→flour→bread chain. ## Ingredient: grain. Output: flour. Worked at the Millstone (accepted_skill = crafting). ## Any crafter can do this — no culinary expertise required for grinding. var r := Recipe.new() r.id = &"flour" r.label = "Flour" r.ingredient_type = Item.TYPE_GRAIN r.output_type = Item.TYPE_FLOUR r.work_ticks = 50 # ~2.5 sim seconds at 1× — quick grinding pass r.required_skill = Recipe.SKILL_CRAFTING r.skill_threshold = 0 r.target_workbench = &"millstone" return r static func bread() -> Recipe: ## Step 2 of the grain→flour→bread chain. ## Ingredient: flour. Output: bread. Worked at the Hearth (accepted_skill = cooking). var r := Recipe.new() r.id = &"bread" r.label = "Bread" r.ingredient_type = Item.TYPE_FLOUR r.output_type = Item.TYPE_BREAD r.work_ticks = 90 # ~4.5 sim seconds at 1× — baking takes longer r.required_skill = Recipe.SKILL_COOKING r.skill_threshold = 0 return r static func meal_from_vegetables() -> Recipe: ## Single-step cooking: vegetable → meal. Worked at the Hearth (accepted_skill = cooking). ## Parallel path so harvested produce (potatoes, etc.) can reach the belly ## without going through the grain chain. var r := Recipe.new() r.id = &"meal_veg" r.label = "Veggie meal" r.ingredient_type = Item.TYPE_VEGETABLE r.output_type = Item.TYPE_MEAL r.work_ticks = 80 # ~4 sim seconds at 1× r.required_skill = Recipe.SKILL_COOKING r.skill_threshold = 0 return r # ── Phase 14 — Death + cremation ───────────────────────────────────────────── static func cremate_corpse() -> Recipe: ## Cremation recipe. Primary ingredient: 1 corpse (TYPE_CORPSE). ## Secondary ingredient: 5 wood (ingredient2_type / ingredient2_count) — see ## recipe.gd for the Phase 14 extension fields. ## Output: 1 ash item (TYPE_ASH). Work time: 60 ticks (~3 sim seconds at 1×). ## No Quality roll — cremation is binary. accepted_skill = manual_labor; ## any laborer can operate the pyre. ## ## Stub gap: CraftingProvider's ingredient-pickup step only handles the ## primary ingredient (ingredient_type = TYPE_CORPSE). The 5-wood secondary ## requirement is recorded in ingredient2_type/ingredient2_count but is NOT ## enforced at runtime until CraftingProvider is extended (Phase 14 follow-up). var r := Recipe.new() r.id = &"cremate_corpse" r.label = "Cremate corpse" r.ingredient_type = Item.TYPE_CORPSE r.ingredient2_type = Item.TYPE_WOOD r.ingredient2_count = 5 r.output_type = Item.TYPE_ASH r.work_ticks = 60 # ~3 sim seconds at 1× r.required_skill = &"manual_labor" r.target_workbench = &"pyre" r.skill_threshold = 0 return r ## Quarry workbench — no input, produces 1 stone per work cycle. Used by the ## QuarryWorkbench placed on a BigRockNode for renewable stone supply. static func quarry_stone() -> Recipe: var r := Recipe.new() r.id = &"quarry_stone" r.label = "Quarry stone" r.ingredient_type = &"" # no input r.output_type = Item.TYPE_STONE r.work_ticks = 300 r.required_skill = &"manual_labor" r.target_workbench = &"quarry" r.skill_threshold = 0 return r # ── Phase 19 — iron/gold smelting ──────────────────────────────────────────── static func iron_smelt() -> Recipe: ## Iron ore → iron ingot. Worked at the Smelter (accepted_skill = crafting). ## Secondary fuel ingredient (wood) is recorded but not yet enforced at ## runtime — CraftingProvider only checks the primary ingredient today. var r := Recipe.new() r.id = &"iron_smelt" r.label = "Smelt iron ingot" r.ingredient_type = Item.TYPE_IRON_ORE r.ingredient2_type = Item.TYPE_WOOD r.ingredient2_count = 1 r.output_type = Item.TYPE_IRON_INGOT r.work_ticks = 200 # ~10 sim seconds at 1× — slower than stone-block r.required_skill = Recipe.SKILL_CRAFTING r.skill_threshold = 0 r.target_workbench = &"smelter" return r static func gold_smelt() -> Recipe: ## Gold ore → gold ingot. Same smelting chain as iron. var r := Recipe.new() r.id = &"gold_smelt" r.label = "Smelt gold ingot" r.ingredient_type = Item.TYPE_GOLD r.ingredient2_type = Item.TYPE_WOOD r.ingredient2_count = 1 r.output_type = Item.TYPE_GOLD_INGOT r.work_ticks = 200 # ~10 sim seconds at 1× r.required_skill = Recipe.SKILL_CRAFTING r.skill_threshold = 0 r.target_workbench = &"smelter" return r ## Returns one fresh instance of every recipe in the catalog. Used by UI ## recipe-pickers to enumerate available bills; callers filter by ## `recipe.required_skill` and `recipe.target_workbench` against the ## workbench's `accepted_skill` and `label_text`. static func all() -> Array[Recipe]: return [ plank(), stone_block(), flour(), bread(), meal_from_vegetables(), cremate_corpse(), quarry_stone(), iron_smelt(), gold_smelt(), ]