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 
00017 #include "saveload.h"
00018 #include "newgrf_sl.h"
00019 
00028 void UpdateHousesAndTowns()
00029 {
00030   Town *town;
00031   InitializeBuildingCounts();
00032 
00033   /* Reset town population and num_houses */
00034   FOR_ALL_TOWNS(town) {
00035     town->population = 0;
00036     town->num_houses = 0;
00037   }
00038 
00039   for (TileIndex t = 0; t < MapSize(); t++) {
00040     if (!IsTileType(t, MP_HOUSE)) continue;
00041 
00042     HouseID house_id = GetCleanHouseType(t);
00043     if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
00044       /* The specs for this type of house are not available any more, so
00045        * replace it with the substitute original house type. */
00046       house_id = _house_mngr.GetSubstituteID(house_id);
00047       SetHouseType(t, house_id);
00048     }
00049   }
00050 
00051   /* Check for cases when a NewGRF has set a wrong house substitute type. */
00052   for (TileIndex t = 0; t < MapSize(); t++) {
00053     if (!IsTileType(t, MP_HOUSE)) continue;
00054 
00055     HouseID house_type = GetCleanHouseType(t);
00056     TileIndex north_tile = t + GetHouseNorthPart(house_type); // modifies 'house_type'!
00057     if (t == north_tile) {
00058       const HouseSpec *hs = HouseSpec::Get(house_type);
00059       bool valid_house = true;
00060       if (hs->building_flags & TILE_SIZE_2x1) {
00061         TileIndex tile = t + TileDiffXY(1, 0);
00062         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
00063       } else if (hs->building_flags & TILE_SIZE_1x2) {
00064         TileIndex tile = t + TileDiffXY(0, 1);
00065         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
00066       } else if (hs->building_flags & TILE_SIZE_2x2) {
00067         TileIndex tile = t + TileDiffXY(0, 1);
00068         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
00069         tile = t + TileDiffXY(1, 0);
00070         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 2) valid_house = false;
00071         tile = t + TileDiffXY(1, 1);
00072         if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 3) valid_house = false;
00073       }
00074       /* If not all tiles of this house are present remove the house.
00075        * The other tiles will get removed later in this loop because
00076        * their north tile is not the correct type anymore. */
00077       if (!valid_house) DoClearSquare(t);
00078     } else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) {
00079       /* This tile should be part of a multi-tile building but the
00080        * north tile of this house isn't on the map. */
00081       DoClearSquare(t);
00082     }
00083   }
00084 
00085   for (TileIndex t = 0; t < MapSize(); t++) {
00086     if (!IsTileType(t, MP_HOUSE)) continue;
00087 
00088     HouseID house_id = GetCleanHouseType(t);
00089     town = Town::GetByTile(t);
00090     IncreaseBuildingCount(town, house_id);
00091     if (IsHouseCompleted(t)) town->population += HouseSpec::Get(house_id)->population;
00092 
00093     /* Increase the number of houses for every house, but only once. */
00094     if (GetHouseNorthPart(house_id) == 0) town->num_houses++;
00095   }
00096 
00097   /* Update the population and num_house dependant values */
00098   FOR_ALL_TOWNS(town) {
00099     UpdateTownRadius(town);
00100     UpdateTownCargos(town);
00101   }
00102 }
00103 
00105 static const SaveLoad _town_desc[] = {
00106   SLE_CONDVAR(Town, xy,                    SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
00107   SLE_CONDVAR(Town, xy,                    SLE_UINT32,                 6, SL_MAX_VERSION),
00108 
00109   SLE_CONDNULL(2, 0, 2),                   
00110   SLE_CONDNULL(4, 3, 84),                  
00111   SLE_CONDNULL(2, 0, 91),                  
00112 
00113   SLE_CONDVAR(Town, townnamegrfid,         SLE_UINT32, 66, SL_MAX_VERSION),
00114       SLE_VAR(Town, townnametype,          SLE_UINT16),
00115       SLE_VAR(Town, townnameparts,         SLE_UINT32),
00116   SLE_CONDSTR(Town, name,                  SLE_STR, 0, 84, SL_MAX_VERSION),
00117 
00118       SLE_VAR(Town, flags,                 SLE_UINT8),
00119   SLE_CONDVAR(Town, statues,               SLE_FILE_U8  | SLE_VAR_U16, 0, 103),
00120   SLE_CONDVAR(Town, statues,               SLE_UINT16,               104, SL_MAX_VERSION),
00121 
00122   SLE_CONDNULL(1, 0, 1),                   
00123 
00124   SLE_CONDVAR(Town, have_ratings,          SLE_FILE_U8  | SLE_VAR_U16, 0, 103),
00125   SLE_CONDVAR(Town, have_ratings,          SLE_UINT16,               104, SL_MAX_VERSION),
00126   SLE_CONDARR(Town, ratings,               SLE_INT16, 8,               0, 103),
00127   SLE_CONDARR(Town, ratings,               SLE_INT16, MAX_COMPANIES, 104, SL_MAX_VERSION),
00128   /* failed bribe attempts are stored since savegame format 4 */
00129   SLE_CONDARR(Town, unwanted,              SLE_INT8,  8,               4, 103),
00130   SLE_CONDARR(Town, unwanted,              SLE_INT8,  MAX_COMPANIES, 104, SL_MAX_VERSION),
00131 
00132   SLE_CONDVAR(Town, pass.old_max,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00133   SLE_CONDVAR(Town, mail.old_max,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00134   SLE_CONDVAR(Town, pass.new_max,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00135   SLE_CONDVAR(Town, mail.new_max,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00136   SLE_CONDVAR(Town, pass.old_act,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00137   SLE_CONDVAR(Town, mail.old_act,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00138   SLE_CONDVAR(Town, pass.new_act,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00139   SLE_CONDVAR(Town, mail.new_act,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
00140 
00141   SLE_CONDVAR(Town, pass.old_max,          SLE_UINT32,                 9, SL_MAX_VERSION),
00142   SLE_CONDVAR(Town, mail.old_max,          SLE_UINT32,                 9, SL_MAX_VERSION),
00143   SLE_CONDVAR(Town, pass.new_max,          SLE_UINT32,                 9, SL_MAX_VERSION),
00144   SLE_CONDVAR(Town, mail.new_max,          SLE_UINT32,                 9, SL_MAX_VERSION),
00145   SLE_CONDVAR(Town, pass.old_act,          SLE_UINT32,                 9, SL_MAX_VERSION),
00146   SLE_CONDVAR(Town, mail.old_act,          SLE_UINT32,                 9, SL_MAX_VERSION),
00147   SLE_CONDVAR(Town, pass.new_act,          SLE_UINT32,                 9, SL_MAX_VERSION),
00148   SLE_CONDVAR(Town, mail.new_act,          SLE_UINT32,                 9, SL_MAX_VERSION),
00149 
00150       SLE_VAR(Town, pct_pass_transported,  SLE_UINT8),
00151       SLE_VAR(Town, pct_mail_transported,  SLE_UINT8),
00152 
00153       SLE_VAR(Town, act_food,              SLE_UINT16),
00154       SLE_VAR(Town, act_water,             SLE_UINT16),
00155       SLE_VAR(Town, new_act_food,          SLE_UINT16),
00156       SLE_VAR(Town, new_act_water,         SLE_UINT16),
00157 
00158   SLE_CONDVAR(Town, time_until_rebuild,    SLE_FILE_U8 | SLE_VAR_U16,  0, 53),
00159   SLE_CONDVAR(Town, grow_counter,          SLE_FILE_U8 | SLE_VAR_U16,  0, 53),
00160   SLE_CONDVAR(Town, growth_rate,           SLE_FILE_U8 | SLE_VAR_I16,  0, 53),
00161 
00162   SLE_CONDVAR(Town, time_until_rebuild,    SLE_UINT16,                54, SL_MAX_VERSION),
00163   SLE_CONDVAR(Town, grow_counter,          SLE_UINT16,                54, SL_MAX_VERSION),
00164   SLE_CONDVAR(Town, growth_rate,           SLE_INT16,                 54, SL_MAX_VERSION),
00165 
00166       SLE_VAR(Town, fund_buildings_months, SLE_UINT8),
00167       SLE_VAR(Town, road_build_months,     SLE_UINT8),
00168 
00169   SLE_CONDVAR(Town, exclusivity,           SLE_UINT8,                  2, SL_MAX_VERSION),
00170   SLE_CONDVAR(Town, exclusive_counter,     SLE_UINT8,                  2, SL_MAX_VERSION),
00171 
00172   SLE_CONDVAR(Town, larger_town,           SLE_BOOL,                  56, SL_MAX_VERSION),
00173   SLE_CONDVAR(Town, layout,                SLE_UINT8,                113, SL_MAX_VERSION),
00174 
00175   SLE_CONDVAR(Town, cargo_produced,        SLE_UINT32,               161, SL_MAX_VERSION),
00176 
00177   /* reserve extra space in savegame here. (currently 30 bytes) */
00178   SLE_CONDNULL(30, 2, SL_MAX_VERSION),
00179 
00180   SLE_END()
00181 };
00182 
00183 static void Save_HIDS()
00184 {
00185   Save_NewGRFMapping(_house_mngr);
00186 }
00187 
00188 static void Load_HIDS()
00189 {
00190   Load_NewGRFMapping(_house_mngr);
00191 }
00192 
00193 const SaveLoad *GetTileMatrixDesc()
00194 {
00195   /* Here due to private member vars. */
00196   static const SaveLoad _tilematrix_desc[] = {
00197     SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
00198     SLE_VAR(AcceptanceMatrix, area.w,    SLE_UINT16),
00199     SLE_VAR(AcceptanceMatrix, area.h,    SLE_UINT16),
00200     SLE_END()
00201   };
00202 
00203   return _tilematrix_desc;
00204 }
00205 
00206 void RealSave_TOWN(Town *t)
00207 {
00208   SlObject(t, _town_desc);
00209   t->SaveCargoSourceSink();
00210 
00211   if (IsSavegameVersionBefore(161)) return;
00212 
00213   SlObject(&t->cargo_accepted, GetTileMatrixDesc());
00214   if (t->cargo_accepted.area.w != 0) {
00215     uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
00216     SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32);
00217   }
00218 }
00219 
00220 static void Save_TOWN()
00221 {
00222   Town *t;
00223 
00224   FOR_ALL_TOWNS(t) {
00225     SlSetArrayIndex(t->index);
00226     SlAutolength((AutolengthProc *)RealSave_TOWN, t);
00227   }
00228 }
00229 
00230 void Load_TOWN()
00231 {
00232   int index;
00233 
00234   while ((index = SlIterateArray()) != -1) {
00235     Town *t = new (index) Town();
00236     SlObject(t, _town_desc);
00237     t->LoadCargoSourceSink();
00238 
00239     if (IsSavegameVersionBefore(161)) continue;
00240 
00241     SlObject(&t->cargo_accepted, GetTileMatrixDesc());
00242     if (t->cargo_accepted.area.w != 0) {
00243       uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
00244       t->cargo_accepted.data = MallocT<uint32>(arr_len);
00245       SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32);
00246 
00247       /* Rebuild total cargo acceptance. */
00248       UpdateTownCargoTotal(t);
00249     }
00250 
00251     /* Cache the aligned tile index of the centre tile. */
00252     uint town_x = (TileX(t->xy) / AcceptanceMatrix::GRID) * AcceptanceMatrix::GRID;
00253     uint town_y = (TileY(t->xy) / AcceptanceMatrix::GRID) * AcceptanceMatrix::GRID;
00254     t->xy_aligned= TileXY(town_x, town_y);
00255   }
00256 }
00257 
00258 static void Ptrs_TOWN()
00259 {
00260   Town *t;
00261 
00262   FOR_ALL_TOWNS(t) {
00263     t->PtrsCargoSourceSink();
00264   }
00265 }
00266 
00267 extern const ChunkHandler _town_chunk_handlers[] = {
00268   { 'HIDS', Save_HIDS, Load_HIDS, NULL,      NULL, CH_ARRAY },
00269   { 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, NULL, CH_ARRAY | CH_LAST},
00270 };

Generated on Sun May 8 07:30:18 2011 for OpenTTD by  doxygen 1.6.1