OpenTTD Source 20260218-master-g2123fca5ea
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
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"
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.blocks = {}; // 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.Test(VehState::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.Reset(VehState::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 = TileIndex{}; // 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();
228 EngineID first_engine[4] = { EngineID::Invalid(), EngineID::Invalid(), EngineID::Invalid(), EngineID::Invalid() };
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
259void AfterLoadVehiclesPhase1(bool part_of_load)
260{
261 for (Vehicle *v : Vehicle::Iterate()) {
262 /* Reinstate the previous pointer */
263 if (v->Next() != nullptr) v->Next()->previous = v;
264 if (v->NextShared() != nullptr) v->NextShared()->previous_shared = v;
265
266 if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID;
267 v->first = nullptr;
268 if (v->IsGroundVehicle()) v->GetGroundVehicleCache()->first_engine = EngineID::Invalid();
269 }
270
271 /* AfterLoadVehicles may also be called in case of NewGRF reload, in this
272 * case we may not convert orders again. */
273 if (part_of_load) {
274 /* Create shared vehicle chain for very old games (pre 5,2) and create
275 * OrderList from shared vehicle chains. For this to work correctly, the
276 * following conditions must be fulfilled:
277 * a) both next_shared and previous_shared are not set for pre 5,2 games
278 * b) both next_shared and previous_shared are set for later games
279 */
280 std::map<uint32_t, OrderList *> mapping;
281
282 for (Vehicle *v : Vehicle::Iterate()) {
283 if (v->orders != nullptr) {
284 if (IsSavegameVersionBefore(SLV_105)) { // Pre-105 didn't save an OrderList
285 if (mapping[v->old_orders] == nullptr) {
286 /* This adds the whole shared vehicle chain for case b */
287
288 /* Creating an OrderList here is safe because the number of vehicles
289 * allowed in these savegames matches the number of OrderLists. As
290 * such each vehicle can get an OrderList and it will (still) fit. */
292 std::vector<Order> orders;
293 for (const OldOrderSaveLoadItem *old_order = GetOldOrder(v->old_orders); old_order != nullptr; old_order = GetOldOrder(old_order->next)) {
294 orders.push_back(std::move(old_order->order));
295 }
296 v->orders = mapping[v->old_orders] = OrderList::Create(std::move(orders), v);
297 } else {
298 v->orders = mapping[v->old_orders];
299 /* For old games (case a) we must create the shared vehicle chain */
301 v->AddToShared(v->orders->GetFirstSharedVehicle());
302 }
303 }
304 } else { // OrderList was saved as such, only recalculate not saved values
305 if (v->PreviousShared() == nullptr) {
306 v->orders->Initialize(v);
307 }
308 }
309 }
310 }
311 }
312
313 for (Vehicle *v : Vehicle::Iterate()) {
314 /* Fill the first pointers */
315 if (v->Previous() == nullptr) {
316 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
317 u->first = v;
318 }
319 }
320 }
321
322 if (part_of_load) {
324 /* Before 105 there was no order for shared orders, thus it messed up horribly */
325 for (Vehicle *v : Vehicle::Iterate()) {
326 if (v->First() != v || v->orders != nullptr || v->previous_shared != nullptr || v->next_shared == nullptr) continue;
327
328 /* As above, allocating OrderList here is safe. */
330 v->orders = OrderList::Create();
331 v->orders->first_shared = v;
332 for (Vehicle *u = v; u != nullptr; u = u->next_shared) {
333 u->orders = v->orders;
334 }
335 }
336 }
337
339 /* The road vehicle subtype was converted to a flag. */
340 for (RoadVehicle *rv : RoadVehicle::Iterate()) {
341 if (rv->subtype == 0) {
342 /* The road vehicle is at the front. */
343 rv->SetFrontEngine();
344 } else if (rv->subtype == 1) {
345 /* The road vehicle is an articulated part. */
346 rv->subtype = 0;
347 rv->SetArticulatedPart();
348 } else {
349 SlErrorCorrupt("Invalid road vehicle subtype");
350 }
351 }
352 }
353
355 /* In some old savegames there might be some "crap" stored. */
356 for (Vehicle *v : Vehicle::Iterate()) {
357 if (!v->IsPrimaryVehicle() && v->type != VEH_DISASTER) {
358 v->current_order.Free();
359 v->unitnumber = 0;
360 }
361 }
362 }
363
365 /* Set the vehicle-local cargo age counter from the old global counter. */
366 for (Vehicle *v : Vehicle::Iterate()) {
367 v->cargo_age_counter = _age_cargo_skip_counter;
368 }
369 }
370
372 /* Set service interval flags */
373 for (Vehicle *v : Vehicle::Iterate()) {
374 if (!v->IsPrimaryVehicle()) continue;
375
376 const Company *c = Company::Get(v->owner);
377 int interval = CompanyServiceInterval(c, v->type);
378
379 v->SetServiceIntervalIsCustom(v->GetServiceInterval() != interval);
380 v->SetServiceIntervalIsPercent(c->settings.vehicle.servint_ispercent);
381 }
382 }
383
385 /* Ship rotation added */
386 for (Ship *s : Ship::Iterate()) {
387 s->rotation = s->direction;
388 }
389 } else {
390 for (Ship *s : Ship::Iterate()) {
391 if (s->rotation == s->direction) continue;
392 /* In case we are rotating on gameload, set the rotation position to
393 * the current position, otherwise the applied workaround offset would
394 * be with respect to 0,0.
395 */
396 s->rotation_x_pos = s->x_pos;
397 s->rotation_y_pos = s->y_pos;
398 }
399 }
400
402 /* Convert timetable start from a date to an absolute tick in TimerGameTick::counter. */
403 for (Vehicle *v : Vehicle::Iterate()) {
404 /* If the start date is 0, the vehicle is not waiting to start and can be ignored. */
405 if (v->timetable_start == 0) continue;
406
407 v->timetable_start = GetStartTickFromDate(TimerGameEconomy::Date(v->timetable_start));
408 }
409 }
410
412 /* Set vehicle economy age based on calendar age. */
413 for (Vehicle *v : Vehicle::Iterate()) {
414 v->economy_age = TimerGameEconomy::Date{v->age.base()};
415 }
416 }
417 }
418
420}
421
423void AfterLoadVehiclesPhase2(bool part_of_load)
424{
425 for (Vehicle *v : Vehicle::Iterate()) {
426 assert(v->First() != nullptr);
427
428 v->trip_occupancy = CalcPercentVehicleFilled(v, nullptr);
429
430 switch (v->type) {
431 case VEH_TRAIN: {
432 Train *t = Train::From(v);
433 if (t->IsFrontEngine() || t->IsFreeWagon()) {
434 t->gcache.last_speed = t->cur_speed; // update displayed train speed
436 }
437 break;
438 }
439
440 case VEH_ROAD: {
442 if (rv->IsFrontEngine()) {
443 rv->gcache.last_speed = rv->cur_speed; // update displayed road vehicle speed
444
445 rv->roadtype = Engine::Get(rv->engine_type)->VehInfo<RoadVehicleInfo>().roadtype;
447 RoadTramType rtt = GetRoadTramType(rv->roadtype);
448 for (RoadVehicle *u = rv; u != nullptr; u = u->Next()) {
449 u->roadtype = rv->roadtype;
450 u->compatible_roadtypes = rv->compatible_roadtypes;
451 if (GetRoadType(u->tile, rtt) == INVALID_ROADTYPE) SlErrorCorrupt("Road vehicle on invalid road type");
452 }
453
455 if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) {
456 rv->CargoChanged();
457 }
458 }
459 break;
460 }
461
462 case VEH_SHIP:
464 break;
465
466 default: break;
467 }
468 }
469
470 /* Stop non-front engines */
471 if (part_of_load && IsSavegameVersionBefore(SLV_112)) {
472 for (Vehicle *v : Vehicle::Iterate()) {
473 if (v->type == VEH_TRAIN) {
474 Train *t = Train::From(v);
475 if (!t->IsFrontEngine()) {
477 /* cur_speed is now relevant for non-front parts - nonzero breaks
478 * moving-wagons-inside-depot- and autoreplace- code */
479 t->cur_speed = 0;
480 }
481 }
482 /* trains weren't stopping gradually in old OTTD versions (and TTO/TTD)
483 * other vehicle types didn't have zero speed while stopped (even in 'recent' OTTD versions) */
484 if (v->vehstatus.Test(VehState::Stopped) && (v->type != VEH_TRAIN || IsSavegameVersionBefore(SLV_2, 1))) {
485 v->cur_speed = 0;
486 }
487 }
488 }
489
490 for (Vehicle *v : Vehicle::Iterate()) {
491 switch (v->type) {
492 case VEH_ROAD:
493 case VEH_TRAIN:
494 case VEH_SHIP:
495 v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_cache.sprite_seq);
496 break;
497
498 case VEH_AIRCRAFT:
499 if (Aircraft::From(v)->IsNormalAircraft()) {
500 v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_cache.sprite_seq);
501
502 /* The aircraft's shadow will have the same image as the aircraft, but no colour */
503 Vehicle *shadow = v->Next();
504 if (shadow == nullptr) SlErrorCorrupt("Missing shadow for aircraft");
505
506 shadow->sprite_cache.sprite_seq.CopyWithoutPalette(v->sprite_cache.sprite_seq);
507
508 /* In the case of a helicopter we will update the rotor sprites */
509 if (v->subtype == AIR_HELICOPTER) {
510 Vehicle *rotor = shadow->Next();
511 if (rotor == nullptr) SlErrorCorrupt("Missing rotor for helicopter");
512
513 GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_cache.sprite_seq);
514 }
515
517 }
518 break;
519
520 case VEH_DISASTER: {
521 auto *dv = DisasterVehicle::From(v);
522 if (dv->subtype == ST_SMALL_UFO && dv->state != 0) {
523 RoadVehicle *u = RoadVehicle::GetIfValid(v->dest_tile.base());
524 if (u != nullptr && u->IsFrontEngine()) {
525 /* Delete UFO targetting a vehicle which is already a target. */
526 if (u->disaster_vehicle != VehicleID::Invalid() && u->disaster_vehicle != dv->index) {
527 delete v;
528 continue;
529 } else {
530 u->disaster_vehicle = dv->index;
531 }
532 }
533 }
534 break;
535 }
536
537 default: break;
538 }
539
540 if (part_of_load && v->unitnumber != 0) {
541 Company::Get(v->owner)->freeunits[v->type].UseID(v->unitnumber);
542 }
543
544 v->UpdateDeltaXY();
545 v->coord.left = INVALID_COORD;
546 v->sprite_cache.old_coord.left = INVALID_COORD;
547 if (v->type != VEH_EFFECT) v->UpdatePosition();
548 v->UpdateViewport(false);
549 }
550}
551
552bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // From train_cmd.cpp
554void ReverseTrainSwapVeh(Train *v, int l, int r);
555
558{
559 /* Vehicle center was moved from 4 units behind the front to half the length
560 * behind the front. Move vehicles so they end up on the same spot. */
561 for (Vehicle *v : Vehicle::Iterate()) {
562 if (v->type == VEH_TRAIN && v->IsPrimaryVehicle()) {
563 /* The vehicle center is now more to the front depending on vehicle length,
564 * so we need to move all vehicles forward to cover the difference to the
565 * old center, otherwise wagon spacing in trains would be broken upon load. */
566 for (Train *u = Train::From(v); u != nullptr; u = u->Next()) {
567 if (u->track == TRACK_BIT_DEPOT || u->vehstatus.Test(VehState::Crashed)) continue;
568
569 Train *next = u->Next();
570
571 /* Try to pull the vehicle half its length forward. */
572 int diff = (VEHICLE_LENGTH - u->gcache.cached_veh_length) / 2;
573 int done;
574 for (done = 0; done < diff; done++) {
575 if (!TrainController(u, next, false)) break;
576 }
577
578 if (next != nullptr && done < diff && u->IsFrontEngine()) {
579 /* Pulling the front vehicle forwards failed, we either encountered a dead-end
580 * or a red signal. To fix this, we try to move the whole train the required
581 * space backwards and re-do the fix up of the front vehicle. */
582
583 /* Ignore any signals when backtracking. */
584 TrainForceProceeding old_tfp = u->force_proceed;
585 u->force_proceed = TFP_SIGNAL;
586
587 /* Swap start<>end, start+1<>end-1, ... */
588 int r = CountVehiclesInChain(u) - 1; // number of vehicles - 1
589 int l = 0;
590 do ReverseTrainSwapVeh(u, l++, r--); while (l <= r);
591
592 /* We moved the first vehicle which is now the last. Move it back to the
593 * original position as we will fix up the last vehicle later in the loop. */
594 for (int i = 0; i < done; i++) TrainController(u->Last(), nullptr);
595
596 /* Move the train backwards to get space for the first vehicle. As the stopping
597 * distance from a line end is rounded up, move the train one unit more to cater
598 * for front vehicles with odd lengths. */
599 int moved;
600 for (moved = 0; moved < diff + 1; moved++) {
601 if (!TrainController(u, nullptr, false)) break;
602 }
603
604 /* Swap start<>end, start+1<>end-1, ... again. */
605 r = CountVehiclesInChain(u) - 1; // number of vehicles - 1
606 l = 0;
607 do ReverseTrainSwapVeh(u, l++, r--); while (l <= r);
608
609 u->force_proceed = old_tfp;
610
611 /* Tracks are too short to fix the train length. The player has to fix the
612 * train in a depot. Bail out so we don't damage the vehicle chain any more. */
613 if (moved < diff + 1) break;
614
615 /* Re-do the correction for the first vehicle. */
616 for (done = 0; done < diff; done++) TrainController(u, next, false);
617
618 /* We moved one unit more backwards than needed for even-length front vehicles,
619 * try to move that unit forward again. We don't care if this step fails. */
620 TrainController(u, nullptr, false);
621 }
622
623 /* If the next wagon is still in a depot, check if it shouldn't be outside already. */
624 if (next != nullptr && next->track == TRACK_BIT_DEPOT) {
625 int d = TicksToLeaveDepot(u);
626 if (d <= 0) {
627 /* Next vehicle should have left the depot already, show it and pull forward. */
629 next->track = TrackToTrackBits(GetRailDepotTrack(next->tile));
630 for (int i = 0; i >= d; i--) TrainController(next, nullptr);
631 }
632 }
633 }
634
635 /* Update all cached properties after moving the vehicle chain around. */
637 }
638 }
639}
640
641static uint8_t _cargo_periods;
642static StationID _cargo_source;
643static TileIndex _cargo_source_xy;
644static uint16_t _cargo_count;
645static uint16_t _cargo_paid_for;
646static Money _cargo_feeder_share;
647
648class SlVehicleCommon : public DefaultSaveLoadHandler<SlVehicleCommon, Vehicle> {
649public:
650 static inline const SaveLoad description[] = {
651 SLE_VAR(Vehicle, subtype, SLE_UINT8),
652
654 SLE_CONDVAR(Vehicle, name, SLE_NAME, SL_MIN_VERSION, SLV_84),
656 SLE_CONDVAR(Vehicle, unitnumber, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_8),
657 SLE_CONDVAR(Vehicle, unitnumber, SLE_UINT16, SLV_8, SL_MAX_VERSION),
658 SLE_VAR(Vehicle, owner, SLE_UINT8),
659 SLE_CONDVAR(Vehicle, tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
660 SLE_CONDVAR(Vehicle, tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
661 SLE_CONDVAR(Vehicle, dest_tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
662 SLE_CONDVAR(Vehicle, dest_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
663
664 SLE_CONDVAR(Vehicle, x_pos, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
665 SLE_CONDVAR(Vehicle, x_pos, SLE_UINT32, SLV_6, SL_MAX_VERSION),
666 SLE_CONDVAR(Vehicle, y_pos, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
667 SLE_CONDVAR(Vehicle, y_pos, SLE_UINT32, SLV_6, SL_MAX_VERSION),
668 SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
669 SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, SLV_164, SL_MAX_VERSION),
670 SLE_VAR(Vehicle, direction, SLE_UINT8),
671
672 SLE_VAR(Vehicle, spritenum, SLE_UINT8),
673 SLE_VAR(Vehicle, engine_type, SLE_UINT16),
674 SLE_VAR(Vehicle, cur_speed, SLE_UINT16),
675 SLE_VAR(Vehicle, subspeed, SLE_UINT8),
676 SLE_VAR(Vehicle, acceleration, SLE_UINT8),
677 SLE_CONDVAR(Vehicle, motion_counter, SLE_UINT32, SLV_VEH_MOTION_COUNTER, SL_MAX_VERSION),
678 SLE_VAR(Vehicle, progress, SLE_UINT8),
679
680 SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
681 SLE_CONDVAR(Vehicle, last_station_visited, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
682 SLE_CONDVAR(Vehicle, last_station_visited, SLE_UINT16, SLV_5, SL_MAX_VERSION),
683 SLE_CONDVAR(Vehicle, last_loading_station, SLE_UINT16, SLV_182, SL_MAX_VERSION),
684
685 SLE_VAR(Vehicle, cargo_type, SLE_UINT8),
686 SLE_CONDVAR(Vehicle, cargo_subtype, SLE_UINT8, SLV_35, SL_MAX_VERSION),
687 SLEG_CONDVAR("cargo_days", _cargo_periods, SLE_UINT8, SL_MIN_VERSION, SLV_68),
688 SLEG_CONDVAR("cargo_source", _cargo_source, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_7),
689 SLEG_CONDVAR("cargo_source", _cargo_source, SLE_UINT16, SLV_7, SLV_68),
690 SLEG_CONDVAR("cargo_source_xy", _cargo_source_xy, SLE_UINT32, SLV_44, SLV_68),
691 SLE_VAR(Vehicle, cargo_cap, SLE_UINT16),
692 SLE_CONDVAR(Vehicle, refit_cap, SLE_UINT16, SLV_182, SL_MAX_VERSION),
693 SLEG_CONDVAR("cargo_count", _cargo_count, SLE_UINT16, SL_MIN_VERSION, SLV_68),
695 SLE_CONDARR(Vehicle, cargo.action_counts, SLE_UINT, VehicleCargoList::NUM_MOVE_TO_ACTION, SLV_181, SL_MAX_VERSION),
696 SLE_CONDVAR(Vehicle, cargo_age_counter, SLE_UINT16, SLV_162, SL_MAX_VERSION),
697
698 SLE_VAR(Vehicle, day_counter, SLE_UINT8),
699 SLE_VAR(Vehicle, tick_counter, SLE_UINT8),
700 SLE_CONDVAR(Vehicle, running_ticks, SLE_UINT8, SLV_88, SL_MAX_VERSION),
701
702 SLE_VAR(Vehicle, cur_implicit_order_index, SLE_UINT8),
703 SLE_CONDVAR(Vehicle, cur_real_order_index, SLE_UINT8, SLV_158, SL_MAX_VERSION),
704
705 /* This next line is for version 4 and prior compatibility.. it temporarily reads
706 type and flags (which were both 4 bits) into type. Later on this is
707 converted correctly */
708 SLE_CONDVAR(Vehicle, current_order.type, SLE_UINT8, SL_MIN_VERSION, SLV_5),
709 SLE_CONDVAR(Vehicle, current_order.dest, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
710
711 /* Orders for version 5 and on */
712 SLE_CONDVAR(Vehicle, current_order.type, SLE_UINT8, SLV_5, SL_MAX_VERSION),
713 SLE_CONDVAR(Vehicle, current_order.flags, SLE_UINT8, SLV_5, SL_MAX_VERSION),
714 SLE_CONDVAR(Vehicle, current_order.dest, SLE_UINT16, SLV_5, SL_MAX_VERSION),
715
716 /* Refit in current order */
717 SLE_CONDVAR(Vehicle, current_order.refit_cargo, SLE_UINT8, SLV_36, SL_MAX_VERSION),
718
719 /* Timetable in current order */
720 SLE_CONDVAR(Vehicle, current_order.wait_time, SLE_UINT16, SLV_67, SL_MAX_VERSION),
721 SLE_CONDVAR(Vehicle, current_order.travel_time, SLE_UINT16, SLV_67, SL_MAX_VERSION),
722 SLE_CONDVAR(Vehicle, current_order.max_speed, SLE_UINT16, SLV_174, SL_MAX_VERSION),
723 SLE_CONDVAR(Vehicle, timetable_start, SLE_FILE_I32 | SLE_VAR_U64, SLV_129, SLV_TIMETABLE_START_TICKS),
724 SLE_CONDVAR(Vehicle, timetable_start, SLE_UINT64, SLV_TIMETABLE_START_TICKS, SL_MAX_VERSION),
725
726 SLE_CONDVARNAME(Vehicle, old_orders, "orders", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_69),
727 SLE_CONDVARNAME(Vehicle, old_orders, "orders", SLE_UINT32, SLV_69, SLV_105),
729
730 SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
731 SLE_CONDVAR(Vehicle, age, SLE_INT32, SLV_31, SL_MAX_VERSION),
733 SLE_CONDVAR(Vehicle, max_age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
734 SLE_CONDVAR(Vehicle, max_age, SLE_INT32, SLV_31, SL_MAX_VERSION),
735 SLE_CONDVAR(Vehicle, date_of_last_service, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
736 SLE_CONDVAR(Vehicle, date_of_last_service, SLE_INT32, SLV_31, SL_MAX_VERSION),
737 SLE_CONDVAR(Vehicle, date_of_last_service_newgrf, SLE_INT32, SLV_NEWGRF_LAST_SERVICE, SL_MAX_VERSION),
738 SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SL_MIN_VERSION, SLV_31),
739 SLE_CONDVAR(Vehicle, service_interval, SLE_FILE_U32 | SLE_VAR_U16, SLV_31, SLV_180),
740 SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SLV_180, SL_MAX_VERSION),
741 SLE_VAR(Vehicle, reliability, SLE_UINT16),
742 SLE_VAR(Vehicle, reliability_spd_dec, SLE_UINT16),
743 SLE_VAR(Vehicle, breakdown_ctr, SLE_UINT8),
744 SLE_VAR(Vehicle, breakdown_delay, SLE_UINT8),
745 SLE_VAR(Vehicle, breakdowns_since_last_service, SLE_UINT8),
746 SLE_VAR(Vehicle, breakdown_chance, SLE_UINT8),
747 SLE_CONDVAR(Vehicle, build_year, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
748 SLE_CONDVAR(Vehicle, build_year, SLE_INT32, SLV_31, SL_MAX_VERSION),
749
750 SLE_VAR(Vehicle, load_unload_ticks, SLE_UINT16),
751 SLEG_CONDVAR("cargo_paid_for", _cargo_paid_for, SLE_UINT16, SLV_45, SL_MAX_VERSION),
752 SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_40, SLV_180),
753 SLE_CONDVAR(Vehicle, vehicle_flags, SLE_UINT16, SLV_180, SL_MAX_VERSION),
754
755 SLE_CONDVAR(Vehicle, profit_this_year, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
756 SLE_CONDVAR(Vehicle, profit_this_year, SLE_INT64, SLV_65, SL_MAX_VERSION),
757 SLE_CONDVAR(Vehicle, profit_last_year, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
758 SLE_CONDVAR(Vehicle, profit_last_year, SLE_INT64, SLV_65, SL_MAX_VERSION),
759 SLEG_CONDVAR("cargo_feeder_share", _cargo_feeder_share, SLE_FILE_I32 | SLE_VAR_I64, SLV_51, SLV_65),
760 SLEG_CONDVAR("cargo_feeder_share", _cargo_feeder_share, SLE_INT64, SLV_65, SLV_68),
761 SLE_CONDVAR(Vehicle, value, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
762 SLE_CONDVAR(Vehicle, value, SLE_INT64, SLV_65, SL_MAX_VERSION),
763
764 SLE_CONDVAR(Vehicle, random_bits, SLE_FILE_U8 | SLE_VAR_U16, SLV_2, SLV_EXTEND_VEHICLE_RANDOM),
766 SLE_CONDVARNAME(Vehicle, waiting_random_triggers, "waiting_triggers", SLE_UINT8, SLV_2, SL_MAX_VERSION),
767
769 SLE_CONDVAR(Vehicle, group_id, SLE_UINT16, SLV_60, SL_MAX_VERSION),
770
771 SLE_CONDVAR(Vehicle, current_order_time, SLE_FILE_U32 | SLE_VAR_I32, SLV_67, SLV_TIMETABLE_TICKS_TYPE),
772 SLE_CONDVAR(Vehicle, current_order_time, SLE_INT32, SLV_TIMETABLE_TICKS_TYPE, SL_MAX_VERSION),
773 SLE_CONDVAR(Vehicle, last_loading_tick, SLE_UINT64, SLV_LAST_LOADING_TICK, SL_MAX_VERSION),
774 SLE_CONDVAR(Vehicle, lateness_counter, SLE_INT32, SLV_67, SL_MAX_VERSION),
775
776 SLE_CONDVAR(Vehicle, depot_unbunching_last_departure, SLE_UINT64, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION),
777 SLE_CONDVAR(Vehicle, depot_unbunching_next_departure, SLE_UINT64, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION),
778 SLE_CONDVAR(Vehicle, round_trip_time, SLE_INT32, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION),
779 };
780
781 static inline const SaveLoadCompatTable compat_description = _vehicle_common_sl_compat;
782
783 void Save(Vehicle *v) const override
784 {
785 SlObject(v, this->GetDescription());
786 }
787
788 void Load(Vehicle *v) const override
789 {
790 SlObject(v, this->GetLoadDescription());
791 }
792
793 void FixPointers(Vehicle *v) const override
794 {
795 SlObject(v, this->GetDescription());
796 }
797};
798
799class SlVehicleTrain : public DefaultSaveLoadHandler<SlVehicleTrain, Vehicle> {
800public:
801 static inline const SaveLoad description[] = {
802 SLEG_STRUCT("common", SlVehicleCommon),
803 SLE_VAR(Train, crash_anim_pos, SLE_UINT16),
804 SLE_VAR(Train, force_proceed, SLE_UINT8),
805 SLE_VAR(Train, track, SLE_UINT8),
806
807 SLE_CONDVAR(Train, flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_2, SLV_100),
808 SLE_CONDVAR(Train, flags, SLE_UINT16, SLV_100, SL_MAX_VERSION),
809 SLE_CONDVAR(Train, wait_counter, SLE_UINT16, SLV_136, SL_MAX_VERSION),
810 SLE_CONDVAR(Train, gv_flags, SLE_UINT16, SLV_139, SL_MAX_VERSION),
811 };
812 static inline const SaveLoadCompatTable compat_description = _vehicle_train_sl_compat;
813
814 void Save(Vehicle *v) const override
815 {
816 if (v->type != VEH_TRAIN) return;
817 SlObject(v, this->GetDescription());
818 }
819
820 void Load(Vehicle *v) const override
821 {
822 if (v->type != VEH_TRAIN) return;
823 SlObject(v, this->GetLoadDescription());
824 }
825
826 void FixPointers(Vehicle *v) const override
827 {
828 if (v->type != VEH_TRAIN) return;
829 SlObject(v, this->GetDescription());
830 }
831};
832
833class SlVehicleRoadVehPath : public VectorSaveLoadHandler<SlVehicleRoadVehPath, RoadVehicle, RoadVehPathElement> {
834public:
835 static inline const SaveLoad description[] = {
836 SLE_VAR(RoadVehPathElement, trackdir, SLE_UINT8),
837 SLE_VAR(RoadVehPathElement, tile, SLE_UINT32),
838 };
839 static inline const SaveLoadCompatTable compat_description = {};
840
841 std::vector<RoadVehPathElement> &GetVector(RoadVehicle *rv) const override { return rv->path; }
842};
843
844class SlVehicleRoadVeh : public DefaultSaveLoadHandler<SlVehicleRoadVeh, Vehicle> {
845public:
846 /* RoadVehicle path is stored in std::pair which cannot be directly saved. */
847 static inline std::vector<Trackdir> rv_path_td;
848 static inline std::vector<TileIndex> rv_path_tile;
849
850 static inline const SaveLoad description[] = {
851 SLEG_STRUCT("common", SlVehicleCommon),
852 SLE_VAR(RoadVehicle, state, SLE_UINT8),
853 SLE_VAR(RoadVehicle, frame, SLE_UINT8),
854 SLE_VAR(RoadVehicle, blocked_ctr, SLE_UINT16),
855 SLE_VAR(RoadVehicle, overtaking, SLE_UINT8),
856 SLE_VAR(RoadVehicle, overtaking_ctr, SLE_UINT8),
857 SLE_VAR(RoadVehicle, crashed_ctr, SLE_UINT16),
858 SLE_VAR(RoadVehicle, reverse_ctr, SLE_UINT8),
859 SLEG_CONDVECTOR("path.td", rv_path_td, SLE_UINT8, SLV_ROADVEH_PATH_CACHE, SLV_PATH_CACHE_FORMAT),
860 SLEG_CONDVECTOR("path.tile", rv_path_tile, SLE_UINT32, SLV_ROADVEH_PATH_CACHE, SLV_PATH_CACHE_FORMAT),
862 SLE_CONDVAR(RoadVehicle, gv_flags, SLE_UINT16, SLV_139, SL_MAX_VERSION),
863 };
864 static inline const SaveLoadCompatTable compat_description = _vehicle_roadveh_sl_compat;
865
866 static void ConvertPathCache(RoadVehicle &rv)
867 {
868 /* The two vectors should be the same size, but if not we can just ignore the cache and not cause more issues. */
869 if (rv_path_td.size() != rv_path_tile.size()) {
870 Debug(sl, 1, "Found RoadVehicle {} with invalid path cache, ignoring.", rv.index);
871 return;
872 }
873 size_t n = std::min(rv_path_td.size(), rv_path_tile.size());
874 if (n == 0) return;
875
876 rv.path.reserve(n);
877 for (size_t c = 0; c < n; ++c) {
878 rv.path.emplace_back(rv_path_td[c], rv_path_tile[c]);
879 }
880
881 /* Path cache is now taken from back instead of front, so needs reversing. */
882 std::reverse(std::begin(rv.path), std::end(rv.path));
883 }
884
885 void Save(Vehicle *v) const override
886 {
887 if (v->type != VEH_ROAD) return;
888 SlObject(v, this->GetDescription());
889 }
890
891 void Load(Vehicle *v) const override
892 {
893 if (v->type != VEH_ROAD) return;
894 SlObject(v, this->GetLoadDescription());
896 ConvertPathCache(*static_cast<RoadVehicle *>(v));
897 }
898 }
899
900 void FixPointers(Vehicle *v) const override
901 {
902 if (v->type != VEH_ROAD) return;
903 SlObject(v, this->GetDescription());
904 }
905};
906
907class SlVehicleShipPath : public VectorSaveLoadHandler<SlVehicleShipPath, Ship, ShipPathElement> {
908public:
909 static inline const SaveLoad description[] = {
910 SLE_VAR(ShipPathElement, trackdir, SLE_UINT8),
911 };
912 static inline const SaveLoadCompatTable compat_description = {};
913
914 std::vector<ShipPathElement> &GetVector(Ship *s) const override { return s->path; }
915};
916
917class SlVehicleShip : public DefaultSaveLoadHandler<SlVehicleShip, Vehicle> {
918public:
919 static inline std::vector<Trackdir> ship_path_td;
920
921 static inline const SaveLoad description[] = {
922 SLEG_STRUCT("common", SlVehicleCommon),
923 SLE_VAR(Ship, state, SLE_UINT8),
924 SLEG_CONDVECTOR("path", ship_path_td, SLE_UINT8, SLV_SHIP_PATH_CACHE, SLV_PATH_CACHE_FORMAT),
926 SLE_CONDVAR(Ship, rotation, SLE_UINT8, SLV_SHIP_ROTATION, SL_MAX_VERSION),
927 };
928 static inline const SaveLoadCompatTable compat_description = _vehicle_ship_sl_compat;
929
930 void Save(Vehicle *v) const override
931 {
932 if (v->type != VEH_SHIP) return;
933 SlObject(v, this->GetDescription());
934 }
935
936 void Load(Vehicle *v) const override
937 {
938 if (v->type != VEH_SHIP) return;
939 SlObject(v, this->GetLoadDescription());
940
942 /* Path cache is now taken from back instead of front, so needs reversing. */
943 Ship *s = static_cast<Ship *>(v);
944 std::transform(std::rbegin(ship_path_td), std::rend(ship_path_td), std::back_inserter(s->path), [](Trackdir trackdir) { return trackdir; });
945 }
946 }
947
948 void FixPointers(Vehicle *v) const override
949 {
950 if (v->type != VEH_SHIP) return;
951 SlObject(v, this->GetDescription());
952 }
953};
954
955class SlVehicleAircraft : public DefaultSaveLoadHandler<SlVehicleAircraft, Vehicle> {
956public:
957 static inline const SaveLoad description[] = {
958 SLEG_STRUCT("common", SlVehicleCommon),
959 SLE_VAR(Aircraft, crashed_counter, SLE_UINT16),
960 SLE_VAR(Aircraft, pos, SLE_UINT8),
961
962 SLE_CONDVAR(Aircraft, targetairport, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
963 SLE_CONDVAR(Aircraft, targetairport, SLE_UINT16, SLV_5, SL_MAX_VERSION),
964
965 SLE_VAR(Aircraft, state, SLE_UINT8),
966
967 SLE_CONDVAR(Aircraft, previous_pos, SLE_UINT8, SLV_2, SL_MAX_VERSION),
968 SLE_CONDVAR(Aircraft, last_direction, SLE_UINT8, SLV_2, SL_MAX_VERSION),
969 SLE_CONDVAR(Aircraft, number_consecutive_turns, SLE_UINT8, SLV_2, SL_MAX_VERSION),
970
971 SLE_CONDVAR(Aircraft, turn_counter, SLE_UINT8, SLV_136, SL_MAX_VERSION),
972 SLE_CONDVAR(Aircraft, flags, SLE_UINT8, SLV_167, SL_MAX_VERSION),
973 };
974 static inline const SaveLoadCompatTable compat_description = _vehicle_aircraft_sl_compat;
975
976 void Save(Vehicle *v) const override
977 {
978 if (v->type != VEH_AIRCRAFT) return;
979 SlObject(v, this->GetDescription());
980 }
981
982 void Load(Vehicle *v) const override
983 {
984 if (v->type != VEH_AIRCRAFT) return;
985 SlObject(v, this->GetLoadDescription());
986 }
987
988 void FixPointers(Vehicle *v) const override
989 {
990 if (v->type != VEH_AIRCRAFT) return;
991 SlObject(v, this->GetDescription());
992 }
993};
994
995class SlVehicleEffect : public DefaultSaveLoadHandler<SlVehicleEffect, Vehicle> {
996public:
997 static inline const SaveLoad description[] = {
998 SLE_VAR(Vehicle, subtype, SLE_UINT8),
999
1000 SLE_CONDVAR(Vehicle, tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
1001 SLE_CONDVAR(Vehicle, tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
1002
1003 SLE_CONDVAR(Vehicle, x_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
1004 SLE_CONDVAR(Vehicle, x_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
1005 SLE_CONDVAR(Vehicle, y_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
1006 SLE_CONDVAR(Vehicle, y_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
1007 SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
1008 SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, SLV_164, SL_MAX_VERSION),
1009
1010 SLE_VAR(Vehicle, sprite_cache.sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
1011 SLE_VAR(Vehicle, progress, SLE_UINT8),
1012 SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
1013
1014 SLE_VAR(EffectVehicle, animation_state, SLE_UINT16),
1015 SLE_VAR(EffectVehicle, animation_substate, SLE_UINT8),
1016
1017 SLE_CONDVAR(Vehicle, spritenum, SLE_UINT8, SLV_2, SL_MAX_VERSION),
1018 };
1019 static inline const SaveLoadCompatTable compat_description = _vehicle_effect_sl_compat;
1020
1021 void Save(Vehicle *v) const override
1022 {
1023 if (v->type != VEH_EFFECT) return;
1024 SlObject(v, this->GetDescription());
1025 }
1026
1027 void Load(Vehicle *v) const override
1028 {
1029 if (v->type != VEH_EFFECT) return;
1030 SlObject(v, this->GetLoadDescription());
1031 }
1032
1033 void FixPointers(Vehicle *v) const override
1034 {
1035 if (v->type != VEH_EFFECT) return;
1036 SlObject(v, this->GetDescription());
1037 }
1038};
1039
1040class SlVehicleDisaster : public DefaultSaveLoadHandler<SlVehicleDisaster, Vehicle> {
1041public:
1042 static inline const SaveLoad description[] = {
1044
1045 SLE_VAR(Vehicle, subtype, SLE_UINT8),
1046 SLE_CONDVAR(Vehicle, tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
1047 SLE_CONDVAR(Vehicle, tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
1048 SLE_CONDVAR(Vehicle, dest_tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
1049 SLE_CONDVAR(Vehicle, dest_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
1050
1051 SLE_CONDVAR(Vehicle, x_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
1052 SLE_CONDVAR(Vehicle, x_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
1053 SLE_CONDVAR(Vehicle, y_pos, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
1054 SLE_CONDVAR(Vehicle, y_pos, SLE_INT32, SLV_6, SL_MAX_VERSION),
1055 SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
1056 SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, SLV_164, SL_MAX_VERSION),
1057 SLE_VAR(Vehicle, direction, SLE_UINT8),
1058
1059 SLE_VAR(Vehicle, owner, SLE_UINT8),
1060 SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
1061 SLE_CONDVARNAME(DisasterVehicle, state, "current_order.dest", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
1062 SLE_CONDVARNAME(DisasterVehicle, state, "current_order.dest", SLE_UINT16, SLV_5, SLV_DISASTER_VEH_STATE),
1064
1065 SLE_VAR(Vehicle, sprite_cache.sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
1066 SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
1067 SLE_CONDVAR(Vehicle, age, SLE_INT32, SLV_31, SL_MAX_VERSION),
1068 SLE_VAR(Vehicle, tick_counter, SLE_UINT8),
1069
1070 SLE_CONDVAR(DisasterVehicle, image_override, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_191),
1071 SLE_CONDVAR(DisasterVehicle, image_override, SLE_UINT32, SLV_191, SL_MAX_VERSION),
1072 SLE_CONDVAR(DisasterVehicle, big_ufo_destroyer_target, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_191),
1073 SLE_CONDVAR(DisasterVehicle, big_ufo_destroyer_target, SLE_UINT32, SLV_191, SL_MAX_VERSION),
1075 };
1076
1077 static inline const SaveLoadCompatTable compat_description = _vehicle_disaster_sl_compat;
1078
1079 void Save(Vehicle *v) const override
1080 {
1081 if (v->type != VEH_DISASTER) return;
1082 SlObject(v, this->GetDescription());
1083 }
1084
1085 void Load(Vehicle *v) const override
1086 {
1087 if (v->type != VEH_DISASTER) return;
1088 SlObject(v, this->GetLoadDescription());
1089 }
1090
1091 void FixPointers(Vehicle *v) const override
1092 {
1093 if (v->type != VEH_DISASTER) return;
1094 SlObject(v, this->GetDescription());
1095 }
1096};
1097
1098static const SaveLoad _vehicle_desc[] = {
1099 SLE_SAVEBYTE(Vehicle, type),
1100 SLEG_STRUCT("train", SlVehicleTrain),
1101 SLEG_STRUCT("roadveh", SlVehicleRoadVeh),
1102 SLEG_STRUCT("ship", SlVehicleShip),
1103 SLEG_STRUCT("aircraft", SlVehicleAircraft),
1104 SLEG_STRUCT("effect", SlVehicleEffect),
1105 SLEG_STRUCT("disaster", SlVehicleDisaster),
1106};
1107
1108struct VEHSChunkHandler : ChunkHandler {
1109 VEHSChunkHandler() : ChunkHandler('VEHS', CH_SPARSE_TABLE) {}
1110
1111 void Save() const override
1112 {
1113 SlTableHeader(_vehicle_desc);
1114
1115 /* Write the vehicles */
1116 for (Vehicle *v : Vehicle::Iterate()) {
1117 SlSetArrayIndex(v->index);
1118 SlObject(v, _vehicle_desc);
1119 }
1120 }
1121
1122 void Load() const override
1123 {
1124 const std::vector<SaveLoad> slt = SlCompatTableHeader(_vehicle_desc, _vehicle_sl_compat);
1125
1126 int index;
1127
1128 _cargo_count = 0;
1129
1130 while ((index = SlIterateArray()) != -1) {
1131 Vehicle *v;
1133
1134 switch (vtype) {
1135 case VEH_TRAIN: v = Train::CreateAtIndex(VehicleID(index)); break;
1136 case VEH_ROAD: v = RoadVehicle::CreateAtIndex(VehicleID(index)); break;
1137 case VEH_SHIP: v = Ship::CreateAtIndex(VehicleID(index)); break;
1138 case VEH_AIRCRAFT: v = Aircraft::CreateAtIndex(VehicleID(index)); break;
1139 case VEH_EFFECT: v = EffectVehicle::CreateAtIndex(VehicleID(index)); break;
1140 case VEH_DISASTER: v = DisasterVehicle::CreateAtIndex(VehicleID(index)); break;
1141 case VEH_INVALID: // Savegame shouldn't contain invalid vehicles
1142 default: SlErrorCorrupt("Invalid vehicle type");
1143 }
1144
1145 SlObject(v, slt);
1146
1147 if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) {
1148 /* Don't construct the packet with station here, because that'll fail with old savegames */
1149 CargoPacket *cp = CargoPacket::Create(_cargo_count, _cargo_periods, _cargo_source, _cargo_source_xy, _cargo_feeder_share);
1150 v->cargo.Append(cp);
1151 }
1152
1153 /* Old savegames used 'last_station_visited = 0xFF' */
1155 v->last_station_visited = StationID::Invalid();
1156 }
1157
1158 if (IsSavegameVersionBefore(SLV_182)) v->last_loading_station = StationID::Invalid();
1159
1161 /* Convert the current_order.type (which is a mix of type and flags, because
1162 * in those versions, they both were 4 bits big) to type and flags */
1163 v->current_order.flags = GB(v->current_order.type, 4, 4);
1164 v->current_order.type &= 0x0F;
1165 }
1166
1167 /* Advanced vehicle lists got added */
1169 }
1170 }
1171
1172 void FixPointers() const override
1173 {
1174 for (Vehicle *v : Vehicle::Iterate()) {
1175 SlObject(v, _vehicle_desc);
1176 }
1177 }
1178};
1179
1180static const VEHSChunkHandler VEHS;
1181static const ChunkHandlerRef veh_chunk_handlers[] = {
1182 VEHS,
1183};
1184
1185extern const ChunkHandlerTable _veh_chunk_handlers(veh_chunk_handlers);
Base for aircraft.
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:64
@ FLYING
Vehicle is flying in the air.
Definition airport.h:77
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 SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
Default handler for saving/loading an object to/from disk.
Definition saveload.h:600
SaveLoadTable GetDescription() const override
Definition saveload.h:602
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:96
SaveLoadTable GetLoadDescription() const
Get the description for how to load the chunk.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SL_REF integers into pointers.
void Save(Vehicle *v) const override
Save the object to disk.
void Save(Vehicle *v) const override
Save the object to disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SL_REF integers into pointers.
void Load(Vehicle *v) const override
Load the object from disk.
void Save(Vehicle *v) const override
Save the object to disk.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SL_REF integers into pointers.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SL_REF integers into pointers.
void Save(Vehicle *v) const override
Save the object to disk.
void Load(Vehicle *v) const override
Load the object from disk.
std::vector< RoadVehPathElement > & GetVector(RoadVehicle *rv) const override
Get instance of vector to load/save.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SL_REF integers into pointers.
void Save(Vehicle *v) const override
Save the object to disk.
std::vector< ShipPathElement > & GetVector(Ship *s) const override
Get instance of vector to load/save.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SL_REF integers into pointers.
void Save(Vehicle *v) const override
Save the object to disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SL_REF integers into pointers.
void Load(Vehicle *v) const override
Load the object from disk.
void Save(Vehicle *v) const override
Save the object to disk.
Default handler for saving/loading a vector to/from disk.
Definition saveload.h:1403
void Append(CargoPacket *cp, MoveToAction action=MTA_KEEP)
Appends the given cargo packet.
Definition of stuff that is very close to a company, like the company struct itself.
int CompanyServiceInterval(const Company *c, VehicleType type)
Get the service interval for the given company and vehicle type.
Functions related to companies.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
All disaster vehicles.
@ ST_SMALL_UFO
Small UFO, tries to find a road vehicle to destroy.
Base classes related to the economy.
Base class for all effect vehicles.
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF > EngineID
Unique identification number of an engine.
Definition engine_type.h:26
@ RAILVEH_WAGON
simple wagon, not motorized
Definition engine_type.h:34
@ RAILVEH_MULTIHEAD
indicates a combination of two locomotives
Definition engine_type.h:33
static constexpr GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:18
uint8_t _age_cargo_skip_counter
Skip aging of cargo? Used before savegame version 162.
Definition misc_sl.cpp:79
OldOrderSaveLoadItem * GetOldOrder(size_t pool_index)
Get a pointer to an old order with the given reference index.
Definition order_sl.cpp:125
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:215
RoadType GetRoadType(Tile t, RoadTramType rtt)
Get the road type for the given RoadTramType.
Definition road_map.h:175
RoadTramType
The different types of road type.
Definition road_type.h:37
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
Road vehicle states.
void RoadVehUpdateCache(RoadVehicle *v, bool same_length=false)
Update the cache of a road vehicle.
A number of safeguards to prevent using unsafe methods.
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:677
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition saveload.cpp:369
uint8_t SlReadByte()
Wrapper for reading a byte from the buffer.
Definition saveload.cpp:410
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.
#define SLEG_CONDVAR(name, variable, type, from, to)
Storage of a global variable in some savegame versions.
Definition saveload.h:1145
@ SLF_ALLOW_CONTROL
Allow control codes in the strings.
Definition saveload.h:723
#define SLEG_CONDVECTOR(name, variable, type, from, to)
Storage of a global vector of SL_VAR elements in some savegame versions.
Definition saveload.h:1205
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition saveload.h:526
@ REF_VEHICLE_OLD
Load/save an old-style reference to a vehicle (for pre-4.4 savegames).
Definition saveload.h:640
@ REF_CARGO_PACKET
Load/save a reference to a cargo packet.
Definition saveload.h:643
@ REF_ORDERLIST
Load/save a reference to an orderlist.
Definition saveload.h:644
@ REF_VEHICLE
Load/save a reference to a vehicle.
Definition saveload.h:637
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition saveload.h:529
#define SLE_SAVEBYTE(base, variable)
Only write byte during saving; never read it during loading.
Definition saveload.h:1119
#define SLE_REF(base, variable, type)
Storage of a reference in every version of a savegame.
Definition saveload.h:1055
#define SLE_CONDREFLIST(base, variable, type, from, to)
Storage of a list of SL_REF elements in some savegame versions.
Definition saveload.h:990
#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:936
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition saveload.h:535
#define SLEG_STRUCT(name, handler)
Storage of a structs in every savegame version.
Definition saveload.h:1254
#define SLE_CONDSSTR(base, variable, type, from, to)
Storage of a std::string in some savegame versions.
Definition saveload.h:969
#define SLE_CONDVAR(base, variable, type, from, to)
Storage of a variable in some savegame versions.
Definition saveload.h:904
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition saveload.h:1299
@ SLV_69
69 10319
Definition saveload.h:125
@ 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:418
@ 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:925
#define SLEG_CONDSTRUCTLIST(name, handler, from, to)
Storage of a list of structs in some savegame versions.
Definition saveload.h:1214
#define SLE_VAR(base, variable, type)
Storage of a variable in every version of a savegame.
Definition saveload.h:1038
#define SLE_CONDVARNAME(base, variable, name, type, from, to)
Storage of a variable in some savegame versions.
Definition saveload.h:915
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
Base for ships.
Base classes/functions for stations.
Definition of base types and functions in a cross-platform compatible way.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition aircraft.h:73
VehicleType type
Type of vehicle.
Container for cargo from the same location and time.
Definition cargopacket.h:41
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:
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.
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Compatibility struct to allow saveload of pool-based orders.
Definition order_base.h:367
std::vector< Order > orders
Orders of the order list.
Definition order_base.h:394
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:66
uint8_t type
The type of order + non-stop flags.
Definition order_base.h:47
uint8_t flags
Load/unload types, depot order/action types.
Definition order_base.h:48
static Pool::IterateWrapper< Vehicle > Iterate(size_t from=0)
static T * CreateAtIndex(VehicleID index, Targs &&... args)
static Company * Get(auto index)
static Vehicle * GetIfValid(auto index)
Information about a rail vehicle.
Definition engine_type.h:74
Element of the RoadVehPathCache.
Definition roadveh.h:85
Information about a road vehicle.
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:753
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:231
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
T * Next() const
Get next vehicle in the chain.
static Train * From(Vehicle *v)
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:91
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
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.
VehStates vehstatus
Status.
Order current_order
The current order (+ status, like: loading).
Vehicle * Next() const
Get the next vehicle of this vehicle.
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
uint16_t cur_speed
current speed
bool IsFrontEngine() const
Check if the vehicle is a front engine.
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
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
Functions related to time tabling.
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:66
Base for the train class.
static constexpr ConsistChangeFlags CCF_TRACK
Valid changes while vehicle is driving, and possibly changing tracks.
Definition train.h:52
static constexpr ConsistChangeFlags CCF_SAVELOAD
Valid changes when loading a savegame. (Everything that is not stored in the save....
Definition train.h:57
TrainForceProceeding
Modes for ignoring signals.
Definition train.h:38
@ TFP_SIGNAL
Ignore next signal, after the signal ignore being stuck.
Definition train.h:41
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition vehicle.cpp:1777
uint8_t CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition vehicle.cpp:1477
@ Crashed
Vehicle is crashed.
@ Hidden
Vehicle is not visible.
@ Stopped
Vehicle is stopped by the player.
static const int32_t INVALID_COORD
Sentinel for an invalid coordinate.
Functions related to vehicles.
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.
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.
PoolID< uint32_t, struct VehicleIDTag, 0xFF000, 0xFFFFF > VehicleID
The type all our vehicle IDs have.
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 uint VEHICLE_LENGTH
The length of a vehicle in tile units.