OpenTTD Source 20241224-master-gf74b0cf984
vehicle_sl.cpp
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#include "../stdafx.h"
11
12#include "saveload.h"
14
15#include "../debug.h"
16#include "../vehicle_func.h"
17#include "../train.h"
18#include "../roadveh.h"
19#include "../ship.h"
20#include "../aircraft.h"
21#include "../timetable.h"
22#include "../station_base.h"
23#include "../effectvehicle_base.h"
24#include "../company_base.h"
25#include "../company_func.h"
26#include "../disaster_vehicle.h"
27#include "../economy_base.h"
28
29#include "../safeguards.h"
30
36{
37 for (Train *v : Train::Iterate()) {
38 v->other_multiheaded_part = nullptr;
39 }
40
41 for (Train *v : Train::Iterate()) {
42 if (v->IsFrontEngine() || v->IsFreeWagon()) {
43 /* Two ways to associate multiheaded parts to each other:
44 * sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
45 * bracket-matching: Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
46 *
47 * Note: Old savegames might contain chains which do not comply with these rules, e.g.
48 * - the front and read parts have invalid orders
49 * - different engine types might be combined
50 * - there might be different amounts of front and rear parts.
51 *
52 * Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
53 * This is why two matching strategies are needed.
54 */
55
56 bool sequential_matching = v->IsFrontEngine();
57
58 for (Train *u = v; u != nullptr; u = u->GetNextVehicle()) {
59 if (u->other_multiheaded_part != nullptr) continue; // we already linked this one
60
61 if (u->IsMultiheaded()) {
62 if (!u->IsEngine()) {
63 /* we got a rear car without a front car. We will convert it to a front one */
64 u->SetEngine();
65 u->spritenum--;
66 }
67
68 /* Find a matching back part */
69 EngineID eid = u->engine_type;
70 Train *w;
71 if (sequential_matching) {
72 for (w = u->GetNextVehicle(); w != nullptr; w = w->GetNextVehicle()) {
73 if (w->engine_type != eid || w->other_multiheaded_part != nullptr || !w->IsMultiheaded()) continue;
74
75 /* we found a car to partner with this engine. Now we will make sure it face the right way */
76 if (w->IsEngine()) {
77 w->ClearEngine();
78 w->spritenum++;
79 }
80 break;
81 }
82 } else {
83 uint stack_pos = 0;
84 for (w = u->GetNextVehicle(); w != nullptr; w = w->GetNextVehicle()) {
85 if (w->engine_type != eid || w->other_multiheaded_part != nullptr || !w->IsMultiheaded()) continue;
86
87 if (w->IsEngine()) {
88 stack_pos++;
89 } else {
90 if (stack_pos == 0) break;
91 stack_pos--;
92 }
93 }
94 }
95
96 if (w != nullptr) {
97 w->other_multiheaded_part = u;
98 u->other_multiheaded_part = w;
99 } else {
100 /* we got a front car and no rear cars. We will fake this one for forget that it should have been multiheaded */
101 u->ClearMultiheaded();
102 }
103 }
104 }
105 }
106 }
107}
108
114{
115 for (Train *t : Train::Iterate()) SetBit(t->subtype, 7); // indicates that it's the old format and needs to be converted in the next loop
116
117 for (Train *t : Train::Iterate()) {
118 if (HasBit(t->subtype, 7) && ((t->subtype & ~0x80) == 0 || (t->subtype & ~0x80) == 4)) {
119 for (Train *u = t; u != nullptr; u = u->Next()) {
120 const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
121
122 ClrBit(u->subtype, 7);
123 switch (u->subtype) {
124 case 0: // TS_Front_Engine
125 if (rvi->railveh_type == RAILVEH_MULTIHEAD) u->SetMultiheaded();
126 u->SetFrontEngine();
127 u->SetEngine();
128 break;
129
130 case 1: // TS_Artic_Part
131 u->subtype = 0;
132 u->SetArticulatedPart();
133 break;
134
135 case 2: // TS_Not_First
136 u->subtype = 0;
137 if (rvi->railveh_type == RAILVEH_WAGON) {
138 /* normal wagon */
139 u->SetWagon();
140 break;
141 }
142 if (rvi->railveh_type == RAILVEH_MULTIHEAD && rvi->image_index == u->spritenum - 1) {
143 /* rear end of a multiheaded engine */
144 u->SetMultiheaded();
145 break;
146 }
147 if (rvi->railveh_type == RAILVEH_MULTIHEAD) u->SetMultiheaded();
148 u->SetEngine();
149 break;
150
151 case 4: // TS_Free_Car
152 u->subtype = 0;
153 u->SetWagon();
154 u->SetFreeWagon();
155 break;
156 default: SlErrorCorrupt("Invalid train subtype");
157 }
158 }
159 }
160 }
161}
162
163
166{
167 /* set airport_flags to 0 for all airports just to be sure */
168 for (Station *st : Station::Iterate()) {
169 st->airport.flags = 0; // reset airport
170 }
171
172 for (Aircraft *a : Aircraft::Iterate()) {
173 /* airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor)
174 * skip those */
175 if (a->IsNormalAircraft()) {
176 /* airplane in terminal stopped doesn't hurt anyone, so goto next */
177 if ((a->vehstatus & VS_STOPPED) && a->state == 0) {
178 a->state = HANGAR;
179 continue;
180 }
181
182 AircraftLeaveHangar(a, a->direction); // make airplane visible if it was in a depot for example
183 a->vehstatus &= ~VS_STOPPED; // make airplane moving
185 a->cur_speed = a->vcache.cached_max_speed; // so aircraft don't have zero speed while in air
186 if (!a->current_order.IsType(OT_GOTO_STATION) && !a->current_order.IsType(OT_GOTO_DEPOT)) {
187 /* reset current order so aircraft doesn't have invalid "station-only" order */
188 a->current_order.MakeDummy();
189 }
190 a->state = FLYING;
191 AircraftNextAirportPos_and_Order(a); // move it to the entry point of the airport
193 a->tile = 0; // aircraft in air is tile=0
194
195 /* correct speed of helicopter-rotors */
196 if (a->subtype == AIR_HELICOPTER) a->Next()->Next()->cur_speed = 32;
197
198 /* set new position x,y,z */
199 GetAircraftFlightLevelBounds(a, &a->z_pos, nullptr);
200 SetAircraftPosition(a, gp.x, gp.y, GetAircraftFlightLevel(a));
201 }
202 }
203
204 /* Clear aircraft from loading vehicles, if we bumped them into the air. */
205 for (Station *st : Station::Iterate()) {
206 for (auto iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); /* nothing */) {
207 Vehicle *v = *iter;
208 if (v->type == VEH_AIRCRAFT && !v->current_order.IsType(OT_LOADING)) {
209 iter = st->loading_vehicles.erase(iter);
210 delete v->cargo_payment;
211 } else {
212 ++iter;
213 }
214 }
215 }
216}
217
226{
227 size_t total_engines = Engine::GetPoolSize();
229
230 for (const Engine *e : Engine::IterateType(VEH_TRAIN)) { first_engine[VEH_TRAIN] = e->index; break; }
231 for (const Engine *e : Engine::IterateType(VEH_ROAD)) { first_engine[VEH_ROAD] = e->index; break; }
232 for (const Engine *e : Engine::IterateType(VEH_SHIP)) { first_engine[VEH_SHIP] = e->index; break; }
233 for (const Engine *e : Engine::IterateType(VEH_AIRCRAFT)) { first_engine[VEH_AIRCRAFT] = e->index; break; }
234
235 for (Vehicle *v : Vehicle::Iterate()) {
236 /* Test if engine types match */
237 switch (v->type) {
238 case VEH_TRAIN:
239 case VEH_ROAD:
240 case VEH_SHIP:
241 case VEH_AIRCRAFT:
242 if (v->engine_type >= total_engines || v->type != v->GetEngine()->type) {
243 v->engine_type = first_engine[v->type];
244 }
245 break;
246
247 default:
248 break;
249 }
250 }
251}
252
253extern uint8_t _age_cargo_skip_counter; // From misc_sl.cpp
254
256void AfterLoadVehiclesPhase1(bool part_of_load)
257{
258 for (Vehicle *v : Vehicle::Iterate()) {
259 /* Reinstate the previous pointer */
260 if (v->Next() != nullptr) v->Next()->previous = v;
261 if (v->NextShared() != nullptr) v->NextShared()->previous_shared = v;
262
263 if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID;
264 v->first = nullptr;
265 if (v->IsGroundVehicle()) v->GetGroundVehicleCache()->first_engine = INVALID_ENGINE;
266 }
267
268 /* AfterLoadVehicles may also be called in case of NewGRF reload, in this
269 * case we may not convert orders again. */
270 if (part_of_load) {
271 /* Create shared vehicle chain for very old games (pre 5,2) and create
272 * OrderList from shared vehicle chains. For this to work correctly, the
273 * following conditions must be fulfilled:
274 * a) both next_shared and previous_shared are not set for pre 5,2 games
275 * b) both next_shared and previous_shared are set for later games
276 */
277 std::map<Order*, OrderList*> mapping;
278
279 for (Vehicle *v : Vehicle::Iterate()) {
280 if (v->old_orders != nullptr) {
281 if (IsSavegameVersionBefore(SLV_105)) { // Pre-105 didn't save an OrderList
282 if (mapping[v->old_orders] == nullptr) {
283 /* This adds the whole shared vehicle chain for case b */
284
285 /* Creating an OrderList here is safe because the number of vehicles
286 * allowed in these savegames matches the number of OrderLists. As
287 * such each vehicle can get an OrderList and it will (still) fit. */
289 v->orders = mapping[v->old_orders] = new OrderList(v->old_orders, v);
290 } else {
291 v->orders = mapping[v->old_orders];
292 /* For old games (case a) we must create the shared vehicle chain */
294 v->AddToShared(v->orders->GetFirstSharedVehicle());
295 }
296 }
297 } else { // OrderList was saved as such, only recalculate not saved values
298 if (v->PreviousShared() == nullptr) {
299 v->orders->Initialize(v->orders->first, v);
300 }
301 }
302 }
303 }
304 }
305
306 for (Vehicle *v : Vehicle::Iterate()) {
307 /* Fill the first pointers */
308 if (v->Previous() == nullptr) {
309 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
310 u->first = v;
311 }
312 }
313 }
314
315 if (part_of_load) {
317 /* Before 105 there was no order for shared orders, thus it messed up horribly */
318 for (Vehicle *v : Vehicle::Iterate()) {
319 if (v->First() != v || v->orders != nullptr || v->previous_shared != nullptr || v->next_shared == nullptr) continue;
320
321 /* As above, allocating OrderList here is safe. */
323 v->orders = new OrderList(nullptr, v);
324 for (Vehicle *u = v; u != nullptr; u = u->next_shared) {
325 u->orders = v->orders;
326 }
327 }
328 }
329
331 /* The road vehicle subtype was converted to a flag. */
332 for (RoadVehicle *rv : RoadVehicle::Iterate()) {
333 if (rv->subtype == 0) {
334 /* The road vehicle is at the front. */
335 rv->SetFrontEngine();
336 } else if (rv->subtype == 1) {
337 /* The road vehicle is an articulated part. */
338 rv->subtype = 0;
339 rv->SetArticulatedPart();
340 } else {
341 SlErrorCorrupt("Invalid road vehicle subtype");
342 }
343 }
344 }
345
347 /* In some old savegames there might be some "crap" stored. */
348 for (Vehicle *v : Vehicle::Iterate()) {
349 if (!v->IsPrimaryVehicle() && v->type != VEH_DISASTER) {
350 v->current_order.Free();
351 v->unitnumber = 0;
352 }
353 }
354 }
355
357 /* Set the vehicle-local cargo age counter from the old global counter. */
358 for (Vehicle *v : Vehicle::Iterate()) {
359 v->cargo_age_counter = _age_cargo_skip_counter;
360 }
361 }
362
364 /* Set service interval flags */
365 for (Vehicle *v : Vehicle::Iterate()) {
366 if (!v->IsPrimaryVehicle()) continue;
367
368 const Company *c = Company::Get(v->owner);
369 int interval = CompanyServiceInterval(c, v->type);
370
371 v->SetServiceIntervalIsCustom(v->GetServiceInterval() != interval);
372 v->SetServiceIntervalIsPercent(c->settings.vehicle.servint_ispercent);
373 }
374 }
375
377 /* Ship rotation added */
378 for (Ship *s : Ship::Iterate()) {
379 s->rotation = s->direction;
380 }
381 } else {
382 for (Ship *s : Ship::Iterate()) {
383 if (s->rotation == s->direction) continue;
384 /* In case we are rotating on gameload, set the rotation position to
385 * the current position, otherwise the applied workaround offset would
386 * be with respect to 0,0.
387 */
388 s->rotation_x_pos = s->x_pos;
389 s->rotation_y_pos = s->y_pos;
390 }
391 }
392
394 /* Convert timetable start from a date to an absolute tick in TimerGameTick::counter. */
395 for (Vehicle *v : Vehicle::Iterate()) {
396 /* If the start date is 0, the vehicle is not waiting to start and can be ignored. */
397 if (v->timetable_start == 0) continue;
398
399 v->timetable_start = GetStartTickFromDate(v->timetable_start);
400 }
401 }
402
404 /* Set vehicle economy age based on calendar age. */
405 for (Vehicle *v : Vehicle::Iterate()) {
406 v->economy_age = v->age.base();
407 }
408 }
409 }
410
412}
413
415void AfterLoadVehiclesPhase2(bool part_of_load)
416{
417 for (Vehicle *v : Vehicle::Iterate()) {
418 assert(v->First() != nullptr);
419
420 v->trip_occupancy = CalcPercentVehicleFilled(v, nullptr);
421
422 switch (v->type) {
423 case VEH_TRAIN: {
424 Train *t = Train::From(v);
425 if (t->IsFrontEngine() || t->IsFreeWagon()) {
426 t->gcache.last_speed = t->cur_speed; // update displayed train speed
428 }
429 break;
430 }
431
432 case VEH_ROAD: {
434 if (rv->IsFrontEngine()) {
435 rv->gcache.last_speed = rv->cur_speed; // update displayed road vehicle speed
436
437 rv->roadtype = Engine::Get(rv->engine_type)->u.road.roadtype;
439 RoadTramType rtt = GetRoadTramType(rv->roadtype);
440 for (RoadVehicle *u = rv; u != nullptr; u = u->Next()) {
441 u->roadtype = rv->roadtype;
442 u->compatible_roadtypes = rv->compatible_roadtypes;
443 if (GetRoadType(u->tile, rtt) == INVALID_ROADTYPE) SlErrorCorrupt("Road vehicle on invalid road type");
444 }
445
448 rv->CargoChanged();
449 }
450 }
451 break;
452 }
453
454 case VEH_SHIP:
456 break;
457
458 default: break;
459 }
460 }
461
462 /* Stop non-front engines */
463 if (part_of_load && IsSavegameVersionBefore(SLV_112)) {
464 for (Vehicle *v : Vehicle::Iterate()) {
465 if (v->type == VEH_TRAIN) {
466 Train *t = Train::From(v);
467 if (!t->IsFrontEngine()) {
468 if (t->IsEngine()) t->vehstatus |= VS_STOPPED;
469 /* cur_speed is now relevant for non-front parts - nonzero breaks
470 * moving-wagons-inside-depot- and autoreplace- code */
471 t->cur_speed = 0;
472 }
473 }
474 /* trains weren't stopping gradually in old OTTD versions (and TTO/TTD)
475 * other vehicle types didn't have zero speed while stopped (even in 'recent' OTTD versions) */
476 if ((v->vehstatus & VS_STOPPED) && (v->type != VEH_TRAIN || IsSavegameVersionBefore(SLV_2, 1))) {
477 v->cur_speed = 0;
478 }
479 }
480 }
481
482 for (Vehicle *v : Vehicle::Iterate()) {
483 switch (v->type) {
484 case VEH_ROAD:
485 case VEH_TRAIN:
486 case VEH_SHIP:
487 v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_cache.sprite_seq);
488 break;
489
490 case VEH_AIRCRAFT:
492 v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_cache.sprite_seq);
493
494 /* The aircraft's shadow will have the same image as the aircraft, but no colour */
495 Vehicle *shadow = v->Next();
496 if (shadow == nullptr) SlErrorCorrupt("Missing shadow for aircraft");
497
498 shadow->sprite_cache.sprite_seq.CopyWithoutPalette(v->sprite_cache.sprite_seq);
499
500 /* In the case of a helicopter we will update the rotor sprites */
501 if (v->subtype == AIR_HELICOPTER) {
502 Vehicle *rotor = shadow->Next();
503 if (rotor == nullptr) SlErrorCorrupt("Missing rotor for helicopter");
504
505 GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_cache.sprite_seq);
506 }
507
509 }
510 break;
511
512 case VEH_DISASTER: {
513 auto *dv = DisasterVehicle::From(v);
514 if (dv->subtype == ST_SMALL_UFO && dv->state != 0) {
515 RoadVehicle *u = RoadVehicle::GetIfValid(v->dest_tile.base());
516 if (u != nullptr && u->IsFrontEngine()) {
517 /* Delete UFO targetting a vehicle which is already a target. */
518 if (u->disaster_vehicle != INVALID_VEHICLE && u->disaster_vehicle != dv->index) {
519 delete v;
520 continue;
521 } else {
522 u->disaster_vehicle = dv->index;
523 }
524 }
525 }
526 break;
527 }
528
529 default: break;
530 }
531
532 if (part_of_load && v->unitnumber != 0) {
533 Company::Get(v->owner)->freeunits[v->type].UseID(v->unitnumber);
534 }
535
536 v->UpdateDeltaXY();
537 v->coord.left = INVALID_COORD;
538 v->sprite_cache.old_coord.left = INVALID_COORD;
539 v->UpdatePosition();
540 v->UpdateViewport(false);
541 }
542}
543
544bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // From train_cmd.cpp
546void ReverseTrainSwapVeh(Train *v, int l, int r);
547
550{
551 /* Vehicle center was moved from 4 units behind the front to half the length
552 * behind the front. Move vehicles so they end up on the same spot. */
553 for (Vehicle *v : Vehicle::Iterate()) {
554 if (v->type == VEH_TRAIN && v->IsPrimaryVehicle()) {
555 /* The vehicle center is now more to the front depending on vehicle length,
556 * so we need to move all vehicles forward to cover the difference to the
557 * old center, otherwise wagon spacing in trains would be broken upon load. */
558 for (Train *u = Train::From(v); u != nullptr; u = u->Next()) {
559 if (u->track == TRACK_BIT_DEPOT || (u->vehstatus & VS_CRASHED)) continue;
560
561 Train *next = u->Next();
562
563 /* Try to pull the vehicle half its length forward. */
564 int diff = (VEHICLE_LENGTH - u->gcache.cached_veh_length) / 2;
565 int done;
566 for (done = 0; done < diff; done++) {
567 if (!TrainController(u, next, false)) break;
568 }
569
570 if (next != nullptr && done < diff && u->IsFrontEngine()) {
571 /* Pulling the front vehicle forwards failed, we either encountered a dead-end
572 * or a red signal. To fix this, we try to move the whole train the required
573 * space backwards and re-do the fix up of the front vehicle. */
574
575 /* Ignore any signals when backtracking. */
576 TrainForceProceeding old_tfp = u->force_proceed;
577 u->force_proceed = TFP_SIGNAL;
578
579 /* Swap start<>end, start+1<>end-1, ... */
580 int r = CountVehiclesInChain(u) - 1; // number of vehicles - 1
581 int l = 0;
582 do ReverseTrainSwapVeh(u, l++, r--); while (l <= r);
583
584 /* We moved the first vehicle which is now the last. Move it back to the
585 * original position as we will fix up the last vehicle later in the loop. */
586 for (int i = 0; i < done; i++) TrainController(u->Last(), nullptr);
587
588 /* Move the train backwards to get space for the first vehicle. As the stopping
589 * distance from a line end is rounded up, move the train one unit more to cater
590 * for front vehicles with odd lengths. */
591 int moved;
592 for (moved = 0; moved < diff + 1; moved++) {
593 if (!TrainController(u, nullptr, false)) break;
594 }
595
596 /* Swap start<>end, start+1<>end-1, ... again. */
597 r = CountVehiclesInChain(u) - 1; // number of vehicles - 1
598 l = 0;
599 do ReverseTrainSwapVeh(u, l++, r--); while (l <= r);
600
601 u->force_proceed = old_tfp;
602
603 /* Tracks are too short to fix the train length. The player has to fix the
604 * train in a depot. Bail out so we don't damage the vehicle chain any more. */
605 if (moved < diff + 1) break;
606
607 /* Re-do the correction for the first vehicle. */
608 for (done = 0; done < diff; done++) TrainController(u, next, false);
609
610 /* We moved one unit more backwards than needed for even-length front vehicles,
611 * try to move that unit forward again. We don't care if this step fails. */
612 TrainController(u, nullptr, false);
613 }
614
615 /* If the next wagon is still in a depot, check if it shouldn't be outside already. */
616 if (next != nullptr && next->track == TRACK_BIT_DEPOT) {
617 int d = TicksToLeaveDepot(u);
618 if (d <= 0) {
619 /* Next vehicle should have left the depot already, show it and pull forward. */
620 next->vehstatus &= ~VS_HIDDEN;
621 next->track = TrackToTrackBits(GetRailDepotTrack(next->tile));
622 for (int i = 0; i >= d; i--) TrainController(next, nullptr);
623 }
624 }
625 }
626
627 /* Update all cached properties after moving the vehicle chain around. */
628 Train::From(v)->ConsistChanged(CCF_TRACK);
629 }
630 }
631}
632
633static uint8_t _cargo_periods;
634static uint16_t _cargo_source;
635static uint32_t _cargo_source_xy;
636static uint16_t _cargo_count;
637static uint16_t _cargo_paid_for;
638static Money _cargo_feeder_share;
639
640class SlVehicleCommon : public DefaultSaveLoadHandler<SlVehicleCommon, Vehicle> {
641public:
642 inline static const SaveLoad description[] = {
643 SLE_VAR(Vehicle, subtype, SLE_UINT8),
644
646 SLE_CONDVAR(Vehicle, name, SLE_NAME, SL_MIN_VERSION, SLV_84),
648 SLE_CONDVAR(Vehicle, unitnumber, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_8),
649 SLE_CONDVAR(Vehicle, unitnumber, SLE_UINT16, SLV_8, SL_MAX_VERSION),
650 SLE_VAR(Vehicle, owner, SLE_UINT8),
651 SLE_CONDVAR(Vehicle, tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
652 SLE_CONDVAR(Vehicle, tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
653 SLE_CONDVAR(Vehicle, dest_tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
654 SLE_CONDVAR(Vehicle, dest_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
655
656 SLE_CONDVAR(Vehicle, x_pos, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
657 SLE_CONDVAR(Vehicle, x_pos, SLE_UINT32, SLV_6, SL_MAX_VERSION),
658 SLE_CONDVAR(Vehicle, y_pos, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
659 SLE_CONDVAR(Vehicle, y_pos, SLE_UINT32, SLV_6, SL_MAX_VERSION),
660 SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
661 SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, SLV_164, SL_MAX_VERSION),
662 SLE_VAR(Vehicle, direction, SLE_UINT8),
663
664 SLE_VAR(Vehicle, spritenum, SLE_UINT8),
665 SLE_VAR(Vehicle, engine_type, SLE_UINT16),
666 SLE_VAR(Vehicle, cur_speed, SLE_UINT16),
667 SLE_VAR(Vehicle, subspeed, SLE_UINT8),
668 SLE_VAR(Vehicle, acceleration, SLE_UINT8),
669 SLE_CONDVAR(Vehicle, motion_counter, SLE_UINT32, SLV_VEH_MOTION_COUNTER, SL_MAX_VERSION),
670 SLE_VAR(Vehicle, progress, SLE_UINT8),
671
672 SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
673 SLE_CONDVAR(Vehicle, last_station_visited, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
674 SLE_CONDVAR(Vehicle, last_station_visited, SLE_UINT16, SLV_5, SL_MAX_VERSION),
675 SLE_CONDVAR(Vehicle, last_loading_station, SLE_UINT16, SLV_182, SL_MAX_VERSION),
676
677 SLE_VAR(Vehicle, cargo_type, SLE_UINT8),
678 SLE_CONDVAR(Vehicle, cargo_subtype, SLE_UINT8, SLV_35, SL_MAX_VERSION),
679 SLEG_CONDVAR("cargo_days", _cargo_periods, SLE_UINT8, SL_MIN_VERSION, SLV_68),
680 SLEG_CONDVAR("cargo_source", _cargo_source, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_7),
681 SLEG_CONDVAR("cargo_source", _cargo_source, SLE_UINT16, SLV_7, SLV_68),
682 SLEG_CONDVAR("cargo_source_xy", _cargo_source_xy, SLE_UINT32, SLV_44, SLV_68),
683 SLE_VAR(Vehicle, cargo_cap, SLE_UINT16),
684 SLE_CONDVAR(Vehicle, refit_cap, SLE_UINT16, SLV_182, SL_MAX_VERSION),
685 SLEG_CONDVAR("cargo_count", _cargo_count, SLE_UINT16, SL_MIN_VERSION, SLV_68),
687 SLE_CONDARR(Vehicle, cargo.action_counts, SLE_UINT, VehicleCargoList::NUM_MOVE_TO_ACTION, SLV_181, SL_MAX_VERSION),
688 SLE_CONDVAR(Vehicle, cargo_age_counter, SLE_UINT16, SLV_162, SL_MAX_VERSION),
689
690 SLE_VAR(Vehicle, day_counter, SLE_UINT8),
691 SLE_VAR(Vehicle, tick_counter, SLE_UINT8),
692 SLE_CONDVAR(Vehicle, running_ticks, SLE_UINT8, SLV_88, SL_MAX_VERSION),
693
694 SLE_VAR(Vehicle, cur_implicit_order_index, SLE_UINT8),
695 SLE_CONDVAR(Vehicle, cur_real_order_index, SLE_UINT8, SLV_158, SL_MAX_VERSION),
696
697 /* This next line is for version 4 and prior compatibility.. it temporarily reads
698 type and flags (which were both 4 bits) into type. Later on this is
699 converted correctly */
700 SLE_CONDVAR(Vehicle, current_order.type, SLE_UINT8, SL_MIN_VERSION, SLV_5),
701 SLE_CONDVAR(Vehicle, current_order.dest, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
702
703 /* Orders for version 5 and on */
704 SLE_CONDVAR(Vehicle, current_order.type, SLE_UINT8, SLV_5, SL_MAX_VERSION),
705 SLE_CONDVAR(Vehicle, current_order.flags, SLE_UINT8, SLV_5, SL_MAX_VERSION),
706 SLE_CONDVAR(Vehicle, current_order.dest, SLE_UINT16, SLV_5, SL_MAX_VERSION),
707
708 /* Refit in current order */
709 SLE_CONDVAR(Vehicle, current_order.refit_cargo, SLE_UINT8, SLV_36, SL_MAX_VERSION),
710
711 /* Timetable in current order */
712 SLE_CONDVAR(Vehicle, current_order.wait_time, SLE_UINT16, SLV_67, SL_MAX_VERSION),
713 SLE_CONDVAR(Vehicle, current_order.travel_time, SLE_UINT16, SLV_67, SL_MAX_VERSION),
714 SLE_CONDVAR(Vehicle, current_order.max_speed, SLE_UINT16, SLV_174, SL_MAX_VERSION),
715 SLE_CONDVAR(Vehicle, timetable_start, SLE_FILE_I32 | SLE_VAR_U64, SLV_129, SLV_TIMETABLE_START_TICKS),
716 SLE_CONDVAR(Vehicle, timetable_start, SLE_UINT64, SLV_TIMETABLE_START_TICKS, SL_MAX_VERSION),
717
720
721 SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
722 SLE_CONDVAR(Vehicle, age, SLE_INT32, SLV_31, SL_MAX_VERSION),
724 SLE_CONDVAR(Vehicle, max_age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
725 SLE_CONDVAR(Vehicle, max_age, SLE_INT32, SLV_31, SL_MAX_VERSION),
726 SLE_CONDVAR(Vehicle, date_of_last_service, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
727 SLE_CONDVAR(Vehicle, date_of_last_service, SLE_INT32, SLV_31, SL_MAX_VERSION),
728 SLE_CONDVAR(Vehicle, date_of_last_service_newgrf, SLE_INT32, SLV_NEWGRF_LAST_SERVICE, SL_MAX_VERSION),
729 SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SL_MIN_VERSION, SLV_31),
730 SLE_CONDVAR(Vehicle, service_interval, SLE_FILE_U32 | SLE_VAR_U16, SLV_31, SLV_180),
731 SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SLV_180, SL_MAX_VERSION),
732 SLE_VAR(Vehicle, reliability, SLE_UINT16),
733 SLE_VAR(Vehicle, reliability_spd_dec, SLE_UINT16),
734 SLE_VAR(Vehicle, breakdown_ctr, SLE_UINT8),
735 SLE_VAR(Vehicle, breakdown_delay, SLE_UINT8),
736 SLE_VAR(Vehicle, breakdowns_since_last_service, SLE_UINT8),
737 SLE_VAR(Vehicle, breakdown_chance, SLE_UINT8),
738 SLE_CONDVAR(Vehicle, build_year, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
739 SLE_CONDVAR(Vehicle, build_year, SLE_INT32, SLV_31, SL_MAX_VERSION),
740
741 SLE_VAR(Vehicle, load_unload_ticks, SLE_UINT16),
742 SLEG_CONDVAR("cargo_paid_for", _cargo_paid_for, SLE_UINT16, SLV_45, SL_MAX_VERSION),
743 SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_40, SLV_180),
744 SLE_CONDVAR(Vehicle, vehicle_flags, SLE_UINT16, SLV_180, SL_MAX_VERSION),
745
746 SLE_CONDVAR(Vehicle, profit_this_year, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
747 SLE_CONDVAR(Vehicle, profit_this_year, SLE_INT64, SLV_65, SL_MAX_VERSION),
748 SLE_CONDVAR(Vehicle, profit_last_year, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
749 SLE_CONDVAR(Vehicle, profit_last_year, SLE_INT64, SLV_65, SL_MAX_VERSION),
750 SLEG_CONDVAR("cargo_feeder_share", _cargo_feeder_share, SLE_FILE_I32 | SLE_VAR_I64, SLV_51, SLV_65),
751 SLEG_CONDVAR("cargo_feeder_share", _cargo_feeder_share, SLE_INT64, SLV_65, SLV_68),
752 SLE_CONDVAR(Vehicle, value, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
753 SLE_CONDVAR(Vehicle, value, SLE_INT64, SLV_65, SL_MAX_VERSION),
754
755 SLE_CONDVAR(Vehicle, random_bits, SLE_FILE_U8 | SLE_VAR_U16, SLV_2, SLV_EXTEND_VEHICLE_RANDOM),
757 SLE_CONDVAR(Vehicle, waiting_triggers, SLE_UINT8, SLV_2, SL_MAX_VERSION),
758
760 SLE_CONDVAR(Vehicle, group_id, SLE_UINT16, SLV_60, SL_MAX_VERSION),
761
762 SLE_CONDVAR(Vehicle, current_order_time, SLE_FILE_U32 | SLE_VAR_I32, SLV_67, SLV_TIMETABLE_TICKS_TYPE),
763 SLE_CONDVAR(Vehicle, current_order_time, SLE_INT32, SLV_TIMETABLE_TICKS_TYPE, SL_MAX_VERSION),
764 SLE_CONDVAR(Vehicle, last_loading_tick, SLE_UINT64, SLV_LAST_LOADING_TICK, SL_MAX_VERSION),
765 SLE_CONDVAR(Vehicle, lateness_counter, SLE_INT32, SLV_67, SL_MAX_VERSION),
766
767 SLE_CONDVAR(Vehicle, depot_unbunching_last_departure, SLE_UINT64, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION),
768 SLE_CONDVAR(Vehicle, depot_unbunching_next_departure, SLE_UINT64, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION),
769 SLE_CONDVAR(Vehicle, round_trip_time, SLE_INT32, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION),
770 };
771
772 inline const static SaveLoadCompatTable compat_description = _vehicle_common_sl_compat;
773
774 void Save(Vehicle *v) const override
775 {
776 SlObject(v, this->GetDescription());
777 }
778
779 void Load(Vehicle *v) const override
780 {
781 SlObject(v, this->GetLoadDescription());
782 }
783
784 void FixPointers(Vehicle *v) const override
785 {
786 SlObject(v, this->GetDescription());
787 }
788};
789
790class SlVehicleTrain : public DefaultSaveLoadHandler<SlVehicleTrain, Vehicle> {
791public:
792 inline static const SaveLoad description[] = {
793 SLEG_STRUCT("common", SlVehicleCommon),
794 SLE_VAR(Train, crash_anim_pos, SLE_UINT16),
795 SLE_VAR(Train, force_proceed, SLE_UINT8),
796 SLE_VAR(Train, railtype, SLE_UINT8),
797 SLE_VAR(Train, track, SLE_UINT8),
798
799 SLE_CONDVAR(Train, flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_2, SLV_100),
800 SLE_CONDVAR(Train, flags, SLE_UINT16, SLV_100, SL_MAX_VERSION),
801 SLE_CONDVAR(Train, wait_counter, SLE_UINT16, SLV_136, SL_MAX_VERSION),
802 SLE_CONDVAR(Train, gv_flags, SLE_UINT16, SLV_139, SL_MAX_VERSION),
803 };
804 inline const static SaveLoadCompatTable compat_description = _vehicle_train_sl_compat;
805
806 void Save(Vehicle *v) const override
807 {
808 if (v->type != VEH_TRAIN) return;
809 SlObject(v, this->GetDescription());
810 }
811
812 void Load(Vehicle *v) const override
813 {
814 if (v->type != VEH_TRAIN) return;
815 SlObject(v, this->GetLoadDescription());
816 }
817
818 void FixPointers(Vehicle *v) const override
819 {
820 if (v->type != VEH_TRAIN) return;
821 SlObject(v, this->GetDescription());
822 }
823};
824
825class SlVehicleRoadVehPath : public VectorSaveLoadHandler<SlVehicleRoadVehPath, RoadVehicle, RoadVehPathElement> {
826public:
827 inline static const SaveLoad description[] = {
828 SLE_VAR(RoadVehPathElement, trackdir, SLE_UINT8),
829 SLE_VAR(RoadVehPathElement, tile, SLE_UINT32),
830 };
831 inline const static SaveLoadCompatTable compat_description = {};
832
833 std::vector<RoadVehPathElement> &GetVector(RoadVehicle *rv) const override { return rv->path; }
834};
835
836class SlVehicleRoadVeh : public DefaultSaveLoadHandler<SlVehicleRoadVeh, Vehicle> {
837public:
838 /* RoadVehicle path is stored in std::pair which cannot be directly saved. */
839 static inline std::vector<Trackdir> rv_path_td;
840 static inline std::vector<TileIndex> rv_path_tile;
841
842 inline static const SaveLoad description[] = {
843 SLEG_STRUCT("common", SlVehicleCommon),
844 SLE_VAR(RoadVehicle, state, SLE_UINT8),
845 SLE_VAR(RoadVehicle, frame, SLE_UINT8),
846 SLE_VAR(RoadVehicle, blocked_ctr, SLE_UINT16),
847 SLE_VAR(RoadVehicle, overtaking, SLE_UINT8),
848 SLE_VAR(RoadVehicle, overtaking_ctr, SLE_UINT8),
849 SLE_VAR(RoadVehicle, crashed_ctr, SLE_UINT16),
850 SLE_VAR(RoadVehicle, reverse_ctr, SLE_UINT8),
851 SLEG_CONDVECTOR("path.td", rv_path_td, SLE_UINT8, SLV_ROADVEH_PATH_CACHE, SLV_PATH_CACHE_FORMAT),
852 SLEG_CONDVECTOR("path.tile", rv_path_tile, SLE_UINT32, SLV_ROADVEH_PATH_CACHE, SLV_PATH_CACHE_FORMAT),
854 SLE_CONDVAR(RoadVehicle, gv_flags, SLE_UINT16, SLV_139, SL_MAX_VERSION),
855 };
856 inline const static SaveLoadCompatTable compat_description = _vehicle_roadveh_sl_compat;
857
858 static void ConvertPathCache(RoadVehicle &rv)
859 {
860 /* The two vectors should be the same size, but if not we can just ignore the cache and not cause more issues. */
861 if (rv_path_td.size() != rv_path_tile.size()) {
862 Debug(sl, 1, "Found RoadVehicle {} with invalid path cache, ignoring.", rv.index);
863 return;
864 }
865 size_t n = std::min(rv_path_td.size(), rv_path_tile.size());
866 if (n == 0) return;
867
868 rv.path.reserve(n);
869 for (size_t c = 0; c < n; ++c) {
870 rv.path.emplace_back(rv_path_td[c], rv_path_tile[c]);
871 }
872
873 /* Path cache is now taken from back instead of front, so needs reversing. */
874 std::reverse(std::begin(rv.path), std::end(rv.path));
875 }
876
877 void Save(Vehicle *v) const override
878 {
879 if (v->type != VEH_ROAD) return;
880 SlObject(v, this->GetDescription());
881 }
882
883 void Load(Vehicle *v) const override
884 {
885 if (v->type != VEH_ROAD) return;
886 SlObject(v, this->GetLoadDescription());
888 ConvertPathCache(*static_cast<RoadVehicle *>(v));
889 }
890 }
891
892 void FixPointers(Vehicle *v) const override
893 {
894 if (v->type != VEH_ROAD) return;
895 SlObject(v, this->GetDescription());
896 }
897};
898
899class SlVehicleShipPath : public VectorSaveLoadHandler<SlVehicleShipPath, Ship, ShipPathElement> {
900public:
901 inline static const SaveLoad description[] = {
902 SLE_VAR(ShipPathElement, trackdir, SLE_UINT8),
903 };
904 inline const static SaveLoadCompatTable compat_description = {};
905
906 std::vector<ShipPathElement> &GetVector(Ship *s) const override { return s->path; }
907};
908
909class SlVehicleShip : public DefaultSaveLoadHandler<SlVehicleShip, Vehicle> {
910public:
911 static inline std::vector<Trackdir> ship_path_td;
912
913 inline static const SaveLoad description[] = {
914 SLEG_STRUCT("common", SlVehicleCommon),
915 SLE_VAR(Ship, state, SLE_UINT8),
916 SLEG_CONDVECTOR("path", ship_path_td, SLE_UINT8, SLV_SHIP_PATH_CACHE, SLV_PATH_CACHE_FORMAT),
918 SLE_CONDVAR(Ship, rotation, SLE_UINT8, SLV_SHIP_ROTATION, SL_MAX_VERSION),
919 };
920 inline const static SaveLoadCompatTable compat_description = _vehicle_ship_sl_compat;
921
922 void Save(Vehicle *v) const override
923 {
924 if (v->type != VEH_SHIP) return;
925 SlObject(v, this->GetDescription());
926 }
927
928 void Load(Vehicle *v) const override
929 {
930 if (v->type != VEH_SHIP) return;
931 SlObject(v, this->GetLoadDescription());
932
934 /* Path cache is now taken from back instead of front, so needs reversing. */
935 Ship *s = static_cast<Ship *>(v);
936 std::transform(std::rbegin(ship_path_td), std::rend(ship_path_td), std::back_inserter(s->path), [](Trackdir trackdir) { return trackdir; });
937 }
938 }
939
940 void FixPointers(Vehicle *v) const override
941 {
942 if (v->type != VEH_SHIP) return;
943 SlObject(v, this->GetDescription());
944 }
945};
946
947class SlVehicleAircraft : public DefaultSaveLoadHandler<SlVehicleAircraft, Vehicle> {
948public:
949 inline static const SaveLoad description[] = {
950 SLEG_STRUCT("common", SlVehicleCommon),
951 SLE_VAR(Aircraft, crashed_counter, SLE_UINT16),
952 SLE_VAR(Aircraft, pos, SLE_UINT8),
953
954 SLE_CONDVAR(Aircraft, targetairport, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
955 SLE_CONDVAR(Aircraft, targetairport, SLE_UINT16, SLV_5, SL_MAX_VERSION),
956
957 SLE_VAR(Aircraft, state, SLE_UINT8),
958
959 SLE_CONDVAR(Aircraft, previous_pos, SLE_UINT8, SLV_2, SL_MAX_VERSION),
960 SLE_CONDVAR(Aircraft, last_direction, SLE_UINT8, SLV_2, SL_MAX_VERSION),
961 SLE_CONDVAR(Aircraft, number_consecutive_turns, SLE_UINT8, SLV_2, SL_MAX_VERSION),
962
963 SLE_CONDVAR(Aircraft, turn_counter, SLE_UINT8, SLV_136, SL_MAX_VERSION),
964 SLE_CONDVAR(Aircraft, flags, SLE_UINT8, SLV_167, SL_MAX_VERSION),
965 };
966 inline const static SaveLoadCompatTable compat_description = _vehicle_aircraft_sl_compat;
967
968 void Save(Vehicle *v) const override
969 {
970 if (v->type != VEH_AIRCRAFT) return;
971 SlObject(v, this->GetDescription());
972 }
973
974 void Load(Vehicle *v) const override
975 {
976 if (v->type != VEH_AIRCRAFT) return;
977 SlObject(v, this->GetLoadDescription());
978 }
979
980 void FixPointers(Vehicle *v) const override
981 {
982 if (v->type != VEH_AIRCRAFT) return;
983 SlObject(v, this->GetDescription());
984 }
985};
986
987class SlVehicleEffect : public DefaultSaveLoadHandler<SlVehicleEffect, Vehicle> {
988public:
989 inline static const SaveLoad description[] = {
990 SLE_VAR(Vehicle, subtype, SLE_UINT8),
991
992 SLE_CONDVAR(Vehicle, tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
993 SLE_CONDVAR(Vehicle, tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
994
995 SLE_CONDVAR(Vehicle, x_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
996 SLE_CONDVAR(Vehicle, x_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
997 SLE_CONDVAR(Vehicle, y_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
998 SLE_CONDVAR(Vehicle, y_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
999 SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
1000 SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, SLV_164, SL_MAX_VERSION),
1001
1002 SLE_VAR(Vehicle, sprite_cache.sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
1003 SLE_VAR(Vehicle, progress, SLE_UINT8),
1004 SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
1005
1006 SLE_VAR(EffectVehicle, animation_state, SLE_UINT16),
1007 SLE_VAR(EffectVehicle, animation_substate, SLE_UINT8),
1008
1009 SLE_CONDVAR(Vehicle, spritenum, SLE_UINT8, SLV_2, SL_MAX_VERSION),
1010 };
1011 inline const static SaveLoadCompatTable compat_description = _vehicle_effect_sl_compat;
1012
1013 void Save(Vehicle *v) const override
1014 {
1015 if (v->type != VEH_EFFECT) return;
1016 SlObject(v, this->GetDescription());
1017 }
1018
1019 void Load(Vehicle *v) const override
1020 {
1021 if (v->type != VEH_EFFECT) return;
1022 SlObject(v, this->GetLoadDescription());
1023 }
1024
1025 void FixPointers(Vehicle *v) const override
1026 {
1027 if (v->type != VEH_EFFECT) return;
1028 SlObject(v, this->GetDescription());
1029 }
1030};
1031
1032class SlVehicleDisaster : public DefaultSaveLoadHandler<SlVehicleDisaster, Vehicle> {
1033public:
1034 inline static const SaveLoad description[] = {
1036
1037 SLE_VAR(Vehicle, subtype, SLE_UINT8),
1038 SLE_CONDVAR(Vehicle, tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
1039 SLE_CONDVAR(Vehicle, tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
1040 SLE_CONDVAR(Vehicle, dest_tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
1041 SLE_CONDVAR(Vehicle, dest_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
1042
1043 SLE_CONDVAR(Vehicle, x_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
1044 SLE_CONDVAR(Vehicle, x_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
1045 SLE_CONDVAR(Vehicle, y_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
1046 SLE_CONDVAR(Vehicle, y_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
1047 SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
1048 SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, SLV_164, SL_MAX_VERSION),
1049 SLE_VAR(Vehicle, direction, SLE_UINT8),
1050
1051 SLE_VAR(Vehicle, owner, SLE_UINT8),
1052 SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
1053 SLE_CONDVARNAME(DisasterVehicle, state, "current_order.dest", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
1054 SLE_CONDVARNAME(DisasterVehicle, state, "current_order.dest", SLE_UINT16, SLV_5, SLV_DISASTER_VEH_STATE),
1056
1057 SLE_VAR(Vehicle, sprite_cache.sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
1058 SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
1059 SLE_CONDVAR(Vehicle, age, SLE_INT32, SLV_31, SL_MAX_VERSION),
1060 SLE_VAR(Vehicle, tick_counter, SLE_UINT8),
1061
1062 SLE_CONDVAR(DisasterVehicle, image_override, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_191),
1063 SLE_CONDVAR(DisasterVehicle, image_override, SLE_UINT32, SLV_191, SL_MAX_VERSION),
1064 SLE_CONDVAR(DisasterVehicle, big_ufo_destroyer_target, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_191),
1065 SLE_CONDVAR(DisasterVehicle, big_ufo_destroyer_target, SLE_UINT32, SLV_191, SL_MAX_VERSION),
1067 };
1068
1069 inline const static SaveLoadCompatTable compat_description = _vehicle_disaster_sl_compat;
1070
1071 void Save(Vehicle *v) const override
1072 {
1073 if (v->type != VEH_DISASTER) return;
1074 SlObject(v, this->GetDescription());
1075 }
1076
1077 void Load(Vehicle *v) const override
1078 {
1079 if (v->type != VEH_DISASTER) return;
1080 SlObject(v, this->GetLoadDescription());
1081 }
1082
1083 void FixPointers(Vehicle *v) const override
1084 {
1085 if (v->type != VEH_DISASTER) return;
1086 SlObject(v, this->GetDescription());
1087 }
1088};
1089
1090const static SaveLoad _vehicle_desc[] = {
1091 SLE_SAVEBYTE(Vehicle, type),
1092 SLEG_STRUCT("train", SlVehicleTrain),
1093 SLEG_STRUCT("roadveh", SlVehicleRoadVeh),
1094 SLEG_STRUCT("ship", SlVehicleShip),
1095 SLEG_STRUCT("aircraft", SlVehicleAircraft),
1096 SLEG_STRUCT("effect", SlVehicleEffect),
1097 SLEG_STRUCT("disaster", SlVehicleDisaster),
1098};
1099
1101 VEHSChunkHandler() : ChunkHandler('VEHS', CH_SPARSE_TABLE) {}
1102
1103 void Save() const override
1104 {
1105 SlTableHeader(_vehicle_desc);
1106
1107 /* Write the vehicles */
1108 for (Vehicle *v : Vehicle::Iterate()) {
1109 SlSetArrayIndex(v->index);
1110 SlObject(v, _vehicle_desc);
1111 }
1112 }
1113
1114 void Load() const override
1115 {
1116 const std::vector<SaveLoad> slt = SlCompatTableHeader(_vehicle_desc, _vehicle_sl_compat);
1117
1118 int index;
1119
1120 _cargo_count = 0;
1121
1122 while ((index = SlIterateArray()) != -1) {
1123 Vehicle *v;
1125
1126 switch (vtype) {
1127 case VEH_TRAIN: v = new (index) Train(); break;
1128 case VEH_ROAD: v = new (index) RoadVehicle(); break;
1129 case VEH_SHIP: v = new (index) Ship(); break;
1130 case VEH_AIRCRAFT: v = new (index) Aircraft(); break;
1131 case VEH_EFFECT: v = new (index) EffectVehicle(); break;
1132 case VEH_DISASTER: v = new (index) DisasterVehicle(); break;
1133 case VEH_INVALID: // Savegame shouldn't contain invalid vehicles
1134 default: SlErrorCorrupt("Invalid vehicle type");
1135 }
1136
1137 SlObject(v, slt);
1138
1139 if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) {
1140 /* Don't construct the packet with station here, because that'll fail with old savegames */
1141 CargoPacket *cp = new CargoPacket(_cargo_count, _cargo_periods, _cargo_source, _cargo_source_xy, _cargo_feeder_share);
1142 v->cargo.Append(cp);
1143 }
1144
1145 /* Old savegames used 'last_station_visited = 0xFF' */
1147 v->last_station_visited = INVALID_STATION;
1148 }
1149
1150 if (IsSavegameVersionBefore(SLV_182)) v->last_loading_station = INVALID_STATION;
1151
1153 /* Convert the current_order.type (which is a mix of type and flags, because
1154 * in those versions, they both were 4 bits big) to type and flags */
1155 v->current_order.flags = GB(v->current_order.type, 4, 4);
1156 v->current_order.type &= 0x0F;
1157 }
1158
1159 /* Advanced vehicle lists got added */
1161 }
1162 }
1163
1164 void FixPointers() const override
1165 {
1166 for (Vehicle *v : Vehicle::Iterate()) {
1167 SlObject(v, _vehicle_desc);
1168 }
1169 }
1170};
1171
1172static const VEHSChunkHandler VEHS;
1173static const ChunkHandlerRef veh_chunk_handlers[] = {
1174 VEHS,
1175};
1176
1177extern const ChunkHandlerTable _veh_chunk_handlers(veh_chunk_handlers);
void GetAircraftFlightLevelBounds(const Vehicle *v, int *min, int *max)
Get the 'flight level' bounds, in pixels from 'z_pos' 0 for a particular vehicle for normal flight si...
void AircraftNextAirportPos_and_Order(Aircraft *v)
set the right pos when heading to other airports after takeoff
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir)
Aircraft is about to leave the hangar.
void SetAircraftPosition(Aircraft *v, int x, int y, int z)
Set aircraft position.
@ AIR_HELICOPTER
an helicopter
Definition aircraft.h:29
void UpdateAircraftCache(Aircraft *v, bool update_range=false)
Update cached values of an aircraft.
@ HANGAR
Heading for hangar.
Definition airport.h:62
@ FLYING
Vehicle is flying in the air.
Definition airport.h:75
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Default handler for saving/loading an object to/from disk.
Definition saveload.h:581
SaveLoadTable GetDescription() const override
Definition saveload.h:583
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:122
SaveLoadTable GetLoadDescription() const
Get the description for how to load the chunk.
std::vector< RoadVehPathElement > & GetVector(RoadVehicle *rv) const override
Get instance of vector to load/save.
std::vector< ShipPathElement > & GetVector(Ship *s) const override
Get instance of vector to load/save.
Default handler for saving/loading a vector to/from disk.
Definition saveload.h:1365
void Append(CargoPacket *cp, MoveToAction action=MTA_KEEP)
Appends the given cargo packet.
int CompanyServiceInterval(const Company *c, VehicleType type)
Get the service interval for the given company and vehicle type.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition debug.h:37
@ ST_SMALL_UFO
Small UFO, tries to find a road vehicle to destroy.
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
uint16_t EngineID
Unique identification number of an engine.
Definition engine_type.h:21
@ RAILVEH_WAGON
simple wagon, not motorized
Definition engine_type.h:29
@ RAILVEH_MULTIHEAD
indicates a combination of two locomotives
Definition engine_type.h:28
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:17
int TicksToLeaveDepot(const Train *v)
Compute number of ticks when next wagon will leave a depot.
Track GetRailDepotTrack(Tile t)
Returns the track of a depot, ignoring direction.
Definition rail_map.h:182
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:227
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:30
void RoadVehUpdateCache(RoadVehicle *v, bool same_length=false)
Update the cache of a road vehicle.
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition saveload.cpp:659
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition saveload.cpp:351
uint8_t SlReadByte()
Wrapper for reading a byte from the buffer.
Definition saveload.cpp:392
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Functions/types related to saving and loading games.
@ SLF_ALLOW_CONTROL
Allow control codes in the strings.
Definition saveload.h:688
#define SLEG_CONDVAR(name, variable, type, from, to)
Storage of a global variable in some savegame versions.
Definition saveload.h:1109
#define SLEG_CONDVECTOR(name, variable, type, from, to)
Storage of a global vector of SL_VAR elements in some savegame versions.
Definition saveload.h:1169
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition saveload.h:509
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition saveload.h:512
#define SLE_SAVEBYTE(base, variable)
Only write byte during saving; never read it during loading.
Definition saveload.h:1083
#define SLE_REF(base, variable, type)
Storage of a reference in every version of a savegame.
Definition saveload.h:1019
#define SLE_CONDREFLIST(base, variable, type, from, to)
Storage of a list of SL_REF elements in some savegame versions.
Definition saveload.h:954
#define SLE_CONDARR(base, variable, type, length, from, to)
Storage of a fixed-size array of SL_VAR elements in some savegame versions.
Definition saveload.h:900
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition saveload.h:518
#define SLEG_STRUCT(name, handler)
Storage of a structs in every savegame version.
Definition saveload.h:1218
#define SLE_CONDSSTR(base, variable, type, from, to)
Storage of a std::string in some savegame versions.
Definition saveload.h:933
#define SLE_CONDVAR(base, variable, type, from, to)
Storage of a variable in some savegame versions.
Definition saveload.h:868
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition saveload.h:1263
@ SLV_67
67 10236
Definition saveload.h:123
@ SLV_182
182 25115 FS#5492, r25259, r25296 Goal status
Definition saveload.h:261
@ SLV_40
40 7326
Definition saveload.h:91
@ SLV_129
129 18292
Definition saveload.h:197
@ SLV_84
84 11822
Definition saveload.h:143
@ SLV_36
36 6624
Definition saveload.h:86
@ SLV_180
180 24998 1.3.x
Definition saveload.h:259
@ SLV_174
174 23973 1.2.x
Definition saveload.h:251
@ SLV_100
100 13952
Definition saveload.h:163
@ SLV_44
44 8144
Definition saveload.h:95
@ SLV_VEHICLE_ECONOMY_AGE
334 PR#12141 v14.0 Add vehicle age in economy year, for profit stats minimum age
Definition saveload.h:380
@ SLV_ROADVEH_PATH_CACHE
211 PR#7261 Add path cache for road vehicles.
Definition saveload.h:297
@ SLV_6
6.0 1721 6.1 1768
Definition saveload.h:46
@ SLV_181
181 25012
Definition saveload.h:260
@ SLV_60
60 9874
Definition saveload.h:115
@ SLV_65
65 10210
Definition saveload.h:121
@ SLV_DISASTER_VEH_STATE
312 PR#10798 Explicit storage of disaster vehicle state.
Definition saveload.h:354
@ SLV_TIMETABLE_START_TICKS
321 PR#11468 Convert timetable start from a date to ticks.
Definition saveload.h:365
@ SLV_SHIP_ROTATION
204 PR#7065 Add extra rotation stages for ships.
Definition saveload.h:288
@ SLV_191
191 26636 FS#6026 Fix disaster vehicle storage (No bump) 191 26646 FS#6041 Linkgraph - store location...
Definition saveload.h:272
@ SLV_8
8.0 1786
Definition saveload.h:49
@ SLV_112
112 15290
Definition saveload.h:177
@ SLV_SHIP_PATH_CACHE
203 PR#7072 Add path cache for ships
Definition saveload.h:287
@ SLV_PATH_CACHE_FORMAT
346 PR#12345 Vehicle path cache format changed.
Definition saveload.h:395
@ SL_MAX_VERSION
Highest possible saveload version.
Definition saveload.h:399
@ SLV_164
164 23290
Definition saveload.h:239
@ SLV_160
160 21974 1.1.x
Definition saveload.h:235
@ SL_MIN_VERSION
First savegame version.
Definition saveload.h:31
@ SLV_VEH_MOTION_COUNTER
288 PR#8591 Desync safe motion counter
Definition saveload.h:325
@ SLV_EXTEND_VEHICLE_RANDOM
310 PR#10701 Extend vehicle random bits.
Definition saveload.h:352
@ SLV_51
51 8978
Definition saveload.h:104
@ SLV_35
35 6602
Definition saveload.h:85
@ SLV_68
68 10266
Definition saveload.h:124
@ SLV_2
2.0 0.3.0 2.1 0.3.1, 0.3.2
Definition saveload.h:34
@ SLV_157
157 21862
Definition saveload.h:231
@ SLV_LAST_LOADING_TICK
301 PR#9693 Store tick of last loading for vehicles.
Definition saveload.h:341
@ SLV_105
105 14803
Definition saveload.h:169
@ SLV_DEPOT_UNBUNCHING
331 PR#11945 Allow unbunching shared order vehicles at a depot.
Definition saveload.h:377
@ SLV_139
139 19346
Definition saveload.h:209
@ SLV_158
158 21933
Definition saveload.h:232
@ SLV_45
45 8501
Definition saveload.h:97
@ SLV_167
167 23504
Definition saveload.h:243
@ SLV_TIMETABLE_TICKS_TYPE
323 PR#11435 Convert timetable current order time to ticks.
Definition saveload.h:367
@ SLV_5
5.0 1429 5.1 1440 5.2 1525 0.3.6
Definition saveload.h:43
@ SLV_NEWGRF_LAST_SERVICE
317 PR#11124 Added stable date_of_last_service to avoid NewGRF trouble.
Definition saveload.h:360
@ SLV_88
88 12134
Definition saveload.h:148
@ SLV_7
7.0 1770
Definition saveload.h:48
@ SLV_194
194 26881 v1.5
Definition saveload.h:276
@ SLV_162
162 22713
Definition saveload.h:237
@ SLV_31
31 5999
Definition saveload.h:80
@ SLV_136
136 18764
Definition saveload.h:206
#define SLE_CONDREF(base, variable, type, from, to)
Storage of a reference in some savegame versions.
Definition saveload.h:889
@ REF_VEHICLE_OLD
Load/save an old-style reference to a vehicle (for pre-4.4 savegames).
Definition saveload.h:605
@ REF_CARGO_PACKET
Load/save a reference to a cargo packet.
Definition saveload.h:608
@ REF_ORDER
Load/save a reference to an order.
Definition saveload.h:601
@ REF_ORDERLIST
Load/save a reference to an orderlist.
Definition saveload.h:609
@ REF_VEHICLE
Load/save a reference to a vehicle.
Definition saveload.h:602
#define SLEG_CONDSTRUCTLIST(name, handler, from, to)
Storage of a list of structs in some savegame versions.
Definition saveload.h:1178
#define SLE_VAR(base, variable, type)
Storage of a variable in every version of a savegame.
Definition saveload.h:1002
#define SLE_CONDVARNAME(base, variable, name, type, from, to)
Storage of a variable in some savegame versions.
Definition saveload.h:879
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:57
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition aircraft.h:72
bool IsNormalAircraft() const
Check if the aircraft type is a normal flying device; eg not a rotor or a shadow.
Definition aircraft.h:121
VehicleType type
Type of vehicle.
Container for cargo from the same location and time.
Definition cargopacket.h:40
Handlers and description of chunk.
Definition saveload.h:463
CompanySettings settings
settings specific for each company
VehicleDefaultSettings vehicle
default settings for vehicles
Disasters, like submarines, skyrangers and their shadows, belong to this class.
A special vehicle is one of the following:
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
VehicleSettings vehicle
options for vehicles
Position information of a vehicle after it moved.
int y
x and y position of the vehicle after moving
uint16_t last_speed
The last speed we did display, so we only have to redraw when this changes.
GroundVehicleCache gcache
Cache of often calculated values.
void CargoChanged()
Recalculates the cached weight of a vehicle and its parts.
bool IsEngine() const
Check if a vehicle is an engine (can be first in a consist).
bool IsMultiheaded() const
Check if the vehicle is a multiheaded engine.
bool IsFreeWagon() const
Check if the vehicle is a free wagon (got no engine in front of it).
void ClearEngine()
Clear engine status.
void ClearMultiheaded()
Clear multiheaded engine property.
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition order_base.h:259
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:70
uint8_t type
The type of order + non-stop flags.
Definition order_base.h:48
uint8_t flags
Load/unload types, depot order/action types.
Definition order_base.h:49
static size_t GetPoolSize()
Returns first unused index.
Tindex index
Index of this pool item.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t index)
Returns Titem with given index.
Information about a rail vehicle.
Definition engine_type.h:42
Element of the RoadVehPathCache.
Definition roadveh.h:85
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
RoadVehPathCache path
Cached path.
Definition roadveh.h:99
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition roadveh.h:108
VehicleID disaster_vehicle
NOSAVE: Disaster vehicle targetting this vehicle.
Definition roadveh.h:109
SaveLoad type struct.
Definition saveload.h:717
Element of the ShipPathCache.
Definition ship.h:20
All ships have this type.
Definition ship.h:32
ShipPathCache path
Cached path.
Definition ship.h:33
void UpdateCache()
Update the caches of this ship.
Definition ship_cmd.cpp:232
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
static T * GetIfValid(size_t index)
Returns vehicle if the index is a valid index for this vehicle type.
T * Next() const
Get next vehicle in the chain.
static Pool::IterateWrapper< T > Iterate(size_t from=0)
Returns an iterable ensemble of all valid vehicles of type T.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
T * GetNextVehicle() const
Get the next real (non-articulated part) vehicle in the consist.
Station data structure.
'Train' is either a loco or a wagon.
Definition train.h:89
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
void FixPointers() const override
Fix the pointers.
void Load() const override
Load the chunk.
void Save() const override
Save the chunk.
bool servint_ispercent
service intervals are in percents
uint8_t roadveh_acceleration_model
realistic acceleration for road vehicles
void CopyWithoutPalette(const VehicleSpriteSeq &src)
Copy data from another sprite sequence, while dropping all recolouring information.
Vehicle data structure.
CargoPayment * cargo_payment
The cargo payment we're currently in.
EngineID engine_type
The type of engine used for this vehicle.
VehicleCargoList cargo
The cargo this vehicle is carrying.
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
GroupID group_id
Index of group Pool array.
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Order current_order
The current order (+ status, like: loading)
Vehicle * Next() const
Get the next vehicle of this vehicle.
uint8_t vehstatus
Status.
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
uint16_t cur_speed
current speed
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
TileIndex tile
Current tile index.
StationID last_station_visited
The last station we stopped at.
Vehicle * next_shared
pointer to the next vehicle that shares the order
TimerGameTick::TickCounter GetStartTickFromDate(TimerGameEconomy::Date start_date)
Get the TimerGameTick::TickCounter tick of a given date.
TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition track_func.h:77
@ TRACK_BIT_DEPOT
Bitflag for a depot.
Definition track_type.h:53
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:67
@ CCF_TRACK
Valid changes while vehicle is driving, and possibly changing tracks.
Definition train.h:48
@ CCF_SAVELOAD
Valid changes when loading a savegame. (Everything that is not stored in the save....
Definition train.h:53
TrainForceProceeding
Modes for ignoring signals.
Definition train.h:37
@ TFP_SIGNAL
Ignore next signal, after the signal ignore being stuck.
Definition train.h:40
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition vehicle.cpp:1784
uint8_t CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition vehicle.cpp:1493
@ VS_STOPPED
Vehicle is stopped by the player.
@ VS_CRASHED
Vehicle is crashed.
static const int32_t INVALID_COORD
Sentinel for an invalid coordinate.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
void AfterLoadVehiclesPhase1(bool part_of_load)
Called after load for phase 1 of vehicle initialisation.
void FixupTrainLengths()
Fixup old train spacing.
void UpdateOldAircraft()
need to be called to load aircraft from old version
void ReverseTrainDirection(Train *v)
Turn a train around.
void ConvertOldMultiheadToNew()
Converts all trains to the new subtype format introduced in savegame 16.2 It also links multiheaded e...
bool TrainController(Train *v, Vehicle *nomove, bool reverse=true)
Move a vehicle chain one movement stop forwards.
void ConnectMultiheadedTrains()
Link front and rear multiheaded engines to each other This is done when loading a savegame.
uint8_t _age_cargo_skip_counter
Skip aging of cargo? Used before savegame version 162.
Definition misc_sl.cpp:79
void AfterLoadVehiclesPhase2(bool part_of_load)
Called after load for phase 2 of vehicle initialisation.
void ReverseTrainSwapVeh(Train *v, int l, int r)
Swap vehicles l and r in consist v, and reverse their direction.
static void CheckValidVehicles()
Check all vehicles to ensure their engine type is valid for the currently loaded NewGRFs (that includ...
Loading of vehicle chunks before table headers were added.
const SaveLoadCompat _vehicle_train_sl_compat[]
Original field order for SlVehicleTrain.
const SaveLoadCompat _vehicle_disaster_sl_compat[]
Original field order for SlVehicleDisaster.
const SaveLoadCompat _vehicle_effect_sl_compat[]
Original field order for SlVehicleEffect.
const SaveLoadCompat _vehicle_ship_sl_compat[]
Original field order for SlVehicleShip.
const SaveLoadCompat _vehicle_sl_compat[]
Original field order for vehicle_desc.
const SaveLoadCompat _vehicle_roadveh_sl_compat[]
Original field order for SlVehicleRoadVeh.
const SaveLoadCompat _vehicle_common_sl_compat[]
Original field order for SlVehicleCommon.
const SaveLoadCompat _vehicle_aircraft_sl_compat[]
Original field order for SlVehicleAircraft.
@ EIT_ON_MAP
Vehicle drawn in viewport.
VehicleType
Available vehicle types.
@ VEH_INVALID
Non-existing type of vehicle.
@ VEH_ROAD
Road vehicle type.
@ VEH_DISASTER
Disaster vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_EFFECT
Effect vehicle type (smoke, explosions, sparks, bubbles)
@ VEH_TRAIN
Train vehicle type.
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.