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

150 lines
5.3 KiB
C#
Raw Normal View History

2026-07-18 03:16:20 -04:00
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
{
/// <summary>
/// 驱动整局 Roguelite Run 的会话管理器。
/// 对外保持原有 RunManager API对内将生命周期、节点流程、奖励、统计等职责拆分给 Submodule。
/// </summary>
public partial class RunManager : Singleton<RunManager>, 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<RunPhase> OnPhaseChanged;
public event Action<Vector2Int> OnNodeSelected;
public event Action<ZoneEntryContext> OnZoneEntered;
public event Action<RunMapNode> OnCombatRoomCleared;
public event Action<RunMapNode> OnNodeCompleted;
public event Action<RunState> 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<Vector2Int> GetSelectablePositions() => mapQuerySm.GetSelectablePositions();
public Dictionary<Vector2Int, NodeDisplayState> 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,
}
}