+}
+
+void
+FGAIManager::bind() {
+ root = globals->get_props()->getNode("ai/models", true);
+ root->tie("count", SGRawValueMethods<FGAIManager, int>(*this,
+ &FGAIManager::getNumAiObjects));
+}
+
+void
+FGAIManager::unbind() {
+ root->untie("count");
+}
+
+void
+FGAIManager::update(double dt) {
+ // initialize these for finding nearest thermals
+ range_nearest = 10000.0;
+ strength = 0.0;
+
+ if (!enabled)
+ return;
+
+ FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
+ _dt = dt;
+
+ ai_list_iterator ai_list_itr = ai_list.begin();
+
+ while(ai_list_itr != ai_list.end()) {
+
+ if ((*ai_list_itr)->getDie()) {
+ tmgr->release((*ai_list_itr)->getID());
+ --mNumAiModels;
+ --(mNumAiTypeModels[(*ai_list_itr)->getType()]);
+ FGAIBase *base = (*ai_list_itr).get();
+ SGPropertyNode *props = base->_getProps();
+
+ props->setBoolValue("valid", false);
+ base->unbind();
+
+ // for backward compatibility reset properties, so that aircraft,
+ // which don't know the <valid> property, keep working
+ // TODO: remove after a while
+ props->setIntValue("id", -1);
+ props->setBoolValue("radar/in-range", false);
+ props->setIntValue("refuel/tanker", false);
+
+ ai_list_itr = ai_list.erase(ai_list_itr);
+ } else {
+ fetchUserState();
+ if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
+ FGAIBase *base = (*ai_list_itr).get();
+ processThermal((FGAIThermal*)base);
+ } else {
+ (*ai_list_itr)->update(_dt);
+ }
+ ++ai_list_itr;
+ }
+ }
+
+ thermal_lift_node->setDoubleValue( strength ); // for thermals
+}
+
+void
+FGAIManager::attach(FGAIBase *model)
+{
+ //unsigned idx = mNumAiTypeModels[model->getType()];
+ const char* typeString = model->getTypeString();
+ SGPropertyNode* root = globals->get_props()->getNode("ai/models", true);
+ SGPropertyNode* p;
+ int i;
+
+ // find free index in the property tree, if we have
+ // more than 10000 mp-aircrafts in the property tree we should optimize the mp-server
+ for (i = 0; i < 10000; i++) {
+ p = root->getNode(typeString, i, false);
+
+ if (!p || !p->getBoolValue("valid", false))
+ break;
+
+ if (p->getIntValue("id",-1)==model->getID()) {
+ p->setStringValue("callsign","***invalid node***"); //debug only, should never set!
+ }
+ }
+
+ p = root->getNode(typeString, i, true);
+ model->setManager(this, p);
+ ai_list.push_back(model);
+ ++mNumAiModels;
+ ++(mNumAiTypeModels[model->getType()]);
+ model->init(model->getType()==FGAIBase::otAircraft
+ || model->getType()==FGAIBase::otMultiplayer
+ || model->getType()==FGAIBase::otStatic);
+ model->bind();
+ p->setBoolValue("valid", true);
+}
+
+void
+FGAIManager::destroyObject( int ID ) {
+ ai_list_iterator ai_list_itr = ai_list.begin();
+
+ while(ai_list_itr != ai_list.end()) {
+
+ if ((*ai_list_itr)->getID() == ID) {
+ --mNumAiModels;
+ --(mNumAiTypeModels[(*ai_list_itr)->getType()]);
+ (*ai_list_itr)->unbind();
+ ai_list_itr = ai_list.erase(ai_list_itr);
+ } else
+ ++ai_list_itr;
+ }
+
+}
+
+int
+FGAIManager::getNumAiObjects(void) const
+{
+ return mNumAiModels;
+}