Changeset - r15914:d0a68c65cbc5
[Not reviewed]
master
0 1 0
yexo - 14 years ago 2010-08-24 16:00:35
yexo@openttd.org
(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
1 file changed with 40 insertions and 3 deletions:
0 comments (0 inline, 0 general)
src/saveload/town_sl.cpp
Show inline comments
 
@@ -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;
0 comments (0 inline, 0 general)