diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -101,21 +101,16 @@ static void MarkCanalsAndRiversAroundDir * @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 MakeWaterOrCanalDependingOnSurround 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 MakeWaterOrCanalDependingOnSurround 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 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 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 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(TileI /* 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(TileI 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(TileI } /* 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(TileI } 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(TileIn 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, 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(TileI { 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 } 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 } } +/** 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 TileInf } } -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 TileInf } } - 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 { 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 GetFloodingBeha 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 GetFloodingBeha 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(T 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) {