mirror of https://github.com/OpenTTD/OpenTTD
(svn r15278) -Fix [FS#2332]: test noise limit of nearest town instead of st->town
parent
7f9c91901e
commit
659989af45
|
@ -115,6 +115,7 @@
|
||||||
|
|
||||||
/* static */ int AIAirport::GetNoiseLevelIncrease(TileIndex tile, AirportType type)
|
/* static */ int AIAirport::GetNoiseLevelIncrease(TileIndex tile, AirportType type)
|
||||||
{
|
{
|
||||||
|
extern Town *AirportGetNearestTown(const AirportFTAClass *afc, TileIndex airport_tile);
|
||||||
extern uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile);
|
extern uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile);
|
||||||
|
|
||||||
if (!::IsValidTile(tile)) return -1;
|
if (!::IsValidTile(tile)) return -1;
|
||||||
|
@ -122,7 +123,7 @@
|
||||||
|
|
||||||
if (_settings_game.economy.station_noise_level) {
|
if (_settings_game.economy.station_noise_level) {
|
||||||
const AirportFTAClass *afc = ::GetAirport(type);
|
const AirportFTAClass *afc = ::GetAirport(type);
|
||||||
const Town *t = ::ClosestTownFromTile(tile, UINT_MAX);
|
const Town *t = AirportGetNearestTown(afc, tile);
|
||||||
return GetAirportNoiseLevelForTown(afc, t->xy, tile);
|
return GetAirportNoiseLevelForTown(afc, t->xy, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1751,6 +1751,32 @@ static const byte * const _airport_sections[] = {
|
||||||
_airport_sections_helistation // Helistation
|
_airport_sections_helistation // Helistation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the minimal distance from town's xy to any airport's tile.
|
||||||
|
* @param afc airport's description
|
||||||
|
* @param town_tile town's tile (t->xy)
|
||||||
|
* @param airport_tile st->airport_tile
|
||||||
|
* @return minimal manhattan distance from town_tile to any airport's tile
|
||||||
|
*/
|
||||||
|
static uint GetMinimalAirportDistanceToTile(const AirportFTAClass *afc, TileIndex town_tile, TileIndex airport_tile)
|
||||||
|
{
|
||||||
|
uint ttx = TileX(town_tile); // X, Y of town
|
||||||
|
uint tty = TileY(town_tile);
|
||||||
|
|
||||||
|
uint atx = TileX(airport_tile); // X, Y of northern airport corner
|
||||||
|
uint aty = TileY(airport_tile);
|
||||||
|
|
||||||
|
uint btx = TileX(airport_tile) + afc->size_x - 1; // X, Y of southern corner
|
||||||
|
uint bty = TileY(airport_tile) + afc->size_y - 1;
|
||||||
|
|
||||||
|
/* if ttx < atx, dx = atx - ttx
|
||||||
|
* if atx <= ttx <= btx, dx = 0
|
||||||
|
* else, dx = ttx - btx (similiar for dy) */
|
||||||
|
uint dx = ttx < atx ? atx - ttx : (ttx <= btx ? 0 : ttx - btx);
|
||||||
|
uint dy = tty < aty ? aty - tty : (tty <= bty ? 0 : tty - bty);
|
||||||
|
|
||||||
|
return dx + dy;
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a possible noise reduction factor based on distance from town center.
|
/** Get a possible noise reduction factor based on distance from town center.
|
||||||
* The further you get, the less noise you generate.
|
* The further you get, the less noise you generate.
|
||||||
|
@ -1762,44 +1788,11 @@ static const byte * const _airport_sections[] = {
|
||||||
*/
|
*/
|
||||||
uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile)
|
uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile)
|
||||||
{
|
{
|
||||||
struct TileIndexDistance {
|
|
||||||
TileIndex index;
|
|
||||||
uint distance;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
|
/* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
|
||||||
* So no need to go any further*/
|
* So no need to go any further*/
|
||||||
if (afc->noise_level < 2) return afc->noise_level;
|
if (afc->noise_level < 2) return afc->noise_level;
|
||||||
|
|
||||||
uint distance;
|
uint distance = GetMinimalAirportDistanceToTile(afc, town_tile, tile);
|
||||||
|
|
||||||
/* Find the airport-to-be's closest corner to the town */
|
|
||||||
if (afc->size_x == 1 && afc->size_y == 1) {
|
|
||||||
distance = DistanceManhattan(town_tile, tile); // ont tile, one corner, it's THE corner
|
|
||||||
} else {
|
|
||||||
/* calculate manhattan distance to town of each side of the airport */
|
|
||||||
TileIndexDistance dist[4]; ///< Array that will contain all 4 corners in TileIndex and distance
|
|
||||||
uint min_tile = UINT_MAX; ///< Sentinel value
|
|
||||||
uint min_indice = 4;
|
|
||||||
|
|
||||||
/* Based on the size of the airport, establish location of each corner*/
|
|
||||||
dist[0].index = tile; // north tile
|
|
||||||
dist[1].index = TileAddWrap(tile, afc->size_x - 1, afc->size_y - 1); // south tile
|
|
||||||
dist[2].index = TileAddWrap(tile, afc->size_x - 1, 0); // west tile
|
|
||||||
dist[3].index = TileAddWrap(tile, 0, afc->size_y - 1); //east tile
|
|
||||||
|
|
||||||
/* now, go and find the smallest one, thus the closest to town */
|
|
||||||
for (uint i = 0; i < 4; i++) {
|
|
||||||
dist[i].distance = DistanceManhattan(town_tile, dist[i].index);
|
|
||||||
|
|
||||||
if (dist[i].distance < min_tile) {
|
|
||||||
min_tile = dist[i].distance; // here's a new candidate
|
|
||||||
min_indice = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
distance = dist[min_indice].distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
|
/* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
|
||||||
* adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
|
* adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
|
||||||
|
@ -1816,6 +1809,31 @@ uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_til
|
||||||
return noise_reduction >= afc->noise_level ? 1 : afc->noise_level - noise_reduction;
|
return noise_reduction >= afc->noise_level ? 1 : afc->noise_level - noise_reduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 afc airport's description
|
||||||
|
* @param airport_tile st->airport_tile
|
||||||
|
* @return nearest town to airport
|
||||||
|
*/
|
||||||
|
Town *AirportGetNearestTown(const AirportFTAClass *afc, TileIndex airport_tile)
|
||||||
|
{
|
||||||
|
Town *t, *nearest = NULL;
|
||||||
|
uint add = afc->size_x + afc->size_y - 2; // GetMinimalAirportDistanceToTile can differ from DistanceManhattan by this much
|
||||||
|
uint mindist = UINT_MAX - add; // prevent overflow
|
||||||
|
FOR_ALL_TOWNS(t) {
|
||||||
|
if (DistanceManhattan(t->xy, airport_tile) < mindist + add) { // avoid calling GetMinimalAirportDistanceToTile too often
|
||||||
|
uint dist = GetMinimalAirportDistanceToTile(afc, t->xy, airport_tile);
|
||||||
|
if (dist < mindist) {
|
||||||
|
nearest = t;
|
||||||
|
mindist = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Recalculate the noise generated by the airports of each town */
|
/** Recalculate the noise generated by the airports of each town */
|
||||||
void UpdateAirportsNoise()
|
void UpdateAirportsNoise()
|
||||||
|
@ -1827,7 +1845,9 @@ void UpdateAirportsNoise()
|
||||||
|
|
||||||
FOR_ALL_STATIONS(st) {
|
FOR_ALL_STATIONS(st) {
|
||||||
if (st->airport_tile != INVALID_TILE) {
|
if (st->airport_tile != INVALID_TILE) {
|
||||||
st->town->noise_reached += GetAirportNoiseLevelForTown(GetAirport(st->airport_type), st->town->xy, st->airport_tile);
|
const AirportFTAClass *afc = GetAirport(st->airport_type);
|
||||||
|
Town *nearest = AirportGetNearestTown(afc, st->airport_tile);
|
||||||
|
nearest->noise_reached += GetAirportNoiseLevelForTown(afc, nearest->xy, st->airport_tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1871,14 +1891,15 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2,
|
||||||
if (CmdFailed(cost)) return cost;
|
if (CmdFailed(cost)) return cost;
|
||||||
|
|
||||||
/* Go get the final noise level, that is base noise minus factor from distance to town center */
|
/* Go get the final noise level, that is base noise minus factor from distance to town center */
|
||||||
uint newnoise_level = GetAirportNoiseLevelForTown(afc, t->xy, tile);
|
Town *nearest = AirportGetNearestTown(afc, tile);
|
||||||
|
uint newnoise_level = GetAirportNoiseLevelForTown(afc, nearest->xy, tile);
|
||||||
|
|
||||||
/* Check if local auth would allow a new airport */
|
/* Check if local auth would allow a new airport */
|
||||||
bool authority_refused;
|
bool authority_refused;
|
||||||
|
|
||||||
if (_settings_game.economy.station_noise_level) {
|
if (_settings_game.economy.station_noise_level) {
|
||||||
/* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
|
/* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
|
||||||
authority_refused = (t->noise_reached + newnoise_level) > t->MaxTownNoise();
|
authority_refused = (nearest->noise_reached + newnoise_level) > nearest->MaxTownNoise();
|
||||||
} else {
|
} else {
|
||||||
uint num = 0;
|
uint num = 0;
|
||||||
const Station *st;
|
const Station *st;
|
||||||
|
@ -1939,7 +1960,7 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2,
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
/* Always add the noise, so there will be no need to recalculate when option toggles */
|
/* Always add the noise, so there will be no need to recalculate when option toggles */
|
||||||
st->town->noise_reached += newnoise_level;
|
nearest->noise_reached += newnoise_level;
|
||||||
|
|
||||||
st->airport_tile = tile;
|
st->airport_tile = tile;
|
||||||
st->AddFacility(FACIL_AIRPORT, tile);
|
st->AddFacility(FACIL_AIRPORT, tile);
|
||||||
|
@ -2020,7 +2041,8 @@ static CommandCost RemoveAirport(Station *st, uint32 flags)
|
||||||
/* Go get the final noise level, that is base noise minus factor from distance to town center.
|
/* Go get the final noise level, that is base noise minus factor from distance to town center.
|
||||||
* And as for construction, always remove it, even if the patch is not set, in order to avoid the
|
* And as for construction, always remove it, even if the patch is not set, in order to avoid the
|
||||||
* need of recalculation */
|
* need of recalculation */
|
||||||
st->town->noise_reached -= GetAirportNoiseLevelForTown(afc, st->town->xy, tile);
|
Town *nearest = AirportGetNearestTown(afc, tile);
|
||||||
|
nearest->noise_reached -= GetAirportNoiseLevelForTown(afc, nearest->xy, tile);
|
||||||
|
|
||||||
st->rect.AfterRemoveRect(st, tile, w, h);
|
st->rect.AfterRemoveRect(st, tile, w, h);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue