OpenTTD
tunnelbridge_cmd.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
16 #include "stdafx.h"
17 #include "newgrf_object.h"
18 #include "viewport_func.h"
19 #include "cmd_helper.h"
20 #include "command_func.h"
21 #include "town.h"
22 #include "train.h"
23 #include "ship.h"
24 #include "roadveh.h"
26 #include "newgrf_sound.h"
27 #include "autoslope.h"
28 #include "tunnelbridge_map.h"
29 #include "strings_func.h"
30 #include "date_func.h"
31 #include "clear_func.h"
32 #include "vehicle_func.h"
33 #include "sound_func.h"
34 #include "tunnelbridge.h"
35 #include "cheat_type.h"
36 #include "elrail_func.h"
37 #include "pbs.h"
38 #include "company_base.h"
39 #include "newgrf_railtype.h"
40 #include "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 
170 static CommandCost CheckBridgeSlope(BridgePieces bridge_piece, Axis axis, Slope *tileh, int *z)
171 {
172  assert(bridge_piece == BRIDGE_PIECE_NORTH || bridge_piece == BRIDGE_PIECE_SOUTH);
173 
174  Foundation f = GetBridgeFoundation(*tileh, axis);
175  *z += ApplyFoundationToSlope(f, tileh);
176 
177  Slope valid_inclined;
178  if (bridge_piece == BRIDGE_PIECE_NORTH) {
179  valid_inclined = (axis == AXIS_X ? SLOPE_NE : SLOPE_NW);
180  } else {
181  valid_inclined = (axis == AXIS_X ? SLOPE_SW : SLOPE_SE);
182  }
183  if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
184 
185  if (f == FOUNDATION_NONE) return CommandCost();
186 
187  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
188 }
189 
197 CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags)
198 {
199  if (flags & DC_QUERY_COST) {
200  if (bridge_len <= _settings_game.construction.max_bridge_length) return CommandCost();
201  return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
202  }
203 
204  if (bridge_type >= MAX_BRIDGES) return CMD_ERROR;
205 
206  const BridgeSpec *b = GetBridgeSpec(bridge_type);
207  if (b->avail_year > _cur_year) return CMD_ERROR;
208 
210 
211  if (b->min_length > bridge_len) return CMD_ERROR;
212  if (bridge_len <= max) return CommandCost();
213  return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
214 }
215 
228 CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
229 {
230  CompanyID company = _current_company;
231 
232  RailType railtype = INVALID_RAILTYPE;
233  RoadTypes roadtypes = ROADTYPES_NONE;
234 
235  /* unpack parameters */
236  BridgeType bridge_type = GB(p2, 0, 8);
237 
238  if (!IsValidTile(p1)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
239 
240  TransportType transport_type = Extract<TransportType, 15, 2>(p2);
241 
242  /* type of bridge */
243  switch (transport_type) {
244  case TRANSPORT_ROAD:
245  roadtypes = Extract<RoadTypes, 8, 2>(p2);
246  if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(company, roadtypes)) return CMD_ERROR;
247  break;
248 
249  case TRANSPORT_RAIL:
250  railtype = Extract<RailType, 8, 6>(p2);
251  if (!ValParamRailtype(railtype)) return CMD_ERROR;
252  break;
253 
254  case TRANSPORT_WATER:
255  break;
256 
257  default:
258  /* Airports don't have bridges. */
259  return CMD_ERROR;
260  }
261  TileIndex tile_start = p1;
262  TileIndex tile_end = end_tile;
263 
264  if (company == OWNER_DEITY) {
265  if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
266  const Town *town = CalcClosestTownFromTile(tile_start);
267 
268  company = OWNER_TOWN;
269 
270  /* If we are not within a town, we are not owned by the town */
271  if (town == NULL || DistanceSquare(tile_start, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
272  company = OWNER_NONE;
273  }
274  }
275 
276  if (tile_start == tile_end) {
277  return_cmd_error(STR_ERROR_CAN_T_START_AND_END_ON);
278  }
279 
280  Axis direction;
281  if (TileX(tile_start) == TileX(tile_end)) {
282  direction = AXIS_Y;
283  } else if (TileY(tile_start) == TileY(tile_end)) {
284  direction = AXIS_X;
285  } else {
286  return_cmd_error(STR_ERROR_START_AND_END_MUST_BE_IN);
287  }
288 
289  if (tile_end < tile_start) Swap(tile_start, tile_end);
290 
291  uint bridge_len = GetTunnelBridgeLength(tile_start, tile_end);
292  if (transport_type != TRANSPORT_WATER) {
293  /* set and test bridge length, availability */
294  CommandCost ret = CheckBridgeAvailability(bridge_type, bridge_len, flags);
295  if (ret.Failed()) return ret;
296  } else {
297  if (bridge_len > _settings_game.construction.max_bridge_length) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
298  }
299 
300  int z_start;
301  int z_end;
302  Slope tileh_start = GetTileSlope(tile_start, &z_start);
303  Slope tileh_end = GetTileSlope(tile_end, &z_end);
304  bool pbs_reservation = false;
305 
306  CommandCost terraform_cost_north = CheckBridgeSlope(BRIDGE_PIECE_NORTH, direction, &tileh_start, &z_start);
307  CommandCost terraform_cost_south = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, direction, &tileh_end, &z_end);
308 
309  /* Aqueducts can't be built of flat land. */
310  if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
311  if (z_start != z_end) return_cmd_error(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT);
312 
314  Owner owner;
315  bool is_new_owner;
316  if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
317  GetOtherBridgeEnd(tile_start) == tile_end &&
318  GetTunnelBridgeTransportType(tile_start) == transport_type) {
319  /* Replace a current bridge. */
320 
321  /* If this is a railway bridge, make sure the railtypes match. */
322  if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
323  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
324  }
325 
326  /* Do not replace town bridges with lower speed bridges, unless in scenario editor. */
327  if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
328  GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed &&
329  _game_mode != GM_EDITOR) {
330  Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
331 
332  if (t == NULL) {
333  return CMD_ERROR;
334  } else {
335  SetDParam(0, t->index);
336  return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
337  }
338  }
339 
340  /* Do not replace the bridge with the same bridge type. */
341  if (!(flags & DC_QUERY_COST) && (bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || (roadtypes & ~GetRoadTypes(tile_start)) == 0)) {
342  return_cmd_error(STR_ERROR_ALREADY_BUILT);
343  }
344 
345  /* Do not allow replacing another company's bridges. */
346  if (!IsTileOwner(tile_start, company) && !IsTileOwner(tile_start, OWNER_TOWN) && !IsTileOwner(tile_start, OWNER_NONE)) {
347  return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
348  }
349 
350  cost.AddCost((bridge_len + 1) * _price[PR_CLEAR_BRIDGE]); // The cost of clearing the current bridge.
351  owner = GetTileOwner(tile_start);
352 
353  /* If bridge belonged to bankrupt company, it has a new owner now */
354  is_new_owner = (owner == OWNER_NONE);
355  if (is_new_owner) owner = company;
356 
357  switch (transport_type) {
358  case TRANSPORT_RAIL:
359  /* Keep the reservation, the path stays valid. */
360  pbs_reservation = HasTunnelBridgeReservation(tile_start);
361  break;
362 
363  case TRANSPORT_ROAD:
364  /* Do not remove road types when upgrading a bridge */
365  roadtypes |= GetRoadTypes(tile_start);
366  break;
367 
368  default: break;
369  }
370  } else {
371  /* Build a new bridge. */
372 
373  bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
374 
375  /* Try and clear the start landscape */
376  CommandCost ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
377  if (ret.Failed()) return ret;
378  cost = ret;
379 
380  if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
381  cost.AddCost(terraform_cost_north);
382 
383  /* Try and clear the end landscape */
384  ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
385  if (ret.Failed()) return ret;
386  cost.AddCost(ret);
387 
388  /* false - end tile slope check */
389  if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
390  cost.AddCost(terraform_cost_south);
391 
392  const TileIndex heads[] = {tile_start, tile_end};
393  for (int i = 0; i < 2; i++) {
394  if (IsBridgeAbove(heads[i])) {
395  TileIndex north_head = GetNorthernBridgeEnd(heads[i]);
396 
397  if (direction == GetBridgeAxis(heads[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
398 
399  if (z_start + 1 == GetBridgeHeight(north_head)) {
400  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
401  }
402  }
403  }
404 
405  TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
406  for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
407  if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN);
408 
409  if (z_start >= (GetTileZ(tile) + _settings_game.construction.max_bridge_height)) {
410  /*
411  * Disallow too high bridges.
412  * Properly rendering a map where very high bridges (might) exist is expensive.
413  * See http://www.tt-forums.net/viewtopic.php?f=33&t=40844&start=980#p1131762
414  * for a detailed discussion. z_start here is one heightlevel below the bridge level.
415  */
416  return_cmd_error(STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN);
417  }
418 
419  if (IsBridgeAbove(tile)) {
420  /* Disallow crossing bridges for the time being */
421  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
422  }
423 
424  switch (GetTileType(tile)) {
425  case MP_WATER:
426  if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
427  break;
428 
429  case MP_RAILWAY:
430  if (!IsPlainRail(tile)) goto not_valid_below;
431  break;
432 
433  case MP_ROAD:
434  if (IsRoadDepot(tile)) goto not_valid_below;
435  break;
436 
437  case MP_TUNNELBRIDGE:
438  if (IsTunnel(tile)) break;
439  if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below;
440  if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
441  break;
442 
443  case MP_OBJECT: {
444  const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
445  if ((spec->flags & OBJECT_FLAG_ALLOW_UNDER_BRIDGE) == 0) goto not_valid_below;
446  if (GetTileMaxZ(tile) + spec->height > z_start) goto not_valid_below;
447  break;
448  }
449 
450  case MP_CLEAR:
451  break;
452 
453  default:
454  not_valid_below:;
455  /* try and clear the middle landscape */
456  ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
457  if (ret.Failed()) return ret;
458  cost.AddCost(ret);
459  break;
460  }
461 
462  if (flags & DC_EXEC) {
463  /* We do this here because when replacing a bridge with another
464  * type calling SetBridgeMiddle isn't needed. After all, the
465  * tile already has the has_bridge_above bits set. */
466  SetBridgeMiddle(tile, direction);
467  }
468  }
469 
470  owner = company;
471  is_new_owner = true;
472  }
473 
474  /* do the drill? */
475  if (flags & DC_EXEC) {
476  DiagDirection dir = AxisToDiagDir(direction);
477 
478  Company *c = Company::GetIfValid(company);
479  switch (transport_type) {
480  case TRANSPORT_RAIL:
481  /* Add to company infrastructure count if required. */
482  if (is_new_owner && c != NULL) c->infrastructure.rail[railtype] += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
483  MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
484  MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype);
485  SetTunnelBridgeReservation(tile_start, pbs_reservation);
486  SetTunnelBridgeReservation(tile_end, pbs_reservation);
487  break;
488 
489  case TRANSPORT_ROAD: {
490  RoadTypes prev_roadtypes = IsBridgeTile(tile_start) ? GetRoadTypes(tile_start) : ROADTYPES_NONE;
491  if (is_new_owner) {
492  /* Also give unowned present roadtypes to new owner */
493  if (HasBit(prev_roadtypes, ROADTYPE_ROAD) && GetRoadOwner(tile_start, ROADTYPE_ROAD) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_ROAD);
494  if (HasBit(prev_roadtypes, ROADTYPE_TRAM) && GetRoadOwner(tile_start, ROADTYPE_TRAM) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_TRAM);
495  }
496  if (c != NULL) {
497  /* Add all new road types to the company infrastructure counter. */
498  RoadType new_rt;
499  FOR_EACH_SET_ROADTYPE(new_rt, roadtypes ^ prev_roadtypes) {
500  /* A full diagonal road tile has two road bits. */
501  c->infrastructure.road[new_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
502  }
503  }
504  Owner owner_road = HasBit(prev_roadtypes, ROADTYPE_ROAD) ? GetRoadOwner(tile_start, ROADTYPE_ROAD) : company;
505  Owner owner_tram = HasBit(prev_roadtypes, ROADTYPE_TRAM) ? GetRoadOwner(tile_start, ROADTYPE_TRAM) : company;
506  MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, roadtypes);
507  MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), roadtypes);
508  break;
509  }
510 
511  case TRANSPORT_WATER:
512  if (is_new_owner && c != NULL) c->infrastructure.water += (bridge_len + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
513  MakeAqueductBridgeRamp(tile_start, owner, dir);
514  MakeAqueductBridgeRamp(tile_end, owner, ReverseDiagDir(dir));
515  break;
516 
517  default:
518  NOT_REACHED();
519  }
520 
521  /* Mark all tiles dirty */
522  MarkBridgeDirty(tile_start, tile_end, AxisToDiagDir(direction), z_start);
524  }
525 
526  if ((flags & DC_EXEC) && transport_type == TRANSPORT_RAIL) {
527  Track track = AxisToTrack(direction);
528  AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, company);
529  YapfNotifyTrackLayoutChange(tile_start, track);
530  }
531 
532  /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
533  * It's unnecessary to execute this command every time for every bridge. So it is done only
534  * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
535  */
536  Company *c = Company::GetIfValid(company);
537  if (!(flags & DC_QUERY_COST) || (c != NULL && c->is_ai)) {
538  bridge_len += 2; // begin and end tiles/ramps
539 
540  switch (transport_type) {
541  case TRANSPORT_ROAD: cost.AddCost(bridge_len * _price[PR_BUILD_ROAD] * 2 * CountBits(roadtypes)); break;
542  case TRANSPORT_RAIL: cost.AddCost(bridge_len * RailBuildCost(railtype)); break;
543  default: break;
544  }
545 
546  if (c != NULL) bridge_len = CalcBridgeLenCostFactor(bridge_len);
547 
548  if (transport_type != TRANSPORT_WATER) {
549  cost.AddCost((int64)bridge_len * _price[PR_BUILD_BRIDGE] * GetBridgeSpec(bridge_type)->price >> 8);
550  } else {
551  /* Aqueducts use a separate base cost. */
552  cost.AddCost((int64)bridge_len * _price[PR_BUILD_AQUEDUCT]);
553  }
554 
555  }
556 
557  return cost;
558 }
559 
560 
571 CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
572 {
573  CompanyID company = _current_company;
574 
575  TransportType transport_type = Extract<TransportType, 8, 2>(p1);
576 
577  RailType railtype = INVALID_RAILTYPE;
580  switch (transport_type) {
581  case TRANSPORT_RAIL:
582  railtype = Extract<RailType, 0, 6>(p1);
583  if (!ValParamRailtype(railtype)) return CMD_ERROR;
584  break;
585 
586  case TRANSPORT_ROAD:
587  rts = Extract<RoadTypes, 0, 2>(p1);
588  if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(company, rts)) return CMD_ERROR;
589  break;
590 
591  default: return CMD_ERROR;
592  }
593 
594  if (company == OWNER_DEITY) {
595  if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
596  const Town *town = CalcClosestTownFromTile(start_tile);
597 
598  company = OWNER_TOWN;
599 
600  /* If we are not within a town, we are not owned by the town */
601  if (town == NULL || DistanceSquare(start_tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
602  company = OWNER_NONE;
603  }
604  }
605 
606  int start_z;
607  int end_z;
608  Slope start_tileh = GetTileSlope(start_tile, &start_z);
609  DiagDirection direction = GetInclinedSlopeDirection(start_tileh);
610  if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL);
611 
612  if (HasTileWaterGround(start_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
613 
614  CommandCost ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
615  if (ret.Failed()) return ret;
616 
617  /* XXX - do NOT change 'ret' in the loop, as it is used as the price
618  * for the clearing of the entrance of the tunnel. Assigning it to
619  * cost before the loop will yield different costs depending on start-
620  * position, because of increased-cost-by-length: 'cost += cost >> 3' */
621 
622  TileIndexDiff delta = TileOffsByDiagDir(direction);
623  DiagDirection tunnel_in_way_dir;
624  if (DiagDirToAxis(direction) == AXIS_Y) {
625  tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
626  } else {
627  tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
628  }
629 
630  TileIndex end_tile = start_tile;
631 
632  /* Tile shift coefficient. Will decrease for very long tunnels to avoid exponential growth of price*/
633  int tiles_coef = 3;
634  /* Number of tiles from start of tunnel */
635  int tiles = 0;
636  /* Number of tiles at which the cost increase coefficient per tile is halved */
637  int tiles_bump = 25;
638 
640  Slope end_tileh;
641  for (;;) {
642  end_tile += delta;
643  if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER);
644  end_tileh = GetTileSlope(end_tile, &end_z);
645 
646  if (start_z == end_z) break;
647 
648  if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
649  return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY);
650  }
651 
652  tiles++;
653  if (tiles == tiles_bump) {
654  tiles_coef++;
655  tiles_bump *= 2;
656  }
657 
658  cost.AddCost(_price[PR_BUILD_TUNNEL]);
659  cost.AddCost(cost.GetCost() >> tiles_coef); // add a multiplier for longer tunnels
660  }
661 
662  /* Add the cost of the entrance */
663  cost.AddCost(_price[PR_BUILD_TUNNEL]);
664  cost.AddCost(ret);
665 
666  /* if the command fails from here on we want the end tile to be highlighted */
667  _build_tunnel_endtile = end_tile;
668 
669  if (tiles > _settings_game.construction.max_tunnel_length) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG);
670 
671  if (HasTileWaterGround(end_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
672 
673  /* Clear the tile in any case */
674  ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
675  if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
676  cost.AddCost(ret);
677 
678  /* slope of end tile must be complementary to the slope of the start tile */
679  if (end_tileh != ComplementSlope(start_tileh)) {
680  /* Mark the tile as already cleared for the terraform command.
681  * Do this for all tiles (like trees), not only objects. */
682  ClearedObjectArea *coa = FindClearedObject(end_tile);
683  if (coa == NULL) {
684  coa = _cleared_object_areas.Append();
685  coa->first_tile = end_tile;
686  coa->area = TileArea(end_tile, 1, 1);
687  }
688 
689  /* Hide the tile from the terraforming command */
690  TileIndex old_first_tile = coa->first_tile;
691  coa->first_tile = INVALID_TILE;
692 
693  /* CMD_TERRAFORM_LAND may append further items to _cleared_object_areas,
694  * however it will never erase or re-order existing items.
695  * _cleared_object_areas is a value-type SmallVector, therefore appending items
696  * may result in a backing-store re-allocation, which would invalidate the coa pointer.
697  * The index of the coa pointer into the _cleared_object_areas vector remains valid,
698  * and can be used safely after the CMD_TERRAFORM_LAND operation.
699  * Deliberately clear the coa pointer to avoid leaving dangling pointers which could
700  * inadvertently be dereferenced.
701  */
702  assert(coa >= _cleared_object_areas.Begin() && coa < _cleared_object_areas.End());
703  size_t coa_index = coa - _cleared_object_areas.Begin();
704  assert(coa_index < UINT_MAX); // more than 2**32 cleared areas would be a bug in itself
705  coa = NULL;
706 
707  ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND);
708  _cleared_object_areas[(uint)coa_index].first_tile = old_first_tile;
709  if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND);
710  cost.AddCost(ret);
711  }
712  cost.AddCost(_price[PR_BUILD_TUNNEL]);
713 
714  /* Pay for the rail/road in the tunnel including entrances */
715  switch (transport_type) {
716  case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * _price[PR_BUILD_ROAD] * 2); break;
717  case TRANSPORT_RAIL: cost.AddCost((tiles + 2) * RailBuildCost(railtype)); break;
718  default: NOT_REACHED();
719  }
720 
721  if (flags & DC_EXEC) {
722  Company *c = Company::GetIfValid(company);
723  uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
724  if (transport_type == TRANSPORT_RAIL) {
725  if (!IsTunnelTile(start_tile) && c != NULL) c->infrastructure.rail[railtype] += num_pieces;
726  MakeRailTunnel(start_tile, company, direction, railtype);
727  MakeRailTunnel(end_tile, company, ReverseDiagDir(direction), railtype);
728  AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company);
729  YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
730  } else {
731  if (c != NULL) {
732  RoadType rt;
733  FOR_EACH_SET_ROADTYPE(rt, rts ^ (IsTunnelTile(start_tile) ? GetRoadTypes(start_tile) : ROADTYPES_NONE)) {
734  c->infrastructure.road[rt] += num_pieces * 2; // A full diagonal road has two road bits.
735  }
736  }
737  MakeRoadTunnel(start_tile, company, direction, rts);
738  MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), rts);
739  }
741  }
742 
743  return cost;
744 }
745 
746 
753 {
754  /* Floods can remove anything as well as the scenario editor */
755  if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return CommandCost();
756 
757  switch (GetTunnelBridgeTransportType(tile)) {
758  case TRANSPORT_ROAD: {
759  RoadTypes rts = GetRoadTypes(tile);
760  Owner road_owner = _current_company;
761  Owner tram_owner = _current_company;
762 
763  if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
764  if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
765 
766  /* We can remove unowned road and if the town allows it */
768  /* Town does not allow */
769  return CheckTileOwnership(tile);
770  }
771  if (road_owner == OWNER_NONE || road_owner == OWNER_TOWN) road_owner = _current_company;
772  if (tram_owner == OWNER_NONE) tram_owner = _current_company;
773 
774  CommandCost ret = CheckOwnership(road_owner, tile);
775  if (ret.Succeeded()) ret = CheckOwnership(tram_owner, tile);
776  return ret;
777  }
778 
779  case TRANSPORT_RAIL:
780  return CheckOwnership(GetTileOwner(tile));
781 
782  case TRANSPORT_WATER: {
783  /* Always allow to remove aqueducts without owner. */
784  Owner aqueduct_owner = GetTileOwner(tile);
785  if (aqueduct_owner == OWNER_NONE) aqueduct_owner = _current_company;
786  return CheckOwnership(aqueduct_owner);
787  }
788 
789  default: NOT_REACHED();
790  }
791 }
792 
800 {
802  if (ret.Failed()) return ret;
803 
804  TileIndex endtile = GetOtherTunnelEnd(tile);
805 
806  ret = TunnelBridgeIsFree(tile, endtile);
807  if (ret.Failed()) return ret;
808 
809  _build_tunnel_endtile = endtile;
810 
811  Town *t = NULL;
812  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
813  t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
814 
815  /* Check if you are allowed to remove the tunnel owned by a town
816  * Removal depends on difficulty settings */
818  if (ret.Failed()) return ret;
819  }
820 
821  /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
822  * you have a "Poor" (0) town rating */
823  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
825  }
826 
827  uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
828 
829  if (flags & DC_EXEC) {
831  /* We first need to request values before calling DoClearSquare */
833  Track track = DiagDirToDiagTrack(dir);
834  Owner owner = GetTileOwner(tile);
835 
836  Train *v = NULL;
837  if (HasTunnelBridgeReservation(tile)) {
838  v = GetTrainForReservation(tile, track);
839  if (v != NULL) FreeTrainTrackReservation(v);
840  }
841 
842  if (Company::IsValidID(owner)) {
843  Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
845  }
846 
847  DoClearSquare(tile);
848  DoClearSquare(endtile);
849 
850  /* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
851  AddSideToSignalBuffer(tile, ReverseDiagDir(dir), owner);
852  AddSideToSignalBuffer(endtile, dir, owner);
853 
854  YapfNotifyTrackLayoutChange(tile, track);
855  YapfNotifyTrackLayoutChange(endtile, track);
856 
857  if (v != NULL) TryPathReserve(v);
858  } else {
859  RoadType rt;
861  /* A full diagonal road tile has two road bits. */
862  Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
863  if (c != NULL) {
866  }
867  }
868 
869  DoClearSquare(tile);
870  DoClearSquare(endtile);
871  }
872  }
873  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_TUNNEL] * len);
874 }
875 
876 
884 {
886  if (ret.Failed()) return ret;
887 
888  TileIndex endtile = GetOtherBridgeEnd(tile);
889 
890  ret = TunnelBridgeIsFree(tile, endtile);
891  if (ret.Failed()) return ret;
892 
893  DiagDirection direction = GetTunnelBridgeDirection(tile);
894  TileIndexDiff delta = TileOffsByDiagDir(direction);
895 
896  Town *t = NULL;
897  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
898  t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
899 
900  /* Check if you are allowed to remove the bridge owned by a town
901  * Removal depends on difficulty settings */
903  if (ret.Failed()) return ret;
904  }
905 
906  /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
907  * you have a "Poor" (0) town rating */
908  if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
910  }
911 
912  Money base_cost = (GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) ? _price[PR_CLEAR_BRIDGE] : _price[PR_CLEAR_AQUEDUCT];
913  uint len = GetTunnelBridgeLength(tile, endtile) + 2; // Don't forget the end tiles.
914 
915  if (flags & DC_EXEC) {
916  /* read this value before actual removal of bridge */
917  bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
918  Owner owner = GetTileOwner(tile);
919  int height = GetBridgeHeight(tile);
920  Train *v = NULL;
921 
922  if (rail && HasTunnelBridgeReservation(tile)) {
923  v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
924  if (v != NULL) FreeTrainTrackReservation(v);
925  }
926 
927  /* Update company infrastructure counts. */
928  if (rail) {
929  if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
930  } else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) {
931  RoadType rt;
933  Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
934  if (c != NULL) {
935  /* A full diagonal road tile has two road bits. */
938  }
939  }
940  } else { // Aqueduct
941  if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.water -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
942  }
944 
945  DoClearSquare(tile);
946  DoClearSquare(endtile);
947  for (TileIndex c = tile + delta; c != endtile; c += delta) {
948  /* do not let trees appear from 'nowhere' after removing bridge */
949  if (IsNormalRoadTile(c) && GetRoadside(c) == ROADSIDE_TREES) {
950  int minz = GetTileMaxZ(c) + 3;
951  if (height < minz) SetRoadside(c, ROADSIDE_PAVED);
952  }
954  MarkTileDirtyByTile(c, height - TileHeight(c));
955  }
956 
957  if (rail) {
958  /* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
959  AddSideToSignalBuffer(tile, ReverseDiagDir(direction), owner);
960  AddSideToSignalBuffer(endtile, direction, owner);
961 
962  Track track = DiagDirToDiagTrack(direction);
963  YapfNotifyTrackLayoutChange(tile, track);
964  YapfNotifyTrackLayoutChange(endtile, track);
965 
966  if (v != NULL) TryPathReserve(v, true);
967  }
968  }
969 
970  return CommandCost(EXPENSES_CONSTRUCTION, len * base_cost);
971 }
972 
980 {
981  if (IsTunnel(tile)) {
982  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST);
983  return DoClearTunnel(tile, flags);
984  } else { // IsBridge(tile)
985  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
986  return DoClearBridge(tile, flags);
987  }
988 }
989 
1000 static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
1001 {
1002  static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START;
1003  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);
1004 }
1005 
1017 static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, int x, int y, int w, int h)
1018 {
1019  int cur_z;
1020  for (cur_z = z_top; cur_z >= z_bottom; cur_z -= TILE_HEIGHT) {
1021  DrawPillar(psid, x, y, cur_z, w, h, NULL);
1022  }
1023  return cur_z;
1024 }
1025 
1037 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
1038 {
1039  static const int bounding_box_size[2] = {16, 2};
1040  static const int back_pillar_offset[2] = { 0, 9};
1041 
1042  static const int INF = 1000;
1043  static const SubSprite half_pillar_sub_sprite[2][2] = {
1044  { { -14, -INF, INF, INF }, { -INF, -INF, -15, INF } }, // X axis, north and south
1045  { { -INF, -INF, 15, INF }, { 16, -INF, INF, INF } }, // Y axis, north and south
1046  };
1047 
1048  if (psid->sprite == 0) return;
1049 
1050  /* Determine ground height under pillars */
1051  DiagDirection south_dir = AxisToDiagDir(axis);
1052  int z_front_north = ti->z;
1053  int z_back_north = ti->z;
1054  int z_front_south = ti->z;
1055  int z_back_south = ti->z;
1056  GetSlopePixelZOnEdge(ti->tileh, south_dir, &z_front_south, &z_back_south);
1057  GetSlopePixelZOnEdge(ti->tileh, ReverseDiagDir(south_dir), &z_front_north, &z_back_north);
1058 
1059  /* Shared height of pillars */
1060  int z_front = max(z_front_north, z_front_south);
1061  int z_back = max(z_back_north, z_back_south);
1062 
1063  /* x and y size of bounding-box of pillars */
1064  int w = bounding_box_size[axis];
1065  int h = bounding_box_size[OtherAxis(axis)];
1066  /* sprite position of back facing pillar */
1067  int x_back = x - back_pillar_offset[axis];
1068  int y_back = y - back_pillar_offset[OtherAxis(axis)];
1069 
1070  /* Draw front pillars */
1071  int bottom_z = DrawPillarColumn(z_front, z_bridge, psid, x, y, w, h);
1072  if (z_front_north < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1073  if (z_front_south < z_front) DrawPillar(psid, x, y, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1074 
1075  /* Draw back pillars, skip top two parts, which are hidden by the bridge */
1076  int z_bridge_back = z_bridge - 2 * (int)TILE_HEIGHT;
1077  if (drawfarpillar && (z_back_north <= z_bridge_back || z_back_south <= z_bridge_back)) {
1078  bottom_z = DrawPillarColumn(z_back, z_bridge_back, psid, x_back, y_back, w, h);
1079  if (z_back_north < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][0]);
1080  if (z_back_south < z_back) DrawPillar(psid, x_back, y_back, bottom_z, w, h, &half_pillar_sub_sprite[axis][1]);
1081  }
1082 }
1083 
1093 static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head)
1094 {
1095  static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
1096  static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
1097  static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
1098 
1099  static const uint size_x[6] = { 1, 16, 16, 1, 16, 1 };
1100  static const uint size_y[6] = { 16, 1, 1, 16, 1, 16 };
1101  static const uint front_bb_offset_x[6] = { 15, 0, 0, 15, 0, 15 };
1102  static const uint front_bb_offset_y[6] = { 0, 15, 15, 0, 15, 0 };
1103 
1104  /* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
1105  * The bounding boxes here are the same as for bridge front/roof */
1106  if (head || !IsInvisibilitySet(TO_BRIDGES)) {
1107  AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE,
1108  x, y, size_x[offset], size_y[offset], 0x28, z,
1109  !head && IsTransparencySet(TO_BRIDGES));
1110  }
1111 
1112  /* Do not draw catenary if it is set invisible */
1114  AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NONE,
1115  x, y, size_x[offset], size_y[offset], 0x28, z,
1117  }
1118 
1119  /* Start a new SpriteCombine for the front part */
1120  EndSpriteCombine();
1122 
1123  /* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */
1125  AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE,
1126  x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
1127  IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]);
1128  }
1129 }
1130 
1145 {
1146  TransportType transport_type = GetTunnelBridgeTransportType(ti->tile);
1147  DiagDirection tunnelbridge_direction = GetTunnelBridgeDirection(ti->tile);
1148 
1149  if (IsTunnel(ti->tile)) {
1150  /* Front view of tunnel bounding boxes:
1151  *
1152  * 122223 <- BB_Z_SEPARATOR
1153  * 1 3
1154  * 1 3 1,3 = empty helper BB
1155  * 1 3 2 = SpriteCombine of tunnel-roof and catenary (tram & elrail)
1156  *
1157  */
1158 
1159  static const int _tunnel_BB[4][12] = {
1160  /* tunnnel-roof | Z-separator | tram-catenary
1161  * w h bb_x bb_y| x y w h |bb_x bb_y w h */
1162  { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // NE
1163  { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // SE
1164  { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // SW
1165  { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // NW
1166  };
1167  const int *BB_data = _tunnel_BB[tunnelbridge_direction];
1168 
1169  bool catenary = false;
1170 
1171  SpriteID image;
1172  SpriteID railtype_overlay = 0;
1173  if (transport_type == TRANSPORT_RAIL) {
1174  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1175  image = rti->base_sprites.tunnel;
1176  if (rti->UsesOverlay()) {
1177  /* Check if the railtype has custom tunnel portals. */
1178  railtype_overlay = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL_PORTAL);
1179  if (railtype_overlay != 0) image = SPR_RAILTYPE_TUNNEL_BASE; // Draw blank grass tunnel base.
1180  }
1181  } else {
1182  image = SPR_TUNNEL_ENTRY_REAR_ROAD;
1183  }
1184 
1185  if (HasTunnelBridgeSnowOrDesert(ti->tile)) image += railtype_overlay != 0 ? 8 : 32;
1186 
1187  image += tunnelbridge_direction * 2;
1188  DrawGroundSprite(image, PAL_NONE);
1189 
1190  if (transport_type == TRANSPORT_ROAD) {
1191  RoadTypes rts = GetRoadTypes(ti->tile);
1192 
1193  if (HasBit(rts, ROADTYPE_TRAM)) {
1194  static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, { 5, 76, 77, 4 } };
1195 
1196  DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][tunnelbridge_direction], PAL_NONE);
1197 
1198  /* Do not draw wires if they are invisible */
1200  catenary = true;
1202  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);
1203  }
1204  }
1205  } else {
1206  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1207  if (rti->UsesOverlay()) {
1208  SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL);
1209  if (surface != 0) DrawGroundSprite(surface + tunnelbridge_direction, PAL_NONE);
1210  }
1211 
1212  /* PBS debugging, draw reserved tracks darker */
1213  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1214  if (rti->UsesOverlay()) {
1215  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1216  DrawGroundSprite(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH);
1217  } else {
1218  DrawGroundSprite(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH);
1219  }
1220  }
1221 
1223  /* Maybe draw pylons on the entry side */
1224  DrawRailCatenary(ti);
1225 
1226  catenary = true;
1228  /* Draw wire above the ramp */
1230  }
1231  }
1232 
1233  if (railtype_overlay != 0 && !catenary) StartSpriteCombine();
1234 
1235  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);
1236  /* Draw railtype tunnel portal overlay if defined. */
1237  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);
1238 
1239  if (catenary || railtype_overlay != 0) EndSpriteCombine();
1240 
1241  /* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
1242  AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x, ti->y, BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
1243  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);
1244 
1245  DrawBridgeMiddle(ti);
1246  } else { // IsBridge(ti->tile)
1247  const PalSpriteID *psid;
1248  int base_offset;
1249  bool ice = HasTunnelBridgeSnowOrDesert(ti->tile);
1250 
1251  if (transport_type == TRANSPORT_RAIL) {
1252  base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
1253  assert(base_offset != 8); // This one is used for roads
1254  } else {
1255  base_offset = 8;
1256  }
1257 
1258  /* as the lower 3 bits are used for other stuff, make sure they are clear */
1259  assert( (base_offset & 0x07) == 0x00);
1260 
1261  DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(tunnelbridge_direction)));
1262 
1263  /* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
1264  base_offset += (6 - tunnelbridge_direction) % 4;
1265 
1266  /* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
1267  if (transport_type != TRANSPORT_WATER) {
1268  if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
1269  psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD)[base_offset];
1270  } else {
1271  psid = _aqueduct_sprites + base_offset;
1272  }
1273 
1274  if (!ice) {
1275  TileIndex next = ti->tile + TileOffsByDiagDir(tunnelbridge_direction);
1276  if (ti->tileh != SLOPE_FLAT && ti->z == 0 && HasTileWaterClass(next) && GetWaterClass(next) == WATER_CLASS_SEA) {
1277  DrawShoreTile(ti->tileh);
1278  } else {
1279  DrawClearLandTile(ti, 3);
1280  }
1281  } else {
1282  DrawGroundSprite(SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
1283  }
1284 
1285  /* draw ramp */
1286 
1287  /* Draw Trambits and PBS Reservation as SpriteCombine */
1288  if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1289 
1290  /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1291  * it doesn't disappear behind it
1292  */
1293  /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1294  AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
1295 
1296  if (transport_type == TRANSPORT_ROAD) {
1297  RoadTypes rts = GetRoadTypes(ti->tile);
1298 
1299  if (HasBit(rts, ROADTYPE_TRAM)) {
1300  uint offset = tunnelbridge_direction;
1301  int z = ti->z;
1302  if (ti->tileh != SLOPE_FLAT) {
1303  offset = (offset + 1) & 1;
1304  z += TILE_HEIGHT;
1305  } else {
1306  offset += 2;
1307  }
1308  /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1309  DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
1310  }
1311  EndSpriteCombine();
1312  } else if (transport_type == TRANSPORT_RAIL) {
1313  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1314  if (rti->UsesOverlay()) {
1315  SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE);
1316  if (surface != 0) {
1317  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1318  AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1319  } else {
1320  AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, 16, 16, 8, ti->z);
1321  }
1322  }
1323  /* Don't fallback to non-overlay sprite -- the spec states that
1324  * if an overlay is present then the bridge surface must be
1325  * present. */
1326  }
1327 
1328  /* PBS debugging, draw reserved tracks darker */
1329  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasTunnelBridgeReservation(ti->tile)) {
1330  if (rti->UsesOverlay()) {
1331  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1332  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1333  AddSortableSpriteToDraw(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
1334  } else {
1335  AddSortableSpriteToDraw(overlay + RTO_SLOPE_NE + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1336  }
1337  } else {
1338  if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
1339  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);
1340  } else {
1341  AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
1342  }
1343  }
1344  }
1345 
1346  EndSpriteCombine();
1348  DrawRailCatenary(ti);
1349  }
1350  }
1351 
1352  DrawBridgeMiddle(ti);
1353  }
1354 }
1355 
1356 
1375 static BridgePieces CalcBridgePiece(uint north, uint south)
1376 {
1377  if (north == 1) {
1378  return BRIDGE_PIECE_NORTH;
1379  } else if (south == 1) {
1380  return BRIDGE_PIECE_SOUTH;
1381  } else if (north < south) {
1382  return north & 1 ? BRIDGE_PIECE_INNER_SOUTH : BRIDGE_PIECE_INNER_NORTH;
1383  } else if (north > south) {
1384  return south & 1 ? BRIDGE_PIECE_INNER_NORTH : BRIDGE_PIECE_INNER_SOUTH;
1385  } else {
1386  return north & 1 ? BRIDGE_PIECE_MIDDLE_EVEN : BRIDGE_PIECE_MIDDLE_ODD;
1387  }
1388 }
1389 
1395 {
1396  /* Sectional view of bridge bounding boxes:
1397  *
1398  * 1 2 1,2 = SpriteCombine of Bridge front/(back&floor) and RoadCatenary
1399  * 1 2 3 = empty helper BB
1400  * 1 7 2 4,5 = pillars under higher bridges
1401  * 1 6 88888 6 2 6 = elrail-pylons
1402  * 1 6 88888 6 2 7 = elrail-wire
1403  * 1 6 88888 6 2 <- TILE_HEIGHT 8 = rail-vehicle on bridge
1404  * 3333333333333 <- BB_Z_SEPARATOR
1405  * <- unused
1406  * 4 5 <- BB_HEIGHT_UNDER_BRIDGE
1407  * 4 5
1408  * 4 5
1409  *
1410  */
1411 
1412  if (!IsBridgeAbove(ti->tile)) return;
1413 
1414  TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile);
1415  TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile);
1416  TransportType transport_type = GetTunnelBridgeTransportType(rampsouth);
1417 
1418  Axis axis = GetBridgeAxis(ti->tile);
1419  BridgePieces piece = CalcBridgePiece(
1420  GetTunnelBridgeLength(ti->tile, rampnorth) + 1,
1421  GetTunnelBridgeLength(ti->tile, rampsouth) + 1
1422  );
1423 
1424  const PalSpriteID *psid;
1425  bool drawfarpillar;
1426  if (transport_type != TRANSPORT_WATER) {
1427  BridgeType type = GetBridgeType(rampsouth);
1428  drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
1429 
1430  uint base_offset;
1431  if (transport_type == TRANSPORT_RAIL) {
1432  base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
1433  } else {
1434  base_offset = 8;
1435  }
1436 
1437  psid = base_offset + GetBridgeSpriteTable(type, piece);
1438  } else {
1439  drawfarpillar = true;
1440  psid = _aqueduct_sprites;
1441  }
1442 
1443  if (axis != AXIS_X) psid += 4;
1444 
1445  int x = ti->x;
1446  int y = ti->y;
1447  uint bridge_z = GetBridgePixelHeight(rampsouth);
1448  int z = bridge_z - BRIDGE_Z_START;
1449 
1450  /* Add a bounding box that separates the bridge from things below it. */
1451  AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
1452 
1453  /* Draw Trambits as SpriteCombine */
1454  if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
1455 
1456  /* Draw floor and far part of bridge*/
1457  if (!IsInvisibilitySet(TO_BRIDGES)) {
1458  if (axis == AXIS_X) {
1459  AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1460  } else {
1461  AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1462  }
1463  }
1464 
1465  psid++;
1466 
1467  if (transport_type == TRANSPORT_ROAD) {
1468  RoadTypes rts = GetRoadTypes(rampsouth);
1469 
1470  if (HasBit(rts, ROADTYPE_TRAM)) {
1471  /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1472  DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD), false);
1473  } else {
1474  EndSpriteCombine();
1476  }
1477  } else if (transport_type == TRANSPORT_RAIL) {
1478  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth));
1479  if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
1480  SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE);
1481  if (surface != 0) {
1482  AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1483  }
1484  }
1485 
1486  if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
1487  if (rti->UsesOverlay()) {
1488  SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
1489  AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
1490  } else {
1491  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));
1492  }
1493  }
1494 
1495  EndSpriteCombine();
1496 
1497  if (HasRailCatenaryDrawn(GetRailType(rampsouth))) {
1499  }
1500  }
1501 
1502  /* draw roof, the component of the bridge which is logically between the vehicle and the camera */
1503  if (!IsInvisibilitySet(TO_BRIDGES)) {
1504  if (axis == AXIS_X) {
1505  y += 12;
1506  if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
1507  } else {
1508  x += 12;
1509  if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
1510  }
1511  }
1512 
1513  /* Draw TramFront as SpriteCombine */
1514  if (transport_type == TRANSPORT_ROAD) EndSpriteCombine();
1515 
1516  /* Do not draw anything more if bridges are invisible */
1517  if (IsInvisibilitySet(TO_BRIDGES)) return;
1518 
1519  psid++;
1520  if (ti->z + 5 == z) {
1521  /* draw poles below for small bridges */
1522  if (psid->sprite != 0) {
1523  SpriteID image = psid->sprite;
1524  SpriteID pal = psid->pal;
1527  pal = PALETTE_TO_TRANSPARENT;
1528  }
1529 
1530  DrawGroundSpriteAt(image, pal, x - ti->x, y - ti->y, z - ti->z);
1531  }
1532  } else {
1533  /* draw pillars below for high bridges */
1534  DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
1535  }
1536 }
1537 
1538 
1539 static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
1540 {
1541  int z;
1542  Slope tileh = GetTilePixelSlope(tile, &z);
1543 
1544  x &= 0xF;
1545  y &= 0xF;
1546 
1547  if (IsTunnel(tile)) {
1548  uint pos = (DiagDirToAxis(GetTunnelBridgeDirection(tile)) == AXIS_X ? y : x);
1549 
1550  /* In the tunnel entrance? */
1551  if (5 <= pos && pos <= 10) return z;
1552  } else { // IsBridge(tile)
1554  uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
1555 
1557 
1558  /* On the bridge ramp? */
1559  if (5 <= pos && pos <= 10) {
1560  int delta;
1561 
1562  if (tileh != SLOPE_FLAT) return z + TILE_HEIGHT;
1563 
1564  switch (dir) {
1565  default: NOT_REACHED();
1566  case DIAGDIR_NE: delta = (TILE_SIZE - 1 - x) / 2; break;
1567  case DIAGDIR_SE: delta = y / 2; break;
1568  case DIAGDIR_SW: delta = x / 2; break;
1569  case DIAGDIR_NW: delta = (TILE_SIZE - 1 - y) / 2; break;
1570  }
1571  return z + 1 + delta;
1572  }
1573  }
1574 
1575  return z + GetPartialPixelZ(x, y, tileh);
1576 }
1577 
1578 static Foundation GetFoundation_TunnelBridge(TileIndex tile, Slope tileh)
1579 {
1581 }
1582 
1583 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
1584 {
1586 
1587  if (IsTunnel(tile)) {
1588  td->str = (tt == TRANSPORT_RAIL) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD;
1589  } else { // IsBridge(tile)
1590  td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
1591  }
1592  td->owner[0] = GetTileOwner(tile);
1593 
1594  Owner road_owner = INVALID_OWNER;
1595  Owner tram_owner = INVALID_OWNER;
1596  RoadTypes rts = GetRoadTypes(tile);
1597  if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
1598  if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
1599 
1600  /* Is there a mix of owners? */
1601  if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
1602  (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
1603  uint i = 1;
1604  if (road_owner != INVALID_OWNER) {
1605  td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
1606  td->owner[i] = road_owner;
1607  i++;
1608  }
1609  if (tram_owner != INVALID_OWNER) {
1610  td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
1611  td->owner[i] = tram_owner;
1612  }
1613  }
1614 
1615  if (tt == TRANSPORT_RAIL) {
1616  const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
1617  td->rail_speed = rti->max_speed;
1618  td->railtype = rti->strings.name;
1619 
1620  if (!IsTunnel(tile)) {
1621  uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1622  if (td->rail_speed == 0 || spd < td->rail_speed) {
1623  td->rail_speed = spd;
1624  }
1625  }
1626  } else if (tt == TRANSPORT_ROAD && !IsTunnel(tile)) {
1628  }
1629 }
1630 
1631 
1632 static void TileLoop_TunnelBridge(TileIndex tile)
1633 {
1634  bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile);
1636  case LT_ARCTIC: {
1637  /* As long as we do not have a snow density, we want to use the density
1638  * from the entry edge. For tunnels this is the lowest point for bridges the highest point.
1639  * (Independent of foundations) */
1640  int z = IsBridge(tile) ? GetTileMaxZ(tile) : GetTileZ(tile);
1641  if (snow_or_desert != (z > GetSnowLine())) {
1642  SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
1643  MarkTileDirtyByTile(tile);
1644  }
1645  break;
1646  }
1647 
1648  case LT_TROPIC:
1649  if (GetTropicZone(tile) == TROPICZONE_DESERT && !snow_or_desert) {
1650  SetTunnelBridgeSnowOrDesert(tile, true);
1651  MarkTileDirtyByTile(tile);
1652  }
1653  break;
1654 
1655  default:
1656  break;
1657  }
1658 }
1659 
1660 static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
1661 {
1662  TransportType transport_type = GetTunnelBridgeTransportType(tile);
1663  if (transport_type != mode || (transport_type == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0)) return 0;
1664 
1666  if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
1668 }
1669 
1670 static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
1671 {
1672  TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
1673  /* Set number of pieces to zero if it's the southern tile as we
1674  * don't want to update the infrastructure counts twice. */
1675  uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
1676 
1677  for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
1678  /* Update all roadtypes, no matter if they are present */
1679  if (GetRoadOwner(tile, rt) == old_owner) {
1680  if (HasBit(GetRoadTypes(tile), rt)) {
1681  /* Update company infrastructure counts. A full diagonal road tile has two road bits.
1682  * No need to dirty windows here, we'll redraw the whole screen anyway. */
1683  Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2;
1684  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2;
1685  }
1686 
1687  SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
1688  }
1689  }
1690 
1691  if (!IsTileOwner(tile, old_owner)) return;
1692 
1693  /* Update company infrastructure counts for rail and water as well.
1694  * No need to dirty windows here, we'll redraw the whole screen anyway. */
1696  Company *old = Company::Get(old_owner);
1697  if (tt == TRANSPORT_RAIL) {
1698  old->infrastructure.rail[GetRailType(tile)] -= num_pieces;
1699  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.rail[GetRailType(tile)] += num_pieces;
1700  } else if (tt == TRANSPORT_WATER) {
1701  old->infrastructure.water -= num_pieces;
1702  if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.water += num_pieces;
1703  }
1704 
1705  if (new_owner != INVALID_OWNER) {
1706  SetTileOwner(tile, new_owner);
1707  } else {
1708  if (tt == TRANSPORT_RAIL) {
1709  /* Since all of our vehicles have been removed, it is safe to remove the rail
1710  * bridge / tunnel. */
1712  assert(ret.Succeeded());
1713  } else {
1714  /* In any other case, we can safely reassign the ownership to OWNER_NONE. */
1715  SetTileOwner(tile, OWNER_NONE);
1716  }
1717  }
1718 }
1719 
1725 static const byte TUNNEL_SOUND_FRAME = 1;
1726 
1735 extern const byte _tunnel_visibility_frame[DIAGDIR_END] = {12, 8, 8, 12};
1736 
1737 static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
1738 {
1739  int z = GetSlopePixelZ(x, y) - v->z_pos;
1740 
1741  if (abs(z) > 2) return VETSB_CANNOT_ENTER;
1742  /* Direction into the wormhole */
1743  const DiagDirection dir = GetTunnelBridgeDirection(tile);
1744  /* Direction of the vehicle */
1745  const DiagDirection vdir = DirToDiagDir(v->direction);
1746  /* New position of the vehicle on the tile */
1747  byte pos = (DiagDirToAxis(vdir) == AXIS_X ? x : y) & TILE_UNIT_MASK;
1748  /* Number of units moved by the vehicle since entering the tile */
1749  byte frame = (vdir == DIAGDIR_NE || vdir == DIAGDIR_NW) ? TILE_SIZE - 1 - pos : pos;
1750 
1751  if (IsTunnel(tile)) {
1752  if (v->type == VEH_TRAIN) {
1753  Train *t = Train::From(v);
1754 
1755  if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
1756  if (t->IsFrontEngine() && frame == TUNNEL_SOUND_FRAME) {
1757  if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
1758  SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
1759  }
1760  return VETSB_CONTINUE;
1761  }
1762  if (frame == _tunnel_visibility_frame[dir]) {
1763  t->tile = tile;
1764  t->track = TRACK_BIT_WORMHOLE;
1765  t->vehstatus |= VS_HIDDEN;
1766  return VETSB_ENTERED_WORMHOLE;
1767  }
1768  }
1769 
1770  if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1771  /* We're at the tunnel exit ?? */
1772  t->tile = tile;
1773  t->track = DiagDirToDiagTrackBits(vdir);
1774  assert(t->track);
1775  t->vehstatus &= ~VS_HIDDEN;
1776  return VETSB_ENTERED_WORMHOLE;
1777  }
1778  } else if (v->type == VEH_ROAD) {
1779  RoadVehicle *rv = RoadVehicle::From(v);
1780 
1781  /* Enter tunnel? */
1782  if (rv->state != RVSB_WORMHOLE && dir == vdir) {
1783  if (frame == _tunnel_visibility_frame[dir]) {
1784  /* Frame should be equal to the next frame number in the RV's movement */
1785  assert(frame == rv->frame + 1);
1786  rv->tile = tile;
1787  rv->state = RVSB_WORMHOLE;
1788  rv->vehstatus |= VS_HIDDEN;
1789  return VETSB_ENTERED_WORMHOLE;
1790  } else {
1791  return VETSB_CONTINUE;
1792  }
1793  }
1794 
1795  /* We're at the tunnel exit ?? */
1796  if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
1797  rv->tile = tile;
1798  rv->state = DiagDirToDiagTrackdir(vdir);
1799  rv->frame = frame;
1800  rv->vehstatus &= ~VS_HIDDEN;
1801  return VETSB_ENTERED_WORMHOLE;
1802  }
1803  }
1804  } else { // IsBridge(tile)
1805  if (v->type != VEH_SHIP) {
1806  /* modify speed of vehicle */
1807  uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1808 
1809  if (v->type == VEH_ROAD) spd *= 2;
1810  Vehicle *first = v->First();
1811  first->cur_speed = min(first->cur_speed, spd);
1812  }
1813 
1814  if (vdir == dir) {
1815  /* Vehicle enters bridge at the last frame inside this tile. */
1816  if (frame != TILE_SIZE - 1) return VETSB_CONTINUE;
1817  switch (v->type) {
1818  case VEH_TRAIN: {
1819  Train *t = Train::From(v);
1820  t->track = TRACK_BIT_WORMHOLE;
1823  break;
1824  }
1825 
1826  case VEH_ROAD: {
1827  RoadVehicle *rv = RoadVehicle::From(v);
1828  rv->state = RVSB_WORMHOLE;
1829  /* There are no slopes inside bridges / tunnels. */
1832  break;
1833  }
1834 
1835  case VEH_SHIP:
1837  break;
1838 
1839  default: NOT_REACHED();
1840  }
1841  return VETSB_ENTERED_WORMHOLE;
1842  } else if (vdir == ReverseDiagDir(dir)) {
1843  v->tile = tile;
1844  switch (v->type) {
1845  case VEH_TRAIN: {
1846  Train *t = Train::From(v);
1847  if (t->track == TRACK_BIT_WORMHOLE) {
1848  t->track = DiagDirToDiagTrackBits(vdir);
1849  return VETSB_ENTERED_WORMHOLE;
1850  }
1851  break;
1852  }
1853 
1854  case VEH_ROAD: {
1855  RoadVehicle *rv = RoadVehicle::From(v);
1856  if (rv->state == RVSB_WORMHOLE) {
1857  rv->state = DiagDirToDiagTrackdir(vdir);
1858  rv->frame = 0;
1859  return VETSB_ENTERED_WORMHOLE;
1860  }
1861  break;
1862  }
1863 
1864  case VEH_SHIP: {
1865  Ship *ship = Ship::From(v);
1866  if (ship->state == TRACK_BIT_WORMHOLE) {
1867  ship->state = DiagDirToDiagTrackBits(vdir);
1868  return VETSB_ENTERED_WORMHOLE;
1869  }
1870  break;
1871  }
1872 
1873  default: NOT_REACHED();
1874  }
1875  }
1876  }
1877  return VETSB_CONTINUE;
1878 }
1879 
1880 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
1881 {
1883  DiagDirection direction = GetTunnelBridgeDirection(tile);
1884  Axis axis = DiagDirToAxis(direction);
1885  CommandCost res;
1886  int z_old;
1887  Slope tileh_old = GetTileSlope(tile, &z_old);
1888 
1889  /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
1890  if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
1891  CheckBridgeSlope(BRIDGE_PIECE_SOUTH, axis, &tileh_old, &z_old);
1892  res = CheckBridgeSlope(BRIDGE_PIECE_SOUTH, axis, &tileh_new, &z_new);
1893  } else {
1894  CheckBridgeSlope(BRIDGE_PIECE_NORTH, axis, &tileh_old, &z_old);
1895  res = CheckBridgeSlope(BRIDGE_PIECE_NORTH, axis, &tileh_new, &z_new);
1896  }
1897 
1898  /* Surface slope is valid and remains unchanged? */
1899  if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
1900  }
1901 
1902  return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
1903 }
1904 
1905 extern const TileTypeProcs _tile_type_tunnelbridge_procs = {
1906  DrawTile_TunnelBridge, // draw_tile_proc
1907  GetSlopePixelZ_TunnelBridge, // get_slope_z_proc
1908  ClearTile_TunnelBridge, // clear_tile_proc
1909  NULL, // add_accepted_cargo_proc
1910  GetTileDesc_TunnelBridge, // get_tile_desc_proc
1911  GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc
1912  NULL, // click_tile_proc
1913  NULL, // animate_tile_proc
1914  TileLoop_TunnelBridge, // tile_loop_proc
1915  ChangeTileOwner_TunnelBridge, // change_tile_owner_proc
1916  NULL, // add_produced_cargo_proc
1917  VehicleEnter_TunnelBridge, // vehicle_enter_tile_proc
1918  GetFoundation_TunnelBridge, // get_foundation_proc
1919  TerraformTile_TunnelBridge, // terraform_tile_proc
1920 };
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
Definition: bridge_map.cpp:61
static bool HasSlopeHighestCorner(Slope s)
Tests if a slope has a highest corner (i.e.
Definition: slope_func.h:115
Functions related to OTTD&#39;s strings.
static TileType GetTileType(TileIndex tile)
Get the tiletype of a given tile.
Definition: tile_map.h:98
Road vehicle states.
don&#39;t allow building on structures
Definition: command_type.h:346
uint ApplyFoundationToSlope(Foundation f, Slope *s)
Applies a foundation to a slope.
Definition: landscape.cpp:164
static void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:277
TileIndex first_tile
The first tile being cleared, which then causes the whole object to be cleared.
Definition: object_base.h:90
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:1577
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:298
Year avail_year
the year where it becomes available
Definition: bridge.h:44
static TropicZone GetTropicZone(TileIndex tile)
Get the tropic zone.
Definition: tile_map.h:240
static TransportType GetTunnelBridgeTransportType(TileIndex t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
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:200
Tile information, used while rendering the tile.
Definition: tile_cmd.h:44
south and east corner are raised
Definition: slope_type.h:59
SpriteID single_sloped
single piece of rail for slopes
Definition: rail.h:134
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:1530
bool HasBridgeFlatRamp(Slope tileh, Axis axis)
Determines if the track on a bridge ramp is flat or goes up/down.
uint32 squared_town_zone_radius[HZB_END]
UpdateTownRadius updates this given the house count.
Definition: town.h:50
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Definition: landscape.cpp:217
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:347
A tile with road (or tram tracks)
Definition: tile_type.h:45
Bridge surface images.
Definition: rail.h:48
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:208
static void MakeRailTunnel(TileIndex t, Owner o, DiagDirection d, RailType r)
Makes a rail tunnel entrance.
Definition: tunnel_map.h:74
Piece of rail on slope with north-east raised.
Definition: rail.h:68
Transport over water.
Functions related to vehicles.
static TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track bits incidating with that diagdir. ...
Definition: track_func.h:534
void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner)
Add side of tile to signal update buffer.
Definition: signal.cpp:614
static bool HasTileWaterGround(TileIndex t)
Checks whether the tile has water at the ground.
Definition: water_map.h: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:29
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:463
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:522
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:152
const byte _tunnel_visibility_frame[DIAGDIR_END]
Frame when a vehicle should be hidden in a tunnel with a certain direction.
A railway.
Definition: tile_type.h:44
static Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track AXIS_X -> TRACK_X AXIS_Y -> TRACK_Y Uses the fact that the...
Definition: track_func.h:76
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:84
bool IsTunnelInWayDir(TileIndex tile, int z, DiagDirection dir)
Is there a tunnel in the way in the given direction?
Definition: tunnel_map.cpp:50
Contains objects such as transmitters and owned land.
Definition: tile_type.h:53
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:751
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
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:472
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:64
Owner owner[4]
Name of the owner(s)
Definition: tile_cmd.h:55
TileIndex GetNorthernBridgeEnd(TileIndex t)
Finds the northern end of a bridge starting at a middle tile.
Definition: bridge_map.cpp:41
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track)
Use this function to notify YAPF that track layout (or signal configuration) has change.
Definition: yapf_rail.cpp:644
north and east corner are raised
Definition: slope_type.h:60
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:118
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition: tile_map.cpp:123
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:351
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:61
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:163
SpriteID single_y
single piece of rail in Y direction, without ground
Definition: rail.h:129
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition: viewport.cpp:761
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:216
Base for all objects.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold...
Definition: town_cmd.cpp:3329
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
struct RailtypeInfo::@40 strings
Strings associated with the rail type.
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:131
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:440
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:86
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:84
StringID owner_type[4]
Type of each owner.
Definition: tile_cmd.h:56
Road with trees on paved sidewalks.
Definition: road_map.h:453
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:43
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:568
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:180
struct RailtypeInfo::@37 base_sprites
Struct containing the main sprites.
static DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:343
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:62
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:282
static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
Remove a bridge from the game, update town rating, etc.
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in #ZOOM_LVL_BASE.
Definition: tile_type.h:18
Train * GetTrainForReservation(TileIndex tile, Track track)
Find the train which has reserved a specific path.
Definition: pbs.cpp:333
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:883
uint16 max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:222
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:92
The tile has no ownership.
Definition: company_type.h:27
Northwest.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:1785
static Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition: track_func.h:547
SpriteID single_x
single piece of rail in X direction, without ground
Definition: rail.h:128
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:27
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:168
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:594
static TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition: track_func.h:398
bool build_on_slopes
allow building on slopes
bool Failed() const
Did this command fail?
Definition: command_type.h:161
Piece of rail in Y direction.
Definition: rail.h:85
Trams.
Definition: road_type.h:39
All ships have this type.
Definition: ship.h:28
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:654
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:473
static const SpriteID SPR_RAILTYPE_TUNNEL_BASE
Tunnel sprites with grass only for custom railtype tunnel.
Definition: sprites.h:293
Ship vehicle type.
Definition: vehicle_type.h:28
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
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition: company_base.h:130
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:3304
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:345
void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2)
Determine the Z height of the corners of a specific tile edge.
Definition: landscape.cpp:395
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:143
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:1580
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:346
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:52
when a sprite is to be displayed transparently, this bit needs to be set.
Definition: sprites.h:1519
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:2236
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:570
byte GetSnowLine()
Get the current snow line, either variable or static.
Definition: landscape.cpp:646
uint BridgeType
Bridge spec number.
Definition: bridge.h:38
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-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:187
Base for ships.
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
Definition: sprites.h:266
TileIndex GetOtherTunnelEnd(TileIndex tile)
Gets the other end of the tunnel.
Definition: tunnel_map.cpp:24
static uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition: slope_func.h:417
static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
Remove a tunnel from the game, update town rating, etc.
ConstructionSettings construction
construction of things in-game
Functions that have tunnels and bridges in common.
static TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition: map_func.h:181
static 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:167
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:136
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:45
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:547
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:179
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:2674
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:56
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:3445
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:3408
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:26
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
static CommandCost CheckBridgeSlope(BridgePieces bridge_piece, Axis axis, Slope *tileh, int *z)
Determines the foundation for the bridge head, and tests if the resulting slope is valid...
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:26
uint32 water
Count of company owned track bits for canals.
Definition: company_base.h:35