mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-09-01 06:59:20 +00:00
upload "kind" alien swarm
This commit is contained in:
+278
-40
@@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "utlmap.h"
|
||||
|
||||
#include "soundflags.h"
|
||||
#include "AI_ResponseSystem.h"
|
||||
#include "ai_responsesystem.h"
|
||||
#include "utldict.h"
|
||||
#include "ai_speechconcept.h"
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
@@ -21,6 +22,10 @@
|
||||
class KeyValues;
|
||||
class AI_CriteriaSet;
|
||||
|
||||
using ResponseRules::ResponseType_t;
|
||||
using ResponseRules::AI_ResponseFollowup;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Used to share a global resource or prevent a system stepping on
|
||||
// own toes.
|
||||
@@ -63,8 +68,6 @@ extern CAI_TimedSemaphore g_AIFoesTalkSemaphore;
|
||||
// Constants
|
||||
|
||||
|
||||
const float AIS_DEF_MIN_DELAY = 2.8; // Minimum amount of time an NPCs will wait after someone has spoken before considering speaking again
|
||||
const float AIS_DEF_MAX_DELAY = 3.2; // Maximum amount of time an NPCs will wait after someone has spoken before considering speaking again
|
||||
const float AIS_NO_DELAY = 0;
|
||||
const soundlevel_t AIS_DEF_SNDLVL = SNDLVL_TALKING;
|
||||
#define AI_NULL_CONCEPT NULL
|
||||
@@ -92,17 +95,20 @@ const soundlevel_t AIS_DEF_SNDLVL = SNDLVL_TALKING;
|
||||
// An id that represents the core meaning of a spoken phrase,
|
||||
// eventually to be mapped to a sentence group or scene
|
||||
|
||||
#if AI_CONCEPTS_ARE_STRINGS
|
||||
typedef const char *AIConcept_t;
|
||||
|
||||
inline bool CompareConcepts( AIConcept_t c1, AIConcept_t c2 )
|
||||
{
|
||||
return ( (void *)c1 == (void *)c2 || ( c1 && c2 && Q_stricmp( c1, c2 ) == 0 ) );
|
||||
}
|
||||
#else
|
||||
typedef CAI_Concept AIConcept_t;
|
||||
inline bool CompareConcepts( AIConcept_t c1, AIConcept_t c2 )
|
||||
{
|
||||
return c1.m_iConcept == c2.m_iConcept;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
// Specifies and stores the base timing and attentuation values for concepts
|
||||
//
|
||||
class AI_Response;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAI_Expresser
|
||||
@@ -127,7 +133,7 @@ struct ConceptHistory_t
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
|
||||
ConceptHistory_t(float timeSpoken = -1 )
|
||||
: timeSpoken( timeSpoken ), response( NULL )
|
||||
: timeSpoken( timeSpoken ), m_response( )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -137,11 +143,11 @@ struct ConceptHistory_t
|
||||
~ConceptHistory_t();
|
||||
|
||||
float timeSpoken;
|
||||
AI_Response *response;
|
||||
AI_Response m_response;
|
||||
};
|
||||
//-------------------------------------
|
||||
|
||||
class CAI_Expresser : public IResponseFilter
|
||||
class CAI_Expresser : public ResponseRules::IResponseFilter
|
||||
{
|
||||
public:
|
||||
CAI_Expresser( CBaseFlex *pOuter = NULL );
|
||||
@@ -156,11 +162,20 @@ public:
|
||||
|
||||
// --------------------------------
|
||||
|
||||
bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
bool Speak( AIConcept_t &concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
bool Speak( AIConcept_t &concept, AI_CriteriaSet *criteria, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
|
||||
// Given modifiers (which are colon-delimited strings), fill out a criteria set including this
|
||||
// character's contexts and the ones in the modifier. This lets us hang on to them after a call
|
||||
// to SpeakFindResponse.
|
||||
void GatherCriteria( AI_CriteriaSet *outputCritera, const AIConcept_t &concept, const char *modifiers );
|
||||
// These two methods allow looking up a response and dispatching it to be two different steps
|
||||
AI_Response *SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL );
|
||||
bool SpeakDispatchResponse( AIConcept_t concept, AI_Response *response, IRecipientFilter *filter = NULL );
|
||||
// AI_Response *SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL );
|
||||
// AI_Response *SpeakFindResponse( AIConcept_t &concept, AI_CriteriaSet *criteria );
|
||||
// Find the appropriate response for the given concept. Return false if none found.
|
||||
// Fills out the response object that you provide.
|
||||
bool FindResponse( AI_Response &outResponse, AIConcept_t &concept, AI_CriteriaSet *modifiers = NULL );
|
||||
virtual bool SpeakDispatchResponse( AIConcept_t &concept, AI_Response *response, AI_CriteriaSet *criteria, IRecipientFilter *filter = NULL );
|
||||
float GetResponseDuration( AI_Response *response );
|
||||
|
||||
virtual int SpeakRawSentence( const char *pszSentence, float delay, float volume = VOL_NORM, soundlevel_t soundlevel = SNDLVL_TALKING, CBaseEntity *pListener = NULL );
|
||||
@@ -168,6 +183,11 @@ public:
|
||||
bool SemaphoreIsAvailable( CBaseEntity *pTalker );
|
||||
float GetSemaphoreAvailableTime( CBaseEntity *pTalker );
|
||||
|
||||
virtual void OnSpeechFinished() {};
|
||||
|
||||
// This function can be overriden by games to suppress speech altogether during glue screens, etc
|
||||
static bool IsSpeechGloballySuppressed();
|
||||
|
||||
// --------------------------------
|
||||
|
||||
virtual bool IsSpeaking();
|
||||
@@ -194,6 +214,12 @@ public:
|
||||
// Force the NPC to release the semaphore & clear next speech time
|
||||
void ForceNotSpeaking( void );
|
||||
|
||||
// helper used in dealing with RESPONSE_ENTITYIO
|
||||
// response is the output of AI_Response::GetName
|
||||
// note: the response string will get stomped on (by strtok)
|
||||
// returns false on failure (eg, couldn't match parse contents)
|
||||
static bool FireEntIOFromResponse( char *response, CBaseEntity *pInitiator );
|
||||
|
||||
protected:
|
||||
CAI_TimedSemaphore *GetMySpeechSemaphore( CBaseEntity *pNpc );
|
||||
|
||||
@@ -203,7 +229,7 @@ protected:
|
||||
|
||||
void DumpHistories();
|
||||
|
||||
void SpeechMsg( CBaseEntity *pFlex, PRINTF_FORMAT_STRING const char *pszFormat, ... );
|
||||
void SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... );
|
||||
|
||||
// --------------------------------
|
||||
|
||||
@@ -241,7 +267,7 @@ private:
|
||||
// --------------------------------
|
||||
//
|
||||
public:
|
||||
virtual void SetOuter( CBaseFlex *pOuter ) { m_pOuter = pOuter; }
|
||||
void SetOuter( CBaseFlex *pOuter );
|
||||
|
||||
CBaseFlex * GetOuter() { return m_pOuter; }
|
||||
const CBaseFlex * GetOuter() const { return m_pOuter; }
|
||||
@@ -250,22 +276,6 @@ private:
|
||||
CHandle<CBaseFlex> m_pOuter;
|
||||
};
|
||||
|
||||
class CMultiplayer_Expresser : public CAI_Expresser
|
||||
{
|
||||
public:
|
||||
CMultiplayer_Expresser( CBaseFlex *pOuter = NULL );
|
||||
//~CMultiplayer_Expresser();
|
||||
|
||||
virtual bool IsSpeaking();
|
||||
|
||||
void AllowMultipleScenes();
|
||||
void DisallowMultipleScenes();
|
||||
|
||||
private:
|
||||
bool m_bAllowMultipleScenes;
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// An NPC base class to assist a branch of the inheritance graph
|
||||
@@ -281,10 +291,19 @@ public:
|
||||
virtual void NoteSpeaking( float duration, float delay );
|
||||
|
||||
virtual bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
virtual bool Speak( AIConcept_t concept, AI_CriteriaSet *pCriteria, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
|
||||
|
||||
void GatherCriteria( AI_CriteriaSet *outputCritera, const AIConcept_t &concept, const char *modifiers );
|
||||
// These two methods allow looking up a response and dispatching it to be two different steps
|
||||
AI_Response * SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL );
|
||||
bool SpeakDispatchResponse( AIConcept_t concept, AI_Response *response );
|
||||
// AI_Response * SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL );
|
||||
// AI_Response *SpeakFindResponse( AIConcept_t concept, AI_CriteriaSet *criteria );
|
||||
// AI_Response *SpeakFindResponse( AIConcept_t concept );
|
||||
// Find the appropriate response for the given concept. Return false if none found.
|
||||
// Fills out the response object that you provide.
|
||||
bool FindResponse( AI_Response &outResponse, AIConcept_t &concept, AI_CriteriaSet *criteria = NULL );
|
||||
|
||||
bool SpeakDispatchResponse( AIConcept_t concept, AI_Response *response, AI_CriteriaSet *criteria = NULL );
|
||||
virtual void PostSpeakDispatchResponse( AIConcept_t concept, AI_Response *response ) { return; }
|
||||
float GetResponseDuration( AI_Response *response );
|
||||
|
||||
@@ -302,7 +321,7 @@ protected:
|
||||
int PlaySentence( const char *pszSentence, float delay, float volume = VOL_NORM, soundlevel_t soundlevel = SNDLVL_TALKING, CBaseEntity *pListener = NULL );
|
||||
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set );
|
||||
|
||||
virtual IResponseSystem *GetResponseSystem();
|
||||
virtual ResponseRules::IResponseSystem *GetResponseSystem();
|
||||
// Override of base entity response input handler
|
||||
virtual void DispatchResponse( const char *conceptName );
|
||||
};
|
||||
@@ -324,6 +343,21 @@ inline bool CAI_ExpresserHost<BASE_NPC>::Speak( AIConcept_t concept, const char
|
||||
return this->GetExpresser()->Speak( concept, modifiers, pszOutResponseChosen, bufsize, filter );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_ExpresserHost<BASE_NPC>::Speak( AIConcept_t concept, AI_CriteriaSet *pCriteria, char *pszOutResponseChosen /*=NULL*/, size_t bufsize /* = 0 */, IRecipientFilter *filter /* = NULL */ )
|
||||
{
|
||||
AssertOnce( this->GetExpresser()->GetOuter() == this );
|
||||
CAI_Expresser * const RESTRICT pExpresser = this->GetExpresser();
|
||||
concept.SetSpeaker(this);
|
||||
// add in any local criteria to the one passed on the command line.
|
||||
pExpresser->GatherCriteria( pCriteria, concept, NULL );
|
||||
// call the "I have aleady gathered criteria" version of Expresser::Speak
|
||||
return pExpresser->Speak( concept, pCriteria, pszOutResponseChosen, bufsize, filter );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
@@ -341,22 +375,36 @@ inline void CAI_ExpresserHost<BASE_NPC>::ModifyOrAppendCriteria( AI_CriteriaSet&
|
||||
{
|
||||
BaseClass::ModifyOrAppendCriteria( criteriaSet );
|
||||
|
||||
|
||||
if ( this->MyNPCPointer() )
|
||||
{
|
||||
CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria( this->MyNPCPointer(), criteriaSet );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
inline IResponseSystem *CAI_ExpresserHost<BASE_NPC>::GetResponseSystem()
|
||||
inline ResponseRules::IResponseSystem *CAI_ExpresserHost<BASE_NPC>::GetResponseSystem()
|
||||
{
|
||||
extern IResponseSystem *g_pResponseSystem;
|
||||
extern ResponseRules::IResponseSystem *g_pResponseSystem;
|
||||
// Expressive NPC's use the general response system
|
||||
return g_pResponseSystem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
inline void CAI_ExpresserHost<BASE_NPC>::GatherCriteria( AI_CriteriaSet *outputCriteria, const AIConcept_t &concept, const char *modifiers )
|
||||
{
|
||||
return this->GetExpresser()->GatherCriteria( outputCriteria, concept, modifiers );
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
@@ -364,13 +412,47 @@ inline AI_Response *CAI_ExpresserHost<BASE_NPC>::SpeakFindResponse( AIConcept_t
|
||||
{
|
||||
return this->GetExpresser()->SpeakFindResponse( concept, modifiers );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
inline AI_Response *CAI_ExpresserHost<BASE_NPC>::SpeakFindResponse( AIConcept_t concept, AI_CriteriaSet *criteria /*= NULL*/ )
|
||||
{
|
||||
return this->GetExpresser()->SpeakFindResponse( concept, criteria );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// In this case we clearly don't care to hang on to the criteria, so make a convenience
|
||||
// class that generates a one off.
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
inline AI_Response * CAI_ExpresserHost<BASE_NPC>::SpeakFindResponse( AIConcept_t concept )
|
||||
{
|
||||
AI_CriteriaSet criteria;
|
||||
GatherCriteria( &criteria, concept, NULL );
|
||||
return this->GetExpresser()->SpeakFindResponse( concept, &criteria );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_ExpresserHost<BASE_NPC>::SpeakDispatchResponse( AIConcept_t concept, AI_Response *response )
|
||||
inline bool CAI_ExpresserHost<BASE_NPC>::FindResponse( AI_Response &outResponse, AIConcept_t &concept, AI_CriteriaSet *criteria )
|
||||
{
|
||||
if ( this->GetExpresser()->SpeakDispatchResponse( concept, response ) )
|
||||
return this->GetExpresser()->FindResponse( outResponse, concept, criteria );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_ExpresserHost<BASE_NPC>::SpeakDispatchResponse( AIConcept_t concept, AI_Response *response, AI_CriteriaSet *criteria )
|
||||
{
|
||||
if ( this->GetExpresser()->SpeakDispatchResponse( concept, response, criteria ) )
|
||||
{
|
||||
PostSpeakDispatchResponse( concept, response );
|
||||
return true;
|
||||
@@ -398,4 +480,160 @@ inline void CAI_ExpresserHost<BASE_NPC>::DispatchResponse( const char *conceptNa
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// A shim under CAI_ExpresserHost you can use when deriving a new expresser
|
||||
/// host type under CAI_BaseNPC. This does the extra step of declaring an m_pExpresser
|
||||
/// member and initializing it from CreateComponents(). If your BASE_NPC class isn't
|
||||
/// actually an NPC, then CreateComponents() never gets called and you won't have
|
||||
/// an expresser created.
|
||||
/// Note: you still need to add m_pExpresser to the Datadesc for your derived type.
|
||||
/// This is because I couldn't figure out how to make a templatized datadesc declaration
|
||||
/// that works generically on the template type.
|
||||
template <class BASE_NPC, class EXPRESSER_TYPE>
|
||||
class CAI_ExpresserHostWithData : public CAI_ExpresserHost<BASE_NPC>
|
||||
{
|
||||
DECLARE_CLASS_NOFRIEND( CAI_ExpresserHostWithData, CAI_ExpresserHost );
|
||||
|
||||
public:
|
||||
CAI_ExpresserHostWithData( ) : m_pExpresser(NULL) {};
|
||||
|
||||
virtual CAI_Expresser *GetExpresser() { return m_pExpresser; }
|
||||
const CAI_Expresser *GetExpresser() const { return m_pExpresser; }
|
||||
|
||||
virtual bool CreateComponents()
|
||||
{
|
||||
return BaseClass::CreateComponents() && ( CreateExpresser() != NULL );
|
||||
}
|
||||
|
||||
protected:
|
||||
EXPRESSER_TYPE *CreateExpresser( void )
|
||||
{
|
||||
AssertMsg1( m_pExpresser == NULL, "Tried to double-initialize expresser in %s\n", GetDebugName() );
|
||||
m_pExpresser = new EXPRESSER_TYPE(this);
|
||||
if ( !m_pExpresser)
|
||||
{
|
||||
AssertMsg1( false, "Creating an expresser failed in %s\n", GetDebugName() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_pExpresser->Connect(this);
|
||||
return m_pExpresser;
|
||||
}
|
||||
|
||||
virtual ~CAI_ExpresserHostWithData( void )
|
||||
{
|
||||
delete m_pExpresser;
|
||||
m_pExpresser = NULL;
|
||||
}
|
||||
|
||||
EXPRESSER_TYPE *m_pExpresser;
|
||||
};
|
||||
|
||||
/// response rules
|
||||
namespace RR
|
||||
{
|
||||
/// some applycontext clauses have operators preceding them,
|
||||
/// like ++1 which means "take the current value and increment it
|
||||
/// by one". These classes detect these cases and do the appropriate
|
||||
/// thing.
|
||||
class CApplyContextOperator
|
||||
{
|
||||
public:
|
||||
inline CApplyContextOperator( int nSkipChars ) : m_nSkipChars(nSkipChars) {};
|
||||
|
||||
/// perform whatever this operator does upon the given context value.
|
||||
/// Default op is simply to copy old to new.
|
||||
/// pOldValue should be the currently set value of the context. May be NULL meaning no prior value.
|
||||
/// pOperator the value that applycontext says to set
|
||||
/// pNewValue a pointer to a buffer where the real new value will be writ.
|
||||
/// returns true on success; false on failure (eg, tried to increment a
|
||||
/// non-numeric value).
|
||||
virtual bool Apply( const char *pOldValue, const char *pOperator, char *pNewValue, int pNewValBufSize );
|
||||
|
||||
/// This is the function that should be called from outside,
|
||||
/// fed the input string, it'll select the right operator
|
||||
/// to apply.
|
||||
static CApplyContextOperator *FindOperator( const char *pContextString );
|
||||
|
||||
protected:
|
||||
int m_nSkipChars; // how many chars to "skip" in the value string to get past the op specifier to the actual value
|
||||
// eg, "++3" has a m_nSkipChars of 2, because the op string "++" is two characters.
|
||||
};
|
||||
|
||||
class CIncrementOperator : public CApplyContextOperator
|
||||
{
|
||||
public:
|
||||
inline CIncrementOperator( int nSkipChars ) : CApplyContextOperator(nSkipChars) {};
|
||||
virtual bool Apply( const char *pOldValue, const char *pOperator, char *pNewValue, int pNewValBufSize );
|
||||
};
|
||||
|
||||
class CDecrementOperator : public CApplyContextOperator
|
||||
{
|
||||
public:
|
||||
inline CDecrementOperator( int nSkipChars ) : CApplyContextOperator(nSkipChars) {};
|
||||
virtual bool Apply( const char *pOldValue, const char *pOperator, char *pNewValue, int pNewValBufSize );
|
||||
};
|
||||
|
||||
class CToggleOperator : public CApplyContextOperator
|
||||
{
|
||||
public:
|
||||
inline CToggleOperator( int nSkipChars ) : CApplyContextOperator(nSkipChars) {};
|
||||
virtual bool Apply( const char *pOldValue, const char *pOperator, char *pNewValue, int pNewValBufSize );
|
||||
};
|
||||
|
||||
// the singleton operators
|
||||
extern CApplyContextOperator sm_OpCopy;
|
||||
extern CIncrementOperator sm_OpIncrement;
|
||||
extern CDecrementOperator sm_OpDecrement;
|
||||
extern CToggleOperator sm_OpToggle;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "ai_speechqueue.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A kind of AI Expresser that can dispatch a follow-up speech event when it
|
||||
// finishes speaking.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAI_ExpresserWithFollowup : public CAI_Expresser
|
||||
{
|
||||
public:
|
||||
CAI_ExpresserWithFollowup( CBaseFlex *pOuter = NULL ) : CAI_Expresser(pOuter),
|
||||
m_pPostponedFollowup(NULL)
|
||||
{};
|
||||
virtual bool Speak( AIConcept_t &concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||
virtual bool SpeakDispatchResponse( AIConcept_t &concept, AI_Response *response, AI_CriteriaSet *criteria, IRecipientFilter *filter = NULL );
|
||||
virtual void SpeakDispatchFollowup( AI_ResponseFollowup &followup );
|
||||
|
||||
virtual void OnSpeechFinished();
|
||||
|
||||
typedef CAI_Expresser BaseClass;
|
||||
protected:
|
||||
static void DispatchFollowupThroughQueue( const AIConcept_t &concept,
|
||||
const char *criteriaStr,
|
||||
const CResponseQueue::CFollowupTargetSpec_t &target,
|
||||
float delay,
|
||||
CBaseEntity * RESTRICT pOuter );
|
||||
|
||||
AI_ResponseFollowup *m_pPostponedFollowup; // TODO: save/restore
|
||||
CResponseQueue::CFollowupTargetSpec_t m_followupTarget;
|
||||
};
|
||||
|
||||
class CMultiplayer_Expresser : public CAI_ExpresserWithFollowup
|
||||
{
|
||||
public:
|
||||
CMultiplayer_Expresser( CBaseFlex *pOuter = NULL );
|
||||
//~CMultiplayer_Expresser();
|
||||
|
||||
virtual bool IsSpeaking();
|
||||
|
||||
void AllowMultipleScenes();
|
||||
void DisallowMultipleScenes();
|
||||
|
||||
private:
|
||||
bool m_bAllowMultipleScenes;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // AI_SPEECH_H
|
||||
|
||||
Reference in New Issue
Block a user