补全 S1 测试
- 调整 CombatNode 正常结束与异常的变量语义,现在是 DidCombatWin 与 Exception - 补充测试样例 - 完成 S1 目标
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
"name": "GeometryTD.Runtime",
|
||||
"rootNamespace": "GeometryTD",
|
||||
"references": [
|
||||
"UnityGameFramework.Editor",
|
||||
"UnityGameFramework.Runtime",
|
||||
"Unity.InputSystem",
|
||||
"Unity.TextMeshPro"
|
||||
@@ -15,4 +16,4 @@
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -91,7 +91,7 @@ namespace GeometryTD.CustomComponent
|
||||
_runtime.EnemyManager.EndPhase();
|
||||
_runtime.EnemyManager.ResetCombatStats();
|
||||
_coordinator.ResetRuntime();
|
||||
_runtime.IsFinishAsVictory = true;
|
||||
_runtime.DidCombatWin = true;
|
||||
|
||||
_runtime.CurrentLevel = level;
|
||||
_runtime.RunId = runId;
|
||||
|
||||
+19
-9
@@ -53,7 +53,7 @@ namespace GeometryTD.CustomComponent
|
||||
_runtime.EnemyDropResolver.Reset();
|
||||
_runtime.SettlementContext = null;
|
||||
_runtime.CurrentLevel = null;
|
||||
_runtime.IsFinishAsVictory = true;
|
||||
_runtime.DidCombatWin = true;
|
||||
_runtime.IsCompleted = false;
|
||||
_runtime.NodeEnterFired = false;
|
||||
_runtime.RunId = null;
|
||||
@@ -124,21 +124,21 @@ namespace GeometryTD.CustomComponent
|
||||
TryBeginNextPhase();
|
||||
}
|
||||
|
||||
public bool ShouldEnterSettlementFromActiveState(out bool isVictory)
|
||||
public bool ShouldEnterSettlementFromActiveState(out bool didCombatWin)
|
||||
{
|
||||
if (GetCurrentBaseHp() <= 0)
|
||||
{
|
||||
isVictory = false;
|
||||
didCombatWin = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_runtime.PhaseLoopRuntime.IsEndCombatRequested)
|
||||
{
|
||||
isVictory = true;
|
||||
didCombatWin = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
isVictory = true;
|
||||
didCombatWin = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -198,9 +198,9 @@ namespace GeometryTD.CustomComponent
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.DialogForm);
|
||||
}
|
||||
|
||||
public void CompleteNormalCombatAndNotify(bool succeeded)
|
||||
public void CompleteNormalCombatAndNotify(bool didCombatWin)
|
||||
{
|
||||
CompleteCombat(succeeded);
|
||||
CompleteCombat(didCombatWin);
|
||||
GameEntry.Event.Fire(
|
||||
this,
|
||||
NodeCompleteEventArgs.Create(
|
||||
@@ -208,7 +208,8 @@ namespace GeometryTD.CustomComponent
|
||||
_runtime.NodeId,
|
||||
_runtime.NodeType,
|
||||
_runtime.SequenceIndex,
|
||||
succeeded,
|
||||
RunNodeCompletionStatus.Completed,
|
||||
didCombatWin,
|
||||
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||
}
|
||||
|
||||
@@ -219,7 +220,16 @@ namespace GeometryTD.CustomComponent
|
||||
CloseRewardSelectForm();
|
||||
CloseDialogForm();
|
||||
CompleteCombat(false);
|
||||
GameEntry.Event.Fire(this, CombatFailureReturnEventArgs.Create());
|
||||
GameEntry.Event.Fire(
|
||||
this,
|
||||
NodeCompleteEventArgs.Create(
|
||||
_runtime.RunId,
|
||||
_runtime.NodeId,
|
||||
_runtime.NodeType,
|
||||
_runtime.SequenceIndex,
|
||||
RunNodeCompletionStatus.Exception,
|
||||
false,
|
||||
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||
}
|
||||
|
||||
public bool HandleStartFailure(string errorMessage)
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ namespace GeometryTD.CustomComponent
|
||||
public RewardSelectFormUseCase RewardSelectFormUseCase { get; set; }
|
||||
public CombatStateBase CurrentState { get; set; }
|
||||
public Action<bool> CombatEndedCallback { get; set; }
|
||||
public bool IsFinishAsVictory { get; set; } = true;
|
||||
public bool DidCombatWin { get; set; } = true;
|
||||
public bool IsCompleted { get; set; }
|
||||
public bool NodeEnterFired { get; set; }
|
||||
public CombatSettlementContext SettlementContext { get; set; }
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ namespace GeometryTD.CustomComponent
|
||||
|
||||
internal sealed class CombatSettlementResult
|
||||
{
|
||||
public bool IsVictory;
|
||||
public bool DidCombatWin;
|
||||
public int FinalCoin;
|
||||
public int FinalBaseHp;
|
||||
public int MaxBaseHp;
|
||||
|
||||
+5
-5
@@ -18,14 +18,14 @@ namespace GeometryTD.CustomComponent
|
||||
private const float LowBaseHpTowerEndurancePenalty = 10f;
|
||||
|
||||
public CombatSettlementContext BuildSettlementContext(
|
||||
bool isVictory,
|
||||
bool didCombatWin,
|
||||
DRLevel currentLevel,
|
||||
int defeatedEnemyCount,
|
||||
CombatRunResourceStore resourceStore)
|
||||
{
|
||||
bool shouldOpenFullBaseHpRewardSelect = false;
|
||||
ResolveSettlementByBaseHp(
|
||||
isVictory,
|
||||
didCombatWin,
|
||||
currentLevel,
|
||||
resourceStore,
|
||||
out int currentBaseHp,
|
||||
@@ -39,7 +39,7 @@ namespace GeometryTD.CustomComponent
|
||||
CombatSettlementContext settlementContext = new CombatSettlementContext
|
||||
{
|
||||
};
|
||||
settlementContext.Result.IsVictory = isVictory;
|
||||
settlementContext.Result.DidCombatWin = didCombatWin;
|
||||
settlementContext.Result.FinalCoin = Mathf.Max(0, resourceStore != null ? resourceStore.CurrentCoin : 0);
|
||||
settlementContext.Result.FinalBaseHp = currentBaseHp;
|
||||
settlementContext.Result.MaxBaseHp = maxBaseHp;
|
||||
@@ -173,7 +173,7 @@ namespace GeometryTD.CustomComponent
|
||||
}
|
||||
|
||||
private static void ResolveSettlementByBaseHp(
|
||||
bool isVictory,
|
||||
bool didCombatWin,
|
||||
DRLevel currentLevel,
|
||||
CombatRunResourceStore resourceStore,
|
||||
out int currentBaseHp,
|
||||
@@ -197,7 +197,7 @@ namespace GeometryTD.CustomComponent
|
||||
appliedLowBaseHpPenalty = false;
|
||||
shouldOpenFullBaseHpRewardSelect = false;
|
||||
|
||||
if (!isVictory || resourceStore == null)
|
||||
if (!didCombatWin || resourceStore == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-2
@@ -66,9 +66,9 @@ namespace GeometryTD.CustomComponent
|
||||
Runtime.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
Runtime.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
|
||||
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool isVictory))
|
||||
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool didCombatWin))
|
||||
{
|
||||
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, isVictory));
|
||||
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, didCombatWin));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -2,23 +2,23 @@ namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class CombatSettlementState : CombatStateBase
|
||||
{
|
||||
private readonly bool _isVictory;
|
||||
private readonly bool _didCombatWin;
|
||||
|
||||
public CombatSettlementState(
|
||||
CombatSchedulerRuntime runtime,
|
||||
CombatSchedulerCoordinator coordinator,
|
||||
bool isVictory) : base(runtime, coordinator)
|
||||
bool didCombatWin) : base(runtime, coordinator)
|
||||
{
|
||||
_isVictory = isVictory;
|
||||
_didCombatWin = didCombatWin;
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
Runtime.EnemyManager.EndPhase();
|
||||
Runtime.EnemyManager.CleanupTrackedEnemies();
|
||||
Runtime.IsFinishAsVictory = _isVictory;
|
||||
Runtime.DidCombatWin = _didCombatWin;
|
||||
Runtime.SettlementContext = Runtime.CombatSettlementService.BuildSettlementContext(
|
||||
_isVictory,
|
||||
_didCombatWin,
|
||||
Runtime.CurrentLevel,
|
||||
Runtime.EnemyManager.DefeatedEnemyCount,
|
||||
Runtime.CombatRunResourceStore);
|
||||
|
||||
+2
-2
@@ -22,9 +22,9 @@ namespace GeometryTD.CustomComponent
|
||||
|
||||
Runtime.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
|
||||
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool isVictory))
|
||||
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool didCombatWin))
|
||||
{
|
||||
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, isVictory));
|
||||
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, didCombatWin));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ namespace GeometryTD.CustomComponent
|
||||
Runtime.LoadSession.Cleanup();
|
||||
Coordinator.CloseCombatFinishForm();
|
||||
Coordinator.CloseRewardSelectForm();
|
||||
Coordinator.CompleteNormalCombatAndNotify(Runtime.IsFinishAsVictory);
|
||||
Coordinator.CompleteNormalCombatAndNotify(Runtime.DidCombatWin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ namespace GeometryTD.CustomComponent
|
||||
_activeNodeId,
|
||||
_activeNodeType,
|
||||
_activeSequenceIndex,
|
||||
RunNodeCompletionStatus.Completed,
|
||||
true,
|
||||
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||
ClearActiveNodeContext();
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace GeometryTD.CustomComponent
|
||||
_activeNodeId,
|
||||
_activeNodeType,
|
||||
_activeSequenceIndex,
|
||||
RunNodeCompletionStatus.Completed,
|
||||
true,
|
||||
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||
ClearActiveNodeContext();
|
||||
|
||||
@@ -114,12 +114,10 @@ namespace GeometryTD.Entity
|
||||
{
|
||||
GameEntry.HPBar?.ShowHPBar(this, (float)previousHealth / _maxHealth,
|
||||
(float)_currentHealth / _maxHealth);
|
||||
Log.Info($"ShowBar: {_currentHealth}/{_maxHealth}");
|
||||
}
|
||||
|
||||
if (_currentHealth <= 0)
|
||||
{
|
||||
Log.Info("Enemy Dead");
|
||||
_killedEnemyEntityIds.Add(Id);
|
||||
RequestDespawn();
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using GameFramework;
|
||||
using GameFramework.Event;
|
||||
|
||||
namespace GeometryTD.CustomEvent
|
||||
{
|
||||
public class CombatFailureReturnEventArgs : GameEventArgs
|
||||
{
|
||||
public static int EventId => typeof(CombatFailureReturnEventArgs).GetHashCode();
|
||||
|
||||
public override int Id => EventId;
|
||||
|
||||
public static CombatFailureReturnEventArgs Create()
|
||||
{
|
||||
return ReferencePool.Acquire<CombatFailureReturnEventArgs>();
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7db1bf4f6f5f435d8d3086510e178d1d
|
||||
timeCreated: 1772863200
|
||||
@@ -20,7 +20,9 @@ namespace GeometryTD.CustomEvent
|
||||
|
||||
public int SequenceIndex { get; private set; }
|
||||
|
||||
public bool Succeeded { get; private set; }
|
||||
public RunNodeCompletionStatus CompletionStatus { get; private set; }
|
||||
|
||||
public bool CombatWon { get; private set; }
|
||||
|
||||
public BackpackInventoryData InventorySnapshotAfterNode { get; private set; }
|
||||
|
||||
@@ -30,7 +32,7 @@ namespace GeometryTD.CustomEvent
|
||||
|
||||
public static NodeCompleteEventArgs Create()
|
||||
{
|
||||
return Create(null, 0, RunNodeType.None, -1, true, null);
|
||||
return Create(null, 0, RunNodeType.None, -1, RunNodeCompletionStatus.Completed, true, null);
|
||||
}
|
||||
|
||||
public static NodeCompleteEventArgs Create(
|
||||
@@ -38,7 +40,8 @@ namespace GeometryTD.CustomEvent
|
||||
int nodeId,
|
||||
RunNodeType nodeType,
|
||||
int sequenceIndex,
|
||||
bool succeeded,
|
||||
RunNodeCompletionStatus completionStatus,
|
||||
bool combatWon,
|
||||
BackpackInventoryData inventorySnapshotAfterNode)
|
||||
{
|
||||
var args = ReferencePool.Acquire<NodeCompleteEventArgs>();
|
||||
@@ -46,7 +49,8 @@ namespace GeometryTD.CustomEvent
|
||||
args.NodeId = nodeId;
|
||||
args.NodeType = nodeType;
|
||||
args.SequenceIndex = sequenceIndex;
|
||||
args.Succeeded = succeeded;
|
||||
args.CompletionStatus = completionStatus;
|
||||
args.CombatWon = combatWon;
|
||||
args.InventorySnapshotAfterNode = InventoryCloneUtility.CloneInventory(inventorySnapshotAfterNode);
|
||||
|
||||
return args;
|
||||
@@ -58,7 +62,8 @@ namespace GeometryTD.CustomEvent
|
||||
NodeId = 0;
|
||||
NodeType = RunNodeType.None;
|
||||
SequenceIndex = -1;
|
||||
Succeeded = false;
|
||||
CompletionStatus = RunNodeCompletionStatus.None;
|
||||
CombatWon = false;
|
||||
InventorySnapshotAfterNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,19 +18,26 @@ namespace GeometryTD.Procedure
|
||||
public enum ProcedureMainRunAdvanceResult
|
||||
{
|
||||
NoChange = 0,
|
||||
NodeFailed = 1,
|
||||
NodeException = 1,
|
||||
AdvancedToNextNode = 2,
|
||||
RunCompleted = 3
|
||||
}
|
||||
|
||||
public enum ProcedureMainRunCompletionResult
|
||||
{
|
||||
NoChange = 0,
|
||||
ShowCompletionDialog = 1,
|
||||
ReturnToMenu = 2
|
||||
}
|
||||
|
||||
public static class ProcedureMainRunFlowService
|
||||
{
|
||||
public static ProcedureMainRunAdvanceResult TryAdvanceRun(
|
||||
RunState runState,
|
||||
bool succeeded,
|
||||
RunNodeCompletionStatus completionStatus,
|
||||
BackpackInventoryData snapshot)
|
||||
{
|
||||
if (!RunStateAdvanceService.TryCompleteCurrentNode(runState, succeeded, snapshot))
|
||||
if (!RunStateAdvanceService.TryCompleteCurrentNode(runState, completionStatus, snapshot))
|
||||
{
|
||||
return ProcedureMainRunAdvanceResult.NoChange;
|
||||
}
|
||||
@@ -40,9 +47,31 @@ namespace GeometryTD.Procedure
|
||||
return ProcedureMainRunAdvanceResult.RunCompleted;
|
||||
}
|
||||
|
||||
return succeeded
|
||||
? ProcedureMainRunAdvanceResult.AdvancedToNextNode
|
||||
: ProcedureMainRunAdvanceResult.NodeFailed;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +83,8 @@ namespace GeometryTD.Procedure
|
||||
private NodeMapFormUseCase _nodeMapFormUseCase;
|
||||
private RunState _currentRunState;
|
||||
private ProcedureMainFlowPhase _flowPhase = ProcedureMainFlowPhase.Hub;
|
||||
private bool _isRunCompleteDialogShown;
|
||||
private bool _isReturnToMenuPending;
|
||||
|
||||
#region FSM
|
||||
|
||||
@@ -61,7 +92,6 @@ namespace GeometryTD.Procedure
|
||||
{
|
||||
base.OnEnter(procedureOwner);
|
||||
|
||||
GameEntry.Event.Subscribe(CombatFailureReturnEventArgs.EventId, OnCombatFailureReturn);
|
||||
GameEntry.Event.Subscribe(NodeCompleteEventArgs.EventId, OnNodeComplete);
|
||||
GameEntry.Event.Subscribe(NodeEnterEventArgs.EventId, OnNodeEnter);
|
||||
GameEntry.Event.Subscribe(NodeMapNodeEnterRequestedEventArgs.EventId, OnNodeMapNodeEnterRequested);
|
||||
@@ -83,6 +113,8 @@ namespace GeometryTD.Procedure
|
||||
_nodeMapFormUseCase = new NodeMapFormUseCase();
|
||||
_nodeMapFormUseCase.SetRunState(_currentRunState);
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.NodeMapForm, _nodeMapFormUseCase);
|
||||
_isRunCompleteDialogShown = false;
|
||||
_isReturnToMenuPending = false;
|
||||
|
||||
EnterHubFlow();
|
||||
}
|
||||
@@ -92,6 +124,14 @@ namespace GeometryTD.Procedure
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -99,16 +139,18 @@ namespace GeometryTD.Procedure
|
||||
{
|
||||
GameEntry.CombatNode.OnShutdown();
|
||||
GameEntry.Event.Unsubscribe(NodeMapNodeEnterRequestedEventArgs.EventId, OnNodeMapNodeEnterRequested);
|
||||
GameEntry.Event.Unsubscribe(CombatFailureReturnEventArgs.EventId, OnCombatFailureReturn);
|
||||
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);
|
||||
}
|
||||
@@ -178,26 +220,23 @@ namespace GeometryTD.Procedure
|
||||
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.Succeeded, snapshot));
|
||||
}
|
||||
|
||||
private void OnCombatFailureReturn(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is CombatFailureReturnEventArgs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BackpackInventoryData snapshot = GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetInventorySnapshot()
|
||||
: null;
|
||||
HandleRunAdvanceResult(ProcedureMainRunFlowService.TryAdvanceRun(_currentRunState, false, snapshot));
|
||||
HandleRunAdvanceResult(
|
||||
ProcedureMainRunFlowService.TryAdvanceRun(_currentRunState, args.CompletionStatus, snapshot));
|
||||
}
|
||||
|
||||
private void OnNodeMapNodeEnterRequested(object sender, GameEventArgs e)
|
||||
@@ -275,9 +314,9 @@ namespace GeometryTD.Procedure
|
||||
{
|
||||
case ProcedureMainRunAdvanceResult.NoChange:
|
||||
return;
|
||||
case ProcedureMainRunAdvanceResult.NodeFailed:
|
||||
case ProcedureMainRunAdvanceResult.NodeException:
|
||||
Log.Info(
|
||||
"ProcedureMain current node failed. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}.",
|
||||
"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,
|
||||
@@ -322,6 +361,14 @@ namespace GeometryTD.Procedure
|
||||
_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()
|
||||
@@ -345,5 +392,37 @@ namespace GeometryTD.Procedure
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,17 @@ namespace GeometryTD.Procedure
|
||||
Locked = 0,
|
||||
Available = 1,
|
||||
Completed = 2,
|
||||
Failed = 3,
|
||||
Exception = 3,
|
||||
Skipped = 4
|
||||
}
|
||||
|
||||
public enum RunNodeCompletionStatus
|
||||
{
|
||||
None = 0,
|
||||
Completed = 1,
|
||||
Exception = 2
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class RunNodeSeed
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace GeometryTD.Procedure
|
||||
{
|
||||
public static bool TryCompleteCurrentNode(
|
||||
RunState runState,
|
||||
bool succeeded,
|
||||
RunNodeCompletionStatus completionStatus,
|
||||
BackpackInventoryData inventorySnapshotAfterNode)
|
||||
{
|
||||
if (runState == null || runState.IsCompleted)
|
||||
@@ -22,12 +22,17 @@ namespace GeometryTD.Procedure
|
||||
|
||||
runState.ReplaceInventorySnapshot(inventorySnapshotAfterNode);
|
||||
|
||||
if (!succeeded)
|
||||
if (completionStatus == RunNodeCompletionStatus.Exception)
|
||||
{
|
||||
currentNode.Status = RunNodeStatus.Failed;
|
||||
currentNode.Status = RunNodeStatus.Exception;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (completionStatus != RunNodeCompletionStatus.Completed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
currentNode.Status = RunNodeStatus.Completed;
|
||||
|
||||
int nextIndex = runState.CurrentNodeIndex + 1;
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace GeometryTD.UI
|
||||
public bool IsLocked;
|
||||
public bool IsCurrent;
|
||||
public bool IsCompleted;
|
||||
public bool IsFailed;
|
||||
public bool IsException;
|
||||
public bool CanClick;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace GeometryTD.UI
|
||||
IsLocked = node != null && node.Status == RunNodeStatus.Locked,
|
||||
IsCurrent = node != null && node.IsCurrentNode,
|
||||
IsCompleted = node != null && node.Status == RunNodeStatus.Completed,
|
||||
IsFailed = node != null && node.Status == RunNodeStatus.Failed,
|
||||
IsException = node != null && node.Status == RunNodeStatus.Exception,
|
||||
CanClick = node != null && node.CanEnter
|
||||
};
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ namespace GeometryTD.UI
|
||||
return "可进入";
|
||||
case RunNodeStatus.Completed:
|
||||
return "已完成";
|
||||
case RunNodeStatus.Failed:
|
||||
return "失败";
|
||||
case RunNodeStatus.Exception:
|
||||
return "异常";
|
||||
case RunNodeStatus.Skipped:
|
||||
return "跳过";
|
||||
default:
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace GeometryTD.UI
|
||||
[SerializeField] private Color _lockedColor = Color.gray;
|
||||
[SerializeField] private Color _activeColor = Color.cyan;
|
||||
[SerializeField] private Color _passedColor = Color.green;
|
||||
[SerializeField] private Color _failedColor = Color.red;
|
||||
[SerializeField] private Color _exceptionColor = Color.red;
|
||||
[SerializeField] private Color _defaultIconColor = Color.white;
|
||||
[SerializeField] private Color _lockedIconColor = Color.gray;
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace GeometryTD.UI
|
||||
{
|
||||
targetColor = _passedColor;
|
||||
}
|
||||
else if (context.IsFailed)
|
||||
else if (context.IsException)
|
||||
{
|
||||
targetColor = _failedColor;
|
||||
targetColor = _exceptionColor;
|
||||
}
|
||||
else if (context.IsCurrent)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user