diff options
-rw-r--r-- | docs/landscape.html | 1 | ||||
-rw-r--r-- | docs/landscape_grid.html | 2 | ||||
-rw-r--r-- | src/industry_cmd.cpp | 25 | ||||
-rw-r--r-- | src/industry_map.h | 16 | ||||
-rw-r--r-- | src/newgrf_industrytiles.cpp | 11 | ||||
-rw-r--r-- | src/openttd.cpp | 20 | ||||
-rw-r--r-- | src/saveload.cpp | 2 | ||||
-rw-r--r-- | src/station_cmd.cpp | 6 | ||||
-rw-r--r-- | src/station_map.h | 3 | ||||
-rw-r--r-- | src/water.h | 2 | ||||
-rw-r--r-- | src/water_cmd.cpp | 45 | ||||
-rw-r--r-- | src/water_map.h | 13 |
12 files changed, 110 insertions, 36 deletions
diff --git a/docs/landscape.html b/docs/landscape.html index 9493f35a2..9a92ba9c0 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -1035,6 +1035,7 @@ <ul> <li>m1 bit 7: clear = under construction <ul> + <li>m1 bits 6..5 : Water class (sea, canal, river or land) <li>m1 bits 3..2: construction counter, for buildings under construction incremented on every periodic tile processing</li> <li>m1 bits 1..0: stage of construction (<tt>3</tt> = completed), incremented when the construction counter wraps around<br> the meaning is different for some animated tiles which are never under construction (types <tt>01</tt>, <tt>1E</tt>..<tt>20</tt>, <tt>30</tt>, <tt>58</tt>; see above)</li> diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index f47b7f43a..291447f30 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -293,7 +293,7 @@ the array so you can quickly see what is used and what is not. <td>8</td> <td class="caption">industry</td> <td class="bits">XXXX XXXX</td> - <td class="bits">X<span class="free">OOO</span> <span class="abuse"> + <td class="bits">XXX<span class="free">O</span> <span class="abuse"> XXXX</span></td> <td class="bits">XXXX XXXX XXXX XXXX</td> <td class="bits">XXXX XXXX</td> diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 88d85486e..3d6f4bbd9 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -147,7 +147,8 @@ Industry::~Industry() BEGIN_TILE_LOOP(tile_cur, this->width, this->height, this->xy); if (IsTileType(tile_cur, MP_INDUSTRY)) { if (GetIndustryIndex(tile_cur) == this->index) { - DoClearSquare(tile_cur); + /* MakeWaterKeepingClass() can also handle 'land' */ + MakeWaterKeepingClass(tile_cur, OWNER_NONE); } } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) { DeleteOilRig(tile_cur); @@ -300,7 +301,13 @@ static void DrawTile_Industry(TileInfo *ti) /* DrawFoundation() modifes ti->z and ti->tileh */ if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED); - DrawGroundSprite(image, pal); + /* If the ground sprite is the default flat water sprite, draw also canal/river borders. + * Do not do this if the tile's WaterClass is 'land'. */ + if (image == SPR_FLAT_WATER_TILE && IsIndustryTileOnWater(ti->tile)) { + DrawWaterClassGround(ti); + } else { + DrawGroundSprite(image, pal); + } /* If industries are transparent and invisible, do not draw the upper part */ if (IsInvisibilitySet(TO_INDUSTRIES)) return; @@ -724,6 +731,8 @@ static void TileLoop_Industry(TileIndex tile) IndustryGfx newgfx; IndustryGfx gfx; + if (IsIndustryTileOnWater(tile)) TileLoop_Water(tile); + TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP); if (!IsIndustryCompleted(tile)) { @@ -748,14 +757,6 @@ static void TileLoop_Industry(TileIndex tile) gfx = GetIndustryGfx(tile); switch (gfx) { - case GFX_OILRIG_1: // coast line at oilrigs - case GFX_OILRIG_2: - case GFX_OILRIG_3: - case GFX_OILRIG_4: - case GFX_OILRIG_5: - TileLoop_Water(tile); - break; - case GFX_COAL_MINE_TOWER_NOT_ANIMATED: case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: @@ -1548,9 +1549,11 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const Ind size = it->ti.y; if (size > i->height)i->height = size; + WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID); + DoCommand(cur_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); - MakeIndustry(cur_tile, i->index, it->gfx, Random()); + MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc); if (_generating_world) { SetIndustryConstructionCounter(cur_tile, 3); diff --git a/src/industry_map.h b/src/industry_map.h index 77cab8920..04be3513a 100644 --- a/src/industry_map.h +++ b/src/industry_map.h @@ -7,7 +7,7 @@ #include "industry.h" #include "tile_map.h" - +#include "water_map.h" /** @@ -155,13 +155,24 @@ static inline void SetIndustryGfx(TileIndex t, IndustryGfx gfx) } /** + * Tests if the industry tile was built on water. + * @param t the industry tile + * @return true iff on water + */ +static inline bool IsIndustryTileOnWater(TileIndex t) +{ + assert(IsTileType(t, MP_INDUSTRY)); + return (GetWaterClass(t) != WATER_CLASS_INVALID); +} + +/** * Make the given tile an industry tile * @param t the tile to make an industry tile * @param index the industry this tile belongs to * @param gfx the graphics to use for the tile * @param random the random value */ -static inline void MakeIndustry(TileIndex t, IndustryID index, IndustryGfx gfx, uint8 random) +static inline void MakeIndustry(TileIndex t, IndustryID index, IndustryGfx gfx, uint8 random, WaterClass wc) { SetTileType(t, MP_INDUSTRY); _m[t].m1 = 0; @@ -170,6 +181,7 @@ static inline void MakeIndustry(TileIndex t, IndustryID index, IndustryGfx gfx, _m[t].m4 = 0; SetIndustryGfx(t, gfx); _me[t].m7 = random; + SetWaterClass(t, wc); } /** diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 7f0aa2b8b..63c7cbf34 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -25,6 +25,7 @@ #include "town.h" #include "command_func.h" #include "animated_tile_func.h" +#include "water.h" #include "table/sprites.h" #include "table/strings.h" @@ -185,7 +186,15 @@ void IndustryDrawTileLayout(const TileInfo *ti, const SpriteGroup *group, byte r if (IS_CUSTOM_SPRITE(image)) image += stage; - if (GB(image, 0, SPRITE_WIDTH) != 0) DrawGroundSprite(image, pal); + if (GB(image, 0, SPRITE_WIDTH) != 0) { + /* If the ground sprite is the default flat water sprite, draw also canal/river borders + * Do not do this if the tile's WaterClass is 'land'. */ + if (image == SPR_FLAT_WATER_TILE && IsIndustryTileOnWater(ti->tile)) { + DrawWaterClassGround(ti); + } else { + DrawGroundSprite(image, pal); + } + } foreach_draw_tile_seq(dtss, dts->seq) { if (GB(dtss->image.sprite, 0, SPRITE_WIDTH) == 0) continue; diff --git a/src/openttd.cpp b/src/openttd.cpp index 31bfeb33d..29c230c8e 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -2340,8 +2340,8 @@ bool AfterLoadGame() for (TileIndex t = 0; t < map_size; t++) { if (GetTileSlope(t, NULL) != SLOPE_FLAT) continue; - if (IsTileType(t, MP_WATER) && IsLock(t)) SetWaterClassDependingOnSurroundings(t); - if (IsTileType(t, MP_STATION) && (IsDock(t) || IsBuoy(t))) SetWaterClassDependingOnSurroundings(t); + if (IsTileType(t, MP_WATER) && IsLock(t)) SetWaterClassDependingOnSurroundings(t, false); + if (IsTileType(t, MP_STATION) && (IsDock(t) || IsBuoy(t))) SetWaterClassDependingOnSurroundings(t, false); } } @@ -2438,6 +2438,22 @@ bool AfterLoadGame() } } + if (CheckSavegameVersion(99)) { + /* Set newly introduced WaterClass of industry tiles */ + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_STATION) && IsOilRig(t)) { + SetWaterClassDependingOnSurroundings(t, true); + } + if (IsTileType(t, MP_INDUSTRY)) { + if ((GetIndustrySpec(GetIndustryType(t))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) { + SetWaterClassDependingOnSurroundings(t, true); + } else { + SetWaterClass(t, WATER_CLASS_INVALID); + } + } + } + } + GamelogPrintDebug(1); return InitializeWindowsAndCaches(); diff --git a/src/saveload.cpp b/src/saveload.cpp index dd0824582..640ebcc7f 100644 --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -36,7 +36,7 @@ #include "table/strings.h" -extern const uint16 SAVEGAME_VERSION = 98; +extern const uint16 SAVEGAME_VERSION = 99; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 0fc0a14df..67afd5a1d 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2932,7 +2932,8 @@ void BuildOilRig(TileIndex tile) st->string_id = GenerateStationName(st, tile, STATIONNAMING_OILRIG); - MakeOilrig(tile, st->index); + assert(IsTileType(tile, MP_INDUSTRY)); + MakeOilrig(tile, st->index, GetWaterClass(tile)); st->owner = OWNER_NONE; st->airport_flags = 0; @@ -2967,7 +2968,8 @@ void DeleteOilRig(TileIndex tile) { Station *st = GetStationByTile(tile); - MakeWater(tile); + MakeWaterKeepingClass(tile, OWNER_NONE); + MarkTileDirtyByTile(tile); st->dock_tile = 0; st->airport_tile = 0; diff --git a/src/station_map.h b/src/station_map.h index 0ec6797dc..7422a32e5 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -313,9 +313,10 @@ static inline void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d SetWaterClass(t + TileOffsByDiagDir(d), wc); } -static inline void MakeOilrig(TileIndex t, StationID sid) +static inline void MakeOilrig(TileIndex t, StationID sid, WaterClass wc) { MakeStation(t, OWNER_NONE, sid, STATION_OILRIG, 0); + SetWaterClass(t, wc); } #endif /* STATION_MAP_H */ diff --git a/src/water.h b/src/water.h index 2ed54856b..e54d2e1ea 100644 --- a/src/water.h +++ b/src/water.h @@ -15,6 +15,6 @@ void DrawWaterClassGround(const struct TileInfo *ti); void DrawShoreTile(Slope tileh); void MakeWaterKeepingClass(TileIndex tile, Owner o); -void SetWaterClassDependingOnSurroundings(TileIndex t); +void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_water_class); #endif /* WATER_H */ diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index b72b0a9cf..dd90530ed 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -109,10 +109,20 @@ static void MarkCanalsAndRiversAroundDirty(TileIndex tile) * whether the tile used to be canal or 'normal' water. * @param t the tile to change. * @param o the owner of the new tile. + * @param include_invalid_water_class Also consider WATER_CLASS_INVALID, i.e. industry tiles on land */ -void SetWaterClassDependingOnSurroundings(TileIndex t) +void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_water_class) { - assert(GetTileSlope(t, NULL) == SLOPE_FLAT); + /* If the slope is not flat, we always assume 'land' (if allowed). Also for one-corner-raised-shores. + * Note: Wrt. autosloping under industry tiles this is the most fool-proof behaviour. */ + if (GetTileSlope(t, NULL) != SLOPE_FLAT) { + if (include_invalid_water_class) { + SetWaterClass(t, WATER_CLASS_INVALID); + return; + } else { + NOT_REACHED(); + } + } /* Mark tile dirty in all cases */ MarkTileDirtyByTile(t); @@ -158,6 +168,11 @@ void SetWaterClassDependingOnSurroundings(TileIndex t) } } + if (!has_water && !has_canal && !has_river && include_invalid_water_class) { + SetWaterClass(t, WATER_CLASS_INVALID); + return; + } + if (has_river && !has_canal) { SetWaterClass(t, WATER_CLASS_RIVER); } else if (has_canal || !has_water) { @@ -219,12 +234,21 @@ CommandCost CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 void MakeWaterKeepingClass(TileIndex tile, Owner o) { - assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile)))); + assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile) || IsOilRig(tile))) || IsTileType(tile, MP_INDUSTRY)); + + WaterClass wc = GetWaterClass(tile); + + /* Autoslope might turn an originally canal or river tile into land */ + uint z; + if (GetTileSlope(tile, &z) != SLOPE_FLAT) wc = WATER_CLASS_INVALID; - switch (GetWaterClass(tile)) { + if (wc == WATER_CLASS_SEA && z > 0) wc = WATER_CLASS_CANAL; + + switch (wc) { case WATER_CLASS_SEA: MakeWater(tile); break; case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break; case WATER_CLASS_RIVER: MakeRiver(tile, Random()); break; + default: DoClearSquare(tile); break; } } @@ -512,7 +536,7 @@ static bool IsWateredTile(TileIndex tile, Direction from) return false; 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; + case MP_INDUSTRY: return IsIndustryTileOnWater(tile); case MP_TUNNELBRIDGE: return GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER && ReverseDiagDir(GetTunnelBridgeDirection(tile)) == DirToDiagDir(from); default: return false; } @@ -671,6 +695,7 @@ void DrawWaterClassGround(const TileInfo *ti) { case WATER_CLASS_SEA: DrawSeaWater(ti->tile); break; case WATER_CLASS_CANAL: DrawCanalWater(ti->tile); break; case WATER_CLASS_RIVER: DrawRiverWater(ti); break; + default: NOT_REACHED(); } } @@ -882,9 +907,9 @@ static void FloodVehicle(Vehicle *v) */ static FloodingBehaviour GetFloodingBehaviour(TileIndex tile) { - /* FLOOD_ACTIVE: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile + /* FLOOD_ACTIVE: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile, sea-water-industries, sea-oilrigs * FLOOD_DRYUP: coast with more than one corner raised, coast with rail-track, coast with trees - * FLOOD_PASSIVE: oilrig, water-industries + * FLOOD_PASSIVE: (not used) * FLOOD_NONE: canals, rivers, everything else */ switch (GetTileType(tile)) { @@ -906,13 +931,13 @@ static FloodingBehaviour GetFloodingBehaviour(TileIndex tile) return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE); case MP_STATION: - if (IsBuoy(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT)) { + if (IsBuoy(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsOilRig(tile)) { return (GetWaterClass(tile) == WATER_CLASS_SEA ? FLOOD_ACTIVE : FLOOD_NONE); } - return (IsOilRig(tile) ? FLOOD_PASSIVE : FLOOD_NONE); + return FLOOD_NONE; case MP_INDUSTRY: - return ((GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0 ? FLOOD_PASSIVE : FLOOD_NONE); + return ((IsIndustryTileOnWater(tile) && GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE); default: return FLOOD_NONE; diff --git a/src/water_map.h b/src/water_map.h index 94e805342..a0faab036 100644 --- a/src/water_map.h +++ b/src/water_map.h @@ -16,6 +16,7 @@ enum WaterClass { WATER_CLASS_SEA, WATER_CLASS_CANAL, WATER_CLASS_RIVER, + WATER_CLASS_INVALID, ///< Used for industry tiles on land (also for oilrig if newgrf says so) }; enum DepotPart { @@ -45,14 +46,18 @@ static inline WaterTileType GetWaterTileType(TileIndex t) static inline WaterClass GetWaterClass(TileIndex t) { - assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION)); - return (WaterClass)GB(_m[t].m3, 0, 2); + assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION) || IsTileType(t, MP_INDUSTRY)); + return (WaterClass)(IsTileType(t, MP_INDUSTRY) ? GB(_m[t].m1, 5, 2) : 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); + assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION) || IsTileType(t, MP_INDUSTRY)); + if (IsTileType(t, MP_INDUSTRY)) { + SB(_m[t].m1, 5, 2, wc); + } else { + SB(_m[t].m3, 0, 2, wc); + } } /** IsWater return true if any type of clear water like ocean, river, canal */ |