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