refactor 6:

- CombatInfoFormUseCase.cs 改成回调驱动:
    - 不再直接读 GameEntry.CombatNode
    - 由 CombatLoadSession.cs 在打开 CombatInfoForm 前注入 modelProvider 和 TryEndCombat 回调
- CombatSelectFormUseCase.cs 的默认 coin provider 改成返回 0,不再偷偷 fallback 到 GameEntry.CombatNode
- CombatFinishFormUseCase.cs 去掉了未准备 summary 时对 GameEntry.CombatNode 的兜底读取
- MapData.cs 进一步补充了战斗初始快照:
    - InventorySnapshot
    - ParticipantTowerSnapshot
- CombatLoadingState.cs 现在会把这些背包/参战塔快照也一起打进 MapData
- MapEntity.cs 配置建塔面板时不再直接读 PlayerInventory,改为用 MapData 里的快照
This commit is contained in:
2026-03-07 15:22:24 +08:00
parent ca7b2f2dca
commit ab7c7172b8
7 changed files with 105 additions and 47 deletions
@@ -45,12 +45,8 @@ namespace GeometryTD.UI
{
if (!_isSummaryPrepared)
{
_defeatedEnemyCount = GameEntry.CombatNode != null
? Mathf.Max(0, GameEntry.CombatNode.LastDefeatedEnemyCount)
: 0;
_gainedGold = GameEntry.CombatNode != null
? Mathf.Max(0, GameEntry.CombatNode.LastGainedGold)
: 0;
_defeatedEnemyCount = 0;
_gainedGold = 0;
_rewardInventory = null;
}
@@ -1,9 +1,14 @@
using System;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.UI
{
public class CombatInfoFormUseCase : IUIUseCase
{
private Func<CombatInfoFormRawData> _modelProvider;
private Func<bool> _tryEndCombat;
public CombatInfoFormRawData CreateInitialModel()
{
return BuildModel();
@@ -14,43 +19,49 @@ namespace GeometryTD.UI
return BuildModel();
}
public void Configure(Func<CombatInfoFormRawData> modelProvider, Func<bool> tryEndCombat)
{
_modelProvider = modelProvider;
_tryEndCombat = tryEndCombat;
}
public bool TryEndCombat()
{
if (GameEntry.CombatNode == null || !GameEntry.CombatNode.CanEndCombat)
if (_tryEndCombat == null)
{
return false;
}
return GameEntry.CombatNode.TryEndCombatByPlayer();
return _tryEndCombat.Invoke();
}
private static CombatInfoFormRawData BuildModel()
private CombatInfoFormRawData BuildModel()
{
if (GameEntry.CombatNode == null)
{
return null;
}
var level = GameEntry.CombatNode.CurrentLevel;
LevelThemeType themeType = level != null ? level.LevelThemeType : GameEntry.CombatNode.CurrentThemeType;
int levelId = level != null ? level.Id : 0;
int baseHpMax = level != null ? level.BaseHp : 0;
int enemyHpRateMultiplier = ResolveEnemyHpRateMultiplier(
GameEntry.CombatNode.CurrentPhaseIndex,
GameEntry.CombatNode.CurrentLevelPhaseCount);
return _modelProvider != null ? _modelProvider.Invoke() : null;
}
public static CombatInfoFormRawData BuildRawData(
LevelThemeType themeType,
int levelId,
int currentPhaseIndex,
int totalPhaseCount,
int coin,
int baseHp,
int baseHpMax,
bool canEnd)
{
return new CombatInfoFormRawData
{
LevelThemeType = themeType,
LevelId = levelId,
CurrentPhaseIndex = GameEntry.CombatNode.CurrentPhaseIndex,
TotalPhaseCount = GameEntry.CombatNode.CurrentLevelPhaseCount,
Coin = GameEntry.CombatNode.CurrentCoin,
BaseHp = GameEntry.CombatNode.CurrentBaseHp,
BaseHpMax = baseHpMax,
EnemyHpRateMultiplier = enemyHpRateMultiplier,
CurrentPhaseIndex = Mathf.Max(0, currentPhaseIndex),
TotalPhaseCount = Mathf.Max(0, totalPhaseCount),
Coin = Mathf.Max(0, coin),
BaseHp = Mathf.Max(0, baseHp),
BaseHpMax = Mathf.Max(0, baseHpMax),
EnemyHpRateMultiplier = ResolveEnemyHpRateMultiplier(currentPhaseIndex, totalPhaseCount),
CanPause = true,
CanEnd = GameEntry.CombatNode.CanEndCombat
CanEnd = canEnd
};
}
@@ -61,7 +72,7 @@ namespace GeometryTD.UI
return 1;
}
int completedLoopCount = UnityEngine.Mathf.Max(0, (currentPhaseIndex - 1) / totalPhaseCount);
int completedLoopCount = Mathf.Max(0, (currentPhaseIndex - 1) / totalPhaseCount);
if (completedLoopCount >= 30)
{
return int.MaxValue;
@@ -269,12 +269,7 @@ namespace GeometryTD.UI
private static int DefaultCoinProvider()
{
if (GameEntry.CombatNode == null)
{
return 0;
}
return Mathf.Max(0, GameEntry.CombatNode.CurrentCoin);
return 0;
}
private static bool CanExecute(Option option, int currentCoin)