refactor 5:

- CombatSettlementFlowService.cs 负责结算上下文构建、基地血量奖励修正、奖励选择准备、奖励追加、结算背包提交、FinishForm 摘要准备。
- CombatSettlementContext.cs 变成独立共享上下文,不再作为 CombatScheduler 内部私有类。
- 状态链改成各司其职:
    - CombatSettlementState.cs 负责结束战斗现场并构建结算上下文。
    - CombatRewardSelectionState.cs 只负责进入奖励选择流程。
    - CombatFinishFormState.cs 只负责提交结算背包并打开 FinishForm。
- CombatScheduler.cs 删除了大块结算/奖励构建细节,保留状态切换、共享运行时和少量桥接回调。
This commit is contained in:
SepComet 2026-03-07 15:05:59 +08:00
parent e488a2ca0f
commit ccb4738b96
8 changed files with 378 additions and 285 deletions

View File

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using GeometryTD.CustomEvent;
using GeometryTD.DataTable;
@ -12,13 +11,6 @@ namespace GeometryTD.CustomComponent
{
public partial class CombatScheduler
{
private const int RewardSelectDisplayCount = 3;
private const float FullBaseHpGoldBonusRate = 0.3f;
private const float HighBaseHpGoldBonusRate = 0.1f;
private const float HighBaseHpThreshold = 0.8f;
private const float MidBaseHpThreshold = 0.5f;
private const float LowBaseHpTowerEndurancePenalty = 10f;
private readonly List<DRLevelPhase> _phaseBuffer = new();
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
private readonly EnemyManager _enemyManager = new();
@ -27,6 +19,7 @@ namespace GeometryTD.CustomComponent
private readonly CombatEventBridge _eventBridge = new();
private readonly CombatInRunResourceManager _combatInRunResourceManager = new();
private readonly EnemyDropResolver _enemyDropResolver = new();
private readonly CombatSettlementFlowService _settlementFlowService = new();
private EntityComponent _entity;
private DRLevel _currentLevel;
@ -37,7 +30,7 @@ namespace GeometryTD.CustomComponent
private bool _isFinishAsVictory = true;
private bool _isCompleted;
private bool _nodeEnterFired;
private SettlementContext _settlementContext;
private CombatSettlementContext _settlementContext;
public bool IsRunning =>
_currentState is CombatLoadingState or CombatRunningPhaseState or CombatWaitingForPhaseEndState;
@ -343,179 +336,6 @@ namespace GeometryTD.CustomComponent
return false;
}
private void OpenCombatFinishForm(SettlementContext settlementContext)
{
EnsureCombatFinishFormUseCaseBound();
_combatFinishFormUseCase.SetSummary(
settlementContext.DefeatedEnemyCount,
settlementContext.GainedGold,
settlementContext.RewardInventory);
GameEntry.UIRouter.OpenUI(UIFormType.CombatFinishForm);
}
private SettlementContext BuildSettlementContext(string reason, bool isVictory)
{
int defeatedEnemyCount = _enemyManager.DefeatedEnemyCount;
_enemyManager.EndPhase();
_enemyManager.CleanupTrackedEnemies();
_isFinishAsVictory = isVictory;
bool shouldOpenFullBaseHpRewardSelect = false;
ApplySettlementModifierByBaseHp(isVictory, out shouldOpenFullBaseHpRewardSelect);
SettlementContext settlementContext = new SettlementContext
{
DefeatedEnemyCount = Mathf.Max(0, defeatedEnemyCount),
GainedGold = Mathf.Max(0, _combatInRunResourceManager.GainedGold),
RewardInventory = _combatInRunResourceManager.GetRewardInventorySnapshot(),
ShouldOpenRewardSelection = shouldOpenFullBaseHpRewardSelect,
Reason = reason
};
Log.Info(
"CombatScheduler entered finish flow. Level={0}. Reason={1}",
_currentLevel != null ? _currentLevel.Id : 0,
reason);
return settlementContext;
}
private void CommitSettlementInventory(SettlementContext settlementContext)
{
if (settlementContext == null || settlementContext.IsCommitted)
{
return;
}
BackpackInventoryData rewardInventory = settlementContext.RewardInventory ?? new BackpackInventoryData();
GameEntry.PlayerInventory?.MergeInventory(rewardInventory);
settlementContext.RewardInventory = rewardInventory;
settlementContext.IsCommitted = true;
}
private void ApplySettlementModifierByBaseHp(bool isVictory, out bool shouldOpenFullBaseHpRewardSelect)
{
shouldOpenFullBaseHpRewardSelect = false;
if (!isVictory)
{
return;
}
int levelRewardGold = _currentLevel != null ? Mathf.Max(0, _currentLevel.RewardGold) : 0;
int currentBaseHp;
int maxBaseHp;
float bonusRate = 0f;
bool appliedLowBaseHpPenalty = false;
ResolveBaseHpSnapshot(out currentBaseHp, out maxBaseHp);
if (maxBaseHp > 0 && currentBaseHp >= maxBaseHp)
{
bonusRate = FullBaseHpGoldBonusRate;
shouldOpenFullBaseHpRewardSelect = true;
}
else if (maxBaseHp > 0)
{
float hpRate = (float)Mathf.Clamp(currentBaseHp, 0, maxBaseHp) / maxBaseHp;
if (hpRate >= HighBaseHpThreshold)
{
bonusRate = HighBaseHpGoldBonusRate;
}
else if (hpRate < MidBaseHpThreshold)
{
appliedLowBaseHpPenalty = ApplyLowBaseHpPenalty();
}
}
int goldForBonusCalculation = Mathf.Max(0, _combatInRunResourceManager.GainedGold) + levelRewardGold;
int bonusGold = bonusRate > 0f ? Mathf.FloorToInt(goldForBonusCalculation * bonusRate) : 0;
int settlementGold = levelRewardGold + bonusGold;
_combatInRunResourceManager.AddSettlementGold(settlementGold);
Log.Info(
"Combat settlement resolved. BaseHp={0}/{1}, LevelReward={2}, BonusRate={3:P0}, BonusGold={4}, FullHpRewardSelect={5}, LowHpPenalty={6}.",
currentBaseHp,
maxBaseHp,
levelRewardGold,
bonusRate,
bonusGold,
shouldOpenFullBaseHpRewardSelect,
appliedLowBaseHpPenalty);
}
private void ResolveBaseHpSnapshot(out int currentBaseHp, out int maxBaseHp)
{
currentBaseHp = Mathf.Max(0, GetCurrentBaseHp());
maxBaseHp = _combatInRunResourceManager.MaxBaseHp;
if (maxBaseHp > 0)
{
currentBaseHp = Mathf.Clamp(currentBaseHp, 0, maxBaseHp);
}
}
private bool ApplyLowBaseHpPenalty()
{
PlayerInventoryComponent inventory = GameEntry.PlayerInventory;
if (inventory == null)
{
return false;
}
int affectedTowerCount = inventory.ReduceAllTowerEndurance(LowBaseHpTowerEndurancePenalty);
return affectedTowerCount > 0;
}
private bool TryPrepareRewardSelection(SettlementContext settlementContext)
{
IReadOnlyList<TowerCompItemData> candidateItems = _combatInRunResourceManager.RollSettlementRewardCandidates(
_phaseLoopRuntime.DisplayPhaseIndex,
ResolveCurrentThemeType(),
RewardSelectDisplayCount);
if (candidateItems == null || candidateItems.Count <= 0)
{
settlementContext.ShouldOpenRewardSelection = false;
return false;
}
List<RewardSelectItemRawData> rewardPool = new List<RewardSelectItemRawData>(candidateItems.Count);
for (int i = 0; i < candidateItems.Count; i++)
{
TowerCompItemData item = candidateItems[i];
if (item == null)
{
continue;
}
rewardPool.Add(BuildRewardSelectRawData(item));
}
if (rewardPool.Count <= 0)
{
settlementContext.ShouldOpenRewardSelection = false;
return false;
}
EnsureRewardSelectFormUseCaseBound();
_rewardSelectFormUseCase.SetCallbacks(OnFullBaseHpRewardSelected, OnFullBaseHpRewardGiveUp);
_rewardSelectFormUseCase.ConfigureRewardPool(
rewardPool,
displayCount: RewardSelectDisplayCount,
refreshCost: 0,
allowRefreshOnce: false,
allowGiveUp: false,
tipText: "基地满血奖励:请选择 1 个组件");
RewardSelectFormRawData rawData = _rewardSelectFormUseCase.CreateInitialModel();
if (rawData == null || rawData.RewardItems == null || rawData.RewardItems.Length <= 0)
{
settlementContext.ShouldOpenRewardSelection = false;
return false;
}
GameEntry.UIRouter.OpenUI(UIFormType.RewardSelectForm, rawData);
return true;
}
private void OnFullBaseHpRewardSelected(RewardSelectItemRawData selectedReward)
{
if (_currentState is not CombatRewardSelectionState || _settlementContext == null)
@ -523,11 +343,7 @@ namespace GeometryTD.CustomComponent
return;
}
if (_settlementContext.RewardInventory != null && selectedReward?.SourceItem != null)
{
TryAppendRewardComponent(_settlementContext.RewardInventory, selectedReward.SourceItem);
}
_settlementFlowService.ApplySelectedReward(_settlementContext, selectedReward);
ChangeState(new CombatFinishFormState(this));
}
@ -541,87 +357,6 @@ namespace GeometryTD.CustomComponent
ChangeState(new CombatFinishFormState(this));
}
private static bool TryAppendRewardComponent(BackpackInventoryData rewardInventory, TowerCompItemData selectedItem)
{
if (rewardInventory == null || selectedItem == null)
{
return false;
}
if (selectedItem is MuzzleCompItemData muzzleComp)
{
rewardInventory.MuzzleComponents.Add(muzzleComp);
return true;
}
if (selectedItem is BearingCompItemData bearingComp)
{
rewardInventory.BearingComponents.Add(bearingComp);
return true;
}
if (selectedItem is BaseCompItemData baseComp)
{
rewardInventory.BaseComponents.Add(baseComp);
return true;
}
return false;
}
private static RewardSelectItemRawData BuildRewardSelectRawData(TowerCompItemData item)
{
return new RewardSelectItemRawData
{
RewardId = item.InstanceId,
SlotType = item.SlotType,
Title = item.Name,
TypeText = BuildRewardTypeText(item.SlotType),
Description = BuildRewardDescription(item),
Rarity = item.Rarity,
Tags = item.Tags != null ? (TagType[])item.Tags.Clone() : Array.Empty<TagType>(),
Icon = null,
IsSelectable = true,
SourceItem = item
};
}
private static string BuildRewardTypeText(TowerCompSlotType slotType)
{
return slotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static string BuildRewardDescription(TowerCompItemData item)
{
if (item is MuzzleCompItemData muzzle)
{
int damage = muzzle.AttackDamage != null && muzzle.AttackDamage.Length > 0 ? muzzle.AttackDamage[0] : 0;
return $"Damage: {damage}, Spread: {muzzle.DamageRandomRate:P0}";
}
if (item is BearingCompItemData bearing)
{
float range = bearing.AttackRange != null && bearing.AttackRange.Length > 0 ? bearing.AttackRange[0] : 0f;
float rotateSpeed = bearing.RotateSpeed != null && bearing.RotateSpeed.Length > 0 ? bearing.RotateSpeed[0] : 0f;
return $"Range: {range:0.##}, Rotate Speed: {rotateSpeed:0.##}";
}
if (item is BaseCompItemData baseComp)
{
float attackSpeed = baseComp.AttackSpeed != null && baseComp.AttackSpeed.Length > 0 ? baseComp.AttackSpeed[0] : 0f;
return $"Attack Speed: {attackSpeed:0.##}, Property: {baseComp.AttackPropertyType}";
}
return string.Empty;
}
private LevelThemeType ResolveCurrentThemeType()
{
if (_currentLevel != null)
@ -770,15 +505,5 @@ namespace GeometryTD.CustomComponent
CompleteCombatAndNotify(false);
}
private sealed class SettlementContext
{
public int DefeatedEnemyCount;
public int GainedGold;
public BackpackInventoryData RewardInventory;
public bool ShouldOpenRewardSelection;
public bool IsCommitted;
public string Reason;
}
}
}

View File

@ -0,0 +1,14 @@
using GeometryTD.Definition;
namespace GeometryTD.CustomComponent
{
internal sealed class CombatSettlementContext
{
public int DefeatedEnemyCount;
public int GainedGold;
public BackpackInventoryData RewardInventory;
public bool ShouldOpenRewardSelection;
public bool IsCommitted;
public string Reason;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f00e1b4791824896b50b52f3c94308f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,315 @@
using System;
using System.Collections.Generic;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using GeometryTD.UI;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace GeometryTD.CustomComponent
{
internal sealed class CombatSettlementFlowService
{
private const int RewardSelectDisplayCount = 3;
private const float FullBaseHpGoldBonusRate = 0.3f;
private const float HighBaseHpGoldBonusRate = 0.1f;
private const float HighBaseHpThreshold = 0.8f;
private const float MidBaseHpThreshold = 0.5f;
private const float LowBaseHpTowerEndurancePenalty = 10f;
public CombatSettlementContext BuildSettlementContext(
string reason,
bool isVictory,
DRLevel currentLevel,
int defeatedEnemyCount,
CombatInRunResourceManager resourceManager)
{
bool shouldOpenFullBaseHpRewardSelect = false;
ResolveSettlementByBaseHp(
isVictory,
currentLevel,
resourceManager,
out int currentBaseHp,
out int maxBaseHp,
out int levelRewardGold,
out float bonusRate,
out int bonusGold,
out bool appliedLowBaseHpPenalty,
out shouldOpenFullBaseHpRewardSelect);
CombatSettlementContext settlementContext = new CombatSettlementContext
{
DefeatedEnemyCount = Mathf.Max(0, defeatedEnemyCount),
GainedGold = Mathf.Max(0, resourceManager != null ? resourceManager.GainedGold : 0),
RewardInventory = resourceManager != null
? resourceManager.GetRewardInventorySnapshot()
: new BackpackInventoryData(),
ShouldOpenRewardSelection = shouldOpenFullBaseHpRewardSelect,
Reason = reason
};
Log.Info(
"Combat settlement resolved. Level={0}, Reason={1}, BaseHp={2}/{3}, LevelReward={4}, BonusRate={5:P0}, BonusGold={6}, FullHpRewardSelect={7}, LowHpPenalty={8}.",
currentLevel != null ? currentLevel.Id : 0,
reason,
currentBaseHp,
maxBaseHp,
levelRewardGold,
bonusRate,
bonusGold,
shouldOpenFullBaseHpRewardSelect,
appliedLowBaseHpPenalty);
return settlementContext;
}
public void CommitSettlementInventory(CombatSettlementContext settlementContext)
{
if (settlementContext == null || settlementContext.IsCommitted)
{
return;
}
BackpackInventoryData rewardInventory = settlementContext.RewardInventory ?? new BackpackInventoryData();
GameEntry.PlayerInventory?.MergeInventory(rewardInventory);
settlementContext.RewardInventory = rewardInventory;
settlementContext.IsCommitted = true;
}
public bool TryPrepareRewardSelection(
CombatSettlementContext settlementContext,
CombatInRunResourceManager resourceManager,
int displayPhaseIndex,
LevelThemeType themeType,
RewardSelectFormUseCase rewardSelectFormUseCase,
Action<RewardSelectItemRawData> onRewardSelected,
Action onGiveUp)
{
if (settlementContext == null || resourceManager == null || rewardSelectFormUseCase == null)
{
return false;
}
IReadOnlyList<TowerCompItemData> candidateItems = resourceManager.RollSettlementRewardCandidates(
displayPhaseIndex,
themeType,
RewardSelectDisplayCount);
if (candidateItems == null || candidateItems.Count <= 0)
{
settlementContext.ShouldOpenRewardSelection = false;
return false;
}
List<RewardSelectItemRawData> rewardPool = new List<RewardSelectItemRawData>(candidateItems.Count);
for (int i = 0; i < candidateItems.Count; i++)
{
TowerCompItemData item = candidateItems[i];
if (item == null)
{
continue;
}
rewardPool.Add(BuildRewardSelectRawData(item));
}
if (rewardPool.Count <= 0)
{
settlementContext.ShouldOpenRewardSelection = false;
return false;
}
rewardSelectFormUseCase.SetCallbacks(onRewardSelected, onGiveUp);
rewardSelectFormUseCase.ConfigureRewardPool(
rewardPool,
displayCount: RewardSelectDisplayCount,
refreshCost: 0,
allowRefreshOnce: false,
allowGiveUp: false,
tipText: "基地满血奖励:请选择 1 个组件");
RewardSelectFormRawData rawData = rewardSelectFormUseCase.CreateInitialModel();
if (rawData == null || rawData.RewardItems == null || rawData.RewardItems.Length <= 0)
{
settlementContext.ShouldOpenRewardSelection = false;
return false;
}
GameEntry.UIRouter.OpenUI(UIFormType.RewardSelectForm, rawData);
return true;
}
public void ApplySelectedReward(CombatSettlementContext settlementContext, RewardSelectItemRawData selectedReward)
{
if (settlementContext?.RewardInventory == null || selectedReward?.SourceItem == null)
{
return;
}
TryAppendRewardComponent(settlementContext.RewardInventory, selectedReward.SourceItem);
}
public void OpenCombatFinishForm(
CombatSettlementContext settlementContext,
CombatInRunResourceManager resourceManager,
CombatFinishFormUseCase combatFinishFormUseCase)
{
if (settlementContext == null || combatFinishFormUseCase == null)
{
return;
}
settlementContext.GainedGold = Mathf.Max(0, resourceManager != null ? resourceManager.GainedGold : settlementContext.GainedGold);
combatFinishFormUseCase.SetSummary(
settlementContext.DefeatedEnemyCount,
settlementContext.GainedGold,
settlementContext.RewardInventory);
GameEntry.UIRouter.OpenUI(UIFormType.CombatFinishForm);
}
private static void ResolveSettlementByBaseHp(
bool isVictory,
DRLevel currentLevel,
CombatInRunResourceManager resourceManager,
out int currentBaseHp,
out int maxBaseHp,
out int levelRewardGold,
out float bonusRate,
out int bonusGold,
out bool appliedLowBaseHpPenalty,
out bool shouldOpenFullBaseHpRewardSelect)
{
currentBaseHp = Mathf.Max(0, resourceManager != null ? resourceManager.CurrentBaseHp : 0);
maxBaseHp = resourceManager != null ? Mathf.Max(0, resourceManager.MaxBaseHp) : 0;
if (maxBaseHp > 0)
{
currentBaseHp = Mathf.Clamp(currentBaseHp, 0, maxBaseHp);
}
levelRewardGold = currentLevel != null ? Mathf.Max(0, currentLevel.RewardGold) : 0;
bonusRate = 0f;
bonusGold = 0;
appliedLowBaseHpPenalty = false;
shouldOpenFullBaseHpRewardSelect = false;
if (!isVictory || resourceManager == null)
{
return;
}
if (maxBaseHp > 0 && currentBaseHp >= maxBaseHp)
{
bonusRate = FullBaseHpGoldBonusRate;
shouldOpenFullBaseHpRewardSelect = true;
}
else if (maxBaseHp > 0)
{
float hpRate = (float)currentBaseHp / maxBaseHp;
if (hpRate >= HighBaseHpThreshold)
{
bonusRate = HighBaseHpGoldBonusRate;
}
else if (hpRate < MidBaseHpThreshold)
{
appliedLowBaseHpPenalty = ApplyLowBaseHpPenalty();
}
}
int goldForBonusCalculation = Mathf.Max(0, resourceManager.GainedGold) + levelRewardGold;
bonusGold = bonusRate > 0f ? Mathf.FloorToInt(goldForBonusCalculation * bonusRate) : 0;
int settlementGold = levelRewardGold + bonusGold;
resourceManager.AddSettlementGold(settlementGold);
}
private static bool ApplyLowBaseHpPenalty()
{
PlayerInventoryComponent inventory = GameEntry.PlayerInventory;
if (inventory == null)
{
return false;
}
int affectedTowerCount = inventory.ReduceAllTowerEndurance(LowBaseHpTowerEndurancePenalty);
return affectedTowerCount > 0;
}
private static bool TryAppendRewardComponent(BackpackInventoryData rewardInventory, TowerCompItemData selectedItem)
{
if (rewardInventory == null || selectedItem == null)
{
return false;
}
if (selectedItem is MuzzleCompItemData muzzleComp)
{
rewardInventory.MuzzleComponents.Add(muzzleComp);
return true;
}
if (selectedItem is BearingCompItemData bearingComp)
{
rewardInventory.BearingComponents.Add(bearingComp);
return true;
}
if (selectedItem is BaseCompItemData baseComp)
{
rewardInventory.BaseComponents.Add(baseComp);
return true;
}
return false;
}
private static RewardSelectItemRawData BuildRewardSelectRawData(TowerCompItemData item)
{
return new RewardSelectItemRawData
{
RewardId = item.InstanceId,
SlotType = item.SlotType,
Title = item.Name,
TypeText = BuildRewardTypeText(item.SlotType),
Description = BuildRewardDescription(item),
Rarity = item.Rarity,
Tags = item.Tags != null ? (TagType[])item.Tags.Clone() : Array.Empty<TagType>(),
Icon = null,
IsSelectable = true,
SourceItem = item
};
}
private static string BuildRewardTypeText(TowerCompSlotType slotType)
{
return slotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static string BuildRewardDescription(TowerCompItemData item)
{
if (item is MuzzleCompItemData muzzle)
{
int damage = muzzle.AttackDamage != null && muzzle.AttackDamage.Length > 0 ? muzzle.AttackDamage[0] : 0;
return $"Damage: {damage}, Spread: {muzzle.DamageRandomRate:P0}";
}
if (item is BearingCompItemData bearing)
{
float range = bearing.AttackRange != null && bearing.AttackRange.Length > 0 ? bearing.AttackRange[0] : 0f;
float rotateSpeed = bearing.RotateSpeed != null && bearing.RotateSpeed.Length > 0 ? bearing.RotateSpeed[0] : 0f;
return $"Range: {range:0.##}, Rotate Speed: {rotateSpeed:0.##}";
}
if (item is BaseCompItemData baseComp)
{
float attackSpeed = baseComp.AttackSpeed != null && baseComp.AttackSpeed.Length > 0 ? baseComp.AttackSpeed[0] : 0f;
return $"Attack Speed: {attackSpeed:0.##}, Property: {baseComp.AttackPropertyType}";
}
return string.Empty;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac4d5b5da086454e917694f8000fc8fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,3 @@
using UnityEngine;
namespace GeometryTD.CustomComponent
{
public partial class CombatScheduler
@ -18,9 +16,12 @@ namespace GeometryTD.CustomComponent
return;
}
Scheduler.CommitSettlementInventory(Scheduler._settlementContext);
Scheduler._settlementContext.GainedGold = Mathf.Max(0, Scheduler._combatInRunResourceManager.GainedGold);
Scheduler.OpenCombatFinishForm(Scheduler._settlementContext);
Scheduler._settlementFlowService.CommitSettlementInventory(Scheduler._settlementContext);
Scheduler.EnsureCombatFinishFormUseCaseBound();
Scheduler._settlementFlowService.OpenCombatFinishForm(
Scheduler._settlementContext,
Scheduler._combatInRunResourceManager,
Scheduler._combatFinishFormUseCase);
Scheduler.ChangeState(new CombatWaitingForReturnState(Scheduler));
}
}

View File

@ -16,7 +16,15 @@ namespace GeometryTD.CustomComponent
return;
}
if (!Scheduler.TryPrepareRewardSelection(Scheduler._settlementContext))
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));
}

View File

@ -15,7 +15,15 @@ namespace GeometryTD.CustomComponent
public override void OnEnter()
{
Scheduler._settlementContext = Scheduler.BuildSettlementContext(_reason, _isVictory);
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));