# town_sl.cpp

Go to the documentation of this file.

    00001 /* $Id: town_sl.cpp 20698 2010-08-30 16:52:37Z 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 "../newgrf_commons.h"
    00015 #include "../town.h"
    00016 #include "../landscape.h"
    00017
    00018 #include "saveload.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   }
    00101 }
    00102
    00104 static const SaveLoad _town_desc[] = {
    00105   SLE_CONDVAR(Town, xy,                    SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
    00106   SLE_CONDVAR(Town, xy,                    SLE_UINT32,                 6, SL_MAX_VERSION),
    00107
    00108   SLE_CONDNULL(2, 0, 2),
    00109   SLE_CONDNULL(4, 3, 84),
    00110   SLE_CONDNULL(2, 0, 91),
    00111
    00112   SLE_CONDVAR(Town, townnamegrfid,         SLE_UINT32, 66, SL_MAX_VERSION),
    00113       SLE_VAR(Town, townnametype,          SLE_UINT16),
    00114       SLE_VAR(Town, townnameparts,         SLE_UINT32),
    00115   SLE_CONDSTR(Town, name,                  SLE_STR, 0, 84, SL_MAX_VERSION),
    00116
    00117       SLE_VAR(Town, flags,                 SLE_UINT8),
    00118   SLE_CONDVAR(Town, statues,               SLE_FILE_U8  | SLE_VAR_U16, 0, 103),
    00119   SLE_CONDVAR(Town, statues,               SLE_UINT16,               104, SL_MAX_VERSION),
    00120
    00121   SLE_CONDNULL(1, 0, 1),
    00122
    00123   SLE_CONDVAR(Town, have_ratings,          SLE_FILE_U8  | SLE_VAR_U16, 0, 103),
    00124   SLE_CONDVAR(Town, have_ratings,          SLE_UINT16,               104, SL_MAX_VERSION),
    00125   SLE_CONDARR(Town, ratings,               SLE_INT16, 8,               0, 103),
    00126   SLE_CONDARR(Town, ratings,               SLE_INT16, MAX_COMPANIES, 104, SL_MAX_VERSION),
    00127   /* failed bribe attempts are stored since savegame format 4 */
    00128   SLE_CONDARR(Town, unwanted,              SLE_INT8,  8,               4, 103),
    00129   SLE_CONDARR(Town, unwanted,              SLE_INT8,  MAX_COMPANIES, 104, SL_MAX_VERSION),
    00130
    00131   SLE_CONDVAR(Town, max_pass,              SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00132   SLE_CONDVAR(Town, max_mail,              SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00133   SLE_CONDVAR(Town, new_max_pass,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00134   SLE_CONDVAR(Town, new_max_mail,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00135   SLE_CONDVAR(Town, act_pass,              SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00136   SLE_CONDVAR(Town, act_mail,              SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00137   SLE_CONDVAR(Town, new_act_pass,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00138   SLE_CONDVAR(Town, new_act_mail,          SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
    00139
    00140   SLE_CONDVAR(Town, max_pass,              SLE_UINT32,                 9, SL_MAX_VERSION),
    00141   SLE_CONDVAR(Town, max_mail,              SLE_UINT32,                 9, SL_MAX_VERSION),
    00142   SLE_CONDVAR(Town, new_max_pass,          SLE_UINT32,                 9, SL_MAX_VERSION),
    00143   SLE_CONDVAR(Town, new_max_mail,          SLE_UINT32,                 9, SL_MAX_VERSION),
    00144   SLE_CONDVAR(Town, act_pass,              SLE_UINT32,                 9, SL_MAX_VERSION),
    00145   SLE_CONDVAR(Town, act_mail,              SLE_UINT32,                 9, SL_MAX_VERSION),
    00146   SLE_CONDVAR(Town, new_act_pass,          SLE_UINT32,                 9, SL_MAX_VERSION),
    00147   SLE_CONDVAR(Town, new_act_mail,          SLE_UINT32,                 9, SL_MAX_VERSION),
    00148
    00149       SLE_VAR(Town, pct_pass_transported,  SLE_UINT8),
    00150       SLE_VAR(Town, pct_mail_transported,  SLE_UINT8),
    00151
    00152       SLE_VAR(Town, act_food,              SLE_UINT16),
    00153       SLE_VAR(Town, act_water,             SLE_UINT16),
    00154       SLE_VAR(Town, new_act_food,          SLE_UINT16),
    00155       SLE_VAR(Town, new_act_water,         SLE_UINT16),
    00156
    00157   SLE_CONDVAR(Town, time_until_rebuild,    SLE_FILE_U8 | SLE_VAR_U16,  0, 53),
    00158   SLE_CONDVAR(Town, grow_counter,          SLE_FILE_U8 | SLE_VAR_U16,  0, 53),
    00159   SLE_CONDVAR(Town, growth_rate,           SLE_FILE_U8 | SLE_VAR_I16,  0, 53),
    00160
    00161   SLE_CONDVAR(Town, time_until_rebuild,    SLE_UINT16,                54, SL_MAX_VERSION),
    00162   SLE_CONDVAR(Town, grow_counter,          SLE_UINT16,                54, SL_MAX_VERSION),
    00163   SLE_CONDVAR(Town, growth_rate,           SLE_INT16,                 54, SL_MAX_VERSION),
    00164
    00165       SLE_VAR(Town, fund_buildings_months, SLE_UINT8),
    00166       SLE_VAR(Town, road_build_months,     SLE_UINT8),
    00167
    00168   SLE_CONDVAR(Town, exclusivity,           SLE_UINT8,                  2, SL_MAX_VERSION),
    00169   SLE_CONDVAR(Town, exclusive_counter,     SLE_UINT8,                  2, SL_MAX_VERSION),
    00170
    00171   SLE_CONDVAR(Town, larger_town,           SLE_BOOL,                  56, SL_MAX_VERSION),
    00172   SLE_CONDVAR(Town, layout,                SLE_UINT8,                113, SL_MAX_VERSION),
    00173
    00174   /* reserve extra space in savegame here. (currently 30 bytes) */
    00175   SLE_CONDNULL(30, 2, SL_MAX_VERSION),
    00176
    00177   SLE_END()
    00178 };
    00179
    00180 /* Save and load the mapping between the house id on the map, and the grf file
    00181  * it came from. */
    00182 static const SaveLoad _house_id_mapping_desc[] = {
    00183   SLE_VAR(EntityIDMapping, grfid,         SLE_UINT32),
    00184   SLE_VAR(EntityIDMapping, entity_id,     SLE_UINT8),
    00185   SLE_VAR(EntityIDMapping, substitute_id, SLE_UINT8),
    00186   SLE_END()
    00187 };
    00188
    00189 static void Save_HOUSEIDS()
    00190 {
    00191   uint j = _house_mngr.GetMaxMapping();
    00192
    00193   for (uint i = 0; i < j; i++) {
    00194     SlSetArrayIndex(i);
    00195     SlObject(&_house_mngr.mapping_ID[i], _house_id_mapping_desc);
    00196   }
    00197 }
    00198
    00199 static void Load_HOUSEIDS()
    00200 {
    00201   int index;
    00202
    00203   _house_mngr.ResetMapping();
    00204   uint max_id = _house_mngr.GetMaxMapping();
    00205
    00206   while ((index = SlIterateArray()) != -1) {
    00207     if ((uint)index >= max_id) break;
    00208     SlObject(&_house_mngr.mapping_ID[index], _house_id_mapping_desc);
    00209   }
    00210 }
    00211
    00212 static void Save_TOWN()
    00213 {
    00214   Town *t;
    00215
    00216   FOR_ALL_TOWNS(t) {
    00217     SlSetArrayIndex(t->index);
    00218     SlObject(t, _town_desc);
    00219   }
    00220 }
    00221
    00222 static void Load_TOWN()
    00223 {
    00224   int index;
    00225
    00226   while ((index = SlIterateArray()) != -1) {
    00227     Town *t = new (index) Town();
    00228     SlObject(t, _town_desc);
    00229   }
    00230 }
    00231
    00232 extern const ChunkHandler _town_chunk_handlers[] = {
    00233   { 'HIDS', Save_HOUSEIDS, Load_HOUSEIDS, NULL, CH_ARRAY },
    00234   { 'CITY', Save_TOWN,     Load_TOWN,     NULL, CH_ARRAY | CH_LAST},
    00235 };