Monsters & World

monstats

Monster definitions — stats, AI, drops, immunities, and treasure classes for every monster in the game.

monstats.txt is the primary definition table for every monster unit in D2R: enemy monsters, pets, and NPCs. Each row encodes the monster's identity, per-difficulty stats, AI behavior, resistances, skills, and treasure classes. With 752 rows × 273 columns, it's the widest table in the canonical data set.

Related: monlvl supplies the per-level scaling multipliers applied to the base stats here. superuniques overlays named unique champions on top of monstats base rows.

Column count by group:

GroupColumns
Identity and references12
Spawn control7
Grouping and escort9
Movement2
Level and rarity4
AI behavior28
Missiles8
Boolean flags26
D2R-era flags5
Skills (8 slots)25
Combat modifiers24
Per-difficulty stats (Normal)12
Per-difficulty stats (Nightmare)12
Per-difficulty stats (Hell)12
Elemental attacks (3 types × 3 diffs)42
Treasure classes (8 columns × 3 diffs)24
Quest TC and animation6

What's in a row

Identity

ColumnMeaning
IdUnique name key — the row's primary key. Used by all other tables to reference this monster (Class in superuniques, BaseId/NextInClass within monstats itself).
*hcIdxNumeric index (comment, not read by engine). Can be used as an index for tools.
BaseIdPoints to another Id to define this monster's base type. Used to group variants — skeleton1, skeleton2, skeleton3 all have BaseId=skeleton1, making them the same monster class for code-sharing purposes.
NextInClassNext monster in the class chain. The chain should be contiguous: skeleton1skeleton2skeleton3 → …
TransLvlColor transform index for the monster's palette. Controls the visual tier shift between variants (skeleton → returned → bone warrior).
NameStrString-table key for the display name. Multiple Id rows can share the same NameStr — see the Council Member example below.
MonStatsExReferences a row in MonStats2.txt for extended properties.
MonPropReferences MonProp.txt for per-difficulty bonus properties (curses, auras).
MonTypeType group (skeleton, councilmember, etc.) used by other systems to identify monster families.
AIReferences MonAi.txt for the monster's attack/movement logic.
CodeTwo-letter animation code for the monster's visual asset.

Spawn control

ColumnMeaning
enabled1 = monster can spawn. 0 = disabled (never spawns). 720 of 752 rows are enabled.
rangedtypeFlags whether the monster is a ranged attacker.
placespawn1 = can be placed by a spawn-point preset.
spawnReferences a minion type that spawns with this monster on death (e.g., skeletons that rise from corpses).

Grouping and escort

ColumnMeaning
minion1, minion2Monster Ids that can act as this monster's minions.
PartyMin, PartyMaxMinimum and maximum party size for random packs.
MinGrp, MaxGrpMin/max count within a single group.
SetBoss1 = this monster is the pack leader in its group.

Level and rarity

ColumnMeaning
LevelBase monster level (Normal difficulty).
Level(N)Monster level in Nightmare.
Level(H)Monster level in Hell. This is the index into monlvl for scaling multipliers.
RarityRelative frequency of this monster variant when spawning from its base class.

Boolean flags

Key flags relevant for queries:

ColumnMeaning
killable1 = can be killed. 0 = invincible (NPCs, Tyrael). 649 of 752 rows are killable.
demon1 = demon type. Affects Holy Bolt, Smite, Sanctuary aura mechanics. 192 demons.
lUndead1 = low undead (zombies, skeletons).
hUndead1 = high undead (vampires). Combined: 124 undead rows.
boss1 = designated boss (not just any champion). 28 boss rows.
primeevil1 = prime evil (act bosses: Andariel, Duriel, Mephisto, Diablo, Baal).
npc1 = NPC unit (Akara, Warriv, etc.).
flying1 = flying monster (bats, mosquitos, valkyrie).
neverCount1 = does not count toward the player's kill total or density triggers.
CannotDesecrate1 = cannot be a target in a Terror Zone (D2R-era column).
CannotHerald1 = cannot trigger a Herald spawn (D2R-era column).

Per-difficulty stats

The same stat block repeats three times — once for each difficulty. Normal uses no suffix; Nightmare appends (N); Hell appends (H):

ColumnMeaning
minHP(H), maxHP(H)Base HP range before monlvl scaling. Actual HP = roll(minHP, maxHP) × L-HP(H) / 100.
AC(H)Base defense before monlvl scaling.
Exp(H)Base XP before monlvl scaling.
A1MinD(H), A1MaxD(H), A1TH(H)Primary attack: min damage, max damage, attack rating.
A2MinD(H), A2MaxD(H), A2TH(H)Secondary attack.
S1MinD(H), S1MaxD(H), S1TH(H)Special attack.

Resistances

Six resistance columns per difficulty (18 total):

ColumnsMeaning
ResDm(H)Physical damage reduction %
ResMa(H)Magic resistance %
ResFi(H)Fire resistance %
ResLi(H)Lightning resistance %
ResCo(H)Cold resistance %
ResPo(H)Poison resistance %

Values ≥ 100 = immune. Negative values = extra vulnerability (Andariel has ResFi(H)=-50 — fire spells deal 50% bonus damage).

116 of 649 killable Hell monsters have ResFi(H) ≥ 100 (fire immune). This is why dual-element builds are standard for Hell progression.

Treasure classes

Eight TC variants per difficulty (24 total). For Hell:

ColumnMeaning
TreasureClass(H)Standard kill drop.
TreasureClassChamp(H)Drop when this monster is a champion.
TreasureClassUnique(H)Drop when this monster is a unique (rare boss).
TreasureClassQuest(H)Drop from a quest-scripted kill.
TreasureClassDesecrated(H)Drop when the area is a Terror Zone.
TreasureClassDesecratedChamp(H)Champion drop in a Terror Zone.
TreasureClassDesecratedUnique(H)Unique drop in a Terror Zone.
TreasureClassHerald(H)Herald event drop.

The Desecrated/Herald columns are D2R-era additions for Terror Zone and Herald mechanics.

Worked example — Fallen (basic mob)

The Fallen family illustrates the per-difficulty level progression. The BaseId=fallen1 chain spans multiple variants (fallen1 through fallen5), each used in progressively higher-level areas.

SELECT Id, NameStr, "Level(H)", "MinHP(H)", "MaxHP(H)", "Exp(H)",
       "ResFi(H)", "ResCo(H)", "ResMa(H)",
       demon, killable, "TreasureClass(H)"
FROM monstats
WHERE Id = 'fallen1';
ColumnValueNotes
Idfallen1Lowest-tier Fallen variant
NameStrFallenDisplay name key
Level(H)67Used to look up monlvl multipliers
MinHP(H)25, MaxHP(H)=55Base HP range — scaled by L-HP(H)=4049 (mlvl 67)
Exp(H)65Base XP — scaled by L-XP(H) at mlvl 67
ResFi(H)100Fire immune — spawns only in Act 1 Hell but carries fire immunity from day one
ResCo(H)40Cold resistant (not immune)
demon1Demon type
killable1Can be killed normally
TreasureClass(H)Act 1 H2H AStandard Hell drop table

Worked example — Council Members (multiple variants, one name)

The three Council Member variants in Travincal show how Id is the true key while NameStr can be shared:

SELECT Id, "Level(H)", "MinHP(H)", "MaxHP(H)", "ResFi(H)", "ResLi(H)", "ResCo(H)",
       demon, MonType, "TreasureClass(H)", "TreasureClassDesecrated(H)"
FROM monstats
WHERE Id IN ('councilmember1','councilmember2','councilmember3');
IdLevel(H)MinHP(H)MaxHP(H)ResFi(H)ResLi(H)ResCo(H)Desecrated TC
councilmember188200350120 (immune)3333Council (H) Desecrated A
councilmember28820035033100 (immune)33Council (H) Desecrated A
councilmember38820035033100 (immune)33Council (H) Desecrated A

All three share NameStr="Council Member" and MonType="councilmember", but councilmember1 is fire-immune while councilmember2/councilmember3 are lightning-immune. The superuniques table assigns two named Council members to each base type — Ismail Vilehand and Toorc Icefist spawn as councilmember1; Bremm Sparkfist and Maffer Dragonhand spawn as councilmember3. Querying NameStr alone would miss this resistance split; always filter on Id.

The TreasureClassDesecrated(H) column confirms these monsters have an elevated drop table when Travincal is the active Terror Zone.

Common queries

-- All Hell fire-immune killable monsters
SELECT Id, NameStr, "Level(H)", "ResFi(H)", "ResMa(H)", demon, lUndead, hUndead
FROM monstats
WHERE CAST("ResFi(H)" AS INTEGER) >= 100 AND killable = '1'
ORDER BY CAST("Level(H)" AS INTEGER) DESC;
-- 116 rows

-- Act boss lineup (prime evils only)
SELECT Id, NameStr, "Level(H)", "MinHP(H)", "MaxHP(H)",
       "ResFi(H)", "ResLi(H)", "ResCo(H)", "ResMa(H)"
FROM monstats WHERE primeevil = '1'
ORDER BY CAST("Level(H)" AS INTEGER);

-- Demons with all resistances under 100 in Hell (dual-element viable)
SELECT Id, NameStr, "Level(H)",
       "ResFi(H)", "ResLi(H)", "ResCo(H)", "ResPo(H)"
FROM monstats
WHERE demon = '1' AND killable = '1'
  AND CAST("ResFi(H)" AS INTEGER) < 100
  AND CAST("ResLi(H)" AS INTEGER) < 100
ORDER BY CAST("Level(H)" AS INTEGER) DESC
LIMIT 20;