You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1973 lines
58 KiB
1973 lines
58 KiB
//========= 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
|
|
|