65 lines
2.7 KiB
C#
65 lines
2.7 KiB
C#
// Assets/_Project/Scripts/Gameplay/BuilderSpells/SlowAreaSpellDefinition.cs
|
|
using UnityEngine;
|
|
using TD.Core;
|
|
|
|
namespace TD.Gameplay.BuilderSpells
|
|
{
|
|
/// <summary>
|
|
/// Builder spell #2 — slow every enemy within an area for a duration.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <see cref="BuilderSpellDefinition.TargetType"/> is <see cref="SpellTargetType.AreaOfEffect"/>
|
|
/// — the cast controller previews <see cref="BuilderSpellDefinition.Radius"/> as a decal
|
|
/// while aiming, and this spell resolves against that same radius (no separate field).
|
|
/// Reuses the existing slow/DoT system (<see cref="EnemyStatus.ApplyEffect"/>) rather than
|
|
/// introducing a new status mechanism.
|
|
/// </remarks>
|
|
[CreateAssetMenu(fileName = "SlowAreaSpell", menuName = "TD/Builder Spells/Slow Area")]
|
|
public class SlowAreaSpellDefinition : BuilderSpellDefinition
|
|
{
|
|
public override BuilderSpellKind Kind => BuilderSpellKind.SlowArea;
|
|
|
|
[Header("Slow Area")]
|
|
[Tooltip("Speed multiplier applied to affected enemies for EffectDuration " +
|
|
"(e.g. 0.5 = half speed).")]
|
|
[Range(0f, 1f)]
|
|
public float SlowFactor = 0.5f;
|
|
|
|
[Tooltip("Seconds the slow lasts. Re-casting on an already-slowed enemy refreshes it.")]
|
|
[Min(0f)]
|
|
public float EffectDuration = 3f;
|
|
|
|
public override bool ServerCast(ulong clientId, Vector3 targetPoint)
|
|
{
|
|
PlayerSlot owner = PlayerMatchState.SlotForClient(clientId);
|
|
|
|
int count = Physics.OverlapSphereNonAlloc(
|
|
targetPoint, Mathf.Max(Radius, 0.01f), s_overlapBuffer, enemyLayerMask);
|
|
|
|
// TEMP DEBUG — remove once cast resolution is confirmed working.
|
|
Debug.Log($"[SlowAreaSpellDefinition] ServerCast at {targetPoint}, radius " +
|
|
$"{Mathf.Max(Radius, 0.01f):0.##}, found {count} colliders.");
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var c = s_overlapBuffer[i];
|
|
Debug.Log($" hit[{i}]: '{c.name}' layer={LayerMask.LayerToName(c.gameObject.layer)} " +
|
|
$"hasEnemyHealth={c.GetComponent<EnemyHealth>() != null}");
|
|
}
|
|
|
|
bool hitAny = false;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var enemyHealth = s_overlapBuffer[i].GetComponent<EnemyHealth>();
|
|
if (enemyHealth == null || enemyHealth.IsDead) continue;
|
|
|
|
var enemyStatus = s_overlapBuffer[i].GetComponent<EnemyStatus>();
|
|
if (enemyStatus == null) continue;
|
|
|
|
enemyStatus.ApplyEffect(DamageType.Cold, SlowFactor, EffectDuration, owner);
|
|
hitAny = true;
|
|
}
|
|
|
|
return hitAny;
|
|
}
|
|
}
|
|
}
|