Patch missing footpath in scenarios (#23128)

* Fix #22972: Missing flat footpath in scenarios

Scenarios touched:
- Alton Towers
- Build your own Six Flags Magic Mountain
- Mirage Madness
- Six Flags Magic Mountain

* Part of #20070: missing sloped footpath in scenarios

Scenarios amended:
- Alton Towers
- Rollercoaster Heaven

* Part of #20070: Allow fixing paths with queues

Fixes Mines of Africa

* Add changelog and bump network version

---------

Co-authored-by: Tulio Leao <tupaschoal@gmail.com>
This commit is contained in:
Michał Janiszewski 2024-12-05 18:57:27 +01:00 committed by GitHub
commit 96f6b76e7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 429 additions and 26 deletions

View file

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

View file

@ -18,5 +18,20 @@
[ 140, 74 ], [ 141, 74 ], [ 142, 74 ], [ 143, 74 ], [ 144, 74 ], [ 145, 74 ], [ 146, 74 ], [ 147, 74 ] [ 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

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

View file

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

View file

@ -7,5 +7,18 @@
[ 11, 31 ], [ 68, 112 ], [ 72, 118 ] [ 11, 31 ], [ 68, 112 ], [ 72, 118 ]
] ]
} }
} },
"paths": [
{
"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
}
]
} }

View file

@ -4,11 +4,11 @@
"land_ownership": { "land_ownership": {
"available": { "available": {
"coordinates": [ "coordinates": [
[ 104, 190 ], [ 105, 190 ], [ 108, 197 ], [ 104, 190 ], [ 105, 190 ], [ 108, 197 ],
[ 75, 167 ], [ 75, 167 ],
[ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ],
[ 92, 57 ], [ 93, 57 ], [ 92, 57 ], [ 93, 57 ],
[ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ],
[ 168, 20 ], [ 169, 20 ], [ 168, 20 ], [ 169, 20 ],
[ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ]
] ]
@ -21,5 +21,12 @@
[ 103, 76 ], [ 104, 76 ] [ 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": { "land_ownership": {
"available": { "available": {
"coordinates": [ "coordinates": [
[ 104, 190 ], [ 105, 190 ], [ 108, 197 ], [ 104, 190 ], [ 105, 190 ], [ 108, 197 ],
[ 75, 167 ], [ 75, 167 ],
[ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ],
[ 92, 57 ], [ 93, 57 ], [ 92, 57 ], [ 93, 57 ],
[ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ],
[ 168, 20 ], [ 169, 20 ], [ 168, 20 ], [ 169, 20 ],
[ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ]
] ]
@ -21,5 +21,12 @@
[ 103, 76 ], [ 104, 76 ] [ 103, 76 ], [ 104, 76 ]
] ]
} }
],
"paths": [
{
"railings": "rct2.footpath_railings.bamboo_brown",
"surface": "rct2.footpath_surface.dirt",
"coordinates": [ [ 144, 100, 34 ] ]
}
] ]
} }

View file

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

View file

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

View file

@ -4,11 +4,11 @@
"land_ownership": { "land_ownership": {
"available": { "available": {
"coordinates": [ "coordinates": [
[ 104, 190 ], [ 105, 190 ], [ 108, 197 ], [ 104, 190 ], [ 105, 190 ], [ 108, 197 ],
[ 75, 167 ], [ 75, 167 ],
[ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ],
[ 92, 57 ], [ 93, 57 ], [ 92, 57 ], [ 93, 57 ],
[ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ],
[ 168, 20 ], [ 169, 20 ], [ 168, 20 ], [ 169, 20 ],
[ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ]
] ]
@ -21,5 +21,12 @@
[ 103, 76 ], [ 104, 76 ] [ 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": { "land_ownership": {
"available": { "available": {
"coordinates": [ "coordinates": [
[ 104, 190 ], [ 105, 190 ], [ 108, 197 ], [ 104, 190 ], [ 105, 190 ], [ 108, 197 ],
[ 75, 167 ], [ 75, 167 ],
[ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ], [ 61, 92 ], [ 61, 93 ], [ 61, 94 ], [ 61, 95 ], [ 62, 90 ], [ 62, 91 ], [ 62, 92 ], [ 62, 93 ], [ 62, 94 ],
[ 92, 57 ], [ 93, 57 ], [ 92, 57 ], [ 93, 57 ],
[ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ], [ 89, 40 ], [ 89, 41 ], [ 89, 42 ], [ 88, 42 ],
[ 168, 20 ], [ 169, 20 ], [ 168, 20 ], [ 169, 20 ],
[ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ] [ 46, 51 ], [ 58, 159 ], [ 71, 201 ], [ 126, 15 ], [ 190, 6 ]
] ]
@ -21,5 +21,12 @@
[ 103, 76 ], [ 104, 76 ] [ 103, 76 ], [ 104, 76 ]
] ]
} }
],
"paths": [
{
"railings": "rct2.footpath_railings.bamboo_brown",
"surface": "rct2.footpath_surface.dirt",
"coordinates": [ [ 144, 100, 34 ] ]
}
] ]
} }

View file

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

View file

@ -39,6 +39,8 @@
'fcc15f9c9b42bdd4aa8761c3a6df17c1293aa616780bc4aadd348d191e275112'], 'fcc15f9c9b42bdd4aa8761c3a6df17c1293aa616780bc4aadd348d191e275112'],
'Lost City Founder': ['13e81f2', 'Lost City Founder': ['13e81f2',
'13e81f23ab1a7051b5465e4a7bb214b4188f2264d499f8f7e106372c3a984331'], '13e81f23ab1a7051b5465e4a7bb214b4188f2264d499f8f7e106372c3a984331'],
'Mines of Africa': ['2980c28',
'2980c287d81e4e96a46db30d1a80e6bfa0caace6a14488dddc6f20ac71676cff'],
'Mirage Madness': ['2696a05', 'Mirage Madness': ['2696a05',
'2696a059c2c1b23c60cbfcc293fd29cfec45d7e3da7f3b38bc2b52aff834fd34'], '2696a059c2c1b23c60cbfcc293fd29cfec45d7e3da7f3b38bc2b52aff834fd34'],
'Mythological Madness': ['ef0c020', 'Mythological Madness': ['ef0c020',
@ -51,6 +53,8 @@
'33bac63d13aa7513ac8536d865cbc6fa4a2189c79e3943869e6380072e71bce7'], '33bac63d13aa7513ac8536d865cbc6fa4a2189c79e3943869e6380072e71bce7'],
'Rock n Roll Revival': ['d48bbfe', 'Rock n Roll Revival': ['d48bbfe',
'd48bbfe4833347dfbf5befe63eb3795df3bce36cdc9152048ee7851e36d45ad9'], 'd48bbfe4833347dfbf5befe63eb3795df3bce36cdc9152048ee7851e36d45ad9'],
'Rollercoaster Heaven': ['0b8cc95',
'0b8cc952c399e1515546a4ababe5ba2f7aace83915a7e51c56ee901568c9ef56'],
'Schneider Shores': ['e57112f', 'Schneider Shores': ['e57112f',
'e57112f58a7710d3e80242e867fb65d720e0cd3b67bebfd6b7df8b404fc7ea2b'], 'e57112f58a7710d3e80242e867fb65d720e0cd3b67bebfd6b7df8b404fc7ea2b'],
'Sherwood Forest': ['825134a', 'Sherwood Forest': ['825134a',
@ -87,6 +91,8 @@
'102a1c52853e77b6efd448a44572a862fa440615b4ea9ae5d7fb31c48c96aac9'], '102a1c52853e77b6efd448a44572a862fa440615b4ea9ae5d7fb31c48c96aac9'],
'Hydro Hills': ['bfbd61f', 'Hydro Hills': ['bfbd61f',
'bfbd61f6d22cdc5f2e017935f4e9e5969dece159218a08c695bfd727382cc717'], 'bfbd61f6d22cdc5f2e017935f4e9e5969dece159218a08c695bfd727382cc717'],
'Iceberg Islands': ['4a762ae',
'4a762ae89bf279dbcaead9e457c21014a9e39eb4a46cf1cbf63304450f9ed050'],
'katie\'s dreamland': ['73d0921', 'katie\'s dreamland': ['73d0921',
'73d0921f1d49388ffb4deb300c6ebb3920564410c2239580a7d1145fa54c2d4a'], '73d0921f1d49388ffb4deb300c6ebb3920564410c2239580a7d1145fa54c2d4a'],
'Leafy Lake': ['83bd798', 'Leafy Lake': ['83bd798',
@ -130,7 +136,9 @@
'Haunted Harbour': ['b2cebe1', 'Haunted Harbour': ['b2cebe1',
'b2cebe149b2330e071a028d079f6632af144fb44e076a5eca89780eb4007e136'], 'b2cebe149b2330e071a028d079f6632af144fb44e076a5eca89780eb4007e136'],
'hydro hills': ['ce24961', 'hydro hills': ['ce24961',
'ce249614e735c560c5019318bc6fa8603ba6630576f7fb038def0bdac3e143ef'] 'ce249614e735c560c5019318bc6fa8603ba6630576f7fb038def0bdac3e143ef'],
'Iceberg Islands': ['b20bd80',
'b20bd803c0a99c8748b48688501ba6ef8a5ce5d746540a486617e0564aa407d5'],
'katie\'s dreamland': ['b8b572d', 'katie\'s dreamland': ['b8b572d',
'b8b572d394b145535cdb20f66b0bee9a497683a5885e4d78af6773c5bc0323ff'], 'b8b572d394b145535cdb20f66b0bee9a497683a5885e4d78af6773c5bc0323ff'],
'mel\'s world': ['bfaf504', 'mel\'s world': ['bfaf504',
@ -195,6 +203,8 @@
'adffe2ff1e06ebeb821bbf01263125dc40311a8350722c62908be8d1c8852259'], 'adffe2ff1e06ebeb821bbf01263125dc40311a8350722c62908be8d1c8852259'],
'Lost City Founder': ['70ce3e1', 'Lost City Founder': ['70ce3e1',
'70ce3e11f1dd59929a6d82d0f6f88897c95b94d1f9d4efd6ef3a0c6c449f966f'], '70ce3e11f1dd59929a6d82d0f6f88897c95b94d1f9d4efd6ef3a0c6c449f966f'],
'Mines of Africa': ['b080197',
'b080197d430a6ded46945035a95c8f2d9e3064637e9119e68270554eda48e747'],
'Mirage Madness': ['82aeaf6', 'Mirage Madness': ['82aeaf6',
'82aeaf6bd628bf26dabd1ca87455b667f3081598bcf4d4c7751e2bdfbd266ac2'], '82aeaf6bd628bf26dabd1ca87455b667f3081598bcf4d4c7751e2bdfbd266ac2'],
'Mythological Madness': ['6633d17', 'Mythological Madness': ['6633d17',
@ -207,6 +217,8 @@
'b43b07e47f2e6cb762a86760ac0242595617aa59bfd9811cec7e2dcc121ae367'], 'b43b07e47f2e6cb762a86760ac0242595617aa59bfd9811cec7e2dcc121ae367'],
'Rock n Roll Revival': ['f71c978', 'Rock n Roll Revival': ['f71c978',
'f71c9788ab40ac591d5c96397fad8b12d9d3ac7830eac53f6ee5dc024c8c2bcf'], 'f71c9788ab40ac591d5c96397fad8b12d9d3ac7830eac53f6ee5dc024c8c2bcf'],
'Rollercoaster Heaven': ['eabcb3d',
'eabcb3d924e8e3438bfd90f6758a723c89df4136a817533d34985598d58ba38f'],
'Schneider Shores': ['0d53bdc', 'Schneider Shores': ['0d53bdc',
'0d53bdc076d75d86b31b6b3e6948e3d45671cf5aeff6b2b3c07a7618923223f5'], '0d53bdc076d75d86b31b6b3e6948e3d45671cf5aeff6b2b3c07a7618923223f5'],
'Sherwood Forest': ['a04b536', 'Sherwood Forest': ['a04b536',
@ -220,4 +232,4 @@
'Six Flags over Texas': ['6226822', 'Six Flags over Texas': ['6226822',
'62268223a1539c92b7494973263457c9e9bf386c1e68eef21d377854f0ac0e38'], '62268223a1539c92b7494973263457c9e9bf386c1e68eef21d377854f0ac0e38'],
'Wacky Waikiki': ['72cf3d2', 'Wacky Waikiki': ['72cf3d2',
'72cf3d220740fd64f7681d3533320598cf6d3b71dff484bc43045e8d9d7a1a4b'], '72cf3d220740fd64f7681d3533320598cf6d3b71dff484bc43045e8d9d7a1a4b'],

View file

@ -6,6 +6,7 @@
- Improved: [#23123] Improve sorting of roller coasters in build new ride menu. - Improved: [#23123] Improve sorting of roller coasters in build new ride menu.
- Improved: [#23211] Add boosters to classic wooden roller coaster (cheats only). - Improved: [#23211] Add boosters to classic wooden roller coaster (cheats only).
- Improved: [#23233] Add diagonal booster to LSM Launched Coaster. - 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: [#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: [#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. - Fix: [#23066] Stand-Up Roller Coaster has many supports that don't join up to the track.

View file

@ -12,6 +12,8 @@
#include "../Context.h" #include "../Context.h"
#include "../Game.h" #include "../Game.h"
#include "../PlatformEnvironment.h" #include "../PlatformEnvironment.h"
#include "../actions/FootpathPlaceAction.h"
#include "../actions/GameActionResult.h"
#include "../core/File.h" #include "../core/File.h"
#include "../core/Guard.hpp" #include "../core/Guard.hpp"
#include "../core/Json.hpp" #include "../core/Json.hpp"
@ -27,6 +29,8 @@
#include "../world/Location.hpp" #include "../world/Location.hpp"
#include "../world/Map.h" #include "../world/Map.h"
#include "../world/tile_element/EntranceElement.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/SurfaceElement.h"
#include "../world/tile_element/TileElement.h" #include "../world/tile_element/TileElement.h"
#include "../world/tile_element/TileElementType.h" #include "../world/tile_element/TileElementType.h"
@ -74,6 +78,13 @@ static const std::string _ridesKey = "rides";
static const std::string _rideIdKey = "id"; static const std::string _rideIdKey = "id";
static const std::string _operationKey = "operation"; 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 const std::string _directionKey = "slope_direction";
static const std::string _isQueue = "queue";
static u8string ToOwnershipJsonKey(int ownershipType) static u8string ToOwnershipJsonKey(int ownershipType)
{ {
switch (ownershipType) switch (ownershipType)
@ -93,7 +104,33 @@ static u8string ToOwnershipJsonKey(int ownershipType)
return {}; 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)) if (!parameters.contains(_coordinatesKey))
{ {
@ -113,7 +150,7 @@ static std::vector<TileCoordsXY> getCoordinates(const json_t& parameters)
return {}; return {};
} }
std::vector<TileCoordsXY> parsedCoordinates; std::vector<TTileCoords> parsedCoordinates;
parsedCoordinates.reserve(coords.size()); parsedCoordinates.reserve(coords.size());
for (size_t i = 0; i < coords.size(); ++i) for (size_t i = 0; i < coords.size(); ++i)
{ {
@ -123,18 +160,52 @@ static std::vector<TileCoordsXY> getCoordinates(const json_t& parameters)
return {}; return {};
} }
auto coordinatesPair = OpenRCT2::Json::AsArray(coords[i]); auto coordinatesArray = OpenRCT2::Json::AsArray(coords[i]);
if (coordinatesPair.size() != 2) readCoordinate(parsedCoordinates, coordinatesArray);
{
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]));
} }
return parsedCoordinates; 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<Direction>(parameters[_directionKey]);
if (direction > 3)
{
OpenRCT2::Guard::Assert(0, "Direction must be between 0 and 3");
return INVALID_DIRECTION;
}
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) static void ApplyLandOwnershipFixes(const json_t& landOwnershipFixes, int ownershipType)
{ {
auto ownershipTypeKey = ToOwnershipJsonKey(ownershipType); auto ownershipTypeKey = ToOwnershipJsonKey(ownershipType);
@ -517,6 +588,84 @@ 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);
Direction direction = GetDirection(pathFix);
PathConstructFlags constructionFlags = IsQueue(pathFix) ? OpenRCT2::PathConstructFlag::IsQueue : 0;
for (auto coordinate : coordinates)
{
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)
{
OpenRCT2::Guard::Assert(0, "Could not patch path");
}
}
}
}
static u8string getScenarioSHA256(u8string_view scenarioPath) static u8string getScenarioSHA256(u8string_view scenarioPath)
{ {
auto env = OpenRCT2::GetContext()->GetPlatformEnvironment(); auto env = OpenRCT2::GetContext()->GetPlatformEnvironment();
@ -581,6 +730,7 @@ void OpenRCT2::RCT12::ApplyScenarioPatch(u8string_view scenarioPatchFile, u8stri
ApplySurfaceFixes(scenarioPatch); ApplySurfaceFixes(scenarioPatch);
RemoveTileElements(scenarioPatch); RemoveTileElements(scenarioPatch);
ApplyRideFixes(scenarioPatch); ApplyRideFixes(scenarioPatch);
ApplyPathFixes(scenarioPatch);
} }
void OpenRCT2::RCT12::FetchAndApplyScenarioPatch(u8string_view scenarioPath) void OpenRCT2::RCT12::FetchAndApplyScenarioPatch(u8string_view scenarioPath)