Renewable resources: tree growth + WildGrowth + Quarry on BigRockNode

Trees: 4 growth stages (Sapling→Young→Growing→Mature), only Mature
yields wood. WildGrowth ticker fires every in-game hour; rejection-
samples grass tiles and plants a sapling with ~30% probability (capped
at MAP_TREE_LIMIT=60). New `paint_plant_tree` designation lets the
player manually plant — ghost sapling registered as a build_site that
ConstructionProvider fulfils. Stage round-trips through save/load.
Initial seed mixes 4 saplings + 6 mature so growth is visible day 1.

Quarry: new BigRockNode entity (2×2 permanent stone outcrop, never
depletes). 3 nodes seeded far from cabin. New QuarryWorkbench
(extends Workbench, auto-FOREVER `quarry_stone` bill, recipe drops
1 stone per 300 work-ticks). New `paint_quarry` designation only
accepts BigRockNode tiles. CraftingProvider now supports recipes
with `ingredient_count == 0` — skips ingredient-fetch and goes
straight to walk+craft toils. Recipe gains `ingredient_count` field
(defaults 0). Save/load layering: big_rock_node spawns at priority 0
(same as rock/tree), quarry_workbench at priority 2 (after the node).

UI: Plant tree + Build quarry buttons added to Build drawer.
build_drawer_thumb gains `plant_tree` (sapling sprout in dirt) and
`paint_quarry` (stone block + chisel + cut-stone pile) shapes.
inspect_tooltip recognises BigRockNode + shows tree growth stage on
hover.

Delegation: gdscript-refactor (Sonnet ×2) for trees full impl +
quarry skeleton; quick-edit (Haiku) for CraftingProvider no-ingredient
plumbing + TopBar polish; integration handled on Opus.
This commit is contained in:
megaproxy 2026-05-16 16:36:16 +01:00
parent 296894ff7a
commit d98d2c2425
20 changed files with 716 additions and 38 deletions

View file

@ -180,10 +180,11 @@ func _build_designate_tab() -> Control:
var flow := _make_flow_grid()
box.add_child(flow)
_add_tool_btn(flow, Strings.t(&"tool.chop"), &"chop", func() -> void: _activate(&"chop", &"", Strings.t(&"tool.chop")))
_add_tool_btn(flow, Strings.t(&"tool.mine"), &"mine", func() -> void: _activate(&"mine", &"", Strings.t(&"tool.mine")))
_add_tool_btn(flow, Strings.t(&"tool.dig_grave"),&"dig_grave", func() -> void: _activate(&"dig_grave", &"", Strings.t(&"tool.dig_grave")))
_add_tool_btn(flow, Strings.t(&"tool.no_roof"), &"no_roof", func() -> void: _activate(&"no_roof", &"", Strings.t(&"tool.no_roof")))
_add_tool_btn(flow, Strings.t(&"tool.chop"), &"chop", func() -> void: _activate(&"chop", &"", Strings.t(&"tool.chop")))
_add_tool_btn(flow, Strings.t(&"tool.mine"), &"mine", func() -> void: _activate(&"mine", &"", Strings.t(&"tool.mine")))
_add_tool_btn(flow, Strings.t(&"tool.dig_grave"), &"dig_grave", func() -> void: _activate(&"dig_grave", &"", Strings.t(&"tool.dig_grave")))
_add_tool_btn(flow, Strings.t(&"tool.no_roof"), &"no_roof", func() -> void: _activate(&"no_roof", &"", Strings.t(&"tool.no_roof")))
_add_tool_btn(flow, Strings.t(&"tool.plant_tree"), &"plant_tree", func() -> void: _activate(&"plant_tree", &"", Strings.t(&"tool.plant_tree")))
return box
@ -237,6 +238,12 @@ func _build_build_tab() -> Control:
&"build_workbench_cremation_pyre",
func() -> void: _activate(&"build_workbench_cremation_pyre", &"", Strings.t(&"tool.workbench_cremation_pyre")))
# Quarry — must be painted on a stone outcrop (BigRockNode); world.gd
# rejects placements on plain ground.
_add_tool_btn(flow, Strings.t(&"tool.paint_quarry"),
&"paint_quarry",
func() -> void: _activate(&"paint_quarry", &"", Strings.t(&"tool.paint_quarry")))
return box