Guide
Game damage over time (DoT) systems explained
Harbor Swamp's witch-doctor encounter was tuned for “spread pressure”: three poison clouds, a rot curse, and a channeled plague bolt. Playtesters reported the fight felt random — not because numbers were wrong, but because tick damage arrived in invisible bursts, refreshes clipped duration without feedback, and two different poisons overwrote each other silently. The refactor did not buff any ability. It introduced a single global tick scheduler, explicit stacking policies per debuff family, and floating combat text grouped by source. Average attempt time dropped 1.8 minutes; support players finally understood when to cleanse.
Damage over time (DoT) is sustained harm applied across multiple ticks instead of one upfront hit. It powers poison rogues, burn mages, bleed warriors, and environmental hazards. Its mirror, healing over time (HoT), shares the same engine. This guide covers DoT taxonomy, tick scheduling, snapshot vs dynamic scaling, stacking and refresh rules, resistance and shield interaction, archetype design, UI readability, multiplayer authority, the Harbor Swamp refactor, a technique decision table, pitfalls, and a production checklist. For the broader buff/debuff container model, see status effects; for one-shot damage typing, see elemental damage.
DoT taxonomy: not every tick is the same
Designers often lump all periodic damage under “poison.” Production code should separate behavior classes:
| Type | Tick model | Typical feel | Examples |
|---|---|---|---|
| Fixed-interval DoT | Every T seconds for N ticks | Predictable, spreadsheet-friendly | Classic poison, regen denial |
| Ramp DoT | Damage increases per tick or over time | Urgent cleanse pressure | Accelerating rot, heat buildup |
| Aura / ground DoT | Tick while inside volume | Positioning puzzle | Fire pools, toxic fog |
| Channeled DoT | Tick only while caster channels | Interruptible sustained pressure | Blizzard, flamethrower beam |
| On-hit bleed | Extra tick when target moves or acts | Kiting punishment | Bleed, thorns |
| Percent-max-HP DoT | Tick scales with target health | Boss enrage, anti-tank | Melt, curse of pain |
Channeled DoTs belong to the cast FSM described in channeling and cast-time systems — ticks stop when the channel breaks. Ground auras need spatial queries each tick or on enter/exit events; do not re-raycast the whole arena naively every frame.
Tick scheduler: global clock vs per-instance timers
The scheduler decides when damage fires. Two dominant patterns:
Global combat tick (recommended for RPGs)
A server-side clock fires every 1.0 s (or 0.5 s for fast action). All active DoTs
with nextTick <= now apply damage, then advance
nextTick += interval. Benefits: one loop, easy combat log grouping,
consistent cleanse windows. Drawback: all DoTs align to the same beat unless you
stagger initial offsets.
Per-instance coroutines
Each DoT runs its own timer from application time. Feels organic in small fights but explodes into hundreds of timers in large raids and desyncs under lag unless server-authoritative.
Rule: pick one scheduler per game mode and never mix silently. MMORPGs almost always use global ticks; roguelikes with five enemies can use per-instance. Document the interval in tooltips (“Deals 120 every 2 s for 10 s”).
Tick batching and floating combat text
Five DoTs ticking the same frame should not spawn five identical numbers. Batch by source ability or debuff family for floating combat text, or show a single merged tick with a breakdown on hover. Uncapped number spam trains players to ignore feedback.
Snapshot vs dynamic scaling
When a DoT is applied, should later stat changes affect tick damage?
| Model | Behavior | Player skill expression |
|---|---|---|
| Snapshot at apply | Store attack power / spell power at cast; ticks use frozen values | Buff before apply, then refresh; rewards rotation planning |
| Dynamic live | Recalculate each tick from current stats | Debuffs on target and buffs on caster update mid-DoT |
| Hybrid | Snapshot base, dynamic crit/vulnerability multipliers | Middle ground; document clearly |
World of Warcraft popularized snapshot gameplay for fire mages and affliction warlocks. Dynamic models suit games without buff weaving. Whichever you choose, expose it in internal docs and QA scripts — switching models mid-expansion breaks player guides.
Percent-max-HP DoTs should snapshot max HP at apply or use current HP each tick; current-HP models accelerate kills on wounded targets and feel unfair on tanks unless capped per tick.
Stacking, refresh, and pandemic rules
Stacking policy is where most DoT bugs hide. Define per debuff family
(e.g. poison_wd_rot), not per visual icon.
- Unique — only one instance; reapply refreshes duration, does not stack damage.
- Intensify stack — each stack adds damage or tick rate up to cap (3 stacks = 3× tick).
- Parallel instances — multiple independent timers (rare; hard to read).
- Pandemic refresh — reapply before expiry adds remaining duration to new full duration, up to 130% cap (WoW-style); rewards proactive maintenance without infinite extension.
- Clipped refresh — naive refresh resets timer to full duration, wasting remaining ticks; feels bad if accidental.
When two abilities share a family, the weaker reapply should not downgrade a stronger active DoT unless that is an explicit PvP counter. Log apply attempts that are rejected (“stronger poison already active”) for balance review.
HoT symmetry
Healing over time uses identical machinery with inverted polarity. If cleanses dispel DoTs, dispel or purge should interact with HoTs in documented ways for PvP. See healing and lifesteal systems for burst-vs-sustain tradeoffs.
Resistance, shields, and mitigation per tick
Decide whether armor, resistance, and damage reduction apply:
- Per tick — standard for physical bleeds; target buffs mid-DoT matter.
- At apply only — snapshot mitigation; simpler but can be exploited.
- Ignored — true damage DoTs; reserve for boss mechanics with telegraphed cleanse windows.
Shields and barriers should absorb tick damage consistently — either every tick chips shield or DoT bypasses shields entirely. Mixed behavior confuses TTK math. Overkill on the killing tick should not roll excess into shield break VFX twice.
Critical hits on DoT: common patterns are (a) crit chance rolled once at apply doubling all ticks, (b) crit per tick at reduced rate, or (c) no crit on DoT. Pick one per damage school and match tooltips.
Archetype design: bleed, poison, burn
Archetypes give players build identity even when math is similar:
- Bleed — physical, often unmitigated by armor or bonus vs bleeding targets; pairs with on-movement bonus ticks.
- Poison — nature/chaos; long duration, low per-tick; stacking intensify common.
- Burn — fire; short intense duration or ground spread; interacts with elemental weaknesses.
Give each archetype distinct VFX palette, audio stinger on apply, and debuff-bar icon. Players should identify threat at a glance during boss phase transitions.
UI and readability
DoT fails when players cannot answer: “How much am I taking, for how long, from whom?”
- Debuff bar slots with duration sweep and stack count numerals.
- Tooltip: total remaining damage estimate (optional advanced stat).
- Distinct border color per family; never reuse stun icon for poison.
- Boss frame: priority sort — lethal DoTs and dispellable debuffs rise to the left.
- Audio cue on apply and on final tick before expiry for cleanse timing practice.
Accessibility: do not rely on color alone; use shape overlays for color-blind modes. Screen readers need “Rot poison, 4 stacks, 6 seconds remaining, 480 damage total estimated.”
Technique decision table
| When you need… | Prefer | Over |
|---|---|---|
| Burst check or opener | Direct nuke + short DoT rider | Long ramp-only damage with no upfront hit |
| Sustained boss DPS window | Snapshot DoT + pandemic refresh rotation | Spam instant hits into damage immunity phases |
| Area denial | Ground aura with enter/exit tick | Homing poison bolt with hidden infinite uptime |
| PvP fairness | Capped stacks, dispel windows, visible timers | Uncapped parallel poison instances |
| Co-op clarity | Named debuff families + cleanse callouts | Generic “afflicted” state |
Harbor Swamp witch-doctor refactor (worked example)
Three abilities shared the poison icon but used incompatible rules: Venom Cloud (aura), Rot Curse (stacking intensify), and Plague Bolt (snapshot single-target). Refactor steps:
- Migrated all three to a
PeriodicDamageControllerwith family IDspoison_aura,poison_rot,poison_bolt. - Global 1.0 s combat tick on server; clients predict bar countdown only.
- Rot Curse: max 4 stacks, intensify +25% per stack, pandemic refresh capped at 130% duration.
- Venom Cloud: tick on enter + every 1 s while inside; no stack; exiting clears after 2 s linger.
- Plague Bolt: snapshot spell power at hit; 6 ticks; unique family — cannot be overwritten by weaker cloud ticks.
- Grouped floating text per tick per target; debuff tooltips show “~720 remaining.”
- Added 0.5 s telegraph on curse apply for cleanse practice in normal mode.
Outcome: cleanse casts +41%, “unfair poison” survey responses -67%, no DPS number changes.
Multiplayer authority
Server applies DoT on tick; clients show predicted debuff bars and reconcile on
DoTApply, DoTTick, DoTExpire, and
DoTDispel events. Never apply tick damage client-side in PvP.
Serialize apply payloads with: familyId, snapshot stats, endTime, stackCount,
sourceEntityId.
On target death, clear all DoTs or let plague spread to nearby — but document ghost-tick policy (ticks after death should not award loot-tracked damage). Cap active DoT instances per target (e.g. 12) to prevent aura-stack exploits.
Common pitfalls
- Invisible tick interval — players cannot learn cleanse timing.
- Clipped refresh without feedback — reapply feels like it did nothing.
- Weaker overwrite — spam ability replaces stronger raid debuff.
- Mixed schedulers — some DoTs on global tick, some on coroutines; combat logs lie.
- DoT through invulnerability — i-frames should pause or immune ticks.
- Uncapped percent-max-HP — melts tanks in one enrage cycle.
- Shield bypass inconsistency — only some poisons ignore barriers.
- Float rounding drift — 0.1 + 0.2 tick intervals accumulate desync over long fights.
Production checklist
- Define DoT taxonomy per ability: fixed, ramp, aura, channel, on-hit, percent-HP.
- Implement one authoritative tick scheduler per game mode; document interval.
- Choose snapshot vs dynamic scaling per school; lock in tooltip formulas.
- Assign debuff family IDs; specify stack, unique, parallel, or pandemic refresh rules.
- Apply mitigation policy per tick or at apply; align shield and crit behavior.
- Ship debuff bar with duration, stacks, and distinct icons per family.
- Batch floating combat text; avoid per-tick number floods.
- Server-authorize apply, tick, expire, dispel; cap instances per target.
- QA: refresh at 10%, 50%, 90% duration; verify pandemic cap and weaker-overwrite guard.
- Telemetry: tick damage share, dispel rate, average stacks at death, rejected reapply count.
- Accessibility: non-color cues, tooltips, screen reader strings.
Key takeaways
- DoT is a scheduling and stacking problem before it is a balance spreadsheet.
- Snapshot vs dynamic scaling defines your entire rotation meta — choose deliberately.
- Pandemic refresh rewards skilled maintenance; clipped refresh punishes without teaching.
- One global tick clock keeps combat logs honest and cleanses readable.
- If players cannot see ticks coming, they blame RNG instead of learning mechanics.
Related reading
- Game status effects explained — buff/debuff containers, CC, and cleanse pipelines
- Game elemental damage systems explained — typing, weaknesses, and resistance tables
- Game channeling and cast-time systems explained — channeled DoTs and interrupt windows
- Game healing and lifesteal systems explained — HoT mirror and sustain vs burst