diff --git a/src/openrct2-ui/WindowManager.cpp b/src/openrct2-ui/WindowManager.cpp index 17db049a6f..b40e314fb0 100644 --- a/src/openrct2-ui/WindowManager.cpp +++ b/src/openrct2-ui/WindowManager.cpp @@ -444,6 +444,7 @@ public: case INTENT_ACTION_TRACK_DESIGN_REMOVE_PROVISIONAL: TrackPlaceClearProvisionalTemporarily(); break; + case INTENT_ACTION_TRACK_DESIGN_RESTORE_PROVISIONAL: TrackPlaceRestoreProvisional(); break; diff --git a/src/openrct2-ui/windows/TrackDesignPlace.cpp b/src/openrct2-ui/windows/TrackDesignPlace.cpp index 44d66feb72..899e7ce3c3 100644 --- a/src/openrct2-ui/windows/TrackDesignPlace.cpp +++ b/src/openrct2-ui/windows/TrackDesignPlace.cpp @@ -120,8 +120,6 @@ static std::unique_ptr _trackDesign; static void window_track_place_clear_provisional(); static int32_t window_track_place_get_base_z(int32_t x, int32_t y); -static void window_track_place_attempt_placement( - TrackDesign* td6, int32_t x, int32_t y, int32_t z, int32_t bl, money32* cost, ride_id_t* rideIndex); static void window_track_place_clear_mini_preview(); static void window_track_place_draw_mini_preview(TrackDesign* td6); @@ -303,18 +301,20 @@ static void window_track_place_toolupdate(rct_window* w, rct_widgetindex widgetI if (res->Error == GA_ERROR::OK) { // Valid location found. Place the ghost at the location. - ride_id_t rideIndex; - window_track_place_attempt_placement( - _trackDesign.get(), trackLoc.x, trackLoc.y, trackLoc.z, - GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST, &cost, &rideIndex); - if (cost != MONEY32_UNDEFINED) - { - _window_track_place_ride_index = rideIndex; - _window_track_place_last_valid_x = trackLoc.x; - _window_track_place_last_valid_y = trackLoc.y; - _window_track_place_last_valid_z = trackLoc.z; - _window_track_place_last_was_valid = true; - } + auto tdAction = TrackDesignAction({ trackLoc, _currentTrackPieceDirection }, *_trackDesign); + tdAction.SetFlags(GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST); + tdAction.SetCallback([trackLoc](const GameAction*, const TrackDesignActionResult* result) { + if (result->Error == GA_ERROR::OK) + { + _window_track_place_ride_index = result->rideIndex; + _window_track_place_last_valid_x = trackLoc.x; + _window_track_place_last_valid_y = trackLoc.y; + _window_track_place_last_valid_z = trackLoc.z; + _window_track_place_last_was_valid = true; + } + }); + res = GameActions::Execute(&tdAction); + cost = res->Error == GA_ERROR::OK ? res->Cost : MONEY32_UNDEFINED; } } @@ -353,7 +353,7 @@ static void window_track_place_tooldown(rct_window* w, rct_widgetindex widgetInd auto res = FindValidTrackDesignPlaceHeight(trackLoc, 0); if (res->Error == GA_ERROR::OK) { - auto tdAction = TrackDesignAction({ trackLoc.x, trackLoc.y, trackLoc.z, _currentTrackPieceDirection }, *_trackDesign); + auto tdAction = TrackDesignAction({trackLoc, _currentTrackPieceDirection }, *_trackDesign); tdAction.SetCallback([trackLoc](const GameAction*, const TrackDesignActionResult* result) { if (result->Error == GA_ERROR::OK) { @@ -361,7 +361,7 @@ static void window_track_place_tooldown(rct_window* w, rct_widgetindex widgetInd if (ride != nullptr) { window_close_by_class(WC_ERROR); - audio_play_sound_at_location(SoundId::PlaceItem, { trackLoc.x, trackLoc.y, trackLoc.z }); + audio_play_sound_at_location(SoundId::PlaceItem, trackLoc); _currentRideIndex = result->rideIndex; if (track_design_are_entrance_and_exit_placed()) @@ -454,13 +454,13 @@ void TrackPlaceRestoreProvisional() { if (_window_track_place_last_was_valid) { - money32 cost; - ride_id_t rideIndex; - window_track_place_attempt_placement( - _trackDesign.get(), _window_track_place_last_valid_x, _window_track_place_last_valid_y, - _window_track_place_last_valid_z, GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST, - &cost, &rideIndex); - if (cost == MONEY32_UNDEFINED) + auto tdAction = TrackDesignAction( + { _window_track_place_last_valid_x, _window_track_place_last_valid_y, _window_track_place_last_valid_z, + _currentTrackPieceDirection }, + *_trackDesign); + tdAction.SetFlags(GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST); + auto res = GameActions::Execute(&tdAction); + if (res->Error != GA_ERROR::OK) { _window_track_place_last_was_valid = false; } @@ -497,24 +497,6 @@ static int32_t window_track_place_get_base_z(int32_t x, int32_t y) return z + place_virtual_track(_trackDesign.get(), PTD_OPERATION_GET_PLACE_Z, true, GetOrAllocateRide(0), x, y, z); } -static void window_track_place_attempt_placement( - TrackDesign* td6, int32_t x, int32_t y, int32_t z, int32_t bl, money32* cost, ride_id_t* rideIndex) -{ - auto tdAction = TrackDesignAction({ x, y, z, _currentTrackPieceDirection }, *_trackDesign); - tdAction.SetFlags(bl); - auto res = (bl & GAME_COMMAND_FLAG_APPLY) ? GameActions::Execute(&tdAction) : GameActions::Query(&tdAction); - - if (res->Error != GA_ERROR::OK) - { - *cost = MONEY32_UNDEFINED; - } - else - { - *cost = res->Cost; - } - *rideIndex = dynamic_cast(res.get())->rideIndex; -} - /** * * rct2: 0x006CFD9D diff --git a/src/openrct2/actions/GameActionCompat.cpp b/src/openrct2/actions/GameActionCompat.cpp index ad155c9fb8..a52ca86900 100644 --- a/src/openrct2/actions/GameActionCompat.cpp +++ b/src/openrct2/actions/GameActionCompat.cpp @@ -91,30 +91,6 @@ void ride_construct_new(ride_list_item listItem) GameActions::Execute(&gameAction); } -money32 ride_create_command(int32_t type, int32_t subType, int32_t flags, ride_id_t* outRideIndex, uint8_t* outRideColour) -{ - int32_t rideEntryIndex = ride_get_entry_index(type, subType); - int32_t colour1 = ride_get_random_colour_preset_index(type); - int32_t colour2 = ride_get_unused_preset_vehicle_colour(rideEntryIndex); - - auto gameAction = RideCreateAction(type, subType, colour1, colour2); - gameAction.SetFlags(flags); - - auto r = GameActions::ExecuteNested(&gameAction); - const RideCreateGameActionResult* res = static_cast(r.get()); - - // Callee's of this function expect MONEY32_UNDEFINED in case of failure. - if (res->Error != GA_ERROR::OK) - { - return MONEY32_UNDEFINED; - } - - *outRideIndex = res->rideIndex; - *outRideColour = colour1; - - return res->Cost; -} - #pragma endregion #pragma region RideSetStatusAction diff --git a/src/openrct2/actions/TrackDesignAction.cpp b/src/openrct2/actions/TrackDesignAction.cpp index e246c40216..b5ea614703 100644 --- a/src/openrct2/actions/TrackDesignAction.cpp +++ b/src/openrct2/actions/TrackDesignAction.cpp @@ -14,6 +14,7 @@ #include "../object/ObjectRepository.h" #include "../ride/RideGroupManager.h" #include "../ride/TrackDesign.h" +#include "RideCreateAction.hpp" #include "RideDemolishAction.hpp" #include "RideSetName.hpp" #include "RideSetSetting.hpp" @@ -34,14 +35,6 @@ GameActionResult::Ptr TrackDesignAction::Query() const res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; _currentTrackPieceDirection = _loc.direction; - if (!(GetFlags() & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)) - { - if (game_is_paused() && !gCheatsBuildInPauseMode) - { - return MakeResult(GA_ERROR::GAME_PAUSED, STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED); - } - } - const rct_object_entry* rideEntryObject = &_td.vehicle_object; uint8_t entryType, entryIndex; @@ -84,10 +77,13 @@ GameActionResult::Ptr TrackDesignAction::Query() const } } - ride_id_t rideIndex; - uint8_t rideColour; - money32 createRideResult = ride_create_command(_td.type, entryIndex, GetFlags(), &rideIndex, &rideColour); - if (createRideResult == MONEY32_UNDEFINED) + // Colours do not matter as will be overwritten + auto rideCreateAction = RideCreateAction(_td.type, entryIndex, 0, 0); + rideCreateAction.SetFlags(GetFlags()); + auto r = GameActions::ExecuteNested(&rideCreateAction); + auto rideIndex = static_cast(r.get())->rideIndex; + + if (r->Error != GA_ERROR::OK) { return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_CANT_CREATE_NEW_RIDE_ATTRACTION, STR_NONE); } @@ -130,14 +126,6 @@ GameActionResult::Ptr TrackDesignAction::Execute() const res->Position.z = _loc.z; res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - if (!(GetFlags() & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)) - { - if (game_is_paused() && !gCheatsBuildInPauseMode) - { - return MakeResult(GA_ERROR::GAME_PAUSED, STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED); - } - } - const rct_object_entry* rideEntryObject = &_td.vehicle_object; uint8_t entryType, entryIndex; @@ -180,10 +168,13 @@ GameActionResult::Ptr TrackDesignAction::Execute() const } } - ride_id_t rideIndex; - uint8_t rideColour; - money32 createRideResult = ride_create_command(_td.type, entryIndex, GetFlags(), &rideIndex, &rideColour); - if (createRideResult == MONEY32_UNDEFINED) + // Colours do not matter as will be overwritten + auto rideCreateAction = RideCreateAction(_td.type, entryIndex, 0, 0); + rideCreateAction.SetFlags(GetFlags()); + auto r = GameActions::ExecuteNested(&rideCreateAction); + auto rideIndex = static_cast(r.get())->rideIndex; + + if (r->Error != GA_ERROR::OK) { return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_CANT_CREATE_NEW_RIDE_ATTRACTION, STR_NONE); } diff --git a/src/openrct2/actions/TrackDesignAction.h b/src/openrct2/actions/TrackDesignAction.h index bbd890bf38..bc09fe7150 100644 --- a/src/openrct2/actions/TrackDesignAction.h +++ b/src/openrct2/actions/TrackDesignAction.h @@ -42,9 +42,8 @@ private: TrackDesign _td; public: - TrackDesignAction() - { - } + TrackDesignAction() = default; + TrackDesignAction(CoordsXYZD location, const TrackDesign& td) : _loc(location) , _td(td) diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index 20400b6101..c4a788e66f 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -1181,7 +1181,6 @@ int32_t ride_get_refund_price(const Ride* ride); int32_t ride_get_random_colour_preset_index(uint8_t ride_type); money32 ride_get_common_price(Ride* forRide); rct_ride_name get_ride_naming(const uint8_t rideType, rct_ride_entry* rideEntry); -money32 ride_create_command(int32_t type, int32_t subType, int32_t flags, ride_id_t* outRideIndex, uint8_t* outRideColour); void ride_clear_for_construction(Ride* ride); void ride_entrance_exit_place_provisional_ghost(); diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 9e9670af13..c59dc32615 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -18,6 +18,7 @@ #include "../actions/LargeSceneryPlaceAction.hpp" #include "../actions/LargeSceneryRemoveAction.hpp" #include "../actions/MazePlaceTrackAction.hpp" +#include "../actions/RideCreateAction.hpp" #include "../actions/RideEntranceExitPlaceAction.hpp" #include "../actions/RideSetName.hpp" #include "../actions/RideSetSetting.hpp" @@ -1830,6 +1831,27 @@ int32_t place_virtual_track( return _trackDesignPlaceCost; } + +money32 track_design_ride_create_command(int32_t type, int32_t subType, int32_t flags, ride_id_t* outRideIndex) +{ + // Don't set colours as will be set correctly later. + auto gameAction = RideCreateAction(type, subType, 0, 0); + gameAction.SetFlags(flags); + + auto r = GameActions::ExecuteNested(&gameAction); + const RideCreateGameActionResult* res = static_cast(r.get()); + + // Callee's of this function expect MONEY32_UNDEFINED in case of failure. + if (res->Error != GA_ERROR::OK) + { + return MONEY32_UNDEFINED; + } + + *outRideIndex = res->rideIndex; + + return res->Cost; +} + /** * * rct2: 0x006D2189 @@ -1848,9 +1870,8 @@ static bool track_design_place_preview(TrackDesign* td6, money32* cost, Ride** o } ride_id_t rideIndex; - uint8_t colour; uint8_t rideCreateFlags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND; - if (ride_create_command(td6->type, entry_index, rideCreateFlags, &rideIndex, &colour) == MONEY32_UNDEFINED) + if (track_design_ride_create_command(td6->type, entry_index, rideCreateFlags, &rideIndex) == MONEY32_UNDEFINED) { return false; } diff --git a/src/openrct2/world/Location.hpp b/src/openrct2/world/Location.hpp index fc02a12663..b1f47281cf 100644 --- a/src/openrct2/world/Location.hpp +++ b/src/openrct2/world/Location.hpp @@ -359,6 +359,12 @@ struct CoordsXYZD : public CoordsXYZ { } + constexpr CoordsXYZD(CoordsXYZ _c, Direction _d) + : CoordsXYZ(_c) + , direction(_d) + { + } + bool operator==(const CoordsXYZD& other) const { return x == other.x && y == other.y && z == other.z && direction == other.direction;