Smart Calculators

Smart

Calculators

ZDoom Damage and DPS Calculator

Compute exact damage range, expected DPS and time-to-kill for any ZDoom / GZDoom weapon or projectile. Includes the random(1,8) multiplier, STRIFEDAMAGE flag, and a tic-to-seconds converter for ACS scripts.

ZS>ZDoom Damage and DPS

Damage range, DPS & tic converter for Doom modders.

Compute min/avg/max damage for any projectile, hitscan weapon or custom DamageFunction.

Damage formula

Uses Damage × random(1, 8) — the standard ZDoom projectile formula.

Pick a vanilla Doom projectile to autofill Damage. Editing Damage afterwards switches the preset back to Custom.

dmg

The N you put after Damage in DECORATE/ZScript (e.g. Damage 3 on the imp fireball).

Strife-style multiplier: damage × random(1, 4) instead of × random(1, 8). Works on any actor in any ZDoom mod regardless of base game.

Expected damage per hit
13.5
3–24 per hit, avg 13.5
Damage 3 × random(1, 8)
Minimum damage per hit
3
Maximum damage per hit
24

Damage distribution

random(1, N) is uniform — every multiplier is equally likely.

Damage distribution3691215182124Damage per hitProbabilityExpected (13.5)
Damage distribution data table for screen readers.
Damage per hitProbability
312.5%
612.5%
912.5%
1212.5%
1512.5%
1812.5%
2112.5%
2412.5%

Vanilla projectile reference

Click a row to load it into the inputs above.

ProjectileDamageMultiplierMinMaxAvgSpeed (mu/tic)
Imp fireball — DoomImpBall3× random(1, 8)32413.510
Cacodemon ball — CacodemonBall5× random(1, 8)54022.510
Arachnotron plasma — ArachnotronPlasma5× random(1, 8)54022.525
Plasma rifle ball — PlasmaBall5× random(1, 8)54022.525
Baron of Hell / Hell Knight ball — BaronBall8× random(1, 8)8643615
Mancubus fireball — FatShot8× random(1, 8)8643620
Revenant tracer (homing) — RevenantTracer10× random(1, 8)10804510
Rocket (direct hit) — Rocket20× random(1, 8)201609020
BFG spray (per ray)67× 1..8 loop1512067.5
BFG ball (direct hit) — BFGBall100× random(1, 8)10080045025

DECORATE/ZScript snippet that reproduces these numbers.

ACTOR CustomProjectile : DoomImpBall
{
Damage 3
// Min 3 Max 24 Avg 13.5 (× random(1, 8))
}
Updated May 11, 2026
OpenTTD Cargo Income CalculatorGenshin Pity Calculator

ZDoom damage calculator. Damage range, DPS and tics for Doom modders.

A ZDoom damage calculator turns a Damage value into the min, average and max it rolls in-game, the expected DPS, and tics for ACS Delay() math. It bundles the random multiplier, the STRIFEDAMAGE flag, vanilla projectile and hitscan presets, a 19-monster HP table, and the tic to seconds converter on one page.

What is the ZDoom Damage and DPS Calculator?

The ZDoom Damage and DPS Calculator is a web tool that, given a Damage property, a weapon or projectile preset, and an attack rate, returns the exact damage range, expected DPS, shots-to-kill against any vanilla Doom or Doom II monster, and the tic count that an ACS Delay() call would need. It targets ZDoom and GZDoom (the source ports where DECORATE and ZScript actors live), reproduces the engine math used since the 1997 id Software source release, and treats the three highest-volume modder questions as three modes inside one page.
The core source of confusion the calculator removes is the random multiplier. By default, a projectile with Damage 3 does not hit for 3 damage in-game — it hits for 3 multiplied by a random integer from 1 to 8, so the imp's fireball lands somewhere in the 3 to 24 range with an expected value of 13.5 per hit. A custom projectile written with Damage 10 in the Default block deals 10, 20, 30, 40, 50, 60, 70 or 80, never exactly 10. The +STRIFEDAMAGE flag swaps the multiplier to random(1, 4) — same Damage 10 now lands at 10, 20, 30 or 40. The hitscan weapons take a separate path: the pistol, shotgun and chaingun all use 5 multiplied by random(1, 3) per pellet (5, 10 or 15), and the fist and chainsaw use 2 multiplied by random(1, 10). The Damage property on a hitscan actor is ignored — the formula is hardcoded inside the weapon's action function. The Berserk powerup multiplies fist damage by 10 after the random roll; nothing else benefits.
Mode 2 turns those per-shot ranges into expected DPS. Enter the per-pellet damage, the pellet count, the tics per attack (the state duration the actor sits in between shots), and pick a target — Zombieman at 20 HP, Cacodemon at 400, Spider Mastermind at 3000, Cyberdemon at 4000, or any of the 19 vanilla monsters from the ZScript actor definitions. The calculator returns expected damage per shot, expected DPS, expected shots-to-kill, time-to-kill in seconds, and best-case and worst-case kill counts so you know the full kill range, not just the average. A DamageFactor input handles the resistance and vulnerability case (DamageFactor 0.5 halves all damage, 2.0 doubles it, 0 makes the target invulnerable).
Mode 3 covers two converters Doom modders need every time they touch an ACS script or balance a projectile's travel time. The first converts between tics and seconds using TICRATE = 35 — so Delay(35 * 2) is exactly two seconds in modern GZDoom (v3.2.2 and later), 35 tics ago it would have measured 0.98 seconds because of an integer-division precision quirk. The second converts a projectile's Speed property (in map units per tic) into map units per second, meters per second, km per hour and mph, using the canonical 16 horizontal map units = 1 foot ratio. Pair Speed with a target distance and you also get the projectile's travel time, rounded up to the next tic the way the engine actually steps.

How to calculate ZDoom damage, DPS and tic conversions (and how the calculator does it)

There are three independent calculations bundled here, because three questions recur in every DECORATE / ZScript / ACS thread. The calculator above runs all three on every input change; the manual version below is the one you use on paper to sanity-check a projectile before re-launching the WAD.
Using the tool
1. Pick a mode at the top: Damage range, DPS and time-to-kill, or Tic and speed converter. Each mode preserves its own inputs when you switch.
2. Damage range mode. Choose the sub-mode that matches your actor. Projectile sub-mode takes a Damage value plus the optional +STRIFEDAMAGE toggle and outputs Damage times 1 (min), Damage times 4.5 (avg) and Damage times 8 (max). Hitscan sub-mode takes a weapon preset and a pellet count — the per-pellet formula is hardcoded. Custom sub-mode takes a free-form min and max if you are using a DamageFunction expression. Pick a preset projectile (imp fireball, cacodemon ball, plasma rifle ball, rocket, BFG ball, BFG spray ray, and six more) to auto-fill Damage from the vanilla actor's Default block.
3. DPS mode. Enter per-pellet damage, the formula type (projectile, STRIFEDAMAGE or hitscan), pellet count, tics per attack, and pick a monster from the 19-row vanilla preset list (or type a custom HP). The advanced accordion exposes DamageFactor and a per-target HP override. The result hero shows expected DPS and expected shots-to-kill; secondary cards add time-to-kill in seconds, best-case shots (max damage rolls every time) and worst-case shots (min damage rolls every time).
4. Tic and speed mode. Type a tic count to see the matching seconds, or vice versa. Below, enter a Speed value (map units per tic) and an optional distance in map units to get the speed in mu per second, m per second, km per hour and mph, plus the travel time in tics and seconds.
Doing the math by hand
1. Projectile damage range: min = $D$, max = $D \times 8$, expected = $D \times 4.5$. With +STRIFEDAMAGE: max = $D \times 4$, expected = $D \times 2.5$. The distribution is uniform — every multiplier from 1 through 8 (or 1 through 4) is equally likely.
2. Hitscan damage per pellet: pistol / shotgun / chaingun = $5 \times \text{random}(1, 3)$, mean 10 per pellet. Fist / chainsaw = $2 \times \text{random}(1, 10)$, mean 11. Berserk multiplies fist damage by 10 after the roll. Multiply by pellet count for total: shotgun 7, super shotgun 20, everything else 1.
3. Expected DPS: $\text{DPS} = \frac{\text{expected damage per shot} \times 35}{\text{tics per attack}}$. The 35 is TICRATE; tics per attack is the sum of state durations between consecutive A_FireProjectile or A_FireBullets calls in your actor's States block.
4. Shots-to-kill: $\lceil \frac{\text{HP}}{\text{expected damage per shot} \times \text{damageFactor}} \rceil$. Time-to-kill: shots-to-kill multiplied by tics-per-attack divided by 35.
5. Tics to seconds: tics divided by 35. Seconds to tics: round(seconds times 35). For Delay() in ACS, write `Delay(35 * seconds)` directly — the engine handles the multiplication.
6. Projectile travel: tics = $\lceil \frac{\text{distance in mu}}{\text{Speed}} \rceil$, seconds = tics divided by 35. The engine moves projectiles in integer steps, so always round up. Real-world speed: $\text{mph} \approx \text{Speed} \times 1.49$, $\text{km/h} \approx \text{Speed} \times 2.4$, $\text{m/s} \approx \text{Speed} \times 0.667$.
Worked reproduction of the default scenario: a Damage 3 imp fireball hits a Cacodemon (HP 400). Per-shot expected damage = $3 \times 4.5 = 13.5$. Cacodemon HP 400 divided by 13.5 = 29.6, so expected shots-to-kill = 30. The same Cacodemon takes between 2 and 4 super shotgun blasts (best case 2, worst case 4, expected 2) because each blast averages 200 damage with the canonical 20-pellet formula — a 15x per-shot gap that translates directly into how many seconds you spend on the Cacodemon depending on which weapon is in your hand.

Damage, DPS and tic conversion — the engine formulas

damagemin=Dmmin,damagemax=Dmmax,E[damage]=Dmmin+mmax2DPS=E[damage per shot]35tattack,shots=HE[damage per shot]ftics=round(s35),travel=dv\begin{aligned} \text{damage}_{\min} &= D \cdot m_{\min}, \quad \text{damage}_{\max} = D \cdot m_{\max}, \quad \mathbb{E}[\text{damage}] = D \cdot \tfrac{m_{\min} + m_{\max}}{2} \\ \text{DPS} &= \frac{\mathbb{E}[\text{damage per shot}] \cdot 35}{t_{\text{attack}}}, \quad \text{shots} = \left\lceil \frac{H}{\mathbb{E}[\text{damage per shot}] \cdot f} \right\rceil \\ \text{tics} &= \text{round}(s \cdot 35), \quad \text{travel} = \left\lceil \frac{d}{v} \right\rceil \end{aligned}
  • DD = Damage property from the DECORATE or ZScript actor's Default block (an integer)
  • mmin,mmaxm_{\min}, m_{\max} = Random multiplier bounds — 1 and 8 by default; 1 and 4 with +STRIFEDAMAGE; 1 and 3 for pistol/shotgun/chaingun pellets; 1 and 10 for fist/chainsaw
  • tattackt_{\text{attack}} = Tics per attack — the state-machine duration between consecutive fire calls in the actor's States block
  • HH = Target HP — 20 for Zombieman, 60 for Imp, 400 for Cacodemon, 1000 for Baron of Hell, 3000 for Spider Mastermind, 4000 for Cyberdemon
  • ff = DamageFactor multiplier — 1.0 normal, 0.5 resistance, 2.0 vulnerability, 0.0 invulnerable
  • ss = Time in seconds — multiplied by TICRATE = 35 and rounded to integer tics for state durations and Delay() arguments
  • d,vd, v = Travel distance in map units and projectile Speed in map units per tic; ceiling division gives tics because the engine moves in integer steps
The 35 in the DPS denominator is TICRATE, the constant id Software locked at the top of doomdef.h in 1993 and that ZDoom, GZDoom and every Doom source port preserve verbatim. The same constant drives every state-machine duration in DECORATE and ZScript: a TNT1 A 24 state lasts 24 tics, the per-attack interval that goes into the DPS denominator. The BFG spray formula is the one exception to the uniform random(1, 8) rule — it sums fifteen independent random(1, 8) rolls per ray, so the per-ray range is 15 to 120 with an expected value of 67.5; a BFG ball releases up to 40 rays. The Berserk fist multiplier is applied after the random(1, 10) roll, so a Berserked punch lands in the 20 to 200 range with an expected value of 110.

Worked examples with the full math

Imp fireball vs Cacodemon — the default scenario

Imp fireball has Damage 3 in the DoomImpBall actor's Default block. Per-shot range = 3 to 24 (3 multiplied by 1 to 8), expected = 13.5. Cacodemon HP = 400 (from the Cacodemon actor's Health property). Expected shots-to-kill = $\lceil 400 / 13.5 \rceil$ = 30. Worst-case shots (every roll lands minimum) = $\lceil 400 / 3 \rceil$ = 134. Best-case shots (every roll lands maximum) = $\lceil 400 / 24 \rceil$ = 17. That 17 to 134 range surprises new modders — the random multiplier is the dominant variable, far more than damage scaling. A Damage 6 fireball cuts the expected count in half (15 shots) but the worst-case shrinks only to 67.

Pistol DPS against a Zombieman — "is the pistol really worthless"

Pistol formula: $5 \times \text{random}(1, 3)$ per shot, pellet count 1. Per-shot range = 5 to 15, expected = 10. A_FirePistol fires at ~150 shots/minute in vanilla Doom (~14 tics per cycle). DPS = $10 \times 35 / 14$ ≈ 25 expected damage per second. Zombieman HP = 20. Expected shots-to-kill = $\lceil 20 / 10 \rceil$ = 2. Best-case = 2 shots (back-to-back 15s), worst-case = 4 shots (four 5s). Time-to-kill at 14 tics per attack = $2 \times (14/35) = 0.8$ seconds expected, up to 1.6 seconds worst case. The pistol is not worthless — it kills Zombiemen in 2 shots and chips Imps in 6 — but its DPS is roughly a third of the chaingun's (same per-shot formula, ~4 tics per attack instead of 14) and a tenth of the rocket launcher's, which is why the chaingun replaces it the moment you find one.

Super shotgun on a Hell Knight — point-blank reality

Super shotgun formula: $5 \times \text{random}(1, 3)$ per pellet, pellet count 20. Per-blast range = 100 to 300, expected = 200. Hell Knight HP = 500. Expected blasts-to-kill = $\lceil 500 / 200 \rceil$ = 3. Worst-case = $\lceil 500 / 100 \rceil$ = 5 blasts (every pellet rolls 1). Best-case = $\lceil 500 / 300 \rceil$ = 2 blasts (every pellet rolls 3). A_FireShotgun2 cycles at ~36.8 shots/minute (about 57 tics per attack including load and reload), so time-to-kill at 3 blasts = $3 \times (57/35) \approx 4.9$ seconds. This matches the forum consensus that two blasts drop Hell Knights only if you get lucky with the rolls; three is the realistic plan.

BFG ball direct hit on a Cyberdemon (no spray)

BFG ball Damage = 100 in the BFGBall actor. Per-direct-hit range = 100 to 800, expected = 450. Cyberdemon HP = 4000, no splash. Expected direct hits = $\lceil 4000 / 450 \rceil$ = 9. Best-case = $\lceil 4000 / 800 \rceil$ = 5 hits. Worst-case = $\lceil 4000 / 100 \rceil$ = 40 hits (every roll lands the minimum). The wiki's "three to four BFG hits kills a Cyberdemon" advice assumes the spray rays are also connecting — and that the player's distance keeps the Cyberdemon inside the spray cone. The spray contribution is what makes the BFG efficient: a single full-coverage ball + 40-ray spray averages 450 + 40 multiplied by 67.5 = 3150 expected damage in one trigger pull, which puts the Cyberdemon down in 2 if you nail both the direct hit and the cone.

ACS Delay math — "how many tics is 2.5 seconds"

Tics per second = 35. Seconds to tics for 2.5 seconds = $\text{round}(2.5 \times 35)$ = round(87.5) = 88 tics. In ACS: write `Delay(35 * 25 / 10)` if you want to keep the arithmetic readable, or just `Delay(88)`. The most common values modders memorise: 0.1 s = 4 tics, 0.5 s = 18 tics, 1 s = 35 tics, 1.5 s = 53 tics, 2 s = 70 tics, 3 s = 105 tics, 5 s = 175 tics, 10 s = 350 tics. Imp fireball Speed = 10 map units per tic. Travel time across 1024 map units = $\lceil 1024 / 10 \rceil$ = 103 tics ≈ 2.94 seconds, or about 15 mph (10 multiplied by 1.49 ≈ 14.9). The plasma rifle ball at Speed 25 covers the same 1024 mu in 41 tics ≈ 1.17 seconds, or about 60 km/h.

ZDoom damage and balance tips for modders, mappers and curious players

  • Read your actor's Damage property in expected-value terms, not literal-value terms. A projectile with Damage 5 averages 22.5 in-game (5 multiplied by 4.5), not 5. If your new monster's fireball is supposed to compete with the imp's 13.5-average fireball, set Damage 3 — not Damage 10. The #1 balance mistake in DECORATE is reading Damage 10 as "this hits for 10" when it actually hits for 10 to 80 with a 45 average.
  • The +STRIFEDAMAGE flag is the lowest-overhead way to tighten a projectile's range. Same Damage value, max multiplier drops from 8 to 4, expected value drops from 4.5x to 2.5x. Useful when you want a predictable mid-range projectile (e.g. a custom rocket that should always feel like 60 to 240 instead of 60 to 480). It works on any actor in any ZDoom mod regardless of base game — the name comes from Strife (the engine's first non-Doom IWAD) but the flag itself is portable.
  • Hitscan weapons ignore the Damage property entirely. Pistol, shotgun, chaingun, super shotgun all hardcode $5 \times \text{random}(1, 3)$ per pellet inside their A_FireBullets / A_FirePistol / A_FireShotgun calls. To raise a hitscan weapon's damage you change the pellet count, the A_CustomBulletAttack damage argument, or convert to projectile. The fist and chainsaw use $2 \times \text{random}(1, 10)$; the only way Berserk affects damage is on the fist, where it multiplies by 10 after the roll (so 20 to 200 per punch, expected 110).
  • Tics per attack matters more than per-shot damage for DPS comparisons. The chaingun and the pistol have identical per-shot damage (5 to 15, expected 10), but the chaingun fires at ~4 tics per attack vs the pistol's ~14 — roughly 3.5x the DPS for the same per-pellet math. When balancing a weapon mod, decide DPS first (vanilla pistol ~25 DPS, shotgun ~70, super shotgun ~150, chaingun ~88, plasma ~263, rocket direct ~159), then back out the per-shot damage and the tics per attack that produce it.
  • Use the 19-monster cheat-sheet to gut-check encounter design. Zombieman (HP 20), Shotgun Guy (30), Wolfenstein SS (50), Imp (60), Chaingunner (70), Lost Soul / Commander Keen (100), Demon / Spectre (150), Revenant (300), Pain Elemental / Cacodemon (400), Hell Knight / Arachnotron (500), Mancubus (600), Arch-vile (700), Baron of Hell (1000), Spider Mastermind (3000), Cyberdemon (4000). A super shotgun blast (expected 200, max 300) one-shots everything up to Revenant (HP 300) in the best case; Pain Elemental and Cacodemon (HP 400) need at least two best-case blasts. A pistol shot (expected 10) only one-shots a Zombieman. Designing a map's first encounter around a Demon vs a Mancubus is a 4x difficulty jump, not a 1.5x jump — the HP curve is geometric, not linear.
  • GZDoom v3.2.2 (late 2017) and later guarantee that 35 tics equal exactly one second of real time. Earlier versions display a tic interval of 28 ms (so 35 tics show as 0.98 seconds) because of an integer-division truncation in the timer code. If your ACS Delay() math needs sub-second precision and you target a pre-late-2017 player base, account for the 2% drift — `Delay(35 * 60)` is 58.8 wall-clock seconds on the legacy timer, 1.2 seconds short of a full real-world minute.
  • BFG spray is the one projectile that does not follow $\text{Damage} \times \text{random}(1, 8)$. Inside the A_BFGSpray function, the per-ray damage is computed as the sum of 15 independent random(1, 8) rolls — so range is 15 to 120, expected 67.5, distribution bell-shaped (not uniform). A BFG ball releases up to 40 rays in a 90-degree forward cone, so a full-coverage hit can stack 40 multiplied by 67.5 = 2700 expected damage on top of the ball's own 100 to 800. This is why a single BFG trigger pull can two-shot a Cyberdemon when both the direct ball and the spray cone connect.
  • Map units have two conversion rates, not one. Horizontally, 16 map units equal one foot (0.3048 m); vertically, only 10 map units equal one foot because Doom's original 320x200 video mode stretched 20% vertically. For projectile speed conversions the calculator uses the horizontal ratio because projectiles travel along the map plane: Speed 10 (imp fireball) ≈ 6.67 m/s ≈ 15 mph; Speed 25 (plasma, BFG ball) ≈ 16.67 m/s ≈ 60 km/h ≈ 37 mph. Doomguy's running speed is around Speed 16 — about 24 mph, which is why imps occasionally outrun you in a corridor.
  • DamageFactor handles resistance and vulnerability without rewriting your damage code. DamageFactor 'Fire', 0.5 on a monster halves all Fire-typed damage; DamageFactor 'Fire', 2.0 doubles it; DamageFactor 'Fire', 0 makes the monster fully immune. The calculator's DPS mode exposes a single scalar DamageFactor input so you can model the resistant case without a custom damage type — useful when you are comparing a vanilla weapon's TTK against, say, a Cacodemon variant with 0.7 plasma resistance.
  • Range and worst-case numbers matter more than averages for survival math. "Expected shots-to-kill = 30" hides the fact that a Cacodemon can survive 134 imp fireballs in the pathological worst case. The calculator surfaces best/worst alongside expected for exactly this reason — when you are designing a slaughter map and an arena's monster has to die in a strict shot budget, you size to the worst case, not the expected. When you are designing a casual map, you size to the expected. The two numbers can differ by a factor of 5 to 10 for random(1, 8) projectiles.

ZDoom damage calculator — frequently asked questions

Why does my Damage 10 projectile hit for 80 sometimes?

ZDoom multiplies a projectile's Damage property by random(1, 8) on every hit. Damage 10 yields 10, 20, 30, 40, 50, 60, 70 or 80 — every value equally likely. Average is 45. The +STRIFEDAMAGE flag changes the multiplier to random(1, 4), giving 10, 20, 30 or 40 with an average of 25.

What is the formula for pistol damage in classic Doom?

The pistol uses 5 multiplied by random(1, 3) per shot, so each shot deals 5, 10 or 15 damage with an expected value of 10. The chaingun and the shotgun (per pellet) use the same formula. The Damage property on a hitscan actor is ignored — the formula is hardcoded inside A_FirePistol, A_FireShotgun and A_FireCGun.

How many tics is one second in ZDoom?

35 tics per second. TICRATE has been locked at 35 since the original 1993 release. GZDoom v3.2.2 and later guarantee that 35 tics equal exactly 1.000 seconds of real time; earlier versions truncated to 28 ms per tic so 35 tics displayed as 0.98 seconds — a 2% drift that only matters for long Delay() sequences.

How do I calculate ACS Delay() for X seconds?

Multiply seconds by 35 and round to an integer. 0.5 s = 18 tics, 1 s = 35 tics, 2 s = 70 tics, 5 s = 175 tics, 10 s = 350 tics, 60 s = 2100 tics. In ACS write Delay(35 * seconds) directly — the engine does the multiplication at compile time.

What does the +STRIFEDAMAGE flag do?

+STRIFEDAMAGE swaps the projectile damage multiplier from random(1, 8) to random(1, 4). Same Damage value, narrower range, lower average. It works on any actor in any ZDoom mod regardless of base game — the name comes from Strife but the flag is portable. Useful when you want a predictable mid-range projectile.

How much HP does a Cyberdemon have?

4000 HP. Cyberdemons take only direct damage — splash damage from rockets and Mancubus shots does nothing. The BFG9000 is the canonical kill (about 2 to 4 trigger pulls including spray); 20 expected super shotgun blasts at point-blank or ~45 expected rocket direct hits also do the job if you have the ammo. The calculator's 19-row monster table lists every vanilla Doom HP value.

Why is BFG damage so weird — what is the 15× loop?

The BFG main ball uses the standard formula (Damage 100 multiplied by random(1, 8) = 100 to 800), but the spray tracers do not. Each of up to 40 rays sums 15 independent random(1, 8) rolls, yielding 15 to 120 per ray with an average of 67.5. The Doom Wiki notes that pseudorandom-table determinism narrows the in-practice range to 49 to 87, but theoretical max remains 120 per ray.

Does this calculator work for ZScript actors too?

Yes. ZScript and DECORATE share the same Damage / DamageFunction / Speed / Health / +STRIFEDAMAGE semantics — they differ only in syntax. A ZScript actor with `Damage 5;` in its Default block rolls the exact same 5 multiplied by random(1, 8) formula as a DECORATE actor with the same property. The calculator's outputs apply to both.

Is the pistol really worthless?

No, but it is the worst weapon by DPS. Pistol expected DPS ≈ 25; chaingun ≈ 88 (same per-shot, three times the fire rate); shotgun ≈ 70; super shotgun ≈ 150; plasma rifle ≈ 263. The pistol two-shots Zombiemen and one-shots barrels — useful while you save shells. The moment you find a chaingun the pistol is a backup.

How accurate is this calculator vs the actual game?

Engine-exact for vanilla Doom and Doom II behavior under ZDoom / GZDoom. Engine cross-checks cover every projectile preset, every hitscan weapon, every monster HP value, and the BFG spray 15× loop — every damage range, monster HP and projectile speed matches the vanilla actor definitions to the unit. DECORATE / ZScript replacement actors, custom DamageFunction expressions and the modern Doom titles (2016, Eternal, The Dark Ages) use different math and are out of scope.

Why does the Revenant tracer deal 10 to 80, not 10 to 40?

RevenantTracer has Damage 10 in its actor block but does NOT carry the +STRIFEDAMAGE flag — it uses the default random(1, 8) multiplier. So its range is 10 to 80 with an expected value of 45, not 10 to 40. This is a common point of confusion because Revenant rockets feel like they should follow Strife-style math; they do not.

Does difficulty (UV / Nightmare) increase weapon damage?

No. Nightmare doubles monster aggression and ammo pickups, but weapon damage is identical across all five skill settings. The only damage multiplier that exists in vanilla Doom is the Berserk powerup, which multiplies fist damage by 10. Skill level changes who shoots first and how often, not how hard the shots hit.

Can I bookmark a specific damage scenario to share with another modder?

Yes. The selected mode is reflected in the URL query string (?mode=damage / dps / tics), so bookmarking the page restores that mode on the next visit. Inputs persist across reloads via localStorage, and the three modes — damage range, DPS / time-to-kill, and tic / speed conversion — share the same page so cross-mode lookups stay in one tab.


ZDoom damage and timing glossary

Damage property

A numeric property on a DECORATE or ZScript actor's Default block that the engine multiplies by random(1, 8) on every hit (random(1, 4) with +STRIFEDAMAGE). Setting Damage 10 produces an in-game range of 10 to 80, not a flat 10.

+STRIFEDAMAGE

An actor flag that changes the projectile damage multiplier from random(1, 8) to random(1, 4). Same Damage value, narrower range, lower average (Damage times 2.5 instead of Damage times 4.5). Works on any actor in any ZDoom mod regardless of base game.

tic

The atomic time unit of the Doom engine. TICRATE = 35 tics per second; 1 tic ≈ 28.5714 ms. State durations in DECORATE / ZScript and the argument to ACS Delay() are both expressed in tics. GZDoom v3.2.2+ guarantees 35 tics = exactly 1.000 seconds; earlier versions truncated at 28 ms.

Hitscan weapon

A weapon whose damage is resolved instantly along a straight line, no projectile actor involved. Pistol, shotgun, super shotgun and chaingun are hitscan; their damage formulas are hardcoded in their A_Fire* action functions (5 multiplied by random(1, 3) per pellet) and the Damage property on the actor is ignored.

DamageFactor

A multiplier on incoming damage of a specific damage type. DamageFactor 'Fire', 0.5 halves Fire damage; 2.0 doubles it; 0.0 makes the actor immune. The calculator's DPS mode exposes a single scalar DamageFactor input for the resistant / vulnerable cases.

Berserk

A powerup that multiplies fist damage by 10 after the random(1, 10) roll, yielding a 20 to 200 range with an expected value of 110. Only the fist gets the bonus; chainsaw, hitscan and projectile weapons are unaffected.

Map unit

Doom's spatial coordinate unit. 16 horizontal map units = 1 real-world foot = 0.3048 m, by Doom community consensus (Doomguy is 56 vertical units tall = 5 feet 7 inches). The calculator converts projectile Speed (map units per tic) to m/s, km/h and mph using the 16-mu-per-foot horizontal ratio.

Speed property

A projectile actor's velocity in map units per tic. Imp fireball Speed 10; rocket Speed 20; plasma ball and BFG ball Speed 25. Multiply by 35 to get map units per second; multiply by 0.667 to get meters per second; multiply by 1.49 to get mph.

BFG spray

The 40-ray cone the BFG ball releases on impact (the spray fires from the ball's death state via A_BFGSpray). Each ray's damage is the sum of 15 independent random(1, 8) rolls, yielding 15 to 120 per ray with an expected value of 67.5. The BFG's reputation for one-shotting Cyberdemons is the spray's doing, not the main ball's.

TICRATE

The engine constant locking Doom's frame rate at 35 tics per second since 1993. Defined in id Software's doomdef.h; preserved exactly by ZDoom, GZDoom, Zandronum, Boom, MBF21 and every other vanilla-compatible source port. Every state duration, every Delay() argument, every projectile travel-time computation uses 35 as the conversion constant.

DamageFunction

An alternative to the Damage property that lets a modder return a custom integer at hit time via a ZScript expression. Bypasses the random(1, 8) multiplier — return a flat number for deterministic damage, or compute it from the inflictor / target / distance for context-sensitive behavior.


Content verified by the Smart Calculators Team