tunnelbridge_cmd.c
branchcustombridgeheads
changeset 5593 3e0dd1f014ca
parent 5592 fd60d4ecc921
equal deleted inserted replaced
5592:fd60d4ecc921 5593:3e0dd1f014ca
   639 	}
   639 	}
   640 
   640 
   641 	return (DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge;
   641 	return (DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge;
   642 }
   642 }
   643 
   643 
   644 static int32 ClearTile_TunnelBridge(TileIndex tile, byte flags)
   644 static int32 ClearTile_Tunnel(TileIndex tile, byte flags)
   645 {
   645 {
   646 	if (IsTunnelTile(tile)) {
   646 	assert(IsTunnelTile(tile));
   647 		if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
   647 	if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
   648 		return DoClearTunnel(tile, flags);
   648 	return DoClearTunnel(tile, flags);
   649 	} else if (IsBridgeTile(tile)) { // XXX Is this necessary?
   649 }
   650 		if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   650 
   651 		return DoClearBridge(tile, flags);
   651 static int32 ClearTile_Bridge(TileIndex tile, byte flags)
   652 	}
   652 {
   653 
   653 	assert(IsBridgeTile(tile));
   654 	return CMD_ERROR;
   654 	if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
       
   655 	return DoClearBridge(tile, flags);
   655 }
   656 }
   656 
   657 
   657 int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
   658 int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
   658 {
   659 {
   659 	TileIndex endtile;
   660 	TileIndex endtile;
   785 	if (axis != AXIS_X) ++i;
   786 	if (axis != AXIS_X) ++i;
   786 	return i + 15;
   787 	return i + 15;
   787 }
   788 }
   788 
   789 
   789 /**
   790 /**
   790  * Draws a tunnel of bridge tile.
   791  * Draws a tunnel tile.
   791  * For tunnels, this is rather simple, as you only needa draw the entrance.
   792  * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
   792  * Bridges are a bit more complex. base_offset is where the sprite selection comes into play
   793  */
       
   794 static void DrawTile_Tunnel(TileInfo *ti)
       
   795 {
       
   796 	uint32 image;
       
   797 
       
   798 	if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) {
       
   799 		image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.tunnel;
       
   800 	} else {
       
   801 		image = SPR_TUNNEL_ENTRY_REAR_ROAD;
       
   802 	}
       
   803 
       
   804 	if (HasTunnelSnowOrDesert(ti->tile)) image += 32;
       
   805 
       
   806 	image += GetTunnelDirection(ti->tile) * 2;
       
   807 	DrawGroundSprite(image);
       
   808 	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
       
   809 
       
   810 	AddSortableSpriteToDraw(image+1, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z);
       
   811 	DrawBridgeMiddle(ti);
       
   812 }
       
   813 
       
   814 /**
       
   815  * Draws a bridge tile.
       
   816  * base_offset is where the sprite selection comes into play
   793  * and it works a bit like a bitmask.<p> For bridge heads:
   817  * and it works a bit like a bitmask.<p> For bridge heads:
   794  * <ul><li>Bit 0: direction</li>
   818  * <ul><li>Bit 0: direction</li>
   795  * <li>Bit 1: northern or southern heads</li>
   819  * <li>Bit 1: northern or southern heads</li>
   796  * <li>Bit 2: Set if the bridge head is sloped</li>
   820  * <li>Bit 2: Set if the bridge head is sloped</li>
   797  * <li>Bit 3 and more: Railtype Specific subset</li>
   821  * <li>Bit 3 and more: Railtype Specific subset</li>
   798  * </ul>
   822  * </ul>
   799  * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
   823  * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
   800  */
   824  */
   801 static void DrawTile_TunnelBridge(TileInfo *ti)
   825 static void DrawTile_Bridge(TileInfo *ti)
   802 {
   826 {
   803 	uint32 image;
   827 	uint32 image;
   804 
   828 
   805 	if (IsTunnelTile(ti->tile)) {
   829 	int base_offset;
   806 		if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) {
   830 	bool ice = HasBridgeSnowOrDesert(ti->tile);
   807 			image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.tunnel;
   831 
   808 		} else {
   832 	if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
   809 			image = SPR_TUNNEL_ENTRY_REAR_ROAD;
   833 		base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
   810 		}
   834 		assert(base_offset != 8); /* This one is used for roads */
   811 
   835 	} else {
   812 		if (HasTunnelSnowOrDesert(ti->tile)) image += 32;
   836 		base_offset = 8;
   813 
   837 	}
   814 		image += GetTunnelDirection(ti->tile) * 2;
   838 
   815 		DrawGroundSprite(image);
   839 	/* as the lower 3 bits are used for other stuff, make sure they are clear */
   816 		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
   840 	assert( (base_offset & 0x07) == 0x00);
   817 
   841 
   818 		AddSortableSpriteToDraw(image+1, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z);
   842 	if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) {
   819 		DrawBridgeMiddle(ti);
   843 		int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
   820 	} else if (IsBridgeTile(ti->tile)) { // XXX is this necessary?
   844 		if (f != 0) DrawFoundation(ti, f);
   821 		int base_offset;
   845 	}
   822 		bool ice = HasBridgeSnowOrDesert(ti->tile);
   846 
   823 
   847 	// HACK Wizardry to convert the bridge ramp direction into a sprite offset
   824 		if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
   848 	base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
   825 			base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
   849 
   826 			assert(base_offset != 8); /* This one is used for roads */
   850 	if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
   827 		} else {
   851 
   828 			base_offset = 8;
   852 	/* Table number 6 always refers to the bridge heads for any bridge type */
   829 		}
   853 	image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
   830 
   854 
   831 		/* as the lower 3 bits are used for other stuff, make sure they are clear */
   855 	if (!ice) {
   832 		assert( (base_offset & 0x07) == 0x00);
   856 		DrawClearLandTile(ti, 3);
   833 
   857 	} else {
   834 		if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) {
   858 		DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]);
   835 			int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
   859 	}
   836 			if (f != 0) DrawFoundation(ti, f);
   860 
   837 		}
   861 	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
   838 
   862 
   839 		// HACK Wizardry to convert the bridge ramp direction into a sprite offset
   863 	// draw ramp
   840 		base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
   864 	if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
   841 
   865 	/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
   842 		if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
   866 	 * it doesn't disappear behind it
   843 
   867 	 */
   844 		/* Table number 6 always refers to the bridge heads for any bridge type */
   868 	AddSortableSpriteToDraw(
   845 		image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
   869 		image, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 1 : 8, ti->z
   846 
   870 	);
   847 		if (!ice) {
   871 
   848 			DrawClearLandTile(ti, 3);
   872 	DrawBridgeMiddle(ti);
   849 		} else {
       
   850 			DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]);
       
   851 		}
       
   852 
       
   853 		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
       
   854 
       
   855 		// draw ramp
       
   856 		if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
       
   857 		/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
       
   858 		 * it doesn't disappear behind it
       
   859 		 */
       
   860 		AddSortableSpriteToDraw(
       
   861 			image, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 1 : 8, ti->z
       
   862 		);
       
   863 
       
   864 		DrawBridgeMiddle(ti);
       
   865 	}
       
   866 }
   873 }
   867 
   874 
   868 
   875 
   869 /** Compute bridge piece. Computes the bridge piece to display depending on the position inside the bridge.
   876 /** Compute bridge piece. Computes the bridge piece to display depending on the position inside the bridge.
   870  * bridges pieces sequence (middle parts)
   877  * bridges pieces sequence (middle parts)
   985 	if (v->cur_speed > bridge_speed) v->cur_speed = bridge_speed;
   992 	if (v->cur_speed > bridge_speed) v->cur_speed = bridge_speed;
   986 	return bridge_speed;
   993 	return bridge_speed;
   987 }
   994 }
   988 
   995 
   989 
   996 
   990 
   997 /** Gets the absolute z coordinate of a point inside a tunnel tile
   991 static uint GetSlopeZ_TunnelBridge(TileIndex tile, uint x, uint y)
   998  *  When we're on the track (that means between position 5 and 10)
   992 {
   999  *  on the coordinate perpendicular to the track it returns only the
   993 	uint z;
  1000  *  base height of the tile (because the track is horizontal).
       
  1001  *  Outside this range (from 0 to 4 and from 11 to 15) it returns the
       
  1002  *  "true" Z coordinate of the tile by taking the slope into account
       
  1003  *  @param tile The index of the tile we are talking about
       
  1004  *  @param x Absolute or relative x coordinate
       
  1005  *  @param y Absolute or relative y coordinate
       
  1006  *  @return Absolute z coordinate
       
  1007  */
       
  1008 static uint GetSlopeZ_Tunnel(TileIndex tile, uint x, uint y)
       
  1009 {
       
  1010 	uint z, pos;
   994 	Slope tileh = GetTileSlope(tile, &z);
  1011 	Slope tileh = GetTileSlope(tile, &z);
   995 
  1012 
   996 	x &= 0xF;
  1013 	x &= 0xF;
   997 	y &= 0xF;
  1014 	y &= 0xF;
   998 
  1015 
   999 	if (IsTunnelTile(tile)) {
  1016 	pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x);
  1000 		uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x);
  1017 
  1001 
  1018 	// In the tunnel entrance?
  1002 		// In the tunnel entrance?
  1019 	if (5 <= pos && pos <= 10) return z;
  1003 		if (5 <= pos && pos <= 10) return z;
  1020 
  1004 	} else {
  1021 	return z + GetPartialZ(x, y, tileh);
  1005 		DiagDirection dir = GetBridgeRampDirection(tile);
  1022 }
  1006 		uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
  1023 
  1007 
  1024 /** Gets the absolute z coordinate of a point inside a bridge tile
  1008 		// On the bridge ramp?
  1025  *  When we're on the track (that means between position 5 and 10)
  1009 		if (5 <= pos && pos <= 10) {
  1026  *  on the coordinate perpendicular to the track it returns the base
  1010 			uint delta;
  1027  *  height of the ramp
  1011 
  1028  *  Outside this range (from 0 to 4 and from 11 to 15) it returns the
  1012 			if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2;
  1029  *  "true" Z coordinate of the tile by taking the slope into account
  1013 			if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT;
  1030  *  @param tile The index of the tile we are talking about
  1014 
  1031  *  @param x Absolute or relative x coordinate
  1015 			if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT;
  1032  *  @param y Absolute or relative y coordinate
  1016 			switch (dir) {
  1033  *  @return Absolute z coordinate
  1017 				default: NOT_REACHED();
  1034  */
  1018 				case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
  1035 static uint GetSlopeZ_Bridge(TileIndex tile, uint x, uint y)
  1019 				case DIAGDIR_SE: delta = y / 2; break;
  1036 {
  1020 				case DIAGDIR_SW: delta = x / 2; break;
  1037 	uint z, pos;
  1021 				case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
  1038 	Slope tileh = GetTileSlope(tile, &z);
       
  1039 	DiagDirection dir = GetBridgeRampDirection(tile);
       
  1040 
       
  1041 	x &= 0xF;
       
  1042 	y &= 0xF;
       
  1043 
       
  1044 	pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
       
  1045 
       
  1046 	// On the bridge ramp?
       
  1047 	if (5 <= pos && pos <= 10) {
       
  1048 		uint delta;
       
  1049 
       
  1050 		if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2;
       
  1051 
       
  1052 		if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT;
       
  1053 
       
  1054 		if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT;
       
  1055 		switch (dir) {
       
  1056 			default: NOT_REACHED();
       
  1057 			case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
       
  1058 			case DIAGDIR_SE: delta = y / 2; break;
       
  1059 			case DIAGDIR_SW: delta = x / 2; break;
       
  1060 			case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
       
  1061 		}
       
  1062 		return z + 1 + delta;
       
  1063 	} else {
       
  1064 		uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir));
       
  1065 
       
  1066 		if (f != 0) {
       
  1067 			if (IsSteepSlope(tileh)) {
       
  1068 				z += TILE_HEIGHT;
       
  1069 			} else if (f < 15) {
       
  1070 				return z + TILE_HEIGHT;
  1022 			}
  1071 			}
  1023 			return z + 1 + delta;
  1072 			tileh = _inclined_tileh[f - 15];
  1024 		} else {
  1073 		}
  1025 			uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir));
  1074 	}
  1026 
       
  1027 			if (f != 0) {
       
  1028 				if (IsSteepSlope(tileh)) {
       
  1029 					z += TILE_HEIGHT;
       
  1030 				} else if (f < 15) {
       
  1031 					return z + TILE_HEIGHT;
       
  1032 				}
       
  1033 				tileh = _inclined_tileh[f - 15];
       
  1034 			}
       
  1035 		}
       
  1036 	}
       
  1037 
       
  1038 	return z + GetPartialZ(x, y, tileh);
  1075 	return z + GetPartialZ(x, y, tileh);
  1039 }
  1076 }
  1040 
  1077 
  1041 static Slope GetSlopeTileh_TunnelBridge(TileIndex tile, Slope tileh)
  1078 static Slope GetSlopeTileh_Tunnel(TileIndex tile, Slope tileh)
  1042 {
  1079 {
  1043 	if (IsTunnelTile(tile)) {
  1080 	return tileh;
       
  1081 }
       
  1082 
       
  1083 static Slope GetSlopeTileh_Bridge(TileIndex tile, Slope tileh)
       
  1084 {
       
  1085 	if (HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
  1044 		return tileh;
  1086 		return tileh;
  1045 	} else {
  1087 	} else {
  1046 		if (HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
  1088 		uint f = GetBridgeFoundation(tileh, DiagDirToAxis(GetBridgeRampDirection(tile)));
  1047 			return tileh;
  1089 
  1048 		} else {
  1090 		if (f == 0) return tileh;
  1049 			uint f = GetBridgeFoundation(tileh, DiagDirToAxis(GetBridgeRampDirection(tile)));
  1091 		if (f < 15) return SLOPE_FLAT;
  1050 
  1092 		return _inclined_tileh[f - 15];
  1051 			if (f == 0) return tileh;
  1093 	}
  1052 			if (f < 15) return SLOPE_FLAT;
  1094 }
  1053 			return _inclined_tileh[f - 15];
  1095 
  1054 		}
  1096 static void GetAcceptedCargo_Tunnel(TileIndex tile, AcceptedCargo ac)
  1055 	}
  1097 {
  1056 }
  1098 	/* not used */
  1057 
  1099 }
  1058 
  1100 
  1059 static void GetAcceptedCargo_TunnelBridge(TileIndex tile, AcceptedCargo ac)
  1101 static void GetAcceptedCargo_Bridge(TileIndex tile, AcceptedCargo ac)
  1060 {
  1102 {
  1061 	/* not used */
  1103 	/* not used */
  1062 }
  1104 }
  1063 
  1105 
  1064 static const StringID _bridge_tile_str[(MAX_BRIDGES + 3) + (MAX_BRIDGES + 3)] = {
  1106 static const StringID _bridge_tile_str[(MAX_BRIDGES + 3) + (MAX_BRIDGES + 3)] = {
  1091 	STR_5028_TUBULAR_ROAD_BRIDGE,
  1133 	STR_5028_TUBULAR_ROAD_BRIDGE,
  1092 	STR_5028_TUBULAR_ROAD_BRIDGE,
  1134 	STR_5028_TUBULAR_ROAD_BRIDGE,
  1093 	0, 0, 0,
  1135 	0, 0, 0,
  1094 };
  1136 };
  1095 
  1137 
  1096 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
  1138 static void GetTileDesc_Tunnel(TileIndex tile, TileDesc *td)
  1097 {
  1139 {
  1098 	if (IsTunnelTile(tile)) {
  1140 	td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ?  STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
  1099 		td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ?
       
  1100 			STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
       
  1101 	} else {
       
  1102 		td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
       
  1103 	}
       
  1104 	td->owner = GetTileOwner(tile);
  1141 	td->owner = GetTileOwner(tile);
  1105 }
  1142 }
  1106 
  1143 
  1107 
  1144 static void GetTileDesc_Bridge(TileIndex tile, TileDesc *td)
  1108 static void AnimateTile_TunnelBridge(TileIndex tile)
  1145 {
       
  1146 	td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
       
  1147 	td->owner = GetTileOwner(tile);
       
  1148 }
       
  1149 
       
  1150 
       
  1151 static void AnimateTile_Tunnel(TileIndex tile)
  1109 {
  1152 {
  1110 	/* not used */
  1153 	/* not used */
  1111 }
  1154 }
  1112 
  1155 
  1113 static void TileLoop_TunnelBridge(TileIndex tile)
  1156 static void AnimateTile_Bridge(TileIndex tile)
  1114 {
  1157 {
  1115 	bool snow_or_desert = IsTunnelTile(tile) ? HasTunnelSnowOrDesert(tile) : HasBridgeSnowOrDesert(tile);
  1158 	/* not used */
       
  1159 }
       
  1160 
       
  1161 static void TileLoop_Tunnel(TileIndex tile)
       
  1162 {
       
  1163 	bool snow_or_desert = HasTunnelSnowOrDesert(tile);
  1116 	switch (_opt.landscape) {
  1164 	switch (_opt.landscape) {
  1117 		case LT_HILLY:
  1165 		case LT_HILLY:
  1118 			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
  1166 			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
  1119 				if (IsTunnelTile(tile)) {
  1167 				SetTunnelSnowOrDesert(tile, !snow_or_desert);
  1120 					SetTunnelSnowOrDesert(tile, !snow_or_desert);
       
  1121 				} else {
       
  1122 					SetBridgeSnowOrDesert(tile, !snow_or_desert);
       
  1123 				}
       
  1124 				MarkTileDirtyByTile(tile);
  1168 				MarkTileDirtyByTile(tile);
  1125 			}
  1169 			}
  1126 			break;
  1170 			break;
  1127 
  1171 
  1128 		case LT_DESERT:
  1172 		case LT_DESERT:
  1129 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
  1173 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
  1130 				if (IsTunnelTile(tile)) {
  1174 				SetTunnelSnowOrDesert(tile, true);
  1131 					SetTunnelSnowOrDesert(tile, true);
       
  1132 				} else {
       
  1133 					SetBridgeSnowOrDesert(tile, true);
       
  1134 				}
       
  1135 				MarkTileDirtyByTile(tile);
  1175 				MarkTileDirtyByTile(tile);
  1136 			}
  1176 			}
  1137 			break;
  1177 			break;
  1138 	}
  1178 	}
  1139 }
  1179 }
  1140 
  1180 
  1141 static void ClickTile_TunnelBridge(TileIndex tile)
  1181 static void TileLoop_Bridge(TileIndex tile)
       
  1182 {
       
  1183 	bool snow_or_desert = HasBridgeSnowOrDesert(tile);
       
  1184 	switch (_opt.landscape) {
       
  1185 		case LT_HILLY:
       
  1186 			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
       
  1187 				SetBridgeSnowOrDesert(tile, !snow_or_desert);
       
  1188 				MarkTileDirtyByTile(tile);
       
  1189 			}
       
  1190 			break;
       
  1191 
       
  1192 		case LT_DESERT:
       
  1193 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
       
  1194 				SetBridgeSnowOrDesert(tile, true);
       
  1195 				MarkTileDirtyByTile(tile);
       
  1196 			}
       
  1197 			break;
       
  1198 	}
       
  1199 }
       
  1200 
       
  1201 static void ClickTile_Tunnel(TileIndex tile)
  1142 {
  1202 {
  1143 	/* not used */
  1203 	/* not used */
  1144 }
  1204 }
  1145 
  1205 
  1146 
  1206 static void ClickTile_Bridge(TileIndex tile)
  1147 static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode)
  1207 {
  1148 {
  1208 	/* not used */
  1149 	if (IsTunnelTile(tile)) {
  1209 }
  1150 		if (GetTunnelTransportType(tile) != mode) return 0;
  1210 
  1151 		return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101;
  1211 
  1152 	} else {
  1212 static uint32 GetTileTrackStatus_Tunnel(TileIndex tile, TransportType mode)
  1153 		if (GetBridgeTransportType(tile) != mode) return 0;
  1213 {
  1154 		return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
  1214 	if (GetTunnelTransportType(tile) != mode) return 0;
  1155 	}
  1215 	return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101;
  1156 }
  1216 }
  1157 
  1217 
  1158 static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1218 static uint32 GetTileTrackStatus_Bridge(TileIndex tile, TransportType mode)
       
  1219 {
       
  1220 	if (GetBridgeTransportType(tile) != mode) return 0;
       
  1221 	return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
       
  1222 }
       
  1223 
       
  1224 static void ChangeTileOwner_Tunnel(TileIndex tile, PlayerID old_player, PlayerID new_player)
       
  1225 {
       
  1226 	if (!IsTileOwner(tile, old_player)) return;
       
  1227 
       
  1228 	if (new_player != PLAYER_SPECTATOR) {
       
  1229 		SetTileOwner(tile, new_player);
       
  1230 	} else {
       
  1231 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
       
  1232 	}
       
  1233 }
       
  1234 
       
  1235 static void ChangeTileOwner_Bridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1159 {
  1236 {
  1160 	if (!IsTileOwner(tile, old_player)) return;
  1237 	if (!IsTileOwner(tile, old_player)) return;
  1161 
  1238 
  1162 	if (new_player != PLAYER_SPECTATOR) {
  1239 	if (new_player != PLAYER_SPECTATOR) {
  1163 		SetTileOwner(tile, new_player);
  1240 		SetTileOwner(tile, new_player);
  1178 static const byte _tunnel_fractcoord_4[4]    = {0x52, 0x85, 0x98, 0x29};
  1255 static const byte _tunnel_fractcoord_4[4]    = {0x52, 0x85, 0x98, 0x29};
  1179 static const byte _tunnel_fractcoord_5[4]    = {0x92, 0x89, 0x58, 0x25};
  1256 static const byte _tunnel_fractcoord_5[4]    = {0x92, 0x89, 0x58, 0x25};
  1180 static const byte _tunnel_fractcoord_6[4]    = {0x92, 0x89, 0x56, 0x45};
  1257 static const byte _tunnel_fractcoord_6[4]    = {0x92, 0x89, 0x56, 0x45};
  1181 static const byte _tunnel_fractcoord_7[4]    = {0x52, 0x85, 0x96, 0x49};
  1258 static const byte _tunnel_fractcoord_7[4]    = {0x52, 0x85, 0x96, 0x49};
  1182 
  1259 
  1183 static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
  1260 static uint32 VehicleEnter_Tunnel(Vehicle *v, TileIndex tile, int x, int y)
  1184 {
  1261 {
  1185 	int z = GetSlopeZ(x, y) - v->z_pos;
  1262 	int z = GetSlopeZ(x, y) - v->z_pos;
  1186 
  1263 
       
  1264 	byte fc;
       
  1265 	DiagDirection dir;
       
  1266 	DiagDirection vdir;
       
  1267 
  1187 	if (myabs(z) > 2) return 8;
  1268 	if (myabs(z) > 2) return 8;
  1188 
  1269 
  1189 	if (IsTunnelTile(tile)) {
  1270 	if (v->type == VEH_Train) {
  1190 		byte fc;
  1271 		fc = (x & 0xF) + (y << 4);
  1191 		DiagDirection dir;
  1272 
  1192 		DiagDirection vdir;
  1273 		dir = GetTunnelDirection(tile);
  1193 
  1274 		vdir = DirToDiagDir(v->direction);
  1194 		if (v->type == VEH_Train) {
  1275 
  1195 			fc = (x & 0xF) + (y << 4);
  1276 		if (v->u.rail.track != 0x40 && dir == vdir) {
  1196 
  1277 			if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
  1197 			dir = GetTunnelDirection(tile);
  1278 				if (!PlayVehicleSound(v, VSE_TUNNEL) && v->spritenum < 4) {
  1198 			vdir = DirToDiagDir(v->direction);
  1279 					SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
  1199 
       
  1200 			if (v->u.rail.track != 0x40 && dir == vdir) {
       
  1201 				if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
       
  1202 					if (!PlayVehicleSound(v, VSE_TUNNEL) && v->spritenum < 4) {
       
  1203 						SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
       
  1204 					}
       
  1205 					return 0;
       
  1206 				}
  1280 				}
  1207 				if (fc == _tunnel_fractcoord_2[dir]) {
  1281 				return 0;
  1208 					v->tile = tile;
       
  1209 					v->u.rail.track = 0x40;
       
  1210 					v->vehstatus |= VS_HIDDEN;
       
  1211 					return 4;
       
  1212 				}
       
  1213 			}
  1282 			}
  1214 
  1283 			if (fc == _tunnel_fractcoord_2[dir]) {
  1215 			if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) {
       
  1216 				/* We're at the tunnel exit ?? */
       
  1217 				v->tile = tile;
  1284 				v->tile = tile;
  1218 				v->u.rail.track = _exit_tunnel_track[dir];
  1285 				v->u.rail.track = 0x40;
  1219 				assert(v->u.rail.track);
  1286 				v->vehstatus |= VS_HIDDEN;
  1220 				v->vehstatus &= ~VS_HIDDEN;
       
  1221 				return 4;
  1287 				return 4;
  1222 			}
  1288 			}
  1223 		} else if (v->type == VEH_Road) {
  1289 		}
  1224 			fc = (x & 0xF) + (y << 4);
  1290 
  1225 			dir = GetTunnelDirection(tile);
  1291 		if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) {
  1226 			vdir = DirToDiagDir(v->direction);
  1292 			/* We're at the tunnel exit ?? */
  1227 
  1293 			v->tile = tile;
  1228 			// Enter tunnel?
  1294 			v->u.rail.track = _exit_tunnel_track[dir];
  1229 			if (v->u.road.state != 0xFF && dir == vdir) {
  1295 			assert(v->u.rail.track);
  1230 				if (fc == _tunnel_fractcoord_4[dir] ||
  1296 			v->vehstatus &= ~VS_HIDDEN;
  1231 						fc == _tunnel_fractcoord_5[dir]) {
  1297 			return 4;
  1232 					v->tile = tile;
  1298 		}
  1233 					v->u.road.state = 0xFF;
  1299 	} else if (v->type == VEH_Road) {
  1234 					v->vehstatus |= VS_HIDDEN;
  1300 		fc = (x & 0xF) + (y << 4);
  1235 					return 4;
  1301 		dir = GetTunnelDirection(tile);
  1236 				} else {
  1302 		vdir = DirToDiagDir(v->direction);
  1237 					return 0;
  1303 
  1238 				}
  1304 		// Enter tunnel?
       
  1305 		if (v->u.road.state != 0xFF && dir == vdir) {
       
  1306 			if (fc == _tunnel_fractcoord_4[dir] ||
       
  1307 					fc == _tunnel_fractcoord_5[dir]) {
       
  1308 				v->tile = tile;
       
  1309 				v->u.road.state = 0xFF;
       
  1310 				v->vehstatus |= VS_HIDDEN;
       
  1311 				return 4;
       
  1312 			} else {
       
  1313 				return 0;
  1239 			}
  1314 			}
  1240 
  1315 		}
  1241 			if (dir == ReverseDiagDir(vdir) && (
  1316 
  1242 						/* We're at the tunnel exit ?? */
  1317 		if (dir == ReverseDiagDir(vdir) && (
  1243 						fc == _tunnel_fractcoord_6[dir] ||
  1318 					/* We're at the tunnel exit ?? */
  1244 						fc == _tunnel_fractcoord_7[dir]
  1319 					fc == _tunnel_fractcoord_6[dir] ||
  1245 					) &&
  1320 					fc == _tunnel_fractcoord_7[dir]
  1246 					z == 0) {
  1321 				) &&
  1247 				v->tile = tile;
  1322 				z == 0) {
  1248 				v->u.road.state = _road_exit_tunnel_state[dir];
  1323 			v->tile = tile;
  1249 				v->u.road.frame = _road_exit_tunnel_frame[dir];
  1324 			v->u.road.state = _road_exit_tunnel_state[dir];
  1250 				v->vehstatus &= ~VS_HIDDEN;
  1325 			v->u.road.frame = _road_exit_tunnel_frame[dir];
       
  1326 			v->vehstatus &= ~VS_HIDDEN;
       
  1327 			return 4;
       
  1328 		}
       
  1329 	}
       
  1330 	return 0;
       
  1331 }
       
  1332 
       
  1333 static uint32 VehicleEnter_Bridge(Vehicle *v, TileIndex tile, int x, int y)
       
  1334 {
       
  1335 	int z = GetSlopeZ(x, y) - v->z_pos;
       
  1336 
       
  1337 	DiagDirection dir;
       
  1338 
       
  1339 	if (myabs(z) > 2) return 8;
       
  1340 
       
  1341 	if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) {
       
  1342 		/* modify speed of vehicle */
       
  1343 		uint16 spd = _bridge[GetBridgeType(tile)].speed;
       
  1344 
       
  1345 		if (v->type == VEH_Road) spd *= 2;
       
  1346 		if (v->cur_speed > spd) v->cur_speed = spd;
       
  1347 	}
       
  1348 
       
  1349 	dir = GetBridgeRampDirection(tile);
       
  1350 	if (DirToDiagDir(v->direction) == dir) {
       
  1351 		switch (dir) {
       
  1352 			default: NOT_REACHED();
       
  1353 			case DIAGDIR_NE: if ((x & 0xF) != 0)             return 0; break;
       
  1354 			case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break;
       
  1355 			case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break;
       
  1356 			case DIAGDIR_NW: if ((y & 0xF) != 0)             return 0; break;
       
  1357 		}
       
  1358 		if (v->type == VEH_Train) {
       
  1359 			v->u.rail.track = 0x40;
       
  1360 			CLRBIT(v->u.rail.flags, VRF_GOINGUP);
       
  1361 			CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
       
  1362 		} else {
       
  1363 			v->u.road.state = 0xFF;
       
  1364 		}
       
  1365 		return 4;
       
  1366 	} else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
       
  1367 		v->tile = tile;
       
  1368 		if (v->type == VEH_Train) {
       
  1369 			if (v->u.rail.track == 0x40) {
       
  1370 				v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
  1251 				return 4;
  1371 				return 4;
  1252 			}
  1372 			}
  1253 		}
  1373 		} else {
  1254 	} else if (IsBridgeTile(tile)) { // XXX is this necessary?
  1374 			if (v->u.road.state == 0xFF) {
  1255 		DiagDirection dir;
  1375 				v->u.road.state = _road_exit_tunnel_state[dir];
  1256 
  1376 				v->u.road.frame = 0;
  1257 		if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) {
  1377 				return 4;
  1258 			/* modify speed of vehicle */
       
  1259 			uint16 spd = _bridge[GetBridgeType(tile)].speed;
       
  1260 
       
  1261 			if (v->type == VEH_Road) spd *= 2;
       
  1262 			if (v->cur_speed > spd) v->cur_speed = spd;
       
  1263 		}
       
  1264 
       
  1265 		dir = GetBridgeRampDirection(tile);
       
  1266 		if (DirToDiagDir(v->direction) == dir) {
       
  1267 			switch (dir) {
       
  1268 				default: NOT_REACHED();
       
  1269 				case DIAGDIR_NE: if ((x & 0xF) != 0)             return 0; break;
       
  1270 				case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break;
       
  1271 				case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break;
       
  1272 				case DIAGDIR_NW: if ((y & 0xF) != 0)             return 0; break;
       
  1273 			}
  1378 			}
  1274 			if (v->type == VEH_Train) {
  1379 		}
  1275 				v->u.rail.track = 0x40;
  1380 		return 0;
  1276 				CLRBIT(v->u.rail.flags, VRF_GOINGUP);
       
  1277 				CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
       
  1278 			} else {
       
  1279 				v->u.road.state = 0xFF;
       
  1280 			}
       
  1281 			return 4;
       
  1282 		} else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
       
  1283 			v->tile = tile;
       
  1284 			if (v->type == VEH_Train) {
       
  1285 				if (v->u.rail.track == 0x40) {
       
  1286 					v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
       
  1287 					return 4;
       
  1288 				}
       
  1289 			} else {
       
  1290 				if (v->u.road.state == 0xFF) {
       
  1291 					v->u.road.state = _road_exit_tunnel_state[dir];
       
  1292 					v->u.road.frame = 0;
       
  1293 					return 4;
       
  1294 				}
       
  1295 			}
       
  1296 			return 0;
       
  1297 		}
       
  1298 	}
  1381 	}
  1299 	return 0;
  1382 	return 0;
  1300 }
  1383 }
  1301 
  1384 
  1302 const TileTypeProcs _tile_type_tunnelbridge_procs = {
  1385 const TileTypeProcs _tile_type_tunnel_procs = {
  1303 	DrawTile_TunnelBridge,           /* draw_tile_proc */
  1386 	DrawTile_Tunnel,           /* draw_tile_proc */
  1304 	GetSlopeZ_TunnelBridge,          /* get_slope_z_proc */
  1387 	GetSlopeZ_Tunnel,          /* get_slope_z_proc */
  1305 	ClearTile_TunnelBridge,          /* clear_tile_proc */
  1388 	ClearTile_Tunnel,          /* clear_tile_proc */
  1306 	GetAcceptedCargo_TunnelBridge,   /* get_accepted_cargo_proc */
  1389 	GetAcceptedCargo_Tunnel,   /* get_accepted_cargo_proc */
  1307 	GetTileDesc_TunnelBridge,        /* get_tile_desc_proc */
  1390 	GetTileDesc_Tunnel,        /* get_tile_desc_proc */
  1308 	GetTileTrackStatus_TunnelBridge, /* get_tile_track_status_proc */
  1391 	GetTileTrackStatus_Tunnel, /* get_tile_track_status_proc */
  1309 	ClickTile_TunnelBridge,          /* click_tile_proc */
  1392 	ClickTile_Tunnel,          /* click_tile_proc */
  1310 	AnimateTile_TunnelBridge,        /* animate_tile_proc */
  1393 	AnimateTile_Tunnel,        /* animate_tile_proc */
  1311 	TileLoop_TunnelBridge,           /* tile_loop_clear */
  1394 	TileLoop_Tunnel,           /* tile_loop_clear */
  1312 	ChangeTileOwner_TunnelBridge,    /* change_tile_owner_clear */
  1395 	ChangeTileOwner_Tunnel,    /* change_tile_owner_clear */
  1313 	NULL,                            /* get_produced_cargo_proc */
  1396 	NULL,                            /* get_produced_cargo_proc */
  1314 	VehicleEnter_TunnelBridge,       /* vehicle_enter_tile_proc */
  1397 	VehicleEnter_Tunnel,       /* vehicle_enter_tile_proc */
  1315 	GetSlopeTileh_TunnelBridge,      /* get_slope_tileh_proc */
  1398 	GetSlopeTileh_Tunnel,      /* get_slope_tileh_proc */
  1316 };
  1399 };
       
  1400 
       
  1401 const TileTypeProcs _tile_type_bridge_procs = {
       
  1402 	DrawTile_Bridge,           /* draw_tile_proc */
       
  1403 	GetSlopeZ_Bridge,          /* get_slope_z_proc */
       
  1404 	ClearTile_Bridge,          /* clear_tile_proc */
       
  1405 	GetAcceptedCargo_Bridge,   /* get_accepted_cargo_proc */
       
  1406 	GetTileDesc_Bridge,        /* get_tile_desc_proc */
       
  1407 	GetTileTrackStatus_Bridge, /* get_tile_track_status_proc */
       
  1408 	ClickTile_Bridge,          /* click_tile_proc */
       
  1409 	AnimateTile_Bridge,        /* animate_tile_proc */
       
  1410 	TileLoop_Bridge,           /* tile_loop_clear */
       
  1411 	ChangeTileOwner_Bridge,    /* change_tile_owner_clear */
       
  1412 	NULL,                      /* get_produced_cargo_proc */
       
  1413 	VehicleEnter_Bridge,       /* vehicle_enter_tile_proc */
       
  1414 	GetSlopeTileh_Bridge,      /* get_slope_tileh_proc */
       
  1415 };