mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r3992) -Fix: 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. That means the terraform feature should not work as intended; it also uses _valid_tileh_slopes to determine valid configurations instead of hand-brewn stuff. TODO: _terraform_err_tile and similar TileIndices should have INVALID_TILE as "unused", not 0. (0 is a valid tile).
This commit is contained in:
parent
7bedab1a40
commit
fc32e20195
60
clear_cmd.c
60
clear_cmd.c
|
@ -88,38 +88,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 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};
|
||||
|
||||
// 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 (IsPlainRailTile(tile) && GetTrackBits(tile) == _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)) {
|
||||
|
@ -261,26 +236,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 (IsTunnelInWay(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 && IsTunnelInWay(tile, min)) return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
|
||||
|
||||
_terraform_err_tile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags
|
|||
}
|
||||
|
||||
|
||||
static const TrackBits _valid_tileh_slopes[][15] = {
|
||||
const TrackBits _valid_tileh_slopes[2][15] = {
|
||||
|
||||
// set of normal ones
|
||||
{
|
||||
|
|
41
tile.c
41
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,23 +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)
|
||||
|
|
1
tile.h
1
tile.h
|
@ -24,6 +24,7 @@ typedef enum TileTypes {
|
|||
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);
|
||||
|
||||
|
|
|
@ -634,7 +634,7 @@ static void DrawTileSelection(const TileInfo *ti)
|
|||
#endif
|
||||
|
||||
// Draw a red error square?
|
||||
if (_thd.redsq != 0 && _thd.redsq == ti->tile) {
|
||||
if (_thd.redsq != INVALID_TILE && _thd.redsq == ti->tile) {
|
||||
DrawSelectionSprite(PALETTE_TILE_RED_PULSATING | (SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh]), ti);
|
||||
return;
|
||||
}
|
||||
|
@ -1812,8 +1812,8 @@ void SetRedErrorSquare(TileIndex tile)
|
|||
_thd.redsq = tile;
|
||||
|
||||
if (tile != old) {
|
||||
if (tile != 0) MarkTileDirtyByTile(tile);
|
||||
if (old != 0) MarkTileDirtyByTile(old);
|
||||
if (tile != INVALID_TILE) MarkTileDirtyByTile(tile);
|
||||
if (old != INVALID_TILE) MarkTileDirtyByTile(old);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue