-- ===================================================================== -- content/stone_age.lua — T1-modder content pack: Stone-Age items + recipes. -- -- PURE CONTENT via the authoring API `c` (see init.lua's content facade): -- c.T{ id, name, desc, weight, vol, material={...}, affordance={...}, -- atlas="tc"|"stone", uv="", scale? } -- define an item -- c.R{ ...crafting.define_recipe def... } -- define a recipe -- c.S{ template, x, y } -- place item in world -- -- ROLE-BASED RECIPES (the intent): a recipe slot asks for the CAPABILITY it -- needs, and ANY item that offers that capability qualifies — not a specific -- item id. Capabilities are expressed as property-constraints (crafting v0.3 / -- ADR-0055 + its 2026-07-31 amendment). Two orthogonal axes carry a recipe: -- * `affordance.*` — what an item OFFERS / can DO / what role it fills: -- cutting / hammering / chopping / leverage / binding / -- spinnable / knappable / piercing … (open vocabulary) -- * `composition.*`— material makeup (wood / stone / fiber …) -- * `weight` — mass discriminator (light stick vs heavy branch) -- e.g. a "haft" = { ["affordance.leverage"]=true } → any stick OR branch OR -- pole works. The SAME affordance vocabulary is required by both consumed -- `inputs` and non-consumed `tools`; the inputs/tools split (not a separate -- axis) says whether the item is used up. -- -- `form` was RETIRED (ADR-0055 amendment): a physical-shape axis mixed -- geometry, identity and capability. Its functional members became -- affordances; its identity members (a "tree") stay template-id. -- -- Template-id matching ({ template="tree" }) is ALSO valid — it is just the -- trivial one-property constraint — and is used where a recipe genuinely wants -- one specific item (see rock_pick/rock_pile in init.lua, and chop_tree below). -- Role-based is the default; template-id is one of the options, not the norm. -- ===================================================================== return function(c) -- ---- items (each tagged with the CAPABILITIES it offers) --------- -- NOTE: `rock` (affordance.knappable) and `stick` (affordance.leverage, -- weight 0.3) are BASE items defined in init.lua; this pack's role-based -- recipes match them by affordance the same as pack items. -- World-gathered c.T{ id = "branch", name = "Branch", desc = "A heavy springy branch. Snap it into sticks.", weight = 1.5, vol = 0.006, material = { wood = 1.0 }, affordance = { leverage = true }, -- a haft candidate, but heavy atlas = "tc", uv = "log_pile1", scale = 0.85 } c.T{ id = "log", name = "Log", desc = "A heavy wooden log. Saw it into planks.", weight = 20, vol = 0.05, material = { wood = 1.0 }, -- raw heavy wood; matched by material+weight atlas = "tc", uv = "log_pile1" } c.T{ id = "tree", name = "Tree", desc = "A standing tree. Chop it down for logs.", weight = 400, vol = 1.0, material = { wood = 1.0 }, -- one concrete item → matched by template-id atlas = "tc", uv = "log_pile1", scale = 1.6 } c.T{ id = "plant_fiber", name = "Plant Fiber", desc = "Tough plant fiber. Twist several into cordage.", weight = 0.05, vol = 0.0002, material = { fiber = 1.0 }, affordance = { spinnable = true }, -- can be twisted; cord itself is NOT spinnable atlas = "tc", uv = "sack1", scale = 0.6 } -- Crafted c.T{ id = "sharp_stone", name = "Sharp Stone", desc = "A knapped stone with a cutting edge.", weight = 1, vol = 0.0004, material = { stone = 1.0 }, affordance = { cutting = true }, -- "blade" role = affords cutting atlas = "tc", uv = "spade" } c.T{ id = "cordage", name = "Cordage", desc = "Twisted plant-fiber cord. A binding.", weight = 0.1, vol = 0.0003, material = { fiber = 1.0 }, affordance = { binding = true }, -- "cord" role = affords binding (NOT spinnable → no re-twist) atlas = "tc", uv = "sack1" } c.T{ id = "plank", name = "Plank", desc = "A sawn wooden plank.", weight = 2, vol = 0.004, material = { wood = 1.0 }, -- output only; light wood (not re-sawable) atlas = "tc", uv = "bench1" } c.T{ id = "stone_axe", name = "Stone Axe", desc = "A hafted stone axe. Chops wood.", weight = 1.8, vol = 0.0012, material = { stone = 0.6, wood = 0.3, fiber = 0.1 }, affordance = { chopping = true }, atlas = "tc", uv = "spade" } c.T{ id = "stone_hammer", name = "Stone Hammer", desc = "A stone lashed to a haft. Pounds and knaps.", weight = 1.5, vol = 0.001, material = { stone = 0.6, wood = 0.3, fiber = 0.1 }, affordance = { hammering = true }, atlas = "tc", uv = "spade" } c.T{ id = "sharpened_stick", name = "Sharpened Stick", desc = "A stick whittled to a point. A crude spear.", weight = 0.3, vol = 0.0005, material = { wood = 1.0 }, affordance = { piercing = true }, atlas = "tc", uv = "log_pile1", scale = 0.9 } -- ---- recipes (match by CAPABILITY, not by item id) -------------- -- knap: any KNAPPABLE stone + a HAMMERING tool -> a cutting edge. -- (rock is knappable; sharp_stone is NOT → no self-recursion.) c.R{ id = "knap_sharp_stone", inputs = { { match = { ["affordance.knappable"] = true }, count = 1 } }, tools = { { match = { ["affordance.hammering"] = true } } }, outputs = { { template = "sharp_stone", count = 1 } }, name = "Knap Sharp Stone", description = "Strike a stone with a hammerstone to flake off a sharp edge." } -- cordage: three SPINNABLE fibers (any fiber source) -> cord. -- (cordage is binding-but-not-spinnable → you can't re-twist cord.) c.R{ id = "twist_cordage", inputs = { { match = { ["affordance.spinnable"] = true }, count = 3 } }, outputs = { { template = "cordage", count = 1 } }, name = "Twist Cordage", description = "Twist three plant fibers into a length of cordage." } -- hammer: a heavy STONE head + a LEVERAGE haft + a BINDING. -- head matched the primitive way (material+mass); haft/binding by affordance — -- one recipe, both matching styles, one mechanism (ADR-0055). c.R{ id = "craft_stone_hammer", inputs = { { match = { ["composition.stone"] = ">0.5", weight = ">1" }, count = 1 }, -- head (a stone chunk) { match = { ["affordance.leverage"] = true }, count = 1 }, -- haft (stick OR branch) { match = { ["affordance.binding"] = true }, count = 1 }, -- binding }, outputs = { { template = "stone_hammer", count = 1 } }, name = "Haft Stone Hammer", description = "Lash a stone to a haft for a pounding tool (enables knapping)." } -- axe: a CUTTING head + a LEVERAGE haft + a BINDING. c.R{ id = "craft_stone_axe", inputs = { { match = { ["affordance.cutting"] = true }, count = 1 }, -- head (a sharp stone) { match = { ["affordance.leverage"] = true }, count = 1 }, -- haft { match = { ["affordance.binding"] = true }, count = 1 }, -- binding }, outputs = { { template = "stone_axe", count = 1 } }, name = "Haft Stone Axe", description = "Bind a sharp stone to a haft with cordage." } -- break: a HEAVY leverage-thing (branch, not a light stick) -> two sticks. c.R{ id = "break_branch", inputs = { { match = { ["affordance.leverage"] = true, weight = ">1" }, count = 1 } }, outputs = { { template = "stick", count = 2 } }, name = "Break Branch", description = "Snap a heavy branch over your knee into two sticks." } -- sharpen: a LIGHT leverage-thing (a stick) + a CUTTING tool -> pointed stick. c.R{ id = "sharpen_stick", inputs = { { match = { ["affordance.leverage"] = true, weight = "<1" }, count = 1 } }, tools = { { match = { ["affordance.cutting"] = true } } }, outputs = { { template = "sharpened_stick", count = 1 } }, name = "Sharpen Stick", description = "Whittle a stick to a point with a cutting edge." } -- chop: THE tree (genuine single item → template-id) + a CHOPPING tool -> logs. -- (Multiple tree species would switch this to an affordance/material match.) c.R{ id = "chop_tree", inputs = { { match = { template = "tree" }, count = 1 } }, tools = { { match = { ["affordance.chopping"] = true } } }, outputs = { { template = "log", count = 2 } }, name = "Chop Tree", description = "Fell a tree with a chopping edge — yields two logs." } -- saw: any heavy WOOD (matched by material+mass) + a CUTTING tool -> planks. -- A light plank (weight 2) is correctly not re-sawable. c.R{ id = "saw_planks", inputs = { { match = { ["composition.wood"] = ">0.5", weight = ">5" }, count = 1 } }, tools = { { match = { ["affordance.cutting"] = true } } }, outputs = { { template = "plank", count = 4 } }, name = "Saw Planks", description = "Saw a heavy wooden log into four planks (needs a cutting edge)." } -- ---- world spawns (backpack sits at 350,400) --------------------- c.S{ template = "log", x = 110, y = 400 } c.S{ template = "sharp_stone", x = 110, y = 330 } for i = 1, 3 do c.S{ template = "plant_fiber", x = 50, y = 300 + (i - 1) * 28 } end c.S{ template = "branch", x = 50, y = 250 } c.S{ template = "branch", x = 85, y = 250 } c.S{ template = "tree", x = 200, y = 190 } end