diff --git a/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/InventoryGenerationComponent.cs b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/InventoryGenerationComponent.cs index d9ecdc7..cb7416b 100644 --- a/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/InventoryGenerationComponent.cs +++ b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/InventoryGenerationComponent.cs @@ -1,12 +1,9 @@ using System; using System.Collections.Generic; using GameFramework.DataTable; -using GeometryTD.CustomUtility; using GeometryTD.DataTable; using GeometryTD.Definition; -using GeometryTD.Factory; using GeometryTD.UI; -using UnityEngine; using UnityGameFramework.Runtime; namespace GeometryTD.CustomComponent @@ -20,23 +17,12 @@ namespace GeometryTD.CustomComponent private IDataTable _muzzleCompTable; private IDataTable _bearingCompTable; private IDataTable _baseCompTable; + private ShopGoodsBuilder _shopGoodsBuilder; public List BuildShopGoods(int goodsCount, int runSeed = 0, int sequenceIndex = -1) { - if (goodsCount <= 0) - { - return new List(); - } - - EnsureShopTables(); - - List goodsItems = new(goodsCount); - for (int i = 0; i < goodsCount; i++) - { - goodsItems.Add(BuildShopGoodsItem(i, runSeed, sequenceIndex)); - } - - return goodsItems; + EnsureShopBuilder(); + return _shopGoodsBuilder.BuildGoods(goodsCount, runSeed, sequenceIndex, AllocateTempInstanceId); } public EnemyDropResult ResolveEnemyDrop(in EnemyDropContext context) @@ -94,125 +80,19 @@ namespace GeometryTD.CustomComponent } } - private GoodsItemRawData BuildShopGoodsItem(int goodsIndex, int runSeed, int sequenceIndex) + private void EnsureShopBuilder() { - TowerCompItemData sourceItem = BuildRandomComponentItem(goodsIndex, runSeed, sequenceIndex); - return new GoodsItemRawData - { - GoodsIndex = goodsIndex, - Title = sourceItem.Name, - TypeText = BuildTypeText(sourceItem.SlotType), - Description = BuildDescription(sourceItem), - Price = ResolveRandomPrice(sourceItem.Rarity), - Tags = sourceItem.Tags != null ? (TagType[])sourceItem.Tags.Clone() : Array.Empty(), - IconAreaContext = BuildIconAreaContext(sourceItem), - SourceItem = sourceItem, - IsPurchased = false - }; + EnsureShopTables(); + _shopGoodsBuilder ??= new ShopGoodsBuilder( + _shopPriceRows, + _muzzleCompTable, + _bearingCompTable, + _baseCompTable); } - private TowerCompItemData BuildRandomComponentItem(int goodsIndex, int runSeed, int sequenceIndex) + private long AllocateTempInstanceId() { - int slotRoll = UnityEngine.Random.Range(0, 3); - DRShopPrice priceRow = _shopPriceRows[UnityEngine.Random.Range(0, _shopPriceRows.Count)]; - RarityType rarity = InventoryRarityRuleService.NormalizeComponentRarity( - priceRow != null ? priceRow.Rarity : RarityType.White); - - return slotRoll switch - { - 0 => BuildRandomMuzzleItem(rarity, goodsIndex, runSeed, sequenceIndex), - 1 => BuildRandomBearingItem(rarity, goodsIndex, runSeed, sequenceIndex), - _ => BuildRandomBaseItem(rarity, goodsIndex, runSeed, sequenceIndex) - }; - } - - private MuzzleCompItemData BuildRandomMuzzleItem(RarityType rarity, int goodsIndex, int runSeed, - int sequenceIndex) - { - DRMuzzleComp[] rows = _muzzleCompTable.GetAllDataRows(); - DRMuzzleComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; - long instanceId = _nextTempInstanceId++; - InventoryTagRandomContext randomContext = - InventoryTagRandomContext.CreateShop(runSeed, sequenceIndex, goodsIndex, config.Id); - return ComponentItemFactory.CreateMuzzle(config, instanceId, rarity, randomContext); - } - - private BearingCompItemData BuildRandomBearingItem(RarityType rarity, int goodsIndex, int runSeed, - int sequenceIndex) - { - DRBearingComp[] rows = _bearingCompTable.GetAllDataRows(); - DRBearingComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; - long instanceId = _nextTempInstanceId++; - InventoryTagRandomContext randomContext = - InventoryTagRandomContext.CreateShop(runSeed, sequenceIndex, goodsIndex, config.Id); - return ComponentItemFactory.CreateBearing(config, instanceId, rarity, randomContext); - } - - private BaseCompItemData BuildRandomBaseItem(RarityType rarity, int goodsIndex, int runSeed, int sequenceIndex) - { - DRBaseComp[] rows = _baseCompTable.GetAllDataRows(); - DRBaseComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; - long instanceId = _nextTempInstanceId++; - InventoryTagRandomContext randomContext = - InventoryTagRandomContext.CreateShop(runSeed, sequenceIndex, goodsIndex, config.Id); - return ComponentItemFactory.CreateBase(config, instanceId, rarity, randomContext); - } - - private int ResolveRandomPrice(RarityType rarity) - { - for (int i = 0; i < _shopPriceRows.Count; i++) - { - DRShopPrice row = _shopPriceRows[i]; - if (row != null && row.Rarity == rarity) - { - int min = Mathf.Max(0, row.MinPrice); - int max = Mathf.Max(min, row.MaxPrice); - return UnityEngine.Random.Range(min, max + 1); - } - } - - return 0; - } - - private static IconAreaContext BuildIconAreaContext(TowerCompItemData item) - { - return new IconAreaContext - { - Rarity = item.Rarity, - ComponentSlotType = item.SlotType, - Color = IconColorGenerator.GenerateForComponent(item) - }; - } - - private static string BuildTypeText(TowerCompSlotType slotType) - { - return slotType switch - { - TowerCompSlotType.Muzzle => "枪口组件", - TowerCompSlotType.Bearing => "轴承组件", - TowerCompSlotType.Base => "底座组件", - _ => "组件" - }; - } - - private static string BuildDescription(TowerCompItemData item) - { - if (item is MuzzleCompItemData muzzleComp) - { - return ItemDescUtility.BuildMuzzleDesc(muzzleComp); - } - - if (item is BearingCompItemData bearingComp) - { - return ItemDescUtility.BuildBearingDesc(bearingComp); - } - - if (item is BaseCompItemData baseComp) - { - return ItemDescUtility.BuildBaseDesc(baseComp); - } - - return string.Empty; + return _nextTempInstanceId++; } } } diff --git a/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs new file mode 100644 index 0000000..c8def5f --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using GameFramework.DataTable; +using GeometryTD.CustomUtility; +using GeometryTD.DataTable; +using GeometryTD.Factory; +using GeometryTD.UI; +using UnityEngine; + +namespace GeometryTD.Definition +{ + public sealed class ShopGoodsBuilder + { + private readonly IReadOnlyList _shopPriceRows; + private readonly IDataTable _muzzleCompTable; + private readonly IDataTable _bearingCompTable; + private readonly IDataTable _baseCompTable; + + public ShopGoodsBuilder( + IReadOnlyList shopPriceRows, + IDataTable muzzleCompTable, + IDataTable bearingCompTable, + IDataTable baseCompTable) + { + _shopPriceRows = shopPriceRows; + _muzzleCompTable = muzzleCompTable; + _bearingCompTable = bearingCompTable; + _baseCompTable = baseCompTable; + } + + public List BuildGoods( + int goodsCount, + int runSeed, + int sequenceIndex, + Func allocateInstanceId) + { + if (goodsCount <= 0) + { + return new List(); + } + + List goodsItems = new(goodsCount); + for (int i = 0; i < goodsCount; i++) + { + goodsItems.Add(BuildGoodsItem(i, runSeed, sequenceIndex, allocateInstanceId)); + } + + return goodsItems; + } + + private GoodsItemRawData BuildGoodsItem( + int goodsIndex, + int runSeed, + int sequenceIndex, + Func allocateInstanceId) + { + TowerCompItemData sourceItem = BuildRandomComponentItem(goodsIndex, runSeed, sequenceIndex, allocateInstanceId); + return new GoodsItemRawData + { + GoodsIndex = goodsIndex, + Title = sourceItem.Name, + TypeText = BuildTypeText(sourceItem.SlotType), + Description = BuildDescription(sourceItem), + Price = ResolveRandomPrice(sourceItem.Rarity), + Tags = sourceItem.Tags != null ? (TagType[])sourceItem.Tags.Clone() : Array.Empty(), + IconAreaContext = BuildIconAreaContext(sourceItem), + SourceItem = sourceItem, + IsPurchased = false + }; + } + + private TowerCompItemData BuildRandomComponentItem( + int goodsIndex, + int runSeed, + int sequenceIndex, + Func allocateInstanceId) + { + int slotRoll = UnityEngine.Random.Range(0, 3); + DRShopPrice priceRow = _shopPriceRows[UnityEngine.Random.Range(0, _shopPriceRows.Count)]; + RarityType rarity = InventoryRarityRuleService.NormalizeComponentRarity( + priceRow != null ? priceRow.Rarity : RarityType.White); + + return slotRoll switch + { + 0 => BuildRandomMuzzleItem(rarity, goodsIndex, runSeed, sequenceIndex, allocateInstanceId), + 1 => BuildRandomBearingItem(rarity, goodsIndex, runSeed, sequenceIndex, allocateInstanceId), + _ => BuildRandomBaseItem(rarity, goodsIndex, runSeed, sequenceIndex, allocateInstanceId) + }; + } + + private MuzzleCompItemData BuildRandomMuzzleItem( + RarityType rarity, + int goodsIndex, + int runSeed, + int sequenceIndex, + Func allocateInstanceId) + { + DRMuzzleComp[] rows = _muzzleCompTable.GetAllDataRows(); + DRMuzzleComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; + long instanceId = allocateInstanceId(); + InventoryTagRandomContext randomContext = + InventoryTagRandomContext.CreateShop(runSeed, sequenceIndex, goodsIndex, config.Id); + return ComponentItemFactory.CreateMuzzle(config, instanceId, rarity, randomContext); + } + + private BearingCompItemData BuildRandomBearingItem( + RarityType rarity, + int goodsIndex, + int runSeed, + int sequenceIndex, + Func allocateInstanceId) + { + DRBearingComp[] rows = _bearingCompTable.GetAllDataRows(); + DRBearingComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; + long instanceId = allocateInstanceId(); + InventoryTagRandomContext randomContext = + InventoryTagRandomContext.CreateShop(runSeed, sequenceIndex, goodsIndex, config.Id); + return ComponentItemFactory.CreateBearing(config, instanceId, rarity, randomContext); + } + + private BaseCompItemData BuildRandomBaseItem( + RarityType rarity, + int goodsIndex, + int runSeed, + int sequenceIndex, + Func allocateInstanceId) + { + DRBaseComp[] rows = _baseCompTable.GetAllDataRows(); + DRBaseComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; + long instanceId = allocateInstanceId(); + InventoryTagRandomContext randomContext = + InventoryTagRandomContext.CreateShop(runSeed, sequenceIndex, goodsIndex, config.Id); + return ComponentItemFactory.CreateBase(config, instanceId, rarity, randomContext); + } + + private int ResolveRandomPrice(RarityType rarity) + { + for (int i = 0; i < _shopPriceRows.Count; i++) + { + DRShopPrice row = _shopPriceRows[i]; + if (row != null && row.Rarity == rarity) + { + int min = Mathf.Max(0, row.MinPrice); + int max = Mathf.Max(min, row.MaxPrice); + return UnityEngine.Random.Range(min, max + 1); + } + } + + return 0; + } + + private static IconAreaContext BuildIconAreaContext(TowerCompItemData item) + { + return new IconAreaContext + { + Rarity = item.Rarity, + ComponentSlotType = item.SlotType, + Color = IconColorGenerator.GenerateForComponent(item) + }; + } + + private static string BuildTypeText(TowerCompSlotType slotType) + { + return slotType switch + { + TowerCompSlotType.Muzzle => "枪口组件", + TowerCompSlotType.Bearing => "轴承组件", + TowerCompSlotType.Base => "底座组件", + _ => "组件" + }; + } + + private static string BuildDescription(TowerCompItemData item) + { + if (item is MuzzleCompItemData muzzleComp) + { + return ItemDescUtility.BuildMuzzleDesc(muzzleComp); + } + + if (item is BearingCompItemData bearingComp) + { + return ItemDescUtility.BuildBearingDesc(bearingComp); + } + + if (item is BaseCompItemData baseComp) + { + return ItemDescUtility.BuildBaseDesc(baseComp); + } + + return string.Empty; + } + } +} diff --git a/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs.meta b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs.meta new file mode 100644 index 0000000..1e6eb1d --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/InventoryGeneration/ShopGoodsBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b91e1b8301e40ae4e892d5fcf3d9e75a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/UI/Shop/UseCase/ShopFormUseCase.cs b/Assets/GameMain/Scripts/UI/Shop/UseCase/ShopFormUseCase.cs index 659da7d..3b8a8ea 100644 --- a/Assets/GameMain/Scripts/UI/Shop/UseCase/ShopFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/Shop/UseCase/ShopFormUseCase.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using GameFramework.DataTable; using GeometryTD.CustomUtility; -using GeometryTD.DataTable; using GeometryTD.Definition; -using UnityEngine; using UnityGameFramework.Runtime; namespace GeometryTD.UI @@ -12,38 +9,19 @@ namespace GeometryTD.UI public sealed class ShopFormUseCase : IUIUseCase { private const int GoodsCount = 4; - private long _nextTempInstanceId = 1000000; - private int _activeRunSeed; - private int _activeSequenceIndex = -1; private readonly List _currentGoods = new List(GoodsCount); - private readonly List _shopPriceRows = new List(); - private IDataTable _shopPriceTable; - private IDataTable _muzzleCompTable; - private IDataTable _bearingCompTable; - private IDataTable _baseCompTable; public bool PrepareForOpen(int runSeed = 0, int sequenceIndex = -1) { - if (!EnsureTables()) + if (GameEntry.InventoryGeneration == null) { + Log.Warning("ShopFormUseCase.PrepareForOpen() inventory generation component is null."); return false; } - _activeRunSeed = runSeed; - _activeSequenceIndex = sequenceIndex; _currentGoods.Clear(); - for (int i = 0; i < GoodsCount; i++) - { - if (!TryBuildRandomGoodsItem(i, out GoodsItemRawData goodsItem)) - { - Log.Warning("ShopFormUseCase.PrepareForOpen() failed to build goods item {0}.", i); - return false; - } - - _currentGoods.Add(goodsItem); - } - + _currentGoods.AddRange(GameEntry.InventoryGeneration.BuildShopGoods(GoodsCount, runSeed, sequenceIndex)); return _currentGoods.Count == GoodsCount; } @@ -96,212 +74,6 @@ namespace GeometryTD.UI return true; } - private bool EnsureTables() - { - _shopPriceTable ??= GameEntry.DataTable.GetDataTable(); - _muzzleCompTable ??= GameEntry.DataTable.GetDataTable(); - _bearingCompTable ??= GameEntry.DataTable.GetDataTable(); - _baseCompTable ??= GameEntry.DataTable.GetDataTable(); - - if (_shopPriceTable == null || _muzzleCompTable == null || _bearingCompTable == null || _baseCompTable == null) - { - Log.Warning("ShopFormUseCase.EnsureTables() failed. Missing required data tables."); - return false; - } - - if (_shopPriceRows.Count <= 0) - { - DRShopPrice[] rows = _shopPriceTable.GetAllDataRows(); - if (rows == null || rows.Length <= 0) - { - Log.Warning("ShopFormUseCase.EnsureTables() failed. Shop price table is empty."); - return false; - } - - foreach (var price in rows) - { - if (price != null) - { - _shopPriceRows.Add(price); - } - } - } - - return _shopPriceRows.Count > 0 && - _muzzleCompTable.Count > 0 && - _bearingCompTable.Count > 0 && - _baseCompTable.Count > 0; - } - - private bool TryBuildRandomGoodsItem(int goodsIndex, out GoodsItemRawData goodsItem) - { - goodsItem = null; - TowerCompItemData sourceItem = BuildRandomComponentItem(goodsIndex); - if (sourceItem == null) - { - return false; - } - - goodsItem = new GoodsItemRawData - { - GoodsIndex = goodsIndex, - Title = sourceItem.Name, - TypeText = BuildTypeText(sourceItem.SlotType), - Description = BuildDescription(sourceItem), - Price = ResolveRandomPrice(sourceItem.Rarity), - Tags = sourceItem.Tags != null ? (TagType[])sourceItem.Tags.Clone() : Array.Empty(), - IconAreaContext = BuildIconAreaContext(sourceItem), - SourceItem = sourceItem, - IsPurchased = false - }; - return true; - } - - private TowerCompItemData BuildRandomComponentItem(int goodsIndex) - { - int slotRoll = UnityEngine.Random.Range(0, 3); - DRShopPrice priceRow = _shopPriceRows[UnityEngine.Random.Range(0, _shopPriceRows.Count)]; - RarityType rarity = InventoryRarityRuleService.NormalizeComponentRarity( - priceRow != null ? priceRow.Rarity : RarityType.White); - - switch (slotRoll) - { - case 0: - return BuildRandomMuzzleItem(rarity, goodsIndex); - case 1: - return BuildRandomBearingItem(rarity, goodsIndex); - default: - return BuildRandomBaseItem(rarity, goodsIndex); - } - } - - private MuzzleCompItemData BuildRandomMuzzleItem(RarityType rarity, int goodsIndex) - { - DRMuzzleComp[] rows = _muzzleCompTable.GetAllDataRows(); - DRMuzzleComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; - long instanceId = _nextTempInstanceId++; - RarityType normalizedRarity = InventoryRarityRuleService.NormalizeComponentRarity(rarity); - return new MuzzleCompItemData - { - InstanceId = instanceId, - ConfigId = config.Id, - Name = config.Name, - Rarity = normalizedRarity, - Endurance = 100f, - Constraint = config.Constraint, - Tags = ComponentTagGenerationService.ResolveComponentTags( - config.PossibleTag, - normalizedRarity, - InventoryTagRandomContext.CreateShop(_activeRunSeed, _activeSequenceIndex, goodsIndex, config.Id)), - AttackDamage = config.AttackDamage != null ? (int[])config.AttackDamage.Clone() : Array.Empty(), - DamageRandomRate = config.DamageRandomRate, - AttackMethodType = config.AttackMethodType - }; - } - - private BearingCompItemData BuildRandomBearingItem(RarityType rarity, int goodsIndex) - { - DRBearingComp[] rows = _bearingCompTable.GetAllDataRows(); - DRBearingComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; - long instanceId = _nextTempInstanceId++; - RarityType normalizedRarity = InventoryRarityRuleService.NormalizeComponentRarity(rarity); - return new BearingCompItemData - { - InstanceId = instanceId, - ConfigId = config.Id, - Name = config.Name, - Rarity = normalizedRarity, - Endurance = 100f, - Constraint = config.Constraint, - Tags = ComponentTagGenerationService.ResolveComponentTags( - config.PossibleTag, - normalizedRarity, - InventoryTagRandomContext.CreateShop(_activeRunSeed, _activeSequenceIndex, goodsIndex, config.Id)), - RotateSpeed = config.RotateSpeed != null ? (float[])config.RotateSpeed.Clone() : Array.Empty(), - AttackRange = config.AttackRange != null ? (float[])config.AttackRange.Clone() : Array.Empty() - }; - } - - private BaseCompItemData BuildRandomBaseItem(RarityType rarity, int goodsIndex) - { - DRBaseComp[] rows = _baseCompTable.GetAllDataRows(); - DRBaseComp config = rows[UnityEngine.Random.Range(0, rows.Length)]; - long instanceId = _nextTempInstanceId++; - RarityType normalizedRarity = InventoryRarityRuleService.NormalizeComponentRarity(rarity); - return new BaseCompItemData - { - InstanceId = instanceId, - ConfigId = config.Id, - Name = config.Name, - Rarity = normalizedRarity, - Endurance = 100f, - Constraint = config.Constraint, - Tags = ComponentTagGenerationService.ResolveComponentTags( - config.PossibleTag, - normalizedRarity, - InventoryTagRandomContext.CreateShop(_activeRunSeed, _activeSequenceIndex, goodsIndex, config.Id)), - AttackSpeed = config.AttackSpeed != null ? (float[])config.AttackSpeed.Clone() : Array.Empty(), - AttackPropertyType = config.AttackPropertyType - }; - } - - private int ResolveRandomPrice(RarityType rarity) - { - for (int i = 0; i < _shopPriceRows.Count; i++) - { - DRShopPrice row = _shopPriceRows[i]; - if (row != null && row.Rarity == rarity) - { - int min = Mathf.Max(0, row.MinPrice); - int max = Mathf.Max(min, row.MaxPrice); - return UnityEngine.Random.Range(min, max + 1); - } - } - - return 0; - } - - private static IconAreaContext BuildIconAreaContext(TowerCompItemData item) - { - return new IconAreaContext - { - Rarity = item.Rarity, - ComponentSlotType = item.SlotType, - Color = IconColorGenerator.GenerateForComponent(item) - }; - } - - private static string BuildTypeText(TowerCompSlotType slotType) - { - return slotType switch - { - TowerCompSlotType.Muzzle => "枪口组件", - TowerCompSlotType.Bearing => "轴承组件", - TowerCompSlotType.Base => "底座组件", - _ => "组件" - }; - } - - private static string BuildDescription(TowerCompItemData item) - { - if (item is MuzzleCompItemData muzzleComp) - { - return ItemDescUtility.BuildMuzzleDesc(muzzleComp); - } - - if (item is BearingCompItemData bearingComp) - { - return ItemDescUtility.BuildBearingDesc(bearingComp); - } - - if (item is BaseCompItemData baseComp) - { - return ItemDescUtility.BuildBaseDesc(baseComp); - } - - return string.Empty; - } - private static BackpackInventoryData WrapSingleItem(TowerCompItemData item) { BackpackInventoryData inventory = new BackpackInventoryData();