OpenTTD Source 20250610-master-g8c90be8c9f
oldloader_sl.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "../stdafx.h"
11#include "../town.h"
12#include "../industry.h"
13#include "../company_func.h"
14#include "../aircraft.h"
15#include "../roadveh.h"
16#include "../ship.h"
17#include "../train.h"
18#include "../signs_base.h"
19#include "../station_base.h"
20#include "../subsidy_base.h"
21#include "../debug.h"
22#include "../depot_base.h"
23#include "../timer/timer_game_calendar.h"
24#include "../timer/timer_game_calendar.h"
25#include "../vehicle_func.h"
26#include "../effectvehicle_base.h"
27#include "../engine_func.h"
28#include "../company_base.h"
29#include "../disaster_vehicle.h"
30#include "../timer/timer.h"
31#include "../timer/timer_game_tick.h"
32#include "../timer/timer_game_calendar.h"
33#include "saveload_internal.h"
34#include "oldloader.h"
35
36#include "table/strings.h"
37#include "../table/engines.h"
38#include "../table/townname.h"
39
40#include "../safeguards.h"
41
43static uint16_t _old_extra_chunk_nums;
44
45void FixOldMapArray()
46{
47 /* TTO/TTD/TTDP savegames could have buoys at tile 0
48 * (without assigned station struct) */
49 MakeSea(0);
50}
51
52static void FixTTDMapArray()
53{
54 for (auto tile : Map::Iterate()) {
55 switch (GetTileType(tile)) {
56 case MP_STATION:
57 tile.m4() = 0; // We do not understand this TTDP station mapping (yet)
58 switch (tile.m5()) {
59 /* We have drive through stops at a totally different place */
60 case 0x53: case 0x54: tile.m5() += 170 - 0x53; break; // Bus drive through
61 case 0x57: case 0x58: tile.m5() += 168 - 0x57; break; // Truck drive through
62 case 0x55: case 0x56: tile.m5() += 170 - 0x55; break; // Bus tram stop
63 case 0x59: case 0x5A: tile.m5() += 168 - 0x59; break; // Truck tram stop
64 default: break;
65 }
66 break;
67
68 case MP_RAILWAY:
69 /* We save presignals different from TTDPatch, convert them */
70 if (GB(tile.m5(), 6, 2) == 1) { // RAIL_TILE_SIGNALS
71 /* This byte is always zero in TTD for this type of tile */
72 if (tile.m4()) { // Convert the presignals to our own format
73 tile.m4() = (tile.m4() >> 1) & 7;
74 }
75 }
76 /* TTDPatch stores PBS things in L6 and all elsewhere; so we'll just
77 * clear it for ourselves and let OTTD's rebuild PBS itself */
78 tile.m4() &= 0xF; // Only keep the lower four bits; upper four is PBS
79 break;
80
81 case MP_WATER:
82 /* if water class == 3, make river there */
83 if (GB(tile.m3(), 0, 2) == 3) {
84 SetTileType(tile, MP_WATER);
86 tile.m2() = 0;
87 tile.m3() = 2; // WATER_CLASS_RIVER
88 tile.m4() = Random();
89 tile.m5() = 0;
90 }
91 break;
92
93 default:
94 break;
95 }
96 }
97
98 FixOldMapArray();
99}
100
101static void FixTTDDepots()
102{
103 for (const Depot *d : Depot::Iterate(252)) {
104 if (!IsDepotTile(d->xy) || GetDepotIndex(d->xy) != d->index) {
106 delete d;
107 }
108 }
109}
110
111static uint32_t RemapOldTownName(uint32_t townnameparts, uint8_t old_town_name_type)
112{
113 auto fix_num = [](uint32_t i, uint32_t n, uint8_t s) -> uint32_t {
114 return ((i << 16) / n + 1) << s;
115 };
116
117 switch (old_town_name_type) {
118 case 0: case 3: // English, American
119 /* Already OK */
120 return townnameparts;
121
122 case 1: // French
123 /* For some reason 86 needs to be subtracted from townnameparts
124 * 0000 0000 0000 0000 0000 0000 1111 1111 */
125 return fix_num(townnameparts - 86, lengthof(_name_french_real), 0);
126
127 case 2: // German
128 Debug(misc, 0, "German Townnames are buggy ({})", townnameparts);
129 return townnameparts;
130
131 case 4: // Latin-American
132 /* 0000 0000 0000 0000 0000 0000 1111 1111 */
133 return fix_num(townnameparts, lengthof(_name_spanish_real), 0);
134
135 case 5: // Silly
136 /* NUM_SILLY_1 - lower 16 bits
137 * NUM_SILLY_2 - upper 16 bits without leading 1 (first 8 bytes)
138 * 1000 0000 2222 2222 0000 0000 1111 1111 */
139 return fix_num(townnameparts, lengthof(_name_silly_1), 0) | fix_num(GB(townnameparts, 16, 8), lengthof(_name_silly_2), 16);
140 }
141 return 0;
142}
143
144static void FixOldTowns()
145{
146 /* Convert town-names if needed */
147 for (Town *town : Town::Iterate()) {
148 if (IsInsideMM(town->townnametype, 0x20C1, 0x20C3)) {
150 town->townnameparts = RemapOldTownName(town->townnameparts, _settings_game.game_creation.town_name);
151 }
152 }
153}
154
161{
162 for (Vehicle *v : Vehicle::Iterate()) {
163 if ((size_t)v->next == 0xFFFF) {
164 v->next = nullptr;
165 } else {
166 v->next = Vehicle::GetIfValid((size_t)v->next);
167 }
168
169 /* For some reason we need to correct for this */
170 switch (v->spritenum) {
171 case 0xfd: break;
172 case 0xff: v->spritenum = 0xfe; break;
173 default: v->spritenum >>= 1; break;
174 }
175
176 /* Vehicle-subtype is different in TTD(Patch) */
177 if (v->type == VEH_EFFECT) v->subtype = v->subtype >> 1;
178
179 v->name = CopyFromOldName(ls.vehicle_names[v->index.base()]);
180
181 /* We haven't used this bit for stations for ages */
182 if (v->type == VEH_ROAD) {
184 if (rv->state != RVSB_IN_DEPOT && rv->state != RVSB_WORMHOLE) {
185 ClrBit(rv->state, 2);
186 Tile tile(rv->tile);
187 if (IsTileType(tile, MP_STATION) && tile.m5() >= 168) {
188 /* Update the vehicle's road state to show we're in a drive through road stop. */
190 }
191 }
192 }
193
194 /* The subtype should be 0, but it sometimes isn't :( */
195 if (v->type == VEH_ROAD || v->type == VEH_SHIP) v->subtype = 0;
196
197 /* Sometimes primary vehicles would have a nothing (invalid) order
198 * or vehicles that could not have an order would still have a
199 * (loading) order which causes assertions and the like later on.
200 */
202 (v->IsPrimaryVehicle() && v->current_order.IsType(OT_NOTHING))) {
203 v->current_order.MakeDummy();
204 }
205
206 /* Shared orders are fixed in AfterLoadVehicles now */
207 }
208}
209
210static bool FixTTOMapArray()
211{
212 for (auto tile : Map::Iterate()) {
213 TileType tt = GetTileType(tile);
214 if (tt == 11) {
215 /* TTO has a different way of storing monorail.
216 * Instead of using bits in m3 it uses a different tile type. */
217 tile.m3() = 1; // rail type = monorail (in TTD)
218 SetTileType(tile, MP_RAILWAY);
219 tile.m2() = 1; // set monorail ground to RAIL_GROUND_GRASS
220 tt = MP_RAILWAY;
221 }
222
223 switch (tt) {
224 case MP_CLEAR:
225 break;
226
227 case MP_RAILWAY:
228 switch (GB(tile.m5(), 6, 2)) {
229 case 0: // RAIL_TILE_NORMAL
230 break;
231 case 1: // RAIL_TILE_SIGNALS
232 tile.m4() = (~tile.m5() & 1) << 2; // signal variant (present only in OTTD)
233 SB(tile.m2(), 6, 2, GB(tile.m5(), 3, 2)); // signal status
234 tile.m3() |= 0xC0; // both signals are present
235 tile.m5() = HasBit(tile.m5(), 5) ? 2 : 1; // track direction (only X or Y)
236 tile.m5() |= 0x40; // RAIL_TILE_SIGNALS
237 break;
238 case 3: // RAIL_TILE_DEPOT
239 tile.m2() = 0;
240 break;
241 default:
242 return false;
243 }
244 break;
245
246 case MP_ROAD: // road (depot) or level crossing
247 switch (GB(tile.m5(), 4, 4)) {
248 case 0: // ROAD_TILE_NORMAL
249 if (tile.m2() == 4) tile.m2() = 5; // 'small trees' -> ROADSIDE_TREES
250 break;
251 case 1: // ROAD_TILE_CROSSING (there aren't monorail crossings in TTO)
252 tile.m3() = tile.m1(); // set owner of road = owner of rail
253 break;
254 case 2: // ROAD_TILE_DEPOT
255 break;
256 default:
257 return false;
258 }
259 break;
260
261 case MP_HOUSE:
262 tile.m3() = tile.m2() & 0xC0; // construction stage
263 tile.m2() &= 0x3F; // building type
264 if (tile.m2() >= 5) tile.m2()++; // skip "large office block on snow"
265 break;
266
267 case MP_TREES:
268 tile.m3() = GB(tile.m5(), 3, 3); // type of trees
269 tile.m5() &= 0xC7; // number of trees and growth status
270 break;
271
272 case MP_STATION:
273 tile.m3() = (tile.m5() >= 0x08 && tile.m5() <= 0x0F) ? 1 : 0; // monorail -> 1, others 0 (rail, road, airport, dock)
274 if (tile.m5() >= 8) tile.m5() -= 8; // shift for monorail
275 if (tile.m5() >= 0x42) tile.m5()++; // skip heliport
276 break;
277
278 case MP_WATER:
279 tile.m3() = tile.m2() = 0;
280 break;
281
282 case MP_VOID:
283 tile.m2() = tile.m3() = tile.m5() = 0;
284 break;
285
286 case MP_INDUSTRY:
287 tile.m3() = 0;
288 switch (tile.m5()) {
289 case 0x24: // farm silo
290 tile.m5() = 0x25;
291 break;
292 case 0x25: case 0x27: // farm
293 case 0x28: case 0x29: case 0x2A: case 0x2B: // factory
294 tile.m5()--;
295 break;
296 default:
297 if (tile.m5() >= 0x2C) tile.m5() += 3; // iron ore mine, steel mill or bank
298 break;
299 }
300 break;
301
302 case MP_TUNNELBRIDGE:
303 if (HasBit(tile.m5(), 7)) { // bridge
304 uint8_t m5 = tile.m5();
305 tile.m5() = m5 & 0xE1; // copy bits 7..5, 1
306 if (GB(m5, 1, 2) == 1) tile.m5() |= 0x02; // road bridge
307 if (GB(m5, 1, 2) == 3) tile.m2() |= 0xA0; // monorail bridge -> tubular, steel bridge
308 if (!HasBit(m5, 6)) { // bridge head
309 tile.m3() = (GB(m5, 1, 2) == 3) ? 1 : 0; // track subtype (1 for monorail, 0 for others)
310 } else { // middle bridge part
311 tile.m3() = HasBit(m5, 2) ? 0x10 : 0; // track subtype on bridge
312 if (GB(m5, 3, 2) == 3) tile.m3() |= 1; // track subtype under bridge
313 if (GB(m5, 3, 2) == 1) tile.m5() |= 0x08; // set for road/water under (0 for rail/clear)
314 }
315 } else { // tunnel entrance/exit
316 tile.m2() = 0;
317 tile.m3() = HasBit(tile.m5(), 3); // monorail
318 tile.m5() &= HasBit(tile.m5(), 3) ? 0x03 : 0x07 ; // direction, transport type (== 0 for rail)
319 }
320 break;
321
322 case MP_OBJECT:
323 tile.m2() = 0;
324 tile.m3() = 0;
325 break;
326
327 default:
328 return false;
329
330 }
331 }
332
333 FixOldMapArray();
334
335 return true;
336}
337
338static Engine *_old_engines;
339
340static bool FixTTOEngines()
341{
342 using OldEngineID = uint8_t;
344 static const OldEngineID ttd_to_tto[] = {
345 0, 255, 255, 255, 255, 255, 255, 255, 5, 7, 8, 9, 10, 11, 12, 13,
346 255, 255, 255, 255, 255, 255, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
347 25, 26, 27, 29, 28, 30, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
348 255, 255, 255, 255, 255, 255, 255, 31, 255, 32, 33, 34, 35, 36, 37, 38,
349 39, 40, 41, 42, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
350 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
351 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
352 255, 255, 255, 255, 44, 45, 46, 255, 255, 255, 255, 47, 48, 255, 49, 50,
353 255, 255, 255, 255, 51, 52, 255, 53, 54, 255, 55, 56, 255, 57, 59, 255,
354 58, 60, 255, 61, 62, 255, 63, 64, 255, 65, 66, 255, 255, 255, 255, 255,
355 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
356 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
357 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 67, 68, 69, 70,
358 71, 255, 255, 76, 77, 255, 255, 78, 79, 80, 81, 82, 83, 84, 85, 86,
359 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 255,
360 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 102, 255, 255
361 };
362
364 static const OldEngineID tto_to_ttd[] = {
365 0, 0, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 22,
366 23, 24, 25, 26, 27, 29, 28, 30, 31, 32, 33, 34, 35, 36, 37, 55,
367 57, 59, 58, 60, 61, 62, 63, 64, 65, 66, 67, 116, 116, 117, 118, 123,
368 124, 126, 127, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145, 147, 148, 150,
369 151, 153, 154, 204, 205, 206, 207, 208, 211, 212, 211, 212, 211, 212, 215, 216,
370 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
371 233, 234, 235, 236, 237, 238, 253
372 };
373
374 for (Vehicle *v : Vehicle::Iterate()) {
375 if (v->engine_type >= lengthof(tto_to_ttd)) return false;
376 v->engine_type = static_cast<EngineID>(tto_to_ttd[v->engine_type.base()]);
377 }
378
379 /* Load the default engine set. Many of them will be overridden later */
380 {
381 EngineID j = EngineID::Begin();
382 for (uint16_t i = 0; i < lengthof(_orig_rail_vehicle_info); ++i, ++j) new (GetTempDataEngine(j)) Engine(VEH_TRAIN, i);
383 for (uint16_t i = 0; i < lengthof(_orig_road_vehicle_info); ++i, ++j) new (GetTempDataEngine(j)) Engine(VEH_ROAD, i);
384 for (uint16_t i = 0; i < lengthof(_orig_ship_vehicle_info); ++i, ++j) new (GetTempDataEngine(j)) Engine(VEH_SHIP, i);
385 for (uint16_t i = 0; i < lengthof(_orig_aircraft_vehicle_info); ++i, ++j) new (GetTempDataEngine(j)) Engine(VEH_AIRCRAFT, i);
386 }
387
389 TimerGameCalendar::YearMonthDay aging_ymd = TimerGameCalendar::ConvertDateToYMD(aging_date);
390
391 for (EngineID i = EngineID::Begin(); i < 256; ++i) {
392 OldEngineID oi = ttd_to_tto[i.base()];
393 Engine *e = GetTempDataEngine(i);
394
395 if (oi == 255) {
396 /* Default engine is used */
398 StartupOneEngine(e, aging_ymd, 0);
399 CalcEngineReliability(e, false);
402
403 /* Make sure for example monorail and maglev are available when they should be */
404 if (TimerGameCalendar::date >= e->intro_date && e->info.climates.Test(LandscapeType::Temperate)) {
406 e->company_avail.Set();
408 }
409 } else {
410 /* Using data from TTO savegame */
411 Engine *oe = &_old_engines[oi];
412
413 e->intro_date = oe->intro_date;
414 e->age = oe->age;
415 e->reliability = oe->reliability;
423 e->flags = oe->flags;
424
426
427 /* One or more engines were remapped to this one. Make this engine available
428 * if at least one of them was available. */
429 for (uint j = 0; j < lengthof(tto_to_ttd); j++) {
430 if (tto_to_ttd[j] == i && _old_engines[j].company_avail.Any()) {
431 e->company_avail.Set();
433 break;
434 }
435 }
436
437 e->info.climates = LandscapeType::Temperate;
438 }
439
440 e->preview_company = CompanyID::Invalid();
441 e->preview_asked.Set();
442 e->preview_wait = 0;
443 e->name = std::string{};
444 }
445
446 return true;
447}
448
449static void FixTTOCompanies()
450{
451 for (Company *c : Company::Iterate()) {
452 c->cur_economy.company_value = CalculateCompanyValue(c); // company value history is zeroed
453 }
454}
455
456static inline Colours RemapTTOColour(Colours tto)
457{
459 static const Colours tto_colour_remap[] = {
460 COLOUR_DARK_BLUE, COLOUR_GREY, COLOUR_YELLOW, COLOUR_RED,
461 COLOUR_PURPLE, COLOUR_DARK_GREEN, COLOUR_ORANGE, COLOUR_PALE_GREEN,
462 COLOUR_BLUE, COLOUR_GREEN, COLOUR_CREAM, COLOUR_BROWN,
463 COLOUR_WHITE, COLOUR_LIGHT_BLUE, COLOUR_MAUVE, COLOUR_PINK
464 };
465
466 if (static_cast<size_t>(tto) >= std::size(tto_colour_remap)) return COLOUR_GREY; // this shouldn't happen
467
468 return tto_colour_remap[tto];
469}
470
471static inline uint RemapTownIndex(uint x)
472{
473 return _savegame_type == SGT_TTO ? (x - 0x264) / 78 : (x - 0x264) / 94;
474}
475
476static inline uint RemapOrderIndex(uint x)
477{
478 return _savegame_type == SGT_TTO ? (x - 0x1AC4) / 2 : (x - 0x1C18) / 2;
479}
480
481extern std::vector<TileIndex> _animated_tiles;
483extern std::unique_ptr<std::string[]> _old_name_array;
484
485static uint32_t _old_town_index;
486static uint16_t _old_string_id;
487static uint16_t _old_string_id_2;
488
489static void ClearOldMap3(TileIndex t)
490{
491 Tile tile(t);
492 tile.m3() = 0;
493 tile.m4() = 0;
494}
495
496static Town *RemapTown(TileIndex fallback)
497{
498 /* In some cases depots, industries and stations could refer to a missing town. */
499 Town *t = Town::GetIfValid(RemapTownIndex(_old_town_index));
500 if (t == nullptr) {
501 /* In case the town that was referred to does not exist, find the closest.
502 * However, this needs the kd-tree to be present. */
503 RebuildTownKdtree();
504 t = CalcClosestTownFromTile(fallback);
505 }
506 return t;
507}
508
509static void ReadTTDPatchFlags(LoadgameState &ls)
510{
511 if (_read_ttdpatch_flags) return;
512
514
515 /* Set default values */
516 ls.vehicle_multiplier = 1;
517 _ttdp_version = 0;
519 _bump_assert_value = 0;
520
521 if (_savegame_type == SGT_TTO) {
522 ls.vehicle_names.resize(800);
523 return;
524 }
525
526 /* TTDPatch misuses old map3 (now m3/m4) for flags.. read them! */
527 ls.vehicle_multiplier = Tile(0).m3();
528 /* Somehow.... there was an error in some savegames, so 0 becomes 1
529 * and 1 becomes 2. The rest of the values are okay */
530 if (ls.vehicle_multiplier < 2) ls.vehicle_multiplier++;
531
532 ls.vehicle_names.resize(ls.vehicle_multiplier * 850);
533
534 /* TTDPatch increases the Vehicle-part in the middle of the game,
535 * so if the multiplier is anything else but 1, the assert fails..
536 * bump the assert value so it doesn't!
537 * (1 multiplier == 850 vehicles
538 * 1 vehicle == 128 bytes */
539 _bump_assert_value = (ls.vehicle_multiplier - 1) * 850 * 128;
540
541 /* The first 17 bytes are used by TTDP1, which translates to the first 9 m3s and first 8 m4s. */
542 for (TileIndex i{}; i <= 8; i++) { // check tile 0, too
543 Tile tile(i);
544 if (tile.m3() != 0 || (i != 8 && tile.m4() != 0)) _savegame_type = SGT_TTDP1;
545 }
546
547 /* Check if we have a modern TTDPatch savegame (has extra data all around) */
548 Tile ttdp2_header_first(Map::Size() - 3);
549 Tile ttdp2_header_second(Map::Size() - 2);
550 if (ttdp2_header_first.m3() == 'T' && ttdp2_header_first.m4() == 'T' &&
551 ttdp2_header_second.m3() == 'D' && ttdp2_header_second.m4() == 'p') {
553 }
554
555 Tile extra_chunk_tile = Tile(_savegame_type == SGT_TTDP2 ? Map::Size() - 1 : 1);
556 _old_extra_chunk_nums = extra_chunk_tile.m3() | extra_chunk_tile.m4() << 8;
557
558 /* Clean the misused places */
559 for (TileIndex i{}; i < 9; i++) ClearOldMap3(i);
560 for (TileIndex i = TileXY(0, Map::MaxY()); i < Map::Size(); i++) ClearOldMap3(i);
561
562 if (_savegame_type == SGT_TTDP2) Debug(oldloader, 2, "Found TTDPatch game");
563
564 Debug(oldloader, 3, "Vehicle-multiplier is set to {} ({} vehicles)", ls.vehicle_multiplier, ls.vehicle_multiplier * 850);
565}
566
567static const OldChunks town_chunk[] = {
568 OCL_SVAR( OC_TILE, Town, xy ),
569 OCL_NULL( 2 ),
570 OCL_SVAR( OC_UINT16, Town, townnametype ),
571 OCL_SVAR( OC_UINT32, Town, townnameparts ),
572 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, grow_counter ),
573 OCL_NULL( 1 ),
574 OCL_NULL( 4 ),
575 OCL_NULL( 2 ),
576 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Town, flags ),
577 OCL_NULL( 10 ),
578
579 OCL_SVAR( OC_INT16, Town, ratings[0] ),
580 OCL_SVAR( OC_INT16, Town, ratings[1] ),
581 OCL_SVAR( OC_INT16, Town, ratings[2] ),
582 OCL_SVAR( OC_INT16, Town, ratings[3] ),
583 OCL_SVAR( OC_INT16, Town, ratings[4] ),
584 OCL_SVAR( OC_INT16, Town, ratings[5] ),
585 OCL_SVAR( OC_INT16, Town, ratings[6] ),
586 OCL_SVAR( OC_INT16, Town, ratings[7] ),
587
588 OCL_SVAR( OC_FILE_U32 | OC_VAR_U16, Town, have_ratings ),
589 OCL_SVAR( OC_FILE_U32 | OC_VAR_U16, Town, statues ),
590 OCL_NULL( 2 ),
591 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, time_until_rebuild ),
592 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, growth_rate ),
593
594 /* Slots 0 and 2 are passengers and mail respectively for old saves. */
595 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_max ),
596 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_max ),
597 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_act ),
598 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_act ),
599 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_max ),
600 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_max ),
601 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_act ),
602 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_act ),
603
604 OCL_NULL( 2 ),
605
606 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_FOOD].new_act ),
607 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_WATER].new_act ),
608 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_FOOD].old_act ),
609 OCL_SVAR( OC_TTD | OC_UINT16, Town, received[TAE_WATER].old_act ),
610
611 OCL_SVAR( OC_UINT8, Town, road_build_months ),
612 OCL_SVAR( OC_UINT8, Town, fund_buildings_months ),
613
614 OCL_CNULL( OC_TTD, 8 ),
615
616 OCL_END()
617};
618
619static bool LoadOldTown(LoadgameState &ls, int num)
620{
621 Town *t = new (TownID(num)) Town();
622 if (!LoadChunk(ls, t, town_chunk)) return false;
623
624 if (t->xy != 0) {
625 if (_savegame_type == SGT_TTO) {
626 /* 0x10B6 is auto-generated name, others are custom names */
627 t->townnametype = t->townnametype == 0x10B6 ? 0x20C1 : t->townnametype + 0x2A00;
628 }
629 } else {
630 delete t;
631 }
632
633 return true;
634}
635
636static uint16_t _old_order;
637static const OldChunks order_chunk[] = {
638 OCL_VAR ( OC_UINT16, 1, &_old_order ),
639 OCL_END()
640};
641
642static bool LoadOldOrder(LoadgameState &ls, int num)
643{
644 if (!LoadChunk(ls, nullptr, order_chunk)) return false;
645
647 o.order.AssignOrder(UnpackOldOrder(_old_order));
648
649 if (!o.order.IsType(OT_NOTHING) && num > 0) {
650 /* Relink the orders to each other (in the orders for one vehicle are behind each other,
651 * with an invalid order (OT_NOTHING) as indication that it is the last order */
652 OldOrderSaveLoadItem *prev = GetOldOrder(num + 1 - 1);
653 if (prev != nullptr) prev->next = num + 1; // next is 1-based.
654 }
655
656 return true;
657}
658
659static bool LoadOldAnimTileList(LoadgameState &ls, int)
660{
661 TileIndex anim_list[256];
662 const OldChunks anim_chunk[] = {
663 OCL_VAR ( OC_TILE, 256, anim_list ),
664 OCL_END ()
665 };
666
667 if (!LoadChunk(ls, nullptr, anim_chunk)) return false;
668
669 /* The first zero in the loaded array indicates the end of the list. */
670 for (int i = 0; i < 256; i++) {
671 if (anim_list[i] == 0) break;
672 _animated_tiles.push_back(anim_list[i]);
673 }
674
675 return true;
676}
677
678static const OldChunks depot_chunk[] = {
679 OCL_SVAR( OC_TILE, Depot, xy ),
680 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
681 OCL_END()
682};
683
684static bool LoadOldDepot(LoadgameState &ls, int num)
685{
686 Depot *d = new (DepotID(num)) Depot();
687 if (!LoadChunk(ls, d, depot_chunk)) return false;
688
689 if (d->xy != 0) {
690 d->town = RemapTown(d->xy);
691 } else {
692 delete d;
693 }
694
695 return true;
696}
697
698static StationID _current_station_id;
699static uint16_t _waiting_acceptance;
700static uint8_t _cargo_source;
701static uint8_t _cargo_periods;
702
703static const OldChunks goods_chunk[] = {
704 OCL_VAR ( OC_UINT16, 1, &_waiting_acceptance ),
705 OCL_SVAR( OC_UINT8, GoodsEntry, time_since_pickup ),
706 OCL_SVAR( OC_UINT8, GoodsEntry, rating ),
707 OCL_VAR ( OC_UINT8, 1, &_cargo_source ),
708 OCL_VAR ( OC_UINT8, 1, &_cargo_periods ),
709 OCL_SVAR( OC_UINT8, GoodsEntry, last_speed ),
710 OCL_SVAR( OC_UINT8, GoodsEntry, last_age ),
711
712 OCL_END()
713};
714
715static bool LoadOldGood(LoadgameState &ls, int num)
716{
717 /* for TTO games, 12th (num == 11) goods entry is created in the Station constructor */
718 if (_savegame_type == SGT_TTO && num == 11) return true;
719
720 Station *st = Station::Get(_current_station_id);
721 GoodsEntry *ge = &st->goods[num];
722
723 if (!LoadChunk(ls, ge, goods_chunk)) return false;
724
725 ge->status.Set(GoodsEntry::State::Acceptance, HasBit(_waiting_acceptance, 15));
726 ge->status.Set(GoodsEntry::State::Rating, _cargo_source != 0xFF);
727 if (GB(_waiting_acceptance, 0, 12) != 0 && CargoPacket::CanAllocateItem()) {
728 ge->GetOrCreateData().cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_periods, (_cargo_source == 0xFF) ? StationID::Invalid() : StationID{_cargo_source}, INVALID_TILE, 0),
729 StationID::Invalid());
730 }
731
732 return true;
733}
734
735static const OldChunks station_chunk[] = {
736 OCL_SVAR( OC_TILE, Station, xy ),
737 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
738
739 OCL_NULL( 4 ),
740 OCL_SVAR( OC_TILE, Station, train_station.tile ),
741 OCL_SVAR( OC_TILE, Station, airport.tile ),
742 OCL_NULL( 2 ),
743 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Station, train_station.w ),
744
745 OCL_NULL( 1 ),
746 OCL_NULL( 2 ),
747
748 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
749
750 OCL_NULL( 4 ),
751
752 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Station, had_vehicle_of_type ),
753
754 OCL_CHUNK( 12, LoadOldGood ),
755
756 OCL_SVAR( OC_UINT8, Station, time_since_load ),
757 OCL_SVAR( OC_UINT8, Station, time_since_unload ),
758 OCL_SVAR( OC_UINT8, Station, delete_ctr ),
759 OCL_SVAR( OC_UINT8, Station, owner ),
760 OCL_SVAR( OC_UINT8, Station, facilities ),
761 OCL_SVAR( OC_TTD | OC_UINT8, Station, airport.type ),
762 OCL_SVAR( OC_TTO | OC_FILE_U16 | OC_VAR_U64, Station, airport.blocks ),
763 OCL_NULL( 3 ),
764 OCL_CNULL( OC_TTD, 1 ),
765 OCL_SVAR( OC_TTD | OC_FILE_U16 | OC_VAR_U64, Station, airport.blocks ),
766 OCL_CNULL( OC_TTD, 2 ),
767 OCL_CNULL( OC_TTD, 4 ),
768
769 OCL_END()
770};
771
772static bool LoadOldStation(LoadgameState &ls, int num)
773{
774 Station *st = new (StationID(num)) Station();
775 _current_station_id = st->index;
776
777 if (!LoadChunk(ls, st, station_chunk)) return false;
778
779 if (st->xy != 0) {
780 st->town = RemapTown(st->xy);
781
782 if (_savegame_type == SGT_TTO) {
783 if (IsInsideBS(_old_string_id, 0x180F, 32)) {
784 st->string_id = STR_SV_STNAME + (_old_string_id - 0x180F); // automatic name
785 } else {
786 st->string_id = _old_string_id + 0x2800; // custom name
787 }
788
789 if (st->airport.blocks.Test(AirportBlock{8})) {
790 st->airport.type = 1; // large airport
791 } else if (st->airport.blocks.Test(AirportBlock{6})) {
792 st->airport.type = 3; // oil rig
793 } else {
794 st->airport.type = 0; // small airport
795 }
796 } else {
797 st->string_id = RemapOldStringID(_old_string_id);
798 }
799 } else {
800 delete st;
801 }
802
803 return true;
804}
805
806/* Old save games always have 3 input and 2 output slots per industry. */
807static std::array<Industry::AcceptedCargo, INDUSTRY_ORIGINAL_NUM_INPUTS> _old_accepted{};
808static std::array<Industry::ProducedCargo, INDUSTRY_ORIGINAL_NUM_OUTPUTS> _old_produced{};
809
810static const OldChunks industry_chunk[] = {
811 OCL_SVAR( OC_TILE, Industry, location.tile ),
812 OCL_VAR ( OC_UINT32, 1, &_old_town_index ),
813 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Industry, location.w ),
814 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Industry, location.h ),
815 OCL_NULL( 2 ),
816
817 OCL_VAR( OC_TTD | OC_UINT16, 1, &_old_produced[0].waiting ),
818 OCL_VAR( OC_TTD | OC_UINT16, 1, &_old_produced[1].waiting ),
819 OCL_VAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, 1, &_old_produced[0].waiting ),
820 OCL_VAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, 1, &_old_produced[1].waiting ),
821
822 OCL_VAR( OC_UINT8, 1, &_old_produced[0].rate ),
823 OCL_VAR( OC_UINT8, 1, &_old_produced[1].rate ),
824
825 OCL_NULL( 3 ),
826
827 OCL_SVAR( OC_UINT8, Industry, prod_level ),
828
829 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[THIS_MONTH].production ),
830 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[THIS_MONTH].production ),
831 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[THIS_MONTH].transported ),
832 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[THIS_MONTH].transported ),
833
834 OCL_NULL( 2 ),
835
836 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[LAST_MONTH].production ),
837 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[LAST_MONTH].production ),
838 OCL_VAR( OC_UINT16, 1, &_old_produced[0].history[LAST_MONTH].transported ),
839 OCL_VAR( OC_UINT16, 1, &_old_produced[1].history[LAST_MONTH].transported ),
840
841 OCL_SVAR( OC_UINT8, Industry, type ),
842 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Industry, counter ),
843 OCL_SVAR( OC_UINT8, Industry, owner ),
844 OCL_SVAR( OC_UINT8, Industry, random_colour ),
845 OCL_SVAR( OC_TTD | OC_FILE_U8 | OC_VAR_I32, Industry, last_prod_year ),
846 OCL_SVAR( OC_TTD | OC_UINT16, Industry, counter ),
847 OCL_SVAR( OC_TTD | OC_UINT8, Industry, was_cargo_delivered ),
848
849 OCL_CNULL( OC_TTD, 9 ),
850
851 OCL_END()
852};
853
854static bool LoadOldIndustry(LoadgameState &ls, int num)
855{
856 Industry *i = new (IndustryID(num)) Industry();
857 if (!LoadChunk(ls, i, industry_chunk)) return false;
858
859 if (i->location.tile != 0) {
860 /* Copy data from old fixed arrays to industry. */
861 std::copy(std::begin(_old_accepted), std::end(_old_accepted), std::back_inserter(i->accepted));
862 std::copy(std::begin(_old_produced), std::end(_old_produced), std::back_inserter(i->produced));
863
864 i->town = RemapTown(i->location.tile);
865
866 if (_savegame_type == SGT_TTO) {
867 if (i->type > 0x06) i->type++; // Printing Works were added
868 if (i->type == 0x0A) i->type = 0x12; // Iron Ore Mine has different ID
869
870 TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
871 i->last_prod_year = ymd.year;
872
874 }
875
876 Industry::industries[i->type].insert(i->index);
877 } else {
878 delete i;
879 }
880
881 return true;
882}
883
884static CompanyID _current_company_id;
885static int32_t _old_yearly;
886
887static const OldChunks _company_yearly_chunk[] = {
888 OCL_VAR( OC_INT32, 1, &_old_yearly ),
889 OCL_END()
890};
891
892static bool LoadOldCompanyYearly(LoadgameState &ls, int num)
893{
894 Company *c = Company::Get(_current_company_id);
895
896 for (uint i = 0; i < 13; i++) {
897 if (_savegame_type == SGT_TTO && i == 6) {
898 _old_yearly = 0; // property maintenance
899 } else {
900 if (!LoadChunk(ls, nullptr, _company_yearly_chunk)) return false;
901 }
902
903 c->yearly_expenses[num][i] = _old_yearly;
904 }
905
906 return true;
907}
908
909static const OldChunks _company_economy_chunk[] = {
910 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, income ),
911 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, expenses ),
912 OCL_SVAR( OC_INT32, CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1] ),
913 OCL_SVAR( OC_INT32, CompanyEconomyEntry, performance_history ),
914 OCL_SVAR( OC_TTD | OC_FILE_I32 | OC_VAR_I64, CompanyEconomyEntry, company_value ),
915
916 OCL_END()
917};
918
919static bool LoadOldCompanyEconomy(LoadgameState &ls, int)
920{
921 Company *c = Company::Get(_current_company_id);
922
923 if (!LoadChunk(ls, &c->cur_economy, _company_economy_chunk)) return false;
924
925 /* Don't ask, but the number in TTD(Patch) are inversed to OpenTTD */
928
929 for (uint i = 0; i < 24; i++) {
930 if (!LoadChunk(ls, &c->old_economy[i], _company_economy_chunk)) return false;
931
932 c->old_economy[i].income = -c->old_economy[i].income;
933 c->old_economy[i].expenses = -c->old_economy[i].expenses;
934 }
935
936 return true;
937}
938
939static const OldChunks _company_chunk[] = {
940 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
941 OCL_SVAR( OC_UINT32, Company, name_2 ),
942 OCL_SVAR( OC_UINT32, Company, face ),
943 OCL_VAR ( OC_UINT16, 1, &_old_string_id_2 ),
944 OCL_SVAR( OC_UINT32, Company, president_name_2 ),
945
946 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Company, money ),
947 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Company, current_loan ),
948
949 OCL_SVAR( OC_UINT8, Company, colour ),
950 OCL_SVAR( OC_UINT8, Company, money_fraction ),
951 OCL_SVAR( OC_UINT8, Company, months_of_bankruptcy ),
952 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Company, bankrupt_asked ),
953 OCL_SVAR( OC_FILE_U32 | OC_VAR_I64, Company, bankrupt_value ),
954 OCL_SVAR( OC_UINT16, Company, bankrupt_timeout ),
955
956 OCL_CNULL( OC_TTD, 4 ), // cargo_types
957 OCL_CNULL( OC_TTO, 2 ), // cargo_types
958
959 OCL_CHUNK( 3, LoadOldCompanyYearly ),
960 OCL_CHUNK( 1, LoadOldCompanyEconomy ),
961
962 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Company, inaugurated_year),
963 OCL_SVAR( OC_TILE, Company, last_build_coordinate ),
964 OCL_SVAR( OC_UINT8, Company, num_valid_stat_ent ),
965
966 OCL_NULL( 230 ), // Old AI
967
968 OCL_SVAR( OC_UINT8, Company, block_preview ),
969 OCL_CNULL( OC_TTD, 1 ), // Old AI
970 OCL_CNULL( OC_TTD, 1 ), // avail_railtypes
971 OCL_SVAR( OC_TILE, Company, location_of_HQ ),
972
973 OCL_CNULL( OC_TTD, 4 ), // Shares
974
975 OCL_CNULL( OC_TTD, 8 ), // junk at end of chunk
976
977 OCL_END()
978};
979
980static bool LoadOldCompany(LoadgameState &ls, int num)
981{
982 Company *c = new (CompanyID(num)) Company();
983
984 _current_company_id = (CompanyID)num;
985
986 if (!LoadChunk(ls, c, _company_chunk)) return false;
987
988 if (_old_string_id == 0) {
989 delete c;
990 return true;
991 }
992
993 if (_savegame_type == SGT_TTO) {
994 /* adjust manager's face */
995 if (HasBit(c->face, 27) && GB(c->face, 26, 1) == GB(c->face, 19, 1)) {
996 /* if face would be black in TTD, adjust tie colour and thereby face colour */
997 ClrBit(c->face, 27);
998 }
999
1000 /* Company name */
1001 if (_old_string_id == 0 || _old_string_id == 0x4C00) {
1002 _old_string_id = STR_SV_UNNAMED; // "Unnamed"
1003 } else if (GB(_old_string_id, 8, 8) == 0x52) {
1004 _old_string_id += 0x2A00; // Custom name
1005 } else {
1006 _old_string_id = RemapOldStringID(_old_string_id += 0x240D); // Automatic name
1007 }
1008 c->name_1 = _old_string_id;
1009
1010 /* Manager name */
1011 switch (_old_string_id_2) {
1012 case 0x4CDA: _old_string_id_2 = SPECSTR_PRESIDENT_NAME; break; // automatic name
1013 case 0x0006: _old_string_id_2 = STR_SV_EMPTY; break; // empty name
1014 default: _old_string_id_2 = _old_string_id_2 + 0x2A00; break; // custom name
1015 }
1016 c->president_name_1 = _old_string_id_2;
1017
1018 c->colour = RemapTTOColour(c->colour);
1019
1020 if (num != 0) c->is_ai = true;
1021 } else {
1022 c->name_1 = RemapOldStringID(_old_string_id);
1023 c->president_name_1 = RemapOldStringID(_old_string_id_2);
1024
1025 if (num == 0) {
1026 /* If the first company has no name, make sure we call it UNNAMED */
1027 if (c->name_1 == STR_NULL) {
1028 c->name_1 = STR_SV_UNNAMED;
1029 }
1030 } else {
1031 /* Beside some multiplayer maps (1 on 1), which we don't official support,
1032 * all other companies are an AI.. mark them as such */
1033 c->is_ai = true;
1034 }
1035
1036 /* Sometimes it is better to not ask.. in old scenarios, the money
1037 * was always 893288 pounds. In the newer versions this is correct,
1038 * but correct for those oldies
1039 * Ps: this also means that if you had exact 893288 pounds, you will go back
1040 * to 100000.. this is a very VERY small chance ;) */
1041 if (c->money == 893288) c->money = c->current_loan = 100000;
1042 }
1043
1044 _company_colours[num] = c->colour;
1046
1047 return true;
1048}
1049
1050static uint32_t _old_order_ptr;
1051static uint16_t _old_next_ptr;
1052static typename VehicleID::BaseType _current_vehicle_id;
1053
1054static const OldChunks vehicle_train_chunk[] = {
1055 OCL_SVAR( OC_UINT8, Train, track ),
1056 OCL_SVAR( OC_UINT8, Train, force_proceed ),
1057 OCL_SVAR( OC_UINT16, Train, crash_anim_pos ),
1058 OCL_SVAR( OC_UINT8, Train, railtype ),
1059
1060 OCL_NULL( 5 ),
1061
1062 OCL_END()
1063};
1064
1065static const OldChunks vehicle_road_chunk[] = {
1066 OCL_SVAR( OC_UINT8, RoadVehicle, state ),
1067 OCL_SVAR( OC_UINT8, RoadVehicle, frame ),
1068 OCL_SVAR( OC_UINT16, RoadVehicle, blocked_ctr ),
1069 OCL_SVAR( OC_UINT8, RoadVehicle, overtaking ),
1070 OCL_SVAR( OC_UINT8, RoadVehicle, overtaking_ctr ),
1071 OCL_SVAR( OC_UINT16, RoadVehicle, crashed_ctr ),
1072 OCL_SVAR( OC_UINT8, RoadVehicle, reverse_ctr ),
1073
1074 OCL_NULL( 1 ),
1075
1076 OCL_END()
1077};
1078
1079static const OldChunks vehicle_ship_chunk[] = {
1080 OCL_SVAR( OC_UINT8, Ship, state ),
1081
1082 OCL_NULL( 9 ),
1083
1084 OCL_END()
1085};
1086
1087static const OldChunks vehicle_air_chunk[] = {
1088 OCL_SVAR( OC_UINT8, Aircraft, pos ),
1089 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Aircraft, targetairport ),
1090 OCL_SVAR( OC_UINT16, Aircraft, crashed_counter ),
1091 OCL_SVAR( OC_UINT8, Aircraft, state ),
1092
1093 OCL_NULL( 5 ),
1094
1095 OCL_END()
1096};
1097
1098static const OldChunks vehicle_effect_chunk[] = {
1099 OCL_SVAR( OC_UINT16, EffectVehicle, animation_state ),
1100 OCL_SVAR( OC_UINT8, EffectVehicle, animation_substate ),
1101
1102 OCL_NULL( 7 ), // Junk
1103
1104 OCL_END()
1105};
1106
1107static const OldChunks vehicle_disaster_chunk[] = {
1108 OCL_SVAR( OC_UINT16, DisasterVehicle, image_override ),
1109 OCL_SVAR( OC_UINT16, DisasterVehicle, big_ufo_destroyer_target ),
1110
1111 OCL_NULL( 6 ),
1112
1113 OCL_END()
1114};
1115
1116static const OldChunks vehicle_empty_chunk[] = {
1117 OCL_NULL( 10 ),
1118
1119 OCL_END()
1120};
1121
1122static bool LoadOldVehicleUnion(LoadgameState &ls, int)
1123{
1124 Vehicle *v = Vehicle::GetIfValid(_current_vehicle_id);
1125 uint temp = ls.total_read;
1126 bool res;
1127
1128 if (v == nullptr) {
1129 res = LoadChunk(ls, nullptr, vehicle_empty_chunk);
1130 } else {
1131 switch (v->type) {
1132 default: SlErrorCorrupt("Invalid vehicle type");
1133 case VEH_TRAIN : res = LoadChunk(ls, v, vehicle_train_chunk); break;
1134 case VEH_ROAD : res = LoadChunk(ls, v, vehicle_road_chunk); break;
1135 case VEH_SHIP : res = LoadChunk(ls, v, vehicle_ship_chunk); break;
1136 case VEH_AIRCRAFT: res = LoadChunk(ls, v, vehicle_air_chunk); break;
1137 case VEH_EFFECT : res = LoadChunk(ls, v, vehicle_effect_chunk); break;
1138 case VEH_DISASTER: res = LoadChunk(ls, v, vehicle_disaster_chunk); break;
1139 }
1140 }
1141
1142 /* This chunk size should always be 10 bytes */
1143 if (ls.total_read - temp != 10) {
1144 Debug(oldloader, 0, "Assert failed in VehicleUnion: invalid chunk size");
1145 return false;
1146 }
1147
1148 return res;
1149}
1150
1151static uint16_t _cargo_count;
1152
1153static const OldChunks vehicle_chunk[] = {
1154 OCL_SVAR( OC_UINT8, Vehicle, subtype ),
1155
1156 OCL_NULL( 2 ),
1157 OCL_NULL( 2 ),
1158
1159 OCL_VAR ( OC_UINT32, 1, &_old_order_ptr ),
1160 OCL_VAR ( OC_UINT16, 1, &_old_order ),
1161
1162 OCL_NULL ( 1 ),
1163 OCL_SVAR( OC_UINT8, Vehicle, cur_implicit_order_index ),
1164 OCL_SVAR( OC_TILE, Vehicle, dest_tile ),
1165 OCL_SVAR( OC_UINT16, Vehicle, load_unload_ticks ),
1166 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, date_of_last_service ),
1167 OCL_SVAR( OC_UINT16, Vehicle, service_interval ),
1168 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, last_station_visited ),
1169 OCL_SVAR( OC_TTD | OC_UINT8, Vehicle, tick_counter ),
1170 OCL_CNULL( OC_TTD, 2 ),
1171 OCL_CNULL( OC_TTO, 1 ),
1172
1173 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, x_pos ),
1174 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Vehicle, y_pos ),
1175 OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, z_pos ),
1176 OCL_SVAR( OC_UINT8, Vehicle, direction ),
1177 OCL_NULL( 2 ),
1178 OCL_NULL( 2 ),
1179 OCL_NULL( 1 ),
1180
1181 OCL_SVAR( OC_UINT8, Vehicle, owner ),
1182 OCL_SVAR( OC_TILE, Vehicle, tile ),
1183 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, sprite_cache.sprite_seq.seq[0].sprite ),
1184
1185 OCL_NULL( 8 ),
1186
1187 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Vehicle, vehstatus ),
1188 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, cur_speed ),
1189 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, cur_speed ),
1190 OCL_SVAR( OC_UINT8, Vehicle, subspeed ),
1191 OCL_SVAR( OC_UINT8, Vehicle, acceleration ),
1192 OCL_SVAR( OC_UINT8, Vehicle, progress ),
1193
1194 OCL_SVAR( OC_UINT8, Vehicle, cargo_type ),
1195 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, cargo_cap ),
1196 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, cargo_cap ),
1197 OCL_VAR ( OC_TTD | OC_UINT16, 1, &_cargo_count ),
1198 OCL_VAR ( OC_TTO | OC_FILE_U8 | OC_VAR_U16, 1, &_cargo_count ),
1199 OCL_VAR ( OC_UINT8, 1, &_cargo_source ),
1200 OCL_VAR ( OC_UINT8, 1, &_cargo_periods ),
1201
1202 OCL_SVAR( OC_TTO | OC_UINT8, Vehicle, tick_counter ),
1203
1204 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, age ),
1205 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, max_age ),
1206 OCL_SVAR( OC_FILE_U8 | OC_VAR_I32, Vehicle, build_year ),
1207 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, unitnumber ),
1208
1209 OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, engine_type ),
1210 OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, engine_type ),
1211
1212 OCL_SVAR( OC_UINT8, Vehicle, spritenum ),
1213 OCL_SVAR( OC_UINT8, Vehicle, day_counter ),
1214
1215 OCL_SVAR( OC_UINT8, Vehicle, breakdowns_since_last_service ),
1216 OCL_SVAR( OC_UINT8, Vehicle, breakdown_ctr ),
1217 OCL_SVAR( OC_UINT8, Vehicle, breakdown_delay ),
1218 OCL_SVAR( OC_UINT8, Vehicle, breakdown_chance ),
1219
1220 OCL_CNULL( OC_TTO, 1 ),
1221
1222 OCL_SVAR( OC_UINT16, Vehicle, reliability ),
1223 OCL_SVAR( OC_UINT16, Vehicle, reliability_spd_dec ),
1224
1225 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Vehicle, profit_this_year ),
1226 OCL_SVAR( OC_FILE_I32 | OC_VAR_I64, Vehicle, profit_last_year ),
1227
1228 OCL_VAR ( OC_UINT16, 1, &_old_next_ptr ),
1229
1230 OCL_SVAR( OC_FILE_U32 | OC_VAR_I64, Vehicle, value ),
1231
1232 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
1233
1234 OCL_CHUNK( 1, LoadOldVehicleUnion ),
1235
1236 OCL_CNULL( OC_TTO, 24 ),
1237 OCL_CNULL( OC_TTD, 20 ),
1238
1239 OCL_END()
1240};
1241
1249{
1250 /* Read the TTDPatch flags, because we need some info from it */
1251 ReadTTDPatchFlags(ls);
1252
1253 for (uint i = 0; i < ls.vehicle_multiplier; i++) {
1254 _current_vehicle_id = num * ls.vehicle_multiplier + i;
1255
1256 Vehicle *v;
1257
1258 if (_savegame_type == SGT_TTO) {
1259 uint type = ReadByte(ls);
1260 switch (type) {
1261 default: return false;
1262 case 0x00 /* VEH_INVALID */: v = nullptr; break;
1263 case 0x25 /* MONORAIL */:
1264 case 0x20 /* VEH_TRAIN */: v = new (VehicleID(_current_vehicle_id)) Train(); break;
1265 case 0x21 /* VEH_ROAD */: v = new (VehicleID(_current_vehicle_id)) RoadVehicle(); break;
1266 case 0x22 /* VEH_SHIP */: v = new (VehicleID(_current_vehicle_id)) Ship(); break;
1267 case 0x23 /* VEH_AIRCRAFT */: v = new (VehicleID(_current_vehicle_id)) Aircraft(); break;
1268 case 0x24 /* VEH_EFFECT */: v = new (VehicleID(_current_vehicle_id)) EffectVehicle(); break;
1269 case 0x26 /* VEH_DISASTER */: v = new (VehicleID(_current_vehicle_id)) DisasterVehicle(); break;
1270 }
1271
1272 if (!LoadChunk(ls, v, vehicle_chunk)) return false;
1273 if (v == nullptr) continue;
1274 v->refit_cap = v->cargo_cap;
1275
1276 SpriteID sprite = v->sprite_cache.sprite_seq.seq[0].sprite;
1277 /* no need to override other sprites */
1278 if (IsInsideMM(sprite, 1460, 1465)) {
1279 sprite += 580; // aircraft smoke puff
1280 } else if (IsInsideMM(sprite, 2096, 2115)) {
1281 sprite += 977; // special effects part 1
1282 } else if (IsInsideMM(sprite, 2396, 2436)) {
1283 sprite += 1305; // special effects part 2
1284 } else if (IsInsideMM(sprite, 2516, 2539)) {
1285 sprite += 1385; // rotor or disaster-related vehicles
1286 }
1287 v->sprite_cache.sprite_seq.seq[0].sprite = sprite;
1288
1289 switch (v->type) {
1290 case VEH_TRAIN: {
1291 static const uint8_t spriteset_rail[] = {
1292 0, 2, 4, 4, 8, 10, 12, 14, 16, 18, 20, 22, 40, 42, 44, 46,
1293 48, 52, 54, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 120, 122,
1294 124, 126, 128, 130, 132, 134, 136, 138, 140
1295 };
1296 if (v->spritenum / 2 >= lengthof(spriteset_rail)) return false;
1297 v->spritenum = spriteset_rail[v->spritenum / 2]; // adjust railway sprite set offset
1298 /* Should be the original values for monorail / rail, can't use RailType constants */
1299 Train::From(v)->railtype = static_cast<RailType>(type == 0x25 ? 1 : 0);
1300 break;
1301 }
1302
1303 case VEH_ROAD:
1304 if (v->spritenum >= 22) v->spritenum += 12;
1305 break;
1306
1307 case VEH_SHIP:
1308 v->spritenum += 2;
1309
1310 switch (v->spritenum) {
1311 case 2: // oil tanker && cargo type != oil
1312 if (v->cargo_type != 3) v->spritenum = 0; // make it a coal/goods ship
1313 break;
1314 case 4: // passenger ship && cargo type == mail
1315 if (v->cargo_type == 2) v->spritenum = 0; // make it a mail ship
1316 break;
1317 default:
1318 break;
1319 }
1320 break;
1321
1322 default:
1323 break;
1324 }
1325
1326 switch (_old_string_id) {
1327 case 0x0000: break; // empty (invalid vehicles)
1328 case 0x0006: _old_string_id = STR_SV_EMPTY; break; // empty (special vehicles)
1329 case 0x8495: _old_string_id = STR_SV_TRAIN_NAME; break; // "Train X"
1330 case 0x8842: _old_string_id = STR_SV_ROAD_VEHICLE_NAME; break; // "Road Vehicle X"
1331 case 0x8C3B: _old_string_id = STR_SV_SHIP_NAME; break; // "Ship X"
1332 case 0x9047: _old_string_id = STR_SV_AIRCRAFT_NAME; break; // "Aircraft X"
1333 default: _old_string_id += 0x2A00; break; // custom name
1334 }
1335
1336 ls.vehicle_names[_current_vehicle_id] = _old_string_id;
1337 } else {
1338 /* Read the vehicle type and allocate the right vehicle */
1339 switch (ReadByte(ls)) {
1340 default: SlErrorCorrupt("Invalid vehicle type");
1341 case 0x00 /* VEH_INVALID */: v = nullptr; break;
1342 case 0x10 /* VEH_TRAIN */: v = new (VehicleID(_current_vehicle_id)) Train(); break;
1343 case 0x11 /* VEH_ROAD */: v = new (VehicleID(_current_vehicle_id)) RoadVehicle(); break;
1344 case 0x12 /* VEH_SHIP */: v = new (VehicleID(_current_vehicle_id)) Ship(); break;
1345 case 0x13 /* VEH_AIRCRAFT*/: v = new (VehicleID(_current_vehicle_id)) Aircraft(); break;
1346 case 0x14 /* VEH_EFFECT */: v = new (VehicleID(_current_vehicle_id)) EffectVehicle(); break;
1347 case 0x15 /* VEH_DISASTER*/: v = new (VehicleID(_current_vehicle_id)) DisasterVehicle(); break;
1348 }
1349
1350 if (!LoadChunk(ls, v, vehicle_chunk)) return false;
1351 if (v == nullptr) continue;
1352
1353 ls.vehicle_names[_current_vehicle_id] = RemapOldStringID(_old_string_id);
1354
1355 /* This should be consistent, else we have a big problem... */
1356 if (v->index != _current_vehicle_id) {
1357 Debug(oldloader, 0, "Loading failed - vehicle-array is invalid");
1358 return false;
1359 }
1360 }
1361
1362 if (_old_order_ptr != 0 && _old_order_ptr != 0xFFFFFFFF) {
1363 uint max = _savegame_type == SGT_TTO ? 3000 : 5000;
1364 uint old_id = RemapOrderIndex(_old_order_ptr);
1365 if (old_id < max) v->old_orders = old_id + 1;
1366 }
1368
1369 if (v->type == VEH_DISASTER) {
1370 DisasterVehicle::From(v)->state = UnpackOldOrder(_old_order).GetDestination().value;
1371 }
1372
1373 v->next = (Vehicle *)(size_t)_old_next_ptr;
1374
1375 if (_cargo_count != 0 && CargoPacket::CanAllocateItem()) {
1376 StationID source = (_cargo_source == 0xFF) ? StationID::Invalid() : StationID{_cargo_source};
1377 TileIndex source_xy = (source != StationID::Invalid()) ? Station::Get(source)->xy : (TileIndex)0;
1378 v->cargo.Append(new CargoPacket(_cargo_count, _cargo_periods, source, source_xy, 0));
1379 }
1380 }
1381
1382 return true;
1383}
1384
1392{
1393 /*
1394 * Data is stored in fixed size "cells"; read these completely.
1395 * Validation and conversion to UTF-8 are happening at a later stage.
1396 */
1397 std::string &str = _old_name_array[index];
1398 str.resize(_savegame_type == SGT_TTO ? 24 : 32);
1399 for (auto &c : str) c = ReadByte(ls);
1400
1401 return true;
1402}
1403
1404static const OldChunks sign_chunk[] = {
1405 OCL_VAR ( OC_UINT16, 1, &_old_string_id ),
1406 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Sign, x ),
1407 OCL_SVAR( OC_FILE_U16 | OC_VAR_I32, Sign, y ),
1408 OCL_SVAR( OC_FILE_U16 | OC_VAR_I8, Sign, z ),
1409
1410 OCL_NULL( 6 ),
1411
1412 OCL_END()
1413};
1414
1415static bool LoadOldSign(LoadgameState &ls, int num)
1416{
1417 Sign *si = new (SignID(num)) Sign();
1418 if (!LoadChunk(ls, si, sign_chunk)) return false;
1419
1420 if (_old_string_id != 0) {
1421 if (_savegame_type == SGT_TTO) {
1422 if (_old_string_id != 0x140A) si->name = CopyFromOldName(_old_string_id + 0x2A00);
1423 } else {
1424 si->name = CopyFromOldName(RemapOldStringID(_old_string_id));
1425 }
1426 si->owner = OWNER_NONE;
1427 } else {
1428 delete si;
1429 }
1430
1431 return true;
1432}
1433
1434static const OldChunks engine_chunk[] = {
1435 OCL_SVAR( OC_UINT16, Engine, company_avail ),
1436 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, intro_date ),
1437 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Engine, age ),
1438 OCL_SVAR( OC_UINT16, Engine, reliability ),
1439 OCL_SVAR( OC_UINT16, Engine, reliability_spd_dec ),
1440 OCL_SVAR( OC_UINT16, Engine, reliability_start ),
1441 OCL_SVAR( OC_UINT16, Engine, reliability_max ),
1442 OCL_SVAR( OC_UINT16, Engine, reliability_final ),
1443 OCL_SVAR( OC_UINT16, Engine, duration_phase_1 ),
1444 OCL_SVAR( OC_UINT16, Engine, duration_phase_2 ),
1445 OCL_SVAR( OC_UINT16, Engine, duration_phase_3 ),
1446
1447 OCL_NULL( 1 ), // lifelength
1448 OCL_SVAR( OC_UINT8, Engine, flags ),
1449 OCL_NULL( 1 ), // preview_company_rank
1450 OCL_SVAR( OC_UINT8, Engine, preview_wait ),
1451
1452 OCL_CNULL( OC_TTD, 2 ),
1453
1454 OCL_END()
1455};
1456
1457static bool LoadOldEngine(LoadgameState &ls, int num)
1458{
1459 Engine *e = _savegame_type == SGT_TTO ? &_old_engines[num] : GetTempDataEngine(static_cast<EngineID>(num));
1460 return LoadChunk(ls, e, engine_chunk);
1461}
1462
1463static bool LoadOldEngineName(LoadgameState &ls, int num)
1464{
1465 Engine *e = GetTempDataEngine(static_cast<EngineID>(num));
1466 e->name = CopyFromOldName(RemapOldStringID(ReadUint16(ls)));
1467 return true;
1468}
1469
1470static const OldChunks subsidy_chunk[] = {
1471 OCL_SVAR( OC_UINT8, Subsidy, cargo_type ),
1472 OCL_SVAR( OC_UINT8, Subsidy, remaining ),
1473 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, src ),
1474 OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Subsidy, dst ),
1475
1476 OCL_END()
1477};
1478
1479static bool LoadOldSubsidy(LoadgameState &ls, int num)
1480{
1481 Subsidy *s = new (SubsidyID(num)) Subsidy();
1482 bool ret = LoadChunk(ls, s, subsidy_chunk);
1483 if (!IsValidCargoType(s->cargo_type)) delete s;
1484 return ret;
1485}
1486
1487static const OldChunks game_difficulty_chunk[] = {
1488 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, max_no_competitors ),
1489 OCL_NULL( 2), // competitor_start_time
1490 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, number_towns ),
1491 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, industry_density ),
1492 OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, DifficultySettings, max_loan ),
1493 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, initial_interest ),
1494 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_costs ),
1495 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, competitor_speed ),
1496 OCL_NULL( 2), // competitor_intelligence
1497 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_breakdowns ),
1498 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, subsidy_multiplier ),
1499 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, construction_cost ),
1500 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, terrain_type ),
1501 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, quantity_sea_lakes ),
1502 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, economy ),
1503 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, line_reverse_mode ),
1504 OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, disasters ),
1505 OCL_END()
1506};
1507
1508static bool LoadOldGameDifficulty(LoadgameState &ls, int)
1509{
1510 bool ret = LoadChunk(ls, &_settings_game.difficulty, game_difficulty_chunk);
1512 return ret;
1513}
1514
1515
1516static bool LoadOldMapPart1(LoadgameState &ls, int)
1517{
1518 if (_savegame_type == SGT_TTO) {
1519 Map::Allocate(OLD_MAP_SIZE, OLD_MAP_SIZE);
1520 }
1521
1522 for (auto t : Map::Iterate()) {
1523 t.m1() = ReadByte(ls);
1524 }
1525 for (auto t : Map::Iterate()) {
1526 t.m2() = ReadByte(ls);
1527 }
1528
1529 if (_savegame_type != SGT_TTO) {
1530 /* old map3 is split into to m3 and m4 */
1531 for (auto t : Map::Iterate()) {
1532 t.m3() = ReadByte(ls);
1533 t.m4() = ReadByte(ls);
1534 }
1535 auto range = Map::Iterate();
1536 for (auto it = range.begin(); it != range.end(); /* nothing. */) {
1537 uint8_t b = ReadByte(ls);
1538 for (int i = 0; i < 8; i += 2, ++it) (*it).m6() = GB(b, i, 2);
1539 }
1540 }
1541
1542 return true;
1543}
1544
1545static bool LoadOldMapPart2(LoadgameState &ls, int)
1546{
1547 for (auto t : Map::Iterate()) {
1548 t.type() = ReadByte(ls);
1549 }
1550 for (auto t : Map::Iterate()) {
1551 t.m5() = ReadByte(ls);
1552 }
1553
1554 return true;
1555}
1556
1557static bool LoadTTDPatchExtraChunks(LoadgameState &ls, int)
1558{
1559 ReadTTDPatchFlags(ls);
1560
1561 Debug(oldloader, 2, "Found {} extra chunk(s)", _old_extra_chunk_nums);
1562
1563 for (int i = 0; i != _old_extra_chunk_nums; i++) {
1564 uint16_t id = ReadUint16(ls);
1565 uint32_t len = ReadUint32(ls);
1566
1567 switch (id) {
1568 /* List of GRFIDs, used in the savegame. 0x8004 is the new ID
1569 * They are saved in a 'GRFID:4 active:1' format, 5 bytes for each entry */
1570 case 0x2:
1571 case 0x8004: {
1572 /* Skip the first element: TTDP hack for the Action D special variables (FFFF0000 01) */
1573 ReadUint32(ls); ReadByte(ls); len -= 5;
1574
1576 while (len != 0) {
1577 uint32_t grfid = ReadUint32(ls);
1578
1579 if (ReadByte(ls) == 1) {
1580 auto c = std::make_unique<GRFConfig>("TTDP game, no information");
1581 c->ident.grfid = grfid;
1582
1583 Debug(oldloader, 3, "TTDPatch game using GRF file with GRFID {:08X}", std::byteswap(c->ident.grfid));
1584 AppendToGRFConfigList(_grfconfig, std::move(c));
1585 }
1586 len -= 5;
1587 }
1588
1589 /* Append static NewGRF configuration */
1591 break;
1592 }
1593
1594 /* TTDPatch version and configuration */
1595 case 0x3:
1596 _ttdp_version = ReadUint32(ls);
1597 Debug(oldloader, 3, "Game saved with TTDPatch version {}.{}.{} r{}",
1598 GB(_ttdp_version, 24, 8), GB(_ttdp_version, 20, 4), GB(_ttdp_version, 16, 4), GB(_ttdp_version, 0, 16));
1599 len -= 4;
1600 while (len-- != 0) ReadByte(ls); // skip the configuration
1601 break;
1602
1603 default:
1604 Debug(oldloader, 4, "Skipping unknown extra chunk {}", id);
1605 while (len-- != 0) ReadByte(ls);
1606 break;
1607 }
1608 }
1609
1610 return true;
1611}
1612
1613extern TileIndex _cur_tileloop_tile;
1614extern uint16_t _disaster_delay;
1615extern uint8_t _trees_tick_ctr;
1616extern uint8_t _age_cargo_skip_counter; // From misc_sl.cpp
1617extern uint8_t _old_diff_level;
1618extern uint8_t _old_units;
1619static const OldChunks main_chunk[] = {
1620 OCL_ASSERT( OC_TTD, 0 ),
1621 OCL_ASSERT( OC_TTO, 0 ),
1622 OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &TimerGameCalendar::date ),
1623 OCL_VAR ( OC_UINT16, 1, &TimerGameCalendar::date_fract ),
1624 OCL_NULL( 600 ),
1625 OCL_VAR ( OC_UINT32, 2, &_random.state ),
1626
1627 OCL_ASSERT( OC_TTD, 0x264 ),
1628 OCL_ASSERT( OC_TTO, 0x264 ),
1629
1630 OCL_CCHUNK( OC_TTD, 70, LoadOldTown ),
1631 OCL_CCHUNK( OC_TTO, 80, LoadOldTown ),
1632
1633 OCL_ASSERT( OC_TTD, 0x1C18 ),
1634 OCL_ASSERT( OC_TTO, 0x1AC4 ),
1635
1636 OCL_CCHUNK( OC_TTD, 5000, LoadOldOrder ),
1637 OCL_CCHUNK( OC_TTO, 3000, LoadOldOrder ),
1638
1639 OCL_ASSERT( OC_TTD, 0x4328 ),
1640 OCL_ASSERT( OC_TTO, 0x3234 ),
1641
1642 OCL_CHUNK( 1, LoadOldAnimTileList ),
1643 OCL_NULL( 4 ),
1644
1645 OCL_ASSERT( OC_TTO, 0x3438 ),
1646
1647 OCL_CCHUNK( OC_TTD, 255, LoadOldDepot ),
1648 OCL_CCHUNK( OC_TTO, 252, LoadOldDepot ),
1649
1650 OCL_ASSERT( OC_TTD, 0x4B26 ),
1651 OCL_ASSERT( OC_TTO, 0x3A20 ),
1652
1653 OCL_NULL( 4 ),
1654 OCL_NULL( 2 ),
1655 OCL_NULL( 2 ),
1656
1657 OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_age_cargo_skip_counter ),
1658 OCL_VAR ( OC_FILE_U16 | OC_VAR_U64, 1, &TimerGameTick::counter ),
1659 OCL_VAR ( OC_TILE, 1, &_cur_tileloop_tile ),
1660
1661 OCL_ASSERT( OC_TTO, 0x3A2E ),
1662
1663 OCL_CNULL( OC_TTO, 48 * 6 ),
1664 OCL_CNULL( OC_TTD, 49 * 6 ),
1665
1666 OCL_ASSERT( OC_TTO, 0x3B4E ),
1667
1668 OCL_CNULL( OC_TTO, 11 * 8 ),
1669 OCL_CNULL( OC_TTD, 12 * 8 ),
1670
1671 OCL_ASSERT( OC_TTD, 0x4CBA ),
1672 OCL_ASSERT( OC_TTO, 0x3BA6 ),
1673
1674 OCL_CHUNK( 1, LoadOldMapPart1 ),
1675
1676 OCL_ASSERT( OC_TTD, 0x48CBA ),
1677 OCL_ASSERT( OC_TTO, 0x23BA6 ),
1678
1679 OCL_CCHUNK( OC_TTD, 250, LoadOldStation ),
1680 OCL_CCHUNK( OC_TTO, 200, LoadOldStation ),
1681
1682 OCL_ASSERT( OC_TTO, 0x29E16 ),
1683
1684 OCL_CCHUNK( OC_TTD, 90, LoadOldIndustry ),
1685 OCL_CCHUNK( OC_TTO, 100, LoadOldIndustry ),
1686
1687 OCL_ASSERT( OC_TTO, 0x2ADB6 ),
1688
1689 OCL_CHUNK( 8, LoadOldCompany ),
1690
1691 OCL_ASSERT( OC_TTD, 0x547F2 ),
1692 OCL_ASSERT( OC_TTO, 0x2C746 ),
1693
1694 OCL_CCHUNK( OC_TTD, 850, LoadOldVehicle ),
1695 OCL_CCHUNK( OC_TTO, 800, LoadOldVehicle ),
1696
1697 OCL_ASSERT( OC_TTD, 0x6F0F2 ),
1698 OCL_ASSERT( OC_TTO, 0x45746 ),
1699
1700 OCL_CCHUNK( OC_TTD, 500, LoadOldCustomString ),
1701 OCL_CCHUNK( OC_TTO, 200, LoadOldCustomString ),
1702
1703 OCL_ASSERT( OC_TTO, 0x46A06 ),
1704
1705 OCL_NULL( 0x2000 ),
1706
1707 OCL_CHUNK( 40, LoadOldSign ),
1708
1709 OCL_ASSERT( OC_TTO, 0x48C36 ),
1710
1711 OCL_CCHUNK( OC_TTD, 256, LoadOldEngine ),
1712 OCL_CCHUNK( OC_TTO, 103, LoadOldEngine ),
1713
1714 OCL_ASSERT( OC_TTO, 0x496AC ),
1715
1716 OCL_NULL ( 2 ), // _vehicle_id_ctr_day
1717
1718 OCL_CHUNK( 8, LoadOldSubsidy ),
1719
1720 OCL_ASSERT( OC_TTO, 0x496CE ),
1721
1722 OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_new_competitor_timeout.period.value ),
1723
1724 OCL_CNULL( OC_TTO, 2 ),
1725
1726 OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_x ),
1727 OCL_VAR ( OC_FILE_I16 | OC_VAR_I32, 1, &_saved_scrollpos_y ),
1728 OCL_VAR ( OC_FILE_U16 | OC_VAR_U8, 1, &_saved_scrollpos_zoom ),
1729
1730 OCL_NULL( 4 ),
1731 OCL_VAR ( OC_FILE_U32 | OC_VAR_I64, 1, &_economy.old_max_loan_unround ),
1732 OCL_VAR ( OC_INT16, 1, &_economy.fluct ),
1733
1734 OCL_VAR ( OC_UINT16, 1, &_disaster_delay ),
1735
1736 OCL_ASSERT( OC_TTO, 0x496E4 ),
1737
1738 OCL_CNULL( OC_TTD, 144 ),
1739
1740 OCL_CCHUNK( OC_TTD, 256, LoadOldEngineName ),
1741
1742 OCL_CNULL( OC_TTD, 144 ),
1743 OCL_NULL( 2 ),
1744 OCL_NULL( 1 ),
1745
1746 OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.currency ),
1747 OCL_VAR ( OC_UINT8, 1, &_old_units ),
1748 OCL_VAR ( OC_FILE_U8 | OC_VAR_U32, 1, &_cur_company_tick_index ),
1749
1750 OCL_NULL( 2 ),
1751 OCL_NULL( 8 ),
1752
1753 OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount ),
1754 OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount_pr ),
1755 OCL_VAR ( OC_UINT8, 1, &_economy.interest_rate ),
1756 OCL_NULL( 1 ), // available airports
1757 OCL_VAR ( OC_UINT8, 1, &_settings_game.vehicle.road_side ),
1758 OCL_VAR ( OC_UINT8, 1, &_settings_game.game_creation.town_name ),
1759
1760 OCL_CHUNK( 1, LoadOldGameDifficulty ),
1761
1762 OCL_ASSERT( OC_TTD, 0x77130 ),
1763
1764 OCL_VAR ( OC_UINT8, 1, &_old_diff_level ),
1765
1766 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_settings_game.game_creation.landscape ),
1767 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_trees_tick_ctr ),
1768
1769 OCL_CNULL( OC_TTD, 1 ),
1770 OCL_VAR ( OC_TTD | OC_UINT8, 1, &_settings_game.game_creation.snow_line_height ),
1771
1772 OCL_CNULL( OC_TTD, 32 ),
1773 OCL_CNULL( OC_TTD, 36 ),
1774
1775 OCL_ASSERT( OC_TTD, 0x77179 ),
1776 OCL_ASSERT( OC_TTO, 0x4971D ),
1777
1778 OCL_CHUNK( 1, LoadOldMapPart2 ),
1779
1780 OCL_ASSERT( OC_TTD, 0x97179 ),
1781 OCL_ASSERT( OC_TTO, 0x6971D ),
1782
1783 /* Below any (if available) extra chunks from TTDPatch can follow */
1784 OCL_CHUNK(1, LoadTTDPatchExtraChunks),
1785
1786 OCL_END()
1787};
1788
1789bool LoadTTDMain(LoadgameState &ls)
1790{
1791 Debug(oldloader, 3, "Reading main chunk...");
1792
1793 _read_ttdpatch_flags = false;
1794
1795 /* Load the biggest chunk */
1796 if (!LoadChunk(ls, nullptr, main_chunk)) {
1797 Debug(oldloader, 0, "Loading failed");
1798 return false;
1799 }
1800
1801 Debug(oldloader, 3, "Done, converting game data...");
1802
1803 FixTTDMapArray();
1804 FixTTDDepots();
1805
1806 /* Fix some general stuff */
1807 if (to_underlying(_settings_game.game_creation.landscape) >= NUM_LANDSCAPE) _settings_game.game_creation.landscape = LandscapeType::Temperate;
1808
1809 /* Fix the game to be compatible with OpenTTD */
1810 FixOldTowns();
1811 FixOldVehicles(ls);
1812
1813 /* We have a new difficulty setting */
1814 _settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
1815
1816 Debug(oldloader, 3, "Finished converting game data");
1817 Debug(oldloader, 1, "TTD(Patch) savegame successfully converted");
1818
1819 return true;
1820}
1821
1822bool LoadTTOMain(LoadgameState &ls)
1823{
1824 Debug(oldloader, 3, "Reading main chunk...");
1825
1826 _read_ttdpatch_flags = false;
1827
1828 std::array<uint8_t, 103 * sizeof(Engine)> engines; // we don't want to call Engine constructor here
1829 _old_engines = (Engine *)engines.data();
1830
1831 /* Load the biggest chunk */
1832 if (!LoadChunk(ls, nullptr, main_chunk)) {
1833 Debug(oldloader, 0, "Loading failed");
1834 return false;
1835 }
1836 Debug(oldloader, 3, "Done, converting game data...");
1837
1839
1840 _settings_game.game_creation.landscape = LandscapeType::Temperate;
1841 _trees_tick_ctr = 0xFF;
1842
1843 if (!FixTTOMapArray() || !FixTTOEngines()) {
1844 Debug(oldloader, 0, "Conversion failed");
1845 return false;
1846 }
1847
1848 FixOldTowns();
1849 FixOldVehicles(ls);
1850 FixTTOCompanies();
1851
1852 /* We have a new difficulty setting */
1853 _settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
1854
1855 /* SVXConverter about cargo payment rates correction:
1856 * "increase them to compensate for the faster time advance in TTD compared to TTO
1857 * which otherwise would cause much less income while the annual running costs of
1858 * the vehicles stay the same" */
1859 _economy.inflation_payment = std::min(_economy.inflation_payment * 124 / 74, MAX_INFLATION);
1860
1861 Debug(oldloader, 3, "Finished converting game data");
1862 Debug(oldloader, 1, "TTO savegame successfully converted");
1863
1864 return true;
1865}
AirportBlock
Movement Blocks on Airports blocks (eg_airport_flags).
Definition airport.h:90
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
debug_inline 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 ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:106
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
Definition cargo_type.h:75
@ TAE_FOOD
Cargo behaves food/fizzy-drinks-like.
Definition cargotype.h:29
@ TAE_WATER
Cargo behaves water-like.
Definition cargotype.h:28
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
void Append(CargoPacket *cp, StationID next)
Appends the given cargo packet to the range of packets with the same next station.
Wrapper class to abstract away the way the tiles are stored.
Definition map_func.h:25
debug_inline uint8_t & m4()
General purpose.
Definition map_func.h:149
debug_inline uint8_t & m3()
General purpose.
Definition map_func.h:137
debug_inline uint8_t & m5()
General purpose.
Definition map_func.h:161
A timeout timer will fire once after the interval.
Definition timer.h:116
static Date ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
static constexpr TimerGame< struct Economy >::Year ORIGINAL_BASE_YEAR
The minimum starting year/base year of the original TTD.
static constexpr TimerGame< struct Calendar >::Date DAYS_TILL_ORIGINAL_BASE_YEAR
The date of the first day of the original base year.
static Date date
Current date in days (day counter).
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
void Append(CargoPacket *cp, MoveToAction action=MTA_KEEP)
Appends the given cargo packet.
Money CalculateCompanyValue(const Company *c, bool including_loan=true)
Calculate the value of the company.
Definition economy.cpp:150
uint _cur_company_tick_index
used to generate a name for one company that doesn't have a name yet per tick
TimeoutTimer< TimerGameTick > _new_competitor_timeout({ TimerGameTick::Priority::COMPETITOR_TIMEOUT, 0 }, []() { if(_game_mode==GM_MENU||!AI::CanStartNew()) return;if(_networking &&Company::GetNumItems() >=_settings_client.network.max_companies) return;if(_settings_game.difficulty.competitors_interval==0) return;uint8_t n=0;for(const Company *c :Company::Iterate()) { if(c->is_ai) n++;} if(n >=_settings_game.difficulty.max_no_competitors) return;Command< CMD_COMPANY_CTRL >::Post(CCA_NEW_AI, CompanyID::Invalid(), CRR_NONE, INVALID_CLIENT_ID);})
Start a new competitor company if possible.
ReferenceThroughBaseContainer< std::array< Colours, MAX_COMPANIES > > _company_colours
NOSAVE: can be determined from company structs.
static constexpr Owner OWNER_NONE
The tile has no ownership.
static constexpr Owner OWNER_WATER
The tile/execution is done by "water".
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
DepotID GetDepotIndex(Tile t)
Get the index of which depot is attached to the tile.
Definition depot_map.h:53
bool IsDepotTile(Tile tile)
Is the given tile a tile with a depot on it?
Definition depot_map.h:42
PoolID< uint16_t, struct DepotIDTag, 64000, 0xFFFF > DepotID
Type for the unique identifier of depots.
Definition depot_type.h:15
static const uint64_t MAX_INFLATION
Maximum inflation (including fractional part) without causing overflows in int64_t price computations...
void StartupOneEngine(Engine *e, const TimerGameCalendar::YearMonthDay &aging_ymd, uint32_t seed)
Start/initialise one engine.
Definition engine.cpp:718
void CalcEngineReliability(Engine *e, bool new_month)
Update Engine::reliability and (if needed) update the engine GUIs.
Definition engine.cpp:647
@ Available
This vehicle is available to everyone.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Definition enum_type.hpp:17
uint32_t _ttdp_version
version of TTDP savegame (if applicable)
Definition saveload.cpp:68
SavegameType _savegame_type
type of savegame we are loading
Definition saveload.cpp:65
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ Random
Randomise borders.
static debug_inline TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition map_func.h:372
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
GRFConfigList _grfconfig
First item in list of current GRF set up.
void AppendStaticGRFConfigs(GRFConfigList &dst)
Appends the static GRFs to a list of GRFs.
void AppendToGRFConfigList(GRFConfigList &dst, std::unique_ptr< GRFConfig > &&el)
Appends an element to a list of GRFs.
void ClearGRFConfigList(GRFConfigList &config)
Clear a GRF Config list, freeing all nodes.
@ Invalid
GRF is unusable with this version of OpenTTD.
bool LoadChunk(LoadgameState &ls, void *base, const OldChunks *chunks)
Loads a chunk from the old savegame.
uint8_t ReadByte(LoadgameState &ls)
Reads a byte from the buffer and decompress if needed.
Definition oldloader.cpp:86
Declarations of structures and functions used in loader of old savegames.
@ OC_TTO
-//- TTO (default is neither of these)
Definition oldloader.h:46
@ OC_TTD
chunk is valid ONLY for TTD savegames
Definition oldloader.h:45
std::unique_ptr< std::string[]> _old_name_array
Location to load the old names to.
bool LoadOldCustomString(LoadgameState &ls, int index)
Read a single string from the savegame.
void FixOldVehicles(LoadgameState &ls)
Convert the old style vehicles into something that resembles the old new style savegames.
bool LoadOldVehicle(LoadgameState &ls, int num)
Load the vehicles of an old style savegame.
static void FixTTDDepots()
uint16_t _disaster_delay
Delay counter for considering the next disaster.
static bool _read_ttdpatch_flags
Have we (tried to) read TTDPatch extra flags?
static Colours RemapTTOColour(Colours tto)
static uint16_t _old_extra_chunk_nums
Number of extra TTDPatch chunks.
static bool FixTTOEngines()
uint8_t _age_cargo_skip_counter
Skip aging of cargo? Used before savegame version 162.
Definition misc_sl.cpp:79
uint8_t _trees_tick_ctr
Determines when to consider building more trees.
Definition tree_cmd.cpp:56
std::vector< TileIndex > _animated_tiles
The table/list with animated tiles.
OldOrderSaveLoadItem * GetOldOrder(size_t pool_index)
Get a pointer to an old order with the given reference index.
Definition order_sl.cpp:122
OldOrderSaveLoadItem & AllocateOldOrder(size_t pool_index)
Allocate an old order with the given pool index.
Definition order_sl.cpp:134
Order UnpackOldOrder(uint16_t packed)
Unpacks a order from savegames made with TTD(Patch)
Definition order_sl.cpp:92
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
Randomizer _random
Random used in the game state calculations.
@ RVS_IN_DT_ROAD_STOP
The vehicle is in a drive-through road stop.
Definition roadveh.h:46
@ RVSB_IN_DEPOT
The vehicle is in a depot.
Definition roadveh.h:38
@ RVSB_WORMHOLE
The vehicle is in a tunnel and/or bridge.
Definition roadveh.h:39
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition saveload.cpp:357
@ SGT_TTDP2
TTDP savegame in new format (data at SE border)
Definition saveload.h:431
@ SGT_TTO
TTO savegame.
Definition saveload.h:433
@ SGT_TTDP1
TTDP savegame ( -//- ) (data at NW border)
Definition saveload.h:430
Declaration of functions used in more save/load files.
StringID RemapOldStringID(StringID s)
Remap a string ID from the old format to the new format.
std::string CopyFromOldName(StringID id)
Copy and convert old custom names to UTF-8.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
PoolID< uint16_t, struct SignIDTag, 64000, 0xFFFF > SignID
The type of the IDs of signs.
Definition signs_type.h:16
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
static constexpr StringID SPECSTR_PRESIDENT_NAME
Special string for the president's name.
static constexpr StringID SPECSTR_TOWNNAME_START
Special strings for town names.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition aircraft.h:72
AirportBlocks blocks
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
uint8_t type
Type of this airport,.
StringID string_id
Default name (town area) of station.
TileIndex xy
Base tile of the station.
Town * town
The town this station is associated with.
VehicleType type
Type of vehicle.
Container for cargo from the same location and time.
Definition cargopacket.h:41
Statistics about the economy.
Money income
The amount of income.
Money expenses
The amount of expenses.
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
StringID name_1
Name of the company if the user did not change it.
Money current_loan
Amount of money borrowed from the bank.
TimerGameEconomy::Year inaugurated_year
Economy year of starting the company.
CompanyEconomyEntry cur_economy
Economic data of the company of this quarter.
Colours colour
Company colour.
std::array< CompanyEconomyEntry, MAX_HISTORY_QUARTERS > old_economy
Economic data of the company of the last MAX_HISTORY_QUARTERS quarters.
CompanyManagerFace face
Face description of the president.
std::array< Expenses, 3 > yearly_expenses
Expenses of the company for the last three years.
StringID president_name_1
Name of the president if the user did not change it.
Money money
Money owned by the company.
Settings related to the difficulty of the game.
uint32_t max_loan
the maximum initial loan
uint8_t town_council_tolerance
minimum required town ratings to be allowed to demolish stuff
Disasters, like submarines, skyrangers and their shadows, belong to this class.
uint16_t state
Action stage of the disaster vehicle.
uint64_t inflation_payment
Cumulated inflation of cargo payment since game start; 16 bit fractional part.
uint8_t infl_amount
inflation amount
Money old_max_loan_unround
Old: Unrounded max loan.
int16_t fluct
Economy fluctuation status.
uint8_t infl_amount_pr
inflation rate for payment rates
uint8_t interest_rate
Interest.
A special vehicle is one of the following:
LandscapeTypes climates
Climates supported by the engine.
uint16_t reliability_spd_dec
Speed of reliability decay between services (per day).
Definition engine_base.h:49
uint16_t reliability_start
Initial reliability of the engine.
Definition engine_base.h:50
TimerGameCalendar::Date intro_date
Date of introduction of the engine.
Definition engine_base.h:45
EngineFlags flags
Flags of the engine.
Definition engine_base.h:56
CompanyMask company_avail
Bit for each company whether the engine is available for that company.
Definition engine_base.h:39
uint16_t reliability_max
Maximal reliability of the engine.
Definition engine_base.h:51
uint16_t reliability_final
Final reliability of the engine.
Definition engine_base.h:52
CompanyID preview_company
Company which is currently being offered a preview CompanyID::Invalid() means no company.
Definition engine_base.h:58
uint16_t duration_phase_3
Third reliability phase in months, decaying to reliability_final.
Definition engine_base.h:55
uint16_t duration_phase_2
Second reliability phase in months, keeping reliability_max.
Definition engine_base.h:54
uint8_t preview_wait
Daily countdown timer for timeout of offering the engine to the preview_company company.
Definition engine_base.h:59
uint16_t reliability
Current reliability of the engine.
Definition engine_base.h:48
CompanyMask preview_asked
Bit for each company which has already been offered a preview.
Definition engine_base.h:41
int32_t age
Age of the engine in months.
Definition engine_base.h:46
std::string name
Custom name of engine.
Definition engine_base.h:43
uint16_t duration_phase_1
First reliability phase in months, increasing reliability from reliability_start to reliability_max.
Definition engine_base.h:53
LandscapeType landscape
the landscape we're currently in
uint8_t snow_line_height
the configured snow line height (deduced from "snow_coverage")
uint8_t town_name
the town name generator used for town names
LocaleSettings locale
settings related to used currency/unit system in the current game
DifficultySettings difficulty
settings related to the difficulty
GameCreationSettings game_creation
settings used during the creation of a game (map)
VehicleSettings vehicle
options for vehicles
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Stores station stats for a single cargo.
States status
Status of this cargo, see State.
@ Acceptance
Set when the station accepts the cargo currently for final deliveries.
@ Rating
This indicates whether a cargo has a rating at the station.
GoodsEntryData & GetOrCreateData()
Get optional cargo packet/flow data.
Defines the internal data of a functional industry.
Definition industry.h:64
IndustryType type
type of industry.
Definition industry.h:100
Colours random_colour
randomized colour of the industry, for display purpose
Definition industry.h:102
TimerGameEconomy::Year last_prod_year
last economy year of production
Definition industry.h:103
ProducedCargoes produced
produced cargo slots
Definition industry.h:95
Town * town
Nearest town.
Definition industry.h:93
AcceptedCargoes accepted
accepted cargo slots
Definition industry.h:96
TileArea location
Location of the industry.
Definition industry.h:92
static std::array< FlatSet< IndustryID >, NUM_INDUSTRYTYPES > industries
List of industries of each type.
Definition industry.h:261
uint8_t vehicle_multiplier
TTDPatch vehicle multiplier.
Definition oldloader.h:33
uint8_t currency
currency we currently use
Size related data of the map.
Definition map_func.h:206
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:362
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition map_func.h:305
static void Allocate(uint size_x, uint size_y)
(Re)allocates a map with the given dimension
Definition map.cpp:35
static debug_inline uint Size()
Get the size of the map.
Definition map_func.h:287
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Compatibility struct to allow saveload of pool-based orders.
Definition order_base.h:248
Order order
The order data.
Definition order_base.h:251
uint32_t next
The next order index (1-based).
Definition order_base.h:250
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:99
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:66
void AssignOrder(const Order &other)
Assign data to an order (from another order) This function makes sure that the index is maintained co...
TileIndex tile
The base tile of the area.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * GetIfValid(auto index)
Returns Titem with given index.
uint32_t state[2]
The state of the randomizer.
Buses, trucks and trams belong to this class.
Definition roadveh.h:98
uint8_t state
Definition roadveh.h:100
All ships have this type.
Definition ship.h:32
static Station * Get(auto index)
Gets station with given index.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Station data structure.
std::array< GoodsEntry, NUM_CARGO > goods
Goods at this station.
Airport airport
Tile area the airport covers.
Templated helper to make a type-safe 'typedef' representing a single POD value.
Struct about subsidies, offered and awarded.
CargoType cargo_type
Cargo type involved in this subsidy, INVALID_CARGO for invalid subsidy.
Town data structure.
Definition town.h:52
TileIndex xy
town center tile
Definition town.h:53
'Train' is either a loco or a wagon.
Definition train.h:91
uint8_t road_side
the side of the road vehicles drive on
Vehicle data structure.
VehicleCargoList cargo
The cargo this vehicle is carrying.
uint16_t cargo_cap
total capacity
CargoType cargo_type
type of cargo this vehicle is carrying
Order current_order
The current order (+ status, like: loading)
uint16_t refit_cap
Capacity left over from before last refit.
uint32_t old_orders
Only used during conversion of old save games.
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
Vehicle * next
pointer to the next vehicle in the chain
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
TileIndex tile
Current tile index.
PoolID< uint16_t, struct SubsidyIDTag, 256, 0xFFFF > SubsidyID
ID of a subsidy.
void SetTileType(Tile tile, TileType type)
Set the type of a tile.
Definition tile_map.h:131
void SetTileOwner(Tile tile, Owner owner)
Sets the owner of a tile.
Definition tile_map.h:198
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
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:87
TileType
The different types of tiles.
Definition tile_type.h:47
@ MP_TREES
Tile got trees.
Definition tile_type.h:52
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:48
@ MP_HOUSE
A house by a town.
Definition tile_type.h:51
@ MP_WATER
Water tile.
Definition tile_type.h:54
@ MP_RAILWAY
A railway.
Definition tile_type.h:49
@ MP_INDUSTRY
Part of an industry.
Definition tile_type.h:56
@ MP_VOID
Invisible tiles at the SW and SE border.
Definition tile_type.h:55
@ MP_OBJECT
Contains objects such as transmitters and owned land.
Definition tile_type.h:58
Town * CalcClosestTownFromTile(TileIndex tile, uint threshold=UINT_MAX)
Return the town closest to the given tile within threshold.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
PoolID< uint32_t, struct VehicleIDTag, 0xFF000, 0xFFFFF > VehicleID
The type all our vehicle IDs have.
@ VEH_ROAD
Road vehicle type.
@ VEH_DISASTER
Disaster vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_EFFECT
Effect vehicle type (smoke, explosions, sparks, bubbles)
@ VEH_TRAIN
Train vehicle type.
void MakeSea(Tile t)
Make a sea tile.
Definition water_map.h:422