OpenTTD Source  20241124-master-g9399a92a4f
tunnelbridge_cmd.cpp
Go to the documentation of this file.
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 
14 #include "stdafx.h"
15 #include "newgrf_object.h"
16 #include "viewport_func.h"
17 #include "command_func.h"
18 #include "town.h"
19 #include "train.h"
20 #include "ship.h"
21 #include "roadveh.h"
24 #include "newgrf_sound.h"
25 #include "autoslope.h"
26 #include "tunnelbridge_map.h"
27 #include "strings_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 #include "tunnelbridge_cmd.h"
44 #include "landscape_cmd.h"
45 #include "terraform_cmd.h"
46 
47 #include "table/strings.h"
48 #include "table/bridge_land.h"
49 
50 #include "safeguards.h"
51 
54 
56 static const int BRIDGE_Z_START = 3;
57 
58 
67 void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height)
68 {
69  TileIndexDiff delta = TileOffsByDiagDir(direction);
70  for (TileIndex t = begin; t != end; t += delta) {
71  MarkTileDirtyByTile(t, bridge_height - TileHeight(t));
72  }
74 }
75 
81 {
83 }
84 
87 {
88  /* First, free sprite table data */
89  for (BridgeType i = 0; i < MAX_BRIDGES; i++) {
90  if (_bridge[i].sprite_table != nullptr) {
91  for (BridgePieces j = BRIDGE_PIECE_NORTH; j < BRIDGE_PIECE_INVALID; j++) free(_bridge[i].sprite_table[j]);
92  free(_bridge[i].sprite_table);
93  }
94  }
95 
96  /* Then, wipe out current bridges */
97  memset(&_bridge, 0, sizeof(_bridge));
98  /* And finally, reinstall default data */
99  memcpy(&_bridge, &_orig_bridge, sizeof(_orig_bridge));
100 }
101 
108 int CalcBridgeLenCostFactor(int length)
109 {
110  if (length < 2) return length;
111 
112  length -= 2;
113  int sum = 2;
114  for (int delta = 1;; delta++) {
115  for (int count = 0; count < delta; count++) {
116  if (length == 0) return sum;
117  sum += delta;
118  length--;
119  }
120  }
121 }
122 
130 {
131  if (tileh == SLOPE_FLAT ||
132  ((tileh == SLOPE_NE || tileh == SLOPE_SW) && axis == AXIS_X) ||
133  ((tileh == SLOPE_NW || tileh == SLOPE_SE) && axis == AXIS_Y)) return FOUNDATION_NONE;
134 
135  return (HasSlopeHighestCorner(tileh) ? InclinedFoundation(axis) : FlatteningFoundation(tileh));
136 }
137 
145 bool HasBridgeFlatRamp(Slope tileh, Axis axis)
146 {
147  ApplyFoundationToSlope(GetBridgeFoundation(tileh, axis), tileh);
148  /* If the foundation slope is flat the bridge has a non-flat ramp and vice versa. */
149  return (tileh != SLOPE_FLAT);
150 }
151 
152 static inline const PalSpriteID *GetBridgeSpriteTable(int index, BridgePieces table)
153 {
154  const BridgeSpec *bridge = GetBridgeSpec(index);
155  assert(table < BRIDGE_PIECE_INVALID);
156  if (bridge->sprite_table == nullptr || bridge->sprite_table[table] == nullptr) {
157  return _bridge_sprite_table[index][table];
158  } else {
159  return bridge->sprite_table[table];
160  }
161 }
162 
163 
173 static CommandCost CheckBridgeSlope(BridgePieces bridge_piece, Axis axis, Slope &tileh, int &z)
174 {
175  assert(bridge_piece == BRIDGE_PIECE_NORTH || bridge_piece == BRIDGE_PIECE_SOUTH);
176 
177  Foundation f = GetBridgeFoundation(tileh, axis);
178  z += ApplyFoundationToSlope(f, tileh);
179 
180  Slope valid_inclined;
181  if (bridge_piece == BRIDGE_PIECE_NORTH) {
182  valid_inclined = (axis == AXIS_X ? SLOPE_NE : SLOPE_NW);
183  } else {
184  valid_inclined = (axis == AXIS_X ? SLOPE_SW : SLOPE_SE);
185  }
186  if ((tileh != SLOPE_FLAT) && (tileh != valid_inclined)) return CMD_ERROR;
187 
188  if (f == FOUNDATION_NONE) return CommandCost();
189 
190  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
191 }
192 
200 CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags)
201 {
202  if (flags & DC_QUERY_COST) {
203  if (bridge_len <= _settings_game.construction.max_bridge_length) return CommandCost();
204  return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
205  }
206 
207  if (bridge_type >= MAX_BRIDGES) return CMD_ERROR;
208 
209  const BridgeSpec *b = GetBridgeSpec(bridge_type);
211 
212  uint max = std::min(b->max_length, _settings_game.construction.max_bridge_length);
213 
214  if (b->min_length > bridge_len) return CMD_ERROR;
215  if (bridge_len <= max) return CommandCost();
216  return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
217 }
218 
224 static Money TunnelBridgeClearCost(TileIndex tile, Price base_price)
225 {
226  Money base_cost = _price[base_price];
227 
228  /* Add the cost of the transport that is on the tunnel/bridge. */
229  switch (GetTunnelBridgeTransportType(tile)) {
230  case TRANSPORT_ROAD: {
231  RoadType road_rt = GetRoadTypeRoad(tile);
232  RoadType tram_rt = GetRoadTypeTram(tile);
233 
234  if (road_rt != INVALID_ROADTYPE) {
235  base_cost += 2 * RoadClearCost(road_rt);
236  }
237  if (tram_rt != INVALID_ROADTYPE) {
238  base_cost += 2 * RoadClearCost(tram_rt);
239  }
240  } break;
241 
242  case TRANSPORT_RAIL: base_cost += RailClearCost(GetRailType(tile)); break;
243  /* Aquaducts have their own clear price. */
244  case TRANSPORT_WATER: base_cost = _price[PR_CLEAR_AQUEDUCT]; break;
245  default: break;
246  }
247 
248  return base_cost;
249 }
250 
261 CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, uint8_t road_rail_type)
262 {
263  CompanyID company = _current_company;
264 
265  RailType railtype = INVALID_RAILTYPE;
266  RoadType roadtype = INVALID_ROADTYPE;
267 
268  if (!IsValidTile(tile_start)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
269 
270  /* type of bridge */
271  switch (transport_type) {
272  case TRANSPORT_ROAD:
273  roadtype = (RoadType)road_rail_type;
274  if (!ValParamRoadType(roadtype)) return CMD_ERROR;
275  break;
276 
277  case TRANSPORT_RAIL:
278  railtype = (RailType)road_rail_type;
279  if (!ValParamRailType(railtype)) return CMD_ERROR;
280  break;
281 
282  case TRANSPORT_WATER:
283  break;
284 
285  default:
286  /* Airports don't have bridges. */
287  return CMD_ERROR;
288  }
289 
290  if (company == OWNER_DEITY) {
291  if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
292  const Town *town = CalcClosestTownFromTile(tile_start);
293 
294  company = OWNER_TOWN;
295 
296  /* If we are not within a town, we are not owned by the town */
297  if (town == nullptr || DistanceSquare(tile_start, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
298  company = OWNER_NONE;
299  }
300  }
301 
302  if (tile_start == tile_end) {
303  return_cmd_error(STR_ERROR_CAN_T_START_AND_END_ON);
304  }
305 
306  Axis direction;
307  if (TileX(tile_start) == TileX(tile_end)) {
308  direction = AXIS_Y;
309  } else if (TileY(tile_start) == TileY(tile_end)) {
310  direction = AXIS_X;
311  } else {
312  return_cmd_error(STR_ERROR_START_AND_END_MUST_BE_IN);
313  }
314 
315  if (tile_end < tile_start) Swap(tile_start, tile_end);
316 
317  uint bridge_len = GetTunnelBridgeLength(tile_start, tile_end);
318  if (transport_type != TRANSPORT_WATER) {
319  /* set and test bridge length, availability */
320  CommandCost ret = CheckBridgeAvailability(bridge_type, bridge_len, flags);
321  if (ret.Failed()) return ret;
322  } else {
323  if (bridge_len > _settings_game.construction.max_bridge_length) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
324  }
325  bridge_len += 2; // begin and end tiles/ramps
326 
327  auto [tileh_start, z_start] = GetTileSlopeZ(tile_start);
328  auto [tileh_end, z_end] = GetTileSlopeZ(tile_end);
329  bool pbs_reservation = false;
330 
331  CommandCost terraform_cost_north = CheckBridgeSlope(BRIDGE_PIECE_NORTH, direction, tileh_start, z_start);
332  CommandCost terraform_cost_south = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, direction, tileh_end, z_end);
333 
334  /* Aqueducts can't be built of flat land. */
335  if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
336  if (z_start != z_end) return_cmd_error(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT);
337 
339  Owner owner;
340  bool is_new_owner;
341  RoadType road_rt = INVALID_ROADTYPE;
342  RoadType tram_rt = INVALID_ROADTYPE;
343  if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
344  GetOtherBridgeEnd(tile_start) == tile_end &&
345  GetTunnelBridgeTransportType(tile_start) == transport_type) {
346  /* Replace a current bridge. */
347 
348  switch (transport_type) {
349  case TRANSPORT_RAIL:
350  /* Keep the reservation, the path stays valid. */
351  pbs_reservation = HasTunnelBridgeReservation(tile_start);
352  break;
353 
354  case TRANSPORT_ROAD:
355  /* Do not remove road types when upgrading a bridge */
356  road_rt = GetRoadTypeRoad(tile_start);
357  tram_rt = GetRoadTypeTram(tile_start);
358  break;
359 
360  default: break;
361  }
362 
363  /* If this is a railway bridge, make sure the railtypes match. */
364  if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
365  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
366  }
367 
368  /* If this is a road bridge, make sure the roadtype matches. */
369  if (transport_type == TRANSPORT_ROAD) {
370  RoadType existing_rt = RoadTypeIsRoad(roadtype) ? road_rt : tram_rt;
371  if (existing_rt != roadtype && existing_rt != INVALID_ROADTYPE) {
372  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
373  }
374  }
375 
376  if (!(flags & DC_QUERY_COST)) {
377  /* Do not replace the bridge with the same bridge type. */
378  if ((bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || road_rt == roadtype || tram_rt == roadtype)) {
379  return_cmd_error(STR_ERROR_ALREADY_BUILT);
380  }
381 
382  /* Do not replace town bridges with lower speed bridges, unless in scenario editor. */
383  if (IsTileOwner(tile_start, OWNER_TOWN) && _game_mode != GM_EDITOR) {
384  Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
385  if (t == nullptr) return CMD_ERROR;
386 
387  if (GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed) {
388  SetDParam(0, t->index);
389  return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
390  } else {
391  ChangeTownRating(t, RATING_TUNNEL_BRIDGE_UP_STEP, RATING_MAXIMUM, flags);
392  }
393  }
394  }
395 
396  /* Do not allow replacing another company's bridges. */
397  if (!IsTileOwner(tile_start, company) && !IsTileOwner(tile_start, OWNER_TOWN) && !IsTileOwner(tile_start, OWNER_NONE)) {
398  return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
399  }
400 
401  /* The cost of clearing the current bridge. */
402  cost.AddCost(bridge_len * TunnelBridgeClearCost(tile_start, PR_CLEAR_BRIDGE));
403  owner = GetTileOwner(tile_start);
404 
405  /* If bridge belonged to bankrupt company, it has a new owner now */
406  is_new_owner = (owner == OWNER_NONE);
407  if (is_new_owner) owner = company;
408  } else {
409  /* Build a new bridge. */
410 
411  bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
412 
413  /* Try and clear the start landscape */
414  CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_start);
415  if (ret.Failed()) return ret;
416  cost = ret;
417 
418  if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
419  cost.AddCost(terraform_cost_north);
420 
421  /* Try and clear the end landscape */
422  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile_end);
423  if (ret.Failed()) return ret;
424  cost.AddCost(ret);
425 
426  /* false - end tile slope check */
427  if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
428  cost.AddCost(terraform_cost_south);
429 
430  const TileIndex heads[] = {tile_start, tile_end};
431  for (int i = 0; i < 2; i++) {
432  if (IsBridgeAbove(heads[i])) {
433  TileIndex north_head = GetNorthernBridgeEnd(heads[i]);
434 
435  if (direction == GetBridgeAxis(heads[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
436 
437  if (z_start + 1 == GetBridgeHeight(north_head)) {
438  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
439  }
440  }
441  }
442 
443  TileIndexDiff delta = TileOffsByAxis(direction);
444  for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
445  if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN);
446 
447  if (z_start >= (GetTileZ(tile) + _settings_game.construction.max_bridge_height)) {
448  /*
449  * Disallow too high bridges.
450  * Properly rendering a map where very high bridges (might) exist is expensive.
451  * See http://www.tt-forums.net/viewtopic.php?f=33&t=40844&start=980#p1131762
452  * for a detailed discussion. z_start here is one heightlevel below the bridge level.
453  */
454  return_cmd_error(STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN);
455  }
456 
457  if (IsBridgeAbove(tile)) {
458  /* Disallow crossing bridges for the time being */
459  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
460  }
461 
462  switch (GetTileType(tile)) {
463  case MP_WATER:
464  if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
465  break;
466 
467  case MP_RAILWAY:
468  if (!IsPlainRail(tile)) goto not_valid_below;
469  break;
470 
471  case MP_ROAD:
472  if (IsRoadDepot(tile)) goto not_valid_below;
473  break;
474 
475  case MP_TUNNELBRIDGE:
476  if (IsTunnel(tile)) break;
477  if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below;
478  if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
479  break;
480 
481  case MP_OBJECT: {
482  const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
483  if ((spec->flags & OBJECT_FLAG_ALLOW_UNDER_BRIDGE) == 0) goto not_valid_below;
484  if (GetTileMaxZ(tile) + spec->height > z_start) goto not_valid_below;
485  break;
486  }
487 
488  case MP_CLEAR:
489  break;
490 
491  default:
492  not_valid_below:;
493  /* try and clear the middle landscape */
494  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
495  if (ret.Failed()) return ret;
496  cost.AddCost(ret);
497  break;
498  }
499 
500  if (flags & DC_EXEC) {
501  /* We do this here because when replacing a bridge with another
502  * type calling SetBridgeMiddle isn't needed. After all, the
503  * tile already has the has_bridge_above bits set. */
504  SetBridgeMiddle(tile, direction);
505  }
506  }
507 
508  owner = company;
509  is_new_owner = true;
510  }
511 
512  bool hasroad = road_rt != INVALID_ROADTYPE;
513  bool hastram = tram_rt != INVALID_ROADTYPE;
514  if (transport_type == TRANSPORT_ROAD) {
515  if (RoadTypeIsRoad(roadtype)) road_rt = roadtype;
516  if (RoadTypeIsTram(roadtype)) tram_rt = roadtype;
517  }
518 
519  /* do the drill? */
520  if (flags & DC_EXEC) {
521  DiagDirection dir = AxisToDiagDir(direction);
522 
523  Company *c = Company::GetIfValid(company);
524  switch (transport_type) {
525  case TRANSPORT_RAIL:
526  /* Add to company infrastructure count if required. */
527  if (is_new_owner && c != nullptr) c->infrastructure.rail[railtype] += bridge_len * TUNNELBRIDGE_TRACKBIT_FACTOR;
528  MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
529  MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype);
530  SetTunnelBridgeReservation(tile_start, pbs_reservation);
531  SetTunnelBridgeReservation(tile_end, pbs_reservation);
532  break;
533 
534  case TRANSPORT_ROAD: {
535  if (is_new_owner) {
536  /* Also give unowned present roadtypes to new owner */
537  if (hasroad && GetRoadOwner(tile_start, RTT_ROAD) == OWNER_NONE) hasroad = false;
538  if (hastram && GetRoadOwner(tile_start, RTT_TRAM) == OWNER_NONE) hastram = false;
539  }
540  if (c != nullptr) {
541  /* Add all new road types to the company infrastructure counter. */
542  if (!hasroad && road_rt != INVALID_ROADTYPE) {
543  /* A full diagonal road tile has two road bits. */
544  c->infrastructure.road[road_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
545  }
546  if (!hastram && tram_rt != INVALID_ROADTYPE) {
547  /* A full diagonal road tile has two road bits. */
548  c->infrastructure.road[tram_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
549  }
550  }
551  Owner owner_road = hasroad ? GetRoadOwner(tile_start, RTT_ROAD) : company;
552  Owner owner_tram = hastram ? GetRoadOwner(tile_start, RTT_TRAM) : company;
553  MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, road_rt, tram_rt);
554  MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), road_rt, tram_rt);
555  break;
556  }
557 
558  case TRANSPORT_WATER:
559  if (is_new_owner && c != nullptr) c->infrastructure.water += bridge_len * TUNNELBRIDGE_TRACKBIT_FACTOR;
560  MakeAqueductBridgeRamp(tile_start, owner, dir);
561  MakeAqueductBridgeRamp(tile_end, owner, ReverseDiagDir(dir));
562  CheckForDockingTile(tile_start);
563  CheckForDockingTile(tile_end);
564  break;
565 
566  default:
567  NOT_REACHED();
568  }
569 
570  /* Mark all tiles dirty */
571  MarkBridgeDirty(tile_start, tile_end, AxisToDiagDir(direction), z_start);
573  }
574 
575  if ((flags & DC_EXEC) && transport_type == TRANSPORT_RAIL) {
576  Track track = AxisToTrack(direction);
577  AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, company);
578  YapfNotifyTrackLayoutChange(tile_start, track);
579  }
580 
581  /* Human players that build bridges get a selection to choose from (DC_QUERY_COST)
582  * It's unnecessary to execute this command every time for every bridge.
583  * So it is done only for humans and cost is computed in bridge_gui.cpp.
584  * For (non-spectated) AI, Towns this has to be of course calculated. */
585  Company *c = Company::GetIfValid(company);
586  if (!(flags & DC_QUERY_COST) || (c != nullptr && c->is_ai && company != _local_company)) {
587  switch (transport_type) {
588  case TRANSPORT_ROAD:
589  if (road_rt != INVALID_ROADTYPE) {
590  cost.AddCost(bridge_len * 2 * RoadBuildCost(road_rt));
591  }
592  if (tram_rt != INVALID_ROADTYPE) {
593  cost.AddCost(bridge_len * 2 * RoadBuildCost(tram_rt));
594  }
595  break;
596 
597  case TRANSPORT_RAIL: cost.AddCost(bridge_len * RailBuildCost(railtype)); break;
598  default: break;
599  }
600 
601  if (c != nullptr) bridge_len = CalcBridgeLenCostFactor(bridge_len);
602 
603  if (transport_type != TRANSPORT_WATER) {
604  cost.AddCost((int64_t)bridge_len * _price[PR_BUILD_BRIDGE] * GetBridgeSpec(bridge_type)->price >> 8);
605  } else {
606  /* Aqueducts use a separate base cost. */
607  cost.AddCost((int64_t)bridge_len * _price[PR_BUILD_AQUEDUCT]);
608  }
609 
610  }
611 
612  return cost;
613 }
614 
615 
624 CommandCost CmdBuildTunnel(DoCommandFlag flags, TileIndex start_tile, TransportType transport_type, uint8_t road_rail_type)
625 {
626  CompanyID company = _current_company;
627 
628  RailType railtype = INVALID_RAILTYPE;
629  RoadType roadtype = INVALID_ROADTYPE;
631  switch (transport_type) {
632  case TRANSPORT_RAIL:
633  railtype = (RailType)road_rail_type;
634  if (!ValParamRailType(railtype)) return CMD_ERROR;
635  break;
636 
637  case TRANSPORT_ROAD:
638  roadtype = (RoadType)road_rail_type;
639  if (!ValParamRoadType(roadtype)) return CMD_ERROR;
640  break;
641 
642  default: return CMD_ERROR;
643  }
644 
645  if (company == OWNER_DEITY) {
646  if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
647  const Town *town = CalcClosestTownFromTile(start_tile);
648 
649  company = OWNER_TOWN;
650 
651  /* If we are not within a town, we are not owned by the town */
652  if (town == nullptr || DistanceSquare(start_tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
653  company = OWNER_NONE;
654  }
655  }
656 
657  auto [start_tileh, start_z] = GetTileSlopeZ(start_tile);
658  DiagDirection direction = GetInclinedSlopeDirection(start_tileh);
659  if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL);
660 
661  if (HasTileWaterGround(start_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
662 
663  CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, start_tile);
664  if (ret.Failed()) return ret;
665 
666  /* XXX - do NOT change 'ret' in the loop, as it is used as the price
667  * for the clearing of the entrance of the tunnel. Assigning it to
668  * cost before the loop will yield different costs depending on start-
669  * position, because of increased-cost-by-length: 'cost += cost >> 3' */
670 
671  TileIndexDiff delta = TileOffsByDiagDir(direction);
672  DiagDirection tunnel_in_way_dir;
673  if (DiagDirToAxis(direction) == AXIS_Y) {
674  tunnel_in_way_dir = (TileX(start_tile) < (Map::MaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
675  } else {
676  tunnel_in_way_dir = (TileY(start_tile) < (Map::MaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
677  }
678 
679  TileIndex end_tile = start_tile;
680 
681  /* Tile shift coefficient. Will decrease for very long tunnels to avoid exponential growth of price*/
682  int tiles_coef = 3;
683  /* Number of tiles from start of tunnel */
684  int tiles = 0;
685  /* Number of tiles at which the cost increase coefficient per tile is halved */
686  int tiles_bump = 25;
687 
689  Slope end_tileh;
690  int end_z;
691  for (;;) {
692  end_tile += delta;
693  if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER);
694  std::tie(end_tileh, end_z) = GetTileSlopeZ(end_tile);
695 
696  if (start_z == end_z) break;
697 
698  if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
699  return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY);
700  }
701 
702  tiles++;
703  if (tiles == tiles_bump) {
704  tiles_coef++;
705  tiles_bump *= 2;
706  }
707 
708  cost.AddCost(_price[PR_BUILD_TUNNEL]);
709  cost.AddCost(cost.GetCost() >> tiles_coef); // add a multiplier for longer tunnels
710  }
711 
712  /* Add the cost of the entrance */
713  cost.AddCost(_price[PR_BUILD_TUNNEL]);
714  cost.AddCost(ret);
715 
716  /* if the command fails from here on we want the end tile to be highlighted */
717  _build_tunnel_endtile = end_tile;
718 
719  if (tiles > _settings_game.construction.max_tunnel_length) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG);
720 
721  if (HasTileWaterGround(end_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
722 
723  /* Clear the tile in any case */
724  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, end_tile);
725  if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
726  cost.AddCost(ret);
727 
728  /* slope of end tile must be complementary to the slope of the start tile */
729  if (end_tileh != ComplementSlope(start_tileh)) {
730  /* Mark the tile as already cleared for the terraform command.
731  * Do this for all tiles (like trees), not only objects. */
732  ClearedObjectArea *coa = FindClearedObject(end_tile);
733  if (coa == nullptr) {
734  coa = &_cleared_object_areas.emplace_back(ClearedObjectArea{ end_tile, TileArea(end_tile, 1, 1) });
735  }
736 
737  /* Hide the tile from the terraforming command */
738  TileIndex old_first_tile = coa->first_tile;
739  coa->first_tile = INVALID_TILE;
740 
741  /* CMD_TERRAFORM_LAND may append further items to _cleared_object_areas,
742  * however it will never erase or re-order existing items.
743  * _cleared_object_areas is a value-type self-resizing vector, therefore appending items
744  * may result in a backing-store re-allocation, which would invalidate the coa pointer.
745  * The index of the coa pointer into the _cleared_object_areas vector remains valid,
746  * and can be used safely after the CMD_TERRAFORM_LAND operation.
747  * Deliberately clear the coa pointer to avoid leaving dangling pointers which could
748  * inadvertently be dereferenced.
749  */
750  ClearedObjectArea *begin = _cleared_object_areas.data();
751  assert(coa >= begin && coa < begin + _cleared_object_areas.size());
752  size_t coa_index = coa - begin;
753  assert(coa_index < UINT_MAX); // more than 2**32 cleared areas would be a bug in itself
754  coa = nullptr;
755 
756  ret = std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(flags, end_tile, end_tileh & start_tileh, false));
757  _cleared_object_areas[(uint)coa_index].first_tile = old_first_tile;
758  if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
759  cost.AddCost(ret);
760  }
761  cost.AddCost(_price[PR_BUILD_TUNNEL]);
762 
763  /* Pay for the rail/road in the tunnel including entrances */
764  switch (transport_type) {
765  case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * RoadBuildCost(roadtype) * 2); break;
766  case TRANSPORT_RAIL: cost.AddCost((tiles + 2) * RailBuildCost(railtype)); break;
767  default: NOT_REACHED();
768  }
769 
770  if (flags & DC_EXEC) {
771  Company *c = Company::GetIfValid(company);
772  uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
773  if (transport_type == TRANSPORT_RAIL) {
774  if (c != nullptr) c->infrastructure.rail[railtype] += num_pieces;
775  MakeRailTunnel(start_tile, company, direction, railtype);
776  MakeRailTunnel(end_tile, company, ReverseDiagDir(direction), railtype);
777  AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company);
778  YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
779  } else {
780  if (c != nullptr) c->infrastructure.road[roadtype] += num_pieces * 2; // A full diagonal road has two road bits.
781  RoadType road_rt = RoadTypeIsRoad(roadtype) ? roadtype : INVALID_ROADTYPE;
782  RoadType tram_rt = RoadTypeIsTram(roadtype) ? roadtype : INVALID_ROADTYPE;
783  MakeRoadTunnel(start_tile, company, direction, road_rt, tram_rt);
784  MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), road_rt, tram_rt);
785  }
787  }
788 
789  return cost;
790 }
791 
792 
799 {
800  /* Floods can remove anything as well as the scenario editor */
801  if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return CommandCost();
802 
803  switch (GetTunnelBridgeTransportType(tile)) {
804  case TRANSPORT_ROAD: {
805  RoadType road_rt = GetRoadTypeRoad(tile);
806  RoadType tram_rt = GetRoadTypeTram(tile);
807  Owner road_owner = _current_company;
808  Owner tram_owner = _current_company;
809 
810  if (road_rt != INVALID_ROADTYPE) road_owner = GetRoadOwner(tile, RTT_ROAD);
811  if (tram_rt != INVALID_ROADTYPE) tram_owner = GetRoadOwner(tile, RTT_TRAM);
812 
813  /* We can remove unowned road and if the town allows it */
815  /* Town does not allow */
816  return CheckTileOwnership(tile);
817  }
818  if (road_owner == OWNER_NONE || road_owner == OWNER_TOWN) road_owner = _current_company;
819  if (tram_owner == OWNER_NONE) tram_owner = _current_company;
820 
821  CommandCost ret = CheckOwnership(road_owner, tile);
822  if (ret.Succeeded()) ret = CheckOwnership(tram_owner, tile);
823  return ret;
824  }
825 
826  case TRANSPORT_RAIL:
827  return CheckOwnership(GetTileOwner(tile));
828 
829  case TRANSPORT_WATER: {
830  /* Always allow to remove aqueducts without owner. */
831  Owner aqueduct_owner = GetTileOwner(tile);
832  if (aqueduct_owner == OWNER_NONE) aqueduct_owner = _current_company;
833  return CheckOwnership(aqueduct_owner);
834  }
835 
836  default: NOT_REACHED();
837  }
838 }
839 
847 {
849  if (ret.Failed()) return ret;
850 
851  TileIndex endtile = GetOtherTunnelEnd(tile);
852 
853  ret = TunnelBridgeIsFree(tile, endtile);
854  if (ret.Failed()) return ret;
855 
856  _build_tunnel_endtile = endtile;
857 
858  Town *t = nullptr;
859  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
860  t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
861 
862  /* Check if you are allowed to remove the tunnel owned by a town
863  * Removal depends on difficulty settings */
864  ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
865  if (ret.Failed()) return ret;
866  }
867 
868  /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
869  * you have a "Poor" (0) town rating */
870  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
872  }
873 
874  Money base_cost = TunnelBridgeClearCost(tile, PR_CLEAR_TUNNEL);
875  uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
876 
877  if (flags & DC_EXEC) {
879  /* We first need to request values before calling DoClearSquare */
881  Track track = DiagDirToDiagTrack(dir);
882  Owner owner = GetTileOwner(tile);
883 
884  Train *v = nullptr;
885  if (HasTunnelBridgeReservation(tile)) {
886  v = GetTrainForReservation(tile, track);
887  if (v != nullptr) FreeTrainTrackReservation(v);
888  }
889 
890  if (Company::IsValidID(owner)) {
891  Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
893  }
894 
895  DoClearSquare(tile);
896  DoClearSquare(endtile);
897 
898  /* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
899  AddSideToSignalBuffer(tile, ReverseDiagDir(dir), owner);
900  AddSideToSignalBuffer(endtile, dir, owner);
901 
902  YapfNotifyTrackLayoutChange(tile, track);
903  YapfNotifyTrackLayoutChange(endtile, track);
904 
905  if (v != nullptr) TryPathReserve(v);
906  } else {
907  /* A full diagonal road tile has two road bits. */
908  UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
909  UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
910 
911  DoClearSquare(tile);
912  DoClearSquare(endtile);
913  }
914  }
915 
916  return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
917 }
918 
919 
927 {
929  if (ret.Failed()) return ret;
930 
931  TileIndex endtile = GetOtherBridgeEnd(tile);
932 
933  ret = TunnelBridgeIsFree(tile, endtile);
934  if (ret.Failed()) return ret;
935 
936  DiagDirection direction = GetTunnelBridgeDirection(tile);
937  TileIndexDiff delta = TileOffsByDiagDir(direction);
938 
939  Town *t = nullptr;
940  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
941  t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
942 
943  /* Check if you are allowed to remove the bridge owned by a town
944  * Removal depends on difficulty settings */
945  ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
946  if (ret.Failed()) return ret;
947  }
948 
949  /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
950  * you have a "Poor" (0) town rating */
951  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
953  }
954 
955  Money base_cost = TunnelBridgeClearCost(tile, PR_CLEAR_BRIDGE);
956  uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
957 
958  if (flags & DC_EXEC) {
959  /* read this value before actual removal of bridge */
960  bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
961  Owner owner = GetTileOwner(tile);
962  int height = GetBridgeHeight(tile);
963  Train *v = nullptr;
964 
965  if (rail && HasTunnelBridgeReservation(tile)) {
966  v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
967  if (v != nullptr) FreeTrainTrackReservation(v);
968  }
969 
970  /* Update company infrastructure counts. */
971  if (rail) {
972  if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
973  } else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) {
974  /* A full diagonal road tile has two road bits. */
975  UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
976  UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
977  } else { // Aqueduct
978  if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.water -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
979  }
981 
982  DoClearSquare(tile);
983  DoClearSquare(endtile);
984 
985  for (TileIndex c = tile + delta; c != endtile; c += delta) {
986  /* do not let trees appear from 'nowhere' after removing bridge */
987  if (IsNormalRoadTile(c) && GetRoadside(c) == ROADSIDE_TREES) {
988  int minz = GetTileMaxZ(c) + 3;
989  if (height < minz) SetRoadside(c, ROADSIDE_PAVED);
990  }
992  MarkTileDirtyByTile(c, height - TileHeight(c));
993  }
994 
995  if (rail) {
996  /* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
997  AddSideToSignalBuffer(tile, ReverseDiagDir(direction), owner);
998  AddSideToSignalBuffer(endtile, direction, owner);
999 
1000  Track track = DiagDirToDiagTrack(direction);
1001  YapfNotifyTrackLayoutChange(tile, track);
1002  YapfNotifyTrackLayoutChange(endtile, track);
1003 
1004  if (v != nullptr) TryPathReserve(v, true);
1005  }
1006  }
1007 
1008  return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
1009 }
1010 
1018 {
1019  if (IsTunnel(tile)) {
1020  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST);
1021  return DoClearTunnel(tile, flags);
1022  } else { // IsBridge(tile)
1023  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1024  return DoClearBridge(tile, flags);
1025  }
1026 }
1027 
1038 static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
1039 {
1040  static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START;
1041  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);
1042 }
1043 
1055 static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, int x, int y, int w, int h)
1056 {
1057  int cur_z;
1058  for (cur_z = z_top; cur_z >= z_bottom; cur_z -= TILE_HEIGHT) {
1059  DrawPillar(psid, x, y, cur_z, w, h, nullptr);
1060  }
1061  return cur_z;
1062 }
1063 
1075 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
1076 {
1077  static const int bounding_box_size[2] = {16, 2};
1078  static const int back_pillar_offset[2] = { 0, 9};
1079 
1080  static const int INF = 1000;
1081  static const SubSprite half_pillar_sub_sprite[2][2] = {
1082  { { -14, -INF, INF, INF }, { -INF, -INF, -15, INF } }, // X axis, north and south
1083  { { -INF, -INF, 15, INF }, { 16, -INF, INF, INF } }, // Y axis, north and south
1084  };
1085 
1086  if (psid->sprite == 0) return;
1087 
1088  /* Determine ground height under pillars */
1089  DiagDirection south_dir = AxisToDiagDir(axis);
1090  int z_front_north = ti->z;
1091  int z_back_north = ti->z;
1092  int z_front_south = ti->z;
1093  int z_back_south = ti->z;
1094  GetSlopePixelZOnEdge(ti->tileh, south_dir, z_front_south, z_back_south);
1095  GetSlopePixelZOnEdge(ti->tileh, ReverseDiagDir(south_dir), z_front_north, z_back_north);
1096 
1097  /* Shared height of pillars */
1098  int z_front = std::max(z_front_north, z_front_south);
1099  int z_back = std::max(z_back_north, z_back_south);
1100 
1101  /* x and y size of bounding-box of pillars */
1102  int w = bounding_box_size[axis];
1103  int h = bounding_box_size[OtherAxis(axis)];
1104  /* sprite position of back facing pillar */
1105  int x_back = x - back_pillar_offset[axis];
1106  int y_back = y - back_pillar_offset[OtherAxis(axis)];
1107 
1108  /* Draw front pillars */
1109  int bottom_z = DrawPillarColumn(z_front, z_bridge, psid, x, y, w, h);
1110  if (z_front_north < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1111  if (z_front_south < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1112 
1113  /* Draw back pillars, skip top two parts, which are hidden by the bridge */
1114  int z_bridge_back = z_bridge - 2 * (int)TILE_HEIGHT;
1115  if (drawfarpillar && (z_back_north <= z_bridge_back || z_back_south <= z_bridge_back)) {
1116  bottom_z = DrawPillarColumn(z_back, z_bridge_back, psid, x_back, y_back, w, h);
1117  if (z_back_north < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1118  if (z_back_south < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1119  }
1120 }
1121 
1131 static void GetBridgeRoadCatenary(const RoadTypeInfo *rti, TileIndex head_tile, int offset, bool head, SpriteID &spr_back, SpriteID &spr_front)
1132 {
1133  static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
1134  static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
1135 
1136  /* Simplified from DrawRoadTypeCatenary() to remove all the special cases required for regular ground road */
1137  spr_back = GetCustomRoadSprite(rti, head_tile, ROTSG_CATENARY_BACK, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1138  spr_front = GetCustomRoadSprite(rti, head_tile, ROTSG_CATENARY_FRONT, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1139  if (spr_back == 0 && spr_front == 0) {
1140  spr_back = SPR_TRAMWAY_BASE + back_offsets[offset];
1141  spr_front = SPR_TRAMWAY_BASE + front_offsets[offset];
1142  } else {
1143  if (spr_back != 0) spr_back += 23 + offset;
1144  if (spr_front != 0) spr_front += 23 + offset;
1145  }
1146 }
1147 
1157 static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int offset, bool head)
1158 {
1159  RoadType road_rt = GetRoadTypeRoad(head_tile);
1160  RoadType tram_rt = GetRoadTypeTram(head_tile);
1161  const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1162  const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1163 
1164  SpriteID seq_back[4] = { 0 };
1165  bool trans_back[4] = { false };
1166  SpriteID seq_front[4] = { 0 };
1167  bool trans_front[4] = { false };
1168 
1169  static const SpriteID overlay_offsets[6] = { 0, 1, 11, 12, 13, 14 };
1170  if (head || !IsInvisibilitySet(TO_BRIDGES)) {
1171  /* Road underlay takes precedence over tram */
1172  trans_back[0] = !head && IsTransparencySet(TO_BRIDGES);
1173  if (road_rti != nullptr) {
1174  if (road_rti->UsesOverlay()) {
1175  seq_back[0] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
1176  }
1177  } else if (tram_rti != nullptr) {
1178  if (tram_rti->UsesOverlay()) {
1179  seq_back[0] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
1180  } else {
1181  seq_back[0] = SPR_TRAMWAY_BRIDGE + offset;
1182  }
1183  }
1184 
1185  /* Draw road overlay */
1186  trans_back[1] = !head && IsTransparencySet(TO_BRIDGES);
1187  if (road_rti != nullptr) {
1188  if (road_rti->UsesOverlay()) {
1189  seq_back[1] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1190  if (seq_back[1] != 0) seq_back[1] += overlay_offsets[offset];
1191  }
1192  }
1193 
1194  /* Draw tram overlay */
1195  trans_back[2] = !head && IsTransparencySet(TO_BRIDGES);
1196  if (tram_rti != nullptr) {
1197  if (tram_rti->UsesOverlay()) {
1198  seq_back[2] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
1199  if (seq_back[2] != 0) seq_back[2] += overlay_offsets[offset];
1200  } else if (road_rti != nullptr) {
1201  seq_back[2] = SPR_TRAMWAY_OVERLAY + overlay_offsets[offset];
1202  }
1203  }
1204 
1205  /* Road catenary takes precedence over tram */
1206  trans_back[3] = IsTransparencySet(TO_CATENARY);
1207  trans_front[0] = IsTransparencySet(TO_CATENARY);
1208  if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
1209  GetBridgeRoadCatenary(road_rti, head_tile, offset, head, seq_back[3], seq_front[0]);
1210  } else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
1211  GetBridgeRoadCatenary(tram_rti, head_tile, offset, head, seq_back[3], seq_front[0]);
1212  }
1213  }
1214 
1215  static const uint size_x[6] = { 1, 16, 16, 1, 16, 1 };
1216  static const uint size_y[6] = { 16, 1, 1, 16, 1, 16 };
1217  static const uint front_bb_offset_x[6] = { 15, 0, 0, 15, 0, 15 };
1218  static const uint front_bb_offset_y[6] = { 0, 15, 15, 0, 15, 0 };
1219 
1220  /* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
1221  * The bounding boxes here are the same as for bridge front/roof */
1222  for (uint i = 0; i < lengthof(seq_back); ++i) {
1223  if (seq_back[i] != 0) {
1224  AddSortableSpriteToDraw(seq_back[i], PAL_NONE,
1225  x, y, size_x[offset], size_y[offset], 0x28, z,
1226  trans_back[i]);
1227  }
1228  }
1229 
1230  /* Start a new SpriteCombine for the front part */
1231  EndSpriteCombine();
1233 
1234  for (uint i = 0; i < lengthof(seq_front); ++i) {
1235  if (seq_front[i] != 0) {
1236  AddSortableSpriteToDraw(seq_front[i], PAL_NONE,
1237  x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
1238  trans_front[i],
1239  front_bb_offset_x[offset], front_bb_offset_y[offset]);
1240  }
1241  }
1242 }
1243 
1258 {
1259  TransportType transport_type = GetTunnelBridgeTransportType(ti->tile);
1260  DiagDirection tunnelbridge_direction = GetTunnelBridgeDirection(ti->tile);
1261 
1262  if (IsTunnel(ti->tile)) {
1263  /* Front view of tunnel bounding boxes:
1264  *
1265  * 122223 <- BB_Z_SEPARATOR
1266  * 1 3
1267  * 1 3 1,3 = empty helper BB
1268  * 1 3 2 = SpriteCombine of tunnel-roof and catenary (tram & elrail)
1269  *
1270  */
1271 
1272  static const int _tunnel_BB[4][12] = {
1273  /* tunnnel-roof | Z-separator | tram-catenary
1274  * w h bb_x bb_y| x y w h |bb_x bb_y w h */
1275  { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // NE
1276  { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // SE
1277  { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // SW
1278  { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // NW
1279  };
1280  const int *BB_data = _tunnel_BB[tunnelbridge_direction];
1281 
1282  bool catenary = false;
1283 
1284  SpriteID image;
1285  SpriteID railtype_overlay = 0;
1286  if (transport_type == TRANSPORT_RAIL) {
1287  const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1288  image = rti->base_sprites.tunnel;
1289  if (rti->UsesOverlay()) {
1290  /* Check if the railtype has custom tunnel portals. */
1291  railtype_overlay = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL_PORTAL);
1292  if (railtype_overlay != 0) image = SPR_RAILTYPE_TUNNEL_BASE; // Draw blank grass tunnel base.
1293  }
1294  } else {
1295  image = SPR_TUNNEL_ENTRY_REAR_ROAD;
1296  }
1297 
1298  if (HasTunnelBridgeSnowOrDesert(ti->tile)) image += railtype_overlay != 0 ? 8 : 32;
1299 
1300  image += tunnelbridge_direction * 2;
1301  DrawGroundSprite(image, PAL_NONE);
1302 
1303  if (transport_type == TRANSPORT_ROAD) {
1304  RoadType road_rt = GetRoadTypeRoad(ti->tile);
1305  RoadType tram_rt = GetRoadTypeTram(ti->tile);
1306  const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
1307  const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
1308  uint sprite_offset = DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? 1 : 0;
1309  bool draw_underlay = true;
1310 
1311  /* Road underlay takes precedence over tram */
1312  if (road_rti != nullptr) {
1313  if (road_rti->UsesOverlay()) {
1314  SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_TUNNEL);
1315  if (ground != 0) {
1316  DrawGroundSprite(ground + tunnelbridge_direction, PAL_NONE);
1317  draw_underlay = false;
1318  }
1319  }
1320  } else {
1321  if (tram_rti->UsesOverlay()) {
1322  SpriteID ground = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_TUNNEL);
1323  if (ground != 0) {
1324  DrawGroundSprite(ground + tunnelbridge_direction, PAL_NONE);
1325  draw_underlay = false;
1326  }
1327  }
1328  }
1329 
1330  DrawRoadOverlays(ti, PAL_NONE, road_rti, tram_rti, sprite_offset, sprite_offset, draw_underlay);
1331 
1332  /* Road catenary takes precedence over tram */
1333  SpriteID catenary_sprite_base = 0;
1334  if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
1335  catenary_sprite_base = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_CATENARY_FRONT);
1336  if (catenary_sprite_base == 0) {
1337  catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
1338  } else {
1339  catenary_sprite_base += 19;
1340  }
1341  } else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
1342  catenary_sprite_base = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_CATENARY_FRONT);
1343  if (catenary_sprite_base == 0) {
1344  catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
1345  } else {
1346  catenary_sprite_base += 19;
1347  }
1348  }
1349 
1350  if (catenary_sprite_base != 0) {
1351  catenary = true;
1353  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);
1354  }
1355  } else {
1356  const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1357  if (rti->UsesOverlay()) {
1358  SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL);
1359  if (surface != 0) DrawGroundSprite(surface + tunnelbridge_direction, PAL_NONE);
1360  }
1361 
1362  /* PBS debugging, draw reserved tracks darker */
1363  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1364  if (rti->UsesOverlay()) {
1365  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1366  DrawGroundSprite(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH);
1367  } else {
1368  DrawGroundSprite(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH);
1369  }
1370  }
1371 
1373  /* Maybe draw pylons on the entry side */
1374  DrawRailCatenary(ti);
1375 
1376  catenary = true;
1378  /* Draw wire above the ramp */
1380  }
1381  }
1382 
1383  if (railtype_overlay != 0 && !catenary) StartSpriteCombine();
1384 
1385  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);
1386  /* Draw railtype tunnel portal overlay if defined. */
1387  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);
1388 
1389  if (catenary || railtype_overlay != 0) EndSpriteCombine();
1390 
1391  /* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
1392  AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x, ti->y, BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
1393  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);
1394 
1395  DrawBridgeMiddle(ti);
1396  } else { // IsBridge(ti->tile)
1397  const PalSpriteID *psid;
1398  int base_offset;
1399  bool ice = HasTunnelBridgeSnowOrDesert(ti->tile);
1400 
1401  if (transport_type == TRANSPORT_RAIL) {
1402  base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
1403  assert(base_offset != 8); // This one is used for roads
1404  } else {
1405  base_offset = 8;
1406  }
1407 
1408  /* as the lower 3 bits are used for other stuff, make sure they are clear */
1409  assert( (base_offset & 0x07) == 0x00);
1410 
1411  DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(tunnelbridge_direction)));
1412 
1413  /* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
1414  base_offset += (6 - tunnelbridge_direction) % 4;
1415 
1416  /* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
1417  if (transport_type != TRANSPORT_WATER) {
1418  if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
1419  psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD)[base_offset];
1420  } else {
1421  psid = _aqueduct_sprites + base_offset;
1422  }
1423 
1424  if (!ice) {
1425  TileIndex next = ti->tile + TileOffsByDiagDir(tunnelbridge_direction);
1426  if (ti->tileh != SLOPE_FLAT && ti->z == 0 && HasTileWaterClass(next) && GetWaterClass(next) == WATER_CLASS_SEA) {
1427  DrawShoreTile(ti->tileh);
1428  } else {
1429  DrawClearLandTile(ti, 3);
1430  }
1431  } else {
1432  DrawGroundSprite(SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
1433  }
1434 
1435  /* draw ramp */
1436 
1437  /* Draw Trambits and PBS Reservation as SpriteCombine */
1438  if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1439 
1440  /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1441  * it doesn't disappear behind it
1442  */
1443  /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1444  AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
1445 
1446  if (transport_type == TRANSPORT_ROAD) {
1447  uint offset = tunnelbridge_direction;
1448  int z = ti->z;
1449  if (ti->tileh != SLOPE_FLAT) {
1450  offset = (offset + 1) & 1;
1451  z += TILE_HEIGHT;
1452  } else {
1453  offset += 2;
1454  }
1455 
1456  /* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
1457  DrawBridgeRoadBits(ti->tile, ti->x, ti->y, z, offset, true);
1458 
1459  EndSpriteCombine();
1460  } else if (transport_type == TRANSPORT_RAIL) {
1461  const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1462  if (rti->UsesOverlay()) {
1463  SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE);
1464  if (surface != 0) {
1465  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1466  AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1467  } else {
1468  AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, 16, 16, 8, ti->z);
1469  }
1470  }
1471  /* Don't fallback to non-overlay sprite -- the spec states that
1472  * if an overlay is present then the bridge surface must be
1473  * present. */
1474  }
1475 
1476  /* PBS debugging, draw reserved tracks darker */
1477  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1478  if (rti->UsesOverlay()) {
1479  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1480  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1481  AddSortableSpriteToDraw(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1482  } else {
1483  AddSortableSpriteToDraw(overlay + RTO_SLOPE_NE + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1484  }
1485  } else {
1486  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1487  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);
1488  } else {
1489  AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1490  }
1491  }
1492  }
1493 
1494  EndSpriteCombine();
1496  DrawRailCatenary(ti);
1497  }
1498  }
1499 
1500  DrawBridgeMiddle(ti);
1501  }
1502 }
1503 
1504 
1523 static BridgePieces CalcBridgePiece(uint north, uint south)
1524 {
1525  if (north == 1) {
1526  return BRIDGE_PIECE_NORTH;
1527  } else if (south == 1) {
1528  return BRIDGE_PIECE_SOUTH;
1529  } else if (north < south) {
1530  return north & 1 ? BRIDGE_PIECE_INNER_SOUTH : BRIDGE_PIECE_INNER_NORTH;
1531  } else if (north > south) {
1532  return south & 1 ? BRIDGE_PIECE_INNER_NORTH : BRIDGE_PIECE_INNER_SOUTH;
1533  } else {
1534  return north & 1 ? BRIDGE_PIECE_MIDDLE_EVEN : BRIDGE_PIECE_MIDDLE_ODD;
1535  }
1536 }
1537 
1543 {
1544  /* Sectional view of bridge bounding boxes:
1545  *
1546  * 1 2 1,2 = SpriteCombine of Bridge front/(back&floor) and RoadCatenary
1547  * 1 2 3 = empty helper BB
1548  * 1 7 2 4,5 = pillars under higher bridges
1549  * 1 6 88888 6 2 6 = elrail-pylons
1550  * 1 6 88888 6 2 7 = elrail-wire
1551  * 1 6 88888 6 2 <- TILE_HEIGHT 8 = rail-vehicle on bridge
1552  * 3333333333333 <- BB_Z_SEPARATOR
1553  * <- unused
1554  * 4 5 <- BB_HEIGHT_UNDER_BRIDGE
1555  * 4 5
1556  * 4 5
1557  *
1558  */
1559 
1560  if (!IsBridgeAbove(ti->tile)) return;
1561 
1562  TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile);
1563  TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile);
1564  TransportType transport_type = GetTunnelBridgeTransportType(rampsouth);
1565 
1566  Axis axis = GetBridgeAxis(ti->tile);
1567  BridgePieces piece = CalcBridgePiece(
1568  GetTunnelBridgeLength(ti->tile, rampnorth) + 1,
1569  GetTunnelBridgeLength(ti->tile, rampsouth) + 1
1570  );
1571 
1572  const PalSpriteID *psid;
1573  bool drawfarpillar;
1574  if (transport_type != TRANSPORT_WATER) {
1575  BridgeType type = GetBridgeType(rampsouth);
1576  drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
1577 
1578  uint base_offset;
1579  if (transport_type == TRANSPORT_RAIL) {
1580  base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
1581  } else {
1582  base_offset = 8;
1583  }
1584 
1585  psid = base_offset + GetBridgeSpriteTable(type, piece);
1586  } else {
1587  drawfarpillar = true;
1588  psid = _aqueduct_sprites;
1589  }
1590 
1591  if (axis != AXIS_X) psid += 4;
1592 
1593  int x = ti->x;
1594  int y = ti->y;
1595  uint bridge_z = GetBridgePixelHeight(rampsouth);
1596  int z = bridge_z - BRIDGE_Z_START;
1597 
1598  /* Add a bounding box that separates the bridge from things below it. */
1599  AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
1600 
1601  /* Draw Trambits as SpriteCombine */
1602  if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1603 
1604  /* Draw floor and far part of bridge*/
1605  if (!IsInvisibilitySet(TO_BRIDGES)) {
1606  if (axis == AXIS_X) {
1607  AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1608  } else {
1609  AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1610  }
1611  }
1612 
1613  psid++;
1614 
1615  if (transport_type == TRANSPORT_ROAD) {
1616  /* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
1617  DrawBridgeRoadBits(rampsouth, x, y, bridge_z, axis ^ 1, false);
1618  } else if (transport_type == TRANSPORT_RAIL) {
1619  const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth));
1620  if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
1621  SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE);
1622  if (surface != 0) {
1623  AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1624  }
1625  }
1626 
1627  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
1628  if (rti->UsesOverlay()) {
1629  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1630  AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1631  } else {
1632  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));
1633  }
1634  }
1635 
1636  EndSpriteCombine();
1637 
1638  if (HasRailCatenaryDrawn(GetRailType(rampsouth))) {
1640  }
1641  }
1642 
1643  /* draw roof, the component of the bridge which is logically between the vehicle and the camera */
1644  if (!IsInvisibilitySet(TO_BRIDGES)) {
1645  if (axis == AXIS_X) {
1646  y += 12;
1647  if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
1648  } else {
1649  x += 12;
1650  if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
1651  }
1652  }
1653 
1654  /* Draw TramFront as SpriteCombine */
1655  if (transport_type == TRANSPORT_ROAD) EndSpriteCombine();
1656 
1657  /* Do not draw anything more if bridges are invisible */
1658  if (IsInvisibilitySet(TO_BRIDGES)) return;
1659 
1660  psid++;
1661  DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
1662 }
1663 
1664 
1665 static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y, bool ground_vehicle)
1666 {
1667  auto [tileh, z] = GetTilePixelSlope(tile);
1668 
1669  x &= 0xF;
1670  y &= 0xF;
1671 
1672  if (IsTunnel(tile)) {
1673  /* In the tunnel entrance? */
1674  if (ground_vehicle) return z;
1675  } else { // IsBridge(tile)
1678 
1679  /* On the bridge ramp? */
1680  if (ground_vehicle) {
1681  if (tileh != SLOPE_FLAT) return z + TILE_HEIGHT;
1682 
1683  switch (dir) {
1684  default: NOT_REACHED();
1685  case DIAGDIR_NE: tileh = SLOPE_NE; break;
1686  case DIAGDIR_SE: tileh = SLOPE_SE; break;
1687  case DIAGDIR_SW: tileh = SLOPE_SW; break;
1688  case DIAGDIR_NW: tileh = SLOPE_NW; break;
1689  }
1690  }
1691  }
1692 
1693  return z + GetPartialPixelZ(x, y, tileh);
1694 }
1695 
1696 static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
1697 {
1699 }
1700 
1701 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
1702 {
1704 
1705  if (IsTunnel(tile)) {
1706  td->str = (tt == TRANSPORT_RAIL) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD;
1707  } else { // IsBridge(tile)
1708  td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
1709  }
1710  td->owner[0] = GetTileOwner(tile);
1711 
1712  Owner road_owner = INVALID_OWNER;
1713  Owner tram_owner = INVALID_OWNER;
1714  RoadType road_rt = GetRoadTypeRoad(tile);
1715  RoadType tram_rt = GetRoadTypeTram(tile);
1716  if (road_rt != INVALID_ROADTYPE) {
1717  const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
1718  td->roadtype = rti->strings.name;
1719  td->road_speed = rti->max_speed / 2;
1720  road_owner = GetRoadOwner(tile, RTT_ROAD);
1721  }
1722  if (tram_rt != INVALID_ROADTYPE) {
1723  const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
1724  td->tramtype = rti->strings.name;
1725  td->tram_speed = rti->max_speed / 2;
1726  tram_owner = GetRoadOwner(tile, RTT_TRAM);
1727  }
1728 
1729  /* Is there a mix of owners? */
1730  if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
1731  (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
1732  uint i = 1;
1733  if (road_owner != INVALID_OWNER) {
1734  td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
1735  td->owner[i] = road_owner;
1736  i++;
1737  }
1738  if (tram_owner != INVALID_OWNER) {
1739  td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
1740  td->owner[i] = tram_owner;
1741  }
1742  }
1743 
1744  if (tt == TRANSPORT_RAIL) {
1745  const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
1746  td->rail_speed = rti->max_speed;
1747  td->railtype = rti->strings.name;
1748 
1749  if (!IsTunnel(tile)) {
1750  uint16_t spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1751  /* rail speed special-cases 0 as unlimited, hides display of limit etc. */
1752  if (spd == UINT16_MAX) spd = 0;
1753  if (td->rail_speed == 0 || spd < td->rail_speed) {
1754  td->rail_speed = spd;
1755  }
1756  }
1757  } else if (tt == TRANSPORT_ROAD && !IsTunnel(tile)) {
1758  uint16_t spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1759  /* road speed special-cases 0 as unlimited, hides display of limit etc. */
1760  if (spd == UINT16_MAX) spd = 0;
1761  if (road_rt != INVALID_ROADTYPE && (td->road_speed == 0 || spd < td->road_speed)) td->road_speed = spd;
1762  if (tram_rt != INVALID_ROADTYPE && (td->tram_speed == 0 || spd < td->tram_speed)) td->tram_speed = spd;
1763  }
1764 }
1765 
1766 
1767 static void TileLoop_TunnelBridge(TileIndex tile)
1768 {
1769  bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile);
1771  case LT_ARCTIC: {
1772  /* As long as we do not have a snow density, we want to use the density
1773  * from the entry edge. For tunnels this is the lowest point for bridges the highest point.
1774  * (Independent of foundations) */
1775  int z = IsBridge(tile) ? GetTileMaxZ(tile) : GetTileZ(tile);
1776  if (snow_or_desert != (z > GetSnowLine())) {
1777  SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
1778  MarkTileDirtyByTile(tile);
1779  }
1780  break;
1781  }
1782 
1783  case LT_TROPIC:
1784  if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
1785  SetTunnelBridgeSnowOrDesert(tile, true);
1786  MarkTileDirtyByTile(tile);
1787  }
1788  break;
1789 
1790  default:
1791  break;
1792  }
1793 }
1794 
1795 static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
1796 {
1797  TransportType transport_type = GetTunnelBridgeTransportType(tile);
1798  if (transport_type != mode || (transport_type == TRANSPORT_ROAD && !HasTileRoadType(tile, (RoadTramType)sub_mode))) return 0;
1799 
1801  if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
1803 }
1804 
1805 static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
1806 {
1807  TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
1808  /* Set number of pieces to zero if it's the southern tile as we
1809  * don't want to update the infrastructure counts twice. */
1810  uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
1811 
1812  for (RoadTramType rtt : _roadtramtypes) {
1813  /* Update all roadtypes, no matter if they are present */
1814  if (GetRoadOwner(tile, rtt) == old_owner) {
1815  RoadType rt = GetRoadType(tile, rtt);
1816  if (rt != INVALID_ROADTYPE) {
1817  /* Update company infrastructure counts. A full diagonal road tile has two road bits.
1818  * No need to dirty windows here, we'll redraw the whole screen anyway. */
1819  Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2;
1820  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2;
1821  }
1822 
1823  SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
1824  }
1825  }
1826 
1827  if (!IsTileOwner(tile, old_owner)) return;
1828 
1829  /* Update company infrastructure counts for rail and water as well.
1830  * No need to dirty windows here, we'll redraw the whole screen anyway. */
1832  Company *old = Company::Get(old_owner);
1833  if (tt == TRANSPORT_RAIL) {
1834  old->infrastructure.rail[GetRailType(tile)] -= num_pieces;
1835  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += num_pieces;
1836  } else if (tt == TRANSPORT_WATER) {
1837  old->infrastructure.water -= num_pieces;
1838  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.water += num_pieces;
1839  }
1840 
1841  if (new_owner != INVALID_OWNER) {
1842  SetTileOwner(tile, new_owner);
1843  } else {
1844  if (tt == TRANSPORT_RAIL) {
1845  /* Since all of our vehicles have been removed, it is safe to remove the rail
1846  * bridge / tunnel. */
1847  [[maybe_unused]] CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC | DC_BANKRUPT, tile);
1848  assert(ret.Succeeded());
1849  } else {
1850  /* In any other case, we can safely reassign the ownership to OWNER_NONE. */
1851  SetTileOwner(tile, OWNER_NONE);
1852  }
1853  }
1854 }
1855 
1868 template <typename T>
1869 static void PrepareToEnterBridge(T *gv)
1870 {
1871  if (HasBit(gv->gv_flags, GVF_GOINGUP_BIT)) {
1872  gv->z_pos++;
1873  ClrBit(gv->gv_flags, GVF_GOINGUP_BIT);
1874  } else {
1875  ClrBit(gv->gv_flags, GVF_GOINGDOWN_BIT);
1876  }
1877 }
1878 
1884 static const uint8_t TUNNEL_SOUND_FRAME = 1;
1885 
1894 extern const uint8_t _tunnel_visibility_frame[DIAGDIR_END] = {12, 8, 8, 12};
1895 
1896 static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
1897 {
1898  int z = GetSlopePixelZ(x, y, true) - v->z_pos;
1899 
1900  if (abs(z) > 2) return VETSB_CANNOT_ENTER;
1901  /* Direction into the wormhole */
1902  const DiagDirection dir = GetTunnelBridgeDirection(tile);
1903  /* Direction of the vehicle */
1904  const DiagDirection vdir = DirToDiagDir(v->direction);
1905  /* New position of the vehicle on the tile */
1906  uint8_t pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK;
1907  /* Number of units moved by the vehicle since entering the tile */
1908  uint8_t frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
1909 
1910  if (IsTunnel(tile)) {
1911  if (v->type == VEH_TRAIN) {
1912  Train *t = Train::From(v);
1913 
1914  if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
1915  if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) {
1916  if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
1917  SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
1918  }
1919  return VETSB_CONTINUE;
1920  }
1921  if (frame == _tunnel_visibility_frame[dir]) {
1922  t->tile = tile;
1923  t->track = TRACK_BIT_WORMHOLE;
1924  t->vehstatus |= VS_HIDDEN;
1925  return VETSB_ENTERED_WORMHOLE;
1926  }
1927  }
1928 
1929  if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1930  /* We're at the tunnel exit ?? */
1931  t->tile = tile;
1932  t->track = DiagDirToDiagTrackBits(vdir);
1933  assert(t->track);
1934  t->vehstatus &= ~VS_HIDDEN;
1935  return VETSB_ENTERED_WORMHOLE;
1936  }
1937  } else if (v->type == VEH_ROAD) {
1938  RoadVehicle *rv = RoadVehicle::From(v);
1939 
1940  /* Enter tunnel? */
1941  if (rv->state != RVSB_WORMHOLE && dir == vdir) {
1942  if (frame == _tunnel_visibility_frame[dir]) {
1943  /* Frame should be equal to the next frame number in the RV's movement */
1944  assert(frame == rv->frame + 1);
1945  rv->tile = tile;
1946  rv->state = RVSB_WORMHOLE;
1947  rv->vehstatus |= VS_HIDDEN;
1948  return VETSB_ENTERED_WORMHOLE;
1949  } else {
1950  return VETSB_CONTINUE;
1951  }
1952  }
1953 
1954  /* We're at the tunnel exit ?? */
1955  if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1956  rv->tile = tile;
1957  rv->state = DiagDirToDiagTrackdir(vdir);
1958  rv->frame = frame;
1959  rv->vehstatus &= ~VS_HIDDEN;
1960  return VETSB_ENTERED_WORMHOLE;
1961  }
1962  }
1963  } else { // IsBridge(tile)
1964  if (v->type != VEH_SHIP) {
1965  /* modify speed of vehicle */
1966  uint16_t spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1967 
1968  if (v->type == VEH_ROAD) spd *= 2;
1969  Vehicle *first = v->First();
1970  first->cur_speed = std::min(first->cur_speed, spd);
1971  }
1972 
1973  if (vdir == dir) {
1974  /* Vehicle enters bridge at the last frame inside this tile. */
1975  if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
1976  switch (v->type) {
1977  case VEH_TRAIN: {
1978  Train *t = Train::From(v);
1979  t->track = TRACK_BIT_WORMHOLE;
1981  break;
1982  }
1983 
1984  case VEH_ROAD: {
1985  RoadVehicle *rv = RoadVehicle::From(v);
1986  rv->state = RVSB_WORMHOLE;
1988  break;
1989  }
1990 
1991  case VEH_SHIP:
1993  break;
1994 
1995  default: NOT_REACHED();
1996  }
1997  return VETSB_ENTERED_WORMHOLE;
1998  } else if (vdir == ReverseDiagDir(dir)) {
1999  v->tile = tile;
2000  switch (v->type) {
2001  case VEH_TRAIN: {
2002  Train *t = Train::From(v);
2003  if (t->track == TRACK_BIT_WORMHOLE) {
2004  t->track = DiagDirToDiagTrackBits(vdir);
2005  return VETSB_ENTERED_WORMHOLE;
2006  }
2007  break;
2008  }
2009 
2010  case VEH_ROAD: {
2011  RoadVehicle *rv = RoadVehicle::From(v);
2012  if (rv->state == RVSB_WORMHOLE) {
2013  rv->state = DiagDirToDiagTrackdir(vdir);
2014  rv->frame = 0;
2015  return VETSB_ENTERED_WORMHOLE;
2016  }
2017  break;
2018  }
2019 
2020  case VEH_SHIP: {
2021  Ship *ship = Ship::From(v);
2022  if (ship->state == TRACK_BIT_WORMHOLE) {
2023  ship->state = DiagDirToDiagTrackBits(vdir);
2024  return VETSB_ENTERED_WORMHOLE;
2025  }
2026  break;
2027  }
2028 
2029  default: NOT_REACHED();
2030  }
2031  }
2032  }
2033  return VETSB_CONTINUE;
2034 }
2035 
2036 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2037 {
2039  DiagDirection direction = GetTunnelBridgeDirection(tile);
2040  Axis axis = DiagDirToAxis(direction);
2041  CommandCost res;
2042  auto [tileh_old, z_old] = GetTileSlopeZ(tile);
2043 
2044  /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
2045  if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
2046  CheckBridgeSlope(BRIDGE_PIECE_SOUTH, axis, tileh_old, z_old);
2047  res = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, axis, tileh_new, z_new);
2048  } else {
2049  CheckBridgeSlope(BRIDGE_PIECE_NORTH, axis, tileh_old, z_old);
2050  res = CheckBridgeSlope(BRIDGE_PIECE_NORTH, axis, tileh_new, z_new);
2051  }
2052 
2053  /* Surface slope is valid and remains unchanged? */
2054  if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2055  }
2056 
2057  return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
2058 }
2059 
2060 extern const TileTypeProcs _tile_type_tunnelbridge_procs = {
2061  DrawTile_TunnelBridge, // draw_tile_proc
2062  GetSlopePixelZ_TunnelBridge, // get_slope_z_proc
2063  ClearTile_TunnelBridge, // clear_tile_proc
2064  nullptr, // add_accepted_cargo_proc
2065  GetTileDesc_TunnelBridge, // get_tile_desc_proc
2066  GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc
2067  nullptr, // click_tile_proc
2068  nullptr, // animate_tile_proc
2069  TileLoop_TunnelBridge, // tile_loop_proc
2070  ChangeTileOwner_TunnelBridge, // change_tile_owner_proc
2071  nullptr, // add_produced_cargo_proc
2072  VehicleEnter_TunnelBridge, // vehicle_enter_tile_proc
2073  GetFoundation_TunnelBridge, // get_foundation_proc
2074  TerraformTile_TunnelBridge, // terraform_tile_proc
2075 };
Functions related to autoslope.
bool AutoslopeEnabled()
Tests if autoslope is enabled for _current_company.
Definition: autoslope.h:65
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
BridgePieces
This enum is related to the definition of bridge pieces, which is used to determine the proper sprite...
Definition: bridge.h:22
uint BridgeType
Bridge spec number.
Definition: bridge.h:37
static const uint MAX_BRIDGES
Maximal number of available bridge specs.
Definition: bridge.h:35
const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition: bridge.h:66
This file contains all the sprites for bridges It consists of a number of arrays.
TileIndex GetSouthernBridgeEnd(TileIndex t)
Finds the southern end of a bridge starting at a middle tile.
Definition: bridge_map.cpp:49
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
Definition: bridge_map.cpp:59
TileIndex GetNorthernBridgeEnd(TileIndex t)
Finds the northern end of a bridge starting at a middle tile.
Definition: bridge_map.cpp:39
int GetBridgeHeight(TileIndex t)
Get the height ('z') of a bridge.
Definition: bridge_map.cpp:70
void SetBridgeMiddle(Tile t, Axis a)
Set that there is a bridge over the given axis.
Definition: bridge_map.h:114
void MakeAqueductBridgeRamp(Tile t, Owner o, DiagDirection d)
Make a bridge ramp for aqueducts.
Definition: bridge_map.h:181
bool IsBridgeTile(Tile t)
checks if there is a bridge on this tile
Definition: bridge_map.h:35
void MakeRailBridgeRamp(Tile t, Owner o, BridgeType bridgetype, DiagDirection d, RailType rt)
Make a bridge ramp for rails.
Definition: bridge_map.h:169
int GetBridgePixelHeight(TileIndex tile)
Get the height ('z') of a bridge in pixels.
Definition: bridge_map.h:84
void ClearBridgeMiddle(Tile t)
Removes bridges from the given, that is bridges along the X and Y axis.
Definition: bridge_map.h:103
void MakeRoadBridgeRamp(Tile t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadType road_rt, RoadType tram_rt)
Make a bridge ramp for roads.
Definition: bridge_map.h:153
BridgeType GetBridgeType(Tile t)
Determines the type of bridge on a tile.
Definition: bridge_map.h:56
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition: bridge_map.h:45
Axis GetBridgeAxis(Tile t)
Get the axis of the bridge that goes over the tile.
Definition: bridge_map.h:68
bool IsBridge(Tile t)
Checks if this is a bridge, instead of a tunnel.
Definition: bridge_map.h:24
Cheats _cheats
All the cheats.
Definition: cheat.cpp:16
Types related to cheating.
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:63
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
bool Failed() const
Did this command fail?
Definition: command_type.h:171
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:127
SpriteID single_x
single piece of rail in X direction, without ground
Definition: rail.h:137
SpriteID bridge_offset
Bridge offset.
Definition: rail.h:196
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:231
struct RailTypeInfo::@23 base_sprites
Struct containing the main sprites.
struct RailTypeInfo::@26 strings
Strings associated with the rail type.
SpriteID single_y
single piece of rail in Y direction, without ground
Definition: rail.h:138
StringID name
Name of this rail type.
Definition: rail.h:176
SpriteID tunnel
tunnel sprites base
Definition: rail.h:145
SpriteID single_sloped
single piece of rail for slopes
Definition: rail.h:143
struct RoadTypeInfo::@29 strings
Strings associated with the rail type.
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition: road.h:142
StringID name
Name of this rail type.
Definition: road.h:103
static Year year
Current year, starting at 0.
Functions related to clear (MP_CLEAR) land.
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:38
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_AUTO
don't allow building on structures
Definition: command_type.h:377
@ DC_BANKRUPT
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:382
@ DC_QUERY_COST
query cost only, don't build.
Definition: command_type.h:378
@ DC_EXEC
execute the given command
Definition: command_type.h:376
Definition of stuff that is very close to a company, like the company struct itself.
CommandCost CheckTileOwnership(TileIndex tile)
Check whether the current owner owns the stuff on the given tile.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ INVALID_OWNER
An invalid owner.
Definition: company_type.h:29
@ OWNER_DEITY
The object is owned by a superuser / goal script.
Definition: company_type.h:27
@ OWNER_NONE
The tile has no ownership.
Definition: company_type.h:25
@ OWNER_WATER
The tile/execution is done by "water".
Definition: company_type.h:26
@ OWNER_TOWN
A town owns the tile, or a town is expanding.
Definition: company_type.h:24
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection AxisToDiagDir(Axis a)
Converts an Axis to a DiagDirection.
Axis OtherAxis(Axis a)
Select the other axis as provided.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
Axis
Allow incrementing of DiagDirDiff variables.
@ AXIS_X
The X axis.
@ AXIS_Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_END
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
@ DIAGDIR_SW
Southwest.
@ EXPENSES_CONSTRUCTION
Construction costs.
Definition: economy_type.h:173
static const uint TUNNELBRIDGE_TRACKBIT_FACTOR
Multiplier for how many regular track bits a tunnel/bridge counts.
Definition: economy_type.h:241
Price
Enumeration of all base prices for use with Prices.
Definition: economy_type.h:89
void DrawRailCatenaryOnBridge(const TileInfo *ti)
Draws wires on a tunnel tile.
Definition: elrail.cpp:506
void DrawRailCatenaryOnTunnel(const TileInfo *ti)
Draws wires on a tunnel tile.
Definition: elrail.cpp:249
void DrawRailCatenary(const TileInfo *ti)
Draws overhead wires and pylons for electric railways.
Definition: elrail.cpp:568
header file for electrified rail specific functions
bool HasRailCatenaryDrawn(RailType rt)
Test if we should draw rail catenary.
Definition: elrail_func.h:30
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:18
@ GVF_GOINGDOWN_BIT
Vehicle is currently going downhill. (Cached track information for acceleration)
@ GVF_GOINGUP_BIT
Vehicle is currently going uphill. (Cached track information for acceleration)
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
Definition: landscape.cpp:609
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:2057
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Definition: landscape.cpp:228
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
Definition: landscape.cpp:425
void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int &z1, int &z2)
Determine the Z height of the corners of a specific tile edge.
Definition: landscape.cpp:354
uint ApplyFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition: landscape.cpp:170
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Definition: landscape.cpp:303
uint ApplyPixelFoundationToSlope(Foundation f, Slope &s)
Applies a foundation to a slope.
Definition: landscape.h:126
Command definitions related to landscape (slopes etc.).
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition: map.cpp:163
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition: map_func.h:552
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
int32_t TileIndexDiff
An offset value between two tiles.
Definition: map_type.h:23
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:23
constexpr void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:283
@ TCX_ON_BRIDGE
Querying information about stuff on the bridge (via some bridgehead).
@ TCX_NORMAL
Nothing special.
Functions related to NewGRF objects.
@ OBJECT_FLAG_ALLOW_UNDER_BRIDGE
Object can built under a bridge.
Definition: newgrf_object.h:37
SpriteID GetCustomRailSprite(const RailTypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
NewGRF handling of rail types.
SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context, uint *num_results)
Get the sprite to draw for the given tile.
NewGRF handling of road types.
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event, bool force)
Checks whether a NewGRF wants to play a different vehicle sound effect.
Functions related to NewGRF provided sounds.
@ VSE_TUNNEL
Train entering a tunnel.
Definition: newgrf_sound.h:20
Base for all objects.
ClearedObjectArea * FindClearedObject(TileIndex tile)
Find the entry in _cleared_object_areas which occupies a certain tile.
Definition: object_cmd.cpp:531
Train * GetTrainForReservation(TileIndex tile, Track track)
Find the train which has reserved a specific path.
Definition: pbs.cpp:330
PBS support routines.
bool ValParamRailType(const RailType rail)
Validate functions for rail building.
Definition: rail.cpp:206
@ RTSG_TUNNEL
Main group of ground images for snow or desert.
Definition: rail.h:53
@ RTSG_OVERLAY
Images for overlaying track.
Definition: rail.h:51
@ RTSG_BRIDGE
Bridge surface images.
Definition: rail.h:56
@ RTSG_TUNNEL_PORTAL
Tunnel portal overlay.
Definition: rail.h:60
@ RTBO_Y
Piece of rail in Y direction.
Definition: rail.h:94
@ RTBO_X
Piece of rail in X direction.
Definition: rail.h:93
@ RTBO_SLOPE
Sloped rail pieces, in order NE, SE, SW, NW.
Definition: rail.h:95
Money RailClearCost(RailType railtype)
Returns the 'cost' of clearing the specified railtype.
Definition: rail.h:386
Money RailBuildCost(RailType railtype)
Returns the cost of building the specified railtype.
Definition: rail.h:375
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:307
@ RTO_SLOPE_NE
Piece of rail on slope with north-east raised.
Definition: rail.h:77
@ RTO_X
Piece of rail in X direction.
Definition: rail.h:71
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition: rail_map.h:115
static debug_inline bool IsPlainRail(Tile t)
Returns whether this is plain rails, with or without signals.
Definition: rail_map.h:49
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:27
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition: rail_type.h:34
bool ValParamRoadType(RoadType roadtype)
Validate functions for rail building.
Definition: road.cpp:153
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition: road.h:227
Money RoadClearCost(RoadType roadtype)
Returns the cost of clearing the specified roadtype.
Definition: road.h:263
@ ROTSG_OVERLAY
Optional: Images for overlaying track.
Definition: road.h:61
@ ROTSG_CATENARY_BACK
Optional: Catenary back.
Definition: road.h:65
@ ROTSG_BRIDGE
Required: Bridge surface images.
Definition: road.h:66
@ ROTSG_CATENARY_FRONT
Optional: Catenary front.
Definition: road.h:64
@ ROTSG_TUNNEL
Optional: Ground images for tunnels.
Definition: road.h:63
Money RoadBuildCost(RoadType roadtype)
Returns the cost of building the specified roadtype.
Definition: road.h:252
void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count)
Update road infrastructure counts for a company.
Definition: road_cmd.cpp:190
void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rti, uint road_offset, uint tram_offset, bool draw_underlay)
Draw road underlay and overlay sprites.
Definition: road_cmd.cpp:1515
bool HasRoadCatenaryDrawn(RoadType roadtype)
Test if we should draw road catenary.
Definition: road_func.h:145
void SetRoadOwner(Tile t, RoadTramType rtt, Owner o)
Set the owner of a specific road type.
Definition: road_map.h:251
static debug_inline bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition: road_map.h:74
static debug_inline bool IsRoadDepot(Tile t)
Return whether a tile is a road depot.
Definition: road_map.h:106
bool HasTileRoadType(Tile t, RoadTramType rtt)
Check if a tile has a road or a tram road type.
Definition: road_map.h:211
Roadside GetRoadside(Tile tile)
Get the decorations of a road.
Definition: road_map.h:493
Owner GetRoadOwner(Tile t, RoadTramType rtt)
Get the owner of a specific road type.
Definition: road_map.h:234
void SetRoadside(Tile tile, Roadside s)
Set the decorations of a road.
Definition: road_map.h:503
@ ROADSIDE_PAVED
Road with paved sidewalks.
Definition: road_map.h:480
@ ROADSIDE_TREES
Road with trees on paved sidewalks.
Definition: road_map.h:483
RoadType
The different roadtypes we support.
Definition: road_type.h:25
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition: road_type.h:30
Road vehicle states.
@ RVSB_WORMHOLE
The vehicle is in a tunnel and/or bridge.
Definition: roadveh.h:39
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
Base for ships.
void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner)
Add side of tile to signal update buffer.
Definition: signal.cpp:624
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition: slope_func.h:415
bool HasSlopeHighestCorner(Slope s)
Tests if a slope has a highest corner (i.e.
Definition: slope_func.h:113
Foundation FlatteningFoundation(Slope s)
Returns the foundation needed to flatten a slope.
Definition: slope_func.h:369
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition: slope_func.h:239
Foundation InclinedFoundation(Axis axis)
Returns the along a specific axis inclined foundation.
Definition: slope_func.h:380
Slope ComplementSlope(Slope s)
Return the complement of a slope.
Definition: slope_func.h:76
Slope
Enumeration for the slope-type.
Definition: slope_type.h:48
@ SLOPE_SW
south and west corner are raised
Definition: slope_type.h:56
@ SLOPE_FLAT
a flat tile
Definition: slope_type.h:49
@ SLOPE_NE
north and east corner are raised
Definition: slope_type.h:58
@ SLOPE_SE
south and east corner are raised
Definition: slope_type.h:57
@ SLOPE_NW
north and west corner are raised
Definition: slope_type.h:55
Foundation
Enumeration for Foundations.
Definition: slope_type.h:93
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition: slope_type.h:94
Functions related to sound.
@ SND_05_TRAIN_THROUGH_TUNNEL
3 == 0x03 Train enters tunnel: steam engine
Definition: sound_type.h:42
static constexpr uint32_t SPRITE_MASK
The mask to for the main sprite.
Definition: sprites.h:1556
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1605
static const SpriteID SPR_RAILTYPE_TUNNEL_BASE
Tunnel sprites with grass only for custom railtype tunnel.
Definition: sprites.h:299
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
Definition: sprites.h:272
Functions related to stations.
Definition of base types and functions in a cross-platform compatible way.
void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:334
#define lengthof(array)
Return the length of an fixed size array.
Definition: stdafx.h:280
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
Functions related to OTTD's strings.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
Struct containing information about a single bridge type.
Definition: bridge.h:42
uint8_t min_length
the minimum length (not counting start and end tile)
Definition: bridge.h:44
TimerGameCalendar::Year avail_year
the year where it becomes available
Definition: bridge.h:43
PalSpriteID ** sprite_table
table of sprites for drawing the bridge
Definition: bridge.h:52
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition: bridge.h:47
uint16_t max_length
the maximum length (not counting start and end tile)
Definition: bridge.h:45
bool value
tells if the bool cheat is active or not
Definition: cheat_type.h:18
Cheat crossing_tunnels
allow tunnels that cross each other
Definition: cheat_type.h:30
Cheat magic_bulldozer
dynamite industries, objects
Definition: cheat_type.h:27
Keeps track of removed objects during execution/testruns of commands.
Definition: object_base.h:84
TileIndex first_tile
The first tile being cleared, which then causes the whole object to be cleared.
Definition: object_base.h:85
GUISettings gui
settings related to the GUI
std::array< uint32_t, ROADTYPE_END > road
Count of company owned track bits for each road type.
Definition: company_base.h:34
std::array< uint32_t, RAILTYPE_END > rail
Count of company owned track bits for each rail type.
Definition: company_base.h:33
uint32_t water
Count of company owned track bits for canals.
Definition: company_base.h:36
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Definition: company_base.h:112
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition: company_base.h:147
uint8_t max_bridge_height
maximum height of bridges
bool build_on_slopes
allow building on slopes
bool extra_dynamite
extra dynamite
uint16_t max_bridge_length
maximum length of bridges
uint16_t max_tunnel_length
maximum length of tunnels
bool show_track_reservation
highlight reserved tracks.
uint8_t landscape
the landscape we're currently in
ConstructionSettings construction
construction of things in-game
GameCreationSettings game_creation
settings used during the creation of a game (map)
static debug_inline uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition: map_func.h:297
Allow incrementing of ObjectClassID variables.
Definition: newgrf_object.h:60
static const ObjectSpec * GetByTile(TileIndex tile)
Get the specification associated with a tile.
ObjectFlags flags
Flags/settings related to the object.
Definition: newgrf_object.h:72
uint8_t height
The height of this structure, in heightlevels; max MAX_TILE_HEIGHT.
Definition: newgrf_object.h:74
Combination of a palette sprite and a 'real' sprite.
Definition: gfx_type.h:23
SpriteID sprite
The 'real' sprite.
Definition: gfx_type.h:24
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:25
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
EngineClass engclass
Class of engine for this vehicle.
Definition: engine_type.h:54
Buses, trucks and trams belong to this class.
Definition: roadveh.h:98
uint8_t state
Definition: roadveh.h:100
All ships have this type.
Definition: ship.h:32
TrackBits state
The "track" the ship is following.
Definition: ship.h:34
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Used to only draw a part of the sprite.
Definition: gfx_type.h:231
Tile description for the 'land area information' tool.
Definition: tile_cmd.h:52
uint16_t rail_speed
Speed limit of rail (bridges and track)
Definition: tile_cmd.h:65
StringID str
Description of the tile.
Definition: tile_cmd.h:53
uint16_t tram_speed
Speed limit of tram (bridges and track)
Definition: tile_cmd.h:69
StringID roadtype
Type of road on the tile.
Definition: tile_cmd.h:66
StringID tramtype
Type of tram on the tile.
Definition: tile_cmd.h:68
StringID railtype
Type of rail on the tile.
Definition: tile_cmd.h:64
uint16_t road_speed
Speed limit of road (bridges and track)
Definition: tile_cmd.h:67
Owner owner[4]
Name of the owner(s)
Definition: tile_cmd.h:55
StringID owner_type[4]
Type of each owner.
Definition: tile_cmd.h:56
Tile information, used while rendering the tile.
Definition: tile_cmd.h:43
int z
Height.
Definition: tile_cmd.h:48
int x
X position of the tile in unit coordinates.
Definition: tile_cmd.h:44
Slope tileh
Slope of the tile.
Definition: tile_cmd.h:46
TileIndex tile
Tile index.
Definition: tile_cmd.h:47
int y
Y position of the tile in unit coordinates.
Definition: tile_cmd.h:45
Set of callback functions for performing tile operations of a given tile type.
Definition: tile_cmd.h:158
std::array< uint32_t, HZB_END > squared_town_zone_radius
UpdateTownRadius updates this given the house count.
Definition: town.h:47
Town data structure.
Definition: town.h:54
TileIndex xy
town center tile
Definition: town.h:55
TownCache cache
Container for all cacheable data.
Definition: town.h:57
'Train' is either a loco or a wagon.
Definition: train.h:89
Vehicle data structure.
Definition: vehicle_base.h:244
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:323
int32_t z_pos
z coordinate.
Definition: vehicle_base.h:306
Direction direction
facing
Definition: vehicle_base.h:307
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:645
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:945
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
uint16_t cur_speed
current speed
Definition: vehicle_base.h:328
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
Command definitions related to terraforming.
VehicleEnterTileStatus
The returned bits of VehicleEnterTile.
Definition: tile_cmd.h:21
@ VETSB_ENTERED_WORMHOLE
The vehicle either entered a bridge, tunnel or depot tile (this includes the last tile of the bridge/...
Definition: tile_cmd.h:37
@ VETSB_CANNOT_ENTER
The vehicle cannot enter the tile.
Definition: tile_cmd.h:38
@ VETSB_CONTINUE
Bit sets of the above specified bits.
Definition: tile_cmd.h:35
std::tuple< Slope, int > GetTileSlopeZ(TileIndex tile)
Return the slope of a given tile inside the map.
Definition: tile_map.cpp:55
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition: tile_map.cpp:136
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition: tile_map.cpp:116
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:214
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition: tile_map.h:178
void SetTileOwner(Tile tile, Owner owner)
Sets the owner of a tile.
Definition: tile_map.h:198
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition: tile_map.h:96
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition: tile_map.h:161
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition: tile_map.h:238
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition: tile_map.h:289
static debug_inline uint TileHeight(Tile tile)
Returns the height of a tile.
Definition: tile_map.h:29
@ TROPICZONE_DESERT
Tile is desert.
Definition: tile_type.h:78
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in #ZOOM_BASE.
Definition: tile_type.h:18
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
static const uint TILE_UNIT_MASK
For masking in/out the inner-tile world coordinate units.
Definition: tile_type.h:16
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
@ MP_ROAD
A tile with road (or tram tracks)
Definition: tile_type.h:50
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:57
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition: tile_type.h:48
@ MP_WATER
Water tile.
Definition: tile_type.h:54
@ MP_RAILWAY
A railway.
Definition: tile_type.h:49
@ MP_OBJECT
Contains objects such as transmitters and owned land.
Definition: tile_type.h:58
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition of the game-calendar-timer.
Base of the town class.
@ TUNNELBRIDGE_REMOVE
Removal of a tunnel or bridge owned by the towb.
Definition: town.h:177
Town * CalcClosestTownFromTile(TileIndex tile, uint threshold=UINT_MAX)
Return the town closest to the given tile within threshold.
Definition: town_cmd.cpp:3852
void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags)
Changes town rating of the current company.
Definition: town_cmd.cpp:3949
CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type)
Does the town authority allow the (destructive) action of the current company?
Definition: town_cmd.cpp:3986
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
Definition: town_cmd.cpp:3870
static constexpr int RATING_TUNNEL_BRIDGE_UP_STEP
rating increase for improving a town-owned bridge
Definition: town_type.h:56
static constexpr int RATING_TUNNEL_BRIDGE_MINIMUM
minimum rating after removing tunnel or bridge
Definition: town_type.h:58
static constexpr int RATING_TUNNEL_BRIDGE_DOWN_STEP
penalty for removing town owned tunnel or bridge
Definition: town_type.h:57
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition: track_func.h:319
TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition: track_func.h:388
TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track bits incidating with that diagdir.
Definition: track_func.h:524
Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition: track_func.h:537
Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track AXIS_X -> TRACK_X AXIS_Y -> TRACK_Y Uses the fact that the...
Definition: track_func.h:66
Track DiagDirToDiagTrack(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track incidating with that diagdir.
Definition: track_func.h:512
@ TRACK_BIT_WORMHOLE
Bitflag for a wormhole (used for tunnels)
Definition: track_type.h:52
@ TRACKDIR_BIT_NONE
No track build.
Definition: track_type.h:99
Track
These are used to specify a single track.
Definition: track_type.h:19
Base for the train class.
bool TryPathReserve(Train *v, bool mark_as_stuck=false, bool first_tile_okay=false)
Try to reserve a path to a safe position.
Definition: train_cmd.cpp:2866
void FreeTrainTrackReservation(const Train *v)
Free the reserved path in front of a vehicle.
Definition: train_cmd.cpp:2386
@ TO_BRIDGES
bridges
Definition: transparency.h:28
@ TO_CATENARY
catenary
Definition: transparency.h:30
bool IsTransparencySet(TransparencyOption to)
Check if the transparency option bit is set and if we aren't in the game menu (there's never transpar...
Definition: transparency.h:48
bool IsInvisibilitySet(TransparencyOption to)
Check if the invisibility option bit is set and if we aren't in the game menu (there's never transpar...
Definition: transparency.h:59
TransportType
Available types of transport.
@ TRANSPORT_RAIL
Transport by train.
@ TRANSPORT_ROAD
Transport by road vehicle.
@ TRANSPORT_WATER
Transport over water.
bool IsTunnelInWayDir(TileIndex tile, int z, DiagDirection dir)
Is there a tunnel in the way in the given direction?
Definition: tunnel_map.cpp:48
TileIndex GetOtherTunnelEnd(TileIndex tile)
Gets the other end of the tunnel.
Definition: tunnel_map.cpp:22
void MakeRailTunnel(Tile t, Owner o, DiagDirection d, RailType r)
Makes a rail tunnel entrance.
Definition: tunnel_map.h:73
bool IsTunnel(Tile t)
Is this a tunnel (entrance)?
Definition: tunnel_map.h:23
void MakeRoadTunnel(Tile t, Owner o, DiagDirection d, RoadType road_rt, RoadType tram_rt)
Makes a road tunnel entrance.
Definition: tunnel_map.h:50
Header file for things common for tunnels and bridges.
uint GetTunnelBridgeLength(TileIndex begin, TileIndex end)
Calculates the length of a tunnel or a bridge (without end tiles)
Definition: tunnelbridge.h:25
CommandCost CmdBuildTunnel(DoCommandFlag flags, TileIndex start_tile, TransportType transport_type, uint8_t road_rail_type)
Build Tunnel.
static BridgePieces CalcBridgePiece(uint north, uint south)
Compute bridge piece.
static CommandCost CheckAllowRemoveTunnelBridge(TileIndex tile)
Are we allowed to remove the tunnel or bridge at tile?
static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
Remove a bridge from the game, update town rating, etc.
static Money TunnelBridgeClearCost(TileIndex tile, Price base_price)
Calculate the base cost of clearing a tunnel/bridge per tile.
void DrawBridgeMiddle(const TileInfo *ti)
Draw the middle bits of a bridge.
Foundation GetBridgeFoundation(Slope tileh, Axis axis)
Get the foundation for a bridge.
static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int offset, bool head)
Draws the road and trambits over an already drawn (lower end) of a bridge.
const uint8_t _tunnel_visibility_frame[DIAGDIR_END]
Frame when a vehicle should be hidden in a tunnel with a certain direction.
static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, int x, int y, int w, int h)
Draw two bridge pillars (north and south).
void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height)
Mark bridge tiles dirty.
CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags)
Is a bridge of the specified type and length available?
bool HasBridgeFlatRamp(Slope tileh, Axis axis)
Determines if the track on a bridge ramp is flat or goes up/down.
CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, uint8_t road_rail_type)
Build a Bridge.
static void DrawTile_TunnelBridge(TileInfo *ti)
Draws a tunnel of bridge tile.
static CommandCost ClearTile_TunnelBridge(TileIndex tile, DoCommandFlag flags)
Remove a tunnel or a bridge from the game.
static const int BRIDGE_Z_START
Z position of the bridge sprites relative to bridge height (downwards)
static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
Remove a tunnel from the game, update town rating, etc.
TileIndex _build_tunnel_endtile
The end of a tunnel; as hidden return from the tunnel build command for GUI purposes.
BridgeSpec _bridge[MAX_BRIDGES]
The specification of all bridges.
static void GetBridgeRoadCatenary(const RoadTypeInfo *rti, TileIndex head_tile, int offset, bool head, SpriteID &spr_back, SpriteID &spr_front)
Retrieve the sprites required for catenary on a road/tram bridge.
int CalcBridgeLenCostFactor(int length)
Calculate the price factor for building a long bridge.
static void PrepareToEnterBridge(T *gv)
Helper to prepare the ground vehicle when entering a bridge.
static void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
Draw a single pillar sprite.
void ResetBridges()
Reset the data been eventually changed by the grf loaded.
static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
Draws the pillars under high bridges.
static CommandCost CheckBridgeSlope(BridgePieces bridge_piece, Axis axis, Slope &tileh, int &z)
Determines the foundation for the bridge head, and tests if the resulting slope is valid.
static const uint8_t TUNNEL_SOUND_FRAME
Frame when the 'enter tunnel' sound should be played.
Command definitions related to tunnels and bridges.
Functions that have tunnels and bridges in common.
void SetTunnelBridgeSnowOrDesert(Tile t, bool snow_or_desert)
Tunnel: Places this tunnel entrance in a snowy or desert area, or takes it out of there.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
bool HasTunnelBridgeSnowOrDesert(Tile t)
Tunnel: Is this tunnel entrance in a snowy or desert area? Bridge: Does the bridge ramp lie in a snow...
bool HasTunnelBridgeReservation(Tile t)
Get the reservation state of the rail tunnel/bridge.
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
void SetTunnelBridgeReservation(Tile t, bool b)
Set the reservation state of the rail tunnel/bridge.
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition: vehicle.cpp:575
@ VS_HIDDEN
Vehicle is not visible.
Definition: vehicle_base.h:33
Functions related to vehicles.
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition: viewport.cpp:767
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition: viewport.cpp:671
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition: viewport.cpp:777
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition: viewport.cpp:587
Functions related to (drawing on) viewports.
static const uint BB_HEIGHT_UNDER_BRIDGE
Some values for constructing bounding boxes (BB).
Definition: viewport_type.h:88
static const uint BB_Z_SEPARATOR
Separates the bridge/tunnel from the things under/above it.
Definition: viewport_type.h:89
Functions related to water (management)
void CheckForDockingTile(TileIndex t)
Mark the supplied tile as a docking tile if it is suitable for docking.
Definition: water_cmd.cpp:195
bool HasTileWaterGround(Tile t)
Checks whether the tile has water at the ground.
Definition: water_map.h:350
@ WATER_CLASS_SEA
Sea.
Definition: water_map.h:40
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition: water_map.h:101
bool IsCoast(Tile t)
Is it a coast tile?
Definition: water_map.h:201
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition: water_map.h:112
bool IsWater(Tile t)
Is it a plain water tile?
Definition: water_map.h:147
Handles dividing the water in the map into regions to assist pathfinding.
Entry point for OpenTTD to YAPF's cache.
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track)
Use this function to notify YAPF that track layout (or signal configuration) has change.
Definition: yapf_rail.cpp:635