Combat: MC-4 combo-chain melee as the primary verb (DR-030)
Melee combo (left-click / pad-West) becomes the player's primary verb; the ranged projectile is demoted to right-click / pad-left-trigger. Predicted, owner-replicated combo Step (path-dependent -> [GhostField] anchor + absolute-write idempotency, NOT derived like the dash), server-only cleave mirroring ProjectileDamageSystem (SourceTick-stamped DamageEvent + KnockbackState), dash-cancellable movement-commit, 9 live TuningConfig knobs, and swing juice scaling with the combo step. The MC-6 archetype byte is deferred (the melee is its own verb). See DR-030. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// Pure, deterministic cone hit-test for the MC-4 melee cleave. Shares the EXACT range + bearing predicate with
|
||||
/// <see cref="AutoTarget"/> (planar XZ distance gate + <c>dot(bearing, facing) >= cos(halfAngle)</c>) but as a
|
||||
/// per-candidate boolean, so the cleave can collect ALL enemies in the cone — <see cref="AutoTarget.Resolve"/> is a
|
||||
/// single-winner reducer and cannot be reused for collect-all (MC-4 review REUSE-1). Burst-safe, allocation-free,
|
||||
/// no wall-clock / no randomness; intended to run server-side inside the predicted <c>MeleeComboSystem</c>.
|
||||
/// </summary>
|
||||
public static class MeleeConeMath
|
||||
{
|
||||
/// <summary>
|
||||
/// True iff <paramref name="targetPos"/> lies within <paramref name="range"/> (planar XZ) of
|
||||
/// <paramref name="from"/> AND its bearing from <paramref name="from"/> is within the cone half-angle of
|
||||
/// <paramref name="facingDir"/> (<paramref name="cosHalfAngle"/> = cos(halfAngle)). A coincident
|
||||
/// (zero-distance) target is excluded (undefined bearing). <paramref name="facingDir"/> must be
|
||||
/// caller-normalized; a zero-length facing or a non-positive range returns false.
|
||||
/// </summary>
|
||||
public static bool InCone(float3 from, float2 facingDir, float range, float cosHalfAngle, float3 targetPos)
|
||||
{
|
||||
if (range <= 0f || math.lengthsq(facingDir) < 1e-6f)
|
||||
return false;
|
||||
|
||||
float3 offset = targetPos - from;
|
||||
float2 planar = new float2(offset.x, offset.z);
|
||||
float distSq = math.lengthsq(planar);
|
||||
|
||||
if (distSq < 1e-6f)
|
||||
return false; // coincident -> undefined bearing
|
||||
if (distSq > range * range)
|
||||
return false; // out of range
|
||||
|
||||
float2 bearing = planar * math.rsqrt(distSq); // normalized planar bearing
|
||||
return math.dot(bearing, facingDir) >= cosHalfAngle;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user