OpenTTD Source  20241120-master-g6d3adc6169
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 
225 static void CheckValidVehicles()
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 
253 extern uint8_t _age_cargo_skip_counter; // From misc_sl.cpp
254 
256 void 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. */
288  assert(OrderList::CanAllocateItem());
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 */
293  if (IsSavegameVersionBefore(SLV_5, 2)) {
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. */
322  assert(OrderList::CanAllocateItem());
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 
415 void 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 
446  RoadVehUpdateCache(rv);
448  rv->CargoChanged();
449  }
450  }
451  break;
452  }
453 
454  case VEH_SHIP:
455  Ship::From(v)->UpdateCache();
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:
491  if (Aircraft::From(v)->IsNormalAircraft()) {
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 
544 bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // From train_cmd.cpp
546 void 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 
633 static uint8_t _cargo_periods;
634 static uint16_t _cargo_source;
635 static uint32_t _cargo_source_xy;
636 static uint16_t _cargo_count;
637 static uint16_t _cargo_paid_for;
638 static Money _cargo_feeder_share;
639 
640 class SlVehicleCommon : public DefaultSaveLoadHandler<SlVehicleCommon, Vehicle> {
641 public:
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),
723  SLE_CONDVAR(Vehicle, economy_age, SLE_INT32, SLV_VEHICLE_ECONOMY_AGE, 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),
756  SLE_CONDVAR(Vehicle, random_bits, SLE_UINT16, SLV_EXTEND_VEHICLE_RANDOM, SL_MAX_VERSION),
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 
790 class SlVehicleTrain : public DefaultSaveLoadHandler<SlVehicleTrain, Vehicle> {
791 public:
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 
825 class SlVehicleRoadVehPath : public VectorSaveLoadHandler<SlVehicleRoadVehPath, RoadVehicle, RoadVehPathElement> {
826 public:
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 
836 class SlVehicleRoadVeh : public DefaultSaveLoadHandler<SlVehicleRoadVeh, Vehicle> {
837 public:
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 
899 class SlVehicleShipPath : public VectorSaveLoadHandler<SlVehicleShipPath, Ship, ShipPathElement> {
900 public:
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 
909 class SlVehicleShip : public DefaultSaveLoadHandler<SlVehicleShip, Vehicle> {
910 public:
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 
947 class SlVehicleAircraft : public DefaultSaveLoadHandler<SlVehicleAircraft, Vehicle> {
948 public:
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 
987 class SlVehicleEffect : public DefaultSaveLoadHandler<SlVehicleEffect, Vehicle> {
988 public:
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 
1032 class SlVehicleDisaster : public DefaultSaveLoadHandler<SlVehicleDisaster, Vehicle> {
1033 public:
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),
1066  SLE_CONDVAR(DisasterVehicle, flags, SLE_UINT8, SLV_194, 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 
1090 const 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;
1124  VehicleType vtype = (VehicleType)SlReadByte();
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' */
1146  if (IsSavegameVersionBefore(SLV_5) && v->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 
1172 static const VEHSChunkHandler VEHS;
1173 static const ChunkHandlerRef veh_chunk_handlers[] = {
1174  VEHS,
1175 };
1176 
1177 extern 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
constexpr debug_inline 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.
constexpr static debug_inline 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:579
SaveLoadTable GetDescription() const override
Definition: saveload.h:581
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.
Definition: saveload.cpp:3293
std::vector< RoadVehPathElement > & GetVector(RoadVehicle *rv) const override
Get instance of vector to load/save.
Definition: vehicle_sl.cpp:833
std::vector< ShipPathElement > & GetVector(Ship *s) const override
Get instance of vector to load/save.
Definition: vehicle_sl.cpp:906
Default handler for saving/loading a vector to/from disk.
Definition: saveload.h:1341
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.
@ 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 EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:206
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
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.
Definition: rail_cmd.cpp:2916
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.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:658
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:351
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
Definition: saveload.cpp:1893
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Definition: saveload.cpp:1755
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.
Definition: saveload.cpp:1702
Functions/types related to saving and loading games.
@ SLF_ALLOW_CONTROL
Allow control codes in the strings.
Definition: saveload.h:686
#define SLEG_CONDVAR(name, variable, type, from, to)
Storage of a global variable in some savegame versions.
Definition: saveload.h:1086
#define SLEG_CONDVECTOR(name, variable, type, from, to)
Storage of a global vector of SL_VAR elements in some savegame versions.
Definition: saveload.h:1146
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition: saveload.h:507
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition: saveload.h:510
#define SLE_SAVEBYTE(base, variable)
Only write byte during saving; never read it during loading.
Definition: saveload.h:1060
#define SLE_REF(base, variable, type)
Storage of a reference in every version of a savegame.
Definition: saveload.h:1004
#define SLE_CONDREFLIST(base, variable, type, from, to)
Storage of a list of SL_REF elements in some savegame versions.
Definition: saveload.h:949
#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:895
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition: saveload.h:516
#define SLEG_STRUCT(name, handler)
Storage of a structs in every savegame version.
Definition: saveload.h:1194
#define SLE_CONDSSTR(base, variable, type, from, to)
Storage of a std::string in some savegame versions.
Definition: saveload.h:928
#define SLE_CONDVAR(base, variable, type, from, to)
Storage of a variable in some savegame versions.
Definition: saveload.h:863
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition: saveload.h:1239
@ 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:397
@ 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:884
@ REF_VEHICLE_OLD
Load/save an old-style reference to a vehicle (for pre-4.4 savegames).
Definition: saveload.h:603
@ REF_CARGO_PACKET
Load/save a reference to a cargo packet.
Definition: saveload.h:606
@ REF_ORDER
Load/save a reference to an order.
Definition: saveload.h:599
@ REF_ORDERLIST
Load/save a reference to an orderlist.
Definition: saveload.h:607
@ REF_VEHICLE
Load/save a reference to a vehicle.
Definition: saveload.h:600
#define SLEG_CONDSTRUCTLIST(name, handler, from, to)
Storage of a list of structs in some savegame versions.
Definition: saveload.h:1155
#define SLE_VAR(base, variable, type)
Storage of a variable in every version of a savegame.
Definition: saveload.h:987
#define SLE_CONDVARNAME(base, variable, name, type, from, to)
Storage of a variable in some savegame versions.
Definition: saveload.h:874
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
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
Container for cargo from the same location and time.
Definition: cargopacket.h:40
Handlers and description of chunk.
Definition: saveload.h:461
CompanySettings settings
settings specific for each company
Definition: company_base.h:122
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.
Definition: engine_base.h:186
VehicleSettings vehicle
options for vehicles
Position information of a vehicle after it moved.
Definition: vehicle_func.h:77
int y
x and y position of the vehicle after moving
Definition: vehicle_func.h:78
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.
Definition: vehicle_base.h:200
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.
Definition: pool_type.hpp:360
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
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:713
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 * 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.
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 * GetIfValid(size_t index)
Returns vehicle if the index is a valid index for this vehicle type.
Station data structure.
Definition: station_base.h:439
'Train' is either a loco or a wagon.
Definition: train.h:89
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
Definition: train_cmd.cpp:110
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.
Definition: vehicle_base.h:178
Vehicle data structure.
Definition: vehicle_base.h:244
CargoPayment * cargo_payment
The cargo payment we're currently in.
Definition: vehicle_base.h:277
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:323
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:341
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
Definition: vehicle_base.h:338
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:366
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:632
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:945
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:356
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
Definition: vehicle_base.h:315
uint16_t cur_speed
current speed
Definition: vehicle_base.h:328
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
Definition: vehicle_base.h:368
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:337
Vehicle * next_shared
pointer to the next vehicle that shares the order
Definition: vehicle_base.h:252
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.
Definition: vehicle_base.h:34
@ VS_HIDDEN
Vehicle is not visible.
Definition: vehicle_base.h:33
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
static const int32_t INVALID_COORD
Sentinel for an invalid coordinate.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition: vehicle_func.h:91
void AfterLoadVehiclesPhase1(bool part_of_load)
Called after load for phase 1 of vehicle initialisation.
Definition: vehicle_sl.cpp:256
void FixupTrainLengths()
Fixup old train spacing.
Definition: vehicle_sl.cpp:549
void UpdateOldAircraft()
need to be called to load aircraft from old version
Definition: vehicle_sl.cpp:165
void ReverseTrainDirection(Train *v)
Turn a train around.
Definition: train_cmd.cpp:1967
void ConvertOldMultiheadToNew()
Converts all trains to the new subtype format introduced in savegame 16.2 It also links multiheaded e...
Definition: vehicle_sl.cpp:113
bool TrainController(Train *v, Vehicle *nomove, bool reverse=true)
Move a vehicle chain one movement stop forwards.
Definition: train_cmd.cpp:3278
void ConnectMultiheadedTrains()
Link front and rear multiheaded engines to each other This is done when loading a savegame.
Definition: vehicle_sl.cpp:35
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.
Definition: vehicle_sl.cpp:415
void ReverseTrainSwapVeh(Train *v, int l, int r)
Swap vehicles l and r in consist v, and reverse their direction.
Definition: train_cmd.cpp:1630
static void CheckValidVehicles()
Check all vehicles to ensure their engine type is valid for the currently loaded NewGRFs (that includ...
Definition: vehicle_sl.cpp:225
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.
Definition: vehicle_type.h:79
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
@ VEH_INVALID
Non-existing type of vehicle.
Definition: vehicle_type.h:35
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_DISASTER
Disaster vehicle type.
Definition: vehicle_type.h:32
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_EFFECT
Effect vehicle type (smoke, explosions, sparks, bubbles)
Definition: vehicle_type.h:31
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:54
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.
Definition: vehicle_type.h:69