feat: surface open opportunity need on villager field note
This commit is contained in:
@@ -13,6 +13,7 @@ var target_name: String
|
||||
var carried_amounts: Dictionary
|
||||
var decision_reason: String
|
||||
var _has_decision_reason: bool
|
||||
var opportunity_note: VillagerOpportunityNote
|
||||
|
||||
|
||||
func _init(
|
||||
@@ -24,7 +25,8 @@ func _init(
|
||||
inspection_target_id: StringName,
|
||||
inspection_target_name: String,
|
||||
inspection_carried_amounts: Dictionary,
|
||||
inspection_decision_reason := ""
|
||||
inspection_decision_reason := "",
|
||||
inspection_opportunity_note: VillagerOpportunityNote = null
|
||||
) -> void:
|
||||
npc_id = inspection_npc_id
|
||||
npc_name = inspection_npc_name
|
||||
@@ -36,6 +38,7 @@ func _init(
|
||||
carried_amounts = inspection_carried_amounts.duplicate(true)
|
||||
_has_decision_reason = not inspection_decision_reason.strip_edges().is_empty()
|
||||
decision_reason = (inspection_decision_reason if _has_decision_reason else AWAITING_REASON)
|
||||
opportunity_note = inspection_opportunity_note
|
||||
|
||||
|
||||
func has_decision_reason() -> bool:
|
||||
@@ -67,6 +70,7 @@ func cache_key() -> String:
|
||||
var carried_parts: Array[String] = []
|
||||
for item_id in carried_keys:
|
||||
carried_parts.append("%s=%.3f" % [String(item_id), float(carried_amounts[item_id])])
|
||||
var note_part := opportunity_note.cache_key() if opportunity_note != null else "-"
|
||||
return (
|
||||
"|"
|
||||
. join(
|
||||
@@ -80,6 +84,7 @@ func cache_key() -> String:
|
||||
target_name,
|
||||
",".join(carried_parts),
|
||||
decision_reason,
|
||||
note_part,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
class_name VillagerOpportunityNote
|
||||
extends RefCounted
|
||||
|
||||
const HELP_PLAYER_ROUTE := &"player_route"
|
||||
const HELP_HELPER := &"helper"
|
||||
const HELP_UNAVAILABLE := &"unavailable"
|
||||
|
||||
var has_need := false
|
||||
var need_text := ""
|
||||
var help_kind: StringName = &""
|
||||
var help_text := ""
|
||||
|
||||
|
||||
func _init(
|
||||
note_has_need := false,
|
||||
note_need_text := "",
|
||||
note_help_kind: StringName = &"",
|
||||
note_help_text := ""
|
||||
) -> void:
|
||||
has_need = note_has_need
|
||||
need_text = note_need_text
|
||||
help_kind = note_help_kind
|
||||
help_text = note_help_text
|
||||
|
||||
|
||||
func cache_key() -> String:
|
||||
return "%s|%s|%s|%s" % [has_need, need_text, String(help_kind), help_text]
|
||||
|
||||
|
||||
static func derive(
|
||||
opportunity: OpportunityStateRecord,
|
||||
player_response: OpportunityPlayerResponseResult,
|
||||
helper: OpportunityHelperResult,
|
||||
helper_npc_name: String,
|
||||
storage: StorageStateRecord,
|
||||
target_display_name: String,
|
||||
resource_display_name: String
|
||||
) -> VillagerOpportunityNote:
|
||||
if opportunity == null:
|
||||
return VillagerOpportunityNote.new()
|
||||
var need_text := "The %s needs %s" % [target_display_name, resource_display_name]
|
||||
if player_response != null:
|
||||
return (
|
||||
VillagerOpportunityNote
|
||||
. new(
|
||||
true,
|
||||
need_text,
|
||||
HELP_PLAYER_ROUTE,
|
||||
"You can help · forage %s to the %s" % [resource_display_name, target_display_name],
|
||||
)
|
||||
)
|
||||
if helper != null:
|
||||
return VillagerOpportunityNote.new(
|
||||
true,
|
||||
need_text,
|
||||
HELP_HELPER,
|
||||
"%s is bringing %s" % [helper_npc_name, resource_display_name]
|
||||
)
|
||||
if storage == null:
|
||||
return VillagerOpportunityNote.new(
|
||||
true, need_text, HELP_UNAVAILABLE, "No storage is within reach right now."
|
||||
)
|
||||
var remaining := maxf(
|
||||
opportunity.get_target_amount() - storage.get_amount(opportunity.get_resource_id()), 0.0
|
||||
)
|
||||
if remaining <= 0.0:
|
||||
return VillagerOpportunityNote.new(
|
||||
true,
|
||||
need_text,
|
||||
HELP_UNAVAILABLE,
|
||||
"The %s already has enough %s." % [target_display_name, resource_display_name]
|
||||
)
|
||||
if storage.get_available_capacity() < remaining:
|
||||
return VillagerOpportunityNote.new(
|
||||
true, need_text, HELP_UNAVAILABLE, "The %s has no room right now." % target_display_name
|
||||
)
|
||||
return VillagerOpportunityNote.new(
|
||||
true, need_text, HELP_UNAVAILABLE, "No stocked source is in reach right now."
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
uid://ds7o7atkwyfon
|
||||
+54
-1
@@ -142,6 +142,7 @@ func get_nearby_villager_inspection() -> VillagerInspectionResult:
|
||||
var decision: ActionSelectionResult = simulation_manager.get_latest_decision(npc.id)
|
||||
if decision != null and decision.action_id == npc.current_task:
|
||||
reason = decision.reason
|
||||
var opportunity_note := _build_opportunity_note(npc)
|
||||
return VillagerInspectionResult.new(
|
||||
npc.id,
|
||||
npc.npc_name,
|
||||
@@ -151,10 +152,62 @@ func get_nearby_villager_inspection() -> VillagerInspectionResult:
|
||||
npc.target_id,
|
||||
target_name,
|
||||
carried_amounts,
|
||||
reason
|
||||
reason,
|
||||
opportunity_note
|
||||
)
|
||||
|
||||
|
||||
func _build_opportunity_note(npc: SimNPC) -> VillagerOpportunityNote:
|
||||
if (
|
||||
simulation_manager == null
|
||||
or not simulation_manager.has_method("get_active_opportunity")
|
||||
or not simulation_manager.has_method("get_active_opportunity_player_response")
|
||||
or not simulation_manager.has_method("get_active_opportunity_helper")
|
||||
):
|
||||
return null
|
||||
var opportunity: OpportunityStateRecord = simulation_manager.get_active_opportunity()
|
||||
if (
|
||||
opportunity == null
|
||||
or opportunity.get_interested_npc_id() != npc.id
|
||||
or (
|
||||
opportunity.get_target_id()
|
||||
not in [SimulationIds.STORAGE_VILLAGE_PANTRY, SimulationIds.STORAGE_VILLAGE_WOODPILE]
|
||||
)
|
||||
):
|
||||
return null
|
||||
var player_response: OpportunityPlayerResponseResult = (
|
||||
simulation_manager.get_active_opportunity_player_response()
|
||||
)
|
||||
var helper: OpportunityHelperResult = simulation_manager.get_active_opportunity_helper()
|
||||
var helper_name := ""
|
||||
if helper != null:
|
||||
var helper_npc := _find_npc(helper.helper_npc_id)
|
||||
if helper_npc != null:
|
||||
helper_name = helper_npc.npc_name
|
||||
return VillagerOpportunityNote.derive(
|
||||
opportunity,
|
||||
player_response,
|
||||
helper,
|
||||
helper_name,
|
||||
_get_opportunity_storage(opportunity),
|
||||
_get_target_display_name(opportunity.get_target_id()),
|
||||
_display_id(opportunity.get_resource_id()).to_lower()
|
||||
)
|
||||
|
||||
|
||||
func _get_opportunity_storage(opportunity: OpportunityStateRecord) -> StorageStateRecord:
|
||||
if simulation_manager == null:
|
||||
return null
|
||||
if not simulation_manager.has_method("get_pantry"):
|
||||
return null
|
||||
if opportunity.get_target_id() == SimulationIds.STORAGE_VILLAGE_PANTRY:
|
||||
return simulation_manager.get_pantry() as StorageStateRecord
|
||||
if opportunity.get_target_id() == SimulationIds.STORAGE_VILLAGE_WOODPILE:
|
||||
if simulation_manager.has_method("get_woodpile"):
|
||||
return simulation_manager.get_woodpile() as StorageStateRecord
|
||||
return null
|
||||
|
||||
|
||||
func _find_feed_animal() -> AnimalNode:
|
||||
if not ("animal_care" in simulation_manager) or simulation_manager.animal_care == null:
|
||||
push_error("Player: SimulationManager has no animal-care service")
|
||||
|
||||
Reference in New Issue
Block a user