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