Skip to content

Item power (⚡) redesign: bound affix variance, score god items, and account for the full 50-zone ilvl range #618

Description

@stphung

Background

Supersedes #272 (god items should outscore top Legendaries) and #332 (Legendary power variance too high from affix type weighting). Both are symptoms of the same formula, and both were written against a Zone-10 world that no longer exists.

Current formula (src/items/types.rs Item::power(), weights in src/items/scoring.rs):

power = Σ attribute_values + Σ (affix_value × affix_weight)     // weights 0.5x–2.0x

Two structural problems:

  1. Affix values live on incommensurate scales. At the same ilvl/tier/rarity, an HPBonus roll is ~50–80 base, DamagePercent is 6–10, CritMultiplier is 0.2–0.35, AttackSpeed is 2.0–3.3 (src/items/generation.rs). The weight table tries to correct for scale and impact simultaneously and does neither — a CritMultiplier 1.3 (a strong roll) contributes ⚡2 while an HPBonus 125 contributes ⚡63.
  2. The formula only sees attributes and affixes. God item passives (Giant's Might 150% dmg, Windborne 100% AtkSpd, Divine Bulwark 30% multiplicative DR) and non-combat bonuses are invisible, so all three god items score ⚡100.

What changed since #272/#332: there are 50 zones

ilvl_for_zone(zone_id) = zone_id × 10 is uncapped and process_item_drop passes current_zone_id (up to 50) straight through. The stat multiplier 1 + (ilvl − 10)/30 therefore spans:

Zone ilvl Multiplier
10 100 4.0x
20 200 7.3x
30 300 10.7x
40 400 13.7x
50 500 17.3x

Consequences:

Reference items

Hand-rolled from the actual generator ranges in generation.rs (all values are legal rolls). Used for every comparison below.

# Item Rolls
A T6 Legendary Ring, ilvl 40 (Zone 4) — the "Evaa ring" from #332; near-perfect rolls of low-weight types CON 6; HPBonus 125, DR 14%, CritMult 0.53, DR 15%, HPBonus 121
B T9 Legendary Armor, ilvl 40 (Zone 4) — mediocre defensive rolls CON 10, WIS 8; HPBonus 102, HPRegen 13, Reflect 13%, XPGain 12%
C T9 Legendary Weapon, ilvl 100 (Zone 10) — hot offensive rolls STR 22, DEX 18, CON 16; Dmg 38%, Dmg 36%, Dmg 33%, CritChance 30%, CritMult 1.30
D T9 Legendary Weapon, ilvl 300 (Zone 30) — typical good rolls STR 53, DEX 43; Dmg 96%, CritChance 75%, HPBonus 693, DR 85%, XPGain 75%
E T9 Legendary Weapon, ilvl 500 (Zone 50) — theoretical perfect roll 3× attr 104; 5× Dmg 173%
F God items (Asprika / Sleipnir / Megingjord) — ilvl 100, T9, fixed stats 60 attrs; XPGain 40%; passive (30% DR / 100% AtkSpd / 150% Dmg)

Current-formula scores: A=167, B=104, C=317, D=933, E≈2,040, F=100 each.

The A-vs-B pair is the #332 tier inversion (T6 beats T9 at the same ilvl by 1.6x). F-vs-everything is #272, now much worse than the issue described.

Candidate designs

Design 1 — Base power × roll quality ("budget" model) — recommended

power = rarity_base × ilvl_mult × tier_mult × (1 + 0.25 × roll_quality)
  • rarity_base: Common 10, Magic 20, Rare 35, Epic 55, Legendary 80, Mythic 120
  • roll_quality ∈ [0,1]: mean of each attribute/affix roll normalized against its own max possible roll at that ilvl/tier/rarity — HPBonus 125 is judged as "a 98% HP roll", not as 125 raw points
  • Deterministic progression inputs (ilvl, tier, rarity) form the base; RNG only modulates ±25%
  • God items: Mythic base plus passives scored as oversized normalized rolls

Properties: tier is near-monotonic (worst T9 = best T6 at same ilvl/rarity); affix-type luck bounded at 1.25x instead of ~4x; every input already exists in generation.rs. Open detail: affix-count luck (Legendary rolls 4–5 affixes) — fold into roll_quality or into rarity_base.

Design 2 — Minimal patch: normalize affixes in place, feed passives through as affixes

Keep the formula shape. Per affix: quality × budget × weight where quality = value / max_roll(type, ilvl, tier), budget = 20 × ilvl_mult × tier_mult, and weights narrowed to 0.8x–1.5x. God item passives enter as pseudo-affixes at true magnitude (150% Dmg normalizes to 3.75× a perfect Dmg roll) with a uniform "unique passive" weight of 2.0.

Properties: smallest diff, kills the per-type scale artifact (CritMult 1.30 goes from ⚡2 to ⚡89). But tier inversions shrink rather than disappear (see table: A still beats B), and Asprika fails — 30% multiplicative DR normalizes small against a 40% DR affix roll even though it's far stronger in the damage pipeline. Fixing that requires a hand-tuned premium, which is #272's rejected option 3 wearing a hat.

Design 3 — Impact model: marginal DPS/EHP on a fixed reference hero

power = k × (ΔDPS% + ΔEHP% + Δutility%) computed against a fixed reference build (character-independence preserved). Every affix and passive gets an exact conversion instead of a guessed weight: Windborne = 2× DPS, Divine Bulwark 30% multiplicative DR = +43% EHP, flat HP judged against the reference HP pool.

Properties: most principled, player-meaningful number, new affixes scored for free. Highest effort: needs conversions mirroring combat/, revalidation when combat formulas change, and it immediately surfaces that late-zone % affix rolls are balance-broken in their own right (see "Related" below).

How the reference items score under each design

Designs 1–2 computed exactly; Design 3 is coarse (depends on reference-build assumptions).

Item Current Design 1 Design 2 Design 3 (~)
A — Z4 T6 ring, lucky types 167 154 161 ~700
B — Z4 T9 armor, mediocre 104 184 ✅ beats A 109 ❌ still loses to A ~250
C — Z10 T9 weapon, hot 317 388 538 ~1,400
D — Z30 T9 weapon, good 933 999 1,001 ~3,500
E — Z50 T9 weapon, perfect ~2,040 1,733 2,912 ~9,000
Megingjord 100 ~2,300–2,600 (pinned*) / ~575 unpinned 740 ~1,600
Sleipnir 100 ~2,300–2,600 (pinned*) / ~575 unpinned 1,352 ~1,200
Asprika 100 ~2,300–2,600 (pinned*) / ~575 unpinned ~260 ❌ ~550

* "Pinned" = god items scored at the max-zone ilvl multiplier (see decision below).

Reading the table:

  • Legendary item power variance too high due to affix type weighting #332's tier inversion (A vs B): only Design 1 fixes it outright. Design 2 narrows the gap ~1.7x → ~1.5x but quality+count luck still outweighs the T6→T9 budget difference.
  • God items should score higher than T9 Legendaries in item power #272 (god items): under Design 1 pinned, all three clear the Zone 50 ceiling with no hand-set values (Mythic base 120 × 17.3 = 2,076 > max Legendary 1,733). Design 2 handles Megingjord/Sleipnir but fails Asprika without arbitrary tuning. Design 3 scores passives truthfully but leaves god items mid-scale.
  • Zone progression: all three designs keep median power rising with zone, matching the 1.6x/1.25x enemy scaling story.

Decision needed: where do god items sit on a 50-zone scale?

God items have fixed stats (ilvl 100) while drops scale to ilvl 500. Auto-equip already never replaces a Mythic (scoring.rs), so this is purely about what the ⚡ number communicates. Options:

Acceptance criteria (zone-aware replacements for #272's)

  • At the same ilvl and rarity, a T9 with worst-case rolls scores ≥ a T6 with best-case rolls (tier monotonicity)
  • Within the same ilvl/tier/rarity, max/min power ratio from affix luck ≤ ~1.3x (was ~4x)
  • Median Legendary power strictly increases with zone bracket across all 50 zones
  • All 3 god items score above the max possible drop from any zone (if option (a) above)
  • Power stays character-independent and computed on the fly (no save migration)
  • Unit tests: god-item ceiling test, statistical tier-ordering test over N generated items
  • src/items/CLAUDE.md and wiki updated (both document the current 0.5x–2.0x weights)

Related observation (probably its own issue)

While hand-rolling item D: generic % affixes scale linearly and uncapped with ilvl, so a single Zone 30 Legendary affix can roll +85% DamageReduction and Zone 50 +173% Damage — independent of how we score them, these raw magnitudes look balance-broken (DR stacking past 100%?). Whatever design wins here, the generator's late-zone affix ranges deserve their own audit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew game content, systems, or mechanics

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions