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.

Resistances & the 75% cap

Fire, Cold, Lightning, and Poison resistances are each capped at 75% for your hero. Single-element resistance affixes roll on armour, amulets and rings; All Resistances stays amulet-only. Some skills and passives raise resistances too. Resistances can also go negative (a vulnerability), and enemies are capped higher, at 95%.

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 three caps are hand-tunable constants in src/data/balance/combat.ts:

CapValueConstant (combat.ts)
Hero resistance (per element)75%FORMULA_CONFIG.maxResistance (line 40)
Enemy resistance95%FORMULA_CONFIG.maxEnemyResistance (line 58)
Debuff / penetration effectiveness90%MAX_DEBUFF_EFFECTIVENESS (line 82)

Every resistance value — hero and enemy, direct hit and DoT — is clamped to [0, 0.95] inside damageAfterResistance, and penetration is clamped to [0, 0.90] before it is subtracted.

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.

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 weapon’s intrinsic interval — procChance = min(1, 0.10 × weaponInterval) — giving equal CC uptime per second on fast and slow weapons. Freeze applies COLD_FREEZE_ATTACK_SPEED_REDUCTION = 0.30; Stun sets the enemy action-speed factor to 0 for its duration.

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. 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.