Items

magicprefix

Magic and rare prefix affix pool.

magicprefix.txt defines every prefix that can roll on a magic, rare, or crafted item — the Sharp or Glimmering half of an affix pair. Identical 39-column schema to magicsuffix (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.

722 rows total: 689 named affixes plus 32 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 689 named rows: 603 roll naturally (spawnable=1), 66 are explicitly disabled (spawnable=0), and 20 have a blank spawnable column (also effectively non-spawning — see Historical accumulation). 573 of the spawnable rows are also rare-eligible. 132 rows are class-restricted via classspecific, spread across all 8 classes (16–18 entries each). 37 distinct exclusion groups partition the pool.

What's in a row

The 39 columns split into seven groups.

Identity

ColumnMeaning
NameDisplay name (the prefix word: Sturdy, Glorious, Sharp). 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
classspecificClass code from PlayerClass.txt (ama, ass, bar, dru, nec, pal, sor, war). When set, the affix is class-scoped — only used on class-specific items for that class. Magicprefix uses this column for class restriction; magicsuffix uses class instead.
classCompanion to classlevelreq for class-specific equip gating. Always blank in magicprefix (the prefix file uses classspecific exclusively for class restriction).
classlevelreqClass-specific clvl equip gate. Always blank in magicprefix. If null, defaults to levelreq.

The 132 class-restricted prefixes are distributed across all 8 classes:

ClassRowsExamples
pal18Paladin-shield prefixes
bar18Barbarian-helm prefixes
dru16Druid-pelt prefixes
war16Warrior (mercenary) prefixes
ass16Assassin-claw prefixes
sor16Sorceress-orb prefixes
ama16Amazon-weapon prefixes (Fletcher's, Acrobat's, Harpoonist's, Bowyer's, Gymnast's, Spearmaiden's, Archer's, Athlete's, Lancer's, Maiden's, Valkyrie's, etc.)
nec16Necromancer-head prefixes

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 magicprefix is unrelated to group 1 in magicsuffix. 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. 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 101 — the armor-defense family — which contains the familiar ac% ladder on body armor (alongside flat-ac rows on charms/jewels and ac/lvl per-level rows). The ac% subset on armo only:

Nameqlvlclvl reqac%frequency
Sturdy1 / 41 / 310–20 / 21–309
Strong9631–408
Glorious191441–508
Blessed251851–657
Saintly312366–807
Holy362781–1006
Godly45 / 5038 / 43101–2003 / 1

When the engine rolls a prefix on a qlvl-30 piece of body armor:

  1. Filters group 101 to rows where level ≤ 30 ≤ maxlevel (Sturdy, Strong, Glorious, Blessed, Saintly all eligible)
  2. Computes each row's effective weight using the formula in Magic-level frequency multiplier below — for body armor (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

Group 101 also contains parallel rows for charms (Stout/Burly/Stalwart with flat ac) and per-level scaling (Miocene/Oligocene/Eocene/Paleocene with ac/lvl) — same group, different itypes. They don't compete with the armor ac% rows because the itype filter rules them out on body armor.

A magic item only gets one prefix total, so all groups compete for that single slot via their combined frequencies — group 101 is one of ~37 prefix 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 Berserker's "more often" because of an 18× multiplier on Berserker's; it rolls Berserker's more often because the entire pool gets re-weighted by per-affix level, and Berserker's level=90 puts it near the top of that re-weighting. Filler affixes at level=1–10 are essentially unchanged; mid-tier affixes get moderate boosts; high-tier affixes (level 60+) become competitive in groups they'd otherwise lose.

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 — Berserker's vs Slayer's on a Diadem

Group 125 (class skills) contains a +1 tier and a +2 tier per class. Within the Barbarian sub-pool:

AffixTierbase frequencylevelWeight on body armor (no magic_lvl)Weight on Diadem (magic_lvl > 0)
Slayer's+1 Barb skills4364144
Berserker's+2 Barb skills2902180

On a regular helm of equivalent qlvl, Slayer's is 2× more common than Berserker's (4 vs 2). On a Diadem, Berserker's is 1.25× more common than Slayer's (180 vs 144) — the within-group +1/+2 ratio fully flips.

Group 125 also gets dramatically more weight in cross-group competition. Its constituent affixes have level=36 and level=90 — both well above the level=1–10 filler that dominates the prefix pool by raw count. Under the multiplier, group 125 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 affixes (e.g. Berserker's at level=90) 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:

  • Sturdy appears twice for armo (qlvl 1 with ac% 10–20, qlvl 4 with ac% 21–30) — same Name, separate tier entries.
  • Stout appears five times: lcha / scha / mcha / jewl (different itypes) and at different qlvl thresholds within charms.

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 magicprefix, of 689 named rows: 603 roll, 66 are spawnable=0, 20 are spawnable=blank, and an additional handful 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 magicprefix:

versionspawnable=1spawnable=0spawnable=blank
086
11002
1004176420

The blank-spawnable cluster lives almost entirely in version=100: those are 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 affixes; 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.
  • magicsuffix — identical schema, parallel pool. A magic item rolls one prefix and one suffix.
  • PlayerClass.txt — the classspecific 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.