using System.Collections.Generic; using Cielonos.MainGame.Characters; using Cielonos.MainGame.Rewards; using UnityEngine; namespace Cielonos.MainGame { public partial class RunManager { /// /// CombatRoom 到 Run 流程的桥接层。 /// CombatRoomSubmodule 只负责报告“战斗清空”,这里负责判断当前节点是否合法、生成 CombatRewardSession 并推动节点完成。 /// public class RunCombatSubmodule : SubmoduleBase { public RunCombatSubmodule(RunManager owner) : base(owner) { } public void SubscribeRoomEvents() { // RunManager 是战斗结果进入 Run 流程的唯一入口,避免 UI/奖励系统重复解释 CombatRoom 事件。 CombatManager.CombatRoomSm.OnRoomCleared += OnRoomCleared; CombatManager.CombatRoomSm.OnEnemyDefeated += OnEnemyDefeated; } public void UnsubscribeRoomEvents() { if (CombatManager.Instance == null || CombatManager.CombatRoomSm == null) { return; } CombatManager.CombatRoomSm.OnRoomCleared -= OnRoomCleared; CombatManager.CombatRoomSm.OnEnemyDefeated -= OnEnemyDefeated; } private void OnEnemyDefeated(CharacterBase enemy) { owner.progressSm.RecordEnemyDefeated(enemy); EnemyDefeatRewardDispatcher.Dispatch(enemy, owner.currentRun?.randomizer?.Channel("EnemyDrop")); } private void OnRoomCleared() { if (owner.currentRun == null) return; if (!owner.currentRun.mapData.nodes.TryGetValue(owner.currentRun.currentPosition, out RunMapNode node)) { return; } if (!RunNodeTypeUtility.IsCombatNode(node.nodeType)) { // 起点或非战斗节点不应该因为空房间触发 Run 完成逻辑。 Debug.LogWarning($"[RunManager] Ignored OnRoomCleared because current node is not a Combat node: {node.nodeType}."); return; } owner.RaiseCombatRoomCleared(node); if (owner.currentRun.currentPosition == owner.currentRun.mapData.bossPosition) { Debug.Log("[RunManager] Boss 房间已清空,等待玩家交互并离开。"); owner.phaseSm.TransitionToPhase(RunPhase.MapSelection); return; } CombatRewardContext rewardContext = new CombatRewardContext( owner.currentRun, node, owner.currentRun.currentPosition, owner.currentRun.randomizer?.Next() ?? new System.Random()); // 奖励结算分三步:建立 session、解析配置、让装备/被动修正奖励列表。 owner.combatRewardSm.BeginCombatRewardSession(rewardContext); List rewards = CombatRewardResolver.Resolve(MainGameManager.Config?.combatRewardProfile, rewardContext); owner.combatRewardSm.ApplyCombatRewardModifiers(rewardContext, rewards); bool hasInteractableReward = RunCombatRewardSubmodule.HasInteractableCombatReward(rewards); if (hasInteractableReward) { owner.phaseSm.TransitionToPhase(RunPhase.MapSelection); } bool hasPendingReward = rewards.Count > 0 && CombatRewardDispatcher.Dispatch(rewardContext, rewards); owner.combatRewardSm.NotifyCombatRewardDispatched(rewardContext); if (hasPendingReward) { Debug.Log($"[RunManager] Combat 房间已清空,生成 {owner.combatRewardSm.PendingCount} 个待领取奖励。"); return; } if (hasInteractableReward) { Debug.LogWarning("[RunManager] Combat 奖励规则包含交互奖励,但没有成功生成任何待领取奖励。"); } Debug.Log("[RunManager] 收到 OnRoomCleared,完成当前 Combat 节点。"); owner.combatRewardSm.CompleteCombatRewardSessionIfEmpty(); } } } }