(svn r4012) -Backport from trunk (3992, 3995): Rewrote the code to determine whether a rail-tile can be terraformed. 0.4.5
authorcelestar
Wed, 22 Mar 2006 10:32:07 +0000
branch0.4.5
changeset 9942 56446313309e
parent 9941 2dd05b8458d9
child 9943 bedd1ceaa101
(svn r4012) -Backport from trunk (3992, 3995): Rewrote the code to determine whether a rail-tile can be terraformed.
Fixes a bug where you could terraform a tunnel (fixed by r3228, but reverted that one)
Fixes a bug introduced by r3228 which allowed steep rail tiles resulting in ... unwanted effects such as display artifacts.
clear_cmd.c
rail_cmd.c
tile.c
tile.h
--- a/clear_cmd.c	Sun Mar 19 09:03:25 2006 +0000
+++ b/clear_cmd.c	Wed Mar 22 10:32:07 2006 +0000
@@ -86,38 +86,13 @@
 static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
 {
 	int r;
-	bool skip_clear = false;
 
 	assert(tile < MapSize());
 
 	if ((r=TerraformAllowTileProcess(ts, tile)) <= 0)
 		return r;
 
-	if (IsTileType(tile, MP_RAILWAY)) {
-		static const byte _railway_modes[4] = {8, 0x10, 4, 0x20};
-		static const byte _railway_dangslopes[4] = {0xd, 0xe, 7, 0xb};
-		static const byte _railway_dangslopes2[4] = {0x2, 0x1, 0x8, 0x4};
-
-		// Nothing could be built at the steep slope - this avoids a bug
-		// when you have a single diagonal track in one corner on a
-		// basement and then you raise/lower the other corner.
-		int tileh = GetTileSlope(tile, NULL) & 0xF;
-		if (tileh == _railway_dangslopes[mode] ||
-				tileh == _railway_dangslopes2[mode]) {
-			_terraform_err_tile = tile;
-			_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
-			return -1;
-		}
-
-		// If we have a single diagonal track there, the other side of
-		// tile can be terraformed.
-		if ((_m[tile].m5 & ~0x40) == _railway_modes[mode]) {
-			if (ts->direction == 1) return 0;
-			skip_clear = true;
-		}
-	}
-
-	if (!skip_clear) {
+	if (!IsTileType(tile, MP_RAILWAY)) {
 		int32 ret = DoCommandByTile(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
 		if (CmdFailed(ret)) {
@@ -259,26 +234,35 @@
 					return CMD_ERROR;
 	}
 
-	if (direction == -1) {
-		/* Check if tunnel would take damage */
+	{ /* Check if tunnel or track would take damage */
 		int count;
 		TileIndex *ti = ts.tile_table;
 
 		for (count = ts.tile_table_count; count != 0; count--, ti++) {
-			uint z, t;
+			uint a, b, c, d, r, min;
 			TileIndex tile = *ti;
 
-			z = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0));
-			t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0));
-			if (t <= z) z = t;
-			t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1));
-			if (t <= z) z = t;
-			t = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1));
-			if (t <= z) z = t;
+			_terraform_err_tile = tile;
 
-			if (!CheckTunnelInWay(tile, z * 8)) {
-				return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
+			a = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 0));
+			b = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 0));
+			c = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(0, 1));
+			d = TerraformGetHeightOfTile(&ts, tile + TileDiffXY(1, 1));
+
+			r = GetTileh(a, b, c, d, &min);
+
+			if (IsTileType(tile, MP_RAILWAY)) {
+				if (IsSteepTileh(r)) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
+
+				if (IsPlainRailTile(tile)) {
+					extern const TrackBits _valid_tileh_slopes[2][15];
+					if (GetTrackBits(tile) & ~_valid_tileh_slopes[0][r]) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
+				} else return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
 			}
+
+			if (direction == -1 && CheckTunnelInWay(tile, min)) return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
+
+			_terraform_err_tile = 0;
 		}
 	}
 
--- a/rail_cmd.c	Sun Mar 19 09:03:25 2006 +0000
+++ b/rail_cmd.c	Wed Mar 22 10:32:07 2006 +0000
@@ -128,7 +128,7 @@
 }
 
 
-static const byte _valid_tileh_slopes[4][15] = {
+const TrackBits _valid_tileh_slopes[4][15] = {
 
 // set of normal ones
 {
--- a/tile.c	Sun Mar 19 09:03:25 2006 +0000
+++ b/tile.c	Wed Mar 22 10:32:07 2006 +0000
@@ -15,6 +15,30 @@
 	return GB(_m[tile].extra, 0, 2);
 }
 
+/** Converts the heights of 4 corners into a tileh, and returns the minimum height of the tile
+  * @param n,w,e,s the four corners
+  * @param h uint pointer to write the height to
+  * @return the tileh
+*/
+uint GetTileh(uint n, uint w, uint e, uint s, uint *h)
+{
+	uint min = n;
+	uint r;
+
+	if (min >= w) min = w;
+	if (min >= e) min = e;
+	if (min >= s) min = s;
+
+	r = 0;
+	if ((n -= min) != 0) r += (--n << 4) + 8;
+	if ((e -= min) != 0) r += (--e << 4) + 4;
+	if ((s -= min) != 0) r += (--s << 4) + 2;
+	if ((w -= min) != 0) r += (--w << 4) + 1;
+
+	if (h != NULL) *h = min * 8;
+
+	return r;
+}
 
 uint GetTileSlope(TileIndex tile, uint *h)
 {
@@ -22,8 +46,6 @@
 	uint b;
 	uint c;
 	uint d;
-	uint min;
-	uint r;
 
 	assert(tile < MapSize());
 
@@ -32,24 +54,12 @@
 		return 0;
 	}
 
-	min = a = TileHeight(tile);
+	a = TileHeight(tile);
 	b = TileHeight(tile + TileDiffXY(1, 0));
-	if (min >= b) min = b;
 	c = TileHeight(tile + TileDiffXY(0, 1));
-	if (min >= c) min = c;
 	d = TileHeight(tile + TileDiffXY(1, 1));
-	if (min >= d) min = d;
 
-	r = 0;
-	if ((a -= min) != 0) r += (--a << 4) + 8;
-	if ((c -= min) != 0) r += (--c << 4) + 4;
-	if ((d -= min) != 0) r += (--d << 4) + 2;
-	if ((b -= min) != 0) r += (--b << 4) + 1;
-
-	if (h != NULL)
-		*h = min * 8;
-
-	return r;
+	return GetTileh(a, b, c, d, h);
 }
 
 uint GetTileZ(TileIndex tile)
--- a/tile.h	Sun Mar 19 09:03:25 2006 +0000
+++ b/tile.h	Wed Mar 22 10:32:07 2006 +0000
@@ -47,6 +47,7 @@
 void SetMapExtraBits(TileIndex tile, byte flags);
 uint GetMapExtraBits(TileIndex tile);
 
+uint GetTileh(uint n, uint w, uint e, uint s, uint *h);
 uint GetTileSlope(TileIndex tile, uint *h);
 uint GetTileZ(TileIndex tile);