feat(player): use server-authoritative Run + Jump skill values from PlayerDescription

Before this commit, PlayerWeenie used hardcoded ACDREAM_RUN_SKILL
(default 200) and ACDREAM_JUMP_SKILL (default 300) regardless of
the actual character skill. PlayerDescription's skill table HAS
been parsed since Phase H, but the values weren't plumbed into
PlayerMovementController, so a high-Jump character still got the
3-4m default arc instead of their real 5m+ arc, and a low-Jump
character got too much.

GameEventWiring.WireAll gains an optional `onSkillsUpdated`
callback. The PlayerDescription handler scans the parsed skill
table for SkillId 24 (Run) and SkillId 22 (Jump) — ACE Skill enum
ordinals from references/ACE/.../Enum/Skill.cs:11-37 — and fires
the callback with `init + ranks` for each (the holtburger-named
"init" field is the attribute-derived initial component, ranks
is XP-bought additions; closest sane approximation of ACE's
CreatureSkill.Current short of porting Aug + Multiplier + Vitae
chains).

GameWindow stores the most recent values in _lastSeenRunSkill /
_lastSeenJumpSkill and pushes them into the controller at two
points:
  * Immediately if _playerController already exists (PD arriving
    mid-session, e.g. after a relog).
  * Inside EnterPlayerModeNow when constructing a fresh
    controller (the auto-entry path: PD always arrives at login
    before auto-entry fires, so this is the normal path).

Both sites also log "applied server skills run=X jump=Y" so live
testing can confirm the right values reached the formula.

Console output (ACDREAM_DUMP_VITALS=1) gains a "vitals: PD-skills
run=X jump=Y" line on every PlayerDescription with skill data.

Tests stay 1222 green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-26 17:22:59 +02:00
parent 5145938d06
commit 1fce21034a
2 changed files with 83 additions and 2 deletions

View file

@ -37,7 +37,18 @@ public static class GameEventWiring
Spellbook spellbook,
ChatLog chat,
LocalPlayerState? localPlayer = null,
TurbineChatState? turbineChat = null)
TurbineChatState? turbineChat = null,
// K-fix7 (2026-04-26): server-sent skill update callback. Fires
// whenever PlayerDescription's skill table arrives with Run (24)
// or Jump (22) entries — we only care about those two for
// movement physics. Caller (GameWindow) plumbs this into the
// active PlayerMovementController + caches it for the next
// EnterPlayerModeNow construction. Each value is `init + ranks`
// (the holtburger-named "init" field is already the
// attribute-derived initial component, ranks is XP-bought
// additions; matches retail's GetCreatureSkill.Current minus
// augs / multipliers / vitae).
Action<int /*runSkill*/, int /*jumpSkill*/>? onSkillsUpdated = null)
{
ArgumentNullException.ThrowIfNull(dispatcher);
ArgumentNullException.ThrowIfNull(items);
@ -295,6 +306,33 @@ public static class GameEventWiring
foreach (uint sid in p.Value.Spells.Keys)
spellbook.OnSpellLearned(sid);
// K-fix7 (2026-04-26): push Run + Jump skill values to the
// PlayerMovementController so the runRate / jump-arc formulas
// use the SERVER's authoritative skill instead of our
// hardcoded ACDREAM_*_SKILL defaults. ACE Skill enum
// ordinals (Skill.cs:11-37): Jump = 22, Run = 24. The
// SkillEntry.Init field is the attribute-derived initial
// component; .Ranks is XP-bought additions. Their sum is
// the closest we get to ACE's CreatureSkill.Current short
// of porting the full Aug/Multiplier/Vitae chain.
if (onSkillsUpdated is not null)
{
int runSkill = -1;
int jumpSkill = -1;
foreach (var s in p.Value.Skills)
{
int total = (int)(s.Init + s.Ranks);
if (s.SkillId == 24u) runSkill = total;
else if (s.SkillId == 22u) jumpSkill = total;
}
if (runSkill >= 0 || jumpSkill >= 0)
{
if (dumpPd)
Console.WriteLine($"vitals: PD-skills run={runSkill} jump={jumpSkill}");
onSkillsUpdated(runSkill, jumpSkill);
}
}
// Issue #7 — enchantment block: feed each entry into the
// Spellbook with full StatMod data so EnchantmentMath can
// aggregate buffs in vital-max calc (issue #6 lights up).