using System.Collections.Generic;
using Cielonos.MainGame.Map;
using Cielonos.MainGame.UI;
using SLSUtilities.General;
using UnityEngine;
namespace Cielonos.MainGame
{
public partial class RunManager
{
///
/// 管理一局 Run 的创建和销毁。
/// 这里只负责 RunState 初始化、事件订阅入口和返回 Hub 的清理,不处理单个节点完成或奖励结算。
///
public class RunSessionSubmodule : SubmoduleBase
{
public RunSessionSubmodule(RunManager owner) : base(owner)
{
}
public void StartNewRun()
{
if (owner.mapConfig == null)
{
Debug.LogError("[RunManager] mapConfig 未配置,无法开始 Run。");
return;
}
owner.progressSm.UnsubscribePlayerEvents();
owner.combatSm.UnsubscribeRoomEvents();
Randomizer runRng = new Randomizer(MainGameManager.Seed);
RunMapData mapData = MapGenerator.Generate(owner.mapConfig);
if (mapData == null)
{
Debug.LogError("[RunManager] 地图生成失败,无法开始 Run。");
return;
}
owner.currentRun = new RunState
{
randomizer = runRng,
mapData = mapData,
currentPosition = mapData.startPosition,
visitedNodes = new HashSet { mapData.startPosition },
exhaustedNodes = new HashSet(),
completedNodes = new HashSet(),
permanentlyRevealedNodes = new HashSet(),
permanentlyRevealedTypes = new HashSet(),
scoutRange = 1,
elapsedTime = 0f,
roomsCleared = 0,
enemiesDefeated = 0,
hurtCount = 0,
isCompleted = false,
};
owner.combatRewardSm.Clear();
Debug.Log(
$"[RunManager] 新一局开始(Seed: {runRng.Seed}),地图节点数:{mapData.totalNodes}," +
$"起点:{mapData.startPosition},Boss:{mapData.bossPosition}");
PlayerCanvas.MainGamePages.mapPage.Populate(mapData);
owner.progressSm.SubscribePlayerEvents();
owner.combatSm.SubscribeRoomEvents();
LoadStartZone(mapData);
}
public void ReturnToHub()
{
owner.progressSm.UnsubscribePlayerEvents();
owner.combatSm.UnsubscribeRoomEvents();
owner.combatRewardSm.Clear();
owner.currentRun = null;
owner.phaseSm.TransitionToPhase(RunPhase.Idle);
Debug.Log("[RunManager] 已返回 Hub,RunState 已清理。");
}
private void LoadStartZone(RunMapData mapData)
{
RunMapNode startNode = mapData.nodes[mapData.startPosition];
if (startNode.zoneData == null)
{
Debug.LogWarning("[RunManager] 起点节点没有配置 ZoneData,直接进入地图选择。");
owner.phaseSm.TransitionToPhase(RunPhase.MapSelection);
return;
}
owner.phaseSm.TransitionToPhase(RunPhase.Transitioning);
ZoneSetupMode setupMode = RunNodeTypeUtility.ShouldStartBattleSetup(startNode, isCompleted: false)
? ZoneSetupMode.CombatEncounter
: ZoneSetupMode.EnvironmentOnly;
MapManager.Instance.LoadZone(startNode.zoneData, onComplete: () =>
{
owner.phaseSm.TransitionToPhase(RunPhase.MapSelection);
}, setupMode: setupMode);
}
}
}
}