src/tunnelbridge_cmd.cpp
changeset 8083 ad22eade501f
parent 8081 4fddceb00aa6
child 8088 92fca5b09665
equal deleted inserted replaced
8082:63240e1bd6cc 8083:ad22eade501f
    32 #include "yapf/yapf.h"
    32 #include "yapf/yapf.h"
    33 #include "date.h"
    33 #include "date.h"
    34 #include "newgrf_sound.h"
    34 #include "newgrf_sound.h"
    35 #include "autoslope.h"
    35 #include "autoslope.h"
    36 #include "transparency.h"
    36 #include "transparency.h"
    37 
    37 #include "tunnelbridge_map.h"
    38 #include "table/bridge_land.h"
    38 #include "table/bridge_land.h"
       
    39 
    39 
    40 
    40 const Bridge orig_bridge[] = {
    41 const Bridge orig_bridge[] = {
    41 /*
    42 /*
    42 	     year of availablity
    43 	     year of availablity
    43 	     |  minimum length
    44 	     |  minimum length
   264 
   265 
   265 	TransportType transport_type = railtype == INVALID_RAILTYPE ? TRANSPORT_ROAD : TRANSPORT_RAIL;
   266 	TransportType transport_type = railtype == INVALID_RAILTYPE ? TRANSPORT_ROAD : TRANSPORT_RAIL;
   266 
   267 
   267 	if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
   268 	if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
   268 			GetOtherBridgeEnd(tile_start) == tile_end &&
   269 			GetOtherBridgeEnd(tile_start) == tile_end &&
   269 			GetBridgeTransportType(tile_start) == transport_type) {
   270 			GetTunnelBridgeTransportType(tile_start) == transport_type) {
   270 		/* Replace a current bridge. */
   271 		/* Replace a current bridge. */
   271 
   272 
   272 		/* If this is a railway bridge, make sure the railtypes match. */
   273 		/* If this is a railway bridge, make sure the railtypes match. */
   273 		if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
   274 		if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
   274 			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   275 			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   389 				break;
   390 				break;
   390 
   391 
   391 			case MP_TUNNELBRIDGE:
   392 			case MP_TUNNELBRIDGE:
   392 				if (IsTunnel(tile)) break;
   393 				if (IsTunnel(tile)) break;
   393 				if (replace_bridge) break;
   394 				if (replace_bridge) break;
   394 				if (direction == DiagDirToAxis(GetBridgeRampDirection(tile))) goto not_valid_below;
   395 				if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below;
   395 				if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
   396 				if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
   396 				break;
   397 				break;
   397 
   398 
   398 			case MP_UNMOVABLE:
   399 			case MP_UNMOVABLE:
   399 				if (!IsOwnedLand(tile)) goto not_valid_below;
   400 				if (!IsOwnedLand(tile)) goto not_valid_below;
   600 	}
   601 	}
   601 
   602 
   602 	if (flags & DC_EXEC) {
   603 	if (flags & DC_EXEC) {
   603 		/* We first need to request the direction before calling DoClearSquare
   604 		/* We first need to request the direction before calling DoClearSquare
   604 		 *  else the direction is always 0.. dah!! ;) */
   605 		 *  else the direction is always 0.. dah!! ;) */
   605 		DiagDirection dir = GetTunnelDirection(tile);
   606 		DiagDirection dir = GetTunnelBridgeDirection(tile);
   606 		Track track;
   607 		Track track;
   607 
   608 
   608 		/* Adjust the town's player rating. Do this before removing the tile owner info. */
   609 		/* Adjust the town's player rating. Do this before removing the tile owner info. */
   609 		if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR)
   610 		if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR)
   610 			ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
   611 			ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
   634 
   635 
   635 	endtile = GetOtherBridgeEnd(tile);
   636 	endtile = GetOtherBridgeEnd(tile);
   636 
   637 
   637 	if (GetVehicleTunnelBridge(tile, endtile) != NULL) return CMD_ERROR;
   638 	if (GetVehicleTunnelBridge(tile, endtile) != NULL) return CMD_ERROR;
   638 
   639 
   639 	direction = GetBridgeRampDirection(tile);
   640 	direction = GetTunnelBridgeDirection(tile);
   640 	delta = TileOffsByDiagDir(direction);
   641 	delta = TileOffsByDiagDir(direction);
   641 
   642 
   642 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
   643 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
   643 		t = ClosestTownFromTile(tile, (uint)-1); // town penalty rating
   644 		t = ClosestTownFromTile(tile, (uint)-1); // town penalty rating
   644 
   645 
   699  * @return            The cost and state of the operation
   700  * @return            The cost and state of the operation
   700  * @retval CMD_ERROR  An error occured during the operation.
   701  * @retval CMD_ERROR  An error occured during the operation.
   701  */
   702  */
   702 CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
   703 CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
   703 {
   704 {
   704 	if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) {
   705 	if (IsTunnel(tile) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
   705 		TileIndex endtile = GetOtherTunnelEnd(tile);
   706 		TileIndex endtile = GetOtherTunnelEnd(tile);
   706 
   707 
   707 		/* If not coverting rail <-> el. rail, any vehicle cannot be in tunnel */
   708 		/* If not coverting rail <-> el. rail, any vehicle cannot be in tunnel */
   708 		if (!IsCompatibleRail(GetRailType(tile), totype) &&
   709 		if (!IsCompatibleRail(GetRailType(tile), totype) &&
   709 				GetVehicleTunnelBridge(tile, endtile) != NULL) {
   710 				GetVehicleTunnelBridge(tile, endtile) != NULL) {
   714 			SetRailType(tile, totype);
   715 			SetRailType(tile, totype);
   715 			SetRailType(endtile, totype);
   716 			SetRailType(endtile, totype);
   716 			MarkTileDirtyByTile(tile);
   717 			MarkTileDirtyByTile(tile);
   717 			MarkTileDirtyByTile(endtile);
   718 			MarkTileDirtyByTile(endtile);
   718 
   719 
   719 			Track track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile)));
   720 			Track track = AxisToTrack(DiagDirToAxis(GetTunnelBridgeDirection(tile)));
   720 
   721 
   721 			YapfNotifyTrackLayoutChange(tile, track);
   722 			YapfNotifyTrackLayoutChange(tile, track);
   722 			YapfNotifyTrackLayoutChange(endtile, track);
   723 			YapfNotifyTrackLayoutChange(endtile, track);
   723 
   724 
   724 			VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
   725 			VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
   725 			VehicleFromPos(endtile, NULL, &UpdateTrainPowerProc);
   726 			VehicleFromPos(endtile, NULL, &UpdateTrainPowerProc);
   726 		}
   727 		}
   727 
   728 
   728 		return CommandCost((DistanceManhattan(tile, endtile) + 1) * RailConvertCost(GetRailType(tile), totype));
   729 		return CommandCost((DistanceManhattan(tile, endtile) + 1) * RailConvertCost(GetRailType(tile), totype));
   729 	} else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
   730 	} else if (IsBridge(tile) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
   730 		TileIndex endtile = GetOtherBridgeEnd(tile);
   731 		TileIndex endtile = GetOtherBridgeEnd(tile);
   731 
   732 
   732 		if (!IsCompatibleRail(GetRailType(tile), totype) &&
   733 		if (!IsCompatibleRail(GetRailType(tile), totype) &&
   733 				GetVehicleTunnelBridge(tile, endtile) != NULL) {
   734 				GetVehicleTunnelBridge(tile, endtile) != NULL) {
   734 			return CMD_ERROR;
   735 			return CMD_ERROR;
   738 			SetRailType(tile, totype);
   739 			SetRailType(tile, totype);
   739 			SetRailType(endtile, totype);
   740 			SetRailType(endtile, totype);
   740 			MarkTileDirtyByTile(tile);
   741 			MarkTileDirtyByTile(tile);
   741 			MarkTileDirtyByTile(endtile);
   742 			MarkTileDirtyByTile(endtile);
   742 
   743 
   743 			Track track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile)));
   744 			Track track = AxisToTrack(DiagDirToAxis(GetTunnelBridgeDirection(tile)));
   744 			TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
   745 			TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
   745 
   746 
   746 			YapfNotifyTrackLayoutChange(tile, track);
   747 			YapfNotifyTrackLayoutChange(tile, track);
   747 			YapfNotifyTrackLayoutChange(endtile, track);
   748 			YapfNotifyTrackLayoutChange(endtile, track);
   748 
   749 
   749 			VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
   750 			VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
   892 			{  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // NE
   893 			{  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // NE
   893 			{  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // SE
   894 			{  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // SE
   894 			{  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // SW
   895 			{  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // SW
   895 			{  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // NW
   896 			{  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // NW
   896 		};
   897 		};
   897 		const int *BB_data = _tunnel_BB[GetTunnelDirection(ti->tile)];
   898 		const int *BB_data = _tunnel_BB[GetTunnelBridgeDirection(ti->tile)];
   898 
   899 
   899 		bool catenary = false;
   900 		bool catenary = false;
   900 
   901 
   901 		if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) {
   902 		if (GetTunnelBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
   902 			image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.tunnel;
   903 			image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.tunnel;
   903 		} else {
   904 		} else {
   904 			image = SPR_TUNNEL_ENTRY_REAR_ROAD;
   905 			image = SPR_TUNNEL_ENTRY_REAR_ROAD;
   905 		}
   906 		}
   906 
   907 
   907 		if (HasTunnelSnowOrDesert(ti->tile)) image += 32;
   908 		if (HasTunnelBridgeSnowOrDesert(ti->tile)) image += 32;
   908 
   909 
   909 		image += GetTunnelDirection(ti->tile) * 2;
   910 		image += GetTunnelBridgeDirection(ti->tile) * 2;
   910 		DrawGroundSprite(image, PAL_NONE);
   911 		DrawGroundSprite(image, PAL_NONE);
   911 		if (GetTunnelTransportType(ti->tile) == TRANSPORT_ROAD) {
   912 		if (GetTunnelBridgeTransportType(ti->tile) == TRANSPORT_ROAD) {
   912 			DiagDirection dir = GetTunnelDirection(ti->tile);
   913 			DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
   913 			RoadTypes rts = GetRoadTypes(ti->tile);
   914 			RoadTypes rts = GetRoadTypes(ti->tile);
   914 
   915 
   915 			if (HasBit(rts, ROADTYPE_TRAM)) {
   916 			if (HasBit(rts, ROADTYPE_TRAM)) {
   916 				static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, {  5, 76, 77,  4 } };
   917 				static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, {  5, 76, 77,  4 } };
   917 
   918 
   939 
   940 
   940 		DrawBridgeMiddle(ti);
   941 		DrawBridgeMiddle(ti);
   941 	} else if (IsBridge(ti->tile)) { // XXX is this necessary?
   942 	} else if (IsBridge(ti->tile)) { // XXX is this necessary?
   942 		const PalSpriteID *psid;
   943 		const PalSpriteID *psid;
   943 		int base_offset;
   944 		int base_offset;
   944 		bool ice = HasBridgeSnowOrDesert(ti->tile);
   945 		bool ice = HasTunnelBridgeSnowOrDesert(ti->tile);
   945 
   946 
   946 		if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
   947 		if (GetTunnelBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
   947 			base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
   948 			base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
   948 			assert(base_offset != 8); // This one is used for roads
   949 			assert(base_offset != 8); // This one is used for roads
   949 		} else {
   950 		} else {
   950 			base_offset = 8;
   951 			base_offset = 8;
   951 		}
   952 		}
   952 
   953 
   953 		/* as the lower 3 bits are used for other stuff, make sure they are clear */
   954 		/* as the lower 3 bits are used for other stuff, make sure they are clear */
   954 		assert( (base_offset & 0x07) == 0x00);
   955 		assert( (base_offset & 0x07) == 0x00);
   955 
   956 
   956 		DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))));
   957 		DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetTunnelBridgeDirection(ti->tile))));
   957 
   958 
   958 		/* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
   959 		/* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
   959 		base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
   960 		base_offset += (6 - GetTunnelBridgeDirection(ti->tile)) % 4;
   960 
   961 
   961 		if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
   962 		if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
   962 
   963 
   963 		/* Table number 6 always refers to the bridge heads for any bridge type */
   964 		/* Table number 6 always refers to the bridge heads for any bridge type */
   964 		psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
   965 		psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
   970 		}
   971 		}
   971 
   972 
   972 		/* draw ramp */
   973 		/* draw ramp */
   973 
   974 
   974 		/* Draw Trambits as SpriteCombine */
   975 		/* Draw Trambits as SpriteCombine */
   975 		if (GetBridgeTransportType(ti->tile) == TRANSPORT_ROAD) StartSpriteCombine();
   976 		if (GetTunnelBridgeTransportType(ti->tile) == TRANSPORT_ROAD) StartSpriteCombine();
   976 
   977 
   977 		/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
   978 		/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
   978 		 * it doesn't disappear behind it
   979 		 * it doesn't disappear behind it
   979 		 */
   980 		 */
   980 		AddSortableSpriteToDraw(
   981 		AddSortableSpriteToDraw(
   981 			psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z, IsTransparencySet(TO_BRIDGES)
   982 			psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z, IsTransparencySet(TO_BRIDGES)
   982 		);
   983 		);
   983 
   984 
   984 		if (GetBridgeTransportType(ti->tile) == TRANSPORT_ROAD) {
   985 		if (GetTunnelBridgeTransportType(ti->tile) == TRANSPORT_ROAD) {
   985 			RoadTypes rts = GetRoadTypes(ti->tile);
   986 			RoadTypes rts = GetRoadTypes(ti->tile);
   986 
   987 
   987 			if (HasBit(rts, ROADTYPE_TRAM)) {
   988 			if (HasBit(rts, ROADTYPE_TRAM)) {
   988 				uint offset = GetBridgeRampDirection(ti->tile);
   989 				uint offset = GetTunnelBridgeDirection(ti->tile);
   989 				uint z = ti->z;
   990 				uint z = ti->z;
   990 				if (ti->tileh != SLOPE_FLAT) {
   991 				if (ti->tileh != SLOPE_FLAT) {
   991 					offset = (offset + 1) & 1;
   992 					offset = (offset + 1) & 1;
   992 					z += TILE_HEIGHT;
   993 					z += TILE_HEIGHT;
   993 				} else {
   994 				} else {
  1082 		DistanceManhattan(ti->tile, rampnorth),
  1083 		DistanceManhattan(ti->tile, rampnorth),
  1083 		DistanceManhattan(ti->tile, rampsouth)
  1084 		DistanceManhattan(ti->tile, rampsouth)
  1084 	);
  1085 	);
  1085 	type = GetBridgeType(rampsouth);
  1086 	type = GetBridgeType(rampsouth);
  1086 
  1087 
  1087 	if (GetBridgeTransportType(rampsouth) == TRANSPORT_RAIL) {
  1088 	if (GetTunnelBridgeTransportType(rampsouth) == TRANSPORT_RAIL) {
  1088 		base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
  1089 		base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
  1089 	} else {
  1090 	} else {
  1090 		base_offset = 8;
  1091 		base_offset = 8;
  1091 	}
  1092 	}
  1092 
  1093 
  1100 
  1101 
  1101 	/* Add a bounding box, that separates the bridge from things below it. */
  1102 	/* Add a bounding box, that separates the bridge from things below it. */
  1102 	AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
  1103 	AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
  1103 
  1104 
  1104 	/* Draw Trambits as SpriteCombine */
  1105 	/* Draw Trambits as SpriteCombine */
  1105 	if (GetBridgeTransportType(rampsouth) == TRANSPORT_ROAD) StartSpriteCombine();
  1106 	if (GetTunnelBridgeTransportType(rampsouth) == TRANSPORT_ROAD) StartSpriteCombine();
  1106 
  1107 
  1107 	/* Draw floor and far part of bridge*/
  1108 	/* Draw floor and far part of bridge*/
  1108 	if (axis == AXIS_X) {
  1109 	if (axis == AXIS_X) {
  1109 		AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
  1110 		AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
  1110 	} else {
  1111 	} else {
  1111 		AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
  1112 		AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
  1112 	}
  1113 	}
  1113 
  1114 
  1114 	psid++;
  1115 	psid++;
  1115 
  1116 
  1116 	if (GetBridgeTransportType(rampsouth) == TRANSPORT_ROAD) {
  1117 	if (GetTunnelBridgeTransportType(rampsouth) == TRANSPORT_ROAD) {
  1117 		RoadTypes rts = GetRoadTypes(rampsouth);
  1118 		RoadTypes rts = GetRoadTypes(rampsouth);
  1118 
  1119 
  1119 		if (HasBit(rts, ROADTYPE_TRAM)) {
  1120 		if (HasBit(rts, ROADTYPE_TRAM)) {
  1120 			/* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
  1121 			/* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
  1121 			DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD));
  1122 			DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD));
  1135 		x += 12;
  1136 		x += 12;
  1136 		if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
  1137 		if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
  1137 	}
  1138 	}
  1138 
  1139 
  1139 	/* Draw TramFront as SpriteCombine */
  1140 	/* Draw TramFront as SpriteCombine */
  1140 	if (GetBridgeTransportType(rampsouth) == TRANSPORT_ROAD) EndSpriteCombine();
  1141 	if (GetTunnelBridgeTransportType(rampsouth) == TRANSPORT_ROAD) EndSpriteCombine();
  1141 
  1142 
  1142 	psid++;
  1143 	psid++;
  1143 	if (ti->z + 5 == z) {
  1144 	if (ti->z + 5 == z) {
  1144 		/* draw poles below for small bridges */
  1145 		/* draw poles below for small bridges */
  1145 		if (psid->sprite != 0) {
  1146 		if (psid->sprite != 0) {
  1166 
  1167 
  1167 	x &= 0xF;
  1168 	x &= 0xF;
  1168 	y &= 0xF;
  1169 	y &= 0xF;
  1169 
  1170 
  1170 	if (IsTunnel(tile)) {
  1171 	if (IsTunnel(tile)) {
  1171 		uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x);
  1172 		uint pos = (DiagDirToAxis(GetTunnelBridgeDirection(tile)) == AXIS_X ? y : x);
  1172 
  1173 
  1173 		/* In the tunnel entrance? */
  1174 		/* In the tunnel entrance? */
  1174 		if (5 <= pos && pos <= 10) return z;
  1175 		if (5 <= pos && pos <= 10) return z;
  1175 	} else {
  1176 	} else {
  1176 		DiagDirection dir = GetBridgeRampDirection(tile);
  1177 		DiagDirection dir = GetTunnelBridgeDirection(tile);
  1177 		uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
  1178 		uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
  1178 
  1179 
  1179 		z += ApplyFoundationToSlope(GetBridgeFoundation(tileh, DiagDirToAxis(dir)), &tileh);
  1180 		z += ApplyFoundationToSlope(GetBridgeFoundation(tileh, DiagDirToAxis(dir)), &tileh);
  1180 
  1181 
  1181 		/* On the bridge ramp? */
  1182 		/* On the bridge ramp? */
  1198 	return z + GetPartialZ(x, y, tileh);
  1199 	return z + GetPartialZ(x, y, tileh);
  1199 }
  1200 }
  1200 
  1201 
  1201 static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
  1202 static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
  1202 {
  1203 {
  1203 	return IsTunnel(tile) ? FOUNDATION_NONE : GetBridgeFoundation(tileh, DiagDirToAxis(GetBridgeRampDirection(tile)));
  1204 	return IsTunnel(tile) ? FOUNDATION_NONE : GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(tile)));
  1204 }
  1205 }
  1205 
  1206 
  1206 
  1207 
  1207 static void GetAcceptedCargo_TunnelBridge(TileIndex tile, AcceptedCargo ac)
  1208 static void GetAcceptedCargo_TunnelBridge(TileIndex tile, AcceptedCargo ac)
  1208 {
  1209 {
  1242 };
  1243 };
  1243 
  1244 
  1244 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
  1245 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
  1245 {
  1246 {
  1246 	if (IsTunnel(tile)) {
  1247 	if (IsTunnel(tile)) {
  1247 		td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ?
  1248 		td->str = (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) ?
  1248 			STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
  1249 			STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
  1249 	} else {
  1250 	} else {
  1250 		td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
  1251 		td->str = _bridge_tile_str[GetTunnelBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
  1251 	}
  1252 	}
  1252 	td->owner = GetTileOwner(tile);
  1253 	td->owner = GetTileOwner(tile);
  1253 }
  1254 }
  1254 
  1255 
  1255 
  1256 
  1258 	/* not used */
  1259 	/* not used */
  1259 }
  1260 }
  1260 
  1261 
  1261 static void TileLoop_TunnelBridge(TileIndex tile)
  1262 static void TileLoop_TunnelBridge(TileIndex tile)
  1262 {
  1263 {
  1263 	bool snow_or_desert = IsTunnelTile(tile) ? HasTunnelSnowOrDesert(tile) : HasBridgeSnowOrDesert(tile);
  1264 	bool snow_or_desert = IsTunnelTile(tile) ? HasTunnelBridgeSnowOrDesert(tile) : HasTunnelBridgeSnowOrDesert(tile);
  1264 	switch (_opt.landscape) {
  1265 	switch (_opt.landscape) {
  1265 		case LT_ARCTIC:
  1266 		case LT_ARCTIC:
  1266 			if (snow_or_desert != (GetTileZ(tile) > GetSnowLine())) {
  1267 			if (snow_or_desert != (GetTileZ(tile) > GetSnowLine())) {
  1267 				if (IsTunnelTile(tile)) {
  1268 				if (IsTunnelTile(tile)) {
  1268 					SetTunnelSnowOrDesert(tile, !snow_or_desert);
  1269 					SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
  1269 				} else {
  1270 				} else {
  1270 					SetBridgeSnowOrDesert(tile, !snow_or_desert);
  1271 					SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
  1271 				}
  1272 				}
  1272 				MarkTileDirtyByTile(tile);
  1273 				MarkTileDirtyByTile(tile);
  1273 			}
  1274 			}
  1274 			break;
  1275 			break;
  1275 
  1276 
  1276 		case LT_TROPIC:
  1277 		case LT_TROPIC:
  1277 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
  1278 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
  1278 				if (IsTunnelTile(tile)) {
  1279 				if (IsTunnelTile(tile)) {
  1279 					SetTunnelSnowOrDesert(tile, true);
  1280 					SetTunnelBridgeSnowOrDesert(tile, true);
  1280 				} else {
  1281 				} else {
  1281 					SetBridgeSnowOrDesert(tile, true);
  1282 					SetTunnelBridgeSnowOrDesert(tile, true);
  1282 				}
  1283 				}
  1283 				MarkTileDirtyByTile(tile);
  1284 				MarkTileDirtyByTile(tile);
  1284 			}
  1285 			}
  1285 			break;
  1286 			break;
  1286 	}
  1287 	}
  1293 
  1294 
  1294 
  1295 
  1295 static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode)
  1296 static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode)
  1296 {
  1297 {
  1297 	if (IsTunnel(tile)) {
  1298 	if (IsTunnel(tile)) {
  1298 		if (GetTunnelTransportType(tile) != mode) return 0;
  1299 		if (GetTunnelBridgeTransportType(tile) != mode) return 0;
  1299 		if (GetTunnelTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0;
  1300 		if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0;
  1300 		return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101;
  1301 		return AxisToTrackBits(DiagDirToAxis(GetTunnelBridgeDirection(tile))) * 0x101;
  1301 	} else {
  1302 	} else {
  1302 		if (GetBridgeTransportType(tile) != mode) return 0;
  1303 		if (GetTunnelBridgeTransportType(tile) != mode) return 0;
  1303 		if (GetBridgeTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0;
  1304 		if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0;
  1304 		return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
  1305 		return AxisToTrackBits(DiagDirToAxis(GetTunnelBridgeDirection(tile))) * 0x101;
  1305 	}
  1306 	}
  1306 }
  1307 }
  1307 
  1308 
  1308 static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1309 static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1309 {
  1310 {
  1315 		if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
  1316 		if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
  1316 			/* When clearing the bridge/tunnel failed there are still vehicles on/in
  1317 			/* When clearing the bridge/tunnel failed there are still vehicles on/in
  1317 			 * the bridge/tunnel. As all *our* vehicles are already removed, they
  1318 			 * the bridge/tunnel. As all *our* vehicles are already removed, they
  1318 			 * must be of another owner. Therefor this must be a road bridge/tunnel.
  1319 			 * must be of another owner. Therefor this must be a road bridge/tunnel.
  1319 			 * In that case we can safely reassign the ownership to OWNER_NONE. */
  1320 			 * In that case we can safely reassign the ownership to OWNER_NONE. */
  1320 			assert((IsTunnel(tile) ? GetTunnelTransportType(tile) : GetBridgeTransportType(tile)) == TRANSPORT_ROAD);
  1321 			assert((IsTunnel(tile) ? GetTunnelBridgeTransportType(tile) : GetTunnelBridgeTransportType(tile)) == TRANSPORT_ROAD);
  1321 			SetTileOwner(tile, OWNER_NONE);
  1322 			SetTileOwner(tile, OWNER_NONE);
  1322 		}
  1323 		}
  1323 	}
  1324 	}
  1324 }
  1325 }
  1325 
  1326 
  1352 		DiagDirection vdir;
  1353 		DiagDirection vdir;
  1353 
  1354 
  1354 		if (v->type == VEH_TRAIN) {
  1355 		if (v->type == VEH_TRAIN) {
  1355 			fc = (x & 0xF) + (y << 4);
  1356 			fc = (x & 0xF) + (y << 4);
  1356 
  1357 
  1357 			dir = GetTunnelDirection(tile);
  1358 			dir = GetTunnelBridgeDirection(tile);
  1358 			vdir = DirToDiagDir(v->direction);
  1359 			vdir = DirToDiagDir(v->direction);
  1359 
  1360 
  1360 			if (v->u.rail.track != TRACK_BIT_WORMHOLE && dir == vdir) {
  1361 			if (v->u.rail.track != TRACK_BIT_WORMHOLE && dir == vdir) {
  1361 				if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
  1362 				if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
  1362 					if (!PlayVehicleSound(v, VSE_TUNNEL) && RailVehInfo(v->engine_type)->engclass == 0) {
  1363 					if (!PlayVehicleSound(v, VSE_TUNNEL) && RailVehInfo(v->engine_type)->engclass == 0) {
  1380 				v->vehstatus &= ~VS_HIDDEN;
  1381 				v->vehstatus &= ~VS_HIDDEN;
  1381 				return VETSB_ENTERED_WORMHOLE;
  1382 				return VETSB_ENTERED_WORMHOLE;
  1382 			}
  1383 			}
  1383 		} else if (v->type == VEH_ROAD) {
  1384 		} else if (v->type == VEH_ROAD) {
  1384 			fc = (x & 0xF) + (y << 4);
  1385 			fc = (x & 0xF) + (y << 4);
  1385 			dir = GetTunnelDirection(tile);
  1386 			dir = GetTunnelBridgeDirection(tile);
  1386 			vdir = DirToDiagDir(v->direction);
  1387 			vdir = DirToDiagDir(v->direction);
  1387 
  1388 
  1388 			/* Enter tunnel? */
  1389 			/* Enter tunnel? */
  1389 			if (v->u.road.state != RVSB_WORMHOLE && dir == vdir) {
  1390 			if (v->u.road.state != RVSB_WORMHOLE && dir == vdir) {
  1390 				if (fc == _tunnel_fractcoord_4[dir] ||
  1391 				if (fc == _tunnel_fractcoord_4[dir] ||
  1420 
  1421 
  1421 			if (v->type == VEH_ROAD) spd *= 2;
  1422 			if (v->type == VEH_ROAD) spd *= 2;
  1422 			if (v->cur_speed > spd) v->cur_speed = spd;
  1423 			if (v->cur_speed > spd) v->cur_speed = spd;
  1423 		}
  1424 		}
  1424 
  1425 
  1425 		dir = GetBridgeRampDirection(tile);
  1426 		dir = GetTunnelBridgeDirection(tile);
  1426 		if (DirToDiagDir(v->direction) == dir) {
  1427 		if (DirToDiagDir(v->direction) == dir) {
  1427 			switch (dir) {
  1428 			switch (dir) {
  1428 				default: NOT_REACHED();
  1429 				default: NOT_REACHED();
  1429 				case DIAGDIR_NE: if ((x & 0xF) != 0)             return VETSB_CONTINUE; break;
  1430 				case DIAGDIR_NE: if ((x & 0xF) != 0)             return VETSB_CONTINUE; break;
  1430 				case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break;
  1431 				case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break;
  1460 }
  1461 }
  1461 
  1462 
  1462 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
  1463 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
  1463 {
  1464 {
  1464 	if (_patches.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) {
  1465 	if (_patches.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) {
  1465 		DiagDirection direction = GetBridgeRampDirection(tile);
  1466 		DiagDirection direction = GetTunnelBridgeDirection(tile);
  1466 		Axis axis = DiagDirToAxis(direction);
  1467 		Axis axis = DiagDirToAxis(direction);
  1467 		CommandCost res;
  1468 		CommandCost res;
  1468 
  1469 
  1469 		/* Check if new slope is valid for bridges in general (so we can savely call GetBridgeFoundation()) */
  1470 		/* Check if new slope is valid for bridges in general (so we can savely call GetBridgeFoundation()) */
  1470 		if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
  1471 		if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {