AI package cleanups

pull/1/head
Allofich 9 years ago
parent 372f2e2f18
commit c2b51112f2

@ -16,7 +16,6 @@
#include "movement.hpp" #include "movement.hpp"
/* /*
TODO: Test vanilla behavior on passing x0, y0, and z0 with duration of anything including 0.
TODO: Different behavior for AIEscort a d x y z and AIEscortCell a c d x y z. TODO: Different behavior for AIEscort a d x y z and AIEscortCell a c d x y z.
TODO: Take account for actors being in different cells. TODO: Take account for actors being in different cells.
*/ */
@ -109,7 +108,7 @@ namespace MWMechanics
} }
else else
{ {
// Stop moving if the player is to far away // Stop moving if the player is too far away
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1); MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1);
actor.getClass().getMovementSettings(actor).mPosition[1] = 0; actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
mMaxDist = 250; mMaxDist = 250;

@ -75,6 +75,21 @@ namespace MWMechanics
std::vector<unsigned short> mBadIdles; // Idle animations that when called cause errors std::vector<unsigned short> mBadIdles; // Idle animations that when called cause errors
PathFinder mPathFinder; PathFinder mPathFinder;
// do we need to calculate allowed nodes based on mDistance
bool mPopulateAvailableNodes;
// allowed pathgrid nodes based on mDistance from the spawn point
// in local coordinates of mCell
std::vector<ESM::Pathgrid::Point> mAllowedNodes;
ESM::Pathgrid::Point mCurrentNode;
bool mTrimCurrentNode;
ObstacleCheck mObstacleCheck;
float mDoorCheckDuration;
int mStuckCount;
AiWanderStorage(): AiWanderStorage():
mTargetAngleRadians(0), mTargetAngleRadians(0),
@ -87,7 +102,12 @@ namespace MWMechanics
mIsWanderingManually(false), mIsWanderingManually(false),
mCanWanderAlongPathGrid(true), mCanWanderAlongPathGrid(true),
mIdleAnimation(0), mIdleAnimation(0),
mBadIdles() mBadIdles(),
mPopulateAvailableNodes(true),
mAllowedNodes(),
mTrimCurrentNode(false),
mDoorCheckDuration(0), // TODO: maybe no longer needed
mStuckCount(0)
{}; {};
void setState(const AiWander::WanderState wanderState, const bool isManualWander = false) { void setState(const AiWander::WanderState wanderState, const bool isManualWander = false) {
@ -108,11 +128,6 @@ namespace MWMechanics
{ {
// NOTE: mDistance and mDuration must be set already // NOTE: mDistance and mDuration must be set already
mStuckCount = 0;// TODO: maybe no longer needed
mDoorCheckDuration = 0;
mTrimCurrentNode = false;
mHasReturnPosition = false; mHasReturnPosition = false;
mReturnPosition = osg::Vec3f(0,0,0); mReturnPosition = osg::Vec3f(0,0,0);
@ -120,16 +135,6 @@ namespace MWMechanics
mDistance = 0; mDistance = 0;
if(mDuration < 0) if(mDuration < 0)
mDuration = 0; mDuration = 0;
if(mDuration == 0)
mTimeOfDay = 0;
if(mDuration > 24)
{
mDuration = 24;
mRemainingDuration = (mDuration);
}
mPopulateAvailableNodes = true;
} }
AiPackage * MWMechanics::AiWander::clone() const AiPackage * MWMechanics::AiWander::clone() const
@ -202,7 +207,7 @@ namespace MWMechanics
if(!currentCell || cellChange) if(!currentCell || cellChange)
{ {
currentCell = actor.getCell(); currentCell = actor.getCell();
mPopulateAvailableNodes = true; storage.mPopulateAvailableNodes = true;
} }
mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600); mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
@ -248,7 +253,7 @@ namespace MWMechanics
} }
// Initialization to discover & store allowed node points for this actor. // Initialization to discover & store allowed node points for this actor.
if (mPopulateAvailableNodes) if (storage.mPopulateAvailableNodes)
{ {
getAllowedNodes(actor, currentCell->getCell(), storage); getAllowedNodes(actor, currentCell->getCell(), storage);
} }
@ -256,19 +261,19 @@ namespace MWMechanics
// Actor becomes stationary - see above URL's for previous research // Actor becomes stationary - see above URL's for previous research
// If a creature or an NPC with a wander distance and no pathgrid is available, // If a creature or an NPC with a wander distance and no pathgrid is available,
// randomly idle or wander around near spawn point // randomly idle or wander around near spawn point
if(mAllowedNodes.empty() && mDistance > 0 && !storage.mIsWanderingManually) { if(storage.mAllowedNodes.empty() && mDistance > 0 && !storage.mIsWanderingManually) {
// Typically want to idle for a short time before the next wander // Typically want to idle for a short time before the next wander
if (Misc::Rng::rollDice(100) >= 96) { if (Misc::Rng::rollDice(100) >= 96) {
wanderNearStart(actor, storage, mDistance); wanderNearStart(actor, storage, mDistance);
} else { } else {
storage.setState(Wander_IdleNow); storage.setState(Wander_IdleNow);
} }
} else if (mAllowedNodes.empty() && !storage.mIsWanderingManually) { } else if (storage.mAllowedNodes.empty() && !storage.mIsWanderingManually) {
storage.mCanWanderAlongPathGrid = false; storage.mCanWanderAlongPathGrid = false;
} }
// If Wandering manually and hit an obstacle, stop // If Wandering manually and hit an obstacle, stop
if (storage.mIsWanderingManually && mObstacleCheck.check(actor, duration, 2.0f)) { if (storage.mIsWanderingManually && storage.mObstacleCheck.check(actor, duration, 2.0f)) {
completeManualWalking(actor, storage); completeManualWalking(actor, storage);
} }
@ -297,7 +302,7 @@ namespace MWMechanics
// Construct a new path if there isn't one // Construct a new path if there isn't one
if(!storage.mPathFinder.isPathConstructed()) if(!storage.mPathFinder.isPathConstructed())
{ {
if (!mAllowedNodes.empty()) if (!storage.mAllowedNodes.empty())
{ {
setPathToAnAllowedNode(actor, storage, pos); setPathToAnAllowedNode(actor, storage, pos);
} }
@ -314,6 +319,7 @@ namespace MWMechanics
return mRepeat; return mRepeat;
} }
bool AiWander::isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage) bool AiWander::isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage)
{ {
if (mDuration) if (mDuration)
@ -401,7 +407,7 @@ namespace MWMechanics
void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) { void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) {
stopWalking(actor, storage); stopWalking(actor, storage);
mObstacleCheck.clear(); storage.mObstacleCheck.clear();
storage.setState(Wander_IdleNow); storage.setState(Wander_IdleNow);
} }
@ -434,15 +440,15 @@ namespace MWMechanics
void AiWander::onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage) void AiWander::onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage)
{ {
// Check if an idle actor is too close to a door - if so start walking // Check if an idle actor is too close to a door - if so start walking
mDoorCheckDuration += duration; storage.mDoorCheckDuration += duration;
if (mDoorCheckDuration >= DOOR_CHECK_INTERVAL) if (storage.mDoorCheckDuration >= DOOR_CHECK_INTERVAL)
{ {
mDoorCheckDuration = 0; // restart timer storage.mDoorCheckDuration = 0; // restart timer
if (mDistance && // actor is not intended to be stationary if (mDistance && // actor is not intended to be stationary
proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6f*1.6f)) // NOTE: checks interior cells only proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6f*1.6f)) // NOTE: checks interior cells only
{ {
storage.setState(Wander_MoveNow); storage.setState(Wander_MoveNow);
mTrimCurrentNode = false; // just in case storage.mTrimCurrentNode = false; // just in case
return; return;
} }
} }
@ -515,15 +521,15 @@ namespace MWMechanics
zTurn(actor, storage.mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])); zTurn(actor, storage.mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]));
MWMechanics::Movement& movement = actor.getClass().getMovementSettings(actor); MWMechanics::Movement& movement = actor.getClass().getMovementSettings(actor);
if (mObstacleCheck.check(actor, duration)) if (storage.mObstacleCheck.check(actor, duration))
{ {
// first check if we're walking into a door // first check if we're walking into a door
if (proximityToDoor(actor)) // NOTE: checks interior cells only if (proximityToDoor(actor)) // NOTE: checks interior cells only
{ {
// remove allowed points then select another random destination // remove allowed points then select another random destination
mTrimCurrentNode = true; storage.mTrimCurrentNode = true;
trimAllowedNodes(mAllowedNodes, storage.mPathFinder); trimAllowedNodes(storage.mAllowedNodes, storage.mPathFinder);
mObstacleCheck.clear(); storage.mObstacleCheck.clear();
storage.mPathFinder.clearPath(); storage.mPathFinder.clearPath();
storage.setState(Wander_MoveNow); storage.setState(Wander_MoveNow);
} }
@ -531,9 +537,9 @@ namespace MWMechanics
{ {
// TODO: diagonal should have same animation as walk forward // TODO: diagonal should have same animation as walk forward
// but doesn't seem to do that? // but doesn't seem to do that?
mObstacleCheck.takeEvasiveAction(movement); storage.mObstacleCheck.takeEvasiveAction(movement);
} }
mStuckCount++; // TODO: maybe no longer needed storage.mStuckCount++; // TODO: maybe no longer needed
} }
else else
{ {
@ -541,14 +547,14 @@ namespace MWMechanics
} }
// if stuck for sufficiently long, act like current location was the destination // if stuck for sufficiently long, act like current location was the destination
if (mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset if (storage.mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset
{ {
//std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl; //std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl;
mObstacleCheck.clear(); storage.mObstacleCheck.clear();
stopWalking(actor, storage); stopWalking(actor, storage);
storage.setState(Wander_ChooseAction); storage.setState(Wander_ChooseAction);
mStuckCount = 0; storage.mStuckCount = 0;
} }
} }
@ -621,7 +627,7 @@ namespace MWMechanics
if (storage.mState == Wander_Walking) if (storage.mState == Wander_Walking)
{ {
stopWalking(actor, storage); stopWalking(actor, storage);
mObstacleCheck.clear(); storage.mObstacleCheck.clear();
storage.setState(Wander_IdleNow); storage.setState(Wander_IdleNow);
} }
@ -653,8 +659,8 @@ namespace MWMechanics
void AiWander::setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos) void AiWander::setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos)
{ {
unsigned int randNode = Misc::Rng::rollDice(mAllowedNodes.size()); unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size());
ESM::Pathgrid::Point dest(mAllowedNodes[randNode]); ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
ToWorldCoordinates(dest, storage.mCell->getCell()); ToWorldCoordinates(dest, storage.mCell->getCell());
// actor position is already in world co-ordinates // actor position is already in world co-ordinates
@ -666,20 +672,20 @@ namespace MWMechanics
if (storage.mPathFinder.isPathConstructed()) if (storage.mPathFinder.isPathConstructed())
{ {
// Remove this node as an option and add back the previously used node (stops NPC from picking the same node): // Remove this node as an option and add back the previously used node (stops NPC from picking the same node):
ESM::Pathgrid::Point temp = mAllowedNodes[randNode]; ESM::Pathgrid::Point temp = storage.mAllowedNodes[randNode];
mAllowedNodes.erase(mAllowedNodes.begin() + randNode); storage.mAllowedNodes.erase(storage.mAllowedNodes.begin() + randNode);
// check if mCurrentNode was taken out of mAllowedNodes // check if mCurrentNode was taken out of mAllowedNodes
if (mTrimCurrentNode && mAllowedNodes.size() > 1) if (storage.mTrimCurrentNode && storage.mAllowedNodes.size() > 1)
mTrimCurrentNode = false; storage.mTrimCurrentNode = false;
else else
mAllowedNodes.push_back(mCurrentNode); storage.mAllowedNodes.push_back(storage.mCurrentNode);
mCurrentNode = temp; storage.mCurrentNode = temp;
storage.setState(Wander_Walking); storage.setState(Wander_Walking);
} }
// Choose a different node and delete this one from possible nodes because it is uncreachable: // Choose a different node and delete this one from possible nodes because it is uncreachable:
else else
mAllowedNodes.erase(mAllowedNodes.begin() + randNode); storage.mAllowedNodes.erase(storage.mAllowedNodes.begin() + randNode);
} }
void AiWander::ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell) void AiWander::ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell)
@ -788,17 +794,17 @@ namespace MWMechanics
if (mDistance == 0) if (mDistance == 0)
return; return;
if (mPopulateAvailableNodes) AiWanderStorage& storage = state.get<AiWanderStorage>();
getAllowedNodes(actor, actor.getCell()->getCell(), state.get<AiWanderStorage>()); if (storage.mPopulateAvailableNodes)
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
if (mAllowedNodes.empty()) if (storage.mAllowedNodes.empty())
return; return;
int index = Misc::Rng::rollDice(storage.mAllowedNodes.size());
ESM::Pathgrid::Point dest = storage.mAllowedNodes[index];
state.moveIn(new AiWanderStorage()); state.moveIn(new AiWanderStorage());
int index = Misc::Rng::rollDice(mAllowedNodes.size());
ESM::Pathgrid::Point dest = mAllowedNodes[index];
dest.mX += OffsetToPreventOvercrowding(); dest.mX += OffsetToPreventOvercrowding();
dest.mY += OffsetToPreventOvercrowding(); dest.mY += OffsetToPreventOvercrowding();
ToWorldCoordinates(dest, actor.getCell()->getCell()); ToWorldCoordinates(dest, actor.getCell()->getCell());
@ -808,7 +814,7 @@ namespace MWMechanics
actor.getClass().adjustPosition(actor, false); actor.getClass().adjustPosition(actor, false);
// may have changed cell // may have changed cell
mPopulateAvailableNodes = true; storage.mPopulateAvailableNodes = true;
} }
int AiWander::OffsetToPreventOvercrowding() int AiWander::OffsetToPreventOvercrowding()
@ -823,7 +829,7 @@ namespace MWMechanics
pathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell); pathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell);
const MWWorld::CellStore* cellStore = actor.getCell(); const MWWorld::CellStore* cellStore = actor.getCell();
mAllowedNodes.clear(); storage.mAllowedNodes.clear();
// If there is no path this actor doesn't go anywhere. See: // If there is no path this actor doesn't go anywhere. See:
// https://forum.openmw.org/viewtopic.php?t=1556 // https://forum.openmw.org/viewtopic.php?t=1556
@ -856,40 +862,40 @@ namespace MWMechanics
if((npcPos - nodePos).length2() <= mDistance * mDistance && if((npcPos - nodePos).length2() <= mDistance * mDistance &&
cellStore->isPointConnected(closestPointIndex, counter)) cellStore->isPointConnected(closestPointIndex, counter))
{ {
mAllowedNodes.push_back(pathgrid->mPoints[counter]); storage.mAllowedNodes.push_back(pathgrid->mPoints[counter]);
pointIndex = counter; pointIndex = counter;
} }
} }
if (mAllowedNodes.size() == 1) if (storage.mAllowedNodes.size() == 1)
{ {
AddNonPathGridAllowedPoints(npcPos, pathgrid, pointIndex); AddNonPathGridAllowedPoints(npcPos, pathgrid, pointIndex, storage);
} }
if(!mAllowedNodes.empty()) if(!storage.mAllowedNodes.empty())
{ {
SetCurrentNodeToClosestAllowedNode(npcPos); SetCurrentNodeToClosestAllowedNode(npcPos, storage);
} }
} }
mPopulateAvailableNodes = false; storage.mPopulateAvailableNodes = false;
} }
// When only one path grid point in wander distance, // When only one path grid point in wander distance,
// additional points for NPC to wander to are: // additional points for NPC to wander to are:
// 1. NPC's initial location // 1. NPC's initial location
// 2. Partway along the path between the point and its connected points. // 2. Partway along the path between the point and its connected points.
void AiWander::AddNonPathGridAllowedPoints(osg::Vec3f npcPos, const ESM::Pathgrid * pathGrid, int pointIndex) void AiWander::AddNonPathGridAllowedPoints(osg::Vec3f npcPos, const ESM::Pathgrid * pathGrid, int pointIndex, AiWanderStorage& storage)
{ {
mAllowedNodes.push_back(PathFinder::MakePathgridPoint(npcPos)); storage.mAllowedNodes.push_back(PathFinder::MakePathgridPoint(npcPos));
for (std::vector<ESM::Pathgrid::Edge>::const_iterator it = pathGrid->mEdges.begin(); it != pathGrid->mEdges.end(); ++it) for (std::vector<ESM::Pathgrid::Edge>::const_iterator it = pathGrid->mEdges.begin(); it != pathGrid->mEdges.end(); ++it)
{ {
if (it->mV0 == pointIndex) if (it->mV0 == pointIndex)
{ {
AddPointBetweenPathGridPoints(pathGrid->mPoints[it->mV0], pathGrid->mPoints[it->mV1]); AddPointBetweenPathGridPoints(pathGrid->mPoints[it->mV0], pathGrid->mPoints[it->mV1], storage);
} }
} }
} }
void AiWander::AddPointBetweenPathGridPoints(const ESM::Pathgrid::Point& start, const ESM::Pathgrid::Point& end) void AiWander::AddPointBetweenPathGridPoints(const ESM::Pathgrid::Point& start, const ESM::Pathgrid::Point& end, AiWanderStorage& storage)
{ {
osg::Vec3f vectorStart = PathFinder::MakeOsgVec3(start); osg::Vec3f vectorStart = PathFinder::MakeOsgVec3(start);
osg::Vec3f delta = PathFinder::MakeOsgVec3(end) - vectorStart; osg::Vec3f delta = PathFinder::MakeOsgVec3(end) - vectorStart;
@ -901,16 +907,16 @@ namespace MWMechanics
// must not travel longer than distance between waypoints or NPC goes past waypoint // must not travel longer than distance between waypoints or NPC goes past waypoint
distance = std::min(distance, static_cast<int>(length)); distance = std::min(distance, static_cast<int>(length));
delta *= distance; delta *= distance;
mAllowedNodes.push_back(PathFinder::MakePathgridPoint(vectorStart + delta)); storage.mAllowedNodes.push_back(PathFinder::MakePathgridPoint(vectorStart + delta));
} }
void AiWander::SetCurrentNodeToClosestAllowedNode(osg::Vec3f npcPos) void AiWander::SetCurrentNodeToClosestAllowedNode(osg::Vec3f npcPos, AiWanderStorage& storage)
{ {
float distanceToClosestNode = std::numeric_limits<float>::max(); float distanceToClosestNode = std::numeric_limits<float>::max();
unsigned int index = 0; unsigned int index = 0;
for (unsigned int counterThree = 0; counterThree < mAllowedNodes.size(); counterThree++) for (unsigned int counterThree = 0; counterThree < storage.mAllowedNodes.size(); counterThree++)
{ {
osg::Vec3f nodePos(PathFinder::MakeOsgVec3(mAllowedNodes[counterThree])); osg::Vec3f nodePos(PathFinder::MakeOsgVec3(storage.mAllowedNodes[counterThree]));
float tempDist = (npcPos - nodePos).length2(); float tempDist = (npcPos - nodePos).length2();
if (tempDist < distanceToClosestNode) if (tempDist < distanceToClosestNode)
{ {
@ -918,8 +924,8 @@ namespace MWMechanics
distanceToClosestNode = tempDist; distanceToClosestNode = tempDist;
} }
} }
mCurrentNode = mAllowedNodes[index]; storage.mCurrentNode = storage.mAllowedNodes[index];
mAllowedNodes.erase(mAllowedNodes.begin() + index); storage.mAllowedNodes.erase(storage.mAllowedNodes.begin() + index);
} }
void AiWander::writeState(ESM::AiSequence::AiSequence &sequence) const void AiWander::writeState(ESM::AiSequence::AiSequence &sequence) const

@ -10,7 +10,6 @@
#include "../mwworld/timestamp.hpp" #include "../mwworld/timestamp.hpp"
#include "aistate.hpp" #include "aistate.hpp"
namespace ESM namespace ESM
@ -23,9 +22,7 @@ namespace ESM
} }
namespace MWMechanics namespace MWMechanics
{ {
struct AiWanderStorage; struct AiWanderStorage;
/// \brief Causes the Actor to wander within a specified range /// \brief Causes the Actor to wander within a specified range
@ -42,8 +39,6 @@ namespace MWMechanics
AiWander (const ESM::AiSequence::AiWander* wander); AiWander (const ESM::AiSequence::AiWander* wander);
virtual AiPackage *clone() const; virtual AiPackage *clone() const;
virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration); virtual bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration);
@ -72,10 +67,10 @@ namespace MWMechanics
Wander_MoveNow, Wander_MoveNow,
Wander_Walking Wander_Walking
}; };
private: private:
// NOTE: mDistance and mDuration must be set already // NOTE: mDistance and mDuration must be set already
void init(); void init();
void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage); void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage);
/// Have the given actor play an idle animation /// Have the given actor play an idle animation
@ -107,42 +102,16 @@ namespace MWMechanics
int mTimeOfDay; int mTimeOfDay;
std::vector<unsigned char> mIdle; std::vector<unsigned char> mIdle;
bool mRepeat; bool mRepeat;
bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position, bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position,
// if we had the actor in the AiWander constructor... // if we had the actor in the AiWander constructor...
osg::Vec3f mReturnPosition; osg::Vec3f mReturnPosition;
osg::Vec3f mInitialActorPosition; osg::Vec3f mInitialActorPosition;
bool mStoredInitialActorPosition; bool mStoredInitialActorPosition;
// do we need to calculate allowed nodes based on mDistance
bool mPopulateAvailableNodes;
// allowed pathgrid nodes based on mDistance from the spawn point
// in local coordinates of mCell
// FIXME: move to AiWanderStorage
std::vector<ESM::Pathgrid::Point> mAllowedNodes;
void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage); void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage);
// FIXME: move to AiWanderStorage void trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes, const PathFinder& pathfinder);
ESM::Pathgrid::Point mCurrentNode;
bool mTrimCurrentNode;
void trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
const PathFinder& pathfinder);
// FIXME: move to AiWanderStorage
// ObstacleCheck mObstacleCheck;
float mDoorCheckDuration;
int mStuckCount;
// constants for converting idleSelect values into groupNames // constants for converting idleSelect values into groupNames
enum GroupIndex enum GroupIndex
@ -154,19 +123,17 @@ namespace MWMechanics
/// convert point from local (i.e. cell) to world co-ordinates /// convert point from local (i.e. cell) to world co-ordinates
void ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell); void ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell);
void SetCurrentNodeToClosestAllowedNode(osg::Vec3f npcPos); void SetCurrentNodeToClosestAllowedNode(osg::Vec3f npcPos, AiWanderStorage& storage);
void AddNonPathGridAllowedPoints(osg::Vec3f npcPos, const ESM::Pathgrid * pathGrid, int pointIndex); void AddNonPathGridAllowedPoints(osg::Vec3f npcPos, const ESM::Pathgrid * pathGrid, int pointIndex, AiWanderStorage& storage);
void AddPointBetweenPathGridPoints(const ESM::Pathgrid::Point& start, const ESM::Pathgrid::Point& end); void AddPointBetweenPathGridPoints(const ESM::Pathgrid::Point& start, const ESM::Pathgrid::Point& end, AiWanderStorage& storage);
/// lookup table for converting idleSelect value to groupName /// lookup table for converting idleSelect value to groupName
static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1]; static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1];
static int OffsetToPreventOvercrowding(); static int OffsetToPreventOvercrowding();
}; };
} }
#endif #endif

Loading…
Cancel
Save