mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #18713
This commit is contained in:
commit
5c34d1d7b9
|
@ -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")
|
||||
|
|
|
@ -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 #
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1405,6 +1405,8 @@ public:
|
|||
_currentTrackBankEnd = TRACK_BANK_NONE;
|
||||
_currentTrackLiftHill &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
|
||||
break;
|
||||
case TrackElemType::BlockBrakes:
|
||||
_currentBrakeSpeed2 = kRCT2DefaultBlockBrakeSpeed;
|
||||
}
|
||||
_currentTrackCurve = trackPiece | RideConstructionSpecialPieceSelected;
|
||||
WindowRideConstructionUpdateActiveElements();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue