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 void AfterLoadTripHistory()
478 FOR_ALL_VEHICLES(v
) {
479 // We used to only story the date. Now we store the ticks, so multiply by DAY_TICKS.
480 // Old values will be less accurate because of this, but they're constantly overwritten anyway.
481 if (IsSavegameVersionBefore(SL_PATCH_PACK_1_24
)) {
482 for (int i
= 0; i
< NUM_TRIP_HISTORY_ENTRIES
; ++i
) {
483 v
->trip_history
.entries
[i
].ticks
*= DAY_TICKS
;
487 v
->trip_history
.UpdateCalculated(true);
491 bool TrainController(Train
*v
, Vehicle
*nomove
, bool reverse
= true); // From train_cmd.cpp
492 void ReverseTrainDirection(Train
*v
);
493 void ReverseTrainSwapVeh(Train
*v
, int l
, int r
);
495 /** Fixup old train spacing. */
496 void FixupTrainLengths()
498 /* Vehicle center was moved from 4 units behind the front to half the length
499 * behind the front. Move vehicles so they end up on the same spot. */
501 FOR_ALL_VEHICLES(v
) {
502 if (v
->type
== VEH_TRAIN
&& v
->IsPrimaryVehicle()) {
503 /* The vehicle center is now more to the front depending on vehicle length,
504 * so we need to move all vehicles forward to cover the difference to the
505 * old center, otherwise wagon spacing in trains would be broken upon load. */
506 for (Train
*u
= Train::From(v
); u
!= NULL
; u
= u
->Next()) {
507 if (u
->track
== TRACK_BIT_DEPOT
|| (u
->vehstatus
& VS_CRASHED
)) continue;
509 Train
*next
= u
->Next();
511 /* Try to pull the vehicle half its length forward. */
512 int diff
= (VEHICLE_LENGTH
- u
->gcache
.cached_veh_length
) / 2;
514 for (done
= 0; done
< diff
; done
++) {
515 if (!TrainController(u
, next
, false)) break;
518 if (next
!= NULL
&& done
< diff
&& u
->IsFrontEngine()) {
519 /* Pulling the front vehicle forwards failed, we either encountered a dead-end
520 * or a red signal. To fix this, we try to move the whole train the required
521 * space backwards and re-do the fix up of the front vehicle. */
523 /* Ignore any signals when backtracking. */
524 TrainForceProceeding old_tfp
= u
->force_proceed
;
525 u
->force_proceed
= TFP_SIGNAL
;
527 /* Swap start<>end, start+1<>end-1, ... */
528 int r
= CountVehiclesInChain(u
) - 1; // number of vehicles - 1
530 do ReverseTrainSwapVeh(u
, l
++, r
--); while (l
<= r
);
532 /* We moved the first vehicle which is now the last. Move it back to the
533 * original position as we will fix up the last vehicle later in the loop. */
534 for (int i
= 0; i
< done
; i
++) TrainController(u
->Last(), NULL
);
536 /* Move the train backwards to get space for the first vehicle. As the stopping
537 * distance from a line end is rounded up, move the train one unit more to cater
538 * for front vehicles with odd lengths. */
540 for (moved
= 0; moved
< diff
+ 1; moved
++) {
541 if (!TrainController(u
, NULL
, false)) break;
544 /* Swap start<>end, start+1<>end-1, ... again. */
545 r
= CountVehiclesInChain(u
) - 1; // number of vehicles - 1
547 do ReverseTrainSwapVeh(u
, l
++, r
--); while (l
<= r
);
549 u
->force_proceed
= old_tfp
;
551 /* Tracks are too short to fix the train length. The player has to fix the
552 * train in a depot. Bail out so we don't damage the vehicle chain any more. */
553 if (moved
< diff
+ 1) break;
555 /* Re-do the correction for the first vehicle. */
556 for (done
= 0; done
< diff
; done
++) TrainController(u
, next
, false);
558 /* We moved one unit more backwards than needed for even-length front vehicles,
559 * try to move that unit forward again. We don't care if this step fails. */
560 TrainController(u
, NULL
, false);
563 /* If the next wagon is still in a depot, check if it shouldn't be outside already. */
564 if (next
!= NULL
&& next
->track
== TRACK_BIT_DEPOT
) {
565 int d
= TicksToLeaveDepot(u
);
567 /* Next vehicle should have left the depot already, show it and pull forward. */
568 next
->vehstatus
&= ~VS_HIDDEN
;
569 next
->track
= TrackToTrackBits(GetRailDepotTrack(next
->tile
));
570 for (int i
= 0; i
>= d
; i
--) TrainController(next
, NULL
);
575 /* Update all cached properties after moving the vehicle chain around. */
576 Train::From(v
)->ConsistChanged(CCF_TRACK
);
581 static uint8 _cargo_days
;
582 static uint16 _cargo_source
;
583 static uint32 _cargo_source_xy
;
584 static uint16 _cargo_count
;
585 static uint16 _cargo_paid_for
;
586 static Money _cargo_feeder_share
;
587 static uint32 _cargo_loaded_at_xy
;
590 * Make it possible to make the saveload tables "friends" of other classes.
591 * @param vt the vehicle type. Can be VEH_END for the common vehicle description data
592 * @return the saveload description
594 const SaveLoad
*GetVehicleDescription(VehicleType vt
)
596 /** Save and load of vehicles */
597 static const SaveLoad _common_veh_desc
[] = {
598 SLE_VAR(Vehicle
, subtype
, SLE_UINT8
),
600 SLE_REF(Vehicle
, next
, REF_VEHICLE_OLD
),
601 SLE_CONDVAR(Vehicle
, name
, SLE_NAME
, 0, 83),
602 SLE_CONDSTR(Vehicle
, name
, SLE_STR
| SLF_ALLOW_CONTROL
, 0, 84, SL_MAX_VERSION
),
603 SLE_CONDVAR(Vehicle
, unitnumber
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 7),
604 SLE_CONDVAR(Vehicle
, unitnumber
, SLE_UINT16
, 8, SL_MAX_VERSION
),
605 SLE_VAR(Vehicle
, owner
, SLE_UINT8
),
606 SLE_CONDVAR(Vehicle
, tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
607 SLE_CONDVAR(Vehicle
, tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
608 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
609 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
611 SLE_CONDVAR(Vehicle
, x_pos
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
612 SLE_CONDVAR(Vehicle
, x_pos
, SLE_UINT32
, 6, SL_MAX_VERSION
),
613 SLE_CONDVAR(Vehicle
, y_pos
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
614 SLE_CONDVAR(Vehicle
, y_pos
, SLE_UINT32
, 6, SL_MAX_VERSION
),
615 SLE_CONDVAR(Vehicle
, z_pos
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 163),
616 SLE_CONDVAR(Vehicle
, z_pos
, SLE_INT32
, 164, SL_MAX_VERSION
),
617 SLE_VAR(Vehicle
, direction
, SLE_UINT8
),
619 SLE_CONDNULL(2, 0, 57),
620 SLE_VAR(Vehicle
, spritenum
, SLE_UINT8
),
621 SLE_CONDNULL(5, 0, 57),
622 SLE_VAR(Vehicle
, engine_type
, SLE_UINT16
),
624 SLE_CONDNULL(2, 0, 151),
625 SLE_VAR(Vehicle
, cur_speed
, SLE_UINT16
),
626 SLE_VAR(Vehicle
, subspeed
, SLE_UINT8
),
627 SLE_VAR(Vehicle
, acceleration
, SLE_UINT8
),
628 SLE_VAR(Vehicle
, progress
, SLE_UINT8
),
630 SLE_VAR(Vehicle
, vehstatus
, SLE_UINT8
),
631 SLE_CONDVAR(Vehicle
, last_station_visited
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
632 SLE_CONDVAR(Vehicle
, last_station_visited
, SLE_UINT16
, 5, SL_MAX_VERSION
),
633 SLE_CONDVAR(Vehicle
, last_loading_station
, SLE_UINT16
, 182, SL_MAX_VERSION
),
635 SLE_VAR(Vehicle
, cargo_type
, SLE_UINT8
),
636 SLE_CONDVAR(Vehicle
, cargo_subtype
, SLE_UINT8
, 35, SL_MAX_VERSION
),
637 SLEG_CONDVAR( _cargo_days
, SLE_UINT8
, 0, 67),
638 SLEG_CONDVAR( _cargo_source
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 6),
639 SLEG_CONDVAR( _cargo_source
, SLE_UINT16
, 7, 67),
640 SLEG_CONDVAR( _cargo_source_xy
, SLE_UINT32
, 44, 67),
641 SLE_VAR(Vehicle
, cargo_cap
, SLE_UINT16
),
642 SLE_CONDVAR(Vehicle
, refit_cap
, SLE_UINT16
, 182, SL_MAX_VERSION
),
643 SLEG_CONDVAR( _cargo_count
, SLE_UINT16
, 0, 67),
644 SLE_CONDDEQ(Vehicle
, cargo
.packets
, REF_CARGO_PACKET
, 68, SL_MAX_VERSION
),
645 SLE_CONDARR(Vehicle
, cargo
.action_counts
, SLE_UINT
, VehicleCargoList::NUM_MOVE_TO_ACTION
, 181, SL_MAX_VERSION
),
646 SLE_CONDVAR(Vehicle
, cargo_age_counter
, SLE_UINT16
, 162, SL_MAX_VERSION
),
648 SLE_CONDNULL(1, SL_PATCH_PACK_1_8
, SL_PATCH_PACK_1_19
- 1), // trip_occupancy
650 SLE_VAR(Vehicle
, day_counter
, SLE_UINT8
),
651 SLE_VAR(Vehicle
, tick_counter
, SLE_UINT8
),
653 SLE_CONDVAR(Vehicle
, running_ticks
, SLE_FILE_U8
| SLE_VAR_U16
, 88, SL_PATCH_PACK_1_8
- 1),
654 SLE_CONDVAR(Vehicle
, running_ticks
, SLE_UINT16
, SL_PATCH_PACK_1_8
, SL_MAX_VERSION
),
656 SLE_VAR(Vehicle
, cur_implicit_order_index
, SLE_UINT8
),
657 SLE_CONDVAR(Vehicle
, cur_real_order_index
, SLE_UINT8
, 158, SL_MAX_VERSION
),
658 SLE_CONDVAR(Vehicle
, cur_timetable_order_index
, SLE_UINT8
, SL_PATCH_PACK_1_24
, SL_MAX_VERSION
),
659 /* num_orders is now part of OrderList and is not saved but counted */
660 SLE_CONDNULL(1, 0, 104),
662 /* This next line is for version 4 and prior compatibility.. it temporarily reads
663 type and flags (which were both 4 bits) into type. Later on this is
664 converted correctly */
665 SLE_CONDVAR(Vehicle
, current_order
.type
, SLE_UINT8
, 0, 4),
666 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
668 /* Orders for version 5 and on */
669 SLE_CONDVAR(Vehicle
, current_order
.type
, SLE_UINT8
, 5, SL_MAX_VERSION
),
670 SLE_CONDVAR(Vehicle
, current_order
.flags
, SLE_UINT8
, 5, SL_MAX_VERSION
),
671 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_UINT16
, 5, SL_MAX_VERSION
),
673 /* Refit in current order */
674 SLE_CONDVAR(Vehicle
, current_order
.refit_cargo
, SLE_UINT8
, 36, SL_MAX_VERSION
),
675 SLE_CONDNULL(1, 36, 181), // refit_subtype
677 /* Timetable in current order */
678 SLE_CONDVAR(Vehicle
, current_order
.wait_time
, SLE_UINT16
, 67, SL_MAX_VERSION
),
679 SLE_CONDVAR(Vehicle
, current_order
.travel_time
, SLE_UINT16
, 67, SL_MAX_VERSION
),
680 SLE_CONDVAR(Vehicle
, current_order
.max_speed
, SLE_UINT16
, 174, SL_MAX_VERSION
),
681 SLE_CONDVAR(Vehicle
, timetable_start
, SLE_INT32
, 129, SL_MAX_VERSION
),
683 SLE_CONDREF(Vehicle
, orders
, REF_ORDER
, 0, 104),
684 SLE_CONDREF(Vehicle
, orders
, REF_ORDERLIST
, 105, SL_MAX_VERSION
),
686 SLE_CONDVAR(Vehicle
, age
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
687 SLE_CONDVAR(Vehicle
, age
, SLE_INT32
, 31, SL_MAX_VERSION
),
688 SLE_CONDVAR(Vehicle
, max_age
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
689 SLE_CONDVAR(Vehicle
, max_age
, SLE_INT32
, 31, SL_MAX_VERSION
),
690 SLE_CONDVAR(Vehicle
, date_of_last_service
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
691 SLE_CONDVAR(Vehicle
, date_of_last_service
, SLE_INT32
, 31, SL_MAX_VERSION
),
692 SLE_CONDVAR(Vehicle
, service_interval
, SLE_UINT16
, 0, 30),
693 SLE_CONDVAR(Vehicle
, service_interval
, SLE_FILE_U32
| SLE_VAR_U16
, 31, 179),
694 SLE_CONDVAR(Vehicle
, service_interval
, SLE_UINT16
, 180, SL_MAX_VERSION
),
695 SLE_VAR(Vehicle
, reliability
, SLE_UINT16
),
696 SLE_VAR(Vehicle
, reliability_spd_dec
, SLE_UINT16
),
697 SLE_VAR(Vehicle
, breakdown_ctr
, SLE_UINT8
),
698 SLE_VAR(Vehicle
, breakdown_delay
, SLE_UINT8
),
699 SLE_VAR(Vehicle
, breakdowns_since_last_service
, SLE_UINT8
),
700 SLE_VAR(Vehicle
, breakdown_chance
, SLE_UINT8
),
701 SLE_CONDVAR(Vehicle
, build_year
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 30),
702 SLE_CONDVAR(Vehicle
, build_year
, SLE_INT32
, 31, SL_MAX_VERSION
),
704 SLE_VAR(Vehicle
, load_unload_ticks
, SLE_UINT16
),
705 SLEG_CONDVAR( _cargo_paid_for
, SLE_UINT16
, 45, SL_MAX_VERSION
),
706 SLE_CONDVAR(Vehicle
, vehicle_flags
, SLE_FILE_U8
| SLE_VAR_U16
, 40, 179),
707 SLE_CONDVAR(Vehicle
, vehicle_flags
, SLE_UINT16
, 180, SL_MAX_VERSION
),
709 SLE_CONDVAR(Vehicle
, profit_this_year
, SLE_FILE_I32
| SLE_VAR_I64
, 0, 64),
710 SLE_CONDVAR(Vehicle
, profit_this_year
, SLE_INT64
, 65, SL_MAX_VERSION
),
711 SLE_CONDVAR(Vehicle
, profit_last_year
, SLE_FILE_I32
| SLE_VAR_I64
, 0, 64),
712 SLE_CONDVAR(Vehicle
, profit_last_year
, SLE_INT64
, 65, SL_MAX_VERSION
),
713 SLE_CONDVAR(Vehicle
, profit_lifetime
, SLE_INT64
, SL_PATCH_PACK_1_14
, SL_MAX_VERSION
),
714 SLEG_CONDVAR( _cargo_feeder_share
, SLE_FILE_I32
| SLE_VAR_I64
, 51, 64),
715 SLEG_CONDVAR( _cargo_feeder_share
, SLE_INT64
, 65, 67),
716 SLEG_CONDVAR( _cargo_loaded_at_xy
, SLE_UINT32
, 51, 67),
717 SLE_CONDVAR(Vehicle
, value
, SLE_FILE_I32
| SLE_VAR_I64
, 0, 64),
718 SLE_CONDVAR(Vehicle
, value
, SLE_INT64
, 65, SL_MAX_VERSION
),
720 SLE_CONDVAR(Vehicle
, random_bits
, SLE_UINT8
, 2, SL_MAX_VERSION
),
721 SLE_CONDVAR(Vehicle
, waiting_triggers
, SLE_UINT8
, 2, SL_MAX_VERSION
),
723 SLE_CONDREF(Vehicle
, ahead_separation
, REF_VEHICLE
, SL_PATCH_PACK
, SL_PATCH_PACK_1_5
),
724 SLE_CONDREF(Vehicle
, behind_separation
, REF_VEHICLE
, SL_PATCH_PACK
, SL_PATCH_PACK_1_5
),
726 SLE_CONDREF(Vehicle
, next_shared
, REF_VEHICLE
, 2, SL_MAX_VERSION
),
727 SLE_CONDNULL(2, 2, 68),
728 SLE_CONDNULL(4, 69, 100),
730 SLE_CONDVAR(Vehicle
, group_id
, SLE_UINT16
, 60, SL_MAX_VERSION
),
732 SLE_CONDVAR(Vehicle
, current_order_time
, SLE_UINT32
, 67, SL_MAX_VERSION
),
733 SLE_CONDVAR(Vehicle
, current_loading_time
, SLE_UINT32
, SL_PATCH_PACK
, SL_PATCH_PACK_1_5
),
734 SLE_CONDVAR(Vehicle
, current_loading_time
, SLE_UINT32
, SL_PATCH_PACK_1_23
, SL_MAX_VERSION
),
735 SLE_CONDVAR(Vehicle
, lateness_counter
, SLE_INT32
, 67, SL_MAX_VERSION
),
737 SLE_CONDNULL(10, 2, 143), // old reserved space
739 // Trip History Arrays
740 SLE_CONDVAR(Vehicle
, trip_history
.entries
[0].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
741 SLE_CONDVAR(Vehicle
, trip_history
.entries
[1].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
742 SLE_CONDVAR(Vehicle
, trip_history
.entries
[2].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
743 SLE_CONDVAR(Vehicle
, trip_history
.entries
[3].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
744 SLE_CONDVAR(Vehicle
, trip_history
.entries
[4].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
745 SLE_CONDVAR(Vehicle
, trip_history
.entries
[5].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
746 SLE_CONDVAR(Vehicle
, trip_history
.entries
[6].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
747 SLE_CONDVAR(Vehicle
, trip_history
.entries
[7].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
748 SLE_CONDVAR(Vehicle
, trip_history
.entries
[8].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
749 SLE_CONDVAR(Vehicle
, trip_history
.entries
[9].profit
, SLE_INT64
, SL_PATCH_PACK
, SL_MAX_VERSION
),
750 SLE_CONDVAR(Vehicle
, trip_history
.entries
[0].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
751 SLE_CONDVAR(Vehicle
, trip_history
.entries
[1].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
752 SLE_CONDVAR(Vehicle
, trip_history
.entries
[2].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
753 SLE_CONDVAR(Vehicle
, trip_history
.entries
[3].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
754 SLE_CONDVAR(Vehicle
, trip_history
.entries
[4].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
755 SLE_CONDVAR(Vehicle
, trip_history
.entries
[5].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
756 SLE_CONDVAR(Vehicle
, trip_history
.entries
[6].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
757 SLE_CONDVAR(Vehicle
, trip_history
.entries
[7].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
758 SLE_CONDVAR(Vehicle
, trip_history
.entries
[8].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
759 SLE_CONDVAR(Vehicle
, trip_history
.entries
[9].ticks
, SLE_FILE_I64
| SLE_VAR_I32
, SL_PATCH_PACK
, SL_MAX_VERSION
),
765 static const SaveLoad _train_desc
[] = {
766 SLE_WRITEBYTE(Vehicle
, type
, VEH_TRAIN
),
768 SLE_VAR(Train
, crash_anim_pos
, SLE_UINT16
),
769 SLE_VAR(Train
, force_proceed
, SLE_UINT8
),
770 SLE_VAR(Train
, railtype
, SLE_UINT8
),
771 SLE_VAR(Train
, track
, SLE_UINT8
),
773 SLE_CONDVAR(Train
, flags
, SLE_FILE_U8
| SLE_VAR_U32
, 2, 99),
774 SLE_CONDVAR(Train
, flags
, SLE_FILE_U16
| SLE_VAR_U32
, 100, SL_PATCH_PACK_1_19
-1),
775 SLE_CONDVAR(Train
, flags
, SLE_UINT32
, SL_PATCH_PACK_1_19
, SL_MAX_VERSION
),
776 SLE_CONDNULL(2, 2, 59),
778 SLE_CONDVAR(Train
, wait_counter
, SLE_UINT16
, 136, SL_MAX_VERSION
),
779 SLE_CONDVAR(Train
, tunnel_bridge_signal_num
, SLE_UINT16
, SL_PATCH_PACK_1_19
, SL_MAX_VERSION
),
781 SLE_CONDNULL(2, 2, 19),
782 SLE_CONDVAR(Train
, gv_flags
, SLE_UINT16
, 139, SL_MAX_VERSION
),
783 SLE_CONDNULL(11, 2, 143), // old reserved space
784 SLE_CONDVAR(Train
, reverse_distance
, SLE_UINT16
, SL_PATCH_PACK_1_12
, SL_MAX_VERSION
),
789 static const SaveLoad _roadveh_desc
[] = {
790 SLE_WRITEBYTE(Vehicle
, type
, VEH_ROAD
),
792 SLE_VAR(RoadVehicle
, state
, SLE_UINT8
),
793 SLE_VAR(RoadVehicle
, frame
, SLE_UINT8
),
794 SLE_VAR(RoadVehicle
, blocked_ctr
, SLE_UINT16
),
795 SLE_VAR(RoadVehicle
, overtaking
, SLE_UINT8
),
796 SLE_VAR(RoadVehicle
, overtaking_ctr
, SLE_UINT8
),
797 SLE_VAR(RoadVehicle
, crashed_ctr
, SLE_UINT16
),
798 SLE_VAR(RoadVehicle
, reverse_ctr
, SLE_UINT8
),
800 SLE_CONDNULL(2, 6, 68),
801 SLE_CONDVAR(RoadVehicle
, gv_flags
, SLE_UINT16
, 139, SL_MAX_VERSION
),
802 SLE_CONDNULL(4, 69, 130),
803 SLE_CONDNULL(2, 6, 130),
804 SLE_CONDNULL(16, 2, 143), // old reserved space
809 static const SaveLoad _ship_desc
[] = {
810 SLE_WRITEBYTE(Vehicle
, type
, VEH_SHIP
),
812 SLE_VAR(Ship
, state
, SLE_UINT8
),
814 SLE_CONDNULL(16, 2, 143), // old reserved space
819 static const SaveLoad _aircraft_desc
[] = {
820 SLE_WRITEBYTE(Vehicle
, type
, VEH_AIRCRAFT
),
822 SLE_VAR(Aircraft
, crashed_counter
, SLE_UINT16
),
823 SLE_VAR(Aircraft
, pos
, SLE_UINT8
),
825 SLE_CONDVAR(Aircraft
, targetairport
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
826 SLE_CONDVAR(Aircraft
, targetairport
, SLE_UINT16
, 5, SL_MAX_VERSION
),
828 SLE_VAR(Aircraft
, state
, SLE_UINT8
),
830 SLE_CONDVAR(Aircraft
, previous_pos
, SLE_UINT8
, 2, SL_MAX_VERSION
),
831 SLE_CONDVAR(Aircraft
, last_direction
, SLE_UINT8
, 2, SL_MAX_VERSION
),
832 SLE_CONDVAR(Aircraft
, number_consecutive_turns
, SLE_UINT8
, 2, SL_MAX_VERSION
),
834 SLE_CONDVAR(Aircraft
, turn_counter
, SLE_UINT8
, 136, SL_MAX_VERSION
),
835 SLE_CONDVAR(Aircraft
, flags
, SLE_UINT8
, 167, SL_MAX_VERSION
),
837 SLE_CONDNULL(13, 2, 143), // old reserved space
842 static const SaveLoad _special_desc
[] = {
843 SLE_WRITEBYTE(Vehicle
, type
, VEH_EFFECT
),
845 SLE_VAR(Vehicle
, subtype
, SLE_UINT8
),
847 SLE_CONDVAR(Vehicle
, tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
848 SLE_CONDVAR(Vehicle
, tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
850 SLE_CONDVAR(Vehicle
, x_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
851 SLE_CONDVAR(Vehicle
, x_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
852 SLE_CONDVAR(Vehicle
, y_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
853 SLE_CONDVAR(Vehicle
, y_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
854 SLE_CONDVAR(Vehicle
, z_pos
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 163),
855 SLE_CONDVAR(Vehicle
, z_pos
, SLE_INT32
, 164, SL_MAX_VERSION
),
857 SLE_VAR(Vehicle
, sprite_seq
.seq
[0].sprite
, SLE_FILE_U16
| SLE_VAR_U32
),
858 SLE_CONDNULL(5, 0, 57),
859 SLE_VAR(Vehicle
, progress
, SLE_UINT8
),
860 SLE_VAR(Vehicle
, vehstatus
, SLE_UINT8
),
862 SLE_VAR(EffectVehicle
, animation_state
, SLE_UINT16
),
863 SLE_VAR(EffectVehicle
, animation_substate
, SLE_UINT8
),
865 SLE_CONDVAR(Vehicle
, spritenum
, SLE_UINT8
, 2, SL_MAX_VERSION
),
867 SLE_CONDNULL(15, 2, 143), // old reserved space
872 static const SaveLoad _disaster_desc
[] = {
873 SLE_WRITEBYTE(Vehicle
, type
, VEH_DISASTER
),
875 SLE_REF(Vehicle
, next
, REF_VEHICLE_OLD
),
877 SLE_VAR(Vehicle
, subtype
, SLE_UINT8
),
878 SLE_CONDVAR(Vehicle
, tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
879 SLE_CONDVAR(Vehicle
, tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
880 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 5),
881 SLE_CONDVAR(Vehicle
, dest_tile
, SLE_UINT32
, 6, SL_MAX_VERSION
),
883 SLE_CONDVAR(Vehicle
, x_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
884 SLE_CONDVAR(Vehicle
, x_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
885 SLE_CONDVAR(Vehicle
, y_pos
, SLE_FILE_I16
| SLE_VAR_I32
, 0, 5),
886 SLE_CONDVAR(Vehicle
, y_pos
, SLE_INT32
, 6, SL_MAX_VERSION
),
887 SLE_CONDVAR(Vehicle
, z_pos
, SLE_FILE_U8
| SLE_VAR_I32
, 0, 163),
888 SLE_CONDVAR(Vehicle
, z_pos
, SLE_INT32
, 164, SL_MAX_VERSION
),
889 SLE_VAR(Vehicle
, direction
, SLE_UINT8
),
891 SLE_CONDNULL(5, 0, 57),
892 SLE_VAR(Vehicle
, owner
, SLE_UINT8
),
893 SLE_VAR(Vehicle
, vehstatus
, SLE_UINT8
),
894 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_FILE_U8
| SLE_VAR_U16
, 0, 4),
895 SLE_CONDVAR(Vehicle
, current_order
.dest
, SLE_UINT16
, 5, SL_MAX_VERSION
),
897 SLE_VAR(Vehicle
, sprite_seq
.seq
[0].sprite
, SLE_FILE_U16
| SLE_VAR_U32
),
898 SLE_CONDVAR(Vehicle
, age
, SLE_FILE_U16
| SLE_VAR_I32
, 0, 30),
899 SLE_CONDVAR(Vehicle
, age
, SLE_INT32
, 31, SL_MAX_VERSION
),
900 SLE_VAR(Vehicle
, tick_counter
, SLE_UINT8
),
902 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 190),
903 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_UINT32
, 191, SL_PATCH_PACK
- 1),
904 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_FILE_U16
| SLE_VAR_U32
, SL_PATCH_PACK
, SL_PATCH_PACK_1_7
),
905 SLE_CONDVAR(DisasterVehicle
, image_override
, SLE_UINT32
, SL_PATCH_PACK_1_8
, SL_MAX_VERSION
),
907 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_FILE_U16
| SLE_VAR_U32
, 0, 190),
908 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_UINT32
, 191, SL_PATCH_PACK
- 1),
909 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_FILE_U16
| SLE_VAR_U32
, SL_PATCH_PACK
, SL_PATCH_PACK_1_7
),
910 SLE_CONDVAR(DisasterVehicle
, big_ufo_destroyer_target
, SLE_UINT32
, SL_PATCH_PACK_1_8
, SL_MAX_VERSION
),
912 SLE_CONDVAR(DisasterVehicle
, flags
, SLE_UINT8
, 194, SL_PATCH_PACK
- 1),
913 SLE_CONDVAR(DisasterVehicle
, flags
, SLE_UINT8
, SL_PATCH_PACK_1_9
, SL_MAX_VERSION
),
915 SLE_CONDNULL(16, 2, 143), // old reserved space
921 static const SaveLoad
* const _veh_descs
[] = {
931 return _veh_descs
[vt
];
934 /** Will be called when the vehicles need to be saved. */
935 static void Save_VEHS()
938 /* Write the vehicles */
939 FOR_ALL_VEHICLES(v
) {
940 SlSetArrayIndex(v
->index
);
941 SlObject(v
, GetVehicleDescription(v
->type
));
945 /** Will be called when vehicles need to be loaded. */
952 while ((index
= SlIterateArray()) != -1) {
954 VehicleType vtype
= (VehicleType
)SlReadByte();
957 case VEH_TRAIN
: v
= new (index
) Train(); break;
958 case VEH_ROAD
: v
= new (index
) RoadVehicle(); break;
959 case VEH_SHIP
: v
= new (index
) Ship(); break;
960 case VEH_AIRCRAFT
: v
= new (index
) Aircraft(); break;
961 case VEH_EFFECT
: v
= new (index
) EffectVehicle(); break;
962 case VEH_DISASTER
: v
= new (index
) DisasterVehicle(); break;
963 case VEH_INVALID
: // Savegame shouldn't contain invalid vehicles
964 default: SlErrorCorrupt("Invalid vehicle type");
967 SlObject(v
, GetVehicleDescription(vtype
));
969 if (_cargo_count
!= 0 && IsCompanyBuildableVehicleType(v
) && CargoPacket::CanAllocateItem()) {
970 /* Don't construct the packet with station here, because that'll fail with old savegames */
971 CargoPacket
*cp
= new CargoPacket(_cargo_count
, _cargo_days
, _cargo_source
, _cargo_source_xy
, _cargo_loaded_at_xy
, _cargo_feeder_share
);
975 /* Old savegames used 'last_station_visited = 0xFF' */
976 if (IsSavegameVersionBefore(5) && v
->last_station_visited
== 0xFF) {
977 v
->last_station_visited
= INVALID_STATION
;
980 if (IsSavegameVersionBefore(182)) v
->last_loading_station
= INVALID_STATION
;
982 if (IsSavegameVersionBefore(5)) {
983 /* Convert the current_order.type (which is a mix of type and flags, because
984 * in those versions, they both were 4 bits big) to type and flags */
985 v
->current_order
.flags
= GB(v
->current_order
.type
, 4, 4);
986 v
->current_order
.type
&= 0x0F;
989 /* Advanced vehicle lists got added */
990 if (IsSavegameVersionBefore(60)) v
->group_id
= DEFAULT_GROUP
;
994 static void Ptrs_VEHS()
997 FOR_ALL_VEHICLES(v
) {
998 SlObject(v
, GetVehicleDescription(v
->type
));
1002 const SaveLoad
*GetOrderExtraInfoDescription();
1006 /* save extended order info for vehicle current order */
1008 FOR_ALL_VEHICLES(v
) {
1009 if (v
->current_order
.extra
) {
1010 SlSetArrayIndex(v
->index
);
1011 SlObject(v
->current_order
.extra
.get(), GetOrderExtraInfoDescription());
1018 /* load extended order info for vehicle current order */
1020 while ((index
= SlIterateArray()) != -1) {
1021 Vehicle
*v
= Vehicle::GetIfValid(index
);
1023 v
->current_order
.AllocExtraInfo();
1024 SlObject(v
->current_order
.extra
.get(), GetOrderExtraInfoDescription());
1028 extern const ChunkHandler _veh_chunk_handlers
[] = {
1029 { 'VEHS', Save_VEHS
, Load_VEHS
, Ptrs_VEHS
, NULL
, CH_SPARSE_ARRAY
},
1030 { 'VEOX', Save_VEOX
, Load_VEOX
, NULL
, NULL
, CH_SPARSE_ARRAY
| CH_LAST
},