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; namespace GeometryTD.CustomComponent { 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; } } }