diff --git a/data/scenario_patches/2ca68df.parkpatch b/data/scenario_patches/2ca68df.parkpatch index ee2702be41..95ac8f1290 100644 --- a/data/scenario_patches/2ca68df.parkpatch +++ b/data/scenario_patches/2ca68df.parkpatch @@ -15,5 +15,25 @@ [ 46, 55 ], [ 46, 56 ], [ 46, 57 ] ] } + ], + "surfaces": [ + { + "to_surface": "rct2.terrain_surface.sand", + "coordinates": [ + [ 41, 47 ], [ 41, 48 ], [ 41, 49 ], [ 41, 50 ], [ 41, 51 ], [ 41, 52 ], [ 41, 53 ], + [ 41, 54 ], [ 41, 55 ], [ 41, 56 ], [ 41, 57 ], [ 41, 58 ], [ 41, 59 ], [ 41, 60 ], + [ 42, 48 ], [ 42, 49 ], [ 42, 50 ], [ 42, 51 ], [ 42, 52 ], [ 42, 53 ], [ 42, 54 ], + [ 42, 55 ], [ 42, 56 ], [ 42, 57 ], [ 42, 58 ], [ 42, 59 ], + [ 43, 48 ], [ 43, 49 ], [ 43, 50 ], [ 43, 51 ], [ 43, 52 ], [ 43, 53 ], [ 43, 54 ], + [ 43, 55 ], [ 43, 56 ], [ 43, 57 ], [ 43, 58 ], + [ 44, 49 ], [ 44, 50 ], [ 44, 51 ], [ 44, 52 ], [ 44, 53 ], [ 44, 54 ], [ 44, 55 ], + [ 44, 56 ], [ 44, 57 ], [ 44, 58 ], + [ 45, 49 ], [ 45, 50 ], [ 45, 51 ], [ 45, 52 ], [ 45, 53 ], [ 45, 54 ], [ 45, 55 ], + [ 45, 56 ], [ 45, 57 ], [ 45, 58 ], + [ 46, 51 ], [ 46, 52 ], [ 46, 53 ], [ 46, 54 ], [ 46, 55 ], [ 46, 56 ], [ 46, 57 ], + [ 46, 58 ], + [ 47, 54 ], [ 47, 55 ], [ 47, 56 ], [ 47, 57 ] + ] + } ] } diff --git a/data/scenario_patches/aead175.parkpatch b/data/scenario_patches/aead175.parkpatch index 2ddf061e99..9b2445a306 100644 --- a/data/scenario_patches/aead175.parkpatch +++ b/data/scenario_patches/aead175.parkpatch @@ -15,5 +15,25 @@ [ 46, 55 ], [ 46, 56 ], [ 46, 57 ] ] } + ], + "surfaces": [ + { + "to_surface": "rct2.terrain_surface.sand", + "coordinates": [ + [ 41, 47 ], [ 41, 48 ], [ 41, 49 ], [ 41, 50 ], [ 41, 51 ], [ 41, 52 ], [ 41, 53 ], + [ 41, 54 ], [ 41, 55 ], [ 41, 56 ], [ 41, 57 ], [ 41, 58 ], [ 41, 59 ], [ 41, 60 ], + [ 42, 48 ], [ 42, 49 ], [ 42, 50 ], [ 42, 51 ], [ 42, 52 ], [ 42, 53 ], [ 42, 54 ], + [ 42, 55 ], [ 42, 56 ], [ 42, 57 ], [ 42, 58 ], [ 42, 59 ], + [ 43, 48 ], [ 43, 49 ], [ 43, 50 ], [ 43, 51 ], [ 43, 52 ], [ 43, 53 ], [ 43, 54 ], + [ 43, 55 ], [ 43, 56 ], [ 43, 57 ], [ 43, 58 ], + [ 44, 49 ], [ 44, 50 ], [ 44, 51 ], [ 44, 52 ], [ 44, 53 ], [ 44, 54 ], [ 44, 55 ], + [ 44, 56 ], [ 44, 57 ], [ 44, 58 ], + [ 45, 49 ], [ 45, 50 ], [ 45, 51 ], [ 45, 52 ], [ 45, 53 ], [ 45, 54 ], [ 45, 55 ], + [ 45, 56 ], [ 45, 57 ], [ 45, 58 ], + [ 46, 51 ], [ 46, 52 ], [ 46, 53 ], [ 46, 54 ], [ 46, 55 ], [ 46, 56 ], [ 46, 57 ], + [ 46, 58 ], + [ 47, 54 ], [ 47, 55 ], [ 47, 56 ], [ 47, 57 ] + ] + } ] } diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 42d497dfee..e0946159d5 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -6,6 +6,7 @@ - Fix: [#21959] “Save this before...?” message does not appear when selecting “New Game”. - Fix: [#22231] Invalid object version can cause a crash. - Fix: [#22653] Add several .parkpatch files for missing water tiles in RCT1 and RCT2 scenarios. +- Fix: [#22655] Fix surface style of Botany Breakers around missing water tiles. 0.4.14 (2024-09-01) ------------------------------------------------------------------------ diff --git a/src/openrct2/rct12/ScenarioPatcher.cpp b/src/openrct2/rct12/ScenarioPatcher.cpp index 8206f53838..820587bf5c 100644 --- a/src/openrct2/rct12/ScenarioPatcher.cpp +++ b/src/openrct2/rct12/ScenarioPatcher.cpp @@ -19,6 +19,7 @@ #include "../entity/EntityList.h" #include "../entity/Guest.h" #include "../entity/Peep.h" +#include "../object/ObjectManager.h" #include "../ride/Ride.h" #include "../ride/Track.h" #include "../world/Footpath.h" @@ -56,6 +57,10 @@ static const std::string s_toKey = "to"; static const std::string s_tilesKey = "tiles"; static const std::string s_typeKey = "type"; +// Surface fix keys +static const std::string s_surfacesKey = "surfaces"; +static const std::string s_destinationSurface = "to_surface"; + // Ride fix keys static const std::string s_ridesKey = "rides"; static const std::string s_rideIdKey = "id"; @@ -307,6 +312,57 @@ static void ApplyTileFixes(const json_t& scenarioPatch) } } +static void ApplySurfaceFixes(const json_t& scenarioPatch) +{ + if (!scenarioPatch.contains(s_surfacesKey)) + { + return; + } + + if (!scenarioPatch[s_surfacesKey].is_array()) + { + OpenRCT2::Guard::Assert(0, "Surface fix should be an array"); + return; + } + + auto surfaceFixes = OpenRCT2::Json::AsArray(scenarioPatch[s_surfacesKey]); + if (surfaceFixes.empty()) + { + OpenRCT2::Guard::Assert(0, "Surface fix array should not be empty"); + return; + } + + for (size_t i = 0; i < surfaceFixes.size(); ++i) + { + if (!surfaceFixes[i].contains(s_destinationSurface)) + { + OpenRCT2::Guard::Assert(0, "Surface fix sub-array should set a destination surface"); + return; + } + if (s_dryRun) + { + continue; + } + + auto destinationSurface = OpenRCT2::Json::GetString(surfaceFixes[i][s_destinationSurface]); + auto& objectManager = OpenRCT2::GetContext()->GetObjectManager(); + auto surfaceObj = objectManager.GetLoadedObject(ObjectEntryDescriptor::Parse(destinationSurface)); + if (surfaceObj == nullptr) + { + OpenRCT2::Guard::Assert(0, "Surface object not found"); + return; + } + + auto surfaceObjIndex = objectManager.GetLoadedObjectEntryIndex(surfaceObj); + auto coordinatesVector = getCoordinates(surfaceFixes[i]); + for (const auto& tile : coordinatesVector) + { + auto surfaceElement = MapGetSurfaceElementAt(tile); + surfaceElement->SetSurfaceObjectIndex(surfaceObjIndex); + } + } +} + static void SwapRideEntranceAndExit(RideId rideId) { auto ride = GetRide(rideId); @@ -464,6 +520,7 @@ void OpenRCT2::RCT12::ApplyScenarioPatch(u8string_view scenarioPatchFile, u8stri ApplyLandOwnershipFixes(scenarioPatch); ApplyWaterFixes(scenarioPatch); ApplyTileFixes(scenarioPatch); + ApplySurfaceFixes(scenarioPatch); ApplyRideFixes(scenarioPatch); }