src/bridge_cmd.c
branchcustombridgeheads
changeset 5643 3778051e8095
parent 5633 c61d481dbd0b
child 5648 1608018c5ff2
equal deleted inserted replaced
5642:bfa6074e2833 5643:3778051e8095
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file bridge_cmd.c
       
     4  * This file deals with tunnels and bridges (non-gui stuff)
       
     5  * @todo seperate this file into two
       
     6  */
       
     7 
       
     8 #include "stdafx.h"
       
     9 #include "openttd.h"
       
    10 #include "bridge_map.h"
       
    11 #include "rail_map.h"
       
    12 #include "road_map.h"
       
    13 #include "table/sprites.h"
       
    14 #include "table/strings.h"
       
    15 #include "functions.h"
       
    16 #include "map.h"
       
    17 #include "tile.h"
       
    18 #include "tunnel_map.h"
       
    19 #include "unmovable_map.h"
       
    20 #include "vehicle.h"
       
    21 #include "viewport.h"
       
    22 #include "command.h"
       
    23 #include "player.h"
       
    24 #include "town.h"
       
    25 #include "sound.h"
       
    26 #include "variables.h"
       
    27 #include "bridge.h"
       
    28 #include "train.h"
       
    29 #include "water_map.h"
       
    30 #include "yapf/yapf.h"
       
    31 #include "date.h"
       
    32 #include "newgrf_sound.h"
       
    33 
       
    34 #include "table/bridge_land.h"
       
    35 
       
    36 const Bridge orig_bridge[] = {
       
    37 /*
       
    38 	     year of availablity
       
    39 	     |  minimum length
       
    40 	     |  |   maximum length
       
    41 	     |  |   |    price
       
    42 	     |  |   |    |    maximum speed
       
    43 	     |  |   |    |    |  sprite to use in GUI                string with description
       
    44 	     |  |   |    |    |  |                                   |                            */
       
    45 	{    0, 0, 16,  80,  32, 0xA24                             , STR_5012_WOODEN             , NULL, 0 },
       
    46 	{    0, 0,  2, 112,  48, 0xA26 | PALETTE_TO_STRUCT_RED     , STR_5013_CONCRETE           , NULL, 0 },
       
    47 	{ 1930, 0,  5, 144,  64, 0xA25                             , STR_500F_GIRDER_STEEL       , NULL, 0 },
       
    48 	{    0, 2, 10, 168,  80, 0xA22 | PALETTE_TO_STRUCT_CONCRETE, STR_5011_SUSPENSION_CONCRETE, NULL, 0 },
       
    49 	{ 1930, 3, 16, 185,  96, 0xA22                             , STR_500E_SUSPENSION_STEEL   , NULL, 0 },
       
    50 	{ 1930, 3, 16, 192, 112, 0xA22 | PALETTE_TO_STRUCT_YELLOW  , STR_500E_SUSPENSION_STEEL   , NULL, 0 },
       
    51 	{ 1930, 3,  7, 224, 160, 0xA23                             , STR_5010_CANTILEVER_STEEL   , NULL, 0 },
       
    52 	{ 1930, 3,  8, 232, 208, 0xA23 | PALETTE_TO_STRUCT_BROWN   , STR_5010_CANTILEVER_STEEL   , NULL, 0 },
       
    53 	{ 1930, 3,  9, 248, 240, 0xA23 | PALETTE_TO_STRUCT_RED     , STR_5010_CANTILEVER_STEEL   , NULL, 0 },
       
    54 	{ 1930, 0,  2, 240, 256, 0xA27                             , STR_500F_GIRDER_STEEL       , NULL, 0 },
       
    55 	{ 1995, 2, 16, 255, 320, 0xA28                             , STR_5014_TUBULAR_STEEL      , NULL, 0 },
       
    56 	{ 2005, 2, 32, 380, 512, 0xA28 | PALETTE_TO_STRUCT_YELLOW  , STR_5014_TUBULAR_STEEL      , NULL, 0 },
       
    57 	{ 2010, 2, 32, 510, 608, 0xA28 | PALETTE_TO_STRUCT_GREY    , STR_BRIDGE_TUBULAR_SILICON  , NULL, 0 }
       
    58 };
       
    59 
       
    60 Bridge _bridge[MAX_BRIDGES];
       
    61 
       
    62 
       
    63 // calculate the price factor for building a long bridge.
       
    64 // basically the cost delta is 1,1, 1, 2,2, 3,3,3, 4,4,4,4, 5,5,5,5,5, 6,6,6,6,6,6,  7,7,7,7,7,7,7,  8,8,8,8,8,8,8,8,
       
    65 int CalcBridgeLenCostFactor(int x)
       
    66 {
       
    67 	int n;
       
    68 	int r;
       
    69 
       
    70 	if (x < 2) return x;
       
    71 	x -= 2;
       
    72 	for (n = 0, r = 2;; n++) {
       
    73 		if (x <= n) return r + x * n;
       
    74 		r += n * n;
       
    75 		x -= n;
       
    76 	}
       
    77 }
       
    78 
       
    79 static inline const PalSpriteID *GetBridgeSpriteTable(int index, byte table)
       
    80 {
       
    81 	const Bridge *bridge = &_bridge[index];
       
    82 	assert(table < 7);
       
    83 	if (bridge->sprite_table == NULL || bridge->sprite_table[table] == NULL) {
       
    84 		return _bridge_sprite_table[index][table];
       
    85 	} else {
       
    86 		return bridge->sprite_table[table];
       
    87 	}
       
    88 }
       
    89 
       
    90 static inline byte GetBridgeFlags(int index) { return _bridge[index].flags;}
       
    91 
       
    92 
       
    93 /** Check the slope at the bridge ramps in three easy steps:
       
    94  * - valid slopes without foundation
       
    95  * - valid slopes with foundation
       
    96  * - rest is invalid
       
    97  */
       
    98 #define M(x) (1 << (x))
       
    99 static int32 CheckBridgeSlopeNorth(Axis axis, Slope tileh)
       
   100 {
       
   101 	uint32 valid;
       
   102 
       
   103 	valid = M(SLOPE_FLAT) | (axis == AXIS_X ? M(SLOPE_NE) : M(SLOPE_NW));
       
   104 	if (HASBIT(valid, tileh)) return 0;
       
   105 
       
   106 	valid =
       
   107 		BRIDGE_FULL_LEVELED_FOUNDATION | M(SLOPE_N) | M(SLOPE_STEEP_N) |
       
   108 		(axis == AXIS_X ? M(SLOPE_E) | M(SLOPE_STEEP_E) : M(SLOPE_W) | M(SLOPE_STEEP_W));
       
   109 	if (HASBIT(valid, tileh)) return _price.terraform;
       
   110 
       
   111 	return CMD_ERROR;
       
   112 }
       
   113 
       
   114 static int32 CheckBridgeSlopeSouth(Axis axis, Slope tileh)
       
   115 {
       
   116 	uint32 valid;
       
   117 
       
   118 	valid = M(SLOPE_FLAT) | (axis == AXIS_X ? M(SLOPE_SW) : M(SLOPE_SE));
       
   119 	if (HASBIT(valid, tileh)) return 0;
       
   120 
       
   121 	valid =
       
   122 		BRIDGE_FULL_LEVELED_FOUNDATION | M(SLOPE_S) | M(SLOPE_STEEP_S) |
       
   123 		(axis == AXIS_X ? M(SLOPE_W) | M(SLOPE_STEEP_W) : M(SLOPE_E) | M(SLOPE_STEEP_E));
       
   124 	if (HASBIT(valid, tileh)) return _price.terraform;
       
   125 
       
   126 	return CMD_ERROR;
       
   127 }
       
   128 #undef M
       
   129 
       
   130 
       
   131 uint32 GetBridgeLength(TileIndex begin, TileIndex end)
       
   132 {
       
   133 	int x1 = TileX(begin);
       
   134 	int y1 = TileY(begin);
       
   135 	int x2 = TileX(end);
       
   136 	int y2 = TileY(end);
       
   137 
       
   138 	return abs(x2 + y2 - x1 - y1) - 1;
       
   139 }
       
   140 
       
   141 bool CheckBridge_Stuff(byte bridge_type, uint bridge_len)
       
   142 {
       
   143 	const Bridge *b = &_bridge[bridge_type];
       
   144 	uint max; // max possible length of a bridge (with patch 100)
       
   145 
       
   146 	if (bridge_type >= MAX_BRIDGES) return false;
       
   147 	if (b->avail_year > _cur_year) return false;
       
   148 
       
   149 	max = b->max_length;
       
   150 	if (max >= 16 && _patches.longbridges) max = 100;
       
   151 
       
   152 	return b->min_length <= bridge_len && bridge_len <= max;
       
   153 }
       
   154 
       
   155 /** Build a Bridge
       
   156  * @param end_tile end tile
       
   157  * @param p1 packed start tile coords (~ dx)
       
   158  * @param p2 various bitstuffed elements
       
   159  * - p2 = (bit 0- 7) - bridge type (hi bh)
       
   160  * - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge.
       
   161  */
       
   162 int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
       
   163 {
       
   164 	int bridge_type;
       
   165 	TransportType transport;
       
   166 	RailType railtype;
       
   167 	uint x;
       
   168 	uint y;
       
   169 	uint sx;
       
   170 	uint sy;
       
   171 	TileIndex tile_start;
       
   172 	TileIndex tile_end;
       
   173 	Slope tileh_start;
       
   174 	Slope tileh_end;
       
   175 	uint z_start;
       
   176 	uint z_end;
       
   177 	TileIndex tile;
       
   178 	TileIndexDiff delta;
       
   179 	uint bridge_len;
       
   180 	Axis direction;
       
   181 	int32 cost, terraformcost, ret;
       
   182 	bool allow_on_slopes;
       
   183 
       
   184 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   185 
       
   186 	/* unpack parameters */
       
   187 	bridge_type = GB(p2, 0, 8);
       
   188 
       
   189 	if (p1 >= MapSize()) return CMD_ERROR;
       
   190 
       
   191 	// type of bridge
       
   192 	if (HASBIT(p2, 15)) {
       
   193 		railtype = 0;
       
   194 		transport = TRANSPORT_ROAD;
       
   195 	} else {
       
   196 		if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR;
       
   197 		railtype = GB(p2, 8, 8);
       
   198 		transport = TRANSPORT_RAIL;
       
   199 	}
       
   200 
       
   201 	x = TileX(end_tile);
       
   202 	y = TileY(end_tile);
       
   203 	sx = TileX(p1);
       
   204 	sy = TileY(p1);
       
   205 
       
   206 	/* check if valid, and make sure that (x,y) are smaller than (sx,sy) */
       
   207 	if (x == sx) {
       
   208 		if (y == sy) return_cmd_error(STR_5008_CANNOT_START_AND_END_ON);
       
   209 		direction = AXIS_Y;
       
   210 		if (y > sy) uintswap(y,sy);
       
   211 	} else if (y == sy) {
       
   212 		direction = AXIS_X;
       
   213 		if (x > sx) uintswap(x,sx);
       
   214 	} else {
       
   215 		return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN);
       
   216 	}
       
   217 
       
   218 	/* set and test bridge length, availability */
       
   219 	bridge_len = sx + sy - x - y - 1;
       
   220 	if (!CheckBridge_Stuff(bridge_type, bridge_len)) return_cmd_error(STR_5015_CAN_T_BUILD_BRIDGE_HERE);
       
   221 
       
   222 	/* retrieve landscape height and ensure it's on land */
       
   223 	tile_start = TileXY(x, y);
       
   224 	tile_end = TileXY(sx, sy);
       
   225 	if (IsClearWaterTile(tile_start) || IsClearWaterTile(tile_end)) {
       
   226 		return_cmd_error(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH);
       
   227 	}
       
   228 
       
   229 	tileh_start = GetTileSlope(tile_start, &z_start);
       
   230 	tileh_end = GetTileSlope(tile_end, &z_end);
       
   231 
       
   232 	if (IsSteepSlope(tileh_start)) z_start += TILE_HEIGHT;
       
   233 	if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh_start)) {
       
   234 		z_start += TILE_HEIGHT;
       
   235 		tileh_start = SLOPE_FLAT;
       
   236 	}
       
   237 
       
   238 	if (IsSteepSlope(tileh_end)) z_end += TILE_HEIGHT;
       
   239 	if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh_end)) {
       
   240 		z_end += TILE_HEIGHT;
       
   241 		tileh_end = SLOPE_FLAT;
       
   242 	}
       
   243 
       
   244 	if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED);
       
   245 
       
   246 	// Towns are not allowed to use bridges on slopes.
       
   247 	allow_on_slopes = (!_is_old_ai_player
       
   248 	                   && _current_player != OWNER_TOWN && _patches.build_on_slopes);
       
   249 
       
   250 	/* Try and clear the start landscape */
       
   251 
       
   252 	ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   253 	if (CmdFailed(ret)) return ret;
       
   254 	cost = ret;
       
   255 
       
   256 	terraformcost = CheckBridgeSlopeNorth(direction, tileh_start);
       
   257 	if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
       
   258 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   259 	cost += terraformcost;
       
   260 
       
   261 	/* Try and clear the end landscape */
       
   262 
       
   263 	ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   264 	if (CmdFailed(ret)) return ret;
       
   265 	cost += ret;
       
   266 
       
   267 	// false - end tile slope check
       
   268 	terraformcost = CheckBridgeSlopeSouth(direction, tileh_end);
       
   269 	if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
       
   270 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   271 	cost += terraformcost;
       
   272 
       
   273 	{
       
   274 		TileIndex Heads[] = {tile_start, tile_end};
       
   275 		int i;
       
   276 
       
   277 		for (i = 0; i < 2; i++) {
       
   278 			if (MayHaveBridgeAbove(Heads[i])) {
       
   279 				if (IsBridgeAbove(Heads[i])) {
       
   280 					TileIndex north_head = GetNorthernBridgeEnd(Heads[i]);
       
   281 
       
   282 					if (direction == GetBridgeAxis(Heads[i])) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
       
   283 
       
   284 					if (z_start + TILE_HEIGHT == GetBridgeHeight(north_head)) {
       
   285 						return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
       
   286 					}
       
   287 				}
       
   288 			}
       
   289 		}
       
   290 	}
       
   291 
       
   292 	/* do the drill? */
       
   293 	if (flags & DC_EXEC) {
       
   294 		DiagDirection dir = AxisToDiagDir(direction);
       
   295 
       
   296 		if (transport == TRANSPORT_RAIL) {
       
   297 			MakeRailBridgeRamp(tile_start, _current_player, bridge_type, dir, railtype);
       
   298 			MakeRailBridgeRamp(tile_end,   _current_player, bridge_type, ReverseDiagDir(dir), railtype);
       
   299 		} else {
       
   300 			MakeRoadBridgeRamp(tile_start, _current_player, bridge_type, dir);
       
   301 			MakeRoadBridgeRamp(tile_end,   _current_player, bridge_type, ReverseDiagDir(dir));
       
   302 		}
       
   303 		MarkTileDirtyByTile(tile_start);
       
   304 		MarkTileDirtyByTile(tile_end);
       
   305 	}
       
   306 
       
   307 	delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
       
   308 	for (tile = tile_start + delta; tile != tile_end; tile += delta) {
       
   309 		uint z;
       
   310 
       
   311 		if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED);
       
   312 
       
   313 		if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) {
       
   314 			/* Disallow crossing bridges for the time being */
       
   315 			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
       
   316 		}
       
   317 
       
   318 		switch (GetTileType(tile)) {
       
   319 			case MP_WATER:
       
   320 				if (!EnsureNoVehicle(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY);
       
   321 				if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
       
   322 				break;
       
   323 
       
   324 			case MP_RAILWAY:
       
   325 				if (!IsPlainRailTile(tile)) goto not_valid_below;
       
   326 				break;
       
   327 
       
   328 			case MP_STREET:
       
   329 				if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) goto not_valid_below;
       
   330 				break;
       
   331 
       
   332 			case MP_TUNNEL:
       
   333 				break;
       
   334 
       
   335 			case MP_STREET_BRIDGE:
       
   336 			case MP_RAILWAY_BRIDGE:
       
   337 				if (direction == DiagDirToAxis(GetBridgeRampDirection(tile))) goto not_valid_below;
       
   338 				if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
       
   339 				break;
       
   340 
       
   341 			case MP_UNMOVABLE:
       
   342 				if (!IsOwnedLand(tile)) goto not_valid_below;
       
   343 				break;
       
   344 
       
   345 			case MP_CLEAR:
       
   346 				if (IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
       
   347 				break;
       
   348 
       
   349 			default:
       
   350 not_valid_below:;
       
   351 				/* try and clear the middle landscape */
       
   352 				ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   353 				if (CmdFailed(ret)) return ret;
       
   354 				cost += ret;
       
   355 				break;
       
   356 		}
       
   357 
       
   358 		if (flags & DC_EXEC) {
       
   359 			SetBridgeMiddle(tile, direction);
       
   360 			MarkTileDirtyByTile(tile);
       
   361 		}
       
   362 	}
       
   363 
       
   364 	SetSignalsOnBothDir(tile_start, AxisToTrack(direction));
       
   365 	YapfNotifyTrackLayoutChange(tile_start, AxisToTrack(direction));
       
   366 
       
   367 	/* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
       
   368 	 * It's unnecessary to execute this command every time for every bridge. So it is done only
       
   369 	 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
       
   370 	 */
       
   371 	if (!(flags & DC_QUERY_COST)) {
       
   372 		const Bridge *b = &_bridge[bridge_type];
       
   373 
       
   374 		bridge_len += 2; // begin and end tiles/ramps
       
   375 
       
   376 		if (IsValidPlayer(_current_player) && !_is_old_ai_player)
       
   377 			bridge_len = CalcBridgeLenCostFactor(bridge_len);
       
   378 
       
   379 		cost += (int64)bridge_len * _price.build_bridge * b->price >> 8;
       
   380 	}
       
   381 
       
   382 	return cost;
       
   383 }
       
   384 
       
   385 
       
   386 static inline bool CheckAllowRemoveBridge(TileIndex tile)
       
   387 {
       
   388 	/* Floods can remove anything as well as the scenario editor */
       
   389 	if (_current_player == OWNER_WATER || _game_mode == GM_EDITOR) return true;
       
   390 	/* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
       
   391 	if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
       
   392 	/* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */
       
   393 	if (IsTileOwner(tile, OWNER_TOWN) && (_patches.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
       
   394 	return false;
       
   395 }
       
   396 
       
   397 static bool IsVehicleOnBridge(TileIndex starttile, TileIndex endtile, uint z)
       
   398 {
       
   399 	const Vehicle *v;
       
   400 	FOR_ALL_VEHICLES(v) {
       
   401 		if ((v->tile == starttile || v->tile == endtile) && v->z_pos == z) {
       
   402 			_error_message = VehicleInTheWayErrMsg(v);
       
   403 			return true;
       
   404 		}
       
   405 	}
       
   406 	return false;
       
   407 }
       
   408 
       
   409 static int32 DoClearBridge(TileIndex tile, uint32 flags)
       
   410 {
       
   411 	DiagDirection direction;
       
   412 	TileIndexDiff delta;
       
   413 	TileIndex endtile;
       
   414 	Town *t = NULL;
       
   415 
       
   416 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   417 
       
   418 	if (!CheckAllowRemoveBridge(tile)) return CMD_ERROR;
       
   419 
       
   420 	endtile = GetOtherBridgeEnd(tile);
       
   421 
       
   422 	if (!EnsureNoVehicle(tile) ||
       
   423 			!EnsureNoVehicle(endtile) ||
       
   424 			IsVehicleOnBridge(tile, endtile, GetBridgeHeight(tile))) {
       
   425 		return CMD_ERROR;
       
   426 	}
       
   427 
       
   428 	direction = GetBridgeRampDirection(tile);
       
   429 	delta = TileOffsByDiagDir(direction);
       
   430 
       
   431 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
       
   432 		t = ClosestTownFromTile(tile, (uint)-1); // town penalty rating
       
   433 
       
   434 		/* Check if you are allowed to remove the bridge owned by a town
       
   435 		 * Removal depends on difficulty settings */
       
   436 		if (!CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE)) {
       
   437 			SetDParam(0, t->index);
       
   438 			return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
       
   439 		}
       
   440 	}
       
   441 
       
   442 	if (flags & DC_EXEC) {
       
   443 		TileIndex c;
       
   444 		Track track;
       
   445 
       
   446 		//checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
       
   447 		// you have a "Poor" (0) town rating
       
   448 		if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR)
       
   449 			ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
       
   450 
       
   451 		DoClearSquare(tile);
       
   452 		DoClearSquare(endtile);
       
   453 		for (c = tile + delta; c != endtile; c += delta) {
       
   454 				ClearBridgeMiddle(c);
       
   455 			MarkTileDirtyByTile(c);
       
   456 		}
       
   457 
       
   458 		UpdateSignalsOnSegment(tile, ReverseDiagDir(direction));
       
   459 		UpdateSignalsOnSegment(endtile, direction);
       
   460 		track = AxisToTrack(DiagDirToAxis(direction));
       
   461 		YapfNotifyTrackLayoutChange(tile, track);
       
   462 		YapfNotifyTrackLayoutChange(endtile, track);
       
   463 	}
       
   464 
       
   465 	return (DistanceManhattan(tile, endtile) + 1) * _price.clear_bridge;
       
   466 }
       
   467 
       
   468 
       
   469 static int32 ClearTile_Bridge(TileIndex tile, byte flags)
       
   470 {
       
   471 	assert(IsBridgeTile(tile));
       
   472 	if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
       
   473 	return DoClearBridge(tile, flags);
       
   474 }
       
   475 
       
   476 int32 DoConvertBridgeRail(TileIndex tile, RailType totype, bool exec)
       
   477 {
       
   478 	TileIndex endtile;
       
   479 
       
   480 	if (GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
       
   481 		if (!CheckTileOwnership(tile)) return CMD_ERROR;
       
   482 
       
   483 		endtile = GetOtherBridgeEnd(tile);
       
   484 
       
   485 		if (!EnsureNoVehicle(tile) ||
       
   486 				!EnsureNoVehicle(endtile) ||
       
   487 				IsVehicleOnBridge(tile, endtile, GetBridgeHeight(tile))) {
       
   488 			return CMD_ERROR;
       
   489 		}
       
   490 
       
   491 		if (GetRailType(tile) == totype) return CMD_ERROR;
       
   492 
       
   493 		if (exec) {
       
   494 			TileIndexDiff delta;
       
   495 			Track track;
       
   496 
       
   497 			SetRailType(tile, totype);
       
   498 			SetRailType(endtile, totype);
       
   499 			MarkTileDirtyByTile(tile);
       
   500 			MarkTileDirtyByTile(endtile);
       
   501 
       
   502 			track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile)));
       
   503 			YapfNotifyTrackLayoutChange(tile, track);
       
   504 			YapfNotifyTrackLayoutChange(endtile, track);
       
   505 
       
   506 			delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
       
   507 			for (tile += delta; tile != endtile; tile += delta) {
       
   508 				MarkTileDirtyByTile(tile); // TODO encapsulate this into a function
       
   509 			}
       
   510 		}
       
   511 
       
   512 		return (DistanceManhattan(tile, endtile) + 1) * (_price.build_rail >> 1);
       
   513 	} else {
       
   514 		return CMD_ERROR;
       
   515 	}
       
   516 }
       
   517 
       
   518 
       
   519 static void DrawBridgePillars(PalSpriteID image, const TileInfo* ti, Axis axis, uint type, int x, int y, int z)
       
   520 {
       
   521 	if (image != 0) {
       
   522 		bool drawfarpillar = !HASBIT(GetBridgeFlags(type), 0);
       
   523 		int back_height, front_height;
       
   524 		int i = z;
       
   525 		const byte *p;
       
   526 
       
   527 		static const byte _tileh_bits[4][8] = {
       
   528 			{ 2, 1, 8, 4,  16,  2, 0, 9 },
       
   529 			{ 1, 8, 4, 2,   2, 16, 9, 0 },
       
   530 			{ 4, 8, 1, 2,  16,  2, 0, 9 },
       
   531 			{ 2, 4, 8, 1,   2, 16, 9, 0 }
       
   532 		};
       
   533 
       
   534 		if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
       
   535 
       
   536 		p = _tileh_bits[(image & 1) * 2 + (axis == AXIS_X ? 0 : 1)];
       
   537 		front_height = ti->z + (ti->tileh & p[0] ? TILE_HEIGHT : 0);
       
   538 		back_height  = ti->z + (ti->tileh & p[1] ? TILE_HEIGHT : 0);
       
   539 
       
   540 		if (IsSteepSlope(ti->tileh)) {
       
   541 			if (!(ti->tileh & p[2])) front_height += TILE_HEIGHT;
       
   542 			if (!(ti->tileh & p[3])) back_height  += TILE_HEIGHT;
       
   543 		}
       
   544 
       
   545 		for (; z >= front_height || z >= back_height; z -= TILE_HEIGHT) {
       
   546 			/* HACK set height of the BB of pillars to 1, because the origin of the
       
   547 			 * sprites is at the top
       
   548 			 */
       
   549 			if (z >= front_height) { // front facing pillar
       
   550 				AddSortableSpriteToDraw(image, x, y, p[4], p[5], 1, z);
       
   551 			}
       
   552 
       
   553 			if (drawfarpillar && z >= back_height && z < i - TILE_HEIGHT) { // back facing pillar
       
   554 				AddSortableSpriteToDraw(image, x - p[6], y - p[7], p[4], p[5], 1, z);
       
   555 			}
       
   556 		}
       
   557 	}
       
   558 }
       
   559 
       
   560 uint GetBridgeFoundation(Slope tileh, Axis axis)
       
   561 {
       
   562 	uint i;
       
   563 
       
   564 	if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) return tileh;
       
   565 
       
   566 	// inclined sloped building
       
   567 	switch (tileh) {
       
   568 		case SLOPE_W:
       
   569 		case SLOPE_STEEP_W: i = 0; break;
       
   570 		case SLOPE_S:
       
   571 		case SLOPE_STEEP_S: i = 2; break;
       
   572 		case SLOPE_E:
       
   573 		case SLOPE_STEEP_E: i = 4; break;
       
   574 		case SLOPE_N:
       
   575 		case SLOPE_STEEP_N: i = 6; break;
       
   576 		default: return 0;
       
   577 	}
       
   578 	if (axis != AXIS_X) ++i;
       
   579 	return i + 15;
       
   580 }
       
   581 
       
   582 
       
   583 /**
       
   584  * Draws a bridge tile.
       
   585  * base_offset is where the sprite selection comes into play
       
   586  * and it works a bit like a bitmask.<p> For bridge heads:
       
   587  * <ul><li>Bit 0: direction</li>
       
   588  * <li>Bit 1: northern or southern heads</li>
       
   589  * <li>Bit 2: Set if the bridge head is sloped</li>
       
   590  * <li>Bit 3 and more: Railtype Specific subset</li>
       
   591  * </ul>
       
   592  * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
       
   593  */
       
   594 static void DrawTile_Bridge(TileInfo *ti)
       
   595 {
       
   596 	uint32 image;
       
   597 
       
   598 	int base_offset;
       
   599 	bool ice = HasBridgeSnowOrDesert(ti->tile);
       
   600 
       
   601 	if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
       
   602 		if (GetTrackBits(ti->tile) != TRACK_BIT_X && GetTrackBits(ti->tile) != TRACK_BIT_Y) {
       
   603 			DrawTile_Track(ti);
       
   604 			return;
       
   605 		}
       
   606 		base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
       
   607 		assert(base_offset != 8); /* This one is used for roads */
       
   608 	} else {
       
   609 		base_offset = 8;
       
   610 	}
       
   611 
       
   612 	/* as the lower 3 bits are used for other stuff, make sure they are clear */
       
   613 	assert( (base_offset & 0x07) == 0x00);
       
   614 
       
   615 	if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) {
       
   616 		int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
       
   617 		if (f != 0) DrawFoundation(ti, f);
       
   618 	}
       
   619 
       
   620 	// HACK Wizardry to convert the bridge ramp direction into a sprite offset
       
   621 	base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4;
       
   622 
       
   623 	if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
       
   624 
       
   625 	/* Table number 6 always refers to the bridge heads for any bridge type */
       
   626 	image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
       
   627 
       
   628 	if (!ice) {
       
   629 		DrawClearLandTile(ti, 3);
       
   630 	} else {
       
   631 		DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh]);
       
   632 	}
       
   633 
       
   634 	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
       
   635 
       
   636 	// draw ramp
       
   637 	if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
       
   638 	/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
       
   639 	 * it doesn't disappear behind it
       
   640 	 */
       
   641 	AddSortableSpriteToDraw(
       
   642 		image, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 1 : 8, ti->z
       
   643 	);
       
   644 
       
   645 	if (IsTileType(ti->tile, MP_RAILWAY_BRIDGE) && HasSignals(ti->tile)) DrawSignals(ti->tile, GetTrackBits(ti->tile));
       
   646 
       
   647 	DrawBridgeMiddle(ti);
       
   648 }
       
   649 
       
   650 
       
   651 /** Compute bridge piece. Computes the bridge piece to display depending on the position inside the bridge.
       
   652  * bridges pieces sequence (middle parts)
       
   653  * bridge len 1: 0
       
   654  * bridge len 2: 0 1
       
   655  * bridge len 3: 0 4 1
       
   656  * bridge len 4: 0 2 3 1
       
   657  * bridge len 5: 0 2 5 3 1
       
   658  * bridge len 6: 0 2 3 2 3 1
       
   659  * bridge len 7: 0 2 3 4 2 3 1
       
   660  * #0 - always as first, #1 - always as last (if len>1)
       
   661  * #2,#3 are to pair in order
       
   662  * for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0)
       
   663  * @param north Northernmost tile of bridge
       
   664  * @param south Southernmost tile of bridge
       
   665  * @return Index of bridge piece
       
   666  */
       
   667 static uint CalcBridgePiece(uint north, uint south)
       
   668 {
       
   669 	if (north == 1) {
       
   670 		return 0;
       
   671 	} else if (south == 1) {
       
   672 		return 1;
       
   673 	} else if (north < south) {
       
   674 		return north & 1 ? 3 : 2;
       
   675 	} else if (north > south) {
       
   676 		return south & 1 ? 2 : 3;
       
   677 	} else {
       
   678 		return north & 1 ? 5 : 4;
       
   679 	}
       
   680 }
       
   681 
       
   682 
       
   683 void DrawBridgeMiddle(const TileInfo* ti)
       
   684 {
       
   685 	const PalSpriteID* b;
       
   686 	PalSpriteID image;
       
   687 	uint base_offset;
       
   688 	TileIndex rampnorth;
       
   689 	TileIndex rampsouth;
       
   690 	Axis axis;
       
   691 	uint piece;
       
   692 	uint type;
       
   693 	int x;
       
   694 	int y;
       
   695 	uint z;
       
   696 
       
   697 	if (!IsBridgeAbove(ti->tile)) return;
       
   698 
       
   699 	rampnorth = GetNorthernBridgeEnd(ti->tile);
       
   700 	rampsouth = GetSouthernBridgeEnd(ti->tile);
       
   701 
       
   702 	axis = GetBridgeAxis(ti->tile);
       
   703 	piece = CalcBridgePiece(
       
   704 		DistanceManhattan(ti->tile, rampnorth),
       
   705 		DistanceManhattan(ti->tile, rampsouth)
       
   706 	);
       
   707 	type = GetBridgeType(rampsouth);
       
   708 
       
   709 	if (GetBridgeTransportType(rampsouth) == TRANSPORT_RAIL) {
       
   710 		base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
       
   711 	} else {
       
   712 		base_offset = 8;
       
   713 	}
       
   714 
       
   715 	b = base_offset + GetBridgeSpriteTable(type, piece);
       
   716 	if (axis != AXIS_X) b += 4;
       
   717 
       
   718 	x = ti->x;
       
   719 	y = ti->y;
       
   720 	z = GetBridgeHeight(rampsouth) - 3;
       
   721 
       
   722 	image = b[0];
       
   723 	if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
       
   724 	if (axis == AXIS_X) {
       
   725 		AddSortableSpriteToDraw(image, x, y, 16, 11, 1, z);
       
   726 	} else {
       
   727 		AddSortableSpriteToDraw(image, x, y, 11, 16, 1, z);
       
   728 	}
       
   729 
       
   730 	image = b[1];
       
   731 	if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
       
   732 
       
   733 	// draw roof, the component of the bridge which is logically between the vehicle and the camera
       
   734 	if (axis == AXIS_X) {
       
   735 		y += 12;
       
   736 		if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 16, 1, 0x28, z);
       
   737 	} else {
       
   738 		x += 12;
       
   739 		if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, x, y, 1, 16, 0x28, z);
       
   740 	}
       
   741 
       
   742 	if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
       
   743 
       
   744 	if (ti->z + 5 == z) {
       
   745 		// draw poles below for small bridges
       
   746 		image = b[2];
       
   747 		if (image != 0) {
       
   748 			if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
       
   749 			DrawGroundSpriteAt(image, x, y, z);
       
   750 		}
       
   751 	} else if (_patches.bridge_pillars) {
       
   752 		// draw pillars below for high bridges
       
   753 		DrawBridgePillars(b[2], ti, axis, type, x, y, z);
       
   754 	}
       
   755 }
       
   756 
       
   757 
       
   758 uint SetSpeedLimitOnBridge(Vehicle *v)
       
   759 {
       
   760 	uint bridge_speed;
       
   761 	if (v->vehstatus & VS_HIDDEN) return v->max_speed; /* in tunnel */
       
   762 
       
   763 	bridge_speed = _bridge[GetBridgeType(v->tile)].speed;
       
   764 
       
   765 	if (v->type == VEH_Road) bridge_speed *= 2; /* XXX give vehicles proper speeds */
       
   766 
       
   767 	if (v->cur_speed > bridge_speed) v->cur_speed = bridge_speed;
       
   768 	return bridge_speed;
       
   769 }
       
   770 
       
   771 static bool IsCustomBridgeHead(TileIndex tile)
       
   772 {
       
   773 	assert(IsBridgeTile(tile));
       
   774 
       
   775 	if (IsTileType(tile, MP_RAILWAY_BRIDGE)) {
       
   776 		return !(GetTrackBits(tile) == TRACK_BIT_X || GetTrackBits(tile) == TRACK_BIT_Y);
       
   777 	}
       
   778 
       
   779 	return false; /* TODO - street bridges */
       
   780 }
       
   781 
       
   782 
       
   783 /** Gets the absolute z coordinate of a point inside a bridge tile
       
   784  *  When we're on the track (that means between position 5 and 10)
       
   785  *  on the coordinate perpendicular to the track it returns the base
       
   786  *  height of the ramp
       
   787  *  Outside this range (from 0 to 4 and from 11 to 15) it returns the
       
   788  *  "true" Z coordinate of the tile by taking the slope into account
       
   789  *  For custom bridge heads the entire bridge head is flat and has the
       
   790  *  same z coordinate
       
   791  *  @param tile The index of the tile we are talking about
       
   792  *  @param x Absolute or relative x coordinate
       
   793  *  @param y Absolute or relative y coordinate
       
   794  *  @return Absolute z coordinate
       
   795  */
       
   796 static uint GetSlopeZ_Bridge(TileIndex tile, uint x, uint y)
       
   797 {
       
   798 	uint z, pos;
       
   799 	Slope tileh = GetTileSlope(tile, &z);
       
   800 	DiagDirection dir = GetBridgeRampDirection(tile);
       
   801 
       
   802 	x &= 0xF;
       
   803 	y &= 0xF;
       
   804 
       
   805 	pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
       
   806 
       
   807 	// On the bridge ramp or flat bridge head?
       
   808 	if ( (2 <= pos && pos <= 13) || IsCustomBridgeHead(tile)) {
       
   809 		uint delta;
       
   810 
       
   811 		if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2;
       
   812 
       
   813 		if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT;
       
   814 
       
   815 		if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) z += TILE_HEIGHT;
       
   816 		switch (dir) {
       
   817 			default: NOT_REACHED();
       
   818 			case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
       
   819 			case DIAGDIR_SE: delta = y / 2; break;
       
   820 			case DIAGDIR_SW: delta = x / 2; break;
       
   821 			case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
       
   822 		}
       
   823 		return z + 1 + delta;
       
   824 	} else {
       
   825 		uint f = GetBridgeFoundation(tileh, DiagDirToAxis(dir));
       
   826 
       
   827 		if (f != 0) {
       
   828 			if (IsSteepSlope(tileh)) {
       
   829 				z += TILE_HEIGHT;
       
   830 			} else if (f < 15) {
       
   831 				return z + TILE_HEIGHT;
       
   832 			}
       
   833 			tileh = _inclined_tileh[f - 15];
       
   834 		}
       
   835 	}
       
   836 	return z + GetPartialZ(x, y, tileh);
       
   837 }
       
   838 
       
   839 static Slope GetSlopeTileh_Bridge(TileIndex tile, Slope tileh)
       
   840 {
       
   841 	if (HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
       
   842 		return tileh;
       
   843 	} else {
       
   844 		uint f = GetBridgeFoundation(tileh, DiagDirToAxis(GetBridgeRampDirection(tile)));
       
   845 
       
   846 		if (f == 0) return tileh;
       
   847 		if (f < 15) return SLOPE_FLAT;
       
   848 		return _inclined_tileh[f - 15];
       
   849 	}
       
   850 }
       
   851 
       
   852 static void GetAcceptedCargo_Bridge(TileIndex tile, AcceptedCargo ac)
       
   853 {
       
   854 	/* not used */
       
   855 }
       
   856 
       
   857 static const StringID _bridge_tile_str[(MAX_BRIDGES + 3) + (MAX_BRIDGES + 3)] = {
       
   858 	STR_501F_WOODEN_RAIL_BRIDGE,
       
   859 	STR_5020_CONCRETE_RAIL_BRIDGE,
       
   860 	STR_501C_STEEL_GIRDER_RAIL_BRIDGE,
       
   861 	STR_501E_REINFORCED_CONCRETE_SUSPENSION,
       
   862 	STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE,
       
   863 	STR_501B_STEEL_SUSPENSION_RAIL_BRIDGE,
       
   864 	STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE,
       
   865 	STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE,
       
   866 	STR_501D_STEEL_CANTILEVER_RAIL_BRIDGE,
       
   867 	STR_501C_STEEL_GIRDER_RAIL_BRIDGE,
       
   868 	STR_5027_TUBULAR_RAIL_BRIDGE,
       
   869 	STR_5027_TUBULAR_RAIL_BRIDGE,
       
   870 	STR_5027_TUBULAR_RAIL_BRIDGE,
       
   871 	0, 0, 0,
       
   872 
       
   873 	STR_5025_WOODEN_ROAD_BRIDGE,
       
   874 	STR_5026_CONCRETE_ROAD_BRIDGE,
       
   875 	STR_5022_STEEL_GIRDER_ROAD_BRIDGE,
       
   876 	STR_5024_REINFORCED_CONCRETE_SUSPENSION,
       
   877 	STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE,
       
   878 	STR_5021_STEEL_SUSPENSION_ROAD_BRIDGE,
       
   879 	STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE,
       
   880 	STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE,
       
   881 	STR_5023_STEEL_CANTILEVER_ROAD_BRIDGE,
       
   882 	STR_5022_STEEL_GIRDER_ROAD_BRIDGE,
       
   883 	STR_5028_TUBULAR_ROAD_BRIDGE,
       
   884 	STR_5028_TUBULAR_ROAD_BRIDGE,
       
   885 	STR_5028_TUBULAR_ROAD_BRIDGE,
       
   886 	0, 0, 0,
       
   887 };
       
   888 
       
   889 static void GetTileDesc_Bridge(TileIndex tile, TileDesc *td)
       
   890 {
       
   891 	td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
       
   892 	td->owner = GetTileOwner(tile);
       
   893 }
       
   894 
       
   895 
       
   896 static void AnimateTile_Bridge(TileIndex tile)
       
   897 {
       
   898 	/* not used */
       
   899 }
       
   900 
       
   901 
       
   902 static void TileLoop_Bridge(TileIndex tile)
       
   903 {
       
   904 	bool snow_or_desert = HasBridgeSnowOrDesert(tile);
       
   905 	switch (_opt.landscape) {
       
   906 		case LT_HILLY:
       
   907 			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
       
   908 				SetBridgeSnowOrDesert(tile, !snow_or_desert);
       
   909 				MarkTileDirtyByTile(tile);
       
   910 			}
       
   911 			break;
       
   912 
       
   913 		case LT_DESERT:
       
   914 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
       
   915 				SetBridgeSnowOrDesert(tile, true);
       
   916 				MarkTileDirtyByTile(tile);
       
   917 			}
       
   918 			break;
       
   919 	}
       
   920 }
       
   921 
       
   922 static void ClickTile_Bridge(TileIndex tile)
       
   923 {
       
   924 	/* not used */
       
   925 }
       
   926 
       
   927 
       
   928 static uint32 GetTileTrackStatus_Bridge(TileIndex tile, TransportType mode)
       
   929 {
       
   930 	if (GetBridgeTransportType(tile) != mode) return 0;
       
   931 
       
   932 	if (IsTileType(tile, MP_RAILWAY_BRIDGE)) return GetTileTrackStatus_Track(tile, mode);
       
   933 	return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
       
   934 }
       
   935 
       
   936 
       
   937 static void ChangeTileOwner_Bridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
       
   938 {
       
   939 	if (!IsTileOwner(tile, old_player)) return;
       
   940 
       
   941 	if (new_player != PLAYER_SPECTATOR) {
       
   942 		SetTileOwner(tile, new_player);
       
   943 	} else {
       
   944 		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
       
   945 	}
       
   946 }
       
   947 
       
   948 
       
   949 static uint32 VehicleEnter_Street_Bridge(Vehicle *v, TileIndex tile, int x, int y)
       
   950 {
       
   951 	int z = GetSlopeZ(x, y) - v->z_pos;
       
   952 
       
   953 	DiagDirection dir;
       
   954 
       
   955 	if (myabs(z) > 2) return 8;
       
   956 
       
   957 	if (v->type == VEH_Road) {
       
   958 		/* modify speed of vehicle */
       
   959 		uint16 spd = _bridge[GetBridgeType(tile)].speed * 2;
       
   960 		if (v->cur_speed > spd) v->cur_speed = spd;
       
   961 	}
       
   962 
       
   963 	dir = GetBridgeRampDirection(tile);
       
   964 	if (DirToDiagDir(v->direction) == dir) {
       
   965 		switch (dir) {
       
   966 			default: NOT_REACHED();
       
   967 			case DIAGDIR_NE: if ((x & 0xF) != 0)             return 0; break;
       
   968 			case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return 0; break;
       
   969 			case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return 0; break;
       
   970 			case DIAGDIR_NW: if ((y & 0xF) != 0)             return 0; break;
       
   971 		}
       
   972 		v->u.road.state = 0xFF;
       
   973 		return 4;
       
   974 	} else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
       
   975 		v->tile = tile;
       
   976 		if (v->u.road.state == 0xFF) {
       
   977 			static const byte road_exit_bridge_state[4] = {8, 9, 0, 1};
       
   978 			v->u.road.state = road_exit_bridge_state[dir];
       
   979 			v->u.road.frame = 0;
       
   980 			return 4;
       
   981 		}
       
   982 		return 0;
       
   983 	}
       
   984 	return 0;
       
   985 }
       
   986 
       
   987 /**
       
   988   * @retval 0 The vehicle can proceed
       
   989   * @retval 4 The vehicle changed onto of off the bridge (depending on the
       
   990   *           status before, check with v->u.rail.track == 0x40)
       
   991   * @retval 8 The vehicle cannot enter the tile
       
   992   */
       
   993 static uint32 VehicleEnter_Railway_Bridge(Vehicle *v, TileIndex tile, int x, int y)
       
   994 {
       
   995 	int z = GetSlopeZ(x, y) - v->z_pos;
       
   996 
       
   997 	DiagDirection dir;
       
   998 
       
   999 	if (IsCustomBridgeHead(tile)) {
       
  1000 		uint h;
       
  1001 		GetTileSlope(tile, &h);
       
  1002 
       
  1003 		z = h + TILE_HEIGHT - v->z_pos;
       
  1004 	}
       
  1005 
       
  1006 	if (myabs(z) > 2) return 8;
       
  1007 
       
  1008 	if (IsFrontEngine(v)) {
       
  1009 		/* modify speed of vehicle */
       
  1010 		uint16 spd = _bridge[GetBridgeType(tile)].speed;
       
  1011 		if (v->cur_speed > spd) v->cur_speed = spd;
       
  1012 	}
       
  1013 
       
  1014 	dir = GetBridgeRampDirection(tile);
       
  1015 
       
  1016 	if (v->direction == DiagDirToDir(ReverseDiagDir(dir))) {
       
  1017 		/* We are entering the bridge head from the bridge itself */
       
  1018 		if (v->u.rail.track == 0x40) {
       
  1019 			/* Get the vehicle out of the wormhole, the track will be chosen later
       
  1020 			   by the pathfinder */
       
  1021 			v->tile = tile;
       
  1022 			v->u.rail.track = TrackToTrackBits(TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
       
  1023 			return 4;
       
  1024 		}
       
  1025 		return 0;
       
  1026 
       
  1027 	} else {
       
  1028 		TileIndex other_bridge_end_tile;
       
  1029 		uint32 bridge_length;
       
  1030 		/* We are on the bridge head itself, possibly entering the bridge */
       
  1031 		/* Vehicle will enter the bridge wormhole when it reaches the tile edge in the
       
  1032 		 * direction of the bridge. */
       
  1033 		TileIndexDiffC diff = TileIndexDiffCByDiagDir(dir);
       
  1034 		/* If vehicle didn't reach the edge we can return and try it next time */
       
  1035 		if (((diff.x != 0 ? x : y) & 0x0F) != (diff.x + diff.y > 0 ? TILE_SIZE - 1 : 0)) return 0;
       
  1036 		/* We will enter the bridge wormhole. */
       
  1037 
       
  1038 		other_bridge_end_tile = GetOtherBridgeEnd(tile);
       
  1039 		bridge_length = GetBridgeLength(tile, other_bridge_end_tile);
       
  1040 		if (bridge_length > 0) {
       
  1041 			/* Non-zero bridge length. Adjust the other coordinate to the middle of tile
       
  1042 			* to allow train controller to select proper vehicle image */
       
  1043 			if (diff.x != 0) v->y_pos = y; else v->x_pos = x;
       
  1044 			v->direction = DiagDirToDir(dir);
       
  1045 			/* We're about to enter the bridge body, clear all up/down flags just in case */
       
  1046 			v->u.rail.track = 0x40;
       
  1047 			v->direction = DiagDirToDir(dir);
       
  1048 			CLRBIT(v->u.rail.flags, VRF_GOINGUP);
       
  1049 			CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
       
  1050 			return 4;
       
  1051 		} else {
       
  1052 			/* Zero bridge length. Pretend that nothing extra happened. Custom bridge heads should act as normal tracks. */
       
  1053 			;
       
  1054 		}
       
  1055 	}
       
  1056 	return 0;
       
  1057 }
       
  1058 
       
  1059 static uint32 VehicleEnter_Bridge(Vehicle *v, TileIndex tile, int x, int y)
       
  1060 {
       
  1061 	if (v->type == VEH_Train) return VehicleEnter_Railway_Bridge(v, tile, x, y);
       
  1062 
       
  1063 	if (v->type == VEH_Road) return VehicleEnter_Street_Bridge(v, tile, x, y);
       
  1064 
       
  1065 	NOT_REACHED();
       
  1066 }
       
  1067 
       
  1068 const TileTypeProcs _tile_type_bridge_procs = {
       
  1069 	DrawTile_Bridge,           /* draw_tile_proc */
       
  1070 	GetSlopeZ_Bridge,          /* get_slope_z_proc */
       
  1071 	ClearTile_Bridge,          /* clear_tile_proc */
       
  1072 	GetAcceptedCargo_Bridge,   /* get_accepted_cargo_proc */
       
  1073 	GetTileDesc_Bridge,        /* get_tile_desc_proc */
       
  1074 	GetTileTrackStatus_Bridge, /* get_tile_track_status_proc */
       
  1075 	ClickTile_Bridge,          /* click_tile_proc */
       
  1076 	AnimateTile_Bridge,        /* animate_tile_proc */
       
  1077 	TileLoop_Bridge,           /* tile_loop_clear */
       
  1078 	ChangeTileOwner_Bridge,    /* change_tile_owner_clear */
       
  1079 	NULL,                      /* get_produced_cargo_proc */
       
  1080 	VehicleEnter_Bridge,       /* vehicle_enter_tile_proc */
       
  1081 	GetSlopeTileh_Bridge,      /* get_slope_tileh_proc */
       
  1082 };