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 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; 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 ///Returns the list of actors which are siding with the given actor in fights
/**ie AiFollow is active and the target is the actor**/ /**ie AiFollow or AiEscort is active and the target is the actor **/
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor) = 0; virtual std::list<MWWorld::Ptr> getActorsSidingWith(const MWWorld::Ptr& actor) = 0;
virtual std::list<int> getActorsFollowingIndices(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 ///Returns a list of actors who are fighting the given actor within the fAlarmDistance

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

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

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

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

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

@ -20,6 +20,16 @@
MWMechanics::AiPackage::~AiPackage() {} 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 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 /// Simulates the passing of time
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state) {} 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); bool isTargetMagicallyHidden(const MWWorld::Ptr& target);
protected: protected:

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

Loading…
Cancel
Save