Threat and Aggro
Threat and aggro decide whom an enemy attacks. The enemy keeps a threat score for each player, damage and healing raise it, time lowers it, and the highest score gets attacked. A rival must pass by a margin and the enemy needs a moment to turn, so it does not flip. A taunt forces the target for a while.

Paste this to your AI
Copy it into Claude, Cursor or ChatGPT. It already has good values and the usual mistakes in it.
Add "Threat and Aggro" to my game.
What it should do: Threat lets a team of players share a fight on purpose: one holds the enemy's attention while the others do their work. Players can read why the enemy chose someone, and can change it.
Build it exactly as this state machine. First check that it fits my game, then build it like this:
```mermaid
stateDiagram-v2
[*] --> idle
idle: No target
locked: Locked on
turning: Turning
taunted: Taunted
idle --> locked: someone is hit
idle --> taunted: taunt lands
locked --> idle: no threat left
locked --> turning: rival passes the lead
locked --> taunted: taunt lands
turning --> locked: turn ends
turning --> idle: no threat left
turning --> taunted: taunt lands
taunted --> locked: taunt ends
taunted --> idle: taunt ends, no threat
```
Use these starting values:
- switchMargin: 1.1
- switchDelay: 0.4 s
- decayRate: 2 units/s
- healShare: 0.5
- tauntTime: 3 s
Watch out for these common mistakes:
- Swapping back and forth between two players: Tell your AI: a rival must have more threat than the current target times a margin, such as one and a tenth, and the enemy needs a short moment to turn. Cancel the turn if the rival is no longer ahead.
- Attacking someone who has fallen: Tell your AI: when a player is not alive, set their threat to zero and pick a new target at once, with no turning. A player who comes back starts from nothing.
- A taunt that is forgotten at once: Tell your AI: a taunt lifts the taunter's threat to the highest in the fight, not above it. When it ends, the taunter keeps the lead until someone passes them by the margin.
- Healing that counts as full threat: Tell your AI: count only a share of the healing as threat, such as half.
- Threat that never fades: Tell your AI: take a little threat from everyone each second. Apply the fading before adding the new hit, so a hit always counts in full.
Do not change anything else in the game. Do not claim anything without proof: model what it takes, and show me what your solution rests on and how I can see that it works. If you cannot show something, say you do not know. When you are done, tell me in plain words how to try it.Or skip this and connect the MCP: your AI then finds all of this by itself.Connect the MCP
What it does
Threat lets a team of players share a fight on purpose: one holds the enemy's attention while the others do their work. Players can read why the enemy chose someone, and can change it.
How it runs, as a diagram
Everything it can be in, and what moves it on. Your AI builds from exactly this.
How it runs, as a diagram
- No target → Locked on: someone is hit
- No target → Taunted: taunt lands
- Locked on → No target: no threat left
- Locked on → Turning: rival passes the lead
- Locked on → Taunted: taunt lands
- Turning → Locked on: turn ends
- Turning → No target: no threat left
- Turning → Taunted: taunt lands
- Taunted → Locked on: taunt ends
- Taunted → No target: taunt ends, no threat
Good starting values
| Value | Start with | What it changes |
|---|---|---|
| switchMargin | 1.1 | How many times the current target's threat a rival needs before the enemy leaves its target. A tenth more is enough to stop two close players from swapping the enemy back and forth, and still feels fair. Raise it to make the tank harder to pull away from. |
| switchDelay | 0.4 s | The moment the enemy needs to turn once a rival has passed the margin. It gives the player a short warning that the enemy is about to change and a chance to react, instead of a sudden switch. |
| decayRate | 2 units/s | How much threat every player loses each second. It is small next to a hit of ten or twenty, so a player who stops fighting slowly lets go of the enemy, but one good pause does not reset the fight. |
| healShare | 0.5 | How much of the healing counts as threat. Half keeps healers a little out of the front line without making them invisible, so a healer who does everything alone still gets noticed. |
| tauntTime | 3 s | How long a taunt holds the enemy. Three seconds gives the others time to act, and it is short enough that the taunt has to be used again. |
What usually goes wrong
Swapping back and forth between two players
Two players deal almost the same damage. Every hit puts a different one in front by a hair, and the enemy turns to the other one again and again without ever finishing an attack.
Fix: Tell your AI: a rival must have more threat than the current target times a margin, such as one and a tenth, and the enemy needs a short moment to turn. Cancel the turn if the rival is no longer ahead.
Attacking someone who has fallen
A player falls, but their threat stays. The enemy keeps attacking the spot where they lie, or goes for them again the instant they get up.
Fix: Tell your AI: when a player is not alive, set their threat to zero and pick a new target at once, with no turning. A player who comes back starts from nothing.
A taunt that is forgotten at once
The taunt holds the enemy for three seconds, but the taunter has hardly any threat. The moment it ends, the enemy turns away to whoever was hurting it most.
Fix: Tell your AI: a taunt lifts the taunter's threat to the highest in the fight, not above it. When it ends, the taunter keeps the lead until someone passes them by the margin.
Healing that counts as full threat
A healer heals the whole team and gets as much threat as the fighter who dealt the damage. The enemy ignores the fighter and chases the healer.
Fix: Tell your AI: count only a share of the healing as threat, such as half.
Threat that never fades
A player who ran away ten minutes ago still has the highest score, so the enemy keeps coming back for them while the players in front of it do whatever they like.
Fix: Tell your AI: take a little threat from everyone each second. Apply the fading before adding the new hit, so a hit always counts in full.
How to check it works
- An enemy that has nobody to attack. A player hits it for 10: That player has 10 threat and the enemy attacks them.
- An enemy that has nobody to attack. A player heals for 10: That player has 5 threat and the enemy attacks them.
- An enemy that has nobody to attack. Three players hit it for 10, 30 and 20 in the same moment: The enemy attacks the one who hit for 30.
- The enemy attacks a player with 100 threat. A rival gets 105, and then 111: At 105 nothing changes, and at 111 the enemy starts to turn.
- The enemy attacks a player with 50 threat, and the margin is the smallest allowed. A rival gets exactly 50: The enemy stays with its target.
- A rival has just passed the margin. You watch the enemy: It keeps its old target for the turning time, and then attacks the rival.
- The enemy is turning towards a rival. The old target hits hard before the turn is over: The enemy stays with the old target.
- The enemy attacks a player, and others have less threat. That player falls: The enemy goes for the next in line at once, with no turning, and the fallen player has no threat.
- The enemy attacks a player. Another player taunts, and the first player then hits for 500: The enemy keeps attacking the taunter for the whole taunt.
- The highest threat is 100. A player with 5 threat taunts: Their threat becomes 100, and if it was already higher, it stays where it was.
- A taunt runs out. A rival has 105 percent of the taunter's threat: The enemy stays with the taunter.
- A taunt is running. The taunter falls: The taunt ends and the enemy picks the highest of the rest.
- Players with 50 and 30 threat, and nothing happening. A second passes: Each has lost the fading amount, and nobody drops below zero.
- Everyone's threat is nearly gone. It fades away, or everyone falls: The enemy has no target.
- Damage or healing that is below zero or not a number. It arrives: No threat is added.
Works well with
- Health and Damage: Threat from damage that was soaked up by armor or a protection time would make a player the target for hits that did nothing. Count the threat from the damage that really happened, after armor.
- Ability Cooldowns: A taunt needs a cooldown that is longer than its time, or one player can hold the enemy for the whole fight and the others have nothing to manage.
- Block and Guard: The player who holds the enemy's attention is the one who needs the guard. Give them a bigger meter, not a smaller one. Pick the target first, then let that player's guard decide how much gets through.
Common questions
what do i tell my ai to add aggro and taunt
Paste this: Give each enemy a threat score for every player. Damage adds its size, healing adds half of it, and every score loses two a second. The enemy attacks the highest score. A rival must have more than one and a tenth times the current target's score, and the enemy takes 0.4 seconds to turn. A taunt lifts the taunter to the highest score and holds the enemy for three seconds. A player who falls loses all threat.
why does my enemy keep switching between two players
Because it switches the moment someone is ahead by even a hair. Make the rival pass the current target by a margin, such as a tenth, and give the enemy a short moment to turn.
should healing give threat
A share of it, such as half. Without any, a healer can heal for free and the enemy never cares. With all of it, the enemy ignores the fighters and goes after the healer.
what should a taunt do to threat
Force the target for a few seconds and lift the taunter's threat to the highest in the fight. If it only forces the target, the enemy turns away the moment it ends.
Where it comes from
We could not find a reliable origin for this one yet.
What was checked
- 24 tests pass on the reference code.
- The state diagram was checked against the code, at the default values and at every listed low and high value.
Your AI gets the code
Tested example code comes through the Spielerando connection, so your AI can use it right away. How to connect it