summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clear_cmd.c83
-rw-r--r--rail_cmd.c2
-rw-r--r--tile.c42
-rw-r--r--tile.h1
4 files changed, 61 insertions, 67 deletions
diff --git a/clear_cmd.c b/clear_cmd.c
index 2802fc9cf..19b475124 100644
--- a/clear_cmd.c
+++ b/clear_cmd.c
@@ -87,25 +87,48 @@ static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile)
TerraformAddDirtyTile(ts, tile);
}
-static int TerraformProc(TerraformerState *ts, TileIndex tile)
+static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
{
int r;
+ int32 ret;
assert(tile < MapSize());
- if ((r = TerraformAllowTileProcess(ts, tile)) <= 0) return r;
+ if ((r=TerraformAllowTileProcess(ts, tile)) <= 0)
+ return r;
- if (!IsTileType(tile, MP_RAILWAY)) {
- int32 ret = DoCommand(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
+ if (IsTileType(tile, MP_RAILWAY)) {
+ static const TrackBits _railway_modes[] = { TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER, TRACK_BIT_RIGHT };
+ static const byte _railway_dangslopes[4] = {0xd, 0xe, 7, 0xb};
+ static const byte _railway_dangslopes2[4] = {0x2, 0x1, 0x8, 0x4};
- if (CmdFailed(ret)) {
+ // 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;
}
- ts->cost += ret;
+ // If we have a single diagonal track there, the other side of
+ // tile can be terraformed.
+ if (IsPlainRailTile(tile) && GetTrackBits(tile) == _railway_modes[mode]) {
+ return 0;
+ }
+ }
+
+ ret = DoCommand(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
+
+ if (ret == CMD_ERROR) {
+ _terraform_err_tile = tile;
+ return -1;
}
+ ts->cost += ret;
+
if (ts->tile_table_count >= 625) return -1;
ts->tile_table[ts->tile_table_count++] = tile;
@@ -132,10 +155,10 @@ static bool TerraformTileHeight(TerraformerState *ts, TileIndex tile, int height
nh = TerraformGetHeightOfTile(ts, tile);
if (nh < 0 || height == nh) return false;
- if (TerraformProc(ts, tile) < 0) return false;
- if (TerraformProc(ts, tile + TileDiffXY( 0, -1)) < 0) return false;
- if (TerraformProc(ts, tile + TileDiffXY(-1, -1)) < 0) return false;
- if (TerraformProc(ts, tile + TileDiffXY(-1, 0)) < 0) return false;
+ if (TerraformProc(ts, tile, 0) < 0) return false;
+ if (TerraformProc(ts, tile + TileDiffXY( 0, -1), 1) < 0) return false;
+ if (TerraformProc(ts, tile + TileDiffXY(-1, -1), 2) < 0) return false;
+ if (TerraformProc(ts, tile + TileDiffXY(-1, 0), 3) < 0) return false;
mod = ts->modheight;
count = ts->modheight_count;
@@ -237,42 +260,26 @@ int32 CmdTerraformLand(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
}
}
- { /* Check if tunnel or track would take damage */
+ if (direction == -1) {
+ /* Check if tunnel would take damage */
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
- uint a, b, c, d, min;
- Slope s;
+ uint z, t;
TileIndex tile = *ti;
- _terraform_err_tile = tile;
-
- 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));
-
- s = GetTileh(a, b, c, d, &min);
-
- if (IsTileType(tile, MP_RAILWAY)) {
- if (IsSteepSlope(s)) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
+ 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;
- if (IsPlainRailTile(tile)) {
- /* If a piece of rail is on a foundation, prohibit any terraforming
- * of that tile. We do need to check this with the original slope, not
- * the would-be one. */
- extern const TrackBits _valid_tileh_slopes[2][15];
- TrackBits tb = GetTrackBits(tile);
-
- if (GetRailFoundation(GetTileSlope(tile, NULL), tb) != 0) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
- if (tb & ~_valid_tileh_slopes[0][s]) return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
- } else return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
+ if (IsTunnelInWay(tile, z * TILE_HEIGHT)) {
+ return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
}
-
- if (direction == -1 && IsTunnelInWay(tile, min)) return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
-
- _terraform_err_tile = 0;
}
}
diff --git a/rail_cmd.c b/rail_cmd.c
index 1039509f9..005072016 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -105,7 +105,7 @@ static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags
}
-const TrackBits _valid_tileh_slopes[2][15] = {
+static const TrackBits _valid_tileh_slopes[][15] = {
// set of normal ones
{
diff --git a/tile.c b/tile.c
index 98fb5f0bd..ba6900a36 100644
--- a/tile.c
+++ b/tile.c
@@ -3,37 +3,14 @@
#include "stdafx.h"
#include "tile.h"
-/** 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
-*/
-Slope GetTileh(uint n, uint w, uint e, uint s, uint *h)
-{
- uint min = n;
- Slope r;
-
- if (min >= w) min = w;
- if (min >= e) min = e;
- if (min >= s) min = s;
-
- r = SLOPE_FLAT;
- if ((n -= min) != 0) r += (--n << 4) + SLOPE_N;
- if ((e -= min) != 0) r += (--e << 4) + SLOPE_E;
- if ((s -= min) != 0) r += (--s << 4) + SLOPE_S;
- if ((w -= min) != 0) r += (--w << 4) + SLOPE_W;
-
- if (h != NULL) *h = min * TILE_HEIGHT;
-
- return r;
-}
-
Slope GetTileSlope(TileIndex tile, uint *h)
{
uint a;
uint b;
uint c;
uint d;
+ uint min;
+ uint r;
assert(tile < MapSize());
@@ -42,12 +19,23 @@ Slope GetTileSlope(TileIndex tile, uint *h)
return 0;
}
- a = TileHeight(tile);
+ min = 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 = SLOPE_FLAT;
+ if ((a -= min) != 0) r += (--a << 4) + SLOPE_N;
+ if ((c -= min) != 0) r += (--c << 4) + SLOPE_E;
+ if ((d -= min) != 0) r += (--d << 4) + SLOPE_S;
+ if ((b -= min) != 0) r += (--b << 4) + SLOPE_W;
- return GetTileh(a, b, c, d, h);
+ if (h != NULL) *h = min * TILE_HEIGHT;
+
+ return r;
}
uint GetTileZ(TileIndex tile)
diff --git a/tile.h b/tile.h
index c2c0f0168..98ece8c3c 100644
--- a/tile.h
+++ b/tile.h
@@ -27,7 +27,6 @@ typedef enum TropicZones {
TROPICZONE_RAINFOREST = 2,
} TropicZone;
-Slope GetTileh(uint n, uint w, uint e, uint s, uint *h);
Slope GetTileSlope(TileIndex tile, uint *h);
uint GetTileZ(TileIndex tile);
uint GetTileMaxZ(TileIndex tile);