LANTERN feel pass (DR-052 + gap list): SoD facing, underwater feel, Bathynaut kit, walk/run gait, suit lamp + new Synty anim packs

- SoD facing: PlayerFacing = body-yaw only (move-facing / cast-turn / idle-hold); every fire
  direction re-sourced to FacingMath.ResolveAim (pre-code review blocking catch); TickWindowMath
  shared windows with Movement-skip; reticle/FX coupled to the damage direction; cursor-dash kept.
- Underwater feel: sharpness 15->6, turn 720->360, MoveSpeed 6->4.2; TuningKnob 26-28
  (0 = no-override sentinels, dev-protocol bump on DebugTuningReport); stride footsteps + silt +
  cadence floor; bubbles; underwater ambience bed + distant groans; camera drag + dev scroll zoom.
- Bathynaut kit in-engine: dome/tank/shoulder-lamp + bare head grafted (GraftSmr rigid rebase,
  RecalculateTangents); EmissiveGloamSkinned shader (Rukhanka deformation); shoulder lamp CASTS
  (warm steady spot on body yaw).
- Gait: two-ring walk/run FreeformDirectional tree (walk @0.35, run @1.0) + blended-natural
  StrideScale; additive Posture(Bank) + Lead(chest-lead) layers; idle = AnimationIdles Base;
  banking driven from facing turn rate; flat terrain (Env_SeabedKit seabed squashed - CC is planar).
- New packs: Synty AnimationIdles + AnimationSwordCombat (combat pass queued) + SyntyPropBoneTool;
  four authored clips (sway/trudge/banks/lean) + Anim_Player_Underwater.blend + suit-kit FBX.
- Validation: 411/411 EditMode green; Play smokes (server==client facing, Aim-true projectile,
  bank/stride live-sampled, lamp beam verified); pre-code + post-impl adversarial reviews applied.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 13:56:02 -07:00
parent 385d0de08e
commit 7571091394
2637 changed files with 1810753 additions and 303 deletions
@@ -171,8 +171,7 @@ namespace ProjectM.Simulation
{
if (isServer)
{
float2 cFace = facing.ValueRO.Direction;
cFace = math.lengthsq(cFace) < 1e-6f ? new float2(0f, 1f) : math.normalize(cFace);
float2 cFace = FacingMath.ResolveAim(input.ValueRO.Aim, facing.ValueRO.Direction); // manual-aim (07-15): cursor wins; facing fallback = resting gamepad stick
float cRange = math.max(0.1f, es.Range);
float cCosHalf = math.cos(math.clamp(es.AutoTargetConeRadians, 0.01f, 3.14159f));
uint cStamp = TickUtil.NonZero(serverTick.TickIndexForValidTick);
@@ -206,8 +205,7 @@ namespace ProjectM.Simulation
if (abilityPrefabs[i].Id == sparkId) { aoePrefab = abilityPrefabs[i].Prefab; break; }
if (aoePrefab != Entity.Null)
{
float2 aFace = facing.ValueRO.Direction;
aFace = math.lengthsq(aFace) < 1e-6f ? new float2(0f, 1f) : math.normalize(aFace);
float2 aFace = FacingMath.ResolveAim(input.ValueRO.Aim, facing.ValueRO.Direction); // manual-aim (07-15)
float3 spawnPos = xform.ValueRO.Position + new float3(aFace.x, 0f, aFace.y) * k_AoeCastAhead;
spawnPos.y = xform.ValueRO.Position.y;
uint expire = adef.DurationTicks > 0
@@ -239,8 +237,7 @@ namespace ProjectM.Simulation
{
if (isServer)
{
float2 hFace = facing.ValueRO.Direction;
hFace = math.lengthsq(hFace) < 1e-6f ? new float2(0f, 1f) : math.normalize(hFace);
float2 hFace = FacingMath.ResolveAim(input.ValueRO.Aim, facing.ValueRO.Direction); // manual-aim (07-15)
float hRange = math.max(0.1f, es.Range);
uint hStamp = TickUtil.NonZero(serverTick.TickIndexForValidTick);
for (int hi = 0; hi < coneTargets.Length; hi++)
@@ -276,8 +273,9 @@ namespace ProjectM.Simulation
uint socketFireCount = applied.InternalInput.GetSocket(sk).Count;
float2 rawAim = facing.ValueRO.Direction;
rawAim = math.lengthsq(rawAim) < 1e-6f ? new float2(0f, 1f) : math.normalize(rawAim);
// Manual-aim (07-15): the projectile (and the server's auto-target seed below) fires along the
// CURRENT tick's replicated Aim — PlayerFacing is body-yaw only under the SoD facing model.
float2 rawAim = FacingMath.ResolveAim(input.ValueRO.Aim, facing.ValueRO.Direction);
// Client fires along raw aim; only the server applies the gamepad auto-target assist.
float2 dir = rawAim;