/**
* Find the nearest hangar to v
* INVALID_STATION is returned, if the company does not have any suitable
* airports (like helipads only)
* @param v vehicle looking for a hangar
* @return the StationID if one is found, otherwise, INVALID_STATION
*/
static StationID FindNearestHangar(const Aircraft *v)
{
const Station *st;
uint best = 0;
StationID index = INVALID_STATION;
TileIndex vtile = TileVirtXY(v->x_pos, v->y_pos);
const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
FOR_ALL_STATIONS(st) {
if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT) || !st->airport.HasHangar()) continue;
const AirportFTAClass *afc = st->airport.GetFTA();
/* don't crash the plane if we know it can't land at the airport */
if ((afc->flags & AirportFTAClass::SHORT_STRIP) && (avi->subtype & AIR_FAST) &&
(!_cheats.no_jetcrash.value || !_settings_game.vehicle.large_plane_on_short_runway)) continue;
/* the plane won't land at any helicopter station */
if (!(afc->flags & AirportFTAClass::AIRPLANES) && (avi->subtype & AIR_CTOL)) continue;
/* v->tile can't be used here, when aircraft is flying v->tile is set to 0 */
uint distance = DistanceSquare(vtile, st->airport.tile);
uint max_range = v->acache.cached_max_range_sqr;
if (max_range != 0) {
/* Determine destinations */
const Station *cur_dest = GetTargetAirportIfValid(v);
const Station *next_dest;
if (v->current_order.IsType(OT_GOTO_STATION) ||
v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDepotActionType() != ODATFB_NEAREST_DEPOT) {
next_dest = Station::GetIfValid(v->current_order.GetDestination());
if (next_dest == cur_dest) next_dest = Station::GetIfValid(v->last_station_visited);
} else {
next_dest = Station::GetIfValid(v->GetNextStoppingStation().value);
}
/* Check if our current and next (or previous) destinations can be reached from the depot airport. */
uint cur_dist = cur_dest != NULL ? DistanceSquare(st->airport.tile, cur_dest->airport.tile) : UINT_MAX;
uint next_dist = next_dest != NULL || next_dest->airport.tile != INVALID_TILE ? DistanceSquare(st->airport.tile, next_dest->airport.tile) : UINT_MAX;
if (cur_dist != UINT_MAX && next_dist != UINT_MAX && (cur_dist > max_range || next_dist > max_range)) continue;
if (cur_dist != UINT_MAX && next_dist == UINT_MAX && cur_dist > max_range) continue;
if (cur_dist == UINT_MAX && next_dist != UINT_MAX && next_dist > max_range) continue;
}
if (distance < best || index == INVALID_STATION) {
best = distance;
index = st->index;
}
}
return index;
}