4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file vehicle_sl.cpp Code handling saving and loading of vehicles */
12 #include "../stdafx.h"
13 #include "../vehicle_func.h"
15 #include "../roadveh.h"
17 #include "../aircraft.h"
18 #include "../station_base.h"
19 #include "../effectvehicle_base.h"
20 #include "../company_base.h"
21 #include "../company_func.h"
22 #include "../disaster_vehicle.h"
28 #include "../safeguards.h"
31 * Link front and rear multiheaded engines to each other
32 * This is done when loading a savegame
34 void ConnectMultiheadedTrains()
39 v
->other_multiheaded_part
= NULL
;
43 if (v
->IsFrontEngine() || v
->IsFreeWagon()) {
44 /* Two ways to associate multiheaded parts to each other:
45 * sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
46 * bracket-matching: Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
48 * Note: Old savegames might contain chains which do not comply with these rules, e.g.
49 * - the front and read parts have invalid orders
50 * - different engine types might be combined
51 * - there might be different amounts of front and rear parts.
53 * Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
54 * This is why two matching strategies are needed.
57 bool sequential_matching
= v
->IsFrontEngine();
59 for (Train
*u
= v
; u
!= NULL
; u
= u
->GetNextVehicle()) {
60 if (u
->other_multiheaded_part
!= NULL
) continue; // we already linked this one
62 if (u
->IsMultiheaded()) {
64 /* we got a rear car without a front car. We will convert it to a front one */
69 /* Find a matching back part */
70 EngineID eid
= u
->engine_type
;
72 if (sequential_matching
) {
73 for (w
= u
->GetNextVehicle(); w
!= NULL
; w
= w
->GetNextVehicle()) {
74 if (w
->engine_type
!= eid
|| w
->other_multiheaded_part
!= NULL
|| !w
->IsMultiheaded()) continue;
76 /* we found a car to partner with this engine. Now we will make sure it face the right way */
85 for (w
= u
->GetNextVehicle(); w
!= NULL
; w
= w
->GetNextVehicle()) {
86 if (w
->engine_type
!= eid
|| w
->other_multiheaded_part
!= NULL
|| !w
->IsMultiheaded()) continue;
91 if (stack_pos
== 0) break;
98 w
->other_multiheaded_part
= u
;
99 u
->other_multiheaded_part
= w
;
101 /* we got a front car and no rear cars. We will fake this one for forget that it should have been multiheaded */
102 u
->ClearMultiheaded();
111 * Converts all trains to the new subtype format introduced in savegame 16.2
112 * It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found
114 void ConvertOldMultiheadToNew()
117 FOR_ALL_TRAINS(t
) SetBit(t
->subtype
, 7); // indicates that it's the old format and needs to be converted in the next loop
120 if (HasBit(t
->subtype
, 7) && ((t
->subtype
& ~0x80) == 0 || (t
->subtype
& ~0x80) == 4)) {
121 for (Train
*u
= t
; u
!= NULL
; u
= u
->Next()) {
122 const RailVehicleInfo
*rvi
= RailVehInfo(u
->engine_type
);
124 ClrBit(u
->subtype
, 7);
125 switch (u
->subtype
) {
126 case 0: // TS_Front_Engine
127 if (rvi
->railveh_type
== RAILVEH_MULTIHEAD
) u
->SetMultiheaded();
132 case 1: // TS_Artic_Part
134 u
->SetArticulatedPart();
137 case 2: // TS_Not_First
139 if (rvi
->railveh_type
== RAILVEH_WAGON
) {
144 if (rvi
->railveh_type
== RAILVEH_MULTIHEAD
&& rvi
->image_index
== u
->spritenum
- 1) {
145 /* rear end of a multiheaded engine */
149 if (rvi
->railveh_type
== RAILVEH_MULTIHEAD
) u
->SetMultiheaded();
153 case 4: // TS_Free_Car
158 default: SlErrorCorrupt("Invalid train subtype");
166 /** need to be called to load aircraft from old version */
167 void UpdateOldAircraft()
169 /* set airport_flags to 0 for all airports just to be sure */
171 FOR_ALL_STATIONS(st
) {
172 st
->airport
.flags
= 0; // reset airport
176 FOR_ALL_AIRCRAFT(a
) {
177 /* airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor)
179 if (a
->IsNormalAircraft()) {
180 /* airplane in terminal stopped doesn't hurt anyone, so goto next */
181 if ((a
->vehstatus
& VS_STOPPED
) && a
->state
== 0) {
186 AircraftLeaveHangar(a
, a
->direction
); // make airplane visible if it was in a depot for example
187 a
->vehstatus
&= ~VS_STOPPED
; // make airplane moving
188 UpdateAircraftCache(a
);
189 a
->cur_speed
= a
->vcache
.cached_max_speed
; // so aircraft don't have zero speed while in air
190 if (!a
->current_order
.IsType(OT_GOTO_STATION
) && !a
->current_order
.IsType(OT_GOTO_DEPOT
)) {
191 /* reset current order so aircraft doesn't have invalid "station-only" order */
192 a
->current_order
.MakeDummy();
195 AircraftNextAirportPos_and_Order(a
); // move it to the entry point of the airport
196 GetNewVehiclePosResult gp
= GetNewVehiclePos(a
);
197 a
->tile
= 0; // aircraft in air is tile=0
199 /* correct speed of helicopter-rotors */
200 if (a
->subtype
== AIR_HELICOPTER
) a
->Next()->Next()->cur_speed
= 32;
202 /* set new position x,y,z */
203 GetAircraftFlightLevelBounds(a
, &a
->z_pos
, NULL
);
204 SetAircraftPosition(a
, gp
.x
, gp
.y
, GetAircraftFlightLevel(a
));
210 * Check all vehicles to ensure their engine type is valid
211 * for the currently loaded NewGRFs (that includes none...)
212 * This only makes a difference if NewGRFs are missing, otherwise
213 * all vehicles will be valid. This does not make such a game
214 * playable, it only prevents crash.
216 static void CheckValidVehicles()
218 size_t total_engines
= Engine::GetPoolSize();
219 EngineID first_engine
[4] = { INVALID_ENGINE
, INVALID_ENGINE
, INVALID_ENGINE
, INVALID_ENGINE
};
222 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_TRAIN
) { first_engine
[VEH_TRAIN
] = e
->index
; break; }
223 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_ROAD
) { first_engine
[VEH_ROAD
] = e
->index
; break; }
224 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_SHIP
) { first_engine
[VEH_SHIP
] = e
->index
; break; }
225 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_AIRCRAFT
) { first_engine
[VEH_AIRCRAFT
] = e
->index
; break; }
228 FOR_ALL_VEHICLES(v
) {
229 /* Test if engine types match */
235 if (v
->engine_type
>= total_engines
|| v
->type
!= v
->GetEngine()->type
) {
236 v
->engine_type
= first_engine
[v
->type
];
246 extern byte _age_cargo_skip_counter
; // From misc_sl.cpp
248 /** Called after load to update coordinates */
249 void AfterLoadVehicles(bool part_of_load
)
253 FOR_ALL_VEHICLES(v
) {
254 /* Reinstate the previous pointer */
255 if (v
->Next() != NULL
) v
->Next()->previous
= v
;
256 if (v
->NextShared() != NULL
) v
->NextShared()->previous_shared
= v
;
258 if (part_of_load
) v
->fill_percent_te_id
= INVALID_TE_ID
;
260 if (v
->IsGroundVehicle()) v
->GetGroundVehicleCache()->first_engine
= INVALID_ENGINE
;
263 /* AfterLoadVehicles may also be called in case of NewGRF reload, in this
264 * case we may not convert orders again. */
266 /* Create shared vehicle chain for very old games (pre 5,2) and create
267 * OrderList from shared vehicle chains. For this to work correctly, the
268 * following conditions must be fulfilled:
269 * a) both next_shared and previous_shared are not set for pre 5,2 games
270 * b) both next_shared and previous_shared are set for later games
272 std::map
<Order
*, OrderList
*> mapping
;
274 FOR_ALL_VEHICLES(v
) {
275 if (v
->orders
.old
!= NULL
) {
276 if (IsSavegameVersionBefore(105)) { // Pre-105 didn't save an OrderList
277 if (mapping
[v
->orders
.old
] == NULL
) {
278 /* This adds the whole shared vehicle chain for case b */
280 /* Creating an OrderList here is safe because the number of vehicles
281 * allowed in these savegames matches the number of OrderLists. As
282 * such each vehicle can get an OrderList and it will (still) fit. */
283 assert(OrderList::CanAllocateItem());
284 v
->orders
.list
= mapping
[v
->orders
.old
] = new OrderList(v
->orders
.old
, v
);
286 v
->orders
.list
= mapping
[v
->orders
.old
];
287 /* For old games (case a) we must create the shared vehicle chain */
288 if (IsSavegameVersionBefore(5, 2)) {
289 v
->AddToShared(v
->orders
.list
->GetFirstSharedVehicle());
292 } else { // OrderList was saved as such, only recalculate not saved values
293 if (v
->PreviousShared() == NULL
) {
294 v
->orders
.list
->Initialize(v
->orders
.list
->first
, v
);
301 FOR_ALL_VEHICLES(v
) {
302 /* Fill the first pointers */
303 if (v
->Previous() == NULL
) {
304 for (Vehicle
*u
= v
; u
!= NULL
; u
= u
->Next()) {
311 if (IsSavegameVersionBefore(105)) {
312 /* Before 105 there was no order for shared orders, thus it messed up horribly */
313 FOR_ALL_VEHICLES(v
) {
314 if (v
->First() != v
|| v
->orders
.list
!= NULL
|| v
->previous_shared
!= NULL
|| v
->next_shared
== NULL
) continue;
316 /* As above, allocating OrderList here is safe. */
317 assert(OrderList::CanAllocateItem());
318 v
->orders
.list
= new OrderList(NULL
, v
);
319 for (Vehicle
*u
= v
; u
!= NULL
; u
= u
->next_shared
) {
320 u
->orders
.list
= v
->orders
.list
;
325 if (IsSavegameVersionBefore(157)) {
326 /* The road vehicle subtype was converted to a flag. */
328 FOR_ALL_ROADVEHICLES(rv
) {
329 if (rv
->subtype
== 0) {
330 /* The road vehicle is at the front. */
331 rv
->SetFrontEngine();
332 } else if (rv
->subtype
== 1) {
333 /* The road vehicle is an articulated part. */
335 rv
->SetArticulatedPart();
337 SlErrorCorrupt("Invalid road vehicle subtype");
342 if (IsSavegameVersionBefore(160)) {
343 /* In some old savegames there might be some "crap" stored. */
344 FOR_ALL_VEHICLES(v
) {
345 if (!v
->IsPrimaryVehicle() && v
->type
!= VEH_DISASTER
) {
346 v
->current_order
.Free();
352 if (IsSavegameVersionBefore(162)) {
353 /* Set the vehicle-local cargo age counter from the old global counter. */
354 FOR_ALL_VEHICLES(v
) {
355 v
->cargo_age_counter
= _age_cargo_skip_counter
;
359 if (IsSavegameVersionBefore(180)) {
360 /* Set service interval flags */
361 FOR_ALL_VEHICLES(v
) {
362 if (!v
->IsPrimaryVehicle()) continue;
364 const Company
*c
= Company::Get(v
->owner
);
365 int interval
= CompanyServiceInterval(c
, v
->type
);
367 v
->SetServiceIntervalIsCustom(v
->GetServiceInterval() != interval
);
368 v
->SetServiceIntervalIsPercent(c
->settings
.vehicle
.servint_ispercent
);
373 CheckValidVehicles();
375 FOR_ALL_VEHICLES(v
) {
376 assert(v
->first
!= NULL
);
380 Train
*t
= Train::From(v
);
381 if (t
->IsFrontEngine() || t
->IsFreeWagon()) {
382 t
->gcache
.last_speed
= t
->cur_speed
; // update displayed train speed
383 t
->ConsistChanged(CCF_SAVELOAD
);
389 RoadVehicle
*rv
= RoadVehicle::From(v
);
390 if (rv
->IsFrontEngine()) {
391 rv
->gcache
.last_speed
= rv
->cur_speed
; // update displayed road vehicle speed
392 RoadVehUpdateCache(rv
);
393 if (_settings_game
.vehicle
.roadveh_acceleration_model
!= AM_ORIGINAL
) {
401 Ship::From(v
)->UpdateCache();
408 /* Stop non-front engines */
409 if (part_of_load
&& IsSavegameVersionBefore(112)) {
410 FOR_ALL_VEHICLES(v
) {
411 if (v
->type
== VEH_TRAIN
) {
412 Train
*t
= Train::From(v
);
413 if (!t
->IsFrontEngine()) {
415 t
->vehstatus
|= VS_STOPPED
;
416 /* cur_speed is now relevant for non-front parts - nonzero breaks
417 * moving-wagons-inside-depot- and autoreplace- code */
421 /* trains weren't stopping gradually in old OTTD versions (and TTO/TTD)
422 * other vehicle types didn't have zero speed while stopped (even in 'recent' OTTD versions) */
423 if ((v
->vehstatus
& VS_STOPPED
) && (v
->type
!= VEH_TRAIN
|| IsSavegameVersionBefore(2, 1))) {
429 FOR_ALL_VEHICLES(v
) {
432 RoadVehicle
*rv
= RoadVehicle::From(v
);
433 rv
->roadtype
= HasBit(EngInfo(v
->First()->engine_type
)->misc_flags
, EF_ROAD_TRAM
) ? ROADTYPE_TRAM
: ROADTYPE_ROAD
;
434 rv
->compatible_roadtypes
= RoadTypeToRoadTypes(rv
->roadtype
);
440 v
->GetImage(v
->direction
, EIT_ON_MAP
, &v
->sprite_seq
);
441 v
->UpdateSpriteSeqBound();
445 if (Aircraft::From(v
)->IsNormalAircraft()) {
446 v
->GetImage(v
->direction
, EIT_ON_MAP
, &v
->sprite_seq
);
447 v
->UpdateSpriteSeqBound();
449 /* The plane's shadow will have the same image as the plane, but no colour */
450 Vehicle
*shadow
= v
->Next();
451 shadow
->sprite_seq
.CopyWithoutPalette(v
->sprite_seq
);
452 shadow
->sprite_seq_bounds
= v
->sprite_seq_bounds
;
454 /* In the case of a helicopter we will update the rotor sprites */
455 if (v
->subtype
== AIR_HELICOPTER
) {
456 Vehicle
*rotor
= shadow
->Next();
457 GetRotorImage(Aircraft::From(v
), EIT_ON_MAP
, &rotor
->sprite_seq
);
458 rotor
->UpdateSpriteSeqBound();
461 UpdateAircraftCache(Aircraft::From(v
), true);
467 v
->UpdateDeltaXY(v
->direction
);
468 v
->coord
.left
= INVALID_COORD
;
470 v
->UpdateViewport(false);
474 bool TrainController(Train
*v
, Vehicle
*nomove
, bool reverse
= true); // From train_cmd.cpp
475 void ReverseTrainDirection(Train
*v
);
476 void ReverseTrainSwapVeh(Train
*v
, int l
, int r
);
478 /** Fixup old train spacing. */
479 void FixupTrainLengths()
481 /* Vehicle center was moved from 4 units behind the front to half the length
482 * behind the front. Move vehicles so they end up on the same spot. */
484 FOR_ALL_VEHICLES(v
) {
485 if (v
->type
== VEH_TRAIN
&& v
->IsPrimaryVehicle()) {
486 /* The vehicle center is now more to the front depending on vehicle length,
487 * so we need to move all vehicles forward to cover the difference to the
488 * old center, otherwise wagon spacing in trains would be broken upon load. */
489 for (Train
*u
= Train::From(v
); u
!= NULL
; u
= u
->Next()) {
490 if (u
->track
== TRACK_BIT_DEPOT
|| (u
->vehstatus
& VS_CRASHED
)) continue;
492 Train
*next
= u
->Next();
494 /* Try to pull the vehicle half its length forward. */
495 int diff
= (VEHICLE_LENGTH
- u
->gcache
.cached_veh_length
) / 2;
497 for (done
= 0; done
< diff
; done
++) {
498 if (!TrainController(u
, next
, false)) break;
501 if (next
!= NULL
&& done
< diff
&& u
->IsFrontEngine()) {
502 /* Pulling the front vehicle forwards failed, we either encountered a dead-end
503 * or a red signal. To fix this, we try to move the whole train the required
504 * space backwards and re-do the fix up of the front vehicle. */
506 /* Ignore any signals when backtracking. */
507 TrainForceProceeding old_tfp
= u
->force_proceed
;
508 u
->force_proceed
= TFP_SIGNAL
;
510 /* Swap start<>end, start+1<>end-1, ... */
511 int r
= CountVehiclesInChain(u
) - 1; // number of vehicles - 1
513 do ReverseTrainSwapVeh(u
, l
++, r
--); while (l
<= r
);
515 /* We moved the first vehicle which is now the last. Move it back to the
516 * original position as we will fix up the last vehicle later in the loop. */
517 for (int i
= 0; i
< done
; i
++) TrainController(u
->Last(), NULL
);
519 /* Move the train backwards to get space for the first vehicle. As the stopping
520 * distance from a line end is rounded up, move the train one unit more to cater
521 * for front vehicles with odd lengths. */
523 for (moved
= 0; moved
< diff
+ 1; moved
++) {
524 if (!TrainController(u
, NULL
, false)) break;
527 /* Swap start<>end, start+1<>end-1, ... again. */
528 r
= CountVehiclesInChain(u
) - 1; // number of vehicles - 1
530 do ReverseTrainSwapVeh(u
, l
++, r
--); while (l
<= r
);
532 u
->force_proceed
= old_tfp
;
534 /* Tracks are too short to fix the train length. The player has to fix the
535 * train in a depot. Bail out so we don't damage the vehicle chain any more. */
536 if (moved
< diff
+ 1) break;
538 /* Re-do the correction for the first vehicle. */
539 for (done
= 0; done
< diff
; done
++) TrainController(u
, next
, false);
541 /* We moved one unit more backwards than needed for even-length front vehicles,
542 * try to move that unit forward again. We don't care if this step fails. */
543 TrainController(u
, NULL
, false);
546 /* If the next wagon is still in a depot, check if it shouldn't be outside already. */
547 if (next
!= NULL
&& next
->track
== TRACK_BIT_DEPOT
) {
548 int d
= TicksToLeaveDepot(u
);
550 /* Next vehicle should have left the depot already, show it and pull forward. */
551 next
->vehstatus
&= ~VS_HIDDEN
;
552 next
->track
= TrackToTrackBits(GetRailDepotTrack(next
->tile
));
553 for (int i
= 0; i
>= d
; i
--) TrainController(next
, NULL
);
558 /* Update all cached properties after moving the vehicle chain around. */
559 Train::From(v
)->ConsistChanged(CCF_TRACK
);
564 static uint8 _cargo_days
;
565 static uint16 _cargo_source
;
566 static uint32 _cargo_source_xy
;
567 static uint16 _cargo_count
;
568 static uint16 _cargo_paid_for
;
569 static Money _cargo_feeder_share
;
570 static uint32 _cargo_loaded_at_xy
;
573 * Make it possible to make the saveload tables "friends" of other classes.
574 * @param vt the vehicle type. Can be VEH_END for the common vehicle description data
575 * @return the saveload description
577 const SaveLoad
*GetVehicleDescription(VehicleType vt
)
579 /** Save and load of vehicles */
580 static const SaveLoad _common_veh_desc
[] = {
581 SLE_VAR(Vehicle
, subtype
, SLE_UINT8
),
583 SLE_REF(Vehicle
, next
, REF_VEHICLE_OLD
),
584 SLE_CONDVAR(Vehicle
, name
, SLE_NAME
, 0, 83),
585 SLE_CONDSTR(Vehicle
, name
, SLE_STR
| SLF_ALLOW_CONTROL
, 0, 84, SL_MAX_VERSION
),
586 SLE_CONDVAR(Vehicle
, unitnumber
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 7),
587 SLE_CONDVAR(Vehicle
, unitnumber
, SLE_UINT16
, 8, SL_MAX_VERSION
),
588 SLE_VAR(Vehicle
, owner
, SLE_UINT8
),
589 SLE_CONDVAR(Vehicle
, tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
590 SLE_CONDVAR(Vehicle
, tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
591 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
592 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
594 SLE_CONDVAR(Vehicle
, x_pos
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
595 SLE_CONDVAR(Vehicle
, x_pos
, SLE_UINT32
, 6, SL_MAX_VERSION
),
596 SLE_CONDVAR(Vehicle
, y_pos
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
597 SLE_CONDVAR(Vehicle
, y_pos
, SLE_UINT32
, 6, SL_MAX_VERSION
),
598 SLE_CONDVAR(Vehicle
, z_pos
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 163),
599 SLE_CONDVAR(Vehicle
, z_pos
, SLE_INT32
, 164, SL_MAX_VERSION
),
600 SLE_VAR(Vehicle
, direction
, SLE_UINT8
),
602 SLE_CONDNULL(2, 0, 57),
603 SLE_VAR(Vehicle
, spritenum
, SLE_UINT8
),
604 SLE_CONDNULL(5, 0, 57),
605 SLE_VAR(Vehicle
, engine_type
, SLE_UINT16
),
607 SLE_CONDNULL(2, 0, 151),
608 SLE_VAR(Vehicle
, cur_speed
, SLE_UINT16
),
609 SLE_VAR(Vehicle
, subspeed
, SLE_UINT8
),
610 SLE_VAR(Vehicle
, acceleration
, SLE_UINT8
),
611 SLE_VAR(Vehicle
, progress
, SLE_UINT8
),
613 SLE_VAR(Vehicle
, vehstatus
, SLE_UINT8
),
614 SLE_CONDVAR(Vehicle
, last_station_visited
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
615 SLE_CONDVAR(Vehicle
, last_station_visited
, SLE_UINT16
, 5, SL_MAX_VERSION
),
616 SLE_CONDVAR(Vehicle
, last_loading_station
, SLE_UINT16
, 182, SL_MAX_VERSION
),
618 SLE_VAR(Vehicle
, cargo_type
, SLE_UINT8
),
619 SLE_CONDVAR(Vehicle
, cargo_subtype
, SLE_UINT8
, 35, SL_MAX_VERSION
),
620 SLEG_CONDVAR( _cargo_days
, SLE_UINT8
, 0, 67),
621 SLEG_CONDVAR( _cargo_source
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 6),
622 SLEG_CONDVAR( _cargo_source
, SLE_UINT16
, 7, 67),
623 SLEG_CONDVAR( _cargo_source_xy
, SLE_UINT32
, 44, 67),
624 SLE_VAR(Vehicle
, cargo_cap
, SLE_UINT16
),
625 SLE_CONDVAR(Vehicle
, refit_cap
, SLE_UINT16
, 182, SL_MAX_VERSION
),
626 SLEG_CONDVAR( _cargo_count
, SLE_UINT16
, 0, 67),
627 SLE_CONDDEQ(Vehicle
, cargo
.packets
, REF_CARGO_PACKET
, 68, SL_MAX_VERSION
),
628 SLE_CONDARR(Vehicle
, cargo
.action_counts
, SLE_UINT
, VehicleCargoList::NUM_MOVE_TO_ACTION
, 181, SL_MAX_VERSION
),
629 SLE_CONDVAR(Vehicle
, cargo_age_counter
, SLE_UINT16
, 162, SL_MAX_VERSION
),
631 SLE_CONDNULL(1, SL_PATCH_PACK_1_8
, SL_PATCH_PACK_1_19
- 1), // trip_occupancy
633 SLE_VAR(Vehicle
, day_counter
, SLE_UINT8
),
634 SLE_VAR(Vehicle
, tick_counter
, SLE_UINT8
),
636 SLE_CONDVAR(Vehicle
, running_ticks
, SLE_FILE_U8
| SLE_VAR_U16
, 88, SL_PATCH_PACK_1_8
- 1),
637 SLE_CONDVAR(Vehicle
, running_ticks
, SLE_UINT16
, SL_PATCH_PACK_1_8
, SL_MAX_VERSION
),
639 SLE_VAR(Vehicle
, cur_implicit_order_index
, SLE_UINT8
),
640 SLE_CONDVAR(Vehicle
, cur_real_order_index
, SLE_UINT8
, 158, SL_MAX_VERSION
),
641 /* num_orders is now part of OrderList and is not saved but counted */
642 SLE_CONDNULL(1, 0, 104),
644 /* This next line is for version 4 and prior compatibility.. it temporarily reads
645 type and flags (which were both 4 bits) into type. Later on this is
646 converted correctly */
647 SLE_CONDVAR(Vehicle
, current_order
.type
, SLE_UINT8
, 0, 4),
648 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
650 /* Orders for version 5 and on */
651 SLE_CONDVAR(Vehicle
, current_order
.type
, SLE_UINT8
, 5, SL_MAX_VERSION
),
652 SLE_CONDVAR(Vehicle
, current_order
.flags
, SLE_UINT8
, 5, SL_MAX_VERSION
),
653 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_UINT16
, 5, SL_MAX_VERSION
),
655 /* Refit in current order */
656 SLE_CONDVAR(Vehicle
, current_order
.refit_cargo
, SLE_UINT8
, 36, SL_MAX_VERSION
),
657 SLE_CONDNULL(1, 36, 181), // refit_subtype
659 /* Timetable in current order */
660 SLE_CONDVAR(Vehicle
, current_order
.wait_time
, SLE_UINT16
, 67, SL_MAX_VERSION
),
661 SLE_CONDVAR(Vehicle
, current_order
.travel_time
, SLE_UINT16
, 67, SL_MAX_VERSION
),
662 SLE_CONDVAR(Vehicle
, current_order
.max_speed
, SLE_UINT16
, 174, SL_MAX_VERSION
),
663 SLE_CONDVAR(Vehicle
, timetable_start
, SLE_INT32
, 129, SL_MAX_VERSION
),
665 SLE_CONDREF(Vehicle
, orders
, REF_ORDER
, 0, 104),
666 SLE_CONDREF(Vehicle
, orders
, REF_ORDERLIST
, 105, SL_MAX_VERSION
),
668 SLE_CONDVAR(Vehicle
, age
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
669 SLE_CONDVAR(Vehicle
, age
, SLE_INT32
, 31, SL_MAX_VERSION
),
670 SLE_CONDVAR(Vehicle
, max_age
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
671 SLE_CONDVAR(Vehicle
, max_age
, SLE_INT32
, 31, SL_MAX_VERSION
),
672 SLE_CONDVAR(Vehicle
, date_of_last_service
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
673 SLE_CONDVAR(Vehicle
, date_of_last_service
, SLE_INT32
, 31, SL_MAX_VERSION
),
674 SLE_CONDVAR(Vehicle
, service_interval
, SLE_UINT16
, 0, 30),
675 SLE_CONDVAR(Vehicle
, service_interval
, SLE_FILE_U32
| SLE_VAR_U16
, 31, 179),
676 SLE_CONDVAR(Vehicle
, service_interval
, SLE_UINT16
, 180, SL_MAX_VERSION
),
677 SLE_VAR(Vehicle
, reliability
, SLE_UINT16
),
678 SLE_VAR(Vehicle
, reliability_spd_dec
, SLE_UINT16
),
679 SLE_VAR(Vehicle
, breakdown_ctr
, SLE_UINT8
),
680 SLE_VAR(Vehicle
, breakdown_delay
, SLE_UINT8
),
681 SLE_VAR(Vehicle
, breakdowns_since_last_service
, SLE_UINT8
),
682 SLE_VAR(Vehicle
, breakdown_chance
, SLE_UINT8
),
683 SLE_CONDVAR(Vehicle
, build_year
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 30),
684 SLE_CONDVAR(Vehicle
, build_year
, SLE_INT32
, 31, SL_MAX_VERSION
),
686 SLE_VAR(Vehicle
, load_unload_ticks
, SLE_UINT16
),
687 SLEG_CONDVAR( _cargo_paid_for
, SLE_UINT16
, 45, SL_MAX_VERSION
),
688 SLE_CONDVAR(Vehicle
, vehicle_flags
, SLE_FILE_U8
| SLE_VAR_U16
, 40, 179),
689 SLE_CONDVAR(Vehicle
, vehicle_flags
, SLE_UINT16
, 180, SL_MAX_VERSION
),
691 SLE_CONDVAR(Vehicle
, profit_this_year
, SLE_FILE_I32
| SLE_VAR_I64
, 0, 64),
692 SLE_CONDVAR(Vehicle
, profit_this_year
, SLE_INT64
, 65, SL_MAX_VERSION
),
693 SLE_CONDVAR(Vehicle
, profit_last_year
, SLE_FILE_I32
| SLE_VAR_I64
, 0, 64),
694 SLE_CONDVAR(Vehicle
, profit_last_year
, SLE_INT64
, 65, SL_MAX_VERSION
),
695 SLE_CONDVAR(Vehicle
, profit_lifetime
, SLE_INT64
, SL_PATCH_PACK_1_14
, SL_MAX_VERSION
),
696 SLEG_CONDVAR( _cargo_feeder_share
, SLE_FILE_I32
| SLE_VAR_I64
, 51, 64),
697 SLEG_CONDVAR( _cargo_feeder_share
, SLE_INT64
, 65, 67),
698 SLEG_CONDVAR( _cargo_loaded_at_xy
, SLE_UINT32
, 51, 67),
699 SLE_CONDVAR(Vehicle
, value
, SLE_FILE_I32
| SLE_VAR_I64
, 0, 64),
700 SLE_CONDVAR(Vehicle
, value
, SLE_INT64
, 65, SL_MAX_VERSION
),
702 SLE_CONDVAR(Vehicle
, random_bits
, SLE_UINT8
, 2, SL_MAX_VERSION
),
703 SLE_CONDVAR(Vehicle
, waiting_triggers
, SLE_UINT8
, 2, SL_MAX_VERSION
),
705 SLE_CONDREF(Vehicle
, ahead_separation
, REF_VEHICLE
, SL_PATCH_PACK
, SL_PATCH_PACK_1_5
),
706 SLE_CONDREF(Vehicle
, behind_separation
, REF_VEHICLE
, SL_PATCH_PACK
, SL_PATCH_PACK_1_5
),
708 SLE_CONDREF(Vehicle
, next_shared
, REF_VEHICLE
, 2, SL_MAX_VERSION
),
709 SLE_CONDNULL(2, 2, 68),
710 SLE_CONDNULL(4, 69, 100),
712 SLE_CONDVAR(Vehicle
, group_id
, SLE_UINT16
, 60, SL_MAX_VERSION
),
714 SLE_CONDVAR(Vehicle
, current_order_time
, SLE_UINT32
, 67, SL_MAX_VERSION
),
715 SLE_CONDVAR(Vehicle
, current_loading_time
, SLE_UINT32
, SL_PATCH_PACK
, SL_PATCH_PACK_1_5
),
716 SLE_CONDVAR(Vehicle
, current_loading_time
, SLE_UINT32
, SL_PATCH_PACK_1_23
, SL_MAX_VERSION
),
717 SLE_CONDVAR(Vehicle
, lateness_counter
, SLE_INT32
, 67, SL_MAX_VERSION
),
719 SLE_CONDNULL(10, 2, 143), // old reserved space
721 // Trip History Arrays
722 SLE_CONDVAR(Vehicle
, trip_history
.t
[0].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
723 SLE_CONDVAR(Vehicle
, trip_history
.t
[1].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
724 SLE_CONDVAR(Vehicle
, trip_history
.t
[2].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
725 SLE_CONDVAR(Vehicle
, trip_history
.t
[3].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
726 SLE_CONDVAR(Vehicle
, trip_history
.t
[4].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
727 SLE_CONDVAR(Vehicle
, trip_history
.t
[5].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
728 SLE_CONDVAR(Vehicle
, trip_history
.t
[6].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
729 SLE_CONDVAR(Vehicle
, trip_history
.t
[7].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
730 SLE_CONDVAR(Vehicle
, trip_history
.t
[8].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
731 SLE_CONDVAR(Vehicle
, trip_history
.t
[9].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
732 SLE_CONDVAR(Vehicle
, trip_history
.t
[0].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
733 SLE_CONDVAR(Vehicle
, trip_history
.t
[1].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
734 SLE_CONDVAR(Vehicle
, trip_history
.t
[2].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
735 SLE_CONDVAR(Vehicle
, trip_history
.t
[3].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
736 SLE_CONDVAR(Vehicle
, trip_history
.t
[4].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
737 SLE_CONDVAR(Vehicle
, trip_history
.t
[5].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
738 SLE_CONDVAR(Vehicle
, trip_history
.t
[6].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
739 SLE_CONDVAR(Vehicle
, trip_history
.t
[7].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
740 SLE_CONDVAR(Vehicle
, trip_history
.t
[8].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
741 SLE_CONDVAR(Vehicle
, trip_history
.t
[9].date
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
746 static const SaveLoad _train_desc
[] = {
747 SLE_WRITEBYTE(Vehicle
, type
, VEH_TRAIN
),
749 SLE_VAR(Train
, crash_anim_pos
, SLE_UINT16
),
750 SLE_VAR(Train
, force_proceed
, SLE_UINT8
),
751 SLE_VAR(Train
, railtype
, SLE_UINT8
),
752 SLE_VAR(Train
, track
, SLE_UINT8
),
754 SLE_CONDVAR(Train
, flags
, SLE_FILE_U8
| SLE_VAR_U32
, 2, 99),
755 SLE_CONDVAR(Train
, flags
, SLE_FILE_U16
| SLE_VAR_U32
, 100, SL_PATCH_PACK_1_19
-1),
756 SLE_CONDVAR(Train
, flags
, SLE_UINT32
, SL_PATCH_PACK_1_19
, SL_MAX_VERSION
),
757 SLE_CONDNULL(2, 2, 59),
759 SLE_CONDVAR(Train
, wait_counter
, SLE_UINT16
, 136, SL_MAX_VERSION
),
760 SLE_CONDVAR(Train
, tunnel_bridge_signal_num
, SLE_UINT16
, SL_PATCH_PACK_1_19
, SL_MAX_VERSION
),
762 SLE_CONDNULL(2, 2, 19),
763 SLE_CONDVAR(Train
, gv_flags
, SLE_UINT16
, 139, SL_MAX_VERSION
),
764 SLE_CONDNULL(11, 2, 143), // old reserved space
765 SLE_CONDVAR(Train
, reverse_distance
, SLE_UINT16
, SL_PATCH_PACK_1_12
, SL_MAX_VERSION
),
770 static const SaveLoad _roadveh_desc
[] = {
771 SLE_WRITEBYTE(Vehicle
, type
, VEH_ROAD
),
773 SLE_VAR(RoadVehicle
, state
, SLE_UINT8
),
774 SLE_VAR(RoadVehicle
, frame
, SLE_UINT8
),
775 SLE_VAR(RoadVehicle
, blocked_ctr
, SLE_UINT16
),
776 SLE_VAR(RoadVehicle
, overtaking
, SLE_UINT8
),
777 SLE_VAR(RoadVehicle
, overtaking_ctr
, SLE_UINT8
),
778 SLE_VAR(RoadVehicle
, crashed_ctr
, SLE_UINT16
),
779 SLE_VAR(RoadVehicle
, reverse_ctr
, SLE_UINT8
),
781 SLE_CONDNULL(2, 6, 68),
782 SLE_CONDVAR(RoadVehicle
, gv_flags
, SLE_UINT16
, 139, SL_MAX_VERSION
),
783 SLE_CONDNULL(4, 69, 130),
784 SLE_CONDNULL(2, 6, 130),
785 SLE_CONDNULL(16, 2, 143), // old reserved space
790 static const SaveLoad _ship_desc
[] = {
791 SLE_WRITEBYTE(Vehicle
, type
, VEH_SHIP
),
793 SLE_VAR(Ship
, state
, SLE_UINT8
),
795 SLE_CONDNULL(16, 2, 143), // old reserved space
800 static const SaveLoad _aircraft_desc
[] = {
801 SLE_WRITEBYTE(Vehicle
, type
, VEH_AIRCRAFT
),
803 SLE_VAR(Aircraft
, crashed_counter
, SLE_UINT16
),
804 SLE_VAR(Aircraft
, pos
, SLE_UINT8
),
806 SLE_CONDVAR(Aircraft
, targetairport
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
807 SLE_CONDVAR(Aircraft
, targetairport
, SLE_UINT16
, 5, SL_MAX_VERSION
),
809 SLE_VAR(Aircraft
, state
, SLE_UINT8
),
811 SLE_CONDVAR(Aircraft
, previous_pos
, SLE_UINT8
, 2, SL_MAX_VERSION
),
812 SLE_CONDVAR(Aircraft
, last_direction
, SLE_UINT8
, 2, SL_MAX_VERSION
),
813 SLE_CONDVAR(Aircraft
, number_consecutive_turns
, SLE_UINT8
, 2, SL_MAX_VERSION
),
815 SLE_CONDVAR(Aircraft
, turn_counter
, SLE_UINT8
, 136, SL_MAX_VERSION
),
816 SLE_CONDVAR(Aircraft
, flags
, SLE_UINT8
, 167, SL_MAX_VERSION
),
818 SLE_CONDNULL(13, 2, 143), // old reserved space
823 static const SaveLoad _special_desc
[] = {
824 SLE_WRITEBYTE(Vehicle
, type
, VEH_EFFECT
),
826 SLE_VAR(Vehicle
, subtype
, SLE_UINT8
),
828 SLE_CONDVAR(Vehicle
, tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
829 SLE_CONDVAR(Vehicle
, tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
831 SLE_CONDVAR(Vehicle
, x_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
832 SLE_CONDVAR(Vehicle
, x_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
833 SLE_CONDVAR(Vehicle
, y_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
834 SLE_CONDVAR(Vehicle
, y_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
835 SLE_CONDVAR(Vehicle
, z_pos
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 163),
836 SLE_CONDVAR(Vehicle
, z_pos
, SLE_INT32
, 164, SL_MAX_VERSION
),
838 SLE_VAR(Vehicle
, sprite_seq
.seq
[0].sprite
, SLE_FILE_U16
| SLE_VAR_U32
),
839 SLE_CONDNULL(5, 0, 57),
840 SLE_VAR(Vehicle
, progress
, SLE_UINT8
),
841 SLE_VAR(Vehicle
, vehstatus
, SLE_UINT8
),
843 SLE_VAR(EffectVehicle
, animation_state
, SLE_UINT16
),
844 SLE_VAR(EffectVehicle
, animation_substate
, SLE_UINT8
),
846 SLE_CONDVAR(Vehicle
, spritenum
, SLE_UINT8
, 2, SL_MAX_VERSION
),
848 SLE_CONDNULL(15, 2, 143), // old reserved space
853 static const SaveLoad _disaster_desc
[] = {
854 SLE_WRITEBYTE(Vehicle
, type
, VEH_DISASTER
),
856 SLE_REF(Vehicle
, next
, REF_VEHICLE_OLD
),
858 SLE_VAR(Vehicle
, subtype
, SLE_UINT8
),
859 SLE_CONDVAR(Vehicle
, tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
860 SLE_CONDVAR(Vehicle
, tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
861 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
862 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
864 SLE_CONDVAR(Vehicle
, x_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
865 SLE_CONDVAR(Vehicle
, x_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
866 SLE_CONDVAR(Vehicle
, y_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
867 SLE_CONDVAR(Vehicle
, y_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
868 SLE_CONDVAR(Vehicle
, z_pos
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 163),
869 SLE_CONDVAR(Vehicle
, z_pos
, SLE_INT32
, 164, SL_MAX_VERSION
),
870 SLE_VAR(Vehicle
, direction
, SLE_UINT8
),
872 SLE_CONDNULL(5, 0, 57),
873 SLE_VAR(Vehicle
, owner
, SLE_UINT8
),
874 SLE_VAR(Vehicle
, vehstatus
, SLE_UINT8
),
875 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
876 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_UINT16
, 5, SL_MAX_VERSION
),
878 SLE_VAR(Vehicle
, sprite_seq
.seq
[0].sprite
, SLE_FILE_U16
| SLE_VAR_U32
),
879 SLE_CONDVAR(Vehicle
, age
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
880 SLE_CONDVAR(Vehicle
, age
, SLE_INT32
, 31, SL_MAX_VERSION
),
881 SLE_VAR(Vehicle
, tick_counter
, SLE_UINT8
),
883 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 190),
884 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_UINT32
, 191, SL_PATCH_PACK
- 1),
885 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_FILE_U16
| SLE_VAR_U32
, SL_PATCH_PACK
, SL_PATCH_PACK_1_7
),
886 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_UINT32
, SL_PATCH_PACK_1_8
, SL_MAX_VERSION
),
888 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 190),
889 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_UINT32
, 191, SL_PATCH_PACK
- 1),
890 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_FILE_U16
| SLE_VAR_U32
, SL_PATCH_PACK
, SL_PATCH_PACK_1_7
),
891 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_UINT32
, SL_PATCH_PACK_1_8
, SL_MAX_VERSION
),
893 SLE_CONDVAR(DisasterVehicle
, flags
, SLE_UINT8
, 194, SL_PATCH_PACK
- 1),
894 SLE_CONDVAR(DisasterVehicle
, flags
, SLE_UINT8
, SL_PATCH_PACK_1_9
, SL_MAX_VERSION
),
896 SLE_CONDNULL(16, 2, 143), // old reserved space
902 static const SaveLoad
* const _veh_descs
[] = {
912 return _veh_descs
[vt
];
915 /** Will be called when the vehicles need to be saved. */
916 static void Save_VEHS()
919 /* Write the vehicles */
920 FOR_ALL_VEHICLES(v
) {
921 SlSetArrayIndex(v
->index
);
922 SlObject(v
, GetVehicleDescription(v
->type
));
926 /** Will be called when vehicles need to be loaded. */
933 while ((index
= SlIterateArray()) != -1) {
935 VehicleType vtype
= (VehicleType
)SlReadByte();
938 case VEH_TRAIN
: v
= new (index
) Train(); break;
939 case VEH_ROAD
: v
= new (index
) RoadVehicle(); break;
940 case VEH_SHIP
: v
= new (index
) Ship(); break;
941 case VEH_AIRCRAFT
: v
= new (index
) Aircraft(); break;
942 case VEH_EFFECT
: v
= new (index
) EffectVehicle(); break;
943 case VEH_DISASTER
: v
= new (index
) DisasterVehicle(); break;
944 case VEH_INVALID
: // Savegame shouldn't contain invalid vehicles
945 default: SlErrorCorrupt("Invalid vehicle type");
948 SlObject(v
, GetVehicleDescription(vtype
));
950 if (_cargo_count
!= 0 && IsCompanyBuildableVehicleType(v
) && CargoPacket::CanAllocateItem()) {
951 /* Don't construct the packet with station here, because that'll fail with old savegames */
952 CargoPacket
*cp
= new CargoPacket(_cargo_count
, _cargo_days
, _cargo_source
, _cargo_source_xy
, _cargo_loaded_at_xy
, _cargo_feeder_share
);
956 /* Old savegames used 'last_station_visited = 0xFF' */
957 if (IsSavegameVersionBefore(5) && v
->last_station_visited
== 0xFF) {
958 v
->last_station_visited
= INVALID_STATION
;
961 if (IsSavegameVersionBefore(182)) v
->last_loading_station
= INVALID_STATION
;
963 if (IsSavegameVersionBefore(5)) {
964 /* Convert the current_order.type (which is a mix of type and flags, because
965 * in those versions, they both were 4 bits big) to type and flags */
966 v
->current_order
.flags
= GB(v
->current_order
.type
, 4, 4);
967 v
->current_order
.type
&= 0x0F;
970 /* Advanced vehicle lists got added */
971 if (IsSavegameVersionBefore(60)) v
->group_id
= DEFAULT_GROUP
;
975 static void Ptrs_VEHS()
978 FOR_ALL_VEHICLES(v
) {
979 SlObject(v
, GetVehicleDescription(v
->type
));
983 const SaveLoad
*GetOrderExtraInfoDescription();
987 /* save extended order info for vehicle current order */
989 FOR_ALL_VEHICLES(v
) {
990 if (v
->current_order
.extra
) {
991 SlSetArrayIndex(v
->index
);
992 SlObject(v
->current_order
.extra
.get(), GetOrderExtraInfoDescription());
999 /* load extended order info for vehicle current order */
1001 while ((index
= SlIterateArray()) != -1) {
1002 Vehicle
*v
= Vehicle::GetIfValid(index
);
1004 v
->current_order
.AllocExtraInfo();
1005 SlObject(v
->current_order
.extra
.get(), GetOrderExtraInfoDescription());
1009 extern const ChunkHandler _veh_chunk_handlers
[] = {
1010 { 'VEHS', Save_VEHS
, Load_VEHS
, Ptrs_VEHS
, NULL
, CH_SPARSE_ARRAY
},
1011 { 'VEOX', Save_VEOX
, Load_VEOX
, NULL
, NULL
, CH_SPARSE_ARRAY
| CH_LAST
},