/** * 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); if (v->acache.cached_max_range_sqr != 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. */ if (next_dest != NULL && next_dest->airport.tile != INVALID_TILE && cur_dest != NULL) { if (DistanceSquare(st->airport.tile, next_dest->airport.tile) > v->acache.cached_max_range_sqr || DistanceSquare(st->airport.tile, cur_dest->airport.tile) > v->acache.cached_max_range_sqr) continue; } else if (next_dest != NULL && next_dest->airport.tile != INVALID_TILE && cur_dest == NULL) { if (DistanceSquare(st->airport.tile, next_dest->airport.tile) > v->acache.cached_max_range_sqr) continue; } else if ((next_dest == NULL || next_dest->airport.tile == INVALID_TILE) && cur_dest != NULL) { if (DistanceSquare(st->airport.tile, cur_dest->airport.tile) > v->acache.cached_max_range_sqr) continue; } } if (distance < best || index == INVALID_STATION) { best = distance; index = st->index; } } return index; }