Browse Source

aiInfo getPosition now optionally takes a doCastray bool (off by default)

AIFlyingVehicleControllerData add flightfloor and cieling
resolvepitch from (portions of) the old aiflyingvehicle resource
no reversing for flyingvehicles, so bottom out resolvespeed at 0
AzaezelX 5 months ago
parent
commit
584093f48d

+ 61 - 13
Engine/source/T3D/AI/AIController.cpp

@@ -158,7 +158,7 @@ bool AIController::getAIMove(Move* movePtr)
             if (getGoal()->mObj.isValid())
             if (getGoal()->mObj.isValid())
                getNav()->followObject(getGoal()->mObj, mControllerData->mFollowTolerance);
                getNav()->followObject(getGoal()->mObj, mControllerData->mFollowTolerance);
             else if (getGoal()->mPosSet)
             else if (getGoal()->mPosSet)
-               getNav()->setPathDestination(getGoal()->getPosition());
+               getNav()->setPathDestination(getGoal()->getPosition(true));
          }
          }
       }
       }
       else
       else
@@ -271,7 +271,7 @@ DefineEngineMethod(AIController, setMoveSpeed, void, (F32 speed), ,
    "@brief Sets the move speed for an AI object.\n\n"
    "@brief Sets the move speed for an AI object.\n\n"
 
 
    "@param speed A speed multiplier between 0.0 and 1.0.  "
    "@param speed A speed multiplier between 0.0 and 1.0.  "
-   "This is multiplied by the AIPlayer's base movement rates (as defined in "
+   "This is multiplied by the AIController controlled object's base movement rates (as defined in "
    "its PlayerData datablock)\n\n"
    "its PlayerData datablock)\n\n"
 
 
    "@see getMoveDestination()\n")
    "@see getMoveDestination()\n")
@@ -290,7 +290,7 @@ DefineEngineMethod(AIController, getMoveSpeed, F32, (), ,
 }
 }
 
 
 DefineEngineMethod(AIController, stop, void, (), ,
 DefineEngineMethod(AIController, stop, void, (), ,
-   "@brief Tells the AIPlayer to stop moving.\n\n")
+   "@brief Tells the AIController controlled object to stop moving.\n\n")
 {
 {
    object->mMovement.stopMove();
    object->mMovement.stopMove();
 }
 }
@@ -514,28 +514,35 @@ void AIControllerData::initPersistFields()
 
 
    addFieldV("moveTolerance", TypeRangedF32, Offset(mMoveTolerance, AIControllerData), &CommonValidators::PositiveFloat,
    addFieldV("moveTolerance", TypeRangedF32, Offset(mMoveTolerance, AIControllerData), &CommonValidators::PositiveFloat,
       "@brief Distance from destination before stopping.\n\n"
       "@brief Distance from destination before stopping.\n\n"
-      "When the AIPlayer is moving to a given destination it will move to within "
+      "When the AIController controlled object is moving to a given destination it will move to within "
       "this distance of the destination and then stop.  By providing this tolerance "
       "this distance of the destination and then stop.  By providing this tolerance "
-      "it helps the AIPlayer from never reaching its destination due to minor obstacles, "
+      "it helps the AIController controlled object from never reaching its destination due to minor obstacles, "
       "rounding errors on its position calculation, etc.  By default it is set to 0.25.\n");
       "rounding errors on its position calculation, etc.  By default it is set to 0.25.\n");
 
 
    addFieldV("followTolerance", TypeRangedF32, Offset(mFollowTolerance, AIControllerData), &CommonValidators::PositiveFloat,
    addFieldV("followTolerance", TypeRangedF32, Offset(mFollowTolerance, AIControllerData), &CommonValidators::PositiveFloat,
       "@brief Distance from destination before stopping.\n\n"
       "@brief Distance from destination before stopping.\n\n"
-      "When the AIPlayer is moving to a given destination it will move to within "
+      "When the AIController controlled object is moving to a given destination it will move to within "
       "this distance of the destination and then stop.  By providing this tolerance "
       "this distance of the destination and then stop.  By providing this tolerance "
-      "it helps the AIPlayer from never reaching its destination due to minor obstacles, "
+      "it helps the AIController controlled object from never reaching its destination due to minor obstacles, "
       "rounding errors on its position calculation, etc.  By default it is set to 0.25.\n");
       "rounding errors on its position calculation, etc.  By default it is set to 0.25.\n");
 
 
    addFieldV("moveStuckTolerance", TypeRangedF32, Offset(mMoveStuckTolerance, AIControllerData), &CommonValidators::PositiveFloat,
    addFieldV("moveStuckTolerance", TypeRangedF32, Offset(mMoveStuckTolerance, AIControllerData), &CommonValidators::PositiveFloat,
       "@brief Distance tolerance on stuck check.\n\n"
       "@brief Distance tolerance on stuck check.\n\n"
-      "When the AIPlayer is moving to a given destination, if it ever moves less than "
-      "this tolerance during a single tick, the AIPlayer is considered stuck.  At this point "
+      "When the AIController controlled object controlled object is moving to a given destination, if it ever moves less than "
+      "this tolerance during a single tick, the AIController controlled object is considered stuck.  At this point "
       "the onMoveStuck() callback is called on the datablock.\n");
       "the onMoveStuck() callback is called on the datablock.\n");
 
 
+   addFieldV("HeightTolerance", TypeRangedF32, Offset(mHeightTolerance, AIControllerData), &CommonValidators::PositiveFloat,
+      "@brief Distance from destination before stopping.\n\n"
+      "When the AIController controlled object is moving to a given destination it will move to within "
+      "this distance of the destination and then stop.  By providing this tolerance "
+      "it helps the AIController controlled object from never reaching its destination due to minor obstacles, "
+      "rounding errors on its position calculation, etc.  By default it is set to 0.25.\n");
+   
    addFieldV("moveStuckTestDelay", TypeRangedS32, Offset(mMoveStuckTestDelay, AIControllerData), &CommonValidators::PositiveInt,
    addFieldV("moveStuckTestDelay", TypeRangedS32, Offset(mMoveStuckTestDelay, AIControllerData), &CommonValidators::PositiveInt,
-      "@brief The number of ticks to wait before testing if the AIPlayer is stuck.\n\n"
-      "When the AIPlayer is asked to move, this property is the number of ticks to wait "
-      "before the AIPlayer starts to check if it is stuck.  This delay allows the AIPlayer "
+      "@brief The number of ticks to wait before testing if the AIController controlled object is stuck.\n\n"
+      "When the AIController controlled object is asked to move, this property is the number of ticks to wait "
+      "before the AIController controlled object starts to check if it is stuck.  This delay allows the AIController controlled object "
       "to accelerate to full speed without its initial slow start being considered as stuck.\n"
       "to accelerate to full speed without its initial slow start being considered as stuck.\n"
       "@note Set to zero to have the stuck test start immediately.\n");
       "@note Set to zero to have the stuck test start immediately.\n");
 
 
@@ -796,6 +803,22 @@ void AIWheeledVehicleControllerData::resolveSpeed(AIController* obj, Point3F loc
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 IMPLEMENT_CO_DATABLOCK_V1(AIFlyingVehicleControllerData);
 IMPLEMENT_CO_DATABLOCK_V1(AIFlyingVehicleControllerData);
+
+void AIFlyingVehicleControllerData::initPersistFields()
+{
+   docsURL;
+   addGroup("AI");
+
+   addFieldV("FlightFloor", TypeRangedF32, Offset(mFlightFloor, AIFlyingVehicleControllerData), &CommonValidators::PositiveFloat,
+      "@brief Max height we can target.");
+
+   addFieldV("FlightCeiling", TypeRangedF32, Offset(mFlightCeiling, AIFlyingVehicleControllerData), &CommonValidators::PositiveFloat,
+      "@brief Max height we can target.");
+
+   endGroup("AI");
+
+   Parent::initPersistFields();
+}
 // Build a Triangle .. calculate angle of rotation required to meet target..
 // Build a Triangle .. calculate angle of rotation required to meet target..
 // man there has to be a better way! >:)
 // man there has to be a better way! >:)
 F32 AIFlyingVehicleControllerData::getSteeringAngle(AIController* obj, Point3F location)
 F32 AIFlyingVehicleControllerData::getSteeringAngle(AIController* obj, Point3F location)
@@ -927,6 +950,31 @@ void AIFlyingVehicleControllerData::resolveYaw(AIController* obj, Point3F locati
    }
    }
 };
 };
 
 
+void AIFlyingVehicleControllerData::resolvePitch(AIController* obj, Point3F location, Move* movePtr)
+{
+   FlyingVehicle* wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj.getPointer());
+   if (!wvo)
+   {
+      //cover the case of a connection controling an object in turn controlling another
+      if (obj->getAIInfo()->mObj->getObjectMount())
+         wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj->getObjectMount());
+   }
+   if (!wvo) return;//not a FlyingVehicle
+
+   Point3F up = wvo->getTransform().getUpVector();
+   up.normalize();
+   Point3F aimLoc = obj->mMovement.mAimLocation;
+   aimLoc.z = mClampF(aimLoc.z, mFlightFloor, mFlightCeiling);
+
+   // Get the Target to AI vector and normalize it.
+   Point3F toTarg = aimLoc - location;
+   toTarg.normalize();
+
+   F32 dotPitch = mDot(up, toTarg);
+   if (mFabs(dotPitch) > 0.05f)
+      movePtr->pitch = -dotPitch;
+}
+
 void AIFlyingVehicleControllerData::resolveSpeed(AIController* obj, Point3F location, Move* movePtr)
 void AIFlyingVehicleControllerData::resolveSpeed(AIController* obj, Point3F location, Move* movePtr)
 {
 {
    FlyingVehicle* wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj.getPointer());
    FlyingVehicle* wvo = dynamic_cast<FlyingVehicle*>(obj->getAIInfo()->mObj.getPointer());
@@ -942,6 +990,6 @@ void AIFlyingVehicleControllerData::resolveSpeed(AIController* obj, Point3F loca
 
 
    VehicleData* db = static_cast<VehicleData*>(wvo->getDataBlock());
    VehicleData* db = static_cast<VehicleData*>(wvo->getDataBlock());
    movePtr->x = 0;// 1.1 - wvo->getSteering().x / db->maxSteeringAngle;
    movePtr->x = 0;// 1.1 - wvo->getSteering().x / db->maxSteeringAngle;
-   movePtr->y *= 1.1 - wvo->getSteering().y / db->maxSteeringAngle;
+   movePtr->y = mMax(movePtr->y*1.1 - wvo->getSteering().y / db->maxSteeringAngle, 0.0f);
 }
 }
 #endif //_AICONTROLLER_H_
 #endif //_AICONTROLLER_H_

+ 8 - 1
Engine/source/T3D/AI/AIController.h

@@ -236,17 +236,24 @@ class AIFlyingVehicleControllerData : public AIControllerData
       Right,
       Right,
       Straight
       Straight
    };
    };
-
+   F32 mFlightFloor;
+   F32 mFlightCeiling;
 public:
 public:
    AIFlyingVehicleControllerData()
    AIFlyingVehicleControllerData()
    {
    {
       resolveYawPtr.bind(this, &AIFlyingVehicleControllerData::resolveYaw);
       resolveYawPtr.bind(this, &AIFlyingVehicleControllerData::resolveYaw);
+      resolvePitchPtr.bind(this, &AIFlyingVehicleControllerData::resolvePitch);
       resolveSpeedPtr.bind(this, &AIFlyingVehicleControllerData::resolveSpeed);
       resolveSpeedPtr.bind(this, &AIFlyingVehicleControllerData::resolveSpeed);
       mHeightTolerance = 200.0f;
       mHeightTolerance = 200.0f;
+      mFlightCeiling = 200.0f;
+      mFlightFloor = 1.0;
    }
    }
+   static void initPersistFields();
    F32 getSteeringAngle(AIController* obj, Point3F location);
    F32 getSteeringAngle(AIController* obj, Point3F location);
    void resolveYaw(AIController* obj, Point3F location, Move* movePtr);
    void resolveYaw(AIController* obj, Point3F location, Move* movePtr);
    void resolveSpeed(AIController* obj, Point3F location, Move* movePtr);
    void resolveSpeed(AIController* obj, Point3F location, Move* movePtr);
+   void resolvePitch(AIController* obj, Point3F location, Move* movePtr);
+
    DECLARE_CONOBJECT(AIFlyingVehicleControllerData);
    DECLARE_CONOBJECT(AIFlyingVehicleControllerData);
 };
 };
 #endif // TORQUE_NAVIGATION_ENABLED
 #endif // TORQUE_NAVIGATION_ENABLED

+ 21 - 1
Engine/source/T3D/AI/AIInfo.cpp

@@ -52,10 +52,30 @@ AIInfo::AIInfo(AIController* controller, Point3F pointIn, F32 radIn)
    mPosSet = true;
    mPosSet = true;
 };
 };
 
 
+Point3F AIInfo::getPosition(bool doCastray)
+{
+   Point3F pos = (mObj.isValid()) ? mObj->getPosition() : mPosition;
+   if (doCastray)
+   {
+      RayInfo info;
+      if (gServerContainer.castRay(pos, pos - Point3F(0, 0, getCtrl()->mControllerData->mHeightTolerance), StaticShapeObjectType, &info))
+      {
+         pos = info.point;
+      }
+   }
+
+   return pos;
+}
+
 F32 AIInfo::getDist()
 F32 AIInfo::getDist()
 {
 {
    AIInfo* controlObj = getCtrl()->getAIInfo();
    AIInfo* controlObj = getCtrl()->getAIInfo();
-   F32 ret = VectorF(controlObj->getPosition() - getPosition()).len();
+   Point3F targPos = getPosition();
+
+   if (mFabs(targPos.z - controlObj->getPosition().z) < getCtrl()->mControllerData->mHeightTolerance)
+      targPos.z = controlObj->getPosition().z;
+
+   F32 ret = VectorF(controlObj->getPosition() - targPos).len();
    ret -= controlObj->mRadius + mRadius;
    ret -= controlObj->mRadius + mRadius;
    return ret;
    return ret;
 }
 }

+ 1 - 1
Engine/source/T3D/AI/AIInfo.h

@@ -36,7 +36,7 @@ struct AIInfo
    Point3F mPosition, mLastPos;
    Point3F mPosition, mLastPos;
    bool mPosSet;
    bool mPosSet;
    F32 mRadius;
    F32 mRadius;
-   Point3F getPosition() { return (mObj.isValid()) ? mObj->getPosition() : mPosition; }
+   Point3F getPosition(bool doCastray = false);
    F32 getDist();
    F32 getDist();
    AIInfo() = delete;
    AIInfo() = delete;
    AIInfo(AIController* controller);
    AIInfo(AIController* controller);

+ 5 - 5
Engine/source/T3D/AI/AINavigation.cpp

@@ -134,11 +134,11 @@ void AINavigation::repath()
    else
    else
    {
    {
       // If we're following, get their position.
       // If we're following, get their position.
-      mPathData.path->mTo = getCtrl()->getGoal()->getPosition();
+      mPathData.path->mTo = getCtrl()->getGoal()->getPosition(true);
    }
    }
 
 
    // Update from position and replan.
    // Update from position and replan.
-   mPathData.path->mFrom = getCtrl()->getAIInfo()->getPosition();
+   mPathData.path->mFrom = getCtrl()->getAIInfo()->getPosition(true);
    mPathData.path->plan();
    mPathData.path->plan();
 
 
    // Move to first node (skip start pos).
    // Move to first node (skip start pos).
@@ -215,8 +215,8 @@ bool AINavigation::setPathDestination(const Point3F& pos, bool replace)
    NavPath* path = new NavPath();
    NavPath* path = new NavPath();
 
 
    path->mMesh = mNavMesh;
    path->mMesh = mNavMesh;
-   path->mFrom = getCtrl()->getAIInfo()->getPosition();
-   path->mTo = getCtrl()->getGoal()->getPosition();
+   path->mFrom = getCtrl()->getAIInfo()->getPosition(true);
+   path->mTo = getCtrl()->getGoal()->getPosition(true);
    path->mFromSet = path->mToSet = true;
    path->mFromSet = path->mToSet = true;
    path->mAlwaysRender = true;
    path->mAlwaysRender = true;
    path->mLinkTypes = getCtrl()->mControllerData->mLinkTypes;
    path->mLinkTypes = getCtrl()->mControllerData->mLinkTypes;
@@ -257,7 +257,7 @@ void AINavigation::followObject()
    if (getCtrl()->getGoal()->getDist() < getCtrl()->mControllerData->mMoveTolerance)
    if (getCtrl()->getGoal()->getDist() < getCtrl()->mControllerData->mMoveTolerance)
       return;
       return;
 
 
-   if (setPathDestination(getCtrl()->getGoal()->getPosition()))
+   if (setPathDestination(getCtrl()->getGoal()->getPosition(true)))
    {
    {
       getCtrl()->clearCover();
       getCtrl()->clearCover();
    }
    }