OpenTTD Source 20260917-master-gec444f7315
vehicle_sl.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "../stdafx.h"
11
12#include "saveload.h"
14
15#include "../debug.h"
16#include "../vehicle_func.h"
17#include "../train.h"
18#include "../roadveh.h"
19#include "../ship.h"
20#include "../aircraft.h"
21#include "../timetable.h"
22#include "../station_base.h"
24#include "../company_base.h"
25#include "../company_func.h"
26#include "../disaster_vehicle.h"
27#include "../economy_base.h"
28
29#include "../safeguards.h"
30
36{
37 for (Train *v : Train::Iterate()) {
38 v->other_multiheaded_part = nullptr;
39 }
40
41 for (Train *v : Train::Iterate()) {
42 if (v->IsFrontEngine() || v->IsFreeWagon()) {
43 /* Two ways to associate multiheaded parts to each other:
44 * sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
45 * bracket-matching: Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
46 *
47 * Note: Old savegames might contain chains which do not comply with these rules, e.g.
48 * - the front and read parts have invalid orders
49 * - different engine types might be combined
50 * - there might be different amounts of front and rear parts.
51 *
52 * Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
53 * This is why two matching strategies are needed.
54 */
55
56 bool sequential_matching = v->IsFrontEngine();
57
58 for (Train *u = v; u != nullptr; u = u->GetNextVehicle()) {
59 if (u->other_multiheaded_part != nullptr) continue; // we already linked this one
60
61 if (u->IsMultiheaded()) {
62 if (!u->IsEngine()) {
63 /* we got a rear car without a front car. We will convert it to a front one */
64 u->SetEngine();
65 u->spritenum--;
66 }
67
68 /* Find a matching back part */
69 EngineID eid = u->engine_type;
70 Train *w;
71 if (sequential_matching) {
72 for (w = u->GetNextVehicle(); w != nullptr; w = w->GetNextVehicle()) {
73 if (w->engine_type != eid || w->other_multiheaded_part != nullptr || !w->IsMultiheaded()) continue;
74
75 /* we found a car to partner with this engine. Now we will make sure it face the right way */
76 if (w->IsEngine()) {
77 w->ClearEngine();
78 w->spritenum++;
79 }
80 break;
81 }
82 } else {
83 uint stack_pos = 0;
84 for (w = u->GetNextVehicle(); w != nullptr; w = w->GetNextVehicle()) {
85 if (w->engine_type != eid || w->other_multiheaded_part != nullptr || !w->IsMultiheaded()) continue;
86
87 if (w->IsEngine()) {
88 stack_pos++;
89 } else {
90 if (stack_pos == 0) break;
91 stack_pos--;
92 }
93 }
94 }
95
96 if (w != nullptr) {
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 == RailVehicleType::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;
138 /* normal wagon */
139 u->SetWagon();
140 break;
141 }
142 if (rvi->railveh_type == RailVehicleType::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 == RailVehicleType::Multihead) u->SetMultiheaded();
148 u->SetEngine();
149 break;
150
151 case 4: // TS_Free_Car
152 u->subtype = 0;
153 u->SetWagon();
154 u->SetFreeWagon();
155 break;
156 default: SlErrorCorrupt("Invalid train subtype");
157 }
158 }
159 }
160 }
161}
162
163
166{
167 /* set airport_flags to 0 for all airports just to be sure */
168 for (Station *st : Station::Iterate()) {
169 st->airport.blocks = {}; // reset airport
170 }
171
172 for (Aircraft *a : Aircraft::Iterate()) {
173 /* airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor)
174 * skip those */
175 if (a->IsNormalAircraft()) {
176 /* airplane in terminal stopped doesn't hurt anyone, so goto next */
177 if (a->vehstatus.Test(VehState::Stopped) && a->state == 0) {
178 a->state = HANGAR;
179 continue;
180 }
181
182 AircraftLeaveHangar(a, a->direction); // make airplane visible if it was in a depot for example
183 a->vehstatus.Reset(VehState::Stopped); // make airplane moving
185 a->cur_speed = a->vcache.cached_max_speed; // so aircraft don't have zero speed while in air
186 if (!a->current_order.IsType(OT_GOTO_STATION) && !a->current_order.IsType(OT_GOTO_DEPOT)) {
187 /* reset current order so aircraft doesn't have invalid "station-only" order */
188 a->current_order.MakeDummy();
189 }
190 a->state = FLYING;
191 AircraftNextAirportPos_and_Order(a); // move it to the entry point of the airport
193 a->tile = TileIndex{}; // aircraft in air is tile=0
194
195 /* correct speed of helicopter-rotors */
196 if (a->subtype == AIR_HELICOPTER) a->Next()->Next()->cur_speed = 32;
197
198 /* set new position x,y,z */
199 GetAircraftFlightLevelBounds(a, &a->z_pos, nullptr);
200 SetAircraftPosition(a, gp.x, gp.y, GetAircraftFlightLevel(a));
201 }
202 }
203
204 /* Clear aircraft from loading vehicles, if we bumped them into the air. */
205 for (Station *st : Station::Iterate()) {
206 for (auto iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); /* nothing */) {
207 Vehicle *v = *iter;
208 if (v->type == VehicleType::Aircraft && !v->current_order.IsType(OT_LOADING)) {
209 iter = st->loading_vehicles.erase(iter);
210 delete v->cargo_payment;
211 } else {
212 ++iter;
213 }
214 }
215 }
216}
217
226{
227 size_t total_engines = Engine::GetPoolSize();
228 VehicleTypeIndexArray<EngineID> first_engine = { EngineID::Invalid(), EngineID::Invalid(), EngineID::Invalid(), EngineID::Invalid() };
229
230 for (const Engine *e : Engine::IterateType(VehicleType::Train)) { first_engine[VehicleType::Train] = e->index; break; }
231 for (const Engine *e : Engine::IterateType(VehicleType::Road)) { first_engine[VehicleType::Road] = e->index; break; }
232 for (const Engine *e : Engine::IterateType(VehicleType::Ship)) { first_engine[VehicleType::Ship] = e->index; break; }
233 for (const Engine *e : Engine::IterateType(VehicleType::Aircraft)) { first_engine[VehicleType::Aircraft] = e->index; break; }
234
235 for (Vehicle *v : Vehicle::Iterate()) {
236 /* Test if engine types match */
237 switch (v->type) {
242 if (v->engine_type >= total_engines || v->type != v->GetEngine()->type) {
243 v->engine_type = first_engine[v->type];
244 }
245 break;
246
247 default:
248 break;
249 }
250 }
251}
252
253extern uint8_t _age_cargo_skip_counter; // From misc_sl.cpp
254
259void AfterLoadVehiclesPhase1(bool part_of_load)
260{
261 for (Vehicle *v : Vehicle::Iterate()) {
262 /* Reinstate the previous pointer */
263 if (v->Next() != nullptr) v->Next()->previous = v;
264 if (v->NextShared() != nullptr) v->NextShared()->previous_shared = v;
265
266 if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID;
267 v->first = nullptr;
268 v->last = nullptr;
269 if (v->IsGroundVehicle()) v->GetGroundVehicleCache()->first_engine = EngineID::Invalid();
270 }
271
272 /* AfterLoadVehicles may also be called in case of NewGRF reload, in this
273 * case we may not convert orders again. */
274 if (part_of_load) {
275 /* Create shared vehicle chain for very old games (pre 5,2) and create
276 * OrderList from shared vehicle chains. For this to work correctly, the
277 * following conditions must be fulfilled:
278 * a) both next_shared and previous_shared are not set for pre 5,2 games
279 * b) both next_shared and previous_shared are set for later games
280 */
281 std::map<uint32_t, OrderList *> mapping;
282
283 for (Vehicle *v : Vehicle::Iterate()) {
284 if (v->orders != nullptr) {
285 if (IsSavegameVersionBefore(SaveLoadVersion::OrderList)) { // Pre-105 didn't save an OrderList
286 if (mapping[v->old_orders] == nullptr) {
287 /* This adds the whole shared vehicle chain for case b */
288
289 /* Creating an OrderList here is safe because the number of vehicles
290 * allowed in these savegames matches the number of OrderLists. As
291 * such each vehicle can get an OrderList and it will (still) fit. */
293 std::vector<Order> orders;
294 for (const OldOrderSaveLoadItem *old_order = GetOldOrder(v->old_orders); old_order != nullptr; old_order = GetOldOrder(old_order->next)) {
295 orders.push_back(std::move(old_order->order));
296 }
297 v->orders = mapping[v->old_orders] = OrderList::Create(std::move(orders), v);
298 } else {
299 v->orders = mapping[v->old_orders];
300 /* For old games (case a) we must create the shared vehicle chain */
302 v->AddToShared(v->orders->GetFirstSharedVehicle());
303 }
304 }
305 } else { // OrderList was saved as such, only recalculate not saved values
306 if (v->PreviousShared() == nullptr) {
307 v->orders->Initialize(v);
308 }
309 }
310 }
311 }
312 }
313
314 for (Vehicle *v : Vehicle::Iterate()) {
315 /* Fill the first pointers. */
316 if (v->Previous() == nullptr) {
317 for (Vehicle *u = v; u != nullptr; u = u->Next()) {
318 u->first = v;
319 }
320 }
321
322 /* Fill the last pointers. */
323 if (v->Next() == nullptr) {
324 for (Vehicle *u = v; u != nullptr; u = u->Previous()) {
325 u->last = v;
326 }
327 }
328 }
329
330 if (part_of_load) {
332 /* Before 105 there was no order for shared orders, thus it messed up horribly */
333 for (Vehicle *v : Vehicle::Iterate()) {
334 if (v->First() != v || v->orders != nullptr || v->previous_shared != nullptr || v->next_shared == nullptr) continue;
335
336 /* As above, allocating OrderList here is safe. */
338 v->orders = OrderList::Create();
339 v->orders->first_shared = v;
340 for (Vehicle *u = v; u != nullptr; u = u->next_shared) {
341 u->orders = v->orders;
342 }
343 }
344 }
345
347 /* The road vehicle subtype was converted to a flag. */
348 for (RoadVehicle *rv : RoadVehicle::Iterate()) {
349 if (rv->subtype == 0) {
350 /* The road vehicle is at the front. */
351 rv->SetFrontEngine();
352 } else if (rv->subtype == 1) {
353 /* The road vehicle is an articulated part. */
354 rv->subtype = 0;
355 rv->SetArticulatedPart();
356 } else {
357 SlErrorCorrupt("Invalid road vehicle subtype");
358 }
359 }
360 }
361
363 /* In some old savegames there might be some "crap" stored. */
364 for (Vehicle *v : Vehicle::Iterate()) {
365 if (!v->IsPrimaryVehicle() && v->type != VehicleType::Disaster) {
366 v->current_order.Free();
367 v->unitnumber = 0;
368 }
369 }
370 }
371
373 /* Set the vehicle-local cargo age counter from the old global counter. */
374 for (Vehicle *v : Vehicle::Iterate()) {
375 v->cargo_age_counter = _age_cargo_skip_counter;
376 }
377 }
378
380 /* Set service interval flags */
381 for (Vehicle *v : Vehicle::Iterate()) {
382 if (!v->IsPrimaryVehicle()) continue;
383
384 const Company *c = Company::Get(v->owner);
385 int interval = CompanyServiceInterval(c, v->type);
386
387 v->SetServiceIntervalIsCustom(v->GetServiceInterval() != interval);
388 v->SetServiceIntervalIsPercent(c->settings.vehicle.servint_ispercent);
389 }
390 }
391
393 /* Ship rotation added */
394 for (Ship *s : Ship::Iterate()) {
395 s->rotation = s->direction;
396 }
397 } else {
398 for (Ship *s : Ship::Iterate()) {
399 if (s->rotation == s->direction) continue;
400 /* In case we are rotating on gameload, set the rotation position to
401 * the current position, otherwise the applied workaround offset would
402 * be with respect to 0,0.
403 */
404 s->rotation_x_pos = s->x_pos;
405 s->rotation_y_pos = s->y_pos;
406 }
407 }
408
410 /* Convert timetable start from a date to an absolute tick in TimerGameTick::counter. */
411 for (Vehicle *v : Vehicle::Iterate()) {
412 /* If the start date is 0, the vehicle is not waiting to start and can be ignored. */
413 if (v->timetable_start == 0) continue;
414
415 v->timetable_start = GetStartTickFromDate(TimerGameEconomy::Date(v->timetable_start));
416 }
417 }
418
420 /* Set vehicle economy age based on calendar age. */
421 for (Vehicle *v : Vehicle::Iterate()) {
422 v->economy_age = TimerGameEconomy::Date{v->age.base()};
423 }
424 }
425 }
426
428}
429
434void AfterLoadVehiclesPhase2(bool part_of_load)
435{
436 for (Vehicle *v : Vehicle::Iterate()) {
437 assert(v->First() != nullptr);
438
439 v->trip_occupancy = CalcPercentVehicleFilled(v, nullptr);
440
441 switch (v->type) {
442 case VehicleType::Train: {
443 Train *t = Train::From(v);
444 if (t->IsFrontEngine() || t->IsFreeWagon()) {
445 t->gcache.last_speed = t->cur_speed; // update displayed train speed
447 }
448 break;
449 }
450
451 case VehicleType::Road: {
453 if (rv->IsFrontEngine()) {
454 rv->gcache.last_speed = rv->cur_speed; // update displayed road vehicle speed
455
456 rv->roadtype = Engine::Get(rv->engine_type)->VehInfo<RoadVehicleInfo>().roadtype;
458 RoadTramType rtt = GetRoadTramType(rv->roadtype);
459 for (RoadVehicle *u = rv; u != nullptr; u = u->Next()) {
460 u->roadtype = rv->roadtype;
461 u->compatible_roadtypes = rv->compatible_roadtypes;
462 if (GetRoadType(u->tile, rtt) == INVALID_ROADTYPE) SlErrorCorrupt("Road vehicle on invalid road type");
463 }
464
466 if (_settings_game.vehicle.roadveh_acceleration_model != AccelerationModel::Original) {
467 rv->CargoChanged();
468 }
469 }
470 break;
471 }
472
475 break;
476
477 default: break;
478 }
479 }
480
481 /* Stop non-front engines */
483 for (Vehicle *v : Vehicle::Iterate()) {
484 if (v->type == VehicleType::Train) {
485 Train *t = Train::From(v);
486 if (!t->IsFrontEngine()) {
488 /* cur_speed is now relevant for non-front parts - nonzero breaks
489 * moving-wagons-inside-depot- and autoreplace- code */
490 t->cur_speed = 0;
491 }
492 }
493 /* trains weren't stopping gradually in old OTTD versions (and TTO/TTD)
494 * other vehicle types didn't have zero speed while stopped (even in 'recent' OTTD versions) */
496 v->cur_speed = 0;
497 }
498 }
499 }
500
501 for (Vehicle *v : Vehicle::Iterate()) {
502 switch (v->type) {
506 v->GetImage(v->direction, EngineImageType::OnMap, &v->sprite_cache.sprite_seq);
507 break;
508
510 if (Aircraft::From(v)->IsNormalAircraft()) {
511 v->GetImage(v->direction, EngineImageType::OnMap, &v->sprite_cache.sprite_seq);
512
513 /* The aircraft's shadow will have the same image as the aircraft, but no colour */
514 Vehicle *shadow = v->Next();
515 if (shadow == nullptr) SlErrorCorrupt("Missing shadow for aircraft");
516
517 shadow->sprite_cache.sprite_seq.CopyWithoutPalette(v->sprite_cache.sprite_seq);
518
519 /* In the case of a helicopter we will update the rotor sprites */
520 if (v->subtype == AIR_HELICOPTER) {
521 Vehicle *rotor = shadow->Next();
522 if (rotor == nullptr) SlErrorCorrupt("Missing rotor for helicopter");
523
525 }
526
528 }
529 break;
530
532 auto *dv = DisasterVehicle::From(v);
533 if (dv->subtype == ST_SMALL_UFO && dv->state != 0) {
534 RoadVehicle *u = RoadVehicle::GetIfValid(v->dest_tile.base());
535 if (u != nullptr && u->IsFrontEngine()) {
536 /* Delete UFO targetting a vehicle which is already a target. */
537 if (u->disaster_vehicle != VehicleID::Invalid() && u->disaster_vehicle != dv->index) {
538 delete v;
539 continue;
540 } else {
541 u->disaster_vehicle = dv->index;
542 }
543 }
544 }
545 break;
546 }
547
548 default: break;
549 }
550
551 if (part_of_load && v->unitnumber != 0) {
552 Company::Get(v->owner)->freeunits[v->type].UseID(v->unitnumber);
553 }
554
555 v->UpdateDeltaXY();
556 v->coord.left = INVALID_COORD;
557 v->sprite_cache.old_coord.left = INVALID_COORD;
558 if (v->type != VehicleType::Effect) v->UpdatePosition();
559 v->UpdateViewport(false);
560 }
561}
562
563bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // From train_cmd.cpp
565
568{
569 /* Vehicle center was moved from 4 units behind the front to half the length
570 * behind the front. Move vehicles so they end up on the same spot. */
571 for (Vehicle *v : Vehicle::Iterate()) {
572 if (v->type == VehicleType::Train && v->IsPrimaryVehicle()) {
573 /* The vehicle center is now more to the front depending on vehicle length,
574 * so we need to move all vehicles forward to cover the difference to the
575 * old center, otherwise wagon spacing in trains would be broken upon load. */
576 for (Train *u = Train::From(v); u != nullptr; u = u->Next()) {
577 if (u->track == Track::Depot || u->vehstatus.Test(VehState::Crashed)) continue;
578
579 Train *next = u->Next();
580
581 /* Try to pull the vehicle half its length forward. */
582 int diff = (VEHICLE_LENGTH - u->gcache.cached_veh_length) / 2;
583 int done;
584 for (done = 0; done < diff; done++) {
585 if (!TrainController(u, next, false)) break;
586 }
587
588 if (next != nullptr && done < diff && u->IsFrontEngine()) {
589 /* Pulling the front vehicle forwards failed, we either encountered a dead-end
590 * or a red signal. To fix this, we try to move the whole train the required
591 * space backwards and re-do the fix up of the front vehicle. */
592
593 /* Ignore any signals when backtracking. */
594 TrainForceProceeding old_tfp = u->force_proceed;
595 u->force_proceed = TFP_SIGNAL;
596
597 /* Swap start<>end, start+1<>end-1, ... */
599
600 /* We moved the first vehicle which is now the last. Move it back to the
601 * original position as we will fix up the last vehicle later in the loop. */
602 for (int i = 0; i < done; i++) TrainController(u->Last(), nullptr);
603
604 /* Move the train backwards to get space for the first vehicle. As the stopping
605 * distance from a line end is rounded up, move the train one unit more to cater
606 * for front vehicles with odd lengths. */
607 int moved;
608 for (moved = 0; moved < diff + 1; moved++) {
609 if (!TrainController(u, nullptr, false)) break;
610 }
611
612 /* Swap start<>end, start+1<>end-1, ... again. */
614
615 u->force_proceed = old_tfp;
616
617 /* Tracks are too short to fix the train length. The player has to fix the
618 * train in a depot. Bail out so we don't damage the vehicle chain any more. */
619 if (moved < diff + 1) break;
620
621 /* Re-do the correction for the first vehicle. */
622 for (done = 0; done < diff; done++) TrainController(u, next, false);
623
624 /* We moved one unit more backwards than needed for even-length front vehicles,
625 * try to move that unit forward again. We don't care if this step fails. */
626 TrainController(u, nullptr, false);
627 }
628
629 /* If the next wagon is still in a depot, check if it shouldn't be outside already. */
630 if (next != nullptr && next->track == Track::Depot) {
631 int d = TicksToLeaveDepot(u);
632 if (d <= 0) {
633 /* Next vehicle should have left the depot already, show it and pull forward. */
635 next->track = GetRailDepotTrack(next->tile);
636 for (int i = 0; i >= d; i--) TrainController(next, nullptr);
637 }
638 }
639 }
640
641 /* Update all cached properties after moving the vehicle chain around. */
643 }
644 }
645}
646
647static uint8_t _cargo_periods;
648static StationID _cargo_source;
649static TileIndex _cargo_source_xy;
650static uint16_t _cargo_count;
651static uint16_t _cargo_paid_for;
652static Money _cargo_feeder_share;
653
654class SlVehicleCommon : public DefaultSaveLoadHandler<SlVehicleCommon, Vehicle> {
655public:
656 static inline const SaveLoad description[] = {
658
669
677
682 SaveLoad::Variable<VarFileType::U8>("acceleration", SLE_OBJECT_ADDRESS(Vehicle, acceleration)),
685
688 SaveLoad::Variable<VarFileType::U16>("last_station_visited", SLE_OBJECT_ADDRESS(Vehicle, last_station_visited), SaveLoadVersion::BigMap),
690
703
705 SaveLoad::Variable<VarFileType::U8>("tick_counter", SLE_OBJECT_ADDRESS(Vehicle, tick_counter)),
707
708 SaveLoad::Variable<VarFileType::U8>("cur_implicit_order_index", SLE_OBJECT_ADDRESS(Vehicle, cur_implicit_order_index)),
710
711 /* This next line is for version 4 and prior compatibility.. it temporarily reads
712 type and flags (which were both 4 bits) into type. Later on this is
713 converted correctly */
716
717 /* Orders for version 5 and on */
719 SaveLoad::Variable<VarFileType::U8>("current_order.flags", SLE_OBJECT_ADDRESS(Vehicle, current_order.flags), SaveLoadVersion::BigMap),
721
722 /* Refit in current order */
723 SaveLoad::Variable<VarFileType::U8>("current_order.refit_cargo", SLE_OBJECT_ADDRESS(Vehicle, current_order.refit_cargo), SaveLoadVersion::RefitOrders),
724
725 /* Timetable in current order */
726 SaveLoad::Variable<VarFileType::U16>("current_order.wait_time", SLE_OBJECT_ADDRESS(Vehicle, current_order.wait_time), SaveLoadVersion::Timetables),
727 SaveLoad::Variable<VarFileType::U16>("current_order.travel_time", SLE_OBJECT_ADDRESS(Vehicle, current_order.travel_time), SaveLoadVersion::Timetables),
731
735
742 SaveLoad::Variable<VarFileType::I32>("date_of_last_service", SLE_OBJECT_ADDRESS(Vehicle, date_of_last_service), SaveLoadVersion::BigDates),
743 SaveLoad::Variable<VarFileType::I32>("date_of_last_service_newgrf", SLE_OBJECT_ADDRESS(Vehicle, date_of_last_service_newgrf), SaveLoadVersion::NewGRFLastService),
748 SaveLoad::Variable<VarFileType::U16>("reliability_spd_dec", SLE_OBJECT_ADDRESS(Vehicle, reliability_spd_dec)),
749 SaveLoad::Variable<VarFileType::U8>("breakdown_ctr", SLE_OBJECT_ADDRESS(Vehicle, breakdown_ctr)),
750 SaveLoad::Variable<VarFileType::U8>("breakdown_delay", SLE_OBJECT_ADDRESS(Vehicle, breakdown_delay)),
751 SaveLoad::Variable<VarFileType::U8>("breakdowns_since_last_service", SLE_OBJECT_ADDRESS(Vehicle, breakdowns_since_last_service)),
752 SaveLoad::Variable<VarFileType::U8>("breakdown_chance", SLE_OBJECT_ADDRESS(Vehicle, breakdown_chance)),
755
756 SaveLoad::Variable<VarFileType::U16>("load_unload_ticks", SLE_OBJECT_ADDRESS(Vehicle, load_unload_ticks)),
760
769
773
776
781
782 SaveLoad::Variable<VarFileType::U64>("depot_unbunching_last_departure", SLE_OBJECT_ADDRESS(Vehicle, depot_unbunching_last_departure), SaveLoadVersion::DepotUnbunching),
783 SaveLoad::Variable<VarFileType::U64>("depot_unbunching_next_departure", SLE_OBJECT_ADDRESS(Vehicle, depot_unbunching_next_departure), SaveLoadVersion::DepotUnbunching),
785 };
786
787 static inline const SaveLoadCompatTable compat_description = _vehicle_common_sl_compat;
788
789 void Save(Vehicle *v) const override
790 {
791 SlObject(v, this->GetDescription());
792 }
793
794 void Load(Vehicle *v) const override
795 {
796 SlObject(v, this->GetLoadDescription());
797 }
798
799 void FixPointers(Vehicle *v) const override
800 {
801 SlObject(v, this->GetDescription());
802 }
803};
804
805class SlVehicleTrain : public DefaultSaveLoadHandler<SlVehicleTrain, Vehicle> {
806public:
807 static inline const SaveLoad description[] = {
809 SaveLoad::Variable<VarFileType::U16>("crash_anim_pos", SLE_OBJECT_ADDRESS(Train, crash_anim_pos)),
810 SaveLoad::Variable<VarFileType::U8>("force_proceed", SLE_OBJECT_ADDRESS(Train, force_proceed)),
812
817 };
818 static inline const SaveLoadCompatTable compat_description = _vehicle_train_sl_compat;
819
820 void Save(Vehicle *v) const override
821 {
822 if (v->type != VehicleType::Train) return;
823 SlObject(v, this->GetDescription());
824 }
825
826 void Load(Vehicle *v) const override
827 {
828 if (v->type != VehicleType::Train) return;
829 SlObject(v, this->GetLoadDescription());
830 }
831
832 void FixPointers(Vehicle *v) const override
833 {
834 if (v->type != VehicleType::Train) return;
835 SlObject(v, this->GetDescription());
836 }
837};
838
839class SlVehicleRoadVehPath : public VectorSaveLoadHandler<SlVehicleRoadVehPath, RoadVehicle, RoadVehPathElement> {
840public:
841 static inline const SaveLoad description[] = {
844 };
845 static inline const SaveLoadCompatTable compat_description = {};
846
847 std::vector<RoadVehPathElement> &GetVector(RoadVehicle *rv) const override { return rv->path; }
848};
849
850class SlVehicleRoadVeh : public DefaultSaveLoadHandler<SlVehicleRoadVeh, Vehicle> {
851public:
854 static inline std::vector<Trackdir> rv_path_td;
855 static inline std::vector<TileIndex> rv_path_tile;
857
858 static inline const SaveLoad description[] = {
864 SaveLoad::Variable<VarFileType::U8>("overtaking_ctr", SLE_OBJECT_ADDRESS(RoadVehicle, overtaking_ctr)),
871 };
872 static inline const SaveLoadCompatTable compat_description = _vehicle_roadveh_sl_compat;
873
874 static void ConvertPathCache(RoadVehicle &rv)
875 {
876 /* The two vectors should be the same size, but if not we can just ignore the cache and not cause more issues. */
877 if (rv_path_td.size() != rv_path_tile.size()) {
878 Debug(Facility::Sl, Severity::Error, "Found RoadVehicle {} with invalid path cache, ignoring.", rv.index);
879 return;
880 }
881 size_t n = std::min(rv_path_td.size(), rv_path_tile.size());
882 if (n == 0) return;
883
884 rv.path.reserve(n);
885 for (size_t c = 0; c < n; ++c) {
886 rv.path.emplace_back(rv_path_td[c], rv_path_tile[c]);
887 }
888
889 /* Path cache is now taken from back instead of front, so needs reversing. */
890 std::reverse(std::begin(rv.path), std::end(rv.path));
891 }
892
893 void Save(Vehicle *v) const override
894 {
895 if (v->type != VehicleType::Road) return;
896 SlObject(v, this->GetDescription());
897 }
898
899 void Load(Vehicle *v) const override
900 {
901 if (v->type != VehicleType::Road) return;
902 SlObject(v, this->GetLoadDescription());
904 ConvertPathCache(*static_cast<RoadVehicle *>(v));
905 }
906 }
907
908 void FixPointers(Vehicle *v) const override
909 {
910 if (v->type != VehicleType::Road) return;
911 SlObject(v, this->GetDescription());
912 }
913};
914
915class SlVehicleShipPath : public VectorSaveLoadHandler<SlVehicleShipPath, Ship, ShipPathElement> {
916public:
917 static inline const SaveLoad description[] = {
919 };
920 static inline const SaveLoadCompatTable compat_description = {};
921
922 std::vector<ShipPathElement> &GetVector(Ship *s) const override { return s->path; }
923};
924
925class SlVehicleShip : public DefaultSaveLoadHandler<SlVehicleShip, Vehicle> {
926public:
927 static inline std::vector<Trackdir> ship_path_td;
928
929 static inline const SaveLoad description[] = {
936 };
937 static inline const SaveLoadCompatTable compat_description = _vehicle_ship_sl_compat;
938
939 void Save(Vehicle *v) const override
940 {
941 if (v->type != VehicleType::Ship) return;
942 SlObject(v, this->GetDescription());
943 }
944
945 void Load(Vehicle *v) const override
946 {
947 if (v->type != VehicleType::Ship) return;
948 SlObject(v, this->GetLoadDescription());
949
951 /* Path cache is now taken from back instead of front, so needs reversing. */
952 Ship *s = static_cast<Ship *>(v);
953 std::transform(std::rbegin(ship_path_td), std::rend(ship_path_td), std::back_inserter(s->path), [](Trackdir trackdir) { return trackdir; });
954 }
955 }
956
957 void FixPointers(Vehicle *v) const override
958 {
959 if (v->type != VehicleType::Ship) return;
960 SlObject(v, this->GetDescription());
961 }
962};
963
964class SlVehicleAircraft : public DefaultSaveLoadHandler<SlVehicleAircraft, Vehicle> {
965public:
966 static inline const SaveLoad description[] = {
968 SaveLoad::Variable<VarFileType::U16>("crashed_counter", SLE_OBJECT_ADDRESS(Aircraft, crashed_counter)),
970
973
975
979
982 };
983 static inline const SaveLoadCompatTable compat_description = _vehicle_aircraft_sl_compat;
984
985 void Save(Vehicle *v) const override
986 {
987 if (v->type != VehicleType::Aircraft) return;
988 SlObject(v, this->GetDescription());
989 }
990
991 void Load(Vehicle *v) const override
992 {
993 if (v->type != VehicleType::Aircraft) return;
994 SlObject(v, this->GetLoadDescription());
995 }
996
997 void FixPointers(Vehicle *v) const override
998 {
999 if (v->type != VehicleType::Aircraft) return;
1000 SlObject(v, this->GetDescription());
1001 }
1002};
1003
1004class SlVehicleEffect : public DefaultSaveLoadHandler<SlVehicleEffect, Vehicle> {
1005public:
1006 static inline const SaveLoad description[] = {
1008
1011
1018
1019 SaveLoad::Variable<VarFileType::U16>("sprite_cache.sprite_seq.seq[0].sprite", SLE_OBJECT_ADDRESS(Vehicle, sprite_cache.sprite_seq.seq[0].sprite)),
1022
1023 SaveLoad::Variable<VarFileType::U16>("animation_state", SLE_OBJECT_ADDRESS(EffectVehicle, animation_state)),
1024 SaveLoad::Variable<VarFileType::U8>("animation_substate", SLE_OBJECT_ADDRESS(EffectVehicle, animation_substate)),
1025
1027 };
1028 static inline const SaveLoadCompatTable compat_description = _vehicle_effect_sl_compat;
1029
1030 void Save(Vehicle *v) const override
1031 {
1032 if (v->type != VehicleType::Effect) return;
1033 SlObject(v, this->GetDescription());
1034 }
1035
1036 void Load(Vehicle *v) const override
1037 {
1038 if (v->type != VehicleType::Effect) return;
1039 SlObject(v, this->GetLoadDescription());
1040 }
1041
1042 void FixPointers(Vehicle *v) const override
1043 {
1044 if (v->type != VehicleType::Effect) return;
1045 SlObject(v, this->GetDescription());
1046 }
1047};
1048
1049class SlVehicleDisaster : public DefaultSaveLoadHandler<SlVehicleDisaster, Vehicle> {
1050public:
1051 static inline const SaveLoad description[] = {
1053
1059
1067
1073
1074 SaveLoad::Variable<VarFileType::U16>("sprite_cache.sprite_seq.seq[0].sprite", SLE_OBJECT_ADDRESS(Vehicle, sprite_cache.sprite_seq.seq[0].sprite)),
1077 SaveLoad::Variable<VarFileType::U8>("tick_counter", SLE_OBJECT_ADDRESS(Vehicle, tick_counter)),
1078
1084 };
1085
1086 static inline const SaveLoadCompatTable compat_description = _vehicle_disaster_sl_compat;
1087
1088 void Save(Vehicle *v) const override
1089 {
1090 if (v->type != VehicleType::Disaster) return;
1091 SlObject(v, this->GetDescription());
1092 }
1093
1094 void Load(Vehicle *v) const override
1095 {
1096 if (v->type != VehicleType::Disaster) return;
1097 SlObject(v, this->GetLoadDescription());
1098 }
1099
1100 void FixPointers(Vehicle *v) const override
1101 {
1102 if (v->type != VehicleType::Disaster) return;
1103 SlObject(v, this->GetDescription());
1104 }
1105};
1106
1107static const SaveLoad _vehicle_desc[] = {
1115};
1116
1117struct VEHSChunkHandler : ChunkHandler {
1118 VEHSChunkHandler() : ChunkHandler("VEHS", ChunkType::SparseTable) {}
1119
1120 void Save() const override
1121 {
1122 SlTableHeader(_vehicle_desc);
1123
1124 /* Write the vehicles */
1125 for (Vehicle *v : Vehicle::Iterate()) {
1126 SlSetArrayIndex(v->index);
1127 SlObject(v, _vehicle_desc);
1128 }
1129 }
1130
1131 void Load() const override
1132 {
1133 const std::vector<SaveLoad> slt = SlCompatTableHeader(_vehicle_desc, _vehicle_sl_compat);
1134
1135 int index;
1136
1137 _cargo_count = 0;
1138
1139 while ((index = SlIterateArray()) != -1) {
1140 Vehicle *v;
1142
1143 switch (vtype) {
1144 case VehicleType::Train: v = Train::CreateAtIndex(VehicleID(index)); break;
1146 case VehicleType::Ship: v = Ship::CreateAtIndex(VehicleID(index)); break;
1150 case VehicleType::Invalid: // Savegame shouldn't contain invalid vehicles
1151 default: SlErrorCorrupt("Invalid vehicle type");
1152 }
1153
1154 SlObject(v, slt);
1155
1156 if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) {
1157 /* Don't construct the packet with station here, because that'll fail with old savegames */
1158 CargoPacket *cp = CargoPacket::Create(_cargo_count, _cargo_periods, _cargo_source, _cargo_source_xy, _cargo_feeder_share);
1159 v->cargo.Append(cp);
1160 }
1161
1162 /* Old savegames used 'last_station_visited = 0xFF' */
1164 v->last_station_visited = StationID::Invalid();
1165 }
1166
1168
1170 /* Convert the current_order.type (which is a mix of type and flags, because
1171 * in those versions, they both were 4 bits big) to type and flags */
1172 v->current_order.flags = GB(v->current_order.type, 4, 4);
1173 v->current_order.type &= 0x0F;
1174 }
1175
1176 /* Advanced vehicle lists got added */
1178 }
1179 }
1180
1181 void FixPointers() const override
1182 {
1183 for (Vehicle *v : Vehicle::Iterate()) {
1184 SlObject(v, _vehicle_desc);
1185 }
1186 }
1187};
1188
1189static const VEHSChunkHandler VEHS;
1190static const ChunkHandlerRef veh_chunk_handlers[] = {
1191 VEHS,
1192};
1193
1194extern const ChunkHandlerTable _veh_chunk_handlers(veh_chunk_handlers);
Base for aircraft.
void GetAircraftFlightLevelBounds(const Vehicle *v, int *min, int *max)
Get the 'flight level' bounds, in pixels from 'z_pos' 0 for a particular vehicle for normal flight si...
void AircraftNextAirportPos_and_Order(Aircraft *v)
Set the right pos when heading to other airports after takeoff.
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir)
Aircraft is about to leave the hangar.
void SetAircraftPosition(Aircraft *v, int x, int y, int z)
Set aircraft position.
@ AIR_HELICOPTER
an helicopter
Definition aircraft.h:29
void UpdateAircraftCache(Aircraft *v, bool update_range=false)
Update cached values of an aircraft.
@ HANGAR
Heading for hangar.
Definition airport.h:65
@ FLYING
Vehicle is flying in the air.
Definition airport.h:78
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
Default handler for saving/loading an object to/from disk.
Definition saveload.h:586
SaveLoadTable GetDescription() const override
Definition saveload.h:588
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition road.h:98
SaveLoadTable GetLoadDescription() const
Get the description for how to load the chunk.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Save(Vehicle *v) const override
Save the object to disk.
void Save(Vehicle *v) const override
Save the object to disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Load(Vehicle *v) const override
Load the object from disk.
void Save(Vehicle *v) const override
Save the object to disk.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Save(Vehicle *v) const override
Save the object to disk.
void Load(Vehicle *v) const override
Load the object from disk.
std::vector< RoadVehPathElement > & GetVector(RoadVehicle *rv) const override
Get instance of vector to load/save.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
static std::vector< TileIndex > rv_path_tile
static std::vector< Trackdir > rv_path_td
void Save(Vehicle *v) const override
Save the object to disk.
std::vector< ShipPathElement > & GetVector(Ship *s) const override
Get instance of vector to load/save.
void Load(Vehicle *v) const override
Load the object from disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Save(Vehicle *v) const override
Save the object to disk.
void FixPointers(Vehicle *v) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Load(Vehicle *v) const override
Load the object from disk.
void Save(Vehicle *v) const override
Save the object to disk.
StrongType::Typedef< int32_t, DateTag< struct Economy >, StrongType::Compare, StrongType::Integer > Date
Default handler for saving/loading a vector to/from disk.
Definition saveload.h:1341
void Append(CargoPacket *cp, MoveToAction action=MoveToAction::Keep)
Appends the given cargo packet.
Definition of stuff that is very close to a company, like the company struct itself.
int CompanyServiceInterval(const Company *c, VehicleType type)
Get the service interval for the given company and vehicle type.
Functions related to companies.
Functions related to debugging.
#define Debug(facility, severity, format_string,...)
Output a line of debugging information.
Definition debug.h:37
@ Sl
Saveload message facility.
Definition debug_type.h:39
@ Error
Error, but we are recovering.
Definition debug_type.h:16
All disaster vehicles.
@ ST_SMALL_UFO
Small UFO, tries to find a road vehicle to destroy.
Base classes related to the economy.
Base class for all effect vehicles.
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF > EngineID
Unique identification number of an engine.
Definition engine_type.h:26
@ Multihead
indicates a combination of two locomotives
Definition engine_type.h:33
@ Wagon
simple wagon, not motorized
Definition engine_type.h:34
static constexpr GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:18
uint8_t _age_cargo_skip_counter
Skip aging of cargo? Used before savegame version 162.
Definition misc_sl.cpp:83
OldOrderSaveLoadItem * GetOldOrder(size_t pool_index)
Get a pointer to an old order with the given reference index.
Definition order_sl.cpp:126
int TicksToLeaveDepot(const Train *v)
Compute number of ticks when next wagon will leave a depot.
Track GetRailDepotTrack(Tile t)
Returns the track of a depot, ignoring direction.
Definition rail_map.h:182
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:217
RoadType GetRoadType(Tile t, RoadTramType rtt)
Get the road type for the given RoadTramType.
Definition road_map.h:175
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:29
RoadTramType
The different types of road type.
Definition road_type.h:38
Road vehicle states.
void RoadVehUpdateCache(RoadVehicle *v, bool same_length=false)
Update the cache of a road vehicle.
A number of safeguards to prevent using unsafe methods.
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition saveload.cpp:745
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition saveload.cpp:369
uint8_t SlReadByte()
Wrapper for reading a byte from the buffer.
Definition saveload.cpp:410
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Functions/types related to saving and loading games.
#define SLE_OBJECT_ADDRESS(base, variable)
Macro to be able to pass the variable type and construct the SaveLoad::AddressFunction given a base c...
Definition saveload.h:754
#define SLE_GLOBAL_ADDRESS(variable)
Macro to be able to pass the variable type and construct the SaveLoad::AddressFunction given a global...
Definition saveload.h:761
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition saveload.h:513
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition saveload.h:516
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition saveload.h:519
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition saveload.h:1226
@ LastLoadingTick
Saveload version: 301, GitHub pull request: 9693 Store tick of last loading for vehicles.
Definition saveload.h:347
@ BigDates
Saveload version: 31, SVN revision: 5999 Change date from 1920 - 2090 to 0 - 5 000 000.
Definition saveload.h:87
@ FractionProfitRunningTicks
Saveload version: 88, SVN revision: 12134 Store vehicle profits as a (fixed point) fraction,...
Definition saveload.h:155
@ VehicleEconomyAge
Saveload version: 334, GitHub pull request: 12141, release: 14.0 Add vehicle age in economy year,...
Definition saveload.h:386
@ GoalProgressPlaneAcceleration
Saveload version: 182, SVN revision: 25115, r25259, r25296 Goal status and plane acceleration fixes.
Definition saveload.h:268
@ LiveryRefit
Saveload version: 35, SVN revision: 6602 NewGRF livery refits.
Definition saveload.h:92
@ CountPaidForCargo
Saveload version: 45, SVN revision: 8501 Count the amount of cargo that was paid for.
Definition saveload.h:104
@ UnifyCurrency
Saveload version: 65, SVN revision: 10210 Make all variables related to currency 64 bits.
Definition saveload.h:128
@ DisasterVehState
Saveload version: 312, GitHub pull request: 10798 Explicit storage of disaster vehicle state.
Definition saveload.h:360
@ CargoReservation
Saveload version: 181, SVN revision: 25012 Persist the reservation of cargo for vehicles instead of ...
Definition saveload.h:267
@ LargerUnitNumber
Saveload version: 8.0, SVN revision: 1786 Increase size of (vehicle) unit numbers.
Definition saveload.h:56
@ ReplaceCustomNameArray
Saveload version: 84, SVN revision: 11822 Replace single fixed size array of custom names,...
Definition saveload.h:150
@ OrderList
Saveload version: 105, SVN revision: 14803 Create separate order list objects for maintaining orders...
Definition saveload.h:176
@ PathCacheFormat
Saveload version: 346, GitHub pull request: 12345 Vehicle path cache format changed.
Definition saveload.h:401
@ VehicleCurrencyStationChanges
Saveload version: 2.0, release: 0.3.0 Adding vehicle state, larger currency size for statistics,...
Definition saveload.h:40
@ ShipPathCache
Saveload version: 203, GitHub pull request: 7072 Add path cache for ships.
Definition saveload.h:293
@ TrackRealAndAutoOrders
Saveload version: 158, SVN revision: 21933 Track which real and auto order is the current order.
Definition saveload.h:239
@ VehicleCentreAndZPos
Saveload version: 164, SVN revision: 23290 Vehicle centres are not fixed at 4/8 of the vehicle; chan...
Definition saveload.h:246
@ BigMap
Saveload version: 5.0, SVN revision: 1429 Making maps a different size than 256x256.
Definition saveload.h:50
@ LargerCargoSource
Saveload version: 7.0, SVN revision: 1770 With more stations, the size of the cargo source needed to...
Definition saveload.h:55
@ NewGRFLastService
Saveload version: 317, GitHub pull request: 11124 Added stable date_of_last_service to avoid NewGRF ...
Definition saveload.h:366
@ MoreCargoPackets
Saveload version: 69, SVN revision: 10319 Allow more than ~65k cargo packets.
Definition saveload.h:132
@ LinkgraphLocationDisasterStore
Saveload version: 191, SVN revision: 26636, 26646 Fix disaster vehicle storage, Linkgraph - store lo...
Definition saveload.h:279
@ RoadvehPathCache
Saveload version: 211, GitHub pull request: 7261 Add path cache for road vehicles.
Definition saveload.h:303
@ RefitOrders
Saveload version: 36, SVN revision: 6624 Vehicles can be refitted as part of an order.
Definition saveload.h:93
@ UnifyGroundVehicles
Saveload version: 157, SVN revision: 21862 Unify the way ground vehicles are handled (articulated pa...
Definition saveload.h:238
@ CargoSourceTile
Saveload version: 44, SVN revision: 8144 Store the source tile of the cargo, so accurate payment can...
Definition saveload.h:102
@ VehMotionCounter
Saveload version: 288, GitHub pull request: 8591 Desync safe motion counter.
Definition saveload.h:331
@ TimetableStartTicks
Saveload version: 321, GitHub pull request: 11468 Convert timetable start from a date to ticks.
Definition saveload.h:371
@ CurrentOrderMaxSpeed
Saveload version: 174, SVN revision: 23973, release: 1.2.x Save maximum speed of current order.
Definition saveload.h:258
@ MultipleRoadStops
Saveload version: 6.0, SVN revision: 1721 Multi tile road stops, and some map size related fixes.
Definition saveload.h:53
@ VehicleGroups
Saveload version: 60, SVN revision: 9874 Arbitrary grouping, by the player, of vehicles.
Definition saveload.h:122
@ ServiceIntervalPercent
Saveload version: 180, SVN revision: 24998, release: 1.3.x Service interval in percent or days store...
Definition saveload.h:266
@ NewGRFCustomCargoAging
Saveload version: 162, SVN revision: 22713 NewGRF influence on aging of cargo in vehicles.
Definition saveload.h:244
@ DisallowRoadReconstruction
Saveload version: 160, SVN revision: 21974, release: 1.1.x Setting to disallow road reconstruction.
Definition saveload.h:242
@ TimetableTicksType
Saveload version: 323, GitHub pull request: 11435 Convert timetable current order time to ticks.
Definition saveload.h:373
@ NewGRFAircraftRange
Saveload version: 167, SVN revision: 23504 NewGRF provided maximum aircraft range.
Definition saveload.h:250
@ ExtendVehicleRandom
Saveload version: 310, GitHub pull request: 10701 Extend vehicle random bits.
Definition saveload.h:358
@ MinVersion
First savegame version.
Definition saveload.h:37
@ SplitLoadWaitCounters
Saveload version: 136, SVN revision: 18764 Split counters for (un)loading and signal waiting/turning...
Definition saveload.h:213
@ SplitHQ
Saveload version: 112, SVN revision: 15290 Split the behaviour of headquarters from the other unmova...
Definition saveload.h:184
@ FeederShare
Saveload version: 51, SVN revision: 8978 Rewrite of transfers to retain knowledge about the already ...
Definition saveload.h:111
@ DepotUnbunching
Saveload version: 331, GitHub pull request: 11945 Allow unbunching shared order vehicles at a depot.
Definition saveload.h:383
@ ShipRotation
Saveload version: 204, GitHub pull request: 7065 Add extra rotation stages for ships.
Definition saveload.h:294
@ Timetables
Saveload version: 67, SVN revision: 10236 Introduce timetables for vehicles.
Definition saveload.h:130
@ RvRealisticAcceleration
Saveload version: 139, SVN revision: 19346 Realistic acceleration of road vehicles.
Definition saveload.h:216
@ Yapp
Saveload version: 100, SVN revision: 13952 New version of path based signals.
Definition saveload.h:170
@ CargoPackets
Saveload version: 68, SVN revision: 10266 Account for individual units of cargo, i....
Definition saveload.h:131
@ MaxBridgeMapHeight
Saveload version: 194, SVN revision: 26881, release: 1.5 Setting for maximum bridge and map height.
Definition saveload.h:282
@ TimetableStart
Saveload version: 129, SVN revision: 18292 Allow setting the start date of a timetable.
Definition saveload.h:204
@ GradualLoading
Saveload version: 40, SVN revision: 7326 Gradual (un)loading of cargo.
Definition saveload.h:98
@ SparseTable
A SparseArray with a header describing the elements.
Definition saveload.h:451
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
Base for ships.
Base classes/functions for stations.
Definition of base types and functions in a cross-platform compatible way.
@ AllowControlCode
Allow the special control codes.
Definition string_type.h:47
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition aircraft.h:75
VehicleType type
Type of vehicle.
Container for cargo from the same location and time.
Definition cargopacket.h:41
ChunkHandler(ChunkId id, ChunkType type)
Create this ChunkHandler.
Definition saveload.h:470
CompanySettings settings
settings specific for each company
VehicleDefaultSettings vehicle
default settings for vehicles
Disasters, like submarines, skyrangers and their shadows, belong to this class.
A special vehicle is one of the following:
Position information of a vehicle after it moved.
int y
x and y position of the vehicle after moving
uint16_t last_speed
The last speed we did display, so we only have to redraw when this changes.
GroundVehicleCache gcache
Cache of often calculated values.
void CargoChanged()
Recalculates the cached weight of a vehicle and its parts.
bool IsEngine() const
Check if a vehicle is an engine (can be first in a consist).
bool IsMultiheaded() const
Check if the vehicle is a multiheaded engine.
bool IsFreeWagon() const
Check if the vehicle is a free wagon (got no engine in front of it).
void ClearEngine()
Clear engine status.
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Compatibility struct to allow saveload of pool-based orders.
Definition order_base.h:368
std::vector< Order > orders
Orders of the order list.
Definition order_base.h:395
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
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 Pool::IterateWrapper< Vehicle > Iterate(size_t from=0)
static T * CreateAtIndex(VehicleID index, Targs &&... args)
static Company * Get(auto index)
static Vehicle * GetIfValid(auto index)
Information about a rail vehicle.
Definition engine_type.h:74
RailVehicleType railveh_type
Type of rail vehicle.
Definition engine_type.h:76
Element of the RoadVehPathCache.
Definition roadveh.h:92
Information about a road vehicle.
Buses, trucks and trams belong to this class.
Definition roadveh.h:105
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition roadveh.h:117
RoadVehPathCache path
Cached path.
Definition roadveh.h:106
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition roadveh.h:115
VehicleID disaster_vehicle
NOSAVE: Disaster vehicle targetting this vehicle.
Definition roadveh.h:116
SaveLoad type struct.
Definition saveload.h:764
static SaveLoad StructList(std::string name, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a list of structs, optionally in some savegame versions.
Definition saveload.h:1103
static SaveLoad SaveByte(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a byte variable in some savegame versions that is not automatically read by the SaveLoad c...
Definition saveload.h:1125
static SaveLoad Variable(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion, size_t extra=0)
Storage of a variable in some savegame versions.
Definition saveload.h:926
static SaveLoad ReferenceList(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a list of references to pool elements in some savegame versions.
Definition saveload.h:1078
static SaveLoad Array(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion, size_t extra=0)
Storage of an array in some savegame versions.
Definition saveload.h:1026
static SaveLoad Vector(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a vector in some savegame versions.
Definition saveload.h:1053
static SaveLoad Reference(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a reference to a pool element in some savegame versions.
Definition saveload.h:951
static SaveLoad Struct(std::string name, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a structs, optionally in some savegame versions.
Definition saveload.h:1001
static SaveLoad String(std::string name, AddressFunction< T > address_func, StringValidationSettings string_validation_settings={}, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion, size_t extra=0)
Storage of a string in some savegame versions.
Definition saveload.h:977
Element of the ShipPathCache.
Definition ship.h:20
All ships have this type.
Definition ship.h:39
ShipPathCache path
Cached path.
Definition ship.h:40
void UpdateCache()
Update the caches of this ship.
Definition ship_cmd.cpp:237
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
T * Next() const
Get next vehicle in the chain.
static Train * From(Vehicle *v)
T * GetNextVehicle() const
Get the next real (non-articulated part) vehicle in the consist.
Station data structure.
'Train' is either a loco or a wagon.
Definition train.h:97
Train * other_multiheaded_part
Link between the two ends of a multiheaded engine.
Definition train.h:105
TrackBits track
On which track the train currently is.
Definition train.h:110
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
void FixPointers() const override
Fix the pointers.
void Load() const override
Load the chunk.
void Save() const override
Save the chunk.
bool servint_ispercent
service intervals are in percents
void CopyWithoutPalette(const VehicleSpriteSeq &src)
Copy data from another sprite sequence, while dropping all recolouring information.
Vehicle data structure.
CargoPayment * cargo_payment
The cargo payment we're currently in.
EngineID engine_type
The type of engine used for this vehicle.
VehicleCargoList cargo
The cargo this vehicle is carrying.
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
GroupID group_id
Index of group Pool array.
VehStates vehstatus
Status.
Order current_order
The current order (+ status, like: loading).
Vehicle * Next() const
Get the next vehicle of this vehicle.
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
uint16_t cur_speed
current speed
bool IsFrontEngine() const
Check if the vehicle is a front engine.
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
Vehicle * Previous() const
Get the previous vehicle of this vehicle.
TileIndex tile
Current tile index.
StationID last_station_visited
The last station we stopped at.
Vehicle * next_shared
pointer to the next vehicle that shares the order
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
Functions related to time tabling.
TimerGameTick::TickCounter GetStartTickFromDate(TimerGameEconomy::Date start_date)
Get the TimerGameTick::TickCounter tick of a given date.
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:63
@ Depot
Special flag indicating a vehicle is inside a depot.
Definition track_type.h:30
Base for the train class.
static constexpr ConsistChangeFlags CCF_TRACK
Valid changes while vehicle is driving, and possibly changing tracks.
Definition train.h:53
static constexpr ConsistChangeFlags CCF_SAVELOAD
Valid changes when loading a savegame. (Everything that is not stored in the save....
Definition train.h:58
TrainForceProceeding
Modes for ignoring signals.
Definition train.h:39
@ TFP_SIGNAL
Ignore next signal, after the signal ignore being stuck.
Definition train.h:42
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition vehicle.cpp:1803
uint8_t CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition vehicle.cpp:1504
@ Crashed
Vehicle is crashed.
@ Hidden
Vehicle is not visible.
@ Stopped
Vehicle is stopped by the player.
static const int32_t INVALID_COORD
Sentinel for an invalid coordinate.
Functions related to vehicles.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
void AfterLoadVehiclesPhase1(bool part_of_load)
Called after load for phase 1 of vehicle initialisation.
void FixupTrainLengths()
Fixup old train spacing.
void UpdateOldAircraft()
need to be called to load aircraft from old version
void ConvertOldMultiheadToNew()
Converts all trains to the new subtype format introduced in savegame 16.2 It also links multiheaded e...
void ReverseTrainSwapVehicles(Train *v)
Swap vehicles in chain starting from v, and reverse their direction.
bool TrainController(Train *v, Vehicle *nomove, bool reverse=true)
Move a vehicle chain one movement stop forwards.
void ConnectMultiheadedTrains()
Link front and rear multiheaded engines to each other This is done when loading a savegame.
void AfterLoadVehiclesPhase2(bool part_of_load)
Called after load for phase 2 of vehicle initialisation.
static void CheckValidVehicles()
Check all vehicles to ensure their engine type is valid for the currently loaded NewGRFs (that includ...
Loading of vehicle chunks before table headers were added.
const SaveLoadCompat _vehicle_train_sl_compat[]
Original field order for SlVehicleTrain.
const SaveLoadCompat _vehicle_disaster_sl_compat[]
Original field order for SlVehicleDisaster.
const SaveLoadCompat _vehicle_effect_sl_compat[]
Original field order for SlVehicleEffect.
const SaveLoadCompat _vehicle_ship_sl_compat[]
Original field order for SlVehicleShip.
const SaveLoadCompat _vehicle_sl_compat[]
Original field order for vehicle_desc.
const SaveLoadCompat _vehicle_roadveh_sl_compat[]
Original field order for SlVehicleRoadVeh.
const SaveLoadCompat _vehicle_common_sl_compat[]
Original field order for SlVehicleCommon.
const SaveLoadCompat _vehicle_aircraft_sl_compat[]
Original field order for SlVehicleAircraft.
@ OnMap
Vehicle drawn in viewport.
PoolID< uint32_t, struct VehicleIDTag, 0xFF000, 0xFFFFF > VehicleID
The type all our vehicle IDs have.
VehicleType
Available vehicle types.
@ Ship
Ship vehicle type.
@ Invalid
Non-existing type of vehicle.
@ Effect
Effect vehicle type (smoke, explosions, sparks, bubbles).
@ Aircraft
Aircraft vehicle type.
@ Road
Road vehicle type.
@ Disaster
Disaster vehicle type.
@ Train
Train vehicle type.
@ Original
Original acceleration model.
EnumIndexArray< T, VehicleType, Tend > VehicleTypeIndexArray
Array with VehicleType as index.
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.