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