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/>.
8 /** @file company_sl.cpp Code handling saving and loading of company data */
10 #include "../stdafx.h"
13 #include "compat/company_sl_compat.h"
15 #include "../company_func.h"
16 #include "../company_manager_face.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"
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):
34 * - 13 to 15: lips (also moustache for males)
36 * - 20 to 22: eye colour
37 * - 20 to 27: tie, ear rings etc.
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);
68 if (!HasBit(ge
, GENDER_FEMALE
)) {
69 lips
= lips
* 15 / 16;
71 if (HasBit(ge
, ETHNICITY_BLACK
) && lips
> 8) lips
= 0;
73 lips
= ScaleCompanyManagerFaceValue(CMFV_LIPS
, ge
, lips
);
75 SetCompanyManagerFaceBits(cmf
, CMFV_LIPS
, ge
, lips
);
77 uint nose
= GB(face
, 13, 3);
79 nose
= (nose
* 3 >> 3) * 3 >> 2; // There is 'hole' in the nose sprites for females
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));
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
++;
109 for (TileIndex tile
= 0; tile
< Map::Size(); tile
++) {
110 switch (GetTileType(tile
)) {
112 c
= Company::GetIfValid(GetTileOwner(tile
));
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
));
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;
144 c
= Company::GetIfValid(GetTileOwner(tile
));
145 if (c
!= nullptr && GetStationType(tile
) != STATION_AIRPORT
&& !IsBuoy(tile
)) c
->infrastructure
.station
++;
147 switch (GetStationType(tile
)) {
149 case STATION_WAYPOINT
:
150 if (c
!= nullptr && !IsStationTileBlocked(tile
)) c
->infrastructure
.rail
[GetRailType(tile
)]++;
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.
168 if (GetWaterClass(tile
) == WATER_CLASS_CANAL
) {
169 if (c
!= nullptr) c
->infrastructure
.water
++;
179 if (IsShipDepot(tile
) || IsLock(tile
)) {
180 c
= Company::GetIfValid(GetTileOwner(tile
));
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
193 if (GetWaterClass(tile
) == WATER_CLASS_CANAL
) {
194 c
= Company::GetIfValid(GetTileOwner(tile
));
195 if (c
!= nullptr) c
->infrastructure
.water
++;
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
)) {
209 c
= Company::GetIfValid(GetTileOwner(tile
));
210 if (c
!= nullptr) c
->infrastructure
.rail
[GetRailType(tile
)] += len
;
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.
224 case TRANSPORT_WATER
:
225 c
= Company::GetIfValid(GetTileOwner(tile
));
226 if (c
!= nullptr) c
->infrastructure
.water
+= len
;
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
> {
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
> {
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;
277 SlObject(&old_ai
, this->GetLoadDescription());
280 void LoadCheck(CompanyProperties
*c
) const override
{ this->Load(c
); }
283 class SlCompanySettings
: public DefaultSaveLoadHandler
<SlCompanySettings
, CompanyProperties
> {
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
> {
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
{
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
> {
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
;
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
> {
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
);
553 while ((index
= SlIterateArray()) != -1) {
554 Company
*c
= new (index
) Company();
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
);
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
[] = {
607 extern const ChunkHandlerTable
_company_chunk_handlers(company_chunk_handlers
);