On this page
  1. Related
  2. Games
  3. References
  4. Sources

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

GameYearHowNote
Doom1993Retaliationa 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 II1997Same kinda 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

  1. ^ 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_Chase lowers it by 1 per call and clears it at once when the target is gone or dead.Codeid-Software/DOOMrevised
    How 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 M34
    
    linuxdoom-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.

    In the claim ledger

  2. ^ 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.

    In the claim ledger

  3. ^ abWhen a monster survives damage from another monster, Quake II's M_ReactToDamage makes 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-Toolsrevised
    How 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.

    In the claim ledger

Sources

Code