Files
Cielonos/Assets/Scripts/MainGame/GameRun/RunManager/RunManager_CombatRewardSubmodule.cs

166 lines
5.7 KiB
C#
Raw Permalink Normal View History

2026-07-18 03:16:20 -04:00
using System.Collections.Generic;
using Cielonos.MainGame.Rewards;
using UnityEngine;
namespace Cielonos.MainGame
{
public partial class RunManager
{
/// <summary>
/// 管理一次 Combat 节点清空后的奖励会话。
/// 它记录待领取交互奖励数量,并集中处理装备/被动对奖励列表的临时修正。
/// </summary>
public class RunCombatRewardSubmodule : SubmoduleBase<RunManager>
{
private CombatRewardSession _combatRewardSession;
private readonly List<ICombatRewardModifier> _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<CombatRewardInstruction> 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<CombatRewardInstruction> rewards)
{
if (rewards == null)
{
return false;
}
foreach (CombatRewardInstruction reward in rewards)
{
if (reward != null && reward.UsesInteractable && reward.count > 0)
{
return true;
}
}
return false;
}
}
}
}