diff --git a/src/house.h b/src/house.h index 512665ae71..0f362f83df 100644 --- a/src/house.h +++ b/src/house.h @@ -52,35 +52,40 @@ static constexpr BuildingFlags BUILDING_2_TILES_X = {BuildingFlag::Size2x1, Bu static constexpr BuildingFlags BUILDING_2_TILES_Y = {BuildingFlag::Size1x2, BuildingFlag::Size2x2}; static constexpr BuildingFlags BUILDING_HAS_4_TILES = {BuildingFlag::Size2x2}; -enum HouseZonesBits : uint8_t { - HZB_BEGIN = 0, - HZB_TOWN_EDGE = 0, - HZB_TOWN_OUTSKIRT, - HZB_TOWN_OUTER_SUBURB, - HZB_TOWN_INNER_SUBURB, - HZB_TOWN_CENTRE, - HZB_END, -}; -static_assert(HZB_END == 5); +enum class HouseZone : uint8_t { + TownEdge = 0, + TownOutskirt = 1, + TownOuterSuburb = 2, + TownInnerSuburb = 3, + TownCentre = 4, + TownEnd, -DECLARE_INCREMENT_DECREMENT_OPERATORS(HouseZonesBits) - -enum HouseZones : uint16_t { - HZ_NOZNS = 0x0000, ///< 0 This is just to get rid of zeros, meaning none - HZ_ZON1 = 1U << HZB_TOWN_EDGE, ///< 0..4 1,2,4,8,10 which town zones the building can be built in, Zone1 been the further suburb - HZ_ZON2 = 1U << HZB_TOWN_OUTSKIRT, - HZ_ZON3 = 1U << HZB_TOWN_OUTER_SUBURB, - HZ_ZON4 = 1U << HZB_TOWN_INNER_SUBURB, - HZ_ZON5 = 1U << HZB_TOWN_CENTRE, ///< center of town - HZ_ZONALL = 0x001F, ///< 1F This is just to englobe all above types at once - HZ_SUBARTC_ABOVE = 0x0800, ///< 11 800 can appear in sub-arctic climate above the snow line - HZ_TEMP = 0x1000, ///< 12 1000 can appear in temperate climate - HZ_SUBARTC_BELOW = 0x2000, ///< 13 2000 can appear in sub-arctic climate below the snow line - HZ_SUBTROPIC = 0x4000, ///< 14 4000 can appear in subtropical climate - HZ_TOYLND = 0x8000, ///< 15 8000 can appear in toyland climate - HZ_CLIMALL = 0xF800, ///< Bitmask of all climate bits + ClimateSubarcticAboveSnow = 11, ///< Building can appear in sub-arctic climate above the snow line + ClimateTemperate = 12, ///< Building can appear in temperate climate + ClimateSubarcticBelowSnow = 13, ///< Building can appear in sub-arctic climate below the snow line + ClimateSubtropic = 14, ///< Building can appear in subtropical climate + ClimateToyland = 15, ///< Building can appear in toyland climate +}; +using HouseZones = EnumBitSet; + +static constexpr uint NUM_HOUSE_ZONES = to_underlying(HouseZone::TownEnd); +static_assert(NUM_HOUSE_ZONES == 5); + +static constexpr HouseZones HZ_ZONE_ALL = { + HouseZone::TownEdge, + HouseZone::TownOutskirt, + HouseZone::TownOuterSuburb, + HouseZone::TownInnerSuburb, + HouseZone::TownCentre, +}; + +static constexpr HouseZones HZ_CLIMATE_ALL = { + HouseZone::ClimateSubarcticAboveSnow, + HouseZone::ClimateTemperate, + HouseZone::ClimateSubarcticBelowSnow, + HouseZone::ClimateSubtropic, + HouseZone::ClimateToyland, }; -DECLARE_ENUM_AS_BIT_SET(HouseZones) enum class HouseExtraFlag : uint8_t { BuildingIsHistorical = 0, ///< this house will only appear during town generation in random games, thus the historical @@ -139,5 +144,6 @@ inline HouseID GetTranslatedHouseID(HouseID hid) } void ShowBuildHousePicker(struct Window *); +HouseZones GetClimateMaskForLandscape(); #endif /* HOUSE_H */ diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 6ef9c2cb5a..c3c664e4c4 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2704,19 +2704,13 @@ struct IndustryCargoesWindow : public Window { */ static bool HousesCanAccept(const std::span cargoes) { - HouseZones climate_mask; - switch (_settings_game.game_creation.landscape) { - case LandscapeType::Temperate: climate_mask = HZ_TEMP; break; - case LandscapeType::Arctic: climate_mask = HZ_SUBARTC_ABOVE | HZ_SUBARTC_BELOW; break; - case LandscapeType::Tropic: climate_mask = HZ_SUBTROPIC; break; - case LandscapeType::Toyland: climate_mask = HZ_TOYLND; break; - default: NOT_REACHED(); - } + HouseZones climate_mask = GetClimateMaskForLandscape(); + for (const CargoType cargo_type : cargoes) { if (!IsValidCargoType(cargo_type)) continue; for (const auto &hs : HouseSpec::Specs()) { - if (!hs.enabled || !(hs.building_availability & climate_mask)) continue; + if (!hs.enabled || !hs.building_availability.Any(climate_mask)) continue; for (uint j = 0; j < lengthof(hs.accepts_cargo); j++) { if (hs.cargo_acceptance[j] > 0 && cargo_type == hs.accepts_cargo[j]) return true; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 099f23a56d..b9534adfee 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -976,7 +976,7 @@ static bool IsHouseSpecValid(HouseSpec &hs, const HouseSpec *next1, const HouseS } /* Make sure that additional parts of multitile houses are not available. */ - if (!hs.building_flags.Any(BUILDING_HAS_1_TILE) && (hs.building_availability & HZ_ZONALL) != 0 && (hs.building_availability & HZ_CLIMALL) != 0) { + if (!hs.building_flags.Any(BUILDING_HAS_1_TILE) && hs.building_availability.Any(HZ_ZONE_ALL) && hs.building_availability.Any(HZ_CLIMATE_ALL)) { hs.enabled = false; if (!filename.empty()) Debug(grf, 1, "FinaliseHouseArray: {} defines house {} without a size but marked it as available. Disabling house.", filename, hs.grf_prop.local_id); return false; @@ -997,7 +997,7 @@ static void EnsureEarlyHouse(HouseZones bitmask) for (const auto &hs : HouseSpec::Specs()) { if (!hs.enabled) continue; - if ((hs.building_availability & bitmask) != bitmask) continue; + if (!hs.building_availability.All(bitmask)) continue; if (hs.min_year < min_year) min_year = hs.min_year; } @@ -1005,7 +1005,7 @@ static void EnsureEarlyHouse(HouseZones bitmask) for (auto &hs : HouseSpec::Specs()) { if (!hs.enabled) continue; - if ((hs.building_availability & bitmask) != bitmask) continue; + if (!hs.building_availability.All(bitmask)) continue; if (hs.min_year == min_year) hs.min_year = CalendarTime::MIN_YEAR; } } @@ -1077,19 +1077,11 @@ static void FinaliseHouseArray() } } - HouseZones climate_mask = (HouseZones)(1 << (to_underlying(_settings_game.game_creation.landscape) + 12)); - EnsureEarlyHouse(HZ_ZON1 | climate_mask); - EnsureEarlyHouse(HZ_ZON2 | climate_mask); - EnsureEarlyHouse(HZ_ZON3 | climate_mask); - EnsureEarlyHouse(HZ_ZON4 | climate_mask); - EnsureEarlyHouse(HZ_ZON5 | climate_mask); - - if (_settings_game.game_creation.landscape == LandscapeType::Arctic) { - EnsureEarlyHouse(HZ_ZON1 | HZ_SUBARTC_ABOVE); - EnsureEarlyHouse(HZ_ZON2 | HZ_SUBARTC_ABOVE); - EnsureEarlyHouse(HZ_ZON3 | HZ_SUBARTC_ABOVE); - EnsureEarlyHouse(HZ_ZON4 | HZ_SUBARTC_ABOVE); - EnsureEarlyHouse(HZ_ZON5 | HZ_SUBARTC_ABOVE); + HouseZones climate_mask = GetClimateMaskForLandscape(); + for (HouseZone climate : climate_mask) { + for (HouseZone zone : HZ_ZONE_ALL) { + EnsureEarlyHouse({climate, zone}); + } } } diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp index a13482f155..f5815e3abf 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -170,7 +170,7 @@ static uint32_t GetAirportTileIDAtOffset(TileIndex tile, const Station *st, uint case 0x41: return GetTerrainType(this->tile); /* Current town zone of the tile in the nearest town */ - case 0x42: return GetTownRadiusGroup(ClosestTownFromTile(this->tile, UINT_MAX), this->tile); + case 0x42: return to_underlying(GetTownRadiusGroup(ClosestTownFromTile(this->tile, UINT_MAX), this->tile)); /* Position relative to most northern airport tile. */ case 0x43: return GetRelativePosition(this->tile, this->st->airport.tile); diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index 3bcd644128..d7dc676715 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -345,7 +345,7 @@ static uint32_t GetDistanceFromNearbyHouse(uint8_t parameter, TileIndex start_ti case 0x41: return IsTileType(this->tile, MP_HOUSE) ? GetHouseAge(this->tile).base() : 0; /* Town zone */ - case 0x42: return GetTownRadiusGroup(this->town, this->tile); + case 0x42: return to_underlying(GetTownRadiusGroup(this->town, this->tile)); /* Terrain type */ case 0x43: return GetTerrainType(this->tile); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index b10c67fa79..9bf1b99ea7 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -185,7 +185,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t param_set_id, uint8 case 0x87: return GetTerrainType(this->tile); /* Town zone */ - case 0x88: return GetTownRadiusGroup(this->industry->town, this->tile); + case 0x88: return to_underlying(GetTownRadiusGroup(this->industry->town, this->tile)); /* Manhattan distance of the closest town */ case 0x89: return ClampTo(DistanceManhattan(this->industry->town->xy, this->tile)); @@ -295,7 +295,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t param_set_id, uint8 case 0x65: { if (this->tile == INVALID_TILE) break; TileIndex tile = GetNearbyTile(parameter, this->tile, true); - return GetTownRadiusGroup(this->industry->town, tile) << 16 | ClampTo(DistanceManhattan(tile, this->industry->town->xy)); + return to_underlying(GetTownRadiusGroup(this->industry->town, tile)) << 16 | ClampTo(DistanceManhattan(tile, this->industry->town->xy)); } /* Get square of Euclidean distance of closest town */ case 0x66: { diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 0e8c5ed695..ac5838e759 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -69,7 +69,7 @@ uint32_t GetRelativePosition(TileIndex tile, TileIndex ind_tile) case 0x41: return GetTerrainType(this->tile); /* Current town zone of the tile in the nearest town */ - case 0x42: return GetTownRadiusGroup(ClosestTownFromTile(this->tile, UINT_MAX), this->tile); + case 0x42: return to_underlying(GetTownRadiusGroup(ClosestTownFromTile(this->tile, UINT_MAX), this->tile)); /* Relative position */ case 0x43: return GetRelativePosition(this->tile, this->industry->location.tile); diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index c853ebfff1..ff059e33fb 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -331,7 +331,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t local_id, uint32_t case 0x44: return GetTileOwner(this->tile).base(); /* Get town zone and Manhattan distance of closest town */ - case 0x45: return GetTownRadiusGroup(t, this->tile) << 16 | ClampTo(DistanceManhattan(this->tile, t->xy)); + case 0x45: return to_underlying(GetTownRadiusGroup(t, this->tile)) << 16 | ClampTo(DistanceManhattan(this->tile, t->xy)); /* Get square of Euclidean distance of closest town */ case 0x46: return DistanceSquare(this->tile, t->xy); diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index f455904506..89d06952ef 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -33,7 +33,7 @@ case 0x41: return 0; case 0x42: return 0; case 0x43: return TimerGameCalendar::date.base(); - case 0x44: return HZB_TOWN_EDGE; + case 0x44: return to_underlying(HouseZone::TownEdge); case 0x45: { auto rt = GetRailTypeInfoIndex(this->rti); uint8_t local = GetReverseRailTypeTranslation(rt, this->ro.grffile); @@ -57,7 +57,7 @@ } else if (IsLevelCrossingTile(this->tile)) { t = ClosestTownFromTile(this->tile, UINT_MAX); } - return t != nullptr ? GetTownRadiusGroup(t, this->tile) : HZB_TOWN_EDGE; + return to_underlying(t != nullptr ? GetTownRadiusGroup(t, this->tile) : HouseZone::TownEdge); } case 0x45: return GetTrackTypes(this->tile, ro.grffile); diff --git a/src/newgrf_roadstop.cpp b/src/newgrf_roadstop.cpp index d1e4aca577..ba98dc7691 100644 --- a/src/newgrf_roadstop.cpp +++ b/src/newgrf_roadstop.cpp @@ -106,9 +106,9 @@ uint32_t RoadStopScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] u /* Town zone and Manhattan distance of closest town */ case 0x45: { - if (this->tile == INVALID_TILE) return HZB_TOWN_EDGE << 16; + if (this->tile == INVALID_TILE) return to_underlying(HouseZone::TownEdge) << 16; const Town *t = (this->st == nullptr) ? ClosestTownFromTile(this->tile, UINT_MAX) : this->st->town; - return t != nullptr ? (GetTownRadiusGroup(t, this->tile) << 16 | ClampTo(DistanceManhattan(this->tile, t->xy))) : HZB_TOWN_EDGE << 16; + return t != nullptr ? (to_underlying(GetTownRadiusGroup(t, this->tile)) << 16 | ClampTo(DistanceManhattan(this->tile, t->xy))) : to_underlying(HouseZone::TownEdge) << 16; } /* Get square of Euclidean distance of closest town */ diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index 4498cc0507..afd8fa05f3 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -67,7 +67,7 @@ uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile) case 0x41: return 0; case 0x42: return 0; case 0x43: return TimerGameCalendar::date.base(); - case 0x44: return HZB_TOWN_EDGE; + case 0x44: return to_underlying(HouseZone::TownEdge); case 0x45: { auto rt = GetRoadTypeInfoIndex(this->rti); uint8_t local = GetReverseRoadTypeTranslation(rt, this->ro.grffile); @@ -95,7 +95,7 @@ uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile) } else { t = ClosestTownFromTile(this->tile, UINT_MAX); } - return t != nullptr ? GetTownRadiusGroup(t, this->tile) : HZB_TOWN_EDGE; + return to_underlying(t != nullptr ? GetTownRadiusGroup(t, this->tile) : HouseZone::TownEdge); } case 0x45: return GetTrackTypes(this->tile, ro.grffile); diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp index 74baa8e4c0..81a89f1e70 100644 --- a/src/newgrf_town.cpp +++ b/src/newgrf_town.cpp @@ -57,16 +57,16 @@ case 0x8A: return this->t->grow_counter / Ticks::TOWN_GROWTH_TICKS; case 0x92: return this->t->flags; // In original game, 0x92 and 0x93 are really one word. Since flags is a byte, this is to adjust case 0x93: return 0; - case 0x94: return ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_EDGE]); - case 0x95: return GB(ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_EDGE]), 8, 8); - case 0x96: return ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_OUTSKIRT]); - case 0x97: return GB(ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_OUTSKIRT]), 8, 8); - case 0x98: return ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_OUTER_SUBURB]); - case 0x99: return GB(ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_OUTER_SUBURB]), 8, 8); - case 0x9A: return ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_INNER_SUBURB]); - case 0x9B: return GB(ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_INNER_SUBURB]), 8, 8); - case 0x9C: return ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_CENTRE]); - case 0x9D: return GB(ClampTo(this->t->cache.squared_town_zone_radius[HZB_TOWN_CENTRE]), 8, 8); + case 0x94: return ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]); + case 0x95: return GB(ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]), 8, 8); + case 0x96: return ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownOutskirt)]); + case 0x97: return GB(ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownOutskirt)]), 8, 8); + case 0x98: return ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownOuterSuburb)]); + case 0x99: return GB(ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownOuterSuburb)]), 8, 8); + case 0x9A: return ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownInnerSuburb)]); + case 0x9B: return GB(ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownInnerSuburb)]), 8, 8); + case 0x9C: return ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownCentre)]); + case 0x9D: return GB(ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownCentre)]), 8, 8); case 0x9E: return this->t->ratings[0]; case 0x9F: return GB(this->t->ratings[0], 8, 8); case 0xA0: return this->t->ratings[1]; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 584730a101..b685e37ef0 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -621,7 +621,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, company = OWNER_TOWN; /* If we are not within a town, we are not owned by the town */ - if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) { + if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) { company = OWNER_NONE; } } @@ -1956,7 +1956,7 @@ static const Roadside _town_road_types[][2] = { { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED } }; -static_assert(lengthof(_town_road_types) == HZB_END); +static_assert(lengthof(_town_road_types) == NUM_HOUSE_ZONES); static const Roadside _town_road_types_2[][2] = { { ROADSIDE_GRASS, ROADSIDE_GRASS }, @@ -1966,7 +1966,7 @@ static const Roadside _town_road_types_2[][2] = { { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED } }; -static_assert(lengthof(_town_road_types_2) == HZB_END); +static_assert(lengthof(_town_road_types_2) == NUM_HOUSE_ZONES); static void TileLoop_Road(TileIndex tile) @@ -1997,14 +1997,14 @@ static void TileLoop_Road(TileIndex tile) const Town *t = ClosestTownFromTile(tile, UINT_MAX); if (!HasRoadWorks(tile)) { - HouseZonesBits grp = HZB_TOWN_EDGE; + HouseZone grp = HouseZone::TownEdge; if (t != nullptr) { grp = GetTownRadiusGroup(t, tile); /* Show an animation to indicate road work */ if (t->road_build_months != 0 && - (DistanceManhattan(t->xy, tile) < 8 || grp != HZB_TOWN_EDGE) && + (DistanceManhattan(t->xy, tile) < 8 || grp != HouseZone::TownEdge) && IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) { if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) { StartRoadWorks(tile); @@ -2023,7 +2023,7 @@ static void TileLoop_Road(TileIndex tile) { /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */ - const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[grp] : _town_road_types[grp]; + const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[to_underlying(grp)] : _town_road_types[to_underlying(grp)]; Roadside cur_rs = GetRoadside(tile); /* We have our desired type, do nothing */ diff --git a/src/script/api/script_town.cpp b/src/script/api/script_town.cpp index e4e0c12623..730d1829ee 100644 --- a/src/script/api/script_town.cpp +++ b/src/script/api/script_town.cpp @@ -206,7 +206,7 @@ if (!IsValidTown(town_id)) return false; const Town *t = ::Town::Get(town_id); - return ((uint32_t)GetDistanceSquareToTile(town_id, tile) <= t->cache.squared_town_zone_radius[HZB_TOWN_EDGE]); + return ((uint32_t)GetDistanceSquareToTile(town_id, tile) <= t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]); } /* static */ bool ScriptTown::HasStatue(TownID town_id) diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 25e009e19f..0e93152019 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3644,14 +3644,14 @@ static void TileLoop_Station(TileIndex tile) default: break; } - HouseZonesBits new_zone = HZB_TOWN_EDGE; + HouseZone new_zone = HouseZone::TownEdge; const Town *t = ClosestTownFromTile(tile, UINT_MAX); if (t != nullptr) { new_zone = GetTownRadiusGroup(t, tile); } /* Adjust road ground type depending on 'new_zone' */ - Roadside new_rs = new_zone > HZB_TOWN_EDGE ? ROADSIDE_PAVED : ROADSIDE_GRASS; + Roadside new_rs = new_zone != HouseZone::TownEdge ? ROADSIDE_PAVED : ROADSIDE_GRASS; Roadside cur_rs = GetRoadWaypointRoadside(tile); if (new_rs != cur_rs) { diff --git a/src/table/town_land.h b/src/table/town_land.h index 98f3c11b5f..12c9c0c1b5 100644 --- a/src/table/town_land.h +++ b/src/table/town_land.h @@ -1834,443 +1834,443 @@ extern const HouseSpec _original_house_specs[] = { */ MS(1963, CalendarTime::MAX_YEAR, 187, 150, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 140, 70, 8, 3, 4, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 00 MS(1957, CalendarTime::MAX_YEAR, 85, 140, STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_1, 130, 55, 8, 3, 4, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 01 MS(1968, CalendarTime::MAX_YEAR, 40, 100, STR_TOWN_BUILDING_NAME_SMALL_BLOCK_OF_FLATS_1, 90, 20, 8, 3, 1, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 02 MS( 0, CalendarTime::MAX_YEAR, 5, 90, STR_TOWN_BUILDING_NAME_CHURCH_1, 230, 2, 2, 0, 0, BuildingFlags({BuildingFlag::IsChurch, BuildingFlag::Size1x1}), - HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 03 MS(1975, CalendarTime::MAX_YEAR, 220, 160, STR_TOWN_BUILDING_NAME_LARGE_OFFICE_BLOCK_1, 160, 85, 10, 4, 6, BuildingFlags({BuildingFlag::IsAnimated, BuildingFlag::Size1x1}), - HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5, + HouseZones({HouseZone::ClimateTemperate, HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 04 MS(1975, CalendarTime::MAX_YEAR, 220, 160, STR_TOWN_BUILDING_NAME_LARGE_OFFICE_BLOCK_1, 160, 85, 10, 4, 6, BuildingFlags({BuildingFlag::IsAnimated, BuildingFlag::Size1x1}), - HZ_SUBARTC_ABOVE | HZ_ZON5, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 05 MS( 0, CalendarTime::MAX_YEAR, 30, 80, STR_TOWN_BUILDING_NAME_TOWN_HOUSES_1, 80, 12, 4, 1, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 06 MS(1959, CalendarTime::MAX_YEAR, 140, 180, STR_TOWN_BUILDING_NAME_HOTEL_1, 150, 22, 6, 1, 2, BuildingFlag::Size1x2, - HZ_TEMP | HZ_ZON5 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 07 MS(1959, CalendarTime::MAX_YEAR, 0, 180, STR_TOWN_BUILDING_NAME_HOTEL_1, 150, 22, 6, 1, 2, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 08 MS(1945, CalendarTime::MAX_YEAR, 0, 65, STR_TOWN_BUILDING_NAME_STATUE_1, 40, 0, 2, 0, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateTemperate, HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 09 MS(1945, CalendarTime::MAX_YEAR, 0, 65, STR_TOWN_BUILDING_NAME_FOUNTAIN_1, 40, 0, 2, 0, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5, + HouseZones({HouseZone::ClimateTemperate, HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 0A MS( 0, CalendarTime::MAX_YEAR, 0, 60, STR_TOWN_BUILDING_NAME_PARK_1, 75, 0, 2, 0, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 0B MS(1935, CalendarTime::MAX_YEAR, 0, 60, STR_TOWN_BUILDING_NAME_PARK_1, 75, 0, 2, 0, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON4, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 0C MS(1951, CalendarTime::MAX_YEAR, 150, 130, STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_2, 110, 65, 8, 2, 4, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 0D MS(1930, 1960, 95, 110, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 100, 48, 6, 2, 3, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 0E MS(1930, 1960, 95, 105, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 100, 48, 6, 2, 3, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 0F MS(1930, 1960, 95, 107, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 100, 48, 6, 2, 3, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 10 MS(1977, CalendarTime::MAX_YEAR, 130, 200, STR_TOWN_BUILDING_NAME_MODERN_OFFICE_BUILDING_1, 150, 50, 10, 3, 6, BuildingFlag::Size1x1, - HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5, + HouseZones({HouseZone::ClimateTemperate, HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 11 MS(1983, CalendarTime::MAX_YEAR, 6, 145, STR_TOWN_BUILDING_NAME_WAREHOUSE_1, 110, 10, 6, 3, 8, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 12 MS(1985, CalendarTime::MAX_YEAR, 110, 155, STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_3, 110, 55, 6, 2, 6, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 13 MS( 0, CalendarTime::MAX_YEAR, 65, 250, STR_TOWN_BUILDING_NAME_STADIUM_1, 300, 5, 4, 0, 0, BuildingFlags({BuildingFlag::IsStadium, BuildingFlag::Size2x2}), - HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 14 MS( 0, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_STADIUM_1, 300, 5, 4, 0, 0, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 15 MS( 0, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_STADIUM_1, 300, 5, 4, 0, 0, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 16 MS( 0, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_STADIUM_1, 300, 5, 4, 0, 0, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 17 MS( 0, 1951, 15, 70, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1, 75, 6, 3, 1, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 18 MS( 0, 1952, 12, 75, STR_TOWN_BUILDING_NAME_COTTAGES_1, 75, 7, 3, 1, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON1, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 19 MS(1931, CalendarTime::MAX_YEAR, 13, 71, STR_TOWN_BUILDING_NAME_HOUSES_1, 75, 8, 3, 1, 0, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 1A MS(1935, CalendarTime::MAX_YEAR, 100, 135, STR_TOWN_BUILDING_NAME_FLATS_1, 100, 35, 7, 2, 2, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 1B MS(1963, CalendarTime::MAX_YEAR, 170, 145, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_2, 170, 50, 8, 3, 3, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 1C MS( 0, 1955, 100, 132, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_2, 135, 40, 6, 2, 3, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 1D MS(1973, CalendarTime::MAX_YEAR, 180, 155, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_3, 180, 64, 8, 3, 3, BuildingFlag::Size1x1, - HZ_TEMP | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 1E MS( 0, CalendarTime::MAX_YEAR, 35, 220, STR_TOWN_BUILDING_NAME_THEATER_1, 230, 23, 8, 2, 2, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 1F MS(1958, CalendarTime::MAX_YEAR, 65, 250, STR_TOWN_BUILDING_NAME_STADIUM_2, 300, 5, 4, 0, 0, BuildingFlags({BuildingFlag::IsStadium, BuildingFlag::Size2x2}), - HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateTemperate, HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 20 MS(1958, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_STADIUM_2, 300, 5, 4, 0, 0, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 21 MS(1958, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_STADIUM_2, 300, 5, 4, 0, 0, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 22 MS(1958, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_STADIUM_2, 300, 5, 4, 0, 0, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 23 MS(2000, CalendarTime::MAX_YEAR, 140, 170, STR_TOWN_BUILDING_NAME_OFFICES_1, 250, 65, 8, 3, 2, BuildingFlag::Size1x1, - HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateTemperate, HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 24 MS( 0, 1960, 15, 70, STR_TOWN_BUILDING_NAME_HOUSES_2, 75, 6, 3, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 25 MS( 0, 1960, 15, 70, STR_TOWN_BUILDING_NAME_HOUSES_2, 75, 6, 3, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 26 MS(1945, CalendarTime::MAX_YEAR, 35, 210, STR_TOWN_BUILDING_NAME_CINEMA_1, 230, 23, 8, 2, 2, BuildingFlag::Size1x1, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 27 MS(1983, CalendarTime::MAX_YEAR, 180, 250, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1, 300, 5, 8, 2, 3, BuildingFlag::Size2x2, - HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 |HZ_ZON2, + HouseZones({HouseZone::ClimateTemperate, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb,HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 28 MS(1983, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1, 300, 5, 8, 2, 3, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 29 MS(1983, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1, 300, 5, 8, 2, 3, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 2A MS(1983, CalendarTime::MAX_YEAR, 0, 250, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1, 300, 5, 8, 2, 3, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 2B MS( 0, CalendarTime::MAX_YEAR, 80, 100, STR_TOWN_BUILDING_NAME_FLATS_1, 90, 20, 5, 2, 2, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 2C MS( 0, CalendarTime::MAX_YEAR, 80, 100, STR_TOWN_BUILDING_NAME_FLATS_1, 90, 20, 5, 2, 2, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 2D MS( 0, CalendarTime::MAX_YEAR, 16, 70, STR_TOWN_BUILDING_NAME_HOUSES_2, 70, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 2E MS( 0, CalendarTime::MAX_YEAR, 16, 70, STR_TOWN_BUILDING_NAME_HOUSES_2, 70, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 2F MS( 0, 1963, 14, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 70, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 30 MS( 0, 1963, 14, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 70, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 31 MS(1966, CalendarTime::MAX_YEAR, 135, 150, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 120, 60, 8, 3, 4, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 32 MS(1966, CalendarTime::MAX_YEAR, 135, 150, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 120, 60, 8, 3, 4, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 33 MS(1970, CalendarTime::MAX_YEAR, 170, 170, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 130, 70, 9, 3, 4, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 34 MS(1970, CalendarTime::MAX_YEAR, 170, 170, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 130, 70, 9, 3, 4, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 35 MS(1974, CalendarTime::MAX_YEAR, 210, 200, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 140, 80, 10, 3, 5, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 36 MS(1974, CalendarTime::MAX_YEAR, 210, 200, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 140, 80, 10, 3, 5, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 37 MS( 0, CalendarTime::MAX_YEAR, 10, 60, STR_TOWN_BUILDING_NAME_HOUSES_2, 60, 5, 2, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 38 MS( 0, CalendarTime::MAX_YEAR, 10, 60, STR_TOWN_BUILDING_NAME_HOUSES_2, 60, 5, 2, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 39 MS( 0, CalendarTime::MAX_YEAR, 25, 100, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 80, 20, 3, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 3A MS( 0, CalendarTime::MAX_YEAR, 25, 100, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 80, 20, 3, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 3B MS( 0, CalendarTime::MAX_YEAR, 6, 85, STR_TOWN_BUILDING_NAME_CHURCH_1, 230, 2, 2, 0, 0, BuildingFlags({BuildingFlag::IsChurch, BuildingFlag::Size1x1}), - HZ_SUBARTC_BELOW | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 3C MS( 0, CalendarTime::MAX_YEAR, 6, 85, STR_TOWN_BUILDING_NAME_CHURCH_1, 230, 2, 2, 0, 0, BuildingFlags({BuildingFlag::IsChurch, BuildingFlag::Size1x1}), - HZ_SUBARTC_ABOVE | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 3D MS( 0, CalendarTime::MAX_YEAR, 17, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 7, 3, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 3E MS( 0, CalendarTime::MAX_YEAR, 17, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 7, 3, 1, 1, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 3F MS( 0, 1960, 90, 140, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 110, 45, 6, 2, 3, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 40 MS( 0, 1960, 90, 140, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 110, 45, 6, 2, 3, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 41 MS(1972, CalendarTime::MAX_YEAR, 140, 160, STR_TOWN_BUILDING_NAME_HOTEL_1, 160, 25, 6, 1, 3, BuildingFlag::Size1x2, - HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 42 MS(1972, CalendarTime::MAX_YEAR, 0, 160, STR_TOWN_BUILDING_NAME_HOTEL_1, 160, 25, 6, 1, 2, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 43 MS(1972, CalendarTime::MAX_YEAR, 140, 160, STR_TOWN_BUILDING_NAME_HOTEL_1, 160, 25, 6, 1, 3, BuildingFlag::Size1x2, - HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 44 MS(1972, CalendarTime::MAX_YEAR, 0, 160, STR_TOWN_BUILDING_NAME_HOTEL_1, 160, 25, 6, 1, 2, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 45 MS(1963, CalendarTime::MAX_YEAR, 105, 130, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 105, 50, 7, 2, 3, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 46 MS(1963, CalendarTime::MAX_YEAR, 105, 130, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 105, 50, 7, 2, 3, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 47 MS(1978, CalendarTime::MAX_YEAR, 190, 190, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 135, 75, 9, 3, 4, BuildingFlag::Size1x1, - HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 48 MS(1978, CalendarTime::MAX_YEAR, 190, 190, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 135, 75, 9, 3, 4, BuildingFlag::Size1x1, - HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 49 MS(1967, CalendarTime::MAX_YEAR, 250, 140, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 200, 60, 7, 2, 2, BuildingFlag::Size2x1, - HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticBelowSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 4A MS(1967, CalendarTime::MAX_YEAR, 0, 140, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 200, 60, 7, 2, 2, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 4B MS(1967, CalendarTime::MAX_YEAR, 250, 140, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 200, 60, 7, 2, 2, BuildingFlag::Size2x1, - HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubarcticAboveSnow, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 4C MS(1967, CalendarTime::MAX_YEAR, 0, 140, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 200, 60, 7, 2, 2, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_GOODS), // 4D MS( 0, CalendarTime::MAX_YEAR, 16, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 4E MS( 0, CalendarTime::MAX_YEAR, 16, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 4F MS( 0, CalendarTime::MAX_YEAR, 16, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 5, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 50 MS( 0, CalendarTime::MAX_YEAR, 7, 30, STR_TOWN_BUILDING_NAME_HOUSES_2, 30, 4, 3, 1, 1, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON1, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 51 MS( 0, CalendarTime::MAX_YEAR, 45, 130, STR_TOWN_BUILDING_NAME_FLATS_1, 95, 15, 6, 2, 1, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 52 MS( 0, CalendarTime::MAX_YEAR, 8, 90, STR_TOWN_BUILDING_NAME_CHURCH_1, 200, 3, 2, 0, 0, BuildingFlags({BuildingFlag::IsChurch, BuildingFlag::Size1x1}), - HZ_SUBTROPIC | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 53 MS( 0, CalendarTime::MAX_YEAR, 18, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 7, 3, 1, 2, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt}), CT_PASSENGERS, CT_MAIL, CT_FOOD), // 54 MS(1973, CalendarTime::MAX_YEAR, 90, 110, STR_TOWN_BUILDING_NAME_FLATS_1, 95, 24, 6, 2, 1, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 55 MS(1962, CalendarTime::MAX_YEAR, 120, 120, STR_TOWN_BUILDING_NAME_FLATS_1, 95, 25, 6, 2, 1, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 56 MS(1984, CalendarTime::MAX_YEAR, 250, 190, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 140, 80, 8, 3, 4, BuildingFlag::Size2x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 57 MS(1984, CalendarTime::MAX_YEAR, 0, 190, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 140, 80, 8, 3, 4, {}, - HZ_SUBTROPIC, + HouseZones({HouseZone::ClimateSubtropic}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 58 MS( 0, CalendarTime::MAX_YEAR, 80, 110, STR_TOWN_BUILDING_NAME_FLATS_1, 95, 23, 6, 2, 1, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 59 MS(1993, CalendarTime::MAX_YEAR, 180, 180, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 150, 90, 8, 3, 4, BuildingFlag::Size1x1, - HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateSubtropic, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_GOODS), // 5A MS( 0, CalendarTime::MAX_YEAR, 8, 90, STR_TOWN_BUILDING_NAME_CHURCH_1, 200, 3, 2, 0, 0, BuildingFlags({BuildingFlag::IsChurch, BuildingFlag::Size1x1}), - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 5B MS( 0, CalendarTime::MAX_YEAR, 18, 90, STR_TOWN_BUILDING_NAME_HOUSES_2, 90, 5, 6, 2, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 5C MS( 0, CalendarTime::MAX_YEAR, 7, 70, STR_TOWN_BUILDING_NAME_HOUSES_2, 50, 3, 3, 1, 1, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 5D MS( 0, CalendarTime::MAX_YEAR, 15, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 75, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 5E MS( 0, CalendarTime::MAX_YEAR, 17, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 75, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 5F MS( 0, CalendarTime::MAX_YEAR, 19, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 75, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 60 MS( 0, CalendarTime::MAX_YEAR, 21, 80, STR_TOWN_BUILDING_NAME_HOUSES_2, 75, 6, 3, 1, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 61 MS( 0, CalendarTime::MAX_YEAR, 75, 160, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 130, 20, 8, 4, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 62 MS( 0, CalendarTime::MAX_YEAR, 35, 90, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 9, 4, 1, 2, BuildingFlag::Size1x2, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 63 MS( 0, CalendarTime::MAX_YEAR, 0, 90, STR_TOWN_BUILDING_NAME_HOUSES_2, 80, 0, 4, 1, 2, {}, - HZ_NOZNS, + {}, CT_PASSENGERS, CT_MAIL, CT_CANDY), // 64 MS( 0, CalendarTime::MAX_YEAR, 85, 150, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 130, 18, 8, 4, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 65 MS( 0, CalendarTime::MAX_YEAR, 11, 60, STR_TOWN_BUILDING_NAME_IGLOO_1, 45, 3, 3, 1, 1, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 66 MS( 0, CalendarTime::MAX_YEAR, 10, 60, STR_TOWN_BUILDING_NAME_TEPEES_1, 45, 3, 3, 1, 1, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 67 MS( 0, CalendarTime::MAX_YEAR, 67, 140, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 130, 22, 8, 4, 4, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_FIZZY_DRINKS), // 68 MS( 0, CalendarTime::MAX_YEAR, 86, 145, STR_TOWN_BUILDING_NAME_SHOPS_AND_OFFICES_1, 130, 23, 8, 4, 4, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_FIZZY_DRINKS), // 69 MS( 0, CalendarTime::MAX_YEAR, 95, 165, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, 130, 28, 8, 4, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 6A MS( 0, CalendarTime::MAX_YEAR, 30, 90, STR_TOWN_BUILDING_NAME_STATUE_1, 70, 10, 4, 1, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 6B MS( 0, CalendarTime::MAX_YEAR, 25, 75, STR_TOWN_BUILDING_NAME_TEAPOT_HOUSE_1, 65, 8, 3, 1, 2, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_CANDY), // 6C MS( 0, CalendarTime::MAX_YEAR, 18, 85, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1, 95, 7, 3, 2, 4, BuildingFlag::Size1x1, - HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1, + HouseZones({HouseZone::ClimateToyland, HouseZone::TownCentre, HouseZone::TownInnerSuburb, HouseZone::TownOuterSuburb, HouseZone::TownOutskirt, HouseZone::TownEdge}), CT_PASSENGERS, CT_MAIL, CT_FIZZY_DRINKS), // 6D }; #undef MS diff --git a/src/town.h b/src/town.h index 1c6e134db6..ba4310ad1f 100644 --- a/src/town.h +++ b/src/town.h @@ -42,7 +42,7 @@ struct TownCache { uint32_t population = 0; ///< Current population of people TrackedViewportSign sign{}; ///< Location of name sign, UpdateVirtCoord updates this PartsOfSubsidy part_of_subsidy{}; ///< Is this town a source/destination of a subsidy? - std::array squared_town_zone_radius{}; ///< UpdateTownRadius updates this given the house count + std::array squared_town_zone_radius{}; ///< UpdateTownRadius updates this given the house count BuildingCounts building_counts{}; ///< The number of each type of building in the town auto operator<=>(const TownCache &) const = default; @@ -228,7 +228,7 @@ void UpdateTownRadius(Town *t); CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlags flags); Town *ClosestTownFromTile(TileIndex tile, uint threshold); void ChangeTownRating(Town *t, int add, int max, DoCommandFlags flags); -HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile); +HouseZone GetTownRadiusGroup(const Town *t, TileIndex tile); void SetTownRatingTestMode(bool mode); TownActions GetMaskOfTownActions(CompanyID cid, const Town *t); bool GenerateTowns(TownLayout layout); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 2ccda65ba4..5f07725944 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1943,7 +1943,7 @@ static bool GrowTown(Town *t) */ void UpdateTownRadius(Town *t) { - static const std::array, 23> _town_squared_town_zone_radius_data = {{ + static const std::array, 23> _town_squared_town_zone_radius_data = {{ { 4, 0, 0, 0, 0}, // 0 { 16, 0, 0, 0, 0}, { 25, 0, 0, 0, 0}, @@ -1976,11 +1976,11 @@ void UpdateTownRadius(Town *t) /* Actually we are proportional to sqrt() but that's right because we are covering an area. * The offsets are to make sure the radii do not decrease in size when going from the table * to the calculated value.*/ - t->cache.squared_town_zone_radius[HZB_TOWN_EDGE] = mass * 15 - 40; - t->cache.squared_town_zone_radius[HZB_TOWN_OUTSKIRT] = mass * 9 - 15; - t->cache.squared_town_zone_radius[HZB_TOWN_OUTER_SUBURB] = 0; - t->cache.squared_town_zone_radius[HZB_TOWN_INNER_SUBURB] = mass * 5 - 5; - t->cache.squared_town_zone_radius[HZB_TOWN_CENTRE] = mass * 3 + 5; + t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)] = mass * 15 - 40; + t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownOutskirt)] = mass * 9 - 15; + t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownOuterSuburb)] = 0; + t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownInnerSuburb)] = mass * 5 - 5; + t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownCentre)] = mass * 3 + 5; } } @@ -2304,6 +2304,21 @@ static TileIndex FindNearestGoodCoastalTownSpot(TileIndex tile, TownLayout layou return INVALID_TILE; } +/** + * Get the HouseZones climate mask for the current landscape type. + * @return HouseZones climate mask. + */ +HouseZones GetClimateMaskForLandscape() +{ + switch (_settings_game.game_creation.landscape) { + case LandscapeType::Temperate: return HouseZone::ClimateTemperate; + case LandscapeType::Arctic: return {HouseZone::ClimateSubarcticAboveSnow, HouseZone::ClimateSubarcticBelowSnow}; + case LandscapeType::Tropic: return HouseZone::ClimateSubtropic; + case LandscapeType::Toyland: return HouseZone::ClimateToyland; + default: NOT_REACHED(); + } +} + /** * Create a random town somewhere in the world. * @param attempts How many times should we try? @@ -2426,15 +2441,15 @@ bool GenerateTowns(TownLayout layout) * @param tile TileIndex where town zone needs to be found. * @return the bit position of the given zone, as defined in HouseZones. */ -HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile) +HouseZone GetTownRadiusGroup(const Town *t, TileIndex tile) { uint dist = DistanceSquare(tile, t->xy); - if (t->fund_buildings_months && dist <= 25) return HZB_TOWN_CENTRE; + if (t->fund_buildings_months != 0 && dist <= 25) return HouseZone::TownCentre; - HouseZonesBits smallest = HZB_TOWN_EDGE; - for (HouseZonesBits i = HZB_BEGIN; i < HZB_END; i++) { - if (dist < t->cache.squared_town_zone_radius[i]) smallest = i; + HouseZone smallest = HouseZone::TownEdge; + for (HouseZone i : HZ_ZONE_ALL) { + if (dist < t->cache.squared_town_zone_radius[to_underlying(i)]) smallest = i; } return smallest; @@ -2733,13 +2748,14 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile) /* Get the town zone type of the current tile, as well as the climate. * This will allow to easily compare with the specs of the new house to build */ - HouseZonesBits rad = GetTownRadiusGroup(t, tile); + HouseZones zones = GetTownRadiusGroup(t, tile); - /* Above snow? */ - int land = to_underlying(_settings_game.game_creation.landscape); - if (_settings_game.game_creation.landscape == LandscapeType::Arctic && maxz > HighestSnowLine()) land = -1; - - uint bitmask = (1 << rad) + (1 << (land + 12)); + switch (_settings_game.game_creation.landscape) { + case LandscapeType::Temperate: zones.Set(HouseZone::ClimateTemperate); break; + case LandscapeType::Arctic: zones.Set(maxz > HighestSnowLine() ? HouseZone::ClimateSubarcticAboveSnow : HouseZone::ClimateSubarcticBelowSnow); break; + case LandscapeType::Tropic: zones.Set(HouseZone::ClimateSubtropic); break; + case LandscapeType::Toyland: zones.Set(HouseZone::ClimateToyland); break; + } /* bits 0-4 are used * bits 11-15 are used @@ -2752,7 +2768,7 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile) /* Generate a list of all possible houses that can be built. */ for (const auto &hs : HouseSpec::Specs()) { /* Verify that the candidate house spec matches the current tile status */ - if ((~hs.building_availability & bitmask) != 0 || !hs.enabled || hs.grf_prop.override_id != INVALID_HOUSE_ID) continue; + if (!hs.building_availability.All(zones) || !hs.enabled || hs.grf_prop.override_id != INVALID_HOUSE_ID) continue; /* Don't let these counters overflow. Global counters are 32bit, there will never be that many houses. */ if (hs.class_id != HOUSE_NO_CLASS) { @@ -3651,9 +3667,9 @@ static void ForAllStationsNearTown(Town *t, Func func) * The true radius is not stored or calculated anywhere, only the squared radius. */ /* The efficiency of this search might be improved for large towns and many stations on the map, * by using an integer square root approximation giving a value not less than the true square root. */ - uint search_radius = t->cache.squared_town_zone_radius[HZB_TOWN_EDGE] / 2; + uint search_radius = t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)] / 2; ForAllStationsRadius(t->xy, search_radius, [&](const Station * st) { - if (DistanceSquare(st->xy, t->xy) <= t->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) { + if (DistanceSquare(st->xy, t->xy) <= t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) { func(st); } }); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index e0f5bea8ea..6f0ac5f9bf 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -1421,13 +1421,7 @@ public: */ void SetClimateMask() { - switch (_settings_game.game_creation.landscape) { - case LandscapeType::Temperate: this->climate_mask = HZ_TEMP; break; - case LandscapeType::Arctic: this->climate_mask = HZ_SUBARTC_ABOVE | HZ_SUBARTC_BELOW; break; - case LandscapeType::Tropic: this->climate_mask = HZ_SUBTROPIC; break; - case LandscapeType::Toyland: this->climate_mask = HZ_TOYLND; break; - default: NOT_REACHED(); - } + this->climate_mask = GetClimateMaskForLandscape(); /* In some cases, not all 'classes' (house zones) have distinct houses, so we need to disable those. * As we need to check all types, and this cannot change with the picker window open, pre-calculate it. @@ -1455,7 +1449,7 @@ public: /* Houses do not have classes like NewGRFClass. We'll make up fake classes based on town zone * availability instead. */ - static inline const std::array zone_names = { + static inline const std::array zone_names = { STR_HOUSE_PICKER_CLASS_ZONE1, STR_HOUSE_PICKER_CLASS_ZONE2, STR_HOUSE_PICKER_CLASS_ZONE3, @@ -1500,16 +1494,19 @@ public: int GetSelectedType() const override { return sel_type; } void SetSelectedType(int id) const override { sel_type = id; } + static HouseZone GetHouseZoneFromClassId(int cls_id) { return static_cast(to_underlying(HouseZone::TownEdge) + cls_id); } + static int GetClassIdFromHouseZone(HouseZones zones) { return FindFirstBit((zones & HZ_ZONE_ALL).base()) - to_underlying(HouseZone::TownEdge); } + StringID GetTypeName(int cls_id, int id) const override { const HouseSpec *spec = HouseSpec::Get(id); if (spec == nullptr) return INVALID_STRING_ID; if (!spec->enabled) return INVALID_STRING_ID; - if ((spec->building_availability & climate_mask) == 0) return INVALID_STRING_ID; - if (!HasBit(spec->building_availability, cls_id)) return INVALID_STRING_ID; + if (!spec->building_availability.Any(climate_mask)) return INVALID_STRING_ID; + if (!spec->building_availability.Test(GetHouseZoneFromClassId(cls_id))) return INVALID_STRING_ID; for (int i = 0; i < cls_id; i++) { /* Don't include if it's already included in an earlier zone. */ - if (HasBit(spec->building_availability, i)) return INVALID_STRING_ID; + if (spec->building_availability.Test(GetHouseZoneFromClassId(i))) return INVALID_STRING_ID; } return GetHouseName(spec); @@ -1520,11 +1517,11 @@ public: const auto *spec = HouseSpec::Get(id); if (spec == nullptr) return {}; if (!spec->enabled) return {}; - if ((spec->building_availability & climate_mask) == 0) return {}; - if (!HasBit(spec->building_availability, cls_id)) return {}; + if (!spec->building_availability.Any(climate_mask)) return {}; + if (!spec->building_availability.Test(GetHouseZoneFromClassId(cls_id))) return {}; for (int i = 0; i < cls_id; i++) { /* Don't include if it's already included in an earlier zone. */ - if (HasBit(spec->building_availability, i)) return {}; + if (spec->building_availability.Test(GetHouseZoneFromClassId(i))) return {}; } return spec->badges; @@ -1548,7 +1545,7 @@ public: if (*it == 0) continue; HouseID house = static_cast(std::distance(id_count.begin(), it)); const HouseSpec *hs = HouseSpec::Get(house); - int class_index = FindFirstBit(hs->building_availability & HZ_ZONALL); + int class_index = GetClassIdFromHouseZone(hs->building_availability); items.insert({0, house, class_index, house}); } } @@ -1569,7 +1566,7 @@ public: /* Not preset, hide from UI. */ dst.insert({item.grfid, item.local_id, -1, -1}); } else { - int class_index = FindFirstBit(it->building_availability & HZ_ZONALL); + int class_index = GetClassIdFromHouseZone(it->building_availability); dst.insert( {item.grfid, item.local_id, class_index, it->Index()}); } } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 1188556463..458fa5b785 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -281,7 +281,7 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t company = OWNER_TOWN; /* If we are not within a town, we are not owned by the town */ - if (town == nullptr || DistanceSquare(tile_start, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) { + if (town == nullptr || DistanceSquare(tile_start, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) { company = OWNER_NONE; } } @@ -635,7 +635,7 @@ CommandCost CmdBuildTunnel(DoCommandFlags flags, TileIndex start_tile, Transport company = OWNER_TOWN; /* If we are not within a town, we are not owned by the town */ - if (town == nullptr || DistanceSquare(start_tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) { + if (town == nullptr || DistanceSquare(start_tile, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) { company = OWNER_NONE; } }