using System.Collections.Generic; using Cielonos.MainGame.Rewards; using UnityEngine; namespace Cielonos.MainGame { public partial class RunManager { /// /// 管理一次 Combat 节点清空后的奖励会话。 /// 它记录待领取交互奖励数量,并集中处理装备/被动对奖励列表的临时修正。 /// public class RunCombatRewardSubmodule : SubmoduleBase { private CombatRewardSession _combatRewardSession; private readonly List _combatRewardModifiers = new(); public RunCombatRewardSubmodule(RunManager owner) : base(owner) { } public bool HasPendingCombatRewards => _combatRewardSession != null && _combatRewardSession.IsActive && _combatRewardSession.PendingCount > 0; public int PendingCount => _combatRewardSession?.PendingCount ?? 0; public void RegisterPendingCombatReward() { Debug.LogWarning("[RunManager] RegisterPendingCombatReward() is obsolete. Use RegisterPendingCombatReward(Vector3)."); } public void RegisterPendingCombatReward(Vector3 spawnPosition) { if (_combatRewardSession == null || !_combatRewardSession.IsActive) { Debug.LogWarning("[RunManager] 没有可用的 CombatRewardSession,无法登记待领取奖励。"); return; } // Interactable 奖励生成后必须登记,RunManager 才能阻止玩家在领取前前往下一个节点。 _combatRewardSession.RegisterPendingReward(spawnPosition); } public bool TryCompletePendingCombatReward() { if (_combatRewardSession == null || !_combatRewardSession.IsActive) { return false; } if (!_combatRewardSession.ResolvePendingReward()) { return false; } if (_combatRewardSession.PendingCount <= 0) { // 所有待领取奖励处理完毕后,Combat 节点才真正进入完成状态。 Clear(); owner.nodeFlowSm.CompleteCurrentNode(); } return true; } public void AddCombatRewardModifier(ICombatRewardModifier modifier) { if (modifier == null || _combatRewardModifiers.Contains(modifier)) { return; } _combatRewardModifiers.Add(modifier); } public CombatRewardSession GetActiveCombatRewardSession() { return _combatRewardSession != null && _combatRewardSession.IsActive ? _combatRewardSession : null; } public void Clear() { _combatRewardSession?.End(); _combatRewardSession = null; _combatRewardModifiers.Clear(); } public void BeginCombatRewardSession(CombatRewardContext context) { _combatRewardSession?.End(); _combatRewardSession = new CombatRewardSession(context); } public void ApplyCombatRewardModifiers(CombatRewardContext context, List rewards) { for (int i = _combatRewardModifiers.Count - 1; i >= 0; i--) { ICombatRewardModifier modifier = _combatRewardModifiers[i]; if (modifier == null || modifier.IsExpired) { _combatRewardModifiers.RemoveAt(i); continue; } modifier.Modify(context, rewards); } } public void NotifyCombatRewardDispatched(CombatRewardContext context) { for (int i = _combatRewardModifiers.Count - 1; i >= 0; i--) { ICombatRewardModifier modifier = _combatRewardModifiers[i]; if (modifier == null) { _combatRewardModifiers.RemoveAt(i); continue; } modifier.OnDispatched(context); if (modifier.IsExpired) { _combatRewardModifiers.RemoveAt(i); } } } public bool CompleteCombatRewardSessionIfEmpty() { if (_combatRewardSession == null || !_combatRewardSession.IsActive) { return false; } if (_combatRewardSession.PendingCount > 0) { return true; } _combatRewardSession.End(); _combatRewardSession = null; owner.nodeFlowSm.CompleteCurrentNode(); return true; } public static bool HasInteractableCombatReward(IReadOnlyList rewards) { if (rewards == null) { return false; } foreach (CombatRewardInstruction reward in rewards) { if (reward != null && reward.UsesInteractable && reward.count > 0) { return true; } } return false; } } } }