You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
12 KiB
383 lines
12 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef AI_MOVETYPES_H |
|
#define AI_MOVETYPES_H |
|
|
|
#if defined( _WIN32 ) |
|
#pragma once |
|
#endif |
|
|
|
#include "ai_navtype.h" |
|
|
|
class CAI_Path; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Debugging code |
|
// |
|
// Use this function to set breakpoints to find out where movement is failing |
|
// |
|
#ifdef DEBUG |
|
extern void DebugNoteMovementFailure(); |
|
#define DebugNoteMovementFailureIfBlocked( moveResult ) if ( !IsMoveBlocked( moveResult ) ) ((void)0); else DebugNoteMovementFailure() |
|
#else |
|
#define DebugNoteMovementFailure() ((void)0) |
|
#define DebugNoteMovementFailureIfBlocked( moveResult ) ((void)0) |
|
#endif |
|
|
|
enum AIMoveResult_t |
|
{ |
|
AIMR_BLOCKED_ENTITY = -1, // Move was blocked by an entity |
|
AIMR_BLOCKED_WORLD = -2, // Move was blocked by the world |
|
AIMR_BLOCKED_NPC = -3, // Move was blocked by an NPC |
|
AIMR_ILLEGAL = -4, // Move is illegal for some reason |
|
|
|
AIMR_OK = 0, |
|
|
|
AIMR_CHANGE_TYPE, // Locomotion method has changed |
|
}; |
|
|
|
|
|
#ifdef DEBUG |
|
extern AIMoveResult_t DbgResult( AIMoveResult_t result ); |
|
#else |
|
inline AIMoveResult_t DbgResult( AIMoveResult_t result ) { return result; } // inline not macro for compiler typing |
|
#endif |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Movement related constants and base types |
|
//----------------------------------------------------------------------------- |
|
#ifdef PHYSICS_NPC_SHADOW_DISCREPENCY |
|
const float AI_EPS_CASTS = 0.3; // The amount physics and hull cast can disagree |
|
#endif |
|
|
|
|
|
inline bool IsMoveBlocked( AIMoveResult_t moveResult ) |
|
{ |
|
return (moveResult < AIMR_OK ); |
|
} |
|
|
|
//------------------------------------- |
|
|
|
enum StepGroundTest_t |
|
{ |
|
STEP_DONT_CHECK_GROUND = 0, |
|
STEP_ON_VALID_GROUND, |
|
STEP_ON_INVALID_GROUND, |
|
}; |
|
|
|
|
|
//------------------------------------- |
|
|
|
struct AIMoveTrace_t |
|
{ |
|
AIMoveTrace_t() |
|
{ |
|
memset( this, 0, sizeof(*this) ); |
|
} |
|
|
|
AIMoveResult_t fStatus; // See AIMoveResult_t |
|
Vector vEndPosition; // The last point that could be moved to |
|
Vector vHitNormal; // The normal of a hit, if any. vec3_origin if none. Can be none even if "hit" |
|
CBaseEntity* pObstruction; // The obstruction I bumped into (if any) |
|
float flTotalDist; |
|
float flDistObstructed; // FIXME: This is a strange number. In the case |
|
// of calling MoveLimit with navtype NAV_GROUND, |
|
// it represents a 2D distance to the obstruction. |
|
// In the case of other navtypes, it represents a |
|
// 3D distance to the obstruction |
|
Vector vJumpVelocity; // FIXME: Remove this; it's bogus |
|
// It's only returned by JumpMoveLimit |
|
// which seems to be a bogus concept to begin with |
|
float flStepUpDistance; |
|
}; |
|
|
|
inline bool IsMoveBlocked( const AIMoveTrace_t &moveTrace ) |
|
{ |
|
return (moveTrace.fStatus < AIMR_OK ); |
|
} |
|
|
|
|
|
// Categorizes the blocker and sets the appropriate bits |
|
AIMoveResult_t AIComputeBlockerMoveResult( CBaseEntity *pBlocker ); |
|
|
|
|
|
//------------------------------------- |
|
// Purpose: Specifies an immediate, localized, straight line movement goal |
|
//------------------------------------- |
|
|
|
enum AILocalMoveGoalFlags_t |
|
{ |
|
AILMG_NONE, |
|
AILMG_TARGET_IS_GOAL = 0x01, |
|
AILMG_CONSUME_INTERVAL = 0x02, |
|
AILMG_TARGET_IS_TRANSITION = 0x04, |
|
AILMG_NO_STEER = 0x08, |
|
AILMG_NO_AVOIDANCE_PATHS = 0x10, |
|
}; |
|
|
|
struct AILocalMoveGoal_t |
|
{ |
|
AILocalMoveGoal_t() |
|
{ |
|
memset( this, 0, sizeof(*this) ); |
|
} |
|
|
|
// Object of the goal |
|
Vector target; |
|
|
|
// The actual move. Note these need not always agree with "target" |
|
Vector dir; |
|
Vector facing; |
|
float speed; |
|
|
|
// The distance maximum distance intended to travel in path length |
|
float maxDist; |
|
|
|
// The distance expected to move this think |
|
float curExpectedDist; |
|
|
|
Navigation_t navType; |
|
CBaseEntity * pMoveTarget; |
|
|
|
unsigned flags; |
|
|
|
// The path from which this goal was derived |
|
CAI_Path * pPath; |
|
|
|
// The result if a forward probing trace has been done |
|
bool bHasTraced; |
|
AIMoveTrace_t directTrace; |
|
AIMoveTrace_t thinkTrace; |
|
|
|
#ifdef DEBUG |
|
int solveCookie; |
|
#endif |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
enum AIMotorMoveResult_t |
|
{ |
|
AIM_FAILED, |
|
AIM_SUCCESS, |
|
|
|
// Partial successes |
|
AIM_PARTIAL_HIT_NPC, |
|
AIM_PARTIAL_HIT_WORLD, |
|
AIM_PARTIAL_HIT_TARGET, |
|
|
|
AIM_NUM_RESULTS |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: The set of callbacks used by lower-level movement classes to |
|
// notify and receive guidance from higher level-classes |
|
//----------------------------------------------------------------------------- |
|
|
|
abstract_class IAI_MovementSink |
|
{ |
|
public: |
|
//--------------------------------- |
|
// |
|
// Queries |
|
// |
|
virtual float CalcYawSpeed( void ) = 0; |
|
|
|
//--------------------------------- |
|
// |
|
// Local navigation notifications, each allows services provider to overridde default result |
|
// |
|
virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ) = 0; |
|
|
|
virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ) = 0; |
|
|
|
virtual bool OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ) = 0; |
|
|
|
virtual bool OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ) = 0; |
|
|
|
virtual bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ) = 0; |
|
|
|
|
|
virtual bool OnMoveBlocked( AIMoveResult_t *pResult ) = 0; |
|
|
|
//--------------------------------- |
|
// |
|
// Motor notifications, each allows services provider to overridde default result |
|
// |
|
virtual bool OnMoveStalled( const AILocalMoveGoal_t &move ) = 0; |
|
virtual bool OnMoveExecuteFailed( const AILocalMoveGoal_t &move, |
|
const AIMoveTrace_t &trace, |
|
AIMotorMoveResult_t fMotorResult, |
|
AIMoveResult_t *pResult ) = 0; |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Default implementations of IAI_MovementSink |
|
//----------------------------------------------------------------------------- |
|
|
|
class CAI_DefMovementSink : public IAI_MovementSink |
|
{ |
|
public: |
|
//--------------------------------- |
|
// |
|
// Queries |
|
// |
|
virtual float CalcYawSpeed( void ) { return -1.0; } |
|
|
|
|
|
//--------------------------------- |
|
// |
|
// Local navigation notifications, each allows services provider to overridde default result |
|
// |
|
virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } |
|
virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } |
|
virtual bool OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } |
|
virtual bool OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } |
|
virtual bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } |
|
virtual bool OnMoveBlocked( AIMoveResult_t *pResult ) { return false; } |
|
|
|
//--------------------------------- |
|
// |
|
// Motor notifications, each allows services provider to overridde default result |
|
// |
|
virtual bool OnMoveStalled( const AILocalMoveGoal_t &move ) { return false; } |
|
virtual bool OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ) { return false; } |
|
|
|
}; |
|
|
|
//------------------------------------- |
|
|
|
class CAI_ProxyMovementSink : public CAI_DefMovementSink |
|
{ |
|
public: |
|
CAI_ProxyMovementSink() |
|
: m_pProxied( NULL ) |
|
{ |
|
} |
|
|
|
//--------------------------------- |
|
|
|
void Init( IAI_MovementSink *pMovementServices ) { m_pProxied = pMovementServices; } |
|
|
|
//--------------------------------- |
|
// |
|
// Queries |
|
// |
|
virtual float CalcYawSpeed( void ); |
|
|
|
//--------------------------------- |
|
// |
|
// Local navigation notifications, each allows services provider to overridde default result |
|
// |
|
virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ); |
|
|
|
virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ); |
|
virtual bool OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ); |
|
virtual bool OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ); |
|
virtual bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, |
|
float distClear, |
|
AIMoveResult_t *pResult ); |
|
virtual bool OnMoveBlocked( AIMoveResult_t *pResult ); |
|
|
|
//--------------------------------- |
|
// |
|
// Motor notifications, each allows services provider to overridde default result |
|
// |
|
virtual bool OnMoveStalled( const AILocalMoveGoal_t &move ); |
|
virtual bool OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ); |
|
|
|
IAI_MovementSink *m_pProxied; |
|
}; |
|
|
|
// ---------------------------------------------------------------------------- |
|
|
|
inline float CAI_ProxyMovementSink::CalcYawSpeed( void ) |
|
{ |
|
float result; |
|
if ( m_pProxied && ( result = m_pProxied->CalcYawSpeed() ) != -1.0 ) |
|
return result; |
|
return CAI_DefMovementSink::CalcYawSpeed(); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnCalcBaseMove( pMoveGoal, distClear, pResult ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnCalcBaseMove( pMoveGoal, distClear, pResult ); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnObstructionPreSteer( pMoveGoal, distClear, pResult ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnObstructionPreSteer( pMoveGoal, distClear, pResult ); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnFailedSteer( pMoveGoal, distClear, pResult ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnFailedSteer( pMoveGoal, distClear, pResult ); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnFailedLocalNavigation( pMoveGoal, distClear, pResult ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnFailedLocalNavigation( pMoveGoal, distClear, pResult ); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnInsufficientStopDist( pMoveGoal, distClear, pResult ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnInsufficientStopDist( pMoveGoal, distClear, pResult ); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnMoveStalled( const AILocalMoveGoal_t &move ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnMoveStalled( move ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnMoveStalled( move ); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnMoveExecuteFailed( move, trace, fMotorResult, pResult ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnMoveExecuteFailed( move, trace, fMotorResult, pResult ); |
|
} |
|
|
|
inline bool CAI_ProxyMovementSink::OnMoveBlocked( AIMoveResult_t *pResult ) |
|
{ |
|
if ( m_pProxied && m_pProxied->OnMoveBlocked( pResult ) ) |
|
return true; |
|
return CAI_DefMovementSink::OnMoveBlocked( pResult ); |
|
} |
|
|
|
//============================================================================= |
|
|
|
#endif // AI_MOVETYPES_H
|
|
|