Fix disconnected entrances when loading save

This commit is contained in:
Michael Steenbeek 2017-10-25 10:25:55 +02:00
parent 98043c284b
commit e53d76f7e1
5 changed files with 108 additions and 0 deletions

View File

@ -1124,6 +1124,9 @@ void game_fix_save_vars()
// Fix gParkEntrance locations for which the map_element no longer exists
fix_park_entrance_locations();
// Fix ride entrances that were moved without updating ride->entrances[]
fix_ride_entrance_locations();
}
void handle_park_load_failure_with_title_opt(const ParkLoadResult * result, const utf8 * path, bool loadTitleFirst)

View File

@ -8226,3 +8226,81 @@ LocationXY16 ride_get_rotated_coords(sint16 x, sint16 y, sint16 z)
return rotatedCoords;
}
void fix_ride_entrance_locations()
{
sint32 rideIndex;
Ride * ride;
FOR_ALL_RIDES(rideIndex, ride)
{
for (sint32 stationIndex = 0; stationIndex < MAX_STATIONS; stationIndex++)
{
LocationXY8 entranceLoc = ride->entrances[stationIndex];
uint8 entranceHeight = ride->station_heights[stationIndex];
// Skip if the station has no entrance
if (entranceLoc.xy == RCT_XY8_UNDEFINED)
{
continue;
}
rct_map_element * mapElement = map_get_ride_entrance_element_at(entranceLoc.x * 32, entranceLoc.y * 32, entranceHeight, false);
if (mapElement != NULL && mapElement->properties.entrance.ride_index == rideIndex && map_element_get_station(mapElement) == stationIndex)
{
continue;
}
// At this point, we know we have a disconnected entrance.
// Search the map to find it. Skip the outer ring of invisible tiles.
bool alreadyFoundOne = false;
for (uint8 x = 1; x < MAXIMUM_MAP_SIZE_TECHNICAL - 1; x++)
{
for (uint8 y = 1; y < MAXIMUM_MAP_SIZE_TECHNICAL - 1; y++)
{
mapElement = map_get_first_element_at(x, y);
if (mapElement != NULL)
{
do
{
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
{
continue;
}
if (mapElement->properties.entrance.type != ENTRANCE_TYPE_RIDE_ENTRANCE)
{
continue;
}
if (mapElement->properties.entrance.ride_index != rideIndex)
{
continue;
}
if (map_element_get_station(mapElement) != stationIndex)
{
continue;
}
// There are some cases (like Belmont Shores), where there is both a sunk and a disconnected entrance.
// Not sure why, but in this case, pick the highest one.
if (alreadyFoundOne && ride->station_heights[stationIndex] > mapElement->base_height)
{
continue;
}
// Found our entrance
ride->entrances[stationIndex].x = x;
ride->entrances[stationIndex].y = y;
ride->station_heights[stationIndex] = mapElement->base_height;
alreadyFoundOne = true;
log_info("Fixed disconnected entrance of ride %d, station %d to x = %d, y = %d and z = %d.", rideIndex, stationIndex, x, y, mapElement->base_height);
}
while (!map_element_is_last_for_tile(mapElement++));
}
}
}
}
}
}

View File

@ -1214,6 +1214,8 @@ void ride_stop_peeps_queuing(sint32 rideIndex);
LocationXY16 ride_get_rotated_coords(sint16 x, sint16 y, sint16 z);
void fix_ride_entrance_locations();
#ifdef __cplusplus
}
#endif

View File

@ -3832,6 +3832,30 @@ rct_map_element *map_get_park_entrance_element_at(sint32 x, sint32 y, sint32 z,
return NULL;
}
rct_map_element * map_get_ride_entrance_element_at(sint32 x, sint32 y, sint32 z, bool ghost)
{
rct_map_element * mapElement = map_get_first_element_at(x >> 5, y >> 5);
do
{
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
continue;
if (mapElement->base_height != z)
continue;
if (mapElement->properties.entrance.type != ENTRANCE_TYPE_RIDE_ENTRANCE)
continue;
if ((ghost == false) && (mapElement->flags & MAP_ELEMENT_FLAG_GHOST))
continue;
return mapElement;
}
while (!map_element_is_last_for_tile(mapElement++));
return NULL;
}
rct_map_element *map_get_small_scenery_element_at(sint32 x, sint32 y, sint32 z, sint32 type, uint8 quadrant)
{
rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5);

View File

@ -415,6 +415,7 @@ rct_map_element* map_get_path_element_at(sint32 x, sint32 y, sint32 z);
rct_map_element *map_get_wall_element_at(sint32 x, sint32 y, sint32 z, sint32 direction);
rct_map_element *map_get_small_scenery_element_at(sint32 x, sint32 y, sint32 z, sint32 type, uint8 quadrant);
rct_map_element *map_get_park_entrance_element_at(sint32 x, sint32 y, sint32 z, bool ghost);
rct_map_element * map_get_ride_entrance_element_at(sint32 x, sint32 y, sint32 z, bool ghost);
sint32 map_element_height(sint32 x, sint32 y);
void sub_68B089();
sint32 map_coord_is_connected(sint32 x, sint32 y, sint32 z, uint8 faceDirection);