feat: add nearby villager field notes
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
class_name VillagerInspectionResult
|
||||
extends RefCounted
|
||||
|
||||
const AWAITING_REASON := "Awaiting the next decision"
|
||||
|
||||
var npc_id: int
|
||||
var npc_name: String
|
||||
var action_id: StringName
|
||||
var action_name: String
|
||||
var task_state: StringName
|
||||
var target_id: StringName
|
||||
var target_name: String
|
||||
var carried_amounts: Dictionary
|
||||
var decision_reason: String
|
||||
var _has_decision_reason: bool
|
||||
|
||||
|
||||
func _init(
|
||||
inspection_npc_id: int,
|
||||
inspection_npc_name: String,
|
||||
inspection_action_id: StringName,
|
||||
inspection_action_name: String,
|
||||
inspection_task_state: StringName,
|
||||
inspection_target_id: StringName,
|
||||
inspection_target_name: String,
|
||||
inspection_carried_amounts: Dictionary,
|
||||
inspection_decision_reason := ""
|
||||
) -> void:
|
||||
npc_id = inspection_npc_id
|
||||
npc_name = inspection_npc_name
|
||||
action_id = inspection_action_id
|
||||
action_name = inspection_action_name
|
||||
task_state = inspection_task_state
|
||||
target_id = inspection_target_id
|
||||
target_name = inspection_target_name
|
||||
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)
|
||||
|
||||
|
||||
func has_decision_reason() -> bool:
|
||||
return _has_decision_reason
|
||||
|
||||
|
||||
func activity_text() -> String:
|
||||
return "%s · %s" % [action_name, _display_id(task_state)]
|
||||
|
||||
|
||||
func carrying_text() -> String:
|
||||
var item_ids: Array = carried_amounts.keys()
|
||||
item_ids.sort()
|
||||
var entries: Array[String] = []
|
||||
for item_id in item_ids:
|
||||
var amount := float(carried_amounts[item_id])
|
||||
if amount <= 0.0:
|
||||
continue
|
||||
var amount_text := (
|
||||
"%.0f" % amount if is_equal_approx(amount, roundf(amount)) else "%.1f" % amount
|
||||
)
|
||||
entries.append("%s %s" % [amount_text, _display_id(StringName(item_id)).to_lower()])
|
||||
return "nothing" if entries.is_empty() else " · ".join(entries)
|
||||
|
||||
|
||||
func cache_key() -> String:
|
||||
var carried_keys: Array = carried_amounts.keys()
|
||||
carried_keys.sort()
|
||||
var carried_parts: Array[String] = []
|
||||
for item_id in carried_keys:
|
||||
carried_parts.append("%s=%.3f" % [String(item_id), float(carried_amounts[item_id])])
|
||||
return (
|
||||
"|"
|
||||
. join(
|
||||
[
|
||||
str(npc_id),
|
||||
npc_name,
|
||||
String(action_id),
|
||||
action_name,
|
||||
String(task_state),
|
||||
String(target_id),
|
||||
target_name,
|
||||
",".join(carried_parts),
|
||||
decision_reason,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
static func _display_id(value: StringName) -> String:
|
||||
return String(value).replace("_", " ").capitalize()
|
||||
@@ -0,0 +1 @@
|
||||
uid://dec7j7j08cipj
|
||||
@@ -8,6 +8,7 @@ signal interaction_feedback(heading: String, message: String, succeeded: bool)
|
||||
@export var camera_rig: Node3D
|
||||
|
||||
@export var simulation_manager: Node
|
||||
@export var world_view_manager: Node
|
||||
|
||||
@export var pantry_storage: StorageNode
|
||||
@export var guard_site: ActivitySite
|
||||
@@ -15,6 +16,7 @@ signal interaction_feedback(heading: String, message: String, succeeded: bool)
|
||||
|
||||
@export var stomach_capacity_for_food := 5
|
||||
@export var interaction_range := 3.0
|
||||
@export var villager_inspection_range := 3.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -115,6 +117,44 @@ func get_interaction_context() -> PlayerInteractionResult:
|
||||
return null
|
||||
|
||||
|
||||
func get_nearby_villager_inspection() -> VillagerInspectionResult:
|
||||
if (
|
||||
simulation_manager == null
|
||||
or world_view_manager == null
|
||||
or not world_view_manager.has_method("find_nearest_active_npc_id")
|
||||
):
|
||||
return null
|
||||
var npc_id: int = world_view_manager.find_nearest_active_npc_id(
|
||||
global_position, villager_inspection_range
|
||||
)
|
||||
var npc := _find_npc(npc_id)
|
||||
if npc == null:
|
||||
return null
|
||||
var action_name := _get_action_display_name(npc.current_task)
|
||||
var target_name := _get_target_display_name(npc.target_id)
|
||||
var carried_amounts := {}
|
||||
for raw_item_id in npc.inventory:
|
||||
var amount := npc.get_inventory_amount(StringName(raw_item_id))
|
||||
if amount > 0.0:
|
||||
carried_amounts[String(raw_item_id)] = amount
|
||||
var reason := ""
|
||||
if simulation_manager.has_method("get_latest_decision"):
|
||||
var decision: ActionSelectionResult = simulation_manager.get_latest_decision(npc.id)
|
||||
if decision != null and decision.action_id == npc.current_task:
|
||||
reason = decision.reason
|
||||
return VillagerInspectionResult.new(
|
||||
npc.id,
|
||||
npc.npc_name,
|
||||
npc.current_task,
|
||||
action_name,
|
||||
npc.task_state,
|
||||
npc.target_id,
|
||||
target_name,
|
||||
carried_amounts,
|
||||
reason
|
||||
)
|
||||
|
||||
|
||||
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")
|
||||
@@ -129,6 +169,44 @@ func _find_resource_node() -> ResourceNode:
|
||||
return simulation_manager.find_resource_node_for_player(global_position, interaction_range)
|
||||
|
||||
|
||||
func _find_npc(npc_id: int) -> SimNPC:
|
||||
if npc_id < 0:
|
||||
return null
|
||||
for npc in simulation_manager.npcs:
|
||||
if npc.id == npc_id and not npc.is_dead:
|
||||
return npc
|
||||
return null
|
||||
|
||||
|
||||
func _get_action_display_name(action_id: StringName) -> String:
|
||||
if action_id == SimulationIds.ACTION_IDLE:
|
||||
return "Idle"
|
||||
if action_id == SimulationIds.ACTION_DEAD:
|
||||
return "Dead"
|
||||
var definition := SimulationDefinitions.get_action(action_id)
|
||||
return definition.display_name if definition != null else _display_id(action_id)
|
||||
|
||||
|
||||
func _get_target_display_name(target_id: StringName) -> String:
|
||||
if target_id.is_empty():
|
||||
return "None recorded"
|
||||
if "animal_care" in simulation_manager and simulation_manager.animal_care != null:
|
||||
var animal_state: AnimalStateRecord = simulation_manager.animal_care.get_state(target_id)
|
||||
if animal_state != null:
|
||||
return animal_state.get_display_name()
|
||||
var storage := StorageNode.get_by_id(target_id) as StorageNode
|
||||
if storage != null:
|
||||
return storage.display_name
|
||||
var activity := ActivitySite.get_by_id(target_id) as ActivitySite
|
||||
if activity != null:
|
||||
return activity.display_name
|
||||
return _display_id(target_id)
|
||||
|
||||
|
||||
static func _display_id(value: StringName) -> String:
|
||||
return String(value).replace("_", " ").capitalize()
|
||||
|
||||
|
||||
func _build_animal_context(node: AnimalNode) -> PlayerInteractionResult:
|
||||
var cost := _get_animal_feed_cost()
|
||||
var pantry_food := _get_pantry_food()
|
||||
|
||||
Reference in New Issue
Block a user