summaryrefslogtreecommitdiff
path: root/src/station_cmd.cpp
diff options
context:
space:
mode:
authoryexo <yexo@openttd.org>2011-12-09 19:30:30 +0000
committeryexo <yexo@openttd.org>2011-12-09 19:30:30 +0000
commitc9be5d50dac64fe9fefe1a1e85d4eeaf8cc2470c (patch)
treeb9ca1f44038117b6c621e448b6e87e2a2897685b /src/station_cmd.cpp
parent42c4fdf9ab6c9123609afdf5a0dde3f3164795fd (diff)
downloadopenttd-c9be5d50dac64fe9fefe1a1e85d4eeaf8cc2470c.tar.xz
(svn r23461) -Fix: handle a missing airport newgrf as graceful as possible by not crashing when loading such savegame or when an airport is removed
Diffstat (limited to 'src/station_cmd.cpp')
-rw-r--r--src/station_cmd.cpp62
1 files changed, 30 insertions, 32 deletions
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 49711f2e6..27b0c0934 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -2019,24 +2019,17 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
/**
* Computes the minimal distance from town's xy to any airport's tile.
- * @param as airport's description
+ * @param it An iterator over all airport tiles.
* @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 AirportSpec *as, byte layout, TileIndex town_tile, TileIndex airport_tile)
+static uint GetMinimalAirportDistanceToTile(TileIterator &it, TileIndex town_tile)
{
uint mindist = UINT_MAX;
- const AirportTileTable *it = as->table[layout];
- do {
- TileIndex cur_tile = airport_tile + ToTileIndexDiff(it->ti);
-
- uint dist = DistanceManhattan(town_tile, cur_tile);
- if (dist < mindist) {
- mindist = dist;
- }
- } while ((++it)->ti.x != -0x80);
+ for (TileIndex cur_tile = it; cur_tile != INVALID_TILE; cur_tile = ++it) {
+ mindist = min(mindist, DistanceManhattan(town_tile, cur_tile));
+ }
return mindist;
}
@@ -2046,18 +2039,17 @@ static uint GetMinimalAirportDistanceToTile(const AirportSpec *as, byte layout,
* The further you get, the less noise you generate.
* So all those folks at city council can now happily slee... work in their offices
* @param as airport information
+ * @param it An iterator over all airport tiles.
* @param town_tile TileIndex of town's center, the one who will receive the airport's candidature
- * @param tile TileIndex of northern tile of an airport (present or to-be-built), NOT the station tile
* @return the noise that will be generated, according to distance
*/
-uint8 GetAirportNoiseLevelForTown(const AirportSpec *as, byte layout, TileIndex town_tile, TileIndex tile)
+uint8 GetAirportNoiseLevelForTown(const AirportSpec *as, TileIterator &it, TileIndex town_tile)
{
/* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
* So no need to go any further*/
if (as->noise_level < 2) return as->noise_level;
- assert(layout < as->num_table);
- uint distance = GetMinimalAirportDistanceToTile(as, layout, town_tile, tile);
+ uint distance = GetMinimalAirportDistanceToTile(it, town_tile);
/* 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.
@@ -2078,19 +2070,19 @@ uint8 GetAirportNoiseLevelForTown(const AirportSpec *as, byte layout, TileIndex
* 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 airport_tile st->airport.tile
+ * @param it An iterator over all airport tiles
* @return nearest town to airport
*/
-Town *AirportGetNearestTown(const AirportSpec *as, byte layout, TileIndex airport_tile)
+Town *AirportGetNearestTown(const AirportSpec *as, const TileIterator &it)
{
- assert(layout < as->num_table);
-
Town *t, *nearest = NULL;
uint add = as->size_x + as->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(as, layout, t->xy, airport_tile);
+ if (DistanceManhattan(t->xy, it) < mindist + add) { // avoid calling GetMinimalAirportDistanceToTile too often
+ TileIterator *copy = it.Clone();
+ uint dist = GetMinimalAirportDistanceToTile(*copy, t->xy);
+ delete copy;
if (dist < mindist) {
nearest = t;
mindist = dist;
@@ -2113,8 +2105,9 @@ void UpdateAirportsNoise()
FOR_ALL_STATIONS(st) {
if (st->airport.tile != INVALID_TILE && st->airport.type != AT_OILRIG) {
const AirportSpec *as = st->airport.GetSpec();
- Town *nearest = AirportGetNearestTown(as, st->airport.layout, st->airport.tile);
- nearest->noise_reached += GetAirportNoiseLevelForTown(as, st->airport.layout, nearest->xy, st->airport.tile);
+ AirportTileIterator it(st);
+ Town *nearest = AirportGetNearestTown(as, it);
+ nearest->noise_reached += GetAirportNoiseLevelForTown(as, it, nearest->xy);
}
}
}
@@ -2166,8 +2159,9 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
if (cost.Failed()) return cost;
/* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */
- Town *nearest = AirportGetNearestTown(as, layout, tile);
- uint newnoise_level = GetAirportNoiseLevelForTown(as, layout, nearest->xy, tile);
+ AirportTileTableIterator iter(as->table[layout], tile);
+ Town *nearest = AirportGetNearestTown(as, iter);
+ uint newnoise_level = GetAirportNoiseLevelForTown(as, iter, nearest->xy);
/* Check if local auth would allow a new airport */
StringID authority_refuse_message = STR_NULL;
@@ -2309,6 +2303,16 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
if (a->targetairport == st->index && a->state != FLYING) return CMD_ERROR;
}
+ if (flags & DC_EXEC) {
+ 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);
+ Town *nearest = AirportGetNearestTown(as, it);
+ nearest->noise_reached -= GetAirportNoiseLevelForTown(as, it, nearest->xy);
+ }
+
TILE_AREA_LOOP(tile_cur, st->airport) {
if (!st->TileBelongsToAirport(tile_cur)) continue;
@@ -2336,12 +2340,6 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
);
}
- /* 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 */
- Town *nearest = AirportGetNearestTown(as, st->airport.layout, tile);
- nearest->noise_reached -= GetAirportNoiseLevelForTown(as, st->airport.layout, nearest->xy, tile);
-
st->rect.AfterRemoveRect(st, st->airport);
st->airport.Clear();