using System; using System.Collections.Generic; using Cielonos.MainGame.Map; using Cielonos.MainGame.Rewards; using Sirenix.OdinInspector; using SLSUtilities.General; using UnityEngine; namespace Cielonos.MainGame { /// /// 驱动整局 Roguelite Run 的会话管理器。 /// 对外保持原有 RunManager API,对内将生命周期、节点流程、奖励、统计等职责拆分给 Submodule。 /// public partial class RunManager : Singleton, ISubstructureOwner { [TitleGroup("配置")] [Tooltip("地图生成配置")] public MapGenerationConfig mapConfig; [TitleGroup("运行时状态"), ReadOnly] public RunState currentRun; [TitleGroup("运行时状态"), ReadOnly] public RunPhase currentPhase = RunPhase.Idle; [ShowInInspector, FoldoutGroup("Submodules"), ReadOnly] private RunSessionSubmodule sessionSm; [ShowInInspector, FoldoutGroup("Submodules"), ReadOnly] private RunPhaseSubmodule phaseSm; [ShowInInspector, FoldoutGroup("Submodules"), ReadOnly] private RunNodeFlowSubmodule nodeFlowSm; [ShowInInspector, FoldoutGroup("Submodules"), ReadOnly] private RunCombatSubmodule combatSm; [ShowInInspector, FoldoutGroup("Submodules"), ReadOnly] private RunCombatRewardSubmodule combatRewardSm; [ShowInInspector, FoldoutGroup("Submodules"), ReadOnly] private RunProgressSubmodule progressSm; [ShowInInspector, FoldoutGroup("Submodules"), ReadOnly] private RunMapQuerySubmodule mapQuerySm; public event Action OnPhaseChanged; public event Action OnNodeSelected; public event Action OnZoneEntered; public event Action OnCombatRoomCleared; public event Action OnNodeCompleted; public event Action OnRunEnded; protected override void Awake() { base.Awake(); InitializeSubstructures(); } public void InitializeSubstructures() { InitializeSubmodules(); } private void InitializeSubmodules() { phaseSm ??= new RunPhaseSubmodule(this); combatRewardSm ??= new RunCombatRewardSubmodule(this); progressSm ??= new RunProgressSubmodule(this); combatSm ??= new RunCombatSubmodule(this); nodeFlowSm ??= new RunNodeFlowSubmodule(this); mapQuerySm ??= new RunMapQuerySubmodule(this); sessionSm ??= new RunSessionSubmodule(this); } public void StartNewRun() => sessionSm.StartNewRun(); public void ReturnToHub() => sessionSm.ReturnToHub(); public void SelectNode(Vector2Int targetPosition) => nodeFlowSm.SelectNode(targetPosition); public void CompleteCurrentNode() => nodeFlowSm.CompleteCurrentNode(); public void RegisterPendingCombatReward() => combatRewardSm.RegisterPendingCombatReward(); public void RegisterPendingCombatReward(Vector3 spawnPosition) => combatRewardSm.RegisterPendingCombatReward(spawnPosition); public bool TryCompletePendingCombatReward() => combatRewardSm.TryCompletePendingCombatReward(); public void AddCombatRewardModifier(ICombatRewardModifier modifier) => combatRewardSm.AddCombatRewardModifier(modifier); public CombatRewardSession GetActiveCombatRewardSession() => combatRewardSm.GetActiveCombatRewardSession(); public bool HasPendingCombatRewards => combatRewardSm.HasPendingCombatRewards; public bool CanSelectMapNodes => mapQuerySm.CanSelectMapNodes; public bool IsNormalCombatNode(MapNodeType nodeType) => RunNodeTypeUtility.IsNormalCombatNode(nodeType); public bool IsCombatNode(MapNodeType nodeType) => RunNodeTypeUtility.IsCombatNode(nodeType); public HashSet GetSelectablePositions() => mapQuerySm.GetSelectablePositions(); public Dictionary GetAllNodeDisplayStates() => mapQuerySm.GetAllNodeDisplayStates(); public bool IsNodeExhausted(Vector2Int position) => mapQuerySm.IsNodeExhausted(position); public void IncreaseScoutRange(int amount) => mapQuerySm.IncreaseScoutRange(amount); public void RevealNode(Vector2Int position) => mapQuerySm.RevealNode(position); public void RevealNodeType(MapNodeType nodeType) => mapQuerySm.RevealNodeType(nodeType); private void Update() { progressSm.TickElapsedTime(); } internal void RaisePhaseChanged(RunPhase phase) => OnPhaseChanged?.Invoke(phase); internal void RaiseNodeSelected(Vector2Int position) => OnNodeSelected?.Invoke(position); internal void RaiseZoneEntered(ZoneEntryContext context) => OnZoneEntered?.Invoke(context); internal void RaiseCombatRoomCleared(RunMapNode node) => OnCombatRoomCleared?.Invoke(node); internal void RaiseNodeCompleted(RunMapNode node) => OnNodeCompleted?.Invoke(node); internal void RaiseRunEnded(RunState run) => OnRunEnded?.Invoke(run); } public enum RunPhase { Idle, MapSelection, Transitioning, InCombat, InShop, InRest, InMechanical, InBoss, InEvent, Settlement, } }