feat: add location-based food storage loop
This commit is contained in:
+107
-19
@@ -22,6 +22,7 @@ var clock: SimulationClock
|
||||
var tick_count := 0
|
||||
var wander_random_sources := {}
|
||||
var resource_states: Dictionary = {}
|
||||
var storage_states: Dictionary = {}
|
||||
var action_selector := ActionSelectionSystem.new()
|
||||
var action_executor := ActionExecutionSystem.new()
|
||||
var target_resolver := ActionTargetResolver.new()
|
||||
@@ -40,6 +41,7 @@ func _ready() -> void:
|
||||
return
|
||||
clock = SimulationClock.new(tick_interval)
|
||||
village.debug_logs = debug_logs
|
||||
_initialize_storage()
|
||||
village.update_modifiers()
|
||||
village.update_priorities()
|
||||
generate_npcs()
|
||||
@@ -140,9 +142,14 @@ func simulate_tick() -> void:
|
||||
|
||||
if not was_complete and npc.task_complete and not npc.is_dead:
|
||||
var completed_task := npc.current_task
|
||||
var needs_immediate_food_after_gather := npc.should_eat_immediately_after_task()
|
||||
|
||||
if npc.target_id != &"":
|
||||
var completed_definition := SimulationDefinitions.get_action(
|
||||
completed_task
|
||||
)
|
||||
if (
|
||||
npc.target_id != &""
|
||||
and completed_definition != null
|
||||
and completed_definition.target_type == SimulationIds.TARGET_RESOURCE
|
||||
):
|
||||
var resource_state := get_resource_state(npc.target_id)
|
||||
if (
|
||||
resource_state != null
|
||||
@@ -150,10 +157,16 @@ func simulate_tick() -> void:
|
||||
):
|
||||
var extracted := resource_state.extract()
|
||||
if extracted > 0:
|
||||
village.apply_resource_delta(
|
||||
resource_state.get_resource_id(),
|
||||
extracted
|
||||
)
|
||||
if resource_state.get_resource_id() == SimulationIds.RESOURCE_FOOD:
|
||||
npc.add_inventory(
|
||||
SimulationIds.RESOURCE_FOOD,
|
||||
extracted
|
||||
)
|
||||
else:
|
||||
village.apply_resource_delta(
|
||||
resource_state.get_resource_id(),
|
||||
extracted
|
||||
)
|
||||
if debug_logs:
|
||||
print(
|
||||
"[SimulationManager] ",
|
||||
@@ -168,6 +181,12 @@ func simulate_tick() -> void:
|
||||
elif debug_logs:
|
||||
print("[SimulationManager] ", npc.npc_name, " could not complete ", completed_task, ": target reservation was invalid")
|
||||
release_npc_reservation(npc.id)
|
||||
elif completed_task == SimulationIds.ACTION_DEPOSIT_FOOD:
|
||||
deposit_npc_inventory(npc, SimulationIds.RESOURCE_FOOD)
|
||||
elif completed_task == SimulationIds.ACTION_WITHDRAW_FOOD:
|
||||
withdraw_to_npc(npc, SimulationIds.RESOURCE_FOOD, 1.0)
|
||||
elif completed_task == SimulationIds.ACTION_EAT:
|
||||
consume_npc_food(npc)
|
||||
elif completed_task not in [
|
||||
SimulationIds.ACTION_GATHER_FOOD,
|
||||
SimulationIds.ACTION_GATHER_WOOD
|
||||
@@ -183,14 +202,7 @@ func simulate_tick() -> void:
|
||||
npc.last_task = completed_task
|
||||
npc.current_task = SimulationIds.ACTION_IDLE
|
||||
npc.has_travel_target = false
|
||||
|
||||
if needs_immediate_food_after_gather and village.food > 0:
|
||||
npc.set_task(SimulationIds.ACTION_EAT, 1.0)
|
||||
npc_task_changed.emit(npc, completed_task, npc.current_task)
|
||||
npc_target_requested.emit(npc)
|
||||
|
||||
if debug_logs:
|
||||
print("[SimulationManager] ", npc.npc_name, " gathered food while starving and is going to eat immediately.")
|
||||
npc.target_id = &""
|
||||
|
||||
if debug_logs:
|
||||
print(
|
||||
@@ -251,7 +263,14 @@ func notify_npc_arrived(npc_id: int) -> void:
|
||||
return
|
||||
|
||||
if npc.task_state == SimNPC.TASK_STATE_TRAVELING:
|
||||
if npc.target_id != &"":
|
||||
var definition := SimulationDefinitions.get_action(
|
||||
npc.current_task
|
||||
)
|
||||
if (
|
||||
npc.target_id != &""
|
||||
and definition != null
|
||||
and definition.target_type == SimulationIds.TARGET_RESOURCE
|
||||
):
|
||||
var resource_state := get_resource_state(npc.target_id)
|
||||
if (
|
||||
resource_state == null
|
||||
@@ -336,6 +355,57 @@ func synchronize_npc_position(npc_id: int, active_position: Vector3) -> bool:
|
||||
return true
|
||||
return false
|
||||
|
||||
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}
|
||||
)
|
||||
)
|
||||
_sync_village_food()
|
||||
|
||||
func get_pantry() -> StorageStateRecord:
|
||||
return storage_states.get(
|
||||
SimulationIds.STORAGE_VILLAGE_PANTRY
|
||||
) as StorageStateRecord
|
||||
|
||||
func _sync_village_food() -> void:
|
||||
var pantry := get_pantry()
|
||||
if pantry != null:
|
||||
village.food = pantry.get_amount(SimulationIds.RESOURCE_FOOD)
|
||||
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)
|
||||
npc.remove_inventory(item_id, deposited)
|
||||
_sync_village_food()
|
||||
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)
|
||||
_sync_village_food()
|
||||
return withdrawn
|
||||
|
||||
func consume_npc_food(npc: SimNPC) -> bool:
|
||||
if npc.remove_inventory(SimulationIds.RESOURCE_FOOD, 1.0) < 1.0:
|
||||
npc.hunger = minf(npc.hunger + 5.0, 100.0)
|
||||
npc.is_starving = npc.hunger >= 90.0
|
||||
return false
|
||||
npc.hunger = maxf(npc.hunger - 55.0, 0.0)
|
||||
npc.starvation_ticks = 0
|
||||
npc.is_starving = npc.hunger >= 90.0
|
||||
return true
|
||||
|
||||
func register_loaded_resource_nodes() -> void:
|
||||
for node in ResourceNode.get_all():
|
||||
register_resource_node(node)
|
||||
@@ -409,7 +479,11 @@ func harvest_resource_node(node: ResourceNode) -> float:
|
||||
if extracted <= 0.0:
|
||||
return 0.0
|
||||
|
||||
village.apply_resource_delta(resource_state.get_resource_id(), extracted)
|
||||
if resource_state.get_resource_id() == SimulationIds.RESOURCE_FOOD:
|
||||
get_pantry().deposit(SimulationIds.RESOURCE_FOOD, extracted)
|
||||
_sync_village_food()
|
||||
else:
|
||||
village.apply_resource_delta(resource_state.get_resource_id(), extracted)
|
||||
village_changed.emit(village)
|
||||
|
||||
if debug_logs:
|
||||
@@ -425,11 +499,16 @@ func harvest_resource_node(node: ResourceNode) -> float:
|
||||
return extracted
|
||||
|
||||
func eat_food(amount: float) -> void:
|
||||
village.apply_resource_delta(&"food", -amount)
|
||||
get_pantry().withdraw(SimulationIds.RESOURCE_FOOD, amount)
|
||||
_sync_village_food()
|
||||
village_changed.emit(village)
|
||||
|
||||
func add_food(amount: float) -> void:
|
||||
village.apply_resource_delta(&"food", amount)
|
||||
if amount >= 0.0:
|
||||
get_pantry().deposit(SimulationIds.RESOURCE_FOOD, amount)
|
||||
else:
|
||||
get_pantry().withdraw(SimulationIds.RESOURCE_FOOD, -amount)
|
||||
_sync_village_food()
|
||||
village_changed.emit(village)
|
||||
|
||||
func add_wood(amount: float) -> void:
|
||||
@@ -523,6 +602,11 @@ func create_state_record() -> SimulationStateRecord:
|
||||
for resource_id in sorted_resource_ids:
|
||||
var resource_state: ResourceStateRecord = resource_states[resource_id]
|
||||
record.resources.append(resource_state)
|
||||
var sorted_storage_ids: Array = storage_states.keys()
|
||||
sorted_storage_ids.sort()
|
||||
for storage_id in sorted_storage_ids:
|
||||
var storage_state: StorageStateRecord = storage_states[storage_id]
|
||||
record.storages.append(storage_state)
|
||||
return record
|
||||
|
||||
func serialize_state() -> String:
|
||||
@@ -546,6 +630,10 @@ func restore_state(record: SimulationStateRecord) -> bool:
|
||||
clock.accumulator = float(record.simulation["clock_accumulator"])
|
||||
clock.elapsed_ticks = int(record.simulation["clock_elapsed_ticks"])
|
||||
village = record.village.restore(debug_logs)
|
||||
storage_states.clear()
|
||||
for storage_record in record.storages:
|
||||
storage_states[storage_record.get_storage_id()] = storage_record
|
||||
_sync_village_food()
|
||||
|
||||
npcs.clear()
|
||||
for npc_record in record.npcs:
|
||||
|
||||
Reference in New Issue
Block a user