Merge pull request #18713

This commit is contained in:
Hielke Morsink 2023-04-13 00:03:00 +02:00 committed by GitHub
commit 5c34d1d7b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 253 additions and 41 deletions

View File

@ -76,9 +76,9 @@ set(OPENMSX_VERSION "1.2.0")
set(OPENMSX_URL "https://github.com/OpenRCT2/OpenMusic/releases/download/v${OPENMSX_VERSION}/openmusic.zip")
set(OPENMSX_SHA1 "c1c9b030c83c12ff628e8ec72fcfe748291a5344")
set(REPLAYS_VERSION "0.0.77")
set(REPLAYS_VERSION "0.0.78")
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip")
set(REPLAYS_SHA1 "65CA6D830789C074F575F15E3F9E2C28691C24F8")
set(REPLAYS_SHA1 "31C5D07EED8481D5C6D57F9E4FE9443AAEDE7739")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests")

View File

@ -3679,6 +3679,9 @@ STR_6573 :Invisible
STR_6574 :Void
STR_6575 :Allow special colour schemes
STR_6576 :Adds special colours to colour dropdown
STR_6577 :Block brake speed
STR_6578 :Set speed limit for block brakes. In block section mode, adjacent brakes with a slower speed are linked to the block brake.
STR_6579 :Block brakes will be set to default speed when saved as track design
#############
# Scenarios #

View File

@ -1,5 +1,6 @@
0.4.5 (in development)
------------------------------------------------------------------------
- Feature: [#18713] Block brakes have speed control and brakes slower than adjacent block brakes copy block brake speed when block brake open.
- Feature: [#19276] Add Powered Lifthill to Giga Coaster.
- Feature: [#19446] Add new color options to color dropdown.
- Feature: [#19547] Add large sloped turns to hybrid coaster and single rail coaster.

View File

@ -51,8 +51,8 @@
<OpenSFXSha1>64EF7E0B7785602C91AEC66F005C035B05A2133B</OpenSFXSha1>
<OpenMSXUrl>https://github.com/OpenRCT2/OpenMusic/releases/download/v1.2.0/openmusic.zip</OpenMSXUrl>
<OpenMSXSha1>c1c9b030c83c12ff628e8ec72fcfe748291a5344</OpenMSXSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.77/replays.zip</ReplaysUrl>
<ReplaysSha1>65CA6D830789C074F575F15E3F9E2C28691C24F8</ReplaysSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.78/replays.zip</ReplaysUrl>
<ReplaysSha1>31C5D07EED8481D5C6D57F9E4FE9443AAEDE7739</ReplaysSha1>
</PropertyGroup>
<ItemGroup>

View File

@ -1405,6 +1405,8 @@ public:
_currentTrackBankEnd = TRACK_BANK_NONE;
_currentTrackLiftHill &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
break;
case TrackElemType::BlockBrakes:
_currentBrakeSpeed2 = kRCT2DefaultBlockBrakeSpeed;
}
_currentTrackCurve = trackPiece | RideConstructionSpecialPieceSelected;
WindowRideConstructionUpdateActiveElements();

View File

@ -455,6 +455,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots
COMPARE_FIELD(Vehicle, target_seat_rotation);
COMPARE_FIELD(Vehicle, BoatLocation.x);
COMPARE_FIELD(Vehicle, BoatLocation.y);
COMPARE_FIELD(Vehicle, BlockBrakeSpeed);
}
void CompareSpriteDataLitter(const Litter& spriteBase, const Litter& spriteCmp, GameStateSpriteChange& changeData) const

View File

@ -573,12 +573,16 @@ GameActions::Result TrackPlaceAction::Execute() const
case TrackElemType::SpinningTunnel:
MapAnimationCreate(MAP_ANIMATION_TYPE_TRACK_SPINNINGTUNNEL, CoordsXYZ{ mapLoc, trackElement->GetBaseZ() });
break;
case TrackElemType::Brakes:
trackElement->SetBrakeClosed(true);
break;
}
if (TrackTypeHasSpeedSetting(_trackType))
{
trackElement->SetBrakeBoosterSpeed(_brakeSpeed);
}
else if (ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS))
if (ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS))
{
trackElement->SetDoorAState(LANDSCAPE_DOOR_CLOSED);
trackElement->SetDoorBState(LANDSCAPE_DOOR_CLOSED);

View File

@ -3977,6 +3977,10 @@ enum : uint16_t
STR_CHEAT_ALLOW_SPECIAL_COLOUR_SCHEMES = 6575,
STR_CHEAT_ALLOW_SPECIAL_COLOUR_SCHEMES_TIP = 6576,
STR_RIDE_CONSTRUCTION_BLOCK_BRAKE_SPEED = 6577,
STR_RIDE_CONSTRUCTION_BLOCK_BRAKE_SPEED_LIMIT_TIP = 6578,
STR_TRACK_DESIGN_BLOCK_BRAKE_SPEED_RESET = 6579,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
/* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings
};

View File

@ -43,7 +43,7 @@
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "9"
#define NETWORK_STREAM_VERSION "10"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION

View File

@ -64,6 +64,8 @@
#include <string_view>
#include <vector>
constexpr const uint32_t BlockBrakeImprovementsVersion = 27;
using namespace OpenRCT2;
namespace OpenRCT2
@ -1092,12 +1094,19 @@ namespace OpenRCT2
else if (it.element->GetType() == TileElementType::Track)
{
auto* trackElement = it.element->AsTrack();
auto trackType = trackElement->GetTrackType();
if (TrackTypeMustBeMadeInvisible(
trackElement->GetRideType(), trackElement->GetTrackType(),
os.GetHeader().TargetVersion))
trackElement->GetRideType(), trackType, os.GetHeader().TargetVersion))
{
it.element->SetInvisible(true);
}
if (os.GetHeader().TargetVersion < BlockBrakeImprovementsVersion)
{
if (trackType == TrackElemType::Brakes)
trackElement->SetBrakeClosed(true);
if (trackType == TrackElemType::BlockBrakes)
trackElement->SetBrakeBoosterSpeed(kRCT2DefaultBlockBrakeSpeed);
}
}
else if (
it.element->GetType() == TileElementType::SmallScenery && os.GetHeader().TargetVersion < 23)
@ -2088,7 +2097,18 @@ namespace OpenRCT2
cs.ReadWrite(entity.scream_sound_id);
cs.ReadWrite(entity.TrackSubposition);
cs.ReadWrite(entity.NumLaps);
cs.ReadWrite(entity.brake_speed);
if (cs.GetMode() == OrcaStream::Mode::READING && os.GetHeader().TargetVersion < BlockBrakeImprovementsVersion)
{
uint8_t brakeSpeed;
cs.ReadWrite(brakeSpeed);
if (entity.GetTrackType() == TrackElemType::BlockBrakes)
brakeSpeed = kRCT2DefaultBlockBrakeSpeed;
entity.brake_speed = brakeSpeed;
}
else
{
cs.ReadWrite(entity.brake_speed);
}
cs.ReadWrite(entity.lost_time_out);
cs.ReadWrite(entity.vertical_drop_countdown);
cs.ReadWrite(entity.var_D3);
@ -2107,6 +2127,14 @@ namespace OpenRCT2
entity.SetFlag(VehicleFlags::Crashed);
}
}
if (cs.GetMode() == OrcaStream::Mode::READING && os.GetHeader().TargetVersion < BlockBrakeImprovementsVersion)
{
entity.BlockBrakeSpeed = kRCT2DefaultBlockBrakeSpeed;
}
else
{
cs.ReadWrite(entity.BlockBrakeSpeed);
}
}
template<> void ParkFile::ReadWriteEntity(OrcaStream& os, OrcaStream::ChunkStream& cs, Guest& guest)

View File

@ -9,10 +9,10 @@ struct ObjectRepositoryItem;
namespace OpenRCT2
{
// Current version that is saved.
constexpr uint32_t PARK_FILE_CURRENT_VERSION = 26;
constexpr uint32_t PARK_FILE_CURRENT_VERSION = 27;
// The minimum version that is forwards compatible with the current version.
constexpr uint32_t PARK_FILE_MIN_VERSION = 26;
constexpr uint32_t PARK_FILE_MIN_VERSION = 27;
// The minimum version that is backwards compatible with the current version.
// If this is increased beyond 0, uncomment the checks in ParkFile.cpp and Context.cpp!

View File

@ -1674,6 +1674,8 @@ namespace RCT1
// Skipping IsHighlighted()
auto trackType = dst2->GetTrackType();
// Brakes import as closed to preserve legacy behaviour
dst2->SetBrakeClosed(trackType == TrackElemType::Brakes);
if (TrackTypeHasSpeedSetting(trackType))
{
dst2->SetBrakeBoosterSpeed(src2->GetBrakeBoosterSpeed());
@ -2817,6 +2819,7 @@ namespace RCT1
{
dst->SetFlag(VehicleFlags::Crashed);
}
dst->BlockBrakeSpeed = kRCT2DefaultBlockBrakeSpeed;
}
template<> void S4Importer::ImportEntity<Guest>(const RCT12EntityBase& srcBase)

View File

@ -1440,11 +1440,17 @@ namespace RCT2
dst2->SetInverted(src2->IsInverted());
dst2->SetStationIndex(StationIndex::FromUnderlying(src2->GetStationIndex()));
dst2->SetHasGreenLight(src2->HasGreenLight());
dst2->SetBrakeClosed(src2->BlockBrakeClosed());
// Brakes import as closed to preserve legacy behaviour
dst2->SetBrakeClosed(src2->BlockBrakeClosed() || (trackType == TrackElemType::Brakes));
dst2->SetIsIndestructible(src2->IsIndestructible());
// Skipping IsHighlighted()
if (TrackTypeHasSpeedSetting(trackType))
// Import block brakes to keep legacy behaviour
if (trackType == TrackElemType::BlockBrakes)
{
dst2->SetBrakeBoosterSpeed(kRCT2DefaultBlockBrakeSpeed);
}
else if (TrackTypeHasSpeedSetting(trackType))
{
dst2->SetBrakeBoosterSpeed(src2->GetBrakeBoosterSpeed());
}
@ -2009,6 +2015,10 @@ namespace RCT2
if (tileElement2 != nullptr)
dst->SetTrackType(TrackElemType::RotationControlToggle);
}
else if (src->GetTrackType() == TrackElemType::BlockBrakes)
{
dst->brake_speed = kRCT2DefaultBlockBrakeSpeed;
}
}
else
{
@ -2075,6 +2085,7 @@ namespace RCT2
{
dst->SetFlag(VehicleFlags::Crashed);
}
dst->BlockBrakeSpeed = kRCT2DefaultBlockBrakeSpeed;
}
static uint32_t AdjustScenarioToCurrentTicks(const S6Data& s6, uint32_t tick)

View File

@ -3050,13 +3050,17 @@ static void RideOpenBlockBrakes(const CoordsXYE& startElement)
auto trackType = currentElement.element->AsTrack()->GetTrackType();
switch (trackType)
{
case TrackElemType::BlockBrakes:
BlockBrakeSetLinkedBrakesClosed(
CoordsXYZ(currentElement.x, currentElement.y, currentElement.element->GetBaseZ()),
*currentElement.element->AsTrack(), false);
[[fallthrough]];
case TrackElemType::EndStation:
case TrackElemType::CableLiftHill:
case TrackElemType::Up25ToFlat:
case TrackElemType::Up60ToFlat:
case TrackElemType::DiagUp25ToFlat:
case TrackElemType::DiagUp60ToFlat:
case TrackElemType::BlockBrakes:
currentElement.element->AsTrack()->SetBrakeClosed(false);
break;
}
@ -3064,6 +3068,60 @@ static void RideOpenBlockBrakes(const CoordsXYE& startElement)
&& currentElement.element != startElement.element);
}
/**
* Set the open status of brakes adjacent to the block brake
*/
void BlockBrakeSetLinkedBrakesClosed(const CoordsXYZ& vehicleTrackLocation, TrackElement& trackElement, bool isClosed)
{
uint8_t brakeSpeed = trackElement.GetBrakeBoosterSpeed();
auto tileElement = reinterpret_cast<TileElement*>(&trackElement);
auto location = vehicleTrackLocation;
TrackBeginEnd trackBeginEnd, slowTrackBeginEnd;
TileElement slowTileElement = *tileElement;
bool counter = true;
CoordsXY slowLocation = location;
do
{
if (!TrackBlockGetPrevious({ location, tileElement }, &trackBeginEnd))
{
return;
}
if (trackBeginEnd.begin_x == vehicleTrackLocation.x && trackBeginEnd.begin_y == vehicleTrackLocation.y
&& tileElement == trackBeginEnd.begin_element)
{
return;
}
location.x = trackBeginEnd.end_x;
location.y = trackBeginEnd.end_y;
location.z = trackBeginEnd.begin_z;
tileElement = trackBeginEnd.begin_element;
if (trackBeginEnd.begin_element->AsTrack()->GetTrackType() == TrackElemType::Brakes)
{
trackBeginEnd.begin_element->AsTrack()->SetBrakeClosed(
(trackBeginEnd.begin_element->AsTrack()->GetBrakeBoosterSpeed() >= brakeSpeed) || isClosed);
}
// prevent infinite loop
counter = !counter;
if (counter)
{
TrackBlockGetPrevious({ slowLocation, &slowTileElement }, &slowTrackBeginEnd);
slowLocation.x = slowTrackBeginEnd.end_x;
slowLocation.y = slowTrackBeginEnd.end_y;
slowTileElement = *(slowTrackBeginEnd.begin_element);
if (slowLocation == location && slowTileElement.GetBaseZ() == tileElement->GetBaseZ()
&& slowTileElement.GetType() == tileElement->GetType()
&& slowTileElement.GetDirection() == tileElement->GetDirection())
{
return;
}
}
} while (trackBeginEnd.begin_element->AsTrack()->GetTrackType() == TrackElemType::Brakes);
}
/**
*
* rct2: 0x006B4D26
@ -3534,7 +3592,8 @@ ResultWithMessage Ride::CreateVehicles(const CoordsXYE& element, bool isApplying
{
CoordsXYE firstBlock{};
RideCreateVehiclesFindFirstBlock(*this, &firstBlock);
MoveTrainsToBlockBrakes(firstBlock.element->AsTrack());
MoveTrainsToBlockBrakes(
{ firstBlock.x, firstBlock.y, firstBlock.element->GetBaseZ() }, *firstBlock.element->AsTrack());
}
else
{
@ -3567,7 +3626,7 @@ ResultWithMessage Ride::CreateVehicles(const CoordsXYE& element, bool isApplying
* preceding that block.
* rct2: 0x006DDF9C
*/
void Ride::MoveTrainsToBlockBrakes(TrackElement* firstBlock)
void Ride::MoveTrainsToBlockBrakes(const CoordsXYZ& firstBlockPosition, TrackElement& firstBlock)
{
for (int32_t i = 0; i < NumTrains; i++)
{
@ -3578,7 +3637,8 @@ void Ride::MoveTrainsToBlockBrakes(TrackElement* firstBlock)
// At this point, all vehicles have state of MovingToEndOfStation, which slowly moves forward at a constant speed
// regardless of incline. The first vehicle stops at the station immediately, while all other vehicles seek forward
// until they reach a closed block brake. The block brake directly before the station is set to closed every frame
// because the trains will open the block brake when the tail leaves the station.
// because the trains will open the block brake when the tail leaves the station. Brakes have no effect at this time, so
// do not set linked brakes when closing the first block.
train->UpdateTrackMotion(nullptr);
if (i == 0)
@ -3597,7 +3657,7 @@ void Ride::MoveTrainsToBlockBrakes(TrackElement* firstBlock)
break;
}
firstBlock->SetBrakeClosed(true);
firstBlock.SetBrakeClosed(true);
for (Vehicle* car = train; car != nullptr; car = GetEntity<Vehicle>(car->next_vehicle_on_train))
{
car->velocity = 0;
@ -3607,8 +3667,13 @@ void Ride::MoveTrainsToBlockBrakes(TrackElement* firstBlock)
}
} while (!(train->UpdateTrackMotion(nullptr) & VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_BLOCK_BRAKE));
// All vehicles are in position, set the block brake directly before the station one last time
firstBlock->SetBrakeClosed(true);
// All vehicles are in position, set the block brake directly before the station one last time and make sure the brakes
// are set appropriately
firstBlock.SetBrakeClosed(true);
if (firstBlock.GetTrackType() == TrackElemType::BlockBrakes)
{
BlockBrakeSetLinkedBrakesClosed(firstBlockPosition, firstBlock, true);
}
for (Vehicle* car = train; car != nullptr; car = GetEntity<Vehicle>(car->next_vehicle_on_train))
{
car->ClearFlag(VehicleFlags::CollisionDisabled);

View File

@ -304,7 +304,7 @@ private:
void Update();
void UpdateQueueLength(StationIndex stationIndex);
ResultWithMessage CreateVehicles(const CoordsXYE& element, bool isApplying);
void MoveTrainsToBlockBrakes(TrackElement* firstBlock);
void MoveTrainsToBlockBrakes(const CoordsXYZ& firstBlockPosition, TrackElement& firstBlock);
money64 CalculateIncomePerHour() const;
void ChainQueues() const;
void ConstructMissingEntranceOrExit() const;
@ -1067,6 +1067,8 @@ money64 RideEntranceExitPlaceGhost(
ResultWithMessage RideAreAllPossibleEntrancesAndExitsBuilt(const Ride& ride);
void RideFixBreakdown(Ride& ride, int32_t reliabilityIncreaseFactor);
void BlockBrakeSetLinkedBrakesClosed(const CoordsXYZ& vehicleTrackLocation, TrackElement& tileElement, bool isOpen);
uint8_t RideEntryGetVehicleAtPosition(int32_t rideEntryIndex, int32_t numCarsPerTrain, int32_t position);
void RideUpdateVehicleColours(const Ride& ride);

View File

@ -655,7 +655,7 @@ bool TrackElementIsCovered(track_type_t trackElementType)
bool TrackTypeHasSpeedSetting(track_type_t trackType)
{
return trackType == TrackElemType::Brakes || trackType == TrackElemType::Booster;
return trackType == TrackElemType::Brakes || trackType == TrackElemType::Booster || trackType == TrackElemType::BlockBrakes;
}
bool TrackTypeIsHelix(track_type_t trackType)

View File

@ -18,7 +18,9 @@
constexpr const uint32_t RideConstructionSpecialPieceSelected = 0x10000;
constexpr const int32_t BLOCK_BRAKE_BASE_SPEED = 0x20364;
constexpr const uint8_t kRCT2DefaultBlockBrakeSpeed = 2;
constexpr const int32_t kBlockBrakeBaseSpeed = 0x20364;
constexpr const int32_t kBlockBrakeSpeedOffset = kBlockBrakeBaseSpeed - (kRCT2DefaultBlockBrakeSpeed << 16);
using track_type_t = uint16_t;
using roll_type_t = uint8_t;

View File

@ -182,6 +182,8 @@ ResultWithMessage TrackDesign::CreateTrackDesignTrack(TrackDesignState& tds, con
return { false, STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY };
}
StringId warningMessage = STR_NONE;
RideGetStartOfTrack(&trackElement);
int32_t z = trackElement.element->GetBaseZ();
@ -222,7 +224,8 @@ ResultWithMessage TrackDesign::CreateTrackDesignTrack(TrackDesignState& tds, con
track.type = trackElement.element->AsTrack()->GetTrackType();
uint8_t trackFlags;
if (TrackTypeHasSpeedSetting(track.type))
// This if-else block only applies to td6. New track design format will always encode speed and seat rotation.
if (TrackTypeHasSpeedSetting(track.type) && track.type != TrackElemType::BlockBrakes)
{
trackFlags = trackElement.element->AsTrack()->GetBrakeBoosterSpeed() >> 1;
}
@ -231,6 +234,13 @@ ResultWithMessage TrackDesign::CreateTrackDesignTrack(TrackDesignState& tds, con
trackFlags = trackElement.element->AsTrack()->GetSeatRotation();
}
// This warning will not apply to new track design format
if (track.type == TrackElemType::BlockBrakes
&& trackElement.element->AsTrack()->GetBrakeBoosterSpeed() != kRCT2DefaultBlockBrakeSpeed)
{
warningMessage = STR_TRACK_DESIGN_BLOCK_BRAKE_SPEED_RESET;
}
if (trackElement.element->AsTrack()->HasChain())
trackFlags |= RCT12_TRACK_ELEMENT_TYPE_FLAG_CHAIN_LIFT;
trackFlags |= trackElement.element->AsTrack()->GetColourScheme() << 4;
@ -349,7 +359,7 @@ ResultWithMessage TrackDesign::CreateTrackDesignTrack(TrackDesignState& tds, con
space_required_x = ((tds.PreviewMax.x - tds.PreviewMin.x) / 32) + 1;
space_required_y = ((tds.PreviewMax.y - tds.PreviewMin.y) / 32) + 1;
return { true };
return { true, warningMessage };
}
ResultWithMessage TrackDesign::CreateTrackDesignMaze(TrackDesignState& tds, const Ride& ride)
@ -1617,7 +1627,17 @@ static GameActions::Result TrackDesignPlaceRide(TrackDesignState& tds, TrackDesi
// di
int16_t tempZ = newCoords.z - trackCoordinates->z_begin;
uint32_t trackColour = (track.flags >> 4) & 0x3;
uint32_t brakeSpeed = (track.flags & 0x0F) * 2;
uint32_t brakeSpeed;
// RCT2-created track designs write brake speed to all tracks; block brake speed must be treated as
// garbage data.
if (trackType == TrackElemType::BlockBrakes)
{
brakeSpeed = kRCT2DefaultBlockBrakeSpeed;
}
else
{
brakeSpeed = (track.flags & 0x0F) * 2;
}
uint32_t seatRotation = track.flags & 0x0F;
int32_t liftHillAndAlternativeState = 0;

View File

@ -6004,15 +6004,14 @@ void Vehicle::ApplyNonStopBlockBrake()
if (velocity >= 0)
{
// If the vehicle is below the speed limit
if (velocity <= BLOCK_BRAKE_BASE_SPEED)
if (velocity <= kBlockBrakeBaseSpeed)
{
// Boost it to the fixed block brake speed
velocity = BLOCK_BRAKE_BASE_SPEED;
velocity = kBlockBrakeBaseSpeed;
acceleration = 0;
}
else
else if (velocity > (brake_speed << 16) + kBlockBrakeSpeedOffset)
{
// Slow it down till the fixed block brake speed
velocity -= velocity >> 4;
acceleration = 0;
}
@ -6185,12 +6184,14 @@ static void block_brakes_open_previous_section(
MapInvalidateElement(location, reinterpret_cast<TileElement*>(trackElement));
auto trackType = trackElement->GetTrackType();
if (trackType == TrackElemType::BlockBrakes || trackType == TrackElemType::EndStation)
if (trackType == TrackElemType::EndStation)
{
if (ride.IsBlockSectioned())
{
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::BlockBrakeClose, location);
}
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::BlockBrakeClose, location);
}
else if (trackType == TrackElemType::BlockBrakes)
{
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::BlockBrakeClose, location);
BlockBrakeSetLinkedBrakesClosed(location, *trackElement, false);
}
}
@ -6981,7 +6982,7 @@ void Vehicle::UpdateLandscapeDoorBackwards() const
static void vehicle_update_play_water_splash_sound()
{
if (_vehicleVelocityF64E08 <= BLOCK_BRAKE_BASE_SPEED)
if (_vehicleVelocityF64E08 <= kBlockBrakeBaseSpeed)
{
return;
}
@ -7377,6 +7378,60 @@ void Vehicle::Sub6DBF3E()
}
}
/**
* Determine whether to use block brake speed or brake speed. If block brake is closed or no block brake present, use the
* brake's speed; if block brake is open, use maximum of brake speed or block brake speed.
*/
uint8_t Vehicle::ChooseBrakeSpeed() const
{
if (GetTrackType() != TrackElemType::Brakes)
return brake_speed;
auto trackElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, GetTrackType(), 0);
if (trackElement != nullptr)
{
if (trackElement->AsTrack()->IsBrakeClosed())
return brake_speed;
else
return std::max<uint8_t>(brake_speed, BlockBrakeSpeed);
}
return brake_speed;
}
/**
* Populate the vehicle's brake_speed and BlockBrakeSpeed values.
*/
void Vehicle::PopulateBrakeSpeed(const CoordsXYZ& vehicleTrackLocation, TrackElement& brake)
{
auto trackSpeed = brake.GetBrakeBoosterSpeed();
brake_speed = trackSpeed;
if (brake.GetTrackType() != TrackElemType::Brakes)
{
BlockBrakeSpeed = trackSpeed;
return;
}
// As soon as feasible, encode block brake speed into track element so the lookforward can be skipped here.
CoordsXYE output = CoordsXYE(vehicleTrackLocation.x, vehicleTrackLocation.y, reinterpret_cast<TileElement*>(&brake));
int32_t outputZ = vehicleTrackLocation.z;
uint16_t timeoutCount = 256;
do
{
if (output.element->AsTrack()->GetTrackType() == TrackElemType::BlockBrakes)
{
BlockBrakeSpeed = output.element->AsTrack()->GetBrakeBoosterSpeed();
return;
}
if (output.element->AsTrack()->GetTrackType() != TrackElemType::Brakes)
{
break;
}
timeoutCount--;
} while (TrackBlockGetNext(&output, &output, &outputZ, nullptr) && timeoutCount);
// If block brake is not found, use the track's speed
BlockBrakeSpeed = trackSpeed;
}
/**
*
* rct2: 0x006DB08C
@ -7413,6 +7468,10 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, const Rid
}
MapInvalidateElement(TrackLocation, tileElement);
block_brakes_open_previous_section(curRide, TrackLocation, tileElement);
if (trackType == TrackElemType::BlockBrakes)
{
BlockBrakeSetLinkedBrakesClosed(TrackLocation, *tileElement->AsTrack(), true);
}
}
}
@ -7542,7 +7601,7 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, const Rid
}
SetTrackDirection(location.direction);
SetTrackType(trackType);
brake_speed = tileElement->AsTrack()->GetBrakeBoosterSpeed();
PopulateBrakeSpeed(TrackLocation, *tileElement->AsTrack());
if (trackType == TrackElemType::OnRidePhoto)
{
trigger_on_ride_photo(TrackLocation, tileElement);
@ -7589,8 +7648,9 @@ Loc6DAEB9:
&& curRide.breakdown_reason_pending == BREAKDOWN_BRAKES_FAILURE;
if (!hasBrakesFailure || curRide.mechanic_status == RIDE_MECHANIC_STATUS_HAS_FIXED_STATION_BRAKES)
{
auto brakeSpeed = brake_speed << 16;
if (brakeSpeed < _vehicleVelocityF64E08)
auto brakeSpeed = ChooseBrakeSpeed();
if ((brakeSpeed << 16) < _vehicleVelocityF64E08)
{
acceleration = -_vehicleVelocityF64E08 * 16;
}
@ -7947,7 +8007,7 @@ bool Vehicle::UpdateTrackMotionBackwardsGetNewTrack(uint16_t trackType, const Ri
direction &= 3;
SetTrackType(trackType);
SetTrackDirection(direction);
brake_speed = tileElement->AsTrack()->GetBrakeBoosterSpeed();
PopulateBrakeSpeed(TrackLocation, *tileElement->AsTrack());
// There are two bytes before the move info list
uint16_t trackTotalProgress = GetTrackProgress();
@ -7978,7 +8038,9 @@ bool Vehicle::UpdateTrackMotionBackwards(const CarEntry* carEntry, const Ride& c
if (trackType == TrackElemType::Brakes)
{
if (-(brake_speed << 16) > _vehicleVelocityF64E08)
auto brakeSpeed = ChooseBrakeSpeed();
if (-(brakeSpeed << 16) > _vehicleVelocityF64E08)
{
acceleration = _vehicleVelocityF64E08 * -16;
}
@ -9400,4 +9462,5 @@ void Vehicle::Serialise(DataSerialiser& stream)
stream << seat_rotation;
stream << target_seat_rotation;
stream << BoatLocation;
stream << BlockBrakeSpeed;
}

View File

@ -210,6 +210,7 @@ struct Vehicle : EntityBase
uint8_t seat_rotation;
uint8_t target_seat_rotation;
CoordsXY BoatLocation;
uint8_t BlockBrakeSpeed;
constexpr bool IsHead() const
{
@ -377,6 +378,8 @@ private:
void UpdateLandscapeDoor() const;
void UpdateLandscapeDoorBackwards() const;
int32_t CalculateRiderBraking() const;
uint8_t ChooseBrakeSpeed() const;
void PopulateBrakeSpeed(const CoordsXYZ& vehicleTrackLocation, TrackElement& brake);
void Loc6DCE02(const Ride& curRide);
};