From c6033b63fb159d3a5bc7ccbef2620b04a9072c7a Mon Sep 17 00:00:00 2001 From: Rijad Zuzo Date: Fri, 3 Jul 2026 18:32:34 +0200 Subject: [PATCH] feat: authoritative extraction from ResourceNode on task completion Phase 3 of ResourceNode migration: - Add apply_resource_delta to SimVillage for clean resource changes - Extract from reserved ResourceNode on task completion instead of hard-coded apply_npc_task for gather_food/gather_wood - Detect depleted/unavailable targets on arrival and replan --- simulation/SimVillage.gd | 19 +++++++++++++++++++ simulation/SimulationManager.gd | 19 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/simulation/SimVillage.gd b/simulation/SimVillage.gd index 5bf64f4..f9ae6b3 100644 --- a/simulation/SimVillage.gd +++ b/simulation/SimVillage.gd @@ -69,6 +69,25 @@ func update_priorities() -> void: if DEBUG_LOGS: print(get_priority_summary()) +func apply_resource_delta(resource_id: StringName, amount: float) -> void: + match resource_id: + &"food": + food += amount + &"wood": + wood += amount + &"safety": + safety = clamp(safety + amount, 0.0, 100.0) + &"knowledge": + knowledge += amount + + food = max(food, 0.0) + wood = max(wood, 0.0) + safety = clamp(safety, 0.0, 100.0) + knowledge = max(knowledge, 0.0) + + update_modifiers() + update_priorities() + func apply_npc_task(npc: SimNPC) -> void: if npc.is_dead: return diff --git a/simulation/SimulationManager.gd b/simulation/SimulationManager.gd index 46af4d6..11fa421 100644 --- a/simulation/SimulationManager.gd +++ b/simulation/SimulationManager.gd @@ -86,9 +86,17 @@ func simulate_tick() -> void: var needs_immediate_food_after_gather := npc.should_eat_immediately_after_task() if npc.target_id != &"": + var node := ResourceNode.get_by_id(npc.target_id) + if node != null: + var extracted := node.extract() + if extracted > 0: + village.apply_resource_delta(node.resource_id, extracted) + if DEBUG_LOGS: + print("[SimulationManager] ", npc.npc_name, " extracted ", extracted, " ", node.resource_id, " from ", node.node_id) release_npc_reservation(npc.id) + else: + village.apply_npc_task(npc) - village.apply_npc_task(npc) village_was_changed = true npc.task_complete = true @@ -161,6 +169,15 @@ func notify_npc_arrived(npc_id: int) -> void: return if npc.task_state == SimNPC.TASK_STATE_TRAVELING: + if npc.target_id != &"": + var node := ResourceNode.get_by_id(npc.target_id) + if node == null or not node.can_extract(): + if DEBUG_LOGS: + print("[SimulationManager] ", npc.npc_name, " arrived but target ", npc.target_id, " is unavailable, replanning") + release_npc_reservation(npc.id) + npc.task_state = SimNPC.TASK_STATE_IDLE + return + npc.start_working() if DEBUG_LOGS: