feat: add physical animal care delivery

This commit is contained in:
Rijad Zuzo
2026-07-31 00:19:41 +02:00
parent 7d410d8193
commit ead75fca68
25 changed files with 1469 additions and 191 deletions
+55 -73
View File
@@ -3,6 +3,7 @@ extends Node
const SimulationEventLogScript := preload("res://simulation/events/SimulationEventLog.gd")
const VillageEconomyScript := preload("res://simulation/economy/VillageEconomy.gd")
const AnimalCareSystemScript := preload("res://simulation/animals/animal_care_system.gd")
const NpcTickDebugLog := preload("res://simulation/debug/npc_tick_debug_log.gd")
const RelationshipSystemScript := preload("res://simulation/relationships/RelationshipSystem.gd")
const EventKnowledgeSystemScript := preload("res://simulation/knowledge/EventKnowledgeSystem.gd")
@@ -187,6 +188,13 @@ func _simulate_npc_tick(npc: SimNPC) -> bool:
var was_complete := npc.task_complete
var was_dead := npc.is_dead
if animal_care.requires_working_feed_recovery(npc):
npc.task_state = SimNPC.TASK_STATE_TRAVELING
npc.task_complete = false
if not _continue_animal_feed_delivery(npc):
_redirect_npc_to_wander(npc)
return false
action_executor.advance_npc(npc, village)
_population_view.refresh_npc(npc)
_select_action_if_idle(npc, previous_state)
@@ -205,7 +213,8 @@ func _simulate_npc_tick(npc: SimNPC) -> bool:
_complete_current_action(npc)
_population_view.refresh_npc(npc)
_debug_npc_tick(npc, previous_state)
if debug_logs:
NpcTickDebugLog.print_tick(npc, previous_state)
return completed
@@ -333,45 +342,6 @@ func _complete_resource_gather(npc: SimNPC, completed_task: StringName) -> void:
release_npc_reservation(npc.id)
func _debug_npc_tick(npc: SimNPC, previous_state: StringName) -> void:
if not debug_logs:
return
print(
npc.npc_name,
" | ",
npc.profession,
" | task: ",
npc.current_task,
" | state: ",
npc.task_state,
" | progress: ",
npc.task_progress,
"/",
npc.task_duration,
" | complete: ",
npc.task_complete,
" | hunger: ",
round(npc.hunger),
" | energy: ",
round(npc.energy),
" | starving: ",
npc.is_starving,
" | starvation_ticks: ",
npc.starvation_ticks,
" | dead: ",
npc.is_dead
)
if previous_state != npc.task_state:
print(
"[SimulationManager] State changed: ",
npc.npc_name,
" ",
previous_state,
" -> ",
npc.task_state
)
func release_npc_reservation(npc_id: int) -> void:
for npc in npcs:
if npc.id == npc_id:
@@ -406,13 +376,7 @@ func notify_npc_arrived(npc_id: int) -> void:
or resource_state.get_reserved_by() != npc.id
):
if debug_logs:
print(
"[SimulationManager] ",
npc.npc_name,
" arrived but target ",
npc.target_id,
" is unavailable, replanning"
)
NpcTickDebugLog.print_unavailable_resource(npc)
notify_npc_navigation_failed(npc.id)
return
if (
@@ -422,18 +386,19 @@ func notify_npc_arrived(npc_id: int) -> void:
):
if not animal_care.can_complete_feed(npc.target_id, npc.id):
if debug_logs:
print(
"[SimulationManager] ",
npc.npc_name,
" arrived but animal ",
npc.target_id,
" no longer needs feeding, replanning"
)
NpcTickDebugLog.print_unavailable_animal(npc)
notify_npc_navigation_failed(npc.id)
return
if animal_care.requires_feed_pickup(npc):
if _continue_animal_feed_delivery(npc):
return
_redirect_npc_to_wander(npc)
return
npc.has_travel_target = false
npc.start_working()
npc.start_working(
npc.current_task == SimulationIds.ACTION_FEED_ANIMAL and npc.task_progress > 0.0
)
var working_speakers: Array[SimNPC] = []
if npc.target_id != &"":
@@ -455,15 +420,42 @@ func notify_npc_arrived(npc_id: int) -> void:
break
if debug_logs:
print(
"[SimulationManager] ",
npc.npc_name,
" arrived and started working on: ",
npc.current_task
)
NpcTickDebugLog.print_started_work(npc)
return
func _continue_animal_feed_delivery(npc: SimNPC) -> bool:
var animal_target := target_resolver.resolve_claimed_animal(npc, self, active_world_adapter)
var pantry_target := target_resolver.resolve_storage_target(
SimulationIds.STORAGE_VILLAGE_PANTRY, active_world_adapter
)
if animal_target.is_empty() or pantry_target.is_empty():
return false
if not npc.travel_target_position.is_equal_approx(pantry_target["position"]):
npc.travel_target_position = pantry_target["position"]
npc.has_travel_target = true
npc_travel_requested.emit(npc, npc.travel_target_position)
return true
var pickup_target := npc.travel_target_position
npc.travel_target_position = animal_target["position"]
npc.has_travel_target = true
if not animal_care.collect_feed_supply(npc):
npc.travel_target_position = pickup_target
return false
village_changed.emit(village)
npc_travel_requested.emit(npc, npc.travel_target_position)
return true
func _redirect_npc_to_wander(npc: SimNPC) -> void:
var failed_task := npc.current_task
release_npc_reservation(npc.id)
npc.last_task = failed_task
npc.set_task(SimulationIds.ACTION_WANDER, 2.0)
npc_task_changed.emit(npc, failed_task, npc.current_task)
npc_target_requested.emit(npc)
func notify_npc_navigation_failed(npc_id: int) -> void:
for npc in npcs:
if npc.id != npc_id:
@@ -472,20 +464,10 @@ func notify_npc_navigation_failed(npc_id: int) -> void:
return
var failed_task := npc.current_task
release_npc_reservation(npc.id)
npc.last_task = failed_task
npc.set_task(SimulationIds.ACTION_WANDER, 2.0)
npc_task_changed.emit(npc, failed_task, npc.current_task)
npc_target_requested.emit(npc)
_redirect_npc_to_wander(npc)
if debug_logs:
print(
"[SimulationManager] ",
npc.npc_name,
" could not navigate for ",
failed_task,
" and is trying a wander target"
)
NpcTickDebugLog.print_navigation_failure(npc, failed_task)
return