|
|
@@ -28,8 +28,10 @@ static U32 sAILoSMask = TerrainObjectType | StaticShapeObjectType | StaticObject
|
|
|
AINavigation::AINavigation(AIController* controller)
|
|
|
{
|
|
|
mControllerRef = controller;
|
|
|
+#ifdef TORQUE_NAVIGATION_ENABLED
|
|
|
mJump = None;
|
|
|
mNavSize = Regular;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
AINavigation::~AINavigation()
|
|
|
@@ -40,6 +42,175 @@ AINavigation::~AINavigation()
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+void AINavigation::setMoveDestination(const Point3F& location, bool slowdown)
|
|
|
+{
|
|
|
+ mMoveDestination = location;
|
|
|
+ getCtrl()->mMovement.mMoveState = AIController::ModeMove;
|
|
|
+ getCtrl()->mMovement.mMoveSlowdown = slowdown;
|
|
|
+ getCtrl()->mMovement.mMoveStuckTestCountdown = getCtrl()->mControllerData->mMoveStuckTestDelay;
|
|
|
+}
|
|
|
+
|
|
|
+bool AINavigation::setPathDestination(const Point3F& pos, bool replace)
|
|
|
+{
|
|
|
+#ifdef TORQUE_NAVIGATION_ENABLED
|
|
|
+ if (replace)
|
|
|
+ getCtrl()->setGoal(pos, getCtrl()->mControllerData->mMoveTolerance);
|
|
|
+
|
|
|
+ if (!mNavMesh)
|
|
|
+ updateNavMesh();
|
|
|
+
|
|
|
+ // If we can't find a mesh, just move regularly.
|
|
|
+ if (!mNavMesh)
|
|
|
+ {
|
|
|
+ //setMoveDestination(pos);
|
|
|
+ getCtrl()->throwCallback("onPathFailed");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create a new path.
|
|
|
+ NavPath* path = new NavPath();
|
|
|
+
|
|
|
+ path->mMesh = mNavMesh;
|
|
|
+ path->mFrom = getCtrl()->getAIInfo()->getPosition(true);
|
|
|
+ path->mTo = getCtrl()->getGoal()->getPosition(true);
|
|
|
+ path->mFromSet = path->mToSet = true;
|
|
|
+ path->mAlwaysRender = true;
|
|
|
+ path->mLinkTypes = getCtrl()->mControllerData->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();
|
|
|
+ getCtrl()->clearCover();
|
|
|
+ // Store new path.
|
|
|
+ mPathData.path = path;
|
|
|
+ mPathData.owned = true;
|
|
|
+ // Skip node 0, which we are currently standing on.
|
|
|
+ moveToNode(1);
|
|
|
+ getCtrl()->throwCallback("onPathSuccess");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Just move normally if we can't path.
|
|
|
+ //setMoveDestination(pos, true);
|
|
|
+ //return;
|
|
|
+ getCtrl()->throwCallback("onPathFailed");
|
|
|
+ path->deleteObject();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ setMoveDestination(pos, false);
|
|
|
+ return true;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+Point3F AINavigation::getPathDestination() const
|
|
|
+{
|
|
|
+#ifdef TORQUE_NAVIGATION_ENABLED
|
|
|
+ if (!mPathData.path.isNull())
|
|
|
+ return mPathData.path->mTo;
|
|
|
+ return Point3F(0, 0, 0);
|
|
|
+#else
|
|
|
+ return getMoveDestination();
|
|
|
+#endif
|
|
|
+}
|
|
|
+void AINavigation::onReachDestination()
|
|
|
+{
|
|
|
+
|
|
|
+#ifdef TORQUE_NAVIGATION_ENABLED
|
|
|
+ if (!getPath().isNull())
|
|
|
+ {
|
|
|
+ if (mPathData.index == getPath()->size() - 1)
|
|
|
+ {
|
|
|
+ // Handle looping paths.
|
|
|
+ if (getPath()->mIsLooping)
|
|
|
+ moveToNode(0);
|
|
|
+ // Otherwise end path.
|
|
|
+ else
|
|
|
+ {
|
|
|
+ clearPath();
|
|
|
+ getCtrl()->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
|
|
|
+ {
|
|
|
+ getCtrl()->throwCallback("onReachDestination");
|
|
|
+ getCtrl()->mMovement.mMoveState = AIController::ModeStop;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+DefineEngineMethod(AIController, setMoveDestination, void, (Point3F goal, bool slowDown), (true),
|
|
|
+ "@brief Tells the AI to move to the location provided\n\n"
|
|
|
+
|
|
|
+ "@param goal Coordinates in world space representing location to move to.\n"
|
|
|
+ "@param slowDown A boolean value. If set to true, the bot will slow down "
|
|
|
+ "when it gets within 5-meters of its move destination. If false, the bot "
|
|
|
+ "will stop abruptly when it reaches the move destination. By default, this is true.\n\n"
|
|
|
+
|
|
|
+ "@note Upon reaching a move destination, the bot will clear its move destination and "
|
|
|
+ "calls to getMoveDestination will return \"0 0 0\"."
|
|
|
+
|
|
|
+ "@see getMoveDestination()\n")
|
|
|
+{
|
|
|
+ object->getNav()->setMoveDestination(goal, slowDown);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+DefineEngineMethod(AIController, getMoveDestination, Point3F, (), ,
|
|
|
+ "@brief Get the AIPlayer's current destination.\n\n"
|
|
|
+
|
|
|
+ "@return Returns a point containing the \"x y z\" position "
|
|
|
+ "of the AIPlayer's current move destination. If no move destination "
|
|
|
+ "has yet been set, this returns \"0 0 0\"."
|
|
|
+
|
|
|
+ "@see setMoveDestination()\n")
|
|
|
+{
|
|
|
+ return object->getNav()->getMoveDestination();
|
|
|
+}
|
|
|
+
|
|
|
+DefineEngineMethod(AIController, setPathDestination, bool, (Point3F goal), ,
|
|
|
+ "@brief Tells the AI to find a path to the location provided\n\n"
|
|
|
+
|
|
|
+ "@param goal Coordinates in world space representing location to move to.\n"
|
|
|
+ "@return True if a path was found.\n\n"
|
|
|
+
|
|
|
+ "@see getPathDestination()\n"
|
|
|
+ "@see setMoveDestination()\n")
|
|
|
+{
|
|
|
+ return object->getNav()->setPathDestination(goal, true);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+DefineEngineMethod(AIController, getPathDestination, Point3F, (), ,
|
|
|
+ "@brief Get the AIPlayer's current pathfinding destination.\n\n"
|
|
|
+
|
|
|
+ "@return Returns a point containing the \"x y z\" position "
|
|
|
+ "of the AIPlayer's current path destination. If no path destination "
|
|
|
+ "has yet been set, this returns \"0 0 0\"."
|
|
|
+
|
|
|
+ "@see setPathDestination()\n")
|
|
|
+{
|
|
|
+ return object->getNav()->getPathDestination();
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef TORQUE_NAVIGATION_ENABLED
|
|
|
NavMesh* AINavigation::findNavMesh() const
|
|
|
{
|
|
|
GameBase* gbo = dynamic_cast<GameBase*>(mControllerRef->getAIInfo()->mObj.getPointer());
|
|
|
@@ -144,113 +315,6 @@ void AINavigation::repath()
|
|
|
moveToNode(1);
|
|
|
}
|
|
|
|
|
|
-Point3F AINavigation::getPathDestination() const
|
|
|
-{
|
|
|
- if (!mPathData.path.isNull())
|
|
|
- return mPathData.path->mTo;
|
|
|
- return Point3F(0, 0, 0);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-void AINavigation::setMoveDestination(const Point3F& location, bool slowdown)
|
|
|
-{
|
|
|
- mMoveDestination = location;
|
|
|
- getCtrl()->mMovement.mMoveState = AIController::ModeMove;
|
|
|
- getCtrl()->mMovement.mMoveSlowdown = slowdown;
|
|
|
- getCtrl()->mMovement.mMoveStuckTestCountdown = getCtrl()->mControllerData->mMoveStuckTestDelay;
|
|
|
-}
|
|
|
-
|
|
|
-void AINavigation::onReachDestination()
|
|
|
-{
|
|
|
-
|
|
|
-#ifdef TORQUE_NAVIGATION_ENABLED
|
|
|
- if (!getPath().isNull())
|
|
|
- {
|
|
|
- if (mPathData.index == getPath()->size() - 1)
|
|
|
- {
|
|
|
- // Handle looping paths.
|
|
|
- if (getPath()->mIsLooping)
|
|
|
- moveToNode(0);
|
|
|
- // Otherwise end path.
|
|
|
- else
|
|
|
- {
|
|
|
- clearPath();
|
|
|
- getCtrl()->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
|
|
|
- {
|
|
|
- getCtrl()->throwCallback("onReachDestination");
|
|
|
- getCtrl()->mMovement.mMoveState = AIController::ModeStop;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-bool AINavigation::setPathDestination(const Point3F& pos, bool replace)
|
|
|
-{
|
|
|
- if (replace)
|
|
|
- getCtrl()->setGoal(pos, getCtrl()->mControllerData->mMoveTolerance);
|
|
|
-
|
|
|
- if (!mNavMesh)
|
|
|
- updateNavMesh();
|
|
|
-
|
|
|
- // If we can't find a mesh, just move regularly.
|
|
|
- if (!mNavMesh)
|
|
|
- {
|
|
|
- //setMoveDestination(pos);
|
|
|
- getCtrl()->throwCallback("onPathFailed");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // Create a new path.
|
|
|
- NavPath* path = new NavPath();
|
|
|
-
|
|
|
- path->mMesh = mNavMesh;
|
|
|
- path->mFrom = getCtrl()->getAIInfo()->getPosition(true);
|
|
|
- path->mTo = getCtrl()->getGoal()->getPosition(true);
|
|
|
- path->mFromSet = path->mToSet = true;
|
|
|
- path->mAlwaysRender = true;
|
|
|
- path->mLinkTypes = getCtrl()->mControllerData->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();
|
|
|
- getCtrl()->clearCover();
|
|
|
- // Store new path.
|
|
|
- mPathData.path = path;
|
|
|
- mPathData.owned = true;
|
|
|
- // Skip node 0, which we are currently standing on.
|
|
|
- moveToNode(1);
|
|
|
- getCtrl()->throwCallback("onPathSuccess");
|
|
|
- return true;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Just move normally if we can't path.
|
|
|
- //setMoveDestination(pos, true);
|
|
|
- //return;
|
|
|
- getCtrl()->throwCallback("onPathFailed");
|
|
|
- path->deleteObject();
|
|
|
- return false;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void AINavigation::followObject()
|
|
|
{
|
|
|
if (getCtrl()->getGoal()->getDist() < getCtrl()->mControllerData->mMoveTolerance)
|
|
|
@@ -422,59 +486,6 @@ bool AINavigation::flock()
|
|
|
return flocking;
|
|
|
}
|
|
|
|
|
|
-DefineEngineMethod(AIController, setMoveDestination, void, (Point3F goal, bool slowDown), (true),
|
|
|
- "@brief Tells the AI to move to the location provided\n\n"
|
|
|
-
|
|
|
- "@param goal Coordinates in world space representing location to move to.\n"
|
|
|
- "@param slowDown A boolean value. If set to true, the bot will slow down "
|
|
|
- "when it gets within 5-meters of its move destination. If false, the bot "
|
|
|
- "will stop abruptly when it reaches the move destination. By default, this is true.\n\n"
|
|
|
-
|
|
|
- "@note Upon reaching a move destination, the bot will clear its move destination and "
|
|
|
- "calls to getMoveDestination will return \"0 0 0\"."
|
|
|
-
|
|
|
- "@see getMoveDestination()\n")
|
|
|
-{
|
|
|
- object->getNav()->setMoveDestination(goal, slowDown);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-DefineEngineMethod(AIController, getMoveDestination, Point3F, (), ,
|
|
|
- "@brief Get the AIPlayer's current destination.\n\n"
|
|
|
-
|
|
|
- "@return Returns a point containing the \"x y z\" position "
|
|
|
- "of the AIPlayer's current move destination. If no move destination "
|
|
|
- "has yet been set, this returns \"0 0 0\"."
|
|
|
-
|
|
|
- "@see setMoveDestination()\n")
|
|
|
-{
|
|
|
- return object->getNav()->getMoveDestination();
|
|
|
-}
|
|
|
-
|
|
|
-DefineEngineMethod(AIController, setPathDestination, bool, (Point3F goal), ,
|
|
|
- "@brief Tells the AI to find a path to the location provided\n\n"
|
|
|
-
|
|
|
- "@param goal Coordinates in world space representing location to move to.\n"
|
|
|
- "@return True if a path was found.\n\n"
|
|
|
-
|
|
|
- "@see getPathDestination()\n"
|
|
|
- "@see setMoveDestination()\n")
|
|
|
-{
|
|
|
- return object->getNav()->setPathDestination(goal,true);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-DefineEngineMethod(AIController, getPathDestination, Point3F, (), ,
|
|
|
- "@brief Get the AIPlayer's current pathfinding destination.\n\n"
|
|
|
-
|
|
|
- "@return Returns a point containing the \"x y z\" position "
|
|
|
- "of the AIPlayer's current path destination. If no path destination "
|
|
|
- "has yet been set, this returns \"0 0 0\"."
|
|
|
-
|
|
|
- "@see setPathDestination()\n")
|
|
|
-{
|
|
|
- return object->getNav()->getPathDestination();
|
|
|
-}
|
|
|
|
|
|
DefineEngineMethod(AIController, followNavPath, void, (SimObjectId obj), ,
|
|
|
"@brief Tell the AIPlayer to follow a path.\n\n"
|
|
|
@@ -555,3 +566,4 @@ DefineEngineMethod(AIController, getNavSize, const char*, (), ,
|
|
|
}
|
|
|
return "";
|
|
|
}
|
|
|
+#endif
|