using UnityEngine; using BaseGames.Core; using BaseGames.Dialogue; using BaseGames.Player; using QuestStateEnum = BaseGames.Core.Events.QuestState; using SL = BaseGames.Core.ServiceLocator; namespace BaseGames.Quest { /// /// 可发布/完成任务的 NPC(架构 22_QuestChallengeModule §6)。 /// 继承 InteractableNPC,根据任务状态切换对话版本,在交互时处理任务接收/完成。 /// public class QuestGiver : InteractableNPC { [Header("任务")] [SerializeField] private QuestSO[] _offeredQuests; // 该 NPC 可提供的所有任务(按优先级排列) [Header("对话版本(根据任务状态切换)")] [SerializeField] private DialogueSequenceSO _availableDialogue; // 任务可接时 [SerializeField] private DialogueSequenceSO _activeDialogue; // 任务进行中 [SerializeField] private DialogueSequenceSO _readyDialogue; // 完成条件满足时 [SerializeField] private DialogueSequenceSO _completedDialogue; // 任务已完成后 // ── InteractableNPC 覆盖 ────────────────────────────────────────────── protected override void Interact_Internal(Transform player) { var qm = SL.GetOrDefault(); var quest = GetCurrentQuest(qm); if (quest == null || qm == null) return; var state = qm.GetState(quest.questId); if (state == QuestStateEnum.Available) { qm.AcceptQuest(quest.questId); } else if (qm.IsReadyToComplete(quest.questId)) { // 直接从 player 获取 PlayerStats,避免对 PlayerController 的程序集依赖 var stats = player.GetComponentInParent(); qm.CompleteQuest(quest.questId, stats); } } protected override DialogueSequenceSO GetCurrentDialogue() { var qm = SL.GetOrDefault(); var quest = GetCurrentQuest(qm); if (quest == null || qm == null) return base.GetCurrentDialogue(); var state = qm.GetState(quest.questId); return state switch { QuestStateEnum.Available => _availableDialogue, QuestStateEnum.Active => qm.IsReadyToComplete(quest.questId) ? _readyDialogue : _activeDialogue, QuestStateEnum.Completed => _completedDialogue, _ => base.GetCurrentDialogue(), }; } // ── 私有辅助 ───────────────────────────────────────────────────────── /// 返回当前处于 Available 或 Active 状态的第一个任务。 private QuestSO GetCurrentQuest(IQuestManager qm = null) { if (_offeredQuests == null) return null; qm ??= SL.GetOrDefault(); if (qm == null) return null; foreach (var q in _offeredQuests) { if (q == null) continue; var s = qm.GetState(q.questId); if (s == QuestStateEnum.Available || s == QuestStateEnum.Active) return q; } return null; } } }