Adding Tesla Coil Tower and Arc VFX

New tower!
This commit is contained in:
Matt F 2026-06-25 11:35:23 -07:00
parent 7b93137216
commit 699ea34268
20 changed files with 1317 additions and 2 deletions

View file

@ -90,6 +90,13 @@ namespace TD.Combat
/// </summary>
public event Action<Vector3> OnFire;
/// <summary>
/// Fired locally on ALL peers when an <see cref="TargetType.AllInRange"/> tower
/// attacks, carrying the world positions of every enemy hit this tick. A visual
/// component (e.g. <c>TeslaArcVisual</c>) subscribes to draw an arc to each.
/// </summary>
public event Action<Vector3[]> OnAreaFired;
// ----- NGO lifecycle -----------------------------------------------
public override void OnNetworkSpawn()
@ -300,10 +307,14 @@ namespace TD.Combat
public readonly float ProjectileSpeed;
public readonly int ChainCount;
public readonly float ChainRange;
// The tower's attack range. Carried here so the AllInRange path knows how far
// to sweep without re-reading the TowerDefinition.
public readonly float Range;
public CombatProfile(float damage, DamageType damageType, TargetType targetType,
float splashRadius, float slowFactor, float dotDamagePerSecond,
float effectDuration, float projectileSpeed, int chainCount, float chainRange)
float effectDuration, float projectileSpeed, int chainCount, float chainRange,
float range)
{
Damage = damage;
DamageType = damageType;
@ -315,6 +326,7 @@ namespace TD.Combat
ProjectileSpeed = projectileSpeed;
ChainCount = chainCount;
ChainRange = chainRange;
Range = range;
}
}
@ -354,7 +366,8 @@ namespace TD.Combat
}
return new CombatProfile(damage, damageType, targetType, splash, slow, dot,
duration, def.ProjectileSpeed, def.ChainCount, def.ChainRange);
duration, def.ProjectileSpeed, def.ChainCount, def.ChainRange,
def.Range);
}
// ----- Damage application ------------------------------------------
@ -377,9 +390,33 @@ namespace TD.Combat
case TargetType.Chain:
ApplyChain(p, primary, owner);
break;
case TargetType.AllInRange:
ApplyAllInRange(p, owner);
break;
}
}
// Hits every enemy within the tower's range this tick (Tesla Coil). Broadcasts the
// hit positions so a visual component can draw an arc to each.
private void ApplyAllInRange(in CombatProfile p, PlayerSlot owner)
{
int count = Physics.OverlapSphereNonAlloc(
transform.position, p.Range, s_overlapBuffer, enemyLayerMask);
var hitPositions = new List<Vector3>(count);
for (int i = 0; i < count; i++)
{
var eh = s_overlapBuffer[i].GetComponent<EnemyHealth>();
if (eh == null || eh.IsDead) continue;
HitEnemy(p, eh, owner);
hitPositions.Add(eh.transform.position);
}
if (hitPositions.Count > 0)
AreaFiredClientRpc(hitPositions.ToArray());
}
private void ApplySplash(in CombatProfile p, EnemyHealth primary,
Vector3 origin, PlayerSlot owner)
{
@ -513,6 +550,14 @@ namespace TD.Combat
// and draw a line renderer through these world positions.
}
[ClientRpc]
private void AreaFiredClientRpc(Vector3[] hitPositions)
{
// Visual consumers (TeslaArcVisual) subscribe to OnAreaFired to draw an
// electrical arc from the tower's emitter to each hit enemy.
OnAreaFired?.Invoke(hitPositions);
}
// ----- NV callback (fires on all peers) ----------------------------
private void HandleReplicatedTargetChanged(