修复《机甲指挥官》的“左臂漏洞”乐趣与收获兼得MechCommander 1有个恼人的问题它会把机甲上的大型武器都集中放置在左臂。要是你的机甲主要或只装备了大型武器一旦失去左臂基本上这台机甲就废了。通常这个问题对任务的影响不大。精确瞄准机甲的特定部位命中率很低就算是射击技巧高超的飞行员也不例外所以对敌方机甲而言这问题影响有限而己方机甲恰好失去左臂的概率也不高——尽管这种情况确实可能发生。不过这问题依旧很奇怪一旦发生还是会让人有些头疼。不过现在好了之前我受 Vana 启发开始思考为何武器组件分配代码对大型武器不起作用花了一天时间研究终于找到了解决办法。这里我所说的“左臂”其实并不明确它到底是“左臂”还是“右臂”因为机甲在失去手臂后视觉显示并不一致。但根据手册中“射击左臂”指令所对应的部位我就暂且称之为左臂。大约一个月前我发现 MechCommander 1至少我手头的 MechCommander Gold 版本似乎嵌入了某种调试符号这让我们能大致了解游戏代码的实际运行情况。这意味着我们可以深入探究以下问题哪些武器算“大型”武器是我之前听说的重量≥9 吨的规则吗武器和装备是如何分配到机甲各个部位的为什么大型武器会全部集中在左臂嘿这门长汤姆炮看起来可真大——我觉得能算“大型”游戏的可执行文件是机器代码若先进行反汇编则是汇编语言。不过借助像 Ghidra 这样的工具没错它由美国国家安全局开发我们能把单个函数转化为类似 C 语言的代码。这种转化后的代码结构可能和原始源代码不同但比汇编代码更易读。首先这是一个判断武器是否为“大型”的函数这和“左臂漏洞”密切相关。结合 compbas.csv 文件中的武器 ID该文件包含在 MISC.FST 文件中以及其他信息包括我自己的一些测试我们可以列出“大型”和“小型”武器的清单“小型”武器就是那些未被明确定义为“大型”的武器。从这个列表中我们首先能注意到LRM 用“发射架”SRM 用“发射包”这对对抗氏族入侵者来说可是关键信息。要是有人把它们叫错可没法指望内环星域用命名错误的装备打仗。其次《绝境之战》扩展包中新增的所有武器都被错误地归类为“小型”武器因为 getWeaponLarge() 函数显然没有更新以考虑这些新武器而该分类函数对于未明确排除的武器默认输出为“小型”。有些分类界限比较模糊。比如轻型自动加农炮重 9.5 吨被归为“大型”而同样重量的大型激光炮却不算“大型”。我个人觉得如果大型激光炮不算“大型”那轻型自动加农炮也不该算反之如果轻型自动加农炮算“大型”那大型激光炮也应该算。不过这也没什么好纠结的目前的分类也有其合理性。这也表明“重量≥9 吨即为大型武器”的规则并不完全准确——就算把《绝境之战》中分类错误的武器都排除在外。前面提到的大型激光炮9.5 吨和氏族轻型超高速自动加农炮8.5 吨就不符合这个规则。为了验证我们的理解是否正确我们可以故意制造一些友军误伤事件。这些测试结果表明“大型”武器确实都集中在左臂也有可能纸娃娃系统是镜像显示的或者它们都在右臂而手册中“左臂”的说法有误。“小型”武器不会只集中在左臂而是更均匀地分布在机甲各处。《绝境之战》中的武器被错误地归类为“小型”武器实际上它们应该是“大型”武器。机甲飞行员应该组织工会维权。如果你仔细观察可能会发现测试中的机甲有时看起来是右臂被摧毁而不是左臂。这可能是视觉漏洞也可能是资源限制也许开发者没有为每个缺失的手臂制作单独的模型——机甲模型上缺失的手臂似乎会根据机甲的朝向或者其他未知因素而变化。我可不想去修复游戏里的每一个漏洞所以就先不管这个了。还有个奇怪的现象在重型 LB - X 测试中Beast 的生命值能量条显示大部分武器已损坏但实际上武器都还能正常使用。我原本担心游戏实际功能和界面上的武器显示不一致但所有武器都能正常开火——我猜可能是飞行员的生命值加上武器所在部位受到了一些损伤。也许是侧躯干在手臂被摧毁时受到了一些结构损伤但在大纸娃娃界面上没有显示因为还有护甲只在屏幕底部的简化界面上有所体现。虽然这个纸娃娃显示差异的问题很有意思但深入探究超出了本文的范围我们接着往下看吧。武器分配靠代码而非自然法则那么一般来说装备是如何分配到机甲各个部位的呢首先我们要找到游戏代码中处理这个问题的部分。判断是否找对代码的一个方法是修改疑似的函数然后看看游戏里会发生什么。我修改了疑似的函数让未知物品被分配到不该去的地方。修改后炸掉机甲的左臂会直接导致飞行员死亡但机甲的武器却不会损坏。左臂被炸掉、飞行员死亡后我又射击地上的机甲炸掉它们的右臂武器依然完好无损——这也算是修改带来的一个有趣副作用吧。我其实很好奇武器到底被分配到了哪些部位但在这个过程中我没办法逐一探究所有问题所以就先不研究这个了精确瞄准特定部位射击非常耗时就算是静止目标也不轻松所以要通过实验来确定并不容易。通过调试器追踪装备在机甲上的分配过程我发现我的修改可能至少把生命维持系统和引擎移到了左臂这就能解释为什么这些部件损坏时机甲和飞行员都会受损。这其实很有趣因为这表明《机甲指挥官》至少在一定程度上会使用这类“内部装备”而不是仅仅依靠检查特定部位头部、中心躯干等的结构状况——这和我之前的想法不太一样。顺便说一下在我的测试中这些组件似乎被分配到了机甲的不同部位我没有具体记录每个部位分配到了哪些装备生命维持系统2 个髋关节2 个肩关节陀螺仪传感器推测具体传感器类型会和机甲装备的一致驾驶舱2 个腿部驱动器2 个手臂驱动器核聚变引擎我不能保证所有这些装备都真的有作用但从上面观察到的“炸臂致死”现象来看至少有一部分装备对游戏是有影响的。不过深入研究这些超出了本文的范围。如果想真正解决问题有时候就得果断放弃那些在知识丛林中看似诱人但实则无关的探索。下面是处理装备分配的函数的开头部分。我就不详细讲解整个函数了它有几百行代码我也没完全搞懂它的所有功能而且深入讲解会偏离本文的主题。对我们来说关键是函数开头对 param_1 和 100 的比较。在基础游戏中武器的 ID 从 100 开始这让我们推测函数开头部分处理的是非武器装备的放置比如上面提到的那些组件。现有证据支持这个推测所以这个推测可能至少大部分是正确的但要完全证实它超出了本文的范围。我们真正关心的是这个函数如何处理武器ID 大于等于 100 的装备的放置。多亏了调试符号提供的函数名只要对被调用函数的功能做一些假设大部分高层逻辑还是很清晰的检查武器是大型还是小型。如果是小型武器根据检查这些部位小型武器情况的算法将其分配到 2 - 5 号部位。如果是大型武器根据检查这些部位大型武器情况的算法将其分配到 2 - 5 号部位。合理分配手臂武器让机甲火力不流失从前面的情况到最终找出问题所在这是整个过程中最耗时的部分但其实没什么意思所以我就说重点跳过那些无聊的细节。getWeaponLarge() 函数本身似乎运行正常不过它的设计本身也有一些问题比如对《绝境之战》武器的处理所以问题应该不在这。getSmallWeaponCount() 和 getLargeWeaponCount() 函数也都运行正常所以问题也不在这。左臂或者说使用“射击左臂”指令时实际射击的那个部位似乎是 4 号部位我猜其他三个部位分别是右臂、左躯干和右躯干但我不知道具体哪个数字对应哪个部位而且去弄清楚这个超出了本文的范围。通过追踪组件分配过程我们可以看到游戏中的情况在内存中得到了反映大型武器都集中在同一个地方而小型武器则分布在不同位置。注意观察氏族 ER PPC 炮中右图蓝色轮廓和氏族 ER 大型激光炮中右图红色轮廓在内存中是连续放置的这意味着它们在同一个部位。相比之下氏族脉冲激光炮和氏族重型火焰喷射器下图粉色轮廓在这张截图中分布在两个不同的地方。下图中的蓝色轮廓可能是肩部和手臂驱动器因为它们的组件 ID 相符这表明这两个部位是手臂。最后我像个原始人一样手动逐行追踪代码终于找出了问题所在。小型武器的放置逻辑是第一把武器会被放置在第一个被检查的部位4 号这样当检查第二把武器时由于第一个位置已经有小型武器了它就会被放到第二个位置。这个过程会一直重复直到每个位置都有一把武器然后是两把、三把以此类推直到所有小型武器都放置完毕。如果所有位置都没有小型武器那么武器会被放置在第一个位置。而大型武器的情况不同因为其“备用”值会将武器放置在最后一个位置。所以每把大型武器在检查过程中直到最后一个位置才会找到有武器的位置然后就都被放到了同一个地方也就是左臂。这个“备用”值应该和小型武器的算法保持一致第一把大型武器应该被放置在 2 号位置因为大型武器的检查是从这里开始的这样后续的武器在第一次检查时就会发现这个位置已经有武器了。“备用”值的来源是左图顶部的 iVar6 变量其值为 0。由于小型武器和大型武器的位置检查顺序不同4 - 5 - 2 - 3 与 2 - 3 - 4 - 5适用于小型武器放置计算的“备用”值并不适用于大型武器的放置计算。说句题外话我有点奇怪为什么要花这么多精力来区别分配小型武器和大型武器。也许原本的意图是避免因实现错误而导致的问题——把机甲上最重要的武器集中在一个部位。想象一下如果一台机甲装备了两门非常大/重的武器比如中型机甲上的两门 ER PPC 炮再搭配一些轻型武器为了降低风险肯定不希望这两门 PPC 炮都在同一个地方。如果这真的是设计初衷那这个漏洞就有点讽刺了。前面说过我们看到的代码不是原始源代码只是编译代码的类 C 语言表示方便我们快速理解。要修复这个问题我们得回到原始的汇编代码之前没给大家看是因为你们可能看不懂我也不想在这里上一堂汇编语言入门课。我们关注的值存储在 [EDI 寄存器](https://wiki.osdev.org/CPU_Registers_x86) 中绿色和黄色高亮部分。通常会用 XOR 指令将这个寄存器的值设为 0。这对于小型武器的放置没问题但对于大型武器我们需要将其值设为 2而不是 0。我们不能直接修改这个值因为这样会破坏小型武器的放置逻辑而且这里没有足够的空间来设置两个不同的值插入新字节会使整个程序偏移导致程序无法正常运行。我们可以做的是在附近找一些未使用的字节——也就是一个“代码洞穴”跳转到那个位置进行修改。在 placeItem() 函数下方下一个函数的末尾有几个未使用的字节数量刚好合适。跳转到这个代码洞穴后刚好有足够的空间重写为了跳转到这里而不得不覆盖的指令然后将 2 写入 EDI 寄存器作为大型武器的“备用”值最后再跳回原始代码。这就是修改后的样子修复效果验证应用这个修复并再次制造一次友军误伤事件看起来修复成功了大型武器现在分布在机甲的双臂以及另外两个可能是侧躯干的部位。根据这个结果我们还可以推测 2 号部位大型武器首先放置的位置是侧躯干5 号部位是右臂——因为失去双臂后我们还剩下 4/7 的武器而且我们知道 4 号和 5 号部位在 2 号和 3 号部位之前接收大型武器。不过还有个问题没搞清楚为什么 Beast 认为失去双臂和 3/7 的武器后自己的生命值能量只剩下 25%。和之前的 LB - X 测试不同这次侧躯干损伤有限飞行员也没有受伤无法解释这个差异。也许是生命值条或者其底层数值的计算方式有漏洞比如手臂的生命值是硬编码的……不这超出了本文的范围我不打算去修复它修复“左臂漏洞”的操作方法如果你想在自己的 MechCommander Gold 可执行文件中应用这个修改先备份文件然后用十六进制编辑器打开可执行文件在原始地址 0xEB48C 处将两个字节 E8 7F 替换为 E9 70。在原始地址 0xEB601 处将十五个字节 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 替换为 E8 0A 00 00 00 BF 02 00 00 00 E9 81 FE FF FF。如果这些地址的字节和这里写的不一样可能你玩的游戏版本和我处理的不同**不要**覆盖这些字节否则你的游戏可能无法正常运行。关于《绝境之战》武器分类问题嘿Beast希望你恢复得不错。感谢你指出这个问题。我们很关心飞行员的健康也很重视你在讨论中的贡献。说实话我觉得这些武器的分类问题影响不大。所有的 LB - X 自动加农炮都没什么用你根本不会去装备它们轨道炮和长汤姆加农炮太重了一台机甲不太可能装备多门雷霆炮在《绝境之战》战役中和那些顶级武器相比也比较平庸就算装备也只会偶尔用用。这样看来受影响最大的就只有大型 X 脉冲激光炮了而且这个问题的影响比“左臂漏洞”小很多。不过既然我们不介意破坏那些可能未使用武器的分类修复这个问题比修复“左臂漏洞”要容易得多那我就顺手把它修了吧。原始代码采用的是默认小型武器的系统函数中未明确指定为大型的武器都会被归类为小型。但由于《绝境之战》中新增的所有武器实际上都应该是大型武器修改时我们把规则反过来默认是大型武器然后明确将小型武器归类为小型这样会更容易一些。我们还可以去掉对游戏中不存在武器的引用在修改时节省一些空间——这个函数没有多余的空间来扩展长度因为它下面的空闲空间就是我们之前使用的代码洞穴从技术角度看修改后的函数稍微短了一点但性能上可能会慢一点点因为我在替换代码时优先考虑了代码的可读性而不是复制原有的性能优化方案。我没有改变大型激光炮和轻型自动加农炮的分类前者仍然是“小型”后者仍然是“大型”。和原始实现一样这个修订版本的逻辑仍然是基于对武器列表的假设所以如果我对某个武器的判断有误或者你进行了一些新武器的模组化操作这个函数可能会像原来一样出现分类错误的情况。通过暂时撤销“左臂漏洞”的修复补丁我们可以在确保 Beast 得到充分训练的同时对大型/小型武器分类的修改进行验证。看起来这个修改是有效的——至少对这把武器是这样Beast 也能好好休息一下了。去你的指挥官我听到你说的话了如果你想在自己的 MechCommander Gold 版本中应用这个武器分类函数的修改先备份文件然后用十六进制编辑器打开可执行文件在原始地址 0xEB5B0 处将 81 个字节 55 8B EC 8A 45 08 3C 64 72 04 3C 68 76 3A 3C 6E 72 04 3C 71 76 32 3C 79 74 2E 3C 7A 74 2A 3C 83 74 26 3C 84 74 22 3C 8D 74 1E 3C 8E 74 1A 3C 91 74 16 3C 92 74 12 3C 96 74 0E 3C 97 74 0A 3C 9A 74 06 33 C0 5D C2 04 00 B8 01 00 00 00 5D C2 04 00 替换为 55 8B EC 8A 45 08 3C 78 74 39 3C 7B 74 35 3C 7D 74 31 3C 82 74 2D 3C 85 74 29 3C 87 74 25 3C 8C 74 21 3C 8F 74 1D 3C 90 74 19 3C 93 74 15 3C 98 74 11 3C 99 74 0D 3C 9B 74 09 B8 01 00 00 00 5D C2 04 00 33 C0 5D C2 04 00 90 90 90 90 90 90 90 90。注意这两个序列的前几个字节是相同的这是有意为之。编辑说明2026 - 05 - 05 编辑我刚意识到默认设为大型武器可能会影响弹药的分配也就是说修改后弹药可能会和大型武器一起分配而不是和小型武器一起。我还没有实际确认弹药是如何分配的但我有 80% 的把握我是对的所以我会修复这个问题。如果不考虑代码的可读性幸运的是仍然有足够的空间将函数重新编写为默认小型武器而不需要再去其他地方找空间。由于大多数大型武器是连续分组的可以在每次比较时检查多个武器以弥补大型武器数量远多于小型武器的情况在原始地址 0xEB5B0 处将 81 个字节 55 8B EC 8A 45 08 3C 64 72 04 3C 68 76 3A 3C 6E 72 04 3C 71 76 32 3C 79 74 2E 3C 7A 74 2A 3C 83 74 26 3C 84 74 22 3C 8D 74 1E 3C 8E 74 1A 3C 91 74 16 3C 92 74 12 3C 96 74 0E 3C 97 74 0A 3C 9A 74 06 33 C0 5D C2 04 00 B8 01 00 00 00 5D C2 04 00 替换为 55 8B EC 8A 45 08 3C 62 72 04 3C 68 76 3A 3C 6B 72 04 3C 71 76 32 3C 74 72 04 3C 76 76 2A 3C 7E 74 26 3C 8B 72 04 3C 8E 76 1E 3C 91 72 04 3C 92 76 16 3C 96 72 04 3C 97 76 0E 3C 9A 74 0A 3C A0 74 06 33 C0 5D C2 04 00 B8 01 00 00 00 5D C2 04 00。2026 - 05 - 06 编辑如果你希望轨道炮和轻型高斯步枪也被识别为大型武器还需要将原始地址 0xEB1AD 处的字节从 0x64 改为 0x62这会将非武器组件的截止值从 100 改为 98。我上面介绍的两个修复补丁可以同时应用我也建议你这么做。不过要说明的是我没有对这些修改进行全面测试它们看起来是正确的我使用时也没有遇到崩溃问题但这并不代表没有隐患。请自行承担使用风险如果你遇到了之前没有的崩溃问题请回来告诉我。我只是个初次尝试修改 MechCommander 1 的玩家只是在其他事情之余抽空做了这些一次性的修改工作。最新更新2026 - 05 - 26 更新如果你觉得十六进制编辑很麻烦我做了一个小补丁工具可以自动完成这些修复以及其他一些操作上面的截图中轻型 LB - X 测试似乎还有另一个奇怪的漏洞有一把轻型 LB - X 显示为可操作但 Beast 却无法开火而且也不是弹药不足的问题除非弹药显示也出错了。我很想知道这是怎么回事……不这超出了本文的范围不管了不管了我要退出这个问题的研究评论与回复1. Vana 评论2026 年 5 月 6 日 20:38我最近沉迷于 MechCommander 1 和 MechCommander 2但我想实现的功能好像没办法按照我期望的方式实现。武器方面多带点武器能让元素战士不敢靠近但要是带太多发射架可得小心背后。从魔法角度看调整一个变量或者稍微重新排列现有函数比添加全新的内容要容易得多。除非你能直接跳到文件末尾在那里做任何你想做的事然后再跳回来。虽然这样可能效率不高但这个函数在一次任务中可能只使用一次。不过我对汇编语言了解不多只知道它很复杂。那一连串的 if() if() 语句看起来不是个好方法他们本可以在武器定义中设置一个标志之类的东西。如果我理解正确的话小型武器优先分配到手臂大型武器优先分配到躯干。这和游戏中大多数机甲的经典布局相反但这样一来失去手臂损失的火力会少一些而且 PC 版游戏中手臂的射击角度几乎没有区别。最后说说 LBX……我在想武器是否需要和弹药放在同一个位置或者它们只能从自己的弹药箱获取弹药。Mechcommander 2 的机甲定义似乎很强调部件顺序。但这些都超出了本文的范围。你能解决这个问题真的很厉害。2. MHLoppy 回复2026 年 5 月 7 日 00:08很遗憾你的模组制作尝试不太成功。确实可以采用跳转到文件末尾再跳转回来的方法我在修改《国家的崛起》时就用了这种方法但一开始设置起来比较复杂因为需要为程序分配更多的空间。如果你要进行大规模的修改这种方法是值得的它能提供几乎无限的空间但对于这种一次性的修改可能就没必要了。到时候你也可以考虑其他实现大规模修改的方法说实话那些方法可能更合理不过因为我在《国家的崛起》中用了这种方法所以我对它最熟悉。如果有足够的空间你可以添加一些几乎全新的内容但你得了解新代码开始时系统的状态寄存器、堆栈、内存知道如何改变这个状态以实现你想要的功能包括如何设置状态以便能够调用各个函数完成后还得将状态恢复到原来的样子让程序能继续执行原始代码恢复状态相对简单。如果你只是跳进去修改一些东西就不需要了解太多系统状态和如何改变它因为你不一定需要知道如何将飞行员信息或武器信息提取到寄存器/内存中以进行使用/读取/操作只要修改的内容较小需要理解的范围就很有限。至于这个函数的设置方式有可能是编译器的原因原始的 C 函数可能更易读。因为我不太清楚武器数据是如何处理的所以很难说而且我也没有关于编译器在将 C 代码转换为汇编/机器代码时如何具体修改代码结构的实际经验。没错看起来大型武器分配到躯干小型武器分配到手臂。我也不太清楚为什么要这样设置。如果 MechCommander 2 对某些方面很挑剔鉴于目前这两款游戏在底层看起来惊人地相似MechCommander 1 很可能也会如此。你也可以看看现有的一些 MechCommander 1 模组也许有人有相关的经验可以分享毕竟已经有一些人添加了新武器之类的内容。
修复《机甲指挥官》“左臂漏洞”:乐趣与收获兼得,附详细操作及更新补丁!
发布时间:2026/7/10 5:21:06
修复《机甲指挥官》的“左臂漏洞”乐趣与收获兼得MechCommander 1有个恼人的问题它会把机甲上的大型武器都集中放置在左臂。要是你的机甲主要或只装备了大型武器一旦失去左臂基本上这台机甲就废了。通常这个问题对任务的影响不大。精确瞄准机甲的特定部位命中率很低就算是射击技巧高超的飞行员也不例外所以对敌方机甲而言这问题影响有限而己方机甲恰好失去左臂的概率也不高——尽管这种情况确实可能发生。不过这问题依旧很奇怪一旦发生还是会让人有些头疼。不过现在好了之前我受 Vana 启发开始思考为何武器组件分配代码对大型武器不起作用花了一天时间研究终于找到了解决办法。这里我所说的“左臂”其实并不明确它到底是“左臂”还是“右臂”因为机甲在失去手臂后视觉显示并不一致。但根据手册中“射击左臂”指令所对应的部位我就暂且称之为左臂。大约一个月前我发现 MechCommander 1至少我手头的 MechCommander Gold 版本似乎嵌入了某种调试符号这让我们能大致了解游戏代码的实际运行情况。这意味着我们可以深入探究以下问题哪些武器算“大型”武器是我之前听说的重量≥9 吨的规则吗武器和装备是如何分配到机甲各个部位的为什么大型武器会全部集中在左臂嘿这门长汤姆炮看起来可真大——我觉得能算“大型”游戏的可执行文件是机器代码若先进行反汇编则是汇编语言。不过借助像 Ghidra 这样的工具没错它由美国国家安全局开发我们能把单个函数转化为类似 C 语言的代码。这种转化后的代码结构可能和原始源代码不同但比汇编代码更易读。首先这是一个判断武器是否为“大型”的函数这和“左臂漏洞”密切相关。结合 compbas.csv 文件中的武器 ID该文件包含在 MISC.FST 文件中以及其他信息包括我自己的一些测试我们可以列出“大型”和“小型”武器的清单“小型”武器就是那些未被明确定义为“大型”的武器。从这个列表中我们首先能注意到LRM 用“发射架”SRM 用“发射包”这对对抗氏族入侵者来说可是关键信息。要是有人把它们叫错可没法指望内环星域用命名错误的装备打仗。其次《绝境之战》扩展包中新增的所有武器都被错误地归类为“小型”武器因为 getWeaponLarge() 函数显然没有更新以考虑这些新武器而该分类函数对于未明确排除的武器默认输出为“小型”。有些分类界限比较模糊。比如轻型自动加农炮重 9.5 吨被归为“大型”而同样重量的大型激光炮却不算“大型”。我个人觉得如果大型激光炮不算“大型”那轻型自动加农炮也不该算反之如果轻型自动加农炮算“大型”那大型激光炮也应该算。不过这也没什么好纠结的目前的分类也有其合理性。这也表明“重量≥9 吨即为大型武器”的规则并不完全准确——就算把《绝境之战》中分类错误的武器都排除在外。前面提到的大型激光炮9.5 吨和氏族轻型超高速自动加农炮8.5 吨就不符合这个规则。为了验证我们的理解是否正确我们可以故意制造一些友军误伤事件。这些测试结果表明“大型”武器确实都集中在左臂也有可能纸娃娃系统是镜像显示的或者它们都在右臂而手册中“左臂”的说法有误。“小型”武器不会只集中在左臂而是更均匀地分布在机甲各处。《绝境之战》中的武器被错误地归类为“小型”武器实际上它们应该是“大型”武器。机甲飞行员应该组织工会维权。如果你仔细观察可能会发现测试中的机甲有时看起来是右臂被摧毁而不是左臂。这可能是视觉漏洞也可能是资源限制也许开发者没有为每个缺失的手臂制作单独的模型——机甲模型上缺失的手臂似乎会根据机甲的朝向或者其他未知因素而变化。我可不想去修复游戏里的每一个漏洞所以就先不管这个了。还有个奇怪的现象在重型 LB - X 测试中Beast 的生命值能量条显示大部分武器已损坏但实际上武器都还能正常使用。我原本担心游戏实际功能和界面上的武器显示不一致但所有武器都能正常开火——我猜可能是飞行员的生命值加上武器所在部位受到了一些损伤。也许是侧躯干在手臂被摧毁时受到了一些结构损伤但在大纸娃娃界面上没有显示因为还有护甲只在屏幕底部的简化界面上有所体现。虽然这个纸娃娃显示差异的问题很有意思但深入探究超出了本文的范围我们接着往下看吧。武器分配靠代码而非自然法则那么一般来说装备是如何分配到机甲各个部位的呢首先我们要找到游戏代码中处理这个问题的部分。判断是否找对代码的一个方法是修改疑似的函数然后看看游戏里会发生什么。我修改了疑似的函数让未知物品被分配到不该去的地方。修改后炸掉机甲的左臂会直接导致飞行员死亡但机甲的武器却不会损坏。左臂被炸掉、飞行员死亡后我又射击地上的机甲炸掉它们的右臂武器依然完好无损——这也算是修改带来的一个有趣副作用吧。我其实很好奇武器到底被分配到了哪些部位但在这个过程中我没办法逐一探究所有问题所以就先不研究这个了精确瞄准特定部位射击非常耗时就算是静止目标也不轻松所以要通过实验来确定并不容易。通过调试器追踪装备在机甲上的分配过程我发现我的修改可能至少把生命维持系统和引擎移到了左臂这就能解释为什么这些部件损坏时机甲和飞行员都会受损。这其实很有趣因为这表明《机甲指挥官》至少在一定程度上会使用这类“内部装备”而不是仅仅依靠检查特定部位头部、中心躯干等的结构状况——这和我之前的想法不太一样。顺便说一下在我的测试中这些组件似乎被分配到了机甲的不同部位我没有具体记录每个部位分配到了哪些装备生命维持系统2 个髋关节2 个肩关节陀螺仪传感器推测具体传感器类型会和机甲装备的一致驾驶舱2 个腿部驱动器2 个手臂驱动器核聚变引擎我不能保证所有这些装备都真的有作用但从上面观察到的“炸臂致死”现象来看至少有一部分装备对游戏是有影响的。不过深入研究这些超出了本文的范围。如果想真正解决问题有时候就得果断放弃那些在知识丛林中看似诱人但实则无关的探索。下面是处理装备分配的函数的开头部分。我就不详细讲解整个函数了它有几百行代码我也没完全搞懂它的所有功能而且深入讲解会偏离本文的主题。对我们来说关键是函数开头对 param_1 和 100 的比较。在基础游戏中武器的 ID 从 100 开始这让我们推测函数开头部分处理的是非武器装备的放置比如上面提到的那些组件。现有证据支持这个推测所以这个推测可能至少大部分是正确的但要完全证实它超出了本文的范围。我们真正关心的是这个函数如何处理武器ID 大于等于 100 的装备的放置。多亏了调试符号提供的函数名只要对被调用函数的功能做一些假设大部分高层逻辑还是很清晰的检查武器是大型还是小型。如果是小型武器根据检查这些部位小型武器情况的算法将其分配到 2 - 5 号部位。如果是大型武器根据检查这些部位大型武器情况的算法将其分配到 2 - 5 号部位。合理分配手臂武器让机甲火力不流失从前面的情况到最终找出问题所在这是整个过程中最耗时的部分但其实没什么意思所以我就说重点跳过那些无聊的细节。getWeaponLarge() 函数本身似乎运行正常不过它的设计本身也有一些问题比如对《绝境之战》武器的处理所以问题应该不在这。getSmallWeaponCount() 和 getLargeWeaponCount() 函数也都运行正常所以问题也不在这。左臂或者说使用“射击左臂”指令时实际射击的那个部位似乎是 4 号部位我猜其他三个部位分别是右臂、左躯干和右躯干但我不知道具体哪个数字对应哪个部位而且去弄清楚这个超出了本文的范围。通过追踪组件分配过程我们可以看到游戏中的情况在内存中得到了反映大型武器都集中在同一个地方而小型武器则分布在不同位置。注意观察氏族 ER PPC 炮中右图蓝色轮廓和氏族 ER 大型激光炮中右图红色轮廓在内存中是连续放置的这意味着它们在同一个部位。相比之下氏族脉冲激光炮和氏族重型火焰喷射器下图粉色轮廓在这张截图中分布在两个不同的地方。下图中的蓝色轮廓可能是肩部和手臂驱动器因为它们的组件 ID 相符这表明这两个部位是手臂。最后我像个原始人一样手动逐行追踪代码终于找出了问题所在。小型武器的放置逻辑是第一把武器会被放置在第一个被检查的部位4 号这样当检查第二把武器时由于第一个位置已经有小型武器了它就会被放到第二个位置。这个过程会一直重复直到每个位置都有一把武器然后是两把、三把以此类推直到所有小型武器都放置完毕。如果所有位置都没有小型武器那么武器会被放置在第一个位置。而大型武器的情况不同因为其“备用”值会将武器放置在最后一个位置。所以每把大型武器在检查过程中直到最后一个位置才会找到有武器的位置然后就都被放到了同一个地方也就是左臂。这个“备用”值应该和小型武器的算法保持一致第一把大型武器应该被放置在 2 号位置因为大型武器的检查是从这里开始的这样后续的武器在第一次检查时就会发现这个位置已经有武器了。“备用”值的来源是左图顶部的 iVar6 变量其值为 0。由于小型武器和大型武器的位置检查顺序不同4 - 5 - 2 - 3 与 2 - 3 - 4 - 5适用于小型武器放置计算的“备用”值并不适用于大型武器的放置计算。说句题外话我有点奇怪为什么要花这么多精力来区别分配小型武器和大型武器。也许原本的意图是避免因实现错误而导致的问题——把机甲上最重要的武器集中在一个部位。想象一下如果一台机甲装备了两门非常大/重的武器比如中型机甲上的两门 ER PPC 炮再搭配一些轻型武器为了降低风险肯定不希望这两门 PPC 炮都在同一个地方。如果这真的是设计初衷那这个漏洞就有点讽刺了。前面说过我们看到的代码不是原始源代码只是编译代码的类 C 语言表示方便我们快速理解。要修复这个问题我们得回到原始的汇编代码之前没给大家看是因为你们可能看不懂我也不想在这里上一堂汇编语言入门课。我们关注的值存储在 [EDI 寄存器](https://wiki.osdev.org/CPU_Registers_x86) 中绿色和黄色高亮部分。通常会用 XOR 指令将这个寄存器的值设为 0。这对于小型武器的放置没问题但对于大型武器我们需要将其值设为 2而不是 0。我们不能直接修改这个值因为这样会破坏小型武器的放置逻辑而且这里没有足够的空间来设置两个不同的值插入新字节会使整个程序偏移导致程序无法正常运行。我们可以做的是在附近找一些未使用的字节——也就是一个“代码洞穴”跳转到那个位置进行修改。在 placeItem() 函数下方下一个函数的末尾有几个未使用的字节数量刚好合适。跳转到这个代码洞穴后刚好有足够的空间重写为了跳转到这里而不得不覆盖的指令然后将 2 写入 EDI 寄存器作为大型武器的“备用”值最后再跳回原始代码。这就是修改后的样子修复效果验证应用这个修复并再次制造一次友军误伤事件看起来修复成功了大型武器现在分布在机甲的双臂以及另外两个可能是侧躯干的部位。根据这个结果我们还可以推测 2 号部位大型武器首先放置的位置是侧躯干5 号部位是右臂——因为失去双臂后我们还剩下 4/7 的武器而且我们知道 4 号和 5 号部位在 2 号和 3 号部位之前接收大型武器。不过还有个问题没搞清楚为什么 Beast 认为失去双臂和 3/7 的武器后自己的生命值能量只剩下 25%。和之前的 LB - X 测试不同这次侧躯干损伤有限飞行员也没有受伤无法解释这个差异。也许是生命值条或者其底层数值的计算方式有漏洞比如手臂的生命值是硬编码的……不这超出了本文的范围我不打算去修复它修复“左臂漏洞”的操作方法如果你想在自己的 MechCommander Gold 可执行文件中应用这个修改先备份文件然后用十六进制编辑器打开可执行文件在原始地址 0xEB48C 处将两个字节 E8 7F 替换为 E9 70。在原始地址 0xEB601 处将十五个字节 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 替换为 E8 0A 00 00 00 BF 02 00 00 00 E9 81 FE FF FF。如果这些地址的字节和这里写的不一样可能你玩的游戏版本和我处理的不同**不要**覆盖这些字节否则你的游戏可能无法正常运行。关于《绝境之战》武器分类问题嘿Beast希望你恢复得不错。感谢你指出这个问题。我们很关心飞行员的健康也很重视你在讨论中的贡献。说实话我觉得这些武器的分类问题影响不大。所有的 LB - X 自动加农炮都没什么用你根本不会去装备它们轨道炮和长汤姆加农炮太重了一台机甲不太可能装备多门雷霆炮在《绝境之战》战役中和那些顶级武器相比也比较平庸就算装备也只会偶尔用用。这样看来受影响最大的就只有大型 X 脉冲激光炮了而且这个问题的影响比“左臂漏洞”小很多。不过既然我们不介意破坏那些可能未使用武器的分类修复这个问题比修复“左臂漏洞”要容易得多那我就顺手把它修了吧。原始代码采用的是默认小型武器的系统函数中未明确指定为大型的武器都会被归类为小型。但由于《绝境之战》中新增的所有武器实际上都应该是大型武器修改时我们把规则反过来默认是大型武器然后明确将小型武器归类为小型这样会更容易一些。我们还可以去掉对游戏中不存在武器的引用在修改时节省一些空间——这个函数没有多余的空间来扩展长度因为它下面的空闲空间就是我们之前使用的代码洞穴从技术角度看修改后的函数稍微短了一点但性能上可能会慢一点点因为我在替换代码时优先考虑了代码的可读性而不是复制原有的性能优化方案。我没有改变大型激光炮和轻型自动加农炮的分类前者仍然是“小型”后者仍然是“大型”。和原始实现一样这个修订版本的逻辑仍然是基于对武器列表的假设所以如果我对某个武器的判断有误或者你进行了一些新武器的模组化操作这个函数可能会像原来一样出现分类错误的情况。通过暂时撤销“左臂漏洞”的修复补丁我们可以在确保 Beast 得到充分训练的同时对大型/小型武器分类的修改进行验证。看起来这个修改是有效的——至少对这把武器是这样Beast 也能好好休息一下了。去你的指挥官我听到你说的话了如果你想在自己的 MechCommander Gold 版本中应用这个武器分类函数的修改先备份文件然后用十六进制编辑器打开可执行文件在原始地址 0xEB5B0 处将 81 个字节 55 8B EC 8A 45 08 3C 64 72 04 3C 68 76 3A 3C 6E 72 04 3C 71 76 32 3C 79 74 2E 3C 7A 74 2A 3C 83 74 26 3C 84 74 22 3C 8D 74 1E 3C 8E 74 1A 3C 91 74 16 3C 92 74 12 3C 96 74 0E 3C 97 74 0A 3C 9A 74 06 33 C0 5D C2 04 00 B8 01 00 00 00 5D C2 04 00 替换为 55 8B EC 8A 45 08 3C 78 74 39 3C 7B 74 35 3C 7D 74 31 3C 82 74 2D 3C 85 74 29 3C 87 74 25 3C 8C 74 21 3C 8F 74 1D 3C 90 74 19 3C 93 74 15 3C 98 74 11 3C 99 74 0D 3C 9B 74 09 B8 01 00 00 00 5D C2 04 00 33 C0 5D C2 04 00 90 90 90 90 90 90 90 90。注意这两个序列的前几个字节是相同的这是有意为之。编辑说明2026 - 05 - 05 编辑我刚意识到默认设为大型武器可能会影响弹药的分配也就是说修改后弹药可能会和大型武器一起分配而不是和小型武器一起。我还没有实际确认弹药是如何分配的但我有 80% 的把握我是对的所以我会修复这个问题。如果不考虑代码的可读性幸运的是仍然有足够的空间将函数重新编写为默认小型武器而不需要再去其他地方找空间。由于大多数大型武器是连续分组的可以在每次比较时检查多个武器以弥补大型武器数量远多于小型武器的情况在原始地址 0xEB5B0 处将 81 个字节 55 8B EC 8A 45 08 3C 64 72 04 3C 68 76 3A 3C 6E 72 04 3C 71 76 32 3C 79 74 2E 3C 7A 74 2A 3C 83 74 26 3C 84 74 22 3C 8D 74 1E 3C 8E 74 1A 3C 91 74 16 3C 92 74 12 3C 96 74 0E 3C 97 74 0A 3C 9A 74 06 33 C0 5D C2 04 00 B8 01 00 00 00 5D C2 04 00 替换为 55 8B EC 8A 45 08 3C 62 72 04 3C 68 76 3A 3C 6B 72 04 3C 71 76 32 3C 74 72 04 3C 76 76 2A 3C 7E 74 26 3C 8B 72 04 3C 8E 76 1E 3C 91 72 04 3C 92 76 16 3C 96 72 04 3C 97 76 0E 3C 9A 74 0A 3C A0 74 06 33 C0 5D C2 04 00 B8 01 00 00 00 5D C2 04 00。2026 - 05 - 06 编辑如果你希望轨道炮和轻型高斯步枪也被识别为大型武器还需要将原始地址 0xEB1AD 处的字节从 0x64 改为 0x62这会将非武器组件的截止值从 100 改为 98。我上面介绍的两个修复补丁可以同时应用我也建议你这么做。不过要说明的是我没有对这些修改进行全面测试它们看起来是正确的我使用时也没有遇到崩溃问题但这并不代表没有隐患。请自行承担使用风险如果你遇到了之前没有的崩溃问题请回来告诉我。我只是个初次尝试修改 MechCommander 1 的玩家只是在其他事情之余抽空做了这些一次性的修改工作。最新更新2026 - 05 - 26 更新如果你觉得十六进制编辑很麻烦我做了一个小补丁工具可以自动完成这些修复以及其他一些操作上面的截图中轻型 LB - X 测试似乎还有另一个奇怪的漏洞有一把轻型 LB - X 显示为可操作但 Beast 却无法开火而且也不是弹药不足的问题除非弹药显示也出错了。我很想知道这是怎么回事……不这超出了本文的范围不管了不管了我要退出这个问题的研究评论与回复1. Vana 评论2026 年 5 月 6 日 20:38我最近沉迷于 MechCommander 1 和 MechCommander 2但我想实现的功能好像没办法按照我期望的方式实现。武器方面多带点武器能让元素战士不敢靠近但要是带太多发射架可得小心背后。从魔法角度看调整一个变量或者稍微重新排列现有函数比添加全新的内容要容易得多。除非你能直接跳到文件末尾在那里做任何你想做的事然后再跳回来。虽然这样可能效率不高但这个函数在一次任务中可能只使用一次。不过我对汇编语言了解不多只知道它很复杂。那一连串的 if() if() 语句看起来不是个好方法他们本可以在武器定义中设置一个标志之类的东西。如果我理解正确的话小型武器优先分配到手臂大型武器优先分配到躯干。这和游戏中大多数机甲的经典布局相反但这样一来失去手臂损失的火力会少一些而且 PC 版游戏中手臂的射击角度几乎没有区别。最后说说 LBX……我在想武器是否需要和弹药放在同一个位置或者它们只能从自己的弹药箱获取弹药。Mechcommander 2 的机甲定义似乎很强调部件顺序。但这些都超出了本文的范围。你能解决这个问题真的很厉害。2. MHLoppy 回复2026 年 5 月 7 日 00:08很遗憾你的模组制作尝试不太成功。确实可以采用跳转到文件末尾再跳转回来的方法我在修改《国家的崛起》时就用了这种方法但一开始设置起来比较复杂因为需要为程序分配更多的空间。如果你要进行大规模的修改这种方法是值得的它能提供几乎无限的空间但对于这种一次性的修改可能就没必要了。到时候你也可以考虑其他实现大规模修改的方法说实话那些方法可能更合理不过因为我在《国家的崛起》中用了这种方法所以我对它最熟悉。如果有足够的空间你可以添加一些几乎全新的内容但你得了解新代码开始时系统的状态寄存器、堆栈、内存知道如何改变这个状态以实现你想要的功能包括如何设置状态以便能够调用各个函数完成后还得将状态恢复到原来的样子让程序能继续执行原始代码恢复状态相对简单。如果你只是跳进去修改一些东西就不需要了解太多系统状态和如何改变它因为你不一定需要知道如何将飞行员信息或武器信息提取到寄存器/内存中以进行使用/读取/操作只要修改的内容较小需要理解的范围就很有限。至于这个函数的设置方式有可能是编译器的原因原始的 C 函数可能更易读。因为我不太清楚武器数据是如何处理的所以很难说而且我也没有关于编译器在将 C 代码转换为汇编/机器代码时如何具体修改代码结构的实际经验。没错看起来大型武器分配到躯干小型武器分配到手臂。我也不太清楚为什么要这样设置。如果 MechCommander 2 对某些方面很挑剔鉴于目前这两款游戏在底层看起来惊人地相似MechCommander 1 很可能也会如此。你也可以看看现有的一些 MechCommander 1 模组也许有人有相关的经验可以分享毕竟已经有一些人添加了新武器之类的内容。