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
@@ -56,6 +56,13 @@ namespace ProjectM.Simulation
public float StaggerKnockbackSpeed;
public float SeparationMaxSpeed;
// Facing/underwater feel (07-15): DEV OVERRIDES with a 0 = NO-OVERRIDE sentinel (0 falls back to the
// deterministic source: authored stat / compile-time const / authored sharpness). Unlike other knobs
// these default to 0 and clamp >= 0 — consumers substitute their source, a 0 never reaches an integrator.
public float TurnRateDeg; // locomotion body-turn (deg/s); 0 = EffectiveCharacterStats.TurnRateRadiansPerSec
public float CastTurnRateDeg; // cast-window body-turn (deg/s); 0 = PlayerAimSystem's cast-turn const
public float MoveSharpness; // grounded accel sharpness; 0 = CharacterComponent.DefaultGroundedSharpness
/// <summary>The baked feel defaults == the pre-MC-0 consts. Single source of truth for the fallback path.</summary>
public static TuningConfig Defaults() => new TuningConfig
{
@@ -81,6 +88,10 @@ namespace ProjectM.Simulation
StructureAggroWeight = 0.7f, // EB-1: <1 prefers structures (fortress aggro); live-tunable
StaggerKnockbackSpeed = 7f, // B2 poise: kb.Speed >= this interrupts windups/lunges; below = nudge only
SeparationMaxSpeed = 3f, // B1: max separation push (units/s) so soft-collision can't fling
TurnRateDeg = 0f, // 07-15 facing feel: 0 = no override (authored stat wins)
CastTurnRateDeg = 0f, // 0 = no override (PlayerAimSystem cast-turn const wins)
MoveSharpness = 0f, // 0 = no override (DefaultGroundedSharpness wins)
};
/// <summary>Clamp a knob to its safe floor: tick knobs &gt;= 1, value knobs &gt;= 0. Used by every write path
@@ -101,6 +112,9 @@ namespace ProjectM.Simulation
case TuningKnob.MeleeFinisherMult:
case TuningKnob.StructureAggroWeight:
case TuningKnob.StaggerKnockbackSpeed:
case TuningKnob.TurnRateDeg: // 07-15: 0 = no-override sentinel (never reaches an integrator)
case TuningKnob.CastTurnRateDeg:
case TuningKnob.MoveSharpness:
case TuningKnob.SeparationMaxSpeed:
return math.max(0f, value);
// tick knobs: >= 1 (a 0 tick count is degenerate; a 0 i-frame window divides-by-zero in DashSystem).
@@ -138,6 +152,10 @@ namespace ProjectM.Simulation
case TuningKnob.StructureAggroWeight: c.StructureAggroWeight = value; break;
case TuningKnob.StaggerKnockbackSpeed: c.StaggerKnockbackSpeed = value; break;
case TuningKnob.SeparationMaxSpeed: c.SeparationMaxSpeed = value; break;
case TuningKnob.TurnRateDeg: c.TurnRateDeg = value; break;
case TuningKnob.CastTurnRateDeg: c.CastTurnRateDeg = value; break;
case TuningKnob.MoveSharpness: c.MoveSharpness = value; break;
// unknown index -> no-op (matches the no-default switch convention in DebugCommandReceiveSystem)
}
}
@@ -169,6 +187,10 @@ namespace ProjectM.Simulation
case TuningKnob.StructureAggroWeight: return c.StructureAggroWeight;
case TuningKnob.StaggerKnockbackSpeed: return c.StaggerKnockbackSpeed;
case TuningKnob.SeparationMaxSpeed: return c.SeparationMaxSpeed;
case TuningKnob.TurnRateDeg: return c.TurnRateDeg;
case TuningKnob.CastTurnRateDeg: return c.CastTurnRateDeg;
case TuningKnob.MoveSharpness: return c.MoveSharpness;
default: return 0f;
}
}
@@ -198,6 +220,10 @@ namespace ProjectM.Simulation
StructureAggroWeight = c.StructureAggroWeight,
StaggerKnockbackSpeed = c.StaggerKnockbackSpeed,
SeparationMaxSpeed = c.SeparationMaxSpeed,
TurnRateDeg = c.TurnRateDeg,
CastTurnRateDeg = c.CastTurnRateDeg,
MoveSharpness = c.MoveSharpness,
};
/// <summary>Reconstruct the full config from a wire snapshot (FULL state, not a delta).</summary>
@@ -225,6 +251,10 @@ namespace ProjectM.Simulation
StructureAggroWeight = r.StructureAggroWeight,
StaggerKnockbackSpeed = r.StaggerKnockbackSpeed,
SeparationMaxSpeed = r.SeparationMaxSpeed,
TurnRateDeg = r.TurnRateDeg,
CastTurnRateDeg = r.CastTurnRateDeg,
MoveSharpness = r.MoveSharpness,
};
}
@@ -255,9 +285,13 @@ namespace ProjectM.Simulation
// 20 = CoreDamagePerHusk · 21 = CoreRegenIntervalTicks · 22 = CoreOverrunDrainPct · 23 = FinalSiegeMultiplier
public const byte StaggerKnockbackSpeed = 24;
public const byte SeparationMaxSpeed = 25;
// 07-15 facing/underwater feel dev-overrides (0 = no-override sentinel; see TuningConfig fields):
public const byte TurnRateDeg = 26;
public const byte CastTurnRateDeg = 27;
public const byte MoveSharpness = 28;
/// <summary>Knob count (overlay iteration bound).</summary>
public const byte Count = 26;
public const byte Count = 29;
}
/// <summary>
@@ -290,5 +324,11 @@ namespace ProjectM.Simulation
public float StructureAggroWeight;
public float StaggerKnockbackSpeed;
public float SeparationMaxSpeed;
public float TurnRateDeg;
public float CastTurnRateDeg;
public float MoveSharpness;
}
// NOTE: appending fields = a DEV-PROTOCOL BUMP (RpcCollection hash) — rebuild both peers together.
}