rimlike/scenes/ai/recipe_catalog.gd
megaproxy cc6d60d044 sprint cleanup: corpse_cremated signal, recipe_count, save_system
D: Workbench._last_consumed_ingredient transient field captures the
carried item before queue_free so cremation_pyre.on_craft_complete can
emit corpse_cremated with the real ref. Falls back to proximity scan.
Pawn._on_corpse_cremated null-guarded.

E: removed redundant r.ingredient_count = 0 from recipe_catalog. Field
kept on Recipe for save round-trip compat; nothing reads it functionally.

F: save_system._spawn_workbench simplified from 15 lines to 6 — let
from_dict do all field restoration. Fixed workbench.from_dict to call
_complete() instead of bare _completed=true, which was skipping light
enable + beauty register + designation clear.

Stale ingredient1/2 buffering comment in job_runner._tick_craft fixed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:23:22 +01:00

140 lines
5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
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
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
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.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.skill_threshold = 0
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` against the workbench's `accepted_skill`.
static func all() -> Array[Recipe]:
return [
plank(),
stone_block(),
flour(),
bread(),
meal_from_vegetables(),
cremate_corpse(),
quarry_stone(),
]