Ailment Model¶
Summary: Ailments are status effects that deal damage of an existing damage type — they are NOT damage types themselves and NEVER get resistances of their own. This document exists so the inheritance model survives contributor turnover: do not add
ResistanceBleedorResistancePoison.
The Inheritance Rule¶
Project Eternal follows the PoE ailment model: each ailment applies a DoT (or debuff) of an underlying damage type and inherits that type's mitigation.
| Ailment | Underlying type | Mitigated by | DoT? |
|---|---|---|---|
Status.Bleed |
Physical | — (see below) | Yes |
Status.Ignite |
Fire | ResistanceFire | Yes |
Status.Poison |
Corruption | ResistanceCorruption | Yes |
Status.Shock |
Electric | n/a — debuff that reduces all elemental resistances | No |
Corruption resistance IS the poison resistance. Adding a separate ResistancePoison would
either double-dip with ResistanceCorruption or contradict the inheritance rule. Same logic for
ResistanceBleed vs armor. If you find yourself adding a per-ailment resistance attribute, stop
and re-read this document.
Why Bleed bypasses armor (deliberate)¶
Armor defends against hits (ExecCalc_Damage). DoTs — including Bleed's physical ticks —
skip armor entirely (ExecCalc_DamageOverTime). This is PoE-faithful and intentional:
- A heavy-armor character is NOT automatically safe from bleed. Ailment pressure stays threatening regardless of hit mitigation.
- Bleed defense becomes its own itemization decision (the taken-line below), which is exactly the "defense choices are build choices" texture the itemization pillar wants.
The Four Ailment Modifier Axes¶
| Axis | Side | Mechanism |
|---|---|---|
| Chance to inflict | Source | BleedChance / IgniteChance / PoisonChance / ShockChance (0-100%), rolled by UOnHitAbility |
| Duration inflicted | Source | IncreasedStatusDuration (additive %), consumed when the proc's GE spec is built |
| Damage dealt | Source | IncreasedDamageOverTime + BleedDamageDealt / IgniteDamageDealt / PoisonDamageDealt on one additive line, applied on every tick |
| Damage taken | Target | BleedDamageTaken / IgniteDamageTaken / PoisonDamageTaken (additive %, negative = take less), applied on every tick |
All four follow the GDD's single-additive-line rule (Flat / Increased / Reduced — no More/Less multiplier tier). A planned fifth axis — reduced status duration on self ("of Shrugging") — is tracked as its own backlog task.
Per-type Increased* buckets do NOT apply to ticks. Procs seed their tick damage from the
post-Increased hit, so re-applying the per-type bucket in the DoT exec made "+50% Physical Damage"
secretly worth ~+125% on bleed ticks — the hit→ailment double-dip PoE removed. DoTs scale through
their own vocabulary instead: IncreasedDamageOverTime (all DoTs) + the per-ailment dealt-line
(this ailment only). This is what gives Feral Dual-Wield / Dread Channeler builds scaling knobs
that other builds don't also want.
How the dealt-line selects its attribute¶
Mirror of the taken-line: ExecCalc_DamageOverTime reads the Status.* asset tag on the
executing GE and joins the matching *DamageDealt attribute onto IncreasedDamageOverTime's
additive line, applied once per tick:
Authoring modifiers against the dealt-line¶
Item modifiers target the tags with operation Flat (the attribute holds the summed %):
Stats.Offensive.AilmentDealt.BleedStats.Offensive.AilmentDealt.IgniteStats.Offensive.AilmentDealt.Poison
An offensive prefix rolls positive values (e.g. "Hemorrhaging", +25% Bleed damage). No Shock entry — Shock is not a DoT.
How the taken-line selects its attribute¶
ExecCalc_DamageOverTime reads the Status.* asset tag on the executing GE (GE_Bleed carries
Status.Bleed, etc.) and applies the matching *DamageTaken attribute once to the tick:
Keying by status tag (not damage type) means non-ailment DoTs — ground hazards, future channeled degens — are untouched, and positive rolls ("+% bleed damage taken" curses) work for free.
Authoring modifiers against the taken-line¶
Item modifiers target the tags with operation Flat (the attribute holds the summed %):
Stats.Defensive.AilmentTaken.BleedStats.Defensive.AilmentTaken.IgniteStats.Defensive.AilmentTaken.Poison
A defensive suffix rolls negative values (e.g. "of Stanching", −15% Bleed damage taken). No Shock entry: Shock is a resistance debuff, not a DoT — its counterplay is dispel/avoidance, not a damage-taken stat.
Source Reference¶
| What | Where |
|---|---|
| Taken-line application | Source/ProjectEternal/Private/AbilitySystem/ExecCalc/ExecCalc_DamageOverTime.cpp |
| Attributes | Source/ProjectEternal/Public/AbilitySystem/EternalAttributeSet.h ("Ailment Damage Taken") |
| Tags | Source/ProjectEternal/Private/EternalGameplayTags.cpp (Stats.Defensive.AilmentTaken.*) |
| Damage pipeline | Damage Execution |
| Headless power model | EternalDoTMath (pure tick kernel + ComputeAilmentDPS stacking) → UBuildEvaluatorLibrary; reference-tested by ProjectEternal.Unit.Combat.DoTMath |
| Backlog origin | FSH-307 — "Audit ailment mitigation" |