changeset 18332:d1598ff3329e draft

(svn r23168) -Feature [FS#1824]: always draw fences around field tiles
author yexo <yexo@openttd.org>
date Tue, 08 Nov 2011 19:48:47 +0000 (2011-11-08)
parents 91df70e03ed5
children 672137d1ba54
files docs/landscape.html docs/landscape_grid.html src/clear_cmd.cpp src/clear_func.h src/clear_map.h src/industry_cmd.cpp src/saveload/afterload.cpp src/table/clear_land.h src/tree_cmd.cpp
diffstat 9 files changed, 168 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/docs/landscape.html
+++ b/docs/landscape.html
@@ -106,6 +106,7 @@
     <ul>
      <li>m1 bits 4..0: <a href="#OwnershipInfo">owner</a> of the tile (normally <tt>10</tt>)</li>
      <li>m2: see fields</li>
+     <li>m3 bits 7..5: type of hedge on NE border of the tile</li>
      <li>m3 bits 3..0: see fields</li>
      <li>m3 bit 4: set if the tile is covered with snow</li>
      <li>m4 bits 7..5: type of hedge on the SW border of the tile (1 through 6, or 0=none)</li>
@@ -196,6 +197,7 @@
       </table>
      </li>
      <li>m6 bits 7..6 : Possibility of a bridge above, in the <a href="#bridge_direction">direction specified</a></li>
+     <li>m6 bits 4..2: type of hedge on NW border of the tile</li>
      <li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li>
     </ul>
    </td>
@@ -816,8 +818,6 @@
       </table>
       <small>Note: the actually displayed set of trees depends on both type and number of trees</small>
      </li>
-     <li>m4 bits 7..5: type of hedge on the SW border of the tile (1 through 6, or 0=none)</li>
-     <li>m4 bits 4..2: type of hedge on the SE border of the tile (1 through 6, or 0=none)</li>
      <li>m5 bits 7..6: number of trees minus one</li>
      <li>m5 bits 2..0: growth status:
       <table border="0">
--- a/docs/landscape_grid.html
+++ b/docs/landscape_grid.html
@@ -68,10 +68,10 @@
       <td class="bits">XXXX XXXX</td>
       <td class="bits"><span class="free">OOO</span><span class="option">~ ~~~~</span></td>
       <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
-      <td class="bits"><span class="free">OOO</span>X <span class="free">OOOO</span></td>
+      <td class="bits">XXXX <span class="free">OOOO</span></td>
       <td class="bits">XXXX XX<span class="free">OO</span></td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits">XX<span class="free">O</span>X XXXX</td>
       <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
@@ -79,10 +79,10 @@
       <td class="bits">-inherit-</td>
       <td class="bits">-inherit-</td>
       <td class="bits">XXXX XXXX XXXX XXXX</td>
-      <td class="bits"><span class="free">OOO</span>X XXXX</td>
+      <td class="bits">XXXX XXXX</td>
       <td class="bits">-inherit-</td>
       <td class="bits">-inherit-</td>
-      <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits">XX<span class="free">O</span>X XXXX</td>
       <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
@@ -172,7 +172,7 @@
       <td class="bits"><span class="free">OOO</span><span class="option">~ ~~~~</span></td>
       <td class="bits"><span class="free">OOOO OOO</span>X XXXX XXXX</td>
       <td class="bits"><span class="option">~~</span>XX XXXX</td>
-      <td class="bits">XXXX XX<span class="free">OO</span></td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits">XX<span class="free">OO O</span>XXX</td>
       <td class="bits"><span class="free">OOOO OO</span>XX</td>
       <td class="bits"><span class="free">OOOO OOOO</span></td>
--- a/src/clear_cmd.cpp
+++ b/src/clear_cmd.cpp
@@ -61,22 +61,44 @@
 	}
 }
 
-void DrawClearLandFence(const TileInfo *ti)
+static void DrawClearLandFence(const TileInfo *ti)
 {
+	/* combine fences into one sprite object */
+	StartSpriteCombine();
+
+	int maxz = GetSlopeMaxPixelZ(ti->tileh);
+
+	bool fence_nw = GetFenceNW(ti->tile) != 0;
+	if (fence_nw) {
+		int z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
+		SpriteID sprite = _clear_land_fence_sprites[GetFenceNW(ti->tile) - 1] + _fence_mod_by_tileh_nw[ti->tileh];
+		AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y - 15, 16, 31, maxz - z + 4, ti->z + z, false, 0, 15, -z);
+	}
+
+	bool fence_ne = GetFenceNE(ti->tile) != 0;
+	if (fence_ne) {
+		int z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
+		SpriteID sprite = _clear_land_fence_sprites[GetFenceNE(ti->tile) - 1] + _fence_mod_by_tileh_ne[ti->tileh];
+		AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x - 15, ti->y, 31, 16, maxz - z + 4, ti->z + z, false, 15, 0, -z);
+	}
+
 	bool fence_sw = GetFenceSW(ti->tile) != 0;
 	bool fence_se = GetFenceSE(ti->tile) != 0;
 
-	if (!fence_sw && !fence_se) return;
-
-	int z = GetSlopePixelZInCorner(ti->tileh, CORNER_S);
+	if (fence_sw || fence_se) {
+		int z = GetSlopePixelZInCorner(ti->tileh, CORNER_S);
 
-	if (fence_sw) {
-		DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh_sw[ti->tileh], PAL_NONE, 0, 0, z);
-	}
+		if (fence_sw) {
+			SpriteID sprite = _clear_land_fence_sprites[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh_sw[ti->tileh];
+			AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
+		}
 
-	if (fence_se) {
-		DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_se[ti->tileh], PAL_NONE, 0, 0, z);
+		if (fence_se) {
+			SpriteID sprite = _clear_land_fence_sprites[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_se[ti->tileh];
+			AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
+		}
 	}
+	EndSpriteCombine();
 }
 
 static void DrawTile_Clear(TileInfo *ti)
@@ -96,6 +118,7 @@
 
 		case CLEAR_FIELDS:
 			DrawGroundSprite(_clear_land_sprites_farmland[GetFieldType(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
+			DrawClearLandFence(ti);
 			break;
 
 		case CLEAR_SNOW:
@@ -104,7 +127,6 @@
 			break;
 	}
 
-	DrawClearLandFence(ti);
 	DrawBridgeMiddle(ti);
 }
 
@@ -121,35 +143,33 @@
 	return FOUNDATION_NONE;
 }
 
-void TileLoopClearHelper(TileIndex tile)
+static void UpdateFences(TileIndex tile)
 {
-	bool self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
+	assert(IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
 	bool dirty = false;
 
 	bool neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
-	if (GetFenceSW(tile) == 0) {
-		if (self != neighbour) {
-			SetFenceSW(tile, 3);
-			dirty = true;
-		}
-	} else {
-		if (self == 0 && neighbour == 0) {
-			SetFenceSW(tile, 0);
-			dirty = true;
-		}
+	if (!neighbour && GetFenceSW(tile) == 0) {
+		SetFenceSW(tile, 3);
+		dirty = true;
 	}
 
 	neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
-	if (GetFenceSE(tile) == 0) {
-		if (self != neighbour) {
-			SetFenceSE(tile, 3);
-			dirty = true;
-		}
-	} else {
-		if (self == 0 && neighbour == 0) {
-			SetFenceSE(tile, 0);
-			dirty = true;
-		}
+	if (!neighbour && GetFenceSE(tile) == 0) {
+		SetFenceSE(tile, 3);
+		dirty = true;
+	}
+
+	neighbour = (IsTileType(TILE_ADDXY(tile, -1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, -1, 0), CLEAR_FIELDS));
+	if (!neighbour && GetFenceNE(tile) == 0) {
+		SetFenceNE(tile, 3);
+		dirty = true;
+	}
+
+	neighbour = (IsTileType(TILE_ADDXY(tile, 0, -1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, -1), CLEAR_FIELDS));
+	if (!neighbour && GetFenceNW(tile) == 0) {
+		SetFenceNW(tile, 3);
+		dirty = true;
 	}
 
 	if (dirty) MarkTileDirtyByTile(tile);
@@ -239,7 +259,6 @@
 			return;
 		}
 	}
-	TileLoopClearHelper(tile);
 	AmbientSoundEffectCallback(tile);
 
 	switch (_settings_game.game_creation.landscape) {
@@ -264,8 +283,8 @@
 			}
 			break;
 
-		case CLEAR_FIELDS: {
-			uint field_type;
+		case CLEAR_FIELDS:
+			UpdateFences(tile);
 
 			if (_game_mode == GM_EDITOR) return;
 
@@ -280,12 +299,11 @@
 				/* This farmfield is no longer farmfield, so make it grass again */
 				MakeClear(tile, CLEAR_GRASS, 2);
 			} else {
-				field_type = GetFieldType(tile);
+				uint field_type = GetFieldType(tile);
 				field_type = (field_type < 8) ? field_type + 1 : 0;
 				SetFieldType(tile, field_type);
 			}
 			break;
-		}
 
 		default:
 			return;
--- a/src/clear_func.h
+++ b/src/clear_func.h
@@ -16,7 +16,5 @@
 
 void DrawHillyLandTile(const TileInfo *ti);
 void DrawClearLandTile(const TileInfo *ti, byte set);
-void DrawClearLandFence(const TileInfo *ti);
-void TileLoopClearHelper(TileIndex tile);
 
 #endif /* CLEAR_FUNC_H */
--- a/src/clear_map.h
+++ b/src/clear_map.h
@@ -216,12 +216,12 @@
 /**
  * Is there a fence at the south eastern border?
  * @param t the tile to check for fences
- * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)
+ * @pre IsClearGround(t, CLEAR_FIELDS)
  * @return 0 if there is no fence, otherwise the fence type
  */
 static inline uint GetFenceSE(TileIndex t)
 {
-	assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES));
+	assert(IsClearGround(t, CLEAR_FIELDS));
 	return GB(_m[t].m4, 2, 3);
 }
 
@@ -230,23 +230,23 @@
  * eastern border.
  * @param t the tile to check for fences
  * @param h 0 if there is no fence, otherwise the fence type
- * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)
+ * @pre IsClearGround(t, CLEAR_FIELDS)
  */
 static inline void SetFenceSE(TileIndex t, uint h)
 {
-	assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete
+	assert(IsClearGround(t, CLEAR_FIELDS));
 	SB(_m[t].m4, 2, 3, h);
 }
 
 /**
  * Is there a fence at the south western border?
  * @param t the tile to check for fences
- * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)
+ * @pre IsClearGround(t, CLEAR_FIELDS)
  * @return 0 if there is no fence, otherwise the fence type
  */
 static inline uint GetFenceSW(TileIndex t)
 {
-	assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES));
+	assert(IsClearGround(t, CLEAR_FIELDS));
 	return GB(_m[t].m4, 5, 3);
 }
 
@@ -255,14 +255,64 @@
  * western border.
  * @param t the tile to check for fences
  * @param h 0 if there is no fence, otherwise the fence type
- * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)
+ * @pre IsClearGround(t, CLEAR_FIELDS)
  */
 static inline void SetFenceSW(TileIndex t, uint h)
 {
-	assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete
+	assert(IsClearGround(t, CLEAR_FIELDS));
 	SB(_m[t].m4, 5, 3, h);
 }
 
+/**
+ * Is there a fence at the north eastern border?
+ * @param t the tile to check for fences
+ * @pre IsClearGround(t, CLEAR_FIELDS)
+ * @return 0 if there is no fence, otherwise the fence type
+ */
+static inline uint GetFenceNE(TileIndex t)
+{
+	assert(IsClearGround(t, CLEAR_FIELDS));
+	return GB(_m[t].m3, 5, 3);
+}
+
+/**
+ * Sets the type of fence (and whether there is one) for the north
+ * eastern border.
+ * @param t the tile to check for fences
+ * @param h 0 if there is no fence, otherwise the fence type
+ * @pre IsClearGround(t, CLEAR_FIELDS)
+ */
+static inline void SetFenceNE(TileIndex t, uint h)
+{
+	assert(IsClearGround(t, CLEAR_FIELDS));
+	SB(_m[t].m3, 5, 3, h);
+}
+
+/**
+ * Is there a fence at the north western border?
+ * @param t the tile to check for fences
+ * @pre IsClearGround(t, CLEAR_FIELDS)
+ * @return 0 if there is no fence, otherwise the fence type
+ */
+static inline uint GetFenceNW(TileIndex t)
+{
+	assert(IsClearGround(t, CLEAR_FIELDS));
+	return GB(_m[t].m6, 2, 3);
+}
+
+/**
+ * Sets the type of fence (and whether there is one) for the north
+ * western border.
+ * @param t the tile to check for fences
+ * @param h 0 if there is no fence, otherwise the fence type
+ * @pre IsClearGround(t, CLEAR_FIELDS)
+ */
+static inline void SetFenceNW(TileIndex t, uint h)
+{
+	assert(IsClearGround(t, CLEAR_FIELDS));
+	SB(_m[t].m6, 2, 3, h);
+}
+
 
 /**
  * Make a clear tile.
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -955,20 +955,28 @@
 	}
 }
 
-static void SetupFarmFieldFence(TileIndex tile, int size, byte type, Axis direction)
+static void SetupFarmFieldFence(TileIndex tile, int size, byte type, Axis direction, bool north)
 {
 	do {
 		tile = TILE_MASK(tile);
 
-		if (IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES)) {
+		if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
 			byte or_ = type;
 
 			if (or_ == 1 && Chance16(1, 7)) or_ = 2;
 
 			if (direction == AXIS_X) {
-				SetFenceSE(tile, or_);
+				if (north) {
+					SetFenceNW(tile, or_);
+				} else {
+					SetFenceSE(tile, or_);
+				}
 			} else {
-				SetFenceSW(tile, or_);
+				if (north) {
+					SetFenceNE(tile, or_);
+				} else {
+					SetFenceSW(tile, or_);
+				}
 			}
 		}
 
@@ -1021,10 +1029,10 @@
 		type = _plantfarmfield_type[Random() & 0xF];
 	}
 
-	SetupFarmFieldFence(ta.tile - TileDiffXY(1, 0), ta.h, type, AXIS_Y);
-	SetupFarmFieldFence(ta.tile - TileDiffXY(0, 1), ta.w, type, AXIS_X);
-	SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, AXIS_Y);
-	SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, AXIS_X);
+	SetupFarmFieldFence(ta.tile, ta.h, type, AXIS_Y, true);
+	SetupFarmFieldFence(ta.tile, ta.w, type, AXIS_X, true);
+	SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, AXIS_Y, false);
+	SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, AXIS_X, false);
 }
 
 void PlantRandomFarmField(const Industry *i)
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -1267,10 +1267,6 @@
 			if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) {
 				/* remove fields */
 				MakeClear(t, CLEAR_GRASS, 3);
-			} else if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) {
-				/* remove fences around fields */
-				SetFenceSE(t, 0);
-				SetFenceSW(t, 0);
 			}
 		}
 
@@ -2653,6 +2649,24 @@
 		_settings_game.game_creation.snow_line_height /= TILE_HEIGHT;
 	}
 
+	if (IsSavegameVersionBefore(164) && !IsSavegameVersionBefore(32)) {
+		/* We store 4 fences in the field tiles instead of only SE and SW. */
+		for (TileIndex t = 0; t < map_size; t++) {
+			if (!IsTileType(t, MP_CLEAR) && !IsTileType(t, MP_TREES)) continue;
+			if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) continue;
+			uint fence = GB(_m[t].m4, 5, 3);
+			if (fence != 0 && IsTileType(TILE_ADDXY(t, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 1, 0), CLEAR_FIELDS)) {
+				SetFenceNE(TILE_ADDXY(t, 1, 0), fence);
+			}
+			fence = GB(_m[t].m4, 2, 3);
+			if (fence != 0 && IsTileType(TILE_ADDXY(t, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 0, 1), CLEAR_FIELDS)) {
+				SetFenceNW(TILE_ADDXY(t, 0, 1), fence);
+			}
+			SB(_m[t].m4, 2, 3, 0);
+			SB(_m[t].m4, 5, 3, 0);
+		}
+	}
+
 	/* When any NewGRF has been changed the availability of some vehicles might
 	 * have been changed too. e->company_avail must be set to 0 in that case
 	 * which is done by StartupEngines(). */
--- a/src/table/clear_land.h
+++ b/src/table/clear_land.h
@@ -34,6 +34,20 @@
 	1, 1, 5, 5, 3, 3, 3, 1,
 };
 
+static const byte _fence_mod_by_tileh_ne[32] = {
+	0, 0, 0, 0, 4, 4, 4, 4,
+	2, 2, 2, 2, 0, 0, 0, 0,
+	0, 0, 0, 0, 4, 4, 4, 4,
+	2, 2, 2, 2, 0, 0, 0, 0,
+};
+
+static const byte _fence_mod_by_tileh_nw[32] = {
+	1, 5, 1, 5, 1, 5, 1, 5,
+	3, 1, 3, 1, 3, 1, 3, 1,
+	1, 5, 1, 5, 1, 5, 1, 5,
+	3, 1, 3, 1, 3, 1, 3, 1,
+};
+
 
 static const SpriteID _clear_land_fence_sprites[7] = {
 	SPR_HEDGE_BUSHES,
--- a/src/tree_cmd.cpp
+++ b/src/tree_cmd.cpp
@@ -453,8 +453,6 @@
 		default: DrawGroundSprite(_clear_land_sprites_snow_desert[GetTreeDensity(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE); break;
 	}
 
-	DrawClearLandFence(ti);
-
 	/* Do not draw trees when the invisible trees setting is set */
 	if (IsInvisibilitySet(TO_TREES)) return;
 
@@ -630,7 +628,6 @@
 	}
 
 	AmbientSoundEffectCallback(tile);
-	TileLoopClearHelper(tile);
 
 	uint treeCounter = GetTreeCounter(tile);