Elements & Status Effects

Fire, cold, lightning, and poison damage, plus the DoT / freeze / stun status effects and how resistances reduce them.

On this page

Damage comes in two kinds: physical and elemental. They roll and resolve separately. Physical damage is reduced by Defense Rating, Constitution, and Reduced-Physical affixes (which share a single 50% cap — see Combat); each element is reduced only by its own matching resistance.

The four elements

The elements are Fire, Cold, Lightning, and Poison. Flat elemental damage from a weapon or skill applies on hit, on top of your physical damage:

elementalDamage = rawElementalDamage × (1 − resistance)

Flat elemental damage is speed-normalised per hit: a slow weapon applies a proportionally larger elemental rider per swing, so elemental DPS is equal across weapon speeds.

The Monk’s Siphon heals you for a share of the elemental and burn damage you deal. Like life leech it gives back the full share against a common, ¾ against a rare, ½ against a special and ⅓ against a boss (dungeon bosses, echoed ones included, and hunt marks, the Brood Matriarch included).

Resistances & the 75% cap

Fire, Cold, Lightning, and Poison resistances are each capped at 75% for your hero, and floored at −75%. Single-element resistance affixes roll on armour, amulets and rings; All Resistances rolls on amulets and shields, on the same tier row — with the Resonance tax pushing resistances toward the floor, that second source is one of the things a shield buys you over a two-handed weapon. Some skills and passives raise resistances too. Only the Region Resonance tax (below) pushes a resistance below zero, and enemies are capped higher, at 95%.

Negative resistance does not merely fail to resist — it amplifies that element, because the mitigation step is × (1 − resistance). At the −75% floor an incoming fire rider lands for 175% of its roll.

Some weapon and amulet affixes apply resistance penetration, reducing the target’s resistance by a flat amount before mitigation — this makes elemental builds much stronger against high-resistance enemies. Debuff/penetration effectiveness is itself capped at 90%.

The caps are hand-tunable constants in src/data/balance/combat.ts:

CapValueConstant (combat.ts)
Hero resistance ceiling (per element)75%FORMULA_CONFIG.maxResistance
Hero resistance floor (per element)−75%FORMULA_CONFIG.minResistance
Enemy resistance95%FORMULA_CONFIG.maxEnemyResistance
Debuff / penetration effectiveness90%MAX_DEBUFF_EFFECTIVENESS

An enemy’s resistance — direct hit and DoT alike — is clamped to [0, 0.95] inside damageAfterResistance, and penetration is clamped to [0, 0.90] before it is subtracted. Your resistance is clamped to [−0.75, 0.95] when an enemy’s elemental rider or poison DoT lands, which is what lets a taxed resistance amplify instead of stopping at zero.

The Region Resonance tax

Applied Region Resonance taxes all four elemental resistances while you fight the region’s resonance-scaled tiles: −10% per applied level (RESONANCE_RES_MALUS_PER_LEVEL = 0.10 in src/data/balance/echoes.ts), so Resonance X costs 100 points of resistance and can drive an unprepared hero to the −75% floor.

  • The malus is subtracted from your uncapped gear + skill total, and the result is clamped once. Resistance above 75% is therefore real headroom against the tax, not waste.
  • Physical damage is untouched — only the four elements.
  • It applies under the same guards as the Resonance rank scaling: unlocked overworld combat tiles of a region with applied Resonance. Dungeons and the Endless Delve are exempt.
  • The endgame boss fights set their own penalty instead, 1% per level of the fight above 100: −50% in an echoed regional dungeon, −75% against the Brood Matriarch, −100% in the echoed Dark Citadel finale (see Echo Ascension).

See Region Resonance for the ladder itself and what it pays back.

Status effects

When you carry flat elemental damage (or use the matching skill), a landed hit can apply a status effect. Fire, Cold, and Lightning roll a 10% proc chance per hit; Cold and Lightning normalise that chance by weapon speed (slow weapons roll a higher per-hit chance) so crowd-control uptime per second is equal across weapons. Poison’s damage-over-time applies on every hit. Bleed comes from the Rend main skill rather than an element.

IconEffect (source)Proc chanceDurationMagnitudeResisted by
BurnIgnite / Burn — Fire10% per hit (flat)6 s25% of the hit’s fire damage, split into 0.5 s ticksFire resistance
PoisonPoison — Poison damageAlways (every hit)6 sThe flat poison-damage value, spread evenly over the duration (0.5 s ticks)Poison resistance
BleedBleed — Rend (physical)On every Rend hit5 samount × bleed%, spread evenly over the durationUnresisted
FreezeFreeze — Coldmin(1, 0.10 × weaponInterval)2 sSlows the enemy’s attack speed by 30%— (crowd control)
StunStun — Lightningmin(1, 0.10 × weaponInterval)2 sPauses the enemy’s attack timer entirely— (crowd control)

Durations, tick rate, and the proc chance are the hand-tunable constants in src/data/balance/status-effects.ts: FIRE_DOT_DURATION_SECONDS = 6, POISON_DOT_DURATION_SECONDS = 6 (unified with fire in v0.8.12 — the flat-poison affix and the poison-skill path both use this same value), BLEED_DOT_DURATION_SECONDS = 5, LIGHTNING_STUN_DURATION_SECONDS = COLD_FREEZE_DURATION_SECONDS = 2, DOT_TICK_INTERVAL_SECONDS = 0.5, and PLAYER_ELEMENTAL_PROC_CHANCE = 0.10.

Status effects on you

Enemies carry an element too. Most regions give theirs a fixed one (Parched Grasslands lightning, Cursed Swamp poison, Scorched Foothills fire, Shattered Mountains cold); Dark Citadel and Endless Delve enemies roll a random one, and some hunt marks bring their own. Every enemy hit that lands (blocked or not) adds that element on top, through your matching resistance, and can put its status on you: Stun (lightning) stops you acting for 2 s (no swings, no skill casts), Freeze (cold) cuts your attack speed by 30% for 2 s. Their chance follows the enemy’s swing speed, like yours: 10% per hit for an enemy swinging every 2.25 s (the middle of the enemy range), less for a faster one and more for a slower one (10% × enemy interval ÷ 2.25, ENEMY_STATUS_PROC_INTERVAL_ANCHOR), so a fast enemy stuns you no more often per second than a slow one. Fire ignites you at a flat 10% per hit; poison always arrives as a damage-over-time.

Stun and freeze don’t chain on you either. For 3 s after a stun or freeze on you ends, no new stun or freeze lands (HERO_CONTROL_RESIST_SECONDS).

Two pairs of affixes answer the crowd control:

  • Reduced Stun Duration / Reduced Freeze Duration (armor, amulets, rings): the status lasts 1.5 s instead of 2 s, and a shorter freeze still slows by the full 30%. The same one on a second item changes nothing.
  • Immune to Stun / Immune to Freeze (uniques only): the status never lands, and the combat log reads “You are immune to …‘s stun”. Immunity beats the reduction.

While one of them is active, the character sheet lists Stun Duration / Freeze Duration under your resistances (75% or Immune).

DoT magnitude — exact formulas

All three damage-over-time effects are stored as a damage-per-second value that ticks every 0.5 s. Poison and Ignite are reduced by the enemy’s matching resistance when applied (minus any penetration, capped at 90%); Bleed is physical and never resisted (src/core/simulation.ts, applyPlayerElementalOnHit + applyEnemyDamageOverTime).

  • Ignite (Fire DoT) — the total is a fixed fraction of your flat fire damage, independent of duration:

    FIRE_DOT_DAMAGE_FACTOR = 0.25 / 6            # = 0.25 over the 6 s duration
    dotPerSecond = fireDamage × FIRE_DOT_DAMAGE_FACTOR
    totalIgnite  = dotPerSecond × 6 = fireDamage × 0.25     (before fire resistance)

    The proc chance is a flat 10% (not speed-normalised): the DoT magnitude already scales off fireDamage, which is itself speed-normalised per hit, so slow weapons land bigger-but-rarer ignites for equal DPS.

  • Poison DoT — the flat poison-damage stat is the DoT total, spread over the duration, and it is applied on every landed hit with no proc roll:

    dotPerSecond = poisonDamage / 6
    totalPoison  = poisonDamage                              (before poison resistance)

    Because it never rolls a proc, poison is the most consistent DoT — but on multi-hit skills (Zeal) the poison damage still applies on every sub-hit while status procs only roll on the first.

  • Bleed (Rend) — physical, unresisted, magnitude scales off the damage of the Rend hit:

    totalBleed   = amount × bleedPercent                    # amount = the post-mitigation physical hit
    dotPerSecond = totalBleed / 5

Freeze and Stun are fixed-duration crowd control (no damage), so instead their chance is speed-normalised by the intrinsic interval of the damage source you actually swing — procChance = min(1, 0.10 × swingInterval) — giving equal CC uptime per second on fast and slow weapons.

Two caps sit on the player’s proc chance. Skill nodes can raise the base chance (Conduit, a rider’s own per-rank chance), so both ends are clamped: the chance before speed normalisation can never exceed 20% (STATUS_PROC_CHANCE_CAP_BASE), and the finished chance after normalisation can never exceed 50% (STATUS_PROC_CHANCE_CAP_NORMALISED). A slow staff can no longer ride the ×interval scaling into permanent crowd control. On a shield-strike build (Aegis, Smite) that interval is the shield’s (divided by the skill’s attack-speed multiplier), not the idle weapon’s. Freeze applies COLD_FREEZE_ATTACK_SPEED_REDUCTION = 0.30; Stun sets the enemy action-speed factor to 0 for its duration.

Stun and freeze don’t chain. A stunned or frozen enemy can’t be stunned or frozen again until it recovers, and for 3 s after either ends it resists both (ENEMY_CONTROL_RESIST_SECONDS). Every source counts: elemental procs, skills (Aegis, Smite, Shield Charge, Staggering Blow, Cataclysm) and the Blunt T6 Concussion. Shield Charge’s and Staggering Blow’s own stun can land at most once every 5 s on top of that.

Worked example — a 200 fire-damage hit

Suppose your flat fire damage is 200 and you land a hit that rolls an Ignite (10% chance):

  1. totalIgnite = 200 × 0.25 = 50 fire damage over 6 s (before resistance).
  2. dotPerSecond = 50 / 6 ≈ 8.33, and with DOT_TICK_INTERVAL_SECONDS = 0.5 each tick deals 8.33 × 0.5 ≈ 4.17, i.e. 12 ticks of ~4.17 across the 6 seconds.
  3. Against an enemy with 40% fire resistance, the whole DoT is scaled by (1 − 0.40): 50 × 0.60 = 30 total, ~2.5 per tick.

The instant fire portion of that same swing (200 × (1 − 0.40) = 120) lands separately and immediately; the 50-point (pre-resist) Ignite is the DoT rider stacked on top. Multiple ignites stack in parallel — a fresh proc does not refresh the old one.

DoT stacking

Multiple damage-over-time instances stack — applying a new ignite, poison, or bleed does not refresh or overwrite an existing one. Each ticks down in parallel, up to 10 of each type on one enemy (DOT_STACK_CAP_PER_TYPE): an 11th burn, poison or bleed replaces the oldest of its type. Note that on multi-hit attacks (such as Zeal), the elemental damage applies on every hit, but a status proc (and Crushing Blow) rolls only on the first hit.