00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "../station_base.h"
00014 #include "../waypoint_base.h"
00015 #include "../roadstop_base.h"
00016 #include "../vehicle_base.h"
00017 #include "../newgrf_station.h"
00018
00019 #include "saveload.h"
00020 #include "table/strings.h"
00021
00026 static void UpdateWaypointOrder(Order *o)
00027 {
00028 if (!o->IsType(OT_GOTO_STATION)) return;
00029
00030 const Station *st = Station::Get(o->GetDestination());
00031 if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) return;
00032
00033 o->MakeGoToWaypoint(o->GetDestination());
00034 }
00035
00040 void MoveBuoysToWaypoints()
00041 {
00042
00043 OrderList *ol;
00044 FOR_ALL_ORDER_LISTS(ol) {
00045 if (ol->GetFirstSharedVehicle()->type != VEH_SHIP) continue;
00046
00047 for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o);
00048 }
00049
00050 Vehicle *v;
00051 FOR_ALL_VEHICLES(v) {
00052 if (v->type != VEH_SHIP) continue;
00053
00054 UpdateWaypointOrder(&v->current_order);
00055 }
00056
00057
00058 Station *st;
00059 FOR_ALL_STATIONS(st) {
00060 if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) continue;
00061
00062 StationID index = st->index;
00063 TileIndex xy = st->xy;
00064 Town *town = st->town;
00065 StringID string_id = st->string_id;
00066 char *name = st->name;
00067 Date build_date = st->build_date;
00068
00069
00070 delete st;
00071
00072 Waypoint *wp = new (index) Waypoint(xy);
00073 wp->town = town;
00074 wp->string_id = STR_SV_STNAME_BUOY;
00075 wp->name = name;
00076 wp->delete_ctr = 0;
00077 wp->build_date = build_date;
00078 wp->owner = OWNER_NONE;
00079
00080 if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = string_id - STR_SV_STNAME_BUOY;
00081
00082 if (IsBuoyTile(xy) && GetStationIndex(xy) == index) {
00083 wp->facilities |= FACIL_DOCK;
00084 }
00085
00086 wp->rect.BeforeAddTile(xy, StationRect::ADD_FORCE);
00087 }
00088 }
00089
00090 void AfterLoadStations()
00091 {
00092
00093 BaseStation *st;
00094 FOR_ALL_BASE_STATIONS(st) {
00095 for (uint i = 0; i < st->num_specs; i++) {
00096 if (st->speclist[i].grfid == 0) continue;
00097
00098 st->speclist[i].spec = GetCustomStationSpecByGrf(st->speclist[i].grfid, st->speclist[i].localidx, NULL);
00099 }
00100
00101 if (Station::IsExpected(st)) {
00102 Station *sta = Station::From(st);
00103 for (const RoadStop *rs = sta->bus_stops; rs != NULL; rs = rs->next) sta->bus_station.Add(rs->xy);
00104 for (const RoadStop *rs = sta->truck_stops; rs != NULL; rs = rs->next) sta->truck_station.Add(rs->xy);
00105 }
00106
00107 StationUpdateAnimTriggers(st);
00108 }
00109 }
00110
00114 void AfterLoadRoadStops()
00115 {
00116
00117 RoadStop *rs;
00118 FOR_ALL_ROADSTOPS(rs) {
00119 if (IsDriveThroughStopTile(rs->xy)) rs->MakeDriveThrough();
00120 }
00121
00122 FOR_ALL_ROADSTOPS(rs) {
00123 if (!HasBit(rs->status, RoadStop::RSSFB_BASE_ENTRY)) continue;
00124
00125 rs->GetEntry(DIAGDIR_NE)->Rebuild(rs);
00126 rs->GetEntry(DIAGDIR_NW)->Rebuild(rs);
00127 }
00128 }
00129
00130 static const SaveLoad _roadstop_desc[] = {
00131 SLE_VAR(RoadStop, xy, SLE_UINT32),
00132 SLE_CONDNULL(1, 0, 44),
00133 SLE_VAR(RoadStop, status, SLE_UINT8),
00134
00135 SLE_CONDNULL(4, 0, 8),
00136 SLE_CONDNULL(2, 0, 44),
00137 SLE_CONDNULL(1, 0, 25),
00138
00139 SLE_REF(RoadStop, next, REF_ROADSTOPS),
00140 SLE_CONDNULL(2, 0, 44),
00141
00142 SLE_CONDNULL(4, 0, 24),
00143 SLE_CONDNULL(1, 25, 25),
00144
00145 SLE_END()
00146 };
00147
00148 static const SaveLoad _old_station_desc[] = {
00149 SLE_CONDVAR(Station, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
00150 SLE_CONDVAR(Station, xy, SLE_UINT32, 6, SL_MAX_VERSION),
00151 SLE_CONDNULL(4, 0, 5),
00152 SLE_CONDVAR(Station, train_station.tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
00153 SLE_CONDVAR(Station, train_station.tile, SLE_UINT32, 6, SL_MAX_VERSION),
00154 SLE_CONDVAR(Station, airport_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
00155 SLE_CONDVAR(Station, airport_tile, SLE_UINT32, 6, SL_MAX_VERSION),
00156 SLE_CONDVAR(Station, dock_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
00157 SLE_CONDVAR(Station, dock_tile, SLE_UINT32, 6, SL_MAX_VERSION),
00158 SLE_REF(Station, town, REF_TOWN),
00159 SLE_VAR(Station, train_station.w, SLE_UINT8),
00160 SLE_CONDVAR(Station, train_station.h, SLE_UINT8, 2, SL_MAX_VERSION),
00161
00162 SLE_CONDNULL(1, 0, 3),
00163
00164 SLE_VAR(Station, string_id, SLE_STRINGID),
00165 SLE_CONDSTR(Station, name, SLE_STR, 0, 84, SL_MAX_VERSION),
00166 SLE_CONDVAR(Station, indtype, SLE_UINT8, 103, SL_MAX_VERSION),
00167 SLE_CONDVAR(Station, had_vehicle_of_type, SLE_FILE_U16 | SLE_VAR_U8, 0, 121),
00168 SLE_CONDVAR(Station, had_vehicle_of_type, SLE_UINT8, 122, SL_MAX_VERSION),
00169
00170 SLE_VAR(Station, time_since_load, SLE_UINT8),
00171 SLE_VAR(Station, time_since_unload, SLE_UINT8),
00172 SLE_VAR(Station, delete_ctr, SLE_UINT8),
00173 SLE_VAR(Station, owner, SLE_UINT8),
00174 SLE_VAR(Station, facilities, SLE_UINT8),
00175 SLE_VAR(Station, airport_type, SLE_UINT8),
00176
00177 SLE_CONDNULL(2, 0, 5),
00178 SLE_CONDNULL(1, 0, 4),
00179
00180 SLE_CONDVAR(Station, airport_flags, SLE_VAR_U64 | SLE_FILE_U16, 0, 2),
00181 SLE_CONDVAR(Station, airport_flags, SLE_VAR_U64 | SLE_FILE_U32, 3, 45),
00182 SLE_CONDVAR(Station, airport_flags, SLE_UINT64, 46, SL_MAX_VERSION),
00183
00184 SLE_CONDNULL(2, 0, 25),
00185 SLE_CONDVAR(Station, last_vehicle_type, SLE_UINT8, 26, SL_MAX_VERSION),
00186
00187 SLE_CONDNULL(2, 3, 25),
00188 SLE_CONDVAR(Station, build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30),
00189 SLE_CONDVAR(Station, build_date, SLE_INT32, 31, SL_MAX_VERSION),
00190
00191 SLE_CONDREF(Station, bus_stops, REF_ROADSTOPS, 6, SL_MAX_VERSION),
00192 SLE_CONDREF(Station, truck_stops, REF_ROADSTOPS, 6, SL_MAX_VERSION),
00193
00194
00195 SLE_CONDVAR(Station, random_bits, SLE_UINT16, 27, SL_MAX_VERSION),
00196 SLE_CONDVAR(Station, waiting_triggers, SLE_UINT8, 27, SL_MAX_VERSION),
00197 SLE_CONDVAR(Station, num_specs, SLE_UINT8, 27, SL_MAX_VERSION),
00198
00199 SLE_CONDLST(Station, loading_vehicles, REF_VEHICLE, 57, SL_MAX_VERSION),
00200
00201
00202 SLE_CONDNULL(32, 2, SL_MAX_VERSION),
00203
00204 SLE_END()
00205 };
00206
00207 static uint16 _waiting_acceptance;
00208 static uint16 _cargo_source;
00209 static uint32 _cargo_source_xy;
00210 static uint16 _cargo_days;
00211 static Money _cargo_feeder_share;
00212
00213 static const SaveLoad _station_speclist_desc[] = {
00214 SLE_CONDVAR(StationSpecList, grfid, SLE_UINT32, 27, SL_MAX_VERSION),
00215 SLE_CONDVAR(StationSpecList, localidx, SLE_UINT8, 27, SL_MAX_VERSION),
00216
00217 SLE_END()
00218 };
00219
00225 const SaveLoad *GetGoodsDesc()
00226 {
00227 static const SaveLoad goods_desc[] = {
00228 SLEG_CONDVAR( _waiting_acceptance, SLE_UINT16, 0, 67),
00229 SLE_CONDVAR(GoodsEntry, acceptance_pickup, SLE_UINT8, 68, SL_MAX_VERSION),
00230 SLE_CONDNULL(2, 51, 67),
00231 SLE_VAR(GoodsEntry, days_since_pickup, SLE_UINT8),
00232 SLE_VAR(GoodsEntry, rating, SLE_UINT8),
00233 SLEG_CONDVAR( _cargo_source, SLE_FILE_U8 | SLE_VAR_U16, 0, 6),
00234 SLEG_CONDVAR( _cargo_source, SLE_UINT16, 7, 67),
00235 SLEG_CONDVAR( _cargo_source_xy, SLE_UINT32, 44, 67),
00236 SLEG_CONDVAR( _cargo_days, SLE_UINT8, 0, 67),
00237 SLE_VAR(GoodsEntry, last_speed, SLE_UINT8),
00238 SLE_VAR(GoodsEntry, last_age, SLE_UINT8),
00239 SLEG_CONDVAR( _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
00240 SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, 65, 67),
00241 SLE_CONDLST(GoodsEntry, cargo.packets, REF_CARGO_PACKET, 68, SL_MAX_VERSION),
00242
00243 SLE_END()
00244 };
00245
00246 return goods_desc;
00247 }
00248
00249
00250 static void Load_STNS()
00251 {
00252 int index;
00253 while ((index = SlIterateArray()) != -1) {
00254 Station *st = new (index) Station();
00255
00256 SlObject(st, _old_station_desc);
00257
00258 _waiting_acceptance = 0;
00259
00260 uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
00261 for (CargoID i = 0; i < num_cargo; i++) {
00262 GoodsEntry *ge = &st->goods[i];
00263 SlObject(ge, GetGoodsDesc());
00264 if (CheckSavegameVersion(68)) {
00265 SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
00266 if (GB(_waiting_acceptance, 0, 12) != 0) {
00267
00268 StationID source = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
00269
00270
00271 ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, source, _cargo_source_xy, _cargo_source_xy, _cargo_feeder_share));
00272 SB(ge->acceptance_pickup, GoodsEntry::PICKUP, 1, 1);
00273 }
00274 }
00275 }
00276
00277 if (st->num_specs != 0) {
00278
00279 st->speclist = CallocT<StationSpecList>(st->num_specs);
00280 for (uint i = 0; i < st->num_specs; i++) {
00281 SlObject(&st->speclist[i], _station_speclist_desc);
00282 }
00283 }
00284 }
00285 }
00286
00287 static void Ptrs_STNS()
00288 {
00289
00290 if (!CheckSavegameVersion(123)) return;
00291
00292 Station *st;
00293 FOR_ALL_STATIONS(st) {
00294 if (!CheckSavegameVersion(68)) {
00295 for (CargoID i = 0; i < NUM_CARGO; i++) {
00296 GoodsEntry *ge = &st->goods[i];
00297 SlObject(ge, GetGoodsDesc());
00298 }
00299 }
00300 SlObject(st, _old_station_desc);
00301 }
00302 }
00303
00304
00305 static const SaveLoad _base_station_desc[] = {
00306 SLE_VAR(BaseStation, xy, SLE_UINT32),
00307 SLE_REF(BaseStation, town, REF_TOWN),
00308 SLE_VAR(BaseStation, string_id, SLE_STRINGID),
00309 SLE_STR(BaseStation, name, SLE_STR, 0),
00310 SLE_VAR(BaseStation, delete_ctr, SLE_UINT8),
00311 SLE_VAR(BaseStation, owner, SLE_UINT8),
00312 SLE_VAR(BaseStation, facilities, SLE_UINT8),
00313 SLE_VAR(BaseStation, build_date, SLE_INT32),
00314
00315
00316 SLE_VAR(BaseStation, random_bits, SLE_UINT16),
00317 SLE_VAR(BaseStation, waiting_triggers, SLE_UINT8),
00318 SLE_VAR(BaseStation, num_specs, SLE_UINT8),
00319
00320 SLE_END()
00321 };
00322
00323 static const SaveLoad _station_desc[] = {
00324 SLE_WRITEBYTE(Station, facilities, FACIL_NONE),
00325 SLE_ST_INCLUDE(),
00326
00327 SLE_VAR(Station, train_station.tile, SLE_UINT32),
00328 SLE_VAR(Station, train_station.w, SLE_UINT8),
00329 SLE_VAR(Station, train_station.h, SLE_UINT8),
00330
00331 SLE_REF(Station, bus_stops, REF_ROADSTOPS),
00332 SLE_REF(Station, truck_stops, REF_ROADSTOPS),
00333 SLE_VAR(Station, dock_tile, SLE_UINT32),
00334 SLE_VAR(Station, airport_tile, SLE_UINT32),
00335 SLE_VAR(Station, airport_type, SLE_UINT8),
00336 SLE_VAR(Station, airport_flags, SLE_UINT64),
00337
00338 SLE_VAR(Station, indtype, SLE_UINT8),
00339
00340 SLE_VAR(Station, time_since_load, SLE_UINT8),
00341 SLE_VAR(Station, time_since_unload, SLE_UINT8),
00342 SLE_VAR(Station, last_vehicle_type, SLE_UINT8),
00343 SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8),
00344 SLE_LST(Station, loading_vehicles, REF_VEHICLE),
00345 SLE_CONDVAR(Station, always_accepted, SLE_UINT32, 127, SL_MAX_VERSION),
00346
00347 SLE_END()
00348 };
00349
00350 static const SaveLoad _waypoint_desc[] = {
00351 SLE_WRITEBYTE(Waypoint, facilities, FACIL_WAYPOINT),
00352 SLE_ST_INCLUDE(),
00353
00354 SLE_VAR(Waypoint, town_cn, SLE_UINT16),
00355
00356 SLE_CONDVAR(Waypoint, train_station.tile, SLE_UINT32, 124, SL_MAX_VERSION),
00357 SLE_CONDVAR(Waypoint, train_station.w, SLE_UINT8, 124, SL_MAX_VERSION),
00358 SLE_CONDVAR(Waypoint, train_station.h, SLE_UINT8, 124, SL_MAX_VERSION),
00359
00360 SLE_END()
00361 };
00362
00367 const SaveLoad *GetBaseStationDescription()
00368 {
00369 return _base_station_desc;
00370 }
00371
00372 static void RealSave_STNN(BaseStation *bst)
00373 {
00374 bool waypoint = (bst->facilities & FACIL_WAYPOINT) != 0;
00375 SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
00376
00377 if (!waypoint) {
00378 Station *st = Station::From(bst);
00379 for (CargoID i = 0; i < NUM_CARGO; i++) {
00380 SlObject(&st->goods[i], GetGoodsDesc());
00381 }
00382 }
00383
00384 for (uint i = 0; i < bst->num_specs; i++) {
00385 SlObject(&bst->speclist[i], _station_speclist_desc);
00386 }
00387 }
00388
00389 static void Save_STNN()
00390 {
00391 BaseStation *st;
00392
00393 FOR_ALL_BASE_STATIONS(st) {
00394 SlSetArrayIndex(st->index);
00395 SlAutolength((AutolengthProc*)RealSave_STNN, st);
00396 }
00397 }
00398
00399 static void Load_STNN()
00400 {
00401 int index;
00402
00403 while ((index = SlIterateArray()) != -1) {
00404 bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
00405
00406 BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
00407 SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
00408
00409 if (!waypoint) {
00410 Station *st = Station::From(bst);
00411 for (CargoID i = 0; i < NUM_CARGO; i++) {
00412 SlObject(&st->goods[i], GetGoodsDesc());
00413 }
00414 }
00415
00416 if (bst->num_specs != 0) {
00417
00418 bst->speclist = CallocT<StationSpecList>(bst->num_specs);
00419 for (uint i = 0; i < bst->num_specs; i++) {
00420 SlObject(&bst->speclist[i], _station_speclist_desc);
00421 }
00422 }
00423 }
00424 }
00425
00426 static void Ptrs_STNN()
00427 {
00428
00429 if (CheckSavegameVersion(123)) return;
00430
00431 Station *st;
00432 FOR_ALL_STATIONS(st) {
00433 for (CargoID i = 0; i < NUM_CARGO; i++) {
00434 GoodsEntry *ge = &st->goods[i];
00435 SlObject(ge, GetGoodsDesc());
00436 }
00437 SlObject(st, _station_desc);
00438 }
00439
00440 Waypoint *wp;
00441 FOR_ALL_WAYPOINTS(wp) {
00442 SlObject(wp, _waypoint_desc);
00443 }
00444 }
00445
00446 static void Save_ROADSTOP()
00447 {
00448 RoadStop *rs;
00449
00450 FOR_ALL_ROADSTOPS(rs) {
00451 SlSetArrayIndex(rs->index);
00452 SlObject(rs, _roadstop_desc);
00453 }
00454 }
00455
00456 static void Load_ROADSTOP()
00457 {
00458 int index;
00459
00460 while ((index = SlIterateArray()) != -1) {
00461 RoadStop *rs = new (index) RoadStop(INVALID_TILE);
00462
00463 SlObject(rs, _roadstop_desc);
00464 }
00465 }
00466
00467 static void Ptrs_ROADSTOP()
00468 {
00469 RoadStop *rs;
00470 FOR_ALL_ROADSTOPS(rs) {
00471 SlObject(rs, _roadstop_desc);
00472 }
00473 }
00474
00475 extern const ChunkHandler _station_chunk_handlers[] = {
00476 { 'STNS', NULL, Load_STNS, Ptrs_STNS, CH_ARRAY },
00477 { 'STNN', Save_STNN, Load_STNN, Ptrs_STNN, CH_ARRAY },
00478 { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, CH_ARRAY | CH_LAST},
00479 };