merge: integrate remote player quest slices
This commit is contained in:
+151
-6
@@ -249,6 +249,7 @@ func get_nearby_villager_inspection() -> VillagerInspectionResult:
|
||||
if decision != null and decision.action_id == npc.current_task:
|
||||
reason = decision.reason
|
||||
var need := _get_open_need_for_npc(npc)
|
||||
need["opportunity_note"] = _build_opportunity_note(npc)
|
||||
return VillagerInspectionResult.new(
|
||||
npc.id,
|
||||
npc.npc_name,
|
||||
@@ -263,6 +264,57 @@ func get_nearby_villager_inspection() -> VillagerInspectionResult:
|
||||
)
|
||||
|
||||
|
||||
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 opportunity.get_target_id() == SimulationIds.STORAGE_VILLAGE_PANTRY:
|
||||
return simulation_manager.get_pantry() as StorageStateRecord
|
||||
if (
|
||||
opportunity.get_target_id() == SimulationIds.STORAGE_VILLAGE_WOODPILE
|
||||
and simulation_manager.has_method("get_woodpile")
|
||||
):
|
||||
return simulation_manager.get_woodpile() as StorageStateRecord
|
||||
return null
|
||||
|
||||
|
||||
func _get_open_need_for_npc(npc: SimNPC) -> Dictionary:
|
||||
if not simulation_manager.has_method("get_latest_opportunity_for_npc"):
|
||||
return {
|
||||
@@ -439,14 +491,24 @@ func _build_resource_context(node: ResourceNode) -> PlayerInteractionResult:
|
||||
definition.display_name if definition != null else String(node.action_id).capitalize()
|
||||
)
|
||||
var display_name := String(node.node_id).replace("_", " ").capitalize()
|
||||
var carried := _get_player_carried(node.resource_id)
|
||||
var detail := (
|
||||
"%s · %.1f remaining · carrying %.1f" % [display_name, node.get_amount_remaining(), carried]
|
||||
)
|
||||
if _get_available_carry() <= 0.0:
|
||||
detail = "Hands full — deposit before gathering"
|
||||
return PlayerInteractionResult.new(
|
||||
PlayerInteractionResult.KIND_RESOURCE,
|
||||
node.action_id,
|
||||
node.node_id,
|
||||
display_name,
|
||||
prompt,
|
||||
"%s · %.1f remaining" % [display_name, node.get_amount_remaining()],
|
||||
node
|
||||
detail,
|
||||
node,
|
||||
{
|
||||
"blocked_reason":
|
||||
"" if _get_available_carry() > 0.0 else "You cannot carry more right now."
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -526,13 +588,19 @@ func _execute_animal_interaction(context: PlayerInteractionResult) -> void:
|
||||
|
||||
func _execute_resource_interaction(context: PlayerInteractionResult) -> void:
|
||||
var node := context.target_node as ResourceNode
|
||||
if node == null or not simulation_manager.has_method("harvest_resource_node"):
|
||||
push_error("Player: SimulationManager cannot harvest the resolved ResourceNode")
|
||||
if node == null or not simulation_manager.has_method("player_gather"):
|
||||
push_error("Player: SimulationManager cannot gather the resolved ResourceNode")
|
||||
return
|
||||
var extracted: float = simulation_manager.harvest_resource_node(node)
|
||||
var extracted: float = simulation_manager.player_gather(node)
|
||||
if extracted <= 0.0:
|
||||
interaction_feedback.emit(
|
||||
"%s is unavailable" % context.display_name, "Nothing could be gathered.", false
|
||||
"%s is unavailable" % context.display_name,
|
||||
(
|
||||
context.blocked_reason
|
||||
if not context.blocked_reason.is_empty()
|
||||
else "Nothing could be gathered."
|
||||
),
|
||||
false
|
||||
)
|
||||
return
|
||||
interaction_feedback.emit(
|
||||
@@ -582,6 +650,38 @@ func _execute_activity_interaction(context: PlayerInteractionResult) -> void:
|
||||
)
|
||||
|
||||
|
||||
func _execute_talk_interaction(context: PlayerInteractionResult) -> void:
|
||||
var npc_id := _talk_npc_id_from_target(context.target_id)
|
||||
if npc_id < 0:
|
||||
return
|
||||
var quest: PlayerQuestRecord = simulation_manager.accept_villager_request(npc_id)
|
||||
if quest == null:
|
||||
interaction_feedback.emit(
|
||||
"%s declines" % context.display_name,
|
||||
"They have no request you can accept right now.",
|
||||
false
|
||||
)
|
||||
return
|
||||
interaction_feedback.emit(
|
||||
"Request accepted",
|
||||
(
|
||||
"%s asked you for help · +%.0f Standing on completion"
|
||||
% [context.display_name, quest.get_standing_reward()]
|
||||
),
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
func _talk_npc_id_from_target(target_id: StringName) -> int:
|
||||
var prefix := "npc_"
|
||||
var suffix := "_inventory"
|
||||
var raw := String(target_id)
|
||||
if not raw.begins_with(prefix) or not raw.ends_with(suffix):
|
||||
return -1
|
||||
var id_text := raw.trim_prefix(prefix).trim_suffix(suffix)
|
||||
return id_text.to_int()
|
||||
|
||||
|
||||
func _execute_pantry_interaction(context: PlayerInteractionResult) -> void:
|
||||
if not context.is_available():
|
||||
interaction_feedback.emit("The pantry is empty", context.blocked_reason, false)
|
||||
@@ -624,6 +724,37 @@ func _storage_name_for(resource_id: StringName) -> String:
|
||||
return "village pantry" if resource_id == SimulationIds.RESOURCE_FOOD else "village woodpile"
|
||||
|
||||
|
||||
func _get_player_hunger() -> float:
|
||||
if simulation_manager == null or not simulation_manager.has_method("get_player_state"):
|
||||
return 0.0
|
||||
var state: PlayerStateRecord = simulation_manager.get_player_state()
|
||||
return state.get_hunger() if state != null else 0.0
|
||||
|
||||
|
||||
func is_starving() -> bool:
|
||||
if simulation_manager == null or not simulation_manager.has_method("get_player_state"):
|
||||
return false
|
||||
var state: PlayerStateRecord = simulation_manager.get_player_state()
|
||||
return state.is_starving() if state != null else false
|
||||
|
||||
|
||||
func _needs_speed_factor() -> float:
|
||||
if simulation_manager == null or not simulation_manager.has_method("get_player_state"):
|
||||
return 1.0
|
||||
var state: PlayerStateRecord = simulation_manager.get_player_state()
|
||||
if state == null or state.is_dead():
|
||||
return 0.0
|
||||
var factor := 1.0
|
||||
if state.is_starving():
|
||||
factor *= 0.5
|
||||
var energy := state.get_energy()
|
||||
if energy < 20.0:
|
||||
factor *= 0.6
|
||||
elif energy < 45.0:
|
||||
factor *= 0.8
|
||||
return factor
|
||||
|
||||
|
||||
func _get_animal_feed_cost() -> float:
|
||||
var definition := SimulationDefinitions.get_action(SimulationIds.ACTION_FEED_ANIMAL)
|
||||
return definition.completion_cost_amount if definition != null else 1.0
|
||||
@@ -648,6 +779,20 @@ func _get_carried_wood() -> float:
|
||||
return simulation_manager.get_player_state().get_inventory_amount(SimulationIds.RESOURCE_WOOD)
|
||||
|
||||
|
||||
func _get_player_carried(resource_id: StringName) -> float:
|
||||
if simulation_manager == null or not simulation_manager.has_method("get_player_state"):
|
||||
return 0.0
|
||||
var state: PlayerStateRecord = simulation_manager.get_player_state()
|
||||
return state.get_inventory_amount(resource_id) if state != null else 0.0
|
||||
|
||||
|
||||
func _get_available_carry() -> float:
|
||||
if simulation_manager == null or not simulation_manager.has_method("get_player_state"):
|
||||
return 0.0
|
||||
var state: PlayerStateRecord = simulation_manager.get_player_state()
|
||||
return state.get_available_carry() if state != null else 0.0
|
||||
|
||||
|
||||
func is_near_storage(storage_node: StorageNode) -> bool:
|
||||
if storage_node == null:
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user