AiEscort makes the actor side with target in fights (Bug #2697)

Also will follow the player through teleport doors.
openmw-38
scrawl 9 years ago
parent 4e678ce6b3
commit 965bea45c0

@ -184,9 +184,9 @@ namespace MWBase
virtual void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0;
virtual void getActorsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects) = 0;
///return the list of actors which are following the given actor
/**ie AiFollow is active and the target is the actor**/
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor) = 0;
///Returns the list of actors which are siding with the given actor in fights
/**ie AiFollow or AiEscort is active and the target is the actor **/
virtual std::list<MWWorld::Ptr> getActorsSidingWith(const MWWorld::Ptr& actor) = 0;
virtual std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor) = 0;
///Returns a list of actors who are fighting the given actor within the fAlarmDistance

@ -303,7 +303,7 @@ namespace MWMechanics
if (againstPlayer)
{
// followers with high fight should not engage in combat with the player (e.g. bm_bear_black_summon)
const std::list<MWWorld::Ptr>& followers = getActorsFollowing(actor2);
const std::list<MWWorld::Ptr>& followers = getActorsSidingWith(actor2);
if (std::find(followers.begin(), followers.end(), actor1) != followers.end())
return;
@ -322,7 +322,7 @@ namespace MWMechanics
}
// start combat if target actor is in combat with one of our followers
const std::list<MWWorld::Ptr>& followers = getActorsFollowing(actor1);
const std::list<MWWorld::Ptr>& followers = getActorsSidingWith(actor1);
const CreatureStats& creatureStats2 = actor2.getClass().getCreatureStats(actor2);
for (std::list<MWWorld::Ptr>::const_iterator it = followers.begin(); it != followers.end(); ++it)
{
@ -336,20 +336,21 @@ namespace MWMechanics
// start combat if target actor is in combat with someone we are following
for (std::list<MWMechanics::AiPackage*>::const_iterator it = creatureStats.getAiSequence().begin(); it != creatureStats.getAiSequence().end(); ++it)
{
if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow)
{
MWWorld::Ptr followTarget = static_cast<MWMechanics::AiFollow*>(*it)->getTarget();
if (followTarget.isEmpty())
continue;
if (!(*it)->sideWithTarget())
continue;
if (creatureStats.getAiSequence().isInCombat(followTarget))
continue;
MWWorld::Ptr followTarget = (*it)->getTarget();
// need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(followTarget)
|| followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2))
aggressive = true;
}
if (followTarget.isEmpty())
continue;
if (creatureStats.getAiSequence().isInCombat(followTarget))
continue;
// need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(followTarget)
|| followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2))
aggressive = true;
}
if(aggressive)
@ -1290,7 +1291,7 @@ namespace MWMechanics
}
}
std::list<MWWorld::Ptr> Actors::getActorsFollowing(const MWWorld::Ptr& actor)
std::list<MWWorld::Ptr> Actors::getActorsSidingWith(const MWWorld::Ptr& actor)
{
std::list<MWWorld::Ptr> list;
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
@ -1300,19 +1301,11 @@ namespace MWMechanics
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
// An actor counts as following if AiFollow or AiEscort is the current AiPackage, or there are only Combat packages before the AiFollow/AiEscort package
for (std::list<MWMechanics::AiPackage*>::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it)
{
if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow)
{
MWWorld::Ptr followTarget = static_cast<MWMechanics::AiFollow*>(*it)->getTarget();
if (followTarget.isEmpty())
continue;
if (followTarget == actor)
list.push_back(iter->first);
else
break;
}
if ((*it)->sideWithTarget() && (*it)->getTarget() == actor)
list.push_back(iter->first);
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
break;
}

@ -111,9 +111,9 @@ namespace MWMechanics
void getObjectsInRange(const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out);
///Returns the list of actors which are following the given actor
/**ie AiFollow is active and the target is the actor **/
std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
///Returns the list of actors which are siding with the given actor in fights
/**ie AiFollow or AiEscort is active and the target is the actor **/
std::list<MWWorld::Ptr> getActorsSidingWith(const MWWorld::Ptr& actor);
/// Get the list of AiFollow::mFollowIndex for all actors following this target
std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor);

@ -119,6 +119,11 @@ namespace MWMechanics
return TypeIdEscort;
}
MWWorld::Ptr AiEscort::getTarget()
{
return MWBase::Environment::get().getWorld()->getPtr(mActorId, false);
}
void AiEscort::writeState(ESM::AiSequence::AiSequence &sequence) const
{
std::auto_ptr<ESM::AiSequence::AiEscort> escort(new ESM::AiSequence::AiEscort());

@ -37,6 +37,9 @@ namespace MWMechanics
virtual int getTypeId() const;
MWWorld::Ptr getTarget();
virtual bool sideWithTarget() const { return true; }
void writeState(ESM::AiSequence::AiSequence &sequence) const;
private:

@ -32,6 +32,7 @@ namespace MWMechanics
AiFollow(const ESM::AiSequence::AiFollow* follow);
MWWorld::Ptr getTarget();
virtual bool sideWithTarget() const { return true; }
virtual AiFollow *clone() const;

@ -20,6 +20,16 @@
MWMechanics::AiPackage::~AiPackage() {}
MWWorld::Ptr MWMechanics::AiPackage::getTarget()
{
return MWWorld::Ptr();
}
bool MWMechanics::AiPackage::sideWithTarget() const
{
return false;
}
MWMechanics::AiPackage::AiPackage() : mTimer(0.26f) { //mTimer starts at .26 to force initial pathbuild
}

@ -69,6 +69,12 @@ namespace MWMechanics
/// Simulates the passing of time
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state) {}
/// Get the target actor the AI is targeted at (not applicable to all AI packages, default return empty Ptr)
virtual MWWorld::Ptr getTarget();
/// Return true if having this AiPackage makes the actor side with the target in fights (default false)
virtual bool sideWithTarget() const;
bool isTargetMagicallyHidden(const MWWorld::Ptr& target);
protected:

@ -1053,7 +1053,7 @@ namespace MWMechanics
void getFollowers (const MWWorld::Ptr& actor, std::set<MWWorld::Ptr>& out)
{
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor);
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsSidingWith(actor);
for(std::list<MWWorld::Ptr>::iterator it = followers.begin();it != followers.end();++it)
{
if (out.insert(*it).second)
@ -1310,7 +1310,7 @@ namespace MWMechanics
if (ptr == getPlayer())
return false;
std::list<MWWorld::Ptr> followers = getActorsFollowing(attacker);
std::list<MWWorld::Ptr> followers = getActorsSidingWith(attacker);
MWMechanics::CreatureStats& targetStats = ptr.getClass().getCreatureStats(ptr);
if (std::find(followers.begin(), followers.end(), ptr) != followers.end())
{
@ -1487,9 +1487,9 @@ namespace MWMechanics
mActors.getObjectsInRange(position, radius, objects);
}
std::list<MWWorld::Ptr> MechanicsManager::getActorsFollowing(const MWWorld::Ptr& actor)
std::list<MWWorld::Ptr> MechanicsManager::getActorsSidingWith(const MWWorld::Ptr& actor)
{
return mActors.getActorsFollowing(actor);
return mActors.getActorsSidingWith(actor);
}
std::list<int> MechanicsManager::getActorsFollowingIndices(const MWWorld::Ptr& actor)

@ -150,7 +150,7 @@ namespace MWMechanics
virtual void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& objects);
virtual void getActorsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects);
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
virtual std::list<MWWorld::Ptr> getActorsSidingWith(const MWWorld::Ptr& actor);
virtual std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor);
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);

@ -13,7 +13,7 @@ namespace
void getFollowers (const MWWorld::Ptr& actor, std::set<MWWorld::Ptr>& out)
{
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor);
std::list<MWWorld::Ptr> followers = MWBase::Environment::get().getMechanicsManager()->getActorsSidingWith(actor);
for(std::list<MWWorld::Ptr>::iterator it = followers.begin();it != followers.end();++it)
{
if (out.insert(*it).second)

Loading…
Cancel
Save