重构
- 重构 `RepoItem`,统一点击事件
- 重构 `PlayerInventoryComponent`:
- `PlayerInventoryStateStore`:状态与库存写模型
- `PlayerInventoryTowerAssemblyService`:炮塔组装域
- `PlayerInventoryTowerRosterService`:编队/耐久域
- `InventoryParticipantUtility`/`InventoryCloneUtility`/`InventorySeedUtility`:通用工具类
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.CustomUtility
|
||||
{
|
||||
public static class InventoryCloneUtility
|
||||
{
|
||||
public static BackpackInventoryData CloneInventory(BackpackInventoryData source)
|
||||
{
|
||||
BackpackInventoryData cloned = new BackpackInventoryData();
|
||||
if (source == null)
|
||||
{
|
||||
return cloned;
|
||||
}
|
||||
|
||||
cloned.Gold = Mathf.Max(0, source.Gold);
|
||||
|
||||
if (source.MuzzleComponents != null)
|
||||
{
|
||||
for (int i = 0; i < source.MuzzleComponents.Count; i++)
|
||||
{
|
||||
MuzzleCompItemData item = source.MuzzleComponents[i];
|
||||
if (item != null)
|
||||
{
|
||||
cloned.MuzzleComponents.Add(CloneMuzzleComp(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source.BearingComponents != null)
|
||||
{
|
||||
for (int i = 0; i < source.BearingComponents.Count; i++)
|
||||
{
|
||||
BearingCompItemData item = source.BearingComponents[i];
|
||||
if (item != null)
|
||||
{
|
||||
cloned.BearingComponents.Add(CloneBearingComp(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source.BaseComponents != null)
|
||||
{
|
||||
for (int i = 0; i < source.BaseComponents.Count; i++)
|
||||
{
|
||||
BaseCompItemData item = source.BaseComponents[i];
|
||||
if (item != null)
|
||||
{
|
||||
cloned.BaseComponents.Add(CloneBaseComp(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source.Towers != null)
|
||||
{
|
||||
for (int i = 0; i < source.Towers.Count; i++)
|
||||
{
|
||||
TowerItemData item = source.Towers[i];
|
||||
if (item != null)
|
||||
{
|
||||
cloned.Towers.Add(CloneTower(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source.ParticipantTowerInstanceIds != null)
|
||||
{
|
||||
for (int i = 0; i < source.ParticipantTowerInstanceIds.Count; i++)
|
||||
{
|
||||
long id = source.ParticipantTowerInstanceIds[i];
|
||||
if (id > 0)
|
||||
{
|
||||
cloned.ParticipantTowerInstanceIds.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
public static MuzzleCompItemData CloneMuzzleComp(MuzzleCompItemData source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new MuzzleCompItemData
|
||||
{
|
||||
InstanceId = source.InstanceId,
|
||||
ConfigId = source.ConfigId,
|
||||
Name = source.Name,
|
||||
Rarity = source.Rarity,
|
||||
Endurance = source.Endurance,
|
||||
IsAssembledIntoTower = source.IsAssembledIntoTower,
|
||||
Constraint = source.Constraint,
|
||||
Tags = CloneTags(source.Tags),
|
||||
AttackDamage = CloneIntArray(source.AttackDamage),
|
||||
DamageRandomRate = source.DamageRandomRate,
|
||||
AttackMethodType = source.AttackMethodType
|
||||
};
|
||||
}
|
||||
|
||||
public static BearingCompItemData CloneBearingComp(BearingCompItemData source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BearingCompItemData
|
||||
{
|
||||
InstanceId = source.InstanceId,
|
||||
ConfigId = source.ConfigId,
|
||||
Name = source.Name,
|
||||
Rarity = source.Rarity,
|
||||
Endurance = source.Endurance,
|
||||
IsAssembledIntoTower = source.IsAssembledIntoTower,
|
||||
Constraint = source.Constraint,
|
||||
Tags = CloneTags(source.Tags),
|
||||
RotateSpeed = CloneFloatArray(source.RotateSpeed),
|
||||
AttackRange = CloneFloatArray(source.AttackRange)
|
||||
};
|
||||
}
|
||||
|
||||
public static BaseCompItemData CloneBaseComp(BaseCompItemData source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BaseCompItemData
|
||||
{
|
||||
InstanceId = source.InstanceId,
|
||||
ConfigId = source.ConfigId,
|
||||
Name = source.Name,
|
||||
Rarity = source.Rarity,
|
||||
Endurance = source.Endurance,
|
||||
IsAssembledIntoTower = source.IsAssembledIntoTower,
|
||||
Constraint = source.Constraint,
|
||||
Tags = CloneTags(source.Tags),
|
||||
AttackSpeed = CloneFloatArray(source.AttackSpeed),
|
||||
AttackPropertyType = source.AttackPropertyType
|
||||
};
|
||||
}
|
||||
|
||||
public static TowerItemData CloneTower(TowerItemData source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TowerItemData
|
||||
{
|
||||
InstanceId = source.InstanceId,
|
||||
Name = source.Name,
|
||||
Rarity = source.Rarity,
|
||||
IsParticipatingInCombat = source.IsParticipatingInCombat,
|
||||
MuzzleComponentInstanceId = source.MuzzleComponentInstanceId,
|
||||
BearingComponentInstanceId = source.BearingComponentInstanceId,
|
||||
BaseComponentInstanceId = source.BaseComponentInstanceId,
|
||||
Stats = CloneTowerStats(source.Stats)
|
||||
};
|
||||
}
|
||||
|
||||
public static TowerStatsData CloneTowerStats(TowerStatsData source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return new TowerStatsData();
|
||||
}
|
||||
|
||||
return new TowerStatsData
|
||||
{
|
||||
AttackDamage = CloneIntArray(source.AttackDamage),
|
||||
DamageRandomRate = source.DamageRandomRate,
|
||||
RotateSpeed = CloneFloatArray(source.RotateSpeed),
|
||||
AttackRange = CloneFloatArray(source.AttackRange),
|
||||
AttackSpeed = CloneFloatArray(source.AttackSpeed),
|
||||
AttackMethodType = source.AttackMethodType,
|
||||
AttackPropertyType = source.AttackPropertyType,
|
||||
Tags = CloneTags(source.Tags)
|
||||
};
|
||||
}
|
||||
|
||||
public static int[] CloneIntArray(int[] source)
|
||||
{
|
||||
return source != null ? (int[])source.Clone() : Array.Empty<int>();
|
||||
}
|
||||
|
||||
public static float[] CloneFloatArray(float[] source)
|
||||
{
|
||||
return source != null ? (float[])source.Clone() : Array.Empty<float>();
|
||||
}
|
||||
|
||||
public static TagType[] CloneTags(TagType[] source)
|
||||
{
|
||||
return source != null ? (TagType[])source.Clone() : Array.Empty<TagType>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71ce567f99e231a48a4c25a322c2b8cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,140 @@
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.CustomUtility
|
||||
{
|
||||
public static class InventoryParticipantUtility
|
||||
{
|
||||
public static bool TryAddParticipantTower(BackpackInventoryData inventory, long towerInstanceId, int maxCount)
|
||||
{
|
||||
if (inventory == null || towerInstanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int resolvedMaxCount = Mathf.Max(1, maxCount);
|
||||
NormalizeParticipantState(inventory, resolvedMaxCount);
|
||||
if (!TryGetTowerById(inventory, towerInstanceId, out TowerItemData tower))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inventory.ParticipantTowerInstanceIds ??= new List<long>();
|
||||
if (inventory.ParticipantTowerInstanceIds.Contains(towerInstanceId))
|
||||
{
|
||||
tower.IsParticipatingInCombat = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inventory.ParticipantTowerInstanceIds.Count >= resolvedMaxCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inventory.ParticipantTowerInstanceIds.Add(towerInstanceId);
|
||||
tower.IsParticipatingInCombat = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryRemoveParticipantTower(BackpackInventoryData inventory, long towerInstanceId, int maxCount)
|
||||
{
|
||||
if (inventory == null || towerInstanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NormalizeParticipantState(inventory, maxCount);
|
||||
if (inventory.ParticipantTowerInstanceIds == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool removed = inventory.ParticipantTowerInstanceIds.Remove(towerInstanceId);
|
||||
if (!removed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TryGetTowerById(inventory, towerInstanceId, out TowerItemData tower))
|
||||
{
|
||||
tower.IsParticipatingInCombat = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void NormalizeParticipantState(BackpackInventoryData inventory, int maxCount)
|
||||
{
|
||||
if (inventory == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int resolvedMaxCount = Mathf.Max(1, maxCount);
|
||||
inventory.ParticipantTowerInstanceIds ??= new List<long>();
|
||||
Dictionary<long, TowerItemData> towerMap = new Dictionary<long, TowerItemData>();
|
||||
if (inventory.Towers != null)
|
||||
{
|
||||
for (int i = 0; i < inventory.Towers.Count; i++)
|
||||
{
|
||||
TowerItemData tower = inventory.Towers[i];
|
||||
if (tower == null || tower.InstanceId <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tower.IsParticipatingInCombat = false;
|
||||
towerMap[tower.InstanceId] = tower;
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<long> uniqueIds = new HashSet<long>();
|
||||
List<long> normalizedIds = new List<long>(inventory.ParticipantTowerInstanceIds.Count);
|
||||
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count; i++)
|
||||
{
|
||||
if (normalizedIds.Count >= resolvedMaxCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
long towerId = inventory.ParticipantTowerInstanceIds[i];
|
||||
if (towerId <= 0 || !uniqueIds.Add(towerId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!towerMap.TryGetValue(towerId, out TowerItemData tower))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tower.IsParticipatingInCombat = true;
|
||||
normalizedIds.Add(towerId);
|
||||
}
|
||||
|
||||
inventory.ParticipantTowerInstanceIds = normalizedIds;
|
||||
}
|
||||
|
||||
public static bool TryGetTowerById(BackpackInventoryData inventory, long towerInstanceId, out TowerItemData tower)
|
||||
{
|
||||
tower = null;
|
||||
if (inventory?.Towers == null || towerInstanceId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < inventory.Towers.Count; i++)
|
||||
{
|
||||
TowerItemData candidate = inventory.Towers[i];
|
||||
if (candidate != null && candidate.InstanceId == towerInstanceId)
|
||||
{
|
||||
tower = candidate;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24bb2803b971d424aaba0cb472ead5d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,190 @@
|
||||
using GeometryTD.Definition;
|
||||
|
||||
namespace GeometryTD.CustomUtility
|
||||
{
|
||||
public static class InventorySeedUtility
|
||||
{
|
||||
public static BackpackInventoryData CreateSampleInventory()
|
||||
{
|
||||
BackpackInventoryData inventory = new BackpackInventoryData
|
||||
{
|
||||
Gold = 500
|
||||
};
|
||||
|
||||
MuzzleCompItemData muzzle = new MuzzleCompItemData
|
||||
{
|
||||
InstanceId = 10001,
|
||||
ConfigId = 1,
|
||||
Name = "元素枪口",
|
||||
Rarity = RarityType.Green,
|
||||
Endurance = 90f,
|
||||
IsAssembledIntoTower = true,
|
||||
AttackDamage = new[] { 20, 30, 40, 50, 80 },
|
||||
DamageRandomRate = 0.05f,
|
||||
AttackMethodType = AttackMethodType.NormalBullet,
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Fire }
|
||||
};
|
||||
inventory.MuzzleComponents.Add(muzzle);
|
||||
inventory.MuzzleComponents.Add(new MuzzleCompItemData
|
||||
{
|
||||
InstanceId = 10002,
|
||||
ConfigId = 2,
|
||||
Name = "控制枪口",
|
||||
Rarity = RarityType.Blue,
|
||||
Endurance = 80,
|
||||
IsAssembledIntoTower = false,
|
||||
AttackDamage = new[] { 30, 50, 70, 90, 100 },
|
||||
DamageRandomRate = 0.01f,
|
||||
AttackMethodType = AttackMethodType.NormalBullet,
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Ice, TagType.FreezeMask }
|
||||
});
|
||||
inventory.MuzzleComponents.Add(new MuzzleCompItemData
|
||||
{
|
||||
InstanceId = 10003,
|
||||
ConfigId = 3,
|
||||
Name = "穿透枪口",
|
||||
Rarity = RarityType.Purple,
|
||||
Endurance = 97f,
|
||||
IsAssembledIntoTower = false,
|
||||
AttackDamage = new[] { 50, 55, 60, 80, 90 },
|
||||
DamageRandomRate = 0.02f,
|
||||
AttackMethodType = AttackMethodType.NormalBullet,
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Pierce, TagType.Crit }
|
||||
});
|
||||
|
||||
BearingCompItemData bearing = new BearingCompItemData
|
||||
{
|
||||
InstanceId = 20001,
|
||||
ConfigId = 1,
|
||||
Name = "元素轴承",
|
||||
Rarity = RarityType.Green,
|
||||
Endurance = 1f,
|
||||
IsAssembledIntoTower = true,
|
||||
RotateSpeed = new[] { 10f, 12f, 13f, 14f, 15f },
|
||||
AttackRange = new[] { 2f, 2f, 2f, 2f, 2f },
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Fire }
|
||||
};
|
||||
inventory.BearingComponents.Add(bearing);
|
||||
inventory.BearingComponents.Add(new BearingCompItemData
|
||||
{
|
||||
InstanceId = 20002,
|
||||
ConfigId = 2,
|
||||
Name = "控制轴承",
|
||||
Rarity = RarityType.Blue,
|
||||
Endurance = 20,
|
||||
IsAssembledIntoTower = false,
|
||||
RotateSpeed = new[] { 20f, 25f, 30f, 32f, 35f },
|
||||
AttackRange = new[] { 6f, 6.5f, 7f, 8f, 8f },
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Ice, TagType.Shatter }
|
||||
});
|
||||
inventory.BearingComponents.Add(new BearingCompItemData
|
||||
{
|
||||
InstanceId = 20003,
|
||||
ConfigId = 3,
|
||||
Name = "穿透轴承",
|
||||
Rarity = RarityType.Purple,
|
||||
Endurance = 96f,
|
||||
IsAssembledIntoTower = false,
|
||||
RotateSpeed = new[] { 60f, 70f, 80f, 90f, 100f },
|
||||
AttackRange = new[] { 4f, 4.5f, 5f, 5.5f, 6f },
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Pierce, TagType.Overpenetrate }
|
||||
});
|
||||
|
||||
BaseCompItemData baseComp = new BaseCompItemData
|
||||
{
|
||||
InstanceId = 30001,
|
||||
ConfigId = 1,
|
||||
Name = "元素底座",
|
||||
Rarity = RarityType.Green,
|
||||
Endurance = 88f,
|
||||
IsAssembledIntoTower = true,
|
||||
AttackSpeed = new[] { 2f, 1.5f, 1f, 0.8f, 0.7f },
|
||||
AttackPropertyType = AttackPropertyType.Fire,
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Fire }
|
||||
};
|
||||
inventory.BaseComponents.Add(baseComp);
|
||||
inventory.BaseComponents.Add(new BaseCompItemData
|
||||
{
|
||||
InstanceId = 30002,
|
||||
ConfigId = 2,
|
||||
Name = "控制底座",
|
||||
Rarity = RarityType.Blue,
|
||||
Endurance = 50f,
|
||||
IsAssembledIntoTower = false,
|
||||
AttackSpeed = new[] { 4f, 4.2f, 4.4f, 4.6f, 4.8f },
|
||||
AttackPropertyType = AttackPropertyType.Ice,
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Ice, TagType.AbsoluteZero }
|
||||
});
|
||||
inventory.BaseComponents.Add(new BaseCompItemData
|
||||
{
|
||||
InstanceId = 30003,
|
||||
ConfigId = 3,
|
||||
Name = "穿透底座",
|
||||
Rarity = RarityType.Purple,
|
||||
Endurance = 30f,
|
||||
IsAssembledIntoTower = false,
|
||||
AttackSpeed = new[] { 1f, 1f, 1f, 1f, 1f },
|
||||
AttackPropertyType = AttackPropertyType.Physics,
|
||||
Constraint = string.Empty,
|
||||
Tags = new[] { TagType.Pierce, TagType.Execution }
|
||||
});
|
||||
|
||||
TowerItemData tower = new TowerItemData
|
||||
{
|
||||
InstanceId = 90001,
|
||||
Name = "测试防御塔-A",
|
||||
Rarity = RarityType.Green,
|
||||
IsParticipatingInCombat = true,
|
||||
MuzzleComponentInstanceId = muzzle.InstanceId,
|
||||
BearingComponentInstanceId = bearing.InstanceId,
|
||||
BaseComponentInstanceId = baseComp.InstanceId,
|
||||
Stats = new TowerStatsData
|
||||
{
|
||||
AttackDamage = new[] { 200, 220, 240, 260, 300 },
|
||||
DamageRandomRate = 0f,
|
||||
RotateSpeed = new[] { 200f, 210f, 220f, 230f, 240f },
|
||||
AttackRange = new[] { 4.5f, 4.7f, 4.9f, 5.1f, 5.3f },
|
||||
AttackSpeed = new[] { 1.5f, 1.2f, 1.1f, 1.0f, 0.8f },
|
||||
AttackMethodType = AttackMethodType.NormalBullet,
|
||||
AttackPropertyType = AttackPropertyType.Fire,
|
||||
Tags = new[] { TagType.Fire, TagType.BurnSpread }
|
||||
}
|
||||
};
|
||||
inventory.Towers.Add(tower);
|
||||
|
||||
inventory.Towers.Add(new TowerItemData
|
||||
{
|
||||
InstanceId = 90002,
|
||||
Name = "测试防御塔-B",
|
||||
Rarity = RarityType.Blue,
|
||||
IsParticipatingInCombat = false,
|
||||
MuzzleComponentInstanceId = 0,
|
||||
BearingComponentInstanceId = 0,
|
||||
BaseComponentInstanceId = 0,
|
||||
Stats = new TowerStatsData
|
||||
{
|
||||
AttackDamage = new[] { 200, 220, 240, 260, 300 },
|
||||
DamageRandomRate = 0.1f,
|
||||
RotateSpeed = new[] { 200f, 210f, 220f, 230f, 240f },
|
||||
AttackRange = new[] { 4.5f, 4.7f, 4.9f, 5.1f, 5.3f },
|
||||
AttackSpeed = new[] { 1.5f, 1.2f, 1.1f, 1.0f, 0.8f },
|
||||
AttackMethodType = AttackMethodType.NormalBullet,
|
||||
AttackPropertyType = AttackPropertyType.Physics,
|
||||
Tags = new[] { TagType.Pierce }
|
||||
}
|
||||
});
|
||||
|
||||
inventory.ParticipantTowerInstanceIds.Add(90001);
|
||||
|
||||
return inventory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6a4b82844aa4417a949907fadd92bb7
|
||||
timeCreated: 1772632267
|
||||
Reference in New Issue
Block a user