station_sl.cpp

Go to the documentation of this file.
00001 /* $Id: station_sl.cpp 21795 2011-01-14 20:52:22Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
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   /* Buoy orders become waypoint orders */
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   /* Now make the stations waypoints */
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     /* TTDPatch could use "buoys with rail station" for rail waypoints */
00072     bool train         = st->train_station.tile != INVALID_TILE;
00073     TileArea train_st  = st->train_station;
00074 
00075     /* Delete the station, so we can make it a real waypoint. */
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; // Just reset delete counter for once.
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       /* When we make a rail waypoint of the station, convert the map as well. */
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   /* Update the speclists of all stations to point to the currently loaded custom stations. */
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   /* First construct the drive through entries */
00133   RoadStop *rs;
00134   FOR_ALL_ROADSTOPS(rs) {
00135     if (IsDriveThroughStopTile(rs->xy)) rs->MakeDriveThrough();
00136   }
00137   /* And then rebuild the data in those entries */
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   /* Index was saved in some versions, but this is not needed */
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   /* Used by newstations for graphic variations */
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   /* reserve extra space in savegame here. (currently 32 bytes) */
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           /* In old versions, enroute_from used 0xFF as INVALID_STATION */
00285           StationID source = (IsSavegameVersionBefore(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
00286 
00287           /* Don't construct the packet with station here, because that'll fail with old savegames */
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       /* Allocate speclist memory when loading a game */
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   /* Don't run when savegame version is higher than or equal to 123. */
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   /* Used by newstations for graphic variations */
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   /* Write the stations */
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       /* Allocate speclist memory when loading a game */
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   /* Don't run when savegame version lower than 123. */
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 };

Generated on Thu Jan 20 22:57:39 2011 for OpenTTD by  doxygen 1.6.1