Items

magicsuffix

Magic and rare suffix affix pool.

magicsuffix.txt defines every suffix that can roll on a magic, rare, or crafted item — the of the Bear or of Frost half of an affix pair. Identical 39-column schema to magicprefix (same gating rules, same Properties.txtitemstatcost chain), but a separate pool: a magic item rolls one prefix and one suffix from the two tables independently.

786 rows total: 779 named affixes plus 6 blank-Name placeholder rows and one Expansion section marker (an engine row dividing Classic v1.x affixes from LoD additions in the source file).

Of the 779 named rows: 583 roll naturally (spawnable=1), 38 are explicitly disabled (spawnable=0), and 158 have a blank spawnable column (also effectively non-spawning — see Historical accumulation). 588 of the spawnable rows are also rare-eligible. 213 rows are class-restricted via class (with classlevelreq for the per-class equip gate), spread across 7 classes — these are the charged-skill-on-class-item suffixes ("of Magic Arrows", "of Power Strike") plus staffmod-style "+to skill" suffixes. 42 distinct exclusion groups partition the pool.

What's in a row

The 39 columns split into seven groups.

Identity

ColumnMeaning
NameDisplay name (the suffix phrase: of Health, of the Bear). Doesn't need to be uniquely named.
versionGame-version gate. <100 = Classic (the file uses 0 for original v1.0 affixes and 1 for v1.01–1.06 additions); 100 = LoD/D2R-era. See Historical accumulation.

Spawn gating

ColumnMeaning
spawnableThree meaningful states: 1 = rolls naturally on generated items; 0 = explicitly disabled (used by uniques, sets, crafted-recipe outputs); blank = legacy row with no explicit flag, treated as not naturally spawning.
rare1 = also eligible on rare items. 0 = magic-only.
levelqlvl at which this row becomes eligible. Higher-tier rows have higher level.
maxlevelOptional upper qlvl. Once item qlvl exceeds this, the row drops out of eligibility (lets newer tiers replace older ones).
levelreqPlayer clvl needed to equip the item once the affix has rolled. Independent of level.

Class restriction

ColumnMeaning
classspecificCompanion column for class restriction — always blank in magicsuffix (the suffix file uses class and classlevelreq exclusively). magicprefix uses classspecific instead.
classClass code from PlayerClass.txt (ama, bar, dru, nec, pal, sor, war). When set, the affix is class-scoped — only used on class-specific items for that class, with classlevelreq overriding levelreq for that class.
classlevelreqClass-specific clvl equip gate. If null, defaults to levelreq. Lets class-restricted suffixes have lower clvl requirements for the matching class — e.g. "of Magic Arrows" has levelreq=11 but class=ama, classlevelreq=1 so an Amazon can equip it from clvl 1 while a non-Amazon (when accessible) needs clvl 11.

The 213 class-restricted suffixes are distributed across 7 classes — note that ass is missing from this list (assassin-specific suffixes for her claws live elsewhere, not via the class column):

ClassRowsExamples
nec54Necromancer charged-skill suffixes (of Bone Spirit, of Iron Maiden, etc.)
sor51Sorceress charged-skill suffixes (of Frost Nova, of Fire Bolt, etc.)
ama42Amazon charged-skill suffixes (of Magic Arrows, of Power Strike, of Charged Strike, etc.)
bar26Barbarian charged-skill suffixes
dru18Druid charged-skill suffixes
pal14Paladin charged-skill suffixes
war8Warrior (mercenary) suffixes

These are predominantly charged-skill suffixes (mod1code = charged, with mod1param identifying the class skill and mod1min/mod1max controlling the charge count) — the "of [Class Skill]" suffixes that grant a finite number of skill charges. The same class column is also used by staffmod-style "+to skill" suffixes that grant flat skill bonuses on caster items. See d2r-docs/STAFFMODS.md for the deeper editorial.

Pool weighting

ColumnMeaning
frequencyRelative weight in the affix pool. The selection formula is affix_weight / Σ(all-eligible-affix-weights), but the per-affix weight differs based on whether the item has a magic lvl set (see Magic-level frequency multiplier below). 0 or blank = this specific row isn't picked from the magic-affix pool (but the same Name may still roll via its other rows).

Group exclusion

ColumnMeaning
groupNumeric group ID. Affixes sharing a group cannot co-exist on the same item — the engine picks one row per group based on level eligibility weighted by frequency. Group numbers are scoped per-table — group 1 in magicsuffix is unrelated to group 1 in magicprefix. If null, the group defaults to 0.

Mod block (×3)

ColumnMeaning
mod1codemod3maxUp to 3 stats per affix, each as Code / Param / Min / Max. Code is a property name from Properties.txt (which composes one or more itemstatcost stats with display logic). Param is stat-specific (the skill ID for charged mods). Min/Max is the roll range — equal for fixed values, otherwise the affix rolls within.

Item-type filter

ColumnMeaning
itype1itype7Allowed item types (itemtypes codes). Filled left-to-right; trailing slots blank. The walk goes upward through the itype hierarchy — armo matches every armor subtype.
etype1etype5Excluded item types — carve exceptions out of an itype* allowance.

Cosmetic / value

ColumnMeaning
transformcolorColor change applied to the item when this affix rolls. Empty = no change. References the Code column in Colors.txt.
multiplyMultiplicative buy/sell cost modifier. Calculated in 1024ths for buy cost and 4096ths for sell cost.
addFlat integer modifier added to the item's buy and sell costs.

Group exclusion — the tier-ladder mechanism

group is what makes affix tiers feel like tiers. The canonical example is group 1 — the damage-reduction family (red-dmg mod) on torsos, shields, rings, amulets, and circlets:

Nameqlvlclvl reqred-dmgfrequency
of Health7514
of Protection18 / 2413 / 1824
of Absorption26 / 3219 / 2434
of Life35 / 4126 / 334 (or 4–7)4
of Life Everlasting453710–254
of Anima51438–154

When the engine rolls a suffix on a qlvl-30 amulet:

  1. Filters group 1 to rows where level ≤ 30 ≤ maxlevel and itype matches amul (Health, Protection, Absorption all eligible)
  2. Computes each row's effective weight using the formula in Magic-level frequency multiplier below — for amulets (no magic lvl) this is just frequency; for circlets/orbs/staves/wands it's frequency × this-affix's-level
  3. Picks one weighted by the resulting weights
  4. Rolls the value within the chosen row's Min/Max (most red-dmg rows are fixed; the upper-tier ones range)

Group 1 spans multiple itype combinations — torsos and shields get one set of rows, jewelry gets another, with different qlvl thresholds for the same Name (e.g. of Protection opens at qlvl 18 on rings/amulets but qlvl 24 on torsos/shields). Suffix tier ladders aren't strictly monotonic in mod value either: of Life Everlasting has higher max than of Anima despite lower qlvl, because tier ordering is by qlvl, not raw stat.

A magic item only gets one suffix total, so all groups compete for that single slot via their combined frequencies — group 1 is one of ~42 suffix groups vying for it.

Magic-level frequency multiplier

When the item being rolled has a non-zero magic lvl (set in weapons, armor, or misc.txt), the engine flips into a fundamentally different pool-weighting mode that dramatically shifts the pool toward high-level affixes. Disassembly of the v1.13c game binary confirms two paths:

if (item.magic_lvl > 0) {
  effective_weight = affix.frequency × affix.level
} else {
  effective_weight = affix.frequency
}

The presence of any non-zero magic lvl triggers the multiplication — its actual value (1 for orbs/staves/wands, 3/8/13/18 for the four circlet tiers) doesn't multiply directly. The triggered mode multiplies each eligible affix's frequency by that affix's own level field before summing the pool denominator.

This is what makes circlets/coronets/tiaras/diadems and caster-class weapons so coveted for high-tier rolls. A Diadem (magic_lvl 18) doesn't roll high-tier suffixes "more often" because of an 18× multiplier on each one; it rolls them more often because the entire pool gets re-weighted by per-affix level, and high-level suffixes (e.g. of the Magus at level=29, of Speed at level=37, of the Lamprey at level=77) sit far above the level=1–10 filler that otherwise dominates the pool by raw count.

Items with magic lvl > 0

Only 42 items in the entire game carry a non-zero magic lvl:

typeItemsmagic lvlNotes
orb (Sorc)All 15 — Eagle Orb → Dimensional Shard1Every tier (Normal / Exceptional / Elite).
staf (Caster)All 15 — Short Staff → Archon Staff1Every tier.
wand (Necro)8 — Wand → Grave Wand1Normal + Exceptional only. Elite wands (Polished / Ghost / Lich / Unearthed) have blank magic lvl despite higher clvl requirements — likely an oversight in the original data, ships that way in D2R.
circ (Sorc)All 4 — Circlet / Coronet / Tiara / Diadem3 / 8 / 13 / 18The only armor type with magic lvl. The only family where the value scales per tier.

The frequency-multiplier trigger is binary — any non-zero magic lvl flips the engine into level-weighted mode at the same intensity. The per-tier scaling on circlets only matters for the additive ilvl boost below.

Worked example — of Speed vs of Pacing on a Diadem

Group 35 (FRW) on circlet-eligible itypes contains a 3-tier ladder:

AffixTierbase frequencylevelWeight on amulet (no magic_lvl)Weight on Diadem (magic_lvl > 0)
of Pacing+10% FRW312336
of Haste+20% FRW422488
of Speed+30% FRW4374148

On an amulet of equivalent qlvl, the three tiers are nearly evenly weighted (3 / 4 / 4) — top-tier of Speed appears about as often as the bottom tier. On a Diadem, of Speed's weight (148) is 4× of Pacing's (36) — top tier dominates the group.

Group 35 also gets dramatically more weight in cross-group competition. Its level=12/22/37 affixes are well above the level=1–10 filler that dominates the suffix pool by raw count. Under the multiplier, group 35 punches far above its raw-frequency weight class.

Pool-level eligibility (additive)

Separately from the frequency multiplier, magic lvl also extends the affix-eligibility ceiling. The effective alvl for affix selection is:

if (item.magic_lvl > 0) {
  alvl = MAX(ilvl, qlvl) + item.magic_lvl   // capped at 99
}

A Diadem (qlvl=85, magic_lvl=18) effectively rolls at alvl=99 regardless of where it dropped, unlocking the highest-level suffixes (e.g. of the Lamprey at level=77) even on a Diadem dropped at low ilvl. The two effects compound: items with magic_lvl get more affixes in their eligible pool AND those high-level affixes get amplified weighting within the pool.

Same affix, multiple rows

Many affixes appear in multiple rows because the engine needs different per-itype or per-tier mod ranges for the same display name:

  • of Health appears twice in group 1 — once for tors/helm/shld (frequency blank), once for tors/shld/ring (frequency 4) — same Name, different itype splits.
  • of Protection and of Absorption similarly fan out across rings, amulets, circlets, torsos, and shields with separate qlvl thresholds.

The implication: filtering by Name won't give you "the row" — there isn't one. To know what an affix can do, query all rows with that Name and scan their itype*/level constraints.

frequency=0 vs spawnable=0 vs blank

These columns mean different things and overlap imperfectly. Three failure modes for "this row won't roll on a magic item":

  • spawnable=0 — affix is engine-defined but never appears on naturally-rolled items. Used by uniques, sets, and crafted-recipe outputs.
  • spawnable=blank — legacy entry with no explicit flag. Treated as not naturally spawning.
  • frequency=0 (or blank) — this specific row isn't picked from the magic-affix pool. The same Name might still appear in other rows with non-zero frequency, so the affix as a whole can still roll.

In magicsuffix, of 779 named rows: 583 roll, 38 are spawnable=0, 158 are spawnable=blank, and a few more are spawnable=1 but frequency=0 (rows that exist for engine reference but don't compete in the magic-affix pool — usually duplicates of spawnable rows).

If you're asking "can this affix appear on a magic item I'm rolling?", check all three.

Historical accumulation across versions

The version column reveals that this file is a historical accumulation, not a current snapshot. Affixes from every era of the game live in the same file:

  • version = 0 — original Classic Diablo II (June 2000 release)
  • version = 1 — Classic patches (v1.01–v1.06)
  • version = 100 — Lord of Destruction expansion (June 2001) and everything after, including D2R additions

Old affixes are never removed. They stay in the file for save-game compatibility (legacy items on old characters still need their mod definitions resolvable), for unique-item references, and for version-context spawning (Classic-only realms draw from the version=0/1 pool; LoD/D2R can draw from all three). The Expansion row is the visual divider in the source file between Classic and LoD entries — an engine artifact, not an affix.

This accumulation is why the file is so much larger than what actually rolls in current play. The version × spawnable distribution in magicsuffix:

versionspawnable=1spawnable=0spawnable=blank
0108
1148
10032738158

The blank-spawnable cluster — 158 rows in magicsuffix, the largest single category outside spawnable=1 — lives entirely in version=100: LoD-era entries the dev team chose to define but never wire into the active pool, present for engine reference, future-proofing, or planned content that didn't ship. The version=0/version=1 rows are the original Classic suffixes; they're still spawnable on Classic realms but largely shadowed by their LoD equivalents on LoD/D2R.

Cross-references

  • automagic — separate auto-attached-prefix system for class-specific bases (Sorc orbs, Amazon weapons, etc.). Doesn't interact with the magic-affix pool — auto-mods attach in addition, not instead.
  • itemtypesitype*/etype* reference the item-type taxonomy.
  • itemstatcostmod*Code resolves through Properties.txt to stats defined here.
  • weapons / armormagic lvl from these files multiplies frequency during affix-pool weighting.
  • magicprefix — identical schema, parallel pool. A magic item rolls one prefix and one suffix.
  • PlayerClass.txt — the class column references class codes defined here.
  • Properties.txt — defines what each mod*Code resolves to.
  • Colors.txt — the transformcolor column references color codes defined here.
  • d2r-docs/STAFFMODS.md — staff-mods (the +N to specific class skills affixes that roll on caster weapons) live here in magicsuffix via the class column and are documented separately in this constellation doc.