using UnityEngine; using BaseGames.Core.Events; using BaseGames.Player; namespace BaseGames.Quest { /// /// 任务奖励 SO(架构 22_QuestChallengeModule §4)。 /// 由 QuestManager.CompleteQuest() 调用 Apply() 发放奖励。 /// 资产路径: Assets/ScriptableObjects/Quest/Reward_{questId}.asset /// [CreateAssetMenu(menuName = "BaseGames/Quest/Reward")] public class RewardSO : ScriptableObject { [Header("货币与属性")] [Tooltip("完成任务奖励的灵珠数量(0 = 不奖励)。")] public int lingZhu; [Tooltip("完成任务后永久增加的灵魂槽上限数值(0 = 不奖励)。")] public int soulBonus; [Header("物品")] [Tooltip("完成任务奖励的物品/护符 ID 列表。每个 ID 通过 EVT_CollectiblePickup 事件频道广播,由 InventoryManager 处理。\n" + "格式如 [\"Charm_DashBoost\", \"Item_HealShard\"]。留空表示无物品奖励。")] public string[] itemIds; [Header("NPC 关系")] [Tooltip("完成任务后对发布 NPC(QuestSO.giverNpc)的好感度增量。\n" + "正值=好感增加,负值=好感降低。0 = 不影响好感度。\n" + "增量以强类型 NpcAffinityEvent(npcId + delta + newTotal)广播至 EVT_NpcAffinityChanged,\n" + "并持久化到 SaveData.World.NpcRelations。接收方无需字符串解析。")] public int affinityBonus; [Tooltip("完成任务后解锁的 NPC 台词集合 Key(格式如 \"DLG_Elder_PostQuest\")。\n" + "非空时广播 EVT_DialogueKeyUnlocked 事件,供 NPC 台词管理系统监听并切换对话集。\n" + "留空表示不解锁新台词。")] public string unlockDialogueKey; [Header("能力解锁")] [Tooltip("勾选后,unlockedAbilityFlag 中指定的能力将在完成任务时解锁。")] public bool unlocksAbility; [Tooltip("要解锁的能力(AbilityType 组合标志位,仅当 unlocksAbility == true 有效)。\n" + "可多选,支持组合解锁多项能力。")] public AbilityType unlockedAbilityFlag; [Header("物品发放事件")] [Tooltip("EVT_CollectiblePickup 事件频道(StringEventChannelSO)。\n" + "Apply() 调用时,每个 itemId 都会通过此频道广播,供 EquipmentManager/QuestManager 处理。\n" + "未连线时物品奖励不生效。")] [SerializeField] private StringEventChannelSO _onCollectiblePickup; /// /// 将奖励应用到游戏状态(由 QuestManager.CompleteQuest 调用)。 /// 通过 接口操作,避免直接依赖 BaseGames.Player 程序集。 /// public void Apply(IRewardTarget target) { if (target == null) return; if (lingZhu > 0) target.AddLingZhu(lingZhu); if (soulBonus > 0) target.AddSoulPower(soulBonus); if (unlocksAbility && unlockedAbilityFlag != AbilityType.None) target.UnlockAbilityFlag((uint)unlockedAbilityFlag); // 通过 EVT_CollectiblePickup 事件频道广播每个物品 ID if (itemIds != null && itemIds.Length > 0) { if (_onCollectiblePickup != null) { foreach (var id in itemIds) _onCollectiblePickup.Raise(id); } else { #if UNITY_EDITOR || DEVELOPMENT_BUILD Debug.LogWarning( $"[RewardSO] '{name}' 配置了 {itemIds.Length} 个 itemIds," + "但 _onCollectiblePickup 事件频道未连线,物品奖励不会发放。请在 Inspector 中指定 EVT_CollectiblePickup 频道。", this); #endif } } } } }