/** * Called when we get within mMoveTolerance of our destination set using * setMoveDestination(). Only fires the script callback if we are at the end * of a pathfinding path, or have no pathfinding path. */ void AIPlayer::onReachDestination() { #ifdef TORQUE_NAVIGATION_ENABLED if(!mPathData.path.isNull()) { if(mPathData.index == mPathData.path->size() - 1) { // Handle looping paths. if(mPathData.path->mIsLooping) moveToNode(0); // Otherwise end path. else { clearPath(); throwCallback("onReachDestination"); } } else { moveToNode(mPathData.index + 1); // Throw callback every time if we're on a looping path. //if(mPathData.path->mIsLooping) //throwCallback("onReachDestination"); } } else #endif throwCallback("onReachDestination"); }
bool AIPlayer::setPathDestination(const Point3F &pos) { // Pathfinding only happens on the server. if(!isServerObject()) return false; if(!getNavMesh()) updateNavMesh(); // If we can't find a mesh, just move regularly. if(!getNavMesh()) { //setMoveDestination(pos); throwCallback("onPathFailed"); return false; } // Create a new path. NavPath *path = new NavPath(); path->mMesh = getNavMesh(); path->mFrom = getPosition(); path->mTo = pos; path->mFromSet = path->mToSet = true; path->mAlwaysRender = true; path->mLinkTypes = mLinkTypes; path->mXray = true; // Paths plan automatically upon being registered. if(!path->registerObject()) { delete path; return false; } if(path->success()) { // Clear any current path we might have. clearPath(); clearCover(); clearFollow(); // Store new path. mPathData.path = path; mPathData.owned = true; // Skip node 0, which we are currently standing on. moveToNode(1); throwCallback("onPathSuccess"); return true; } else { // Just move normally if we can't path. //setMoveDestination(pos, true); //return; throwCallback("onPathFailed"); path->deleteObject(); return false; } }
void SearcherThread::run(void) { { if (!node->isOpen()) return; t->mutex.lock(); emit statusChanged(false); unsigned int kids = node->getNumberOfChildNodes(*t->na, t->curBest, t->stats, t->c_d, t->a_d); if (kids == 0 || node->getStatus() == STOP) { t->mutex.unlock(); updateCanvas(); emit statusChanged(true); return; } std::stack<SearchItem> stck; stck.push(SearchItem(node,kids)); t->stats.maxDepth = std::max(static_cast<long unsigned int>(t->stats.maxDepth), static_cast<long unsigned int>(depth+stck.size())); VisualNode* sol = NULL; int nodeCount = 0; t->stopSearchFlag = false; while (!stck.empty() && !t->stopSearchFlag) { if (t->refresh > 0 && nodeCount >= t->refresh) { node->dirtyUp(*t->na); updateCanvas(); emit statusChanged(false); nodeCount = 0; if (t->refreshPause > 0) msleep(t->refreshPause); } SearchItem& si = stck.top(); si.i++; if (si.i == si.noOfChildren) { stck.pop(); } else { VisualNode* n = si.n->getChild(*t->na,si.i); if (n->isOpen()) { if (n->getStatus() == UNDETERMINED) nodeCount++; kids = n->getNumberOfChildNodes(*t->na, t->curBest, t->stats, t->c_d, t->a_d); if (t->moveDuringSearch) emit moveToNode(n,false); if (kids == 0) { if (n->getStatus() == SOLVED) { assert(n->hasCopy()); emit solution(n->getWorkingSpace()); n->purge(*t->na); sol = n; if (!a) break; } } else { if ( n->getStatus() != STOP ) stck.push(SearchItem(n,kids)); else if (!a) break; t->stats.maxDepth = std::max(static_cast<long unsigned int>(t->stats.maxDepth), static_cast<long unsigned int>(depth+stck.size())); } } } } node->dirtyUp(*t->na); t->stopSearchFlag = false; t->mutex.unlock(); if (sol != NULL) { t->setCurrentNode(sol,true,false); } else { t->setCurrentNode(node,true,false); } } updateCanvas(); emit statusChanged(true); if (t->finishedFlag) emit searchFinished(); }