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) != SLOPE_FLAT || GetTileSlope(tile2) != 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)->infrastructure.water += wc1 == WATER_CLASS_CANAL && wc2 == WATER_CLASS_CANAL ? 2 : 1;
00142 }
00143 Company::Get(_current_company)->infrastructure.water += 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 int 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->infrastructure.water--;
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->infrastructure.water++;
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->infrastructure.water -= 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 int delta = TileOffsByDiagDir(dir);
00243 CommandCost ret = EnsureNoVehicleOnGround(tile);
00244 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
00245 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
00246 if (ret.Failed()) return ret;
00247
00248
00249 WaterClass wc_middle = IsWaterTile(tile) ? GetWaterClass(tile) : WATER_CLASS_CANAL;
00250 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00251 if (ret.Failed()) return ret;
00252 cost.AddCost(ret);
00253
00254
00255 WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
00256
00257 if (!IsWaterTile(tile - delta)) {
00258 ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00259 if (ret.Failed()) return ret;
00260 cost.AddCost(ret);
00261 cost.AddCost(_price[PR_BUILD_CANAL]);
00262 }
00263 if (GetTileSlope(tile - delta) != SLOPE_FLAT) {
00264 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00265 }
00266
00267
00268 WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
00269
00270 if (!IsWaterTile(tile + delta)) {
00271 ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00272 if (ret.Failed()) return ret;
00273 cost.AddCost(ret);
00274 cost.AddCost(_price[PR_BUILD_CANAL]);
00275 }
00276 if (GetTileSlope(tile + delta) != SLOPE_FLAT) {
00277 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00278 }
00279
00280 if ((MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) ||
00281 (MayHaveBridgeAbove(tile - delta) && IsBridgeAbove(tile - delta)) ||
00282 (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) {
00283 return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00284 }
00285
00286 if (flags & DC_EXEC) {
00287
00288 Company *c = Company::GetIfValid(_current_company);
00289 if (c != NULL) {
00290
00291 c->infrastructure.water++;
00292 if (!IsWaterTile(tile - delta)) c->infrastructure.water++;
00293 if (!IsWaterTile(tile + delta)) c->infrastructure.water++;
00294
00295 c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR;
00296 DirtyCompanyInfrastructureWindows(_current_company);
00297 }
00298
00299 MakeLock(tile, _current_company, dir, wc_lower, wc_upper, wc_middle);
00300 MarkTileDirtyByTile(tile);
00301 MarkTileDirtyByTile(tile - delta);
00302 MarkTileDirtyByTile(tile + delta);
00303 MarkCanalsAndRiversAroundDirty(tile - delta);
00304 MarkCanalsAndRiversAroundDirty(tile + delta);
00305 }
00306 cost.AddCost(_price[PR_BUILD_LOCK]);
00307
00308 return cost;
00309 }
00310
00317 static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
00318 {
00319 if (GetTileOwner(tile) != OWNER_NONE) {
00320 CommandCost ret = CheckTileOwnership(tile);
00321 if (ret.Failed()) return ret;
00322 }
00323
00324 TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile));
00325
00326
00327 CommandCost ret = EnsureNoVehicleOnGround(tile);
00328 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
00329 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
00330 if (ret.Failed()) return ret;
00331
00332 if (flags & DC_EXEC) {
00333
00334 Company *c = Company::GetIfValid(GetTileOwner(tile));
00335 if (c != NULL) {
00336 c->infrastructure.water -= 1 + 3 * LOCK_DEPOT_TILE_FACTOR;
00337 DirtyCompanyInfrastructureWindows(c->index);
00338 }
00339
00340 if (GetWaterClass(tile) == WATER_CLASS_RIVER) {
00341 MakeRiver(tile, Random());
00342 } else {
00343 DoClearSquare(tile);
00344 }
00345 MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
00346 MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
00347 MarkCanalsAndRiversAroundDirty(tile);
00348 MarkCanalsAndRiversAroundDirty(tile - delta);
00349 MarkCanalsAndRiversAroundDirty(tile + delta);
00350 }
00351
00352 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]);
00353 }
00354
00364 CommandCost CmdBuildLock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00365 {
00366 DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));
00367 if (dir == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00368
00369 return DoBuildLock(tile, dir, flags);
00370 }
00371
00373 bool RiverModifyDesertZone(TileIndex tile, void *)
00374 {
00375 if (GetTropicZone(tile) == TROPICZONE_DESERT) SetTropicZone(tile, TROPICZONE_NORMAL);
00376 return false;
00377 }
00378
00388 CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00389 {
00390 WaterClass wc = Extract<WaterClass, 0, 2>(p2);
00391 if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR;
00392
00393
00394 if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;
00395
00396 TileArea ta(tile, p1);
00397
00398
00399 if (_game_mode != GM_EDITOR && ta.w != 1 && ta.h != 1) return CMD_ERROR;
00400
00401 CommandCost cost(EXPENSES_CONSTRUCTION);
00402 TILE_AREA_LOOP(tile, ta) {
00403 CommandCost ret;
00404
00405 Slope slope = GetTileSlope(tile);
00406 if (slope != SLOPE_FLAT && (wc != WATER_CLASS_RIVER || !IsInclinedSlope(slope))) {
00407 return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
00408 }
00409
00410
00411 if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;
00412
00413 ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
00414 if (ret.Failed()) return ret;
00415 cost.AddCost(ret);
00416
00417 if (flags & DC_EXEC) {
00418 switch (wc) {
00419 case WATER_CLASS_RIVER:
00420 MakeRiver(tile, Random());
00421 if (_game_mode == GM_EDITOR) {
00422 TileIndex tile2 = tile;
00423 CircularTileSearch(&tile2, 5, RiverModifyDesertZone, NULL);
00424 }
00425 break;
00426
00427 case WATER_CLASS_SEA:
00428 if (TileHeight(tile) == 0) {
00429 MakeSea(tile);
00430 break;
00431 }
00432
00433
00434 default:
00435 MakeCanal(tile, _current_company, Random());
00436 if (Company::IsValidID(_current_company)) {
00437 Company::Get(_current_company)->infrastructure.water++;
00438 DirtyCompanyInfrastructureWindows(_current_company);
00439 }
00440 break;
00441 }
00442 MarkTileDirtyByTile(tile);
00443 MarkCanalsAndRiversAroundDirty(tile);
00444 }
00445
00446 cost.AddCost(_price[PR_BUILD_CANAL]);
00447 }
00448
00449 if (cost.GetCost() == 0) {
00450 return_cmd_error(STR_ERROR_ALREADY_BUILT);
00451 } else {
00452 return cost;
00453 }
00454 }
00455
00456 static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
00457 {
00458 switch (GetWaterTileType(tile)) {
00459 case WATER_TILE_CLEAR: {
00460 if (flags & DC_NO_WATER) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
00461
00462 Money base_cost = IsCanal(tile) ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER];
00463
00464 if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(tile), 1, MapMaxX() - 1) ||
00465 !IsInsideMM(TileY(tile), 1, MapMaxY() - 1))) {
00466 return_cmd_error(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
00467 }
00468
00469
00470 CommandCost ret = EnsureNoVehicleOnGround(tile);
00471 if (ret.Failed()) return ret;
00472
00473 Owner owner = GetTileOwner(tile);
00474 if (owner != OWNER_WATER && owner != OWNER_NONE) {
00475 CommandCost ret = CheckTileOwnership(tile);
00476 if (ret.Failed()) return ret;
00477 }
00478
00479 if (flags & DC_EXEC) {
00480 if (IsCanal(tile) && Company::IsValidID(owner)) {
00481 Company::Get(owner)->infrastructure.water--;
00482 DirtyCompanyInfrastructureWindows(owner);
00483 }
00484 DoClearSquare(tile);
00485 MarkCanalsAndRiversAroundDirty(tile);
00486 }
00487
00488 return CommandCost(EXPENSES_CONSTRUCTION, base_cost);
00489 }
00490
00491 case WATER_TILE_COAST: {
00492 Slope slope = GetTileSlope(tile);
00493
00494
00495 CommandCost ret = EnsureNoVehicleOnGround(tile);
00496 if (ret.Failed()) return ret;
00497
00498 if (flags & DC_EXEC) {
00499 DoClearSquare(tile);
00500 MarkCanalsAndRiversAroundDirty(tile);
00501 }
00502 if (IsSlopeWithOneCornerRaised(slope)) {
00503 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WATER]);
00504 } else {
00505 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROUGH]);
00506 }
00507 }
00508
00509 case WATER_TILE_LOCK: {
00510 static const TileIndexDiffC _lock_tomiddle_offs[][DIAGDIR_END] = {
00511
00512 { { 0, 0}, {0, 0}, { 0, 0}, {0, 0} },
00513 { {-1, 0}, {0, 1}, { 1, 0}, {0, -1} },
00514 { { 1, 0}, {0, -1}, {-1, 0}, {0, 1} },
00515 };
00516
00517 if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
00518 if (_current_company == OWNER_WATER) return CMD_ERROR;
00519
00520 return RemoveLock(tile + ToTileIndexDiff(_lock_tomiddle_offs[GetLockPart(tile)][GetLockDirection(tile)]), flags);
00521 }
00522
00523 case WATER_TILE_DEPOT:
00524 if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
00525 return RemoveShipDepot(tile, flags);
00526
00527 default:
00528 NOT_REACHED();
00529 }
00530 }
00531
00540 static bool IsWateredTile(TileIndex tile, Direction from)
00541 {
00542 switch (GetTileType(tile)) {
00543 case MP_WATER:
00544 switch (GetWaterTileType(tile)) {
00545 default: NOT_REACHED();
00546 case WATER_TILE_DEPOT: case WATER_TILE_CLEAR: return true;
00547 case WATER_TILE_LOCK: return DiagDirToAxis(GetLockDirection(tile)) == DiagDirToAxis(DirToDiagDir(from));
00548
00549 case WATER_TILE_COAST:
00550 switch (GetTileSlope(tile)) {
00551 case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
00552 case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
00553 case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
00554 case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
00555 default: return false;
00556 }
00557 }
00558
00559 case MP_RAILWAY:
00560 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
00561 assert(IsPlainRail(tile));
00562 switch (GetTileSlope(tile)) {
00563 case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
00564 case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
00565 case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
00566 case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
00567 default: return false;
00568 }
00569 }
00570 return false;
00571
00572 case MP_STATION:
00573 if (IsOilRig(tile)) {
00574
00575
00576 TileIndex src_tile = tile + TileOffsByDir(from);
00577 if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
00578 (IsTileType(src_tile, MP_INDUSTRY))) return true;
00579
00580 return IsTileOnWater(tile);
00581 }
00582 return (IsDock(tile) && GetTileSlope(tile) == SLOPE_FLAT) || IsBuoy(tile);
00583
00584 case MP_INDUSTRY: {
00585
00586
00587 TileIndex src_tile = tile + TileOffsByDir(from);
00588 if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
00589 (IsTileType(src_tile, MP_INDUSTRY) && GetIndustryIndex(src_tile) == GetIndustryIndex(tile))) return true;
00590
00591 return IsTileOnWater(tile);
00592 }
00593
00594 case MP_OBJECT: return IsTileOnWater(tile);
00595
00596 case MP_TUNNELBRIDGE: return GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER && ReverseDiagDir(GetTunnelBridgeDirection(tile)) == DirToDiagDir(from);
00597
00598 default: return false;
00599 }
00600 }
00601
00609 static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
00610 {
00611 if (base != SPR_FLAT_WATER_TILE) {
00612
00613 offset = GetCanalSpriteOffset(feature, tile, offset);
00614 }
00615 DrawGroundSprite(base + offset, PAL_NONE);
00616 }
00617
00624 static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
00625 {
00626 CanalFeature feature;
00627 SpriteID base = 0;
00628 if (canal) {
00629 feature = CF_DIKES;
00630 base = GetCanalSprite(CF_DIKES, tile);
00631 if (base == 0) base = SPR_CANAL_DIKES_BASE;
00632 } else {
00633 feature = CF_RIVER_EDGE;
00634 base = GetCanalSprite(CF_RIVER_EDGE, tile);
00635 if (base == 0) return;
00636 }
00637
00638 uint wa;
00639
00640
00641 wa = IsWateredTile(TILE_ADDXY(tile, -1, 0), DIR_SW) << 0;
00642 wa += IsWateredTile(TILE_ADDXY(tile, 0, 1), DIR_NW) << 1;
00643 wa += IsWateredTile(TILE_ADDXY(tile, 1, 0), DIR_NE) << 2;
00644 wa += IsWateredTile(TILE_ADDXY(tile, 0, -1), DIR_SE) << 3;
00645
00646 if (!(wa & 1)) DrawWaterSprite(base, offset, feature, tile);
00647 if (!(wa & 2)) DrawWaterSprite(base, offset + 1, feature, tile);
00648 if (!(wa & 4)) DrawWaterSprite(base, offset + 2, feature, tile);
00649 if (!(wa & 8)) DrawWaterSprite(base, offset + 3, feature, tile);
00650
00651
00652 switch (wa & 0x03) {
00653 case 0: DrawWaterSprite(base, offset + 4, feature, tile); break;
00654 case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1), DIR_W)) DrawWaterSprite(base, offset + 8, feature, tile); break;
00655 }
00656
00657
00658 switch (wa & 0x06) {
00659 case 0: DrawWaterSprite(base, offset + 5, feature, tile); break;
00660 case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1), DIR_N)) DrawWaterSprite(base, offset + 9, feature, tile); break;
00661 }
00662
00663
00664 switch (wa & 0x0C) {
00665 case 0: DrawWaterSprite(base, offset + 6, feature, tile); break;
00666 case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1), DIR_E)) DrawWaterSprite(base, offset + 10, feature, tile); break;
00667 }
00668
00669
00670 switch (wa & 0x09) {
00671 case 0: DrawWaterSprite(base, offset + 7, feature, tile); break;
00672 case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawWaterSprite(base, offset + 11, feature, tile); break;
00673 }
00674 }
00675
00677 static void DrawSeaWater(TileIndex tile)
00678 {
00679 DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
00680 }
00681
00683 static void DrawCanalWater(TileIndex tile)
00684 {
00685 SpriteID image = SPR_FLAT_WATER_TILE;
00686 if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00687
00688 image = GetCanalSprite(CF_WATERSLOPE, tile);
00689 if (image == 0) image = SPR_FLAT_WATER_TILE;
00690 }
00691 DrawWaterSprite(image, 0, CF_WATERSLOPE, tile);
00692
00693 DrawWaterEdges(true, 0, tile);
00694 }
00695
00696 #include "table/water_land.h"
00697
00707 static void DrawWaterTileStruct(const TileInfo *ti, const DrawTileSeqStruct *dtss, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
00708 {
00709
00710 if (IsInvisibilitySet(TO_BUILDINGS)) return;
00711
00712 for (; !dtss->IsTerminator(); dtss++) {
00713 uint tile_offs = offset + dtss->image.sprite;
00714 if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
00715 AddSortableSpriteToDraw(base + tile_offs, palette,
00716 ti->x + dtss->delta_x, ti->y + dtss->delta_y,
00717 dtss->size_x, dtss->size_y,
00718 dtss->size_z, ti->z + dtss->delta_z,
00719 IsTransparencySet(TO_BUILDINGS));
00720 }
00721 }
00722
00724 static void DrawWaterLock(const TileInfo *ti)
00725 {
00726 int part = GetLockPart(ti->tile);
00727 const DrawTileSprites &dts = _lock_display_data[part][GetLockDirection(ti->tile)];
00728
00729
00730 SpriteID image = dts.ground.sprite;
00731
00732 SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile);
00733 if (water_base == 0) {
00734
00735 water_base = SPR_CANALS_BASE;
00736 } else if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00737
00738 if (image == SPR_FLAT_WATER_TILE) {
00739 image = water_base;
00740 } else {
00741 image++;
00742 }
00743 }
00744
00745 if (image < 5) image += water_base;
00746 DrawGroundSprite(image, PAL_NONE);
00747
00748
00749 uint zoffs = 0;
00750 SpriteID base = GetCanalSprite(CF_LOCKS, ti->tile);
00751
00752 if (base == 0) {
00753
00754 base = SPR_LOCK_BASE;
00755 uint8 z_threshold = part == LOCK_PART_UPPER ? 8 : 0;
00756 zoffs = ti->z > z_threshold ? 24 : 0;
00757 }
00758
00759 DrawWaterTileStruct(ti, dts.seq, base, zoffs, PAL_NONE, CF_LOCKS);
00760 }
00761
00763 static void DrawWaterDepot(const TileInfo *ti)
00764 {
00765 DrawWaterClassGround(ti);
00766 DrawWaterTileStruct(ti, _shipdepot_display_data[GetShipDepotAxis(ti->tile)][GetShipDepotPart(ti->tile)].seq, 0, 0, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)), CF_END);
00767 }
00768
00769 static void DrawRiverWater(const TileInfo *ti)
00770 {
00771 SpriteID image = SPR_FLAT_WATER_TILE;
00772 uint offset = 0;
00773 uint edges_offset = 0;
00774
00775 if (ti->tileh != SLOPE_FLAT || HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00776 image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
00777 if (image == 0) {
00778 switch (ti->tileh) {
00779 case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
00780 case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP; break;
00781 case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP; break;
00782 case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
00783 default: image = SPR_FLAT_WATER_TILE; break;
00784 }
00785 } else {
00786
00787 offset = HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE) ? 1 : 0;
00788
00789 switch (ti->tileh) {
00790 case SLOPE_SE: edges_offset += 12; break;
00791 case SLOPE_NE: offset += 1; edges_offset += 24; break;
00792 case SLOPE_SW: offset += 2; edges_offset += 36; break;
00793 case SLOPE_NW: offset += 3; edges_offset += 48; break;
00794 default: offset = 0; break;
00795 }
00796
00797 offset = GetCanalSpriteOffset(CF_RIVER_SLOPE, ti->tile, offset);
00798 }
00799 }
00800
00801 DrawGroundSprite(image + offset, PAL_NONE);
00802
00803
00804 DrawWaterEdges(false, edges_offset, ti->tile);
00805 }
00806
00807 void DrawShoreTile(Slope tileh)
00808 {
00809
00810
00811 static const byte tileh_to_shoresprite[32] = {
00812 0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
00813 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 15, 0,
00814 };
00815
00816 assert(!IsHalftileSlope(tileh));
00817 assert(tileh != SLOPE_FLAT);
00818
00819 assert((tileh != SLOPE_EW) && (tileh != SLOPE_NS));
00820
00821 DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[tileh], PAL_NONE);
00822 }
00823
00824 void DrawWaterClassGround(const TileInfo *ti)
00825 {
00826 switch (GetWaterClass(ti->tile)) {
00827 case WATER_CLASS_SEA: DrawSeaWater(ti->tile); break;
00828 case WATER_CLASS_CANAL: DrawCanalWater(ti->tile); break;
00829 case WATER_CLASS_RIVER: DrawRiverWater(ti); break;
00830 default: NOT_REACHED();
00831 }
00832 }
00833
00834 static void DrawTile_Water(TileInfo *ti)
00835 {
00836 switch (GetWaterTileType(ti->tile)) {
00837 case WATER_TILE_CLEAR:
00838 DrawWaterClassGround(ti);
00839 DrawBridgeMiddle(ti);
00840 break;
00841
00842 case WATER_TILE_COAST: {
00843 DrawShoreTile(ti->tileh);
00844 DrawBridgeMiddle(ti);
00845 break;
00846 }
00847
00848 case WATER_TILE_LOCK:
00849 DrawWaterLock(ti);
00850 break;
00851
00852 case WATER_TILE_DEPOT:
00853 DrawWaterDepot(ti);
00854 break;
00855 }
00856 }
00857
00858 void DrawShipDepotSprite(int x, int y, Axis axis, DepotPart part)
00859 {
00860 const DrawTileSprites &dts = _shipdepot_display_data[axis][part];
00861
00862 DrawSprite(dts.ground.sprite, dts.ground.pal, x, y);
00863 DrawOrigTileSeqInGUI(x, y, &dts, COMPANY_SPRITE_COLOUR(_local_company));
00864 }
00865
00866
00867 static int GetSlopePixelZ_Water(TileIndex tile, uint x, uint y)
00868 {
00869 int z;
00870 Slope tileh = GetTilePixelSlope(tile, &z);
00871
00872 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
00873 }
00874
00875 static Foundation GetFoundation_Water(TileIndex tile, Slope tileh)
00876 {
00877 return FOUNDATION_NONE;
00878 }
00879
00880 static void GetTileDesc_Water(TileIndex tile, TileDesc *td)
00881 {
00882 switch (GetWaterTileType(tile)) {
00883 case WATER_TILE_CLEAR:
00884 switch (GetWaterClass(tile)) {
00885 case WATER_CLASS_SEA: td->str = STR_LAI_WATER_DESCRIPTION_WATER; break;
00886 case WATER_CLASS_CANAL: td->str = STR_LAI_WATER_DESCRIPTION_CANAL; break;
00887 case WATER_CLASS_RIVER: td->str = STR_LAI_WATER_DESCRIPTION_RIVER; break;
00888 default: NOT_REACHED(); break;
00889 }
00890 break;
00891 case WATER_TILE_COAST: td->str = STR_LAI_WATER_DESCRIPTION_COAST_OR_RIVERBANK; break;
00892 case WATER_TILE_LOCK : td->str = STR_LAI_WATER_DESCRIPTION_LOCK; break;
00893 case WATER_TILE_DEPOT:
00894 td->str = STR_LAI_WATER_DESCRIPTION_SHIP_DEPOT;
00895 td->build_date = Depot::GetByTile(tile)->build_date;
00896 break;
00897 default: NOT_REACHED(); break;
00898 }
00899
00900 td->owner[0] = GetTileOwner(tile);
00901 }
00902
00908 static void FloodVehicle(Vehicle *v)
00909 {
00910 uint pass = v->Crash(true);
00911
00912 AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED));
00913 SetDParam(0, pass);
00914 AddVehicleNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NS_ACCIDENT, v->index);
00915 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
00916 SndPlayVehicleFx(SND_12_EXPLOSION, v);
00917 }
00918
00925 static Vehicle *FloodVehicleProc(Vehicle *v, void *data)
00926 {
00927 if ((v->vehstatus & VS_CRASHED) != 0) return NULL;
00928
00929 switch (v->type) {
00930 default: break;
00931
00932 case VEH_AIRCRAFT: {
00933 if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
00934 if (v->subtype == AIR_SHADOW) break;
00935
00936
00937
00938 const Station *st = Station::GetByTile(v->tile);
00939 const AirportFTAClass *airport = st->airport.GetFTA();
00940 if (v->z_pos != airport->delta_z + 1) break;
00941
00942 FloodVehicle(v);
00943 break;
00944 }
00945
00946 case VEH_TRAIN:
00947 case VEH_ROAD: {
00948 int z = *(int*)data;
00949 if (v->z_pos > z) break;
00950 FloodVehicle(v->First());
00951 break;
00952 }
00953 }
00954
00955 return NULL;
00956 }
00957
00963 static void FloodVehicles(TileIndex tile)
00964 {
00965 int z = 0;
00966
00967 if (IsAirportTile(tile)) {
00968 const Station *st = Station::GetByTile(tile);
00969 TILE_AREA_LOOP(tile, st->airport) {
00970 if (st->TileBelongsToAirport(tile)) FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00971 }
00972
00973
00974 return;
00975 }
00976
00977 if (!IsBridgeTile(tile)) {
00978 FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00979 return;
00980 }
00981
00982 TileIndex end = GetOtherBridgeEnd(tile);
00983 z = GetBridgePixelHeight(tile);
00984
00985 FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00986 FindVehicleOnPos(end, &z, &FloodVehicleProc);
00987 }
00988
00994 FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
00995 {
00996
00997
00998
00999
01000
01001 switch (GetTileType(tile)) {
01002 case MP_WATER:
01003 if (IsCoast(tile)) {
01004 Slope tileh = GetTileSlope(tile);
01005 return (IsSlopeWithOneCornerRaised(tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
01006 }
01007
01008 case MP_STATION:
01009 case MP_INDUSTRY:
01010 case MP_OBJECT:
01011 return (GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE;
01012
01013 case MP_RAILWAY:
01014 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
01015 return (IsSlopeWithOneCornerRaised(GetTileSlope(tile)) ? FLOOD_ACTIVE : FLOOD_DRYUP);
01016 }
01017 return FLOOD_NONE;
01018
01019 case MP_TREES:
01020 return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
01021
01022 default:
01023 return FLOOD_NONE;
01024 }
01025 }
01026
01030 void DoFloodTile(TileIndex target)
01031 {
01032 assert(!IsTileType(target, MP_WATER));
01033
01034 bool flooded = false;
01035
01036 Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
01037
01038 Slope tileh = GetTileSlope(target);
01039 if (tileh != SLOPE_FLAT) {
01040
01041 switch (GetTileType(target)) {
01042 case MP_RAILWAY: {
01043 if (!IsPlainRail(target)) break;
01044 FloodVehicles(target);
01045 flooded = FloodHalftile(target);
01046 break;
01047 }
01048
01049 case MP_TREES:
01050 if (!IsSlopeWithOneCornerRaised(tileh)) {
01051 SetTreeGroundDensity(target, TREE_GROUND_SHORE, 3);
01052 MarkTileDirtyByTile(target);
01053 flooded = true;
01054 break;
01055 }
01056
01057
01058 case MP_CLEAR:
01059 if (DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
01060 MakeShore(target);
01061 MarkTileDirtyByTile(target);
01062 flooded = true;
01063 }
01064 break;
01065
01066 default:
01067 break;
01068 }
01069 } else {
01070
01071 FloodVehicles(target);
01072
01073
01074 if (DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
01075 MakeSea(target);
01076 MarkTileDirtyByTile(target);
01077 flooded = true;
01078 }
01079 }
01080
01081 if (flooded) {
01082
01083 MarkCanalsAndRiversAroundDirty(target);
01084
01085
01086 UpdateSignalsInBuffer();
01087 }
01088
01089 cur_company.Restore();
01090 }
01091
01095 static void DoDryUp(TileIndex tile)
01096 {
01097 Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
01098
01099 switch (GetTileType(tile)) {
01100 case MP_RAILWAY:
01101 assert(IsPlainRail(tile));
01102 assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
01103
01104 RailGroundType new_ground;
01105 switch (GetTrackBits(tile)) {
01106 case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
01107 case TRACK_BIT_LOWER: new_ground = RAIL_GROUND_FENCE_HORIZ2; break;
01108 case TRACK_BIT_LEFT: new_ground = RAIL_GROUND_FENCE_VERT1; break;
01109 case TRACK_BIT_RIGHT: new_ground = RAIL_GROUND_FENCE_VERT2; break;
01110 default: NOT_REACHED();
01111 }
01112 SetRailGroundType(tile, new_ground);
01113 MarkTileDirtyByTile(tile);
01114 break;
01115
01116 case MP_TREES:
01117 SetTreeGroundDensity(tile, TREE_GROUND_GRASS, 3);
01118 MarkTileDirtyByTile(tile);
01119 break;
01120
01121 case MP_WATER:
01122 assert(IsCoast(tile));
01123
01124 if (DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
01125 MakeClear(tile, CLEAR_GRASS, 3);
01126 MarkTileDirtyByTile(tile);
01127 }
01128 break;
01129
01130 default: NOT_REACHED();
01131 }
01132
01133 cur_company.Restore();
01134 }
01135
01142 void TileLoop_Water(TileIndex tile)
01143 {
01144 if (IsTileType(tile, MP_WATER)) AmbientSoundEffectCallback(tile);
01145
01146 switch (GetFloodingBehaviour(tile)) {
01147 case FLOOD_ACTIVE:
01148 for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
01149 TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir(dir));
01150 if (dest == INVALID_TILE) continue;
01151
01152 if (IsTileType(dest, MP_WATER)) continue;
01153
01154 int z_dest;
01155 Slope slope_dest = GetFoundationSlope(dest, &z_dest) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
01156 if (z_dest > 0) continue;
01157
01158 if (!HasBit(_flood_from_dirs[slope_dest], ReverseDir(dir))) continue;
01159
01160 DoFloodTile(dest);
01161 }
01162 break;
01163
01164 case FLOOD_DRYUP: {
01165 Slope slope_here = GetFoundationSlope(tile) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
01166 uint dir;
01167 FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope_here]) {
01168 TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir((Direction)dir));
01169 if (dest == INVALID_TILE) continue;
01170
01171 FloodingBehaviour dest_behaviour = GetFloodingBehaviour(dest);
01172 if ((dest_behaviour == FLOOD_ACTIVE) || (dest_behaviour == FLOOD_PASSIVE)) return;
01173 }
01174 DoDryUp(tile);
01175 break;
01176 }
01177
01178 default: return;
01179 }
01180 }
01181
01182 void ConvertGroundTilesIntoWaterTiles()
01183 {
01184 int z;
01185
01186 for (TileIndex tile = 0; tile < MapSize(); ++tile) {
01187 Slope slope = GetTileSlope(tile, &z);
01188 if (IsTileType(tile, MP_CLEAR) && z == 0) {
01189
01190
01191
01192 switch (slope) {
01193 case SLOPE_FLAT:
01194 MakeSea(tile);
01195 break;
01196
01197 case SLOPE_N:
01198 case SLOPE_E:
01199 case SLOPE_S:
01200 case SLOPE_W:
01201 MakeShore(tile);
01202 break;
01203
01204 default:
01205 uint dir;
01206 FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope & ~SLOPE_STEEP]) {
01207 TileIndex dest = TILE_ADD(tile, TileOffsByDir((Direction)dir));
01208 Slope slope_dest = GetTileSlope(dest) & ~SLOPE_STEEP;
01209 if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) {
01210 MakeShore(tile);
01211 break;
01212 }
01213 }
01214 break;
01215 }
01216 }
01217 }
01218 }
01219
01220 static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
01221 {
01222 static const byte coast_tracks[] = {0, 32, 4, 0, 16, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0};
01223
01224 TrackBits ts;
01225
01226 if (mode != TRANSPORT_WATER) return 0;
01227
01228 switch (GetWaterTileType(tile)) {
01229 case WATER_TILE_CLEAR: ts = (GetTileSlope(tile) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
01230 case WATER_TILE_COAST: ts = (TrackBits)coast_tracks[GetTileSlope(tile) & 0xF]; break;
01231 case WATER_TILE_LOCK: ts = DiagDirToDiagTrackBits(GetLockDirection(tile)); break;
01232 case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
01233 default: return 0;
01234 }
01235 if (TileX(tile) == 0) {
01236
01237 ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
01238 }
01239 if (TileY(tile) == 0) {
01240
01241 ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
01242 }
01243 return CombineTrackStatus(TrackBitsToTrackdirBits(ts), TRACKDIR_BIT_NONE);
01244 }
01245
01246 static bool ClickTile_Water(TileIndex tile)
01247 {
01248 if (GetWaterTileType(tile) == WATER_TILE_DEPOT) {
01249 ShowDepotWindow(GetShipDepotNorthTile(tile), VEH_SHIP);
01250 return true;
01251 }
01252 return false;
01253 }
01254
01255 static void ChangeTileOwner_Water(TileIndex tile, Owner old_owner, Owner new_owner)
01256 {
01257 if (!IsTileOwner(tile, old_owner)) return;
01258
01259
01260 if (IsCanal(tile)) Company::Get(old_owner)->infrastructure.water--;
01261 if (new_owner != INVALID_OWNER) {
01262 if (IsCanal(tile)) Company::Get(new_owner)->infrastructure.water++;
01263 SetTileOwner(tile, new_owner);
01264 return;
01265 }
01266
01267
01268 if (IsShipDepot(tile)) DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
01269
01270
01271
01272 if (IsTileOwner(tile, old_owner)) {
01273 if (IsCanal(tile)) Company::Get(old_owner)->infrastructure.water--;
01274 SetTileOwner(tile, OWNER_NONE);
01275 }
01276 }
01277
01278 static VehicleEnterTileStatus VehicleEnter_Water(Vehicle *v, TileIndex tile, int x, int y)
01279 {
01280 return VETSB_CONTINUE;
01281 }
01282
01283 static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
01284 {
01285
01286 if (IsWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
01287
01288 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
01289 }
01290
01291
01292 extern const TileTypeProcs _tile_type_water_procs = {
01293 DrawTile_Water,
01294 GetSlopePixelZ_Water,
01295 ClearTile_Water,
01296 NULL,
01297 GetTileDesc_Water,
01298 GetTileTrackStatus_Water,
01299 ClickTile_Water,
01300 NULL,
01301 TileLoop_Water,
01302 ChangeTileOwner_Water,
01303 NULL,
01304 VehicleEnter_Water,
01305 GetFoundation_Water,
01306 TerraformTile_Water,
01307 };