//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef AI_CRITERIA_H #define AI_CRITERIA_H #ifdef _WIN32 #pragma once #endif #include "tier1/utlrbtree.h" #include "tier1/utlsymbol.h" #include "interval.h" #include "mathlib/compressed_vector.h" extern const char *SplitContext( const char *raw, char *key, int keylen, char *value, int valuelen, float *duration ); class AI_CriteriaSet { public: AI_CriteriaSet(); AI_CriteriaSet( const AI_CriteriaSet& src ); ~AI_CriteriaSet(); void AppendCriteria( const char *criteria, const char *value = "", float weight = 1.0f ); void RemoveCriteria( const char *criteria ); void Describe(); int GetCount() const; int FindCriterionIndex( const char *name ) const; const char *GetName( int index ) const; const char *GetValue( int index ) const; float GetWeight( int index ) const; private: struct CritEntry_t { CritEntry_t() : criterianame( UTL_INVAL_SYMBOL ), weight( 0.0f ) { value[ 0 ] = 0; } CritEntry_t( const CritEntry_t& src ) { criterianame = src.criterianame; value[ 0 ] = 0; weight = src.weight; SetValue( src.value ); } CritEntry_t& operator=( const CritEntry_t& src ) { if ( this == &src ) return *this; criterianame = src.criterianame; weight = src.weight; SetValue( src.value ); return *this; } static bool LessFunc( const CritEntry_t& lhs, const CritEntry_t& rhs ) { return Q_stricmp( lhs.criterianame.String(), rhs.criterianame.String() ) < 0 ? true : false; } void SetValue( char const *str ) { if ( !str ) { value[ 0 ] = 0; } else { Q_strncpy( value, str, sizeof( value ) ); } } CUtlSymbol criterianame; char value[ 64 ]; float weight; }; CUtlRBTree< CritEntry_t, short > m_Lookup; }; //#pragma pack(1) template struct response_interval_t { T start; T range; interval_t &ToInterval( interval_t &dest ) const { dest.start = start; dest.range = range; return dest; } void FromInterval( const interval_t &from ) { start = from.start; range = from.range; } float Random() const { interval_t temp = { start, range }; return RandomInterval( temp ); } }; typedef response_interval_t responseparams_interval_t; struct AI_ResponseParams { DECLARE_SIMPLE_DATADESC(); enum { RG_DELAYAFTERSPEAK = (1<<0), RG_SPEAKONCE = (1<<1), RG_ODDS = (1<<2), RG_RESPEAKDELAY = (1<<3), RG_SOUNDLEVEL = (1<<4), RG_DONT_USE_SCENE = (1<<5), RG_STOP_ON_NONIDLE = (1<<6), RG_WEAPONDELAY = (1<<7), RG_DELAYBEFORESPEAK = (1<<8), }; AI_ResponseParams() { flags = 0; odds = 100; delay.start = 0; delay.range = 0; respeakdelay.start = 0; respeakdelay.range = 0; weapondelay.start = 0; weapondelay.range = 0; soundlevel = 0; predelay.start = 0; predelay.range = 0; } responseparams_interval_t delay; //4 responseparams_interval_t respeakdelay; //8 responseparams_interval_t weapondelay; //12 short odds; //14 short flags; //16 byte soundlevel; //17 responseparams_interval_t predelay; //21 }; //#pragma pack() //----------------------------------------------------------------------------- // Purpose: Generic container for a response to a match to a criteria set // This is what searching for a response returns //----------------------------------------------------------------------------- enum ResponseType_t { RESPONSE_NONE = 0, RESPONSE_SPEAK, RESPONSE_SENTENCE, RESPONSE_SCENE, RESPONSE_RESPONSE, // A reference to another response by name RESPONSE_PRINT, NUM_RESPONSES, }; class AI_Response { public: DECLARE_SIMPLE_DATADESC(); AI_Response(); AI_Response( const AI_Response &from ); ~AI_Response(); AI_Response &operator=( const AI_Response &from ); void Release(); void GetName( char *buf, size_t buflen ) const; void GetResponse( char *buf, size_t buflen ) const; const AI_ResponseParams *GetParams() const { return &m_Params; } ResponseType_t GetType() const { return (ResponseType_t)m_Type; } soundlevel_t GetSoundLevel() const; float GetRespeakDelay() const; float GetWeaponDelay() const; bool GetSpeakOnce() const; bool ShouldntUseScene( ) const; bool ShouldBreakOnNonIdle( void ) const; int GetOdds() const; float GetDelay() const; float GetPreDelay() const; void SetContext( const char *context ); const char * GetContext( void ) const { return m_szContext; } bool IsApplyContextToWorld( void ) { return m_bApplyContextToWorld; } void Describe(); const AI_CriteriaSet* GetCriteria(); void Init( ResponseType_t type, const char *responseName, const AI_CriteriaSet& criteria, const AI_ResponseParams& responseparams, const char *matchingRule, const char *applyContext, bool bApplyContextToWorld ); static const char *DescribeResponse( ResponseType_t type ); enum { MAX_RESPONSE_NAME = 64, MAX_RULE_NAME = 64 }; private: byte m_Type; char m_szResponseName[ MAX_RESPONSE_NAME ]; char m_szMatchingRule[ MAX_RULE_NAME ]; // The initial criteria to which we are responsive AI_CriteriaSet *m_pCriteria; AI_ResponseParams m_Params; char * m_szContext; bool m_bApplyContextToWorld; }; #endif // AI_CRITERIA_H