From f3ef698e890b41a3f7a7fe22c63b8d893b715961 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Wed, 16 Apr 2025 17:27:26 -0500 Subject: [PATCH] getmovedestination, set/get speed, targetting script commands todo: need to see why getAIController().setAimLocation("10 10 0"); seems to get into an onreachdestination+stuck callback loop --- Engine/source/T3D/AI/AIAimTarget.cpp | 146 +++++++++++++++++++++++++- Engine/source/T3D/AI/AIAimTarget.h | 5 +- Engine/source/T3D/AI/AIController.cpp | 22 ++++ Engine/source/T3D/AI/AIController.h | 2 + Engine/source/T3D/AI/AINavigation.cpp | 14 +++ Engine/source/T3D/AI/AINavigation.h | 1 + 6 files changed, 187 insertions(+), 3 deletions(-) diff --git a/Engine/source/T3D/AI/AIAimTarget.cpp b/Engine/source/T3D/AI/AIAimTarget.cpp index 907b2da3d..6e4b3d299 100644 --- a/Engine/source/T3D/AI/AIAimTarget.cpp +++ b/Engine/source/T3D/AI/AIAimTarget.cpp @@ -25,7 +25,31 @@ static U32 sAILoSMask = TerrainObjectType | StaticShapeObjectType | StaticObjectType; -bool AIAimTarget::checkInLos(GameBase* target, bool _useMuzzle, bool _checkEnabled) +F32 AIAimTarget::getTargetDistance(SceneObject* target, bool _checkEnabled) +{ + if (!target) + { + target = mObj.getPointer(); + if (!target) + return F32_MAX; + } + + if (_checkEnabled) + { + if (target->getTypeMask() & ShapeBaseObjectType) + { + ShapeBase* shapeBaseCheck = static_cast(target); + if (shapeBaseCheck) + if (shapeBaseCheck->getDamageState() != ShapeBase::Enabled) return false; + } + else + return F32_MAX; + } + + return (getPosition() - target->getPosition()).len(); +} + +bool AIAimTarget::checkInLos(SceneObject* target, bool _useMuzzle, bool _checkEnabled) { ShapeBase* sbo = dynamic_cast(getCtrl()->getAIInfo()->mObj.getPointer()); if (!target) @@ -75,3 +99,123 @@ bool AIAimTarget::checkInLos(GameBase* target, bool _useMuzzle, bool _checkEnabl } return hit; } + +bool AIAimTarget::checkInFoV(SceneObject* target, F32 camFov, bool _checkEnabled) +{ + ShapeBase* sbo = dynamic_cast(getCtrl()->getAIInfo()->mObj.getPointer()); + if (!target) + { + target = dynamic_cast(mObj.getPointer()); + if (!target) + return false; + } + if (_checkEnabled) + { + if (target->getTypeMask() & ShapeBaseObjectType) + { + ShapeBase* shapeBaseCheck = static_cast(target); + if (shapeBaseCheck) + if (shapeBaseCheck->getDamageState() != ShapeBase::Enabled) return false; + } + else + return false; + } + + MatrixF cam = sbo->getTransform(); + Point3F camPos; + VectorF camDir; + + cam.getColumn(3, &camPos); + cam.getColumn(1, &camDir); + + camFov = mDegToRad(camFov) / 2; + + Point3F shapePos = target->getBoxCenter(); + VectorF shapeDir = shapePos - camPos; + // Test to see if it's within our viewcone, this test doesn't + // actually match the viewport very well, should consider + // projection and box test. + shapeDir.normalize(); + F32 dot = mDot(shapeDir, camDir); + return (dot > mCos(camFov)); +} + +DefineEngineMethod(AIController, setAimLocation, void, (Point3F target), , + "@brief Tells the AIPlayer to aim at the location provided.\n\n" + + "@param target An \"x y z\" position in the game world to target.\n\n" + + "@see getAimLocation()\n") +{ + object->setAim(target); +} + +DefineEngineMethod(AIController, getAimLocation, Point3F, (), , + "@brief Returns the point the AIPlayer is aiming at.\n\n" + + "This will reflect the position set by setAimLocation(), " + "or the position of the object that the bot is now aiming at. " + "If the bot is not aiming at anything, this value will " + "change to whatever point the bot's current line-of-sight intercepts." + + "@return World space coordinates of the object AI is aiming at. Formatted as \"X Y Z\".\n\n" + + "@see setAimLocation()\n" + "@see setAimObject()\n") +{ + return object->getAim()->getPosition(); +} + +DefineEngineMethod(AIController, setAimObject, void, (const char* objName, Point3F offset), (Point3F::Zero), "( GameBase obj, [Point3F offset] )" + "Sets the bot's target object. Optionally set an offset from target location." + "@hide") +{ + // Find the target + SceneObject* targetObject; + if (Sim::findObject(objName, targetObject)) + { + + object->setAim(targetObject, 0.0f, offset); + } + else + object->setAim(0, 0.0f, offset); +} + +DefineEngineMethod(AIController, getAimObject, S32, (), , + "@brief Gets the object the AIPlayer is targeting.\n\n" + + "@return Returns -1 if no object is being aimed at, " + "or the SimObjectID of the object the AIPlayer is aiming at.\n\n" + + "@see setAimObject()\n") +{ + SceneObject* obj = dynamic_cast(object->getAim()->mObj.getPointer()); + return obj ? obj->getId() : -1; +} + + +DefineEngineMethod(AIController, getTargetDistance, F32, (SceneObject* obj, bool checkEnabled), (nullAsType(), false), + "@brief The distance to a given target.\n" + "@obj Object to check. (If blank, it will check the current target).\n" + "@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n") +{ + return object->getAim()->getTargetDistance(obj, checkEnabled); +} + +DefineEngineMethod(AIController, checkInLos, bool, (SceneObject* obj, bool useMuzzle, bool checkEnabled), (nullAsType(), false, false), + "@brief Check whether an object is in line of sight.\n" + "@obj Object to check. (If blank, it will check the current target).\n" + "@useMuzzle Use muzzle position. Otherwise use eye position. (defaults to false).\n" + "@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n") +{ + return object->getAim()->checkInLos(obj, useMuzzle, checkEnabled); +} + +DefineEngineMethod(AIController, checkInFoV, bool, (SceneObject* obj, F32 fov, bool checkEnabled), (nullAsType(), 45.0f, 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->getAim()->checkInFoV(obj, fov, checkEnabled); +} diff --git a/Engine/source/T3D/AI/AIAimTarget.h b/Engine/source/T3D/AI/AIAimTarget.h index 650a4f9b8..f9b66a217 100644 --- a/Engine/source/T3D/AI/AIAimTarget.h +++ b/Engine/source/T3D/AI/AIAimTarget.h @@ -29,8 +29,9 @@ struct AIAimTarget : AIInfo Point3F mAimOffset; bool mTargetInLOS; // Is target object visible? Point3F getPosition() { return ((mObj) ? mObj->getPosition() : mPosition) + mAimOffset; } - bool checkInLos(GameBase* target = NULL, bool _useMuzzle = false, bool _checkEnabled = false); - bool checkInFoV(GameBase* target = NULL, F32 camFov = 45.0f, bool _checkEnabled = false); + bool checkInLos(SceneObject* target = NULL, bool _useMuzzle = false, bool _checkEnabled = false); + bool checkInFoV(SceneObject* target = NULL, F32 camFov = 45.0f, bool _checkEnabled = false); + F32 getTargetDistance(SceneObject* target, bool _checkEnabled); AIAimTarget(AIController* controller) : Parent(controller) {}; AIAimTarget(AIController* controller, SimObjectPtr objIn, F32 radIn) : Parent(controller, objIn, radIn) {}; AIAimTarget(AIController* controller, Point3F pointIn, F32 radIn) : Parent(controller, pointIn, radIn) {}; diff --git a/Engine/source/T3D/AI/AIController.cpp b/Engine/source/T3D/AI/AIController.cpp index 49d3e2a76..c51518a53 100644 --- a/Engine/source/T3D/AI/AIController.cpp +++ b/Engine/source/T3D/AI/AIController.cpp @@ -183,6 +183,28 @@ void AIController::clearCover() SAFE_DELETE(mCover); } +DefineEngineMethod(AIController, setMoveSpeed, void, (F32 speed), , + "@brief Sets the move speed for an AI object.\n\n" + + "@param speed A speed multiplier between 0.0 and 1.0. " + "This is multiplied by the AIPlayer's base movement rates (as defined in " + "its PlayerData datablock)\n\n" + + "@see getMoveDestination()\n") +{ + object->mMovement.setMoveSpeed(speed); +} + +DefineEngineMethod(AIController, getMoveSpeed, F32, (), , + "@brief Gets the move speed of an AI object.\n\n" + + "@return A speed multiplier between 0.0 and 1.0.\n\n" + + "@see setMoveSpeed()\n") +{ + return object->mMovement.getMoveSpeed(); +} + //----------------------------------------------------------------------------- IMPLEMENT_CO_DATABLOCK_V1(AIControllerData); diff --git a/Engine/source/T3D/AI/AIController.h b/Engine/source/T3D/AI/AIController.h index bc5ad3a33..2f0839498 100644 --- a/Engine/source/T3D/AI/AIController.h +++ b/Engine/source/T3D/AI/AIController.h @@ -85,6 +85,8 @@ public: { MoveState mMoveState; F32 mMoveSpeed = 1.0; + void setMoveSpeed(F32 speed) { mMoveSpeed = speed; }; + F32 getMoveSpeed() { return mMoveSpeed; }; bool mMoveSlowdown; // Slowdown as we near the destination Point3F mLastLocation; // For stuck check S32 mMoveStuckTestCountdown; // The current countdown until at AI starts to check if it is stuck diff --git a/Engine/source/T3D/AI/AINavigation.cpp b/Engine/source/T3D/AI/AINavigation.cpp index d9f4bb3ea..63491b459 100644 --- a/Engine/source/T3D/AI/AINavigation.cpp +++ b/Engine/source/T3D/AI/AINavigation.cpp @@ -274,3 +274,17 @@ DefineEngineMethod(AIController, setMoveDestination, void, (Point3F goal, bool s { 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(); +} + diff --git a/Engine/source/T3D/AI/AINavigation.h b/Engine/source/T3D/AI/AINavigation.h index 130305eea..2d6ce1ac3 100644 --- a/Engine/source/T3D/AI/AINavigation.h +++ b/Engine/source/T3D/AI/AINavigation.h @@ -61,6 +61,7 @@ struct AINavigation Point3F mMoveDestination; void setMoveDestination(const Point3F& location, bool slowdown); + Point3F getMoveDestination() { return mMoveDestination; }; void onReachDestination(); /// NavMesh we pathfind on.