Update: Translations from eints
[openttd-github.git] / src / saveload / company_sl.cpp
blob5abf18157bbf8461d995bee7fe06e65c834d52a4
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 */
8 /** @file company_sl.cpp Code handling saving and loading of company data */
10 #include "../stdafx.h"
12 #include "saveload.h"
13 #include "compat/company_sl_compat.h"
15 #include "../company_func.h"
16 #include "../company_manager_face.h"
17 #include "../fios.h"
18 #include "../tunnelbridge_map.h"
19 #include "../tunnelbridge.h"
20 #include "../station_base.h"
21 #include "../strings_func.h"
23 #include "table/strings.h"
25 #include "../safeguards.h"
27 /**
28 * Converts an old company manager's face format to the new company manager's face format
30 * Meaning of the bits in the old face (some bits are used in several times):
31 * - 4 and 5: chin
32 * - 6 to 9: eyebrows
33 * - 10 to 13: nose
34 * - 13 to 15: lips (also moustache for males)
35 * - 16 to 19: hair
36 * - 20 to 22: eye colour
37 * - 20 to 27: tie, ear rings etc.
38 * - 28 to 30: glasses
39 * - 19, 26 and 27: race (bit 27 set and bit 19 equal to bit 26 = black, otherwise white)
40 * - 31: gender (0 = male, 1 = female)
42 * @param face the face in the old format
43 * @return the face in the new format
45 CompanyManagerFace ConvertFromOldCompanyManagerFace(uint32_t face)
47 CompanyManagerFace cmf = 0;
48 GenderEthnicity ge = GE_WM;
50 if (HasBit(face, 31)) SetBit(ge, GENDER_FEMALE);
51 if (HasBit(face, 27) && (HasBit(face, 26) == HasBit(face, 19))) SetBit(ge, ETHNICITY_BLACK);
53 SetCompanyManagerFaceBits(cmf, CMFV_GEN_ETHN, ge, ge);
54 SetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge, GB(face, 28, 3) <= 1);
55 SetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge, HasBit(ge, ETHNICITY_BLACK) ? 0 : ClampU(GB(face, 20, 3), 5, 7) - 5);
56 SetCompanyManagerFaceBits(cmf, CMFV_CHIN, ge, ScaleCompanyManagerFaceValue(CMFV_CHIN, ge, GB(face, 4, 2)));
57 SetCompanyManagerFaceBits(cmf, CMFV_EYEBROWS, ge, ScaleCompanyManagerFaceValue(CMFV_EYEBROWS, ge, GB(face, 6, 4)));
58 SetCompanyManagerFaceBits(cmf, CMFV_HAIR, ge, ScaleCompanyManagerFaceValue(CMFV_HAIR, ge, GB(face, 16, 4)));
59 SetCompanyManagerFaceBits(cmf, CMFV_JACKET, ge, ScaleCompanyManagerFaceValue(CMFV_JACKET, ge, GB(face, 20, 2)));
60 SetCompanyManagerFaceBits(cmf, CMFV_COLLAR, ge, ScaleCompanyManagerFaceValue(CMFV_COLLAR, ge, GB(face, 22, 2)));
61 SetCompanyManagerFaceBits(cmf, CMFV_GLASSES, ge, GB(face, 28, 1));
63 uint lips = GB(face, 10, 4);
64 if (!HasBit(ge, GENDER_FEMALE) && lips < 4) {
65 SetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge, true);
66 SetCompanyManagerFaceBits(cmf, CMFV_MOUSTACHE, ge, std::max(lips, 1U) - 1);
67 } else {
68 if (!HasBit(ge, GENDER_FEMALE)) {
69 lips = lips * 15 / 16;
70 lips -= 3;
71 if (HasBit(ge, ETHNICITY_BLACK) && lips > 8) lips = 0;
72 } else {
73 lips = ScaleCompanyManagerFaceValue(CMFV_LIPS, ge, lips);
75 SetCompanyManagerFaceBits(cmf, CMFV_LIPS, ge, lips);
77 uint nose = GB(face, 13, 3);
78 if (ge == GE_WF) {
79 nose = (nose * 3 >> 3) * 3 >> 2; // There is 'hole' in the nose sprites for females
80 } else {
81 nose = ScaleCompanyManagerFaceValue(CMFV_NOSE, ge, nose);
83 SetCompanyManagerFaceBits(cmf, CMFV_NOSE, ge, nose);
86 uint tie_earring = GB(face, 24, 4);
87 if (!HasBit(ge, GENDER_FEMALE) || tie_earring < 3) { // Not all females have an earring
88 if (HasBit(ge, GENDER_FEMALE)) SetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge, true);
89 SetCompanyManagerFaceBits(cmf, CMFV_TIE_EARRING, ge, HasBit(ge, GENDER_FEMALE) ? tie_earring : ScaleCompanyManagerFaceValue(CMFV_TIE_EARRING, ge, tie_earring / 2));
92 return cmf;
95 /** Rebuilding of company statistics after loading a savegame. */
96 void AfterLoadCompanyStats()
98 /* Reset infrastructure statistics to zero. */
99 for (Company *c : Company::Iterate()) c->infrastructure = {};
101 /* Collect airport count. */
102 for (const Station *st : Station::Iterate()) {
103 if ((st->facilities & FACIL_AIRPORT) && Company::IsValidID(st->owner)) {
104 Company::Get(st->owner)->infrastructure.airport++;
108 Company *c;
109 for (TileIndex tile = 0; tile < Map::Size(); tile++) {
110 switch (GetTileType(tile)) {
111 case MP_RAILWAY:
112 c = Company::GetIfValid(GetTileOwner(tile));
113 if (c != nullptr) {
114 uint pieces = 1;
115 if (IsPlainRail(tile)) {
116 TrackBits bits = GetTrackBits(tile);
117 pieces = CountBits(bits);
118 if (TracksOverlap(bits)) pieces *= pieces;
120 c->infrastructure.rail[GetRailType(tile)] += pieces;
122 if (HasSignals(tile)) c->infrastructure.signal += CountBits(GetPresentSignals(tile));
124 break;
126 case MP_ROAD: {
127 if (IsLevelCrossing(tile)) {
128 c = Company::GetIfValid(GetTileOwner(tile));
129 if (c != nullptr) c->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
132 /* Iterate all present road types as each can have a different owner. */
133 for (RoadTramType rtt : _roadtramtypes) {
134 RoadType rt = GetRoadType(tile, rtt);
135 if (rt == INVALID_ROADTYPE) continue;
136 c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rtt));
137 /* A level crossings and depots have two road bits. */
138 if (c != nullptr) c->infrastructure.road[rt] += IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rtt)) : 2;
140 break;
143 case MP_STATION:
144 c = Company::GetIfValid(GetTileOwner(tile));
145 if (c != nullptr && GetStationType(tile) != STATION_AIRPORT && !IsBuoy(tile)) c->infrastructure.station++;
147 switch (GetStationType(tile)) {
148 case STATION_RAIL:
149 case STATION_WAYPOINT:
150 if (c != nullptr && !IsStationTileBlocked(tile)) c->infrastructure.rail[GetRailType(tile)]++;
151 break;
153 case STATION_BUS:
154 case STATION_TRUCK:
155 case STATION_ROADWAYPOINT: {
156 /* Iterate all present road types as each can have a different owner. */
157 for (RoadTramType rtt : _roadtramtypes) {
158 RoadType rt = GetRoadType(tile, rtt);
159 if (rt == INVALID_ROADTYPE) continue;
160 c = Company::GetIfValid(GetRoadOwner(tile, rtt));
161 if (c != nullptr) c->infrastructure.road[rt] += 2; // A road stop has two road bits.
163 break;
166 case STATION_DOCK:
167 case STATION_BUOY:
168 if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
169 if (c != nullptr) c->infrastructure.water++;
171 break;
173 default:
174 break;
176 break;
178 case MP_WATER:
179 if (IsShipDepot(tile) || IsLock(tile)) {
180 c = Company::GetIfValid(GetTileOwner(tile));
181 if (c != nullptr) {
182 if (IsShipDepot(tile)) c->infrastructure.water += LOCK_DEPOT_TILE_FACTOR;
183 if (IsLock(tile) && GetLockPart(tile) == LOCK_PART_MIDDLE) {
184 /* The middle tile specifies the owner of the lock. */
185 c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // the middle tile specifies the owner of the
186 break; // do not count the middle tile as canal
190 [[fallthrough]];
192 case MP_OBJECT:
193 if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
194 c = Company::GetIfValid(GetTileOwner(tile));
195 if (c != nullptr) c->infrastructure.water++;
197 break;
199 case MP_TUNNELBRIDGE: {
200 /* Only count the tunnel/bridge if we're on the northern end tile. */
201 TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
202 if (tile < other_end) {
203 /* Count each tunnel/bridge TUNNELBRIDGE_TRACKBIT_FACTOR times to simulate
204 * the higher structural maintenance needs, and don't forget the end tiles. */
205 uint len = (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
207 switch (GetTunnelBridgeTransportType(tile)) {
208 case TRANSPORT_RAIL:
209 c = Company::GetIfValid(GetTileOwner(tile));
210 if (c != nullptr) c->infrastructure.rail[GetRailType(tile)] += len;
211 break;
213 case TRANSPORT_ROAD: {
214 /* Iterate all present road types as each can have a different owner. */
215 for (RoadTramType rtt : _roadtramtypes) {
216 RoadType rt = GetRoadType(tile, rtt);
217 if (rt == INVALID_ROADTYPE) continue;
218 c = Company::GetIfValid(GetRoadOwner(tile, rtt));
219 if (c != nullptr) c->infrastructure.road[rt] += len * 2; // A full diagonal road has two road bits.
221 break;
224 case TRANSPORT_WATER:
225 c = Company::GetIfValid(GetTileOwner(tile));
226 if (c != nullptr) c->infrastructure.water += len;
227 break;
229 default:
230 break;
233 break;
236 default:
237 break;
242 /* We do need to read this single value, as the bigger it gets, the more data is stored */
243 struct CompanyOldAI {
244 uint8_t num_build_rec;
247 class SlCompanyOldAIBuildRec : public DefaultSaveLoadHandler<SlCompanyOldAIBuildRec, CompanyOldAI> {
248 public:
249 inline static const SaveLoad description[] = {{}}; // Needed to keep DefaultSaveLoadHandler happy.
250 inline const static SaveLoadCompatTable compat_description = _company_old_ai_buildrec_compat;
252 SaveLoadTable GetDescription() const override { return {}; }
254 void Load(CompanyOldAI *old_ai) const override
256 for (int i = 0; i != old_ai->num_build_rec; i++) {
257 SlObject(nullptr, this->GetLoadDescription());
261 void LoadCheck(CompanyOldAI *old_ai) const override { this->Load(old_ai); }
264 class SlCompanyOldAI : public DefaultSaveLoadHandler<SlCompanyOldAI, CompanyProperties> {
265 public:
266 inline static const SaveLoad description[] = {
267 SLE_CONDVAR(CompanyOldAI, num_build_rec, SLE_UINT8, SL_MIN_VERSION, SLV_107),
268 SLEG_STRUCTLIST("buildrec", SlCompanyOldAIBuildRec),
270 inline const static SaveLoadCompatTable compat_description = _company_old_ai_compat;
272 void Load(CompanyProperties *c) const override
274 if (!c->is_ai) return;
276 CompanyOldAI old_ai;
277 SlObject(&old_ai, this->GetLoadDescription());
280 void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
283 class SlCompanySettings : public DefaultSaveLoadHandler<SlCompanySettings, CompanyProperties> {
284 public:
285 inline static const SaveLoad description[] = {
286 /* Engine renewal settings */
287 SLE_CONDREF(CompanyProperties, engine_renew_list, REF_ENGINE_RENEWS, SLV_19, SL_MAX_VERSION),
288 SLE_CONDVAR(CompanyProperties, settings.engine_renew, SLE_BOOL, SLV_16, SL_MAX_VERSION),
289 SLE_CONDVAR(CompanyProperties, settings.engine_renew_months, SLE_INT16, SLV_16, SL_MAX_VERSION),
290 SLE_CONDVAR(CompanyProperties, settings.engine_renew_money, SLE_UINT32, SLV_16, SL_MAX_VERSION),
291 SLE_CONDVAR(CompanyProperties, settings.renew_keep_length, SLE_BOOL, SLV_2, SL_MAX_VERSION),
293 /* Default vehicle settings */
294 SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_ispercent, SLE_BOOL, SLV_120, SL_MAX_VERSION),
295 SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_trains, SLE_UINT16, SLV_120, SL_MAX_VERSION),
296 SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_roadveh, SLE_UINT16, SLV_120, SL_MAX_VERSION),
297 SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_aircraft, SLE_UINT16, SLV_120, SL_MAX_VERSION),
298 SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_ships, SLE_UINT16, SLV_120, SL_MAX_VERSION),
300 inline const static SaveLoadCompatTable compat_description = _company_settings_compat;
302 void Save(CompanyProperties *c) const override
304 SlObject(c, this->GetDescription());
307 void Load(CompanyProperties *c) const override
309 SlObject(c, this->GetLoadDescription());
312 void FixPointers(CompanyProperties *c) const override
314 SlObject(c, this->GetDescription());
317 void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
320 class SlCompanyEconomy : public DefaultSaveLoadHandler<SlCompanyEconomy, CompanyProperties> {
321 public:
322 inline static const SaveLoad description[] = {
323 SLE_CONDVAR(CompanyEconomyEntry, income, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
324 SLE_CONDVAR(CompanyEconomyEntry, income, SLE_INT64, SLV_2, SL_MAX_VERSION),
325 SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
326 SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_INT64, SLV_2, SL_MAX_VERSION),
327 SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
328 SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_INT64, SLV_2, SL_MAX_VERSION),
330 SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, SL_MIN_VERSION, SLV_170),
331 SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, SLV_170, SLV_EXTEND_CARGOTYPES),
332 SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
333 SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32),
335 inline const static SaveLoadCompatTable compat_description = _company_economy_compat;
337 void Save(CompanyProperties *c) const override
339 SlObject(&c->cur_economy, this->GetDescription());
342 void Load(CompanyProperties *c) const override
344 SlObject(&c->cur_economy, this->GetLoadDescription());
347 void FixPointers(CompanyProperties *c) const override
349 SlObject(&c->cur_economy, this->GetDescription());
352 void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
355 class SlCompanyOldEconomy : public SlCompanyEconomy {
356 public:
357 void Save(CompanyProperties *c) const override
359 SlSetStructListLength(c->num_valid_stat_ent);
360 for (int i = 0; i < c->num_valid_stat_ent; i++) {
361 SlObject(&c->old_economy[i], this->GetDescription());
365 void Load(CompanyProperties *c) const override
367 if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) {
368 c->num_valid_stat_ent = (uint8_t)SlGetStructListLength(UINT8_MAX);
370 if (c->num_valid_stat_ent > lengthof(c->old_economy)) SlErrorCorrupt("Too many old economy entries");
372 for (int i = 0; i < c->num_valid_stat_ent; i++) {
373 SlObject(&c->old_economy[i], this->GetLoadDescription());
377 void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
380 class SlCompanyLiveries : public DefaultSaveLoadHandler<SlCompanyLiveries, CompanyProperties> {
381 public:
382 inline static const SaveLoad description[] = {
383 SLE_CONDVAR(Livery, in_use, SLE_UINT8, SLV_34, SL_MAX_VERSION),
384 SLE_CONDVAR(Livery, colour1, SLE_UINT8, SLV_34, SL_MAX_VERSION),
385 SLE_CONDVAR(Livery, colour2, SLE_UINT8, SLV_34, SL_MAX_VERSION),
387 inline const static SaveLoadCompatTable compat_description = _company_liveries_compat;
390 * Get the number of liveries used by this savegame version.
391 * @return The number of liveries used by this savegame version.
393 size_t GetNumLiveries() const
395 if (IsSavegameVersionBefore(SLV_63)) return LS_END - 4;
396 if (IsSavegameVersionBefore(SLV_85)) return LS_END - 2;
397 if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return LS_END;
398 /* Read from the savegame how long the list is. */
399 return SlGetStructListLength(LS_END);
402 void Save(CompanyProperties *c) const override
404 SlSetStructListLength(LS_END);
405 for (int i = 0; i < LS_END; i++) {
406 SlObject(&c->livery[i], this->GetDescription());
410 void Load(CompanyProperties *c) const override
412 size_t num_liveries = this->GetNumLiveries();
413 bool update_in_use = IsSavegameVersionBefore(SLV_GROUP_LIVERIES);
415 for (size_t i = 0; i < num_liveries; i++) {
416 SlObject(&c->livery[i], this->GetLoadDescription());
417 if (update_in_use && i != LS_DEFAULT) {
418 if (c->livery[i].in_use == 0) {
419 c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
420 c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
421 } else {
422 c->livery[i].in_use = 3;
427 if (IsSavegameVersionBefore(SLV_85)) {
428 /* We want to insert some liveries somewhere in between. This means some have to be moved. */
429 memmove(&c->livery[LS_FREIGHT_WAGON], &c->livery[LS_PASSENGER_WAGON_MONORAIL], (LS_END - LS_FREIGHT_WAGON) * sizeof(c->livery[0]));
430 c->livery[LS_PASSENGER_WAGON_MONORAIL] = c->livery[LS_MONORAIL];
431 c->livery[LS_PASSENGER_WAGON_MAGLEV] = c->livery[LS_MAGLEV];
434 if (IsSavegameVersionBefore(SLV_63)) {
435 /* Copy bus/truck liveries over to trams */
436 c->livery[LS_PASSENGER_TRAM] = c->livery[LS_BUS];
437 c->livery[LS_FREIGHT_TRAM] = c->livery[LS_TRUCK];
441 void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
444 class SlAllowListData : public DefaultSaveLoadHandler<SlAllowListData, CompanyProperties> {
445 public:
446 struct KeyWrapper {
447 std::string key;
450 inline static const SaveLoad description[] = {
451 SLE_SSTR(KeyWrapper, key, SLE_STR),
453 inline const static SaveLoadCompatTable compat_description = {};
455 void Save(CompanyProperties *cprops) const override
457 SlSetStructListLength(cprops->allow_list.size());
458 for (std::string &str : cprops->allow_list) {
459 SlObject(&str, this->GetDescription());
463 void Load(CompanyProperties *cprops) const override
465 size_t num_keys = SlGetStructListLength(UINT32_MAX);
466 cprops->allow_list.clear();
467 cprops->allow_list.resize(num_keys);
468 for (std::string &str : cprops->allow_list) {
469 SlObject(&str, this->GetLoadDescription());
473 void LoadCheck(CompanyProperties *cprops) const override { this->Load(cprops); }
476 /* Save/load of companies */
477 static const SaveLoad _company_desc[] = {
478 SLE_VAR(CompanyProperties, name_2, SLE_UINT32),
479 SLE_VAR(CompanyProperties, name_1, SLE_STRINGID),
480 SLE_CONDSSTR(CompanyProperties, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
482 SLE_VAR(CompanyProperties, president_name_1, SLE_STRINGID),
483 SLE_VAR(CompanyProperties, president_name_2, SLE_UINT32),
484 SLE_CONDSSTR(CompanyProperties, president_name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
486 SLE_CONDVECTOR(CompanyProperties, allow_list, SLE_STR, SLV_COMPANY_ALLOW_LIST, SLV_COMPANY_ALLOW_LIST_V2),
487 SLEG_CONDSTRUCTLIST("allow_list", SlAllowListData, SLV_COMPANY_ALLOW_LIST_V2, SL_MAX_VERSION),
489 SLE_VAR(CompanyProperties, face, SLE_UINT32),
491 /* money was changed to a 64 bit field in savegame version 1. */
492 SLE_CONDVAR(CompanyProperties, money, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SLV_1),
493 SLE_CONDVAR(CompanyProperties, money, SLE_INT64, SLV_1, SL_MAX_VERSION),
495 SLE_CONDVAR(CompanyProperties, current_loan, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SLV_65),
496 SLE_CONDVAR(CompanyProperties, current_loan, SLE_INT64, SLV_65, SL_MAX_VERSION),
497 SLE_CONDVAR(CompanyProperties, max_loan, SLE_INT64, SLV_MAX_LOAN_FOR_COMPANY, SL_MAX_VERSION),
499 SLE_VAR(CompanyProperties, colour, SLE_UINT8),
500 SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8),
501 SLE_VAR(CompanyProperties, block_preview, SLE_UINT8),
503 SLE_CONDVAR(CompanyProperties, location_of_HQ, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
504 SLE_CONDVAR(CompanyProperties, location_of_HQ, SLE_UINT32, SLV_6, SL_MAX_VERSION),
505 SLE_CONDVAR(CompanyProperties, last_build_coordinate, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
506 SLE_CONDVAR(CompanyProperties, last_build_coordinate, SLE_UINT32, SLV_6, SL_MAX_VERSION),
507 SLE_CONDVAR(CompanyProperties, inaugurated_year, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
508 SLE_CONDVAR(CompanyProperties, inaugurated_year, SLE_INT32, SLV_31, SL_MAX_VERSION),
510 SLE_CONDVAR(CompanyProperties, num_valid_stat_ent, SLE_UINT8, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
512 SLE_VAR(CompanyProperties, months_of_bankruptcy, SLE_UINT8),
513 SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
514 SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_UINT16, SLV_104, SL_MAX_VERSION),
515 SLE_VAR(CompanyProperties, bankrupt_timeout, SLE_INT16),
516 SLE_CONDVAR(CompanyProperties, bankrupt_value, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SLV_65),
517 SLE_CONDVAR(CompanyProperties, bankrupt_value, SLE_INT64, SLV_65, SL_MAX_VERSION),
519 /* yearly expenses was changed to 64-bit in savegame version 2. */
520 SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_FILE_I32 | SLE_VAR_I64, 3 * 13, SL_MIN_VERSION, SLV_2),
521 SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 13, SLV_2, SL_MAX_VERSION),
523 SLE_CONDVAR(CompanyProperties, is_ai, SLE_BOOL, SLV_2, SL_MAX_VERSION),
525 SLE_CONDVAR(CompanyProperties, terraform_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION),
526 SLE_CONDVAR(CompanyProperties, clear_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION),
527 SLE_CONDVAR(CompanyProperties, tree_limit, SLE_UINT32, SLV_175, SL_MAX_VERSION),
528 SLEG_STRUCT("settings", SlCompanySettings),
529 SLEG_CONDSTRUCT("old_ai", SlCompanyOldAI, SL_MIN_VERSION, SLV_107),
530 SLEG_STRUCT("cur_economy", SlCompanyEconomy),
531 SLEG_STRUCTLIST("old_economy", SlCompanyOldEconomy),
532 SLEG_CONDSTRUCTLIST("liveries", SlCompanyLiveries, SLV_34, SL_MAX_VERSION),
535 struct PLYRChunkHandler : ChunkHandler {
536 PLYRChunkHandler() : ChunkHandler('PLYR', CH_TABLE) {}
538 void Save() const override
540 SlTableHeader(_company_desc);
542 for (Company *c : Company::Iterate()) {
543 SlSetArrayIndex(c->index);
544 SlObject(c, _company_desc);
548 void Load() const override
550 const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
552 int index;
553 while ((index = SlIterateArray()) != -1) {
554 Company *c = new (index) Company();
555 SlObject(c, slt);
556 _company_colours[index] = c->colour;
561 void LoadCheck(size_t) const override
563 const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
565 int index;
566 while ((index = SlIterateArray()) != -1) {
567 std::unique_ptr<CompanyProperties> cprops = std::make_unique<CompanyProperties>();
568 SlObject(cprops.get(), slt);
570 /* We do not load old custom names */
571 if (IsSavegameVersionBefore(SLV_84)) {
572 if (GetStringTab(cprops->name_1) == TEXT_TAB_OLD_CUSTOM) {
573 cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
576 if (GetStringTab(cprops->president_name_1) == TEXT_TAB_OLD_CUSTOM) {
577 cprops->president_name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
581 if (cprops->name.empty() && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) &&
582 cprops->name_1 != STR_GAME_SAVELOAD_NOT_AVAILABLE && cprops->name_1 != STR_SV_UNNAMED &&
583 cprops->name_1 != SPECSTR_ANDCO_NAME && cprops->name_1 != SPECSTR_PRESIDENT_NAME &&
584 cprops->name_1 != SPECSTR_SILLY_NAME) {
585 cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
588 if (_load_check_data.companies.count(index) == 0) {
589 _load_check_data.companies[index] = std::move(cprops);
594 void FixPointers() const override
596 for (Company *c : Company::Iterate()) {
597 SlObject(c, _company_desc);
602 static const PLYRChunkHandler PLYR;
603 static const ChunkHandlerRef company_chunk_handlers[] = {
604 PLYR,
607 extern const ChunkHandlerTable _company_chunk_handlers(company_chunk_handlers);