fix(inventory-go): add Prodigal Spirit Drinker effect; document dmgMod key substitution; test wand mastery fallback
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
99f394d1ef
commit
9b2f28d942
2 changed files with 44 additions and 5 deletions
|
|
@ -416,6 +416,7 @@ var elemVsMonSpellEffects = map[int]odSpellEffect{
|
||||||
3250: {.03, .03}, // Major Spirit Thirst
|
3250: {.03, .03}, // Major Spirit Thirst
|
||||||
4670: {.05, .05}, // Epic Spirit Thirst
|
4670: {.05, .05}, // Epic Spirit Thirst
|
||||||
6098: {.07, .07}, // Legendary Spirit Thirst
|
6098: {.07, .07}, // Legendary Spirit Thirst
|
||||||
|
3735: {.15, 0}, // Prodigal Spirit Drinker
|
||||||
}
|
}
|
||||||
|
|
||||||
// buffedMaxDamage mirrors GetBuffedIntValueKey(218103842): base value minus
|
// buffedMaxDamage mirrors GetBuffedIntValueKey(218103842): base value minus
|
||||||
|
|
@ -497,11 +498,12 @@ func computeOD(raw map[string]any) (float64, bool) {
|
||||||
}
|
}
|
||||||
bv, ok := bestValues[key]
|
bv, ok := bestValues[key]
|
||||||
if !ok && oc == 31 {
|
if !ok && oc == 31 {
|
||||||
// Wands: our probe showed some wands lack key 353 (mastery), which
|
// Mastery-0 retry for wands: an ADDITION over UB (UB's
|
||||||
// defaults to 0 via ivI — but retry explicitly with mastery 0 so the
|
// DataTable.Select has no retry; our captured wands may carry a
|
||||||
// void VR wand row (43,12,...) stays reachable while items that
|
// mastery key 353 while the table's wand rows use mastery 0).
|
||||||
// genuinely carry a different mastery value still fall back to the
|
// Keeps the void VR wand row (43,12,...) reachable on the first
|
||||||
// normal (34|43, 0, ...) rows.
|
// exact-match attempt while other mastery-carrying wands fall back
|
||||||
|
// to the normal (34|43, 0, ...) rows.
|
||||||
key.mastery = 0
|
key.mastery = 0
|
||||||
bv, ok = bestValues[key]
|
bv, ok = bestValues[key]
|
||||||
}
|
}
|
||||||
|
|
@ -550,6 +552,11 @@ func computeOD(raw map[string]any) (float64, bool) {
|
||||||
remaining = 0
|
remaining = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: UB's literal CalcMissileDamage reads DoubleValues[63], but no
|
||||||
|
// DoubleValueKey ordinal 63 exists (verified against Decal.Adapter) —
|
||||||
|
// that line is a stale/bugged reference in the UB source. The correct
|
||||||
|
// populated key is 167772174 (DamageBonus), consistent with UB's own
|
||||||
|
// CalcedBuffedMissileDamage. Do NOT "fix" this back to 63.
|
||||||
dmgMod := dvF(dv, "167772174", 0)*100 - 100
|
dmgMod := dvF(dv, "167772174", 0)*100 - 100
|
||||||
bDmg := float64(buffedMaxDamage(raw, iv))
|
bDmg := float64(buffedMaxDamage(raw, iv))
|
||||||
if bDmg <= 10 {
|
if bDmg <= 10 {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,38 @@ func TestOD_Wand(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wand with an ACTIVE Prodigal Spirit Drinker (3735, change .15, bonus 0):
|
||||||
|
// shown ElemVsMonsters 1.55 un-buffs to 1.55 − .15 = 1.40 → OD +22, same
|
||||||
|
// underlying weapon as TestOD_Wand.
|
||||||
|
func TestOD_WandActiveProdigalSpiritDrinker(t *testing.T) {
|
||||||
|
raw := map[string]any{
|
||||||
|
"ObjectClass": 31.0,
|
||||||
|
"IntValues": map[string]any{"159": 34.0, "160": 385.0},
|
||||||
|
"DoubleValues": map[string]any{"152": 1.55, "167772169": 8.0},
|
||||||
|
"Spells": []any{}, "ActiveSpells": []any{3735.0},
|
||||||
|
}
|
||||||
|
od, ok := computeOD(raw)
|
||||||
|
if !ok || !approx(od, 22.0) {
|
||||||
|
t.Fatalf("wand w/ active Prodigal SD OD = %v ok=%v, want +22", od, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wand carrying a mastery value (353) with no matching wand table row: the
|
||||||
|
// exact-match lookup on (34,5,0,385) misses, and the mastery-0 retry must hit
|
||||||
|
// the (34,0,0,385) row → OD +22 as in TestOD_Wand.
|
||||||
|
func TestOD_WandMasteryFallback(t *testing.T) {
|
||||||
|
raw := map[string]any{
|
||||||
|
"ObjectClass": 31.0,
|
||||||
|
"IntValues": map[string]any{"159": 34.0, "353": 5.0, "160": 385.0},
|
||||||
|
"DoubleValues": map[string]any{"152": 1.40, "167772169": 8.0},
|
||||||
|
"Spells": []any{}, "ActiveSpells": []any{},
|
||||||
|
}
|
||||||
|
od, ok := computeOD(raw)
|
||||||
|
if !ok || !approx(od, 22.0) {
|
||||||
|
t.Fatalf("wand mastery-fallback OD = %v ok=%v, want +22", od, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Non-loot (no workmanship) → no OD.
|
// Non-loot (no workmanship) → no OD.
|
||||||
func TestOD_NonLootNull(t *testing.T) {
|
func TestOD_NonLootNull(t *testing.T) {
|
||||||
raw := map[string]any{
|
raw := map[string]any{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue