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:
parent
296894ff7a
commit
d98d2c2425
20 changed files with 716 additions and 38 deletions
|
|
@ -29,6 +29,7 @@ const _PAWN_SCENE: PackedScene = preload("res://scenes/pawn/pawn.tscn")
|
|||
const _TREE_SCENE: PackedScene = preload("res://scenes/entities/tree.tscn")
|
||||
const _ROCK_SCENE: PackedScene = preload("res://scenes/entities/rock.tscn")
|
||||
const _BIG_ROCK_SCENE: PackedScene = preload("res://scenes/entities/big_rock.tscn")
|
||||
const _BIG_ROCK_NODE_SCENE: PackedScene = preload("res://scenes/entities/big_rock_node.tscn")
|
||||
const _ITEM_SCENE: PackedScene = preload("res://scenes/entities/item.tscn")
|
||||
const _WALL_SCENE: PackedScene = preload("res://scenes/entities/wall.tscn")
|
||||
const _FLOOR_SCENE: PackedScene = preload("res://scenes/entities/floor.tscn")
|
||||
|
|
@ -276,6 +277,7 @@ func _collect_entities() -> Array:
|
|||
var registries: Array = [
|
||||
World.trees,
|
||||
World.rocks,
|
||||
World.big_rock_nodes,
|
||||
World.items,
|
||||
World.build_queue, # ghost walls / floors / doors / grave_slots
|
||||
World.doors,
|
||||
|
|
@ -316,6 +318,7 @@ const _SPAWN_PRIORITY: Dictionary = {
|
|||
&"tree": 0,
|
||||
&"rock": 0,
|
||||
&"big_rock": 0,
|
||||
&"big_rock_node": 0,
|
||||
&"wall": 0,
|
||||
&"floor": 0,
|
||||
&"door": 1,
|
||||
|
|
@ -351,6 +354,7 @@ func _register_factories() -> void:
|
|||
_factories[&"tree"] = _spawn_tree
|
||||
_factories[&"rock"] = _spawn_rock
|
||||
_factories[&"big_rock"] = _spawn_big_rock
|
||||
_factories[&"big_rock_node"] = _spawn_big_rock_node
|
||||
_factories[&"item"] = _spawn_item
|
||||
_factories[&"wall"] = _spawn_wall
|
||||
_factories[&"floor"] = _spawn_floor
|
||||
|
|
@ -377,8 +381,18 @@ func _register_factories() -> void:
|
|||
func _spawn_tree(world_scene: Node, d: Dictionary) -> void:
|
||||
var ent = _TREE_SCENE.instantiate()
|
||||
world_scene.add_child(ent)
|
||||
ent.setup(Vector2i(int(d.get("tile_x", 0)), int(d.get("tile_y", 0))))
|
||||
# Pass growth_stage to setup() so _refresh_sprite() picks the right visual.
|
||||
# Default 3 (STAGE_MATURE) so pre-growth-system saves load as mature trees.
|
||||
var gs: int = int(d.get("growth_stage", 3))
|
||||
ent.setup(Vector2i(int(d.get("tile_x", 0)), int(d.get("tile_y", 0))), gs)
|
||||
ent.chop_progress = int(d.get("chop_progress", 0))
|
||||
ent.growth_progress = int(d.get("growth_progress", 0))
|
||||
ent.chop_designated = bool(d.get("chop_designated", false))
|
||||
ent.pending_plant = bool(d.get("pending_plant", false))
|
||||
ent._plant_progress = int(d.get("plant_progress", 0))
|
||||
# Re-register as build site if planting is still in progress.
|
||||
if ent.pending_plant:
|
||||
World.register_build_site(ent)
|
||||
ent.queue_redraw()
|
||||
|
||||
|
||||
|
|
@ -398,6 +412,14 @@ func _spawn_big_rock(world_scene: Node, d: Dictionary) -> void:
|
|||
ent.queue_redraw()
|
||||
|
||||
|
||||
func _spawn_big_rock_node(world_scene: Node, d: Dictionary) -> void:
|
||||
var ent = _BIG_ROCK_NODE_SCENE.instantiate()
|
||||
world_scene.add_child(ent)
|
||||
ent.setup(Vector2i(int(d.get("tile_x", 0)), int(d.get("tile_y", 0))))
|
||||
ent.is_quarry_site = bool(d.get("is_quarry_site", false))
|
||||
ent.queue_redraw()
|
||||
|
||||
|
||||
func _spawn_item(world_scene: Node, d: Dictionary) -> void:
|
||||
var ent = _ITEM_SCENE.instantiate()
|
||||
world_scene.add_child(ent)
|
||||
|
|
|
|||
|
|
@ -194,8 +194,15 @@ const TABLE: Dictionary = {
|
|||
&"tool.workbench_millstone": "Millstone",
|
||||
&"tool.workbench_hearth": "Hearth",
|
||||
&"tool.workbench_cremation_pyre": "Cremation Pyre",
|
||||
&"tool.paint_quarry": "Build quarry",
|
||||
&"tool.stockpile_general": "Stockpile",
|
||||
&"tool.graveyard": "Graveyard",
|
||||
&"tool.plant_tree": "Plant tree",
|
||||
# Tree growth stage names (shown in inspect tooltip).
|
||||
&"tree.stage.sapling": "Sapling",
|
||||
&"tree.stage.young": "Young tree",
|
||||
&"tree.stage.growing": "Growing tree",
|
||||
&"tree.stage.mature": "Mature tree",
|
||||
&"ui.bill.mode_forever": "Forever",
|
||||
&"ui.bill.mode_count": "Do X times",
|
||||
&"ui.bill.mode_until_n": "Do until X",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ var work_providers: Array = []
|
|||
# from their _ready/_exit_tree. Phase 16 will add stable IDs and persistence wiring.
|
||||
var trees: Array = [] # Array of Tree
|
||||
var rocks: Array = [] # Array of Rock
|
||||
var big_rock_nodes: Array = [] # Array of BigRockNode (permanent stone outcrops)
|
||||
var items: Array = [] # Array of Item (on-floor stacks)
|
||||
var stockpiles: Array = [] # Array of StorageDestination (StockpileZone for now; containers Phase 5)
|
||||
|
||||
|
|
@ -207,6 +208,24 @@ func unregister_rock(r) -> void:
|
|||
rocks.erase(r)
|
||||
|
||||
|
||||
func register_big_rock_node(n) -> void:
|
||||
if not big_rock_nodes.has(n):
|
||||
big_rock_nodes.append(n)
|
||||
|
||||
|
||||
func unregister_big_rock_node(n) -> void:
|
||||
big_rock_nodes.erase(n)
|
||||
|
||||
|
||||
## Returns the BigRockNode whose 2×2 footprint covers `tile`, or null.
|
||||
## Used by `paint_quarry` designation to validate the build site.
|
||||
func big_rock_node_at_tile(tile: Vector2i):
|
||||
for n in big_rock_nodes:
|
||||
if n.is_at(tile):
|
||||
return n
|
||||
return null
|
||||
|
||||
|
||||
func register_item(it) -> void:
|
||||
if items.has(it):
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue