feat(diag): #266 - [stat-chain] apparatus across the vitae-to-movement chain
Three permanent low-volume probes: installed vitae record (id/type/key/ value) at ReplaceManifest, any vitae record dropped by GetMod's spell-table prepass (retail's _vitae singleton never runs family stacking - if this fires, hoist the Bucket-4 branch), and the full recompute state (base skills, runMod, effective skills, active count). One instrumented relog decides the break point. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4880d7d9cf
commit
f6e895c06c
3 changed files with 42 additions and 0 deletions
|
|
@ -100,7 +100,23 @@ public static class EnchantmentMath
|
||||||
foreach (var ench in enchantments)
|
foreach (var ench in enchantments)
|
||||||
{
|
{
|
||||||
if (!table.TryGet(ench.SpellId, out var meta))
|
if (!table.TryGet(ench.SpellId, out var meta))
|
||||||
|
{
|
||||||
|
// #266 apparatus (permanent, rare): a VITAE record silently
|
||||||
|
// dropped by the spell-table lookup would zero the whole
|
||||||
|
// stat-chain effect — surface it. (Retail keeps _vitae on a
|
||||||
|
// dedicated singleton slot that never runs family stacking;
|
||||||
|
// if this line ever fires the faithful fix is hoisting the
|
||||||
|
// Bucket-4 branch above the table lookup.)
|
||||||
|
if (ench.Bucket == 4)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine(
|
||||||
|
System.FormattableString.Invariant(
|
||||||
|
$"[stat-chain] VITAE DROPPED by spell-table lookup: "
|
||||||
|
+ $"spell={ench.SpellId} value="
|
||||||
|
+ $"{(ench.StatModValue is float dv ? dv.ToString("F4") : "NULL")}"));
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
// Family 0 means "no stacking bucket" — these don't dedup;
|
// Family 0 means "no stacking bucket" — these don't dedup;
|
||||||
// pass them through with a synthetic key per layer.
|
// pass them through with a synthetic key per layer.
|
||||||
uint bucket = meta.Family == 0 ? ench.LayerId | 0x80000000u : meta.Family;
|
uint bucket = meta.Family == 0 ? ench.LayerId | 0x80000000u : meta.Family;
|
||||||
|
|
|
||||||
|
|
@ -382,7 +382,21 @@ public sealed class Spellbook
|
||||||
_vitalModCache.Clear();
|
_vitalModCache.Clear();
|
||||||
_skillModCache.Clear();
|
_skillModCache.Clear();
|
||||||
foreach (ActiveEnchantmentRecord enchantment in enchantments)
|
foreach (ActiveEnchantmentRecord enchantment in enchantments)
|
||||||
|
{
|
||||||
UpsertManifestEnchantment(enchantment);
|
UpsertManifestEnchantment(enchantment);
|
||||||
|
// #266 apparatus (permanent, login-only volume): surface every
|
||||||
|
// installed VITAE record so the stat-chain break point is
|
||||||
|
// decidable from one log. Bucket 4 = vitae singleton class.
|
||||||
|
if (enchantment.Bucket == 4)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine(
|
||||||
|
System.FormattableString.Invariant(
|
||||||
|
$"[stat-chain] login vitae installed: spell={enchantment.SpellId} "
|
||||||
|
+ $"statModType=0x{enchantment.StatModType ?? 0:X} "
|
||||||
|
+ $"key={enchantment.StatModKey ?? 0} "
|
||||||
|
+ $"value={(enchantment.StatModValue is float v ? v.ToString("F4") : "NULL")}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _favoriteSpells.Length; i++)
|
for (int i = 0; i < _favoriteSpells.Length; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,18 @@ public sealed class RuntimeCharacterState : IDisposable
|
||||||
int jump = _jumpSkillBase >= 0
|
int jump = _jumpSkillBase >= 0
|
||||||
? ApplySkillEnchantments(_jumpSkillBase, JumpSkillId)
|
? ApplySkillEnchantments(_jumpSkillBase, JumpSkillId)
|
||||||
: -1;
|
: -1;
|
||||||
|
// #266 apparatus (permanent, low-volume — fires only on skill-base or
|
||||||
|
// enchantment changes, the [snap] class): the full stat-chain state at
|
||||||
|
// each recompute. If vitae is active but runMod prints 1.0, the break
|
||||||
|
// is in GetSkillMod's record handling; if runMod is right but the
|
||||||
|
// felt speed doesn't change, the break is downstream of MovementSkills.
|
||||||
|
EnchantmentMath.VitalMod runMod = Spellbook.GetSkillMod(RunSkillId);
|
||||||
|
System.Console.WriteLine(
|
||||||
|
System.FormattableString.Invariant(
|
||||||
|
$"[stat-chain] base run={_runSkillBase} jump={_jumpSkillBase} "
|
||||||
|
+ $"runMod={runMod.Multiplier:F4}x+{runMod.Additive:F1} "
|
||||||
|
+ $"-> eff run={run} jump={jump} "
|
||||||
|
+ $"(activeEnchantments={System.Linq.Enumerable.Count(Spellbook.ActiveEnchantments)})"));
|
||||||
MovementSkills.Update(run, jump);
|
MovementSkills.Update(run, jump);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue