aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/ai_playerally.h
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /sp/src/game/server/ai_playerally.h
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'sp/src/game/server/ai_playerally.h')
-rw-r--r--sp/src/game/server/ai_playerally.h493
1 files changed, 493 insertions, 0 deletions
diff --git a/sp/src/game/server/ai_playerally.h b/sp/src/game/server/ai_playerally.h
new file mode 100644
index 00000000..13b4bccf
--- /dev/null
+++ b/sp/src/game/server/ai_playerally.h
@@ -0,0 +1,493 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef AI_PLAYERALLY_H
+#define AI_PLAYERALLY_H
+
+#include "utlmap.h"
+#include "simtimer.h"
+#include "AI_Criteria.h"
+#include "ai_baseactor.h"
+#include "ai_speechfilter.h"
+#ifndef _WIN32
+#undef min
+#endif
+#include "stdstring.h"
+#ifndef _WIN32
+#undef MINMAX_H
+#include "minmax.h"
+#endif
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//-----------------------------------------------------------------------------
+
+#define TLK_ANSWER "TLK_ANSWER"
+#define TLK_ANSWER_HELLO "TLK_ANSWER_HELLO"
+#define TLK_QUESTION "TLK_QUESTION"
+#define TLK_IDLE "TLK_IDLE"
+#define TLK_STARE "TLK_STARE"
+#define TLK_LOOK "TLK_LOOK" // player looking at player for a second
+#define TLK_USE "TLK_USE"
+#define TLK_STARTFOLLOW "TLK_STARTFOLLOW"
+#define TLK_STOPFOLLOW "TLK_STOPFOLLOW"
+#define TLK_JOINPLAYER "TLK_JOINPLAYER"
+#define TLK_STOP "TLK_STOP"
+#define TLK_NOSHOOT "TLK_NOSHOOT"
+#define TLK_HELLO "TLK_HELLO"
+#define TLK_PHELLO "TLK_PHELLO"
+#define TLK_HELLO_NPC "TLK_HELLO_NPC"
+#define TLK_PIDLE "TLK_PIDLE"
+#define TLK_PQUESTION "TLK_PQUESTION"
+#define TLK_PLHURT1 "TLK_PLHURT1"
+#define TLK_PLHURT2 "TLK_PLHURT2"
+#define TLK_PLHURT3 "TLK_PLHURT3"
+#define TLK_PLHURT "TLK_PLHURT"
+#define TLK_PLPUSH "TLK_PLPUSH"
+#define TLK_PLRELOAD "TLK_PLRELOAD"
+#define TLK_SMELL "TLK_SMELL"
+#define TLK_SHOT "TLK_SHOT"
+#define TLK_WOUND "TLK_WOUND"
+#define TLK_MORTAL "TLK_MORTAL"
+#define TLK_DANGER "TLK_DANGER"
+#define TLK_SEE_COMBINE "TLK_SEE_COMBINE"
+#define TLK_ENEMY_DEAD "TLK_ENEMY_DEAD"
+#define TLK_ALYX_ENEMY_DEAD "TLK_ALYX_ENEMY_DEAD"
+#define TLK_SELECTED "TLK_SELECTED" // selected by player in command mode.
+#define TLK_COMMANDED "TLK_COMMANDED" // received orders from player in command mode
+#define TLK_COMMAND_FAILED "TLK_COMMAND_FAILED"
+#define TLK_DENY_COMMAND "TLK_DENY_COMMAND" // designer has asked this NPC to politely deny player commands to move the squad
+#define TLK_BETRAYED "TLK_BETRAYED" // player killed an ally in front of me.
+#define TLK_ALLY_KILLED "TLK_ALLY_KILLED" // witnessed an ally die some other way.
+#define TLK_ATTACKING "TLK_ATTACKING" // about to fire my weapon at a target
+#define TLK_HEAL "TLK_HEAL" // healing someone
+#define TLK_GIVEAMMO "TLK_GIVEAMMO" // giving ammo to someone
+#define TLK_DEATH "TLK_DEATH" // Death rattle
+#define TLK_HELP_ME "TLK_HELP_ME" // call out to the player for help
+#define TLK_PLYR_PHYSATK "TLK_PLYR_PHYSATK" // Player's attacked me with a thrown physics object
+#define TLK_NEWWEAPON "TLK_NEWWEAPON"
+#define TLK_PLDEAD "TLK_PLDEAD"
+#define TLK_HIDEANDRELOAD "TLK_HIDEANDRELOAD"
+#define TLK_STARTCOMBAT "TLK_STARTCOMBAT"
+#define TLK_WATCHOUT "TLK_WATCHOUT"
+#define TLK_MOBBED "TLK_MOBBED"
+#define TLK_MANY_ENEMIES "TLK_MANY_ENEMIES"
+#define TLK_FLASHLIGHT_ILLUM "TLK_FLASHLIGHT_ILLUM"
+#define TLK_FLASHLIGHT_ON "TLK_FLASHLIGHT_ON" // player turned on flashlight
+#define TLK_FLASHLIGHT_OFF "TLK_FLASHLIGHT_OFF" // player turned off flashlight
+#define TLK_DARKNESS_LOSTPLAYER "TLK_DARKNESS_LOSTPLAYER"
+#define TLK_DARKNESS_FOUNDPLAYER "TLK_DARKNESS_FOUNDPLAYER"
+#define TLK_DARKNESS_UNKNOWN_WOUND "TLK_DARKNESS_UNKNOWN_WOUND"
+#define TLK_DARKNESS_HEARDSOUND "TLK_DARKNESS_HEARDSOUND"
+#define TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT "TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT"
+#define TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT_EXPIRED "TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT_EXPIRED"
+#define TLK_DARKNESS_FOUNDENEMY_BY_FLASHLIGHT "TLK_DARKNESS_FOUNDENEMY_BY_FLASHLIGHT"
+#define TLK_DARKNESS_FLASHLIGHT_EXPIRED "TLK_DARKNESS_FLASHLIGHT_EXPIRED" // flashlight expired while not in combat
+#define TLK_DARKNESS_ENEMY_IN_DARKNESS "TLK_DARKNESS_ENEMY_IN_DARKNESS" // have an enemy, but it's in the darkness
+#define TLK_SPOTTED_INCOMING_HEADCRAB "TLK_SPOTTED_INCOMING_HEADCRAB"
+#define TLK_CANT_INTERACT_NOW "TLK_CANT_INTERACT_NOW" // to busy to interact with an object the player is holding up to me
+#define TLK_ALLY_IN_BARNACLE "TLK_ALLY_IN_BARNACLE" // Barnacle is lifting my buddy!
+#define TLK_SELF_IN_BARNACLE "TLK_SELF_IN_BARNACLE" // I was grabbed by a barnacle!
+#define TLK_FOUNDPLAYER "TLK_FOUNDPLAYER"
+#define TLK_PLAYER_KILLED_NPC "TLK_PLAYER_KILLED_NPC"
+#define TLK_ENEMY_BURNING "TLK_ENEMY_BURNING"
+#define TLK_SPOTTED_ZOMBIE_WAKEUP "TLK_SPOTTED_ZOMBIE_WAKEUP"
+#define TLK_SPOTTED_HEADCRAB_LEAVING_ZOMBIE "TLK_SPOTTED_HEADCRAB_LEAVING_ZOMBIE"
+#define TLK_DANGER_ZOMBINE_GRENADE "TLK_DANGER_ZOMBINE_GRENADE"
+#define TLK_BALLSOCKETED "TLK_BALLSOCKETED"
+
+// Vehicle passenger
+#define TLK_PASSENGER_WARN_COLLISION "TLK_PASSENGER_WARN_COLLISION" // About to collide with something
+#define TLK_PASSENGER_IMPACT "TLK_PASSENGER_IMPACT" // Just hit something
+#define TLK_PASSENGER_OVERTURNED "TLK_PASSENGER_OVERTURNED" // Vehicle has just overturned
+#define TLK_PASSENGER_REQUEST_UPRIGHT "TLK_PASSENGER_REQUEST_UPRIGHT" // Vehicle needs to be put upright
+#define TLK_PASSENGER_ERRATIC_DRIVING "TLK_PASSENGER_ERRATIC_DRIVING" // Vehicle is moving erratically
+#define TLK_PASSENGER_VEHICLE_STARTED "TLK_PASSENGER_VEHICLE_STARTED" // Vehicle has started moving
+#define TLK_PASSENGER_VEHICLE_STOPPED "TLK_PASSENGER_VEHICLE_STOPPED" // Vehicle has stopped moving
+#define TLK_PASSENGER_BEGIN_ENTRANCE "TLK_PASSENGER_BEGIN_ENTRANCE" // Passenger started entering
+#define TLK_PASSENGER_FINISH_ENTRANCE "TLK_PASSENGER_FINISH_ENTRANCE" // Passenger finished entering (is in seat)
+#define TLK_PASSENGER_BEGIN_EXIT "TLK_PASSENGER_BEGIN_EXIT" // Passenger started exiting
+#define TLK_PASSENGER_FINISH_EXIT "TLK_PASSENGER_FINISH_EXIT" // Passenger finished exiting (seat is vacated)
+#define TLK_PASSENGER_PLAYER_ENTERED "TLK_PASSENGER_PLAYER_ENTERED" // Player entered the vehicle
+#define TLK_PASSENGER_PLAYER_EXITED "TLK_PASSENGER_PLAYER_EXITED" // Player exited the vehicle
+#define TLK_PASSENGER_NEW_RADAR_CONTACT "TLK_PASSENGER_NEW_RADAR_CONTACT" // Noticed a brand new contact on the radar
+#define TLK_PASSENGER_PUNTED "TLK_PASSENGER_PUNTED" // The player has punted us while we're sitting in the vehicle
+
+// Vortigaunt
+#define TLK_VORTIGAUNT_DISPEL "TLK_VORTIGAUNT_DISPEL" // Dispel attack starting
+
+// resume is "as I was saying..." or "anyhow..."
+#define TLK_RESUME "TLK_RESUME"
+
+// tourguide stuff below
+#define TLK_TGSTAYPUT "TLK_TGSTAYPUT"
+#define TLK_TGFIND "TLK_TGFIND"
+#define TLK_TGSEEK "TLK_TGSEEK"
+#define TLK_TGLOSTYOU "TLK_TGLOSTYOU"
+#define TLK_TGCATCHUP "TLK_TGCATCHUP"
+#define TLK_TGENDTOUR "TLK_TGENDTOUR"
+
+//-----------------------------------------------------------------------------
+
+#define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this
+
+//-----------------------------------------------------------------------------
+
+#define TALKER_STARE_DIST 128 // anyone closer than this and looking at me is probably staring at me.
+
+#define TALKER_DEFER_IDLE_SPEAK_MIN 10
+#define TALKER_DEFER_IDLE_SPEAK_MAX 20
+
+//-----------------------------------------------------------------------------
+
+class CAI_PlayerAlly;
+
+//-----------------------------------------------------------------------------
+//
+// CLASS: CAI_AllySpeechManager
+//
+//-----------------------------------------------------------------------------
+
+enum ConceptCategory_t
+{
+ SPEECH_IDLE,
+ SPEECH_IMPORTANT,
+ SPEECH_PRIORITY,
+
+ SPEECH_NUM_CATEGORIES
+};
+
+struct ConceptCategoryInfo_t
+{
+ float minGlobalDelay;
+ float maxGlobalDelay;
+ float minPersonalDelay;
+ float maxPersonalDelay;
+};
+
+enum AIConceptFlags_t
+{
+ AICF_DEFAULT = 0,
+ AICF_SPEAK_ONCE = 0x01,
+ AICF_PROPAGATE_SPOKEN = 0x02,
+ AICF_TARGET_PLAYER = 0x04,
+ AICF_QUESTION = 0x08,
+ AICF_ANSWER = 0x10,
+};
+
+struct ConceptInfo_t
+{
+ AIConcept_t concept;
+ ConceptCategory_t category;
+ float minGlobalCategoryDelay;
+ float maxGlobalCategoryDelay;
+ float minPersonalCategoryDelay;
+ float maxPersonalCategoryDelay;
+ float minConceptDelay;
+ float maxConceptDelay;
+ int flags;
+};
+
+//-------------------------------------
+
+class CAI_AllySpeechManager : public CLogicalEntity
+{
+ DECLARE_CLASS( CAI_AllySpeechManager, CLogicalEntity );
+public:
+ CAI_AllySpeechManager();
+ ~CAI_AllySpeechManager();
+
+ void Spawn();
+
+ void AddCustomConcept( const ConceptInfo_t &conceptInfo );
+ ConceptCategoryInfo_t *GetConceptCategoryInfo( ConceptCategory_t category );
+ ConceptInfo_t *GetConceptInfo( AIConcept_t concept );
+ void OnSpokeConcept( CAI_PlayerAlly *pPlayerAlly, AIConcept_t concept, AI_Response *response );
+
+ void SetCategoryDelay( ConceptCategory_t category, float minDelay, float maxDelay = 0.0 );
+ bool CategoryDelayExpired( ConceptCategory_t category );
+ bool ConceptDelayExpired( AIConcept_t concept );
+
+private:
+
+ CSimpleSimTimer m_ConceptCategoryTimers[SPEECH_NUM_CATEGORIES];
+
+ CUtlMap<string_t, CSimpleSimTimer, char> m_ConceptTimers;
+
+ friend CAI_AllySpeechManager *GetAllySpeechManager();
+ static CAI_AllySpeechManager *gm_pSpeechManager;
+
+ DECLARE_DATADESC();
+};
+
+//-------------------------------------
+
+CAI_AllySpeechManager *GetAllySpeechManager();
+
+//-----------------------------------------------------------------------------
+//
+// CLASS: CAI_PlayerAlly
+//
+//-----------------------------------------------------------------------------
+
+class CAI_AllySpeechManager;
+
+enum AISpeechTargetSearchFlags_t
+{
+ AIST_PLAYERS = (1<<0),
+ AIST_NPCS = (1<<1),
+ AIST_IGNORE_RELATIONSHIP = (1<<2),
+ AIST_ANY_QUALIFIED = (1<<3),
+ AIST_FACING_TARGET = (1<<4),
+};
+
+struct AISpeechSelection_t
+{
+ AISpeechSelection_t()
+ : pResponse(NULL)
+ {
+ }
+
+ void Set( AIConcept_t newConcept, AI_Response *pNewResponse, CBaseEntity *pTarget = NULL )
+ {
+ pResponse = pNewResponse;
+ concept = newConcept;
+ hSpeechTarget = pTarget;
+ }
+
+ std::string concept;
+ AI_Response * pResponse;
+ EHANDLE hSpeechTarget;
+};
+
+//-------------------------------------
+
+class CAI_PlayerAlly : public CAI_BaseActor
+{
+ DECLARE_CLASS( CAI_PlayerAlly, CAI_BaseActor );
+
+public:
+ //---------------------------------
+
+ int ObjectCaps( void ) { return UsableNPCObjectCaps(BaseClass::ObjectCaps()); }
+ void TalkInit( void );
+
+ //---------------------------------
+ // Behavior
+ //---------------------------------
+ void GatherConditions( void );
+ void GatherEnemyConditions( CBaseEntity *pEnemy );
+ void OnStateChange( NPC_STATE OldState, NPC_STATE NewState );
+ void PrescheduleThink( void );
+ int SelectSchedule( void );
+ int SelectNonCombatSpeech( AISpeechSelection_t *pSelection );
+ virtual int SelectNonCombatSpeechSchedule();
+ int TranslateSchedule( int scheduleType );
+ void OnStartSchedule( int scheduleType );
+ void StartTask( const Task_t *pTask );
+ void RunTask( const Task_t *pTask );
+ void TaskFail( AI_TaskFailureCode_t );
+ void TaskFail( const char *pszGeneralFailText ) { BaseClass::TaskFail( pszGeneralFailText ); }
+ void ClearTransientConditions();
+ void Touch( CBaseEntity *pOther );
+
+ //---------------------------------
+ // Combat
+ //---------------------------------
+ void OnKilledNPC( CBaseCombatCharacter *pKilled );
+
+ //---------------------------------
+ // Damage handling
+ //---------------------------------
+ void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
+ int OnTakeDamage_Alive( const CTakeDamageInfo &info );
+ int TakeHealth( float flHealth, int bitsDamageType );
+ void Event_Killed( const CTakeDamageInfo &info );
+ bool CreateVPhysics();
+
+ //---------------------------------
+
+ virtual void PainSound( const CTakeDamageInfo &info );
+
+ //---------------------------------
+ // Speech & Acting
+ //---------------------------------
+ CBaseEntity *EyeLookTarget( void ); // Override to look at talk target
+ CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL );
+
+ CBaseEntity *FindSpeechTarget( int flags );
+ virtual bool IsValidSpeechTarget( int flags, CBaseEntity *pEntity );
+
+ CBaseEntity *GetSpeechTarget() { return m_hTalkTarget.Get(); }
+ void SetSpeechTarget( CBaseEntity *pSpeechTarget ) { m_hTalkTarget = pSpeechTarget; }
+
+ void SetSpeechFilter( CAI_SpeechFilter *pFilter ) { m_hSpeechFilter = pFilter; }
+ CAI_SpeechFilter *GetSpeechFilter( void ) { return m_hSpeechFilter; }
+
+ //---------------------------------
+
+ virtual bool SelectIdleSpeech( AISpeechSelection_t *pSelection );
+ virtual bool SelectAlertSpeech( AISpeechSelection_t *pSelection );
+
+ virtual bool SelectInterjection();
+ virtual bool SelectPlayerUseSpeech();
+
+ //---------------------------------
+
+ virtual bool SelectQuestionAndAnswerSpeech( AISpeechSelection_t *pSelection );
+ virtual void PostSpeakDispatchResponse( AIConcept_t concept, AI_Response *response );
+ bool SelectQuestionFriend( CBaseEntity *pFriend, AISpeechSelection_t *pSelection );
+ bool SelectAnswerFriend( CBaseEntity *pFriend, AISpeechSelection_t *pSelection, bool bRespondingToHello );
+
+ //---------------------------------
+
+ bool SelectSpeechResponse( AIConcept_t concept, const char *pszModifiers, CBaseEntity *pTarget, AISpeechSelection_t *pSelection );
+ void SetPendingSpeech( AIConcept_t concept, AI_Response *pResponse );
+ void ClearPendingSpeech();
+ bool HasPendingSpeech() { return !m_PendingConcept.empty(); }
+
+ //---------------------------------
+
+ bool CanPlaySentence( bool fDisregardState );
+ int PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener );
+
+ //---------------------------------
+
+ void DeferAllIdleSpeech( float flDelay = -1, CAI_BaseNPC *pIgnore = NULL );
+
+ //---------------------------------
+
+ bool IsOkToSpeak( ConceptCategory_t category, bool fRespondingToPlayer = false );
+
+ //---------------------------------
+
+ bool IsOkToSpeak( void );
+ bool IsOkToCombatSpeak( void );
+ bool IsOkToSpeakInResponseToPlayer( void );
+
+ bool ShouldSpeakRandom( AIConcept_t concept, int iChance );
+ bool IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPlayer = false );
+ virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
+ void ModifyOrAppendCriteria( AI_CriteriaSet& set );
+
+ //---------------------------------
+
+ float GetTimePlayerStaring() { return ( m_flTimePlayerStartStare != 0 ) ? gpGlobals->curtime - m_flTimePlayerStartStare : 0; }
+
+ //---------------------------------
+ // NPC Event Response System
+ virtual bool CanRespondToEvent( const char *ResponseConcept );
+ virtual bool RespondedTo( const char *ResponseConcept, bool bForce, bool bCancelScene );
+
+ //---------------------------------
+
+ void OnSpokeConcept( AIConcept_t concept, AI_Response *response );
+ void OnStartSpeaking();
+
+ // Inputs
+ virtual void InputIdleRespond( inputdata_t &inputdata ) {};
+ void InputSpeakResponseConcept( inputdata_t &inputdata );
+ virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept );
+
+ void DisplayDeathMessage( void );
+ virtual const char *GetDeathMessageText( void ) { return "GAMEOVER_ALLY"; }
+ void InputMakeGameEndAlly( inputdata_t &inputdata );
+ void InputMakeRegularAlly( inputdata_t &inputdata );
+ void InputAnswerQuestion( inputdata_t &inputdata );
+ void InputAnswerQuestionHello( inputdata_t &inputdata );
+ void InputEnableSpeakWhileScripting( inputdata_t &inputdata );
+ void InputDisableSpeakWhileScripting( inputdata_t &inputdata );
+
+ void AnswerQuestion( CAI_PlayerAlly *pQuestioner, int iQARandomNum, bool bAnsweringHello );
+
+protected:
+
+#ifdef HL2_DLL
+ // Health regeneration for friendly allies
+ virtual bool ShouldRegenerateHealth( void ) { return ( Classify() == CLASS_PLAYER_ALLY_VITAL ); }
+#endif
+
+ inline bool CanSpeakWhileScripting();
+
+ // Whether we are a vital ally (useful for wrting Classify() for classes that are only sometimes vital,
+ // such as the Lone Vort in Ep2.) The usual means by which any other function should determine if a character
+ // is vital is to determine Classify() == CLASS_PLAYER_ALLY_VITAL. Do not use this function outside that
+ // context.
+ inline bool IsGameEndAlly( void ) { return m_bGameEndAlly; }
+
+ //-----------------------------------------------------
+ // Conditions, Schedules, Tasks
+ //-----------------------------------------------------
+ enum
+ {
+ SCHED_TALKER_SPEAK_PENDING_IDLE = BaseClass::NEXT_SCHEDULE,
+ SCHED_TALKER_SPEAK_PENDING_ALERT,
+ SCHED_TALKER_SPEAK_PENDING_COMBAT,
+ NEXT_SCHEDULE,
+
+ TASK_TALKER_SPEAK_PENDING = BaseClass::NEXT_TASK,
+ NEXT_TASK,
+
+ COND_TALKER_CLIENTUNSEEN = BaseClass::NEXT_CONDITION,
+ COND_TALKER_PLAYER_DEAD,
+ COND_TALKER_PLAYER_STARING,
+ NEXT_CONDITION
+ };
+
+private:
+ void SetCategoryDelay( ConceptCategory_t category, float minDelay, float maxDelay = 0.0 ) { m_ConceptCategoryTimers[category].Set( minDelay, maxDelay ); }
+ bool CategoryDelayExpired( ConceptCategory_t category ) { return m_ConceptCategoryTimers[category].Expired(); }
+
+ friend class CAI_AllySpeechManager;
+
+ //---------------------------------
+
+ AI_Response m_PendingResponse;
+ std::string m_PendingConcept;
+ float m_TimePendingSet;
+
+ //---------------------------------
+
+ EHANDLE m_hTalkTarget; // who to look at while talking
+ float m_flNextRegenTime;
+ float m_flTimePlayerStartStare;
+ EHANDLE m_hPotentialSpeechTarget; // NPC to tell the response rules about when trying to find a response to talk to them with
+ float m_flNextIdleSpeechTime;
+ int m_iQARandomNumber;
+
+ //---------------------------------
+
+ CSimpleSimTimer m_ConceptCategoryTimers[3];
+
+ //---------------------------------
+
+ CHandle<CAI_SpeechFilter> m_hSpeechFilter;
+
+ bool m_bGameEndAlly;
+ bool m_bCanSpeakWhileScripting; // Allows mapmakers to override NPC_STATE_SCRIPT or IsScripting() for responses.
+
+ float m_flTimeLastRegen; // Last time I regenerated a bit of health.
+ float m_flHealthAccumulator; // Counterpart to the damage accumulator in CBaseCombatCharacter. So ally health regeneration is accurate over time.
+
+#ifdef _XBOX
+protected:
+#endif
+ DECLARE_DATADESC();
+protected:
+ DEFINE_CUSTOM_AI;
+};
+
+
+bool CAI_PlayerAlly::CanSpeakWhileScripting()
+{
+ return m_bCanSpeakWhileScripting;
+}
+
+//-----------------------------------------------------------------------------
+
+#endif // AI_PLAYERALLY_H