Files
Project-M/Assets/_Project/Scripts/Simulation/Combat/EnemyAIMath.cs
T
kronic e362aaeb43 Import art/VFX asset packs + game-feel systems; normalize texture extensions to lowercase for LFS
Add BefourStudios SciFi environment packs, Gabriel Aguiar VFX, and the
ShaderCrew Toon Shader embedded packages, plus combat/enemy/wave/death
gameplay systems and supporting vault docs/screenshots.

Rename 11 vendor textures from uppercase .PNG/.HDR to lowercase so the
case-sensitive Git LFS filters (*.png/*.hdr) match on case-sensitive
filesystems (Linux CI, case-sensitive macOS), not just locally where
core.ignorecase=true masks the gap. Each .meta moved with its asset so
GUID references are preserved. All ~1000 binaries tracked via LFS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 22:50:43 -07:00

55 lines
2.2 KiB
C#

using Unity.Mathematics;
namespace ProjectM.Simulation
{
/// <summary>
/// Pure, deterministic Husk AI math — no RNG, no wall-clock — so server simulation stays reproducible and
/// the helpers are EditMode-unit-testable without an ECS world (mirrors <see cref="PlayerSpawnMath"/> /
/// <c>StatMath</c>).
/// </summary>
public static class EnemyAIMath
{
/// <summary>
/// Planar (XZ) seek velocity from <paramref name="from"/> toward <paramref name="to"/> at
/// <paramref name="speed"/>. Y is forced to 0 (top-down plane). Returns zero once within
/// <paramref name="stopDistance"/> (so the Husk halts at strike range instead of jittering through the
/// target) or when the two points coincide.
/// </summary>
public static float3 SeekVelocity(float3 from, float3 to, float speed, float stopDistance)
{
float3 d = to - from;
d.y = 0f;
float distSq = math.lengthsq(d);
if (distSq <= stopDistance * stopDistance || distSq < 1e-8f)
return float3.zero;
return math.normalize(d) * speed;
}
/// <summary>
/// True when <paramref name="to"/> is within <paramref name="range"/> of <paramref name="from"/> on the
/// XZ plane.
/// </summary>
public static bool InAttackRange(float3 from, float3 to, float range)
{
float3 d = to - from;
d.y = 0f;
return math.lengthsq(d) <= range * range;
}
/// <summary>
/// Deterministic planar ring position around <paramref name="center"/> for spawn
/// <paramref name="index"/>: evenly spaced over <paramref name="slots"/> angles at
/// <paramref name="radius"/>. Stable per index so a replayed spawn lands identically.
/// </summary>
public static float3 RingPosition(float3 center, int index, int slots, float radius)
{
if (slots < 1)
slots = 1;
int slot = ((index % slots) + slots) % slots;
float angle = (2f * math.PI * slot) / slots;
math.sincos(angle, out float s, out float c);
return center + new float3(c * radius, 0f, s * radius);
}
}
}