using System; using BaseGames.Core.Events; using QuestStateEnum = BaseGames.Core.Events.QuestState; namespace BaseGames.Quest { // ========================================================================= // QuestLockReason / QuestLockInfo ── 任务锁定原因(强类型 API) // ========================================================================= /// 任务无法接取的原因枚举。 表示无锁定(可接取)。 public enum QuestLockReason { /// 无锁定,任务当前可以接取。 None, /// 任务已在进行中(Active)。 AlreadyActive, /// 任务已完成(Completed)。 AlreadyCompleted, /// 任务已失败(Failed)。 Failed, /// 任务已暂停(Paused)。 Paused, /// 任务 ID 未找到或资产未加载。 NotFound, /// 好感度或存档数据尚未初始化。 DataNotLoaded, /// NPC 好感度不足。 格式:"{actual}/{min}"。 InsufficientAffinity, /// 前置任务未完成。 为该前置任务的 questId。 RequiresQuest, /// 世界状态标志条件未满足。 FlagConditionNotMet, } /// /// 任务锁定信息(强类型版本)。 /// 相比字符串 Key,可在编译期检查原因类型,UI 层无需手动解析冒号分隔的参数。 /// 通过 可转换为与旧版 GetQuestLockReason 兼容的 Key 格式。 /// public struct QuestLockInfo { /// 锁定原因枚举值。 表示无锁定(可接取)。 public QuestLockReason Reason; /// /// 附带参数(可选):
/// - :前置任务 questId
/// - :格式 "{actual}/{min}" ///
public string Param; /// 任务当前是否处于锁定状态(不可接取)。 public bool IsLocked => Reason != QuestLockReason.None; /// /// 转换为本地化 Key 格式,与旧版 完全兼容。 /// 格式:"Quest.LockReason.{Reason}";有参数时为 "Quest.LockReason.{Reason}:{Param}"。 /// public string ToLocalizationKey() => Reason == QuestLockReason.None ? string.Empty : string.IsNullOrEmpty(Param) ? $"Quest.LockReason.{Reason}" : $"Quest.LockReason.{Reason}:{Param}"; } /// /// 任务管理器的公开契约。ServiceLocator.Get<IQuestManager>() 获取实例, /// 避免外部代码直接依赖 QuestManager 具体类型。 /// public interface IQuestManager { /// 接取任务(幂等)。 void AcceptQuest(string questId); /// /// 主动放弃进行中的任务(Active → Available/Unavailable),清除目标进度。 /// 非 Active 状态的任务调用此方法无效。 /// void AbandonQuest(string questId); /// 完成任务并发放奖励。rewardTarget 接收奖励(如玩家)。 void CompleteQuest(string questId, IRewardTarget rewardTarget); /// /// 暂停进行中的任务(Active → Paused)。暂停期间目标不推进,失败条件不判定。 /// 非 Active 状态的任务调用此方法无效。 /// void PauseQuest(string questId); /// /// 恢复已暂停的任务(Paused → Active)。 /// 非 Paused 状态的任务调用此方法无效。 /// void ResumeQuest(string questId); /// 返回当前任务状态。未知 questId 返回 Unavailable。 QuestStateEnum GetState(string questId); /// 判断任务是否满足完成条件。 bool IsReadyToComplete(string questId); /// 返回指定 NPC 的当前好感度数值(未记录时返回 0)。 int GetNpcAffinity(string npcId); /// /// 返回任务无法被接取的原因(本地化 Key 格式)。 /// 若任务当前可以接取,返回空字符串。 /// Key 格式:"Quest.LockReason.{Reason}";带动态参数时以冒号分隔,如 /// "Quest.LockReason.RequiresQuest:Quest_FindMushroom"。 /// 推荐新代码使用 获取强类型结果,无需手动解析字符串。 /// string GetQuestLockReason(string questId); /// /// 返回任务无法被接取的强类型锁定信息。 /// 相比 ,可在编译期检查原因枚举,UI 层无需解析字符串。 /// 若任务当前可以接取,返回 的实例。 /// QuestLockInfo GetQuestLockInfo(string questId); /// /// 返回当前处于指定状态的所有任务 ID 快照列表。 /// 适用于任务日志 UI 分组显示、成就系统批量统计等场景。 /// System.Collections.Generic.IReadOnlyList GetQuestsInState(QuestStateEnum state); /// /// 对所有已注册任务执行谓词过滤,返回满足条件的任务 ID 快照列表。 /// 适用于自定义筛选(如"活跃且含 NPC 亲密度门槛")等场景。 /// System.Collections.Generic.IReadOnlyList FilterQuests(System.Func predicate); } /// /// 任务事件订阅接口。 /// 外部系统(成就、地图标记、HUD、埋点)通过此接口订阅任务生命周期事件, /// 无需直接持有 StringEventChannelSO,保持与 QuestManager 具体实现的解耦。 /// 获取方式:ServiceLocator.Get<IQuestManager>() as IQuestEventSource /// public interface IQuestEventSource { /// 任务成功接取时触发。参数 = questId。 event Action OnQuestStarted; /// 任务完成时触发。参数 = questId。 event Action OnQuestCompleted; /// 任务失败时触发。参数 = questId。 event Action OnQuestFailed; /// 任务被主动放弃时触发。参数 = questId。 event Action OnQuestAbandoned; /// 任务暂停时触发(Active → Paused)。参数 = questId。供埋点/分析系统使用。 event Action OnQuestPaused; /// 任务从暂停恢复时触发(Paused → Active)。参数 = questId。供埋点/分析系统使用。 event Action OnQuestResumed; /// 目标全部达成、可回去交任务时触发(去重,同任务只触发一次)。参数 = questId。 event Action OnQuestReadyToComplete; /// /// 任务状态发生任意转换时触发(涵盖所有状态变更,含旧状态和新状态)。 /// 供状态机审计面板、通用 UI 绑定(无需分别订阅六个离散事件)使用。 /// 参数:(questId, oldState, newState)。 /// event Action OnQuestStateChanged; } #if UNITY_EDITOR || DEVELOPMENT_BUILD /// /// 任务调试接口(仅编辑器 / 开发构建可用)。 /// 通过 (IQuestManager as IQuestDebugger)?.ResetQuest(id) 使用, /// 正式发布构建中此接口不存在,调用方无需任何 #if 守卫。 /// public interface IQuestDebugger { /// /// 将任务重置为 Available(前置满足)或 Unavailable(前置未满足),并清除目标进度。 /// 不广播 QuestStarted / QuestCompleted 等运行时事件,仅用于开发/调试。 /// /// 要重置的任务 ID。 /// 若为 true(默认),同步回滚此任务对应 NPC 的好感度增量, /// 防止调试期间重复完成导致好感度叠加。 void ResetQuest(string questId, bool rollbackAffinity = true); } #endif }