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:
committed by
GitHub
parent
b6fa27be96
commit
8ecbabf8bf
@@ -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
|
||||
|
||||
@@ -466,6 +466,8 @@ public:
|
||||
|
||||
uint8_t GetNumShelteredSections() const;
|
||||
void IncreaseNumShelteredSections();
|
||||
|
||||
void RemoveVehicles();
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user