1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Fix #18714: Allow block-sectioned rides to simulate with incomplete circuit (#25034)

* Allow block-sectioned rides to simulate with incomplete circuit

* Remove unused variable
This commit is contained in:
kyphii
2025-08-29 05:53:22 -04:00
committed by GitHub
parent f4b5ba72eb
commit 39aab71e7d
4 changed files with 29 additions and 29 deletions

View File

@@ -1,6 +1,7 @@
0.4.26 (in development)
------------------------------------------------------------------------
- Feature: [#24949] Add an option to the command line screenshot function to draw debug bounding boxes.
- Improved: [#18714] Rides using block-sectioned operating modes can now enter simulating mode without having to complete the circuit first.
- Improved: [#24734] Save files now use Zstd compression for faster saving and smaller files.
- Improved: [#24890] The ride list is now searchable.
- Improved: [#24893] The ride list now has headers, and can be sorted in both directions.

View File

@@ -49,7 +49,7 @@ using namespace OpenRCT2;
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
constexpr uint8_t kNetworkStreamVersion = 3;
constexpr uint8_t kNetworkStreamVersion = 4;
const std::string kNetworkStreamID = std::string(kOpenRCT2Version) + "-" + std::to_string(kNetworkStreamVersion);

View File

@@ -2703,7 +2703,7 @@ void Ride::chainQueues() const
*
* rct2: 0x006D3319
*/
static ResultWithMessage RideCheckBlockBrakes(const CoordsXYE& input, CoordsXYE* output)
static ResultWithMessage RideCheckBlockBrakes(const CoordsXYE& input, CoordsXYE* output, bool shouldCheckCompleteCircuit)
{
if (input.element == nullptr || input.element->GetType() != TileElementType::Track)
return { false };
@@ -2740,7 +2740,7 @@ static ResultWithMessage RideCheckBlockBrakes(const CoordsXYE& input, CoordsXYE*
}
}
}
if (!it.looped)
if (!it.looped && shouldCheckCompleteCircuit)
{
// Not sure why this is the case...
*output = it.last;
@@ -3459,14 +3459,14 @@ static TrainReference VehicleCreateTrain(
return train;
}
static bool VehicleCreateTrains(Ride& ride, const CoordsXYZ& trainsPos, TrackElement* trackElement)
static bool VehicleCreateTrains(Ride& ride, const CoordsXYZ& trainsPos, TrackElement* trackElement, int16_t numberOfTrains)
{
TrainReference firstTrain = {};
TrainReference lastTrain = {};
int32_t remainingDistance = 0;
bool allTrainsCreated = true;
for (int32_t vehicleIndex = 0; vehicleIndex < ride.numTrains; vehicleIndex++)
for (int32_t vehicleIndex = 0; vehicleIndex < numberOfTrains; vehicleIndex++)
{
if (ride.isBlockSectioned())
{
@@ -3586,7 +3586,7 @@ static void RidecreateVehiclesFindFirstBlock(const Ride& ride, CoordsXYE* outXYE
* Create and place the rides vehicles
* rct2: 0x006DD84C
*/
ResultWithMessage Ride::createVehicles(const CoordsXYE& element, bool isApplying)
ResultWithMessage Ride::createVehicles(const CoordsXYE& element, bool isApplying, bool isSimulating)
{
updateMaxVehicles();
if (subtype == kObjectEntryIndexNull)
@@ -3595,7 +3595,12 @@ ResultWithMessage Ride::createVehicles(const CoordsXYE& element, bool isApplying
}
// Check if there are enough free sprite slots for all the vehicles
int32_t totalCars = numTrains * numCarsPerTrain;
int32_t numberOfTrains = numTrains;
if (isBlockSectioned() && isSimulating)
{
numberOfTrains = 1;
}
int32_t totalCars = numberOfTrains * numCarsPerTrain;
if (totalCars > count_free_misc_sprite_slots())
{
return { false, STR_UNABLE_TO_CREATE_ENOUGH_VEHICLES };
@@ -3620,7 +3625,7 @@ ResultWithMessage Ride::createVehicles(const CoordsXYE& element, bool isApplying
vehiclePos.z = trackElement->GetBaseZ();
}
if (!VehicleCreateTrains(*this, vehiclePos, trackElement))
if (!VehicleCreateTrains(*this, vehiclePos, trackElement, numberOfTrains))
{
// This flag is needed for Ride::removeVehicles()
lifecycleFlags |= RIDE_LIFECYCLE_ON_TRACK;
@@ -3640,7 +3645,7 @@ ResultWithMessage Ride::createVehicles(const CoordsXYE& element, bool isApplying
//
if (type != RIDE_TYPE_SPACE_RINGS && !getRideTypeDescriptor().HasFlag(RtdFlag::vehicleIsIntegral))
{
if (isBlockSectioned())
if (isBlockSectioned() && !isSimulating)
{
CoordsXYE firstBlock{};
RidecreateVehiclesFindFirstBlock(*this, &firstBlock);
@@ -4068,18 +4073,18 @@ ResultWithMessage Ride::test(bool isApplying)
return message;
}
message = changeStatusCheckTrackValidity(trackElement);
message = changeStatusCheckTrackValidity(trackElement, false);
if (!message.Successful)
{
return message;
}
return changeStatusCreateVehicles(isApplying, trackElement);
return changeStatusCreateVehicles(isApplying, trackElement, false);
}
ResultWithMessage Ride::simulate(bool isApplying)
{
CoordsXYE trackElement, problematicTrackElement = {};
CoordsXYE trackElement = {};
if (type == kRideTypeNull)
{
LOG_WARNING("Invalid ride type for ride %u", id.ToUnderlying());
@@ -4099,19 +4104,13 @@ ResultWithMessage Ride::simulate(bool isApplying)
return message;
}
if (isBlockSectioned() && findTrackGap(trackElement, &problematicTrackElement))
{
RideScrollToTrackError(problematicTrackElement);
return { false, STR_TRACK_IS_NOT_A_COMPLETE_CIRCUIT };
}
message = changeStatusCheckTrackValidity(trackElement);
message = changeStatusCheckTrackValidity(trackElement, true);
if (!message.Successful)
{
return message;
}
return changeStatusCreateVehicles(isApplying, trackElement);
return changeStatusCreateVehicles(isApplying, trackElement, true);
}
/**
@@ -4163,13 +4162,13 @@ ResultWithMessage Ride::open(bool isApplying)
return message;
}
message = changeStatusCheckTrackValidity(trackElement);
message = changeStatusCheckTrackValidity(trackElement, false);
if (!message.Successful)
{
return message;
}
return changeStatusCreateVehicles(isApplying, trackElement);
return changeStatusCreateVehicles(isApplying, trackElement, false);
}
/**
@@ -5941,13 +5940,13 @@ ResultWithMessage Ride::changeStatusCheckCompleteCircuit(const CoordsXYE& trackE
return { true };
}
ResultWithMessage Ride::changeStatusCheckTrackValidity(const CoordsXYE& trackElement)
ResultWithMessage Ride::changeStatusCheckTrackValidity(const CoordsXYE& trackElement, bool isSimulating)
{
CoordsXYE problematicTrackElement = {};
if (isBlockSectioned())
{
auto blockBrakeCheck = RideCheckBlockBrakes(trackElement, &problematicTrackElement);
auto blockBrakeCheck = RideCheckBlockBrakes(trackElement, &problematicTrackElement, !isSimulating);
if (!blockBrakeCheck.Successful)
{
RideScrollToTrackError(problematicTrackElement);
@@ -6003,7 +6002,7 @@ ResultWithMessage Ride::changeStatusCheckTrackValidity(const CoordsXYE& trackEle
return { true };
}
ResultWithMessage Ride::changeStatusCreateVehicles(bool isApplying, const CoordsXYE& trackElement)
ResultWithMessage Ride::changeStatusCreateVehicles(bool isApplying, const CoordsXYE& trackElement, bool isSimulating)
{
if (isApplying)
RideSetStartFinishPoints(id, trackElement);
@@ -6011,7 +6010,7 @@ ResultWithMessage Ride::changeStatusCreateVehicles(bool isApplying, const Coords
const auto& rtd = getRideTypeDescriptor();
if (!rtd.HasFlag(RtdFlag::noVehicles) && !(lifecycleFlags & RIDE_LIFECYCLE_ON_TRACK))
{
const auto createVehicleResult = createVehicles(trackElement, isApplying);
const auto createVehicleResult = createVehicles(trackElement, isApplying, isSimulating);
if (!createVehicleResult.Successful)
{
return { false, createVehicleResult.Message };

View File

@@ -331,7 +331,7 @@ public:
private:
void update();
void updateQueueLength(StationIndex stationIndex);
ResultWithMessage createVehicles(const CoordsXYE& element, bool isApplying);
ResultWithMessage createVehicles(const CoordsXYE& element, bool isApplying, bool isSimulating);
void moveTrainsToBlockBrakes(const CoordsXYZ& firstBlockPosition, OpenRCT2::TrackElement& firstBlock);
money64 calculateIncomePerHour() const;
void chainQueues() const;
@@ -340,8 +340,8 @@ private:
ResultWithMessage changeStatusDoStationChecks(StationIndex& stationIndex);
ResultWithMessage changeStatusGetStartElement(StationIndex stationIndex, CoordsXYE& trackElement);
ResultWithMessage changeStatusCheckCompleteCircuit(const CoordsXYE& trackElement);
ResultWithMessage changeStatusCheckTrackValidity(const CoordsXYE& trackElement);
ResultWithMessage changeStatusCreateVehicles(bool isApplying, const CoordsXYE& trackElement);
ResultWithMessage changeStatusCheckTrackValidity(const CoordsXYE& trackElement, bool isSimulating);
ResultWithMessage changeStatusCreateVehicles(bool isApplying, const CoordsXYE& trackElement, bool isSimulating);
public:
bool canBreakDown() const;