mirror of https://github.com/OpenTTD/OpenTTD
Merge 0716493bb3
into 5255aabe4d
commit
712b6a3974
|
@ -315,9 +315,6 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t
|
|||
auto [tileh_end, z_end] = GetTileSlopeZ(tile_end);
|
||||
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. */
|
||||
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);
|
||||
|
@ -394,24 +391,71 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t
|
|||
} else {
|
||||
/* Build a new bridge. */
|
||||
|
||||
bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
|
||||
|
||||
/* Try and clear the start landscape */
|
||||
CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_start);
|
||||
if (ret.Failed()) return 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 */
|
||||
ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_end);
|
||||
if (ret.Failed()) return ret;
|
||||
cost.AddCost(ret);
|
||||
|
||||
/* false - end tile slope check */
|
||||
if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||
cost.AddCost(terraform_cost_south);
|
||||
/* for aqueducts, slope of end tile must be complementary to the slope of the start tile */
|
||||
if (transport_type == TRANSPORT_WATER && tileh_end != ComplementSlope(tileh_start)) {
|
||||
/* 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};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
|
Loading…
Reference in New Issue