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.txt → itemstatcost 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
| Column | Meaning |
|---|---|
Name | Display name (the suffix phrase: of Health, of the Bear). Doesn't need to be uniquely named. |
version | Game-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
| Column | Meaning |
|---|---|
spawnable | Three 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. |
rare | 1 = also eligible on rare items. 0 = magic-only. |
level | qlvl at which this row becomes eligible. Higher-tier rows have higher level. |
maxlevel | Optional upper qlvl. Once item qlvl exceeds this, the row drops out of eligibility (lets newer tiers replace older ones). |
levelreq | Player clvl needed to equip the item once the affix has rolled. Independent of level. |
Class restriction
| Column | Meaning |
|---|---|
classspecific | Companion column for class restriction — always blank in magicsuffix (the suffix file uses class and classlevelreq exclusively). magicprefix uses classspecific instead. |
class | Class 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. |
classlevelreq | Class-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):
| Class | Rows | Examples |
|---|---|---|
nec | 54 | Necromancer charged-skill suffixes (of Bone Spirit, of Iron Maiden, etc.) |
sor | 51 | Sorceress charged-skill suffixes (of Frost Nova, of Fire Bolt, etc.) |
ama | 42 | Amazon charged-skill suffixes (of Magic Arrows, of Power Strike, of Charged Strike, etc.) |
bar | 26 | Barbarian charged-skill suffixes |
dru | 18 | Druid charged-skill suffixes |
pal | 14 | Paladin charged-skill suffixes |
war | 8 | Warrior (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
| Column | Meaning |
|---|---|
frequency | Relative 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
| Column | Meaning |
|---|---|
group | Numeric 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)
| Column | Meaning |
|---|---|
mod1code … mod3max | Up 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
| Column | Meaning |
|---|---|
itype1 … itype7 | Allowed item types (itemtypes codes). Filled left-to-right; trailing slots blank. The walk goes upward through the itype hierarchy — armo matches every armor subtype. |
etype1 … etype5 | Excluded item types — carve exceptions out of an itype* allowance. |
Cosmetic / value
| Column | Meaning |
|---|---|
transformcolor | Color change applied to the item when this affix rolls. Empty = no change. References the Code column in Colors.txt. |
multiply | Multiplicative buy/sell cost modifier. Calculated in 1024ths for buy cost and 4096ths for sell cost. |
add | Flat 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:
| Name | qlvl | clvl req | red-dmg | frequency |
|---|---|---|---|---|
| of Health | 7 | 5 | 1 | 4 |
| of Protection | 18 / 24 | 13 / 18 | 2 | 4 |
| of Absorption | 26 / 32 | 19 / 24 | 3 | 4 |
| of Life | 35 / 41 | 26 / 33 | 4 (or 4–7) | 4 |
| of Life Everlasting | 45 | 37 | 10–25 | 4 |
| of Anima | 51 | 43 | 8–15 | 4 |
When the engine rolls a suffix on a qlvl-30 amulet:
- Filters group 1 to rows where
level ≤ 30 ≤ maxleveland itype matchesamul(Health, Protection, Absorption all eligible) - Computes each row's effective weight using the formula in Magic-level frequency multiplier below — for amulets (no
magic lvl) this is justfrequency; for circlets/orbs/staves/wands it'sfrequency × this-affix's-level - Picks one weighted by the resulting weights
- 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:
type | Items | magic lvl | Notes |
|---|---|---|---|
orb (Sorc) | All 15 — Eagle Orb → Dimensional Shard | 1 | Every tier (Normal / Exceptional / Elite). |
staf (Caster) | All 15 — Short Staff → Archon Staff | 1 | Every tier. |
wand (Necro) | 8 — Wand → Grave Wand | 1 | Normal + 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 / Diadem | 3 / 8 / 13 / 18 | The 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:
| Affix | Tier | base frequency | level | Weight on amulet (no magic_lvl) | Weight on Diadem (magic_lvl > 0) |
|---|---|---|---|---|---|
| of Pacing | +10% FRW | 3 | 12 | 3 | 36 |
| of Haste | +20% FRW | 4 | 22 | 4 | 88 |
| of Speed | +30% FRW | 4 | 37 | 4 | 148 |
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 Healthappears twice in group 1 — once fortors/helm/shld(frequency blank), once fortors/shld/ring(frequency 4) — same Name, different itype splits.of Protectionandof Absorptionsimilarly 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:
version | spawnable=1 | spawnable=0 | spawnable=blank |
|---|---|---|---|
0 | 108 | — | — |
1 | 148 | — | — |
100 | 327 | 38 | 158 |
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.itemtypes—itype*/etype*reference the item-type taxonomy.itemstatcost—mod*Coderesolves throughProperties.txtto stats defined here.weapons/armor—magic lvlfrom these files multipliesfrequencyduring affix-pool weighting.magicprefix— identical schema, parallel pool. A magic item rolls one prefix and one suffix.PlayerClass.txt— theclasscolumn references class codes defined here.Properties.txt— defines what eachmod*Coderesolves to.Colors.txt— thetransformcolorcolumn 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 inmagicsuffixvia theclasscolumn and are documented separately in this constellation doc.