diff options
-rw-r--r-- | clear_cmd.c | 83 | ||||
-rw-r--r-- | rail_cmd.c | 2 | ||||
-rw-r--r-- | tile.c | 42 | ||||
-rw-r--r-- | tile.h | 1 |
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 { @@ -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) @@ -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); |