feat(physics): Campaign P P1 - stat-coupled movement (burden/stamina/vitae)
Ports the retail CACQualities/EncumbranceSystem/MovementSystem chain (named-retail decomp pc 256393/412901-414050/416169-416320/695958+) so PlayerWeenie's run rate, jump height, jump permission, and jump stamina cost are real functions of burden, current stamina, and vitae/skill enchantments instead of stubs. Core: - New EncumbranceSystem.cs (delegates to the already-verified BurdenMath formulas — one source of truth for the burden HUD and movement physics) and MovementSystem.cs (GetRunRate/GetJumpHeight/ JumpStaminaCost/GetJumpPower, decomp-cited; ACE cross-referenced where BN dropped the general-case arithmetic entirely). - PlayerWeenie rewritten as the CACQualities-shaped composition: CanJump gates on burden (<2.0 load, UN-8 — x87 polarity resolved by plausibility, Ghidra MCP unavailable this slice), JumpStaminaCost returns the real ceil((load+0.5)*power*8+2) cost and always affords it (matches decomp — retail's own function never refuses; "weak" jump comes entirely from the stamina==0 skill-zeroing gate inside InqRunRate/InqJumpVelocity, not a hard refusal), SetStamina wires a null="unknown, don't gate" sentinel preserving every pre-P1 test. - EnchantmentMath.GetMod gained an optional StatModType flag filter (GetSkillMod convenience wrapper) so the SAME vitae/family-stacking machinery already used for vital-max buffs now also answers "what's the vitae+skill-enchantment-adjusted Run/Jump skill" — reusing the M3 active-enchantment state, not a new engine. Runtime: - RuntimeCharacterState now stores the pre-EnchantSkill base run/jump skill and recomputes the adjusted value (vitae first, then matching Skill-flagged buffs, floor 0.5, truncate) on every base push AND on every Spellbook.EnchantmentsChanged notification — a vitae change alone moves the produced rate without a fresh PlayerDescription. - RuntimeMovementSkillState extended with Burden/CurrentStamina (RuntimeMovementSkillProjection.ApplyTo pushes both through the existing seam); LiveSessionEventRouter recomputes burden from the same Strength+aug-property+EncumbranceVal inputs the burden HUD already assembles (reacting to the same ClientObjectTable events) and pushes current stamina from LocalPlayerState vital updates. - Wires the previously dead-lettered ReportExhaustion() R3-W4 seam: LiveSessionRuntimeFactory's OnMovementStatsUpdated callback re- applies the current snapshot to the live controller and forces an immediate movement re-evaluation on any skill/burden/stamina change. Register: retires TS-5 (CanJump/JumpStaminaCost stubs) and AP-25 (no vitae in pushed skill). Adds AP-127 (two minor unmodeled retail bonus properties + the stamina-buff-adjusts-local-copy nuance, deliberately out of the bounded "run/jump query path only" scope) and UN-8 (the CanJump x87 polarity call, flagged for a future Ghidra MCP confirmation pass). Extends TS-23 (PlayerKillerStatus not parsed) to cover JumpStaminaCost's new pk parameter, hardcoded false pending P3. Full pseudocode + retail citations + the vitae/skill-level finding in docs/research/2026-07-30-stat-coupled-movement-pseudocode.md. Release suite: Core.Tests 3977/2 skips, Runtime.Tests 425/0 skips, App.Tests 3968/3 skips — all green. (One pre-existing, unrelated Debug- only flake in LandblockBuildOriginTests reproduces on the pre-P1 baseline and passes in Release; not touched here.) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
3a4782048e
commit
9355ddcec6
20 changed files with 1714 additions and 74 deletions
|
|
@ -275,25 +275,45 @@ internal sealed class LiveSessionRuntimeFactory
|
|||
_domain.Actions.Combat,
|
||||
_domain.Character,
|
||||
ResolveSkillFormulaBonus: skillCreditResolver.Resolve,
|
||||
OnSkillsUpdated: (runSkill, jumpSkill) =>
|
||||
{
|
||||
if (RuntimeMovementSkillProjection.ApplyTo(
|
||||
_domain.Character.MovementSkills,
|
||||
_player.Controller.Controller))
|
||||
{
|
||||
RuntimeMovementSkillSnapshot snapshot =
|
||||
_domain.Character.MovementSkills.Snapshot;
|
||||
_log(
|
||||
$"player: applied server skills " +
|
||||
$"run={snapshot.RunSkill} " +
|
||||
$"jump={snapshot.JumpSkill}");
|
||||
}
|
||||
},
|
||||
OnSkillsUpdated: (runSkill, jumpSkill) => ApplyMovementStats("skills"),
|
||||
OnConfirmationRequest: request =>
|
||||
_ui.RetailUi?.HandleConfirmationRequest(request),
|
||||
OnConfirmationDone: done =>
|
||||
_ui.RetailUi?.HandleConfirmationDone(done),
|
||||
ClientTime: ClientTimerNow);
|
||||
ClientTime: ClientTimerNow,
|
||||
// Campaign P Slice P1 (2026-07-30): burden/stamina/vitae changes
|
||||
// reactively re-apply to the live controller through the SAME
|
||||
// seam skills already used, then wire the previously-dead
|
||||
// ReportExhaustion() R3-W4 seam so movement re-evaluates
|
||||
// immediately (pseudocode doc §8/§9).
|
||||
OnMovementStatsUpdated: () => ApplyMovementStats("stats"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Re-applies the current <see cref="RuntimeMovementSkillState"/>
|
||||
/// snapshot (skills/burden/stamina) to the live player controller and
|
||||
/// forces an immediate movement re-evaluation via
|
||||
/// <c>MotionInterpreter.ReportExhaustion</c> — the retail
|
||||
/// <c>CMotionInterp::ReportExhaustion</c> dual-dispatch re-apply, now
|
||||
/// wired to a real consumer (Campaign P Slice P1).
|
||||
/// </summary>
|
||||
private void ApplyMovementStats(string reason)
|
||||
{
|
||||
PlayerMovementController? controller = _player.Controller.Controller;
|
||||
if (!RuntimeMovementSkillProjection.ApplyTo(
|
||||
_domain.Character.MovementSkills,
|
||||
controller))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
controller!.Motion.ReportExhaustion();
|
||||
|
||||
RuntimeMovementSkillSnapshot snapshot = _domain.Character.MovementSkills.Snapshot;
|
||||
_log(
|
||||
$"player: applied server movement {reason} "
|
||||
+ $"run={snapshot.RunSkill} jump={snapshot.JumpSkill} "
|
||||
+ $"burden={snapshot.Burden:F2} stamina={snapshot.CurrentStamina}");
|
||||
}
|
||||
|
||||
private LiveSessionCommandBindings CreateCommandBindings(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue