From 8127437de1701acb41f9b025607026bc33f648f4 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Sun, 19 Apr 2020 13:32:43 +0200 Subject: [PATCH] Reduce direct ride type checking; move available piece lookup to RTD (#11353) --- src/openrct2-ui/windows/Ride.cpp | 8 ++++---- src/openrct2-ui/windows/RideConstruction.cpp | 17 ++++++----------- src/openrct2/actions/TrackPlaceAction.hpp | 8 +++++--- src/openrct2/management/Research.cpp | 16 ---------------- src/openrct2/management/Research.h | 2 -- src/openrct2/ride/RideData.cpp | 15 +++++++++++++++ src/openrct2/ride/RideData.h | 3 +++ src/openrct2/ride/Vehicle.cpp | 5 +++-- .../ride/transport/meta/MiniatureRailway.h | 3 ++- src/openrct2/world/Footpath.cpp | 2 +- src/openrct2/world/Map.cpp | 2 +- test/testpaint/Compat.cpp | 2 ++ 12 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 953fbd6d71..9680149b7c 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -2780,7 +2780,7 @@ static rct_string_id window_ride_get_status_vehicle(rct_window* w, void* argumen || trackType == TRACK_ELEM_25_DEG_UP_TO_FLAT || trackType == TRACK_ELEM_60_DEG_UP_TO_FLAT || trackType == TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT || trackType == TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT) { - if (track_piece_is_available_for_ride_type(ride->type, TRACK_BLOCK_BRAKES) && vehicle->velocity == 0) + if (RideTypeDescriptors[ride->type].SupportsTrackPiece(TRACK_BLOCK_BRAKES) && vehicle->velocity == 0) { *reinterpret_cast(reinterpret_cast(arguments)) = STR_STOPPED_BY_BLOCK_BRAKES; return STR_BLACK_STRING; @@ -3646,10 +3646,10 @@ static void window_ride_operating_invalidate(rct_window* w) | (1ULL << WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX)); // Sometimes, only one of the alternatives support lift hill pieces. Make sure to check both. - bool hasAlternativeType = (RideTypeDescriptors[ride->type].Flags & RIDE_TYPE_FLAG_HAS_ALTERNATIVE_TRACK_TYPE) != 0; - if (track_piece_is_available_for_ride_type(ride->type, TRACK_LIFT_HILL) + bool hasAlternativeType = RideTypeDescriptors[ride->type].HasFlag(RIDE_TYPE_FLAG_HAS_ALTERNATIVE_TRACK_TYPE); + if (RideTypeDescriptors[ride->type].SupportsTrackPiece(TRACK_LIFT_HILL) || (hasAlternativeType - && track_piece_is_available_for_ride_type(RideData4[ride->type].alternate_type, TRACK_LIFT_HILL))) + && RideTypeDescriptors[RideData4[ride->type].alternate_type].SupportsTrackPiece(TRACK_LIFT_HILL))) { window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_LABEL].type = WWT_LABEL; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED].type = WWT_SPINNER; diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 67c44ab027..b3bfb1bf3f 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -1109,7 +1109,7 @@ static void window_ride_construction_resize(rct_window* w) disabledWidgets |= (1ULL << WIDX_SLOPE_UP_STEEP); } disabledWidgets |= (1ULL << WIDX_LEFT_CURVE_LARGE) | (1ULL << WIDX_RIGHT_CURVE_LARGE); - if (rideType == RIDE_TYPE_REVERSE_FREEFALL_COASTER || rideType == RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER) + if (RideTypeDescriptors[ride->type].SupportsTrackPiece(TRACK_REVERSE_FREEFALL)) { disabledWidgets |= (1ULL << WIDX_STRAIGHT) | (1ULL << WIDX_RIGHT_CURVE) | (1ULL << WIDX_RIGHT_CURVE_SMALL) | (1ULL << WIDX_LEFT_CURVE_SMALL) | (1ULL << WIDX_LEFT_CURVE); @@ -1122,7 +1122,7 @@ static void window_ride_construction_resize(rct_window* w) disabledWidgets |= (1ULL << WIDX_SLOPE_DOWN_STEEP); } disabledWidgets |= (1ULL << WIDX_LEFT_CURVE_LARGE) | (1ULL << WIDX_RIGHT_CURVE_LARGE); - if (rideType == RIDE_TYPE_REVERSE_FREEFALL_COASTER || rideType == RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER) + if (RideTypeDescriptors[ride->type].SupportsTrackPiece(TRACK_REVERSE_FREEFALL)) { disabledWidgets |= (1ULL << WIDX_STRAIGHT) | (1ULL << WIDX_RIGHT_CURVE) | (1ULL << WIDX_RIGHT_CURVE_SMALL) | (1ULL << WIDX_LEFT_CURVE_SMALL) | (1ULL << WIDX_LEFT_CURVE); @@ -1433,7 +1433,7 @@ static void window_ride_construction_mousedown(rct_window* w, rct_widgetindex wi { _currentTrackBankEnd = TRACK_BANK_NONE; } - if (ride->type == RIDE_TYPE_REVERSE_FREEFALL_COASTER || ride->type == RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER) + if (RideTypeDescriptors[ride->type].SupportsTrackPiece(TRACK_REVERSE_FREEFALL)) { if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_FRONT && _currentTrackCurve == TRACK_CURVE_NONE) { @@ -2542,20 +2542,15 @@ void window_ride_construction_update_enabled_track_pieces() int32_t rideType = (_currentTrackAlternative & RIDE_TYPE_ALTERNATIVE_TRACK_TYPE) ? RideData4[ride->type].alternate_type : ride->type; - if (gCheatsEnableAllDrawableTrackPieces) - { - _enabledRidePieces = get_available_track_pieces_for_ride_type(rideType); - return; - } - if (RideGroupManager::RideTypeHasRideGroups(rideType)) + if (!gCheatsEnableAllDrawableTrackPieces && RideGroupManager::RideTypeHasRideGroups(rideType)) { const RideGroup* rideGroup = RideGroupManager::GetRideGroup(rideType, rideEntry); _enabledRidePieces = rideGroup->AvailableTrackPieces; } else { - _enabledRidePieces = get_available_track_pieces_for_ride_type(rideType); + _enabledRidePieces = RideTypeDescriptors[rideType].GetAvailableTrackPieces(); } } @@ -2919,7 +2914,7 @@ static void window_ride_construction_update_widgets(rct_window* w) window_ride_construction_widgets[WIDX_SLOPE_DOWN_STEEP].tooltip = STR_RIDE_CONSTRUCTION_STEEP_SLOPE_DOWN_TIP; window_ride_construction_widgets[WIDX_SLOPE_UP_STEEP].image = SPR_RIDE_CONSTRUCTION_SLOPE_UP_STEEP; window_ride_construction_widgets[WIDX_SLOPE_UP_STEEP].tooltip = STR_RIDE_CONSTRUCTION_STEEP_SLOPE_UP_TIP; - if (rideType == RIDE_TYPE_REVERSE_FREEFALL_COASTER || rideType == RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER) + if (RideTypeDescriptors[rideType].SupportsTrackPiece(TRACK_REVERSE_FREEFALL)) { window_ride_construction_widgets[WIDX_LEVEL].type = WWT_FLATBTN; window_ride_construction_widgets[WIDX_SLOPE_UP].type = WWT_FLATBTN; diff --git a/src/openrct2/actions/TrackPlaceAction.hpp b/src/openrct2/actions/TrackPlaceAction.hpp index 42e180e21e..f67ee0039a 100644 --- a/src/openrct2/actions/TrackPlaceAction.hpp +++ b/src/openrct2/actions/TrackPlaceAction.hpp @@ -151,7 +151,7 @@ public: } // Backwards steep lift hills are allowed, even on roller coasters that do not support forwards steep lift hills. if ((_trackPlaceFlags & CONSTRUCTION_LIFT_HILL_SELECTED) - && !track_piece_is_available_for_ride_type(ride->type, TRACK_LIFT_HILL_STEEP) + && !RideTypeDescriptors[ride->type].SupportsTrackPiece(TRACK_LIFT_HILL_STEEP) && !gCheatsEnableChainLiftOnAllTrack) { if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_IS_STEEP_UP) @@ -231,7 +231,8 @@ public: return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_TOO_HIGH); } - uint8_t crossingMode = (ride->type == RIDE_TYPE_MINIATURE_RAILWAY && _trackType == TRACK_ELEM_FLAT) + uint8_t crossingMode = (RideTypeDescriptors[ride->type].HasFlag(RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS) + && _trackType == TRACK_ELEM_FLAT) ? CREATE_CROSSING_MODE_TRACK_OVER_PATH : CREATE_CROSSING_MODE_NONE; if (!map_can_construct_with_clear_at( @@ -469,7 +470,8 @@ public: clearanceZ = floor2(clearanceZ, COORDS_Z_STEP) + baseZ; const auto mapLocWithClearance = CoordsXYRangedZ(mapLoc, baseZ, clearanceZ); - uint8_t crossingMode = (ride->type == RIDE_TYPE_MINIATURE_RAILWAY && _trackType == TRACK_ELEM_FLAT) + uint8_t crossingMode = (RideTypeDescriptors[ride->type].HasFlag(RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS) + && _trackType == TRACK_ELEM_FLAT) ? CREATE_CROSSING_MODE_TRACK_OVER_PATH : CREATE_CROSSING_MODE_NONE; if (!map_can_construct_with_clear_at( diff --git a/src/openrct2/management/Research.cpp b/src/openrct2/management/Research.cpp index 1b907dfb0a..0f7d19bd6b 100644 --- a/src/openrct2/management/Research.cpp +++ b/src/openrct2/management/Research.cpp @@ -572,22 +572,6 @@ bool ride_entry_is_invented(int32_t rideEntryIndex) return _researchedRideEntries[rideEntryIndex]; } -uint64_t get_available_track_pieces_for_ride_type(uint8_t rideType) -{ - uint64_t baseVals = RideTypeDescriptors[rideType].EnabledTrackPieces; - uint64_t extendedVals = 0; - if (gCheatsEnableAllDrawableTrackPieces) - { - extendedVals = RideTypeDescriptors[rideType].ExtraTrackPieces; - } - return baseVals | extendedVals; -} - -bool track_piece_is_available_for_ride_type(uint8_t rideType, int32_t trackType) -{ - return (get_available_track_pieces_for_ride_type(rideType)) & (1ULL << trackType); -} - void ride_type_set_invented(uint32_t rideType) { Guard::Assert(rideType < std::size(_researchedRideTypes), GUARD_LINE); diff --git a/src/openrct2/management/Research.h b/src/openrct2/management/Research.h index ba0bf794b0..f21b705c80 100644 --- a/src/openrct2/management/Research.h +++ b/src/openrct2/management/Research.h @@ -131,8 +131,6 @@ void scenery_set_invented(const ScenerySelection& sceneryItem); void scenery_set_not_invented(const ScenerySelection& sceneryItem); bool ride_type_is_invented(uint32_t rideType); bool ride_entry_is_invented(int32_t rideEntryIndex); -uint64_t get_available_track_pieces_for_ride_type(uint8_t rideType); -bool track_piece_is_available_for_ride_type(uint8_t rideType, int32_t trackType); bool scenery_group_is_invented(int32_t sgIndex); void scenery_group_set_invented(int32_t sgIndex); bool scenery_is_invented(const ScenerySelection& sceneryItem); diff --git a/src/openrct2/ride/RideData.cpp b/src/openrct2/ride/RideData.cpp index 52ecbef9dd..373f967fda 100644 --- a/src/openrct2/ride/RideData.cpp +++ b/src/openrct2/ride/RideData.cpp @@ -19,6 +19,7 @@ #include "RideData.h" +#include "../Cheats.h" #include "../audio/audio.h" #include "../interface/Colour.h" #include "../localisation/Localisation.h" @@ -2505,3 +2506,17 @@ bool RideTypeDescriptor::HasFlag(uint64_t flag) const { return Flags & flag; } + +uint64_t RideTypeDescriptor::GetAvailableTrackPieces() const +{ + if (gCheatsEnableAllDrawableTrackPieces) + { + return EnabledTrackPieces | ExtraTrackPieces; + } + return EnabledTrackPieces; +} + +bool RideTypeDescriptor::SupportsTrackPiece(const uint64_t trackPiece) const +{ + return GetAvailableTrackPieces() & (1ULL << trackPiece); +} diff --git a/src/openrct2/ride/RideData.h b/src/openrct2/ride/RideData.h index dbc61c2248..e17b382822 100644 --- a/src/openrct2/ride/RideData.h +++ b/src/openrct2/ride/RideData.h @@ -99,6 +99,8 @@ struct RideTypeDescriptor uint8_t AvailableBreakdowns; bool HasFlag(uint64_t flag) const; + uint64_t GetAvailableTrackPieces() const; + bool SupportsTrackPiece(const uint64_t trackPiece) const; }; #ifdef _WIN32 @@ -176,6 +178,7 @@ enum ride_type_flags : uint64_t RIDE_TYPE_FLAG_START_CONSTRUCTION_INVERTED = (1ULL << 47), // This is only set on the Flying RC and its alternative type. RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY = (1ULL << 48), + RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS = (1ULL << 49), }; // Set on ride types that have a main colour, additional colour and support colour. diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 73baafb23b..cae03ac285 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -9855,8 +9855,9 @@ void Vehicle::UpdateCrossings() const auto curRide = get_ride(ride); // Many New Element parks have invisible rides hacked into the path. - // Limit path blocking to Miniature Railway to prevent peeps getting stuck everywhere. - if (pathElement && curRide != nullptr && curRide->type == RIDE_TYPE_MINIATURE_RAILWAY) + // Limit path blocking to rides actually supporting level crossings to prevent peeps getting stuck everywhere. + if (pathElement && curRide != nullptr + && RideTypeDescriptors[curRide->type].HasFlag(RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS)) { if (!playedClaxon && !pathElement->IsBlockedByVehicle()) { diff --git a/src/openrct2/ride/transport/meta/MiniatureRailway.h b/src/openrct2/ride/transport/meta/MiniatureRailway.h index 93522142f2..5f8ea17a6b 100644 --- a/src/openrct2/ride/transport/meta/MiniatureRailway.h +++ b/src/openrct2/ride/transport/meta/MiniatureRailway.h @@ -23,7 +23,8 @@ constexpr const RideTypeDescriptor MiniatureRailwayRTD = RIDE_TYPE_FLAG_HAS_DATA_LOGGING | RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS | RIDE_TYPE_FLAG_HAS_VEHICLE_COLOURS | RIDE_TYPE_FLAG_HAS_TRACK | RIDE_TYPE_FLAG_HAS_LARGE_CURVES | RIDE_TYPE_FLAG_SUPPORTS_MULTIPLE_TRACK_COLOUR | RIDE_TYPE_FLAG_ALLOW_MUSIC | RIDE_TYPE_FLAG_HAS_ENTRANCE_EXIT | RIDE_TYPE_FLAG_ALLOW_MORE_VEHICLES_THAN_STATION_FITS | - RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_TRANSPORT_RIDE | RIDE_TYPE_FLAG_SHOW_IN_TRACK_DESIGNER), + RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_TRANSPORT_RIDE | RIDE_TYPE_FLAG_SHOW_IN_TRACK_DESIGNER | + RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS), SET_FIELD(NameConvention, { RIDE_COMPONENT_TYPE_TRAIN, RIDE_COMPONENT_TYPE_TRACK, RIDE_COMPONENT_TYPE_STATION }), SET_FIELD(AvailableBreakdowns, (1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION)), }; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 999a478e8c..2894ed502c 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -2260,5 +2260,5 @@ bool PathElement::IsLevelCrossing(const CoordsXY& coords) const return false; } - return (ride->type == RIDE_TYPE_MINIATURE_RAILWAY); + return RideTypeDescriptors[ride->type].HasFlag(RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS); } diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index b0541fc5f1..e3dbddfc59 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1436,7 +1436,7 @@ static GameActionResult::Ptr map_can_construct_with_clear_at( && tileElement->GetBaseZ() == pos.baseZ && tileElement->AsTrack()->GetTrackType() == TRACK_ELEM_FLAT) { auto ride = get_ride(tileElement->AsTrack()->GetRideIndex()); - if (ride != nullptr && ride->type == RIDE_TYPE_MINIATURE_RAILWAY) + if (ride != nullptr && RideTypeDescriptors[ride->type].HasFlag(RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS)) { continue; } diff --git a/test/testpaint/Compat.cpp b/test/testpaint/Compat.cpp index 75dbbc1aaf..f41b14cab2 100644 --- a/test/testpaint/Compat.cpp +++ b/test/testpaint/Compat.cpp @@ -28,6 +28,8 @@ class StationObject; #define gTileElementTilePointers RCT2_ADDRESS(0x013CE9A4, TileElement*) rct_sprite* sprite_list = RCT2_ADDRESS(0x010E63BC, rct_sprite); +bool gCheatsEnableAllDrawableTrackPieces = false; + Ride gRideList[MAX_RIDES]; int16_t gMapSizeUnits; int16_t gMapBaseZ;