1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-17 12:03:07 +01:00

Fix #14974: too many dodgems not handled correctly

Properly check if all vehicles have been created, and clean them up properly if not.
This commit is contained in:
Michael Steenbeek
2021-08-02 22:02:06 +02:00
committed by GitHub
parent b6fa27be96
commit 8ecbabf8bf
3 changed files with 43 additions and 11 deletions

View File

@@ -3087,9 +3087,15 @@ static Vehicle* vehicle_create_car(
vehicle->update_flags = 0;
CoordsXY chosenLoc;
auto numAttempts = 0;
// loc_6DDD26:
do
{
numAttempts++;
// This can happen when trying to spawn dozens of cars in a tiny area.
if (numAttempts > 10000)
return nullptr;
vehicle->sprite_direction = scenario_rand() & 0x1E;
chosenLoc.y = dodgemPos.y + (scenario_rand() & 0xFF);
chosenLoc.x = dodgemPos.x + (scenario_rand() & 0xFF);
@@ -3233,15 +3239,16 @@ static train_ref vehicle_create_train(
return train;
}
static void vehicle_create_trains(ride_id_t rideIndex, const CoordsXYZ& trainsPos, TrackElement* trackElement)
static bool vehicle_create_trains(ride_id_t rideIndex, const CoordsXYZ& trainsPos, TrackElement* trackElement)
{
auto ride = get_ride(rideIndex);
if (ride == nullptr)
return;
return false;
train_ref firstTrain = {};
train_ref lastTrain = {};
int32_t remainingDistance = 0;
bool allTrainsCreated = true;
for (int32_t vehicleIndex = 0; vehicleIndex < ride->num_vehicles; vehicleIndex++)
{
@@ -3251,7 +3258,10 @@ static void vehicle_create_trains(ride_id_t rideIndex, const CoordsXYZ& trainsPo
}
train_ref train = vehicle_create_train(rideIndex, trainsPos, vehicleIndex, &remainingDistance, trackElement);
if (train.head == nullptr || train.tail == nullptr)
{
allTrainsCreated = false;
continue;
}
if (vehicleIndex == 0)
{
@@ -3280,6 +3290,8 @@ static void vehicle_create_trains(ride_id_t rideIndex, const CoordsXYZ& trainsPo
firstTrain.head->prev_vehicle_on_ride = lastTrain.tail->sprite_index;
if (firstTrain.head != nullptr)
lastTrain.tail->next_vehicle_on_ride = firstTrain.head->sprite_index;
return allTrainsCreated;
}
/**
@@ -3389,7 +3401,14 @@ bool Ride::CreateVehicles(const CoordsXYE& element, bool isApplying)
direction = trackElement->GetDirection();
}
vehicle_create_trains(id, vehiclePos, trackElement);
if (!vehicle_create_trains(id, vehiclePos, trackElement))
{
// This flag is needed for Ride::RemoveVehicles()
lifecycle_flags |= RIDE_LIFECYCLE_ON_TRACK;
RemoveVehicles();
gGameCommandErrorText = STR_UNABLE_TO_CREATE_ENOUGH_VEHICLES;
return false;
}
// return true;
// Initialise station departs

View File

@@ -466,6 +466,8 @@ public:
uint8_t GetNumShelteredSections() const;
void IncreaseNumShelteredSections();
void RemoveVehicles();
};
#pragma pack(push, 1)

View File

@@ -40,6 +40,7 @@
#include "RideData.h"
#include "Track.h"
#include "TrackData.h"
#include "TrainManager.h"
#include "Vehicle.h"
bool gGotoStartPlacementMode = false;
@@ -173,16 +174,16 @@ static void ride_remove_cable_lift(Ride* ride)
*
* rct2: 0x006DD506
*/
static void ride_remove_vehicles(Ride* ride)
void Ride::RemoveVehicles()
{
if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)
if (lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)
{
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_ON_TRACK;
ride->lifecycle_flags &= ~(RIDE_LIFECYCLE_TEST_IN_PROGRESS | RIDE_LIFECYCLE_HAS_STALLED_VEHICLE);
lifecycle_flags &= ~RIDE_LIFECYCLE_ON_TRACK;
lifecycle_flags &= ~(RIDE_LIFECYCLE_TEST_IN_PROGRESS | RIDE_LIFECYCLE_HAS_STALLED_VEHICLE);
for (size_t i = 0; i <= MAX_VEHICLES_PER_RIDE; i++)
{
uint16_t spriteIndex = ride->vehicles[i];
uint16_t spriteIndex = vehicles[i];
while (spriteIndex != SPRITE_INDEX_NULL)
{
Vehicle* vehicle = GetEntity<Vehicle>(spriteIndex);
@@ -195,11 +196,21 @@ static void ride_remove_vehicles(Ride* ride)
sprite_remove(vehicle);
}
ride->vehicles[i] = SPRITE_INDEX_NULL;
vehicles[i] = SPRITE_INDEX_NULL;
}
for (size_t i = 0; i < MAX_STATIONS; i++)
ride->stations[i].TrainAtStation = RideStation::NO_TRAIN;
stations[i].TrainAtStation = RideStation::NO_TRAIN;
// Also clean up orphaned vehicles for good measure.
for (auto* vehicle : TrainManager::View())
{
if (vehicle->ride == id)
{
vehicle->Invalidate();
sprite_remove(vehicle);
}
}
}
}
@@ -223,7 +234,7 @@ void ride_clear_for_construction(Ride* ride)
}
ride_remove_cable_lift(ride);
ride_remove_vehicles(ride);
ride->RemoveVehicles();
ride_clear_blocked_tiles(ride);
auto w = window_find_by_number(WC_RIDE, ride->id);