补全防御塔组装与介绍描述功能

- RepoForm.CombineArea:防御塔组装,直接继承所有组件的属性
- ItemDescUtility:根据属性构建不同的 ItemDescForm 的文本
This commit is contained in:
SepComet
2026-03-04 18:17:10 +08:00
parent e12d2e73b2
commit 1e5803f4c5
29 changed files with 832 additions and 168 deletions
@@ -16,7 +16,7 @@ namespace GeometryTD.Map
private readonly Dictionary<Vector3Int, int> _towerEntityIdByFoundationCell = new();
private readonly Dictionary<int, Vector3Int> _foundationCellByTowerEntityId = new();
private readonly Dictionary<int, DefenseTowerStatsData> _towerStatsByEntityId = new();
private readonly Dictionary<int, TowerStatsData> _towerStatsByEntityId = new();
private readonly Dictionary<int, int> _towerLevelByEntityId = new();
private readonly List<int> _towerEntityIdBuffer = new();
@@ -30,8 +30,8 @@ namespace GeometryTD.Map
return false;
}
DefenseTowerStatsData towerStats =
_towerStatsByEntityId.TryGetValue(towerEntityId, out DefenseTowerStatsData cachedStats)
TowerStatsData towerStats =
_towerStatsByEntityId.TryGetValue(towerEntityId, out TowerStatsData cachedStats)
? cachedStats
: null;
int currentLevel = GetTowerLevel(towerEntityId);
@@ -61,7 +61,7 @@ namespace GeometryTD.Map
return false;
}
DefenseTowerStatsData towerStats = BuildTowerStats(buildIndex);
TowerStatsData towerStats = BuildTowerStats(buildIndex);
if (!TryShowTowerEntity(foundationCell, towerStats, towerTypeId, tilemap, out int newTowerEntityId))
{
addCoin?.Invoke(buildCost);
@@ -87,8 +87,8 @@ namespace GeometryTD.Map
return false;
}
DefenseTowerStatsData towerStats =
_towerStatsByEntityId.TryGetValue(towerEntityId, out DefenseTowerStatsData cachedStats)
TowerStatsData towerStats =
_towerStatsByEntityId.TryGetValue(towerEntityId, out TowerStatsData cachedStats)
? CloneTowerStats(cachedStats)
: BuildTowerStats(0);
int currentTowerLevel = GetTowerLevel(towerEntityId);
@@ -177,7 +177,7 @@ namespace GeometryTD.Map
return Mathf.Max(0, buildTowerCosts[buildIndex]);
}
private static bool TryShowTowerEntity(Vector3Int foundationCell, DefenseTowerStatsData towerStats,
private static bool TryShowTowerEntity(Vector3Int foundationCell, TowerStatsData towerStats,
int towerTypeId,
Tilemap tilemap, out int towerEntityId)
{
@@ -191,7 +191,7 @@ namespace GeometryTD.Map
int typeId = towerTypeId > 0 ? towerTypeId : DefaultTowerTypeId;
Vector3 towerPosition = tilemap != null ? tilemap.GetCellCenterWorld(foundationCell) : foundationCell;
towerPosition.z = 0f;
var towerData = new DefenseTowerData(entityId, typeId, towerPosition, Quaternion.identity, towerStats,
var towerData = new TowerData(entityId, typeId, towerPosition, Quaternion.identity, towerStats,
MinTowerLevel);
GameEntry.Entity.ShowDefenseTower(towerData);
@@ -213,15 +213,15 @@ namespace GeometryTD.Map
}
}
private static DefenseTowerStatsData BuildTowerStats(int buildIndex)
private static TowerStatsData BuildTowerStats(int buildIndex)
{
switch (buildIndex)
{
case 0:
return new DefenseTowerStatsData
return new TowerStatsData
{
AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = new[] { 0f, 0f, 0f, 0f, 0f },
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 },
@@ -230,10 +230,10 @@ namespace GeometryTD.Map
Tags = Array.Empty<TagType>()
};
case 1:
return new DefenseTowerStatsData
return new TowerStatsData
{
AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = new[] { 0f, 0f, 0f, 0f, 0f },
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 },
@@ -242,10 +242,10 @@ namespace GeometryTD.Map
Tags = Array.Empty<TagType>()
};
case 2:
return new DefenseTowerStatsData
return new TowerStatsData
{
AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = new[] { 0f, 0f, 0f, 0f, 0f },
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 },
@@ -254,10 +254,10 @@ namespace GeometryTD.Map
Tags = Array.Empty<TagType>()
};
case 3:
return new DefenseTowerStatsData
return new TowerStatsData
{
AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = new[] { 0f, 0f, 0f, 0f, 0f },
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 },
@@ -266,10 +266,10 @@ namespace GeometryTD.Map
Tags = Array.Empty<TagType>()
};
default:
return new DefenseTowerStatsData
return new TowerStatsData
{
AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = new[] { 0f, 0f, 0f, 0f, 0f },
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 },
@@ -280,7 +280,7 @@ namespace GeometryTD.Map
}
}
private static DefenseTowerStatsData CloneTowerStats(DefenseTowerStatsData source)
private static TowerStatsData CloneTowerStats(TowerStatsData source)
{
if (source == null)
{
@@ -288,12 +288,10 @@ namespace GeometryTD.Map
}
TagType[] copiedTags = source.Tags != null ? (TagType[])source.Tags.Clone() : Array.Empty<TagType>();
return new DefenseTowerStatsData
return new TowerStatsData
{
AttackDamage = source.AttackDamage != null ? (int[])source.AttackDamage.Clone() : Array.Empty<int>(),
DamageRandomRate = source.DamageRandomRate != null
? (float[])source.DamageRandomRate.Clone()
: Array.Empty<float>(),
DamageRandomRate = source.DamageRandomRate,
RotateSpeed = source.RotateSpeed != null ? (float[])source.RotateSpeed.Clone() : Array.Empty<float>(),
AttackRange = source.AttackRange != null ? (float[])source.AttackRange.Clone() : Array.Empty<float>(),
AttackSpeed = source.AttackSpeed != null ? (float[])source.AttackSpeed.Clone() : Array.Empty<float>(),
@@ -313,11 +311,10 @@ namespace GeometryTD.Map
return Mathf.Clamp(towerLevel, MinTowerLevel, MaxTowerLevel);
}
private static int ResolveMaxTowerLevel(DefenseTowerStatsData stats)
private static int ResolveMaxTowerLevel(TowerStatsData stats)
{
int maxCount = Mathf.Max(
GetLength(stats?.AttackDamage),
GetLength(stats?.DamageRandomRate),
GetLength(stats?.RotateSpeed),
GetLength(stats?.AttackRange),
GetLength(stats?.AttackSpeed));
@@ -329,14 +326,14 @@ namespace GeometryTD.Map
return Mathf.Clamp(maxCount - 1, MinTowerLevel, MaxTowerLevel);
}
private static bool TryApplyTowerStats(int towerEntityId, DefenseTowerStatsData towerStats, int towerLevel)
private static bool TryApplyTowerStats(int towerEntityId, TowerStatsData towerStats, int towerLevel)
{
if (towerEntityId == 0 || towerStats == null || GameEntry.Entity == null)
{
return false;
}
if (GameEntry.Entity.GetGameEntity(towerEntityId) is not DefenseTowerEntity towerEntity)
if (GameEntry.Entity.GetGameEntity(towerEntityId) is not TowerEntity towerEntity)
{
return false;
}
@@ -349,4 +346,4 @@ namespace GeometryTD.Map
return values != null ? values.Length : 0;
}
}
}
}
@@ -120,7 +120,7 @@ namespace GeometryTD.Map
}
EntityBase gameEntity = GameEntry.Entity.GetGameEntity(towerEntityId);
if (gameEntity is not DefenseTowerEntity towerEntity)
if (gameEntity is not TowerEntity towerEntity)
{
return false;
}