1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /**
9  * @file tunnelbridge_cmd.cpp
10  * This file deals with tunnels and bridges (non-gui stuff)
11  * @todo separate this file into two
12  */
13 
14 #include "stdafx.h"
15 #include "newgrf_object.h"
16 #include "viewport_func.h"
17 #include "cmd_helper.h"
18 #include "command_func.h"
19 #include "town.h"
20 #include "train.h"
21 #include "ship.h"
22 #include "roadveh.h"
23 #include "pathfinder/yapf/yapf_cache.h"
24 #include "newgrf_sound.h"
25 #include "autoslope.h"
26 #include "tunnelbridge_map.h"
27 #include "strings_func.h"
28 #include "date_func.h"
29 #include "clear_func.h"
30 #include "vehicle_func.h"
31 #include "sound_func.h"
32 #include "tunnelbridge.h"
33 #include "cheat_type.h"
34 #include "elrail_func.h"
35 #include "pbs.h"
36 #include "company_base.h"
37 #include "newgrf_railtype.h"
38 #include "newgrf_roadtype.h"
39 #include "object_base.h"
40 #include "water.h"
41 #include "company_gui.h"
42 #include "station_func.h"
43 
44 #include "table/strings.h"
45 #include "table/bridge_land.h"
46 
47 #include "safeguards.h"
48 
49 BridgeSpec _bridge[MAX_BRIDGES]; ///< The specification of all bridges.
50 TileIndex _build_tunnel_endtile; ///< The end of a tunnel; as hidden return from the tunnel build command for GUI purposes.
51 
52 /** Z position of the bridge sprites relative to bridge height (downwards) */
53 static const int BRIDGE_Z_START = 3;
54 
55 
56 /**
57  * Mark bridge tiles dirty.
58  * Note: The bridge does not need to exist, everything is passed via parameters.
59  * @param begin Start tile.
60  * @param end End tile.
61  * @param direction Direction from \a begin to \a end.
62  * @param bridge_height Bridge height level.
63  */
MarkBridgeDirty(TileIndex begin,TileIndex end,DiagDirection direction,uint bridge_height)64 void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height)
65 {
66 	TileIndexDiff delta = TileOffsByDiagDir(direction);
67 	for (TileIndex t = begin; t != end; t += delta) {
68 		MarkTileDirtyByTile(t, bridge_height - TileHeight(t));
69 	}
70 	MarkTileDirtyByTile(end);
71 }
72 
73 /**
74  * Mark bridge tiles dirty.
75  * @param tile Bridge head.
76  */
MarkBridgeDirty(TileIndex tile)77 void MarkBridgeDirty(TileIndex tile)
78 {
79 	MarkBridgeDirty(tile, GetOtherTunnelBridgeEnd(tile), GetTunnelBridgeDirection(tile), GetBridgeHeight(tile));
80 }
81 
82 /** Reset the data been eventually changed by the grf loaded. */
ResetBridges()83 void ResetBridges()
84 {
85 	/* First, free sprite table data */
86 	for (BridgeType i = 0; i < MAX_BRIDGES; i++) {
87 		if (_bridge[i].sprite_table != nullptr) {
88 			for (BridgePieces j = BRIDGE_PIECE_NORTH; j < BRIDGE_PIECE_INVALID; j++) free(_bridge[i].sprite_table[j]);
89 			free(_bridge[i].sprite_table);
90 		}
91 	}
92 
93 	/* Then, wipe out current bridges */
94 	memset(&_bridge, 0, sizeof(_bridge));
95 	/* And finally, reinstall default data */
96 	memcpy(&_bridge, &_orig_bridge, sizeof(_orig_bridge));
97 }
98 
99 /**
100  * Calculate the price factor for building a long bridge.
101  * 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,
102  * @param length Length of the bridge.
103  * @return Price factor for the bridge.
104  */
CalcBridgeLenCostFactor(int length)105 int CalcBridgeLenCostFactor(int length)
106 {
107 	if (length < 2) return length;
108 
109 	length -= 2;
110 	int sum = 2;
111 	for (int delta = 1;; delta++) {
112 		for (int count = 0; count < delta; count++) {
113 			if (length == 0) return sum;
114 			sum += delta;
115 			length--;
116 		}
117 	}
118 }
119 
120 /**
121  * Get the foundation for a bridge.
122  * @param tileh The slope to build the bridge on.
123  * @param axis The axis of the bridge entrance.
124  * @return The foundation required.
125  */
GetBridgeFoundation(Slope tileh,Axis axis)126 Foundation GetBridgeFoundation(Slope tileh, Axis axis)
127 {
128 	if (tileh == SLOPE_FLAT ||
129 			((tileh == SLOPE_NE || tileh == SLOPE_SW) && axis == AXIS_X) ||
130 			((tileh == SLOPE_NW || tileh == SLOPE_SE) && axis == AXIS_Y)) return FOUNDATION_NONE;
131 
132 	return (HasSlopeHighestCorner(tileh) ? InclinedFoundation(axis) : FlatteningFoundation(tileh));
133 }
134 
135 /**
136  * Determines if the track on a bridge ramp is flat or goes up/down.
137  *
138  * @param tileh Slope of the tile under the bridge head
139  * @param axis Orientation of bridge
140  * @return true iff the track is flat.
141  */
HasBridgeFlatRamp(Slope tileh,Axis axis)142 bool HasBridgeFlatRamp(Slope tileh, Axis axis)
143 {
144 	ApplyFoundationToSlope(GetBridgeFoundation(tileh, axis), &tileh);
145 	/* If the foundation slope is flat the bridge has a non-flat ramp and vice versa. */
146 	return (tileh != SLOPE_FLAT);
147 }
148 
GetBridgeSpriteTable(int index,BridgePieces table)149 static inline const PalSpriteID *GetBridgeSpriteTable(int index, BridgePieces table)
150 {
151 	const BridgeSpec *bridge = GetBridgeSpec(index);
152 	assert(table < BRIDGE_PIECE_INVALID);
153 	if (bridge->sprite_table == nullptr || bridge->sprite_table[table] == nullptr) {
154 		return _bridge_sprite_table[index][table];
155 	} else {
156 		return bridge->sprite_table[table];
157 	}
158 }
159 
160 
161 /**
162  * Determines the foundation for the bridge head, and tests if the resulting slope is valid.
163  *
164  * @param bridge_piece Direction of the bridge head.
165  * @param axis Axis of the bridge
166  * @param tileh Slope of the tile under the north bridge head; returns slope on top of foundation
167  * @param z TileZ corresponding to tileh, gets modified as well
168  * @return Error or cost for bridge foundation
169  */
CheckBridgeSlope(BridgePieces bridge_piece,Axis axis,Slope * tileh,int * z)170 static CommandCost CheckBridgeSlope(BridgePieces bridge_piece, Axis axis, Slope *tileh, int *z)
171 {
172 	assert(bridge_piece == BRIDGE_PIECE_NORTH || bridge_piece == BRIDGE_PIECE_SOUTH);
173 
174 	Foundation f = GetBridgeFoundation(*tileh, axis);
175 	*z += ApplyFoundationToSlope(f, tileh);
176 
177 	Slope valid_inclined;
178 	if (bridge_piece == BRIDGE_PIECE_NORTH) {
179 		valid_inclined = (axis == AXIS_X ? SLOPE_NE : SLOPE_NW);
180 	} else {
181 		valid_inclined = (axis == AXIS_X ? SLOPE_SW : SLOPE_SE);
182 	}
183 	if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
184 
185 	if (f == FOUNDATION_NONE) return CommandCost();
186 
187 	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
188 }
189 
190 /**
191  * Is a bridge of the specified type and length available?
192  * @param bridge_type Wanted type of bridge.
193  * @param bridge_len  Wanted length of the bridge.
194  * @param flags       Type of operation.
195  * @return A succeeded (the requested bridge is available) or failed (it cannot be built) command.
196  */
CheckBridgeAvailability(BridgeType bridge_type,uint bridge_len,DoCommandFlag flags)197 CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags)
198 {
199 	if (flags & DC_QUERY_COST) {
200 		if (bridge_len <= _settings_game.construction.max_bridge_length) return CommandCost();
201 		return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
202 	}
203 
204 	if (bridge_type >= MAX_BRIDGES) return CMD_ERROR;
205 
206 	const BridgeSpec *b = GetBridgeSpec(bridge_type);
207 	if (b->avail_year > _cur_year) return CMD_ERROR;
208 
209 	uint max = std::min(b->max_length, _settings_game.construction.max_bridge_length);
210 
211 	if (b->min_length > bridge_len) return CMD_ERROR;
212 	if (bridge_len <= max) return CommandCost();
213 	return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
214 }
215 
216 /**
217  * Calculate the base cost of clearing a tunnel/bridge per tile.
218  * @param tile Start tile of the tunnel/bridge.
219  * @return How much clearing this tunnel/bridge costs per tile.
220  */
TunnelBridgeClearCost(TileIndex tile,Price base_price)221 static Money TunnelBridgeClearCost(TileIndex tile, Price base_price)
222 {
223 	Money base_cost = _price[base_price];
224 
225 	/* Add the cost of the transport that is on the tunnel/bridge. */
226 	switch (GetTunnelBridgeTransportType(tile)) {
227 		case TRANSPORT_ROAD: {
228 			RoadType road_rt = GetRoadTypeRoad(tile);
229 			RoadType tram_rt = GetRoadTypeTram(tile);
230 
231 			if (road_rt != INVALID_ROADTYPE) {
232 				base_cost += 2 * RoadClearCost(road_rt);
233 			}
234 			if (tram_rt != INVALID_ROADTYPE) {
235 				base_cost += 2 * RoadClearCost(tram_rt);
236 			}
237 		} break;
238 
239 		case TRANSPORT_RAIL: base_cost += RailClearCost(GetRailType(tile)); break;
240 		/* Aquaducts have their own clear price. */
241 		case TRANSPORT_WATER: base_cost = _price[PR_CLEAR_AQUEDUCT]; break;
242 		default: break;
243 	}
244 
245 	return base_cost;
246 }
247 
248 /**
249  * Build a Bridge
250  * @param end_tile end tile
251  * @param flags type of operation
252  * @param p1 packed start tile coords (~ dx)
253  * @param p2 various bitstuffed elements
254  * - p2 = (bit  0- 7) - bridge type (hi bh)
255  * - p2 = (bit  8-13) - rail type or road types.
256  * - p2 = (bit 15-16) - transport type.
257  * @param text unused
258  * @return the cost of this operation or an error
259  */
CmdBuildBridge(TileIndex end_tile,DoCommandFlag flags,uint32 p1,uint32 p2,const std::string & text)260 CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
261 {
262 	CompanyID company = _current_company;
263 
264 	RailType railtype = INVALID_RAILTYPE;
265 	RoadType roadtype = INVALID_ROADTYPE;
266 
267 	/* unpack parameters */
268 	BridgeType bridge_type = GB(p2, 0, 8);
269 
270 	if (!IsValidTile(p1)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
271 
272 	TransportType transport_type = Extract<TransportType, 15, 2>(p2);
273 
274 	/* type of bridge */
275 	switch (transport_type) {
276 		case TRANSPORT_ROAD:
277 			roadtype = Extract<RoadType, 8, 6>(p2);
278 			if (!ValParamRoadType(roadtype)) return CMD_ERROR;
279 			break;
280 
281 		case TRANSPORT_RAIL:
282 			railtype = Extract<RailType, 8, 6>(p2);
283 			if (!ValParamRailtype(railtype)) return CMD_ERROR;
284 			break;
285 
286 		case TRANSPORT_WATER:
287 			break;
288 
289 		default:
290 			/* Airports don't have bridges. */
291 			return CMD_ERROR;
292 	}
293 	TileIndex tile_start = p1;
294 	TileIndex tile_end = end_tile;
295 
296 	if (company == OWNER_DEITY) {
297 		if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
298 		const Town *town = CalcClosestTownFromTile(tile_start);
299 
300 		company = OWNER_TOWN;
301 
302 		/* If we are not within a town, we are not owned by the town */
303 		if (town == nullptr || DistanceSquare(tile_start, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
304 			company = OWNER_NONE;
305 		}
306 	}
307 
308 	if (tile_start == tile_end) {
309 		return_cmd_error(STR_ERROR_CAN_T_START_AND_END_ON);
310 	}
311 
312 	Axis direction;
313 	if (TileX(tile_start) == TileX(tile_end)) {
314 		direction = AXIS_Y;
315 	} else if (TileY(tile_start) == TileY(tile_end)) {
316 		direction = AXIS_X;
317 	} else {
318 		return_cmd_error(STR_ERROR_START_AND_END_MUST_BE_IN);
319 	}
320 
321 	if (tile_end < tile_start) Swap(tile_start, tile_end);
322 
323 	uint bridge_len = GetTunnelBridgeLength(tile_start, tile_end);
324 	if (transport_type != TRANSPORT_WATER) {
325 		/* set and test bridge length, availability */
326 		CommandCost ret = CheckBridgeAvailability(bridge_type, bridge_len, flags);
327 		if (ret.Failed()) return ret;
328 	} else {
329 		if (bridge_len > _settings_game.construction.max_bridge_length) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
330 	}
331 	bridge_len += 2; // begin and end tiles/ramps
332 
333 	int z_start;
334 	int z_end;
335 	Slope tileh_start = GetTileSlope(tile_start, &z_start);
336 	Slope tileh_end = GetTileSlope(tile_end, &z_end);
337 	bool pbs_reservation = false;
338 
339 	CommandCost terraform_cost_north = CheckBridgeSlope(BRIDGE_PIECE_NORTH, direction, &tileh_start, &z_start);
340 	CommandCost terraform_cost_south = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, direction, &tileh_end,   &z_end);
341 
342 	/* Aqueducts can't be built of flat land. */
343 	if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
344 	if (z_start != z_end) return_cmd_error(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT);
345 
346 	CommandCost cost(EXPENSES_CONSTRUCTION);
347 	Owner owner;
348 	bool is_new_owner;
349 	RoadType road_rt = INVALID_ROADTYPE;
350 	RoadType tram_rt = INVALID_ROADTYPE;
351 	if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
352 			GetOtherBridgeEnd(tile_start) == tile_end &&
353 			GetTunnelBridgeTransportType(tile_start) == transport_type) {
354 		/* Replace a current bridge. */
355 
356 		switch (transport_type) {
357 			case TRANSPORT_RAIL:
358 				/* Keep the reservation, the path stays valid. */
359 				pbs_reservation = HasTunnelBridgeReservation(tile_start);
360 				break;
361 
362 			case TRANSPORT_ROAD:
363 				/* Do not remove road types when upgrading a bridge */
364 				road_rt = GetRoadTypeRoad(tile_start);
365 				tram_rt = GetRoadTypeTram(tile_start);
366 				break;
367 
368 			default: break;
369 		}
370 
371 		/* If this is a railway bridge, make sure the railtypes match. */
372 		if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
373 			return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
374 		}
375 
376 		/* If this is a road bridge, make sure the roadtype matches. */
377 		if (transport_type == TRANSPORT_ROAD) {
378 			RoadType existing_rt = RoadTypeIsRoad(roadtype) ? road_rt : tram_rt;
379 			if (existing_rt != roadtype && existing_rt != INVALID_ROADTYPE) {
380 				return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
381 			}
382 		}
383 
384 		/* Do not replace town bridges with lower speed bridges, unless in scenario editor. */
385 		if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
386 				GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed &&
387 				_game_mode != GM_EDITOR) {
388 			Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
389 
390 			if (t == nullptr) {
391 				return CMD_ERROR;
392 			} else {
393 				SetDParam(0, t->index);
394 				return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
395 			}
396 		}
397 
398 		/* Do not replace the bridge with the same bridge type. */
399 		if (!(flags & DC_QUERY_COST) && (bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || road_rt == roadtype || tram_rt == roadtype)) {
400 			return_cmd_error(STR_ERROR_ALREADY_BUILT);
401 		}
402 
403 		/* Do not allow replacing another company's bridges. */
404 		if (!IsTileOwner(tile_start, company) && !IsTileOwner(tile_start, OWNER_TOWN) && !IsTileOwner(tile_start, OWNER_NONE)) {
405 			return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
406 		}
407 
408 		/* The cost of clearing the current bridge. */
409 		cost.AddCost(bridge_len * TunnelBridgeClearCost(tile_start, PR_CLEAR_BRIDGE));
410 		owner = GetTileOwner(tile_start);
411 
412 		/* If bridge belonged to bankrupt company, it has a new owner now */
413 		is_new_owner = (owner == OWNER_NONE);
414 		if (is_new_owner) owner = company;
415 	} else {
416 		/* Build a new bridge. */
417 
418 		bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
419 
420 		/* Try and clear the start landscape */
421 		CommandCost ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
422 		if (ret.Failed()) return ret;
423 		cost = ret;
424 
425 		if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
426 		cost.AddCost(terraform_cost_north);
427 
428 		/* Try and clear the end landscape */
429 		ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
430 		if (ret.Failed()) return ret;
431 		cost.AddCost(ret);
432 
433 		/* false - end tile slope check */
434 		if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
435 		cost.AddCost(terraform_cost_south);
436 
437 		const TileIndex heads[] = {tile_start, tile_end};
438 		for (int i = 0; i < 2; i++) {
439 			if (IsBridgeAbove(heads[i])) {
440 				TileIndex north_head = GetNorthernBridgeEnd(heads[i]);
441 
442 				if (direction == GetBridgeAxis(heads[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
443 
444 				if (z_start + 1 == GetBridgeHeight(north_head)) {
445 					return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
446 				}
447 			}
448 		}
449 
450 		TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
451 		for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
452 			if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN);
453 
454 			if (z_start >= (GetTileZ(tile) + _settings_game.construction.max_bridge_height)) {
455 				/*
456 				 * Disallow too high bridges.
457 				 * Properly rendering a map where very high bridges (might) exist is expensive.
458 				 * See http://www.tt-forums.net/viewtopic.php?f=33&t=40844&start=980#p1131762
459 				 * for a detailed discussion. z_start here is one heightlevel below the bridge level.
460 				 */
461 				return_cmd_error(STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN);
462 			}
463 
464 			if (IsBridgeAbove(tile)) {
465 				/* Disallow crossing bridges for the time being */
466 				return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
467 			}
468 
469 			switch (GetTileType(tile)) {
470 				case MP_WATER:
471 					if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
472 					break;
473 
474 				case MP_RAILWAY:
475 					if (!IsPlainRail(tile)) goto not_valid_below;
476 					break;
477 
478 				case MP_ROAD:
479 					if (IsRoadDepot(tile)) goto not_valid_below;
480 					break;
481 
482 				case MP_TUNNELBRIDGE:
483 					if (IsTunnel(tile)) break;
484 					if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below;
485 					if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
486 					break;
487 
488 				case MP_OBJECT: {
489 					const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
490 					if ((spec->flags & OBJECT_FLAG_ALLOW_UNDER_BRIDGE) == 0) goto not_valid_below;
491 					if (GetTileMaxZ(tile) + spec->height > z_start) goto not_valid_below;
492 					break;
493 				}
494 
495 				case MP_CLEAR:
496 					break;
497 
498 				default:
499 	not_valid_below:;
500 					/* try and clear the middle landscape */
501 					ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
502 					if (ret.Failed()) return ret;
503 					cost.AddCost(ret);
504 					break;
505 			}
506 
507 			if (flags & DC_EXEC) {
508 				/* We do this here because when replacing a bridge with another
509 				 * type calling SetBridgeMiddle isn't needed. After all, the
510 				 * tile already has the has_bridge_above bits set. */
511 				SetBridgeMiddle(tile, direction);
512 			}
513 		}
514 
515 		owner = company;
516 		is_new_owner = true;
517 	}
518 
519 	bool hasroad = road_rt != INVALID_ROADTYPE;
520 	bool hastram = tram_rt != INVALID_ROADTYPE;
521 	if (transport_type == TRANSPORT_ROAD) {
522 		if (RoadTypeIsRoad(roadtype)) road_rt = roadtype;
523 		if (RoadTypeIsTram(roadtype)) tram_rt = roadtype;
524 	}
525 
526 	/* do the drill? */
527 	if (flags & DC_EXEC) {
528 		DiagDirection dir = AxisToDiagDir(direction);
529 
530 		Company *c = Company::GetIfValid(company);
531 		switch (transport_type) {
532 			case TRANSPORT_RAIL:
533 				/* Add to company infrastructure count if required. */
534 				if (is_new_owner && c != nullptr) c->infrastructure.rail[railtype] += bridge_len * TUNNELBRIDGE_TRACKBIT_FACTOR;
535 				MakeRailBridgeRamp(tile_start, owner, bridge_type, dir,                 railtype);
536 				MakeRailBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), railtype);
537 				SetTunnelBridgeReservation(tile_start, pbs_reservation);
538 				SetTunnelBridgeReservation(tile_end,   pbs_reservation);
539 				break;
540 
541 			case TRANSPORT_ROAD: {
542 				if (is_new_owner) {
543 					/* Also give unowned present roadtypes to new owner */
544 					if (hasroad && GetRoadOwner(tile_start, RTT_ROAD) == OWNER_NONE) hasroad = false;
545 					if (hastram && GetRoadOwner(tile_start, RTT_TRAM) == OWNER_NONE) hastram = false;
546 				}
547 				if (c != nullptr) {
548 					/* Add all new road types to the company infrastructure counter. */
549 					if (!hasroad && road_rt != INVALID_ROADTYPE) {
550 						/* A full diagonal road tile has two road bits. */
551 						c->infrastructure.road[road_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
552 					}
553 					if (!hastram && tram_rt != INVALID_ROADTYPE) {
554 						/* A full diagonal road tile has two road bits. */
555 						c->infrastructure.road[tram_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
556 					}
557 				}
558 				Owner owner_road = hasroad ? GetRoadOwner(tile_start, RTT_ROAD) : company;
559 				Owner owner_tram = hastram ? GetRoadOwner(tile_start, RTT_TRAM) : company;
560 				MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, road_rt, tram_rt);
561 				MakeRoadBridgeRamp(tile_end,   owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), road_rt, tram_rt);
562 				break;
563 			}
564 
565 			case TRANSPORT_WATER:
566 				if (is_new_owner && c != nullptr) c->infrastructure.water += bridge_len * TUNNELBRIDGE_TRACKBIT_FACTOR;
567 				MakeAqueductBridgeRamp(tile_start, owner, dir);
568 				MakeAqueductBridgeRamp(tile_end,   owner, ReverseDiagDir(dir));
569 				CheckForDockingTile(tile_start);
570 				CheckForDockingTile(tile_end);
571 				break;
572 
573 			default:
574 				NOT_REACHED();
575 		}
576 
577 		/* Mark all tiles dirty */
578 		MarkBridgeDirty(tile_start, tile_end, AxisToDiagDir(direction), z_start);
579 		DirtyCompanyInfrastructureWindows(company);
580 	}
581 
582 	if ((flags & DC_EXEC) && transport_type == TRANSPORT_RAIL) {
583 		Track track = AxisToTrack(direction);
584 		AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, company);
585 		YapfNotifyTrackLayoutChange(tile_start, track);
586 	}
587 
588 	/* Human players that build bridges get a selection to choose from (DC_QUERY_COST)
589 	 * It's unnecessary to execute this command every time for every bridge.
590 	 * So it is done only for humans and cost is computed in bridge_gui.cpp.
591 	 * For (non-spectated) AI, Towns this has to be of course calculated. */
592 	Company *c = Company::GetIfValid(company);
593 	if (!(flags & DC_QUERY_COST) || (c != nullptr && c->is_ai && company != _local_company)) {
594 		switch (transport_type) {
595 			case TRANSPORT_ROAD:
596 				if (road_rt != INVALID_ROADTYPE) {
597 					cost.AddCost(bridge_len * 2 * RoadBuildCost(road_rt));
598 				}
599 				if (tram_rt != INVALID_ROADTYPE) {
600 					cost.AddCost(bridge_len * 2 * RoadBuildCost(tram_rt));
601 				}
602 				break;
603 
604 			case TRANSPORT_RAIL: cost.AddCost(bridge_len * RailBuildCost(railtype)); break;
605 			default: break;
606 		}
607 
608 		if (c != nullptr) bridge_len = CalcBridgeLenCostFactor(bridge_len);
609 
610 		if (transport_type != TRANSPORT_WATER) {
611 			cost.AddCost((int64)bridge_len * _price[PR_BUILD_BRIDGE] * GetBridgeSpec(bridge_type)->price >> 8);
612 		} else {
613 			/* Aqueducts use a separate base cost. */
614 			cost.AddCost((int64)bridge_len * _price[PR_BUILD_AQUEDUCT]);
615 		}
616 
617 	}
618 
619 	return cost;
620 }
621 
622 
623 /**
624  * Build Tunnel.
625  * @param start_tile start tile of tunnel
626  * @param flags type of operation
627  * @param p1 bit 0-5 railtype or roadtype
628  *           bit 8-9 transport type
629  * @param p2 unused
630  * @param text unused
631  * @return the cost of this operation or an error
632  */
CmdBuildTunnel(TileIndex start_tile,DoCommandFlag flags,uint32 p1,uint32 p2,const std::string & text)633 CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
634 {
635 	CompanyID company = _current_company;
636 
637 	TransportType transport_type = Extract<TransportType, 8, 2>(p1);
638 	RailType railtype = INVALID_RAILTYPE;
639 	RoadType roadtype = INVALID_ROADTYPE;
640 	_build_tunnel_endtile = 0;
641 	switch (transport_type) {
642 		case TRANSPORT_RAIL:
643 			railtype = Extract<RailType, 0, 6>(p1);
644 			if (!ValParamRailtype(railtype)) return CMD_ERROR;
645 			break;
646 
647 		case TRANSPORT_ROAD:
648 			roadtype = Extract<RoadType, 0, 6>(p1);
649 			if (!ValParamRoadType(roadtype)) return CMD_ERROR;
650 			break;
651 
652 		default: return CMD_ERROR;
653 	}
654 
655 	if (company == OWNER_DEITY) {
656 		if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
657 		const Town *town = CalcClosestTownFromTile(start_tile);
658 
659 		company = OWNER_TOWN;
660 
661 		/* If we are not within a town, we are not owned by the town */
662 		if (town == nullptr || DistanceSquare(start_tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
663 			company = OWNER_NONE;
664 		}
665 	}
666 
667 	int start_z;
668 	int end_z;
669 	Slope start_tileh = GetTileSlope(start_tile, &start_z);
670 	DiagDirection direction = GetInclinedSlopeDirection(start_tileh);
671 	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL);
672 
673 	if (HasTileWaterGround(start_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
674 
675 	CommandCost ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
676 	if (ret.Failed()) return ret;
677 
678 	/* XXX - do NOT change 'ret' in the loop, as it is used as the price
679 	 * for the clearing of the entrance of the tunnel. Assigning it to
680 	 * cost before the loop will yield different costs depending on start-
681 	 * position, because of increased-cost-by-length: 'cost += cost >> 3' */
682 
683 	TileIndexDiff delta = TileOffsByDiagDir(direction);
684 	DiagDirection tunnel_in_way_dir;
685 	if (DiagDirToAxis(direction) == AXIS_Y) {
686 		tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
687 	} else {
688 		tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
689 	}
690 
691 	TileIndex end_tile = start_tile;
692 
693 	/* Tile shift coefficient. Will decrease for very long tunnels to avoid exponential growth of price*/
694 	int tiles_coef = 3;
695 	/* Number of tiles from start of tunnel */
696 	int tiles = 0;
697 	/* Number of tiles at which the cost increase coefficient per tile is halved */
698 	int tiles_bump = 25;
699 
700 	CommandCost cost(EXPENSES_CONSTRUCTION);
701 	Slope end_tileh;
702 	for (;;) {
703 		end_tile += delta;
704 		if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER);
705 		end_tileh = GetTileSlope(end_tile, &end_z);
706 
707 		if (start_z == end_z) break;
708 
709 		if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
710 			return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY);
711 		}
712 
713 		tiles++;
714 		if (tiles == tiles_bump) {
715 			tiles_coef++;
716 			tiles_bump *= 2;
717 		}
718 
719 		cost.AddCost(_price[PR_BUILD_TUNNEL]);
720 		cost.AddCost(cost.GetCost() >> tiles_coef); // add a multiplier for longer tunnels
721 	}
722 
723 	/* Add the cost of the entrance */
724 	cost.AddCost(_price[PR_BUILD_TUNNEL]);
725 	cost.AddCost(ret);
726 
727 	/* if the command fails from here on we want the end tile to be highlighted */
728 	_build_tunnel_endtile = end_tile;
729 
730 	if (tiles > _settings_game.construction.max_tunnel_length) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG);
731 
732 	if (HasTileWaterGround(end_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
733 
734 	/* Clear the tile in any case */
735 	ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
736 	if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
737 	cost.AddCost(ret);
738 
739 	/* slope of end tile must be complementary to the slope of the start tile */
740 	if (end_tileh != ComplementSlope(start_tileh)) {
741 		/* Mark the tile as already cleared for the terraform command.
742 		 * Do this for all tiles (like trees), not only objects. */
743 		ClearedObjectArea *coa = FindClearedObject(end_tile);
744 		if (coa == nullptr) {
745 			coa = &_cleared_object_areas.emplace_back(ClearedObjectArea{ end_tile, TileArea(end_tile, 1, 1) });
746 		}
747 
748 		/* Hide the tile from the terraforming command */
749 		TileIndex old_first_tile = coa->first_tile;
750 		coa->first_tile = INVALID_TILE;
751 
752 		/* CMD_TERRAFORM_LAND may append further items to _cleared_object_areas,
753 		 * however it will never erase or re-order existing items.
754 		 * _cleared_object_areas is a value-type self-resizing vector, therefore appending items
755 		 * may result in a backing-store re-allocation, which would invalidate the coa pointer.
756 		 * The index of the coa pointer into the _cleared_object_areas vector remains valid,
757 		 * and can be used safely after the CMD_TERRAFORM_LAND operation.
758 		 * Deliberately clear the coa pointer to avoid leaving dangling pointers which could
759 		 * inadvertently be dereferenced.
760 		 */
761 		ClearedObjectArea *begin = _cleared_object_areas.data();
762 		assert(coa >= begin && coa < begin + _cleared_object_areas.size());
763 		size_t coa_index = coa - begin;
764 		assert(coa_index < UINT_MAX); // more than 2**32 cleared areas would be a bug in itself
765 		coa = nullptr;
766 
767 		ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND);
768 		_cleared_object_areas[(uint)coa_index].first_tile = old_first_tile;
769 		if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
770 		cost.AddCost(ret);
771 	}
772 	cost.AddCost(_price[PR_BUILD_TUNNEL]);
773 
774 	/* Pay for the rail/road in the tunnel including entrances */
775 	switch (transport_type) {
776 		case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * RoadBuildCost(roadtype) * 2); break;
777 		case TRANSPORT_RAIL: cost.AddCost((tiles + 2) * RailBuildCost(railtype)); break;
778 		default: NOT_REACHED();
779 	}
780 
781 	if (flags & DC_EXEC) {
782 		Company *c = Company::GetIfValid(company);
783 		uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
784 		if (transport_type == TRANSPORT_RAIL) {
785 			if (c != nullptr) c->infrastructure.rail[railtype] += num_pieces;
786 			MakeRailTunnel(start_tile, company, direction,                 railtype);
787 			MakeRailTunnel(end_tile,   company, ReverseDiagDir(direction), railtype);
788 			AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company);
789 			YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
790 		} else {
791 			if (c != nullptr) c->infrastructure.road[roadtype] += num_pieces * 2; // A full diagonal road has two road bits.
792 			RoadType road_rt = RoadTypeIsRoad(roadtype) ? roadtype : INVALID_ROADTYPE;
793 			RoadType tram_rt = RoadTypeIsTram(roadtype) ? roadtype : INVALID_ROADTYPE;
794 			MakeRoadTunnel(start_tile, company, direction,                 road_rt, tram_rt);
795 			MakeRoadTunnel(end_tile,   company, ReverseDiagDir(direction), road_rt, tram_rt);
796 		}
797 		DirtyCompanyInfrastructureWindows(company);
798 	}
799 
800 	return cost;
801 }
802 
803 
804 /**
805  * Are we allowed to remove the tunnel or bridge at \a tile?
806  * @param tile End point of the tunnel or bridge.
807  * @return A succeeded command if the tunnel or bridge may be removed, a failed command otherwise.
808  */
CheckAllowRemoveTunnelBridge(TileIndex tile)809 static inline CommandCost CheckAllowRemoveTunnelBridge(TileIndex tile)
810 {
811 	/* Floods can remove anything as well as the scenario editor */
812 	if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return CommandCost();
813 
814 	switch (GetTunnelBridgeTransportType(tile)) {
815 		case TRANSPORT_ROAD: {
816 			RoadType road_rt = GetRoadTypeRoad(tile);
817 			RoadType tram_rt = GetRoadTypeTram(tile);
818 			Owner road_owner = _current_company;
819 			Owner tram_owner = _current_company;
820 
821 			if (road_rt != INVALID_ROADTYPE) road_owner = GetRoadOwner(tile, RTT_ROAD);
822 			if (tram_rt != INVALID_ROADTYPE) tram_owner = GetRoadOwner(tile, RTT_TRAM);
823 
824 			/* We can remove unowned road and if the town allows it */
825 			if (road_owner == OWNER_TOWN && _current_company != OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) {
826 				/* Town does not allow */
827 				return CheckTileOwnership(tile);
828 			}
829 			if (road_owner == OWNER_NONE || road_owner == OWNER_TOWN) road_owner = _current_company;
830 			if (tram_owner == OWNER_NONE) tram_owner = _current_company;
831 
832 			CommandCost ret = CheckOwnership(road_owner, tile);
833 			if (ret.Succeeded()) ret = CheckOwnership(tram_owner, tile);
834 			return ret;
835 		}
836 
837 		case TRANSPORT_RAIL:
838 			return CheckOwnership(GetTileOwner(tile));
839 
840 		case TRANSPORT_WATER: {
841 			/* Always allow to remove aqueducts without owner. */
842 			Owner aqueduct_owner = GetTileOwner(tile);
843 			if (aqueduct_owner == OWNER_NONE) aqueduct_owner = _current_company;
844 			return CheckOwnership(aqueduct_owner);
845 		}
846 
847 		default: NOT_REACHED();
848 	}
849 }
850 
851 /**
852  * Remove a tunnel from the game, update town rating, etc.
853  * @param tile Tile containing one of the endpoints of the tunnel.
854  * @param flags Command flags.
855  * @return Succeeded or failed command.
856  */
DoClearTunnel(TileIndex tile,DoCommandFlag flags)857 static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
858 {
859 	CommandCost ret = CheckAllowRemoveTunnelBridge(tile);
860 	if (ret.Failed()) return ret;
861 
862 	TileIndex endtile = GetOtherTunnelEnd(tile);
863 
864 	ret = TunnelBridgeIsFree(tile, endtile);
865 	if (ret.Failed()) return ret;
866 
867 	_build_tunnel_endtile = endtile;
868 
869 	Town *t = nullptr;
870 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
871 		t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
872 
873 		/* Check if you are allowed to remove the tunnel owned by a town
874 		 * Removal depends on difficulty settings */
875 		CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
876 		if (ret.Failed()) return ret;
877 	}
878 
879 	/* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
880 	 * you have a "Poor" (0) town rating */
881 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
882 		ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
883 	}
884 
885 	Money base_cost = TunnelBridgeClearCost(tile, PR_CLEAR_TUNNEL);
886 	uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
887 
888 	if (flags & DC_EXEC) {
889 		if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
890 			/* We first need to request values before calling DoClearSquare */
891 			DiagDirection dir = GetTunnelBridgeDirection(tile);
892 			Track track = DiagDirToDiagTrack(dir);
893 			Owner owner = GetTileOwner(tile);
894 
895 			Train *v = nullptr;
896 			if (HasTunnelBridgeReservation(tile)) {
897 				v = GetTrainForReservation(tile, track);
898 				if (v != nullptr) FreeTrainTrackReservation(v);
899 			}
900 
901 			if (Company::IsValidID(owner)) {
902 				Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
903 				DirtyCompanyInfrastructureWindows(owner);
904 			}
905 
906 			DoClearSquare(tile);
907 			DoClearSquare(endtile);
908 
909 			/* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
910 			AddSideToSignalBuffer(tile,    ReverseDiagDir(dir), owner);
911 			AddSideToSignalBuffer(endtile, dir,                 owner);
912 
913 			YapfNotifyTrackLayoutChange(tile,    track);
914 			YapfNotifyTrackLayoutChange(endtile, track);
915 
916 			if (v != nullptr) TryPathReserve(v);
917 		} else {
918 			/* A full diagonal road tile has two road bits. */
919 			UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
920 			UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
921 
922 			DoClearSquare(tile);
923 			DoClearSquare(endtile);
924 		}
925 	}
926 
927 	return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
928 }
929 
930 
931 /**
932  * Remove a bridge from the game, update town rating, etc.
933  * @param tile Tile containing one of the endpoints of the bridge.
934  * @param flags Command flags.
935  * @return Succeeded or failed command.
936  */
DoClearBridge(TileIndex tile,DoCommandFlag flags)937 static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
938 {
939 	CommandCost ret = CheckAllowRemoveTunnelBridge(tile);
940 	if (ret.Failed()) return ret;
941 
942 	TileIndex endtile = GetOtherBridgeEnd(tile);
943 
944 	ret = TunnelBridgeIsFree(tile, endtile);
945 	if (ret.Failed()) return ret;
946 
947 	DiagDirection direction = GetTunnelBridgeDirection(tile);
948 	TileIndexDiff delta = TileOffsByDiagDir(direction);
949 
950 	Town *t = nullptr;
951 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
952 		t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
953 
954 		/* Check if you are allowed to remove the bridge owned by a town
955 		 * Removal depends on difficulty settings */
956 		CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
957 		if (ret.Failed()) return ret;
958 	}
959 
960 	/* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
961 	 * you have a "Poor" (0) town rating */
962 	if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
963 		ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
964 	}
965 
966 	Money base_cost = TunnelBridgeClearCost(tile, PR_CLEAR_BRIDGE);
967 	uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
968 
969 	if (flags & DC_EXEC) {
970 		/* read this value before actual removal of bridge */
971 		bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
972 		Owner owner = GetTileOwner(tile);
973 		int height = GetBridgeHeight(tile);
974 		Train *v = nullptr;
975 
976 		if (rail && HasTunnelBridgeReservation(tile)) {
977 			v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
978 			if (v != nullptr) FreeTrainTrackReservation(v);
979 		}
980 
981 		bool removetile = false;
982 		bool removeendtile = false;
983 
984 		/* Update company infrastructure counts. */
985 		if (rail) {
986 			if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
987 		} else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) {
988 			/* A full diagonal road tile has two road bits. */
989 			UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
990 			UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
991 		} else { // Aqueduct
992 			if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.water -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
993 			removetile    = IsDockingTile(tile);
994 			removeendtile = IsDockingTile(endtile);
995 		}
996 		DirtyCompanyInfrastructureWindows(owner);
997 
998 		DoClearSquare(tile);
999 		DoClearSquare(endtile);
1000 
1001 		if (removetile)    RemoveDockingTile(tile);
1002 		if (removeendtile) RemoveDockingTile(endtile);
1003 		for (TileIndex c = tile + delta; c != endtile; c += delta) {
1004 			/* do not let trees appear from 'nowhere' after removing bridge */
1005 			if (IsNormalRoadTile(c) && GetRoadside(c) == ROADSIDE_TREES) {
1006 				int minz = GetTileMaxZ(c) + 3;
1007 				if (height < minz) SetRoadside(c, ROADSIDE_PAVED);
1008 			}
1009 			ClearBridgeMiddle(c);
1010 			MarkTileDirtyByTile(c, height - TileHeight(c));
1011 		}
1012 
1013 		if (rail) {
1014 			/* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
1015 			AddSideToSignalBuffer(tile,    ReverseDiagDir(direction), owner);
1016 			AddSideToSignalBuffer(endtile, direction,                 owner);
1017 
1018 			Track track = DiagDirToDiagTrack(direction);
1019 			YapfNotifyTrackLayoutChange(tile,    track);
1020 			YapfNotifyTrackLayoutChange(endtile, track);
1021 
1022 			if (v != nullptr) TryPathReserve(v, true);
1023 		}
1024 	}
1025 
1026 	return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
1027 }
1028 
1029 /**
1030  * Remove a tunnel or a bridge from the game.
1031  * @param tile Tile containing one of the endpoints.
1032  * @param flags Command flags.
1033  * @return Succeeded or failed command.
1034  */
ClearTile_TunnelBridge(TileIndex tile,DoCommandFlag flags)1035 static CommandCost ClearTile_TunnelBridge(TileIndex tile, DoCommandFlag flags)
1036 {
1037 	if (IsTunnel(tile)) {
1038 		if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST);
1039 		return DoClearTunnel(tile, flags);
1040 	} else { // IsBridge(tile)
1041 		if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1042 		return DoClearBridge(tile, flags);
1043 	}
1044 }
1045 
1046 /**
1047  * Draw a single pillar sprite.
1048  * @param psid      Pillarsprite
1049  * @param x         Pillar X
1050  * @param y         Pillar Y
1051  * @param z         Pillar Z
1052  * @param w         Bounding box size in X direction
1053  * @param h         Bounding box size in Y direction
1054  * @param subsprite Optional subsprite for drawing halfpillars
1055  */
DrawPillar(const PalSpriteID * psid,int x,int y,int z,int w,int h,const SubSprite * subsprite)1056 static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
1057 {
1058 	static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START; ///< Start offset of pillar wrt. bridge (downwards)
1059 	AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, w, h, BB_HEIGHT_UNDER_BRIDGE - PILLAR_Z_OFFSET, z, IsTransparencySet(TO_BRIDGES), 0, 0, -PILLAR_Z_OFFSET, subsprite);
1060 }
1061 
1062 /**
1063  * Draw two bridge pillars (north and south).
1064  * @param z_bottom Bottom Z
1065  * @param z_top    Top Z
1066  * @param psid     Pillarsprite
1067  * @param x        Pillar X
1068  * @param y        Pillar Y
1069  * @param w        Bounding box size in X direction
1070  * @param h        Bounding box size in Y direction
1071  * @return Reached Z at the bottom
1072  */
DrawPillarColumn(int z_bottom,int z_top,const PalSpriteID * psid,int x,int y,int w,int h)1073 static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, int x, int y, int w, int h)
1074 {
1075 	int cur_z;
1076 	for (cur_z = z_top; cur_z >= z_bottom; cur_z -= TILE_HEIGHT) {
1077 		DrawPillar(psid, x, y, cur_z, w, h, nullptr);
1078 	}
1079 	return cur_z;
1080 }
1081 
1082 /**
1083  * Draws the pillars under high bridges.
1084  *
1085  * @param psid Image and palette of a bridge pillar.
1086  * @param ti #TileInfo of current bridge-middle-tile.
1087  * @param axis Orientation of bridge.
1088  * @param drawfarpillar Whether to draw the pillar at the back
1089  * @param x Sprite X position of front pillar.
1090  * @param y Sprite Y position of front pillar.
1091  * @param z_bridge Absolute height of bridge bottom.
1092  */
DrawBridgePillars(const PalSpriteID * psid,const TileInfo * ti,Axis axis,bool drawfarpillar,int x,int y,int z_bridge)1093 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
1094 {
1095 	static const int bounding_box_size[2]  = {16, 2}; ///< bounding box size of pillars along bridge direction
1096 	static const int back_pillar_offset[2] = { 0, 9}; ///< sprite position offset of back facing pillar
1097 
1098 	static const int INF = 1000; ///< big number compared to sprite size
1099 	static const SubSprite half_pillar_sub_sprite[2][2] = {
1100 		{ {  -14, -INF, INF, INF }, { -INF, -INF, -15, INF } }, // X axis, north and south
1101 		{ { -INF, -INF,  15, INF }, {   16, -INF, INF, INF } }, // Y axis, north and south
1102 	};
1103 
1104 	if (psid->sprite == 0) return;
1105 
1106 	/* Determine ground height under pillars */
1107 	DiagDirection south_dir = AxisToDiagDir(axis);
1108 	int z_front_north = ti->z;
1109 	int z_back_north = ti->z;
1110 	int z_front_south = ti->z;
1111 	int z_back_south = ti->z;
1112 	GetSlopePixelZOnEdge(ti->tileh, south_dir, &z_front_south, &z_back_south);
1113 	GetSlopePixelZOnEdge(ti->tileh, ReverseDiagDir(south_dir), &z_front_north, &z_back_north);
1114 
1115 	/* Shared height of pillars */
1116 	int z_front = std::max(z_front_north, z_front_south);
1117 	int z_back = std::max(z_back_north, z_back_south);
1118 
1119 	/* x and y size of bounding-box of pillars */
1120 	int w = bounding_box_size[axis];
1121 	int h = bounding_box_size[OtherAxis(axis)];
1122 	/* sprite position of back facing pillar */
1123 	int x_back = x - back_pillar_offset[axis];
1124 	int y_back = y - back_pillar_offset[OtherAxis(axis)];
1125 
1126 	/* Draw front pillars */
1127 	int bottom_z = DrawPillarColumn(z_front, z_bridge, psid, x, y, w, h);
1128 	if (z_front_north < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1129 	if (z_front_south < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1130 
1131 	/* Draw back pillars, skip top two parts, which are hidden by the bridge */
1132 	int z_bridge_back = z_bridge - 2 * (int)TILE_HEIGHT;
1133 	if (drawfarpillar && (z_back_north <= z_bridge_back || z_back_south <= z_bridge_back)) {
1134 		bottom_z = DrawPillarColumn(z_back, z_bridge_back, psid, x_back, y_back, w, h);
1135 		if (z_back_north < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1136 		if (z_back_south < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1137 	}
1138 }
1139 
1140 /**
1141  * Retrieve the sprites required for catenary on a road/tram bridge.
1142  * @param rti              RoadTypeInfo for the road or tram type to get catenary for
1143  * @param head_tile        Bridge head tile with roadtype information
1144  * @param offset           Sprite offset identifying flat to sloped bridge tiles
1145  * @param head             Are we drawing bridge head?
1146  * @param[out] spr_back    Back catenary sprite to use
1147  * @param[out] spr_front   Front catenary sprite to use
1148  */
GetBridgeRoadCatenary(const RoadTypeInfo * rti,TileIndex head_tile,int offset,bool head,SpriteID & spr_back,SpriteID & spr_front)1149 static void GetBridgeRoadCatenary(const RoadTypeInfo *rti, TileIndex head_tile, int offset, bool head, SpriteID &spr_back, SpriteID &spr_front)
1150 {
1151 	static const SpriteID back_offsets[6]  = { 95,  96,  99, 102, 100, 101 };
1152 	static const SpriteID front_offsets[6] = { 97,  98, 103, 106, 104, 105 };
1153 
1154 	/* Simplified from DrawRoadTypeCatenary() to remove all the special cases required for regular ground road */
1155 	spr_back = GetCustomRoadSprite(rti, head_tile, ROTSG_CATENARY_BACK, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1156 	spr_front = GetCustomRoadSprite(rti, head_tile, ROTSG_CATENARY_FRONT, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1157 	if (spr_back == 0 && spr_front == 0) {
1158 		spr_back = SPR_TRAMWAY_BASE + back_offsets[offset];
1159 		spr_front = SPR_TRAMWAY_BASE + front_offsets[offset];
1160 	} else {
1161 		if (spr_back != 0) spr_back += 23 + offset;
1162 		if (spr_front != 0) spr_front += 23 + offset;
1163 	}
1164 }
1165 
1166 /**
1167  * Draws the road and trambits over an already drawn (lower end) of a bridge.
1168  * @param head_tile    bridge head tile with roadtype information
1169  * @param x            the x of the bridge
1170  * @param y            the y of the bridge
1171  * @param z            the z of the bridge
1172  * @param offset       sprite offset identifying flat to sloped bridge tiles
1173  * @param head         are we drawing bridge head?
1174  */
DrawBridgeRoadBits(TileIndex head_tile,int x,int y,int z,int offset,bool head)1175 static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int offset, bool head)
1176 {
1177 	RoadType road_rt = GetRoadTypeRoad(head_tile);
1178 	RoadType tram_rt = GetRoadTypeTram(head_tile);
1179 	const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1180 	const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1181 
1182 	SpriteID seq_back[4] = { 0 };
1183 	bool trans_back[4] = { false };
1184 	SpriteID seq_front[4] = { 0 };
1185 	bool trans_front[4] = { false };
1186 
1187 	static const SpriteID overlay_offsets[6] = {   0,   1,  11,  12,  13,  14 };
1188 	if (head || !IsInvisibilitySet(TO_BRIDGES)) {
1189 		/* Road underlay takes precedence over tram */
1190 		trans_back[0] = !head && IsTransparencySet(TO_BRIDGES);
1191 		if (road_rti != nullptr) {
1192 			if (road_rti->UsesOverlay()) {
1193 				seq_back[0] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
1194 			}
1195 		} else if (tram_rti != nullptr) {
1196 			if (tram_rti->UsesOverlay()) {
1197 				seq_back[0] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
1198 			} else {
1199 				seq_back[0] = SPR_TRAMWAY_BRIDGE + offset;
1200 			}
1201 		}
1202 
1203 		/* Draw road overlay */
1204 		trans_back[1] = !head && IsTransparencySet(TO_BRIDGES);
1205 		if (road_rti != nullptr) {
1206 			if (road_rti->UsesOverlay()) {
1207 				seq_back[1] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1208 				if (seq_back[1] != 0) seq_back[1] += overlay_offsets[offset];
1209 			}
1210 		}
1211 
1212 		/* Draw tram overlay */
1213 		trans_back[2] = !head && IsTransparencySet(TO_BRIDGES);
1214 		if (tram_rti != nullptr) {
1215 			if (tram_rti->UsesOverlay()) {
1216 				seq_back[2] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1217 				if (seq_back[2] != 0) seq_back[2] += overlay_offsets[offset];
1218 			} else if (road_rti != nullptr) {
1219 				seq_back[2] = SPR_TRAMWAY_OVERLAY + overlay_offsets[offset];
1220 			}
1221 		}
1222 
1223 		/* Road catenary takes precedence over tram */
1224 		trans_back[3] = IsTransparencySet(TO_CATENARY);
1225 		trans_front[0] = IsTransparencySet(TO_CATENARY);
1226 		if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
1227 			GetBridgeRoadCatenary(road_rti, head_tile, offset, head, seq_back[3], seq_front[0]);
1228 		} else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
1229 			GetBridgeRoadCatenary(tram_rti, head_tile, offset, head, seq_back[3], seq_front[0]);
1230 		}
1231 	}
1232 
1233 	static const uint size_x[6] = {  1, 16, 16,  1, 16,  1 };
1234 	static const uint size_y[6] = { 16,  1,  1, 16,  1, 16 };
1235 	static const uint front_bb_offset_x[6] = { 15,  0,  0, 15,  0, 15 };
1236 	static const uint front_bb_offset_y[6] = {  0, 15, 15,  0, 15,  0 };
1237 
1238 	/* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
1239 	 * The bounding boxes here are the same as for bridge front/roof */
1240 	for (uint i = 0; i < lengthof(seq_back); ++i) {
1241 		if (seq_back[i] != 0) {
1242 			AddSortableSpriteToDraw(seq_back[i], PAL_NONE,
1243 				x, y, size_x[offset], size_y[offset], 0x28, z,
1244 				trans_back[i]);
1245 		}
1246 	}
1247 
1248 	/* Start a new SpriteCombine for the front part */
1249 	EndSpriteCombine();
1250 	StartSpriteCombine();
1251 
1252 	for (uint i = 0; i < lengthof(seq_front); ++i) {
1253 		if (seq_front[i] != 0) {
1254 			AddSortableSpriteToDraw(seq_front[i], PAL_NONE,
1255 				x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
1256 				trans_front[i],
1257 				front_bb_offset_x[offset], front_bb_offset_y[offset]);
1258 		}
1259 	}
1260 }
1261 
1262 /**
1263  * Draws a tunnel of bridge tile.
1264  * For tunnels, this is rather simple, as you only need to draw the entrance.
1265  * Bridges are a bit more complex. base_offset is where the sprite selection comes into play
1266  * and it works a bit like a bitmask.<p> For bridge heads:
1267  * @param ti TileInfo of the structure to draw
1268  * <ul><li>Bit 0: direction</li>
1269  * <li>Bit 1: northern or southern heads</li>
1270  * <li>Bit 2: Set if the bridge head is sloped</li>
1271  * <li>Bit 3 and more: Railtype Specific subset</li>
1272  * </ul>
1273  * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
1274  */
DrawTile_TunnelBridge(TileInfo * ti)1275 static void DrawTile_TunnelBridge(TileInfo *ti)
1276 {
1277 	TransportType transport_type = GetTunnelBridgeTransportType(ti->tile);
1278 	DiagDirection tunnelbridge_direction = GetTunnelBridgeDirection(ti->tile);
1279 
1280 	if (IsTunnel(ti->tile)) {
1281 		/* Front view of tunnel bounding boxes:
1282 		 *
1283 		 *   122223  <- BB_Z_SEPARATOR
1284 		 *   1    3
1285 		 *   1    3                1,3 = empty helper BB
1286 		 *   1    3                  2 = SpriteCombine of tunnel-roof and catenary (tram & elrail)
1287 		 *
1288 		 */
1289 
1290 		static const int _tunnel_BB[4][12] = {
1291 			/*  tunnnel-roof  |  Z-separator  | tram-catenary
1292 			 * w  h  bb_x bb_y| x   y   w   h |bb_x bb_y w h */
1293 			{  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // NE
1294 			{  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // SE
1295 			{  1,  0, -15, -14,  0, 15, 16,  1, 0, 1, 16, 15 }, // SW
1296 			{  0,  1, -14, -15, 15,  0,  1, 16, 1, 0, 15, 16 }, // NW
1297 		};
1298 		const int *BB_data = _tunnel_BB[tunnelbridge_direction];
1299 
1300 		bool catenary = false;
1301 
1302 		SpriteID image;
1303 		SpriteID railtype_overlay = 0;
1304 		if (transport_type == TRANSPORT_RAIL) {
1305 			const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1306 			image = rti->base_sprites.tunnel;
1307 			if (rti->UsesOverlay()) {
1308 				/* Check if the railtype has custom tunnel portals. */
1309 				railtype_overlay = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL_PORTAL);
1310 				if (railtype_overlay != 0) image = SPR_RAILTYPE_TUNNEL_BASE; // Draw blank grass tunnel base.
1311 			}
1312 		} else {
1313 			image = SPR_TUNNEL_ENTRY_REAR_ROAD;
1314 		}
1315 
1316 		if (HasTunnelBridgeSnowOrDesert(ti->tile)) image += railtype_overlay != 0 ? 8 : 32;
1317 
1318 		image += tunnelbridge_direction * 2;
1319 		DrawGroundSprite(image, PAL_NONE);
1320 
1321 		if (transport_type == TRANSPORT_ROAD) {
1322 			RoadType road_rt = GetRoadTypeRoad(ti->tile);
1323 			RoadType tram_rt = GetRoadTypeTram(ti->tile);
1324 			const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1325 			const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1326 			uint sprite_offset = DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? 1 : 0;
1327 
1328 			DrawRoadOverlays(ti, PAL_NONE, road_rti, tram_rti, sprite_offset, sprite_offset);
1329 
1330 			/* Road catenary takes precedence over tram */
1331 			SpriteID catenary_sprite_base = 0;
1332 			if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
1333 				catenary_sprite_base = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_CATENARY_FRONT);
1334 				if (catenary_sprite_base == 0) {
1335 					catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
1336 				} else {
1337 					catenary_sprite_base += 19;
1338 				}
1339 			} else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
1340 				catenary_sprite_base = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_CATENARY_FRONT);
1341 				if (catenary_sprite_base == 0) {
1342 					catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
1343 				} else {
1344 					catenary_sprite_base += 19;
1345 				}
1346 			}
1347 
1348 			if (catenary_sprite_base != 0) {
1349 				catenary = true;
1350 				StartSpriteCombine();
1351 				AddSortableSpriteToDraw(catenary_sprite_base + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
1352 			}
1353 		} else {
1354 			const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1355 			if (rti->UsesOverlay()) {
1356 				SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL);
1357 				if (surface != 0) DrawGroundSprite(surface + tunnelbridge_direction, PAL_NONE);
1358 			}
1359 
1360 			/* PBS debugging, draw reserved tracks darker */
1361 			if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1362 				if (rti->UsesOverlay()) {
1363 					SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1364 					DrawGroundSprite(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH);
1365 				} else {
1366 					DrawGroundSprite(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH);
1367 				}
1368 			}
1369 
1370 			if (HasRailCatenaryDrawn(GetRailType(ti->tile))) {
1371 				/* Maybe draw pylons on the entry side */
1372 				DrawRailCatenary(ti);
1373 
1374 				catenary = true;
1375 				StartSpriteCombine();
1376 				/* Draw wire above the ramp */
1377 				DrawRailCatenaryOnTunnel(ti);
1378 			}
1379 		}
1380 
1381 		if (railtype_overlay != 0 && !catenary) StartSpriteCombine();
1382 
1383 		AddSortableSpriteToDraw(image + 1, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, BB_data[0], BB_data[1], TILE_HEIGHT, ti->z, false, BB_data[2], BB_data[3], BB_Z_SEPARATOR);
1384 		/* Draw railtype tunnel portal overlay if defined. */
1385 		if (railtype_overlay != 0) AddSortableSpriteToDraw(railtype_overlay + tunnelbridge_direction, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, BB_data[0], BB_data[1], TILE_HEIGHT, ti->z, false, BB_data[2], BB_data[3], BB_Z_SEPARATOR);
1386 
1387 		if (catenary || railtype_overlay != 0) EndSpriteCombine();
1388 
1389 		/* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
1390 		AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x,              ti->y,              BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
1391 		AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x + BB_data[4], ti->y + BB_data[5], BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
1392 
1393 		DrawBridgeMiddle(ti);
1394 	} else { // IsBridge(ti->tile)
1395 		const PalSpriteID *psid;
1396 		int base_offset;
1397 		bool ice = HasTunnelBridgeSnowOrDesert(ti->tile);
1398 
1399 		if (transport_type == TRANSPORT_RAIL) {
1400 			base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
1401 			assert(base_offset != 8); // This one is used for roads
1402 		} else {
1403 			base_offset = 8;
1404 		}
1405 
1406 		/* as the lower 3 bits are used for other stuff, make sure they are clear */
1407 		assert( (base_offset & 0x07) == 0x00);
1408 
1409 		DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(tunnelbridge_direction)));
1410 
1411 		/* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
1412 		base_offset += (6 - tunnelbridge_direction) % 4;
1413 
1414 		/* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
1415 		if (transport_type != TRANSPORT_WATER) {
1416 			if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
1417 			psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD)[base_offset];
1418 		} else {
1419 			psid = _aqueduct_sprites + base_offset;
1420 		}
1421 
1422 		if (!ice) {
1423 			TileIndex next = ti->tile + TileOffsByDiagDir(tunnelbridge_direction);
1424 			if (ti->tileh != SLOPE_FLAT && ti->z == 0 && HasTileWaterClass(next) && GetWaterClass(next) == WATER_CLASS_SEA) {
1425 				DrawShoreTile(ti->tileh);
1426 			} else {
1427 				DrawClearLandTile(ti, 3);
1428 			}
1429 		} else {
1430 			DrawGroundSprite(SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
1431 		}
1432 
1433 		/* draw ramp */
1434 
1435 		/* Draw Trambits and PBS Reservation as SpriteCombine */
1436 		if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1437 
1438 		/* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1439 		 * it doesn't disappear behind it
1440 		 */
1441 		/* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1442 		AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
1443 
1444 		if (transport_type == TRANSPORT_ROAD) {
1445 			uint offset = tunnelbridge_direction;
1446 			int z = ti->z;
1447 			if (ti->tileh != SLOPE_FLAT) {
1448 				offset = (offset + 1) & 1;
1449 				z += TILE_HEIGHT;
1450 			} else {
1451 				offset += 2;
1452 			}
1453 
1454 			/* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
1455 			DrawBridgeRoadBits(ti->tile, ti->x, ti->y, z, offset, true);
1456 
1457 			EndSpriteCombine();
1458 		} else if (transport_type == TRANSPORT_RAIL) {
1459 			const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1460 			if (rti->UsesOverlay()) {
1461 				SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE);
1462 				if (surface != 0) {
1463 					if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1464 						AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1465 					} else {
1466 						AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, 16, 16, 8, ti->z);
1467 					}
1468 				}
1469 				/* Don't fallback to non-overlay sprite -- the spec states that
1470 				 * if an overlay is present then the bridge surface must be
1471 				 * present. */
1472 			}
1473 
1474 			/* PBS debugging, draw reserved tracks darker */
1475 			if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1476 				if (rti->UsesOverlay()) {
1477 					SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1478 					if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1479 						AddSortableSpriteToDraw(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1480 					} else {
1481 						AddSortableSpriteToDraw(overlay + RTO_SLOPE_NE + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1482 					}
1483 				} else {
1484 					if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1485 						AddSortableSpriteToDraw(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1486 					} else {
1487 						AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1488 					}
1489 				}
1490 			}
1491 
1492 			EndSpriteCombine();
1493 			if (HasRailCatenaryDrawn(GetRailType(ti->tile))) {
1494 				DrawRailCatenary(ti);
1495 			}
1496 		}
1497 
1498 		DrawBridgeMiddle(ti);
1499 	}
1500 }
1501 
1502 
1503 /**
1504  * Compute bridge piece. Computes the bridge piece to display depending on the position inside the bridge.
1505  * bridges pieces sequence (middle parts).
1506  * Note that it is not covering the bridge heads, which are always referenced by the same sprite table.
1507  * bridge len 1: BRIDGE_PIECE_NORTH
1508  * bridge len 2: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_SOUTH
1509  * bridge len 3: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_MIDDLE_ODD   BRIDGE_PIECE_SOUTH
1510  * bridge len 4: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
1511  * bridge len 5: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_MIDDLE_EVEN  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
1512  * bridge len 6: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
1513  * bridge len 7: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_MIDDLE_ODD   BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
1514  * #0 - always as first, #1 - always as last (if len>1)
1515  * #2,#3 are to pair in order
1516  * for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0)
1517  * @param north Northernmost tile of bridge
1518  * @param south Southernmost tile of bridge
1519  * @return Index of bridge piece
1520  */
CalcBridgePiece(uint north,uint south)1521 static BridgePieces CalcBridgePiece(uint north, uint south)
1522 {
1523 	if (north == 1) {
1524 		return BRIDGE_PIECE_NORTH;
1525 	} else if (south == 1) {
1526 		return BRIDGE_PIECE_SOUTH;
1527 	} else if (north < south) {
1528 		return north & 1 ? BRIDGE_PIECE_INNER_SOUTH : BRIDGE_PIECE_INNER_NORTH;
1529 	} else if (north > south) {
1530 		return south & 1 ? BRIDGE_PIECE_INNER_NORTH : BRIDGE_PIECE_INNER_SOUTH;
1531 	} else {
1532 		return north & 1 ? BRIDGE_PIECE_MIDDLE_EVEN : BRIDGE_PIECE_MIDDLE_ODD;
1533 	}
1534 }
1535 
1536 /**
1537  * Draw the middle bits of a bridge.
1538  * @param ti Tile information of the tile to draw it on.
1539  */
DrawBridgeMiddle(const TileInfo * ti)1540 void DrawBridgeMiddle(const TileInfo *ti)
1541 {
1542 	/* Sectional view of bridge bounding boxes:
1543 	 *
1544 	 *  1           2                                1,2 = SpriteCombine of Bridge front/(back&floor) and RoadCatenary
1545 	 *  1           2                                  3 = empty helper BB
1546 	 *  1     7     2                                4,5 = pillars under higher bridges
1547 	 *  1 6 88888 6 2                                  6 = elrail-pylons
1548 	 *  1 6 88888 6 2                                  7 = elrail-wire
1549 	 *  1 6 88888 6 2  <- TILE_HEIGHT                  8 = rail-vehicle on bridge
1550 	 *  3333333333333  <- BB_Z_SEPARATOR
1551 	 *                 <- unused
1552 	 *    4       5    <- BB_HEIGHT_UNDER_BRIDGE
1553 	 *    4       5
1554 	 *    4       5
1555 	 *
1556 	 */
1557 
1558 	if (!IsBridgeAbove(ti->tile)) return;
1559 
1560 	TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile);
1561 	TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile);
1562 	TransportType transport_type = GetTunnelBridgeTransportType(rampsouth);
1563 
1564 	Axis axis = GetBridgeAxis(ti->tile);
1565 	BridgePieces piece = CalcBridgePiece(
1566 		GetTunnelBridgeLength(ti->tile, rampnorth) + 1,
1567 		GetTunnelBridgeLength(ti->tile, rampsouth) + 1
1568 	);
1569 
1570 	const PalSpriteID *psid;
1571 	bool drawfarpillar;
1572 	if (transport_type != TRANSPORT_WATER) {
1573 		BridgeType type =  GetBridgeType(rampsouth);
1574 		drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
1575 
1576 		uint base_offset;
1577 		if (transport_type == TRANSPORT_RAIL) {
1578 			base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
1579 		} else {
1580 			base_offset = 8;
1581 		}
1582 
1583 		psid = base_offset + GetBridgeSpriteTable(type, piece);
1584 	} else {
1585 		drawfarpillar = true;
1586 		psid = _aqueduct_sprites;
1587 	}
1588 
1589 	if (axis != AXIS_X) psid += 4;
1590 
1591 	int x = ti->x;
1592 	int y = ti->y;
1593 	uint bridge_z = GetBridgePixelHeight(rampsouth);
1594 	int z = bridge_z - BRIDGE_Z_START;
1595 
1596 	/* Add a bounding box that separates the bridge from things below it. */
1597 	AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
1598 
1599 	/* Draw Trambits as SpriteCombine */
1600 	if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1601 
1602 	/* Draw floor and far part of bridge*/
1603 	if (!IsInvisibilitySet(TO_BRIDGES)) {
1604 		if (axis == AXIS_X) {
1605 			AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1606 		} else {
1607 			AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1608 		}
1609 	}
1610 
1611 	psid++;
1612 
1613 	if (transport_type == TRANSPORT_ROAD) {
1614 		/* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
1615 		DrawBridgeRoadBits(rampsouth, x, y, bridge_z, axis ^ 1, false);
1616 	} else if (transport_type == TRANSPORT_RAIL) {
1617 		const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth));
1618 		if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
1619 			SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE);
1620 			if (surface != 0) {
1621 				AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1622 			}
1623 		}
1624 
1625 		if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
1626 			if (rti->UsesOverlay()) {
1627 				SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1628 				AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1629 			} else {
1630 				AddSortableSpriteToDraw(axis == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1631 			}
1632 		}
1633 
1634 		EndSpriteCombine();
1635 
1636 		if (HasRailCatenaryDrawn(GetRailType(rampsouth))) {
1637 			DrawRailCatenaryOnBridge(ti);
1638 		}
1639 	}
1640 
1641 	/* draw roof, the component of the bridge which is logically between the vehicle and the camera */
1642 	if (!IsInvisibilitySet(TO_BRIDGES)) {
1643 		if (axis == AXIS_X) {
1644 			y += 12;
1645 			if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
1646 		} else {
1647 			x += 12;
1648 			if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
1649 		}
1650 	}
1651 
1652 	/* Draw TramFront as SpriteCombine */
1653 	if (transport_type == TRANSPORT_ROAD) EndSpriteCombine();
1654 
1655 	/* Do not draw anything more if bridges are invisible */
1656 	if (IsInvisibilitySet(TO_BRIDGES)) return;
1657 
1658 	psid++;
1659 	DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
1660 }
1661 
1662 
GetSlopePixelZ_TunnelBridge(TileIndex tile,uint x,uint y)1663 static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
1664 {
1665 	int z;
1666 	Slope tileh = GetTilePixelSlope(tile, &z);
1667 
1668 	x &= 0xF;
1669 	y &= 0xF;
1670 
1671 	if (IsTunnel(tile)) {
1672 		uint pos = (DiagDirToAxis(GetTunnelBridgeDirection(tile)) == AXIS_X ? y : x);
1673 
1674 		/* In the tunnel entrance? */
1675 		if (5 <= pos && pos <= 10) return z;
1676 	} else { // IsBridge(tile)
1677 		DiagDirection dir = GetTunnelBridgeDirection(tile);
1678 		uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
1679 
1680 		z += ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh, DiagDirToAxis(dir)), &tileh);
1681 
1682 		/* On the bridge ramp? */
1683 		if (5 <= pos && pos <= 10) {
1684 			int delta;
1685 
1686 			if (tileh != SLOPE_FLAT) return z + TILE_HEIGHT;
1687 
1688 			switch (dir) {
1689 				default: NOT_REACHED();
1690 				case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
1691 				case DIAGDIR_SE: delta = y / 2; break;
1692 				case DIAGDIR_SW: delta = x / 2; break;
1693 				case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
1694 			}
1695 			return z + 1 + delta;
1696 		}
1697 	}
1698 
1699 	return z + GetPartialPixelZ(x, y, tileh);
1700 }
1701 
GetFoundation_TunnelBridge(TileIndex tile,Slope tileh)1702 static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
1703 {
1704 	return IsTunnel(tile) ? FOUNDATION_NONE : GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(tile)));
1705 }
1706 
GetTileDesc_TunnelBridge(TileIndex tile,TileDesc * td)1707 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
1708 {
1709 	TransportType tt = GetTunnelBridgeTransportType(tile);
1710 
1711 	if (IsTunnel(tile)) {
1712 		td->str = (tt == TRANSPORT_RAIL) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD;
1713 	} else { // IsBridge(tile)
1714 		td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
1715 	}
1716 	td->owner[0] = GetTileOwner(tile);
1717 
1718 	Owner road_owner = INVALID_OWNER;
1719 	Owner tram_owner = INVALID_OWNER;
1720 	RoadType road_rt = GetRoadTypeRoad(tile);
1721 	RoadType tram_rt = GetRoadTypeTram(tile);
1722 	if (road_rt != INVALID_ROADTYPE) {
1723 		const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
1724 		td->roadtype = rti->strings.name;
1725 		td->road_speed = rti->max_speed / 2;
1726 		road_owner = GetRoadOwner(tile, RTT_ROAD);
1727 	}
1728 	if (tram_rt != INVALID_ROADTYPE) {
1729 		const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
1730 		td->tramtype = rti->strings.name;
1731 		td->tram_speed = rti->max_speed / 2;
1732 		tram_owner = GetRoadOwner(tile, RTT_TRAM);
1733 	}
1734 
1735 	/* Is there a mix of owners? */
1736 	if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
1737 			(road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
1738 		uint i = 1;
1739 		if (road_owner != INVALID_OWNER) {
1740 			td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
1741 			td->owner[i] = road_owner;
1742 			i++;
1743 		}
1744 		if (tram_owner != INVALID_OWNER) {
1745 			td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
1746 			td->owner[i] = tram_owner;
1747 		}
1748 	}
1749 
1750 	if (tt == TRANSPORT_RAIL) {
1751 		const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
1752 		td->rail_speed = rti->max_speed;
1753 		td->railtype = rti->strings.name;
1754 
1755 		if (!IsTunnel(tile)) {
1756 			uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1757 			if (td->rail_speed == 0 || spd < td->rail_speed) {
1758 				td->rail_speed = spd;
1759 			}
1760 		}
1761 	} else if (tt == TRANSPORT_ROAD && !IsTunnel(tile)) {
1762 		uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1763 		if (road_rt != INVALID_ROADTYPE && (td->road_speed == 0 || spd < td->road_speed)) td->road_speed = spd;
1764 		if (tram_rt != INVALID_ROADTYPE && (td->tram_speed == 0 || spd < td->tram_speed)) td->tram_speed = spd;
1765 	}
1766 }
1767 
1768 
TileLoop_TunnelBridge(TileIndex tile)1769 static void TileLoop_TunnelBridge(TileIndex tile)
1770 {
1771 	bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile);
1772 	switch (_settings_game.game_creation.landscape) {
1773 		case LT_ARCTIC: {
1774 			/* As long as we do not have a snow density, we want to use the density
1775 			 * from the entry edge. For tunnels this is the lowest point for bridges the highest point.
1776 			 * (Independent of foundations) */
1777 			int z = IsBridge(tile) ? GetTileMaxZ(tile) : GetTileZ(tile);
1778 			if (snow_or_desert != (z > GetSnowLine())) {
1779 				SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
1780 				MarkTileDirtyByTile(tile);
1781 			}
1782 			break;
1783 		}
1784 
1785 		case LT_TROPIC:
1786 			if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
1787 				SetTunnelBridgeSnowOrDesert(tile, true);
1788 				MarkTileDirtyByTile(tile);
1789 			}
1790 			break;
1791 
1792 		default:
1793 			break;
1794 	}
1795 }
1796 
GetTileTrackStatus_TunnelBridge(TileIndex tile,TransportType mode,uint sub_mode,DiagDirection side)1797 static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
1798 {
1799 	TransportType transport_type = GetTunnelBridgeTransportType(tile);
1800 	if (transport_type != mode || (transport_type == TRANSPORT_ROAD && !HasTileRoadType(tile, (RoadTramType)sub_mode))) return 0;
1801 
1802 	DiagDirection dir = GetTunnelBridgeDirection(tile);
1803 	if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
1804 	return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
1805 }
1806 
ChangeTileOwner_TunnelBridge(TileIndex tile,Owner old_owner,Owner new_owner)1807 static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
1808 {
1809 	TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
1810 	/* Set number of pieces to zero if it's the southern tile as we
1811 	 * don't want to update the infrastructure counts twice. */
1812 	uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
1813 
1814 	for (RoadTramType rtt : _roadtramtypes) {
1815 		/* Update all roadtypes, no matter if they are present */
1816 		if (GetRoadOwner(tile, rtt) == old_owner) {
1817 			RoadType rt = GetRoadType(tile, rtt);
1818 			if (rt != INVALID_ROADTYPE) {
1819 				/* Update company infrastructure counts. A full diagonal road tile has two road bits.
1820 				 * No need to dirty windows here, we'll redraw the whole screen anyway. */
1821 				Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2;
1822 				if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2;
1823 			}
1824 
1825 			SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
1826 		}
1827 	}
1828 
1829 	if (!IsTileOwner(tile, old_owner)) return;
1830 
1831 	/* Update company infrastructure counts for rail and water as well.
1832 	 * No need to dirty windows here, we'll redraw the whole screen anyway. */
1833 	TransportType tt = GetTunnelBridgeTransportType(tile);
1834 	Company *old = Company::Get(old_owner);
1835 	if (tt == TRANSPORT_RAIL) {
1836 		old->infrastructure.rail[GetRailType(tile)] -= num_pieces;
1837 		if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += num_pieces;
1838 	} else if (tt == TRANSPORT_WATER) {
1839 		old->infrastructure.water -= num_pieces;
1840 		if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.water += num_pieces;
1841 	}
1842 
1843 	if (new_owner != INVALID_OWNER) {
1844 		SetTileOwner(tile, new_owner);
1845 	} else {
1846 		if (tt == TRANSPORT_RAIL) {
1847 			/* Since all of our vehicles have been removed, it is safe to remove the rail
1848 			 * bridge / tunnel. */
1849 			[[maybe_unused]] CommandCost ret = DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
1850 			assert(ret.Succeeded());
1851 		} else {
1852 			/* In any other case, we can safely reassign the ownership to OWNER_NONE. */
1853 			SetTileOwner(tile, OWNER_NONE);
1854 		}
1855 	}
1856 }
1857 
1858 /**
1859  * Frame when the 'enter tunnel' sound should be played. This is the second
1860  * frame on a tile, so the sound is played shortly after entering the tunnel
1861  * tile, while the vehicle is still visible.
1862  */
1863 static const byte TUNNEL_SOUND_FRAME = 1;
1864 
1865 /**
1866  * Frame when a vehicle should be hidden in a tunnel with a certain direction.
1867  * This differs per direction, because of visibility / bounding box issues.
1868  * Note that direction, in this case, is the direction leading into the tunnel.
1869  * When entering a tunnel, hide the vehicle when it reaches the given frame.
1870  * When leaving a tunnel, show the vehicle when it is one frame further
1871  * to the 'outside', i.e. at (TILE_SIZE-1) - (frame) + 1
1872  */
1873 extern const byte _tunnel_visibility_frame[DIAGDIR_END] = {12, 8, 8, 12};
1874 
VehicleEnter_TunnelBridge(Vehicle * v,TileIndex tile,int x,int y)1875 static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
1876 {
1877 	int z = GetSlopePixelZ(x, y) - v->z_pos;
1878 
1879 	if (abs(z) > 2) return VETSB_CANNOT_ENTER;
1880 	/* Direction into the wormhole */
1881 	const DiagDirection dir = GetTunnelBridgeDirection(tile);
1882 	/* Direction of the vehicle */
1883 	const DiagDirection vdir = DirToDiagDir(v->direction);
1884 	/* New position of the vehicle on the tile */
1885 	byte pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK;
1886 	/* Number of units moved by the vehicle since entering the tile */
1887 	byte frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
1888 
1889 	if (IsTunnel(tile)) {
1890 		if (v->type == VEH_TRAIN) {
1891 			Train *t = Train::From(v);
1892 
1893 			if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
1894 				if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) {
1895 					if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
1896 						SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
1897 					}
1898 					return VETSB_CONTINUE;
1899 				}
1900 				if (frame == _tunnel_visibility_frame[dir]) {
1901 					t->tile = tile;
1902 					t->track = TRACK_BIT_WORMHOLE;
1903 					t->vehstatus |= VS_HIDDEN;
1904 					return VETSB_ENTERED_WORMHOLE;
1905 				}
1906 			}
1907 
1908 			if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1909 				/* We're at the tunnel exit ?? */
1910 				t->tile = tile;
1911 				t->track = DiagDirToDiagTrackBits(vdir);
1912 				assert(t->track);
1913 				t->vehstatus &= ~VS_HIDDEN;
1914 				return VETSB_ENTERED_WORMHOLE;
1915 			}
1916 		} else if (v->type == VEH_ROAD) {
1917 			RoadVehicle *rv = RoadVehicle::From(v);
1918 
1919 			/* Enter tunnel? */
1920 			if (rv->state != RVSB_WORMHOLE && dir == vdir) {
1921 				if (frame == _tunnel_visibility_frame[dir]) {
1922 					/* Frame should be equal to the next frame number in the RV's movement */
1923 					assert(frame == rv->frame + 1);
1924 					rv->tile = tile;
1925 					rv->state = RVSB_WORMHOLE;
1926 					rv->vehstatus |= VS_HIDDEN;
1927 					return VETSB_ENTERED_WORMHOLE;
1928 				} else {
1929 					return VETSB_CONTINUE;
1930 				}
1931 			}
1932 
1933 			/* We're at the tunnel exit ?? */
1934 			if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1935 				rv->tile = tile;
1936 				rv->state = DiagDirToDiagTrackdir(vdir);
1937 				rv->frame = frame;
1938 				rv->vehstatus &= ~VS_HIDDEN;
1939 				return VETSB_ENTERED_WORMHOLE;
1940 			}
1941 		}
1942 	} else { // IsBridge(tile)
1943 		if (v->type != VEH_SHIP) {
1944 			/* modify speed of vehicle */
1945 			uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1946 
1947 			if (v->type == VEH_ROAD) spd *= 2;
1948 			Vehicle *first = v->First();
1949 			first->cur_speed = std::min(first->cur_speed, spd);
1950 		}
1951 
1952 		if (vdir == dir) {
1953 			/* Vehicle enters bridge at the last frame inside this tile. */
1954 			if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
1955 			switch (v->type) {
1956 				case VEH_TRAIN: {
1957 					Train *t = Train::From(v);
1958 					t->track = TRACK_BIT_WORMHOLE;
1959 					ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
1960 					ClrBit(t->gv_flags, GVF_GOINGDOWN_BIT);
1961 					break;
1962 				}
1963 
1964 				case VEH_ROAD: {
1965 					RoadVehicle *rv = RoadVehicle::From(v);
1966 					rv->state = RVSB_WORMHOLE;
1967 					/* There are no slopes inside bridges / tunnels. */
1968 					ClrBit(rv->gv_flags, GVF_GOINGUP_BIT);
1969 					ClrBit(rv->gv_flags, GVF_GOINGDOWN_BIT);
1970 					break;
1971 				}
1972 
1973 				case VEH_SHIP:
1974 					Ship::From(v)->state = TRACK_BIT_WORMHOLE;
1975 					break;
1976 
1977 				default: NOT_REACHED();
1978 			}
1979 			return VETSB_ENTERED_WORMHOLE;
1980 		} else if (vdir == ReverseDiagDir(dir)) {
1981 			v->tile = tile;
1982 			switch (v->type) {
1983 				case VEH_TRAIN: {
1984 					Train *t = Train::From(v);
1985 					if (t->track == TRACK_BIT_WORMHOLE) {
1986 						t->track = DiagDirToDiagTrackBits(vdir);
1987 						return VETSB_ENTERED_WORMHOLE;
1988 					}
1989 					break;
1990 				}
1991 
1992 				case VEH_ROAD: {
1993 					RoadVehicle *rv = RoadVehicle::From(v);
1994 					if (rv->state == RVSB_WORMHOLE) {
1995 						rv->state = DiagDirToDiagTrackdir(vdir);
1996 						rv->frame = 0;
1997 						return VETSB_ENTERED_WORMHOLE;
1998 					}
1999 					break;
2000 				}
2001 
2002 				case VEH_SHIP: {
2003 					Ship *ship = Ship::From(v);
2004 					if (ship->state == TRACK_BIT_WORMHOLE) {
2005 						ship->state = DiagDirToDiagTrackBits(vdir);
2006 						return VETSB_ENTERED_WORMHOLE;
2007 					}
2008 					break;
2009 				}
2010 
2011 				default: NOT_REACHED();
2012 			}
2013 		}
2014 	}
2015 	return VETSB_CONTINUE;
2016 }
2017 
TerraformTile_TunnelBridge(TileIndex tile,DoCommandFlag flags,int z_new,Slope tileh_new)2018 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2019 {
2020 	if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() && IsBridge(tile) && GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) {
2021 		DiagDirection direction = GetTunnelBridgeDirection(tile);
2022 		Axis axis = DiagDirToAxis(direction);
2023 		CommandCost res;
2024 		int z_old;
2025 		Slope tileh_old = GetTileSlope(tile, &z_old);
2026 
2027 		/* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
2028 		if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
2029 			CheckBridgeSlope(BRIDGE_PIECE_SOUTH, axis, &tileh_old, &z_old);
2030 			res = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, axis, &tileh_new, &z_new);
2031 		} else {
2032 			CheckBridgeSlope(BRIDGE_PIECE_NORTH, axis, &tileh_old, &z_old);
2033 			res = CheckBridgeSlope(BRIDGE_PIECE_NORTH, axis, &tileh_new, &z_new);
2034 		}
2035 
2036 		/* Surface slope is valid and remains unchanged? */
2037 		if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2038 	}
2039 
2040 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2041 }
2042 
2043 extern const TileTypeProcs _tile_type_tunnelbridge_procs = {
2044 	DrawTile_TunnelBridge,           // draw_tile_proc
2045 	GetSlopePixelZ_TunnelBridge,     // get_slope_z_proc
2046 	ClearTile_TunnelBridge,          // clear_tile_proc
2047 	nullptr,                            // add_accepted_cargo_proc
2048 	GetTileDesc_TunnelBridge,        // get_tile_desc_proc
2049 	GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc
2050 	nullptr,                            // click_tile_proc
2051 	nullptr,                            // animate_tile_proc
2052 	TileLoop_TunnelBridge,           // tile_loop_proc
2053 	ChangeTileOwner_TunnelBridge,    // change_tile_owner_proc
2054 	nullptr,                            // add_produced_cargo_proc
2055 	VehicleEnter_TunnelBridge,       // vehicle_enter_tile_proc
2056 	GetFoundation_TunnelBridge,      // get_foundation_proc
2057 	TerraformTile_TunnelBridge,      // terraform_tile_proc
2058 };
2059