feat: wood inventory, carrying, and woodpile storage
Wood now follows the same gather-carry-deposit pattern as food. NPCs put harvested wood into inventory, walk to the VillageWoodpile StorageNode, and deposit it. Village wood syncs from storage. Player harvesting also routes wood to the woodpile. ActiveWorldAdapter exposes woodpile routing for DEPOSIT_WOOD action targeting. WorldViewManager recognizes wood inventory changes. Tests verify woodpile node existence, storage ID, navigation reachability, and adapter routing.
This commit is contained in:
@@ -162,6 +162,13 @@ func simulate_tick() -> void:
|
||||
SimulationIds.RESOURCE_FOOD,
|
||||
npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD)
|
||||
)
|
||||
elif resource_state.get_resource_id() == SimulationIds.RESOURCE_WOOD:
|
||||
npc.add_inventory(SimulationIds.RESOURCE_WOOD, extracted)
|
||||
npc_inventory_changed.emit(
|
||||
npc,
|
||||
SimulationIds.RESOURCE_WOOD,
|
||||
npc.get_inventory_amount(SimulationIds.RESOURCE_WOOD)
|
||||
)
|
||||
else:
|
||||
village.apply_resource_delta(
|
||||
resource_state.get_resource_id(), extracted
|
||||
@@ -172,7 +179,9 @@ func simulate_tick() -> void:
|
||||
resource_state.get_node_id(),
|
||||
(
|
||||
_npc_inventory_id(npc.id)
|
||||
if resource_state.get_resource_id() == SimulationIds.RESOURCE_FOOD
|
||||
if resource_state.get_resource_id() in [
|
||||
SimulationIds.RESOURCE_FOOD, SimulationIds.RESOURCE_WOOD
|
||||
]
|
||||
else &"village"
|
||||
),
|
||||
resource_state.get_resource_id(),
|
||||
@@ -200,6 +209,8 @@ func simulate_tick() -> void:
|
||||
release_npc_reservation(npc.id)
|
||||
elif completed_task == SimulationIds.ACTION_DEPOSIT_FOOD:
|
||||
deposit_npc_inventory(npc, SimulationIds.RESOURCE_FOOD)
|
||||
elif completed_task == SimulationIds.ACTION_DEPOSIT_WOOD:
|
||||
deposit_npc_wood(npc)
|
||||
elif completed_task == SimulationIds.ACTION_WITHDRAW_FOOD:
|
||||
withdraw_to_npc(npc, SimulationIds.RESOURCE_FOOD, 1.0)
|
||||
elif completed_task == SimulationIds.ACTION_EAT:
|
||||
@@ -450,19 +461,28 @@ func _record_economic_event(
|
||||
|
||||
|
||||
func _initialize_storage() -> void:
|
||||
if storage_states.has(SimulationIds.STORAGE_VILLAGE_PANTRY):
|
||||
_sync_village_food()
|
||||
return
|
||||
storage_states[SimulationIds.STORAGE_VILLAGE_PANTRY] = (StorageStateRecord.create(
|
||||
SimulationIds.STORAGE_VILLAGE_PANTRY, {String(SimulationIds.RESOURCE_FOOD): village.food}
|
||||
))
|
||||
if not storage_states.has(SimulationIds.STORAGE_VILLAGE_PANTRY):
|
||||
storage_states[SimulationIds.STORAGE_VILLAGE_PANTRY] = (StorageStateRecord.create(
|
||||
SimulationIds.STORAGE_VILLAGE_PANTRY,
|
||||
{String(SimulationIds.RESOURCE_FOOD): village.food}
|
||||
))
|
||||
if not storage_states.has(SimulationIds.STORAGE_VILLAGE_WOODPILE):
|
||||
storage_states[SimulationIds.STORAGE_VILLAGE_WOODPILE] = (StorageStateRecord.create(
|
||||
SimulationIds.STORAGE_VILLAGE_WOODPILE,
|
||||
{String(SimulationIds.RESOURCE_WOOD): village.wood}
|
||||
))
|
||||
_sync_village_food()
|
||||
_sync_village_wood()
|
||||
|
||||
|
||||
func get_pantry() -> StorageStateRecord:
|
||||
return storage_states.get(SimulationIds.STORAGE_VILLAGE_PANTRY) as StorageStateRecord
|
||||
|
||||
|
||||
func get_woodpile() -> StorageStateRecord:
|
||||
return storage_states.get(SimulationIds.STORAGE_VILLAGE_WOODPILE) as StorageStateRecord
|
||||
|
||||
|
||||
func register_loaded_storage_nodes() -> void:
|
||||
for candidate in StorageNode.get_all():
|
||||
var node := candidate as StorageNode
|
||||
@@ -490,6 +510,14 @@ func _sync_village_food() -> void:
|
||||
village.update_priorities()
|
||||
|
||||
|
||||
func _sync_village_wood() -> void:
|
||||
var woodpile := get_woodpile()
|
||||
if woodpile != null:
|
||||
village.wood = woodpile.get_amount(SimulationIds.RESOURCE_WOOD)
|
||||
village.update_modifiers()
|
||||
village.update_priorities()
|
||||
|
||||
|
||||
func deposit_npc_inventory(npc: SimNPC, item_id: StringName) -> float:
|
||||
var available := npc.get_inventory_amount(item_id)
|
||||
var deposited := get_pantry().deposit(item_id, available)
|
||||
@@ -508,6 +536,29 @@ func deposit_npc_inventory(npc: SimNPC, item_id: StringName) -> float:
|
||||
return deposited
|
||||
|
||||
|
||||
func deposit_npc_wood(npc: SimNPC) -> float:
|
||||
var available := npc.get_inventory_amount(SimulationIds.RESOURCE_WOOD)
|
||||
var woodpile := get_woodpile()
|
||||
if woodpile == null:
|
||||
return 0.0
|
||||
var deposited := woodpile.deposit(SimulationIds.RESOURCE_WOOD, available)
|
||||
npc.remove_inventory(SimulationIds.RESOURCE_WOOD, deposited)
|
||||
_sync_village_wood()
|
||||
if deposited > 0.0:
|
||||
npc_inventory_changed.emit(
|
||||
npc, SimulationIds.RESOURCE_WOOD, npc.get_inventory_amount(SimulationIds.RESOURCE_WOOD)
|
||||
)
|
||||
_record_economic_event(
|
||||
SimulationIds.EVENT_STORAGE_DEPOSITED,
|
||||
npc.id,
|
||||
_npc_inventory_id(npc.id),
|
||||
SimulationIds.STORAGE_VILLAGE_WOODPILE,
|
||||
SimulationIds.RESOURCE_WOOD,
|
||||
deposited
|
||||
)
|
||||
return deposited
|
||||
|
||||
|
||||
func withdraw_to_npc(npc: SimNPC, item_id: StringName, amount: float) -> float:
|
||||
var withdrawn := get_pantry().withdraw(item_id, amount)
|
||||
npc.add_inventory(item_id, withdrawn)
|
||||
@@ -620,6 +671,9 @@ func harvest_resource_node(node: ResourceNode) -> float:
|
||||
if resource_state.get_resource_id() == SimulationIds.RESOURCE_FOOD:
|
||||
get_pantry().deposit(SimulationIds.RESOURCE_FOOD, extracted)
|
||||
_sync_village_food()
|
||||
elif resource_state.get_resource_id() == SimulationIds.RESOURCE_WOOD:
|
||||
get_woodpile().deposit(SimulationIds.RESOURCE_WOOD, extracted)
|
||||
_sync_village_wood()
|
||||
else:
|
||||
village.apply_resource_delta(resource_state.get_resource_id(), extracted)
|
||||
_record_economic_event(
|
||||
@@ -629,7 +683,11 @@ func harvest_resource_node(node: ResourceNode) -> float:
|
||||
(
|
||||
SimulationIds.STORAGE_VILLAGE_PANTRY
|
||||
if resource_state.get_resource_id() == SimulationIds.RESOURCE_FOOD
|
||||
else &"village"
|
||||
else (
|
||||
SimulationIds.STORAGE_VILLAGE_WOODPILE
|
||||
if resource_state.get_resource_id() == SimulationIds.RESOURCE_WOOD
|
||||
else &"village"
|
||||
)
|
||||
),
|
||||
resource_state.get_resource_id(),
|
||||
extracted
|
||||
|
||||
@@ -104,6 +104,10 @@ func select_action(npc: SimNPC, village: SimVillage, time_of_day: float = 0.5) -
|
||||
return ActionSelectionResult.new(
|
||||
SimulationIds.ACTION_DEPOSIT_FOOD, -1.0, "Carrying food for storage"
|
||||
)
|
||||
if npc.get_inventory_amount(SimulationIds.RESOURCE_WOOD) > 0.0:
|
||||
return ActionSelectionResult.new(
|
||||
SimulationIds.ACTION_DEPOSIT_WOOD, -1.0, "Carrying wood for storage"
|
||||
)
|
||||
if npc.energy < 25.0:
|
||||
return ActionSelectionResult.new(
|
||||
SimulationIds.ACTION_REST, -1.0, "Energy is below the rest threshold"
|
||||
|
||||
@@ -11,7 +11,8 @@ const ACTION_PATHS := [
|
||||
"res://simulation/definitions/actions/wander.tres",
|
||||
"res://simulation/definitions/actions/deposit_food.tres",
|
||||
"res://simulation/definitions/actions/withdraw_food.tres",
|
||||
"res://simulation/definitions/actions/sleep.tres"
|
||||
"res://simulation/definitions/actions/sleep.tres",
|
||||
"res://simulation/definitions/actions/deposit_wood.tres"
|
||||
]
|
||||
|
||||
const PROFESSION_PATHS := [
|
||||
|
||||
@@ -13,6 +13,7 @@ const ACTION_REST := &"rest"
|
||||
const ACTION_WANDER := &"wander"
|
||||
const ACTION_DEPOSIT_FOOD := &"deposit_food"
|
||||
const ACTION_WITHDRAW_FOOD := &"withdraw_food"
|
||||
const ACTION_DEPOSIT_WOOD := &"deposit_wood"
|
||||
|
||||
const PROFESSION_FARMER := &"farmer"
|
||||
const PROFESSION_WOODCUTTER := &"woodcutter"
|
||||
@@ -28,6 +29,7 @@ const RESOURCE_FOOD := &"food"
|
||||
const RESOURCE_WOOD := &"wood"
|
||||
|
||||
const STORAGE_VILLAGE_PANTRY := &"village_pantry"
|
||||
const STORAGE_VILLAGE_WOODPILE := &"village_woodpile"
|
||||
|
||||
const EVENT_RESOURCE_EXTRACTED := &"resource_extracted"
|
||||
const EVENT_STORAGE_DEPOSITED := &"storage_deposited"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[gd_resource type="Resource" script_class="ActionDefinition" load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://simulation/definitions/ActionDefinition.gd" id="1"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1")
|
||||
action_id = &"deposit_wood"
|
||||
display_name = "Deposit Wood"
|
||||
default_duration = 1.0
|
||||
target_type = &"activity"
|
||||
Reference in New Issue
Block a user