summaryrefslogtreecommitdiff
path: root/src/saveload/town_sl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/saveload/town_sl.cpp')
-rw-r--r--src/saveload/town_sl.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp
new file mode 100644
index 000000000..eaa3edaa3
--- /dev/null
+++ b/src/saveload/town_sl.cpp
@@ -0,0 +1,210 @@
+/* $Id$ */
+
+/** @file town_sl.cpp Code handling saving and loading of towns and houses */
+
+#include "../stdafx.h"
+#include "../town.h"
+#include "../newgrf_house.h"
+#include "../newgrf_commons.h"
+#include "../variables.h"
+#include "../tile_map.h"
+#include "../town_map.h"
+
+#include "saveload.h"
+
+extern uint _total_towns;
+
+/**
+ * Check and update town and house values.
+ *
+ * Checked are the HouseIDs. Updated are the
+ * town population the number of houses per
+ * town, the town radius and the max passengers
+ * of the town.
+ */
+void UpdateHousesAndTowns()
+{
+ Town *town;
+ InitializeBuildingCounts();
+
+ /* Reset town population and num_houses */
+ FOR_ALL_TOWNS(town) {
+ town->population = 0;
+ town->num_houses = 0;
+ }
+
+ for (TileIndex t = 0; t < MapSize(); t++) {
+ HouseID house_id;
+
+ if (!IsTileType(t, MP_HOUSE)) continue;
+
+ house_id = GetHouseType(t);
+ if (!GetHouseSpecs(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
+ /* The specs for this type of house are not available any more, so
+ * replace it with the substitute original house type. */
+ house_id = _house_mngr.GetSubstituteID(house_id);
+ SetHouseType(t, house_id);
+ }
+
+ town = GetTownByTile(t);
+ IncreaseBuildingCount(town, house_id);
+ if (IsHouseCompleted(t)) town->population += GetHouseSpecs(house_id)->population;
+
+ /* Increase the number of houses for every house, but only once. */
+ if (GetHouseNorthPart(house_id) == 0) town->num_houses++;
+ }
+
+ /* Update the population and num_house dependant values */
+ FOR_ALL_TOWNS(town) {
+ UpdateTownRadius(town);
+ UpdateTownMaxPass(town);
+ }
+}
+
+/** Save and load of towns. */
+static const SaveLoad _town_desc[] = {
+ SLE_CONDVAR(Town, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
+ SLE_CONDVAR(Town, xy, SLE_UINT32, 6, SL_MAX_VERSION),
+
+ SLE_CONDNULL(2, 0, 2), ///< population, no longer in use
+ SLE_CONDNULL(4, 3, 84), ///< population, no longer in use
+ SLE_CONDNULL(2, 0, 91), ///< num_houses, no longer in use
+
+ SLE_CONDVAR(Town, townnamegrfid, SLE_UINT32, 66, SL_MAX_VERSION),
+ SLE_VAR(Town, townnametype, SLE_UINT16),
+ SLE_VAR(Town, townnameparts, SLE_UINT32),
+ SLE_CONDSTR(Town, name, SLE_STR, 0, 84, SL_MAX_VERSION),
+
+ SLE_VAR(Town, flags12, SLE_UINT8),
+ SLE_CONDVAR(Town, statues, SLE_FILE_U8 | SLE_VAR_U16, 0, 103),
+ SLE_CONDVAR(Town, statues, SLE_UINT16, 104, SL_MAX_VERSION),
+
+ SLE_CONDNULL(1, 0, 1), ///< sort_index, no longer in use
+
+ SLE_CONDVAR(Town, have_ratings, SLE_FILE_U8 | SLE_VAR_U16, 0, 103),
+ SLE_CONDVAR(Town, have_ratings, SLE_UINT16, 104, SL_MAX_VERSION),
+ SLE_CONDARR(Town, ratings, SLE_INT16, 8, 0, 103),
+ SLE_CONDARR(Town, ratings, SLE_INT16, MAX_COMPANIES, 104, SL_MAX_VERSION),
+ /* failed bribe attempts are stored since savegame format 4 */
+ SLE_CONDARR(Town, unwanted, SLE_INT8, 8, 4, 103),
+ SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, 104, SL_MAX_VERSION),
+
+ SLE_CONDVAR(Town, max_pass, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+ SLE_CONDVAR(Town, max_mail, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+ SLE_CONDVAR(Town, new_max_pass, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+ SLE_CONDVAR(Town, new_max_mail, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+ SLE_CONDVAR(Town, act_pass, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+ SLE_CONDVAR(Town, act_mail, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+ SLE_CONDVAR(Town, new_act_pass, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+ SLE_CONDVAR(Town, new_act_mail, SLE_FILE_U16 | SLE_VAR_U32, 0, 8),
+
+ SLE_CONDVAR(Town, max_pass, SLE_UINT32, 9, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, max_mail, SLE_UINT32, 9, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, new_max_pass, SLE_UINT32, 9, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, new_max_mail, SLE_UINT32, 9, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, act_pass, SLE_UINT32, 9, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, act_mail, SLE_UINT32, 9, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, new_act_pass, SLE_UINT32, 9, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, new_act_mail, SLE_UINT32, 9, SL_MAX_VERSION),
+
+ SLE_VAR(Town, pct_pass_transported, SLE_UINT8),
+ SLE_VAR(Town, pct_mail_transported, SLE_UINT8),
+
+ SLE_VAR(Town, act_food, SLE_UINT16),
+ SLE_VAR(Town, act_water, SLE_UINT16),
+ SLE_VAR(Town, new_act_food, SLE_UINT16),
+ SLE_VAR(Town, new_act_water, SLE_UINT16),
+
+ SLE_CONDVAR(Town, time_until_rebuild, SLE_UINT8, 0, 53),
+ SLE_CONDVAR(Town, grow_counter, SLE_UINT8, 0, 53),
+ SLE_CONDVAR(Town, growth_rate, SLE_UINT8, 0, 53),
+
+ SLE_CONDVAR(Town, time_until_rebuild, SLE_UINT16, 54, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, grow_counter, SLE_UINT16, 54, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, growth_rate, SLE_INT16, 54, SL_MAX_VERSION),
+
+ SLE_VAR(Town, fund_buildings_months, SLE_UINT8),
+ SLE_VAR(Town, road_build_months, SLE_UINT8),
+
+ SLE_CONDVAR(Town, exclusivity, SLE_UINT8, 2, SL_MAX_VERSION),
+ SLE_CONDVAR(Town, exclusive_counter, SLE_UINT8, 2, SL_MAX_VERSION),
+
+ SLE_CONDVAR(Town, larger_town, SLE_BOOL, 56, SL_MAX_VERSION),
+
+ /* reserve extra space in savegame here. (currently 30 bytes) */
+ SLE_CONDNULL(30, 2, SL_MAX_VERSION),
+
+ SLE_END()
+};
+
+/* Save and load the mapping between the house id on the map, and the grf file
+ * it came from. */
+static const SaveLoad _house_id_mapping_desc[] = {
+ SLE_VAR(EntityIDMapping, grfid, SLE_UINT32),
+ SLE_VAR(EntityIDMapping, entity_id, SLE_UINT8),
+ SLE_VAR(EntityIDMapping, substitute_id, SLE_UINT8),
+ SLE_END()
+};
+
+static void Save_HOUSEIDS()
+{
+ uint j = _house_mngr.GetMaxMapping();
+
+ for (uint i = 0; i < j; i++) {
+ SlSetArrayIndex(i);
+ SlObject(&_house_mngr.mapping_ID[i], _house_id_mapping_desc);
+ }
+}
+
+static void Load_HOUSEIDS()
+{
+ int index;
+
+ _house_mngr.ResetMapping();
+ uint max_id = _house_mngr.GetMaxMapping();
+
+ while ((index = SlIterateArray()) != -1) {
+ if ((uint)index >= max_id) break;
+ SlObject(&_house_mngr.mapping_ID[index], _house_id_mapping_desc);
+ }
+}
+
+static void Save_TOWN()
+{
+ Town *t;
+
+ FOR_ALL_TOWNS(t) {
+ SlSetArrayIndex(t->index);
+ SlObject(t, _town_desc);
+ }
+}
+
+static void Load_TOWN()
+{
+ int index;
+
+ _total_towns = 0;
+
+ while ((index = SlIterateArray()) != -1) {
+ Town *t = new (index) Town();
+ SlObject(t, _town_desc);
+
+ _total_towns++;
+ }
+
+ /* This is to ensure all pointers are within the limits of
+ * the size of the TownPool */
+ if (_cur_town_ctr > GetMaxTownIndex())
+ _cur_town_ctr = 0;
+}
+
+void AfterLoadTown()
+{
+ Town *t;
+ FOR_ALL_TOWNS(t) t->InitializeLayout();
+}
+
+extern const ChunkHandler _town_chunk_handlers[] = {
+ { 'HIDS', Save_HOUSEIDS, Load_HOUSEIDS, CH_ARRAY },
+ { 'CITY', Save_TOWN, Load_TOWN, CH_ARRAY | CH_LAST},
+};