water_cmd.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
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 
00039 #include "table/strings.h"
00040 
00044 static const uint8 _flood_from_dirs[] = {
00045   (1 << DIR_NW) | (1 << DIR_SW) | (1 << DIR_SE) | (1 << DIR_NE), // SLOPE_FLAT
00046   (1 << DIR_NE) | (1 << DIR_SE),                                 // SLOPE_W
00047   (1 << DIR_NW) | (1 << DIR_NE),                                 // SLOPE_S
00048   (1 << DIR_NE),                                                 // SLOPE_SW
00049   (1 << DIR_NW) | (1 << DIR_SW),                                 // SLOPE_E
00050   0,                                                             // SLOPE_EW
00051   (1 << DIR_NW),                                                 // SLOPE_SE
00052   (1 << DIR_N ) | (1 << DIR_NW) | (1 << DIR_NE),                 // SLOPE_WSE, SLOPE_STEEP_S
00053   (1 << DIR_SW) | (1 << DIR_SE),                                 // SLOPE_N
00054   (1 << DIR_SE),                                                 // SLOPE_NW
00055   0,                                                             // SLOPE_NS
00056   (1 << DIR_E ) | (1 << DIR_NE) | (1 << DIR_SE),                 // SLOPE_NWS, SLOPE_STEEP_W
00057   (1 << DIR_SW),                                                 // SLOPE_NE
00058   (1 << DIR_S ) | (1 << DIR_SW) | (1 << DIR_SE),                 // SLOPE_ENW, SLOPE_STEEP_N
00059   (1 << DIR_W ) | (1 << DIR_SW) | (1 << DIR_NW),                 // SLOPE_SEN, SLOPE_STEEP_E
00060 };
00061 
00068 static inline void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
00069 {
00070   if (IsTileType(tile, MP_WATER) && (IsCanal(tile) || IsRiver(tile))) MarkTileDirtyByTile(tile);
00071 }
00072 
00079 static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
00080 {
00081   for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
00082     MarkTileDirtyIfCanalOrRiver(tile + TileOffsByDir(dir));
00083   }
00084 }
00085 
00086 
00096 CommandCost CmdBuildShipDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00097 {
00098   Axis axis = Extract<Axis, 0, 1>(p1);
00099 
00100   TileIndex tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
00101 
00102   if (!HasTileWaterGround(tile) || !HasTileWaterGround(tile2)) {
00103     return_cmd_error(STR_ERROR_MUST_BE_BUILT_ON_WATER);
00104   }
00105 
00106   if ((MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) ||
00107     (MayHaveBridgeAbove(tile2) && IsBridgeAbove(tile2))) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00108 
00109   if (GetTileSlope(tile, NULL) != SLOPE_FLAT || GetTileSlope(tile2, NULL) != SLOPE_FLAT) {
00110     /* Prevent depots on rapids */
00111     return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
00112   }
00113 
00114   if (!Depot::CanAllocateItem()) return CMD_ERROR;
00115 
00116   WaterClass wc1 = GetWaterClass(tile);
00117   WaterClass wc2 = GetWaterClass(tile2);
00118   CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_DEPOT_SHIP]);
00119 
00120   bool add_cost = !IsWaterTile(tile);
00121   CommandCost ret = DoCommand(tile, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
00122   if (ret.Failed()) return ret;
00123   if (add_cost) {
00124     cost.AddCost(ret);
00125   }
00126   add_cost = !IsWaterTile(tile2);
00127   ret = DoCommand(tile2, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
00128   if (ret.Failed()) return ret;
00129   if (add_cost) {
00130     cost.AddCost(ret);
00131   }
00132 
00133   if (flags & DC_EXEC) {
00134     Depot *depot = new Depot(tile);
00135     depot->build_date = _date;
00136 
00137     MakeShipDepot(tile,  _current_company, depot->index, DEPOT_NORTH, axis, wc1);
00138     MakeShipDepot(tile2, _current_company, depot->index, DEPOT_SOUTH, axis, wc2);
00139     MarkTileDirtyByTile(tile);
00140     MarkTileDirtyByTile(tile2);
00141     MakeDefaultName(depot);
00142   }
00143 
00144   return cost;
00145 }
00146 
00147 void MakeWaterKeepingClass(TileIndex tile, Owner o)
00148 {
00149   WaterClass wc = GetWaterClass(tile);
00150 
00151   /* Autoslope might turn an originally canal or river tile into land */
00152   uint z;
00153   if (GetTileSlope(tile, &z) != SLOPE_FLAT) wc = WATER_CLASS_INVALID;
00154 
00155   if (wc == WATER_CLASS_SEA && z > 0) wc = WATER_CLASS_CANAL;
00156 
00157   /* Zero map array and terminate animation */
00158   DoClearSquare(tile);
00159 
00160   /* Maybe change to water */
00161   switch (wc) {
00162     case WATER_CLASS_SEA:   MakeSea(tile);                break;
00163     case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
00164     case WATER_CLASS_RIVER: MakeRiver(tile, Random());    break;
00165     default: break;
00166   }
00167 
00168   MarkTileDirtyByTile(tile);
00169 }
00170 
00171 static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlag flags)
00172 {
00173   if (!IsShipDepot(tile)) return CMD_ERROR;
00174 
00175   CommandCost ret = CheckTileOwnership(tile);
00176   if (ret.Failed()) return ret;
00177 
00178   TileIndex tile2 = GetOtherShipDepotTile(tile);
00179 
00180   /* do not check for ship on tile when company goes bankrupt */
00181   if (!(flags & DC_BANKRUPT)) {
00182     CommandCost ret = EnsureNoVehicleOnGround(tile);
00183     if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
00184     if (ret.Failed()) return ret;
00185   }
00186 
00187   if (flags & DC_EXEC) {
00188     delete Depot::GetByTile(tile);
00189 
00190     MakeWaterKeepingClass(tile,  GetTileOwner(tile));
00191     MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
00192   }
00193 
00194   return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_SHIP]);
00195 }
00196 
00204 static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlag flags)
00205 {
00206   CommandCost cost(EXPENSES_CONSTRUCTION);
00207 
00208   /* middle tile */
00209   CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00210   if (ret.Failed()) return ret;
00211   cost.AddCost(ret);
00212 
00213   int delta = TileOffsByDiagDir(dir);
00214   /* lower tile */
00215   WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
00216 
00217   if (!IsWaterTile(tile - delta)) {
00218     ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00219     if (ret.Failed()) return ret;
00220     cost.AddCost(ret);
00221     cost.AddCost(_price[PR_BUILD_CANAL]);
00222   }
00223   if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) {
00224     return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00225   }
00226 
00227   /* upper tile */
00228   WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
00229 
00230   if (!IsWaterTile(tile + delta)) {
00231     ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00232     if (ret.Failed()) return ret;
00233     cost.AddCost(ret);
00234     cost.AddCost(_price[PR_BUILD_CANAL]);
00235   }
00236   if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) {
00237     return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00238   }
00239 
00240   if ((MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) ||
00241       (MayHaveBridgeAbove(tile - delta) && IsBridgeAbove(tile - delta)) ||
00242       (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) {
00243     return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
00244   }
00245 
00246   if (flags & DC_EXEC) {
00247     MakeLock(tile, _current_company, dir, wc_lower, wc_upper);
00248     MarkTileDirtyByTile(tile);
00249     MarkTileDirtyByTile(tile - delta);
00250     MarkTileDirtyByTile(tile + delta);
00251     MarkCanalsAndRiversAroundDirty(tile - delta);
00252     MarkCanalsAndRiversAroundDirty(tile + delta);
00253   }
00254   cost.AddCost(_price[PR_BUILD_LOCK]);
00255 
00256   return cost;
00257 }
00258 
00265 static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
00266 {
00267   if (GetTileOwner(tile) != OWNER_NONE) {
00268     CommandCost ret = CheckTileOwnership(tile);
00269     if (ret.Failed()) return ret;
00270   }
00271 
00272   TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile));
00273 
00274   /* make sure no vehicle is on the tile. */
00275   CommandCost ret = EnsureNoVehicleOnGround(tile);
00276   if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
00277   if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
00278   if (ret.Failed()) return ret;
00279 
00280   if (flags & DC_EXEC) {
00281     DoClearSquare(tile);
00282     MakeWaterKeepingClass(tile + delta, GetTileOwner(tile));
00283     MakeWaterKeepingClass(tile - delta, GetTileOwner(tile));
00284     MarkCanalsAndRiversAroundDirty(tile - delta);
00285     MarkCanalsAndRiversAroundDirty(tile + delta);
00286   }
00287 
00288   return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]);
00289 }
00290 
00300 CommandCost CmdBuildLock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00301 {
00302   DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
00303   if (dir == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
00304 
00305   /* Disallow building of locks on river rapids */
00306   if (IsWaterTile(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
00307 
00308   return DoBuildLock(tile, dir, flags);
00309 }
00310 
00320 CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00321 {
00322   WaterClass wc = Extract<WaterClass, 0, 2>(p2);
00323   if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR;
00324 
00325   /* Outside of the editor you can only build canals, not oceans */
00326   if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;
00327 
00328   TileArea ta(tile, p1);
00329 
00330   /* Outside the editor you can only drag canals, and not areas */
00331   if (_game_mode != GM_EDITOR && ta.w != 1 && ta.h != 1) return CMD_ERROR;
00332 
00333   CommandCost cost(EXPENSES_CONSTRUCTION);
00334   TILE_AREA_LOOP(tile, ta) {
00335     CommandCost ret;
00336 
00337     Slope slope = GetTileSlope(tile, NULL);
00338     if (slope != SLOPE_FLAT && (wc != WATER_CLASS_RIVER || !IsInclinedSlope(slope))) {
00339       return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
00340     }
00341 
00342     /* can't make water of water! */
00343     if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;
00344 
00345     ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
00346     if (ret.Failed()) return ret;
00347     cost.AddCost(ret);
00348 
00349     if (flags & DC_EXEC) {
00350       switch (wc) {
00351         case WATER_CLASS_RIVER:
00352           MakeRiver(tile, Random());
00353           break;
00354 
00355         case WATER_CLASS_SEA:
00356           if (TileHeight(tile) == 0) {
00357             MakeSea(tile);
00358             break;
00359           }
00360           /* FALL THROUGH */
00361 
00362         default:
00363           MakeCanal(tile, _current_company, Random());
00364           break;
00365       }
00366       MarkTileDirtyByTile(tile);
00367       MarkCanalsAndRiversAroundDirty(tile);
00368     }
00369 
00370     cost.AddCost(_price[PR_BUILD_CANAL]);
00371   }
00372 
00373   if (cost.GetCost() == 0) {
00374     return_cmd_error(STR_ERROR_ALREADY_BUILT);
00375   } else {
00376     return cost;
00377   }
00378 }
00379 
00380 static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
00381 {
00382   switch (GetWaterTileType(tile)) {
00383     case WATER_TILE_CLEAR: {
00384       if (flags & DC_NO_WATER) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
00385 
00386       Money base_cost = IsCanal(tile) ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER];
00387       /* Make sure freeform edges are allowed or it's not an edge tile. */
00388       if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(tile), 1, MapMaxX() - 1) ||
00389           !IsInsideMM(TileY(tile), 1, MapMaxY() - 1))) {
00390         return_cmd_error(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
00391       }
00392 
00393       /* Make sure no vehicle is on the tile */
00394       CommandCost ret = EnsureNoVehicleOnGround(tile);
00395       if (ret.Failed()) return ret;
00396 
00397       if (GetTileOwner(tile) != OWNER_WATER && GetTileOwner(tile) != OWNER_NONE) {
00398         CommandCost ret = CheckTileOwnership(tile);
00399         if (ret.Failed()) return ret;
00400       }
00401 
00402       if (flags & DC_EXEC) {
00403         DoClearSquare(tile);
00404         MarkCanalsAndRiversAroundDirty(tile);
00405       }
00406 
00407       return CommandCost(EXPENSES_CONSTRUCTION, base_cost);
00408     }
00409 
00410     case WATER_TILE_COAST: {
00411       Slope slope = GetTileSlope(tile, NULL);
00412 
00413       /* Make sure no vehicle is on the tile */
00414       CommandCost ret = EnsureNoVehicleOnGround(tile);
00415       if (ret.Failed()) return ret;
00416 
00417       if (flags & DC_EXEC) {
00418         DoClearSquare(tile);
00419         MarkCanalsAndRiversAroundDirty(tile);
00420       }
00421       if (IsSlopeWithOneCornerRaised(slope)) {
00422         return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WATER]);
00423       } else {
00424         return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROUGH]);
00425       }
00426     }
00427 
00428     case WATER_TILE_LOCK: {
00429       static const TileIndexDiffC _lock_tomiddle_offs[] = {
00430         { 0,  0}, {0,  0}, { 0, 0}, {0,  0}, // middle
00431         {-1,  0}, {0,  1}, { 1, 0}, {0, -1}, // lower
00432         { 1,  0}, {0, -1}, {-1, 0}, {0,  1}, // upper
00433       };
00434 
00435       if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
00436       if (_current_company == OWNER_WATER) return CMD_ERROR;
00437       /* move to the middle tile.. */
00438       return RemoveLock(tile + ToTileIndexDiff(_lock_tomiddle_offs[GetSection(tile)]), flags);
00439     }
00440 
00441     case WATER_TILE_DEPOT:
00442       if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
00443       return RemoveShipDepot(tile, flags);
00444 
00445     default:
00446       NOT_REACHED();
00447   }
00448 }
00449 
00458 static bool IsWateredTile(TileIndex tile, Direction from)
00459 {
00460   switch (GetTileType(tile)) {
00461     case MP_WATER:
00462       switch (GetWaterTileType(tile)) {
00463         default: NOT_REACHED();
00464         case WATER_TILE_DEPOT: case WATER_TILE_CLEAR: return true;
00465         case WATER_TILE_LOCK: return DiagDirToAxis(GetLockDirection(tile)) == DiagDirToAxis(DirToDiagDir(from));
00466 
00467         case WATER_TILE_COAST:
00468           switch (GetTileSlope(tile, NULL)) {
00469             case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
00470             case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
00471             case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
00472             case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
00473             default: return false;
00474           }
00475       }
00476 
00477     case MP_RAILWAY:
00478       if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
00479         assert(IsPlainRail(tile));
00480         switch (GetTileSlope(tile, NULL)) {
00481           case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
00482           case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
00483           case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
00484           case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
00485           default: return false;
00486         }
00487       }
00488       return false;
00489 
00490     case MP_STATION:
00491       if (IsOilRig(tile)) {
00492         /* Do not draw waterborders inside of industries.
00493          * Note: There is no easy way to detect the industry of an oilrig tile. */
00494         TileIndex src_tile = tile + TileOffsByDir(from);
00495         if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
00496             (IsTileType(src_tile, MP_INDUSTRY))) return true;
00497 
00498         return IsTileOnWater(tile);
00499       }
00500       return (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsBuoy(tile);
00501 
00502     case MP_INDUSTRY: {
00503       /* Do not draw waterborders inside of industries.
00504        * Note: There is no easy way to detect the industry of an oilrig tile. */
00505       TileIndex src_tile = tile + TileOffsByDir(from);
00506       if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
00507           (IsTileType(src_tile, MP_INDUSTRY) && GetIndustryIndex(src_tile) == GetIndustryIndex(tile))) return true;
00508 
00509       return IsTileOnWater(tile);
00510     }
00511 
00512     case MP_OBJECT: return IsTileOnWater(tile);
00513 
00514     case MP_TUNNELBRIDGE: return GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER && ReverseDiagDir(GetTunnelBridgeDirection(tile)) == DirToDiagDir(from);
00515 
00516     default:          return false;
00517   }
00518 }
00519 
00527 static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
00528 {
00529   if (base != SPR_FLAT_WATER_TILE) {
00530     /* Only call offset callback if the sprite is NewGRF-provided. */
00531     offset = GetCanalSpriteOffset(feature, tile, offset);
00532   }
00533   DrawGroundSprite(base + offset, PAL_NONE);
00534 }
00535 
00542 static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
00543 {
00544   CanalFeature feature;
00545   SpriteID base = 0;
00546   if (canal) {
00547     feature = CF_DIKES;
00548     base = GetCanalSprite(CF_DIKES, tile);
00549     if (base == 0) base = SPR_CANAL_DIKES_BASE;
00550   } else {
00551     feature = CF_RIVER_EDGE;
00552     base = GetCanalSprite(CF_RIVER_EDGE, tile);
00553     if (base == 0) return; // Don't draw if no sprites provided.
00554   }
00555 
00556   uint wa;
00557 
00558   /* determine the edges around with water. */
00559   wa  = IsWateredTile(TILE_ADDXY(tile, -1,  0), DIR_SW) << 0;
00560   wa += IsWateredTile(TILE_ADDXY(tile,  0,  1), DIR_NW) << 1;
00561   wa += IsWateredTile(TILE_ADDXY(tile,  1,  0), DIR_NE) << 2;
00562   wa += IsWateredTile(TILE_ADDXY(tile,  0, -1), DIR_SE) << 3;
00563 
00564   if (!(wa & 1)) DrawWaterSprite(base, offset,     feature, tile);
00565   if (!(wa & 2)) DrawWaterSprite(base, offset + 1, feature, tile);
00566   if (!(wa & 4)) DrawWaterSprite(base, offset + 2, feature, tile);
00567   if (!(wa & 8)) DrawWaterSprite(base, offset + 3, feature, tile);
00568 
00569   /* right corner */
00570   switch (wa & 0x03) {
00571     case 0: DrawWaterSprite(base, offset + 4, feature, tile); break;
00572     case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1), DIR_W)) DrawWaterSprite(base, offset + 8, feature, tile); break;
00573   }
00574 
00575   /* bottom corner */
00576   switch (wa & 0x06) {
00577     case 0: DrawWaterSprite(base, offset + 5, feature, tile); break;
00578     case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1), DIR_N)) DrawWaterSprite(base, offset + 9, feature, tile); break;
00579   }
00580 
00581   /* left corner */
00582   switch (wa & 0x0C) {
00583     case  0: DrawWaterSprite(base, offset + 6, feature, tile); break;
00584     case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1), DIR_E)) DrawWaterSprite(base, offset + 10, feature, tile); break;
00585   }
00586 
00587   /* upper corner */
00588   switch (wa & 0x09) {
00589     case 0: DrawWaterSprite(base, offset + 7, feature, tile); break;
00590     case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawWaterSprite(base, offset + 11, feature, tile); break;
00591   }
00592 }
00593 
00595 static void DrawSeaWater(TileIndex tile)
00596 {
00597   DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
00598 }
00599 
00601 static void DrawCanalWater(TileIndex tile)
00602 {
00603   SpriteID image = SPR_FLAT_WATER_TILE;
00604   if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00605     /* First water slope sprite is flat water. */
00606     image = GetCanalSprite(CF_WATERSLOPE, tile);
00607     if (image == 0) image = SPR_FLAT_WATER_TILE;
00608   }
00609   DrawWaterSprite(image, 0, CF_WATERSLOPE, tile);
00610 
00611   DrawWaterEdges(true, 0, tile);
00612 }
00613 
00614 #include "table/water_land.h"
00615 
00625 static void DrawWaterTileStruct(const TileInfo *ti, const DrawTileSeqStruct *dtss, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
00626 {
00627   /* Don't draw if buildings are invisible. */
00628   if (IsInvisibilitySet(TO_BUILDINGS)) return;
00629 
00630   for (; !dtss->IsTerminator(); dtss++) {
00631     uint tile_offs = offset + dtss->image.sprite;
00632     if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
00633     AddSortableSpriteToDraw(base + tile_offs, palette,
00634       ti->x + dtss->delta_x, ti->y + dtss->delta_y,
00635       dtss->size_x, dtss->size_y,
00636       dtss->size_z, ti->z + dtss->delta_z,
00637       IsTransparencySet(TO_BUILDINGS));
00638   }
00639 }
00640 
00642 static void DrawWaterLock(const TileInfo *ti)
00643 {
00644   int section = GetSection(ti->tile);
00645   const DrawTileSprites &dts = _lock_display_data[section];
00646 
00647   /* Draw ground sprite. */
00648   SpriteID image = dts.ground.sprite;
00649 
00650   SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile);
00651   if (water_base == 0) {
00652     /* Use default sprites. */
00653     water_base = SPR_CANALS_BASE;
00654   } else if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00655     /* NewGRF supplies a flat sprite as first sprite. */
00656     if (image == SPR_FLAT_WATER_TILE) {
00657       image = water_base;
00658     } else {
00659       image++;
00660     }
00661   }
00662 
00663   if (image < 5) image += water_base;
00664   DrawGroundSprite(image, PAL_NONE);
00665 
00666   /* Draw structures. */
00667   uint     zoffs = 0;
00668   SpriteID base  = GetCanalSprite(CF_LOCKS, ti->tile);
00669 
00670   if (base == 0) {
00671     /* If no custom graphics, use defaults. */
00672     base = SPR_LOCK_BASE;
00673     uint8 z_threshold = section >= 8 ? 8 : 0;
00674     zoffs = ti->z > z_threshold ? 24 : 0;
00675   }
00676 
00677   DrawWaterTileStruct(ti, dts.seq, base, zoffs, PAL_NONE, CF_LOCKS);
00678 }
00679 
00681 static void DrawWaterDepot(const TileInfo *ti)
00682 {
00683   DrawWaterClassGround(ti);
00684   DrawWaterTileStruct(ti, _shipdepot_display_data[GetSection(ti->tile)].seq, 0, 0, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)), CF_END);
00685 }
00686 
00687 static void DrawRiverWater(const TileInfo *ti)
00688 {
00689   SpriteID image = SPR_FLAT_WATER_TILE;
00690   uint     offset = 0;
00691   uint     edges_offset = 0;
00692 
00693   if (ti->tileh != SLOPE_FLAT || HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
00694     image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
00695     if (image == 0) {
00696       switch (ti->tileh) {
00697         case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
00698         case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP;   break;
00699         case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP;   break;
00700         case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
00701         default:       image = SPR_FLAT_WATER_TILE;    break;
00702       }
00703     } else {
00704       /* Flag bit 0 indicates that the first sprite is flat water. */
00705       offset = HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE) ? 1 : 0;
00706 
00707       switch (ti->tileh) {
00708         case SLOPE_SE:              edges_offset += 12; break;
00709         case SLOPE_NE: offset += 1; edges_offset += 24; break;
00710         case SLOPE_SW: offset += 2; edges_offset += 36; break;
00711         case SLOPE_NW: offset += 3; edges_offset += 48; break;
00712         default:       offset  = 0; break;
00713       }
00714 
00715       offset = GetCanalSpriteOffset(CF_RIVER_SLOPE, ti->tile, offset);
00716     }
00717   }
00718 
00719   DrawGroundSprite(image + offset, PAL_NONE);
00720 
00721   /* Draw river edges if available. */
00722   DrawWaterEdges(false, edges_offset, ti->tile);
00723 }
00724 
00725 void DrawShoreTile(Slope tileh)
00726 {
00727   /* Converts the enum Slope into an offset based on SPR_SHORE_BASE.
00728    * This allows to calculate the proper sprite to display for this Slope */
00729   static const byte tileh_to_shoresprite[32] = {
00730     0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
00731     0, 0, 0, 0, 0,  0, 0, 0, 0, 0,  0,  5,  0, 10, 15, 0,
00732   };
00733 
00734   assert(!IsHalftileSlope(tileh)); // Halftile slopes need to get handled earlier.
00735   assert(tileh != SLOPE_FLAT);     // Shore is never flat
00736 
00737   assert((tileh != SLOPE_EW) && (tileh != SLOPE_NS)); // No suitable sprites for current flooding behaviour
00738 
00739   DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[tileh], PAL_NONE);
00740 }
00741 
00742 void DrawWaterClassGround(const TileInfo *ti)
00743 {
00744   switch (GetWaterClass(ti->tile)) {
00745     case WATER_CLASS_SEA:   DrawSeaWater(ti->tile); break;
00746     case WATER_CLASS_CANAL: DrawCanalWater(ti->tile); break;
00747     case WATER_CLASS_RIVER: DrawRiverWater(ti); break;
00748     default: NOT_REACHED();
00749   }
00750 }
00751 
00752 static void DrawTile_Water(TileInfo *ti)
00753 {
00754   switch (GetWaterTileType(ti->tile)) {
00755     case WATER_TILE_CLEAR:
00756       DrawWaterClassGround(ti);
00757       DrawBridgeMiddle(ti);
00758       break;
00759 
00760     case WATER_TILE_COAST: {
00761       DrawShoreTile(ti->tileh);
00762       DrawBridgeMiddle(ti);
00763       break;
00764     }
00765 
00766     case WATER_TILE_LOCK:
00767       DrawWaterLock(ti);
00768       break;
00769 
00770     case WATER_TILE_DEPOT:
00771       DrawWaterDepot(ti);
00772       break;
00773   }
00774 }
00775 
00776 void DrawShipDepotSprite(int x, int y, int image)
00777 {
00778   const DrawTileSprites &dts = _shipdepot_display_data[image];
00779 
00780   DrawSprite(dts.ground.sprite, dts.ground.pal, x, y);
00781   DrawOrigTileSeqInGUI(x, y, &dts, COMPANY_SPRITE_COLOUR(_local_company));
00782 }
00783 
00784 
00785 static uint GetSlopeZ_Water(TileIndex tile, uint x, uint y)
00786 {
00787   uint z;
00788   Slope tileh = GetTileSlope(tile, &z);
00789 
00790   return z + GetPartialZ(x & 0xF, y & 0xF, tileh);
00791 }
00792 
00793 static Foundation GetFoundation_Water(TileIndex tile, Slope tileh)
00794 {
00795   return FOUNDATION_NONE;
00796 }
00797 
00798 static void GetTileDesc_Water(TileIndex tile, TileDesc *td)
00799 {
00800   switch (GetWaterTileType(tile)) {
00801     case WATER_TILE_CLEAR:
00802       switch (GetWaterClass(tile)) {
00803         case WATER_CLASS_SEA:   td->str = STR_LAI_WATER_DESCRIPTION_WATER; break;
00804         case WATER_CLASS_CANAL: td->str = STR_LAI_WATER_DESCRIPTION_CANAL; break;
00805         case WATER_CLASS_RIVER: td->str = STR_LAI_WATER_DESCRIPTION_RIVER; break;
00806         default: NOT_REACHED(); break;
00807       }
00808       break;
00809     case WATER_TILE_COAST: td->str = STR_LAI_WATER_DESCRIPTION_COAST_OR_RIVERBANK; break;
00810     case WATER_TILE_LOCK : td->str = STR_LAI_WATER_DESCRIPTION_LOCK;               break;
00811     case WATER_TILE_DEPOT:
00812       td->str = STR_LAI_WATER_DESCRIPTION_SHIP_DEPOT;
00813       td->build_date = Depot::GetByTile(tile)->build_date;
00814       break;
00815     default: NOT_REACHED(); break;
00816   }
00817 
00818   td->owner[0] = GetTileOwner(tile);
00819 }
00820 
00826 static void FloodVehicle(Vehicle *v)
00827 {
00828   uint pass = v->Crash(true);
00829 
00830   AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_FLOODED));
00831   SetDParam(0, pass);
00832   AddVehicleNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NS_ACCIDENT, v->index);
00833   CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
00834   SndPlayVehicleFx(SND_12_EXPLOSION, v);
00835 }
00836 
00843 static Vehicle *FloodVehicleProc(Vehicle *v, void *data)
00844 {
00845   if ((v->vehstatus & VS_CRASHED) != 0) return NULL;
00846 
00847   switch (v->type) {
00848     default: break;
00849 
00850     case VEH_AIRCRAFT: {
00851       if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
00852       if (v->subtype == AIR_SHADOW) break;
00853 
00854       /* We compare v->z_pos against delta_z + 1 because the shadow
00855        * is at delta_z and the actual aircraft at delta_z + 1. */
00856       const Station *st = Station::GetByTile(v->tile);
00857       const AirportFTAClass *airport = st->airport.GetFTA();
00858       if (v->z_pos != airport->delta_z + 1) break;
00859 
00860       FloodVehicle(v);
00861       break;
00862     }
00863 
00864     case VEH_TRAIN:
00865     case VEH_ROAD: {
00866       byte z = *(byte*)data;
00867       if (v->z_pos > z) break;
00868       FloodVehicle(v->First());
00869       break;
00870     }
00871   }
00872 
00873   return NULL;
00874 }
00875 
00881 static void FloodVehicles(TileIndex tile)
00882 {
00883   byte z = 0;
00884 
00885   if (IsAirportTile(tile)) {
00886     const Station *st = Station::GetByTile(tile);
00887     TILE_AREA_LOOP(tile, st->airport) {
00888       if (st->TileBelongsToAirport(tile)) FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00889     }
00890 
00891     /* No vehicle could be flooded on this airport anymore */
00892     return;
00893   }
00894 
00895   if (!IsBridgeTile(tile)) {
00896     FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00897     return;
00898   }
00899 
00900   TileIndex end = GetOtherBridgeEnd(tile);
00901   z = GetBridgeHeight(tile);
00902 
00903   FindVehicleOnPos(tile, &z, &FloodVehicleProc);
00904   FindVehicleOnPos(end, &z, &FloodVehicleProc);
00905 }
00906 
00912 FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
00913 {
00914   /* FLOOD_ACTIVE:  'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile, sea-water-industries, sea-oilrigs
00915    * FLOOD_DRYUP:   coast with more than one corner raised, coast with rail-track, coast with trees
00916    * FLOOD_PASSIVE: (not used)
00917    * FLOOD_NONE:    canals, rivers, everything else
00918    */
00919   switch (GetTileType(tile)) {
00920     case MP_WATER:
00921       if (IsCoast(tile)) {
00922         Slope tileh = GetTileSlope(tile, NULL);
00923         return (IsSlopeWithOneCornerRaised(tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
00924       }
00925       /* FALL THROUGH */
00926     case MP_STATION:
00927     case MP_INDUSTRY:
00928     case MP_OBJECT:
00929       return (GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE;
00930 
00931     case MP_RAILWAY:
00932       if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
00933         return (IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL)) ? FLOOD_ACTIVE : FLOOD_DRYUP);
00934       }
00935       return FLOOD_NONE;
00936 
00937     case MP_TREES:
00938       return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
00939 
00940     default:
00941       return FLOOD_NONE;
00942   }
00943 }
00944 
00948 void DoFloodTile(TileIndex target)
00949 {
00950   assert(!IsTileType(target, MP_WATER));
00951 
00952   bool flooded = false; // Will be set to true if something is changed.
00953 
00954   Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
00955 
00956   Slope tileh = GetTileSlope(target, NULL);
00957   if (tileh != SLOPE_FLAT) {
00958     /* make coast.. */
00959     switch (GetTileType(target)) {
00960       case MP_RAILWAY: {
00961         if (!IsPlainRail(target)) break;
00962         FloodVehicles(target);
00963         flooded = FloodHalftile(target);
00964         break;
00965       }
00966 
00967       case MP_TREES:
00968         if (!IsSlopeWithOneCornerRaised(tileh)) {
00969           SetTreeGroundDensity(target, TREE_GROUND_SHORE, 3);
00970           MarkTileDirtyByTile(target);
00971           flooded = true;
00972           break;
00973         }
00974         /* FALL THROUGH */
00975 
00976       case MP_CLEAR:
00977         if (DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
00978           MakeShore(target);
00979           MarkTileDirtyByTile(target);
00980           flooded = true;
00981         }
00982         break;
00983 
00984       default:
00985         break;
00986     }
00987   } else {
00988     /* Flood vehicles */
00989     FloodVehicles(target);
00990 
00991     /* flood flat tile */
00992     if (DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
00993       MakeSea(target);
00994       MarkTileDirtyByTile(target);
00995       flooded = true;
00996     }
00997   }
00998 
00999   if (flooded) {
01000     /* Mark surrounding canal tiles dirty too to avoid glitches */
01001     MarkCanalsAndRiversAroundDirty(target);
01002 
01003     /* update signals if needed */
01004     UpdateSignalsInBuffer();
01005   }
01006 
01007   cur_company.Restore();
01008 }
01009 
01013 static void DoDryUp(TileIndex tile)
01014 {
01015   Backup<CompanyByte> cur_company(_current_company, OWNER_WATER, FILE_LINE);
01016 
01017   switch (GetTileType(tile)) {
01018     case MP_RAILWAY:
01019       assert(IsPlainRail(tile));
01020       assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
01021 
01022       RailGroundType new_ground;
01023       switch (GetTrackBits(tile)) {
01024         case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
01025         case TRACK_BIT_LOWER: new_ground = RAIL_GROUND_FENCE_HORIZ2; break;
01026         case TRACK_BIT_LEFT:  new_ground = RAIL_GROUND_FENCE_VERT1;  break;
01027         case TRACK_BIT_RIGHT: new_ground = RAIL_GROUND_FENCE_VERT2;  break;
01028         default: NOT_REACHED();
01029       }
01030       SetRailGroundType(tile, new_ground);
01031       MarkTileDirtyByTile(tile);
01032       break;
01033 
01034     case MP_TREES:
01035       SetTreeGroundDensity(tile, TREE_GROUND_GRASS, 3);
01036       MarkTileDirtyByTile(tile);
01037       break;
01038 
01039     case MP_WATER:
01040       assert(IsCoast(tile));
01041 
01042       if (DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR).Succeeded()) {
01043         MakeClear(tile, CLEAR_GRASS, 3);
01044         MarkTileDirtyByTile(tile);
01045       }
01046       break;
01047 
01048     default: NOT_REACHED();
01049   }
01050 
01051   cur_company.Restore();
01052 }
01053 
01060 void TileLoop_Water(TileIndex tile)
01061 {
01062   switch (GetFloodingBehaviour(tile)) {
01063     case FLOOD_ACTIVE:
01064       for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
01065         TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir(dir));
01066         if (dest == INVALID_TILE) continue;
01067         /* do not try to flood water tiles - increases performance a lot */
01068         if (IsTileType(dest, MP_WATER)) continue;
01069 
01070         uint z_dest;
01071         Slope slope_dest = GetFoundationSlope(dest, &z_dest) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
01072         if (z_dest > 0) continue;
01073 
01074         if (!HasBit(_flood_from_dirs[slope_dest], ReverseDir(dir))) continue;
01075 
01076         DoFloodTile(dest);
01077       }
01078       break;
01079 
01080     case FLOOD_DRYUP: {
01081       Slope slope_here = GetFoundationSlope(tile, NULL) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
01082       uint dir;
01083       FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope_here]) {
01084         TileIndex dest = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir((Direction)dir));
01085         if (dest == INVALID_TILE) continue;
01086 
01087         FloodingBehaviour dest_behaviour = GetFloodingBehaviour(dest);
01088         if ((dest_behaviour == FLOOD_ACTIVE) || (dest_behaviour == FLOOD_PASSIVE)) return;
01089       }
01090       DoDryUp(tile);
01091       break;
01092     }
01093 
01094     default: return;
01095   }
01096 }
01097 
01098 void ConvertGroundTilesIntoWaterTiles()
01099 {
01100   uint z;
01101 
01102   for (TileIndex tile = 0; tile < MapSize(); ++tile) {
01103     Slope slope = GetTileSlope(tile, &z);
01104     if (IsTileType(tile, MP_CLEAR) && z == 0) {
01105       /* Make both water for tiles at level 0
01106        * and make shore, as that looks much better
01107        * during the generation. */
01108       switch (slope) {
01109         case SLOPE_FLAT:
01110           MakeSea(tile);
01111           break;
01112 
01113         case SLOPE_N:
01114         case SLOPE_E:
01115         case SLOPE_S:
01116         case SLOPE_W:
01117           MakeShore(tile);
01118           break;
01119 
01120         default:
01121           uint dir;
01122           FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope & ~SLOPE_STEEP]) {
01123             TileIndex dest = TILE_ADD(tile, TileOffsByDir((Direction)dir));
01124             Slope slope_dest = GetTileSlope(dest, NULL) & ~SLOPE_STEEP;
01125             if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) {
01126               MakeShore(tile);
01127               break;
01128             }
01129           }
01130           break;
01131       }
01132     }
01133   }
01134 }
01135 
01136 static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
01137 {
01138   static const byte coast_tracks[] = {0, 32, 4, 0, 16, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0};
01139 
01140   TrackBits ts;
01141 
01142   if (mode != TRANSPORT_WATER) return 0;
01143 
01144   switch (GetWaterTileType(tile)) {
01145     case WATER_TILE_CLEAR: ts = (GetTileSlope(tile, NULL) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
01146     case WATER_TILE_COAST: ts = (TrackBits)coast_tracks[GetTileSlope(tile, NULL) & 0xF]; break;
01147     case WATER_TILE_LOCK:  ts = DiagDirToDiagTrackBits(GetLockDirection(tile)); break;
01148     case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
01149     default: return 0;
01150   }
01151   if (TileX(tile) == 0) {
01152     /* NE border: remove tracks that connects NE tile edge */
01153     ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
01154   }
01155   if (TileY(tile) == 0) {
01156     /* NW border: remove tracks that connects NW tile edge */
01157     ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
01158   }
01159   return CombineTrackStatus(TrackBitsToTrackdirBits(ts), TRACKDIR_BIT_NONE);
01160 }
01161 
01162 static bool ClickTile_Water(TileIndex tile)
01163 {
01164   if (GetWaterTileType(tile) == WATER_TILE_DEPOT) {
01165     ShowDepotWindow(GetShipDepotNorthTile(tile), VEH_SHIP);
01166     return true;
01167   }
01168   return false;
01169 }
01170 
01171 static void ChangeTileOwner_Water(TileIndex tile, Owner old_owner, Owner new_owner)
01172 {
01173   if (!IsTileOwner(tile, old_owner)) return;
01174 
01175   if (new_owner != INVALID_OWNER) {
01176     SetTileOwner(tile, new_owner);
01177     return;
01178   }
01179 
01180   /* Remove depot */
01181   if (IsShipDepot(tile)) DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
01182 
01183   /* Set owner of canals and locks ... and also canal under dock there was before.
01184    * Check if the new owner after removing depot isn't OWNER_WATER. */
01185   if (IsTileOwner(tile, old_owner)) SetTileOwner(tile, OWNER_NONE);
01186 }
01187 
01188 static VehicleEnterTileStatus VehicleEnter_Water(Vehicle *v, TileIndex tile, int x, int y)
01189 {
01190   return VETSB_CONTINUE;
01191 }
01192 
01193 static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
01194 {
01195   /* Canals can't be terraformed */
01196   if (IsWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
01197 
01198   return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
01199 }
01200 
01201 
01202 extern const TileTypeProcs _tile_type_water_procs = {
01203   DrawTile_Water,           // draw_tile_proc
01204   GetSlopeZ_Water,          // get_slope_z_proc
01205   ClearTile_Water,          // clear_tile_proc
01206   NULL,                     // add_accepted_cargo_proc
01207   GetTileDesc_Water,        // get_tile_desc_proc
01208   GetTileTrackStatus_Water, // get_tile_track_status_proc
01209   ClickTile_Water,          // click_tile_proc
01210   NULL,                     // animate_tile_proc
01211   TileLoop_Water,           // tile_loop_clear
01212   ChangeTileOwner_Water,    // change_tile_owner_clear
01213   NULL,                     // add_produced_cargo_proc
01214   VehicleEnter_Water,       // vehicle_enter_tile_proc
01215   GetFoundation_Water,      // get_foundation_proc
01216   TerraformTile_Water,      // terraform_tile_proc
01217 };

Generated on Fri Jun 3 05:19:01 2011 for OpenTTD by  doxygen 1.6.1