1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-17 10:21:11 +00:00

Refactor follower and enemy actor processing

Make another exception for wander packages when finding allies (bug #4304)
This commit is contained in:
Capostrophic 2018-08-14 15:36:52 +03:00
parent c0e50b2c02
commit 7029ed0e8d

View File

@ -1777,38 +1777,35 @@ namespace MWMechanics
std::list<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actor) std::list<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actor)
{ {
std::list<MWWorld::Ptr> list; std::list<MWWorld::Ptr> 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 MWWorld::Ptr &iteratedActor = iter->first;
const CreatureStats &stats = cls.getCreatureStats(iter->first); if (iteratedActor == getPlayer())
continue;
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
if (stats.isDead()) if (stats.isDead())
continue; 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 // 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
for (std::list<MWMechanics::AiPackage*>::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;
}
// Actors that are targeted by this actor's Follow or Escort packages also side with them // 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); const MWWorld::Ptr &target = (*package)->getTarget();
for (std::list<MWMechanics::AiPackage*>::const_iterator it2 = stats2.getAiSequence().begin(); it2 != stats2.getAiSequence().end(); ++it2) if ((*package)->sideWithTarget() && !target.isEmpty())
{ {
if ((*it2)->sideWithTarget() && !(*it2)->getTarget().isEmpty()) if (iteratedActor == actor)
{ {
list.push_back((*it2)->getTarget()); list.push_back(target);
break;
} }
else if ((*it2)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) else if (target == actor)
break; {
list.push_back(iteratedActor);
}
break;
} }
else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
break;
} }
} }
return list; return list;
@ -1819,17 +1816,21 @@ namespace MWMechanics
std::list<MWWorld::Ptr> list; std::list<MWWorld::Ptr> 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 MWWorld::Ptr &iteratedActor = iter->first;
CreatureStats &stats = cls.getCreatureStats(iter->first); if (iteratedActor == getPlayer())
continue;
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
if (stats.isDead()) if (stats.isDead())
continue; continue;
// An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package // An actor counts as following if AiFollow is the current AiPackage,
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) // 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) if ((*package)->followTargetThroughDoors() && (*package)->getTarget() == actor)
list.push_back(iter->first); list.push_back(iteratedActor);
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
break; break;
} }
} }
@ -1878,24 +1879,24 @@ namespace MWMechanics
std::list<int> list; std::list<int> 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 MWWorld::Ptr &iteratedActor = iter->first;
CreatureStats &stats = cls.getCreatureStats(iter->first); if (iteratedActor == getPlayer())
continue;
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
if (stats.isDead()) if (stats.isDead())
continue; continue;
// An actor counts as following if AiFollow is the current AiPackage, or there are only Combat packages before the AiFollow package // An actor counts as following if AiFollow is the current AiPackage,
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) // 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(); list.push_back(static_cast<AiFollow*>(*package)->getFollowIndex());
if (followTarget.isEmpty())
continue;
if (followTarget == actor)
list.push_back(static_cast<MWMechanics::AiFollow*>(*it)->getFollowIndex());
break; break;
} }
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat) else if ((*package)->getTypeId() != AiPackage::TypeIdCombat && (*package)->getTypeId() != AiPackage::TypeIdWander)
break; break;
} }
} }
@ -1907,14 +1908,14 @@ namespace MWMechanics
std::vector<MWWorld::Ptr> neighbors; std::vector<MWWorld::Ptr> neighbors;
osg::Vec3f position (actor.getRefData().getPosition().asVec3()); osg::Vec3f position (actor.getRefData().getPosition().asVec3());
getObjectsInRange(position, aiProcessingDistance, neighbors); getObjectsInRange(position, aiProcessingDistance, neighbors);
for(std::vector<MWWorld::Ptr>::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 = neighbor->getClass().getCreatureStats(*neighbor);
const CreatureStats &stats = cls.getCreatureStats(*iter); if (stats.isDead() || *neighbor == actor)
if (stats.isDead() || *iter == actor)
continue; continue;
if (stats.getAiSequence().isInCombat(actor)) if (stats.getAiSequence().isInCombat(actor))
list.push_front(*iter); list.push_front(*neighbor);
} }
return list; return list;
} }
@ -1927,14 +1928,16 @@ namespace MWMechanics
getObjectsInRange(position, aiProcessingDistance, neighbors); getObjectsInRange(position, aiProcessingDistance, neighbors);
std::list<MWWorld::Ptr> followers = getActorsFollowing(actor); std::list<MWWorld::Ptr> followers = getActorsFollowing(actor);
for(std::vector<MWWorld::Ptr>::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); const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor);
if (stats.isDead() || *iter == actor || iter->getClass().isPureWaterCreature(*iter)) if (stats.isDead() || *neighbor == actor || neighbor->getClass().isPureWaterCreature(*neighbor))
continue; 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)) const bool isFollower = std::find(followers.begin(), followers.end(), *neighbor) != followers.end();
list.push_back(*iter);
if (stats.getAiSequence().isInCombat(actor) || (MWBase::Environment::get().getMechanicsManager()->isAggressive(*neighbor, actor) && !isFollower))
list.push_back(*neighbor);
} }
return list; return list;
} }