|
|
|
@ -2303,28 +2303,32 @@ uint8_t GetAirportNoiseLevelForDistance(const AirportSpec *as, uint distance)
|
|
|
|
|
* Finds the town nearest to given airport. Based on minimal manhattan distance to any airport's tile.
|
|
|
|
|
* If two towns have the same distance, town with lower index is returned.
|
|
|
|
|
* @param as airport's description
|
|
|
|
|
* @param rotation airport's rotation
|
|
|
|
|
* @param tile origin tile (top corner of the airport)
|
|
|
|
|
* @param it An iterator over all airport tiles
|
|
|
|
|
* @param it An iterator over all airport tiles (consumed)
|
|
|
|
|
* @param[out] mindist Minimum distance to town
|
|
|
|
|
* @return nearest town to airport
|
|
|
|
|
*/
|
|
|
|
|
Town *AirportGetNearestTown(const AirportSpec *as, TileIndex tile, const TileIterator &it, uint &mindist)
|
|
|
|
|
Town *AirportGetNearestTown(const AirportSpec *as, Direction rotation, TileIndex tile, TileIterator &&it, uint &mindist)
|
|
|
|
|
{
|
|
|
|
|
assert(Town::GetNumItems() > 0);
|
|
|
|
|
|
|
|
|
|
Town *nearest = nullptr;
|
|
|
|
|
|
|
|
|
|
auto width = as->size_x;
|
|
|
|
|
auto height = as->size_y;
|
|
|
|
|
if (rotation == DIR_E || rotation == DIR_W) std::swap(width, height);
|
|
|
|
|
|
|
|
|
|
uint perimeter_min_x = TileX(tile);
|
|
|
|
|
uint perimeter_min_y = TileY(tile);
|
|
|
|
|
uint perimeter_max_x = perimeter_min_x + as->size_x - 1;
|
|
|
|
|
uint perimeter_max_y = perimeter_min_y + as->size_y - 1;
|
|
|
|
|
uint perimeter_max_x = perimeter_min_x + width - 1;
|
|
|
|
|
uint perimeter_max_y = perimeter_min_y + height - 1;
|
|
|
|
|
|
|
|
|
|
mindist = UINT_MAX - 1; // prevent overflow
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<TileIterator> copy(it.Clone());
|
|
|
|
|
for (TileIndex cur_tile = *copy; cur_tile != INVALID_TILE; cur_tile = ++*copy) {
|
|
|
|
|
assert(IsInsideBS(TileX(cur_tile), perimeter_min_x, as->size_x));
|
|
|
|
|
assert(IsInsideBS(TileY(cur_tile), perimeter_min_y, as->size_y));
|
|
|
|
|
for (TileIndex cur_tile = *it; cur_tile != INVALID_TILE; cur_tile = ++it) {
|
|
|
|
|
assert(IsInsideBS(TileX(cur_tile), perimeter_min_x, width));
|
|
|
|
|
assert(IsInsideBS(TileY(cur_tile), perimeter_min_y, height));
|
|
|
|
|
if (TileX(cur_tile) == perimeter_min_x || TileX(cur_tile) == perimeter_max_x || TileY(cur_tile) == perimeter_min_y || TileY(cur_tile) == perimeter_max_y) {
|
|
|
|
|
Town *t = CalcClosestTownFromTile(cur_tile, mindist + 1);
|
|
|
|
|
if (t == nullptr) continue;
|
|
|
|
@ -2341,6 +2345,18 @@ Town *AirportGetNearestTown(const AirportSpec *as, TileIndex tile, const TileIte
|
|
|
|
|
return nearest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Finds the town nearest to given existing airport. Based on minimal manhattan distance to any airport's tile.
|
|
|
|
|
* If two towns have the same distance, town with lower index is returned.
|
|
|
|
|
* @param station existing station with airport
|
|
|
|
|
* @param[out] mindist Minimum distance to town
|
|
|
|
|
* @return nearest town to airport
|
|
|
|
|
*/
|
|
|
|
|
static Town *AirportGetNearestTown(const Station *st, uint &mindist)
|
|
|
|
|
{
|
|
|
|
|
return AirportGetNearestTown(st->airport.GetSpec(), st->airport.rotation, st->airport.tile, AirportTileIterator(st), mindist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Recalculate the noise generated by the airports of each town */
|
|
|
|
|
void UpdateAirportsNoise()
|
|
|
|
@ -2349,11 +2365,9 @@ void UpdateAirportsNoise()
|
|
|
|
|
|
|
|
|
|
for (const Station *st : Station::Iterate()) {
|
|
|
|
|
if (st->airport.tile != INVALID_TILE && st->airport.type != AT_OILRIG) {
|
|
|
|
|
const AirportSpec *as = st->airport.GetSpec();
|
|
|
|
|
AirportTileIterator it(st);
|
|
|
|
|
uint dist;
|
|
|
|
|
Town *nearest = AirportGetNearestTown(as, st->airport.tile, it, dist);
|
|
|
|
|
nearest->noise_reached += GetAirportNoiseLevelForDistance(as, dist);
|
|
|
|
|
Town *nearest = AirportGetNearestTown(st, dist);
|
|
|
|
|
nearest->noise_reached += GetAirportNoiseLevelForDistance(st->airport.GetSpec(), dist);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2402,7 +2416,7 @@ CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_ty
|
|
|
|
|
|
|
|
|
|
/* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */
|
|
|
|
|
uint dist;
|
|
|
|
|
Town *nearest = AirportGetNearestTown(as, tile, tile_iter, dist);
|
|
|
|
|
Town *nearest = AirportGetNearestTown(as, rotation, tile, std::move(tile_iter), dist);
|
|
|
|
|
uint newnoise_level = GetAirportNoiseLevelForDistance(as, dist);
|
|
|
|
|
|
|
|
|
|
/* Check if local auth would allow a new airport */
|
|
|
|
@ -2524,14 +2538,12 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
|
|
|
|
|
CloseWindowById(WC_VEHICLE_DEPOT, tile_cur);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const AirportSpec *as = st->airport.GetSpec();
|
|
|
|
|
/* The noise level is the noise from the airport and reduce it to account for the distance to the town center.
|
|
|
|
|
* And as for construction, always remove it, even if the setting is not set, in order to avoid the
|
|
|
|
|
* need of recalculation */
|
|
|
|
|
AirportTileIterator it(st);
|
|
|
|
|
uint dist;
|
|
|
|
|
Town *nearest = AirportGetNearestTown(as, st->airport.tile, it, dist);
|
|
|
|
|
nearest->noise_reached -= GetAirportNoiseLevelForDistance(as, dist);
|
|
|
|
|
Town *nearest = AirportGetNearestTown(st, dist);
|
|
|
|
|
nearest->noise_reached -= GetAirportNoiseLevelForDistance(st->airport.GetSpec(), dist);
|
|
|
|
|
|
|
|
|
|
if (_settings_game.economy.station_noise_level) {
|
|
|
|
|
SetWindowDirty(WC_TOWN_VIEW, nearest->index);
|
|
|
|
|