# town_sl.cpp

Go to the documentation of this file.

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