src/water_cmd.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6870 ca3fd1fbe311
child 6872 1c4a4a609f85
equal deleted inserted replaced
6870:ca3fd1fbe311 6871:5a9dc001e1ad
    28 #include "water_map.h"
    28 #include "water_map.h"
    29 #include "industry_map.h"
    29 #include "industry_map.h"
    30 #include "newgrf.h"
    30 #include "newgrf.h"
    31 #include "newgrf_canal.h"
    31 #include "newgrf_canal.h"
    32 #include "misc/autoptr.hpp"
    32 #include "misc/autoptr.hpp"
    33 
    33 #include "transparency.h"
       
    34 
       
    35 /** Array for the shore sprites */
    34 static const SpriteID _water_shore_sprites[] = {
    36 static const SpriteID _water_shore_sprites[] = {
    35 	0,
    37 	0,
    36 	SPR_SHORE_TILEH_1,
    38 	SPR_SHORE_TILEH_1,  // SLOPE_W
    37 	SPR_SHORE_TILEH_2,
    39 	SPR_SHORE_TILEH_2,  // SLOPE_S
    38 	SPR_SHORE_TILEH_3,
    40 	SPR_SHORE_TILEH_3,  // SLOPE_SW
    39 	SPR_SHORE_TILEH_4,
    41 	SPR_SHORE_TILEH_4,  // SLOPE_E
    40 	0,
    42 	0,
    41 	SPR_SHORE_TILEH_6,
    43 	SPR_SHORE_TILEH_6,  // SLOPE_SE
    42 	0,
    44 	0,
    43 	SPR_SHORE_TILEH_8,
    45 	SPR_SHORE_TILEH_8,  // SLOPE_N
    44 	SPR_SHORE_TILEH_9,
    46 	SPR_SHORE_TILEH_9,  // SLOPE_NW
    45 	0,
    47 	0,
    46 	0,
    48 	0,
    47 	SPR_SHORE_TILEH_12,
    49 	SPR_SHORE_TILEH_12, // SLOPE_NE
    48 	0,
    50 	0,
    49 	0
    51 	0
    50 };
    52 };
    51 
    53 
    52 
    54 
    53 static Vehicle *FindFloodableVehicleOnTile(TileIndex tile);
    55 static Vehicle *FindFloodableVehicleOnTile(TileIndex tile);
    54 static void FloodVehicle(Vehicle *v);
    56 static void FloodVehicle(Vehicle *v);
       
    57 
       
    58 /**
       
    59  * Makes a tile canal or water depending on the surroundings.
       
    60  * This as for example docks and shipdepots do not store
       
    61  * whether the tile used to be canal or 'normal' water.
       
    62  * @param t the tile to change.
       
    63  * @param o the owner of the new tile.
       
    64  */
       
    65 void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o)
       
    66 {
       
    67 	assert(GetTileSlope(t, NULL) == SLOPE_FLAT);
       
    68 
       
    69 	/* Non-sealevel -> canal */
       
    70 	if (TileHeight(t) != 0) {
       
    71 		MakeCanal(t, o);
       
    72 		return;
       
    73 	}
       
    74 
       
    75 	bool has_water = false;
       
    76 	bool has_canal = false;
       
    77 
       
    78 	for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
       
    79 		TileIndex neighbour = TileAddByDiagDir(t, dir);
       
    80 		if (IsTileType(neighbour, MP_WATER)) {
       
    81 			has_water |= IsSea(neighbour) || IsCoast(neighbour);
       
    82 			has_canal |= IsCanal(neighbour);
       
    83 		}
       
    84 	}
       
    85 	if (has_canal || !has_water) {
       
    86 		MakeCanal(t, o);
       
    87 	} else {
       
    88 		MakeWater(t);
       
    89 	}
       
    90 	MarkTileDirtyByTile(t);
       
    91 }
       
    92 
    55 
    93 
    56 /** Build a ship depot.
    94 /** Build a ship depot.
    57  * @param tile tile where ship depot is built
    95  * @param tile tile where ship depot is built
    58  * @param flags type of operation
    96  * @param flags type of operation
    59  * @param p1 bit 0 depot orientation (Axis)
    97  * @param p1 bit 0 depot orientation (Axis)
    69 
   107 
    70 	Axis axis = Extract<Axis, 0>(p1);
   108 	Axis axis = Extract<Axis, 0>(p1);
    71 
   109 
    72 	tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
   110 	tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
    73 
   111 
    74 	if (!IsClearWaterTile(tile) || !IsClearWaterTile(tile2))
   112 	if (!IsWaterTile(tile) || !IsWaterTile(tile2))
    75 		return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
   113 		return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
    76 
   114 
    77 	if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   115 	if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
    78 
   116 
    79 	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   117 	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   102 {
   140 {
   103 	TileIndex tile2;
   141 	TileIndex tile2;
   104 
   142 
   105 	if (!IsShipDepot(tile)) return CMD_ERROR;
   143 	if (!IsShipDepot(tile)) return CMD_ERROR;
   106 	if (!CheckTileOwnership(tile)) return CMD_ERROR;
   144 	if (!CheckTileOwnership(tile)) return CMD_ERROR;
   107 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
   145 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   108 
   146 
   109 	tile2 = GetOtherShipDepotTile(tile);
   147 	tile2 = GetOtherShipDepotTile(tile);
   110 
   148 
   111 	if (!EnsureNoVehicle(tile2)) return CMD_ERROR;
   149 	if (!EnsureNoVehicleOnGround(tile2)) return CMD_ERROR;
   112 
   150 
   113 	if (flags & DC_EXEC) {
   151 	if (flags & DC_EXEC) {
   114 		/* Kill the depot, which is registered at the northernmost tile. Use that one */
   152 		/* Kill the depot, which is registered at the northernmost tile. Use that one */
   115 		delete GetDepotByTile(tile2 < tile ? tile2 : tile);
   153 		delete GetDepotByTile(tile2 < tile ? tile2 : tile);
   116 
   154 
   169 	TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile));
   207 	TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile));
   170 
   208 
   171 	if (!CheckTileOwnership(tile) && GetTileOwner(tile) != OWNER_NONE) return CMD_ERROR;
   209 	if (!CheckTileOwnership(tile) && GetTileOwner(tile) != OWNER_NONE) return CMD_ERROR;
   172 
   210 
   173 	/* make sure no vehicle is on the tile. */
   211 	/* make sure no vehicle is on the tile. */
   174 	if (!EnsureNoVehicle(tile) || !EnsureNoVehicle(tile + delta) || !EnsureNoVehicle(tile - delta))
   212 	if (!EnsureNoVehicleOnGround(tile) || !EnsureNoVehicleOnGround(tile + delta) || !EnsureNoVehicleOnGround(tile - delta))
   175 		return CMD_ERROR;
   213 		return CMD_ERROR;
   176 
   214 
   177 	if (flags & DC_EXEC) {
   215 	if (flags & DC_EXEC) {
   178 		DoClearSquare(tile);
   216 		DoClearSquare(tile);
   179 		DoClearSquare(tile + delta);
   217 		MakeWaterOrCanalDependingOnSurroundings(tile + delta, _current_player);
   180 		DoClearSquare(tile - delta);
   218 		MakeWaterOrCanalDependingOnSurroundings(tile - delta, _current_player);
   181 	}
   219 	}
   182 
   220 
   183 	return CommandCost(_price.clear_water * 2);
   221 	return CommandCost(_price.clear_water * 2);
   184 }
   222 }
   185 
   223 
   236 	int y;
   274 	int y;
   237 	int sx, sy;
   275 	int sx, sy;
   238 
   276 
   239 	if (p1 >= MapSize()) return CMD_ERROR;
   277 	if (p1 >= MapSize()) return CMD_ERROR;
   240 	/* Outside of the editor you can only build canals, not oceans */
   278 	/* Outside of the editor you can only build canals, not oceans */
   241 	if (HASBIT(p2, 0) && _game_mode != GM_EDITOR) return CMD_ERROR;
   279 	if (HasBit(p2, 0) && _game_mode != GM_EDITOR) return CMD_ERROR;
   242 
   280 
   243 	x = TileX(tile);
   281 	x = TileX(tile);
   244 	y = TileY(tile);
   282 	y = TileY(tile);
   245 	sx = TileX(p1);
   283 	sx = TileX(p1);
   246 	sy = TileY(p1);
   284 	sy = TileY(p1);
   261 		if (GetTileSlope(tile, NULL) != SLOPE_FLAT) {
   299 		if (GetTileSlope(tile, NULL) != SLOPE_FLAT) {
   262 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   300 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   263 		}
   301 		}
   264 
   302 
   265 		/* can't make water of water! */
   303 		/* can't make water of water! */
   266 		if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || HASBIT(p2, 0))) continue;
   304 		if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || HasBit(p2, 0))) continue;
   267 
   305 
   268 		ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   306 		ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   269 		if (CmdFailed(ret)) return ret;
   307 		if (CmdFailed(ret)) return ret;
   270 		cost.AddCost(ret);
   308 		cost.AddCost(ret);
   271 
   309 
   272 		if (flags & DC_EXEC) {
   310 		if (flags & DC_EXEC) {
   273 			if (TileHeight(tile) == 0 && HASBIT(p2, 0)) {
   311 			if (TileHeight(tile) == 0 && HasBit(p2, 0)) {
   274 				MakeWater(tile);
   312 				MakeWater(tile);
   275 			} else {
   313 			} else {
   276 				MakeCanal(tile, _current_player);
   314 				MakeCanal(tile, _current_player);
   277 			}
   315 			}
   278 			MarkTileDirtyByTile(tile);
   316 			MarkTileDirtyByTile(tile);
   294 	switch (GetWaterTileType(tile)) {
   332 	switch (GetWaterTileType(tile)) {
   295 		case WATER_TILE_CLEAR:
   333 		case WATER_TILE_CLEAR:
   296 			if (flags & DC_NO_WATER) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
   334 			if (flags & DC_NO_WATER) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
   297 
   335 
   298 			/* Make sure it's not an edge tile. */
   336 			/* Make sure it's not an edge tile. */
   299 			if (!IS_INT_INSIDE(TileX(tile), 1, MapMaxX() - 1) ||
   337 			if (!IsInsideMM(TileX(tile), 1, MapMaxX() - 1) ||
   300 					!IS_INT_INSIDE(TileY(tile), 1, MapMaxY() - 1)) {
   338 					!IsInsideMM(TileY(tile), 1, MapMaxY() - 1)) {
   301 				return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP);
   339 				return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP);
   302 			}
   340 			}
   303 
   341 
   304 			/* Make sure no vehicle is on the tile */
   342 			/* Make sure no vehicle is on the tile */
   305 			if (!EnsureNoVehicle(tile)) return CMD_ERROR;
   343 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   306 
   344 
   307 			if (GetTileOwner(tile) != OWNER_WATER && GetTileOwner(tile) != OWNER_NONE && !CheckTileOwnership(tile)) return CMD_ERROR;
   345 			if (GetTileOwner(tile) != OWNER_WATER && GetTileOwner(tile) != OWNER_NONE && !CheckTileOwnership(tile)) return CMD_ERROR;
   308 
   346 
   309 			if (flags & DC_EXEC) DoClearSquare(tile);
   347 			if (flags & DC_EXEC) DoClearSquare(tile);
   310 			return CommandCost(_price.clear_water);
   348 			return CommandCost(_price.clear_water);
   311 
   349 
   312 		case WATER_TILE_COAST: {
   350 		case WATER_TILE_COAST: {
   313 			Slope slope = GetTileSlope(tile, NULL);
   351 			Slope slope = GetTileSlope(tile, NULL);
   314 
   352 
   315 			/* Make sure no vehicle is on the tile */
   353 			/* Make sure no vehicle is on the tile */
   316 			if (!EnsureNoVehicle(tile)) return CMD_ERROR;
   354 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
   317 
   355 
   318 			if (flags & DC_EXEC) DoClearSquare(tile);
   356 			if (flags & DC_EXEC) DoClearSquare(tile);
   319 			if (slope == SLOPE_N || slope == SLOPE_E || slope == SLOPE_S || slope == SLOPE_W) {
   357 			if (slope == SLOPE_N || slope == SLOPE_E || slope == SLOPE_S || slope == SLOPE_W) {
   320 				return CommandCost(_price.clear_water);
   358 				return CommandCost(_price.clear_water);
   321 			} else {
   359 			} else {
   322 				return CommandCost(_price.purchase_land);
   360 				return CommandCost(_price.clear_roughland);
   323 			}
   361 			}
   324 		}
   362 		}
   325 
   363 
   326 		case WATER_TILE_LOCK: {
   364 		case WATER_TILE_LOCK: {
   327 			static const TileIndexDiffC _shiplift_tomiddle_offs[] = {
   365 			static const TileIndexDiffC _shiplift_tomiddle_offs[] = {
   374 {
   412 {
   375 	uint wa;
   413 	uint wa;
   376 
   414 
   377 	/* Test for custom graphics, else use the default */
   415 	/* Test for custom graphics, else use the default */
   378 	SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile);
   416 	SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile);
   379 	if (dikes_base == 0) dikes_base = SPR_CANALS_BASE + 57;
   417 	if (dikes_base == 0) dikes_base = SPR_CANAL_DIKES_BASE;
   380 
   418 
   381 	/* determine the edges around with water. */
   419 	/* determine the edges around with water. */
   382 	wa  = IsWateredTile(TILE_ADDXY(tile, -1,  0)) << 0;
   420 	wa  = IsWateredTile(TILE_ADDXY(tile, -1,  0)) << 0;
   383 	wa += IsWateredTile(TILE_ADDXY(tile,  0,  1)) << 1;
   421 	wa += IsWateredTile(TILE_ADDXY(tile,  0,  1)) << 1;
   384 	wa += IsWateredTile(TILE_ADDXY(tile,  1,  0)) << 2;
   422 	wa += IsWateredTile(TILE_ADDXY(tile,  1,  0)) << 2;
   429 	SpriteID image;
   467 	SpriteID image;
   430 	SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile);
   468 	SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile);
   431 	SpriteID locks_base = GetCanalSprite(CF_LOCKS, ti->tile);
   469 	SpriteID locks_base = GetCanalSprite(CF_LOCKS, ti->tile);
   432 
   470 
   433 	/* If no custom graphics, use defaults */
   471 	/* If no custom graphics, use defaults */
   434 	if (water_base == 0) water_base = SPR_CANALS_BASE + 5;
   472 	if (water_base == 0) water_base = SPR_CANALS_BASE;
   435 	if (locks_base == 0) {
   473 	if (locks_base == 0) {
   436 		locks_base = SPR_CANALS_BASE + 9;
   474 		locks_base = SPR_SHIPLIFT_BASE;
   437 	} else {
   475 	} else {
   438 		/* If using custom graphics, ignore the variation on height */
   476 		/* If using custom graphics, ignore the variation on height */
   439 		base = 0;
   477 		base = 0;
   440 	}
   478 	}
   441 
   479 
   446 	for (; wdts->delta_x != 0x80; wdts++) {
   484 	for (; wdts->delta_x != 0x80; wdts++) {
   447 		AddSortableSpriteToDraw(wdts->image + base + ((wdts->image < 24) ? locks_base : 0), palette,
   485 		AddSortableSpriteToDraw(wdts->image + base + ((wdts->image < 24) ? locks_base : 0), palette,
   448 			ti->x + wdts->delta_x, ti->y + wdts->delta_y,
   486 			ti->x + wdts->delta_x, ti->y + wdts->delta_y,
   449 			wdts->width, wdts->height,
   487 			wdts->width, wdts->height,
   450 			wdts->unk, ti->z + wdts->delta_z,
   488 			wdts->unk, ti->z + wdts->delta_z,
   451 			HASBIT(_transparent_opt, TO_BUILDINGS));
   489 			IsTransparencySet(TO_BUILDINGS));
   452 	}
   490 	}
   453 }
   491 }
   454 
   492 
   455 static void DrawTile_Water(TileInfo *ti)
   493 static void DrawTile_Water(TileInfo *ti)
   456 {
   494 {
   457 	switch (GetWaterTileType(ti->tile)) {
   495 	switch (GetWaterTileType(ti->tile)) {
   458 		case WATER_TILE_CLEAR:
   496 		case WATER_TILE_CLEAR:
   459 			DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
   497 			DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
   460 			if (ti->z != 0 || !IsTileOwner(ti->tile, OWNER_WATER)) DrawCanalWater(ti->tile);
   498 			if (IsCanal(ti->tile)) DrawCanalWater(ti->tile);
   461 			DrawBridgeMiddle(ti);
   499 			DrawBridgeMiddle(ti);
   462 			break;
   500 			break;
   463 
   501 
   464 		case WATER_TILE_COAST:
   502 		case WATER_TILE_COAST:
   465 			assert(!IsSteepSlope(ti->tileh));
   503 			assert(!IsSteepSlope(ti->tileh));
   466 			if (_coast_base != 0) {
   504 			if (_loaded_newgrf_features.has_newwater) {
   467 				DrawGroundSprite(_coast_base + ti->tileh, PAL_NONE);
   505 				DrawGroundSprite(_coast_base + ti->tileh, PAL_NONE);
   468 			} else {
   506 			} else {
   469 				DrawGroundSprite(_water_shore_sprites[ti->tileh], PAL_NONE);
   507 				DrawGroundSprite(_water_shore_sprites[ti->tileh], PAL_NONE);
   470 			}
   508 			}
   471 			DrawBridgeMiddle(ti);
   509 			DrawBridgeMiddle(ti);
   515 
   553 
   516 static void GetTileDesc_Water(TileIndex tile, TileDesc *td)
   554 static void GetTileDesc_Water(TileIndex tile, TileDesc *td)
   517 {
   555 {
   518 	switch (GetWaterTileType(tile)) {
   556 	switch (GetWaterTileType(tile)) {
   519 		case WATER_TILE_CLEAR:
   557 		case WATER_TILE_CLEAR:
   520 			if (TilePixelHeight(tile) == 0 || IsTileOwner(tile, OWNER_WATER)) {
   558 			if (!IsCanal(tile)) {
   521 				td->str = STR_3804_WATER;
   559 				td->str = STR_3804_WATER;
   522 			} else {
   560 			} else {
   523 				td->str = STR_LANDINFO_CANAL;
   561 				td->str = STR_LANDINFO_CANAL;
   524 			}
   562 			}
   525 			break;
   563 			break;
   535 static void AnimateTile_Water(TileIndex tile)
   573 static void AnimateTile_Water(TileIndex tile)
   536 {
   574 {
   537 	/* not used */
   575 	/* not used */
   538 }
   576 }
   539 
   577 
       
   578 /**
       
   579  * Floods neighboured floodable tiles
       
   580  *
       
   581  * @param tile The water source tile that causes the flooding.
       
   582  * @param offs[0] Destination tile to flood.
       
   583  * @param offs[1] First corner of edge between source and dest tile.
       
   584  * @param offs[2] Second corder of edge between source and dest tile.
       
   585  * @param offs[3] Third corner of dest tile.
       
   586  * @param offs[4] Fourth corner of dest tile.
       
   587  */
   540 static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs)
   588 static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs)
   541 {
   589 {
   542 	TileIndex target = TILE_ADD(tile, ToTileIndexDiff(offs[0]));
   590 	TileIndex target = TILE_ADD(tile, ToTileIndexDiff(offs[0]));
   543 
   591 
   544 	/* type of this tile mustn't be water already. */
   592 	/* type of this tile mustn't be water already. */
   545 	if (IsTileType(target, MP_WATER)) return;
   593 	if (IsTileType(target, MP_WATER)) return;
   546 
   594 
   547 	/* Ensure sea-level FSMports do not flood */
   595 	/* Ensure sea-level FSMports do not flood */
   548 	if ((IsTileType(target, MP_STATION)))
   596 	if (IsTileType(target, MP_STATION) && GetStationByTile(target)->FSMport_flood_protected) return;
   549 	{
   597 
   550 		if (GetStationByTile(target)->FSMport_flood_protected) return;
   598 	/* Are both corners of the edge between source and dest on height 0 ? */
   551 	}
       
   552 
       
   553 	if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[1]))) != 0 ||
   599 	if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[1]))) != 0 ||
   554 			TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[2]))) != 0) {
   600 			TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[2]))) != 0) {
   555 		return;
   601 		return;
   556 	}
   602 	}
   557 
   603 
       
   604 	/* Is any corner of the dest tile raised? (First two corners already checked above. */
   558 	if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[3]))) != 0 ||
   605 	if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[3]))) != 0 ||
   559 			TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[4]))) != 0) {
   606 			TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[4]))) != 0) {
   560 		/* make coast.. */
   607 		/* make coast.. */
   561 		switch (GetTileType(target)) {
   608 		switch (GetTileType(target)) {
   562 			case MP_RAILWAY: {
   609 			case MP_RAILWAY: {
   563 				TrackBits tracks;
       
   564 				Slope slope;
       
   565 
       
   566 				if (!IsPlainRailTile(target)) break;
   610 				if (!IsPlainRailTile(target)) break;
   567 
   611 
   568 				tracks = GetTrackBits(target);
   612 				FloodHalftile(target);
   569 				slope = GetTileSlope(target, NULL);
       
   570 				if (!(
       
   571 							(slope == SLOPE_W && tracks == TRACK_BIT_RIGHT) ||
       
   572 							(slope == SLOPE_S && tracks == TRACK_BIT_UPPER) ||
       
   573 							(slope == SLOPE_E && tracks == TRACK_BIT_LEFT)  ||
       
   574 							(slope == SLOPE_N && tracks == TRACK_BIT_LOWER)
       
   575 						)) {
       
   576 					break;
       
   577 				}
       
   578 
   613 
   579 				Vehicle *v = FindFloodableVehicleOnTile(target);
   614 				Vehicle *v = FindFloodableVehicleOnTile(target);
   580 				if (v != NULL) FloodVehicle(v);
   615 				if (v != NULL) FloodVehicle(v);
   581 			}
   616 
   582 			/* FALLTHROUGH */
   617 				break;
       
   618 			}
   583 
   619 
   584 			case MP_CLEAR:
   620 			case MP_CLEAR:
   585 			case MP_TREES:
   621 			case MP_TREES:
   586 				_current_player = OWNER_WATER;
   622 				_current_player = OWNER_WATER;
   587 				if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
   623 				if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
   592 
   628 
   593 			default:
   629 			default:
   594 				break;
   630 				break;
   595 		}
   631 		}
   596 	} else {
   632 	} else {
       
   633 		/* Flood vehicles */
   597 		_current_player = OWNER_WATER;
   634 		_current_player = OWNER_WATER;
   598 
   635 
   599 		Vehicle *v = FindFloodableVehicleOnTile(target);
   636 		Vehicle *v = FindFloodableVehicleOnTile(target);
   600 		if (v != NULL) FloodVehicle(v);
   637 		if (v != NULL) FloodVehicle(v);
   601 
   638 
       
   639 		/* flood flat tile */
   602 		if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
   640 		if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
   603 			MakeWater(target);
   641 			MakeWater(target);
   604 			MarkTileDirtyByTile(target);
   642 			MarkTileDirtyByTile(target);
   605 		}
   643 		}
   606 	}
   644 	}
   716 		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
   754 		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
   717 		SndPlayVehicleFx(SND_12_EXPLOSION, v);
   755 		SndPlayVehicleFx(SND_12_EXPLOSION, v);
   718 	}
   756 	}
   719 }
   757 }
   720 
   758 
   721 /** called from tunnelbridge_cmd, and by TileLoop_Industry() */
   759 /**
       
   760  * Let a water tile floods its diagonal adjoining tiles
       
   761  * called from tunnelbridge_cmd, and by TileLoop_Industry() and TileLoop_Track()
       
   762  *
       
   763  * @param tile the water/shore tile that floods
       
   764  */
   722 void TileLoop_Water(TileIndex tile)
   765 void TileLoop_Water(TileIndex tile)
   723 {
   766 {
   724 	static const TileIndexDiffC _tile_loop_offs_array[][5] = {
   767 	static const TileIndexDiffC _tile_loop_offs_array[][5] = {
   725 		// tile to mod              shore?    shore?
   768 		// tile to mod              shore?    shore?
   726 		{{-1,  0}, {0, 0}, {0, 1}, {-1,  0}, {-1,  1}},
   769 		{{-1,  0}, {0, 0}, {0, 1}, {-1,  0}, {-1,  1}},
   727 		{{ 0,  1}, {0, 1}, {1, 1}, { 0,  2}, { 1,  2}},
   770 		{{ 0,  1}, {0, 1}, {1, 1}, { 0,  2}, { 1,  2}},
   728 		{{ 1,  0}, {1, 0}, {1, 1}, { 2,  0}, { 2,  1}},
   771 		{{ 1,  0}, {1, 0}, {1, 1}, { 2,  0}, { 2,  1}},
   729 		{{ 0, -1}, {0, 0}, {1, 0}, { 0, -1}, { 1, -1}}
   772 		{{ 0, -1}, {0, 0}, {1, 0}, { 0, -1}, { 1, -1}}
   730 	};
   773 	};
   731 
   774 
   732 	/* Ensure sea-level canals and buoys on canal borders do not flood */
   775 	/* Ensure buoys on canal borders do not flood */
   733 	if ((IsTileType(tile, MP_WATER) || IsBuoyTile(tile)) && !IsTileOwner(tile, OWNER_WATER)) return;
   776 	if (IsCanalBuoyTile(tile)) return;
   734 
   777 	/* Ensure only sea and coast floods, not canals or rivers */
   735 	if (IS_INT_INSIDE(TileX(tile), 1, MapSizeX() - 3 + 1) &&
   778 	if (IsTileType(tile, MP_WATER) && !(IsSea(tile) || IsCoast(tile))) return;
   736 			IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) {
   779 
       
   780 	/* floods in all four diagonal directions with the exception of the edges */
       
   781 	if (IsInsideMM(TileX(tile), 1, MapSizeX() - 3 + 1) &&
       
   782 			IsInsideMM(TileY(tile), 1, MapSizeY() - 3 + 1)) {
   737 		uint i;
   783 		uint i;
   738 
   784 
   739 		for (i = 0; i != lengthof(_tile_loop_offs_array); i++) {
   785 		for (i = 0; i != lengthof(_tile_loop_offs_array); i++) {
   740 			TileLoopWaterHelper(tile, _tile_loop_offs_array[i]);
   786 			TileLoopWaterHelper(tile, _tile_loop_offs_array[i]);
   741 		}
   787 		}
   742 	}
   788 	}
       
   789 
   743 	/* _current_player can be changed by TileLoopWaterHelper.. reset it back here */
   790 	/* _current_player can be changed by TileLoopWaterHelper.. reset it back here */
   744 	_current_player = OWNER_NONE;
   791 	_current_player = OWNER_NONE;
   745 
   792 
   746 	/* edges */
   793 	/* edges */
   747 	if (TileX(tile) == 0 && IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) { //NE
   794 	if (TileX(tile) == 0 && IsInsideMM(TileY(tile), 1, MapSizeY() - 3 + 1)) { //NE
   748 		TileLoopWaterHelper(tile, _tile_loop_offs_array[2]);
   795 		TileLoopWaterHelper(tile, _tile_loop_offs_array[2]);
   749 	}
   796 	}
   750 
   797 
   751 	if (TileX(tile) == MapSizeX() - 2 && IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) { //SW
   798 	if (TileX(tile) == MapSizeX() - 2 && IsInsideMM(TileY(tile), 1, MapSizeY() - 3 + 1)) { //SW
   752 		TileLoopWaterHelper(tile, _tile_loop_offs_array[0]);
   799 		TileLoopWaterHelper(tile, _tile_loop_offs_array[0]);
   753 	}
   800 	}
   754 
   801 
   755 	if (TileY(tile) == 0 && IS_INT_INSIDE(TileX(tile), 1, MapSizeX() - 3 + 1)) { //NW
   802 	if (TileY(tile) == 0 && IsInsideMM(TileX(tile), 1, MapSizeX() - 3 + 1)) { //NW
   756 		TileLoopWaterHelper(tile, _tile_loop_offs_array[1]);
   803 		TileLoopWaterHelper(tile, _tile_loop_offs_array[1]);
   757 	}
   804 	}
   758 
   805 
   759 	if (TileY(tile) == MapSizeY() - 2 && IS_INT_INSIDE(TileX(tile), 1, MapSizeX() - 3 + 1)) { //SE
   806 	if (TileY(tile) == MapSizeY() - 2 && IsInsideMM(TileX(tile), 1, MapSizeX() - 3 + 1)) { //SE
   760 		TileLoopWaterHelper(tile, _tile_loop_offs_array[3]);
   807 		TileLoopWaterHelper(tile, _tile_loop_offs_array[3]);
   761 	}
   808 	}
   762 }
   809 }
   763 
   810 
   764 static uint32 GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode)
   811 static uint32 GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode)
   815 }
   862 }
   816 
   863 
   817 static CommandCost TerraformTile_Water(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
   864 static CommandCost TerraformTile_Water(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
   818 {
   865 {
   819 	/* Canals can't be terraformed */
   866 	/* Canals can't be terraformed */
   820 	if (IsClearWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_MUST_DEMOLISH_CANAL_FIRST);
   867 	if (IsWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_MUST_DEMOLISH_CANAL_FIRST);
   821 
   868 
   822 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   869 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   823 }
   870 }
   824 
   871 
   825 
   872