Initial support for rail custom bridge heads

This commit is contained in:
Jonathan G Rennison
2018-07-03 19:09:10 +01:00
parent 25af12814b
commit 77362b829a
25 changed files with 1055 additions and 235 deletions

View File

@@ -52,6 +52,7 @@ TileIndex _build_tunnel_endtile; ///< The end of a tunnel; as hidden return from
/** Z position of the bridge sprites relative to bridge height (downwards) */
static const int BRIDGE_Z_START = 3;
extern void DrawTrackBits(TileInfo *ti, TrackBits track);
extern void DrawRoadBits(TileInfo *ti);
extern const RoadBits _invalid_tileh_slopes_road[2][15];
@@ -315,7 +316,6 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
int z_end;
Slope tileh_start = GetTileSlope(tile_start, &z_start);
Slope tileh_end = GetTileSlope(tile_end, &z_end);
bool pbs_reservation = false;
CommandCost terraform_cost_north = CheckBridgeSlopeNorth(direction, &tileh_start, &z_start);
CommandCost terraform_cost_south = CheckBridgeSlopeSouth(direction, &tileh_end, &z_end);
@@ -369,15 +369,6 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
is_new_owner = (owner == OWNER_NONE);
if (is_new_owner) owner = company;
switch (transport_type) {
case TRANSPORT_RAIL:
/* Keep the reservation, the path stays valid. */
pbs_reservation = HasTunnelBridgeReservation(tile_start);
break;
default: break;
}
is_upgrade = true;
} else {
/* Build a new bridge. */
@@ -491,11 +482,9 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
switch (transport_type) {
case TRANSPORT_RAIL:
/* Add to company infrastructure count if required. */
if (is_new_owner && c != NULL) c->infrastructure.rail[railtype] += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype);
SetTunnelBridgeReservation(tile_start, pbs_reservation);
SetTunnelBridgeReservation(tile_end, pbs_reservation);
MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype, is_upgrade);
MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype, is_upgrade);
if (is_new_owner && c != NULL) c->infrastructure.rail[railtype] += (bridge_len * TUNNELBRIDGE_TRACKBIT_FACTOR) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile_start) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile_end);
break;
case TRANSPORT_ROAD: {
@@ -834,7 +823,7 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
Owner owner = GetTileOwner(tile);
Train *v = NULL;
if (HasTunnelBridgeReservation(tile)) {
if (HasTunnelReservation(tile)) {
v = GetTrainForReservation(tile, track);
if (v != NULL) FreeTrainTrackReservation(v);
}
@@ -909,24 +898,48 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
}
CommandCost cost(EXPENSES_CONSTRUCTION);
const bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
TrackBits tile_tracks = TRACK_BIT_NONE;
TrackBits endtile_tracks = TRACK_BIT_NONE;
if (rail) {
tile_tracks = GetCustomBridgeHeadTrackBits(tile);
endtile_tracks = GetCustomBridgeHeadTrackBits(endtile);
cost.AddCost(RailClearCost(GetRailType(tile)) * (CountBits(tile_tracks) + CountBits(endtile_tracks) - 2));
}
Money base_cost = (GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) ? _price[PR_CLEAR_BRIDGE] : _price[PR_CLEAR_AQUEDUCT];
uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
uint middle_len = GetTunnelBridgeLength(tile, endtile);
uint len = middle_len + 2; // Don't forget the end tiles.
cost.AddCost(len * base_cost);
if (flags & DC_EXEC) {
/* read this value before actual removal of bridge */
bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
Owner owner = GetTileOwner(tile);
int height = GetBridgeHeight(tile);
Train *v = NULL;
SmallVector<Train *, 2> vehicles_affected;
if (rail && HasTunnelBridgeReservation(tile)) {
v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
if (v != NULL) FreeTrainTrackReservation(v);
if (rail) {
auto find_train_reservations = [&vehicles_affected](TileIndex tile) {
TrackBits reserved = GetBridgeReservationTrackBits(tile);
Track track;
while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
Train *v = GetTrainForReservation(tile, track);
if (v != NULL) {
FreeTrainTrackReservation(v);
*vehicles_affected.Append() = v;
}
}
};
find_train_reservations(tile);
find_train_reservations(endtile);
}
/* Update company infrastructure counts. */
if (rail) {
if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= (middle_len * TUNNELBRIDGE_TRACKBIT_FACTOR) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile) + GetTunnelBridgeHeadOnlyRailInfrastructureCount(endtile);
} else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) {
SubtractRoadTunnelBridgeInfrastructure(tile, endtile);
} else { // Aqueduct
@@ -948,18 +961,28 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
if (rail) {
/* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
AddSideToSignalBuffer(tile, ReverseDiagDir(direction), owner);
AddSideToSignalBuffer(endtile, direction, owner);
Track track = DiagDirToDiagTrack(direction);
YapfNotifyTrackLayoutChange(tile, track);
YapfNotifyTrackLayoutChange(endtile, track);
auto notify_track_change = [owner](TileIndex tile, DiagDirection direction, TrackBits tracks) {
auto check_dir = [&](DiagDirection d) {
if (DiagdirReachesTracks(d) & tracks) AddSideToSignalBuffer(tile, d, owner);
};
check_dir(ChangeDiagDir(direction, DIAGDIRDIFF_90RIGHT));
check_dir(ChangeDiagDir(direction, DIAGDIRDIFF_REVERSE));
check_dir(ChangeDiagDir(direction, DIAGDIRDIFF_90LEFT));
while (tracks != TRACK_BIT_NONE) {
YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
}
};
notify_track_change(tile, direction, tile_tracks);
notify_track_change(endtile, ReverseDiagDir(direction), endtile_tracks);
if (v != NULL) TryPathReserve(v, true);
for (uint i = 0; i < vehicles_affected.Length(); ++i) {
TryPathReserve(vehicles_affected[i], true);
}
}
}
return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
return cost;
}
/**
@@ -1202,7 +1225,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
}
/* PBS debugging, draw reserved tracks darker */
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelReservation(ti->tile)) {
if (rti->UsesOverlay()) {
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
DrawGroundSprite(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH);
@@ -1241,6 +1264,14 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
DrawBridgeMiddle(ti);
return;
}
if (transport_type == TRANSPORT_RAIL && IsRailCustomBridgeHead(ti->tile)) {
DrawTrackBits(ti, GetCustomBridgeHeadTrackBits(ti->tile));
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) {
DrawRailCatenary(ti);
}
DrawBridgeMiddle(ti);
return;
}
const PalSpriteID *psid;
int base_offset;
@@ -1324,7 +1355,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
}
/* PBS debugging, draw reserved tracks darker */
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && GetBridgeReservationTrackBits(ti->tile) != TRACK_BIT_NONE) {
if (rti->UsesOverlay()) {
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
@@ -1489,7 +1520,7 @@ void DrawBridgeMiddle(const TileInfo *ti)
}
}
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && (HasAcrossBridgeReservation(rampnorth) || HasAcrossBridgeReservation(rampsouth))) {
if (rti->UsesOverlay()) {
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
@@ -1556,7 +1587,7 @@ static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
/* In the tunnel entrance? */
if (5 <= pos && pos <= 10) return z;
} else { // IsBridge(tile)
if (IsRoadCustomBridgeHeadTile(tile)) {
if (IsCustomBridgeHeadTile(tile)) {
return z + TILE_HEIGHT + (IsSteepSlope(tileh) ? TILE_HEIGHT : 0);
}
@@ -1587,7 +1618,7 @@ static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
{
if (IsRoadCustomBridgeHeadTile(tile)) return FOUNDATION_LEVELED;
if (IsCustomBridgeHeadTile(tile)) return FOUNDATION_LEVELED;
return IsTunnel(tile) ? FOUNDATION_NONE : GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(tile)));
}
@@ -1677,15 +1708,14 @@ static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType
DiagDirection dir = GetTunnelBridgeDirection(tile);
if (side != INVALID_DIAGDIR && side == dir) return 0;
if (mode == TRANSPORT_ROAD && IsRoadCustomBridgeHeadTile(tile)) {
if (side != INVALID_DIAGDIR && side == dir) return 0;
TrackBits bits = TRACK_BIT_NONE;
if (sub_mode & ROADTYPES_TRAM) bits |= _road_trackbits[GetCustomBridgeHeadRoadBits(tile, ROADTYPE_TRAM)];
if (sub_mode & ROADTYPES_ROAD) bits |= _road_trackbits[GetCustomBridgeHeadRoadBits(tile, ROADTYPE_ROAD)];
return CombineTrackStatus(TrackBitsToTrackdirBits(bits), TRACKDIR_BIT_NONE);
}
if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
return CombineTrackStatus(TrackBitsToTrackdirBits(mode == TRANSPORT_RAIL ? GetTunnelBridgeTrackBits(tile) : DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
}
static void UpdateRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end, bool add) {
@@ -1743,9 +1773,6 @@ void SubtractRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end) {
static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
{
const TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
/* Set number of pieces to zero if it's the southern tile as we
* don't want to update the infrastructure counts twice. */
const uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
const TransportType tt = GetTunnelBridgeTransportType(tile);
if (tt == TRANSPORT_ROAD && tile < other_end) {
@@ -1772,9 +1799,15 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner
Company *old = Company::Get(old_owner);
if (tt == TRANSPORT_RAIL) {
/* Set number of middle pieces to zero if it's the southern tile as we
* don't want to update the infrastructure counts twice. */
const uint num_pieces = GetTunnelBridgeHeadOnlyRailInfrastructureCount(tile) + (tile < other_end ? GetTunnelBridgeLength(tile, other_end) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0);
old->infrastructure.rail[GetRailType(tile)] -= num_pieces;
if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += num_pieces;
} else if (tt == TRANSPORT_WATER) {
/* Set number of pieces to zero if it's the southern tile as we
* don't want to update the infrastructure counts twice. */
const uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
old->infrastructure.water -= num_pieces;
if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.water += num_pieces;
}
@@ -1813,23 +1846,31 @@ extern const byte _tunnel_visibility_frame[DIAGDIR_END] = {12, 8, 8, 12};
static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
{
/* Direction into the wormhole */
const DiagDirection dir = GetTunnelBridgeDirection(tile);
/* New position of the vehicle on the tile */
int pos = (DiagDirToAxis(dir) == AXIS_X ? x - (TileX(tile) * TILE_SIZE) : y - (TileY(tile) * TILE_SIZE));
/* Number of units moved by the vehicle since entering the tile */
int frame = (dir == DIAGDIR_NE || dir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
if (frame > (int) TILE_SIZE || frame < 0) return VETSB_CANNOT_ENTER;
if (frame == TILE_SIZE) {
TileIndexDiffC offset = TileIndexDiffCByDiagDir(ReverseDiagDir(dir));
x += offset.x;
y += offset.y;
}
int z = GetSlopePixelZ(x, y) - v->z_pos;
if (abs(z) > 2) return VETSB_CANNOT_ENTER;
/* Direction into the wormhole */
const DiagDirection dir = GetTunnelBridgeDirection(tile);
/* Direction of the vehicle */
const DiagDirection vdir = DirToDiagDir(v->direction);
/* New position of the vehicle on the tile */
byte pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK;
/* Number of units moved by the vehicle since entering the tile */
byte frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
if (IsTunnel(tile)) {
/* Direction of the vehicle */
const DiagDirection vdir = DirToDiagDir(v->direction);
if (v->type == VEH_TRAIN) {
Train *t = Train::From(v);
if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
if (!(t->track & TRACK_BIT_WORMHOLE) && dir == vdir) {
if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) {
if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
@@ -1844,7 +1885,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
}
}
if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
if (dir == ReverseDiagDir(vdir) && frame == (int) (_tunnel_visibility_frame[dir] - 1) && z == 0) {
/* We're at the tunnel exit ?? */
t->tile = tile;
t->track = DiagDirToDiagTrackBits(vdir);
@@ -1870,7 +1911,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
}
/* We're at the tunnel exit ?? */
if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
if (dir == ReverseDiagDir(vdir) && frame == (int) (_tunnel_visibility_frame[dir] - 1) && z == 0) {
rv->tile = tile;
rv->state = DiagDirToDiagTrackdir(vdir);
rv->frame = frame;
@@ -1888,11 +1929,12 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
first->cur_speed = min(first->cur_speed, spd);
}
if (vdir == dir) {
/* Vehicle enters bridge at the last frame inside this tile. */
if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
const Direction bridge_dir = DiagDirToDir(dir);
if (v->direction == bridge_dir) {
switch (v->type) {
case VEH_TRAIN: {
/* Trains enter bridge at the first frame beyond this tile. */
if (frame != TILE_SIZE) return VETSB_CONTINUE;
Train *t = Train::From(v);
t->track = TRACK_BIT_WORMHOLE;
ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
@@ -1901,6 +1943,8 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
}
case VEH_ROAD: {
/* Non-train vehicles enter bridge at the last frame inside this tile. */
if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
RoadVehicle *rv = RoadVehicle::From(v);
if (IsRoadCustomBridgeHeadTile(tile)) {
RoadBits bits = ROAD_NONE;
@@ -1916,28 +1960,35 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
}
case VEH_SHIP:
/* Non-train vehicles enter bridge at the last frame inside this tile. */
if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
Ship::From(v)->state = TRACK_BIT_WORMHOLE;
break;
default: NOT_REACHED();
}
return VETSB_ENTERED_WORMHOLE;
} else if (vdir == ReverseDiagDir(dir)) {
v->tile = tile;
} else if (v->direction == ReverseDir(bridge_dir)) {
switch (v->type) {
case VEH_TRAIN: {
Train *t = Train::From(v);
if (t->track == TRACK_BIT_WORMHOLE) {
t->track = DiagDirToDiagTrackBits(vdir);
if (t->track & TRACK_BIT_WORMHOLE) {
if (IsRailCustomBridgeHeadTile(tile)) {
return VETSB_ENTERED_WORMHOLE;
} else {
v->tile = tile;
t->track = DiagDirToDiagTrackBits(DirToDiagDir(v->direction));
}
return VETSB_ENTERED_WORMHOLE;
}
break;
}
case VEH_ROAD: {
v->tile = tile;
RoadVehicle *rv = RoadVehicle::From(v);
if (rv->state == RVSB_WORMHOLE) {
rv->state = DiagDirToDiagTrackdir(vdir);
rv->state = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
rv->frame = 0;
return VETSB_ENTERED_WORMHOLE;
}
@@ -1945,9 +1996,10 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
}
case VEH_SHIP: {
v->tile = tile;
Ship *ship = Ship::From(v);
if (ship->state == TRACK_BIT_WORMHOLE) {
ship->state = DiagDirToDiagTrackBits(vdir);
ship->state = DiagDirToDiagTrackBits(DirToDiagDir(v->direction));
return VETSB_ENTERED_WORMHOLE;
}
break;
@@ -1955,6 +2007,29 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
default: NOT_REACHED();
}
} else if (v->type == VEH_TRAIN && IsRailCustomBridgeHeadTile(tile)) {
DirDiff dir_diff = DirDifference(v->direction, bridge_dir);
DirDiff reverse_dir_diff = DirDifference(v->direction, ReverseDir(bridge_dir));
if (dir_diff == DIRDIFF_45RIGHT || dir_diff == DIRDIFF_45LEFT) {
if (frame != TILE_SIZE) return VETSB_CONTINUE;
Train *t = Train::From(v);
TileIndex other = GetOtherTunnelBridgeEnd(tile);
if (GetTunnelBridgeLength(tile, other) == 0 && IsRailCustomBridgeHead(other)) {
t->track |= TRACK_BIT_WORMHOLE;
} else {
t->direction = bridge_dir;
t->track = TRACK_BIT_WORMHOLE;
}
ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
ClrBit(t->gv_flags, GVF_GOINGDOWN_BIT);
return VETSB_ENTERED_WORMHOLE;
}
if (reverse_dir_diff == DIRDIFF_45RIGHT || reverse_dir_diff == DIRDIFF_45LEFT) {
Train *t = Train::From(v);
if (t->track & TRACK_BIT_WORMHOLE) return VETSB_ENTERED_WORMHOLE;
}
}
}
return VETSB_CONTINUE;
@@ -1980,6 +2055,16 @@ static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flag
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
}
if (IsRailCustomBridgeHeadTile(tile)) {
extern bool IsValidFlatRailBridgeHeadTrackBits(Slope normalised_slope, DiagDirection bridge_direction, TrackBits tracks);
/* Steep slopes behave the same as slopes with one corner raised. */
const Slope normalised_tileh_new = IsSteepSlope(tileh_new) ? SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh_new)) : tileh_new;
if (!IsValidFlatRailBridgeHeadTrackBits(normalised_tileh_new, direction, GetCustomBridgeHeadTrackBits(tile))) {
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
}
/* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {