fix slow area spell area of effect
This commit is contained in:
parent
04d7b42e60
commit
35ea90f71b
3 changed files with 92 additions and 18 deletions
|
|
@ -0,0 +1,77 @@
|
|||
// Assets/_Project/Scripts/Gameplay/BuilderSpells/SlowAreaZone.cs
|
||||
using UnityEngine;
|
||||
using TD.Core;
|
||||
|
||||
namespace TD.Gameplay.BuilderSpells
|
||||
{
|
||||
/// <summary>
|
||||
/// Server-only, non-networked lingering area spawned by
|
||||
/// <see cref="SlowAreaSpellDefinition.ServerCast"/>. Re-scans its radius on an
|
||||
/// interval for its lifetime and keeps refreshing the slow on anything standing
|
||||
/// inside, so enemies get slowed as they walk through rather than only at the
|
||||
/// instant of cast.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Never spawned as a <see cref="Unity.Netcode.NetworkObject"/> — it runs
|
||||
/// server-side only, and the slow it applies already reaches clients through
|
||||
/// <see cref="EnemyStatus"/>'s own NetworkVariable, the same as an instant hit.
|
||||
/// </remarks>
|
||||
public class SlowAreaZone : MonoBehaviour
|
||||
{
|
||||
private const float TickInterval = 0.2f;
|
||||
|
||||
private float radius;
|
||||
private float slowFactor;
|
||||
private float effectDuration;
|
||||
private LayerMask enemyLayerMask;
|
||||
private PlayerSlot owner;
|
||||
|
||||
private readonly Collider[] overlapBuffer = new Collider[64];
|
||||
private float tickTimer;
|
||||
|
||||
public static SlowAreaZone Spawn(Vector3 position, float radius, float slowFactor,
|
||||
float effectDuration, LayerMask enemyLayerMask, PlayerSlot owner)
|
||||
{
|
||||
var zoneObject = new GameObject("SlowAreaZone (Server)");
|
||||
zoneObject.transform.position = position;
|
||||
|
||||
var zone = zoneObject.AddComponent<SlowAreaZone>();
|
||||
zone.radius = radius;
|
||||
zone.slowFactor = slowFactor;
|
||||
zone.effectDuration = effectDuration;
|
||||
zone.enemyLayerMask = enemyLayerMask;
|
||||
zone.owner = owner;
|
||||
zone.ApplyToOverlapping();
|
||||
|
||||
Destroy(zoneObject, effectDuration);
|
||||
return zone;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
tickTimer -= Time.deltaTime;
|
||||
if (tickTimer > 0f) return;
|
||||
|
||||
ApplyToOverlapping();
|
||||
}
|
||||
|
||||
private void ApplyToOverlapping()
|
||||
{
|
||||
tickTimer = TickInterval;
|
||||
|
||||
int count = Physics.OverlapSphereNonAlloc(
|
||||
transform.position, radius, overlapBuffer, enemyLayerMask);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var enemyHealth = overlapBuffer[i].GetComponent<EnemyHealth>();
|
||||
if (enemyHealth == null || enemyHealth.IsDead) continue;
|
||||
|
||||
var enemyStatus = overlapBuffer[i].GetComponent<EnemyStatus>();
|
||||
if (enemyStatus == null) continue;
|
||||
|
||||
enemyStatus.ApplyEffect(DamageType.Cold, slowFactor, effectDuration, owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue