feat: add missing wood opportunities

This commit is contained in:
Rijad Zuzo
2026-07-16 01:50:19 +02:00
parent f82d9683de
commit 79dd503343
26 changed files with 1054 additions and 175 deletions
+59 -8
View File
@@ -37,6 +37,8 @@ func _ready() -> void:
simulation_manager.opportunity_opened.connect(_on_opportunity_opened)
if simulation_manager.has_signal("opportunity_resolved"):
simulation_manager.opportunity_resolved.connect(_on_opportunity_resolved)
if simulation_manager.has_signal("opportunity_invalidated"):
simulation_manager.opportunity_invalidated.connect(_on_opportunity_invalidated)
if "village" in simulation_manager:
_on_village_changed(simulation_manager.village)
@@ -158,6 +160,11 @@ func _on_opportunity_resolved(
_refresh_npc_inspector()
func _on_opportunity_invalidated(_opportunity: RefCounted) -> 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)
@@ -256,10 +263,15 @@ func _build_active_opportunity_display() -> String:
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())
var current_amount := _get_opportunity_current_amount(opportunity)
if opportunity.get_opportunity_type() == SimulationIds.OPPORTUNITY_SUPPLY_MISSING_WOOD:
var action_name := _get_opportunity_action_name(opportunity)
return (
"\n\nVillage need\n"
+ "◆ Supply wood for blocked work\n"
+ "%s could not finish %s\n" % [interested_name, action_name]
+ "%s %.0f / %.0f" % [resource_name, current_amount, opportunity.get_target_amount()]
)
return (
"\n\nVillage need\n"
+ "◆ Restock the empty pantry\n"
@@ -276,10 +288,16 @@ func _build_npc_opportunity_display(npc: SimNPC) -> String:
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())
var current_amount := _get_opportunity_current_amount(opportunity)
if opportunity.get_opportunity_type() == SimulationIds.OPPORTUNITY_SUPPLY_MISSING_WOOD:
return (
"Open village need\n"
+ "◆ Find wood for %s\n" % _get_opportunity_action_name(opportunity)
+ (
"%s %.0f / %.0f\n\n"
% [resource_name, current_amount, opportunity.get_target_amount()]
)
)
return (
"Open village need\n"
+ "◆ Restock the empty pantry\n"
@@ -288,6 +306,16 @@ func _build_npc_opportunity_display(npc: SimNPC) -> String:
% [resource_name, current_amount, opportunity.get_target_amount()]
)
)
if opportunity.get_status() == OpportunityStateRecord.STATUS_INVALIDATED:
var reason := (
"The interested villager died"
if (
opportunity.get_invalidation_reason()
== SimulationIds.OPPORTUNITY_INVALIDATED_INTERESTED_DIED
)
else "The evidence became stale"
)
return "Closed village need\n%s\n\n" % reason
if opportunity.get_status() != OpportunityStateRecord.STATUS_RESOLVED:
return ""
var resolution_event: EconomicEventRecord = simulation_manager.get_opportunity_resolution_event(
@@ -297,6 +325,12 @@ func _build_npc_opportunity_display(npc: SimNPC) -> String:
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)
if opportunity.get_opportunity_type() == SimulationIds.OPPORTUNITY_SUPPLY_MISSING_WOOD:
return (
"Resolved village need\n"
+ "%s supplied the woodpile\n" % actor_name
+ "%s target %.0f\n\n" % [resource_name, opportunity.get_target_amount()]
)
return (
"Resolved village need\n"
+ "%s restocked the pantry\n" % actor_name
@@ -304,6 +338,23 @@ func _build_npc_opportunity_display(npc: SimNPC) -> String:
)
func _get_opportunity_current_amount(opportunity: OpportunityStateRecord) -> float:
var storage: StorageStateRecord
match opportunity.get_target_id():
SimulationIds.STORAGE_VILLAGE_PANTRY:
storage = simulation_manager.get_pantry()
SimulationIds.STORAGE_VILLAGE_WOODPILE:
storage = simulation_manager.get_woodpile()
return storage.get_amount(opportunity.get_resource_id()) if storage != null else 0.0
func _get_opportunity_action_name(opportunity: OpportunityStateRecord) -> String:
var trigger: EconomicEventRecord = simulation_manager.get_opportunity_trigger_event(opportunity)
if trigger == null:
return "work"
return _get_action_name(StringName(trigger.data.get("action_id", &"")))
func _get_npc_name(npc_id: int) -> String:
for npc in simulation_manager.npcs:
if npc.id == npc_id:
+15 -2
View File
@@ -57,6 +57,8 @@ func initialize_world_view() -> void:
simulation_manager.opportunity_resolved.connect(_on_opportunity_resolved)
else:
push_error("WorldViewManager: SimulationManager has no opportunity_resolved signal")
if simulation_manager.has_signal("opportunity_invalidated"):
simulation_manager.opportunity_invalidated.connect(_on_opportunity_invalidated)
if simulation_manager.has_signal("state_restored"):
simulation_manager.state_restored.connect(_on_simulation_state_restored)
else:
@@ -229,6 +231,10 @@ func _on_opportunity_resolved(
_refresh_world_state_presentation(true)
func _on_opportunity_invalidated(_opportunity: OpportunityStateRecord) -> void:
_refresh_world_state_presentation(false)
func _on_simulation_state_restored() -> void:
for visual in active_npc_visuals.values():
visual.queue_free()
@@ -257,7 +263,10 @@ func _refresh_opportunity_concern() -> void:
if visual.has_method("set_opportunity_concern_visible"):
visual.set_opportunity_concern_visible(false)
var opportunity: OpportunityStateRecord = simulation_manager.get_active_opportunity()
if opportunity == null:
if (
opportunity == null
or opportunity.get_opportunity_type() != SimulationIds.OPPORTUNITY_RESTOCK_EMPTY_PANTRY
):
return
var interested_visual = active_npc_visuals.get(opportunity.get_interested_npc_id())
if (
@@ -272,5 +281,9 @@ func _sync_npc_opportunity_concern(npc_id: int, visual: Node3D) -> void:
return
var opportunity: OpportunityStateRecord = simulation_manager.get_active_opportunity()
visual.set_opportunity_concern_visible(
opportunity != null and opportunity.get_interested_npc_id() == npc_id
(
opportunity != null
and opportunity.get_opportunity_type() == SimulationIds.OPPORTUNITY_RESTOCK_EMPTY_PANTRY
and opportunity.get_interested_npc_id() == npc_id
)
)