diff --git a/src/openrct2/actions/RideEntranceExitPlaceAction.hpp b/src/openrct2/actions/RideEntranceExitPlaceAction.hpp index d8a269a88e..4f0720c885 100644 --- a/src/openrct2/actions/RideEntranceExitPlaceAction.hpp +++ b/src/openrct2/actions/RideEntranceExitPlaceAction.hpp @@ -9,16 +9,18 @@ #pragma once +#include "../actions/RideEntranceExitRemoveAction.hpp" #include "../ride/Ride.h" #include "../ride/Station.h" #include "../world/Entrance.h" -#include "../actions/RideEntranceExitRemoveAction.hpp" +#include "../world/MapAnimation.h" #include "GameAction.h" DEFINE_GAME_ACTION(RideEntranceExitPlaceAction, GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, GameActionResult) { private: - CoordsXYZD _loc; + CoordsXY _loc; + Direction _direction; NetworkRideId_t _rideIndex; uint8_t _stationNum; bool _isExit; @@ -26,8 +28,9 @@ private: public: RideEntranceExitPlaceAction() = default; - RideEntranceExitPlaceAction(CoordsXYZD loc, ride_id_t rideIndex, uint8_t stationNum, bool isExit) + RideEntranceExitPlaceAction(CoordsXY loc, Direction direction, ride_id_t rideIndex, uint8_t stationNum, bool isExit) : _loc(loc) + , _direction(direction) , _rideIndex(rideIndex) , _stationNum(stationNum) , _isExit(isExit) @@ -48,158 +51,125 @@ public: GameActionResult::Ptr Query() const override { - // Remember when in unknown station num mode rideIndex is unknown and z is set - // When in known station num mode rideIndex is known and z is unknown - auto errorTitle = _isExit ? STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION: - STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION; + auto errorTitle = _isExit ? STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION + : STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION; if (!map_check_free_elements_and_reorganise(1)) { return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, errorTitle); } - if (_stationNum == 0xFF) + if (_rideIndex >= MAX_RIDES || _rideIndex == RIDE_ID_NULL) { - auto z = _loc.z * 16; + log_warning("Invalid game command for ride %u", _rideIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle); + } - if (!gCheatsSandboxMode && !map_is_location_owned(_loc.x, _loc.y, z)) - { - return MakeResult(GA_ERROR::NOT_OWNED, errorTitle); - } + Ride* ride = get_ride(_rideIndex); + if (ride == nullptr || ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", _rideIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle); + } - int16_t clear_z = z / 8 + (_isExit ? 5 : 7); - auto cost = MONEY32_UNDEFINED; - if (!map_can_construct_with_clear_at( - _loc.x, _loc.y, z / 8, clear_z, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags(), &cost, - CREATE_CROSSING_MODE_NONE)) - { - return MakeResult(GA_ERROR::NO_CLEARANCE, errorTitle, gGameCommandErrorText, gCommonFormatArgs); - } + if (_stationNum > MAX_STATIONS) + { + log_warning("Invalid station number for ride. stationNum: %u", _stationNum); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle); + } - if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) - { - return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER); - } + if (ride->status != RIDE_STATUS_CLOSED) + { + return MakeResult(GA_ERROR::NOT_CLOSED, errorTitle, STR_MUST_BE_CLOSED_FIRST); + } - if (z / 8 > 244) + if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) + { + return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_NOT_ALLOWED_TO_MODIFY_STATION); + } + + ride_clear_for_construction(ride); + ride_remove_peeps(ride); + + bool requiresRemove = false; + LocationXY16 removeCoord = { 0, 0 }; + + if (_isExit) + { + const auto exit = ride_get_exit_location(ride, _stationNum); + if (!exit.isNull()) { - return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_TOO_HIGH); + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) + { + return MakeResult(GA_ERROR::DISALLOWED, errorTitle); + } + + removeCoord.x = exit.x * 32; + removeCoord.y = exit.y * 32; + requiresRemove = true; } - auto res = MakeResult(); - res->Position.x = _loc.x + 16; - res->Position.y = _loc.y + 16; - res->Position.z = tile_element_height(_loc.x, _loc.y); - res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - return res; } else { - if (_rideIndex >= MAX_RIDES || _rideIndex == RIDE_ID_NULL) + const auto entrance = ride_get_entrance_location(ride, _stationNum); + if (!entrance.isNull()) { - log_warning("Invalid game command for ride %u", _rideIndex); - return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle); - } - - Ride* ride = get_ride(_rideIndex); - if (ride == nullptr || ride->type == RIDE_TYPE_NULL) - { - log_warning("Invalid game command for ride %u", _rideIndex); - return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle); - } - - if (ride->status != RIDE_STATUS_CLOSED) - { - return MakeResult(GA_ERROR::NOT_CLOSED, errorTitle, STR_MUST_BE_CLOSED_FIRST); - } - - if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) - { - return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_NOT_ALLOWED_TO_MODIFY_STATION); - } - - ride_clear_for_construction(ride); - ride_remove_peeps(ride); - - bool requiresRemove = false; - LocationXY16 removeCoord = { 0, 0 }; - - if (_isExit) - { - const auto exit = ride_get_exit_location(ride, _stationNum); - if (!exit.isNull()) + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) { - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - return MakeResult(GA_ERROR::DISALLOWED, errorTitle); - } - - removeCoord.x = exit.x * 32; - removeCoord.y = exit.y * 32; - requiresRemove = true; + return MakeResult(GA_ERROR::DISALLOWED, errorTitle); } + + removeCoord.x = entrance.x * 32; + removeCoord.y = entrance.y * 32; + requiresRemove = true; } - else - { - const auto entrance = ride_get_entrance_location(ride, _stationNum); - if (!entrance.isNull()) - { - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - return MakeResult(GA_ERROR::DISALLOWED, errorTitle); - } - - removeCoord.x = entrance.x * 32; - removeCoord.y = entrance.y * 32; - requiresRemove = true; - } - } - - if (requiresRemove) - { - auto rideEntranceExitRemove = RideEntranceExitRemoveAction( - { removeCoord.x, removeCoord.y }, _rideIndex, _stationNum, _isExit); - rideEntranceExitRemove.SetFlags(GetFlags()); - - auto result = GameActions::QueryNested(&rideEntranceExitRemove); - if (result->Error != GA_ERROR::OK) - { - return result; - } - } - - auto z = ride->stations[_stationNum].Height * 8; - gCommandPosition.z = z; - - if (!gCheatsSandboxMode && !map_is_location_owned(_loc.x, _loc.y, z)) - { - return MakeResult(GA_ERROR::NOT_OWNED, errorTitle); - } - - int8_t clear_z = (z / 8) + (_isExit ? 5 : 7); - auto cost = MONEY32_UNDEFINED; - if (!map_can_construct_with_clear_at( - _loc.x, _loc.y, z / 8, clear_z, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags(), &cost, - CREATE_CROSSING_MODE_NONE)) - { - return MakeResult(GA_ERROR::NO_CLEARANCE, errorTitle, gGameCommandErrorText, gCommonFormatArgs); - } - - if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) - { - return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER); - } - - if (z / 8 > 244) - { - return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_TOO_HIGH); - } - - auto res = MakeResult(); - res->Position.x = _loc.x + 16; - res->Position.y = _loc.y + 16; - res->Position.z = tile_element_height(_loc.x, _loc.y); - res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - return res; } + + if (requiresRemove) + { + auto rideEntranceExitRemove = RideEntranceExitRemoveAction( + { removeCoord.x, removeCoord.y }, _rideIndex, _stationNum, _isExit); + rideEntranceExitRemove.SetFlags(GetFlags()); + + auto result = GameActions::QueryNested(&rideEntranceExitRemove); + if (result->Error != GA_ERROR::OK) + { + return result; + } + } + + auto z = ride->stations[_stationNum].Height * 8; + gCommandPosition.z = z; + + if (!gCheatsSandboxMode && !map_is_location_owned(_loc.x, _loc.y, z)) + { + return MakeResult(GA_ERROR::NOT_OWNED, errorTitle); + } + + int8_t clear_z = (z / 8) + (_isExit ? 5 : 7); + auto cost = MONEY32_UNDEFINED; + if (!map_can_construct_with_clear_at( + _loc.x, _loc.y, z / 8, clear_z, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags(), &cost, + CREATE_CROSSING_MODE_NONE)) + { + return MakeResult(GA_ERROR::NO_CLEARANCE, errorTitle, gGameCommandErrorText, gCommonFormatArgs); + } + + if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) + { + return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER); + } + + if (z / 8 > 244) + { + return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_TOO_HIGH); + } + + auto res = MakeResult(); + res->Position.x = _loc.x + 16; + res->Position.y = _loc.y + 16; + res->Position.z = tile_element_height(_loc.x, _loc.y); + res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + return res; } GameActionResult::Ptr Execute() const override @@ -208,126 +178,159 @@ public: // When in known station num mode rideIndex is known and z is unknown auto errorTitle = _isExit ? STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION : STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION; - if (_stationNum == 0xFF) + Ride* ride = get_ride(_rideIndex); + if (ride == nullptr || ride->type == RIDE_TYPE_NULL) { - return MakeResult(GA_ERROR::UNKNOWN, errorTitle); + log_warning("Invalid game command for ride %u", _rideIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle); + } + + ride_clear_for_construction(ride); + ride_remove_peeps(ride); + + bool requiresRemove = false; + LocationXY16 removeCoord = { 0, 0 }; + + if (_isExit) + { + const auto exit = ride_get_exit_location(ride, _stationNum); + if (!exit.isNull()) + { + removeCoord.x = exit.x * 32; + removeCoord.y = exit.y * 32; + requiresRemove = true; + } } else { - Ride* ride = get_ride(_rideIndex); - if (ride == nullptr || ride->type == RIDE_TYPE_NULL) + const auto entrance = ride_get_entrance_location(ride, _stationNum); + if (!entrance.isNull()) { - log_warning("Invalid game command for ride %u", _rideIndex); - return MakeResult(GA_ERROR::INVALID_PARAMETERS, errorTitle); + removeCoord.x = entrance.x * 32; + removeCoord.y = entrance.y * 32; + requiresRemove = true; } - - ride_clear_for_construction(ride); - ride_remove_peeps(ride); - - bool requiresRemove = false; - LocationXY16 removeCoord = { 0, 0 }; - - if (_isExit) - { - const auto exit = ride_get_exit_location(ride, _stationNum); - if (!exit.isNull()) - { - removeCoord.x = exit.x * 32; - removeCoord.y = exit.y * 32; - requiresRemove = true; - } - } - else - { - const auto entrance = ride_get_entrance_location(ride, _stationNum); - if (!entrance.isNull()) - { - removeCoord.x = entrance.x * 32; - removeCoord.y = entrance.y * 32; - requiresRemove = true; - } - } - - if (requiresRemove) - { - auto rideEntranceExitRemove = RideEntranceExitRemoveAction( - { removeCoord.x, removeCoord.y }, _rideIndex, _stationNum, _isExit); - rideEntranceExitRemove.SetFlags(GetFlags()); - - auto result = GameActions::ExecuteNested(&rideEntranceExitRemove); - if (result->Error != GA_ERROR::OK) - { - return result; - } - } - - auto z = ride->stations[_stationNum].Height * 8; - gCommandPosition.z = z; - - if (!(GetFlags() & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) - && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - footpath_remove_litter(_loc.x, _loc.y, z); - wall_remove_at_z(_loc.x, _loc.y, z); - } - - int8_t clear_z = (z / 8) + (_isExit ? 5 : 7); - auto cost = MONEY32_UNDEFINED; - if (!map_can_construct_with_clear_at( - _loc.x, _loc.y, z / 8, clear_z, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags(), &cost, - CREATE_CROSSING_MODE_NONE)) - { - return MakeResult(GA_ERROR::NO_CLEARANCE, errorTitle, gGameCommandErrorText, gCommonFormatArgs); - } - - auto res = MakeResult(); - res->Position.x = _loc.x + 16; - res->Position.y = _loc.y + 16; - res->Position.z = tile_element_height(_loc.x, _loc.y); - res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - - TileElement* tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, z / 8, 0b1111); - assert(tileElement != nullptr); - tileElement->SetType(TILE_ELEMENT_TYPE_ENTRANCE); - tileElement->SetDirection(_loc.direction); - tileElement->clearance_height = clear_z; - tileElement->AsEntrance()->SetEntranceType(_isExit ? ENTRANCE_TYPE_RIDE_EXIT : ENTRANCE_TYPE_RIDE_ENTRANCE); - tileElement->AsEntrance()->SetStationIndex(_stationNum); - tileElement->AsEntrance()->SetRideIndex(_rideIndex); - - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - tileElement->SetGhost(true); - } - - if (_isExit) - { - ride_set_exit_location( - ride, _stationNum, { _loc.x / 32, _loc.y / 32, z / 8, (uint8_t)tileElement->GetDirection() }); - } - else - { - ride_set_entrance_location( - ride, _stationNum, { _loc.x / 32, _loc.y / 32, z / 8, (uint8_t)tileElement->GetDirection() }); - ride->stations[_stationNum].LastPeepInQueue = SPRITE_INDEX_NULL; - ride->stations[_stationNum].QueueLength = 0; - - map_animation_create(MAP_ANIMATION_TYPE_RIDE_ENTRANCE, _loc.x, _loc.y, z / 8); - } - - footpath_queue_chain_reset(); - - if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) - { - maze_entrance_hedge_removal(_loc.x, _loc.y, tileElement); - } - - footpath_connect_edges(_loc.x, _loc.y, tileElement, GetFlags()); - footpath_update_queue_chains(); - - map_invalidate_tile_full(_loc.x, _loc.y); - - return res; } + + if (requiresRemove) + { + auto rideEntranceExitRemove = RideEntranceExitRemoveAction( + { removeCoord.x, removeCoord.y }, _rideIndex, _stationNum, _isExit); + rideEntranceExitRemove.SetFlags(GetFlags()); + + auto result = GameActions::ExecuteNested(&rideEntranceExitRemove); + if (result->Error != GA_ERROR::OK) + { + return result; + } + } + + auto z = ride->stations[_stationNum].Height * 8; + gCommandPosition.z = z; + + if (!(GetFlags() & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + footpath_remove_litter(_loc.x, _loc.y, z); + wall_remove_at_z(_loc.x, _loc.y, z); + } + + int8_t clear_z = (z / 8) + (_isExit ? 5 : 7); + auto cost = MONEY32_UNDEFINED; + if (!map_can_construct_with_clear_at( + _loc.x, _loc.y, z / 8, clear_z, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags(), &cost, + CREATE_CROSSING_MODE_NONE)) + { + return MakeResult(GA_ERROR::NO_CLEARANCE, errorTitle, gGameCommandErrorText, gCommonFormatArgs); + } + + auto res = MakeResult(); + res->Position.x = _loc.x + 16; + res->Position.y = _loc.y + 16; + res->Position.z = tile_element_height(_loc.x, _loc.y); + res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + + TileElement* tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, z / 8, 0b1111); + assert(tileElement != nullptr); + tileElement->SetType(TILE_ELEMENT_TYPE_ENTRANCE); + tileElement->SetDirection(_direction); + tileElement->clearance_height = clear_z; + tileElement->AsEntrance()->SetEntranceType(_isExit ? ENTRANCE_TYPE_RIDE_EXIT : ENTRANCE_TYPE_RIDE_ENTRANCE); + tileElement->AsEntrance()->SetStationIndex(_stationNum); + tileElement->AsEntrance()->SetRideIndex(_rideIndex); + + if (GetFlags() & GAME_COMMAND_FLAG_GHOST) + { + tileElement->SetGhost(true); + } + + if (_isExit) + { + ride_set_exit_location( + ride, _stationNum, { _loc.x / 32, _loc.y / 32, z / 8, (uint8_t)tileElement->GetDirection() }); + } + else + { + ride_set_entrance_location( + ride, _stationNum, { _loc.x / 32, _loc.y / 32, z / 8, (uint8_t)tileElement->GetDirection() }); + ride->stations[_stationNum].LastPeepInQueue = SPRITE_INDEX_NULL; + ride->stations[_stationNum].QueueLength = 0; + + map_animation_create(MAP_ANIMATION_TYPE_RIDE_ENTRANCE, _loc.x, _loc.y, z / 8); + } + + footpath_queue_chain_reset(); + + if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) + { + maze_entrance_hedge_removal(_loc.x, _loc.y, tileElement); + } + + footpath_connect_edges(_loc.x, _loc.y, tileElement, GetFlags()); + footpath_update_queue_chains(); + + map_invalidate_tile_full(_loc.x, _loc.y); + + return res; + } + + static GameActionResult::Ptr TrackPlaceQuery(const CoordsXYZ loc, const bool isExit) + { + auto errorTitle = isExit ? STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION + : STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION; + if (!map_check_free_elements_and_reorganise(1)) + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, errorTitle); + } + + if (!gCheatsSandboxMode && !map_is_location_owned(loc.x, loc.y, loc.z)) + { + return MakeResult(GA_ERROR::NOT_OWNED, errorTitle); + } + + int16_t baseZ = loc.z / 8; + int16_t clearZ = baseZ + (isExit ? 5 : 7); + auto cost = MONEY32_UNDEFINED; + if (!map_can_construct_with_clear_at( + loc.x, loc.y, baseZ, clearZ, &map_place_non_scenery_clear_func, { 0b1111, 0 }, 0, &cost, + CREATE_CROSSING_MODE_NONE)) + { + return MakeResult(GA_ERROR::NO_CLEARANCE, errorTitle, gGameCommandErrorText, gCommonFormatArgs); + } + + if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) + { + return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER); + } + + if (baseZ > 244) + { + return MakeResult(GA_ERROR::DISALLOWED, errorTitle, STR_TOO_HIGH); + } + auto res = MakeResult(); + res->Position.x = loc.x + 16; + res->Position.y = loc.y + 16; + res->Position.z = tile_element_height(loc.x, loc.y); + res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + return res; } }; diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 1a717d31c1..005ccb117a 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -13,6 +13,7 @@ #include "../Game.h" #include "../OpenRCT2.h" #include "../actions/LargeSceneryRemoveAction.hpp" +#include "../actions/RideEntranceExitPlaceAction.hpp" #include "../actions/RideSetSetting.hpp" #include "../actions/RideSetVehiclesAction.hpp" #include "../actions/SmallSceneryPlaceAction.hpp" @@ -1217,9 +1218,8 @@ static int32_t track_design_place_maze(rct_track_td6* td6, int16_t x, int16_t y, if (_trackDesignPlaceOperation == PTD_OPERATION_1) { - cost = game_do_command( - mapCoord.x, 0 | rotation << 8, mapCoord.y, (z / 16) & 0xFF, - GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, -1, 0); + auto res = RideEntranceExitPlaceAction::TrackPlaceQuery({mapCoord.x, mapCoord.y, z}, false); + cost = res->Error == GA_ERROR::OK ? res->Cost : MONEY32_UNDEFINED; } else { @@ -1251,9 +1251,8 @@ static int32_t track_design_place_maze(rct_track_td6* td6, int16_t x, int16_t y, if (_trackDesignPlaceOperation == PTD_OPERATION_1) { - cost = game_do_command( - mapCoord.x, 0 | rotation << 8, mapCoord.y, ((z / 16) & 0xFF) | (1 << 8), - GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, -1, 0); + auto res = RideEntranceExitPlaceAction::TrackPlaceQuery({ mapCoord.x, mapCoord.y, z }, true); + cost = res->Error == GA_ERROR::OK ? res->Cost : MONEY32_UNDEFINED; } else { @@ -1635,19 +1634,16 @@ static bool track_design_place_ride(rct_track_td6* td6, int16_t x, int16_t y, in z = (entrance->z == (int8_t)(uint8_t)0x80) ? -1 : entrance->z; z *= 8; z += gTrackPreviewOrigin.z; - z >>= 4; - gGameCommandErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; - money32 cost = game_do_command( - x, 0 | (rotation << 8), y, z | (isExit << 8), GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, -1, 0); - if (cost == MONEY32_UNDEFINED) + auto res = RideEntranceExitPlaceAction::TrackPlaceQuery({ x, y, z }, false); + if (res->Error != GA_ERROR::OK) { - _trackDesignPlaceCost = cost; + _trackDesignPlaceCost = MONEY32_UNDEFINED; return false; } else { - _trackDesignPlaceCost += cost; + _trackDesignPlaceCost += res->Cost; _trackDesignPlaceStateEntranceExitPlaced = true; } }