1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-04 13:42:55 +01:00

Fix #22972: Missing flat footpath in scenarios

Scenarios touched:
- Alton Towers
- Build your own Six Flags Magic Mountain
- Mirage Madness
- Six Flags Magic Mountain
This commit is contained in:
Brendan Heinonen
2024-11-03 20:05:03 -05:00
committed by Tulio Leao
parent 979bdcd4ca
commit 5da7d0e4db
7 changed files with 182 additions and 24 deletions

View File

@@ -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 ] ]
}
]
}

View File

@@ -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 ] ]
}
]
}

View File

@@ -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 ] ]
}
]
}

View File

@@ -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 ] ]
}
]
}

View File

@@ -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 ] ]
}
]
}

View File

@@ -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 ] ]
}
]
}

View File

@@ -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<TileCoordsXY> getCoordinates(const json_t& parameters)
static void readCoordinate(std::vector<TileCoordsXY>& 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<int32_t>(coordinatesArray[0]), OpenRCT2::Json::GetNumber<int32_t>(coordinatesArray[1]));
}
static void readCoordinate(std::vector<TileCoordsXYZ>& 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<int32_t>(coordinatesArray[0]), OpenRCT2::Json::GetNumber<int32_t>(coordinatesArray[1]),
OpenRCT2::Json::GetNumber<int32_t>(coordinatesArray[2]));
}
template<typename TTileCoords = TileCoordsXY>
static std::vector<TTileCoords> getCoordinates(const json_t& parameters)
{
if (!parameters.contains(_coordinatesKey))
{
@@ -113,7 +145,7 @@ static std::vector<TileCoordsXY> getCoordinates(const json_t& parameters)
return {};
}
std::vector<TileCoordsXY> parsedCoordinates;
std::vector<TTileCoords> parsedCoordinates;
parsedCoordinates.reserve(coords.size());
for (size_t i = 0; i < coords.size(); ++i)
{
@@ -123,14 +155,8 @@ static std::vector<TileCoordsXY> 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<int32_t>(coordinatesPair[0]), OpenRCT2::Json::GetNumber<int32_t>(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<TileCoordsXYZ>(pathFix);
for (auto coordinate : coordinates)
{
auto* pathElement = TileElementInsert<PathElement>(coordinate.ToCoordsXYZ(), 0b1111);
OpenRCT2::Guard::Assert(pathElement != nullptr);
pathElement->SetSurfaceEntryIndex(surfaceObjIndex);
pathElement->SetRailingsEntryIndex(railingsObjIndex);
FootpathQueueChainReset();
FootpathConnectEdges(
coordinate.ToCoordsXY(), pathElement->as<TileElement>(),
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)