OpenTTD Source 20250818-master-g1850ad1aa2
follow_track.hpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#ifndef FOLLOW_TRACK_HPP
11#define FOLLOW_TRACK_HPP
12
13#include "../pbs.h"
14#include "../roadveh.h"
15#include "../station_base.h"
16#include "../train.h"
17#include "../tunnelbridge.h"
18#include "../tunnelbridge_map.h"
19#include "../depot_map.h"
20#include "pathfinder_func.h"
21
27template <TransportType Ttr_type_, typename VehicleType, bool T90deg_turns_allowed_ = true, bool Tmask_reserved_tracks = false>
29 enum ErrorCode : uint8_t {
30 EC_NONE,
31 EC_OWNER,
32 EC_RAIL_ROAD_TYPE,
33 EC_90DEG,
34 EC_NO_WAY,
35 EC_RESERVED,
36 };
37
45 bool is_tunnel;
46 bool is_bridge;
49 ErrorCode err;
50 RailTypes railtypes;
51
52 inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES)
53 {
54 Init(v, railtype_override);
55 }
56
57 inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES)
58 {
59 assert(IsRailTT());
60 this->veh = nullptr;
61 Init(o, railtype_override);
62 }
63
64 inline void Init(const VehicleType *v, RailTypes railtype_override)
65 {
66 assert(!IsRailTT() || (v != nullptr && v->type == VEH_TRAIN));
67 this->veh = v;
68 Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override);
69 }
70
71 inline void Init(Owner o, RailTypes railtype_override)
72 {
73 assert(!IsRoadTT() || this->veh != nullptr);
74 assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES);
75 this->veh_owner = o;
76 /* don't worry, all is inlined so compiler should remove unnecessary initializations */
77 this->old_tile = INVALID_TILE;
78 this->old_td = INVALID_TRACKDIR;
79 this->new_tile = INVALID_TILE;
80 this->new_td_bits = TRACKDIR_BIT_NONE;
81 this->exitdir = INVALID_DIAGDIR;
82 this->is_station = false;
83 this->is_bridge = false;
84 this->is_tunnel = false;
85 this->tiles_skipped = 0;
86 this->err = EC_NONE;
87 this->railtypes = railtype_override;
88 }
89
90 debug_inline static TransportType TT() { return Ttr_type_; }
91 debug_inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; }
92 debug_inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; }
93 inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(this->veh)->roadtype); }
94 debug_inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; }
95 static inline bool Allow90degTurns() { return T90deg_turns_allowed_; }
96 static inline bool DoTrackMasking() { return Tmask_reserved_tracks; }
97
100 {
101 assert(this->IsTram()); // this function shouldn't be called in other cases
102
103 if (IsNormalRoadTile(tile)) {
104 RoadBits rb = GetRoadBits(tile, RTT_TRAM);
105 switch (rb) {
106 case ROAD_NW: return DIAGDIR_NW;
107 case ROAD_SW: return DIAGDIR_SW;
108 case ROAD_SE: return DIAGDIR_SE;
109 case ROAD_NE: return DIAGDIR_NE;
110 default: break;
111 }
112 }
113 return INVALID_DIAGDIR;
114 }
115
121 {
122 this->old_tile = old_tile;
123 this->old_td = old_td;
124 this->err = EC_NONE;
125
126 assert([&]() {
127 if (this->IsTram() && this->GetSingleTramBit(this->old_tile) != INVALID_DIAGDIR) return true; // Skip the check for single tram bits
128 const uint sub_mode = (IsRoadTT() && this->veh != nullptr) ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0;
129 const TrackdirBits old_tile_valid_dirs = TrackStatusToTrackdirBits(GetTileTrackStatus(this->old_tile, TT(), sub_mode));
130 return (old_tile_valid_dirs & TrackdirToTrackdirBits(this->old_td)) != TRACKDIR_BIT_NONE;
131 }());
132
133 this->exitdir = TrackdirToExitdir(this->old_td);
134 if (this->ForcedReverse()) return true;
135 if (!this->CanExitOldTile()) return false;
136 this->FollowTileExit();
137 if (!this->QueryNewTileTrackStatus()) return TryReverse();
138 this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
139 if (this->new_td_bits == TRACKDIR_BIT_NONE || !this->CanEnterNewTile()) {
140 /* In case we can't enter the next tile, but are
141 * a normal road vehicle, then we can actually
142 * try to reverse as this is the end of the road.
143 * Trams can only turn on the appropriate bits in
144 * which case reaching this would mean a dead end
145 * near a building and in that case there would
146 * a "false" QueryNewTileTrackStatus result and
147 * as such reversing is already tried. The fact
148 * that function failed can have to do with a
149 * missing road bit, or inability to connect the
150 * different bits due to slopes. */
151 if (IsRoadTT() && !this->IsTram() && this->TryReverse()) return true;
152
153 /* CanEnterNewTile already set a reason.
154 * Do NOT overwrite it (important for example for EC_RAIL_ROAD_TYPE).
155 * Only set a reason if CanEnterNewTile was not called */
156 if (this->new_td_bits == TRACKDIR_BIT_NONE) this->err = EC_NO_WAY;
157
158 return false;
159 }
160 if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(this->old_tile), GetTileRailType(this->new_tile), !Allow90degTurns()))) {
161 this->new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(this->old_td);
162 if (this->new_td_bits == TRACKDIR_BIT_NONE) {
163 this->err = EC_90DEG;
164 return false;
165 }
166 }
167 return true;
168 }
169
170 inline bool MaskReservedTracks()
171 {
172 if (!DoTrackMasking()) return true;
173
174 if (this->is_station) {
175 /* Check skipped station tiles as well. */
176 TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
177 for (TileIndex tile = this->new_tile - diff * this->tiles_skipped; tile != this->new_tile; tile += diff) {
178 if (HasStationReservation(tile)) {
179 this->new_td_bits = TRACKDIR_BIT_NONE;
180 this->err = EC_RESERVED;
181 return false;
182 }
183 }
184 }
185
186 TrackBits reserved = GetReservedTrackbits(this->new_tile);
187 /* Mask already reserved trackdirs. */
188 this->new_td_bits &= ~TrackBitsToTrackdirBits(reserved);
189 /* Mask out all trackdirs that conflict with the reservation. */
191 if (TracksOverlap(reserved | TrackToTrackBits(t))) this->new_td_bits &= ~TrackToTrackdirBits(t);
192 }
193 if (this->new_td_bits == TRACKDIR_BIT_NONE) {
194 this->err = EC_RESERVED;
195 return false;
196 }
197 return true;
198 }
199
200protected:
202 inline void FollowTileExit()
203 {
204 this->is_station = false;
205 this->is_bridge = false;
206 this->is_tunnel = false;
207 this->tiles_skipped = 0;
208
209 /* extra handling for tunnels and bridges in our direction */
210 if (IsTileType(this->old_tile, MP_TUNNELBRIDGE)) {
211 DiagDirection enterdir = GetTunnelBridgeDirection(this->old_tile);
212 if (enterdir == this->exitdir) {
213 /* we are entering the tunnel / bridge */
214 if (IsTunnel(this->old_tile)) {
215 this->is_tunnel = true;
216 this->new_tile = GetOtherTunnelEnd(this->old_tile);
217 } else { // IsBridge(old_tile)
218 this->is_bridge = true;
219 this->new_tile = GetOtherBridgeEnd(this->old_tile);
220 }
221 this->tiles_skipped = GetTunnelBridgeLength(this->new_tile, this->old_tile);
222 return;
223 }
224 assert(ReverseDiagDir(enterdir) == this->exitdir);
225 }
226
227 /* normal or station tile, do one step */
228 this->new_tile = TileAddByDiagDir(this->old_tile, this->exitdir);
229
230 /* special handling for stations */
231 if (IsRailTT() && HasStationTileRail(this->new_tile)) {
232 this->is_station = true;
233 } else if (IsRoadTT() && IsStationRoadStopTile(this->new_tile)) {
234 this->is_station = true;
235 }
236 }
237
240 {
241 if (IsRailTT() && IsPlainRailTile(this->new_tile)) {
242 this->new_td_bits = (TrackdirBits)(GetTrackBits(this->new_tile) * 0x101);
243 } else if (IsRoadTT()) {
244 this->new_td_bits = GetTrackdirBitsForRoad(this->new_tile, this->IsTram() ? RTT_TRAM : RTT_ROAD);
245 } else {
246 this->new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(this->new_tile, TT(), 0));
247 }
248 return (this->new_td_bits != TRACKDIR_BIT_NONE);
249 }
250
252 inline bool CanExitOldTile()
253 {
254 /* road stop can be left at one direction only unless it's a drive-through stop */
255 if (IsRoadTT() && IsBayRoadStopTile(this->old_tile)) {
256 DiagDirection exitdir = GetBayRoadStopDir(this->old_tile);
257 if (exitdir != this->exitdir) {
258 this->err = EC_NO_WAY;
259 return false;
260 }
261 }
262
263 /* single tram bits can only be left in one direction */
264 if (this->IsTram()) {
265 DiagDirection single_tram = GetSingleTramBit(this->old_tile);
266 if (single_tram != INVALID_DIAGDIR && single_tram != this->exitdir) {
267 this->err = EC_NO_WAY;
268 return false;
269 }
270 }
271
272 /* road depots can be also left in one direction only */
273 if (IsRoadTT() && IsDepotTypeTile(this->old_tile, TT())) {
275 if (exitdir != this->exitdir) {
276 this->err = EC_NO_WAY;
277 return false;
278 }
279 }
280 return true;
281 }
282
284 inline bool CanEnterNewTile()
285 {
286 if (IsRoadTT() && IsBayRoadStopTile(this->new_tile)) {
287 /* road stop can be entered from one direction only unless it's a drive-through stop */
288 DiagDirection exitdir = GetBayRoadStopDir(this->new_tile);
289 if (ReverseDiagDir(exitdir) != this->exitdir) {
290 this->err = EC_NO_WAY;
291 return false;
292 }
293 }
294
295 /* single tram bits can only be entered from one direction */
296 if (this->IsTram()) {
297 DiagDirection single_tram = this->GetSingleTramBit(this->new_tile);
298 if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(this->exitdir)) {
299 this->err = EC_NO_WAY;
300 return false;
301 }
302 }
303
304 /* road and rail depots can also be entered from one direction only */
305 if (IsRoadTT() && IsDepotTypeTile(this->new_tile, TT())) {
307 if (ReverseDiagDir(exitdir) != this->exitdir) {
308 this->err = EC_NO_WAY;
309 return false;
310 }
311 /* don't try to enter other company's depots */
312 if (GetTileOwner(this->new_tile) != this->veh_owner) {
313 this->err = EC_OWNER;
314 return false;
315 }
316 }
317 if (IsRailTT() && IsDepotTypeTile(this->new_tile, TT())) {
319 if (ReverseDiagDir(exitdir) != this->exitdir) {
320 this->err = EC_NO_WAY;
321 return false;
322 }
323 }
324
325 /* rail transport is possible only on tiles with the same owner as vehicle */
326 if (IsRailTT() && GetTileOwner(this->new_tile) != this->veh_owner) {
327 /* different owner */
328 this->err = EC_NO_WAY;
329 return false;
330 }
331
332 /* rail transport is possible only on compatible rail types */
333 if (IsRailTT() && this->railtypes.Any()) {
334 RailType rail_type = GetTileRailType(this->new_tile);
335 if (!this->railtypes.Test(rail_type)) {
336 /* incompatible rail type */
337 this->err = EC_RAIL_ROAD_TYPE;
338 return false;
339 }
340 }
341
342 /* road transport is possible only on compatible road types */
343 if (IsRoadTT()) {
344 const RoadVehicle *v = RoadVehicle::From(this->veh);
345 RoadType roadtype = GetRoadType(this->new_tile, GetRoadTramType(v->roadtype));
346 if (!v->compatible_roadtypes.Test(roadtype)) {
347 /* incompatible road type */
348 this->err = EC_RAIL_ROAD_TYPE;
349 return false;
350 }
351 }
352
353 /* tunnel holes and bridge ramps can be entered only from proper direction */
354 if (IsTileType(this->new_tile, MP_TUNNELBRIDGE)) {
355 if (IsTunnel(this->new_tile)) {
356 if (!this->is_tunnel) {
357 DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(this->new_tile);
358 if (tunnel_enterdir != this->exitdir) {
359 this->err = EC_NO_WAY;
360 return false;
361 }
362 }
363 } else { // IsBridge(new_tile)
364 if (!this->is_bridge) {
365 DiagDirection ramp_enderdir = GetTunnelBridgeDirection(this->new_tile);
366 if (ramp_enderdir != this->exitdir) {
367 this->err = EC_NO_WAY;
368 return false;
369 }
370 }
371 }
372 }
373
374 /* special handling for rail stations - get to the end of platform */
375 if (IsRailTT() && this->is_station) {
376 /* entered railway station
377 * get platform length */
378 uint length = BaseStation::GetByTile(this->new_tile)->GetPlatformLength(this->new_tile, TrackdirToExitdir(this->old_td));
379 /* how big step we must do to get to the last platform tile? */
380 this->tiles_skipped = length - 1;
381 /* move to the platform end */
382 TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
383 diff *= this->tiles_skipped;
384 this->new_tile = TileAdd(this->new_tile, diff);
385 return true;
386 }
387
388 return true;
389 }
390
392 inline bool ForcedReverse()
393 {
394 /* rail and road depots cause reversing */
395 if (!IsWaterTT() && IsDepotTypeTile(this->old_tile, TT())) {
396 DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(this->old_tile) : GetRoadDepotDirection(this->old_tile);
397 if (exitdir != this->exitdir) {
398 /* reverse */
399 this->new_tile = this->old_tile;
400 this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
401 this->exitdir = exitdir;
402 this->tiles_skipped = 0;
403 this->is_tunnel = false;
404 this->is_bridge = false;
405 this->is_station = false;
406 return true;
407 }
408 }
409
410 /* Single tram bits and standard road stops cause reversing. */
411 if (IsRoadTT() && ((this->IsTram() && GetSingleTramBit(this->old_tile) == ReverseDiagDir(this->exitdir)) ||
412 (IsBayRoadStopTile(this->old_tile) && GetBayRoadStopDir(this->old_tile) == ReverseDiagDir(this->exitdir)))) {
413 /* reverse */
414 this->new_tile = this->old_tile;
415 this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
416 this->exitdir = ReverseDiagDir(this->exitdir);
417 this->tiles_skipped = 0;
418 this->is_tunnel = false;
419 this->is_bridge = false;
420 this->is_station = false;
421 return true;
422 }
423
424 return false;
425 }
426
428 inline bool TryReverse()
429 {
430 if (IsRoadTT() && !this->IsTram()) {
431 /* if we reached the end of road, we can reverse the RV and continue moving */
432 this->exitdir = ReverseDiagDir(this->exitdir);
433 /* new tile will be the same as old one */
434 this->new_tile = this->old_tile;
435 /* set new trackdir bits to all reachable trackdirs */
437 this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
438 if (this->new_td_bits != TRACKDIR_BIT_NONE) {
439 /* we have some trackdirs reachable after reversal */
440 return true;
441 }
442 }
443 this->err = EC_NO_WAY;
444 return false;
445 }
446
447public:
449 int GetSpeedLimit(int *pmin_speed = nullptr) const
450 {
451 int min_speed = 0;
452 int max_speed = INT_MAX; // no limit
453
454 /* Check for on-bridge speed limit */
455 if (!IsWaterTT() && IsBridgeTile(this->old_tile)) {
456 int spd = GetBridgeSpec(GetBridgeType(this->old_tile))->speed;
457 if (IsRoadTT()) spd *= 2;
458 max_speed = std::min(max_speed, spd);
459 }
460 /* Check for speed limit imposed by railtype */
461 if (IsRailTT()) {
462 uint16_t rail_speed = GetRailTypeInfo(GetRailType(this->old_tile))->max_speed;
463 if (rail_speed > 0) max_speed = std::min<int>(max_speed, rail_speed);
464 }
465 if (IsRoadTT()) {
466 /* max_speed is already in roadvehicle units, no need to further modify (divide by 2) */
467 uint16_t road_speed = GetRoadTypeInfo(GetRoadType(this->old_tile, GetRoadTramType(RoadVehicle::From(this->veh)->roadtype)))->max_speed;
468 if (road_speed > 0) max_speed = std::min<int>(max_speed, road_speed);
469 }
470
471 /* if min speed was requested, return it */
472 if (pmin_speed != nullptr) *pmin_speed = min_speed;
473 return max_speed;
474 }
475};
476
480
482
485
486#endif /* FOLLOW_TRACK_HPP */
const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition bridge.h:60
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
bool IsBridgeTile(Tile t)
checks if there is a bridge on this tile
Definition bridge_map.h:35
BridgeType GetBridgeType(Tile t)
Determines the type of bridge on a tile.
Definition bridge_map.h:56
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:222
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:133
static constexpr Owner INVALID_OWNER
An invalid owner.
bool IsDepotTypeTile(Tile tile, TransportType type)
Check if a tile is a depot and it is a depot of the given type.
Definition depot_map.h:19
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
@ DIAGDIR_SW
Southwest.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:610
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
Definition map_func.h:456
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:569
int32_t TileIndexDiff
An offset value between two tiles.
Definition map_type.h:23
General functions related to pathfinders.
TrackdirBits GetTrackdirBitsForRoad(TileIndex tile, RoadTramType rtt)
Wrapper around GetTileTrackStatus() and TrackStatusToTrackdirBits(), as for single tram bits GetTileT...
TrackBits GetReservedTrackbits(TileIndex t)
Get the reserved trackbits for any tile, regardless of type.
Definition pbs.cpp:24
RailType GetTileRailType(Tile tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition rail.cpp:155
bool Rail90DegTurnDisallowed(RailType rt1, RailType rt2, bool def=_settings_game.pf.forbid_90_deg)
Test if 90 degree turns are disallowed between two railtypes.
Definition rail.h:363
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:300
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition rail_map.h:115
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition rail_map.h:136
DiagDirection GetRailDepotDirection(Tile t)
Returns the direction the depot is facing to.
Definition rail_map.h:171
static debug_inline bool IsPlainRailTile(Tile t)
Checks whether the tile is a rail tile or rail tile with signals.
Definition rail_map.h:60
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:230
static debug_inline bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition road_map.h:58
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:112
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition road_map.h:545
RoadBits
Enumeration for the road parts on a tile.
Definition road_type.h:40
@ ROAD_SW
South-west part.
Definition road_type.h:43
@ ROAD_NE
North-east part.
Definition road_type.h:45
@ ROAD_SE
South-east part.
Definition road_type.h:44
@ ROAD_NW
North-west part.
Definition road_type.h:42
RoadType
The different roadtypes we support.
Definition road_type.h:23
bool IsStationRoadStopTile(Tile t)
Is tile t a road stop station?
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
bool HasStationTileRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
bool HasStationReservation(Tile t)
Get the reservation state of the rail station.
DiagDirection GetBayRoadStopDir(Tile t)
Gets the direction the bay road stop entrance points towards.
virtual uint GetPlatformLength(TileIndex tile) const =0
Obtain the length of a platform.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition bridge.h:39
Track follower helper template class (can serve pathfinders and vehicle controllers).
bool CanExitOldTile()
return true if we can leave old_tile in exitdir
bool Follow(TileIndex old_tile, Trackdir old_td)
main follower routine.
bool CanEnterNewTile()
return true if we can enter new_tile from exitdir
bool is_tunnel
last turn passed tunnel
bool QueryNewTileTrackStatus()
stores track status (available trackdirs) for the new tile into new_td_bits
bool TryReverse()
return true if we successfully reversed at end of road/track
bool is_bridge
last turn passed bridge ramp
int GetSpeedLimit(int *pmin_speed=nullptr) const
Helper for pathfinders - get min/max speed on the old_tile/old_td.
const VehicleType * veh
moving vehicle
bool ForcedReverse()
return true if we must reverse (in depots and single tram bits)
int tiles_skipped
number of skipped tunnel or station tiles
DiagDirection exitdir
exit direction (leaving the old tile)
TrackdirBits new_td_bits
the new set of available trackdirs
void FollowTileExit()
Follow the exitdir from old_tile and fill new_tile and tiles_skipped.
TileIndex new_tile
the new tile (the vehicle has entered)
Trackdir old_td
the trackdir (the vehicle was on) before move
bool is_station
last turn passed station
DiagDirection GetSingleTramBit(TileIndex tile)
Tests if a tile is a road tile with a single tramtrack (tram can reverse)
Owner veh_owner
owner of the vehicle
TileIndex old_tile
the origin (vehicle moved from) before move
Buses, trucks and trams belong to this class.
Definition roadveh.h:98
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition roadveh.h:110
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition roadveh.h:108
Iterable ensemble of each set bit in a value.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
'Train' is either a loco or a wagon.
Definition train.h:91
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition track_func.h:77
TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition track_func.h:352
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:247
bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition track_func.h:645
TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
Maps a trackdir to all trackdirs that make 90 deg turns with it.
Definition track_func.h:606
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:555
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
Definition track_func.h:111
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition track_func.h:439
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition track_func.h:308
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:66
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:85
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:97
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:98
Track
These are used to specify a single track.
Definition track_type.h:19
TransportType
Available types of transport.
@ TRANSPORT_RAIL
Transport by train.
@ TRANSPORT_ROAD
Transport by road vehicle.
@ TRANSPORT_WATER
Transport over water.
TileIndex GetOtherTunnelEnd(TileIndex tile)
Gets the other end of the tunnel.
bool IsTunnel(Tile t)
Is this a tunnel (entrance)?
Definition tunnel_map.h:23
uint GetTunnelBridgeLength(TileIndex begin, TileIndex end)
Calculates the length of a tunnel or a bridge (without end tiles)
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
VehicleType
Available vehicle types.
@ VEH_TRAIN
Train vehicle type.