--- a/src/water_cmd.cpp Sun Feb 03 01:34:21 2008 +0000
+++ b/src/water_cmd.cpp Sun Feb 03 20:34:26 2008 +0000
@@ -34,6 +34,7 @@
#include "player_func.h"
#include "settings_type.h"
#include "clear_map.h"
+#include "tree_map.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -70,9 +71,28 @@
};
/**
- * Slopes that contain flat water and not only shore.
+ * Marks tile dirty if it is a canal or river tile.
+ * Called to avoid glitches when flooding tiles next to canal tile.
+ *
+ * @param tile tile to check
*/
-static const uint32 _active_water_slopes = (1 << SLOPE_FLAT) | (1 << SLOPE_W) | (1 << SLOPE_S) | (1 << SLOPE_E) | (1 << SLOPE_N);
+static inline void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
+{
+ if (IsTileType(tile, MP_WATER) && (IsCanal(tile) || IsRiver(tile))) MarkTileDirtyByTile(tile);
+}
+
+/**
+ * Marks the tiles around a tile as dirty, if they are canals or rivers.
+ *
+ * @param tile The center of the tile where all other tiles are marked as dirty
+ * @ingroup dirty
+ */
+static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
+{
+ for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
+ MarkTileDirtyIfCanalOrRiver(tile + TileOffsByDir(dir));
+ }
+}
/**
* Makes a tile canal or water depending on the surroundings.
@@ -81,33 +101,46 @@
* @param t the tile to change.
* @param o the owner of the new tile.
*/
-void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o)
+void SetWaterClassDependingOnSurroundings(TileIndex t)
{
assert(GetTileSlope(t, NULL) == SLOPE_FLAT);
/* Mark tile dirty in all cases */
MarkTileDirtyByTile(t);
- /* Non-sealevel -> canal */
- if (TileHeight(t) != 0) {
- MakeCanal(t, o, Random());
- return;
- }
-
bool has_water = false;
bool has_canal = false;
+ bool has_river = false;
for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
TileIndex neighbour = TileAddByDiagDir(t, dir);
- if (IsTileType(neighbour, MP_WATER)) {
- has_water |= IsSea(neighbour) || IsCoast(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) == OWNER_WATER);
- has_canal |= IsCanal(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) != OWNER_WATER);
+ switch (GetTileType(neighbour)) {
+ case MP_WATER:
+ has_water |= IsSea(neighbour) || IsCoast(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) == OWNER_WATER);
+ has_canal |= IsCanal(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) != OWNER_WATER);
+ has_river |= IsRiver(neighbour);
+ break;
+
+ case MP_RAILWAY:
+ /* Shore or flooded halftile */
+ has_water |= (GetRailGroundType(neighbour) == RAIL_GROUND_WATER);
+ break;
+
+ case MP_TREES:
+ /* trees on shore */
+ has_water |= (GetTreeGround(neighbour) == TREE_GROUND_SHORE);
+ break;
+
+ default: break;
}
}
- if (has_canal || !has_water) {
- MakeCanal(t, o, Random());
+
+ if (has_river && !has_canal) {
+ SetWaterClass(t, WATER_CLASS_RIVER);
+ } else if (has_canal || !has_water) {
+ SetWaterClass(t, WATER_CLASS_CANAL);
} else {
- MakeWater(t);
+ SetWaterClass(t, WATER_CLASS_SEA);
}
}
@@ -128,11 +161,19 @@
tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
- if (!IsWaterTile(tile) || !IsWaterTile(tile2))
+ if (!IsWaterTile(tile) || !IsWaterTile(tile2)) {
return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
+ }
if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+ if (GetTileSlope(tile, NULL) != SLOPE_FLAT || GetTileSlope(tile2, NULL) != SLOPE_FLAT) {
+ /* Prevent depots on rapids */
+ return_cmd_error(STR_0239_SITE_UNSUITABLE);
+ }
+
+ WaterClass wc1 = GetWaterClass(tile);
+ WaterClass wc2 = GetWaterClass(tile2);
Owner o1 = GetTileOwner(tile);
Owner o2 = GetTileOwner(tile2);
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
@@ -147,8 +188,8 @@
if (flags & DC_EXEC) {
depot->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
- MakeShipDepot(tile, _current_player, DEPOT_NORTH, axis, o1);
- MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, o2);
+ MakeShipDepot(tile, _current_player, DEPOT_NORTH, axis, wc1, o1);
+ MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, wc2, o2);
MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(tile2);
d_auto_delete.Detach();
@@ -157,12 +198,14 @@
return CommandCost(EXPENSES_CONSTRUCTION, _price.build_ship_depot);
}
-void MakeWaterOrCanalDependingOnOwner(TileIndex tile, Owner o)
+void MakeWaterKeepingClass(TileIndex tile, Owner o)
{
- if (o == OWNER_WATER) {
- MakeWater(tile);
- } else {
- MakeCanal(tile, o, Random());
+ assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile))));
+
+ switch (GetWaterClass(tile)) {
+ case WATER_CLASS_SEA: MakeWater(tile); break;
+ case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
+ case WATER_CLASS_RIVER: MakeRiver(tile, Random()); break;
}
}
@@ -182,8 +225,8 @@
/* Kill the depot, which is registered at the northernmost tile. Use that one */
delete GetDepotByTile(tile2 < tile ? tile2 : tile);
- MakeWaterOrCanalDependingOnOwner(tile, GetShipDepotWaterOwner(tile));
- MakeWaterOrCanalDependingOnOwner(tile2, GetShipDepotWaterOwner(tile2));
+ MakeWaterKeepingClass(tile, GetShipDepotWaterOwner(tile));
+ MakeWaterKeepingClass(tile2, GetShipDepotWaterOwner(tile2));
MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(tile2);
}
@@ -203,6 +246,8 @@
delta = TileOffsByDiagDir(dir);
/* lower tile */
+ WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
+
ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) return CMD_ERROR;
if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) {
@@ -210,6 +255,8 @@
}
/* upper tile */
+ WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
+
ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) return CMD_ERROR;
if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) {
@@ -223,10 +270,12 @@
}
if (flags & DC_EXEC) {
- MakeLock(tile, _current_player, dir);
+ MakeLock(tile, _current_player, dir, wc_lower, wc_upper);
MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(tile - delta);
MarkTileDirtyByTile(tile + delta);
+ MarkCanalsAndRiversAroundDirty(tile - delta);
+ MarkCanalsAndRiversAroundDirty(tile + delta);
}
return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water * 22 >> 3);
@@ -244,30 +293,17 @@
if (flags & DC_EXEC) {
DoClearSquare(tile);
- MakeWaterOrCanalDependingOnSurroundings(tile + delta, _current_player);
- MakeWaterOrCanalDependingOnSurroundings(tile - delta, _current_player);
+ MakeWaterKeepingClass(tile + delta, GetTileOwner(tile));
+ MakeWaterKeepingClass(tile - delta, GetTileOwner(tile));
+ MarkTileDirtyByTile(tile - delta);
+ MarkTileDirtyByTile(tile + delta);
+ MarkCanalsAndRiversAroundDirty(tile - delta);
+ MarkCanalsAndRiversAroundDirty(tile + delta);
}
return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water * 2);
}
-/**
- * Marks the tiles around a tile as dirty.
- *
- * This functions marks the tiles around a given tile as dirty for repaint.
- *
- * @param tile The center of the tile where all other tiles are marked as dirty
- * @ingroup dirty
- * @see TerraformAddDirtyTileAround
- */
-static void MarkTilesAroundDirty(TileIndex tile)
-{
- MarkTileDirtyByTile(TILE_ADDXY(tile, 0, 1));
- MarkTileDirtyByTile(TILE_ADDXY(tile, 0, -1));
- MarkTileDirtyByTile(TILE_ADDXY(tile, 1, 0));
- MarkTileDirtyByTile(TILE_ADDXY(tile, -1, 0));
-}
-
/** Builds a lock (ship-lift)
* @param tile tile where to place the lock
* @param flags type of operation
@@ -276,15 +312,12 @@
*/
CommandCost CmdBuildLock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
- DiagDirection dir;
+ DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
+ if (dir == INVALID_DIAGDIR) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
- switch (GetTileSlope(tile, NULL)) {
- case SLOPE_SW: dir = DIAGDIR_SW; break;
- case SLOPE_SE: dir = DIAGDIR_SE; break;
- case SLOPE_NW: dir = DIAGDIR_NW; break;
- case SLOPE_NE: dir = DIAGDIR_NE; break;
- default: return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
- }
+ /* Disallow building of locks on river rapids */
+ if (IsWaterTile(tile)) return_cmd_error(STR_0239_SITE_UNSUITABLE);
+
return DoBuildShiplift(tile, dir, flags);
}
@@ -292,7 +325,7 @@
* @param tile end tile of stretch-dragging
* @param flags type of operation
* @param p1 start tile of stretch-dragging
- * @param p2 ctrl pressed - toggles ocean / canals at sealevel (ocean only allowed in the scenario editor)
+ * @param p2 specifies canal (0), water (1) or river (2); last two can only be built in scenario editor
*/
CommandCost CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
@@ -324,7 +357,7 @@
CommandCost ret;
Slope slope = GetTileSlope(tile, NULL);
- if (slope != SLOPE_FLAT && (p2 != 2 || (slope != SLOPE_NW && slope != SLOPE_NE && slope != SLOPE_SW && slope != SLOPE_SE))) {
+ if (slope != SLOPE_FLAT && (p2 != 2 || !IsInclinedSlope(slope))) {
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
}
@@ -344,7 +377,7 @@
MakeCanal(tile, _current_player, Random());
}
MarkTileDirtyByTile(tile);
- MarkTilesAroundDirty(tile);
+ MarkCanalsAndRiversAroundDirty(tile);
}
cost.AddCost(_price.clear_water);
@@ -361,7 +394,6 @@
{
switch (GetWaterTileType(tile)) {
case WATER_TILE_CLEAR:
- case WATER_TILE_RIVER:
if (flags & DC_NO_WATER) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
/* Make sure it's not an edge tile. */
@@ -375,7 +407,10 @@
if (GetTileOwner(tile) != OWNER_WATER && GetTileOwner(tile) != OWNER_NONE && !CheckTileOwnership(tile)) return CMD_ERROR;
- if (flags & DC_EXEC) DoClearSquare(tile);
+ if (flags & DC_EXEC) {
+ DoClearSquare(tile);
+ MarkCanalsAndRiversAroundDirty(tile);
+ }
return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water);
case WATER_TILE_COAST: {
@@ -384,8 +419,11 @@
/* Make sure no vehicle is on the tile */
if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
- if (flags & DC_EXEC) DoClearSquare(tile);
- if (slope == SLOPE_N || slope == SLOPE_E || slope == SLOPE_S || slope == SLOPE_W) {
+ if (flags & DC_EXEC) {
+ DoClearSquare(tile);
+ MarkCanalsAndRiversAroundDirty(tile);
+ }
+ if (IsSlopeWithOneCornerRaised(slope)) {
return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water);
} else {
return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_roughland);
@@ -414,26 +452,41 @@
}
}
-/** return true if a tile is a water tile. */
-static bool IsWateredTile(TileIndex tile)
+/**
+ * return true if a tile is a water tile wrt. a certain direction.
+ *
+ * @param tile The tile of interest.
+ * @param from The direction of interest.
+ * @return true iff the tile is water in the view of 'from'.
+ *
+ */
+static bool IsWateredTile(TileIndex tile, Direction from)
{
switch (GetTileType(tile)) {
case MP_WATER:
if (!IsCoast(tile)) return true;
-
switch (GetTileSlope(tile, NULL)) {
- case SLOPE_W:
- case SLOPE_S:
- case SLOPE_E:
- case SLOPE_N:
- return true;
-
- default:
- return false;
+ case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
+ case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
+ case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
+ case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
+ default: return false;
}
- case MP_RAILWAY: return GetRailGroundType(tile) == RAIL_GROUND_WATER;
- case MP_STATION: return IsCustomFSMportsSpecIndex(tile) || IsOilRig(tile) || IsDock(tile) || IsBuoy(tile);
+ case MP_RAILWAY:
+ if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
+ assert(IsPlainRailTile(tile));
+ switch (GetTileSlope(tile, NULL)) {
+ case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
+ case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
+ case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
+ case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
+ default: return false;
+ }
+ }
+ return false;
+
+ case MP_STATION: return IsCustomFSMportsSpecIndex(tile) || IsOilRig(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsBuoy(tile);
case MP_INDUSTRY: return (GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0;
default: return false;
}
@@ -444,10 +497,10 @@
uint wa;
/* determine the edges around with water. */
- wa = IsWateredTile(TILE_ADDXY(tile, -1, 0)) << 0;
- wa += IsWateredTile(TILE_ADDXY(tile, 0, 1)) << 1;
- wa += IsWateredTile(TILE_ADDXY(tile, 1, 0)) << 2;
- wa += IsWateredTile(TILE_ADDXY(tile, 0, -1)) << 3;
+ wa = IsWateredTile(TILE_ADDXY(tile, -1, 0), DIR_SW) << 0;
+ wa += IsWateredTile(TILE_ADDXY(tile, 0, 1), DIR_NW) << 1;
+ wa += IsWateredTile(TILE_ADDXY(tile, 1, 0), DIR_NE) << 2;
+ wa += IsWateredTile(TILE_ADDXY(tile, 0, -1), DIR_SE) << 3;
if (!(wa & 1)) DrawGroundSprite(base, PAL_NONE);
if (!(wa & 2)) DrawGroundSprite(base + 1, PAL_NONE);
@@ -457,31 +510,39 @@
/* right corner */
switch (wa & 0x03) {
case 0: DrawGroundSprite(base + 4, PAL_NONE); break;
- case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(base + 8, PAL_NONE); break;
+ case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1), DIR_W)) DrawGroundSprite(base + 8, PAL_NONE); break;
}
/* bottom corner */
switch (wa & 0x06) {
case 0: DrawGroundSprite(base + 5, PAL_NONE); break;
- case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(base + 9, PAL_NONE); break;
+ case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1), DIR_N)) DrawGroundSprite(base + 9, PAL_NONE); break;
}
/* left corner */
switch (wa & 0x0C) {
case 0: DrawGroundSprite(base + 6, PAL_NONE); break;
- case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(base + 10, PAL_NONE); break;
+ case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1), DIR_E)) DrawGroundSprite(base + 10, PAL_NONE); break;
}
/* upper corner */
switch (wa & 0x09) {
case 0: DrawGroundSprite(base + 7, PAL_NONE); break;
- case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(base + 11, PAL_NONE); break;
+ case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawGroundSprite(base + 11, PAL_NONE); break;
}
}
+/** Draw a plain sea water tile with no edges */
+void DrawSeaWater(TileIndex tile)
+{
+ DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
+}
+
/** draw a canal styled water tile with dikes around */
-void DrawCanalWater(TileIndex tile)
+void DrawCanalWater(TileIndex tile, bool draw_base)
{
+ if (draw_base) DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
+
/* Test for custom graphics, else use the default */
SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile);
if (dikes_base == 0) dikes_base = SPR_CANAL_DIKES_BASE;
@@ -527,7 +588,7 @@
}
}
-static void DrawRiverWater(const TileInfo *ti)
+void DrawRiverWater(const TileInfo *ti, bool draw_base)
{
SpriteID image = SPR_FLAT_WATER_TILE;
SpriteID edges_base = GetCanalSprite(CF_RIVER_EDGE, ti->tile);
@@ -535,7 +596,13 @@
if (ti->tileh != SLOPE_FLAT) {
image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
if (image == 0) {
- image = SPR_FLAT_WATER_TILE;
+ switch (ti->tileh) {
+ case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
+ case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP; break;
+ case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP; break;
+ case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
+ default: image = SPR_FLAT_WATER_TILE; break;
+ }
} else {
switch (ti->tileh) {
default: NOT_REACHED();
@@ -547,11 +614,10 @@
}
}
- DrawGroundSprite(image, PAL_NONE);
+ if (draw_base) DrawGroundSprite(image, PAL_NONE);
- /* Draw canal dikes if there are no river edges to draw. */
- if (edges_base <= 48) edges_base = SPR_CANAL_DIKES_BASE;
- DrawWaterEdges(edges_base, ti->tile);
+ /* Draw river edges if available. */
+ if (edges_base > 48) DrawWaterEdges(edges_base, ti->tile);
}
void DrawShoreTile(Slope tileh)
@@ -575,8 +641,11 @@
{
switch (GetWaterTileType(ti->tile)) {
case WATER_TILE_CLEAR:
- DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
- if (IsCanal(ti->tile)) DrawCanalWater(ti->tile);
+ switch (GetWaterClass(ti->tile)) {
+ case WATER_CLASS_SEA: DrawSeaWater(ti->tile); break;
+ case WATER_CLASS_CANAL: DrawCanalWater(ti->tile, true); break;
+ case WATER_CLASS_RIVER: DrawRiverWater(ti, true); break;
+ }
DrawBridgeMiddle(ti);
break;
@@ -593,11 +662,6 @@
case WATER_TILE_DEPOT:
DrawWaterStuff(ti, _shipdepot_display_seq[GetSection(ti->tile)], PLAYER_SPRITE_COLOR(GetTileOwner(ti->tile)), 0);
break;
-
- case WATER_TILE_RIVER:
- DrawRiverWater(ti);
- DrawBridgeMiddle(ti);
- break;
}
}
@@ -636,7 +700,6 @@
{
switch (GetWaterTileType(tile)) {
case WATER_TILE_CLEAR:
- case WATER_TILE_RIVER:
if (!IsCanal(tile)) {
td->str = STR_3804_WATER;
} else {
@@ -657,17 +720,6 @@
/* not used */
}
-/**
- * Marks tile dirty if it is a canal tile.
- * Called to avoid glitches when flooding tiles next to canal tile.
- *
- * @param tile tile to check
- */
-static inline void MarkTileDirtyIfCanal(TileIndex tile)
-{
- if (IsTileType(tile, MP_WATER) && IsCanal(tile)) MarkTileDirtyByTile(tile);
-}
-
/**
* Finds a vehicle to flood.
@@ -803,7 +855,7 @@
static FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
{
/* FLOOD_ACTIVE: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, rail with flooded halftile
- * FLOOD_DRYUP: coast with more than one corner raised
+ * FLOOD_DRYUP: coast with more than one corner raised, coast with rail-track, coast with trees
* FLOOD_PASSIVE: oilrig, dock, water-industries
* FLOOD_NONE: canals, rivers, everything else
*/
@@ -811,16 +863,22 @@
case MP_WATER:
if (IsCoast(tile)) {
Slope tileh = GetTileSlope(tile, NULL);
- return (HasBit(_active_water_slopes, tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
+ return (IsSlopeWithOneCornerRaised(tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
} else {
- return ((IsSea(tile) || (IsShipDepot(tile) && (GetShipDepotWaterOwner(tile) == OWNER_WATER))) ? FLOOD_ACTIVE : FLOOD_NONE);
+ return (GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE;
}
case MP_RAILWAY:
- return ((GetRailGroundType(tile) == RAIL_GROUND_WATER) ? FLOOD_ACTIVE : FLOOD_NONE);
+ if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
+ return (IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL)) ? FLOOD_ACTIVE : FLOOD_DRYUP);
+ }
+ return FLOOD_NONE;
+
+ case MP_TREES:
+ return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
case MP_STATION:
- if (IsSeaBuoyTile(tile)) return FLOOD_ACTIVE;
+ if (IsBuoy(tile) && GetWaterClass(tile) == WATER_CLASS_SEA) return FLOOD_ACTIVE;
if (IsOilRig(tile) || IsDock(tile)) return FLOOD_PASSIVE;
if (GetStationByTile(tile)->FSMport_flood_protected) return FLOOD_PASSIVE;
return FLOOD_NONE;
@@ -844,7 +902,8 @@
_current_player = OWNER_WATER;
- if (GetTileSlope(target, NULL) != SLOPE_FLAT) {
+ Slope tileh = GetTileSlope(target, NULL);
+ if (tileh != SLOPE_FLAT) {
/* make coast.. */
switch (GetTileType(target)) {
case MP_RAILWAY: {
@@ -858,8 +917,15 @@
break;
}
+ case MP_TREES:
+ if (!IsSlopeWithOneCornerRaised(tileh)) {
+ SetTreeGroundDensity(target, TREE_GROUND_SHORE, 3);
+ MarkTileDirtyByTile(target);
+ flooded = true;
+ break;
+ }
+ /* FALL THROUGH */
case MP_CLEAR:
- case MP_TREES:
if (CmdSucceeded(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
MakeShore(target);
MarkTileDirtyByTile(target);
@@ -888,9 +954,7 @@
if (flooded) {
/* Mark surrounding canal tiles dirty too to avoid glitches */
- for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
- MarkTileDirtyIfCanal(target + TileOffsByDir(dir));
- }
+ MarkCanalsAndRiversAroundDirty(target);
/* update signals if needed */
UpdateSignalsInBuffer();
@@ -904,12 +968,40 @@
*/
static void DoDryUp(TileIndex tile)
{
- assert(IsTileType(tile, MP_WATER) && IsCoast(tile));
_current_player = OWNER_WATER;
- if (CmdSucceeded(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
- MakeClear(tile, CLEAR_GRASS, 3);
- MarkTileDirtyByTile(tile);
+ switch (GetTileType(tile)) {
+ case MP_RAILWAY:
+ assert(IsPlainRailTile(tile));
+ assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
+
+ RailGroundType new_ground;
+ switch (GetTrackBits(tile)) {
+ case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
+ case TRACK_BIT_LOWER: new_ground = RAIL_GROUND_FENCE_HORIZ2; break;
+ case TRACK_BIT_LEFT: new_ground = RAIL_GROUND_FENCE_VERT1; break;
+ case TRACK_BIT_RIGHT: new_ground = RAIL_GROUND_FENCE_VERT2; break;
+ default: NOT_REACHED();
+ }
+ SetRailGroundType(tile, new_ground);
+ MarkTileDirtyByTile(tile);
+ break;
+
+ case MP_TREES:
+ SetTreeGroundDensity(tile, TREE_GROUND_GRASS, 3);
+ MarkTileDirtyByTile(tile);
+ break;
+
+ case MP_WATER:
+ assert(IsCoast(tile));
+
+ if (CmdSucceeded(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
+ MakeClear(tile, CLEAR_GRASS, 3);
+ MarkTileDirtyByTile(tile);
+ }
+ break;
+
+ default: NOT_REACHED();
}
_current_player = OWNER_NONE;
@@ -988,7 +1080,7 @@
FOR_EACH_SET_BIT(dir, check_dirs) {
TileIndex dest = TILE_ADD(tile, TileOffsByDir((Direction)dir));
Slope slope_dest = (Slope)(GetTileSlope(dest, NULL) & ~SLOPE_STEEP);
- if (HasBit(_active_water_slopes, slope_dest)) {
+ if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) {
MakeShore(tile);
break;
}
@@ -1008,11 +1100,10 @@
if (mode != TRANSPORT_WATER) return 0;
switch (GetWaterTileType(tile)) {
- case WATER_TILE_CLEAR: ts = TRACK_BIT_ALL; break;
+ case WATER_TILE_CLEAR: ts = (GetTileSlope(tile, NULL) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
case WATER_TILE_COAST: ts = (TrackBits)coast_tracks[GetTileSlope(tile, NULL) & 0xF]; break;
case WATER_TILE_LOCK: ts = AxisToTrackBits(DiagDirToAxis(GetLockDirection(tile))); break;
case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
- case WATER_TILE_RIVER: ts = (GetTileSlope(tile, NULL) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
default: return 0;
}
if (TileX(tile) == 0) {