Repair the four broken Radar damage mappings; document the findings
The whole-tree audit after the previous commit found four Radar rows scoring
0.266-0.638 against their artwork, with boxes bounding blank space. All four are
chassis whose Radar sets J&J never delivered, so the rows had never been checked
against the art. They are pre-existing, not regressions.
With each chassis's MFD now correct, the Radar mapping is derived from it rather
than measured by hand: source boxes come from the Radar art's own connected
components, zone identity is matched from the MFD by normalised position plus a
size-consistency term, and placement scales each piece's ART CENTRE by ~1.25.
Two details that matter and are easy to get wrong. Position-only matching swaps
CT and HD, because a head and a torso can sit at similar normalised positions;
the size term fixes it. And scaling a piece's corner rather than its centre
misplaces it whenever the Radar piece is a different proportion from its MFD
counterpart - the Longbow's Radar CT includes the pelvis while its MFD CT does
not, which put CT 23px off centre until centre-scaling was used.
kodiak 0.266 -> 0.962
longbow 0.379 -> 0.959
argus 0.457 -> 0.956
fafnir 0.638 -> 0.963
Longbow additionally had a phantom special zone. The chassis declares no
Special1Internal, no joint_specialone and ships no *_specialone.erf, yet both
displays mapped S1. On the Radar that piece is the cockpit canopy - it matches
the CT's recess exactly - so it is remapped to HD and S1 is cleared. On the MFD
the S1 piece is the pelvis, a genuinely different component, and is deliberately
retained so the pelvis still renders; it simply never takes damage.
Whole tree after this change: 130 mech/display combinations, mean 0.949, median
0.955, minimum 0.795, none below 0.75 (was four).
MFD-RADAR-MAPPINGS.md is corrected and expanded. Three things it stated were
wrong and had caused real defects:
- it instructed storing the unexploded rect in texuv and the exploded origin
in offset, which is backwards and broke all 21 imported rows;
- it cited Behemoth MFD x=281 and Black Hawk Radar x=85 as intentional odd
coordinates to preserve, when both are transcription errors bounding blank
space (218 transposed, and a lost leading digit of 285);
- it recorded all 19 supplied BMPs as pixel-identical to the runtime art, when
all 19 differ by 6-35% because the art had never been installed.
Added: the handedness rule and its one-line assertion; the .damage cross-check
for special zones; the derivation method above; a catalogue of every verified
defect; and a tooling-pitfalls section covering blob thresholds hiding small
parts, unreliable hole detection on anti-aliased art, ink coverage not implying
correct placement, and overlap audits needing blob ownership to avoid ~107 false
positives. It also notes that generate_comparison_maps.py compares coord.cpp
only to the measurement files and never to the artwork, so it reported "19
exact" throughout every one of these failures.
Requires a Windows VC6 rebuild of MW4.exe and hardware testing on physical
MFD/Radar displays.
Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
This commit is contained in:
co-authored by
Claude Opus 5
GitHub Copilot
parent
ef4e014066
commit
a26ff967d8
@@ -145,7 +145,7 @@ float texuv3[65][11][4]={
|
||||
{{351,185,422,405},{ 84,185,154,405},{407, 52,492,170},{ 18, 52,103,170},{132, 24,178,140},{334, 24,380,140},{200, 5,310,228},{ 0, 0, 0, 0},{249,273,262,284},{ 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
|
||||
{{400,173,481,397},{ 25,173,106,397},{398, 71,500,132},{ 12, 72,114,133},{122, 84,197,177},{315, 83,390,177},{209, 91,305,241},{ 0, 0, 0, 0},{246,350,268,360},{224,278,290,314},{201, 3,313, 67}}, // 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
|
||||
{{347,165,492,400},{ 8,165,153,400},{365, 24,472,148},{ 60, 31,149,125},{161, 40,196,145},{301, 40,341,144},{216, 21,281,225},{ 0, 0, 0, 0},{233,277,265,288},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Argus - Skippy
|
||||
{{336,220,398,456},{ 8,220, 72,456},{314, 48,398,184},{ 8, 48, 92,184},{120, 48,168,170},{244, 48,294,170},{178,206,242,398},{ 0, 0, 0, 0},{192, 78,218, 98},{178, 3,230, 49},{ 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
|
||||
{{384,258,450,484},{ 50,258,116,484},{408, 38,490,112},{ 24, 38, 80,110},{104, 38,152,162},{324, 38,372,162},{198, 38,278,248},{ 0, 0, 0, 0},{230,356,248,372},{224,302,254,332},{ 0, 0, 0, 0}}, // M_Avatar
|
||||
@@ -168,7 +168,7 @@ float texuv3[65][11][4]={
|
||||
{{340,272,496,496},{ 14,272,170,496},{428, 92,490,216},{ 20, 92, 82,216},{100, 74,186,218},{314, 74,400,218},{208, 98,300,276},{ 0, 0, 0, 0},{222, 10,286, 54},{218,354,294,408},{ 0, 0, 0, 0}}, // M_Daishi
|
||||
{{372,258,470,496},{ 42,258,138,496},{398,118,476,218},{ 34,118,112,220},{144,116,216,204},{296,116,368,204},{234,120,278,288},{ 0, 0, 0, 0},{240,320,272,336},{272, 14,346, 78},{166, 14,240, 78}}, // M_Deimos
|
||||
{{348,238,430,498},{ 94,238,176,498},{430,146,488,222},{ 40,134, 98,206},{ 58, 40,132,128},{412, 40,476,128},{208, 56,326,240},{ 0, 0, 0, 0},{250,314,284,332},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Dragon
|
||||
{{390,258,488,488},{ 20,260,118,490},{440, 20,500,162},{ 20, 20, 78,162},{160,200,266,466},{320, 20,428,186},{180, 20,308,266},{ 0, 0, 0, 0},{300,300,324,316},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Fafnir - Skippy
|
||||
{{385,264,481,491},{ 32,264,128,491},{433, 21,493,161},{ 23, 21, 82,161},{104, 10,200,176},{315, 10,411,176},{226, 12,290,250},{ 0, 0, 0, 0},{244,297,271,315},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Fafnir - Skippy
|
||||
{{220,160,330,432},{ 20,160,128,432},{220,120,228,146},{ 20,120, 28,147},{ 20, 20, 86,108},{220, 20,286,108},{140, 20,206,210},{ 0, 0, 0, 0},{140,240,182,264},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Flea - Skippy
|
||||
{{420,290,488,494},{ 20,290, 88,494},{420, 50,476,166},{ 20, 70, 70,188},{110, 70,160,208},{340, 40,390,178},{190, 30,286,278},{ 0, 0, 0, 0},{190,350,222,364},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Gladiator - Skippy
|
||||
{{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
|
||||
@@ -178,9 +178,9 @@ float texuv3[65][11][4]={
|
||||
{{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
|
||||
{{360,278,456,492},{ 54,278,150,492},{420,160,508,270},{ 4,158, 90,270},{ 94, 22,174,170},{336, 22,416,170},{196,206,320,378},{ 0, 0, 0, 0},{218, 24,294, 98},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Kodiak - GhostHawk
|
||||
{{309,264,401,467},{109,264,201,467},{416, 70,500,177},{ 11, 70, 94,177},{110, 36,178,203},{330, 36,399,203},{218, 12,292,243},{ 0, 0, 0, 0},{238,280,271,290},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Kodiak - GhostHawk
|
||||
{{418,266,488,494},{ 22,266, 92,494},{416, 60,474,170},{ 26, 60, 86,170},{136, 38,182,162},{338, 28,386,162},{238, 38,294,220},{ 0, 0, 0, 0},{252,302,278,314},{144,262,200,298},{ 0, 0, 0, 0}}, // M_Loki
|
||||
{{360,238,436,472},{ 94,236,172,472},{410,120,500,214},{ 16,116,108,210},{120, 14,204,126},{316, 14,402,126},{226, 68,294,192},{ 0, 0, 0, 0},{254,366,272,376},{220,232,302,302},{ 0, 0, 0, 0}}, // M_Longbow - GhostHawk
|
||||
{{332,246,404,470},{115,246,187,470},{413, 53,499,142},{ 12, 53, 98,142},{118, 47,198,151},{315, 47,395,152},{220, 32,299,212},{ 0, 0, 0, 0},{239,238,280,257},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Longbow - GhostHawk
|
||||
{{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_Madcat
|
||||
{{364,276,496,494},{ 10,276,144,494},{416,114,498,176},{ 10,114, 90,176},{122, 32,182,174},{332, 32,394,174},{204, 90,304,232},{ 0, 0, 0, 0},{232,298,274,314},{ 8, 4, 86, 80},{422, 4,498, 80}}, // M_Madcat_MKII
|
||||
{{330,248,500,494},{ 6,248,176,494},{414, 44,496,162},{ 10, 44, 92,162},{126, 6,186,152},{302, 6,392,152},{226, 4,282,214},{ 0, 0, 0, 0},{230,324,276,342},{ 0, 0, 0, 0},{ 0, 0, 0, 0}}, // M_Masakari
|
||||
@@ -213,7 +213,7 @@ int offset3[65][11][2]={
|
||||
{{277,185},{162,185},{334, 52},{ 91, 52},{179, 24},{285, 24},{200, 5},{ 0, 0},{249, 54},{ 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
|
||||
{{280,195},{153,195},{354, 83},{ 58, 84},{163, 84},{276, 83},{209, 91},{ 0, 0},{246,103},{224,170},{201, 25}}, // 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
|
||||
{{231,176},{ 62,176},{291, 33},{ 73, 37},{154, 48},{250, 48},{187, 28},{ 0, 0},{201, 63},{ 0, 0},{ 0, 0}}, // M_Argus - Skippy
|
||||
{{232,170},{114,170},{264, 48},{ 60, 48},{142, 18},{218, 18},{174, 36},{ 0, 0},{192, 78},{178, 2},{ 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
|
||||
{{222,174},{ 98,174},{266, 64},{ 62, 64},{118, 44},{220, 44},{152, 10},{ 0, 0},{184, 24},{178,124},{ 0, 0}}, // M_Avatar
|
||||
@@ -236,7 +236,7 @@ int offset3[65][11][2]={
|
||||
{{220,182},{ 34,182},{288, 52},{ 60, 52},{120, 34},{204, 34},{158, 58},{ 0, 0},{172, 60},{218, 4},{ 0, 0}}, // M_Daishi
|
||||
{{222,168},{ 92,168},{288, 68},{ 44, 68},{114, 66},{226, 66},{184, 70},{ 0, 0},{190,100},{222, 4},{116, 4}}, // M_Deimos
|
||||
{{228,148},{104,148},{280, 76},{ 60, 64},{ 78, 0},{262, 0},{148, 16},{ 0, 0},{190, 24},{ 0, 0},{ 0, 0}}, // M_Dragon
|
||||
{{214,175},{ 92,175},{332, 13},{ 13, 13},{ 72, 2},{224, 2},{138, 4},{ 0, 0},{190, 99},{ 0, 0},{ 0, 0}}, // M_Fafnir - Skippy
|
||||
{{223,181},{104,181},{344, 28},{ 21, 28},{ 82, 12},{244, 12},{180, 18},{ 0, 0},{200,111},{ 0, 0},{ 0, 0}}, // M_Fafnir - Skippy
|
||||
{{234,134},{ 68,134},{276, 74},{126, 74},{120, 22},{224, 22},{174, 8},{ 0, 0},{184, 56},{ 0, 0},{ 0, 0}}, // M_Flea - Skippy
|
||||
{{220,201},{115,201},{268, 66},{ 87, 66},{128, 38},{228, 38},{154, 3},{ 0, 0},{186, 67},{ 0, 0},{ 0, 0}}, // M_Gladiator - Skippy
|
||||
{{218,196},{104,196},{288, 46},{ 78, 46},{120, 38},{236, 34},{172, 20},{ 0, 0},{182, 86},{252, 6},{ 0, 0}}, // M_Grizzly
|
||||
@@ -246,9 +246,9 @@ int offset3[65][11][2]={
|
||||
{{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
|
||||
{{214,196},{100,196},{280, 62},{ 44, 62},{104, 28},{226, 28},{144, 74},{ 0, 0},{168, 2},{ 0, 0},{ 0, 0}}, // M_Kodiak - GhostHawk
|
||||
{{213,188},{ 99,188},{276, 64},{ 45, 64},{105, 22},{231, 22},{165, 8},{ 0, 0},{183, 23},{ 0, 0},{ 0, 0}}, // M_Kodiak - GhostHawk
|
||||
{{228,176},{112,176},{276, 60},{ 76, 60},{136, 38},{228, 28},{178, 38},{ 0, 0},{192, 52},{124, 2},{ 0, 0}}, // M_Loki
|
||||
{{228,154},{112,154},{326, 46},{ 0, 46},{ 90, 38},{240, 38},{174, 24},{ 0, 0},{216, 86},{166,148},{ 0, 0}}, // M_Longbow - GhostHawk
|
||||
{{221,157},{115,157},{315, 49},{ 4, 50},{ 93, 42},{234, 41},{164, 29},{ 0, 0},{182, 74},{ 0, 0},{ 0, 0}}, // M_Longbow - GhostHawk
|
||||
{{208,162},{ 76,162},{286, 76},{ 46, 76},{122, 32},{204, 32},{152, 60},{ 0, 0},{188, 66},{256, 2},{ 68, 2}}, // M_Madcat
|
||||
{{234,186},{ 40,186},{266,114},{ 60,114},{142, 32},{202, 32},{154, 90},{ 0, 0},{182,108},{ 68, 4},{262, 4}}, // M_Madcat_MKII
|
||||
{{220,158},{ 16,158},{284, 44},{ 40, 44},{116, 6},{202, 6},{176, 4},{ 0, 0},{180, 84},{ 0, 0},{ 0, 0}}, // M_Masakari
|
||||
|
||||
+275
-99
@@ -65,37 +65,43 @@ Treat the header comment as stale and preserve the index order above.
|
||||
|
||||
## What the values mean
|
||||
|
||||
An unexploded rectangle is recorded as:
|
||||
**This is the single most important section. Getting it backwards silently breaks every row,
|
||||
and it has already happened once ? see "Verified defect catalogue".**
|
||||
|
||||
`texuv` is a **source rectangle in the runtime BMP**, and the runtime BMP is the **exploded**
|
||||
sheet. `offset` is a **destination point on screen**, which is the **assembled** (unexploded)
|
||||
layout. So:
|
||||
|
||||
| Field | Holds | Measured on |
|
||||
|---|---|---|
|
||||
| `texuv2` / `texuv3` | the rectangle bounding that component's piece | the **exploded** sheet |
|
||||
| `offset2` / `offset3` | the upper-left point where the piece is drawn | the **unexploded / assembled** view |
|
||||
|
||||
```text
|
||||
(x0, y0, x1, y1)
|
||||
texuv = (x0, y0, x1, y1) the piece's box on the exploded sheet
|
||||
offset = (x2, y2) where that piece belongs on the assembled mech
|
||||
drawn bounds = (x2, y2, x2 + (x1-x0), y2 + (y1-y0))
|
||||
```
|
||||
|
||||
`(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:
|
||||
The authoring steps below record the unexploded rectangle first and the exploded origin second,
|
||||
which makes it tempting to store them in that order. **Do not.** The measurement order is the
|
||||
reverse of the storage order:
|
||||
|
||||
```text
|
||||
(x2, y2)
|
||||
recorded (x,y,x1,y1) on the unexploded view -> supplies offset (its x,y) and the piece SIZE
|
||||
recorded (x2,y2) on the exploded view -> supplies texuv (its origin) + that same size
|
||||
```
|
||||
|
||||
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:
|
||||
The quickest check: **every `texuv` rectangle must tightly bound real artwork in the exploded
|
||||
BMP.** If a `texuv` lands on blank space or straddles two pieces, the two fields are transposed.
|
||||
|
||||
```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.
|
||||
Coordinates are normally even because both pipelines were designed around even pixel boundaries,
|
||||
and Radar's integer `/2` at runtime truncates odd values. But **an odd or surprising value is
|
||||
more often a transcription error than an intentional choice**. Verify it against the artwork
|
||||
before preserving it. Values previously documented here as "intentional odd coordinates" were
|
||||
later proved to be typos: Behemoth MFD `x=281` is a digit transposition of `218`, and Black Hawk
|
||||
Radar `x=85` lost the leading digit of `285`. Both bounded blank space. Work from the upper-left
|
||||
to lower-right of each component and do not overlap source rectangles.
|
||||
|
||||
## Canonical authoring steps
|
||||
|
||||
@@ -160,6 +166,11 @@ coord.cpp (under GameOS/External dependancies)
|
||||
runtime BMP.
|
||||
- Prefer even numbers when recording, but never round an odd value that has already been
|
||||
visually validated.
|
||||
- **The doll faces the viewer.** The mech's own right side must be drawn on the viewer's LEFT,
|
||||
so that shooting an enemy's right arm lights the left of your display. Art authored from the
|
||||
mech's own viewpoint must have its `L`/`R` zone pairs swapped before it is stored. See
|
||||
"Handedness".
|
||||
- The measurement order is the reverse of the storage order. See "What the values mean".
|
||||
|
||||
## MFD authoring pipeline
|
||||
|
||||
@@ -177,7 +188,8 @@ Start with the finished 1024x1024 full-color 'Mech image.
|
||||
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`.
|
||||
Store the **exploded** boxes in `texuv2` and the **unexploded** upper-left points in `offset2`.
|
||||
This is the reverse of the order in which they are measured; see "What the values mean".
|
||||
|
||||
At runtime, `huddamage.cpp` draws an MFD component as:
|
||||
|
||||
@@ -215,7 +227,8 @@ Start with the same finished 1024x1024 full-color image.
|
||||
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`.
|
||||
Store the **exploded** boxes in `texuv3` and the **unexploded** upper-left points in `offset3`.
|
||||
This is the reverse of the order in which they are measured; see "What the values mean".
|
||||
|
||||
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
|
||||
@@ -249,10 +262,12 @@ The runtime loads `hsh\radar\hud\<name>.bmp` through
|
||||
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.
|
||||
7. Score every rectangle against the runtime BMP. This is the only check that catches
|
||||
transposition, mirroring and transcription errors at once.
|
||||
8. Check rectangle bounds and non-overlap, and treat any odd or surprising coordinate as suspect
|
||||
until it is confirmed against the artwork. MFD source geometry is normally inside the 340x340
|
||||
working area; Radar's nominal art area is 410x410, though exploded pieces legitimately occupy
|
||||
the full 512x512 sheet. A rectangle that bounds blank space is an error, not a style.
|
||||
|
||||
## Making or fixing a mapping
|
||||
|
||||
@@ -261,18 +276,22 @@ The runtime loads `hsh\radar\hud\<name>.bmp` through
|
||||
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
|
||||
6. Check handedness: `offset[RA].x < offset[LA].x`, and likewise for the torso and leg pairs.
|
||||
7. Check `S1`/`S2` against the chassis's `.damage` file before mapping either.
|
||||
8. Score every rectangle against the artwork; a set should average 0.85 or better excluding `HD`.
|
||||
9. Replace only that Mech's row in `texuv2`, `offset2`, `texuv3`, and `offset3` as needed.
|
||||
10. Preserve `coord.cpp` CRLF line endings and each row's own indentation and trailing text.
|
||||
11. 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
|
||||
12. 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,
|
||||
13. 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.
|
||||
14. Install a changed runtime BMP under the matching `Gameleap/mw4/hsh` path. Loose `hsh` art
|
||||
does not require a resource-package rebuild. Edit the source tree `Gameleap/mw4/hsh`, not the
|
||||
`MW4/` deployment, which `deploy-mw4.ps1` regenerates.
|
||||
15. 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
|
||||
@@ -373,81 +392,119 @@ executable because `DXRasterizer.cpp` includes `coord.cpp` directly.
|
||||
|
||||
## Reproducible validation
|
||||
|
||||
After editing coordinates, rerun:
|
||||
> **`generate_comparison_maps.py` cannot detect the failures that actually occurred.** It compares
|
||||
> `coord.cpp` against the J&J measurement files only ? never against the artwork. It therefore
|
||||
> reported "19 exact, 0 different" while the stored rows had `texuv`/`offset` transposed, left and
|
||||
> right mirrored, eight transcription errors, and artwork that had never been installed. It
|
||||
> confirms transcription fidelity, nothing more. It now reports differences by design, because
|
||||
> the stored rows deliberately diverge from the supplied files in the places listed below.
|
||||
|
||||
```bash
|
||||
python3 "Finished HUDS from J&J/generate_comparison_maps.py"
|
||||
```
|
||||
|
||||
For the 2026-08-07 data set, the expected terminal result is:
|
||||
The check that does work is scoring each stored rectangle against the artwork it claims to bound.
|
||||
For every zone, take the best intersection-over-union against the connected components of the
|
||||
runtime BMP, and average per set **excluding `HD`**:
|
||||
|
||||
```text
|
||||
Generated 38 maps for 19 display sets: 19 exact, 0 different
|
||||
Warnings: 0; missing display sets: 7
|
||||
healthy 0.85 - 0.99
|
||||
suspect below 0.75
|
||||
broken below 0.55
|
||||
```
|
||||
|
||||
The distribution is strongly bimodal, so the threshold is not delicate. Whole-tree state after
|
||||
this work, across all 65 chassis and both displays:
|
||||
|
||||
```text
|
||||
130 combinations mean 0.949 median 0.955 minimum 0.795 none below 0.75
|
||||
```
|
||||
|
||||
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.
|
||||
Note that mech ID 60's rows in `offset2`/`offset3` lack the leading tab, and rows for Avatar,
|
||||
Vulture and Zeus have irregular trailing whitespace. Preserve each row's own prefix and suffix
|
||||
rather than assuming a uniform format.
|
||||
- The diff changes only intended Mech rows.
|
||||
- Handedness holds for every row: `offset[RA].x < offset[LA].x`.
|
||||
- Special zones agree with each chassis's `.damage` file.
|
||||
- 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
|
||||
## Verified defect catalogue
|
||||
|
||||
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.
|
||||
Behemoth II (Mech ID 12) has no separate J&J measurement set because it deliberately shares
|
||||
Behemoth's geometry and art. Its four rows now inherit Behemoth's validated ID 11 rows, bringing
|
||||
the effective installed result to 21 MFD/Radar mappings across 14 Mech IDs. The comparison
|
||||
generator asserts this inheritance on every run and fails if any row diverges.
|
||||
Every one of these was found by scoring rectangles against artwork and confirmed by eye. They are
|
||||
recorded because they show what the failure modes look like.
|
||||
|
||||
Installed sets:
|
||||
### Systemic
|
||||
|
||||
| Defect | Effect | Detection |
|
||||
|---|---|---|
|
||||
| `texuv`/`offset` transposed on all 21 imported rows | no rectangle bounded its own art | every zone scores far below 0.55 |
|
||||
| left/right mirrored on all 21 imported rows | damage displayed on the wrong side | `offset[RA].x > offset[LA].x` |
|
||||
| artwork never installed | rows described art that was not on disk | 6-35% of pixels differ from the supplied BMP |
|
||||
|
||||
The handedness fault was confined exactly to the imported rows: all 13 affected chassis were
|
||||
mirrored, and all 52 untouched chassis were correct. That correlation is what proved the fault
|
||||
arrived with the import rather than existing in the original game data.
|
||||
|
||||
### Transcription errors in the supplied measurement files
|
||||
|
||||
| Chassis | Zone | As written | Corrected | Nature |
|
||||
|---|---|---|---|---|
|
||||
| Annihilator Radar | RA | `30,24,126,42` | `...,142` | dropped digit |
|
||||
| Assassin II Radar | CT | 60x104 | 64x192 | omitted the pelvis flare |
|
||||
| Behemoth MFD | LA | `x=281` | `218` | digit transposition |
|
||||
| Black Hawk MFD | RT | `0,96,152,114` | `96,0,...` | first pair transposed |
|
||||
| Black Hawk MFD | HD | `164,146,178,150` | `...,136,...` | box only 4px tall |
|
||||
| Black Hawk Radar | LT | `85,56,362,200` | `284,...` | lost leading digit |
|
||||
| Black Hawk Radar | LA | `y0=30` | `28` | clipped 2 rows of art |
|
||||
| Fafnir MFD | RT, LA | ? | trimmed 2px | box overlapped the neighbouring piece |
|
||||
|
||||
Previously normalized in the source files without changing geometry: Behemoth MFD LT `1742`
|
||||
to `174`, Behemoth Radar CT `202.242` to `202,242`, Fafnir MFD LL `162.326` to `162,326`, and
|
||||
Behemoth Radar's blank S2 made explicit as `0,0`.
|
||||
|
||||
### Mapping errors
|
||||
|
||||
- **Kodiak MFD `HD`** sat mid-torso on flat plating; moved into the CT's cockpit slot.
|
||||
- **Warhammer MFD `CT`** sat 19px right, burying `LT` inside it and throwing `HD` off centre.
|
||||
Moving `CT` alone fixed all three symptoms.
|
||||
- **Longbow Radar `S1`** was the cockpit canopy, not a special; remapped to `HD`.
|
||||
- **Argus, Fafnir, Kodiak, Longbow Radar** were wholly misaligned (0.266-0.638) and were derived
|
||||
from their corrected MFD counterparts.
|
||||
|
||||
## Status as of 2026-08-09
|
||||
|
||||
All 19 supplied display sets are installed with corrected geometry, and the four broken
|
||||
opposite-display Radar mappings have been derived. Artwork for all 19 sets was installed for the
|
||||
first time; `behemothii` art was resynced from `behemoth` because ID 12 inherits ID 11's rows.
|
||||
|
||||
| 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 |
|
||||
| 0 | Annihilator | J&J, corrected | J&J, corrected |
|
||||
| 4 | Argus | J&J, corrected | derived 0.956 |
|
||||
| 5 | Assassin II | J&J, corrected | J&J, corrected |
|
||||
| 7 | Avatar | J&J, corrected | J&J, corrected |
|
||||
| 11 | Behemoth | J&J, corrected | J&J, corrected |
|
||||
| 12 | Behemoth II | inherited from ID 11 | inherited from ID 11 |
|
||||
| 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 |
|
||||
| 13 | Black Hawk | J&J, corrected | J&J, corrected |
|
||||
| 27 | Fafnir | J&J, corrected | derived 0.963 |
|
||||
| 28 | Flea | J&J, corrected | original, 0.967 |
|
||||
| 29 | Gladiator | J&J, corrected | original, 0.984 |
|
||||
| 33 | Hellspawn | original | J&J, corrected |
|
||||
| 37 | Kodiak | J&J, corrected | derived 0.962 |
|
||||
| 39 | Longbow | J&J, corrected | derived 0.959 |
|
||||
| 62 | Warhammer | J&J, corrected | J&J, corrected |
|
||||
|
||||
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.
|
||||
Outstanding, both pre-existing and blocked on missing art:
|
||||
|
||||
Pixel-identical runtime files:
|
||||
- **Annihilator** declares `Special2Internal` with no S2 mapping or art.
|
||||
- **Behemoth II** declares both specials but inherits Behemoth's rows, which define only S1.
|
||||
|
||||
```text
|
||||
MFD: annihilator, argus, assassin2, avatar, behemoth, blackhawk, Fafnir,
|
||||
flea, gladiator, kodiak, longbow, warhammer
|
||||
Radar: annihilator, assassin2, avatar, behemoth, blackhawk, hellspawn, warhammer
|
||||
```
|
||||
|
||||
Behemoth II uses separate canonical files, `hud/behemothii.bmp` and
|
||||
`radar/hud/behemothii.bmp`. Both were decoded and compared to their corresponding Behemoth
|
||||
runtime BMP on 2026-08-07; both were already pixel-identical 512x512 grayscale images, so no art
|
||||
files were copied or replaced.
|
||||
|
||||
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`.
|
||||
The supplied exploded BMPs were **not** pixel-identical to the runtime files, contrary to what
|
||||
this document previously recorded. All 19 differed by 6-35% of pixels, confirming the art had
|
||||
never been installed. Sources arrived as a mix of `P`, `L` and `RGB` and were normalised to
|
||||
512x512 8-bit greyscale to match the existing `hsh` convention.
|
||||
|
||||
### Assassin II details
|
||||
|
||||
@@ -485,33 +542,143 @@ game.
|
||||
|
||||
### Implemented Assassin II rows
|
||||
|
||||
MFD `texuv2`:
|
||||
These are the corrected rows as stored on 2026-08-09, after the transposition and handedness
|
||||
fixes and after extending Radar `CT` to include the pelvis flare. Compare against the raw
|
||||
supplied files and the differences are exactly those two systemic corrections plus that one
|
||||
zone.
|
||||
|
||||
MFD `texuv2` (exploded boxes):
|
||||
|
||||
```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}}
|
||||
{{282,148,332,334},{ 6,148, 56,334},{266, 10,332,116},{ 6, 10, 74,116},{ 98, 22,136,120},{206, 22,246,120},{144,180,194,330},{ 0, 0, 0, 0},{158,140,180,156},{148, 10,190, 48},{ 0, 0, 0, 0}}
|
||||
```
|
||||
|
||||
MFD `offset2`:
|
||||
MFD `offset2` (assembled points):
|
||||
|
||||
```cpp
|
||||
{{ 6,148},{282,148},{ 6, 10},{266, 10},{206, 22},{ 98, 22},{144,180},{ 0, 0},{158,140},{148, 10},{ 0, 0}}
|
||||
{{190,142},{ 98,142},{216, 48},{ 56, 48},{120, 22},{180, 22},{144, 36},{ 0, 0},{158, 70},{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}}
|
||||
{{336,220,398,456},{ 8,220, 72,456},{314, 48,398,184},{ 8, 48, 92,184},{120, 48,168,170},{244, 48,294,170},{178,206,242,398},{ 0, 0, 0, 0},{192, 78,218, 98},{178, 3,230, 49},{ 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}}
|
||||
{{232,170},{114,170},{264, 48},{ 60, 48},{142, 18},{218, 18},{174, 36},{ 0, 0},{192, 78},{178, 2},{ 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.
|
||||
Note `LL` precedes `RL` in storage order while `offset[RL].x < offset[LL].x` on screen ? that is
|
||||
the handedness rule working correctly, not an error.
|
||||
|
||||
The Radar `S1` rectangle retains an odd `y=3`. Unlike the other odd values once recorded here,
|
||||
this one was checked against the artwork and is genuinely the piece's edge, so it stands.
|
||||
|
||||
## Handedness
|
||||
|
||||
The paper doll shows the mech **facing the viewer**. Damage must map to the side the shooter
|
||||
actually hit, so:
|
||||
|
||||
```text
|
||||
the mech's RIGHT zones (RA, RT, RL) are drawn on the VIEWER'S LEFT
|
||||
the mech's LEFT zones (LA, LT, LL) are drawn on the VIEWER'S RIGHT
|
||||
```
|
||||
|
||||
In stored terms, `offset[RA].x < offset[LA].x` for every chassis. This is checkable mechanically
|
||||
and should be asserted on any new or imported row:
|
||||
|
||||
```python
|
||||
assert off["RA"][0] < off["LA"][0] # and likewise RT/LT, RL/LL
|
||||
```
|
||||
|
||||
`S1`/`S2` are **not** a left/right pair by convention. Shipped chassis have S1 on either side, so
|
||||
only swap them when both exist and they are genuinely mirrored hardpoints. When only one special
|
||||
is defined, leave it in `S1`.
|
||||
|
||||
Art supplied by an external author is frequently labelled from the mech's own viewpoint, which is
|
||||
the natural way to think when drawing a mech. The entire J&J delivery was labelled that way. The
|
||||
check above catches it in one pass.
|
||||
|
||||
## Cross-check special zones against the damage model
|
||||
|
||||
A zone must not be mapped unless the chassis actually declares it. The authority is the mech's
|
||||
`.damage` file under `Gameleap/mw4/Content/Mechs/<Chassis>/`:
|
||||
|
||||
```text
|
||||
[joint_specialone] + [Special1Internal] + <prefix>_specialone.erf -> S1 exists
|
||||
[Special2Internal] -> S2 exists
|
||||
neither -> S1 and S2 must be {0,0,0,0}
|
||||
```
|
||||
|
||||
Run this whenever rows are imported. It caught two real problems:
|
||||
|
||||
- **Longbow** declares no special zone at all, yet both displays had `S1` mapped. On the Radar
|
||||
that "S1" piece was in fact the **cockpit canopy** and is now mapped to `HD`. On the MFD it is
|
||||
the pelvis; it is deliberately retained so the pelvis still renders, and simply never takes
|
||||
damage.
|
||||
- **Annihilator** declares `Special2Internal` and **Behemoth II** declares both specials, but
|
||||
neither has the corresponding mapping. These remain unmapped for lack of art.
|
||||
|
||||
The general lesson: a piece labelled `S1` by an art supplier is only a guess. Confirm what the
|
||||
component actually is before trusting the label.
|
||||
|
||||
## Deriving a missing display from the other
|
||||
|
||||
Six chassis were delivered with only one of the two displays. Where the opposite display's art
|
||||
exists but its mapping is wrong, the mapping can be derived rather than measured by hand, using
|
||||
the corrected display as a template. This produced 0.956-0.963 mean fits for Argus, Fafnir,
|
||||
Kodiak and Longbow Radar.
|
||||
|
||||
Method:
|
||||
|
||||
1. Detect the connected components in the target display's exploded BMP. Their bounding boxes
|
||||
are the `texuv` rectangles directly.
|
||||
2. Assign zone identity by matching each piece against the **known-good** other display, scoring
|
||||
normalised position **plus a size-consistency term**. Position alone is not enough ? it
|
||||
confidently swapped `CT` and `HD` on every chassis, because a head and a torso can sit at
|
||||
similar normalised positions.
|
||||
3. Compute the scale as the median of matched piece sizes. MFD to Radar is about **1.25-1.30**,
|
||||
not 2, despite Radar's runtime `/2`.
|
||||
4. Place each piece by scaling its **art centre**, not its bounding-box corner. Radar pieces are
|
||||
not the same proportion as their MFD counterparts ? the Longbow's Radar `CT` includes the
|
||||
pelvis while its MFD `CT` does not ? so scaling the corner misplaces them. Centre-scaling put
|
||||
`CT` within 0-2px of the `RT`/`LT` midpoint on all four chassis; corner-scaling was 23px out.
|
||||
5. A zone present in the template but absent from the target's art (a head drawn into the CT
|
||||
rather than as a separate piece) is placed by its position **relative to CT in the assembled
|
||||
layout**, then cut from the CT piece. Do not use its position within the CT's *sheet* box ?
|
||||
the two are unrelated.
|
||||
6. Clamp the finished layout so nothing lands at a negative coordinate.
|
||||
7. Review every zone visually and adjust. Automation gets the fit; only the eye gets the pose.
|
||||
|
||||
## Tooling pitfalls
|
||||
|
||||
Hard-won, all of which produced a wrong answer at least once during this work:
|
||||
|
||||
- **Blob detection hides small parts.** A minimum-area threshold of 300px silently drops heads
|
||||
and small pods, making a perfectly good zone score 0.00. Use ~30px and confirm before
|
||||
concluding a zone is broken. Four "defects" evaporated when the threshold was lowered.
|
||||
- **A low IoU on `HD` is usually normal.** Heads are slivers cut from the CT and often have no
|
||||
dedicated blob. Score sets on the mean **excluding** `HD`.
|
||||
- **Enclosed-hole detection is unreliable on anti-aliased art.** A thin trail of mid-grey edge
|
||||
pixels can connect a real recess to unrelated dark regions, inflating the bounding box until
|
||||
"centre the head in the hole" pushes it onto solid plating. Always render the host piece with
|
||||
the detected hole outlined before trusting it. This produced one wrong Longbow edit that had
|
||||
to be reverted; the Kodiak edit survived the same test because its slot is a clean isolated
|
||||
rectangle.
|
||||
- **High ink coverage does not mean correct placement.** A head box scoring 100% ink may simply
|
||||
be sitting on the solid interior of the torso. Compare candidate positions visually.
|
||||
- **Overlap audits need blob ownership.** Naively flagging any box that overlaps any blob reports
|
||||
~107 false positives, because detail features inside a piece register as separate blobs. Assign
|
||||
each blob to its best-matching zone first, then flag only cross-zone overlaps: that reduced the
|
||||
same batch to 4 real cases.
|
||||
- **Mirrored pairs must be levelled on the ART, not the box.** Mirrored pieces often carry
|
||||
different internal padding, so matching box edges leaves the visible art unlevel. Measure the
|
||||
first and last inked row.
|
||||
- **`str.replace` on a config file hits every match.** An override keyed `("behemoth","mfd","LA")`
|
||||
existed in two dicts and a single replace corrupted both. Anchor edits or rewrite the file.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
@@ -529,4 +696,13 @@ round it while transcribing the row.
|
||||
- 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.
|
||||
- Rounding odd coordinates despite a visually aligned overlay.
|
||||
- Storing the unexploded rectangle in `texuv` and the exploded origin in `offset`. They are the
|
||||
other way round; this broke all 21 imported rows.
|
||||
- Accepting art labelled from the mech's own viewpoint without swapping the L/R zone pairs.
|
||||
- Trusting an `S1`/`S2` label from an art supplier without checking the chassis's `.damage` file.
|
||||
- Trusting `generate_comparison_maps.py` as a correctness check. It only compares `coord.cpp` to
|
||||
the measurement files, never to the artwork.
|
||||
- Concluding a zone is broken from a low IoU without first lowering the blob-area threshold, or
|
||||
from a low `HD` score, which is normal.
|
||||
- Editing `MW4/hsh` instead of the source tree `Gameleap/mw4/hsh`.
|
||||
Reference in New Issue
Block a user