summaryrefslogtreecommitdiff
path: root/src/saveload
diff options
context:
space:
mode:
authoryexo <yexo@openttd.org>2010-08-24 16:00:35 +0000
committeryexo <yexo@openttd.org>2010-08-24 16:00:35 +0000
commit3b04f510b14a44529cad789983b5071540a1bb7a (patch)
treec15b61b671bed8231efbe10f3e311dbb09ccec4d /src/saveload
parent5e08df7689e871f40a5d62162269200d847cf230 (diff)
downloadopenttd-3b04f510b14a44529cad789983b5071540a1bb7a.tar.xz
(svn r20609) -Fix [FS#3702]: crash when a NewGRF defined an invalid substitute type for a house and the NewGRF was removed during the game
Diffstat (limited to 'src/saveload')
-rw-r--r--src/saveload/town_sl.cpp43
1 files changed, 40 insertions, 3 deletions
diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp
index af255ee91..820c879f7 100644
--- a/src/saveload/town_sl.cpp
+++ b/src/saveload/town_sl.cpp
@@ -36,18 +36,55 @@ void UpdateHousesAndTowns()
}
for (TileIndex t = 0; t < MapSize(); t++) {
- HouseID house_id;
-
if (!IsTileType(t, MP_HOUSE)) continue;
- house_id = GetCleanHouseType(t);
+ HouseID house_id = GetCleanHouseType(t);
if (!HouseSpec::Get(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);
}
+ }
+
+ /* Check for cases when a NewGRF has set a wrong house substitute type. */
+ for (TileIndex t = 0; t < MapSize(); t++) {
+ if (!IsTileType(t, MP_HOUSE)) continue;
+
+ HouseID house_type = GetCleanHouseType(t);
+ TileIndex north_tile = t + GetHouseNorthPart(house_type); // modifies 'house_type'!
+ if (t == north_tile) {
+ const HouseSpec *hs = HouseSpec::Get(house_type);
+ bool valid_house = true;
+ if (hs->building_flags & TILE_SIZE_2x1) {
+ TileIndex tile = t + TileDiffXY(1, 0);
+ if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
+ } else if (hs->building_flags & TILE_SIZE_1x2) {
+ TileIndex tile = t + TileDiffXY(0, 1);
+ if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
+ } else if (hs->building_flags & TILE_SIZE_2x2) {
+ TileIndex tile = t + TileDiffXY(1, 0);
+ if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
+ tile = t + TileDiffXY(0, 1);
+ if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 2) valid_house = false;
+ tile = t + TileDiffXY(1, 1);
+ if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 3) valid_house = false;
+ }
+ /* If not all tiles of this house are present remove the house.
+ * The other tiles will get removed later in this loop because
+ * their north tile is not the correct type anymore. */
+ if (!valid_house) DoClearSquare(t);
+ } else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) {
+ /* This tile should be part of a multi-tile building but the
+ * north tile of this house isn't on the map. */
+ DoClearSquare(t);
+ }
+ }
+
+ for (TileIndex t = 0; t < MapSize(); t++) {
+ if (!IsTileType(t, MP_HOUSE)) continue;
+ HouseID house_id = GetCleanHouseType(t);
town = Town::GetByTile(t);
IncreaseBuildingCount(town, house_id);
if (IsHouseCompleted(t)) town->population += HouseSpec::Get(house_id)->population;