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; private IDataTable _drBearingComp; private IDataTable _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 = ResolveAverageRarity(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, Tags = MergeTags(muzzleComp.Tags, bearingComp.Tags, baseComp.Tags) }; 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] = 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] = 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 static TagType[] MergeTags(params TagType[][] sources) { HashSet uniqueTags = new HashSet(); if (sources != null) { for (int i = 0; i < sources.Length; i++) { TagType[] tags = sources[i]; if (tags == null) { continue; } for (int j = 0; j < tags.Length; j++) { uniqueTags.Add(tags[j]); } } } TagType[] mergedTags = new TagType[uniqueTags.Count]; uniqueTags.CopyTo(mergedTags); return mergedTags; } private static RarityType ResolveAverageRarity(RarityType muzzleRarity, RarityType bearingRarity, RarityType baseRarity) { float avg = ((int)muzzleRarity + (int)bearingRarity + (int)baseRarity) / 3f; int rounded = Mathf.RoundToInt(avg); int clamped = Mathf.Clamp(rounded, (int)RarityType.White, (int)RarityType.Red); return (RarityType)clamped; } private IDataTable EnsureMuzzleTable() { _drMuzzleComp ??= GameEntry.DataTable.GetDataTable(); return _drMuzzleComp; } private IDataTable EnsureBearingTable() { _drBearingComp ??= GameEntry.DataTable.GetDataTable(); return _drBearingComp; } private IDataTable EnsureBaseTable() { _drBaseComp ??= GameEntry.DataTable.GetDataTable(); return _drBaseComp; } } }