init
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.CustomUtility;
|
||||
using GeometryTD.Definition;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public class PlayerInventoryComponent : GameFrameworkComponent
|
||||
{
|
||||
private const int MaxParticipantTowerCount = 4;
|
||||
|
||||
private PlayerInventoryState _state;
|
||||
private PlayerInventoryQueryModel _queryModel;
|
||||
private PlayerInventoryCommandModel _commandModel;
|
||||
private PlayerInventoryTowerRosterService _towerRosterService;
|
||||
private PlayerInventoryTowerAssemblyService _towerAssemblyService;
|
||||
private PlayerInventoryTradeService _tradeService;
|
||||
|
||||
public int Gold
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _queryModel.Gold;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnInit(BackpackInventoryData initialInventory = null)
|
||||
{
|
||||
EnsureServices();
|
||||
_commandModel.Initialize(initialInventory ?? InventorySeedUtility.CreateSampleInventory(), MaxParticipantTowerCount);
|
||||
|
||||
BackpackInventoryData inventory = _queryModel.Inventory;
|
||||
Log.Info(
|
||||
"PlayerInventory initialized. Gold={0}, Tower={1}, Muzzle={2}, Bearing={3}, Base={4}.",
|
||||
inventory.Gold,
|
||||
inventory.Towers.Count,
|
||||
inventory.MuzzleComponents.Count,
|
||||
inventory.BearingComponents.Count,
|
||||
inventory.BaseComponents.Count);
|
||||
}
|
||||
|
||||
public BackpackInventoryData GetInventorySnapshot()
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _queryModel.GetSnapshot();
|
||||
}
|
||||
|
||||
public void ReplaceInventorySnapshot(BackpackInventoryData inventorySnapshot)
|
||||
{
|
||||
EnsureServices();
|
||||
_commandModel.ReplaceInventorySnapshot(inventorySnapshot, MaxParticipantTowerCount);
|
||||
}
|
||||
|
||||
public IReadOnlyList<TowerItemData> GetParticipantTowerSnapshot()
|
||||
{
|
||||
EnsureInitialized();
|
||||
|
||||
BackpackInventoryData inventory = _queryModel.Inventory;
|
||||
if (inventory?.ParticipantTowerInstanceIds == null || inventory.ParticipantTowerInstanceIds.Count <= 0)
|
||||
{
|
||||
return new List<TowerItemData>();
|
||||
}
|
||||
|
||||
List<TowerItemData> result = new List<TowerItemData>(inventory.ParticipantTowerInstanceIds.Count);
|
||||
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count && result.Count < MaxParticipantTowerCount; i++)
|
||||
{
|
||||
long towerId = inventory.ParticipantTowerInstanceIds[i];
|
||||
if (!_queryModel.TryGetTowerById(towerId, out TowerItemData tower) || tower == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(InventoryCloneUtility.CloneTower(tower));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void MergeInventory(BackpackInventoryData gainedInventory)
|
||||
{
|
||||
EnsureInitialized();
|
||||
PlayerInventoryMergeSummary summary = _commandModel.MergeInventory(gainedInventory);
|
||||
if (!summary.HasAnyGain)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Info(
|
||||
"PlayerInventory merged reward. Gold+{0}, Tower+{1}, Muzzle+{2}, Bearing+{3}, Base+{4}.",
|
||||
summary.GainedGold,
|
||||
summary.GainedTowerCount,
|
||||
summary.GainedMuzzleCount,
|
||||
summary.GainedBearingCount,
|
||||
summary.GainedBaseCount);
|
||||
}
|
||||
|
||||
public bool TryConsumeGold(int costGold)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _commandModel.TryConsumeGold(costGold);
|
||||
}
|
||||
|
||||
public bool TryPurchaseComponent(TowerCompItemData item, int price)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _tradeService.TryPurchaseComponent(item, price);
|
||||
}
|
||||
|
||||
public void AddGold(int gainGold)
|
||||
{
|
||||
EnsureInitialized();
|
||||
_commandModel.AddGold(gainGold);
|
||||
}
|
||||
|
||||
public ParticipantTowerAssignResult TryAddParticipantTower(long towerInstanceId, int maxCount = 4)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _towerRosterService.TryAddParticipantTower(towerInstanceId, maxCount);
|
||||
}
|
||||
|
||||
public bool TryRemoveParticipantTower(long towerInstanceId)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _towerRosterService.TryRemoveParticipantTower(towerInstanceId);
|
||||
}
|
||||
|
||||
public bool TryAssembleTower(
|
||||
long muzzleInstanceId,
|
||||
long bearingInstanceId,
|
||||
long baseInstanceId,
|
||||
out TowerItemData assembledTower)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _towerAssemblyService.TryAssembleTower(
|
||||
muzzleInstanceId,
|
||||
bearingInstanceId,
|
||||
baseInstanceId,
|
||||
out assembledTower);
|
||||
}
|
||||
|
||||
public int ReduceTowerEndurance(IReadOnlyList<long> towerInstanceIds, float enduranceLoss)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _towerRosterService.ReduceTowerEndurance(towerInstanceIds, enduranceLoss);
|
||||
}
|
||||
|
||||
public bool TryDisassembleTower(long towerInstanceId)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _towerAssemblyService.TryDisassembleTower(towerInstanceId);
|
||||
}
|
||||
|
||||
public bool TryGetSaleCandidate(long itemId, out PlayerInventorySaleCandidate candidate)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _tradeService.TryGetSaleCandidate(itemId, out candidate);
|
||||
}
|
||||
|
||||
public bool TrySellItems(IReadOnlyCollection<long> itemIds, out PlayerInventorySaleResult result)
|
||||
{
|
||||
EnsureInitialized();
|
||||
return _tradeService.TrySellItems(itemIds, out result);
|
||||
}
|
||||
|
||||
private void EnsureInitialized()
|
||||
{
|
||||
if (_queryModel.IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OnInit();
|
||||
}
|
||||
|
||||
private void EnsureServices()
|
||||
{
|
||||
_state ??= new PlayerInventoryState();
|
||||
_queryModel ??= new PlayerInventoryQueryModel(_state);
|
||||
_commandModel ??= new PlayerInventoryCommandModel(_state);
|
||||
_towerRosterService ??= new PlayerInventoryTowerRosterService(_queryModel, MaxParticipantTowerCount);
|
||||
_towerAssemblyService ??= new PlayerInventoryTowerAssemblyService(_queryModel, _commandModel);
|
||||
_tradeService ??= new PlayerInventoryTradeService(_queryModel, _commandModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.CustomUtility;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public struct PlayerInventoryMergeSummary
|
||||
{
|
||||
public int GainedGold;
|
||||
public int GainedMuzzleCount;
|
||||
public int GainedBearingCount;
|
||||
public int GainedBaseCount;
|
||||
public int GainedTowerCount;
|
||||
|
||||
public bool HasAnyGain =>
|
||||
GainedGold > 0 || GainedMuzzleCount > 0 || GainedBearingCount > 0 || GainedBaseCount > 0 ||
|
||||
GainedTowerCount > 0;
|
||||
}
|
||||
|
||||
public sealed class PlayerInventoryState
|
||||
{
|
||||
public BackpackInventoryData Inventory = new BackpackInventoryData();
|
||||
public long NextInstanceId = 1;
|
||||
public bool IsInitialized;
|
||||
}
|
||||
|
||||
public sealed class PlayerInventoryQueryModel
|
||||
{
|
||||
private readonly PlayerInventoryState _state;
|
||||
|
||||
public PlayerInventoryQueryModel(PlayerInventoryState state)
|
||||
{
|
||||
_state = state;
|
||||
}
|
||||
|
||||
public BackpackInventoryData Inventory => _state.Inventory;
|
||||
public bool IsInitialized => _state.IsInitialized;
|
||||
public int Gold => _state.Inventory.Gold;
|
||||
|
||||
public BackpackInventoryData GetSnapshot()
|
||||
{
|
||||
return InventoryCloneUtility.CloneInventory(_state.Inventory);
|
||||
}
|
||||
|
||||
public bool TryGetTowerById(long towerInstanceId, out TowerItemData tower)
|
||||
{
|
||||
return InventoryParticipantUtility.TryGetTowerById(_state.Inventory, towerInstanceId, out tower);
|
||||
}
|
||||
|
||||
public bool TryGetComponentById<TComp>(List<TComp> components, long instanceId, out TComp result)
|
||||
where TComp : TowerCompItemData
|
||||
{
|
||||
result = null;
|
||||
if (components == null || instanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < components.Count; i++)
|
||||
{
|
||||
TComp component = components[i];
|
||||
if (component != null && component.InstanceId == instanceId)
|
||||
{
|
||||
result = component;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PlayerInventoryCommandModel
|
||||
{
|
||||
private readonly PlayerInventoryState _state;
|
||||
|
||||
public PlayerInventoryCommandModel(PlayerInventoryState state)
|
||||
{
|
||||
_state = state;
|
||||
}
|
||||
|
||||
public void Initialize(BackpackInventoryData sourceInventory, int maxParticipantTowerCount)
|
||||
{
|
||||
_state.Inventory = InventoryCloneUtility.CloneInventory(sourceInventory);
|
||||
InventoryParticipantUtility.NormalizeParticipantState(_state.Inventory, maxParticipantTowerCount);
|
||||
RebuildNextInstanceId();
|
||||
_state.IsInitialized = true;
|
||||
}
|
||||
|
||||
public void ReplaceInventorySnapshot(BackpackInventoryData sourceInventory, int maxParticipantTowerCount)
|
||||
{
|
||||
Initialize(sourceInventory, maxParticipantTowerCount);
|
||||
}
|
||||
|
||||
public PlayerInventoryMergeSummary MergeInventory(BackpackInventoryData gainedInventory)
|
||||
{
|
||||
PlayerInventoryMergeSummary summary = default;
|
||||
if (gainedInventory == null)
|
||||
{
|
||||
return summary;
|
||||
}
|
||||
|
||||
summary.GainedGold = Mathf.Max(0, gainedInventory.Gold);
|
||||
if (summary.GainedGold > 0)
|
||||
{
|
||||
_state.Inventory.Gold += summary.GainedGold;
|
||||
}
|
||||
|
||||
if (gainedInventory.MuzzleComponents != null)
|
||||
{
|
||||
for (int i = 0; i < gainedInventory.MuzzleComponents.Count; i++)
|
||||
{
|
||||
MuzzleCompItemData source = gainedInventory.MuzzleComponents[i];
|
||||
if (source == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MuzzleCompItemData cloned = InventoryCloneUtility.CloneMuzzleComp(source);
|
||||
cloned.InstanceId = AllocateInstanceId();
|
||||
_state.Inventory.MuzzleComponents.Add(cloned);
|
||||
summary.GainedMuzzleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (gainedInventory.BearingComponents != null)
|
||||
{
|
||||
for (int i = 0; i < gainedInventory.BearingComponents.Count; i++)
|
||||
{
|
||||
BearingCompItemData source = gainedInventory.BearingComponents[i];
|
||||
if (source == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BearingCompItemData cloned = InventoryCloneUtility.CloneBearingComp(source);
|
||||
cloned.InstanceId = AllocateInstanceId();
|
||||
_state.Inventory.BearingComponents.Add(cloned);
|
||||
summary.GainedBearingCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (gainedInventory.BaseComponents != null)
|
||||
{
|
||||
for (int i = 0; i < gainedInventory.BaseComponents.Count; i++)
|
||||
{
|
||||
BaseCompItemData source = gainedInventory.BaseComponents[i];
|
||||
if (source == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BaseCompItemData cloned = InventoryCloneUtility.CloneBaseComp(source);
|
||||
cloned.InstanceId = AllocateInstanceId();
|
||||
_state.Inventory.BaseComponents.Add(cloned);
|
||||
summary.GainedBaseCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (gainedInventory.Towers != null)
|
||||
{
|
||||
for (int i = 0; i < gainedInventory.Towers.Count; i++)
|
||||
{
|
||||
TowerItemData source = gainedInventory.Towers[i];
|
||||
if (source == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TowerItemData cloned = InventoryCloneUtility.CloneTower(source);
|
||||
cloned.InstanceId = AllocateInstanceId();
|
||||
_state.Inventory.Towers.Add(cloned);
|
||||
summary.GainedTowerCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
public bool TryConsumeGold(int costGold)
|
||||
{
|
||||
int resolvedCost = Mathf.Max(0, costGold);
|
||||
if (resolvedCost <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_state.Inventory.Gold < resolvedCost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_state.Inventory.Gold -= resolvedCost;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddGold(int gainGold)
|
||||
{
|
||||
int resolvedGain = Mathf.Max(0, gainGold);
|
||||
if (resolvedGain <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_state.Inventory.Gold += resolvedGain;
|
||||
}
|
||||
|
||||
public long AllocateInstanceId()
|
||||
{
|
||||
if (_state.NextInstanceId < 1)
|
||||
{
|
||||
_state.NextInstanceId = 1;
|
||||
}
|
||||
|
||||
return _state.NextInstanceId++;
|
||||
}
|
||||
|
||||
private void RebuildNextInstanceId()
|
||||
{
|
||||
long maxInstanceId = 0;
|
||||
BackpackInventoryData inventory = _state.Inventory;
|
||||
if (inventory.Towers != null)
|
||||
{
|
||||
for (int i = 0; i < inventory.Towers.Count; i++)
|
||||
{
|
||||
TowerItemData item = inventory.Towers[i];
|
||||
if (item != null)
|
||||
{
|
||||
maxInstanceId = Math.Max(maxInstanceId, item.InstanceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory.MuzzleComponents != null)
|
||||
{
|
||||
for (int i = 0; i < inventory.MuzzleComponents.Count; i++)
|
||||
{
|
||||
MuzzleCompItemData item = inventory.MuzzleComponents[i];
|
||||
if (item != null)
|
||||
{
|
||||
maxInstanceId = Math.Max(maxInstanceId, item.InstanceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory.BearingComponents != null)
|
||||
{
|
||||
for (int i = 0; i < inventory.BearingComponents.Count; i++)
|
||||
{
|
||||
BearingCompItemData item = inventory.BearingComponents[i];
|
||||
if (item != null)
|
||||
{
|
||||
maxInstanceId = Math.Max(maxInstanceId, item.InstanceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory.BaseComponents != null)
|
||||
{
|
||||
for (int i = 0; i < inventory.BaseComponents.Count; i++)
|
||||
{
|
||||
BaseCompItemData item = inventory.BaseComponents[i];
|
||||
if (item != null)
|
||||
{
|
||||
maxInstanceId = Math.Max(maxInstanceId, item.InstanceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_state.NextInstanceId = Math.Max(1, maxInstanceId + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
using System.Collections.Generic;
|
||||
using GameFramework.DataTable;
|
||||
using GeometryTD.CustomUtility;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
internal sealed class PlayerInventoryTowerAssemblyService
|
||||
{
|
||||
private const int TowerLevelCount = 5;
|
||||
|
||||
private readonly PlayerInventoryQueryModel _queryModel;
|
||||
private readonly PlayerInventoryCommandModel _commandModel;
|
||||
private IDataTable<DRMuzzleComp> _drMuzzleComp;
|
||||
private IDataTable<DRBearingComp> _drBearingComp;
|
||||
private IDataTable<DRBaseComp> _drBaseComp;
|
||||
|
||||
public PlayerInventoryTowerAssemblyService(
|
||||
PlayerInventoryQueryModel queryModel,
|
||||
PlayerInventoryCommandModel commandModel)
|
||||
{
|
||||
_queryModel = queryModel;
|
||||
_commandModel = commandModel;
|
||||
}
|
||||
|
||||
public bool TryAssembleTower(
|
||||
long muzzleInstanceId,
|
||||
long bearingInstanceId,
|
||||
long baseInstanceId,
|
||||
out TowerItemData assembledTower)
|
||||
{
|
||||
assembledTower = null;
|
||||
BackpackInventoryData inventory = _queryModel.Inventory;
|
||||
if (muzzleInstanceId <= 0 || bearingInstanceId <= 0 || baseInstanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_queryModel.TryGetComponentById(inventory.MuzzleComponents, muzzleInstanceId, out MuzzleCompItemData muzzleComp) ||
|
||||
!_queryModel.TryGetComponentById(inventory.BearingComponents, bearingInstanceId, out BearingCompItemData bearingComp) ||
|
||||
!_queryModel.TryGetComponentById(inventory.BaseComponents, baseInstanceId, out BaseCompItemData baseComp))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (muzzleComp.IsAssembledIntoTower || bearingComp.IsAssembledIntoTower || baseComp.IsAssembledIntoTower)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryBuildTowerStats(muzzleComp, bearingComp, baseComp, out TowerStatsData stats))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
long towerInstanceId = _commandModel.AllocateInstanceId();
|
||||
TowerItemData tower = new TowerItemData
|
||||
{
|
||||
InstanceId = towerInstanceId,
|
||||
Name = $"组装防御塔-{towerInstanceId}",
|
||||
Rarity = InventoryRarityRuleService.ResolveTowerRarity(
|
||||
muzzleComp.Rarity,
|
||||
bearingComp.Rarity,
|
||||
baseComp.Rarity),
|
||||
MuzzleComponentInstanceId = muzzleComp.InstanceId,
|
||||
BearingComponentInstanceId = bearingComp.InstanceId,
|
||||
BaseComponentInstanceId = baseComp.InstanceId,
|
||||
Stats = stats
|
||||
};
|
||||
|
||||
muzzleComp.IsAssembledIntoTower = true;
|
||||
bearingComp.IsAssembledIntoTower = true;
|
||||
baseComp.IsAssembledIntoTower = true;
|
||||
inventory.Towers.Add(tower);
|
||||
assembledTower = InventoryCloneUtility.CloneTower(tower);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryBuildTowerStats(
|
||||
MuzzleCompItemData muzzleComp,
|
||||
BearingCompItemData bearingComp,
|
||||
BaseCompItemData baseComp,
|
||||
out TowerStatsData stats)
|
||||
{
|
||||
stats = null;
|
||||
if (muzzleComp == null || bearingComp == null || baseComp == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DRMuzzleComp muzzleConfig = EnsureMuzzleTable()?.GetDataRow(muzzleComp.ConfigId);
|
||||
DRBearingComp bearingConfig = EnsureBearingTable()?.GetDataRow(bearingComp.ConfigId);
|
||||
DRBaseComp baseConfig = EnsureBaseTable()?.GetDataRow(baseComp.ConfigId);
|
||||
if (muzzleConfig == null || bearingConfig == null || baseConfig == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
stats = new TowerStatsData
|
||||
{
|
||||
AttackDamage = BuildLevelIntArray(muzzleComp.AttackDamage, muzzleComp.Rarity, muzzleConfig.AttackDamagePerLevel),
|
||||
DamageRandomRate = Mathf.Max(0f, muzzleComp.DamageRandomRate),
|
||||
RotateSpeed = BuildLevelFloatArray(bearingComp.RotateSpeed, bearingComp.Rarity, bearingConfig.RotateSpeedPerLevel),
|
||||
AttackRange = BuildLevelFloatArray(bearingComp.AttackRange, bearingComp.Rarity, bearingConfig.AttackRangePerLevel),
|
||||
AttackSpeed = BuildLevelFloatArray(baseComp.AttackSpeed, baseComp.Rarity, baseConfig.AttackSpeedPerLevel),
|
||||
AttackMethodType = muzzleComp.AttackMethodType,
|
||||
AttackPropertyType = baseComp.AttackPropertyType,
|
||||
TagRuntimes = TowerTagAggregationService.AggregateTowerTags(
|
||||
muzzleComp.Tags,
|
||||
bearingComp.Tags,
|
||||
baseComp.Tags)
|
||||
};
|
||||
stats.Tags = TowerTagAggregationService.FlattenUniqueTags(stats.TagRuntimes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int[] BuildLevelIntArray(int[] rarityBaseArray, RarityType rarity, int perLevel)
|
||||
{
|
||||
int baseValue = ResolveRarityBaseValue(rarityBaseArray, rarity);
|
||||
int[] values = new int[TowerLevelCount];
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
values[i] = Mathf.Max(0, baseValue + perLevel * i);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private static float[] BuildLevelFloatArray(float[] rarityBaseArray, RarityType rarity, float perLevel)
|
||||
{
|
||||
float baseValue = ResolveRarityBaseValue(rarityBaseArray, rarity);
|
||||
float[] values = new float[TowerLevelCount];
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
values[i] = Mathf.Max(0f, baseValue + perLevel * i);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private static int ResolveRarityBaseValue(int[] rarityBaseArray, RarityType rarity)
|
||||
{
|
||||
if (rarityBaseArray == null || rarityBaseArray.Length <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rarityIndex = Mathf.Clamp((int)rarity - 1, 0, rarityBaseArray.Length - 1);
|
||||
return rarityBaseArray[rarityIndex];
|
||||
}
|
||||
|
||||
private static float ResolveRarityBaseValue(float[] rarityBaseArray, RarityType rarity)
|
||||
{
|
||||
if (rarityBaseArray == null || rarityBaseArray.Length <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
int rarityIndex = Mathf.Clamp((int)rarity - 1, 0, rarityBaseArray.Length - 1);
|
||||
return rarityBaseArray[rarityIndex];
|
||||
}
|
||||
|
||||
private IDataTable<DRMuzzleComp> EnsureMuzzleTable()
|
||||
{
|
||||
_drMuzzleComp ??= GameEntry.DataTable.GetDataTable<DRMuzzleComp>();
|
||||
return _drMuzzleComp;
|
||||
}
|
||||
|
||||
private IDataTable<DRBearingComp> EnsureBearingTable()
|
||||
{
|
||||
_drBearingComp ??= GameEntry.DataTable.GetDataTable<DRBearingComp>();
|
||||
return _drBearingComp;
|
||||
}
|
||||
|
||||
private IDataTable<DRBaseComp> EnsureBaseTable()
|
||||
{
|
||||
_drBaseComp ??= GameEntry.DataTable.GetDataTable<DRBaseComp>();
|
||||
return _drBaseComp;
|
||||
}
|
||||
|
||||
public bool TryDisassembleTower(long towerInstanceId)
|
||||
{
|
||||
BackpackInventoryData inventory = _queryModel.Inventory;
|
||||
if (towerInstanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_queryModel.TryGetTowerById(towerInstanceId, out TowerItemData tower) || tower == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_queryModel.TryGetComponentById(inventory.MuzzleComponents, tower.MuzzleComponentInstanceId, out MuzzleCompItemData muzzleComp) ||
|
||||
!_queryModel.TryGetComponentById(inventory.BearingComponents, tower.BearingComponentInstanceId, out BearingCompItemData bearingComp) ||
|
||||
!_queryModel.TryGetComponentById(inventory.BaseComponents, tower.BaseComponentInstanceId, out BaseCompItemData baseComp))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
InventoryParticipantUtility.TryRemoveParticipantTower(inventory, towerInstanceId, MaxParticipantTowerCount);
|
||||
|
||||
muzzleComp.IsAssembledIntoTower = false;
|
||||
bearingComp.IsAssembledIntoTower = false;
|
||||
baseComp.IsAssembledIntoTower = false;
|
||||
|
||||
inventory.Towers.Remove(tower);
|
||||
return true;
|
||||
}
|
||||
|
||||
private const int MaxParticipantTowerCount = 4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.CustomUtility;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public sealed class PlayerInventoryTowerRosterService
|
||||
{
|
||||
private readonly PlayerInventoryQueryModel _queryModel;
|
||||
private readonly int _maxParticipantTowerCount;
|
||||
|
||||
public PlayerInventoryTowerRosterService(PlayerInventoryQueryModel queryModel, int maxParticipantTowerCount)
|
||||
{
|
||||
_queryModel = queryModel;
|
||||
_maxParticipantTowerCount = Mathf.Max(1, maxParticipantTowerCount);
|
||||
}
|
||||
|
||||
public ParticipantTowerAssignResult TryAddParticipantTower(long towerInstanceId, int maxCount)
|
||||
{
|
||||
int resolvedMaxCount = Mathf.Max(1, maxCount);
|
||||
resolvedMaxCount = Mathf.Min(resolvedMaxCount, _maxParticipantTowerCount);
|
||||
return InventoryParticipantUtility.TryAddParticipantTower(
|
||||
_queryModel.Inventory,
|
||||
towerInstanceId,
|
||||
resolvedMaxCount);
|
||||
}
|
||||
|
||||
public bool TryRemoveParticipantTower(long towerInstanceId)
|
||||
{
|
||||
return InventoryParticipantUtility.TryRemoveParticipantTower(
|
||||
_queryModel.Inventory,
|
||||
towerInstanceId,
|
||||
_maxParticipantTowerCount);
|
||||
}
|
||||
|
||||
public int ReduceTowerEndurance(IReadOnlyList<long> towerInstanceIds, float enduranceLoss)
|
||||
{
|
||||
return InventoryTowerEnduranceUtility.ReduceTowerEndurance(
|
||||
_queryModel.Inventory,
|
||||
towerInstanceIds,
|
||||
enduranceLoss);
|
||||
}
|
||||
}
|
||||
|
||||
public static class InventoryTowerEnduranceUtility
|
||||
{
|
||||
public static int ReduceTowerEndurance(
|
||||
BackpackInventoryData inventory,
|
||||
IReadOnlyList<long> towerInstanceIds,
|
||||
float enduranceLoss)
|
||||
{
|
||||
float resolvedLoss = Mathf.Max(0f, enduranceLoss);
|
||||
if (inventory?.Towers == null ||
|
||||
inventory.Towers.Count <= 0 ||
|
||||
resolvedLoss <= 0f ||
|
||||
towerInstanceIds == null ||
|
||||
towerInstanceIds.Count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Dictionary<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(inventory.MuzzleComponents);
|
||||
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(inventory.BearingComponents);
|
||||
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(inventory.BaseComponents);
|
||||
HashSet<long> processedTowerIds = new HashSet<long>();
|
||||
|
||||
int affectedCount = 0;
|
||||
for (int i = 0; i < towerInstanceIds.Count; i++)
|
||||
{
|
||||
long towerInstanceId = towerInstanceIds[i];
|
||||
if (towerInstanceId <= 0 || !processedTowerIds.Add(towerInstanceId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!InventoryParticipantUtility.TryGetTowerById(inventory, towerInstanceId, out TowerItemData tower) ||
|
||||
tower == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool towerAffected = false;
|
||||
if (muzzleMap.TryGetValue(tower.MuzzleComponentInstanceId, out MuzzleCompItemData muzzleComp))
|
||||
{
|
||||
towerAffected |= TryReduceComponentEndurance(muzzleComp, resolvedLoss);
|
||||
}
|
||||
|
||||
if (bearingMap.TryGetValue(tower.BearingComponentInstanceId, out BearingCompItemData bearingComp))
|
||||
{
|
||||
towerAffected |= TryReduceComponentEndurance(bearingComp, resolvedLoss);
|
||||
}
|
||||
|
||||
if (baseMap.TryGetValue(tower.BaseComponentInstanceId, out BaseCompItemData baseComp))
|
||||
{
|
||||
towerAffected |= TryReduceComponentEndurance(baseComp, resolvedLoss);
|
||||
}
|
||||
|
||||
if (towerAffected)
|
||||
{
|
||||
affectedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return affectedCount;
|
||||
}
|
||||
|
||||
private static bool TryReduceComponentEndurance(TowerCompItemData component, float enduranceLoss)
|
||||
{
|
||||
if (component == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float originalEndurance = component.Endurance;
|
||||
float nextEndurance = Mathf.Clamp(originalEndurance - Mathf.Max(0f, enduranceLoss), 0f, 100f);
|
||||
if (nextEndurance >= originalEndurance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
component.Endurance = nextEndurance;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Dictionary<long, TComp> BuildComponentMap<TComp>(List<TComp> components)
|
||||
where TComp : TowerCompItemData
|
||||
{
|
||||
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
|
||||
if (components == null || components.Count <= 0)
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
for (int i = 0; i < components.Count; i++)
|
||||
{
|
||||
TComp component = components[i];
|
||||
if (component == null || component.InstanceId <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
map[component.InstanceId] = component;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
using System.Collections.Generic;
|
||||
using GameFramework.DataTable;
|
||||
using GeometryTD.CustomUtility;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.CustomComponent
|
||||
{
|
||||
public enum PlayerInventorySaleFailureReason : byte
|
||||
{
|
||||
None = 0,
|
||||
InvalidSelection = 1,
|
||||
ItemNotFound = 2,
|
||||
AssembledComponent = 3,
|
||||
ParticipantTower = 4,
|
||||
MissingTowerComponent = 5
|
||||
}
|
||||
|
||||
public sealed class PlayerInventorySaleCandidate
|
||||
{
|
||||
public long ItemId;
|
||||
public bool IsSellable;
|
||||
public bool IsTower;
|
||||
public int Price;
|
||||
public PlayerInventorySaleFailureReason FailureReason;
|
||||
}
|
||||
|
||||
public sealed class PlayerInventorySaleResult
|
||||
{
|
||||
public int GainedGold;
|
||||
public int SoldComponentCount;
|
||||
public int SoldTowerCount;
|
||||
public PlayerInventorySaleFailureReason FailureReason;
|
||||
|
||||
public bool IsSuccess => FailureReason == PlayerInventorySaleFailureReason.None;
|
||||
public int SoldItemCount => SoldComponentCount + SoldTowerCount;
|
||||
}
|
||||
|
||||
public sealed class PlayerInventoryTradeService
|
||||
{
|
||||
private readonly PlayerInventoryQueryModel _queryModel;
|
||||
private readonly PlayerInventoryCommandModel _commandModel;
|
||||
private IDataTable<DRShopPrice> _shopPriceTable;
|
||||
|
||||
public PlayerInventoryTradeService(
|
||||
PlayerInventoryQueryModel queryModel,
|
||||
PlayerInventoryCommandModel commandModel,
|
||||
IDataTable<DRShopPrice> shopPriceTable = null)
|
||||
{
|
||||
_queryModel = queryModel;
|
||||
_commandModel = commandModel;
|
||||
_shopPriceTable = shopPriceTable;
|
||||
}
|
||||
|
||||
public bool TryPurchaseComponent(TowerCompItemData item, int price)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_commandModel.TryConsumeGold(price))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BackpackInventoryData inventoryDelta = WrapSingleItem(item);
|
||||
PlayerInventoryMergeSummary summary = _commandModel.MergeInventory(inventoryDelta);
|
||||
return summary.HasAnyGain;
|
||||
}
|
||||
|
||||
public bool TryGetSaleCandidate(long itemId, out PlayerInventorySaleCandidate candidate)
|
||||
{
|
||||
candidate = BuildSaleCandidate(itemId);
|
||||
return candidate != null;
|
||||
}
|
||||
|
||||
public bool TrySellItems(IReadOnlyCollection<long> itemIds, out PlayerInventorySaleResult result)
|
||||
{
|
||||
result = new PlayerInventorySaleResult();
|
||||
if (itemIds == null || itemIds.Count <= 0)
|
||||
{
|
||||
result.FailureReason = PlayerInventorySaleFailureReason.InvalidSelection;
|
||||
return false;
|
||||
}
|
||||
|
||||
HashSet<long> uniqueIds = new HashSet<long>();
|
||||
List<PlayerInventorySaleCandidate> candidates = new List<PlayerInventorySaleCandidate>(itemIds.Count);
|
||||
foreach (long itemId in itemIds)
|
||||
{
|
||||
if (itemId <= 0 || !uniqueIds.Add(itemId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerInventorySaleCandidate candidate = BuildSaleCandidate(itemId);
|
||||
if (candidate == null || !candidate.IsSellable)
|
||||
{
|
||||
result.FailureReason = candidate?.FailureReason ?? PlayerInventorySaleFailureReason.ItemNotFound;
|
||||
return false;
|
||||
}
|
||||
|
||||
candidates.Add(candidate);
|
||||
}
|
||||
|
||||
if (candidates.Count <= 0)
|
||||
{
|
||||
result.FailureReason = PlayerInventorySaleFailureReason.InvalidSelection;
|
||||
return false;
|
||||
}
|
||||
|
||||
BackpackInventoryData inventory = _queryModel.Inventory;
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
PlayerInventorySaleCandidate candidate = candidates[i];
|
||||
if (candidate.IsTower)
|
||||
{
|
||||
if (!TryRemoveTower(inventory, candidate.ItemId))
|
||||
{
|
||||
result.FailureReason = PlayerInventorySaleFailureReason.MissingTowerComponent;
|
||||
return false;
|
||||
}
|
||||
|
||||
result.SoldTowerCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TryRemoveComponent(inventory, candidate.ItemId))
|
||||
{
|
||||
result.FailureReason = PlayerInventorySaleFailureReason.ItemNotFound;
|
||||
return false;
|
||||
}
|
||||
|
||||
result.SoldComponentCount++;
|
||||
}
|
||||
|
||||
result.GainedGold += Mathf.Max(0, candidate.Price);
|
||||
}
|
||||
|
||||
_commandModel.AddGold(result.GainedGold);
|
||||
result.FailureReason = PlayerInventorySaleFailureReason.None;
|
||||
return true;
|
||||
}
|
||||
|
||||
private PlayerInventorySaleCandidate BuildSaleCandidate(long itemId)
|
||||
{
|
||||
if (itemId <= 0)
|
||||
{
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = itemId,
|
||||
IsSellable = false,
|
||||
FailureReason = PlayerInventorySaleFailureReason.InvalidSelection
|
||||
};
|
||||
}
|
||||
|
||||
BackpackInventoryData inventory = _queryModel.Inventory;
|
||||
if (inventory == null)
|
||||
{
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = itemId,
|
||||
IsSellable = false,
|
||||
FailureReason = PlayerInventorySaleFailureReason.ItemNotFound
|
||||
};
|
||||
}
|
||||
|
||||
if (_queryModel.TryGetTowerById(itemId, out TowerItemData tower) && tower != null)
|
||||
{
|
||||
if (inventory.ParticipantTowerInstanceIds != null && inventory.ParticipantTowerInstanceIds.Contains(itemId))
|
||||
{
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = itemId,
|
||||
IsSellable = false,
|
||||
IsTower = true,
|
||||
FailureReason = PlayerInventorySaleFailureReason.ParticipantTower
|
||||
};
|
||||
}
|
||||
|
||||
if (!ShopPriceRuleService.TryResolveTowerSalePrice(tower, inventory, out int towerPrice, EnsureShopPriceTable()))
|
||||
{
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = itemId,
|
||||
IsSellable = false,
|
||||
IsTower = true,
|
||||
FailureReason = PlayerInventorySaleFailureReason.MissingTowerComponent
|
||||
};
|
||||
}
|
||||
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = itemId,
|
||||
IsSellable = true,
|
||||
IsTower = true,
|
||||
Price = towerPrice,
|
||||
FailureReason = PlayerInventorySaleFailureReason.None
|
||||
};
|
||||
}
|
||||
|
||||
if (TryGetComponentById(inventory.MuzzleComponents, itemId, out MuzzleCompItemData muzzleComp))
|
||||
{
|
||||
return BuildComponentCandidate(muzzleComp);
|
||||
}
|
||||
|
||||
if (TryGetComponentById(inventory.BearingComponents, itemId, out BearingCompItemData bearingComp))
|
||||
{
|
||||
return BuildComponentCandidate(bearingComp);
|
||||
}
|
||||
|
||||
if (TryGetComponentById(inventory.BaseComponents, itemId, out BaseCompItemData baseComp))
|
||||
{
|
||||
return BuildComponentCandidate(baseComp);
|
||||
}
|
||||
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = itemId,
|
||||
IsSellable = false,
|
||||
FailureReason = PlayerInventorySaleFailureReason.ItemNotFound
|
||||
};
|
||||
}
|
||||
|
||||
private PlayerInventorySaleCandidate BuildComponentCandidate(TowerCompItemData component)
|
||||
{
|
||||
if (component == null)
|
||||
{
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
IsSellable = false,
|
||||
FailureReason = PlayerInventorySaleFailureReason.ItemNotFound
|
||||
};
|
||||
}
|
||||
|
||||
if (component.IsAssembledIntoTower)
|
||||
{
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = component.InstanceId,
|
||||
IsSellable = false,
|
||||
FailureReason = PlayerInventorySaleFailureReason.AssembledComponent
|
||||
};
|
||||
}
|
||||
|
||||
return new PlayerInventorySaleCandidate
|
||||
{
|
||||
ItemId = component.InstanceId,
|
||||
IsSellable = true,
|
||||
IsTower = false,
|
||||
Price = ShopPriceRuleService.ResolveComponentSalePrice(component, EnsureShopPriceTable()),
|
||||
FailureReason = PlayerInventorySaleFailureReason.None
|
||||
};
|
||||
}
|
||||
|
||||
private bool TryRemoveTower(BackpackInventoryData inventory, long towerId)
|
||||
{
|
||||
if (inventory?.Towers == null || towerId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TowerItemData targetTower = null;
|
||||
for (int i = 0; i < inventory.Towers.Count; i++)
|
||||
{
|
||||
TowerItemData tower = inventory.Towers[i];
|
||||
if (tower != null && tower.InstanceId == towerId)
|
||||
{
|
||||
targetTower = tower;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetTower == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ContainsInstanceId(inventory.MuzzleComponents, targetTower.MuzzleComponentInstanceId) ||
|
||||
!ContainsInstanceId(inventory.BearingComponents, targetTower.BearingComponentInstanceId) ||
|
||||
!ContainsInstanceId(inventory.BaseComponents, targetTower.BaseComponentInstanceId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool removedMuzzle = RemoveByInstanceId(inventory.MuzzleComponents, targetTower.MuzzleComponentInstanceId);
|
||||
bool removedBearing = RemoveByInstanceId(inventory.BearingComponents, targetTower.BearingComponentInstanceId);
|
||||
bool removedBase = RemoveByInstanceId(inventory.BaseComponents, targetTower.BaseComponentInstanceId);
|
||||
if (!removedMuzzle || !removedBearing || !removedBase)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inventory.Towers.Remove(targetTower);
|
||||
inventory.ParticipantTowerInstanceIds?.Remove(towerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryRemoveComponent(BackpackInventoryData inventory, long itemId)
|
||||
{
|
||||
return RemoveByInstanceId(inventory?.MuzzleComponents, itemId) ||
|
||||
RemoveByInstanceId(inventory?.BearingComponents, itemId) ||
|
||||
RemoveByInstanceId(inventory?.BaseComponents, itemId);
|
||||
}
|
||||
|
||||
private static bool RemoveByInstanceId<TItem>(List<TItem> items, long instanceId)
|
||||
where TItem : class
|
||||
{
|
||||
if (items == null || instanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
switch (items[i])
|
||||
{
|
||||
case TowerCompItemData component when component.InstanceId == instanceId:
|
||||
items.RemoveAt(i);
|
||||
return true;
|
||||
case TowerItemData tower when tower.InstanceId == instanceId:
|
||||
items.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool ContainsInstanceId<TItem>(IReadOnlyList<TItem> items, long instanceId)
|
||||
where TItem : class
|
||||
{
|
||||
if (items == null || instanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
switch (items[i])
|
||||
{
|
||||
case TowerCompItemData component when component.InstanceId == instanceId:
|
||||
return true;
|
||||
case TowerItemData tower when tower.InstanceId == instanceId:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGetComponentById<TComp>(IReadOnlyList<TComp> items, long instanceId, out TComp result)
|
||||
where TComp : TowerCompItemData
|
||||
{
|
||||
result = null;
|
||||
if (items == null || instanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
TComp item = items[i];
|
||||
if (item != null && item.InstanceId == instanceId)
|
||||
{
|
||||
result = item;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static BackpackInventoryData WrapSingleItem(TowerCompItemData item)
|
||||
{
|
||||
BackpackInventoryData inventory = new BackpackInventoryData();
|
||||
switch (item)
|
||||
{
|
||||
case MuzzleCompItemData muzzleComp:
|
||||
inventory.MuzzleComponents.Add(InventoryCloneUtility.CloneMuzzleComp(muzzleComp));
|
||||
break;
|
||||
case BearingCompItemData bearingComp:
|
||||
inventory.BearingComponents.Add(InventoryCloneUtility.CloneBearingComp(bearingComp));
|
||||
break;
|
||||
case BaseCompItemData baseComp:
|
||||
inventory.BaseComponents.Add(InventoryCloneUtility.CloneBaseComp(baseComp));
|
||||
break;
|
||||
}
|
||||
|
||||
return inventory;
|
||||
}
|
||||
|
||||
private IDataTable<DRShopPrice> EnsureShopPriceTable()
|
||||
{
|
||||
_shopPriceTable ??= GameEntry.DataTable.GetDataTable<DRShopPrice>();
|
||||
return _shopPriceTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user