|
|
|
|
@@ -19,7 +19,30 @@
|
|
|
|
|
#include "../world/Surface.h"
|
|
|
|
|
#include "GameAction.h"
|
|
|
|
|
|
|
|
|
|
DEFINE_GAME_ACTION(TrackPlaceAction, GAME_COMMAND_PLACE_TRACK, GameActionResult)
|
|
|
|
|
class TrackPlaceActionResult final : public GameActionResult
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
TrackPlaceActionResult()
|
|
|
|
|
: GameActionResult(GA_ERROR::OK, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
TrackPlaceActionResult(GA_ERROR error)
|
|
|
|
|
: GameActionResult(error, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
TrackPlaceActionResult(GA_ERROR error, rct_string_id message)
|
|
|
|
|
: GameActionResult(error, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, message)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
TrackPlaceActionResult(GA_ERROR error, rct_string_id message, uint8_t* args)
|
|
|
|
|
: GameActionResult(error, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, message, args)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t GroundFlags{ 0 };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
DEFINE_GAME_ACTION(TrackPlaceAction, GAME_COMMAND_PLACE_TRACK, TrackPlaceActionResult)
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
NetworkRideId_t _rideIndex;
|
|
|
|
|
@@ -68,53 +91,47 @@ public:
|
|
|
|
|
if (ride == nullptr)
|
|
|
|
|
{
|
|
|
|
|
log_warning("Invalid ride for track placement, rideIndex = %d", (int32_t)_rideIndex);
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_NONE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
|
|
|
|
|
}
|
|
|
|
|
if (ride->type == RIDE_TYPE_NULL)
|
|
|
|
|
{
|
|
|
|
|
log_warning("Invalid ride type, rideIndex = %d", (int32_t)_rideIndex);
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_NONE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
|
|
|
|
|
}
|
|
|
|
|
rct_ride_entry* rideEntry = get_ride_entry(ride->subtype);
|
|
|
|
|
if (rideEntry == nullptr)
|
|
|
|
|
{
|
|
|
|
|
log_warning("Invalid ride subtype for track placement, rideIndex = %d", (int32_t)_rideIndex);
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_NONE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!direction_valid(_origin.direction))
|
|
|
|
|
{
|
|
|
|
|
log_warning("Invalid direction for track placement, direction = %d", _origin.direction);
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_NONE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto res = std::make_unique<GameActionResult>();
|
|
|
|
|
auto res = std::make_unique<TrackPlaceActionResult>();
|
|
|
|
|
res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
|
|
|
|
res->Position.x = _origin.x + 16;
|
|
|
|
|
res->Position.y = _origin.y + 16;
|
|
|
|
|
res->Position.z = _origin.z;
|
|
|
|
|
|
|
|
|
|
gTrackGroundFlags = 0;
|
|
|
|
|
res->GroundFlags = 0;
|
|
|
|
|
|
|
|
|
|
uint32_t rideTypeFlags = RideProperties[ride->type].flags;
|
|
|
|
|
|
|
|
|
|
if ((ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && _trackType == TRACK_ELEM_END_STATION)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_NOT_ALLOWED_TO_MODIFY_STATION);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_NOT_ALLOWED_TO_MODIFY_STATION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(GetActionFlags() & GA_FLAGS::ALLOW_WHILE_PAUSED))
|
|
|
|
|
{
|
|
|
|
|
if (game_is_paused() && !gCheatsBuildInPauseMode)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -124,18 +141,15 @@ public:
|
|
|
|
|
{
|
|
|
|
|
if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_ONLY_ONE_ON_RIDE_PHOTO_PER_RIDE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_ONLY_ONE_ON_RIDE_PHOTO_PER_RIDE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (_trackType == TRACK_ELEM_CABLE_LIFT_HILL)
|
|
|
|
|
{
|
|
|
|
|
if (ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT_HILL_COMPONENT_USED)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_ONLY_ONE_CABLE_LIFT_HILL_PER_RIDE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_ONLY_ONE_CABLE_LIFT_HILL_PER_RIDE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Backwards steep lift hills are allowed, even on roller coasters that do not support forwards steep lift hills.
|
|
|
|
|
@@ -145,8 +159,7 @@ public:
|
|
|
|
|
{
|
|
|
|
|
if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_IS_STEEP_UP)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_STEEP_FOR_LIFT_HILL);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_TOO_STEEP_FOR_LIFT_HILL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -166,8 +179,7 @@ public:
|
|
|
|
|
|
|
|
|
|
if (!map_is_location_owned(tileCoords.x, tileCoords.y, tileCoords.z) && !gCheatsSandboxMode)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_LAND_NOT_OWNED_BY_PARK);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_LAND_NOT_OWNED_BY_PARK);
|
|
|
|
|
}
|
|
|
|
|
numElements++;
|
|
|
|
|
}
|
|
|
|
|
@@ -175,24 +187,21 @@ public:
|
|
|
|
|
if (!map_check_free_elements_and_reorganise(numElements))
|
|
|
|
|
{
|
|
|
|
|
log_warning("Not enough free map elments to place track.");
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::NO_FREE_ELEMENTS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TILE_ELEMENT_LIMIT_REACHED);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::NO_FREE_ELEMENTS, STR_TILE_ELEMENT_LIMIT_REACHED);
|
|
|
|
|
}
|
|
|
|
|
const uint16_t* trackFlags = (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE) ? FlatTrackFlags : TrackFlags;
|
|
|
|
|
if (trackFlags[_trackType] & TRACK_ELEM_FLAG_STARTS_AT_HALF_HEIGHT)
|
|
|
|
|
{
|
|
|
|
|
if ((_origin.z & 0x0F) != 8)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CONSTRUCTION_ERR_UNKNOWN);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_CONSTRUCTION_ERR_UNKNOWN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((_origin.z & 0x0F) != 0)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CONSTRUCTION_ERR_UNKNOWN);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_CONSTRUCTION_ERR_UNKNOWN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -211,8 +220,7 @@ public:
|
|
|
|
|
|
|
|
|
|
if (mapLoc.z < 16)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_LOW);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_TOO_LOW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t baseZ = mapLoc.z / 8;
|
|
|
|
|
@@ -231,8 +239,7 @@ public:
|
|
|
|
|
|
|
|
|
|
if (clearanceZ >= 255)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_HIGH);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS, STR_TOO_HIGH);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t crossingMode = (ride->type == RIDE_TYPE_MINIATURE_RAILWAY && _trackType == TRACK_ELEM_FLAT)
|
|
|
|
|
@@ -242,29 +249,26 @@ public:
|
|
|
|
|
mapLoc.x, mapLoc.y, baseZ, clearanceZ, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &cost,
|
|
|
|
|
crossingMode))
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::NO_CLEARANCE, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, gGameCommandErrorText,
|
|
|
|
|
gCommonFormatArgs);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::NO_CLEARANCE, gGameCommandErrorText, gCommonFormatArgs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t mapGroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
|
|
|
|
|
if (gTrackGroundFlags != 0 && (gTrackGroundFlags & mapGroundFlags) == 0)
|
|
|
|
|
if (res->GroundFlags != 0 && (res->GroundFlags & mapGroundFlags) == 0)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gTrackGroundFlags = mapGroundFlags;
|
|
|
|
|
res->GroundFlags = mapGroundFlags;
|
|
|
|
|
if (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE)
|
|
|
|
|
{
|
|
|
|
|
if (FlatTrackFlags[_trackType] & TRACK_ELEM_FLAG_ONLY_ABOVE_GROUND)
|
|
|
|
|
{
|
|
|
|
|
if (gTrackGroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND)
|
|
|
|
|
if (res->GroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -272,11 +276,10 @@ public:
|
|
|
|
|
{
|
|
|
|
|
if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_ONLY_ABOVE_GROUND)
|
|
|
|
|
{
|
|
|
|
|
if (gTrackGroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND)
|
|
|
|
|
if (res->GroundFlags & TRACK_ELEMENT_LOCATION_IS_UNDERGROUND)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -287,9 +290,8 @@ public:
|
|
|
|
|
{
|
|
|
|
|
if (!(gMapGroundFlags & ELEMENT_IS_UNDERWATER))
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CAN_ONLY_BUILD_THIS_UNDERWATER);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_CAN_ONLY_BUILD_THIS_UNDERWATER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -299,17 +301,15 @@ public:
|
|
|
|
|
{ // No element has this flag
|
|
|
|
|
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CAN_ONLY_BUILD_THIS_UNDERWATER);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_CAN_ONLY_BUILD_THIS_UNDERWATER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER && !gCheatsDisableClearanceChecks)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_RIDE_CANT_BUILD_THIS_UNDERWATER);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_RIDE_CANT_BUILD_THIS_UNDERWATER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((rideTypeFlags & RIDE_TYPE_FLAG_TRACK_MUST_BE_ON_WATER) && !byte_9D8150)
|
|
|
|
|
@@ -319,14 +319,12 @@ public:
|
|
|
|
|
uint8_t waterHeight = tileElement->AsSurface()->GetWaterHeight() * 2;
|
|
|
|
|
if (waterHeight == 0)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CAN_ONLY_BUILD_THIS_ON_WATER);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_CAN_ONLY_BUILD_THIS_ON_WATER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (waterHeight != baseZ)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CAN_ONLY_BUILD_THIS_ON_WATER);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_CAN_ONLY_BUILD_THIS_ON_WATER);
|
|
|
|
|
}
|
|
|
|
|
waterHeight -= 2;
|
|
|
|
|
if (waterHeight == tileElement->base_height)
|
|
|
|
|
@@ -335,9 +333,7 @@ public:
|
|
|
|
|
if (slope == TILE_ELEMENT_SLOPE_W_CORNER_DN || slope == TILE_ELEMENT_SLOPE_S_CORNER_DN
|
|
|
|
|
|| slope == TILE_ELEMENT_SLOPE_E_CORNER_DN || slope == TILE_ELEMENT_SLOPE_N_CORNER_DN)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CAN_ONLY_BUILD_THIS_ON_WATER);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_CAN_ONLY_BUILD_THIS_ON_WATER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -355,8 +351,7 @@ public:
|
|
|
|
|
{
|
|
|
|
|
if (!track_add_station_element(mapLoc.x, mapLoc.y, baseZ, _origin.direction, _rideIndex, 0))
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::UNKNOWN, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, gGameCommandErrorText);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::UNKNOWN, gGameCommandErrorText);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -386,8 +381,7 @@ public:
|
|
|
|
|
ride_height /= 2;
|
|
|
|
|
if (ride_height > maxHeight && !byte_9D8150)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_TOO_HIGH_FOR_SUPPORTS);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::DISALLOWED, STR_TOO_HIGH_FOR_SUPPORTS);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -415,25 +409,23 @@ public:
|
|
|
|
|
if (ride == nullptr)
|
|
|
|
|
{
|
|
|
|
|
log_warning("Invalid ride for track placement, rideIndex = %d", (int32_t)_rideIndex);
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rct_ride_entry* rideEntry = get_ride_entry(ride->subtype);
|
|
|
|
|
if (rideEntry == nullptr)
|
|
|
|
|
{
|
|
|
|
|
log_warning("Invalid ride subtype for track placement, rideIndex = %d", (int32_t)_rideIndex);
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::INVALID_PARAMETERS, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(GA_ERROR::INVALID_PARAMETERS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto res = std::make_unique<GameActionResult>();
|
|
|
|
|
auto res = std::make_unique<TrackPlaceActionResult>();
|
|
|
|
|
res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
|
|
|
|
res->Position.x = _origin.x + 16;
|
|
|
|
|
res->Position.y = _origin.y + 16;
|
|
|
|
|
res->Position.z = _origin.z;
|
|
|
|
|
|
|
|
|
|
gTrackGroundFlags = 0;
|
|
|
|
|
res->GroundFlags = 0;
|
|
|
|
|
|
|
|
|
|
uint32_t rideTypeFlags = RideProperties[ride->type].flags;
|
|
|
|
|
|
|
|
|
|
@@ -483,9 +475,8 @@ public:
|
|
|
|
|
mapLoc.x, mapLoc.y, baseZ, clearanceZ, &map_place_non_scenery_clear_func, quarterTile,
|
|
|
|
|
GetFlags() | GAME_COMMAND_FLAG_APPLY, &cost, crossingMode))
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::NO_CLEARANCE, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, gGameCommandErrorText,
|
|
|
|
|
gCommonFormatArgs);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::NO_CLEARANCE, gGameCommandErrorText, gCommonFormatArgs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !gCheatsDisableClearanceChecks)
|
|
|
|
|
@@ -511,14 +502,13 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t mapGroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
|
|
|
|
|
if (gTrackGroundFlags != 0 && (gTrackGroundFlags & mapGroundFlags) == 0)
|
|
|
|
|
if (res->GroundFlags != 0 && (res->GroundFlags & mapGroundFlags) == 0)
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<GameActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE,
|
|
|
|
|
STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND);
|
|
|
|
|
return std::make_unique<TrackPlaceActionResult>(
|
|
|
|
|
GA_ERROR::DISALLOWED, STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gTrackGroundFlags = mapGroundFlags;
|
|
|
|
|
res->GroundFlags = mapGroundFlags;
|
|
|
|
|
|
|
|
|
|
// 6c5648 12 push
|
|
|
|
|
tileElement = map_get_surface_element_at({ mapLoc.x, mapLoc.y });
|
|
|
|
|
|