Smart Calculators

Smart

Calculators

ZDoom 伤害与 DPS 计算器

计算任何 ZDoom/GZDoom 武器或投射物的精确伤害范围、期望 DPS 与击杀时间。包含 random(1,8) 倍率、STRIFEDAMAGE 旗标,以及给 ACS 脚本用的 tic 与秒互换器。

ZS>ZDoom 伤害与 DPS

毁灭战士 MOD 作者的伤害范围、DPS 与 tic 换算器。

计算任何投射物、扫描枪或自定义 DamageFunction 的最小/平均/最大伤害。

伤害公式

使用 Damage × random(1, 8) — ZDoom 标准投射物公式。

选择原版《毁灭战士》投射物即可自动填入 Damage。事后修改 Damage 会把预设切回自定义。

dmg

DECORATE/ZScript 中 Damage 后面写的 N 值(例如:小鬼火球 Damage 3)。

Strife 风格倍率:伤害 × random(1, 4),取代 × random(1, 8)。在任何 ZDoom MOD 的任何 actor 上都能用,与底层游戏无关。

每次命中期望伤害
13.5
每次命中 3–24,平均 13.5
Damage 3 × random(1, 8)
每次命中最小伤害
3
每次命中最大伤害
24

伤害分布

random(1, N) 是均匀分布——每个倍率概率相同。

伤害分布3691215182124每次命中伤害概率期望值(13.5)
伤害分布数据表(屏幕阅读器专用)。
每次命中伤害概率
312.5%
612.5%
912.5%
1212.5%
1512.5%
1812.5%
2112.5%
2412.5%

原版投射物速查表

点击任意一行即可载入到上方输入栏。

投射物Damage倍率最小最大平均速度(mu/tic)
小鬼火球 — DoomImpBall3× random(1, 8)32413.510
巨脑魔等离子弹 — CacodemonBall5× random(1, 8)54022.510
Arachnotron 等离子弹 — ArachnotronPlasma5× random(1, 8)54022.525
等离子枪球 — PlasmaBall5× random(1, 8)54022.525
地狱男爵/地狱骑士火球 — BaronBall8× random(1, 8)8643615
Mancubus 火球 — FatShot8× random(1, 8)8643620
Revenant 追踪导弹 — RevenantTracer10× random(1, 8)10804510
火箭(直击) — Rocket20× random(1, 8)201609020
BFG 散射(每条光线)67× 1..8 loop1512067.5
BFG 球体(直击) — BFGBall100× random(1, 8)10080045025

可重现这些数值的 DECORATE/ZScript 片段。

ACTOR CustomProjectile : DoomImpBall
{
Damage 3
// Min 3 Max 24 Avg 13.5 (× random(1, 8))
}
更新于 2026年5月11日
OpenTTD 货物收益计算器原神抽卡保底计算器

ZDoom 伤害计算器。给毁灭战士 MOD 作者用的伤害范围、DPS 与 tic 速查表。

ZDoom 伤害计算器把 Damage 值换算成游戏里实际掷出的最小、平均、最大伤害,并算出期望 DPS 与 ACS Delay() 所需 tic 数。随机倍率、+STRIFEDAMAGE 旗标、原版投射物与扫描枪预设、19 个怪物的 HP 表,以及 tic 与秒的换算全部集中在同一页。

ZDoom 伤害与 DPS 计算器是什么?

ZDoom 伤害与 DPS 计算器是一款网页工具:输入一个 actor 的 Damage 属性、武器或投射物预设、攻击间隔,它就会返回精确的伤害范围、期望 DPS、把原版《毁灭战士》/《毁灭战士 II》怪物打到 0 HP 所需的发数,以及 ACS Delay() 调用该写多少 tic。工具锁定 ZDoom 与 GZDoom(DECORATE 与 ZScript actor 真正运行在上面的两个 source port),完整重现 id Software 1997 年开源那一版的引擎算术,把 MOD 作者最常遇到的三个问题用同一页的三个模式一次性解决。
这款计算器要厘清的最大误区就是「随机倍率」。Damage 3 的投射物在游戏里并不是固定打 3 点伤害,而是 3 乘以 1 到 8 之间的一个整数随机数,所以小鬼(Imp)扔出来的火球落在 3 到 24 之间,期望值是每发 13.5 点。Default 区块里写 `Damage 10` 的自制投射物会扔出 10、20、30、40、50、60、70 或 80 中的一个,唯独不会刚好是 10。+STRIFEDAMAGE 旗标把倍率切成 random(1, 4),同样的 Damage 10 就会落在 10、20、30、40 中。扫描枪(hitscan)走另一条代码路径:手枪、霰弹枪、加特林每颗弹丸都是 5 乘以 random(1, 3),也就是 5、10 或 15;拳头与电锯则是 2 乘以 random(1, 10)。扫描枪 actor 上的 Damage 属性会被忽略 — 公式直接写死在武器的 action 函数里。狂暴(Berserk)加成只对拳头生效,在随机数掷完之后再乘以 10,其他武器都吃不到这个 buff。
模式 2 把单发范围转成期望 DPS。输入每颗弹丸的伤害、弹丸数、每次攻击的 tic 数(actor 的 States 区块里两次连续 A_FireProjectile 或 A_FireBullets 调用之间所有 state 的时长总和),再从原版 19 个怪物里挑一个目标:丧尸兵 20 HP、巨脑魔(Cacodemon)400、蜘蛛魔王(Spider Mastermind)3000、机械巨魔(Cyberdemon)4000,或者从 ZScript actor 定义里一字一句抓出来的其余 16 种怪物。计算器返回单发期望伤害、期望 DPS、期望击杀发数、击杀秒数,以及最佳运气(每次都掷到最大)与最差运气(每次都掷到最小)下的击杀发数,让你看到的不只是平均值,而是整个区间。DamageFactor 字段对应抗性与弱点:0.5 表示半伤、2.0 表示双倍受伤、0 表示完全免疫。
模式 3 覆盖两个换算器,是写 ACS 脚本与调整投射物飞行时间时绕不开的工具。第一个用 TICRATE = 35 在 tic 与秒之间互转,所以新版 GZDoom(v3.2.2 之后)里 `Delay(35 * 2)` 就是准确的 2 秒;更早的版本因为计时器内部整数除法截断,同样的 35 tic 会被显示成 0.98 秒。第二个把投射物的 Speed 属性(每 tic 多少 map unit)换成 map unit 每秒、米每秒、公里每小时与英里每小时,采用 Doom 社区公认的「水平方向 16 map units = 1 英尺」比例。在 Speed 旁边填上目标距离,还会得到按引擎规则向上取整到下一个 tic 的飞行时间。

如何计算 ZDoom 的伤害、DPS 与 tic 换算(顺便看看这款计算器在做什么)

国内 Doom MOD 圈讨论(无论是百度贴吧 doom 吧、B 站专栏、CSDN 博客,还是 ZDoom 官方论坛与 Doomworld)反复出现三个问题,所以这里把三组互相独立的算式集中在同一页。上方的计算器每次输入变动都会即时跑完三组;想在重新发布 PK3 之前先在纸上验算,请对照下面这份手算流程。
使用计算器
1. 顶部先选模式:伤害范围、DPS 与击杀时间、tic 与速度换算。每个模式都会单独保留自己的输入。
2. 伤害范围模式。挑一个匹配你 actor 类型的子模式。「投射物」子模式接受 Damage 值与可选的 +STRIFEDAMAGE 开关,返回 Damage × 1(最小)、Damage × 4.5(平均)、Damage × 8(最大)。「扫描枪」子模式接受武器预设与弹丸数,每颗弹丸的公式已经写死。「自定义」子模式直接接受最小值与最大值,方便处理用 DamageFunction 写的复杂表达式。挑一个投射物预设(小鬼火球、巨脑魔等离子球、等离子枪球、火箭、BFG 球体、BFG 散射光线等十款),就会自动从原版 actor 的 Default 区块带入 Damage。
3. DPS 模式。输入每颗弹丸的伤害、公式类型(投射物/STRIFEDAMAGE/扫描枪)、弹丸数、每次攻击的 tic 数,再从 19 行原版怪物清单里挑目标(也可以手动填 HP)。展开「进阶」折叠区即可使用 DamageFactor 与目标 HP 覆盖。主结果卡显示期望 DPS 与期望击杀发数;副卡列出击杀秒数、最佳运气(每次都掷到最大)与最差运气(每次都掷到最小)下的击杀发数。
4. tic 与速度模式。输入 tic 数即可看到对应的秒数,反之亦然。下方输入 Speed(每 tic 多少 map units)与可选的距离(map units),就会得到 map unit 每秒、m/s、km/h、mph,以及 tic 与秒两种单位下的飞行时间。
自己拿纸笔算
1. 投射物伤害范围:min = $D$、max = $D \times 8$、期望值 = $D \times 4.5$。挂上 +STRIFEDAMAGE:max = $D \times 4$、期望值 = $D \times 2.5$。分布为均匀分布,1 到 8(或 1 到 4)每个倍率概率相同。
2. 扫描枪每颗弹丸:手枪/霰弹枪/加特林 = $5 \times \text{random}(1, 3)$,平均 10。拳头/电锯 = $2 \times \text{random}(1, 10)$,平均 11。狂暴对拳头在随机数掷完之后再乘以 10。把每发伤害乘以弹丸数即为总伤害:霰弹枪 7、超级霰弹枪 20,其余为 1。
3. 期望 DPS:$\text{DPS} = \frac{\text{单发期望伤害} \times 35}{\text{每次攻击 tic 数}}$。其中 35 即为 TICRATE,每次攻击 tic 数是 actor 的 States 区块里两次连续开火调用之间所有 state 时长的总和。
4. 击杀发数:$\lceil \frac{\text{HP}}{\text{单发期望伤害} \times \text{damageFactor}} \rceil$。击杀时间:击杀发数 × 每次攻击 tic 数 ÷ 35。
5. tic 换秒:tic ÷ 35。秒换 tic:round(秒 × 35)。在 ACS 里直接写 `Delay(35 * seconds)` 就行,乘法交给引擎在编译期完成。
6. 投射物飞行:tic = $\lceil \frac{\text{距离}}{\text{Speed}} \rceil$,秒 = tic ÷ 35。引擎以整数 tic 为步进,所以一律向上取整。实际速度换算:$\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$。
默认场景的验算:Damage 3 的小鬼火球打巨脑魔(HP 400)。单发期望伤害 = $3 \times 4.5 = 13.5$,400 ÷ 13.5 ≈ 29.6,所以期望击杀 = 30 发。最差运气(每次都最小)= $\lceil 400 / 3 \rceil$ = 134 发。最佳运气(每次都最大)= $\lceil 400 / 24 \rceil$ = 17 发。同一只巨脑魔换成超级霰弹枪只需要 2 到 4 发(最佳 2、最差 4、期望 2),因为 20 颗弹丸的标准公式让单发平均 200 伤害 — 也就是说,从拳头、手枪一路换到 BFG,你花在同一只巨脑魔身上的时间能差到 15 倍。

伤害、DPS 与 tic 换算 — 引擎里的数学

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 = DECORATE 或 ZScript actor 的 Default 区块中声明的 Damage 属性(整数)
  • mmin,mmaxm_{\min}, m_{\max} = 随机倍率上下界 — 默认为 1 与 8;挂 +STRIFEDAMAGE 为 1 与 4;手枪/霰弹枪/加特林的每颗弹丸为 1 与 3;拳头/电锯为 1 与 10
  • tattackt_{\text{attack}} = 每次攻击的 tic 数 — actor 的 States 区块里两次连续开火调用之间 state machine 的时长
  • HH = 目标 HP — 丧尸兵 20、小鬼 60、巨脑魔 400、地狱男爵 1000、蜘蛛魔王 3000、机械巨魔 4000
  • ff = DamageFactor 倍率 — 1.0 正常、0.5 抗性、2.0 弱点、0.0 无敌
  • ss = 以秒为单位的时间 — 乘以 TICRATE = 35 并四舍五入到整数 tic,用作 state 时长或 Delay() 参数
  • d,vd, v = 飞行距离(map units)与投射物 Speed(map units/tic);引擎以整数 tic 为步进,故除法向上取整即为飞行 tic 数
DPS 分母里的 35 就是 TICRATE,id Software 在 1993 年写进 doomdef.h 开头那一行的常数,此后 ZDoom、GZDoom 以及所有 Doom source port 全都原封不动继承下来。同一个常数驱动 DECORATE 与 ZScript 里每一个 state 的时长:`TNT1 A 24` 这样的 state 持续 24 tic,也就是塞进 DPS 分母的「每次攻击 tic 数」。BFG 散射(spray)是 random(1, 8) 规则的唯一例外 — 每条光线的伤害是 15 次独立 random(1, 8) 的总和,所以单条光线范围 15 到 120、期望值 67.5;一颗 BFG 球体最多射出 40 条光线。狂暴的拳头加成是在 random(1, 10) 掷完之后再乘以 10,所以开了狂暴的拳头伤害落在 20 到 200 之间,期望值 110。

完整数字逐步走过的范例

小鬼火球 vs 巨脑魔 — 默认场景

小鬼火球的 actor `DoomImpBall` 在 Default 区块里写的是 Damage 3。单发范围 = 3 到 24(3 乘以 1 到 8),期望值 = 13.5。巨脑魔 HP = 400(来自 `Cacodemon` actor 的 Health 属性)。期望击杀发数 = $\lceil 400 / 13.5 \rceil$ = 30 发。最差运气(每次都最小)= $\lceil 400 / 3 \rceil$ = 134 发。最佳运气(每次都最大)= $\lceil 400 / 24 \rceil$ = 17 发。17 到 134 这个范围每次都能吓到刚入坑的 MOD 作者:随机倍率比 Damage 本身对结果的影响大得多。Damage 改成 6 会把期望直接砍半到 15 发,但最差运气只缩到 67 发。

手枪打丧尸兵的 DPS — 「手枪真的废吗」

手枪公式:每发 $5 \times \text{random}(1, 3)$,弹丸数 1。单发范围 = 5 到 15,期望值 = 10。原版 Doom 里 A_FirePistol 一分钟大约打 150 发(每个循环 14 tic)。DPS = $10 \times 35 / 14$ ≈ 每秒期望 25 点伤害。丧尸兵 HP = 20,期望击杀 = $\lceil 20 / 10 \rceil$ = 2 发。最佳 2 发(连两次掷到 15),最差 4 发(连四次掷到 5)。每次攻击 14 tic 之下,击杀秒数 = $2 \times (14/35) = 0.8$ 秒(期望),最差 1.6 秒。手枪并不废 — 丧尸兵 2 发解决、小鬼 6 发左右 — 但 DPS 大约只有加特林的三分之一(每发公式一样,每次攻击只要 4 tic),更只有火箭筒的十分之一。这就是为什么一拿到加特林,手枪立刻退到备胎位置。

超级霰弹枪打地狱骑士 — 贴脸开枪的真实数字

超级霰弹枪公式:每颗弹丸 $5 \times \text{random}(1, 3)$,弹丸数 20。单发范围 = 100 到 300,期望值 = 200。地狱骑士 HP = 500。期望击杀 = $\lceil 500 / 200 \rceil$ = 3 发。最差运气 = $\lceil 500 / 100 \rceil$ = 5 发(每颗弹丸都掷到 1)。最佳运气 = $\lceil 500 / 300 \rceil$ = 2 发(每颗弹丸都掷到 3)。A_FireShotgun2 大约每分钟 36.8 发(连同上膛、退壳一共约 57 tic 一轮),所以三发解决的击杀秒数 = $3 \times (57/35) \approx 4.9$ 秒。B 站攻略与百度贴吧 doom 吧常说的「两发解决地狱骑士」只在运气好的时候成立;稳妥的规划还是要按 3 发来算。

BFG 球体直击机械巨魔(不计散射)

BFG 球体 actor `BFGBall` 的 Damage 为 100。每次直击范围 = 100 到 800,期望值 = 450。机械巨魔 HP = 4000,对溅射完全免疫 — 只吃直击。期望直击次数 = $\lceil 4000 / 450 \rceil$ = 9 发。最佳运气 = $\lceil 4000 / 800 \rceil$ = 5 发。最差运气 = $\lceil 4000 / 100 \rceil$ = 40 发(每次都掷到最小)。各路攻略里常见的「BFG 三到四发解决机械巨魔」是把散射光线也算进去的结论,而且默认玩家距离适中、机械巨魔整只待在散射锥里。BFG 真正高效的部位是散射:一发 BFG 球体 + 40 条散射光线的全覆盖击发,期望输出 = $450 + 40 \times 67.5 = 3150$,直击与锥形散射同时命中时,2 发就能让机械巨魔倒地。

ACS Delay 换算 — 「2.5 秒是多少 tic」

每秒 tic 数 = 35。2.5 秒换成 tic = $\text{round}(2.5 \times 35)$ = round(87.5) = 88 tic。在 ACS 里想保留可读性可以写 `Delay(35 * 25 / 10)`,想直接写死也可以用 `Delay(88)`。MOD 作者必记的常用数值:0.1 秒 = 4 tic、0.5 秒 = 18 tic、1 秒 = 35 tic、1.5 秒 = 53 tic、2 秒 = 70 tic、3 秒 = 105 tic、5 秒 = 175 tic、10 秒 = 350 tic。小鬼火球 Speed = 10 map units/tic,飞 1024 map units 需要 $\lceil 1024 / 10 \rceil$ = 103 tic ≈ 2.94 秒,约 15 mph(10 × 1.49 ≈ 14.9)。等离子枪球 Speed 25 走同样 1024 map units 只要 41 tic ≈ 1.17 秒,约 60 km/h。

ZDoom 伤害与平衡心得 — MOD 作者、地图作者与好奇玩家都用得上

  • 读 actor 的 Damage 属性时,要用「期望值」而不是「字面值」去想。Damage 5 的投射物在游戏里平均 22.5(5 × 4.5),不是 5。如果你的自制怪物火球要跟小鬼(期望 13.5)打成同一个级别,Damage 应该写 3,而不是 10。DECORATE 平衡最常见的错误就是把 Damage 10 当作「固定 10 伤害」,结果在游戏里跑出 10 到 80、平均 45 的数字。
  • +STRIFEDAMAGE 旗标是最低成本的「收范围」手段。Damage 不变,最大倍率从 8 降到 4,期望值从 4.5× 降到 2.5×。想做一支「固定落在 60 到 240 之间,而不是 60 到 480」的自制火箭时非常好用。旗标取名自 Strife(引擎第一个非 Doom IWAD),但跟底层游戏无关 — 任何 ZDoom MOD 都能用,纯 Doom IWAD 也照样吃。
  • 扫描枪完全无视 Damage 属性。手枪、霰弹枪、加特林、超级霰弹枪的 A_FireBullets/A_FirePistol/A_FireShotgun 内部写死了每颗弹丸 $5 \times \text{random}(1, 3)$。想增强扫描枪的伤害,必须改弹丸数、改 A_CustomBulletAttack 的 damage 参数,或者干脆改造成投射物型武器。拳头与电锯是 $2 \times \text{random}(1, 10)$;狂暴只对拳头生效,在随机数之后再乘以 10(每拳 20 到 200,期望 110)。
  • 对比 DPS 时,每次攻击的 tic 数比单发伤害更重要。加特林跟手枪的每发公式完全一样(5 到 15,期望 10),但加特林每次攻击大约 4 tic、手枪大约 14 tic — 同样的弹丸公式,DPS 直接差到 3.5 倍。设计武器 MOD 时,先定目标 DPS(原版手枪约 25、霰弹枪约 70、超级霰弹枪约 150、加特林约 88、等离子枪约 263、火箭直击约 150),再反推单发伤害与每次攻击 tic。
  • 19 种怪物速查表是设计遭遇战的好工具。丧尸兵(HP 20)、霰弹兵(30)、Wolfenstein SS(50)、小鬼(60)、加特林兵(70)、亡魂/Commander Keen(100)、牛怪/Spectre(150)、Revenant(300)、Pain Elemental/巨脑魔(400)、地狱骑士/Arachnotron(500)、Mancubus(600)、Arch-vile(700)、地狱男爵(1000)、蜘蛛魔王(3000)、机械巨魔(4000)。超级霰弹枪一发(期望 200、最大 300)在最佳运气下一枪就放倒 Revenant(HP 300);Pain Elemental 与巨脑魔(HP 400)至少要两发最佳运气。手枪一发(期望 10)只放得倒丧尸兵。在地图第一个房间放牛怪还是放 Mancubus,是难度 4 倍的差距,而不是 1.5 倍 — HP 曲线是等比上升,不是线性上升。
  • GZDoom v3.2.2(2017 年底)起保证 35 tic 等于实时 1.000 秒。再早的版本因为计时器内部整数除法截断,tic 间隔被显示成 28 ms,于是 35 tic 显示成 0.98 秒。如果你的 ACS Delay() 算术需要次秒精度而且要兼容 2017 年前的玩家版本,请预留 2% 的偏移:`Delay(35 * 60)` 在旧版计时器上实际只跑了 58.8 实时秒,比整整一分钟少 1.2 秒。
  • BFG 散射是唯一一个不照 $\text{Damage} \times \text{random}(1, 8)$ 跑的投射物。A_BFGSpray 内部把每条光线的伤害定义成 15 次独立 random(1, 8) 的总和,所以单条光线范围 15 到 120、期望 67.5,分布是钟形而不是均匀分布。BFG 球体在前方 90 度锥里最多射 40 条光线,全覆盖击发会在 BFG 球体本体 100 到 800 上面再叠 $40 \times 67.5 = 2700$ 点期望伤害 — 这就是「BFG 一发秒掉机械巨魔」传说的真相,前提是直击与锥形散射同时命中。
  • Map unit 的实际尺寸换算有水平、垂直两种,不是一条。水平方向:16 map units = 1 英尺(0.3048 m);垂直方向:因为原版 320×200 分辨率被纵向拉长 20%,10 map units = 1 英尺。投射物沿地图平面飞,所以 Speed 换算用水平比:Speed 10(小鬼火球)≈ 6.67 m/s ≈ 15 mph;Speed 25(等离子、BFG 球体)≈ 16.67 m/s ≈ 60 km/h ≈ 37 mph。毁灭战士本人跑步速度大约 Speed 16,约 24 mph — 这就是为什么在窄走廊里偶尔会被小鬼追上咬到屁股。
  • DamageFactor 让你不必改伤害代码就能做抗性与弱点。在怪物身上写 `DamageFactor 'Fire', 0.5` 会把 Fire 类伤害减半,2.0 加倍,0.0 完全免疫。计算器的 DPS 模式用一个标量 DamageFactor 字段呈现,可以不必声明自定义伤害类型就快速建模「对 Fire 0.7 抗性的巨脑魔变种下,原版武器的 TTK 变多少」这种场景。
  • 做生存型计算时,最差运气与最佳运气比期望值更实用。「期望击杀 = 30」这个数字藏住了一个极端结果:运气最差时,巨脑魔可以硬吃 134 颗小鬼火球。计算器之所以把最佳/最差跟期望一起列出来,就是为了这种场景 — 做大屠杀地图、需要在严格的弹药预算内把怪物清光时,按最差运气来设计;做休闲地图,按期望来设计。random(1, 8) 投射物两个数字差到 5 到 10 倍并不少见。
  • 在中文环境写 MOD 时,actor 名与属性名一律保留引擎里的英文写法(Damage、Speed、Health、+STRIFEDAMAGE、Cacodemon、Cyberdemon 等)。DECORATE 与 ZScript 都不接受被本地化的标识符。B 站、百度贴吧、机核或萌娘百科上看到的「巨脑魔」「机械巨魔」「蜘蛛魔王」只是给玩家看的译名,代码里仍然是 `Cacodemon`、`Cyberdemon`、`SpiderMastermind`。PK3 内坚持英文写法,能让其他 MOD 作者打开 WAD 时省下大把调试时间。

ZDoom 伤害计算器 — 常见问题

为什么我写的 Damage 10 投射物有时候打出 80 点伤害?

ZDoom 每次命中都会把投射物的 Damage 属性乘以 random(1, 8)。Damage 10 会等概率打出 10、20、30、40、50、60、70 或 80,平均 45。加上 +STRIFEDAMAGE 旗标后倍率变成 random(1, 4),落在 10、20、30、40 之间,平均 25。

原版毁灭战士的手枪伤害公式是什么?

手枪每发 $5 \times \text{random}(1, 3)$,也就是 5、10 或 15 等概率落点,期望值 10。加特林与霰弹枪(每颗弹丸)用同一条公式。扫描枪 actor 上的 Damage 属性会被忽略,公式直接写死在 A_FirePistol、A_FireShotgun、A_FireCGun 里。

ZDoom 里 1 秒等于多少 tic?

35 tic。TICRATE 自 1993 年首发以来一直锁在 35。GZDoom v3.2.2 之后保证 35 tic 等于实时 1.000 秒;更早的版本把 tic 间隔截断成 28 ms,所以 35 tic 显示成 0.98 秒 — 这在长串 Delay() 累加时会以约 2% 的速率漂移。

ACS 里要怎么写 X 秒的延迟?

把秒数乘以 35 并四舍五入。0.5 秒 = 18 tic、1 秒 = 35 tic、2 秒 = 70 tic、5 秒 = 175 tic、10 秒 = 350 tic、60 秒 = 2100 tic。在 ACS 里可以直接写 `Delay(35 * seconds)`,乘法会在编译期被解掉。

+STRIFEDAMAGE 旗标到底在做什么?

+STRIFEDAMAGE 把投射物伤害倍率从 random(1, 8) 切成 random(1, 4)。Damage 值不变,范围更窄、平均值更低。旗标取名自 Strife,但跟底层游戏无关 — 任何 ZDoom MOD 都能用,包括纯 Doom/Doom II 套装。想要伤害更稳、波动更小的中威力投射物时,这个旗标最划算。

机械巨魔(Cyberdemon)的 HP 是多少?

4000 HP。机械巨魔对溅射完全免疫 — 火箭与 Mancubus 投射物炸到它脚边都不会吃到溅射伤害,只能靠直击。BFG9000 是惯例武器(连同散射约 2 到 4 个 trigger),其他选项包括贴脸超级霰弹枪约 20 发、火箭直击期望约 45 发(前提是弹药够)。计算器下方的 19 行怪物表完整列出原版每只怪物的 HP。

BFG 的伤害为什么这么怪?「15 次循环」是什么?

BFG 球体本体按标准公式跑(Damage 100 × random(1, 8) = 100 到 800),但散射光线不是。每条光线(最多 40 条)是把 15 次独立 random(1, 8) 加起来,所以单条光线范围 15 到 120、期望 67.5。Doom Wiki 提到 P_Random 的 256-byte 伪随机表确定性会把实机观察到的单条光线范围收窄到 49 到 87 之间,但理论最大值 120 不变。

ZScript actor 也能用这款计算器吗?

可以。ZScript 与 DECORATE 共用同一套 Damage/DamageFunction/Speed/Health/+STRIFEDAMAGE 语义,差别只在语法。Default 区块里写 `Damage 5;` 的 ZScript actor 跟同样写法的 DECORATE actor 掷出完全一样的 $5 \times \text{random}(1, 8)$。本工具的输出对两者皆适用。

Brutal Doom 或 Project Brutality 也能用吗?

对于还在用标准 Damage 属性与原版扫描枪函数的 actor 是可以的。Brutal Doom(Sergeant Mark IV 制作)与 Project Brutality 把大部分武器改写成自定义 DamageFunction 与 A_FireCustomMissile 路径,不再遵守 random(1, 8) 倍率。这类武器只能拿到原版近似值,建议翻一下该 MOD 的 DECORATE/ZScript 自行修正。

PrBoom+、ZDoom、GZDoom、Zandronum 之间,伤害会不一样吗?

对原版《毁灭战士》/《毁灭战士 II》来说不会。PrBoom+、ZDoom、GZDoom、Zandronum 都把 TICRATE 35、random(1, 8) 与 random(1, 3) 公式、原版 HP 数值一字不漏地保留下来。不同 source port 的差异发生在进阶功能(物理、MAPINFO、ZScript、MBF21 怪物脚本),不会发生在伤害基本算式上。同样的随机数序列下,HP 400 的巨脑魔在四套引擎里会用同样的发数倒下。

Revenant 的追踪导弹为什么是 10 到 80 而不是 10 到 40?

`RevenantTracer` actor 虽然写了 Damage 10,但没有挂 +STRIFEDAMAGE 旗标,所以使用默认 random(1, 8) 倍率,范围 10 到 80、期望 45,不是 10 到 40。很多 MOD 作者直觉以为 Revenant 火箭应该走 Strife 风格的数学 — 其实不是。

难度(UV/Nightmare)会让武器伤害变高吗?

不会。Nightmare 把怪物攻击性与弹药拾取数翻倍,但武器伤害在五个难度等级下完全相同。原版里唯一存在的伤害倍率是狂暴(Berserk),它把拳头伤害乘以 10。难度改变的是「谁先开枪、开几枪」,不是「每枪打多重」。

这款计算器跟实机游戏的精度差多少?

在 ZDoom/GZDoom 下跑原版《毁灭战士》/《毁灭战士 II》行为时,引擎级精确。校验范围覆盖每一个投射物预设、每一支扫描枪、每一个怪物 HP,以及 BFG 散射的 15 次循环 — 伤害范围、HP 与投射物 Speed 与原版 actor 定义到单位都对得上。DECORATE/ZScript 替换的 actor、自定义 DamageFunction 表达式、新世代《毁灭战士》(2016、永恒、黑暗时代)用不同算法,不在工具覆盖范围之内。

工具是免费的吗?要不要注册?

完全免费,不必注册,全部运算都在你的浏览器里完成。输入会用 localStorage 在页面刷新之间保留,所选模式也会反映到网址查询字符串(?mode=damage / dps / tics)里,方便书签分享到 B 站专栏、百度贴吧 doom 吧、机核或 ZDoom 论坛。


ZDoom 伤害与时间术语表

Damage 属性

DECORATE 或 ZScript actor 的 Default 区块里的一个整数属性。引擎每次命中都会乘以 random(1, 8)(挂 +STRIFEDAMAGE 为 random(1, 4)),所以 Damage 10 在游戏里会跑出 10 到 80 的范围,不是固定 10。

+STRIFEDAMAGE

把投射物伤害倍率从 random(1, 8) 切成 random(1, 4) 的 actor 旗标。Damage 不变、范围变窄、平均值降低(Damage × 2.5 而非 Damage × 4.5)。跟底层游戏无关,任何 ZDoom MOD 都能使用。

tic

Doom 引擎的最小时间单位。TICRATE = 每秒 35 tic,1 tic ≈ 28.5714 ms。DECORATE/ZScript 的 state 时长与 ACS Delay() 参数都以 tic 为单位。GZDoom v3.2.2 起保证 35 tic = 实时 1.000 秒,更早的版本截断为 28 ms。

扫描枪(Hitscan)武器

不依赖投射物 actor、沿直线即时结算伤害的武器。手枪、霰弹枪、超级霰弹枪、加特林都是扫描枪。公式直接写死在 A_Fire* 动作函数里(每颗弹丸 $5 \times \text{random}(1, 3)$),actor 的 Damage 属性会被忽略。

DamageFactor

针对特定伤害类型的受击倍率。`DamageFactor 'Fire', 0.5` 把 Fire 类伤害减半,2.0 双倍、0.0 完全免疫。计算器 DPS 模式给一个标量 DamageFactor 字段,方便快速建模抗性与弱点场景。

狂暴(Berserk)

在 random(1, 10) 之后再把拳头伤害乘以 10 的能力强化道具,范围 20 到 200、期望 110。电锯、扫描枪、投射物全都吃不到这个 buff,只有拳头吃。

Map unit

Doom 的空间坐标单位。社区公认:水平 16 map units = 1 英尺 = 0.3048 m(毁灭战士本人垂直 56 个单位高 = 5 英尺 7 英寸)。计算器用水平 16 mu/英尺的比例,把投射物 Speed(map units/tic)换成 m/s、km/h、mph。

Speed 属性

投射物 actor 的速度(map units/tic)。小鬼火球 Speed 10;火箭 Speed 20;等离子枪球与 BFG 球体 Speed 25。乘以 35 得到 map units/秒;乘以 0.667 得到 m/s;乘以 1.49 得到 mph。

BFG 散射(BFG spray)

BFG 球体命中时释放的 40 条光线锥形扩散(从 BFG 球体的死亡 state 通过 A_BFGSpray 发射)。每条光线伤害为 15 次独立 random(1, 8) 的总和 — 单条 15 到 120、期望 67.5。BFG 一发秒掉机械巨魔的传说就来自散射,本体球体并不够。

TICRATE

把 Doom 帧率锁在每秒 35 tic 的引擎常数,自 1993 年以来从未变过。在 id Software 的 doomdef.h 里声明,被 ZDoom、GZDoom、Zandronum、PrBoom+、Boom、MBF21 以及所有原版兼容 source port 一字不漏地继承。所有 state 时长、Delay() 参数、投射物飞行时间都以 35 作为换算常数。

DamageFunction

Damage 属性的替代品,让 MOD 作者在命中时通过 ZScript 表达式返回任意整数,绕过 random(1, 8) 倍率。可以返回定值做确定性伤害,也可以根据 inflictor/target/distance 动态计算,做出对场景敏感的行为。

P_Random

Doom 引擎的伪随机数函数,使用一张固定 256 byte、洗牌过的表,索引顺序往前推进,每次调用返回下一个 byte。分布并不均匀(值 1 永远不出现、值 145 出现 5 次),但对战斗算术已经够用。所有伤害掷骰都使用它;M_Random 走另一条索引,给非游戏性效果用,避免破坏多人联机的同步。


由 Smart Calculators 团队审核