mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 03:35:27 +00:00
Fixed issue where allowed nodes were being erased. PathFinder was returning an empty path if the closest pathgrid point to the start was also the closest pathgrid point to the goal. Still need to clean up and remove logging statements.
This commit is contained in:
parent
d3be725ee7
commit
aad13d315c
@ -112,11 +112,13 @@ namespace MWMechanics
|
|||||||
* allowed set. The issue is when the door opens the allowed set is not
|
* allowed set. The issue is when the door opens the allowed set is not
|
||||||
* re-calculated. Normally this would not be an issue since hostile actors will
|
* re-calculated. Normally this would not be an issue since hostile actors will
|
||||||
* enter combat (i.e. no longer wandering)
|
* enter combat (i.e. no longer wandering)
|
||||||
*
|
|
||||||
* FIXME: Sometimes allowed nodes that shouldn't be deleted are deleted.
|
|
||||||
*/
|
*/
|
||||||
bool AiWander::execute (const MWWorld::Ptr& actor,float duration)
|
bool AiWander::execute (const MWWorld::Ptr& actor,float duration)
|
||||||
{
|
{
|
||||||
|
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
|
||||||
|
if(cStats.isDead() || cStats.getHealth().getCurrent() <= 0)
|
||||||
|
return true; // Don't bother with dead actors
|
||||||
|
|
||||||
bool cellChange = mCell && (actor.getCell() != mCell);
|
bool cellChange = mCell && (actor.getCell() != mCell);
|
||||||
if(!mCell || cellChange)
|
if(!mCell || cellChange)
|
||||||
{
|
{
|
||||||
@ -125,7 +127,6 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
const ESM::Cell *cell = mCell->getCell();
|
const ESM::Cell *cell = mCell->getCell();
|
||||||
|
|
||||||
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
|
|
||||||
cStats.setDrawState(DrawState_Nothing);
|
cStats.setDrawState(DrawState_Nothing);
|
||||||
cStats.setMovementFlag(CreatureStats::Flag_Run, false);
|
cStats.setMovementFlag(CreatureStats::Flag_Run, false);
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
@ -188,45 +189,56 @@ namespace MWMechanics
|
|||||||
mYCell = mCellY * ESM::Land::REAL_SIZE;
|
mYCell = mCellY * ESM::Land::REAL_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert actorPos to local (i.e. cell) co-ordinates
|
// FIXME: There might be a bug here. The allowed node points are
|
||||||
Ogre::Vector3 actorPos(pos.pos);
|
// based on the actor's current position rather than the actor's
|
||||||
actorPos[0] = actorPos[0] - mXCell;
|
// spawn point. As a result the allowed nodes for wander can change
|
||||||
actorPos[1] = actorPos[1] - mYCell;
|
// between saves, for example.
|
||||||
|
//
|
||||||
|
// convert npcPos to local (i.e. cell) co-ordinates
|
||||||
|
Ogre::Vector3 npcPos(pos.pos);
|
||||||
|
npcPos[0] = npcPos[0] - mXCell;
|
||||||
|
npcPos[1] = npcPos[1] - mYCell;
|
||||||
|
|
||||||
// mAllowedNodes for this actor with pathgrid point indexes
|
// mAllowedNodes for this actor with pathgrid point indexes based on mDistance
|
||||||
// based on mDistance
|
|
||||||
// NOTE: mPoints and mAllowedNodes are in local co-ordinates
|
// NOTE: mPoints and mAllowedNodes are in local co-ordinates
|
||||||
float closestNodeDist = -1;
|
|
||||||
unsigned int closestIndex = 0;
|
|
||||||
unsigned int indexAllowedNodes = 0;
|
|
||||||
for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++)
|
for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++)
|
||||||
{
|
{
|
||||||
float sqrDist = actorPos.squaredDistance(Ogre::Vector3(
|
Ogre::Vector3 nodePos(pathgrid->mPoints[counter].mX, pathgrid->mPoints[counter].mY,
|
||||||
pathgrid->mPoints[counter].mX,
|
pathgrid->mPoints[counter].mZ);
|
||||||
pathgrid->mPoints[counter].mY,
|
if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance)
|
||||||
pathgrid->mPoints[counter].mZ));
|
|
||||||
if(sqrDist <= (mDistance * mDistance))
|
|
||||||
{
|
|
||||||
mAllowedNodes.push_back(pathgrid->mPoints[counter]);
|
mAllowedNodes.push_back(pathgrid->mPoints[counter]);
|
||||||
// keep track of the closest node
|
|
||||||
if(closestNodeDist == -1 || sqrDist < closestNodeDist)
|
|
||||||
{
|
|
||||||
closestNodeDist = sqrDist;
|
|
||||||
closestIndex = indexAllowedNodes;
|
|
||||||
}
|
|
||||||
indexAllowedNodes++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(!mAllowedNodes.empty())
|
if(!mAllowedNodes.empty())
|
||||||
{
|
{
|
||||||
// Start with the closest node and remove it from the allowed set
|
Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ);
|
||||||
// so that it does not get selected again. The removed node will
|
float closestNode = npcPos.squaredDistance(firstNodePos);
|
||||||
// later be put in the back of the queue, unless it gets removed
|
unsigned int index = 0;
|
||||||
// due to inaccessibility (e.g. a closed door)
|
for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
|
||||||
mCurrentNode = mAllowedNodes[closestIndex];
|
{
|
||||||
mAllowedNodes.erase(mAllowedNodes.begin() + closestIndex);
|
Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY,
|
||||||
// set only if successful in finding allowed nodes
|
mAllowedNodes[counterThree].mZ);
|
||||||
mStoredAvailableNodes = true;
|
float tempDist = npcPos.squaredDistance(nodePos);
|
||||||
|
if(tempDist < closestNode)
|
||||||
|
index = counterThree;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if(actor.getClass().getName(actor) == "Rat")
|
||||||
|
{
|
||||||
|
std::cout << "rat allowed "<< std::to_string(mAllowedNodes.size())
|
||||||
|
+" mDist "+std::to_string(mDistance)
|
||||||
|
+" pos "+std::to_string(static_cast<int>(npcPos[0]))
|
||||||
|
+", "+std::to_string(static_cast<int>(npcPos[1]))
|
||||||
|
<<std::endl;
|
||||||
|
for(int i=0; i<mAllowedNodes.size(); i++)
|
||||||
|
std::cout <<"rat "+std::to_string(mAllowedNodes[i].mX)
|
||||||
|
+", "+std::to_string(mAllowedNodes[i].mY)<<std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
mCurrentNode = mAllowedNodes[index];
|
||||||
|
|
||||||
|
mAllowedNodes.erase(mAllowedNodes.begin() + index);
|
||||||
|
|
||||||
|
mStoredAvailableNodes = true; // set only if successful in finding allowed nodes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,10 +410,14 @@ namespace MWMechanics
|
|||||||
if(mTrimCurrentNode && mAllowedNodes.size() > 1)
|
if(mTrimCurrentNode && mAllowedNodes.size() > 1)
|
||||||
{
|
{
|
||||||
mTrimCurrentNode = false;
|
mTrimCurrentNode = false;
|
||||||
#if 0
|
//#if 0
|
||||||
std::cout << "deleted "<< std::to_string(mCurrentNode.mX)
|
std::cout << "deleted "<< std::to_string(mCurrentNode.mX)
|
||||||
+", "+std::to_string(mCurrentNode.mY) << std::endl;
|
+", "+std::to_string(mCurrentNode.mY) << std::endl;
|
||||||
#endif
|
//#endif
|
||||||
|
//#if 0
|
||||||
|
std::cout << "allowed size "<<
|
||||||
|
std::to_string(mAllowedNodes.size()) << std::endl;
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mAllowedNodes.push_back(mCurrentNode);
|
mAllowedNodes.push_back(mCurrentNode);
|
||||||
@ -412,7 +428,15 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
// 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);
|
mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
|
||||||
|
//#if 0
|
||||||
|
//std::cout << "actor \""<< actor.getClass().getName(actor) << "\"" << std::endl;
|
||||||
|
if(actor.getClass().getName(actor) == "Rat")
|
||||||
|
std::cout << "erase no path "<< std::to_string(mAllowedNodes[randNode].mX)
|
||||||
|
+", "+std::to_string(mAllowedNodes[randNode].mY) << std::endl;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,9 +501,6 @@ namespace MWMechanics
|
|||||||
void AiWander::trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
|
void AiWander::trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
|
||||||
const PathFinder& pathfinder)
|
const PathFinder& pathfinder)
|
||||||
{
|
{
|
||||||
//#if 0
|
|
||||||
std::cout << "allowed size "<< std::to_string(nodes.size()) << std::endl;
|
|
||||||
//#endif
|
|
||||||
// TODO: how to add these back in once the door opens?
|
// TODO: how to add these back in once the door opens?
|
||||||
std::list<ESM::Pathgrid::Point> paths = pathfinder.getPath();
|
std::list<ESM::Pathgrid::Point> paths = pathfinder.getPath();
|
||||||
while(paths.size() >= 2)
|
while(paths.size() >= 2)
|
||||||
|
@ -100,8 +100,11 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(start == closestReachableIndex)
|
// AiWander has logic that depends on whether a path was created, deleting
|
||||||
closestReachableIndex = -1; // couldn't find anyting other than start
|
// allowed nodes if not. Hence a path needs to be created even if the start
|
||||||
|
// and the end points are the same.
|
||||||
|
//if(start == closestReachableIndex)
|
||||||
|
//closestReachableIndex = -1; // couldn't find anyting other than start
|
||||||
|
|
||||||
return std::pair<int, bool>
|
return std::pair<int, bool>
|
||||||
(closestReachableIndex, closestReachableIndex == closestIndex);
|
(closestReachableIndex, closestReachableIndex == closestIndex);
|
||||||
@ -224,6 +227,18 @@ namespace MWMechanics
|
|||||||
// this shouldn't really happen, but just in case
|
// this shouldn't really happen, but just in case
|
||||||
if(endNode.first != -1)
|
if(endNode.first != -1)
|
||||||
{
|
{
|
||||||
|
// AiWander has logic that depends on whether a path was created,
|
||||||
|
// deleting allowed nodes if not. Hence a path needs to be created
|
||||||
|
// even if the start and the end points are the same.
|
||||||
|
// NOTE: aStarSearch will return an empty path if the start and end
|
||||||
|
// nodes are the same
|
||||||
|
if(startNode == endNode.first)
|
||||||
|
{
|
||||||
|
mPath.push_back(endPoint);
|
||||||
|
mIsPathConstructed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mPath = mCell->aStarSearch(startNode, endNode.first);
|
mPath = mCell->aStarSearch(startNode, endNode.first);
|
||||||
|
|
||||||
if(!mPath.empty())
|
if(!mPath.empty())
|
||||||
@ -243,9 +258,32 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
mIsPathConstructed = false;
|
mIsPathConstructed = false;
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
mIsPathConstructed = false;
|
||||||
|
std::cout << "no path "<<
|
||||||
|
std::to_string(startPoint.mX-xCell)
|
||||||
|
+", "+std::to_string(startPoint.mY-yCell)
|
||||||
|
+", "+std::to_string(startNode)
|
||||||
|
+", "+std::to_string(endPoint.mX-xCell)
|
||||||
|
+", "+std::to_string(endPoint.mY-yCell)
|
||||||
|
+", "+std::to_string(endNode.first)<<std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mIsPathConstructed = false;
|
mIsPathConstructed = false;
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
mIsPathConstructed = false;
|
||||||
|
std::cout << "no end "<<
|
||||||
|
std::to_string(startPoint.mX-xCell)
|
||||||
|
+", "+std::to_string(startPoint.mY-yCell)
|
||||||
|
+", "+std::to_string(startNode)
|
||||||
|
+", "+std::to_string(endPoint.mX-xCell)
|
||||||
|
+", "+std::to_string(endPoint.mY-yCell)<<std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mIsPathConstructed = false;
|
mIsPathConstructed = false;
|
||||||
|
@ -206,6 +206,20 @@ namespace MWMechanics
|
|||||||
if(mSCCPoint[v].first == -1) // undefined (haven't visited)
|
if(mSCCPoint[v].first == -1) // undefined (haven't visited)
|
||||||
recursiveStrongConnect(v);
|
recursiveStrongConnect(v);
|
||||||
}
|
}
|
||||||
|
//#if 0
|
||||||
|
// for debugging only
|
||||||
|
if(mCell->mName == "Gnisis, Arvs-Drelen")
|
||||||
|
for(unsigned int v = 0; v < mPathgrid->mPoints.size(); v++)
|
||||||
|
{
|
||||||
|
std::cout << "SCC \"X:" <<
|
||||||
|
std::to_string(mPathgrid->mPoints[v].mX)
|
||||||
|
+", Y:"+std::to_string(mPathgrid->mPoints[v].mY)
|
||||||
|
+", Num:"+std::to_string(mSCCId)
|
||||||
|
+", Point:"+std::to_string(v)
|
||||||
|
+", Group:"+std::to_string(mGraph[v].componentId)
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathgridGraph::isPointConnected(const int start, const int end) const
|
bool PathgridGraph::isPointConnected(const int start, const int end) const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user