OpenTTD
tunnelbridge_cmd.cpp
Go to the documentation of this file.
1 /* $Id: tunnelbridge_cmd.cpp 27686 2016-12-09 21:27:22Z frosch $ */
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 "object_base.h"
41 #include "water.h"
42 #include "company_gui.h"
43 
44 #include "table/strings.h"
45 #include "table/bridge_land.h"
46 
47 #include "safeguards.h"
48 
51 
53 static const int BRIDGE_Z_START = 3;
54 
55 
64 void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height)
65 {
66  TileIndexDiff delta = TileOffsByDiagDir(direction);
67  for (TileIndex t = begin; t != end; t += delta) {
68  MarkTileDirtyByTile(t, bridge_height - TileHeight(t));
69  }
71 }
72 
78 {
80 }
81 
84 {
85  /* First, free sprite table data */
86  for (BridgeType i = 0; i < MAX_BRIDGES; i++) {
87  if (_bridge[i].sprite_table != NULL) {
88  for (BridgePieces j = BRIDGE_PIECE_NORTH; j < BRIDGE_PIECE_INVALID; j++) free(_bridge[i].sprite_table[j]);
89  free(_bridge[i].sprite_table);
90  }
91  }
92 
93  /* Then, wipe out current bridges */
94  memset(&_bridge, 0, sizeof(_bridge));
95  /* And finally, reinstall default data */
96  memcpy(&_bridge, &_orig_bridge, sizeof(_orig_bridge));
97 }
98 
105 int CalcBridgeLenCostFactor(int length)
106 {
107  if (length < 2) return length;
108 
109  length -= 2;
110  int sum = 2;
111  for (int delta = 1;; delta++) {
112  for (int count = 0; count < delta; count++) {
113  if (length == 0) return sum;
114  sum += delta;
115  length--;
116  }
117  }
118 }
119 
127 {
128  if (tileh == SLOPE_FLAT ||
129  ((tileh == SLOPE_NE || tileh == SLOPE_SW) && axis == AXIS_X) ||
130  ((tileh == SLOPE_NW || tileh == SLOPE_SE) && axis == AXIS_Y)) return FOUNDATION_NONE;
131 
132  return (HasSlopeHighestCorner(tileh) ? InclinedFoundation(axis) : FlatteningFoundation(tileh));
133 }
134 
142 bool HasBridgeFlatRamp(Slope tileh, Axis axis)
143 {
144  ApplyFoundationToSlope(GetBridgeFoundation(tileh, axis), &tileh);
145  /* If the foundation slope is flat the bridge has a non-flat ramp and vice versa. */
146  return (tileh != SLOPE_FLAT);
147 }
148 
149 static inline const PalSpriteID *GetBridgeSpriteTable(int index, BridgePieces table)
150 {
151  const BridgeSpec *bridge = GetBridgeSpec(index);
152  assert(table < BRIDGE_PIECE_INVALID);
153  if (bridge->sprite_table == NULL || bridge->sprite_table[table] == NULL) {
154  return _bridge_sprite_table[index][table];
155  } else {
156  return bridge->sprite_table[table];
157  }
158 }
159 
160 
169 static CommandCost CheckBridgeSlopeNorth(Axis axis, Slope *tileh, int *z)
170 {
171  Foundation f = GetBridgeFoundation(*tileh, axis);
172  *z += ApplyFoundationToSlope(f, tileh);
173 
174  Slope valid_inclined = (axis == AXIS_X ? SLOPE_NE : SLOPE_NW);
175  if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
176 
177  if (f == FOUNDATION_NONE) return CommandCost();
178 
179  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
180 }
181 
190 static CommandCost CheckBridgeSlopeSouth(Axis axis, Slope *tileh, int *z)
191 {
192  Foundation f = GetBridgeFoundation(*tileh, axis);
193  *z += ApplyFoundationToSlope(f, tileh);
194 
195  Slope valid_inclined = (axis == AXIS_X ? SLOPE_SW : SLOPE_SE);
196  if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
197 
198  if (f == FOUNDATION_NONE) return CommandCost();
199 
200  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
201 }
202 
209 CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags)
210 {
211  if (flags & DC_QUERY_COST) {
212  if (bridge_len <= _settings_game.construction.max_bridge_length) return CommandCost();
213  return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
214  }
215 
216  if (bridge_type >= MAX_BRIDGES) return CMD_ERROR;
217 
218  const BridgeSpec *b = GetBridgeSpec(bridge_type);
219  if (b->avail_year > _cur_year) return CMD_ERROR;
220 
222 
223  if (b->min_length > bridge_len) return CMD_ERROR;
224  if (bridge_len <= max) return CommandCost();
225  return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
226 }
227 
240 CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
241 {
242  CompanyID company = _current_company;
243 
244  RailType railtype = INVALID_RAILTYPE;
245  RoadTypes roadtypes = ROADTYPES_NONE;
246 
247  /* unpack parameters */
248  BridgeType bridge_type = GB(p2, 0, 8);
249 
250  if (!IsValidTile(p1)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
251 
252  TransportType transport_type = Extract<TransportType, 15, 2>(p2);
253 
254  /* type of bridge */
255  switch (transport_type) {
256  case TRANSPORT_ROAD:
257  roadtypes = Extract<RoadTypes, 8, 2>(p2);
258  if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(company, roadtypes)) return CMD_ERROR;
259  break;
260 
261  case TRANSPORT_RAIL:
262  railtype = Extract<RailType, 8, 4>(p2);
263  if (!ValParamRailtype(railtype)) return CMD_ERROR;
264  break;
265 
266  case TRANSPORT_WATER:
267  break;
268 
269  default:
270  /* Airports don't have bridges. */
271  return CMD_ERROR;
272  }
273  TileIndex tile_start = p1;
274  TileIndex tile_end = end_tile;
275 
276  if (company == OWNER_DEITY) {
277  if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
278  const Town *town = CalcClosestTownFromTile(tile_start);
279 
280  company = OWNER_TOWN;
281 
282  /* If we are not within a town, we are not owned by the town */
283  if (town == NULL || DistanceSquare(tile_start, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
284  company = OWNER_NONE;
285  }
286  }
287 
288  if (tile_start == tile_end) {
289  return_cmd_error(STR_ERROR_CAN_T_START_AND_END_ON);
290  }
291 
292  Axis direction;
293  if (TileX(tile_start) == TileX(tile_end)) {
294  direction = AXIS_Y;
295  } else if (TileY(tile_start) == TileY(tile_end)) {
296  direction = AXIS_X;
297  } else {
298  return_cmd_error(STR_ERROR_START_AND_END_MUST_BE_IN);
299  }
300 
301  if (tile_end < tile_start) Swap(tile_start, tile_end);
302 
303  uint bridge_len = GetTunnelBridgeLength(tile_start, tile_end);
304  if (transport_type != TRANSPORT_WATER) {
305  /* set and test bridge length, availability */
306  CommandCost ret = CheckBridgeAvailability(bridge_type, bridge_len, flags);
307  if (ret.Failed()) return ret;
308  } else {
309  if (bridge_len > _settings_game.construction.max_bridge_length) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
310  }
311 
312  int z_start;
313  int z_end;
314  Slope tileh_start = GetTileSlope(tile_start, &z_start);
315  Slope tileh_end = GetTileSlope(tile_end, &z_end);
316  bool pbs_reservation = false;
317 
318  CommandCost terraform_cost_north = CheckBridgeSlopeNorth(direction, &tileh_start, &z_start);
319  CommandCost terraform_cost_south = CheckBridgeSlopeSouth(direction, &tileh_end, &z_end);
320 
321  /* Aqueducts can't be built of flat land. */
322  if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
323  if (z_start != z_end) return_cmd_error(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT);
324 
326  Owner owner;
327  bool is_new_owner;
328  if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
329  GetOtherBridgeEnd(tile_start) == tile_end &&
330  GetTunnelBridgeTransportType(tile_start) == transport_type) {
331  /* Replace a current bridge. */
332 
333  /* If this is a railway bridge, make sure the railtypes match. */
334  if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
335  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
336  }
337 
338  /* Do not replace town bridges with lower speed bridges, unless in scenario editor. */
339  if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
340  GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed &&
341  _game_mode != GM_EDITOR) {
342  Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
343 
344  if (t == NULL) {
345  return CMD_ERROR;
346  } else {
347  SetDParam(0, t->index);
348  return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
349  }
350  }
351 
352  /* Do not replace the bridge with the same bridge type. */
353  if (!(flags & DC_QUERY_COST) && (bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || (roadtypes & ~GetRoadTypes(tile_start)) == 0)) {
354  return_cmd_error(STR_ERROR_ALREADY_BUILT);
355  }
356 
357  /* Do not allow replacing another company's bridges. */
358  if (!IsTileOwner(tile_start, company) && !IsTileOwner(tile_start, OWNER_TOWN) && !IsTileOwner(tile_start, OWNER_NONE)) {
359  return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
360  }
361 
362  cost.AddCost((bridge_len + 1) * _price[PR_CLEAR_BRIDGE]); // The cost of clearing the current bridge.
363  owner = GetTileOwner(tile_start);
364 
365  /* If bridge belonged to bankrupt company, it has a new owner now */
366  is_new_owner = (owner == OWNER_NONE);
367  if (is_new_owner) owner = company;
368 
369  switch (transport_type) {
370  case TRANSPORT_RAIL:
371  /* Keep the reservation, the path stays valid. */
372  pbs_reservation = HasTunnelBridgeReservation(tile_start);
373  break;
374 
375  case TRANSPORT_ROAD:
376  /* Do not remove road types when upgrading a bridge */
377  roadtypes |= GetRoadTypes(tile_start);
378  break;
379 
380  default: break;
381  }
382  } else {
383  /* Build a new bridge. */
384 
385  bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
386 
387  /* Try and clear the start landscape */
388  CommandCost ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
389  if (ret.Failed()) return ret;
390  cost = ret;
391 
392  if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
393  cost.AddCost(terraform_cost_north);
394 
395  /* Try and clear the end landscape */
396  ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
397  if (ret.Failed()) return ret;
398  cost.AddCost(ret);
399 
400  /* false - end tile slope check */
401  if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
402  cost.AddCost(terraform_cost_south);
403 
404  const TileIndex heads[] = {tile_start, tile_end};
405  for (int i = 0; i < 2; i++) {
406  if (IsBridgeAbove(heads[i])) {
407  TileIndex north_head = GetNorthernBridgeEnd(heads[i]);
408 
409  if (direction == GetBridgeAxis(heads[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
410 
411  if (z_start + 1 == GetBridgeHeight(north_head)) {
412  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
413  }
414  }
415  }
416 
417  TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
418  for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
419  if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN);
420 
421  if (z_start >= (GetTileZ(tile) + _settings_game.construction.max_bridge_height)) {
422  /*
423  * Disallow too high bridges.
424  * Properly rendering a map where very high bridges (might) exist is expensive.
425  * See http://www.tt-forums.net/viewtopic.php?f=33&t=40844&start=980#p1131762
426  * for a detailed discussion. z_start here is one heightlevel below the bridge level.
427  */
428  return_cmd_error(STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN);
429  }
430 
431  if (IsBridgeAbove(tile)) {
432  /* Disallow crossing bridges for the time being */
433  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
434  }
435 
436  switch (GetTileType(tile)) {
437  case MP_WATER:
438  if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
439  break;
440 
441  case MP_RAILWAY:
442  if (!IsPlainRail(tile)) goto not_valid_below;
443  break;
444 
445  case MP_ROAD:
446  if (IsRoadDepot(tile)) goto not_valid_below;
447  break;
448 
449  case MP_TUNNELBRIDGE:
450  if (IsTunnel(tile)) break;
451  if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below;
452  if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
453  break;
454 
455  case MP_OBJECT: {
456  const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
457  if ((spec->flags & OBJECT_FLAG_ALLOW_UNDER_BRIDGE) == 0) goto not_valid_below;
458  if (GetTileMaxZ(tile) + spec->height > z_start) goto not_valid_below;
459  break;
460  }
461 
462  case MP_CLEAR:
463  break;
464 
465  default:
466  not_valid_below:;
467  /* try and clear the middle landscape */
468  ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
469  if (ret.Failed()) return ret;
470  cost.AddCost(ret);
471  break;
472  }
473 
474  if (flags & DC_EXEC) {
475  /* We do this here because when replacing a bridge with another
476  * type calling SetBridgeMiddle isn't needed. After all, the
477  * tile already has the has_bridge_above bits set. */
478  SetBridgeMiddle(tile, direction);
479  }
480  }
481 
482  owner = company;
483  is_new_owner = true;
484  }
485 
486  /* do the drill? */
487  if (flags & DC_EXEC) {
488  DiagDirection dir = AxisToDiagDir(direction);
489 
490  Company *c = Company::GetIfValid(company);
491  switch (transport_type) {
492  case TRANSPORT_RAIL:
493  /* Add to company infrastructure count if required. */
494  if (is_new_owner && c != NULL) c->infrastructure.rail[railtype] += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
495  MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
496  MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype);
497  SetTunnelBridgeReservation(tile_start, pbs_reservation);
498  SetTunnelBridgeReservation(tile_end, pbs_reservation);
499  break;
500 
501  case TRANSPORT_ROAD: {
502  RoadTypes prev_roadtypes = IsBridgeTile(tile_start) ? GetRoadTypes(tile_start) : ROADTYPES_NONE;
503  if (is_new_owner) {
504  /* Also give unowned present roadtypes to new owner */
505  if (HasBit(prev_roadtypes, ROADTYPE_ROAD) && GetRoadOwner(tile_start, ROADTYPE_ROAD) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_ROAD);
506  if (HasBit(prev_roadtypes, ROADTYPE_TRAM) && GetRoadOwner(tile_start, ROADTYPE_TRAM) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_TRAM);
507  }
508  if (c != NULL) {
509  /* Add all new road types to the company infrastructure counter. */
510  RoadType new_rt;
511  FOR_EACH_SET_ROADTYPE(new_rt, roadtypes ^ prev_roadtypes) {
512  /* A full diagonal road tile has two road bits. */
513  c->infrastructure.road[new_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
514  }
515  }
516  Owner owner_road = HasBit(prev_roadtypes, ROADTYPE_ROAD) ? GetRoadOwner(tile_start, ROADTYPE_ROAD) : company;
517  Owner owner_tram = HasBit(prev_roadtypes, ROADTYPE_TRAM) ? GetRoadOwner(tile_start, ROADTYPE_TRAM) : company;
518  MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, roadtypes);
519  MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), roadtypes);
520  break;
521  }
522 
523  case TRANSPORT_WATER:
524  if (is_new_owner && c != NULL) c->infrastructure.water += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
525  MakeAqueductBridgeRamp(tile_start, owner, dir);
526  MakeAqueductBridgeRamp(tile_end, owner, ReverseDiagDir(dir));
527  break;
528 
529  default:
530  NOT_REACHED();
531  }
532 
533  /* Mark all tiles dirty */
534  MarkBridgeDirty(tile_start, tile_end, AxisToDiagDir(direction), z_start);
536  }
537 
538  if ((flags & DC_EXEC) && transport_type == TRANSPORT_RAIL) {
539  Track track = AxisToTrack(direction);
540  AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, company);
541  YapfNotifyTrackLayoutChange(tile_start, track);
542  }
543 
544  /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
545  * It's unnecessary to execute this command every time for every bridge. So it is done only
546  * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
547  */
548  Company *c = Company::GetIfValid(company);
549  if (!(flags & DC_QUERY_COST) || (c != NULL && c->is_ai)) {
550  bridge_len += 2; // begin and end tiles/ramps
551 
552  switch (transport_type) {
553  case TRANSPORT_ROAD: cost.AddCost(bridge_len * _price[PR_BUILD_ROAD] * 2 * CountBits(roadtypes)); break;
554  case TRANSPORT_RAIL: cost.AddCost(bridge_len * RailBuildCost(railtype)); break;
555  default: break;
556  }
557 
558  if (c != NULL) bridge_len = CalcBridgeLenCostFactor(bridge_len);
559 
560  if (transport_type != TRANSPORT_WATER) {
561  cost.AddCost((int64)bridge_len * _price[PR_BUILD_BRIDGE] * GetBridgeSpec(bridge_type)->price >> 8);
562  } else {
563  /* Aqueducts use a separate base cost. */
564  cost.AddCost((int64)bridge_len * _price[PR_BUILD_AQUEDUCT]);
565  }
566 
567  }
568 
569  return cost;
570 }
571 
572 
583 CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
584 {
585  CompanyID company = _current_company;
586 
587  TransportType transport_type = Extract<TransportType, 8, 2>(p1);
588 
589  RailType railtype = INVALID_RAILTYPE;
592  switch (transport_type) {
593  case TRANSPORT_RAIL:
594  railtype = Extract<RailType, 0, 4>(p1);
595  if (!ValParamRailtype(railtype)) return CMD_ERROR;
596  break;
597 
598  case TRANSPORT_ROAD:
599  rts = Extract<RoadTypes, 0, 2>(p1);
600  if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(company, rts)) return CMD_ERROR;
601  break;
602 
603  default: return CMD_ERROR;
604  }
605 
606  if (company == OWNER_DEITY) {
607  if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
608  const Town *town = CalcClosestTownFromTile(start_tile);
609 
610  company = OWNER_TOWN;
611 
612  /* If we are not within a town, we are not owned by the town */
613  if (town == NULL || DistanceSquare(start_tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
614  company = OWNER_NONE;
615  }
616  }
617 
618  int start_z;
619  int end_z;
620  Slope start_tileh = GetTileSlope(start_tile, &start_z);
621  DiagDirection direction = GetInclinedSlopeDirection(start_tileh);
622  if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL);
623 
624  if (HasTileWaterGround(start_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
625 
626  CommandCost ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
627  if (ret.Failed()) return ret;
628 
629  /* XXX - do NOT change 'ret' in the loop, as it is used as the price
630  * for the clearing of the entrance of the tunnel. Assigning it to
631  * cost before the loop will yield different costs depending on start-
632  * position, because of increased-cost-by-length: 'cost += cost >> 3' */
633 
634  TileIndexDiff delta = TileOffsByDiagDir(direction);
635  DiagDirection tunnel_in_way_dir;
636  if (DiagDirToAxis(direction) == AXIS_Y) {
637  tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
638  } else {
639  tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
640  }
641 
642  TileIndex end_tile = start_tile;
643 
644  /* Tile shift coefficient. Will decrease for very long tunnels to avoid exponential growth of price*/
645  int tiles_coef = 3;
646  /* Number of tiles from start of tunnel */
647  int tiles = 0;
648  /* Number of tiles at which the cost increase coefficient per tile is halved */
649  int tiles_bump = 25;
650 
652  Slope end_tileh;
653  for (;;) {
654  end_tile += delta;
655  if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER);
656  end_tileh = GetTileSlope(end_tile, &end_z);
657 
658  if (start_z == end_z) break;
659 
660  if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
661  return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY);
662  }
663 
664  tiles++;
665  if (tiles == tiles_bump) {
666  tiles_coef++;
667  tiles_bump *= 2;
668  }
669 
670  cost.AddCost(_price[PR_BUILD_TUNNEL]);
671  cost.AddCost(cost.GetCost() >> tiles_coef); // add a multiplier for longer tunnels
672  }
673 
674  /* Add the cost of the entrance */
675  cost.AddCost(_price[PR_BUILD_TUNNEL]);
676  cost.AddCost(ret);
677 
678  /* if the command fails from here on we want the end tile to be highlighted */
679  _build_tunnel_endtile = end_tile;
680 
681  if (tiles > _settings_game.construction.max_tunnel_length) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG);
682 
683  if (HasTileWaterGround(end_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
684 
685  /* Clear the tile in any case */
686  ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
687  if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
688  cost.AddCost(ret);
689 
690  /* slope of end tile must be complementary to the slope of the start tile */
691  if (end_tileh != ComplementSlope(start_tileh)) {
692  /* Mark the tile as already cleared for the terraform command.
693  * Do this for all tiles (like trees), not only objects. */
694  ClearedObjectArea *coa = FindClearedObject(end_tile);
695  if (coa == NULL) {
696  coa = _cleared_object_areas.Append();
697  coa->first_tile = end_tile;
698  coa->area = TileArea(end_tile, 1, 1);
699  }
700 
701  /* Hide the tile from the terraforming command */
702  TileIndex old_first_tile = coa->first_tile;
703  coa->first_tile = INVALID_TILE;
704  ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND);
705  coa->first_tile = old_first_tile;
706  if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
707  cost.AddCost(ret);
708  }
709  cost.AddCost(_price[PR_BUILD_TUNNEL]);
710 
711  /* Pay for the rail/road in the tunnel including entrances */
712  switch (transport_type) {
713  case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * _price[PR_BUILD_ROAD] * 2); break;
714  case TRANSPORT_RAIL: cost.AddCost((tiles + 2) * RailBuildCost(railtype)); break;
715  default: NOT_REACHED();
716  }
717 
718  if (flags & DC_EXEC) {
719  Company *c = Company::GetIfValid(company);
720  uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
721  if (transport_type == TRANSPORT_RAIL) {
722  if (!IsTunnelTile(start_tile) && c != NULL) c->infrastructure.rail[railtype] += num_pieces;
723  MakeRailTunnel(start_tile, company, direction, railtype);
724  MakeRailTunnel(end_tile, company, ReverseDiagDir(direction), railtype);
725  AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company);
726  YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
727  } else {
728  if (c != NULL) {
729  RoadType rt;
730  FOR_EACH_SET_ROADTYPE(rt, rts ^ (IsTunnelTile(start_tile) ? GetRoadTypes(start_tile) : ROADTYPES_NONE)) {
731  c->infrastructure.road[rt] += num_pieces * 2; // A full diagonal road has two road bits.
732  }
733  }
734  MakeRoadTunnel(start_tile, company, direction, rts);
735  MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), rts);
736  }
738  }
739 
740  return cost;
741 }
742 
743 
750 {
751  /* Floods can remove anything as well as the scenario editor */
752  if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return CommandCost();
753 
754  switch (GetTunnelBridgeTransportType(tile)) {
755  case TRANSPORT_ROAD: {
756  RoadTypes rts = GetRoadTypes(tile);
757  Owner road_owner = _current_company;
758  Owner tram_owner = _current_company;
759 
760  if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
761  if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
762 
763  /* We can remove unowned road and if the town allows it */
765  /* Town does not allow */
766  return CheckTileOwnership(tile);
767  }
768  if (road_owner == OWNER_NONE || road_owner == OWNER_TOWN) road_owner = _current_company;
769  if (tram_owner == OWNER_NONE) tram_owner = _current_company;
770 
771  CommandCost ret = CheckOwnership(road_owner, tile);
772  if (ret.Succeeded()) ret = CheckOwnership(tram_owner, tile);
773  return ret;
774  }
775 
776  case TRANSPORT_RAIL:
777  return CheckOwnership(GetTileOwner(tile));
778 
779  case TRANSPORT_WATER: {
780  /* Always allow to remove aqueducts without owner. */
781  Owner aqueduct_owner = GetTileOwner(tile);
782  if (aqueduct_owner == OWNER_NONE) aqueduct_owner = _current_company;
783  return CheckOwnership(aqueduct_owner);
784  }
785 
786  default: NOT_REACHED();
787  }
788 }
789 
797 {
799  if (ret.Failed()) return ret;
800 
801  TileIndex endtile = GetOtherTunnelEnd(tile);
802 
803  ret = TunnelBridgeIsFree(tile, endtile);
804  if (ret.Failed()) return ret;
805 
806  _build_tunnel_endtile = endtile;
807 
808  Town *t = NULL;
809  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
810  t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
811 
812  /* Check if you are allowed to remove the tunnel owned by a town
813  * Removal depends on difficulty settings */
815  if (ret.Failed()) return ret;
816  }
817 
818  /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
819  * you have a "Poor" (0) town rating */
820  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
822  }
823 
824  uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
825 
826  if (flags & DC_EXEC) {
828  /* We first need to request values before calling DoClearSquare */
830  Track track = DiagDirToDiagTrack(dir);
831  Owner owner = GetTileOwner(tile);
832 
833  Train *v = NULL;
834  if (HasTunnelBridgeReservation(tile)) {
835  v = GetTrainForReservation(tile, track);
836  if (v != NULL) FreeTrainTrackReservation(v);
837  }
838 
839  if (Company::IsValidID(owner)) {
840  Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
842  }
843 
844  DoClearSquare(tile);
845  DoClearSquare(endtile);
846 
847  /* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
848  AddSideToSignalBuffer(tile, ReverseDiagDir(dir), owner);
849  AddSideToSignalBuffer(endtile, dir, owner);
850 
851  YapfNotifyTrackLayoutChange(tile, track);
852  YapfNotifyTrackLayoutChange(endtile, track);
853 
854  if (v != NULL) TryPathReserve(v);
855  } else {
856  RoadType rt;
858  /* A full diagonal road tile has two road bits. */
859  Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
860  if (c != NULL) {
863  }
864  }
865 
866  DoClearSquare(tile);
867  DoClearSquare(endtile);
868  }
869  }
870  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_TUNNEL] * len);
871 }
872 
873 
881 {
883  if (ret.Failed()) return ret;
884 
885  TileIndex endtile = GetOtherBridgeEnd(tile);
886 
887  ret = TunnelBridgeIsFree(tile, endtile);
888  if (ret.Failed()) return ret;
889 
890  DiagDirection direction = GetTunnelBridgeDirection(tile);
891  TileIndexDiff delta = TileOffsByDiagDir(direction);
892 
893  Town *t = NULL;
894  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
895  t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
896 
897  /* Check if you are allowed to remove the bridge owned by a town
898  * Removal depends on difficulty settings */
900  if (ret.Failed()) return ret;
901  }
902 
903  /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
904  * you have a "Poor" (0) town rating */
905  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
907  }
908 
909  Money base_cost = (GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) ? _price[PR_CLEAR_BRIDGE] : _price[PR_CLEAR_AQUEDUCT];
910  uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
911 
912  if (flags & DC_EXEC) {
913  /* read this value before actual removal of bridge */
914  bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
915  Owner owner = GetTileOwner(tile);
916  int height = GetBridgeHeight(tile);
917  Train *v = NULL;
918 
919  if (rail && HasTunnelBridgeReservation(tile)) {
920  v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
921  if (v != NULL) FreeTrainTrackReservation(v);
922  }
923 
924  /* Update company infrastructure counts. */
925  if (rail) {
926  if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
927  } else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) {
928  RoadType rt;
930  Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
931  if (c != NULL) {
932  /* A full diagonal road tile has two road bits. */
935  }
936  }
937  } else { // Aqueduct
938  if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.water -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
939  }
941 
942  DoClearSquare(tile);
943  DoClearSquare(endtile);
944  for (TileIndex c = tile + delta; c != endtile; c += delta) {
945  /* do not let trees appear from 'nowhere' after removing bridge */
946  if (IsNormalRoadTile(c) && GetRoadside(c) == ROADSIDE_TREES) {
947  int minz = GetTileMaxZ(c) + 3;
948  if (height < minz) SetRoadside(c, ROADSIDE_PAVED);
949  }
951  MarkTileDirtyByTile(c, height - TileHeight(c));
952  }
953 
954  if (rail) {
955  /* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
956  AddSideToSignalBuffer(tile, ReverseDiagDir(direction), owner);
957  AddSideToSignalBuffer(endtile, direction, owner);
958 
959  Track track = DiagDirToDiagTrack(direction);
960  YapfNotifyTrackLayoutChange(tile, track);
961  YapfNotifyTrackLayoutChange(endtile, track);
962 
963  if (v != NULL) TryPathReserve(v, true);
964  }
965  }
966 
967  return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
968 }
969 
977 {
978  if (IsTunnel(tile)) {
979  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST);
980  return DoClearTunnel(tile, flags);
981  } else { // IsBridge(tile)
982  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
983  return DoClearBridge(tile, flags);
984  }
985 }
986 
997 static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
998 {
999  static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START;
1000  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);
1001 }
1002 
1014 static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, int x, int y, int w, int h)
1015 {
1016  int cur_z;
1017  for (cur_z = z_top; cur_z >= z_bottom; cur_z -= TILE_HEIGHT) {
1018  DrawPillar(psid, x, y, cur_z, w, h, NULL);
1019  }
1020  return cur_z;
1021 }
1022 
1034 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
1035 {
1036  static const int bounding_box_size[2] = {16, 2};
1037  static const int back_pillar_offset[2] = { 0, 9};
1038 
1039  static const int INF = 1000;
1040  static const SubSprite half_pillar_sub_sprite[2][2] = {
1041  { { -14, -INF, INF, INF }, { -INF, -INF, -15, INF } }, // X axis, north and south
1042  { { -INF, -INF, 15, INF }, { 16, -INF, INF, INF } }, // Y axis, north and south
1043  };
1044 
1045  if (psid->sprite == 0) return;
1046 
1047  /* Determine ground height under pillars */
1048  DiagDirection south_dir = AxisToDiagDir(axis);
1049  int z_front_north = ti->z;
1050  int z_back_north = ti->z;
1051  int z_front_south = ti->z;
1052  int z_back_south = ti->z;
1053  GetSlopePixelZOnEdge(ti->tileh, south_dir, &z_front_south, &z_back_south);
1054  GetSlopePixelZOnEdge(ti->tileh, ReverseDiagDir(south_dir), &z_front_north, &z_back_north);
1055 
1056  /* Shared height of pillars */
1057  int z_front = max(z_front_north, z_front_south);
1058  int z_back = max(z_back_north, z_back_south);
1059 
1060  /* x and y size of bounding-box of pillars */
1061  int w = bounding_box_size[axis];
1062  int h = bounding_box_size[OtherAxis(axis)];
1063  /* sprite position of back facing pillar */
1064  int x_back = x - back_pillar_offset[axis];
1065  int y_back = y - back_pillar_offset[OtherAxis(axis)];
1066 
1067  /* Draw front pillars */
1068  int bottom_z = DrawPillarColumn(z_front, z_bridge, psid, x, y, w, h);
1069  if (z_front_north < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1070  if (z_front_south < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1071 
1072  /* Draw back pillars, skip top two parts, which are hidden by the bridge */
1073  int z_bridge_back = z_bridge - 2 * (int)TILE_HEIGHT;
1074  if (drawfarpillar && (z_back_north <= z_bridge_back || z_back_south <= z_bridge_back)) {
1075  bottom_z = DrawPillarColumn(z_back, z_bridge_back, psid, x_back, y_back, w, h);
1076  if (z_back_north < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1077  if (z_back_south < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1078  }
1079 }
1080 
1090 static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head)
1091 {
1092  static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
1093  static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
1094  static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
1095 
1096  static const uint size_x[6] = { 1, 16, 16, 1, 16, 1 };
1097  static const uint size_y[6] = { 16, 1, 1, 16, 1, 16 };
1098  static const uint front_bb_offset_x[6] = { 15, 0, 0, 15, 0, 15 };
1099  static const uint front_bb_offset_y[6] = { 0, 15, 15, 0, 15, 0 };
1100 
1101  /* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
1102  * The bounding boxes here are the same as for bridge front/roof */
1103  if (head || !IsInvisibilitySet(TO_BRIDGES)) {
1104  AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE,
1105  x, y, size_x[offset], size_y[offset], 0x28, z,
1106  !head && IsTransparencySet(TO_BRIDGES));
1107  }
1108 
1109  /* Do not draw catenary if it is set invisible */
1111  AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NONE,
1112  x, y, size_x[offset], size_y[offset], 0x28, z,
1114  }
1115 
1116  /* Start a new SpriteCombine for the front part */
1117  EndSpriteCombine();
1119 
1120  /* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */
1122  AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE,
1123  x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
1124  IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]);
1125  }
1126 }
1127 
1142 {
1143  TransportType transport_type = GetTunnelBridgeTransportType(ti->tile);
1144  DiagDirection tunnelbridge_direction = GetTunnelBridgeDirection(ti->tile);
1145 
1146  if (IsTunnel(ti->tile)) {
1147  /* Front view of tunnel bounding boxes:
1148  *
1149  * 122223 <- BB_Z_SEPARATOR
1150  * 1 3
1151  * 1 3 1,3 = empty helper BB
1152  * 1 3 2 = SpriteCombine of tunnel-roof and catenary (tram & elrail)
1153  *
1154  */
1155 
1156  static const int _tunnel_BB[4][12] = {
1157  /* tunnnel-roof | Z-separator | tram-catenary
1158  * w h bb_x bb_y| x y w h |bb_x bb_y w h */
1159  { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // NE
1160  { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // SE
1161  { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // SW
1162  { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // NW
1163  };
1164  const int *BB_data = _tunnel_BB[tunnelbridge_direction];
1165 
1166  bool catenary = false;
1167 
1168  SpriteID image;
1169  SpriteID railtype_overlay = 0;
1170  if (transport_type == TRANSPORT_RAIL) {
1171  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1172  image = rti->base_sprites.tunnel;
1173  if (rti->UsesOverlay()) {
1174  /* Check if the railtype has custom tunnel portals. */
1175  railtype_overlay = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL_PORTAL);
1176  if (railtype_overlay != 0) image = SPR_RAILTYPE_TUNNEL_BASE; // Draw blank grass tunnel base.
1177  }
1178  } else {
1179  image = SPR_TUNNEL_ENTRY_REAR_ROAD;
1180  }
1181 
1182  if (HasTunnelBridgeSnowOrDesert(ti->tile)) image += railtype_overlay != 0 ? 8 : 32;
1183 
1184  image += tunnelbridge_direction * 2;
1185  DrawGroundSprite(image, PAL_NONE);
1186 
1187  if (transport_type == TRANSPORT_ROAD) {
1188  RoadTypes rts = GetRoadTypes(ti->tile);
1189 
1190  if (HasBit(rts, ROADTYPE_TRAM)) {
1191  static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, { 5, 76, 77, 4 } };
1192 
1193  DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][tunnelbridge_direction], PAL_NONE);
1194 
1195  /* Do not draw wires if they are invisible */
1197  catenary = true;
1199  AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + 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);
1200  }
1201  }
1202  } else {
1203  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1204  if (rti->UsesOverlay()) {
1205  SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL);
1206  if (surface != 0) DrawGroundSprite(surface + tunnelbridge_direction, PAL_NONE);
1207  }
1208 
1209  /* PBS debugging, draw reserved tracks darker */
1210  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1211  if (rti->UsesOverlay()) {
1212  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1213  DrawGroundSprite(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH);
1214  } else {
1215  DrawGroundSprite(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH);
1216  }
1217  }
1218 
1220  /* Maybe draw pylons on the entry side */
1221  DrawRailCatenary(ti);
1222 
1223  catenary = true;
1225  /* Draw wire above the ramp */
1227  }
1228  }
1229 
1230  if (railtype_overlay != 0 && !catenary) StartSpriteCombine();
1231 
1232  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);
1233  /* Draw railtype tunnel portal overlay if defined. */
1234  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);
1235 
1236  if (catenary || railtype_overlay != 0) EndSpriteCombine();
1237 
1238  /* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
1239  AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x, ti->y, BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
1240  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);
1241 
1242  DrawBridgeMiddle(ti);
1243  } else { // IsBridge(ti->tile)
1244  const PalSpriteID *psid;
1245  int base_offset;
1246  bool ice = HasTunnelBridgeSnowOrDesert(ti->tile);
1247 
1248  if (transport_type == TRANSPORT_RAIL) {
1249  base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
1250  assert(base_offset != 8); // This one is used for roads
1251  } else {
1252  base_offset = 8;
1253  }
1254 
1255  /* as the lower 3 bits are used for other stuff, make sure they are clear */
1256  assert( (base_offset & 0x07) == 0x00);
1257 
1258  DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(tunnelbridge_direction)));
1259 
1260  /* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
1261  base_offset += (6 - tunnelbridge_direction) % 4;
1262 
1263  /* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
1264  if (transport_type != TRANSPORT_WATER) {
1265  if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
1266  psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD)[base_offset];
1267  } else {
1268  psid = _aqueduct_sprites + base_offset;
1269  }
1270 
1271  if (!ice) {
1272  TileIndex next = ti->tile + TileOffsByDiagDir(tunnelbridge_direction);
1273  if (ti->tileh != SLOPE_FLAT && ti->z == 0 && HasTileWaterClass(next) && GetWaterClass(next) == WATER_CLASS_SEA) {
1274  DrawShoreTile(ti->tileh);
1275  } else {
1276  DrawClearLandTile(ti, 3);
1277  }
1278  } else {
1279  DrawGroundSprite(SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
1280  }
1281 
1282  /* draw ramp */
1283 
1284  /* Draw Trambits and PBS Reservation as SpriteCombine */
1285  if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1286 
1287  /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1288  * it doesn't disappear behind it
1289  */
1290  /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1291  AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
1292 
1293  if (transport_type == TRANSPORT_ROAD) {
1294  RoadTypes rts = GetRoadTypes(ti->tile);
1295 
1296  if (HasBit(rts, ROADTYPE_TRAM)) {
1297  uint offset = tunnelbridge_direction;
1298  int z = ti->z;
1299  if (ti->tileh != SLOPE_FLAT) {
1300  offset = (offset + 1) & 1;
1301  z += TILE_HEIGHT;
1302  } else {
1303  offset += 2;
1304  }
1305  /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1306  DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
1307  }
1308  EndSpriteCombine();
1309  } else if (transport_type == TRANSPORT_RAIL) {
1310  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1311  if (rti->UsesOverlay()) {
1312  SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE);
1313  if (surface != 0) {
1314  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1315  AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1316  } else {
1317  AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, 16, 16, 8, ti->z);
1318  }
1319  }
1320  /* Don't fallback to non-overlay sprite -- the spec states that
1321  * if an overlay is present then the bridge surface must be
1322  * present. */
1323  }
1324 
1325  /* PBS debugging, draw reserved tracks darker */
1326  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1327  if (rti->UsesOverlay()) {
1328  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1329  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1330  AddSortableSpriteToDraw(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1331  } else {
1332  AddSortableSpriteToDraw(overlay + RTO_SLOPE_NE + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1333  }
1334  } else {
1335  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1336  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);
1337  } else {
1338  AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1339  }
1340  }
1341  }
1342 
1343  EndSpriteCombine();
1345  DrawRailCatenary(ti);
1346  }
1347  }
1348 
1349  DrawBridgeMiddle(ti);
1350  }
1351 }
1352 
1353 
1372 static BridgePieces CalcBridgePiece(uint north, uint south)
1373 {
1374  if (north == 1) {
1375  return BRIDGE_PIECE_NORTH;
1376  } else if (south == 1) {
1377  return BRIDGE_PIECE_SOUTH;
1378  } else if (north < south) {
1379  return north & 1 ? BRIDGE_PIECE_INNER_SOUTH : BRIDGE_PIECE_INNER_NORTH;
1380  } else if (north > south) {
1381  return south & 1 ? BRIDGE_PIECE_INNER_NORTH : BRIDGE_PIECE_INNER_SOUTH;
1382  } else {
1383  return north & 1 ? BRIDGE_PIECE_MIDDLE_EVEN : BRIDGE_PIECE_MIDDLE_ODD;
1384  }
1385 }
1386 
1392 {
1393  /* Sectional view of bridge bounding boxes:
1394  *
1395  * 1 2 1,2 = SpriteCombine of Bridge front/(back&floor) and RoadCatenary
1396  * 1 2 3 = empty helper BB
1397  * 1 7 2 4,5 = pillars under higher bridges
1398  * 1 6 88888 6 2 6 = elrail-pylons
1399  * 1 6 88888 6 2 7 = elrail-wire
1400  * 1 6 88888 6 2 <- TILE_HEIGHT 8 = rail-vehicle on bridge
1401  * 3333333333333 <- BB_Z_SEPARATOR
1402  * <- unused
1403  * 4 5 <- BB_HEIGHT_UNDER_BRIDGE
1404  * 4 5
1405  * 4 5
1406  *
1407  */
1408 
1409  if (!IsBridgeAbove(ti->tile)) return;
1410 
1411  TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile);
1412  TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile);
1413  TransportType transport_type = GetTunnelBridgeTransportType(rampsouth);
1414 
1415  Axis axis = GetBridgeAxis(ti->tile);
1416  BridgePieces piece = CalcBridgePiece(
1417  GetTunnelBridgeLength(ti->tile, rampnorth) + 1,
1418  GetTunnelBridgeLength(ti->tile, rampsouth) + 1
1419  );
1420 
1421  const PalSpriteID *psid;
1422  bool drawfarpillar;
1423  if (transport_type != TRANSPORT_WATER) {
1424  BridgeType type = GetBridgeType(rampsouth);
1425  drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
1426 
1427  uint base_offset;
1428  if (transport_type == TRANSPORT_RAIL) {
1429  base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
1430  } else {
1431  base_offset = 8;
1432  }
1433 
1434  psid = base_offset + GetBridgeSpriteTable(type, piece);
1435  } else {
1436  drawfarpillar = true;
1437  psid = _aqueduct_sprites;
1438  }
1439 
1440  if (axis != AXIS_X) psid += 4;
1441 
1442  int x = ti->x;
1443  int y = ti->y;
1444  uint bridge_z = GetBridgePixelHeight(rampsouth);
1445  int z = bridge_z - BRIDGE_Z_START;
1446 
1447  /* Add a bounding box that separates the bridge from things below it. */
1448  AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
1449 
1450  /* Draw Trambits as SpriteCombine */
1451  if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1452 
1453  /* Draw floor and far part of bridge*/
1454  if (!IsInvisibilitySet(TO_BRIDGES)) {
1455  if (axis == AXIS_X) {
1456  AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1457  } else {
1458  AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1459  }
1460  }
1461 
1462  psid++;
1463 
1464  if (transport_type == TRANSPORT_ROAD) {
1465  RoadTypes rts = GetRoadTypes(rampsouth);
1466 
1467  if (HasBit(rts, ROADTYPE_TRAM)) {
1468  /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1469  DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD), false);
1470  } else {
1471  EndSpriteCombine();
1473  }
1474  } else if (transport_type == TRANSPORT_RAIL) {
1475  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth));
1476  if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
1477  SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE);
1478  if (surface != 0) {
1479  AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1480  }
1481  }
1482 
1483  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
1484  if (rti->UsesOverlay()) {
1485  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1486  AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1487  } else {
1488  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));
1489  }
1490  }
1491 
1492  EndSpriteCombine();
1493 
1494  if (HasRailCatenaryDrawn(GetRailType(rampsouth))) {
1496  }
1497  }
1498 
1499  /* draw roof, the component of the bridge which is logically between the vehicle and the camera */
1500  if (!IsInvisibilitySet(TO_BRIDGES)) {
1501  if (axis == AXIS_X) {
1502  y += 12;
1503  if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
1504  } else {
1505  x += 12;
1506  if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
1507  }
1508  }
1509 
1510  /* Draw TramFront as SpriteCombine */
1511  if (transport_type == TRANSPORT_ROAD) EndSpriteCombine();
1512 
1513  /* Do not draw anything more if bridges are invisible */
1514  if (IsInvisibilitySet(TO_BRIDGES)) return;
1515 
1516  psid++;
1517  if (ti->z + 5 == z) {
1518  /* draw poles below for small bridges */
1519  if (psid->sprite != 0) {
1520  SpriteID image = psid->sprite;
1521  SpriteID pal = psid->pal;
1524  pal = PALETTE_TO_TRANSPARENT;
1525  }
1526 
1527  DrawGroundSpriteAt(image, pal, x - ti->x, y - ti->y, z - ti->z);
1528  }
1529  } else {
1530  /* draw pillars below for high bridges */
1531  DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
1532  }
1533 }
1534 
1535 
1536 static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
1537 {
1538  int z;
1539  Slope tileh = GetTilePixelSlope(tile, &z);
1540 
1541  x &= 0xF;
1542  y &= 0xF;
1543 
1544  if (IsTunnel(tile)) {
1545  uint pos = (DiagDirToAxis(GetTunnelBridgeDirection(tile)) == AXIS_X ? y : x);
1546 
1547  /* In the tunnel entrance? */
1548  if (5 <= pos && pos <= 10) return z;
1549  } else { // IsBridge(tile)
1551  uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
1552 
1554 
1555  /* On the bridge ramp? */
1556  if (5 <= pos && pos <= 10) {
1557  int delta;
1558 
1559  if (tileh != SLOPE_FLAT) return z + TILE_HEIGHT;
1560 
1561  switch (dir) {
1562  default: NOT_REACHED();
1563  case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
1564  case DIAGDIR_SE: delta = y / 2; break;
1565  case DIAGDIR_SW: delta = x / 2; break;
1566  case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
1567  }
1568  return z + 1 + delta;
1569  }
1570  }
1571 
1572  return z + GetPartialPixelZ(x, y, tileh);
1573 }
1574 
1575 static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
1576 {
1578 }
1579 
1580 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
1581 {
1583 
1584  if (IsTunnel(tile)) {
1585  td->str = (tt == TRANSPORT_RAIL) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD;
1586  } else { // IsBridge(tile)
1587  td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
1588  }
1589  td->owner[0] = GetTileOwner(tile);
1590 
1591  Owner road_owner = INVALID_OWNER;
1592  Owner tram_owner = INVALID_OWNER;
1593  RoadTypes rts = GetRoadTypes(tile);
1594  if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
1595  if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
1596 
1597  /* Is there a mix of owners? */
1598  if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
1599  (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
1600  uint i = 1;
1601  if (road_owner != INVALID_OWNER) {
1602  td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
1603  td->owner[i] = road_owner;
1604  i++;
1605  }
1606  if (tram_owner != INVALID_OWNER) {
1607  td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
1608  td->owner[i] = tram_owner;
1609  }
1610  }
1611 
1612  if (tt == TRANSPORT_RAIL) {
1613  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
1614  td->rail_speed = rti->max_speed;
1615  td->railtype = rti->strings.name;
1616 
1617  if (!IsTunnel(tile)) {
1618  uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1619  if (td->rail_speed == 0 || spd < td->rail_speed) {
1620  td->rail_speed = spd;
1621  }
1622  }
1623  } else if (tt == TRANSPORT_ROAD && !IsTunnel(tile)) {
1625  }
1626 }
1627 
1628 
1629 static void TileLoop_TunnelBridge(TileIndex tile)
1630 {
1631  bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile);
1633  case LT_ARCTIC: {
1634  /* As long as we do not have a snow density, we want to use the density
1635  * from the entry edge. For tunnels this is the lowest point for bridges the highest point.
1636  * (Independent of foundations) */
1637  int z = IsBridge(tile) ? GetTileMaxZ(tile) : GetTileZ(tile);
1638  if (snow_or_desert != (z > GetSnowLine())) {
1639  SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
1640  MarkTileDirtyByTile(tile);
1641  }
1642  break;
1643  }
1644 
1645  case LT_TROPIC:
1646  if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
1647  SetTunnelBridgeSnowOrDesert(tile, true);
1648  MarkTileDirtyByTile(tile);
1649  }
1650  break;
1651 
1652  default:
1653  break;
1654  }
1655 }
1656 
1657 static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
1658 {
1659  TransportType transport_type = GetTunnelBridgeTransportType(tile);
1660  if (transport_type != mode || (transport_type == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0)) return 0;
1661 
1663  if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
1665 }
1666 
1667 static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
1668 {
1669  TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
1670  /* Set number of pieces to zero if it's the southern tile as we
1671  * don't want to update the infrastructure counts twice. */
1672  uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
1673 
1674  for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
1675  /* Update all roadtypes, no matter if they are present */
1676  if (GetRoadOwner(tile, rt) == old_owner) {
1677  if (HasBit(GetRoadTypes(tile), rt)) {
1678  /* Update company infrastructure counts. A full diagonal road tile has two road bits.
1679  * No need to dirty windows here, we'll redraw the whole screen anyway. */
1680  Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2;
1681  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2;
1682  }
1683 
1684  SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
1685  }
1686  }
1687 
1688  if (!IsTileOwner(tile, old_owner)) return;
1689 
1690  /* Update company infrastructure counts for rail and water as well.
1691  * No need to dirty windows here, we'll redraw the whole screen anyway. */
1693  Company *old = Company::Get(old_owner);
1694  if (tt == TRANSPORT_RAIL) {
1695  old->infrastructure.rail[GetRailType(tile)] -= num_pieces;
1696  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += num_pieces;
1697  } else if (tt == TRANSPORT_WATER) {
1698  old->infrastructure.water -= num_pieces;
1699  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.water += num_pieces;
1700  }
1701 
1702  if (new_owner != INVALID_OWNER) {
1703  SetTileOwner(tile, new_owner);
1704  } else {
1705  if (tt == TRANSPORT_RAIL) {
1706  /* Since all of our vehicles have been removed, it is safe to remove the rail
1707  * bridge / tunnel. */
1709  assert(ret.Succeeded());
1710  } else {
1711  /* In any other case, we can safely reassign the ownership to OWNER_NONE. */
1712  SetTileOwner(tile, OWNER_NONE);
1713  }
1714  }
1715 }
1716 
1722 static const byte TUNNEL_SOUND_FRAME = 1;
1723 
1732 extern const byte _tunnel_visibility_frame[DIAGDIR_END] = {12, 8, 8, 12};
1733 
1734 static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
1735 {
1736  int z = GetSlopePixelZ(x, y) - v->z_pos;
1737 
1738  if (abs(z) > 2) return VETSB_CANNOT_ENTER;
1739  /* Direction into the wormhole */
1740  const DiagDirection dir = GetTunnelBridgeDirection(tile);
1741  /* Direction of the vehicle */
1742  const DiagDirection vdir = DirToDiagDir(v->direction);
1743  /* New position of the vehicle on the tile */
1744  byte pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK;
1745  /* Number of units moved by the vehicle since entering the tile */
1746  byte frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
1747 
1748  if (IsTunnel(tile)) {
1749  if (v->type == VEH_TRAIN) {
1750  Train *t = Train::From(v);
1751 
1752  if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
1753  if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) {
1754  if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
1755  SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
1756  }
1757  return VETSB_CONTINUE;
1758  }
1759  if (frame == _tunnel_visibility_frame[dir]) {
1760  t->tile = tile;
1761  t->track = TRACK_BIT_WORMHOLE;
1762  t->vehstatus |= VS_HIDDEN;
1763  return VETSB_ENTERED_WORMHOLE;
1764  }
1765  }
1766 
1767  if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1768  /* We're at the tunnel exit ?? */
1769  t->tile = tile;
1770  t->track = DiagDirToDiagTrackBits(vdir);
1771  assert(t->track);
1772  t->vehstatus &= ~VS_HIDDEN;
1773  return VETSB_ENTERED_WORMHOLE;
1774  }
1775  } else if (v->type == VEH_ROAD) {
1776  RoadVehicle *rv = RoadVehicle::From(v);
1777 
1778  /* Enter tunnel? */
1779  if (rv->state != RVSB_WORMHOLE && dir == vdir) {
1780  if (frame == _tunnel_visibility_frame[dir]) {
1781  /* Frame should be equal to the next frame number in the RV's movement */
1782  assert(frame == rv->frame + 1);
1783  rv->tile = tile;
1784  rv->state = RVSB_WORMHOLE;
1785  rv->vehstatus |= VS_HIDDEN;
1786  return VETSB_ENTERED_WORMHOLE;
1787  } else {
1788  return VETSB_CONTINUE;
1789  }
1790  }
1791 
1792  /* We're at the tunnel exit ?? */
1793  if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1794  rv->tile = tile;
1795  rv->state = DiagDirToDiagTrackdir(vdir);
1796  rv->frame = frame;
1797  rv->vehstatus &= ~VS_HIDDEN;
1798  return VETSB_ENTERED_WORMHOLE;
1799  }
1800  }
1801  } else { // IsBridge(tile)
1802  if (v->type != VEH_SHIP) {
1803  /* modify speed of vehicle */
1804  uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1805 
1806  if (v->type == VEH_ROAD) spd *= 2;
1807  Vehicle *first = v->First();
1808  first->cur_speed = min(first->cur_speed, spd);
1809  }
1810 
1811  if (vdir == dir) {
1812  /* Vehicle enters bridge at the last frame inside this tile. */
1813  if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
1814  switch (v->type) {
1815  case VEH_TRAIN: {
1816  Train *t = Train::From(v);
1817  t->track = TRACK_BIT_WORMHOLE;
1820  break;
1821  }
1822 
1823  case VEH_ROAD: {
1824  RoadVehicle *rv = RoadVehicle::From(v);
1825  rv->state = RVSB_WORMHOLE;
1826  /* There are no slopes inside bridges / tunnels. */
1829  break;
1830  }
1831 
1832  case VEH_SHIP:
1834  break;
1835 
1836  default: NOT_REACHED();
1837  }
1838  return VETSB_ENTERED_WORMHOLE;
1839  } else if (vdir == ReverseDiagDir(dir)) {
1840  v->tile = tile;
1841  switch (v->type) {
1842  case VEH_TRAIN: {
1843  Train *t = Train::From(v);
1844  if (t->track == TRACK_BIT_WORMHOLE) {
1845  t->track = DiagDirToDiagTrackBits(vdir);
1846  return VETSB_ENTERED_WORMHOLE;
1847  }
1848  break;
1849  }
1850 
1851  case VEH_ROAD: {
1852  RoadVehicle *rv = RoadVehicle::From(v);
1853  if (rv->state == RVSB_WORMHOLE) {
1854  rv->state = DiagDirToDiagTrackdir(vdir);
1855  rv->frame = 0;
1856  return VETSB_ENTERED_WORMHOLE;
1857  }
1858  break;
1859  }
1860 
1861  case VEH_SHIP: {
1862  Ship *ship = Ship::From(v);
1863  if (ship->state == TRACK_BIT_WORMHOLE) {
1864  ship->state = DiagDirToDiagTrackBits(vdir);
1865  return VETSB_ENTERED_WORMHOLE;
1866  }
1867  break;
1868  }
1869 
1870  default: NOT_REACHED();
1871  }
1872  }
1873  }
1874  return VETSB_CONTINUE;
1875 }
1876 
1877 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
1878 {
1880  DiagDirection direction = GetTunnelBridgeDirection(tile);
1881  Axis axis = DiagDirToAxis(direction);
1882  CommandCost res;
1883  int z_old;
1884  Slope tileh_old = GetTileSlope(tile, &z_old);
1885 
1886  /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
1887  if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
1888  CheckBridgeSlopeSouth(axis, &tileh_old, &z_old);
1889  res = CheckBridgeSlopeSouth(axis, &tileh_new, &z_new);
1890  } else {
1891  CheckBridgeSlopeNorth(axis, &tileh_old, &z_old);
1892  res = CheckBridgeSlopeNorth(axis, &tileh_new, &z_new);
1893  }
1894 
1895  /* Surface slope is valid and remains unchanged? */
1896  if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
1897  }
1898 
1899  return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
1900 }
1901 
1902 extern const TileTypeProcs _tile_type_tunnelbridge_procs = {
1903  DrawTile_TunnelBridge, // draw_tile_proc
1904  GetSlopePixelZ_TunnelBridge, // get_slope_z_proc
1905  ClearTile_TunnelBridge, // clear_tile_proc
1906  NULL, // add_accepted_cargo_proc
1907  GetTileDesc_TunnelBridge, // get_tile_desc_proc
1908  GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc
1909  NULL, // click_tile_proc
1910  NULL, // animate_tile_proc
1911  TileLoop_TunnelBridge, // tile_loop_proc
1912  ChangeTileOwner_TunnelBridge, // change_tile_owner_proc
1913  NULL, // add_produced_cargo_proc
1914  VehicleEnter_TunnelBridge, // vehicle_enter_tile_proc
1915  GetFoundation_TunnelBridge, // get_foundation_proc
1916  TerraformTile_TunnelBridge, // terraform_tile_proc
1917 };
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:89
Road vehicle states.
don&#39;t allow building on structures
Definition: command_type.h:343
uint ApplyFoundationToSlope(Foundation f, Slope *s)
Applies a foundation to a slope.
Definition: landscape.cpp:99
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:103
byte state
Definition: roadveh.h:89
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
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:1566
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:296
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:231
static TransportType GetTunnelBridgeTransportType(TileIndex t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
ObjectFlags flags
Flags/settings related to the object.
Definition: newgrf_object.h:72
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:191
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:132
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
DirectionByte direction
facing
Definition: vehicle_base.h:271
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:29
Tile is desert.
Definition: tile_type.h:73
The mask to for the main sprite.
Definition: sprites.h:1519
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:152
Flag for an invalid DiagDirection.
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:141
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:35
Functions related to dates.
static WaterClass GetWaterClass(TileIndex t)
Get the water class at a tile.
Definition: water_map.h:106
Basic road type.
Definition: road_type.h:24
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 T SetBit(T &x, const uint8 y)
Set a bit in a variable.
terraform a tile
Definition: command_type.h:188
Track
These are used to specify a single track.
Definition: track_type.h:21
uint16 cur_speed
current speed
Definition: vehicle_base.h:293
query cost only, don&#39;t build.
Definition: command_type.h:344
A tile with road (or tram tracks)
Definition: tile_type.h:45
Bridge surface images.
Definition: rail.h:46
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:25
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
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...
Used for iterations.
Definition: road_type.h:26
bool extra_dynamite
extra dynamite
bool ValParamRailtype(const RailType rail)
Validate functions for rail building.
Definition: rail.cpp:198
static void MakeRailTunnel(TileIndex t, Owner o, DiagDirection d, RailType r)
Makes a rail tunnel entrance.
Definition: tunnel_map.h:73
Piece of rail on slope with north-east raised.
Definition: rail.h:66
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:512
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:344
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:207
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.
TrackBitsByte state
The "track" the ship is following.
Definition: ship.h:25
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
#define FOR_EACH_SET_ROADTYPE(var, road_types)
Iterate through each set RoadType in a RoadTypes value.
Definition: road_func.h:28
static Roadside GetRoadside(TileIndex tile)
Get the decorations of a road.
Definition: road_map.h:462
Northeast, upper right on your monitor.
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:500
static void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadTypes r)
Make a bridge ramp for roads.
Definition: bridge_map.h:151
const byte _tunnel_visibility_frame[DIAGDIR_END]
Frame when a vehicle should be hidden in a tunnel with a certain direction.
static CommandCost CheckBridgeSlopeNorth(Axis axis, Slope *tileh, int *z)
Determines the foundation for the north bridge head, and tests if the resulting slope is valid...
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
south and west corner are raised
Definition: slope_type.h:58
Common return value for all commands.
Definition: command_type.h:25
static bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition: viewport.cpp:785
RoadType
The different roadtypes we support.
Definition: road_type.h:22
static void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
Draw a single pillar sprite.
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp: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:450
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:390
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
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:642
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:116
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition: tile_map.cpp:182
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:348
void DrawBridgeMiddle(const TileInfo *ti)
Draw the middle bits of a bridge.
Functions related to (drawing on) viewports.
Functions related to NewGRF objects.
The object is owned by a superuser / goal script.
Definition: company_type.h:29
Slope GetTileSlope(TileIndex tile, int *h)
Return the slope of a given tile inside the map.
Definition: tile_map.cpp:115
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:154
SpriteID single_y
single piece of rail in Y direction, without ground
Definition: rail.h:127
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition: viewport.cpp:795
static bool IsBridgeAbove(TileIndex t)
checks if a bridge is set above the ground of this tile
Definition: bridge_map.h:45
Buses, trucks and trams belong to this class.
Definition: roadveh.h:88
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:207
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:3239
uint8 height
The height of this structure, in heightlevels; max MAX_TILE_HEIGHT.
Definition: newgrf_object.h:75
Train entering a tunnel.
Definition: newgrf_sound.h:22
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
static TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:343
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition: tilearea_type.h:96
Foundation
Enumeration for Foundations.
Definition: slope_type.h:95
Types related to cheating.
TileIndex xy
town center tile
Definition: town.h:56
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:127
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:436
static bool IsCoast(TileIndex t)
Is it a coast tile?
Definition: water_map.h:195
The y axis.
Sloped rail pieces, in order NE, SE, SW, NW.
Definition: rail.h:84
static Owner GetRoadOwner(TileIndex t, RoadType rt)
Get the owner of a specific road type.
Definition: road_map.h:199
Piece of rail in X direction.
Definition: rail.h:82
StringID owner_type[4]
Type of each owner.
Definition: tile_cmd.h:56
Road with trees on paved sidewalks.
Definition: road_map.h:452
Header file for things common for tunnels and bridges.
static void SetRoadOwner(TileIndex t, RoadType rt, Owner o)
Set the owner of a specific road type.
Definition: road_map.h:220
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
Images for overlaying track.
Definition: rail.h:41
bool HasRoadTypesAvail(const CompanyID company, const RoadTypes rts)
Finds out, whether given company has all given RoadTypes available.
Definition: road.cpp:110
Entry point for OpenTTD to YAPF&#39;s cache.
The vehicle is in a tunnel and/or bridge.
Definition: roadveh.h:40
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
Finds vehicle in tunnel / bridge.
Definition: vehicle.cpp:567
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:171
static DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:340
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:26
Southeast.
Southwest.
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:76
Piece of rail in X direction.
Definition: rail.h:60
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
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.
Trams.
Definition: road_type.h:25
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.
TileArea area
The area of the object.
Definition: object_base.h:91
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
Used for iterations.
static Slope GetTilePixelSlope(TileIndex tile, int *h)
Return the slope of a given tile.
Definition: tile_map.h:273
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
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:214
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:882
uint16 max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:220
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
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Definition: company_base.h:94
The tile has no ownership.
Definition: company_type.h:27
Northwest.
static Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition: track_func.h:525
SpriteID single_x
single piece of rail in X direction, without ground
Definition: rail.h:126
BridgePieces
This enum is related to the definition of bridge pieces, which is used to determine the proper sprite...
Definition: bridge.h:23
DiagDirection
Enumeration for diagonal directions.
CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Build Tunnel.
Road vehicle type.
Definition: vehicle_type.h:25
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
static void MakeRailBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, DiagDirection d, RailType r)
Make a bridge ramp for rails.
Definition: bridge_map.h:167
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:114
ClearedObjectArea * FindClearedObject(TileIndex tile)
Find the entry in _cleared_object_areas which occupies a certain tile.
Definition: object_cmd.cpp:453
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:595
static TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition: track_func.h:376
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:83
Trams.
Definition: road_type.h:39
All ships have this type.
Definition: ship.h:24
RoadTypes
The different roadtypes we support, but then a bitmask of them.
Definition: road_type.h:36
static Axis GetBridgeAxis(TileIndex t)
Get the axis of the bridge that goes over the tile.
Definition: bridge_map.h:68
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition: viewport.cpp:688
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 SetRoadside(TileIndex tile, Roadside s)
Set the decorations of a road.
Definition: road_map.h:472
static const SpriteID SPR_RAILTYPE_TUNNEL_BASE
Tunnel sprites with grass only for custom railtype tunnel.
Definition: sprites.h:288
Ship vehicle type.
Definition: vehicle_type.h:26
Removal of a tunnel or bridge owned by the towb.
Definition: town.h:153
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:88
Functions related to clear (MP_CLEAR) land.
static BridgeType GetBridgeType(TileIndex t)
Determines the type of bridge on a tile.
Definition: bridge_map.h:56
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:1904
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition: company_base.h:125
The X axis.
uint32 rail[RAILTYPE_END]
Count of company owned track bits for each rail type.
Definition: company_base.h:34
Construction costs.
Definition: economy_type.h:151
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:3214
Bitflag for a wormhole (used for tunnels)
Definition: track_type.h:58
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:342
static CommandCost CheckBridgeSlopeSouth(Axis axis, Slope *tileh, int *z)
Determines the foundation for the south bridge head, and tests if the resulting slope is valid...
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:313
Vehicle is currently going downhill. (Cached track information for acceleration)
static bool IsNormalRoadTile(TileIndex t)
Return whether a tile is a normal road tile.
Definition: road_map.h:57
static void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTypes r)
Makes a road tunnel entrance.
Definition: tunnel_map.h:51
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
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:215
uint16 road_speed
Speed limit of road (bridges)
Definition: tile_cmd.h:67
CompanyByte _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
Set of callback functions for performing tile operations of a given tile type.
Definition: tile_cmd.h:144
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:1569
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. ...
A town owns the tile, or a town is expanding.
Definition: company_type.h:26
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:84
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:344
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:50
when a sprite is to be displayed transparently, this bit needs to be set.
Definition: sprites.h:1508
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:2258
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
void DrawRailCatenary(const TileInfo *ti)
Draws overhead wires and pylons for electric railways.
Definition: elrail.cpp:564
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
static uint CountBits(T value)
Counts the number of set bits in a variable.
Functions related to commands.
No roadtypes.
Definition: road_type.h:37
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:604
byte GetSnowLine()
Get the current snow line, either variable or static.
Definition: landscape.cpp:564
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-NULL) 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
static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head)
Draws the trambits over an already drawn (lower end) of a bridge.
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:185
Base for ships.
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
Definition: sprites.h:261
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 RoadTypes GetRoadTypes(TileIndex t)
Get the present road types of a tile.
Definition: road_map.h:166
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
static bool IsTunnelTile(TileIndex t)
Is this a tunnel (entrance)?
Definition: tunnel_map.h:35
static void DrawTile_TunnelBridge(TileInfo *ti)
Draws a tunnel of bridge tile.
StringID name
Name of this rail type.
Definition: rail.h:165
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:134
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
static bool HasTileWaterClass(TileIndex t)
Checks whether the tile has an waterclass associated.
Definition: water_map.h:95
Functions related to NewGRF provided sounds.
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.
Main group of ground images for snow or desert.
Definition: rail.h:43
GameCreationSettings game_creation
settings used during the creation of a game (map)
No track build.
Definition: track_type.h:107
static bool IsPlainRail(TileIndex t)
Returns whether this is plain rails, with or without signals.
Definition: rail_map.h:50
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
Flag for invalid railtype.
Definition: rail_type.h:36
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:581
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:178
Owner
Enum for all companies/owners.
Definition: company_type.h:20
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:2696
The tile/execution is done by "water".
Definition: company_type.h:28
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
VehicleTypeByte type
Type of vehicle.
Definition: vehicle_type.h:54
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:89
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:116
static bool IsBridge(TileIndex t)
Checks if this is a bridge, instead of a tunnel.
Definition: bridge_map.h:24
CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type)
Does the town authority allow the (destructive) action of the current company?
Definition: town_cmd.cpp:3355
An invalid owner.
Definition: company_type.h:31
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:3318
TileIndex _build_tunnel_endtile
The end of a tunnel; as hidden return from the tunnel build command for GUI purposes.
Cheats _cheats
All the cheats.
Definition: cheat.cpp:18
uint16 max_tunnel_length
maximum length of tunnels
Train vehicle type.
Definition: vehicle_type.h:24
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
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