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