forked from mirror/openmw-tes3mp
AiEscort makes the actor side with target in fights (Bug #2697)
Also will follow the player through teleport doors.
This commit is contained in:
parent
4e678ce6b3
commit
965bea45c0
11 changed files with 56 additions and 38 deletions
|
@ -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…
Reference in a new issue