From 7029ed0e8d45010e8d2934073bccfdba4ff3c0c3 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 14 Aug 2018 15:36:52 +0300 Subject: [PATCH] Refactor follower and enemy actor processing Make another exception for wander packages when finding allies (bug #4304) --- apps/openmw/mwmechanics/actors.cpp | 105 +++++++++++++++-------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index d53c4407b5..5c59efe308 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1777,38 +1777,35 @@ namespace MWMechanics std::list Actors::getActorsSidingWith(const MWWorld::Ptr& actor) { std::list list; - for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for(PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter) { - const MWWorld::Class &cls = iter->first.getClass(); - const CreatureStats &stats = cls.getCreatureStats(iter->first); + const MWWorld::Ptr &iteratedActor = iter->first; + if (iteratedActor == getPlayer()) + continue; + + const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor); if (stats.isDead()) continue; - // An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Combat packages before the Follow/Escort package - for (std::list::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) - { - if ((*it)->sideWithTarget() && (*it)->getTarget() == actor) - { - list.push_back(iter->first); - break; - } - else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) - break; - } + // An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Combat and Wander packages before the Follow/Escort package // Actors that are targeted by this actor's Follow or Escort packages also side with them - if (actor != getPlayer()) + for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package) { - const CreatureStats &stats2 = actor.getClass().getCreatureStats(actor); - for (std::list::const_iterator it2 = stats2.getAiSequence().begin(); it2 != stats2.getAiSequence().end(); ++it2) + const MWWorld::Ptr &target = (*package)->getTarget(); + if ((*package)->sideWithTarget() && !target.isEmpty()) { - if ((*it2)->sideWithTarget() && !(*it2)->getTarget().isEmpty()) + if (iteratedActor == actor) { - list.push_back((*it2)->getTarget()); - break; + list.push_back(target); } - else if ((*it2)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) - break; + else if (target == actor) + { + list.push_back(iteratedActor); + } + break; } + else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander) + break; } } return list; @@ -1819,17 +1816,21 @@ namespace MWMechanics std::list list; for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { - const MWWorld::Class &cls = iter->first.getClass(); - CreatureStats &stats = cls.getCreatureStats(iter->first); + const MWWorld::Ptr &iteratedActor = iter->first; + if (iteratedActor == getPlayer()) + continue; + + const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor); if (stats.isDead()) continue; - // An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package - for (std::list::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) + // An actor counts as following if AiFollow is the current AiPackage, + // or there are only Combat and Wander packages before the AiFollow package + for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package) { - if ((*it)->followTargetThroughDoors() && (*it)->getTarget() == actor) - list.push_back(iter->first); - else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) + if ((*package)->followTargetThroughDoors() && (*package)->getTarget() == actor) + list.push_back(iteratedActor); + else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander) break; } } @@ -1878,24 +1879,24 @@ namespace MWMechanics std::list list; for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { - const MWWorld::Class &cls = iter->first.getClass(); - CreatureStats &stats = cls.getCreatureStats(iter->first); + const MWWorld::Ptr &iteratedActor = iter->first; + if (iteratedActor == getPlayer()) + continue; + + const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor); if (stats.isDead()) continue; - // An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package - for (std::list::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) + // An actor counts as following if AiFollow is the current AiPackage, + // or there are only Combat and Wander packages before the AiFollow package + for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package) { - if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow) + if ((*package)->followTargetThroughDoors() && (*package)->getTarget() == actor) { - MWWorld::Ptr followTarget = (*it)->getTarget(); - if (followTarget.isEmpty()) - continue; - if (followTarget == actor) - list.push_back(static_cast(*it)->getFollowIndex()); + list.push_back(static_cast(*package)->getFollowIndex()); break; } - else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) + else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander) break; } } @@ -1907,14 +1908,14 @@ namespace MWMechanics std::vector neighbors; osg::Vec3f position (actor.getRefData().getPosition().asVec3()); getObjectsInRange(position, aiProcessingDistance, neighbors); - for(std::vector::const_iterator iter(neighbors.begin());iter != neighbors.end();++iter) + for(auto neighbor = neighbors.begin(); neighbor != neighbors.end(); ++neighbor) { - const MWWorld::Class &cls = iter->getClass(); - const CreatureStats &stats = cls.getCreatureStats(*iter); - if (stats.isDead() || *iter == actor) + const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor); + if (stats.isDead() || *neighbor == actor) continue; + if (stats.getAiSequence().isInCombat(actor)) - list.push_front(*iter); + list.push_front(*neighbor); } return list; } @@ -1927,14 +1928,16 @@ namespace MWMechanics getObjectsInRange(position, aiProcessingDistance, neighbors); std::list followers = getActorsFollowing(actor); - for(std::vector::const_iterator iter(neighbors.begin());iter != neighbors.end();++iter) + for(auto neighbor = neighbors.begin(); neighbor != neighbors.end(); ++neighbor) { - const CreatureStats &stats = iter->getClass().getCreatureStats(*iter); - if (stats.isDead() || *iter == actor || iter->getClass().isPureWaterCreature(*iter)) + const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor); + if (stats.isDead() || *neighbor == actor || neighbor->getClass().isPureWaterCreature(*neighbor)) continue; - const bool isFollower = std::find(followers.begin(), followers.end(), *iter) != followers.end(); - if (stats.getAiSequence().isInCombat(actor) || (MWBase::Environment::get().getMechanicsManager()->isAggressive(*iter, actor) && !isFollower)) - list.push_back(*iter); + + const bool isFollower = std::find(followers.begin(), followers.end(), *neighbor) != followers.end(); + + if (stats.getAiSequence().isInCombat(actor) || (MWBase::Environment::get().getMechanicsManager()->isAggressive(*neighbor, actor) && !isFollower)) + list.push_back(*neighbor); } return list; }