diff --git a/Engine/source/T3D/aiPlayer.cpp b/Engine/source/T3D/aiPlayer.cpp index 8b35e478e..40fcc4709 100644 --- a/Engine/source/T3D/aiPlayer.cpp +++ b/Engine/source/T3D/aiPlayer.cpp @@ -145,6 +145,9 @@ void AIPlayer::initPersistFields() "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"); + addField( "AttackRadius", TypeF32, Offset( mAttackRadius, AIPlayer ), + "@brief Distance considered in firing range for callback purposes."); + endGroup( "AI" ); #ifdef TORQUE_NAVIGATION_ENABLED @@ -372,6 +375,11 @@ bool AIPlayer::getAIMove(Move *movePtr) { clearPath(); mMoveState = ModeStop; + throwCallback("onTargetInRange"); + } + else if((getPosition() - mFollowData.object->getPosition()).len() < mAttackRadius) + { + throwCallback("onTargetInFiringRange"); } } } @@ -499,7 +507,7 @@ bool AIPlayer::getAIMove(Move *movePtr) { F32 speed = mMoveSpeed; F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff); - F32 maxDist = 5.0f; + F32 maxDist = mMoveTolerance*2; if (dist < maxDist) speed *= dist / maxDist; movePtr->x *= speed; @@ -539,29 +547,22 @@ bool AIPlayer::getAIMove(Move *movePtr) // Test for target location in sight if it's an object. The LOS is // run from the eye position to the center of the object's bounding, // which is not very accurate. - if (mAimObject) { - MatrixF eyeMat; - getEyeTransform(&eyeMat); - eyeMat.getColumn(3,&location); - Point3F targetLoc = mAimObject->getBoxCenter(); - - // This ray ignores non-static shapes. Cast Ray returns true - // if it hit something. - RayInfo dummy; - if (getContainer()->castRay( location, targetLoc, - StaticShapeObjectType | StaticObjectType | - TerrainObjectType, &dummy)) { - if (mTargetInLOS) { - throwCallback( "onTargetExitLOS" ); - mTargetInLOS = false; - } - } - else - if (!mTargetInLOS) { + if (mAimObject) + { + if (checkInLos(mAimObject.getPointer())) + { + if (!mTargetInLOS) + { throwCallback( "onTargetEnterLOS" ); mTargetInLOS = true; } } + else if (mTargetInLOS) + { + throwCallback( "onTargetExitLOS" ); + mTargetInLOS = false; + } + } Pose desiredPose = mPose; @@ -606,14 +607,24 @@ bool AIPlayer::getAIMove(Move *movePtr) return true; } +void AIPlayer::updateMove(const Move* move) +{ + if (!getControllingClient() && isGhost()) + return; + + Parent::updateMove(move); +} + void AIPlayer::setAiPose( S32 pose ) { + if (!getControllingClient() && isGhost()) + return; mAiPose = pose; } S32 AIPlayer::getAiPose() { - return mAiPose; + return mAiPose; } /** @@ -745,6 +756,7 @@ bool AIPlayer::setPathDestination(const Point3F &pos) if(!getNavMesh()) { //setMoveDestination(pos); + throwCallback("onPathFailed"); return false; } @@ -776,6 +788,7 @@ bool AIPlayer::setPathDestination(const Point3F &pos) mPathData.owned = true; // Skip node 0, which we are currently standing on. moveToNode(1); + throwCallback("onPathSuccess"); return true; } else @@ -783,7 +796,7 @@ bool AIPlayer::setPathDestination(const Point3F &pos) // Just move normally if we can't path. //setMoveDestination(pos, true); //return; - //throwCallback("onPathFailed"); + throwCallback("onPathFailed"); path->deleteObject(); return false; } @@ -871,6 +884,10 @@ DefineEngineMethod(AIPlayer, followObject, void, (SimObjectId obj, F32 radius),, "@param radius Maximum distance we let the target escape to.") { SceneObject *follow; + object->clearPath(); + object->clearCover(); + object->clearFollow(); + if(Sim::findObject(obj, follow)) object->followObject(follow, radius); } @@ -1374,6 +1391,40 @@ DefineEngineMethod( AIPlayer, clearMoveTriggers, void, ( ),, object->clearMoveTriggers(); } +F32 AIPlayer::getTargetDistance(GameBase* target, bool _checkEnabled) +{ + if (!isServerObject()) return false; + if (!target) + { + target = mAimObject.getPointer(); + if (!target) + return F32_MAX; + } + + if (_checkEnabled) + { + if (target->getTypeMask() & ShapeBaseObjectType) + { + ShapeBase *shapeBaseCheck = static_cast(target); + if (shapeBaseCheck) + if (shapeBaseCheck->getDamageState() != Enabled) return false; + } + else + return F32_MAX; + } + + return (getPosition() - target->getPosition()).len(); +} + +DefineEngineMethod(AIPlayer, getTargetDistance, bool, (ShapeBase* obj, bool checkEnabled), (NULL, false), + "@brief Check whether an object is within a specified veiw cone.\n" + "@obj Object to check. (If blank, it will check the current target).\n" + "@fov view angle in degrees.(Defaults to 45)\n" + "@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n") +{ + return object->getTargetDistance(obj, checkEnabled); +} + DefineEngineMethod( AIPlayer, setAiPose, void, ( S32 pose ),, "@brief Sets the AiPose for an AI object.\n" "@param pose StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n" diff --git a/Engine/source/T3D/aiPlayer.h b/Engine/source/T3D/aiPlayer.h index f072d2423..e4f47eb9a 100644 --- a/Engine/source/T3D/aiPlayer.h +++ b/Engine/source/T3D/aiPlayer.h @@ -49,6 +49,7 @@ private: MoveState mMoveState; F32 mMoveSpeed; F32 mMoveTolerance; // Distance from destination before we stop + F32 mAttackRadius; // Distance to trigger weaponry calcs Point3F mMoveDestination; // Destination for movement Point3F mLastLocation; // For stuck check F32 mMoveStuckTolerance; // Distance tolerance on stuck check @@ -96,8 +97,6 @@ private: /// Path we are currently following. PathData mPathData; - /// Clear out the current path. - void clearPath(); /// Get the current path we're following. NavPath *getPath() { return mPathData.path; } @@ -113,8 +112,6 @@ private: /// Current cover we're trying to get to. CoverData mCoverData; - /// Stop searching for cover. - void clearCover(); /// Information about a target we're following. struct FollowData { @@ -134,8 +131,6 @@ private: /// Current object we're following. FollowData mFollowData; - /// Stop following me! - void clearFollow(); /// NavMesh we pathfind on. SimObjectPtr mNavMesh; @@ -160,6 +155,13 @@ public: void onRemove(); virtual bool getAIMove( Move *move ); + virtual void updateMove(const Move *move); + /// Clear out the current path. + void clearPath(); + /// Stop searching for cover. + void clearCover(); + /// Stop following me! + void clearFollow(); // Targeting and aiming sets/gets void setAimObject( GameBase *targetObject ); @@ -170,6 +172,7 @@ public: void clearAim(); bool checkInLos(GameBase* target = NULL, bool _useMuzzle = false, bool _checkEnabled = false); bool checkInFoV(GameBase* target = NULL, F32 camFov = 45.0f, bool _checkEnabled = false); + F32 getTargetDistance(GameBase* target, bool _checkEnabled); // Movement sets/gets void setMoveSpeed( const F32 speed );