using System.Collections.Generic; using GeometryTD.CustomEvent; using GeometryTD.CustomUtility; using GeometryTD.DataTable; using GeometryTD.Definition; using UnityEngine; namespace GeometryTD.CustomComponent { public sealed class CombatRunResourceStore { private readonly List _buildTowerStatsSnapshot = new(); private readonly List _participantTowerSnapshot = new(); private readonly BackpackInventoryData _rewardInventory = new(); private BackpackInventoryData _combatInventorySnapshot = new(); 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 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); CacheCombatSnapshots(); _isCombatActive = true; } public void MarkCombatEnded() { _isCombatActive = false; } public void Reset() { _isCombatActive = false; CurrentCoin = 0; CurrentBaseHp = 0; MaxBaseHp = 0; GainedCoin = 0; GainedGold = 0; _buildTowerStatsSnapshot.Clear(); _participantTowerSnapshot.Clear(); _combatInventorySnapshot = new BackpackInventoryData(); _rewardInventory.Gold = 0; _rewardInventory.MuzzleComponents.Clear(); _rewardInventory.BearingComponents.Clear(); _rewardInventory.BaseComponents.Clear(); _rewardInventory.Towers.Clear(); _rewardInventory.ParticipantTowerInstanceIds.Clear(); } public BackpackInventoryData GetRewardInventorySnapshot() { return InventoryCloneUtility.CloneInventory(_rewardInventory); } public BackpackInventoryData GetCombatInventorySnapshot() { return InventoryCloneUtility.CloneInventory(_combatInventorySnapshot); } public IReadOnlyList GetParticipantTowerSnapshot() { List snapshot = new List(_participantTowerSnapshot.Count); for (int i = 0; i < _participantTowerSnapshot.Count; i++) { TowerItemData tower = _participantTowerSnapshot[i]; if (tower != null) { snapshot.Add(InventoryCloneUtility.CloneTower(tower)); } } return snapshot; } public IReadOnlyList GetParticipantTowerInstanceIdSnapshot() { List snapshot = new List(_participantTowerSnapshot.Count); for (int i = 0; i < _participantTowerSnapshot.Count; i++) { TowerItemData tower = _participantTowerSnapshot[i]; if (tower != null && tower.InstanceId > 0) { snapshot.Add(tower.InstanceId); } } return snapshot; } public bool TryConsumeCoin(int coin) { int requiredCoin = Mathf.Max(0, coin); if (requiredCoin <= 0) { return true; } if (!_isCombatActive || CurrentCoin < requiredCoin) { 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) { if (!_isCombatActive) { return; } int coin = Mathf.Max(0, gainedCoin); int gold = Mathf.Max(0, gainedGold); GainedCoin += coin; GainedGold += gold; if (coin > 0) { CurrentCoin += coin; FireCoinChangedEvent(coin); } if (gold > 0) { _rewardInventory.Gold += gold; } } public void AddSettlementGold(int gainedGold) { int gold = Mathf.Max(0, gainedGold); if (gold <= 0) { return; } GainedGold += gold; _rewardInventory.Gold += gold; } public void AddEnemyDefeatedLoot(TowerCompItemData droppedItem) { if (!_isCombatActive || droppedItem == null) { return; } AppendRewardItem(droppedItem); } private void CacheCombatSnapshots() { _buildTowerStatsSnapshot.Clear(); _participantTowerSnapshot.Clear(); _combatInventorySnapshot = GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : new BackpackInventoryData(); if (GameEntry.PlayerInventory == null) { return; } IReadOnlyList 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 == null) { continue; } _participantTowerSnapshot.Add(InventoryCloneUtility.CloneTower(tower)); if (tower.Stats != null) { _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)); } private void AppendRewardItem(TowerCompItemData droppedItem) { switch (droppedItem) { case MuzzleCompItemData muzzleComp: _rewardInventory.MuzzleComponents.Add(InventoryCloneUtility.CloneMuzzleComp(muzzleComp)); break; case BearingCompItemData bearingComp: _rewardInventory.BearingComponents.Add(InventoryCloneUtility.CloneBearingComp(bearingComp)); break; case BaseCompItemData baseComp: _rewardInventory.BaseComponents.Add(InventoryCloneUtility.CloneBaseComp(baseComp)); break; } } } }