aicontroller:

in order to call derivatives of AIControllerData datablocks *without* requiring an accompanying AIController subclass as well, leverage the fastdelegate system for our resolver callbacks
additionally, don't try and repath in mid air
aigoal: initialize inange/infirinrange to false. use those to filter callbacks
This commit is contained in:
AzaezelX 2025-04-17 17:55:38 -05:00
parent f84bf058c9
commit 32f9917ed2
3 changed files with 91 additions and 41 deletions

View file

@ -138,17 +138,33 @@ bool AIController::getAIMove(Move* movePtr)
else
{
if (getGoal()->getDist() > mControllerData->mFollowTolerance)
getNav()->repath();
if (getGoal()->getDist() < mControllerData->mFollowTolerance)
{
RayInfo info;
if (getAIInfo()->mObj->getContainer()->castRay(getAIInfo()->getPosition(), getAIInfo()->getPosition() - Point3F(0, 0, 0.001f), StaticShapeObjectType, &info))
{
getNav()->repath();
}
getGoal()->mInRange = false;
}
if (getGoal()->getDist() < mControllerData->mFollowTolerance && !getGoal()->mInRange)
{
getNav()->clearPath();
mMovement.mMoveState = ModeStop;
getGoal()->mInRange = true;
throwCallback("onTargetInRange");
}
else if (getGoal()->getDist() < mControllerData->mAttackRadius)
else
{
throwCallback("onTargetInFiringRange");
if (getGoal()->getDist() < mControllerData->mAttackRadius )
{
if (!getGoal()->mInFiringRange)
{
getGoal()->mInFiringRange = true;
throwCallback("onTargetInFiringRange");
}
}
else
getGoal()->mInFiringRange = false;
}
}
}
@ -164,9 +180,9 @@ bool AIController::getAIMove(Move* movePtr)
else
mMovement.mAimLocation = getNav()->mMoveDestination;
mControllerData->resolveYaw(this, location, movePtr);
mControllerData->resolvePitch(this, location, movePtr);
mControllerData->resolveRoll(this, location, movePtr);
mControllerData->resolveYawPtr(this, location, movePtr);
mControllerData->resolvePitchPtr(this, location, movePtr);
mControllerData->resolveRollPtr(this, location, movePtr);
if (mMovement.mMoveState != AIController::ModeStop)
{
@ -179,12 +195,14 @@ bool AIController::getAIMove(Move* movePtr)
}
else
{
mControllerData->resolveSpeed(this, location, movePtr);
mControllerData->resolveStuck(this);
mControllerData->resolveSpeedPtr(this, location, movePtr);
mControllerData->resolveStuckPtr(this);
}
}
}
mControllerData->resolveTriggerStatePtr(this, 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.
@ -206,31 +224,6 @@ bool AIController::getAIMove(Move* movePtr)
}
}
/*
// Replicate the trigger state into the move so that
// triggers can be controlled from scripts.
for (U32 i = 0; i < MaxTriggerKeys; i++)
movePtr->trigger[i] = getImageTriggerState(i);
*/
#ifdef TORQUE_NAVIGATION_ENABLED
if (getNav()->mJump == AINavigation::Now)
{
movePtr->trigger[2] = true;
getNav()->mJump = AINavigation::None;
}
else if (getNav()->mJump == AINavigation::Ledge)
{
// If we're not touching the ground, jump!
RayInfo info;
if (!getAIInfo()->mObj->getContainer()->castRay(getAIInfo()->getPosition(), getAIInfo()->getPosition() - Point3F(0, 0, 0.4f), StaticShapeObjectType, &info))
{
movePtr->trigger[2] = true;
getNav()->mJump = AINavigation::None;
}
}
#endif // TORQUE_NAVIGATION_ENABLED
return true;
}
@ -438,6 +431,15 @@ void AIControllerData::resolveSpeed(AIController* obj, Point3F location, Move* m
}
}
void AIControllerData::resolveTriggerState(AIController* obj, Move* movePtr)
{
//check for scripted overides
for (U32 slot = 0; slot < MaxTriggerKeys; slot++)
{
movePtr->trigger[slot] = obj->mTriggerState.mMoveTriggers[slot];
}
}
void AIControllerData::resolveStuck(AIController* obj)
{
if (obj->mMovement.mMoveState == AIController::ModeStop) return;
@ -539,10 +541,10 @@ void AIPlayerControllerData::resolvePitch(AIController* obj, Point3F location, M
Player* po = dynamic_cast<Player*>(obj->getAIInfo()->mObj.getPointer());
if (!po) return;//not a player
if (obj->getAim()->mObj || obj->getAim()->mPosSet || obj->mMovement.mMoveState != AIController::ModeStop)
if (obj->getAim() || obj->mMovement.mMoveState != AIController::ModeStop)
{
// Next do pitch.
if (!obj->getAim()->mObj && !obj->getAim()->mPosSet)
if (!obj->getAim())
{
// Level out if were just looking at our next way point.
Point3F headRotation = po->getHeadRotation();
@ -572,4 +574,26 @@ void AIPlayerControllerData::resolvePitch(AIController* obj, Point3F location, M
movePtr->pitch = -headRotation.x;
}
}
void AIPlayerControllerData::resolveTriggerState(AIController* obj, Move* movePtr)
{
Parent::resolveTriggerState(obj, movePtr);
#ifdef TORQUE_NAVIGATION_ENABLED
if (obj->getNav()->mJump == AINavigation::Now)
{
movePtr->trigger[2] = true;
obj->getNav()->mJump = AINavigation::None;
}
else if (obj->getNav()->mJump == AINavigation::Ledge)
{
// If we're not touching the ground, jump!
RayInfo info;
if (!obj->getAIInfo()->mObj->getContainer()->castRay(obj->getAIInfo()->getPosition(), obj->getAIInfo()->getPosition() - Point3F(0, 0, 0.4f), StaticShapeObjectType, &info))
{
movePtr->trigger[2] = true;
obj->getNav()->mJump = AINavigation::None;
}
}
#endif // TORQUE_NAVIGATION_ENABLED
}
#endif //_AICONTROLLER_H_

View file

@ -124,7 +124,7 @@ public:
mCover = NULL;
mMovement.mMoveState = ModeStop;
};
DECLARE_CONOBJECT(AIController);
};
@ -144,6 +144,13 @@ public:
mMoveStuckTestDelay = 30;
mLinkTypes = LinkData(AllFlags);
mNavSize = AINavigation::Regular;
resolveYawPtr.bind(this, &AIControllerData::resolveYaw);
resolvePitchPtr.bind(this, &AIControllerData::resolvePitch);
resolveRollPtr.bind(this, &AIControllerData::resolveRoll);
resolveSpeedPtr.bind(this, &AIControllerData::resolveSpeed);
resolveTriggerStatePtr.bind(this, &AIControllerData::resolveTriggerState);
resolveStuckPtr.bind(this, &AIControllerData::resolveStuck);
};
~AIControllerData() {};
@ -158,10 +165,22 @@ public:
/// Types of link we can use.
LinkData mLinkTypes;
AINavigation::NavSize mNavSize;
Delegate<void(AIController* obj, Point3F location, Move* movePtr)> resolveYawPtr;
void resolveYaw(AIController* obj, Point3F location, Move* movePtr);
Delegate<void(AIController* obj, Point3F location, Move* movePtr)> resolvePitchPtr;
void resolvePitch(AIController* obj, Point3F location, Move* movePtr) {};
Delegate<void(AIController* obj, Point3F location, Move* movePtr)> resolveRollPtr;
void resolveRoll(AIController* obj, Point3F location, Move* movePtr);
Delegate<void(AIController* obj, Point3F location, Move* movePtr)> resolveSpeedPtr;
void resolveSpeed(AIController* obj, Point3F location, Move* movePtr);
Delegate<void(AIController* obj, Move* movePtr)> resolveTriggerStatePtr;
void resolveTriggerState(AIController* obj, Move* movePtr);
Delegate<void(AIController* obj)> resolveStuckPtr;
void resolveStuck(AIController* obj);
};
@ -170,7 +189,13 @@ class AIPlayerControllerData : public AIControllerData
typedef AIControllerData Parent;
public:
AIPlayerControllerData()
{
resolvePitchPtr.bind(this, &AIPlayerControllerData::resolvePitch);
resolveTriggerStatePtr.bind(this, &AIPlayerControllerData::resolveTriggerState);
}
void resolvePitch(AIController* obj, Point3F location, Move* movePtr);
void resolveTriggerState(AIController* obj, Move* movePtr);
DECLARE_CONOBJECT(AIPlayerControllerData);
};
#endif // TORQUE_NAVIGATION_ENABLED

View file

@ -27,9 +27,10 @@
struct AIGoal : public AIInfo
{
typedef AIInfo Parent;
bool mInRange, mInFiringRange;
AIGoal() = delete;
AIGoal(AIController* controller): Parent(controller) {};
AIGoal(AIController* controller, SimObjectPtr<SceneObject> objIn, F32 radIn) : Parent(controller, objIn, radIn) {};
AIGoal(AIController* controller, Point3F pointIn, F32 radIn) : Parent(controller, pointIn, radIn) {};
AIGoal(AIController* controller) : Parent(controller) { mInRange = mInFiringRange = false; };
AIGoal(AIController* controller, SimObjectPtr<SceneObject> objIn, F32 radIn) : Parent(controller, objIn, radIn) { mInRange = mInFiringRange = false; };
AIGoal(AIController* controller, Point3F pointIn, F32 radIn) : Parent(controller, pointIn, radIn) { mInRange = mInFiringRange = false; };
};
#endif