rimworld-ordinatus-calculi
Laurence-042
- 5 minutes read - 1015 wordsRimWorld 计算仪典:破甲者之歌・留命者之吟
RimWorld Ordinatus Calculi:Song of the Breaker ・ Chant of the Keeper
一个基于 Vue 3 + TypeScript 的 RimWorld 战斗机制计算器,用于计算给定武器在不同的距离/护甲情况下的DPS,以及给定护甲组合在不同单发伤害/穿甲情况下的受伤期望。
功能特性
Features
武器 DPS 计算器(Weapon-Centric)
Weapon DPS Calculator (Weapon-Centric)
多武器对比:同时评估多个武器在不同护甲率(0–200%)下的 DPS 表现
Multi-weapon comparison: Evaluate multiple weapons across armor values (0–200%).
精确命中率:基于距离分段(贴近/近/中/远)的线性插值算法
Accurate hit chance: Linear interpolation across distance segments (touch / short / medium / long).
连发机制:完整模拟预热、连发间隔、冷却时序
Burst mechanics: Full simulation of warm-up, burst interval, and cooldown timings.
2D/3D 可视化:
2D/3D Visualization:
2D 曲线图:特定距离下 DPS 随护甲率变化的曲线
2D line plots: DPS vs. armor curves at a fixed distance.
3D 曲面图:护甲率随距离与穿甲变化的曲面,并标记两种武器曲面交线(何种情况下两武器 DPS 相等)
3D surface plots: DPS surface over distance and armor penetration, with intersection lines showing where two weapons have equal expected DPS.
护甲效能计算器(Armor-Centric)
Armor Effectiveness Calculator (Armor-Centric)
多层护甲系统:支持多层护甲叠加计算
Multi-layer armor system: Supports stacked armor calculations.
身体部位覆盖:根据部位覆盖情况计算综合防护效果
Body part coverage: Computes protection based on armor coverage over body parts.
伤害类型模拟:利器 / 钝器 / 热能伤害的不同穿透与减伤机制
Damage type simulation: Different penetration/reduction rules for sharp, blunt, and heat damage.
概率分布:显示完全偏转 / 部分穿透 / 完全穿透的概率
Probability distribution: Shows chances of deflection, partial penetration, and full penetration.
实战场景:
Practical scenarios:
减伤概率分布:特定穿甲值下的减伤概率
Damage reduction distribution: Damage reduction probability for a given AP value.
减伤期望曲线:不同穿甲对应的减伤期望
Expected reduction curves: Expected damage reduction across different AP values.
快速开始
Quick Start
在线演示 / Demo:
https://laurence-042.github.io/project/rimworld-ordinatus-calculi/demo/
使用示例
Usage Examples
调整语言(目前只支持简体中文和英文)
Change Language (currently supports Simplified Chinese & English)
修改 / 添加扩展数据源
Modify / Add Extra Data Sources
默认数据源仓库:
Default dataset repository:
rimworld-ordinatus-calculi-extra-data
创建新的扩展数据源
Creating a New Extra Data Source
执行前请修改 tools\xml_def_data_parser\config.ts 中的配置,以对应实际 Mod 路径。
Before running, edit the configuration in tools\xml_def_data_parser\config.ts to match your actual mod paths.
默认配置通常用于为官方扩展数据集
rimworld-ordinatus-calculi-extra-data
生成数据。
The default configuration matches the settings used when generating the official extra dataset above.
请注意:从 Mod 中提取的数据 只应提交到扩展数据集仓库,因为许多 Mod 使用 CC 系列协议(或未声明许可)。若将其包含在本仓库中,本仓库的 License 条款将不再适用。
Note: Extracted Mod data should only be committed to the extra dataset repository, since many Mods use CC licenses (or lack proper licensing). Including such data in this main repository would invalidate its License terms.
执行命令:
Run:
npm run parse-mod
环境要求
- Node.js
^20.19.0或>=22.12.0 - 推荐使用
pnpm或npm
安装依赖
npm install
启动开发服务器
npm run dev
访问 http://localhost:5173/project/rimworld-ordinatus-calculi/demo/
这个路径是我的项目部署页 https://laurence-042.github.io/project/rimworld-ordinatus-calculi/demo/index.html ,其就像普通 vite 项目一样在
vite.config.ts里定义
构建生产版本
npm run build
类型检查
npm run type-check
代码格式化
npm run lint # ESLint 检查并自动修复
npm run format # Prettier 格式化
核心计算公式
武器 DPS
// 完整射击周期(ticks)
cycleDuration = warmUp × 60 + (burstCount - 1) × burstTicks + cooldown × 60
// 实际 DPS(考虑命中率)
DPS = (burstCount × damage × hitChance × 60) / cycleDuration
命中率插值
根据距离在 4 个精度区间(贴近 0-3, 近 3-12, 中 12-25, 远 25-40)之间线性插值:
hitChance = interpolate(distance, accuracyBrackets)
多层护甲伤害
- 外层到内层依次处理
- 每层 RNG 判定:
< armor/2:完全偏转(0% 伤害)>= armor/2 && < armor:部分穿透(50% 伤害)>= armor:完全穿透(100% 伤害)
- 利器伤害转换:若减伤 ≥50%,剩余伤害转为钝器
- 穿透力不衰减:对所有层使用原始 AP 值
项目结构
src/
├── components/
│ ├── DPSCalculator.vue # 武器 DPS 计算器主界面
│ ├── ArmorCalculator.vue # 护甲计算器主界面
│ ├── DPSChart.vue # 2D DPS 曲线图
│ ├── DPSSurface3D.vue # 3D DPS 曲面图
│ ├── ArmorChart.vue # 2D 护甲效能图
│ ├── ArmorReductionCurve.vue # 护甲减伤曲线
│ ├── LanguageSelector.vue # 语言切换组件
│ └── SliderInput.vue # 通用滑块输入组件
├── i18n/
│ ├── index.ts # vue-i18n 配置
│ └── locales/
│ ├── zh-CN.json # 简体中文
│ └── en-US.json # English
├── types/
│ ├── weapon.ts # 武器参数接口
│ ├── armor.ts # 护甲与装备接口
│ ├── material.ts # 材料系统
│ ├── bodyPart.ts # 身体部位定义
│ └── quality.ts # 品质等级定义
├── utils/
│ ├── weaponCalculations.ts # 武器 DPS 计算
│ ├── armorCalculations.ts # 多层护甲计算
│ ├── weaponDataParser.ts # 武器数据解析
│ ├── apparelDataParser.ts # 服装数据解析
│ ├── materialDataParser.ts # 材料数据解析
│ ├── dataSourceConfig.ts # 数据源配置(manifest加载)
│ ├── coverageUtils.ts # 覆盖率计算工具
│ ├── bodyPartUtils.ts # 身体部位工具
│ ├── armorUtils.ts # 护甲工具函数
│ ├── csvParserUtils.ts # CSV 解析工具
│ └── plotlyUtils.ts # Plotly 3D 图表工具
├── App.vue # 根组件(Tab 切换)
└── main.ts # 入口文件
public/data/ # 游戏数据(由 xml_def_data_parser 生成)
├── manifest.json # 数据清单(MOD列表、语言、数据类型)
├── weapon/<ModName>/<locale>.csv
├── apparel/<ModName>/<locale>.csv
└── material/<ModName>/<locale>.csv
tools/xml_def_data_parser/ # RimWorld XML 数据提取工具
├── config.ts # MOD 路径配置
├── tool.ts # 主解析器
├── weaponParser.ts # 武器解析
├── apparelParser.ts # 服装解析
├── materialParser.ts # 材料解析
├── baseParser.ts # 基础解析与继承处理
├── projectileParser.ts # 投射物解析
└── README.template.md # 生成 README 的模板
技术栈
- 前端框架:Vue 3 (Composition API +
<script setup>) - 类型系统:TypeScript 5.9(严格模式)
- UI 组件库:Element Plus 2.11
- 国际化:vue-i18n(支持中文/英文切换)
- 图表库:
- Chart.js 4.5 + vue-chartjs 5.3(2D 曲线)
- Plotly.js 3.3(3D 曲面)
- 数据解析:papaparse 5.5(CSV 处理)
- 构建工具:Vite 7.1
- 代码规范:ESLint + Prettier
如果哪天我失联了,而有人想要扩展这个项目,大概会用到这些
添加 Mod 数据
项目使用 tools/xml_def_data_parser/ 工具从 RimWorld 的 XML 定义文件中提取数据:
编辑
tools/xml_def_data_parser/config.ts,添加 MOD 配置:{ path: 'D:\\SteamLibrary\\steamapps\\workshop\\content\\294100\\<MOD_ID>', sourceUrl: 'https://steamcommunity.com/sharedfiles/filedetails/?id=<MOD_ID>', enabled: true, }运行解析器:
npm run parse-mod工具会自动:
- 解析 MOD 的 XML 定义文件
- 处理继承关系(ParentName)
- 提取多语言翻译
- 生成 CSV 文件到
public/data/(或者其他config.js里指定的相对于public/的路径) - 更新
manifest.json - 生成带有来源归属的
README.md
数据源系统
- Manifest 驱动:
public/data/manifest.json记录所有可用的 MOD、语言和数据类型 - 自动合并:Core、Royalty、Ideology、Biotech、Anomaly、Odyssey 会被合并为 “Vanilla”
- 多语言支持:每个 MOD 可以有多个语言版本的 CSV(如
zh-CN.csv、en-US.csv)
修改计算逻辑
核心计算函数位于 src/utils/*Calculations.ts,包含详细的 JSDoc 注释和游戏机制说明。
添加新语言
- 在
src/i18n/locales/下创建新的 JSON 文件(如ja-JP.json) - 在
src/i18n/index.ts中导入并注册 - 更新
LanguageSelector.vue(如需要)
常见的坑
Plotly Surface 的坐标系统:
z数据的第一维对应 Y 轴,第二维对应 X 轴:z[i][j]对应(x[j], y[i])text数据的第一维对应 X 轴,第二维对应 Y 轴:text[i][j]对应(x[i], y[j])- 所以画 3D 图时,
z需要转置但text不用 - 详见
src/utils/plotlyUtils.ts里的transposeMatrix()注释
许可证
法典绪言
此计算仪典以 MIT 之契约,赐诸信徒自由修习。
然其中一切数值皆溯源于 Tynan 所赐之官方 XML 典藏。
圣典之契,仅约束吾所编之代码、算式之实现、与数据之架构。
至于兵戎衣铠之名与诸身躯部位之称,皆出自 Tynan 之典籍,不属敝人可予之许可,仍循其原有之法。
正经的许可证说明
本项目以 MIT 协议开源。
MIT 许可仅适用于本项目的源代码、计算逻辑的实现方式,以及生成的数据结构格式。 本项目中出现的武器、护甲、材料等名称均来自 RimWorld 原作,其著作权归 Ludeon Studios 所有,不在 MIT 授权范围内。
RimWorld 原版数据速查
如果怀疑预设数据存在问题,可以使用如下链接查询
RimWorld 灰机 Wiki 是国内优秀的 RimWorld 社区,在开发数据提取脚本的过程中,其 SMW 查询接口极大方便了数据对照与验证,使我得以快速检查脚本输出是否有缺失和冗余,对此表示感谢。
致谢
RimWorld 灰机 Wiki:其SWM接口真不错,要是没法导出数据一个个用眼睛比对数据,那我得瞎
Quality Colors (Continued):选择品质时的颜色参考了这个 Mod
米莉拉派系扩展:米莉拉帝国:做这个工具的直接原因就是,我无法区分这里面的磁轨杠杆步枪和电磁突击步枪哪个比较好。前者有高达 85% 的穿甲但单发且有较长的前后摇,后者穿甲只有 15% 还不如突击步枪但6连发前后摇也更短,而两者制造成本没啥本质差别。我猜测可能有个特定点护甲值,高于这个值磁轨 DPS 更高,低于这个值电突 DPS 更高。但我不知道具体值,所以我写了这个工具,然后被计算结果震惊了——想知道答案?自己试一下吧! [ROC] milira faction_ milira imperium 就是这个 Mod 的数据,其中 ROC 是这个项目名称的缩写,表示这个是这个项目的附属项目提供的数据
NewRatkinPlus[1.6]:在没有鼠鼠的黑暗时代燃起了火光,感谢你,风信子大佬!
致破甲者:愿你的子弹找到缝隙
致留命者:愿你的护甲承载希望
TODO
基础功能
都搞定了,如果没有 bug,短时间内应该不会加啥新特性了
- DPS曲线
- DPS曲面
- 护甲层叠计算
- 护甲受伤概率分布
- 护甲受伤期望曲线
- 预设数据
- 数据加载
- 武器数据加载
- 服装数据加载
- 材料数据加载
- 第三方MOD数据
- XML 数据提取工具
- 开个仓库存mod的数据,作为数据源示例
- 加载自定义数据源
- 数据加载
- i18n
如果以后有时间可能会做的进阶功能
毕竟没人用的话做这么多不是白做了嘛
不过这些大多不是很重要,当前手调参数也能支持的功能,所以也不急着做
咕咕咕
- 前后摇的全局乘数参数(射击专家等等)
- 暂时想不到了
使用中的注意事项
这个工具应且仅应用作参考,实际游戏中会有更多的变量影响实际结果,这也正是 RimWorld 的魅力之一。
比如,虽然很多武器的 DPS 接近或超过速射机枪,但这很大程度上是因为速射机枪的 DPS 严重受其长前后摇的影响。而实际使用中,射击专家可以大幅降低前摇,而因为原版没啥东西能抗住速射小队一轮齐射后摇再长也没啥影响,所以速射机枪的实际价值是比看起来更高的(实际上,你可以在加载了速射机枪的预设后自行调整其参数,比如前摇降到一半模拟射击专家的影响之类的,以此适应你的游戏环境)
已知但不准备修复的问题(特性)
一个ThingDef要么被忽略,要么被视为武器、衣物、材料三者之一,不能同时为多种类型
这个问题在原版中只有一个影响,即原木(WoodLog)不会被作为武器加载。
这个没啥问题,反正这个计算器目前没打算支持近战武器,近战武器也都在生成数据表格阶段就被过滤掉了(毕竟近战武器的数值大多一眼就能看出好不好)
不过我没太多mod开发经验,不确定有没有可能做出能穿、能开火的材料,或者能拿手上开火的衣服……但我觉得这种设计太抽象了,就算可以做也不会有mod做,所以没有为此做兼容的计划。但如果真有mod整了这种抽象活,那这个特殊物品会依次匹配“材料”、“武器”、“衣物”,会被视为第一个匹配的类型。
比如原木(WoodLog)就匹配到了材料,能拿手上开火的衣服会被视为武器,能穿、能开火的材料会被视为材料
开发过程中发现的一些有趣的事实
防弹套可能比海军甲还好?
在面对原版的护甲杀手-电荷标枪(35%穿甲)和更低穿甲的武器时,普通品质的防弹夹克和防弹夹板组成的防弹套在对躯干的保护上优于普通品质的海军甲
但这不代表有海军甲不穿去穿防弹套是个好主意,只是说当你没有海军甲时,防弹套对躯干的防护效果可能比大多数人想象得还高。因为防弹套是不保护双臂的,腿部也只能穿防弹裤来提供单层保护,有海军甲还是摇好好穿上,这样能避免缺胳膊少腿
极差巨弓射穿大师级海军头?
不同于流行的“极差巨弓一箭射穿大师级海军头盔”meme,实际上即使是一般的巨弓(15%穿甲)也不可能完全打穿大师级海军头盔,只是有 30.65% 造成半数钝器伤害。
而减伤后 8.5 的钝器伤害并不足以致命,只有打中大脑才能让健康殖民者倒地。这种情况发生的概率实际上大约是 30.65%(头盔未内完全抵挡伤害) * 0.41%(命中大脑概率)= 0.125665%,也就是说至少要挨 2385 才有 95% 的概率能至少射到一次大脑
而且别忘了巨弓的前后摇都极长,精度也不算好,再加上殖民者通常在掩体后面吃掩体加成,本身“挨1下”就已经不算是高概率事件了
虽然乍一听似乎很离谱,但我觉得这主要是因为我们下意识把海军甲当成 机动龙骑 里的那种载具级装甲了。但其实从海军甲描述和英文来看,其设定比起钢铁侠那种近未来都没戏的玩意,更接近辐射系列里的动力甲(两者的英文都是 PoweredArmor)。你要说能扛几吨垃圾健步如飞、挨了十几发步枪直射都不倒的部落老哥能拉开的巨弓,在 2385 次尝试后才能以刁钻的角度击碎眼部透明材料并让材料击穿眼睛伤害大脑,那我觉得也不是说不通
为什么速射机枪是神?
在同为大师级品质的情况下,链霰即使在面对高护甲下平均DPS也高于速射啊
不过链霰确实手太短了,而且一般也没啥能抗住一轮速射队的齐射,所以实际使用时速射的长后摇一般不会造成什么影响,也正因如此速射是神
黑曜石是金属
不确定是不是我眼神不好,我此前真的完全没注意到黑曜石算一种金属
枪械的伤害是怎么算的
RimWorld 原版战斗虽然看似是个扔骰子的粗略模拟,但其数据结构却出乎意料地真实,即:
枪械的伤害和穿甲取决于其子弹的伤害和穿甲
但具体计算逻辑就有点复杂了,枪械的伤害和穿甲的定义流程大致可以理解为下面这样,完整逻辑请参考 RimWorld 源码里的 ProjectileProperties.GetArmorPenetration 方法
- 枪械定义
- 枪械动作
- 类型:Verb_Shoot
- 投射物:子弹定义
- 枪械动作
- 子弹定义
- 伤害类型
- 伤害(可选)
- 若不存在这个字段,视为伤害类型的默认伤害值
- 穿甲(可选)
- 若不存在这个字段,视为伤害类型的默认穿甲值
- 若伤害类型的默认穿甲值也不存在(默认值-1),视为 子弹伤害*0.015
- 若不存在这个字段,视为伤害类型的默认穿甲值
实际案例:栓动步枪的子弹伤害是18,其没有直接提供穿甲值,其伤害类型 Bullet 也没提供默认穿甲值, 那么栓动步枪的穿甲值就是 18*0.015=0.27,即 27%)
顺带一提,如果你看 public/data 里的原版数据/在界面上加载预设,发现有些穿甲值有三位小数,基本就是这个原因。
顺带一提,你可能会发现而且和 wiki 上写的差0.5%,那基本就是这个 0.015 乘出来的。wiki 上的值优先采用游戏里实际显示的值,而这个值是被格式化过的。比如 0.825 会被先乘 100 变成 82.5 后,经过 Mathf.RoundToInt 的银行家舍入规则(Round half to even,如果正好在中间,就舍入到最近的偶数)四舍五入会得到 82,也就是游戏和 wiki 上写的数值 82%
于此同时,游戏实际计算仍然使用 0.825 这种小数,所以这个应用也会使用 0.825 计算来达到更精确的结果。不过通常来说,也没必要纠结这 0.5%,它通常不会有啥明显影响。所以如果你正在使用这个应用还未覆盖的 Mod,你完全可以直接填界面上的值进来,不管那可能的 0.5%
品质加成可以让精度超过上限吗
不能
简单来说,品质加成时就会做截断,保证不超出最大值。所以即便你有个基础精度 100%,品质还是传奇级的枪,那也不会出现“按照超过 100% 的精度和射手技能、天气、目标大小等参数算完命中率后再截断到100%,导致枪枪比中”的好事。武器精度最高只能 100%