diff --git a/clear_cmd.c b/clear_cmd.c index 52dd174f7c..a5a9b31bdb 100644 --- a/clear_cmd.c +++ b/clear_cmd.c @@ -86,38 +86,13 @@ static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile) 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 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2) 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; } } diff --git a/rail_cmd.c b/rail_cmd.c index ab6ca5a59d..8afcab6981 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -128,7 +128,7 @@ static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags } -static const byte _valid_tileh_slopes[4][15] = { +const TrackBits _valid_tileh_slopes[4][15] = { // set of normal ones { diff --git a/tile.c b/tile.c index 9fe175766f..f18932c3f3 100644 --- a/tile.c +++ b/tile.c @@ -15,6 +15,30 @@ uint GetMapExtraBits(TileIndex tile) 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 GetTileSlope(TileIndex tile, uint *h) uint b; uint c; uint d; - uint min; - uint r; assert(tile < MapSize()); @@ -32,24 +54,12 @@ uint GetTileSlope(TileIndex tile, uint *h) 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) diff --git a/tile.h b/tile.h index e02c9e4431..90a2941063 100644 --- a/tile.h +++ b/tile.h @@ -47,6 +47,7 @@ typedef enum DiagonalDirections { 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);