From 3bb71b8195f68aacf506dc141a519603369ca313 Mon Sep 17 00:00:00 2001 From: Spacek531 Date: Sat, 18 Jan 2025 16:03:37 -0800 Subject: [PATCH] Track Archetype Proof-Of-Concept --- src/openrct2-ui/windows/RideConstruction.cpp | 24 +++--- .../actions/RideSetColourSchemeAction.cpp | 9 ++- .../actions/TrackSetBrakeSpeedAction.cpp | 7 +- src/openrct2/rct2/S6Importer.cpp | 5 +- src/openrct2/ride/CableLift.cpp | 6 +- src/openrct2/ride/Ride.cpp | 15 ++-- src/openrct2/ride/RideConstruction.cpp | 25 +++--- src/openrct2/ride/Track.cpp | 79 ++++++++++++++++++- src/openrct2/ride/Track.h | 18 ++++- src/openrct2/ride/TrackDesign.cpp | 6 +- src/openrct2/ride/Vehicle.cpp | 38 ++++++--- .../bindings/ride/ScTrackIterator.cpp | 8 +- src/openrct2/world/Map.cpp | 68 +++++++++++++++- src/openrct2/world/Map.h | 13 ++- src/openrct2/world/TileInspector.cpp | 8 +- .../world/tile_element/TrackElement.h | 3 +- 16 files changed, 266 insertions(+), 66 deletions(-) diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 518e05e6c582..bc5a2f5bd312 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -2351,7 +2351,8 @@ namespace OpenRCT2::Ui::Windows Direction currentDirection = _currentTrackPieceDirection; OpenRCT2::TrackElemType type = _currentTrackPieceType; auto newCoords = GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(direction & 3) }, type, 0, &tileElement, 0); + { _currentTrackBegin, static_cast(direction & 3) }, GetSimplifiedTrackType(type), + GetTrackArchetype(type), 0, &tileElement, 0); if (!newCoords.has_value()) { WindowRideConstructionUpdateActiveElements(); @@ -2382,7 +2383,8 @@ namespace OpenRCT2::Ui::Windows direction = _currentTrackPieceDirection; type = _currentTrackPieceType; newCoords = GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(direction & 3) }, type, 0, &tileElement, 0); + { _currentTrackBegin, static_cast(direction & 3) }, GetSimplifiedTrackType(type), + GetTrackArchetype(type), 0, &tileElement, 0); if (!newCoords.has_value()) { @@ -2510,8 +2512,9 @@ namespace OpenRCT2::Ui::Windows TileElement* tileElement; if (GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, _currentTrackPieceType, 0, - &tileElement, 0) + { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, + GetSimplifiedTrackType(_currentTrackPieceType), GetTrackArchetype(_currentTrackPieceType), 0, &tileElement, + 0) != std::nullopt) { auto trackSetBrakeSpeed = TrackSetBrakeSpeedAction( @@ -2565,8 +2568,9 @@ namespace OpenRCT2::Ui::Windows void RideSelectedTrackSetSeatRotation(int32_t seatRotation) { GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, _currentTrackPieceType, - seatRotation, nullptr, TRACK_ELEMENT_SET_SEAT_ROTATION); + { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, + GetSimplifiedTrackType(_currentTrackPieceType), GetTrackArchetype(_currentTrackPieceType), seatRotation, + nullptr, TRACK_ELEMENT_SET_SEAT_ROTATION); WindowRideConstructionUpdateActiveElements(); } @@ -3089,8 +3093,9 @@ namespace OpenRCT2::Ui::Windows { TileElement* tileElement; if (GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, _currentTrackPieceType, 0, - &tileElement, 0) + { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, + GetSimplifiedTrackType(_currentTrackPieceType), GetTrackArchetype(_currentTrackPieceType), 0, &tileElement, + 0) != std::nullopt) { _selectedTrackType = tileElement->AsTrack()->GetTrackType(); @@ -3212,7 +3217,8 @@ namespace OpenRCT2::Ui::Windows uint16_t flags = _currentTrackSelectionFlags & TRACK_SELECTION_FLAG_ARROW ? TRACK_ELEMENT_SET_HIGHLIGHT_TRUE : TRACK_ELEMENT_SET_HIGHLIGHT_FALSE; auto newCoords = GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(direction) }, type, 0, nullptr, flags); + { _currentTrackBegin, static_cast(direction) }, GetSimplifiedTrackType(type), + GetTrackArchetype(type), 0, nullptr, flags); if (!newCoords.has_value()) { RideConstructionRemoveGhosts(); diff --git a/src/openrct2/actions/RideSetColourSchemeAction.cpp b/src/openrct2/actions/RideSetColourSchemeAction.cpp index 4f8bdb478f2e..31ba37da64b2 100644 --- a/src/openrct2/actions/RideSetColourSchemeAction.cpp +++ b/src/openrct2/actions/RideSetColourSchemeAction.cpp @@ -54,7 +54,8 @@ GameActions::Result RideSetColourSchemeAction::Query() const return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_SET_COLOUR_SCHEME, STR_OFF_EDGE_OF_MAP); } // Find the relevant track piece, prefer sequence 0 (logic copied from GetTrackElementOriginAndApplyChanges) - auto trackElement = MapGetTrackElementAtOfTypeSeq(_loc, _trackType, 0); + auto trackElement = MapGetTrackElementAtOfTypeSeqArchetype( + _loc, GetSimplifiedTrackType(_trackType), GetTrackArchetype(_trackType), 0); if (trackElement == nullptr) { trackElement = MapGetTrackElementAtOfType(_loc, _trackType); @@ -77,8 +78,10 @@ GameActions::Result RideSetColourSchemeAction::Execute() const GameActions::Result res = GameActions::Result(); res.Expenditure = ExpenditureType::RideConstruction; res.ErrorTitle = STR_CANT_SET_COLOUR_SCHEME; - - GetTrackElementOriginAndApplyChanges(_loc, _trackType, _newColourScheme, nullptr, TRACK_ELEMENT_SET_COLOUR_SCHEME); + // TODO: Update this after proof-of-concept + GetTrackElementOriginAndApplyChanges( + _loc, GetSimplifiedTrackType(_trackType), GetTrackArchetype(_trackType), _newColourScheme, nullptr, + TRACK_ELEMENT_SET_COLOUR_SCHEME); return res; } diff --git a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp index 3fc18438535a..32a04955aed6 100644 --- a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp +++ b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp @@ -64,7 +64,8 @@ GameActions::Result TrackSetBrakeSpeedAction::QueryExecute(bool isExecuting) con return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_CHANGE_THIS, STR_OFF_EDGE_OF_MAP); } - TileElement* tileElement = MapGetTrackElementAtOfType(_loc, _trackType); + TileElement* tileElement = MapGetTrackElementAtOfTypeArchetype( + _loc, GetSimplifiedTrackType(_trackType), GetTrackArchetype(_trackType)); if (tileElement == nullptr) { LOG_ERROR("Track element of type %u not found at x = %d, y = %d, z = %d", _trackType, _loc.x, _loc.y, _loc.z); @@ -80,8 +81,10 @@ GameActions::Result TrackSetBrakeSpeedAction::QueryExecute(bool isExecuting) con if (isExecuting) { + // TODO: Update this after proof-of-concept GetTrackElementOriginAndApplyChanges( - { _loc, tileElement->GetDirection() }, tileElement->AsTrack()->GetTrackType(), _brakeSpeed, nullptr, + { _loc, tileElement->GetDirection() }, GetSimplifiedTrackType(tileElement->AsTrack()->GetTrackType()), + GetTrackArchetype(tileElement->AsTrack()->GetTrackType()), _brakeSpeed, nullptr, TRACK_ELEMENT_SET_BRAKE_BOOSTER_SPEED); } return res; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 3f3b960d8aae..d76cbcbf06b0 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1950,8 +1950,9 @@ namespace OpenRCT2::RCT2 // ride is on. It's possible to create unwanted behavior if a user layers spinning control track on top of // booster track but this is unlikely since only two rides have spinning control track - by default they load as // booster. - TileElement* tileElement2 = MapGetTrackElementAtOfTypeSeq( - dst->TrackLocation, TrackElemType::RotationControlToggle, 0); + TileElement* tileElement2 = MapGetTrackElementAtOfTypeSeqArchetype( + dst->TrackLocation, GetSimplifiedTrackType(TrackElemType::RotationControlToggle), GetTrackArchetype(TrackElemType::RotationControlToggle), + 0); if (tileElement2 != nullptr) dst->SetTrackType(TrackElemType::RotationControlToggle); diff --git a/src/openrct2/ride/CableLift.cpp b/src/openrct2/ride/CableLift.cpp index 7b410a018577..44614eacf5b8 100644 --- a/src/openrct2/ride/CableLift.cpp +++ b/src/openrct2/ride/CableLift.cpp @@ -249,7 +249,8 @@ bool Vehicle::CableLiftUpdateTrackMotionForwards() uint16_t trackTotalProgress = GetTrackProgress(); if (trackProgress >= trackTotalProgress) { - TileElement* trackElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, trackType, 0); + TileElement* trackElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0); CoordsXYE output; int32_t outputZ; @@ -312,7 +313,8 @@ bool Vehicle::CableLiftUpdateTrackMotionBackwards() if (static_cast(trackProgress) == -1) { auto trackType = GetTrackType(); - TileElement* trackElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, trackType, 0); + TileElement* trackElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0); auto input = CoordsXYE{ TrackLocation, trackElement }; TrackBeginEnd output; diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 77b41badd067..3e26d19cd2f0 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -2985,7 +2985,8 @@ static void RideSetBoatHireReturnPoint(Ride& ride, const CoordsXYE& startElement int32_t direction = trackBeginEnd.begin_direction; trackType = trackBeginEnd.begin_element->AsTrack()->GetTrackType(); auto newCoords = GetTrackElementOriginAndApplyChanges( - { trackCoords, static_cast(direction) }, trackType, 0, &returnPos.element, 0); + { trackCoords, static_cast(direction) }, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), + 0, &returnPos.element, 0); returnPos = newCoords.has_value() ? CoordsXYE{ newCoords.value(), returnPos.element } : CoordsXYE{ trackCoords, returnPos.element }; }; @@ -3056,7 +3057,8 @@ void SetBrakeClosedMultiTile(TrackElement& trackElement, const CoordsXY& trackLo case TrackElemType::DiagBrakes: case TrackElemType::DiagBlockBrakes: GetTrackElementOriginAndApplyChanges( - { trackLocation, trackElement.GetBaseZ(), trackElement.GetDirection() }, trackElement.GetTrackType(), isClosed, + { trackLocation, trackElement.GetBaseZ(), trackElement.GetDirection() }, + GetSimplifiedTrackType(trackElement.GetTrackType()), GetTrackArchetype(trackElement.GetTrackType()), isClosed, nullptr, TRACK_ELEMENT_SET_BRAKE_CLOSED_STATE); break; default: @@ -3074,6 +3076,7 @@ static void RideOpenBlockBrakes(const CoordsXYE& startElement) do { auto trackType = currentElement.element->AsTrack()->GetTrackType(); + // TODO: Update this after proof-of-concept switch (trackType) { case TrackElemType::BlockBrakes: @@ -3541,8 +3544,9 @@ static void RideCreateVehiclesFindFirstBlock(const Ride& ride, CoordsXYE* outXYE [[fallthrough]]; case TrackElemType::DiagBlockBrakes: { - TileElement* tileElement = MapGetTrackElementAtOfTypeSeq( - { trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }, trackType, 0); + TileElement* tileElement = MapGetTrackElementAtOfTypeSeqArchetype( + { trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }, GetSimplifiedTrackType(trackType), + GetTrackArchetype(trackType), 0); if (tileElement != nullptr) { @@ -3859,7 +3863,8 @@ static ResultWithMessage RideInitialiseCableLiftTrack(const Ride& ride, bool isA auto tmpLoc = CoordsXYZ{ it.current, tileElement->GetBaseZ() }; auto direction = tileElement->GetDirection(); trackType = tileElement->AsTrack()->GetTrackType(); - GetTrackElementOriginAndApplyChanges({ tmpLoc, direction }, trackType, 0, &tileElement, flags); + GetTrackElementOriginAndApplyChanges( + { tmpLoc, direction }, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0, &tileElement, flags); } } return { true }; diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index e97cc55fc04a..754248adc5e9 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -377,14 +377,14 @@ void RideClearBlockedTiles(const Ride& ride) * bp : flags */ std::optional GetTrackElementOriginAndApplyChanges( - const CoordsXYZD& location, OpenRCT2::TrackElemType type, uint16_t extra_params, TileElement** output_element, - uint16_t flags) + const CoordsXYZD& location, OpenRCT2::TrackElemType type, OpenRCT2::TrackArchetype archetype, uint16_t extra_params, + TileElement** output_element, uint16_t flags) { // Find the relevant track piece, prefer sequence 0 (this ensures correct behaviour for diagonal track pieces) - auto trackElement = MapGetTrackElementAtOfTypeSeq(location, type, 0); + auto trackElement = MapGetTrackElementAtOfTypeSeqArchetype(location, type, archetype, 0); if (trackElement == nullptr) { - trackElement = MapGetTrackElementAtOfType(location, type); + trackElement = MapGetTrackElementAtOfTypeArchetype(location, type, archetype); if (trackElement == nullptr) { return std::nullopt; @@ -423,7 +423,8 @@ std::optional GetTrackElementOriginAndApplyChanges( MapInvalidateTileFull(cur); - trackElement = MapGetTrackElementAtOfTypeSeq({ cur, cur_z, static_cast(location.direction) }, type, i); + trackElement = MapGetTrackElementAtOfTypeSeqArchetype( + { cur, cur_z, static_cast(location.direction) }, type, archetype, i); if (trackElement == nullptr) { return std::nullopt; @@ -502,8 +503,9 @@ void RideConstructionInvalidateCurrentTrack() { case RideConstructionState::Selected: GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, _currentTrackPieceType, 0, - nullptr, TRACK_ELEMENT_SET_HIGHLIGHT_FALSE); + { _currentTrackBegin, static_cast(_currentTrackPieceDirection & 3) }, + GetSimplifiedTrackType(_currentTrackPieceType), GetTrackArchetype(_currentTrackPieceType), 0, nullptr, + TRACK_ELEMENT_SET_HIGHLIGHT_FALSE); break; case RideConstructionState::MazeBuild: case RideConstructionState::MazeMove: @@ -707,7 +709,8 @@ void RideSelectNextSection() auto type = _currentTrackPieceType; TileElement* tileElement; auto newCoords = GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(direction & 3) }, type, 0, &tileElement, 0); + { _currentTrackBegin, static_cast(direction & 3) }, GetSimplifiedTrackType(type), + GetTrackArchetype(type), 0, &tileElement, 0); if (!newCoords.has_value()) { _rideConstructionState = RideConstructionState::State0; @@ -765,7 +768,8 @@ void RideSelectPreviousSection() auto type = _currentTrackPieceType; TileElement* tileElement; auto newCoords = GetTrackElementOriginAndApplyChanges( - { _currentTrackBegin, static_cast(direction & 3) }, type, 0, &tileElement, 0); + { _currentTrackBegin, static_cast(direction & 3) }, GetSimplifiedTrackType(type), + GetTrackArchetype(type), 0, &tileElement, 0); if (newCoords == std::nullopt) { _rideConstructionState = RideConstructionState::State0; @@ -980,7 +984,8 @@ bool RideModify(const CoordsXYE& input) auto tileCoords = CoordsXYZ{ tileElement, tileElement.element->GetBaseZ() }; auto direction = tileElement.element->GetDirection(); auto type = tileElement.element->AsTrack()->GetTrackType(); - auto newCoords = GetTrackElementOriginAndApplyChanges({ tileCoords, direction }, type, 0, nullptr, 0); + auto newCoords = GetTrackElementOriginAndApplyChanges( + { tileCoords, direction }, GetSimplifiedTrackType(type), GetTrackArchetype(type), 0, nullptr, 0); if (!newCoords.has_value()) return false; diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index baa640f62128..1ac92d081319 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -566,7 +566,9 @@ TrackElement* TrackGetPreviousBlock(CoordsXYZ& location, TileElement* tileElemen // Get the start of the track block instead of the end location = { trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }; - auto trackOrigin = MapGetTrackElementAtOfTypeSeq(location, trackBeginEnd.begin_element->AsTrack()->GetTrackType(), 0); + auto trackOrigin = MapGetTrackElementAtOfTypeSeqArchetype( + location, GetSimplifiedTrackType(trackBeginEnd.begin_element->AsTrack()->GetTrackType()), GetTrackArchetype(trackBeginEnd.begin_element->AsTrack()->GetTrackType()), + 0); if (trackOrigin == nullptr) { return nullptr; @@ -778,3 +780,78 @@ std::optional GetTrackSegmentOrigin(const CoordsXYE& posEl) return CoordsXYZD(coords, direction); } + +TrackArchetype GetTrackArchetype(TrackElemType trackType) +{ + TrackArchetype archetype; + archetype = TrackArchetype::normal; + if (TrackTypeIsBrakes(trackType)) + archetype = TrackArchetype::brake; + if (TrackTypeIsBlockBrakes(trackType)) + archetype = TrackArchetype::blockBrake; + if (TrackTypeIsBooster(trackType)) + archetype = TrackArchetype::booster; + if (TrackElementIsCovered(trackType)) + archetype = static_cast(EnumValue(archetype) + EnumValue(TrackArchetype::covered)); + + return archetype; +} + +TrackElemType GetSimplifiedTrackType(TrackElemType trackType) +{ + switch (trackType) + { + case TrackElemType::Booster: + case TrackElemType::Brakes: + case TrackElemType::BlockBrakes: + case TrackElemType::FlatCovered: + return TrackElemType::Flat; + + case TrackElemType::DiagBooster: + case TrackElemType::DiagBrakes: + case TrackElemType::DiagBlockBrakes: + return TrackElemType::DiagFlat; + + case TrackElemType::Down25Brakes: + case TrackElemType::Down25Covered: + return TrackElemType::Down25; + + case TrackElemType::Up25Covered: + return TrackElemType::Up25; + case TrackElemType::Up60Covered: + return TrackElemType::Up60; + case TrackElemType::FlatToUp25Covered: + return TrackElemType::FlatToUp25; + case TrackElemType::Up25ToUp60Covered: + return TrackElemType::Up25ToUp60; + case TrackElemType::Up60ToUp25Covered: + return TrackElemType::Up60ToUp25; + case TrackElemType::Up25ToFlatCovered: + return TrackElemType::Up25ToFlat; + case TrackElemType::Down60Covered: + return TrackElemType::Down60; + case TrackElemType::FlatToDown25Covered: + return TrackElemType::FlatToDown25; + case TrackElemType::Down25ToDown60Covered: + return TrackElemType::Down25ToDown60; + case TrackElemType::Down60ToDown25Covered: + return TrackElemType::Down60ToDown25; + case TrackElemType::Down25ToFlatCovered: + return TrackElemType::Down25ToFlat; + case TrackElemType::LeftQuarterTurn5TilesCovered: + return TrackElemType::LeftQuarterTurn5Tiles; + case TrackElemType::RightQuarterTurn5TilesCovered: + return TrackElemType::RightQuarterTurn5Tiles; + case TrackElemType::SBendLeftCovered: + return TrackElemType::SBendLeft; + case TrackElemType::SBendRightCovered: + return TrackElemType::SBendRight; + case TrackElemType::LeftQuarterTurn3TilesCovered: + return TrackElemType::LeftQuarterTurn3Tiles; + case TrackElemType::RightQuarterTurn3TilesCovered: + return TrackElemType::RightQuarterTurn3Tiles; + + default: + return trackType; + } +} diff --git a/src/openrct2/ride/Track.h b/src/openrct2/ride/Track.h index 7efff552896f..5cf27c8eddda 100644 --- a/src/openrct2/ride/Track.h +++ b/src/openrct2/ride/Track.h @@ -619,7 +619,16 @@ namespace OpenRCT2 None = 65535, }; -} + + enum class TrackArchetype : uint8_t + { + normal = 0, + brake = 1, + booster = 2, + blockBrake = 3, + covered = 8, + }; +} // namespace OpenRCT2 enum { @@ -725,8 +734,8 @@ bool TrackTypeIsBlockBrakes(OpenRCT2::TrackElemType trackType); bool TrackTypeIsBooster(OpenRCT2::TrackElemType trackType); std::optional GetTrackElementOriginAndApplyChanges( - const CoordsXYZD& location, OpenRCT2::TrackElemType type, uint16_t extra_params, TileElement** output_element, - uint16_t flags); + const CoordsXYZD& location, OpenRCT2::TrackElemType type, OpenRCT2::TrackArchetype, uint16_t extra_params, + TileElement** output_element, uint16_t flags); TrackRoll TrackGetActualBank(TileElement* tileElement, TrackRoll bank); TrackRoll TrackGetActualBank2(ride_type_t rideType, bool isInverted, TrackRoll bank); @@ -738,3 +747,6 @@ ResultWithMessage TrackRemoveStationElement(const CoordsXYZD& loc, RideId rideIn bool TrackTypeHasSpeedSetting(OpenRCT2::TrackElemType trackType); bool TrackTypeIsHelix(OpenRCT2::TrackElemType trackType); std::optional GetTrackSegmentOrigin(const CoordsXYE& posEl); + +OpenRCT2::TrackArchetype GetTrackArchetype(OpenRCT2::TrackElemType trackType); +OpenRCT2::TrackElemType GetSimplifiedTrackType(OpenRCT2::TrackElemType trackType); diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 42fbf78e245f..e8dc06c58d9c 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -195,7 +195,8 @@ ResultWithMessage TrackDesign::CreateTrackDesignTrack(TrackDesignState& tds, con uint8_t direction = trackElement.element->GetDirection(); _saveDirection = direction; auto newCoords = GetTrackElementOriginAndApplyChanges( - { trackElement, z, direction }, trackType, 0, &trackElement.element, 0); + { trackElement, z, direction }, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0, + &trackElement.element, 0); if (!newCoords.has_value()) { @@ -257,7 +258,8 @@ ResultWithMessage TrackDesign::CreateTrackDesignTrack(TrackDesignState& tds, con direction = trackElement.element->GetDirection(); trackType = trackElement.element->AsTrack()->GetTrackType(); newCoords = GetTrackElementOriginAndApplyChanges( - { trackElement, z, direction }, trackType, 0, &trackElement.element, 0); + { trackElement, z, direction }, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0, + &trackElement.element, 0); if (!newCoords.has_value()) { diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index be6de68fecde..253b4f3c4aa4 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -2397,6 +2397,7 @@ void Vehicle::TestReset() // Therefore, it will return true if anything is amiss. bool Vehicle::CurrentTowerElementIsTop() { + // I don't think this check needs updating to archetype. That would be a *very* obscure hack. TileElement* tileElement = MapGetTrackElementAtOfType(TrackLocation, GetTrackType()); if (tileElement == nullptr) return true; @@ -5508,7 +5509,8 @@ void Vehicle::CheckAndApplyBlockSectionStopSite() auto trackType = GetTrackType(); - TileElement* trackElement = MapGetTrackElementAtOfType(TrackLocation, trackType); + TileElement* trackElement = MapGetTrackElementAtOfTypeArchetype( + TrackLocation, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType)); if (trackElement == nullptr) { @@ -5621,7 +5623,9 @@ static void block_brakes_open_previous_section( // Get the start of the track block instead of the end location = { trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }; - auto trackOrigin = MapGetTrackElementAtOfTypeSeq(location, trackBeginEnd.begin_element->AsTrack()->GetTrackType(), 0); + auto trackOrigin = MapGetTrackElementAtOfTypeSeqArchetype( + location, GetSimplifiedTrackType(trackBeginEnd.begin_element->AsTrack()->GetTrackType()), GetTrackArchetype(trackBeginEnd.begin_element->AsTrack()->GetTrackType()), + 0); if (trackOrigin == nullptr) { return; @@ -6016,9 +6020,7 @@ void Vehicle::UpdateAnimationAnimalFlying() if (animation_frame == 0) { - auto trackType = GetTrackType(); - TileElement* trackElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, trackType, 0); - if (trackElement != nullptr && trackElement->AsTrack()->HasChain()) + if (HasFlag(VehicleFlags::OnLiftHill)) { // start flapping, bird animation_frame = 1; @@ -6764,7 +6766,8 @@ void Vehicle::Sub6DBF3E() TileElement* tileElement = nullptr; if (MapIsLocationValid(TrackLocation)) { - tileElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, trackType, 0); + tileElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0); } if (tileElement == nullptr) @@ -6840,7 +6843,8 @@ uint8_t Vehicle::ChooseBrakeSpeed() const { if (!TrackTypeIsBrakes(GetTrackType())) return brake_speed; - auto trackElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, GetTrackType(), 0); + auto trackElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(GetTrackType()), GetTrackArchetype(GetTrackType()), 0); if (trackElement != nullptr) { if (trackElement->AsTrack()->IsBrakeClosed()) @@ -6896,7 +6900,8 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack( CoordsXYZD location = {}; auto pitchAndRollEnd = TrackPitchAndRollEnd(trackType); - TileElement* tileElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, trackType, 0); + TileElement* tileElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0); if (tileElement == nullptr) { @@ -7330,7 +7335,8 @@ static PitchAndRoll PitchAndRollEnd( bool Vehicle::UpdateTrackMotionBackwardsGetNewTrack(TrackElemType trackType, const Ride& curRide, uint16_t* progress) { auto pitchAndRollStart = TrackPitchAndRollStart(trackType); - TileElement* tileElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, trackType, 0); + TileElement* tileElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(trackType), GetTrackArchetype(trackType), 0); if (tileElement == nullptr) return false; @@ -7852,7 +7858,8 @@ void Vehicle::UpdateTrackMotionMiniGolfVehicle(const Ride& curRide, const RideOb uint16_t trackTotalProgress = GetTrackProgress(); if (track_progress + 1 >= trackTotalProgress) { - tileElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, GetTrackType(), 0); + tileElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(GetTrackType()), GetTrackArchetype(GetTrackType()), 0); { CoordsXYE output; int32_t outZ{}; @@ -8047,7 +8054,8 @@ void Vehicle::UpdateTrackMotionMiniGolfVehicle(const Ride& curRide, const RideOb Loc6DCA9A: if (track_progress == 0) { - tileElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, GetTrackType(), 0); + tileElement = MapGetTrackElementAtOfTypeSeqArchetype( + TrackLocation, GetSimplifiedTrackType(GetTrackType()), GetTrackArchetype(GetTrackType()), 0); { TrackBeginEnd trackBeginEnd; if (!TrackBlockGetPrevious({ TrackLocation, tileElement }, &trackBeginEnd)) @@ -8744,7 +8752,9 @@ void Vehicle::UpdateCrossings() const int32_t direction{}; CoordsXYE xyElement = { frontVehicle->TrackLocation, - MapGetTrackElementAtOfTypeSeq(frontVehicle->TrackLocation, frontVehicle->GetTrackType(), 0) }; + MapGetTrackElementAtOfTypeSeqArchetype( + frontVehicle->TrackLocation, GetSimplifiedTrackType(frontVehicle->GetTrackType()), GetTrackArchetype(frontVehicle->GetTrackType()), + 0) }; int32_t curZ = frontVehicle->TrackLocation.z; if (xyElement.element != nullptr && status != Vehicle::Status::Arriving) @@ -8812,7 +8822,9 @@ void Vehicle::UpdateCrossings() const } xyElement = { backVehicle->TrackLocation, - MapGetTrackElementAtOfTypeSeq(backVehicle->TrackLocation, backVehicle->GetTrackType(), 0) }; + MapGetTrackElementAtOfTypeSeqArchetype( + backVehicle->TrackLocation, GetSimplifiedTrackType(backVehicle->GetTrackType()), GetTrackArchetype(backVehicle->GetTrackType()), + 0) }; if (xyElement.element == nullptr) { return; diff --git a/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp b/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp index 93283e907dcb..197283b25c98 100644 --- a/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp +++ b/src/openrct2/scripting/bindings/ride/ScTrackIterator.cpp @@ -78,7 +78,7 @@ DukValue ScTrackIterator::previousPosition_get() const const auto& seq0 = ted.sequences[0].clearance; auto pos = _position + CoordsXYZ(seq0.x, seq0.y, seq0.z); - auto el = MapGetTrackElementAtOfTypeSeq(pos, _type, 0); + auto el = MapGetTrackElementAtOfTypeSeqArchetype(pos, GetSimplifiedTrackType(_type), GetTrackArchetype(_type), 0); if (el == nullptr) return ToDuk(ctx, nullptr); @@ -98,7 +98,7 @@ DukValue ScTrackIterator::nextPosition_get() const const auto& seq0 = ted.sequences[0].clearance; auto pos = _position + CoordsXYZ(seq0.x, seq0.y, seq0.z); - auto el = MapGetTrackElementAtOfTypeSeq(pos, _type, 0); + auto el = MapGetTrackElementAtOfTypeSeqArchetype(pos, GetSimplifiedTrackType(_type), GetTrackArchetype(_type), 0); if (el == nullptr) return ToDuk(ctx, nullptr); @@ -117,7 +117,7 @@ bool ScTrackIterator::previous() const auto& seq0 = ted.sequences[0].clearance; auto pos = _position + CoordsXYZ(seq0.x, seq0.y, seq0.z); - auto el = MapGetTrackElementAtOfTypeSeq(pos, _type, 0); + auto el = MapGetTrackElementAtOfTypeSeqArchetype(pos, GetSimplifiedTrackType(_type), GetTrackArchetype(_type), 0); if (el == nullptr) return false; @@ -143,7 +143,7 @@ bool ScTrackIterator::next() const auto& seq0 = ted.sequences[0].clearance; auto pos = _position + CoordsXYZ(seq0.x, seq0.y, seq0.z); - auto el = MapGetTrackElementAtOfTypeSeq(pos, _type, 0); + auto el = MapGetTrackElementAtOfTypeSeqArchetype(pos, GetSimplifiedTrackType(_type), GetTrackArchetype(_type), 0); if (el == nullptr) return false; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index cc1a0efd5498..c378542758a1 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1929,13 +1929,43 @@ TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, OpenRCT2::Tra return nullptr; } +/** + * Gets the track element at x, y, z that is the given track type. + * @param x x units, not tiles. + * @param y y units, not tiles. + * @param z Base height. + */ +TileElement* MapGetTrackElementAtOfTypeArchetype(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype) +{ + TileElement* tileElement = MapGetFirstElementAt(trackPos); + if (tileElement == nullptr) + return nullptr; + auto trackTilePos = TileCoordsXYZ{ trackPos }; + do + { + if (tileElement->GetType() != TileElementType::Track) + continue; + if (tileElement->BaseHeight != trackTilePos.z) + continue; + if (GetSimplifiedTrackType(tileElement->AsTrack()->GetTrackType()) != trackType) + continue; + if (GetTrackArchetype(tileElement->AsTrack()->GetTrackType()) != archetype) + continue; + + return tileElement; + } while (!(tileElement++)->IsLastForTile()); + + return nullptr; +} + /** * Gets the track element at x, y, z that is the given track type and sequence. * @param x x units, not tiles. * @param y y units, not tiles. * @param z Base height. */ -TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, int32_t sequence) +TileElement* MapGetTrackElementAtOfTypeSeqArchetype( + const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype, int32_t sequence) { TileElement* tileElement = MapGetFirstElementAt(trackPos); auto trackTilePos = TileCoordsXYZ{ trackPos }; @@ -1947,10 +1977,12 @@ TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, OpenRCT2:: continue; if (tileElement->BaseHeight != trackTilePos.z) continue; - if (tileElement->AsTrack()->GetTrackType() != trackType) + if (GetSimplifiedTrackType(tileElement->AsTrack()->GetTrackType()) != trackType) continue; if (tileElement->AsTrack()->GetSequenceIndex() != sequence) continue; + if (GetTrackArchetype(tileElement->AsTrack()->GetTrackType()) != archetype) + continue; return tileElement; } while (!(tileElement++)->IsLastForTile()); @@ -1981,7 +2013,7 @@ TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, OpenRCT2::T return nullptr; } -TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, int32_t sequence) +TrackElement* MapGetTrackElementAtOfTypeArchetype(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype) { auto tileElement = MapGetFirstElementAt(location); if (tileElement != nullptr) @@ -1995,10 +2027,38 @@ TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, OpenRCT2 continue; if (trackElement->GetDirection() != location.direction) continue; - if (trackElement->GetTrackType() != trackType) + if (GetSimplifiedTrackType(tileElement->AsTrack()->GetTrackType()) != trackType) + continue; + if (GetTrackArchetype(tileElement->AsTrack()->GetTrackType()) != archetype) + continue; + return trackElement; + } + } while (!(tileElement++)->IsLastForTile()); + } + return nullptr; +} + +TrackElement* MapGetTrackElementAtOfTypeSeqArchetype( + const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype, int32_t sequence) +{ + auto tileElement = MapGetFirstElementAt(location); + if (tileElement != nullptr) + { + do + { + auto trackElement = tileElement->AsTrack(); + if (trackElement != nullptr) + { + if (trackElement->GetBaseZ() != location.z) + continue; + if (trackElement->GetDirection() != location.direction) + continue; + if (GetSimplifiedTrackType(tileElement->AsTrack()->GetTrackType()) != trackType) continue; if (trackElement->GetSequenceIndex() != sequence) continue; + if (GetTrackArchetype(tileElement->AsTrack()->GetTrackType()) != archetype) + continue; return trackElement; } } while (!(tileElement++)->IsLastForTile()); diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 72c6df576104..d42bf14c86ef 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -61,7 +61,8 @@ enum class TileElementType : uint8_t; namespace OpenRCT2 { enum class TrackElemType : uint16_t; -} + enum class TrackArchetype : uint8_t; +} // namespace OpenRCT2 struct CoordsXYE : public CoordsXY { @@ -241,9 +242,15 @@ std::optional MapLargeSceneryGetOrigin( TrackElement* MapGetTrackElementAt(const CoordsXYZ& trackPos); TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType); -TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, int32_t sequence); +TileElement* MapGetTrackElementAtOfTypeArchetype( + const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype); +TileElement* MapGetTrackElementAtOfTypeSeqArchetype( + const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype, int32_t sequence); TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType); -TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, int32_t sequence); +TrackElement* MapGetTrackElementAtOfTypeArchetype( + const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype); +TrackElement* MapGetTrackElementAtOfTypeSeqArchetype( + const CoordsXYZD& location, OpenRCT2::TrackElemType trackType, OpenRCT2::TrackArchetype archetype, int32_t sequence); TileElement* MapGetTrackElementAtOfTypeFromRide(const CoordsXYZ& trackPos, OpenRCT2::TrackElemType trackType, RideId rideIndex); TileElement* MapGetTrackElementAtFromRide(const CoordsXYZ& trackPos, RideId rideIndex); TileElement* MapGetTrackElementAtWithDirectionFromRide(const CoordsXYZD& trackPos, RideId rideIndex); diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 843e74dc3bf9..e9fc5461b7d3 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -42,6 +42,8 @@ TileCoordsXY windowTileInspectorTile; int32_t windowTileInspectorElementCount = 0; int32_t windowTileInspectorSelectedIndex = -1; +using TrackArchetype = uint8_t; + using namespace OpenRCT2::TrackMetaData; namespace OpenRCT2::TileInspector @@ -753,7 +755,8 @@ namespace OpenRCT2::TileInspector offsets.y = trackBlock2.y; elem += offsets.Rotate(originDirection); - TrackElement* nextTrackElement = MapGetTrackElementAtOfTypeSeq(elem, type, i); + TrackElement* nextTrackElement = MapGetTrackElementAtOfTypeSeqArchetype( + elem, GetSimplifiedTrackType(type), GetTrackArchetype(type), i); if (nextTrackElement == nullptr) { LOG_ERROR("Track map element part not found!"); @@ -835,7 +838,8 @@ namespace OpenRCT2::TileInspector offsets.y = trackBlock2.y; elem += offsets.Rotate(originDirection); - TrackElement* nextTrackElement = MapGetTrackElementAtOfTypeSeq(elem, type, i); + TrackElement* nextTrackElement = MapGetTrackElementAtOfTypeSeqArchetype( + elem, GetSimplifiedTrackType(type), GetTrackArchetype(type), i); if (nextTrackElement == nullptr) { LOG_ERROR("Track map element part not found!"); diff --git a/src/openrct2/world/tile_element/TrackElement.h b/src/openrct2/world/tile_element/TrackElement.h index 75f6a0328920..c5a4f4440fa0 100644 --- a/src/openrct2/world/tile_element/TrackElement.h +++ b/src/openrct2/world/tile_element/TrackElement.h @@ -18,7 +18,8 @@ enum class RideColourScheme : uint8_t; namespace OpenRCT2 { enum class TrackElemType : uint16_t; -} + enum class TrackArchetype : uint8_t; +} // namespace OpenRCT2 enum {