663 lines
26 KiB
C#
663 lines
26 KiB
C#
using System.Text;
|
|
using GameFramework.Event;
|
|
using GameFramework.Fsm;
|
|
using GameFramework.Procedure;
|
|
using GeometryTD.CustomEvent;
|
|
using GeometryTD.Definition;
|
|
using GeometryTD.UI;
|
|
using UnityGameFramework.Runtime;
|
|
|
|
namespace GeometryTD.Procedure
|
|
{
|
|
public enum ProcedureMainFlowPhase
|
|
{
|
|
Hub = 0,
|
|
NodeActive = 1,
|
|
RunCompletedPendingFinish = 2
|
|
}
|
|
|
|
public enum ProcedureMainRunAdvanceResult
|
|
{
|
|
NoChange = 0,
|
|
NodeException = 1,
|
|
AdvancedToNextNode = 2,
|
|
RunCompleted = 3
|
|
}
|
|
|
|
public enum ProcedureMainRunCompletionResult
|
|
{
|
|
NoChange = 0,
|
|
ShowCompletionDialog = 1,
|
|
ReturnToMenu = 2
|
|
}
|
|
|
|
public enum ProcedureMainCombatEntryBlockReason
|
|
{
|
|
None = 0,
|
|
InventoryUnavailable = 1,
|
|
NoValidParticipantTower = 2
|
|
}
|
|
|
|
public sealed class ProcedureMainCombatEntryValidationResult
|
|
{
|
|
public bool CanEnterCombat => BlockReason == ProcedureMainCombatEntryBlockReason.None;
|
|
|
|
public ProcedureMainCombatEntryBlockReason BlockReason { get; set; }
|
|
|
|
public CombatParticipantTowerValidationSummary ValidationSummary { get; set; }
|
|
}
|
|
|
|
public static class ProcedureMainRunFlowService
|
|
{
|
|
public static ProcedureMainRunAdvanceResult TryAdvanceRun(
|
|
RunState runState,
|
|
RunNodeCompletionStatus completionStatus,
|
|
BackpackInventoryData snapshot)
|
|
{
|
|
if (!RunStateAdvanceService.TryCompleteCurrentNode(runState, completionStatus, snapshot))
|
|
{
|
|
return ProcedureMainRunAdvanceResult.NoChange;
|
|
}
|
|
|
|
if (runState != null && runState.IsCompleted)
|
|
{
|
|
return ProcedureMainRunAdvanceResult.RunCompleted;
|
|
}
|
|
|
|
return completionStatus == RunNodeCompletionStatus.Exception
|
|
? ProcedureMainRunAdvanceResult.NodeException
|
|
: ProcedureMainRunAdvanceResult.AdvancedToNextNode;
|
|
}
|
|
}
|
|
|
|
public static class ProcedureMainRunCompletionService
|
|
{
|
|
public static ProcedureMainRunCompletionResult TryEnterCompletedPendingFinish(bool isCompletionDialogShown)
|
|
{
|
|
return isCompletionDialogShown
|
|
? ProcedureMainRunCompletionResult.NoChange
|
|
: ProcedureMainRunCompletionResult.ShowCompletionDialog;
|
|
}
|
|
|
|
public static ProcedureMainRunCompletionResult TryConfirmReturnToMenu(
|
|
ProcedureMainFlowPhase flowPhase,
|
|
bool isReturnToMenuPending)
|
|
{
|
|
if (flowPhase != ProcedureMainFlowPhase.RunCompletedPendingFinish || isReturnToMenuPending)
|
|
{
|
|
return ProcedureMainRunCompletionResult.NoChange;
|
|
}
|
|
|
|
return ProcedureMainRunCompletionResult.ReturnToMenu;
|
|
}
|
|
}
|
|
|
|
public static class ProcedureMainNodeEventGuardService
|
|
{
|
|
public static bool MatchesCurrentNode(
|
|
RunState runState,
|
|
int nodeId,
|
|
RunNodeType nodeType,
|
|
int sequenceIndex)
|
|
{
|
|
RunNodeState currentNode = runState?.CurrentNode;
|
|
if (currentNode == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return (nodeId <= 0 || nodeId == currentNode.NodeId) &&
|
|
(nodeType == RunNodeType.None || nodeType == currentNode.NodeType) &&
|
|
(sequenceIndex < 0 || sequenceIndex == currentNode.SequenceIndex);
|
|
}
|
|
}
|
|
|
|
public static class ProcedureMainCombatEntryValidationService
|
|
{
|
|
public static ProcedureMainCombatEntryValidationResult Validate(BackpackInventoryData inventory)
|
|
{
|
|
if (inventory == null)
|
|
{
|
|
return new ProcedureMainCombatEntryValidationResult
|
|
{
|
|
BlockReason = ProcedureMainCombatEntryBlockReason.InventoryUnavailable,
|
|
ValidationSummary = new CombatParticipantTowerValidationSummary()
|
|
};
|
|
}
|
|
|
|
CombatParticipantTowerValidationSummary summary =
|
|
CombatParticipantTowerValidationService.ValidateParticipantTowers(inventory);
|
|
|
|
return new ProcedureMainCombatEntryValidationResult
|
|
{
|
|
BlockReason = summary.HasAnyValidParticipantTower
|
|
? ProcedureMainCombatEntryBlockReason.None
|
|
: ProcedureMainCombatEntryBlockReason.NoValidParticipantTower,
|
|
ValidationSummary = summary
|
|
};
|
|
}
|
|
|
|
public static string BuildInvalidParticipantTowerLog(
|
|
CombatParticipantTowerValidationSummary summary)
|
|
{
|
|
if (summary?.InvalidResults == null || summary.InvalidResults.Count <= 0)
|
|
{
|
|
return "none";
|
|
}
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
for (int i = 0; i < summary.InvalidResults.Count; i++)
|
|
{
|
|
CombatParticipantTowerValidationResult result = summary.InvalidResults[i];
|
|
if (result == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (builder.Length > 0)
|
|
{
|
|
builder.Append(", ");
|
|
}
|
|
|
|
builder.Append('#');
|
|
builder.Append(result.TowerInstanceId);
|
|
builder.Append(':');
|
|
builder.Append(result.FailureReason);
|
|
}
|
|
|
|
return builder.Length > 0 ? builder.ToString() : "none";
|
|
}
|
|
|
|
public static DialogFormRawData BuildBlockedCombatDialogRawData(
|
|
ProcedureMainCombatEntryValidationResult validationResult)
|
|
{
|
|
return new DialogFormRawData
|
|
{
|
|
Mode = 1,
|
|
Title = "无法进入战斗",
|
|
Message = BuildBlockedCombatDialogMessage(validationResult),
|
|
PauseGame = false,
|
|
ConfirmText = "知道了"
|
|
};
|
|
}
|
|
|
|
private static string BuildBlockedCombatDialogMessage(
|
|
ProcedureMainCombatEntryValidationResult validationResult)
|
|
{
|
|
if (validationResult == null)
|
|
{
|
|
return "当前无法确认出战信息,请稍后重试。";
|
|
}
|
|
|
|
switch (validationResult.BlockReason)
|
|
{
|
|
case ProcedureMainCombatEntryBlockReason.InventoryUnavailable:
|
|
return "当前无法读取库存快照,暂时不能进入战斗。请重新进入本轮流程后再试。";
|
|
case ProcedureMainCombatEntryBlockReason.NoValidParticipantTower:
|
|
return BuildNoValidParticipantTowerMessage(validationResult.ValidationSummary);
|
|
default:
|
|
return "当前出战校验未通过,暂时不能进入战斗。";
|
|
}
|
|
}
|
|
|
|
private static string BuildNoValidParticipantTowerMessage(
|
|
CombatParticipantTowerValidationSummary summary)
|
|
{
|
|
if (summary?.InvalidResults == null || summary.InvalidResults.Count <= 0)
|
|
{
|
|
return "参战区至少需要 1 座完整装配了枪口、轴承、底座的塔,才能进入战斗。";
|
|
}
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
builder.Append("参战区没有可出战的完整塔。");
|
|
for (int i = 0; i < summary.InvalidResults.Count; i++)
|
|
{
|
|
CombatParticipantTowerValidationResult result = summary.InvalidResults[i];
|
|
if (result == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
builder.Append('\n');
|
|
builder.Append("塔 #");
|
|
builder.Append(result.TowerInstanceId);
|
|
builder.Append(' ');
|
|
builder.Append(GetFailureReasonMessage(result.FailureReason));
|
|
}
|
|
|
|
return builder.ToString();
|
|
}
|
|
|
|
private static string GetFailureReasonMessage(CombatParticipantTowerValidationFailureReason failureReason)
|
|
{
|
|
switch (failureReason)
|
|
{
|
|
case CombatParticipantTowerValidationFailureReason.TowerMissing:
|
|
return "已不存在,无法参战。";
|
|
case CombatParticipantTowerValidationFailureReason.MissingMuzzleComponent:
|
|
return "缺少枪口组件。";
|
|
case CombatParticipantTowerValidationFailureReason.MissingBearingComponent:
|
|
return "缺少轴承组件。";
|
|
case CombatParticipantTowerValidationFailureReason.MissingBaseComponent:
|
|
return "缺少底座组件。";
|
|
default:
|
|
return "不满足当前参战条件。";
|
|
}
|
|
}
|
|
}
|
|
|
|
public class ProcedureMain : ProcedureBase
|
|
{
|
|
public override bool UseNativeDialog => false;
|
|
|
|
private RepoFormUseCase _repoFormUseCase;
|
|
private NodeMapFormUseCase _nodeMapFormUseCase;
|
|
private RunState _currentRunState;
|
|
private ProcedureMainFlowPhase _flowPhase = ProcedureMainFlowPhase.Hub;
|
|
private bool _isRunCompleteDialogShown;
|
|
private bool _isReturnToMenuPending;
|
|
|
|
#region FSM
|
|
|
|
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
|
|
{
|
|
base.OnEnter(procedureOwner);
|
|
|
|
GameEntry.Event.Subscribe(NodeCompleteEventArgs.EventId, OnNodeComplete);
|
|
GameEntry.Event.Subscribe(NodeEnterEventArgs.EventId, OnNodeEnter);
|
|
GameEntry.Event.Subscribe(NodeMapNodeEnterRequestedEventArgs.EventId, OnNodeMapNodeEnterRequested);
|
|
|
|
GameEntry.EventNode.OnInit();
|
|
GameEntry.CombatNode.OnInit(LevelThemeType.Plain);
|
|
GameEntry.ShopNode.OnInit();
|
|
GameEntry.PlayerInventory?.OnInit();
|
|
|
|
_currentRunState = RunStateFactory.CreateFixedRun(
|
|
LevelThemeType.Plain,
|
|
GameEntry.PlayerInventory != null
|
|
? GameEntry.PlayerInventory.GetInventorySnapshot()
|
|
: null);
|
|
|
|
_repoFormUseCase = new RepoFormUseCase();
|
|
GameEntry.UIRouter.BindUIUseCase(UIFormType.RepoForm, _repoFormUseCase);
|
|
|
|
_nodeMapFormUseCase = new NodeMapFormUseCase();
|
|
_nodeMapFormUseCase.SetRunState(_currentRunState);
|
|
GameEntry.UIRouter.BindUIUseCase(UIFormType.NodeMapForm, _nodeMapFormUseCase);
|
|
_isRunCompleteDialogShown = false;
|
|
_isReturnToMenuPending = false;
|
|
|
|
EnterHubFlow();
|
|
}
|
|
|
|
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds,
|
|
float realElapseSeconds)
|
|
{
|
|
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
|
|
|
|
if (_isReturnToMenuPending)
|
|
{
|
|
_isReturnToMenuPending = false;
|
|
procedureOwner.SetData<VarInt32>("NextSceneId", (int)SceneType.Menu);
|
|
ChangeState<ProcedureChangeScene>(procedureOwner);
|
|
return;
|
|
}
|
|
|
|
GameEntry.CombatNode.OnUpdate(elapseSeconds, realElapseSeconds);
|
|
}
|
|
|
|
protected override void OnLeave(IFsm<IProcedureManager> procedureOwner, bool isShutdown)
|
|
{
|
|
GameEntry.CombatNode.OnShutdown();
|
|
GameEntry.Event.Unsubscribe(NodeMapNodeEnterRequestedEventArgs.EventId, OnNodeMapNodeEnterRequested);
|
|
GameEntry.Event.Unsubscribe(NodeEnterEventArgs.EventId, OnNodeEnter);
|
|
GameEntry.Event.Unsubscribe(NodeCompleteEventArgs.EventId, OnNodeComplete);
|
|
GameEntry.UIRouter.CloseUI(UIFormType.RepoForm);
|
|
GameEntry.UIRouter.CloseUI(UIFormType.NodeMapForm);
|
|
GameEntry.UIRouter.CloseUI(UIFormType.MainForm);
|
|
GameEntry.UIRouter.CloseUI(UIFormType.DialogForm);
|
|
_repoFormUseCase = null;
|
|
_nodeMapFormUseCase = null;
|
|
_currentRunState = null;
|
|
_flowPhase = ProcedureMainFlowPhase.Hub;
|
|
_isRunCompleteDialogShown = false;
|
|
_isReturnToMenuPending = false;
|
|
|
|
base.OnLeave(procedureOwner, isShutdown);
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
private void OnNodeEnter(object sender, GameEventArgs e)
|
|
{
|
|
if (!(e is NodeEnterEventArgs args))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(args.RunId) &&
|
|
_currentRunState != null &&
|
|
!string.Equals(args.RunId, _currentRunState.RunId))
|
|
{
|
|
Log.Warning(
|
|
"ProcedureMain.OnNodeEnter() ignored. EventRunId={0}, CurrentRunId={1}.",
|
|
args.RunId,
|
|
_currentRunState.RunId);
|
|
return;
|
|
}
|
|
|
|
RunNodeState currentNode = _currentRunState?.CurrentNode;
|
|
if (!ProcedureMainNodeEventGuardService.MatchesCurrentNode(
|
|
_currentRunState,
|
|
args.NodeId,
|
|
args.NodeType,
|
|
args.SequenceIndex))
|
|
{
|
|
Log.Warning(
|
|
"ProcedureMain.OnNodeEnter() node mismatch. EventNodeId={0}, EventNodeType={1}, EventSequenceIndex={2}; CurrentNodeId={3}, CurrentNodeType={4}, CurrentSequenceIndex={5}.",
|
|
args.NodeId,
|
|
args.NodeType,
|
|
args.SequenceIndex,
|
|
currentNode?.NodeId ?? 0,
|
|
currentNode?.NodeType ?? RunNodeType.None,
|
|
currentNode?.SequenceIndex ?? -1);
|
|
return;
|
|
}
|
|
|
|
Log.Info(
|
|
"ProcedureMain.OnNodeEnter() accepted. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}.",
|
|
string.IsNullOrWhiteSpace(args.RunId) ? _currentRunState?.RunId : args.RunId,
|
|
args.NodeId,
|
|
args.NodeType,
|
|
args.SequenceIndex);
|
|
|
|
EnterNodeFlow();
|
|
}
|
|
|
|
private void OnNodeComplete(object sender, GameEventArgs e)
|
|
{
|
|
if (!(e is NodeCompleteEventArgs args))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(args.RunId) &&
|
|
_currentRunState != null &&
|
|
!string.Equals(args.RunId, _currentRunState.RunId))
|
|
{
|
|
Log.Warning(
|
|
"ProcedureMain.OnNodeComplete() ignored. EventRunId={0}, CurrentRunId={1}.",
|
|
args.RunId,
|
|
_currentRunState.RunId);
|
|
return;
|
|
}
|
|
|
|
RunNodeState currentNode = _currentRunState?.CurrentNode;
|
|
if (!ProcedureMainNodeEventGuardService.MatchesCurrentNode(
|
|
_currentRunState,
|
|
args.NodeId,
|
|
args.NodeType,
|
|
args.SequenceIndex))
|
|
{
|
|
Log.Warning(
|
|
"ProcedureMain.OnNodeComplete() node mismatch. EventNodeId={0}, EventNodeType={1}, EventSequenceIndex={2}; CurrentNodeId={3}, CurrentNodeType={4}, CurrentSequenceIndex={5}.",
|
|
args.NodeId,
|
|
args.NodeType,
|
|
args.SequenceIndex,
|
|
currentNode?.NodeId ?? 0,
|
|
currentNode?.NodeType ?? RunNodeType.None,
|
|
currentNode?.SequenceIndex ?? -1);
|
|
return;
|
|
}
|
|
|
|
Log.Info(
|
|
"ProcedureMain.OnNodeComplete() accepted. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}, CompletionStatus={4}, CombatWon={5}.",
|
|
string.IsNullOrWhiteSpace(args.RunId) ? _currentRunState?.RunId : args.RunId,
|
|
args.NodeId,
|
|
args.NodeType,
|
|
args.SequenceIndex,
|
|
args.CompletionStatus,
|
|
args.CombatWon);
|
|
|
|
BackpackInventoryData snapshot = args.InventorySnapshotAfterNode;
|
|
if (snapshot == null && GameEntry.PlayerInventory != null)
|
|
{
|
|
snapshot = GameEntry.PlayerInventory.GetInventorySnapshot();
|
|
}
|
|
|
|
HandleRunAdvanceResult(
|
|
ProcedureMainRunFlowService.TryAdvanceRun(_currentRunState, args.CompletionStatus, snapshot));
|
|
}
|
|
|
|
private void OnNodeMapNodeEnterRequested(object sender, GameEventArgs e)
|
|
{
|
|
if (!(sender is NodeMapForm) || !(e is NodeMapNodeEnterRequestedEventArgs args))
|
|
{
|
|
return;
|
|
}
|
|
|
|
RunNodeState currentNode = _currentRunState?.CurrentNode;
|
|
if (_currentRunState == null ||
|
|
_flowPhase != ProcedureMainFlowPhase.Hub ||
|
|
!_currentRunState.CanEnterCurrentNode ||
|
|
currentNode == null)
|
|
{
|
|
Log.Warning(
|
|
"ProcedureMain.OnNodeMapNodeEnterRequested() ignored. FlowPhase={0}, HasEnterableNode={1}.",
|
|
_flowPhase,
|
|
_currentRunState != null && _currentRunState.CanEnterCurrentNode);
|
|
return;
|
|
}
|
|
|
|
if (args.SequenceIndex != currentNode.SequenceIndex || args.NodeType != currentNode.NodeType)
|
|
{
|
|
Log.Warning(
|
|
"ProcedureMain.OnNodeMapNodeEnterRequested() ignored. Requested={0}#{1}, CurrentNode={2}#{3}.",
|
|
args.NodeType,
|
|
args.SequenceIndex,
|
|
currentNode.NodeType,
|
|
currentNode.SequenceIndex);
|
|
return;
|
|
}
|
|
|
|
switch (currentNode.NodeType)
|
|
{
|
|
case RunNodeType.Combat:
|
|
case RunNodeType.BossCombat:
|
|
ProcedureMainCombatEntryValidationResult validationResult =
|
|
ProcedureMainCombatEntryValidationService.Validate(
|
|
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null);
|
|
if (!validationResult.CanEnterCombat)
|
|
{
|
|
LogCombatEntryBlocked(currentNode, validationResult);
|
|
OpenBlockedCombatDialog(validationResult);
|
|
return;
|
|
}
|
|
|
|
GameEntry.CombatNode.StartCombat(
|
|
currentNode.LinkedLevelId,
|
|
_currentRunState.RunId,
|
|
currentNode.NodeId,
|
|
currentNode.NodeType,
|
|
currentNode.SequenceIndex);
|
|
return;
|
|
case RunNodeType.Event:
|
|
GameEntry.EventNode.StartEvent(
|
|
_currentRunState.RunId,
|
|
currentNode.NodeId,
|
|
currentNode.NodeType,
|
|
currentNode.SequenceIndex);
|
|
return;
|
|
case RunNodeType.Shop:
|
|
GameEntry.ShopNode.StartShop(
|
|
_currentRunState.RunId,
|
|
currentNode.NodeId,
|
|
currentNode.NodeType,
|
|
currentNode.SequenceIndex);
|
|
return;
|
|
default:
|
|
Log.Warning("ProcedureMain.OnNodeMapNodeEnterRequested() encountered unsupported node type: {0}.",
|
|
currentNode.NodeType);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void OpenBlockedCombatDialog(ProcedureMainCombatEntryValidationResult validationResult)
|
|
{
|
|
GameEntry.UIRouter.CloseUI(UIFormType.DialogForm);
|
|
GameEntry.UIRouter.OpenUI(
|
|
UIFormType.DialogForm,
|
|
ProcedureMainCombatEntryValidationService.BuildBlockedCombatDialogRawData(validationResult));
|
|
}
|
|
|
|
private void LogCombatEntryBlocked(
|
|
RunNodeState currentNode,
|
|
ProcedureMainCombatEntryValidationResult validationResult)
|
|
{
|
|
switch (validationResult?.BlockReason)
|
|
{
|
|
case ProcedureMainCombatEntryBlockReason.InventoryUnavailable:
|
|
Log.Warning(
|
|
"ProcedureMain blocked combat start. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}, Reason={4}.",
|
|
_currentRunState?.RunId,
|
|
currentNode?.NodeId ?? 0,
|
|
currentNode?.NodeType ?? RunNodeType.None,
|
|
currentNode?.SequenceIndex ?? -1,
|
|
ProcedureMainCombatEntryBlockReason.InventoryUnavailable);
|
|
return;
|
|
case ProcedureMainCombatEntryBlockReason.NoValidParticipantTower:
|
|
Log.Warning(
|
|
"ProcedureMain blocked combat start. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}, Reason={4}, InvalidParticipantTowers={5}.",
|
|
_currentRunState?.RunId,
|
|
currentNode?.NodeId ?? 0,
|
|
currentNode?.NodeType ?? RunNodeType.None,
|
|
currentNode?.SequenceIndex ?? -1,
|
|
ProcedureMainCombatEntryBlockReason.NoValidParticipantTower,
|
|
ProcedureMainCombatEntryValidationService.BuildInvalidParticipantTowerLog(
|
|
validationResult.ValidationSummary));
|
|
return;
|
|
default:
|
|
Log.Warning(
|
|
"ProcedureMain blocked combat start. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}, Reason=Unknown.",
|
|
_currentRunState?.RunId,
|
|
currentNode?.NodeId ?? 0,
|
|
currentNode?.NodeType ?? RunNodeType.None,
|
|
currentNode?.SequenceIndex ?? -1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void HandleRunAdvanceResult(ProcedureMainRunAdvanceResult result)
|
|
{
|
|
switch (result)
|
|
{
|
|
case ProcedureMainRunAdvanceResult.NoChange:
|
|
return;
|
|
case ProcedureMainRunAdvanceResult.NodeException:
|
|
Log.Info(
|
|
"ProcedureMain current node entered exception state. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}.",
|
|
_currentRunState?.RunId,
|
|
_currentRunState?.CurrentNode?.NodeId ?? 0,
|
|
_currentRunState?.CurrentNode?.NodeType ?? RunNodeType.None,
|
|
_currentRunState?.CurrentNode?.SequenceIndex ?? -1);
|
|
EnterHubFlow();
|
|
return;
|
|
case ProcedureMainRunAdvanceResult.AdvancedToNextNode:
|
|
LogNextNode();
|
|
EnterHubFlow();
|
|
return;
|
|
case ProcedureMainRunAdvanceResult.RunCompleted:
|
|
EnterRunCompletedPendingFinish();
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void EnterHubFlow()
|
|
{
|
|
_flowPhase = ProcedureMainFlowPhase.Hub;
|
|
_nodeMapFormUseCase?.SetRunState(_currentRunState);
|
|
GameEntry.UIRouter.OpenUI(UIFormType.NodeMapForm);
|
|
GameEntry.UIRouter.OpenUI(UIFormType.MainForm);
|
|
}
|
|
|
|
private void EnterNodeFlow()
|
|
{
|
|
_flowPhase = ProcedureMainFlowPhase.NodeActive;
|
|
CloseHubUI();
|
|
}
|
|
|
|
private void EnterRunCompletedPendingFinish()
|
|
{
|
|
_flowPhase = ProcedureMainFlowPhase.RunCompletedPendingFinish;
|
|
_nodeMapFormUseCase?.SetRunState(_currentRunState);
|
|
CloseHubUI();
|
|
Log.Info("ProcedureMain run completed. RunId={0}", _currentRunState?.RunId);
|
|
|
|
ProcedureMainRunCompletionResult result =
|
|
ProcedureMainRunCompletionService.TryEnterCompletedPendingFinish(_isRunCompleteDialogShown);
|
|
if (result == ProcedureMainRunCompletionResult.ShowCompletionDialog)
|
|
{
|
|
_isRunCompleteDialogShown = true;
|
|
OpenRunCompleteDialog();
|
|
}
|
|
}
|
|
|
|
private void CloseHubUI()
|
|
{
|
|
GameEntry.UIRouter.CloseUI(UIFormType.NodeMapForm);
|
|
GameEntry.UIRouter.CloseUI(UIFormType.MainForm);
|
|
}
|
|
|
|
private void LogNextNode()
|
|
{
|
|
RunNodeState nextNode = _currentRunState?.CurrentNode;
|
|
if (nextNode == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log.Info(
|
|
"ProcedureMain advanced run. RunId={0}, NextNodeType={1}, SequenceIndex={2}, LevelId={3}.",
|
|
_currentRunState.RunId,
|
|
nextNode.NodeType,
|
|
nextNode.SequenceIndex,
|
|
nextNode.LinkedLevelId);
|
|
}
|
|
|
|
private void OpenRunCompleteDialog()
|
|
{
|
|
GameEntry.UIRouter.OpenUI(UIFormType.DialogForm, new DialogFormRawData
|
|
{
|
|
Mode = 1,
|
|
Title = "Run Complete",
|
|
Message = "Boss node completed. This run is finished and will return to the main menu.",
|
|
PauseGame = false,
|
|
ConfirmText = "Return to Menu",
|
|
OnClickConfirm = OnRunCompleteDialogConfirmed
|
|
});
|
|
}
|
|
|
|
private void OnRunCompleteDialogConfirmed(object userData)
|
|
{
|
|
_ = userData;
|
|
|
|
ProcedureMainRunCompletionResult result = ProcedureMainRunCompletionService.TryConfirmReturnToMenu(
|
|
_flowPhase,
|
|
_isReturnToMenuPending);
|
|
if (result != ProcedureMainRunCompletionResult.ReturnToMenu)
|
|
{
|
|
Log.Warning(
|
|
"ProcedureMain ignored run completion confirm. FlowPhase={0}, ReturnPending={1}.",
|
|
_flowPhase,
|
|
_isReturnToMenuPending);
|
|
return;
|
|
}
|
|
|
|
_isReturnToMenuPending = true;
|
|
}
|
|
}
|
|
}
|