//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef AI_CRITERIA_H #define AI_CRITERIA_H #ifdef _WIN32 #pragma once #endif #include "interval.h" #include "mathlib/compressed_vector.h" #include "tier1/utlrbtree.h" #include "tier1/utlsymbol.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)); } } // We use CUtlRBTree CopyFrom() in ctor, so CritEntry_t must be POD. If // you add CUtlString or something then you must change AI_CriteriaSet // copy ctor. CUtlSymbol criterianame; char value[64]; float weight; }; CUtlRBTree 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(); const char *GetNamePtr() const; const char *GetResponsePtr() 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.Length() ? m_szContext.Get() : NULL; } 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; CUtlString m_szContext; bool m_bApplyContextToWorld; }; #endif // AI_CRITERIA_H