void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, bool cancelOther) { if (actor == getPlayer()) throw std::runtime_error("Can't add AI packages to player"); // Stop combat when a non-combat AI package is added if (isActualAiPackage(package.getTypeId())) stopCombat(); // We should return a wandering actor back after combat, casting or pursuit. // The same thing for actors without AI packages. // Also there is no point to stack return packages. int currentTypeId = getTypeId(); int newTypeId = package.getTypeId(); if (currentTypeId <= MWMechanics::AiPackage::TypeIdWander && !hasPackage(MWMechanics::AiPackage::TypeIdInternalTravel) && (newTypeId <= MWMechanics::AiPackage::TypeIdCombat || newTypeId == MWMechanics::AiPackage::TypeIdPursue || newTypeId == MWMechanics::AiPackage::TypeIdCast)) { osg::Vec3f dest; if (currentTypeId == MWMechanics::AiPackage::TypeIdWander) { AiPackage* activePackage = getActivePackage(); dest = activePackage->getDestination(actor); } else { dest = actor.getRefData().getPosition().asVec3(); } MWMechanics::AiTravel travelPackage(dest.x(), dest.y(), dest.z(), true); stack(travelPackage, actor, false); } // remove previous packages if required if (cancelOther && package.shouldCancelPreviousAi()) { for(std::list<AiPackage *>::iterator it = mPackages.begin(); it != mPackages.end();) { if((*it)->canCancel()) { delete *it; it = mPackages.erase(it); } else ++it; } mRepeat=false; } // insert new package in correct place depending on priority for(std::list<AiPackage *>::iterator it = mPackages.begin(); it != mPackages.end(); ++it) { // We should keep current AiCast package, if we try to add a new one. if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdCast && package.getTypeId() == MWMechanics::AiPackage::TypeIdCast) { continue; } if((*it)->getPriority() <= package.getPriority()) { mPackages.insert(it,package.clone()); return; } } mPackages.push_back (package.clone()); // Make sure that temporary storage is empty if (cancelOther) { mAiState.moveIn(new AiCombatStorage()); mAiState.moveIn(new AiFollowStorage()); mAiState.moveIn(new AiWanderStorage()); } }