プログラミング
MechCommanderの「左腕バグ」を楽しみと利益のためにパッチ適用する
Patching MechCommander's "left arm bug" for fun and profit (mhloppy.com)
要約
MechCommander 1には、メックの最も強力な兵器がすべて左腕に集中してしまうという奇妙なバグが存在する。このバグは、強力な兵器を多数装備したメックの左腕が破壊されると、そのメックがほぼ無力化されるという問題を引き起こす。著者は、逆アセンブラやGhidraなどのツールを用いてゲームのコードを解析し、兵器の「大型」「小型」の分類ロジックを特定した結果、拡張パックの兵器が誤って「小型」に分類されていることが原因であることを突き止めた。この発見に基づき、著者はバグ修正パッチを作成した。
全文翻訳
MechCommanderの「左腕バグ」を楽しみと利益のためにパッチ適用する
MechCommander 1には、メックの最も強力な兵器がすべて左腕に集中してしまうという、厄介な癖があります。もしあなたのメックがほとんど、あるいはすべて強力な兵器で武装されている場合、その腕を失うことは、実質的にメックを失うことを意味します。
通常、この問題はミッションの結果に大きな影響を与えません。メックの個々の部位を特に狙うことは、(射撃能力の高いパイロットでも)精度がかなり低いため、敵メックにとってはあまり問題になりません。また、自分のメックの腕だけが偶然失われる確率はかなり低いですが、起こり得ます。それでも奇妙な問題であり、あなたに起こるたびに少し辛いことがあります。
もうそんなことはありません!Vanaに、コンポーネントの配布コードが強力な兵器に対して機能していないように見える理由について脳みそを汚染された後、私は一日かけてそれを解明し、動作する修正パッチを作成しました。(注:問題の部位を「左腕」と呼びますが、それが実際に「左腕」なのか「右腕」なのかは不明であり、メックのビジュアルは腕を失った後に一貫性がありません。これは、マニュアルに記載されている「左腕を撃て」コマンドを使用したときに破壊される部位であり、それに従っています。)
約1ヶ月前、MechCommander 1(少なくとも私の持っているMechCommander Goldのコピー)には、ある種の埋め込みデバッグシンボルが含まれているようで、ゲームのコードが実際に行っていることについて、有用な限定的な洞察が得られることに気づきました。これにより、以下のことを調べることができます。
どの兵器が「大型」と見なされるか(よく見かける「9トン以上」というルールか?)
兵器と装備がメックにどのように配布されるか
なぜ「大型」兵器が特にすべて左腕に集中するのか
Sir, this Long Tom looks real big from down here — I think we can call it “big”
ゲームの実行ファイル自体は機械語(または最初に逆アセンブルされた場合はアセンブリ)です。しかし、Ghidra(NSAの素晴らしい人々によるツール)のようなツールのおかげで、個々の関数をCライクなコードに変換することもできます。この変換は、元のソースコードの構造と必ずしも正確ではありませんが、アセンブリよりも一目で読みやすいことが一般的です。
まず、左腕バグに関連する「大型」または「ラージ」と分類されるかどうかを決定すると思われる関数を以下に示します。
compbas.csvファイル(MISC.FSTファイルにパックされています)内の兵器IDや、その他の情報(自身のテストを含む)と組み合わせることで、これを「大型」と「小型」兵器のリストに変換できます。「小型」は、明示的に「大型」として定義されていないものすべてです。
ID Weapon Availability Tonnage Size
98 Rail Gun Expansion only 30.0 Small
99 Light Gauss Rifle Expansion only 13.5 Small
100 Light Autocannon Base game 9.5 Large
101 Autocannon Base game 15.5 Large
102 Heavy Autocannon Base game 19.5 Large
103 Light Ultra Autocannon Base game 11.0 Large
104 Gauss Rifle Base game 16.5 Large
107 Light LB-X Autocannon Expansion only 9.5 Small
108 LB-X Autocannon Expansion only 14.5 Small
109 Heavy LB-X Autocannon Expansion only 19.5 Small
110 C. Light Ultra Autocannon Base game 8.5 Large
111 C. Ultra Autocannon Base game 13.5 Large
112 C. Heavy Ultra Autocannon Base game 17.5 Large
113 C. Gauss Rifle Base game 13.5 Large
116 C. Light LB-X Autocannon Expansion only 8.5 Small
117 C. LB-X Autocannon Expansion only 13.5 Small
118 C. Heavy LB-X Autocannon Expansion only 17.5 Small
120 LRM Rack Base game 4.0 Small
123 SRM Pack Base game 3.0 Small
125 Streak SRM Pack Base game 5.0 Small
126 Heavy Thunderbolt Expansion only 21.0 Small
130 C. LRM Rack Base game 3.0 Small
133 C. SRM Pack Base game 3.0 Small
135 C. Streak SRM Pack Base game 4.75 Small
139 Large X-Pulse Laser Expansion only 13.0 Small
140 Laser Laser Base game 9.5 Small
141 Large ER Laser Base game 11.0 Large
142 Large Pulse Laser Base game 12.0 Large
143 Laser Base game 4.0 Small
144 Pulse Laser Base game 6.0 Small
145 PPC Base game 12.0 Large
146 ER PPC Base game 15.5 Large
147 Heavy Flamer Base game 8.0 Small
150 C. Large ER Laser Base game 10.0 Large
151 C. Large Pulse Laser Base game 11.0 Large
152 C. ER Laser Base game 3.5 Small
153 C. Pulse Laser Base game 4.0 Small
154 C. ER PPC Base game 13.5 Large
155 C. Heavy Flamer Base game 7.0 Small
160 Long Tom Cannon Expansion only 34.0 Small
(いくつかの無効な兵器、例えばgetWeaponLarge()関数で明示的にチェックされているLRM 15など、ゲーム内で実際には遭遇しないと思われるカットコンテンツは除外しています。チートでしか入手できないSniper Cannonも、この記事の目的ではアクセス不可能なコンテンツとして扱っています。)
最初の、そして最も明白な結論は、LRMはラック(rack)で、SRMはパック(pack)であるということです。これはクラン侵略者を倒す上で非常に重要な情報です。誰かがそれらをLRMパックやSRMラックと呼んだと想像できますか?内惑星連邦が間違った名前の装備で戦争を戦うことを期待することはできません。
2番目に明白な結論は、Desperate Measuresで追加されたすべての兵器が誤って「小型」兵器として分類されていることです。なぜなら、getWeaponLarge()関数はそれらを考慮するように更新されておらず、明示的な例外がない兵器に対する分類関数のデフォルト出力は「小型」だからです。
主観的に少し境界線上の分類がいくつかあります。Light Autocannonは9.5トンで「大型」ですが、Large Laserは同じ重量で「大型」とは見なされません。個人的には、Large Laserが「大型」でなければ、Light ACもそうであるべきか、あるいはLight ACがそうであるならLarge Laserもそうであるべきだと思いますが、これに悩むほどの価値はないと思いますし、現状を維持する合理的な議論もいくつかあります。
これはまた、「9トン以上なら大型」というルールは近いものの、正確ではないことを示しています。たとえ、誤って分類されたDesperate Measuresの兵器すべてにこのルールを包括的に除外したとしてもです。前述のLarge Laser(9.5トン)とClan Light Ultra Autocannon(8.5トン)がこのルールを破っています。
ベースラインの理解が正しいことを確認するために、パイロットにいくつかの誤射事故を経験させてみましょう。これらの結果は以下を支持しています。
「大型」兵器は左腕に入る(そしてペーパードールはミラーリングされているか、すべて右腕に入っておりミラーリングされておらず、マニュアルが「左腕」という用語を誤って使用している)。
「小型」兵器は左腕にだけ入るわけではなく、メック全体に分散している。
Desperate Measuresの兵器は、論理的には「大型」であるべきなのに、「小型」兵器として誤って分類されている。
メックパイロットは労働組合を結成すべきです。
よく見ると、テスト中のメックが左腕ではなく右腕を破壊されているように見えることがあります。これは単なるビジュアルバグか、アートリソースの制約(欠損した腕ごとに別のバージョンを作成しなかったのかもしれません)のようです。メックスプライトで視覚的に欠損している腕は、メックが向いている角度や、水星が逆行しているかどうかによって異なるようです。そして、このゲームにあるすべてのバグを修正する気はないので、無視しましょう。
もう一つの奇妙な点は、Heavy LB-Xのテストで、Beastのヘルス(パワー?)バーが、武器がすべて失われているわけではないのに、あたかもほとんどの武器が失われているかのように動作していることです。ゲーム内の実際の機能とUIの兵器リストが同期していないリスクがあるかもしれないと思いましたが、4つの兵器すべてが正常に発射されているように見えました。これはパイロットのヘルスと、おそらく4つの兵器すべてが配置されている場所へのダメージだと思われます。サイドトルソーが破壊された腕から構造的なダメージを受けており、それが大きなペーパードール(まだ装甲があるため)には表示されず、画面下部の簡略化されたものにだけ表示されているのでしょうか?
脱線としては興味深いですが、ペーパードールの不一致について正確に何が起こっているのかを解明することは、範囲外なので、次に進みましょう。
兵器の配布は、自然によって決定されるのではなく、コードによって決定されます。
さて、ではどのようにして、g