00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "cmd_helper.h"
00014 #include "landscape.h"
00015 #include "viewport_func.h"
00016 #include "command_func.h"
00017 #include "town.h"
00018 #include "news_func.h"
00019 #include "depot_base.h"
00020 #include "depot_func.h"
00021 #include "water.h"
00022 #include "industry_map.h"
00023 #include "newgrf_canal.h"
00024 #include "strings_func.h"
00025 #include "vehicle_func.h"
00026 #include "sound_func.h"
00027 #include "company_func.h"
00028 #include "clear_map.h"
00029 #include "tree_map.h"
00030 #include "aircraft.h"
00031 #include "effectvehicle_func.h"
00032 #include "tunnelbridge_map.h"
00033 #include "station_base.h"
00034 #include "ai/ai.hpp"
00035 #include "core/random_func.hpp"
00036 #include "core/backup_type.hpp"
00037 #include "date_func.h"
00038 #include "company_base.h"
00039 #include "company_gui.h"
00040
00041 #include "table/strings.h"
00042
00046 static const uint8 _flood_from_dirs[] = {
00047 (1 << DIR_NW) | (1 << DIR_SW) | (1 << DIR_SE) | (1 << DIR_NE),
00048 (1 << DIR_NE) | (1 << DIR_SE),
00049 (1 << DIR_NW) | (1 << DIR_NE),
00050 (1 << DIR_NE),
00051 (1 << DIR_NW) | (1 << DIR_SW),
00052 0,
00053 (1 << DIR_NW),
00054 (1 << DIR_N ) | (1 << DIR_NW) | (1 << DIR_NE),
00055 (1 << DIR_SW) | (1 << DIR_SE),
00056 (1 << DIR_SE),
00057 0,
00058 (1 << DIR_E ) | (1 << DIR_NE) | (1 << DIR_SE),
00059 (1 << DIR_SW),
00060 (1 << DIR_S ) | (1 << DIR_SW) | (1 << DIR_SE),
00061 (1 << DIR_W ) | (1 << DIR_SW) | (1 << DIR_NW),
00062 };
00063
00070 static inline void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
00071 {
00072 if (IsTileType(tile, MP_WATER) && (IsCanal(tile) || IsRiver(tile))) MarkTileDirtyByTile(tile);
00073 }
00074
00081 static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
00082 {
00083 for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
00084 MarkTileDirtyIfCanalOrRiver(tile + TileOffsByDir(dir));
00085 }
00086 }
00087
00088
00098 CommandCost CmdBuildShipDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00099 {
00100 Axis axis = Extract<Axis, 0, 1>(p1);
00101
00102 TileIndex tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
00103
00104 if (!HasTileWaterGround(tile) || !HasTileWaterGround(tile2)) {
00105 return_cmd_error(STR_ERROR_MUST_BE_BUILT_ON_WATER);
00106 }
00107
00108 if ((MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) ||
00109 (MayHaveBridgeAbove(tile2) && IsBridgeAbove(tile2))) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00110
00111 if (GetTileSlope(tile, NULL) != SLOPE_FLAT || GetTileSlope(tile2, NULL) != SLOPE_FLAT) {
00112
00113 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
00114 }
00115
00116 if (!Depot::CanAllocateItem()) return CMD_ERROR;
00117
00118 WaterClass wc1 = GetWaterClass(tile);
00119 WaterClass wc2 = GetWaterClass(tile2);
00120 CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_DEPOT_SHIP]);
00121
00122 bool add_cost = !IsWaterTile(tile);
00123 CommandCost ret = DoCommand(tile, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
00124 if (ret.Failed()) return ret;
00125 if (add_cost) {
00126 cost.AddCost(ret);
00127 }
00128 add_cost = !IsWaterTile(tile2);
00129 ret = DoCommand(tile2, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
00130 if (ret.Failed()) return ret;
00131 if (add_cost) {
00132 cost.AddCost(ret);
00133 }
00134
00135 if (flags & DC_EXEC) {
00136 Depot *depot = new Depot(tile);
00137 depot->build_date = _date;
00138
00139 if (wc1 == WATER_CLASS_CANAL || wc2 == WATER_CLASS_CANAL) {
00140
00141 Company::Get(_current_company)->water_infrastructure += wc1 == WATER_CLASS_CANAL && wc2 == WATER_CLASS_CANAL ? 2 : 1;
00142 }
00143 Company::Get(_current_company)->water_infrastructure += 2 * LOCK_DEPOT_TILE_FACTOR;
00144 DirtyCompanyInfrastructureWindows(_current_company);
00145
00146 MakeShipDepot(tile, _current_company, depot->index, DEPOT_PART_NORTH, axis, wc1);
00147 MakeShipDepot(tile2, _current_company, depot->index, DEPOT_PART_SOUTH, axis, wc2);
00148 MarkTileDirtyByTile(tile);
00149 MarkTileDirtyByTile(tile2);
00150 MakeDefaultName(depot);
00151 }
00152
00153 return cost;
00154 }
00155
00156 void MakeWaterKeepingClass(TileIndex tile, Owner o)
00157 {
00158 WaterClass wc = GetWaterClass(tile);
00159
00160
00161 uint z;
00162 if (GetTileSlope(tile, &z) != SLOPE_FLAT) {
00163 if (wc == WATER_CLASS_CANAL) {
00164
00165 Company *c = Company::GetIfValid(o);
00166 if (c != NULL) {
00167 c->water_infrastructure--;
00168 DirtyCompanyInfrastructureWindows(c->index);
00169 }
00170 }
00171 wc = WATER_CLASS_INVALID;
00172 }
00173
00174 if (wc == WATER_CLASS_SEA && z > 0) {
00175
00176 Company *c = Company::GetIfValid(o);
00177 if (c != NULL) {
00178 c->water_infrastructure++;
00179 DirtyCompanyInfrastructureWindows(c->index);
00180 }
00181
00182 wc = WATER_CLASS_CANAL;
00183 }
00184
00185
00186 DoClearSquare(tile);
00187
00188
00189 switch (wc) {
00190 case WATER_CLASS_SEA: MakeSea(tile); break;
00191 case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
00192 case WATER_CLASS_RIVER: MakeRiver(tile, Random()); break;
00193 default: break;
00194 }
00195
00196 MarkTileDirtyByTile(tile);
00197 }
00198
00199 static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlag flags)
00200 {
00201 if (!IsShipDepot(tile)) return CMD_ERROR;
00202
00203 CommandCost ret = CheckTileOwnership(tile);
00204 if (ret.Failed()) return ret;
00205
00206 TileIndex tile2 = GetOtherShipDepotTile(tile);
00207
00208
00209 if (!(flags & DC_BANKRUPT)) {
00210 CommandCost ret = EnsureNoVehicleOnGround(tile);
00211 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
00212 if (ret.Failed()) return ret;
00213 }
00214
00215 if (flags & DC_EXEC) {
00216 delete Depot::GetByTile(tile);
00217
00218 Company *c = Company::GetIfValid(GetTileOwner(tile));
00219 if (c != NULL) {
00220 c->water_infrastructure -= 2 * LOCK_DEPOT_TILE_FACTOR;
00221 DirtyCompanyInfrastructureWindows(c->index);
00222 }
00223
00224 MakeWaterKeepingClass(tile, GetTileOwner(tile));
00225 MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
00226 }
00227
00228 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_SHIP]);
00229 }
00230
00238 static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlag flags)
00239 {
00240 CommandCost cost(EXPENSES_CONSTRUCTION);
00241
00242
00243 WaterClass wc_middle = IsWaterTile(tile) ? GetWaterClass(tile) : WATER_CLASS_CANAL;
00244 CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00245 if (ret.Failed()) return ret;
00246 cost.AddCost(ret);
00247
00248 int delta = TileOffsByDiagDir(dir);
00249
00250 WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
00251
00252 if (!IsWaterTile(tile - delta)) {
00253 ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00254 if (ret.Failed()) return ret;
00255 cost.AddCost(ret);
00256 cost.AddCost(_price[PR_BUILD_CANAL]);
00257 }
00258 if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) {
00259 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00260 }
00261
00262
00263 WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
00264
00265 if (!IsWaterTile(tile + delta)) {
00266 ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00267 if (ret.Failed()) return ret;
00268 cost.AddCost(ret);
00269 cost.AddCost(_price[PR_BUILD_CANAL]);
00270 }
00271 if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) {
00272 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00273 }
00274
00275 if ((MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) ||
00276 (MayHaveBridgeAbove(tile - delta) && IsBridgeAbove(tile - delta)) ||
00277 (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) {
00278 return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00279 }
00280
00281 if (flags & DC_EXEC) {
00282
00283 Company *c = Company::GetIfValid(_current_company);
00284 if (c != NULL) {
00285
00286 if (!IsWaterTile(tile - delta)) c->water_infrastructure++;
00287 if (!IsWaterTile(tile + delta)) c->water_infrastructure++;
00288
00289 c->water_infrastructure += 3 * LOCK_DEPOT_TILE_FACTOR;
00290 DirtyCompanyInfrastructureWindows(_current_company);
00291 }
00292
00293 MakeLock(tile, _current_company, dir, wc_lower, wc_upper, wc_middle);
00294 MarkTileDirtyByTile(tile);
00295 MarkTileDirtyByTile(tile - delta);
00296 MarkTileDirtyByTile(tile + delta);
00297 MarkCanalsAndRiversAroundDirty(tile - delta);
00298 MarkCanalsAndRiversAroundDirty(tile + delta);
00299 }
00300 cost.AddCost(_price[PR_BUILD_LOCK]);
00301
00302 return cost;
00303 }
00304
00311 static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
00312 {
00313 if (GetTileOwner(tile) != OWNER_NONE) {
00314 CommandCost ret = CheckTileOwnership(tile);
00315 if (ret.Failed()) return ret;
00316 }
00317
00318 TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile));
00319
00320
00321 CommandCost ret = EnsureNoVehicleOnGround(tile);
00322 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
00323 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
00324 if (ret.Failed()) return ret;
00325
00326 if (flags & DC_EXEC) {
00327
00328 Company *c = Company::GetIfValid(GetTileOwner(tile));
00329 if (c != NULL) {
00330 c->water_infrastructure -= 3 * LOCK_DEPOT_TILE_FACTOR;
00331 DirtyCompanyInfrastructureWindows(c->index);
00332 }
00333
00334 if (GetWaterClass(tile) == WATER_CLASS_RIVER) {
00335 MakeRiver(tile, Random());
00336 } else {
00337 DoClearSquare(tile);
00338 }
00339
00340 MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
00341 MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
00342 MarkCanalsAndRiversAroundDirty(tile);
00343 MarkCanalsAndRiversAroundDirty(tile - delta);
00344 MarkCanalsAndRiversAroundDirty(tile + delta);
00345 }
00346
00347 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]);
00348 }
00349
00359 CommandCost CmdBuildLock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00360 {
00361 DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
00362 if (dir == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00363
00364 return DoBuildLock(tile, dir, flags);
00365 }
00366
00376 CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00377 {
00378 WaterClass wc = Extract<WaterClass, 0, 2>(p2);
00379 if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR;
00380
00381
00382 if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;
00383
00384 TileArea ta(tile, p1);
00385
00386
00387 if (_game_mode != GM_EDITOR && ta.w != 1 && ta.h != 1) return CMD_ERROR;
00388
00389 CommandCost cost(EXPENSES_CONSTRUCTION);
00390 TILE_AREA_LOOP(tile, ta) {
00391 CommandCost ret;
00392
00393 Slope slope = GetTileSlope(tile, NULL);
00394 if (slope != SLOPE_FLAT && (wc != WATER_CLASS_RIVER || !IsInclinedSlope(slope))) {
00395 return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
00396 }
00397
00398
00399 if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;
00400
00401 ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
00402 if (ret.Failed()) return ret;
00403 cost.AddCost(ret);
00404
00405 if (flags & DC_EXEC) {
00406 switch (wc) {
00407 case WATER_CLASS_RIVER:
00408 MakeRiver(tile, Random());
00409 break;
00410
00411 case WATER_CLASS_SEA:
00412 if (TileHeight(tile) == 0) {
00413 MakeSea(tile);
00414 break;
00415 }
00416
00417
00418 default:
00419 MakeCanal(tile, _current_company, Random());
00420 if (Company::IsValidID(_current_company)) {
00421 Company::Get(_current_company)->water_infrastructure++;
00422 DirtyCompanyInfrastructureWindows(_current_company);
00423 }
00424 break;
00425 }
00426 MarkTileDirtyByTile(tile);
00427 MarkCanalsAndRiversAroundDirty(tile);
00428 }
00429
00430 cost.AddCost(_price[PR_BUILD_CANAL]);
00431 }
00432
00433 if (cost.GetCost() == 0) {
00434 return_cmd_error(STR_ERROR_ALREADY_BUILT);
00435 } else {
00436 return cost;
00437 }
00438 }
00439
00440 static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
00441 {
00442 switch (GetWaterTileType(tile)) {
00443 case WATER_TILE_CLEAR: {
00444 if (flags & DC_NO_WATER) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
00445
00446 Money base_cost = IsCanal(tile) ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER];
00447
00448 if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(tile), 1, MapMaxX() - 1) ||
00449 !IsInsideMM(TileY(tile), 1, MapMaxY() - 1))) {
00450 return_cmd_error(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
00451 }
00452
00453
00454 if (GetTileZ(tile) == 0 && IsTunnelInWay(tile, 0)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST);
00455
00456
00457 CommandCost ret = EnsureNoVehicleOnGround(tile);
00458 if (ret.Failed()) return ret;
00459
00460 Owner owner = GetTileOwner(tile);
00461 if (owner != OWNER_WATER && owner != OWNER_NONE) {
00462 CommandCost ret = CheckTileOwnership(tile);
00463 if (ret.Failed()) return ret;
00464 }
00465
00466 if (flags & DC_EXEC) {
00467 if (IsCanal(tile) && Company::IsValidID(owner)) {
00468 Company::Get(owner)->water_infrastructure--;
00469 DirtyCompanyInfrastructureWindows(owner);
00470 }
00471 DoClearSquare(tile);
00472 MarkCanalsAndRiversAroundDirty(tile);
00473 }
00474
00475 return CommandCost(EXPENSES_CONSTRUCTION, base_cost);
00476 }
00477
00478 case WATER_TILE_COAST: {
00479 Slope slope = GetTileSlope(tile, NULL);
00480
00481
00482 CommandCost ret = EnsureNoVehicleOnGround(tile);
00483 if (ret.Failed()) return ret;
00484
00485 if (flags & DC_EXEC) {
00486 DoClearSquare(tile);
00487 MarkCanalsAndRiversAroundDirty(tile);
00488 }
00489 if (IsSlopeWithOneCornerRaised(slope)) {
00490 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WATER]);
00491 } else {
00492 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROUGH]);
00493 }
00494 }
00495
00496 case WATER_TILE_LOCK: {
00497 static const TileIndexDiffC _lock_tomiddle_offs[][DIAGDIR_END] = {
00498
00499 { { 0, 0}, {0, 0}, { 0, 0}, {0, 0} },
00500 { {-1, 0}, {0, 1}, { 1, 0}, {0, -1} },
00501 { { 1, 0}, {0, -1}, {-1, 0}, {0, 1} },
00502 };
00503
00504 if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
00505 if (_current_company == OWNER_WATER) return CMD_ERROR;
00506
00507 return RemoveLock(tile + ToTileIndexDiff(_lock_tomiddle_offs[GetLockPart(tile)][GetLockDirection(tile)]), flags);
00508 }
00509
00510 case WATER_TILE_DEPOT:
00511 if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
00512 return RemoveShipDepot(tile, flags);
00513
00514 default:
00515 NOT_REACHED();
00516 }
00517 }
00518
00527 static bool IsWateredTile(TileIndex tile, Direction from)
00528 {
00529 switch (GetTileType(tile)) {
00530 case MP_WATER:
00531 switch (GetWaterTileType(tile)) {
00532 default: NOT_REACHED();
00533 case WATER_TILE_DEPOT: case WATER_TILE_CLEAR: return true;
00534 case WATER_TILE_LOCK: return DiagDirToAxis(GetLockDirection(tile)) == DiagDirToAxis(DirToDiagDir(from));
00535
00536 case WATER_TILE_COAST:
00537 switch (GetTileSlope(tile, NULL)) {
00538 case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
00539 case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
00540 case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
00541 case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
00542 default: return false;
00543 }
00544 }
00545
00546 case MP_RAILWAY:
00547 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
00548 assert(IsPlainRail(tile));
00549 switch (GetTileSlope(tile, NULL)) {
00550 case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
00551 case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
00552 case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
00553 case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
00554 default: return false;
00555 }
00556 }
00557 return false;
00558
00559 case MP_STATION:
00560 if (IsOilRig(tile)) {
00561
00562
00563 TileIndex src_tile = tile + TileOffsByDir(from);
00564 if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
00565 (IsTileType(src_tile, MP_INDUSTRY))) return true;
00566
00567 return IsTileOnWater(tile);
00568 }
00569 return (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsBuoy(tile);
00570
00571 case MP_INDUSTRY: {
00572
00573
00574 TileIndex src_tile = tile + TileOffsByDir(from);
00575 if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
00576 (IsTileType(src_tile, MP_INDUSTRY) && GetIndustryIndex(src_tile) == GetIndustryIndex(tile))) return true;
00577
00578 return IsTileOnWater(tile);
00579 }
00580
00581 case MP_OBJECT: return IsTileOnWater(tile);
00582
00583 case MP_TUNNELBRIDGE: return GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER && ReverseDiagDir(GetTunnelBridgeDirection(tile)) == DirToDiagDir(from);
00584
00585 default: return false;
00586 }
00587 }
00588
00596 static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
00597 {
00598 if (base != SPR_FLAT_WATER_TILE) {
00599
00600 offset = GetCanalSpriteOffset(feature, tile, offset);
00601 }
00602 DrawGroundSprite(base + offset, PAL_NONE);
00603 }
00604
00611 static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
00612 {
00613 CanalFeature feature;
00614 SpriteID base = 0;
00615 if (canal) {
00616 feature = CF_DIKES;
00617 base = GetCanalSprite(CF_DIKES, tile);
00618 if (base == 0) base = SPR_CANAL_DIKES_BASE;
00619 } else {
00620 feature = CF_RIVER_EDGE;
00621 base = GetCanalSprite(CF_RIVER_EDGE, tile);
00622 if (base == 0) return;
00623 }
00624
00625 uint wa;
00626
00627
00628 wa = IsWateredTile(TILE_ADDXY(tile, -1, 0), DIR_SW) << 0;
00629 wa += IsWateredTile(TILE_ADDXY(tile, 0, 1), DIR_NW) << 1;
00630 wa += IsWateredTile(TILE_ADDXY(tile, 1, 0), DIR_NE) << 2;
00631 wa += IsWateredTile(TILE_ADDXY(tile, 0, -1), DIR_SE) << 3;
00632
00633 if (!(wa & 1)) DrawWaterSprite(base, offset, feature, tile);
00634 if (!(wa & 2)) DrawWaterSprite(base, offset + 1, feature, tile);
00635 if (!(wa & 4)) DrawWaterSprite(base, offset + 2, feature, tile);
00636 if (!(wa & 8)) DrawWaterSprite(base, offset + 3, feature, tile);
00637
00638
00639 switch (wa & 0x03) {
00640 case 0: DrawWaterSprite(base, offset + 4, feature, tile); break;
00641 case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1), DIR_W)) DrawWaterSprite(base, offset + 8, feature, tile); break;
00642 }
00643
00644
00645 switch (wa & 0x06) {
00646 case 0: DrawWaterSprite(base, offset + 5, feature, tile); break;
00647 case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1), DIR_N)) DrawWaterSprite(base, offset + 9, feature, tile); break;
00648 }
00649
00650
00651 switch (wa & 0x0C) {
00652 case 0: DrawWaterSprite(base, offset + 6, feature, tile); break;
00653 case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1), DIR_E)) DrawWaterSprite(base, offset + 10, feature, tile); break;
00654 }
00655
00656
00657 switch (wa & 0x09) {
00658 case 0: DrawWaterSprite(base, offset + 7, feature, tile); break;
00659 case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawWaterSprite(base, offset + 11, feature, tile); break;
00660 }
00661 }
00662
00664 static void DrawSeaWater(TileIndex tile)
00665 {
00666 DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
00667 }
00668
00670 static void DrawCanalWater(TileIndex tile)
00671 {
00672 SpriteID image = SPR_FLAT_WATER_TILE;
00673 if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00674
00675 image = GetCanalSprite(CF_WATERSLOPE, tile);
00676 if (image == 0) image = SPR_FLAT_WATER_TILE;
00677 }
00678 DrawWaterSprite(image, 0, CF_WATERSLOPE, tile);
00679
00680 DrawWaterEdges(true, 0, tile);
00681 }
00682
00683 #include "table/water_land.h"
00684
00694 static void DrawWaterTileStruct(const TileInfo *ti, const DrawTileSeqStruct *dtss, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
00695 {
00696
00697 if (IsInvisibilitySet(TO_BUILDINGS)) return;
00698
00699 for (; !dtss->IsTerminator(); dtss++) {
00700 uint tile_offs = offset + dtss->image.sprite;
00701 if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
00702 AddSortableSpriteToDraw(base + tile_offs, palette,
00703 ti->x + dtss->delta_x, ti->y + dtss->delta_y,
00704 dtss->size_x, dtss->size_y,
00705 dtss->size_z, ti->z + dtss->delta_z,
00706 IsTransparencySet(TO_BUILDINGS));
00707 }
00708 }
00709
00711 static void DrawWaterLock(const TileInfo *ti)
00712 {
00713 int part = GetLockPart(ti->tile);
00714 const DrawTileSprites &dts = _lock_display_data[part][GetLockDirection(ti->tile)];
00715
00716
00717 SpriteID image = dts.ground.sprite;
00718
00719 SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile);
00720 if (water_base == 0) {
00721
00722 water_base = SPR_CANALS_BASE;
00723 } else if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00724
00725 if (image == SPR_FLAT_WATER_TILE) {
00726 image = water_base;
00727 } else {
00728 image++;
00729 }
00730 }
00731
00732 if (image < 5) image += water_base;
00733 DrawGroundSprite(image, PAL_NONE);
00734
00735
00736 uint zoffs = 0;
00737 SpriteID base = GetCanalSprite(CF_LOCKS, ti->tile);
00738
00739 if (base == 0) {
00740
00741 base = SPR_LOCK_BASE;
00742 uint8 z_threshold = part == LOCK_PART_UPPER ? 8 : 0;
00743 zoffs = ti->z > z_threshold ? 24 : 0;
00744 }
00745
00746 DrawWaterTileStruct(ti, dts.seq, base, zoffs, PAL_NONE, CF_LOCKS);
00747 }
00748
00750 static void DrawWaterDepot(const TileInfo *ti)
00751 {
00752 DrawWaterClassGround(ti);
00753 DrawWaterTileStruct(ti, _shipdepot_display_data[GetShipDepotAxis(ti->tile)][GetShipDepotPart(ti->tile)].seq, 0, 0, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)), CF_END);
00754 }
00755
00756 static void DrawRiverWater(const TileInfo *ti)
00757 {
00758 SpriteID image = SPR_FLAT_WATER_TILE;
00759 uint offset = 0;
00760 uint edges_offset = 0;
00761
00762 if (ti->tileh != SLOPE_FLAT || HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00763 image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
00764 if (image == 0) {
00765 switch (ti->tileh) {
00766 case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
00767 case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP; break;
00768 case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP; break;
00769 case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
00770 default: image = SPR_FLAT_WATER_TILE; break;
00771 }
00772 } else {
00773
00774 offset = HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE) ? 1 : 0;
00775
00776 switch (ti->tileh) {
00777 case SLOPE_SE: edges_offset += 12; break;
00778 case SLOPE_NE: offset += 1; edges_offset += 24; break;
00779 case SLOPE_SW: offset += 2; edges_offset += 36; break;
00780 case SLOPE_NW: offset += 3; edges_offset += 48; break;
00781 default: offset = 0; break;
00782 }
00783
00784 offset = GetCanalSpriteOffset(CF_RIVER_SLOPE, ti->tile, offset);
00785 }
00786 }
00787
00788 DrawGroundSprite(image + offset, PAL_NONE);
00789
00790
00791 DrawWaterEdges(false, edges_offset, ti->tile);
00792 }
00793
00794 void DrawShoreTile(Slope tileh)
00795 {
00796
00797
00798 static const byte tileh_to_shoresprite[32] = {
00799 0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
00800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 15, 0,
00801 };
00802
00803 assert(!IsHalftileSlope(tileh));
00804 assert(tileh != SLOPE_FLAT);
00805
00806 assert((tileh != SLOPE_EW) && (tileh != SLOPE_NS));
00807
00808 DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[tileh], PAL_NONE);
00809 }
00810
00811 void DrawWaterClassGround(const TileInfo *ti)
00812 {
00813 switch (GetWaterClass(ti->tile)) {
00814 case WATER_CLASS_SEA: DrawSeaWater(ti->tile); break;
00815 case WATER_CLASS_CANAL: DrawCanalWater(ti->tile); break;
00816 case WATER_CLASS_RIVER: DrawRiverWater(ti); break;
00817 default: NOT_REACHED();
00818 }
00819 }
00820
00821 static void DrawTile_Water(TileInfo *ti)
00822 {
00823 switch (GetWaterTileType(ti->tile)) {
00824 case WATER_TILE_CLEAR:
00825 DrawWaterClassGround(ti);
00826 DrawBridgeMiddle(ti);
00827 break;
00828
00829 case WATER_TILE_COAST: {
00830 DrawShoreTile(ti->tileh);
00831 DrawBridgeMiddle(ti);
00832 break;
00833 }
00834
00835 case WATER_TILE_LOCK:
00836 DrawWaterLock(ti);
00837 break;
00838
00839 case WATER_TILE_DEPOT:
00840 DrawWaterDepot(ti);
00841 break;
00842 }
00843 }
00844
00845 void DrawShipDepotSprite(int x, int y, Axis axis, DepotPart part)
00846 {
00847 const DrawTileSprites &dts = _shipdepot_display_data[axis][part];
00848
00849 DrawSprite(dts.ground.sprite, dts.ground.pal, x, y);
00850 DrawOrigTileSeqInGUI(x, y, &dts, COMPANY_SPRITE_COLOUR(_local_company));
00851 }
00852
00853
00854 static uint GetSlopeZ_Water(TileIndex tile, uint x, uint y)
00855 {
00856 uint z;
00857 Slope tileh = GetTileSlope(tile, &z);
00858
00859 return z + GetPartialZ(x & 0xF, y & 0xF, tileh);
00860 }
00861
00862 static Foundation GetFoundation_Water(TileIndex tile, Slope tileh)
00863 {
00864 return FOUNDATION_NONE;
00865 }
00866
00867 static void GetTileDesc_Water(TileIndex tile, TileDesc *td)
00868 {
00869 switch (GetWaterTileType(tile)) {
00870 case WATER_TILE_CLEAR:
00871 switch (GetWaterClass(tile)) {
00872 case WATER_CLASS_SEA: td->str = STR_LAI_WATER_DESCRIPTION_WATER; break;
00873 case WATER_CLASS_CANAL: td->str = STR_LAI_WATER_DESCRIPTION_CANAL; break;
00874 case WATER_CLASS_RIVER: td->str = STR_LAI_WATER_DESCRIPTION_RIVER; break;
00875 default: NOT_REACHED(); break;
00876 }
00877 break;
00878 case WATER_TILE_COAST: td->str = STR_LAI_WATER_DESCRIPTION_COAST_OR_RIVERBANK; break;
00879 case WATER_TILE_LOCK : td->str = STR_LAI_WATER_DESCRIPTION_LOCK; break;
00880 case WATER_TILE_DEPOT:
00881 td->str = STR_LAI_WATER_DESCRIPTION_SHIP_DEPOT;
00882 td->build_date = Depot::GetByTile(tile)->build_date;
00883 break;
00884 default: NOT_REACHED(); break;
00885 }
00886
00887 td->owner[0] = GetTileOwner(tile);
00888 }
00889
00895 static void FloodVehicle(Vehicle *v)
00896 {
00897 uint pass = v->Crash(true);
00898
00899 AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_FLOODED));
00900 SetDParam(0, pass);
00901 AddVehicleNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NS_ACCIDENT, v->index);
00902 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
00903 SndPlayVehicleFx(SND_12_EXPLOSION, v);
00904 }
00905
00912 static Vehicle *FloodVehicleProc(Vehicle *v, void *data)
00913 {
00914 if ((v->vehstatus & VS_CRASHED) != 0) return NULL;
00915
00916 switch (v->type) {
00917 default: break;
00918
00919 case VEH_AIRCRAFT: {
00920 if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
00921 if (v->subtype == AIR_SHADOW) break;
00922
00923
00924
00925 const Station *st = Station::GetByTile(v->tile);
00926 const AirportFTAClass *airport = st->airport.GetFTA();
00927 if (v->z_pos != airport->delta_z + 1) break;
00928
00929 FloodVehicle(v);
00930 break;
00931 }
00932
00933 case VEH_TRAIN:
00934 case VEH_ROAD: {
00935 int z = *(byte*)data;
00936 if (v->z_pos > z) break;
00937 FloodVehicle(v->First());
00938 break;
00939 }
00940 }
00941
00942 return NULL;
00943 }
00944
00950 static void FloodVehicles(TileIndex tile)
00951 {
00952 int z = 0;
00953
00954 if (IsAirportTile(tile)) {
00955 const Station *st = Station::GetByTile(tile);
00956 TILE_AREA_LOOP(tile, st->airport) {
00957 if (st->TileBelongsToAirport(tile)) FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00958 }
00959
00960
00961 return;
00962 }
00963
00964 if (!IsBridgeTile(tile)) {
00965 FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00966 return;
00967 }
00968
00969 TileIndex end = GetOtherBridgeEnd(tile);
00970 z = GetBridgeHeight(tile);
00971
00972 FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00973 FindVehicleOnPos(end, &z, &FloodVehicleProc);
00974 }
00975
00981 FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
00982 {
00983
00984
00985
00986
00987
00988 switch (GetTileType(tile)) {
00989 case MP_WATER:
00990 if (IsCoast(tile)) {
00991 Slope tileh = GetTileSlope(tile, NULL);
00992 return (IsSlopeWithOneCornerRaised(tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
00993 }
00994
00995 case MP_STATION:
00996 case MP_INDUSTRY:
00997 case MP_OBJECT:
00998 return (GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE;
00999
01000 case MP_RAILWAY:
01001 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
01002 return (IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL)) ? FLOOD_ACTIVE : FLOOD_DRYUP);
01003 }
01004 return FLOOD_NONE;
01005
01006 case MP_TREES:
01007 return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
01008
01009 default:
01010 return FLOOD_NONE;
01011 }
01012 }
01013
01017 void DoFloodTile(TileIndex target)
01018 {
01019 assert(!IsTileType(target, MP_WATER));
01020
01021 bool flooded = false;
01022
01023 Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
01024
01025 Slope tileh = GetTileSlope(target, NULL);
01026 if (tileh != SLOPE_FLAT) {
01027
01028 switch (GetTileType(target)) {
01029 case MP_RAILWAY: {
01030 if (!IsPlainRail(target)) break;
01031 FloodVehicles(target);
01032 flooded = FloodHalftile(target);
01033 break;
01034 }
01035
01036 case MP_TREES:
01037 if (!IsSlopeWithOneCornerRaised(tileh)) {
01038 SetTreeGroundDensity(target, TREE_GROUND_SHORE, 3);
01039 MarkTileDirtyByTile(target);
01040 flooded = true;
01041 break;
01042 }
01043
01044
01045 case MP_CLEAR:
01046 if (DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
01047 MakeShore(target);
01048 MarkTileDirtyByTile(target);
01049 flooded = true;
01050 }
01051 break;
01052
01053 default:
01054 break;
01055 }
01056 } else {
01057
01058 FloodVehicles(target);
01059
01060
01061 if (DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
01062 MakeSea(target);
01063 MarkTileDirtyByTile(target);
01064 flooded = true;
01065 }
01066 }
01067
01068 if (flooded) {
01069
01070 MarkCanalsAndRiversAroundDirty(target);
01071
01072
01073 UpdateSignalsInBuffer();
01074 }
01075
01076 cur_company.Restore();
01077 }
01078
01082 static void DoDryUp(TileIndex tile)
01083 {
01084 Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
01085
01086 switch (GetTileType(tile)) {
01087 case MP_RAILWAY:
01088 assert(IsPlainRail(tile));
01089 assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
01090
01091 RailGroundType new_ground;
01092 switch (GetTrackBits(tile)) {
01093 case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
01094 case TRACK_BIT_LOWER: new_ground = RAIL_GROUND_FENCE_HORIZ2; break;
01095 case TRACK_BIT_LEFT: new_ground = RAIL_GROUND_FENCE_VERT1; break;
01096 case TRACK_BIT_RIGHT: new_ground = RAIL_GROUND_FENCE_VERT2; break;
01097 default: NOT_REACHED();
01098 }
01099 SetRailGroundType(tile, new_ground);
01100 MarkTileDirtyByTile(tile);
01101 break;
01102
01103 case MP_TREES:
01104 SetTreeGroundDensity(tile, TREE_GROUND_GRASS, 3);
01105 MarkTileDirtyByTile(tile);
01106 break;
01107
01108 case MP_WATER:
01109 assert(IsCoast(tile));
01110
01111 if (DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
01112 MakeClear(tile, CLEAR_GRASS, 3);
01113 MarkTileDirtyByTile(tile);
01114 }
01115 break;
01116
01117 default: NOT_REACHED();
01118 }
01119
01120 cur_company.Restore();
01121 }
01122
01129 void TileLoop_Water(TileIndex tile)
01130 {
01131 switch (GetFloodingBehaviour(tile)) {
01132 case FLOOD_ACTIVE:
01133 for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
01134 TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir(dir));
01135 if (dest == INVALID_TILE) continue;
01136
01137 if (IsTileType(dest, MP_WATER)) continue;
01138
01139 uint z_dest;
01140 Slope slope_dest = GetFoundationSlope(dest, &z_dest) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
01141 if (z_dest > 0) continue;
01142
01143 if (!HasBit(_flood_from_dirs[slope_dest], ReverseDir(dir))) continue;
01144
01145 DoFloodTile(dest);
01146 }
01147 break;
01148
01149 case FLOOD_DRYUP: {
01150 Slope slope_here = GetFoundationSlope(tile, NULL) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
01151 uint dir;
01152 FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope_here]) {
01153 TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir((Direction)dir));
01154 if (dest == INVALID_TILE) continue;
01155
01156 FloodingBehaviour dest_behaviour = GetFloodingBehaviour(dest);
01157 if ((dest_behaviour == FLOOD_ACTIVE) || (dest_behaviour == FLOOD_PASSIVE)) return;
01158 }
01159 DoDryUp(tile);
01160 break;
01161 }
01162
01163 default: return;
01164 }
01165 }
01166
01167 void ConvertGroundTilesIntoWaterTiles()
01168 {
01169 uint z;
01170
01171 for (TileIndex tile = 0; tile < MapSize(); ++tile) {
01172 Slope slope = GetTileSlope(tile, &z);
01173 if (IsTileType(tile, MP_CLEAR) && z == 0) {
01174
01175
01176
01177 switch (slope) {
01178 case SLOPE_FLAT:
01179 MakeSea(tile);
01180 break;
01181
01182 case SLOPE_N:
01183 case SLOPE_E:
01184 case SLOPE_S:
01185 case SLOPE_W:
01186 MakeShore(tile);
01187 break;
01188
01189 default:
01190 uint dir;
01191 FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope & ~SLOPE_STEEP]) {
01192 TileIndex dest = TILE_ADD(tile, TileOffsByDir((Direction)dir));
01193 Slope slope_dest = GetTileSlope(dest, NULL) & ~SLOPE_STEEP;
01194 if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) {
01195 MakeShore(tile);
01196 break;
01197 }
01198 }
01199 break;
01200 }
01201 }
01202 }
01203 }
01204
01205 static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
01206 {
01207 static const byte coast_tracks[] = {0, 32, 4, 0, 16, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0};
01208
01209 TrackBits ts;
01210
01211 if (mode != TRANSPORT_WATER) return 0;
01212
01213 switch (GetWaterTileType(tile)) {
01214 case WATER_TILE_CLEAR: ts = (GetTileSlope(tile, NULL) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
01215 case WATER_TILE_COAST: ts = (TrackBits)coast_tracks[GetTileSlope(tile, NULL) & 0xF]; break;
01216 case WATER_TILE_LOCK: ts = DiagDirToDiagTrackBits(GetLockDirection(tile)); break;
01217 case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
01218 default: return 0;
01219 }
01220 if (TileX(tile) == 0) {
01221
01222 ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
01223 }
01224 if (TileY(tile) == 0) {
01225
01226 ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
01227 }
01228 return CombineTrackStatus(TrackBitsToTrackdirBits(ts), TRACKDIR_BIT_NONE);
01229 }
01230
01231 static bool ClickTile_Water(TileIndex tile)
01232 {
01233 if (GetWaterTileType(tile) == WATER_TILE_DEPOT) {
01234 ShowDepotWindow(GetShipDepotNorthTile(tile), VEH_SHIP);
01235 return true;
01236 }
01237 return false;
01238 }
01239
01240 static void ChangeTileOwner_Water(TileIndex tile, Owner old_owner, Owner new_owner)
01241 {
01242 if (!IsTileOwner(tile, old_owner)) return;
01243
01244 bool is_lock_middle = IsLock(tile) && GetLockPart(tile) == LOCK_PART_MIDDLE;
01245
01246
01247 if (is_lock_middle) Company::Get(old_owner)->water_infrastructure -= 3 * LOCK_DEPOT_TILE_FACTOR;
01248 if (new_owner != INVALID_OWNER) {
01249 if (is_lock_middle) Company::Get(new_owner)->water_infrastructure += 3 * LOCK_DEPOT_TILE_FACTOR;
01250
01251
01252 if (GetWaterClass(tile) == WATER_CLASS_CANAL && !is_lock_middle) {
01253 Company::Get(old_owner)->water_infrastructure--;
01254 Company::Get(new_owner)->water_infrastructure++;
01255 }
01256 if (IsShipDepot(tile)) {
01257 Company::Get(old_owner)->water_infrastructure -= LOCK_DEPOT_TILE_FACTOR;
01258 Company::Get(new_owner)->water_infrastructure += LOCK_DEPOT_TILE_FACTOR;
01259 }
01260
01261 SetTileOwner(tile, new_owner);
01262 return;
01263 }
01264
01265
01266 if (IsShipDepot(tile)) DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
01267
01268
01269
01270 if (IsTileOwner(tile, old_owner)) {
01271 if (GetWaterClass(tile) == WATER_CLASS_CANAL && !is_lock_middle) Company::Get(old_owner)->water_infrastructure--;
01272 SetTileOwner(tile, OWNER_NONE);
01273 }
01274 }
01275
01276 static VehicleEnterTileStatus VehicleEnter_Water(Vehicle *v, TileIndex tile, int x, int y)
01277 {
01278 return VETSB_CONTINUE;
01279 }
01280
01281 static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
01282 {
01283
01284 if (IsWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
01285
01286 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
01287 }
01288
01289
01290 extern const TileTypeProcs _tile_type_water_procs = {
01291 DrawTile_Water,
01292 GetSlopeZ_Water,
01293 ClearTile_Water,
01294 NULL,
01295 GetTileDesc_Water,
01296 GetTileTrackStatus_Water,
01297 ClickTile_Water,
01298 NULL,
01299 TileLoop_Water,
01300 ChangeTileOwner_Water,
01301 NULL,
01302 VehicleEnter_Water,
01303 GetFoundation_Water,
01304 TerraformTile_Water,
01305 };