35 } |
35 } |
36 |
36 |
37 FORCEINLINE static TransportType TT() {return Ttr_type_;} |
37 FORCEINLINE static TransportType TT() {return Ttr_type_;} |
38 FORCEINLINE static bool IsWaterTT() {return TT() == TRANSPORT_WATER;} |
38 FORCEINLINE static bool IsWaterTT() {return TT() == TRANSPORT_WATER;} |
39 FORCEINLINE static bool IsRailTT() {return TT() == TRANSPORT_RAIL;} |
39 FORCEINLINE static bool IsRailTT() {return TT() == TRANSPORT_RAIL;} |
|
40 FORCEINLINE bool IsTram() {return IsRoadTT() && HasBit(m_veh->u.road.compatible_roadtypes, ROADTYPE_TRAM);} |
40 FORCEINLINE static bool IsRoadTT() {return TT() == TRANSPORT_ROAD;} |
41 FORCEINLINE static bool IsRoadTT() {return TT() == TRANSPORT_ROAD;} |
41 FORCEINLINE static bool Allow90degTurns() {return T90deg_turns_allowed_;} |
42 FORCEINLINE static bool Allow90degTurns() {return T90deg_turns_allowed_;} |
|
43 |
|
44 /** Tests if a tile is a road tile with a single tramtrack (tram can reverse) */ |
|
45 FORCEINLINE DiagDirection GetSingleTramBit(TileIndex tile) |
|
46 { |
|
47 if (IsTram() && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL) { |
|
48 RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM); |
|
49 switch (rb) { |
|
50 case ROAD_NW: return DIAGDIR_NW; |
|
51 case ROAD_SW: return DIAGDIR_SW; |
|
52 case ROAD_SE: return DIAGDIR_SE; |
|
53 case ROAD_NE: return DIAGDIR_NE; |
|
54 default: break; |
|
55 } |
|
56 } |
|
57 return INVALID_DIAGDIR; |
|
58 } |
42 |
59 |
43 /** main follower routine. Fills all members and return true on success. |
60 /** main follower routine. Fills all members and return true on success. |
44 * Otherwise returns false if track can't be followed. */ |
61 * Otherwise returns false if track can't be followed. */ |
45 FORCEINLINE bool Follow(TileIndex old_tile, Trackdir old_td) |
62 FORCEINLINE bool Follow(TileIndex old_tile, Trackdir old_td) |
46 { |
63 { |
47 m_old_tile = old_tile; |
64 m_old_tile = old_tile; |
48 m_old_td = old_td; |
65 m_old_td = old_td; |
49 m_err = EC_NONE; |
66 m_err = EC_NONE; |
50 assert((GetTileTrackStatus(m_old_tile, TT(), m_veh->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(m_old_td)) != 0); |
67 assert(((GetTileTrackStatus(m_old_tile, TT(), m_veh->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(m_old_td)) != 0) || |
|
68 (GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR)); // Disable the assertion for single tram bits |
51 m_exitdir = TrackdirToExitdir(m_old_td); |
69 m_exitdir = TrackdirToExitdir(m_old_td); |
52 if (EnteredDepot()) return true; |
70 if (ForcedReverse()) return true; |
53 if (!CanExitOldTile()) return false; |
71 if (!CanExitOldTile()) return false; |
54 FollowTileExit(); |
72 FollowTileExit(); |
55 if (!QueryNewTileTrackStatus()) return TryReverse(); |
73 if (!QueryNewTileTrackStatus()) return TryReverse(); |
56 if (!CanEnterNewTile()) return false; |
74 if (!CanEnterNewTile()) return false; |
57 m_new_td_bits &= DiagdirReachesTrackdirs(m_exitdir); |
75 m_new_td_bits &= DiagdirReachesTrackdirs(m_exitdir); |
74 FORCEINLINE void FollowTileExit() |
92 FORCEINLINE void FollowTileExit() |
75 { |
93 { |
76 m_is_station = m_is_bridge = m_is_tunnel = false; |
94 m_is_station = m_is_bridge = m_is_tunnel = false; |
77 m_tiles_skipped = 0; |
95 m_tiles_skipped = 0; |
78 |
96 |
79 // extra handling for tunnels in our direction |
97 // extra handling for tunnels and bridges in our direction |
80 if (IsTunnelTile(m_old_tile)) { |
98 if (IsTileType(m_old_tile, MP_TUNNELBRIDGE)) { |
81 DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(m_old_tile); |
99 DiagDirection enterdir = GetTunnelBridgeDirection(m_old_tile); |
82 if (tunnel_enterdir == m_exitdir) { |
100 if (enterdir == m_exitdir) { |
83 // we are entering the tunnel |
101 // we are entering the tunnel / bridge |
84 FindLengthOfTunnelResult flotr = FindLengthOfTunnel(m_old_tile, m_exitdir); |
102 if (IsTunnel(m_old_tile)) { |
85 m_new_tile = flotr.tile; |
103 m_is_tunnel = true; |
86 m_is_tunnel = true; |
104 m_new_tile = GetOtherTunnelEnd(m_old_tile); |
87 m_tiles_skipped = flotr.length - 1; |
105 } else { // IsBridge(m_old_tile) |
|
106 m_is_bridge = true; |
|
107 m_new_tile = GetOtherBridgeEnd(m_old_tile); |
|
108 } |
|
109 m_tiles_skipped = GetTunnelBridgeLength(m_new_tile, m_old_tile); |
88 return; |
110 return; |
89 } |
111 } |
90 assert(ReverseDiagDir(tunnel_enterdir) == m_exitdir); |
112 assert(ReverseDiagDir(enterdir) == m_exitdir); |
91 } |
|
92 |
|
93 // extra handling for bridge ramp in our direction |
|
94 if (IsBridgeTile(m_old_tile)) { |
|
95 DiagDirection bridge_enterdir = GetTunnelBridgeDirection(m_old_tile); |
|
96 if (bridge_enterdir == m_exitdir) { |
|
97 // we are entering the bridge ramp |
|
98 m_new_tile = GetOtherBridgeEnd(m_old_tile); |
|
99 uint32 bridge_length = GetBridgeLength(m_old_tile, m_new_tile); |
|
100 m_tiles_skipped = bridge_length; |
|
101 m_is_bridge = true; |
|
102 return; |
|
103 } |
|
104 assert(ReverseDiagDir(bridge_enterdir) == m_exitdir); |
|
105 } |
113 } |
106 |
114 |
107 // normal or station tile, do one step |
115 // normal or station tile, do one step |
108 TileIndexDiff diff = TileOffsByDiagDir(m_exitdir); |
116 TileIndexDiff diff = TileOffsByDiagDir(m_exitdir); |
109 m_new_tile = TILE_ADD(m_old_tile, diff); |
117 m_new_tile = TILE_ADD(m_old_tile, diff); |
125 if (IsRailTT() && GetTileType(m_new_tile) == MP_RAILWAY && IsPlainRailTile(m_new_tile)) { |
133 if (IsRailTT() && GetTileType(m_new_tile) == MP_RAILWAY && IsPlainRailTile(m_new_tile)) { |
126 m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101); |
134 m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101); |
127 } else { |
135 } else { |
128 uint32 ts = GetTileTrackStatus(m_new_tile, TT(), m_veh->u.road.compatible_roadtypes); |
136 uint32 ts = GetTileTrackStatus(m_new_tile, TT(), m_veh->u.road.compatible_roadtypes); |
129 m_new_td_bits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK); |
137 m_new_td_bits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK); |
|
138 |
|
139 if (m_new_td_bits == 0) { |
|
140 /* GetTileTrackStatus() returns 0 for single tram bits. |
|
141 * As we cannot change it there (easily) without breaking something, change it here */ |
|
142 switch (GetSingleTramBit(m_new_tile)) { |
|
143 case DIAGDIR_NE: |
|
144 case DIAGDIR_SW: |
|
145 m_new_td_bits = TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW; |
|
146 break; |
|
147 |
|
148 case DIAGDIR_NW: |
|
149 case DIAGDIR_SE: |
|
150 m_new_td_bits = TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE; |
|
151 break; |
|
152 |
|
153 default: break; |
|
154 } |
|
155 } |
130 } |
156 } |
131 return (m_new_td_bits != TRACKDIR_BIT_NONE); |
157 return (m_new_td_bits != TRACKDIR_BIT_NONE); |
132 } |
158 } |
133 |
159 |
134 /** return true if we can leave m_old_tile in m_exitdir */ |
160 /** return true if we can leave m_old_tile in m_exitdir */ |
141 m_err = EC_NO_WAY; |
167 m_err = EC_NO_WAY; |
142 return false; |
168 return false; |
143 } |
169 } |
144 } |
170 } |
145 |
171 |
|
172 /* single tram bits can only be left in one direction */ |
|
173 DiagDirection single_tram = GetSingleTramBit(m_old_tile); |
|
174 if (single_tram != INVALID_DIAGDIR && single_tram != m_exitdir) { |
|
175 m_err = EC_NO_WAY; |
|
176 return false; |
|
177 } |
|
178 |
146 // road depots can be also left in one direction only |
179 // road depots can be also left in one direction only |
147 if (IsRoadTT() && IsTileDepotType(m_old_tile, TT())) { |
180 if (IsRoadTT() && IsTileDepotType(m_old_tile, TT())) { |
148 DiagDirection exitdir = GetRoadDepotDirection(m_old_tile); |
181 DiagDirection exitdir = GetRoadDepotDirection(m_old_tile); |
149 if (exitdir != m_exitdir) { |
182 if (exitdir != m_exitdir) { |
150 m_err = EC_NO_WAY; |
183 m_err = EC_NO_WAY; |
162 DiagDirection exitdir = GetRoadStopDir(m_new_tile); |
195 DiagDirection exitdir = GetRoadStopDir(m_new_tile); |
163 if (ReverseDiagDir(exitdir) != m_exitdir) { |
196 if (ReverseDiagDir(exitdir) != m_exitdir) { |
164 m_err = EC_NO_WAY; |
197 m_err = EC_NO_WAY; |
165 return false; |
198 return false; |
166 } |
199 } |
|
200 } |
|
201 |
|
202 /* single tram bits can only be entered from one direction */ |
|
203 DiagDirection single_tram = GetSingleTramBit(m_new_tile); |
|
204 if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(m_exitdir)) { |
|
205 m_err = EC_NO_WAY; |
|
206 return false; |
167 } |
207 } |
168 |
208 |
169 // road and rail depots can also be entered from one direction only |
209 // road and rail depots can also be entered from one direction only |
170 if (IsRoadTT() && IsTileDepotType(m_new_tile, TT())) { |
210 if (IsRoadTT() && IsTileDepotType(m_new_tile, TT())) { |
171 DiagDirection exitdir = GetRoadDepotDirection(m_new_tile); |
211 DiagDirection exitdir = GetRoadDepotDirection(m_new_tile); |
240 } |
280 } |
241 |
281 |
242 return true; |
282 return true; |
243 } |
283 } |
244 |
284 |
245 /** return true if we entered depot and reversed inside */ |
285 /** return true if we must reverse (in depots and single tram bits) */ |
246 FORCEINLINE bool EnteredDepot() |
286 FORCEINLINE bool ForcedReverse() |
247 { |
287 { |
248 // rail and road depots cause reversing |
288 // rail and road depots cause reversing |
249 if (!IsWaterTT() && IsTileDepotType(m_old_tile, TT())) { |
289 if (!IsWaterTT() && IsTileDepotType(m_old_tile, TT())) { |
250 DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(m_old_tile) : GetRoadDepotDirection(m_old_tile); |
290 DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(m_old_tile) : GetRoadDepotDirection(m_old_tile); |
251 if (exitdir != m_exitdir) { |
291 if (exitdir != m_exitdir) { |
256 m_tiles_skipped = 0; |
296 m_tiles_skipped = 0; |
257 m_is_tunnel = m_is_bridge = m_is_station = false; |
297 m_is_tunnel = m_is_bridge = m_is_station = false; |
258 return true; |
298 return true; |
259 } |
299 } |
260 } |
300 } |
|
301 |
|
302 // single tram bits cause reversing |
|
303 if (GetSingleTramBit(m_old_tile) == ReverseDiagDir(m_exitdir)) { |
|
304 // reverse |
|
305 m_new_tile = m_old_tile; |
|
306 m_new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(m_old_td)); |
|
307 m_exitdir = ReverseDiagDir(m_exitdir); |
|
308 m_tiles_skipped = 0; |
|
309 m_is_tunnel = m_is_bridge = m_is_station = false; |
|
310 return true; |
|
311 } |
|
312 |
261 return false; |
313 return false; |
262 } |
314 } |
263 |
315 |
264 /** return true if we successfully reversed at end of road/track */ |
316 /** return true if we successfully reversed at end of road/track */ |
265 FORCEINLINE bool TryReverse() |
317 FORCEINLINE bool TryReverse() |
266 { |
318 { |
267 if (IsRoadTT()) { |
319 if (IsRoadTT() && !IsTram()) { |
268 // if we reached the end of road, we can reverse the RV and continue moving |
320 // if we reached the end of road, we can reverse the RV and continue moving |
269 m_exitdir = ReverseDiagDir(m_exitdir); |
321 m_exitdir = ReverseDiagDir(m_exitdir); |
270 // new tile will be the same as old one |
322 // new tile will be the same as old one |
271 m_new_tile = m_old_tile; |
323 m_new_tile = m_old_tile; |
272 // set new trackdir bits to all reachable trackdirs |
324 // set new trackdir bits to all reachable trackdirs |