From 8ce8eec426d22936040fb58dcd853b78bfd4feb4 Mon Sep 17 00:00:00 2001 From: mix <167040362+mixiate@users.noreply.github.com> Date: Sat, 27 Dec 2025 13:29:49 +0000 Subject: [PATCH] Fix #11617: Zero clearance ghost track design paths break connections (#25685) --- distribution/changelog.txt | 1 + src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/world/Footpath.cpp | 56 ---------------------------- 3 files changed, 2 insertions(+), 57 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 85cfd80c9e..312398c5c0 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -13,6 +13,7 @@ - Change: [#25485] Make the enlarged pressed swatch sprite more pronounced. - Change: [#25544] The default game window size is now 1280×720px instead of 640×480px. - Fix: [#9895] Stand-up coaster gets wrong intensity boost from the synchronisation bonus. +- Fix: [#11617] Path corner connections are broken when hovering track design ghosts with paths over them in zero clearances. - Fix: [#22484] Lingering ghost entrance after placing park entrance. - Fix: [#24952] Duplicate track designs when running via Steam without having RCT1 linked. - Fix: [#25187] On-ride photo platform does not render as ghost when placing track design. diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index fea97e716c..7c0157908a 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -47,7 +47,7 @@ // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -constexpr uint8_t kStreamVersion = 5; +constexpr uint8_t kStreamVersion = 6; const std::string kStreamID = std::string(kOpenRCT2Version) + "-" + std::to_string(kStreamVersion); diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index e897bc6d3b..f6e65dd27c 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -1722,49 +1722,6 @@ bool TileElementWantsPathConnectionTowards(const TileCoordsXYZD& coords, const T return false; } -// fix up the corners around the given path element that gets removed -static void FootpathFixCornersAround(const TileCoordsXY& footpathPos, TileElement* pathElement) -{ - // A mask for the paths' corners of each possible neighbour - static constexpr uint8_t cornersTouchingTile[3][3] = { - { 0b0010, 0b0011, 0b0001 }, - { 0b0110, 0b0000, 0b1001 }, - { 0b0100, 0b1100, 0b1000 }, - }; - - // Sloped paths don't create filled corners, so no need to remove any - if (pathElement->GetType() == TileElementType::Path && pathElement->AsPath()->IsSloped()) - return; - - for (int32_t xOffset = -1; xOffset <= 1; xOffset++) - { - for (int32_t yOffset = -1; yOffset <= 1; yOffset++) - { - // Skip self - if (xOffset == 0 && yOffset == 0) - continue; - - TileElement* tileElement = MapGetFirstElementAt( - TileCoordsXY{ footpathPos.x + xOffset, footpathPos.y + yOffset }.ToCoordsXY()); - if (tileElement == nullptr) - continue; - do - { - if (tileElement->GetType() != TileElementType::Path) - continue; - if (tileElement->AsPath()->IsSloped()) - continue; - if (tileElement->BaseHeight != pathElement->BaseHeight) - continue; - - const int32_t ix = xOffset + 1; - const int32_t iy = yOffset + 1; - tileElement->AsPath()->SetCorners(tileElement->AsPath()->GetCorners() & ~(cornersTouchingTile[iy][ix])); - } while (!(tileElement++)->IsLastForTile()); - } - } -} - /** * * rct2: 0x006A6AA7 @@ -1786,7 +1743,6 @@ void FootpathRemoveEdgesAt(const CoordsXY& footpathPos, TileElement* tileElement FootpathUpdateQueueEntranceBanner(footpathPos, tileElement); - bool fixCorners = false; for (uint8_t direction = 0; direction < kNumOrthogonalDirections; direction++) { int32_t z1 = tileElement->BaseHeight; @@ -1814,18 +1770,6 @@ void FootpathRemoveEdgesAt(const CoordsXY& footpathPos, TileElement* tileElement FootpathRemoveEdgesTowards( { footpathPos + CoordsDirectionDelta[direction], z0 * kCoordsZStep, z1 * kCoordsZStep }, direction, isQueue); } - else - { - // A footpath may stay connected, but its edges must be fixed later on when another edge does get removed. - fixCorners = true; - } - } - - // Only fix corners when needed, to avoid changing corners that have been set for its looks. - if (fixCorners && tileElement->IsGhost()) - { - auto tileFootpathPos = TileCoordsXY{ footpathPos }; - FootpathFixCornersAround(tileFootpathPos, tileElement); } if (tileElement->GetType() == TileElementType::Path)