Monster infighting
Enemies hurt by each other turn and fight among themselves.
On this page
Monster infighting happens when enemies damage each other and turn to fight. In Doom, a monster that survives damage from a source makes that source its target, the player included, unless the monster hurt itself or switched targets within its last 1001 chase steps1. A projectile can’t damage its shooter’s own species, so those attacks never start a fight within one, but bullets can2. Quake II narrows the switch: a hurt monster turns on another only if both walk, fly, or swim alike and their classes differ, and the tanks and bosses are never targeted this way; otherwise it joins its attacker’s target3.
- RetaliationDoom (1993). A monster that survives a hit turns on its attacker unless it hurt itself or switched within 100 chase steps, and a projectile can't hurt its shooter's own species.1,2
- Same kindQuake II (1997). A hurt monster turns on another of a different class that moves the same way, except the tanks and bosses, and otherwise joins its attacker's target.3
Games
| Game | Year | How | Note |
|---|---|---|---|
| Doom | 1993 | Retaliation | a monster that survives a hit turns on its attacker unless it hurt itself or switched within 100 chase steps, and a projectile can't hurt its shooter's own species |
| Quake II | 1997 | Same kind | a hurt monster turns on another of a different class that moves the same way, except the tanks and bosses, and otherwise joins its attacker's target |
Every claim about this mechanic, by game (3)
References
- ^ abcWhen damage with a source hits a Doom monster and the monster survives, it makes that source its target, player or monster alike, unless the source is the monster itself or Doom II's Arch-vile (
MT_VILE), or the monster's threshold from an earlier switch is still above 0; a damaged Arch-vile ignores its own threshold. Damage with no source never retargets. Each switch sets the threshold to 100;A_Chaselowers it by 1 per call and clears it at once when the target is gone or dead.Codeid-Software/DOOMrevisedHow we know
886 // do the damage 887 target->health -= damage; 888 if (target->health <= 0) ⋮ 890 P_KillMobj (source, target); 891 return; ⋮ 904 if ( (!target->threshold || target->type == MT_VILE) 905 && source && source != target 906 && source->type != MT_VILE) ⋮ 908 // if not intent on another player, 909 // chase after this one 910 target->target = source; 911 target->threshold = BASETHRESHOLD;
linuxdoom-1.10/p_inter.c lines 886–915 at a77dfb9 · upstream ↗ 60// follow a player exlusively for 3 seconds 61#define BASETHRESHOLD 100
linuxdoom-1.10/p_local.h lines 60–61 at a77dfb9 · upstream ↗ 680 // modify target threshold 681 if (actor->threshold) ⋮ 683 if (!actor->target 684 || actor->target->health <= 0) ⋮ 686 actor->threshold = 0; ⋮ 688 else 689 actor->threshold--;
linuxdoom-1.10/p_enemy.c lines 680–689 at a77dfb9 · upstream ↗ 354 {CC_ARCH, MT_VILE},linuxdoom-1.10/f_finale.c line 354 at a77dfb9 · upstream ↗ 690#define CC_ARCH "ARCH-VILE"linuxdoom-1.10/d_englsh.h line 690 at a77dfb9 · upstream ↗ 212 if ( (gamemode == commercial) ⋮ 222 if (gamemap == 30) 223 F_StartCast ();
linuxdoom-1.10/f_finale.c lines 212–223 at a77dfb9 · upstream ↗ 42 commercial, // DOOM 2 retail, E1 M34linuxdoom-1.10/doomdef.h line 42 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^ abA Doom projectile that touches a monster of its shooter's own type explodes without dealing damage, so those projectiles can't start infighting within a species; a hitscan attack has no such check.Codeid-Software/DOOMrevised
How we know
299 if (tmthing->target && ( 300 tmthing->target->type == thing->type || 301 (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)|| 302 (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) ) ⋮ 304 // Don't hit same species as originator. ⋮ 308 if (thing->type != MT_PLAYER) ⋮ 310 // Explode, but do no damage. 311 // Let players missile other players. 312 return false;
linuxdoom-1.10/p_map.c lines 299–313 at a77dfb9 · upstream ↗ 974 // shoot a thing 975 th = in->d.thing; 976 if (th == shootthing) 977 return true; // can't shoot self ⋮ 1010 if (la_damage) 1011 P_DamageMobj (th, shootthing, shootthing, la_damage);
linuxdoom-1.10/p_map.c lines 974–1011 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^ abWhen a monster survives damage from another monster, Quake II's
M_ReactToDamagemakes the attacker its enemy if both move the same way (walking, flying, or swimming), their class names differ, and the attacker isn't a tank, super tank, Makron, or Jorg; failing that, it fights back only if the attacker was targeting it, and otherwise takes on the attacker's enemy, unless that enemy is itself. Nothing happens when it hurt itself or the attacker is already its enemy. A player it was chasing is kept as the old enemy. Quake's rule, in the version 1.01 QuakeC of id's Quake-Tools release, is simpler: a monster turns on any attacker of a different class, and soldiers turn on each other too.Codeid-Software/Quake-2 · id-Software/Quake-ToolsrevisedHow we know
295void M_ReactToDamage (edict_t *targ, edict_t *attacker) ⋮ 297 if (!(attacker->client) && !(attacker->svflags & SVF_MONSTER)) 298 return; ⋮ 300 if (attacker == targ || attacker == targ->enemy) 301 return;
game/g_combat.c lines 295–301 at 372afde · upstream ↗ 335 // it's the same base (walk/swim/fly) type and a different classname and it's not a tank 336 // (they spray too much), get mad at them 337 if (((targ->flags & (FL_FLY|FL_SWIM)) == (attacker->flags & (FL_FLY|FL_SWIM))) && 338 (strcmp (targ->classname, attacker->classname) != 0) && 339 (strcmp(attacker->classname, "monster_tank") != 0) && 340 (strcmp(attacker->classname, "monster_supertank") != 0) && 341 (strcmp(attacker->classname, "monster_makron") != 0) && 342 (strcmp(attacker->classname, "monster_jorg") != 0) ) ⋮ 344 if (targ->enemy && targ->enemy->client) 345 targ->oldenemy = targ->enemy; 346 targ->enemy = attacker; ⋮ 350 // if they *meant* to shoot us, then shoot back ⋮
game/g_combat.c lines 335–367 at 372afde · upstream ↗ 506 if (targ->svflags & SVF_MONSTER) ⋮ 508 M_ReactToDamage (targ, attacker);
game/g_combat.c lines 506–508 at 372afde · upstream ↗ 198 if ( (self.flags & FL_MONSTER) && attacker != world) ⋮ 200 // get mad unless of the same class (except for soldiers) 201 if (self != attacker && attacker != self.enemy) ⋮ 203 if ( (self.classname != attacker.classname) 204 || (self.classname == "monster_army" ) ) ⋮ 206 if (self.enemy.classname == "player") 207 self.oldenemy = self.enemy; 208 self.enemy = attacker;
qcc/v101qc/combat.qc lines 198–210 at c0d1b91 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
Sources
Code
- Software, id. 2024. “DOOM: the Linux source release (id-Software/DOOM, linuxdoom-1.10).” Commit a77dfb9. id-Software/DOOM @ a77dfb9 · licence, all uses
- Software, id. 2012. “Quake II: the GPL source release (id-Software/Quake-2, 3.19).” Commit 372afde. id-Software/Quake-2 @ 372afde · licence, all uses
- Software, id. 2012. “Quake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc).” Commit c0d1b91. id-Software/Quake-Tools @ c0d1b91 · licence, all uses