Files
zeling_v2/Assets/_Game/Scripts/Quest/QuestGiver.cs
Joywayer 446fd5dcd0 feat: Add WorldStateFlagAttribute and custom property drawer for enhanced dialogue management
- Implemented WorldStateFlagAttribute to mark string fields as world state flags.
- Created NarrativeNPCEditor for custom inspector to visualize dialogue version activation states.
- Developed WorldStateFlagDrawer to provide dropdown menu for known flags in the inspector.
- Introduced ActorModule for managing DialogueActorSO assets, including viewing, creating, and deleting actors.
- Added DialogueModule for managing DialogueSequenceSO assets with detailed previews and action bars.
- Established QuestModule for managing QuestSO assets, including objectives and branches.
- Implemented QuestManagerPostprocessor to automatically refresh QuestManager's quest list on asset changes.
2026-05-24 00:36:11 +08:00

89 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// 可发布/完成任务的 NPC架构 22_QuestChallengeModule §6
/// 继承 InteractableNPC根据任务状态切换对话版本在交互时处理任务接收/完成。
/// </summary>
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<IQuestManager>();
var quest = GetCurrentOrCompletedQuest(qm);
if (quest == null || qm == null) return;
var state = qm.GetState(quest.questId);
if (state == QuestStateEnum.Available)
{
qm.AcceptQuest(quest.questId);
}
else if (state == QuestStateEnum.Active && qm.IsReadyToComplete(quest.questId))
{
// 直接从 player 获取 PlayerStats避免对 PlayerController 的程序集依赖
var stats = player.GetComponentInParent<PlayerStats>();
qm.CompleteQuest(quest.questId, stats);
}
}
protected override DialogueSequenceSO GetCurrentDialogue()
{
var qm = SL.GetOrDefault<IQuestManager>();
var quest = GetCurrentOrCompletedQuest(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(),
};
}
// ── 私有辅助 ─────────────────────────────────────────────────────────
/// <summary>
/// 返回当前处于 Available 或 Active 状态的第一个任务;
/// 若全部已完成,返回最后一个已完成任务(用于显示 completedDialogue
/// </summary>
private QuestSO GetCurrentOrCompletedQuest(IQuestManager qm = null)
{
if (_offeredQuests == null) return null;
qm ??= SL.GetOrDefault<IQuestManager>();
if (qm == null) return null;
QuestSO lastCompleted = 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;
if (s == QuestStateEnum.Completed) lastCompleted = q;
}
return lastCompleted;
}
}
}