feat: add knowledge-gated pantry opportunities
This commit is contained in:
+102
-4
@@ -33,6 +33,10 @@ func _ready() -> void:
|
||||
simulation_manager.event_knowledge_changed.connect(_on_event_knowledge_changed)
|
||||
if simulation_manager.has_signal("event_knowledge_forgotten"):
|
||||
simulation_manager.event_knowledge_forgotten.connect(_on_event_knowledge_forgotten)
|
||||
if simulation_manager.has_signal("opportunity_opened"):
|
||||
simulation_manager.opportunity_opened.connect(_on_opportunity_opened)
|
||||
if simulation_manager.has_signal("opportunity_resolved"):
|
||||
simulation_manager.opportunity_resolved.connect(_on_opportunity_resolved)
|
||||
|
||||
if "village" in simulation_manager:
|
||||
_on_village_changed(simulation_manager.village)
|
||||
@@ -79,6 +83,7 @@ func _on_village_changed(village: SimVillage) -> void:
|
||||
var wood_rate := ""
|
||||
if rates["wood_per_day"] > 0.01:
|
||||
wood_rate = " (−%.0f/d)" % rates["wood_per_day"]
|
||||
var opportunity_text := _build_active_opportunity_display()
|
||||
village_stats_label.text = (
|
||||
"""
|
||||
Village [%s]
|
||||
@@ -92,7 +97,7 @@ func _on_village_changed(village: SimVillage) -> void:
|
||||
Food Mod: %.2f
|
||||
Safety Mod: %.2f
|
||||
Knowledge Mod: %.2f
|
||||
%s
|
||||
%s%s
|
||||
"""
|
||||
% [
|
||||
speed_text,
|
||||
@@ -106,7 +111,8 @@ func _on_village_changed(village: SimVillage) -> void:
|
||||
village.food_modifier,
|
||||
village.safety_modifier,
|
||||
village.knowledge_modifier,
|
||||
event_text
|
||||
opportunity_text,
|
||||
event_text,
|
||||
]
|
||||
)
|
||||
|
||||
@@ -117,6 +123,7 @@ func _on_npc_decision_recorded(_npc: SimNPC, _decision: ActionSelectionResult) -
|
||||
|
||||
func _on_state_restored() -> void:
|
||||
selected_npc_index = 0
|
||||
_refresh_village_display()
|
||||
_refresh_npc_inspector()
|
||||
|
||||
|
||||
@@ -139,6 +146,23 @@ func _on_event_knowledge_forgotten(_knower_id: int, _event: EconomicEventRecord)
|
||||
_refresh_npc_inspector()
|
||||
|
||||
|
||||
func _on_opportunity_opened(_opportunity: RefCounted) -> void:
|
||||
_refresh_village_display()
|
||||
_refresh_npc_inspector()
|
||||
|
||||
|
||||
func _on_opportunity_resolved(
|
||||
_opportunity: RefCounted, _resolution_event: EconomicEventRecord
|
||||
) -> void:
|
||||
_refresh_village_display()
|
||||
_refresh_npc_inspector()
|
||||
|
||||
|
||||
func _refresh_village_display() -> void:
|
||||
if simulation_manager != null and "village" in simulation_manager:
|
||||
_on_village_changed(simulation_manager.village)
|
||||
|
||||
|
||||
func _refresh_npc_inspector() -> void:
|
||||
if not debug_overlay_visible:
|
||||
return
|
||||
@@ -189,6 +213,7 @@ func _refresh_npc_inspector() -> void:
|
||||
var event_text := _build_event_history(npc)
|
||||
var relationship_text := _build_relationship_display(npc)
|
||||
var memory_history_text := _build_memory_history_display(npc)
|
||||
var opportunity_text := _build_npc_opportunity_display(npc)
|
||||
npc_inspector_label.text = (
|
||||
(
|
||||
"%s · %s\n"
|
||||
@@ -198,6 +223,7 @@ func _refresh_npc_inspector() -> void:
|
||||
+ "Carrying food: %.0f wood: %.0f\n"
|
||||
+ "%s\n"
|
||||
+ "%s\n"
|
||||
+ "%s"
|
||||
+ "Why\n%s%s\n\n"
|
||||
+ "Own history\n%s\n\n"
|
||||
+ "[Tab] Next villager [F10] Cinematic/debug [F12] Demo reset"
|
||||
@@ -214,6 +240,7 @@ func _refresh_npc_inspector() -> void:
|
||||
npc.get_inventory_amount(SimulationIds.RESOURCE_WOOD),
|
||||
relationship_text,
|
||||
memory_history_text,
|
||||
opportunity_text,
|
||||
reason_text,
|
||||
score_text,
|
||||
event_text
|
||||
@@ -221,6 +248,69 @@ func _refresh_npc_inspector() -> void:
|
||||
)
|
||||
|
||||
|
||||
func _build_active_opportunity_display() -> String:
|
||||
if not simulation_manager.has_method("get_active_opportunity"):
|
||||
return ""
|
||||
var opportunity = simulation_manager.get_active_opportunity()
|
||||
if opportunity == null:
|
||||
return ""
|
||||
var interested_name := _get_npc_name(opportunity.get_interested_npc_id())
|
||||
var resource_name := String(opportunity.get_resource_id()).capitalize()
|
||||
var current_amount := 0.0
|
||||
var pantry: StorageStateRecord = simulation_manager.get_pantry()
|
||||
if pantry != null:
|
||||
current_amount = pantry.get_amount(opportunity.get_resource_id())
|
||||
return (
|
||||
"\n\nVillage need\n"
|
||||
+ "◆ Restock the empty pantry\n"
|
||||
+ "%s is worried about the shortage\n" % interested_name
|
||||
+ "%s %.0f / %.0f" % [resource_name, current_amount, opportunity.get_target_amount()]
|
||||
)
|
||||
|
||||
|
||||
func _build_npc_opportunity_display(npc: SimNPC) -> String:
|
||||
if not simulation_manager.has_method("get_latest_opportunity_for_npc"):
|
||||
return ""
|
||||
var opportunity = simulation_manager.get_latest_opportunity_for_npc(npc.id)
|
||||
if opportunity == null:
|
||||
return ""
|
||||
var resource_name := String(opportunity.get_resource_id()).capitalize()
|
||||
if opportunity.get_status() == OpportunityStateRecord.STATUS_OPEN:
|
||||
var pantry: StorageStateRecord = simulation_manager.get_pantry()
|
||||
var current_amount := 0.0
|
||||
if pantry != null:
|
||||
current_amount = pantry.get_amount(opportunity.get_resource_id())
|
||||
return (
|
||||
"Open village need\n"
|
||||
+ "◆ Restock the empty pantry\n"
|
||||
+ (
|
||||
"%s %.0f / %.0f\n\n"
|
||||
% [resource_name, current_amount, opportunity.get_target_amount()]
|
||||
)
|
||||
)
|
||||
if opportunity.get_status() != OpportunityStateRecord.STATUS_RESOLVED:
|
||||
return ""
|
||||
var resolution_event: EconomicEventRecord = simulation_manager.get_opportunity_resolution_event(
|
||||
opportunity
|
||||
)
|
||||
var actor_name := "Someone"
|
||||
if resolution_event != null:
|
||||
var actor_id := int(resolution_event.data["actor_id"])
|
||||
actor_name = "Player" if actor_id < 0 else _get_npc_name(actor_id)
|
||||
return (
|
||||
"Resolved village need\n"
|
||||
+ "◆ %s restocked the pantry\n" % actor_name
|
||||
+ "%s target %.0f\n\n" % [resource_name, opportunity.get_target_amount()]
|
||||
)
|
||||
|
||||
|
||||
func _get_npc_name(npc_id: int) -> String:
|
||||
for npc in simulation_manager.npcs:
|
||||
if npc.id == npc_id:
|
||||
return npc.npc_name
|
||||
return "Someone"
|
||||
|
||||
|
||||
func _get_action_name(action_id: StringName) -> String:
|
||||
if action_id == SimulationIds.ACTION_IDLE:
|
||||
return "Idle"
|
||||
@@ -327,12 +417,20 @@ func _build_memory_history_display(npc: SimNPC) -> String:
|
||||
|
||||
|
||||
func _build_compact_memory_summary(event: EconomicEventRecord, name_map: Dictionary) -> String:
|
||||
var event_type := StringName(event.data["event_type"])
|
||||
var item_id := StringName(event.data["item_id"])
|
||||
if (
|
||||
StringName(event.data["event_type"]) == SimulationIds.EVENT_STORAGE_DEPOSITED
|
||||
and StringName(event.data["item_id"]) == SimulationIds.RESOURCE_FOOD
|
||||
event_type == SimulationIds.EVENT_STORAGE_DEPOSITED
|
||||
and item_id == SimulationIds.RESOURCE_FOOD
|
||||
):
|
||||
var actor_name: String = name_map.get(int(event.data["actor_id"]), "Someone")
|
||||
return "%s stocked %.0f food" % [actor_name, float(event.data["amount"])]
|
||||
if (
|
||||
event_type == SimulationIds.EVENT_STORAGE_WITHDRAWN
|
||||
and item_id == SimulationIds.RESOURCE_FOOD
|
||||
):
|
||||
var actor_name: String = name_map.get(int(event.data["actor_id"]), "Someone")
|
||||
return "%s took %.0f food from the pantry" % [actor_name, float(event.data["amount"])]
|
||||
return event.description(name_map)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user