(svn r7610) [cbh] - Codechange: Created seperate Tile Type Procs for tunnel and bridge tiles custombridgeheads
authorcelestar
Fri, 29 Dec 2006 11:03:39 +0000
branchcustombridgeheads
changeset 5593 3e0dd1f014ca
parent 5592 fd60d4ecc921
child 5594 04068f82afaa
(svn r7610) [cbh] - Codechange: Created seperate Tile Type Procs for tunnel and bridge tiles
landscape.c
tunnelbridge_cmd.c
--- a/landscape.c	Fri Dec 29 10:13:35 2006 +0000
+++ b/landscape.c	Fri Dec 29 11:03:39 2006 +0000
@@ -32,10 +32,10 @@
 	_tile_type_water_procs,
 	_tile_type_dummy_procs,
 	_tile_type_industry_procs,
-	_tile_type_tunnelbridge_procs,
+	_tile_type_tunnel_procs,
 	_tile_type_unmovable_procs,
-	_tile_type_tunnelbridge_procs,
-	_tile_type_tunnelbridge_procs;
+	_tile_type_bridge_procs,
+	_tile_type_bridge_procs;
 
 const TileTypeProcs * const _tile_type_procs[16] = {
 	&_tile_type_clear_procs,
@@ -47,10 +47,10 @@
 	&_tile_type_water_procs,
 	&_tile_type_dummy_procs,
 	&_tile_type_industry_procs,
-	&_tile_type_tunnelbridge_procs,
+	&_tile_type_tunnel_procs,
 	&_tile_type_unmovable_procs,
-	&_tile_type_tunnelbridge_procs,
-	&_tile_type_tunnelbridge_procs,
+	&_tile_type_bridge_procs,
+	&_tile_type_bridge_procs,
 	NULL,
 	NULL,
 	NULL
--- a/tunnelbridge_cmd.c	Fri Dec 29 10:13:35 2006 +0000
+++ b/tunnelbridge_cmd.c	Fri Dec 29 11:03:39 2006 +0000
@@ -641,17 +641,18 @@
 	return (DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge;
 }
 
-static int32 ClearTile_TunnelBridge(TileIndex tile, byte flags)
+static int32 ClearTile_Tunnel(TileIndex tile, byte flags)
 {
-	if (IsTunnelTile(tile)) {
-		if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
-		return DoClearTunnel(tile, flags);
-	} else if (IsBridgeTile(tile)) { // XXX Is this necessary?
-		if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
-		return DoClearBridge(tile, flags);
-	}
+	assert(IsTunnelTile(tile));
+	if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
+	return DoClearTunnel(tile, flags);
+}
 
-	return CMD_ERROR;
+static int32 ClearTile_Bridge(TileIndex tile, byte flags)
+{
+	assert(IsBridgeTile(tile));
+	if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
+	return DoClearBridge(tile, flags);
 }
 
 int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
@@ -787,9 +788,32 @@
 }
 
 /**
- * Draws a tunnel of bridge tile.
- * For tunnels, this is rather simple, as you only needa draw the entrance.
- * Bridges are a bit more complex. base_offset is where the sprite selection comes into play
+ * Draws a tunnel tile.
+ * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
+ */
+static void DrawTile_Tunnel(TileInfo *ti)
+{
+	uint32 image;
+
+	if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) {
+		image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.tunnel;
+	} else {
+		image = SPR_TUNNEL_ENTRY_REAR_ROAD;
+	}
+
+	if (HasTunnelSnowOrDesert(ti->tile)) image += 32;
+
+	image += GetTunnelDirection(ti->tile) * 2;
+	DrawGroundSprite(image);
+	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+
+	AddSortableSpriteToDraw(image+1, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z);
+	DrawBridgeMiddle(ti);
+}
+
+/**
+ * Draws a bridge tile.
+ * base_offset is where the sprite selection comes into play
  * and it works a bit like a bitmask.<p> For bridge heads:
  * <ul><li>Bit 0: direction</li>
  * <li>Bit 1: northern or southern heads</li>
@@ -798,71 +822,54 @@
  * </ul>
  * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
  */
-static void DrawTile_TunnelBridge(TileInfo *ti)
+static void DrawTile_Bridge(TileInfo *ti)
 {
 	uint32 image;
 
-	if (IsTunnelTile(ti->tile)) {
-		if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) {
-			image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.tunnel;
-		} else {
-			image = SPR_TUNNEL_ENTRY_REAR_ROAD;
-		}
-
-		if (HasTunnelSnowOrDesert(ti->tile)) image += 32;
-
-		image += GetTunnelDirection(ti->tile) * 2;
-		DrawGroundSprite(image);
-		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
-
-		AddSortableSpriteToDraw(image+1, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z);
-		DrawBridgeMiddle(ti);
-	} else if (IsBridgeTile(ti->tile)) { // XXX is this necessary?
-		int base_offset;
-		bool ice = HasBridgeSnowOrDesert(ti->tile);
-
-		if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
-			base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
-			assert(base_offset != 8); /* This one is used for roads */
-		} else {
-			base_offset = 8;
-		}
-
-		/* as the lower 3 bits are used for other stuff, make sure they are clear */
-		assert( (base_offset & 0x07) == 0x00);
+	int base_offset;
+	bool ice = HasBridgeSnowOrDesert(ti->tile);
 
-		if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) {
-			int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
-			if (f != 0) DrawFoundation(ti, f);
-		}
-
-		// HACK Wizardry to convert the bridge ramp direction into a sprite offset
-		base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
-
-		if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
-
-		/* Table number 6 always refers to the bridge heads for any bridge type */
-		image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
+	if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
+		base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
+		assert(base_offset != 8); /* This one is used for roads */
+	} else {
+		base_offset = 8;
+	}
 
-		if (!ice) {
-			DrawClearLandTile(ti, 3);
-		} else {
-			DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]);
-		}
-
-		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+	/* as the lower 3 bits are used for other stuff, make sure they are clear */
+	assert( (base_offset & 0x07) == 0x00);
 
-		// draw ramp
-		if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
-		/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
-		 * it doesn't disappear behind it
-		 */
-		AddSortableSpriteToDraw(
-			image, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 1 : 8, ti->z
-		);
+	if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) {
+		int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
+		if (f != 0) DrawFoundation(ti, f);
+	}
 
-		DrawBridgeMiddle(ti);
+	// HACK Wizardry to convert the bridge ramp direction into a sprite offset
+	base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
+
+	if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
+
+	/* Table number 6 always refers to the bridge heads for any bridge type */
+	image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
+
+	if (!ice) {
+		DrawClearLandTile(ti, 3);
+	} else {
+		DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]);
 	}
+
+	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+
+	// draw ramp
+	if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
+	/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
+	 * it doesn't disappear behind it
+	 */
+	AddSortableSpriteToDraw(
+		image, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 1 : 8, ti->z
+	);
+
+	DrawBridgeMiddle(ti);
 }
 
 
@@ -987,76 +994,111 @@
 }
 
 
-
-static uint GetSlopeZ_TunnelBridge(TileIndex tile, uint x, uint y)
+/** Gets the absolute z coordinate of a point inside a tunnel tile
+ *  When we're on the track (that means between position 5 and 10)
+ *  on the coordinate perpendicular to the track it returns only the
+ *  base height of the tile (because the track is horizontal).
+ *  Outside this range (from 0 to 4 and from 11 to 15) it returns the
+ *  "true" Z coordinate of the tile by taking the slope into account
+ *  @param tile The index of the tile we are talking about
+ *  @param x Absolute or relative x coordinate
+ *  @param y Absolute or relative y coordinate
+ *  @return Absolute z coordinate
+ */
+static uint GetSlopeZ_Tunnel(TileIndex tile, uint x, uint y)
 {
-	uint z;
+	uint z, pos;
 	Slope tileh = GetTileSlope(tile, &z);
 
 	x &= 0xF;
 	y &= 0xF;
 
-	if (IsTunnelTile(tile)) {
-		uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x);
-
-		// In the tunnel entrance?
-		if (5 <= pos && pos <= 10) return z;
-	} else {
-		DiagDirection dir = GetBridgeRampDirection(tile);
-		uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
-
-		// On the bridge ramp?
-		if (5 <= pos && pos <= 10) {
-			uint delta;
-
-			if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2;
-			if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT;
+	pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x);
 
-			if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT;
-			switch (dir) {
-				default: NOT_REACHED();
-				case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
-				case DIAGDIR_SE: delta = y / 2; break;
-				case DIAGDIR_SW: delta = x / 2; break;
-				case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
-			}
-			return z + 1 + delta;
-		} else {
-			uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir));
-
-			if (f != 0) {
-				if (IsSteepSlope(tileh)) {
-					z += TILE_HEIGHT;
-				} else if (f < 15) {
-					return z + TILE_HEIGHT;
-				}
-				tileh = _inclined_tileh[f - 15];
-			}
-		}
-	}
+	// In the tunnel entrance?
+	if (5 <= pos && pos <= 10) return z;
 
 	return z + GetPartialZ(x, y, tileh);
 }
 
-static Slope GetSlopeTileh_TunnelBridge(TileIndex tile, Slope tileh)
+/** Gets the absolute z coordinate of a point inside a bridge tile
+ *  When we're on the track (that means between position 5 and 10)
+ *  on the coordinate perpendicular to the track it returns the base
+ *  height of the ramp
+ *  Outside this range (from 0 to 4 and from 11 to 15) it returns the
+ *  "true" Z coordinate of the tile by taking the slope into account
+ *  @param tile The index of the tile we are talking about
+ *  @param x Absolute or relative x coordinate
+ *  @param y Absolute or relative y coordinate
+ *  @return Absolute z coordinate
+ */
+static uint GetSlopeZ_Bridge(TileIndex tile, uint x, uint y)
 {
-	if (IsTunnelTile(tile)) {
+	uint z, pos;
+	Slope tileh = GetTileSlope(tile, &z);
+	DiagDirection dir = GetBridgeRampDirection(tile);
+
+	x &= 0xF;
+	y &= 0xF;
+
+	pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
+
+	// On the bridge ramp?
+	if (5 <= pos && pos <= 10) {
+		uint delta;
+
+		if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2;
+
+		if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT;
+
+		if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT;
+		switch (dir) {
+			default: NOT_REACHED();
+			case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
+			case DIAGDIR_SE: delta = y / 2; break;
+			case DIAGDIR_SW: delta = x / 2; break;
+			case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
+		}
+		return z + 1 + delta;
+	} else {
+		uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir));
+
+		if (f != 0) {
+			if (IsSteepSlope(tileh)) {
+				z += TILE_HEIGHT;
+			} else if (f < 15) {
+				return z + TILE_HEIGHT;
+			}
+			tileh = _inclined_tileh[f - 15];
+		}
+	}
+	return z + GetPartialZ(x, y, tileh);
+}
+
+static Slope GetSlopeTileh_Tunnel(TileIndex tile, Slope tileh)
+{
+	return tileh;
+}
+
+static Slope GetSlopeTileh_Bridge(TileIndex tile, Slope tileh)
+{
+	if (HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
 		return tileh;
 	} else {
-		if (HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
-			return tileh;
-		} else {
-			uint f = GetBridgeFoundation(tileh, DiagDirToAxis(GetBridgeRampDirection(tile)));
+		uint f = GetBridgeFoundation(tileh, DiagDirToAxis(GetBridgeRampDirection(tile)));
 
-			if (f == 0) return tileh;
-			if (f < 15) return SLOPE_FLAT;
-			return _inclined_tileh[f - 15];
-		}
+		if (f == 0) return tileh;
+		if (f < 15) return SLOPE_FLAT;
+		return _inclined_tileh[f - 15];
 	}
 }
 
+static void GetAcceptedCargo_Tunnel(TileIndex tile, AcceptedCargo ac)
+{
+	/* not used */
+}
 
-static void GetAcceptedCargo_TunnelBridge(TileIndex tile, AcceptedCargo ac)
+static void GetAcceptedCargo_Bridge(TileIndex tile, AcceptedCargo ac)
 {
 	/* not used */
 }
@@ -1093,69 +1135,104 @@
 	0, 0, 0,
 };
 
-static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
+static void GetTileDesc_Tunnel(TileIndex tile, TileDesc *td)
 {
-	if (IsTunnelTile(tile)) {
-		td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ?
-			STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
-	} else {
-		td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
-	}
+	td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ?  STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
+	td->owner = GetTileOwner(tile);
+}
+
+static void GetTileDesc_Bridge(TileIndex tile, TileDesc *td)
+{
+	td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
 	td->owner = GetTileOwner(tile);
 }
 
 
-static void AnimateTile_TunnelBridge(TileIndex tile)
+static void AnimateTile_Tunnel(TileIndex tile)
 {
 	/* not used */
 }
 
-static void TileLoop_TunnelBridge(TileIndex tile)
+static void AnimateTile_Bridge(TileIndex tile)
 {
-	bool snow_or_desert = IsTunnelTile(tile) ? HasTunnelSnowOrDesert(tile) : HasBridgeSnowOrDesert(tile);
+	/* not used */
+}
+
+static void TileLoop_Tunnel(TileIndex tile)
+{
+	bool snow_or_desert = HasTunnelSnowOrDesert(tile);
 	switch (_opt.landscape) {
 		case LT_HILLY:
 			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
-				if (IsTunnelTile(tile)) {
-					SetTunnelSnowOrDesert(tile, !snow_or_desert);
-				} else {
-					SetBridgeSnowOrDesert(tile, !snow_or_desert);
-				}
+				SetTunnelSnowOrDesert(tile, !snow_or_desert);
 				MarkTileDirtyByTile(tile);
 			}
 			break;
 
 		case LT_DESERT:
 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
-				if (IsTunnelTile(tile)) {
-					SetTunnelSnowOrDesert(tile, true);
-				} else {
-					SetBridgeSnowOrDesert(tile, true);
-				}
+				SetTunnelSnowOrDesert(tile, true);
 				MarkTileDirtyByTile(tile);
 			}
 			break;
 	}
 }
 
-static void ClickTile_TunnelBridge(TileIndex tile)
+static void TileLoop_Bridge(TileIndex tile)
+{
+	bool snow_or_desert = HasBridgeSnowOrDesert(tile);
+	switch (_opt.landscape) {
+		case LT_HILLY:
+			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
+				SetBridgeSnowOrDesert(tile, !snow_or_desert);
+				MarkTileDirtyByTile(tile);
+			}
+			break;
+
+		case LT_DESERT:
+			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
+				SetBridgeSnowOrDesert(tile, true);
+				MarkTileDirtyByTile(tile);
+			}
+			break;
+	}
+}
+
+static void ClickTile_Tunnel(TileIndex tile)
+{
+	/* not used */
+}
+
+static void ClickTile_Bridge(TileIndex tile)
 {
 	/* not used */
 }
 
 
-static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Tunnel(TileIndex tile, TransportType mode)
 {
-	if (IsTunnelTile(tile)) {
-		if (GetTunnelTransportType(tile) != mode) return 0;
-		return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101;
+	if (GetTunnelTransportType(tile) != mode) return 0;
+	return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101;
+}
+
+static uint32 GetTileTrackStatus_Bridge(TileIndex tile, TransportType mode)
+{
+	if (GetBridgeTransportType(tile) != mode) return 0;
+	return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
+}
+
+static void ChangeTileOwner_Tunnel(TileIndex tile, PlayerID old_player, PlayerID new_player)
+{
+	if (!IsTileOwner(tile, old_player)) return;
+
+	if (new_player != PLAYER_SPECTATOR) {
+		SetTileOwner(tile, new_player);
 	} else {
-		if (GetBridgeTransportType(tile) != mode) return 0;
-		return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
+		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 	}
 }
 
-static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
+static void ChangeTileOwner_Bridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
 {
 	if (!IsTileOwner(tile, old_player)) return;
 
@@ -1180,137 +1257,159 @@
 static const byte _tunnel_fractcoord_6[4]    = {0x92, 0x89, 0x56, 0x45};
 static const byte _tunnel_fractcoord_7[4]    = {0x52, 0x85, 0x96, 0x49};
 
-static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
+static uint32 VehicleEnter_Tunnel(Vehicle *v, TileIndex tile, int x, int y)
 {
 	int z = GetSlopeZ(x, y) - v->z_pos;
 
+	byte fc;
+	DiagDirection dir;
+	DiagDirection vdir;
+
 	if (myabs(z) > 2) return 8;
 
-	if (IsTunnelTile(tile)) {
-		byte fc;
-		DiagDirection dir;
-		DiagDirection vdir;
-
-		if (v->type == VEH_Train) {
-			fc = (x & 0xF) + (y << 4);
-
-			dir = GetTunnelDirection(tile);
-			vdir = DirToDiagDir(v->direction);
+	if (v->type == VEH_Train) {
+		fc = (x & 0xF) + (y << 4);
 
-			if (v->u.rail.track != 0x40 && dir == vdir) {
-				if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
-					if (!PlayVehicleSound(v, VSE_TUNNEL) && v->spritenum < 4) {
-						SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
-					}
-					return 0;
+		dir = GetTunnelDirection(tile);
+		vdir = DirToDiagDir(v->direction);
+
+		if (v->u.rail.track != 0x40 && dir == vdir) {
+			if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
+				if (!PlayVehicleSound(v, VSE_TUNNEL) && v->spritenum < 4) {
+					SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
 				}
-				if (fc == _tunnel_fractcoord_2[dir]) {
-					v->tile = tile;
-					v->u.rail.track = 0x40;
-					v->vehstatus |= VS_HIDDEN;
-					return 4;
-				}
+				return 0;
 			}
-
-			if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) {
-				/* We're at the tunnel exit ?? */
+			if (fc == _tunnel_fractcoord_2[dir]) {
 				v->tile = tile;
-				v->u.rail.track = _exit_tunnel_track[dir];
-				assert(v->u.rail.track);
-				v->vehstatus &= ~VS_HIDDEN;
-				return 4;
-			}
-		} else if (v->type == VEH_Road) {
-			fc = (x & 0xF) + (y << 4);
-			dir = GetTunnelDirection(tile);
-			vdir = DirToDiagDir(v->direction);
-
-			// Enter tunnel?
-			if (v->u.road.state != 0xFF && dir == vdir) {
-				if (fc == _tunnel_fractcoord_4[dir] ||
-						fc == _tunnel_fractcoord_5[dir]) {
-					v->tile = tile;
-					v->u.road.state = 0xFF;
-					v->vehstatus |= VS_HIDDEN;
-					return 4;
-				} else {
-					return 0;
-				}
-			}
-
-			if (dir == ReverseDiagDir(vdir) && (
-						/* We're at the tunnel exit ?? */
-						fc == _tunnel_fractcoord_6[dir] ||
-						fc == _tunnel_fractcoord_7[dir]
-					) &&
-					z == 0) {
-				v->tile = tile;
-				v->u.road.state = _road_exit_tunnel_state[dir];
-				v->u.road.frame = _road_exit_tunnel_frame[dir];
-				v->vehstatus &= ~VS_HIDDEN;
+				v->u.rail.track = 0x40;
+				v->vehstatus |= VS_HIDDEN;
 				return 4;
 			}
 		}
-	} else if (IsBridgeTile(tile)) { // XXX is this necessary?
-		DiagDirection dir;
 
-		if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) {
-			/* modify speed of vehicle */
-			uint16 spd = _bridge[GetBridgeType(tile)].speed;
+		if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) {
+			/* We're at the tunnel exit ?? */
+			v->tile = tile;
+			v->u.rail.track = _exit_tunnel_track[dir];
+			assert(v->u.rail.track);
+			v->vehstatus &= ~VS_HIDDEN;
+			return 4;
+		}
+	} else if (v->type == VEH_Road) {
+		fc = (x & 0xF) + (y << 4);
+		dir = GetTunnelDirection(tile);
+		vdir = DirToDiagDir(v->direction);
 
-			if (v->type == VEH_Road) spd *= 2;
-			if (v->cur_speed > spd) v->cur_speed = spd;
+		// Enter tunnel?
+		if (v->u.road.state != 0xFF && dir == vdir) {
+			if (fc == _tunnel_fractcoord_4[dir] ||
+					fc == _tunnel_fractcoord_5[dir]) {
+				v->tile = tile;
+				v->u.road.state = 0xFF;
+				v->vehstatus |= VS_HIDDEN;
+				return 4;
+			} else {
+				return 0;
+			}
 		}
 
-		dir = GetBridgeRampDirection(tile);
-		if (DirToDiagDir(v->direction) == dir) {
-			switch (dir) {
-				default: NOT_REACHED();
-				case DIAGDIR_NE: if ((x & 0xF) != 0)             return 0; break;
-				case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break;
-				case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break;
-				case DIAGDIR_NW: if ((y & 0xF) != 0)             return 0; break;
-			}
-			if (v->type == VEH_Train) {
-				v->u.rail.track = 0x40;
-				CLRBIT(v->u.rail.flags, VRF_GOINGUP);
-				CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
-			} else {
-				v->u.road.state = 0xFF;
-			}
+		if (dir == ReverseDiagDir(vdir) && (
+					/* We're at the tunnel exit ?? */
+					fc == _tunnel_fractcoord_6[dir] ||
+					fc == _tunnel_fractcoord_7[dir]
+				) &&
+				z == 0) {
+			v->tile = tile;
+			v->u.road.state = _road_exit_tunnel_state[dir];
+			v->u.road.frame = _road_exit_tunnel_frame[dir];
+			v->vehstatus &= ~VS_HIDDEN;
 			return 4;
-		} else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
-			v->tile = tile;
-			if (v->type == VEH_Train) {
-				if (v->u.rail.track == 0x40) {
-					v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
-					return 4;
-				}
-			} else {
-				if (v->u.road.state == 0xFF) {
-					v->u.road.state = _road_exit_tunnel_state[dir];
-					v->u.road.frame = 0;
-					return 4;
-				}
-			}
-			return 0;
 		}
 	}
 	return 0;
 }
 
-const TileTypeProcs _tile_type_tunnelbridge_procs = {
-	DrawTile_TunnelBridge,           /* draw_tile_proc */
-	GetSlopeZ_TunnelBridge,          /* get_slope_z_proc */
-	ClearTile_TunnelBridge,          /* clear_tile_proc */
-	GetAcceptedCargo_TunnelBridge,   /* get_accepted_cargo_proc */
-	GetTileDesc_TunnelBridge,        /* get_tile_desc_proc */
-	GetTileTrackStatus_TunnelBridge, /* get_tile_track_status_proc */
-	ClickTile_TunnelBridge,          /* click_tile_proc */
-	AnimateTile_TunnelBridge,        /* animate_tile_proc */
-	TileLoop_TunnelBridge,           /* tile_loop_clear */
-	ChangeTileOwner_TunnelBridge,    /* change_tile_owner_clear */
+static uint32 VehicleEnter_Bridge(Vehicle *v, TileIndex tile, int x, int y)
+{
+	int z = GetSlopeZ(x, y) - v->z_pos;
+
+	DiagDirection dir;
+
+	if (myabs(z) > 2) return 8;
+
+	if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) {
+		/* modify speed of vehicle */
+		uint16 spd = _bridge[GetBridgeType(tile)].speed;
+
+		if (v->type == VEH_Road) spd *= 2;
+		if (v->cur_speed > spd) v->cur_speed = spd;
+	}
+
+	dir = GetBridgeRampDirection(tile);
+	if (DirToDiagDir(v->direction) == dir) {
+		switch (dir) {
+			default: NOT_REACHED();
+			case DIAGDIR_NE: if ((x & 0xF) != 0)             return 0; break;
+			case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break;
+			case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break;
+			case DIAGDIR_NW: if ((y & 0xF) != 0)             return 0; break;
+		}
+		if (v->type == VEH_Train) {
+			v->u.rail.track = 0x40;
+			CLRBIT(v->u.rail.flags, VRF_GOINGUP);
+			CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
+		} else {
+			v->u.road.state = 0xFF;
+		}
+		return 4;
+	} else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
+		v->tile = tile;
+		if (v->type == VEH_Train) {
+			if (v->u.rail.track == 0x40) {
+				v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
+				return 4;
+			}
+		} else {
+			if (v->u.road.state == 0xFF) {
+				v->u.road.state = _road_exit_tunnel_state[dir];
+				v->u.road.frame = 0;
+				return 4;
+			}
+		}
+		return 0;
+	}
+	return 0;
+}
+
+const TileTypeProcs _tile_type_tunnel_procs = {
+	DrawTile_Tunnel,           /* draw_tile_proc */
+	GetSlopeZ_Tunnel,          /* get_slope_z_proc */
+	ClearTile_Tunnel,          /* clear_tile_proc */
+	GetAcceptedCargo_Tunnel,   /* get_accepted_cargo_proc */
+	GetTileDesc_Tunnel,        /* get_tile_desc_proc */
+	GetTileTrackStatus_Tunnel, /* get_tile_track_status_proc */
+	ClickTile_Tunnel,          /* click_tile_proc */
+	AnimateTile_Tunnel,        /* animate_tile_proc */
+	TileLoop_Tunnel,           /* tile_loop_clear */
+	ChangeTileOwner_Tunnel,    /* change_tile_owner_clear */
 	NULL,                            /* get_produced_cargo_proc */
-	VehicleEnter_TunnelBridge,       /* vehicle_enter_tile_proc */
-	GetSlopeTileh_TunnelBridge,      /* get_slope_tileh_proc */
+	VehicleEnter_Tunnel,       /* vehicle_enter_tile_proc */
+	GetSlopeTileh_Tunnel,      /* get_slope_tileh_proc */
 };
+
+const TileTypeProcs _tile_type_bridge_procs = {
+	DrawTile_Bridge,           /* draw_tile_proc */
+	GetSlopeZ_Bridge,          /* get_slope_z_proc */
+	ClearTile_Bridge,          /* clear_tile_proc */
+	GetAcceptedCargo_Bridge,   /* get_accepted_cargo_proc */
+	GetTileDesc_Bridge,        /* get_tile_desc_proc */
+	GetTileTrackStatus_Bridge, /* get_tile_track_status_proc */
+	ClickTile_Bridge,          /* click_tile_proc */
+	AnimateTile_Bridge,        /* animate_tile_proc */
+	TileLoop_Bridge,           /* tile_loop_clear */
+	ChangeTileOwner_Bridge,    /* change_tile_owner_clear */
+	NULL,                      /* get_produced_cargo_proc */
+	VehicleEnter_Bridge,       /* vehicle_enter_tile_proc */
+	GetSlopeTileh_Bridge,      /* get_slope_tileh_proc */
+};