town_sl.cpp

Go to the documentation of this file.
00001 /* $Id$ */
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 "../newgrf_house.h"
00014 #include "../town.h"
00015 #include "../landscape.h"
00016 #include "../subsidy_func.h"
00017 
00018 #include "saveload.h"
00019 #include "newgrf_sl.h"
00020 
00024 void RebuildTownCaches()
00025 {
00026   Town *town;
00027   InitializeBuildingCounts();
00028 
00029   /* Reset town population and num_houses */
00030   FOR_ALL_TOWNS(town) {
00031     town->cache.population = 0;
00032     town->cache.num_houses = 0;
00033   }
00034 
00035   for (TileIndex t = 0; t < MapSize(); t++) {
00036     if (!IsTileType(t, MP_HOUSE)) continue;
00037 
00038     HouseID house_id = GetHouseType(t);
00039     town = Town::GetByTile(t);
00040     IncreaseBuildingCount(town, house_id);
00041     if (IsHouseCompleted(t)) town->cache.population += HouseSpec::Get(house_id)->population;
00042 
00043     /* Increase the number of houses for every house, but only once. */
00044     if (GetHouseNorthPart(house_id) == 0) town->cache.num_houses++;
00045   }
00046 
00047   /* Update the population and num_house dependant values */
00048   FOR_ALL_TOWNS(town) {
00049     UpdateTownRadius(town);
00050     UpdateTownCargoes(town);
00051   }
00052   UpdateTownCargoBitmap();
00053 }
00054 
00063 void UpdateHousesAndTowns()
00064 {
00065   for (TileIndex t = 0; t < MapSize(); t++) {
00066     if (!IsTileType(t, MP_HOUSE)) continue;
00067 
00068     HouseID house_id = GetCleanHouseType(t);
00069     if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
00070       /* The specs for this type of house are not available any more, so
00071        * replace it with the substitute original house type. */
00072       house_id = _house_mngr.GetSubstituteID(house_id);
00073       SetHouseType(t, house_id);
00074     }
00075   }
00076 
00077   /* Check for cases when a NewGRF has set a wrong house substitute type. */
00078   for (TileIndex t = 0; t < MapSize(); t++) {
00079     if (!IsTileType(t, MP_HOUSE)) continue;
00080 
00081     HouseID house_type = GetCleanHouseType(t);
00082     TileIndex north_tile = t + GetHouseNorthPart(house_type); // modifies 'house_type'!
00083     if (t == north_tile) {
00084       const HouseSpec *hs = HouseSpec::Get(house_type);
00085       bool valid_house = true;
00086       if (hs->building_flags & TILE_SIZE_2x1) {
00087         TileIndex tile = t + TileDiffXY(1, 0);
00088         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
00089       } else if (hs->building_flags & TILE_SIZE_1x2) {
00090         TileIndex tile = t + TileDiffXY(0, 1);
00091         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
00092       } else if (hs->building_flags & TILE_SIZE_2x2) {
00093         TileIndex tile = t + TileDiffXY(0, 1);
00094         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
00095         tile = t + TileDiffXY(1, 0);
00096         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 2) valid_house = false;
00097         tile = t + TileDiffXY(1, 1);
00098         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 3) valid_house = false;
00099       }
00100       /* If not all tiles of this house are present remove the house.
00101        * The other tiles will get removed later in this loop because
00102        * their north tile is not the correct type anymore. */
00103       if (!valid_house) DoClearSquare(t);
00104     } else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) {
00105       /* This tile should be part of a multi-tile building but the
00106        * north tile of this house isn't on the map. */
00107       DoClearSquare(t);
00108     }
00109   }
00110 
00111   RebuildTownCaches();
00112 }
00113 
00115 static const SaveLoad _town_desc[] = {
00116   SLE_CONDVAR(Town, xy,                    SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
00117   SLE_CONDVAR(Town, xy,                    SLE_UINT32,                 6, SL_MAX_VERSION),
00118 
00119   SLE_CONDNULL(2, 0, 2),                   
00120   SLE_CONDNULL(4, 3, 84),                  
00121   SLE_CONDNULL(2, 0, 91),                  
00122 
00123   SLE_CONDVAR(Town, townnamegrfid,         SLE_UINT32, 66, SL_MAX_VERSION),
00124       SLE_VAR(Town, townnametype,          SLE_UINT16),
00125       SLE_VAR(Town, townnameparts,         SLE_UINT32),
00126   SLE_CONDSTR(Town, name,                  SLE_STR | SLF_ALLOW_CONTROL, 0, 84, SL_MAX_VERSION),
00127 
00128       SLE_VAR(Town, flags,                 SLE_UINT8),
00129   SLE_CONDVAR(Town, statues,               SLE_FILE_U8  | SLE_VAR_U16, 0, 103),
00130   SLE_CONDVAR(Town, statues,               SLE_UINT16,               104, SL_MAX_VERSION),
00131 
00132   SLE_CONDNULL(1, 0, 1),                   
00133 
00134   SLE_CONDVAR(Town, have_ratings,          SLE_FILE_U8  | SLE_VAR_U16, 0, 103),
00135   SLE_CONDVAR(Town, have_ratings,          SLE_UINT16,               104, SL_MAX_VERSION),
00136   SLE_CONDARR(Town, ratings,               SLE_INT16, 8,               0, 103),
00137   SLE_CONDARR(Town, ratings,               SLE_INT16, MAX_COMPANIES, 104, SL_MAX_VERSION),
00138   /* failed bribe attempts are stored since savegame format 4 */
00139   SLE_CONDARR(Town, unwanted,              SLE_INT8,  8,               4, 103),
00140   SLE_CONDARR(Town, unwanted,              SLE_INT8,  MAX_COMPANIES, 104, SL_MAX_VERSION),
00141 
00142   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00143   SLE_CONDVAR(Town, supplied[CT_MAIL].old_max,       SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00144   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00145   SLE_CONDVAR(Town, supplied[CT_MAIL].new_max,       SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00146   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00147   SLE_CONDVAR(Town, supplied[CT_MAIL].old_act,       SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00148   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00149   SLE_CONDVAR(Town, supplied[CT_MAIL].new_act,       SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00150 
00151   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_UINT32,                 9, 164),
00152   SLE_CONDVAR(Town, supplied[CT_MAIL].old_max,       SLE_UINT32,                 9, 164),
00153   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_UINT32,                 9, 164),
00154   SLE_CONDVAR(Town, supplied[CT_MAIL].new_max,       SLE_UINT32,                 9, 164),
00155   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_UINT32,                 9, 164),
00156   SLE_CONDVAR(Town, supplied[CT_MAIL].old_act,       SLE_UINT32,                 9, 164),
00157   SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_UINT32,                 9, 164),
00158   SLE_CONDVAR(Town, supplied[CT_MAIL].new_act,       SLE_UINT32,                 9, 164),
00159 
00160   SLE_CONDNULL(2, 0, 163),                 
00161 
00162   SLE_CONDVAR(Town, received[TE_FOOD].old_act,       SLE_UINT16,                 0, 164),
00163   SLE_CONDVAR(Town, received[TE_WATER].old_act,      SLE_UINT16,                 0, 164),
00164   SLE_CONDVAR(Town, received[TE_FOOD].new_act,       SLE_UINT16,                 0, 164),
00165   SLE_CONDVAR(Town, received[TE_WATER].new_act,      SLE_UINT16,                 0, 164),
00166 
00167   SLE_CONDARR(Town, goal, SLE_UINT32, NUM_TE, 165, SL_MAX_VERSION),
00168 
00169   SLE_CONDSTR(Town, text,                  SLE_STR | SLF_ALLOW_CONTROL, 0, 168, SL_MAX_VERSION),
00170 
00171   SLE_CONDVAR(Town, time_until_rebuild,    SLE_FILE_U8 | SLE_VAR_U16,  0, 53),
00172   SLE_CONDVAR(Town, grow_counter,          SLE_FILE_U8 | SLE_VAR_U16,  0, 53),
00173   SLE_CONDVAR(Town, growth_rate,           SLE_FILE_U8 | SLE_VAR_I16,  0, 53),
00174 
00175   SLE_CONDVAR(Town, time_until_rebuild,    SLE_UINT16,                54, SL_MAX_VERSION),
00176   SLE_CONDVAR(Town, grow_counter,          SLE_UINT16,                54, SL_MAX_VERSION),
00177 
00178   SLE_CONDVAR(Town, growth_rate,           SLE_FILE_I16 | SLE_VAR_U16, 54, 164),
00179   SLE_CONDVAR(Town, growth_rate,           SLE_UINT16,                 165, SL_MAX_VERSION),
00180 
00181       SLE_VAR(Town, fund_buildings_months, SLE_UINT8),
00182       SLE_VAR(Town, road_build_months,     SLE_UINT8),
00183 
00184   SLE_CONDVAR(Town, exclusivity,           SLE_UINT8,                  2, SL_MAX_VERSION),
00185   SLE_CONDVAR(Town, exclusive_counter,     SLE_UINT8,                  2, SL_MAX_VERSION),
00186 
00187   SLE_CONDVAR(Town, larger_town,           SLE_BOOL,                  56, SL_MAX_VERSION),
00188   SLE_CONDVAR(Town, layout,                SLE_UINT8,                113, SL_MAX_VERSION),
00189 
00190   SLE_CONDLST(Town, psa_list,            REF_STORAGE,                161, SL_MAX_VERSION),
00191 
00192   SLE_CONDVAR(Town, cargo_produced,       SLE_UINT32,                166, SL_MAX_VERSION),
00193 
00194   /* reserve extra space in savegame here. (currently 30 bytes) */
00195   SLE_CONDNULL(30, 2, SL_MAX_VERSION),
00196 
00197   SLE_END()
00198 };
00199 
00200 static const SaveLoad _town_supplied_desc[] = {
00201   SLE_CONDVAR(TransportedCargoStat<uint32>, old_max, SLE_UINT32, 165, SL_MAX_VERSION),
00202   SLE_CONDVAR(TransportedCargoStat<uint32>, new_max, SLE_UINT32, 165, SL_MAX_VERSION),
00203   SLE_CONDVAR(TransportedCargoStat<uint32>, old_act, SLE_UINT32, 165, SL_MAX_VERSION),
00204   SLE_CONDVAR(TransportedCargoStat<uint32>, new_act, SLE_UINT32, 165, SL_MAX_VERSION),
00205 
00206   SLE_END()
00207 };
00208 
00209 static const SaveLoad _town_received_desc[] = {
00210   SLE_CONDVAR(TransportedCargoStat<uint16>, old_max, SLE_UINT16, 165, SL_MAX_VERSION),
00211   SLE_CONDVAR(TransportedCargoStat<uint16>, new_max, SLE_UINT16, 165, SL_MAX_VERSION),
00212   SLE_CONDVAR(TransportedCargoStat<uint16>, old_act, SLE_UINT16, 165, SL_MAX_VERSION),
00213   SLE_CONDVAR(TransportedCargoStat<uint16>, new_act, SLE_UINT16, 165, SL_MAX_VERSION),
00214 
00215   SLE_END()
00216 };
00217 
00218 static void Save_HIDS()
00219 {
00220   Save_NewGRFMapping(_house_mngr);
00221 }
00222 
00223 static void Load_HIDS()
00224 {
00225   Load_NewGRFMapping(_house_mngr);
00226 }
00227 
00228 const SaveLoad *GetTileMatrixDesc()
00229 {
00230   /* Here due to private member vars. */
00231   static const SaveLoad _tilematrix_desc[] = {
00232     SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
00233     SLE_VAR(AcceptanceMatrix, area.w,    SLE_UINT16),
00234     SLE_VAR(AcceptanceMatrix, area.h,    SLE_UINT16),
00235     SLE_END()
00236   };
00237 
00238   return _tilematrix_desc;
00239 }
00240 
00241 static void RealSave_Town(Town *t)
00242 {
00243   SlObject(t, _town_desc);
00244 
00245   for (CargoID i = 0; i < NUM_CARGO; i++) {
00246     SlObject(&t->supplied[i], _town_supplied_desc);
00247   }
00248   for (int i = TE_BEGIN; i < NUM_TE; i++) {
00249     SlObject(&t->received[i], _town_received_desc);
00250   }
00251 
00252   if (IsSavegameVersionBefore(166)) return;
00253 
00254   SlObject(&t->cargo_accepted, GetTileMatrixDesc());
00255   if (t->cargo_accepted.area.w != 0) {
00256     uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
00257     SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32);
00258   }
00259 }
00260 
00261 static void Save_TOWN()
00262 {
00263   Town *t;
00264 
00265   FOR_ALL_TOWNS(t) {
00266     SlSetArrayIndex(t->index);
00267     SlAutolength((AutolengthProc*)RealSave_Town, t);
00268   }
00269 }
00270 
00271 static void Load_TOWN()
00272 {
00273   int index;
00274 
00275   while ((index = SlIterateArray()) != -1) {
00276     Town *t = new (index) Town();
00277     SlObject(t, _town_desc);
00278 
00279     for (CargoID i = 0; i < NUM_CARGO; i++) {
00280       SlObject(&t->supplied[i], _town_supplied_desc);
00281     }
00282     for (int i = TE_BEGIN; i < TE_END; i++) {
00283       SlObject(&t->received[i], _town_received_desc);
00284     }
00285 
00286     if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GB(t->townnametype, 11, 5) != 15) {
00287       SlErrorCorrupt("Invalid town name generator");
00288     }
00289 
00290     if (IsSavegameVersionBefore(166)) continue;
00291 
00292     SlObject(&t->cargo_accepted, GetTileMatrixDesc());
00293     if (t->cargo_accepted.area.w != 0) {
00294       uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
00295       t->cargo_accepted.data = MallocT<uint32>(arr_len);
00296       SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32);
00297 
00298       /* Rebuild total cargo acceptance. */
00299       UpdateTownCargoTotal(t);
00300     }
00301   }
00302 }
00303 
00305 static void Ptrs_TOWN()
00306 {
00307   /* Don't run when savegame version lower than 161. */
00308   if (IsSavegameVersionBefore(161)) return;
00309 
00310   Town *t;
00311   FOR_ALL_TOWNS(t) {
00312     SlObject(t, _town_desc);
00313   }
00314 }
00315 
00317 extern const ChunkHandler _town_chunk_handlers[] = {
00318   { 'HIDS', Save_HIDS, Load_HIDS,      NULL, NULL, CH_ARRAY },
00319   { 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, NULL, CH_ARRAY | CH_LAST},
00320 };