mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-02 01:36:41 +00:00
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
|
///return the list of actors which are following the given actor
|
||||||
/**ie AiFollow is active and the target is the 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<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
|
///Returns a list of actors who are fighting the given actor within the fAlarmDistance
|
||||||
/** ie AiCombat is active and the target is the actor **/
|
/** ie AiCombat is active and the target is the actor **/
|
||||||
|
|
|
@ -1470,6 +1470,36 @@ namespace MWMechanics
|
||||||
return list;
|
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> Actors::getActorsFighting(const MWWorld::Ptr& actor) {
|
||||||
std::list<MWWorld::Ptr> list;
|
std::list<MWWorld::Ptr> list;
|
||||||
std::vector<MWWorld::Ptr> neighbors;
|
std::vector<MWWorld::Ptr> neighbors;
|
||||||
|
|
|
@ -112,6 +112,9 @@ namespace MWMechanics
|
||||||
/**ie AiFollow is active and the target is the actor **/
|
/**ie AiFollow is active and the target is the actor **/
|
||||||
std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& 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
|
///Returns the list of actors which are fighting the given actor
|
||||||
/**ie AiCombat is active and the target is the actor **/
|
/**ie AiCombat is active and the target is the actor **/
|
||||||
std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);
|
std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
|
@ -15,28 +16,31 @@
|
||||||
|
|
||||||
#include "steering.hpp"
|
#include "steering.hpp"
|
||||||
|
|
||||||
|
int MWMechanics::AiFollow::mFollowIndexCounter = 0;
|
||||||
|
|
||||||
MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z)
|
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)
|
: 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)
|
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)
|
: 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)
|
MWMechanics::AiFollow::AiFollow(const std::string &actorId, bool commanded)
|
||||||
: mAlwaysFollow(true), mCommanded(commanded), mRemainingDuration(0), mX(0), mY(0), mZ(0)
|
: 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)
|
MWMechanics::AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow)
|
||||||
: mAlwaysFollow(follow->mAlwaysFollow), mRemainingDuration(follow->mRemainingDuration)
|
: mAlwaysFollow(follow->mAlwaysFollow), mRemainingDuration(follow->mRemainingDuration)
|
||||||
, mX(follow->mData.mX), mY(follow->mData.mY), mZ(follow->mData.mZ)
|
, mX(follow->mData.mX), mY(follow->mData.mY), mZ(follow->mData.mZ)
|
||||||
, mActorRefId(follow->mTargetId), mActorId(-1), mCellId(follow->mCellId)
|
, 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
|
if (target.isEmpty() || !target.getRefData().getCount() || !target.getRefData().isEnabled() // Really we should be checking whether the target is currently registered
|
||||||
// with the MechanicsManager
|
// 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);
|
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
|
||||||
|
|
||||||
ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
|
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
|
if(!mAlwaysFollow) //Update if you only follow for a bit
|
||||||
{
|
{
|
||||||
//Check if we've run out of time
|
//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) +
|
if((pos.pos[0]-mX)*(pos.pos[0]-mX) +
|
||||||
(pos.pos[1]-mY)*(pos.pos[1]-mY) +
|
(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?
|
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
|
//Set the target destination from the actor
|
||||||
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos;
|
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;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
||||||
else {
|
else {
|
||||||
pathTo(actor, dest, duration); //Go to the destination
|
pathTo(actor, dest, duration); //Go to the destination
|
||||||
|
@ -159,3 +175,8 @@ MWWorld::Ptr MWMechanics::AiFollow::getTarget()
|
||||||
else
|
else
|
||||||
return MWWorld::Ptr();
|
return MWWorld::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MWMechanics::AiFollow::getFollowIndex() const
|
||||||
|
{
|
||||||
|
return mFollowIndex;
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool isCommanded() const;
|
bool isCommanded() const;
|
||||||
|
|
||||||
|
int getFollowIndex() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// This will make the actor always follow.
|
/// This will make the actor always follow.
|
||||||
/** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/
|
/** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/
|
||||||
|
@ -58,6 +60,9 @@ namespace MWMechanics
|
||||||
std::string mActorRefId;
|
std::string mActorRefId;
|
||||||
int mActorId;
|
int mActorId;
|
||||||
std::string mCellId;
|
std::string mCellId;
|
||||||
|
int mFollowIndex;
|
||||||
|
|
||||||
|
static int mFollowIndexCounter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1268,6 +1268,11 @@ namespace MWMechanics
|
||||||
return mActors.getActorsFollowing(actor);
|
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) {
|
std::list<MWWorld::Ptr> MechanicsManager::getActorsFighting(const MWWorld::Ptr& actor) {
|
||||||
return mActors.getActorsFighting(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 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<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);
|
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue