//========= 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 m_scriptMove; CUtlVector 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 CAI_BlendingHost : public BASE_NPC { DECLARE_CLASS_NOFRIEND(CAI_BlendingHost, BASE_NPC); public: const CAI_BlendedMotor *GetBlendedMotor() const { return assert_cast(this->GetMotor()); } CAI_BlendedMotor *GetBlendedMotor() { return assert_cast(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 { DECLARE_CLASS(CAI_BlendedNPC, CAI_BlendingHost); }; //----------------------------------------------------------------------------- #endif