From c4b459570848db20d2138f681a5c44e3d9bbf736 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 21 Nov 2021 18:23:44 +0000 Subject: [PATCH] Fix importing maps containing 255 height elements --- src/openrct2/rct1/S4Importer.cpp | 27 ++++++----- src/openrct2/rct2/S6Importer.cpp | 80 ++++++++++++++++---------------- 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 56e036a7e2..b8fb46a882 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1542,13 +1542,8 @@ namespace RCT1 { for (coords.x = 0; coords.x < MAXIMUM_MAP_SIZE_TECHNICAL; coords.x++) { - if (coords.x >= RCT1_MAX_MAP_SIZE || coords.y >= RCT1_MAX_MAP_SIZE) - { - auto& dstElement = tileElements.emplace_back(); - dstElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE); - dstElement.SetLastForTile(true); - } - else + auto tileAdded = false; + if (coords.x < RCT1_MAX_MAP_SIZE && coords.y < RCT1_MAX_MAP_SIZE) { // This is the equivalent of map_get_first_element_at(x, y), but on S4 data. RCT12TileElement* srcElement = tilePointerIndex.GetFirstElementAt(coords); @@ -1564,12 +1559,20 @@ namespace RCT1 auto numAddedElements = ImportTileElement(dstElement, srcElement); tileElements.resize(originalSize + numAddedElements); } while (!(srcElement++)->IsLastForTile()); + } - // Set last element flag in case the original last element was never added - if (tileElements.size() > 0) - { - tileElements.back().SetLastForTile(true); - } + if (!tileAdded) + { + // Add a default surface element, we always need at least one element per tile + auto& dstElement = tileElements.emplace_back(); + dstElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE); + dstElement.SetLastForTile(true); + } + + // Set last element flag in case the original last element was never added + if (tileElements.size() > 0) + { + tileElements.back().SetLastForTile(true); } } } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 91a6e0e136..928ac83368 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1096,52 +1096,52 @@ public: nextElementInvisible = false; restOfTileInvisible = false; - if (coords.x >= RCT2_MAXIMUM_MAP_SIZE_TECHNICAL || coords.y >= RCT2_MAXIMUM_MAP_SIZE_TECHNICAL) + auto tileAdded = false; + if (coords.x < RCT2_MAXIMUM_MAP_SIZE_TECHNICAL && coords.y < RCT2_MAXIMUM_MAP_SIZE_TECHNICAL) { + const auto* srcElement = tilePointerIndex.GetFirstElementAt(coords); + if (srcElement != nullptr) + { + do + { + if (srcElement->base_height == RCT12_MAX_ELEMENT_HEIGHT) + { + continue; + } + + auto tileElementType = static_cast(srcElement->GetType()); + if (tileElementType == RCT12TileElementType::Corrupt) + { + // One property of corrupt elements was to hide tops of tower tracks, and to avoid the next + // element from being hidden, multiple consecutive corrupt elements were sometimes used. This + // would essentially toggle the flag, so we inverse nextElementInvisible here instead of always + // setting it to true. + nextElementInvisible = !nextElementInvisible; + continue; + } + if (tileElementType == RCT12TileElementType::EightCarsCorrupt14 + || tileElementType == RCT12TileElementType::EightCarsCorrupt15) + { + restOfTileInvisible = true; + continue; + } + + auto& dstElement = tileElements.emplace_back(); + ImportTileElement(&dstElement, srcElement, nextElementInvisible || restOfTileInvisible); + nextElementInvisible = false; + tileAdded = true; + } while (!(srcElement++)->IsLastForTile()); + } + } + + if (!tileAdded) + { + // Add a default surface element, we always need at least one element per tile auto& dstElement = tileElements.emplace_back(); dstElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE); dstElement.SetLastForTile(true); - continue; } - RCT12TileElement* srcElement = tilePointerIndex.GetFirstElementAt(coords); - // This might happen with damaged parks. Make sure there is *something* to avoid crashes. - if (srcElement == nullptr) - { - auto& dstElement = tileElements.emplace_back(); - dstElement.ClearAs(TILE_ELEMENT_TYPE_SURFACE); - dstElement.SetLastForTile(true); - continue; - } - - do - { - if (srcElement->base_height == RCT12_MAX_ELEMENT_HEIGHT) - { - continue; - } - - auto tileElementType = static_cast(srcElement->GetType()); - if (tileElementType == RCT12TileElementType::Corrupt) - { - // One property of corrupt elements was to hide tops of tower tracks, and to avoid the next element from - // being hidden, multiple consecutive corrupt elements were sometimes used. This would essentially - // toggle the flag, so we inverse nextElementInvisible here instead of always setting it to true. - nextElementInvisible = !nextElementInvisible; - continue; - } - if (tileElementType == RCT12TileElementType::EightCarsCorrupt14 - || tileElementType == RCT12TileElementType::EightCarsCorrupt15) - { - restOfTileInvisible = true; - continue; - } - - auto& dstElement = tileElements.emplace_back(); - ImportTileElement(&dstElement, srcElement, nextElementInvisible || restOfTileInvisible); - nextElementInvisible = false; - } while (!(srcElement++)->IsLastForTile()); - // Set last element flag in case the original last element was never added if (tileElements.size() > 0) {