diff --git a/distribution/changelog.txt b/distribution/changelog.txt index cb9e7a68bf..3e7b876559 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -13,6 +13,7 @@ - Fix: [#11126] Cannot place Frightmare track design. - Fix: [#11208] Cannot export parks with RCT2 DLC objects. - Fix: [#11230] Seat Rotation not imported correctly for hacked rides. +- Fix: [#11225] Replay manager cannot handle track designs. - Fix: Small red gardens in RCT1 saves are imported in the wrong colour. - Improved: [#11157] Slimmer virtual floor lines. diff --git a/src/openrct2/actions/TrackDesignAction.cpp b/src/openrct2/actions/TrackDesignAction.cpp index 9d1b3c9d7a..f3707ed59e 100644 --- a/src/openrct2/actions/TrackDesignAction.cpp +++ b/src/openrct2/actions/TrackDesignAction.cpp @@ -211,7 +211,10 @@ GameActionResult::Ptr TrackDesignAction::Execute() const { operation = PTD_OPERATION_PLACE; } - + if (GetFlags() & GAME_COMMAND_FLAG_REPLAY) + { + operation |= PTD_OPERATION_FLAG_IS_REPLAY; + } cost = place_virtual_track(_td, operation, placeScenery, ride, _loc); } diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index a00fec9c70..c01cdfca7a 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -91,6 +91,7 @@ static bool _trackDesignPlaceStateEntranceExitPlaced = false; bool _trackDesignPlaceStateSceneryUnavailable = false; static bool _trackDesignPlaceStateHasScenery = false; static bool _trackDesignPlaceStatePlaceScenery = true; +static bool _trackDesignPlaceIsReplay = false; static map_backup* track_design_preview_backup_map(); @@ -1036,7 +1037,10 @@ static bool TrackDesignPlaceSceneryElement( { flags = GAME_COMMAND_FLAG_PATH_SCENERY; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } gGameCommandErrorTitle = STR_CANT_POSITION_THIS_HERE; auto smallSceneryPlace = SmallSceneryPlaceAction( @@ -1081,12 +1085,15 @@ static bool TrackDesignPlaceSceneryElement( { flags = GAME_COMMAND_FLAG_PATH_SCENERY; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } auto sceneryPlaceAction = LargeSceneryPlaceAction( { mapCoord.x, mapCoord.y, z, rotation }, entry_index, scenery.primary_colour, scenery.secondary_colour); sceneryPlaceAction.SetFlags(flags); - auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::Execute(&sceneryPlaceAction) - : GameActions::Query(&sceneryPlaceAction); + auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&sceneryPlaceAction) + : GameActions::QueryNested(&sceneryPlaceAction); cost = res->Cost; break; @@ -1121,7 +1128,10 @@ static bool TrackDesignPlaceSceneryElement( { flags = 0; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } auto wallPlaceAction = WallPlaceAction( entry_index, { mapCoord.x, mapCoord.y, z }, rotation, scenery.primary_colour, scenery.secondary_colour, (scenery.flags & 0xFC) >> 2); @@ -1169,7 +1179,10 @@ static bool TrackDesignPlaceSceneryElement( { flags = 0; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } uint8_t slope = ((bh >> 5) & 0x3) | ((bh >> 2) & 0x4); uint8_t edges = bh & 0xF; auto footpathPlaceAction = FootpathPlaceFromTrackAction( @@ -1207,7 +1220,10 @@ static bool TrackDesignPlaceSceneryElement( flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } footpath_connect_edges(mapCoord, reinterpret_cast(pathElement), flags); footpath_update_queue_chains(); return true; @@ -1337,6 +1353,10 @@ static int32_t track_design_place_maze(TrackDesign* td6, int16_t x, int16_t y, i flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST; } + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } auto rideEntranceExitPlaceAction = RideEntranceExitPlaceAction(mapCoord, rotation, ride->id, 0, false); rideEntranceExitPlaceAction.SetFlags(flags); auto res = GameActions::ExecuteNested(&rideEntranceExitPlaceAction); @@ -1372,6 +1392,10 @@ static int32_t track_design_place_maze(TrackDesign* td6, int16_t x, int16_t y, i flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST; } + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } auto rideEntranceExitPlaceAction = RideEntranceExitPlaceAction(mapCoord, rotation, ride->id, 0, true); rideEntranceExitPlaceAction.SetFlags(flags); auto res = GameActions::ExecuteNested(&rideEntranceExitPlaceAction); @@ -1402,7 +1426,10 @@ static int32_t track_design_place_maze(TrackDesign* td6, int16_t x, int16_t y, i { flags = GAME_COMMAND_FLAG_APPLY; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } gGameCommandErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; auto mazePlace = MazePlaceTrackAction({ mapCoord, z }, ride->id, maze_entry); @@ -1560,7 +1587,10 @@ static bool track_design_place_ride(TrackDesign* td6, int16_t x, int16_t y, int1 { flags = 0; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } gGameCommandErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; auto trackPlaceAction = TrackPlaceAction( _currentRideIndex, trackType, { x, y, tempZ, static_cast(rotation) }, brakeSpeed, trackColour, @@ -1701,7 +1731,10 @@ static bool track_design_place_ride(TrackDesign* td6, int16_t x, int16_t y, int1 { flags = 0; } - + if (_trackDesignPlaceIsReplay) + { + flags |= GAME_COMMAND_FLAG_REPLAY; + } gGameCommandErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; auto rideEntranceExitPlaceAction = RideEntranceExitPlaceAction( { x, y }, rotation, ride->id, stationIndex, entrance.isExit); @@ -1772,6 +1805,8 @@ int32_t place_virtual_track( _trackDesignPlaceStateSceneryUnavailable = false; _trackDesignPlaceStateHasScenery = false; + _trackDesignPlaceIsReplay = ptdOperation & PTD_OPERATION_FLAG_IS_REPLAY; + ptdOperation &= ~PTD_OPERATION_FLAG_IS_REPLAY; _trackDesignPlaceOperation = ptdOperation; if (gTrackDesignSceneryToggle) { diff --git a/src/openrct2/ride/TrackDesign.h b/src/openrct2/ride/TrackDesign.h index 5947e57358..3b05beb61b 100644 --- a/src/openrct2/ride/TrackDesign.h +++ b/src/openrct2/ride/TrackDesign.h @@ -183,6 +183,8 @@ enum PTD_OPERATION_REMOVE_GHOST, }; +static constexpr uint8_t PTD_OPERATION_FLAG_IS_REPLAY = (1 << 7); + enum { MAZE_ELEMENT_TYPE_MAZE_TRACK = 0,