Refine combat settlement exit flow

This commit is contained in:
basil 2026-03-07 20:09:50 +08:00
parent 3ad7d04b47
commit 703fd6f540
9 changed files with 16 additions and 19 deletions

View File

@ -92,7 +92,7 @@ namespace GeometryTD.CustomComponent
{ {
if (!_context.PhaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase)) if (!_context.PhaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase))
{ {
_schedulerHost.ChangeState(new CombatSettlementState(_context, this, "Combat ended after loop completion.", true)); _schedulerHost.ChangeState(new CombatSettlementState(_context, this, true));
return false; return false;
} }
@ -118,23 +118,20 @@ namespace GeometryTD.CustomComponent
TryBeginNextPhase(); TryBeginNextPhase();
} }
public bool ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory) public bool ShouldEnterSettlementFromActiveState(out bool isVictory)
{ {
if (GetCurrentBaseHp() <= 0) if (GetCurrentBaseHp() <= 0)
{ {
reason = "Combat ended because base HP reached zero.";
isVictory = false; isVictory = false;
return true; return true;
} }
if (_context.PhaseLoopRuntime.IsEndCombatRequested) if (_context.PhaseLoopRuntime.IsEndCombatRequested)
{ {
reason = "Combat ended by player.";
isVictory = true; isVictory = true;
return true; return true;
} }
reason = null;
isVictory = true; isVictory = true;
return false; return false;
} }

View File

@ -25,7 +25,6 @@ namespace GeometryTD.CustomComponent
public int DefeatedEnemyCount; public int DefeatedEnemyCount;
public int GainedGold; public int GainedGold;
public BackpackInventoryData RewardInventory; public BackpackInventoryData RewardInventory;
public string Reason;
public CombatSettlementPenaltyResult Penalty { get; } = new(); public CombatSettlementPenaltyResult Penalty { get; } = new();
} }

View File

@ -18,7 +18,6 @@ namespace GeometryTD.CustomComponent
private const float LowBaseHpTowerEndurancePenalty = 10f; private const float LowBaseHpTowerEndurancePenalty = 10f;
public CombatSettlementContext BuildSettlementContext( public CombatSettlementContext BuildSettlementContext(
string reason,
bool isVictory, bool isVictory,
DRLevel currentLevel, DRLevel currentLevel,
int defeatedEnemyCount, int defeatedEnemyCount,
@ -49,7 +48,6 @@ namespace GeometryTD.CustomComponent
settlementContext.Result.RewardInventory = resourceManager != null settlementContext.Result.RewardInventory = resourceManager != null
? resourceManager.GetRewardInventorySnapshot() ? resourceManager.GetRewardInventorySnapshot()
: new BackpackInventoryData(); : new BackpackInventoryData();
settlementContext.Result.Reason = reason;
settlementContext.Result.Penalty.ShouldApplyLowBaseHpPenalty = appliedLowBaseHpPenalty; settlementContext.Result.Penalty.ShouldApplyLowBaseHpPenalty = appliedLowBaseHpPenalty;
settlementContext.Result.Penalty.LowBaseHpEndurancePenaltyValue = settlementContext.Result.Penalty.LowBaseHpEndurancePenaltyValue =
appliedLowBaseHpPenalty ? LowBaseHpTowerEndurancePenalty : 0f; appliedLowBaseHpPenalty ? LowBaseHpTowerEndurancePenalty : 0f;
@ -60,9 +58,8 @@ namespace GeometryTD.CustomComponent
settlementContext.Summary.RewardInventory = settlementContext.Result.RewardInventory; settlementContext.Summary.RewardInventory = settlementContext.Result.RewardInventory;
Log.Info( Log.Info(
"Combat settlement resolved. Level={0}, Reason={1}, BaseHp={2}/{3}, LevelReward={4}, BonusRate={5:P0}, BonusGold={6}, FullHpRewardSelect={7}, LowHpPenalty={8}.", "Combat settlement resolved. Level={0}, BaseHp={1}/{2}, LevelReward={3}, BonusRate={4:P0}, BonusGold={5}, FullHpRewardSelect={6}, LowHpPenalty={7}.",
currentLevel != null ? currentLevel.Id : 0, currentLevel != null ? currentLevel.Id : 0,
reason,
currentBaseHp, currentBaseHp,
maxBaseHp, maxBaseHp,
levelRewardGold, levelRewardGold,

View File

@ -15,7 +15,6 @@ namespace GeometryTD.CustomComponent
return; return;
} }
Context.SettlementFlowService.CommitSettlementInventory(Context.SettlementContext);
Flow.EnsureCombatFinishFormUseCaseBound(); Flow.EnsureCombatFinishFormUseCaseBound();
Context.SettlementFlowService.OpenCombatFinishForm( Context.SettlementFlowService.OpenCombatFinishForm(
Context.SettlementContext, Context.SettlementContext,

View File

@ -60,9 +60,9 @@ namespace GeometryTD.CustomComponent
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds); Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
Context.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds); Context.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
if (Flow.ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory)) if (Flow.ShouldEnterSettlementFromActiveState(out bool isVictory))
{ {
Flow.ChangeState(new CombatSettlementState(Context, Flow, reason, isVictory)); Flow.ChangeState(new CombatSettlementState(Context, Flow, isVictory));
return; return;
} }

View File

@ -2,16 +2,13 @@ namespace GeometryTD.CustomComponent
{ {
internal sealed class CombatSettlementState : CombatStateBase internal sealed class CombatSettlementState : CombatStateBase
{ {
private readonly string _reason;
private readonly bool _isVictory; private readonly bool _isVictory;
public CombatSettlementState( public CombatSettlementState(
CombatSchedulerRuntimeContext context, CombatSchedulerRuntimeContext context,
CombatSchedulerFlowCoordinator flow, CombatSchedulerFlowCoordinator flow,
string reason,
bool isVictory) : base(context, flow) bool isVictory) : base(context, flow)
{ {
_reason = reason;
_isVictory = isVictory; _isVictory = isVictory;
} }
@ -21,7 +18,6 @@ namespace GeometryTD.CustomComponent
Context.EnemyManager.CleanupTrackedEnemies(); Context.EnemyManager.CleanupTrackedEnemies();
Context.IsFinishAsVictory = _isVictory; Context.IsFinishAsVictory = _isVictory;
Context.SettlementContext = Context.SettlementFlowService.BuildSettlementContext( Context.SettlementContext = Context.SettlementFlowService.BuildSettlementContext(
_reason,
_isVictory, _isVictory,
Context.CurrentLevel, Context.CurrentLevel,
Context.EnemyManager.DefeatedEnemyCount, Context.EnemyManager.DefeatedEnemyCount,

View File

@ -22,9 +22,9 @@ namespace GeometryTD.CustomComponent
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds); Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
if (Flow.ShouldEnterSettlementFromActiveState(out string reason, out bool isVictory)) if (Flow.ShouldEnterSettlementFromActiveState(out bool isVictory))
{ {
Flow.ChangeState(new CombatSettlementState(Context, Flow, reason, isVictory)); Flow.ChangeState(new CombatSettlementState(Context, Flow, isVictory));
return; return;
} }

View File

@ -24,6 +24,13 @@ namespace GeometryTD.CustomComponent
return; return;
} }
if (Context.SettlementContext == null)
{
Flow.EnterFailureFallback("Combat return failed. Settlement context is missing.");
return;
}
Context.SettlementFlowService.CommitSettlementInventory(Context.SettlementContext);
Context.LoadSession.Cleanup(); Context.LoadSession.Cleanup();
Flow.CloseCombatFinishForm(); Flow.CloseCombatFinishForm();
Flow.CloseRewardSelectForm(); Flow.CloseRewardSelectForm();

View File

@ -174,6 +174,7 @@
- 奖励选择相关流程标记 - 奖励选择相关流程标记
- 低血惩罚相关事实 - 低血惩罚相关事实
- 低血惩罚已改为“先记录事实,提交阶段再统一落库”,不再在结算构造期直接写库存 - 低血惩罚已改为“先记录事实,提交阶段再统一落库”,不再在结算构造期直接写库存
- 结算背包合并当前发生在 `WaitingForReturn` 的真正退出点,而不是 `FinishForm`
- `CombatFinishForm` 当前只消费它真正展示需要的摘要,不再把额外结算事实继续灌进 UI Context - `CombatFinishForm` 当前只消费它真正展示需要的摘要,不再把额外结算事实继续灌进 UI Context
关键文件: 关键文件:
@ -247,6 +248,7 @@
- 流程控制字段现在集中在 `Flow` - 流程控制字段现在集中在 `Flow`
- 结算事实与惩罚事实现在集中在 `Result` - 结算事实与惩罚事实现在集中在 `Result`
- `CombatFinishFormUseCase` 当前只消费 `Summary` - `CombatFinishFormUseCase` 当前只消费 `Summary`
- 已去掉单独的结束原因字段,结束链不再依赖 `CombatEndReason` 风格数据
- 奖励选择与延迟提交惩罚已同步切到分层后的上下文访问路径 - 奖励选择与延迟提交惩罚已同步切到分层后的上下文访问路径
关键文件: 关键文件: