/**
* Builds a lock.
* @param tile Central tile of the lock.
* @param dir Uphill direction.
* @param flags Operation to perform.
* @return The cost in case of success, or an error code if it failed.
*/
static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlag flags)
{
CommandCost cost(EXPENSES_CONSTRUCTION);
int delta = TileOffsByDiagDir(dir);
CommandCost ret = EnsureNoVehicleOnGround(tile);
if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
if (ret.Failed()) return ret;
/* middle tile */
WaterClass wc_middle = IsWaterTile(tile) ? GetWaterClass(tile) : WATER_CLASS_CANAL;
if (!IsWaterTile(tile)) {
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (ret.Failed()) return ret;
cost.AddCost(ret);
cost.AddCost(_price[PR_BUILD_CANAL]);
}
/* lower tile */
WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
if (!IsWaterTile(tile - delta)) {
ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (ret.Failed()) return ret;
cost.AddCost(ret);
cost.AddCost(_price[PR_BUILD_CANAL]);
}
if (!IsTileFlat(tile - delta)) {
return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
}
/* upper tile */
WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
if (!IsWaterTile(tile + delta)) {
ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (ret.Failed()) return ret;
cost.AddCost(ret);
cost.AddCost(_price[PR_BUILD_CANAL]);
}
if (!IsTileFlat(tile + delta)) {
return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
}
if (IsBridgeAbove(tile) || IsBridgeAbove(tile - delta) || IsBridgeAbove(tile + delta)) {
return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
}
if (flags & DC_EXEC) {
/* Update company infrastructure counts. */
Company *c = Company::GetIfValid(_current_company);
if (c != NULL) {
/* Counts for the water. */
if (!IsWaterTile(tile - delta)) c->infrastructure.water++;
if (!IsWaterTile(tile)) c->infrastructure.water++;
if (!IsWaterTile(tile + delta)) c->infrastructure.water++;
/* Count for the lock itself. */
c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock is three tiles.
DirtyCompanyInfrastructureWindows(_current_company);
}
MakeLock(tile, _current_company, dir, wc_lower, wc_upper, wc_middle);
MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(tile - delta);
MarkTileDirtyByTile(tile + delta);
MarkCanalsAndRiversAroundDirty(tile - delta);
MarkCanalsAndRiversAroundDirty(tile + delta);
}
cost.AddCost(_price[PR_BUILD_LOCK]);
return cost;
}
/**
* Remove a lock.
* @param tile Central tile of the lock.
* @param flags Operation to perform.
* @return The cost in case of success, or an error code if it failed.
*/
static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
{
if (GetTileOwner(tile) != OWNER_NONE) {
CommandCost ret = CheckTileOwnership(tile);
if (ret.Failed()) return ret;
}
TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile));
/* make sure no vehicle is on the tile. */
CommandCost ret = EnsureNoVehicleOnGround(tile);
if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
if (ret.Failed()) return ret;
if (flags & DC_EXEC) {
/* Remove middle part from company infrastructure count. */
Company *c = Company::GetIfValid(GetTileOwner(tile));
if (c != NULL) {
c->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // three parts of the lock.
DirtyCompanyInfrastructureWindows(c->index);
}
if (GetWaterClass(tile) == WATER_CLASS_RIVER) {
MakeRiver(tile, Random());
} else {
c->infrastructure.water--;
DoClearSquare(tile);
}
MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
MarkCanalsAndRiversAroundDirty(tile);
MarkCanalsAndRiversAroundDirty(tile - delta);
MarkCanalsAndRiversAroundDirty(tile + delta);
}
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]);
}