Merge branch 'master' into infrastructure_sharing
Conflicts: src/aircraft_cmd.cpp src/economy.cpp src/lang/english.txt src/order_gui.cpp src/roadveh_cmd.cpp src/saveload/saveload.cpp src/settings.cpp src/settings_gui.cpp src/train_cmd.cpp
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include "../fios.h"
|
||||
#include "../gamelog_internal.h"
|
||||
#include "../network/network.h"
|
||||
#include "../network/network_func.h"
|
||||
#include "../gfxinit.h"
|
||||
#include "../viewport_func.h"
|
||||
#include "../industry.h"
|
||||
@@ -52,13 +53,17 @@
|
||||
#include "../core/mem_func.hpp"
|
||||
#include "../smallmap_gui.h"
|
||||
#include "../news_func.h"
|
||||
#include "../order_backup.h"
|
||||
#include "../error.h"
|
||||
#include "../disaster_vehicle.h"
|
||||
|
||||
|
||||
#include "saveload_internal.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY);
|
||||
|
||||
/**
|
||||
@@ -75,7 +80,7 @@ void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_wate
|
||||
{
|
||||
/* If the slope is not flat, we always assume 'land' (if allowed). Also for one-corner-raised-shores.
|
||||
* Note: Wrt. autosloping under industry tiles this is the most fool-proof behaviour. */
|
||||
if (GetTileSlope(t) != SLOPE_FLAT) {
|
||||
if (!IsTileFlat(t)) {
|
||||
if (include_invalid_water_class) {
|
||||
SetWaterClass(t, WATER_CLASS_INVALID);
|
||||
return;
|
||||
@@ -249,6 +254,35 @@ static void InitializeWindowsAndCaches()
|
||||
}
|
||||
}
|
||||
|
||||
/* Count number of objects per type */
|
||||
Object *o;
|
||||
FOR_ALL_OBJECTS(o) {
|
||||
Object::IncTypeCount(o->type);
|
||||
}
|
||||
|
||||
/* Identify owners of persistent storage arrays */
|
||||
Industry *i;
|
||||
FOR_ALL_INDUSTRIES(i) {
|
||||
if (i->psa != NULL) {
|
||||
i->psa->feature = GSF_INDUSTRIES;
|
||||
i->psa->tile = i->location.tile;
|
||||
}
|
||||
}
|
||||
Station *s;
|
||||
FOR_ALL_STATIONS(s) {
|
||||
if (s->airport.psa != NULL) {
|
||||
s->airport.psa->feature = GSF_AIRPORTS;
|
||||
s->airport.psa->tile = s->airport.tile;
|
||||
}
|
||||
}
|
||||
Town *t;
|
||||
FOR_ALL_TOWNS(t) {
|
||||
for (std::list<PersistentStorage *>::iterator it = t->psa_list.begin(); it != t->psa_list.end(); ++it) {
|
||||
(*it)->feature = GSF_FAKE_TOWNS;
|
||||
(*it)->tile = t->xy;
|
||||
}
|
||||
}
|
||||
|
||||
RecomputePrices();
|
||||
|
||||
GroupStatistics::UpdateAfterLoad();
|
||||
@@ -459,8 +493,8 @@ static uint FixVehicleInclination(Vehicle *v, Direction dir)
|
||||
byte entry_z = GetSlopePixelZ(entry_x, entry_y);
|
||||
|
||||
/* Compute middle of the tile. */
|
||||
int middle_x = (v->x_pos & ~TILE_UNIT_MASK) + HALF_TILE_SIZE;
|
||||
int middle_y = (v->y_pos & ~TILE_UNIT_MASK) + HALF_TILE_SIZE;
|
||||
int middle_x = (v->x_pos & ~TILE_UNIT_MASK) + TILE_SIZE / 2;
|
||||
int middle_y = (v->y_pos & ~TILE_UNIT_MASK) + TILE_SIZE / 2;
|
||||
byte middle_z = GetSlopePixelZ(middle_x, middle_y);
|
||||
|
||||
/* middle_z == entry_z, no height change. */
|
||||
@@ -473,6 +507,18 @@ static uint FixVehicleInclination(Vehicle *v, Direction dir)
|
||||
return 1U << GVF_GOINGUP_BIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for the possibility that a bridge may be on this tile
|
||||
* These are in fact all the tile types on which a bridge can be found
|
||||
* @param t The tile to analyze
|
||||
* @return True if a bridge might have been present prior to savegame 194.
|
||||
*/
|
||||
static inline bool MayHaveBridgeAbove(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_CLEAR) || IsTileType(t, MP_RAILWAY) || IsTileType(t, MP_ROAD) ||
|
||||
IsTileType(t, MP_WATER) || IsTileType(t, MP_TUNNELBRIDGE) || IsTileType(t, MP_OBJECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a (large) amount of savegame conversion *magic* in order to
|
||||
* load older savegames and to fill the caches for various purposes.
|
||||
@@ -484,6 +530,10 @@ bool AfterLoadGame()
|
||||
|
||||
TileIndex map_size = MapSize();
|
||||
|
||||
extern TileIndex _cur_tileloop_tile; // From landscape.cpp.
|
||||
/* The LFSR used in RunTileLoop iteration cannot have a zeroed state, make it non-zeroed. */
|
||||
if (_cur_tileloop_tile == 0) _cur_tileloop_tile = 1;
|
||||
|
||||
if (IsSavegameVersionBefore(98)) GamelogOldver();
|
||||
|
||||
GamelogTestRevision();
|
||||
@@ -534,6 +584,23 @@ bool AfterLoadGame()
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(194)) {
|
||||
_settings_game.construction.max_heightlevel = 15;
|
||||
|
||||
/* In old savegame versions, the heightlevel was coded in bits 0..3 of the type field */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
_m[t].height = GB(_m[t].type, 0, 4);
|
||||
SB(_m[t].type, 0, 2, GB(_me[t].m6, 0, 2));
|
||||
SB(_me[t].m6, 0, 2, 0);
|
||||
if (MayHaveBridgeAbove(t)) {
|
||||
SB(_m[t].type, 2, 2, GB(_me[t].m6, 6, 2));
|
||||
SB(_me[t].m6, 6, 2, 0);
|
||||
} else {
|
||||
SB(_m[t].type, 2, 2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* in version 2.1 of the savegame, town owner was unified. */
|
||||
if (IsSavegameVersionBefore(2, 1)) ConvertTownOwner();
|
||||
|
||||
@@ -633,7 +700,12 @@ bool AfterLoadGame()
|
||||
SetDate(_date, _date_fract);
|
||||
|
||||
/*
|
||||
* Force the old behaviour for compatability reasons with old savegames.
|
||||
* Force the old behaviour for compatibility reasons with old savegames. As new
|
||||
* settings can only be loaded from new savegames loading old savegames with new
|
||||
* versions of OpenTTD will normally initialize settings newer than the savegame
|
||||
* version with "new game" defaults which the player can define to their liking.
|
||||
* For some settings we override that to keep the behaviour the same as when the
|
||||
* game was saved.
|
||||
*
|
||||
* Note that there is no non-stop in here. This is because the setting could have
|
||||
* either value in TTDPatch. To convert it properly the user has to make sure the
|
||||
@@ -645,9 +717,27 @@ bool AfterLoadGame()
|
||||
if (IsSavegameVersionBefore(21)) _settings_game.vehicle.train_acceleration_model = 0;
|
||||
if (IsSavegameVersionBefore(90)) _settings_game.vehicle.plane_speed = 4;
|
||||
if (IsSavegameVersionBefore(95)) _settings_game.vehicle.dynamic_engines = 0;
|
||||
if (IsSavegameVersionBefore(133)) _settings_game.vehicle.roadveh_acceleration_model = 0;
|
||||
if (IsSavegameVersionBefore(159)) _settings_game.vehicle.max_train_length = 50;
|
||||
if (IsSavegameVersionBefore(96)) _settings_game.economy.station_noise_level = false;
|
||||
if (IsSavegameVersionBefore(133)) {
|
||||
_settings_game.vehicle.roadveh_acceleration_model = 0;
|
||||
_settings_game.vehicle.train_slope_steepness = 3;
|
||||
}
|
||||
if (IsSavegameVersionBefore(134)) _settings_game.economy.feeder_payment_share = 75;
|
||||
if (IsSavegameVersionBefore(138)) _settings_game.vehicle.plane_crashes = 2;
|
||||
if (IsSavegameVersionBefore(139)) _settings_game.vehicle.roadveh_slope_steepness = 7;
|
||||
if (IsSavegameVersionBefore(143)) _settings_game.economy.allow_town_level_crossings = true;
|
||||
if (IsSavegameVersionBefore(159)) {
|
||||
_settings_game.vehicle.max_train_length = 50;
|
||||
_settings_game.construction.max_bridge_length = 64;
|
||||
_settings_game.construction.max_tunnel_length = 64;
|
||||
}
|
||||
if (IsSavegameVersionBefore(166)) _settings_game.economy.infrastructure_maintenance = false;
|
||||
if (IsSavegameVersionBefore(183)) {
|
||||
_settings_game.linkgraph.distribution_pax = DT_MANUAL;
|
||||
_settings_game.linkgraph.distribution_mail = DT_MANUAL;
|
||||
_settings_game.linkgraph.distribution_armoured = DT_MANUAL;
|
||||
_settings_game.linkgraph.distribution_default = DT_MANUAL;
|
||||
}
|
||||
|
||||
/* Load the sprites */
|
||||
GfxLoadSprites();
|
||||
@@ -710,10 +800,12 @@ bool AfterLoadGame()
|
||||
|
||||
/* If Load Scenario / New (Scenario) Game is used,
|
||||
* a company does not exist yet. So create one here.
|
||||
* 1 exeption: network-games. Those can have 0 companies
|
||||
* But this exeption is not true for non dedicated network_servers! */
|
||||
* 1 exception: network-games. Those can have 0 companies
|
||||
* But this exception is not true for non-dedicated network servers! */
|
||||
if (!Company::IsValidID(COMPANY_FIRST) && (!_networking || (_networking && _network_server && !_network_dedicated))) {
|
||||
DoStartupNewCompany(false);
|
||||
Company *c = Company::Get(COMPANY_FIRST);
|
||||
c->settings = _settings_client.company;
|
||||
}
|
||||
|
||||
/* Fix the cache for cargo payments. */
|
||||
@@ -734,7 +826,7 @@ bool AfterLoadGame()
|
||||
break;
|
||||
|
||||
case MP_STATION: {
|
||||
if (HasBit(_m[t].m6, 3)) SetBit(_m[t].m6, 2);
|
||||
if (HasBit(_me[t].m6, 3)) SetBit(_me[t].m6, 2);
|
||||
StationGfx gfx = GetStationGfx(t);
|
||||
StationType st;
|
||||
if ( IsInsideMM(gfx, 0, 8)) { // Rail station
|
||||
@@ -772,7 +864,7 @@ bool AfterLoadGame()
|
||||
ResetSignalHandlers();
|
||||
return false;
|
||||
}
|
||||
SB(_m[t].m6, 3, 3, st);
|
||||
SB(_me[t].m6, 3, 3, st);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -816,7 +908,7 @@ bool AfterLoadGame()
|
||||
|
||||
case STATION_OILRIG: {
|
||||
/* Very old savegames sometimes have phantom oil rigs, i.e.
|
||||
* an oil rig which got shut down, but not completly removed from
|
||||
* an oil rig which got shut down, but not completely removed from
|
||||
* the map
|
||||
*/
|
||||
TileIndex t1 = TILE_ADDXY(t, 0, 1);
|
||||
@@ -946,7 +1038,7 @@ bool AfterLoadGame()
|
||||
case ROAD_TILE_NORMAL:
|
||||
SB(_m[t].m4, 0, 4, GB(_m[t].m5, 0, 4));
|
||||
SB(_m[t].m4, 4, 4, 0);
|
||||
SB(_m[t].m6, 2, 4, 0);
|
||||
SB(_me[t].m6, 2, 4, 0);
|
||||
break;
|
||||
case ROAD_TILE_CROSSING:
|
||||
SB(_m[t].m4, 5, 2, GB(_m[t].m5, 2, 2));
|
||||
@@ -985,19 +1077,19 @@ bool AfterLoadGame()
|
||||
switch (GetRoadTileType(t)) {
|
||||
default: SlErrorCorrupt("Invalid road tile type");
|
||||
case ROAD_TILE_NORMAL:
|
||||
SB(_me[t].m7, 0, 4, GB(_m[t].m3, 0, 4)); // road works
|
||||
SB(_m[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
||||
SB(_m[t].m3, 0, 4, GB(_m[t].m4, 4, 4)); // tram bits
|
||||
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
|
||||
SB(_m[t].m5, 0, 4, GB(_m[t].m4, 0, 4)); // road bits
|
||||
SB(_me[t].m7, 0, 4, GB(_m[t].m3, 0, 4)); // road works
|
||||
SB(_me[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
||||
SB(_m[t].m3, 0, 4, GB(_m[t].m4, 4, 4)); // tram bits
|
||||
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
|
||||
SB(_m[t].m5, 0, 4, GB(_m[t].m4, 0, 4)); // road bits
|
||||
break;
|
||||
|
||||
case ROAD_TILE_CROSSING:
|
||||
SB(_me[t].m7, 0, 5, GB(_m[t].m4, 0, 5)); // road owner
|
||||
SB(_m[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
||||
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
|
||||
SB(_m[t].m5, 0, 1, GB(_m[t].m4, 6, 1)); // road axis
|
||||
SB(_m[t].m5, 5, 1, GB(_m[t].m4, 5, 1)); // crossing state
|
||||
SB(_me[t].m7, 0, 5, GB(_m[t].m4, 0, 5)); // road owner
|
||||
SB(_me[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
||||
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
|
||||
SB(_m[t].m5, 0, 1, GB(_m[t].m4, 6, 1)); // road axis
|
||||
SB(_m[t].m5, 5, 1, GB(_m[t].m4, 5, 1)); // crossing state
|
||||
break;
|
||||
|
||||
case ROAD_TILE_DEPOT:
|
||||
@@ -1014,7 +1106,7 @@ bool AfterLoadGame()
|
||||
if (!IsRoadStop(t)) break;
|
||||
|
||||
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_m[t].m3, 0, 3));
|
||||
SB(_me[t].m7, 0, 5, HasBit(_m[t].m6, 2) ? OWNER_TOWN : GetTileOwner(t));
|
||||
SB(_me[t].m7, 0, 5, HasBit(_me[t].m6, 2) ? OWNER_TOWN : GetTileOwner(t));
|
||||
SB(_m[t].m3, 4, 4, _m[t].m1);
|
||||
_m[t].m4 = 0;
|
||||
break;
|
||||
@@ -1028,7 +1120,7 @@ bool AfterLoadGame()
|
||||
SB(_me[t].m7, 0, 5, o); // road owner
|
||||
SB(_m[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); // tram owner
|
||||
}
|
||||
SB(_m[t].m6, 2, 4, GB(_m[t].m2, 4, 4)); // bridge type
|
||||
SB(_me[t].m6, 2, 4, GB(_m[t].m2, 4, 4)); // bridge type
|
||||
SB(_me[t].m7, 5, 1, GB(_m[t].m4, 7, 1)); // snow/desert
|
||||
|
||||
_m[t].m2 = 0;
|
||||
@@ -1072,7 +1164,7 @@ bool AfterLoadGame()
|
||||
if (GB(_m[t].m5, 3, 2) == 0) {
|
||||
MakeClear(t, CLEAR_GRASS, 3);
|
||||
} else {
|
||||
if (GetTileSlope(t) != SLOPE_FLAT) {
|
||||
if (!IsTileFlat(t)) {
|
||||
MakeShore(t);
|
||||
} else {
|
||||
if (GetTileOwner(t) == OWNER_WATER) {
|
||||
@@ -1164,7 +1256,7 @@ bool AfterLoadGame()
|
||||
}
|
||||
|
||||
FOR_ALL_TRAINS(v) {
|
||||
if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(true);
|
||||
if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(CCF_TRACK);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1191,11 +1283,15 @@ bool AfterLoadGame()
|
||||
switch (GetTileType(t)) {
|
||||
case MP_RAILWAY:
|
||||
if (HasSignals(t)) {
|
||||
/* Original signal type/variant was stored in m4 but since saveload
|
||||
* version 48 they are in m2. The bits has been already moved to m2
|
||||
* (see the code somewhere above) so don't use m4, use m2 instead. */
|
||||
|
||||
/* convert PBS signals to combo-signals */
|
||||
if (HasBit(_m[t].m2, 2)) SetSignalType(t, TRACK_X, SIGTYPE_COMBO);
|
||||
if (HasBit(_m[t].m2, 2)) SB(_m[t].m2, 0, 2, SIGTYPE_COMBO);
|
||||
|
||||
/* move the signal variant back */
|
||||
SetSignalVariant(t, TRACK_X, HasBit(_m[t].m2, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
||||
SB(_m[t].m2, 2, 1, HasBit(_m[t].m2, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
||||
ClrBit(_m[t].m2, 3);
|
||||
}
|
||||
|
||||
@@ -1270,7 +1366,7 @@ bool AfterLoadGame()
|
||||
}
|
||||
|
||||
/* From 32 on we save the industry who made the farmland.
|
||||
* To give this prettyness to old savegames, we remove all farmfields and
|
||||
* To give this prettiness to old savegames, we remove all farmfields and
|
||||
* plant new ones. */
|
||||
if (IsSavegameVersionBefore(32)) {
|
||||
Industry *i;
|
||||
@@ -1416,7 +1512,7 @@ bool AfterLoadGame()
|
||||
|
||||
if (IsSavegameVersionBefore(52)) {
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (IsStatueTile(t)) {
|
||||
if (IsTileType(t, MP_OBJECT) && _m[t].m5 == OBJECT_STATUE) {
|
||||
_m[t].m2 = CalcClosestTownFromTile(t)->index;
|
||||
}
|
||||
}
|
||||
@@ -1475,13 +1571,15 @@ bool AfterLoadGame()
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(64)) {
|
||||
/* copy the signal type/variant and move signal states bits */
|
||||
/* Since now we allow different signal types and variants on a single tile.
|
||||
* Move signal states to m4 to make room and clone the signal type/variant. */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (IsTileType(t, MP_RAILWAY) && HasSignals(t)) {
|
||||
/* move signal states */
|
||||
SetSignalStates(t, GB(_m[t].m2, 4, 4));
|
||||
SetSignalVariant(t, INVALID_TRACK, GetSignalVariant(t, TRACK_X));
|
||||
SetSignalType(t, INVALID_TRACK, GetSignalType(t, TRACK_X));
|
||||
ClrBit(_m[t].m2, 7);
|
||||
SB(_m[t].m2, 4, 4, 0);
|
||||
/* clone signal type and variant */
|
||||
SB(_m[t].m2, 4, 3, GB(_m[t].m2, 0, 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1534,7 +1632,7 @@ bool AfterLoadGame()
|
||||
FOR_ALL_STATIONS(st) {
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
||||
st->goods[c].last_speed = 0;
|
||||
if (st->goods[c].cargo.Count() != 0) SetBit(st->goods[c].acceptance_pickup, GoodsEntry::GES_PICKUP);
|
||||
if (st->goods[c].cargo.AvailableCount() != 0) SetBit(st->goods[c].status, GoodsEntry::GES_RATING);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1678,7 +1776,7 @@ bool AfterLoadGame()
|
||||
* on its neighbouring tiles. Done after river and canal updates to
|
||||
* ensure neighbours are correct. */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (GetTileSlope(t) != SLOPE_FLAT) continue;
|
||||
if (!IsTileFlat(t)) continue;
|
||||
|
||||
if (IsTileType(t, MP_WATER) && IsLock(t)) SetWaterClassDependingOnSurroundings(t, false);
|
||||
if (IsTileType(t, MP_STATION) && (IsDock(t) || IsBuoy(t))) SetWaterClassDependingOnSurroundings(t, false);
|
||||
@@ -1756,7 +1854,7 @@ bool AfterLoadGame()
|
||||
/* Increase HouseAnimationFrame from 5 to 7 bits */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (IsTileType(t, MP_HOUSE) && GetHouseType(t) >= NEW_HOUSE_OFFSET) {
|
||||
SB(_m[t].m6, 2, 6, GB(_m[t].m6, 3, 5));
|
||||
SB(_me[t].m6, 2, 6, GB(_me[t].m6, 3, 5));
|
||||
SB(_m[t].m3, 5, 1, 0);
|
||||
}
|
||||
}
|
||||
@@ -1826,7 +1924,7 @@ bool AfterLoadGame()
|
||||
if (HasStationRail(t)) SetRailStationReservation(t, false);
|
||||
break;
|
||||
|
||||
case MP_TUNNELBRIDGE: // Clear PBS reservation on tunnels/birdges
|
||||
case MP_TUNNELBRIDGE: // Clear PBS reservation on tunnels/bridges
|
||||
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) SetTunnelBridgeReservation(t, false);
|
||||
break;
|
||||
|
||||
@@ -1912,8 +2010,8 @@ bool AfterLoadGame()
|
||||
if (!IsTileType(t, MP_OBJECT)) continue;
|
||||
|
||||
/* Reordering/generalisation of the object bits. */
|
||||
ObjectType type = GetObjectType(t);
|
||||
SB(_m[t].m6, 2, 4, type == OBJECT_HQ ? GB(_m[t].m3, 2, 3) : 0);
|
||||
ObjectType type = _m[t].m5;
|
||||
SB(_me[t].m6, 2, 4, type == OBJECT_HQ ? GB(_m[t].m3, 2, 3) : 0);
|
||||
_m[t].m3 = type == OBJECT_HQ ? GB(_m[t].m3, 1, 1) | GB(_m[t].m3, 0, 1) << 4 : 0;
|
||||
|
||||
/* Make sure those bits are clear as well! */
|
||||
@@ -1934,12 +2032,12 @@ bool AfterLoadGame()
|
||||
uint offset = _m[t].m3;
|
||||
|
||||
/* Also move the animation state. */
|
||||
_m[t].m3 = GB(_m[t].m6, 2, 4);
|
||||
SB(_m[t].m6, 2, 4, 0);
|
||||
_m[t].m3 = GB(_me[t].m6, 2, 4);
|
||||
SB(_me[t].m6, 2, 4, 0);
|
||||
|
||||
if (offset == 0) {
|
||||
/* No offset, so make the object. */
|
||||
ObjectType type = GetObjectType(t);
|
||||
ObjectType type = _m[t].m5;
|
||||
int size = type == OBJECT_HQ ? 2 : 1;
|
||||
|
||||
if (!Object::CanAllocateItem()) {
|
||||
@@ -2026,7 +2124,7 @@ bool AfterLoadGame()
|
||||
/* Delete small ufos heading for non-existing vehicles */
|
||||
Vehicle *v;
|
||||
FOR_ALL_DISASTERVEHICLES(v) {
|
||||
if (v->subtype == 2/*ST_SMALL_UFO*/ && v->current_order.GetDestination() != 0) {
|
||||
if (v->subtype == 2 /* ST_SMALL_UFO */ && v->current_order.GetDestination() != 0) {
|
||||
const Vehicle *u = Vehicle::GetIfValid(v->dest_tile);
|
||||
if (u == NULL || u->type != VEH_ROAD || !RoadVehicle::From(u)->IsFrontEngine()) {
|
||||
delete v;
|
||||
@@ -2168,15 +2266,10 @@ bool AfterLoadGame()
|
||||
|
||||
/* Simulate the inflation, so we also get the payment inflation */
|
||||
while (_economy.inflation_prices < aimed_inflation) {
|
||||
AddInflation(false);
|
||||
if (AddInflation(false)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(127)) {
|
||||
Station *st;
|
||||
FOR_ALL_STATIONS(st) UpdateStationAcceptance(st, false);
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(128)) {
|
||||
const Depot *d;
|
||||
FOR_ALL_DEPOTS(d) {
|
||||
@@ -2326,7 +2419,10 @@ bool AfterLoadGame()
|
||||
UpdateAircraftCache(v);
|
||||
AircraftNextAirportPos_and_Order(v);
|
||||
/* get aircraft back on running altitude */
|
||||
if ((v->vehstatus & VS_CRASHED) == 0) SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlyingAltitude(v));
|
||||
if ((v->vehstatus & VS_CRASHED) == 0) {
|
||||
GetAircraftFlightLevelBounds(v, &v->z_pos, NULL);
|
||||
SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlightLevel(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2338,9 +2434,9 @@ bool AfterLoadGame()
|
||||
case MP_HOUSE:
|
||||
if (GetHouseType(t) >= NEW_HOUSE_OFFSET) {
|
||||
uint per_proc = _me[t].m7;
|
||||
_me[t].m7 = GB(_m[t].m6, 2, 6) | (GB(_m[t].m3, 5, 1) << 6);
|
||||
_me[t].m7 = GB(_me[t].m6, 2, 6) | (GB(_m[t].m3, 5, 1) << 6);
|
||||
SB(_m[t].m3, 5, 1, 0);
|
||||
SB(_m[t].m6, 2, 6, min(per_proc, 63));
|
||||
SB(_me[t].m6, 2, 6, min(per_proc, 63));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2375,7 +2471,7 @@ bool AfterLoadGame()
|
||||
if (IsSavegameVersionBefore(149)) {
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (!IsTileType(t, MP_STATION)) continue;
|
||||
if (!IsBuoy(t) && !IsOilRig(t) && !(IsDock(t) && GetTileSlope(t) == SLOPE_FLAT)) {
|
||||
if (!IsBuoy(t) && !IsOilRig(t) && !(IsDock(t) && IsTileFlat(t))) {
|
||||
SetWaterClass(t, WATER_CLASS_INVALID);
|
||||
}
|
||||
}
|
||||
@@ -2680,11 +2776,11 @@ bool AfterLoadGame()
|
||||
if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) continue;
|
||||
uint fence = GB(_m[t].m4, 5, 3);
|
||||
if (fence != 0 && IsTileType(TILE_ADDXY(t, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 1, 0), CLEAR_FIELDS)) {
|
||||
SetFenceNE(TILE_ADDXY(t, 1, 0), fence);
|
||||
SetFence(TILE_ADDXY(t, 1, 0), DIAGDIR_NE, fence);
|
||||
}
|
||||
fence = GB(_m[t].m4, 2, 3);
|
||||
if (fence != 0 && IsTileType(TILE_ADDXY(t, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 0, 1), CLEAR_FIELDS)) {
|
||||
SetFenceNW(TILE_ADDXY(t, 0, 1), fence);
|
||||
SetFence(TILE_ADDXY(t, 0, 1), DIAGDIR_NW, fence);
|
||||
}
|
||||
SB(_m[t].m4, 2, 3, 0);
|
||||
SB(_m[t].m4, 5, 3, 0);
|
||||
@@ -2747,16 +2843,166 @@ bool AfterLoadGame()
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(175)) {
|
||||
/* Introduced tree planting limit. */
|
||||
Company *c;
|
||||
FOR_ALL_COMPANIES(c) c->tree_limit = _settings_game.construction.tree_frame_burst << 16;
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(177)) {
|
||||
/* Fix too high inflation rates */
|
||||
if (_economy.inflation_prices > MAX_INFLATION) _economy.inflation_prices = MAX_INFLATION;
|
||||
if (_economy.inflation_payment > MAX_INFLATION) _economy.inflation_payment = MAX_INFLATION;
|
||||
|
||||
/* We have to convert the quarters of bankruptcy into months of bankruptcy */
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
c->months_of_bankruptcy = 3 * c->months_of_bankruptcy;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(178)) {
|
||||
extern uint8 _old_diff_level;
|
||||
/* Initialise script settings profile */
|
||||
_settings_game.script.settings_profile = IsInsideMM(_old_diff_level, SP_BEGIN, SP_END) ? _old_diff_level : (uint)SP_MEDIUM;
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(182)) {
|
||||
Aircraft *v;
|
||||
/* Aircraft acceleration variable was bonkers */
|
||||
FOR_ALL_AIRCRAFT(v) {
|
||||
if (v->subtype <= AIR_AIRCRAFT) {
|
||||
const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
|
||||
v->acceleration = avi->acceleration;
|
||||
}
|
||||
}
|
||||
|
||||
/* Blocked tiles could be reserved due to a bug, which causes
|
||||
* other places to assert upon e.g. station reconstruction. */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (HasStationTileRail(t) && IsStationTileBlocked(t)) {
|
||||
SetRailStationReservation(t, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(184)) {
|
||||
/* The global units configuration is split up in multiple configurations. */
|
||||
extern uint8 _old_units;
|
||||
_settings_game.locale.units_velocity = Clamp(_old_units, 0, 2);
|
||||
_settings_game.locale.units_power = Clamp(_old_units, 0, 2);
|
||||
_settings_game.locale.units_weight = Clamp(_old_units, 1, 2);
|
||||
_settings_game.locale.units_volume = Clamp(_old_units, 1, 2);
|
||||
_settings_game.locale.units_force = 2;
|
||||
_settings_game.locale.units_height = Clamp(_old_units, 0, 2);
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(186)) {
|
||||
/* Move ObjectType from map to pool */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (IsTileType(t, MP_OBJECT)) {
|
||||
Object *o = Object::Get(_m[t].m2);
|
||||
o->type = _m[t].m5;
|
||||
_m[t].m5 = 0; // zero upper bits of (now bigger) ObjectID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(188)) {
|
||||
/* Fix articulated road vehicles.
|
||||
* Some curves were shorter than other curves.
|
||||
* Now they have the same length, but that means that trailing articulated parts will
|
||||
* take longer to go through the curve than the parts in front which already left the courve.
|
||||
* So, make articulated parts catch up. */
|
||||
RoadVehicle *v;
|
||||
bool roadside = _settings_game.vehicle.road_side == 1;
|
||||
SmallVector<uint, 16> skip_frames;
|
||||
FOR_ALL_ROADVEHICLES(v) {
|
||||
if (!v->IsFrontEngine()) continue;
|
||||
skip_frames.Clear();
|
||||
TileIndex prev_tile = v->tile;
|
||||
uint prev_tile_skip = 0;
|
||||
uint cur_skip = 0;
|
||||
for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
|
||||
if (u->tile != prev_tile) {
|
||||
prev_tile_skip = cur_skip;
|
||||
prev_tile = u->tile;
|
||||
} else {
|
||||
cur_skip = prev_tile_skip;
|
||||
}
|
||||
|
||||
uint *this_skip = skip_frames.Append();
|
||||
*this_skip = prev_tile_skip;
|
||||
|
||||
/* The following 3 curves now take longer than before */
|
||||
switch (u->state) {
|
||||
case 2:
|
||||
cur_skip++;
|
||||
if (u->frame <= (roadside ? 9 : 5)) *this_skip = cur_skip;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
cur_skip++;
|
||||
if (u->frame <= (roadside ? 5 : 9)) *this_skip = cur_skip;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
cur_skip++;
|
||||
if (u->frame <= (roadside ? 4 : 2)) *this_skip = cur_skip;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (cur_skip > skip_frames[0]) {
|
||||
RoadVehicle *u = v;
|
||||
RoadVehicle *prev = NULL;
|
||||
for (uint *it = skip_frames.Begin(); it != skip_frames.End(); ++it, prev = u, u = u->Next()) {
|
||||
extern bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev);
|
||||
if (*it >= cur_skip) IndividualRoadVehicleController(u, prev);
|
||||
}
|
||||
cur_skip--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Only keep order-backups for network clients (and when replaying).
|
||||
* If we are a network server or not networking, then we just loaded a previously
|
||||
* saved-by-server savegame. There are no clients with a backup, so clear it.
|
||||
* Furthermore before savegame version 192 the actual content was always corrupt.
|
||||
*/
|
||||
if (!_networking || _network_server || IsSavegameVersionBefore(192)) {
|
||||
#ifndef DEBUG_DUMP_COMMANDS
|
||||
/* Note: We cannot use CleanPool since that skips part of the destructor
|
||||
* and then leaks un-reachable Orders in the order pool. */
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
delete ob;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Station acceptance is some kind of cache */
|
||||
if (IsSavegameVersionBefore(127)) {
|
||||
Station *st;
|
||||
FOR_ALL_STATIONS(st) UpdateStationAcceptance(st, false);
|
||||
}
|
||||
|
||||
/* Road stops is 'only' updating some caches */
|
||||
AfterLoadRoadStops();
|
||||
AfterLoadLabelMaps();
|
||||
AfterLoadCompanyStats();
|
||||
AfterLoadStoryBook();
|
||||
|
||||
GamelogPrintDebug(1);
|
||||
|
||||
InitializeWindowsAndCaches();
|
||||
/* Restore the signals */
|
||||
ResetSignalHandlers();
|
||||
|
||||
AfterLoadLinkGraphs();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,8 @@
|
||||
#include "../network/network.h"
|
||||
#include "../ai/ai_instance.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static char _ai_saveload_name[64];
|
||||
static int _ai_saveload_version;
|
||||
static char _ai_saveload_settings[1024];
|
||||
@@ -39,7 +41,7 @@ static void SaveReal_AIPL(int *index_ptr)
|
||||
AIConfig *config = AIConfig::GetConfig(index);
|
||||
|
||||
if (config->HasScript()) {
|
||||
ttd_strlcpy(_ai_saveload_name, config->GetName(), lengthof(_ai_saveload_name));
|
||||
strecpy(_ai_saveload_name, config->GetName(), lastof(_ai_saveload_name));
|
||||
_ai_saveload_version = config->GetVersion();
|
||||
} else {
|
||||
/* No AI is configured for this so store an empty string as name. */
|
||||
@@ -49,7 +51,7 @@ static void SaveReal_AIPL(int *index_ptr)
|
||||
|
||||
_ai_saveload_is_random = config->IsRandom();
|
||||
_ai_saveload_settings[0] = '\0';
|
||||
config->SettingsToString(_ai_saveload_settings, lengthof(_ai_saveload_settings));
|
||||
config->SettingsToString(_ai_saveload_settings, lastof(_ai_saveload_settings));
|
||||
|
||||
SlObject(NULL, _ai_company);
|
||||
/* If the AI was active, store his data too */
|
||||
|
@@ -14,6 +14,8 @@
|
||||
#include "saveload.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static void Save_APID()
|
||||
{
|
||||
Save_NewGRFMapping(_airport_mngr);
|
||||
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern TileIndex *_animated_tile_list;
|
||||
extern uint _animated_tile_count;
|
||||
extern uint _animated_tile_allocated;
|
||||
|
@@ -14,12 +14,15 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _engine_renew_desc[] = {
|
||||
SLE_VAR(EngineRenew, from, SLE_UINT16),
|
||||
SLE_VAR(EngineRenew, to, SLE_UINT16),
|
||||
|
||||
SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS),
|
||||
SLE_CONDVAR(EngineRenew, group_id, SLE_UINT16, 60, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(EngineRenew, replace_when_old, SLE_BOOL, 175, SL_MAX_VERSION),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
|
105
src/saveload/cargomonitor_sl.cpp
Normal file
105
src/saveload/cargomonitor_sl.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* 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.
|
||||
* 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.
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/** @file cargomonitor_sl.cpp Code handling saving and loading of Cargo monitoring. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../cargomonitor.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Temporary storage of cargo monitoring data for loading or saving it. */
|
||||
struct TempStorage {
|
||||
CargoMonitorID number;
|
||||
uint32 amount;
|
||||
};
|
||||
|
||||
/** Description of the #TempStorage structure for the purpose of load and save. */
|
||||
static const SaveLoad _cargomonitor_pair_desc[] = {
|
||||
SLE_VAR(TempStorage, number, SLE_UINT32),
|
||||
SLE_VAR(TempStorage, amount, SLE_UINT32),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
/** Save the #_cargo_deliveries monitoring map. */
|
||||
static void SaveDelivery()
|
||||
{
|
||||
TempStorage storage;
|
||||
|
||||
int i = 0;
|
||||
CargoMonitorMap::const_iterator iter = _cargo_deliveries.begin();
|
||||
while (iter != _cargo_deliveries.end()) {
|
||||
storage.number = iter->first;
|
||||
storage.amount = iter->second;
|
||||
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Load the #_cargo_deliveries monitoring map. */
|
||||
static void LoadDelivery()
|
||||
{
|
||||
TempStorage storage;
|
||||
|
||||
ClearCargoDeliveryMonitoring();
|
||||
for (;;) {
|
||||
if (SlIterateArray() < 0) break;
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
|
||||
std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
|
||||
_cargo_deliveries.insert(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Save the #_cargo_pickups monitoring map. */
|
||||
static void SavePickup()
|
||||
{
|
||||
TempStorage storage;
|
||||
|
||||
int i = 0;
|
||||
CargoMonitorMap::const_iterator iter = _cargo_pickups.begin();
|
||||
while (iter != _cargo_pickups.end()) {
|
||||
storage.number = iter->first;
|
||||
storage.amount = iter->second;
|
||||
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Load the #_cargo_pickups monitoring map. */
|
||||
static void LoadPickup()
|
||||
{
|
||||
TempStorage storage;
|
||||
|
||||
ClearCargoPickupMonitoring();
|
||||
for (;;) {
|
||||
if (SlIterateArray() < 0) break;
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
|
||||
std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
|
||||
_cargo_pickups.insert(p);
|
||||
}
|
||||
}
|
||||
|
||||
/** Chunk definition of the cargomonitoring maps. */
|
||||
extern const ChunkHandler _cargomonitor_chunk_handlers[] = {
|
||||
{ 'CMDL', SaveDelivery, LoadDelivery, NULL, NULL, CH_ARRAY},
|
||||
{ 'CMPU', SavePickup, LoadPickup, NULL, NULL, CH_ARRAY | CH_LAST},
|
||||
};
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Savegame conversion for cargopackets.
|
||||
*/
|
||||
@@ -22,14 +24,14 @@
|
||||
{
|
||||
if (IsSavegameVersionBefore(44)) {
|
||||
Vehicle *v;
|
||||
/* If we remove a station while cargo from it is still enroute, payment calculation will assume
|
||||
/* If we remove a station while cargo from it is still en route, payment calculation will assume
|
||||
* 0, 0 to be the source of the cargo, resulting in very high payments usually. v->source_xy
|
||||
* stores the coordinates, preserving them even if the station is removed. However, if a game is loaded
|
||||
* where this situation exists, the cargo-source information is lost. in this case, we set the source
|
||||
* to the current tile of the vehicle to prevent excessive profits
|
||||
*/
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
const VehicleCargoList::List *packets = v->cargo.Packets();
|
||||
const CargoPacketList *packets = v->cargo.Packets();
|
||||
for (VehicleCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
|
||||
CargoPacket *cp = *it;
|
||||
cp->source_xy = Station::IsValidID(cp->source) ? Station::Get(cp->source)->xy : v->tile;
|
||||
@@ -47,7 +49,7 @@
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
||||
GoodsEntry *ge = &st->goods[c];
|
||||
|
||||
const StationCargoList::List *packets = ge->cargo.Packets();
|
||||
const StationCargoPacketMap *packets = ge->cargo.Packets();
|
||||
for (StationCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
|
||||
CargoPacket *cp = *it;
|
||||
cp->source_xy = Station::IsValidID(cp->source) ? Station::Get(cp->source)->xy : st->xy;
|
||||
@@ -77,6 +79,11 @@
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(181)) {
|
||||
Vehicle *v;
|
||||
FOR_ALL_VEHICLES(v) v->cargo.KeepAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Save the cheat values.
|
||||
*/
|
||||
|
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Converts an old company manager's face format to the new company manager's face format
|
||||
*
|
||||
@@ -256,7 +258,7 @@ static const SaveLoad _company_desc[] = {
|
||||
|
||||
SLE_VAR(CompanyProperties, colour, SLE_UINT8),
|
||||
SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8),
|
||||
SLE_CONDVAR(CompanyProperties, avail_railtypes, SLE_UINT8, 0, 57),
|
||||
SLE_CONDVAR(CompanyProperties, avail_railtypes, SLE_VAR_I32 | SLE_FILE_I8, 0, 57),
|
||||
SLE_VAR(CompanyProperties, block_preview, SLE_UINT8),
|
||||
|
||||
SLE_CONDNULL(2, 0, 93), ///< cargo_types
|
||||
@@ -272,7 +274,7 @@ static const SaveLoad _company_desc[] = {
|
||||
|
||||
SLE_VAR(CompanyProperties, num_valid_stat_ent, SLE_UINT8),
|
||||
|
||||
SLE_VAR(CompanyProperties, quarters_of_bankruptcy,SLE_UINT8),
|
||||
SLE_VAR(CompanyProperties, months_of_bankruptcy, SLE_UINT8),
|
||||
SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_FILE_U8 | SLE_VAR_U16, 0, 103),
|
||||
SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_UINT16, 104, SL_MAX_VERSION),
|
||||
SLE_VAR(CompanyProperties, bankrupt_timeout, SLE_INT16),
|
||||
@@ -281,7 +283,7 @@ static const SaveLoad _company_desc[] = {
|
||||
|
||||
/* yearly expenses was changed to 64-bit in savegame version 2. */
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_FILE_I32 | SLE_VAR_I64, 3 * 13, 0, 1),
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 13, 2, 200),
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 13, 2, 199),
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 15, 200, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, is_ai, SLE_BOOL, 2, SL_MAX_VERSION),
|
||||
@@ -290,6 +292,7 @@ static const SaveLoad _company_desc[] = {
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, terraform_limit, SLE_UINT32, 156, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, clear_limit, SLE_UINT32, 156, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, tree_limit, SLE_UINT32, 175, SL_MAX_VERSION),
|
||||
|
||||
SLE_END()
|
||||
};
|
||||
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static TownID _town_index;
|
||||
|
||||
static const SaveLoad _depot_desc[] = {
|
||||
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Prices in pre 126 savegames */
|
||||
static void Load_PRIC()
|
||||
{
|
||||
@@ -63,11 +65,11 @@ static void Load_ECMY()
|
||||
}
|
||||
|
||||
static const SaveLoad _cargopayment_desc[] = {
|
||||
SLE_REF(CargoPayment, front, REF_VEHICLE),
|
||||
SLE_VAR(CargoPayment, route_profit, SLE_INT64),
|
||||
SLE_VAR(CargoPayment, visual_profit, SLE_INT64),
|
||||
|
||||
SLE_END()
|
||||
SLE_REF(CargoPayment, front, REF_VEHICLE),
|
||||
SLE_VAR(CargoPayment, route_profit, SLE_INT64),
|
||||
SLE_VAR(CargoPayment, visual_profit, SLE_INT64),
|
||||
SLE_CONDVAR(CargoPayment, visual_transfer, SLE_INT64, 181, SL_MAX_VERSION),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_CAPY()
|
||||
|
@@ -12,7 +12,10 @@
|
||||
#include "../stdafx.h"
|
||||
#include "saveload_internal.h"
|
||||
#include "../engine_base.h"
|
||||
#include <map>
|
||||
#include "../string_func.h"
|
||||
#include <vector>
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _engine_desc[] = {
|
||||
SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
|
||||
@@ -30,11 +33,14 @@ static const SaveLoad _engine_desc[] = {
|
||||
|
||||
SLE_CONDNULL(1, 0, 120),
|
||||
SLE_VAR(Engine, flags, SLE_UINT8),
|
||||
SLE_VAR(Engine, preview_company_rank,SLE_UINT8),
|
||||
SLE_CONDNULL(1, 0, 178), // old preview_company_rank
|
||||
SLE_CONDVAR(Engine, preview_asked, SLE_UINT16, 179, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Engine, preview_company, SLE_UINT8, 179, SL_MAX_VERSION),
|
||||
SLE_VAR(Engine, preview_wait, SLE_UINT8),
|
||||
SLE_CONDNULL(1, 0, 44),
|
||||
SLE_CONDVAR(Engine, company_avail, SLE_FILE_U8 | SLE_VAR_U16, 0, 103),
|
||||
SLE_CONDVAR(Engine, company_avail, SLE_UINT16, 104, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Engine, company_hidden, SLE_UINT16, 193, SL_MAX_VERSION),
|
||||
SLE_CONDSTR(Engine, name, SLE_STR, 0, 84, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(16, 2, 143), // old reserved space
|
||||
@@ -42,11 +48,42 @@ static const SaveLoad _engine_desc[] = {
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static std::map<EngineID, Engine> _temp_engine;
|
||||
static std::vector<Engine*> _temp_engine;
|
||||
|
||||
/**
|
||||
* Allocate an Engine structure, but not using the pools.
|
||||
* The allocated Engine must be freed using FreeEngine;
|
||||
* @return Allocated engine.
|
||||
*/
|
||||
static Engine* CallocEngine()
|
||||
{
|
||||
uint8 *zero = CallocT<uint8>(sizeof(Engine));
|
||||
Engine *engine = new (zero) Engine();
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocate an Engine constructed by CallocEngine.
|
||||
* @param e Engine to free.
|
||||
*/
|
||||
static void FreeEngine(Engine *e)
|
||||
{
|
||||
if (e != NULL) {
|
||||
e->~Engine();
|
||||
free(e);
|
||||
}
|
||||
}
|
||||
|
||||
Engine *GetTempDataEngine(EngineID index)
|
||||
{
|
||||
return &_temp_engine[index];
|
||||
if (index < _temp_engine.size()) {
|
||||
return _temp_engine[index];
|
||||
} else if (index == _temp_engine.size()) {
|
||||
_temp_engine.push_back(CallocEngine());
|
||||
return _temp_engine[index];
|
||||
} else {
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_ENGN()
|
||||
@@ -67,6 +104,14 @@ static void Load_ENGN()
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Engine *e = GetTempDataEngine(index);
|
||||
SlObject(e, _engine_desc);
|
||||
|
||||
if (IsSavegameVersionBefore(179)) {
|
||||
/* preview_company_rank was replaced with preview_company and preview_asked.
|
||||
* Just cancel any previews. */
|
||||
e->flags &= ~4; // ENGINE_OFFER_WINDOW_OPEN
|
||||
e->preview_company = INVALID_COMPANY;
|
||||
e->preview_asked = (CompanyMask)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +136,18 @@ void CopyTempEngineData()
|
||||
e->duration_phase_2 = se->duration_phase_2;
|
||||
e->duration_phase_3 = se->duration_phase_3;
|
||||
e->flags = se->flags;
|
||||
e->preview_company_rank= se->preview_company_rank;
|
||||
e->preview_asked = se->preview_asked;
|
||||
e->preview_company = se->preview_company;
|
||||
e->preview_wait = se->preview_wait;
|
||||
e->company_avail = se->company_avail;
|
||||
if (se->name != NULL) e->name = strdup(se->name);
|
||||
e->company_hidden = se->company_hidden;
|
||||
if (se->name != NULL) e->name = stredup(se->name);
|
||||
}
|
||||
|
||||
/* Get rid of temporary data */
|
||||
for (std::vector<Engine*>::iterator it = _temp_engine.begin(); it != _temp_engine.end(); ++it) {
|
||||
FreeEngine(*it);
|
||||
}
|
||||
_temp_engine.clear();
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,8 @@
|
||||
#include "../game/game_instance.hpp"
|
||||
#include "../game/game_text.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static char _game_saveload_name[64];
|
||||
static int _game_saveload_version;
|
||||
static char _game_saveload_settings[1024];
|
||||
@@ -38,7 +40,7 @@ static void SaveReal_GSDT(int *index_ptr)
|
||||
GameConfig *config = GameConfig::GetConfig();
|
||||
|
||||
if (config->HasScript()) {
|
||||
ttd_strlcpy(_game_saveload_name, config->GetName(), lengthof(_game_saveload_name));
|
||||
strecpy(_game_saveload_name, config->GetName(), lastof(_game_saveload_name));
|
||||
_game_saveload_version = config->GetVersion();
|
||||
} else {
|
||||
/* No GameScript is configured for this so store an empty string as name. */
|
||||
@@ -48,7 +50,7 @@ static void SaveReal_GSDT(int *index_ptr)
|
||||
|
||||
_game_saveload_is_random = config->IsRandom();
|
||||
_game_saveload_settings[0] = '\0';
|
||||
config->SettingsToString(_game_saveload_settings, lengthof(_game_saveload_settings));
|
||||
config->SettingsToString(_game_saveload_settings, lastof(_game_saveload_settings));
|
||||
|
||||
SlObject(NULL, _game_script);
|
||||
Game::Save();
|
||||
@@ -76,22 +78,22 @@ static void Load_GSDT()
|
||||
config->Change(_game_saveload_name, _game_saveload_version, false, _game_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
/* No version of the GameScript available that can load the data. Try to load the
|
||||
* latest version of the GameScript instead. */
|
||||
* latest version of the GameScript instead. */
|
||||
config->Change(_game_saveload_name, -1, false, _game_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
if (strcmp(_game_saveload_name, "%_dummy") != 0) {
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version);
|
||||
DEBUG(script, 0, "This game wil continue to run without GameScript.");
|
||||
DEBUG(script, 0, "This game will continue to run without GameScript.");
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame had no GameScript available at the time of saving.");
|
||||
DEBUG(script, 0, "This game wil continue to run without GameScript.");
|
||||
DEBUG(script, 0, "This game will continue to run without GameScript.");
|
||||
}
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name, _game_saveload_version);
|
||||
DEBUG(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible.");
|
||||
}
|
||||
/* Make sure the GameScript doesn't get the saveload data, as he was not the
|
||||
* writer of the saveload data in the first place */
|
||||
* writer of the saveload data in the first place */
|
||||
_game_saveload_version = -1;
|
||||
}
|
||||
}
|
||||
@@ -148,10 +150,10 @@ static void Load_GSTR()
|
||||
_game_saveload_string = NULL;
|
||||
SlObject(NULL, _game_language_header);
|
||||
|
||||
LanguageStrings *ls = new LanguageStrings(_game_saveload_string);
|
||||
LanguageStrings *ls = new LanguageStrings(_game_saveload_string != NULL ? _game_saveload_string : "");
|
||||
for (uint i = 0; i < _game_saveload_strings; i++) {
|
||||
SlObject(NULL, _game_language_string);
|
||||
*ls->lines.Append() = strdup(_game_saveload_string != NULL ? _game_saveload_string : "");
|
||||
*ls->lines.Append() = stredup(_game_saveload_string != NULL ? _game_saveload_string : "");
|
||||
}
|
||||
|
||||
*_current_data->raw_strings.Append() = ls;
|
||||
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _glog_action_desc[] = {
|
||||
SLE_VAR(LoggedAction, tick, SLE_UINT16),
|
||||
SLE_END()
|
||||
|
@@ -14,11 +14,15 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _goals_desc[] = {
|
||||
SLE_VAR(Goal, company, SLE_UINT16),
|
||||
SLE_VAR(Goal, type, SLE_UINT16),
|
||||
SLE_VAR(Goal, dst, SLE_UINT32),
|
||||
SLE_STR(Goal, text, SLE_STR | SLF_ALLOW_CONTROL, 0),
|
||||
SLE_VAR(Goal, company, SLE_FILE_U16 | SLE_VAR_U8),
|
||||
SLE_VAR(Goal, type, SLE_FILE_U16 | SLE_VAR_U8),
|
||||
SLE_VAR(Goal, dst, SLE_UINT32),
|
||||
SLE_STR(Goal, text, SLE_STR | SLF_ALLOW_CONTROL, 0),
|
||||
SLE_CONDSTR(Goal, progress, SLE_STR | SLF_ALLOW_CONTROL, 0, 182, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Goal, completed, SLE_BOOL, 182, SL_MAX_VERSION),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
|
@@ -14,14 +14,17 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _group_desc[] = {
|
||||
SLE_CONDVAR(Group, name, SLE_NAME, 0, 83),
|
||||
SLE_CONDSTR(Group, name, SLE_STR | SLF_ALLOW_CONTROL, 0, 84, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(2, 0, 163), // num_vehicle
|
||||
SLE_VAR(Group, owner, SLE_UINT8),
|
||||
SLE_VAR(Group, vehicle_type, SLE_UINT8),
|
||||
SLE_VAR(Group, replace_protection, SLE_BOOL),
|
||||
SLE_END()
|
||||
SLE_CONDVAR(Group, name, SLE_NAME, 0, 83),
|
||||
SLE_CONDSTR(Group, name, SLE_STR | SLF_ALLOW_CONTROL, 0, 84, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(2, 0, 163), // num_vehicle
|
||||
SLE_VAR(Group, owner, SLE_UINT8),
|
||||
SLE_VAR(Group, vehicle_type, SLE_UINT8),
|
||||
SLE_VAR(Group, replace_protection, SLE_BOOL),
|
||||
SLE_CONDVAR(Group, parent, SLE_UINT16, 189, SL_MAX_VERSION),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_GRPS()
|
||||
@@ -42,6 +45,8 @@ static void Load_GRPS()
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Group *g = new (index) Group();
|
||||
SlObject(g, _group_desc);
|
||||
|
||||
if (IsSavegameVersionBefore(189)) g->parent = INVALID_GROUP;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,8 @@
|
||||
#include "saveload.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static OldPersistentStorage _old_ind_persistent_storage;
|
||||
|
||||
static const SaveLoad _industry_desc[] = {
|
||||
@@ -98,7 +100,7 @@ static void Load_INDY()
|
||||
if (IsSavegameVersionBefore(161) && !IsSavegameVersionBefore(76)) {
|
||||
/* Store the old persistent storage. The GRFID will be added later. */
|
||||
assert(PersistentStorage::CanAllocateItem());
|
||||
i->psa = new PersistentStorage(0);
|
||||
i->psa = new PersistentStorage(0, 0, 0);
|
||||
memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(i->psa->storage));
|
||||
}
|
||||
Industry::IncIndustryTypeCount(i->type);
|
||||
@@ -158,14 +160,14 @@ static void Save_ITBL()
|
||||
/** Load industry-type build data. */
|
||||
static void Load_ITBL()
|
||||
{
|
||||
int index;
|
||||
for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
|
||||
index = SlIterateArray();
|
||||
assert(index == i);
|
||||
SlObject(_industry_builder.builddata + i, _industrytype_builder_desc);
|
||||
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
||||
_industry_builder.builddata[it].Reset();
|
||||
}
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if ((uint)index >= NUM_INDUSTRYTYPES) SlErrorCorrupt("Too many industry builder datas");
|
||||
SlObject(_industry_builder.builddata + index, _industrytype_builder_desc);
|
||||
}
|
||||
index = SlIterateArray();
|
||||
assert(index == -1);
|
||||
}
|
||||
|
||||
extern const ChunkHandler _industry_chunk_handlers[] = {
|
||||
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static SmallVector<RailTypeLabel, RAILTYPE_END> _railtype_list;
|
||||
|
||||
/**
|
||||
|
296
src/saveload/linkgraph_sl.cpp
Normal file
296
src/saveload/linkgraph_sl.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* 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.
|
||||
* 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.
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/** @file linkgraph_sl.cpp Code handling saving and loading of link graphs */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../linkgraph/linkgraph.h"
|
||||
#include "../linkgraph/linkgraphjob.h"
|
||||
#include "../linkgraph/linkgraphschedule.h"
|
||||
#include "../settings_internal.h"
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
typedef LinkGraph::BaseNode Node;
|
||||
typedef LinkGraph::BaseEdge Edge;
|
||||
|
||||
const SettingDesc *GetSettingDescription(uint index);
|
||||
|
||||
static uint16 _num_nodes;
|
||||
|
||||
/**
|
||||
* Get a SaveLoad array for a link graph.
|
||||
* @return SaveLoad array for link graph.
|
||||
*/
|
||||
const SaveLoad *GetLinkGraphDesc()
|
||||
{
|
||||
static const SaveLoad link_graph_desc[] = {
|
||||
SLE_VAR(LinkGraph, last_compression, SLE_INT32),
|
||||
SLEG_VAR(_num_nodes, SLE_UINT16),
|
||||
SLE_VAR(LinkGraph, cargo, SLE_UINT8),
|
||||
SLE_END()
|
||||
};
|
||||
return link_graph_desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a SaveLoad array for a link graph job. The settings struct is derived from
|
||||
* the global settings saveload array. The exact entries are calculated when the function
|
||||
* is called the first time.
|
||||
* It's necessary to keep a copy of the settings for each link graph job so that you can
|
||||
* change the settings while in-game and still not mess with current link graph runs.
|
||||
* Of course the settings have to be saved and loaded, too, to avoid desyncs.
|
||||
* @return Array of SaveLoad structs.
|
||||
*/
|
||||
const SaveLoad *GetLinkGraphJobDesc()
|
||||
{
|
||||
static SmallVector<SaveLoad, 16> saveloads;
|
||||
static const char *prefix = "linkgraph.";
|
||||
|
||||
/* Build the SaveLoad array on first call and don't touch it later on */
|
||||
if (saveloads.Length() == 0) {
|
||||
size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
|
||||
size_t offset_component = cpp_offsetof(LinkGraphJob, settings);
|
||||
|
||||
size_t prefixlen = strlen(prefix);
|
||||
|
||||
int setting = 0;
|
||||
const SettingDesc *desc = GetSettingDescription(setting);
|
||||
while (desc->save.cmd != SL_END) {
|
||||
if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) {
|
||||
SaveLoad sl = desc->save;
|
||||
char *&address = reinterpret_cast<char *&>(sl.address);
|
||||
address -= offset_gamesettings;
|
||||
address += offset_component;
|
||||
*(saveloads.Append()) = sl;
|
||||
}
|
||||
desc = GetSettingDescription(++setting);
|
||||
}
|
||||
|
||||
const SaveLoad job_desc[] = {
|
||||
SLE_VAR(LinkGraphJob, join_date, SLE_INT32),
|
||||
SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
*(saveloads.Append()) = job_desc[i++];
|
||||
} while (saveloads[saveloads.Length() - 1].cmd != SL_END);
|
||||
}
|
||||
|
||||
return &saveloads[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a SaveLoad array for the link graph schedule.
|
||||
* @return SaveLoad array for the link graph schedule.
|
||||
*/
|
||||
const SaveLoad *GetLinkGraphScheduleDesc()
|
||||
{
|
||||
static const SaveLoad schedule_desc[] = {
|
||||
SLE_LST(LinkGraphSchedule, schedule, REF_LINK_GRAPH),
|
||||
SLE_LST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB),
|
||||
SLE_END()
|
||||
};
|
||||
return schedule_desc;
|
||||
}
|
||||
|
||||
/* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
|
||||
|
||||
/**
|
||||
* SaveLoad desc for a link graph node.
|
||||
*/
|
||||
static const SaveLoad _node_desc[] = {
|
||||
SLE_CONDVAR(Node, xy, SLE_UINT32, 191, SL_MAX_VERSION),
|
||||
SLE_VAR(Node, supply, SLE_UINT32),
|
||||
SLE_VAR(Node, demand, SLE_UINT32),
|
||||
SLE_VAR(Node, station, SLE_UINT16),
|
||||
SLE_VAR(Node, last_update, SLE_INT32),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
/**
|
||||
* SaveLoad desc for a link graph edge.
|
||||
*/
|
||||
static const SaveLoad _edge_desc[] = {
|
||||
SLE_CONDNULL(4, 0, 190), // distance
|
||||
SLE_VAR(Edge, capacity, SLE_UINT32),
|
||||
SLE_VAR(Edge, usage, SLE_UINT32),
|
||||
SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
|
||||
SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, 187, SL_MAX_VERSION),
|
||||
SLE_VAR(Edge, next_edge, SLE_UINT16),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
/**
|
||||
* Save/load a link graph.
|
||||
* @param comp Link graph to be saved or loaded.
|
||||
*/
|
||||
void SaveLoad_LinkGraph(LinkGraph &lg)
|
||||
{
|
||||
uint size = lg.Size();
|
||||
for (NodeID from = 0; from < size; ++from) {
|
||||
Node *node = &lg.nodes[from];
|
||||
SlObject(node, _node_desc);
|
||||
if (IsSavegameVersionBefore(191)) {
|
||||
/* We used to save the full matrix ... */
|
||||
for (NodeID to = 0; to < size; ++to) {
|
||||
SlObject(&lg.edges[from][to], _edge_desc);
|
||||
}
|
||||
} else {
|
||||
/* ... but as that wasted a lot of space we save a sparse matrix now. */
|
||||
for (NodeID to = from; to != INVALID_NODE; to = lg.edges[from][to].next_edge) {
|
||||
SlObject(&lg.edges[from][to], _edge_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a link graph job.
|
||||
* @param lgj LinkGraphJob to be saved.
|
||||
*/
|
||||
static void DoSave_LGRJ(LinkGraphJob *lgj)
|
||||
{
|
||||
SlObject(lgj, GetLinkGraphJobDesc());
|
||||
_num_nodes = lgj->Size();
|
||||
SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
|
||||
SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a link graph.
|
||||
* @param lg LinkGraph to be saved.
|
||||
*/
|
||||
static void DoSave_LGRP(LinkGraph *lg)
|
||||
{
|
||||
_num_nodes = lg->Size();
|
||||
SlObject(lg, GetLinkGraphDesc());
|
||||
SaveLoad_LinkGraph(*lg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all link graphs.
|
||||
*/
|
||||
static void Load_LGRP()
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if (!LinkGraph::CanAllocateItem()) {
|
||||
/* Impossible as they have been present in previous game. */
|
||||
NOT_REACHED();
|
||||
}
|
||||
LinkGraph *lg = new (index) LinkGraph();
|
||||
SlObject(lg, GetLinkGraphDesc());
|
||||
lg->Init(_num_nodes);
|
||||
SaveLoad_LinkGraph(*lg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all link graph jobs.
|
||||
*/
|
||||
static void Load_LGRJ()
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if (!LinkGraphJob::CanAllocateItem()) {
|
||||
/* Impossible as they have been present in previous game. */
|
||||
NOT_REACHED();
|
||||
}
|
||||
LinkGraphJob *lgj = new (index) LinkGraphJob();
|
||||
SlObject(lgj, GetLinkGraphJobDesc());
|
||||
LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
|
||||
SlObject(&lg, GetLinkGraphDesc());
|
||||
lg.Init(_num_nodes);
|
||||
SaveLoad_LinkGraph(lg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the link graph schedule.
|
||||
*/
|
||||
static void Load_LGRS()
|
||||
{
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn the threads for running link graph calculations.
|
||||
* Has to be done after loading as the cargo classes might have changed.
|
||||
*/
|
||||
void AfterLoadLinkGraphs()
|
||||
{
|
||||
if (IsSavegameVersionBefore(191)) {
|
||||
LinkGraph *lg;
|
||||
FOR_ALL_LINK_GRAPHS(lg) {
|
||||
for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
|
||||
(*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
|
||||
}
|
||||
}
|
||||
|
||||
LinkGraphJob *lgj;
|
||||
FOR_ALL_LINK_GRAPH_JOBS(lgj) {
|
||||
lg = &(const_cast<LinkGraph &>(lgj->Graph()));
|
||||
for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
|
||||
(*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinkGraphSchedule::instance.SpawnAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all link graphs.
|
||||
*/
|
||||
static void Save_LGRP()
|
||||
{
|
||||
LinkGraph *lg;
|
||||
FOR_ALL_LINK_GRAPHS(lg) {
|
||||
SlSetArrayIndex(lg->index);
|
||||
SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all link graph jobs.
|
||||
*/
|
||||
static void Save_LGRJ()
|
||||
{
|
||||
LinkGraphJob *lgj;
|
||||
FOR_ALL_LINK_GRAPH_JOBS(lgj) {
|
||||
SlSetArrayIndex(lgj->index);
|
||||
SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the link graph schedule.
|
||||
*/
|
||||
static void Save_LGRS()
|
||||
{
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitute pointers in link graph schedule.
|
||||
*/
|
||||
static void Ptrs_LGRS()
|
||||
{
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
|
||||
extern const ChunkHandler _linkgraph_chunk_handlers[] = {
|
||||
{ 'LGRP', Save_LGRP, Load_LGRP, NULL, NULL, CH_ARRAY },
|
||||
{ 'LGRJ', Save_LGRJ, Load_LGRJ, NULL, NULL, CH_ARRAY },
|
||||
{ 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, NULL, CH_LAST }
|
||||
};
|
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static uint32 _map_dim_x;
|
||||
static uint32 _map_dim_y;
|
||||
|
||||
@@ -54,7 +56,7 @@ static void Load_MAPT()
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type_height = buf[j];
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +67,30 @@ static void Save_MAPT()
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type_height;
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type;
|
||||
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAPH()
|
||||
{
|
||||
SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_MAPH()
|
||||
{
|
||||
SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height;
|
||||
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
@@ -198,16 +223,16 @@ static void Load_MAP6()
|
||||
/* 1024, otherwise we overflow on 64x64 maps! */
|
||||
SlArray(buf, 1024, SLE_UINT8);
|
||||
for (uint j = 0; j != 1024; j++) {
|
||||
_m[i++].m6 = GB(buf[j], 0, 2);
|
||||
_m[i++].m6 = GB(buf[j], 2, 2);
|
||||
_m[i++].m6 = GB(buf[j], 4, 2);
|
||||
_m[i++].m6 = GB(buf[j], 6, 2);
|
||||
_me[i++].m6 = GB(buf[j], 0, 2);
|
||||
_me[i++].m6 = GB(buf[j], 2, 2);
|
||||
_me[i++].m6 = GB(buf[j], 4, 2);
|
||||
_me[i++].m6 = GB(buf[j], 6, 2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m6 = buf[j];
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,7 +244,7 @@ static void Save_MAP6()
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m6;
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6;
|
||||
SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
@@ -250,6 +275,7 @@ static void Save_MAP7()
|
||||
extern const ChunkHandler _map_chunk_handlers[] = {
|
||||
{ 'MAPS', Save_MAPS, Load_MAPS, NULL, Check_MAPS, CH_RIFF },
|
||||
{ 'MAPT', Save_MAPT, Load_MAPT, NULL, NULL, CH_RIFF },
|
||||
{ 'MAPH', Save_MAPH, Load_MAPH, NULL, NULL, CH_RIFF },
|
||||
{ 'MAPO', Save_MAP1, Load_MAP1, NULL, NULL, CH_RIFF },
|
||||
{ 'MAP2', Save_MAP2, Load_MAP2, NULL, NULL, CH_RIFF },
|
||||
{ 'M3LO', Save_MAP3, Load_MAP3, NULL, NULL, CH_RIFF },
|
||||
|
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern TileIndex _cur_tileloop_tile;
|
||||
extern uint16 _disaster_delay;
|
||||
extern byte _trees_tick_ctr;
|
||||
|
@@ -15,6 +15,8 @@
|
||||
#include "saveload.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Save and load the mapping between a spec and the NewGRF it came from. */
|
||||
static const SaveLoad _newgrf_mapping_desc[] = {
|
||||
SLE_VAR(EntityIDMapping, grfid, SLE_UINT32),
|
||||
@@ -49,7 +51,7 @@ void Load_NewGRFMapping(OverrideManagerBase &mapping)
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if ((uint)index >= max_id) break;
|
||||
if ((uint)index >= max_id) SlErrorCorrupt("Too many NewGRF entity mappings");
|
||||
SlObject(&mapping.mapping_ID[index], _newgrf_mapping_desc);
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#include "saveload.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _object_desc[] = {
|
||||
SLE_VAR(Object, location.tile, SLE_UINT32),
|
||||
SLE_VAR(Object, location.w, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
@@ -24,6 +26,7 @@ static const SaveLoad _object_desc[] = {
|
||||
SLE_VAR(Object, build_date, SLE_UINT32),
|
||||
SLE_CONDVAR(Object, colour, SLE_UINT8, 148, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Object, view, SLE_UINT8, 155, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Object, type, SLE_UINT16, 186, SL_MAX_VERSION),
|
||||
|
||||
SLE_END()
|
||||
};
|
||||
@@ -56,8 +59,6 @@ static void Ptrs_OBJS()
|
||||
if (IsSavegameVersionBefore(148) && !IsTileType(o->location.tile, MP_OBJECT)) {
|
||||
/* Due to a small bug stale objects could remain. */
|
||||
delete o;
|
||||
} else {
|
||||
Object::IncTypeCount(GetObjectType(o->location.tile));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,8 @@
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const int TTO_HEADER_SIZE = 41;
|
||||
static const int TTD_HEADER_SIZE = 49;
|
||||
|
||||
@@ -78,7 +80,7 @@ byte ReadByte(LoadgameState *ls)
|
||||
which means that we have a chunk, which starts with a length
|
||||
byte. If that byte is negative, we have to repeat the next byte
|
||||
that many times ( + 1). Else, we need to read that amount of bytes.
|
||||
Works pretty good if you have many zero's behind eachother */
|
||||
Works pretty well if you have many zeros behind each other */
|
||||
|
||||
if (ls->chunk_size == 0) {
|
||||
/* Read new chunk */
|
||||
@@ -235,7 +237,7 @@ static inline bool CheckOldSavegameType(FILE *f, char *temp, const char *last, u
|
||||
}
|
||||
|
||||
bool ret = VerifyOldNameChecksum(temp, len);
|
||||
temp[len - 2] = '\0'; // name is nul-terminated in savegame, but it's better to be sure
|
||||
temp[len - 2] = '\0'; // name is null-terminated in savegame, but it's better to be sure
|
||||
str_validate(temp, last);
|
||||
|
||||
return ret;
|
||||
@@ -244,16 +246,15 @@ static inline bool CheckOldSavegameType(FILE *f, char *temp, const char *last, u
|
||||
static SavegameType DetermineOldSavegameType(FILE *f, char *title, const char *last)
|
||||
{
|
||||
assert_compile(TTD_HEADER_SIZE >= TTO_HEADER_SIZE);
|
||||
char temp[TTD_HEADER_SIZE];
|
||||
char temp[TTD_HEADER_SIZE] = "Unknown";
|
||||
|
||||
SavegameType type = SGT_TTO;
|
||||
|
||||
/* Can't fseek to 0 as in tar files that is not correct */
|
||||
long pos = ftell(f);
|
||||
if (!CheckOldSavegameType(f, temp, lastof(temp), TTO_HEADER_SIZE)) {
|
||||
if (pos >= 0 && !CheckOldSavegameType(f, temp, lastof(temp), TTO_HEADER_SIZE)) {
|
||||
type = SGT_TTD;
|
||||
fseek(f, pos, SEEK_SET);
|
||||
if (!CheckOldSavegameType(f, temp, lastof(temp), TTD_HEADER_SIZE)) {
|
||||
if (fseek(f, pos, SEEK_SET) < 0 || !CheckOldSavegameType(f, temp, lastof(temp), TTD_HEADER_SIZE)) {
|
||||
type = SGT_INVALID;
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "../effectvehicle_base.h"
|
||||
#include "../engine_func.h"
|
||||
#include "../company_base.h"
|
||||
#include "../disaster_vehicle.h"
|
||||
#include "saveload_internal.h"
|
||||
#include "oldloader.h"
|
||||
|
||||
@@ -34,6 +35,8 @@
|
||||
#include "../table/engines.h"
|
||||
#include "../table/townname.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static bool _read_ttdpatch_flags; ///< Have we (tried to) read TTDPatch extra flags?
|
||||
static uint16 _old_extra_chunk_nums; ///< Number of extra TTDPatch chunks
|
||||
static byte _old_vehicle_multiplier; ///< TTDPatch vehicle multiplier
|
||||
@@ -445,7 +448,8 @@ static bool FixTTOEngines()
|
||||
e->info.climates = 1;
|
||||
}
|
||||
|
||||
e->preview_company_rank = 0;
|
||||
e->preview_company = INVALID_COMPANY;
|
||||
e->preview_asked = (CompanyMask)-1;
|
||||
e->preview_wait = 0;
|
||||
e->name = NULL;
|
||||
}
|
||||
@@ -625,7 +629,7 @@ static bool LoadOldOrder(LoadgameState *ls, int num)
|
||||
if (o->IsType(OT_NOTHING)) {
|
||||
delete o;
|
||||
} else {
|
||||
/* Relink the orders to eachother (in the orders for one vehicle are behind eachother,
|
||||
/* Relink the orders to each other (in the orders for one vehicle are behind each other,
|
||||
* with an invalid order (OT_NOTHING) as indication that it is the last order */
|
||||
Order *prev = Order::GetIfValid(num - 1);
|
||||
if (prev != NULL) prev->next = o;
|
||||
@@ -636,7 +640,7 @@ static bool LoadOldOrder(LoadgameState *ls, int num)
|
||||
|
||||
static bool LoadOldAnimTileList(LoadgameState *ls, int num)
|
||||
{
|
||||
/* This is sligthly hackish - we must load a chunk into an array whose
|
||||
/* This is slightly hackish - we must load a chunk into an array whose
|
||||
* address isn't static, but instead pointed to by _animated_tile_list.
|
||||
* To achieve that, create an OldChunks list on the stack on the fly.
|
||||
* The list cannot be static because the value of _animated_tile_list
|
||||
@@ -687,7 +691,7 @@ static uint8 _cargo_days;
|
||||
|
||||
static const OldChunks goods_chunk[] = {
|
||||
OCL_VAR ( OC_UINT16, 1, &_waiting_acceptance ),
|
||||
OCL_SVAR( OC_UINT8, GoodsEntry, days_since_pickup ),
|
||||
OCL_SVAR( OC_UINT8, GoodsEntry, time_since_pickup ),
|
||||
OCL_SVAR( OC_UINT8, GoodsEntry, rating ),
|
||||
OCL_VAR ( OC_UINT8, 1, &_cargo_source ),
|
||||
OCL_VAR ( OC_UINT8, 1, &_cargo_days ),
|
||||
@@ -707,10 +711,11 @@ static bool LoadOldGood(LoadgameState *ls, int num)
|
||||
|
||||
if (!LoadChunk(ls, ge, goods_chunk)) return false;
|
||||
|
||||
SB(ge->acceptance_pickup, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
|
||||
SB(ge->acceptance_pickup, GoodsEntry::GES_PICKUP, 1, _cargo_source != 0xFF);
|
||||
SB(ge->status, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
|
||||
SB(ge->status, GoodsEntry::GES_RATING, 1, _cargo_source != 0xFF);
|
||||
if (GB(_waiting_acceptance, 0, 12) != 0 && CargoPacket::CanAllocateItem()) {
|
||||
ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, 0, 0));
|
||||
ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, 0, 0),
|
||||
INVALID_STATION);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -926,7 +931,7 @@ static const OldChunks _company_chunk[] = {
|
||||
|
||||
OCL_SVAR( OC_UINT8, Company, colour ),
|
||||
OCL_SVAR( OC_UINT8, Company, money_fraction ),
|
||||
OCL_SVAR( OC_UINT8, Company, quarters_of_bankruptcy ),
|
||||
OCL_SVAR( OC_UINT8, Company, months_of_bankruptcy ),
|
||||
OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Company, bankrupt_asked ),
|
||||
OCL_SVAR( OC_FILE_U32 | OC_VAR_I64, Company, bankrupt_value ),
|
||||
OCL_SVAR( OC_UINT16, Company, bankrupt_timeout ),
|
||||
@@ -1251,6 +1256,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
|
||||
|
||||
if (!LoadChunk(ls, v, vehicle_chunk)) return false;
|
||||
if (v == NULL) continue;
|
||||
v->refit_cap = v->cargo_cap;
|
||||
|
||||
SpriteID sprite = v->cur_image;
|
||||
/* no need to override other sprites */
|
||||
@@ -1401,7 +1407,7 @@ static const OldChunks engine_chunk[] = {
|
||||
|
||||
OCL_NULL( 1 ), // lifelength
|
||||
OCL_SVAR( OC_UINT8, Engine, flags ),
|
||||
OCL_SVAR( OC_UINT8, Engine, preview_company_rank ),
|
||||
OCL_NULL( 1 ), // preview_company_rank
|
||||
OCL_SVAR( OC_UINT8, Engine, preview_wait ),
|
||||
|
||||
OCL_CNULL( OC_TTD, 2 ), ///< railtype + junk
|
||||
@@ -1489,10 +1495,10 @@ static bool LoadOldMapPart1(LoadgameState *ls, int num)
|
||||
}
|
||||
for (uint i = 0; i < OLD_MAP_SIZE / 4; i++) {
|
||||
byte b = ReadByte(ls);
|
||||
_m[i * 4 + 0].m6 = GB(b, 0, 2);
|
||||
_m[i * 4 + 1].m6 = GB(b, 2, 2);
|
||||
_m[i * 4 + 2].m6 = GB(b, 4, 2);
|
||||
_m[i * 4 + 3].m6 = GB(b, 6, 2);
|
||||
_me[i * 4 + 0].m6 = GB(b, 0, 2);
|
||||
_me[i * 4 + 1].m6 = GB(b, 2, 2);
|
||||
_me[i * 4 + 2].m6 = GB(b, 4, 2);
|
||||
_me[i * 4 + 3].m6 = GB(b, 6, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1504,7 +1510,7 @@ static bool LoadOldMapPart2(LoadgameState *ls, int num)
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < OLD_MAP_SIZE; i++) {
|
||||
_m[i].type_height = ReadByte(ls);
|
||||
_m[i].type = ReadByte(ls);
|
||||
}
|
||||
for (i = 0; i < OLD_MAP_SIZE; i++) {
|
||||
_m[i].m5 = ReadByte(ls);
|
||||
@@ -1573,6 +1579,8 @@ extern TileIndex _cur_tileloop_tile;
|
||||
extern uint16 _disaster_delay;
|
||||
extern byte _trees_tick_ctr;
|
||||
extern byte _age_cargo_skip_counter; // From misc_sl.cpp
|
||||
extern uint8 _old_diff_level;
|
||||
extern uint8 _old_units;
|
||||
static const OldChunks main_chunk[] = {
|
||||
OCL_ASSERT( OC_TTD, 0 ),
|
||||
OCL_ASSERT( OC_TTO, 0 ),
|
||||
@@ -1701,7 +1709,7 @@ static const OldChunks main_chunk[] = {
|
||||
OCL_NULL( 1 ), ///< Station tick counter, no longer in use
|
||||
|
||||
OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.currency ),
|
||||
OCL_VAR ( OC_UINT8, 1, &_settings_game.locale.units ),
|
||||
OCL_VAR ( OC_UINT8, 1, &_old_units ),
|
||||
OCL_VAR ( OC_FILE_U8 | OC_VAR_U32, 1, &_cur_company_tick_index ),
|
||||
|
||||
OCL_NULL( 2 ), ///< Date stuff, calculated automatically
|
||||
@@ -1718,7 +1726,7 @@ static const OldChunks main_chunk[] = {
|
||||
|
||||
OCL_ASSERT( OC_TTD, 0x77130 ),
|
||||
|
||||
OCL_VAR ( OC_UINT8, 1, &_settings_game.difficulty.diff_level ),
|
||||
OCL_VAR ( OC_UINT8, 1, &_old_diff_level ),
|
||||
|
||||
OCL_VAR ( OC_TTD | OC_UINT8, 1, &_settings_game.game_creation.landscape ),
|
||||
OCL_VAR ( OC_TTD | OC_UINT8, 1, &_trees_tick_ctr ),
|
||||
@@ -1777,7 +1785,7 @@ bool LoadTTDMain(LoadgameState *ls)
|
||||
FixOldVehicles();
|
||||
|
||||
/* We have a new difficulty setting */
|
||||
_settings_game.difficulty.town_council_tolerance = Clamp(_settings_game.difficulty.diff_level, 0, 2);
|
||||
_settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
|
||||
|
||||
DEBUG(oldloader, 3, "Finished converting game data");
|
||||
DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted");
|
||||
@@ -1820,7 +1828,7 @@ bool LoadTTOMain(LoadgameState *ls)
|
||||
FixTTOCompanies();
|
||||
|
||||
/* We have a new difficulty setting */
|
||||
_settings_game.difficulty.town_council_tolerance = Clamp(_settings_game.difficulty.diff_level, 0, 2);
|
||||
_settings_game.difficulty.town_council_tolerance = Clamp(_old_diff_level, 0, 2);
|
||||
|
||||
/* SVXConverter about cargo payment rates correction:
|
||||
* "increase them to compensate for the faster time advance in TTD compared to TTO
|
||||
|
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "saveload_internal.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Converts this order from an old savegame's version;
|
||||
* it moves all bits to the new location.
|
||||
@@ -107,7 +109,7 @@ const SaveLoad *GetOrderDescription()
|
||||
SLE_VAR(Order, dest, SLE_UINT16),
|
||||
SLE_REF(Order, next, REF_ORDER),
|
||||
SLE_CONDVAR(Order, refit_cargo, SLE_UINT8, 36, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Order, refit_subtype, SLE_UINT8, 36, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(1, 36, 181), // refit_subtype
|
||||
SLE_CONDVAR(Order, wait_time, SLE_UINT16, 67, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Order, travel_time, SLE_UINT16, 67, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Order, max_speed, SLE_UINT16, 172, SL_MAX_VERSION),
|
||||
@@ -184,6 +186,10 @@ static void Load_ORDR()
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Order *order = new (index) Order();
|
||||
SlObject(order, GetOrderDescription());
|
||||
if (IsSavegameVersionBefore(190)) {
|
||||
order->SetTravelTimetabled(order->GetTravelTime() > 0);
|
||||
order->SetWaitTimetabled(order->GetWaitTime() > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,15 +250,23 @@ static void Ptrs_ORDL()
|
||||
const SaveLoad *GetOrderBackupDescription()
|
||||
{
|
||||
static const SaveLoad _order_backup_desc[] = {
|
||||
SLE_VAR(OrderBackup, user, SLE_UINT32),
|
||||
SLE_VAR(OrderBackup, tile, SLE_UINT32),
|
||||
SLE_VAR(OrderBackup, group, SLE_UINT16),
|
||||
SLE_VAR(OrderBackup, service_interval, SLE_INT32),
|
||||
SLE_STR(OrderBackup, name, SLE_STR, 0),
|
||||
SLE_VAR(OrderBackup, clone, SLE_UINT16),
|
||||
SLE_VAR(OrderBackup, orderindex, SLE_UINT8),
|
||||
SLE_REF(OrderBackup, orders, REF_ORDER),
|
||||
SLE_END()
|
||||
SLE_VAR(OrderBackup, user, SLE_UINT32),
|
||||
SLE_VAR(OrderBackup, tile, SLE_UINT32),
|
||||
SLE_VAR(OrderBackup, group, SLE_UINT16),
|
||||
SLE_CONDVAR(OrderBackup, service_interval, SLE_FILE_U32 | SLE_VAR_U16, 0, 191),
|
||||
SLE_CONDVAR(OrderBackup, service_interval, SLE_UINT16, 192, SL_MAX_VERSION),
|
||||
SLE_STR(OrderBackup, name, SLE_STR, 0),
|
||||
SLE_CONDNULL(2, 0, 191), // clone (2 bytes of pointer, i.e. garbage)
|
||||
SLE_CONDREF(OrderBackup, clone, REF_VEHICLE, 192, SL_MAX_VERSION),
|
||||
SLE_VAR(OrderBackup, cur_real_order_index, SLE_UINT8),
|
||||
SLE_CONDVAR(OrderBackup, cur_implicit_order_index, SLE_UINT8, 176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(OrderBackup, current_order_time, SLE_UINT32, 176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(OrderBackup, lateness_counter, SLE_INT32, 176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(OrderBackup, timetable_start, SLE_INT32, 176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, 176, 179),
|
||||
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_UINT16, 180, SL_MAX_VERSION),
|
||||
SLE_REF(OrderBackup, orders, REF_ORDER),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
return _order_backup_desc;
|
||||
@@ -281,13 +295,6 @@ void Load_BKOR()
|
||||
OrderBackup *ob = new (index) OrderBackup();
|
||||
SlObject(ob, GetOrderBackupDescription());
|
||||
}
|
||||
|
||||
/* If we are a network server, then we just loaded
|
||||
* a previously saved-by-server savegame. There are
|
||||
* no clients with a backup anymore, so clear it. */
|
||||
if (_networking && _network_server) {
|
||||
_order_backup_pool.CleanPool();
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_BKOR()
|
||||
|
@@ -35,6 +35,8 @@
|
||||
#include "../date_func.h"
|
||||
#include "../autoreplace_base.h"
|
||||
#include "../roadstop_base.h"
|
||||
#include "../linkgraph/linkgraph.h"
|
||||
#include "../linkgraph/linkgraphjob.h"
|
||||
#include "../statusbar_gui.h"
|
||||
#include "../fileio_func.h"
|
||||
#include "../gamelog.h"
|
||||
@@ -47,6 +49,8 @@
|
||||
#include "saveload_internal.h"
|
||||
#include "saveload_filter.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/*
|
||||
* Previous savegame versions, the trunk revision where they were
|
||||
* introduced and the released version that had that particular
|
||||
@@ -238,6 +242,26 @@
|
||||
* 172 23947
|
||||
* 173 23967 1.2.0-RC1
|
||||
* 174 23973 1.2.x
|
||||
* 175 24136
|
||||
* 176 24446
|
||||
* 177 24619
|
||||
* 178 24789
|
||||
* 179 24810
|
||||
* 180 24998 1.3.x
|
||||
* 181 25012
|
||||
* 182 25296
|
||||
* 183 25363
|
||||
* 184 25508
|
||||
* 185 25620
|
||||
* 186 25833
|
||||
* 187 25899
|
||||
* 188 26169 1.4.x
|
||||
* 189 26450
|
||||
* 190 26547
|
||||
* 191 26646
|
||||
* 192 26700
|
||||
* 193 26802
|
||||
* 194 26881 1.5.x
|
||||
*/
|
||||
extern const uint16 SAVEGAME_VERSION = 200; ///< Current savegame version of OpenTTD.
|
||||
|
||||
@@ -408,7 +432,9 @@ extern const ChunkHandler _station_chunk_handlers[];
|
||||
extern const ChunkHandler _industry_chunk_handlers[];
|
||||
extern const ChunkHandler _economy_chunk_handlers[];
|
||||
extern const ChunkHandler _subsidy_chunk_handlers[];
|
||||
extern const ChunkHandler _cargomonitor_chunk_handlers[];
|
||||
extern const ChunkHandler _goal_chunk_handlers[];
|
||||
extern const ChunkHandler _story_page_chunk_handlers[];
|
||||
extern const ChunkHandler _ai_chunk_handlers[];
|
||||
extern const ChunkHandler _game_chunk_handlers[];
|
||||
extern const ChunkHandler _animated_tile_chunk_handlers[];
|
||||
@@ -417,6 +443,7 @@ extern const ChunkHandler _group_chunk_handlers[];
|
||||
extern const ChunkHandler _cargopacket_chunk_handlers[];
|
||||
extern const ChunkHandler _autoreplace_chunk_handlers[];
|
||||
extern const ChunkHandler _labelmaps_chunk_handlers[];
|
||||
extern const ChunkHandler _linkgraph_chunk_handlers[];
|
||||
extern const ChunkHandler _airport_chunk_handlers[];
|
||||
extern const ChunkHandler _object_chunk_handlers[];
|
||||
extern const ChunkHandler _persistent_storage_chunk_handlers[];
|
||||
@@ -436,7 +463,9 @@ static const ChunkHandler * const _chunk_handlers[] = {
|
||||
_industry_chunk_handlers,
|
||||
_economy_chunk_handlers,
|
||||
_subsidy_chunk_handlers,
|
||||
_cargomonitor_chunk_handlers,
|
||||
_goal_chunk_handlers,
|
||||
_story_page_chunk_handlers,
|
||||
_engine_chunk_handlers,
|
||||
_town_chunk_handlers,
|
||||
_sign_chunk_handlers,
|
||||
@@ -450,6 +479,7 @@ static const ChunkHandler * const _chunk_handlers[] = {
|
||||
_cargopacket_chunk_handlers,
|
||||
_autoreplace_chunk_handlers,
|
||||
_labelmaps_chunk_handlers,
|
||||
_linkgraph_chunk_handlers,
|
||||
_airport_chunk_handlers,
|
||||
_object_chunk_handlers,
|
||||
_persistent_storage_chunk_handlers,
|
||||
@@ -502,11 +532,11 @@ void NORETURN SlError(StringID string, const char *extra_msg)
|
||||
if (_sl.action == SLA_LOAD_CHECK) {
|
||||
_load_check_data.error = string;
|
||||
free(_load_check_data.error_data);
|
||||
_load_check_data.error_data = (extra_msg == NULL) ? NULL : strdup(extra_msg);
|
||||
_load_check_data.error_data = (extra_msg == NULL) ? NULL : stredup(extra_msg);
|
||||
} else {
|
||||
_sl.error_str = string;
|
||||
free(_sl.extra_msg);
|
||||
_sl.extra_msg = (extra_msg == NULL) ? NULL : strdup(extra_msg);
|
||||
_sl.extra_msg = (extra_msg == NULL) ? NULL : stredup(extra_msg);
|
||||
}
|
||||
|
||||
/* We have to NULL all pointers here; we might be in a state where
|
||||
@@ -648,7 +678,11 @@ static uint SlReadSimpleGamma()
|
||||
if (HasBit(i, 5)) {
|
||||
i &= ~0x20;
|
||||
if (HasBit(i, 4)) {
|
||||
SlErrorCorrupt("Unsupported gamma");
|
||||
i &= ~0x10;
|
||||
if (HasBit(i, 3)) {
|
||||
SlErrorCorrupt("Unsupported gamma");
|
||||
}
|
||||
i = SlReadByte(); // 32 bits only.
|
||||
}
|
||||
i = (i << 8) | SlReadByte();
|
||||
}
|
||||
@@ -668,6 +702,11 @@ static uint SlReadSimpleGamma()
|
||||
* 10xxxxxx xxxxxxxx
|
||||
* 110xxxxx xxxxxxxx xxxxxxxx
|
||||
* 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx
|
||||
* 11110--- xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
|
||||
* We could extend the scheme ad infinum to support arbitrarily
|
||||
* large chunks, but as sizeof(size_t) == 4 is still very common
|
||||
* we don't support anything above 32 bits. That's why in the last
|
||||
* case the 3 most significant bits are unused.
|
||||
* @param i Index being written
|
||||
*/
|
||||
|
||||
@@ -676,8 +715,13 @@ static void SlWriteSimpleGamma(size_t i)
|
||||
if (i >= (1 << 7)) {
|
||||
if (i >= (1 << 14)) {
|
||||
if (i >= (1 << 21)) {
|
||||
assert(i < (1 << 28));
|
||||
SlWriteByte((byte)(0xE0 | (i >> 24)));
|
||||
if (i >= (1 << 28)) {
|
||||
assert(i <= UINT32_MAX); // We can only support 32 bits for now.
|
||||
SlWriteByte((byte)(0xF0));
|
||||
SlWriteByte((byte)(i >> 24));
|
||||
} else {
|
||||
SlWriteByte((byte)(0xE0 | (i >> 24)));
|
||||
}
|
||||
SlWriteByte((byte)(i >> 16));
|
||||
} else {
|
||||
SlWriteByte((byte)(0xC0 | (i >> 16)));
|
||||
@@ -693,7 +737,7 @@ static void SlWriteSimpleGamma(size_t i)
|
||||
/** Return how many bytes used to encode a gamma value */
|
||||
static inline uint SlGetGammaLength(size_t i)
|
||||
{
|
||||
return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21));
|
||||
return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)) + (i >= (1 << 28));
|
||||
}
|
||||
|
||||
static inline uint SlReadSparseIndex()
|
||||
@@ -1197,23 +1241,25 @@ static size_t ReferenceToInt(const void *obj, SLRefType rt)
|
||||
if (obj == NULL) return 0;
|
||||
|
||||
switch (rt) {
|
||||
case REF_VEHICLE_OLD: // Old vehicles we save as new onces
|
||||
case REF_VEHICLE_OLD: // Old vehicles we save as new ones
|
||||
case REF_VEHICLE: return ((const Vehicle*)obj)->index + 1;
|
||||
case REF_STATION: return ((const Station*)obj)->index + 1;
|
||||
case REF_TOWN: return ((const Town*)obj)->index + 1;
|
||||
case REF_ORDER: return ((const Order*)obj)->index + 1;
|
||||
case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
|
||||
case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1;
|
||||
case REF_CARGO_PACKET: return ((const CargoPacket*)obj)->index + 1;
|
||||
case REF_ORDERLIST: return ((const OrderList*)obj)->index + 1;
|
||||
case REF_STORAGE: return ((const PersistentStorage*)obj)->index + 1;
|
||||
case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1;
|
||||
case REF_CARGO_PACKET: return ((const CargoPacket*)obj)->index + 1;
|
||||
case REF_ORDERLIST: return ((const OrderList*)obj)->index + 1;
|
||||
case REF_STORAGE: return ((const PersistentStorage*)obj)->index + 1;
|
||||
case REF_LINK_GRAPH: return ((const LinkGraph*)obj)->index + 1;
|
||||
case REF_LINK_GRAPH_JOB: return ((const LinkGraphJob*)obj)->index + 1;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pointers cannot be loaded from a savegame, so this function
|
||||
* gets the index from the savegame and returns the appropiate
|
||||
* gets the index from the savegame and returns the appropriate
|
||||
* pointer from the already loaded base.
|
||||
* Remember that an index of 0 is a NULL pointer so all indices
|
||||
* are +1 so vehicle 0 is saved as 1.
|
||||
@@ -1280,6 +1326,14 @@ static void *IntToReference(size_t index, SLRefType rt)
|
||||
if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index);
|
||||
SlErrorCorrupt("Referencing invalid PersistentStorage");
|
||||
|
||||
case REF_LINK_GRAPH:
|
||||
if (LinkGraph::IsValidID(index)) return LinkGraph::Get(index);
|
||||
SlErrorCorrupt("Referencing invalid LinkGraph");
|
||||
|
||||
case REF_LINK_GRAPH_JOB:
|
||||
if (LinkGraphJob::IsValidID(index)) return LinkGraphJob::Get(index);
|
||||
SlErrorCorrupt("Referencing invalid LinkGraphJob");
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
@@ -1385,7 +1439,7 @@ static inline bool SlSkipVariableOnLoad(const SaveLoad *sld)
|
||||
* Calculate the size of an object.
|
||||
* @param object to be measured
|
||||
* @param sld The SaveLoad description of the object so we know how to manipulate it
|
||||
* @return size of given objetc
|
||||
* @return size of given object
|
||||
*/
|
||||
size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
|
||||
{
|
||||
@@ -1428,9 +1482,50 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the variable size of the variable in the saveload configuration
|
||||
* matches with the actual variable size.
|
||||
* @param sld The saveload configuration to test.
|
||||
*/
|
||||
static bool IsVariableSizeRight(const SaveLoad *sld)
|
||||
{
|
||||
switch (sld->cmd) {
|
||||
case SL_VAR:
|
||||
switch (GetVarMemType(sld->conv)) {
|
||||
case SLE_VAR_BL:
|
||||
return sld->size == sizeof(bool);
|
||||
case SLE_VAR_I8:
|
||||
case SLE_VAR_U8:
|
||||
return sld->size == sizeof(int8);
|
||||
case SLE_VAR_I16:
|
||||
case SLE_VAR_U16:
|
||||
return sld->size == sizeof(int16);
|
||||
case SLE_VAR_I32:
|
||||
case SLE_VAR_U32:
|
||||
return sld->size == sizeof(int32);
|
||||
case SLE_VAR_I64:
|
||||
case SLE_VAR_U64:
|
||||
return sld->size == sizeof(int64);
|
||||
default:
|
||||
return sld->size == sizeof(void *);
|
||||
}
|
||||
case SL_REF:
|
||||
/* These should all be pointer sized. */
|
||||
return sld->size == sizeof(void *);
|
||||
|
||||
case SL_STR:
|
||||
/* These should be pointer sized, or fixed array. */
|
||||
return sld->size == sizeof(void *) || sld->size == sld->length;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SlObjectMember(void *ptr, const SaveLoad *sld)
|
||||
{
|
||||
assert(IsVariableSizeRight(sld));
|
||||
|
||||
VarType conv = GB(sld->conv, 0, 8);
|
||||
switch (sld->cmd) {
|
||||
case SL_VAR:
|
||||
@@ -1572,9 +1667,11 @@ static void SlLoadChunk(const ChunkHandler *ch)
|
||||
case CH_ARRAY:
|
||||
_sl.array_index = 0;
|
||||
ch->load_proc();
|
||||
if (_next_offs != 0) SlErrorCorrupt("Invalid array length");
|
||||
break;
|
||||
case CH_SPARSE_ARRAY:
|
||||
ch->load_proc();
|
||||
if (_next_offs != 0) SlErrorCorrupt("Invalid array length");
|
||||
break;
|
||||
default:
|
||||
if ((m & 0xF) == CH_RIFF) {
|
||||
@@ -1670,7 +1767,7 @@ static void SlStubSaveProc()
|
||||
|
||||
/**
|
||||
* Save a chunk of data (eg. vehicles, stations, etc.). Each chunk is
|
||||
* prefixed by an ID identifying it, followed by data, and terminator where appropiate
|
||||
* prefixed by an ID identifying it, followed by data, and terminator where appropriate
|
||||
* @param ch The chunkhandler that will be used for the operation
|
||||
*/
|
||||
static void SlSaveChunk(const ChunkHandler *ch)
|
||||
@@ -1725,7 +1822,7 @@ static void SlSaveChunks()
|
||||
* Find the ChunkHandler that will be used for processing the found
|
||||
* chunk in the savegame or in memory
|
||||
* @param id the chunk in question
|
||||
* @return returns the appropiate chunkhandler
|
||||
* @return returns the appropriate chunkhandler
|
||||
*/
|
||||
static const ChunkHandler *SlFindChunkHandler(uint32 id)
|
||||
{
|
||||
@@ -1817,7 +1914,9 @@ struct FileReader : LoadFilter {
|
||||
/* virtual */ void Reset()
|
||||
{
|
||||
clearerr(this->file);
|
||||
fseek(this->file, this->begin, SEEK_SET);
|
||||
if (fseek(this->file, this->begin, SEEK_SET)) {
|
||||
DEBUG(sl, 1, "Could not reset the file reading");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1908,7 +2007,7 @@ struct LZOLoadFilter : LoadFilter {
|
||||
if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum");
|
||||
|
||||
/* Decompress */
|
||||
lzo1x_decompress(out + sizeof(uint32) * 1, size, buf, &len, NULL);
|
||||
lzo1x_decompress_safe(out + sizeof(uint32) * 1, size, buf, &len, NULL);
|
||||
return len;
|
||||
}
|
||||
};
|
||||
@@ -2080,7 +2179,7 @@ struct ZlibSaveFilter : SaveFilter {
|
||||
* "Conditional jump or move depends on uninitialised value(s)" kind:
|
||||
* According to the author of zlib it is not a bug and it won't be fixed.
|
||||
* http://groups.google.com/group/comp.compression/browse_thread/thread/b154b8def8c2a3ef/cdf9b8729ce17ee2
|
||||
* [Mark Adler, Feb 24 2004, 'zlib-1.2.1 valgrind warnings' in the newgroup comp.compression]
|
||||
* [Mark Adler, Feb 24 2004, 'zlib-1.2.1 valgrind warnings' in the newsgroup comp.compression]
|
||||
*/
|
||||
int r = deflate(&this->z, mode);
|
||||
|
||||
@@ -2267,7 +2366,7 @@ static const SaveLoadFormat _saveload_formats[] = {
|
||||
* Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
|
||||
* The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
|
||||
* slower while not improving the filesize, while level 0 and 1 are faster, but don't reduce savegame size much.
|
||||
* It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is prefered over .tar.lzma. */
|
||||
* It's OTTX and not e.g. OTTL because liblzma is part of xz-utils and .tar.xz is preferred over .tar.lzma. */
|
||||
{"lzma", TO_BE32X('OTTX'), CreateLoadFilter<LZMALoadFilter>, CreateSaveFilter<LZMASaveFilter>, 0, 2, 9},
|
||||
#else
|
||||
{"lzma", TO_BE32X('OTTX'), NULL, NULL, 0, 0, 0},
|
||||
@@ -2403,7 +2502,7 @@ static void SaveFileError()
|
||||
|
||||
/**
|
||||
* We have written the whole game into memory, _memory_savegame, now find
|
||||
* and appropiate compressor and start writing to file.
|
||||
* and appropriate compressor and start writing to file.
|
||||
*/
|
||||
static SaveOrLoadResult SaveFileToDisk(bool threaded)
|
||||
{
|
||||
@@ -2465,10 +2564,10 @@ void WaitTillSaved()
|
||||
|
||||
/**
|
||||
* Actually perform the saving of the savegame.
|
||||
* General tactic is to first save the game to memory, then write it to file
|
||||
* General tactics is to first save the game to memory, then write it to file
|
||||
* using the writer, either in threaded mode if possible, or single-threaded.
|
||||
* @param writer The filter to write the savegame to.
|
||||
* @param threaded Whether to try to perform the saving asynchroniously.
|
||||
* @param threaded Whether to try to perform the saving asynchronously.
|
||||
* @return Return the result of the action. #SL_OK or #SL_ERROR
|
||||
*/
|
||||
static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
|
||||
@@ -2499,7 +2598,7 @@ static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
|
||||
/**
|
||||
* Save the game using a (writer) filter.
|
||||
* @param writer The filter to write the savegame to.
|
||||
* @param threaded Whether to try to perform the saving asynchroniously.
|
||||
* @param threaded Whether to try to perform the saving asynchronously.
|
||||
* @return Return the result of the action. #SL_OK or #SL_ERROR
|
||||
*/
|
||||
SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded)
|
||||
@@ -2561,7 +2660,7 @@ static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
|
||||
_sl_version = TO_BE32(hdr[1]) >> 16;
|
||||
/* Minor is not used anymore from version 18.0, but it is still needed
|
||||
* in versions before that (4 cases) which can't be removed easy.
|
||||
* Therefor it is loaded, but never saved (or, it saves a 0 in any scenario). */
|
||||
* Therefore it is loaded, but never saved (or, it saves a 0 in any scenario). */
|
||||
_sl_minor_version = (TO_BE32(hdr[1]) >> 8) & 0xFF;
|
||||
|
||||
DEBUG(sl, 1, "Loading savegame version %d", _sl_version);
|
||||
@@ -2577,7 +2676,7 @@ static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
|
||||
/* loader for this savegame type is not implemented? */
|
||||
if (fmt->init_load == NULL) {
|
||||
char err_str[64];
|
||||
snprintf(err_str, lengthof(err_str), "Loader for '%s' is not available.", fmt->name);
|
||||
seprintf(err_str, lastof(err_str), "Loader for '%s' is not available.", fmt->name);
|
||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
|
||||
}
|
||||
|
||||
@@ -2687,36 +2786,36 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
|
||||
}
|
||||
WaitTillSaved();
|
||||
|
||||
/* Load a TTDLX or TTDPatch game */
|
||||
if (mode == SL_OLD_LOAD) {
|
||||
InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
|
||||
|
||||
/* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
|
||||
* and if so a new NewGRF list will be made in LoadOldSaveGame.
|
||||
* Note: this is done here because AfterLoadGame is also called
|
||||
* for OTTD savegames which have their own NewGRF logic. */
|
||||
ClearGRFConfigList(&_grfconfig);
|
||||
GamelogReset();
|
||||
if (!LoadOldSaveGame(filename)) return SL_REINIT;
|
||||
_sl_version = 0;
|
||||
_sl_minor_version = 0;
|
||||
GamelogStartAction(GLAT_LOAD);
|
||||
if (!AfterLoadGame()) {
|
||||
GamelogStopAction();
|
||||
return SL_REINIT;
|
||||
}
|
||||
GamelogStopAction();
|
||||
return SL_OK;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
|
||||
case SL_LOAD: _sl.action = SLA_LOAD; break;
|
||||
case SL_SAVE: _sl.action = SLA_SAVE; break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
try {
|
||||
/* Load a TTDLX or TTDPatch game */
|
||||
if (mode == SL_OLD_LOAD) {
|
||||
InitializeGame(256, 256, true, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
|
||||
|
||||
/* TTD/TTO savegames have no NewGRFs, TTDP savegame have them
|
||||
* and if so a new NewGRF list will be made in LoadOldSaveGame.
|
||||
* Note: this is done here because AfterLoadGame is also called
|
||||
* for OTTD savegames which have their own NewGRF logic. */
|
||||
ClearGRFConfigList(&_grfconfig);
|
||||
GamelogReset();
|
||||
if (!LoadOldSaveGame(filename)) return SL_REINIT;
|
||||
_sl_version = 0;
|
||||
_sl_minor_version = 0;
|
||||
GamelogStartAction(GLAT_LOAD);
|
||||
if (!AfterLoadGame()) {
|
||||
GamelogStopAction();
|
||||
return SL_REINIT;
|
||||
}
|
||||
GamelogStopAction();
|
||||
return SL_OK;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case SL_LOAD_CHECK: _sl.action = SLA_LOAD_CHECK; break;
|
||||
case SL_LOAD: _sl.action = SLA_LOAD; break;
|
||||
case SL_SAVE: _sl.action = SLA_SAVE; break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
FILE *fh = (mode == SL_SAVE) ? FioFOpenFile(filename, "wb", sb) : FioFOpenFile(filename, "rb", sb);
|
||||
|
||||
/* Make it a little easier to load savegames from the console */
|
||||
@@ -2746,7 +2845,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
|
||||
if (mode != SL_LOAD_CHECK) DEBUG(sl, 0, "%s", GetSaveLoadErrorString() + 3);
|
||||
|
||||
/* A saver/loader exception!! reinitialize all variables to prevent crash! */
|
||||
return (mode == SL_LOAD) ? SL_REINIT : SL_ERROR;
|
||||
return (mode == SL_LOAD || mode == SL_OLD_LOAD) ? SL_REINIT : SL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -73,20 +73,22 @@ struct NullStruct {
|
||||
|
||||
/** Type of reference (#SLE_REF, #SLE_CONDREF). */
|
||||
enum SLRefType {
|
||||
REF_ORDER = 0, ///< Load/save a reference to an order.
|
||||
REF_VEHICLE = 1, ///< Load/save a reference to a vehicle.
|
||||
REF_STATION = 2, ///< Load/save a reference to a station.
|
||||
REF_TOWN = 3, ///< Load/save a reference to a town.
|
||||
REF_VEHICLE_OLD = 4, ///< Load/save an old-style reference to a vehicle (for pre-4.4 savegames).
|
||||
REF_ROADSTOPS = 5, ///< Load/save a reference to a bus/truck stop.
|
||||
REF_ENGINE_RENEWS = 6, ///< Load/save a reference to an engine renewal (autoreplace).
|
||||
REF_CARGO_PACKET = 7, ///< Load/save a reference to a cargo packet.
|
||||
REF_ORDERLIST = 8, ///< Load/save a reference to an orderlist.
|
||||
REF_STORAGE = 9, ///< Load/save a reference to a persistent storage.
|
||||
REF_ORDER = 0, ///< Load/save a reference to an order.
|
||||
REF_VEHICLE = 1, ///< Load/save a reference to a vehicle.
|
||||
REF_STATION = 2, ///< Load/save a reference to a station.
|
||||
REF_TOWN = 3, ///< Load/save a reference to a town.
|
||||
REF_VEHICLE_OLD = 4, ///< Load/save an old-style reference to a vehicle (for pre-4.4 savegames).
|
||||
REF_ROADSTOPS = 5, ///< Load/save a reference to a bus/truck stop.
|
||||
REF_ENGINE_RENEWS = 6, ///< Load/save a reference to an engine renewal (autoreplace).
|
||||
REF_CARGO_PACKET = 7, ///< Load/save a reference to a cargo packet.
|
||||
REF_ORDERLIST = 8, ///< Load/save a reference to an orderlist.
|
||||
REF_STORAGE = 9, ///< Load/save a reference to a persistent storage.
|
||||
REF_LINK_GRAPH = 10, ///< Load/save a reference to a link graph.
|
||||
REF_LINK_GRAPH_JOB = 11, ///< Load/save a reference to a link graph job.
|
||||
};
|
||||
|
||||
/** Highest possible savegame version. */
|
||||
#define SL_MAX_VERSION 255
|
||||
#define SL_MAX_VERSION UINT16_MAX
|
||||
|
||||
/** Flags of a chunk. */
|
||||
enum ChunkType {
|
||||
@@ -210,6 +212,7 @@ struct SaveLoad {
|
||||
* during runtime. Decision on which one to use is controlled by the function
|
||||
* that is called to save it. address: global=true, offset: global=false */
|
||||
void *address; ///< address of variable OR offset of variable in the struct (max offset is 65536)
|
||||
size_t size; ///< the sizeof size.
|
||||
};
|
||||
|
||||
/** Same as #SaveLoad but global variables are used (for better readability); */
|
||||
@@ -225,7 +228,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param to Last savegame version that has the field.
|
||||
* @note In general, it is better to use one of the SLE_* macros below.
|
||||
*/
|
||||
#define SLE_GENERAL(cmd, base, variable, type, length, from, to) {false, cmd, type, length, from, to, (void*)cpp_offsetof(base, variable)}
|
||||
#define SLE_GENERAL(cmd, base, variable, type, length, from, to) {false, cmd, type, length, from, to, (void*)cpp_offsetof(base, variable), cpp_sizeof(base, variable)}
|
||||
|
||||
/**
|
||||
* Storage of a variable in some savegame versions.
|
||||
@@ -338,11 +341,11 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
/** Translate values ingame to different values in the savegame and vv. */
|
||||
#define SLE_WRITEBYTE(base, variable, value) SLE_GENERAL(SL_WRITEBYTE, base, variable, 0, 0, value, value)
|
||||
|
||||
#define SLE_VEH_INCLUDE() {false, SL_VEH_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL}
|
||||
#define SLE_ST_INCLUDE() {false, SL_ST_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL}
|
||||
#define SLE_VEH_INCLUDE() {false, SL_VEH_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0}
|
||||
#define SLE_ST_INCLUDE() {false, SL_ST_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0}
|
||||
|
||||
/** End marker of a struct/class save or load. */
|
||||
#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL}
|
||||
#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL, 0}
|
||||
|
||||
/**
|
||||
* Storage of global simple variables, references (pointers), and arrays.
|
||||
@@ -353,7 +356,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
* @param to Last savegame version that has the field.
|
||||
* @note In general, it is better to use one of the SLEG_* macros below.
|
||||
*/
|
||||
#define SLEG_GENERAL(cmd, variable, type, length, from, to) {true, cmd, type, length, from, to, (void*)&variable}
|
||||
#define SLEG_GENERAL(cmd, variable, type, length, from, to) {true, cmd, type, length, from, to, (void*)&variable, sizeof(variable)}
|
||||
|
||||
/**
|
||||
* Storage of a global variable in some savegame versions.
|
||||
@@ -446,7 +449,7 @@ typedef SaveLoad SaveLoadGlobVarList;
|
||||
#define SLEG_CONDNULL(length, from, to) {true, SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, (void*)NULL}
|
||||
|
||||
/** End marker of global variables save or load. */
|
||||
#define SLEG_END() {true, SL_END, 0, 0, 0, 0, NULL}
|
||||
#define SLEG_END() {true, SL_END, 0, 0, 0, 0, NULL, 0}
|
||||
|
||||
/**
|
||||
* Checks whether the savegame is below \a major.\a minor.
|
||||
|
@@ -31,6 +31,8 @@ void FixupTrainLengths();
|
||||
void AfterLoadStations();
|
||||
void AfterLoadRoadStops();
|
||||
void AfterLoadLabelMaps();
|
||||
void AfterLoadStoryBook();
|
||||
void AfterLoadLinkGraphs();
|
||||
void AfterLoadCompanyStats();
|
||||
void UpdateHousesAndTowns();
|
||||
|
||||
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Description of a sign within the savegame. */
|
||||
static const SaveLoad _sign_desc[] = {
|
||||
SLE_CONDVAR(Sign, name, SLE_NAME, 0, 83),
|
||||
|
@@ -19,6 +19,8 @@
|
||||
#include "saveload.h"
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Update the buoy orders to be waypoint orders.
|
||||
* @param o the order 'list' to check.
|
||||
@@ -93,7 +95,7 @@ void MoveBuoysToWaypoints()
|
||||
TILE_AREA_LOOP(t, train_st) {
|
||||
if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != index) continue;
|
||||
|
||||
SB(_m[t].m6, 3, 3, STATION_WAYPOINT);
|
||||
SB(_me[t].m6, 3, 3, STATION_WAYPOINT);
|
||||
wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
|
||||
}
|
||||
|
||||
@@ -123,7 +125,7 @@ void AfterLoadStations()
|
||||
for (const RoadStop *rs = sta->truck_stops; rs != NULL; rs = rs->next) sta->truck_station.Add(rs->xy);
|
||||
}
|
||||
|
||||
StationUpdateAnimTriggers(st);
|
||||
StationUpdateCachedTriggers(st);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,9 +226,10 @@ static const SaveLoad _old_station_desc[] = {
|
||||
};
|
||||
|
||||
static uint16 _waiting_acceptance;
|
||||
static uint32 _num_flows;
|
||||
static uint16 _cargo_source;
|
||||
static uint32 _cargo_source_xy;
|
||||
static uint16 _cargo_days;
|
||||
static uint8 _cargo_days;
|
||||
static Money _cargo_feeder_share;
|
||||
|
||||
static const SaveLoad _station_speclist_desc[] = {
|
||||
@@ -236,6 +239,25 @@ static const SaveLoad _station_speclist_desc[] = {
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
std::list<CargoPacket *> _packets;
|
||||
uint32 _num_dests;
|
||||
|
||||
struct FlowSaveLoad {
|
||||
FlowSaveLoad() : source(0), via(0), share(0), restricted(false) {}
|
||||
StationID source;
|
||||
StationID via;
|
||||
uint32 share;
|
||||
bool restricted;
|
||||
};
|
||||
|
||||
static const SaveLoad _flow_desc[] = {
|
||||
SLE_VAR(FlowSaveLoad, source, SLE_UINT16),
|
||||
SLE_VAR(FlowSaveLoad, via, SLE_UINT16),
|
||||
SLE_VAR(FlowSaveLoad, share, SLE_UINT32),
|
||||
SLE_CONDVAR(FlowSaveLoad, restricted, SLE_BOOL, 187, SL_MAX_VERSION),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper function to get the GoodsEntry's internal structure while
|
||||
* some of the variables itself are private.
|
||||
@@ -244,28 +266,62 @@ static const SaveLoad _station_speclist_desc[] = {
|
||||
const SaveLoad *GetGoodsDesc()
|
||||
{
|
||||
static const SaveLoad goods_desc[] = {
|
||||
SLEG_CONDVAR( _waiting_acceptance, SLE_UINT16, 0, 67),
|
||||
SLE_CONDVAR(GoodsEntry, acceptance_pickup, SLE_UINT8, 68, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(2, 51, 67),
|
||||
SLE_VAR(GoodsEntry, days_since_pickup, SLE_UINT8),
|
||||
SLE_VAR(GoodsEntry, rating, SLE_UINT8),
|
||||
SLEG_CONDVAR( _cargo_source, SLE_FILE_U8 | SLE_VAR_U16, 0, 6),
|
||||
SLEG_CONDVAR( _cargo_source, SLE_UINT16, 7, 67),
|
||||
SLEG_CONDVAR( _cargo_source_xy, SLE_UINT32, 44, 67),
|
||||
SLEG_CONDVAR( _cargo_days, SLE_UINT8, 0, 67),
|
||||
SLE_VAR(GoodsEntry, last_speed, SLE_UINT8),
|
||||
SLE_VAR(GoodsEntry, last_age, SLE_UINT8),
|
||||
SLEG_CONDVAR( _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
|
||||
SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, 65, 67),
|
||||
SLE_CONDVAR(GoodsEntry, amount_fract, SLE_UINT8, 150, SL_MAX_VERSION),
|
||||
SLE_CONDLST(GoodsEntry, cargo.packets, REF_CARGO_PACKET, 68, SL_MAX_VERSION),
|
||||
|
||||
SLEG_CONDVAR( _waiting_acceptance, SLE_UINT16, 0, 67),
|
||||
SLE_CONDVAR(GoodsEntry, status, SLE_UINT8, 68, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(2, 51, 67),
|
||||
SLE_VAR(GoodsEntry, time_since_pickup, SLE_UINT8),
|
||||
SLE_VAR(GoodsEntry, rating, SLE_UINT8),
|
||||
SLEG_CONDVAR( _cargo_source, SLE_FILE_U8 | SLE_VAR_U16, 0, 6),
|
||||
SLEG_CONDVAR( _cargo_source, SLE_UINT16, 7, 67),
|
||||
SLEG_CONDVAR( _cargo_source_xy, SLE_UINT32, 44, 67),
|
||||
SLEG_CONDVAR( _cargo_days, SLE_UINT8, 0, 67),
|
||||
SLE_VAR(GoodsEntry, last_speed, SLE_UINT8),
|
||||
SLE_VAR(GoodsEntry, last_age, SLE_UINT8),
|
||||
SLEG_CONDVAR( _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
|
||||
SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, 65, 67),
|
||||
SLE_CONDVAR(GoodsEntry, amount_fract, SLE_UINT8, 150, SL_MAX_VERSION),
|
||||
SLEG_CONDLST( _packets, REF_CARGO_PACKET, 68, 182),
|
||||
SLEG_CONDVAR( _num_dests, SLE_UINT32, 183, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(GoodsEntry, cargo.reserved_count, SLE_UINT, 181, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(GoodsEntry, link_graph, SLE_UINT16, 183, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(GoodsEntry, node, SLE_UINT16, 183, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR( _num_flows, SLE_UINT32, 183, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(GoodsEntry, max_waiting_cargo, SLE_UINT32, 183, SL_MAX_VERSION),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
return goods_desc;
|
||||
}
|
||||
|
||||
typedef std::pair<const StationID, std::list<CargoPacket *> > StationCargoPair;
|
||||
|
||||
static const SaveLoad _cargo_list_desc[] = {
|
||||
SLE_VAR(StationCargoPair, first, SLE_UINT16),
|
||||
SLE_LST(StationCargoPair, second, REF_CARGO_PACKET),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
/**
|
||||
* Swap the temporary packets with the packets without specific destination in
|
||||
* the given goods entry. Assert that at least one of those is empty.
|
||||
* @param ge Goods entry to swap with.
|
||||
*/
|
||||
static void SwapPackets(GoodsEntry *ge)
|
||||
{
|
||||
StationCargoPacketMap &ge_packets = const_cast<StationCargoPacketMap &>(*ge->cargo.Packets());
|
||||
|
||||
if (_packets.empty()) {
|
||||
std::map<StationID, std::list<CargoPacket *> >::iterator it(ge_packets.find(INVALID_STATION));
|
||||
if (it == ge_packets.end()) {
|
||||
return;
|
||||
} else {
|
||||
it->second.swap(_packets);
|
||||
}
|
||||
} else {
|
||||
assert(ge_packets[INVALID_STATION].empty());
|
||||
ge_packets[INVALID_STATION].swap(_packets);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_STNS()
|
||||
{
|
||||
@@ -281,8 +337,9 @@ static void Load_STNS()
|
||||
for (CargoID i = 0; i < num_cargo; i++) {
|
||||
GoodsEntry *ge = &st->goods[i];
|
||||
SlObject(ge, GetGoodsDesc());
|
||||
SwapPackets(ge);
|
||||
if (IsSavegameVersionBefore(68)) {
|
||||
SB(ge->acceptance_pickup, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
|
||||
SB(ge->status, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
|
||||
if (GB(_waiting_acceptance, 0, 12) != 0) {
|
||||
/* In old versions, enroute_from used 0xFF as INVALID_STATION */
|
||||
StationID source = (IsSavegameVersionBefore(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
|
||||
@@ -292,8 +349,11 @@ static void Load_STNS()
|
||||
* savegame versions. As the CargoPacketPool has more than
|
||||
* 16 million entries; it fits by an order of magnitude. */
|
||||
assert(CargoPacket::CanAllocateItem());
|
||||
ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, source, _cargo_source_xy, _cargo_source_xy, _cargo_feeder_share));
|
||||
SB(ge->acceptance_pickup, GoodsEntry::GES_PICKUP, 1, 1);
|
||||
|
||||
/* Don't construct the packet with station here, because that'll fail with old savegames */
|
||||
CargoPacket *cp = new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, source, _cargo_source_xy, _cargo_source_xy, _cargo_feeder_share);
|
||||
ge->cargo.Append(cp, INVALID_STATION);
|
||||
SB(ge->status, GoodsEntry::GES_RATING, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,7 +378,9 @@ static void Ptrs_STNS()
|
||||
if (!IsSavegameVersionBefore(68)) {
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
GoodsEntry *ge = &st->goods[i];
|
||||
SwapPackets(ge);
|
||||
SlObject(ge, GetGoodsDesc());
|
||||
SwapPackets(ge);
|
||||
}
|
||||
}
|
||||
SlObject(st, _old_station_desc);
|
||||
@@ -409,7 +471,29 @@ static void RealSave_STNN(BaseStation *bst)
|
||||
if (!waypoint) {
|
||||
Station *st = Station::From(bst);
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
_num_dests = (uint32)st->goods[i].cargo.Packets()->MapSize();
|
||||
_num_flows = 0;
|
||||
for (FlowStatMap::const_iterator it(st->goods[i].flows.begin()); it != st->goods[i].flows.end(); ++it) {
|
||||
_num_flows += (uint32)it->second.GetShares()->size();
|
||||
}
|
||||
SlObject(&st->goods[i], GetGoodsDesc());
|
||||
for (FlowStatMap::const_iterator outer_it(st->goods[i].flows.begin()); outer_it != st->goods[i].flows.end(); ++outer_it) {
|
||||
const FlowStat::SharesMap *shares = outer_it->second.GetShares();
|
||||
uint32 sum_shares = 0;
|
||||
FlowSaveLoad flow;
|
||||
flow.source = outer_it->first;
|
||||
for (FlowStat::SharesMap::const_iterator inner_it(shares->begin()); inner_it != shares->end(); ++inner_it) {
|
||||
flow.via = inner_it->second;
|
||||
flow.share = inner_it->first - sum_shares;
|
||||
flow.restricted = inner_it->first > outer_it->second.GetUnrestricted();
|
||||
sum_shares = inner_it->first;
|
||||
assert(flow.share > 0);
|
||||
SlObject(&flow, _flow_desc);
|
||||
}
|
||||
}
|
||||
for (StationCargoPacketMap::ConstMapIterator it(st->goods[i].cargo.Packets()->begin()); it != st->goods[i].cargo.Packets()->end(); ++it) {
|
||||
SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), _cargo_list_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,12 +529,34 @@ static void Load_STNN()
|
||||
if (IsSavegameVersionBefore(161) && !IsSavegameVersionBefore(145) && st->facilities & FACIL_AIRPORT) {
|
||||
/* Store the old persistent storage. The GRFID will be added later. */
|
||||
assert(PersistentStorage::CanAllocateItem());
|
||||
st->airport.psa = new PersistentStorage(0);
|
||||
st->airport.psa = new PersistentStorage(0, 0, 0);
|
||||
memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(st->airport.psa->storage));
|
||||
}
|
||||
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
SlObject(&st->goods[i], GetGoodsDesc());
|
||||
FlowSaveLoad flow;
|
||||
FlowStat *fs = NULL;
|
||||
StationID prev_source = INVALID_STATION;
|
||||
for (uint32 j = 0; j < _num_flows; ++j) {
|
||||
SlObject(&flow, _flow_desc);
|
||||
if (fs == NULL || prev_source != flow.source) {
|
||||
fs = &(st->goods[i].flows.insert(std::make_pair(flow.source, FlowStat(flow.via, flow.share, flow.restricted))).first->second);
|
||||
} else {
|
||||
fs->AppendShare(flow.via, flow.share, flow.restricted);
|
||||
}
|
||||
prev_source = flow.source;
|
||||
}
|
||||
if (IsSavegameVersionBefore(183)) {
|
||||
SwapPackets(&st->goods[i]);
|
||||
} else {
|
||||
StationCargoPair pair;
|
||||
for (uint j = 0; j < _num_dests; ++j) {
|
||||
SlObject(&pair, _cargo_list_desc);
|
||||
const_cast<StationCargoPacketMap &>(*(st->goods[i].cargo.Packets()))[pair.first].swap(pair.second);
|
||||
assert(pair.second.empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,7 +579,16 @@ static void Ptrs_STNN()
|
||||
FOR_ALL_STATIONS(st) {
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
GoodsEntry *ge = &st->goods[i];
|
||||
SlObject(ge, GetGoodsDesc());
|
||||
if (IsSavegameVersionBefore(183)) {
|
||||
SwapPackets(ge);
|
||||
SlObject(ge, GetGoodsDesc());
|
||||
SwapPackets(ge);
|
||||
} else {
|
||||
SlObject(ge, GetGoodsDesc());
|
||||
for (StationCargoPacketMap::ConstMapIterator it = ge->cargo.Packets()->begin(); it != ge->cargo.Packets()->end(); ++it) {
|
||||
SlObject(const_cast<StationCargoPair *>(&(*it)), _cargo_list_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
SlObject(st, _station_desc);
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@
|
||||
#include "../newgrf_storage.h"
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Description of the data to save and load in #PersistentStorage. */
|
||||
static const SaveLoad _storage_desc[] = {
|
||||
SLE_CONDVAR(PersistentStorage, grfid, SLE_UINT32, 6, SL_MAX_VERSION),
|
||||
@@ -27,7 +29,7 @@ static void Load_PSAC()
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
assert(PersistentStorage::CanAllocateItem());
|
||||
PersistentStorage *ps = new (index) PersistentStorage(0);
|
||||
PersistentStorage *ps = new (index) PersistentStorage(0, 0, 0);
|
||||
SlObject(ps, _storage_desc);
|
||||
}
|
||||
}
|
||||
@@ -39,6 +41,7 @@ static void Save_PSAC()
|
||||
|
||||
/* Write the industries */
|
||||
FOR_ALL_STORAGES(ps) {
|
||||
ps->ClearChanges();
|
||||
SlSetArrayIndex(ps->index);
|
||||
SlObject(ps, _storage_desc);
|
||||
}
|
||||
|
107
src/saveload/story_sl.cpp
Normal file
107
src/saveload/story_sl.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* 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.
|
||||
* 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.
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/** @file story_sl.cpp Code handling saving and loading of story pages */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../story_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Called after load to trash broken pages. */
|
||||
void AfterLoadStoryBook()
|
||||
{
|
||||
if (IsSavegameVersionBefore(185)) {
|
||||
/* Trash all story pages and page elements because
|
||||
* they were saved with wrong data types.
|
||||
*/
|
||||
_story_page_element_pool.CleanPool();
|
||||
_story_page_pool.CleanPool();
|
||||
}
|
||||
}
|
||||
|
||||
static const SaveLoad _story_page_elements_desc[] = {
|
||||
SLE_CONDVAR(StoryPageElement, sort_value, SLE_FILE_U16 | SLE_VAR_U32, 0, 184),
|
||||
SLE_CONDVAR(StoryPageElement, sort_value, SLE_UINT32, 185, SL_MAX_VERSION),
|
||||
SLE_VAR(StoryPageElement, page, SLE_UINT16),
|
||||
SLE_CONDVAR(StoryPageElement, type, SLE_FILE_U16 | SLE_VAR_U8, 0, 184),
|
||||
SLE_CONDVAR(StoryPageElement, type, SLE_UINT8, 185, SL_MAX_VERSION),
|
||||
SLE_VAR(StoryPageElement, referenced_id, SLE_UINT32),
|
||||
SLE_STR(StoryPageElement, text, SLE_STR | SLF_ALLOW_CONTROL, 0),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_STORY_PAGE_ELEMENT()
|
||||
{
|
||||
StoryPageElement *s;
|
||||
FOR_ALL_STORY_PAGE_ELEMENTS(s) {
|
||||
SlSetArrayIndex(s->index);
|
||||
SlObject(s, _story_page_elements_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_STORY_PAGE_ELEMENT()
|
||||
{
|
||||
int index;
|
||||
uint32 max_sort_value = 0;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
StoryPageElement *s = new (index) StoryPageElement();
|
||||
SlObject(s, _story_page_elements_desc);
|
||||
if (s->sort_value > max_sort_value) {
|
||||
max_sort_value = s->sort_value;
|
||||
}
|
||||
}
|
||||
/* Update the next sort value, so that the next
|
||||
* created page is shown after all existing pages.
|
||||
*/
|
||||
_story_page_element_next_sort_value = max_sort_value + 1;
|
||||
}
|
||||
|
||||
static const SaveLoad _story_pages_desc[] = {
|
||||
SLE_CONDVAR(StoryPage, sort_value, SLE_FILE_U16 | SLE_VAR_U32, 0, 184),
|
||||
SLE_CONDVAR(StoryPage, sort_value, SLE_UINT32, 185, SL_MAX_VERSION),
|
||||
SLE_VAR(StoryPage, date, SLE_UINT32),
|
||||
SLE_CONDVAR(StoryPage, company, SLE_FILE_U16 | SLE_VAR_U8, 0, 184),
|
||||
SLE_CONDVAR(StoryPage, company, SLE_UINT8, 185, SL_MAX_VERSION),
|
||||
SLE_STR(StoryPage, title, SLE_STR | SLF_ALLOW_CONTROL, 0),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
static void Save_STORY_PAGE()
|
||||
{
|
||||
StoryPage *s;
|
||||
FOR_ALL_STORY_PAGES(s) {
|
||||
SlSetArrayIndex(s->index);
|
||||
SlObject(s, _story_pages_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_STORY_PAGE()
|
||||
{
|
||||
int index;
|
||||
uint32 max_sort_value = 0;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
StoryPage *s = new (index) StoryPage();
|
||||
SlObject(s, _story_pages_desc);
|
||||
if (s->sort_value > max_sort_value) {
|
||||
max_sort_value = s->sort_value;
|
||||
}
|
||||
}
|
||||
/* Update the next sort value, so that the next
|
||||
* created page is shown after all existing pages.
|
||||
*/
|
||||
_story_page_next_sort_value = max_sort_value + 1;
|
||||
}
|
||||
|
||||
extern const ChunkHandler _story_page_chunk_handlers[] = {
|
||||
{ 'STPE', Save_STORY_PAGE_ELEMENT, Load_STORY_PAGE_ELEMENT, NULL, NULL, CH_ARRAY},
|
||||
{ 'STPA', Save_STORY_PAGE, Load_STORY_PAGE, NULL, NULL, CH_ARRAY | CH_LAST},
|
||||
};
|
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const int NUM_OLD_STRINGS = 512; ///< The number of custom strings stored in old savegames.
|
||||
static const int LEN_OLD_STRINGS = 32; ///< The number of characters per string.
|
||||
static const int LEN_OLD_STRINGS_TTO = 24; ///< The number of characters per string in TTO savegames.
|
||||
@@ -92,10 +94,10 @@ char *CopyFromOldName(StringID id)
|
||||
/* Terminate the new string and copy it back to the name array */
|
||||
*strto = '\0';
|
||||
|
||||
return strdup(tmp);
|
||||
return stredup(tmp);
|
||||
} else {
|
||||
/* Name will already be in UTF-8. */
|
||||
return strdup(&_old_name_array[LEN_OLD_STRINGS * GB(id, 0, 9)]);
|
||||
return stredup(&_old_name_array[LEN_OLD_STRINGS * GB(id, 0, 9)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _subsidies_desc[] = {
|
||||
SLE_VAR(Subsidy, cargo_type, SLE_UINT8),
|
||||
SLE_VAR(Subsidy, remaining, SLE_UINT8),
|
||||
|
@@ -13,10 +13,47 @@
|
||||
#include "../newgrf_house.h"
|
||||
#include "../town.h"
|
||||
#include "../landscape.h"
|
||||
#include "../subsidy_func.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Rebuild all the cached variables of towns.
|
||||
*/
|
||||
void RebuildTownCaches()
|
||||
{
|
||||
Town *town;
|
||||
InitializeBuildingCounts();
|
||||
|
||||
/* Reset town population and num_houses */
|
||||
FOR_ALL_TOWNS(town) {
|
||||
town->cache.population = 0;
|
||||
town->cache.num_houses = 0;
|
||||
}
|
||||
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
if (!IsTileType(t, MP_HOUSE)) continue;
|
||||
|
||||
HouseID house_id = GetHouseType(t);
|
||||
town = Town::GetByTile(t);
|
||||
IncreaseBuildingCount(town, house_id);
|
||||
if (IsHouseCompleted(t)) town->cache.population += HouseSpec::Get(house_id)->population;
|
||||
|
||||
/* Increase the number of houses for every house, but only once. */
|
||||
if (GetHouseNorthPart(house_id) == 0) town->cache.num_houses++;
|
||||
}
|
||||
|
||||
/* Update the population and num_house dependent values */
|
||||
FOR_ALL_TOWNS(town) {
|
||||
UpdateTownRadius(town);
|
||||
UpdateTownCargoes(town);
|
||||
}
|
||||
UpdateTownCargoBitmap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and update town and house values.
|
||||
*
|
||||
@@ -27,15 +64,6 @@
|
||||
*/
|
||||
void UpdateHousesAndTowns()
|
||||
{
|
||||
Town *town;
|
||||
InitializeBuildingCounts();
|
||||
|
||||
/* Reset town population and num_houses */
|
||||
FOR_ALL_TOWNS(town) {
|
||||
town->population = 0;
|
||||
town->num_houses = 0;
|
||||
}
|
||||
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
if (!IsTileType(t, MP_HOUSE)) continue;
|
||||
|
||||
@@ -82,24 +110,7 @@ void UpdateHousesAndTowns()
|
||||
}
|
||||
}
|
||||
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
if (!IsTileType(t, MP_HOUSE)) continue;
|
||||
|
||||
HouseID house_id = GetCleanHouseType(t);
|
||||
town = Town::GetByTile(t);
|
||||
IncreaseBuildingCount(town, house_id);
|
||||
if (IsHouseCompleted(t)) town->population += HouseSpec::Get(house_id)->population;
|
||||
|
||||
/* Increase the number of houses for every house, but only once. */
|
||||
if (GetHouseNorthPart(house_id) == 0) town->num_houses++;
|
||||
}
|
||||
|
||||
/* Update the population and num_house dependant values */
|
||||
FOR_ALL_TOWNS(town) {
|
||||
UpdateTownRadius(town);
|
||||
UpdateTownCargoes(town);
|
||||
}
|
||||
UpdateTownCargoBitmap();
|
||||
RebuildTownCaches();
|
||||
}
|
||||
|
||||
/** Save and load of towns. */
|
||||
|
@@ -17,11 +17,16 @@
|
||||
#include "../aircraft.h"
|
||||
#include "../station_base.h"
|
||||
#include "../effectvehicle_base.h"
|
||||
#include "../company_base.h"
|
||||
#include "../company_func.h"
|
||||
#include "../disaster_vehicle.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Link front and rear multiheaded engines to each other
|
||||
* This is done when loading a savegame
|
||||
@@ -195,7 +200,8 @@ void UpdateOldAircraft()
|
||||
if (a->subtype == AIR_HELICOPTER) a->Next()->Next()->cur_speed = 32;
|
||||
|
||||
/* set new position x,y,z */
|
||||
SetAircraftPosition(a, gp.x, gp.y, GetAircraftFlyingAltitude(a));
|
||||
GetAircraftFlightLevelBounds(a, &a->z_pos, NULL);
|
||||
SetAircraftPosition(a, gp.x, gp.y, GetAircraftFlightLevel(a));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -349,6 +355,19 @@ void AfterLoadVehicles(bool part_of_load)
|
||||
v->cargo_age_counter = _age_cargo_skip_counter;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(180)) {
|
||||
/* Set service interval flags */
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (!v->IsPrimaryVehicle()) continue;
|
||||
|
||||
const Company *c = Company::Get(v->owner);
|
||||
int interval = CompanyServiceInterval(c, v->type);
|
||||
|
||||
v->SetServiceIntervalIsCustom(v->GetServiceInterval() != interval);
|
||||
v->SetServiceIntervalIsPercent(c->settings.vehicle.servint_ispercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckValidVehicles();
|
||||
@@ -361,7 +380,7 @@ void AfterLoadVehicles(bool part_of_load)
|
||||
Train *t = Train::From(v);
|
||||
if (t->IsFrontEngine() || t->IsFreeWagon()) {
|
||||
t->gcache.last_speed = t->cur_speed; // update displayed train speed
|
||||
t->ConsistChanged(false);
|
||||
t->ConsistChanged(CCF_SAVELOAD);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -442,8 +461,8 @@ void AfterLoadVehicles(bool part_of_load)
|
||||
|
||||
v->UpdateDeltaXY(v->direction);
|
||||
v->coord.left = INVALID_COORD;
|
||||
VehicleUpdatePosition(v);
|
||||
VehicleUpdateViewport(v, false);
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,7 +551,7 @@ void FixupTrainLengths()
|
||||
}
|
||||
|
||||
/* Update all cached properties after moving the vehicle chain around. */
|
||||
Train::From(v)->ConsistChanged(true);
|
||||
Train::From(v)->ConsistChanged(CCF_TRACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -589,6 +608,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
|
||||
SLE_CONDVAR(Vehicle, last_station_visited, SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
|
||||
SLE_CONDVAR(Vehicle, last_station_visited, SLE_UINT16, 5, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, last_loading_station, SLE_UINT16, 182, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Vehicle, cargo_type, SLE_UINT8),
|
||||
SLE_CONDVAR(Vehicle, cargo_subtype, SLE_UINT8, 35, SL_MAX_VERSION),
|
||||
@@ -597,8 +617,10 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
SLEG_CONDVAR( _cargo_source, SLE_UINT16, 7, 67),
|
||||
SLEG_CONDVAR( _cargo_source_xy, SLE_UINT32, 44, 67),
|
||||
SLE_VAR(Vehicle, cargo_cap, SLE_UINT16),
|
||||
SLE_CONDVAR(Vehicle, refit_cap, SLE_UINT16, 182, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR( _cargo_count, SLE_UINT16, 0, 67),
|
||||
SLE_CONDLST(Vehicle, cargo.packets, REF_CARGO_PACKET, 68, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Vehicle, cargo.action_counts, SLE_UINT, VehicleCargoList::NUM_MOVE_TO_ACTION, 181, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, cargo_age_counter, SLE_UINT16, 162, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Vehicle, day_counter, SLE_UINT8),
|
||||
@@ -623,7 +645,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
|
||||
/* Refit in current order */
|
||||
SLE_CONDVAR(Vehicle, current_order.refit_cargo, SLE_UINT8, 36, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, current_order.refit_subtype, SLE_UINT8, 36, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(1, 36, 181), // refit_subtype
|
||||
|
||||
/* Timetable in current order */
|
||||
SLE_CONDVAR(Vehicle, current_order.wait_time, SLE_UINT16, 67, SL_MAX_VERSION),
|
||||
@@ -640,8 +662,9 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
SLE_CONDVAR(Vehicle, max_age, SLE_INT32, 31, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, date_of_last_service, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
|
||||
SLE_CONDVAR(Vehicle, date_of_last_service, SLE_INT32, 31, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, service_interval, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
|
||||
SLE_CONDVAR(Vehicle, service_interval, SLE_INT32, 31, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, 0, 30),
|
||||
SLE_CONDVAR(Vehicle, service_interval, SLE_FILE_U32 | SLE_VAR_U16, 31, 179),
|
||||
SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, 180, SL_MAX_VERSION),
|
||||
SLE_VAR(Vehicle, reliability, SLE_UINT16),
|
||||
SLE_VAR(Vehicle, reliability_spd_dec, SLE_UINT16),
|
||||
SLE_VAR(Vehicle, breakdown_ctr, SLE_UINT8),
|
||||
@@ -653,7 +676,8 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
|
||||
SLE_VAR(Vehicle, load_unload_ticks, SLE_UINT16),
|
||||
SLEG_CONDVAR( _cargo_paid_for, SLE_UINT16, 45, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_UINT8, 40, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U16, 40, 179),
|
||||
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_UINT16, 180, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Vehicle, profit_this_year, SLE_FILE_I32 | SLE_VAR_I64, 0, 64),
|
||||
SLE_CONDVAR(Vehicle, profit_this_year, SLE_INT64, 65, SL_MAX_VERSION),
|
||||
@@ -817,8 +841,11 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
||||
SLE_CONDVAR(Vehicle, age, SLE_INT32, 31, SL_MAX_VERSION),
|
||||
SLE_VAR(Vehicle, tick_counter, SLE_UINT8),
|
||||
|
||||
SLE_VAR(DisasterVehicle, image_override, SLE_UINT16),
|
||||
SLE_VAR(DisasterVehicle, big_ufo_destroyer_target, SLE_UINT16),
|
||||
SLE_CONDVAR(DisasterVehicle, image_override, SLE_FILE_U16 | SLE_VAR_U32, 0, 190),
|
||||
SLE_CONDVAR(DisasterVehicle, image_override, SLE_UINT32, 191, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(DisasterVehicle, big_ufo_destroyer_target, SLE_FILE_U16 | SLE_VAR_U32, 0, 190),
|
||||
SLE_CONDVAR(DisasterVehicle, big_ufo_destroyer_target, SLE_UINT32, 191, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(DisasterVehicle, flags, SLE_UINT8, 194, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(16, 2, 143), // old reserved space
|
||||
|
||||
@@ -885,6 +912,8 @@ void Load_VEHS()
|
||||
v->last_station_visited = INVALID_STATION;
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(182)) v->last_loading_station = INVALID_STATION;
|
||||
|
||||
if (IsSavegameVersionBefore(5)) {
|
||||
/* Convert the current_order.type (which is a mix of type and flags, because
|
||||
* in those versions, they both were 4 bits big) to type and flags */
|
||||
|
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "saveload_internal.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Helper structure to convert from the old waypoint system. */
|
||||
struct OldWaypoint {
|
||||
size_t index;
|
||||
@@ -76,15 +78,16 @@ void MoveWaypointsToBaseStations()
|
||||
_m[wp->xy].m2 = (StationID)wp->index;
|
||||
|
||||
if (HasBit(_m[wp->xy].m3, 4)) {
|
||||
wp->spec = StationClass::Get(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1);
|
||||
wp->spec = StationClass::Get(STAT_CLASS_WAYP)->GetSpec(_m[wp->xy].m4 + 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* As of version 17, we recalculate the custom graphic ID of waypoints
|
||||
* from the GRF ID / station index. */
|
||||
for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
|
||||
for (uint i = 0; i < StationClass::GetCount(STAT_CLASS_WAYP); i++) {
|
||||
const StationSpec *statspec = StationClass::Get(STAT_CLASS_WAYP, i);
|
||||
StationClass* stclass = StationClass::Get(STAT_CLASS_WAYP);
|
||||
for (uint i = 0; i < stclass->GetSpecCount(); i++) {
|
||||
const StationSpec *statspec = stclass->GetSpec(i);
|
||||
if (statspec != NULL && statspec->grf_prop.grffile->grfid == wp->grfid && statspec->grf_prop.local_id == wp->localidx) {
|
||||
wp->spec = statspec;
|
||||
break;
|
||||
|
Reference in New Issue
Block a user