feat: structured narrative event feed with per-NPC inspector timeline

Add narrative event types (task_started, npc_slept, npc_died, resource_depleted) alongside economic transfers. EconomicEventRecord gains create_narrative factory and human-readable description method. SimulationManager records task-start and sleep/death events, exposes get_npc_events() for per-NPC history queries. Inspector now shows a Recent timeline of the last 5 events for the selected NPC, plus displays carried wood count. Relax EconomicEventRecord validation to accept non-economic events. Update roadmap with completed milestones.
This commit is contained in:
2026-07-08 19:02:11 +02:00
parent c61d286005
commit 8a1913c5ae
6 changed files with 151 additions and 22 deletions
+21 -2
View File
@@ -118,13 +118,15 @@ func _refresh_npc_inspector() -> void:
)
if not score_rows.is_empty():
score_text = "\n\nUtility\n" + "\n".join(score_rows)
var event_text := _build_event_history(npc)
npc_inspector_label.text = (
"%s · %s\n"
+ "Task: %s (%s)\n"
+ "Destination: %s\n"
+ "Hunger: %.0f Energy: %.0f\n"
+ "Carrying food: %.0f\n\n"
+ "Carrying food: %.0f wood: %.0f\n\n"
+ "Why\n%s%s\n\n"
+ "Recent\n%s\n\n"
+ "[Tab] Next villager [F10] Cinematic/debug [F12] Demo reset"
) % [
npc.npc_name,
@@ -135,8 +137,10 @@ func _refresh_npc_inspector() -> void:
npc.hunger,
npc.energy,
npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD),
npc.get_inventory_amount(SimulationIds.RESOURCE_WOOD),
reason_text,
score_text
score_text,
event_text
]
@@ -156,3 +160,18 @@ func set_debug_overlay_visible(is_visible: bool) -> void:
visible = is_visible
if is_visible:
_refresh_npc_inspector()
func _build_event_history(npc: SimNPC) -> String:
if not simulation_manager.has_method("get_npc_events"):
return ""
var events: Array = simulation_manager.get_npc_events(npc.id, 5)
if events.is_empty():
return "No recorded events yet"
var name_map := {}
for other_npc in simulation_manager.npcs:
name_map[other_npc.id] = other_npc.npc_name
var lines: Array[String] = []
for event in events:
lines.append(event.description(name_map))
return "\n".join(lines)