diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 89b3afa7c0..aa1f740f76 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -68,6 +68,7 @@ - Fix: [#19493] SV4 saves not importing the correct vehicle colours. - Fix: [#19517] Crash when peeps try to exit or enter hacked rides that have no waypoints specified. - Fix: [#19524] Staff counter shows incorrect values if there are more than 32767 staff members. +- Fix: [#19574] Handle exits in null locations. - Fix: [#19641, #19643] Missing water tile in Infernal Views’ and Six Flags Holland’s river. 0.4.3 (2022-12-14) diff --git a/src/openrct2/entity/Guest.cpp b/src/openrct2/entity/Guest.cpp index 14e45644e6..04a82658e8 100644 --- a/src/openrct2/entity/Guest.cpp +++ b/src/openrct2/entity/Guest.cpp @@ -3597,7 +3597,10 @@ uint8_t Guest::GetWaypointedSeatLocation(const Ride& ride, const CarEntry* vehic void Guest::UpdateRideLeaveEntranceWaypoints(const Ride& ride) { const auto& station = ride.GetStation(CurrentRideStation); - Guard::Assert(!station.Entrance.IsNull()); + if (station.Entrance.IsNull()) + { + return; + } uint8_t direction_entrance = station.Entrance.direction; TileElement* tile_element = RideGetStationStartTrackElement(ride, CurrentRideStation); @@ -3684,7 +3687,10 @@ void Guest::UpdateRideAdvanceThroughEntrance() { const auto& station = ride->GetStation(CurrentRideStation); auto entranceLocation = station.Entrance.ToCoordsXYZD(); - Guard::Assert(!entranceLocation.IsNull()); + if (entranceLocation.IsNull()) + { + return; + } const auto& rtd = GetRideTypeDescriptor(ride->type); rtd.UpdateLeaveEntrance(this, *ride, entranceLocation); @@ -3770,7 +3776,6 @@ static void PeepGoToRideExit(Peep* peep, const Ride& ride, int16_t x, int16_t y, Guard::Assert(peep->CurrentRideStation.ToUnderlying() < OpenRCT2::Limits::MaxStationsPerRide); auto exit = ride.GetStation(peep->CurrentRideStation).Exit; - Guard::Assert(!exit.IsNull()); x = exit.x; y = exit.y; x *= 32; @@ -3778,8 +3783,16 @@ static void PeepGoToRideExit(Peep* peep, const Ride& ride, int16_t x, int16_t y, x += 16; y += 16; - int16_t x_shift = DirectionOffsets[exit_direction].x; - int16_t y_shift = DirectionOffsets[exit_direction].y; + auto [x_shift, y_shift] = [exit_direction]() { + if (exit_direction < DirectionOffsets.size()) + { + return std::pair(DirectionOffsets[exit_direction].x, DirectionOffsets[exit_direction].y); + } + else + { + return std::pair(0, 0); + } + }(); int16_t shift_multiplier = 20; @@ -3877,8 +3890,11 @@ static void PeepUpdateRideNoFreeVehicleRejoinQueue(Guest* peep, Ride& ride) int32_t x = entranceLocation.x * 32; int32_t y = entranceLocation.y * 32; - x += 16 - DirectionOffsets[entranceLocation.direction].x * 20; - y += 16 - DirectionOffsets[entranceLocation.direction].y * 20; + if (entranceLocation.direction < DirectionOffsets.size()) + { + x += 16 - DirectionOffsets[entranceLocation.direction].x * 20; + y += 16 - DirectionOffsets[entranceLocation.direction].y * 20; + } peep->SetDestination({ x, y }, 2); peep->SetState(PeepState::QueuingFront); @@ -4188,8 +4204,16 @@ void Guest::UpdateRideLeaveVehicle() } } - int16_t xShift = DirectionOffsets[specialDirection].x; - int16_t yShift = DirectionOffsets[specialDirection].y; + auto [xShift, yShift] = [specialDirection]() { + if (specialDirection < DirectionOffsets.size()) + { + return std::pair(DirectionOffsets[specialDirection].x, DirectionOffsets[specialDirection].y); + } + else + { + return std::pair(0, 0); + } + }(); platformLocation.x = vehicle->x + xShift * shiftMultiplier; platformLocation.y = vehicle->y + yShift * shiftMultiplier; @@ -4237,7 +4261,10 @@ void Guest::UpdateRideLeaveVehicle() } auto exitLocation = station.Exit.ToCoordsXYZD(); - Guard::Assert(!exitLocation.IsNull()); + if (exitLocation.IsNull()) + { + return; + } TileElement* trackElement = RideGetStationStartTrackElement(*ride, CurrentRideStation); @@ -4297,8 +4324,17 @@ void Guest::UpdateRidePrepareForExit() auto exit = ride->GetStation(CurrentRideStation).Exit; auto newDestination = exit.ToCoordsXY().ToTileCentre(); - auto xShift = DirectionOffsets[exit.direction].x; - auto yShift = DirectionOffsets[exit.direction].y; + + auto [xShift, yShift] = [exit]() { + if (exit.direction < DirectionOffsets.size()) + { + return std::pair(DirectionOffsets[exit.direction].x, DirectionOffsets[exit.direction].y); + } + else + { + return std::pair(0, 0); + } + }(); int16_t shiftMultiplier = 20; @@ -4618,7 +4654,12 @@ void Guest::UpdateRideApproachSpiralSlide() { auto exit = ride->GetStation(CurrentRideStation).Exit; waypoint = 1; - Var37 = (exit.direction * 4) | (Var37 & 0x30) | waypoint; + auto directionTemp = exit.direction; + if (exit.direction == INVALID_DIRECTION) + { + directionTemp = 0; + } + Var37 = (directionTemp * 4) | (Var37 & 0x30) | waypoint; CoordsXY targetLoc = ride->GetStation(CurrentRideStation).Start; assert(rtd.HasFlag(RIDE_TYPE_FLAG_IS_SPIRAL_SLIDE)); diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index b3c8b372eb..a38966c0d9 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -61,8 +61,8 @@ static RideId _footpathQueueChain[64]; // This is the coordinates that a user of the bin should move to // rct2: 0x00992A4C -const CoordsXY BinUseOffsets[4] = { - { 11, 16 }, +const std::array BinUseOffsets = { + CoordsXY{ 11, 16 }, { 16, 21 }, { 21, 16 }, { 16, 11 }, @@ -70,13 +70,13 @@ const CoordsXY BinUseOffsets[4] = { // These are the offsets for bench positions on footpaths, 2 for each edge // rct2: 0x00981F2C, 0x00981F2E -const CoordsXY BenchUseOffsets[8] = { - { 7, 12 }, { 12, 25 }, { 25, 20 }, { 20, 7 }, { 7, 20 }, { 20, 25 }, { 25, 12 }, { 12, 7 }, +const std::array BenchUseOffsets = { + CoordsXY{ 7, 12 }, { 12, 25 }, { 25, 20 }, { 20, 7 }, { 7, 20 }, { 20, 25 }, { 25, 12 }, { 12, 7 }, }; /** rct2: 0x00981D6C, 0x00981D6E */ -const CoordsXY DirectionOffsets[4] = { - { -1, 0 }, +const std::array DirectionOffsets = { + CoordsXY{ -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, diff --git a/src/openrct2/world/Footpath.h b/src/openrct2/world/Footpath.h index 3af84db0c9..03d935d364 100644 --- a/src/openrct2/world/Footpath.h +++ b/src/openrct2/world/Footpath.h @@ -180,9 +180,9 @@ extern uint8_t gFootpathConstructSlope; extern uint8_t gFootpathGroundFlags; // Given a direction, this will return how to increase/decrease the x and y coordinates. -extern const CoordsXY DirectionOffsets[NumOrthogonalDirections]; -extern const CoordsXY BinUseOffsets[NumOrthogonalDirections]; -extern const CoordsXY BenchUseOffsets[NumOrthogonalDirections * 2]; +extern const std::array DirectionOffsets; +extern const std::array BinUseOffsets; +extern const std::array BenchUseOffsets; TileElement* MapGetFootpathElement(const CoordsXYZ& coords); void FootpathInterruptPeeps(const CoordsXYZ& footpathPos);