Files @ r14743:6ee8646cf93f
Branch filter:

Location: cpp/openttd-patchpack/source/src/train.h - annotation

terkhen
(svn r19341) -Codechange: Move GOINGUP/GOINGDOWN flags to GroundVehicle.
-Codechange: Move GetSlopeResistance to GroundVehicle.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
r5475:3f5cd13d1b63
r5475:3f5cd13d1b63
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r9111:983de9c5a848
r6422:5983361e241a
r5475:3f5cd13d1b63
r5475:3f5cd13d1b63
r5475:3f5cd13d1b63
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14739:f991a219ff8a
r5475:3f5cd13d1b63
r11980:193f7a6b6e37
r5475:3f5cd13d1b63
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r5475:3f5cd13d1b63
r5475:3f5cd13d1b63
r9704:108fa337b182
r7490:4e86e893fa7f
r11980:193f7a6b6e37
r11980:193f7a6b6e37
r9810:a537c0857d3f
r11980:193f7a6b6e37
r11980:193f7a6b6e37
r11982:ff4390b32b95
r14740:9c3af6ca7b4c
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r14393:2a8179560351
r14393:2a8179560351
r14393:2a8179560351
r11982:ff4390b32b95
r12080:8115dddfc1a2
r12080:8115dddfc1a2
r12080:8115dddfc1a2
r12080:8115dddfc1a2
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r11982:ff4390b32b95
r13171:0e07c3ba2aa9
r11982:ff4390b32b95
r11982:ff4390b32b95
r6552:7cade7798fcb
r12033:6a560c929ec8
r6552:7cade7798fcb
r14739:f991a219ff8a
r11982:ff4390b32b95
r11982:ff4390b32b95
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r11981:3840cc07cbe4
r14203:aea88883737e
r14203:aea88883737e
r14203:aea88883737e
r12090:c20f83257241
r14739:f991a219ff8a
r6552:7cade7798fcb
r7412:e5f07529a093
r6552:7cade7798fcb
r14741:668486b3d9e3
r14741:668486b3d9e3
r6563:67c636a8e3d4
r6553:04028e73a0f7
r6558:469828caa298
r6563:67c636a8e3d4
r6593:469af92ae569
r12290:442d5d533a57
r9022:5be8b7703ae9
r11982:ff4390b32b95
r11982:ff4390b32b95
r7488:e5f4cea230c4
r12423:199e8b46a11b
r13938:79b6be1ab675
r13938:79b6be1ab675
r11965:2b94ac4aa35a
r8467:0ea88f22d4aa
r13863:252b1a5c4f87
r11971:ac7eb21a00e4
r8827:6ee5217ef94b
r8890:02179c54681e
r12290:442d5d533a57
r12413:18cb483f6737
r12296:564aa4953d26
r14251:3ca1b5f41119
r14251:3ca1b5f41119
r14251:3ca1b5f41119
r14251:3ca1b5f41119
r14274:562f45526a0b
r14274:562f45526a0b
r14251:3ca1b5f41119
r14251:3ca1b5f41119
r14276:fe74de3c3311
r14276:fe74de3c3311
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12290:442d5d533a57
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12293:15e6328523ce
r12291:690f4158878e
r12291:690f4158878e
r12290:442d5d533a57
r12290:442d5d533a57
r12291:690f4158878e
r12291:690f4158878e
r12291:690f4158878e
r12291:690f4158878e
r12291:690f4158878e
r12291:690f4158878e
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12292:c3b6baef441a
r12295:bb9023f54628
r12292:c3b6baef441a
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12440:97b7db79722d
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r12296:564aa4953d26
r14276:fe74de3c3311
r14276:fe74de3c3311
r14509:7fa74c77b7ed
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14292:0a897b68b658
r14276:fe74de3c3311
r14292:0a897b68b658
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14276:fe74de3c3311
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14372:c020b32eb5e4
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r14738:57a777833535
r6552:7cade7798fcb
r6552:7cade7798fcb
r12029:5b077ec055c0
r12029:5b077ec055c0
r5475:3f5cd13d1b63
/* $Id$ */

/*
 * This file is part of OpenTTD.
 * 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.
 * 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.
 * 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/>.
 */

/** @file train.h Base for the train class. */

#ifndef TRAIN_H
#define TRAIN_H

#include "newgrf_engine.h"
#include "cargotype.h"
#include "rail.h"
#include "engine_base.h"
#include "rail_map.h"
#include "ground_vehicle.hpp"

struct Train;

enum VehicleRailFlags {
	VRF_REVERSING         = 0,

	/* used to store if a wagon is powered or not */
	VRF_POWEREDWAGON      = 3,

	/* used to reverse the visible direction of the vehicle */
	VRF_REVERSE_DIRECTION = 4,

	/* used to mark train as lost because PF can't find the route */
	VRF_NO_PATH_TO_DESTINATION = 5,

	/* used to mark that electric train engine is allowed to run on normal rail */
	VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL = 6,

	/* used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle only) */
	VRF_TOGGLE_REVERSE = 7,

	/* used to mark a train that can't get a path reservation */
	VRF_TRAIN_STUCK    = 8,
};

byte FreightWagonMult(CargoID cargo);

void CheckTrainsLengths();

void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);

int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);

/** Variables that are cached to improve performance and such */
struct TrainCache {
	/* Cached wagon override spritegroup */
	const struct SpriteGroup *cached_override;

	uint16 last_speed; // NOSAVE: only used in UI

	/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
	uint16 cached_total_length; ///< Length of the whole train, valid only for first engine.
	uint8 cached_veh_length;    ///< length of this vehicle in units of 1/8 of normal length, cached because this can be set by a callback
	bool cached_tilt;           ///< train can tilt; feature provides a bonus in curves

	/* cached max. speed / acceleration data */
	uint16 cached_max_speed;    ///< max speed of the consist. (minimum of the max speed of all vehicles in the consist)
	int cached_max_curve_speed; ///< max consist speed limited by curves

	/**
	 * Position/type of visual effect.
	 * bit 0 - 3 = position of effect relative to vehicle. (0 = front, 8 = centre, 15 = rear)
	 * bit 4 - 5 = type of effect. (0 = default for engine class, 1 = steam, 2 = diesel, 3 = electric)
	 * bit     6 = disable visual effect.
	 * bit     7 = disable powered wagons.
	 */
	byte cached_vis_effect;
	byte user_def_data;

	EngineID first_engine;  ///< cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
};

/**
 * 'Train' is either a loco or a wagon.
 */
struct Train : public GroundVehicle<Train, VEH_TRAIN> {
	TrainCache tcache;

	/* Link between the two ends of a multiheaded engine */
	Train *other_multiheaded_part;

	uint16 crash_anim_pos;

	uint16 flags;
	TrackBitsByte track;
	byte force_proceed;
	RailTypeByte railtype;
	RailTypes compatible_railtypes;

	/** Ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through signals. */
	uint16 wait_counter;

	/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
	Train() : GroundVehicle<Train, VEH_TRAIN>() {}
	/** We want to 'destruct' the right class. */
	virtual ~Train() { this->PreDestructor(); }

	friend struct GroundVehicle<Train, VEH_TRAIN>; // GroundVehicle needs to use the acceleration functions defined at Train.

	const char *GetTypeString() const { return "train"; }
	void MarkDirty();
	void UpdateDeltaXY(Direction direction);
	ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
	void PlayLeaveStationSound() const;
	bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
	SpriteID GetImage(Direction direction) const;
	int GetDisplaySpeed() const { return this->tcache.last_speed; }
	int GetDisplayMaxSpeed() const { return this->tcache.cached_max_speed; }
	Money GetRunningCost() const;
	int GetDisplayImageWidth(Point *offset = NULL) const;
	bool IsInDepot() const;
	bool IsStoppedInDepot() const;
	bool Tick();
	void OnNewDay();
	uint Crash(bool flooded = false);
	Trackdir GetVehicleTrackdir() const;
	TileIndex GetOrderStationLocation(StationID station);
	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);

	void ReserveTrackUnderConsist() const;

	int GetCurveSpeedLimit() const;

	void ConsistChanged(bool same_length);

	int UpdateSpeed();

	void UpdateAcceleration();

	int GetCurrentMaxSpeed() const;

	/**
	 * enum to handle train subtypes
	 * Do not access it directly unless you have to. Use the access functions below
	 * This is an enum to tell what bit to access as it is a bitmask
	 */
	enum TrainSubtype {
		TS_FRONT             = 0, ///< Leading engine of a train
		TS_ARTICULATED_PART  = 1, ///< Articulated part of an engine
		TS_WAGON             = 2, ///< Wagon
		TS_ENGINE            = 3, ///< Engine, that can be front engine, but might be placed behind another engine
		TS_FREE_WAGON        = 4, ///< First in a wagon chain (in depot)
		TS_MULTIHEADED       = 5, ///< Engine is multiheaded
	};

	/**
	 * Set front engine state
	 */
	FORCEINLINE void SetFrontEngine() { SetBit(this->subtype, TS_FRONT); }

	/**
	 * Remove the front engine state
	 */
	FORCEINLINE void ClearFrontEngine() { ClrBit(this->subtype, TS_FRONT); }

	/**
	 * Set a vehicle to be an articulated part
	 */
	FORCEINLINE void SetArticulatedPart() { SetBit(this->subtype, TS_ARTICULATED_PART); }

	/**
	 * Clear a vehicle from being an articulated part
	 */
	FORCEINLINE void ClearArticulatedPart() { ClrBit(this->subtype, TS_ARTICULATED_PART); }

	/**
	 * Set a vehicle to be a wagon
	 */
	FORCEINLINE void SetWagon() { SetBit(this->subtype, TS_WAGON); }

	/**
	 * Clear wagon property
	 */
	FORCEINLINE void ClearWagon() { ClrBit(this->subtype, TS_WAGON); }

	/**
	 * Set engine status
	 */
	FORCEINLINE void SetEngine() { SetBit(this->subtype, TS_ENGINE); }

	/**
	 * Clear engine status
	 */
	FORCEINLINE void ClearEngine() { ClrBit(this->subtype, TS_ENGINE); }

	/**
	 * Set if a vehicle is a free wagon
	 */
	FORCEINLINE void SetFreeWagon() { SetBit(this->subtype, TS_FREE_WAGON); }

	/**
	 * Clear a vehicle from being a free wagon
	 */
	FORCEINLINE void ClearFreeWagon() { ClrBit(this->subtype, TS_FREE_WAGON); }

	/**
	 * Set if a vehicle is a multiheaded engine
	 */
	FORCEINLINE void SetMultiheaded() { SetBit(this->subtype, TS_MULTIHEADED); }

	/**
	 * Clear multiheaded engine property
	 */
	FORCEINLINE void ClearMultiheaded() { ClrBit(this->subtype, TS_MULTIHEADED); }


	/**
	 * Check if train is a front engine
	 * @return Returns true if train is a front engine
	 */
	FORCEINLINE bool IsFrontEngine() const { return HasBit(this->subtype, TS_FRONT); }

	/**
	 * Check if train is a free wagon (got no engine in front of it)
	 * @return Returns true if train is a free wagon
	 */
	FORCEINLINE bool IsFreeWagon() const { return HasBit(this->subtype, TS_FREE_WAGON); }

	/**
	 * Check if a vehicle is an engine (can be first in a train)
	 * @return Returns true if vehicle is an engine
	 */
	FORCEINLINE bool IsEngine() const { return HasBit(this->subtype, TS_ENGINE); }

	/**
	 * Check if a train is a wagon
	 * @return Returns true if vehicle is a wagon
	 */
	FORCEINLINE bool IsWagon() const { return HasBit(this->subtype, TS_WAGON); }

	/**
	 * Check if train is a multiheaded engine
	 * @return Returns true if vehicle is a multiheaded engine
	 */
	FORCEINLINE bool IsMultiheaded() const { return HasBit(this->subtype, TS_MULTIHEADED); }

	/**
	 * Tell if we are dealing with the rear end of a multiheaded engine.
	 * @return True if the engine is the rear part of a dualheaded engine.
	 */
	FORCEINLINE bool IsRearDualheaded() const { return this->IsMultiheaded() && !this->IsEngine(); }

	/**
	 * Check if train is an articulated part of an engine
	 * @return Returns true if train is an articulated part
	 */
	FORCEINLINE bool IsArticulatedPart() const { return HasBit(this->subtype, TS_ARTICULATED_PART); }

	/**
	 * Check if an engine has an articulated part.
	 * @return True if the engine has an articulated part.
	 */
	FORCEINLINE bool HasArticulatedPart() const { return this->Next() != NULL && this->Next()->IsArticulatedPart(); }


	/**
	 * Get the next part of a multi-part engine.
	 * Will only work on a multi-part engine (this->EngineHasArticPart() == true),
	 * Result is undefined for normal engine.
	 * @return next part of articulated engine
	 */
	FORCEINLINE Train *GetNextArticPart() const
	{
		assert(this->HasArticulatedPart());
		return this->Next();
	}

	/**
	 * Get the first part of a multi-part engine.
	 * @return First part of the engine.
	 */
	FORCEINLINE Train *GetFirstEnginePart()
	{
		Train *v = this;
		while (v->IsArticulatedPart()) v = v->Previous();
		return v;
	}

	/**
	 * Get the first part of a multi-part engine.
	 * @return First part of the engine.
	 */
	FORCEINLINE const Train *GetFirstEnginePart() const
	{
		const Train *v = this;
		while (v->IsArticulatedPart()) v = v->Previous();
		return v;
	}

	/**
	 * Get the last part of a multi-part engine.
	 * @return Last part of the engine.
	 */
	FORCEINLINE Train *GetLastEnginePart()
	{
		Train *v = this;
		while (v->HasArticulatedPart()) v = v->GetNextArticPart();
		return v;
	}

	/**
	 * Get the next real (non-articulated part) vehicle in the consist.
	 * @return Next vehicle in the consist.
	 */
	FORCEINLINE Train *GetNextVehicle() const
	{
		const Train *v = this;
		while (v->HasArticulatedPart()) v = v->GetNextArticPart();

		/* v now contains the last artic part in the engine */
		return v->Next();
	}

	/**
	 * Get the previous real (non-articulated part) vehicle in the consist.
	 * @return Previous vehicle in the consist.
	 */
	FORCEINLINE Train *GetPrevVehicle() const
	{
		Train *v = this->Previous();
		while (v != NULL && v->IsArticulatedPart()) v = v->Previous();

		return v;
	}

	/**
	 * Get the next real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
	 * @return Next vehicle in the consist.
	 */
	FORCEINLINE Train *GetNextUnit() const
	{
		Train *v = this->GetNextVehicle();
		if (v != NULL && v->IsRearDualheaded()) v = v->GetNextVehicle();

		return v;
	}

	/**
	 * Get the previous real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
	 * @return Previous vehicle in the consist.
	 */
	FORCEINLINE Train *GetPrevUnit()
	{
		Train *v = this->GetPrevVehicle();
		if (v != NULL && v->IsRearDualheaded()) v = v->GetPrevVehicle();

		return v;
	}


protected: // These functions should not be called outside acceleration code.

	/**
	 * Allows to know the power value that this vehicle will use.
	 * @return Power value from the engine in HP, or zero if the vehicle is not powered.
	 */
	FORCEINLINE uint16 GetPower() const
	{
		/* Power is not added for articulated parts */
		if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
			uint16 power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
			/* Halve power for multiheaded parts */
			if (this->IsMultiheaded()) power /= 2;
			return power;
		}

		return 0;
	}

	/**
	 * Returns a value if this articulated part is powered.
	 * @return Power value from the articulated part in HP, or zero if it is not powered.
	 */
	FORCEINLINE uint16 GetPoweredPartPower(const Train *head) const
	{
		if (HasBit(this->flags, VRF_POWEREDWAGON) && HasPowerOnRail(head->railtype, GetRailType(head->tile))) {
			return RailVehInfo(this->tcache.first_engine)->pow_wag_power;
		}

		return 0;
	}

	/**
	 * Allows to know the weight value that this vehicle will use.
	 * @return Weight value from the engine in tonnes.
	 */
	FORCEINLINE uint16 GetWeight() const
	{
		uint16 weight = (CargoSpec::Get(this->cargo_type)->weight * this->cargo.Count() * FreightWagonMult(this->cargo_type)) / 16;

		/* Vehicle weight is not added for articulated parts. */
		if (!this->IsArticulatedPart()) {
			weight += GetVehicleProperty(this, PROP_TRAIN_WEIGHT, RailVehInfo(this->engine_type)->weight);
		}

		/* Powered wagons have extra weight added. */
		if (HasBit(this->flags, VRF_POWEREDWAGON)) {
			weight += RailVehInfo(this->tcache.first_engine)->pow_wag_weight;
		}

		return weight;
	}

	/**
	 * Allows to know the tractive effort value that this vehicle will use.
	 * @return Tractive effort value from the engine.
	 */
	FORCEINLINE byte GetTractiveEffort() const
	{
		return GetVehicleProperty(this, PROP_TRAIN_TRACTIVE_EFFORT, RailVehInfo(this->engine_type)->tractive_effort);
	}

	/**
	 * Checks the current acceleration status of this vehicle.
	 * @return Acceleration status.
	 */
	FORCEINLINE AccelStatus GetAccelerationStatus() const
	{
		return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) ? AS_BRAKE : AS_ACCEL;
	}

	/**
	 * Calculates the current speed of this vehicle.
	 * @return Current speed in mph.
	 */
	FORCEINLINE uint16 GetCurrentSpeed() const
	{
		return this->cur_speed * 10 / 16;
	}

	/**
	 * Returns the rolling friction coefficient of this vehicle.
	 * @return Rolling friction coefficient in [1e-3].
	 */
	FORCEINLINE uint32 GetRollingFriction() const
	{
		return 35;
	}

	/**
	 * Allows to know the acceleration type of a vehicle.
	 * @return Acceleration type of the vehicle.
	 */
	FORCEINLINE int GetAccelerationType() const
	{
		return GetRailTypeInfo(this->railtype)->acceleration_type;
	}

	/**
	 * Returns the slope steepness used by this vehicle.
	 * @return Slope steepness used by the vehicle.
	 */
	FORCEINLINE uint32 GetSlopeSteepness() const
	{
		return 20 * _settings_game.vehicle.train_slope_steepness; // 1% slope * slope steepness
	}

	/**
	 * Gets the maximum speed of the vehicle, ignoring the limitations of the kind of track the vehicle is on.
	 * @return Maximum speed of the vehicle.
	 */
	FORCEINLINE uint16 GetInitialMaxSpeed() const
	{
		return this->tcache.cached_max_speed;
	}

	/**
	 * Gets the maximum speed allowed by the track for this vehicle.
	 * @return Maximum speed allowed.
	 */
	FORCEINLINE uint16 GetMaxTrackSpeed() const
	{
		return GetRailTypeInfo(GetRailType(this->tile))->max_speed;
	}
};

#define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)

#endif /* TRAIN_H */