From aea88b7320216778ad648105ed1aea79a3658753 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 5 Feb 2021 12:53:03 +0200 Subject: [PATCH 1/2] Fix #13997: Placing track design influences clients ride construction --- src/openrct2/ride/TrackDesign.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 035305a266..13f97ced49 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -1623,7 +1623,7 @@ static GameActions::Result TrackDesignPlaceRide(TrackDesignState& tds, TrackDesi } auto trackPlaceAction = TrackPlaceAction( - _currentRideIndex, trackType, ride->type, { newCoords, tempZ, static_cast(rotation) }, brakeSpeed, + ride->id, trackType, ride->type, { newCoords, tempZ, static_cast(rotation) }, brakeSpeed, trackColour, seatRotation, liftHillAndAlternativeState, true); trackPlaceAction.SetFlags(flags); @@ -1843,6 +1843,8 @@ static GameActions::Result TrackDesignPlaceVirtual( tds.PlaceScenery = false; } + // NOTE: We need to save this, in networked games this would affect all clients otherwise. + auto savedRideId = _currentRideIndex; _currentRideIndex = ride->id; GameActions::Result trackPlaceRes; @@ -1854,6 +1856,7 @@ static GameActions::Result TrackDesignPlaceVirtual( { trackPlaceRes = TrackDesignPlaceRide(tds, td6, coords, ride); } + _currentRideIndex = savedRideId; if (trackPlaceRes.Error != GameActions::Status::Ok) { From 0b9184b99b2d1d46bff8c1cbb338559fce7c6b3a Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 10 May 2022 22:39:00 +0100 Subject: [PATCH 2/2] Avoid overwriting _currentTrackPieceDirection when placing TD --- distribution/changelog.txt | 1 + src/openrct2-ui/windows/TrackDesignPlace.cpp | 15 +++++++----- src/openrct2/actions/TrackDesignAction.cpp | 1 - src/openrct2/ride/TrackDesign.cpp | 25 ++++++++++++-------- src/openrct2/ride/TrackDesign.h | 8 +++---- 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index e6f4063956..d1afb12e2a 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -9,6 +9,7 @@ - Improved: [#17059] Show Tile Inspector usage hint when nothing is selected. - Change: [#16952] Make “Object Selection” order more coherent. - Removed: [#16864] Title sequence editor (replaced by plug-in). +- Fix: [#13997] Placing a track design interferes with other players building a ride. - Fix: [#16934] Park size displayed incorrectly in Park window. - Fix: [#16974] Small scenery ghosts can be deleted. - Fix: [#17005] Unable to set patrol area for first staff member in park. diff --git a/src/openrct2-ui/windows/TrackDesignPlace.cpp b/src/openrct2-ui/windows/TrackDesignPlace.cpp index 0469b24c3f..91d2e08901 100644 --- a/src/openrct2-ui/windows/TrackDesignPlace.cpp +++ b/src/openrct2-ui/windows/TrackDesignPlace.cpp @@ -162,7 +162,8 @@ public: // Check if tool map position has changed since last update if (mapCoords == _placementLoc) { - TrackDesignPreviewDrawOutlines(tds, _trackDesign.get(), GetOrAllocateRide(PreviewRideId), { mapCoords, 0 }); + TrackDesignPreviewDrawOutlines( + tds, _trackDesign.get(), GetOrAllocateRide(PreviewRideId), { mapCoords, 0, _currentTrackPieceDirection }); return; } @@ -170,7 +171,7 @@ public: // Get base Z position mapZ = GetBaseZ(mapCoords); - CoordsXYZ trackLoc = { mapCoords, mapZ }; + CoordsXYZD trackLoc = { mapCoords, mapZ, _currentTrackPieceDirection }; if (game_is_not_paused() || gCheatsBuildInPauseMode) { @@ -180,7 +181,7 @@ public: if (res.Error == GameActions::Status::Ok) { // Valid location found. Place the ghost at the location. - auto tdAction = TrackDesignAction({ trackLoc, _currentTrackPieceDirection }, *_trackDesign); + auto tdAction = TrackDesignAction(trackLoc, *_trackDesign); tdAction.SetFlags(GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST); tdAction.SetCallback([&](const GameAction*, const GameActions::Result* result) { if (result->Error == GameActions::Status::Ok) @@ -327,7 +328,7 @@ public: { if (_hasPlacementGhost) { - auto tdAction = TrackDesignAction({ _placementGhostLoc, _currentTrackPieceDirection }, *_trackDesign); + auto tdAction = TrackDesignAction({ _placementGhostLoc }, *_trackDesign); tdAction.SetFlags(GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST); auto res = GameActions::Execute(&tdAction); if (res.Error != GameActions::Status::Ok) @@ -382,7 +383,7 @@ private: RideId _placementGhostRideId; bool _hasPlacementGhost; money32 _placementCost; - CoordsXYZ _placementGhostLoc; + CoordsXYZD _placementGhostLoc; std::vector _miniPreview; @@ -421,7 +422,9 @@ private: if (surfaceElement->GetWaterHeight() > 0) z = std::max(z, surfaceElement->GetWaterHeight()); - return z + TrackDesignGetZPlacement(_trackDesign.get(), GetOrAllocateRide(PreviewRideId), { loc, z }); + return z + + TrackDesignGetZPlacement( + _trackDesign.get(), GetOrAllocateRide(PreviewRideId), { loc, z, _currentTrackPieceDirection }); } void DrawMiniPreviewTrack(TrackDesign* td6, int32_t pass, const CoordsXY& origin, CoordsXY min, CoordsXY max) diff --git a/src/openrct2/actions/TrackDesignAction.cpp b/src/openrct2/actions/TrackDesignAction.cpp index c8e96d60e8..a2b9d35712 100644 --- a/src/openrct2/actions/TrackDesignAction.cpp +++ b/src/openrct2/actions/TrackDesignAction.cpp @@ -55,7 +55,6 @@ GameActions::Result TrackDesignAction::Query() const res.Position.y = _loc.y + 16; res.Position.z = _loc.z; res.Expenditure = ExpenditureType::RideConstruction; - _currentTrackPieceDirection = _loc.direction; if (!LocationValid(_loc)) { diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 13f97ced49..22b4d1a214 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -315,7 +315,7 @@ rct_string_id TrackDesign::CreateTrackDesignTrack(TrackDesignState& tds, const R } } - TrackDesignPreviewDrawOutlines(tds, this, GetOrAllocateRide(PreviewRideId), { 4096, 4096, 0 }); + TrackDesignPreviewDrawOutlines(tds, this, GetOrAllocateRide(PreviewRideId), { 4096, 4096, 0, _currentTrackPieceDirection }); // Resave global vars for scenery reasons. tds.Origin = startPos; @@ -434,7 +434,7 @@ rct_string_id TrackDesign::CreateTrackDesignMaze(TrackDesignState& tds, const Ri // Save global vars as they are still used by scenery???? int32_t startZ = tds.Origin.z; - TrackDesignPreviewDrawOutlines(tds, this, GetOrAllocateRide(PreviewRideId), { 4096, 4096, 0 }); + TrackDesignPreviewDrawOutlines(tds, this, GetOrAllocateRide(PreviewRideId), { 4096, 4096, 0, _currentTrackPieceDirection }); tds.Origin = { startLoc.x, startLoc.y, startZ }; gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT; @@ -1821,7 +1821,7 @@ static GameActions::Result TrackDesignPlaceRide(TrackDesignState& tds, TrackDesi * rct2: 0x006D01B3 */ static GameActions::Result TrackDesignPlaceVirtual( - TrackDesignState& tds, TrackDesign* td6, uint8_t ptdOperation, bool placeScenery, Ride* ride, const CoordsXYZ& coords) + TrackDesignState& tds, TrackDesign* td6, uint8_t ptdOperation, bool placeScenery, Ride* ride, const CoordsXYZD& coords) { _trackDesignPlaceStateSceneryUnavailable = false; _trackDesignPlaceStateEntranceExitPlaced = false; @@ -1845,7 +1845,9 @@ static GameActions::Result TrackDesignPlaceVirtual( // NOTE: We need to save this, in networked games this would affect all clients otherwise. auto savedRideId = _currentRideIndex; + auto savedTrackPieceDirection = _currentTrackPieceDirection; _currentRideIndex = ride->id; + _currentTrackPieceDirection = coords.direction; GameActions::Result trackPlaceRes; if (td6->type == RIDE_TYPE_MAZE) @@ -1857,6 +1859,7 @@ static GameActions::Result TrackDesignPlaceVirtual( trackPlaceRes = TrackDesignPlaceRide(tds, td6, coords, ride); } _currentRideIndex = savedRideId; + _currentTrackPieceDirection = savedTrackPieceDirection; if (trackPlaceRes.Error != GameActions::Status::Ok) { @@ -1885,7 +1888,7 @@ static GameActions::Result TrackDesignPlaceVirtual( return res; } -GameActions::Result TrackDesignPlace(TrackDesign* td6, uint32_t flags, bool placeScenery, Ride* ride, const CoordsXYZ& coords) +GameActions::Result TrackDesignPlace(TrackDesign* td6, uint32_t flags, bool placeScenery, Ride* ride, const CoordsXYZD& coords) { uint32_t ptdOperation = (flags & GAME_COMMAND_FLAG_APPLY) != 0 ? PTD_OPERATION_PLACE : PTD_OPERATION_PLACE_QUERY; if ((flags & GAME_COMMAND_FLAG_APPLY) != 0 && (flags & GAME_COMMAND_FLAG_GHOST) != 0) @@ -1899,18 +1902,18 @@ GameActions::Result TrackDesignPlace(TrackDesign* td6, uint32_t flags, bool plac return TrackDesignPlaceVirtual(tds, td6, ptdOperation, placeScenery, ride, coords); } -void TrackDesignPreviewRemoveGhosts(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords) +void TrackDesignPreviewRemoveGhosts(TrackDesign* td6, Ride* ride, const CoordsXYZD& coords) { TrackDesignState tds{}; TrackDesignPlaceVirtual(tds, td6, PTD_OPERATION_REMOVE_GHOST, true, ride, coords); } -void TrackDesignPreviewDrawOutlines(TrackDesignState& tds, TrackDesign* td6, Ride* ride, const CoordsXYZ& coords) +void TrackDesignPreviewDrawOutlines(TrackDesignState& tds, TrackDesign* td6, Ride* ride, const CoordsXYZD& coords) { TrackDesignPlaceVirtual(tds, td6, PTD_OPERATION_DRAW_OUTLINES, true, ride, coords); } -static int32_t TrackDesignGetZPlacement(TrackDesignState& tds, TrackDesign* td6, Ride* ride, const CoordsXYZ& coords) +static int32_t TrackDesignGetZPlacement(TrackDesignState& tds, TrackDesign* td6, Ride* ride, const CoordsXYZD& coords) { TrackDesignPlaceVirtual(tds, td6, PTD_OPERATION_GET_PLACE_Z, true, ride, coords); @@ -1919,7 +1922,7 @@ static int32_t TrackDesignGetZPlacement(TrackDesignState& tds, TrackDesign* td6, return tds.PlaceZ - tds.PlaceSceneryZ; } -int32_t TrackDesignGetZPlacement(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords) +int32_t TrackDesignGetZPlacement(TrackDesign* td6, Ride* ride, const CoordsXYZD& coords) { TrackDesignState tds{}; return TrackDesignGetZPlacement(tds, td6, ride, coords); @@ -2004,7 +2007,8 @@ static bool TrackDesignPlacePreview(TrackDesignState& tds, TrackDesign* td6, mon auto mapSize = TileCoordsXY{ gMapSize.x * 16, gMapSize.y * 16 }; _currentTrackPieceDirection = 0; - int32_t z = TrackDesignGetZPlacement(tds, td6, GetOrAllocateRide(PreviewRideId), { mapSize.x, mapSize.y, 16 }); + int32_t z = TrackDesignGetZPlacement( + tds, td6, GetOrAllocateRide(PreviewRideId), { mapSize.x, mapSize.y, 16, _currentTrackPieceDirection }); if (tds.HasScenery) { @@ -2021,7 +2025,8 @@ static bool TrackDesignPlacePreview(TrackDesignState& tds, TrackDesign* td6, mon } auto res = TrackDesignPlaceVirtual( - tds, td6, PTD_OPERATION_PLACE_TRACK_PREVIEW, placeScenery, ride, { mapSize.x, mapSize.y, z }); + tds, td6, PTD_OPERATION_PLACE_TRACK_PREVIEW, placeScenery, ride, + { mapSize.x, mapSize.y, z, _currentTrackPieceDirection }); gParkFlags = backup_park_flags; if (res.Error == GameActions::Status::Ok) diff --git a/src/openrct2/ride/TrackDesign.h b/src/openrct2/ride/TrackDesign.h index fb50db872a..be4967501a 100644 --- a/src/openrct2/ride/TrackDesign.h +++ b/src/openrct2/ride/TrackDesign.h @@ -222,10 +222,10 @@ extern RideId gTrackDesignSaveRideIndex; void TrackDesignMirror(TrackDesign* td6); -GameActions::Result TrackDesignPlace(TrackDesign* td6, uint32_t flags, bool placeScenery, Ride* ride, const CoordsXYZ& coords); -void TrackDesignPreviewRemoveGhosts(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords); -void TrackDesignPreviewDrawOutlines(TrackDesignState& tds, TrackDesign* td6, Ride* ride, const CoordsXYZ& coords); -int32_t TrackDesignGetZPlacement(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords); +GameActions::Result TrackDesignPlace(TrackDesign* td6, uint32_t flags, bool placeScenery, Ride* ride, const CoordsXYZD& coords); +void TrackDesignPreviewRemoveGhosts(TrackDesign* td6, Ride* ride, const CoordsXYZD& coords); +void TrackDesignPreviewDrawOutlines(TrackDesignState& tds, TrackDesign* td6, Ride* ride, const CoordsXYZD& coords); +int32_t TrackDesignGetZPlacement(TrackDesign* td6, Ride* ride, const CoordsXYZD& coords); /////////////////////////////////////////////////////////////////////////////// // Track design preview