From 1d891a8b15f750ea7aaa14622536e87765c59e7a Mon Sep 17 00:00:00 2001 From: peter1138 Date: Sat, 2 Feb 2008 09:28:43 +0000 Subject: (svn r12042) -Fix [FS#1676]: Reimplement how rivers and canals are stored in the map, allowing the sea/river/canal status to also be stored for buoys, docks, locks and depots. All these are now allowed on rivers and removal of them will revert to the original water type. --- src/industry_cmd.cpp | 2 +- src/newgrf_canal.cpp | 3 +- src/openttd.cpp | 25 +++++++++++- src/saveload.cpp | 2 +- src/station_cmd.cpp | 24 +++++++++--- src/station_map.h | 17 +++----- src/tunnelbridge_cmd.cpp | 8 ++-- src/water.h | 7 ++-- src/water_cmd.cpp | 100 ++++++++++++++++++++++++++++------------------- src/water_map.h | 61 +++++++++++++++++------------ 10 files changed, 153 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 2ef3cf353..d462b185b 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -1226,7 +1226,7 @@ static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour; /* Perform land/water check if not disabled */ - if (!HasBit(its->slopes_refused, 5) && ((IsWaterTile(cur_tile) || IsRiverTile(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return false; + if (!HasBit(its->slopes_refused, 5) && (IsWaterTile(cur_tile) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return false; if (HasBit(its->callback_flags, CBM_INDT_SHAPE_CHECK)) { custom_shape = true; diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp index 1a276ea7d..df3d7630c 100644 --- a/src/newgrf_canal.cpp +++ b/src/newgrf_canal.cpp @@ -22,7 +22,8 @@ WaterFeature _water_feature[CF_END]; * three functions are stubs. */ static uint32 CanalGetRandomBits(const ResolverObject *object) { - return GetWaterTileRandomBits(object->u.canal.tile); + /* Return random bits only for water tiles, not station tiles */ + return IsTileType(object->u.canal.tile, MP_WATER) ? GetWaterTileRandomBits(object->u.canal.tile) : 0; } diff --git a/src/openttd.cpp b/src/openttd.cpp index 736acb978..1b298de8b 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -77,6 +77,7 @@ #include "tree_map.h" #include "tunnelbridge_map.h" #include "void_map.h" +#include "water.h" #include @@ -2323,9 +2324,31 @@ bool AfterLoadGame() } if (CheckSavegameVersion(86)) { - /* Now all crossings should be in correct state */ for (TileIndex t = 0; t < map_size; t++) { + /* Now all crossings should be in correct state */ if (IsLevelCrossingTile(t)) UpdateLevelCrossing(t, false); + + /* Move river flag and update canals to use water class */ + if (IsTileType(t, MP_WATER)) { + if (_m[t].m5 == 2) { + MakeRiver(t, Random()); + } else { + Owner o = GetTileOwner(t); + if (IsWater(t) && o != OWNER_WATER) { + MakeCanal(t, o, Random()); + } + } + } + } + + /* Update locks, depots, docks and buoys to have a water class based + * on its neighbouring tiles. Done after river and canal updates to + * ensure neighbours are correct. */ + for (TileIndex t = 0; t < map_size; t++) { + if (GetTileSlope(t, NULL) != SLOPE_FLAT) continue; + + if (IsTileType(t, MP_WATER) && (GetWaterTileType(t) == WATER_TILE_LOCK || IsShipDepot(t))) SetWaterClassDependingOnSurroundings(t); + if (IsTileType(t, MP_STATION) && (IsDock(t) || IsBuoy(t))) SetWaterClassDependingOnSurroundings(t); } } diff --git a/src/saveload.cpp b/src/saveload.cpp index 008821df6..3b62a3991 100644 --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -34,7 +34,7 @@ #include "table/strings.h" -extern const uint16 SAVEGAME_VERSION = 85; +extern const uint16 SAVEGAME_VERSION = 86; uint16 _sl_version; ///< the major savegame version identifier byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index b5749c4b8..538c68b72 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1837,6 +1837,8 @@ CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (!IsWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE); if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); + if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_304B_SITE_UNSUITABLE); + /* allocate and initialize new station */ Station *st = new Station(tile); if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); @@ -1859,7 +1861,7 @@ CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) st->build_date = _date; - MakeBuoy(tile, st->index); + MakeBuoy(tile, st->index, GetWaterClass(tile)); UpdateStationVirtCoordDirty(st); UpdateStationAcceptance(st, false); @@ -1917,7 +1919,7 @@ static CommandCost RemoveBuoy(Station *st, uint32 flags) /* We have to set the water tile's state to the same state as before the * buoy was placed. Otherwise one could plant a buoy on a canal edge, * remove it and flood the land (if the canal edge is at level 0) */ - MakeWaterOrCanalDependingOnOwner(tile, GetTileOwner(tile)); + MakeWaterKeepingClass(tile, GetTileOwner(tile)); MarkTileDirtyByTile(tile); UpdateStationVirtCoordDirty(st); @@ -1951,7 +1953,7 @@ CommandCost CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) direction = ReverseDiagDir(direction); /* Docks cannot be placed on rapids */ - if (IsRiverTile(tile)) return_cmd_error(STR_304B_SITE_UNSUITABLE); + if (IsWaterTile(tile)) return_cmd_error(STR_304B_SITE_UNSUITABLE); if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR; @@ -1968,6 +1970,9 @@ CommandCost CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (MayHaveBridgeAbove(tile_cur) && IsBridgeAbove(tile_cur)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); + /* Get the water class of the water tile before it is cleared.*/ + WaterClass wc = GetWaterClass(tile_cur); + cost = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(cost)) return CMD_ERROR; @@ -2025,7 +2030,7 @@ CommandCost CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) st->rect.BeforeAddRect(tile, _dock_w_chk[direction], _dock_h_chk[direction], StationRect::ADD_TRY); - MakeDock(tile, st->owner, st->index, direction); + MakeDock(tile, st->owner, st->index, direction, wc); UpdateStationVirtCoordDirty(st); UpdateStationAcceptance(st, false); @@ -2050,7 +2055,7 @@ static CommandCost RemoveDock(Station *st, uint32 flags) if (flags & DC_EXEC) { DoClearSquare(tile1); - MakeWaterOrCanalDependingOnSurroundings(tile2, st->owner); + MakeWaterKeepingClass(tile2, st->owner); st->rect.AfterRemoveTile(st, tile1); st->rect.AfterRemoveTile(st, tile2); @@ -2155,7 +2160,14 @@ static void DrawTile_Station(TileInfo *ti) DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y); } - if (IsCanalBuoyTile(ti->tile)) DrawCanalWater(ti->tile); + if (IsBuoy(ti->tile)) { + /* Draw appropriate water edges */ + switch (GetWaterClass(ti->tile)) { + case WATER_CLASS_SEA: break; + case WATER_CLASS_CANAL: DrawCanalWater(ti->tile, false); break; + case WATER_CLASS_RIVER: DrawRiverWater(ti, false); break; + } + } const DrawTileSeqStruct *dtss; foreach_draw_tile_seq(dtss, t->seq) { diff --git a/src/station_map.h b/src/station_map.h index b4e40ccef..f2a2f86dd 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -7,6 +7,7 @@ #include "rail_map.h" #include "road_map.h" +#include "water_map.h" #include "station.h" #include "rail.h" @@ -155,16 +156,6 @@ static inline bool IsBuoyTile(TileIndex t) 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); @@ -287,18 +278,20 @@ static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section MakeStation(t, o, sid, STATION_AIRPORT, section); } -static inline void MakeBuoy(TileIndex t, StationID sid) +static inline void MakeBuoy(TileIndex t, StationID sid, WaterClass wc) { /* Make the owner of the buoy tile the same as the current owner of the * water tile. In this way, we can reset the owner of the water to its * original state when the buoy gets removed. */ MakeStation(t, GetTileOwner(t), sid, STATION_BUOY, 0); + SetWaterClass(t, wc); } -static inline void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d) +static inline void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d, WaterClass wc) { MakeStation(t, o, sid, STATION_DOCK, d); MakeStation(t + TileOffsByDiagDir(d), o, sid, STATION_DOCK, GFX_DOCK_BASE_WATER_PART + DiagDirToAxis(d)); + SetWaterClass(t + TileOffsByDiagDir(d), wc); } static inline void MakeOilrig(TileIndex t, StationID sid) diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index bb1a0e85c..c380d9452 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -248,7 +248,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p /* retrieve landscape height and ensure it's on land */ tile_start = TileXY(x, y); tile_end = TileXY(sx, sy); - if (IsWaterTile(tile_start) || IsRiverTile(tile_start) || IsWaterTile(tile_end) || IsRiverTile(tile_end)) { + if (IsWaterTile(tile_start) || IsWaterTile(tile_end)) { return_cmd_error(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH); } @@ -373,7 +373,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p switch (GetTileType(tile)) { case MP_WATER: if (!EnsureNoVehicleOnGround(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY); - if (!IsWater(tile) && !IsCoast(tile) && !IsRiver(tile)) goto not_valid_below; + if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below; break; case MP_RAILWAY: @@ -468,7 +468,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 direction = GetInclinedSlopeDirection(start_tileh); if (direction == INVALID_DIAGDIR) return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL); - if (IsRiverTile(start_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); + if (IsWaterTile(start_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return ret; @@ -522,7 +522,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 /* if the command fails from here on we want the end tile to be highlighted */ _build_tunnel_endtile = end_tile; - if (IsRiverTile(end_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); + if (IsWaterTile(end_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); /* slope of end tile must be complementary to the slope of the start tile */ if (end_tileh != ComplementSlope(start_tileh)) { diff --git a/src/water.h b/src/water.h index 94570612c..3eecc15f4 100644 --- a/src/water.h +++ b/src/water.h @@ -11,10 +11,11 @@ bool FloodHalftile(TileIndex t); void ConvertGroundTilesIntoWaterTiles(); void DrawShipDepotSprite(int x, int y, int image); -void DrawCanalWater(TileIndex tile); +void DrawCanalWater(TileIndex tile, bool draw_base); +void DrawRiverWater(const struct TileInfo *ti, bool draw_base); void DrawShoreTile(Slope tileh); -void MakeWaterOrCanalDependingOnOwner(TileIndex tile, Owner o); -void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o); +void MakeWaterKeepingClass(TileIndex tile, Owner o); +void SetWaterClassDependingOnSurroundings(TileIndex t); #endif /* WATER_H */ diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 55e297f38..5f73b526c 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -101,21 +101,16 @@ static void MarkCanalsAndRiversAroundDirty(TileIndex tile) * @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); @@ -123,6 +118,7 @@ void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o) 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: @@ -138,10 +134,13 @@ void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o) 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); } } @@ -162,11 +161,19 @@ CommandCost CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 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); @@ -181,8 +188,8 @@ CommandCost CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 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(); @@ -191,12 +198,14 @@ CommandCost CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 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; } } @@ -216,8 +225,8 @@ static CommandCost RemoveShipDepot(TileIndex tile, uint32 flags) /* 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); } @@ -237,6 +246,8 @@ static CommandCost DoBuildShiplift(TileIndex tile, DiagDirection dir, uint32 fla 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) { @@ -244,6 +255,8 @@ static CommandCost DoBuildShiplift(TileIndex tile, DiagDirection dir, uint32 fla } /* 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) { @@ -257,7 +270,7 @@ static CommandCost DoBuildShiplift(TileIndex tile, DiagDirection dir, uint32 fla } 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); @@ -280,8 +293,10 @@ static CommandCost RemoveShiplift(TileIndex tile, uint32 flags) 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); } @@ -301,7 +316,7 @@ CommandCost CmdBuildLock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (dir == INVALID_DIAGDIR) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); /* Disallow building of locks on river rapids */ - if (IsRiverTile(tile)) return_cmd_error(STR_0239_SITE_UNSUITABLE); + if (IsWaterTile(tile)) return_cmd_error(STR_0239_SITE_UNSUITABLE); return DoBuildShiplift(tile, dir, flags); } @@ -379,7 +394,6 @@ static CommandCost ClearTile_Water(TileIndex tile, byte flags) { 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. */ @@ -472,7 +486,7 @@ static bool IsWateredTile(TileIndex tile, Direction from) } return false; - case MP_STATION: return IsOilRig(tile) || IsDock(tile) || IsBuoy(tile); + case MP_STATION: return 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; } @@ -518,9 +532,17 @@ static void DrawWaterEdges(SpriteID base, TileIndex tile) } } +/** 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; @@ -566,7 +588,7 @@ static void DrawWaterStuff(const TileInfo *ti, const WaterDrawTileStruct *wdts, } } -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); @@ -592,7 +614,7 @@ static void DrawRiverWater(const TileInfo *ti) } } - DrawGroundSprite(image, PAL_NONE); + if (draw_base) DrawGroundSprite(image, PAL_NONE); /* Draw river edges if available. */ if (edges_base > 48) DrawWaterEdges(edges_base, ti->tile); @@ -619,8 +641,11 @@ static void DrawTile_Water(TileInfo *ti) { 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; @@ -637,11 +662,6 @@ static void DrawTile_Water(TileInfo *ti) 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; } } @@ -680,7 +700,6 @@ static void GetTileDesc_Water(TileIndex tile, TileDesc *td) { switch (GetWaterTileType(tile)) { case WATER_TILE_CLEAR: - case WATER_TILE_RIVER: if (!IsCanal(tile)) { td->str = STR_3804_WATER; } else { @@ -842,7 +861,7 @@ static FloodingBehaviour GetFloodingBehaviour(TileIndex tile) Slope tileh = GetTileSlope(tile, NULL); 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: @@ -855,7 +874,7 @@ static FloodingBehaviour GetFloodingBehaviour(TileIndex tile) 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; return FLOOD_NONE; @@ -1073,11 +1092,10 @@ static uint32 GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint 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) { diff --git a/src/water_map.h b/src/water_map.h index d7d0b0ba8..b9bb4344a 100644 --- a/src/water_map.h +++ b/src/water_map.h @@ -10,7 +10,12 @@ enum WaterTileType { WATER_TILE_COAST, WATER_TILE_LOCK, WATER_TILE_DEPOT, - WATER_TILE_RIVER, +}; + +enum WaterClass { + WATER_CLASS_SEA, + WATER_CLASS_CANAL, + WATER_CLASS_RIVER, }; enum DepotPart { @@ -32,13 +37,24 @@ static inline WaterTileType GetWaterTileType(TileIndex t) if (_m[t].m5 == 0) return WATER_TILE_CLEAR; if (_m[t].m5 == 1) return WATER_TILE_COAST; - if (_m[t].m5 == 2) return WATER_TILE_RIVER; if (IsInsideMM(_m[t].m5, LOCK_MIDDLE, LOCK_END)) return WATER_TILE_LOCK; assert(IsInsideMM(_m[t].m5, DEPOT_NORTH, DEPOT_END)); return WATER_TILE_DEPOT; } +static inline WaterClass GetWaterClass(TileIndex t) +{ + assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION)); + return (WaterClass)GB(_m[t].m3, 0, 2); +} + +static inline void SetWaterClass(TileIndex t, WaterClass wc) +{ + assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION)); + SB(_m[t].m3, 0, 2, wc); +} + /** IsWater return true if any type of clear water like ocean, river, canal */ static inline bool IsWater(TileIndex t) { @@ -47,24 +63,17 @@ static inline bool IsWater(TileIndex t) 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; + return IsWater(t) && GetWaterClass(t) == WATER_CLASS_SEA; } static inline bool IsCanal(TileIndex t) { - return GetWaterTileType(t) == WATER_TILE_CLEAR && GetTileOwner(t) != OWNER_WATER; + return IsWater(t) && GetWaterClass(t) == WATER_CLASS_CANAL; } static inline bool IsRiver(TileIndex t) { - return GetWaterTileType(t) == WATER_TILE_RIVER; + return IsWater(t) && GetWaterClass(t) == WATER_CLASS_RIVER; } static inline bool IsWaterTile(TileIndex t) @@ -72,9 +81,9 @@ static inline bool IsWaterTile(TileIndex t) return IsTileType(t, MP_WATER) && IsWater(t); } -static inline bool IsRiverTile(TileIndex t) +static inline bool IsCoast(TileIndex t) { - return IsTileType(t, MP_WATER) && IsRiver(t); + return GetWaterTileType(t) == WATER_TILE_COAST; } static inline TileIndex GetOtherShipDepotTile(TileIndex t) @@ -124,7 +133,7 @@ static inline void MakeWater(TileIndex t) SetTileType(t, MP_WATER); SetTileOwner(t, OWNER_WATER); _m[t].m2 = 0; - _m[t].m3 = 0; + _m[t].m3 = WATER_CLASS_SEA; _m[t].m4 = 0; _m[t].m5 = 0; } @@ -144,9 +153,9 @@ static inline void MakeRiver(TileIndex t, uint8 random_bits) SetTileType(t, MP_WATER); SetTileOwner(t, OWNER_WATER); _m[t].m2 = 0; - _m[t].m3 = 0; + _m[t].m3 = WATER_CLASS_RIVER; _m[t].m4 = random_bits; - _m[t].m5 = 2; + _m[t].m5 = 0; } static inline void MakeCanal(TileIndex t, Owner o, uint8 random_bits) @@ -155,38 +164,38 @@ static inline void MakeCanal(TileIndex t, Owner o, uint8 random_bits) SetTileType(t, MP_WATER); SetTileOwner(t, o); _m[t].m2 = 0; - _m[t].m3 = 0; + _m[t].m3 = WATER_CLASS_CANAL; _m[t].m4 = random_bits; _m[t].m5 = 0; } -static inline void MakeShipDepot(TileIndex t, Owner o, DepotPart base, Axis a, Owner original_owner) +static inline void MakeShipDepot(TileIndex t, Owner o, DepotPart base, Axis a, WaterClass original_water_class, Owner original_owner) { SetTileType(t, MP_WATER); SetTileOwner(t, o); _m[t].m2 = 0; - _m[t].m3 = 0; + _m[t].m3 = original_water_class; _m[t].m4 = original_owner; _m[t].m5 = base + a * 2; } -static inline void MakeLockTile(TileIndex t, Owner o, byte section) +static inline void MakeLockTile(TileIndex t, Owner o, byte section, WaterClass original_water_class) { SetTileType(t, MP_WATER); SetTileOwner(t, o); _m[t].m2 = 0; - _m[t].m3 = 0; + _m[t].m3 = original_water_class; _m[t].m4 = 0; _m[t].m5 = section; } -static inline void MakeLock(TileIndex t, Owner o, DiagDirection d) +static inline void MakeLock(TileIndex t, Owner o, DiagDirection d, WaterClass wc_lower, WaterClass wc_upper) { TileIndexDiff delta = TileOffsByDiagDir(d); - MakeLockTile(t, o, LOCK_MIDDLE + d); - MakeLockTile(t - delta, o, LOCK_LOWER + d); - MakeLockTile(t + delta, o, LOCK_UPPER + d); + MakeLockTile(t, o, LOCK_MIDDLE + d, WATER_CLASS_CANAL); + MakeLockTile(t - delta, o, LOCK_LOWER + d, wc_lower); + MakeLockTile(t + delta, o, LOCK_UPPER + d, wc_upper); } #endif /* WATER_MAP_H */ -- cgit v1.2.3-70-g09d2