Fix hacked rides with no vehicles crashing the game.

This commit is contained in:
Matt 2018-12-01 14:45:13 +01:00 committed by Hielke Morsink
parent f8d91279ea
commit f0bd72732c
2 changed files with 69 additions and 27 deletions

View File

@ -2595,6 +2595,10 @@ bool Ride::CanBreakDown() const
static void choose_random_train_to_breakdown_safe(Ride* ride)
{
// Prevent integer division by zero in case of hacked ride.
if (ride->num_vehicles == 0)
return;
ride->broken_vehicle = scenario_rand() % ride->num_vehicles;
// Prevent crash caused by accessing SPRITE_INDEX_NULL on hacked rides.
@ -2612,6 +2616,7 @@ static void choose_random_train_to_breakdown_safe(Ride* ride)
void ride_prepare_breakdown(int32_t rideIndex, int32_t breakdownReason)
{
int32_t i;
uint16_t vehicleSpriteIdx;
Ride* ride;
rct_vehicle* vehicle;
@ -2646,21 +2651,25 @@ void ride_prepare_breakdown(int32_t rideIndex, int32_t breakdownReason)
ride->broken_car = scenario_rand() % ride->num_cars_per_train;
// Set flag on broken car
vehicle = GET_VEHICLE(ride->vehicles[ride->broken_vehicle]);
for (i = ride->broken_car; i > 0; i--)
vehicleSpriteIdx = ride->vehicles[ride->broken_vehicle];
if (vehicleSpriteIdx != SPRITE_INDEX_NULL)
{
if (vehicle->next_vehicle_on_train == SPRITE_INDEX_NULL)
vehicle = GET_VEHICLE(vehicleSpriteIdx);
for (i = ride->broken_car; i > 0; i--)
{
vehicle = nullptr;
break;
}
else
{
vehicle = GET_VEHICLE(vehicle->next_vehicle_on_train);
if (vehicle->next_vehicle_on_train == SPRITE_INDEX_NULL)
{
vehicle = nullptr;
break;
}
else
{
vehicle = GET_VEHICLE(vehicle->next_vehicle_on_train);
}
}
if (vehicle != nullptr)
vehicle->update_flags |= VEHICLE_UPDATE_FLAG_BROKEN_CAR;
}
if (vehicle != nullptr)
vehicle->update_flags |= VEHICLE_UPDATE_FLAG_BROKEN_CAR;
break;
case BREAKDOWN_VEHICLE_MALFUNCTION:
// Choose a random train
@ -2668,8 +2677,12 @@ void ride_prepare_breakdown(int32_t rideIndex, int32_t breakdownReason)
ride->broken_car = 0;
// Set flag on broken train, first car
vehicle = GET_VEHICLE(ride->vehicles[ride->broken_vehicle]);
vehicle->update_flags |= VEHICLE_UPDATE_FLAG_BROKEN_TRAIN;
vehicleSpriteIdx = ride->vehicles[ride->broken_vehicle];
if (vehicleSpriteIdx != SPRITE_INDEX_NULL)
{
vehicle = GET_VEHICLE(vehicleSpriteIdx);
vehicle->update_flags |= VEHICLE_UPDATE_FLAG_BROKEN_TRAIN;
}
break;
case BREAKDOWN_BRAKES_FAILURE:
// Original code generates a random number but does not use it
@ -2978,11 +2991,15 @@ static void ride_music_update(int32_t rideIndex)
if (ride->type == RIDE_TYPE_CIRCUS)
{
rct_vehicle* vehicle = GET_VEHICLE(ride->vehicles[0]);
if (vehicle->status != VEHICLE_STATUS_DOING_CIRCUS_SHOW)
uint16_t vehicleSpriteIdx = ride->vehicles[0];
if (vehicleSpriteIdx != SPRITE_INDEX_NULL)
{
ride->music_tune_id = 255;
return;
rct_vehicle* vehicle = GET_VEHICLE(vehicleSpriteIdx);
if (vehicle->status != VEHICLE_STATUS_DOING_CIRCUS_SHOW)
{
ride->music_tune_id = 255;
return;
}
}
}
@ -3169,11 +3186,11 @@ void ride_measurements_update()
// For each vehicle
for (int32_t j = 0; j < ride->num_vehicles; j++)
{
uint16_t spriteIndex = ride->vehicles[j];
if (spriteIndex == SPRITE_INDEX_NULL)
uint16_t vehicleSpriteIdx = ride->vehicles[j];
if (vehicleSpriteIdx == SPRITE_INDEX_NULL)
continue;
rct_vehicle* vehicle = GET_VEHICLE(spriteIndex);
rct_vehicle* vehicle = GET_VEHICLE(vehicleSpriteIdx);
if (vehicle->status == VEHICLE_STATUS_DEPARTING || vehicle->status == VEHICLE_STATUS_TRAVELLING_CABLE_LIFT)
{
measurement->vehicle_index = j;
@ -5324,7 +5341,11 @@ void loc_6DDF9C(Ride* ride, TileElement* tileElement)
for (int32_t i = 0; i < ride->num_vehicles; i++)
{
train = GET_VEHICLE(ride->vehicles[i]);
uint16_t vehicleSpriteIdx = ride->vehicles[i];
if (vehicleSpriteIdx == SPRITE_INDEX_NULL)
continue;
train = GET_VEHICLE(vehicleSpriteIdx);
if (i == 0)
{
vehicle_update_track_motion(train, nullptr);

View File

@ -99,7 +99,11 @@ static void ride_update_station_bumpercar(Ride* ride, int32_t stationIndex)
int32_t dh = (dx >> 8) & 0xFF;
for (size_t i = 0; i < ride->num_vehicles; i++)
{
rct_vehicle* vehicle = &(get_sprite(ride->vehicles[i])->vehicle);
uint16_t vehicleSpriteIdx = ride->vehicles[i];
if (vehicleSpriteIdx == SPRITE_INDEX_NULL)
continue;
rct_vehicle* vehicle = GET_VEHICLE(vehicleSpriteIdx);
if (vehicle->var_CE < dh || (vehicle->var_CE < dh && vehicle->sub_state > dl))
continue;
@ -117,7 +121,11 @@ static void ride_update_station_bumpercar(Ride* ride, int32_t stationIndex)
// Check if all vehicles are ready to go
for (size_t i = 0; i < ride->num_vehicles; i++)
{
rct_vehicle* vehicle = &(get_sprite(ride->vehicles[i])->vehicle);
uint16_t vehicleSpriteIdx = ride->vehicles[i];
if (vehicleSpriteIdx == SPRITE_INDEX_NULL)
continue;
rct_vehicle* vehicle = GET_VEHICLE(vehicleSpriteIdx);
if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART)
{
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
@ -185,15 +193,20 @@ static void ride_update_station_race(Ride* ride, int32_t stationIndex)
if (ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING)
{
int32_t numLaps = ride->num_laps;
for (size_t i = 0; i < ride->num_vehicles; i++)
{
rct_vehicle* vehicle = &(get_sprite(ride->vehicles[i])->vehicle);
uint16_t vehicleSpriteIdx = ride->vehicles[i];
if (vehicleSpriteIdx == SPRITE_INDEX_NULL)
continue;
rct_vehicle* vehicle = GET_VEHICLE(vehicleSpriteIdx);
if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART && vehicle->num_laps >= numLaps)
{
// Found a winner
if (vehicle->num_peeps != 0)
{
rct_peep* peep = &(get_sprite(vehicle->peep[0])->peep);
rct_peep* peep = GET_PEEP(vehicle->peep[0]);
ride->race_winner = peep->sprite_index;
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
}
@ -217,7 +230,11 @@ static void ride_update_station_race(Ride* ride, int32_t stationIndex)
// Check if all vehicles are ready to go
for (size_t i = 0; i < ride->num_vehicles; i++)
{
rct_vehicle* vehicle = &(get_sprite(ride->vehicles[i])->vehicle);
uint16_t vehicleSpriteIdx = ride->vehicles[i];
if (vehicleSpriteIdx == SPRITE_INDEX_NULL)
continue;
rct_vehicle* vehicle = GET_VEHICLE(vehicleSpriteIdx);
if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART && vehicle->status != VEHICLE_STATUS_DEPARTING)
{
if (ride->station_depart[stationIndex] & STATION_DEPART_FLAG)
@ -251,7 +268,11 @@ static void ride_race_init_vehicle_speeds(Ride* ride)
{
for (size_t i = 0; i < ride->num_vehicles; i++)
{
rct_vehicle* vehicle = &get_sprite(ride->vehicles[i])->vehicle;
uint16_t vehicleSpriteIdx = ride->vehicles[i];
if (vehicleSpriteIdx == SPRITE_INDEX_NULL)
continue;
rct_vehicle* vehicle = GET_VEHICLE(vehicleSpriteIdx);
vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_6;
rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype);