From 5da7d0e4db84cd96f309d659884d5a069fbec216 Mon Sep 17 00:00:00 2001 From: Brendan Heinonen Date: Sun, 3 Nov 2024 20:05:03 -0500 Subject: [PATCH 1/4] Fix #22972: Missing flat footpath in scenarios Scenarios touched: - Alton Towers - Build your own Six Flags Magic Mountain - Mirage Madness - Six Flags Magic Mountain --- data/scenario_patches/2696a05.parkpatch | 17 +++- data/scenario_patches/5c95a4e.parkpatch | 9 +- data/scenario_patches/7f38f1b.parkpatch | 13 ++- data/scenario_patches/7ffdb44.parkpatch | 13 ++- data/scenario_patches/c1d4056.parkpatch | 13 ++- data/scenario_patches/c82272a.parkpatch | 13 ++- src/openrct2/rct12/ScenarioPatcher.cpp | 128 ++++++++++++++++++++++-- 7 files changed, 182 insertions(+), 24 deletions(-) diff --git a/data/scenario_patches/2696a05.parkpatch b/data/scenario_patches/2696a05.parkpatch index 391ddbd0f9..54c597985b 100644 --- a/data/scenario_patches/2696a05.parkpatch +++ b/data/scenario_patches/2696a05.parkpatch @@ -18,5 +18,20 @@ [ 140, 74 ], [ 141, 74 ], [ 142, 74 ], [ 143, 74 ], [ 144, 74 ], [ 145, 74 ], [ 146, 74 ], [ 147, 74 ] ] } - } + }, + "elements_to_delete": [ + { + "element_index": 1, + "coordinates": [ + [ 86, 75 ], [ 86, 77 ], [ 86, 78 ] + ] + } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.bamboo_brown", + "surface": "rct2.footpath_surface.dirt", + "coordinates": [ [ 86, 74, 12 ], [ 86, 75, 12 ], [ 86, 76, 12 ], [ 86, 77, 12 ], [ 86, 78, 12 ] ] + } + ] } diff --git a/data/scenario_patches/5c95a4e.parkpatch b/data/scenario_patches/5c95a4e.parkpatch index 6c30ef46bf..0f7e0a0e03 100644 --- a/data/scenario_patches/5c95a4e.parkpatch +++ b/data/scenario_patches/5c95a4e.parkpatch @@ -7,5 +7,12 @@ [ 11, 31 ], [ 68, 112 ], [ 72, 118 ] ] } - } + }, + "paths": [ + { + "railings": "rct2.footpath_railings.wood", + "surface": "rct1.footpath_surface.crazy_paving", + "coordinates": [ [ 83, 81, 22 ] ] + } + ] } diff --git a/data/scenario_patches/7f38f1b.parkpatch b/data/scenario_patches/7f38f1b.parkpatch index a282000c56..5ab76eb98e 100644 --- a/data/scenario_patches/7f38f1b.parkpatch +++ b/data/scenario_patches/7f38f1b.parkpatch @@ -4,11 +4,11 @@ "land_ownership": { "available": { "coordinates": [ - [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], - [ 75, 167 ], + [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], + [ 75, 167 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 92, 57 ], [ 93, 57 ], - [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], + [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 168, 20 ], [ 169, 20 ], [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] ] @@ -21,5 +21,12 @@ [ 103, 76 ], [ 104, 76 ] ] } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.bamboo_brown", + "surface": "rct2.footpath_surface.dirt", + "coordinates": [ [ 144, 100, 34 ] ] + } ] } diff --git a/data/scenario_patches/7ffdb44.parkpatch b/data/scenario_patches/7ffdb44.parkpatch index db6206427e..6fd885f4b6 100644 --- a/data/scenario_patches/7ffdb44.parkpatch +++ b/data/scenario_patches/7ffdb44.parkpatch @@ -4,11 +4,11 @@ "land_ownership": { "available": { "coordinates": [ - [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], - [ 75, 167 ], + [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], + [ 75, 167 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 92, 57 ], [ 93, 57 ], - [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], + [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 168, 20 ], [ 169, 20 ], [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] ] @@ -21,5 +21,12 @@ [ 103, 76 ], [ 104, 76 ] ] } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.bamboo_brown", + "surface": "rct2.footpath_surface.dirt", + "coordinates": [ [ 144, 100, 34 ] ] + } ] } diff --git a/data/scenario_patches/c1d4056.parkpatch b/data/scenario_patches/c1d4056.parkpatch index 7f291735a1..96934e447d 100644 --- a/data/scenario_patches/c1d4056.parkpatch +++ b/data/scenario_patches/c1d4056.parkpatch @@ -4,11 +4,11 @@ "land_ownership": { "available": { "coordinates": [ - [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], - [ 75, 167 ], + [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], + [ 75, 167 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 92, 57 ], [ 93, 57 ], - [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], + [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 168, 20 ], [ 169, 20 ], [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] ] @@ -21,5 +21,12 @@ [ 103, 76 ], [ 104, 76 ] ] } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.bamboo_brown", + "surface": "rct2.footpath_surface.dirt", + "coordinates": [ [ 144, 100, 34 ] ] + } ] } diff --git a/data/scenario_patches/c82272a.parkpatch b/data/scenario_patches/c82272a.parkpatch index a75e9e8fef..e220c663c5 100644 --- a/data/scenario_patches/c82272a.parkpatch +++ b/data/scenario_patches/c82272a.parkpatch @@ -4,11 +4,11 @@ "land_ownership": { "available": { "coordinates": [ - [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], - [ 75, 167 ], + [ 104, 190 ], [ 105, 190 ], [ 108, 197 ], + [ 75, 167 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 92, 57 ], [ 93, 57 ], - [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], + [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 168, 20 ], [ 169, 20 ], [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] ] @@ -21,5 +21,12 @@ [ 103, 76 ], [ 104, 76 ] ] } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.bamboo_brown", + "surface": "rct2.footpath_surface.dirt", + "coordinates": [ [ 144, 100, 34 ] ] + } ] } diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index 359d6eba8b..16dfb057d1 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -27,6 +27,7 @@ #include "../world/Location.hpp" #include "../world/Map.h" #include "../world/tile_element/EntranceElement.h" +#include "../world/tile_element/PathElement.h" #include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TileElement.h" #include "../world/tile_element/TileElementType.h" @@ -74,6 +75,11 @@ static const std::string _ridesKey = "rides"; static const std::string _rideIdKey = "id"; static const std::string _operationKey = "operation"; +// Path fix keys +static const std::string _pathsKey = "paths"; +static const std::string _railingsKey = "railings"; +static const std::string _surfaceKey = "surface"; + static u8string ToOwnershipJsonKey(int ownershipType) { switch (ownershipType) @@ -93,7 +99,33 @@ static u8string ToOwnershipJsonKey(int ownershipType) return {}; } -static std::vector getCoordinates(const json_t& parameters) +static void readCoordinate(std::vector& out, const json_t& coordinatesArray) +{ + if (coordinatesArray.size() != 2) + { + OpenRCT2::Guard::Assert(0, "Fix coordinates sub array should have 2 elements"); + return; + } + + out.emplace_back( + OpenRCT2::Json::GetNumber(coordinatesArray[0]), OpenRCT2::Json::GetNumber(coordinatesArray[1])); +} + +static void readCoordinate(std::vector& out, const json_t& coordinatesArray) +{ + if (coordinatesArray.size() != 3) + { + OpenRCT2::Guard::Assert(0, "Fix coordinates sub array should have 3 elements"); + return; + } + + out.emplace_back( + OpenRCT2::Json::GetNumber(coordinatesArray[0]), OpenRCT2::Json::GetNumber(coordinatesArray[1]), + OpenRCT2::Json::GetNumber(coordinatesArray[2])); +} + +template +static std::vector getCoordinates(const json_t& parameters) { if (!parameters.contains(_coordinatesKey)) { @@ -113,7 +145,7 @@ static std::vector getCoordinates(const json_t& parameters) return {}; } - std::vector parsedCoordinates; + std::vector parsedCoordinates; parsedCoordinates.reserve(coords.size()); for (size_t i = 0; i < coords.size(); ++i) { @@ -123,14 +155,8 @@ static std::vector getCoordinates(const json_t& parameters) return {}; } - auto coordinatesPair = OpenRCT2::Json::AsArray(coords[i]); - if (coordinatesPair.size() != 2) - { - OpenRCT2::Guard::Assert(0, "Fix coordinates sub array should have 2 elements"); - return {}; - } - parsedCoordinates.emplace_back( - OpenRCT2::Json::GetNumber(coordinatesPair[0]), OpenRCT2::Json::GetNumber(coordinatesPair[1])); + auto coordinatesArray = OpenRCT2::Json::AsArray(coords[i]); + readCoordinate(parsedCoordinates, coordinatesArray); } return parsedCoordinates; } @@ -517,6 +543,87 @@ static void ApplyRideFixes(const json_t& scenarioPatch) } } +static void ApplyPathFixes(const json_t& scenarioPatch) +{ + if (!scenarioPatch.contains(_pathsKey)) + { + return; + } + + if (!scenarioPatch[_pathsKey].is_array()) + { + OpenRCT2::Guard::Assert(0, "Path fixes should be an array of arrays"); + return; + } + + auto pathFixes = OpenRCT2::Json::AsArray(scenarioPatch[_pathsKey]); + if (pathFixes.empty()) + { + OpenRCT2::Guard::Assert(0, "Path fixes should not be an empty array"); + return; + } + + for (size_t i = 0; i < pathFixes.size(); ++i) + { + auto pathFix = pathFixes[i]; + + if (!pathFix.contains(_railingsKey)) + { + OpenRCT2::Guard::Assert(0, "Path fixes should have railings"); + return; + } + + if (!pathFix.contains(_surfaceKey)) + { + OpenRCT2::Guard::Assert(0, "Path fixes should have a surface"); + return; + } + + auto railings = OpenRCT2::Json::GetString(pathFix[_railingsKey]); + auto surface = OpenRCT2::Json::GetString(pathFix[_surfaceKey]); + + if (_dryRun) + { + continue; + } + + auto& objectManager = OpenRCT2::GetContext()->GetObjectManager(); + auto railingsObjIndex = objectManager.GetLoadedObjectEntryIndex(railings); + auto surfaceObjIndex = objectManager.GetLoadedObjectEntryIndex(surface); + + if (railingsObjIndex == OBJECT_ENTRY_INDEX_NULL) + { + OpenRCT2::Guard::Assert(0, "Railings object not found"); + return; + } + + if (surfaceObjIndex == OBJECT_ENTRY_INDEX_NULL) + { + OpenRCT2::Guard::Assert(0, "Surface object not found"); + return; + } + + auto coordinates = getCoordinates(pathFix); + + for (auto coordinate : coordinates) + { + auto* pathElement = TileElementInsert(coordinate.ToCoordsXYZ(), 0b1111); + OpenRCT2::Guard::Assert(pathElement != nullptr); + + pathElement->SetSurfaceEntryIndex(surfaceObjIndex); + pathElement->SetRailingsEntryIndex(railingsObjIndex); + + FootpathQueueChainReset(); + FootpathConnectEdges( + coordinate.ToCoordsXY(), pathElement->as(), + GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); + FootpathUpdateQueueChains(); + + MapInvalidateTileFull(coordinate.ToCoordsXY()); + } + } +} + static u8string getScenarioSHA256(u8string_view scenarioPath) { auto env = OpenRCT2::GetContext()->GetPlatformEnvironment(); @@ -581,6 +688,7 @@ void OpenRCT2::RCT12::ApplyScenarioPatch(u8string_view scenarioPatchFile, u8stri ApplySurfaceFixes(scenarioPatch); RemoveTileElements(scenarioPatch); ApplyRideFixes(scenarioPatch); + ApplyPathFixes(scenarioPatch); } void OpenRCT2::RCT12::FetchAndApplyScenarioPatch(u8string_view scenarioPath) From 7d958e63dfe32ba6a8a7ace7004223f2a5c7de22 Mon Sep 17 00:00:00 2001 From: Brendan Heinonen Date: Mon, 4 Nov 2024 17:46:52 -0500 Subject: [PATCH 2/4] Part of #20070: missing sloped footpath in scenarios Scenarios amended: - Alton Towers - Rollercoaster Heaven --- data/scenario_patches/0b8cc95.parkpatch | 31 +++++++++++++++++++++++++ data/scenario_patches/5c95a4e.parkpatch | 6 +++++ data/scenario_patches/eabcb3d.parkpatch | 31 +++++++++++++++++++++++++ data/scenario_patches/scenario_to_hash | 6 ++++- src/openrct2/rct12/ScenarioPatcher.cpp | 30 ++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 data/scenario_patches/0b8cc95.parkpatch create mode 100644 data/scenario_patches/eabcb3d.parkpatch diff --git a/data/scenario_patches/0b8cc95.parkpatch b/data/scenario_patches/0b8cc95.parkpatch new file mode 100644 index 0000000000..bfbf52c33e --- /dev/null +++ b/data/scenario_patches/0b8cc95.parkpatch @@ -0,0 +1,31 @@ +{ + "scenario_name": "Rollercoaster Heaven", + "sha256": "0b8cc952c399e1515546a4ababe5ba2f7aace83915a7e51c56ee901568c9ef56", + "elements_to_delete": [ + { + "element_index": 0, + "coordinates": [ + [ 23, 79 ], [ 24, 79 ] + ] + }, + { + "element_index": 1, + "coordinates": [ + [ 87, 13 ] + ] + } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.crazy_paving", + "coordinates": [ [ 24, 79, 14 ], [ 87, 13, 18 ] ] + }, + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.crazy_paving", + "coordinates": [ [ 23, 79, 12 ] ], + "slope_direction": 2 + } + ] +} diff --git a/data/scenario_patches/5c95a4e.parkpatch b/data/scenario_patches/5c95a4e.parkpatch index 0f7e0a0e03..67b6961874 100644 --- a/data/scenario_patches/5c95a4e.parkpatch +++ b/data/scenario_patches/5c95a4e.parkpatch @@ -13,6 +13,12 @@ "railings": "rct2.footpath_railings.wood", "surface": "rct1.footpath_surface.crazy_paving", "coordinates": [ [ 83, 81, 22 ] ] + }, + { + "railings": "rct2.footpath_railings.wood", + "surface": "rct1.footpath_surface.crazy_paving", + "coordinates": [ [ 85, 77, 22 ] ], + "slope_direction": 2 } ] } diff --git a/data/scenario_patches/eabcb3d.parkpatch b/data/scenario_patches/eabcb3d.parkpatch new file mode 100644 index 0000000000..e266f8fc1b --- /dev/null +++ b/data/scenario_patches/eabcb3d.parkpatch @@ -0,0 +1,31 @@ +{ + "scenario_name": "Rollercoaster Heaven (.sea)", + "sha256": "eabcb3d924e8e3438bfd90f6758a723c89df4136a817533d34985598d58ba38f", + "elements_to_delete": [ + { + "element_index": 0, + "coordinates": [ + [ 23, 79 ], [ 24, 79 ] + ] + }, + { + "element_index": 1, + "coordinates": [ + [ 87, 13 ] + ] + } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.crazy_paving", + "coordinates": [ [ 24, 79, 14 ], [ 87, 13, 18 ] ] + }, + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.crazy_paving", + "coordinates": [ [ 23, 79, 12 ] ], + "slope_direction": 2 + } + ] +} diff --git a/data/scenario_patches/scenario_to_hash b/data/scenario_patches/scenario_to_hash index 6d352dc211..7d2b9985fb 100644 --- a/data/scenario_patches/scenario_to_hash +++ b/data/scenario_patches/scenario_to_hash @@ -51,6 +51,8 @@ '33bac63d13aa7513ac8536d865cbc6fa4a2189c79e3943869e6380072e71bce7'], 'Rock ‘n’ Roll Revival': ['d48bbfe', 'd48bbfe4833347dfbf5befe63eb3795df3bce36cdc9152048ee7851e36d45ad9'], + 'Rollercoaster Heaven': ['0b8cc95', + '0b8cc952c399e1515546a4ababe5ba2f7aace83915a7e51c56ee901568c9ef56'], 'Schneider Shores': ['e57112f', 'e57112f58a7710d3e80242e867fb65d720e0cd3b67bebfd6b7df8b404fc7ea2b'], 'Sherwood Forest': ['825134a', @@ -207,6 +209,8 @@ 'b43b07e47f2e6cb762a86760ac0242595617aa59bfd9811cec7e2dcc121ae367'], 'Rock ‘n’ Roll Revival': ['f71c978', 'f71c9788ab40ac591d5c96397fad8b12d9d3ac7830eac53f6ee5dc024c8c2bcf'], + 'Rollercoaster Heaven': ['eabcb3d', + 'eabcb3d924e8e3438bfd90f6758a723c89df4136a817533d34985598d58ba38f'], 'Schneider Shores': ['0d53bdc', '0d53bdc076d75d86b31b6b3e6948e3d45671cf5aeff6b2b3c07a7618923223f5'], 'Sherwood Forest': ['a04b536', @@ -220,4 +224,4 @@ 'Six Flags over Texas': ['6226822', '62268223a1539c92b7494973263457c9e9bf386c1e68eef21d377854f0ac0e38'], 'Wacky Waikiki': ['72cf3d2', - '72cf3d220740fd64f7681d3533320598cf6d3b71dff484bc43045e8d9d7a1a4b'], \ No newline at end of file + '72cf3d220740fd64f7681d3533320598cf6d3b71dff484bc43045e8d9d7a1a4b'], diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index 16dfb057d1..11e23c0ff6 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -79,6 +79,7 @@ static const std::string _operationKey = "operation"; static const std::string _pathsKey = "paths"; static const std::string _railingsKey = "railings"; static const std::string _surfaceKey = "surface"; +static const std::string _directionKey = "slope_direction"; static u8string ToOwnershipJsonKey(int ownershipType) { @@ -161,6 +162,29 @@ static std::vector getCoordinates(const json_t& parameters) return parsedCoordinates; } +static Direction GetDirection(const json_t& parameters) +{ + if (!parameters.contains(_directionKey)) + { + return INVALID_DIRECTION; + } + else if (!parameters[_directionKey].is_number()) + { + OpenRCT2::Guard::Assert(0, "Fix direction must be a number"); + return INVALID_DIRECTION; + } + + Direction direction = OpenRCT2::Json::GetNumber(parameters[_directionKey]); + + if (direction > 3) + { + OpenRCT2::Guard::Assert(0, "Direction must be between 0 and 3"); + return INVALID_DIRECTION; + } + + return direction; +} + static void ApplyLandOwnershipFixes(const json_t& landOwnershipFixes, int ownershipType) { auto ownershipTypeKey = ToOwnershipJsonKey(ownershipType); @@ -604,6 +628,7 @@ static void ApplyPathFixes(const json_t& scenarioPatch) } auto coordinates = getCoordinates(pathFix); + Direction direction = GetDirection(pathFix); for (auto coordinate : coordinates) { @@ -612,6 +637,11 @@ static void ApplyPathFixes(const json_t& scenarioPatch) pathElement->SetSurfaceEntryIndex(surfaceObjIndex); pathElement->SetRailingsEntryIndex(railingsObjIndex); + if (direction != INVALID_DIRECTION) + { + pathElement->SetSloped(true); + pathElement->SetSlopeDirection(direction); + } FootpathQueueChainReset(); FootpathConnectEdges( From 47c8970d712623e731a7b8b506112bab638d5d7e Mon Sep 17 00:00:00 2001 From: Tulio Leao Date: Wed, 13 Nov 2024 08:03:31 -0300 Subject: [PATCH 3/4] Part of #20070: Allow fixing paths with queues Fixes Mines of Africa --- data/scenario_patches/2980c28.parkpatch | 21 ++++++++++++ data/scenario_patches/4a762ae.parkpatch | 40 ++++++++++++++++++++++ data/scenario_patches/b080197.parkpatch | 21 ++++++++++++ data/scenario_patches/b20bd80.parkpatch | 40 ++++++++++++++++++++++ data/scenario_patches/scenario_to_hash | 10 +++++- src/openrct2/rct12/ScenarioPatcher.cpp | 44 ++++++++++++++++--------- 6 files changed, 159 insertions(+), 17 deletions(-) create mode 100644 data/scenario_patches/2980c28.parkpatch create mode 100644 data/scenario_patches/4a762ae.parkpatch create mode 100644 data/scenario_patches/b080197.parkpatch create mode 100644 data/scenario_patches/b20bd80.parkpatch diff --git a/data/scenario_patches/2980c28.parkpatch b/data/scenario_patches/2980c28.parkpatch new file mode 100644 index 0000000000..e16ab06d8f --- /dev/null +++ b/data/scenario_patches/2980c28.parkpatch @@ -0,0 +1,21 @@ +{ + "scenario_name": "Mines of Africa", + "sha256": "2980c287d81e4e96a46db30d1a80e6bfa0caace6a14488dddc6f20ac71676cff", + "elements_to_delete": [ + { + "element_index": 1, + "coordinates": [ + [ 43, 46 ] + ] + } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.queue_yellow", + "coordinates": [ [ 43, 46, 6 ] ], + "slope_direction": 3, + "queue": true + } + ] +} diff --git a/data/scenario_patches/4a762ae.parkpatch b/data/scenario_patches/4a762ae.parkpatch new file mode 100644 index 0000000000..01986fc1c2 --- /dev/null +++ b/data/scenario_patches/4a762ae.parkpatch @@ -0,0 +1,40 @@ +{ + "scenario_name": "Iceberg Islands", + "sha256": "4a762ae89bf279dbcaead9e457c21014a9e39eb4a46cf1cbf63304450f9ed050", + "elements_to_delete": [ + { + "element_index": 2, + "coordinates": [ + [ 49, 43 ], [ 50, 43 ], [ 51, 43 ], [ 44, 55 ] + ] + }, + { + "element_index": 1, + "coordinates": [ + [ 44, 54 ], [ 44, 53 ] + ] + } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct1.footpath_surface.queue_blue", + "coordinates": [ [ 51, 43, 24 ], [ 44, 55, 20 ] ], + "queue": true + }, + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct1.footpath_surface.queue_blue", + "coordinates": [ [ 50, 43, 24 ], [ 49, 43, 26 ] ], + "slope_direction": 0, + "queue": true + }, + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct1.footpath_surface.queue_blue", + "coordinates": [ [ 44, 54, 18 ], [ 44, 53, 16 ] ], + "slope_direction": 1, + "queue": true + } + ] +} diff --git a/data/scenario_patches/b080197.parkpatch b/data/scenario_patches/b080197.parkpatch new file mode 100644 index 0000000000..642e69bf10 --- /dev/null +++ b/data/scenario_patches/b080197.parkpatch @@ -0,0 +1,21 @@ +{ + "scenario_name": "Mines of Africa (.sea)", + "sha256": "b080197d430a6ded46945035a95c8f2d9e3064637e9119e68270554eda48e747", + "elements_to_delete": [ + { + "element_index": 1, + "coordinates": [ + [ 43, 46 ] + ] + } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.queue_yellow", + "coordinates": [ [ 43, 46, 6 ] ], + "slope_direction": 3, + "queue": true + } + ] +} diff --git a/data/scenario_patches/b20bd80.parkpatch b/data/scenario_patches/b20bd80.parkpatch new file mode 100644 index 0000000000..973c8e350e --- /dev/null +++ b/data/scenario_patches/b20bd80.parkpatch @@ -0,0 +1,40 @@ +{ + "scenario_name": "Iceberg Islands (.sea)", + "sha256": "b20bd803c0a99c8748b48688501ba6ef8a5ce5d746540a486617e0564aa407d5", + "elements_to_delete": [ + { + "element_index": 2, + "coordinates": [ + [ 49, 43 ], [ 50, 43 ], [ 51, 43 ], [ 44, 55 ] + ] + }, + { + "element_index": 1, + "coordinates": [ + [ 44, 54 ], [ 44, 53 ] + ] + } + ], + "paths": [ + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.queue_yellow", + "coordinates": [ [ 51, 43, 24 ], [ 44, 55, 20 ] ], + "queue": true + }, + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.queue_yellow", + "coordinates": [ [ 50, 43, 24 ], [ 49, 43, 26 ] ], + "slope_direction": 0, + "queue": true + }, + { + "railings": "rct2.footpath_railings.concrete", + "surface": "rct2.footpath_surface.queue_yellow", + "coordinates": [ [ 44, 54, 18 ], [ 44, 53, 16 ] ], + "slope_direction": 1, + "queue": true + } + ] +} diff --git a/data/scenario_patches/scenario_to_hash b/data/scenario_patches/scenario_to_hash index 7d2b9985fb..3ffa3ec789 100644 --- a/data/scenario_patches/scenario_to_hash +++ b/data/scenario_patches/scenario_to_hash @@ -39,6 +39,8 @@ 'fcc15f9c9b42bdd4aa8761c3a6df17c1293aa616780bc4aadd348d191e275112'], 'Lost City Founder': ['13e81f2', '13e81f23ab1a7051b5465e4a7bb214b4188f2264d499f8f7e106372c3a984331'], + 'Mines of Africa': ['2980c28', + '2980c287d81e4e96a46db30d1a80e6bfa0caace6a14488dddc6f20ac71676cff'], 'Mirage Madness': ['2696a05', '2696a059c2c1b23c60cbfcc293fd29cfec45d7e3da7f3b38bc2b52aff834fd34'], 'Mythological Madness': ['ef0c020', @@ -89,6 +91,8 @@ '102a1c52853e77b6efd448a44572a862fa440615b4ea9ae5d7fb31c48c96aac9'], 'Hydro Hills': ['bfbd61f', 'bfbd61f6d22cdc5f2e017935f4e9e5969dece159218a08c695bfd727382cc717'], + 'Iceberg Islands': ['4a762ae', + '4a762ae89bf279dbcaead9e457c21014a9e39eb4a46cf1cbf63304450f9ed050'], 'katie\'s dreamland': ['73d0921', '73d0921f1d49388ffb4deb300c6ebb3920564410c2239580a7d1145fa54c2d4a'], 'Leafy Lake': ['83bd798', @@ -132,7 +136,9 @@ 'Haunted Harbour': ['b2cebe1', 'b2cebe149b2330e071a028d079f6632af144fb44e076a5eca89780eb4007e136'], 'hydro hills': ['ce24961', - 'ce249614e735c560c5019318bc6fa8603ba6630576f7fb038def0bdac3e143ef'] + 'ce249614e735c560c5019318bc6fa8603ba6630576f7fb038def0bdac3e143ef'], + 'Iceberg Islands': ['b20bd80', + 'b20bd803c0a99c8748b48688501ba6ef8a5ce5d746540a486617e0564aa407d5'], 'katie\'s dreamland': ['b8b572d', 'b8b572d394b145535cdb20f66b0bee9a497683a5885e4d78af6773c5bc0323ff'], 'mel\'s world': ['bfaf504', @@ -197,6 +203,8 @@ 'adffe2ff1e06ebeb821bbf01263125dc40311a8350722c62908be8d1c8852259'], 'Lost City Founder': ['70ce3e1', '70ce3e11f1dd59929a6d82d0f6f88897c95b94d1f9d4efd6ef3a0c6c449f966f'], + 'Mines of Africa': ['b080197', + 'b080197d430a6ded46945035a95c8f2d9e3064637e9119e68270554eda48e747'], 'Mirage Madness': ['82aeaf6', '82aeaf6bd628bf26dabd1ca87455b667f3081598bcf4d4c7751e2bdfbd266ac2'], 'Mythological Madness': ['6633d17', diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index 11e23c0ff6..bb334a3072 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -12,6 +12,8 @@ #include "../Context.h" #include "../Game.h" #include "../PlatformEnvironment.h" +#include "../actions/FootpathPlaceAction.h" +#include "../actions/GameActionResult.h" #include "../core/File.h" #include "../core/Guard.hpp" #include "../core/Json.hpp" @@ -28,6 +30,7 @@ #include "../world/Map.h" #include "../world/tile_element/EntranceElement.h" #include "../world/tile_element/PathElement.h" +#include "../world/tile_element/Slope.h" #include "../world/tile_element/SurfaceElement.h" #include "../world/tile_element/TileElement.h" #include "../world/tile_element/TileElementType.h" @@ -80,6 +83,7 @@ static const std::string _pathsKey = "paths"; static const std::string _railingsKey = "railings"; static const std::string _surfaceKey = "surface"; static const std::string _directionKey = "slope_direction"; +static const std::string _isQueue = "queue"; static u8string ToOwnershipJsonKey(int ownershipType) { @@ -185,6 +189,23 @@ static Direction GetDirection(const json_t& parameters) return direction; } +static bool IsQueue(const json_t& parameters) +{ + if (!parameters.contains(_isQueue)) + { + return false; + } + else if (!parameters[_isQueue].is_boolean()) + { + OpenRCT2::Guard::Assert(0, "queue must be a boolean"); + return false; + } + else + { + return OpenRCT2::Json::GetBoolean(parameters[_isQueue]); + } +} + static void ApplyLandOwnershipFixes(const json_t& landOwnershipFixes, int ownershipType) { auto ownershipTypeKey = ToOwnershipJsonKey(ownershipType); @@ -629,27 +650,18 @@ static void ApplyPathFixes(const json_t& scenarioPatch) auto coordinates = getCoordinates(pathFix); Direction direction = GetDirection(pathFix); + PathConstructFlags constructionFlags = IsQueue(pathFix) ? OpenRCT2::PathConstructFlag::IsQueue : 0; for (auto coordinate : coordinates) { - auto* pathElement = TileElementInsert(coordinate.ToCoordsXYZ(), 0b1111); - OpenRCT2::Guard::Assert(pathElement != nullptr); - - pathElement->SetSurfaceEntryIndex(surfaceObjIndex); - pathElement->SetRailingsEntryIndex(railingsObjIndex); - if (direction != INVALID_DIRECTION) + auto slope = direction != INVALID_DIRECTION ? direction + 4 : 0; + auto footpathPlaceAction = FootpathPlaceAction( + coordinate.ToCoordsXYZ(), slope, surfaceObjIndex, railingsObjIndex, direction, constructionFlags); + auto result = footpathPlaceAction.Execute(); + if (result.Error != OpenRCT2::GameActions::Status::Ok) { - pathElement->SetSloped(true); - pathElement->SetSlopeDirection(direction); + OpenRCT2::Guard::Assert(0, "Could not patch path"); } - - FootpathQueueChainReset(); - FootpathConnectEdges( - coordinate.ToCoordsXY(), pathElement->as(), - GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED); - FootpathUpdateQueueChains(); - - MapInvalidateTileFull(coordinate.ToCoordsXY()); } } } From 7e30d8e4f5a682eef4453b5d48f7590082925fed Mon Sep 17 00:00:00 2001 From: Tulio Leao Date: Tue, 12 Nov 2024 08:08:54 -0300 Subject: [PATCH 4/4] Add changelog and bump network version --- distribution/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 65caffd754..627598ac12 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -6,6 +6,7 @@ - Improved: [#23123] Improve sorting of roller coasters in build new ride menu. - Improved: [#23211] Add boosters to classic wooden roller coaster (cheats only). - Improved: [#23233] Add diagonal booster to LSM Launched Coaster. +- Fix: [#20070, #22972] Missing and mismatched flat and sloped footpaths on several scenarios. - Fix: [#22726] ‘Force park rating’ cheat is not saved with the park. - Fix: [#23064] Stand-Up Roller Coaster unbanked to banked track pieces are misaligned. - Fix: [#23066] Stand-Up Roller Coaster has many supports that don't join up to the track.