mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-24 20:41:35 +00:00
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 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,9 +336,11 @@ 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();
|
|
||||||
|
MWWorld::Ptr followTarget = (*it)->getTarget();
|
||||||
|
|
||||||
if (followTarget.isEmpty())
|
if (followTarget.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -350,7 +352,6 @@ namespace MWMechanics
|
||||||
|| followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2))
|
|| followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2))
|
||||||
aggressive = true;
|
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)
|
||||||
{
|
|
||||||
MWWorld::Ptr followTarget = static_cast<MWMechanics::AiFollow*>(*it)->getTarget();
|
|
||||||
if (followTarget.isEmpty())
|
|
||||||
continue;
|
|
||||||
if (followTarget == actor)
|
|
||||||
list.push_back(iter->first);
|
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…
Reference in a new issue