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 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 -= 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, NT_ACCIDENT, v->index);
00917 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
00918 if (_settings_client.sound.disaster) 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 bool is_lock_middle = IsLock(tile) && GetLockPart(tile) == LOCK_PART_MIDDLE;
01262
01263
01264 if (is_lock_middle) Company::Get(old_owner)->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR;
01265 if (new_owner != INVALID_OWNER) {
01266 if (is_lock_middle) Company::Get(new_owner)->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR;
01267
01268
01269 if (GetWaterClass(tile) == WATER_CLASS_CANAL && !is_lock_middle) {
01270 Company::Get(old_owner)->infrastructure.water--;
01271 Company::Get(new_owner)->infrastructure.water++;
01272 }
01273 if (IsShipDepot(tile)) {
01274 Company::Get(old_owner)->infrastructure.water -= LOCK_DEPOT_TILE_FACTOR;
01275 Company::Get(new_owner)->infrastructure.water += LOCK_DEPOT_TILE_FACTOR;
01276 }
01277
01278 SetTileOwner(tile, new_owner);
01279 return;
01280 }
01281
01282
01283 if (IsShipDepot(tile)) DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
01284
01285
01286
01287 if (IsTileOwner(tile, old_owner)) {
01288 if (GetWaterClass(tile) == WATER_CLASS_CANAL && !is_lock_middle) Company::Get(old_owner)->infrastructure.water--;
01289 SetTileOwner(tile, OWNER_NONE);
01290 }
01291 }
01292
01293 static VehicleEnterTileStatus VehicleEnter_Water(Vehicle *v, TileIndex tile, int x, int y)
01294 {
01295 return VETSB_CONTINUE;
01296 }
01297
01298 static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
01299 {
01300
01301 if (IsWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
01302
01303 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
01304 }
01305
01306
01307 extern const TileTypeProcs _tile_type_water_procs = {
01308 DrawTile_Water,
01309 GetSlopePixelZ_Water,
01310 ClearTile_Water,
01311 NULL,
01312 GetTileDesc_Water,
01313 GetTileTrackStatus_Water,
01314 ClickTile_Water,
01315 NULL,
01316 TileLoop_Water,
01317 ChangeTileOwner_Water,
01318 NULL,
01319 VehicleEnter_Water,
01320 GetFoundation_Water,
01321 TerraformTile_Water,
01322 };