|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef AI_BLENDED_MOVEMENT_H
#define AI_BLENDED_MOVEMENT_H
#include "ai_basenpc.h"
#include "ai_motor.h"
#include "ai_navigator.h"
struct AI_Waypoint_t;
//-----------------------------------------------------------------------------
// CLASS: CAI_BlendedMotor
//
// Purpose: Home of fancy human animation transition code
//
//-----------------------------------------------------------------------------
class CAI_BlendedMotor : public CAI_Motor { typedef CAI_Motor BaseClass; public: CAI_BlendedMotor( CAI_BaseNPC *pOuter ) : BaseClass( pOuter ) { m_iPrimaryLayer = -1; m_nPrimarySequence = ACT_INVALID;
m_iSecondaryLayer = -1; m_nSecondarySequence = ACT_INVALID; m_flSecondaryWeight = 0.0f;
m_nSavedGoalActivity = ACT_INVALID; m_nSavedTranslatedGoalActivity = ACT_INVALID; m_nGoalSequence = ACT_INVALID;
m_nPrevMovementSequence = ACT_INVALID; m_nInteriorSequence = ACT_INVALID;
m_bDeceleratingToGoal = false;
m_flStartCycle = 0.0f;
m_flPredictiveSpeedAdjust = 1.0f; m_flReactiveSpeedAdjust = 1.0f; m_vecPrevOrigin1.Init(); m_vecPrevOrigin2.Init();
m_prevYaw = 0.0f; m_doTurn = 0.0f; m_doLeft = 0.0f; m_doRight = 0.0f; m_flNextTurnAct = 0.0f; }
void MoveClimbStart( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw ); void MoveJumpStart( const Vector &velocity );
void ResetMoveCalculations(); void MoveStart(); void ResetGoalSequence(); void MoveStop(); void MovePaused(); void MoveContinue();
float OverrideMaxYawSpeed( Activity activity ); void UpdateYaw( int speed ); void RecalculateYawSpeed();
bool IsDeceleratingToGoal() const { return m_bDeceleratingToGoal; } float GetMoveScriptTotalTime();
void MaintainTurnActivity( void ); bool AddTurnGesture( float flYD );
private: AIMotorMoveResult_t MoveGroundExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ); AIMotorMoveResult_t MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult );
// --------------------------------
void BuildMoveScript( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult );
void BuildVelocityScript( const AILocalMoveGoal_t &move ); void InsertSlowdown( float distToObstruction, float idealAccel, bool bAlwaysSlowdown );
int BuildTurnScript( int i, int j ); void BuildTurnScript( const AILocalMoveGoal_t &move ); int BuildInsertNode( int i, float flTime );
Activity GetTransitionActivity( void ); // --------------------------------
// helpers to simplify code
float GetCycle() { return GetOuter()->GetCycle(); } int AddLayeredSequence( int sequence, int iPriority ) { return GetOuter()->AddLayeredSequence( sequence, iPriority ); } void SetLayerWeight( int iLayer, float flWeight ) { GetOuter()->SetLayerWeight( iLayer, flWeight ); } void SetLayerPlaybackRate( int iLayer, float flPlaybackRate ) { GetOuter()->SetLayerPlaybackRate( iLayer, flPlaybackRate ); } void SetLayerNoRestore( int iLayer, bool bNoRestore ) { GetOuter()->SetLayerNoRestore( iLayer, bNoRestore ); } void SetLayerCycle( int iLayer, float flCycle ) { GetOuter()->SetLayerCycle( iLayer, flCycle ); } void SetLayerCycle( int iLayer, float flCycle, float flPrevCycle ) { GetOuter()->SetLayerCycle( iLayer, flCycle, flPrevCycle ); } void RemoveLayer( int iLayer, float flKillRate, float flKillDelay ) { GetOuter()->RemoveLayer( iLayer, flKillRate, flKillDelay ); }
// --------------------------------
struct AI_Movementscript_t { public: AI_Movementscript_t( ) { Init( ); };
void Init( void ) { memset( this, 0, sizeof(*this) ); };
float flTime; // time till next entry
float flElapsedTime; // time since first entry
float flDist; // distance to next entry
float flMaxVelocity;
// float flVelocity;
float flYaw; float flAngularVelocity;
bool bLooping; int nFlags;
AI_Waypoint_t *pWaypoint;
public: AI_Movementscript_t *pNext; AI_Movementscript_t *pPrev;
Vector vecLocation;
}; //---------------------------------
CUtlVector<AI_Movementscript_t> m_scriptMove; CUtlVector<AI_Movementscript_t> m_scriptTurn;
//---------------------------------
bool m_bDeceleratingToGoal;
int m_iPrimaryLayer; int m_iSecondaryLayer;
int m_nPrimarySequence; int m_nSecondarySequence; float m_flSecondaryWeight;
Activity m_nSavedGoalActivity; Activity m_nSavedTranslatedGoalActivity; int m_nGoalSequence;
int m_nPrevMovementSequence; int m_nInteriorSequence;
float m_flStartCycle;
float m_flCurrRate;
float m_flPredictiveSpeedAdjust; // predictive speed adjust from probing slope
float m_flReactiveSpeedAdjust; // reactive speed adjust when slope movement detected
Vector m_vecPrevOrigin1; Vector m_vecPrevOrigin2;
//---------------------------------
float m_flNextTurnGesture; // next time for large turn gesture
//---------------------------------
float m_prevYaw; float m_doTurn; float m_doLeft; float m_doRight; float m_flNextTurnAct; // next time for small turn gesture
float GetMoveScriptDist( float &flNewSpeed ); float GetMoveScriptYaw( void ); void SetMoveScriptAnim( float flNewSpeed );
int GetInteriorSequence( int fromSequence );
DECLARE_SIMPLE_DATADESC(); };
//-----------------------------------------------------------------------------
// CLASS: CAI_BlendingHost
//
// Purpose: Bridge to the home of fancy human animation transition code
//
//-----------------------------------------------------------------------------
template <class BASE_NPC> class CAI_BlendingHost : public BASE_NPC { DECLARE_CLASS_NOFRIEND( CAI_BlendingHost, BASE_NPC ); public: const CAI_BlendedMotor *GetBlendedMotor() const { return assert_cast<const CAI_BlendedMotor *>(this->GetMotor()); } CAI_BlendedMotor * GetBlendedMotor() { return assert_cast<CAI_BlendedMotor *>(this->GetMotor()); }
CAI_Motor *CreateMotor() { MEM_ALLOC_CREDIT(); return new CAI_BlendedMotor( this ); }
CAI_Navigator *CreateNavigator() { CAI_Navigator *pNavigator = BaseClass::CreateNavigator(); pNavigator->SetValidateActivitySpeed( false ); return pNavigator; }
float MaxYawSpeed( void ) { float override = GetBlendedMotor()->OverrideMaxYawSpeed( this->GetActivity() ); if ( override != -1 ) return override; return BaseClass::MaxYawSpeed(); }
float GetTimeToNavGoal() { float result = GetBlendedMotor()->GetMoveScriptTotalTime(); if ( result != -1 ) return result; return BaseClass::GetTimeToNavGoal(); }
};
//-------------------------------------
// to simplify basic usage:
class CAI_BlendedNPC : public CAI_BlendingHost<CAI_BaseNPC> { DECLARE_CLASS( CAI_BlendedNPC, CAI_BlendingHost<CAI_BaseNPC> ); };
//-----------------------------------------------------------------------------
#endif
|