Repository navigation
Conversation
…cliff state of maps up to version 7 Merging the Height Map code in 330ad22 gave Generals the cliff state rows of Zero Hour, which have (width+7)/8 bytes. Retail Generals keeps them in rows of (width+1)/8 bytes, which are too short for the last cells of a row when the map width modulo 8 is 2 to 6. These cells share their bit with the first cells of the next row. Since the merge they read as no cliff instead, so the pathfinder classifies them differently and retail Generals replays on such maps mismatch. A retail compatible Generals now restores the shared values after loading. For version 7 maps the last cells of a row take the stored bits of the first cells of the next row. For older maps, whose flags are computed from the heights column by column, the first cells of the next row take the flags of the last cells, which retail computes last. Without retail compatibility, Generals and Zero Hour compute the flags of these cells from the heights for version 7 maps, because the file has no bits for them. Steep slopes in the last columns of such maps are no longer passable for ground units. A retail compatible Zero Hour and all version 8 maps keep the cliff state as before.
WalkthroughThe parser now reconstructs missing cliff-flag row-tail cells using compile-time configuration and blend-data version. The version-7 byte-width calculation is unchanged. ChangesCliff-flag parsing
Priority: Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Possibly related issues
Possibly related PRs
Suggested reviewers: Merge Risk:
|
[Medium impact] The PR appears safe to merge.
|
| if (info->version==K_BLEND_TILE_VERSION_7) { | ||
| Int byteWidth = (m_width+1)/8; // previous incorrect length that got used to save the file. jba. [4/3/2003] | ||
| // previous incorrect length that got used to save the file. jba. [4/3/2003] | ||
| Int byteWidth = (m_width+1)/8; | ||
| UnsignedByte *data = new UnsignedByte[m_height*byteWidth]; | ||
| file.readArrayOfBytes((char*)data, m_height*byteWidth); | ||
| for (j=0; j<m_height; j++) { | ||
| for (i=0; i<byteWidth; i++) { | ||
| m_cellCliffState[j*m_flipStateWidth + i] = data[j*byteWidth + i]; | ||
| } | ||
| } | ||
| delete[] data; | ||
| } else { |
|
I've updated the issue with a second replay and custom map that's not fixed by this change. |
This change fixes a Generals retail mismatch caused by the Height Map merge in #1991 (330ad22).
Problem
The cliff state of a map is a bit array with one bit per terrain cell. The pathfinder reads it to decide which cells are cliffs. Retail Generals keeps it in rows of
(width+1)/8bytes. That is too short for the last cells of a row whenwidth % 8is 2 to 6, so those cells share their bit with the first cells of the next row. The merge gave Generals Zero Hour's rows of(width+7)/8bytes, so those cells read as no cliff. The pathfinder then classifies them differently from retail, and retail Generals replays on such maps mismatch. One example is a 1v1v1 replay on Grand Canyon (350 × 350), which mismatches in frame 35830.Change
WorldHeightMap::ParseBlendTileDataadjusts the cliff state once after loading.getCliffStateandsetCliffStateare unchanged.RTS_GENERALS && RETAIL_COMPATIBLE_CRC) restores the retail values of the shared cells for maps up to version 7:RETAIL_COMPATIBLE_CRC(both games): for version 7 maps, the last cells of a row are computed from the heights, because the file has no bits for them.Testing
-headless -replay: all 6 Generals 1.08 replays of GeneralsReplays plus the Grand Canyon replay pass, and all 10 Zero Hour 1.04 replays pass. Without the fix the Grand Canyon replay mismatches in frame 35830.maps.bigand on the two Generals test maps. That includes the version 6 maps CHI08 and Cliff. With the transform disabled, the model finds 99 to 248 wrong cells per map.RTS_BUILD_OPTION_RETAIL_COMPATIBLE_GAME=OFF. On all version 7 maps in the retailmaps.bigthe recomputed cells lie in the map border, outside the playable area. Maps with a very small border, such as Grand Canyon, gain these cliffs, and the computed values match the retail ones on all of its 1,745 shared cells.AI Use
Issue identified and fixed by Claude Opus 5.5