Combat feel: correct boss bar, player hit-flash, dash-to-move, finisher hit-stop

Boss bar reconstructs the true max client-side (Health.Max unreplicated) via
Kind==Charger + expedition-pos filter; boss slam telegraph = a full ground ring
at BossSlamRadius; IsAttacking OR's IsLunging. Player body flash on hurt (distinct
red, jitter-safe threshold). Dash toward movement input when moving else facing.
Warrior cone: muzzle-cue suppressed (cone arc is its cue). Minimal finisher-only
hit-stop (PrototypeCameraRig.Hold, behind FeelConfig flag; never Time.timeScale).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-05 20:21:32 -07:00
parent 3995af736c
commit 43d7cca2f8
7 changed files with 92 additions and 24 deletions
@@ -67,6 +67,8 @@ namespace ProjectM.Client
dt = dt,
prevPos = _prevPos,
seen = seen,
isLunging = SystemAPI.GetComponentLookup<IsLunging>(true),
};
Dependency = job.Schedule(Dependency); // .Schedule (not parallel): mutates _prevPos
// Prune stale entries (despawned Husks) AFTER the job, on the main thread.
@@ -90,6 +92,8 @@ namespace ProjectM.Client
partial struct EnemyDriveJob : IJobEntity
{
public FastAnimatorParameter moveX, moveZ, speed, isAttacking;
[Unity.Collections.ReadOnly] public ComponentLookup<IsLunging> isLunging; // A7: a lunge has no AttackWindup; OR it in so the boss/Charger attack anim plays during the committed lunge
public float dt;
public NativeParallelHashMap<Entity, float3> prevPos;
public NativeParallelHashSet<Entity> seen;
@@ -111,7 +115,7 @@ namespace ProjectM.Client
float2 facing = AnimParamMath.PlanarForward(xform.Rotation);
float3 p = AnimParamMath.LocomotionParams(vel, facing, stats.MoveSpeed);
bool attacking = windup.WindUpUntilTick != 0;
bool attacking = windup.WindUpUntilTick != 0 || (isLunging.HasComponent(e) && isLunging.IsComponentEnabled(e)); // A7: the committed lunge (which zeroes AttackWindup) still animates as an attack
var a = new AnimatorParametersAspect(parametersArr, indexTable);
if (a.HasParameter(moveX)) a.SetParameterValue(moveX, p.x);