From 972af3f25415d0e8950c9d868769f9e30371afd9 Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 22 Sep 2017 19:06:34 +0100 Subject: [PATCH] Parking selection avoids AIObjects This ensures AITraffic aircraft avoid parking stands occupied by other AI objects, such as the user or MP aircraft --- src/Airports/dynamics.cxx | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 3ae486401..f7e77ce56 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include "airport.hxx" #include "dynamics.hxx" @@ -152,6 +154,62 @@ FGParking* ParkingAssignment::parking() const //////////////////////////////////////////////////////////////////////////////// +/** + * @brief Helper to cache all AIObject positions near the airport when + * searching for available parkings. This allows us to reject parkings + * which we might not have marked as occupied, but which an object is + * neverthless close to; such as the primary user or MP aircraft. + */ +class NearbyAIObjectCache +{ +public: + NearbyAIObjectCache(FGAirportRef apt) : + m_airport(apt) + {} + + bool isAnythingNear(const SGVec3d& cart, double radiusM) + { + if (!m_populated) { + populate(); + } + + for (auto c : m_cache) { + const double d = dist(cart, c); + if (d < radiusM) { + return true; + } + } + + return false; + } + +private: + void populate() + { +#if !defined(FG_TESTLIB) + SGVec3d cartAirportPos = m_airport->cart(); + FGAIManager* aiManager = globals->get_subsystem(); + for (auto ai : aiManager->get_ai_list()) { + const auto cart = ai->getCartPos(); + + // 20km cutoff from airport centre + if (dist(cartAirportPos, cart) > 20000) { + continue; + } + + m_cache.push_back(cart); + } +#endif + m_populated = true; + } + + bool m_populated = false; + FGAirportRef m_airport; + std::vector m_cache; +}; + +//////////////////////////////////////////////////////////////////////////////// + FGAirportDynamics::FGAirportDynamics(FGAirport * ap): _ap(ap), rwyPrefs(ap), startupController (this), @@ -181,6 +239,7 @@ FGParking* FGAirportDynamics::innerGetAvailableParking(double radius, const stri const string & airline, bool skipEmptyAirlineCode) { + NearbyAIObjectCache nearCache(parent()); const FGParkingList& parkings(parent()->groundNetwork()->allParkings()); for (auto parking : parkings) { if (!isParkingAvailable(parking)) { @@ -205,6 +264,10 @@ FGParking* FGAirportDynamics::innerGetAvailableParking(double radius, const stri } } + if (nearCache.isAnythingNear(parking->cart(), parking->getRadius())) { + continue; + } + setParkingAvailable(parking, false); return parking; }