mirror of https://github.com/OpenRCT2/OpenRCT2.git
In park/replay from dump #19574 there was a calamity that happened likely due to a plugin. Pretty much all rides were deleted in single tick, which caused the park to mark some locations as null and then it tripped on one of the many assertions. In many of the places it already bails out if ride or vehicle is a nullptr, so I followed with similar approach for invalid ride exits.
This commit is contained in:
parent
4bf35b267c
commit
1f7ef64627
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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<CoordsXY, NumOrthogonalDirections> 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<CoordsXY, NumOrthogonalDirections* 2> 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<CoordsXY, NumOrthogonalDirections> DirectionOffsets = {
|
||||
CoordsXY{ -1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 0 },
|
||||
{ 0, -1 },
|
||||
|
|
|
@ -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<CoordsXY, NumOrthogonalDirections> DirectionOffsets;
|
||||
extern const std::array<CoordsXY, NumOrthogonalDirections> BinUseOffsets;
|
||||
extern const std::array<CoordsXY, NumOrthogonalDirections * 2> BenchUseOffsets;
|
||||
|
||||
TileElement* MapGetFootpathElement(const CoordsXYZ& coords);
|
||||
void FootpathInterruptPeeps(const CoordsXYZ& footpathPos);
|
||||
|
|
Loading…
Reference in New Issue