forked from teamnwah/openmw-tes3coop
Adjust AiFollow distance for groups of multiple followers (Fixes #1637)
This commit is contained in:
parent
3ad0189982
commit
109a3f78a1
7 changed files with 73 additions and 7 deletions
|
@ -183,6 +183,7 @@ namespace MWBase
|
|||
///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;
|
||||
virtual std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
///Returns a list of actors who are fighting the given actor within the fAlarmDistance
|
||||
/** ie AiCombat is active and the target is the actor **/
|
||||
|
|
|
@ -1470,6 +1470,36 @@ namespace MWMechanics
|
|||
return list;
|
||||
}
|
||||
|
||||
std::list<int> Actors::getActorsFollowingIndices(const MWWorld::Ptr &actor)
|
||||
{
|
||||
std::list<int> list;
|
||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||
{
|
||||
const MWWorld::Class &cls = iter->first.getClass();
|
||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||
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
|
||||
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 = dynamic_cast<MWMechanics::AiFollow*>(*it)->getTarget();
|
||||
if (followTarget.isEmpty())
|
||||
continue;
|
||||
if (followTarget == actor)
|
||||
list.push_back(dynamic_cast<MWMechanics::AiFollow*>(*it)->getFollowIndex());
|
||||
else
|
||||
break;
|
||||
}
|
||||
else if ((*it)->getTypeId() != MWMechanics::AiPackage::TypeIdCombat)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
std::list<MWWorld::Ptr> Actors::getActorsFighting(const MWWorld::Ptr& actor) {
|
||||
std::list<MWWorld::Ptr> list;
|
||||
std::vector<MWWorld::Ptr> neighbors;
|
||||
|
|
|
@ -112,6 +112,9 @@ namespace MWMechanics
|
|||
/**ie AiFollow is active and the target is the actor **/
|
||||
std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
|
||||
|
||||
/// Get the list of AiFollow::mFollowIndex for all actors following this target
|
||||
std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor);
|
||||
|
||||
///Returns the list of actors which are fighting the given actor
|
||||
/**ie AiCombat is active and the target is the actor **/
|
||||
std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
|
@ -15,28 +16,31 @@
|
|||
|
||||
#include "steering.hpp"
|
||||
|
||||
int MWMechanics::AiFollow::mFollowIndexCounter = 0;
|
||||
|
||||
MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z)
|
||||
: mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
||||
, mActorRefId(actorId), mCellId(""), mActorId(-1)
|
||||
, mActorRefId(actorId), mCellId(""), mActorId(-1), mFollowIndex(mFollowIndexCounter++)
|
||||
{
|
||||
}
|
||||
MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z)
|
||||
: mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z)
|
||||
, mActorRefId(actorId), mCellId(cellId), mActorId(-1)
|
||||
, mActorRefId(actorId), mCellId(cellId), mActorId(-1), mFollowIndex(mFollowIndexCounter++)
|
||||
{
|
||||
}
|
||||
|
||||
MWMechanics::AiFollow::AiFollow(const std::string &actorId, bool commanded)
|
||||
: mAlwaysFollow(true), mCommanded(commanded), mRemainingDuration(0), mX(0), mY(0), mZ(0)
|
||||
, mActorRefId(actorId), mCellId(""), mActorId(-1)
|
||||
, mActorRefId(actorId), mCellId(""), mActorId(-1), mFollowIndex(mFollowIndexCounter++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MWMechanics::AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow)
|
||||
: mAlwaysFollow(follow->mAlwaysFollow), mRemainingDuration(follow->mRemainingDuration)
|
||||
, mX(follow->mData.mX), mY(follow->mData.mY), mZ(follow->mData.mZ)
|
||||
, mActorRefId(follow->mTargetId), mActorId(-1), mCellId(follow->mCellId)
|
||||
, mCommanded(follow->mCommanded)
|
||||
, mCommanded(follow->mCommanded), mFollowIndex(mFollowIndexCounter++)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -48,12 +52,24 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor, AiState& state,
|
|||
if (target.isEmpty() || !target.getRefData().getCount() || !target.getRefData().isEnabled() // Really we should be checking whether the target is currently registered
|
||||
// with the MechanicsManager
|
||||
)
|
||||
return true; //Target doesn't exist
|
||||
return false; // Target is not here right now, wait for it to return
|
||||
|
||||
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
|
||||
|
||||
ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
|
||||
|
||||
float followDistance = 180;
|
||||
// When there are multiple actors following the same target, they form a group with each group member at 180*(i+1) distance to the target
|
||||
int i=0;
|
||||
std::list<int> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowingIndices(target);
|
||||
followers.sort();
|
||||
for (std::list<int>::iterator it = followers.begin(); it != followers.end(); ++it)
|
||||
{
|
||||
if (*it == mFollowIndex)
|
||||
followDistance *= (i+1);
|
||||
++i;
|
||||
}
|
||||
|
||||
if(!mAlwaysFollow) //Update if you only follow for a bit
|
||||
{
|
||||
//Check if we've run out of time
|
||||
|
@ -66,7 +82,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor, AiState& state,
|
|||
|
||||
if((pos.pos[0]-mX)*(pos.pos[0]-mX) +
|
||||
(pos.pos[1]-mY)*(pos.pos[1]-mY) +
|
||||
(pos.pos[2]-mZ)*(pos.pos[2]-mZ) < 100*100) //Close-ish to final position
|
||||
(pos.pos[2]-mZ)*(pos.pos[2]-mZ) < followDistance*followDistance) //Close-ish to final position
|
||||
{
|
||||
if(actor.getCell()->isExterior()) //Outside?
|
||||
{
|
||||
|
@ -84,7 +100,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor, AiState& state,
|
|||
//Set the target destination from the actor
|
||||
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos;
|
||||
|
||||
if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) //Stop when you get close
|
||||
if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < followDistance) //Stop when you get close
|
||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
||||
else {
|
||||
pathTo(actor, dest, duration); //Go to the destination
|
||||
|
@ -159,3 +175,8 @@ MWWorld::Ptr MWMechanics::AiFollow::getTarget()
|
|||
else
|
||||
return MWWorld::Ptr();
|
||||
}
|
||||
|
||||
int MWMechanics::AiFollow::getFollowIndex() const
|
||||
{
|
||||
return mFollowIndex;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace MWMechanics
|
|||
|
||||
bool isCommanded() const;
|
||||
|
||||
int getFollowIndex() const;
|
||||
|
||||
private:
|
||||
/// This will make the actor always follow.
|
||||
/** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/
|
||||
|
@ -58,6 +60,9 @@ namespace MWMechanics
|
|||
std::string mActorRefId;
|
||||
int mActorId;
|
||||
std::string mCellId;
|
||||
int mFollowIndex;
|
||||
|
||||
static int mFollowIndexCounter;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1268,6 +1268,11 @@ namespace MWMechanics
|
|||
return mActors.getActorsFollowing(actor);
|
||||
}
|
||||
|
||||
std::list<int> MechanicsManager::getActorsFollowingIndices(const MWWorld::Ptr& actor)
|
||||
{
|
||||
return mActors.getActorsFollowingIndices(actor);
|
||||
}
|
||||
|
||||
std::list<MWWorld::Ptr> MechanicsManager::getActorsFighting(const MWWorld::Ptr& actor) {
|
||||
return mActors.getActorsFighting(actor);
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ namespace MWMechanics
|
|||
virtual void getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects);
|
||||
|
||||
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
|
||||
virtual std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor);
|
||||
|
||||
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);
|
||||
|
||||
|
|
Loading…
Reference in a new issue