217 lines
8.4 KiB
C#
217 lines
8.4 KiB
C#
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;
|
|
}
|
|
}
|