aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/ai_behavior.h
diff options
context:
space:
mode:
Diffstat (limited to 'mp/src/game/server/ai_behavior.h')
-rw-r--r--mp/src/game/server/ai_behavior.h3946
1 files changed, 1973 insertions, 1973 deletions
diff --git a/mp/src/game/server/ai_behavior.h b/mp/src/game/server/ai_behavior.h
index 87383683..f88a0c45 100644
--- a/mp/src/game/server/ai_behavior.h
+++ b/mp/src/game/server/ai_behavior.h
@@ -1,1973 +1,1973 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef AI_BEHAVIOR_H
-#define AI_BEHAVIOR_H
-
-#include "ai_component.h"
-#include "ai_basenpc.h"
-#include "ai_default.h"
-#include "AI_Criteria.h"
-#include "networkvar.h"
-
-#ifdef DEBUG
-#pragma warning(push)
-#include <typeinfo>
-#pragma warning(pop)
-#pragma warning(disable:4290)
-#endif
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-//-----------------------------------------------------------------------------
-// CAI_Behavior...
-//
-// Purpose: The core component that defines a behavior in an NPC by selecting
-// schedules and running tasks
-//
-// Intended to be used as an organizational tool as well as a way
-// for various NPCs to share behaviors without sharing an inheritance
-// relationship, and without cramming those behaviors into the base
-// NPC class.
-//-----------------------------------------------------------------------------
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Base class defines interface to behaviors and provides bridging
-// methods
-//-----------------------------------------------------------------------------
-
-class IBehaviorBackBridge;
-
-//-------------------------------------
-
-abstract_class CAI_BehaviorBase : public CAI_Component
-{
- DECLARE_CLASS( CAI_BehaviorBase, CAI_Component )
-public:
- CAI_BehaviorBase(CAI_BaseNPC *pOuter = NULL)
- : CAI_Component(pOuter),
- m_pBackBridge(NULL)
- {
- }
-
- virtual const char *GetName() = 0;
-
- virtual bool KeyValue( const char *szKeyName, const char *szValue )
- {
- return false;
- }
-
- bool IsRunning() { Assert( GetOuter() ); return ( GetOuter()->GetRunningBehavior() == this ); }
- virtual bool CanSelectSchedule() { return true; }
- virtual void BeginScheduleSelection() {}
- virtual void EndScheduleSelection() {}
-
- void SetBackBridge( IBehaviorBackBridge *pBackBridge )
- {
- Assert( m_pBackBridge == NULL || pBackBridge == NULL );
- m_pBackBridge = pBackBridge;
- }
-
- void BridgePrecache() { Precache(); }
- void BridgeSpawn() { Spawn(); }
- void BridgeUpdateOnRemove() { UpdateOnRemove(); }
- void BridgeEvent_Killed( const CTakeDamageInfo &info ) { Event_Killed( info ); }
- void BridgeCleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) { CleanupOnDeath( pCulprit, bFireDeathOutput ); }
-
- void BridgeOnChangeHintGroup( string_t oldGroup, string_t newGroup ) { OnChangeHintGroup( oldGroup, newGroup ); }
-
- void BridgeGatherConditions() { GatherConditions(); }
- void BridgePrescheduleThink() { PrescheduleThink(); }
- void BridgeOnScheduleChange() { OnScheduleChange(); }
- void BridgeOnStartSchedule( int scheduleType );
-
- int BridgeSelectSchedule();
- bool BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult );
- bool BridgeStartTask( const Task_t *pTask );
- bool BridgeRunTask( const Task_t *pTask);
- bool BridgeAimGun( void );
- int BridgeTranslateSchedule( int scheduleType );
- bool BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult );
- bool BridgeTaskName(int taskID, const char **);
- Activity BridgeNPC_TranslateActivity( Activity activity );
- void BridgeBuildScheduleTestBits() { BuildScheduleTestBits(); }
- bool BridgeIsCurTaskContinuousMove( bool *pResult );
- void BridgeOnMovementFailed() { OnMovementFailed(); }
- void BridgeOnMovementComplete() { OnMovementComplete(); }
- float BridgeGetDefaultNavGoalTolerance();
- bool BridgeFValidateHintType( CAI_Hint *pHint, bool *pResult );
- bool BridgeIsValidEnemy( CBaseEntity *pEnemy );
- CBaseEntity *BridgeBestEnemy();
- bool BridgeIsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
- bool BridgeIsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
- float BridgeGetMaxTacticalLateralMovement( void );
- bool BridgeShouldIgnoreSound( CSound *pSound );
- void BridgeOnSeeEntity( CBaseEntity *pEntity );
- void BridgeOnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
- bool BridgeIsInterruptable( void );
- bool BridgeIsNavigationUrgent( void );
- bool BridgeShouldPlayerAvoid( void );
- int BridgeOnTakeDamage_Alive( const CTakeDamageInfo &info );
- float BridgeGetReasonableFacingDist( void );
- bool BridgeShouldAlwaysThink( bool *pResult );
- void BridgeOnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
- void BridgeOnRestore();
- virtual bool BridgeSpeakMapmakerInterruptConcept( string_t iszConcept );
- bool BridgeCanFlinch( void );
- bool BridgeIsCrouching( void );
- bool BridgeIsCrouchedActivity( Activity activity );
- bool BridgeQueryHearSound( CSound *pSound );
- bool BridgeCanRunAScriptedNPCInteraction( bool bForced );
- Activity BridgeGetFlinchActivity( bool bHeavyDamage, bool bGesture );
- bool BridgeOnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
- void BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
- void BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
- void BridgeHandleAnimEvent( animevent_t *pEvent );
-
- virtual void GatherConditions();
- virtual void GatherConditionsNotActive() { return; } // Override this and your behavior will call this in place of GatherConditions() when your behavior is NOT the active one.
- virtual void OnUpdateShotRegulator() {}
-
- virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace();
-
- virtual int DrawDebugTextOverlays( int text_offset );
-
- virtual int Save( ISave &save );
- virtual int Restore( IRestore &restore );
-
- static void SaveBehaviors(ISave &save, CAI_BehaviorBase *pCurrentBehavior, CAI_BehaviorBase **ppBehavior, int nBehaviors );
- static int RestoreBehaviors(IRestore &restore, CAI_BehaviorBase **ppBehavior, int nBehaviors ); // returns index of "current" behavior, or -1
-
-protected:
-
- int GetNpcState() { return GetOuter()->m_NPCState; }
-
- virtual void Precache() {}
- virtual void Spawn() {}
- virtual void UpdateOnRemove() {}
- virtual void Event_Killed( const CTakeDamageInfo &info ) {}
- virtual void CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) {}
-
- virtual void PrescheduleThink();
- virtual void OnScheduleChange();
- virtual void OnStartSchedule( int scheduleType );
-
- virtual int SelectSchedule();
- virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
- virtual void StartTask( const Task_t *pTask );
- virtual void RunTask( const Task_t *pTask );
- virtual void AimGun( void );
- virtual int TranslateSchedule( int scheduleType );
- virtual CAI_Schedule *GetSchedule(int schedule);
- virtual const char *GetSchedulingErrorName();
- virtual void BuildScheduleTestBits() {}
- bool IsCurSchedule( int schedId, bool fIdeal = true );
-
-
- CAI_Hint * GetHintNode() { return GetOuter()->GetHintNode(); }
- const CAI_Hint *GetHintNode() const { return GetOuter()->GetHintNode(); }
- void SetHintNode( CAI_Hint *pHintNode ) { GetOuter()->SetHintNode( pHintNode ); }
- void ClearHintNode( float reuseDelay = 0.0 ) { GetOuter()->ClearHintNode( reuseDelay ); }
-
-protected:
- // Used by derived classes to chain a task to a task that might not be the
- // one they are currently handling:
- void ChainStartTask( int task, float taskData = 0 );
- void ChainRunTask( int task, float taskData = 0 );
-
-protected:
-
- virtual Activity NPC_TranslateActivity( Activity activity );
-
- virtual bool IsCurTaskContinuousMove();
- virtual void OnMovementFailed() {};
- virtual void OnMovementComplete() {};
- virtual float GetDefaultNavGoalTolerance();
- virtual bool FValidateHintType( CAI_Hint *pHint );
-
- virtual bool IsValidEnemy( CBaseEntity *pEnemy );
- virtual CBaseEntity *BestEnemy();
- virtual bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
- virtual bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
- virtual float GetMaxTacticalLateralMovement( void );
- virtual bool ShouldIgnoreSound( CSound *pSound );
- virtual void OnSeeEntity( CBaseEntity *pEntity );
- virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
- virtual bool IsInterruptable( void );
- virtual bool IsNavigationUrgent( void );
- virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
- virtual float GetReasonableFacingDist( void );
- virtual bool ShouldPlayerAvoid( void );
- virtual bool CanFlinch( void );
- virtual bool IsCrouching( void );
- virtual bool IsCrouchedActivity( Activity activity );
- virtual bool QueryHearSound( CSound *pSound );
- virtual bool CanRunAScriptedNPCInteraction( bool bForced );
- virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
- virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
- virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
- virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
- virtual void HandleAnimEvent( animevent_t *pEvent );
-
- virtual bool ShouldAlwaysThink();
-
- virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) {};
- virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept ) { return false; };
-
- virtual void OnRestore() {};
-
- bool NotifyChangeBehaviorStatus( bool fCanFinishSchedule = false );
-
- bool HaveSequenceForActivity( Activity activity ) { return GetOuter()->HaveSequenceForActivity( activity ); }
-
- //---------------------------------
-
- string_t GetHintGroup() { return GetOuter()->GetHintGroup(); }
- void ClearHintGroup() { GetOuter()->ClearHintGroup(); }
- void SetHintGroup( string_t name ) { GetOuter()->SetHintGroup( name ); }
-
- virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {}
-
- //
- // These allow derived classes to implement custom schedules
- //
- static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return CAI_BaseNPC::GetSchedulingSymbols(); }
- static bool LoadSchedules() { return true; }
- virtual bool IsBehaviorSchedule( int scheduleType ) { return false; }
-
- CAI_Navigator * GetNavigator() { return GetOuter()->GetNavigator(); }
- CAI_Motor * GetMotor() { return GetOuter()->GetMotor(); }
- CAI_TacticalServices * GetTacticalServices() { return GetOuter()->GetTacticalServices(); }
-
- bool m_fOverrode;
- IBehaviorBackBridge *m_pBackBridge;
-
- DECLARE_DATADESC();
-};
-
-//-----------------------------------------------------------------------------
-// Purpose: Template provides provides back bridge to owning class and
-// establishes namespace settings
-//-----------------------------------------------------------------------------
-
-template <class NPC_CLASS = CAI_BaseNPC, const int ID_SPACE_OFFSET = 100000>
-class CAI_Behavior : public CAI_ComponentWithOuter<NPC_CLASS, CAI_BehaviorBase>
-{
-public:
- DECLARE_CLASS_NOFRIEND( CAI_Behavior, NPC_CLASS );
-
- enum
- {
- NEXT_TASK = ID_SPACE_OFFSET,
- NEXT_SCHEDULE = ID_SPACE_OFFSET,
- NEXT_CONDITION = ID_SPACE_OFFSET
- };
-
- void SetCondition( int condition )
- {
- if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
- condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
- this->GetOuter()->SetCondition( condition );
- }
-
- bool HasCondition( int condition )
- {
- if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
- condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
- return this->GetOuter()->HasCondition( condition );
- }
-
- bool HasInterruptCondition( int condition )
- {
- if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
- condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
- return this->GetOuter()->HasInterruptCondition( condition );
- }
-
- void ClearCondition( int condition )
- {
- if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
- condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
- this->GetOuter()->ClearCondition( condition );
- }
-
-protected:
- CAI_Behavior(NPC_CLASS *pOuter = NULL)
- : CAI_ComponentWithOuter<NPC_CLASS, CAI_BehaviorBase>(pOuter)
- {
- }
-
- static CAI_GlobalScheduleNamespace *GetSchedulingSymbols()
- {
- return NPC_CLASS::GetSchedulingSymbols();
- }
- virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace()
- {
- return this->GetOuter()->GetClassScheduleIdSpace();
- }
-
- static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect()
- {
- return NPC_CLASS::AccessClassScheduleIdSpaceDirect();
- }
-
-private:
- virtual bool IsBehaviorSchedule( int scheduleType ) { return ( scheduleType >= ID_SPACE_OFFSET && scheduleType < ID_SPACE_OFFSET + 10000 ); }
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Some bridges a little more complicated to allow behavior to see
-// what base class would do or control order in which it's donw
-//-----------------------------------------------------------------------------
-
-abstract_class IBehaviorBackBridge
-{
-public:
- virtual void BackBridge_GatherConditions() = 0;
- virtual int BackBridge_SelectSchedule() = 0;
- virtual int BackBridge_TranslateSchedule( int scheduleType ) = 0;
- virtual Activity BackBridge_NPC_TranslateActivity( Activity activity ) = 0;
- virtual bool BackBridge_IsValidEnemy(CBaseEntity *pEnemy) = 0;
- virtual CBaseEntity* BackBridge_BestEnemy(void) = 0;
- virtual bool BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) = 0;
- virtual bool BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) = 0;
- virtual float BackBridge_GetMaxTacticalLateralMovement( void ) = 0;
- virtual bool BackBridge_ShouldIgnoreSound( CSound *pSound ) = 0;
- virtual void BackBridge_OnSeeEntity( CBaseEntity *pEntity ) = 0;
- virtual void BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) = 0;
- virtual bool BackBridge_IsInterruptable( void ) = 0;
- virtual bool BackBridge_IsNavigationUrgent( void ) = 0;
- virtual bool BackBridge_ShouldPlayerAvoid( void ) = 0;
- virtual int BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info ) = 0;
- virtual float BackBridge_GetDefaultNavGoalTolerance() = 0;
- virtual float BackBridge_GetReasonableFacingDist( void ) = 0;
- virtual bool BackBridge_CanFlinch( void ) = 0;
- virtual bool BackBridge_IsCrouching( void ) = 0;
- virtual bool BackBridge_IsCrouchedActivity( Activity activity ) = 0;
- virtual bool BackBridge_QueryHearSound( CSound *pSound ) = 0;
- virtual bool BackBridge_CanRunAScriptedNPCInteraction( bool bForced ) = 0;
- virtual Activity BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture ) = 0;
- virtual bool BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) = 0;
- virtual void BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) = 0;
- virtual void BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) = 0;
-
- virtual void BackBridge_HandleAnimEvent( animevent_t *pEvent ) = 0;
-
-//-------------------------------------
-
-};
-
-//-----------------------------------------------------------------------------
-// Purpose: The common instantiation of the above template
-//-----------------------------------------------------------------------------
-
-typedef CAI_Behavior<> CAI_SimpleBehavior;
-
-//-----------------------------------------------------------------------------
-// Purpose: Base class for AIs that want to act as a host for CAI_Behaviors
-// NPCs aren't required to use this, but probably want to.
-//-----------------------------------------------------------------------------
-
-template <class BASE_NPC>
-class CAI_BehaviorHost : public BASE_NPC,
- private IBehaviorBackBridge
-{
-public:
- DECLARE_CLASS_NOFRIEND( CAI_BehaviorHost, BASE_NPC );
-
- CAI_BehaviorHost()
- : m_pCurBehavior(NULL)
- {
-#ifdef DEBUG
- m_fDebugInCreateBehaviors = false;
-#endif
- }
-
- void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
-
- virtual int Save( ISave &save );
- virtual int Restore( IRestore &restore );
- virtual bool CreateComponents();
-
- // Automatically called during entity construction, derived class calls AddBehavior()
- virtual bool CreateBehaviors() { return true; }
-
- // forces movement and sets a new schedule
- virtual bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity );
- virtual bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity );
- virtual void ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun);
- virtual void ForceSelectedGoRandom(void);
-
- // Bridges
- void Precache();
- void NPCInit();
- void UpdateOnRemove();
- void Event_Killed( const CTakeDamageInfo &info );
- void GatherConditions();
- void PrescheduleThink();
- int SelectSchedule();
- void KeepRunningBehavior();
- int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
- void OnScheduleChange();
- void OnStartSchedule( int scheduleType );
- int TranslateSchedule( int scheduleType );
- void StartTask( const Task_t *pTask );
- void RunTask( const Task_t *pTask );
- void AimGun( void );
- CAI_Schedule * GetSchedule(int localScheduleID);
- const char * TaskName(int taskID);
- void BuildScheduleTestBits();
-
- void OnChangeHintGroup( string_t oldGroup, string_t newGroup );
-
- Activity NPC_TranslateActivity( Activity activity );
-
- bool IsCurTaskContinuousMove();
- void OnMovementFailed();
- void OnMovementComplete();
- bool FValidateHintType( CAI_Hint *pHint );
- float GetDefaultNavGoalTolerance();
-
- bool IsValidEnemy(CBaseEntity *pEnemy);
- CBaseEntity* BestEnemy(void);
- bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
- bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
- float GetMaxTacticalLateralMovement( void );
- bool ShouldIgnoreSound( CSound *pSound );
- void OnSeeEntity( CBaseEntity *pEntity );
- void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
- bool IsInterruptable( void );
- bool IsNavigationUrgent( void );
- bool ShouldPlayerAvoid( void );
- int OnTakeDamage_Alive( const CTakeDamageInfo &info );
- float GetReasonableFacingDist( void );
- bool CanFlinch( void );
- bool IsCrouching( void );
- bool IsCrouchedActivity( Activity activity );
- bool QueryHearSound( CSound *pSound );
- bool CanRunAScriptedNPCInteraction( bool bForced );
- Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
- bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
- void HandleAnimEvent( animevent_t *pEvent );
-
- bool ShouldAlwaysThink();
-
- void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
- virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept );
-
- void OnRestore();
-
- void ModifyOrAppendCriteria( AI_CriteriaSet& set );
- void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
-
- //---------------------------------
-
- virtual bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule );
- virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior );
-
-protected:
- void AddBehavior( CAI_BehaviorBase *pBehavior );
-
- bool BehaviorSelectSchedule();
- virtual bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ) { return true; }
-
- bool IsRunningBehavior() const;
- CAI_BehaviorBase *GetRunningBehavior();
- CAI_BehaviorBase *DeferSchedulingToBehavior( CAI_BehaviorBase *pNewBehavior );
- void ChangeBehaviorTo( CAI_BehaviorBase *pNewBehavior );
-
- CAI_Schedule * GetNewSchedule();
- CAI_Schedule * GetFailSchedule();
-private:
- void BackBridge_GatherConditions();
- int BackBridge_SelectSchedule();
- int BackBridge_TranslateSchedule( int scheduleType );
- Activity BackBridge_NPC_TranslateActivity( Activity activity );
- bool BackBridge_IsValidEnemy(CBaseEntity *pEnemy);
- CBaseEntity* BackBridge_BestEnemy(void);
- bool BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
- bool BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
- float BackBridge_GetMaxTacticalLateralMovement( void );
- bool BackBridge_ShouldIgnoreSound( CSound *pSound );
- void BackBridge_OnSeeEntity( CBaseEntity *pEntity );
- void BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
- bool BackBridge_IsInterruptable( void );
- bool BackBridge_IsNavigationUrgent( void );
- bool BackBridge_ShouldPlayerAvoid( void );
- int BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info );
- float BackBridge_GetDefaultNavGoalTolerance();
- float BackBridge_GetReasonableFacingDist( void );
- bool BackBridge_CanFlinch( void );
- bool BackBridge_IsCrouching( void );
- bool BackBridge_IsCrouchedActivity( Activity activity );
- bool BackBridge_QueryHearSound( CSound *pSound );
- bool BackBridge_CanRunAScriptedNPCInteraction( bool bForced );
- Activity BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture );
- bool BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
- void BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
- void BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
-
- void BackBridge_HandleAnimEvent( animevent_t *pEvent );
-
- CAI_BehaviorBase **AccessBehaviors();
- int NumBehaviors();
-
- CAI_BehaviorBase * m_pCurBehavior;
- CUtlVector<CAI_BehaviorBase *> m_Behaviors;
-
- bool m_bCalledBehaviorSelectSchedule;
-
-#ifdef DEBUG
- bool m_fDebugInCreateBehaviors;
-#endif
-
-};
-
-//-----------------------------------------------------------------------------
-
-// The first frame a behavior begins schedule selection, it won't have had it's GatherConditions()
-// called. To fix this, BeginScheduleSelection() manually calls the new behavior's GatherConditions(),
-// but sets this global so that the baseclass GatherConditions() isn't called as well.
-extern bool g_bBehaviorHost_PreventBaseClassGatherConditions;
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_BehaviorBase::BridgeOnStartSchedule( int scheduleType )
-{
- int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType;
- OnStartSchedule( localId );
-}
-
-//-------------------------------------
-
-inline int CAI_BehaviorBase::BridgeSelectSchedule()
-{
- int result = SelectSchedule();
-
- if ( IsBehaviorSchedule( result ) )
- return GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result );
-
- return result;
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult )
-{
- m_fOverrode = true;
- int result = SelectFailSchedule( failedSchedule, failedTask, taskFailCode );
- if ( m_fOverrode )
- {
- if ( result != SCHED_NONE )
- {
- if ( IsBehaviorSchedule( result ) )
- *pResult = GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result );
- else
- *pResult = result;
- return true;
- }
- Warning( "An AI behavior is in control but has no recommended schedule\n" );
- }
- return false;
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeStartTask( const Task_t *pTask )
-{
- m_fOverrode = true;
- StartTask( pTask );
- return m_fOverrode;
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeRunTask( const Task_t *pTask)
-{
- m_fOverrode = true;
- RunTask( pTask );
- return m_fOverrode;
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeAimGun( void )
-{
- m_fOverrode = true;
- AimGun();
- return m_fOverrode;
-}
-
-//-------------------------------------
-
-inline void CAI_BehaviorBase::ChainStartTask( int task, float taskData )
-{
- Task_t tempTask = { task, taskData };
-
- bool fPrevOverride = m_fOverrode;
- GetOuter()->StartTask( (const Task_t *)&tempTask );
- m_fOverrode = fPrevOverride;;
-}
-
-//-------------------------------------
-
-inline void CAI_BehaviorBase::ChainRunTask( int task, float taskData )
-{
- Task_t tempTask = { task, taskData };
- bool fPrevOverride = m_fOverrode;
- GetOuter()->RunTask( (const Task_t *) &tempTask );
- m_fOverrode = fPrevOverride;;
-}
-
-//-------------------------------------
-
-inline int CAI_BehaviorBase::BridgeTranslateSchedule( int scheduleType )
-{
- int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType;
- int result = TranslateSchedule( localId );
-
- return result;
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult )
-{
- *ppResult = GetSchedule( localScheduleID );
- return (*ppResult != NULL );
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeTaskName( int taskID, const char **ppResult )
-{
- if ( AI_IdIsLocal( taskID ) )
- {
- *ppResult = GetSchedulingSymbols()->TaskIdToSymbol( GetClassScheduleIdSpace()->TaskLocalToGlobal( taskID ) );
- return (*ppResult != NULL );
- }
- return false;
-}
-
-//-------------------------------------
-
-inline Activity CAI_BehaviorBase::BridgeNPC_TranslateActivity( Activity activity )
-{
- return NPC_TranslateActivity( activity );
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsCurTaskContinuousMove( bool *pResult )
-{
- bool fPrevOverride = m_fOverrode;
- m_fOverrode = true;
- *pResult = IsCurTaskContinuousMove();
- bool result = m_fOverrode;
- m_fOverrode = fPrevOverride;
- return result;
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeFValidateHintType( CAI_Hint *pHint, bool *pResult )
-{
- bool fPrevOverride = m_fOverrode;
- m_fOverrode = true;
- *pResult = FValidateHintType( pHint );
- bool result = m_fOverrode;
- m_fOverrode = fPrevOverride;
- return result;
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsValidEnemy( CBaseEntity *pEnemy )
-{
- return IsValidEnemy( pEnemy );
-}
-
-//-------------------------------------
-
-inline CBaseEntity *CAI_BehaviorBase::BridgeBestEnemy()
-{
- return BestEnemy();
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsValidCover( const Vector &vLocation, CAI_Hint const *pHint )
-{
- return IsValidCover( vLocation, pHint );
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint )
-{
- return IsValidShootPosition( vLocation, pNode, pHint );
-}
-
-//-------------------------------------
-
-inline float CAI_BehaviorBase::BridgeGetMaxTacticalLateralMovement( void )
-{
- return GetMaxTacticalLateralMovement();
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeShouldIgnoreSound( CSound *pSound )
-{
- return ShouldIgnoreSound( pSound );
-}
-
-//-------------------------------------
-
-inline void CAI_BehaviorBase::BridgeOnSeeEntity( CBaseEntity *pEntity )
-{
- OnSeeEntity( pEntity );
-}
-
-//-------------------------------------
-
-inline void CAI_BehaviorBase::BridgeOnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker )
-{
- OnFriendDamaged( pSquadmate, pAttacker );
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsInterruptable( void )
-{
- return IsInterruptable();
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsNavigationUrgent( void )
-{
- return IsNavigationUrgent();
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeCanFlinch( void )
-{
- return CanFlinch();
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsCrouching( void )
-{
- return IsCrouching();
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeIsCrouchedActivity( Activity activity )
-{
- return IsCrouchedActivity( activity );
-}
-
-inline bool CAI_BehaviorBase::BridgeQueryHearSound( CSound *pSound )
-{
- return QueryHearSound( pSound );
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeCanRunAScriptedNPCInteraction( bool bForced )
-{
- return CanRunAScriptedNPCInteraction( bForced );
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeShouldPlayerAvoid( void )
-{
- return ShouldPlayerAvoid();
-}
-
-//-------------------------------------
-
-inline int CAI_BehaviorBase::BridgeOnTakeDamage_Alive( const CTakeDamageInfo &info )
-{
- return OnTakeDamage_Alive( info );
-}
-
-//-------------------------------------
-
-inline float CAI_BehaviorBase::BridgeGetReasonableFacingDist( void )
-{
- return GetReasonableFacingDist();
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeShouldAlwaysThink( bool *pResult )
-{
- bool fPrevOverride = m_fOverrode;
- m_fOverrode = true;
- *pResult = ShouldAlwaysThink();
- bool result = m_fOverrode;
- m_fOverrode = fPrevOverride;
- return result;
-}
-
-//-------------------------------------
-
-inline void CAI_BehaviorBase::BridgeOnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon )
-{
- OnChangeActiveWeapon( pOldWeapon, pNewWeapon );
-}
-
-//-------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeSpeakMapmakerInterruptConcept( string_t iszConcept )
-{
- return SpeakMapmakerInterruptConcept( iszConcept );
-}
-
-//-------------------------------------
-
-inline void CAI_BehaviorBase::BridgeOnRestore()
-{
- OnRestore();
-}
-
-//-------------------------------------
-
-inline float CAI_BehaviorBase::BridgeGetDefaultNavGoalTolerance()
-{
- return GetDefaultNavGoalTolerance();
-}
-
-//-----------------------------------------------------------------------------
-
-inline Activity CAI_BehaviorBase::BridgeGetFlinchActivity( bool bHeavyDamage, bool bGesture )
-{
- return GetFlinchActivity( bHeavyDamage, bGesture );
-}
-
-//-----------------------------------------------------------------------------
-
-inline bool CAI_BehaviorBase::BridgeOnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
-{
- return OnCalcBaseMove( pMoveGoal, distClear, pResult );
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_BehaviorBase::BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet )
-{
- ModifyOrAppendCriteria( criteriaSet );
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_BehaviorBase::BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
-{
- Teleport( newPosition, newAngles, newVelocity );
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_BehaviorBase::BridgeHandleAnimEvent( animevent_t *pEvent )
-{
- HandleAnimEvent( pEvent );
-}
-
-//-----------------------------------------------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput )
-{
- DeferSchedulingToBehavior( NULL );
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgeCleanupOnDeath( pCulprit, bFireDeathOutput );
- }
- BaseClass::CleanupOnDeath( pCulprit, bFireDeathOutput );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::GatherConditions()
-{
- // Iterate over behaviors and call GatherConditionsNotActive() on each behavior
- // not currently active.
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- if( m_Behaviors[i] != m_pCurBehavior )
- {
- m_Behaviors[i]->GatherConditionsNotActive();
- }
- }
-
- if ( m_pCurBehavior )
- m_pCurBehavior->BridgeGatherConditions();
- else
- BaseClass::GatherConditions();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_GatherConditions()
-{
- if ( g_bBehaviorHost_PreventBaseClassGatherConditions )
- return;
-
- BaseClass::GatherConditions();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnScheduleChange()
-{
- if ( m_pCurBehavior )
- m_pCurBehavior->BridgeOnScheduleChange();
- BaseClass::OnScheduleChange();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnStartSchedule( int scheduleType )
-{
- if ( m_pCurBehavior )
- m_pCurBehavior->BridgeOnStartSchedule( scheduleType );
- BaseClass::OnStartSchedule( scheduleType );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::BackBridge_SelectSchedule()
-{
- return BaseClass::SelectSchedule();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BehaviorSelectSchedule()
-{
- for ( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- if ( m_Behaviors[i]->CanSelectSchedule() && ShouldBehaviorSelectSchedule( m_Behaviors[i] ) )
- {
- DeferSchedulingToBehavior( m_Behaviors[i] );
- return true;
- }
- }
-
- DeferSchedulingToBehavior( NULL );
- return false;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsRunningBehavior() const
-{
- return ( m_pCurBehavior != NULL );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CAI_BehaviorBase *CAI_BehaviorHost<BASE_NPC>::GetRunningBehavior()
-{
- return m_pCurBehavior;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetNewSchedule()
-{
- m_bCalledBehaviorSelectSchedule = false;
- CAI_Schedule *pResult = BaseClass::GetNewSchedule();
- if ( !m_bCalledBehaviorSelectSchedule && m_pCurBehavior )
- DeferSchedulingToBehavior( NULL );
- return pResult;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetFailSchedule()
-{
- m_bCalledBehaviorSelectSchedule = false;
- CAI_Schedule *pResult = BaseClass::GetFailSchedule();
- if ( !m_bCalledBehaviorSelectSchedule && m_pCurBehavior )
- DeferSchedulingToBehavior( NULL );
- return pResult;
-}
-
-//------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::ChangeBehaviorTo( CAI_BehaviorBase *pNewBehavior )
-{
- bool change = ( m_pCurBehavior != pNewBehavior );
- CAI_BehaviorBase *pOldBehavior = m_pCurBehavior;
- m_pCurBehavior = pNewBehavior;
-
- if ( change )
- {
- if ( m_pCurBehavior )
- {
- m_pCurBehavior->BeginScheduleSelection();
-
- g_bBehaviorHost_PreventBaseClassGatherConditions = true;
- m_pCurBehavior->GatherConditions();
- g_bBehaviorHost_PreventBaseClassGatherConditions = false;
- }
-
- if ( pOldBehavior )
- {
- pOldBehavior->EndScheduleSelection();
- this->VacateStrategySlot();
- }
-
- OnChangeRunningBehavior( pOldBehavior, pNewBehavior );
- }
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CAI_BehaviorBase *CAI_BehaviorHost<BASE_NPC>::DeferSchedulingToBehavior( CAI_BehaviorBase *pNewBehavior )
-{
- CAI_BehaviorBase *pOldBehavior = m_pCurBehavior;
- ChangeBehaviorTo( pNewBehavior );
- return pOldBehavior;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::BackBridge_TranslateSchedule( int scheduleType )
-{
- return BaseClass::TranslateSchedule( scheduleType );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::TranslateSchedule( int scheduleType )
-{
- if ( m_pCurBehavior )
- {
- return m_pCurBehavior->BridgeTranslateSchedule( scheduleType );
- }
- return BaseClass::TranslateSchedule( scheduleType );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::PrescheduleThink()
-{
- BaseClass::PrescheduleThink();
- if ( m_pCurBehavior )
- m_pCurBehavior->BridgePrescheduleThink();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::SelectSchedule()
-{
- m_bCalledBehaviorSelectSchedule = true;
- if ( m_pCurBehavior )
- {
- return m_pCurBehavior->BridgeSelectSchedule();
- }
-
- return BaseClass::SelectSchedule();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::KeepRunningBehavior()
-{
- if ( m_pCurBehavior )
- m_bCalledBehaviorSelectSchedule = true;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode )
-{
- m_bCalledBehaviorSelectSchedule = true;
- int result = 0;
- if ( m_pCurBehavior && m_pCurBehavior->BridgeSelectFailSchedule( failedSchedule, failedTask, taskFailCode, &result ) )
- return result;
- return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::StartTask( const Task_t *pTask )
-{
- if ( m_pCurBehavior && m_pCurBehavior->BridgeStartTask( pTask ) )
- return;
- BaseClass::StartTask( pTask );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::RunTask( const Task_t *pTask )
-{
- if ( m_pCurBehavior && m_pCurBehavior->BridgeRunTask( pTask ) )
- return;
- BaseClass::RunTask( pTask );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::AimGun( void )
-{
- if ( m_pCurBehavior && m_pCurBehavior->BridgeAimGun() )
- return;
- BaseClass::AimGun();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetSchedule(int localScheduleID)
-{
- CAI_Schedule *pResult;
- if ( m_pCurBehavior && m_pCurBehavior->BridgeGetSchedule( localScheduleID, &pResult ) )
- return pResult;
- return BaseClass::GetSchedule( localScheduleID );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline const char *CAI_BehaviorHost<BASE_NPC>::TaskName(int taskID)
-{
- const char *pszResult = NULL;
- if ( m_pCurBehavior && m_pCurBehavior->BridgeTaskName( taskID, &pszResult ) )
- return pszResult;
- return BaseClass::TaskName( taskID );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::BuildScheduleTestBits()
-{
- if ( m_pCurBehavior )
- m_pCurBehavior->BridgeBuildScheduleTestBits();
- BaseClass::BuildScheduleTestBits();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnChangeHintGroup( string_t oldGroup, string_t newGroup )
-{
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgeOnChangeHintGroup( oldGroup, newGroup );
- }
- BaseClass::OnChangeHintGroup( oldGroup, newGroup );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline Activity CAI_BehaviorHost<BASE_NPC>::BackBridge_NPC_TranslateActivity( Activity activity )
-{
- return BaseClass::NPC_TranslateActivity( activity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline Activity CAI_BehaviorHost<BASE_NPC>::NPC_TranslateActivity( Activity activity )
-{
- if ( m_pCurBehavior )
- {
- return m_pCurBehavior->BridgeNPC_TranslateActivity( activity );
- }
- return BaseClass::NPC_TranslateActivity( activity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsCurTaskContinuousMove()
-{
- bool result = false;
- if ( m_pCurBehavior && m_pCurBehavior->BridgeIsCurTaskContinuousMove( &result ) )
- return result;
- return BaseClass::IsCurTaskContinuousMove();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnMovementFailed()
-{
- if ( m_pCurBehavior )
- m_pCurBehavior->BridgeOnMovementFailed();
- BaseClass::OnMovementFailed();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnMovementComplete()
-{
- if ( m_pCurBehavior )
- m_pCurBehavior->BridgeOnMovementComplete();
- BaseClass::OnMovementComplete();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline float CAI_BehaviorHost<BASE_NPC>::GetDefaultNavGoalTolerance()
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeGetDefaultNavGoalTolerance();
- return BaseClass::GetDefaultNavGoalTolerance();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline float CAI_BehaviorHost<BASE_NPC>::BackBridge_GetDefaultNavGoalTolerance()
-{
- return BaseClass::GetDefaultNavGoalTolerance();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::FValidateHintType( CAI_Hint *pHint )
-{
- bool result = false;
- if ( m_pCurBehavior && m_pCurBehavior->BridgeFValidateHintType( pHint, &result ) )
- return result;
- return BaseClass::FValidateHintType( pHint );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsValidEnemy(CBaseEntity *pEnemy)
-{
- return BaseClass::IsValidEnemy( pEnemy );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CBaseEntity *CAI_BehaviorHost<BASE_NPC>::BackBridge_BestEnemy(void)
-{
- return BaseClass::BestEnemy();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint )
-{
- return BaseClass::IsValidCover( vLocation, pHint );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint )
-{
- return BaseClass::IsValidShootPosition( vLocation, pNode, pHint );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline float CAI_BehaviorHost<BASE_NPC>::BackBridge_GetMaxTacticalLateralMovement( void )
-{
- return BaseClass::GetMaxTacticalLateralMovement();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_ShouldIgnoreSound( CSound *pSound )
-{
- return BaseClass::ShouldIgnoreSound( pSound );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_OnSeeEntity( CBaseEntity *pEntity )
-{
- BaseClass::OnSeeEntity( pEntity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker )
-{
- BaseClass::OnFriendDamaged( pSquadmate, pAttacker );
-}
-
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsInterruptable( void )
-{
- return BaseClass::IsInterruptable();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsNavigationUrgent( void )
-{
- return BaseClass::IsNavigationUrgent();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanFlinch( void )
-{
- return BaseClass::CanFlinch();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsCrouching( void )
-{
- return BaseClass::IsCrouching();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsCrouchedActivity( Activity activity )
-{
- return BaseClass::IsCrouchedActivity( activity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_QueryHearSound( CSound *pSound )
-{
- return BaseClass::QueryHearSound( pSound );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanRunAScriptedNPCInteraction( bool bForced )
-{
- return BaseClass::CanRunAScriptedNPCInteraction( bForced );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_ShouldPlayerAvoid( void )
-{
- return BaseClass::ShouldPlayerAvoid();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info )
-{
- return BaseClass::OnTakeDamage_Alive( info );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline float CAI_BehaviorHost<BASE_NPC>::BackBridge_GetReasonableFacingDist( void )
-{
- return BaseClass::GetReasonableFacingDist();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline Activity CAI_BehaviorHost<BASE_NPC>::BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture )
-{
- return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
-{
- return BaseClass::OnCalcBaseMove( pMoveGoal, distClear, pResult );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet &criteriaSet )
-{
- BaseClass::ModifyOrAppendCriteria( criteriaSet );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
-{
- BaseClass::Teleport( newPosition, newAngles, newVelocity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_HandleAnimEvent( animevent_t *pEvent )
-{
- BaseClass::HandleAnimEvent( pEvent );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsValidEnemy( CBaseEntity *pEnemy )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeIsValidEnemy( pEnemy );
-
- return BaseClass::IsValidEnemy( pEnemy );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CBaseEntity *CAI_BehaviorHost<BASE_NPC>::BestEnemy()
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeBestEnemy();
-
- return BaseClass::BestEnemy();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::ShouldAlwaysThink()
-{
- bool result = false;
- if ( m_pCurBehavior && m_pCurBehavior->BridgeShouldAlwaysThink( &result ) )
- return result;
- return BaseClass::ShouldAlwaysThink();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon )
-{
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgeOnChangeActiveWeapon( pOldWeapon, pNewWeapon );
- }
- BaseClass::OnChangeActiveWeapon( pOldWeapon, pNewWeapon );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::SpeakMapmakerInterruptConcept( string_t iszConcept )
-{
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- if ( m_Behaviors[i]->BridgeSpeakMapmakerInterruptConcept( iszConcept ) )
- return true;
- }
-
- return false;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnRestore()
-{
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgeOnRestore();
- }
- BaseClass::OnRestore();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsValidCover( const Vector &vLocation, CAI_Hint const *pHint )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeIsValidCover( vLocation, pHint );
-
- return BaseClass::IsValidCover( vLocation, pHint );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeIsValidShootPosition( vLocation, pNode, pHint );
-
- return BaseClass::IsValidShootPosition( vLocation, pNode, pHint );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline float CAI_BehaviorHost<BASE_NPC>::GetMaxTacticalLateralMovement( void )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeGetMaxTacticalLateralMovement();
-
- return BaseClass::GetMaxTacticalLateralMovement();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::ShouldIgnoreSound( CSound *pSound )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeShouldIgnoreSound( pSound );
-
- return BaseClass::ShouldIgnoreSound( pSound );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnSeeEntity( CBaseEntity *pEntity )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeOnSeeEntity( pEntity );
-
- BaseClass::OnSeeEntity( pEntity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeOnFriendDamaged( pSquadmate, pAttacker );
-
- BaseClass::OnFriendDamaged( pSquadmate, pAttacker );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsInterruptable( void )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeIsInterruptable();
-
- return BaseClass::IsInterruptable();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsNavigationUrgent( void )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeIsNavigationUrgent();
-
- return BaseClass::IsNavigationUrgent();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::CanFlinch( void )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeCanFlinch();
-
- return BaseClass::CanFlinch();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsCrouching( void )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeIsCrouching();
-
- return BaseClass::IsCrouching();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::IsCrouchedActivity( Activity activity )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeIsCrouchedActivity( activity );
-
- return BaseClass::IsCrouchedActivity( activity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::QueryHearSound( CSound *pSound )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeQueryHearSound( pSound );
-
- return BaseClass::QueryHearSound( pSound );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::CanRunAScriptedNPCInteraction( bool bForced )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeCanRunAScriptedNPCInteraction( bForced );
-
- return BaseClass::CanRunAScriptedNPCInteraction( bForced );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::ShouldPlayerAvoid( void )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeShouldPlayerAvoid();
-
- return BaseClass::ShouldPlayerAvoid();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::OnTakeDamage_Alive( const CTakeDamageInfo &info )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeOnTakeDamage_Alive( info );
-
- return BaseClass::OnTakeDamage_Alive( info );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline float CAI_BehaviorHost<BASE_NPC>::GetReasonableFacingDist( void )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeGetReasonableFacingDist();
-
- return BaseClass::GetReasonableFacingDist();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::Precache()
-{
- BaseClass::Precache();
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgePrecache();
- }
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity )
-{
- // If a behavior is active, we need to stop running it
- ChangeBehaviorTo( NULL );
-
- return BaseClass::ScheduledMoveToGoalEntity( scheduleType, pGoalEntity, movementActivity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity )
-{
- // If a behavior is active, we need to stop running it
- ChangeBehaviorTo( NULL );
-
- return BaseClass::ScheduledFollowPath( scheduleType, pPathStart, movementActivity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun)
-{
- // If a behavior is active, we need to stop running it
- ChangeBehaviorTo( NULL );
-
- BaseClass::ForceSelectedGo(pPlayer, targetPos, traceDir, bRun);
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::ForceSelectedGoRandom(void)
-{
- // If a behavior is active, we need to stop running it
- ChangeBehaviorTo( NULL );
-
- BaseClass::ForceSelectedGoRandom();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::NPCInit()
-{
- BaseClass::NPCInit();
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgeSpawn();
- }
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::UpdateOnRemove()
-{
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgeUpdateOnRemove();
- }
- BaseClass::UpdateOnRemove();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::Event_Killed( const CTakeDamageInfo &info )
-{
- for( int i = 0; i < m_Behaviors.Count(); i++ )
- {
- m_Behaviors[i]->BridgeEvent_Killed( info );
- }
- BaseClass::Event_Killed( info );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline Activity CAI_BehaviorHost<BASE_NPC>::GetFlinchActivity( bool bHeavyDamage, bool bGesture )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeGetFlinchActivity( bHeavyDamage, bGesture );
-
- return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeOnCalcBaseMove( pMoveGoal, distClear, pResult );
-
- return BaseClass::OnCalcBaseMove( pMoveGoal, distClear, pResult );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::ModifyOrAppendCriteria( AI_CriteriaSet &criteriaSet )
-{
- BaseClass::ModifyOrAppendCriteria( criteriaSet );
-
- if ( m_pCurBehavior )
- {
- // Append active behavior name
- criteriaSet.AppendCriteria( "active_behavior", GetRunningBehavior()->GetName() );
-
- m_pCurBehavior->BridgeModifyOrAppendCriteria( criteriaSet );
- return;
- }
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
-{
- if ( m_pCurBehavior )
- {
- m_pCurBehavior->BridgeTeleport( newPosition, newAngles, newVelocity );
- return;
- }
-
- BaseClass::Teleport( newPosition, newAngles, newVelocity );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::HandleAnimEvent( animevent_t *pEvent )
-{
- if ( m_pCurBehavior )
- return m_pCurBehavior->BridgeHandleAnimEvent( pEvent );
-
- return BaseClass::HandleAnimEvent( pEvent );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule )
-{
- if ( pBehavior == GetRunningBehavior() && !pBehavior->CanSelectSchedule() && !fCanFinishSchedule )
- {
- DeferSchedulingToBehavior( NULL );
- return true;
- }
- return false;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior )
-{
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline void CAI_BehaviorHost<BASE_NPC>::AddBehavior( CAI_BehaviorBase *pBehavior )
-{
-#ifdef DEBUG
- Assert( m_Behaviors.Find( pBehavior ) == m_Behaviors.InvalidIndex() );
- Assert( m_fDebugInCreateBehaviors );
- for ( int i = 0; i < m_Behaviors.Count(); i++)
- {
- Assert( typeid(*m_Behaviors[i]) != typeid(*pBehavior) );
- }
-#endif
- m_Behaviors.AddToTail( pBehavior );
- pBehavior->SetOuter( this );
- pBehavior->SetBackBridge( this );
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline CAI_BehaviorBase **CAI_BehaviorHost<BASE_NPC>::AccessBehaviors()
-{
- if (m_Behaviors.Count())
- return m_Behaviors.Base();
- return NULL;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::NumBehaviors()
-{
- return m_Behaviors.Count();
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::Save( ISave &save )
-{
- int result = BaseClass::Save( save );
- if ( result )
- CAI_BehaviorBase::SaveBehaviors( save, m_pCurBehavior, AccessBehaviors(), NumBehaviors() );
- return result;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline int CAI_BehaviorHost<BASE_NPC>::Restore( IRestore &restore )
-{
- int result = BaseClass::Restore( restore );
- if ( result )
- {
- int iCurrent = CAI_BehaviorBase::RestoreBehaviors( restore, AccessBehaviors(), NumBehaviors() );
- if ( iCurrent != -1 )
- m_pCurBehavior = AccessBehaviors()[iCurrent];
- else
- m_pCurBehavior = NULL;
- }
- return result;
-}
-
-//-------------------------------------
-
-template <class BASE_NPC>
-inline bool CAI_BehaviorHost<BASE_NPC>::CreateComponents()
-{
- if ( BaseClass::CreateComponents() )
- {
-#ifdef DEBUG
- m_fDebugInCreateBehaviors = true;
-#endif
- bool result = CreateBehaviors();
-#ifdef DEBUG
- m_fDebugInCreateBehaviors = false;
-#endif
- return result;
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-
-#endif // AI_BEHAVIOR_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef AI_BEHAVIOR_H
+#define AI_BEHAVIOR_H
+
+#include "ai_component.h"
+#include "ai_basenpc.h"
+#include "ai_default.h"
+#include "AI_Criteria.h"
+#include "networkvar.h"
+
+#ifdef DEBUG
+#pragma warning(push)
+#include <typeinfo>
+#pragma warning(pop)
+#pragma warning(disable:4290)
+#endif
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//-----------------------------------------------------------------------------
+// CAI_Behavior...
+//
+// Purpose: The core component that defines a behavior in an NPC by selecting
+// schedules and running tasks
+//
+// Intended to be used as an organizational tool as well as a way
+// for various NPCs to share behaviors without sharing an inheritance
+// relationship, and without cramming those behaviors into the base
+// NPC class.
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Base class defines interface to behaviors and provides bridging
+// methods
+//-----------------------------------------------------------------------------
+
+class IBehaviorBackBridge;
+
+//-------------------------------------
+
+abstract_class CAI_BehaviorBase : public CAI_Component
+{
+ DECLARE_CLASS( CAI_BehaviorBase, CAI_Component )
+public:
+ CAI_BehaviorBase(CAI_BaseNPC *pOuter = NULL)
+ : CAI_Component(pOuter),
+ m_pBackBridge(NULL)
+ {
+ }
+
+ virtual const char *GetName() = 0;
+
+ virtual bool KeyValue( const char *szKeyName, const char *szValue )
+ {
+ return false;
+ }
+
+ bool IsRunning() { Assert( GetOuter() ); return ( GetOuter()->GetRunningBehavior() == this ); }
+ virtual bool CanSelectSchedule() { return true; }
+ virtual void BeginScheduleSelection() {}
+ virtual void EndScheduleSelection() {}
+
+ void SetBackBridge( IBehaviorBackBridge *pBackBridge )
+ {
+ Assert( m_pBackBridge == NULL || pBackBridge == NULL );
+ m_pBackBridge = pBackBridge;
+ }
+
+ void BridgePrecache() { Precache(); }
+ void BridgeSpawn() { Spawn(); }
+ void BridgeUpdateOnRemove() { UpdateOnRemove(); }
+ void BridgeEvent_Killed( const CTakeDamageInfo &info ) { Event_Killed( info ); }
+ void BridgeCleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) { CleanupOnDeath( pCulprit, bFireDeathOutput ); }
+
+ void BridgeOnChangeHintGroup( string_t oldGroup, string_t newGroup ) { OnChangeHintGroup( oldGroup, newGroup ); }
+
+ void BridgeGatherConditions() { GatherConditions(); }
+ void BridgePrescheduleThink() { PrescheduleThink(); }
+ void BridgeOnScheduleChange() { OnScheduleChange(); }
+ void BridgeOnStartSchedule( int scheduleType );
+
+ int BridgeSelectSchedule();
+ bool BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult );
+ bool BridgeStartTask( const Task_t *pTask );
+ bool BridgeRunTask( const Task_t *pTask);
+ bool BridgeAimGun( void );
+ int BridgeTranslateSchedule( int scheduleType );
+ bool BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult );
+ bool BridgeTaskName(int taskID, const char **);
+ Activity BridgeNPC_TranslateActivity( Activity activity );
+ void BridgeBuildScheduleTestBits() { BuildScheduleTestBits(); }
+ bool BridgeIsCurTaskContinuousMove( bool *pResult );
+ void BridgeOnMovementFailed() { OnMovementFailed(); }
+ void BridgeOnMovementComplete() { OnMovementComplete(); }
+ float BridgeGetDefaultNavGoalTolerance();
+ bool BridgeFValidateHintType( CAI_Hint *pHint, bool *pResult );
+ bool BridgeIsValidEnemy( CBaseEntity *pEnemy );
+ CBaseEntity *BridgeBestEnemy();
+ bool BridgeIsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
+ bool BridgeIsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
+ float BridgeGetMaxTacticalLateralMovement( void );
+ bool BridgeShouldIgnoreSound( CSound *pSound );
+ void BridgeOnSeeEntity( CBaseEntity *pEntity );
+ void BridgeOnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
+ bool BridgeIsInterruptable( void );
+ bool BridgeIsNavigationUrgent( void );
+ bool BridgeShouldPlayerAvoid( void );
+ int BridgeOnTakeDamage_Alive( const CTakeDamageInfo &info );
+ float BridgeGetReasonableFacingDist( void );
+ bool BridgeShouldAlwaysThink( bool *pResult );
+ void BridgeOnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
+ void BridgeOnRestore();
+ virtual bool BridgeSpeakMapmakerInterruptConcept( string_t iszConcept );
+ bool BridgeCanFlinch( void );
+ bool BridgeIsCrouching( void );
+ bool BridgeIsCrouchedActivity( Activity activity );
+ bool BridgeQueryHearSound( CSound *pSound );
+ bool BridgeCanRunAScriptedNPCInteraction( bool bForced );
+ Activity BridgeGetFlinchActivity( bool bHeavyDamage, bool bGesture );
+ bool BridgeOnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
+ void BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
+ void BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
+ void BridgeHandleAnimEvent( animevent_t *pEvent );
+
+ virtual void GatherConditions();
+ virtual void GatherConditionsNotActive() { return; } // Override this and your behavior will call this in place of GatherConditions() when your behavior is NOT the active one.
+ virtual void OnUpdateShotRegulator() {}
+
+ virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace();
+
+ virtual int DrawDebugTextOverlays( int text_offset );
+
+ virtual int Save( ISave &save );
+ virtual int Restore( IRestore &restore );
+
+ static void SaveBehaviors(ISave &save, CAI_BehaviorBase *pCurrentBehavior, CAI_BehaviorBase **ppBehavior, int nBehaviors );
+ static int RestoreBehaviors(IRestore &restore, CAI_BehaviorBase **ppBehavior, int nBehaviors ); // returns index of "current" behavior, or -1
+
+protected:
+
+ int GetNpcState() { return GetOuter()->m_NPCState; }
+
+ virtual void Precache() {}
+ virtual void Spawn() {}
+ virtual void UpdateOnRemove() {}
+ virtual void Event_Killed( const CTakeDamageInfo &info ) {}
+ virtual void CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) {}
+
+ virtual void PrescheduleThink();
+ virtual void OnScheduleChange();
+ virtual void OnStartSchedule( int scheduleType );
+
+ virtual int SelectSchedule();
+ virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
+ virtual void StartTask( const Task_t *pTask );
+ virtual void RunTask( const Task_t *pTask );
+ virtual void AimGun( void );
+ virtual int TranslateSchedule( int scheduleType );
+ virtual CAI_Schedule *GetSchedule(int schedule);
+ virtual const char *GetSchedulingErrorName();
+ virtual void BuildScheduleTestBits() {}
+ bool IsCurSchedule( int schedId, bool fIdeal = true );
+
+
+ CAI_Hint * GetHintNode() { return GetOuter()->GetHintNode(); }
+ const CAI_Hint *GetHintNode() const { return GetOuter()->GetHintNode(); }
+ void SetHintNode( CAI_Hint *pHintNode ) { GetOuter()->SetHintNode( pHintNode ); }
+ void ClearHintNode( float reuseDelay = 0.0 ) { GetOuter()->ClearHintNode( reuseDelay ); }
+
+protected:
+ // Used by derived classes to chain a task to a task that might not be the
+ // one they are currently handling:
+ void ChainStartTask( int task, float taskData = 0 );
+ void ChainRunTask( int task, float taskData = 0 );
+
+protected:
+
+ virtual Activity NPC_TranslateActivity( Activity activity );
+
+ virtual bool IsCurTaskContinuousMove();
+ virtual void OnMovementFailed() {};
+ virtual void OnMovementComplete() {};
+ virtual float GetDefaultNavGoalTolerance();
+ virtual bool FValidateHintType( CAI_Hint *pHint );
+
+ virtual bool IsValidEnemy( CBaseEntity *pEnemy );
+ virtual CBaseEntity *BestEnemy();
+ virtual bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
+ virtual bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
+ virtual float GetMaxTacticalLateralMovement( void );
+ virtual bool ShouldIgnoreSound( CSound *pSound );
+ virtual void OnSeeEntity( CBaseEntity *pEntity );
+ virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
+ virtual bool IsInterruptable( void );
+ virtual bool IsNavigationUrgent( void );
+ virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
+ virtual float GetReasonableFacingDist( void );
+ virtual bool ShouldPlayerAvoid( void );
+ virtual bool CanFlinch( void );
+ virtual bool IsCrouching( void );
+ virtual bool IsCrouchedActivity( Activity activity );
+ virtual bool QueryHearSound( CSound *pSound );
+ virtual bool CanRunAScriptedNPCInteraction( bool bForced );
+ virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
+ virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
+ virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
+ virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
+ virtual void HandleAnimEvent( animevent_t *pEvent );
+
+ virtual bool ShouldAlwaysThink();
+
+ virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) {};
+ virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept ) { return false; };
+
+ virtual void OnRestore() {};
+
+ bool NotifyChangeBehaviorStatus( bool fCanFinishSchedule = false );
+
+ bool HaveSequenceForActivity( Activity activity ) { return GetOuter()->HaveSequenceForActivity( activity ); }
+
+ //---------------------------------
+
+ string_t GetHintGroup() { return GetOuter()->GetHintGroup(); }
+ void ClearHintGroup() { GetOuter()->ClearHintGroup(); }
+ void SetHintGroup( string_t name ) { GetOuter()->SetHintGroup( name ); }
+
+ virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {}
+
+ //
+ // These allow derived classes to implement custom schedules
+ //
+ static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return CAI_BaseNPC::GetSchedulingSymbols(); }
+ static bool LoadSchedules() { return true; }
+ virtual bool IsBehaviorSchedule( int scheduleType ) { return false; }
+
+ CAI_Navigator * GetNavigator() { return GetOuter()->GetNavigator(); }
+ CAI_Motor * GetMotor() { return GetOuter()->GetMotor(); }
+ CAI_TacticalServices * GetTacticalServices() { return GetOuter()->GetTacticalServices(); }
+
+ bool m_fOverrode;
+ IBehaviorBackBridge *m_pBackBridge;
+
+ DECLARE_DATADESC();
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Template provides provides back bridge to owning class and
+// establishes namespace settings
+//-----------------------------------------------------------------------------
+
+template <class NPC_CLASS = CAI_BaseNPC, const int ID_SPACE_OFFSET = 100000>
+class CAI_Behavior : public CAI_ComponentWithOuter<NPC_CLASS, CAI_BehaviorBase>
+{
+public:
+ DECLARE_CLASS_NOFRIEND( CAI_Behavior, NPC_CLASS );
+
+ enum
+ {
+ NEXT_TASK = ID_SPACE_OFFSET,
+ NEXT_SCHEDULE = ID_SPACE_OFFSET,
+ NEXT_CONDITION = ID_SPACE_OFFSET
+ };
+
+ void SetCondition( int condition )
+ {
+ if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
+ condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
+ this->GetOuter()->SetCondition( condition );
+ }
+
+ bool HasCondition( int condition )
+ {
+ if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
+ condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
+ return this->GetOuter()->HasCondition( condition );
+ }
+
+ bool HasInterruptCondition( int condition )
+ {
+ if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
+ condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
+ return this->GetOuter()->HasInterruptCondition( condition );
+ }
+
+ void ClearCondition( int condition )
+ {
+ if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
+ condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
+ this->GetOuter()->ClearCondition( condition );
+ }
+
+protected:
+ CAI_Behavior(NPC_CLASS *pOuter = NULL)
+ : CAI_ComponentWithOuter<NPC_CLASS, CAI_BehaviorBase>(pOuter)
+ {
+ }
+
+ static CAI_GlobalScheduleNamespace *GetSchedulingSymbols()
+ {
+ return NPC_CLASS::GetSchedulingSymbols();
+ }
+ virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace()
+ {
+ return this->GetOuter()->GetClassScheduleIdSpace();
+ }
+
+ static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect()
+ {
+ return NPC_CLASS::AccessClassScheduleIdSpaceDirect();
+ }
+
+private:
+ virtual bool IsBehaviorSchedule( int scheduleType ) { return ( scheduleType >= ID_SPACE_OFFSET && scheduleType < ID_SPACE_OFFSET + 10000 ); }
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Some bridges a little more complicated to allow behavior to see
+// what base class would do or control order in which it's donw
+//-----------------------------------------------------------------------------
+
+abstract_class IBehaviorBackBridge
+{
+public:
+ virtual void BackBridge_GatherConditions() = 0;
+ virtual int BackBridge_SelectSchedule() = 0;
+ virtual int BackBridge_TranslateSchedule( int scheduleType ) = 0;
+ virtual Activity BackBridge_NPC_TranslateActivity( Activity activity ) = 0;
+ virtual bool BackBridge_IsValidEnemy(CBaseEntity *pEnemy) = 0;
+ virtual CBaseEntity* BackBridge_BestEnemy(void) = 0;
+ virtual bool BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) = 0;
+ virtual bool BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) = 0;
+ virtual float BackBridge_GetMaxTacticalLateralMovement( void ) = 0;
+ virtual bool BackBridge_ShouldIgnoreSound( CSound *pSound ) = 0;
+ virtual void BackBridge_OnSeeEntity( CBaseEntity *pEntity ) = 0;
+ virtual void BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) = 0;
+ virtual bool BackBridge_IsInterruptable( void ) = 0;
+ virtual bool BackBridge_IsNavigationUrgent( void ) = 0;
+ virtual bool BackBridge_ShouldPlayerAvoid( void ) = 0;
+ virtual int BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info ) = 0;
+ virtual float BackBridge_GetDefaultNavGoalTolerance() = 0;
+ virtual float BackBridge_GetReasonableFacingDist( void ) = 0;
+ virtual bool BackBridge_CanFlinch( void ) = 0;
+ virtual bool BackBridge_IsCrouching( void ) = 0;
+ virtual bool BackBridge_IsCrouchedActivity( Activity activity ) = 0;
+ virtual bool BackBridge_QueryHearSound( CSound *pSound ) = 0;
+ virtual bool BackBridge_CanRunAScriptedNPCInteraction( bool bForced ) = 0;
+ virtual Activity BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture ) = 0;
+ virtual bool BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) = 0;
+ virtual void BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) = 0;
+ virtual void BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) = 0;
+
+ virtual void BackBridge_HandleAnimEvent( animevent_t *pEvent ) = 0;
+
+//-------------------------------------
+
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: The common instantiation of the above template
+//-----------------------------------------------------------------------------
+
+typedef CAI_Behavior<> CAI_SimpleBehavior;
+
+//-----------------------------------------------------------------------------
+// Purpose: Base class for AIs that want to act as a host for CAI_Behaviors
+// NPCs aren't required to use this, but probably want to.
+//-----------------------------------------------------------------------------
+
+template <class BASE_NPC>
+class CAI_BehaviorHost : public BASE_NPC,
+ private IBehaviorBackBridge
+{
+public:
+ DECLARE_CLASS_NOFRIEND( CAI_BehaviorHost, BASE_NPC );
+
+ CAI_BehaviorHost()
+ : m_pCurBehavior(NULL)
+ {
+#ifdef DEBUG
+ m_fDebugInCreateBehaviors = false;
+#endif
+ }
+
+ void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
+
+ virtual int Save( ISave &save );
+ virtual int Restore( IRestore &restore );
+ virtual bool CreateComponents();
+
+ // Automatically called during entity construction, derived class calls AddBehavior()
+ virtual bool CreateBehaviors() { return true; }
+
+ // forces movement and sets a new schedule
+ virtual bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity );
+ virtual bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity );
+ virtual void ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun);
+ virtual void ForceSelectedGoRandom(void);
+
+ // Bridges
+ void Precache();
+ void NPCInit();
+ void UpdateOnRemove();
+ void Event_Killed( const CTakeDamageInfo &info );
+ void GatherConditions();
+ void PrescheduleThink();
+ int SelectSchedule();
+ void KeepRunningBehavior();
+ int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
+ void OnScheduleChange();
+ void OnStartSchedule( int scheduleType );
+ int TranslateSchedule( int scheduleType );
+ void StartTask( const Task_t *pTask );
+ void RunTask( const Task_t *pTask );
+ void AimGun( void );
+ CAI_Schedule * GetSchedule(int localScheduleID);
+ const char * TaskName(int taskID);
+ void BuildScheduleTestBits();
+
+ void OnChangeHintGroup( string_t oldGroup, string_t newGroup );
+
+ Activity NPC_TranslateActivity( Activity activity );
+
+ bool IsCurTaskContinuousMove();
+ void OnMovementFailed();
+ void OnMovementComplete();
+ bool FValidateHintType( CAI_Hint *pHint );
+ float GetDefaultNavGoalTolerance();
+
+ bool IsValidEnemy(CBaseEntity *pEnemy);
+ CBaseEntity* BestEnemy(void);
+ bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
+ bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
+ float GetMaxTacticalLateralMovement( void );
+ bool ShouldIgnoreSound( CSound *pSound );
+ void OnSeeEntity( CBaseEntity *pEntity );
+ void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
+ bool IsInterruptable( void );
+ bool IsNavigationUrgent( void );
+ bool ShouldPlayerAvoid( void );
+ int OnTakeDamage_Alive( const CTakeDamageInfo &info );
+ float GetReasonableFacingDist( void );
+ bool CanFlinch( void );
+ bool IsCrouching( void );
+ bool IsCrouchedActivity( Activity activity );
+ bool QueryHearSound( CSound *pSound );
+ bool CanRunAScriptedNPCInteraction( bool bForced );
+ Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
+ bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
+ void HandleAnimEvent( animevent_t *pEvent );
+
+ bool ShouldAlwaysThink();
+
+ void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
+ virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept );
+
+ void OnRestore();
+
+ void ModifyOrAppendCriteria( AI_CriteriaSet& set );
+ void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
+
+ //---------------------------------
+
+ virtual bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule );
+ virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior );
+
+protected:
+ void AddBehavior( CAI_BehaviorBase *pBehavior );
+
+ bool BehaviorSelectSchedule();
+ virtual bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ) { return true; }
+
+ bool IsRunningBehavior() const;
+ CAI_BehaviorBase *GetRunningBehavior();
+ CAI_BehaviorBase *DeferSchedulingToBehavior( CAI_BehaviorBase *pNewBehavior );
+ void ChangeBehaviorTo( CAI_BehaviorBase *pNewBehavior );
+
+ CAI_Schedule * GetNewSchedule();
+ CAI_Schedule * GetFailSchedule();
+private:
+ void BackBridge_GatherConditions();
+ int BackBridge_SelectSchedule();
+ int BackBridge_TranslateSchedule( int scheduleType );
+ Activity BackBridge_NPC_TranslateActivity( Activity activity );
+ bool BackBridge_IsValidEnemy(CBaseEntity *pEnemy);
+ CBaseEntity* BackBridge_BestEnemy(void);
+ bool BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint );
+ bool BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
+ float BackBridge_GetMaxTacticalLateralMovement( void );
+ bool BackBridge_ShouldIgnoreSound( CSound *pSound );
+ void BackBridge_OnSeeEntity( CBaseEntity *pEntity );
+ void BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
+ bool BackBridge_IsInterruptable( void );
+ bool BackBridge_IsNavigationUrgent( void );
+ bool BackBridge_ShouldPlayerAvoid( void );
+ int BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info );
+ float BackBridge_GetDefaultNavGoalTolerance();
+ float BackBridge_GetReasonableFacingDist( void );
+ bool BackBridge_CanFlinch( void );
+ bool BackBridge_IsCrouching( void );
+ bool BackBridge_IsCrouchedActivity( Activity activity );
+ bool BackBridge_QueryHearSound( CSound *pSound );
+ bool BackBridge_CanRunAScriptedNPCInteraction( bool bForced );
+ Activity BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture );
+ bool BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
+ void BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
+ void BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
+
+ void BackBridge_HandleAnimEvent( animevent_t *pEvent );
+
+ CAI_BehaviorBase **AccessBehaviors();
+ int NumBehaviors();
+
+ CAI_BehaviorBase * m_pCurBehavior;
+ CUtlVector<CAI_BehaviorBase *> m_Behaviors;
+
+ bool m_bCalledBehaviorSelectSchedule;
+
+#ifdef DEBUG
+ bool m_fDebugInCreateBehaviors;
+#endif
+
+};
+
+//-----------------------------------------------------------------------------
+
+// The first frame a behavior begins schedule selection, it won't have had it's GatherConditions()
+// called. To fix this, BeginScheduleSelection() manually calls the new behavior's GatherConditions(),
+// but sets this global so that the baseclass GatherConditions() isn't called as well.
+extern bool g_bBehaviorHost_PreventBaseClassGatherConditions;
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_BehaviorBase::BridgeOnStartSchedule( int scheduleType )
+{
+ int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType;
+ OnStartSchedule( localId );
+}
+
+//-------------------------------------
+
+inline int CAI_BehaviorBase::BridgeSelectSchedule()
+{
+ int result = SelectSchedule();
+
+ if ( IsBehaviorSchedule( result ) )
+ return GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result );
+
+ return result;
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult )
+{
+ m_fOverrode = true;
+ int result = SelectFailSchedule( failedSchedule, failedTask, taskFailCode );
+ if ( m_fOverrode )
+ {
+ if ( result != SCHED_NONE )
+ {
+ if ( IsBehaviorSchedule( result ) )
+ *pResult = GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result );
+ else
+ *pResult = result;
+ return true;
+ }
+ Warning( "An AI behavior is in control but has no recommended schedule\n" );
+ }
+ return false;
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeStartTask( const Task_t *pTask )
+{
+ m_fOverrode = true;
+ StartTask( pTask );
+ return m_fOverrode;
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeRunTask( const Task_t *pTask)
+{
+ m_fOverrode = true;
+ RunTask( pTask );
+ return m_fOverrode;
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeAimGun( void )
+{
+ m_fOverrode = true;
+ AimGun();
+ return m_fOverrode;
+}
+
+//-------------------------------------
+
+inline void CAI_BehaviorBase::ChainStartTask( int task, float taskData )
+{
+ Task_t tempTask = { task, taskData };
+
+ bool fPrevOverride = m_fOverrode;
+ GetOuter()->StartTask( (const Task_t *)&tempTask );
+ m_fOverrode = fPrevOverride;;
+}
+
+//-------------------------------------
+
+inline void CAI_BehaviorBase::ChainRunTask( int task, float taskData )
+{
+ Task_t tempTask = { task, taskData };
+ bool fPrevOverride = m_fOverrode;
+ GetOuter()->RunTask( (const Task_t *) &tempTask );
+ m_fOverrode = fPrevOverride;;
+}
+
+//-------------------------------------
+
+inline int CAI_BehaviorBase::BridgeTranslateSchedule( int scheduleType )
+{
+ int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType;
+ int result = TranslateSchedule( localId );
+
+ return result;
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult )
+{
+ *ppResult = GetSchedule( localScheduleID );
+ return (*ppResult != NULL );
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeTaskName( int taskID, const char **ppResult )
+{
+ if ( AI_IdIsLocal( taskID ) )
+ {
+ *ppResult = GetSchedulingSymbols()->TaskIdToSymbol( GetClassScheduleIdSpace()->TaskLocalToGlobal( taskID ) );
+ return (*ppResult != NULL );
+ }
+ return false;
+}
+
+//-------------------------------------
+
+inline Activity CAI_BehaviorBase::BridgeNPC_TranslateActivity( Activity activity )
+{
+ return NPC_TranslateActivity( activity );
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsCurTaskContinuousMove( bool *pResult )
+{
+ bool fPrevOverride = m_fOverrode;
+ m_fOverrode = true;
+ *pResult = IsCurTaskContinuousMove();
+ bool result = m_fOverrode;
+ m_fOverrode = fPrevOverride;
+ return result;
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeFValidateHintType( CAI_Hint *pHint, bool *pResult )
+{
+ bool fPrevOverride = m_fOverrode;
+ m_fOverrode = true;
+ *pResult = FValidateHintType( pHint );
+ bool result = m_fOverrode;
+ m_fOverrode = fPrevOverride;
+ return result;
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsValidEnemy( CBaseEntity *pEnemy )
+{
+ return IsValidEnemy( pEnemy );
+}
+
+//-------------------------------------
+
+inline CBaseEntity *CAI_BehaviorBase::BridgeBestEnemy()
+{
+ return BestEnemy();
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsValidCover( const Vector &vLocation, CAI_Hint const *pHint )
+{
+ return IsValidCover( vLocation, pHint );
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint )
+{
+ return IsValidShootPosition( vLocation, pNode, pHint );
+}
+
+//-------------------------------------
+
+inline float CAI_BehaviorBase::BridgeGetMaxTacticalLateralMovement( void )
+{
+ return GetMaxTacticalLateralMovement();
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeShouldIgnoreSound( CSound *pSound )
+{
+ return ShouldIgnoreSound( pSound );
+}
+
+//-------------------------------------
+
+inline void CAI_BehaviorBase::BridgeOnSeeEntity( CBaseEntity *pEntity )
+{
+ OnSeeEntity( pEntity );
+}
+
+//-------------------------------------
+
+inline void CAI_BehaviorBase::BridgeOnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker )
+{
+ OnFriendDamaged( pSquadmate, pAttacker );
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsInterruptable( void )
+{
+ return IsInterruptable();
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsNavigationUrgent( void )
+{
+ return IsNavigationUrgent();
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeCanFlinch( void )
+{
+ return CanFlinch();
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsCrouching( void )
+{
+ return IsCrouching();
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeIsCrouchedActivity( Activity activity )
+{
+ return IsCrouchedActivity( activity );
+}
+
+inline bool CAI_BehaviorBase::BridgeQueryHearSound( CSound *pSound )
+{
+ return QueryHearSound( pSound );
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeCanRunAScriptedNPCInteraction( bool bForced )
+{
+ return CanRunAScriptedNPCInteraction( bForced );
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeShouldPlayerAvoid( void )
+{
+ return ShouldPlayerAvoid();
+}
+
+//-------------------------------------
+
+inline int CAI_BehaviorBase::BridgeOnTakeDamage_Alive( const CTakeDamageInfo &info )
+{
+ return OnTakeDamage_Alive( info );
+}
+
+//-------------------------------------
+
+inline float CAI_BehaviorBase::BridgeGetReasonableFacingDist( void )
+{
+ return GetReasonableFacingDist();
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeShouldAlwaysThink( bool *pResult )
+{
+ bool fPrevOverride = m_fOverrode;
+ m_fOverrode = true;
+ *pResult = ShouldAlwaysThink();
+ bool result = m_fOverrode;
+ m_fOverrode = fPrevOverride;
+ return result;
+}
+
+//-------------------------------------
+
+inline void CAI_BehaviorBase::BridgeOnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon )
+{
+ OnChangeActiveWeapon( pOldWeapon, pNewWeapon );
+}
+
+//-------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeSpeakMapmakerInterruptConcept( string_t iszConcept )
+{
+ return SpeakMapmakerInterruptConcept( iszConcept );
+}
+
+//-------------------------------------
+
+inline void CAI_BehaviorBase::BridgeOnRestore()
+{
+ OnRestore();
+}
+
+//-------------------------------------
+
+inline float CAI_BehaviorBase::BridgeGetDefaultNavGoalTolerance()
+{
+ return GetDefaultNavGoalTolerance();
+}
+
+//-----------------------------------------------------------------------------
+
+inline Activity CAI_BehaviorBase::BridgeGetFlinchActivity( bool bHeavyDamage, bool bGesture )
+{
+ return GetFlinchActivity( bHeavyDamage, bGesture );
+}
+
+//-----------------------------------------------------------------------------
+
+inline bool CAI_BehaviorBase::BridgeOnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
+{
+ return OnCalcBaseMove( pMoveGoal, distClear, pResult );
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_BehaviorBase::BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet )
+{
+ ModifyOrAppendCriteria( criteriaSet );
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_BehaviorBase::BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
+{
+ Teleport( newPosition, newAngles, newVelocity );
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_BehaviorBase::BridgeHandleAnimEvent( animevent_t *pEvent )
+{
+ HandleAnimEvent( pEvent );
+}
+
+//-----------------------------------------------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput )
+{
+ DeferSchedulingToBehavior( NULL );
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgeCleanupOnDeath( pCulprit, bFireDeathOutput );
+ }
+ BaseClass::CleanupOnDeath( pCulprit, bFireDeathOutput );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::GatherConditions()
+{
+ // Iterate over behaviors and call GatherConditionsNotActive() on each behavior
+ // not currently active.
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ if( m_Behaviors[i] != m_pCurBehavior )
+ {
+ m_Behaviors[i]->GatherConditionsNotActive();
+ }
+ }
+
+ if ( m_pCurBehavior )
+ m_pCurBehavior->BridgeGatherConditions();
+ else
+ BaseClass::GatherConditions();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_GatherConditions()
+{
+ if ( g_bBehaviorHost_PreventBaseClassGatherConditions )
+ return;
+
+ BaseClass::GatherConditions();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnScheduleChange()
+{
+ if ( m_pCurBehavior )
+ m_pCurBehavior->BridgeOnScheduleChange();
+ BaseClass::OnScheduleChange();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnStartSchedule( int scheduleType )
+{
+ if ( m_pCurBehavior )
+ m_pCurBehavior->BridgeOnStartSchedule( scheduleType );
+ BaseClass::OnStartSchedule( scheduleType );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::BackBridge_SelectSchedule()
+{
+ return BaseClass::SelectSchedule();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BehaviorSelectSchedule()
+{
+ for ( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ if ( m_Behaviors[i]->CanSelectSchedule() && ShouldBehaviorSelectSchedule( m_Behaviors[i] ) )
+ {
+ DeferSchedulingToBehavior( m_Behaviors[i] );
+ return true;
+ }
+ }
+
+ DeferSchedulingToBehavior( NULL );
+ return false;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsRunningBehavior() const
+{
+ return ( m_pCurBehavior != NULL );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CAI_BehaviorBase *CAI_BehaviorHost<BASE_NPC>::GetRunningBehavior()
+{
+ return m_pCurBehavior;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetNewSchedule()
+{
+ m_bCalledBehaviorSelectSchedule = false;
+ CAI_Schedule *pResult = BaseClass::GetNewSchedule();
+ if ( !m_bCalledBehaviorSelectSchedule && m_pCurBehavior )
+ DeferSchedulingToBehavior( NULL );
+ return pResult;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetFailSchedule()
+{
+ m_bCalledBehaviorSelectSchedule = false;
+ CAI_Schedule *pResult = BaseClass::GetFailSchedule();
+ if ( !m_bCalledBehaviorSelectSchedule && m_pCurBehavior )
+ DeferSchedulingToBehavior( NULL );
+ return pResult;
+}
+
+//------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::ChangeBehaviorTo( CAI_BehaviorBase *pNewBehavior )
+{
+ bool change = ( m_pCurBehavior != pNewBehavior );
+ CAI_BehaviorBase *pOldBehavior = m_pCurBehavior;
+ m_pCurBehavior = pNewBehavior;
+
+ if ( change )
+ {
+ if ( m_pCurBehavior )
+ {
+ m_pCurBehavior->BeginScheduleSelection();
+
+ g_bBehaviorHost_PreventBaseClassGatherConditions = true;
+ m_pCurBehavior->GatherConditions();
+ g_bBehaviorHost_PreventBaseClassGatherConditions = false;
+ }
+
+ if ( pOldBehavior )
+ {
+ pOldBehavior->EndScheduleSelection();
+ this->VacateStrategySlot();
+ }
+
+ OnChangeRunningBehavior( pOldBehavior, pNewBehavior );
+ }
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CAI_BehaviorBase *CAI_BehaviorHost<BASE_NPC>::DeferSchedulingToBehavior( CAI_BehaviorBase *pNewBehavior )
+{
+ CAI_BehaviorBase *pOldBehavior = m_pCurBehavior;
+ ChangeBehaviorTo( pNewBehavior );
+ return pOldBehavior;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::BackBridge_TranslateSchedule( int scheduleType )
+{
+ return BaseClass::TranslateSchedule( scheduleType );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::TranslateSchedule( int scheduleType )
+{
+ if ( m_pCurBehavior )
+ {
+ return m_pCurBehavior->BridgeTranslateSchedule( scheduleType );
+ }
+ return BaseClass::TranslateSchedule( scheduleType );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::PrescheduleThink()
+{
+ BaseClass::PrescheduleThink();
+ if ( m_pCurBehavior )
+ m_pCurBehavior->BridgePrescheduleThink();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::SelectSchedule()
+{
+ m_bCalledBehaviorSelectSchedule = true;
+ if ( m_pCurBehavior )
+ {
+ return m_pCurBehavior->BridgeSelectSchedule();
+ }
+
+ return BaseClass::SelectSchedule();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::KeepRunningBehavior()
+{
+ if ( m_pCurBehavior )
+ m_bCalledBehaviorSelectSchedule = true;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode )
+{
+ m_bCalledBehaviorSelectSchedule = true;
+ int result = 0;
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeSelectFailSchedule( failedSchedule, failedTask, taskFailCode, &result ) )
+ return result;
+ return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::StartTask( const Task_t *pTask )
+{
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeStartTask( pTask ) )
+ return;
+ BaseClass::StartTask( pTask );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::RunTask( const Task_t *pTask )
+{
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeRunTask( pTask ) )
+ return;
+ BaseClass::RunTask( pTask );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::AimGun( void )
+{
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeAimGun() )
+ return;
+ BaseClass::AimGun();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetSchedule(int localScheduleID)
+{
+ CAI_Schedule *pResult;
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeGetSchedule( localScheduleID, &pResult ) )
+ return pResult;
+ return BaseClass::GetSchedule( localScheduleID );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline const char *CAI_BehaviorHost<BASE_NPC>::TaskName(int taskID)
+{
+ const char *pszResult = NULL;
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeTaskName( taskID, &pszResult ) )
+ return pszResult;
+ return BaseClass::TaskName( taskID );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::BuildScheduleTestBits()
+{
+ if ( m_pCurBehavior )
+ m_pCurBehavior->BridgeBuildScheduleTestBits();
+ BaseClass::BuildScheduleTestBits();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnChangeHintGroup( string_t oldGroup, string_t newGroup )
+{
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgeOnChangeHintGroup( oldGroup, newGroup );
+ }
+ BaseClass::OnChangeHintGroup( oldGroup, newGroup );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline Activity CAI_BehaviorHost<BASE_NPC>::BackBridge_NPC_TranslateActivity( Activity activity )
+{
+ return BaseClass::NPC_TranslateActivity( activity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline Activity CAI_BehaviorHost<BASE_NPC>::NPC_TranslateActivity( Activity activity )
+{
+ if ( m_pCurBehavior )
+ {
+ return m_pCurBehavior->BridgeNPC_TranslateActivity( activity );
+ }
+ return BaseClass::NPC_TranslateActivity( activity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsCurTaskContinuousMove()
+{
+ bool result = false;
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeIsCurTaskContinuousMove( &result ) )
+ return result;
+ return BaseClass::IsCurTaskContinuousMove();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnMovementFailed()
+{
+ if ( m_pCurBehavior )
+ m_pCurBehavior->BridgeOnMovementFailed();
+ BaseClass::OnMovementFailed();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnMovementComplete()
+{
+ if ( m_pCurBehavior )
+ m_pCurBehavior->BridgeOnMovementComplete();
+ BaseClass::OnMovementComplete();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline float CAI_BehaviorHost<BASE_NPC>::GetDefaultNavGoalTolerance()
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeGetDefaultNavGoalTolerance();
+ return BaseClass::GetDefaultNavGoalTolerance();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline float CAI_BehaviorHost<BASE_NPC>::BackBridge_GetDefaultNavGoalTolerance()
+{
+ return BaseClass::GetDefaultNavGoalTolerance();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::FValidateHintType( CAI_Hint *pHint )
+{
+ bool result = false;
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeFValidateHintType( pHint, &result ) )
+ return result;
+ return BaseClass::FValidateHintType( pHint );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsValidEnemy(CBaseEntity *pEnemy)
+{
+ return BaseClass::IsValidEnemy( pEnemy );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CBaseEntity *CAI_BehaviorHost<BASE_NPC>::BackBridge_BestEnemy(void)
+{
+ return BaseClass::BestEnemy();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint )
+{
+ return BaseClass::IsValidCover( vLocation, pHint );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint )
+{
+ return BaseClass::IsValidShootPosition( vLocation, pNode, pHint );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline float CAI_BehaviorHost<BASE_NPC>::BackBridge_GetMaxTacticalLateralMovement( void )
+{
+ return BaseClass::GetMaxTacticalLateralMovement();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_ShouldIgnoreSound( CSound *pSound )
+{
+ return BaseClass::ShouldIgnoreSound( pSound );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_OnSeeEntity( CBaseEntity *pEntity )
+{
+ BaseClass::OnSeeEntity( pEntity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker )
+{
+ BaseClass::OnFriendDamaged( pSquadmate, pAttacker );
+}
+
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsInterruptable( void )
+{
+ return BaseClass::IsInterruptable();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsNavigationUrgent( void )
+{
+ return BaseClass::IsNavigationUrgent();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanFlinch( void )
+{
+ return BaseClass::CanFlinch();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsCrouching( void )
+{
+ return BaseClass::IsCrouching();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_IsCrouchedActivity( Activity activity )
+{
+ return BaseClass::IsCrouchedActivity( activity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_QueryHearSound( CSound *pSound )
+{
+ return BaseClass::QueryHearSound( pSound );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanRunAScriptedNPCInteraction( bool bForced )
+{
+ return BaseClass::CanRunAScriptedNPCInteraction( bForced );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_ShouldPlayerAvoid( void )
+{
+ return BaseClass::ShouldPlayerAvoid();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info )
+{
+ return BaseClass::OnTakeDamage_Alive( info );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline float CAI_BehaviorHost<BASE_NPC>::BackBridge_GetReasonableFacingDist( void )
+{
+ return BaseClass::GetReasonableFacingDist();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline Activity CAI_BehaviorHost<BASE_NPC>::BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture )
+{
+ return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
+{
+ return BaseClass::OnCalcBaseMove( pMoveGoal, distClear, pResult );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet &criteriaSet )
+{
+ BaseClass::ModifyOrAppendCriteria( criteriaSet );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
+{
+ BaseClass::Teleport( newPosition, newAngles, newVelocity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_HandleAnimEvent( animevent_t *pEvent )
+{
+ BaseClass::HandleAnimEvent( pEvent );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsValidEnemy( CBaseEntity *pEnemy )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeIsValidEnemy( pEnemy );
+
+ return BaseClass::IsValidEnemy( pEnemy );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CBaseEntity *CAI_BehaviorHost<BASE_NPC>::BestEnemy()
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeBestEnemy();
+
+ return BaseClass::BestEnemy();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::ShouldAlwaysThink()
+{
+ bool result = false;
+ if ( m_pCurBehavior && m_pCurBehavior->BridgeShouldAlwaysThink( &result ) )
+ return result;
+ return BaseClass::ShouldAlwaysThink();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon )
+{
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgeOnChangeActiveWeapon( pOldWeapon, pNewWeapon );
+ }
+ BaseClass::OnChangeActiveWeapon( pOldWeapon, pNewWeapon );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::SpeakMapmakerInterruptConcept( string_t iszConcept )
+{
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ if ( m_Behaviors[i]->BridgeSpeakMapmakerInterruptConcept( iszConcept ) )
+ return true;
+ }
+
+ return false;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnRestore()
+{
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgeOnRestore();
+ }
+ BaseClass::OnRestore();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsValidCover( const Vector &vLocation, CAI_Hint const *pHint )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeIsValidCover( vLocation, pHint );
+
+ return BaseClass::IsValidCover( vLocation, pHint );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeIsValidShootPosition( vLocation, pNode, pHint );
+
+ return BaseClass::IsValidShootPosition( vLocation, pNode, pHint );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline float CAI_BehaviorHost<BASE_NPC>::GetMaxTacticalLateralMovement( void )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeGetMaxTacticalLateralMovement();
+
+ return BaseClass::GetMaxTacticalLateralMovement();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::ShouldIgnoreSound( CSound *pSound )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeShouldIgnoreSound( pSound );
+
+ return BaseClass::ShouldIgnoreSound( pSound );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnSeeEntity( CBaseEntity *pEntity )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeOnSeeEntity( pEntity );
+
+ BaseClass::OnSeeEntity( pEntity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeOnFriendDamaged( pSquadmate, pAttacker );
+
+ BaseClass::OnFriendDamaged( pSquadmate, pAttacker );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsInterruptable( void )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeIsInterruptable();
+
+ return BaseClass::IsInterruptable();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsNavigationUrgent( void )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeIsNavigationUrgent();
+
+ return BaseClass::IsNavigationUrgent();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::CanFlinch( void )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeCanFlinch();
+
+ return BaseClass::CanFlinch();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsCrouching( void )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeIsCrouching();
+
+ return BaseClass::IsCrouching();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::IsCrouchedActivity( Activity activity )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeIsCrouchedActivity( activity );
+
+ return BaseClass::IsCrouchedActivity( activity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::QueryHearSound( CSound *pSound )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeQueryHearSound( pSound );
+
+ return BaseClass::QueryHearSound( pSound );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::CanRunAScriptedNPCInteraction( bool bForced )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeCanRunAScriptedNPCInteraction( bForced );
+
+ return BaseClass::CanRunAScriptedNPCInteraction( bForced );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::ShouldPlayerAvoid( void )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeShouldPlayerAvoid();
+
+ return BaseClass::ShouldPlayerAvoid();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::OnTakeDamage_Alive( const CTakeDamageInfo &info )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeOnTakeDamage_Alive( info );
+
+ return BaseClass::OnTakeDamage_Alive( info );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline float CAI_BehaviorHost<BASE_NPC>::GetReasonableFacingDist( void )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeGetReasonableFacingDist();
+
+ return BaseClass::GetReasonableFacingDist();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::Precache()
+{
+ BaseClass::Precache();
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgePrecache();
+ }
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity )
+{
+ // If a behavior is active, we need to stop running it
+ ChangeBehaviorTo( NULL );
+
+ return BaseClass::ScheduledMoveToGoalEntity( scheduleType, pGoalEntity, movementActivity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity )
+{
+ // If a behavior is active, we need to stop running it
+ ChangeBehaviorTo( NULL );
+
+ return BaseClass::ScheduledFollowPath( scheduleType, pPathStart, movementActivity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun)
+{
+ // If a behavior is active, we need to stop running it
+ ChangeBehaviorTo( NULL );
+
+ BaseClass::ForceSelectedGo(pPlayer, targetPos, traceDir, bRun);
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::ForceSelectedGoRandom(void)
+{
+ // If a behavior is active, we need to stop running it
+ ChangeBehaviorTo( NULL );
+
+ BaseClass::ForceSelectedGoRandom();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::NPCInit()
+{
+ BaseClass::NPCInit();
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgeSpawn();
+ }
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::UpdateOnRemove()
+{
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgeUpdateOnRemove();
+ }
+ BaseClass::UpdateOnRemove();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::Event_Killed( const CTakeDamageInfo &info )
+{
+ for( int i = 0; i < m_Behaviors.Count(); i++ )
+ {
+ m_Behaviors[i]->BridgeEvent_Killed( info );
+ }
+ BaseClass::Event_Killed( info );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline Activity CAI_BehaviorHost<BASE_NPC>::GetFlinchActivity( bool bHeavyDamage, bool bGesture )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeGetFlinchActivity( bHeavyDamage, bGesture );
+
+ return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeOnCalcBaseMove( pMoveGoal, distClear, pResult );
+
+ return BaseClass::OnCalcBaseMove( pMoveGoal, distClear, pResult );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::ModifyOrAppendCriteria( AI_CriteriaSet &criteriaSet )
+{
+ BaseClass::ModifyOrAppendCriteria( criteriaSet );
+
+ if ( m_pCurBehavior )
+ {
+ // Append active behavior name
+ criteriaSet.AppendCriteria( "active_behavior", GetRunningBehavior()->GetName() );
+
+ m_pCurBehavior->BridgeModifyOrAppendCriteria( criteriaSet );
+ return;
+ }
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
+{
+ if ( m_pCurBehavior )
+ {
+ m_pCurBehavior->BridgeTeleport( newPosition, newAngles, newVelocity );
+ return;
+ }
+
+ BaseClass::Teleport( newPosition, newAngles, newVelocity );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::HandleAnimEvent( animevent_t *pEvent )
+{
+ if ( m_pCurBehavior )
+ return m_pCurBehavior->BridgeHandleAnimEvent( pEvent );
+
+ return BaseClass::HandleAnimEvent( pEvent );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule )
+{
+ if ( pBehavior == GetRunningBehavior() && !pBehavior->CanSelectSchedule() && !fCanFinishSchedule )
+ {
+ DeferSchedulingToBehavior( NULL );
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior )
+{
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline void CAI_BehaviorHost<BASE_NPC>::AddBehavior( CAI_BehaviorBase *pBehavior )
+{
+#ifdef DEBUG
+ Assert( m_Behaviors.Find( pBehavior ) == m_Behaviors.InvalidIndex() );
+ Assert( m_fDebugInCreateBehaviors );
+ for ( int i = 0; i < m_Behaviors.Count(); i++)
+ {
+ Assert( typeid(*m_Behaviors[i]) != typeid(*pBehavior) );
+ }
+#endif
+ m_Behaviors.AddToTail( pBehavior );
+ pBehavior->SetOuter( this );
+ pBehavior->SetBackBridge( this );
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline CAI_BehaviorBase **CAI_BehaviorHost<BASE_NPC>::AccessBehaviors()
+{
+ if (m_Behaviors.Count())
+ return m_Behaviors.Base();
+ return NULL;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::NumBehaviors()
+{
+ return m_Behaviors.Count();
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::Save( ISave &save )
+{
+ int result = BaseClass::Save( save );
+ if ( result )
+ CAI_BehaviorBase::SaveBehaviors( save, m_pCurBehavior, AccessBehaviors(), NumBehaviors() );
+ return result;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline int CAI_BehaviorHost<BASE_NPC>::Restore( IRestore &restore )
+{
+ int result = BaseClass::Restore( restore );
+ if ( result )
+ {
+ int iCurrent = CAI_BehaviorBase::RestoreBehaviors( restore, AccessBehaviors(), NumBehaviors() );
+ if ( iCurrent != -1 )
+ m_pCurBehavior = AccessBehaviors()[iCurrent];
+ else
+ m_pCurBehavior = NULL;
+ }
+ return result;
+}
+
+//-------------------------------------
+
+template <class BASE_NPC>
+inline bool CAI_BehaviorHost<BASE_NPC>::CreateComponents()
+{
+ if ( BaseClass::CreateComponents() )
+ {
+#ifdef DEBUG
+ m_fDebugInCreateBehaviors = true;
+#endif
+ bool result = CreateBehaviors();
+#ifdef DEBUG
+ m_fDebugInCreateBehaviors = false;
+#endif
+ return result;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+
+#endif // AI_BEHAVIOR_H