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