From 9755803949f25b88cf0e33fb6f63937e73df2ce8 Mon Sep 17 00:00:00 2001 From: RT Date: Fri, 7 Aug 2026 20:46:32 -0500 Subject: [PATCH] Fix external MFD and radar damage mappings Install the validated J&J coordinates for 19 external display sets across 13 chassis. Update all affected texuv2/offset2 and texuv3/offset3 rows while preserving the 65-mech positional layout and coord.cpp CRLF encoding. Add a reusable Pillow comparison generator, 38 red/green review maps, and a generated summary. The final audit reports 19 exact mappings, zero differences, zero input warnings, and seven display sets without complete supplied inputs. Normalize four unambiguous measurement transcription issues: Behemoth MFD LT 1742 to 174, Behemoth Radar CT punctuation and blank S2, and Fafnir MFD LL punctuation. Document the complete authoring and runtime workflow, including legacy tuple normalization, MFD/Radar scaling, odd-coordinate handling, canonical runtime names, pixel-versus-byte BMP comparison, validation checks, rebuild requirements, and the final installed-set inventory. Compare every supplied exploded runtime BMP against Gameleap/mw4/hsh. All 19 are already pixel-identical, so no runtime art files are replaced. --- ...hilator_mfd_exploded_coords_comparison.png | 3 + ...lator_mfd_unexploded_coords_comparison.png | 3 + ...lator_radar_exploded_coords_comparison.png | 3 + ...tor_radar_unexploded_coords_comparison.png | 3 + .../argus_mfd_exploded_coords_comparison.png | 3 + ...argus_mfd_unexploded_coords_comparison.png | 3 + ...assian2_mfd_exploded_coords_comparison.png | 3 + ...sian2_mfd_unexploded_coords_comparison.png | 3 + ...sian2_radar_exploded_coords_comparison.png | 3 + ...an2_radar_unexploded_coords_comparison.png | 3 + .../avatar_mfd_exploded_coords_comparison.png | 3 + ...vatar_mfd_unexploded_coords_comparison.png | 3 + ...vatar_radar_exploded_coords_comparison.png | 3 + ...tar_radar_unexploded_coords_comparison.png | 3 + .../Behemoth/HUD/Behemoth_HUD_unexploded.txt | 2 +- ...ehemoth_mfd_exploded_coords_comparison.png | 3 + ...emoth_mfd_unexploded_coords_comparison.png | 3 + .../Behemoth/Radar/Behemoth_exploded.txt | 4 +- ...emoth_radar_exploded_coords_comparison.png | 3 + ...oth_radar_unexploded_coords_comparison.png | 3 + ...ackhawk_mfd_exploded_coords_comparison.png | 3 + ...khawk_mfd_unexploded_coords_comparison.png | 3 + ...khawk_radar_exploded_coords_comparison.png | 3 + ...awk_radar_unexploded_coords_comparison.png | 3 + Finished HUDS from J&J/COMPARISON-SUMMARY.md | 82 ++++ .../fafnir_mfd_exploded_coords_comparison.png | 3 + ...afnir_mfd_unexploded_coords_comparison.png | 3 + .../Fafnir/HUD/fafnir_unexploded.txt | 2 +- .../flea_mfd_exploded_coords_comparison.png | 3 + .../flea_mfd_unexploded_coords_comparison.png | 3 + ...adiator_mfd_exploded_coords_comparison.png | 3 + ...iator_mfd_unexploded_coords_comparison.png | 3 + .../kodiak_mfd_exploded_coords_comparison.png | 3 + ...odiak_mfd_unexploded_coords_comparison.png | 3 + ...longbow_mfd_exploded_coords_comparison.png | 3 + ...ngbow_mfd_unexploded_coords_comparison.png | 3 + ...rhammer_mfd_exploded_coords_comparison.png | 3 + ...ammer_mfd_unexploded_coords_comparison.png | 3 + ...ammer_radar_exploded_coords_comparison.png | 3 + ...mer_radar_unexploded_coords_comparison.png | 3 + .../generate_comparison_maps.py | 320 +++++++++++++ ...spawn_radar_exploded_coords_comparison.png | 3 + ...awn_radar_unexploded_coords_comparison.png | 3 + .../code/CoreTech/Libraries/GameOS/coord.cpp | 76 +-- MFD-RADAR-MAPPINGS.md | 452 ++++++++++++++++++ 45 files changed, 1010 insertions(+), 42 deletions(-) create mode 100644 Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Argus/MFD/argus_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Argus/MFD/argus_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/AssassinII/Radar/assian2_radar_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/AssassinII/Radar/assian2_radar_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Avatar/MFD/avatar_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Avatar/MFD/avatar_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Avatar/Radar/avatar_radar_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Avatar/Radar/avatar_radar_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/COMPARISON-SUMMARY.md create mode 100644 Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Flea/MFD/flea_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Flea/MFD/flea_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Longbow/MFD/longbow_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Longbow/MFD/longbow_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_unexploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/generate_comparison_maps.py create mode 100644 Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_exploded_coords_comparison.png create mode 100644 Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_unexploded_coords_comparison.png create mode 100644 MFD-RADAR-MAPPINGS.md diff --git a/Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..07b733fb --- /dev/null +++ b/Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e181200a51df18eac4ec9cc46194b93098d17bf91c557a57b55af09d42a5e9f +size 9437 diff --git a/Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..7c2c1e14 --- /dev/null +++ b/Finished HUDS from J&J/Annihilator/MFD/annihilator_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40965a9cbcf4e6b8fd6feec12100edb1d817180e8d3bab9bbde9275cccdc0704 +size 9764 diff --git a/Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_exploded_coords_comparison.png b/Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_exploded_coords_comparison.png new file mode 100644 index 00000000..ea5e7aee --- /dev/null +++ b/Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79f0680600a72deb11efed11213008d33f2f06c27c416f5a2e14347ae27cdfc8 +size 72966 diff --git a/Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_unexploded_coords_comparison.png b/Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_unexploded_coords_comparison.png new file mode 100644 index 00000000..60d44b0f --- /dev/null +++ b/Finished HUDS from J&J/Annihilator/Radar/annihilator_radar_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d6142a86bb7561a65efa8ba78ec3dfa79bc6cebd6089b0b34cbe80adb40bc15 +size 68459 diff --git a/Finished HUDS from J&J/Argus/MFD/argus_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Argus/MFD/argus_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..00aca447 --- /dev/null +++ b/Finished HUDS from J&J/Argus/MFD/argus_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac14f2364fd5570cc403d2a600e3bb211b02b4b8062fe572003b362628e9a321 +size 11628 diff --git a/Finished HUDS from J&J/Argus/MFD/argus_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Argus/MFD/argus_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..944ed420 --- /dev/null +++ b/Finished HUDS from J&J/Argus/MFD/argus_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:013849aa5b047297d95dab696154241ee038c098b8b9a98ba3ed014c0cd1b937 +size 11145 diff --git a/Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..0046b2f8 --- /dev/null +++ b/Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3693ee41a0df744c2977563a1a4301d6fda852d9c57a13c2a2528b386e7c2527 +size 13888 diff --git a/Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..d2a98eea --- /dev/null +++ b/Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2db21377ee7332167314e1cb1aaa3f70462f9483fcfb6c6ccbee75161c652701 +size 52631 diff --git a/Finished HUDS from J&J/AssassinII/Radar/assian2_radar_exploded_coords_comparison.png b/Finished HUDS from J&J/AssassinII/Radar/assian2_radar_exploded_coords_comparison.png new file mode 100644 index 00000000..c3c8da35 --- /dev/null +++ b/Finished HUDS from J&J/AssassinII/Radar/assian2_radar_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e0cbf20ebeba8ed61fa480c5448aed7299516a5a2be26c32e15f98775e7bf22 +size 49922 diff --git a/Finished HUDS from J&J/AssassinII/Radar/assian2_radar_unexploded_coords_comparison.png b/Finished HUDS from J&J/AssassinII/Radar/assian2_radar_unexploded_coords_comparison.png new file mode 100644 index 00000000..5f7a7483 --- /dev/null +++ b/Finished HUDS from J&J/AssassinII/Radar/assian2_radar_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1bd187f74dcae5890af5ed54046894beeab42c22ebd26854469299a508e33be3 +size 46330 diff --git a/Finished HUDS from J&J/Avatar/MFD/avatar_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Avatar/MFD/avatar_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..be87c4a2 --- /dev/null +++ b/Finished HUDS from J&J/Avatar/MFD/avatar_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd2b3fd993cf08f63da51ba96f783a66132dca41a247edef8da5998053b8343e +size 11538 diff --git a/Finished HUDS from J&J/Avatar/MFD/avatar_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Avatar/MFD/avatar_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..477a1aaf --- /dev/null +++ b/Finished HUDS from J&J/Avatar/MFD/avatar_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8306db9bb4d90bee5b1e581b1806b6af6db8bf351c5a75be00a43b9ce6458f35 +size 11716 diff --git a/Finished HUDS from J&J/Avatar/Radar/avatar_radar_exploded_coords_comparison.png b/Finished HUDS from J&J/Avatar/Radar/avatar_radar_exploded_coords_comparison.png new file mode 100644 index 00000000..ee5e6bf3 --- /dev/null +++ b/Finished HUDS from J&J/Avatar/Radar/avatar_radar_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1729e7304a749f654b803bd7ad3d92b48ba794714cfd43bf0b3e9ed05ee9f59 +size 81172 diff --git a/Finished HUDS from J&J/Avatar/Radar/avatar_radar_unexploded_coords_comparison.png b/Finished HUDS from J&J/Avatar/Radar/avatar_radar_unexploded_coords_comparison.png new file mode 100644 index 00000000..a706b9ba --- /dev/null +++ b/Finished HUDS from J&J/Avatar/Radar/avatar_radar_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7384197e535c71de259293a7096e93ccb40f36be69b495cb2b5e84fc108db1ae +size 77845 diff --git a/Finished HUDS from J&J/Behemoth/HUD/Behemoth_HUD_unexploded.txt b/Finished HUDS from J&J/Behemoth/HUD/Behemoth_HUD_unexploded.txt index c7b3e18e..027c13c2 100644 --- a/Finished HUDS from J&J/Behemoth/HUD/Behemoth_HUD_unexploded.txt +++ b/Finished HUDS from J&J/Behemoth/HUD/Behemoth_HUD_unexploded.txt @@ -3,7 +3,7 @@ RL 184,170,262,302 LA 12,106,126,174 RA 212,106,326,174 RT 176,86,226,174 -LT 110,82,160,1742 +LT 110,82,160,174 CT 140,96,198,224 CTR 0,0,0,0 HD 164,122,174,134 diff --git a/Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..9ecf859e --- /dev/null +++ b/Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:418a51ebe64002767376606bb6f5f2d81485895217ee5a13c855ed4a4dcb5e47 +size 15370 diff --git a/Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..ac2f6c1b --- /dev/null +++ b/Finished HUDS from J&J/Behemoth/HUD/behemoth_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6068d435861a52371eaeb9459dabbd924d88f90492855a15355bc0ae4aa61db1 +size 15043 diff --git a/Finished HUDS from J&J/Behemoth/Radar/Behemoth_exploded.txt b/Finished HUDS from J&J/Behemoth/Radar/Behemoth_exploded.txt index 1b87af96..8f7e7409 100644 --- a/Finished HUDS from J&J/Behemoth/Radar/Behemoth_exploded.txt +++ b/Finished HUDS from J&J/Behemoth/Radar/Behemoth_exploded.txt @@ -4,8 +4,8 @@ LA 8,26 RA 302,26 RT 294,130 LT 108,130 -CT 202.242 +CT 202,242 CTR 0,0 HD 230,174 S1 202,28 -S2 \ No newline at end of file +S2 0,0 \ No newline at end of file diff --git a/Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_exploded_coords_comparison.png b/Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_exploded_coords_comparison.png new file mode 100644 index 00000000..e02bfe88 --- /dev/null +++ b/Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce7480f25c30c0fdafa8a5dcb1837adb0529657f1654dd0fb7358dd89c668a81 +size 56993 diff --git a/Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_unexploded_coords_comparison.png b/Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_unexploded_coords_comparison.png new file mode 100644 index 00000000..805bde0d --- /dev/null +++ b/Finished HUDS from J&J/Behemoth/Radar/behemoth_radar_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4db4c17db9b6ee3139ed37ebbf0dd941d89a71aa53797e7ae76e5e5fe9cdf85 +size 53248 diff --git a/Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..31cbe458 --- /dev/null +++ b/Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:716e6ec03f1b17896ba1c3ada195474b01f426ec2a64c98f58b5e8b04895d755 +size 18133 diff --git a/Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..7310a02f --- /dev/null +++ b/Finished HUDS from J&J/BlackHawk/MFD/blackhawk_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e96de2f331de603099b540dd9b6d423faaecb756edc3f68a2b30ab227705282 +size 18171 diff --git a/Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_exploded_coords_comparison.png b/Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_exploded_coords_comparison.png new file mode 100644 index 00000000..1f83c15f --- /dev/null +++ b/Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4d314e80394666f1efdaf2e5760404fdae06d2ad7f0d9e9f8412f0a6c7c71f8 +size 83176 diff --git a/Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_unexploded_coords_comparison.png b/Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_unexploded_coords_comparison.png new file mode 100644 index 00000000..ceabab64 --- /dev/null +++ b/Finished HUDS from J&J/BlackHawk/Radar/blackhawk_radar_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5d81375a2a2e679593ff84341cc0c3e4ccca78fdbbf5c2e9f6c5a9453559432 +size 81139 diff --git a/Finished HUDS from J&J/COMPARISON-SUMMARY.md b/Finished HUDS from J&J/COMPARISON-SUMMARY.md new file mode 100644 index 00000000..2fa99107 --- /dev/null +++ b/Finished HUDS from J&J/COMPARISON-SUMMARY.md @@ -0,0 +1,82 @@ +# J&J Coordinate Comparison Summary + +Generated by `generate_comparison_maps.py`. Red is the current `coord.cpp` mapping; green is the provided J&J mapping. + +`EXACT` means all eleven source rectangles and all eleven exploded offsets match numerically. `DIFFERENT` means at least one value differs; inspect both generated images. + +| Mech | Display | Status | Source rectangles different | Exploded offsets different | +|---|---:|---:|---:|---:| +| Annihilator | MFD | **EXACT** | 0/11 | 0/11 | +| Annihilator | RADAR | **EXACT** | 0/11 | 0/11 | +| Argus | MFD | **EXACT** | 0/11 | 0/11 | +| AssassinII | MFD | **EXACT** | 0/11 | 0/11 | +| AssassinII | RADAR | **EXACT** | 0/11 | 0/11 | +| Avatar | MFD | **EXACT** | 0/11 | 0/11 | +| Avatar | RADAR | **EXACT** | 0/11 | 0/11 | +| Behemoth | MFD | **EXACT** | 0/11 | 0/11 | +| Behemoth | RADAR | **EXACT** | 0/11 | 0/11 | +| BlackHawk | MFD | **EXACT** | 0/11 | 0/11 | +| BlackHawk | RADAR | **EXACT** | 0/11 | 0/11 | +| Fafnir | MFD | **EXACT** | 0/11 | 0/11 | +| Flea | MFD | **EXACT** | 0/11 | 0/11 | +| Gladiator | MFD | **EXACT** | 0/11 | 0/11 | +| hellspawn | RADAR | **EXACT** | 0/11 | 0/11 | +| Kodiak | MFD | **EXACT** | 0/11 | 0/11 | +| Longbow | MFD | **EXACT** | 0/11 | 0/11 | +| Warhammer | MFD | **EXACT** | 0/11 | 0/11 | +| Warhammer | RADAR | **EXACT** | 0/11 | 0/11 | + +## Missing comparison inputs + +- `Argus` RADAR: no complete provided mapping/image set configured +- `Fafnir` RADAR: no complete provided mapping/image set configured +- `Flea` RADAR: no complete provided mapping/image set configured +- `Gladiator` RADAR: no complete provided mapping/image set configured +- `Kodiak` RADAR: no complete provided mapping/image set configured +- `Longbow` RADAR: no complete provided mapping/image set configured +- `hellspawn` MFD: no complete provided mapping/image set configured + +## Input warnings + +- None + +## Generated files + +- `Annihilator/MFD/annihilator_mfd_unexploded_coords_comparison.png` +- `Annihilator/MFD/annihilator_mfd_exploded_coords_comparison.png` +- `Annihilator/Radar/annihilator_radar_unexploded_coords_comparison.png` +- `Annihilator/Radar/annihilator_radar_exploded_coords_comparison.png` +- `Argus/MFD/argus_mfd_unexploded_coords_comparison.png` +- `Argus/MFD/argus_mfd_exploded_coords_comparison.png` +- `AssassinII/HUD/assian2_mfd_unexploded_coords_comparison.png` +- `AssassinII/HUD/assian2_mfd_exploded_coords_comparison.png` +- `AssassinII/Radar/assian2_radar_unexploded_coords_comparison.png` +- `AssassinII/Radar/assian2_radar_exploded_coords_comparison.png` +- `Avatar/MFD/avatar_mfd_unexploded_coords_comparison.png` +- `Avatar/MFD/avatar_mfd_exploded_coords_comparison.png` +- `Avatar/Radar/avatar_radar_unexploded_coords_comparison.png` +- `Avatar/Radar/avatar_radar_exploded_coords_comparison.png` +- `Behemoth/HUD/behemoth_mfd_unexploded_coords_comparison.png` +- `Behemoth/HUD/behemoth_mfd_exploded_coords_comparison.png` +- `Behemoth/Radar/behemoth_radar_unexploded_coords_comparison.png` +- `Behemoth/Radar/behemoth_radar_exploded_coords_comparison.png` +- `BlackHawk/MFD/blackhawk_mfd_unexploded_coords_comparison.png` +- `BlackHawk/MFD/blackhawk_mfd_exploded_coords_comparison.png` +- `BlackHawk/Radar/blackhawk_radar_unexploded_coords_comparison.png` +- `BlackHawk/Radar/blackhawk_radar_exploded_coords_comparison.png` +- `Fafnir/HUD/fafnir_mfd_unexploded_coords_comparison.png` +- `Fafnir/HUD/fafnir_mfd_exploded_coords_comparison.png` +- `Flea/MFD/flea_mfd_unexploded_coords_comparison.png` +- `Flea/MFD/flea_mfd_exploded_coords_comparison.png` +- `Gladiator/MFD/gladiator_mfd_unexploded_coords_comparison.png` +- `Gladiator/MFD/gladiator_mfd_exploded_coords_comparison.png` +- `hellspawn/radar/hellspawn_radar_unexploded_coords_comparison.png` +- `hellspawn/radar/hellspawn_radar_exploded_coords_comparison.png` +- `Kodiak/MFD/kodiak_mfd_unexploded_coords_comparison.png` +- `Kodiak/MFD/kodiak_mfd_exploded_coords_comparison.png` +- `Longbow/MFD/longbow_mfd_unexploded_coords_comparison.png` +- `Longbow/MFD/longbow_mfd_exploded_coords_comparison.png` +- `Warhammer/MFD/warhammer_mfd_unexploded_coords_comparison.png` +- `Warhammer/MFD/warhammer_mfd_exploded_coords_comparison.png` +- `Warhammer/Radar/warhammer_radar_unexploded_coords_comparison.png` +- `Warhammer/Radar/warhammer_radar_exploded_coords_comparison.png` diff --git a/Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..76e5b351 --- /dev/null +++ b/Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d000d4e943f4bafa78746c2cbf4ba08542cbecd778a10cb82f71a44967a77907 +size 9602 diff --git a/Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..b0cb9bc0 --- /dev/null +++ b/Finished HUDS from J&J/Fafnir/HUD/fafnir_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9955e5a639a09289ac2da3a7413ac96eff8bf3ea460ad72a34008109b8e7fdcd +size 12639 diff --git a/Finished HUDS from J&J/Fafnir/HUD/fafnir_unexploded.txt b/Finished HUDS from J&J/Fafnir/HUD/fafnir_unexploded.txt index 5104f4c7..822e8600 100644 --- a/Finished HUDS from J&J/Fafnir/HUD/fafnir_unexploded.txt +++ b/Finished HUDS from J&J/Fafnir/HUD/fafnir_unexploded.txt @@ -1,4 +1,4 @@ -LL 86,142,162.326 +LL 86,142,162,326 RL 178,142,254,326 LA 24,22,68,134 RA 272,22,316,134 diff --git a/Finished HUDS from J&J/Flea/MFD/flea_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Flea/MFD/flea_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..0cc0c2c8 --- /dev/null +++ b/Finished HUDS from J&J/Flea/MFD/flea_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:106bcd70e726e2cd86b6503d1f8867acb93baff5736062c47a24d65ffc226d24 +size 12040 diff --git a/Finished HUDS from J&J/Flea/MFD/flea_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Flea/MFD/flea_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..e7314d6e --- /dev/null +++ b/Finished HUDS from J&J/Flea/MFD/flea_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a6889d849148c8abe63553011b72d54871dbfb40c9b3a35bc20fa4b3ec95c43 +size 10364 diff --git a/Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..0c03f2db --- /dev/null +++ b/Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78e7fb9f2b652a267fb6af2cb90ac90adb88586acdb7017afaeeb54400601f51 +size 12102 diff --git a/Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..87b9eba1 --- /dev/null +++ b/Finished HUDS from J&J/Gladiator/MFD/gladiator_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41ba6e86f32070a73b6d4396f312ef938834f0f6ca3e0eac19a90bc1037b7227 +size 10563 diff --git a/Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..7b225886 --- /dev/null +++ b/Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5ed1c5856bd383d8aae496cfb7adc0fa041d8de7c1b73bd7d55ce58b329ad67 +size 16334 diff --git a/Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..4d342798 --- /dev/null +++ b/Finished HUDS from J&J/Kodiak/MFD/kodiak_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7571a2101d0bed00046cb6a89bc402c2f2c4581a6391b1089a83ff8f7002da10 +size 16003 diff --git a/Finished HUDS from J&J/Longbow/MFD/longbow_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Longbow/MFD/longbow_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..ab37793b --- /dev/null +++ b/Finished HUDS from J&J/Longbow/MFD/longbow_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f9c56ef8c7249ffaae2d0db1934afe1838df5003a84bfd269e93b2edbfa32bf +size 14801 diff --git a/Finished HUDS from J&J/Longbow/MFD/longbow_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Longbow/MFD/longbow_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..ce186d8a --- /dev/null +++ b/Finished HUDS from J&J/Longbow/MFD/longbow_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c766cd5b362c771c1073a0dc61498d7e2d2f405924d4cfec7a93c1ca331cdfe +size 13071 diff --git a/Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_exploded_coords_comparison.png b/Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_exploded_coords_comparison.png new file mode 100644 index 00000000..cf6aea8a --- /dev/null +++ b/Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3046ab529acb820131833a5cd912b5686d52a5dd72298acbd5a901999c2d1cb3 +size 12429 diff --git a/Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_unexploded_coords_comparison.png b/Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_unexploded_coords_comparison.png new file mode 100644 index 00000000..39b937c9 --- /dev/null +++ b/Finished HUDS from J&J/Warhammer/MFD/warhammer_mfd_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e2b90ef78d35a3299f4e66a49af9ad5d3333c3134ee199fdf90b0b1ed4c9df3 +size 12415 diff --git a/Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_exploded_coords_comparison.png b/Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_exploded_coords_comparison.png new file mode 100644 index 00000000..0399a7d5 --- /dev/null +++ b/Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbf2191d46f7302311be9d22926ed011075933ab60a337ca9f2a889331523ab8 +size 67870 diff --git a/Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_unexploded_coords_comparison.png b/Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_unexploded_coords_comparison.png new file mode 100644 index 00000000..e5e3ce02 --- /dev/null +++ b/Finished HUDS from J&J/Warhammer/Radar/warhammer_radar_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99253acfd1989099e9849af1976a8ccc9aa1fbb7b5c26ffe90cea5c9620017b6 +size 64613 diff --git a/Finished HUDS from J&J/generate_comparison_maps.py b/Finished HUDS from J&J/generate_comparison_maps.py new file mode 100644 index 00000000..1063fd13 --- /dev/null +++ b/Finished HUDS from J&J/generate_comparison_maps.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python3 + +import re +from dataclasses import dataclass +from pathlib import Path + +from PIL import Image, ImageDraw, ImageFont + + +ROOT = Path(__file__).resolve().parent +REPO = ROOT.parent +COORD = REPO / "Gameleap/code/CoreTech/Libraries/GameOS/coord.cpp" +ZONES = ("LL", "RL", "LA", "RA", "RT", "LT", "CT", "CTR", "HD", "S1", "S2") +COLORS = {"current": "#ff3030", "provided": "#20e060"} + + +@dataclass(frozen=True) +class Display: + folder: str + mech_id: int + kind: str + output_dir: str + slug: str + unexploded_text: str + exploded_text: str + unexploded_image: str | None + exploded_image: str + source_image: str | None = None + runtime_stem: str | None = None + + +DISPLAYS = ( + Display("Annihilator", 0, "mfd", "MFD", "annihilator", "MFD/Annihilator Unexploded.txt", "MFD/Annihilator Exploded.txt", "MFD/annihilator_unexploded.bmp", "MFD/annihilator_Exploded.bmp"), + Display("Annihilator", 0, "radar", "Radar", "annihilator", "Radar/Annihilator Unexploded.txt", "Radar/Annihilator Exploded.txt", "Radar/annihilator_unexploded.bmp", "Radar/annihilator_exploded.bmp"), + Display("Argus", 4, "mfd", "MFD", "argus", "MFD/Argus Cords.txt", "MFD/Argus Cords.txt", "MFD/argus_unexpanded.bmp", "MFD/argus_explode.bmp"), + Display("AssassinII", 5, "mfd", "HUD", "assian2", "HUD/assassinII_HUD_unexploded.txt", "HUD/assassinII_hud_exploded.txt", None, "HUD/assian2_hud_exploded.bmp", "assian2_color.png", "assassin2"), + Display("AssassinII", 5, "radar", "Radar", "assian2", "Radar/assassinII_radar_unexploded.txt", "Radar/assassinII_radar_exploded.txt", "Radar/assian2_radar_unexploded.bmp", "Radar/assian2_radar_exploded.bmp", None, "assassin2"), + Display("Avatar", 7, "mfd", "MFD", "avatar", "MFD/Avatar Coords.txt", "MFD/Avatar Coords.txt", "MFD/avatar_unexploded.bmp", "MFD/avatar_exploded.bmp"), + Display("Avatar", 7, "radar", "Radar", "avatar", "Radar/Avatar Coords.txt", "Radar/Avatar Coords.txt", "Radar/avatar_unexploded.bmp", "Radar/avatar_exploded.bmp"), + Display("Behemoth", 11, "mfd", "HUD", "behemoth", "HUD/Behemoth_HUD_unexploded.txt", "HUD/Behemoth_HUD_exploded.txt", "HUD/Behemoth_HUD_unexploded.bmp", "HUD/Behemoth_HUD_exploded.bmp"), + Display("Behemoth", 11, "radar", "Radar", "behemoth", "Radar/Behemoth_unexploded.txt", "Radar/Behemoth_exploded.txt", "Radar/Behemoth_unexploded_radar.bmp", "Radar/Behemoth_radar_exploded.bmp"), + Display("BlackHawk", 13, "mfd", "MFD", "blackhawk", "MFD/Black Hawk.txt", "MFD/Black Hawk.txt", "MFD/blackhawk_unexploded.bmp", "MFD/blackhawk_exploded.bmp"), + Display("BlackHawk", 13, "radar", "Radar", "blackhawk", "Radar/Black Hawk.txt", "Radar/Black Hawk.txt", "Radar/blackhawk_unexploded.bmp", "Radar/blackhawk_exploded.bmp"), + Display("Fafnir", 27, "mfd", "HUD", "fafnir", "HUD/fafnir_unexploded.txt", "HUD/fafnir_exploded.txt", "HUD/fafnir_unexploded.bmp", "HUD/fafnir_exploded.bmp"), + Display("Flea", 28, "mfd", "MFD", "flea", "MFD/Flea unexploded.txt", "MFD/Flea exploded.txt", "MFD/flea_unexploded copy.bmp", "MFD/flea_exploded copy.bmp"), + Display("Gladiator", 29, "mfd", "MFD", "gladiator", "MFD/Gladiator unexploded.txt", "MFD/Gladiator Exploded.txt", "MFD/gladiator_unexploded copy.bmp", "MFD/gladiator_exploded copy.bmp"), + Display("hellspawn", 33, "radar", "radar", "hellspawn", "radar/hellspawn_radar_unexploded.txt", "radar/hellspawn_radar_exploded.txt", "radar/hellspawn_radar_unexploded.bmp", "radar/hellspawn_radar_exploded.bmp"), + Display("Kodiak", 37, "mfd", "MFD", "kodiak", "MFD/Kodiak Cords.txt", "MFD/Kodiak Cords.txt", "MFD/kodiak_unexpanded.bmp", "MFD/kodiak_Explode.bmp"), + Display("Longbow", 39, "mfd", "MFD", "longbow", "MFD/Lomgbow unexploded.txt", "MFD/Longbow exploded.txt", "MFD/longbow_unexploded copy.bmp", "MFD/longbow_exploded copy.bmp"), + Display("Warhammer", 62, "mfd", "MFD", "warhammer", "MFD/Warhammer unexploded.txt", "MFD/Warhammer exploded.txt", "MFD/warhammer_unexploded copy.bmp", "MFD/warhammer_exploded.bmp"), + Display("Warhammer", 62, "radar", "Radar", "warhammer", "Radar/Warhammer unexploded.txt", "Radar/Warhammer exploded.txt", "Radar/warhammer_unexploded copy.bmp", "Radar/warhammer_exploded.bmp"), +) + + +def parse_coord_arrays() -> dict[str, list[list[tuple[int, ...]]]]: + text = COORD.read_bytes().decode("ascii") + arrays = {} + for name in ("texuv2", "offset2", "texuv3", "offset3"): + match = re.search(rf"\b{name}\[.*?\]=\{{\r?\n(.*?)\r?\n\}};", text, re.S) + if not match: + raise RuntimeError(f"Could not find {name} in {COORD}") + rows = [] + for line in match.group(1).splitlines(): + if not line.lstrip().startswith("{{"): + continue + values = [ + tuple(map(int, group.split(","))) + for group in re.findall(r"\{\s*([0-9 ]+(?:,\s*[0-9 ]+){1,3})\s*\}", line) + ] + if len(values) != len(ZONES): + raise RuntimeError(f"Expected 11 zones in {name} row: {line}") + rows.append(values) + if len(rows) != 65: + raise RuntimeError(f"Expected 65 active rows in {name}, found {len(rows)}") + arrays[name] = rows + return arrays + + +def parse_measurements(path: Path, wanted_section: str, warnings: list[str]) -> dict[str, tuple[int, ...]]: + rows = {} + section = None + for line_number, raw in enumerate(path.read_text(errors="replace").splitlines(), 1): + stripped = raw.strip() + lower = stripped.lower() + zone_match = re.match(r"^(LL|RL|LA|RA|RT|LT|CT|CTR|HD|S1|S2)\b(.*)$", stripped, re.I) + if not zone_match: + if "unexploded" in lower or "unexpanded" in lower: + section = "unexploded" + elif "exploded" in lower or "explode" in lower: + section = "exploded" + continue + if section and section != wanted_section: + continue + zone = zone_match.group(1).upper() + remainder = zone_match.group(2) + numbers = tuple(map(int, re.findall(r"\d+", remainder))) + if "." in remainder: + warnings.append(f"{path.relative_to(ROOT)}:{line_number}: treated '.' as a coordinate separator") + if not numbers: + warnings.append(f"{path.relative_to(ROOT)}:{line_number}: blank {zone} value treated as zero") + rows[zone] = numbers + return rows + + +def normalize_measurements(display: Display, warnings: list[str]) -> tuple[list[tuple[int, ...]], list[tuple[int, ...]]]: + base = ROOT / display.folder + unexploded_path = base / display.unexploded_text + exploded_path = base / display.exploded_text + unexploded = parse_measurements(unexploded_path, "unexploded", warnings) + exploded = parse_measurements(exploded_path, "exploded", warnings) + + unexploded_lengths = {len(value) for value in unexploded.values() if value and any(value)} + exploded_lengths = {len(value) for value in exploded.values() if value and any(value)} + if unexploded_lengths == {4} and exploded_lengths == {2}: + mode = "modern" + elif unexploded_lengths == {2} and exploded_lengths == {4}: + mode = "legacy" + else: + raise RuntimeError( + f"Cannot determine format for {display.folder} {display.kind}: " + f"unexploded lengths={unexploded_lengths}, exploded lengths={exploded_lengths}" + ) + + rectangles = [] + offsets = [] + for zone in ZONES: + un = unexploded.get(zone, ()) + ex = exploded.get(zone, ()) + if not un: + un = (0, 0, 0, 0) if mode == "modern" else (0, 0) + if not ex: + ex = (0, 0) if mode == "modern" else (0, 0, 0, 0) + expected_un = 4 if mode == "modern" else 2 + expected_ex = 2 if mode == "modern" else 4 + if un and not any(un): + un = (0,) * expected_un + if ex and not any(ex): + ex = (0,) * expected_ex + if len(un) != expected_un or len(ex) != expected_ex: + raise RuntimeError(f"Invalid {zone} values for {display.folder} {display.kind}: {un}, {ex}") + if mode == "modern": + rectangle = un + offset = ex + else: + width = ex[2] - ex[0] + height = ex[3] - ex[1] + rectangle = (un[0], un[1], un[0] + width, un[1] + height) if any(ex) else (0, 0, 0, 0) + offset = ex[:2] + rectangles.append(rectangle) + offsets.append(offset) + return rectangles, offsets + + +def load_unexploded(display: Display) -> Image.Image: + base = ROOT / display.folder + if display.source_image: + source = Image.open(base / display.source_image).convert("RGB") + scaled = source.resize((320, 320), Image.Resampling.LANCZOS) + prepared = Image.new("RGB", (340, 340), "black") + prepared.paste(scaled, (10, 10)) + else: + prepared = Image.open(base / display.unexploded_image).convert("RGB") + if prepared.size == (512, 512): + return prepared + if prepared.width > 512 or prepared.height > 512: + raise RuntimeError(f"Unexpected unexploded size {prepared.size} for {display.folder} {display.kind}") + canvas = Image.new("RGB", (512, 512), "black") + canvas.paste(prepared, (0, 0)) + return canvas + + +def component_boxes(rectangles: list[tuple[int, ...]], offsets: list[tuple[int, ...]]) -> list[tuple[int, ...]]: + boxes = [] + for rectangle, offset in zip(rectangles, offsets): + if not any(rectangle) or not any(offset): + boxes.append((0, 0, 0, 0)) + continue + width = rectangle[2] - rectangle[0] + height = rectangle[3] - rectangle[1] + boxes.append((offset[0], offset[1], offset[0] + width, offset[1] + height)) + return boxes + + +def draw_legend(draw: ImageDraw.ImageDraw, font: ImageFont.ImageFont) -> None: + draw.rectangle((365, 12, 505, 67), fill="black", outline="white", width=1) + draw.line((377, 30, 402, 30), fill=COLORS["current"], width=3) + draw.text((410, 22), "current", fill=COLORS["current"], font=font) + draw.line((377, 51, 402, 51), fill=COLORS["provided"], width=3) + draw.text((410, 43), "provided", fill=COLORS["provided"], font=font) + + +def draw_comparison( + image: Image.Image, + current: list[tuple[int, ...]], + provided: list[tuple[int, ...]], + output: Path, + mark_origins: bool, +) -> None: + draw = ImageDraw.Draw(image) + font = ImageFont.load_default(size=14) + for label, boxes in (("current", current), ("provided", provided)): + color = COLORS[label] + for zone, box in zip(ZONES, boxes): + if not any(box): + continue + draw.rectangle(box, outline=color, width=3) + if mark_origins: + x, y = box[:2] + draw.line((x - 4, y, x + 5, y), fill=color, width=2) + draw.line((x, y - 4, x, y + 5), fill=color, width=2) + draw.text((box[0] + 3, box[1] + 2), zone, fill=color, font=font, stroke_width=2, stroke_fill="black") + draw_legend(draw, font) + output.parent.mkdir(parents=True, exist_ok=True) + image.save(output) + + +def validate_provided( + display: Display, + rectangles: list[tuple[int, ...]], + offsets: list[tuple[int, ...]], + warnings: list[str], +) -> None: + source_limit = 340 if display.kind == "mfd" else 512 + for zone, rectangle, offset in zip(ZONES, rectangles, offsets): + if any(rectangle): + if rectangle[2] <= rectangle[0] or rectangle[3] <= rectangle[1]: + warnings.append(f"{display.folder} {display.kind} {zone}: non-positive source rectangle {rectangle}") + if min(rectangle) < 0 or max(rectangle) > source_limit: + warnings.append(f"{display.folder} {display.kind} {zone}: source rectangle outside 0..{source_limit}: {rectangle}") + if any(offset) and (offset[0] < 0 or offset[1] < 0 or offset[0] > 512 or offset[1] > 512): + warnings.append(f"{display.folder} {display.kind} {zone}: offset outside 512 canvas: {offset}") + + +def difference_count(left: list[tuple[int, ...]], right: list[tuple[int, ...]]) -> int: + return sum(a != b for a, b in zip(left, right)) + + +def main() -> None: + arrays = parse_coord_arrays() + results = [] + all_warnings = [] + generated = [] + + for display in DISPLAYS: + warnings = [] + provided_rectangles, provided_offsets = normalize_measurements(display, warnings) + validate_provided(display, provided_rectangles, provided_offsets, warnings) + current_rectangles = arrays["texuv2" if display.kind == "mfd" else "texuv3"][display.mech_id] + current_offsets = arrays["offset2" if display.kind == "mfd" else "offset3"][display.mech_id] + + output_dir = ROOT / display.folder / display.output_dir + unexploded_output = output_dir / f"{display.slug}_{display.kind}_unexploded_coords_comparison.png" + exploded_output = output_dir / f"{display.slug}_{display.kind}_exploded_coords_comparison.png" + draw_comparison( + load_unexploded(display), + current_rectangles, + provided_rectangles, + unexploded_output, + mark_origins=False, + ) + exploded_image = Image.open(ROOT / display.folder / display.exploded_image).convert("RGB") + draw_comparison( + exploded_image, + component_boxes(current_rectangles, current_offsets), + component_boxes(provided_rectangles, provided_offsets), + exploded_output, + mark_origins=True, + ) + + rectangle_differences = difference_count(current_rectangles, provided_rectangles) + offset_differences = difference_count(current_offsets, provided_offsets) + status = "EXACT" if rectangle_differences == 0 and offset_differences == 0 else "DIFFERENT" + results.append((display, status, rectangle_differences, offset_differences, warnings)) + generated.extend((unexploded_output, exploded_output)) + all_warnings.extend(warnings) + + configured = {(display.folder.lower(), display.kind) for display in DISPLAYS} + missing = [] + for folder in sorted(path.name for path in ROOT.iterdir() if path.is_dir()): + for kind in ("mfd", "radar"): + if (folder.lower(), kind) not in configured: + missing.append((folder, kind)) + + lines = [ + "# J&J Coordinate Comparison Summary", + "", + "Generated by `generate_comparison_maps.py`. Red is the current `coord.cpp` mapping; green is the provided J&J mapping.", + "", + "`EXACT` means all eleven source rectangles and all eleven exploded offsets match numerically. `DIFFERENT` means at least one value differs; inspect both generated images.", + "", + "| Mech | Display | Status | Source rectangles different | Exploded offsets different |", + "|---|---:|---:|---:|---:|", + ] + for display, status, rectangle_differences, offset_differences, _ in results: + lines.append(f"| {display.folder} | {display.kind.upper()} | **{status}** | {rectangle_differences}/11 | {offset_differences}/11 |") + + lines.extend(("", "## Missing comparison inputs", "")) + for folder, kind in missing: + lines.append(f"- `{folder}` {kind.upper()}: no complete provided mapping/image set configured") + + lines.extend(("", "## Input warnings", "")) + if all_warnings: + for warning in sorted(set(all_warnings)): + lines.append(f"- {warning}") + else: + lines.append("- None") + + lines.extend(("", "## Generated files", "")) + for output in generated: + lines.append(f"- `{output.relative_to(ROOT)}`") + lines.append("") + (ROOT / "COMPARISON-SUMMARY.md").write_text("\n".join(lines)) + + exact = sum(status == "EXACT" for _, status, _, _, _ in results) + print(f"Generated {len(generated)} maps for {len(results)} display sets: {exact} exact, {len(results) - exact} different") + print(f"Warnings: {len(set(all_warnings))}; missing display sets: {len(missing)}") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_exploded_coords_comparison.png b/Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_exploded_coords_comparison.png new file mode 100644 index 00000000..85e25081 --- /dev/null +++ b/Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_exploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aae6f92f8403b575a1ca1536ffbd668720c2951c421ff21ab49de4ae6d6ff649 +size 60191 diff --git a/Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_unexploded_coords_comparison.png b/Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_unexploded_coords_comparison.png new file mode 100644 index 00000000..ad784299 --- /dev/null +++ b/Finished HUDS from J&J/hellspawn/radar/hellspawn_radar_unexploded_coords_comparison.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05763f1dd30dc5ed4fc4bb01d661529a32e074ea5d14511c451865ee5b5f4d7b +size 57506 diff --git a/Gameleap/code/CoreTech/Libraries/GameOS/coord.cpp b/Gameleap/code/CoreTech/Libraries/GameOS/coord.cpp index 112c8eb0..2fa17dfd 100644 --- a/Gameleap/code/CoreTech/Libraries/GameOS/coord.cpp +++ b/Gameleap/code/CoreTech/Libraries/GameOS/coord.cpp @@ -2,20 +2,20 @@ // MSL ADD MECH // MFD float texuv2[65][11][4]={ - {{186,156,237,336},{ 96,156,147,336},{237, 24,294,168},{ 57, 24, 93,162},{ 99, 39,150,129},{186, 39,234,129},{312, 48,375,207},{ 0, 0, 0, 0},{159, 24,177, 39},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Annihilator + {{ 78,152,156,328},{182,152,262,328},{ 56, 72,128,164},{210, 72,284,164},{180, 64,208,200},{132, 64,160,200},{146, 10,192,198},{ 0, 0, 0, 0},{162, 32,176, 38},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Annihilator {{195,171,258,351},{ 69,171,132,351},{264,168,309,240},{ 15,168, 60,240},{ 54, 39,141,162},{183, 39,270,162},{141, 51,183,207},{ 0, 0, 0, 0},{153, 15,171, 39},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Archer {{250,150,328,330},{ 10,150, 90,330},{254, 86,332,136},{ 4, 86, 84,136},{102,252,158,310},{168,252,226,312},{128, 34,210,198},{ 0, 0, 0, 0},{154, 10,174, 24},{228, 8,308, 64},{ 28, 8,108, 64}}, // M_Arctic Wolf {{254,142,324,334},{ 16,142, 86,334},{248, 56,326,108},{ 12, 56, 92,108},{ 94, 70,156,152},{182, 70,246,152},{132,166,208,292},{ 0, 0, 0, 0},{ 40, 24, 58, 30},{140,302,198,332},{122, 2,218, 60}}, // M_Ares - {{202,130,326,338},{ 6,130,130,338},{242, 14,334,120},{ 6, 18, 94,100},{100, 26,125,118},{198, 18,232,116},{134, 2,190,188},{ 0, 0, 0, 0},{150,220,174,226},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Argus - {{270,136,330,332},{ 10,136, 68,332},{240, 28,302,114},{ 38, 28, 92,114},{114, 12,218,116},{178,218,218,282},{148,128,192,182},{ 0, 0, 0, 0},{190,294,200,302},{140,230,164,278},{ 0, 0, 0, 0}}, // M_Assassin2 + {{ 42,138,158,326},{176,138,292,336},{ 54, 30,124,106},{224, 24,306,124},{194, 38,222,100},{124, 38,142,100},{128, 14,210,186},{ 0, 0, 0, 0},{156, 48,178, 56},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Argus + {{ 98,142,148,328},{190,142,240,328},{ 56, 48,124,154},{216, 48,282,154},{180, 22,220,120},{120, 22,158,120},{144, 36,194,186},{ 0, 0, 0, 0},{158, 70,180, 86},{148, 10,190, 48},{ 0, 0, 0, 0}}, // M_Assassin2 {{174,153,225,345},{111,153,162,345},{219, 33,276,153},{ 60, 33,117,153},{126, 45,150,144},{186, 45,210,144},{ 6, 24, 54,198},{ 0, 0, 0, 0},{144, 9,162, 18},{291,111,309,129},{252,195,273,252}}, // M_Atlas - {{180,135,285,342},{ 60,135,165,342},{234, 84,291,132},{ 54, 84,111,132},{114, 27,150,126},{195, 27,231,126},{156, 21,189,135},{ 0, 0, 0, 0},{165, 3,180, 18},{297,129,378,168},{ 0, 0, 0, 0}}, // M_Avatar + {{ 60,108,104,250},{138,108,180,250},{ 40, 40, 74, 84},{168, 40,218, 88},{140, 28,168,104},{ 76, 28,102,104},{ 98, 6,146,138},{ 0, 0, 0, 0},{116, 16,124, 24},{112, 78,128, 94},{ 0, 0, 0, 0}}, // M_Avatar {{186,156,237,336},{ 96,156,147,336},{237, 24,294,168},{ 57, 24, 93,162},{ 99, 39,150,129},{186, 39,234,129},{312, 48,375,207},{ 0, 0, 0, 0},{159, 24,177, 39},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Awesome {{174,153,225,345},{111,153,162,345},{219, 33,276,153},{ 60, 33,117,153},{126, 45,150,144},{186, 45,210,144},{ 6, 24, 54,198},{ 0, 0, 0, 0},{144, 9,162, 18},{291,111,309,129},{252,195,273,252}}, // M_Battlemaster {{174,153,225,345},{111,153,162,345},{219, 33,276,153},{ 60, 33,117,153},{126, 45,150,144},{186, 45,210,144},{ 6, 24, 54,198},{ 0, 0, 0, 0},{144, 9,162, 18},{291,111,309,129},{ 0, 0, 0, 0}}, // M_BattlemasterIIc - {{186,177,243,375},{102,177,159,375},{249, 27,324,162},{ 18, 18,102,162},{111, 51,147,141},{201, 51,237,141},{153, 18,192,174},{ 0, 0, 0, 0},{210, 30,231, 39},{ 21,213, 75,330},{ 0, 0, 0, 0}}, // M_Behemoth + {{ 76,170,152,302},{184,170,262,302},{ 12,106,126,174},{212,106,326,174},{176, 86,226,174},{110, 82,160,174},{140, 96,198,224},{ 0, 0, 0, 0},{164,122,174,134},{142, 38,194, 98},{ 0, 0, 0, 0}}, // M_Behemoth {{186,177,243,375},{102,177,159,375},{249, 27,324,162},{ 18, 18,102,162},{111, 51,147,141},{201, 51,237,141},{153, 18,192,174},{ 0, 0, 0, 0},{210, 30,231, 39},{ 21,213, 75,330},{ 0, 0, 0, 0}}, // M_Behemothii - {{177,189,267,378},{ 69,189,159,378},{240, 78,288,171},{ 48, 78, 96,171},{102, 39,165,141},{171, 39,234,141},{309, 60,375,177},{ 0, 0, 0, 0},{156, 24,180, 33},{243, 18,300, 72},{ 36, 18, 93, 72}}, // M_Blackhawk + {{ 32, 82,140,294},{188, 82,294,294},{ 6, 12, 88,134},{236, 12,318,134},{176, 18,234,132},{ 92, 18,244, 36},{152, 6,172,132},{ 0, 0, 0, 0},{154, 38,168, 42},{110,112,142,138},{184,112,216,138}}, // M_Blackhawk {{186,177,243,375},{102,177,159,375},{249, 27,324,162},{ 18, 18,102,162},{111, 51,147,141},{201, 51,237,141},{153, 18,192,174},{ 0, 0, 0, 0},{210, 30,231, 39},{ 21,213, 75,330},{ 0, 0, 0, 0}}, // M_Blackknight {{256,122,336,334},{ 8,122, 88,334},{234, 24,282,100},{ 62, 14,108, 90},{108,162,152,220},{194,162,238,220},{118, 2,226,152},{ 0, 0, 0, 0},{164,208,180,222},{194,238,218,290},{126,238,152,290}}, // M_Blacklanner {{262,160,324,336},{ 18,160, 80,336},{284, 74,328,148},{ 14, 74, 58,148},{ 62, 2,150,156},{150,204,238,326},{172, 10,248,190},{ 0, 0, 0, 0},{282, 36,300, 52},{102,200,130,236},{100,288,128,326}}, // M_Brigand @@ -30,9 +30,9 @@ float texuv2[65][11][4]={ // {{250,174,300,336},{ 40,174, 90,336},{280, 2,322,110},{ 16, 2, 58,110},{ 62, 60,104,136},{234, 60,276,136},{110, 62,230,198},{ 0, 0, 0, 0},{156, 24,182, 34},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Dasher {{191,142,265,337},{ 76,142,150,337},{266, 58,328,142},{ 12, 58, 75,141},{ 93, 56,150,129},{190, 56,246,129},{152, 60,188,198},{ 0, 0, 0, 0},{166, 42,177, 49},{184, 2,245, 55},{ 96, 2,157, 55}}, // M_Deimos {{237,147,300,345},{ 84,147,147,345},{324, 78,372,147},{ 12, 72, 66,135},{ 81, 33,147,111},{237, 33,300,111},{162, 42,222,186},{ 0, 0, 0, 0},{177, 15,207, 30},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Dragon - {{250,140,332,336},{ 90,140,170,336},{260, 10,306,128},{110, 10,156,128},{ 2, 2, 88,140},{ 2,180, 86,318},{180,130,234,334},{ 0, 0, 0, 0},{200, 50,216, 60},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Fafnir - Skippy - {{210,110,296,336},{ 10,110, 96,336},{220, 20,226, 40},{100, 20,106, 42},{ 20, 20, 74, 94},{260, 20,314, 94},{140, 20,194,178},{ 0, 0, 0, 0},{130,200,160,216},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Flea - Skippy - {{270,160,328,330},{ 10,160, 68,330},{280, 10,328,108},{ 10, 10,108, 50},{ 70, 10,106,120},{230, 10,262,120},{130, 10,210,216},{ 0, 0, 0, 0},{160,260,184,268},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Gladiator + {{ 86,142,162,326},{178,142,254,326},{ 24, 22, 68,134},{272, 22,316,134},{188, 14,270,136},{ 68, 14,150,136},{124, 16,214,202},{ 0, 0, 0, 0},{162, 90,178,100},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Fafnir - Skippy + {{ 52,102,136,314},{182,102,270,314},{ 96, 60,102, 78},{216, 62,224, 80},{174, 14,224, 84},{ 92, 14,146, 82},{134, 22,186,154},{ 0, 0, 0, 0},{144, 44,174, 60},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Flea - Skippy + {{ 88,156,142,318},{170,156,226,318},{ 68, 52,108,144},{206, 52,250,144},{170, 32,212,138},{102, 32,144,138},{120, 4,196,196},{ 0, 0, 0, 0},{148, 58,168, 66},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Gladiator {{210,164,286,334},{ 56,164,132,334},{278, 18,314,152},{ 24, 18, 66,144},{ 82, 32,124,132},{218, 28,262,136},{142, 16,200,190},{ 0, 0, 0, 0},{158,214,184,228},{160,254,190,280},{ 0, 0, 0, 0}}, // M_Grizzly {{237,174,312,348},{ 60,174,135,348},{294, 57,342,165},{ 24, 57, 72,165},{ 81, 75,123,165},{240, 69,285,165},{153, 48,222,222},{ 0, 0, 0, 0},{174, 27,201, 33},{102, 24,141, 60},{ 0, 0, 0, 0}}, // M_Hauptmann {{165,144,252,318},{ 69,144,156,318},{291, 90,342,141},{ 24, 90, 75,141},{ 93, 39,141,138},{231, 42,279,141},{282,174,327,291},{ 0, 0, 0, 0},{150, 18,171, 27},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Hellhound @@ -40,9 +40,9 @@ float texuv2[65][11][4]={ {{255,180,315,372},{ 72,183,132,375},{312, 69,369,144},{ 9, 63, 69,147},{ 75, 27,156,138},{225, 24,300,135},{165, 15,216,198},{ 0, 0, 0, 0},{237, 9,270, 18},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Highlander {{270,136,330,332},{ 10,136, 68,332},{240, 28,302,114},{ 38, 28, 92,114},{114, 12,218,116},{178,218,218,282},{148,128,192,182},{ 0, 0, 0, 0},{190,294,200,302},{140,230,164,278},{154,192,186,208}}, // M_HollanderII {{210,165,276,336},{ 69,165,135,336},{327, 48,372,141},{ 6, 48, 51,141},{ 18,165, 54,228},{276, 15,312,147},{135, 27,204,198},{ 0, 0, 0, 0},{165, 9,183, 15},{ 66, 27,114, 90},{ 0, 0, 0, 0}}, // M_Hunchback - {{230,160,310,336},{ 22,160,102,336},{266, 62,336,156},{ 4, 62, 74,156},{ 86, 16,152, 88},{188, 16,254,138},{116,174,220,316},{ 0, 0, 0, 0},{276, 0,340, 60},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Kodiak - GhostHawk + {{ 80,152,154,314},{166,152,238,314},{ 36, 50,102,136},{218, 50,286,134},{180, 24,238,138},{ 82, 24,142,138},{114, 6,208,190},{ 0, 0, 0, 0},{146,118,168,124},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Kodiak - GhostHawk {{192,156,243,342},{ 96,156,150,342},{231, 69,285,156},{ 60, 69,108,156},{114, 54,149,146},{195, 39,225,141},{150, 48,192,192},{ 0, 0, 0, 0},{162, 30,177, 42},{108, 21,146, 50},{ 0, 0, 0, 0}}, // M_Loki - {{270,138,332,332},{ 10,138, 72,332},{186,138,260,216},{ 82,138,158,216},{ 32, 12,100,104},{236, 12,304,104},{142, 18,198,122},{ 0, 0, 0, 0},{162,316,176,326},{134,238,206,292},{ 0, 0, 0, 0}}, // M_Longbow - GhostHawk + {{ 88,120,146,300},{172,120,230,300},{ 4, 38, 70,110},{248, 38,314,108},{186, 30,248,114},{ 72, 30,136,116},{134, 20,184,114},{ 0, 0, 0, 0},{152, 62,168, 68},{132,116,188,166},{ 0, 0, 0, 0}}, // M_Longbow - GhostHawk {{177,189,267,378},{ 69,189,159,378},{240, 78,288,171},{ 48, 78, 96,171},{102, 39,165,141},{171, 39,234,141},{309, 60,375,177},{ 0, 0, 0, 0},{156, 24,180, 33},{243, 18,300, 72},{ 36, 18, 93, 72}}, // M_Madcat {{201,159,294,333},{ 48,159,141,333},{225,102,285,153},{ 57,102,117,153},{120, 45,168,150},{174, 45,222,150},{141,198,201,327},{ 0, 0, 0, 0},{159, 27,183, 39},{ 57, 12,108, 75},{234, 12,285, 75}}, // M_Madcat_MKII {{225,153,360,342},{ 24,153,159,342},{297, 30,378,129},{ 6, 30, 87,129},{123, 45,165,147},{219, 45,261,147},{168, 45,216,198},{ 0, 0, 0, 0},{174, 18,210, 30},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Masakari @@ -65,7 +65,7 @@ float texuv2[65][11][4]={ {{207,156,288,342},{ 51,156,132,342},{264, 30,327,123},{ 18, 30, 75,147},{ 90, 27,138,147},{207, 27,249,147},{138, 33,207,141},{ 0, 0, 0, 0},{159, 6,183, 18},{138,144,201,216},{ 0, 0, 0, 0}}, // M_Uziel {{218,138,280,334},{ 20,138, 82,334},{270, 8,328,134},{ 10, 8, 70,114},{ 88, 66,130,156},{172, 66,210,156},{124,166,176,304},{ 0, 0, 0, 0},{130, 4,210, 52},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Victor - GhostHawk {{180,135,285,342},{ 60,135,165,342},{234, 84,291,132},{ 54, 84,111,132},{114, 27,150,126},{195, 27,231,126},{156, 21,189,135},{ 0, 0, 0, 0},{165, 3,180, 18},{297,129,378,168},{ 0, 0, 0, 0}}, // M_Vulture - {{177,189,267,378},{ 69,189,159,378},{240, 78,288,171},{ 48, 78, 96,171},{102, 39,165,141},{171, 39,234,141},{309, 60,375,177},{ 0, 0, 0, 0},{156, 24,180, 33},{243, 18,300, 72},{ 36, 18, 93, 72}}, // M_Warhammer + {{ 78,134,116,256},{142,134,180,256},{ 52, 46, 90,126},{168, 44,208,126},{146, 42,166,112},{ 90, 42,110,112},{110, 28,184,156},{ 0, 0, 0, 0},{118, 56,138, 64},{ 56, 4, 90, 48},{172, 24,202, 48}}, // M_Warhammer {{198,165,237,348},{102,165,141,348},{270, 42,309,150},{ 24, 45, 75,159},{ 93, 63,123,141},{216, 63,246,141},{138, 24,198,213},{ 0, 0, 0, 0},{216, 42,240, 48},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Wolfhound {{250,152,312,328},{ 26,152, 88,328},{186,234,228,294},{112,234,150,282},{ 20, 12, 96,116},{244, 12,318,116},{128, 12,210,190},{ 0, 0, 0, 0},{158,206,182,218},{ 0, 0, 0, 0},{ 0, 0, 0, 0}} // M_Zeus }; @@ -73,20 +73,20 @@ float texuv2[65][11][4]={ // MSL ADD MECH // MFD int offset2[65][11][2]={ - {{186,151},{ 96,151},{234, 19},{ 60, 19},{ 99, 34},{186, 34},{138, 43},{ 0, 0},{159, 55},{ 0, 0},{ 0, 0}}, // M_Annihilator + {{ 0,148},{260,148},{ 6, 40},{260, 40},{212, 80},{100, 80},{146, 12},{ 0, 0},{162,236},{ 0, 0},{ 0, 0}}, // M_Annihilator {{186,153},{ 99,153},{252,102},{ 51,102},{ 66, 21},{195, 21},{153, 33},{ 0, 0},{165, 51},{ 0, 0},{ 0, 0}}, // M_Archer {{210,156},{ 50,156},{224, 92},{ 34, 92},{ 82, 68},{198, 68},{128, 40},{ 0, 0},{154, 46},{198, 14},{ 58, 14}}, // M_Arctic Wolf {{184,148},{ 86,148},{248, 62},{ 12, 62},{ 94, 56},{182, 56},{132, 62},{ 0, 0},{160, 70},{140,128},{122, 8}}, // M_Ares - {{172,130},{ 26,130},{222, 14},{ 26, 18},{110, 26},{188, 18},{134, 2},{ 0, 0},{150, 40},{ 0, 0},{ 0, 0}}, // M_Argus - {{190,126},{ 90,126},{220, 38},{ 68, 38},{114, 12},{178, 8},{148,118},{ 0, 0},{190, 24},{140, 20},{ 0, 0}}, // M_Assassin2 + {{ 4,138},{216,138},{ 12, 14},{242, 14},{174,200},{140,200},{126, 14},{ 0, 0},{156,294},{ 0, 0},{ 0, 0}}, // M_Argus + {{ 6,148},{282,148},{ 6, 10},{266, 10},{206, 22},{ 98, 22},{144,180},{ 0, 0},{158,140},{148, 10},{ 0, 0}}, // M_Assassin2 {{174,143},{111,143},{216, 23},{ 63, 23},{126, 35},{186, 35},{147, 14},{ 0, 0},{144, 29},{117,101},{207,140}}, // M_Atlas - {{180,135},{ 60,135},{234, 84},{ 54, 84},{114, 27},{195, 27},{156, 21},{ 0, 0},{165, 12},{132,129},{ 0, 0}}, // M_Avatar + {{ 12,174},{198,174},{ 12, 42},{198, 42},{158, 42},{ 60, 42},{ 96, 42},{ 0, 0},{120,202},{116,238},{ 0, 0}}, // M_Avatar {{186,151},{ 96,151},{234, 19},{ 60, 19},{ 99, 34},{186, 34},{138, 43},{ 0, 0},{159, 55},{ 0, 0},{ 0, 0}}, // M_Awesome {{174,143},{111,143},{216, 23},{ 63, 23},{126, 35},{186, 35},{147, 14},{ 0, 0},{144, 29},{117,101},{207,140}}, // M_Battlemaster {{174,143},{111,143},{216, 23},{ 63, 23},{126, 35},{186, 35},{147, 14},{ 0, 0},{144, 29},{117,101},{ 0, 0}}, // M_BattlemasterIIc - {{186,142},{102,142},{234, 22},{ 27, 13},{117, 46},{192, 46},{153, 13},{ 0, 0},{162, 25},{ 24, 13},{ 0, 0}}, // M_Behemoth + {{ 6,172},{246,172},{ 6, 8},{281, 8},{226, 82},{ 72, 82},{138,172},{ 0, 0},{164,122},{142, 8},{ 0, 0}}, // M_Behemoth {{186,142},{102,142},{234, 22},{ 27, 13},{117, 46},{192, 46},{153, 13},{ 0, 0},{162, 25},{ 24, 13},{ 0, 0}}, // M_Behemothii - {{174,147},{ 72,147},{240, 78},{ 48, 78},{102, 39},{171, 39},{135, 60},{ 0, 0},{156, 69},{216, 18},{ 63, 18}}, // M_Black Hawk + {{ 8,128},{228,128},{ 8, 0},{252, 0},{188, 0},{ 0, 96},{160, 0},{ 0, 0},{164,146},{132,168},{176,168}}, // M_Black Hawk {{186,142},{102,142},{234, 22},{ 27, 13},{117, 46},{192, 46},{153, 13},{ 0, 0},{162, 25},{ 24, 13},{ 0, 0}}, // M_Black Knight {{196,128},{ 68,128},{234, 30},{ 62, 20},{108, 18},{194, 18},{118, 8},{ 0, 0},{164, 24},{194, 44},{126, 44}}, // M_Black Lanner {{182,166},{ 98,166},{244, 80},{ 54, 80},{ 82, 8},{170, 40},{142, 16},{ 0, 0},{182, 42},{112,126},{200,124}}, // M_Brigand @@ -101,9 +101,9 @@ int offset2[65][11][2]={ // {{190,180},{100,180},{230, 8},{ 66, 8},{102, 66},{194, 66},{110, 68},{ 0, 0},{156,100},{ 0, 0},{ 0, 0}}, // M_Dasher {{191,144},{ 76,144},{242, 60},{ 35, 60},{ 93, 58},{190, 58},{152, 62},{ 0, 0},{165, 77},{184, 7},{ 96, 7}}, // M_Deimos {{198,134},{ 99,134},{234, 65},{ 63, 59},{ 87, 20},{207, 20},{150, 29},{ 0, 0},{165, 44},{ 0, 0},{ 0, 0}}, // M_Dragon - {{177,141},{ 77,141},{278, 10},{ 10, 10},{ 60, 2},{191, 2},{141, 3},{ 0, 0},{159, 83},{ 0, 0},{ 0, 0}}, // M_Fafnir - Skippy - {{198,112},{ 56,112},{230, 62},{104, 62},{100, 18},{186, 18},{144, 6},{ 0, 0},{154, 48},{ 0, 0},{ 0, 0}}, // M_Flea - Skippy - {{182,166},{ 95,166},{221, 54},{ 72, 54},{107, 31},{194, 31},{128, 2},{ 0, 0},{156, 58},{ 0, 0},{ 0, 0}}, // M_Gladiator - Skippy + {{ 8,142},{256,142},{ 8, 2},{288, 2},{206, 14},{ 50, 14},{126,140},{ 0, 0},{162, 90},{ 0, 0},{ 0, 0}}, // M_Fafnir - Skippy + {{ 8,120},{244,120},{ 24, 62},{306, 66},{218, 14},{ 66, 14},{134, 22},{ 0, 0},{146,210},{ 0, 0},{ 0, 0}}, // M_Flea - Skippy + {{ 20,174},{232,174},{ 4, 52},{278, 52},{218, 32},{ 60, 32},{120, 4},{ 0, 0},{148, 58},{ 0, 0},{ 0, 0}}, // M_Gladiator - Skippy {{180,170},{ 86,170},{238, 44},{ 64, 44},{102, 38},{198, 34},{142, 22},{ 0, 0},{158, 90},{210, 10},{ 0, 0}}, // M_Grizzly {{192,155},{ 69,155},{240, 56},{ 51, 56},{102, 59},{192, 53},{135, 29},{ 0, 0},{156, 53},{102, 20},{ 0, 0}}, // M_Hauptmann {{165,144},{ 69,144},{228, 90},{ 42, 90},{ 93, 42},{180, 42},{138, 66},{ 0, 0},{150,114},{ 0, 0},{ 0, 0}}, // M_Hellhound @@ -111,9 +111,9 @@ int offset2[65][11][2]={ {{183,150},{ 96,150},{237, 75},{ 39, 72},{ 66, 33},{192, 33},{144, 12},{ 0, 0},{153, 27},{ 0, 0},{ 0, 0}}, // M_Highlander {{190,126},{ 90,126},{220, 38},{ 68, 38},{114, 12},{178, 8},{148,118},{ 0, 0},{190, 24},{140, 20},{154, 92}}, // M_HollnaderII {{180,160},{ 93,160},{231, 55},{ 63, 55},{108, 91},{195, 22},{135, 22},{ 0, 0},{165, 34},{105, 22},{ 0, 0}}, // M_Hunchback - {{178,162},{ 84,162},{236, 52},{ 36, 52},{ 86, 22},{188, 22},{118, 62},{ 0, 0},{138, 2},{ 0, 0},{ 0, 0}}, // M_Kodiak - GhostHawk + {{ 2,176},{264,176},{ 10, 60},{264, 62},{198, 22},{ 82, 22},{124,154},{ 0, 0},{160, 18},{ 0, 0},{ 0, 0}}, // M_Kodiak - GhostHawk {{192,151},{ 96,151},{231, 64},{ 60, 64},{114, 49},{195, 34},{150, 43},{ 0, 0},{162, 55},{108, 16},{ 0, 0}}, // M_Loki - {{186,128},{ 94,128},{166, 36},{ 0, 36},{ 76, 32},{198, 30},{142, 18},{ 0, 0},{164, 62},{134,122},{ 0, 0}}, // M_Longbow - GhostHawk + {{ 4,152},{272,152},{ 6, 38},{248, 38},{192,152},{ 72,152},{134, 20},{ 0, 0},{154,146},{132,268},{ 0, 0}}, // M_Longbow - GhostHawk {{174,147},{ 72,147},{240, 78},{ 48, 78},{102, 39},{171, 39},{135, 60},{ 0, 0},{156, 69},{216, 18},{ 63, 18}}, // M_Madcat {{201,162},{ 48,162},{225,105},{ 57,105},{120, 48},{174, 48},{141, 81},{ 0, 0},{159, 93},{ 72, 15},{219, 15}}, // M_Madcat_MKII {{186,143},{ 21,143},{234, 77},{ 27, 77},{102, 35},{198, 35},{147, 35},{ 0, 0},{153, 86},{ 0, 0},{ 0, 0}}, // M_Masakari @@ -136,27 +136,27 @@ int offset2[65][11][2]={ {{207,146},{ 51,146},{243, 59},{ 39, 59},{ 90, 17},{207, 17},{138, 23},{ 0, 0},{159, 95},{138,134},{ 0, 0}}, // M_Uziel {{185,140},{ 98,140},{226, 34},{ 56, 34},{116, 52},{186, 52},{146, 52},{ 0, 0},{130, 4},{ 0, 0},{ 0, 0}}, // M_Victor - GhostHawk {{180,135},{ 60,135},{234, 84},{ 54, 84},{114, 27},{195, 27},{156, 21},{ 0, 0},{165, 12},{132,129},{ 0, 0}}, // M_Vulture - {{174,147},{ 72,147},{240, 78},{ 48, 78},{102, 39},{171, 39},{135, 60},{ 0, 0},{156, 69},{216, 18},{ 63, 18}}, // M_Warhammer + {{ 8,210},{238,210},{ 6, 46},{238, 46},{186, 42},{ 58, 42},{ 92, 28},{ 0, 0},{134,226},{ 76,220},{178,222}}, // M_Warhammer {{198,155},{102,155},{219, 32},{ 69, 35},{123, 53},{186, 53},{138, 14},{ 0, 0},{156, 32},{ 0, 0},{ 0, 0}}, // M_Wolfhound {{180,152},{ 96,152},{226,104},{ 72,104},{ 70, 32},{194, 32},{128, 12},{ 0, 0},{158, 56},{ 0, 0},{ 0, 0}} // M_Zeus }; // LL RL LA RA RT LT CT CTR HD S1 S2 // 5.03 Secondary Damage Display float texuv3[65][11][4]={ - {{332,280,400,502},{ 94,280,164,504},{422, 14,500,214},{ 14, 12, 76,194},{ 96, 40,166,184},{332, 40,406,184},{206, 48,282,252},{ 0, 0, 0, 0},{236,300,254,310},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Annihilator + {{ 34,186,134,416},{164,186,264,416},{ 4, 78,100, 96},{198, 78,296,196},{158, 66,198,240},{100, 68,140,242},{120, 2,176,242},{ 0, 0, 0, 0},{138, 26,160, 36},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Annihilator {{404,268,484,496},{ 22,268,102,496},{426,114,484,208},{ 22,116, 82,208},{ 92, 20,224,192},{292, 22,424,192},{230, 44,286,252},{ 0, 0, 0, 0},{240,308,276,348},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Archer {{356,260,456,490},{ 30,260,132,488},{354,188,454,252},{ 32,188,132,252},{ 62,104,138,180},{358, 94,434,180},{200, 90,308,300},{ 0, 0, 0, 0},{234, 36,262, 56},{360, 8,464, 80},{ 32, 8,136, 80}}, // M_Arctic Wolf {{402,240,486,472},{ 34,240,118,472},{396,108,502,170},{ 6,108,112,170},{130,100,206,200},{312,100,388,200},{220,106,308,260},{ 0, 0, 0, 0},{250,364,278,378},{230,304,298,344},{206, 14,322, 82}}, // M_Ares {{300,200,448,448},{ 20,200,170,448},{380, 20,490,146},{ 20, 20,124,116},{140, 20,166,100},{300, 20,342,110},{180, 20,292,242},{ 0, 0, 0, 0},{250,300,276,306},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Argus - Skippy - {{402,240,474,484},{ 24,240, 98,484},{394, 50,462,156},{ 28, 50,100,156},{186, 18,316,146},{334, 14,386, 98},{218,214,292,288},{ 0, 0, 0, 0},{348,132,366,146},{126, 30,160, 92},{ 0, 0, 0, 0}}, // M_Assassin2 + {{114,170,178,406},{232,170,294,406},{ 60, 48,144,184},{264, 48,348,184},{218, 18,268,140},{142, 18,190,140},{174, 36,234,140},{ 0, 0, 0, 0},{192, 78,218, 98},{178, 2,230, 48},{ 0, 0, 0, 0}}, // M_Assassin2 {{350,260,420,502},{128,246,200,488},{426, 16,500,172},{ 24, 14, 98,172},{162, 26,216,160},{352, 26,406,160},{258, 50,312,268},{ 0, 0, 0, 0},{262, 6,282, 18},{118,118,146,144},{436,218,464,282}}, // M_Atlas - {{356,274,494,504},{ 12,274,152,502},{446, 98,494,164},{ 12, 98, 60,164},{100, 24,174,162},{344, 24,416,162},{218, 4,310,222},{ 0, 0, 0, 0},{252,286,276,296},{220,358,306,396},{ 0, 0, 0, 0}}, // M_Avatar + {{ 98,174,164,400},{222,174,288,400},{ 62, 64,118,136},{266, 64,348,138},{220, 44,268,168},{118, 44,166,168},{152, 10,232,220},{ 0, 0, 0, 0},{184, 24,202, 40},{178,124,208,154},{ 0, 0, 0, 0}}, // M_Avatar {{332,280,400,502},{ 94,280,164,504},{422, 14,500,214},{ 14, 12, 76,194},{ 96, 40,166,184},{332, 40,406,184},{206, 48,282,252},{ 0, 0, 0, 0},{236,300,254,310},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Awesome {{350,260,420,502},{128,246,200,488},{426, 16,500,172},{ 24, 14, 98,172},{162, 26,216,160},{352, 26,406,160},{258, 50,312,268},{ 0, 0, 0, 0},{262, 6,282, 18},{118,118,146,144},{436,218,464,282}}, // M_Battlemaster {{350,260,420,502},{128,246,200,488},{426, 16,500,172},{ 24, 14, 98,172},{162, 26,216,160},{352, 26,406,160},{258, 50,312,268},{ 0, 0, 0, 0},{262, 6,282, 18},{118,118,146,144},{ 0, 0, 0, 0}}, // M_BattlemasterIIc - {{400,258,472,478},{ 42,258,112,478},{372, 58,456,204},{ 72, 96,128,212},{150,100,190,188},{314,100,354,188},{208, 54,296,252},{ 0, 0, 0, 0},{234, 12,270, 24},{234,282,298,452},{ 0, 0, 0, 0}}, // M_Behemoth + {{ 84,206,184,374},{222,206,322,374},{ 2,124,150,210},{260,124,404,210},{214, 94,278,210},{130, 94,194,210},{166,110,242,274},{ 0, 0, 0, 0},{198,144,210,158},{170, 36,236,112},{ 0, 0, 0, 0}}, // M_Behemoth {{400,258,472,478},{ 42,258,112,478},{372, 58,456,204},{ 72, 96,128,212},{150,100,190,188},{314,100,354,188},{208, 54,296,252},{ 0, 0, 0, 0},{234, 12,270, 24},{234,282,298,452},{ 0, 0, 0, 0}}, // M_Behemothii - {{368,252,490,494},{ 16,252,138,494},{416, 96,490,214},{ 6, 96, 82,214},{112, 52,194,182},{314, 52,396,182},{202, 80,304,226},{ 0, 0, 0, 0},{238,276,268,286},{416, 22,498, 90},{ 8, 22, 90, 90}}, // M_Black Hawk + {{ 40,118,178,390},{238,118,376,390},{ 8, 28,114,182},{296, 28,404,180},{220, 38,497,182},{114, 38,192,182},{188, 22,222,184},{ 0, 0, 0, 0},{192, 58,218, 78},{134,156,178,190},{230,156,272,190}}, // M_Black Hawk {{400,258,472,478},{ 42,258,112,478},{372, 58,456,204},{ 72, 96,128,212},{150,100,190,188},{314,100,354,188},{208, 54,296,252},{ 0, 0, 0, 0},{234, 12,270, 24},{234,282,298,452},{ 0, 0, 0, 0}}, // M_Black Knight {{376,226,472,482},{ 24,226,118,482},{412, 48,468,142},{ 36, 36, 92,128},{110, 34,162,104},{332, 32,386,104},{184, 24,312,202},{ 0, 0, 0, 0},{238,250,258,270},{330,126,364,196},{132,126,166,196}}, // M_Black Lanner {{390,264,464,474},{ 48,264,122,474},{444, 90,496,188},{ 24, 92, 78,188},{ 90, 12,196,200},{324, 50,430,200},{218, 22,312,240},{ 0, 0, 0, 0},{248,312,272,334},{166,228,200,278},{320,228,354,278}}, // M_Brigand @@ -177,7 +177,7 @@ float texuv3[65][11][4]={ {{378,276,468,482},{ 44,276,134,482},{398, 86,442,248},{ 68, 86,118,238},{140, 78,196,202},{316, 74,372,204},{222, 60,290,270},{ 0, 0, 0, 0},{232,306,282,340},{332, 26,368, 56},{ 0, 0, 0, 0}}, // M_Grizzly {{378,266,472,496},{ 28,266,122,496},{432, 46,492,190},{ 18, 46, 80,192},{118, 42,174,154},{340, 42,394,154},{196, 14,316,238},{ 0, 0, 0, 0},{234,306,278,328},{172,294,222,342},{ 0, 0, 0, 0}}, // M_Hauptmann {{372,242,494,494},{ 14,242,136,494},{418, 78,482,150},{ 14, 78, 78,150},{108, 6,184,148},{322, 6,398,148},{220, 44,288,208},{ 0, 0, 0, 0},{238,292,268,320},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Hellhound - {{400,260,462,482},{ 20,260, 82,482},{260, 20,324,118},{ 20,120, 88,218},{100,260,332,352},{280,260,348,342},{180,260,252,312},{ 0, 0, 0, 0},{120, 20,162, 28},{ 20, 20, 82, 80},{180, 20,232,108}}, // M_Hellspawn - Skippy + {{116,182,180,408},{232,182,294,408},{ 70, 98,138,202},{272, 98,342,202},{202, 96,274,166},{142, 80,204, 96},{136, 96,240,228},{ 0, 0, 0, 0},{156, 84,190, 92},{160, 2,222, 98},{ 78, 42,142,108}}, // M_Hellspawn - Skippy {{358,262,432,494},{ 62,262,136,494},{412, 74,488,170},{ 10, 74, 82,182},{ 90, 28,188,150},{296, 28,394,150},{206, 4,278,226},{ 0, 0, 0, 0},{228,320,260,330},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Highlander {{402,240,474,484},{ 24,240, 98,484},{394, 50,462,156},{ 28, 50,100,156},{186, 18,316,146},{334, 14,386, 98},{218,214,292,288},{ 0, 0, 0, 0},{348,132,366,146},{126, 30,160, 92},{232,162,278,192}}, // M_HollanderII {{400,262,482,486},{ 16,262, 98,486},{396, 86,450,210},{ 60, 86,116,210},{138, 70,186,218},{322, 46,372,218},{214, 46,294,266},{ 0, 0, 0, 0},{240, 14,268, 34},{230,296,282,354},{ 0, 0, 0, 0}}, // M_Hunchback @@ -206,26 +206,26 @@ float texuv3[65][11][4]={ {{400,292,498,498},{ 10,292,108,498},{378, 20,496, 98},{ 12, 20,130,100},{126,158,192,300},{314,158,380,300},{206,168,302,376},{ 0, 0, 0, 0},{234,108,272,122},{230, 32,276, 78},{ 22,136, 50,166}}, // M_Uziel {{350,256,425,472},{ 76,236,150,472},{410, 46,484,200},{ 30, 46,104,174},{146, 82,198,192},{310, 82,362,192},{220,218,284,384},{ 0, 0, 0, 0},{206, 6,304, 64},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Victor - GhostHawk {{356,274,494,504},{ 12,274,152,502},{446, 98,494,164},{ 12, 98, 60,164},{100, 24,174,162},{344, 24,416,162},{218, 4,310,222},{ 0, 0, 0, 0},{252,286,276,296},{220,358,306,396},{ 0, 0, 0, 0}}, // M_Vulture - {{368,252,490,494},{ 16,252,138,494},{416, 96,490,214},{ 6, 96, 82,214},{112, 52,194,182},{314, 52,396,182},{202, 80,304,226},{ 0, 0, 0, 0},{238,276,268,286},{416, 22,498, 90},{ 8, 22, 90, 90}}, // M_Warhammer + {{126,214,186,408},{228,214,286,408},{ 84, 72,146,202},{268, 72,332,204},{234, 68,270,182},{144, 68,180,178},{148, 46,264,246},{ 0, 0, 0, 0},{190, 90,226,106},{ 92, 8,146, 78},{276, 38,322, 80}}, // M_Warhammer {{326,262,368,486},{142,262,182,486},{380, 72,438,196},{ 72, 72,138,208},{166, 96,200,218},{320, 96,352,216},{214, 48,304,278},{ 0, 0, 0, 0},{240, 10,278, 30},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Wolfhound {{400,262,476,484},{ 34,262,110,484},{284,306,338,378},{182,302,230,362},{ 72, 34,170,166},{340, 34,440,166},{204, 6,306,230},{ 0, 0, 0, 0},{240,250,270,270},{ 0, 0, 0, 0},{ 0, 0, 0, 0}} // M_Zeus }; // LL RL LA RA RT LT CT CTR HD S1 S2 int offset3[65][11][2]={ - {{210,184},{102,182},{274, 4},{ 42, 2},{102, 30},{208, 30},{152, 38},{ 0, 0},{182, 68},{ 0, 0},{ 0, 0}}, // M_Annihilator + {{ 8,270},{398,270},{ 30, 24},{400, 28},{322,120},{146,118},{226, 54},{ 0, 0},{244,338},{ 0, 0},{ 0, 0}}, // M_Annihilator {{224,178},{112,178},{306,114},{ 52,116},{ 62, 0},{222, 2},{180, 24},{ 0, 0},{190, 38},{ 0, 0},{ 0, 0}}, // M_Archer {{256,182},{ 50,182},{274,100},{ 32,100},{ 92, 66},{238, 66},{150, 32},{ 0, 0},{184, 38},{240, 0},{ 62, 0}}, // M_Arctic Wolf {{222,170},{104,170},{296, 68},{ 6, 70},{110, 60},{222, 60},{160, 66},{ 0, 0},{190, 74},{170,144},{146, 4}}, // M_Ares {{208,158},{ 32,158},{268, 18}, {32, 24},{136, 32},{226, 22},{140, 4},{ 0, 0},{182, 48},{ 0, 0},{ 0, 0}}, // M_Argus - Skippy - {{232,150},{104,150},{264, 40},{ 78, 40},{136, 8},{214, 4},{168,134},{ 0, 0},{228, 22},{166, 20},{ 0, 0}}, // M_Assassin2 + {{ 8,220},{336,220},{ 8, 48},{314, 48},{244, 48},{120, 48},{178,206},{ 0, 0},{192, 78},{178, 3},{ 0, 0}}, // M_Assassin2 {{208,162},{130,162},{266, 18},{ 70, 12},{136, 26},{220, 28},{178, 4},{ 0, 0},{182, 28},{136,118},{256,162}}, // M_Atlas - {{236,174},{ 32,174},{296, 98},{ 62, 98},{110, 24},{224, 24},{158, 4},{ 0, 0},{192, 6},{160,138},{ 0, 0}}, // M_Avatar + {{ 50,258},{384,258},{ 24, 38},{408, 38},{324, 38},{104, 38},{198, 38},{ 0, 0},{230,356},{224,302},{ 0, 0}}, // M_Avatar {{210,184},{102,182},{274, 4},{ 42, 2},{102, 30},{208, 30},{152, 38},{ 0, 0},{182, 68},{ 0, 0},{ 0, 0}}, // M_Awesome {{208,162},{130,162},{266, 18},{ 70, 12},{136, 26},{220, 28},{178, 4},{ 0, 0},{182, 28},{136,118},{256,162}}, // M_Battlemaster {{208,162},{130,162},{266, 18},{ 70, 12},{136, 26},{220, 28},{178, 4},{ 0, 0},{182, 28},{136,118},{ 0, 0}}, // M_BattlemasterIIc - {{220,188},{132,188},{282, 38},{ 82, 76},{130, 80},{254, 80},{168, 34},{ 0, 0},{194, 52},{ 44, 2},{ 0, 0}}, // M_Behemoth + {{ 8,236},{348,236},{ 8, 26},{302, 26},{294,130},{108,130},{202,242},{ 0, 0},{230,174},{202, 28},{ 0, 0}}, // M_Behemoth {{220,188},{132,188},{282, 38},{ 82, 76},{130, 80},{254, 80},{168, 34},{ 0, 0},{194, 52},{ 44, 2},{ 0, 0}}, // M_Behemothii - {{208,162},{ 76,162},{286, 76},{ 46, 76},{122, 32},{204, 32},{152, 60},{ 0, 0},{188, 66},{256, 2},{ 68, 2}}, // M_Black Hawk + {{ 8,228},{362,228},{ 8, 28},{392, 30},{ 85, 56},{136, 56},{234, 28},{ 0, 0},{242,250},{170,250},{296,250}}, // M_Black Hawk {{220,188},{132,188},{282, 38},{ 82, 76},{130, 80},{254, 80},{168, 34},{ 0, 0},{194, 52},{ 44, 2},{ 0, 0}}, // M_Black Knight {{236,146},{ 84,146},{282, 28},{ 76, 16},{130, 14},{232, 12},{144, 4},{ 0, 0},{198, 20},{230, 46},{152, 46}}, // M_Black Lanner {{220,194},{118,194},{294, 80},{ 64, 82},{100, 2},{204, 40},{168, 12},{ 0, 0},{218, 42},{136,138},{240,138}}, // M_Brigand @@ -246,7 +246,7 @@ int offset3[65][11][2]={ {{218,196},{104,196},{288, 46},{ 78, 46},{120, 38},{236, 34},{172, 20},{ 0, 0},{182, 86},{252, 6},{ 0, 0}}, // M_Grizzly {{238,176},{ 78,176},{302, 46},{ 48, 46},{108, 42},{250, 42},{146, 14},{ 0, 0},{184, 36},{122, 4},{ 0, 0}}, // M_Hauptmann {{212,152},{ 74,152},{308, 78},{ 34, 78},{ 98, 6},{232, 6},{170, 44},{ 0, 0},{188,102},{ 0, 0},{ 0, 0}}, // M_Hellhound - {{238,184},{122,184},{280,103},{ 76,103},{143, 78},{212, 82},{175,165},{ 0, 0},{158, 85},{ 85, 42},{167, 5}}, // M_Hellspawn - Skippy + {{ 10,226},{282,226},{ 10, 98},{334, 96},{236, 96},{140, 66},{104, 98},{ 0, 0},{152, 50},{106,294},{ 12, 18}}, // M_Hellspawn - Skippy {{218,172},{112,172},{282, 74},{ 50, 74},{ 80, 28},{226, 28},{166, 4},{ 0, 0},{188, 30},{ 0, 0},{ 0, 0}}, // M_Highlander {{232,150},{104,150},{264, 40},{ 78, 40},{136, 8},{214, 4},{168,134},{ 0, 0},{228, 22},{166, 20},{182,102}}, // M_HollanderII {{220,182},{106,182},{286, 46},{ 70, 46},{118, 30},{242, 6},{164, 6},{ 0, 0},{190, 24},{130, 6},{ 0, 0}}, // M_Hunchback @@ -275,7 +275,7 @@ int offset3[65][11][2]={ {{240,172},{ 70,172},{288, 70},{ 2, 70},{106, 28},{234, 28},{156, 38},{ 0, 0},{184,128},{180, 42},{ 12,146}}, // M_Uziel {{220,170},{118,170},{270, 40},{ 68, 40},{140, 62},{220, 62},{176, 62},{ 0, 0},{158, 4},{ 0, 0},{ 0, 0}}, // M_Victor - GhostHawk {{236,174},{ 32,174},{296, 98},{ 62, 98},{110, 24},{224, 24},{158, 4},{ 0, 0},{192, 6},{160,138},{ 0, 0}}, // M_Vulture - {{208,162},{ 76,162},{286, 76},{ 46, 76},{122, 32},{204, 32},{152, 60},{ 0, 0},{188, 66},{256, 2},{ 68, 2}}, // M_Warhammer + {{ 14,310},{290,310},{ 14, 16},{306, 16},{290,172},{ 90,160},{148, 46},{ 0, 0},{188,284},{108,352},{206,366}}, // M_Warhammer {{254,182},{140,182},{258, 32},{110, 32},{164, 56},{238, 56},{172, 8},{ 0, 0},{198, 30},{ 0, 0},{ 0, 0}}, // M_Wolfhound {{220,182},{114,182},{274,126},{ 82,122},{ 82, 34},{230, 34},{154, 6},{ 0, 0},{190, 60},{ 0, 0},{ 0, 0}} // M_Zeus }; diff --git a/MFD-RADAR-MAPPINGS.md b/MFD-RADAR-MAPPINGS.md new file mode 100644 index 00000000..3700e189 --- /dev/null +++ b/MFD-RADAR-MAPPINGS.md @@ -0,0 +1,452 @@ +# MFD and Radar Damage Mapping Guide + +This document explains how the external MFD and Radar damage-paper-doll mappings are authored, +stored, rendered, checked, and added for a new 'Mech. It records the workflow established while +reviewing and installing all usable art under `Finished HUDS from J&J/` on 2026-08-07. + +## Scope and terminology + +There are three related damage displays. Do not mix their mapping tables: + +| Display | Mapping source | Art path | +|---|---|---| +| Normal in-cockpit HUD | `Gameleap/code/mw4/Code/MW4/huddamage.cpp`: `texuv` and `offset` | Content texture `hud\` | +| External MFD | `Gameleap/code/CoreTech/Libraries/GameOS/coord.cpp`: `texuv2` and `offset2` | Loose `Gameleap/mw4/hsh/hud/.bmp` | +| Radar secondary damage display | `coord.cpp`: `texuv3` and `offset3` | Loose `Gameleap/mw4/hsh/radar/hud/.bmp` | + +This guide is about the last two displays, both controlled by `coord.cpp`. The nearby `// MFD` +comments refer to the external display. The normal cockpit HUD has different coordinates in +`huddamage.cpp`. + +The small images in `hsh/MFD/` are also a different asset set. `render.cpp` tiles those images +into a mech texture atlas. They are not the 512x512 damage-mask images mapped by `coord.cpp`. + +## Controlling code + +`coord.cpp` defines four positional arrays: + +```cpp +float texuv2[65][11][4]; // MFD source rectangles +int offset2[65][11][2]; // MFD exploded destination positions +float texuv3[65][11][4]; // Radar source rectangles +int offset3[65][11][2]; // Radar exploded destination positions +``` + +The first index is the numeric Mech ID. It must match the positional ID sequence in +`Gameleap/code/mw4/Code/MW4/MechLabHeaders.h`. At present there are 65 active IDs, 0 through +64. Each array therefore has exactly 65 active rows in the same order, from Annihilator through +Zeus. Dasher rows exist but are commented out because Dasher is not active in the roster. + +The second index always uses this eleven-zone order: + +```text +0 LL left leg +1 RL right leg +2 LA left arm +3 RA right arm +4 RT right torso +5 LT left torso +6 CT center torso +7 CTR center torso rear +8 HD head +9 S1 special 1 +10 S2 special 2 +``` + +Use `{0,0,0,0}` and `{0,0}` for a zone that has no art. The comment above `offset2` currently +says `S2 S1`; the array consumers and the other tables use index 9 as S1 and index 10 as S2. +Treat the header comment as stale and preserve the index order above. + +## What the values mean + +An unexploded rectangle is recorded as: + +```text +(x0, y0, x1, y1) +``` + +`(x0,y0)` is the upper-left pixel and `(x1,y1)` is the lower-right pixel of that component in +the prepared unexploded image. In code this becomes one `texuv2` or `texuv3` entry. + +An exploded position is recorded as: + +```text +(x2, y2) +``` + +It is the upper-left destination position of that component in the exploded layout. In code +this becomes one `offset2` or `offset3` entry. The component keeps the width and height implied +by its unexploded rectangle: + +```text +width = x1 - x0 +height = y1 - y0 +exploded bounds = (x2, y2, x2 + width, y2 + height) +``` + +Coordinates are normally even because both authoring pipelines were designed around even pixel +boundaries. Do not silently round a visually validated odd value: several supplied sets contain +intentional odd coordinates, including Assassin II Radar S1 `y=3`, Behemoth MFD RA `x=281`, and +Black Hawk Radar RT `x=85`. Radar's integer `/2` truncates odd values at runtime, so changing an +odd authored value can move an edge or origin in the rendered 256x256 view. Work from the +upper-left to lower-right of each component, and do not overlap source rectangles. + +## MFD authoring pipeline + +Start with the finished 1024x1024 full-color 'Mech image. + +1. Reduce the image to 320x320. +2. Expand the canvas to 340x340, centered. This adds 10 pixels on every side. +3. Separate adjacent body sections with a 4x4-pixel black line so source rectangles do not + overlap or bleed into one another. +4. Save this as the unexploded working view. +5. For every zone, record its unexploded `(x0,y0,x1,y1)` rectangle, preferring even values. +6. Starting from the unexploded view in the upper-left, place copies of the separated pieces in + their exploded positions. +7. Record each exploded piece's upper-left `(x2,y2)` coordinate, preferring even values. +8. Expand the canvas to 512x512, anchored at the upper-left. Added area is black. +9. Convert the exploded view to indexed color mode and save it as the runtime BMP. + +Enter the rectangle values in `texuv2` and the exploded upper-left values in `offset2`. + +At runtime, `huddamage.cpp` draws an MFD component as: + +```cpp +mfd_device.DrawTexture( + offset2[mech][zone][0] + 100, + offset2[mech][zone][1] + 40, + color, + texuv2[mech][zone][0], + texuv2[mech][zone][1], + texuv2[mech][zone][2], + texuv2[mech][zone][3]); +``` + +The `+100,+40` values position the complete paper doll in the MFD UI. They are not part of the +authored coordinates and must not be added to `coord.cpp`. + +`CMFD_Device::LoadDamageTexture()` receives the logical name `hud\` and loads the loose +bitmap at `hsh\hud\.bmp`. + +## Radar authoring pipeline + +Start with the same finished 1024x1024 full-color image. + +1. Reduce the image to 400x400. +2. Expand the canvas to 410x410, centered. This adds 5 pixels on every side. +3. Expand the canvas to 512x512, anchored at the upper-left. Added area is black. +4. Save this as the unexploded working view. +5. Split the body into non-overlapping components from each component's upper-left to + lower-right. +6. Outline components with a 2x2-pixel white line. +7. Record each unexploded `(x0,y0,x1,y1)` rectangle, preferring even values. +8. Starting from the unexploded view in the upper-left, place copies of the pieces in their + exploded positions. +9. Record each exploded piece's upper-left `(x2,y2)` coordinate, preferring even values. +10. Convert the exploded view to indexed color mode and save it as the runtime BMP. + +Enter the rectangle values in `texuv3` and the exploded upper-left values in `offset3`. + +Radar coordinates are authored in the full 512x512 coordinate space. The runtime deliberately +divides every rectangle and offset coordinate by two, switches the texture dimensions to +256x256 for the draw, and then adds the Radar UI origin: + +```cpp +radar_device.DrawTexture( + (offset3[mech][zone][0] / 2) + 138, + (offset3[mech][zone][1] / 2) + 406, + color, + texuv3[mech][zone][0] / 2, + texuv3[mech][zone][1] / 2, + texuv3[mech][zone][2] / 2, + texuv3[mech][zone][3] / 2); +``` + +Do not pre-divide values when editing `coord.cpp`. Author and store the full-size values; +preserve visually validated odd coordinates because runtime integer division determines their +final half-resolution placement. +The runtime loads `hsh\radar\hud\.bmp` through +`CRadar_Device::LoadRadarDamageTexture()`. + +## Reading an existing mapping + +1. Find the Mech ID in `MechLabHeaders.h`. +2. Confirm that the same row number is used in all four `coord.cpp` arrays. Comments are useful + labels but do not control the mapping; array position does. +3. Read the eleven `texuv` rectangles in the fixed zone order above. +4. Read the eleven matching `offset` points in the same order. +5. Ignore spelling differences in end-of-row comments unless they indicate an actual row-order + error. Examples in the current file include `M_HollnaderII` and capitalization differences. +6. Check that every nonzero rectangle has a corresponding nonzero offset, except where a design + intentionally draws a component at `(0,0)`. +7. Check rectangle bounds, non-overlap, and whether any odd coordinate is intentional and + visually aligned. MFD source geometry is normally inside the 340x340 working area. Radar's + nominal art area is 410x410, but validate imported legacy Radar rectangles against the full + 512x512 prepared canvas: accepted Black Hawk geometry extends beyond 410 and aligns visually. + +## Making or fixing a mapping + +1. Preserve the Mech's row position. Never sort one array independently. +2. Prepare separate MFD and Radar unexploded images using the pipelines above. +3. Measure source rectangles in zone order and record them in a text file before touching code. +4. Prepare exploded layouts and record each upper-left destination point. +5. Verify visually with overlays. +6. Replace only that Mech's row in `texuv2`, `offset2`, `texuv3`, and `offset3` as needed. +7. Preserve `coord.cpp` CRLF line endings and avoid reformatting unrelated rows. +8. Inspect the diff. A one-Mech repair should change at most four rows unless art or roster + registration is also being changed. +9. Rebuild the game because `DXRasterizer.cpp` includes `coord.cpp` directly. Rebuild the needed + Release/Profile targets and redeploy the resulting executable. +10. Compare the supplied exploded BMP to the existing canonical runtime BMP by decoded pixels, + not only by file hash. Replace it only when the pixels differ. See "Runtime art comparison" + below. +11. Install a changed runtime BMP under the matching `Gameleap/mw4/hsh` path. Loose `hsh` art + does not require a resource-package rebuild. +12. Test both intact and damaged states on the real external MFD and Radar displays. + +When adding a new chassis rather than repairing an existing row, also increase the first +dimension of all four arrays and add one correctly positioned row to every array. This is part +of the larger positional-ID workflow documented in `ADDING-A-MECH.md`. + +## Overlay validation method + +Visual overlays are the fastest way to distinguish a coordinate problem from an art problem. + +Generate every available J&J comparison and the status report with: + +```bash +python3 "Finished HUDS from J&J/generate_comparison_maps.py" +``` + +This requires Pillow. It writes two PNGs per available display and updates +`Finished HUDS from J&J/COMPARISON-SUMMARY.md`. The summary reports exact numeric matches, +different zones, missing display inputs, and malformed source measurements. + +Two J&J measurement formats exist: + +- Modern: the Unexploded file contains four-value source rectangles and the Exploded file + contains two-value destination origins. +- Legacy: the Unexploded file contains only each source rectangle's upper-left point, while the + Exploded file contains the complete destination bounding box. For legacy data, derive the + source width and height from the exploded box, apply those dimensions at the unexploded point, + and use the exploded box's upper-left as the destination offset. + +Some combined `Coords.txt` files contain both sections. Trust the section heading and tuple +shape, not the filename alone. The generator handles both formats and indexes current mappings +by numeric Mech ID rather than end-of-row comment spelling. + +All-zero absent-zone tuples are found in both two-value and four-value forms in legacy files. +Normalize an all-zero tuple to the width expected by its section; it still means no art. For +nonzero tuples, a wrong tuple width is an input error and must not be guessed. + +For an unexploded comparison: + +- Use the correctly transformed unexploded canvas, not the exploded-pieces BMP. +- Draw the current `texuv` rectangles in red. +- Draw proposed rectangles in green. +- Label each rectangle with its zone. +- A good rectangle encloses one component, follows its outer extent, and does not include pixels + from another component. + +For an exploded comparison: + +- Use the exploded-pieces BMP. +- Mark each `offset` as an upper-left cross. +- Draw a box from that point using the matching unexploded rectangle's width and height. +- Draw current mappings in red and proposed mappings in green. +- A good exploded mapping places the box exactly over the intended exploded piece. + +Do not draw `texuv2` rectangles directly on the raw 1024x1024 source. For MFD, first apply +1024 -> 320, center on 340, then place at the upper-left of 512. For Radar, apply +1024 -> 400, center on 410, then place at the upper-left of 512. When a supplied legacy +unexploded image is already 512x512, use it directly rather than reconstructing and cropping it; +the supplied coordinates may intentionally reference pixels outside the nominal 410 area. + +## Runtime art comparison + +The exploded 512x512 BMP is the runtime asset. The unexploded BMP and full-color source image +are authoring and measurement references only; do not copy those into `hsh` as the runtime art. + +Resolve the destination by the canonical runtime texture stem for the numeric Mech ID, not by +blindly copying the supplied filename. Current destinations are: + +```text +MFD: Gameleap/mw4/hsh/hud/.bmp +Radar: Gameleap/mw4/hsh/radar/hud/.bmp +``` + +Known naming traps from this review: + +- Assassin II supplied files are misspelled `assian2_*`, but the canonical runtime stem is + `assassin2`; do not overwrite the separate historical `assassinii.bmp` by accident. +- The existing Fafnir runtime file is `Fafnir.bmp` with an uppercase `F` on this case-sensitive + checkout. Resolve destination names case-insensitively, then preserve the existing spelling. +- Folder names, comments, and supplied filenames are labels. Numeric Mech ID and the runtime + texture-name table remain authoritative. + +BMP byte equality is stricter than visual/runtime equality. A supplied file may be indexed `P`, +grayscale `L`, or `RGB`, and may carry a different palette, header, row padding, or metadata while +decoding to exactly the same pixels. Compare in this order before replacing anything: + +1. Confirm both images are 512x512. +2. If file bytes match, the destination is byte-exact. +3. Otherwise decode both images, convert both to a common mode such as RGBA, and compare every + pixel. +4. If decoded pixels match, the destination is already correct. Keep the existing runtime file; + replacing it creates binary churn and may exchange a compact indexed/grayscale BMP for RGB. +5. Copy the supplied exploded BMP only if decoded pixels differ, then repeat the pixel comparison + against the installed destination. + +Loose `hsh` art is not packed into a `.mw4` resource for this path, so an actual art replacement +does not require `build-resources.ps1`. Coordinate changes still require rebuilding the game +executable because `DXRasterizer.cpp` includes `coord.cpp` directly. + +## Reproducible validation + +After editing coordinates, rerun: + +```bash +python3 "Finished HUDS from J&J/generate_comparison_maps.py" +``` + +For the 2026-08-07 data set, the expected terminal result is: + +```text +Generated 38 maps for 19 display sets: 19 exact, 0 different +Warnings: 0; missing display sets: 7 +``` + +Also verify all of the following before considering the source complete: + +- `COMPARISON-SUMMARY.md` contains 19 `EXACT` rows and no `DIFFERENT` rows. +- Each of `texuv2`, `offset2`, `texuv3`, and `offset3` still has 65 active rows. +- Every active row still has exactly 11 zones. +- The edited `coord.cpp` remains CRLF-only; the repository deliberately uses byte-exact files. +- The diff changes only intended Mech rows. This installation changes 38 rows total: two rows + for each of 19 display sets. +- `git status --short -- Gameleap/mw4/hsh` is empty when every runtime image was already correct. +- A Windows VC6 Release/Profile rebuild and physical MFD/Radar test remain required; the Linux + comparison workflow validates data and geometry but cannot replace that runtime test. + +## J&J mapping status as of 2026-08-07 + +All 19 complete display sets under `Finished HUDS from J&J/` are installed in `coord.cpp` and +report `EXACT` in `COMPARISON-SUMMARY.md`: 12 MFD sets and 7 Radar sets across 13 chassis. +Seven opposite-display sets have no complete supplied mapping/image inputs and were not changed. + +Installed sets: + +| Mech ID | Chassis | MFD | Radar | +|---:|---|:---:|:---:| +| 0 | Annihilator | installed | installed | +| 4 | Argus | installed | no supplied set | +| 5 | Assassin II | installed | installed | +| 7 | Avatar | installed | installed | +| 11 | Behemoth | installed | installed | +| 13 | Black Hawk | installed | installed | +| 27 | Fafnir | installed | no supplied set | +| 28 | Flea | installed | no supplied set | +| 29 | Gladiator | installed | no supplied set | +| 33 | Hellspawn | no supplied set | installed | +| 37 | Kodiak | installed | no supplied set | +| 39 | Longbow | installed | no supplied set | +| 62 | Warhammer | installed | installed | + +The supplied exploded BMP for every installed display set was also compared to its canonical +runtime destination under `Gameleap/mw4/hsh/hud/` or `Gameleap/mw4/hsh/radar/hud/`. All 19 are +pixel-identical at 512x512. Their file hashes differ because the supplied files use different BMP +encodings, palettes, or headers; the runtime copies are already correct, so none were replaced. + +Pixel-identical runtime files: + +```text +MFD: annihilator, argus, assassin2, avatar, behemoth, blackhawk, Fafnir, + flea, gladiator, kodiak, longbow, warhammer +Radar: annihilator, assassin2, avatar, behemoth, blackhawk, hellspawn, warhammer +``` + +Three obvious measurement-file transcription errors were normalized without changing the +validated geometry: Behemoth MFD LT `1742` to `174`, Behemoth Radar CT `202.242` to `202,242`, +and Fafnir MFD LL `162.326` to `162,326`. Behemoth Radar's blank S2 was made explicit as `0,0`. + +### Assassin II details + +Reference art and measurements are under: + +```text +Finished HUDS from J&J/AssassinII/ +``` + +The supplied files are: + +```text +HUD/assassinII_HUD_unexploded.txt +HUD/assassinII_hud_exploded.txt +Radar/assassinII_radar_unexploded.txt +Radar/assassinII_radar_exploded.txt +``` + +The supplied Assassin II values were checked against the correctly transformed source art. +Both corrected MFD and Radar mappings align. All four rows were installed in `coord.cpp` on +2026-08-07 and are pending an executable rebuild and hardware test. + +Generated comparison images from the review are: + +```text +Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_unexploded_coords_comparison.png +Finished HUDS from J&J/AssassinII/HUD/assian2_mfd_exploded_coords_comparison.png +Finished HUDS from J&J/AssassinII/Radar/assian2_radar_unexploded_coords_comparison.png +Finished HUDS from J&J/AssassinII/Radar/assian2_radar_exploded_coords_comparison.png +``` + +The generator now draws the installed `coord.cpp` mapping in red and the supplied J&J mapping in +green, so the colors overlap exactly. These PNGs are review art only and are not loaded by the +game. + +### Implemented Assassin II rows + +MFD `texuv2`: + +```cpp +{{ 98,142,148,328},{190,142,240,328},{ 56, 48,124,154},{216, 48,282,154},{180, 22,220,120},{120, 22,158,120},{144, 36,194,186},{ 0, 0, 0, 0},{158, 70,180, 86},{148, 10,190, 48},{ 0, 0, 0, 0}} +``` + +MFD `offset2`: + +```cpp +{{ 6,148},{282,148},{ 6, 10},{266, 10},{206, 22},{ 98, 22},{144,180},{ 0, 0},{158,140},{148, 10},{ 0, 0}} +``` + +Radar `texuv3`: + +```cpp +{{114,170,178,406},{232,170,294,406},{ 60, 48,144,184},{264, 48,348,184},{218, 18,268,140},{142, 18,190,140},{174, 36,234,140},{ 0, 0, 0, 0},{192, 78,218, 98},{178, 2,230, 48},{ 0, 0, 0, 0}} +``` + +Radar `offset3`: + +```cpp +{{ 8,220},{336,220},{ 8, 48},{314, 48},{244, 48},{120, 48},{178,206},{ 0, 0},{192, 78},{178, 3},{ 0, 0}} +``` + +One supplied Radar S1 offset is odd (`y=3`) despite the general even-coordinate rule. Preserve +the measured value until it is deliberately reviewed against the source pixels; do not silently +round it while transcribing the row. + +## Common mistakes + +- Drawing MFD boxes on the raw 1024 image instead of the transformed 340 working canvas. +- Drawing unexploded rectangles on the exploded-pieces BMP. +- Using `texuv`/`offset` from `huddamage.cpp` when the task is external MFD/Radar mapping. +- Using the small `hsh/MFD` atlas image as the external damage-mask source. +- Pre-dividing Radar coordinates by two before putting them in `coord.cpp`. +- Adding the MFD `+100,+40` or Radar `+138,+406` UI origins to authored offsets. +- Treating `(x2,y2)` as a second rectangle instead of an upper-left destination point. +- Measuring overlapping component rectangles or omitting separator/outline pixels. +- Swapping S1 and S2 because of the stale `offset2` header comment. +- Inserting a row into only one parallel array and shifting every later Mech out of alignment. +- Re-encoding or normalizing the entire legacy source file while changing four rows. +- Treating a different BMP hash as different art without decoding and comparing pixels. +- Copying an unexploded/reference BMP instead of the exploded 512x512 runtime BMP. +- Using the supplied `assian2` typo as the destination instead of canonical `assassin2.bmp`. +- Rounding odd coordinates despite a visually aligned overlay. \ No newline at end of file