Index: src/water_map.h =================================================================== --- src/water_map.h (revision 11274) +++ src/water_map.h (working copy) @@ -27,6 +27,8 @@ static inline WaterTileType GetWaterTileType(TileIndex t) { + assert(IsTileType(t, MP_WATER)); + if (_m[t].m5 == 0) return WATER_TILE_CLEAR; if (_m[t].m5 == 1) return WATER_TILE_COAST; if (IS_INT_INSIDE(_m[t].m5, LOCK_MIDDLE, LOCK_END)) return WATER_TILE_LOCK; @@ -35,11 +37,19 @@ return WATER_TILE_DEPOT; } +/** IsWater return true if any type of clear water like ocean, river, canal */ static inline bool IsWater(TileIndex t) { return GetWaterTileType(t) == WATER_TILE_CLEAR; } +static inline bool IsSea(TileIndex t) +{ + if (GetWaterTileType(t) != WATER_TILE_CLEAR) return false; + if (!IsTileOwner(t, OWNER_WATER)) return false; // 'Human' built water = canal, not sea + return true; +} + static inline bool IsCoast(TileIndex t) { return GetWaterTileType(t) == WATER_TILE_COAST; @@ -52,7 +62,11 @@ static inline bool IsClearWaterTile(TileIndex t) { - return IsTileType(t, MP_WATER) && IsWater(t) && GetTileSlope(t, NULL) == SLOPE_FLAT; + /* + * This used to check TileSlope == flat too. + * But none of the uses actually requires flat water, just (clear)Water (canal, river, sea) + */ + return IsTileType(t, MP_WATER) && IsWater(t); } static inline TileIndex GetOtherShipDepotTile(TileIndex t) @@ -109,6 +123,7 @@ static inline void MakeCanal(TileIndex t, Owner o) { + assert(o != OWNER_WATER); SetTileType(t, MP_WATER); SetTileOwner(t, o); _m[t].m2 = 0; Index: src/saveload.cpp =================================================================== --- src/saveload.cpp (revision 11274) +++ src/saveload.cpp (working copy) @@ -29,7 +29,7 @@ #include "strings.h" #include -extern const uint16 SAVEGAME_VERSION = 81; +extern const uint16 SAVEGAME_VERSION = 82; uint16 _sl_version; ///< the major savegame version identifier byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! Index: src/station_cmd.cpp =================================================================== --- src/station_cmd.cpp (revision 11274) +++ src/station_cmd.cpp (working copy) @@ -2088,7 +2088,7 @@ DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y); } - if (IsBuoyTile(ti->tile) && (ti->z != 0 || !IsTileOwner(ti->tile, OWNER_WATER))) DrawCanalWater(ti->tile); + if (IsCanalBuoyTile(ti->tile)) DrawCanalWater(ti->tile); const DrawTileSeqStruct *dtss; foreach_draw_tile_seq(dtss, t->seq) { Index: src/water_cmd.cpp =================================================================== --- src/water_cmd.cpp (revision 11274) +++ src/water_cmd.cpp (working copy) @@ -458,7 +458,7 @@ switch (GetWaterTileType(ti->tile)) { case WATER_TILE_CLEAR: DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE); - if (ti->z != 0 || !IsTileOwner(ti->tile, OWNER_WATER)) DrawCanalWater(ti->tile); + if (IsCanal(ti->tile)) DrawCanalWater(ti->tile); DrawBridgeMiddle(ti); break; @@ -518,7 +518,7 @@ { switch (GetWaterTileType(tile)) { case WATER_TILE_CLEAR: - if (TilePixelHeight(tile) == 0 || IsTileOwner(tile, OWNER_WATER)) { + if (!IsCanal(tile)) { td->str = STR_3804_WATER; } else { td->str = STR_LANDINFO_CANAL; @@ -725,8 +725,10 @@ {{ 0, -1}, {0, 0}, {1, 0}, { 0, -1}, { 1, -1}} }; - /* Ensure sea-level canals and buoys on canal borders do not flood */ - if ((IsTileType(tile, MP_WATER) || IsBuoyTile(tile)) && !IsTileOwner(tile, OWNER_WATER)) return; + /* Ensure buoys on canal borders do not flood */ + if (IsCanalBuoyTile(tile)) return; + /* Ensure only sea and coast floods, not canals or rivers */ + if (IsTileType(tile, MP_WATER) && !(IsSea(tile) || IsCoast(tile))) return; /* floods in all four diagonal directions with the exception of the edges */ if (IS_INT_INSIDE(TileX(tile), 1, MapSizeX() - 3 + 1) && Index: src/station_map.h =================================================================== --- src/station_map.h (revision 11274) +++ src/station_map.h (working copy) @@ -154,7 +154,16 @@ return IsTileType(t, MP_STATION) && IsBuoy(t); } +static inline bool IsCanalBuoyTile(TileIndex t) +{ + return IsBuoyTile(t) && !IsTileOwner(t, OWNER_WATER); +} +static inline bool IsSeaBuoyTile(TileIndex t) +{ + return IsBuoyTile(t) && IsTileOwner(t, OWNER_WATER); +} + static inline bool IsHangarTile(TileIndex t) { return IsTileType(t, MP_STATION) && IsHangar(t); Index: src/openttd.cpp =================================================================== --- src/openttd.cpp (revision 11274) +++ src/openttd.cpp (working copy) @@ -1626,7 +1626,7 @@ if (GB(_m[t].m5, 3, 2) == 0) { MakeClear(t, CLEAR_GRASS, 3); } else { - MakeCanal(t, GetTileOwner(t)); + MakeCanal(t, (GetTileOwner(t) == OWNER_WATER) ? OWNER_NONE : GetTileOwner(t)); } } SetBridgeMiddle(t, axis); @@ -2160,6 +2160,18 @@ FOR_ALL_INDUSTRIES(i) i->founder = OWNER_NONE; } + /* From version 82, old style canals (above sealevel (0), WATER owner) are no longer supported. + Replace the owner for those by OWNER_NONE. */ + if (CheckSavegameVersion(82)) { + for (TileIndex t = 0; t < map_size; t++) { + if (!IsTileType(t, MP_WATER)) continue; + if (GetWaterTileType(t) != WATER_TILE_CLEAR) continue; + if (GetTileOwner(t) != OWNER_WATER) continue; + if (TileHeight(t) == 0 ) continue; + SetTileOwner(t, OWNER_NONE); + } + } + /* Recalculate */ Group *g; FOR_ALL_GROUPS(g) {