bridge_cmd.c
branchcustombridgeheads
changeset 5595 049ed4486972
parent 5594 04068f82afaa
child 5598 166345600ba9
equal deleted inserted replaced
5594:04068f82afaa 5595:049ed4486972
     1 /* $Id$ */
     1 /* $Id$ */
     2 
     2 
     3 /** @file tunnelbridge_cmd.c
     3 /** @file bridge_cmd.c
     4  * This file deals with tunnels and bridges (non-gui stuff)
     4  * This file deals with tunnels and bridges (non-gui stuff)
     5  * @todo seperate this file into two
     5  * @todo seperate this file into two
     6  */
     6  */
     7 
     7 
     8 #include "stdafx.h"
     8 #include "stdafx.h"
   393 
   393 
   394 	return cost;
   394 	return cost;
   395 }
   395 }
   396 
   396 
   397 
   397 
   398 /** Build Tunnel.
   398 static inline bool CheckAllowRemoveBridge(TileIndex tile)
   399  * @param tile start tile of tunnel
       
   400  * @param p1 railtype, 0x200 for road tunnel
       
   401  * @param p2 unused
       
   402  */
       
   403 int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
       
   404 {
       
   405 	TileIndexDiff delta;
       
   406 	TileIndex end_tile;
       
   407 	DiagDirection direction;
       
   408 	Slope start_tileh;
       
   409 	Slope end_tileh;
       
   410 	uint start_z;
       
   411 	uint end_z;
       
   412 	int32 cost;
       
   413 	int32 ret;
       
   414 
       
   415 	_build_tunnel_endtile = 0;
       
   416 
       
   417 	if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR;
       
   418 
       
   419 	start_tileh = GetTileSlope(start_tile, &start_z);
       
   420 
       
   421 	switch (start_tileh) {
       
   422 		case SLOPE_SW: direction = DIAGDIR_SW; break;
       
   423 		case SLOPE_SE: direction = DIAGDIR_SE; break;
       
   424 		case SLOPE_NW: direction = DIAGDIR_NW; break;
       
   425 		case SLOPE_NE: direction = DIAGDIR_NE; break;
       
   426 		default: return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
       
   427 	}
       
   428 
       
   429 	ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   430 	if (CmdFailed(ret)) return ret;
       
   431 
       
   432 	/* XXX - do NOT change 'ret' in the loop, as it is used as the price
       
   433 	 * for the clearing of the entrance of the tunnel. Assigning it to
       
   434 	 * cost before the loop will yield different costs depending on start-
       
   435 	 * position, because of increased-cost-by-length: 'cost += cost >> 3' */
       
   436 	cost = 0;
       
   437 	delta = TileOffsByDiagDir(direction);
       
   438 	end_tile = start_tile;
       
   439 	for (;;) {
       
   440 		end_tile += delta;
       
   441 		end_tileh = GetTileSlope(end_tile, &end_z);
       
   442 
       
   443 		if (start_z == end_z) break;
       
   444 
       
   445 		if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z)) {
       
   446 			return_cmd_error(STR_5003_ANOTHER_TUNNEL_IN_THE_WAY);
       
   447 		}
       
   448 
       
   449 		cost += _price.build_tunnel;
       
   450 		cost += cost >> 3; // add a multiplier for longer tunnels
       
   451 		if (cost >= 400000000) cost = 400000000;
       
   452 	}
       
   453 
       
   454 	/* Add the cost of the entrance */
       
   455 	cost += _price.build_tunnel + ret;
       
   456 
       
   457 	// if the command fails from here on we want the end tile to be highlighted
       
   458 	_build_tunnel_endtile = end_tile;
       
   459 
       
   460 	// slope of end tile must be complementary to the slope of the start tile
       
   461 	if (end_tileh != ComplementSlope(start_tileh)) {
       
   462 		ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND);
       
   463 		if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND);
       
   464 	} else {
       
   465 		ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   466 		if (CmdFailed(ret)) return ret;
       
   467 	}
       
   468 	cost += _price.build_tunnel + ret;
       
   469 
       
   470 	if (flags & DC_EXEC) {
       
   471 		if (GB(p1, 9, 1) == TRANSPORT_RAIL) {
       
   472 			MakeRailTunnel(start_tile, _current_player, direction,                 GB(p1, 0, 4));
       
   473 			MakeRailTunnel(end_tile,   _current_player, ReverseDiagDir(direction), GB(p1, 0, 4));
       
   474 			UpdateSignalsOnSegment(start_tile, direction);
       
   475 			YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction)));
       
   476 		} else {
       
   477 			MakeRoadTunnel(start_tile, _current_player, direction);
       
   478 			MakeRoadTunnel(end_tile,   _current_player, ReverseDiagDir(direction));
       
   479 		}
       
   480 	}
       
   481 
       
   482 	return cost;
       
   483 }
       
   484 
       
   485 TileIndex CheckTunnelBusy(TileIndex tile, uint *length)
       
   486 {
       
   487 	uint z = GetTileZ(tile);
       
   488 	DiagDirection dir = GetTunnelDirection(tile);
       
   489 	TileIndexDiff delta = TileOffsByDiagDir(dir);
       
   490 	uint len = 0;
       
   491 	TileIndex starttile = tile;
       
   492 	Vehicle *v;
       
   493 
       
   494 	do {
       
   495 		tile += delta;
       
   496 		len++;
       
   497 	} while (
       
   498 		!IsTunnelTile(tile) ||
       
   499 		ReverseDiagDir(GetTunnelDirection(tile)) != dir ||
       
   500 		GetTileZ(tile) != z
       
   501 	);
       
   502 
       
   503 	v = FindVehicleBetween(starttile, tile, z);
       
   504 	if (v != NULL) {
       
   505 		_error_message = v->type == VEH_Train ?
       
   506 			STR_5000_TRAIN_IN_TUNNEL : STR_5001_ROAD_VEHICLE_IN_TUNNEL;
       
   507 		return INVALID_TILE;
       
   508 	}
       
   509 
       
   510 	if (length != NULL) *length = len;
       
   511 	return tile;
       
   512 }
       
   513 
       
   514 static inline bool CheckAllowRemoveTunnelBridge(TileIndex tile)
       
   515 {
   399 {
   516 	/* Floods can remove anything as well as the scenario editor */
   400 	/* Floods can remove anything as well as the scenario editor */
   517 	if (_current_player == OWNER_WATER || _game_mode == GM_EDITOR) return true;
   401 	if (_current_player == OWNER_WATER || _game_mode == GM_EDITOR) return true;
   518 	/* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
   402 	/* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
   519 	if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
   403 	if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
   520 	/* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */
   404 	/* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */
   521 	if (IsTileOwner(tile, OWNER_TOWN) && (_patches.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
   405 	if (IsTileOwner(tile, OWNER_TOWN) && (_patches.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
   522 	return false;
   406 	return false;
   523 }
   407 }
   524 
   408 
   525 static int32 DoClearTunnel(TileIndex tile, uint32 flags)
       
   526 {
       
   527 	Town *t = NULL;
       
   528 	TileIndex endtile;
       
   529 	uint length;
       
   530 
       
   531 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   532 
       
   533 	if (!CheckAllowRemoveTunnelBridge(tile)) return CMD_ERROR;
       
   534 
       
   535 	endtile = CheckTunnelBusy(tile, &length);
       
   536 	if (endtile == INVALID_TILE) return CMD_ERROR;
       
   537 
       
   538 	_build_tunnel_endtile = endtile;
       
   539 
       
   540 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
       
   541 		t = ClosestTownFromTile(tile, (uint)-1); // town penalty rating
       
   542 
       
   543 		/* Check if you are allowed to remove the tunnel owned by a town
       
   544 		 * Removal depends on difficulty settings */
       
   545 		if (!CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE)) {
       
   546 			SetDParam(0, t->index);
       
   547 			return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
       
   548 		}
       
   549 	}
       
   550 
       
   551 	if (flags & DC_EXEC) {
       
   552 		// We first need to request the direction before calling DoClearSquare
       
   553 		//  else the direction is always 0.. dah!! ;)
       
   554 		DiagDirection dir = GetTunnelDirection(tile);
       
   555 		Track track;
       
   556 
       
   557 		// Adjust the town's player rating. Do this before removing the tile owner info.
       
   558 		if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR)
       
   559 			ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
       
   560 
       
   561 		DoClearSquare(tile);
       
   562 		DoClearSquare(endtile);
       
   563 		UpdateSignalsOnSegment(tile, ReverseDiagDir(dir));
       
   564 		UpdateSignalsOnSegment(endtile, dir);
       
   565 		track = AxisToTrack(DiagDirToAxis(dir));
       
   566 		YapfNotifyTrackLayoutChange(tile, track);
       
   567 		YapfNotifyTrackLayoutChange(endtile, track);
       
   568 	}
       
   569 	return _price.clear_tunnel * (length + 1);
       
   570 }
       
   571 
       
   572 
       
   573 static bool IsVehicleOnBridge(TileIndex starttile, TileIndex endtile, uint z)
   409 static bool IsVehicleOnBridge(TileIndex starttile, TileIndex endtile, uint z)
   574 {
   410 {
   575 	const Vehicle *v;
   411 	const Vehicle *v;
   576 	FOR_ALL_VEHICLES(v) {
   412 	FOR_ALL_VEHICLES(v) {
   577 		if ((v->tile == starttile || v->tile == endtile) && v->z_pos == z) {
   413 		if ((v->tile == starttile || v->tile == endtile) && v->z_pos == z) {
   589 	TileIndex endtile;
   425 	TileIndex endtile;
   590 	Town *t = NULL;
   426 	Town *t = NULL;
   591 
   427 
   592 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   428 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   593 
   429 
   594 	if (!CheckAllowRemoveTunnelBridge(tile)) return CMD_ERROR;
   430 	if (!CheckAllowRemoveBridge(tile)) return CMD_ERROR;
   595 
   431 
   596 	endtile = GetOtherBridgeEnd(tile);
   432 	endtile = GetOtherBridgeEnd(tile);
   597 
   433 
   598 	if (!EnsureNoVehicle(tile) ||
   434 	if (!EnsureNoVehicle(tile) ||
   599 			!EnsureNoVehicle(endtile) ||
   435 			!EnsureNoVehicle(endtile) ||
   639 	}
   475 	}
   640 
   476 
   641 	return (DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge;
   477 	return (DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge;
   642 }
   478 }
   643 
   479 
   644 static int32 ClearTile_Tunnel(TileIndex tile, byte flags)
       
   645 {
       
   646 	assert(IsTunnelTile(tile));
       
   647 	if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
       
   648 	return DoClearTunnel(tile, flags);
       
   649 }
       
   650 
   480 
   651 static int32 ClearTile_Bridge(TileIndex tile, byte flags)
   481 static int32 ClearTile_Bridge(TileIndex tile, byte flags)
   652 {
   482 {
   653 	assert(IsBridgeTile(tile));
   483 	assert(IsBridgeTile(tile));
   654 	if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   484 	if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   655 	return DoClearBridge(tile, flags);
   485 	return DoClearBridge(tile, flags);
   656 }
   486 }
   657 
   487 
   658 int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
   488 int32 DoConvertBridgeRail(TileIndex tile, RailType totype, bool exec)
   659 {
   489 {
   660 	TileIndex endtile;
   490 	TileIndex endtile;
   661 
   491 
   662 	if (IsTunnelTile(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) {
   492 	if (GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
   663 		uint length;
       
   664 
       
   665 		if (!CheckTileOwnership(tile)) return CMD_ERROR;
       
   666 
       
   667 		if (GetRailType(tile) == totype) return CMD_ERROR;
       
   668 
       
   669 		// 'hidden' elrails can't be downgraded to normal rail when elrails are disabled
       
   670 		if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR;
       
   671 
       
   672 		endtile = CheckTunnelBusy(tile, &length);
       
   673 		if (endtile == INVALID_TILE) return CMD_ERROR;
       
   674 
       
   675 		if (exec) {
       
   676 			Track track;
       
   677 			SetRailType(tile, totype);
       
   678 			SetRailType(endtile, totype);
       
   679 			MarkTileDirtyByTile(tile);
       
   680 			MarkTileDirtyByTile(endtile);
       
   681 
       
   682 			track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile)));
       
   683 			YapfNotifyTrackLayoutChange(tile, track);
       
   684 			YapfNotifyTrackLayoutChange(endtile, track);
       
   685 		}
       
   686 		return (length + 1) * (_price.build_rail >> 1);
       
   687 	} else if (IsBridgeTile(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
       
   688 
       
   689 		if (!CheckTileOwnership(tile)) return CMD_ERROR;
   493 		if (!CheckTileOwnership(tile)) return CMD_ERROR;
   690 
   494 
   691 		endtile = GetOtherBridgeEnd(tile);
   495 		endtile = GetOtherBridgeEnd(tile);
   692 
   496 
   693 		if (!EnsureNoVehicle(tile) ||
   497 		if (!EnsureNoVehicle(tile) ||
   785 	}
   589 	}
   786 	if (axis != AXIS_X) ++i;
   590 	if (axis != AXIS_X) ++i;
   787 	return i + 15;
   591 	return i + 15;
   788 }
   592 }
   789 
   593 
   790 /**
       
   791  * Draws a tunnel tile.
       
   792  * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
       
   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 
   594 
   814 /**
   595 /**
   815  * Draws a bridge tile.
   596  * Draws a bridge tile.
   816  * base_offset is where the sprite selection comes into play
   597  * base_offset is where the sprite selection comes into play
   817  * and it works a bit like a bitmask.<p> For bridge heads:
   598  * and it works a bit like a bitmask.<p> For bridge heads:
   992 	if (v->cur_speed > bridge_speed) v->cur_speed = bridge_speed;
   773 	if (v->cur_speed > bridge_speed) v->cur_speed = bridge_speed;
   993 	return bridge_speed;
   774 	return bridge_speed;
   994 }
   775 }
   995 
   776 
   996 
   777 
   997 /** Gets the absolute z coordinate of a point inside a tunnel tile
       
   998  *  When we're on the track (that means between position 5 and 10)
       
   999  *  on the coordinate perpendicular to the track it returns only the
       
  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;
       
  1011 	Slope tileh = GetTileSlope(tile, &z);
       
  1012 
       
  1013 	x &= 0xF;
       
  1014 	y &= 0xF;
       
  1015 
       
  1016 	pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x);
       
  1017 
       
  1018 	// In the tunnel entrance?
       
  1019 	if (5 <= pos && pos <= 10) return z;
       
  1020 
       
  1021 	return z + GetPartialZ(x, y, tileh);
       
  1022 }
       
  1023 
       
  1024 /** Gets the absolute z coordinate of a point inside a bridge tile
   778 /** Gets the absolute z coordinate of a point inside a bridge tile
  1025  *  When we're on the track (that means between position 5 and 10)
   779  *  When we're on the track (that means between position 5 and 10)
  1026  *  on the coordinate perpendicular to the track it returns the base
   780  *  on the coordinate perpendicular to the track it returns the base
  1027  *  height of the ramp
   781  *  height of the ramp
  1028  *  Outside this range (from 0 to 4 and from 11 to 15) it returns the
   782  *  Outside this range (from 0 to 4 and from 11 to 15) it returns the
  1073 		}
   827 		}
  1074 	}
   828 	}
  1075 	return z + GetPartialZ(x, y, tileh);
   829 	return z + GetPartialZ(x, y, tileh);
  1076 }
   830 }
  1077 
   831 
  1078 static Slope GetSlopeTileh_Tunnel(TileIndex tile, Slope tileh)
       
  1079 {
       
  1080 	return tileh;
       
  1081 }
       
  1082 
       
  1083 static Slope GetSlopeTileh_Bridge(TileIndex tile, Slope tileh)
   832 static Slope GetSlopeTileh_Bridge(TileIndex tile, Slope tileh)
  1084 {
   833 {
  1085 	if (HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
   834 	if (HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
  1086 		return tileh;
   835 		return tileh;
  1087 	} else {
   836 	} else {
  1089 
   838 
  1090 		if (f == 0) return tileh;
   839 		if (f == 0) return tileh;
  1091 		if (f < 15) return SLOPE_FLAT;
   840 		if (f < 15) return SLOPE_FLAT;
  1092 		return _inclined_tileh[f - 15];
   841 		return _inclined_tileh[f - 15];
  1093 	}
   842 	}
  1094 }
       
  1095 
       
  1096 static void GetAcceptedCargo_Tunnel(TileIndex tile, AcceptedCargo ac)
       
  1097 {
       
  1098 	/* not used */
       
  1099 }
   843 }
  1100 
   844 
  1101 static void GetAcceptedCargo_Bridge(TileIndex tile, AcceptedCargo ac)
   845 static void GetAcceptedCargo_Bridge(TileIndex tile, AcceptedCargo ac)
  1102 {
   846 {
  1103 	/* not used */
   847 	/* not used */
  1133 	STR_5028_TUBULAR_ROAD_BRIDGE,
   877 	STR_5028_TUBULAR_ROAD_BRIDGE,
  1134 	STR_5028_TUBULAR_ROAD_BRIDGE,
   878 	STR_5028_TUBULAR_ROAD_BRIDGE,
  1135 	0, 0, 0,
   879 	0, 0, 0,
  1136 };
   880 };
  1137 
   881 
  1138 static void GetTileDesc_Tunnel(TileIndex tile, TileDesc *td)
       
  1139 {
       
  1140 	td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ?  STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
       
  1141 	td->owner = GetTileOwner(tile);
       
  1142 }
       
  1143 
       
  1144 static void GetTileDesc_Bridge(TileIndex tile, TileDesc *td)
   882 static void GetTileDesc_Bridge(TileIndex tile, TileDesc *td)
  1145 {
   883 {
  1146 	td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
   884 	td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
  1147 	td->owner = GetTileOwner(tile);
   885 	td->owner = GetTileOwner(tile);
  1148 }
   886 }
  1149 
   887 
  1150 
   888 
  1151 static void AnimateTile_Tunnel(TileIndex tile)
   889 static void AnimateTile_Bridge(TileIndex tile)
  1152 {
   890 {
  1153 	/* not used */
   891 	/* not used */
  1154 }
   892 }
  1155 
   893 
  1156 static void AnimateTile_Bridge(TileIndex tile)
       
  1157 {
       
  1158 	/* not used */
       
  1159 }
       
  1160 
       
  1161 static void TileLoop_Tunnel(TileIndex tile)
       
  1162 {
       
  1163 	bool snow_or_desert = HasTunnelSnowOrDesert(tile);
       
  1164 	switch (_opt.landscape) {
       
  1165 		case LT_HILLY:
       
  1166 			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
       
  1167 				SetTunnelSnowOrDesert(tile, !snow_or_desert);
       
  1168 				MarkTileDirtyByTile(tile);
       
  1169 			}
       
  1170 			break;
       
  1171 
       
  1172 		case LT_DESERT:
       
  1173 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
       
  1174 				SetTunnelSnowOrDesert(tile, true);
       
  1175 				MarkTileDirtyByTile(tile);
       
  1176 			}
       
  1177 			break;
       
  1178 	}
       
  1179 }
       
  1180 
   894 
  1181 static void TileLoop_Bridge(TileIndex tile)
   895 static void TileLoop_Bridge(TileIndex tile)
  1182 {
   896 {
  1183 	bool snow_or_desert = HasBridgeSnowOrDesert(tile);
   897 	bool snow_or_desert = HasBridgeSnowOrDesert(tile);
  1184 	switch (_opt.landscape) {
   898 	switch (_opt.landscape) {
  1196 			}
   910 			}
  1197 			break;
   911 			break;
  1198 	}
   912 	}
  1199 }
   913 }
  1200 
   914 
  1201 static void ClickTile_Tunnel(TileIndex tile)
   915 static void ClickTile_Bridge(TileIndex tile)
  1202 {
   916 {
  1203 	/* not used */
   917 	/* not used */
  1204 }
   918 }
  1205 
   919 
  1206 static void ClickTile_Bridge(TileIndex tile)
       
  1207 {
       
  1208 	/* not used */
       
  1209 }
       
  1210 
       
  1211 
       
  1212 static uint32 GetTileTrackStatus_Tunnel(TileIndex tile, TransportType mode)
       
  1213 {
       
  1214 	if (GetTunnelTransportType(tile) != mode) return 0;
       
  1215 	return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101;
       
  1216 }
       
  1217 
   920 
  1218 static uint32 GetTileTrackStatus_Bridge(TileIndex tile, TransportType mode)
   921 static uint32 GetTileTrackStatus_Bridge(TileIndex tile, TransportType mode)
  1219 {
   922 {
  1220 	if (GetBridgeTransportType(tile) != mode) return 0;
   923 	if (GetBridgeTransportType(tile) != mode) return 0;
  1221 	return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
   924 	return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
  1222 }
   925 }
  1223 
   926 
  1224 static void ChangeTileOwner_Tunnel(TileIndex tile, PlayerID old_player, PlayerID new_player)
   927 
       
   928 static void ChangeTileOwner_Bridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1225 {
   929 {
  1226 	if (!IsTileOwner(tile, old_player)) return;
   930 	if (!IsTileOwner(tile, old_player)) return;
  1227 
   931 
  1228 	if (new_player != PLAYER_SPECTATOR) {
   932 	if (new_player != PLAYER_SPECTATOR) {
  1229 		SetTileOwner(tile, new_player);
   933 		SetTileOwner(tile, new_player);
  1230 	} else {
   934 	} else {
  1231 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
   935 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
  1232 	}
   936 	}
  1233 }
   937 }
  1234 
   938 
  1235 static void ChangeTileOwner_Bridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
       
  1236 {
       
  1237 	if (!IsTileOwner(tile, old_player)) return;
       
  1238 
       
  1239 	if (new_player != PLAYER_SPECTATOR) {
       
  1240 		SetTileOwner(tile, new_player);
       
  1241 	} else {
       
  1242 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
       
  1243 	}
       
  1244 }
       
  1245 
       
  1246 
       
  1247 static const byte _tunnel_fractcoord_1[4]    = {0x8E, 0x18, 0x81, 0xE8};
       
  1248 static const byte _tunnel_fractcoord_2[4]    = {0x81, 0x98, 0x87, 0x38};
       
  1249 static const byte _tunnel_fractcoord_3[4]    = {0x82, 0x88, 0x86, 0x48};
       
  1250 static const byte _exit_tunnel_track[4]      = {1, 2, 1, 2};
       
  1251 
       
  1252 static const byte _road_exit_tunnel_state[4] = {8, 9, 0, 1};
       
  1253 static const byte _road_exit_tunnel_frame[4] = {2, 7, 9, 4};
       
  1254 
       
  1255 static const byte _tunnel_fractcoord_4[4]    = {0x52, 0x85, 0x98, 0x29};
       
  1256 static const byte _tunnel_fractcoord_5[4]    = {0x92, 0x89, 0x58, 0x25};
       
  1257 static const byte _tunnel_fractcoord_6[4]    = {0x92, 0x89, 0x56, 0x45};
       
  1258 static const byte _tunnel_fractcoord_7[4]    = {0x52, 0x85, 0x96, 0x49};
       
  1259 
       
  1260 static uint32 VehicleEnter_Tunnel(Vehicle *v, TileIndex tile, int x, int y)
       
  1261 {
       
  1262 	int z = GetSlopeZ(x, y) - v->z_pos;
       
  1263 
       
  1264 	byte fc;
       
  1265 	DiagDirection dir;
       
  1266 	DiagDirection vdir;
       
  1267 
       
  1268 	if (myabs(z) > 2) return 8;
       
  1269 
       
  1270 	if (v->type == VEH_Train) {
       
  1271 		fc = (x & 0xF) + (y << 4);
       
  1272 
       
  1273 		dir = GetTunnelDirection(tile);
       
  1274 		vdir = DirToDiagDir(v->direction);
       
  1275 
       
  1276 		if (v->u.rail.track != 0x40 && dir == vdir) {
       
  1277 			if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
       
  1278 				if (!PlayVehicleSound(v, VSE_TUNNEL) && v->spritenum < 4) {
       
  1279 					SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
       
  1280 				}
       
  1281 				return 0;
       
  1282 			}
       
  1283 			if (fc == _tunnel_fractcoord_2[dir]) {
       
  1284 				v->tile = tile;
       
  1285 				v->u.rail.track = 0x40;
       
  1286 				v->vehstatus |= VS_HIDDEN;
       
  1287 				return 4;
       
  1288 			}
       
  1289 		}
       
  1290 
       
  1291 		if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) {
       
  1292 			/* We're at the tunnel exit ?? */
       
  1293 			v->tile = tile;
       
  1294 			v->u.rail.track = _exit_tunnel_track[dir];
       
  1295 			assert(v->u.rail.track);
       
  1296 			v->vehstatus &= ~VS_HIDDEN;
       
  1297 			return 4;
       
  1298 		}
       
  1299 	} else if (v->type == VEH_Road) {
       
  1300 		fc = (x & 0xF) + (y << 4);
       
  1301 		dir = GetTunnelDirection(tile);
       
  1302 		vdir = DirToDiagDir(v->direction);
       
  1303 
       
  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;
       
  1314 			}
       
  1315 		}
       
  1316 
       
  1317 		if (dir == ReverseDiagDir(vdir) && (
       
  1318 					/* We're at the tunnel exit ?? */
       
  1319 					fc == _tunnel_fractcoord_6[dir] ||
       
  1320 					fc == _tunnel_fractcoord_7[dir]
       
  1321 				) &&
       
  1322 				z == 0) {
       
  1323 			v->tile = tile;
       
  1324 			v->u.road.state = _road_exit_tunnel_state[dir];
       
  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 
   939 
  1333 static uint32 VehicleEnter_Bridge(Vehicle *v, TileIndex tile, int x, int y)
   940 static uint32 VehicleEnter_Bridge(Vehicle *v, TileIndex tile, int x, int y)
  1334 {
   941 {
  1335 	int z = GetSlopeZ(x, y) - v->z_pos;
   942 	int z = GetSlopeZ(x, y) - v->z_pos;
  1336 
   943 
  1370 				v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
   977 				v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
  1371 				return 4;
   978 				return 4;
  1372 			}
   979 			}
  1373 		} else {
   980 		} else {
  1374 			if (v->u.road.state == 0xFF) {
   981 			if (v->u.road.state == 0xFF) {
  1375 				v->u.road.state = _road_exit_tunnel_state[dir];
   982 				static const byte road_exit_bridge_state[4] = {8, 9, 0, 1};
       
   983 				v->u.road.state = road_exit_bridge_state[dir];
  1376 				v->u.road.frame = 0;
   984 				v->u.road.frame = 0;
  1377 				return 4;
   985 				return 4;
  1378 			}
   986 			}
  1379 		}
   987 		}
  1380 		return 0;
   988 		return 0;
  1381 	}
   989 	}
  1382 	return 0;
   990 	return 0;
  1383 }
   991 }
  1384 
       
  1385 const TileTypeProcs _tile_type_tunnel_procs = {
       
  1386 	DrawTile_Tunnel,           /* draw_tile_proc */
       
  1387 	GetSlopeZ_Tunnel,          /* get_slope_z_proc */
       
  1388 	ClearTile_Tunnel,          /* clear_tile_proc */
       
  1389 	GetAcceptedCargo_Tunnel,   /* get_accepted_cargo_proc */
       
  1390 	GetTileDesc_Tunnel,        /* get_tile_desc_proc */
       
  1391 	GetTileTrackStatus_Tunnel, /* get_tile_track_status_proc */
       
  1392 	ClickTile_Tunnel,          /* click_tile_proc */
       
  1393 	AnimateTile_Tunnel,        /* animate_tile_proc */
       
  1394 	TileLoop_Tunnel,           /* tile_loop_clear */
       
  1395 	ChangeTileOwner_Tunnel,    /* change_tile_owner_clear */
       
  1396 	NULL,                            /* get_produced_cargo_proc */
       
  1397 	VehicleEnter_Tunnel,       /* vehicle_enter_tile_proc */
       
  1398 	GetSlopeTileh_Tunnel,      /* get_slope_tileh_proc */
       
  1399 };
       
  1400 
   992 
  1401 const TileTypeProcs _tile_type_bridge_procs = {
   993 const TileTypeProcs _tile_type_bridge_procs = {
  1402 	DrawTile_Bridge,           /* draw_tile_proc */
   994 	DrawTile_Bridge,           /* draw_tile_proc */
  1403 	GetSlopeZ_Bridge,          /* get_slope_z_proc */
   995 	GetSlopeZ_Bridge,          /* get_slope_z_proc */
  1404 	ClearTile_Bridge,          /* clear_tile_proc */
   996 	ClearTile_Bridge,          /* clear_tile_proc */