feat: Round 48 narrative systems improvements
- QuestSO: Add ValidateBranchCycles() DFS detection for branches[].nextQuest loop - QuestSO: Mark three legacy prerequisite fields with v2.0 removal warning in Tooltip - IQuestManager: Add QuestLockReason enum + QuestLockInfo struct (strongly-typed lock info) - IQuestManager: Add GetQuestLockInfo() method to interface; GetQuestLockReason() now delegates to it - IQuestEventSource: Add OnQuestStateChanged(questId, oldState, newState) unified event - QuestManager: Implement GetQuestLockInfo(); fire OnQuestStateChanged on all state transitions - DialogueManager: Add one-frame yield in HandleChoices before ShowChoices (skip-debounce fix) - DialogueManager: Increment _playbackId in ForceEnd() to invalidate residual choice callbacks - DialogueSequenceSO: Add UNITY_EDITOR debug log in TryGetActiveVariant on variant match - WorldStateRegistry: Add OnBatchStateChanged event + BatchMark() batch-write API - DialogueModule: List badge shows warning indicator for unconditional-shadowing variants - DialogueModule: BuildVariantsCard shows logic mode (AND/OR) alongside flag conditions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -14,16 +14,42 @@ namespace BaseGames.Quest
|
||||
public class QuestGiver : InteractableNPC
|
||||
{
|
||||
[Header("任务")]
|
||||
[SerializeField] private QuestSO[] _offeredQuests; // 该 NPC 可提供的所有任务(按优先级排列)
|
||||
[Tooltip("该 NPC 可提供的所有任务,按优先级从高到低排列。\n" +
|
||||
"交互时从列表头部找到第一个 Available 或 Active 状态的任务作为当前任务;\n" +
|
||||
"若全部已完成,显示最后一个已完成任务的 completedDialogue。")]
|
||||
[SerializeField] private QuestSO[] _offeredQuests;
|
||||
|
||||
[Header("对话版本(根据任务状态切换)")]
|
||||
[SerializeField] private DialogueSequenceSO _availableDialogue; // 任务可接时
|
||||
[SerializeField] private DialogueSequenceSO _activeDialogue; // 任务进行中
|
||||
[SerializeField] private DialogueSequenceSO _readyDialogue; // 完成条件满足时
|
||||
[SerializeField] private DialogueSequenceSO _completedDialogue; // 任务已完成后
|
||||
[Tooltip("任务尚未接取(QuestState.Available)时播放。通常是 NPC 发布任务、介绍背景的对话。")]
|
||||
[SerializeField] private DialogueSequenceSO _availableDialogue;
|
||||
[Tooltip("任务已接取、目标尚未全部完成(QuestState.Active)时播放。通常是 NPC 催促或加油打气的对话。")]
|
||||
[SerializeField] private DialogueSequenceSO _activeDialogue;
|
||||
[Tooltip("全部非可选目标已达成、任务可以交付时播放(IsReadyToComplete = true)。\n" +
|
||||
"通常是 NPC 感谢、确认收取物品的对话,播放后执行 CompleteQuest 逻辑。")]
|
||||
[SerializeField] private DialogueSequenceSO _readyDialogue;
|
||||
[Tooltip("任务已完成(QuestState.Completed)后再次交互时播放。通常是 NPC 闲聊或后续剧情的对话。")]
|
||||
[SerializeField] private DialogueSequenceSO _completedDialogue;
|
||||
|
||||
// ── InteractableNPC 覆盖 ──────────────────────────────────────────────
|
||||
|
||||
public override string InteractPrompt
|
||||
{
|
||||
get
|
||||
{
|
||||
var qm = SL.GetOrDefault<IQuestManager>();
|
||||
var quest = GetCurrentOrCompletedQuest(qm);
|
||||
if (quest == null || qm == null) return base.InteractPrompt;
|
||||
return qm.GetState(quest.questId) switch
|
||||
{
|
||||
QuestStateEnum.Available => "接受任务",
|
||||
QuestStateEnum.Active => qm.IsReadyToComplete(quest.questId) ? "提交任务" : "进行中…",
|
||||
QuestStateEnum.Paused => "暂停中…",
|
||||
QuestStateEnum.Completed => "对话",
|
||||
_ => base.InteractPrompt,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Interact_Internal(Transform player)
|
||||
{
|
||||
var qm = SL.GetOrDefault<IQuestManager>();
|
||||
@@ -57,6 +83,7 @@ namespace BaseGames.Quest
|
||||
QuestStateEnum.Available => _availableDialogue,
|
||||
QuestStateEnum.Active => qm.IsReadyToComplete(quest.questId)
|
||||
? _readyDialogue : _activeDialogue,
|
||||
QuestStateEnum.Paused => _activeDialogue, // 暂停中显示"催促"对话,不触发任何状态推进
|
||||
QuestStateEnum.Completed => _completedDialogue,
|
||||
_ => base.GetCurrentDialogue(),
|
||||
};
|
||||
@@ -79,7 +106,7 @@ namespace BaseGames.Quest
|
||||
{
|
||||
if (q == null) continue;
|
||||
var s = qm.GetState(q.questId);
|
||||
if (s == QuestStateEnum.Available || s == QuestStateEnum.Active) return q;
|
||||
if (s == QuestStateEnum.Available || s == QuestStateEnum.Active || s == QuestStateEnum.Paused) return q;
|
||||
if (s == QuestStateEnum.Completed) lastCompleted = q;
|
||||
}
|
||||
return lastCompleted;
|
||||
|
||||
Reference in New Issue
Block a user