(svn r13838) -Codechange: Make industry tiles aware of WaterClasses.
authorfrosch
Sat, 26 Jul 2008 16:14:10 +0000
changeset 9718 4b7468076d31
parent 9717 b7806a165a75
child 9719 15e207edea1a
(svn r13838) -Codechange: Make industry tiles aware of WaterClasses.
docs/landscape.html
docs/landscape_grid.html
src/industry_cmd.cpp
src/industry_map.h
src/newgrf_industrytiles.cpp
src/openttd.cpp
src/saveload.cpp
src/station_cmd.cpp
src/station_map.h
src/water.h
src/water_cmd.cpp
src/water_map.h
--- a/docs/landscape.html	Sat Jul 26 14:58:08 2008 +0000
+++ b/docs/landscape.html	Sat Jul 26 16:14:10 2008 +0000
@@ -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>
--- a/docs/landscape_grid.html	Sat Jul 26 14:58:08 2008 +0000
+++ b/docs/landscape_grid.html	Sat Jul 26 16:14:10 2008 +0000
@@ -293,7 +293,7 @@
       <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>
--- a/src/industry_cmd.cpp	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/industry_cmd.cpp	Sat Jul 26 16:14:10 2008 +0000
@@ -147,7 +147,8 @@
 	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 @@
 	/* 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 @@
 	IndustryGfx newgfx;
 	IndustryGfx gfx;
 
+	if (IsIndustryTileOnWater(tile)) TileLoop_Water(tile);
+
 	TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
 
 	if (!IsIndustryCompleted(tile)) {
@@ -748,14 +757,6 @@
 	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 @@
 			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);
--- a/src/industry_map.h	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/industry_map.h	Sat Jul 26 16:14:10 2008 +0000
@@ -7,7 +7,7 @@
 
 #include "industry.h"
 #include "tile_map.h"
-
+#include "water_map.h"
 
 
 /**
@@ -155,13 +155,24 @@
 }
 
 /**
+ * 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 @@
 	_m[t].m4 = 0;
 	SetIndustryGfx(t, gfx);
 	_me[t].m7 = random;
+	SetWaterClass(t, wc);
 }
 
 /**
--- a/src/newgrf_industrytiles.cpp	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/newgrf_industrytiles.cpp	Sat Jul 26 16:14:10 2008 +0000
@@ -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 @@
 
 	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;
--- a/src/openttd.cpp	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/openttd.cpp	Sat Jul 26 16:14:10 2008 +0000
@@ -2340,8 +2340,8 @@
 		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 @@
 		}
 	}
 
+	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();
--- a/src/saveload.cpp	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/saveload.cpp	Sat Jul 26 16:14:10 2008 +0000
@@ -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
 
--- a/src/station_cmd.cpp	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/station_cmd.cpp	Sat Jul 26 16:14:10 2008 +0000
@@ -2932,7 +2932,8 @@
 
 	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 @@
 {
 	Station *st = GetStationByTile(tile);
 
-	MakeWater(tile);
+	MakeWaterKeepingClass(tile, OWNER_NONE);
+	MarkTileDirtyByTile(tile);
 
 	st->dock_tile = 0;
 	st->airport_tile = 0;
--- a/src/station_map.h	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/station_map.h	Sat Jul 26 16:14:10 2008 +0000
@@ -313,9 +313,10 @@
 	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 */
--- a/src/water.h	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/water.h	Sat Jul 26 16:14:10 2008 +0000
@@ -15,6 +15,6 @@
 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 */
--- a/src/water_cmd.cpp	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/water_cmd.cpp	Sat Jul 26 16:14:10 2008 +0000
@@ -109,10 +109,20 @@
  * 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 @@
 		}
 	}
 
+	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 @@
 
 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));
 
-	switch (GetWaterClass(tile)) {
+	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;
+
+	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 @@
 			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 @@
 		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 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 @@
 			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;
--- a/src/water_map.h	Sat Jul 26 14:58:08 2008 +0000
+++ b/src/water_map.h	Sat Jul 26 16:14:10 2008 +0000
@@ -16,6 +16,7 @@
 	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 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 */