using UnityEngine; using BaseGames.Player; namespace BaseGames.Quest { /// /// 任务目标基类(抽象,架构 22_QuestChallengeModule §3)。 /// 所有具体目标类型均继承此类,通过多态实现零代码扩展。 /// 每种目标在事件驱动下由 QuestManager 调用 EvaluateCompletion()。 /// public abstract class QuestObjectiveSO : ScriptableObject { [Header("标识")] [Tooltip("目标唯一 ID,如 \"OBJ_TalkElder\"。空时由 OnValidate 自动以资产名填充。")] public string objectiveId; [Tooltip("本地化 Key,格式如 \"Quest_FindMushroom_Obj1\"。通过 LocalizationManager.Get(displayTextKey, \"Quest\") 显示给玩家。")] [TextArea(1, 4)] public string displayTextKey; [Tooltip("勾选后此目标为可选项:完成可获奖励,但不阻塞任务交接。")] public bool IsOptional; /// 根据当前进度判断目标是否完成。 public abstract bool EvaluateCompletion(QuestObjectiveState state); /// /// 在 DataHub / 编辑器工具中显示的类型徽章文字。 /// 子类应 override 返回简洁中文标签(如 "[对话]")。 /// 避免工具代码中使用 type-switch 维护列表。 /// public virtual string BadgeLabel => "[目标]"; #if UNITY_EDITOR private void OnValidate() { if (!string.IsNullOrEmpty(objectiveId)) return; objectiveId = name; UnityEditor.EditorUtility.SetDirty(this); } #endif } // ── 运行时目标进度状态(由 QuestManager 管理,不继承 SO)──────────────── public class QuestObjectiveState { public bool completed = false; public int progressCount = 0; } // ── 具体目标类型 ──────────────────────────────────────────────────────── /// 与指定 NPC 对话后完成。 [CreateAssetMenu(menuName = "BaseGames/Quest/Objective/TalkToNPC")] public class TalkToNPCObjective : QuestObjectiveSO { [Tooltip("目标 NPC 的唯一 ID,需与 NPC 组件上的 npcId / InteractableNPC.npcId 保持一致。")] public string targetNpcId; public override string BadgeLabel => "[对话]"; public override bool EvaluateCompletion(QuestObjectiveState s) => s.progressCount >= 1; } /// 击败指定 ID 的敌人若干次。 [CreateAssetMenu(menuName = "BaseGames/Quest/Objective/Defeat")] public class DefeatEnemyObjective : QuestObjectiveSO { [Tooltip("目标敌人的唯一 ID,需与敌人 SO 或敌人组件上的 enemyId 保持一致。")] public string targetEnemyId; [Tooltip("需击败的次数,默认 1。")] [Min(1)] public int defeatCount = 1; public override string BadgeLabel => "[击败]"; public override bool EvaluateCompletion(QuestObjectiveState s) => s.progressCount >= defeatCount; } /// 收集指定 ID 的物品若干件。 [CreateAssetMenu(menuName = "BaseGames/Quest/Objective/Collect")] public class CollectItemObjective : QuestObjectiveSO { [Tooltip("目标物品的唯一 ID,需与拾取事件广播的 itemId 保持一致。")] public string itemId; [Tooltip("需收集的数量,默认 1。")] [Min(1)] public int collectCount = 1; public override string BadgeLabel => "[收集]"; public override bool EvaluateCompletion(QuestObjectiveState s) => s.progressCount >= collectCount; } /// 到达指定场景/区域标记点后完成。 [CreateAssetMenu(menuName = "BaseGames/Quest/Objective/Reach")] public class ReachAreaObjective : QuestObjectiveSO { [Tooltip("需到达的场景名(Unity Build Settings 中的场景名称)。")] public string sceneName; [Tooltip("场景内的目标标记 Tag(预留字段,当前未启用)。")] public string markerTag; public override string BadgeLabel => "[到达]"; public override bool EvaluateCompletion(QuestObjectiveState s) => s.progressCount >= 1; } /// 使用指定能力若干次后完成。 [CreateAssetMenu(menuName = "BaseGames/Quest/Objective/UseSkill")] public class UseSkillObjective : QuestObjectiveSO { [Tooltip("目标能力类型。事件频道 EVT_SkillUsed 广播 AbilityType.ToString(),与此值匹配时计数。")] public AbilityType requiredAbility; [Tooltip("需使用的次数,默认 1。")] [Min(1)] public int useCount = 1; public override string BadgeLabel => "[使用]"; public override bool EvaluateCompletion(QuestObjectiveState s) => s.progressCount >= useCount; } }