diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 51ef5249ec..e86b1a69e1 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -9,6 +9,7 @@ - Change: [#24069] [Plugin] Plugins are now available in the scenario editor and track designer. - Change: [#24135] Compress Emscripten js/wasm files. - Change: [#24235] Small changes to RCT1 theme. +- Fix: [#19782] Game stops counting inversions and golf holes after 31. - Fix: [#21207] Track List window gets positioned incorrectly. - Fix: [#21919] Non-recolourable cars still show colour picker. - Fix: [#22182] [Plugin] Crash when using map.getAllEntities("car"). diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 5e28d49df1..41dbfd37e9 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -5683,7 +5683,7 @@ namespace OpenRCT2::Ui::Windows { // Holes ft = Formatter(); - ft.Add(ride->holes); + ft.Add(ride->numHoles); DrawTextBasic(dpi, screenCoords, STR_HOLES, ft); screenCoords.y += kListRowHeight; } @@ -5818,7 +5818,7 @@ namespace OpenRCT2::Ui::Windows if (ride->getRideTypeDescriptor().HasFlag(RtdFlag::hasDrops)) { ft = Formatter(); - ft.Add(ride->getNumDrops()); + ft.Add(ride->numDrops); DrawTextBasic(dpi, screenCoords, STR_DROPS, ft); screenCoords.y += kListRowHeight; @@ -5833,10 +5833,10 @@ namespace OpenRCT2::Ui::Windows if (ride->getRideTypeDescriptor().specialType != RtdSpecialType::miniGolf) { // Inversions - if (ride->inversions != 0) + if (ride->numInversions != 0) { ft = Formatter(); - ft.Add(ride->inversions); + ft.Add(ride->numInversions); DrawTextBasic(dpi, screenCoords, STR_INVERSIONS, ft); screenCoords.y += kListRowHeight; } diff --git a/src/openrct2/Limits.h b/src/openrct2/Limits.h index 907367531b..c2a07a01ab 100644 --- a/src/openrct2/Limits.h +++ b/src/openrct2/Limits.h @@ -8,16 +8,19 @@ *****************************************************************************/ #pragma once + #include "rct2/Limits.h" +#include + namespace OpenRCT2::Limits { constexpr uint16_t kMaxRidesInPark = 1000; constexpr uint16_t kMaxStationsPerRide = 255; constexpr uint8_t kCustomerHistorySize = RCT12::Limits::kCustomerHistorySize; - constexpr uint16_t kMaxGolfHoles = RCT12::Limits::kMaxGolfHoles; - constexpr uint16_t kMaxHelices = RCT12::Limits::kMaxHelices; - constexpr uint16_t kMaxInversions = RCT12::Limits::kMaxInversions; + constexpr uint8_t kMaxGolfHoles = std::numeric_limits::max(); + constexpr uint8_t kMaxHelices = std::numeric_limits::max(); + constexpr uint8_t kMaxInversions = std::numeric_limits::max(); constexpr uint16_t kMaxTrainsPerRide = 255; constexpr uint16_t kMaxCarsPerTrain = 255; constexpr uint16_t kMaxVehicleColours = kMaxTrainsPerRide; // this should really be kMaxTrainsPerRide * @@ -34,4 +37,6 @@ namespace OpenRCT2::Limits constexpr uint16_t kMaxParkEntrances = 256; constexpr uint8_t kMaxWaitingTime = RCT12::Limits::kMaxWaitingTime; constexpr uint8_t kCheatsMaxOperatingLimit = 255; + constexpr uint8_t kRideMaxDropsCount = std::numeric_limits::max(); + constexpr uint8_t kRideMaxNumPoweredLiftsCount = std::numeric_limits::max(); } // namespace OpenRCT2::Limits diff --git a/src/openrct2/core/FlagHolder.hpp b/src/openrct2/core/FlagHolder.hpp index 8b7a780ebc..94fb4ab86c 100644 --- a/src/openrct2/core/FlagHolder.hpp +++ b/src/openrct2/core/FlagHolder.hpp @@ -18,6 +18,11 @@ struct FlagHolder FlagHolder() = default; + explicit FlagHolder(THolderType _holder) + : holder(_holder) + { + } + template constexpr FlagHolder(TTypes... types) : holder(EnumsToFlags(types...)) diff --git a/src/openrct2/park/Legacy.cpp b/src/openrct2/park/Legacy.cpp index bb4f18ca27..ed6858ff4e 100644 --- a/src/openrct2/park/Legacy.cpp +++ b/src/openrct2/park/Legacy.cpp @@ -2987,3 +2987,19 @@ bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, OpenRCT2::TrackElemType return false; } + +std::pair splitCombinedHelicesAndSpecialElements(uint8_t combinedValue) +{ + uint8_t numHelices = combinedValue & 0b00011111; + auto specialElements = SpecialElements(static_cast(combinedValue & ~0b00011111)); + + return std::make_pair(numHelices, specialElements); +} + +std::pair splitCombinedNumDropsPoweredLifts(uint8_t combinedValue) +{ + uint8_t numDrops = combinedValue & 0b00111111; + uint8_t numPoweredLifts = combinedValue >> 6; + + return std::make_pair(numDrops, numPoweredLifts); +} diff --git a/src/openrct2/park/Legacy.h b/src/openrct2/park/Legacy.h index f09e2696e1..f07180b96c 100644 --- a/src/openrct2/park/Legacy.h +++ b/src/openrct2/park/Legacy.h @@ -9,6 +9,7 @@ #pragma once +#include "../core/FlagHolder.hpp" #include "../object/Object.h" #include @@ -36,6 +37,8 @@ namespace OpenRCT2 struct ObjectEntryDescriptor; class ObjectList; using ride_type_t = uint16_t; +enum class SpecialElement : uint8_t; +using SpecialElements = FlagHolder; std::string_view MapToNewObjectIdentifier(std::string_view s); std::optional GetDATPathName(std::string_view newPathName); @@ -62,3 +65,6 @@ std::string_view GetClimateObjectIdFromLegacyClimateType(OpenRCT2::RCT12::Climat * @return */ bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, OpenRCT2::TrackElemType trackType, int32_t parkFileVersion = -1); + +std::pair splitCombinedHelicesAndSpecialElements(uint8_t combinedValue); +std::pair splitCombinedNumDropsPoweredLifts(uint8_t combinedValue); diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index 4dcfb41c64..ac8da037e7 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -1373,7 +1373,7 @@ namespace OpenRCT2 void ReadWriteRidesChunk(GameState_t& gameState, OrcaStream& os) { const auto version = os.GetHeader().TargetVersion; - os.ReadWriteChunk(ParkFileChunkType::RIDES, [this, &version](OrcaStream::ChunkStream& cs) { + os.ReadWriteChunk(ParkFileChunkType::RIDES, [this, &version, &os](OrcaStream::ChunkStream& cs) { std::vector rideIds; if (cs.GetMode() == OrcaStream::Mode::READING) { @@ -1401,7 +1401,7 @@ namespace OpenRCT2 } } } - cs.ReadWriteVector(rideIds, [&cs, &version](RideId& rideId) { + cs.ReadWriteVector(rideIds, [&cs, &version, &os](RideId& rideId) { // Ride ID cs.ReadWrite(rideId); @@ -1548,7 +1548,19 @@ namespace OpenRCT2 } } - cs.ReadWrite(ride.specialTrackElements); + if (os.GetHeader().TargetVersion < kHigherInversionsHolesHelicesStatsVersion) + { + uint8_t combinedValue = cs.Read(); + auto split = splitCombinedHelicesAndSpecialElements(combinedValue); + ride.numHelices = split.first; + ride.specialTrackElements = split.second; + } + else + { + cs.ReadWrite(ride.numHelices); + cs.ReadWrite(ride.specialTrackElements.holder); + } + cs.ReadWrite(ride.maxSpeed); cs.ReadWrite(ride.averageSpeed); cs.ReadWrite(ride.currentTestSegment); @@ -1567,17 +1579,38 @@ namespace OpenRCT2 cs.ReadWrite(ride.turnCountBanked); cs.ReadWrite(ride.turnCountSloped); - cs.ReadWrite(ride.inversions); - cs.ReadWrite(ride.dropsPoweredLifts); + if (version < kHigherInversionsHolesHelicesStatsVersion) + { + uint16_t numInversions = cs.Read(); + ride.numInversions = numInversions; + auto combinedValue = cs.Read(); + auto split = splitCombinedNumDropsPoweredLifts(combinedValue); + ride.numDrops = split.first; + ride.numPoweredLifts = split.second; + } + else + { + cs.ReadWrite(ride.numInversions); + cs.ReadWrite(ride.numDrops); + cs.ReadWrite(ride.numPoweredLifts); + } cs.ReadWrite(ride.startDropHeight); cs.ReadWrite(ride.highestDropHeight); cs.ReadWrite(ride.shelteredLength); cs.ReadWrite(ride.var11C); cs.ReadWrite(ride.numShelteredSections); - if (version > 5) + if (version >= kInversionsHolesShelteredEightsSplit) { cs.ReadWrite(ride.shelteredEighths); - cs.ReadWrite(ride.holes); + if (version < kHigherInversionsHolesHelicesStatsVersion) + { + auto numHoles = cs.Read(); + ride.numHoles = numHoles; + } + else + { + cs.ReadWrite(ride.numHoles); + } } cs.ReadWrite(ride.currentTestStation); cs.ReadWrite(ride.numBlockBrakes); diff --git a/src/openrct2/park/ParkFile.h b/src/openrct2/park/ParkFile.h index 45bdd668c5..4799386e28 100644 --- a/src/openrct2/park/ParkFile.h +++ b/src/openrct2/park/ParkFile.h @@ -20,10 +20,10 @@ namespace OpenRCT2 struct GameState_t; // Current version that is saved. - constexpr uint32_t kParkFileCurrentVersion = 54; + constexpr uint32_t kParkFileCurrentVersion = 55; // The minimum version that is forwards compatible with the current version. - constexpr uint32_t kParkFileMinVersion = 53; + constexpr uint32_t kParkFileMinVersion = 55; // 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! @@ -34,6 +34,7 @@ namespace OpenRCT2 struct IStream; // As uint16_t, in order to allow comparison with int32_t + constexpr uint16_t kInversionsHolesShelteredEightsSplit = 6; constexpr uint16_t kLogFlumeSteepSlopeVersion = 16; constexpr uint16_t kBlockBrakeImprovementsVersion = 27; constexpr uint16_t kGigaCoasterInversions = 31; @@ -51,6 +52,7 @@ namespace OpenRCT2 constexpr uint16_t kEmbeddedParkPreviewChunk = 52; constexpr uint16_t kClimateObjectsVersion = 53; constexpr uint16_t kExtendedGoKartsVersion = 54; + constexpr uint16_t kHigherInversionsHolesHelicesStatsVersion = 55; } // namespace OpenRCT2 class ParkFileExporter diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 21c1b36cb9..dd67eb6b29 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -969,7 +969,9 @@ namespace OpenRCT2::RCT1 dst->proposedNumTrains = src->numTrains; dst->maxTrains = src->maxTrains; dst->proposedNumCarsPerTrain = src->numCarsPerTrain + rideEntry->zero_cars; - dst->specialTrackElements = src->specialTrackElements; + auto split = splitCombinedHelicesAndSpecialElements(src->specialTrackElements); + dst->numHelices = split.first; + dst->specialTrackElements = split.second; dst->numShelteredSections = src->numShelteredSections; dst->shelteredLength = src->shelteredLength; @@ -1055,13 +1057,17 @@ namespace OpenRCT2::RCT1 dst->turnCountBanked = src->turnCountBanked; dst->turnCountDefault = src->turnCountDefault; dst->turnCountSloped = src->turnCountSloped; - dst->dropsPoweredLifts = src->numDrops; + + auto splitDropsLifts = splitCombinedNumDropsPoweredLifts(src->numDrops); + dst->numDrops = splitDropsLifts.first; + dst->numPoweredLifts = splitDropsLifts.second; + dst->startDropHeight = src->startDropHeight / 2; dst->highestDropHeight = src->highestDropHeight / 2; if (src->type == RideType::MiniatureGolf) - dst->holes = src->numInversions & kRCT12InversionAndHoleMask; + dst->numHoles = src->numInversions & kRCT12InversionAndHoleMask; else - dst->inversions = src->numInversions & kRCT12InversionAndHoleMask; + dst->numInversions = src->numInversions & kRCT12InversionAndHoleMask; dst->shelteredEighths = src->numInversions >> 5; dst->boatHireReturnDirection = src->boatHireReturnDirection; dst->boatHireReturnPosition = { src->boatHireReturnPosition.x, src->boatHireReturnPosition.y }; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 767cef9a87..80c691db16 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -850,7 +850,9 @@ namespace OpenRCT2::RCT2 dst->boatHireReturnDirection = src->boatHireReturnDirection; dst->boatHireReturnPosition = { src->boatHireReturnPosition.x, src->boatHireReturnPosition.y }; - dst->specialTrackElements = src->specialTrackElements; + auto split = splitCombinedHelicesAndSpecialElements(src->specialTrackElements); + dst->numHelices = split.first; + dst->specialTrackElements = split.second; // Pad0D6[2]; dst->maxSpeed = src->maxSpeed; @@ -880,11 +882,13 @@ namespace OpenRCT2::RCT2 dst->turnCountBanked = src->turnCountBanked; dst->turnCountSloped = src->turnCountSloped; if (src->type == RIDE_TYPE_MINI_GOLF) - dst->holes = src->inversions & kRCT12InversionAndHoleMask; + dst->numHoles = src->inversions & kRCT12InversionAndHoleMask; else - dst->inversions = src->inversions & kRCT12InversionAndHoleMask; + dst->numInversions = src->inversions & kRCT12InversionAndHoleMask; dst->shelteredEighths = src->inversions >> 5; - dst->dropsPoweredLifts = src->drops; + auto splitDropsLifts = splitCombinedNumDropsPoweredLifts(src->drops); + dst->numDrops = splitDropsLifts.first; + dst->numPoweredLifts = splitDropsLifts.second; dst->startDropHeight = src->startDropHeight; dst->highestDropHeight = src->highestDropHeight; dst->shelteredLength = src->shelteredLength; diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index d4b1257cbb..01b5f82531 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -4567,38 +4567,32 @@ int32_t GetTurnCount4PlusElements(const Ride& ride, uint8_t type) bool Ride::hasSpinningTunnel() const { - return specialTrackElements & RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + return specialTrackElements.has(SpecialElement::spinningTunnel); } bool Ride::hasWaterSplash() const { - return specialTrackElements & RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + return specialTrackElements.has(SpecialElement::splash); } bool Ride::hasRapids() const { - return specialTrackElements & RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + return specialTrackElements.has(SpecialElement::rapids); } bool Ride::hasLogReverser() const { - return specialTrackElements & RIDE_ELEMENT_REVERSER_OR_WATERFALL; + return specialTrackElements.has(SpecialElement::reverser); } bool Ride::hasWaterfall() const { - return specialTrackElements & RIDE_ELEMENT_REVERSER_OR_WATERFALL; + return specialTrackElements.has(SpecialElement::waterfall); } bool Ride::hasWhirlpool() const { - return specialTrackElements & RIDE_ELEMENT_WHIRLPOOL; -} - -uint8_t RideGetHelixSections(const Ride& ride) -{ - // Helix sections stored in the low 5 bits. - return ride.specialTrackElements & 0x1F; + return specialTrackElements.has(SpecialElement::whirlpool); } bool Ride::isPoweredLaunched() const @@ -6015,25 +6009,3 @@ ResultWithMessage Ride::changeStatusCreateVehicles(bool isApplying, const Coords return { true }; } - -uint8_t Ride::getNumDrops() const -{ - return dropsPoweredLifts & kRideNumDropsMask; -} - -void Ride::setNumDrops(uint8_t newValue) -{ - dropsPoweredLifts &= ~kRideNumDropsMask; - dropsPoweredLifts |= (newValue & kRideNumDropsMask); -} - -uint8_t Ride::getNumPoweredLifts() const -{ - return dropsPoweredLifts >> 6; -} - -void Ride::setPoweredLifts(uint8_t newValue) -{ - dropsPoweredLifts &= ~kRideNumPoweredLiftsMask; - dropsPoweredLifts |= (newValue << 6); -} diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index fb22bdc634..92405060ac 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -53,11 +53,6 @@ constexpr uint16_t kMaxStationLocations = OpenRCT2::Limits::kMaxStationsPerRide constexpr uint16_t kMazeClearanceHeight = 4 * kCoordsZStep; -constexpr uint8_t kRideMaxDropsCount = 63; -constexpr uint8_t kRideNumDropsMask = 0b00111111; -constexpr uint8_t kRideMaxNumPoweredLiftsCount = 3; -constexpr uint8_t kRideNumPoweredLiftsMask = 0b11000000; - constexpr money64 kRideMinPrice = 0.00_GBP; constexpr money64 kRideMaxPrice = 20.00_GBP; @@ -133,6 +128,17 @@ struct TrackDesignState; enum class RideMode : uint8_t; enum class RideStatus : uint8_t; +enum class SpecialElement : uint8_t +{ + spinningTunnel = 5, + splash = 5, + rapids = 5, + reverser = 6, + waterfall = 6, + whirlpool = 7, +}; +using SpecialElements = FlagHolder; + /** * Ride structure. * @@ -178,11 +184,8 @@ struct Ride uint8_t boatHireReturnDirection{}; TileCoordsXY boatHireReturnPosition; - // bits 0 through 4 are the number of helix sections - // bit 5: spinning tunnel, water splash, or rapids - // bit 6: log reverser, waterfall - // bit 7: whirlpool - uint8_t specialTrackElements{}; + uint8_t numHelices{}; + SpecialElements specialTrackElements{}; // Use ToHumanReadableSpeed if converting to display int32_t maxSpeed{}; int32_t averageSpeed{}; @@ -202,7 +205,8 @@ struct Ride uint16_t turnCountBanked{}; uint16_t turnCountSloped{}; // X = number turns > 3 elements // Y is number of powered lifts, X is drops - uint8_t dropsPoweredLifts{}; // (YYXX XXXX) + uint8_t numDrops{}; + uint8_t numPoweredLifts{}; uint8_t startDropHeight{}; uint8_t highestDropHeight{}; int32_t shelteredLength{}; @@ -298,13 +302,16 @@ struct Ride uint8_t currentIssues{}; uint32_t lastIssueTime{}; - // TO-DO: those friend functions are temporary, find a way to not access the private fields - friend void updateSpiralSlide(Ride& ride); - friend void updateChairlift(Ride& ride); - private: std::array stations{}; +public: + uint8_t numInversions{}; + uint8_t numHoles{}; + uint8_t shelteredEighths{}; + + std::unique_ptr measurement; + public: RideStation& getStation(StationIndex stationIndex = StationIndex::FromUnderlying(0)); const RideStation& getStation(StationIndex stationIndex = StationIndex::FromUnderlying(0)) const; @@ -316,13 +323,6 @@ public: // in the station array. e.g. if only slot 0 and 2 are in use, index 2 returns 2 instead of 3. StationIndex::UnderlyingType getStationNumber(StationIndex in) const; -public: - uint16_t inversions{}; - uint16_t holes{}; - uint8_t shelteredEighths{}; - - std::unique_ptr measurement; - private: void update(); void updateQueueLength(StationIndex stationIndex); @@ -431,11 +431,9 @@ public: bool findTrackGap(const CoordsXYE& input, CoordsXYE* output) const; - uint8_t getNumDrops() const; - void setNumDrops(uint8_t newValue); - - uint8_t getNumPoweredLifts() const; - void setPoweredLifts(uint8_t newValue); + // TO-DO: those friend functions are temporary, find a way to not access the private fields + friend void updateSpiralSlide(Ride& ride); + friend void updateChairlift(Ride& ride); }; void updateSpiralSlide(Ride& ride); void updateChairlift(Ride& ride); @@ -808,14 +806,6 @@ enum RIDE_MEASUREMENT_FLAG_G_FORCES = 1 << 2 }; -// Constants for ride->specialTrackElements -enum -{ - RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS = 1 << 5, - RIDE_ELEMENT_REVERSER_OR_WATERFALL = 1 << 6, - RIDE_ELEMENT_WHIRLPOOL = 1 << 7 -}; - enum { RIDE_CRASH_TYPE_NONE = 0, @@ -897,8 +887,6 @@ int32_t GetTurnCount2Elements(const Ride& ride, uint8_t type); int32_t GetTurnCount3Elements(const Ride& ride, uint8_t type); int32_t GetTurnCount4PlusElements(const Ride& ride, uint8_t type); -uint8_t RideGetHelixSections(const Ride& ride); - bool RideHasAnyTrackElements(const Ride& ride); bool TrackBlockGetNext(CoordsXYE* input, CoordsXYE* output, int32_t* z, int32_t* direction); diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index 9379c83958..5f7486c4b5 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -1028,7 +1028,7 @@ static void RideRatingsCalculate(RideRatingUpdateState& state, Ride& ride) } // Requirements that may be ignored if the ride has inversions - if (ride.inversions == 0 || !rrd.RelaxRequirementsIfInversions) + if (ride.numInversions == 0 || !rrd.RelaxRequirementsIfInversions) { switch (modifier.type) { @@ -1202,7 +1202,7 @@ static money64 RideComputeUpkeep(RideRatingUpdateState& state, const Ride& ride) auto upkeep = ride.getRideTypeDescriptor().UpkeepCosts.BaseCost; auto trackCost = ride.getRideTypeDescriptor().UpkeepCosts.CostPerTrackPiece; - upkeep += trackCost * ride.getNumPoweredLifts(); + upkeep += trackCost * ride.numPoweredLifts; uint32_t totalLength = ToHumanReadableRideLength(ride.getTotalLength()); @@ -1590,7 +1590,7 @@ static RatingTuple GetSpecialTrackElementsRating(uint8_t type, const Ride& ride) const auto& rtd = ride.getRideTypeDescriptor(); rtd.SpecialElementRatingAdjustment(ride, excitement, intensity, nausea); - uint8_t helixSections = RideGetHelixSections(ride); + auto helixSections = ride.numHelices; int32_t helixesUpTo9 = std::min(helixSections, 9); excitement += (helixesUpTo9 * 254862) >> 16; @@ -1634,7 +1634,7 @@ static RatingTuple ride_ratings_get_turns_ratings(const Ride& ride) intensity += slopedTurnsRating.intensity; nausea += slopedTurnsRating.nausea; - auto inversions = ride.getRideTypeDescriptor().specialType == RtdSpecialType::miniGolf ? ride.holes : ride.inversions; + auto inversions = ride.getRideTypeDescriptor().specialType == RtdSpecialType::miniGolf ? ride.numHoles : ride.numInversions; RatingTuple inversionsRating = get_inversions_ratings(inversions); excitement += inversionsRating.excitement; intensity += inversionsRating.intensity; @@ -1743,7 +1743,7 @@ static RatingTuple ride_ratings_get_drop_ratings(const Ride& ride) }; // Apply number of drops factor - int32_t drops = ride.getNumDrops(); + int32_t drops = ride.numDrops; result.excitement += (std::min(9, drops) * 728177) >> 16; result.intensity += (drops * 928426) >> 16; result.nausea += (drops * 655360) >> 16; @@ -2040,7 +2040,8 @@ static void RideRatingsApplyBonusReversals( static void RideRatingsApplyBonusHoles(RatingTuple& ratings, const Ride& ride, RatingsModifier modifier) { RideRatingsAdd( - ratings, (ride.holes) * modifier.excitement, (ride.holes) * modifier.intensity, (ride.holes) * modifier.nausea); + ratings, (ride.numHoles) * modifier.excitement, (ride.numHoles) * modifier.intensity, + (ride.numHoles) * modifier.nausea); } static void RideRatingsApplyBonusNumTrains(RatingTuple& ratings, const Ride& ride, RatingsModifier modifier) @@ -2136,7 +2137,7 @@ static void RideRatingsApplyRequirementMaxSpeed(RatingTuple& ratings, const Ride static void RideRatingsApplyRequirementNumDrops(RatingTuple& ratings, const Ride& ride, RatingsModifier modifier) { - if (ride.getNumDrops() < modifier.threshold) + if (ride.numDrops < modifier.threshold) { ratings.excitement /= modifier.excitement; ratings.intensity /= modifier.intensity; @@ -2166,7 +2167,7 @@ static void RideRatingsApplyRequirementLateralGs(RatingTuple& ratings, const Rid static void RideRatingsApplyRequirementInversions(RatingTuple& ratings, const Ride& ride, RatingsModifier modifier) { - if (ride.inversions < modifier.threshold) + if (ride.numInversions < modifier.threshold) { ratings.excitement /= modifier.excitement; ratings.intensity /= modifier.intensity; @@ -2198,7 +2199,7 @@ static void RideRatingsApplyRequirementReversals( static void RideRatingsApplyRequirementHoles(RatingTuple& ratings, const Ride& ride, RatingsModifier modifier) { - if (ride.holes < modifier.threshold) + if (ride.numHoles < modifier.threshold) { ratings.excitement /= modifier.excitement; ratings.intensity /= modifier.intensity; @@ -2219,7 +2220,7 @@ static void RideRatingsApplyRequirementStations(RatingTuple& ratings, const Ride static void RideRatingsApplyRequirementSplashdown(RatingTuple& ratings, const Ride& ride, RatingsModifier modifier) { - if (!(ride.specialTrackElements & RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS)) + if (!ride.specialTrackElements.has(SpecialElement::splash)) { ratings.excitement /= modifier.excitement; ratings.intensity /= modifier.intensity; diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 7eab5f0dec..09a4d5ead9 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -157,9 +157,9 @@ ResultWithMessage TrackDesign::CreateTrackDesign(TrackDesignState& tds, const Ri statistics.maxPositiveVerticalG = ride.maxPositiveVerticalG; statistics.maxNegativeVerticalG = ride.maxNegativeVerticalG; statistics.maxLateralG = ride.maxLateralG; - statistics.inversions = ride.inversions; - statistics.holes = ride.holes; - statistics.drops = ride.getNumDrops(); + statistics.inversions = ride.numInversions; + statistics.holes = ride.numHoles; + statistics.drops = ride.numDrops; statistics.highestDropHeight = ride.highestDropHeight; statistics.totalAirTime = ride.totalAirTime; diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 51256caeb2..9a8db2c315 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -808,8 +808,8 @@ void RideUpdateMeasurementsSpecialElements_Default(Ride& ride, const OpenRCT2::T uint16_t trackFlags = ted.flags; if (trackFlags & TRACK_ELEM_FLAG_NORMAL_TO_INVERSION) { - if (ride.inversions < OpenRCT2::Limits::kMaxInversions) - ride.inversions++; + if (ride.numInversions < OpenRCT2::Limits::kMaxInversions) + ride.numInversions++; } } @@ -819,8 +819,8 @@ void RideUpdateMeasurementsSpecialElements_MiniGolf(Ride& ride, const OpenRCT2:: uint16_t trackFlags = ted.flags; if (trackFlags & TRACK_ELEM_FLAG_IS_GOLF_HOLE) { - if (ride.holes < OpenRCT2::Limits::kMaxGolfHoles) - ride.holes++; + if (ride.numHoles < OpenRCT2::Limits::kMaxGolfHoles) + ride.numHoles++; } } @@ -828,7 +828,7 @@ void RideUpdateMeasurementsSpecialElements_WaterCoaster(Ride& ride, const OpenRC { if (trackType >= TrackElemType::FlatCovered && trackType <= TrackElemType::RightQuarterTurn3TilesCovered) { - ride.specialTrackElements |= RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + ride.specialTrackElements.set(SpecialElement::splash); } } @@ -927,12 +927,8 @@ void Vehicle::UpdateMeasurements() if (!(curRide->testingFlags.has(RideTestingFlag::poweredLift))) { curRide->testingFlags.set(RideTestingFlag::poweredLift); - auto numPoweredLifts = curRide->getNumPoweredLifts(); - if (numPoweredLifts < kRideMaxNumPoweredLiftsCount) - { - numPoweredLifts++; - curRide->setPoweredLifts(numPoweredLifts); - } + if (curRide->numPoweredLifts < OpenRCT2::Limits::kRideMaxNumPoweredLiftsCount) + curRide->numPoweredLifts++; } } else @@ -946,20 +942,24 @@ void Vehicle::UpdateMeasurements() switch (trackElemType) { case TrackElemType::Rapids: + curRide->specialTrackElements.set(SpecialElement::rapids); + break; case TrackElemType::SpinningTunnel: - curRide->specialTrackElements |= RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + curRide->specialTrackElements.set(SpecialElement::spinningTunnel); break; case TrackElemType::Waterfall: + curRide->specialTrackElements.set(SpecialElement::waterfall); + break; case TrackElemType::LogFlumeReverser: - curRide->specialTrackElements |= RIDE_ELEMENT_REVERSER_OR_WATERFALL; + curRide->specialTrackElements.set(SpecialElement::reverser); break; case TrackElemType::Whirlpool: - curRide->specialTrackElements |= RIDE_ELEMENT_WHIRLPOOL; + curRide->specialTrackElements.set(SpecialElement::whirlpool); break; case TrackElemType::Watersplash: if (velocity >= 11.0_mph) { - curRide->specialTrackElements |= RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + curRide->specialTrackElements.set(SpecialElement::splash); } default: break; @@ -1064,10 +1064,8 @@ void Vehicle::UpdateMeasurements() curRide->testingFlags.unset(RideTestingFlag::dropUp); curRide->testingFlags.set(RideTestingFlag::dropDown); - uint8_t drops = curRide->getNumDrops(); - if (drops < kRideMaxDropsCount) - drops++; - curRide->setNumDrops(drops); + if (curRide->numDrops < OpenRCT2::Limits::kRideMaxDropsCount) + curRide->numDrops++; curRide->startDropHeight = z / kCoordsZStep; testingFlags.unset(RideTestingFlag::dropUp); @@ -1095,22 +1093,16 @@ void Vehicle::UpdateMeasurements() curRide->testingFlags.unset(RideTestingFlag::dropDown); curRide->testingFlags.set(RideTestingFlag::dropUp); - auto drops = curRide->getNumDrops(); - if (drops != kRideMaxDropsCount) - drops++; - curRide->setNumDrops(drops); + if (curRide->numDrops < OpenRCT2::Limits::kRideMaxDropsCount) + curRide->numDrops++; curRide->startDropHeight = z / kCoordsZStep; } if (trackFlags & TRACK_ELEM_FLAG_HELIX) { - uint8_t helixes = RideGetHelixSections(*curRide); - if (helixes != OpenRCT2::Limits::kMaxHelices) - helixes++; - - curRide->specialTrackElements &= ~0x1F; - curRide->specialTrackElements |= helixes; + if (curRide->numHelices < OpenRCT2::Limits::kMaxHelices) + curRide->numHelices++; } } @@ -2386,15 +2378,17 @@ static void test_reset(Ride& ride, StationIndex curStation) ride.turnCountDefault = 0; ride.turnCountBanked = 0; ride.turnCountSloped = 0; - ride.inversions = 0; - ride.holes = 0; + ride.numInversions = 0; + ride.numHoles = 0; ride.shelteredEighths = 0; - ride.dropsPoweredLifts = 0; + ride.numDrops = 0; + ride.numPoweredLifts = 0; ride.shelteredLength = 0; ride.var11C = 0; ride.numShelteredSections = 0; ride.highestDropHeight = 0; - ride.specialTrackElements = 0; + ride.numHelices = 0; + ride.specialTrackElements.clearAll(); for (auto& station : ride.getStations()) { station.SegmentLength = 0; diff --git a/src/openrct2/scripting/bindings/ride/ScRide.cpp b/src/openrct2/scripting/bindings/ride/ScRide.cpp index 21210b678a..c2bfa6d0fa 100644 --- a/src/openrct2/scripting/bindings/ride/ScRide.cpp +++ b/src/openrct2/scripting/bindings/ride/ScRide.cpp @@ -581,13 +581,13 @@ namespace OpenRCT2::Scripting uint8_t ScRide::numDrops_get() const { auto ride = GetRide(); - return ride != nullptr ? ride->getNumDrops() : 0; + return ride != nullptr ? ride->numDrops : 0; } uint8_t ScRide::numLiftHills_get() const { auto ride = GetRide(); - return ride != nullptr ? ride->getNumPoweredLifts() : 0; + return ride != nullptr ? ride->numPoweredLifts : 0; } double ScRide::highestDropHeight_get() const