refactor 7:
- 拆分 CombatScheduler,将公用方法与字段拆分为:
- FlowCoordinator
- RuntimeContext
- 地图侧现在收口为“MapData 初始快照 + CombatCoinChangedEventArgs 同步 + 独立命令桥接”
This commit is contained in:
+10
-6
@@ -45,7 +45,7 @@ namespace GeometryTD.CustomComponent
|
||||
_currentMap = null;
|
||||
}
|
||||
|
||||
public bool StartLoading(DRLevel level, MapData mapData, CombatScheduler scheduler, out string errorMessage)
|
||||
public bool StartLoading(DRLevel level, MapEntityLoadContext mapLoadContext, CombatScheduler scheduler, out string errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
if (_entity == null)
|
||||
@@ -54,7 +54,7 @@ namespace GeometryTD.CustomComponent
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryShowMap(level, mapData, out errorMessage))
|
||||
if (!TryShowMap(level, mapLoadContext, out errorMessage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -224,7 +224,7 @@ namespace GeometryTD.CustomComponent
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryShowMap(DRLevel level, MapData mapData, out string errorMessage)
|
||||
private bool TryShowMap(DRLevel level, MapEntityLoadContext mapLoadContext, out string errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
if (level == null)
|
||||
@@ -242,10 +242,14 @@ namespace GeometryTD.CustomComponent
|
||||
}
|
||||
|
||||
_loadingMapEntityId = _entity.GenerateSerialId();
|
||||
MapData resolvedMapData = mapData != null
|
||||
? mapData.CloneForEntity(_loadingMapEntityId, Vector3.zero)
|
||||
MapData resolvedMapData = mapLoadContext?.InitialMapData != null
|
||||
? mapLoadContext.InitialMapData.CloneForEntity(_loadingMapEntityId, Vector3.zero)
|
||||
: new MapData(_loadingMapEntityId, level.Id, Vector3.zero);
|
||||
_entity.ShowMap(resolvedMapData, mapAssetName);
|
||||
MapEntityLoadContext resolvedLoadContext = new MapEntityLoadContext(
|
||||
resolvedMapData,
|
||||
mapLoadContext?.TryConsumeCoin,
|
||||
mapLoadContext?.AddCoin);
|
||||
_entity.ShowMap(resolvedLoadContext, mapAssetName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+99
-339
@@ -11,65 +11,54 @@ namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
{
|
||||
private readonly List<DRLevelPhase> _phaseBuffer = new();
|
||||
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
|
||||
private readonly EnemyManager _enemyManager = new();
|
||||
private readonly PhaseLoopRuntime _phaseLoopRuntime = new();
|
||||
private readonly CombatLoadSession _loadSession = new();
|
||||
private readonly CombatEventBridge _eventBridge = new();
|
||||
private readonly CombatInRunResourceManager _combatInRunResourceManager = new();
|
||||
private readonly EnemyDropResolver _enemyDropResolver = new();
|
||||
private readonly CombatSettlementFlowService _settlementFlowService = new();
|
||||
private readonly CombatSchedulerRuntimeContext _context = new();
|
||||
private readonly CombatSchedulerFlowCoordinator _flowCoordinator;
|
||||
|
||||
private EntityComponent _entity;
|
||||
private DRLevel _currentLevel;
|
||||
private CombatFinishFormUseCase _combatFinishFormUseCase;
|
||||
private RewardSelectFormUseCase _rewardSelectFormUseCase;
|
||||
private CombatStateBase _currentState;
|
||||
private bool _initialized;
|
||||
private bool _isFinishAsVictory = true;
|
||||
private bool _isCompleted;
|
||||
private bool _nodeEnterFired;
|
||||
private CombatSettlementContext _settlementContext;
|
||||
|
||||
public CombatScheduler()
|
||||
{
|
||||
_flowCoordinator = new CombatSchedulerFlowCoordinator(this, _context);
|
||||
}
|
||||
|
||||
public bool IsRunning =>
|
||||
_currentState is CombatLoadingState or CombatRunningPhaseState or CombatWaitingForPhaseEndState;
|
||||
_context.CurrentState is CombatLoadingState or CombatRunningPhaseState or CombatWaitingForPhaseEndState;
|
||||
|
||||
public bool IsCompleted => _isCompleted;
|
||||
public DRLevel CurrentLevel => _currentLevel;
|
||||
public DRLevelPhase CurrentPhase => _phaseLoopRuntime.CurrentPhase;
|
||||
public MapEntity CurrentMap => _loadSession.CurrentMap;
|
||||
public int DisplayPhaseIndex => _phaseLoopRuntime.DisplayPhaseIndex;
|
||||
public int PhaseCount => _phaseLoopRuntime.PhaseCount;
|
||||
public bool CanEndCombat => _phaseLoopRuntime.CanEndCombat;
|
||||
public int CurrentCoin => _combatInRunResourceManager.CurrentCoin;
|
||||
public int CurrentGold => _combatInRunResourceManager.CurrentGold;
|
||||
public int CurrentBaseHp => _combatInRunResourceManager.CurrentBaseHp;
|
||||
public int CurrentBuildTowerCount => _combatInRunResourceManager.CurrentBuildTowerCount;
|
||||
public int DefeatedEnemyCount => _enemyManager.DefeatedEnemyCount;
|
||||
public int GainedCoin => _combatInRunResourceManager.GainedCoin;
|
||||
public int GainedGold => _combatInRunResourceManager.GainedGold;
|
||||
public bool IsCompleted => _context.IsCompleted;
|
||||
public DRLevel CurrentLevel => _context.CurrentLevel;
|
||||
public DRLevelPhase CurrentPhase => _context.PhaseLoopRuntime.CurrentPhase;
|
||||
public MapEntity CurrentMap => _context.LoadSession.CurrentMap;
|
||||
public int DisplayPhaseIndex => _context.PhaseLoopRuntime.DisplayPhaseIndex;
|
||||
public int PhaseCount => _context.PhaseLoopRuntime.PhaseCount;
|
||||
public bool CanEndCombat => _context.PhaseLoopRuntime.CanEndCombat;
|
||||
public int CurrentCoin => _context.CombatInRunResourceManager.CurrentCoin;
|
||||
public int CurrentGold => _context.CombatInRunResourceManager.CurrentGold;
|
||||
public int CurrentBaseHp => _context.CombatInRunResourceManager.CurrentBaseHp;
|
||||
public int CurrentBuildTowerCount => _context.CombatInRunResourceManager.CurrentBuildTowerCount;
|
||||
public int DefeatedEnemyCount => _context.EnemyManager.DefeatedEnemyCount;
|
||||
public int GainedCoin => _context.CombatInRunResourceManager.GainedCoin;
|
||||
public int GainedGold => _context.CombatInRunResourceManager.GainedGold;
|
||||
|
||||
public void OnInit()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
_entity = GameEntry.Entity;
|
||||
_eventBridge.Bind(
|
||||
_context.Entity = GameEntry.Entity;
|
||||
_context.EventBridge.Bind(
|
||||
OnShowEntitySuccess,
|
||||
OnShowEntityFailure,
|
||||
OnHideEntityComplete,
|
||||
OnOpenUIFormSuccess,
|
||||
OnOpenUIFormFailure,
|
||||
OnCloseUIFormComplete);
|
||||
_enemyManager.OnInit(this);
|
||||
_loadSession.OnInit(_entity);
|
||||
EnsureCombatFinishFormUseCaseBound();
|
||||
EnsureRewardSelectFormUseCaseBound();
|
||||
_context.EnemyManager.OnInit(this);
|
||||
_context.LoadSession.OnInit(_context.Entity);
|
||||
_flowCoordinator.EnsureCombatFinishFormUseCaseBound();
|
||||
_flowCoordinator.EnsureRewardSelectFormUseCaseBound();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
ResetRuntime();
|
||||
_flowCoordinator.ResetRuntime();
|
||||
}
|
||||
|
||||
public bool Start(
|
||||
@@ -77,32 +66,33 @@ namespace GeometryTD.CustomComponent
|
||||
IReadOnlyList<DRLevelPhase> phases,
|
||||
IReadOnlyDictionary<int, IReadOnlyList<DRLevelSpawnEntry>> spawnEntriesByPhaseId)
|
||||
{
|
||||
if (!_initialized || _entity == null)
|
||||
if (!_initialized || _context.Entity == null)
|
||||
{
|
||||
return HandleStartFailure("CombatScheduler start failed. Runtime is not initialized.");
|
||||
return _flowCoordinator.HandleStartFailure("CombatScheduler start failed. Runtime is not initialized.");
|
||||
}
|
||||
|
||||
if (level == null || phases == null || phases.Count <= 0)
|
||||
{
|
||||
return HandleStartFailure("CombatScheduler start failed. Invalid level or phase data.");
|
||||
return _flowCoordinator.HandleStartFailure("CombatScheduler start failed. Invalid level or phase data.");
|
||||
}
|
||||
|
||||
CleanupAllCombatEntities();
|
||||
CloseCombatFinishForm();
|
||||
CloseRewardSelectForm();
|
||||
_enemyManager.EndPhase();
|
||||
_enemyManager.ResetCombatStats();
|
||||
ResetRuntime();
|
||||
_isFinishAsVictory = true;
|
||||
_flowCoordinator.CleanupAllCombatEntities();
|
||||
_flowCoordinator.CloseCombatFinishForm();
|
||||
_flowCoordinator.CloseRewardSelectForm();
|
||||
_flowCoordinator.CloseDialogForm();
|
||||
_context.EnemyManager.EndPhase();
|
||||
_context.EnemyManager.ResetCombatStats();
|
||||
_flowCoordinator.ResetRuntime();
|
||||
_context.IsFinishAsVictory = true;
|
||||
|
||||
_currentLevel = level;
|
||||
_combatInRunResourceManager.InitializeForCombat(level);
|
||||
_context.CurrentLevel = level;
|
||||
_context.CombatInRunResourceManager.InitializeForCombat(level);
|
||||
for (int i = 0; i < phases.Count; i++)
|
||||
{
|
||||
DRLevelPhase phase = phases[i];
|
||||
if (phase != null)
|
||||
{
|
||||
_phaseBuffer.Add(phase);
|
||||
_context.PhaseBuffer.Add(phase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,27 +100,27 @@ namespace GeometryTD.CustomComponent
|
||||
{
|
||||
foreach (var pair in spawnEntriesByPhaseId)
|
||||
{
|
||||
_spawnEntriesByPhaseId[pair.Key] = pair.Value;
|
||||
_context.SpawnEntriesByPhaseId[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
|
||||
_phaseLoopRuntime.SetPhases(_phaseBuffer);
|
||||
if (_phaseLoopRuntime.PhaseCount <= 0)
|
||||
_context.PhaseLoopRuntime.SetPhases(_context.PhaseBuffer);
|
||||
if (_context.PhaseLoopRuntime.PhaseCount <= 0)
|
||||
{
|
||||
return HandleStartFailure($"CombatScheduler start failed. Level '{level.Id}' has no phase data.");
|
||||
return _flowCoordinator.HandleStartFailure($"CombatScheduler start failed. Level '{level.Id}' has no phase data.");
|
||||
}
|
||||
|
||||
ChangeState(new CombatLoadingState(this));
|
||||
ChangeState(new CombatLoadingState(_context, _flowCoordinator));
|
||||
Log.Info(
|
||||
"CombatScheduler started. Level={0}, PhaseCount={1}.",
|
||||
_currentLevel.Id,
|
||||
_phaseLoopRuntime.PhaseCount);
|
||||
_context.CurrentLevel.Id,
|
||||
_context.PhaseLoopRuntime.PhaseCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_currentState?.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
_context.CurrentState?.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
@@ -140,31 +130,32 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
_currentState?.OnExit();
|
||||
_currentState?.OnDestroy();
|
||||
_currentState = null;
|
||||
CleanupAllCombatEntities();
|
||||
CloseCombatFinishForm();
|
||||
CloseRewardSelectForm();
|
||||
_enemyManager.OnDestroy();
|
||||
ResetRuntime();
|
||||
_eventBridge.Unbind();
|
||||
_combatFinishFormUseCase = null;
|
||||
_rewardSelectFormUseCase = null;
|
||||
_context.CurrentState?.OnExit();
|
||||
_context.CurrentState?.OnDestroy();
|
||||
_context.CurrentState = null;
|
||||
_flowCoordinator.CleanupAllCombatEntities();
|
||||
_flowCoordinator.CloseCombatFinishForm();
|
||||
_flowCoordinator.CloseRewardSelectForm();
|
||||
_flowCoordinator.CloseDialogForm();
|
||||
_context.EnemyManager.OnDestroy();
|
||||
_flowCoordinator.ResetRuntime();
|
||||
_context.EventBridge.Unbind();
|
||||
_context.CombatFinishFormUseCase = null;
|
||||
_context.RewardSelectFormUseCase = null;
|
||||
|
||||
_entity = null;
|
||||
_context.Entity = null;
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
public bool TryEndCombatByPlayer()
|
||||
{
|
||||
if (_currentState is not CombatRunningPhaseState &&
|
||||
_currentState is not CombatWaitingForPhaseEndState)
|
||||
if (_context.CurrentState is not CombatRunningPhaseState &&
|
||||
_context.CurrentState is not CombatWaitingForPhaseEndState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _phaseLoopRuntime.TryRequestEndCombat();
|
||||
return _context.PhaseLoopRuntime.TryRequestEndCombat();
|
||||
}
|
||||
|
||||
public void OnEnemyReachedBase(DREnemy enemy)
|
||||
@@ -180,7 +171,7 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyBaseDamage(resolvedBaseDamage);
|
||||
_flowCoordinator.ApplyBaseDamage(resolvedBaseDamage);
|
||||
}
|
||||
|
||||
public void OnEnemyDefeated(DREnemy enemy)
|
||||
@@ -192,24 +183,24 @@ namespace GeometryTD.CustomComponent
|
||||
|
||||
EnemyDropResolveContext context = new(
|
||||
enemy,
|
||||
_phaseLoopRuntime.DisplayPhaseIndex,
|
||||
ResolveCurrentThemeType());
|
||||
EnemyDropResolveResult result = _enemyDropResolver.Resolve(context);
|
||||
_combatInRunResourceManager.AddEnemyDefeatedReward(result.Coin, result.Gold);
|
||||
_context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
_flowCoordinator.ResolveCurrentThemeType());
|
||||
EnemyDropResolveResult result = _context.EnemyDropResolver.Resolve(context);
|
||||
_context.CombatInRunResourceManager.AddEnemyDefeatedReward(result.Coin, result.Gold);
|
||||
|
||||
if (!result.ShouldRollOutGameItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_combatInRunResourceManager.TryRollOutGameItemDrop(
|
||||
_context.CombatInRunResourceManager.TryRollOutGameItemDrop(
|
||||
context.DisplayPhaseIndex,
|
||||
context.ThemeType);
|
||||
}
|
||||
|
||||
public bool OnCombatFinishReturnRequested()
|
||||
{
|
||||
if (_currentState is not CombatWaitingForReturnState waitingForReturnState)
|
||||
if (_context.CurrentState is not CombatWaitingForReturnState waitingForReturnState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -220,294 +211,63 @@ namespace GeometryTD.CustomComponent
|
||||
|
||||
public bool TryConsumeCoin(int coin)
|
||||
{
|
||||
return _combatInRunResourceManager.TryConsumeCoin(coin);
|
||||
return _context.CombatInRunResourceManager.TryConsumeCoin(coin);
|
||||
}
|
||||
|
||||
public void AddCoin(int coin)
|
||||
{
|
||||
_combatInRunResourceManager.AddCoin(coin);
|
||||
_context.CombatInRunResourceManager.AddCoin(coin);
|
||||
}
|
||||
|
||||
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
|
||||
{
|
||||
return _combatInRunResourceManager.TryGetBuildTowerStats(buildIndex, out stats);
|
||||
return _context.CombatInRunResourceManager.TryGetBuildTowerStats(buildIndex, out stats);
|
||||
}
|
||||
|
||||
public bool TryDebugFail(string errorMessage)
|
||||
{
|
||||
if (_isCompleted || _currentState == null || _currentState is CombatFailedState)
|
||||
if (_context.IsCompleted || _context.CurrentState == null || _context.CurrentState is CombatFailedState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
EnterFailureFallback(string.IsNullOrWhiteSpace(errorMessage)
|
||||
_flowCoordinator.EnterFailureFallback(string.IsNullOrWhiteSpace(errorMessage)
|
||||
? "Manual debug fail."
|
||||
: errorMessage);
|
||||
return _currentState is CombatFailedState;
|
||||
return _context.CurrentState is CombatFailedState;
|
||||
}
|
||||
|
||||
private void ResetRuntime()
|
||||
internal void ChangeState(CombatStateBase nextState)
|
||||
{
|
||||
_currentState = null;
|
||||
_phaseBuffer.Clear();
|
||||
_spawnEntriesByPhaseId.Clear();
|
||||
_phaseLoopRuntime.Reset();
|
||||
_loadSession.Reset();
|
||||
_combatInRunResourceManager.Reset();
|
||||
_settlementContext = null;
|
||||
_currentLevel = null;
|
||||
_isFinishAsVictory = true;
|
||||
_isCompleted = false;
|
||||
_nodeEnterFired = false;
|
||||
}
|
||||
|
||||
private void CleanupAllCombatEntities()
|
||||
{
|
||||
_loadSession.Cleanup();
|
||||
_enemyManager.CleanupTrackedEnemies();
|
||||
}
|
||||
|
||||
private void EnsureCombatFinishFormUseCaseBound()
|
||||
{
|
||||
_combatFinishFormUseCase ??= new CombatFinishFormUseCase(this);
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatFinishForm, _combatFinishFormUseCase);
|
||||
}
|
||||
|
||||
private void EnsureRewardSelectFormUseCaseBound()
|
||||
{
|
||||
_rewardSelectFormUseCase ??= new RewardSelectFormUseCase();
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.RewardSelectForm, _rewardSelectFormUseCase);
|
||||
}
|
||||
|
||||
private void OpenCombatFailureDialog(string errorMessage)
|
||||
{
|
||||
CloseDialogForm();
|
||||
GameEntry.UIRouter.OpenUI(UIFormType.DialogForm, new DialogFormRawData
|
||||
{
|
||||
Mode = 1,
|
||||
Title = "Combat Error",
|
||||
Message = string.IsNullOrWhiteSpace(errorMessage) ? "Combat failed unexpectedly." : errorMessage,
|
||||
PauseGame = false,
|
||||
ConfirmText = "Return Menu",
|
||||
OnClickConfirm = OnCombatFailureDialogConfirmed
|
||||
});
|
||||
}
|
||||
|
||||
private void ChangeState(CombatStateBase nextState)
|
||||
{
|
||||
if (ReferenceEquals(_currentState, nextState))
|
||||
if (ReferenceEquals(_context.CurrentState, nextState))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_currentState?.OnExit();
|
||||
_currentState?.OnDestroy();
|
||||
_currentState = nextState;
|
||||
_currentState?.OnInit();
|
||||
_currentState?.OnEnter();
|
||||
}
|
||||
|
||||
private bool TryBeginNextPhase()
|
||||
{
|
||||
if (!_phaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase))
|
||||
{
|
||||
ChangeState(new CombatSettlementState(this, "Combat ended after loop completion.", true));
|
||||
return false;
|
||||
}
|
||||
|
||||
_spawnEntriesByPhaseId.TryGetValue(nextPhase.Id, out IReadOnlyList<DRLevelSpawnEntry> spawnEntries);
|
||||
ChangeState(new CombatRunningPhaseState(this, nextPhase, spawnEntries));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void EnterWaitingForPhaseEnd()
|
||||
{
|
||||
ChangeState(new CombatWaitingForPhaseEndState(this));
|
||||
}
|
||||
|
||||
private void CompleteCurrentPhase()
|
||||
{
|
||||
_enemyManager.EndPhase();
|
||||
Log.Info(
|
||||
"CombatScheduler phase completed. Level={0}, Phase={1}, Elapsed={2:F2}s.",
|
||||
_currentLevel != null ? _currentLevel.Id : 0,
|
||||
_phaseLoopRuntime.CurrentPhase != null ? _phaseLoopRuntime.CurrentPhase.Id : 0,
|
||||
_phaseLoopRuntime.CurrentPhaseElapsed);
|
||||
|
||||
TryBeginNextPhase();
|
||||
}
|
||||
|
||||
private bool ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory)
|
||||
{
|
||||
if (GetCurrentBaseHp() <= 0)
|
||||
{
|
||||
reason = "Combat ended because base HP reached zero.";
|
||||
isVictory = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_phaseLoopRuntime.IsEndCombatRequested)
|
||||
{
|
||||
reason = "Combat ended by player.";
|
||||
isVictory = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
reason = null;
|
||||
isVictory = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnFullBaseHpRewardSelected(RewardSelectItemRawData selectedReward)
|
||||
{
|
||||
if (_currentState is not CombatRewardSelectionState || _settlementContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_settlementFlowService.ApplySelectedReward(_settlementContext, selectedReward);
|
||||
ChangeState(new CombatFinishFormState(this));
|
||||
}
|
||||
|
||||
private void OnFullBaseHpRewardGiveUp()
|
||||
{
|
||||
if (_currentState is not CombatRewardSelectionState || _settlementContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeState(new CombatFinishFormState(this));
|
||||
}
|
||||
|
||||
private LevelThemeType ResolveCurrentThemeType()
|
||||
{
|
||||
if (_currentLevel != null)
|
||||
{
|
||||
return _currentLevel.LevelThemeType;
|
||||
}
|
||||
|
||||
if (GameEntry.CombatNode != null)
|
||||
{
|
||||
return GameEntry.CombatNode.CurrentThemeType;
|
||||
}
|
||||
|
||||
return LevelThemeType.None;
|
||||
}
|
||||
|
||||
private int ApplyBaseDamage(int damage)
|
||||
{
|
||||
return _combatInRunResourceManager.ApplyBaseDamage(damage);
|
||||
}
|
||||
|
||||
private int GetCurrentBaseHp()
|
||||
{
|
||||
return Mathf.Max(0, _combatInRunResourceManager.CurrentBaseHp);
|
||||
}
|
||||
|
||||
private void CloseCombatFinishForm()
|
||||
{
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.CombatFinishForm);
|
||||
}
|
||||
|
||||
private void CloseRewardSelectForm()
|
||||
{
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.RewardSelectForm);
|
||||
}
|
||||
|
||||
private void CloseDialogForm()
|
||||
{
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.DialogForm);
|
||||
}
|
||||
|
||||
private void CompleteCombat(bool succeeded)
|
||||
{
|
||||
_isCompleted = true;
|
||||
_currentState = null;
|
||||
_combatInRunResourceManager.MarkCombatEnded();
|
||||
GameEntry.CombatNode?.OnCombatEndedByScheduler(succeeded);
|
||||
}
|
||||
|
||||
private void CompleteNormalCombatAndNotify(bool succeeded)
|
||||
{
|
||||
CompleteCombat(succeeded);
|
||||
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
||||
}
|
||||
|
||||
private void CompleteFailureCombatAndNotify()
|
||||
{
|
||||
CleanupAllCombatEntities();
|
||||
CloseCombatFinishForm();
|
||||
CloseRewardSelectForm();
|
||||
CloseDialogForm();
|
||||
CompleteCombat(false);
|
||||
GameEntry.Event.Fire(this, CombatFailureReturnEventArgs.Create());
|
||||
}
|
||||
|
||||
private bool HandleStartFailure(string errorMessage)
|
||||
{
|
||||
Log.Warning("{0}", errorMessage);
|
||||
_enemyManager.EndPhase();
|
||||
CleanupAllCombatEntities();
|
||||
CloseCombatFinishForm();
|
||||
CloseRewardSelectForm();
|
||||
ResetRuntime();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void EnterFailureFallback(string errorMessage)
|
||||
{
|
||||
if (_currentState is CombatFailedState || _isCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeState(new CombatFailedState(this, errorMessage));
|
||||
}
|
||||
|
||||
private static int ResolveEnemyHpRateMultiplier(int displayPhaseIndex, int phaseCount)
|
||||
{
|
||||
if (displayPhaseIndex <= 0 || phaseCount <= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int completedLoopCount = Mathf.Max(0, (displayPhaseIndex - 1) / phaseCount);
|
||||
if (completedLoopCount >= 30)
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
return 1 << completedLoopCount;
|
||||
}
|
||||
|
||||
private void OnCombatFailureDialogConfirmed(object userData)
|
||||
{
|
||||
_ = userData;
|
||||
if (_currentState is not CombatFailedState || _isCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CompleteFailureCombatAndNotify();
|
||||
_context.CurrentState?.OnExit();
|
||||
_context.CurrentState?.OnDestroy();
|
||||
_context.CurrentState = nextState;
|
||||
_context.CurrentState?.OnInit();
|
||||
_context.CurrentState?.OnEnter();
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnShowEntitySuccess(ShowEntitySuccessEventArgs args)
|
||||
{
|
||||
var status = _loadSession.HandleShowEntitySuccess(args, out string errorMessage);
|
||||
var status = _context.LoadSession.HandleShowEntitySuccess(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
EnterFailureFallback(errorMessage);
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == CombatLoadSession.EventHandleStatus.Succeeded)
|
||||
{
|
||||
MapEntity map = _loadSession.CurrentMap;
|
||||
MapEntity map = _context.LoadSession.CurrentMap;
|
||||
Log.Info(
|
||||
"Map ready. LevelId={0}, PathCells={1}, FoundationCells={2}, Spawners={3}, House={4}.",
|
||||
_currentLevel != null ? _currentLevel.Id : 0,
|
||||
_context.CurrentLevel != null ? _context.CurrentLevel.Id : 0,
|
||||
map.PathCells.Count,
|
||||
map.FoundationCells.Count,
|
||||
map.Spawners.Length,
|
||||
@@ -517,39 +277,39 @@ namespace GeometryTD.CustomComponent
|
||||
|
||||
private void OnShowEntityFailure(ShowEntityFailureEventArgs args)
|
||||
{
|
||||
var status = _loadSession.HandleShowEntityFailure(args, out string errorMessage);
|
||||
var status = _context.LoadSession.HandleShowEntityFailure(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
EnterFailureFallback(errorMessage);
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHideEntityComplete(HideEntityCompleteEventArgs args)
|
||||
{
|
||||
_loadSession.HandleHideEntityComplete(args);
|
||||
_context.LoadSession.HandleHideEntityComplete(args);
|
||||
}
|
||||
|
||||
private void OnOpenUIFormSuccess(OpenUIFormSuccessEventArgs args)
|
||||
{
|
||||
var status = _loadSession.HandleOpenUIFormSuccess(args, out string errorMessage);
|
||||
var status = _context.LoadSession.HandleOpenUIFormSuccess(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
EnterFailureFallback(errorMessage);
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOpenUIFormFailure(OpenUIFormFailureEventArgs args)
|
||||
{
|
||||
var status = _loadSession.HandleOpenUIFormFailure(args, out string errorMessage);
|
||||
var status = _context.LoadSession.HandleOpenUIFormFailure(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
EnterFailureFallback(errorMessage);
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloseUIFormComplete(CloseUIFormCompleteEventArgs args)
|
||||
{
|
||||
_loadSession.HandleCloseUIFormComplete(args);
|
||||
_context.LoadSession.HandleCloseUIFormComplete(args);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.CustomEvent;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Definition;
|
||||
using GeometryTD.UI;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class CombatSchedulerFlowCoordinator
|
||||
{
|
||||
private readonly CombatScheduler _scheduler;
|
||||
private readonly CombatSchedulerRuntimeContext _context;
|
||||
|
||||
public CombatScheduler Scheduler => _scheduler;
|
||||
|
||||
public CombatSchedulerFlowCoordinator(CombatScheduler scheduler, CombatSchedulerRuntimeContext context)
|
||||
{
|
||||
_scheduler = scheduler;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public int ResolveEnemyHpRateMultiplier(int displayPhaseIndex, int phaseCount)
|
||||
{
|
||||
if (displayPhaseIndex <= 0 || phaseCount <= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int completedLoopCount = Mathf.Max(0, (displayPhaseIndex - 1) / phaseCount);
|
||||
if (completedLoopCount >= 30)
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
return 1 << completedLoopCount;
|
||||
}
|
||||
|
||||
public void ResetRuntime()
|
||||
{
|
||||
_context.CurrentState = null;
|
||||
_context.PhaseBuffer.Clear();
|
||||
_context.SpawnEntriesByPhaseId.Clear();
|
||||
_context.PhaseLoopRuntime.Reset();
|
||||
_context.LoadSession.Reset();
|
||||
_context.CombatInRunResourceManager.Reset();
|
||||
_context.SettlementContext = null;
|
||||
_context.CurrentLevel = null;
|
||||
_context.IsFinishAsVictory = true;
|
||||
_context.IsCompleted = false;
|
||||
_context.NodeEnterFired = false;
|
||||
}
|
||||
|
||||
public void CleanupAllCombatEntities()
|
||||
{
|
||||
_context.LoadSession.Cleanup();
|
||||
_context.EnemyManager.CleanupTrackedEnemies();
|
||||
}
|
||||
|
||||
public void EnsureCombatFinishFormUseCaseBound()
|
||||
{
|
||||
_context.CombatFinishFormUseCase ??= new CombatFinishFormUseCase(_scheduler);
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatFinishForm, _context.CombatFinishFormUseCase);
|
||||
}
|
||||
|
||||
public void EnsureRewardSelectFormUseCaseBound()
|
||||
{
|
||||
_context.RewardSelectFormUseCase ??= new RewardSelectFormUseCase();
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.RewardSelectForm, _context.RewardSelectFormUseCase);
|
||||
}
|
||||
|
||||
public void OpenCombatFailureDialog(string errorMessage)
|
||||
{
|
||||
CloseDialogForm();
|
||||
GameEntry.UIRouter.OpenUI(UIFormType.DialogForm, new DialogFormRawData
|
||||
{
|
||||
Mode = 1,
|
||||
Title = "Combat Error",
|
||||
Message = string.IsNullOrWhiteSpace(errorMessage) ? "Combat failed unexpectedly." : errorMessage,
|
||||
PauseGame = false,
|
||||
ConfirmText = "Return Menu",
|
||||
OnClickConfirm = OnCombatFailureDialogConfirmed
|
||||
});
|
||||
}
|
||||
|
||||
public bool TryBeginNextPhase()
|
||||
{
|
||||
if (!_context.PhaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase))
|
||||
{
|
||||
_scheduler.ChangeState(new CombatSettlementState(_context, this, "Combat ended after loop completion.", true));
|
||||
return false;
|
||||
}
|
||||
|
||||
_context.SpawnEntriesByPhaseId.TryGetValue(nextPhase.Id, out IReadOnlyList<DRLevelSpawnEntry> spawnEntries);
|
||||
_scheduler.ChangeState(new CombatRunningPhaseState(_context, this, nextPhase, spawnEntries));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void EnterWaitingForPhaseEnd()
|
||||
{
|
||||
_scheduler.ChangeState(new CombatWaitingForPhaseEndState(_context, this));
|
||||
}
|
||||
|
||||
public void CompleteCurrentPhase()
|
||||
{
|
||||
_context.EnemyManager.EndPhase();
|
||||
Log.Info(
|
||||
"CombatScheduler phase completed. Level={0}, Phase={1}, Elapsed={2:F2}s.",
|
||||
_context.CurrentLevel != null ? _context.CurrentLevel.Id : 0,
|
||||
_context.PhaseLoopRuntime.CurrentPhase != null ? _context.PhaseLoopRuntime.CurrentPhase.Id : 0,
|
||||
_context.PhaseLoopRuntime.CurrentPhaseElapsed);
|
||||
|
||||
TryBeginNextPhase();
|
||||
}
|
||||
|
||||
public bool ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory)
|
||||
{
|
||||
if (GetCurrentBaseHp() <= 0)
|
||||
{
|
||||
reason = "Combat ended because base HP reached zero.";
|
||||
isVictory = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_context.PhaseLoopRuntime.IsEndCombatRequested)
|
||||
{
|
||||
reason = "Combat ended by player.";
|
||||
isVictory = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
reason = null;
|
||||
isVictory = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnFullBaseHpRewardSelected(RewardSelectItemRawData selectedReward)
|
||||
{
|
||||
if (_context.CurrentState is not CombatRewardSelectionState || _context.SettlementContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_context.SettlementFlowService.ApplySelectedReward(_context.SettlementContext, selectedReward);
|
||||
_scheduler.ChangeState(new CombatFinishFormState(_context, this));
|
||||
}
|
||||
|
||||
public void OnFullBaseHpRewardGiveUp()
|
||||
{
|
||||
if (_context.CurrentState is not CombatRewardSelectionState || _context.SettlementContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduler.ChangeState(new CombatFinishFormState(_context, this));
|
||||
}
|
||||
|
||||
public LevelThemeType ResolveCurrentThemeType()
|
||||
{
|
||||
if (_context.CurrentLevel != null)
|
||||
{
|
||||
return _context.CurrentLevel.LevelThemeType;
|
||||
}
|
||||
|
||||
if (GameEntry.CombatNode != null)
|
||||
{
|
||||
return GameEntry.CombatNode.CurrentThemeType;
|
||||
}
|
||||
|
||||
return LevelThemeType.None;
|
||||
}
|
||||
|
||||
public int ApplyBaseDamage(int damage)
|
||||
{
|
||||
return _context.CombatInRunResourceManager.ApplyBaseDamage(damage);
|
||||
}
|
||||
|
||||
public int GetCurrentBaseHp()
|
||||
{
|
||||
return Mathf.Max(0, _context.CombatInRunResourceManager.CurrentBaseHp);
|
||||
}
|
||||
|
||||
public void CloseCombatFinishForm()
|
||||
{
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.CombatFinishForm);
|
||||
}
|
||||
|
||||
public void CloseRewardSelectForm()
|
||||
{
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.RewardSelectForm);
|
||||
}
|
||||
|
||||
public void CloseDialogForm()
|
||||
{
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.DialogForm);
|
||||
}
|
||||
|
||||
public void CompleteNormalCombatAndNotify(bool succeeded)
|
||||
{
|
||||
CompleteCombat(succeeded);
|
||||
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
||||
}
|
||||
|
||||
public void CompleteFailureCombatAndNotify()
|
||||
{
|
||||
CleanupAllCombatEntities();
|
||||
CloseCombatFinishForm();
|
||||
CloseRewardSelectForm();
|
||||
CloseDialogForm();
|
||||
CompleteCombat(false);
|
||||
GameEntry.Event.Fire(this, CombatFailureReturnEventArgs.Create());
|
||||
}
|
||||
|
||||
public bool HandleStartFailure(string errorMessage)
|
||||
{
|
||||
Log.Warning("{0}", errorMessage);
|
||||
_context.EnemyManager.EndPhase();
|
||||
CleanupAllCombatEntities();
|
||||
CloseCombatFinishForm();
|
||||
CloseRewardSelectForm();
|
||||
CloseDialogForm();
|
||||
ResetRuntime();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void EnterFailureFallback(string errorMessage)
|
||||
{
|
||||
if (_context.CurrentState is CombatFailedState || _context.IsCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduler.ChangeState(new CombatFailedState(_context, this, errorMessage));
|
||||
}
|
||||
|
||||
public void OnCombatFailureDialogConfirmed(object userData)
|
||||
{
|
||||
_ = userData;
|
||||
if (_context.CurrentState is not CombatFailedState || _context.IsCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CompleteFailureCombatAndNotify();
|
||||
}
|
||||
|
||||
private void CompleteCombat(bool succeeded)
|
||||
{
|
||||
_context.IsCompleted = true;
|
||||
_context.CurrentState = null;
|
||||
_context.CombatInRunResourceManager.MarkCombatEnded();
|
||||
GameEntry.CombatNode?.OnCombatEndedByScheduler(succeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 672e14aaea7d4135874ef7f990eb78f2
|
||||
timeCreated: 1772865001
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Entity;
|
||||
using GeometryTD.UI;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class CombatSchedulerRuntimeContext
|
||||
{
|
||||
public List<DRLevelPhase> PhaseBuffer { get; } = new();
|
||||
public Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> SpawnEntriesByPhaseId { get; } = new();
|
||||
public EnemyManager EnemyManager { get; } = new();
|
||||
public PhaseLoopRuntime PhaseLoopRuntime { get; } = new();
|
||||
public CombatLoadSession LoadSession { get; } = new();
|
||||
public CombatEventBridge EventBridge { get; } = new();
|
||||
public CombatInRunResourceManager CombatInRunResourceManager { get; } = new();
|
||||
public EnemyDropResolver EnemyDropResolver { get; } = new();
|
||||
public CombatSettlementFlowService SettlementFlowService { get; } = new();
|
||||
|
||||
public EntityComponent Entity { get; set; }
|
||||
public DRLevel CurrentLevel { get; set; }
|
||||
public CombatFinishFormUseCase CombatFinishFormUseCase { get; set; }
|
||||
public RewardSelectFormUseCase RewardSelectFormUseCase { get; set; }
|
||||
public CombatStateBase CurrentState { get; set; }
|
||||
public bool IsFinishAsVictory { get; set; } = true;
|
||||
public bool IsCompleted { get; set; }
|
||||
public bool NodeEnterFired { get; set; }
|
||||
public CombatSettlementContext SettlementContext { get; set; }
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebdf96ddef6945efa0e1446597a9c776
|
||||
timeCreated: 1772865000
|
||||
+23
-23
@@ -2,33 +2,33 @@ using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatFailedState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatFailedState : CombatStateBase
|
||||
private readonly string _errorMessage;
|
||||
|
||||
public CombatFailedState(
|
||||
CombatSchedulerRuntimeContext context,
|
||||
CombatSchedulerFlowCoordinator flow,
|
||||
string errorMessage) : base(context, flow)
|
||||
{
|
||||
private readonly string _errorMessage;
|
||||
_errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public CombatFailedState(CombatScheduler scheduler, string errorMessage) : base(scheduler)
|
||||
{
|
||||
_errorMessage = errorMessage;
|
||||
}
|
||||
public override void OnEnter()
|
||||
{
|
||||
Log.Error(
|
||||
"CombatScheduler failed. LevelId={0}, {1}",
|
||||
Context.CurrentLevel != null ? Context.CurrentLevel.Id : 0,
|
||||
_errorMessage);
|
||||
Context.EnemyManager.EndPhase();
|
||||
Flow.CloseCombatFinishForm();
|
||||
Flow.CloseRewardSelectForm();
|
||||
Flow.OpenCombatFailureDialog(_errorMessage);
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
Log.Error(
|
||||
"CombatScheduler failed. LevelId={0}, {1}",
|
||||
Scheduler._currentLevel != null ? Scheduler._currentLevel.Id : 0,
|
||||
_errorMessage);
|
||||
Scheduler._enemyManager.EndPhase();
|
||||
Scheduler.CloseCombatFinishForm();
|
||||
Scheduler.CloseRewardSelectForm();
|
||||
Scheduler.OpenCombatFailureDialog(_errorMessage);
|
||||
}
|
||||
|
||||
public override void OnExit()
|
||||
{
|
||||
Scheduler.CloseDialogForm();
|
||||
}
|
||||
public override void OnExit()
|
||||
{
|
||||
Flow.CloseDialogForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-18
@@ -1,28 +1,26 @@
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatFinishFormState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatFinishFormState : CombatStateBase
|
||||
public CombatFinishFormState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
{
|
||||
public CombatFinishFormState(CombatScheduler scheduler) : base(scheduler)
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (Context.SettlementContext == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("Combat finish form failed. Settlement context is missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (Scheduler._settlementContext == null)
|
||||
{
|
||||
Scheduler.EnterFailureFallback("Combat finish form failed. Settlement context is missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler._settlementFlowService.CommitSettlementInventory(Scheduler._settlementContext);
|
||||
Scheduler.EnsureCombatFinishFormUseCaseBound();
|
||||
Scheduler._settlementFlowService.OpenCombatFinishForm(
|
||||
Scheduler._settlementContext,
|
||||
Scheduler._combatFinishFormUseCase);
|
||||
Scheduler.ChangeState(new CombatWaitingForReturnState(Scheduler));
|
||||
}
|
||||
Context.SettlementFlowService.CommitSettlementInventory(Context.SettlementContext);
|
||||
Flow.EnsureCombatFinishFormUseCaseBound();
|
||||
Context.SettlementFlowService.OpenCombatFinishForm(
|
||||
Context.SettlementContext,
|
||||
Context.CombatFinishFormUseCase);
|
||||
Flow.Scheduler.ChangeState(new CombatWaitingForReturnState(Context, Flow));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+50
-53
@@ -6,70 +6,67 @@ using UnityEngine;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatLoadingState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatLoadingState : CombatStateBase
|
||||
public CombatLoadingState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
{
|
||||
public CombatLoadingState(CombatScheduler scheduler) : base(scheduler)
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (Context.CurrentLevel == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("Combat loading failed. Current level is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
MapEntityLoadContext mapLoadContext = BuildMapLoadContext();
|
||||
if (!Context.LoadSession.StartLoading(Context.CurrentLevel, mapLoadContext, Flow.Scheduler, out string errorMessage))
|
||||
{
|
||||
if (Scheduler._currentLevel == null)
|
||||
{
|
||||
Scheduler.EnterFailureFallback("Combat loading failed. Current level is null.");
|
||||
return;
|
||||
}
|
||||
Flow.EnterFailureFallback($"Combat loading failed. {errorMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
MapData mapData = BuildMapData();
|
||||
if (!Scheduler._loadSession.StartLoading(Scheduler._currentLevel, mapData, Scheduler, out string errorMessage))
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_ = elapseSeconds;
|
||||
_ = realElapseSeconds;
|
||||
|
||||
if (!Context.LoadSession.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Flow.TryBeginNextPhase();
|
||||
}
|
||||
|
||||
private MapEntityLoadContext BuildMapLoadContext()
|
||||
{
|
||||
List<TowerStatsData> buildTowerStatsSnapshot = new();
|
||||
for (int i = 0; i < Context.CombatInRunResourceManager.CurrentBuildTowerCount; i++)
|
||||
{
|
||||
if (Context.CombatInRunResourceManager.TryGetBuildTowerStats(i, out TowerStatsData stats) &&
|
||||
stats != null)
|
||||
{
|
||||
Scheduler.EnterFailureFallback($"Combat loading failed. {errorMessage}");
|
||||
buildTowerStatsSnapshot.Add(stats);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_ = elapseSeconds;
|
||||
_ = realElapseSeconds;
|
||||
|
||||
if (!Scheduler._loadSession.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler.TryBeginNextPhase();
|
||||
}
|
||||
|
||||
private MapData BuildMapData()
|
||||
{
|
||||
List<TowerStatsData> buildTowerStatsSnapshot = new();
|
||||
for (int i = 0; i < Scheduler._combatInRunResourceManager.CurrentBuildTowerCount; i++)
|
||||
{
|
||||
if (Scheduler._combatInRunResourceManager.TryGetBuildTowerStats(i, out TowerStatsData stats) &&
|
||||
stats != null)
|
||||
{
|
||||
buildTowerStatsSnapshot.Add(stats);
|
||||
}
|
||||
}
|
||||
|
||||
return new MapData(
|
||||
entityId: 0,
|
||||
typeId: 0,
|
||||
levelId: Scheduler._currentLevel.Id,
|
||||
position: Vector3.zero,
|
||||
initialCoin: Scheduler._combatInRunResourceManager.CurrentCoin,
|
||||
buildTowerStatsSnapshot: buildTowerStatsSnapshot,
|
||||
inventorySnapshot: GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetInventorySnapshot()
|
||||
: null,
|
||||
participantTowerSnapshot: GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetParticipantTowerSnapshot()
|
||||
: null,
|
||||
tryConsumeCoin: Scheduler.TryConsumeCoin,
|
||||
addCoin: Scheduler.AddCoin);
|
||||
}
|
||||
MapData mapData = new MapData(
|
||||
entityId: 0,
|
||||
typeId: 0,
|
||||
levelId: Context.CurrentLevel.Id,
|
||||
position: Vector3.zero,
|
||||
initialCoin: Context.CombatInRunResourceManager.CurrentCoin,
|
||||
buildTowerStatsSnapshot: buildTowerStatsSnapshot,
|
||||
inventorySnapshot: GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetInventorySnapshot()
|
||||
: null,
|
||||
participantTowerSnapshot: GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetParticipantTowerSnapshot()
|
||||
: null);
|
||||
return new MapEntityLoadContext(mapData, Flow.Scheduler.TryConsumeCoin, Flow.Scheduler.AddCoin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-26
@@ -1,39 +1,37 @@
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatRewardSelectionState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatRewardSelectionState : CombatStateBase
|
||||
public CombatRewardSelectionState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
{
|
||||
public CombatRewardSelectionState(CombatScheduler scheduler) : base(scheduler)
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (Context.SettlementContext == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("Combat reward selection failed. Settlement context is missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
Flow.EnsureRewardSelectFormUseCaseBound();
|
||||
if (!Context.SettlementFlowService.TryPrepareRewardSelection(
|
||||
Context.SettlementContext,
|
||||
Context.CombatInRunResourceManager,
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Flow.ResolveCurrentThemeType(),
|
||||
Context.RewardSelectFormUseCase,
|
||||
Flow.OnFullBaseHpRewardSelected,
|
||||
Flow.OnFullBaseHpRewardGiveUp))
|
||||
{
|
||||
if (Scheduler._settlementContext == null)
|
||||
{
|
||||
Scheduler.EnterFailureFallback("Combat reward selection failed. Settlement context is missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler.EnsureRewardSelectFormUseCaseBound();
|
||||
if (!Scheduler._settlementFlowService.TryPrepareRewardSelection(
|
||||
Scheduler._settlementContext,
|
||||
Scheduler._combatInRunResourceManager,
|
||||
Scheduler._phaseLoopRuntime.DisplayPhaseIndex,
|
||||
Scheduler.ResolveCurrentThemeType(),
|
||||
Scheduler._rewardSelectFormUseCase,
|
||||
Scheduler.OnFullBaseHpRewardSelected,
|
||||
Scheduler.OnFullBaseHpRewardGiveUp))
|
||||
{
|
||||
Scheduler.ChangeState(new CombatFinishFormState(Scheduler));
|
||||
}
|
||||
Flow.Scheduler.ChangeState(new CombatFinishFormState(Context, Flow));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnExit()
|
||||
{
|
||||
Scheduler.CloseRewardSelectForm();
|
||||
}
|
||||
public override void OnExit()
|
||||
{
|
||||
Flow.CloseRewardSelectForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+53
-55
@@ -5,72 +5,70 @@ using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatRunningPhaseState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatRunningPhaseState : CombatStateBase
|
||||
private readonly DRLevelPhase _phase;
|
||||
private readonly IReadOnlyList<DRLevelSpawnEntry> _spawnEntries;
|
||||
|
||||
public CombatRunningPhaseState(
|
||||
CombatSchedulerRuntimeContext context,
|
||||
CombatSchedulerFlowCoordinator flow,
|
||||
DRLevelPhase phase,
|
||||
IReadOnlyList<DRLevelSpawnEntry> spawnEntries) : base(context, flow)
|
||||
{
|
||||
private readonly DRLevelPhase _phase;
|
||||
private readonly IReadOnlyList<DRLevelSpawnEntry> _spawnEntries;
|
||||
_phase = phase;
|
||||
_spawnEntries = spawnEntries;
|
||||
}
|
||||
|
||||
public CombatRunningPhaseState(
|
||||
CombatScheduler scheduler,
|
||||
DRLevelPhase phase,
|
||||
IReadOnlyList<DRLevelSpawnEntry> spawnEntries) : base(scheduler)
|
||||
public override void OnEnter()
|
||||
{
|
||||
Context.EnemyManager.BeginPhase(_phase, _spawnEntries);
|
||||
GameEntry.Event.Fire(
|
||||
Flow,
|
||||
CombatProcessEventArgs.Create(
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Context.PhaseLoopRuntime.PhaseCount));
|
||||
GameEntry.Event.Fire(
|
||||
Flow,
|
||||
CombatEnemyHpRateChangedEventArgs.Create(
|
||||
Flow.ResolveEnemyHpRateMultiplier(
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Context.PhaseLoopRuntime.PhaseCount)));
|
||||
|
||||
if (!Context.NodeEnterFired)
|
||||
{
|
||||
_phase = phase;
|
||||
_spawnEntries = spawnEntries;
|
||||
Context.NodeEnterFired = true;
|
||||
GameEntry.Event.Fire(Flow, NodeEnterEventArgs.Create());
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
Log.Info(
|
||||
"CombatScheduler phase started. Level={0}, Phase={1}, EndType={2}, Entries={3}.",
|
||||
Context.CurrentLevel != null ? Context.CurrentLevel.Id : 0,
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
_phase.EndType,
|
||||
_spawnEntries != null ? _spawnEntries.Count : 0);
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
if (Context.PhaseLoopRuntime.CurrentPhase == null)
|
||||
{
|
||||
Scheduler._enemyManager.BeginPhase(_phase, _spawnEntries);
|
||||
GameEntry.Event.Fire(
|
||||
Scheduler,
|
||||
CombatProcessEventArgs.Create(
|
||||
Scheduler._phaseLoopRuntime.DisplayPhaseIndex,
|
||||
Scheduler._phaseLoopRuntime.PhaseCount));
|
||||
GameEntry.Event.Fire(
|
||||
Scheduler,
|
||||
CombatEnemyHpRateChangedEventArgs.Create(
|
||||
ResolveEnemyHpRateMultiplier(
|
||||
Scheduler._phaseLoopRuntime.DisplayPhaseIndex,
|
||||
Scheduler._phaseLoopRuntime.PhaseCount)));
|
||||
|
||||
if (!Scheduler._nodeEnterFired)
|
||||
{
|
||||
Scheduler._nodeEnterFired = true;
|
||||
GameEntry.Event.Fire(Scheduler, NodeEnterEventArgs.Create());
|
||||
}
|
||||
|
||||
Log.Info(
|
||||
"CombatScheduler phase started. Level={0}, Phase={1}, EndType={2}, Entries={3}.",
|
||||
Scheduler._currentLevel != null ? Scheduler._currentLevel.Id : 0,
|
||||
Scheduler._phaseLoopRuntime.DisplayPhaseIndex,
|
||||
_phase.EndType,
|
||||
_spawnEntries != null ? _spawnEntries.Count : 0);
|
||||
Flow.EnterFailureFallback("CombatScheduler update failed. Current phase is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
Context.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
|
||||
if (Flow.ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory))
|
||||
{
|
||||
if (Scheduler._phaseLoopRuntime.CurrentPhase == null)
|
||||
{
|
||||
Scheduler.EnterFailureFallback("CombatScheduler update failed. Current phase is null.");
|
||||
return;
|
||||
}
|
||||
Flow.Scheduler.ChangeState(new CombatSettlementState(Context, Flow, reason, isVictory));
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler._phaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
Scheduler._enemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
|
||||
if (Scheduler.ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory))
|
||||
{
|
||||
Scheduler.ChangeState(new CombatSettlementState(Scheduler, reason, isVictory));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Scheduler._enemyManager.IsPhaseSpawnCompleted)
|
||||
{
|
||||
Scheduler.EnterWaitingForPhaseEnd();
|
||||
}
|
||||
if (Context.EnemyManager.IsPhaseSpawnCompleted)
|
||||
{
|
||||
Flow.EnterWaitingForPhaseEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-26
@@ -1,37 +1,38 @@
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatSettlementState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatSettlementState : CombatStateBase
|
||||
private readonly string _reason;
|
||||
private readonly bool _isVictory;
|
||||
|
||||
public CombatSettlementState(
|
||||
CombatSchedulerRuntimeContext context,
|
||||
CombatSchedulerFlowCoordinator flow,
|
||||
string reason,
|
||||
bool isVictory) : base(context, flow)
|
||||
{
|
||||
private readonly string _reason;
|
||||
private readonly bool _isVictory;
|
||||
_reason = reason;
|
||||
_isVictory = isVictory;
|
||||
}
|
||||
|
||||
public CombatSettlementState(CombatScheduler scheduler, string reason, bool isVictory) : base(scheduler)
|
||||
public override void OnEnter()
|
||||
{
|
||||
Context.EnemyManager.EndPhase();
|
||||
Context.EnemyManager.CleanupTrackedEnemies();
|
||||
Context.IsFinishAsVictory = _isVictory;
|
||||
Context.SettlementContext = Context.SettlementFlowService.BuildSettlementContext(
|
||||
_reason,
|
||||
_isVictory,
|
||||
Context.CurrentLevel,
|
||||
Context.EnemyManager.DefeatedEnemyCount,
|
||||
Context.CombatInRunResourceManager);
|
||||
if (Context.SettlementContext.ShouldOpenRewardSelection)
|
||||
{
|
||||
_reason = reason;
|
||||
_isVictory = isVictory;
|
||||
Flow.Scheduler.ChangeState(new CombatRewardSelectionState(Context, Flow));
|
||||
return;
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
Scheduler._enemyManager.EndPhase();
|
||||
Scheduler._enemyManager.CleanupTrackedEnemies();
|
||||
Scheduler._isFinishAsVictory = _isVictory;
|
||||
Scheduler._settlementContext = Scheduler._settlementFlowService.BuildSettlementContext(
|
||||
_reason,
|
||||
_isVictory,
|
||||
Scheduler._currentLevel,
|
||||
Scheduler._enemyManager.DefeatedEnemyCount,
|
||||
Scheduler._combatInRunResourceManager);
|
||||
if (Scheduler._settlementContext.ShouldOpenRewardSelection)
|
||||
{
|
||||
Scheduler.ChangeState(new CombatRewardSelectionState(Scheduler));
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler.ChangeState(new CombatFinishFormState(Scheduler));
|
||||
}
|
||||
Flow.Scheduler.ChangeState(new CombatFinishFormState(Context, Flow));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-23
@@ -1,35 +1,34 @@
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal abstract class CombatStateBase
|
||||
{
|
||||
private abstract class CombatStateBase
|
||||
protected CombatSchedulerRuntimeContext Context { get; }
|
||||
protected CombatSchedulerFlowCoordinator Flow { get; }
|
||||
|
||||
protected CombatStateBase(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
{
|
||||
protected CombatScheduler Scheduler { get; }
|
||||
Context = context;
|
||||
Flow = flow;
|
||||
}
|
||||
|
||||
protected CombatStateBase(CombatScheduler scheduler)
|
||||
{
|
||||
Scheduler = scheduler;
|
||||
}
|
||||
public virtual void OnInit()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnInit()
|
||||
{
|
||||
}
|
||||
public virtual void OnEnter()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnEnter()
|
||||
{
|
||||
}
|
||||
public virtual void OnExit()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnExit()
|
||||
{
|
||||
}
|
||||
public virtual void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
-35
@@ -1,46 +1,46 @@
|
||||
using GeometryTD.DataTable;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatWaitingForPhaseEndState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatWaitingForPhaseEndState : CombatStateBase
|
||||
public CombatWaitingForPhaseEndState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
{
|
||||
public CombatWaitingForPhaseEndState(CombatScheduler scheduler) : base(scheduler)
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_ = realElapseSeconds;
|
||||
|
||||
DRLevelPhase currentPhase = Context.PhaseLoopRuntime.CurrentPhase;
|
||||
if (currentPhase == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("CombatScheduler waiting phase failed. Current phase is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
|
||||
if (Flow.ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory))
|
||||
{
|
||||
_ = realElapseSeconds;
|
||||
|
||||
var currentPhase = Scheduler._phaseLoopRuntime.CurrentPhase;
|
||||
if (currentPhase == null)
|
||||
{
|
||||
Scheduler.EnterFailureFallback("CombatScheduler waiting phase failed. Current phase is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler._phaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
|
||||
if (Scheduler.ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory))
|
||||
{
|
||||
Scheduler.ChangeState(new CombatSettlementState(Scheduler, reason, isVictory));
|
||||
return;
|
||||
}
|
||||
|
||||
PhaseEndConditionContext context = new(
|
||||
currentPhase,
|
||||
Scheduler._phaseLoopRuntime.CurrentPhaseElapsed,
|
||||
Scheduler._enemyManager.IsPhaseSpawnCompleted,
|
||||
Scheduler._enemyManager.AliveEnemyCount,
|
||||
Scheduler._enemyManager.HasAliveBoss);
|
||||
IPhaseEndCondition endCondition = PhaseEndConditionFactory.Create(currentPhase.EndType);
|
||||
if (!endCondition.ShouldExit(context))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler.CompleteCurrentPhase();
|
||||
Flow.Scheduler.ChangeState(new CombatSettlementState(Context, Flow, reason, isVictory));
|
||||
return;
|
||||
}
|
||||
|
||||
PhaseEndConditionContext conditionContext = new(
|
||||
currentPhase,
|
||||
Context.PhaseLoopRuntime.CurrentPhaseElapsed,
|
||||
Context.EnemyManager.IsPhaseSpawnCompleted,
|
||||
Context.EnemyManager.AliveEnemyCount,
|
||||
Context.EnemyManager.HasAliveBoss);
|
||||
IPhaseEndCondition endCondition = PhaseEndConditionFactory.Create(currentPhase.EndType);
|
||||
if (!endCondition.ShouldExit(conditionContext))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Flow.CompleteCurrentPhase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-24
@@ -1,35 +1,33 @@
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler
|
||||
internal sealed class CombatWaitingForReturnState : CombatStateBase
|
||||
{
|
||||
private sealed class CombatWaitingForReturnState : CombatStateBase
|
||||
private bool _returnRequested;
|
||||
|
||||
public CombatWaitingForReturnState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
{
|
||||
private bool _returnRequested;
|
||||
}
|
||||
|
||||
public CombatWaitingForReturnState(CombatScheduler scheduler) : base(scheduler)
|
||||
public void RequestReturn()
|
||||
{
|
||||
_returnRequested = true;
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_ = elapseSeconds;
|
||||
_ = realElapseSeconds;
|
||||
|
||||
if (!_returnRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public void RequestReturn()
|
||||
{
|
||||
_returnRequested = true;
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_ = elapseSeconds;
|
||||
_ = realElapseSeconds;
|
||||
|
||||
if (!_returnRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler._loadSession.Cleanup();
|
||||
Scheduler.CloseCombatFinishForm();
|
||||
Scheduler.CloseRewardSelectForm();
|
||||
Scheduler.CompleteNormalCombatAndNotify(Scheduler._isFinishAsVictory);
|
||||
}
|
||||
Context.LoadSession.Cleanup();
|
||||
Flow.CloseCombatFinishForm();
|
||||
Flow.CloseRewardSelectForm();
|
||||
Flow.CompleteNormalCombatAndNotify(Context.IsFinishAsVictory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user