Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: AirportGetNearestTown incorrectly assumed first TileIterator result was origin. #11565

Merged
merged 1 commit into from Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/script/api/script_airport.cpp
Expand Up @@ -139,7 +139,7 @@
if (_settings_game.economy.station_noise_level) {
AirportTileTableIterator it(as->table[0], tile);
uint dist;
AirportGetNearestTown(as, it, dist);
AirportGetNearestTown(as, tile, it, dist);
return GetAirportNoiseLevelForDistance(as, dist);
}

Expand All @@ -155,7 +155,7 @@
if (!as->IsWithinMapBounds(0, tile)) return INVALID_TOWN;

uint dist;
return AirportGetNearestTown(as, AirportTileTableIterator(as->table[0], tile), dist)->index;
return AirportGetNearestTown(as, tile, AirportTileTableIterator(as->table[0], tile), dist)->index;
}

/* static */ SQInteger ScriptAirport::GetMaintenanceCostFactor(AirportType type)
Expand Down
15 changes: 9 additions & 6 deletions src/station_cmd.cpp
Expand Up @@ -2303,25 +2303,28 @@ 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 tile origin tile (top corner of the airport)
* @param it An iterator over all airport tiles
* @param[out] mindist Minimum distance to town
* @return nearest town to airport
*/
Town *AirportGetNearestTown(const AirportSpec *as, const TileIterator &it, uint &mindist)
Town *AirportGetNearestTown(const AirportSpec *as, TileIndex tile, const TileIterator &it, uint &mindist)
{
assert(Town::GetNumItems() > 0);

Town *nearest = nullptr;

uint perimeter_min_x = TileX(it);
uint perimeter_min_y = TileY(it);
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;

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));
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;
Expand Down Expand Up @@ -2349,7 +2352,7 @@ void UpdateAirportsNoise()
const AirportSpec *as = st->airport.GetSpec();
AirportTileIterator it(st);
uint dist;
Town *nearest = AirportGetNearestTown(as, it, dist);
Town *nearest = AirportGetNearestTown(as, st->airport.tile, it, dist);
nearest->noise_reached += GetAirportNoiseLevelForDistance(as, dist);
}
}
Expand Down Expand Up @@ -2399,7 +2402,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_iter, dist);
Town *nearest = AirportGetNearestTown(as, tile, tile_iter, dist);
uint newnoise_level = GetAirportNoiseLevelForDistance(as, dist);

/* Check if local auth would allow a new airport */
Expand Down Expand Up @@ -2527,7 +2530,7 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
* need of recalculation */
AirportTileIterator it(st);
uint dist;
Town *nearest = AirportGetNearestTown(as, it, dist);
Town *nearest = AirportGetNearestTown(as, st->airport.tile, it, dist);
nearest->noise_reached -= GetAirportNoiseLevelForDistance(as, dist);

if (_settings_game.economy.station_noise_level) {
Expand Down
2 changes: 1 addition & 1 deletion src/station_cmd.h
Expand Up @@ -16,7 +16,7 @@
enum StationClassID : byte;
enum RoadStopClassID : byte;

extern Town *AirportGetNearestTown(const struct AirportSpec *as, const TileIterator &it, uint &mindist);
extern Town *AirportGetNearestTown(const struct AirportSpec *as, TileIndex tile, const TileIterator &it, uint &mindist);
extern uint8_t GetAirportNoiseLevelForDistance(const struct AirportSpec *as, uint distance);

CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_type, byte layout, StationID station_to_join, bool allow_adjacent);
Expand Down