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 else
{ {
if (getGoal()->getDist() > mControllerData->mFollowTolerance) if (getGoal()->getDist() > mControllerData->mFollowTolerance)
getNav()->repath(); {
RayInfo info;
if (getGoal()->getDist() < mControllerData->mFollowTolerance) 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(); getNav()->clearPath();
mMovement.mMoveState = ModeStop; mMovement.mMoveState = ModeStop;
getGoal()->mInRange = true;
throwCallback("onTargetInRange"); 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 else
mMovement.mAimLocation = getNav()->mMoveDestination; mMovement.mAimLocation = getNav()->mMoveDestination;
mControllerData->resolveYaw(this, location, movePtr); mControllerData->resolveYawPtr(this, location, movePtr);
mControllerData->resolvePitch(this, location, movePtr); mControllerData->resolvePitchPtr(this, location, movePtr);
mControllerData->resolveRoll(this, location, movePtr); mControllerData->resolveRollPtr(this, location, movePtr);
if (mMovement.mMoveState != AIController::ModeStop) if (mMovement.mMoveState != AIController::ModeStop)
{ {
@ -179,12 +195,14 @@ bool AIController::getAIMove(Move* movePtr)
} }
else else
{ {
mControllerData->resolveSpeed(this, location, movePtr); mControllerData->resolveSpeedPtr(this, location, movePtr);
mControllerData->resolveStuck(this); mControllerData->resolveStuckPtr(this);
} }
} }
} }
mControllerData->resolveTriggerStatePtr(this, movePtr);
// Test for target location in sight if it's an object. The LOS is // 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, // run from the eye position to the center of the object's bounding,
// which is not very accurate. // 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; 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) void AIControllerData::resolveStuck(AIController* obj)
{ {
if (obj->mMovement.mMoveState == AIController::ModeStop) return; 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()); Player* po = dynamic_cast<Player*>(obj->getAIInfo()->mObj.getPointer());
if (!po) return;//not a player 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. // Next do pitch.
if (!obj->getAim()->mObj && !obj->getAim()->mPosSet) if (!obj->getAim())
{ {
// Level out if were just looking at our next way point. // Level out if were just looking at our next way point.
Point3F headRotation = po->getHeadRotation(); Point3F headRotation = po->getHeadRotation();
@ -572,4 +574,26 @@ void AIPlayerControllerData::resolvePitch(AIController* obj, Point3F location, M
movePtr->pitch = -headRotation.x; 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_ #endif //_AICONTROLLER_H_

View file

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

View file

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