1
0
Fork 0
pull/13545/merge
HuyNguyen17 2025-03-17 20:30:13 +00:00 committed by GitHub
commit 712b6a3974
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 55 additions and 11 deletions

View File

@ -315,9 +315,6 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t
auto [tileh_end, z_end] = GetTileSlopeZ(tile_end); auto [tileh_end, z_end] = GetTileSlopeZ(tile_end);
bool pbs_reservation = false; bool pbs_reservation = false;
CommandCost terraform_cost_north = CheckBridgeSlope(BRIDGE_PIECE_NORTH, direction, tileh_start, z_start);
CommandCost terraform_cost_south = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, direction, tileh_end, z_end);
/* Aqueducts can't be built of flat land. */ /* Aqueducts can't be built of flat land. */
if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
if (z_start != z_end) return CommandCost(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT); if (z_start != z_end) return CommandCost(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT);
@ -394,24 +391,71 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t
} else { } else {
/* Build a new bridge. */ /* Build a new bridge. */
bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
/* Try and clear the start landscape */ /* Try and clear the start landscape */
CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_start); CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_start);
if (ret.Failed()) return ret; if (ret.Failed()) return ret;
cost = ret; cost = ret;
if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
cost.AddCost(terraform_cost_north);
/* Try and clear the end landscape */ /* Try and clear the end landscape */
ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_end); ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_end);
if (ret.Failed()) return ret; if (ret.Failed()) return ret;
cost.AddCost(ret); cost.AddCost(ret);
/* false - end tile slope check */ /* for aqueducts, slope of end tile must be complementary to the slope of the start tile */
if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); if (transport_type == TRANSPORT_WATER && tileh_end != ComplementSlope(tileh_start)) {
cost.AddCost(terraform_cost_south); /* Check if the tile to be terraformed is the start or end tile */
TileIndex terraformTile;
Slope terraformTileh;
if (tileh_start == SLOPE_N || tileh_start == SLOPE_S || tileh_start == SLOPE_W || tileh_start == SLOPE_E) {
terraformTile = tile_start;
terraformTileh = tileh_start ^ ComplementSlope(tileh_end);
} else {
terraformTile = tile_end;
terraformTileh = tileh_end ^ ComplementSlope(tileh_start);
}
/* Mark the tile as already cleared for the terraform command.
* Do this for all tiles (like trees), not only objects. */
ClearedObjectArea *coa = FindClearedObject(terraformTile);
if (coa == nullptr) {
coa = &_cleared_object_areas.emplace_back(ClearedObjectArea{ terraformTile, TileArea(terraformTile, 1, 1) });
}
/* Hide the tile from the terraforming command */
TileIndex old_first_tile = coa->first_tile;
coa->first_tile = INVALID_TILE;
/* CMD_TERRAFORM_LAND may append further items to _cleared_object_areas,
* however it will never erase or re-order existing items.
* _cleared_object_areas is a value-type self-resizing vector, therefore appending items
* may result in a backing-store re-allocation, which would invalidate the coa pointer.
* The index of the coa pointer into the _cleared_object_areas vector remains valid,
* and can be used safely after the CMD_TERRAFORM_LAND operation.
* Deliberately clear the coa pointer to avoid leaving dangling pointers which could
* inadvertently be dereferenced.
*/
ClearedObjectArea *begin = _cleared_object_areas.data();
assert(coa >= begin && coa < begin + _cleared_object_areas.size());
size_t coa_index = coa - begin;
assert(coa_index < UINT_MAX); // more than 2**32 cleared areas would be a bug in itself
coa = nullptr;
ret = std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(DoCommandFlag(flags & ~DC_NO_WATER), terraformTile, terraformTileh, true));
_cleared_object_areas[(uint)coa_index].first_tile = old_first_tile;
if (ret.Failed()) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
cost.AddCost(ret);
}
if (transport_type != TRANSPORT_WATER){
CommandCost terraform_cost_north = CheckBridgeSlope(BRIDGE_PIECE_NORTH, direction, tileh_start, z_start);
if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
cost.AddCost(terraform_cost_north);
CommandCost terraform_cost_south = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, direction, tileh_end, z_end);
/* false - end tile slope check */
if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
cost.AddCost(terraform_cost_south);
}
const TileIndex heads[] = {tile_start, tile_end}; const TileIndex heads[] = {tile_start, tile_end};
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {