Every advanced stat of a Project Diablo 2 character, worked out from its gear, skills and auras with the rules read out of the game's own code.
.json file, or select all and copy the text.The Armory doesn't allow other sites to read it directly, so the file makes a short trip through your browser. Nothing is uploaded anywhere.
Switch on the skills you keep running (one aura of your own at a time). Everything else listed below is always on: auras and "when equipped" skills from your gear, and your mercenary's auras while it's with you. Open an aura to see exactly what it gives you.
The same lines PD2's Advanced Stats window shows, in the same order, with the window's own math. Where that math is wrong, the number the game actually uses follows in green as game: …. Hover or tap a value to see where it comes from.
Normal attack against a monster of the given level and defense. The game clamps it to 5–95%.
| Target | Level | Defense | Hit chance |
|---|
Your normal attack against one monster, using the game's damage roll, critical and deadly strike, the monster's resistances and your pierce. Change the target here; the numbers below and the skill table use it.
Leave a box empty to use the game's value for this monster. Map modifiers that change monster resistances or level aren't applied automatically; enter them here.
How much each option raises your damage from where you are now. Both multiply the hit, but they don't grow the same way: skill damage adds to a total that's already above 100%, while every point of −resist below 0 only counts half, and pierce does nothing against an immune monster.
These lower the target's resistances everywhere on this tab. Against an immune monster (base resist 100 or more) PD2 halves them, and once the total drops below 100 your −resist gear works again.
| Added | + skill damage | − enemy resist | Better choice |
|---|
Open an element to see every item, charm, skill and aura that adds to it, and what raises its maximum.
The raw damage of each type it takes to kill you from full life, after your resistances, damage reduction and absorb, in the difficulty chosen above.
| Damage type | Your resist | Reduced / absorbed | Raw damage to kill you | × your life |
|---|
Typical Hell melee monsters at an area level, using the game's monster scaling and hit roll: how often they hit your defense, how often that gets past your block, and what one hit does after damage reduction.
| Monster | Type | Level | Attack rating | Hits you | After block | Damage per hit | Hits to kill you |
|---|
The same switches as on the Overview. Their bonuses flow into every number on the page.
What each skill's damage box and tooltip show at your level, with your synergies, masteries and gear. "Total" adds your weapon where the skill uses it; "vs target" applies the monster chosen under Offense (its resistance and your pierce).
| Skill | Level | Type | Skill damage | Total | Average vs target | Notes |
|---|
| Summon | How many | Level | Life | Damage | Attack rating | Defense | Resists (F/C/L/P) |
|---|
| Skill | How | Level | Detail |
|---|
| ID | Stat | Total | Where it comes from |
|---|
The Armory export doesn't include the mercenary's level, so set it here.
| ID | Stat | Total | Where it comes from |
|---|
Every rule on this page was read out of Project Diablo 2's own program files: D2Common, D2Game and D2Client (Diablo II 1.13c), ProjectDiablo.dll (PD2's changes on top) and BH.dll (PD2's Advanced Stats window). Where a rule is marked VERIFIED, the game's own machine code was run on random inputs and matched this page's formula every time. READ means the rule was read from the code but not run.
api.projectdiablo2.com/game/character/NAME) lists each item's final modifiers, with socketed runes and jewels already folded into the parent item. Set items carry no set-bonus list there, so partial and full set bonuses are rebuilt from SetItems.txt and Sets.txt by how many pieces are worn..d2s reader follows PD2's own item reader (ProjectDiablo.dll 0x102D8C40, which replaces the stock one). Items saved before version 0x67 use 9-bit stat ids, newer items 10-bit ids. Set bonus lists stored on the item are used as they are.A stat's total is the sum of every stat list on the character (D2Common 0x6FD88CD0) plus its "op" links from ItemStatCost (0x6FD89530), applied recursively:
// item level: op 13 = % of the item's own base value (enhanced damage/defense), op 4/5 = per character level // character level (D2Common 0x6FD89530): op 1/11: v += v0 × T(source) / 100 // e.g. +% life op 2: v += (T(source) × base(level)) >> param op 8: mana += ManaPerMagic × (energy − base energy) << 6 op 9: life += LifePerVitality × (vitality − base vitality) << 6, stamina the same with StaminaPerVitality
An item's own enhanced damage or defense stays inside that item when the item has damage or defense to apply it to (D2Common 0x6FD89E5F). Enhanced damage on items with no damage of their own (a ring, body armor, a shield) reaches the character and multiplies the weapon.
+Skills (D2Common 0x6FD9FCB0): all skills, class skills, tab skills, single skills and elemental skills only raise skills that have at least one hard point; "+X to a skill (any class)" (oskills) always count.
Passive skills (D2Common #10056, 0x6FDA2480) apply their passive stats whenever the skill has a passive state, whatever weapon is held. Masteries are matched to the weapon later, where the attack code asks for them.
PD2's Advanced Stats window is drawn by BH.dll (0x1007C040). Each line reads the character's stat totals; this page repeats the same arithmetic. Checked line by line against a real character's window, all lines matched.
resistance penalty = {0, −20, −50}[difficulty] × 2
max resist = min(maximum-resist bonus + 75, 90)
cold length = cannot be frozen ? 0 : (2 − min(half freeze, 2)) × 50
poison length = 100 − poison length reduction − penalty
curse length = max(100 − curse resistance %, 25)
base AR = ToHitFactor + 5 × (dexterity − 7) + gear AR
base defense = dexterity ÷ 4 + gear defense
crushing blow = Two-Handed Mastery (if weapon matches) + items; efficiency 100 + mastery + items
open wounds /s = deep wounds + ((level table + 25) × 25) >> 8 // D2Game 0x6FCCC940
deadly strike = min(chance, min(75 + max-DS bonus, 100)); multiplier 150 + bonus
critical strike = min(masteries + skills + items, 75); multiplier 200 + bonus
added damage = value + value × elemental mastery / 100
poison shown = damage per frame ÷ 256 × length
The FCR and FHR lists in the window are fixed tables inside BH; the IAS list is worked out live from the skill's animation. This page computes all three from the animation data (see Frames), and they agree with BH's.
These are the numbers on the character screen (D2Client), checked by running the screen's own functions on 30,000 random characters.
base AR = gear AR + 5 × dex − 35 + ToHitFactor // D2Common #10621 AR = base + base × (AR% + mastery AR% + skill to-hit) / 100 // D2Client 0x6FADC4F0 defense = (gear defense + dex ÷ 4) × (100 + defense% + skill defense%) / 100 // D2Common #10672 damage % = damage% + mastery% + str × StrBonus/100 + dex × DexBonus/100 (at least −90) min dmg = (100 + off-weapon ED + damage %) × weapon min / 100 + weapon's flat damage + fire/cold/lightning/magic (with masteries) + poison // D2Client 0x6FAE1220, 0x6FAE0E30 hit chance = 222 × AR/(AR+def) × alvl/(alvl+dlvl), at least 5; above 95 the excess counts at 90/111, capped at 100 // PD2 0x10271470 (replaces D2Game 0x6FCFDE90)
PD2 replaces the mastery lookup (ProjectDiablo.dll 0x102728B0): melee masteries use stats 342–344, throwing masteries 345–347, counted only when the mastery's item type matches the weapon.
block = (shield and gear block + CharStats BlockFactor) × (dex − 15) ÷ (2 × level), at most 75 // D2Common #10212
Only with a shield. Stock Diablo II divides block by 3 while you run; PD2's block roll (ProjectDiablo.dll 0x1026FB60) removes that. Weapon block (stat 348, e.g. Weapon Block) is tried only when shield block is below 1%, is capped at 75%, needs two claws or a two-handed sword, and is halved in PvP maps READ.
life per frame = replenish life (1/256 life), 25 frames a second // D2Game 0x6FC97CB0 mana per frame = max(1, max mana ÷ (ManaRegen × 25)) × (100 + regenerate mana %) / 100 // 0x6FC97950 stamina, standing = max stamina >> 8 per frame, walking >> 9, × (100 + heal stamina %)
PD2 sets ManaRegen to 120 for every class, so a full mana bar refills in 120 seconds with no bonus.
effective X = 120 × X / (120 + X) // IAS, FCR, FHR, FBR (D2Common 0x6FD823E0) cast speed = min(100 + effective FCR, 175) hit recovery speed = 50 + effective FHR block speed = 50 (100 with Holy Shield) + effective FBR attack speed = attack rate + effective IAS, −30 for sequences, clamped 15–175 rate = animation speed × speed / 100 frames = ceil((animation length − start frame) × 256 / rate) − 1 // D2Common 0x6FD83110
The animation is picked by class, weapon class and form (AnimData). Chain Lightning and Frozen Orb play a 19-frame sequence at cast speed. Two skills change attack rate while they play: Dragon Tail (−20, both server and client) and Double Swing (+50 on the client, which paces held attacks) READ. Werewolf and werebear attacks are rebuilt from the weapon's speed and its own IAS (D2Common 0x6FD83C20). The full attack model, including follow-up swings, is the one in the Attack Speed calculator.
lvl is the level including +skills; blvl is your hard points in that exact skill, so an item-granted copy (Call to Arms, Hustle) has blvl 0.effective MF = MF ≤ 10 ? MF : MF × f / (MF + f), with f = 250 unique, 500 set, 600 rare; magic uses MF as is // D2Game 0x6FC2E130 gold = gold × (100 + GF) / 100 // D2Game 0x6FC2F260 experience = exp + exp × bonus / 100, after the level-difference penalty // D2Game 0x6FCFC030
speed % = max(25, velocity% + 150 × FRW / (150 + FRW)), velocity% = 100 (+50 running) + skills
velocity = WalkVelocity × 256 × speed% / 100 // D2Common 0x6FD83110
physical = (weapon damage + flat damage) × (100 + ED + damage% + str/dex bonus + mastery)/100 // D2Game 0x6FCFC530 crit / deadly strike: crit rolls first (cap 75), deadly strike only if the crit misses; one of them, ×(200+crit mult)% or ×(150+DS mult)% // PD2 0x10270E00 resist used = monster resist − pierce (pierce ignored while resist ≥ 100); below 0 it counts half; floor −100 // PD2 0x1026F410 damage × (100 − resist)/100, after the monster's flat damage reduction crushing blow = current life ÷ 8 (players and mercenaries ÷ 10, prime evils less) × (1 + efficiency%), less physical resist // PD2 0x102AF610 open wounds bleed per frame = level table + 25 + 5 × deep wounds, for 125 frames // PD2 0x102AF060 leech = physical damage dealt × steal% ÷ (1/2/3 by difficulty) × monster Drain% // PD2 0x102700F0
Auras and curses that lower resist (Conviction, Lower Resist) are halved on immune monsters in PD2 (stock Diablo II divides them by 5), which can bring the monster below 100 so pierce works again.
Both multiply the same hit: (100 + damage%) × (100 − resist). One more point of damage% adds 1 ÷ (100 + damage%), which shrinks as you stack it. One more point of −resist adds 1 ÷ (100 − resist) while the monster's resist is still 0 or more, only half of that once it is below 0, nothing at −100, and nothing at all against an immune monster.
per damage type: flat DR (physical) or magic DR (elemental) → resist or %DR (cap 50) → absorb % (cap 40) → absorb flat
resist = min(gear + difficulty penalty (0/−40/−100), min(75 + max resist, 90)) // D2Game 0x6FCFC0B0, PD2 0x1026F680
raw damage to kill you = flat + (life + absorb flat) ÷ ((1 − resist)(1 − absorb%))
MonStats values scaled by MonLvl for the difficulty and the monster's level (D2Common 0x6FDA4A00, VERIFIED). In Nightmare and Hell the level is the area's level; PD2 adds a map's area-level bonus and sets a rotating set of Hell zones to 85 (PD2 0x10268D00). Champions are 2 levels higher with +66% damage and +49% attack rating in Hell; uniques 3 levels higher. The monster's hit chance uses the same formula as yours, against your defense plus defense vs melee.
Elemental skill damage is (EMin + level tiers) << HitShift, plus synergy % (hard points only), then elemental mastery % of that total (D2Common 0x6FDA0360 / 0x6FDA0460; PD2 adds magic mastery). The damage box each skill shows is chosen by SkillDesc descdam (D2Client 0x6FADFD30). Checked against the game's own code on 58,000 cases and its compiled calc files on 24,000.
A summon's level is min(character level, 3 × level/4 + skill level) for most summons (D2Game 0x6FC6E2A0), and its stats are MonStats × MonLvl plus the skill's own bonuses (D2Game 0x6FC6F970). A mercenary's stats come from the Hireling.txt row for its type and level: strength and dexterity grow by the per-level value ÷ 8, resists by ÷ 4 (D2Game 0x6FC68BA0).