// Assets/_Project/Scripts/Gameplay/BuilderSpells/SlowAreaZone.cs
using UnityEngine;
using TD.Core;
namespace TD.Gameplay.BuilderSpells
{
///
/// Server-only, non-networked lingering area spawned by
/// . 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.
///
///
/// Never spawned as a — it runs
/// server-side only, and the slow it applies already reaches clients through
/// 's own NetworkVariable, the same as an instant hit.
///
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();
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();
if (enemyHealth == null || enemyHealth.IsDead) continue;
var enemyStatus = overlapBuffer[i].GetComponent();
if (enemyStatus == null) continue;
enemyStatus.ApplyEffect(DamageType.Cold, slowFactor, effectDuration, owner);
}
}
}
}