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

A difficulty level is chosen before play, unlike a difficulty ramp, which raises the challenge as play goes on. Doom halves the damage the player takes on its easiest skill1. Quake II does the same on Easy outside deathmatch, and its skill levels also remove the entities a map flags against them2. Perfect Dark keeps a table of multipliers per difficulty: a guard’s hit costs the player half as much on Agent, and the player’s shots count double there3. The same table sets the autoaim margin4.

  • Damage halvedDoom (1993). The easiest skill halves the damage the player takes.1Quake II (1997). Outside deathmatch, Easy halves the damage a player takes and each skill removes the entities flagged against it.2
  • Table of scalesPerfect Dark (2000). Each solo difficulty sets multipliers for damage taken and dealt, enemy accuracy, autoaim, and ammo, and Agent eases off further at low health.3,4

Games

GameYearHowNote
Doom1993Damage halvedthe easiest skill halves the damage the player takes
Quake II1997Damage halvedoutside deathmatch, Easy halves the damage a player takes and each skill removes the entities flagged against it
Perfect Dark2000Table of scaleseach solo difficulty sets multipliers for damage taken and dealt, enemy accuracy, autoaim, and ammo, and Agent eases off further at low health
Every claim about this mechanic, by game (2)

References

  1. ^ abDamage to a Doom player is halved on the easiest skill (sk_baby), and then armor takes a share: a third with the armor pickup (type 1) and half with the MegaArmor (type 2), until its points run out; monsters have no armor or defense value.Codeid-Software/DOOM
    How we know
    798    player = target->player;
    799    if (player && gameskill == sk_baby)
    800	damage >>= 1; 	// take half damage in trainer mode
    
    linuxdoom-1.10/p_inter.c lines 798–800 at a77dfb9 · upstream ↗
    854	if (player->armortype)
    ⋮
    856	    if (player->armortype == 1)
    857		saved = damage/3;
    858	    else
    859		saved = damage/2;
    ⋮
    861	    if (player->armorpoints <= saved)
    ⋮
    863		// armor is used up
    864		saved = player->armorpoints;
    865		player->armortype = 0;
    ⋮
    867	    player->armorpoints -= saved;
    868	    damage -= saved;
    
    linuxdoom-1.10/p_inter.c lines 854–869 at a77dfb9 · upstream ↗
    370      case SPR_ARM1:
    371	if (!P_GiveArmor (player, 1))
    ⋮
    376      case SPR_ARM2:
    377	if (!P_GiveArmor (player, 2))
    
    linuxdoom-1.10/p_inter.c lines 370–380 at a77dfb9 · upstream ↗
    80#define GOTARMOR	"Picked up the armor."
    81#define GOTMEGA	"Picked up the MegaArmor!"
    
    linuxdoom-1.10/d_englsh.h lines 80–81 at a77dfb9 · upstream ↗
    886    // do the damage	
    887    target->health -= damage;	
    
    linuxdoom-1.10/p_inter.c lines 886–887 at a77dfb9 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  2. ^ abOn Easy (skill 0) outside deathmatch, Quake II's T_Damage halves the damage a player takes, to no less than 1; the knockback is worked out separately and isn't halved. Levels also pick their entities by skill: an entity flagged not-easy, not-medium, or not-hard is removed at load on that skill, with Nightmare (3) counted as hard.Codeid-Software/Quake-2
    How we know
    404	// easy mode takes half damage
    405	if (skill->value == 0 && deathmatch->value == 0 && targ->client)
    ⋮
    407		damage *= 0.5;
    408		if (!damage)
    409			damage = 1;
    
    game/g_combat.c lines 404–410 at 372afde · upstream ↗
    428// figure momentum add
    ⋮
    444				VectorScale (dir, 500.0 * (float)knockback / mass, kvel);
    
    game/g_combat.c lines 428–446 at 372afde · upstream ↗
    585			else
    ⋮
    587				if ( /* ((coop->value) && (ent->spawnflags & SPAWNFLAG_NOT_COOP)) || */
    588					((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) ||
    589					((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
    590					(((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))
    ⋮
    593						G_FreeEdict (ent);	
    
    game/g_spawn.c lines 585–593 at 372afde · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  3. ^ abSolo Perfect Dark scales damage by difficulty in lv_update_solo_handicaps, which runs every tick: a guard's hit on the player is multiplied by 0.5 on Agent, 0.6 on Special Agent, and 1 on Perfect Agent (and on the Perfect Dark difficulty, times its own enemy-damage setting); the player's shots are doubled on Agent; and explosions hurt the player 0.25 times on Agent and 0.75 times on Special Agent. On Agent the scales for the damage the player takes, from guards and from explosions, shrink further once health plus shield is at or below 0.6, falling linearly to half at 0.125, so 0.25 for a guard's hit (computed); the player's ×2 on its own shots stays fixed. Doom halves all damage to the player on its easiest skill, sk_baby.Coderyandwyer/perfect-dark · id-Software/DOOMrevised
    How we know
    1840	} else {
    1841		if (g_Difficulty == DIFF_A) {
    1842			f32 totalhealth;
    1843			f32 frac = 1;
    ⋮
    1846				totalhealth = player_get_health_frac() + player_get_shield_frac();
    ⋮
    1848				if (totalhealth <= 0.125f) {
    1849					frac = 0.5f;
    1850				} else if (totalhealth <= 0.6f) {
    1851					frac = (totalhealth - 0.125f) * 0.5f / 0.47500002384186f + 0.5f;
    ⋮
    1861			g_PlayerDamageRxScale = 0.5f * frac;
    1862			g_PlayerDamageTxScale = 2;
    1863			g_ExplosionDamageTxScale = 0.25f * frac;
    
    src/game/lv.c lines 1840–1866 at 46d3393 · upstream ↗
    1867		} else if (g_Difficulty == DIFF_SA) {
    ⋮
    1874			g_PlayerDamageRxScale = 0.6f;
    1875			g_PlayerDamageTxScale = 1;
    1876			g_ExplosionDamageTxScale = 0.75f;
    
    src/game/lv.c lines 1867–1876 at 46d3393 · upstream ↗
    1884		} else if (g_Difficulty == DIFF_PA) {
    ⋮
    1891			g_PlayerDamageRxScale = 1;
    1892			g_PlayerDamageTxScale = 1;
    1893			g_ExplosionDamageTxScale = 1;
    
    src/game/lv.c lines 1884–1893 at 46d3393 · upstream ↗
    1901		} else if (g_Difficulty == DIFF_PD) {
    ⋮
    1908			g_PlayerDamageRxScale = 1;
    1909			g_PlayerDamageTxScale = 1;
    1910			g_ExplosionDamageTxScale = 1;
    
    src/game/lv.c lines 1901–1910 at 46d3393 · upstream ↗
    2297		lv_update_solo_handicaps();
    
    src/game/lv.c line 2297 at 46d3393 · upstream ↗
    4390	// Apply damage scaling based on difficulty settings
    4391	if (g_Vars.mplayerisrunning == false) {
    4392		// Solo
    4393		if (explosion) {
    4394			if (vprop->type == PROPTYPE_PLAYER) {
    4395				damage *= g_ExplosionDamageTxScale;
    ⋮
    4397		} else if (aprop && aprop->type == PROPTYPE_PLAYER) {
    4398			// Player is attacking
    4399			damage *= g_PlayerDamageTxScale;
    4400			headshotdamagescale = 25;
    4401		} else if (aprop && aprop->type == PROPTYPE_CHR && vprop->type == PROPTYPE_PLAYER) {
    4402			// Chr is attacking player
    ⋮
    
    src/game/chraction.c lines 4390–4404 at 46d3393 · upstream ↗
    27f32 pdmode_get_enemy_damage(void)
    ⋮
    29	if (g_MissionConfig.pdmode) {
    30		return g_MissionConfig.pdmodedamagef;
    ⋮
    33	return 1;
    
    src/game/pdmode.c lines 27–33 at 46d3393 · upstream ↗
    798    player = target->player;
    799    if (player && gameskill == sk_baby)
    800	damage >>= 1; 	// take half damage in trainer mode
    
    linuxdoom-1.10/p_inter.c lines 798–800 at a77dfb9 · 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

  4. ^ abIn solo Perfect Dark the autoaim margin (perfect-dark/autoaim) is multiplied by g_AutoAimScale, which lv_update_solo_handicaps sets by difficulty: 1.5 on Agent, 0.75 on Special Agent, 0.2 on Perfect Agent, and 1 on the Perfect Dark difficulty; the ntsc-final build takes the non-Japanese values (g_Jpn is false). Co-op and Counter-Operative use their own values.Coderyandwyer/perfect-dark
    How we know
    1840	} else {
    1841		if (g_Difficulty == DIFF_A) {
    ⋮
    1864			g_AutoAimScale = 1.5f;
    
    src/game/lv.c lines 1840–1864 at 46d3393 · upstream ↗
    1867		} else if (g_Difficulty == DIFF_SA) {
    ⋮
    1877#if VERSION >= VERSION_JPN_FINAL
    1878			g_AutoAimScale = 0.75f;
    1879#else
    1880			g_AutoAimScale = g_Jpn ? 1.1f : 0.75f;
    1881#endif
    
    src/game/lv.c lines 1867–1881 at 46d3393 · upstream ↗
    1884		} else if (g_Difficulty == DIFF_PA) {
    ⋮
    1897			g_AutoAimScale = g_Jpn ? 0.75f : 0.2f;
    1898#endif
    
    src/game/lv.c lines 1884–1898 at 46d3393 · upstream ↗
    1901		} else if (g_Difficulty == DIFF_PD) {
    ⋮
    1911			g_AutoAimScale = 1;
    
    src/game/lv.c lines 1901–1911 at 46d3393 · upstream ↗
    53#if VERSION >= VERSION_PAL_BETA
    54bool g_Jpn = VERSION == VERSION_JPN_FINAL ? true : false;
    
    src/game/lang.c lines 53–54 at 46d3393 · upstream ↗
    66bool g_Jpn = false;
    
    src/game/lang.c line 66 at 46d3393 · upstream ↗
    2451				if (!g_Vars.normmplayerisrunning) {
    2452					sp48 = sp48 * g_AutoAimScale;
    
    src/game/prop.c lines 2451–2453 at 46d3393 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

Sources

Code