1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

Remove map_can_construct[_with_clear]_at() and gMapGroundFlags

This commit is contained in:
Michael Steenbeek
2021-06-13 10:13:13 +02:00
committed by GitHub
parent 6b1141b5a2
commit 474e00d48b
10 changed files with 115 additions and 143 deletions

View File

@@ -248,16 +248,17 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertQuery(GameActions::Re
uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT) uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT)
? CREATE_CROSSING_MODE_NONE ? CREATE_CROSSING_MODE_NONE
: CREATE_CROSSING_MODE_PATH_OVER_TRACK; : CREATE_CROSSING_MODE_PATH_OVER_TRACK;
if (!entrancePath auto canBuild = MapCanConstructWithClearAt(
&& !map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), crossingMode);
{ _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, crossingMode)) if (!entrancePath && canBuild->Error != GameActions::Status::Ok)
{ {
return MakeResult( canBuild->ErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE;
GameActions::Status::NoClearance, STR_CANT_BUILD_FOOTPATH_HERE, gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
res->Cost += canBuild->Cost;
gFootpathGroundFlags = gMapGroundFlags; gFootpathGroundFlags = canBuild->GroundFlags;
if (!gCheatsDisableClearanceChecks && (gMapGroundFlags & ELEMENT_IS_UNDERWATER)) if (!gCheatsDisableClearanceChecks && (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER))
{ {
return MakeResult(GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_CANT_BUILD_THIS_UNDERWATER); return MakeResult(GameActions::Status::Disallowed, STR_CANT_BUILD_FOOTPATH_HERE, STR_CANT_BUILD_THIS_UNDERWATER);
} }
@@ -318,11 +319,12 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions::
crossingMode); crossingMode);
if (!entrancePath && canBuild->Error != GameActions::Status::Ok) if (!entrancePath && canBuild->Error != GameActions::Status::Ok)
{ {
canBuild->ErrorTitle = STR_CANT_BUILD_FOOTPATH_HERE;
return canBuild; return canBuild;
} }
res->Cost += canBuild->Cost; res->Cost += canBuild->Cost;
gFootpathGroundFlags = gMapGroundFlags; gFootpathGroundFlags = canBuild->GroundFlags;
auto surfaceElement = map_get_surface_element_at(_loc); auto surfaceElement = map_get_surface_element_at(_loc);
if (surfaceElement == nullptr) if (surfaceElement == nullptr)

View File

@@ -132,17 +132,17 @@ GameActions::Result::Ptr FootpathPlaceFromTrackAction::ElementInsertQuery(GameAc
uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT) uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT)
? CREATE_CROSSING_MODE_NONE ? CREATE_CROSSING_MODE_NONE
: CREATE_CROSSING_MODE_PATH_OVER_TRACK; : CREATE_CROSSING_MODE_PATH_OVER_TRACK;
if (!entrancePath auto canBuild = MapCanConstructWithClearAt(
&& !map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), crossingMode);
{ _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &res->Cost, crossingMode)) if (!entrancePath && canBuild->Error != GameActions::Status::Ok)
{ {
return MakeResult( canBuild->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
GameActions::Status::NoClearance, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, gGameCommandErrorText, return canBuild;
gCommonFormatArgs);
} }
res->Cost += canBuild->Cost;
gFootpathGroundFlags = canBuild->GroundFlags;
gFootpathGroundFlags = gMapGroundFlags; if (!gCheatsDisableClearanceChecks && (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER))
if (!gCheatsDisableClearanceChecks && (gMapGroundFlags & ELEMENT_IS_UNDERWATER))
{ {
return MakeResult( return MakeResult(
GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CANT_BUILD_THIS_UNDERWATER); GameActions::Status::Disallowed, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, STR_CANT_BUILD_THIS_UNDERWATER);
@@ -199,17 +199,16 @@ GameActions::Result::Ptr FootpathPlaceFromTrackAction::ElementInsertExecute(Game
uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT) uint8_t crossingMode = (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) || (_slope != TILE_ELEMENT_SLOPE_FLAT)
? CREATE_CROSSING_MODE_NONE ? CREATE_CROSSING_MODE_NONE
: CREATE_CROSSING_MODE_PATH_OVER_TRACK; : CREATE_CROSSING_MODE_PATH_OVER_TRACK;
if (!entrancePath auto canBuild = MapCanConstructWithClearAt(
&& !map_can_construct_with_clear_at(
{ _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(), { _loc, zLow, zHigh }, &map_place_non_scenery_clear_func, quarterTile, GAME_COMMAND_FLAG_APPLY | GetFlags(),
&res->Cost, crossingMode)) crossingMode);
if (!entrancePath && canBuild->Error != GameActions::Status::Ok)
{ {
return MakeResult( canBuild->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
GameActions::Status::NoClearance, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE, gGameCommandErrorText, return canBuild;
gCommonFormatArgs);
} }
res->Cost += canBuild->Cost;
gFootpathGroundFlags = gMapGroundFlags; gFootpathGroundFlags = canBuild->GroundFlags;
auto surfaceElement = map_get_surface_element_at(_loc); auto surfaceElement = map_get_surface_element_at(_loc);
if (surfaceElement == nullptr) if (surfaceElement == nullptr)

View File

@@ -160,18 +160,22 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Query() const
int32_t zHigh = tile->z_clearance + zLow; int32_t zHigh = tile->z_clearance + zLow;
QuarterTile quarterTile = QuarterTile{ static_cast<uint8_t>(tile->flags >> 12), 0 }.Rotate(_loc.direction); QuarterTile quarterTile = QuarterTile{ static_cast<uint8_t>(tile->flags >> 12), 0 }.Rotate(_loc.direction);
if (!map_can_construct_with_clear_at( const auto isTree = (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0;
{ curTile, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), &supportsCost, auto canBuild = MapCanConstructWithClearAt(
CREATE_CROSSING_MODE_NONE, (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0)) { curTile, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), CREATE_CROSSING_MODE_NONE,
isTree);
if (canBuild->Error != GameActions::Status::Ok)
{ {
return std::make_unique<LargeSceneryPlaceActionResult>( canBuild->ErrorTitle = STR_CANT_POSITION_THIS_HERE;
GameActions::Status::NoClearance, gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
int32_t tempSceneryGroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND); supportsCost += canBuild->Cost;
int32_t tempSceneryGroundFlags = canBuild->GroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
if (!gCheatsDisableClearanceChecks) if (!gCheatsDisableClearanceChecks)
{ {
if ((gMapGroundFlags & ELEMENT_IS_UNDERWATER) || (gMapGroundFlags & ELEMENT_IS_UNDERGROUND)) if ((canBuild->GroundFlags & ELEMENT_IS_UNDERWATER) || (canBuild->GroundFlags & ELEMENT_IS_UNDERGROUND))
{ {
return std::make_unique<LargeSceneryPlaceActionResult>( return std::make_unique<LargeSceneryPlaceActionResult>(
GameActions::Status::Disallowed, STR_CANT_BUILD_THIS_UNDERWATER); GameActions::Status::Disallowed, STR_CANT_BUILD_THIS_UNDERWATER);
@@ -258,15 +262,18 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Execute() const
int32_t zHigh = tile->z_clearance + zLow; int32_t zHigh = tile->z_clearance + zLow;
QuarterTile quarterTile = QuarterTile{ static_cast<uint8_t>(tile->flags >> 12), 0 }.Rotate(_loc.direction); QuarterTile quarterTile = QuarterTile{ static_cast<uint8_t>(tile->flags >> 12), 0 }.Rotate(_loc.direction);
if (!map_can_construct_with_clear_at( const auto isTree = (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0;
{ curTile, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), &supportsCost, auto canBuild = MapCanConstructWithClearAt(
CREATE_CROSSING_MODE_NONE, (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0)) { curTile, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), CREATE_CROSSING_MODE_NONE,
isTree);
if (canBuild->Error != GameActions::Status::Ok)
{ {
return std::make_unique<LargeSceneryPlaceActionResult>( canBuild->ErrorTitle = STR_CANT_POSITION_THIS_HERE;
GameActions::Status::NoClearance, gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
res->GroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND); supportsCost += canBuild->Cost;
res->GroundFlags = canBuild->GroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST))
{ {

View File

@@ -83,24 +83,22 @@ GameActions::Result::Ptr MazePlaceTrackAction::Query() const
} }
} }
money32 clearCost = 0; auto canBuild = MapCanConstructWithClearAt(
{ _loc.ToTileStart(), baseHeight, clearanceHeight }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags());
if (!map_can_construct_with_clear_at( if (canBuild->Error != GameActions::Status::Ok)
{ _loc.ToTileStart(), baseHeight, clearanceHeight }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags(),
&clearCost, CREATE_CROSSING_MODE_NONE))
{ {
return MakeResult( canBuild->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
GameActions::Status::NoClearance, res->ErrorTitle.GetStringId(), gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) if (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER)
{ {
res->Error = GameActions::Status::NoClearance; res->Error = GameActions::Status::NoClearance;
res->ErrorMessage = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; res->ErrorMessage = STR_RIDE_CANT_BUILD_THIS_UNDERWATER;
return res; return res;
} }
if (gMapGroundFlags & ELEMENT_IS_UNDERGROUND) if (canBuild->GroundFlags & ELEMENT_IS_UNDERGROUND)
{ {
res->Error = GameActions::Status::NoClearance; res->Error = GameActions::Status::NoClearance;
res->ErrorMessage = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND; res->ErrorMessage = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND;
@@ -116,7 +114,7 @@ GameActions::Result::Ptr MazePlaceTrackAction::Query() const
} }
money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16)); money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16));
res->Cost = clearCost + price / 2 * 10; res->Cost = canBuild->Cost + price / 2 * 10;
return res; return res;
} }
@@ -154,17 +152,17 @@ GameActions::Result::Ptr MazePlaceTrackAction::Execute() const
auto baseHeight = _loc.z; auto baseHeight = _loc.z;
auto clearanceHeight = _loc.z + MAZE_CLEARANCE_HEIGHT; auto clearanceHeight = _loc.z + MAZE_CLEARANCE_HEIGHT;
money32 clearCost = 0; auto canBuild = MapCanConstructWithClearAt(
if (!map_can_construct_with_clear_at(
{ _loc.ToTileStart(), baseHeight, clearanceHeight }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, { _loc.ToTileStart(), baseHeight, clearanceHeight }, &map_place_non_scenery_clear_func, { 0b1111, 0 },
GetFlags() | GAME_COMMAND_FLAG_APPLY, &clearCost, CREATE_CROSSING_MODE_NONE)) GetFlags() | GAME_COMMAND_FLAG_APPLY);
if (canBuild->Error != GameActions::Status::Ok)
{ {
return MakeResult( canBuild->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
GameActions::Status::NoClearance, res->ErrorTitle.GetStringId(), gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16)); money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16));
res->Cost = clearCost + price / 2 * 10; res->Cost = canBuild->Cost + price / 2 * 10;
auto startLoc = _loc.ToTileStart(); auto startLoc = _loc.ToTileStart();

View File

@@ -99,15 +99,15 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::Query() const
} }
auto clear_z = z + (_isExit ? RideExitHeight : RideEntranceHeight); auto clear_z = z + (_isExit ? RideExitHeight : RideEntranceHeight);
auto cost = MONEY32_UNDEFINED; auto canBuild = MapCanConstructWithClearAt(
if (!map_can_construct_with_clear_at( { _loc, z, clear_z }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags());
{ _loc, z, clear_z }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags(), &cost, if (canBuild->Error != GameActions::Status::Ok)
CREATE_CROSSING_MODE_NONE))
{ {
return MakeResult(GameActions::Status::NoClearance, errorTitle, gGameCommandErrorText, gCommonFormatArgs); canBuild->ErrorTitle = errorTitle;
return canBuild;
} }
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) if (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER)
{ {
return MakeResult(GameActions::Status::Disallowed, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER); return MakeResult(GameActions::Status::Disallowed, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER);
} }
@@ -163,12 +163,12 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::Execute() const
} }
auto clear_z = z + (_isExit ? RideExitHeight : RideEntranceHeight); auto clear_z = z + (_isExit ? RideExitHeight : RideEntranceHeight);
auto cost = MONEY32_UNDEFINED; auto canBuild = MapCanConstructWithClearAt(
if (!map_can_construct_with_clear_at( { _loc, z, clear_z }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags() | GAME_COMMAND_FLAG_APPLY);
{ _loc, z, clear_z }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags() | GAME_COMMAND_FLAG_APPLY, &cost, if (canBuild->Error != GameActions::Status::Ok)
CREATE_CROSSING_MODE_NONE))
{ {
return MakeResult(GameActions::Status::NoClearance, errorTitle, gGameCommandErrorText, gCommonFormatArgs); canBuild->ErrorTitle = errorTitle;
return canBuild;
} }
auto res = MakeResult(); auto res = MakeResult();
@@ -229,14 +229,14 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::TrackPlaceQuery(const Coor
int16_t baseZ = loc.z; int16_t baseZ = loc.z;
int16_t clearZ = baseZ + (isExit ? RideExitHeight : RideEntranceHeight); int16_t clearZ = baseZ + (isExit ? RideExitHeight : RideEntranceHeight);
auto cost = MONEY32_UNDEFINED; auto canBuild = MapCanConstructWithClearAt({ loc, baseZ, clearZ }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, 0);
if (!map_can_construct_with_clear_at( if (canBuild->Error != GameActions::Status::Ok)
{ loc, baseZ, clearZ }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, 0, &cost, CREATE_CROSSING_MODE_NONE))
{ {
return MakeResult(GameActions::Status::NoClearance, errorTitle, gGameCommandErrorText, gCommonFormatArgs); canBuild->ErrorTitle = errorTitle;
return canBuild;
} }
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) if (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER)
{ {
return MakeResult(GameActions::Status::Disallowed, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER); return MakeResult(GameActions::Status::Disallowed, errorTitle, STR_RIDE_CANT_BUILD_THIS_UNDERWATER);
} }

View File

@@ -276,20 +276,19 @@ GameActions::Result::Ptr SmallSceneryPlaceAction::Query() const
} }
QuarterTile quarterTile = QuarterTile{ collisionQuadrants, supports }.Rotate(quadRotation); QuarterTile quarterTile = QuarterTile{ collisionQuadrants, supports }.Rotate(quadRotation);
money32 clearCost = 0; const auto isTree = scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE);
auto canBuild = MapCanConstructWithClearAt(
if (!map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), CREATE_CROSSING_MODE_NONE, isTree);
{ _loc, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), &clearCost, if (canBuild->Error != GameActions::Status::Ok)
CREATE_CROSSING_MODE_NONE, scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE)))
{ {
return std::make_unique<SmallSceneryPlaceActionResult>( canBuild->ErrorTitle = STR_CANT_POSITION_THIS_HERE;
GameActions::Status::Disallowed, gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
res->GroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND); res->GroundFlags = canBuild->GroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
res->Expenditure = ExpenditureType::Landscaping; res->Expenditure = ExpenditureType::Landscaping;
res->Cost = (sceneryEntry->price * 10) + clearCost; res->Cost = (sceneryEntry->price * 10) + canBuild->Cost;
return res; return res;
} }
@@ -414,20 +413,20 @@ GameActions::Result::Ptr SmallSceneryPlaceAction::Execute() const
} }
QuarterTile quarterTile = QuarterTile{ collisionQuadrants, supports }.Rotate(quadRotation); QuarterTile quarterTile = QuarterTile{ collisionQuadrants, supports }.Rotate(quadRotation);
money32 clearCost = 0; const auto isTree = scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE);
auto canBuild = MapCanConstructWithClearAt(
if (!map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags() | GAME_COMMAND_FLAG_APPLY,
{ _loc, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags() | GAME_COMMAND_FLAG_APPLY, &clearCost, CREATE_CROSSING_MODE_NONE, isTree);
CREATE_CROSSING_MODE_NONE, scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE))) if (canBuild->Error != GameActions::Status::Ok)
{ {
return std::make_unique<SmallSceneryPlaceActionResult>( canBuild->ErrorTitle = STR_CANT_POSITION_THIS_HERE;
GameActions::Status::Disallowed, gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
res->GroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND); res->GroundFlags = canBuild->GroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
res->Expenditure = ExpenditureType::Landscaping; res->Expenditure = ExpenditureType::Landscaping;
res->Cost = (sceneryEntry->price * 10) + clearCost; res->Cost = (sceneryEntry->price * 10) + canBuild->Cost;
auto* sceneryElement = TileElementInsert<SmallSceneryElement>( auto* sceneryElement = TileElementInsert<SmallSceneryElement>(
CoordsXYZ{ _loc, zLow }, quarterTile.GetBaseQuarterOccupied()); CoordsXYZ{ _loc, zLow }, quarterTile.GetBaseQuarterOccupied());

View File

@@ -232,12 +232,14 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
&& _trackType == TrackElemType::Flat) && _trackType == TrackElemType::Flat)
? CREATE_CROSSING_MODE_TRACK_OVER_PATH ? CREATE_CROSSING_MODE_TRACK_OVER_PATH
: CREATE_CROSSING_MODE_NONE; : CREATE_CROSSING_MODE_NONE;
if (!map_can_construct_with_clear_at( auto canBuild = MapCanConstructWithClearAt(
{ mapLoc, baseZ, clearanceZ }, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), &cost, crossingMode)) { mapLoc, baseZ, clearanceZ }, &map_place_non_scenery_clear_func, quarterTile, GetFlags(), crossingMode);
if (canBuild->Error != GameActions::Status::Ok)
{ {
return std::make_unique<TrackPlaceActionResult>( canBuild->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
GameActions::Status::NoClearance, gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
cost += canBuild->Cost;
// When building a level crossing, remove any pre-existing path furniture. // When building a level crossing, remove any pre-existing path furniture.
if (crossingMode == CREATE_CROSSING_MODE_TRACK_OVER_PATH) if (crossingMode == CREATE_CROSSING_MODE_TRACK_OVER_PATH)
@@ -249,7 +251,7 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
} }
} }
uint8_t mapGroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND); uint8_t mapGroundFlags = canBuild->GroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
if (res->GroundFlags != 0 && (res->GroundFlags & mapGroundFlags) == 0) if (res->GroundFlags != 0 && (res->GroundFlags & mapGroundFlags) == 0)
{ {
return std::make_unique<TrackPlaceActionResult>( return std::make_unique<TrackPlaceActionResult>(
@@ -269,14 +271,14 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_ONLY_UNDERWATER) if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_ONLY_UNDERWATER)
{ // No element has this flag { // No element has this flag
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) if (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER)
{ {
return std::make_unique<TrackPlaceActionResult>( return std::make_unique<TrackPlaceActionResult>(
GameActions::Status::Disallowed, STR_CAN_ONLY_BUILD_THIS_UNDERWATER); GameActions::Status::Disallowed, STR_CAN_ONLY_BUILD_THIS_UNDERWATER);
} }
} }
if (gMapGroundFlags & ELEMENT_IS_UNDERWATER && !gCheatsDisableClearanceChecks) if (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER && !gCheatsDisableClearanceChecks)
{ {
return std::make_unique<TrackPlaceActionResult>( return std::make_unique<TrackPlaceActionResult>(
GameActions::Status::Disallowed, STR_RIDE_CANT_BUILD_THIS_UNDERWATER); GameActions::Status::Disallowed, STR_RIDE_CANT_BUILD_THIS_UNDERWATER);
@@ -428,13 +430,15 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
&& _trackType == TrackElemType::Flat) && _trackType == TrackElemType::Flat)
? CREATE_CROSSING_MODE_TRACK_OVER_PATH ? CREATE_CROSSING_MODE_TRACK_OVER_PATH
: CREATE_CROSSING_MODE_NONE; : CREATE_CROSSING_MODE_NONE;
if (!map_can_construct_with_clear_at( auto canBuild = MapCanConstructWithClearAt(
mapLocWithClearance, &map_place_non_scenery_clear_func, quarterTile, GetFlags() | GAME_COMMAND_FLAG_APPLY, mapLocWithClearance, &map_place_non_scenery_clear_func, quarterTile, GetFlags() | GAME_COMMAND_FLAG_APPLY,
&cost, crossingMode)) crossingMode);
if (canBuild->Error != GameActions::Status::Ok)
{ {
return std::make_unique<TrackPlaceActionResult>( canBuild->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
GameActions::Status::NoClearance, gGameCommandErrorText, gCommonFormatArgs); return canBuild;
} }
cost += canBuild->Cost;
if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !gCheatsDisableClearanceChecks) if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST) && !gCheatsDisableClearanceChecks)
{ {
@@ -459,7 +463,7 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
} }
} }
uint8_t mapGroundFlags = gMapGroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND); uint8_t mapGroundFlags = canBuild->GroundFlags & (ELEMENT_IS_ABOVE_GROUND | ELEMENT_IS_UNDERGROUND);
if (res->GroundFlags != 0 && (res->GroundFlags & mapGroundFlags) == 0) if (res->GroundFlags != 0 && (res->GroundFlags & mapGroundFlags) == 0)
{ {
return std::make_unique<TrackPlaceActionResult>( return std::make_unique<TrackPlaceActionResult>(

View File

@@ -534,7 +534,6 @@ GameActions::Result::Ptr WallPlaceAction::WallCheckObstruction(
rct_large_scenery_tile* tile; rct_large_scenery_tile* tile;
*wallAcrossTrack = false; *wallAcrossTrack = false;
gMapGroundFlags = ELEMENT_IS_ABOVE_GROUND;
if (map_is_location_at_edge(_loc)) if (map_is_location_at_edge(_loc))
{ {
return MakeResult(GameActions::Status::InvalidParameters, STR_OFF_EDGE_OF_MAP); return MakeResult(GameActions::Status::InvalidParameters, STR_OFF_EDGE_OF_MAP);

View File

@@ -90,8 +90,6 @@ CoordsXY gMapSelectPositionB;
CoordsXYZ gMapSelectArrowPosition; CoordsXYZ gMapSelectArrowPosition;
uint8_t gMapSelectArrowDirection; uint8_t gMapSelectArrowDirection;
uint8_t gMapGroundFlags;
TileCoordsXY gWidePathTileLoopPosition; TileCoordsXY gWidePathTileLoopPosition;
uint16_t gGrassSceneryTileLoopPosition; uint16_t gGrassSceneryTileLoopPosition;
@@ -1492,37 +1490,9 @@ std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructWithClearAt(
return res; return res;
} }
bool map_can_construct_with_clear_at(
const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, money32* price,
uint8_t crossingMode, bool isTree)
{
auto res = MapCanConstructWithClearAt(pos, clearFunc, quarterTile, flags, crossingMode, isTree);
if (auto message = res->ErrorMessage.AsStringId())
gGameCommandErrorText = *message;
else
gGameCommandErrorText = STR_NONE;
std::copy(res->ErrorMessageArgs.begin(), res->ErrorMessageArgs.end(), gCommonFormatArgs);
if (price != nullptr)
{
*price += res->Cost;
}
gMapGroundFlags = res->GroundFlags;
return res->Error == GameActions::Status::Ok;
}
/**
*
* rct2: 0x0068B93A
*/
int32_t map_can_construct_at(const CoordsXYRangedZ& pos, QuarterTile bl)
{
return map_can_construct_with_clear_at(pos, nullptr, bl, 0, nullptr, CREATE_CROSSING_MODE_NONE);
}
std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl) std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl)
{ {
return MapCanConstructWithClearAt(pos, nullptr, bl, 0, CREATE_CROSSING_MODE_NONE); return MapCanConstructWithClearAt(pos, nullptr, bl, 0);
} }
/** /**
* Updates grass length, scenery age and jumping fountains. * Updates grass length, scenery age and jumping fountains.

View File

@@ -85,7 +85,7 @@ enum
MAP_SELECT_TYPE_EDGE_3, MAP_SELECT_TYPE_EDGE_3,
}; };
// Used when calling map_can_construct_with_clear_at(); // Used when calling MapCanConstructWithClearAt();
// This assumes that the caller has already done the check on the element it wants to place, // This assumes that the caller has already done the check on the element it wants to place,
// as this function can only check the element the player wants to build through. // as this function can only check the element the player wants to build through.
enum enum
@@ -114,8 +114,6 @@ extern CoordsXY gMapSelectPositionB;
extern CoordsXYZ gMapSelectArrowPosition; extern CoordsXYZ gMapSelectArrowPosition;
extern uint8_t gMapSelectArrowDirection; extern uint8_t gMapSelectArrowDirection;
extern uint8_t gMapGroundFlags;
extern std::vector<CoordsXY> gMapSelectionTiles; extern std::vector<CoordsXY> gMapSelectionTiles;
extern std::vector<PeepSpawn> gPeepSpawns; extern std::vector<PeepSpawn> gPeepSpawns;
@@ -235,14 +233,10 @@ using CLEAR_FUNC = int32_t (*)(TileElement** tile_element, const CoordsXY& coord
int32_t map_place_non_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price); int32_t map_place_non_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
int32_t map_place_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price); int32_t map_place_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price);
bool map_can_construct_with_clear_at(
const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, money32* price,
uint8_t crossingMode, bool isTree = false);
std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructWithClearAt( std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructWithClearAt(
const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, uint8_t crossingMode, const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags,
bool isTree = false); uint8_t crossingMode = CREATE_CROSSING_MODE_NONE, bool isTree = false);
std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl); std::unique_ptr<GameActions::ConstructClearResult> MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl);
int32_t map_can_construct_at(const CoordsXYRangedZ& pos, QuarterTile bl);
struct tile_element_iterator struct tile_element_iterator
{ {