From 0bfc151ab9b8dd39b077b96505c895c55d88a09e Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Sat, 30 Jul 2022 18:04:59 +0200 Subject: [PATCH] Remove remaining usages of gGameCommandErrorText --- .../windows/EditorBottomToolbar.cpp | 5 +- .../windows/EditorObjectSelection.cpp | 18 +++-- src/openrct2-ui/windows/Footpath.cpp | 2 - src/openrct2-ui/windows/MazeConstruction.cpp | 18 ++--- src/openrct2-ui/windows/RideConstruction.cpp | 36 ++++++---- src/openrct2/EditorObjectSelectionSession.cpp | 65 +++++++++---------- src/openrct2/EditorObjectSelectionSession.h | 10 ++- src/openrct2/Game.cpp | 3 - src/openrct2/Game.h | 3 - src/openrct2/actions/GameActionCompat.cpp | 34 ---------- src/openrct2/actions/TrackPlaceAction.cpp | 6 +- src/openrct2/actions/TrackRemoveAction.cpp | 16 +++-- src/openrct2/ride/Ride.h | 2 +- src/openrct2/ride/RideConstruction.cpp | 32 +++++---- src/openrct2/ride/Track.cpp | 30 ++++----- src/openrct2/ride/Track.h | 8 +-- src/openrct2/scenario/Scenario.cpp | 16 ++--- src/openrct2/scenario/Scenario.h | 4 +- src/openrct2/windows/_legacy.cpp | 17 +++-- src/openrct2/world/Park.cpp | 5 -- 20 files changed, 157 insertions(+), 173 deletions(-) diff --git a/src/openrct2-ui/windows/EditorBottomToolbar.cpp b/src/openrct2-ui/windows/EditorBottomToolbar.cpp index 8153a0c01e..5273f79e51 100644 --- a/src/openrct2-ui/windows/EditorBottomToolbar.cpp +++ b/src/openrct2-ui/windows/EditorBottomToolbar.cpp @@ -250,9 +250,10 @@ private: void JumpForwardToSaveScenario() const { - if (!scenario_prepare_for_save()) + const auto savePrepareResult = scenario_prepare_for_save(); + if (!savePrepareResult.Successful) { - context_show_error(STR_UNABLE_TO_SAVE_SCENARIO_FILE, gGameCommandErrorText, {}); + context_show_error(STR_UNABLE_TO_SAVE_SCENARIO_FILE, savePrepareResult.Message, {}); gfx_invalidate_screen(); return; } diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 13677b8e3c..edf5845adf 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -594,7 +594,9 @@ public: if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) { - if (!window_editor_object_selection_select_object(0, INPUT_FLAG_EDITOR_OBJECT_SELECT, listItem->repositoryItem)) + const auto objectSelectResult = window_editor_object_selection_select_object( + 0, INPUT_FLAG_EDITOR_OBJECT_SELECT, listItem->repositoryItem); + if (!objectSelectResult.Successful) return; // Close any other open windows such as options/colour schemes to prevent a crash. @@ -611,13 +613,14 @@ public: if (!(object_selection_flags & ObjectSelectionFlags::Selected)) inputFlags |= INPUT_FLAG_EDITOR_OBJECT_SELECT; - _gSceneryGroupPartialSelectError = false; - if (!window_editor_object_selection_select_object(0, inputFlags, listItem->repositoryItem)) + _gSceneryGroupPartialSelectError = std::nullopt; + const auto objectSelectResult = window_editor_object_selection_select_object(0, inputFlags, listItem->repositoryItem); + if (!objectSelectResult.Successful) { rct_string_id error_title = (inputFlags & INPUT_FLAG_EDITOR_OBJECT_SELECT) ? STR_UNABLE_TO_SELECT_THIS_OBJECT : STR_UNABLE_TO_DE_SELECT_THIS_OBJECT; - context_show_error(error_title, gGameCommandErrorText, {}); + context_show_error(error_title, objectSelectResult.Message, {}); return; } @@ -628,9 +631,10 @@ public: Invalidate(); } - if (_gSceneryGroupPartialSelectError) + if (_gSceneryGroupPartialSelectError.has_value()) { - if (gGameCommandErrorText == STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED) + const auto errorMessage = _gSceneryGroupPartialSelectError.value(); + if (errorMessage == STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED) { context_show_error( STR_WARNING_TOO_MANY_OBJECTS_SELECTED, STR_NOT_ALL_OBJECTS_IN_THIS_SCENERY_GROUP_COULD_BE_SELECTED, {}); @@ -638,7 +642,7 @@ public: else { context_show_error( - gGameCommandErrorText, STR_NOT_ALL_OBJECTS_IN_THIS_SCENERY_GROUP_COULD_BE_SELECTED, Formatter::Common()); + errorMessage, STR_NOT_ALL_OBJECTS_IN_THIS_SCENERY_GROUP_COULD_BE_SELECTED, Formatter::Common()); } } } diff --git a/src/openrct2-ui/windows/Footpath.cpp b/src/openrct2-ui/windows/Footpath.cpp index 04ef3c8204..4918cd2640 100644 --- a/src/openrct2-ui/windows/Footpath.cpp +++ b/src/openrct2-ui/windows/Footpath.cpp @@ -1010,7 +1010,6 @@ static void WindowFootpathPlacePathAtPoint(const ScreenCoordsXY& screenCoords) } // Try and place path - gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; auto selectedType = gFootpathSelection.GetSelectedSurface(); PathConstructFlags constructFlags = FootpathCreateConstructFlags(selectedType); @@ -1104,7 +1103,6 @@ static void WindowFootpathConstruct() CoordsXYZ footpathLoc; FootpathGetNextPathInfo(&type, footpathLoc, &slope); - gGameCommandErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE; PathConstructFlags constructFlags = FootpathCreateConstructFlags(type); auto footpathPlaceAction = FootpathPlaceAction( diff --git a/src/openrct2-ui/windows/MazeConstruction.cpp b/src/openrct2-ui/windows/MazeConstruction.cpp index 92ecd489da..3d31ba9774 100644 --- a/src/openrct2-ui/windows/MazeConstruction.cpp +++ b/src/openrct2-ui/windows/MazeConstruction.cpp @@ -7,6 +7,8 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include "openrct2/actions/MazeSetTrackAction.h" + #include #include #include @@ -355,7 +357,7 @@ private: OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position); auto currentRide = get_ride(rideIndex); - if (currentRide != nullptr && ride_are_all_possible_entrances_and_exits_built(currentRide)) + if (currentRide != nullptr && ride_are_all_possible_entrances_and_exits_built(currentRide).Successful) { tool_cancel(); if (currentRide->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_NO_TRACK)) @@ -377,7 +379,7 @@ private: void WindowMazeConstructionConstruct(int32_t direction) { - int32_t x, y, z, actionFlags, mode; + int32_t x, y, z, actionFlags = 0, mode; _currentTrackSelectionFlags = 0; _rideConstructionNextArrowPulse = 0; @@ -391,22 +393,22 @@ private: { case RideConstructionState::MazeBuild: mode = GC_SET_MAZE_TRACK_BUILD; - actionFlags = GAME_COMMAND_FLAG_APPLY; break; case RideConstructionState::MazeMove: mode = GC_SET_MAZE_TRACK_MOVE; - actionFlags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED; + actionFlags = GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED; break; default: case RideConstructionState::MazeFill: mode = GC_SET_MAZE_TRACK_FILL; - actionFlags = GAME_COMMAND_FLAG_APPLY; break; } - money32 cost = maze_set_track( - CoordsXYZD{ x, y, z, static_cast(direction) }, actionFlags, false, _currentRideIndex, mode); - if (cost == MONEY32_UNDEFINED) + const auto loc = CoordsXYZD{ x, y, z, static_cast(direction) }; + auto action = MazeSetTrackAction(loc, false, _currentRideIndex, mode); + action.SetFlags(actionFlags); + const auto res = GameActions::Execute(&action); + if (res.Error != GameActions::Status::Ok) { return; } diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 7e0c9a4329..c75d56c513 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -7,6 +7,8 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include "openrct2/actions/MazeSetTrackAction.h" + #include #include #include @@ -149,6 +151,7 @@ static ScreenCoordsXY _trackPlaceShiftStart; static int32_t _trackPlaceShiftZ; static int32_t _trackPlaceZ; static money32 _trackPlaceCost; +static rct_string_id _trackPlaceErrorMessage; static bool _autoRotatingShop; static constexpr const rct_string_id RideConstructionSeatAngleRotationStrings[] = { @@ -2201,6 +2204,7 @@ private: _currentTrackPrice = MONEY32_UNDEFINED; _trackPlaceCost = MONEY32_UNDEFINED; + _trackPlaceErrorMessage = STR_NONE; ride_construction_invalidate_current_track(); if (window_ride_construction_update_state( &trackType, &trackDirection, &rideIndex, &liftHillAndAlternativeState, &trackPos, &properties)) @@ -2230,16 +2234,13 @@ private: // Used by some functions if (res.Error != GameActions::Status::Ok) { - if (auto* commandError = std::get_if(&res.ErrorMessage)) - gGameCommandErrorText = *commandError; - else - gGameCommandErrorText = STR_NONE; _trackPlaceCost = MONEY32_UNDEFINED; + _trackPlaceErrorMessage = std::get(res.ErrorMessage); } else { - gGameCommandErrorText = STR_NONE; _trackPlaceCost = res.Cost; + _trackPlaceErrorMessage = STR_NONE; } if (res.Error != GameActions::Status::Ok) @@ -2549,7 +2550,7 @@ private: OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position); auto currentRide = get_ride(gRideEntranceExitPlaceRideIndex); - if (currentRide != nullptr && ride_are_all_possible_entrances_and_exits_built(currentRide)) + if (currentRide != nullptr && ride_are_all_possible_entrances_and_exits_built(currentRide).Successful) { tool_cancel(); if (currentRide->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_NO_TRACK)) @@ -2728,7 +2729,7 @@ static void CloseConstructWindowOnCompletion(Ride* ride) auto w = window_find_by_class(WC_RIDE_CONSTRUCTION); if (w != nullptr) { - if (ride_are_all_possible_entrances_and_exits_built(ride)) + if (ride_are_all_possible_entrances_and_exits_built(ride).Successful) { window_close(w); } @@ -3476,15 +3477,26 @@ void ride_construction_tooldown_construct(const ScreenCoordsXY& screenCoords) gDisableErrorWindowSound = true; - _trackPlaceCost = maze_set_track( - CoordsXYZD{ _currentTrackBegin, 0 }, GAME_COMMAND_FLAG_APPLY, true, _currentRideIndex, GC_SET_MAZE_TRACK_BUILD); + auto gameAction = MazeSetTrackAction( + CoordsXYZD{ _currentTrackBegin, 0 }, true, _currentRideIndex, GC_SET_MAZE_TRACK_BUILD); + auto mazeSetTrackResult = GameActions::Execute(&gameAction); + if (mazeSetTrackResult.Error == GameActions::Status::Ok) + { + _trackPlaceCost = mazeSetTrackResult.Cost; + _trackPlaceErrorMessage = STR_NONE; + } + else + { + _trackPlaceCost = MONEY32_UNDEFINED; + _trackPlaceErrorMessage = std::get(mazeSetTrackResult.ErrorMessage); + } gDisableErrorWindowSound = false; - if (_trackPlaceCost == MONEY32_UNDEFINED) + if (mazeSetTrackResult.Error != GameActions::Status::Ok) { _rideConstructionState = RideConstructionState::Place; - rct_string_id errorText = gGameCommandErrorText; + rct_string_id errorText = std::get(mazeSetTrackResult.ErrorMessage); z -= 8; if (errorText == STR_NOT_ENOUGH_CASH_REQUIRES || errorText == STR_CAN_ONLY_BUILD_THIS_UNDERWATER || errorText == STR_CAN_ONLY_BUILD_THIS_ON_WATER || errorText == STR_RIDE_CANT_BUILD_THIS_UNDERWATER @@ -3534,7 +3546,7 @@ void ride_construction_tooldown_construct(const ScreenCoordsXY& screenCoords) if (_trackPlaceCost == MONEY32_UNDEFINED) { - rct_string_id errorText = gGameCommandErrorText; + rct_string_id errorText = _trackPlaceErrorMessage; z -= 8; if (errorText == STR_NOT_ENOUGH_CASH_REQUIRES || errorText == STR_CAN_ONLY_BUILD_THIS_UNDERWATER || errorText == STR_CAN_ONLY_BUILD_THIS_ON_WATER || errorText == STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index 49d48ea11d..1906b10533 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -33,7 +33,7 @@ #include #include -bool _gSceneryGroupPartialSelectError; +std::optional _gSceneryGroupPartialSelectError; std::vector _objectSelectionFlags; int32_t _numSelectedObjectsForType[EnumValue(ObjectType::Count)]; static int32_t _numAvailableObjectsForType[EnumValue(ObjectType::Count)]; @@ -45,6 +45,19 @@ static void window_editor_object_selection_select_default_objects(); static void SelectDesignerObjects(); static void ReplaceSelectedWaterPalette(const ObjectRepositoryItem* item); +/** + * Master objects are objects that are not + * optional / required dependants of an + * object. + */ +static constexpr ResultWithMessage ObjectSelectionError(bool isMasterObject, rct_string_id message) +{ + if (!isMasterObject) + reset_selected_object_count_and_size(); + + return { false, message }; +} + /** * * rct2: 0x006ABCD1 @@ -484,30 +497,16 @@ void finish_object_selection() } } -/** - * Master objects are objects that are not - * optional / required dependants of an - * object. - */ -static void set_object_selection_error(uint8_t is_master_object, rct_string_id error_msg) -{ - gGameCommandErrorText = error_msg; - if (!is_master_object) - { - reset_selected_object_count_and_size(); - } -} - /** * * rct2: 0x006AB54F */ -bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, const ObjectRepositoryItem* item) +ResultWithMessage window_editor_object_selection_select_object( + uint8_t isMasterObject, int32_t flags, const ObjectRepositoryItem* item) { if (item == nullptr) { - set_object_selection_error(isMasterObject, STR_OBJECT_SELECTION_ERR_OBJECT_DATA_NOT_FOUND); - return false; + return ObjectSelectionError(isMasterObject, STR_OBJECT_SELECTION_ERR_OBJECT_DATA_NOT_FOUND); } int32_t numObjects = static_cast(object_repository_get_items_count()); @@ -527,19 +526,17 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_ { if (!(*selectionFlags & ObjectSelectionFlags::Selected)) { - return true; + return { true }; } if (*selectionFlags & ObjectSelectionFlags::InUse) { - set_object_selection_error(isMasterObject, STR_OBJECT_SELECTION_ERR_CURRENTLY_IN_USE); - return false; + return ObjectSelectionError(isMasterObject, STR_OBJECT_SELECTION_ERR_CURRENTLY_IN_USE); } if (*selectionFlags & ObjectSelectionFlags::AlwaysRequired) { - set_object_selection_error(isMasterObject, STR_OBJECT_SELECTION_ERR_ALWAYS_REQUIRED); - return false; + return ObjectSelectionError(isMasterObject, STR_OBJECT_SELECTION_ERR_ALWAYS_REQUIRED); } ObjectType objectType = item->Type; @@ -553,7 +550,7 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_ _numSelectedObjectsForType[EnumValue(objectType)]--; *selectionFlags &= ~ObjectSelectionFlags::Selected; - return true; + return { true }; } if (isMasterObject == 0) @@ -566,7 +563,7 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_ if (*selectionFlags & ObjectSelectionFlags::Selected) { - return true; + return { true }; } ObjectType objectType = item->Type; @@ -574,17 +571,17 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_ if (maxObjects <= _numSelectedObjectsForType[EnumValue(objectType)]) { - set_object_selection_error(isMasterObject, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED); - return false; + return ObjectSelectionError(isMasterObject, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED); } if (objectType == ObjectType::SceneryGroup && (flags & INPUT_FLAG_EDITOR_OBJECT_SELECT_OBJECTS_IN_SCENERY_GROUP)) { for (const auto& sgEntry : item->SceneryGroupInfo.Entries) { - if (!window_editor_object_selection_select_object(++isMasterObject, flags, sgEntry)) + const auto selectionResult = window_editor_object_selection_select_object(++isMasterObject, flags, sgEntry); + if (!selectionResult.Successful) { - _gSceneryGroupPartialSelectError = true; + _gSceneryGroupPartialSelectError = selectionResult.Message; } } } @@ -600,23 +597,21 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_ object_create_identifier_name(objectName, 64, &item->ObjectEntry); auto ft = Formatter::Common(); ft.Add(objectName); - set_object_selection_error(isMasterObject, STR_OBJECT_SELECTION_ERR_SHOULD_SELECT_X_FIRST); - return false; + return ObjectSelectionError(isMasterObject, STR_OBJECT_SELECTION_ERR_SHOULD_SELECT_X_FIRST); } if (maxObjects <= _numSelectedObjectsForType[EnumValue(objectType)]) { - set_object_selection_error(isMasterObject, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED); - return false; + return ObjectSelectionError(isMasterObject, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED); } _numSelectedObjectsForType[EnumValue(objectType)]++; *selectionFlags |= ObjectSelectionFlags::Selected; - return true; + return { true }; } -bool window_editor_object_selection_select_object( +ResultWithMessage window_editor_object_selection_select_object( uint8_t isMasterObject, int32_t flags, const ObjectEntryDescriptor& descriptor) { auto& objectRepository = OpenRCT2::GetContext()->GetObjectRepository(); diff --git a/src/openrct2/EditorObjectSelectionSession.h b/src/openrct2/EditorObjectSelectionSession.h index d543200e1c..62b232bf11 100644 --- a/src/openrct2/EditorObjectSelectionSession.h +++ b/src/openrct2/EditorObjectSelectionSession.h @@ -15,6 +15,8 @@ #include +struct ResultWithMessage; + enum EDITOR_INPUT_FLAGS { INPUT_FLAG_EDITOR_OBJECT_SELECT = (1 << 0), // Set when you want to select an object, not set when you want to deselect it. @@ -23,7 +25,7 @@ enum EDITOR_INPUT_FLAGS INPUT_FLAG_EDITOR_OBJECT_ALWAYS_REQUIRED = (1 << 3) }; -extern bool _gSceneryGroupPartialSelectError; +extern std::optional _gSceneryGroupPartialSelectError; extern std::vector _objectSelectionFlags; extern int32_t _numSelectedObjectsForType[EnumValue(ObjectType::Count)]; @@ -34,8 +36,10 @@ void unload_unselected_objects(); void sub_6AB211(); void reset_selected_object_count_and_size(); void finish_object_selection(); -bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, const ObjectRepositoryItem* item); -bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, const ObjectEntryDescriptor& entry); +ResultWithMessage window_editor_object_selection_select_object( + uint8_t isMasterObject, int32_t flags, const ObjectRepositoryItem* item); +ResultWithMessage window_editor_object_selection_select_object( + uint8_t isMasterObject, int32_t flags, const ObjectEntryDescriptor& entry); /** * Removes all unused objects from the object selection. diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index e380e9ee95..4d6b2461a4 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -86,9 +86,6 @@ bool gLoadKeepWindowsOpen = false; uint32_t gCurrentTicks; uint32_t gCurrentRealTimeTicks; -rct_string_id gGameCommandErrorTitle; -rct_string_id gGameCommandErrorText; - #ifdef ENABLE_SCRIPTING static bool _mapChangedExpected; #endif diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 989b00afad..c9fb86cfc7 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -132,9 +132,6 @@ enum ERROR_TYPE_FILE_LOAD = 255 }; -extern rct_string_id gGameCommandErrorTitle; -extern rct_string_id gGameCommandErrorText; - extern uint32_t gCurrentTicks; extern uint32_t gCurrentRealTimeTicks; diff --git a/src/openrct2/actions/GameActionCompat.cpp b/src/openrct2/actions/GameActionCompat.cpp index 02b3e69713..f628faa94d 100644 --- a/src/openrct2/actions/GameActionCompat.cpp +++ b/src/openrct2/actions/GameActionCompat.cpp @@ -116,37 +116,3 @@ void guest_set_name(EntityId spriteIndex, const char* name) GameActions::Execute(&gameAction); } #pragma endregion - -#pragma region MazeSetTrack -money32 maze_set_track(const CoordsXYZD& loc, uint8_t flags, bool initialPlacement, RideId rideIndex, uint8_t mode) -{ - auto gameAction = MazeSetTrackAction(loc, initialPlacement, rideIndex, mode); - gameAction.SetFlags(flags); - - GameActions::Result res; - - if (!(flags & GAME_COMMAND_FLAG_APPLY)) - res = GameActions::Query(&gameAction); - else - res = GameActions::Execute(&gameAction); - - // NOTE: ride_construction_tooldown_construct requires them to be set. - // Refactor result type once there's no C code referencing this function. - if (const auto* title = std::get_if(&res.ErrorTitle)) - gGameCommandErrorTitle = *title; - else - gGameCommandErrorTitle = STR_NONE; - - if (const auto* message = std::get_if(&res.ErrorMessage)) - gGameCommandErrorText = *message; - else - gGameCommandErrorText = STR_NONE; - - if (res.Error != GameActions::Status::Ok) - { - return MONEY32_UNDEFINED; - } - - return res.Cost; -} -#pragma endregion diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index 48aaf11696..870d956930 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -347,10 +347,12 @@ GameActions::Result TrackPlaceAction::Query() const int32_t entranceDirections = std::get<0>(ted.SequenceProperties); if ((entranceDirections & TRACK_SEQUENCE_FLAG_ORIGIN) && trackBlock->index == 0) { - if (!track_add_station_element({ mapLoc, baseZ, _origin.direction }, _rideIndex, 0, _fromTrackDesign)) + const auto addElementResult = track_add_station_element( + { mapLoc, baseZ, _origin.direction }, _rideIndex, 0, _fromTrackDesign); + if (!addElementResult.Successful) { return GameActions::Result( - GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, gGameCommandErrorText); + GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, addElementResult.Message); } } diff --git a/src/openrct2/actions/TrackRemoveAction.cpp b/src/openrct2/actions/TrackRemoveAction.cpp index 8da95fe59b..31f1c61878 100644 --- a/src/openrct2/actions/TrackRemoveAction.cpp +++ b/src/openrct2/actions/TrackRemoveAction.cpp @@ -206,10 +206,11 @@ GameActions::Result TrackRemoveAction::Query() const int32_t entranceDirections = std::get<0>(ted.SequenceProperties); if (entranceDirections & TRACK_SEQUENCE_FLAG_ORIGIN && (tileElement->AsTrack()->GetSequenceIndex() == 0)) { - if (!track_remove_station_element({ mapLoc, _origin.direction }, rideIndex, 0)) + const auto removeElementResult = track_remove_station_element({ mapLoc, _origin.direction }, rideIndex, 0); + if (!removeElementResult.Successful) { return GameActions::Result( - GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS, gGameCommandErrorText); + GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS, removeElementResult.Message); } } @@ -384,10 +385,11 @@ GameActions::Result TrackRemoveAction::Execute() const int32_t entranceDirections = std::get<0>(ted.SequenceProperties); if (entranceDirections & TRACK_SEQUENCE_FLAG_ORIGIN && (tileElement->AsTrack()->GetSequenceIndex() == 0)) { - if (!track_remove_station_element({ mapLoc, _origin.direction }, rideIndex, 0)) + const auto removeElementResult = track_remove_station_element({ mapLoc, _origin.direction }, rideIndex, 0); + if (!removeElementResult.Successful) { return GameActions::Result( - GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS, gGameCommandErrorText); + GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS, removeElementResult.Message); } } @@ -412,10 +414,12 @@ GameActions::Result TrackRemoveAction::Execute() const && !(ride->status == RideStatus::Simulating && tileElement->Flags & TILE_ELEMENT_FLAG_GHOST) && (tileElement->AsTrack()->GetSequenceIndex() == 0)) { - if (!track_remove_station_element({ mapLoc, _origin.direction }, rideIndex, GAME_COMMAND_FLAG_APPLY)) + const auto removeElementResult = track_remove_station_element( + { mapLoc, _origin.direction }, rideIndex, GAME_COMMAND_FLAG_APPLY); + if (!removeElementResult.Successful) { return GameActions::Result( - GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS, gGameCommandErrorText); + GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS, removeElementResult.Message); } } diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index 44e02027cb..7a7f751678 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -1056,7 +1056,7 @@ void window_ride_construction_update_active_elements(); money32 ride_entrance_exit_place_ghost( Ride* ride, const CoordsXY& entranceExitCoords, Direction direction, int32_t placeType, StationIndex stationNum); -bool ride_are_all_possible_entrances_and_exits_built(Ride* ride); +ResultWithMessage ride_are_all_possible_entrances_and_exits_built(Ride* ride); void ride_fix_breakdown(Ride* ride, int32_t reliabilityIncreaseFactor); uint8_t ride_entry_get_vehicle_at_position(int32_t rideEntryIndex, int32_t numCarsPerTrain, int32_t position); diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index c65ef60f49..0879c032b3 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -11,6 +11,7 @@ #include "../Context.h" #include "../Input.h" +#include "../actions/MazeSetTrackAction.h" #include "../actions/RideEntranceExitRemoveAction.h" #include "../actions/RideSetSettingAction.h" #include "../actions/RideSetStatusAction.h" @@ -491,12 +492,19 @@ void ride_remove_provisional_track_piece() int32_t z = _unkF440C5.z; if (ride->type == RIDE_TYPE_MAZE) { - int32_t flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND - | GAME_COMMAND_FLAG_GHOST; - maze_set_track(CoordsXYZD{ x, y, z, 0 }, flags, false, rideIndex, GC_SET_MAZE_TRACK_FILL); - maze_set_track(CoordsXYZD{ x, y + 16, z, 1 }, flags, false, rideIndex, GC_SET_MAZE_TRACK_FILL); - maze_set_track(CoordsXYZD{ x + 16, y + 16, z, 2 }, flags, false, rideIndex, GC_SET_MAZE_TRACK_FILL); - maze_set_track(CoordsXYZD{ x + 16, y, z, 3 }, flags, false, rideIndex, GC_SET_MAZE_TRACK_FILL); + const int32_t flags = GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST; + const CoordsXYZD quadrants[NumOrthogonalDirections] = { + { x, y, z, 0 }, + { x, y + 16, z, 1 }, + { x + 16, y + 16, z, 2 }, + { x + 16, y, z, 3 }, + }; + for (const auto& quadrant : quadrants) + { + auto gameAction = MazeSetTrackAction(quadrant, false, rideIndex, GC_SET_MAZE_TRACK_FILL); + gameAction.SetFlags(flags); + auto res = GameActions::Execute(&gameAction); + } } else { @@ -1630,10 +1638,10 @@ bool ride_select_forwards_from_back() * * rct2: 0x006B58EF */ -bool ride_are_all_possible_entrances_and_exits_built(Ride* ride) +ResultWithMessage ride_are_all_possible_entrances_and_exits_built(Ride* ride) { if (ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_IS_SHOP)) - return true; + return { true }; for (auto& station : ride->GetStations()) { @@ -1643,14 +1651,12 @@ bool ride_are_all_possible_entrances_and_exits_built(Ride* ride) } if (station.Entrance.IsNull()) { - gGameCommandErrorText = STR_ENTRANCE_NOT_YET_BUILT; - return false; + return { false, STR_ENTRANCE_NOT_YET_BUILT }; } if (station.Exit.IsNull()) { - gGameCommandErrorText = STR_EXIT_NOT_YET_BUILT; - return false; + return { false, STR_EXIT_NOT_YET_BUILT }; } } - return true; + return { true }; } diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index 8974a9aef4..54001c8173 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -111,11 +111,11 @@ static void ride_remove_station(Ride* ride, const CoordsXYZ& location) * * rct2: 0x006C4D89 */ -bool track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, bool fromTrackDesign) +ResultWithMessage track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, bool fromTrackDesign) { auto ride = get_ride(rideIndex); if (ride == nullptr) - return false; + return { false }; CoordsXY stationBackLoc = loc; CoordsXY stationFrontLoc = loc; @@ -125,8 +125,7 @@ bool track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, { if (ride->num_stations >= OpenRCT2::Limits::MaxStationsPerRide) { - gGameCommandErrorText = STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE; - return false; + return { false, STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE }; } if (flags & GAME_COMMAND_FLAG_APPLY) { @@ -141,7 +140,7 @@ bool track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, station.Length = 0; ride->num_stations++; } - return true; + return { true }; } TileElement* stationElement; @@ -195,14 +194,12 @@ bool track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, // This _might_ cause issues if the track designs is bugged and actually has 5. if (stationBackLoc == stationFrontLoc && ride->num_stations >= OpenRCT2::Limits::MaxStationsPerRide && !fromTrackDesign) { - gGameCommandErrorText = STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE; - return false; + return { false, STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE }; } if (stationLength > MAX_STATION_PLATFORM_LENGTH) { - gGameCommandErrorText = STR_STATION_PLATFORM_TOO_LONG; - return false; + return { false, STR_STATION_PLATFORM_TOO_LONG }; } if (flags & GAME_COMMAND_FLAG_APPLY) @@ -257,18 +254,18 @@ bool track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, } } while (!finaliseStationDone); } - return true; + return { true }; } /** * * rct2: 0x006C494B */ -bool track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32_t flags) +ResultWithMessage track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32_t flags) { auto ride = get_ride(rideIndex); if (ride == nullptr) - return false; + return { false }; CoordsXYZD removeLoc = loc; CoordsXYZD stationBackLoc = loc; @@ -286,7 +283,7 @@ bool track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32 ride_remove_station(ride, loc); } } - return true; + return { true }; } TileElement* stationElement; @@ -335,11 +332,10 @@ bool track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32 if ((removeLoc != stationBackLoc) && (removeLoc != stationFrontLoc) && ride->num_stations >= OpenRCT2::Limits::MaxStationsPerRide) { - gGameCommandErrorText = STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE; - return false; + return { false, STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE }; } - return true; + return { true }; } currentLoc = stationFrontLoc; @@ -405,7 +401,7 @@ bool track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32 } } while (!finaliseStationDone); - return true; + return { true }; } void track_circuit_iterator_begin(track_circuit_iterator* it, CoordsXYE first) diff --git a/src/openrct2/ride/Track.h b/src/openrct2/ride/Track.h index d7256617f1..bb09c53be4 100644 --- a/src/openrct2/ride/Track.h +++ b/src/openrct2/ride/Track.h @@ -24,6 +24,8 @@ using track_type_t = uint16_t; using roll_type_t = uint8_t; using pitch_type_t = uint8_t; +struct ResultWithMessage; + struct rct_trackdefinition { track_type_t type; @@ -578,10 +580,8 @@ roll_type_t track_get_actual_bank(TileElement* tileElement, roll_type_t bank); roll_type_t track_get_actual_bank_2(int32_t rideType, bool isInverted, roll_type_t bank); roll_type_t track_get_actual_bank_3(bool useInvertedSprites, TileElement* tileElement); -bool track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, bool fromTrackDesign); -bool track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32_t flags); - -money32 maze_set_track(const CoordsXYZD& coords, uint8_t flags, bool initialPlacement, RideId rideIndex, uint8_t mode); +ResultWithMessage track_add_station_element(CoordsXYZD loc, RideId rideIndex, int32_t flags, bool fromTrackDesign); +ResultWithMessage track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32_t flags); bool TrackTypeHasSpeedSetting(track_type_t trackType); std::optional GetTrackSegmentOrigin(const CoordsXYE& posEl); diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index fad2d41cf0..e7fd293d1d 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -538,7 +538,7 @@ uint32_t scenario_rand_max(uint32_t max) * Prepare rides, for the finish five rollercoasters objective. * rct2: 0x006788F7 */ -static bool scenario_prepare_rides_for_save() +static ResultWithMessage scenario_prepare_rides_for_save() { int32_t isFiveCoasterObjective = gScenarioObjective.Type == OBJECTIVE_FINISH_5_ROLLERCOASTERS; uint8_t rcs = 0; @@ -563,8 +563,7 @@ static bool scenario_prepare_rides_for_save() if (isFiveCoasterObjective && rcs < 5) { - gGameCommandErrorText = STR_NOT_ENOUGH_ROLLER_COASTERS; - return false; + return { false, STR_NOT_ENOUGH_ROLLER_COASTERS }; } bool markTrackAsIndestructible; @@ -591,19 +590,20 @@ static bool scenario_prepare_rides_for_save() } } while (tile_element_iterator_next(&it)); - return true; + return { true }; } /** * * rct2: 0x006726C7 */ -bool scenario_prepare_for_save() +ResultWithMessage scenario_prepare_for_save() { // This can return false if the goal is 'Finish 5 roller coaster' and there are too few. - if (!scenario_prepare_rides_for_save()) + const auto prepareRidesResult = scenario_prepare_rides_for_save(); + if (!prepareRidesResult.Successful) { - return false; + return { false, prepareRidesResult.Message }; } if (gScenarioObjective.Type == OBJECTIVE_GUESTS_AND_RATING) @@ -611,7 +611,7 @@ bool scenario_prepare_for_save() scenario_reset(); - return true; + return { true }; } ObjectiveStatus Objective::CheckGuestsBy() const diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h index dcb8d5ff8d..0cf0115279 100644 --- a/src/openrct2/scenario/Scenario.h +++ b/src/openrct2/scenario/Scenario.h @@ -21,6 +21,8 @@ #include "../world/Map.h" #include "../world/MapAnimation.h" +struct ResultWithMessage; + using random_engine_t = Random::Rct2::Engine; enum @@ -179,7 +181,7 @@ void scenario_rand_seed(random_engine_t::result_type s0, random_engine_t::result random_engine_t::result_type scenario_rand(); uint32_t scenario_rand_max(uint32_t max); -bool scenario_prepare_for_save(); +ResultWithMessage scenario_prepare_for_save(); int32_t scenario_save(u8string_view path, int32_t flags); void scenario_failure(); void scenario_success(); diff --git a/src/openrct2/windows/_legacy.cpp b/src/openrct2/windows/_legacy.cpp index b9e1101d57..e1dd2ea19a 100644 --- a/src/openrct2/windows/_legacy.cpp +++ b/src/openrct2/windows/_legacy.cpp @@ -11,6 +11,7 @@ #include "../Context.h" #include "../Game.h" #include "../Input.h" +#include "../actions/MazeSetTrackAction.h" #include "../actions/TrackPlaceAction.h" #include "../audio/audio.h" #include "../entity/Staff.h" @@ -48,11 +49,13 @@ money32 place_provisional_track_piece( ride_construction_remove_ghosts(); if (ride->type == RIDE_TYPE_MAZE) { - int32_t flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND - | GAME_COMMAND_FLAG_GHOST; // 105 - auto result = maze_set_track(CoordsXYZD{ trackPos, 0 }, flags, true, rideIndex, GC_SET_MAZE_TRACK_BUILD); - if (result == MONEY32_UNDEFINED) - return result; + int32_t flags = GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST; + auto gameAction = MazeSetTrackAction(CoordsXYZD{ trackPos, 0 }, true, rideIndex, GC_SET_MAZE_TRACK_BUILD); + gameAction.SetFlags(flags); + auto result = GameActions::Execute(&gameAction); + + if (result.Error != GameActions::Status::Ok) + return MONEY32_UNDEFINED; _unkF440C5 = { trackPos, static_cast(trackDirection) }; _currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_TRACK; @@ -69,7 +72,7 @@ money32 place_provisional_track_piece( virtual_floor_set_height(trackPos.z); } - return result; + return result.Cost; } auto trackPlaceAction = TrackPlaceAction( @@ -401,7 +404,7 @@ void window_ride_construction_do_entrance_exit_check() w = window_find_by_class(WC_RIDE_CONSTRUCTION); if (w != nullptr) { - if (!ride_are_all_possible_entrances_and_exits_built(ride)) + if (!ride_are_all_possible_entrances_and_exits_built(ride).Successful) { window_event_mouse_up_call(w, WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE); } diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index 847adbe501..1398f6bcd0 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -137,9 +137,6 @@ void update_park_fences(const CoordsXY& coords) if (fenceRequired) { - // As map_is_location_in_park sets the error text - // will require to back it up. - rct_string_id previous_error = gGameCommandErrorText; if (map_is_location_in_park({ coords.x - COORDS_XY_STEP, coords.y })) { newFences |= 0x8; @@ -159,8 +156,6 @@ void update_park_fences(const CoordsXY& coords) { newFences |= 0x1; } - - gGameCommandErrorText = previous_error; } }