Guide
Game threat and aggro systems explained
Harbor Ruins' three-player raid on the Sunken Archivist boss wiped twice in playtests because a mage's opening burst pulled aggro off the tank during the first phase transition. The healer died before anyone understood why the boss had turned. Designers had assumed “whoever hit last” targeting was enough — it wasn't. They replaced proximity aggro with a threat table (also called a hate list or aggro table): a per-enemy scoreboard that tracks how much each combatant has annoyed that enemy, applies modifiers for taunts and heals, decays over time, and drives target selection. Threat systems are the hidden contract between tanks, healers, and DPS in MMOs, action RPGs, and co-op shooters with role clarity. This guide covers threat generation, taunt overrides, decay and wipe rules, healing threat, split-target and boss-swap mechanics, how threat pairs with boss fight design and melee combat, walks a Harbor Ruins refactor, provides an aggro model decision table, lists pitfalls, and ends with a production checklist alongside our companion AI guide and enemy spawning guide.
What threat and aggro mean
Aggro (aggression) is which character an enemy is actively trying to hurt. Threat is the numeric score the game uses to decide aggro. When multiple players are in range, the enemy picks the combatant with the highest threat on its table — unless a scripted override (cutscene grab, random target ability) fires.
Threat is not the same as damage dealt. A tank who deals modest damage but runs threat-generating stance and taunt abilities can hold aggro while a DPS outputs ten times the DPS. Conversely, a healer who tops off the raid during a damage spike may generate enough healing threat to pull adds off the off-tank if those adds use standard MMO rules (healing often generates threat on all enemies in combat).
Threat systems create readable roles: the tank controls who gets hit, DPS trades burst for aggro risk, healers manage triage without becoming the boss's lunch. Without a table, designers fall back to nearest-target or last-hit rules that feel arbitrary in co-op and punish skilled DPS for playing well.
Threat table anatomy
Each hostile NPC maintains a map from actor_id to
threat_value. On every relevant event, the manager updates scores
and re-evaluates the current target:
struct ThreatEntry {
float threat;
float last_update_time;
bool in_combat;
};
// After damage event:
threat[victim_id] += damage * threat_per_damage * victim_threat_mod;
// Target selection (simplified):
current_target = argmax(threat_table, threat);
Production tables also track:
- Taunt lock — forced top threat for N seconds, often with a floor (“110% of previous top”) so a second taunt can steal.
- Decay — threat bleeds down per second out of combat or globally during long fights to prevent stale leaderboards.
- Proximity leash — reset table when the tank kites beyond leash radius (see boss design).
- Transfer on death — wipe table, redistribute to nearest player, or inherit percentage to backup tank.
Common threat sources
| Event | Typical threat rule | Design intent |
|---|---|---|
| Damage dealt | damage × threat_per_damage (often 1.0 for DPS) |
Natural hate from hitting the boss |
| Damage taken (self) | Flat bonus on being hit | Tank gains hate when soaking hits |
| Healing allies | heal_amount × 0.5 split across all engaged enemies |
Healers must not pull adds casually |
| Taunt ability | Set to max + epsilon or +200% top |
Hard snap for tank swaps |
| Buffs / debuffs | Flat threat per application | Utility classes contribute without burst |
| Proximity pulse | Small tick while in melee range | Helps tanks who connect late |
Modifiers stack multiplicatively: a tank stance might be ×3.0
threat on damage, while a rogue stealth opener is ×0.0 until
the first hit lands. Document these in data tables so balance designers can
tune without recompiling AI.
Taunt, threat dump, and tank swaps
Taunt is the emergency override: set threat to guaranteed top for a window. Classic MMO pattern:
- Main tank holds boss; debuff stacks to swap threshold.
- Off-tank taunts — threat jumps to
current_max × 1.1. - Main tank stops generating threat (defensive stance) or uses threat drop.
- After swap timer, boss cleaves the correct player.
Threat dump (fade, vanish, feign death) zeroes or reduces threat so a DPS can survive a random-target mechanic. Pair dumps with boss telegraphs — if the Archivist marks a player for a laser, that player should not also be highest threat unless the mechanic is intentional.
Boss fights often script tank swaps independent of the table:
a slam applies CannotBeTaunted for 3s, then requires off-tank
taunt. Hybrid design (table + script) reads clearer than pure RNG targeting.
See our
boss fight design guide
for phase scripting patterns.
Decay, wipe, and add management
Without decay, early fight threat never matters — the mage who opened with a 10,000-threat crit still leads at minute eight even if they stopped attacking. Common approaches:
- Global decay — subtract
k × dtper second from all entries (tunekso active tanks stay on top). - Combat exit wipe — clear table when enemy resets or leashes; prevents pre-pull threat banking exploits.
- Soft cap — threat above 1M compresses logarithmically so burst windows do not permanently skew targeting.
Add packs need per-enemy tables, not one global list. When the Archivist summons scribes, each scribe tracks threat independently — but healing threat often applies to every add in combat, which is why off-tanks taunt adds on spawn before healers cast group heals. Link add spawn timing to wave and spawn systems so tanks know when to pick up new entries.
Alternatives to full threat tables
Not every game needs WoW-style hate. Pick the model that matches genre and player count:
- Nearest hostile — cheap, works for horde shooters; feels unfair in raids.
- Last damage source — common in action RPGs; rewards kiting, punishes ranged DPS.
- Role-weighted priority — AI always prefers “tank” tag if in range; little player skill expression.
- Utility AI scoring — threat is one feature among many in a utility scorer; flexible but opaque.
- Full threat table — best for co-op RPGs with dedicated roles and long fights.
Harbor Ruins Sunken Archivist refactor (worked example)
Problem. Harbor Ruins' co-op raid used last-hit aggro on the Archivist boss and proximity on adds. Playtest metrics: 38% of wipes featured a healer or mage death in the first 15 seconds after a phase change; survey comments cited “boss randomly turned.”
Change. Implemented per-actor threat tables on the boss and
all adds. Tank sword: threat_per_damage = 3.0, taunt sets
max + 1 for 6s. Mage: 1.0 damage threat, no self-mitigation
bonus. Healer: 0.5 × heal applied to each engaged enemy.
Global decay 50 threat/sec. Phase 2 scripted grab ignores table
(telegraphed 2s); post-grab off-tank taunt required.
UI. Optional threat meter (sorted bar) for tanks; aggro indicator on target frame (red outline on current victim). Tutorial ping on first taunt during practice mode.
Results. Phase-1 wipe rate dropped from 38% to 11%. Average time-to-first-taunt after add spawn fell from 2.4s to 0.8s. Mage players reported higher agency (“I can burst if tank taunts first”). No change to boss DPS check difficulty — only targeting fairness.
Aggro model decision table
| Game context | Recommended model | Why |
|---|---|---|
| 4-player co-op RPG raid | Full threat table + taunt | Role clarity, tank swaps, healer risk |
| Solo action RPG | Last hit or nearest | One player; table adds UI noise |
| PvE horde shooter | Nearest + damage pulse | Fast targets, no tank role |
| Companion-heavy RPG | Table + companion threat halving | Pets should not steal boss aggro |
| Boss with fixed tank-buster | Scripted target + table between casts | Telegraphed mechanics override hate |
| Large-scale PvP AV faction war | No table; player targeting only | Threat is a PvE co-op tool |
Multiplayer and netcode notes
Threat must be server-authoritative in online co-op. Clients predict target selection for animations, but only the host or dedicated server applies damage/heal events to tables. Desync symptoms: boss spins between two players every frame because each client computed a different max.
Replicate current_target_id and optionally top-three threat for
UI — not the full table (bandwidth). On host migration, snapshot tables
or reset combat on boss; half-synced hate is worse than a wipe.
For melee combat netcode, threat updates should align with confirmed hit events, not animation wind-up start, so laggy DPS does not pull aggro before damage lands.
Common pitfalls
- Invisible threat — players cannot learn a system they never see; expose at least target-of-target and taunt success feedback.
- Healing threat surprise — a big AoE heal on pull yanks every add; teach with a low-stakes encounter first.
- Taunt immunity gaps — boss immune during transition but adds are not; off-tank has no tools while healers spike threat.
- Decaying too fast — tank loses top between GCDs; feels like the table is broken.
- Pet and turret leakage — deployables generate full threat; either halve pet hate or assign to owner.
- Random target + high threat — laser on the tank while tank is meant to soak is good; laser on tank during swap is cruel.
- Pre-pull banking — buffs that generate threat before combat starts pull bosses early; wipe tables on leash reset.
Production checklist
- Define threat sources and per-class modifiers in data, not hard-coded AI.
- Implement server-authoritative tables for online co-op.
- Ship taunt with clear cooldown, immunity windows, and UI confirmation.
- Tune healing threat separately for single-target and AoE heals.
- Add global decay or soft cap for fights longer than three minutes.
- Wipe or decay tables on leash reset and combat exit.
- Expose target-of-target and optional threat meter for tanks.
- Script phase overrides that intentionally ignore the table.
- Halve or redirect pet, drone, and turret threat to owners.
- Playtest add packs with healer AoE before tuning boss HP.
Key takeaways
- Threat tables turn targeting into a learnable co-op skill instead of opaque RNG.
- Damage, healing, taunts, and stance modifiers all feed the same per-enemy scoreboard.
- Taunt and threat dump abilities are the player-facing levers on top of passive generation.
- Decay, wipe rules, and scripted boss phases keep long fights from freezing aggro state.
- Match the aggro model to role count — full tables for raids, lighter rules for solo and horde modes.
Related reading
- Boss fight design explained — phase scripting and tank-buster telegraphs
- Melee combat systems explained — hit confirmation and netcode timing
- Companion AI design explained — pet threat and assist behavior
- Enemy spawning and wave systems explained — add pacing and pull timing