Damage & Healing
Field positions for SPELL_DAMAGE, SWING_DAMAGE, ENVIRONMENTAL_DAMAGE, SPELL_HEAL, and SPELL_ABSORBED. The actual damage and healing formulas. The cheat-death exclusion list.
This page documents how damage and healing get encoded, and the formulas that produce numbers matching the de-facto community standard. All field positions assume advanced combat logging is enabled.
SPELL_DAMAGE Suffix
SPELL_DAMAGE, SPELL_PERIODIC_DAMAGE, RANGE_DAMAGE (and their _SUPPORT variants) all use this suffix at fields 31+. Total field count: 42. The advanced block (12–30) describes the target for these events.
| Field | Name | Description |
|---|---|---|
| 31 | baseAmount | Effective damage post-mitigation. The number you want. |
| 32 | rawAmount | Pre-mitigation. Diagnostics only — do not sum this. |
| 33 | overkill | Damage past 0 HP. -1 if not a killing blow. |
| 34 | school | School bitfield (duplicates spell school for compatibility) |
| 35 | resisted | Resisted amount (partial resists) |
| 36 | blocked | Blocked amount |
| 37 | absorbed | Informational. Use the SPELL_ABSORBED event, not this field. |
| 38 | critical | 1 on crit, nil otherwise |
| 39 | glancing | Legacy, basically always nil now |
| 40 | crushing | Legacy, basically always nil now |
| 41 | abilityHint | String tag — ST (single-target) or AOE. Useful for filtering ST vs cleave performance. |
SWING_DAMAGE Suffix
No spell prefix, so offsets shift -3. Total field count: 38 (or 39 if off-hand). The advanced block (9–27) describes the source for SWING_DAMAGE and the target for SWING_DAMAGE_LANDED — they're the same swing logged twice.
| Field | Name | Description |
|---|---|---|
| 28 | baseAmount | Effective damage post-mitigation |
| 29 | rawAmount | Pre-mitigation, diagnostics only |
| 30 | overkill | -1 if not killing |
| 31 | school | Always 0x1 (physical) for swings |
| 32 | resisted | |
| 33 | blocked | |
| 34 | absorbed | Informational; use SPELL_ABSORBED to count |
| 35 | critical | 1 on crit, nil otherwise |
| 36 | glancing | Legacy, always nil |
| 37 | crushing | Legacy, always nil |
| 38 (optional) | isOffHand | 1 for off-hand swings; field is omitted entirely for main-hand swings |
Critical:
SWING_DAMAGE_LANDEDis not a separate hit. It's the same auto-attack reported again with the target's advanced block instead of the source's. Counting bothSWING_DAMAGEandSWING_DAMAGE_LANDEDdoubles every melee swing.
ENVIRONMENTAL_DAMAGE Suffix
The advanced block comes first in this event, then the environmental type, then the damage suffix. The source GUID is always 0000000000000000 (no actor — the world did it):
| Field | Name | Description |
|---|---|---|
| 1–4 | source | Always 0000000000000000, name nil, generic flags |
| 5–8 | target | The player taking damage |
| 9–27 | Advanced logging | The 19-field block (describes target — the player who got hurt) |
| 28 | environmentalType | Falling, Lava, Fire, Slime, Drowning, Fatigue |
| 29 | baseAmount | Effective damage |
| 30 | rawAmount | Pre-mitigation |
| 31 | overkill | 0 or positive if killing, -1 otherwise |
| 32 | school | |
| 33 | resisted | |
| 34 | blocked | |
| 35 | absorbed | |
| 36–38 | crit / glancing / crushing | Usually nil |
When a player dies from a knockback or platform fall, this is the event that records it. Death analysis pipelines that only look at SPELL_DAMAGE / SWING_DAMAGE will silently miss those deaths.
Empirical note: This layout was verified against real M+ and raid logs. Total field count is 39. The
environmentalTypestring lives at field 28 — after the advanced block, not before it.
SPELL_HEAL Suffix
SPELL_HEAL and SPELL_PERIODIC_HEAL:
| Field | Name | Description |
|---|---|---|
| 31 | healedToHP | Raw heal minus shield-converted portion. Don't use for totals. |
| 32 | amount | Total healing including overheal. Use this. |
| 33 | overheal | Wasted healing (already at full HP). |
| 34 | absorbedToShield | Heal converted to a shield (Atonement, Pain and Gain). Already inside amount. |
| 35 | critical | 1 on crit |
SPELL_ABSORBED — The Three-Way Event
SPELL_ABSORBED records "an attack happened, but a shield ate it." It encodes three or four entities: attacker, defender, absorber (the shield-caster, sometimes the same as the defender), and the shield spell. It comes in two formats depending on whether the absorber is the same as the defender:
Format 1: 22 fields — shield on someone else
| Range | Content |
|---|---|
| 1–4 | Attacker (GUID, name, flags, raid flags) |
| 5–8 | Defender |
| 9–11 | Damage spell info |
| 12–15 | Absorber (the shield-caster) |
| 16–18 | Absorb spell info (the shield) |
| 19 | amount — amount absorbed |
| 20 | totalAmount — full attempted damage before absorb |
| 21 | critical — 1 if the absorbed hit would have crit, nil otherwise |
Format 2: 19 fields — self-shielded
| Range | Content |
|---|---|
| 1–4 | Attacker |
| 5–8 | Defender |
| 9–12 | Absorber (= defender) |
| 13–15 | Absorb spell info |
| 16 | amount — amount absorbed |
| 17 | totalAmount — full attempted damage before absorb |
| 18 | critical — 1 if the absorbed hit would have crit, nil otherwise |
Your parser has to count the fields to figure out which format it is. There is no header to disambiguate.
The Damage Formula
effectiveDamage = max(0, baseAmount + blocked + resisted - max(0, overkill))
- Overkill IS subtracted. Effective damage delivered, not raw damage rolled. One-shot a 1M HP boss for 5M = 1M counted, not 5M.
overkill = -1means "didn't kill." Treat negative as zero before subtracting.- Don't add the
absorbedfield. It's informational; the absorbed damage already lives in a separateSPELL_ABSORBEDevent with its own amount. Adding both double-counts partial absorbs. - Add
blockedandresisted. They were dealt; the target just mitigated them.
The Healing Formula
effectiveHealing = max(0, amount - overheal)
- Don't subtract
absorbedToShield. That portion was real healing converted into a shield buff; it counts. - Some "absorbs" are not healing. Cheat-death and Stagger-style mechanics get logged as SPELL_ABSORBED but should NOT be added to healing totals:
| Spell ID | Name | Class/Spec | Why excluded |
|---|---|---|---|
| 114556 | Purgatory | Blood Death Knight | One-shot save mechanic, not healing |
| 31850 | Ardent Defender | Protection Paladin | Same — damage prevention on lethal hits |
| 31230 | Cheat Death | Subtlety Rogue | Same |
| 115069 | Stagger | Brewmaster Monk | Delayed self-damage, not a shield. The "absorbed" amount ticks back as damage. Counting it inflates Brewmaster healing by ~95% on tank logs. |
Pet Damage Attribution
Pet damage gets credited to the owner. Three signals, ranked by reliability:
| Priority | Signal | Why it can be wrong |
|---|---|---|
| 1 (best) | SPELL_SUMMON event | Authoritative — you saw the player summon the pet |
| 2 | ownerGUID in advanced logging | Reliable but absent if advanced logging is off |
| 3 (worst) | Player buff aura on the pet | Wrong for raid-wide auras |
You will see pet damage before you see the SPELL_SUMMON. Pets summoned before combat (warlock demons, hunter pets, DK ghouls) start dealing damage immediately, and ownership data arrives later. The right architecture: buffer unknown-owner pet damage and retroactively reassign when the owner is discovered. Get this wrong and warlocks parse 30% lower than they should.
Citing this page
If this reference helped, please link back so others can find it. Suggested citation:
Damage & Healing — WoW Combat Log Reference (WowCoach.gg). https://wowcoach.gg/docs/combat-log/damage-and-healing