Fix #13958: Queue corruption due to intersecting entrances

There was a whole host of bugs that this issue has exposed which were caused by intersecting the queue of a ride with an entrance/exit or shop. When this was done the peep would be removed from the queue incorrectly and could end up at the wrong station or a variety of other unexpected behaviour
This commit is contained in:
Duncan 2021-01-30 16:20:01 +00:00 committed by GitHub
parent 9ff2138f3f
commit 2d6da7551b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 27 deletions

View File

@ -34,7 +34,7 @@
// This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "17"
#define NETWORK_STREAM_VERSION "18"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static Peep* _pickup_peep = nullptr;

View File

@ -5298,7 +5298,8 @@ void Guest::UpdateQueuing()
return;
}
if (SubState != 10)
// If not in the queue then at front of queue
if (RideSubState != PeepRideSubState::InQueue)
{
bool is_front = true;
// Fix #4819: Occasionally the peep->GuestNextInQueue is incorrectly set

View File

@ -2300,11 +2300,21 @@ static void peep_return_to_centre_of_tile(Peep* peep)
*
* rct2: 0x00693f2C
*/
static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uint8_t& pathing_result)
static bool peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uint8_t& pathing_result)
{
auto tile_element = coords.element;
uint8_t entranceType = tile_element->AsEntrance()->GetEntranceType();
auto rideIndex = tile_element->AsEntrance()->GetRideIndex();
if ((entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE) || (entranceType == ENTRANCE_TYPE_RIDE_EXIT))
{
// If an entrance or exit that doesn't belong to the ride we are queuing for ignore the entrance/exit
// This can happen when paths clip through entrance/exits
if (peep->State == PeepState::Queuing && peep->CurrentRide != rideIndex)
{
return false;
}
}
// Store some details to determine when to override the default
// behaviour (defined below) for when staff attempt to enter a ride
// to fix/inspect it.
@ -2325,15 +2335,14 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
// ride exit is to turn around.
peep->InteractionRideIndex = RIDE_ID_NULL;
peep_return_to_centre_of_tile(peep);
return;
return true;
}
if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE)
{
auto rideIndex = tile_element->AsEntrance()->GetRideIndex();
auto ride = get_ride(rideIndex);
if (ride == nullptr)
return;
return false;
auto guest = peep->AsGuest();
if (guest == nullptr)
@ -2342,15 +2351,15 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
// ride entrance is to turn around.
peep->InteractionRideIndex = RIDE_ID_NULL;
peep_return_to_centre_of_tile(peep);
return;
return true;
}
if (peep->State == PeepState::Queuing)
{
// Guest is in the ride queue.
peep->SubState = 11;
peep->RideSubState = PeepRideSubState::AtQueueFront;
peep->ActionSpriteImageOffset = _unk_F1AEF0;
return;
return true;
}
// Guest is on a normal path, i.e. ride has no queue.
@ -2361,7 +2370,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
// attached to this path tile. i.e. stick with the
// peeps previous decision not to go on the ride.
peep_return_to_centre_of_tile(peep);
return;
return true;
}
peep->TimeLost = 0;
@ -2375,7 +2384,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
// considered while on this path tile.
peep->InteractionRideIndex = rideIndex;
peep_return_to_centre_of_tile(peep);
return;
return true;
}
// Guest has decided to go on the ride.
@ -2391,7 +2400,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
peep->CurrentRideStation = stationNum;
peep->DaysInQueue = 0;
peep->SetState(PeepState::Queuing);
peep->SubState = 11;
peep->RideSubState = PeepRideSubState::AtQueueFront;
peep->TimeInQueue = 0;
if (peep->PeepFlags & PEEP_FLAGS_TRACKING)
{
@ -2413,14 +2422,14 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
{
// Staff cannot leave the park, so go back.
peep_return_to_centre_of_tile(peep);
return;
return true;
}
// If not the centre of the entrance arch
if (tile_element->AsEntrance()->GetSequenceIndex() != 0)
{
peep_return_to_centre_of_tile(peep);
return;
return true;
}
uint8_t entranceDirection = tile_element->GetDirection();
@ -2429,14 +2438,14 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
if (direction_reverse(entranceDirection) != peep->PeepDirection)
{
peep_return_to_centre_of_tile(peep);
return;
return true;
}
// Peep is leaving the park.
if (peep->State != PeepState::Walking)
{
peep_return_to_centre_of_tile(peep);
return;
return true;
}
if (!(peep->PeepFlags & PEEP_FLAGS_LEAVING_PARK))
@ -2445,7 +2454,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
if (gParkFlags & PARK_FLAGS_PARK_OPEN)
{
peep_return_to_centre_of_tile(peep);
return;
return true;
}
}
@ -2465,7 +2474,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
News::AddItemToQueue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_LEFT_PARK, peep->sprite_index, ft);
}
}
return;
return true;
}
// Peep is entering the park.
@ -2473,7 +2482,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
if (peep->State != PeepState::EnteringPark)
{
peep_return_to_centre_of_tile(peep);
return;
return true;
}
if (!(gParkFlags & PARK_FLAGS_PARK_OPEN))
@ -2483,7 +2492,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
decrement_guests_heading_for_park();
peep_window_state_update(peep);
peep_return_to_centre_of_tile(peep);
return;
return true;
}
bool found = false;
@ -2547,7 +2556,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
decrement_guests_heading_for_park();
peep_window_state_update(peep);
peep_return_to_centre_of_tile(peep);
return;
return true;
}
money16 entranceFee = park_get_entrance_fee();
@ -2575,7 +2584,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
decrement_guests_heading_for_park();
peep_window_state_update(peep);
peep_return_to_centre_of_tile(peep);
return;
return true;
}
gTotalIncomeFromAdmissions += entranceFee;
@ -2592,6 +2601,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin
peep->DestinationTolerance = 7;
peep->MoveTo({ coords, peep->z });
}
return true;
}
/**
@ -2819,7 +2829,7 @@ static void peep_interact_with_path(Peep* peep, const CoordsXYE& coords)
peep->DaysInQueue = 0;
peep_window_state_update(peep);
peep->SubState = 10;
peep->RideSubState = PeepRideSubState::InQueue;
peep->DestinationTolerance = 2;
peep->TimeInQueue = 0;
if (peep->PeepFlags & PEEP_FLAGS_TRACKING)
@ -2880,6 +2890,13 @@ static bool peep_interact_with_shop(Peep* peep, const CoordsXYE& coords)
return true;
}
// If we are queuing ignore the 'shop'
// This can happen when paths clip through track
if (peep->State == PeepState::Queuing)
{
return false;
}
peep->TimeLost = 0;
if (ride->status != RIDE_STATUS_OPEN)
@ -3055,9 +3072,11 @@ void Peep::PerformNextAction(uint8_t& pathing_result, TileElement*& tile_result)
}
else if (tileElement->GetType() == TILE_ELEMENT_TYPE_ENTRANCE)
{
peep_interact_with_entrance(this, { newLoc, tileElement }, pathing_result);
tile_result = tileElement;
return;
if (peep_interact_with_entrance(this, { newLoc, tileElement }, pathing_result))
{
tile_result = tileElement;
return;
}
}
} while (!(tileElement++)->IsLastForTile());

View File

@ -264,7 +264,8 @@ enum class PeepRideSubState : uint8_t
LeaveVehicle = 7,
ApproachExit = 8,
InExit = 9,
// 10, 11 not used
InQueue = 10,
AtQueueFront = 11,
ApproachVehicleWaypoints = 12,
ApproachExitWaypoints = 13,
ApproachSpiralSlide = 14,