refactor 2: 迁移局内资源真值
- CombatInRunResourceManager 现在持有并管理:
- CurrentCoin
- CurrentBaseHp
- MaxBaseHp
- GainedCoin / GainedGold
- 本局 BuildTowerStats 快照
- 奖励背包快照
- CombatInRunResourceManager.cs:38
- CombatInRunResourceManager.cs:46
- CombatInRunResourceManager.cs:89
- CombatInRunResourceManager.cs:156
- CombatScheduler 变成资源访问入口,不再通过 CombatNodeComponent 持有 coin/baseHp/build stats 真值。
- 启动时先初始化局内资源。
- 对外提供 CurrentCoin / CurrentGold / CurrentBaseHp / CurrentBuildTowerCount
- 提供 TryConsumeCoin / AddCoin / TryGetBuildTowerStats
- CombatNodeComponent 已退回 facade:
- 不再保存 _currentCoin / _currentGold / _currentBaseHp / _currentBuildTowerStats
- 只做只读转发和启动/结束协调
- 资源变化事件现在由资源管理器发布,并补上了 delta 字段:
额外修正
- Reset() 现在会清掉奖励背包里的 ParticipantTowerInstanceIds,避免跨局残留。
- TryConsumeCoin(0) 保持原先返回 true 的语义。
This commit is contained in:
parent
1d7c5b80d9
commit
853886797c
|
|
@ -23,24 +23,20 @@ namespace GeometryTD.CustomComponent
|
||||||
private readonly Dictionary<int, List<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
|
private readonly Dictionary<int, List<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
|
||||||
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _selectedSpawnEntriesByPhaseId = new();
|
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _selectedSpawnEntriesByPhaseId = new();
|
||||||
private readonly List<int> _levelIdBuffer = new();
|
private readonly List<int> _levelIdBuffer = new();
|
||||||
private readonly List<TowerStatsData> _currentBuildTowerStats = new();
|
|
||||||
private readonly CombatScheduler _combatScheduler = new CombatScheduler();
|
private readonly CombatScheduler _combatScheduler = new CombatScheduler();
|
||||||
|
|
||||||
private bool _runtimeInitialized;
|
private bool _runtimeInitialized;
|
||||||
private bool _isCombatActive;
|
private bool _isCombatActive;
|
||||||
private int _currentCoin;
|
|
||||||
private int _currentGold;
|
|
||||||
private int _currentBaseHp;
|
|
||||||
private bool _lastCombatSucceeded = true;
|
private bool _lastCombatSucceeded = true;
|
||||||
|
|
||||||
public LevelThemeType CurrentThemeType { get; private set; }
|
public LevelThemeType CurrentThemeType { get; private set; }
|
||||||
public DRLevel CurrentLevel { get; private set; }
|
public DRLevel CurrentLevel { get; private set; }
|
||||||
public int CurrentCoin => _currentCoin;
|
public int CurrentCoin => _isCombatActive ? _combatScheduler.CurrentCoin : 0;
|
||||||
public int CurrentGold => _currentGold;
|
public int CurrentGold => _isCombatActive ? _combatScheduler.CurrentGold : 0;
|
||||||
public int CurrentBaseHp => _currentBaseHp;
|
public int CurrentBaseHp => _isCombatActive ? _combatScheduler.CurrentBaseHp : 0;
|
||||||
public bool LastCombatSucceeded => _lastCombatSucceeded;
|
public bool LastCombatSucceeded => _lastCombatSucceeded;
|
||||||
public bool CanEndCombat => _combatScheduler.CanEndCombat;
|
public bool CanEndCombat => _combatScheduler.CanEndCombat;
|
||||||
public int CurrentBuildTowerCount => _currentBuildTowerStats.Count;
|
public int CurrentBuildTowerCount => _isCombatActive ? _combatScheduler.CurrentBuildTowerCount : 0;
|
||||||
public int LastDefeatedEnemyCount { get; private set; }
|
public int LastDefeatedEnemyCount { get; private set; }
|
||||||
public int LastGainedCoin { get; private set; }
|
public int LastGainedCoin { get; private set; }
|
||||||
public int LastGainedGold { get; private set; }
|
public int LastGainedGold { get; private set; }
|
||||||
|
|
@ -78,9 +74,6 @@ namespace GeometryTD.CustomComponent
|
||||||
CurrentThemeType = themeType;
|
CurrentThemeType = themeType;
|
||||||
CurrentLevel = null;
|
CurrentLevel = null;
|
||||||
_isCombatActive = false;
|
_isCombatActive = false;
|
||||||
_currentCoin = 0;
|
|
||||||
_currentGold = 0;
|
|
||||||
_currentBaseHp = 0;
|
|
||||||
_lastCombatSucceeded = true;
|
_lastCombatSucceeded = true;
|
||||||
LastDefeatedEnemyCount = 0;
|
LastDefeatedEnemyCount = 0;
|
||||||
LastGainedCoin = 0;
|
LastGainedCoin = 0;
|
||||||
|
|
@ -90,7 +83,6 @@ namespace GeometryTD.CustomComponent
|
||||||
_spawnEntriesByPhaseId.Clear();
|
_spawnEntriesByPhaseId.Clear();
|
||||||
_selectedSpawnEntriesByPhaseId.Clear();
|
_selectedSpawnEntriesByPhaseId.Clear();
|
||||||
_levelIdBuffer.Clear();
|
_levelIdBuffer.Clear();
|
||||||
_currentBuildTowerStats.Clear();
|
|
||||||
|
|
||||||
IDataTable<DRLevel> dtLevel = GameEntry.DataTable.GetDataTable<DRLevel>();
|
IDataTable<DRLevel> dtLevel = GameEntry.DataTable.GetDataTable<DRLevel>();
|
||||||
IDataTable<DRLevelPhase> dtLevelPhase = GameEntry.DataTable.GetDataTable<DRLevelPhase>();
|
IDataTable<DRLevelPhase> dtLevelPhase = GameEntry.DataTable.GetDataTable<DRLevelPhase>();
|
||||||
|
|
@ -184,7 +176,6 @@ namespace GeometryTD.CustomComponent
|
||||||
|
|
||||||
public void StartCombat()
|
public void StartCombat()
|
||||||
{
|
{
|
||||||
_currentBuildTowerStats.Clear();
|
|
||||||
if (!EnsureCombatRuntimeInitialized())
|
if (!EnsureCombatRuntimeInitialized())
|
||||||
{
|
{
|
||||||
Log.Warning("CombatNodeComponent start failed. Missing scheduler runtime.");
|
Log.Warning("CombatNodeComponent start failed. Missing scheduler runtime.");
|
||||||
|
|
@ -220,11 +211,7 @@ namespace GeometryTD.CustomComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentLevel = selectedLevel;
|
CurrentLevel = selectedLevel;
|
||||||
CacheBuildTowerStatsSnapshot();
|
|
||||||
_isCombatActive = false;
|
_isCombatActive = false;
|
||||||
_currentCoin = Mathf.Max(0, selectedLevel.StartCoin);
|
|
||||||
_currentGold = 0;
|
|
||||||
_currentBaseHp = Mathf.Max(0, selectedLevel.BaseHp);
|
|
||||||
_lastCombatSucceeded = true;
|
_lastCombatSucceeded = true;
|
||||||
LastDefeatedEnemyCount = 0;
|
LastDefeatedEnemyCount = 0;
|
||||||
LastGainedCoin = 0;
|
LastGainedCoin = 0;
|
||||||
|
|
@ -232,10 +219,6 @@ namespace GeometryTD.CustomComponent
|
||||||
if (!_combatScheduler.Start(selectedLevel, phaseList, _selectedSpawnEntriesByPhaseId))
|
if (!_combatScheduler.Start(selectedLevel, phaseList, _selectedSpawnEntriesByPhaseId))
|
||||||
{
|
{
|
||||||
CurrentLevel = null;
|
CurrentLevel = null;
|
||||||
_currentCoin = 0;
|
|
||||||
_currentGold = 0;
|
|
||||||
_currentBaseHp = 0;
|
|
||||||
_currentBuildTowerStats.Clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,11 +236,7 @@ namespace GeometryTD.CustomComponent
|
||||||
LastDefeatedEnemyCount = _combatScheduler.DefeatedEnemyCount;
|
LastDefeatedEnemyCount = _combatScheduler.DefeatedEnemyCount;
|
||||||
LastGainedCoin = _combatScheduler.GainedCoin;
|
LastGainedCoin = _combatScheduler.GainedCoin;
|
||||||
LastGainedGold = _combatScheduler.GainedGold;
|
LastGainedGold = _combatScheduler.GainedGold;
|
||||||
_currentCoin = 0;
|
|
||||||
_currentGold = 0;
|
|
||||||
_currentBaseHp = 0;
|
|
||||||
CurrentLevel = null;
|
CurrentLevel = null;
|
||||||
_currentBuildTowerStats.Clear();
|
|
||||||
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,144 +259,53 @@ namespace GeometryTD.CustomComponent
|
||||||
{
|
{
|
||||||
_isCombatActive = false;
|
_isCombatActive = false;
|
||||||
CurrentLevel = null;
|
CurrentLevel = null;
|
||||||
_currentCoin = 0;
|
|
||||||
_currentGold = 0;
|
|
||||||
_currentBaseHp = 0;
|
|
||||||
_lastCombatSucceeded = true;
|
_lastCombatSucceeded = true;
|
||||||
LastDefeatedEnemyCount = 0;
|
LastDefeatedEnemyCount = 0;
|
||||||
LastGainedCoin = 0;
|
LastGainedCoin = 0;
|
||||||
LastGainedGold = 0;
|
LastGainedGold = 0;
|
||||||
_currentBuildTowerStats.Clear();
|
|
||||||
ShutdownCombatRuntime();
|
ShutdownCombatRuntime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ApplyBaseDamage(int damage)
|
|
||||||
{
|
|
||||||
int resolvedDamage = Mathf.Max(0, damage);
|
|
||||||
if (resolvedDamage <= 0 || CurrentLevel == null || !_isCombatActive)
|
|
||||||
{
|
|
||||||
return _currentBaseHp;
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentBaseHp = Mathf.Max(0, _currentBaseHp - resolvedDamage);
|
|
||||||
FireBaseHpChangedEventIfNeeded();
|
|
||||||
return _currentBaseHp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCombatEndedByScheduler(bool succeeded)
|
public void OnCombatEndedByScheduler(bool succeeded)
|
||||||
{
|
{
|
||||||
_lastCombatSucceeded = succeeded;
|
_lastCombatSucceeded = succeeded;
|
||||||
EndCombat();
|
EndCombat();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyEnemyDropReward(int coin, int gold)
|
|
||||||
{
|
|
||||||
bool coinChanged = false;
|
|
||||||
if (coin > 0)
|
|
||||||
{
|
|
||||||
_currentCoin += coin;
|
|
||||||
coinChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gold > 0)
|
|
||||||
{
|
|
||||||
_currentGold += gold;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (coinChanged)
|
|
||||||
{
|
|
||||||
FireCoinChangedEventIfNeeded();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryConsumeCoin(int coin)
|
public bool TryConsumeCoin(int coin)
|
||||||
{
|
{
|
||||||
int requiredCoin = Mathf.Max(0, coin);
|
if (Mathf.Max(0, coin) <= 0)
|
||||||
if (requiredCoin <= 0)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_currentCoin < requiredCoin)
|
if (!_isCombatActive)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentCoin -= requiredCoin;
|
return _combatScheduler.TryConsumeCoin(coin);
|
||||||
FireCoinChangedEventIfNeeded();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
|
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
|
||||||
{
|
{
|
||||||
stats = null;
|
if (!_isCombatActive)
|
||||||
if (buildIndex < 0 || buildIndex >= _currentBuildTowerStats.Count)
|
|
||||||
{
|
{
|
||||||
|
stats = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
stats = CloneTowerStats(_currentBuildTowerStats[buildIndex]);
|
return _combatScheduler.TryGetBuildTowerStats(buildIndex, out stats);
|
||||||
return stats != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCoin(int coin)
|
public void AddCoin(int coin)
|
||||||
{
|
{
|
||||||
int gainCoin = Mathf.Max(0, coin);
|
if (!_isCombatActive)
|
||||||
if (gainCoin <= 0)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentCoin += gainCoin;
|
_combatScheduler.AddCoin(coin);
|
||||||
FireCoinChangedEventIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void CacheBuildTowerStatsSnapshot()
|
|
||||||
{
|
|
||||||
_currentBuildTowerStats.Clear();
|
|
||||||
if (GameEntry.PlayerInventory == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IReadOnlyList<TowerItemData> towers = GameEntry.PlayerInventory.GetParticipantTowerSnapshot();
|
|
||||||
if (towers == null || towers.Count <= 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < towers.Count; i++)
|
|
||||||
{
|
|
||||||
TowerItemData tower = towers[i];
|
|
||||||
TowerStatsData clonedStats = CloneTowerStats(tower?.Stats);
|
|
||||||
if (clonedStats == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentBuildTowerStats.Add(clonedStats);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TowerStatsData CloneTowerStats(TowerStatsData source)
|
|
||||||
{
|
|
||||||
if (source == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TowerStatsData
|
|
||||||
{
|
|
||||||
AttackDamage = source.AttackDamage != null ? (int[])source.AttackDamage.Clone() : null,
|
|
||||||
DamageRandomRate = source.DamageRandomRate,
|
|
||||||
RotateSpeed = source.RotateSpeed != null ? (float[])source.RotateSpeed.Clone() : null,
|
|
||||||
AttackRange = source.AttackRange != null ? (float[])source.AttackRange.Clone() : null,
|
|
||||||
AttackSpeed = source.AttackSpeed != null ? (float[])source.AttackSpeed.Clone() : null,
|
|
||||||
AttackMethodType = source.AttackMethodType,
|
|
||||||
AttackPropertyType = source.AttackPropertyType,
|
|
||||||
Tags = source.Tags != null ? (TagType[])source.Tags.Clone() : null
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
|
|
@ -482,26 +370,5 @@ namespace GeometryTD.CustomComponent
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FireCoinChangedEventIfNeeded()
|
|
||||||
{
|
|
||||||
if (!_isCombatActive)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameEntry.Event.Fire(this, CombatCoinChangedEventArgs.Create(_currentCoin));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FireBaseHpChangedEventIfNeeded()
|
|
||||||
{
|
|
||||||
if (!_isCombatActive)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameEntry.Event.Fire(this, CombatBaseHpChangedEventArgs.Create(_currentBaseHp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using GameFramework.DataTable;
|
using GameFramework.DataTable;
|
||||||
|
using GeometryTD.CustomEvent;
|
||||||
|
using GeometryTD.CustomUtility;
|
||||||
using GeometryTD.DataTable;
|
using GeometryTD.DataTable;
|
||||||
using GeometryTD.Definition;
|
using GeometryTD.Definition;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
@ -22,6 +24,7 @@ namespace GeometryTD.CustomComponent
|
||||||
private const float RarityCurveScalePhase = 30f;
|
private const float RarityCurveScalePhase = 30f;
|
||||||
|
|
||||||
private readonly List<DROutGameDropPool> _eligibleDropPoolBuffer = new();
|
private readonly List<DROutGameDropPool> _eligibleDropPoolBuffer = new();
|
||||||
|
private readonly List<TowerStatsData> _buildTowerStatsSnapshot = new();
|
||||||
private readonly Dictionary<RarityType, float> _rarityRollWeightBuffer = new();
|
private readonly Dictionary<RarityType, float> _rarityRollWeightBuffer = new();
|
||||||
private readonly BackpackInventoryData _rewardInventory = new();
|
private readonly BackpackInventoryData _rewardInventory = new();
|
||||||
|
|
||||||
|
|
@ -30,46 +33,147 @@ namespace GeometryTD.CustomComponent
|
||||||
private IDataTable<DRBearingComp> _drBearingComp;
|
private IDataTable<DRBearingComp> _drBearingComp;
|
||||||
private IDataTable<DRBaseComp> _drBaseComp;
|
private IDataTable<DRBaseComp> _drBaseComp;
|
||||||
private long _nextDropItemInstanceId = 1;
|
private long _nextDropItemInstanceId = 1;
|
||||||
|
private bool _isCombatActive;
|
||||||
|
|
||||||
|
public int CurrentCoin { get; private set; }
|
||||||
|
public int CurrentGold => _isCombatActive ? GainedGold : 0;
|
||||||
|
public int CurrentBaseHp { get; private set; }
|
||||||
|
public int MaxBaseHp { get; private set; }
|
||||||
|
public int CurrentBuildTowerCount => _isCombatActive ? _buildTowerStatsSnapshot.Count : 0;
|
||||||
public int GainedCoin { get; private set; }
|
public int GainedCoin { get; private set; }
|
||||||
public int GainedGold { get; private set; }
|
public int GainedGold { get; private set; }
|
||||||
|
|
||||||
|
public void InitializeForCombat(DRLevel level)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
if (level == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaxBaseHp = Mathf.Max(0, level.BaseHp);
|
||||||
|
CurrentBaseHp = MaxBaseHp;
|
||||||
|
CurrentCoin = Mathf.Max(0, level.StartCoin);
|
||||||
|
CacheBuildTowerStatsSnapshot();
|
||||||
|
_isCombatActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkCombatEnded()
|
||||||
|
{
|
||||||
|
_isCombatActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
|
_isCombatActive = false;
|
||||||
|
CurrentCoin = 0;
|
||||||
|
CurrentBaseHp = 0;
|
||||||
|
MaxBaseHp = 0;
|
||||||
GainedCoin = 0;
|
GainedCoin = 0;
|
||||||
GainedGold = 0;
|
GainedGold = 0;
|
||||||
|
_buildTowerStatsSnapshot.Clear();
|
||||||
_rewardInventory.Gold = 0;
|
_rewardInventory.Gold = 0;
|
||||||
_rewardInventory.MuzzleComponents.Clear();
|
_rewardInventory.MuzzleComponents.Clear();
|
||||||
_rewardInventory.BearingComponents.Clear();
|
_rewardInventory.BearingComponents.Clear();
|
||||||
_rewardInventory.BaseComponents.Clear();
|
_rewardInventory.BaseComponents.Clear();
|
||||||
_rewardInventory.Towers.Clear();
|
_rewardInventory.Towers.Clear();
|
||||||
|
_rewardInventory.ParticipantTowerInstanceIds.Clear();
|
||||||
_nextDropItemInstanceId = 1;
|
_nextDropItemInstanceId = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BackpackInventoryData GetRewardInventorySnapshot()
|
public BackpackInventoryData GetRewardInventorySnapshot()
|
||||||
{
|
{
|
||||||
return new BackpackInventoryData
|
return InventoryCloneUtility.CloneInventory(_rewardInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryConsumeCoin(int coin)
|
||||||
|
{
|
||||||
|
int requiredCoin = Mathf.Max(0, coin);
|
||||||
|
if (requiredCoin <= 0)
|
||||||
{
|
{
|
||||||
Gold = _rewardInventory.Gold,
|
return true;
|
||||||
MuzzleComponents = new List<MuzzleCompItemData>(_rewardInventory.MuzzleComponents),
|
}
|
||||||
BearingComponents = new List<BearingCompItemData>(_rewardInventory.BearingComponents),
|
|
||||||
BaseComponents = new List<BaseCompItemData>(_rewardInventory.BaseComponents),
|
if (!_isCombatActive || CurrentCoin < requiredCoin)
|
||||||
Towers = new List<TowerItemData>(_rewardInventory.Towers)
|
{
|
||||||
};
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentCoin -= requiredCoin;
|
||||||
|
FireCoinChangedEvent(-requiredCoin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCoin(int coin)
|
||||||
|
{
|
||||||
|
int gainedCoin = Mathf.Max(0, coin);
|
||||||
|
if (!_isCombatActive || gainedCoin <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentCoin += gainedCoin;
|
||||||
|
FireCoinChangedEvent(gainedCoin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ApplyBaseDamage(int damage)
|
||||||
|
{
|
||||||
|
int resolvedDamage = Mathf.Max(0, damage);
|
||||||
|
if (!_isCombatActive || resolvedDamage <= 0)
|
||||||
|
{
|
||||||
|
return CurrentBaseHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int previousBaseHp = CurrentBaseHp;
|
||||||
|
CurrentBaseHp = Mathf.Max(0, CurrentBaseHp - resolvedDamage);
|
||||||
|
int deltaBaseHp = CurrentBaseHp - previousBaseHp;
|
||||||
|
if (deltaBaseHp != 0)
|
||||||
|
{
|
||||||
|
FireBaseHpChangedEvent(deltaBaseHp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CurrentBaseHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
|
||||||
|
{
|
||||||
|
stats = null;
|
||||||
|
if (!_isCombatActive || buildIndex < 0 || buildIndex >= _buildTowerStatsSnapshot.Count)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TowerStatsData sourceStats = _buildTowerStatsSnapshot[buildIndex];
|
||||||
|
if (sourceStats == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats = InventoryCloneUtility.CloneTowerStats(sourceStats);
|
||||||
|
return stats != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddEnemyDefeatedReward(int gainedCoin, int gainedGold)
|
public void AddEnemyDefeatedReward(int gainedCoin, int gainedGold)
|
||||||
{
|
{
|
||||||
|
if (!_isCombatActive)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int coin = Mathf.Max(0, gainedCoin);
|
int coin = Mathf.Max(0, gainedCoin);
|
||||||
int gold = Mathf.Max(0, gainedGold);
|
int gold = Mathf.Max(0, gainedGold);
|
||||||
GainedCoin += coin;
|
GainedCoin += coin;
|
||||||
GainedGold += gold;
|
GainedGold += gold;
|
||||||
|
if (coin > 0)
|
||||||
|
{
|
||||||
|
CurrentCoin += coin;
|
||||||
|
FireCoinChangedEvent(coin);
|
||||||
|
}
|
||||||
|
|
||||||
if (gold > 0)
|
if (gold > 0)
|
||||||
{
|
{
|
||||||
_rewardInventory.Gold += gold;
|
_rewardInventory.Gold += gold;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameEntry.CombatNode?.ApplyEnemyDropReward(coin, gold);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSettlementGold(int gainedGold)
|
public void AddSettlementGold(int gainedGold)
|
||||||
|
|
@ -84,6 +188,52 @@ namespace GeometryTD.CustomComponent
|
||||||
_rewardInventory.Gold += gold;
|
_rewardInventory.Gold += gold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CacheBuildTowerStatsSnapshot()
|
||||||
|
{
|
||||||
|
_buildTowerStatsSnapshot.Clear();
|
||||||
|
if (GameEntry.PlayerInventory == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IReadOnlyList<TowerItemData> towers = GameEntry.PlayerInventory.GetParticipantTowerSnapshot();
|
||||||
|
if (towers == null || towers.Count <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < towers.Count; i++)
|
||||||
|
{
|
||||||
|
TowerItemData tower = towers[i];
|
||||||
|
if (tower?.Stats == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildTowerStatsSnapshot.Add(InventoryCloneUtility.CloneTowerStats(tower.Stats));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireCoinChangedEvent(int deltaCoin)
|
||||||
|
{
|
||||||
|
if (!_isCombatActive)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEntry.Event.Fire(this, CombatCoinChangedEventArgs.Create(CurrentCoin, deltaCoin));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireBaseHpChangedEvent(int deltaBaseHp)
|
||||||
|
{
|
||||||
|
if (!_isCombatActive)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEntry.Event.Fire(this, CombatBaseHpChangedEventArgs.Create(CurrentBaseHp, deltaBaseHp));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 击杀敌人时的掉落入口。
|
/// 击杀敌人时的掉落入口。
|
||||||
/// displayPhaseIndex 会影响:
|
/// displayPhaseIndex 会影响:
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,10 @@ namespace GeometryTD.CustomComponent
|
||||||
public int DisplayPhaseIndex => _phaseLoopRuntime.DisplayPhaseIndex;
|
public int DisplayPhaseIndex => _phaseLoopRuntime.DisplayPhaseIndex;
|
||||||
public int PhaseCount => _phaseLoopRuntime.PhaseCount;
|
public int PhaseCount => _phaseLoopRuntime.PhaseCount;
|
||||||
public bool CanEndCombat => _phaseLoopRuntime.CanEndCombat;
|
public bool CanEndCombat => _phaseLoopRuntime.CanEndCombat;
|
||||||
|
public int CurrentCoin => _combatInRunResourceManager.CurrentCoin;
|
||||||
|
public int CurrentGold => _combatInRunResourceManager.CurrentGold;
|
||||||
|
public int CurrentBaseHp => _combatInRunResourceManager.CurrentBaseHp;
|
||||||
|
public int CurrentBuildTowerCount => _combatInRunResourceManager.CurrentBuildTowerCount;
|
||||||
public int DefeatedEnemyCount => _enemyManager.DefeatedEnemyCount;
|
public int DefeatedEnemyCount => _enemyManager.DefeatedEnemyCount;
|
||||||
public int GainedCoin => _combatInRunResourceManager.GainedCoin;
|
public int GainedCoin => _combatInRunResourceManager.GainedCoin;
|
||||||
public int GainedGold => _combatInRunResourceManager.GainedGold;
|
public int GainedGold => _combatInRunResourceManager.GainedGold;
|
||||||
|
|
@ -95,10 +99,10 @@ namespace GeometryTD.CustomComponent
|
||||||
_enemyManager.EndPhase();
|
_enemyManager.EndPhase();
|
||||||
_enemyManager.ResetCombatStats();
|
_enemyManager.ResetCombatStats();
|
||||||
ResetRuntime();
|
ResetRuntime();
|
||||||
_combatInRunResourceManager.Reset();
|
|
||||||
_isFinishAsVictory = true;
|
_isFinishAsVictory = true;
|
||||||
|
|
||||||
_currentLevel = level;
|
_currentLevel = level;
|
||||||
|
_combatInRunResourceManager.InitializeForCombat(level);
|
||||||
for (int i = 0; i < phases.Count; i++)
|
for (int i = 0; i < phases.Count; i++)
|
||||||
{
|
{
|
||||||
DRLevelPhase phase = phases[i];
|
DRLevelPhase phase = phases[i];
|
||||||
|
|
@ -215,6 +219,21 @@ namespace GeometryTD.CustomComponent
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryConsumeCoin(int coin)
|
||||||
|
{
|
||||||
|
return _combatInRunResourceManager.TryConsumeCoin(coin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCoin(int coin)
|
||||||
|
{
|
||||||
|
_combatInRunResourceManager.AddCoin(coin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
|
||||||
|
{
|
||||||
|
return _combatInRunResourceManager.TryGetBuildTowerStats(buildIndex, out stats);
|
||||||
|
}
|
||||||
|
|
||||||
private void ResetRuntime()
|
private void ResetRuntime()
|
||||||
{
|
{
|
||||||
_currentState = null;
|
_currentState = null;
|
||||||
|
|
@ -416,7 +435,7 @@ namespace GeometryTD.CustomComponent
|
||||||
private void ResolveBaseHpSnapshot(out int currentBaseHp, out int maxBaseHp)
|
private void ResolveBaseHpSnapshot(out int currentBaseHp, out int maxBaseHp)
|
||||||
{
|
{
|
||||||
currentBaseHp = Mathf.Max(0, GetCurrentBaseHp());
|
currentBaseHp = Mathf.Max(0, GetCurrentBaseHp());
|
||||||
maxBaseHp = _currentLevel != null ? Mathf.Max(0, _currentLevel.BaseHp) : 0;
|
maxBaseHp = _combatInRunResourceManager.MaxBaseHp;
|
||||||
if (maxBaseHp > 0)
|
if (maxBaseHp > 0)
|
||||||
{
|
{
|
||||||
currentBaseHp = Mathf.Clamp(currentBaseHp, 0, maxBaseHp);
|
currentBaseHp = Mathf.Clamp(currentBaseHp, 0, maxBaseHp);
|
||||||
|
|
@ -609,24 +628,12 @@ namespace GeometryTD.CustomComponent
|
||||||
|
|
||||||
private int ApplyBaseDamage(int damage)
|
private int ApplyBaseDamage(int damage)
|
||||||
{
|
{
|
||||||
CombatNodeComponent combatNode = GameEntry.CombatNode;
|
return _combatInRunResourceManager.ApplyBaseDamage(damage);
|
||||||
if (combatNode == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return combatNode.ApplyBaseDamage(damage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetCurrentBaseHp()
|
private int GetCurrentBaseHp()
|
||||||
{
|
{
|
||||||
CombatNodeComponent combatNode = GameEntry.CombatNode;
|
return Mathf.Max(0, _combatInRunResourceManager.CurrentBaseHp);
|
||||||
if (combatNode == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Mathf.Max(0, combatNode.CurrentBaseHp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CloseCombatFinishForm()
|
private void CloseCombatFinishForm()
|
||||||
|
|
@ -643,6 +650,7 @@ namespace GeometryTD.CustomComponent
|
||||||
{
|
{
|
||||||
_isCompleted = true;
|
_isCompleted = true;
|
||||||
_currentState = null;
|
_currentState = null;
|
||||||
|
_combatInRunResourceManager.MarkCombatEnded();
|
||||||
GameEntry.CombatNode?.OnCombatEndedByScheduler(succeeded);
|
GameEntry.CombatNode?.OnCombatEndedByScheduler(succeeded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,20 @@ namespace GeometryTD.CustomEvent
|
||||||
public override int Id => EventId;
|
public override int Id => EventId;
|
||||||
|
|
||||||
public int CurrentBaseHp { get; private set; }
|
public int CurrentBaseHp { get; private set; }
|
||||||
|
public int DeltaBaseHp { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
public CombatBaseHpChangedEventArgs()
|
public CombatBaseHpChangedEventArgs()
|
||||||
{
|
{
|
||||||
CurrentBaseHp = 100;
|
CurrentBaseHp = 100;
|
||||||
|
DeltaBaseHp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CombatBaseHpChangedEventArgs Create(int currentBaseHp)
|
public static CombatBaseHpChangedEventArgs Create(int currentBaseHp, int deltaBaseHp = 0)
|
||||||
{
|
{
|
||||||
var args = ReferencePool.Acquire<CombatBaseHpChangedEventArgs>();
|
var args = ReferencePool.Acquire<CombatBaseHpChangedEventArgs>();
|
||||||
args.CurrentBaseHp = currentBaseHp;
|
args.CurrentBaseHp = currentBaseHp;
|
||||||
|
args.DeltaBaseHp = deltaBaseHp;
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
@ -28,6 +31,7 @@ namespace GeometryTD.CustomEvent
|
||||||
public override void Clear()
|
public override void Clear()
|
||||||
{
|
{
|
||||||
CurrentBaseHp = 100;
|
CurrentBaseHp = 100;
|
||||||
|
DeltaBaseHp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,17 +10,20 @@ namespace GeometryTD.CustomEvent
|
||||||
public override int Id => EventId;
|
public override int Id => EventId;
|
||||||
|
|
||||||
public int CurrentCoin { get; private set; }
|
public int CurrentCoin { get; private set; }
|
||||||
|
public int DeltaCoin { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
public CombatCoinChangedEventArgs()
|
public CombatCoinChangedEventArgs()
|
||||||
{
|
{
|
||||||
CurrentCoin = 0;
|
CurrentCoin = 0;
|
||||||
|
DeltaCoin = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CombatCoinChangedEventArgs Create(int currentCoin)
|
public static CombatCoinChangedEventArgs Create(int currentCoin, int deltaCoin = 0)
|
||||||
{
|
{
|
||||||
var args = ReferencePool.Acquire<CombatCoinChangedEventArgs>();
|
var args = ReferencePool.Acquire<CombatCoinChangedEventArgs>();
|
||||||
args.CurrentCoin = currentCoin;
|
args.CurrentCoin = currentCoin;
|
||||||
|
args.DeltaCoin = deltaCoin;
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
@ -28,6 +31,7 @@ namespace GeometryTD.CustomEvent
|
||||||
public override void Clear()
|
public override void Clear()
|
||||||
{
|
{
|
||||||
CurrentCoin = 0;
|
CurrentCoin = 0;
|
||||||
|
DeltaCoin = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue