diff options
author | yexo <yexo@openttd.org> | 2010-08-24 16:00:35 +0000 |
---|---|---|
committer | yexo <yexo@openttd.org> | 2010-08-24 16:00:35 +0000 |
commit | 3b04f510b14a44529cad789983b5071540a1bb7a (patch) | |
tree | c15b61b671bed8231efbe10f3e311dbb09ccec4d | |
parent | 5e08df7689e871f40a5d62162269200d847cf230 (diff) | |
download | openttd-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
-rw-r--r-- | src/saveload/town_sl.cpp | 43 |
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; |