feat: let the player talk to villagers and accept or decline personal requests
This commit is contained in:
@@ -5,6 +5,7 @@ const KIND_ANIMAL := &"animal"
|
||||
const KIND_RESOURCE := &"resource"
|
||||
const KIND_PANTRY := &"pantry"
|
||||
const KIND_DEPOSIT := &"deposit"
|
||||
const KIND_TALK := &"talk"
|
||||
const KIND_GUARD := &"guard"
|
||||
const KIND_STUDY := &"study"
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
class_name PlayerTalkResult
|
||||
extends RefCounted
|
||||
|
||||
var npc_id: int
|
||||
var npc_name: String
|
||||
var greeting: String
|
||||
var has_need: bool
|
||||
var need_text: String
|
||||
var quest_available: bool
|
||||
var quest_reward: float
|
||||
var can_accept: bool
|
||||
var can_decline: bool
|
||||
|
||||
|
||||
func _init(
|
||||
talk_npc_id: int,
|
||||
talk_npc_name: String,
|
||||
talk_greeting: String,
|
||||
talk_has_need: bool,
|
||||
talk_need_text: String,
|
||||
talk_quest_available: bool,
|
||||
talk_quest_reward: float,
|
||||
talk_can_accept: bool,
|
||||
talk_can_decline: bool
|
||||
) -> void:
|
||||
npc_id = talk_npc_id
|
||||
npc_name = talk_npc_name
|
||||
greeting = talk_greeting
|
||||
has_need = talk_has_need
|
||||
need_text = talk_need_text
|
||||
quest_available = talk_quest_available
|
||||
quest_reward = talk_quest_reward
|
||||
can_accept = talk_can_accept
|
||||
can_decline = talk_can_decline
|
||||
|
||||
|
||||
func cache_key() -> String:
|
||||
return (
|
||||
"|"
|
||||
. join(
|
||||
[
|
||||
str(npc_id),
|
||||
npc_name,
|
||||
greeting,
|
||||
str(has_need),
|
||||
need_text,
|
||||
str(quest_available),
|
||||
"%.2f" % quest_reward,
|
||||
str(can_accept),
|
||||
str(can_decline),
|
||||
]
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
uid://i7pjb5605cgr
|
||||
@@ -72,6 +72,8 @@ func try_interact() -> void:
|
||||
_execute_resource_interaction(context)
|
||||
PlayerInteractionResult.KIND_DEPOSIT:
|
||||
_execute_deposit_interaction(context)
|
||||
PlayerInteractionResult.KIND_TALK:
|
||||
_execute_talk_interaction(context)
|
||||
PlayerInteractionResult.KIND_GUARD:
|
||||
simulation_manager.add_safety(3.0)
|
||||
interaction_feedback.emit(
|
||||
@@ -131,9 +133,53 @@ func get_interaction_context() -> PlayerInteractionResult:
|
||||
)
|
||||
if is_near_storage(pantry_storage):
|
||||
return _build_pantry_context()
|
||||
var talk_npc := _find_talk_villager()
|
||||
if talk_npc != null:
|
||||
return _build_talk_context(talk_npc)
|
||||
return null
|
||||
|
||||
|
||||
func _find_talk_villager() -> SimNPC:
|
||||
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, interaction_range
|
||||
)
|
||||
if npc_id < 0:
|
||||
return null
|
||||
var npc := _find_npc(npc_id)
|
||||
if npc == null or npc.is_dead:
|
||||
return null
|
||||
return npc
|
||||
|
||||
|
||||
func _build_talk_context(npc: SimNPC) -> PlayerInteractionResult:
|
||||
var talk: PlayerTalkResult = simulation_manager.get_villager_talk(npc.id)
|
||||
if talk == null or not talk.has_need:
|
||||
return null
|
||||
var prompt := "Talk to %s" % npc.npc_name
|
||||
if talk.quest_available:
|
||||
prompt = "Accept %s's request" % npc.npc_name
|
||||
elif talk.can_accept:
|
||||
prompt = "Offer to help %s" % npc.npc_name
|
||||
var detail := talk.need_text
|
||||
if talk.quest_available:
|
||||
detail = "Help +%.0f Standing" % talk.quest_reward
|
||||
return PlayerInteractionResult.new(
|
||||
PlayerInteractionResult.KIND_TALK,
|
||||
SimulationIds.ACTION_IDLE,
|
||||
SimulationIds.npc_inventory_id(npc.id),
|
||||
npc.npc_name,
|
||||
prompt,
|
||||
detail,
|
||||
null
|
||||
)
|
||||
|
||||
|
||||
func get_nearby_villager_inspection() -> VillagerInspectionResult:
|
||||
if (
|
||||
simulation_manager == null
|
||||
@@ -437,6 +483,38 @@ func _execute_deposit_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)
|
||||
|
||||
Reference in New Issue
Block a user