规范类命名
This commit is contained in:
parent
47ed27bebb
commit
548bc77ba6
|
|
@ -45,7 +45,7 @@ namespace GeometryTD.CustomComponent
|
|||
_currentMap = null;
|
||||
}
|
||||
|
||||
public bool StartLoading(DRLevel level, MapEntityLoadContext mapLoadContext, ICombatSchedulerHost schedulerHost, out string errorMessage)
|
||||
public bool StartLoading(DRLevel level, MapEntityLoadContext mapLoadContext, ICombatSchedulerPort schedulerPort, out string errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
if (_entity == null)
|
||||
|
|
@ -59,7 +59,7 @@ namespace GeometryTD.CustomComponent
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!TryOpenCombatInfoForm(schedulerHost, out errorMessage))
|
||||
if (!TryOpenCombatInfoForm(schedulerPort, out errorMessage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ namespace GeometryTD.CustomComponent
|
|||
return true;
|
||||
}
|
||||
|
||||
private bool TryOpenCombatInfoForm(ICombatSchedulerHost schedulerHost, out string errorMessage)
|
||||
private bool TryOpenCombatInfoForm(ICombatSchedulerPort schedulerPort, out string errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
if (_combatInfoFormUseCase == null)
|
||||
|
|
@ -267,9 +267,9 @@ namespace GeometryTD.CustomComponent
|
|||
}
|
||||
|
||||
_combatInfoFormUseCase.Configure(
|
||||
() => BuildCombatInfoFormRawData(schedulerHost),
|
||||
() => schedulerHost != null && schedulerHost.CanEndCombat && schedulerHost.TryEndCombatByPlayer(),
|
||||
() => schedulerHost != null && schedulerHost.TryDebugFail("Manual debug fail from CombatInfoForm."));
|
||||
() => BuildCombatInfoFormRawData(schedulerPort),
|
||||
() => schedulerPort != null && schedulerPort.CanEndCombat && schedulerPort.TryEndCombatByPlayer(),
|
||||
() => schedulerPort != null && schedulerPort.TryDebugFail("Manual debug fail from CombatInfoForm."));
|
||||
|
||||
int? serialId = GameEntry.UIRouter.OpenUI(UIFormType.CombatInfoForm);
|
||||
if (!serialId.HasValue)
|
||||
|
|
@ -283,26 +283,26 @@ namespace GeometryTD.CustomComponent
|
|||
return true;
|
||||
}
|
||||
|
||||
private static CombatInfoFormRawData BuildCombatInfoFormRawData(ICombatSchedulerHost schedulerHost)
|
||||
private static CombatInfoFormRawData BuildCombatInfoFormRawData(ICombatSchedulerPort schedulerPort)
|
||||
{
|
||||
if (schedulerHost == null)
|
||||
if (schedulerPort == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
DRLevel level = schedulerHost.CurrentLevel;
|
||||
DRLevel level = schedulerPort.CurrentLevel;
|
||||
LevelThemeType themeType = level != null ? level.LevelThemeType : LevelThemeType.None;
|
||||
int levelId = level != null ? level.Id : 0;
|
||||
int baseHpMax = level != null ? Mathf.Max(0, level.BaseHp) : 0;
|
||||
return CombatInfoFormUseCase.BuildRawData(
|
||||
themeType,
|
||||
levelId,
|
||||
schedulerHost.DisplayPhaseIndex,
|
||||
schedulerHost.PhaseCount,
|
||||
schedulerHost.CurrentCoin,
|
||||
schedulerHost.CurrentBaseHp,
|
||||
schedulerPort.DisplayPhaseIndex,
|
||||
schedulerPort.PhaseCount,
|
||||
schedulerPort.CurrentCoin,
|
||||
schedulerPort.CurrentBaseHp,
|
||||
baseHpMax,
|
||||
schedulerHost.CanEndCombat);
|
||||
schedulerPort.CanEndCombat);
|
||||
}
|
||||
|
||||
private void CloseCombatInfoForm()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using UnityEngine;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class CombatInRunResourceManager
|
||||
internal sealed class CombatRunResourceStore
|
||||
{
|
||||
private readonly List<TowerStatsData> _buildTowerStatsSnapshot = new();
|
||||
private readonly List<TowerItemData> _participantTowerSnapshot = new();
|
||||
|
|
@ -11,58 +11,58 @@ using UnityGameFramework.Runtime;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public partial class CombatScheduler : ICombatSchedulerHost
|
||||
public partial class CombatScheduler : ICombatSchedulerPort
|
||||
{
|
||||
private readonly CombatSchedulerRuntimeContext _context = new();
|
||||
private readonly CombatSchedulerFlowCoordinator _flowCoordinator;
|
||||
private readonly CombatSchedulerRuntime _runtime = new();
|
||||
private readonly CombatSchedulerCoordinator _coordinator;
|
||||
|
||||
private bool _initialized;
|
||||
|
||||
public CombatScheduler()
|
||||
{
|
||||
_flowCoordinator = new CombatSchedulerFlowCoordinator(this, _context);
|
||||
_coordinator = new CombatSchedulerCoordinator(this, _runtime);
|
||||
}
|
||||
|
||||
public bool IsRunning =>
|
||||
_context.CurrentState is CombatLoadingState or CombatRunningPhaseState or CombatWaitingForPhaseEndState;
|
||||
_runtime.CurrentState is CombatLoadingState or CombatRunningPhaseState or CombatWaitingForPhaseEndState;
|
||||
|
||||
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 bool IsCompleted => _runtime.IsCompleted;
|
||||
public DRLevel CurrentLevel => _runtime.CurrentLevel;
|
||||
public DRLevelPhase CurrentPhase => _runtime.PhaseLoopRuntime.CurrentPhase;
|
||||
public MapEntity CurrentMap => _runtime.LoadSession.CurrentMap;
|
||||
public int DisplayPhaseIndex => _runtime.PhaseLoopRuntime.DisplayPhaseIndex;
|
||||
public int PhaseCount => _runtime.PhaseLoopRuntime.PhaseCount;
|
||||
public bool CanEndCombat => _runtime.PhaseLoopRuntime.CanEndCombat;
|
||||
public int CurrentCoin => _runtime.CombatRunResourceStore.CurrentCoin;
|
||||
public int CurrentGold => _runtime.CombatRunResourceStore.CurrentGold;
|
||||
public int CurrentBaseHp => _runtime.CombatRunResourceStore.CurrentBaseHp;
|
||||
public int CurrentBuildTowerCount => _runtime.CombatRunResourceStore.CurrentBuildTowerCount;
|
||||
public int DefeatedEnemyCount => _runtime.EnemyManager.DefeatedEnemyCount;
|
||||
public int GainedCoin => _runtime.CombatRunResourceStore.GainedCoin;
|
||||
public int GainedGold => _runtime.CombatRunResourceStore.GainedGold;
|
||||
|
||||
public void OnInit(Action<bool> combatEndedCallback)
|
||||
{
|
||||
_context.CombatEndedCallback = combatEndedCallback;
|
||||
_runtime.CombatEndedCallback = combatEndedCallback;
|
||||
|
||||
if (!_initialized)
|
||||
{
|
||||
_context.Entity = GameEntry.Entity;
|
||||
_context.EventBridge.Bind(
|
||||
_runtime.Entity = GameEntry.Entity;
|
||||
_runtime.EventBridge.Bind(
|
||||
OnShowEntitySuccess,
|
||||
OnShowEntityFailure,
|
||||
OnHideEntityComplete,
|
||||
OnOpenUIFormSuccess,
|
||||
OnOpenUIFormFailure,
|
||||
OnCloseUIFormComplete);
|
||||
_context.EnemyManager.OnInit(this);
|
||||
_context.LoadSession.OnInit(_context.Entity);
|
||||
_flowCoordinator.EnsureCombatFinishFormUseCaseBound();
|
||||
_flowCoordinator.EnsureRewardSelectFormUseCaseBound();
|
||||
_runtime.EnemyManager.OnInit(this);
|
||||
_runtime.LoadSession.OnInit(_runtime.Entity);
|
||||
_coordinator.EnsureCombatFinishFormUseCaseBound();
|
||||
_coordinator.EnsureRewardSelectFormUseCaseBound();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
_flowCoordinator.ResetRuntime();
|
||||
_coordinator.ResetRuntime();
|
||||
}
|
||||
|
||||
public bool Start(
|
||||
|
|
@ -74,37 +74,37 @@ namespace GeometryTD.CustomComponent
|
|||
RunNodeType nodeType = RunNodeType.None,
|
||||
int sequenceIndex = -1)
|
||||
{
|
||||
if (!_initialized || _context.Entity == null)
|
||||
if (!_initialized || _runtime.Entity == null)
|
||||
{
|
||||
return _flowCoordinator.HandleStartFailure("CombatScheduler start failed. Runtime is not initialized.");
|
||||
return _coordinator.HandleStartFailure("CombatScheduler start failed. Runtime is not initialized.");
|
||||
}
|
||||
|
||||
if (level == null || phases == null || phases.Count <= 0)
|
||||
{
|
||||
return _flowCoordinator.HandleStartFailure("CombatScheduler start failed. Invalid level or phase data.");
|
||||
return _coordinator.HandleStartFailure("CombatScheduler start failed. Invalid level or phase data.");
|
||||
}
|
||||
|
||||
_flowCoordinator.CleanupAllCombatEntities();
|
||||
_flowCoordinator.CloseCombatFinishForm();
|
||||
_flowCoordinator.CloseRewardSelectForm();
|
||||
_flowCoordinator.CloseDialogForm();
|
||||
_context.EnemyManager.EndPhase();
|
||||
_context.EnemyManager.ResetCombatStats();
|
||||
_flowCoordinator.ResetRuntime();
|
||||
_context.IsFinishAsVictory = true;
|
||||
_coordinator.CleanupAllCombatEntities();
|
||||
_coordinator.CloseCombatFinishForm();
|
||||
_coordinator.CloseRewardSelectForm();
|
||||
_coordinator.CloseDialogForm();
|
||||
_runtime.EnemyManager.EndPhase();
|
||||
_runtime.EnemyManager.ResetCombatStats();
|
||||
_coordinator.ResetRuntime();
|
||||
_runtime.IsFinishAsVictory = true;
|
||||
|
||||
_context.CurrentLevel = level;
|
||||
_context.RunId = runId;
|
||||
_context.NodeId = nodeId;
|
||||
_context.NodeType = nodeType;
|
||||
_context.SequenceIndex = sequenceIndex;
|
||||
_context.CombatInRunResourceManager.InitializeForCombat(level);
|
||||
_runtime.CurrentLevel = level;
|
||||
_runtime.RunId = runId;
|
||||
_runtime.NodeId = nodeId;
|
||||
_runtime.NodeType = nodeType;
|
||||
_runtime.SequenceIndex = sequenceIndex;
|
||||
_runtime.CombatRunResourceStore.InitializeForCombat(level);
|
||||
for (int i = 0; i < phases.Count; i++)
|
||||
{
|
||||
DRLevelPhase phase = phases[i];
|
||||
if (phase != null)
|
||||
{
|
||||
_context.PhaseBuffer.Add(phase);
|
||||
_runtime.PhaseBuffer.Add(phase);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,27 +112,27 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
foreach (var pair in spawnEntriesByPhaseId)
|
||||
{
|
||||
_context.SpawnEntriesByPhaseId[pair.Key] = pair.Value;
|
||||
_runtime.SpawnEntriesByPhaseId[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
|
||||
_context.PhaseLoopRuntime.SetPhases(_context.PhaseBuffer);
|
||||
if (_context.PhaseLoopRuntime.PhaseCount <= 0)
|
||||
_runtime.PhaseLoopRuntime.SetPhases(_runtime.PhaseBuffer);
|
||||
if (_runtime.PhaseLoopRuntime.PhaseCount <= 0)
|
||||
{
|
||||
return _flowCoordinator.HandleStartFailure($"CombatScheduler start failed. Level '{level.Id}' has no phase data.");
|
||||
return _coordinator.HandleStartFailure($"CombatScheduler start failed. Level '{level.Id}' has no phase data.");
|
||||
}
|
||||
|
||||
ChangeState(new CombatLoadingState(_context, _flowCoordinator));
|
||||
ChangeState(new CombatLoadingState(_runtime, _coordinator));
|
||||
Log.Info(
|
||||
"CombatScheduler started. Level={0}, PhaseCount={1}.",
|
||||
_context.CurrentLevel.Id,
|
||||
_context.PhaseLoopRuntime.PhaseCount);
|
||||
_runtime.CurrentLevel.Id,
|
||||
_runtime.PhaseLoopRuntime.PhaseCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_context.CurrentState?.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
_runtime.CurrentState?.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
|
|
@ -142,33 +142,33 @@ namespace GeometryTD.CustomComponent
|
|||
return;
|
||||
}
|
||||
|
||||
_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;
|
||||
_context.CombatEndedCallback = null;
|
||||
_runtime.CurrentState?.OnExit();
|
||||
_runtime.CurrentState?.OnDestroy();
|
||||
_runtime.CurrentState = null;
|
||||
_coordinator.CleanupAllCombatEntities();
|
||||
_coordinator.CloseCombatFinishForm();
|
||||
_coordinator.CloseRewardSelectForm();
|
||||
_coordinator.CloseDialogForm();
|
||||
_runtime.EnemyManager.OnDestroy();
|
||||
_coordinator.ResetRuntime();
|
||||
_runtime.EventBridge.Unbind();
|
||||
_runtime.CombatFinishFormUseCase = null;
|
||||
_runtime.RewardSelectFormUseCase = null;
|
||||
_runtime.CombatEndedCallback = null;
|
||||
|
||||
_context.Entity = null;
|
||||
_runtime.Entity = null;
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
public bool TryEndCombatByPlayer()
|
||||
{
|
||||
if (_context.CurrentState is not CombatRunningPhaseState &&
|
||||
_context.CurrentState is not CombatWaitingForPhaseEndState)
|
||||
if (_runtime.CurrentState is not CombatRunningPhaseState &&
|
||||
_runtime.CurrentState is not CombatWaitingForPhaseEndState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _context.PhaseLoopRuntime.TryRequestEndCombat();
|
||||
return _runtime.PhaseLoopRuntime.TryRequestEndCombat();
|
||||
}
|
||||
|
||||
public void OnEnemyReachedBase(DREnemy enemy)
|
||||
|
|
@ -184,7 +184,7 @@ namespace GeometryTD.CustomComponent
|
|||
return;
|
||||
}
|
||||
|
||||
_flowCoordinator.ApplyBaseDamage(resolvedBaseDamage);
|
||||
_coordinator.ApplyBaseDamage(resolvedBaseDamage);
|
||||
}
|
||||
|
||||
public void OnEnemyDefeated(DREnemy enemy)
|
||||
|
|
@ -194,18 +194,18 @@ namespace GeometryTD.CustomComponent
|
|||
return;
|
||||
}
|
||||
|
||||
EnemyDropResolveContext context = new(
|
||||
EnemyDropContext context = new(
|
||||
enemy,
|
||||
_context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
_flowCoordinator.ResolveCurrentThemeType());
|
||||
EnemyDropResolveResult result = _context.EnemyDropResolver.Resolve(context);
|
||||
_context.CombatInRunResourceManager.AddEnemyDefeatedReward(result.Coin, result.Gold);
|
||||
_context.CombatInRunResourceManager.AddEnemyDefeatedLoot(result.LootItem);
|
||||
_runtime.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
_coordinator.ResolveCurrentThemeType());
|
||||
EnemyDropResult result = _runtime.EnemyDropResolver.Resolve(context);
|
||||
_runtime.CombatRunResourceStore.AddEnemyDefeatedReward(result.Coin, result.Gold);
|
||||
_runtime.CombatRunResourceStore.AddEnemyDefeatedLoot(result.LootItem);
|
||||
}
|
||||
|
||||
public bool OnCombatFinishReturnRequested()
|
||||
{
|
||||
if (_context.CurrentState is not CombatWaitingForReturnState waitingForReturnState)
|
||||
if (_runtime.CurrentState is not CombatWaitingForReturnState waitingForReturnState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -216,68 +216,68 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public bool TryConsumeCoin(int coin)
|
||||
{
|
||||
return _context.CombatInRunResourceManager.TryConsumeCoin(coin);
|
||||
return _runtime.CombatRunResourceStore.TryConsumeCoin(coin);
|
||||
}
|
||||
|
||||
public void AddCoin(int coin)
|
||||
{
|
||||
_context.CombatInRunResourceManager.AddCoin(coin);
|
||||
_runtime.CombatRunResourceStore.AddCoin(coin);
|
||||
}
|
||||
|
||||
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
|
||||
{
|
||||
return _context.CombatInRunResourceManager.TryGetBuildTowerStats(buildIndex, out stats);
|
||||
return _runtime.CombatRunResourceStore.TryGetBuildTowerStats(buildIndex, out stats);
|
||||
}
|
||||
|
||||
public bool TryDebugFail(string errorMessage)
|
||||
{
|
||||
if (_context.IsCompleted || _context.CurrentState == null || _context.CurrentState is CombatFailedState)
|
||||
if (_runtime.IsCompleted || _runtime.CurrentState == null || _runtime.CurrentState is CombatFailedState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_flowCoordinator.EnterFailureFallback(string.IsNullOrWhiteSpace(errorMessage)
|
||||
_coordinator.EnterFailureFallback(string.IsNullOrWhiteSpace(errorMessage)
|
||||
? "Manual debug fail."
|
||||
: errorMessage);
|
||||
return _context.CurrentState is CombatFailedState;
|
||||
return _runtime.CurrentState is CombatFailedState;
|
||||
}
|
||||
|
||||
void ICombatSchedulerHost.ChangeState(CombatStateBase nextState)
|
||||
void ICombatSchedulerPort.ChangeState(CombatStateBase nextState)
|
||||
{
|
||||
ChangeState(nextState);
|
||||
}
|
||||
|
||||
internal void ChangeState(CombatStateBase nextState)
|
||||
{
|
||||
if (ReferenceEquals(_context.CurrentState, nextState))
|
||||
if (ReferenceEquals(_runtime.CurrentState, nextState))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_context.CurrentState?.OnExit();
|
||||
_context.CurrentState?.OnDestroy();
|
||||
_context.CurrentState = nextState;
|
||||
_context.CurrentState?.OnInit();
|
||||
_context.CurrentState?.OnEnter();
|
||||
_runtime.CurrentState?.OnExit();
|
||||
_runtime.CurrentState?.OnDestroy();
|
||||
_runtime.CurrentState = nextState;
|
||||
_runtime.CurrentState?.OnInit();
|
||||
_runtime.CurrentState?.OnEnter();
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnShowEntitySuccess(ShowEntitySuccessEventArgs args)
|
||||
{
|
||||
var status = _context.LoadSession.HandleShowEntitySuccess(args, out string errorMessage);
|
||||
var status = _runtime.LoadSession.HandleShowEntitySuccess(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
_coordinator.EnterFailureFallback(errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == CombatLoadSession.EventHandleStatus.Succeeded)
|
||||
{
|
||||
MapEntity map = _context.LoadSession.CurrentMap;
|
||||
MapEntity map = _runtime.LoadSession.CurrentMap;
|
||||
Log.Info(
|
||||
"Map ready. LevelId={0}, PathCells={1}, FoundationCells={2}, Spawners={3}, House={4}.",
|
||||
_context.CurrentLevel != null ? _context.CurrentLevel.Id : 0,
|
||||
_runtime.CurrentLevel != null ? _runtime.CurrentLevel.Id : 0,
|
||||
map.PathCells.Count,
|
||||
map.FoundationCells.Count,
|
||||
map.Spawners.Length,
|
||||
|
|
@ -287,39 +287,39 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
private void OnShowEntityFailure(ShowEntityFailureEventArgs args)
|
||||
{
|
||||
var status = _context.LoadSession.HandleShowEntityFailure(args, out string errorMessage);
|
||||
var status = _runtime.LoadSession.HandleShowEntityFailure(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
_coordinator.EnterFailureFallback(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHideEntityComplete(HideEntityCompleteEventArgs args)
|
||||
{
|
||||
_context.LoadSession.HandleHideEntityComplete(args);
|
||||
_runtime.LoadSession.HandleHideEntityComplete(args);
|
||||
}
|
||||
|
||||
private void OnOpenUIFormSuccess(OpenUIFormSuccessEventArgs args)
|
||||
{
|
||||
var status = _context.LoadSession.HandleOpenUIFormSuccess(args, out string errorMessage);
|
||||
var status = _runtime.LoadSession.HandleOpenUIFormSuccess(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
_coordinator.EnterFailureFallback(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOpenUIFormFailure(OpenUIFormFailureEventArgs args)
|
||||
{
|
||||
var status = _context.LoadSession.HandleOpenUIFormFailure(args, out string errorMessage);
|
||||
var status = _runtime.LoadSession.HandleOpenUIFormFailure(args, out string errorMessage);
|
||||
if (status == CombatLoadSession.EventHandleStatus.Failed)
|
||||
{
|
||||
_flowCoordinator.EnterFailureFallback(errorMessage);
|
||||
_coordinator.EnterFailureFallback(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloseUIFormComplete(CloseUIFormCompleteEventArgs args)
|
||||
{
|
||||
_context.LoadSession.HandleCloseUIFormComplete(args);
|
||||
_runtime.LoadSession.HandleCloseUIFormComplete(args);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -9,21 +9,21 @@ using UnityGameFramework.Runtime;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class CombatSchedulerFlowCoordinator
|
||||
internal sealed class CombatSchedulerCoordinator
|
||||
{
|
||||
private readonly ICombatSchedulerHost _schedulerHost;
|
||||
private readonly CombatSchedulerRuntimeContext _context;
|
||||
public ICombatSchedulerHost Host => _schedulerHost;
|
||||
private readonly ICombatSchedulerPort _schedulerPort;
|
||||
private readonly CombatSchedulerRuntime _runtime;
|
||||
public ICombatSchedulerPort Port => _schedulerPort;
|
||||
|
||||
public CombatSchedulerFlowCoordinator(ICombatSchedulerHost schedulerHost, CombatSchedulerRuntimeContext context)
|
||||
public CombatSchedulerCoordinator(ICombatSchedulerPort schedulerPort, CombatSchedulerRuntime runtime)
|
||||
{
|
||||
_schedulerHost = schedulerHost;
|
||||
_context = context;
|
||||
_schedulerPort = schedulerPort;
|
||||
_runtime = runtime;
|
||||
}
|
||||
|
||||
public void ChangeState(CombatStateBase nextState)
|
||||
{
|
||||
_schedulerHost.ChangeState(nextState);
|
||||
_schedulerPort.ChangeState(nextState);
|
||||
}
|
||||
|
||||
public int ResolveEnemyHpRateMultiplier(int displayPhaseIndex, int phaseCount)
|
||||
|
|
@ -44,40 +44,40 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public void ResetRuntime()
|
||||
{
|
||||
_context.CurrentState = null;
|
||||
_context.PhaseBuffer.Clear();
|
||||
_context.SpawnEntriesByPhaseId.Clear();
|
||||
_context.PhaseLoopRuntime.Reset();
|
||||
_context.LoadSession.Reset();
|
||||
_context.CombatInRunResourceManager.Reset();
|
||||
_context.EnemyDropResolver.Reset();
|
||||
_context.SettlementContext = null;
|
||||
_context.CurrentLevel = null;
|
||||
_context.IsFinishAsVictory = true;
|
||||
_context.IsCompleted = false;
|
||||
_context.NodeEnterFired = false;
|
||||
_context.RunId = null;
|
||||
_context.NodeId = 0;
|
||||
_context.NodeType = RunNodeType.None;
|
||||
_context.SequenceIndex = -1;
|
||||
_runtime.CurrentState = null;
|
||||
_runtime.PhaseBuffer.Clear();
|
||||
_runtime.SpawnEntriesByPhaseId.Clear();
|
||||
_runtime.PhaseLoopRuntime.Reset();
|
||||
_runtime.LoadSession.Reset();
|
||||
_runtime.CombatRunResourceStore.Reset();
|
||||
_runtime.EnemyDropResolver.Reset();
|
||||
_runtime.SettlementContext = null;
|
||||
_runtime.CurrentLevel = null;
|
||||
_runtime.IsFinishAsVictory = true;
|
||||
_runtime.IsCompleted = false;
|
||||
_runtime.NodeEnterFired = false;
|
||||
_runtime.RunId = null;
|
||||
_runtime.NodeId = 0;
|
||||
_runtime.NodeType = RunNodeType.None;
|
||||
_runtime.SequenceIndex = -1;
|
||||
}
|
||||
|
||||
public void CleanupAllCombatEntities()
|
||||
{
|
||||
_context.LoadSession.Cleanup();
|
||||
_context.EnemyManager.CleanupTrackedEnemies();
|
||||
_runtime.LoadSession.Cleanup();
|
||||
_runtime.EnemyManager.CleanupTrackedEnemies();
|
||||
}
|
||||
|
||||
public void EnsureCombatFinishFormUseCaseBound()
|
||||
{
|
||||
_context.CombatFinishFormUseCase ??= new CombatFinishFormUseCase(_schedulerHost);
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatFinishForm, _context.CombatFinishFormUseCase);
|
||||
_runtime.CombatFinishFormUseCase ??= new CombatFinishFormUseCase(_schedulerPort);
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatFinishForm, _runtime.CombatFinishFormUseCase);
|
||||
}
|
||||
|
||||
public void EnsureRewardSelectFormUseCaseBound()
|
||||
{
|
||||
_context.RewardSelectFormUseCase ??= new RewardSelectFormUseCase();
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.RewardSelectForm, _context.RewardSelectFormUseCase);
|
||||
_runtime.RewardSelectFormUseCase ??= new RewardSelectFormUseCase();
|
||||
GameEntry.UIRouter.BindUIUseCase(UIFormType.RewardSelectForm, _runtime.RewardSelectFormUseCase);
|
||||
}
|
||||
|
||||
public void OpenCombatFailureDialog(string errorMessage)
|
||||
|
|
@ -96,30 +96,30 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public bool TryBeginNextPhase()
|
||||
{
|
||||
if (!_context.PhaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase))
|
||||
if (!_runtime.PhaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase))
|
||||
{
|
||||
_schedulerHost.ChangeState(new CombatSettlementState(_context, this, true));
|
||||
_schedulerPort.ChangeState(new CombatSettlementState(_runtime, this, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
_context.SpawnEntriesByPhaseId.TryGetValue(nextPhase.Id, out IReadOnlyList<DRLevelSpawnEntry> spawnEntries);
|
||||
_schedulerHost.ChangeState(new CombatRunningPhaseState(_context, this, nextPhase, spawnEntries));
|
||||
_runtime.SpawnEntriesByPhaseId.TryGetValue(nextPhase.Id, out IReadOnlyList<DRLevelSpawnEntry> spawnEntries);
|
||||
_schedulerPort.ChangeState(new CombatRunningPhaseState(_runtime, this, nextPhase, spawnEntries));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void EnterWaitingForPhaseEnd()
|
||||
{
|
||||
_schedulerHost.ChangeState(new CombatWaitingForPhaseEndState(_context, this));
|
||||
_schedulerPort.ChangeState(new CombatWaitingForPhaseEndState(_runtime, this));
|
||||
}
|
||||
|
||||
public void CompleteCurrentPhase()
|
||||
{
|
||||
_context.EnemyManager.EndPhase();
|
||||
_runtime.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);
|
||||
_runtime.CurrentLevel != null ? _runtime.CurrentLevel.Id : 0,
|
||||
_runtime.PhaseLoopRuntime.CurrentPhase != null ? _runtime.PhaseLoopRuntime.CurrentPhase.Id : 0,
|
||||
_runtime.PhaseLoopRuntime.CurrentPhaseElapsed);
|
||||
|
||||
TryBeginNextPhase();
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ namespace GeometryTD.CustomComponent
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_context.PhaseLoopRuntime.IsEndCombatRequested)
|
||||
if (_runtime.PhaseLoopRuntime.IsEndCombatRequested)
|
||||
{
|
||||
isVictory = true;
|
||||
return true;
|
||||
|
|
@ -144,30 +144,30 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public void OnFullBaseHpRewardSelected(RewardSelectItemRawData selectedReward)
|
||||
{
|
||||
if (_context.CurrentState is not CombatRewardSelectionState || _context.SettlementContext == null)
|
||||
if (_runtime.CurrentState is not CombatRewardSelectionState || _runtime.SettlementContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_context.SettlementFlowService.ApplySelectedReward(_context.SettlementContext, selectedReward);
|
||||
_schedulerHost.ChangeState(new CombatFinishFormState(_context, this));
|
||||
_runtime.CombatSettlementService.ApplySelectedReward(_runtime.SettlementContext, selectedReward);
|
||||
_schedulerPort.ChangeState(new CombatFinishFormState(_runtime, this));
|
||||
}
|
||||
|
||||
public void OnFullBaseHpRewardGiveUp()
|
||||
{
|
||||
if (_context.CurrentState is not CombatRewardSelectionState || _context.SettlementContext == null)
|
||||
if (_runtime.CurrentState is not CombatRewardSelectionState || _runtime.SettlementContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_schedulerHost.ChangeState(new CombatFinishFormState(_context, this));
|
||||
_schedulerPort.ChangeState(new CombatFinishFormState(_runtime, this));
|
||||
}
|
||||
|
||||
public LevelThemeType ResolveCurrentThemeType()
|
||||
{
|
||||
if (_context.CurrentLevel != null)
|
||||
if (_runtime.CurrentLevel != null)
|
||||
{
|
||||
return _context.CurrentLevel.LevelThemeType;
|
||||
return _runtime.CurrentLevel.LevelThemeType;
|
||||
}
|
||||
|
||||
return LevelThemeType.None;
|
||||
|
|
@ -175,12 +175,12 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public int ApplyBaseDamage(int damage)
|
||||
{
|
||||
return _context.CombatInRunResourceManager.ApplyBaseDamage(damage);
|
||||
return _runtime.CombatRunResourceStore.ApplyBaseDamage(damage);
|
||||
}
|
||||
|
||||
public int GetCurrentBaseHp()
|
||||
{
|
||||
return Mathf.Max(0, _context.CombatInRunResourceManager.CurrentBaseHp);
|
||||
return Mathf.Max(0, _runtime.CombatRunResourceStore.CurrentBaseHp);
|
||||
}
|
||||
|
||||
public void CloseCombatFinishForm()
|
||||
|
|
@ -204,10 +204,10 @@ namespace GeometryTD.CustomComponent
|
|||
GameEntry.Event.Fire(
|
||||
this,
|
||||
NodeCompleteEventArgs.Create(
|
||||
_context.RunId,
|
||||
_context.NodeId,
|
||||
_context.NodeType,
|
||||
_context.SequenceIndex,
|
||||
_runtime.RunId,
|
||||
_runtime.NodeId,
|
||||
_runtime.NodeType,
|
||||
_runtime.SequenceIndex,
|
||||
succeeded,
|
||||
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||
}
|
||||
|
|
@ -225,7 +225,7 @@ namespace GeometryTD.CustomComponent
|
|||
public bool HandleStartFailure(string errorMessage)
|
||||
{
|
||||
Log.Warning("{0}", errorMessage);
|
||||
_context.EnemyManager.EndPhase();
|
||||
_runtime.EnemyManager.EndPhase();
|
||||
CleanupAllCombatEntities();
|
||||
CloseCombatFinishForm();
|
||||
CloseRewardSelectForm();
|
||||
|
|
@ -236,18 +236,18 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public void EnterFailureFallback(string errorMessage)
|
||||
{
|
||||
if (_context.CurrentState is CombatFailedState || _context.IsCompleted)
|
||||
if (_runtime.CurrentState is CombatFailedState || _runtime.IsCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_schedulerHost.ChangeState(new CombatFailedState(_context, this, errorMessage));
|
||||
_schedulerPort.ChangeState(new CombatFailedState(_runtime, this, errorMessage));
|
||||
}
|
||||
|
||||
public void OnCombatFailureDialogConfirmed(object userData)
|
||||
{
|
||||
_ = userData;
|
||||
if (_context.CurrentState is not CombatFailedState || _context.IsCompleted)
|
||||
if (_runtime.CurrentState is not CombatFailedState || _runtime.IsCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -257,10 +257,10 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
private void CompleteCombat(bool succeeded)
|
||||
{
|
||||
_context.IsCompleted = true;
|
||||
_context.CurrentState = null;
|
||||
_context.CombatInRunResourceManager.MarkCombatEnded();
|
||||
_context.CombatEndedCallback?.Invoke(succeeded);
|
||||
_runtime.IsCompleted = true;
|
||||
_runtime.CurrentState = null;
|
||||
_runtime.CombatRunResourceStore.MarkCombatEnded();
|
||||
_runtime.CombatEndedCallback?.Invoke(succeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ using UnityGameFramework.Runtime;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class CombatSchedulerRuntimeContext
|
||||
internal sealed class CombatSchedulerRuntime
|
||||
{
|
||||
public List<DRLevelPhase> PhaseBuffer { get; } = new();
|
||||
public Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> SpawnEntriesByPhaseId { get; } = new();
|
||||
|
|
@ -16,9 +16,9 @@ namespace GeometryTD.CustomComponent
|
|||
public PhaseLoopRuntime PhaseLoopRuntime { get; } = new();
|
||||
public CombatLoadSession LoadSession { get; } = new();
|
||||
public CombatEventBridge EventBridge { get; } = new();
|
||||
public CombatInRunResourceManager CombatInRunResourceManager { get; } = new();
|
||||
public CombatRunResourceStore CombatRunResourceStore { get; } = new();
|
||||
public EnemyDropResolver EnemyDropResolver { get; } = new();
|
||||
public CombatSettlementFlowService SettlementFlowService { get; } = new();
|
||||
public CombatSettlementService CombatSettlementService { get; } = new();
|
||||
|
||||
public EntityComponent Entity { get; set; }
|
||||
public DRLevel CurrentLevel { get; set; }
|
||||
|
|
@ -4,12 +4,12 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
internal sealed class CombatSettlementContext
|
||||
{
|
||||
public CombatSettlementFlowState Flow { get; } = new();
|
||||
public CombatSettlementFlags Flags { get; } = new();
|
||||
public CombatSettlementResult Result { get; } = new();
|
||||
public CombatSettlementSummary Summary { get; } = new();
|
||||
}
|
||||
|
||||
internal sealed class CombatSettlementFlowState
|
||||
internal sealed class CombatSettlementFlags
|
||||
{
|
||||
public bool ShouldOpenRewardSelection;
|
||||
public bool DidEnterRewardSelection;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using UnityGameFramework.Runtime;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class CombatSettlementFlowService
|
||||
internal sealed class CombatSettlementService
|
||||
{
|
||||
private const int RewardSelectDisplayCount = 3;
|
||||
private const float FullBaseHpGoldBonusRate = 0.3f;
|
||||
|
|
@ -21,13 +21,13 @@ namespace GeometryTD.CustomComponent
|
|||
bool isVictory,
|
||||
DRLevel currentLevel,
|
||||
int defeatedEnemyCount,
|
||||
CombatInRunResourceManager resourceManager)
|
||||
CombatRunResourceStore resourceStore)
|
||||
{
|
||||
bool shouldOpenFullBaseHpRewardSelect = false;
|
||||
ResolveSettlementByBaseHp(
|
||||
isVictory,
|
||||
currentLevel,
|
||||
resourceManager,
|
||||
resourceStore,
|
||||
out int currentBaseHp,
|
||||
out int maxBaseHp,
|
||||
out int levelRewardGold,
|
||||
|
|
@ -40,19 +40,19 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
};
|
||||
settlementContext.Result.IsVictory = isVictory;
|
||||
settlementContext.Result.FinalCoin = Mathf.Max(0, resourceManager != null ? resourceManager.CurrentCoin : 0);
|
||||
settlementContext.Result.FinalCoin = Mathf.Max(0, resourceStore != null ? resourceStore.CurrentCoin : 0);
|
||||
settlementContext.Result.FinalBaseHp = currentBaseHp;
|
||||
settlementContext.Result.MaxBaseHp = maxBaseHp;
|
||||
settlementContext.Result.DefeatedEnemyCount = Mathf.Max(0, defeatedEnemyCount);
|
||||
settlementContext.Result.GainedGold = Mathf.Max(0, resourceManager != null ? resourceManager.GainedGold : 0);
|
||||
settlementContext.Result.RewardInventory = resourceManager != null
|
||||
? resourceManager.GetRewardInventorySnapshot()
|
||||
settlementContext.Result.GainedGold = Mathf.Max(0, resourceStore != null ? resourceStore.GainedGold : 0);
|
||||
settlementContext.Result.RewardInventory = resourceStore != null
|
||||
? resourceStore.GetRewardInventorySnapshot()
|
||||
: new BackpackInventoryData();
|
||||
settlementContext.Result.Penalty.ShouldApplyLowBaseHpPenalty = appliedLowBaseHpPenalty;
|
||||
settlementContext.Result.Penalty.LowBaseHpEndurancePenaltyValue =
|
||||
appliedLowBaseHpPenalty ? LowBaseHpTowerEndurancePenalty : 0f;
|
||||
settlementContext.Flow.ShouldOpenRewardSelection = shouldOpenFullBaseHpRewardSelect;
|
||||
settlementContext.Flow.DidEnterRewardSelection = false;
|
||||
settlementContext.Flags.ShouldOpenRewardSelection = shouldOpenFullBaseHpRewardSelect;
|
||||
settlementContext.Flags.DidEnterRewardSelection = false;
|
||||
settlementContext.Summary.DefeatedEnemyCount = settlementContext.Result.DefeatedEnemyCount;
|
||||
settlementContext.Summary.GainedGold = settlementContext.Result.GainedGold;
|
||||
settlementContext.Summary.RewardInventory = settlementContext.Result.RewardInventory;
|
||||
|
|
@ -72,7 +72,7 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public void CommitSettlementInventory(CombatSettlementContext settlementContext)
|
||||
{
|
||||
if (settlementContext == null || settlementContext.Flow.IsCommitted)
|
||||
if (settlementContext == null || settlementContext.Flags.IsCommitted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ namespace GeometryTD.CustomComponent
|
|||
settlementContext.Result.RewardInventory = rewardInventory;
|
||||
settlementContext.Summary.RewardInventory = rewardInventory;
|
||||
settlementContext.Result.Penalty.AffectedTowerCount = ApplyDeferredSettlementPenalty(settlementContext);
|
||||
settlementContext.Flow.IsCommitted = true;
|
||||
settlementContext.Flags.IsCommitted = true;
|
||||
}
|
||||
|
||||
public bool TryPrepareRewardSelection(
|
||||
|
|
@ -105,7 +105,7 @@ namespace GeometryTD.CustomComponent
|
|||
RewardSelectDisplayCount);
|
||||
if (candidateItems == null || candidateItems.Count <= 0)
|
||||
{
|
||||
settlementContext.Flow.ShouldOpenRewardSelection = false;
|
||||
settlementContext.Flags.ShouldOpenRewardSelection = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
if (rewardPool.Count <= 0)
|
||||
{
|
||||
settlementContext.Flow.ShouldOpenRewardSelection = false;
|
||||
settlementContext.Flags.ShouldOpenRewardSelection = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -139,11 +139,11 @@ namespace GeometryTD.CustomComponent
|
|||
RewardSelectFormRawData rawData = rewardSelectFormUseCase.CreateInitialModel();
|
||||
if (rawData == null || rawData.RewardItems == null || rawData.RewardItems.Length <= 0)
|
||||
{
|
||||
settlementContext.Flow.ShouldOpenRewardSelection = false;
|
||||
settlementContext.Flags.ShouldOpenRewardSelection = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
settlementContext.Flow.DidEnterRewardSelection = true;
|
||||
settlementContext.Flags.DidEnterRewardSelection = true;
|
||||
GameEntry.UIRouter.OpenUI(UIFormType.RewardSelectForm, rawData);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -175,7 +175,7 @@ namespace GeometryTD.CustomComponent
|
|||
private static void ResolveSettlementByBaseHp(
|
||||
bool isVictory,
|
||||
DRLevel currentLevel,
|
||||
CombatInRunResourceManager resourceManager,
|
||||
CombatRunResourceStore resourceStore,
|
||||
out int currentBaseHp,
|
||||
out int maxBaseHp,
|
||||
out int levelRewardGold,
|
||||
|
|
@ -184,8 +184,8 @@ namespace GeometryTD.CustomComponent
|
|||
out bool appliedLowBaseHpPenalty,
|
||||
out bool shouldOpenFullBaseHpRewardSelect)
|
||||
{
|
||||
currentBaseHp = Mathf.Max(0, resourceManager != null ? resourceManager.CurrentBaseHp : 0);
|
||||
maxBaseHp = resourceManager != null ? Mathf.Max(0, resourceManager.MaxBaseHp) : 0;
|
||||
currentBaseHp = Mathf.Max(0, resourceStore != null ? resourceStore.CurrentBaseHp : 0);
|
||||
maxBaseHp = resourceStore != null ? Mathf.Max(0, resourceStore.MaxBaseHp) : 0;
|
||||
if (maxBaseHp > 0)
|
||||
{
|
||||
currentBaseHp = Mathf.Clamp(currentBaseHp, 0, maxBaseHp);
|
||||
|
|
@ -197,7 +197,7 @@ namespace GeometryTD.CustomComponent
|
|||
appliedLowBaseHpPenalty = false;
|
||||
shouldOpenFullBaseHpRewardSelect = false;
|
||||
|
||||
if (!isVictory || resourceManager == null)
|
||||
if (!isVictory || resourceStore == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -220,10 +220,10 @@ namespace GeometryTD.CustomComponent
|
|||
}
|
||||
}
|
||||
|
||||
int goldForBonusCalculation = Mathf.Max(0, resourceManager.GainedGold) + levelRewardGold;
|
||||
int goldForBonusCalculation = Mathf.Max(0, resourceStore.GainedGold) + levelRewardGold;
|
||||
bonusGold = bonusRate > 0f ? Mathf.FloorToInt(goldForBonusCalculation * bonusRate) : 0;
|
||||
int settlementGold = levelRewardGold + bonusGold;
|
||||
resourceManager.AddSettlementGold(settlementGold);
|
||||
resourceStore.AddSettlementGold(settlementGold);
|
||||
}
|
||||
|
||||
private static int ApplyDeferredSettlementPenalty(CombatSettlementContext settlementContext)
|
||||
|
|
@ -7,9 +7,9 @@ namespace GeometryTD.CustomComponent
|
|||
private readonly string _errorMessage;
|
||||
|
||||
public CombatFailedState(
|
||||
CombatSchedulerRuntimeContext context,
|
||||
CombatSchedulerFlowCoordinator flow,
|
||||
string errorMessage) : base(context, flow)
|
||||
CombatSchedulerRuntime runtime,
|
||||
CombatSchedulerCoordinator coordinator,
|
||||
string errorMessage) : base(runtime, coordinator)
|
||||
{
|
||||
_errorMessage = errorMessage;
|
||||
}
|
||||
|
|
@ -18,17 +18,17 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
Log.Error(
|
||||
"CombatScheduler failed. LevelId={0}, {1}",
|
||||
Context.CurrentLevel != null ? Context.CurrentLevel.Id : 0,
|
||||
Runtime.CurrentLevel != null ? Runtime.CurrentLevel.Id : 0,
|
||||
_errorMessage);
|
||||
Context.EnemyManager.EndPhase();
|
||||
Flow.CloseCombatFinishForm();
|
||||
Flow.CloseRewardSelectForm();
|
||||
Flow.OpenCombatFailureDialog(_errorMessage);
|
||||
Runtime.EnemyManager.EndPhase();
|
||||
Coordinator.CloseCombatFinishForm();
|
||||
Coordinator.CloseRewardSelectForm();
|
||||
Coordinator.OpenCombatFailureDialog(_errorMessage);
|
||||
}
|
||||
|
||||
public override void OnExit()
|
||||
{
|
||||
Flow.CloseDialogForm();
|
||||
Coordinator.CloseDialogForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,24 +2,24 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
internal sealed class CombatFinishFormState : CombatStateBase
|
||||
{
|
||||
public CombatFinishFormState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
public CombatFinishFormState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
|
||||
: base(runtime, coordinator)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (Context.SettlementContext == null)
|
||||
if (Runtime.SettlementContext == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("Combat finish form failed. Settlement context is missing.");
|
||||
Coordinator.EnterFailureFallback("Combat finish form failed. Settlement context is missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
Flow.EnsureCombatFinishFormUseCaseBound();
|
||||
Context.SettlementFlowService.OpenCombatFinishForm(
|
||||
Context.SettlementContext,
|
||||
Context.CombatFinishFormUseCase);
|
||||
Flow.ChangeState(new CombatWaitingForReturnState(Context, Flow));
|
||||
Coordinator.EnsureCombatFinishFormUseCaseBound();
|
||||
Runtime.CombatSettlementService.OpenCombatFinishForm(
|
||||
Runtime.SettlementContext,
|
||||
Runtime.CombatFinishFormUseCase);
|
||||
Coordinator.ChangeState(new CombatWaitingForReturnState(Runtime, Coordinator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,23 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
internal sealed class CombatLoadingState : CombatStateBase
|
||||
{
|
||||
public CombatLoadingState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
public CombatLoadingState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
|
||||
: base(runtime, coordinator)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (Context.CurrentLevel == null)
|
||||
if (Runtime.CurrentLevel == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("Combat loading failed. Current level is null.");
|
||||
Coordinator.EnterFailureFallback("Combat loading failed. Current level is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
MapEntityLoadContext mapLoadContext = BuildMapLoadContext();
|
||||
if (!Context.LoadSession.StartLoading(Context.CurrentLevel, mapLoadContext, Flow.Host, out string errorMessage))
|
||||
if (!Runtime.LoadSession.StartLoading(Runtime.CurrentLevel, mapLoadContext, Coordinator.Port, out string errorMessage))
|
||||
{
|
||||
Flow.EnterFailureFallback($"Combat loading failed. {errorMessage}");
|
||||
Coordinator.EnterFailureFallback($"Combat loading failed. {errorMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,20 +33,20 @@ namespace GeometryTD.CustomComponent
|
|||
_ = elapseSeconds;
|
||||
_ = realElapseSeconds;
|
||||
|
||||
if (!Context.LoadSession.IsReady)
|
||||
if (!Runtime.LoadSession.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Flow.TryBeginNextPhase();
|
||||
Coordinator.TryBeginNextPhase();
|
||||
}
|
||||
|
||||
private MapEntityLoadContext BuildMapLoadContext()
|
||||
{
|
||||
List<TowerStatsData> buildTowerStatsSnapshot = new();
|
||||
for (int i = 0; i < Context.CombatInRunResourceManager.CurrentBuildTowerCount; i++)
|
||||
for (int i = 0; i < Runtime.CombatRunResourceStore.CurrentBuildTowerCount; i++)
|
||||
{
|
||||
if (Context.CombatInRunResourceManager.TryGetBuildTowerStats(i, out TowerStatsData stats) &&
|
||||
if (Runtime.CombatRunResourceStore.TryGetBuildTowerStats(i, out TowerStatsData stats) &&
|
||||
stats != null)
|
||||
{
|
||||
buildTowerStatsSnapshot.Add(stats);
|
||||
|
|
@ -56,16 +56,16 @@ namespace GeometryTD.CustomComponent
|
|||
MapData mapData = new MapData(
|
||||
entityId: 0,
|
||||
typeId: 0,
|
||||
levelId: Context.CurrentLevel.Id,
|
||||
levelId: Runtime.CurrentLevel.Id,
|
||||
position: Vector3.zero,
|
||||
initialCoin: Context.CombatInRunResourceManager.CurrentCoin,
|
||||
initialCoin: Runtime.CombatRunResourceStore.CurrentCoin,
|
||||
buildTowerStatsSnapshot: buildTowerStatsSnapshot,
|
||||
inventorySnapshot: Context.CombatInRunResourceManager.GetCombatInventorySnapshot(),
|
||||
participantTowerSnapshot: Context.CombatInRunResourceManager.GetParticipantTowerSnapshot());
|
||||
inventorySnapshot: Runtime.CombatRunResourceStore.GetCombatInventorySnapshot(),
|
||||
participantTowerSnapshot: Runtime.CombatRunResourceStore.GetParticipantTowerSnapshot());
|
||||
return new MapEntityLoadContext(
|
||||
mapData,
|
||||
Context.CombatInRunResourceManager.TryConsumeCoin,
|
||||
Context.CombatInRunResourceManager.AddCoin);
|
||||
Runtime.CombatRunResourceStore.TryConsumeCoin,
|
||||
Runtime.CombatRunResourceStore.AddCoin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,36 +2,36 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
internal sealed class CombatRewardSelectionState : CombatStateBase
|
||||
{
|
||||
public CombatRewardSelectionState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
public CombatRewardSelectionState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
|
||||
: base(runtime, coordinator)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (Context.SettlementContext == null)
|
||||
if (Runtime.SettlementContext == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("Combat reward selection failed. Settlement context is missing.");
|
||||
Coordinator.EnterFailureFallback("Combat reward selection failed. Settlement context is missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
Flow.EnsureRewardSelectFormUseCaseBound();
|
||||
if (!Context.SettlementFlowService.TryPrepareRewardSelection(
|
||||
Context.SettlementContext,
|
||||
Context.EnemyDropResolver,
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Flow.ResolveCurrentThemeType(),
|
||||
Context.RewardSelectFormUseCase,
|
||||
Flow.OnFullBaseHpRewardSelected,
|
||||
Flow.OnFullBaseHpRewardGiveUp))
|
||||
Coordinator.EnsureRewardSelectFormUseCaseBound();
|
||||
if (!Runtime.CombatSettlementService.TryPrepareRewardSelection(
|
||||
Runtime.SettlementContext,
|
||||
Runtime.EnemyDropResolver,
|
||||
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Coordinator.ResolveCurrentThemeType(),
|
||||
Runtime.RewardSelectFormUseCase,
|
||||
Coordinator.OnFullBaseHpRewardSelected,
|
||||
Coordinator.OnFullBaseHpRewardGiveUp))
|
||||
{
|
||||
Flow.ChangeState(new CombatFinishFormState(Context, Flow));
|
||||
Coordinator.ChangeState(new CombatFinishFormState(Runtime, Coordinator));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnExit()
|
||||
{
|
||||
Flow.CloseRewardSelectForm();
|
||||
Coordinator.CloseRewardSelectForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ namespace GeometryTD.CustomComponent
|
|||
private readonly IReadOnlyList<DRLevelSpawnEntry> _spawnEntries;
|
||||
|
||||
public CombatRunningPhaseState(
|
||||
CombatSchedulerRuntimeContext context,
|
||||
CombatSchedulerFlowCoordinator flow,
|
||||
CombatSchedulerRuntime runtime,
|
||||
CombatSchedulerCoordinator coordinator,
|
||||
DRLevelPhase phase,
|
||||
IReadOnlyList<DRLevelSpawnEntry> spawnEntries) : base(context, flow)
|
||||
IReadOnlyList<DRLevelSpawnEntry> spawnEntries) : base(runtime, coordinator)
|
||||
{
|
||||
_phase = phase;
|
||||
_spawnEntries = spawnEntries;
|
||||
|
|
@ -22,59 +22,59 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
public override void OnEnter()
|
||||
{
|
||||
Context.EnemyManager.BeginPhase(_phase, _spawnEntries);
|
||||
Runtime.EnemyManager.BeginPhase(_phase, _spawnEntries);
|
||||
GameEntry.Event.Fire(
|
||||
Flow,
|
||||
Coordinator,
|
||||
CombatProcessEventArgs.Create(
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Context.PhaseLoopRuntime.PhaseCount));
|
||||
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Runtime.PhaseLoopRuntime.PhaseCount));
|
||||
GameEntry.Event.Fire(
|
||||
Flow,
|
||||
Coordinator,
|
||||
CombatEnemyHpRateChangedEventArgs.Create(
|
||||
Flow.ResolveEnemyHpRateMultiplier(
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Context.PhaseLoopRuntime.PhaseCount)));
|
||||
Coordinator.ResolveEnemyHpRateMultiplier(
|
||||
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Runtime.PhaseLoopRuntime.PhaseCount)));
|
||||
|
||||
if (!Context.NodeEnterFired)
|
||||
if (!Runtime.NodeEnterFired)
|
||||
{
|
||||
Context.NodeEnterFired = true;
|
||||
Runtime.NodeEnterFired = true;
|
||||
GameEntry.Event.Fire(
|
||||
Flow,
|
||||
Coordinator,
|
||||
NodeEnterEventArgs.Create(
|
||||
Context.RunId,
|
||||
Context.NodeId,
|
||||
Context.NodeType,
|
||||
Context.SequenceIndex));
|
||||
Runtime.RunId,
|
||||
Runtime.NodeId,
|
||||
Runtime.NodeType,
|
||||
Runtime.SequenceIndex));
|
||||
}
|
||||
|
||||
Log.Info(
|
||||
"CombatScheduler phase started. Level={0}, Phase={1}, EndType={2}, Entries={3}.",
|
||||
Context.CurrentLevel != null ? Context.CurrentLevel.Id : 0,
|
||||
Context.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Runtime.CurrentLevel != null ? Runtime.CurrentLevel.Id : 0,
|
||||
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
_phase.EndType,
|
||||
_spawnEntries != null ? _spawnEntries.Count : 0);
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
if (Context.PhaseLoopRuntime.CurrentPhase == null)
|
||||
if (Runtime.PhaseLoopRuntime.CurrentPhase == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("CombatScheduler update failed. Current phase is null.");
|
||||
Coordinator.EnterFailureFallback("CombatScheduler update failed. Current phase is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
Context.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
Runtime.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
Runtime.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
|
||||
|
||||
if (Flow.ShouldEnterSettlementFromActiveState(out bool isVictory))
|
||||
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool isVictory))
|
||||
{
|
||||
Flow.ChangeState(new CombatSettlementState(Context, Flow, isVictory));
|
||||
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, isVictory));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Context.EnemyManager.IsPhaseSpawnCompleted)
|
||||
if (Runtime.EnemyManager.IsPhaseSpawnCompleted)
|
||||
{
|
||||
Flow.EnterWaitingForPhaseEnd();
|
||||
Coordinator.EnterWaitingForPhaseEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,30 +5,30 @@ namespace GeometryTD.CustomComponent
|
|||
private readonly bool _isVictory;
|
||||
|
||||
public CombatSettlementState(
|
||||
CombatSchedulerRuntimeContext context,
|
||||
CombatSchedulerFlowCoordinator flow,
|
||||
bool isVictory) : base(context, flow)
|
||||
CombatSchedulerRuntime runtime,
|
||||
CombatSchedulerCoordinator coordinator,
|
||||
bool isVictory) : base(runtime, coordinator)
|
||||
{
|
||||
_isVictory = isVictory;
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
Context.EnemyManager.EndPhase();
|
||||
Context.EnemyManager.CleanupTrackedEnemies();
|
||||
Context.IsFinishAsVictory = _isVictory;
|
||||
Context.SettlementContext = Context.SettlementFlowService.BuildSettlementContext(
|
||||
Runtime.EnemyManager.EndPhase();
|
||||
Runtime.EnemyManager.CleanupTrackedEnemies();
|
||||
Runtime.IsFinishAsVictory = _isVictory;
|
||||
Runtime.SettlementContext = Runtime.CombatSettlementService.BuildSettlementContext(
|
||||
_isVictory,
|
||||
Context.CurrentLevel,
|
||||
Context.EnemyManager.DefeatedEnemyCount,
|
||||
Context.CombatInRunResourceManager);
|
||||
if (Context.SettlementContext.Flow.ShouldOpenRewardSelection)
|
||||
Runtime.CurrentLevel,
|
||||
Runtime.EnemyManager.DefeatedEnemyCount,
|
||||
Runtime.CombatRunResourceStore);
|
||||
if (Runtime.SettlementContext.Flags.ShouldOpenRewardSelection)
|
||||
{
|
||||
Flow.ChangeState(new CombatRewardSelectionState(Context, Flow));
|
||||
Coordinator.ChangeState(new CombatRewardSelectionState(Runtime, Coordinator));
|
||||
return;
|
||||
}
|
||||
|
||||
Flow.ChangeState(new CombatFinishFormState(Context, Flow));
|
||||
Coordinator.ChangeState(new CombatFinishFormState(Runtime, Coordinator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
internal abstract class CombatStateBase
|
||||
{
|
||||
protected CombatSchedulerRuntimeContext Context { get; }
|
||||
protected CombatSchedulerFlowCoordinator Flow { get; }
|
||||
protected CombatSchedulerRuntime Runtime { get; }
|
||||
protected CombatSchedulerCoordinator Coordinator { get; }
|
||||
|
||||
protected CombatStateBase(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
protected CombatStateBase(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
|
||||
{
|
||||
Context = context;
|
||||
Flow = flow;
|
||||
Runtime = runtime;
|
||||
Coordinator = coordinator;
|
||||
}
|
||||
|
||||
public virtual void OnInit()
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
internal sealed class CombatWaitingForPhaseEndState : CombatStateBase
|
||||
{
|
||||
public CombatWaitingForPhaseEndState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
public CombatWaitingForPhaseEndState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
|
||||
: base(runtime, coordinator)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -13,34 +13,34 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
_ = realElapseSeconds;
|
||||
|
||||
DRLevelPhase currentPhase = Context.PhaseLoopRuntime.CurrentPhase;
|
||||
DRLevelPhase currentPhase = Runtime.PhaseLoopRuntime.CurrentPhase;
|
||||
if (currentPhase == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("CombatScheduler waiting phase failed. Current phase is null.");
|
||||
Coordinator.EnterFailureFallback("CombatScheduler waiting phase failed. Current phase is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
Runtime.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
|
||||
|
||||
if (Flow.ShouldEnterSettlementFromActiveState(out bool isVictory))
|
||||
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool isVictory))
|
||||
{
|
||||
Flow.ChangeState(new CombatSettlementState(Context, Flow, isVictory));
|
||||
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, isVictory));
|
||||
return;
|
||||
}
|
||||
|
||||
PhaseEndConditionContext conditionContext = new(
|
||||
currentPhase,
|
||||
Context.PhaseLoopRuntime.CurrentPhaseElapsed,
|
||||
Context.EnemyManager.IsPhaseSpawnCompleted,
|
||||
Context.EnemyManager.AliveEnemyCount,
|
||||
Context.EnemyManager.HasAliveBoss);
|
||||
Runtime.PhaseLoopRuntime.CurrentPhaseElapsed,
|
||||
Runtime.EnemyManager.IsPhaseSpawnCompleted,
|
||||
Runtime.EnemyManager.AliveEnemyCount,
|
||||
Runtime.EnemyManager.HasAliveBoss);
|
||||
IPhaseEndCondition endCondition = PhaseEndConditionFactory.Create(currentPhase.EndType);
|
||||
if (!endCondition.ShouldExit(conditionContext))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Flow.CompleteCurrentPhase();
|
||||
Coordinator.CompleteCurrentPhase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
private bool _returnRequested;
|
||||
|
||||
public CombatWaitingForReturnState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
|
||||
: base(context, flow)
|
||||
public CombatWaitingForReturnState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
|
||||
: base(runtime, coordinator)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -24,17 +24,17 @@ namespace GeometryTD.CustomComponent
|
|||
return;
|
||||
}
|
||||
|
||||
if (Context.SettlementContext == null)
|
||||
if (Runtime.SettlementContext == null)
|
||||
{
|
||||
Flow.EnterFailureFallback("Combat return failed. Settlement context is missing.");
|
||||
Coordinator.EnterFailureFallback("Combat return failed. Settlement context is missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
Context.SettlementFlowService.CommitSettlementInventory(Context.SettlementContext);
|
||||
Context.LoadSession.Cleanup();
|
||||
Flow.CloseCombatFinishForm();
|
||||
Flow.CloseRewardSelectForm();
|
||||
Flow.CompleteNormalCombatAndNotify(Context.IsFinishAsVictory);
|
||||
Runtime.CombatSettlementService.CommitSettlementInventory(Runtime.SettlementContext);
|
||||
Runtime.LoadSession.Cleanup();
|
||||
Coordinator.CloseCombatFinishForm();
|
||||
Coordinator.CloseRewardSelectForm();
|
||||
Coordinator.CompleteNormalCombatAndNotify(Runtime.IsFinishAsVictory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ using GeometryTD.Definition;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal readonly struct EnemyDropResolveContext
|
||||
internal readonly struct EnemyDropContext
|
||||
{
|
||||
public EnemyDropResolveContext(DREnemy enemy, int displayPhaseIndex, LevelThemeType themeType)
|
||||
public EnemyDropContext(DREnemy enemy, int displayPhaseIndex, LevelThemeType themeType)
|
||||
{
|
||||
Enemy = enemy;
|
||||
DisplayPhaseIndex = displayPhaseIndex;
|
||||
|
|
@ -31,12 +31,12 @@ namespace GeometryTD.CustomComponent
|
|||
_nextDropItemInstanceId = 1;
|
||||
}
|
||||
|
||||
public EnemyDropResolveResult Resolve(in EnemyDropResolveContext context)
|
||||
public EnemyDropResult Resolve(in EnemyDropContext context)
|
||||
{
|
||||
DREnemy enemy = context.Enemy;
|
||||
if (enemy == null)
|
||||
{
|
||||
return EnemyDropResolveResult.Empty;
|
||||
return EnemyDropResult.Empty;
|
||||
}
|
||||
|
||||
int coin = Mathf.Max(0, enemy.DropCoin);
|
||||
|
|
@ -58,7 +58,7 @@ namespace GeometryTD.CustomComponent
|
|||
lootItem = droppedItem;
|
||||
}
|
||||
|
||||
return new EnemyDropResolveResult(coin, gold, lootItem);
|
||||
return new EnemyDropResult(coin, gold, lootItem);
|
||||
}
|
||||
|
||||
public IReadOnlyList<TowerCompItemData> RollSettlementRewardCandidates(
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ using GeometryTD.Definition;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal readonly struct EnemyDropResolveResult
|
||||
internal readonly struct EnemyDropResult
|
||||
{
|
||||
public static EnemyDropResolveResult Empty => new(0, 0, null);
|
||||
public static EnemyDropResult Empty => new(0, 0, null);
|
||||
|
||||
public EnemyDropResolveResult(int coin, int gold, TowerCompItemData lootItem)
|
||||
public EnemyDropResult(int coin, int gold, TowerCompItemData lootItem)
|
||||
{
|
||||
Coin = coin;
|
||||
Gold = gold;
|
||||
|
|
@ -2,7 +2,7 @@ using GeometryTD.DataTable;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal interface ICombatSchedulerHost
|
||||
internal interface ICombatSchedulerPort
|
||||
{
|
||||
DRLevel CurrentLevel { get; }
|
||||
int DisplayPhaseIndex { get; }
|
||||
|
|
@ -6,7 +6,7 @@ using UnityGameFramework.Runtime;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public sealed class EnemyConfigService
|
||||
public sealed class EnemyConfigProvider
|
||||
{
|
||||
private const int DefaultEnemyConfigId = 1;
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
if (!_enemyConfigMissingLogged)
|
||||
{
|
||||
Log.Warning("EnemyManagerComponent can not find DREnemy data table.");
|
||||
Log.Warning("EnemyConfigProvider can not find DREnemy data table.");
|
||||
_enemyConfigMissingLogged = true;
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
if (!_enemyConfigMissingLogged)
|
||||
{
|
||||
Log.Warning("EnemyManagerComponent found no enemy configs.");
|
||||
Log.Warning("EnemyConfigProvider found no enemy configs.");
|
||||
_enemyConfigMissingLogged = true;
|
||||
}
|
||||
|
||||
|
|
@ -101,4 +101,4 @@ namespace GeometryTD.CustomComponent
|
|||
return Mathf.Max(0, (displayPhaseIndex - 1) / phaseCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,8 +12,8 @@ namespace GeometryTD.CustomComponent
|
|||
{
|
||||
private readonly List<int> _trackedEnemyIdBuffer = new();
|
||||
private readonly EnemySpawnDirector _enemySpawnDirector = new();
|
||||
private readonly EnemyConfigService _enemyConfigService = new();
|
||||
private readonly SpawnerResolver _spawnerResolver = new();
|
||||
private readonly EnemyConfigProvider _enemyConfigProvider = new();
|
||||
private readonly EnemySpawnPathResolver _enemySpawnPathResolver = new();
|
||||
private readonly EnemyLifecycleTracker _enemyLifecycleTracker = new();
|
||||
|
||||
private CombatScheduler _combatScheduler;
|
||||
|
|
@ -39,8 +39,8 @@ namespace GeometryTD.CustomComponent
|
|||
_entity = GameEntry.Entity;
|
||||
_defeatedEnemyCount = 0;
|
||||
_enemySpawnDirector.Reset();
|
||||
_enemyConfigService.Reset();
|
||||
_spawnerResolver.Reset();
|
||||
_enemyConfigProvider.Reset();
|
||||
_enemySpawnPathResolver.Reset();
|
||||
_trackedEnemyIdBuffer.Clear();
|
||||
_enemyLifecycleTracker.Reset();
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ namespace GeometryTD.CustomComponent
|
|||
|
||||
_ = phase;
|
||||
EndPhase();
|
||||
_spawnerResolver.RefreshCache(_combatScheduler, true);
|
||||
_enemySpawnPathResolver.RefreshCache(_combatScheduler, true);
|
||||
_enemySpawnDirector.BeginPhase(spawnEntries);
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ namespace GeometryTD.CustomComponent
|
|||
return;
|
||||
}
|
||||
|
||||
_spawnerResolver.RefreshCache(_combatScheduler, false);
|
||||
_enemySpawnPathResolver.RefreshCache(_combatScheduler, false);
|
||||
_enemySpawnDirector.OnUpdate(elapseSeconds, SpawnEnemies);
|
||||
}
|
||||
|
||||
|
|
@ -93,11 +93,11 @@ namespace GeometryTD.CustomComponent
|
|||
GameEntry.Event.Unsubscribe(ShowEntityFailureEventArgs.EventId, OnShowEntityFailure);
|
||||
GameEntry.Event.Unsubscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete);
|
||||
|
||||
_spawnerResolver.Reset();
|
||||
_enemySpawnPathResolver.Reset();
|
||||
_trackedEnemyIdBuffer.Clear();
|
||||
_enemyLifecycleTracker.Reset();
|
||||
_defeatedEnemyCount = 0;
|
||||
_enemyConfigService.Reset();
|
||||
_enemyConfigProvider.Reset();
|
||||
_combatScheduler = null;
|
||||
_initialized = false;
|
||||
}
|
||||
|
|
@ -139,18 +139,18 @@ namespace GeometryTD.CustomComponent
|
|||
return;
|
||||
}
|
||||
|
||||
if (!_spawnerResolver.TryResolveSpawnPath(_combatScheduler, entry.SpawnPointId, out IReadOnlyList<Vector3> pathPoints))
|
||||
if (!_enemySpawnPathResolver.TryResolveSpawnPath(_combatScheduler, entry.SpawnPointId, out IReadOnlyList<Vector3> pathPoints))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DREnemy enemyConfig = _enemyConfigService.GetEnemyConfig(entry.EnemyId);
|
||||
DREnemy enemyConfig = _enemyConfigProvider.GetEnemyConfig(entry.EnemyId);
|
||||
if (enemyConfig == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int scaledBaseHp = _enemyConfigService.ResolveScaledEnemyBaseHp(enemyConfig.BaseHp, _combatScheduler);
|
||||
int scaledBaseHp = _enemyConfigProvider.ResolveScaledEnemyBaseHp(enemyConfig.BaseHp, _combatScheduler);
|
||||
bool isBoss = entry.EntryType == Definition.EntryType.Boss;
|
||||
|
||||
for (int i = 0; i < spawnCount; i++)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using UnityEngine;
|
|||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class SpawnerResolver
|
||||
internal sealed class EnemySpawnPathResolver
|
||||
{
|
||||
private readonly List<Spawner> _spawners = new();
|
||||
private readonly Dictionary<int, Spawner> _spawnerByOrder = new();
|
||||
|
|
@ -7,7 +7,7 @@ namespace GeometryTD.UI
|
|||
{
|
||||
public class CombatFinishFormUseCase : IUIUseCase
|
||||
{
|
||||
private ICombatSchedulerHost _combatSchedulerHost;
|
||||
private ICombatSchedulerPort _combatSchedulerPort;
|
||||
private CombatSettlementContext _settlementContext;
|
||||
private bool _isSummaryPrepared;
|
||||
|
||||
|
|
@ -27,14 +27,14 @@ namespace GeometryTD.UI
|
|||
_isSummaryPrepared = true;
|
||||
}
|
||||
|
||||
internal CombatFinishFormUseCase(ICombatSchedulerHost combatSchedulerHost)
|
||||
internal CombatFinishFormUseCase(ICombatSchedulerPort combatSchedulerPort)
|
||||
{
|
||||
_combatSchedulerHost = combatSchedulerHost;
|
||||
_combatSchedulerPort = combatSchedulerPort;
|
||||
}
|
||||
|
||||
public bool TryReturnToMenu()
|
||||
{
|
||||
return _combatSchedulerHost != null && _combatSchedulerHost.OnCombatFinishReturnRequested();
|
||||
return _combatSchedulerPort != null && _combatSchedulerPort.OnCombatFinishReturnRequested();
|
||||
}
|
||||
|
||||
private CombatFinishFormRawData BuildModel()
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
和上一版相比,仓库已经把 Run 相关基础件进一步接到了 `ProcedureMain`,因此这份清单不再把重点放在“有没有 Run 模型”,而是聚焦下面这几个真实阻塞项:
|
||||
|
||||
- 已有 `ProcedureMain + NodeMapForm` 的临时 Run 推进闭环,正式节点面板骨架已经接入流程。
|
||||
- 固定 10 节点顺序已经开始驱动战斗 / 事件 / 商店入口,但节点事件上下文仍然是空载版本。
|
||||
- 已有 `ProcedureMenu + MenuForm -> ProcedureMain + NodeMapForm` 的主入口链路,正式节点面板骨架已经接入流程。
|
||||
- 固定 10 节点顺序已经开始驱动战斗 / 事件 / 商店入口,节点事件也已带上基础 Run 上下文字段。
|
||||
- 出战入口已有“至少有参战塔”的最小校验,但还没收口成严格的最终合法性约束。
|
||||
- 品质 / Tag / 耐久仍然停留在部分实现状态,尚未和 M1 范围完全对齐。
|
||||
|
||||
|
|
@ -30,13 +30,13 @@
|
|||
### 2. 战斗结算、掉落与奖励选择已有基础实现
|
||||
|
||||
- 敌人被击败后已能发放 coin / gold / 组件掉落。
|
||||
- `CombatInRunResourceManager` 维护局内资源与奖励背包快照。
|
||||
- `CombatRunResourceStore` 维护局内资源与奖励背包快照。
|
||||
- 结算链已包含奖励计算、奖励选择 UI、FinishForm 返回等基础骨架。
|
||||
|
||||
关键文件:
|
||||
- `Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatInRunResourceManager.cs`
|
||||
- `Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatRunResourceStore.cs`
|
||||
- `Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/EnemyDrop/EnemyDropResolver.cs`
|
||||
- `Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatSettlementFlowService.cs`
|
||||
- `Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatSettlementService.cs`
|
||||
- `Assets/GameMain/Scripts/UI/Combat/`
|
||||
|
||||
### 3. 背包、参战区与组装基础能力已经存在
|
||||
|
|
@ -107,6 +107,19 @@
|
|||
- `Assets/GameMain/Scripts/UI/Game/View/NodeItem.cs`
|
||||
- `Assets/GameMain/Scripts/Event/Game/NodeMapNodeEnterRequestedEventArgs.cs`
|
||||
|
||||
### 8. 菜单入口已切回独立 Menu 流程
|
||||
|
||||
- `ProcedureMenu` 当前只负责菜单入口,不再承载主流程 Hub 与节点推进逻辑。
|
||||
- `MenuForm` 已按五层结构补齐 `RawData / UseCase / Controller / Context / View`。
|
||||
- `Start` 按钮现在会驱动 `ProcedureMenu` 切场景,并在主场景加载完成后进入 `ProcedureMain`。
|
||||
- `Settings` 仍保留 `TODO` 占位,`Exit` 会直接退出游戏。
|
||||
|
||||
关键文件:
|
||||
- `Assets/GameMain/Scripts/Procedure/ProcedureMenu.cs`
|
||||
- `Assets/GameMain/Scripts/Procedure/Base/ProcedureChangeScene.cs`
|
||||
- `Assets/GameMain/Scripts/UI/Menu/Controller/MenuFormController.cs`
|
||||
- `Assets/GameMain/Scripts/UI/Menu/View/MenuForm.cs`
|
||||
|
||||
## 当前未完成
|
||||
|
||||
### 1. Run 主流程已经形成基于 `NodeMapForm` 的临时闭环,但还没完全收口
|
||||
|
|
@ -127,14 +140,14 @@
|
|||
- `Assets/GameMain/Scripts/UI/Game/View/NodeMapForm.cs`
|
||||
- `Assets/GameMain/Scripts/UI/Game/Controller/NodeMapFormController.cs`
|
||||
|
||||
### 2. 固定 10 节点序列已开始驱动真实流程,但上下文仍不完整
|
||||
### 2. 固定 10 节点序列已开始驱动真实流程,但正式上下文系统仍不完整
|
||||
|
||||
- `FixedRunNodeSequenceBuilder` 已定义固定顺序和 Boss 终点。
|
||||
- `ProcedureMain` 已开始用当前 `RunNodeState.LinkedLevelId` 驱动战斗入口。
|
||||
- `EventNodeComponent` 和 `ShopNodeComponent` 已能进入并完成当前节点。
|
||||
- `EventNodeComponent` 的 UI 生命周期也已统一走 `UIRouter`。
|
||||
- 但 `NodeEnter / NodeComplete` 仍是默认空载事件,没有附带当前 Run 节点信息。
|
||||
- 因此“固定 10 节点序列”已经在驱动流程,但还没有形成可观测、可追踪的正式节点上下文系统。
|
||||
- `NodeEnter / NodeComplete` 已带 `runId / nodeId / nodeType / sequenceIndex` 等基础字段,`NodeComplete` 也会回传成功状态与库存快照。
|
||||
- 当前缺的不是“有没有上下文字段”,而是更系统化的节点追踪、展示与统一收口能力。
|
||||
|
||||
关键文件:
|
||||
- `Assets/GameMain/Scripts/Procedure/FixedRunNodeSequenceBuilder.cs`
|
||||
|
|
@ -144,7 +157,7 @@
|
|||
- `Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs`
|
||||
- `Assets/GameMain/Scripts/Event/Game/NodeCompleteEventArgs.cs`
|
||||
|
||||
### 3. 商店节点已纳入临时 Run 推进闭环,但回流目标仍是测试 Hub
|
||||
### 3. 商店节点已纳入临时 Run 推进闭环,但回流目标仍是 MVP Hub
|
||||
|
||||
- 现在可以单独打开商店、随机生成组件、购买并退出。
|
||||
- 商店结束后已能通过 `ProcedureMain` 推进当前 `RunState`。
|
||||
|
|
@ -201,7 +214,7 @@
|
|||
结合静态代码检查,当前更接近下面这个状态:
|
||||
|
||||
- `P0-04`:基础模型已完成,并已接入 `ProcedureMain + NodeMapForm` 的临时 Run 闭环。
|
||||
- `P0-05`:固定 10 节点序列已由 builder + `ProcedureMain + NodeMapForm` 驱动实际流程,但缺完整事件上下文与地图表现层。
|
||||
- `P0-05`:固定 10 节点序列已由 builder + `ProcedureMain + NodeMapForm` 驱动实际流程,基础事件上下文字段已接入,但缺更完整的地图表现层与正式上下文系统。
|
||||
- `P0-06`:节点进入、完成、失败后回 `NodeMapForm` 的临时闭环已存在,但正式地图表现与正式结算仍未完成。
|
||||
- `P0-10`:未完成。
|
||||
- `P0-11`:未完成。
|
||||
|
|
@ -216,9 +229,9 @@
|
|||
- 继续以 `NodeMapForm` 为基础补正式节点地图表现
|
||||
- 至少补上节点连线、Boss 视觉强调、当前节点说明和完成态反馈
|
||||
|
||||
2. 再把节点事件改成带上下文的真实推进
|
||||
- `NodeEnterEventArgs` 和 `NodeCompleteEventArgs` 传递 `runId / nodeId / nodeType / sequenceIndex`
|
||||
- 节点完成后由流程层调用 `RunStateAdvanceService`
|
||||
2. 再补齐节点上下文的消费、追踪与统一推进
|
||||
- 继续沿用 `NodeEnterEventArgs` 和 `NodeCompleteEventArgs` 现有的 `runId / nodeId / nodeType / sequenceIndex`
|
||||
- 节点完成后统一由流程层调用 `RunStateAdvanceService`
|
||||
- 节点失败时明确是否停局、重试或返回菜单
|
||||
|
||||
3. 然后继续收口战斗关卡选择
|
||||
|
|
@ -236,6 +249,7 @@
|
|||
## 当前做变更时要记住的约束
|
||||
|
||||
- 不要再把 Hub 退回 `TestMenuForm` 语义。
|
||||
- 不要把菜单入口和主流程 Hub 混回同一个 Procedure;保持 `ProcedureMenu -> ProcedureMain` 的职责边界。
|
||||
- 优先补“临时闭环 -> 正式节点 UI / 正式上下文”的收口,不要继续只加单点功能。
|
||||
- 商店已经接入 Run,下一步重点不是继续扩商店,而是把 Hub/UI 做正式。
|
||||
- 若 M1 最终不做完整耐久 / 红色品质,要先同步文档再改代码目标。
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@
|
|||
- 上述状态类可以作为 `CombatScheduler` 的嵌套类实现,也可以拆成独立文件;但必须只服务于 `CombatScheduler` 状态机,不形成独立业务边界。
|
||||
- 共享数据与共享服务统一收口到 `CombatScheduler` 内部持有的运行时承载体,不允许散落在各状态类中。
|
||||
- 若 `CombatScheduler` 体量过大,允许在其内部实现中继续拆出:
|
||||
- `CombatSchedulerRuntimeContext`:承载共享运行时字段与共享服务引用
|
||||
- `CombatSchedulerFlowCoordinator`:承载多个状态共用的流程辅助方法
|
||||
- `CombatSchedulerRuntime`:承载共享运行时字段与共享服务引用
|
||||
- `CombatSchedulerCoordinator`:承载多个状态共用的流程辅助方法
|
||||
- 上述拆分只属于 `CombatScheduler` 的内部实现细化,不改变 `CombatScheduler` 作为唯一状态机边界的职责。
|
||||
- 所有状态切换只能通过 `CombatScheduler.ChangeState(...)` 完成。
|
||||
- 状态类不能彼此直接操控。
|
||||
|
|
@ -213,7 +213,23 @@
|
|||
|
||||
## 4. 共享服务与推荐命名
|
||||
|
||||
### 4.1 CombatLoadSession
|
||||
### 4.1 命名后缀词典
|
||||
|
||||
- `Scheduler`:只用于状态机边界或阶段推进总控,例如 `CombatScheduler`。
|
||||
- `Manager`:只用于子域 Facade/聚合入口,例如 `EnemyManager`。
|
||||
- `Coordinator`:只用于跨状态、跨服务的流程编排,不持有独立业务真值。
|
||||
- `Service`:只用于聚焦业务行为,不承担框架事件桥接或异步句柄跟踪。
|
||||
- `Session`:只用于一次加载/交互过程的生命周期对象。
|
||||
- `Bridge`:只用于框架边界适配器。
|
||||
- `Runtime`:只用于运行时可变状态承载。
|
||||
- `Context`:只用于被动数据包或共享上下文。
|
||||
- `Result`:只用于动作输出或结算产出;若外围服务名已表达动作语义,不再重复动作前缀。
|
||||
- `Flags`:只用于聚合布尔控制项,不承载流程编排逻辑。
|
||||
- `Resolver`:只用于映射、查找、判定、解析职责。
|
||||
- `Tracker`:只用于跟踪运行中的实体或事实真值。
|
||||
- `Port`:只用于向内部状态或 use case 暴露的受限宿主接口。
|
||||
|
||||
### 4.2 CombatLoadSession
|
||||
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatLoadSession.cs`
|
||||
|
||||
|
|
@ -227,20 +243,20 @@
|
|||
- 跟踪加载成功/失败状态。
|
||||
- 对外提供 `CurrentMap` 与 `IsReady`。
|
||||
|
||||
### 4.1.x CombatSchedulerRuntimeContext / CombatSchedulerFlowCoordinator(实现细化)
|
||||
### 4.2.x CombatSchedulerRuntime / CombatSchedulerCoordinator(实现细化)
|
||||
|
||||
当前实现允许:
|
||||
- 用 `CombatSchedulerRuntimeContext` 承载所有状态共享的运行时字段与共享服务引用。
|
||||
- 用 `CombatSchedulerFlowCoordinator` 承载多个状态共用的流程辅助逻辑。
|
||||
- 用 `CombatSchedulerRuntime` 承载所有状态共享的运行时字段与共享服务引用。
|
||||
- 用 `CombatSchedulerCoordinator` 承载多个状态共用的流程辅助逻辑。
|
||||
|
||||
约束:
|
||||
- 两者都必须由 `CombatScheduler` 持有并统一管理生命周期。
|
||||
- 两者都不替代 `CombatScheduler` 对外暴露状态机边界。
|
||||
- `RuntimeContext` 不负责状态切换。
|
||||
- `FlowCoordinator` 不持有独立业务真值,只能围绕共享运行时做编排辅助。
|
||||
- 状态类只允许通过 `RuntimeContext + FlowCoordinator` 访问共享状态与共享流程,不应再直接耦合其他状态实现细节。
|
||||
- `Runtime` 不负责状态切换。
|
||||
- `Coordinator` 不持有独立业务真值,只能围绕共享运行时做编排辅助。
|
||||
- 状态类只允许通过 `Runtime + Coordinator` 访问共享状态与共享流程,不应再直接耦合其他状态实现细节。
|
||||
|
||||
### 4.2 PhaseLoopRuntime
|
||||
### 4.3 PhaseLoopRuntime
|
||||
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/PhaseLoopRuntime.cs`
|
||||
|
||||
|
|
@ -257,9 +273,9 @@
|
|||
约束:
|
||||
- 只做 phase 运行时数据管理,不直接切状态。
|
||||
|
||||
### 4.3 CombatInRunResourceManager(推荐命名)
|
||||
### 4.4 CombatRunResourceStore
|
||||
|
||||
当前相关文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatResourceManager.cs`
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatRunResourceStore.cs`
|
||||
|
||||
目标职责:
|
||||
- 持有本局 `Coin` 真值。
|
||||
|
|
@ -280,9 +296,9 @@
|
|||
- `Coin / BaseHp` 变化事件同时携带“当前值”和“变化量”。
|
||||
- `Gold` 只是结算累计值,不要求战斗内实时事件驱动。
|
||||
|
||||
### 4.4 EnemyDropResolver(推荐命名)
|
||||
### 4.5 EnemyDropResolver
|
||||
|
||||
当前相关文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatResourceManager.cs`
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/EnemyDrop/EnemyDropResolver.cs`
|
||||
|
||||
目标职责:
|
||||
- 只负责敌人死亡后的掉落判定。
|
||||
|
|
@ -297,7 +313,7 @@
|
|||
- 不直接修改资源状态。
|
||||
- 不直接读取 `CombatNodeComponent`、`MapEntity`、`EnemyManager` 内部状态。
|
||||
|
||||
### 4.5 IPhaseEndCondition(推荐命名)
|
||||
### 4.6 IPhaseEndCondition
|
||||
|
||||
目标职责:
|
||||
- 作为 `PhaseEndType` 判定接口。
|
||||
|
|
@ -334,9 +350,9 @@
|
|||
生命周期:
|
||||
- 由 `CombatRunningPhaseState` 在状态进入/退出时初始化与重置。
|
||||
|
||||
### 5.2 SpawnerResolver
|
||||
### 5.2 EnemySpawnPathResolver
|
||||
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/EnemyManager/SpawnerResolver.cs`
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/EnemyManager/EnemySpawnPathResolver.cs`
|
||||
|
||||
职责:
|
||||
- 缓存当前地图可用 `Spawner`。
|
||||
|
|
@ -356,9 +372,9 @@ Boss 识别规则:
|
|||
- Boss 身份由 `DRLevelSpawnEntry.EntryType == Boss` 决定。
|
||||
- 不由 `DREnemy` 自身类型决定。
|
||||
|
||||
### 5.4 EnemyConfigService
|
||||
### 5.4 EnemyConfigProvider
|
||||
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/EnemyManager/EnemyConfigService.cs`
|
||||
文件:`Assets/GameMain/Scripts/CustomComponent/CombatNode/EnemyManager/EnemyConfigProvider.cs`
|
||||
|
||||
职责:
|
||||
- 读取 `DREnemy`。
|
||||
|
|
@ -436,6 +452,9 @@ Boss 识别规则:
|
|||
- 是否进入过奖励选择
|
||||
- `FinishForm` 所需摘要数据
|
||||
|
||||
命名约束:
|
||||
- 结算上下文中的布尔控制项统一收口到 `Flags`,不再使用 `Flow` 命名。
|
||||
|
||||
奖励选择约束:
|
||||
- 满血奖励选择结果只写入结算上下文。
|
||||
- 不直接写入局内资源管理器。
|
||||
|
|
@ -447,7 +466,7 @@ Boss 识别规则:
|
|||
|
||||
1. `CombatScheduler` 只做状态机管理与共享运行时收口,不继续吸收具体业务细节。
|
||||
2. `CombatNodeComponent` 不再持有战斗内资源真值。
|
||||
3. 局内 `Coin / Gold / BaseHp / Loot Backpack / BuildTowerSnapshots` 以 `CombatInRunResourceManager` 为唯一真值来源。
|
||||
3. 局内 `Coin / Gold / BaseHp / Loot Backpack / BuildTowerSnapshots` 以 `CombatRunResourceStore` 为唯一真值来源。
|
||||
4. 敌人死亡掉落判定以 `EnemyDropResolver` 为唯一判定入口。
|
||||
5. 存活敌人数与 `HasAliveBoss` 以 `EnemyLifecycleTracker` 为唯一真值来源。
|
||||
6. Phase 运行时信息与统一结束标记以 `PhaseLoopRuntime` 为唯一真值来源。
|
||||
|
|
@ -483,7 +502,7 @@ Boss 识别规则:
|
|||
|
||||
### 10.4 新增战斗内资源或建塔快照规则
|
||||
|
||||
优先改 `CombatInRunResourceManager`,不要回流到 `CombatNodeComponent`。
|
||||
优先改 `CombatRunResourceStore`,不要回流到 `CombatNodeComponent`。
|
||||
|
||||
### 10.5 新增地图/战斗基础 UI 加载规则
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue