diff --git a/SpyCustom/IVGUI.h b/SpyCustom/IVGUI.h new file mode 100644 index 0000000..5eef332 --- /dev/null +++ b/SpyCustom/IVGUI.h @@ -0,0 +1,79 @@ +#ifndef IVGUI_H +#define IVGUI_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "interface.h" +#include "VGUI.h" + +#include "IAppSystem.h" + +class KeyValues; + +namespace vgui +{ + + typedef unsigned long HPanel; + typedef int HContext; + + enum + { + DEFAULT_VGUI_CONTEXT = ((vgui::HContext)~0) + }; + + typedef unsigned long HPanel; + + class IVGui : public IAppSystem + { + public: + virtual void Start() = 0; + + virtual void Stop() = 0; + + virtual bool IsRunning() = 0; + + virtual void RunFrame() = 0; + + virtual void ShutdownMessage(unsigned int shutdownID) = 0; + + virtual VPANEL AllocPanel() = 0; + virtual void FreePanel(VPANEL panel) = 0; + + virtual void DPrintf(PRINTF_FORMAT_STRING const char* format, ...) = 0; + virtual void DPrintf2(PRINTF_FORMAT_STRING const char* format, ...) = 0; + virtual void SpewAllActivePanelNames() = 0; + + virtual HPanel PanelToHandle(VPANEL panel) = 0; + virtual VPANEL HandleToPanel(HPanel index) = 0; + virtual void MarkPanelForDeletion(VPANEL panel) = 0; + + virtual void AddTickSignal(VPANEL panel, int intervalMilliseconds = 0) = 0; + virtual void RemoveTickSignal(VPANEL panel) = 0; + + virtual void PostMessage(VPANEL target, KeyValues* params, VPANEL from, float delaySeconds = 0.0f) = 0; + + virtual HContext CreateContext() = 0; + virtual void DestroyContext(HContext context) = 0; + + virtual void AssociatePanelWithContext(HContext context, VPANEL pRoot) = 0; + + virtual void ActivateContext(HContext context) = 0; + + virtual void SetSleep(bool state) = 0; + + virtual bool GetShouldVGuiControlSleep() = 0; + + virtual void SetVRMode(bool bVRMode) = 0; + virtual bool GetVRMode() = 0; + + virtual void AddTickSignalToHead(VPANEL panel, int intervalMilliseconds = 0) = 0; + }; + +#define VGUI_IVGUI_INTERFACE_VERSION "VGUI_ivgui008" + +}; + + +#endif \ No newline at end of file diff --git a/SpyCustom/IVguiMatInfo.h b/SpyCustom/IVguiMatInfo.h new file mode 100644 index 0000000..1278a27 --- /dev/null +++ b/SpyCustom/IVguiMatInfo.h @@ -0,0 +1,17 @@ +#ifndef IVGUIMATINFO_H +#define IVGUIMATINFO_H + +#include "IVguiMatInfoVar.h" + +class IVguiMatInfo +{ +public: + virtual ~IVguiMatInfo() {} + + virtual IVguiMatInfoVar* FindVarFactory(const char* varName, bool* found) = 0; + + virtual int GetNumAnimationFrames() = 0; + +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/IVguiMatInfoVar.h b/SpyCustom/IVguiMatInfoVar.h new file mode 100644 index 0000000..806b0b2 --- /dev/null +++ b/SpyCustom/IVguiMatInfoVar.h @@ -0,0 +1,15 @@ +#ifndef IVGUIMATINFOVAR_H +#define IVGUIMATINFOVAR_H + + +class IVguiMatInfoVar +{ +public: + virtual ~IVguiMatInfoVar() {} + + virtual int GetIntValue(void) const = 0; + virtual void SetIntValue(int val) = 0; + +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/KeyBindingMap.h b/SpyCustom/KeyBindingMap.h new file mode 100644 index 0000000..1fc0d95 --- /dev/null +++ b/SpyCustom/KeyBindingMap.h @@ -0,0 +1,206 @@ +#ifndef KEYBINDINGMAP_H +#define KEYBINDINGMAP_H +#ifdef _WIN32 +#pragma once +#endif + +#include "utlvector.h" + +namespace vgui +{ + + class Panel; + + enum + { + MODIFIER_SHIFT = (1 << 0), + MODIFIER_CONTROL = (1 << 1), + MODIFIER_ALT = (1 << 2), + }; + + struct BoundKey_t + { + BoundKey_t(); + BoundKey_t(const BoundKey_t& src); + ~BoundKey_t(); + BoundKey_t& operator =(const BoundKey_t& src); + + bool isbuiltin; + char const* bindingname; + int keycode; + int modifiers; + }; + + struct KeyBindingMap_t + { + KeyBindingMap_t(); + KeyBindingMap_t(const KeyBindingMap_t& src); + ~KeyBindingMap_t(); + + char const* bindingname; + ALIGN16 MessageFunc_t func; + char const* helpstring; + char const* docstring; + bool passive; + }; + +#define DECLARE_KEYBINDINGMAP( className ) \ + static void KB_AddToMap \ + ( \ + char const *bindingname, \ + vgui::KeyCode defaultcode, \ + int default_modifiers, \ + vgui::MessageFunc_t function, \ + char const *helpstring, \ + char const *docstring, \ + bool passive \ + ) \ + { \ + vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + \ + vgui::KeyBindingMap_t entry; \ + entry.bindingname = bindingname; \ + \ + entry.func = function; \ + \ + entry.helpstring = helpstring; \ + entry.docstring = docstring; \ + \ + entry.passive = passive; \ + \ + map->entries.AddToTail( entry ); \ + \ + vgui::BoundKey_t kb; \ + kb.isbuiltin = true; \ + kb.bindingname = bindingname; \ + kb.keycode = defaultcode; \ + kb.modifiers = default_modifiers; \ + map->defaultkeys.AddToTail( kb ); \ + map->boundkeys.AddToTail( kb ); \ + } \ + \ + static void KB_ChainToMap( void ) \ + { \ + static bool chained = false; \ + if ( chained ) \ + return; \ + chained = true; \ + vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + map->pfnClassName = &GetPanelClassName; \ + if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ + { \ + map->baseMap = vgui::FindOrAddPanelKeyBindingMap( GetPanelBaseClassName() ); \ + } \ + } \ + \ + static void KB_AddBoundKey \ + ( \ + char const *bindingname, \ + int keycode, \ + int modifiers \ + ) \ + { \ + vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + vgui::BoundKey_t kb; \ + kb.isbuiltin = true; \ + kb.bindingname = bindingname; \ + kb.keycode = keycode; \ + kb.modifiers = modifiers; \ + map->defaultkeys.AddToTail( kb ); \ + map->boundkeys.AddToTail( kb ); \ + } \ + \ + class className##_RegisterKBMap; \ + friend class className##_RegisterKBMap; \ + class className##_RegisterKBMap \ + { \ + public: \ + className##_RegisterKBMap() \ + { \ + className::KB_ChainToMap(); \ + } \ + }; \ + className##_RegisterKBMap m_RegisterClassKB; \ + \ + virtual vgui::PanelKeyBindingMap *GetKBMap() \ + { \ + static vgui::PanelKeyBindingMap *s_pMap = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + return s_pMap; \ + } + +#define _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, passive ) \ + class PanelKBMapFunc_##name; \ + friend class PanelKBMapFunc_##name; \ + class PanelKBMapFunc_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + KB_AddToMap( #name, keycode, modifiers, (vgui::MessageFunc_t)&ThisClass::function, help, doc, passive ); \ + } \ + } \ + PanelKBMapFunc_##name() \ + { \ + PanelKBMapFunc_##name::InitVar(); \ + } \ + }; \ + PanelKBMapFunc_##name m_##name##_register; + +#define _KBBindKeyCommon( name, keycode, modifiers, _classname ) \ + class PanelKBBindFunc_##_classname; \ + friend class PanelKBBindFunc_##_classname; \ + class PanelKBBindFunc_##_classname \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + KB_AddBoundKey( #name, keycode, modifiers ); \ + } \ + } \ + PanelKBBindFunc_##_classname() \ + { \ + PanelKBBindFunc_##_classname::InitVar(); \ + } \ + }; \ + PanelKBBindFunc_##_classname m_##_classname##_bindkey_register; + +#define KEYBINDING_FUNC( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, false ); virtual void function() +#define KEYBINDING_FUNC_NODECLARE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, false ); +#define KEYBINDING_FUNC_PASSIVE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, true ); virtual void function() +#define KEYBINDING_FUNC_PASSIVE_NODECLARE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, true ); + +#define KEYBINDING_ADDBINDING( name, keycode, modifiers ) _KBBindKeyCommon( name, keycode, modifiers, name ); +#define KEYBINDING_ADDBINDING_MULTIPLE( name, keycode, modifiers, _classname ) _KBBindKeyCommon( name, keycode, modifiers, _classname ); + + struct PanelKeyBindingMap + { + PanelKeyBindingMap() + { + baseMap = NULL; + pfnClassName = NULL; + processed = false; + } + + CUtlVector< KeyBindingMap_t > entries; + bool processed; + PanelKeyBindingMap* baseMap; + CUtlVector< BoundKey_t > defaultkeys; + CUtlVector< BoundKey_t > boundkeys; + char const* (*pfnClassName)(void); + }; + + PanelKeyBindingMap* FindPanelKeyBindingMap(char const* className); + PanelKeyBindingMap* FindOrAddPanelKeyBindingMap(char const* className); + +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/KeyCode.h b/SpyCustom/KeyCode.h new file mode 100644 index 0000000..dc23cc4 --- /dev/null +++ b/SpyCustom/KeyCode.h @@ -0,0 +1,15 @@ +#ifndef KEYCODE_H +#define KEYCODE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "ButtonCode.h" + +namespace vgui +{ + typedef ButtonCode_t KeyCode; +} + +#endif \ No newline at end of file diff --git a/SpyCustom/KeyValues.cpp b/SpyCustom/KeyValues.cpp new file mode 100644 index 0000000..053b268 --- /dev/null +++ b/SpyCustom/KeyValues.cpp @@ -0,0 +1,1830 @@ +#include "keyvalues.h" +#include "IKeyValuesSystem.h" + +#include "Interfaces.hpp" + +void V_strncpy(char* pDest, char const* pSrc, int maxLen) +{ + strncpy(pDest, pSrc, maxLen); + if (maxLen > 0) + { + pDest[maxLen - 1] = 0; + } +} + +char* V_strncat(char* pDest, const char* pSrc, size_t destBufferSize, int max_chars_to_copy) +{ + size_t charstocopy = (size_t)0; + + size_t len = strlen(pDest); + size_t srclen = strlen(pSrc); + if (max_chars_to_copy <= COPY_ALL_CHARACTERS) + charstocopy = srclen; + else + charstocopy = (size_t)min(max_chars_to_copy, (int)srclen); + + if (len + charstocopy >= destBufferSize) + charstocopy = destBufferSize - len - 1; + + if ((int)charstocopy <= 0) + return pDest; + + ANALYZE_SUPPRESS(6059); + char* pOut = strncat(pDest, pSrc, charstocopy); + return pOut; +} + + +int _V_strcmp(const char* file, int line, const char* s1, const char* s2) +{ + return strcmp(s1, s2); +} + +int V_strncmp(const char* s1, const char* s2, int count) +{ + while (count > 0) + { + if (*s1 != *s2) + return (unsigned char)*s1 < (unsigned char)*s2 ? -1 : 1; + if (*s1 == '\0') + return 0; + s1++; + s2++; + count--; + } + + return 0; +} + +int V_stricmp(const char* str1, const char* str2) +{ + if (str1 == str2) + { + return 0; + } + const unsigned char* s1 = (const unsigned char*)str1; + const unsigned char* s2 = (const unsigned char*)str2; + for (; *s1; ++s1, ++s2) + { + if (*s1 != *s2) + { + unsigned char c1 = *s1 | 0x20; + unsigned char c2 = *s2 | 0x20; + if (c1 != c2 || (unsigned char)(c1 - 'a') > ('z' - 'a')) + { + if ((c1 | c2) >= 0x80) return stricmp((const char*)s1, (const char*)s2); + if ((unsigned char)(c1 - 'a') > ('z' - 'a')) c1 = *s1; + if ((unsigned char)(c2 - 'a') > ('z' - 'a')) c2 = *s2; + return c1 > c2 ? 1 : -1; + } + } + } + return *s2 ? -1 : 0; +} + +class CLeakTrack +{ +public: + CLeakTrack() + { + } + ~CLeakTrack() + { + if (keys.Count() != 0) + { + Assert(0); + } + } + + struct kve + { + KeyValues* kv; + char name[256]; + }; + + void AddKv(KeyValues* kv, char const* name) + { + kve k; + V_strncpy(k.name, name ? name : "NULL", sizeof(k.name)); + k.kv = kv; + + keys.AddToTail(k); + } + + void RemoveKv(KeyValues* kv) + { + int c = keys.Count(); + for (int i = 0; i < c; i++) + { + if (keys[i].kv == kv) + { + keys.Remove(i); + break; + } + } + } + + CUtlVector< kve > keys; +}; + + +static CLeakTrack track; + +void KeyValues::Init() +{ + m_iKeyName = 0; + m_iKeyNameCaseSensitive1 = 0; + m_iKeyNameCaseSensitive2 = 0; + m_iDataType = TYPE_NONE; + + m_pSub = NULL; + m_pPeer = NULL; + m_pChain = NULL; + + m_sValue = NULL; + m_wsValue = NULL; + m_pValue = NULL; + + m_bHasEscapeSequences = 0; +} + +void KeyValues::SetName(const char* setName) +{ + HKeySymbol hCaseSensitiveKeyName = INVALID_KEY_SYMBOL, hCaseInsensitiveKeyName = INVALID_KEY_SYMBOL; + hCaseSensitiveKeyName = iff.keyValuesSystem->GetSymbolForStringCaseSensitive(hCaseInsensitiveKeyName, setName); + + m_iKeyName = hCaseInsensitiveKeyName; + SPLIT_3_BYTES_INTO_1_AND_2(m_iKeyNameCaseSensitive1, m_iKeyNameCaseSensitive2, hCaseSensitiveKeyName); +} + +KeyValues::KeyValues(const char* setName) +{ + TRACK_KV_ADD(this, setName); + Init(); + SetName(setName); +} + +void* KeyValues::operator new(size_t iAllocSize) +{ + MEM_ALLOC_CREDIT(); + return iff.keyValuesSystem->AllocKeyValuesMemory(iAllocSize); +} + +void KeyValues::operator delete(void* pMem) +{ + iff.keyValuesSystem->FreeKeyValuesMemory((KeyValues*)pMem); +} + +#define TRACK_KV_ADD( ptr, name ) track.AddKv( ptr, name ) +#define TRACK_KV_REMOVE( ptr ) track.RemoveKv( ptr ) + + +KeyValues::~KeyValues() +{ + TRACK_KV_REMOVE(this); + RemoveEverything(); +} + +void KeyValues::RemoveEverything() +{ + KeyValues* dat; + KeyValues* datNext = NULL; + for (dat = m_pSub; dat != NULL; dat = datNext) + { + datNext = dat->m_pPeer; + dat->m_pPeer = NULL; + delete dat; + } + + for (dat = m_pPeer; dat && dat != this; dat = datNext) + { + datNext = dat->m_pPeer; + dat->m_pPeer = NULL; + delete dat; + } + + delete[] m_sValue; + m_sValue = NULL; + delete[] m_wsValue; + m_wsValue = NULL; +} + +char CUtlCharConversion::FindConversion(const char* pString, int* pLength) +{ + for (int i = 0; i < m_nCount; ++i) + { + if (!Q_strcmp(pString, m_pReplacements[(unsigned char)m_pList[i]].m_pReplacementString)) + { + *pLength = m_pReplacements[(unsigned char)m_pList[i]].m_nLength; + return m_pList[i]; + } + } + + *pLength = 0; + return '\0'; +} + +CUtlCharConversion::CUtlCharConversion(char nEscapeChar, const char* pDelimiter, int nCount, ConversionArray_t* pArray) +{ + m_nEscapeChar = nEscapeChar; + m_pDelimiter = pDelimiter; + m_nCount = nCount; + m_nDelimiterLength = Q_strlen(pDelimiter); + m_nMaxConversionLength = 0; + + memset(m_pReplacements, 0, sizeof(m_pReplacements)); + + for (int i = 0; i < nCount; ++i) + { + m_pList[i] = pArray[i].m_nActualChar; + ConversionInfo_t& info = m_pReplacements[(unsigned char)m_pList[i]]; + Assert(info.m_pReplacementString == 0); + info.m_pReplacementString = pArray[i].m_pReplacementString; + info.m_nLength = Q_strlen(info.m_pReplacementString); + if (info.m_nLength > m_nMaxConversionLength) + { + m_nMaxConversionLength = info.m_nLength; + } + } +} + +bool CUtlBuffer::OnGetOverflow(int nSize) +{ + return (this->*m_GetOverflowFunc)(nSize); +} + + +class CUtlCStringConversion : public CUtlCharConversion +{ +public: + CUtlCStringConversion(char nEscapeChar, const char* pDelimiter, int nCount, ConversionArray_t* pArray); + + virtual char FindConversion(const char* pString, int* pLength); + +private: + char m_pConversion[256]; +}; + +CUtlCStringConversion::CUtlCStringConversion(char nEscapeChar, const char* pDelimiter, int nCount, ConversionArray_t* pArray) : + CUtlCharConversion(nEscapeChar, pDelimiter, nCount, pArray) +{ + memset(m_pConversion, 0x0, sizeof(m_pConversion)); + for (int i = 0; i < nCount; ++i) + { + m_pConversion[(unsigned char)pArray[i].m_pReplacementString[0]] = pArray[i].m_nActualChar; + } +} + +char CUtlCStringConversion::FindConversion(const char* pString, int* pLength) +{ + char c = m_pConversion[(unsigned char)pString[0]]; + *pLength = (c != '\0') ? 1 : 0; + return c; +} + +bool CUtlBuffer::OnPutOverflow(int nSize) +{ + return (this->*m_PutOverflowFunc)(nSize); +} + +void CUtlBuffer::SetOverflowFuncs(UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc) +{ + m_GetOverflowFunc = getFunc; + m_PutOverflowFunc = putFunc; +} + +void CUtlBuffer::Get(void* pMem, int size) +{ + if (size > 0 && CheckGet(size)) + { + int Index = m_Get - m_nOffset; + Assert(m_Memory.IsIdxValid(Index) && m_Memory.IsIdxValid(Index + size - 1)); + + memcpy(pMem, &m_Memory[Index], size); + m_Get += size; + } +} + +void CUtlBuffer::GetString(char* pString, int nMaxChars) +{ + if (!IsValid()) + { + *pString = 0; + return; + } + + if (nMaxChars == 0) + { + nMaxChars = INT_MAX; + } + + int nLen = PeekStringLength(); + + if (IsText()) + { + EatWhiteSpace(); + } + + if (nLen == 0) + { + *pString = 0; + m_Error |= GET_OVERFLOW; + return; + } + + if (nLen <= nMaxChars) + { + Get(pString, nLen - 1); + pString[nLen - 1] = 0; + } + else + { + Get(pString, nMaxChars - 1); + pString[nMaxChars - 1] = 0; + SeekGet(SEEK_CURRENT, nLen - 1 - nMaxChars); + } + + if (!IsText()) + { + VerifyEquals(GetChar(), 0); + } +} + + +bool CUtlBuffer::CheckPut(int nSize) +{ + if ((m_Error & PUT_OVERFLOW) || IsReadOnly()) + return false; + + if ((m_Put < m_nOffset) || (m_Memory.NumAllocated() < m_Put - m_nOffset + nSize)) + { + if (!OnPutOverflow(nSize)) + { + m_Error |= PUT_OVERFLOW; + return false; + } + } + return true; +} + +char CUtlCharConversion::GetEscapeChar() const +{ + return m_nEscapeChar; +} + +int CUtlCharConversion::MaxConversionLength() const +{ + return m_nMaxConversionLength; +} + + +char CUtlBuffer::GetDelimitedCharInternal(CUtlCharConversion* pConv) +{ + char c = GetChar(); + if (c == pConv->GetEscapeChar()) + { + int nLength = pConv->MaxConversionLength(); + if (!CheckArbitraryPeekGet(0, nLength)) + return '\0'; + + c = pConv->FindConversion((const char*)PeekGet(), &nLength); + SeekGet(SEEK_CURRENT, nLength); + } + + return c; +} + +bool CUtlBuffer::PutOverflow(int nSize) +{ + MEM_ALLOC_CREDIT(); + + if (m_Memory.IsExternallyAllocated()) + { + if (!IsGrowable()) + return false; + + m_Memory.ConvertToGrowableMemory(0); + } + + while (Size() < m_Put - m_nOffset + nSize) + { + m_Memory.Grow(); + } + + return true; +} + +bool CUtlBuffer::GetOverflow(int nSize) +{ + return false; +} + +bool CUtlBuffer::PeekStringMatch(int nOffset, const char* pString, int nLen) +{ + if (!CheckPeekGet(nOffset, nLen)) + return false; + return !Q_strncmp((const char*)PeekGet(nOffset), pString, nLen); +} + +int CUtlBuffer::PeekWhiteSpace(int nOffset) +{ + if (!IsText() || !IsValid()) + return 0; + + while (CheckPeekGet(nOffset, sizeof(char))) + { + if (!isspace(*(unsigned char*)PeekGet(nOffset))) + break; + nOffset += sizeof(char); + } + + return nOffset; +} + +bool CUtlBuffer::CheckArbitraryPeekGet(int nOffset, int& nIncrement) +{ + if (TellGet() + nOffset >= TellMaxPut()) + { + nIncrement = 0; + return false; + } + + if (TellGet() + nOffset + nIncrement > TellMaxPut()) + { + nIncrement = TellMaxPut() - TellGet() - nOffset; + } + + CheckPeekGet(nOffset, nIncrement); + int nMaxGet = TellMaxPut() - TellGet(); + if (nMaxGet < nIncrement) + { + nIncrement = nMaxGet; + } + return (nIncrement != 0); +} + + + +int CUtlBuffer::PeekStringLength() +{ + if (!IsValid()) + return 0; + + int nOffset = 0; + if (IsText()) + { + nOffset = PeekWhiteSpace(nOffset); + } + + int nStartingOffset = nOffset; + + do + { + int nPeekAmount = 128; + + if (!CheckArbitraryPeekGet(nOffset, nPeekAmount)) + { + if (nOffset == nStartingOffset) + return 0; + return nOffset - nStartingOffset + 1; + } + + const char* pTest = (const char*)PeekGet(nOffset); + + if (!IsText()) + { + for (int i = 0; i < nPeekAmount; ++i) + { + if (pTest[i] == 0) + return (i + nOffset - nStartingOffset + 1); + } + } + else + { + for (int i = 0; i < nPeekAmount; ++i) + { + if (isspace((unsigned char)pTest[i]) || (pTest[i] == 0)) + return (i + nOffset - nStartingOffset + 1); + } + } + + nOffset += nPeekAmount; + + } while (true); +} + + +class CUtlNoEscConversion : public CUtlCharConversion +{ +public: + CUtlNoEscConversion(char nEscapeChar, const char* pDelimiter, int nCount, ConversionArray_t* pArray) : + CUtlCharConversion(nEscapeChar, pDelimiter, nCount, pArray) {} + + virtual char FindConversion(const char* pString, int* pLength) { *pLength = 0; return 0; } +}; + +BEGIN_CUSTOM_CHAR_CONVERSION(CUtlCStringConversion, s_StringCharConversion, (char*)"\"", '\\') + { '\n', (char*)"n" }, + { '\t', (char*)"t" }, + { '\v', (char*)"v" }, + { '\b', (char*)"b" }, + { '\r', (char*)"r" }, + { '\f', (char*)"f" }, + { '\a', (char*)"a" }, + { '\\', (char*)"\\" }, + { '\?', (char*)"\?" }, + { '\'', (char*)"\'" }, + { '\"', (char*)"\"" }, +END_CUSTOM_CHAR_CONVERSION(CUtlCStringConversion, s_StringCharConversion, (char*)"\"", '\\') + +CUtlCharConversion* GetCStringCharConversion() +{ + return &s_StringCharConversion; +} + +BEGIN_CUSTOM_CHAR_CONVERSION(CUtlNoEscConversion, s_NoEscConversion, (char*)"\"", 0x7F) + { + 0x7F, (char*)"" + }, +END_CUSTOM_CHAR_CONVERSION(CUtlNoEscConversion, s_NoEscConversion, (char*)"\"", 0x7F) + +CUtlCharConversion* GetNoEscCharConversion() +{ + return &s_NoEscConversion; +} + + +const char* CUtlCharConversion::GetDelimiter() const +{ + return m_pDelimiter; +} + +int CUtlCharConversion::GetDelimiterLength() const +{ + return m_nDelimiterLength; +} + +void CUtlBuffer::AddNullTermination(int m) +{ + if (m_Put > m_nMaxPut) + { + if (!IsReadOnly() && ((m_Error & PUT_OVERFLOW) == 0)) + { + if (CheckPut(1)) + { + int Index = m_Put - m_nOffset; + Assert(m_Memory.IsIdxValid(Index)); + if (Index >= 0) + { + m_Memory[Index] = 0; + } + } + else + { + m_Error &= ~PUT_OVERFLOW; + } + } + m_nMaxPut = m_Put; + } +} + +CUtlBuffer::CUtlBuffer(int growSize, int initSize, int nFlags) : + m_Error(0) +{ + MEM_ALLOC_CREDIT(); + m_Memory.Init(growSize, initSize); + m_Get = 0; + m_Put = 0; + m_nTab = 0; + m_nOffset = 0; + m_Flags = nFlags; + if ((initSize != 0) && !IsReadOnly()) + { + m_nMaxPut = -1; + AddNullTermination(0); + } + else + { + m_nMaxPut = 0; + } + SetOverflowFuncs(&CUtlBuffer::GetOverflow, &CUtlBuffer::PutOverflow); +} + +CUtlBuffer::CUtlBuffer(const void* pBuffer, int nSize, int nFlags) : + m_Memory((unsigned char*)pBuffer, nSize), m_Error(0) +{ + Assert(nSize != 0); + + m_Get = 0; + m_Put = 0; + m_nTab = 0; + m_nOffset = 0; + m_Flags = nFlags; + if (IsReadOnly()) + { + m_nMaxPut = nSize; + } + else + { + m_nMaxPut = -1; + AddNullTermination(0); + } + SetOverflowFuncs(&CUtlBuffer::GetOverflow, &CUtlBuffer::PutOverflow); +} + + +void CUtlBuffer::GetDelimitedString(CUtlCharConversion* pConv, char* pString, int nMaxChars) +{ + if (!IsText() || !pConv) + { + GetString(pString, nMaxChars); + return; + } + + if (!IsValid()) + { + *pString = 0; + return; + } + + if (nMaxChars == 0) + { + nMaxChars = INT_MAX; + } + + EatWhiteSpace(); + if (!PeekStringMatch(0, pConv->GetDelimiter(), pConv->GetDelimiterLength())) + return; + + SeekGet(SEEK_CURRENT, pConv->GetDelimiterLength()); + + int nRead = 0; + while (IsValid()) + { + if (PeekStringMatch(0, pConv->GetDelimiter(), pConv->GetDelimiterLength())) + { + SeekGet(SEEK_CURRENT, pConv->GetDelimiterLength()); + break; + } + + char c = GetDelimitedCharInternal(pConv); + + if (nRead < nMaxChars) + { + pString[nRead] = c; + ++nRead; + } + } + + if (nRead >= nMaxChars) + { + nRead = nMaxChars - 1; + } + pString[nRead] = '\0'; +} + +void CUtlBuffer::EatWhiteSpace() +{ + if (IsText() && IsValid()) + { + while (CheckGet(sizeof(char))) + { + if (!isspace(*(const unsigned char*)PeekGet())) + break; + m_Get += sizeof(char); + } + } +} +bool CUtlBuffer::EatCPPComment() +{ + if (IsText() && IsValid()) + { + const char* pPeek = (const char*)PeekGet(2 * sizeof(char), 0); + if (!pPeek || (pPeek[0] != '/') || (pPeek[1] != '/')) + return false; + + m_Get += 2; + + for (char c = GetChar(); IsValid(); c = GetChar()) + { + if (c == '\n') + break; + } + return true; + } + return false; +} + +bool CUtlBuffer::CheckGet(int nSize) +{ + if (m_Error & GET_OVERFLOW) + return false; + + if (TellMaxPut() < m_Get + nSize) + { + m_Error |= GET_OVERFLOW; + return false; + } + + if ((m_Get < m_nOffset) || (m_Memory.NumAllocated() < m_Get - m_nOffset + nSize)) + { + if (!OnGetOverflow(nSize)) + { + m_Error |= GET_OVERFLOW; + return false; + } + } + + return true; +} + + +bool CUtlBuffer::CheckPeekGet(int nOffset, int nSize) +{ + if (m_Error & GET_OVERFLOW) + return false; + + bool bOk = CheckGet(nOffset + nSize); + m_Error &= ~GET_OVERFLOW; + return bOk; +} + +const void* CUtlBuffer::PeekGet(int nMaxSize, int nOffset) +{ + if (!CheckPeekGet(nOffset, nMaxSize)) + return NULL; + + int Index = m_Get + nOffset - m_nOffset; + Assert(m_Memory.IsIdxValid(Index) && m_Memory.IsIdxValid(Index + nMaxSize - 1)); + + return &m_Memory[Index]; +} + +void CUtlBuffer::SeekGet(SeekType_t type, int offset) +{ + switch (type) + { + case SEEK_HEAD: + m_Get = offset; + break; + + case SEEK_CURRENT: + m_Get += offset; + break; + + case SEEK_TAIL: + m_Get = m_nMaxPut - offset; + break; + } + + if (m_Get > m_nMaxPut) + { + m_Error |= GET_OVERFLOW; + } + else + { + m_Error &= ~GET_OVERFLOW; + if (m_Get < m_nOffset || m_Get >= m_nOffset + Size()) + { + OnGetOverflow(-1); + } + } +} + + + +void KeyValues::Clear(void) +{ + delete m_pSub; + m_pSub = NULL; + m_iDataType = TYPE_NONE; +} + +void KeyValues::deleteThis() +{ + delete this; +} + + +KeyValues* KeyValues::CreateKey(const char* keyName) +{ + KeyValues* dat = new KeyValues(keyName); + dat->UsesEscapeSequences(m_bHasEscapeSequences != 0); + AddSubKey(dat); + return dat; +} + + +void KeyValues::AddSubKey(KeyValues* pSubkey) +{ + Assert(pSubkey->m_pPeer == NULL); + + if (m_pSub == NULL) + { + m_pSub = pSubkey; + } + else + { + KeyValues* pTempDat = m_pSub; + while (pTempDat->GetNextKey() != NULL) + { + pTempDat = pTempDat->GetNextKey(); + } + + pTempDat->SetNextKey(pSubkey); + } +} + + +void KeyValues::RemoveSubKey(KeyValues* subKey) +{ + if (!subKey) + return; + + if (m_pSub == subKey) + { + m_pSub = subKey->m_pPeer; + } + else + { + KeyValues* kv = m_pSub; + while (kv->m_pPeer) + { + if (kv->m_pPeer == subKey) + { + kv->m_pPeer = subKey->m_pPeer; + break; + } + + kv = kv->m_pPeer; + } + } + + subKey->m_pPeer = NULL; +} + +static char* s_LastFileLoadingFrom = ( char*)"unknown"; + + +void KeyValues::UsesEscapeSequences(bool state) +{ + m_bHasEscapeSequences = state; +} + + +int V_snprintf(char* pDest, int maxLen, char const* pFormat, ...) +{ + Assert(maxLen >= 0); + AssertValidWritePtr(pDest, maxLen); + va_list marker; + + va_start(marker, pFormat); +#ifdef _WIN32 + int len = _vsnprintf(pDest, maxLen, pFormat, marker); +#elif defined _LINUX || defined __APPLE__ + int len = vsnprintf(pDest, maxLen, pFormat, marker); +#else +#error "define vsnprintf type." +#endif + va_end(marker); + + if (len < 0) + { + len = maxLen; + pDest[maxLen - 1] = 0; + } + + return len; +} + + +int V_vsnprintf(char* pDest, int maxLen, char const* pFormat, va_list params) +{ + Assert(maxLen > 0); + AssertValidWritePtr(pDest, maxLen); + int len = _vsnprintf(pDest, maxLen, pFormat, params); + + if (len < 0) + { + len = maxLen; + pDest[maxLen - 1] = 0; + } + + return len; +} + +KeyValues* KeyValues::FindKey(int keySymbol) const +{ + for (KeyValues* dat = m_pSub; dat != NULL; dat = dat->m_pPeer) + { + if (dat->m_iKeyName == keySymbol) + return dat; + } + + return NULL; +} + + +int (*KeyValues::s_pfGetSymbolForString)(const char* name, bool bCreate) = &KeyValues::GetSymbolForStringClassic; +const char* (*KeyValues::s_pfGetStringForSymbol)(int symbol) = &KeyValues::GetStringForSymbolClassic; +CKeyValuesGrowableStringTable* KeyValues::s_pGrowableStringTable = NULL; + +int KeyValues::GetSymbolForStringClassic(const char* name, bool bCreate) +{ + return iff.keyValuesSystem->GetSymbolForString(name, bCreate); +} + +const char* KeyValues::GetStringForSymbolClassic(int symbol) +{ + return iff.keyValuesSystem->GetStringForSymbol(symbol); +} + +KeyValues* KeyValues::GetNextTrueSubKey() +{ + KeyValues* pRet = m_pPeer; + while (pRet && pRet->m_iDataType != TYPE_NONE) + pRet = pRet->m_pPeer; + + return pRet; +} + + +KeyValues* KeyValues::FindKey(const char* keyName, bool bCreate) +{ + if (!keyName || !keyName[0]) + return this; + + char szBuf[256]; + const char* subStr = strchr(keyName, '/'); + const char* searchStr = keyName; + + if (subStr) + { + int size = subStr - keyName; + Q_memcpy(szBuf, keyName, size); + szBuf[size] = 0; + searchStr = szBuf; + } + + HKeySymbol iSearchStr = s_pfGetSymbolForString(searchStr, bCreate); + + if (iSearchStr == INVALID_KEY_SYMBOL) + { + return NULL; + } + + KeyValues* lastItem = NULL; + KeyValues* dat; + for (dat = m_pSub; dat != NULL; dat = dat->m_pPeer) + { + lastItem = dat; + + if (dat->m_iKeyName == iSearchStr) + { + break; + } + } + + if (!dat && m_pChain) + { + dat = m_pChain->FindKey(keyName, false); + } + + if (!dat) + { + if (bCreate) + { + dat = new KeyValues(searchStr); + dat->UsesEscapeSequences(m_bHasEscapeSequences != 0); + if (lastItem) + { + lastItem->m_pPeer = dat; + } + else + { + m_pSub = dat; + } + dat->m_pPeer = NULL; + + m_iDataType = TYPE_NONE; + } + else + { + return NULL; + } + } + + if (subStr) + { + return dat->FindKey(subStr + 1, bCreate); + } + + return dat; +} + +void KeyValues::SetString(const char* keyName, const char* value) +{ + KeyValues* dat = FindKey(keyName, true); + + if (dat) + { + if (dat->m_iDataType == TYPE_STRING && dat->m_sValue == value) + { + return; + } + + delete[] dat->m_sValue; + delete[] dat->m_wsValue; + dat->m_wsValue = NULL; + + if (!value) + { + value = ""; + } + + int len = Q_strlen(value); + dat->m_sValue = new char[len + 1]; + Q_memcpy(dat->m_sValue, value, len + 1); + + dat->m_iDataType = TYPE_STRING; + } +} + + +const char* KeyValues::GetString(const char* keyName, const char* defaultValue) +{ + KeyValues* dat = FindKey(keyName, false); + if (dat) + { + char buf[64]; + switch (dat->m_iDataType) + { + case TYPE_FLOAT: + Q_snprintf(buf, sizeof(buf), "%f", dat->m_flValue); + SetString(keyName, buf); + break; + case TYPE_INT: + case TYPE_PTR: + Q_snprintf(buf, sizeof(buf), "%d", dat->m_iValue); + SetString(keyName, buf); + break; + case TYPE_UINT64: + Q_snprintf(buf, sizeof(buf), "%lld", *((uint64*)(dat->m_sValue))); + SetString(keyName, buf); + break; + + case TYPE_WSTRING: + { + char wideBuf[512]; + int result = Q_UnicodeToUTF8(dat->m_wsValue, wideBuf, 512); + if (result) + { + SetString(keyName, wideBuf); + } + else + { + return defaultValue; + } + break; + } + case TYPE_STRING: + break; + default: + return defaultValue; + }; + + return dat->m_sValue; + } + return defaultValue; +} + + +const char* KeyValues::GetName(void) const +{ + return iff.keyValuesSystem->GetStringForSymbol(m_iKeyName); +} + +int KeyValues::GetNameSymbol() const +{ + return m_iKeyName; +} + +bool KeyValues::LoadFromFile(IBaseFileSystem* filesystem, const char* resourceName, const char* pathID) +{ + Assert(filesystem); + Assert(IsX360() || (IsPC() && _heapchk() == _HEAPOK)); + + FileHandle_t f = iff.g_pFullFileSystem->Open(resourceName, "rb", pathID); + if (!f) + return false; + + s_LastFileLoadingFrom = (char*)resourceName; + + int fileSize = filesystem->Size(f); + unsigned bufSize = ((IFileSystem*)filesystem)->GetOptimalReadSize(f, fileSize + 1); + + char* buffer = (char*)((IFileSystem*)filesystem)->AllocOptimalReadBuffer(f, bufSize); + Assert(buffer); + + bool bRetOK = (((IFileSystem*)filesystem)->ReadEx(buffer, bufSize, fileSize, f) != 0); + + filesystem->Close(f); + + if (bRetOK) + { + buffer[fileSize] = 0; + bRetOK = LoadFromBuffer(resourceName, buffer, filesystem); + } + + ((IFileSystem*)filesystem)->FreeOptimalReadBuffer(buffer); + + return bRetOK; +} + +void KeyValues::SetNextKey(KeyValues* pDat) +{ + m_pPeer = pDat; +} + +void KeyValues::CopySubkeys(KeyValues* pParent) const +{ + KeyValues* pPrev = NULL; + for (KeyValues* sub = m_pSub; sub != NULL; sub = sub->m_pPeer) + { + KeyValues* dat = sub->MakeCopy(); + + if (pPrev) + pPrev->m_pPeer = dat; + else + pParent->m_pSub = dat; + dat->m_pPeer = NULL; + pPrev = dat; + } +} + +KeyValues* KeyValues::MakeCopy(void) const +{ + KeyValues* newKeyValue = new KeyValues(GetName()); + + newKeyValue->m_iDataType = m_iDataType; + switch (m_iDataType) + { + case TYPE_STRING: + { + if (m_sValue) + { + int len = Q_strlen(m_sValue); + Assert(!newKeyValue->m_sValue); + newKeyValue->m_sValue = new char[len + 1]; + Q_memcpy(newKeyValue->m_sValue, m_sValue, len + 1); + } + } + break; + case TYPE_WSTRING: + { + if (m_wsValue) + { + int len = wcslen(m_wsValue); + newKeyValue->m_wsValue = new wchar_t[len + 1]; + Q_memcpy(newKeyValue->m_wsValue, m_wsValue, (len + 1) * sizeof(wchar_t)); + } + } + break; + + case TYPE_INT: + newKeyValue->m_iValue = m_iValue; + break; + + case TYPE_FLOAT: + newKeyValue->m_flValue = m_flValue; + break; + + case TYPE_PTR: + newKeyValue->m_pValue = m_pValue; + break; + + case TYPE_COLOR: + newKeyValue->m_Color[0] = m_Color[0]; + newKeyValue->m_Color[1] = m_Color[1]; + newKeyValue->m_Color[2] = m_Color[2]; + newKeyValue->m_Color[3] = m_Color[3]; + break; + + case TYPE_UINT64: + newKeyValue->m_sValue = new char[sizeof(uint64)]; + Q_memcpy(newKeyValue->m_sValue, m_sValue, sizeof(uint64)); + break; + }; + + CopySubkeys(newKeyValue); + return newKeyValue; +} + + + +const int MAX_ERROR_STACK = 64; +class CKeyValuesErrorStack +{ +public: + CKeyValuesErrorStack() : m_pFilename("NULL"), m_errorIndex(0), m_maxErrorIndex(0) {} + + void SetFilename(const char* pFilename) + { + m_pFilename = pFilename; + m_maxErrorIndex = 0; + } + + int Push(int symName) + { + if (m_errorIndex < MAX_ERROR_STACK) + { + m_errorStack[m_errorIndex] = symName; + } + m_errorIndex++; + m_maxErrorIndex = max(m_maxErrorIndex, (m_errorIndex - 1)); + return m_errorIndex - 1; + } + + void Pop() + { + m_errorIndex--; + Assert(m_errorIndex >= 0); + } + + void Reset(int stackLevel, int symName) + { + Assert(stackLevel >= 0 && stackLevel < m_errorIndex); + m_errorStack[stackLevel] = symName; + } + + void ReportError(const char* pError) + { + printf("KeyValues Error: %s in file %s\n", pError, m_pFilename); + for (int i = 0; i < m_maxErrorIndex; i++) + { + if (m_errorStack[i] != INVALID_KEY_SYMBOL) + { + if (i < m_errorIndex) + { + printf("%s, ", iff.keyValuesSystem->GetStringForSymbol(m_errorStack[i])); + } + else + { + printf("(*%s*), ", iff.keyValuesSystem->GetStringForSymbol(m_errorStack[i])); + } + } + } + printf("\n"); + } + +private: + int m_errorStack[MAX_ERROR_STACK]; + const char* m_pFilename; + int m_errorIndex; + int m_maxErrorIndex; +} g_KeyValuesErrorStack; + + +class CKeyErrorContext +{ +public: + CKeyErrorContext(KeyValues* pKv) + { + Init(pKv->GetNameSymbol()); + } + + ~CKeyErrorContext() + { + g_KeyValuesErrorStack.Pop(); + } + CKeyErrorContext(int symName) + { + Init(symName); + } + void Reset(int symName) + { + g_KeyValuesErrorStack.Reset(m_stackLevel, symName); + } +private: + void Init(int symName) + { + m_stackLevel = g_KeyValuesErrorStack.Push(symName); + } + + int m_stackLevel; +}; + + +void KeyValues::RecursiveLoadFromBuffer(char const* resourceName, CUtlBuffer& buf) +{ + CKeyErrorContext errorReport(this); + bool wasQuoted; + bool wasConditional; + CKeyErrorContext errorKey(INVALID_KEY_SYMBOL); + while (1) + { + bool bAccepted = true; + + const char* name = ReadToken(buf, wasQuoted, wasConditional); + + if (!name) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got EOF instead of keyname"); + break; + } + + if (!*name) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got empty keyname"); + break; + } + + if (*name == '}' && !wasQuoted) + break; + + KeyValues* dat = CreateKey(name); + + errorKey.Reset(dat->GetNameSymbol()); + + const char* value = ReadToken(buf, wasQuoted, wasConditional); + + if (wasConditional && value) + { + bAccepted = EvaluateConditional(value); + + value = ReadToken(buf, wasQuoted, wasConditional); + } + + if (!value) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got NULL key"); + break; + } + + if (*value == '}' && !wasQuoted) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got } in key"); + break; + } + + if (*value == '{' && !wasQuoted) + { + errorKey.Reset(INVALID_KEY_SYMBOL); + dat->RecursiveLoadFromBuffer(resourceName, buf); + } + else + { + if (wasConditional) + { + g_KeyValuesErrorStack.ReportError("RecursiveLoadFromBuffer: got conditional between key and value"); + break; + } + + if (dat->m_sValue) + { + delete[] dat->m_sValue; + dat->m_sValue = NULL; + } + + int len = Q_strlen(value); + + char* pIEnd; + char* pFEnd; + const char* pSEnd = value + len; + + int ival = strtol(value, &pIEnd, 10); + float fval = (float)strtod(value, &pFEnd); + + if (*value == 0) + { + dat->m_iDataType = TYPE_STRING; + } + else if ((18 == len) && (value[0] == '0') && (value[1] == 'x')) + { + int64 retVal = 0; + for (int i = 2; i < 2 + 16; i++) + { + char digit = value[i]; + if (digit >= 'a') + digit -= 'a' - ('9' + 1); + else + if (digit >= 'A') + digit -= 'A' - ('9' + 1); + retVal = (retVal * 16) + (digit - '0'); + } + dat->m_sValue = new char[sizeof(uint64)]; + *((uint64*)dat->m_sValue) = retVal; + dat->m_iDataType = TYPE_UINT64; + } + else if ((pFEnd > pIEnd) && (pFEnd == pSEnd)) + { + dat->m_flValue = fval; + dat->m_iDataType = TYPE_FLOAT; + } + else if (pIEnd == pSEnd) + { + dat->m_iValue = ival; + dat->m_iDataType = TYPE_INT; + } + else + { + dat->m_iDataType = TYPE_STRING; + } + + if (dat->m_iDataType == TYPE_STRING) + { + dat->m_sValue = new char[len + 1]; + Q_memcpy(dat->m_sValue, value, len + 1); + } + + int prevPos = buf.TellGet(); + const char* peek = ReadToken(buf, wasQuoted, wasConditional); + if (wasConditional) + { + bAccepted = EvaluateConditional(peek); + } + else + { + buf.SeekGet(CUtlBuffer::SEEK_HEAD, prevPos); + } + } + + if (!bAccepted) + { + this->RemoveSubKey(dat); + dat->deleteThis(); + dat = NULL; + } + } +} + + +void KeyValues::AppendIncludedKeys(CUtlVector< KeyValues* >& includedKeys) +{ + int includeCount = includedKeys.Count(); + int i; + for (i = 0; i < includeCount; i++) + { + KeyValues* kv = includedKeys[i]; + Assert(kv); + + KeyValues* insertSpot = this; + while (insertSpot->GetNextKey()) + { + insertSpot = insertSpot->GetNextKey(); + } + + insertSpot->SetNextKey(kv); + } +} + +void KeyValues::RecursiveMergeKeyValues(KeyValues* baseKV) +{ + for (KeyValues* baseChild = baseKV->m_pSub; baseChild != NULL; baseChild = baseChild->m_pPeer) + { + bool bFoundMatch = false; + + for (KeyValues* newChild = m_pSub; newChild != NULL; newChild = newChild->m_pPeer) + { + if (!Q_strcmp(baseChild->GetName(), newChild->GetName())) + { + newChild->RecursiveMergeKeyValues(baseChild); + bFoundMatch = true; + break; + } + } + + if (!bFoundMatch) + { + KeyValues* dat = baseChild->MakeCopy(); + Assert(dat); + AddSubKey(dat); + } + } +} + +bool KeyValues::EvaluateConditional(const char* str) +{ + bool bResult = false; + bool bXboxUI = IsX360(); + + if (bXboxUI) + { + bResult = !Q_stricmp("[$X360]", str); + } + else + { + bResult = !Q_stricmp("[$WIN32]", str); + } + + return bResult; +} + +void KeyValues::MergeBaseKeys(CUtlVector< KeyValues* >& baseKeys) +{ + int includeCount = baseKeys.Count(); + int i; + for (i = 0; i < includeCount; i++) + { + KeyValues* kv = baseKeys[i]; + Assert(kv); + + RecursiveMergeKeyValues(kv); + } +} + + +void KeyValues::ParseIncludedKeys(char const* resourceName, const char* filetoinclude, + IBaseFileSystem* pFileSystem, const char* pPathID, CUtlVector< KeyValues* >& includedKeys) +{ + Assert(resourceName); + Assert(filetoinclude); + Assert(pFileSystem); + if (!pFileSystem) + { + return; + } + char fullpath[512]; + Q_strncpy(fullpath, resourceName, sizeof(fullpath)); + bool done = false; + int len = Q_strlen(fullpath); + while (!done) + { + if (len <= 0) + { + break; + } + + if (fullpath[len - 1] == '\\' || + fullpath[len - 1] == '/') + { + break; + } + + fullpath[len - 1] = 0; + --len; + } + + Q_strncat(fullpath, filetoinclude, sizeof(fullpath), COPY_ALL_CHARACTERS); + + KeyValues* newKV = new KeyValues(fullpath); + + newKV->UsesEscapeSequences(m_bHasEscapeSequences != 0); + + if (newKV->LoadFromFile(pFileSystem, fullpath, pPathID)) + { + includedKeys.AddToTail(newKV); + } + else + { + printf("KeyValues::ParseIncludedKeys: Couldn't load included keyvalue file %s\n", fullpath); + newKV->deleteThis(); + } + +} + + + + + + + int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes) + { + AssertValidReadPtr(pUnicode); + + if (cubDestSizeInBytes > 0) + { + pUTF8[0] = 0; + } + +#ifdef _WIN32 + int cchResult = WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL); +#elif POSIX + int cchResult = 0; + if (pUnicode && pUTF8) + cchResult = wcstombs(pUTF8, pUnicode, cubDestSizeInBytes) + 1; +#endif + + if (cubDestSizeInBytes > 0) + { + pUTF8[cubDestSizeInBytes - 1] = 0; + } + + return cchResult; + } + + + +#define KEYVALUES_TOKEN_SIZE 1024 +static char s_pTokenBuf[KEYVALUES_TOKEN_SIZE]; + +#pragma warning (disable:4706) +const char* KeyValues::ReadToken(CUtlBuffer& buf, bool& wasQuoted, bool& wasConditional) +{ + wasQuoted = false; + wasConditional = false; + + if (!buf.IsValid()) + return NULL; + + while (true) + { + buf.EatWhiteSpace(); + if (!buf.IsValid()) + return NULL; + + if (!buf.EatCPPComment()) + break; + } + + const char* c = (const char*)buf.PeekGet(sizeof(char), 0); + if (!c) + return NULL; + + if (*c == '\"') + { + wasQuoted = true; + buf.GetDelimitedString(m_bHasEscapeSequences ? GetCStringCharConversion() : GetNoEscCharConversion(), + s_pTokenBuf, KEYVALUES_TOKEN_SIZE); + return s_pTokenBuf; + } + + if (*c == '{' || *c == '}') + { + s_pTokenBuf[0] = *c; + s_pTokenBuf[1] = 0; + buf.SeekGet(CUtlBuffer::SEEK_CURRENT, 1); + return s_pTokenBuf; + } + + bool bReportedError = false; + bool bConditionalStart = false; + int nCount = 0; + while (c = (const char*)buf.PeekGet(sizeof(char), 0)) + { + if (*c == 0) + break; + + if (*c == '"' || *c == '{' || *c == '}') + break; + + if (*c == '[') + bConditionalStart = true; + + if (*c == ']' && bConditionalStart) + { + wasConditional = true; + } + + if (isspace(*c)) + break; + + if (nCount < (KEYVALUES_TOKEN_SIZE - 1)) + { + s_pTokenBuf[nCount++] = *c; + } + else if (!bReportedError) + { + bReportedError = true; + g_KeyValuesErrorStack.ReportError(" ReadToken overflow"); + } + + buf.SeekGet(CUtlBuffer::SEEK_CURRENT, 1); + } + s_pTokenBuf[nCount] = 0; + return s_pTokenBuf; +} +#pragma warning (default:4706) + + +bool KeyValues::LoadFromBuffer(char const* resourceName, CUtlBuffer& buf, IBaseFileSystem* pFileSystem, const char* pPathID) +{ + KeyValues* pPreviousKey = NULL; + KeyValues* pCurrentKey = this; + CUtlVector< KeyValues* > includedKeys; + CUtlVector< KeyValues* > baseKeys; + bool wasQuoted; + bool wasConditional; + g_KeyValuesErrorStack.SetFilename(resourceName); + do + { + bool bAccepted = true; + + const char* s = ReadToken(buf, wasQuoted, wasConditional); + if (!buf.IsValid() || !s || *s == 0) + break; + + if (!Q_stricmp(s, "#include")) + { + s = ReadToken(buf, wasQuoted, wasConditional); + if (!s || *s == 0) + { + g_KeyValuesErrorStack.ReportError("#include is NULL "); + } + else + { + ParseIncludedKeys(resourceName, s, pFileSystem, pPathID, includedKeys); + } + + continue; + } + else if (!Q_stricmp(s, "#base")) + { + s = ReadToken(buf, wasQuoted, wasConditional); + if (!s || *s == 0) + { + g_KeyValuesErrorStack.ReportError("#base is NULL "); + } + else + { + ParseIncludedKeys(resourceName, s, pFileSystem, pPathID, baseKeys); + } + + continue; + } + + if (!pCurrentKey) + { + pCurrentKey = new KeyValues(s); + Assert(pCurrentKey); + + pCurrentKey->UsesEscapeSequences(m_bHasEscapeSequences != 0); + + if (pPreviousKey) + { + pPreviousKey->SetNextKey(pCurrentKey); + } + } + else + { + pCurrentKey->SetName(s); + } + + s = ReadToken(buf, wasQuoted, wasConditional); + + if (wasConditional) + { + bAccepted = EvaluateConditional(s); + + s = ReadToken(buf, wasQuoted, wasConditional); + } + + if (s && *s == '{' && !wasQuoted) + { + pCurrentKey->RecursiveLoadFromBuffer(resourceName, buf); + } + else + { + g_KeyValuesErrorStack.ReportError("LoadFromBuffer: missing {"); + } + + if (!bAccepted) + { + if (pPreviousKey) + { + pPreviousKey->SetNextKey(NULL); + } + pCurrentKey->Clear(); + } + else + { + pPreviousKey = pCurrentKey; + pCurrentKey = NULL; + } + } while (buf.IsValid()); + + AppendIncludedKeys(includedKeys); + { + int i; + for (i = includedKeys.Count() - 1; i > 0; i--) + { + KeyValues* kv = includedKeys[i]; + kv->deleteThis(); + } + } + + MergeBaseKeys(baseKeys); + { + int i; + for (i = baseKeys.Count() - 1; i >= 0; i--) + { + KeyValues* kv = baseKeys[i]; + kv->deleteThis(); + } + } + + g_KeyValuesErrorStack.SetFilename(""); + + return true; +} + + +bool KeyValues::LoadFromBuffer(char const* resourceName, const char* pBuffer, IBaseFileSystem* pFileSystem, const char* pPathID) +{ + if (!pBuffer) + return true; + + int nLen = Q_strlen(pBuffer); + CUtlBuffer buf(pBuffer, nLen, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER); + return LoadFromBuffer(resourceName, buf, pFileSystem, pPathID); +} \ No newline at end of file diff --git a/SpyCustom/Label.h b/SpyCustom/Label.h new file mode 100644 index 0000000..028c62d --- /dev/null +++ b/SpyCustom/Label.h @@ -0,0 +1,167 @@ +#ifndef LABEL_H +#define LABEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "utlvector.h" +#include "VGUI.h" +#include "Panel.h" +#include "PHandle.h" + +namespace vgui +{ + + class Label : public Panel + { + DECLARE_CLASS_SIMPLE(Label, Panel); + + public: + Label(Panel* parent, const char* panelName, const char* text); + Label(Panel* parent, const char* panelName, const wchar_t* wszText); + ~Label(); + + public: + virtual void SetText(const char* tokenName); + + virtual void SetText(const wchar_t* unicodeString, bool bClearUnlocalizedSymbol = false); + + virtual void GetText(OUT_Z_BYTECAP(bufferLen) char* textOut, int bufferLen); + virtual void GetText(OUT_Z_BYTECAP(bufLenInBytes) wchar_t* textOut, int bufLenInBytes); + + virtual void GetContentSize(int& wide, int& tall); + + enum Alignment + { + a_northwest = 0, + a_north, + a_northeast, + a_west, + a_center, + a_east, + a_southwest, + a_south, + a_southeast, + }; + + virtual void SetContentAlignment(Alignment alignment); + virtual void SetEnabled(bool state); + virtual void SetTextInset(int xInset, int yInset); + virtual void GetTextInset(int* xInset, int* yInset); + + virtual void SetFgColor(Color color); + virtual Color GetFgColor(); + + virtual void SetDisabledFgColor1(Color color); + virtual void SetDisabledFgColor2(Color color); + virtual Color GetDisabledFgColor1(); + virtual Color GetDisabledFgColor2(); + + enum EColorState + { + CS_NORMAL, + CS_DULL, + CS_BRIGHT, + }; + virtual void SetTextColorState(EColorState state); + + virtual void SetFont(HFont font); + virtual HFont GetFont(); + + virtual Panel* HasHotkey(wchar_t key); + virtual void SetHotkey(wchar_t key); + virtual wchar_t GetHotKey(); + + virtual void SetAssociatedControl(Panel* control); + + virtual int AddImage(IImage* image, int preOffset); + virtual void SetImageAtIndex(int index, IImage* image, int preOffset); + virtual void SetImagePreOffset(int index, int preOffset); + virtual IImage* GetImageAtIndex(int index); + virtual int GetImageCount(); + virtual void ClearImages(); + virtual void ResetToSimpleTextImage(); + virtual void SetImageBounds(int index, int x, int width); + + virtual TextImage* GetTextImage(); + + virtual int SetTextImageIndex(int newIndex); + + virtual bool RequestInfo(KeyValues* outputData); + virtual void SizeToContents(); + + enum Padding + { + Content = 8, + }; + + void SetWrap(bool bWrap); + void SetCenterWrap(bool bWrap); + + void SetAllCaps(bool bAllCaps); + + protected: + virtual void PerformLayout(); + virtual wchar_t CalculateHotkey(const char* text); + virtual wchar_t CalculateHotkey(const wchar_t* text); + virtual void ComputeAlignment(int& tx0, int& ty0, int& tx1, int& ty1); + virtual void Paint(); + MESSAGE_FUNC_PARAMS(OnSetText, "SetText", params); + virtual void DrawDashedLine(int x0, int y0, int x1, int y1, int dashLen, int gapLen); + virtual void OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel); + MESSAGE_FUNC(OnHotkeyPressed, "Hotkey"); + virtual void OnMousePressed(MouseCode code); + virtual void OnSizeChanged(int wide, int tall); + + virtual void EnsureImageCapacity(int maxIndex); + + virtual void ApplySchemeSettings(IScheme* pScheme); + virtual void GetSettings(KeyValues* outResourceData); + virtual void ApplySettings(KeyValues* inResourceData); + virtual const char* GetDescription(void); + + MESSAGE_FUNC_PARAMS(OnDialogVariablesChanged, "DialogVariables", dialogVariables); + + void HandleAutoSizing(void); + + private: + void Init(); + + Alignment _contentAlignment; + TextImage* _textImage; + struct TImageInfo + { + IImage* image; + short offset; + short xpos; + short width; + }; + CUtlVector _imageDar; + + int _textInset[2]; + Color _disabledFgColor1; + Color _disabledFgColor2; + Color _associateColor; + int _textImageIndex; + EColorState _textColorState; + + PHandle _associate; + char* _associateName; + + char* _fontOverrideName; + + wchar_t _hotkey; + + bool m_bWrap; + bool m_bCenterWrap; + bool m_bAllCaps; + bool m_bAutoWideToContents; + bool m_bAutoWideDirty; + bool m_bUseProportionalInsets; + + }; + +} + +#endif \ No newline at end of file diff --git a/SpyCustom/ListPanel.h b/SpyCustom/ListPanel.h new file mode 100644 index 0000000..f4b7ca8 --- /dev/null +++ b/SpyCustom/ListPanel.h @@ -0,0 +1,304 @@ +#ifndef LISTPANEL_H +#define LISTPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "utllinkedlist.h" +#include "utlvector.h" +#include "utlrbtree.h" +#include "VGUI.h" +#include "Panel.h" + +class KeyValues; + +namespace vgui +{ + + class ScrollBar; + class TextImage; + class ImagePanel; + class Label; + class Button; + class IDraggerEvent; + class FastSortListPanelItem; + + class ListPanelItem + { + public: + ListPanelItem() : + kv(0), + userData(0), + m_pDragData(0), + m_bImage(false), + m_nImageIndex(-1), + m_nImageIndexSelected(-1), + m_pIcon(0) + { + } + + KeyValues* kv; + unsigned int userData; + KeyValues* m_pDragData; + bool m_bImage; + int m_nImageIndex; + int m_nImageIndexSelected; + IImage* m_pIcon; + }; + + typedef int __cdecl SortFunc( + ListPanel* pPanel, + const ListPanelItem& item1, + const ListPanelItem& item2); + + class ListPanel : public Panel + { + DECLARE_CLASS_SIMPLE(ListPanel, Panel); + + public: + ListPanel(Panel* parent, const char* panelName); + ~ListPanel(); + + enum ColumnFlags_e + { + COLUMN_FIXEDSIZE = 0x01, + COLUMN_RESIZEWITHWINDOW = 0x02, + COLUMN_IMAGE = 0x04, + COLUMN_HIDDEN = 0x08, + COLUMN_UNHIDABLE = 0x10, + }; + + virtual void AddColumnHeader(int index, const char* columnName, const char* columnText, int startingWidth, int minWidth, int maxWidth, int columnFlags = 0); + virtual void AddColumnHeader(int index, const char* columnName, const char* columnText, int width, int columnFlags = 0); + + virtual void RemoveColumn(int column); + virtual int FindColumn(const char* columnName); + virtual void SetColumnHeaderHeight(int height); + virtual void SetColumnHeaderText(int column, const char* text); + virtual void SetColumnHeaderText(int column, wchar_t* text); + virtual void SetColumnHeaderImage(int column, int imageListIndex); + virtual void SetColumnHeaderTooltip(int column, const char* tooltipText); + virtual void SetColumnTextAlignment(int column, int align); + + virtual int GetNumColumnHeaders() const; + virtual bool GetColumnHeaderText(int index, char* pOut, int maxLen); + + virtual void SetSortFunc(int column, SortFunc* func); + virtual void SetSortColumn(int column); + virtual void SortList(void); + virtual void SetColumnSortable(int column, bool sortable); + virtual void SetColumnVisible(int column, bool visible); + int GetSortColumn() const; + + virtual void SetAllowUserModificationOfColumns(bool allowed); + + virtual int AddItem(const KeyValues* data, unsigned int userData, bool bScrollToItem, bool bSortOnAdd); + void SetItemDragData(int itemID, const KeyValues* data); + virtual int GetItemCount(void); + virtual int GetItem(const char* itemName); + virtual KeyValues* GetItem(int itemID); + virtual int GetItemCurrentRow(int itemID); + virtual int GetItemIDFromRow(int currentRow); + virtual unsigned int GetItemUserData(int itemID); + virtual ListPanelItem* GetItemData(int itemID); + virtual void SetUserData(int itemID, unsigned int userData); + virtual int GetItemIDFromUserData(unsigned int userData); + virtual void ApplyItemChanges(int itemID); + virtual void RemoveItem(int itemID); + virtual void RereadAllItems(); + + virtual void RemoveAll(); + virtual void DeleteAllItems(); + + virtual void GetCellText(int itemID, int column, OUT_Z_BYTECAP(bufferSizeInBytes) wchar_t* buffer, int bufferSizeInBytes); + virtual IImage* GetCellImage(int itemID, int column); + + virtual int FirstItem() const; + virtual int NextItem(int iItem) const; + + virtual int InvalidItemID() const; + virtual bool IsValidItemID(int itemID); + + virtual void SetItemVisible(int itemID, bool state); + virtual void SetItemDisabled(int itemID, bool state); + bool IsItemVisible(int itemID); + + virtual void SetFont(HFont font); + + virtual void SetImageList(ImageList* imageList, bool deleteImageListWhenDone); + + virtual int GetSelectedItemsCount(); + + virtual int GetSelectedItem(int selectionIndex); + + virtual void ClearSelectedItems(); + + virtual bool IsItemSelected(int itemID); + + virtual void AddSelectedItem(int itemID); + + virtual void SetSingleSelectedItem(int itemID); + + virtual int GetSelectedColumn(); + + virtual void SetSelectIndividualCells(bool state); + + void SetMultiselectEnabled(bool bState); + bool IsMultiselectEnabled() const; + + virtual void SetSelectedCell(int row, int column); + + virtual bool GetCellAtPos(int x, int y, int& row, int& column); + virtual bool GetCellBounds(int row, int column, int& x, int& y, int& wide, int& tall); + + virtual void SetEmptyListText(const char* text); + virtual void SetEmptyListText(const wchar_t* text); + + void ResetScrollBar(); + + virtual void OnCreateDragData(KeyValues* msg); + + void SetIgnoreDoubleClick(bool state); + + virtual void EnterEditMode(int itemID, int column, vgui::Panel* editPanel); + + virtual void LeaveEditMode(); + + virtual bool IsInEditMode(); + + MESSAGE_FUNC_INT(ResizeColumnToContents, "ResizeColumnToContents", column); + +#ifdef _X360 + virtual void NavigateTo(); +#endif + int m_nUserConfigFileVersion; + + protected: + virtual Panel* GetCellRenderer(int row, int column); + + virtual void OnMouseWheeled(int delta); + virtual void OnSizeChanged(int wide, int tall); + virtual void PerformLayout(); + virtual void Paint(); + virtual void PaintBackground(); + virtual void ApplySchemeSettings(IScheme* pScheme); + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseDoublePressed(MouseCode code); +#ifdef _X360 + virtual void OnKeyCodePressed(KeyCode code); +#else + virtual void OnKeyCodePressed(KeyCode code); +#endif + MESSAGE_FUNC(OnSliderMoved, "ScrollBarSliderMoved"); + MESSAGE_FUNC_INT_INT(OnColumnResized, "ColumnResized", column, delta); + MESSAGE_FUNC_INT(OnSetSortColumn, "SetSortColumn", column); + MESSAGE_FUNC(OpenColumnChoiceMenu, "OpenColumnChoiceMenu"); + MESSAGE_FUNC_INT(OnToggleColumnVisible, "ToggleColumnVisible", col); + virtual float GetRowsPerPage(); + virtual int GetStartItem(); + + virtual void ApplyUserConfigSettings(KeyValues* userConfig); + virtual void GetUserConfigSettings(KeyValues* userConfig); + virtual bool HasUserConfigSettings(); + + public: + virtual void SetSortColumnEx(int iPrimarySortColumn, int iSecondarySortColumn, bool bSortAscending); + void GetSortColumnEx(int& iPrimarySortColumn, int& iSecondarySortColumn, bool& bSortAscending) const; + + private: + void CleanupItem(FastSortListPanelItem* data); + + void IndexItem(int itemID); + + void UpdateSelection(vgui::MouseCode code, int x, int y, int row, int column); + + void HandleMultiSelection(int itemID, int row, int column); + + void HandleAddSelection(int itemID, int row, int column); + + struct IndexItem_t + { + ListPanelItem* dataItem; + int duplicateIndex; + }; + typedef CUtlRBTree IndexRBTree_t; + + struct column_t + { + Button* m_pHeader; + int m_iMinWidth; + int m_iMaxWidth; + bool m_bResizesWithWindow; + Panel* m_pResizer; + SortFunc* m_pSortFunc; + bool m_bTypeIsText; + bool m_bHidden; + bool m_bUnhidable; + IndexRBTree_t m_SortedTree; + int m_nContentAlignment; + }; + + CUtlLinkedList m_ColumnsData; + + CUtlVector m_ColumnsHistory; + + CUtlVector m_CurrentColumns; + + int m_iColumnDraggerMoved; + int m_lastBarWidth; + + CUtlLinkedList m_DataItems; + CUtlVector m_VisibleItems; + + int m_iSortColumn; + int m_iSortColumnSecondary; + + void ResortColumnRBTree(int col); + static bool RBTreeLessFunc(vgui::ListPanel::IndexItem_t& item1, vgui::ListPanel::IndexItem_t& item2); + + TextImage* m_pTextImage; + ImagePanel* m_pImagePanel; + Label* m_pLabel; + ScrollBar* m_hbar; + ScrollBar* m_vbar; + + int m_iSelectedColumn; + + bool m_bNeedsSort : 1; + bool m_bSortAscending : 1; + bool m_bSortAscendingSecondary : 1; + bool m_bCanSelectIndividualCells : 1; + bool m_bShiftHeldDown : 1; + bool m_bMultiselectEnabled : 1; + bool m_bAllowUserAddDeleteColumns : 1; + bool m_bDeleteImageListWhenDone : 1; + bool m_bIgnoreDoubleClick : 1; + + int m_iHeaderHeight; + int m_iRowHeight; + + CUtlVector m_SelectedItems; + int m_LastItemSelected; + + int m_iTableStartX; + int m_iTableStartY; + + Color m_LabelFgColor; + Color m_DisabledColor; + Color m_SelectionFgColor; + Color m_DisabledSelectionFgColor; + + ImageList* m_pImageList; + TextImage* m_pEmptyListText; + + PHandle m_hEditModePanel; + int m_iEditModeItemID; + int m_iEditModeColumn; + + void ResetColumnHeaderCommands(); + }; + +} + +#endif \ No newline at end of file diff --git a/SpyCustom/MaterialSystemUtil.h b/SpyCustom/MaterialSystemUtil.h new file mode 100644 index 0000000..bb2e8ca --- /dev/null +++ b/SpyCustom/MaterialSystemUtil.h @@ -0,0 +1,72 @@ +#ifndef MATERIALSYSTEMUTIL_H +#define MATERIALSYSTEMUTIL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "imageformat.h" +#include "imaterialsystem.h" + +class IMaterial; +class ITexture; +class KeyValues; + +class KeyValues; + + +class CMaterialReference +{ +public: + CMaterialReference(char const* pMaterialName = 0, const char* pTextureGroupName = 0, bool bComplain = true); + ~CMaterialReference(); + + void Init(const char* pMaterialName, const char* pTextureGroupName, bool bComplain = true); + void Init(const char* pMaterialName, KeyValues* pVMTKeyValues); + void Init(IMaterial* pMaterial); + void Init(CMaterialReference& ref); + void Init(const char* pMaterialName, const char* pTextureGroupName, KeyValues* pVMTKeyValues); + + void Shutdown(); + bool IsValid() { return m_pMaterial != 0; } + + operator IMaterial* () { return m_pMaterial; } + operator IMaterial* () const { return m_pMaterial; } + operator IMaterial const* () const { return m_pMaterial; } + IMaterial* operator->() { return m_pMaterial; } + +private: + IMaterial* m_pMaterial; +}; + +class CTextureReference +{ +public: + CTextureReference(); + CTextureReference(const CTextureReference& ref); + ~CTextureReference(); + + void Init(char const* pTexture, const char* pTextureGroupName, bool bComplain = true); + void InitProceduralTexture(const char* pTextureName, const char* pTextureGroupName, int w, int h, ImageFormat fmt, int nFlags); + void InitRenderTarget(int w, int h, RenderTargetSizeMode_t sizeMode, ImageFormat fmt, MaterialRenderTargetDepth_t depth, bool bHDR, char* pStrOptionalName = NULL); +#if defined( _X360 ) + void InitRenderTargetTexture(int width, int height, RenderTargetSizeMode_t sizeMode, ImageFormat fmt, MaterialRenderTargetDepth_t depth, bool bHDR, char* pStrOptionalName = NULL); + void InitRenderTargetSurface(int width, int height, ImageFormat fmt, bool bSameAsTexture); +#endif + void Init(ITexture* pTexture); + + void Shutdown(bool bDeleteIfUnReferenced = false); + bool IsValid() { return m_pTexture != 0; } + + operator ITexture* () { return m_pTexture; } + operator ITexture const* () const { return m_pTexture; } + ITexture* operator->() { return m_pTexture; } + + void operator=(CTextureReference& ref); + +private: + ITexture* m_pTexture; +}; + + +#endif \ No newline at end of file diff --git a/SpyCustom/Menu.h b/SpyCustom/Menu.h new file mode 100644 index 0000000..6f51fa4 --- /dev/null +++ b/SpyCustom/Menu.h @@ -0,0 +1,262 @@ +#ifndef MENU_H +#define MENU_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "Panel.h" +#include "Label.h" +#include "utllinkedlist.h" +#include "utlvector.h" + +namespace vgui +{ + + class MenuItem; + class ScrollBar; + class MenuSeparator; + + class Menu : public Panel + { + DECLARE_CLASS_SIMPLE(Menu, Panel); + friend class MenuItem; + public: + enum MenuDirection_e + { + LEFT, + RIGHT, + UP, + DOWN, + CURSOR, + ALIGN_WITH_PARENT, + }; + + Menu(Panel* parent, const char* panelName); + ~Menu(); + + static void PlaceContextMenu(Panel* parent, Menu* menu); + static void OnInternalMousePressed(Panel* other, MouseCode code); + + virtual void PositionRelativeToPanel(Panel* reference, MenuDirection_e direction, int nAdditionalYOffset = 0, bool showMenu = false); + + virtual int AddMenuItem(const char* itemName, const char* itemText, const char* command, Panel* target, const KeyValues* userData = NULL); + virtual int AddMenuItem(const char* itemName, const wchar_t* wszItemText, const char* command, Panel* target, const KeyValues* userData = NULL); + + virtual int AddMenuItem(const char* itemName, const char* itemText, KeyValues* message, Panel* target, const KeyValues* userData = NULL); + virtual int AddMenuItem(const char* itemName, const wchar_t* wszItemText, KeyValues* message, Panel* target, const KeyValues* userData = NULL); + + virtual int AddMenuItem(const char* itemText, const char* command, Panel* target, const KeyValues* userData = NULL); + virtual int AddMenuItem(const char* itemText, KeyValues* message, Panel* target, const KeyValues* userData = NULL); + virtual int AddMenuItem(const char* itemText, Panel* target, const KeyValues* userData = NULL); + + virtual int AddCheckableMenuItem(const char* itemName, const char* itemText, const char* command, Panel* target, const KeyValues* userData = NULL); + virtual int AddCheckableMenuItem(const char* itemName, const wchar_t* wszItemText, const char* command, Panel* target, const KeyValues* userData = NULL); + + virtual int AddCheckableMenuItem(const char* itemName, const char* itemText, KeyValues* message, Panel* target, const KeyValues* userData = NULL); + virtual int AddCheckableMenuItem(const char* itemName, const wchar_t* wszItemText, KeyValues* message, Panel* target, const KeyValues* userData = NULL); + + virtual int AddCheckableMenuItem(const char* itemText, const char* command, Panel* target, const KeyValues* userData = NULL); + virtual int AddCheckableMenuItem(const char* itemText, KeyValues* message, Panel* target, const KeyValues* userData = NULL); + virtual int AddCheckableMenuItem(const char* itemText, Panel* target, const KeyValues* userData = NULL); + + virtual int AddCascadingMenuItem(const char* itemName, const char* itemText, const char* command, Panel* target, Menu* cascadeMenu, const KeyValues* userData = NULL); + virtual int AddCascadingMenuItem(const char* itemName, const wchar_t* wszItemText, const char* command, Panel* target, Menu* cascadeMenu, const KeyValues* userData = NULL); + + virtual int AddCascadingMenuItem(const char* itemName, const char* itemText, KeyValues* message, Panel* target, Menu* cascadeMenu, const KeyValues* userData = NULL); + virtual int AddCascadingMenuItem(const char* itemName, const wchar_t* wszItemText, KeyValues* message, Panel* target, Menu* cascadeMenu, const KeyValues* userData = NULL); + + virtual int AddCascadingMenuItem(const char* itemText, const char* command, Panel* target, Menu* cascadeMenu, const KeyValues* userData = NULL); + virtual int AddCascadingMenuItem(const char* itemText, KeyValues* message, Panel* target, Menu* cascadeMenu, const KeyValues* userData = NULL); + virtual int AddCascadingMenuItem(const char* itemText, Panel* target, Menu* cascadeMenu, const KeyValues* userData = NULL); + + virtual int AddMenuItem(MenuItem* panel); + + virtual void AddSeparator(); + virtual void AddSeparatorAfterItem(int itemID); + + virtual void UpdateMenuItem(int itemID, const char* itemText, KeyValues* message, const KeyValues* userData = NULL); + virtual void UpdateMenuItem(int itemID, const wchar_t* wszItemText, KeyValues* message, const KeyValues* userData = NULL); + + virtual void MoveMenuItem(int itemID, int moveBeforeThisItemID); + + virtual bool IsValidMenuID(int itemID); + virtual int GetInvalidMenuID(); + + KeyValues* GetItemUserData(int itemID); + void GetItemText(int itemID, wchar_t* text, int bufLenInBytes); + void GetItemText(int itemID, char* text, int bufLenInBytes); + + virtual void SetItemEnabled(const char* itemName, bool state); + virtual void SetItemEnabled(int itemID, bool state); + virtual void SetItemVisible(const char* itemName, bool visible); + virtual void SetItemVisible(int itemID, bool visible); + + void DeleteItem(int itemID); + + void DeleteAllItems(); + + virtual void SetFixedWidth(int width); + + void SetContentAlignment(Label::Alignment alignment); + + virtual void SetMenuItemHeight(int itemHeight); + virtual int GetMenuItemHeight() const; + + virtual void SetNumberOfVisibleItems(int numItems); + + void EnableUseMenuManager(bool bUseMenuManager); + + virtual void PerformLayout(void); + + virtual void SetBorder(class IBorder* border); + virtual void ApplySchemeSettings(IScheme* pScheme); + + enum MenuTypeAheadMode + { + COMPAT_MODE = 0, + HOT_KEY_MODE, + TYPE_AHEAD_MODE, + }; + virtual void SetTypeAheadMode(MenuTypeAheadMode mode); + virtual int GetTypeAheadMode(); + + virtual void OnKeyTyped(wchar_t unichar); + virtual void OnKeyCodeTyped(KeyCode code); + + virtual void SetVisible(bool state); + + virtual void ActivateItem(int itemID); + virtual void SilentActivateItem(int itemID); + virtual void ActivateItemByRow(int row); + virtual int GetActiveItem(); + + virtual int GetItemCount(); + + virtual int GetMenuID(int index); + + int GetCurrentlyVisibleItemsCount(); + + MenuItem* GetMenuItem(int itemID); + void CloseOtherMenus(MenuItem* item); + virtual void OnKillFocus(); + + int GetMenuMode(); + enum MenuMode + { + MOUSE = 0, + KEYBOARD, + }; + + void SetCurrentlyHighlightedItem(int itemID); + int GetCurrentlyHighlightedItem(); + void ClearCurrentlyHighlightedItem(); + + void SetMenuItemChecked(int itemID, bool state); + bool IsChecked(int index); + + + void SetMinimumWidth(int width); + int GetMinimumWidth(); + + virtual void SetFgColor(Color newColor); + virtual void SetBgColor(Color newColor); + + virtual void SetFont(HFont font); + + void SetCurrentKeyBinding(int itemID, char const* hotkey); + + void ForceCalculateWidth(); + + void SetUseFallbackFont(bool bState, HFont hFallback); + + protected: + int AddMenuItemCharCommand(MenuItem* item, const char* command, Panel* target, const KeyValues* userData); + int AddMenuItemKeyValuesCommand(MenuItem* item, KeyValues* message, Panel* target, const KeyValues* userData); + + virtual void OnCommand(const char* command); + MESSAGE_FUNC_PTR(OnMenuItemSelected, "MenuItemSelected", panel); + virtual void AddScrollBar(); + virtual void RemoveScrollBar(); + MESSAGE_FUNC(OnSliderMoved, "ScrollBarSliderMoved"); + virtual void Paint(); + virtual void LayoutMenuBorder(); + virtual void MakeItemsVisibleInScrollRange(int maxVisibleItems, int nNumPixelsAvailable); + virtual void OnMouseWheeled(int delta); + virtual void OnHotKey(wchar_t unichar); + virtual void OnTypeAhead(wchar_t unichar); + + int CountVisibleItems(); + void ComputeWorkspaceSize(int& workWide, int& workTall); + int ComputeFullMenuHeightWithInsets(); + + void CalculateWidth(); + + void LayoutScrollBar(); + void PositionCascadingMenu(); + void SizeMenuItems(); + void OnCursorMoved(int x, int y); + void OnKeyCodePressed(KeyCode code); + void OnMenuClose(); + MESSAGE_FUNC(OnKeyModeSet, "KeyModeSet"); + + void SetCurrentlySelectedItem(MenuItem* item); + void SetCurrentlySelectedItem(int itemID); + MESSAGE_FUNC_INT(OnCursorEnteredMenuItem, "CursorEnteredMenuItem", VPanel); + MESSAGE_FUNC_INT(OnCursorExitedMenuItem, "CursorExitedMenuItem", VPanel); + + void MoveAlongMenuItemList(int direction, int loopCount); + + enum + { + DEFAULT_MENU_ITEM_HEIGHT = 22, + MENU_UP = -1, + MENU_DOWN = 1 + }; + +#ifdef DBGFLAG_VALIDATE + virtual void Validate(CValidator& validator, char* pchName); +#endif + + private: + MenuItem* GetParentMenuItem(); + + int m_iMenuItemHeight; + int m_iFixedWidth; + int m_iMinimumWidth; + int m_iNumVisibleLines; + ScrollBar* m_pScroller; + + CUtlLinkedList m_MenuItems; + + CUtlVector m_VisibleSortedItems; + CUtlVector m_SortedItems; + CUtlVector m_Separators; + CUtlVector m_SeparatorPanels; + + bool _sizedForScrollBar : 1; + bool m_bUseFallbackFont : 1; + bool _recalculateWidth : 1; + bool m_bUseMenuManager : 1; + + int _menuWide; + int m_iCurrentlySelectedItemID; + int m_iInputMode; + int m_iCheckImageWidth; + int m_iProportionalScrollBarSize; + Label::Alignment m_Alignment; + Color _borderDark; + int m_iActivatedItem; + HFont m_hItemFont; + HFont m_hFallbackItemFont; + +#define TYPEAHEAD_BUFSIZE 256 + MenuTypeAheadMode m_eTypeAheadMode; + wchar_t m_szTypeAheadBuf[TYPEAHEAD_BUFSIZE]; + int m_iNumTypeAheadChars; + double m_fLastTypeAheadTime; + }; + +} + +#endif \ No newline at end of file diff --git a/SpyCustom/Menu.hpp b/SpyCustom/Menu.hpp new file mode 100644 index 0000000..61aaa10 --- /dev/null +++ b/SpyCustom/Menu.hpp @@ -0,0 +1,1949 @@ +#pragma once + + + +IMaterial* CreateMaterial(std::string matname, std::string mat_data = "") +{ + KeyValues* keyValues = new KeyValues(matname.c_str()); + keyValues->Init(); + keyValues->LoadFromBuffer(matname.c_str(), mat_data.c_str()); + IMaterial* newmat = iff.g_pMaterialSystem->CreateMaterial(matname.c_str(), keyValues); +#ifdef DEBUG + printf("Material %s created\n", matname.c_str()); +#endif + return newmat; +} + + + +void colorWorld(bool on = 1) noexcept +{ + if (on) { + if (!*g_Options.worldcoloractive) return; + + iff.g_pCVar->FindVar("r_drawspecificstaticprop")->SetValue(false); + + for (MaterialHandle_t h = iff.g_pMaterialSystem->FirstMaterial(); h != iff.g_pMaterialSystem->InvalidMaterial(); h = iff.g_pMaterialSystem->NextMaterial(h)) { + IMaterial* pMaterial = iff.g_pMaterialSystem->GetMaterial(h); + if (!pMaterial || !pMaterial->IsPrecached()) + continue; + const char* textureGroup = pMaterial->GetTextureGroupName(); + if (strstr(textureGroup, "World textures")) + pMaterial->ColorModulate(g_Options.worldcolor.value->r, g_Options.worldcolor.value->g, g_Options.worldcolor.value->b); + if (strstr(textureGroup, "StaticProp")) + pMaterial->ColorModulate(g_Options.staticpropcolor.value->r, g_Options.staticpropcolor.value->g, g_Options.staticpropcolor.value->b); + if (strstr(textureGroup, "Model")) + pMaterial->ColorModulate(g_Options.modelcolor.value->r, g_Options.modelcolor.value->g, g_Options.modelcolor.value->b); + } + } + else + { + iff.g_pCVar->FindVar("r_drawspecificstaticprop")->SetValue(true); + + for (MaterialHandle_t h = iff.g_pMaterialSystem->FirstMaterial(); h != iff.g_pMaterialSystem->InvalidMaterial(); h = iff.g_pMaterialSystem->NextMaterial(h)) { + IMaterial* pMaterial = iff.g_pMaterialSystem->GetMaterial(h); + if (!pMaterial || !pMaterial->IsPrecached()) + continue; + const char* textureGroup = pMaterial->GetTextureGroupName(); + if (strstr(textureGroup, "World textures")) + pMaterial->ColorModulate(1.0f, 1.0f, 1.0f); + if (strstr(textureGroup, "StaticProp")) + pMaterial->ColorModulate(1.0f, 1.0f, 1.0f); + if (strstr(textureGroup, "Model")) + pMaterial->ColorModulate(1.0f, 1.0f, 1.0f); + } + } +} + + +void RefreshThread(int* skinid) +{ + int localskinid = *skinid; + *skinid = 0; + iff.g_pClientState->ForceFullUpdate(); + Sleep(350); + + *skinid = localskinid; + iff.g_pClientState->ForceFullUpdate(); + opt.needupdate = 1; + ProtoFeatures.SendClientHello(); + ProtoFeatures.SendMatchmakingClient2GCHello(); +} + +struct float3 colorConverter(int hexValue) +{ + float3 rgbColor; + rgbColor.b = ((hexValue >> 16) & 0xFF) / 255.0; + rgbColor.g = ((hexValue >> 8) & 0xFF) / 255.0; + rgbColor.r = ((hexValue) & 0xFF) / 255.0; + return rgbColor; +} + +extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +WNDPROC oWndProc; +static HWND window = NULL; +LRESULT __stdcall WndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + if (true && ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam)) + return true; + return CallWindowProc(oWndProc, hWnd, uMsg, wParam, lParam); +} + +#include "imgui/imgui_internal.h" + +ImFont* ifont; ImFont* ifontBD; ImFont* ifontmini; +void InitImGui(LPDIRECT3DDEVICE9 pDevice) +{ + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags = ImGuiConfigFlags_NoMouseCursorChange; + auto a = ImFontConfig(); + a.FontBuilderFlags = 1 << 7 | 1 << 4 | 1 << 5; + ifontBD = io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\segoeuib.ttf", 14); + ifont = io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\arial.ttf", 14); + ifontmini = io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\arial.ttf", 12); + ImGuiStyle* style = &ImGui::GetStyle(); + style->WindowMenuButtonPosition = 2; + style->WindowTitleAlign = ImVec2(0.00f, 1.2f); + style->WindowRounding = 6; + style->Colors[ImGuiCol_FrameBg] = ImVec4(0.463f, 0.463f, 0.463f, 1.0f); + style->Colors[ImGuiCol_TitleBgActive] = ImVec4(0.635f, 0.635f, 0.635f, 1.0f); + style->Colors[ImGuiCol_TitleBg] = ImVec4(0.635f, 0.635f, 0.635f, 1.0f); + style->Colors[ImGuiCol_WindowBg] = ImVec4(0.635f, 0.635f, 0.635f, 1.0f); + style->Colors[ImGuiCol_MenuBarBg] = ImVec4(0.635f, 0.635f, 0.635f, 1.0f); + style->Colors[ImGuiCol_Button] = ImVec4(0.635f, 0.635f, 0.635f, 1.0f); + style->ButtonTextAlign = ImVec2(0.1f, 0.5f); + style->TabRounding = 0; + style->TabBorderSize = 1; + style->Colors[ImGuiCol_Tab] = ImVec4(0.635f, 0.635f, 0.635f, 1.0f); + style->WindowPadding = ImVec2(20.0f, 20.0f); + style->ItemSpacing = ImVec2(7.0f, 15.0f); + style->Colors[ImGuiCol_Border] = ImVec4(0.757f, 0.757f, 0.757f, 1.0f); + style->Colors[ImGuiCol_CheckMark] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + style->Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.757f, 0.757f, 0.757f, 1.0f); + style->Colors[ImGuiCol_FrameBgActive] = ImVec4(0.757f, 0.757f, 0.757f, 1.0f); + style->Colors[ImGuiCol_HeaderHovered] = ImVec4(1.0f, 0.612f, 0, 1.0f); + style->Colors[ImGuiCol_HeaderActive] = ImVec4(1.0f, 0.612f, 0, 1.0f); + style->Colors[ImGuiCol_Header] = ImVec4(1.0f, 0.612f, 0, 1.0f); + style->Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.424f, 0.424f, 0.424f, 1.0f); + style->Colors[ImGuiCol_SliderGrab] = ImVec4(0.424f, 0.424f, 0.424f, 1.0f); + style->Colors[ImGuiCol_PopupBg] = ImVec4(0.635f, 0.635f, 0.635f, 1.0f); + style->ScrollbarRounding = 0; + style->SelectableTextAlign = ImVec2(0, 0); + + ImGui_ImplWin32_Init(window); + ImGui_ImplDX9_Init(pDevice); +#ifdef DEBUG + printf("Imgui initiated\n"); +#endif +} +bool init = false; + + + +ID3DXFont* font; +VMTHook* D3DHook = nullptr; + + +void DisableElements(bool check, bool dis) +{ + if (!check) { + if (dis) + { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + } + + if (!dis) + { + ImGui::PopItemFlag(); + ImGui::PopStyleVar(); + } + } +} + +long __stdcall hkEndScene(IDirect3DDevice9* pDevice) +{ + static auto oEndScene = D3DHook->GetOriginal(42); + + + if (!init) + { + D3DDEVICE_CREATION_PARAMETERS params; + pDevice->GetCreationParameters(¶ms); + window = params.hFocusWindow; + oWndProc = (WNDPROC)SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)WndProc); +#ifdef DEBUG + cout << "oWndProc " << oWndProc << endl; +#endif + InitImGui(pDevice); + init = true; + } + + + if (opt.show) { + + ImGui_ImplDX9_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + ImGuiStyle* style = &ImGui::GetStyle(); + + ImGui::PushFont(ifontBD); + + ImGui::SetNextWindowSize(ImVec2{ 650, 455 }); + + ImGui::Begin(XorStr("Spy's Seaside"), 0, ImGuiWindowFlags_NoResize); + + + ImGui::PushFont(ifont); + ImGui::BeginTabBar("1"); + + if (ImGui::BeginTabItem("Effects")) + { + + style->ChildBorderSize = 0; style->WindowPadding = ImVec2(20.0f, 5.0f); + if (ImGui::BeginChild("ChildTab", ImVec2(665, 350), true, ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + style->ChildBorderSize = 1; style->WindowPadding = ImVec2(20.0f, 20.0f); + + ImGui::Columns(2, nullptr, false); + + ImGui::Checkbox("Bullet trace beam", g_Options.beamtrace); + + DisableElements(*g_Options.beamtrace, 1); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + if (ImGui::BeginTable("ssplit", 2, ImGuiTableFlags_NoSavedSettings)) + { + ImGui::TableNextRow(); ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::TextInputComboBox("Path to .vmt", g_Options.beampath.value->mystring, 255, opt.spriteslist, 0); + ImGui::InputInt("Beam type", g_Options.beamtype, 0, 0); + ImGui::InputFloat("Width", g_Options.beamwidth, 0, 0); + ImGui::InputFloat("Amplitude", g_Options.beamamplitude, 0, 0); + ImGui::InputFloat("Halo scale", g_Options.beamhaloscale, 0, 0); + ImGui::InputFloat("Start frame", g_Options.beamstartframe, 0, 0); + ImGui::InputInt("Segments", g_Options.beamsegments, 0, 0); + + ImGui::TableNextColumn(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 20.0f); + ImGui::ColorEdit4("##BeamColor", (float*)g_Options.beamcolor.value.get(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_AlphaBar); + ImGui::SameLine(); + ImGui::Text("Color/Alpha"); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + ImGui::InputFloat("Life##beam", g_Options.beamlife, 0, 0); + ImGui::InputFloat("End width", g_Options.beamendwidth, 0, 0); + ImGui::InputFloat("Speed##beam", g_Options.beamspeed, 0, 0); + ImGui::InputFloat("Fade length", g_Options.beamfadelength, 0, 0); + ImGui::InputFloat("Framerate", g_Options.beamframerate, 0, 0); + ImGui::InputInt("Flags", g_Options.beamflags, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); + + ImGui::EndTable(); + } + + DisableElements(*g_Options.beamtrace, 0); + + ImGui::NextColumn(); + + ImGui::Checkbox("Bullet impact effect", g_Options.attacheffects); + + DisableElements(g_Options.attacheffects, 1); + + if (ImGui::BeginTable("split", 2, ImGuiTableFlags_NoSavedSettings)) + { + ImGui::TableNextRow(); ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("Interface", opt.EffTypes.at(g_Options.effects.value->type).c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < opt.EffTypes.size(); n++) + { + bool selected = (g_Options.effects.value->type == n); + if (ImGui::Selectable(opt.EffTypes.at(n).c_str(), selected, 0, ImVec2(0, 0), false)) + { + g_Options.effects.value->type = n; + g_Options.effects.value->selectedc = 0; + } + if (selected) + ImGui::SetItemDefaultFocus(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Name", opt.Map.at(opt.EffTypes.at(g_Options.effects.value->type)).at(g_Options.effects.value->selectedc).c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < opt.Map.at(opt.EffTypes.at(g_Options.effects.value->type)).size(); n++) + { + bool selected = (g_Options.effects.value->selectedc == n); + if (ImGui::Selectable(opt.Map.at(opt.EffTypes.at(g_Options.effects.value->type)).at(n).c_str(), selected, 0, ImVec2(0, 0), false)) + g_Options.effects.value->selectedc = n; + if (selected) + ImGui::SetItemDefaultFocus(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + + + ImGui::TableNextColumn(); + + + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() - 25.0f, ImGui::GetCursorPosY() - 20.0f)); + ImGuiWindowFlags window_flags = ImGuiWindowFlags_None; + style->ItemSpacing = ImVec2(7.0f, 2.0f); + if (ImGui::BeginChild("ChildR", ImVec2(135, 100), true, window_flags | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + switch (g_Options.effects.value->type) + { + case (0): + { + switch (g_Options.effects.value->selectedc) + { + case 0: + case 2: + { + ImGui::InputFloat("Size", &g_Options.effects.value->fx_fsize, 0, 0); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + ImGui::InputFloat("Speed", &g_Options.effects.value->fx_fspeed, 0, 0); + break; + } + case 1: + { + ImGui::InputInt("Magnitude", &g_Options.effects.value->fx_magnitude, 0, 0); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + ImGui::InputInt("Trail length", &g_Options.effects.value->fx_traillength, 0, 0); + break; + } + case 3: + { + ImGui::InputFloat("Scale", &g_Options.effects.value->fx_fsize, 0, 0); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + ImGui::InputInt("Type", &g_Options.effects.value->fx_itype, 0, 0); + break; + } + case 4: + case 6: + { + break; + } + case 5: + { + ImGui::Checkbox("Explosive", &g_Options.effects.value->fx_bexplosive); + break; + } + + } + break; + } + + case (1): + { + ImGui::InputInt("Colors", &g_Options.effects.value->icolors, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputFloat("Magnitude", &g_Options.effects.value->fmagtinude, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputFloat("Scale##de", &g_Options.effects.value->fscale, 0, 0); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + ImGui::InputInt("Flags##de", &g_Options.effects.value->fflags, 0, 0, ImGuiInputTextFlags_CharsHexadecimal); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputFloat("Radius", &g_Options.effects.value->fradius, 0, 0); + + break; + } + + case (2): + { + switch (g_Options.effects.value->selectedc) + { + case (0): + { + ImGui::InputFloat("Beam width", &g_Options.effects.value->fbeamwidth, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputFloat("Time visible", &g_Options.effects.value->fltimevisible, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 10.0f); + ImGui::ColorEdit3("##teslacolor", (float*)g_Options.effects.value->teslacolor, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + ImGui::InputFloat("Radius##tesla", &g_Options.effects.value->teslaradius, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputInt("Beams", &g_Options.effects.value->ibeams, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputText("Sprite name", g_Options.effects.value->szSpriteName, 256); + break; + } + case (1): + { + ImGui::InputFloat("Die", &g_Options.effects.value->fdie, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputInt("Style", &g_Options.effects.value->style, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 10.0f); + ImGui::ColorEdit3("##dlightcolor", (float*)g_Options.effects.value->dlightcolor, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + ImGui::InputFloat("Radius##dlight", &g_Options.effects.value->frad, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputInt("Key", &g_Options.effects.value->key, 0, 0); ImGui::InvisibleButton("##ib", ImVec2(0, 10.0f)); + ImGui::InputFloat("Decay", &g_Options.effects.value->decay, 0, 0); + + break; + } + + } + + break; + } + + } + + + ImGui::EndChild(); + } + DisableElements(g_Options.attacheffects, 0); + + ImGui::EndTable(); + } + + + + + if (ImGui::BeginTable("sssplit", 2, ImGuiTableFlags_NoSavedSettings)) + { + ImGui::TableNextRow(); ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::Checkbox("Hit sound", g_Options.hitsound); + DisableElements(*g_Options.hitsound, 1); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 7.0f); + ImGui::TextInputComboBox("Head shot", g_Options.hspath.value->mystring, 255, opt.soundslist, 0); + DisableElements(*g_Options.hitsound, 0); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 13.0f); + ImGui::Checkbox("Flashlight (L)", g_Options.flashlightON); + DisableElements(*g_Options.flashlightON, 1); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + ImGui::TextInputComboBox("Path to .vmt ", g_Options.flashlightTexture.value->mystring, 255, opt.flashlightlist, 0); + DisableElements(*g_Options.flashlightON, 0); + ImGui::Checkbox("Nightvision (N)", g_Options.nvgsON); + + ImGui::TableNextColumn(); + + ImGui::Checkbox("Hit marker", g_Options.hitmarker); + DisableElements(*g_Options.hitsound, 1); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + ImGui::TextInputComboBox("Other bone", g_Options.obpath.value->mystring, 255, opt.soundslist, 0); + DisableElements(*g_Options.hitsound, 0); + DisableElements(*g_Options.flashlightON, 1); + ImGui::Checkbox("Cast shadows", g_Options.flashlightShadows); + ImGui::InputFloat("FOV", g_Options.flashlightFOV, 0, 0); + DisableElements(*g_Options.flashlightON, 0); + + ImGui::EndTable(); + } + + + ImGui::Columns(1, nullptr, false); + + ImGui::EndChild(); + } + + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("World")) + { + + style->ChildBorderSize = 0; style->WindowPadding = ImVec2(20.0f, 5.0f); + if (ImGui::BeginChild("ChildTab", ImVec2(665, 350), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + style->ChildBorderSize = 1; style->WindowPadding = ImVec2(20.0f, 20.0f); + + + ImGui::Columns(2, nullptr, false); + + + if (ImGui::Checkbox("Skybox", g_Options.skyboxactive)) + { + if (g_Options.skyboxactive) + { + iff.g_pCVar->FindVar("sv_skyname")->SetValue((char*)g_Options.skyboxtemp.value.get()); + iff.g_pCVar->FindVar("r_3dsky")->SetValue(false); + } + else iff.g_pCVar->FindVar("r_3dsky")->SetValue(true); + } + + DisableElements(*g_Options.skyboxactive, 1); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 10.0f); + ImGui::PushItemWidth(170.0f); + ImGui::TextInputComboBox("##W1", (char*)g_Options.skyboxtemp.value.get(), 255, opt.skyboxitems, 0); + ImGui::PopItemWidth(); + ImGui::SameLine(); + if (ImGui::Button("Apply##W1", ImVec2(70, 22))) + { + iff.g_pCVar->FindVar("sv_skyname")->SetValue((char*)g_Options.skyboxtemp.value.get()); + } + + DisableElements(*g_Options.skyboxactive, 0); + + if (ImGui::Checkbox("Weather", g_Options.weatheractive)) + { + if (!*g_Options.weatheractive) iff.g_pClientState->ForceFullUpdate(); + + iff.g_pCVar->FindVar("r_rainlength")->SetValue(*g_Options.rainlength); + iff.g_pCVar->FindVar("r_rainspeed")->SetValue(*g_Options.rainspeed); + iff.g_pCVar->FindVar("r_rainradius")->SetValue(*g_Options.rainradius); + iff.g_pCVar->FindVar("cl_windspeed")->SetValue(*g_Options.windspeed); + iff.g_pCVar->FindVar("r_rainwidth")->SetValue(*g_Options.rainwidth); + iff.g_pCVar->FindVar("r_RainSideVel")->SetValue(*g_Options.rainsidevel); + iff.g_pCVar->FindVar("r_rainalpha")->SetValue(*g_Options.rainalpha); + } + + DisableElements(*g_Options.weatheractive, 1); + + if (ImGui::BeginTable("##Weather", 2, ImGuiTableFlags_NoSavedSettings)) + { + ImGui::TableNextRow(); ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::InputInt("Precipitation type", g_Options.weathertype, 0, 0); + + if (ImGui::InputFloat("Length", g_Options.rainlength, 0, 0)) + iff.g_pCVar->FindVar("r_rainlength")->SetValue(*g_Options.rainlength); + if (ImGui::InputFloat("Speed", g_Options.rainspeed, 0, 0)) + iff.g_pCVar->FindVar("r_rainspeed")->SetValue(*g_Options.rainspeed); + if (ImGui::InputFloat("Radius", g_Options.rainradius, 0, 0)) + iff.g_pCVar->FindVar("r_rainradius")->SetValue(*g_Options.rainradius); + + ImGui::TableNextColumn(); + + if (ImGui::InputFloat("Wind speed", g_Options.windspeed, 0, 0)) + iff.g_pCVar->FindVar("cl_windspeed")->SetValue(*g_Options.windspeed); + if (ImGui::InputFloat("Width", g_Options.rainwidth, 0, 0)) + iff.g_pCVar->FindVar("r_rainwidth")->SetValue(*g_Options.rainwidth); + if (ImGui::InputFloat("Side velocity", g_Options.rainsidevel, 0, 0)) + iff.g_pCVar->FindVar("r_RainSideVel")->SetValue(*g_Options.rainsidevel); + if (ImGui::InputFloat("Alpha", g_Options.rainalpha, 0, 0)) + iff.g_pCVar->FindVar("r_rainalpha")->SetValue(*g_Options.rainalpha); + + ImGui::EndTable(); + } + + DisableElements(*g_Options.weatheractive, 0); + + ImGui::NextColumn(); + + + + + if (ImGui::BeginTable("##Fog", 4, ImGuiTableFlags_NoSavedSettings)) + { + ImGui::TableNextColumn(); + + if (ImGui::Checkbox("Fog", g_Options.fogactive)) + { + if (g_Options.fogactive) + { + iff.g_pCVar->FindVar("fog_override")->SetValue(true); + iff.g_pCVar->FindVar("fog_color")->SetValue( + std::string(""). + append(to_string(g_Options.fogcolor.value->r * 255)). + append(" "). + append(to_string(g_Options.fogcolor.value->g * 255)). + append(" "). + append(to_string(g_Options.fogcolor.value->b * 255)). + append(" ").c_str() + ); + iff.g_pCVar->FindVar("fog_colorskybox")->SetValue( + std::string(""). + append(std::to_string(g_Options.fogcolor.value->r * 255)). + append(" "). + append(std::to_string(g_Options.fogcolor.value->g * 255)). + append(" "). + append(std::to_string(g_Options.fogcolor.value->b * 255)). + append(" ").c_str() + ); + iff.g_pCVar->FindVar("fog_maxdensity")->SetValue(g_Options.fogdensity); + iff.g_pCVar->FindVar("fog_maxdensityskybox")->SetValue(g_Options.fogdensity); + iff.g_pCVar->FindVar("fog_start")->SetValue(g_Options.fogstart); + iff.g_pCVar->FindVar("fog_startskybox")->SetValue(g_Options.fogstart); + iff.g_pCVar->FindVar("fog_end")->SetValue(g_Options.fogend); + iff.g_pCVar->FindVar("fog_endskybox")->SetValue(g_Options.fogend); + } + else iff.g_pCVar->FindVar("fog_override")->SetValue(false); + } + + ImGui::TableNextColumn(); + + DisableElements(*g_Options.fogactive, 1); + + if (ImGui::ColorEdit3("##MyColor##W1", (float*)g_Options.fogcolor.value.get(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf)) + { + iff.g_pCVar->FindVar("fog_color")->SetValue( + std::string(""). + append(std::to_string(g_Options.fogcolor.value->r * 255)). + append(" "). + append(std::to_string(g_Options.fogcolor.value->g * 255)). + append(" "). + append(std::to_string(g_Options.fogcolor.value->b * 255)). + append(" ").c_str() + ); + + iff.g_pCVar->FindVar("fog_colorskybox")->SetValue( + std::string(""). + append(std::to_string(g_Options.fogcolor.value->r * 255)). + append(" "). + append(std::to_string(g_Options.fogcolor.value->g * 255)). + append(" "). + append(std::to_string(g_Options.fogcolor.value->b * 255)). + append(" ").c_str() + ); + + } + + ImGui::EndTable(); + } + + + ImGui::PushItemWidth(252.0f); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 10.0f); + + if (ImGui::SliderFloat("Max density", g_Options.fogdensity, 0.0f, 1.0f)) + { + iff.g_pCVar->FindVar("fog_maxdensity")->SetValue(g_Options.fogdensity); + iff.g_pCVar->FindVar("fog_maxdensityskybox")->SetValue(g_Options.fogdensity); + } + + if (ImGui::SliderFloat("Start", g_Options.fogstart, 0.0f, 5000.0f)) + { + iff.g_pCVar->FindVar("fog_start")->SetValue(g_Options.fogstart); + iff.g_pCVar->FindVar("fog_startskybox")->SetValue(g_Options.fogstart); + } + if (ImGui::SliderFloat("End", g_Options.fogend, 0.0f, 5000.0f)) + { + iff.g_pCVar->FindVar("fog_end")->SetValue(g_Options.fogend); + iff.g_pCVar->FindVar("fog_endskybox")->SetValue(g_Options.fogend); + } + + DisableElements(*g_Options.fogactive, 0); + + ImGui::InvisibleButton("##W4", ImVec2(0, 0.0f)); + + if (ImGui::SliderFloat("Tonemap scale", g_Options.tonemapscale, 0.001f, 1.0f)) + iff.g_pCVar->FindVar("mat_force_tonemap_scale")->SetValue(g_Options.tonemapscale); + ImGui::PopItemWidth(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + if (ImGui::Checkbox("Colorize map textures ", g_Options.worldcoloractive)) + { + if (*g_Options.worldcoloractive) colorWorld(); + else colorWorld(0); + } + + DisableElements(*g_Options.worldcoloractive, 1); + + ImGui::SameLine(); + if (ImGui::Button("Modulate", ImVec2(70, 22))) + colorWorld(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + if (ImGui::BeginTable("##Colorworld", 3, ImGuiTableFlags_NoSavedSettings)) + { + ImGui::TableNextColumn(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 3.0f); + ImGui::Text("World"); + ImGui::ColorEdit3("##W1", (float*)g_Options.worldcolor.value.get(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf); + + ImGui::TableNextColumn(); + ImGui::Text("StaticProp"); + ImGui::ColorEdit3("##W2", (float*)g_Options.staticpropcolor.value.get(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf); + + ImGui::TableNextColumn(); + ImGui::Text("Model"); + ImGui::ColorEdit3("##W3", (float*)g_Options.modelcolor.value.get(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf); + + + ImGui::EndTable(); + } + + DisableElements(*g_Options.worldcoloractive, 0); + + + + + ImGui::Columns(1, nullptr, false); + + ImGui::EndChild(); + } + + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Models")) + { + style->ChildBorderSize = 0; style->WindowPadding = ImVec2(20.0f, 5.0f); + if (ImGui::BeginChild("ChildTab", ImVec2(665, 350), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + style->ChildBorderSize = 1; style->WindowPadding = ImVec2(20.0f, 20.0f); + + static int selectedwep = 0; + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0f); + + if (ImGui::BeginTable("##Models", 2, ImGuiTableFlags_NoSavedSettings)) + { + ImGui::TableNextRow(); + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + + + ImGui::PushItemWidth(170.0f); + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("Item", g_Options.models.value->arr[selectedwep].name)) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < g_Options.models.value->itemcount; n++) + { + g_Options.models.value->arr[n].isSelected = (selectedwep == n); + if (ImGui::Selectable(g_Options.models.value->arr[n].name, g_Options.models.value->arr[n].isSelected, 0, ImVec2(0, 0), false)) + selectedwep = n; + if (g_Options.models.value->arr[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + ImGui::PopItemWidth(); + + ImGui::SameLine(); + + if (ImGui::Button("Update", ImVec2(70, 22))) + iff.g_pClientState->ForceFullUpdate(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 6.0f); + + if (ImGui::Checkbox("Set viewmodel ", &g_Options.models.value->arr[selectedwep].active)) + { + if (!g_Options.models.value->arr[selectedwep].active) { + g_Options.models.value->arr[selectedwep].vmodel_hash = fnv2::hash(g_Options.models.value->arr[selectedwep].vmodel_orig); + } + + if (g_Options.models.value->arr[selectedwep].active) { + g_Options.models.value->arr[selectedwep].vmodel_hash = fnv2::hash(g_Options.models.value->arr[selectedwep].vmodel_repl); + } + + if (selectedwep < 2) + { + + if (g_Options.models.value->arr[selectedwep].active) + *g_Options.playerloop_count += 1; + else *g_Options.playerloop_count -= 1; + +#ifdef DEBUG + printf("pl count %d\n", *g_Options.playerloop_count); +#endif + } + + + } + ImGui::SameLine(); + DisableElements(selectedwep > 2 ? true : false, 1); + ImGui::Checkbox("Via FindMDL hook", &g_Options.models.value->arr[selectedwep].findMDLmethode); + DisableElements(selectedwep > 2 ? true : false, 0); + ImGui::PushItemWidth(170.0f); + ImGui::InputText("Path to .mdl##viewmodel", g_Options.models.value->arr[selectedwep].vmodel_repl_temp, 256); + ImGui::PopItemWidth(); + + ImGui::SameLine(); + if (ImGui::Button("Apply##viewmodel", ImVec2(70, 22))) + { + if (const auto modelprecache = iff.g_pNetworkStringTableContainer->FindTable("modelprecache")) + modelprecache->AddString(false, g_Options.models.value->arr[selectedwep].vmodel_repl_temp); + + if (selectedwep > 2) { + for (int i = 0; i < 20; i++) + strcpy(g_Options.models.value->arr[selectedwep].seqs[i].seq_orig_def, ""); + + opt.needtogetseqact = selectedwep; + } + + strcpy(g_Options.models.value->arr[selectedwep].vmodel_repl, g_Options.models.value->arr[selectedwep].vmodel_repl_temp); + g_Options.models.value->arr[selectedwep].vmodel_hash = fnv2::hashRuntime(g_Options.models.value->arr[selectedwep].vmodel_repl); + } + + + ImGui::TableNextColumn(); + + DisableElements(selectedwep == 2 ? false : true, 1); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 10.0f); + + if (ImGui::Checkbox("Set scale", &g_Options.models.value->arr[selectedwep].active_scale)) + { + if (g_Options.models.value->arr[selectedwep].active_scale) + *g_Options.entityloop_count += 1; + else *g_Options.entityloop_count -= 1; + +#ifdef DEBUG + printf("el count %d\n", *g_Options.entityloop_count); +#endif + } + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 30.0f); + + DisableElements(g_Options.models.value->arr[selectedwep].active_scale, 1); + ImGui::PushItemWidth(252.0f); + ImGui::SliderFloat("##scale", &g_Options.models.value->arr[selectedwep].scale, 0.0f, 10.0f); + ImGui::PopItemWidth(); + DisableElements(g_Options.models.value->arr[selectedwep].active_scale, 0); + + DisableElements(selectedwep == 2 ? false : true, 0); + + DisableElements(selectedwep > 2 ? true : false, 1); + + if (ImGui::Checkbox("Set worldmodel", &g_Options.models.value->arr[selectedwep].active_w)) + { + + if (g_Options.models.value->arr[selectedwep].active_w) + *g_Options.entityloop_count += 1; + else *g_Options.entityloop_count -= 1; + +#ifdef DEBUG + printf("el count %d\n", *g_Options.entityloop_count); +#endif + + } + + ImGui::PushItemWidth(170.0f); + ImGui::InputText("Path to .mdl##worldmodel", g_Options.models.value->arr[selectedwep].wmodel_repl_temp, 256); + ImGui::PopItemWidth(); + + ImGui::SameLine(); + if (ImGui::Button("Apply##worldmodel", ImVec2(70, 22))) + { + strcpy(g_Options.models.value->arr[selectedwep].wmodel_repl, g_Options.models.value->arr[selectedwep].wmodel_repl_temp); + g_Options.models.value->arr[selectedwep].wmodel_hash = fnv2::hashRuntime(g_Options.models.value->arr[selectedwep].wmodel_repl); + } + + DisableElements(selectedwep > 2 ? true : false, 0); + + + + ImGui::EndTable(); + } + + + + ImGui::Columns(2, nullptr, false); + + DisableElements(selectedwep > 2 ? true : false, 1); + if (ImGui::Checkbox("Set animations", &g_Options.models.value->arr[selectedwep].seq_active)) + opt.needtogetseqact = selectedwep; + DisableElements(selectedwep > 2 ? true : false, 0); + + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + + DisableElements(g_Options.models.value->arr[selectedwep].seq_active, 1); + + static char ccc[20][5] = { "##0","##1","##2","##3","##4","##5","##6","##7","##8","##9","##10","##11","##12","##13","##14","##15","##16","##17","##18","##19" }; + + static ImGuiTableFlags flags = ImGuiTableFlags_None; + + static ImGuiWindowFlags window_flags = ImGuiWindowFlags_None; + + style->ItemSpacing = ImVec2(7.0f, 2.0f); + if (ImGui::BeginChild("ChildR", ImVec2(252, 150), true, window_flags | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() - 10.0f, ImGui::GetCursorPosY() - 10.0f)); + if (ImGui::BeginTable("split", 2, flags | ImGuiTableFlags_NoSavedSettings)) + { + for (int i = 0; i < 20; i++) + { + char buf[32]; + sprintf(buf, "%01d:", i); + ImGui::TableNextColumn(); + ImGui::Text(buf); + ImGui::SameLine(); + ImGui::Text(g_Options.models.value->arr[selectedwep].seqs[i].seq_orig_def); + + ImGui::TableNextColumn(); + + ImGui::PushItemWidth(100.0f); + + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo(ccc[i], g_Options.models.value->arr[selectedwep].seqs[g_Options.models.value->arr[selectedwep].seqs[i].seq_repl].seq_repl_def_preview)) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < 20; n++) + { + g_Options.models.value->arr[selectedwep].seqs[i].isSelected[n] = (g_Options.models.value->arr[selectedwep].seqs[i].seq_repl == n); + if (ImGui::Selectable(g_Options.models.value->arr[selectedwep].seqs[n].seq_repl_def_preview, g_Options.models.value->arr[selectedwep].seqs[i].isSelected[n], 0, ImVec2(0, 0), false)) + g_Options.models.value->arr[selectedwep].seqs[i].seq_repl = n; + if (g_Options.models.value->arr[selectedwep].seqs[i].isSelected[n]) + ImGui::SetItemDefaultFocus(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + + ImGui::PopItemWidth(); + + } + ImGui::EndTable(); + } + + ImGui::EndChild(); + } + + DisableElements(g_Options.models.value->arr[selectedwep].seq_active, 0); + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + + + ImGui::NextColumn(); + + + + static const char sss[20][6] = { "##0s","##1s","##2s","##3s","##4s","##5s","##6s","##7s","##8s","##9s","##10s", + "##11s","##12s","##13s","##14s","##15s","##16s","##17s","##18s","##19s" }; + + static const char sss1[5][6] = { "##0v","##1v","##2v","##3v","##4v" }; + static const char sss2[5][6] = { "##0p","##1p","##2p","##3p","##4p" }; + + DisableElements(selectedwep > 3 ? true : false, 1); + if (ImGui::Checkbox("Set sounds", &g_Options.models.value->arr[selectedwep].sound_active)) + { + if (g_Options.models.value->arr[selectedwep].sound_active) + *g_Options.soundhook_count += 1; + else *g_Options.soundhook_count -= 1; +#ifdef DEBUG + printf("sh count %d\n", *g_Options.soundhook_count); +#endif + + } + DisableElements(selectedwep > 3 ? true : false, 0); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + + DisableElements(g_Options.models.value->arr[selectedwep].sound_active, 1); + + + + style->ItemSpacing = ImVec2(7.0f, 2.0f); + if (ImGui::BeginChild("ChildS", ImVec2(252, 150), true, ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoScrollbar)) { + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() - 10.0f, ImGui::GetCursorPosY() - 10.0f)); + if (ImGui::BeginTable("splits", 2, ImGuiTableFlags_NoSavedSettings)) + { + for (int i = 0; i < g_Options.models.value->arr[selectedwep].soundcount; i++) + { + + ImGui::TableNextColumn(); + + + ImGui::Text(g_Options.models.value->arr[selectedwep].sounds[i].name); + + ImGui::InvisibleButton("##xz", ImVec2(0, 14.0f)); + ImGui::Text("Pitch"); + ImGui::SameLine(); + ImGui::InputInt((char*)sss2[i], &g_Options.models.value->arr[selectedwep].sounds[i].pitch, 0, 0); + + + ImGui::TableNextColumn(); + + ImGui::PushItemWidth(106.0f); + ImGui::InputText((char*)sss[i], g_Options.models.value->arr[selectedwep].sounds[i].wavpath, 255); + ImGui::PopItemWidth(); + + ImGui::Text("Volume"); + ImGui::SameLine(); + + ImGui::PushItemWidth(56.0f); + ImGui::InputFloat((char*)sss1[i], &g_Options.models.value->arr[selectedwep].sounds[i].volume, 0, 0); + + + ImGui::PopItemWidth(); + + } + ImGui::EndTable(); + } + + ImGui::EndChild(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + DisableElements(g_Options.models.value->arr[selectedwep].sound_active, 0); + + + ImGui::Columns(1, nullptr, false); + + ImGui::EndChild(); + } + + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Materials")) + { + style->ChildBorderSize = 0; style->WindowPadding = ImVec2(20.0f, 5.0f); + if (ImGui::BeginChild("ChildTab", ImVec2(665, 350), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + style->ChildBorderSize = 1; style->WindowPadding = ImVec2(20.0f, 20.0f); + + + ImGui::Columns(2, nullptr, false); + static int selectedwep = 0; + + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + + ImGui::PushItemWidth(170.0f); + + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("Item", g_Options.materials.value->arr[selectedwep].name)) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < g_Options.materials.value->itemcount; n++) + { + g_Options.materials.value->arr[n].isSelected = (selectedwep == n); + if (ImGui::Selectable(g_Options.materials.value->arr[n].name, g_Options.materials.value->arr[n].isSelected, 0, ImVec2(0, 0), false)) + selectedwep = n; + if (g_Options.materials.value->arr[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + + ImGui::PopItemWidth(); + + ImGui::SameLine(); + + if (ImGui::Checkbox("Active##S1", &g_Options.materials.value->arr[selectedwep].active)) + { + if (g_Options.materials.value->arr[selectedwep].active) + *g_Options.dmeloop_count += 1; + else *g_Options.dmeloop_count -= 1; +#ifdef DEBUG + printf("dl count %d\n", *g_Options.dmeloop_count); +#endif + } + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + + DisableElements(g_Options.materials.value->arr[selectedwep].active, 1); + + ImGui::PushItemWidth(170.0f); + ImGui::TextInputComboBox("Texture", g_Options.materials.value->arr[selectedwep].texture_temp, 255, opt.dmeitems, 0); + ImGui::PopItemWidth(); + + ImGui::SameLine(); + + if (ImGui::Button("Apply", ImVec2(70, 22))) + { + if (strstr(g_Options.materials.value->arr[selectedwep].texture_temp, "(0)")) + g_Options.materials.value->arr[selectedwep].customtextureselected = 0; + else if (strstr(g_Options.materials.value->arr[selectedwep].texture_temp, "(1)")) + g_Options.materials.value->arr[selectedwep].customtextureselected = 1; + else if (strstr(g_Options.materials.value->arr[selectedwep].texture_temp, "(2)")) + g_Options.materials.value->arr[selectedwep].customtextureselected = 2; + else if (strstr(g_Options.materials.value->arr[selectedwep].texture_temp, "(3)")) + g_Options.materials.value->arr[selectedwep].customtextureselected = 3; + else if (strstr(g_Options.materials.value->arr[selectedwep].texture_temp, "(4)")) + g_Options.materials.value->arr[selectedwep].customtextureselected = 4; + else g_Options.materials.value->arr[selectedwep].customtextureselected = -1; +#ifdef DEBUG + printf("Custom texture selected? %d\n", g_Options.materials.value->arr[selectedwep].customtextureselected); +#endif + strcpy(g_Options.materials.value->arr[selectedwep].texture, g_Options.materials.value->arr[selectedwep].texture_temp); + } + + + ImGui::NextColumn(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0f); + + if (ImGui::BeginTable("##tablexz", 2)) + { + ImGui::TableNextRow(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Checkbox("Wireframe", &g_Options.materials.value->arr[selectedwep].wireframe); + ImGui::Checkbox("Flat", &g_Options.materials.value->arr[selectedwep].flat); + ImGui::TableNextColumn(); + ImGui::Checkbox("No draw", &g_Options.materials.value->arr[selectedwep].nodraw); + ImGui::ColorEdit4("MyColor##0", (float*)&g_Options.materials.value->arr[selectedwep].coloralpha, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_AlphaBar); + ImGui::SameLine(); + ImGui::Text("Color/Alpha"); + + ImGui::EndTable(); + } + + DisableElements(g_Options.materials.value->arr[selectedwep].active, 0); + + ImGui::Columns(1, nullptr, false); + ImGui::Separator(); + + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + + static int item_current_idx = 0; + + ImGui::InputTextMultiline("KeyValue", g_Options.customtextures.value->arr[item_current_idx].keyvalue, 0x1000, ImVec2(467, 200), ImGuiInputTextFlags_AllowTabInput); + + ImGui::SameLine(); + + ImVec2 savepos = ImGui::GetCursorPos(); + + + style->ItemSpacing = ImVec2(7.0f, 2.0f); + if (ImGui::BeginListBox("Custom textures", ImVec2(98, 100))) + { + ImGui::PushFont(ifontmini); + for (int n = 0; n < 5; n++) + { + g_Options.customtextures.value->arr[n].IsSelected = (item_current_idx == n); + if (ImGui::Selectable(g_Options.customtextures.value->arr[n].Preview, g_Options.customtextures.value->arr[n].IsSelected, 0, ImVec2(0, 0), true)) + item_current_idx = n; + + if (g_Options.customtextures.value->arr[n].IsSelected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndListBox(); + ImGui::PushFont(ifont); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + + savepos.y += 130.0f; + ImGui::SetCursorPos(savepos); + + ImGui::PushItemWidth(100.0f); + ImGui::InputText("Name", g_Options.customtextures.value->arr[item_current_idx].Name, 256); + ImGui::PopItemWidth(); + + savepos.y += 40.0f; + ImGui::SetCursorPos(savepos); + + if (ImGui::Button("Apply##refresh", ImVec2(70, 22))) + { + if (g_Options.customtextures.value->arr[item_current_idx].Name[0] == 0x0 && g_Options.customtextures.value->arr[item_current_idx].keyvalue[0] == 0x0) + { + char newpreview[256] = "("; + strcat_s(newpreview, to_string(item_current_idx).c_str()); + strcat_s(newpreview, ") null"); + strcpy(g_Options.customtextures.value->arr[item_current_idx].Preview, newpreview); + g_Options.customtextures.value->arr[item_current_idx].texturelink = nullptr; + } + else + { + char newpreview[256] = "("; + strcat_s(newpreview, to_string(item_current_idx).c_str()); + strcat_s(newpreview, ") "); + strcat_s(newpreview, g_Options.customtextures.value->arr[item_current_idx].Name); + strcpy(g_Options.customtextures.value->arr[item_current_idx].Preview, newpreview); + + g_Options.customtextures.value->arr[item_current_idx].texturelink = CreateMaterial( + string(g_Options.customtextures.value->arr[item_current_idx].Name), + string(g_Options.customtextures.value->arr[item_current_idx].keyvalue)); + } + + opt.dmeitems.at(item_current_idx) = g_Options.customtextures.value->arr[item_current_idx].Preview; + + + } + + ImGui::EndChild(); + } + + ImGui::EndTabItem(); + } + + + if (ImGui::BeginTabItem("Inventory")) + { + + style->ChildBorderSize = 0; style->WindowPadding = ImVec2(20.0f, 5.0f); + if (ImGui::BeginChild("ChildTab", ImVec2(665, 350), true, ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + style->ChildBorderSize = 1; style->WindowPadding = ImVec2(20.0f, 20.0f); + + + static int selectedwep = 0; + ImGui::Text("Item"); + ImGui::SameLine(); + ImGui::PushItemWidth(390.0f); + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("##label1", g_Options.weapons.value->arr[selectedwep].name)) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < g_Options.weapons.value->weaponzcount; n++) + { + g_Options.weapons.value->arr[n].isSelected = (selectedwep == n); + if (ImGui::Selectable(g_Options.weapons.value->arr[n].name, g_Options.weapons.value->arr[n].isSelected, 0, ImVec2(0, 0), false)) + selectedwep = n; + if (g_Options.weapons.value->arr[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + ImGui::SameLine(); + + ImGui::Checkbox("Active##S1", &g_Options.weapons.value->arr[selectedwep].active); + + ImGui::SameLine(); + if (ImGui::Button("Update", ImVec2(70, 22))) { + CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)RefreshThread, &g_Options.weapons.value->arr[selectedwep].skinid, 0, 0); + } + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 10.0f); + + DisableElements(g_Options.weapons.value->arr[selectedwep].active, 1); + + ImGui::Columns(2, nullptr, false); + + style->WindowPadding = ImVec2(5.0f, 5.0f); + ImGui::PushItemWidth(252.0f); + if (ImGui::BeginCombo("Paint kit ID", opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].Preview.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + + for (int n = 0; n < opt.sc_skins.size(); n++) + { + opt.sc_skins[n].isSelected = (g_Options.weapons.value->arr[selectedwep].skinidc == n); + if (ImGui::Selectable(opt.sc_skins[n].Preview.c_str(), opt.sc_skins[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].skinidc = n; + g_Options.weapons.value->arr[selectedwep].skinid = opt.sc_skins[n].id; + + + g_Options.weapons.value->arr[selectedwep].rarity = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].rarity; + g_Options.weapons.value->arr[selectedwep].pearl = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].pearl; + g_Options.weapons.value->arr[selectedwep].color1 = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color1; + g_Options.weapons.value->arr[selectedwep].color2 = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color2; + g_Options.weapons.value->arr[selectedwep].color3 = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color3; + g_Options.weapons.value->arr[selectedwep].color4 = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color4; + } + + if (opt.sc_skins[n].isSelected) + ImGui::SetItemDefaultFocus(); + + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + ImGui::PopItemWidth(); + + + + if (ImGui::BeginTable("##table1", 2)) + { + ImGui::TableNextRow(); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::InputInt("Seed", &g_Options.weapons.value->arr[selectedwep].seed, 0); + ImGui::InputInt("StatTrak(tm)", &g_Options.weapons.value->arr[selectedwep].stattrak, 0); + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("Quality", qualities[g_Options.weapons.value->arr[selectedwep].qualityc].name.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < qualities.size(); n++) + { + qualities[n].isSelected = (g_Options.weapons.value->arr[selectedwep].quality == qualities[n].defindex); + if (ImGui::Selectable(qualities[n].name.c_str(), qualities[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].qualityc = n; + g_Options.weapons.value->arr[selectedwep].quality = qualities[n].defindex; + } + + if (qualities[n].isSelected) + { + ImGui::SetItemDefaultFocus(); + } + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + + + ImGui::TableNextColumn(); + + float thisy = ImGui::GetCursorPosY(); + ImGui::SetCursorPosY(thisy - 20.0f); + ImGui::Text("Custom colors"); + ImGui::SetCursorPosY(thisy); + + float3 color1 = colorConverter(opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color1); + if (ImGui::ColorEdit3("##Custom colors", (float*)&color1, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf)) + { + int color1int = 0xFF000000 + ((int)(color1.b * 255) << 16) | ((int)(color1.g * 255) << 8) | (int)(color1.r * 255); + opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color1 = color1int; + CPaintKit* pk = (CPaintKit*)opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].link; + pk->color1 = color1int; + g_Options.weapons.value->arr[selectedwep].color1 = color1int; + } + ImGui::SameLine(); + float3 color2 = colorConverter(opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color2); + if (ImGui::ColorEdit3("##Color2", (float*)&color2, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf)) + { + int color2int = 0xFF000000 + ((int)(color2.b * 255) << 16) | ((int)(color2.g * 255) << 8) | (int)(color2.r * 255); + opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color2 = color2int; + CPaintKit* pk = (CPaintKit*)opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].link; + pk->color2 = color2int; + g_Options.weapons.value->arr[selectedwep].color2 = color2int; + } + ImGui::SameLine(); + float3 color3 = colorConverter(opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color3); + if (ImGui::ColorEdit3("##Color3", (float*)&color3, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf)) + { + int color3int = 0xFF000000 + ((int)(color3.b * 255) << 16) | ((int)(color3.g * 255) << 8) | (int)(color3.r * 255); + opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color3 = color3int; + CPaintKit* pk = (CPaintKit*)opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].link; + pk->color3 = color3int; + g_Options.weapons.value->arr[selectedwep].color3 = color3int; + } + ImGui::SameLine(); + float3 color4 = colorConverter(opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color4); + if (ImGui::ColorEdit3("##Color4", (float*)&color4, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf)) + { + int color4int = 0xFF000000 + ((int)(color4.b * 255) << 16) | ((int)(color4.g * 255) << 8) | (int)(color4.r * 255); + opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].color4 = color4int; + CPaintKit* pk = (CPaintKit*)opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].link; + pk->color4 = color4int; + g_Options.weapons.value->arr[selectedwep].color4 = color4int; + } + ImGui::Checkbox("Freeze count", &g_Options.weapons.value->arr[selectedwep].ownerunk); + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("Rarity", rarities[opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].rarity].name.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < rarities.size(); n++) + { + rarities[n].isSelected = (opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].rarity == rarities[n].defindex); + if (ImGui::Selectable(rarities[n].name.c_str(), rarities[n].isSelected, 0, ImVec2(0, 0), false)) + { + opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].rarity = rarities[n].defindex; + CPaintKit* pk = (CPaintKit*)opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].link; + pk->rarity = rarities[n].defindex; + g_Options.weapons.value->arr[selectedwep].rarity = rarities[n].defindex; + } + + if (rarities[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + + + + ImGui::EndTable(); + + } + + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 5.0f); + + ImGui::PushItemWidth(252.0f); + ImGui::SliderFloat("Wear", &g_Options.weapons.value->arr[selectedwep].wear, 0.0f, 1.0f); + if (ImGui::SliderFloat("Pearlescent", &opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].pearl, 0.0f, 255.0f)) + { + CPaintKit* pk = (CPaintKit*)opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].link; + pk->pearlescent = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].pearl; + g_Options.weapons.value->arr[selectedwep].pearl = opt.sc_skins[g_Options.weapons.value->arr[selectedwep].skinidc].pearl; + } + ImGui::PopItemWidth(); + + + if (ImGui::BeginTable("##table3", 2)) + { + ImGui::TableNextRow(); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + style->WindowPadding = ImVec2(5.0f, 5.0f); + + bool disabledDefIndex = (selectedwep > 5) && (selectedwep < (g_Options.weapons.value->weaponzcount - 1)) ? false : true; + bool disabledKFIcon = ((selectedwep > 0) && (selectedwep < 6)) || (selectedwep == g_Options.weapons.value->weaponzcount - 1) ? false : true; + + DisableElements(disabledDefIndex, 1); + + + if (selectedwep == 0) { + if (ImGui::BeginCombo("Definition", knives[g_Options.weapons.value->arr[selectedwep].modelcount].Preview.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + + for (int n = 0; n < knives.size(); n++) + { + knives[n].isSelected = (g_Options.weapons.value->arr[selectedwep].modelcount == n); + if (ImGui::Selectable(knives[n].Preview.c_str(), knives[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].modelcount = n; + g_Options.weapons.value->arr[selectedwep].modeldefindex = knives[n].defindex; + strcpy(g_Options.weapons.value->arr[selectedwep].model, knives[n].viewmodel.c_str()); + strcpy(g_Options.weapons.value->arr[selectedwep].worldmodel, knives[n].worldmodel.c_str()); + + } + + if (knives[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + } + else if (selectedwep == 1) + { + if (ImGui::BeginCombo("Definition", gloves[g_Options.weapons.value->arr[selectedwep].modelcount].Preview.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < gloves.size(); n++) + { + gloves[n].isSelected = (g_Options.weapons.value->arr[selectedwep].modelcount == n); + if (ImGui::Selectable(gloves[n].Preview.c_str(), gloves[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].modelcount = n; + g_Options.weapons.value->arr[selectedwep].modeldefindex = gloves[n].defindex; + strcpy(g_Options.weapons.value->arr[selectedwep].model, gloves[n].viewmodel.c_str()); + strcpy(g_Options.weapons.value->arr[selectedwep].worldmodel, gloves[n].worldmodel.c_str()); + } + if (gloves[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + } + else if (selectedwep == 2 || selectedwep == 3) + { + if (ImGui::BeginCombo("Definition", agents[g_Options.weapons.value->arr[selectedwep].modelcount].Preview.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < agents.size(); n++) + { + agents[n].isSelected = (g_Options.weapons.value->arr[selectedwep].modelcount == n); + if (ImGui::Selectable(agents[n].Preview.c_str(), agents[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].modelcount = n; + g_Options.weapons.value->arr[selectedwep].modeldefindex = agents[n].defindex; + strcpy(g_Options.weapons.value->arr[selectedwep].model, agents[n].viewmodel.c_str()); + + } + if (agents[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + } + + else if (selectedwep == 4) + { + if (ImGui::BeginCombo("Definition", medals[g_Options.weapons.value->arr[selectedwep].modelcount].Preview.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < medals.size(); n++) + { + medals[n].isSelected = (g_Options.weapons.value->arr[selectedwep].modelcount == n); + if (ImGui::Selectable(medals[n].Preview.c_str(), medals[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].modelcount = n; + g_Options.weapons.value->arr[selectedwep].modeldefindex = medals[n].defindex; + } + if (medals[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + } + else if (selectedwep == 5) + { + if (ImGui::BeginCombo("Definition", musickits[g_Options.weapons.value->arr[selectedwep].modelcount].Preview.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < musickits.size(); n++) + { + musickits[n].isSelected = (g_Options.weapons.value->arr[selectedwep].modelcount == n); + if (ImGui::Selectable(musickits[n].Preview.c_str(), musickits[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].modelcount = n; + g_Options.weapons.value->arr[selectedwep].modeldefindex = musickits[n].defindex; + + } + if (musickits[n].isSelected) + ImGui::SetItemDefaultFocus(); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + } + else if (selectedwep == (g_Options.weapons.value->weaponzcount - 1)) + { + if (ImGui::InputInt("Definition", &g_Options.weapons.value->arr[selectedwep].defindex, 0, 0)) + g_Options.weapons.value->arr[selectedwep].modeldefindex = g_Options.weapons.value->arr[selectedwep].defindex; + } + else + { + ImGui::BeginCombo("Definition", "Disabled"); + ImGui::EndCombo; + } + + style->WindowPadding = ImVec2(20.f, 20.0f); + + DisableElements(disabledDefIndex, 0); + + + ImGui::TableNextColumn(); + + + DisableElements(disabledKFIcon, 1); + + + + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("Killfeed icon", g_Options.weapons.value->arr[selectedwep].killfeediconreplace)) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < opt.killfeedicons.size(); n++) + { + if (ImGui::Selectable(opt.killfeedicons[n].c_str(), false, 0, ImVec2(0, 0), false)) + { + strcpy(g_Options.weapons.value->arr[selectedwep].killfeediconreplace, opt.killfeedicons[n].c_str()); + if (n > 0) + g_Options.weapons.value->arr[selectedwep].killfeediconactive = 1; + else + g_Options.weapons.value->arr[selectedwep].killfeediconactive = 0; + } + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + + + + + + + + + + + + + + + + DisableElements(disabledKFIcon, 0); + + ImGui::EndTable(); + } + + + ImGui::NextColumn(); + + + static int stickerselected = 0; + style->ItemSpacing = ImVec2(7.0f, 2.0f); + if (ImGui::BeginListBox("Stickers##lb", ImVec2(251.0f, 5 * ImGui::GetTextLineHeightWithSpacing()))) + { + ImGui::PushFont(ifontmini); + for (int n = 0; n < 5; n++) + { + g_Options.weapons.value->arr[selectedwep].stickers[n].isselected = (stickerselected == n); + if (ImGui::Selectable(g_Options.weapons.value->arr[selectedwep].stickers[n].name, + g_Options.weapons.value->arr[selectedwep].stickers[n].isselected, 0, ImVec2(0, 0), true)) { + stickerselected = n; + } + + if (g_Options.weapons.value->arr[selectedwep].stickers[n].isselected) + ImGui::SetItemDefaultFocus(); + } + ImGui::PushFont(ifont); + ImGui::EndListBox(); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + + ImGui::InvisibleButton("##invisfuckyou", ImVec2(0, 10.0f)); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 5.0f); + + style->WindowPadding = ImVec2(5.0f, 5.0f); + ImGui::PushItemWidth(252.0f); + + if (ImGui::BeginCombo("Sticker ID", opt.sc_stickers[g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].stickerc].Preview.c_str())) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + + for (int n = 0; n < opt.sc_stickers.size(); n++) + { + opt.sc_stickers[n].isSelected = (g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].stickerc == n); + if (ImGui::Selectable(opt.sc_stickers[n].Preview.c_str(), opt.sc_stickers[n].isSelected, 0, ImVec2(0, 0), false)) + { + g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].stickerc = n; + g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].stickerid = opt.sc_stickers[n].id; + + char newname[64] = "("; + strcat_s(newname, to_string(stickerselected).c_str()); + strcat_s(newname, ") "); + strcat_s(newname, opt.sc_stickers[g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].stickerc].Name.c_str()); + + strcpy(g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].name, + newname); + } + if (opt.sc_stickers[n].isSelected) + ImGui::SetItemDefaultFocus(); + + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + ImGui::PopItemWidth(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 7.0f); + + + ImGui::PushItemWidth(252.0f); + ImGui::SliderFloat("Wear##st", &g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].wear, 0, 1.0f); + ImGui::SliderFloat("Scale##st", &g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].scale, 2.0f, 0.0f); + ImGui::SliderFloat("Rotation##st", &g_Options.weapons.value->arr[selectedwep].stickers[stickerselected].rotation, 0, 360.0f); + ImGui::PopItemWidth(); + + if (ImGui::BeginTable("##table5", 2)) + { + ImGui::TableNextRow(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::InputText("Name tag", g_Options.weapons.value->arr[selectedwep].nametag, 32); + ImGui::TableNextColumn(); + ImGui::InputText("Desc tag", g_Options.weapons.value->arr[selectedwep].desctag, 32); + + ImGui::EndTable(); + } + + ImGui::Columns(1, nullptr, false); + + DisableElements(g_Options.weapons.value->arr[selectedwep].active, 0); + + ImGui::EndChild(); + } + + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Profile")) + { + style->ChildBorderSize = 0; style->WindowPadding = ImVec2(20.0f, 5.0f); + if (ImGui::BeginChild("ChildTab", ImVec2(665, 350), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + style->ChildBorderSize = 1; style->WindowPadding = ImVec2(20.0f, 20.0f); + + + if (ImGui::BeginTable("##tablexz", 4)) + { + ImGui::TableNextRow(); ImGui::TableNextRow(); + + ImGui::TableNextRow(); ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 20.0f); + ImGui::TextInputComboBox("Name", g_Options.playername.value->mystring, 1024, opt.names, 0); + ImGui::InputText("Clan tag", g_Options.playerclan.value->mystring, 1024); + + DisableElements(*g_Options.discmsg_active, 1); + ImGui::InputText("Disconnect msg", g_Options.discmsg.value->mystring, 1024); + DisableElements(*g_Options.discmsg_active, 0); + + ImGui::TableNextColumn(); + if (ImGui::Button("Apply##name", ImVec2(70, 22))) + { + ConVar* nameConvar = iff.g_pCVar->FindVar("name"); + *(int*)((DWORD)&nameConvar->m_fnChangeCallbacks + 0xC) = 0; + nameConvar->SetValue(MakeControlChars(g_Options.playername.value->mystring)); + } + + if (ImGui::Button("Apply##clan", ImVec2(70, 22))) + { + char* newclan = MakeControlChars(g_Options.playerclan.value->mystring); + static auto fnClantagChanged = (int(__fastcall*)(const char*, const char*))FindPatternV2("engine.dll", "53 56 57 8B DA 8B F9 FF 15"); + fnClantagChanged(newclan, newclan); + } + + ImGui::Checkbox("Active##discmsg", g_Options.discmsg_active); + + ImGui::TableNextColumn(); + + ImGui::Checkbox("Set score", g_Options.fakescore); + + + DisableElements(g_Options.fakescore, 1); + + ImGui::InputInt("Score", g_Options.score, 0); + ImGui::InputInt("MVPs", g_Options.MVPs, 0); + + ImGui::TableNextColumn(); + + ImGui::InputInt("Kills", g_Options.kills, 0); + ImGui::InputInt("Assists", g_Options.assists, 0); + ImGui::InputInt("Deaths", g_Options.deaths, 0); + + DisableElements(g_Options.fakescore, 0); + + ImGui::EndTable(); + } + + + + ImGui::Separator(); + + + if (ImGui::BeginTable("##tablexz", 4)) + { + ImGui::TableNextRow(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Checkbox("Set MM info", g_Options.profile_active); + ImGui::TableNextColumn(); + if (ImGui::Button("Update##ranks", ImVec2(70, 22))) + { + g_Options.rankz.value->selectedrank = 2; + ProtoFeatures.SendMatchmakingClient2GCHello(); + ProtoFeatures.SendClientGcRankUpdate(); + } + ImGui::EndTable(); + } + + DisableElements(g_Options.profile_active, 1); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 10.0f); + + if (ImGui::BeginTable("##tablexz", 4)) + { + ImGui::TableNextRow(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + static int selectedrank_this = 0; + style->WindowPadding = ImVec2(5.0f, 5.0f); + if (ImGui::BeginCombo("Rank Type", g_Options.rankz.value->arr[selectedrank_this].Name)) + { + ImGui::PushFont(ifontmini); + style->ItemSpacing = ImVec2(7.0f, 2.0f); + for (int n = 0; n < 3; n++) + { + if (ImGui::Selectable(g_Options.rankz.value->arr[n].Name, g_Options.rankz.value->arr[n].isselected, 0, ImVec2(0, 0), false)) + selectedrank_this = n; + + if (g_Options.rankz.value->arr[n].isselected) + ImGui::SetItemDefaultFocus(); + } + style->ItemSpacing = ImVec2(7.0f, 15.0f); + ImGui::PushFont(ifont); + ImGui::EndCombo(); + } + style->WindowPadding = ImVec2(20.f, 20.0f); + + ImGui::InputInt("Rank", &g_Options.rankz.value->arr[selectedrank_this].rank, 0); + ImGui::InputInt("Wins", &g_Options.rankz.value->arr[selectedrank_this].wins, 0); + + ImGui::TableNextColumn(); + + DisableElements(0, 1); + if (ImGui::Checkbox("Prime (unavailable)", g_Options.prime)) + { + if (g_Options.prime) + { + DWORD old_protect; + VirtualProtect(iff.prime, 5, PAGE_EXECUTE_READWRITE, &old_protect); + char patch[] = { 0x31, 0xC0, 0xFE, 0xC0, 0xC3 }; + memcpy(iff.prime, patch, 5); + VirtualProtect(iff.prime, 5, old_protect, nullptr); + } + else + { + DWORD old_protect; + VirtualProtect(iff.prime, 5, PAGE_EXECUTE_READWRITE, &old_protect); + memcpy(iff.prime, iff.oldprime, 5); + VirtualProtect(iff.prime, 5, old_protect, nullptr); + } + } + DisableElements(0, 0); + + ImGui::InputInt("level", g_Options.level, 0); + ImGui::InputInt("XP", g_Options.xp, 0); + + ImGui::TableNextColumn(); + + ImGui::InputInt("Leader", g_Options.comleader, 0); + ImGui::InputInt("Teacher", g_Options.comteacher, 0); + ImGui::InputInt("Friendly", g_Options.comfriendly, 0); + + ImGui::TableNextColumn(); + + ImGui::Checkbox("VAC ban", g_Options.vacban); + ImGui::InputInt("Ban reason", g_Options.banreason, 0); + ImGui::InputInt("Ban duration", g_Options.banduration, 0); + + DisableElements(g_Options.profile_active, 0); + ImGui::EndTable(); + } + + + ImGui::EndChild(); + } + + ImGui::EndTabItem(); + + } + + if (ImGui::BeginTabItem("About")) + { + static ImVec4 colwhite = { 0.8f, 0.8f, 0.8f, 1.0f }; + + style->ChildBorderSize = 0; style->WindowPadding = ImVec2(20.0f, 5.0f); + if (ImGui::BeginChild("ChildTab", ImVec2(665, 350), true, ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysUseWindowPadding)) { + style->ChildBorderSize = 1; style->WindowPadding = ImVec2(20.0f, 20.0f); + + ImGui::Columns(2, nullptr, false); + + ImGui::TextColored(colwhite, XorStr("Seaside")); + ImGui::Text(XorStr("Build 21/06/16")); + ImGui::InvisibleButton("##inv", ImVec2(0, 0)); + ImGui::TextColored(colwhite, XorStr("Developer")); + ImGui::Text(XorStr("0TheSpy")); + ImGui::InvisibleButton("##inv", ImVec2(0, 0)); + ImGui::TextColored(colwhite, XorStr("Check for updates")); + ImGui::Text(XorStr("unknowncheats.me")); + + + ImGui::NextColumn(); + + if (ImGui::BeginTable("##tablexz", 2)) + { + ImGui::TableNextRow(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + if (ImGui::Button("Save", ImVec2(70, 22))) + Config::Get().Save(); + + if (ImGui::Checkbox("Load config on startup", &opt.autoload)) + { + if (opt.autoload) + { + ofstream autoload; + autoload.open("seaside_autoload"); + autoload.close(); + } + else + { + if (remove("seaside_autoload") != 0) + perror("Error deleting file"); + else + puts("File successfully deleted"); + } + } + + ImGui::TableNextColumn(); + + if (ImGui::Button("Load", ImVec2(70, 22))) + Config::Get().Load(); + + if (ImGui::Button("Unhook", ImVec2(70, 22))) + opt.unhook = true; + + ImGui::EndTable(); + } + ImGui::Columns(1, nullptr, false); + + ImGui::InvisibleButton("##inv", ImVec2(0, 30.0f)); + ImGui::TextColored(colwhite, " Author does not take any responsibility for bans caused by this software"); + ImGui::TextColored(colwhite, " Please use VAC Bypass for better protection"); + + ImGui::EndChild(); + } + + + ImGui::EndTabItem(); + } + + ImGui::EndTabBar(); + + + ImGui::End(); + + ImGui::EndFrame(); + ImGui::Render(); + ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); + } + + + + if (*g_Options.hitmarker && iff.g_pEngineClient->IsInGame()) { + iff.g_pDebugOverlay->ClearAllOverlays(); + for (int i = 0; i < bulletdata.size(); i++) { + Vector pos = bulletdata[i].pos; + float delta = bulletdata[i].time - bulletdata[i].curtime; + pos.z += delta * 35; + int alpha = 255; + if (bulletdata[i].time >= bulletdata[i].curtime + 0.70f) + alpha = int(850.0f * (-(delta - 1.0f))); + if (alpha < 0) alpha = 0; + if (!bulletdata[i].hs) + iff.g_pDebugOverlay->AddTextOverlayRGB(pos, 0, 0.09, 255, 50, 50, alpha, std::to_string(bulletdata[i].dmg).c_str()); + else + iff.g_pDebugOverlay->AddTextOverlayRGB(pos, 0, 0.09, 0, 255, 0, alpha, std::to_string(bulletdata[i].dmg).c_str()); + if (delta >= 1.000f) + bulletdata.erase(bulletdata.begin() + i); + bulletdata[i].time += iff.g_pGlobals->curtime - bulletdata[i].time; + } + } + + + + + return oEndScene(pDevice); +} diff --git a/SpyCustom/MenuItem.h b/SpyCustom/MenuItem.h new file mode 100644 index 0000000..aef2cbb --- /dev/null +++ b/SpyCustom/MenuItem.h @@ -0,0 +1,107 @@ +#ifndef MENUITEM_H +#define MENUITEM_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "VGUI.h" +#include "Button.h" +#include "Menu.h" + +namespace vgui +{ + + class IBorder; + class TextImage; + class Menu; + class Image; + + class MenuItem : public Button + { + DECLARE_CLASS_SIMPLE(MenuItem, Button); + + public: + MenuItem(Menu* parent, const char* panelName, const char* text, Menu* cascadeMenu = NULL, bool checkable = false); + MenuItem(Menu* parent, const char* panelName, const wchar_t* wszText, Menu* cascadeMenu = NULL, bool checkable = false); + ~MenuItem(); + + virtual void Paint(); + + virtual void FireActionSignal(); + + virtual bool CanBeDefaultButton(void); + + void OnCursorEntered(); + void OnCursorExited(); + + void CloseCascadeMenu(); + + MESSAGE_FUNC(OnKillFocus, "MenuClose"); + + bool HasMenu(); + + void SetTextImageSize(int wide, int tall); + + void GetTextImageSize(int& wide, int& tall); + + void GetArrowImageSize(int& wide, int& tall); + + void GetCheckImageSize(int& wide, int& tall); + + Menu* GetMenu(); + + virtual void PerformLayout(); + + void OnCursorMoved(int x, int y); + + MESSAGE_FUNC(ArmItem, "ArmItem"); + MESSAGE_FUNC(DisarmItem, "DisarmItem"); + + bool IsItemArmed(); + + void OpenCascadeMenu(); + + bool IsCheckable(); + bool IsChecked(); + + void SetChecked(bool state); + + KeyValues* GetUserData(); + void SetUserData(const KeyValues* kv); + + int GetActiveItem() { if (m_pCascadeMenu) { return m_pCascadeMenu->GetActiveItem(); } else { return 0; } } + + Menu* GetParentMenu(); + + void SetCurrentKeyBinding(char const* keyName); + + virtual void GetContentSize(int& cw, int& ch); + + protected: + void OnKeyCodeReleased(KeyCode code); + void OnMenuClose(); + MESSAGE_FUNC(OnKeyModeSet, "KeyModeSet"); + + virtual void Init(void); + virtual void ApplySchemeSettings(IScheme* pScheme); + virtual IBorder* GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); + + private: + enum { CHECK_INSET = 6 }; + Menu* m_pCascadeMenu; + bool m_bCheckable; + bool m_bChecked; + TextImage* m_pCascadeArrow; + Image* m_pCheck; + TextImage* m_pBlankCheck; + + TextImage* m_pCurrentKeyBinding; + + KeyValues* m_pUserData; + + }; + +} + +#endif \ No newline at end of file diff --git a/SpyCustom/MessageMap.h b/SpyCustom/MessageMap.h new file mode 100644 index 0000000..9555f56 --- /dev/null +++ b/SpyCustom/MessageMap.h @@ -0,0 +1,327 @@ +#ifndef MESSAGEMAP_H +#define MESSAGEMAP_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "dmxelement.h" + +#pragma pointers_to_members( full_generality, virtual_inheritance ) + +namespace vgui +{ + + +#ifndef ARRAYSIZE +#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) +#endif + + + enum DataType_t + { + DATATYPE_VOID, + DATATYPE_CONSTCHARPTR, + DATATYPE_INT, + DATATYPE_FLOAT, + DATATYPE_PTR, + DATATYPE_BOOL, + DATATYPE_KEYVALUES, + DATATYPE_CONSTWCHARPTR, + DATATYPE_UINT64, + DATATYPE_HANDLE, + }; + + class Panel; + typedef uintp VPANEL; + + typedef void (Panel::* MessageFunc_t)(void); + +#pragma warning(disable:4121) + struct MessageMapItem_t + { + const char* name; + ALIGN16 MessageFunc_t func; + + int numParams; + + DataType_t firstParamType; + const char* firstParamName; + + DataType_t secondParamType; + const char* secondParamName; + + int nameSymbol; + int firstParamSymbol; + int secondParamSymbol; + }; + +#define DECLARE_PANELMESSAGEMAP( className ) \ + static void AddToMap( char const *scriptname, vgui::MessageFunc_t function, int paramCount, int p1type, const char *p1name, int p2type, const char *p2name ) \ + { \ + vgui::PanelMessageMap *map = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ + \ + vgui::MessageMapItem_t entry; \ + entry.name = scriptname; \ + entry.func = function; \ + entry.numParams = paramCount; \ + entry.firstParamType = (vgui::DataType_t)p1type; \ + entry.firstParamName = p1name; \ + entry.secondParamType = (vgui::DataType_t)p2type; \ + entry.secondParamName = p2name; \ + entry.nameSymbol = 0; \ + entry.firstParamSymbol = 0; \ + entry.secondParamSymbol = 0; \ + \ + map->entries.AddToTail( entry ); \ + } \ + \ + static void ChainToMap( void ) \ + { \ + static bool chained = false; \ + if ( chained ) \ + return; \ + chained = true; \ + vgui::PanelMessageMap *map = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ + map->pfnClassName = &GetPanelClassName; \ + if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ + { \ + map->baseMap = vgui::FindOrAddPanelMessageMap( GetPanelBaseClassName() ); \ + } \ + } \ + \ + class className##_RegisterMap; \ + friend class className##_RegisterMap; \ + class className##_RegisterMap \ + { \ + public: \ + className##_RegisterMap() \ + { \ + className::ChainToMap(); \ + } \ + }; \ + className##_RegisterMap m_RegisterClass; \ + \ + virtual vgui::PanelMessageMap *GetMessageMap() \ + { \ + static vgui::PanelMessageMap *s_pMap = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ + return s_pMap; \ + } + +#define VGUI_USEKEYBINDINGMAPS 1 + +#if defined( VGUI_USEKEYBINDINGMAPS ) + +#define DECLARE_CLASS_SIMPLE( className, baseClassName ) \ + typedef baseClassName BaseClass; \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + DECLARE_KEYBINDINGMAP( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return #baseClassName; } + +#define DECLARE_CLASS_SIMPLE_NOBASE( className ) \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + DECLARE_KEYBINDINGMAP( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return NULL; } + +#else + +#define DECLARE_CLASS_SIMPLE( className, baseClassName ) \ + typedef baseClassName BaseClass; \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return #baseClassName; } + +#define DECLARE_CLASS_SIMPLE_NOBASE( className ) \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return NULL; } + +#endif + +#define _MessageFuncCommon( name, scriptname, paramCount, p1type, p1name, p2type, p2name ) \ + class PanelMessageFunc_##name; \ + friend class PanelMessageFunc_##name; \ + class PanelMessageFunc_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + AddToMap( scriptname, (vgui::MessageFunc_t)&ThisClass::name, paramCount, p1type, p1name, p2type, p2name ); \ + } \ + } \ + PanelMessageFunc_##name() \ + { \ + PanelMessageFunc_##name::InitVar(); \ + } \ + }; \ + PanelMessageFunc_##name m_##name##_register; \ + +#define MESSAGE_FUNC( name, scriptname ) _MessageFuncCommon( name, scriptname, 0, 0, 0, 0, 0 ); virtual void name( void ) + +#define MESSAGE_FUNC_INT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); virtual void name( int p1 ) +#define MESSAGE_FUNC_UINT64( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_UINT64, #p1, 0, 0 ); virtual void name( uint64 p1 ) +#define MESSAGE_FUNC_PTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_PTR, #p1, 0, 0 ); virtual void name( vgui::Panel *p1 ) +#define MESSAGE_FUNC_HANDLE( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_HANDLE, #p1, 0, 0 ); virtual void name( vgui::VPANEL p1 ) +#define MESSAGE_FUNC_FLOAT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_FLOAT, #p1, 0, 0 ); virtual void name( float p1 ) +#define MESSAGE_FUNC_CHARPTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_CONSTCHARPTR, #p1, 0, 0 ); virtual void name( const char *p1 ) +#define MESSAGE_FUNC_WCHARPTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_CONSTWCHARPTR, #p1, 0, 0 ); virtual void name( const wchar_t *p1 ) + +#define MESSAGE_FUNC_INT_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( int p1, int p2 ) +#define MESSAGE_FUNC_PTR_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( vgui::Panel *p1, int p2 ) +#define MESSAGE_FUNC_HANDLE_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( vgui::VPANEL p1, int p2 ) +#define MESSAGE_FUNC_ENUM_ENUM( name, scriptname, t1, p1, t2, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_PTR, #p2 ); virtual void name( t1 p1, t2 p2 ) +#define MESSAGE_FUNC_INT_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( int p1, const char *p2 ) +#define MESSAGE_FUNC_PTR_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( vgui::Panel *p1, const char *p2 ) +#define MESSAGE_FUNC_HANDLE_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( vgui::VPANEL p1, const char *p2 ) +#define MESSAGE_FUNC_PTR_WCHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_CONSTWCHARPTR, #p2 ); virtual void name( vgui::Panel *p1, const wchar_t *p2 ) +#define MESSAGE_FUNC_HANDLE_WCHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_CONSTWCHARPTR, #p2 ); virtual void name( vgui::VPANEL p1, const wchar_t *p2 ) +#define MESSAGE_FUNC_CHARPTR_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_CONSTCHARPTR, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( const char *p1, const char *p2 ) + +#define MESSAGE_FUNC_PARAMS( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_KEYVALUES, NULL, 0, 0 ); virtual void name( KeyValues *p1 ) + +#define MESSAGE_FUNC_NV( name, scriptname ) _MessageFuncCommon( name, scriptname, 0, 0, 0, 0, 0 ); void name( void ) +#define MESSAGE_FUNC_NV_INT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); void name( int p1 ) +#define MESSAGE_FUNC_NV_INT_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); void name( int p1, int p2 ) + + + struct PanelMessageMap + { + PanelMessageMap() + { + baseMap = NULL; + pfnClassName = NULL; + processed = false; + } + + CUtlVector< MessageMapItem_t > entries; + bool processed; + PanelMessageMap* baseMap; + char const* (*pfnClassName)(void); + }; + + PanelMessageMap* FindPanelMessageMap(char const* className); + PanelMessageMap* FindOrAddPanelMessageMap(char const* className); + + + +#define MAP_MESSAGE( type, name, func ) { name, (vgui::MessageFunc_t)(&type::func), 0 } + +#define MAP_MESSAGE_PARAMS( type, name, func ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_KEYVALUES, NULL } + +#define MAP_MESSAGE_PTR( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_PTR, param1 } +#define MAP_MESSAGE_INT( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_INT, param1 } +#define MAP_MESSAGE_BOOL( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_BOOL, param1 } +#define MAP_MESSAGE_FLOAT( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_FLOAT, param1 } +#define MAP_MESSAGE_PTR( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_PTR, param1 } +#define MAP_MESSAGE_CONSTCHARPTR( type, name, func, param1) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_CONSTCHARPTR, param1 } +#define MAP_MESSAGE_CONSTWCHARPTR( type, name, func, param1) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_CONSTWCHARPTR, param1 } + +#define MAP_MESSAGE_INT_INT( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_INT, param1, vgui::DATATYPE_INT, param2 } +#define MAP_MESSAGE_PTR_INT( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_INT, param2 } +#define MAP_MESSAGE_INT_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_INT, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } +#define MAP_MESSAGE_PTR_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } +#define MAP_MESSAGE_PTR_CONSTWCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_CONSTWCHARPTR, param2 } +#define MAP_MESSAGE_CONSTCHARPTR_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_CONSTCHARPTR, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } + + + struct PanelMap_t + { + MessageMapItem_t* dataDesc; + int dataNumFields; + const char* dataClassName; + PanelMap_t* baseMap; + int processed; + }; + +#define DECLARE_PANELMAP() \ + static vgui::PanelMap_t m_PanelMap; \ + static vgui::MessageMapItem_t m_MessageMap[]; \ + virtual vgui::PanelMap_t *GetPanelMap( void ); + +#define IMPLEMENT_PANELMAP( derivedClass, baseClass ) \ + vgui::PanelMap_t derivedClass::m_PanelMap = { derivedClass::m_MessageMap, ARRAYSIZE(derivedClass::m_MessageMap), #derivedClass, &baseClass::m_PanelMap }; \ + vgui::PanelMap_t *derivedClass::GetPanelMap( void ) { return &m_PanelMap; } + + typedef vgui::Panel* (*PANELCREATEFUNC)(void); + + class CBuildFactoryHelper + { + public: + static CBuildFactoryHelper* m_sHelpers; + + public: + CBuildFactoryHelper(char const* className, PANELCREATEFUNC func); + + CBuildFactoryHelper* GetNext(void); + + char const* GetClassName() const; + + vgui::Panel* CreatePanel(); + + static vgui::Panel* InstancePanel(char const* className); + static void GetFactoryNames(CUtlVector< char const* >& list); + + static CDmxElement* CreatePanelDmxElement(vgui::Panel* pPanel); + static Panel* UnserializeDmxElementPanel(CDmxElement* pElement); + + static bool Serialize(CUtlBuffer& buf, vgui::Panel* pPanel); + static bool Unserialize(Panel** ppPanel, CUtlBuffer& buf, const char* pFileName = NULL); + + + private: + + static bool HasFactory(char const* className); + + CBuildFactoryHelper* m_pNext; + + int m_Type; + PANELCREATEFUNC m_CreateFunc; + char const* m_pClassName; + }; + +#define DECLARE_BUILD_FACTORY( className ) \ + static vgui::Panel *Create_##className( void ) \ + { \ + return new className( NULL, NULL ); \ + }; \ + static vgui::CBuildFactoryHelper g_##className##_Helper( #className, Create_##className );\ + className *g_##className##LinkerHack = NULL; + +#define DECLARE_BUILD_FACTORY_DEFAULT_TEXT( className, defaultText ) \ + static vgui::Panel *Create_##className( void ) \ + { \ + return new className( NULL, NULL, #defaultText ); \ + }; \ + static vgui::CBuildFactoryHelper g_##className##_Helper( #className, Create_##className );\ + className *g_##className##LinkerHack = NULL; + +#define DECLARE_BUILD_FACTORY_CUSTOM( className, createFunc ) \ + static vgui::CBuildFactoryHelper g_##className##_Helper( #className, createFunc );\ + className *g_##className##LinkerHack = NULL; + +#define DECLARE_BUILD_FACTORY_CUSTOM_ALIAS( className, factoryName, createFunc ) \ + static vgui::CBuildFactoryHelper g_##factoryName##_Helper( #factoryName, createFunc );\ + className *g_##factoryName##LinkerHack = NULL; + +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/MouseCode.h b/SpyCustom/MouseCode.h new file mode 100644 index 0000000..feb02ac --- /dev/null +++ b/SpyCustom/MouseCode.h @@ -0,0 +1,15 @@ +#ifndef MOUSECODE_H +#define MOUSECODE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "ButtonCode.h" + +namespace vgui +{ + typedef ButtonCode_t MouseCode; +} + +#endif \ No newline at end of file diff --git a/SpyCustom/NetVarManager.cpp b/SpyCustom/NetVarManager.cpp new file mode 100644 index 0000000..49ce527 --- /dev/null +++ b/SpyCustom/NetVarManager.cpp @@ -0,0 +1,57 @@ +#include "NetVarManager.hpp" +#include + +#ifdef DUMP_NETVARS +#define IF_DUMPING(...) __VA_ARGS__ +#else +#define IF_DUMPING(...) +#endif + +IF_DUMPING(static FILE* s_fp;) + +netvar_manager::netvar_manager() +{ + IF_DUMPING(fopen_s(&s_fp, "netvar_dump.txt", "w");) + for (auto clazz = iff.g_pClient->GetAllClasses(); clazz; clazz = clazz->m_pNext) + if (clazz->m_pRecvTable) + dump_recursive(clazz->m_pNetworkName, clazz->m_pRecvTable, 0); + IF_DUMPING(fclose(s_fp);) +} + +auto netvar_manager::dump_recursive(const char* base_class, RecvTable* table, const std::uint16_t offset) -> void +{ + for (auto i = 0; i < table->m_nProps; ++i) + { + const auto prop_ptr = &table->m_pProps[i]; + + if (!prop_ptr || isdigit(prop_ptr->m_pVarName[0])) + continue; + + if (fnv::hash_runtime(prop_ptr->m_pVarName) == FNV("baseclass")) + continue; + + if (prop_ptr->m_RecvType == DPT_DataTable && + prop_ptr->m_pDataTable != nullptr && + prop_ptr->m_pDataTable->m_pNetTableName[0] == 'D') + { + dump_recursive(base_class, prop_ptr->m_pDataTable, std::uint16_t(offset + prop_ptr->m_Offset)); + } + + char hash_name[256]; + + strcpy_s(hash_name, base_class); + strcat_s(hash_name, "->"); + strcat_s(hash_name, prop_ptr->m_pVarName); + + const auto hash = fnv::hash_runtime(hash_name); + const auto total_offset = std::uint16_t(offset + prop_ptr->m_Offset); + + IF_DUMPING(fprintf(s_fp, "%s\t0x%04X\t%s\n", base_class, total_offset, prop_ptr->m_pVarName);) + + m_props[hash] = + { + prop_ptr, + total_offset + }; + } +} \ No newline at end of file diff --git a/SpyCustom/NetVarManager.hpp b/SpyCustom/NetVarManager.hpp new file mode 100644 index 0000000..b721950 --- /dev/null +++ b/SpyCustom/NetVarManager.hpp @@ -0,0 +1,217 @@ +#ifndef NETVARMGR +#define NETVARMGR +#pragma once + +#include "cdll_int.h" +#include "dt_recv.h" +#include "client_class.h" +#include + +#include "Interfaces.hpp" + + +#include + +namespace detail +{ + template + struct size_dependant_data + { + using type = Type; + constexpr static auto k_offset_basis = OffsetBasis; + constexpr static auto k_prime = Prime; + }; + + template + struct size_selector; + + template <> + struct size_selector<32> + { + using type = size_dependant_data; + }; + + template <> + struct size_selector<64> + { + using type = size_dependant_data; + }; + + template + class fnv_hash + { + private: + using data_t = typename size_selector::type; + + public: + using hash = typename data_t::type; + + private: + constexpr static auto k_offset_basis = data_t::k_offset_basis; + constexpr static auto k_prime = data_t::k_prime; + + public: + template + static __forceinline constexpr auto hash_constexpr(const char(&str)[N], const std::size_t size = N) -> hash + { + return static_cast(1ull * (size == 1 + ? (k_offset_basis ^ str[0]) + : (hash_constexpr(str, size - 1) ^ str[size - 1])) * k_prime); + } + + static auto __forceinline hash_runtime(const char* str) -> hash + { + auto result = k_offset_basis; + do + { + result ^= *str++; + result *= k_prime; + } while (*(str - 1) != '\0'); + + return result; + } + }; +} + +namespace fnv2 { + constexpr uint32_t offsetBasis = 0x811c9dc5; + constexpr uint32_t prime = 0x1000193; + + constexpr uint32_t hash(const char* str, const uint32_t value = offsetBasis) noexcept + { + return *str ? hash(str + 1, (value ^ *str) * static_cast(prime)) : value; + } + + constexpr uint32_t hashRuntime(const char* str) noexcept + { + auto value = offsetBasis; + + while (*str) { + value ^= *str++; + value *= prime; + } + return value; + } +} + +using fnv = ::detail::fnv_hash; + +#define FNV(str) (std::integral_constant::value) + + +#include +#include + +class netvar_manager +{ +private: + struct stored_data + { + RecvProp* prop_ptr; + std::uint16_t class_relative_offset; + }; + +public: + static auto get() -> const netvar_manager& + { + static netvar_manager instance; + return instance; + } + + auto get_offset(const fnv::hash hash) const -> std::uint16_t + { + return m_props.at(hash).class_relative_offset; + } + + auto get_prop(const fnv::hash hash) const -> RecvProp* + { + return m_props.at(hash).prop_ptr; + } + + __declspec(noinline) static auto get_offset_by_hash(const fnv::hash hash) -> std::uint16_t + { + return get().get_offset(hash); + } + + template + static auto get_offset_by_hash_cached() -> std::uint16_t + { + static auto offset = std::uint16_t(0); + if (!offset) + offset = get_offset_by_hash(Hash); + return offset; + } + +private: + netvar_manager(); + auto dump_recursive(const char* base_class, RecvTable* table, std::uint16_t offset) -> void; + +private: + std::map m_props; +}; + + +#define PNETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \ +auto funcname() -> std::add_pointer_t<__VA_ARGS__> \ +{ \ + constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \ + const auto addr = std::uintptr_t(this) + offset + netvar_manager::get_offset_by_hash_cached(); \ + return reinterpret_cast>(addr); \ +} + +#define PNETVAR(funcname, class_name, var_name, ...) \ + PNETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__) + +#define NETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \ +auto funcname() -> std::add_lvalue_reference_t<__VA_ARGS__> \ +{ \ + constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \ + const auto addr = std::uintptr_t(this) + offset + netvar_manager::get_offset_by_hash_cached(); \ + return *reinterpret_cast>(addr); \ +} + +#define NETVAR(funcname, class_name, var_name, ...) \ + NETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__) + +#define NETPROP(funcname, class_name, var_name) \ +static auto funcname() -> RecvProp* \ +{ \ + constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \ + static RecvProp* prop_ptr; \ + if(!prop_ptr) prop_ptr = netvar_manager::get().get_prop(hash); \ + return prop_ptr; \ +} + +class recv_prop_hook +{ +public: + recv_prop_hook(RecvProp* prop, const RecvVarProxyFn proxy_fn) : + m_property(prop), + m_original_proxy_fn(prop->m_ProxyFn) + { + set_proxy_function(proxy_fn); + } + + ~recv_prop_hook() + { + m_property->m_ProxyFn = m_original_proxy_fn; + } + + auto get_original_function() const -> RecvVarProxyFn + { + return m_original_proxy_fn; + } + + auto set_proxy_function(const RecvVarProxyFn proxy_fn) const -> void + { + m_property->m_ProxyFn = proxy_fn; + } + +private: + RecvProp* m_property; + RecvVarProxyFn m_original_proxy_fn; +}; + + + +#endif diff --git a/SpyCustom/Options.hpp b/SpyCustom/Options.hpp new file mode 100644 index 0000000..5afaf73 --- /dev/null +++ b/SpyCustom/Options.hpp @@ -0,0 +1,1102 @@ +#ifndef OPTIONS +#define OPTIONS +#pragma once + +#include +#include +#include +#include + +#define A( s ) #s +#define OPTION(type, var, val) Var var = {A(var), val} + + +template +class Var { +public: + std::string name; + std::shared_ptr value; + int32_t size; + Var(std::string name, T v) : name(name) { + value = std::make_shared(v); + size = sizeof(T); + } + operator T() { return *value; } + operator T* () { return &*value; } + operator T() const { return *value; } +}; + + +#include "resource.h" + +class float3 +{ +public: + float3() { r = 1.0f; g = 1.0f; b = 1.0f; a = 1.0f; } + float3(float r, float g, float b) + { + this->r = r; + this->g = g; + this->b = b; + } + float3(float r, float g, float b, float a) + { + this->r = r; + this->g = g; + this->b = b; + this->a = a; + } + float r = 1.0f; + float g = 1.0f; + float b = 1.0f; + float a = 1.0f; +}; + +class char256 +{ +public: + char256(std::string s) + { + strcpy(mystring, s.c_str()); + } + char mystring[256]; +}; + +class char1024 +{ +public: + char1024(std::string s) + { + strcpy(mystring, s.c_str()); + } + char mystring[1024]; +}; + +class sticker +{ +public: + bool isselected = 1; + char name[256] = "null"; + int stickerid = 0; + float wear = 0; + float rotation = 0; + float scale = 1.0f; + int stickerc = 0; + +}; + + +class weapon +{ +public: + weapon() {}; + weapon(char name1[256], int defindex1, char killfeedicon1[256]) + { + strcpy(name, name1); + strcpy(killfeedicon, killfeedicon1); + defindex = defindex1; + strcpy(killfeediconreplace, killfeedicon1); + + strcpy(stickers[0].name, "(0) null"); + strcpy(stickers[1].name, "(1) null"); + strcpy(stickers[2].name, "(2) null"); + strcpy(stickers[3].name, "(3) null"); + strcpy(stickers[4].name, "(4) null"); + modeldefindex = defindex; + } + char name[256] = ""; + int defindex = 0; + char killfeedicon[256] = ""; + + bool active = 0; + int skinid = 0; + int skinidc = 0; + int seed = 0; + int stattrak = -1; + bool ownerunk = 0; + float wear = 0; + int quality = 0; + int qualityc = 0; + char nametag[256] = ""; + char desctag[256] = ""; + char model[256] = ""; + char worldmodel[256] = ""; + int modeldefindex = 0; + bool modelactive = 0; + int modelcount = 0; + char killfeediconreplace[256] = ""; + bool killfeediconactive = 0; + + int rarity = 0; + int color1 = 0; + int color2 = 0; + int color3 = 0; + int color4 = 0; + float pearl = 0; + DWORD link = 0; + + sticker stickers[5]; + + + int isSelected = 0; +}; + + + +class weaponz +{ +public: + weaponz() + { + int i = 0; + arr[i] = weapon((char*)"Knife", WEAPON_KNIFE_T, (char*)"knife_t"); i++; + arr[i] = weapon((char*)"Glove", GLOVE_STUDDED_BLOODHOUND, (char*)"not_available"); i++; + arr[i] = weapon((char*)"Agent T", 5036, (char*)"not_available"); i++; + arr[i] = weapon((char*)"Agent CT", 5037, (char*)"not_available"); i++; + arr[i] = weapon((char*)"Medal", 1331, (char*)"not_available"); i++; + arr[i] = weapon((char*)"Music Kit", 1314, (char*)"not_available"); i++; + + arr[i] = weapon((char*)"AK-47", WEAPON_AK47, (char*)"ak47"); i++; + arr[i] = weapon((char*)"C4 Explosive", WEAPON_C4, (char*)"c4"); i++; + + arr[i] = weapon((char*)"Desert Eagle", WEAPON_DEAGLE, (char*)"deagle"); i++; + arr[i] = weapon((char*)"Dual Berettas", WEAPON_ELITE, (char*)"elite"); i++; + arr[i] = weapon((char*)"Five-SeveN", WEAPON_FIVESEVEN, (char*)"fiveseven"); i++; + arr[i] = weapon((char*)"Glock-18", WEAPON_GLOCK, (char*)"glock"); i++; + arr[i] = weapon((char*)"AUG", WEAPON_AUG, (char*)"aug"); i++; + arr[i] = weapon((char*)"AWP", WEAPON_AWP, (char*)"awp"); i++; + arr[i] = weapon((char*)"FAMAS", WEAPON_FAMAS, (char*)"famas"); i++; + arr[i] = weapon((char*)"G3SG1", WEAPON_G3SG1, (char*)"g3sg1"); i++; + arr[i] = weapon((char*)"Galil AR", WEAPON_GALILAR, (char*)"galilar"); i++; + arr[i] = weapon((char*)"M249", WEAPON_M249, (char*)"m249"); i++; + + arr[i] = weapon((char*)"M4A4", WEAPON_M4A1, (char*)"m4a1"); i++; + arr[i] = weapon((char*)"MAC-10", WEAPON_MAC10, (char*)"mac10"); i++; + arr[i] = weapon((char*)"P90", WEAPON_P90, (char*)"p90"); i++; + arr[i] = weapon((char*)"UMP-45", WEAPON_UMP45, (char*)"ump45"); i++; + arr[i] = weapon((char*)"XM1014", WEAPON_XM1014, (char*)"xm1014"); i++; + arr[i] = weapon((char*)"PP-Bizon", WEAPON_BIZON, (char*)"bizon"); i++; + arr[i] = weapon((char*)"MAG-7", WEAPON_MAG7, (char*)"mag7"); i++; + arr[i] = weapon((char*)"Negev", WEAPON_NEGEV, (char*)"negev"); i++; + arr[i] = weapon((char*)"Sawed-Off", WEAPON_SAWEDOFF, (char*)"sawedoff"); i++; + + arr[i] = weapon((char*)"Tec-9", WEAPON_TEC9, (char*)"tec9"); i++; + arr[i] = weapon((char*)"P2000", WEAPON_HKP2000, (char*)"hkp2000"); i++; + arr[i] = weapon((char*)"MP7", WEAPON_MP7, (char*)"mp7"); i++; + arr[i] = weapon((char*)"MP9", WEAPON_MP9, (char*)"mp9"); i++; + arr[i] = weapon((char*)"Nova", WEAPON_NOVA, (char*)"nova"); i++; + arr[i] = weapon((char*)"P250", WEAPON_P250, (char*)"p250"); i++; + arr[i] = weapon((char*)"SCAR-20", WEAPON_SCAR20, (char*)"scar20"); i++; + arr[i] = weapon((char*)"SG 553", WEAPON_SG553, (char*)"sg556"); i++; + arr[i] = weapon((char*)"SSG 08", WEAPON_SSG08, (char*)"ssg08"); i++; + + arr[i] = weapon((char*)"M4A1-S", WEAPON_M4A1_SILENCER, (char*)"m4a1_silencer"); i++; + arr[i] = weapon((char*)"USP-S", WEAPON_USP_SILENCER, (char*)"usp_silencer"); i++; + + arr[i] = weapon((char*)"CZ75-Auto", WEAPON_CZ75A, (char*)"cz75a"); i++; + arr[i] = weapon((char*)"RB Revolver", WEAPON_REVOLVER, (char*)"revolver"); i++; + + arr[i] = weapon((char*)"Custom item", 0, (char*)"not_available"); i++; + + weaponzcount = i; + } + + + weapon arr[64]; + int weaponzcount; +}; + + +class Rank +{ +public: + Rank() {}; + Rank(char Name1[256]) + { + strcpy(Name, Name1); + } + char Name[256] = ""; + int rank = 0; + int wins = 0; + int isselected = 0; +}; + +class Rankz +{ +public: + Rankz() + { + arr[0] = Rank((char*)"Competitive MM"); + arr[1] = Rank((char*)"Wingman"); + arr[2] = Rank((char*)"Danger Zone"); + } + Rank arr[3]; + int selectedrank = 0; +}; + + +#include "NetVarManager.hpp" + +class DME +{ +public: + DME() + { + }; + DME(char name1[256], int cust1 = -1) + { + strcpy(name, name1); + customtextureselected = cust1; + } + DME(char name1[256], char texture1[256], char model[256], int cust1 = -1) + { + strcpy(name, name1); + strcpy(texture, texture1); + strcpy(texture_temp, texture1); + model_hash = fnv2::hashRuntime(model); + customtextureselected = cust1; + } + + DME(char name[256], char prefab[32], int cust1 = -1) + { + strcpy(this->name, name); + strcpy(this->prefab, prefab); + customtextureselected = cust1; + } + + char texture_temp[256] = ""; + char texture[256] = ""; + char prefab[32]; + int model_hash = 0; + char name[256] = ""; + bool active = 0; + bool wireframe = 0; + bool nodraw = 0; + bool flat = 0; + ImVec4 coloralpha = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + bool isSelected = 0; + int customtextureselected = -1; +}; + +class DMEs +{ +public: + DMEs() + { + int i = 0; + arr[i] = DME((char*)"Weapons", (char*)"(0) water", (char*)"", 0); i++; + arr[i] = DME((char*)"Glove", (char*)"(0) water", (char*)"", 0); i++; + arr[i] = DME((char*)"Sleeve", (char*)"(0) water", (char*)"", 0); i++; + arr[i] = DME((char*)"Agent T", (char*)"(0) water", (char*)"", 0); i++; + arr[i] = DME((char*)"Agent CT", (char*)"(0) water", (char*)"", 0); i++; + arr[i] = DME((char*)"Knife", (char*)"(0) water", (char*)"", 0); i++; + + arr[i] = DME((char*)"AK-47"); i++; + arr[i] = DME((char*)"C4 Explosive"); i++; + arr[i] = DME((char*)"Desert Eagle"); i++; + arr[i] = DME((char*)"Dual Berettas"); i++; + arr[i] = DME((char*)"Five-SeveN"); i++; + arr[i] = DME((char*)"Glock-18"); i++; + arr[i] = DME((char*)"AUG"); i++; + arr[i] = DME((char*)"AWP"); i++; + arr[i] = DME((char*)"FAMAS"); i++; + arr[i] = DME((char*)"G3SG1"); i++; + arr[i] = DME((char*)"Galil AR"); i++; + arr[i] = DME((char*)"M249"); i++; + arr[i] = DME((char*)"M4A4"); i++; + arr[i] = DME((char*)"MAC-10"); i++; + arr[i] = DME((char*)"P-90"); i++; + arr[i] = DME((char*)"UMP-45"); i++; + arr[i] = DME((char*)"XM1014"); i++; + arr[i] = DME((char*)"PP-Bizon"); i++; + arr[i] = DME((char*)"MAG-7"); i++; + arr[i] = DME((char*)"Negev"); i++; + arr[i] = DME((char*)"Sawed-Off"); i++; + arr[i] = DME((char*)"Tec-9"); i++; + arr[i] = DME((char*)"P2000"); i++; + arr[i] = DME((char*)"MP7"); i++; + arr[i] = DME((char*)"MP9"); i++; + arr[i] = DME((char*)"Nova"); i++; + arr[i] = DME((char*)"P250"); i++; + arr[i] = DME((char*)"SCAR-20"); i++; + arr[i] = DME((char*)"SG 553"); i++; + arr[i] = DME((char*)"SSG 08"); i++; + + itemcount = i; + }; + + int itemcount = 0; + DME arr[64]; +}; + + +class Customtexture +{ +public: + Customtexture() {}; + Customtexture(int id) + { + char preview1[64] = "("; + strcat_s(preview1, std::to_string(id).c_str()); + strcat_s(preview1, ") "); + strcat_s(preview1, "null"); + strcpy(Preview, preview1); + } + Customtexture(char name1[256], char keyvalue1[0x1000], int id) + { + strcpy(Name, name1); + char preview1[64] = "("; + strcat_s(preview1, std::to_string(id).c_str()); + strcat_s(preview1, ") "); + strcat_s(preview1, name1 ); + strcpy(Preview, preview1); + strcpy(keyvalue, keyvalue1); + } + char keyvalue[0x1000] = ""; + char Name[256] = ""; + char Preview[256] = ""; + bool IsSelected = 0; + + void* texturelink = nullptr; +}; + +class Customtextures +{ +public: + Customtextures() + { + int i = 0; + char buf[0x1000] = "\"Refract\"\n{\n\t\"$model\" 1\n\t\"$refractamount\" \"2.0\"\n\t\"$refracttint\" \"[0 1 1 100]\"\n\t\"$dudvmap\" \"dev/water_dudv\"\n\t\"$normalmap\" \"dev/water_normal\"\n\t\"$surfaceprop\" \"water\"\n\t\"$bumpframe\" \"0\"\n\t\"Proxies\"\n\t{\n\t\t\"AnimatedTexture\"\n\t\t{\n\t\t\t\"animatedtexturevar\" \"$normalmap\"\n\t\t\t\"animatedtextureframenumvar\" \"$bumpframe\"\n\t\t\t\"animatedtextureframerate\" 30.00\n\t\t}\n\t\t\"TextureScroll\"\n\t\t{\n\t\t\t\"texturescrollvar\" \"$bumptransform\"\n\t\t\t\"texturescrollrate\" .05\n\t\t\t\"texturescrollangle\" 45.00\n\t\t}\n\t}\n}"; + arr[i] = Customtexture((char*)"water", buf, i); i++; + arr[i] = Customtexture(i); i++; + arr[i] = Customtexture(i); i++; + arr[i] = Customtexture(i); i++; + arr[i] = Customtexture(i); i++; + count = i; + } + Customtexture arr[5]; + int count = 0; +}; + + +class Seqs +{ +public: + Seqs() {}; + int seq_orig = 0; + char seq_orig_def[32] = ""; + int seq_repl = 0; + char seq_repl_def[32] = ""; + + char seq_repl_def_preview[32] = ""; + + bool isSelected[20] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; +}; + +class Sounds +{ +public: + Sounds() {}; + char name[32] = ""; + int hash = 0; + char wavpath[256] = "ui/beep07.wav"; + int pitch = 100; + float volume = 1.0f; +}; + +class Model +{ +public: + Model() {}; + + Model(char name[32]) + { + strcpy(this->name, name); + }; + + Model(char name[32], int defindex, char classid[32], char prefab[32]) + { + this->defindex = defindex; + strcpy(this->name, name); + strcpy(this->classid, classid); + strcpy(this->prefab, prefab); + }; + + Model(char name[32], int defindex, char classid[256], char vmodel_orig[32], bool s) + { + this->defindex = defindex; + strcpy(this->name, name); + strcpy(this->vmodel_orig, vmodel_orig); + strcpy(vmodel_repl_temp, vmodel_orig); + strcpy(vmodel_repl, vmodel_orig); + strcpy(this->classid, classid); + }; + + bool findMDLmethode = false; + + char name[32] = ""; + + char vmodel_orig[256] = ""; + + char vmodel_repl_temp[256] = ""; + char wmodel_repl_temp[256] = ""; + + char vmodel_repl[256] = ""; + char wmodel_repl[256] = ""; + + int vmodel_hash = 0; + int wmodel_hash = 0; + + int defindex = 0; + bool active = 0; + bool active_w = 0; + bool active_scale = 0; + float scale = 1.0f; + + bool seq_active = 0; + Seqs seqs[20]; + + char classid[32] = ""; + + char prefab[32] = ""; + Sounds sounds[5]; + int soundcount = 0; + bool sound_active = 0; + + bool isSelected = 0; +}; + +class Models +{ +public: + Models() { + int i = 0; + + arr[i] = Model((char*)"Agent T"); i++; + arr[i] = Model((char*)"Agent CT"); i++; + arr[i] = Model((char*)"Arms"); i++; + + arr[i] = Model((char*)"Knife", WEAPON_KNIFE_T, (char*)"CKnife", (char*)"models/weapons/v_knife_default_t.mdl", 1); i++; + + arr[i] = Model((char*)"AK-47", WEAPON_AK47, (char*)"CAK47", (char*)"weapon_ak47_prefab"); i++; + arr[i] = Model((char*)"C4 Explosive", WEAPON_C4, (char*)"CC4", (char*)"c4"); i++; + arr[i] = Model((char*)"Desert Eagle", WEAPON_DEAGLE, (char*)"CWeaponDeagle", (char*)"weapon_deagle_prefab"); i++; + arr[i] = Model((char*)"Dual Berettas", WEAPON_ELITE, (char*)"CWeaponElite", (char*)"weapon_elite_prefab"); i++; + arr[i] = Model((char*)"Five-SeveN", WEAPON_FIVESEVEN, (char*)"CWeaponFiveSeven", (char*)"weapon_fiveseven_prefab"); i++; + arr[i] = Model((char*)"Glock-18", WEAPON_GLOCK, (char*)"CWeaponGlock", (char*)"weapon_glock_prefab"); i++; + arr[i] = Model((char*)"AUG", WEAPON_AUG, (char*)"CWeaponAug", (char*)"weapon_aug_prefab"); i++; + arr[i] = Model((char*)"AWP", WEAPON_AWP, (char*)"CWeaponAWP", (char*)"weapon_awp_prefab"); i++; + arr[i] = Model((char*)"FAMAS", WEAPON_FAMAS, (char*)"CWeaponFamas", (char*)"weapon_famas_prefab"); i++; + arr[i] = Model((char*)"G3SG1", WEAPON_G3SG1, (char*)"CWeaponG3SG1", (char*)"weapon_g3sg1_prefab"); i++; + arr[i] = Model((char*)"Galil AR", WEAPON_GALILAR, (char*)"CWeaponGalilAR", (char*)"weapon_galilar_prefab"); i++; + arr[i] = Model((char*)"M249", WEAPON_M249, (char*)"CWeaponM249", (char*)"weapon_m249_prefab"); i++; + arr[i] = Model((char*)"M4A4", WEAPON_M4A1, (char*)"CWeaponM4A1", (char*)"weapon_m4a1_prefab"); i++; + arr[i] = Model((char*)"MAC-10", WEAPON_MAC10, (char*)"CWeaponMAC10", (char*)"weapon_mac10_prefab"); i++; + arr[i] = Model((char*)"P-90", WEAPON_P90, (char*)"CWeaponP90", (char*)"weapon_p90_prefab"); i++; + arr[i] = Model((char*)"UMP-45", WEAPON_UMP45, (char*)"CWeaponUMP45", (char*)"weapon_ump45_prefab"); i++; + arr[i] = Model((char*)"XM1014", WEAPON_XM1014, (char*)"CWeaponXM1014", (char*)"weapon_xm1014_prefab"); i++; + arr[i] = Model((char*)"PP-Bizon", WEAPON_BIZON, (char*)"CWeaponBizon", (char*)"weapon_bizon_prefab"); i++; + arr[i] = Model((char*)"MAG-7", WEAPON_MAG7, (char*)"CWeaponMag7", (char*)"weapon_mag7_prefab"); i++; + arr[i] = Model((char*)"Negev", WEAPON_NEGEV, (char*)"CWeaponNegev", (char*)"weapon_negev_prefab"); i++; + arr[i] = Model((char*)"Sawed-Off", WEAPON_SAWEDOFF, (char*)"CWeaponSawedoff", (char*)"weapon_sawedoff_prefab"); i++; + arr[i] = Model((char*)"Tec-9", WEAPON_TEC9, (char*)"CWeaponTec9", (char*)"weapon_tec9_prefab"); i++; + arr[i] = Model((char*)"P2000", WEAPON_HKP2000, (char*)"CWeaponHKP2000", (char*)"weapon_hkp2000_prefab"); i++; + arr[i] = Model((char*)"MP7", WEAPON_MP7, (char*)"CWeaponMP7", (char*)"weapon_mp7_prefab"); i++; + arr[i] = Model((char*)"MP9", WEAPON_MP9, (char*)"CWeaponMP9", (char*)"weapon_mp9_prefab"); i++; + arr[i] = Model((char*)"Nova", WEAPON_NOVA, (char*)"CWeaponNOVA", (char*)"weapon_nova_prefab"); i++; + arr[i] = Model((char*)"P250", WEAPON_P250, (char*)"CWeaponP250", (char*)"weapon_p250_prefab"); i++; + arr[i] = Model((char*)"SCAR-20", WEAPON_SCAR20, (char*)"CWeaponSCAR20", (char*)"weapon_scar20_prefab"); i++; + arr[i] = Model((char*)"SG 553", WEAPON_SG553, (char*)"CWeaponSG556", (char*)"weapon_sg556_prefab"); i++; + arr[i] = Model((char*)"SSG 08", WEAPON_SSG08, (char*)"CWeaponSSG08", (char*)"weapon_ssg08_prefab"); i++; + + + + + itemcount = i; + } + Model arr[64]; + int itemcount = 0; +}; + + +class Effects +{ +public: + Effects() {}; + int type = 2; + int selectedc = 0; + + int fx_magnitude = 1; + int fx_traillength = 1; + float fx_fsize = 5.0f; + float fx_fspeed = 1.0f; + int fx_itype = 1; + bool fx_bexplosive = false; + + int icolors = 0; + int fflags = 0; + float fscale = 1.0f; + float fmagtinude = 1.0f; + float fradius = 1.0f; + + float fbeamwidth = 1.0f; + float teslaradius = 5.0f; + float teslacolor[3] = { 1.0f,0,0 }; + float fltimevisible = 0.75f; + int ibeams = 3; + char szSpriteName[256] = "sprites/physbeam.vmt"; + float dlightcolor[3] = { 1.0f,0,0 }; + float fdie = 0.1f; + float frad = 500.0f; + int style = 1; + int key = 1; + float decay = 0.0f; +}; + + +inline Vector CalcAngle(register const Vector& src, register const Vector& dst) +{ + Vector angles; + Vector delta = src - dst; + float hyp = sqrt(delta.x * delta.x + delta.y * delta.y); + angles.x = atan(delta.z / hyp) * (180.0f / 3.14); + angles.y = atanf(delta.y / delta.x) * (180.0f / 3.14) + !((*(DWORD*)&delta.x) >> 31 & 1) * 180.0f; + angles.z = 0.0f; + return angles; +} + +class Options +{ +public: + OPTION(bool, attacheffects, false); + OPTION(Effects, effects, Effects()); + OPTION(bool, beamtrace, false); + + OPTION(int, beamtype, 0); + OPTION(float3, beamcolor, float3(0.95f, 0.20f, 0.0f, 1.0f)); + + OPTION(char256, beampath, char256("sprites/purplelaser1.vmt")); + OPTION(float, beamlife, 1.0f); + + OPTION(float, beamwidth, 2.5f); + OPTION(float, beamendwidth, 2.5f); + + OPTION(float, beamhaloscale, 0.0f); + OPTION(float, beamfadelength, 0.3f); + + OPTION(float, beamamplitude, 5.0f); + OPTION(float, beamstartframe, 0.0f); + + OPTION(float, beamspeed, 0.3f); + OPTION(float, beamframerate, 1.0f); + + OPTION(int, beamsegments, 2); + OPTION(int, beamflags, 0x8300); + + OPTION(bool, hitsound, false); + OPTION(char256, hspath, char256("102")); + OPTION(char256, obpath, char256("101")); + + OPTION(bool, hitmarker, false); + + OPTION(bool, flashlightON, false); + OPTION(bool, flashlightShadows, false); + OPTION(float, flashlightFOV, 45.0f); + OPTION(float, flashlightLinearAtten, 1000.0f); + OPTION(float, flashlightFarZ, 1000.0f); + OPTION(char256, flashlightTexture, char256("effects/flashlight001")); + OPTION(bool, nvgsON, false); + OPTION(bool, fogactive, false); + OPTION(float3, fogcolor, float3(0,0,0) ); + OPTION(float, fogdensity, 0); + OPTION(float, fogstart, 0); + OPTION(float, fogend, 0); + OPTION(float, tonemapscale, 1.0f); + OPTION(bool, skyboxactive, false); + OPTION(char256, skyboxtemp, char256("sky_day02_05")); + + OPTION(bool, weatheractive, false); + OPTION(int, weathertype, 1); + OPTION(float, windspeed, 0); + OPTION(float, rainalpha, 0.4f); + OPTION(float, rainlength, 0.1f); + OPTION(float, rainwidth, 0.5f); + OPTION(float, rainsidevel, 130.0f); + OPTION(float, rainradius, 1500.0f); + OPTION(float, rainspeed, 600.0f); + + OPTION(bool, worldcoloractive, false); + OPTION(float3, worldcolor, float3(1.0f, 1.0f, 1.0f)); + OPTION(float3, staticpropcolor, float3(1.0f, 1.0f, 1.0f)); + OPTION(float3, modelcolor, float3(1.0f, 1.0f, 1.0f)); + OPTION(Models, models, Models()); + OPTION(int, soundhook_count, 0); + OPTION(int, entityloop_count, 0); + OPTION(int, playerloop_count, 0); + OPTION(DMEs, materials, DMEs()); + OPTION(Customtextures, customtextures, Customtextures()); + OPTION(bool, dme_gettextures, false); + OPTION(int, dmeloop_count, 0); + OPTION(weaponz, weapons, weaponz()); + OPTION(char1024, playername, char1024("ur name")); + OPTION(char1024, playerclan, char1024("ur tag")); + + OPTION(bool, discmsg_active, false); + OPTION(char1024, discmsg, char1024("SFUI_QMM_ERROR_VacBanned")); + + OPTION(bool, profile_active, false); + OPTION(bool, prime, false); + + OPTION(Rankz, rankz, Rankz()); + + OPTION(int, level, 0); + OPTION(int, xp, 0); + + OPTION(int, comleader, 0); + OPTION(int, comteacher, 0); + OPTION(int, comfriendly, 0); + + OPTION(bool, fakescore, 0); + OPTION(int, MVPs, 0); + OPTION(int, score, 0); + OPTION(int, kills, 0); + OPTION(int, assists, 0); + OPTION(int, deaths, 0); + + OPTION(bool, vacban, 0); + OPTION(int, banreason, 0); + OPTION(int, banduration, 0); + + OPTION(bool, votereveal, 0); + +}; + +inline Options g_Options; +inline bool g_Unload; + + + + +struct skin +{ + skin(bool active1, int skinid1, int seed1, int stattrak1, bool ownerunk1, float wear1, int quality1, char nametag1[256]) + { + active = active1; + skinid = skinid1; + seed = seed1; + stattrak = stattrak1; + ownerunk = ownerunk1; + wear = wear1; + quality = quality1; + strcpy(nametag, nametag1); + }; + + bool active = 0; + int skinid = 0; + int skinidc = 0; + int seed = 0; + int stattrak = -1; + bool ownerunk = 0; + float wear = 0; + int quality = 0; + int qualityc = 0; + char nametag[256] = ""; + char model[256] = ""; + char worldmodel[256] = ""; + int modeldefindex = 0; + bool modelactive = 0; + int modelcount = 0; + char killfeedicon[256] = ""; + char killfeediconorigin[256] = ""; + bool killfeediconactive = 0; +}; + + + + +class Options_my +{ +public: + + std::vector IEffects = { + "Smoke", + "Sparks", + "Dust", + "MuzzleFlash", + "MetalSparks", + "EnergySplash", + "Ricochet" + }; + + std::vector DispatchEffect = { + "Explosion", + "WaterSurfaceExplosion", + "HelicopterMegaBomb", + "CS_HolidayLight", + "ManhackSparks", + "watersplash", + "watersplashquiet", + "gunshotsplash", + "HunterDamage", + "MuzzleFlash", + "Smoke", + "GunshipImpact", + "BoltImpact", + "csblood", + "GlassImpact", + "RPGShotDown", + "WheelDust", + "Error" + }; + + std::vector OtherEff = { + "Tesla", + "DLight" + }; + + std::vector EffTypes = { + "CEffectsClient", + "CTEEffectDispatch", + "Other" + }; + + std::map> Map = { + {"CEffectsClient", IEffects}, + {"CTEEffectDispatch", DispatchEffect}, + {"Other", OtherEff}, + }; + + + + + HMODULE hModuleGlobal = NULL; + + int needtogetseqact = 0; + bool netchannedlhooked = 0; + + bool disconnected = 0; + bool needupdate = 0; + bool loading = 0; + bool autoload = 0; + bool unhook = 0; + + std::vector names = { + "\\x10\\xAD\\xAD\\xAD" + }; + + std::vector skyboxitems = { + "sky_day02_05", + "cs_baggage_skybox_", + "cs_tibet", + "vietnam", + "sky_lunacy", + "embassy", + "italy", + "jungle", + "office", + "sky_cs15_daylight01_hdr", + "sky_cs15_daylight02_hdr", + "nukeblank", + "dustblank", + "sky_venice", + "sky_cs15_daylight03_hdr", + "sky_cs15_daylight04_hdr", + "sky_csgo_cloudy01", + "sky_csgo_night02", + "sky_csgo_night02b", + "vertigo", + "vertigoblue_hdr", + "sky_dust", + "sky_hr_aztec", + "sky_l4d_rural02_ldr", + "vertigo_hdr", + "sky_csgo_night_flat" + }; + + std::vector soundslist = { + "101", + "102", + }; + + + std::vector spriteslist = { + "sprites/purplelaser1.vmt", + "sprites/physbeam.vmt", + "sprites/purpleglow1.vmt", + "sprites/blueglow1.vmt", + "sprites/white.vmt", + "sprites/radio.vmt", + "sprites/gunsmoke.vmt", + "sprites/bubble.vmt" + }; + + + std::vector flashlightlist = { + "effects/flashlight_border", + "effects/flashlight_freezecam", + "effects/flashlight_inspect", + "effects/flashlight_security001", + "effects/flashlight001", + "effects/flashlight001_improved", + "effects/flashlight001_intro", + "effects/flashlight002", + "effects/autumn_access_denied_color", + "effects/coopphoenixloadingscreen", + "effects/combinemuzzle1", + "sprites/purpleglow1", + }; + + std::vector dmeitems = { + "(0) water", + "(1) null", + "(2) null", + "(3) null", + "(4) null", + "models/extras/speech_info", + "models/gibs/glass/glass", + "models/inventory_items/cologne_prediction/cologne_prediction_glass", + "models/inventory_items/contributor_map_tokens/contributor_charset_color", + "models/inventory_items/dogtags/dogtags", + "models/inventory_items/dogtags/dogtags_lightray", + "models/inventory_items/dogtags/dogtags_outline", + "models/inventory_items/dreamhack_trophies/dreamhack_star_blur", + "models/inventory_items/hydra_crystal/hydra_crystal", + "models/inventory_items/hydra_crystal/hydra_crystal_detail", + "models/inventory_items/music_kit/darude_01/mp3_detail", + "models/inventory_items/payback_gold_01/payback_gold_01", + "models/inventory_items/phoenix_gold_01/phoenix_gold_01", + "models/inventory_items/service_medal_2015/glass", + "models/inventory_items/service_medal_2016/glass_lvl4", + "models/inventory_items/sticker_inspect/sticker_backing", + "models/inventory_items/trophy_majors/crystal_blue", + "models/inventory_items/trophy_majors/crystal_clear", + "models/inventory_items/trophy_majors/gloss", + "models/inventory_items/trophy_majors/gold", + "models/inventory_items/trophy_majors/gold_dust", + "models/inventory_items/trophy_majors/silver_winners", + "models/inventory_items/vanguard_gold/vanguard_gold_detail", + "models/inventory_items/wildfire_gold/wildfire_gold_detail", + "models/player/ct_fbi/ct_fbi_glass", + "models/player/t_guerilla/t_guerilla", + "models/props_foliage/urban_tree03_branches", + "models/props_shacks/fishing_net01", + "models/weapons/customization/stickers/cologne2014/esl_c" + }; + + + + std::vector killfeedicons = { + "Default" + }; + + + + char sc_selectedweapon[256]; + bool sc_active1 = false; + int sc_seed1 = 0; + int sc_stattrak1 = 0; + bool sc_unk1 = false; + char sc_selectedskin[256]; + + struct stickerstruct + { + stickerstruct(int id1, std::string Name1, int count1) + { + id = id1; + Name = Name1; + count = count1; + Preview = std::to_string(id).append(": ").append(Name1); + } + int id; + std::string Name; + int count; + bool isSelected; + std::string Preview; + }; + + std::vector sc_stickers = + { + + }; + + struct skinstruct + { + skinstruct(int id1, std::string Name1, int count1, int rarity1, int color11, int color21, int color31, int color41, float pearl1, DWORD link1) + { + id = id1; + Name = Name1; + isSelected = 0; + count = count1; + Preview = std::to_string(id).append(": ").append(Name1); + rarity = rarity1; + color1 = color11; + color2 = color21; + color3 = color31; + color4 = color41; + pearl = pearl1; + link = link1; + } + int id; + std::string Name; + bool isSelected; + int count; + std::string Preview; + int rarity; + int color1; + int color2; + int color3; + int color4; + float pearl; + DWORD link; + }; + + std::vector sc_skins = + { + + }; + + struct selectedweapon + { + selectedweapon(std::string Name1, std::string icon1) + { + Name = Name1; + isSelected = 0; + icon = icon1; + }; + std::string Name; + std::string icon; + bool isSelected; + }; + + + bool show = false; + +}; + +inline Options_my opt; + + +#define SOUND_ENTRY_HASH_SEED 0x444F5441 + +inline uint32 GenerateSoundEntryHash(char const* pSoundEntry) +{ + int nSoundEntryLength = strlen(pSoundEntry); + char* pSoundEntryLowerCase = (char*)stackalloc(nSoundEntryLength + 1); + + for (int nIndex = 0; nIndex < nSoundEntryLength; nIndex++) + pSoundEntryLowerCase[nIndex] = tolower(pSoundEntry[nIndex]); + + const uint32 nMagicNumber = 0x5bd1e995; + + uint32 nSoundHash = SOUND_ENTRY_HASH_SEED ^ nSoundEntryLength; + + unsigned char* pData = (unsigned char*)pSoundEntryLowerCase; + + while (nSoundEntryLength >= 4) + { + uint32 nLittleDWord = LittleDWord(*(uint32*)pData); + + nLittleDWord *= nMagicNumber; + nLittleDWord ^= nLittleDWord >> 24; + nLittleDWord *= nMagicNumber; + + nSoundHash *= nMagicNumber; + nSoundHash ^= nLittleDWord; + + pData += 4; + nSoundEntryLength -= 4; + } + + switch (nSoundEntryLength) + { + case 3: nSoundHash ^= pData[2] << 16; + case 2: nSoundHash ^= pData[1] << 8; + case 1: nSoundHash ^= pData[0]; + nSoundHash *= nMagicNumber; + }; + + nSoundHash ^= nSoundHash >> 13; + nSoundHash *= nMagicNumber; + nSoundHash ^= nSoundHash >> 15; + + return nSoundHash; +} + + +inline int GetCfgIndexByClassId(int ClassID) { + for (int i = 0; i < g_Options.models.value->itemcount; i++) + { + if (fnv2::hash(g_Options.models.value->arr[i].classid) == ClassID) + return i; + } + return -1; +} + + +inline int GetCfgIndexByPrefab(int Prefab) { + for (int i = 4; i < g_Options.models.value->itemcount; i++) + { + if (fnv2::hash(g_Options.models.value->arr[i].prefab) == Prefab) + return i; + } + return -1; +} + + +inline int GetCfgIndex(int item_definition_index) +{ + for (int i = 0; i < g_Options.weapons.value->weaponzcount; i++) + { + if (g_Options.weapons.value->arr[i].defindex == item_definition_index) + return i; + } + return -1; +} + +inline int GetCfgIndex2(int item_definition_index) +{ + for (int i = 2; i < g_Options.models.value->itemcount; i++) + { + if (g_Options.models.value->arr[i].defindex == item_definition_index) + return i; + } + return -1; +} + + +struct soundlist +{ + soundlist(int cfgindex = 0, int sndindex = 0) + { + this->cfgindex = cfgindex; + this->sndindex = sndindex; + } + int cfgindex = 0; + int sndindex = 0; +}; + +inline soundlist GetCfgWavpathBySoundHash(int Hash) { + for (int i = 3; i < g_Options.models.value->itemcount; i++) + { + for (int j = 0; j < g_Options.models.value->arr[i].soundcount; j++) + if (g_Options.models.value->arr[i].sounds[j].hash == Hash) + if (g_Options.models.value->arr[i].sound_active) + return soundlist(i, j); + else return soundlist(-1, 0); + } + return soundlist(-1, 0); +} + + + +void OnLoadCfg(); +void OnLevelInit(); + + + + + + + + +#endif \ No newline at end of file diff --git a/SpyCustom/Other.cpp b/SpyCustom/Other.cpp new file mode 100644 index 0000000..8698c05 --- /dev/null +++ b/SpyCustom/Other.cpp @@ -0,0 +1,265 @@ +#include "Other.hpp" +#include "PatternScan.hpp" + + + +void UpdateFlashLight(CFlashlightEffect* pFlashLight, const Vector& vecPos, const Vector& vecForward, const Vector& vecRight, const Vector& vecUp) +{ + typedef void(__thiscall* UpdateLight_t)(void*, int, const Vector&, const Vector&, const Vector&, const Vector&, float, float, float, bool, const char*); + + static UpdateLight_t oUpdateLight = NULL; + + if (!oUpdateLight) + { + DWORD callInstruction = FindPatternV2("client.dll", "E8 ? ?? ? ? 8B 06 F3 0F 10 46"); + DWORD relativeAddress = *(DWORD*)(callInstruction + 1); + DWORD nextInstruction = callInstruction + 5; + oUpdateLight = (UpdateLight_t)(nextInstruction + relativeAddress); + } + + oUpdateLight(pFlashLight, pFlashLight->m_nEntIndex, vecPos, vecForward, vecRight, vecUp, + pFlashLight->m_flFov, pFlashLight->m_flFarZ, pFlashLight->m_flLinearAtten, pFlashLight->m_bCastsShadows, + pFlashLight->m_textureName); +} + + +CFlashlightEffect* CreateFlashLight(int nEntIndex, const char* pszTextureName, float flFov, float flFarZ, float flLinearAtten) +{ + + CFlashlightEffect* pFlashLight = reinterpret_cast(iff.g_pMemAlloc->Alloc(sizeof(CFlashlightEffect))); + + if (!pFlashLight) + return NULL; + + static DWORD oConstructor = FindPatternV2("client.dll", "55 8B EC F3 0F 10 45 ? B8"); + + __asm + { + movss xmm3, flFov + mov ecx, pFlashLight + push flLinearAtten + push flFarZ + push pszTextureName + push nEntIndex + call oConstructor + } + pFlashLight->m_bIsOn = true; + + + return pFlashLight; +} + +void DestroyFlashLight(CFlashlightEffect* pFlashLight) +{ + static DWORD oDestructor = FindPatternV2("client.dll", "56 8B F1 E8 ? ? ? ? 8B 4E 28"); + + __asm + { + mov ecx, pFlashLight + push ecx + call oDestructor + } + +} + +void AngleVectors(const Vector& angles, Vector* forward, Vector* right, Vector* up) +{ + float sr, sp, sy, cr, cp, cy; + + SinCos(DEG2RAD(angles[1]), &sy, &cy); + SinCos(DEG2RAD(angles[0]), &sp, &cp); + SinCos(DEG2RAD(angles[2]), &sr, &cr); + + if (forward) + { + forward->x = cp * cy; + forward->y = cp * sy; + forward->z = -sp; + } + + if (right) + { + right->x = (-1 * sr * sp * cy + -1 * cr * -sy); + right->y = (-1 * sr * sp * sy + -1 * cr * cy); + right->z = -1 * sr * cp; + } + + if (up) + { + up->x = (cr * sp * cy + -sr * -sy); + up->y = (cr * sp * sy + -sr * cy); + up->z = cr * cp; + } +} + + +static bool ToggleButton(ButtonCode_t code) +{ + static int buttonPressedTick = 0; + if (iff.g_pInputSystem->IsButtonDown(code) && (GetTickCount64() - buttonPressedTick) > 300) + { + buttonPressedTick = GetTickCount64(); + return true; + } + return false; +} + +void FlashlightRun(C_BasePlayer* local) +{ + static CFlashlightEffect* pFlashLight = NULL; + + if (opt.disconnected) + { +#ifdef DEBUG + printf("nullify pFlashlight bc disconnected\n"); +#endif + pFlashLight = NULL; + opt.disconnected = 0; + } + + if (ToggleButton(KEY_L)) + { + if (!pFlashLight) + { +#ifdef DEBUG + printf("creating fl\n"); +#endif + pFlashLight = CreateFlashLight(local->GetIndex(), g_Options.flashlightTexture.value->mystring, *g_Options.flashlightFOV, *g_Options.flashlightFarZ, *g_Options.flashlightLinearAtten); + iff.g_pEngineClient->ExecuteClientCmd("play items/flashlight1.wav"); + } + else + { +#ifdef DEBUG + printf("destroying fl\n"); +#endif + DestroyFlashLight(pFlashLight); + pFlashLight = NULL; + iff.g_pEngineClient->ExecuteClientCmd("play items/flashlight1.wav"); + } + } + + if (pFlashLight) + { + Vector f, r, u; + Vector viewAngles; + + iff.g_pEngineClient->GetViewAngles(viewAngles); + AngleVectors(viewAngles, &f, &r, &u); + + pFlashLight->m_bIsOn = true; + pFlashLight->m_bCastsShadows = *g_Options.flashlightShadows; + pFlashLight->m_flFov = *g_Options.flashlightFOV; + + UpdateFlashLight(pFlashLight, local->GetOrigin() + local->GetViewOffset(), f, r, u); + + } +} + + +#define DRAW_SCREEN_EFFECT(material) \ +{ \ + const auto drawFunction = relativeToAbsolute(FindPatternV2("client.dll", "E8 ? ? ? ? 83 C4 0C 8D 4D F8") + 1); \ + int w, h; \ + iff.g_pVGuiSurface->GetScreenSize(w, h); \ + __asm { \ + __asm push h \ + __asm push w \ + __asm push 0 \ + __asm xor edx, edx \ + __asm mov ecx, material \ + __asm call drawFunction \ + __asm add esp, 12 \ + } \ +} + +void NightvisionRun(C_BasePlayer* local) { + + static int m_flNightVisionAlpha = NetvarSys::Get().GetOffset("DT_CSPlayer", "m_flFlashDuration") - 0x1C; + + if (ToggleButton(KEY_N) ) + { + if (!local->GetNightvision()) + { + local->GetNightvision() = true; + *(float*)(uintptr_t(local) + m_flNightVisionAlpha) = 1.0f; + iff.g_pEngineClient->ExecuteClientCmd("play items/nvg_on.wav"); + + } + else + { + local->GetNightvision() = false; + *(float*)(uintptr_t(local) + m_flNightVisionAlpha) = 0; + iff.g_pEngineClient->ExecuteClientCmd("play items/nvg_off.wav"); + } + } +} + + +void do_precipitation() { + static void* rain_networkable = nullptr; + C_Precipitation* rain_ent = (C_Precipitation*)iff.g_pEntityList->GetClientEntity(MAX_EDICTS - 1); + static ClientClass* precipitation_client_class = nullptr; + + + + + if (!iff.g_pEngineClient->IsInGame() || !iff.g_pEngineClient->IsConnected()) { + rain_networkable = rain_ent = nullptr; + return; + } + + int localplayer_index = iff.g_pEngineClient->GetLocalPlayer(); + C_BasePlayer* localplayer = static_cast(iff.g_pEntityList->GetClientEntity(localplayer_index)); + if (!localplayer) return; + + if (!(localplayer->GetLifeState() == LIFE_ALIVE && localplayer->GetHealth() > 0)) + return; + + + + if (!precipitation_client_class) { + for (auto pclass = iff.g_pClient->GetAllClasses(); pclass && !precipitation_client_class; pclass = pclass->m_pNext) + if (strstr(pclass->GetName(), "CPrecipitation")) + { +#ifdef DEBUG + printf("class found %x\n", pclass); +#endif + precipitation_client_class = pclass; + } + + } + + + else { + if (!rain_ent && precipitation_client_class && precipitation_client_class->m_pCreateFn) { + +#ifdef DEBUG + printf("Creating precipitation\n"); +#endif + + rain_networkable = ((void* (*)(int, int))precipitation_client_class->m_pCreateFn)(MAX_EDICTS - 1, 0); + + if (rain_networkable) { + rain_ent = (C_Precipitation*)iff.g_pEntityList->GetClientEntity(MAX_EDICTS - 1); + + rain_ent->GetPrecipitationType() = (PrecipitationType_t)*g_Options.weathertype; + + rain_ent->PreDataUpdate(DataUpdateType_t::DATA_UPDATE_CREATED); + rain_ent->OnPreDataChanged(DataUpdateType_t::DATA_UPDATE_CREATED); + + rain_ent->GetMins() = Vector(-32767.0f, -32767.0f, -32767.0f); + rain_ent->GetMaxs() = Vector(32767.0f, 32767.0f, 32767.0f); + + rain_ent->OnDataChanged(DataUpdateType_t::DATA_UPDATE_CREATED); + rain_ent->PostDataUpdate(DataUpdateType_t::DATA_UPDATE_CREATED); + +#ifdef DEBUG + printf("Created precipitation %x\n", rain_ent); +#endif + } + } + } + +} + + diff --git a/SpyCustom/Other.hpp b/SpyCustom/Other.hpp new file mode 100644 index 0000000..6ba09d3 --- /dev/null +++ b/SpyCustom/Other.hpp @@ -0,0 +1,15 @@ +#ifndef OTHER +#define OTHER +#pragma once + +#include "Interfaces.hpp" +#include "Options.hpp" + +#include "c_baseentity.h" + +void FlashlightRun(C_BasePlayer* local); +void NightvisionRun(C_BasePlayer* local); + +void do_precipitation(); + +#endif OTHER \ No newline at end of file diff --git a/SpyCustom/PHandle.h b/SpyCustom/PHandle.h new file mode 100644 index 0000000..ff606db --- /dev/null +++ b/SpyCustom/PHandle.h @@ -0,0 +1,70 @@ +#ifndef PHANDLE_H +#define PHANDLE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "VGUI.h" + +namespace vgui +{ + + class Panel; + + class PHandle + { + public: + PHandle() : m_iPanelID(INVALID_PANEL) {} + + Panel* Get(); + Panel* Set(Panel* pPanel); + Panel* Set(HPanel hPanel); + + operator Panel* () { return Get(); } + Panel* operator ->() { return Get(); } + Panel* operator = (Panel* pPanel) { return Set(pPanel); } + + bool operator == (Panel* pPanel) { return (Get() == pPanel); } + operator bool() { return Get() != 0; } + + private: + HPanel m_iPanelID; + }; + + class VPanelHandle + { + public: + VPanelHandle() : m_iPanelID(INVALID_PANEL) {} + + VPANEL Get(); + VPANEL Set(VPANEL pPanel); + + operator VPANEL () { return Get(); } + VPANEL operator = (VPANEL pPanel) { return Set(pPanel); } + + bool operator == (VPANEL pPanel) { return (Get() == pPanel); } + operator bool() { return Get() != 0; } + + private: + HPanel m_iPanelID; + }; + + template< class PanelType > + class DHANDLE : public PHandle + { + public: + PanelType* Get() { return (PanelType*)PHandle::Get(); } + PanelType* Set(PanelType* pPanel) { return (PanelType*)PHandle::Set(pPanel); } + PanelType* Set(HPanel hPanel) { return (PanelType*)PHandle::Set(hPanel); } + + operator PanelType* () { return (PanelType*)PHandle::Get(); } + PanelType* operator ->() { return (PanelType*)PHandle::Get(); } + PanelType* operator = (PanelType* pPanel) { return (PanelType*)PHandle::Set(pPanel); } + bool operator == (Panel* pPanel) { return (PHandle::Get() == pPanel); } + operator bool() { return PHandle::Get() != NULL; } + }; + +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/Panel.h b/SpyCustom/Panel.h new file mode 100644 index 0000000..6d48b3a --- /dev/null +++ b/SpyCustom/Panel.h @@ -0,0 +1,962 @@ +#ifndef PANEL_H +#define PANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "utlflags.h" +#include "vgui.h" +#include "Dar.h" +#include "MessageMap.h" +#if defined( VGUI_USEKEYBINDINGMAPS ) +#include "KeyBindingMap.h" +#endif +#include "IClientPanel.h" +#include "IScheme.h" +#include "Controls.h" +#include "PHandle.h" +#include "PanelAnimationVar.h" +#include "color.h" +#include "keyvalues.h" +#include "ikeyvaluessystem.h" +#include "utlsymbol.h" +#include "BuildGroup.h" +#include "dmxelement.h" + +#ifdef PostMessage +#undef PostMessage +#endif + +#ifdef SetCursor +#undef SetCursor +#endif + + +class CUtlBuffer; +struct DmxElementUnpackStructure_t; + +namespace vgui +{ + +#if !defined( _GAMECONSOLE ) +#define VGUI_USEDRAGDROP 1 +#endif + +#if defined( VGUI_USEKEYBINDINGMAPS ) + struct PanelKeyBindingMap; +#endif + template< class T > + inline T* SETUP_PANEL(T* panel) + { + panel->MakeReadyForUse(); + return panel; + } + +#define CREATE_PANEL(type, parent, name) (SETUP_PANEL(new type(parent, name))) + +#if defined( VGUI_USEDRAGDROP ) + struct DragDrop_t; + class Menu; +#endif + + + + class Panel; + + struct SizerAddArgs_t + { + SizerAddArgs_t() + { + m_flExpandFactor = 0.0f; + m_nPadding = 5; + m_bMinorExpand = true; + m_nMinX = -1; + m_nMinY = -1; + m_bIgnoreMemberMin = false; + } + + SizerAddArgs_t& Expand(float flExpandFactor) { m_flExpandFactor = flExpandFactor; return *this; } + SizerAddArgs_t& Padding(int nPadding) { m_nPadding = nPadding; return *this; } + SizerAddArgs_t& MinorExpand(bool bMinorExpand) { m_bMinorExpand = bMinorExpand; return *this; } + SizerAddArgs_t& MinSize(int nMinX, int nMinY) { m_nMinX = nMinX; m_nMinY = nMinY; return *this; } + SizerAddArgs_t& MinX(int nMinX) { m_nMinX = nMinX; return *this; } + SizerAddArgs_t& MinY(int nMinY) { m_nMinY = nMinY; return *this; } + + SizerAddArgs_t& IgnoreMemberMin(bool bIgnoreMemberMin = true) { m_bIgnoreMemberMin = bIgnoreMemberMin; return *this; } + + SizerAddArgs_t& FixedSize(int nX, int nY) + { + IgnoreMemberMin(true); + MinSize(nX, nY); + Expand(0.f); + MinorExpand(false); + return *this; + } + + float m_flExpandFactor; + int m_nPadding; + bool m_bMinorExpand; + int m_nMinX; + int m_nMinY; + bool m_bIgnoreMemberMin; + }; + + + enum SizerLayoutDirection_t + { + ESLD_HORIZONTAL, + ESLD_VERTICAL + }; + + enum SizerElementType_t + { + ESET_SIZER, + ESET_PANEL, + ESET_SPACER, + }; + + class CSizerBase + { + public: + CSizerBase(); + virtual ~CSizerBase(); + + int GetElementCount() { return m_Members.Count(); } + SizerElementType_t GetElementType(int i); + Panel* GetPanel(int i); + + void SetElementArgs(int nIndex, const SizerAddArgs_t& args) { m_Members[nIndex].Fill(args); } + + void InsertPanel(int nIndex, Panel* pPanel, const SizerAddArgs_t& args); + void InsertSizer(int nIndex, CSizerBase* pSizer, const SizerAddArgs_t& args); + void InsertSpacer(int nIndex, const SizerAddArgs_t& args); + + void AddPanel(Panel* pPanel, const SizerAddArgs_t& args) { InsertPanel(GetElementCount(), pPanel, args); } + void AddSizer(CSizerBase* pSizer, const SizerAddArgs_t& args) { InsertSizer(GetElementCount(), pSizer, args); } + void AddSpacer(const SizerAddArgs_t& args) { InsertSpacer(GetElementCount(), args); } + + void RemoveElement(int i, bool bDelete); + void RemoveAllMembers(bool bDelete); + + void GetMinSize(int& OutX, int& OutY); + + void RecursiveInvalidateCachedSize(); + + virtual void DoLayout(int BaseX, int BaseY, int SizeX, int SizeY) = 0; + virtual void CalculateSize() = 0; + + protected: + class CSizerMember + { + friend class CSizerBase; + + public: + SizerElementType_t GetElementType() const; + Panel* GetPanel() const; + + void GetMemberMinSize(int& OutX, int& OutY); + void RecursiveInvalidateCachedSize(); + void Place(int BaseX, int BaseY, int SizeX, int SizeY); + + float GetExpandFactor() { return m_flExpandFactor; } + bool GetMinorExpand() { return m_bMinorExpand; } + + void DiscardOwnedSizer(); + + bool IsVisible(); + + void Fill(const SizerAddArgs_t& args); + + private: + void RecursiveRemove(bool bDelete); + + Panel* m_pPanel; + CSizerBase* m_pSizer; + + int m_nPadding; + float m_flExpandFactor; + bool m_bMinorExpand; + bool m_bIgnoreMemberMin; + int m_nMinX; + int m_nMinY; + }; + + CUtlVector m_Members; + int m_nMinXSize; + int m_nMinYSize; + }; + + inline int SizerMajorAxis(SizerLayoutDirection_t Dir, int X, int Y) { return (Dir == ESLD_HORIZONTAL) ? X : Y; } + inline int SizerMinorAxis(SizerLayoutDirection_t Dir, int X, int Y) { return (Dir == ESLD_VERTICAL) ? X : Y; } + inline int SizerXAxis(SizerLayoutDirection_t Dir, int MajorAxis, int MinorAxis) { return (Dir == ESLD_HORIZONTAL) ? MajorAxis : MinorAxis; } + inline int SizerYAxis(SizerLayoutDirection_t Dir, int MajorAxis, int MinorAxis) { return (Dir == ESLD_VERTICAL) ? MajorAxis : MinorAxis; } + + class CBoxSizer : public CSizerBase + { + public: + CBoxSizer(SizerLayoutDirection_t LayoutDirection); + + virtual void CalculateSize(); + virtual void DoLayout(int BaseX, int BaseY, int SizeX, int SizeY); + + protected: + SizerLayoutDirection_t m_LayoutDirection; + }; + + + struct OverridableColorEntry + { + char const* name() { return m_pszScriptName; } + + char const* m_pszScriptName; + Color* m_pColor; + Color m_colFromScript; + UtlSymId_t m_sColorNameFromScript; + bool m_bOverridden; + }; + +#define REGISTER_COLOR_AS_OVERRIDABLE( name, scriptname ) \ + AddToOverridableColors( &name, scriptname ); + + +#define DECLARE_VGUI_UNPACK() \ + DECLARE_DMXELEMENT_UNPACK() \ + private: \ + static DmxElementUnpackStructure_t *s_pUnpackParams; \ + public: \ + virtual const DmxElementUnpackStructure_t* GetUnpackStructure() const { return s_pUnpackParams; } + +#define DECLARE_VGUI_UNPACK_NAMESPACE( _namespace ) \ + template friend DmxElementUnpackStructure_t *DmxElementUnpackInit##_namespace(T *); \ + private: \ + static DmxElementUnpackStructure_t *s_pUnpackParams; \ + public: \ + virtual const DmxElementUnpackStructure_t* GetUnpackStructure() const { return s_pUnpackParams; } + +#define BEGIN_VGUI_UNPACK( _structName ) BEGIN_DMXELEMENT_UNPACK( _structName ) +#define END_VGUI_UNPACK( _structName ) \ + END_DMXELEMENT_UNPACK( _structName, s_pUnpackParams ) \ + DmxElementUnpackStructure_t *_structName::s_pUnpackParams = _structName##_UnpackInit::s_pUnpack; + +#define BEGIN_VGUI_UNPACK_NAMESPACE( _nameSpace, _structName ) BEGIN_DMXELEMENT_UNPACK_NAMESPACE( _nameSpace, _structName ) +#define END_VGUI_UNPACK_NAMESPACE( _nameSpace, _structName ) \ + END_DMXELEMENT_UNPACK_NAMESPACE( _nameSpace, _structName, s_pUnpackParams ) \ + DmxElementUnpackStructure_t *_structName::s_pUnpackParams = _namespace##_structName##_UnpackInit::s_pUnpack; + + + class IPanelAnimationPropertyConverter + { + public: + virtual void GetData(Panel* panel, KeyValues* kv, PanelAnimationMapEntry* entry) = 0; + virtual void SetData(Panel* panel, KeyValues* kv, PanelAnimationMapEntry* entry) = 0; + virtual void InitFromDefault(Panel* panel, PanelAnimationMapEntry* entry) = 0; + }; + +#if defined( VGUI_USEKEYBINDINGMAPS ) + enum KeyBindingContextHandle_t + { + INVALID_KEYBINDINGCONTEXT_HANDLE = 0xffffffff, + }; +#endif + +#define PANEL_ROUND_CORNER_TOP_LEFT (1 << 0) +#define PANEL_ROUND_CORNER_TOP_RIGHT (1 << 1) +#define PANEL_ROUND_CORNER_BOTTOM_LEFT (1 << 2) +#define PANEL_ROUND_CORNER_BOTTOM_RIGHT (1 << 3) +#define PANEL_ROUND_CORNER_ALL PANEL_ROUND_CORNER_TOP_LEFT | PANEL_ROUND_CORNER_TOP_RIGHT | PANEL_ROUND_CORNER_BOTTOM_LEFT | PANEL_ROUND_CORNER_BOTTOM_RIGHT + class Panel : public IClientPanel + { + DECLARE_CLASS_SIMPLE_NOBASE(Panel); + DECLARE_DMXELEMENT_UNPACK_NAMESPACE(vgui); + + public: + static void InitPropertyConverters(void); + static void AddPropertyConverter(char const* typeName, IPanelAnimationPropertyConverter* converter); + + Panel(); + Panel(Panel* parent); + Panel(Panel* parent, const char* panelName); + Panel(Panel* parent, const char* panelName, HScheme scheme); + + virtual ~Panel(); + + virtual VPANEL GetVPanel() { return _vpanel; } + HPanel ToHandle() const; + + + void SetName(const char* panelName); + const char* GetName(); + const char* GetClassName(); + + void MakeReadyForUse(); + + void SetPos(int x, int y); + void GetPos(int& x, int& y); + void SetSize(int wide, int tall); + void GetSize(int& wide, int& tall); + void SetBounds(int x, int y, int wide, int tall); + void GetBounds(int& x, int& y, int& wide, int& tall); + int GetWide(); + void SetWide(int wide); + int GetTall(); + void SetTall(int tall); + void SetMinimumSize(int wide, int tall); + void GetMinimumSize(int& wide, int& tall); + bool IsBuildModeEditable(); + void SetBuildModeEditable(bool state); + bool IsBuildModeDeletable(); + void SetBuildModeDeletable(bool state); + bool IsBuildModeActive(); + void SetZPos(int z); + int GetZPos(void); + void SetAlpha(int alpha); + int GetAlpha(); + + virtual void SetVisible(bool state); + virtual bool IsVisible(); + virtual bool IsFullyVisible(); + + virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups); + MESSAGE_FUNC(Repaint, "Repaint"); + virtual void PostMessage(VPANEL target, KeyValues* message, float delaySeconds = 0.0f); + + bool IsWithin(int x, int y); + void LocalToScreen(int& x, int& y); + void ScreenToLocal(int& x, int& y); + void ParentLocalToScreen(int& x, int& y); + void MakePopup(bool showTaskbarIcon = true, bool disabled = false); + virtual void OnMove(); + + virtual Panel* GetParent(); + virtual VPANEL GetVParent(); + virtual void SetParent(Panel* newParent); + virtual void SetParent(VPANEL newParent); + virtual bool HasParent(VPANEL potentialParent); + + int GetChildCount(); + Panel* GetChild(int index); + int FindChildIndexByName(const char* childName); + Panel* FindChildByName(const char* childName, bool recurseDown = false); + Panel* FindSiblingByName(const char* siblingName); + void CallParentFunction(KeyValues* message); + + virtual bool LookupElementBounds(const char* elementName, int& x, int& y, int& wide, int& tall) { return false; } + + virtual void SetAutoDelete(bool state); + virtual bool IsAutoDeleteSet(); + virtual void DeletePanel(); + + virtual void AddActionSignalTarget(Panel* messageTarget); + virtual void AddActionSignalTarget(VPANEL messageTarget); + virtual void RemoveActionSignalTarget(Panel* oldTarget); + virtual void PostActionSignal(KeyValues* message); + virtual bool RequestInfoFromChild(const char* childName, KeyValues* outputData); + virtual void PostMessageToChild(const char* childName, KeyValues* messsage); + virtual void PostMessage(Panel* target, KeyValues* message, float delaySeconds = 0.0f); + virtual bool RequestInfo(KeyValues* outputData); + virtual bool SetInfo(KeyValues* inputData); + virtual void SetSilentMode(bool bSilent); + + virtual void InstallMouseHandler(Panel* pHandler); + + virtual void SetEnabled(bool state); + virtual bool IsEnabled(); + virtual bool IsPopup(); + virtual void GetClipRect(int& x0, int& y0, int& x1, int& y1); + virtual void MoveToFront(); + + enum PinCorner_e + { + PIN_TOPLEFT = 0, + PIN_TOPRIGHT, + PIN_BOTTOMLEFT, + PIN_BOTTOMRIGHT, + PIN_NO, + + PIN_CENTER_TOP, + PIN_CENTER_RIGHT, + PIN_CENTER_BOTTOM, + PIN_CENTER_LEFT, + }; + + enum AutoResize_e + { + AUTORESIZE_NO = 0, + AUTORESIZE_RIGHT, + AUTORESIZE_DOWN, + AUTORESIZE_DOWNANDRIGHT, + }; + + void SetPinCorner(PinCorner_e pinCorner, int nOffsetX, int nOffsetY); + + void SetAutoResize(PinCorner_e pinCorner, AutoResize_e resizeDir, int nPinOffsetX, int nPinOffsetY, int nUnpinnedCornerOffsetX, int nUnpinnedCornerOffsetY); + + AutoResize_e GetAutoResize(); + PinCorner_e GetPinCorner(); + + void GetPinOffset(int& dx, int& dy); + void GetResizeOffset(int& dx, int& dy); + + void PinToSibling(const char* pszSibling, PinCorner_e pinOurCorner, PinCorner_e pinSibling); + void UpdateSiblingPin(void); + + virtual void SetBgColor(Color color); + virtual void SetFgColor(Color color); + virtual Color GetBgColor(); + virtual Color GetFgColor(); + + virtual void SetCursor(HCursor cursor); + virtual HCursor GetCursor(); + virtual void RequestFocus(int direction = 0); + virtual bool HasFocus(); + virtual void InvalidateLayout(bool layoutNow = false, bool reloadScheme = false); + virtual bool RequestFocusPrev(VPANEL panel = NULL); + virtual bool RequestFocusNext(VPANEL panel = NULL); + virtual void SetTabPosition(int position); + virtual int GetTabPosition(); + virtual void SetBorder(IBorder* border); + virtual IBorder* GetBorder(); + virtual void SetPaintBorderEnabled(bool state); + virtual void SetPaintBackgroundEnabled(bool state); + virtual void SetPaintEnabled(bool state); + virtual void SetPostChildPaintEnabled(bool state); + virtual void SetPaintBackgroundType(int type); + virtual void GetInset(int& left, int& top, int& right, int& bottom); + virtual void GetPaintSize(int& wide, int& tall); + virtual void SetBuildGroup(BuildGroup* buildGroup); + virtual bool IsBuildGroupEnabled(); + virtual bool IsCursorNone(); + virtual bool IsCursorOver(); + virtual void MarkForDeletion(); + virtual bool IsLayoutInvalid(); + virtual Panel* HasHotkey(wchar_t key); + virtual bool IsOpaque(); + bool IsRightAligned(); + bool IsBottomAligned(); + bool IsPercentage(); + + virtual HScheme GetScheme(); + virtual void SetScheme(const char* tag); + virtual void SetScheme(HScheme scheme); + virtual Color GetSchemeColor(const char* keyName, IScheme* pScheme); + virtual Color GetSchemeColor(const char* keyName, Color defaultColor, IScheme* pScheme); + + virtual void ApplySchemeSettings(IScheme* pScheme); + + virtual void ApplySettings(KeyValues* inResourceData); + virtual void OnUnserialized(CDmxElement* pElement); + + virtual void GetSettings(KeyValues* outResourceData); + + virtual const char* GetDescription(); + + virtual const char* GetModuleName(); + + virtual void ApplyUserConfigSettings(KeyValues* userConfig); + + virtual void GetUserConfigSettings(KeyValues* userConfig); + + virtual bool HasUserConfigSettings(); + + virtual void OnMessage(const KeyValues* params, VPANEL fromPanel); + MESSAGE_FUNC_CHARPTR(OnCommand, "Command", command); + MESSAGE_FUNC(OnMouseCaptureLost, "MouseCaptureLost"); + MESSAGE_FUNC(OnSetFocus, "SetFocus"); + MESSAGE_FUNC(OnKillFocus, "KillFocus"); + MESSAGE_FUNC(OnDelete, "Delete"); + virtual void OnThink(); + virtual void OnChildAdded(VPANEL child); + virtual void OnSizeChanged(int newWide, int newTall); + + virtual void OnTick(); + + MESSAGE_FUNC_INT_INT(OnCursorMoved, "OnCursorMoved", x, y); + virtual void OnCursorEntered(); + virtual void OnCursorExited(); + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnMouseReleased(MouseCode code); + virtual void OnMouseWheeled(int delta); + + virtual void SetTriplePressAllowed(bool state); + virtual bool IsTriplePressAllowed() const; + virtual void OnMouseTriplePressed(MouseCode code); + + static char const* KeyCodeToString(KeyCode code); + static wchar_t const* KeyCodeToDisplayString(KeyCode code); + static wchar_t const* KeyCodeModifiersToDisplayString(KeyCode code, int modifiers); + + static KeyCode StringToKeyCode(char const* str); +#if defined( VGUI_USEKEYBINDINGMAPS ) + static KeyBindingContextHandle_t CreateKeyBindingsContext(char const* filename, char const* pathID = 0); + virtual void SetKeyBindingsContext(KeyBindingContextHandle_t handle); + virtual KeyBindingContextHandle_t GetKeyBindingsContext() const; + virtual bool IsValidKeyBindingsContext() const; + + static int GetPanelsWithKeyBindingsCount(KeyBindingContextHandle_t handle); + static Panel* GetPanelWithKeyBindings(KeyBindingContextHandle_t handle, int index); + + static void RevertKeyBindings(KeyBindingContextHandle_t handle); + + static void ReloadKeyBindings(KeyBindingContextHandle_t handle); + static void SaveKeyBindings(KeyBindingContextHandle_t handle); + static void SaveKeyBindingsToFile(KeyBindingContextHandle_t handle, char const* filename, char const* pathID = 0); + static void LoadKeyBindings(KeyBindingContextHandle_t handle); + static void LoadKeyBindingsForOnePanel(KeyBindingContextHandle_t handle, Panel* panelOfInterest); + + virtual bool IsKeyRebound(KeyCode code, int modifiers); + virtual bool IsKeyOverridden(KeyCode code, int modifiers); + + virtual void AddKeyBinding(char const* bindingName, int keycode, int modifiers); + + KeyBindingMap_t* LookupBinding(char const* bindingName); + KeyBindingMap_t* LookupBindingByKeyCode(KeyCode code, int modifiers); + void LookupBoundKeys(char const* bindingName, CUtlVector< BoundKey_t* >& list); + BoundKey_t* LookupDefaultKey(char const* bindingName); + PanelKeyBindingMap* LookupMapForBinding(char const* bindingName); + + int GetKeyMappingCount(); + + void RevertKeyBindingsToDefault(); + void RemoveAllKeyBindings(); + void ReloadKeyBindings(); + virtual void EditKeyBindings(); + + void SaveKeyBindingsToBuffer(int level, CUtlBuffer& buf); + bool ParseKeyBindings(KeyValues* kv); + + virtual char const* GetKeyBindingsFile() const; + virtual char const* GetKeyBindingsFilePathID() const; + + void SetAllowKeyBindingChainToParent(bool state); + bool IsKeyBindingChainToParentAllowed() const; +#endif + + virtual void OnKeyCodePressed(KeyCode code); + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnKeyTyped(wchar_t unichar); + virtual void OnKeyCodeReleased(KeyCode code); + virtual void OnKeyFocusTicked(); + + MESSAGE_FUNC(OnMouseFocusTicked, "OnMouseFocusTicked"); + + virtual void PaintBackground(); + virtual void Paint(); + virtual void PaintBorder(); + virtual void PaintBuildOverlay(); + virtual void PostChildPaint(); + virtual void PerformLayout(); + + DECLARE_PANELMAP(); + + virtual VPANEL GetCurrentKeyFocus(); + + BaseTooltip* GetTooltip(); + void SetTooltip(BaseTooltip* pToolTip, const char* pszText); + + virtual bool IsProportional() { return _flags.IsFlagSet(IS_PROPORTIONAL); } + virtual void SetProportional(bool state); + + virtual void SetMouseInputEnabled(bool state); + virtual void SetKeyBoardInputEnabled(bool state); + virtual bool IsMouseInputEnabled(); + virtual bool IsKeyBoardInputEnabled(); + + void DisableMouseInputForThisPanel(bool bDisable); + bool IsMouseInputDisabledForThisPanel() const; + + virtual void DrawTexturedBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha); + virtual void DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, bool hollow = false); + virtual void DrawBoxFade(int x, int y, int wide, int tall, Color color, float normalizedAlpha, unsigned int alpha0, unsigned int alpha1, bool bHorizontal, bool hollow = false); + virtual void DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha); + virtual void DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, int cornerWide, int cornerTall); + + unsigned char GetRoundedCorners() { return m_roundedCorners; } + void SetRoundedCorners(unsigned char cornerFlags) { m_roundedCorners = cornerFlags; } + bool ShouldDrawTopLeftCornerRounded() { return 0 != (m_roundedCorners & PANEL_ROUND_CORNER_TOP_LEFT); } + bool ShouldDrawTopRightCornerRounded() { return 0 != (m_roundedCorners & PANEL_ROUND_CORNER_TOP_RIGHT); } + bool ShouldDrawBottomLeftCornerRounded() { return 0 != (m_roundedCorners & PANEL_ROUND_CORNER_BOTTOM_LEFT); } + bool ShouldDrawBottomRightCornerRounded() { return 0 != (m_roundedCorners & PANEL_ROUND_CORNER_BOTTOM_RIGHT); } + + virtual void SetDragEnabled(bool enabled); + virtual bool IsDragEnabled() const; + + virtual void SetShowDragHelper(bool enabled); + + virtual void OnDragFailed(CUtlVector< KeyValues* >& msglist); + + virtual void SetBlockDragChaining(bool block); + virtual bool IsBlockingDragChaining() const; + + virtual int GetDragStartTolerance() const; + virtual void SetDragSTartTolerance(int nTolerance); + + virtual void SetDropEnabled(bool enabled, float m_flHoverContextTime = 0.0f); + virtual bool IsDropEnabled() const; + + virtual bool GetDropContextMenu(Menu* menu, CUtlVector< KeyValues* >& msglist); + virtual void OnDropContextHoverShow(CUtlVector< KeyValues* >& msglist); + virtual void OnDropContextHoverHide(CUtlVector< KeyValues* >& msglist); + +#if defined( VGUI_USEDRAGDROP ) + virtual DragDrop_t* GetDragDropInfo(); +#endif + virtual void OnGetAdditionalDragPanels(CUtlVector< Panel* >& dragabbles); + + virtual void OnCreateDragData(KeyValues* msg); + virtual bool IsDroppable(CUtlVector< KeyValues* >& msglist); + + virtual void OnDraggablePanelPaint(); + virtual void OnDroppablePanelPaint(CUtlVector< KeyValues* >& msglist, CUtlVector< Panel* >& dragPanels); + + virtual void OnPanelDropped(CUtlVector< KeyValues* >& msglist); + + virtual void OnPanelEnteredDroppablePanel(CUtlVector< KeyValues* >& msglist); + virtual void OnPanelExitedDroppablePanel(CUtlVector< KeyValues* >& msglist); + + virtual Panel* GetDropTarget(CUtlVector< KeyValues* >& msglist); + virtual Panel* GetDragPanel(); + virtual bool IsBeingDragged(); + virtual HCursor GetDropCursor(CUtlVector< KeyValues* >& msglist); + virtual HCursor GetDragFailCursor(CUtlVector< KeyValues* >& msglist) { return dc_no; } + + Color GetDropFrameColor(); + Color GetDragFrameColor(); + + virtual bool CanStartDragging(int startx, int starty, int mx, int my); + + virtual void FillRectSkippingPanel(const Color clr, int x, int y, int w, int h, Panel* skipPanel); + + virtual int GetPaintBackgroundType(); + virtual void GetCornerTextureSize(int& w, int& h); + + bool IsChildOfModalSubTree(); + bool IsChildOfSurfaceModalPanel(); + + bool ShouldHandleInputMessage(); + + virtual void SetSkipChildDuringPainting(Panel* child); + + void SetStartDragWhenMouseExitsPanel(bool state); + bool IsStartDragWhenMouseExitsPanel() const; + + void SetMessageContextId_R(int nContextID); + + void PostMessageToAllSiblings(KeyValues* msg, float delaySeconds = 0.0f); + template< class S > + void PostMessageToAllSiblingsOfType(KeyValues* msg, float delaySeconds = 0.0f); + + void SetConsoleStylePanel(bool bConsoleStyle); + bool IsConsoleStylePanel() const; + + enum NAV_DIRECTION { ND_UP, ND_DOWN, ND_LEFT, ND_RIGHT, ND_BACK, ND_NONE }; + virtual Panel* NavigateUp(); + virtual Panel* NavigateDown(); + virtual Panel* NavigateLeft(); + virtual Panel* NavigateRight(); + virtual void NavigateTo(); + virtual void NavigateFrom(); + virtual void NavigateToChild(Panel* pNavigateTo); + + Panel* SetNavUp(Panel* navUp); + Panel* SetNavDown(Panel* navDown); + Panel* SetNavLeft(Panel* navLeft); + Panel* SetNavRight(Panel* navRight); + NAV_DIRECTION GetLastNavDirection(); + MESSAGE_FUNC_CHARPTR(OnNavigateTo, "OnNavigateTo", panelName); + MESSAGE_FUNC_CHARPTR(OnNavigateFrom, "OnNavigateFrom", panelName); + + protected: + + virtual void OnStartDragging(); + virtual void OnContinueDragging(); + virtual void OnFinishDragging(bool mousereleased, MouseCode code, bool aborted = false); + + virtual void DragDropStartDragging(); + + virtual void GetDragData(CUtlVector< KeyValues* >& list); + virtual void CreateDragData(); + + virtual void PaintTraverse(bool Repaint, bool allowForce = true); + + protected: + MESSAGE_FUNC_ENUM_ENUM(OnRequestFocus, "OnRequestFocus", VPANEL, subFocus, VPANEL, defaultPanel); + MESSAGE_FUNC_INT_INT(OnScreenSizeChanged, "OnScreenSizeChanged", oldwide, oldtall); + virtual void* QueryInterface(EInterfaceID id); + + void AddToOverridableColors(Color* pColor, char const* scriptname) + { + int iIdx = m_OverridableColorEntries.AddToTail(); + m_OverridableColorEntries[iIdx].m_pszScriptName = scriptname; + m_OverridableColorEntries[iIdx].m_pColor = pColor; + m_OverridableColorEntries[iIdx].m_bOverridden = false; + } + + void ApplyOverridableColors(IScheme* pScheme); + void SetOverridableColor(Color* pColor, const Color& newColor); + + protected: + void SetNavUp(const char* controlName); + void SetNavDown(const char* controlName); + void SetNavLeft(const char* controlName); + void SetNavRight(const char* controlName); + + public: + Panel* GetNavUp(Panel* first = NULL); + Panel* GetNavDown(Panel* first = NULL); + Panel* GetNavLeft(Panel* first = NULL); + Panel* GetNavRight(Panel* first = NULL); + + inline void SetWorldPositionCurrentFrame(bool bWorldPositionCurrentFrame) { m_bWorldPositionCurrentFrame = bWorldPositionCurrentFrame; } + inline bool GetWorldPositionCurrentFrame() { return m_bWorldPositionCurrentFrame; } + + protected: + Panel* GetNavUpPanel(); + Panel* GetNavDownPanel(); + Panel* GetNavLeftPanel(); + Panel* GetNavRightPanel(); + + bool m_PassUnhandledInput; + NAV_DIRECTION m_LastNavDirection; + + void InternalInitDefaultValues(PanelAnimationMap* map); + + + private: + enum BuildModeFlags_t + { + BUILDMODE_EDITABLE = 0x01, + BUILDMODE_DELETABLE = 0x02, + BUILDMODE_SAVE_XPOS_RIGHTALIGNED = 0x04, + BUILDMODE_SAVE_XPOS_CENTERALIGNED = 0x08, + BUILDMODE_SAVE_YPOS_BOTTOMALIGNED = 0x10, + BUILDMODE_SAVE_YPOS_CENTERALIGNED = 0x20, + BUILDMODE_SAVE_WIDE_FULL = 0x40, + BUILDMODE_SAVE_TALL_FULL = 0x80, + BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT = 0x100, + BUILDMODE_SAVE_PERCENTAGE = 0x200, + }; + + enum PanelFlags_t + { + MARKED_FOR_DELETION = 0x0001, + NEEDS_REPAINT = 0x0002, + PAINT_BORDER_ENABLED = 0x0004, + PAINT_BACKGROUND_ENABLED = 0x0008, + PAINT_ENABLED = 0x0010, + POST_CHILD_PAINT_ENABLED = 0x0020, + AUTODELETE_ENABLED = 0x0040, + NEEDS_LAYOUT = 0x0080, + NEEDS_SCHEME_UPDATE = 0x0100, + NEEDS_DEFAULT_SETTINGS_APPLIED = 0x0200, +#if defined( VGUI_USEKEYBINDINGMAPS ) + ALLOW_CHAIN_KEYBINDING_TO_PARENT = 0x0400, +#endif + IN_PERFORM_LAYOUT = 0x0800, + IS_PROPORTIONAL = 0x1000, + TRIPLE_PRESS_ALLOWED = 0x2000, + DRAG_REQUIRES_PANEL_EXIT = 0x4000, + IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY = 0x8000, + ALL_FLAGS = 0xFFFF, + }; + + virtual Panel* GetPanel() { return this; } + + void Think(); + void PerformApplySchemeSettings(); + + void InternalPerformLayout(); + void InternalSetCursor(); + + MESSAGE_FUNC_INT_INT(InternalCursorMoved, "CursorMoved", xpos, ypos); + MESSAGE_FUNC(InternalCursorEntered, "CursorEntered"); + MESSAGE_FUNC(InternalCursorExited, "CursorExited"); + + MESSAGE_FUNC_INT(InternalMousePressed, "MousePressed", code); + MESSAGE_FUNC_INT(InternalMouseDoublePressed, "MouseDoublePressed", code); + MESSAGE_FUNC_INT(InternalMouseTriplePressed, "MouseTriplePressed", code); + MESSAGE_FUNC_INT(InternalMouseReleased, "MouseReleased", code); + MESSAGE_FUNC_INT(InternalMouseWheeled, "MouseWheeled", delta); + MESSAGE_FUNC_INT(InternalKeyCodePressed, "KeyCodePressed", code); + MESSAGE_FUNC_INT(InternalKeyCodeTyped, "KeyCodeTyped", code); + MESSAGE_FUNC_INT(InternalKeyTyped, "KeyTyped", unichar); + MESSAGE_FUNC_INT(InternalKeyCodeReleased, "KeyCodeReleased", code); + + MESSAGE_FUNC(InternalKeyFocusTicked, "KeyFocusTicked"); + MESSAGE_FUNC(InternalMouseFocusTicked, "MouseFocusTicked"); + + MESSAGE_FUNC(InternalInvalidateLayout, "Invalidate"); + + MESSAGE_FUNC(InternalMove, "Move"); + virtual void InternalFocusChanged(bool lost); + + void Init(int x, int y, int wide, int tall); + void PreparePanelMap(PanelMap_t* panelMap); + + bool InternalRequestInfo(PanelAnimationMap* map, KeyValues* outputData); + bool InternalSetInfo(PanelAnimationMap* map, KeyValues* inputData); + + PanelAnimationMapEntry* FindPanelAnimationEntry(char const* scriptname, PanelAnimationMap* map); + + void InternalApplySettings(PanelAnimationMap* map, KeyValues* inResourceData); + + void ApplyAutoResizeSettings(KeyValues* inResourceData); + + void FindDropTargetPanel_R(CUtlVector< VPANEL >& panelList, int x, int y, VPANEL check); + Panel* FindDropTargetPanel(); + + int GetProportionalScaledValue(int rootTall, int normalizedValue); + +#if defined( VGUI_USEDRAGDROP ) + DragDrop_t* m_pDragDrop; + Color m_clrDragFrame; + Color m_clrDropFrame; +#endif + + BaseTooltip* m_pTooltips; + bool m_bToolTipOverridden; + + PHandle m_SkipChild; + long m_lLastDoublePressTime; + HFont m_infoFont; + +#if defined( VGUI_USEKEYBINDINGMAPS ) + KeyBindingContextHandle_t m_hKeyBindingsContext; +#endif + + VPANEL _vpanel; + CUtlString _panelName; + IBorder* _border; + + CUtlFlags< unsigned short > _flags; + Dar _actionSignalTargetDar; + + CUtlVector m_OverridableColorEntries; + + Color _fgColor; + Color _bgColor; + + HBuildGroup _buildGroup; + + short m_nPinDeltaX; + short m_nPinDeltaY; + short m_nResizeDeltaX; + short m_nResizeDeltaY; + + HCursor _cursor; + unsigned short _buildModeFlags; + + byte _pinCorner : 4; + byte _autoResizeDirection : 4; + + GCC_DIAG_PUSH_OFF(overflow) + + DECLARE_DMXELEMENT_BITFIELD(_pinCorner, byte, Panel) + DECLARE_DMXELEMENT_BITFIELD(_autoResizeDirection, byte, Panel) + + GCC_DIAG_POP() + + unsigned char _tabPosition; + HScheme m_iScheme; + + bool m_bIsDMXSerialized : 1; + bool m_bUseSchemeColors : 1; + bool m_bIsSilent : 1; + bool m_bIsConsoleStylePanel : 1; + + DECLARE_DMXELEMENT_BITFIELD(m_bUseSchemeColors, bool, Panel) + DECLARE_DMXELEMENT_BITFIELD(m_bIsSilent, bool, Panel) + + char* _pinToSibling; + byte _pinToSiblingCorner; + byte _pinCornerToSibling; + PHandle m_pinSibling; + + char* _tooltipText; + + PHandle m_hMouseEventHandler; + + bool m_bWorldPositionCurrentFrame; + CUtlSymbol m_sBorderName; + + protected: + CUtlString m_sNavUpName; + PHandle m_NavUp; + + CUtlString m_sNavDownName; + PHandle m_NavDown; + + CUtlString m_sNavLeftName; + PHandle m_NavLeft; + + CUtlString m_sNavRightName; + PHandle m_NavRight; + protected: + static int s_NavLock; + + private: + + CPanelAnimationVar(float, m_flAlpha, "alpha", "255"); + + CPanelAnimationVar(int, m_nPaintBackgroundType, "PaintBackgroundType", "0"); + CPanelAnimationVarAliasType(int, m_nBgTextureId1, "Texture1", "vgui/hud/800corner1", "textureid"); + CPanelAnimationVarAliasType(int, m_nBgTextureId2, "Texture2", "vgui/hud/800corner2", "textureid"); + CPanelAnimationVarAliasType(int, m_nBgTextureId3, "Texture3", "vgui/hud/800corner3", "textureid"); + CPanelAnimationVarAliasType(int, m_nBgTextureId4, "Texture4", "vgui/hud/800corner4", "textureid"); + + unsigned char m_roundedCorners; + friend class BuildGroup; + friend class BuildModeDialog; + friend class PHandle; + + void OnOldMessage(KeyValues* params, VPANEL ifromPanel); + + public: + + virtual void GetSizerMinimumSize(int& wide, int& tall); + virtual void GetSizerClientArea(int& x, int& y, int& wide, int& tall); + CSizerBase* GetSizer(); + void SetSizer(CSizerBase* pSizer); + + protected: + + CSizerBase* m_pSizer; + }; + + inline void Panel::DisableMouseInputForThisPanel(bool bDisable) + { + _flags.SetFlag(IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY, bDisable); + } + + inline bool Panel::IsMouseInputDisabledForThisPanel() const + { + return _flags.IsFlagSet(IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY); + } + + template< class S > + inline void Panel::PostMessageToAllSiblingsOfType(KeyValues* msg, float delaySeconds ) + { + Panel* parent = GetParent(); + if (parent) + { + int nChildCount = parent->GetChildCount(); + for (int i = 0; i < nChildCount; ++i) + { + Panel* sibling = parent->GetChild(i); + if (sibling == this) + continue; + if (dynamic_cast(sibling)) + { + PostMessage(sibling->GetVPanel(), msg->MakeCopy(), delaySeconds); + } + } + } + + msg->deleteThis(); + } + +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/PanelAnimationVar.h b/SpyCustom/PanelAnimationVar.h new file mode 100644 index 0000000..8b84555 --- /dev/null +++ b/SpyCustom/PanelAnimationVar.h @@ -0,0 +1,153 @@ +#ifndef PANELANIMATIONVAR_H +#define PANELANIMATIONVAR_H +#ifdef _WIN32 +#pragma once +#endif + +#include "utlvector.h" +#include "Panel.h" + +#define DECLARE_PANELANIMATION( className ) \ + static void AddToAnimationMap( char const *scriptname, char const *type, char const *var, \ + char const *defaultvalue, bool array, PANELLOOKUPFUNC func ) \ + { \ + PanelAnimationMap *map = FindOrAddPanelAnimationMap( GetPanelClassName() ); \ + \ + PanelAnimationMapEntry entry; \ + entry.m_pszScriptName = scriptname; \ + entry.m_pszVariable = var; \ + entry.m_pszType = type; \ + entry.m_pszDefaultValue = defaultvalue; \ + entry.m_pfnLookup = func; \ + entry.m_bArray = array; \ + \ + map->entries.AddToTail( entry ); \ + } \ + \ + static void ChainToAnimationMap( void ) \ + { \ + static bool chained = false; \ + if ( chained ) \ + return; \ + chained = true; \ + PanelAnimationMap *map = FindOrAddPanelAnimationMap( GetPanelClassName() ); \ + map->pfnClassName = GetPanelClassName; \ + if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ + { \ + map->baseMap = FindOrAddPanelAnimationMap( GetPanelBaseClassName() ); \ + } \ + } \ + \ + class className##_Register; \ + friend class className##_Register; \ + class className##_Register \ + { \ + public: \ + className##_Register() \ + { \ + className::ChainToAnimationMap(); \ + } \ + }; \ + className##_Register m_RegisterAnimationClass; \ + \ + virtual PanelAnimationMap *GetAnimMap() \ + { \ + return FindOrAddPanelAnimationMap( GetPanelClassName() ); \ + } + +typedef void* (*PANELLOOKUPFUNC)(vgui::Panel* panel); + +#define CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, typealias ) \ + class PanelAnimationVar_##name; \ + friend class PanelAnimationVar_##name; \ + static void *GetVar_##name( vgui::Panel *panel ) \ + { \ + return &(( ThisClass *)panel)->name; \ + } \ + class PanelAnimationVar_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + AddToAnimationMap( scriptname, typealias, #name, defaultvalue, false, ThisClass::GetVar_##name ); \ + } \ + } \ + PanelAnimationVar_##name() \ + { \ + PanelAnimationVar_##name::InitVar(); \ + } \ + }; \ + PanelAnimationVar_##name m_##name##_register; \ + type name; + +#define CPanelAnimationVar( type, name, scriptname, defaultvalue ) \ + CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, #type ) + +#define CPanelAnimationStringVarAliasType( count, name, scriptname, defaultvalue, typealias ) \ + class PanelAnimationVar_##name; \ + friend class PanelAnimationVar_##name; \ + static void *GetVar_##name( vgui::Panel *panel ) \ + { \ + return &(( ThisClass *)panel)->name; \ + } \ + class PanelAnimationVar_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + AddToAnimationMap( scriptname, typealias, #name, defaultvalue, true, ThisClass::GetVar_##name ); \ + } \ + } \ + PanelAnimationVar_##name() \ + { \ + PanelAnimationVar_##name::InitVar(); \ + } \ + }; \ + PanelAnimationVar_##name m_##name##_register; \ + char name[ count ]; + +#define CPanelAnimationStringVar( count, name, scriptname, defaultvalue ) \ + CPanelAnimationStringVarAliasType( count, name, scriptname, defaultvalue, "string" ) + +struct PanelAnimationMapEntry +{ + char const* name() { return m_pszScriptName; } + char const* type() { return m_pszType; } + char const* defaultvalue() { return m_pszDefaultValue; } + bool isarray() { return m_bArray; } + + char const* m_pszScriptName; + char const* m_pszVariable; + char const* m_pszType; + char const* m_pszDefaultValue; + bool m_bArray; + + PANELLOOKUPFUNC m_pfnLookup; +}; + +struct PanelAnimationMap +{ + PanelAnimationMap() + { + baseMap = NULL; + pfnClassName = NULL; + } + + CUtlVector< PanelAnimationMapEntry > entries; + PanelAnimationMap* baseMap; + char const* (*pfnClassName)(void); +}; + +PanelAnimationMap* FindPanelAnimationMap(char const* className); +PanelAnimationMap* FindOrAddPanelAnimationMap(char const* className); +void PanelAnimationDumpVars(char const* className); + +#endif \ No newline at end of file diff --git a/SpyCustom/ParticleSphereRenderer.h b/SpyCustom/ParticleSphereRenderer.h new file mode 100644 index 0000000..ac7316a --- /dev/null +++ b/SpyCustom/ParticleSphereRenderer.h @@ -0,0 +1,210 @@ +#ifndef PARTICLESPHERERENDERER_H +#define PARTICLESPHERERENDERER_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "particlemgr.h" +#include "particle_util.h" + + +class CParticleSphereRenderer +{ +public: + + CParticleSphereRenderer(); + + void Init(CParticleMgr* pParticleMgr, IMaterial* pMaterial); + + void StartRender(VMatrix& effectMatrix); + + void RenderParticle( + ParticleDraw* pDraw, + const Vector& vOriginalPos, + const Vector& vTransformedPos, + float flAlpha, + float flParticleSize, + float flAngle = 0.0f); + + void RenderParticle_AddColor( + ParticleDraw* pDraw, + const Vector& vOriginalPos, + const Vector& vTransformedPos, + float flAlpha, + float flParticleSize, + const Vector& vToAdd0to1 + ); + + + const Vector& GetBaseColor() const; + void SetBaseColor(const Vector& vColor); + + const CParticleLightInfo& GetAmbientLight() const; + void SetAmbientLight(const CParticleLightInfo& info); + + const CParticleLightInfo& GetDirectionalLight() const; + void SetDirectionalLight(const CParticleLightInfo& info); + + +private: + + void AddLightColor( + Vector const* pPos, + Vector const* pLightPos, + Vector const* pLightColor, + float flLightIntensity, + Vector* pOutColor); + + inline void ClampColor(Vector& vColor); + + +private: + + int m_iLastTickStartRenderCalled; + + CParticleMgr* m_pParticleMgr; + + Vector m_vBaseColor; + CParticleLightInfo m_AmbientLight; + CParticleLightInfo m_DirectionalLight; + bool m_bUsingPixelShaders; +}; + + +inline void CParticleSphereRenderer::AddLightColor( + Vector const* pPos, + Vector const* pLightPos, + Vector const* pLightColor, + float flLightIntensity, + Vector* pOutColor) +{ + if (flLightIntensity) + { + float fDist = pPos->DistToSqr(*pLightPos); + float fAmt; + if (fDist > 0.0001f) + fAmt = flLightIntensity / fDist; + else + fAmt = 1000.f; + + *pOutColor += *pLightColor * fAmt; + } +} + + +inline void CParticleSphereRenderer::ClampColor(Vector& vColor) +{ + float flMax = MAX(vColor.x, MAX(vColor.y, vColor.z)); + if (flMax > 1) + { + vColor *= 255.0f / flMax; + } + else + { + vColor *= 255.0; + } +} + + +inline const Vector& CParticleSphereRenderer::GetBaseColor() const +{ + return m_vBaseColor; +} + +inline void CParticleSphereRenderer::SetBaseColor(const Vector& vColor) +{ + m_vBaseColor = vColor; +} + +inline const CParticleLightInfo& CParticleSphereRenderer::GetAmbientLight() const +{ + return m_AmbientLight; +} + +inline void CParticleSphereRenderer::SetAmbientLight(const CParticleLightInfo& info) +{ + m_AmbientLight = info; +} + +inline const CParticleLightInfo& CParticleSphereRenderer::GetDirectionalLight() const +{ + return m_DirectionalLight; +} + +inline void CParticleSphereRenderer::SetDirectionalLight(const CParticleLightInfo& info) +{ + m_DirectionalLight = info; +} + +inline void CParticleSphereRenderer::RenderParticle( + ParticleDraw* pDraw, + const Vector& vOriginalPos, + const Vector& vTransformedPos, + float flAlpha, + float flParticleSize, + float flAngle) +{ +#ifdef _DEBUG + if (pDraw->GetMeshBuilder()) + { + Assert(m_iLastTickStartRenderCalled == gpGlobals->tickcount); + } +#endif + + Vector vColor = m_vBaseColor; + AddLightColor(&vOriginalPos, &m_AmbientLight.m_vPos, &m_AmbientLight.m_vColor, m_AmbientLight.m_flIntensity, &vColor); + + if (!m_bUsingPixelShaders) + { + AddLightColor(&vOriginalPos, &m_DirectionalLight.m_vPos, &m_DirectionalLight.m_vColor, m_DirectionalLight.m_flIntensity, &vColor); + } + + ClampColor(vColor); + + RenderParticle_Color255SizeNormalAngle( + pDraw, + vTransformedPos, + vColor, + flAlpha, + flParticleSize, + vec3_origin, + flAngle); +} + +inline void CParticleSphereRenderer::RenderParticle_AddColor( + ParticleDraw* pDraw, + const Vector& vOriginalPos, + const Vector& vTransformedPos, + float flAlpha, + float flParticleSize, + const Vector& vToAdd0to1 +) +{ +#ifdef _DEBUG + if (pDraw->GetMeshBuilder()) + { + Assert(m_iLastTickStartRenderCalled == gpGlobals->tickcount); + } +#endif + + Vector vColor = m_vBaseColor + vToAdd0to1; + AddLightColor(&vOriginalPos, &m_AmbientLight.m_vPos, &m_AmbientLight.m_vColor, m_AmbientLight.m_flIntensity, &vColor); + + if (!m_bUsingPixelShaders) + { + AddLightColor(&vOriginalPos, &m_DirectionalLight.m_vPos, &m_DirectionalLight.m_vColor, m_DirectionalLight.m_flIntensity, &vColor); + } + + ClampColor(vColor); + + RenderParticle_Color255Size( + pDraw, + vTransformedPos, + vColor, + flAlpha, + flParticleSize); +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/PatternScan.cpp b/SpyCustom/PatternScan.cpp new file mode 100644 index 0000000..febaa17 --- /dev/null +++ b/SpyCustom/PatternScan.cpp @@ -0,0 +1,76 @@ +#include "PatternScan.hpp" + + +DWORD WaitOnModuleHandle(std::string moduleName) +{ + DWORD ModuleHandle = NULL; + while (!ModuleHandle) + { + ModuleHandle = (DWORD)GetModuleHandle(moduleName.c_str()); + if (!ModuleHandle) + Sleep(50); + } + return ModuleHandle; +} + +DWORD FindPatternV2(std::string moduleName, std::string pattern) +{ + const char* pat = pattern.c_str(); + DWORD firstMatch = 0; + DWORD rangeStart = (DWORD)GetModuleHandleA(moduleName.c_str()); + MODULEINFO miModInfo; GetModuleInformation(GetCurrentProcess(), (HMODULE)rangeStart, &miModInfo, sizeof(MODULEINFO)); + DWORD rangeEnd = rangeStart + miModInfo.SizeOfImage; + for (DWORD pCur = rangeStart; pCur < rangeEnd; pCur++) + { + if (!*pat) + return firstMatch; + + if (*(PBYTE)pat == '\?' || *(BYTE*)pCur == getByte(pat)) + { + if (!firstMatch) + firstMatch = pCur; + + if (!pat[2]) + return firstMatch; + + if (*(PWORD)pat == '\?\?' || *(PBYTE)pat != '\?') + pat += 3; + + else + pat += 2; + } + else + { + pat = pattern.c_str(); + firstMatch = 0; + } + } + return NULL; +} + +bool bCompare(const BYTE* Data, const BYTE* Mask, const char* szMask) +{ + for (; *szMask; ++szMask, ++Mask, ++Data) + { + if (*szMask == 'x' && *Mask != *Data) + { + return false; + } + } + return (*szMask) == 0; +} + +DWORD FindPattern(std::string moduleName, BYTE* Mask, char* szMask) +{ + DWORD Address = WaitOnModuleHandle(moduleName.c_str()); + MODULEINFO ModInfo; GetModuleInformation(GetCurrentProcess(), (HMODULE)Address, &ModInfo, sizeof(MODULEINFO)); + DWORD Length = ModInfo.SizeOfImage; + for (DWORD c = 0; c < Length; c += 1) + { + if (bCompare((BYTE*)(Address + c), Mask, szMask)) + { + return (DWORD)(Address + c); + } + } + return 0; +} \ No newline at end of file diff --git a/SpyCustom/PatternScan.hpp b/SpyCustom/PatternScan.hpp new file mode 100644 index 0000000..bd07ada --- /dev/null +++ b/SpyCustom/PatternScan.hpp @@ -0,0 +1,20 @@ +#ifndef PATTERNSCAN +#define PATTERNSCAN +#pragma once + +#include +#include +#include +#define INRANGE(x,a,b) (x >= a && x <= b) +#define getBits( x ) (INRANGE((x&(~0x20)),'A','F') ? ((x&(~0x20)) - 'A' + 0xa) : (INRANGE(x,'0','9') ? x - '0' : 0)) +#define getByte( x ) (getBits(x[0]) << 4 | getBits(x[1])) + +DWORD WaitOnModuleHandle(std::string moduleName); +DWORD FindPatternV2(std::string moduleName, std::string pattern); +bool bCompare(const BYTE* Data, const BYTE* Mask, const char* szMask); +DWORD FindPattern(std::string moduleName, BYTE* Mask, char* szMask); + + + +#endif + diff --git a/SpyCustom/PlayerInventory.cpp b/SpyCustom/PlayerInventory.cpp new file mode 100644 index 0000000..2a1634a --- /dev/null +++ b/SpyCustom/PlayerInventory.cpp @@ -0,0 +1,207 @@ +#include "PlayerInventory.hpp" + + +void CSharedObjectTypeCache::AddObject(void* obj) +{ + typedef void(__thiscall* tOriginal)(void*, void*); + getvfunc(this, 1)(this, obj); +} + +void CSharedObjectTypeCache::RemoveObject(void* obj) +{ + typedef void(__thiscall* tOriginal)(void*, void*); + getvfunc(this, 3)(this, obj); +} + +std::vector CSharedObjectTypeCache::GetEconItems() +{ + std::vector ret; + + auto size = *reinterpret_cast(this + 0x18); + + auto data = *reinterpret_cast(this + 0x4); + + for (size_t i = 0; i < size; i++) + ret.push_back(reinterpret_cast(data[i])); + + return ret; +} + + +template +void CEconItem::SetAttributeValue(int index, TYPE val) +{ + auto v15 = (DWORD*)GetItemSchema(); + auto v16 = *(DWORD*)(v15[72] + 4 * index); + + static auto fnSetDynamicAttributeValue + = reinterpret_cast( + FindPatternV2("client.dll", "55 8B EC 83 E4 F8 83 EC 3C 53 8B 5D 08 56 57 6A 00") + ); + + fnSetDynamicAttributeValue(this, v16, &val); +} + + + + +int C_EconItemDefinition::get_equipped_position() +{ + return *reinterpret_cast(reinterpret_cast(this) + 0x24C); +} + +const char* C_EconItemDefinition::get_world_model_name() +{ + return *reinterpret_cast(uintptr_t(this) + 0x9C); +} + + + + + +uint32_t* CEconItem::GetAccountID() +{ + return reinterpret_cast(this + 0x1C); +} +uint64_t* CEconItem::GetItemID() +{ + return reinterpret_cast(this + 0x8); +} + +uint64_t* CEconItem::GetOriginalID() +{ + return reinterpret_cast(this + 0x10); +} + +uint16_t* CEconItem::GetDefIndex() +{ + return reinterpret_cast(this + 0x24); +} + +uint32_t* CEconItem::GetInventory() +{ + return reinterpret_cast(this + 0x20); +} + +unsigned char* CEconItem::GetFlags() +{ + return reinterpret_cast(this + 0x30); +} + +unsigned short* CEconItem::GetEconItemData() +{ + return reinterpret_cast(this + 0x26); +} + + + +C_EconItemDefinition* C_EconItemView::get_static_data() +{ + static auto fn = reinterpret_cast(FindPatternV2("client.dll", "55 8B EC 51 53 8B D9 8B ? ? ? ? ? 56 57 8B ? ? ? ? ? 85 FF 74 16")); + + return fn(this); +} + + +CEconItem* C_EconItemView::get_soc_data() +{ + static auto fn = reinterpret_cast(FindPatternV2("client.dll", "55 8B EC 83 E4 F0 83 EC 18 56 8B F1 57 8B 86")); + + return fn(this); +} + + + +void CPlayerInventory::RemoveItem(uint64_t ID) +{ + static auto fnRemoveItem + = reinterpret_cast( + FindPatternV2("client.dll", "55 8B EC 83 E4 F8 56 57 FF 75 0C 8B F1") + ); + + fnRemoveItem(this, ID); +} + +CSharedObjectTypeCache* CPlayerInventory::GetBaseTypeCache() +{ + static auto fnGCSDK_CGCClient_FindSOCache + = reinterpret_cast( + FindPatternV2("client.dll", "55 8B EC 83 E4 F8 83 EC 1C 0F 10 45 08") + ); + + static auto fnGCSDK_CSharedObjectCache_CreateBaseTypeCache + = reinterpret_cast( + FindPatternV2("client.dll", "55 8B EC 51 53 56 8B D9 8D 45 08") + ); + + static auto g_GCClientSystem = **reinterpret_cast(FindPatternV2("client.dll", "8B 0D ? ? ? ? 6A 00 83 EC 10") + 0x2); + auto SOCahce = fnGCSDK_CGCClient_FindSOCache(g_GCClientSystem + 0x60, *reinterpret_cast(this + 0x8), *reinterpret_cast(this + 0x10), 0); + + return fnGCSDK_CSharedObjectCache_CreateBaseTypeCache(SOCahce, 1); +} + +void CPlayerInventory::RemoveItem(CEconItem* item) +{ + RemoveItem(*item->GetItemID()); + GetBaseTypeCache()->RemoveObject(item); +} + +void CPlayerInventory::ClearInventory() +{ + auto BaseTypeCache = this->GetBaseTypeCache(); + auto items = BaseTypeCache->GetEconItems(); + for (auto item : items) + { + RemoveItem(*item->GetItemID()); + BaseTypeCache->RemoveObject(item); + } +} + +uint32_t CPlayerInventory::GetSteamID() +{ + return *reinterpret_cast(this + 0x8); +} + +CUtlVector< C_EconItemView* >* CPlayerInventory::GetInventoryItems() +{ + return reinterpret_cast*>(this + 0x2C); +} + +bool CPlayerInventory::AddEconItem(CEconItem* item, int a3, int a4, char a5) +{ + static auto fnAddEconItem + = reinterpret_cast( + FindPatternV2("client.dll", "55 8B EC 83 E4 F8 A1 ? ? ? ? 83 EC 14 53 56 57 8B F9 8B 08") + ); + + GetBaseTypeCache()->AddObject(item); + + + auto ret = fnAddEconItem(this, item, a3, a4, a5); + + return ret; +} + + +CPlayerInventory* CSInventoryManager::GetLocalPlayerInventory() +{ + static auto local_inventory_offset = *reinterpret_cast(FindPatternV2("client.dll", "8B 8B ? ? ? ? E8 ? ? ? ? 89 44 24 18") + 0x2); + return *reinterpret_cast(this + local_inventory_offset); +} + +CEconItem* CreateEconItem() +{ + static auto fnCreateSharedObjectSubclass_EconItem_ + = reinterpret_cast( + *reinterpret_cast(FindPatternV2("client.dll", "C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4 C7 45 ? ? ? ? ? 50 C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4 C7 45 ? ? ? ? ? 50 C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4 C7 45 ? ? ? ? ? 50 C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4") + 3) + ); + return fnCreateSharedObjectSubclass_EconItem_(); +} +uintptr_t GetItemSchema() +{ + static auto fnGetItemSchema + = reinterpret_cast( + FindPatternV2("client.dll", "A1 ? ? ? ? 85 C0 75 53") + ); + return fnGetItemSchema(); +} diff --git a/SpyCustom/PlayerInventory.hpp b/SpyCustom/PlayerInventory.hpp new file mode 100644 index 0000000..e36667b --- /dev/null +++ b/SpyCustom/PlayerInventory.hpp @@ -0,0 +1,138 @@ +#ifndef PLAYERINV +#define PLAYERINV +#pragma once + +#include "PatternScan.hpp" +#include "Interfaces.hpp" + +#include "utlvector.h" +#include "stdint.h" +#include + +#include "icliententity.h" + + + +enum ItemQuality +{ + ITEM_QUALITY_DEFAULT, + ITEM_QUALITY_GENUINE, + ITEM_QUALITY_VINTAGE, + ITEM_QUALITY_UNUSUAL, + ITEM_QUALITY_SKIN, + ITEM_QUALITY_COMMUNITY, + ITEM_QUALITY_DEVELOPER, + ITEM_QUALITY_SELFMADE, + ITEM_QUALITY_CUSTOMIZED, + ITEM_QUALITY_STRANGE, + ITEM_QUALITY_COMPLETED, + ITEM_QUALITY_UNK2, + ITEM_QUALITY_TOURNAMENT +}; + +enum ItemRarity +{ + ITEM_RARITY_DEFAULT, + ITEM_RARITY_COMMON, + ITEM_RARITY_UNCOMMON, + ITEM_RARITY_RARE, + ITEM_RARITY_MYTHICAL, + ITEM_RARITY_LEGENDARY, + ITEM_RARITY_ANCIENT, + ITEM_RARITY_IMMORTAL +}; + +class CEconItem +{ + unsigned short* GetEconItemData(); + void UpdateEquippedState(unsigned int state); +public: + uint32_t* GetInventory(); + uint32_t* GetAccountID(); + uint16_t* GetDefIndex(); + uint64_t* GetItemID(); + uint64_t* GetOriginalID(); + unsigned char* GetFlags(); + void SetQuality(ItemQuality quality); + void SetRarity(ItemRarity rarity); + void SetOrigin(int origin); + void SetLevel(int level); + void SetInUse(bool in_use); + void SetCustomName(const char* name); + void SetCustomDesc(const char* name); + void SetPaintSeed(float seed); + void SetPaintKit(float kit); + void SetPaintWear(float wear); + void SetStatTrak(int val); + void AddSticker(int index, int kit, float wear, float scale, float rotation); + + template + void SetAttributeValue(int index, TYPE val); + +}; + +class C_EconItemDefinition +{ +public: + int get_equipped_position(); + const char* get_world_model_name(); +}; + +class C_EconItemView +{ +private: + using str_32 = char[32]; +public: + int32_t m_bInitialized; + int16_t m_iItemDefinitionIndex; + int32_t m_iEntityLevel; + int32_t m_iAccountID; + int32_t m_iItemIDLow; + int32_t m_iItemIDHigh; + int32_t m_iEntityQuality; + str_32 m_iCustomName; + + CUtlVector& m_CustomMaterials(); + CUtlVector& m_VisualsDataProcessors(); + + C_EconItemDefinition* get_static_data(); + CEconItem* get_soc_data(); +}; + + +class CSharedObjectTypeCache +{ +public: + void AddObject(void* obj); + void RemoveObject(void* obj); + std::vector GetEconItems(); +}; + + +class CPlayerInventory +{ +public: + void RemoveItem(uint64_t ID); + void RemoveItem(CEconItem* item); + void ClearInventory(); + CSharedObjectTypeCache* GetBaseTypeCache(); + uint32_t GetSteamID(); + CUtlVector* GetInventoryItems(); + bool AddEconItem(CEconItem* item, int a3, int a4, char a5); +}; + + +class CSInventoryManager +{ +public: + CPlayerInventory* GetLocalPlayerInventory(); +}; + + +uintptr_t GetItemSchema(); +CEconItem* CreateEconItem(); + + + + +#endif \ No newline at end of file diff --git a/SpyCustom/ProtoParse.h b/SpyCustom/ProtoParse.h new file mode 100644 index 0000000..c18f0b8 --- /dev/null +++ b/SpyCustom/ProtoParse.h @@ -0,0 +1,581 @@ +#pragma once +#include +#include +#include + +#define MAKE_TAG(FIELD_NUMBER, TYPE) static_cast(((FIELD_NUMBER) << kTagTypeBits) | (TYPE)) + +#define make_struct(_name_, _size_) \ + struct _name_ : ProtoWriter { \ + constexpr static size_t MAX_FIELD = _size_; \ + _name_() : ProtoWriter(MAX_FIELD) {} \ + _name_(void* data, size_t size) : ProtoWriter(data, size, MAX_FIELD) {} \ + _name_(std::string data) : ProtoWriter(data, MAX_FIELD) {} + +#define make_field(_name_, _id_, _type_) \ + constexpr static Tag _name_ = { _id_, _type_ }; \ + void clear_##_name_() { this->clear(_name_); } \ + bool has_##_name_() { return this->has(_name_); } \ + Field get_##_name_() { return this->get(_name_); } \ + std::vector getAll_##_name_() { return this->getAll(_name_); } \ + \ + void add_##_name_(std::string v) { this->add(_name_, v); } \ + template void add_##_name_(T v) { this->add(_name_, v); } \ + void replace_##_name_(std::string v) { this->replace(_name_, v); } \ + void replace_##_name_(std::string v, uint32_t index) { this->replace(_name_, v, index); } \ + template void replace_##_name_(T v) { this->replace(_name_, v); } \ + template void replace_##_name_(T v, uint32_t index) { this->replace(_name_, v, index); } \ + template T get_##_name_() { return std::move( T(this->get(_name_).String()) ); } + + +struct Tag +{ + unsigned field; + unsigned type; +}; + +enum FieldType { + TYPE_DOUBLE = 1, + TYPE_FLOAT = 2, + TYPE_INT64 = 3, + TYPE_UINT64 = 4, + TYPE_INT32 = 5, + TYPE_FIXED64 = 6, + TYPE_FIXED32 = 7, + TYPE_BOOL = 8, + TYPE_STRING = 9, + TYPE_GROUP = 10, + TYPE_MESSAGE = 11, + TYPE_BYTES = 12, + TYPE_UINT32 = 13, + TYPE_ENUM = 14, + TYPE_SFIXED32 = 15, + TYPE_SFIXED64 = 16, + TYPE_SINT32 = 17, + TYPE_SINT64 = 18, + MAX_FIELD_TYPE = 18, +}; + +struct Field +{ + friend class ProtoWriter; +public: + inline Field& operator=(const Field& f); + + Field() : tag({ 0,0 }), value(""), full("") { } + Field(unsigned field, unsigned type, std::string value, std::string full); + + Field(Tag tag, std::string value); + Field(unsigned field, unsigned type, std::string value); + + template + Field(Tag tag, T value); + + template + Field(unsigned field, unsigned type, T value); + +public: + static Field ReadField(void* data, size_t& bytesRead); + +public: + inline float Float(); + inline double Double(); + inline int32_t Int32(); + inline int64_t Int64(); + inline uint32_t UInt32(); + inline uint64_t UInt64(); + inline uint32_t Fixed32(); + inline uint64_t Fixed64(); + inline int32_t SFixed32(); + inline int64_t SFixed64(); + inline bool Bool(); + inline std::string String(); + +private: + Tag tag; + std::string value; + std::string full; + + static std::string getBytesVarint32(uint32_t value); + static std::string getBytesVarint64(uint64_t value); + static uint32_t readVarUint32(void* data, size_t& bytesRead); + static uint64_t readVarUint64(void* data, size_t& bytesRead); + + enum WireType { + WIRETYPE_VARINT = 0, + WIRETYPE_FIXED64 = 1, + WIRETYPE_LENGTH_DELIMITED = 2, + WIRETYPE_START_GROUP = 3, + WIRETYPE_END_GROUP = 4, + WIRETYPE_FIXED32 = 5, + }; + + constexpr static WireType kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = { + static_cast(-1), + WIRETYPE_FIXED64, + WIRETYPE_FIXED32, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + WIRETYPE_FIXED64, + WIRETYPE_FIXED32, + WIRETYPE_VARINT, + WIRETYPE_LENGTH_DELIMITED, + WIRETYPE_START_GROUP, + WIRETYPE_LENGTH_DELIMITED, + WIRETYPE_LENGTH_DELIMITED, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + WIRETYPE_FIXED32, + WIRETYPE_FIXED64, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + }; + + constexpr static int kTagTypeBits = 3; + constexpr static uint32_t kTagTypeMask = (1 << kTagTypeBits) - 1; + constexpr static int kMaxVarintBytes = 10; + constexpr static int kMaxVarint32Bytes = 5; +}; + +class ProtoWriter +{ +public: + inline ProtoWriter(); + inline ProtoWriter(size_t maxFields); + inline ProtoWriter(void* data, size_t size, size_t maxFields); + inline ProtoWriter(std::string dataStr, size_t maxFields); + +public: + inline void add(Field field); + inline void replace(Field field); + inline void replace(Field field, uint32_t index); + inline void clear(unsigned fieldId); + inline bool has(unsigned fieldId); + inline Field get(unsigned fieldId); + inline std::vector getAll(unsigned fieldId); + +public: + inline void add(Tag tag, std::string value); + inline void replace(Tag tag, std::string value); + inline void replace(Tag tag, std::string value, uint32_t index); + inline void clear(Tag tag); + inline bool has(Tag tag); + inline Field get(Tag tag); + inline std::vector getAll(Tag tag); + + template + inline void add(Tag tag, T value); + + template + inline void replace(Tag tag, T value); + + template + inline void replace(Tag tag, T value, uint32_t index); + + + std::string serialize(); + void print(); + +private: + std::vector> fields; +}; + +#pragma region Helper Functions +std::string Field::getBytesVarint32(uint32_t value) +{ + uint8_t bytes[kMaxVarint32Bytes]; + int size = 0; + while (value > 0x7F) { + bytes[size++] = (static_cast(value) & 0x7F) | 0x80; + value >>= 7; + } + bytes[size++] = static_cast(value) & 0x7F; + return std::string{ reinterpret_cast(&bytes[0]), (size_t)size }; +} + +std::string Field::getBytesVarint64(uint64_t value) +{ + uint8_t bytes[kMaxVarintBytes]; + int size = 0; + while (value > 0x7F) { + bytes[size++] = (static_cast(value) & 0x7F) | 0x80; + value >>= 7; + } + bytes[size++] = static_cast(value) & 0x7F; + return std::string{ reinterpret_cast(&bytes[0]), (size_t)size }; +} + +uint32_t Field::readVarUint32(void* data, size_t& bytesRead) +{ + auto ptr = reinterpret_cast(data); + auto value = 0u; + auto bytes = 0u; + + do { + value |= static_cast(*ptr & 0x7f) << (7 * bytes); + bytes++; + } while (*(ptr++) & 0x80 && bytes <= 5); + + bytesRead = bytes; + return value; +} + +uint64_t Field::readVarUint64(void* data, size_t& bytesRead) +{ + auto ptr = reinterpret_cast(data); + auto value = 0ull; + auto bytes = 0u; + + do + { + value |= static_cast(*ptr & 0x7f) << (7 * bytes); + bytes++; + } while (*(ptr++) & 0x80 && bytes <= 10); + + bytesRead = bytes; + + return value; +} + +Field Field::ReadField(void* data, size_t& bytesRead) +{ + unsigned field = *reinterpret_cast(data); + unsigned type = field & kTagTypeMask; + + if (field == 0xffff) { + bytesRead = 0; + return Field(); + } + + if (field & 0x80) { + field = ((field & 0x7f) | ((field & 0xff00) >> 1)) >> kTagTypeBits; + bytesRead = 2; + } + else { + field = (field & 0xff) >> kTagTypeBits; + bytesRead = 1; + } + + size_t length, sizeDelimited; + std::string value, full; + switch (type) + { + case WIRETYPE_VARINT: + readVarUint64((void*)((ptrdiff_t)data + bytesRead), length); + value = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytesRead)), length }; + full = std::string{ reinterpret_cast(data), bytesRead + length }; + bytesRead += length; + break; + case WIRETYPE_FIXED64: + value = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytesRead)), 8 }; + full = std::string{ reinterpret_cast(data), bytesRead + 8 }; + bytesRead += 8; + break; + case WIRETYPE_LENGTH_DELIMITED: + sizeDelimited = readVarUint32((void*)((ptrdiff_t)data + bytesRead), length); + value = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytesRead)), length + sizeDelimited }; + full = std::string{ reinterpret_cast(data), bytesRead + length + sizeDelimited }; + bytesRead += length + sizeDelimited; + break; + case WIRETYPE_START_GROUP: + throw("WIRETYPE_START_GROUP unrealised"); + break; + case WIRETYPE_END_GROUP: + throw("WIRETYPE_END_GROUP unrealised"); + break; + case WIRETYPE_FIXED32: + value = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytesRead)), 4 }; + full = std::string{ reinterpret_cast(data), bytesRead + 4 }; + bytesRead += 4; + break; + default: + throw("Unknown type %i", type); + break; + } + + + return Field(field, type, value, full); +} + +#pragma endregion + +#pragma region Field Definition +Field& Field::operator=(const Field& f) { + this->tag = f.tag; + this->value = f.value; + this->full = f.full; + return *this; +} + +Field::Field(unsigned field, unsigned type, std::string value, std::string full) { + this->tag = { field, type }; + this->value = value; + this->full = full; +} + +template +Field::Field(Tag tag, T value) { + auto wireType = kWireTypeForFieldType[tag.type]; + full = getBytesVarint32(MAKE_TAG(tag.field, wireType)); + + switch (wireType) { + case WIRETYPE_VARINT: + full += getBytesVarint64(static_cast(value)); + break; + case WIRETYPE_FIXED32: + full += std::string{ reinterpret_cast(&value), 4 }; + break; + case WIRETYPE_FIXED64: + full += std::string{ reinterpret_cast(&value), 8 }; + break; + } +} + +template +Field::Field(unsigned field, unsigned type, T value) { + auto wireType = kWireTypeForFieldType[type]; + tag = { field, (unsigned)wireType }; + full = getBytesVarint32(MAKE_TAG(field, wireType)); + + switch (wireType) { + case WIRETYPE_VARINT: + full += getBytesVarint64(static_cast(value)); + break; + case WIRETYPE_FIXED32: + full += std::string{ reinterpret_cast(&value), 4 }; + break; + case WIRETYPE_FIXED64: + full += std::string{ reinterpret_cast(&value), 8 }; + break; + } +} + +Field::Field(Tag tag, std::string value) { + auto wireType = kWireTypeForFieldType[tag.type]; + full = getBytesVarint32(MAKE_TAG(tag.field, wireType)); + full += getBytesVarint32(value.size()); + full += value; +} + +Field::Field(unsigned field, unsigned type, std::string value) { + auto wireType = kWireTypeForFieldType[type]; + tag = { field, (unsigned)wireType }; + full = getBytesVarint32(MAKE_TAG(field, wireType)); + full += getBytesVarint32(value.size()); + full += value; +} + + +float Field::Float() { + return *reinterpret_cast((void*)value.data()); +} +double Field::Double() { + return *reinterpret_cast((void*)value.data()); +} +int32_t Field::Int32() { + size_t bytesRead; + return static_cast(readVarUint64((void*)value.data(), bytesRead)); +} +int64_t Field::Int64() { + size_t bytesRead; + return readVarUint64((void*)value.data(), bytesRead); +} +uint32_t Field::UInt32() { + size_t bytesRead; + return readVarUint32((void*)value.data(), bytesRead); +} +uint64_t Field::UInt64() { + size_t bytesRead; + return readVarUint64((void*)value.data(), bytesRead); +} +uint32_t Field::Fixed32() { + return *reinterpret_cast((void*)value.data()); +} +uint64_t Field::Fixed64() { + return *reinterpret_cast((void*)value.data()); +} +int32_t Field::SFixed32() { + return *reinterpret_cast((void*)value.data()); +} +int64_t Field::SFixed64() { + return *reinterpret_cast((void*)value.data()); +} +bool Field::Bool() { + size_t bytesRead; + return !!readVarUint32((void*)value.data(), bytesRead); +} + +std::string Field::String() +{ + size_t bytesRead; + void* data = (void*)value.data(); + auto length = readVarUint32((void*)value.data(), bytesRead); + auto value = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytesRead)), length }; + return value; +} + +#pragma endregion + +#pragma region ProtoWriter Definition +ProtoWriter::ProtoWriter() +{ + +} + +ProtoWriter::ProtoWriter(size_t maxFields) +{ + size_t vector_size = maxFields + 1; + fields.resize(vector_size); + fields.reserve(vector_size); +} + +ProtoWriter::ProtoWriter(void* data, size_t size, size_t maxFields) : ProtoWriter(maxFields) +{ + size_t vector_size = maxFields + 1, + pos = 0, + bytesRead; + + if (data == nullptr) + return; + while (pos < size) { + auto field = Field::ReadField((void*)((ptrdiff_t)data + pos), bytesRead); + if (!bytesRead) break; + + auto index = field.tag.field; + if (index >= vector_size) throw("fields range error: field[%i]", index); + fields[index].push_back(field); + pos += bytesRead; + } +} + +ProtoWriter::ProtoWriter(std::string dataStr, size_t maxFields) : ProtoWriter((void*)dataStr.data(), dataStr.size(), maxFields) +{ + +} + +std::string ProtoWriter::serialize() +{ + std::string result; + for (auto& f0 : fields) { + for (auto& f1 : f0) { + result += f1.full; + } + } + return result; +} + +void ProtoWriter::print() +{ + auto data = serialize(); + void* mem = (void*)data.data(); + size_t size = data.size(); + int j = 0; + for (size_t i = 0; i <= size; ++i) { + printf("%.2X ", *(unsigned char*)((uintptr_t)mem + i)); + j++; + if (j == 16) + { + j = 0; + printf("\n"); + } + } + printf("\n"); +} + +void ProtoWriter::add(Field field) +{ + fields[field.tag.field].push_back(field); +} + +void ProtoWriter::replace(Field field) +{ + fields[field.tag.field].clear(); + fields[field.tag.field].push_back(field); +} + +void ProtoWriter::replace(Field field, uint32_t index) +{ + fields[field.tag.field][index] = field; +} + +void ProtoWriter::clear(unsigned fieldId) +{ + return fields[fieldId].clear(); +} + +bool ProtoWriter::has(unsigned fieldId) +{ + return fields[fieldId].size() > 0; +} + +Field ProtoWriter::get(unsigned fieldId) +{ + if (fields[fieldId].empty()) + return Field(); + return fields[fieldId][0]; +} + +std::vector ProtoWriter::getAll(unsigned fieldId) +{ + return fields[fieldId]; +} + +template +void ProtoWriter::add(Tag tag, T value) +{ + fields[tag.field].push_back(Field(tag, value)); +} + +template +void ProtoWriter::replace(Tag tag, T value) +{ + fields[tag.field].clear(); + fields[tag.field].push_back(Field(tag, value)); +} + +template +void ProtoWriter::replace(Tag tag, T value, uint32_t index) +{ + fields[tag.field][index] = Field(tag, value); +} + +void ProtoWriter::add(Tag tag, std::string value) +{ + fields[tag.field].push_back(Field(tag, value)); +} + +void ProtoWriter::replace(Tag tag, std::string value) +{ + fields[tag.field].clear(); + fields[tag.field].push_back(Field(tag, value)); +} + +void ProtoWriter::replace(Tag tag, std::string value, uint32_t index) +{ + fields[tag.field][index] = Field(tag, value); +} + +void ProtoWriter::clear(Tag tag) +{ + return fields[tag.field].clear(); +} + +bool ProtoWriter::has(Tag tag) +{ + return fields[tag.field].size() > 0; +} + +Field ProtoWriter::get(Tag tag) +{ + if (fields[tag.field].empty()) + return Field(); + return fields[tag.field][0]; +} + +std::vector ProtoWriter::getAll(Tag tag) +{ + return fields[tag.field]; +} + +#pragma endregion \ No newline at end of file diff --git a/SpyCustom/ProtobuffMessages.h b/SpyCustom/ProtobuffMessages.h new file mode 100644 index 0000000..5eb7868 --- /dev/null +++ b/SpyCustom/ProtobuffMessages.h @@ -0,0 +1,105 @@ +#pragma once +#include "pbwrap.hpp" + +#define k_EMsgGCCStrike15_v2_MatchmakingGC2ClientReserve 9107 +#define k_EMsgGCClientWelcome 4004 +#define k_EMsgGCClientHello 4006 +#define k_EMsgGCAdjustItemEquippedState 1059 +#define k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello 9109 +#define k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello 9110 +#define k_EMsgGCCStrike15_v2_ClientGCRankUpdate 9194 + +using namespace pbwrap; + +struct CMsgClientHello : pbmsg<8> { + PBMSG_CTOR; + PBFIELD(3, types::Uint32, client_session_need); +}; + +struct MatchmakingGC2ClientHello : pbmsg<20> { + struct PlayerRankingInfo : pbmsg<6> { + PBMSG_CTOR; + PBFIELD(1, types::Uint32, account_id); + PBFIELD(2, types::Uint32, rank_id); + PBFIELD(3, types::Uint32, wins); + PBFIELD(6, types::Uint32, rank_type_id); + }; + struct PlayerCommendationInfo : pbmsg<4> { + PBMSG_CTOR; + PBFIELD(1, types::Uint32, cmd_friendly); + PBFIELD(2, types::Uint32, cmd_teaching); + PBFIELD(4, types::Uint32, cmd_leader); + }; + + PBMSG_CTOR; + PBFIELD(7, PlayerRankingInfo, ranking); + PBFIELD(8, PlayerCommendationInfo, commendation); + PBFIELD(17, types::Int32, player_level); + PBFIELD(18, types::Int32, player_cur_xp); + PBFIELD(4, types::Uint32, penalty_seconds); + PBFIELD(5, types::Uint32, penalty_reason); + PBFIELD(6, types::Int32, vac_banned); +}; + +struct CMsgGCCStrike15_v2_ClientGCRankUpdate : pbmsg<1> { + PBMSG_CTOR; + PBFIELD(1, MatchmakingGC2ClientHello::PlayerRankingInfo, ranking); +}; + +struct CSOEconItemEquipped : pbmsg<2> { + PBMSG_CTOR; + PBFIELD(1, types::Int32, new_class); + PBFIELD(2, types::Int32, new_slot); +}; + +struct CSOEconItemAttribute : pbmsg<3> { + PBMSG_CTOR; + PBFIELD(1, types::Uint32, def_index); + PBFIELD(2, types::Uint32, value); + PBFIELD(3, types::Bytes, value_bytes); +}; + +struct CSOEconItem : pbmsg<19> { + PBMSG_CTOR; + PBFIELD(1, types::Uint64, id); + PBFIELD(2, types::Uint32, account_id); + PBFIELD(3, types::Uint32, inventory); + PBFIELD(4, types::Int32, def_index); + PBFIELD(5, types::Uint32, quantity); + PBFIELD(6, types::Uint32, level); + PBFIELD(7, types::Uint32, quality); + PBFIELD(8, types::Uint32, flags); + PBFIELD(9, types::Uint32, origin); + PBFIELD(10, types::String, custom_name); + PBFIELD(11, types::String, custom_desc); + PBFIELD(12, CSOEconItemAttribute, attribute); + PBFIELD(14, types::Bool, in_use); + PBFIELD(15, types::Uint32, style); + PBFIELD(16, types::Uint64, original_id); + PBFIELD(18, CSOEconItemEquipped, equipped_state); + PBFIELD(19, types::Uint32, rarity); +}; + +struct CMsgClientWelcome : pbmsg<11> { + struct SubscribedType : pbmsg<2> { + PBMSG_CTOR; + PBFIELD(1, types::Int32, type_id); + PBFIELD(2, CSOEconItem, object_data); + }; + + struct CMsgSOCacheSubscribed : pbmsg<4> { + PBMSG_CTOR; + PBFIELD(2, SubscribedType, objects); + }; + + PBMSG_CTOR; + PBFIELD(3, CMsgSOCacheSubscribed, outofdate_subscribed_caches); +}; + +struct CMsgAdjustItemEquippedState : pbmsg<4> { + PBMSG_CTOR; + PBFIELD(1, types::Uint64, item_id); + PBFIELD(2, types::Uint32, new_class); + PBFIELD(3, types::Uint32, new_slot); + PBFIELD(4, types::Bool, swap); +}; \ No newline at end of file diff --git a/SpyCustom/RichText.h b/SpyCustom/RichText.h new file mode 100644 index 0000000..ffc2397 --- /dev/null +++ b/SpyCustom/RichText.h @@ -0,0 +1,234 @@ +#ifndef RICHTEXT_H +#define RICHTEXT_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "Panel.h" +#include "utlvector.h" + +namespace vgui +{ + + class ClickPanel; + + class RichText : public Panel + { + DECLARE_CLASS_SIMPLE(RichText, Panel); + + public: + RichText(Panel* parent, const char* panelName); + ~RichText(); + + virtual void SetText(const char* text); + virtual void SetText(const wchar_t* text); + void GetText(int offset, OUT_Z_BYTECAP(bufLenInBytes) wchar_t* buf, int bufLenInBytes); + void GetText(int offset, OUT_Z_BYTECAP(bufLenInBytes) char* pch, int bufLenInBytes); + + void SetFont(HFont font); + + void InsertChar(wchar_t ch); + void InsertString(const char* text); + void InsertString(const wchar_t* wszText); + + void SelectNone(); + void SelectAllText(); + void SelectNoText(); + MESSAGE_FUNC(CutSelected, "DoCutSelected"); + MESSAGE_FUNC(CopySelected, "DoCopySelected"); + + void SetPanelInteractive(bool bInteractive) { m_bInteractive = bInteractive; } + + void SetUnusedScrollbarInvisible(bool bInvis) { m_bUnusedScrollbarInvis = bInvis; } + + void GotoTextStart(); + void GotoTextEnd(); + + void SetVerticalScrollbar(bool state); + void SetMaximumCharCount(int maxChars); + + void InsertColorChange(Color col); + void InsertIndentChange(int pixelsIndent); + void InsertClickableTextStart(const char* pchClickAction = NULL); + void InsertClickableTextEnd(); + void InsertPossibleURLString(const char* text, Color URLTextColor, Color normalTextColor); + + void InsertFade(float flSustain, float flLength); + + void ResetAllFades(bool bHold, bool bOnlyExpired = false, float flNewSustain = -1.0f); + + void SetToFullHeight(); + int GetNumLines(); + + + virtual bool RequestInfo(KeyValues* outputData); + virtual void SetFgColor(Color color); + virtual void SetDrawOffsets(int ofsx, int ofsy); + bool IsScrollbarVisible(); + + void SetURLClickedHandler(Panel* pPanelToHandleClickMsg); + + void SetUnderlineFont(HFont font); + + bool IsAllTextAlphaZero() const; + bool HasText() const; + + void SetDrawTextOnly(); + + protected: + virtual void OnThink(); + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme* pScheme); + virtual void Paint(); + + virtual void ApplySettings(KeyValues* inResourceData); + virtual void GetSettings(KeyValues* outResourceData); + virtual const char* GetDescription(void); + MESSAGE_FUNC_WCHARPTR(OnSetText, "SetText", text); + MESSAGE_FUNC(OnSliderMoved, "ScrollBarSliderMoved"); + virtual void OnKillFocus(); + virtual void OnMouseWheeled(int delta); + virtual void OnKeyCodeTyped(KeyCode code); + + MESSAGE_FUNC_INT(OnClickPanel, "ClickPanel", index); + + virtual void OnCursorMoved(int x, int y); + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnMouseReleased(MouseCode code); + + virtual void OnMouseFocusTicked(); + virtual void OnCursorEntered(); + virtual void OnCursorExited(); + + virtual void OnMouseCaptureLost(); + virtual void OnSizeChanged(int newWide, int newTall); + virtual void OnSetFocus(); + + int ParseTextStringForUrls(const char* text, int startPos, char* pchURLText, int cchURLText, char* pchURL, int cchURL, bool& clickable); + virtual void OnTextClicked(const wchar_t* text); + +#ifdef DBGFLAG_VALIDATE + virtual void Validate(CValidator& validator, char* pchName); +#endif + + protected: + ScrollBar* _vertScrollBar; + + private: + int GetLineHeight(); + HFont GetDefaultFont(); + + const wchar_t* ResolveLocalizedTextAndVariables(char const* pchLookup, OUT_Z_BYTECAP(outbufsizeinbytes) wchar_t* outbuf, size_t outbufsizeinbytes); + void CheckRecalcLineBreaks(); + + void GotoWordRight(); + void GotoWordLeft(); + + void TruncateTextStream(); + bool GetSelectedRange(int& cx0, int& cx1); + void CursorToPixelSpace(int cursorPos, int& cx, int& cy); + int PixelToCursorSpace(int cx, int cy); + void AddAnotherLine(int& cx, int& cy); + void RecalculateDefaultState(int startIndex); + + void LayoutVerticalScrollBarSlider(); + void OpenEditMenu(); + void FinishingURL(int x, int y); + int GetStartDrawIndex(int& lineBreakIndexIndex); + int GetCursorLine(); + int GetClickableTextIndexStart(int startIndex); + void CreateEditMenu(); + + MESSAGE_FUNC_INT(MoveScrollBar, "MoveScrollBar", delta); + MESSAGE_FUNC_INT(MoveScrollBarDirect, "MoveScrollBarDirect", delta); + + void InvalidateLineBreakStream(); + void RecalculateLineBreaks(); + + struct TFade + { + float flFadeStartTime; + float flFadeLength; + float flFadeSustain; + int iOriginalAlpha; + }; + + struct TFormatStream + { + Color color; + int pixelsIndent; + bool textClickable; + CUtlSymbol m_sClickableTextAction; + + TFade fade; + + int textStreamIndex; + }; + + bool m_bResetFades; + bool m_bInteractive; + bool m_bUnusedScrollbarInvis; + bool m_bAllTextAlphaIsZero; + + CUtlVector m_TextStream; + CUtlVector m_LineBreaks; + CUtlVector m_FormatStream; + + bool m_bRecalcLineBreaks; + + int _recalculateBreaksIndex; + bool _invalidateVerticalScrollbarSlider; + int _cursorPos; + bool _mouseSelection; + bool _mouseDragSelection; + int _select[2]; + int _pixelsIndent; + int _maxCharCount; + HFont _font; + HFont m_hFontUnderline; + Color _selectionColor; + Color _selectionTextColor; + bool _currentTextClickable; + CUtlVector _clickableTextPanels; + int _clickableTextIndex; + Color _defaultTextColor; + int _drawOffsetX; + int _drawOffsetY; + + Panel* m_pInterior; + PHandle m_hPanelToHandleClickingURLs; + + + Menu* m_pEditMenu; + + char* m_pszInitialText; + + bool _recalcSavedRenderState; + + struct TRenderState + { + int x, y; + + Color textColor; + int pixelsIndent; + bool textClickable; + + int formatStreamIndex; + }; + TRenderState m_CachedRenderState; + + bool UpdateRenderState(int textStreamPos, TRenderState& renderState); + void CalculateFade(TRenderState& renderState); + + void GenerateRenderStateForTextStreamIndex(int textStreamIndex, TRenderState& renderState); + int FindFormatStreamIndexForTextStreamPos(int textStreamIndex); + + int DrawString(int iFirst, int iLast, TRenderState& renderState, HFont font); + }; + +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/ivdebugoverlay.h b/SpyCustom/ivdebugoverlay.h new file mode 100644 index 0000000..e1253af --- /dev/null +++ b/SpyCustom/ivdebugoverlay.h @@ -0,0 +1,44 @@ +#ifndef IVDEBUGOVERLAY_H +#define IVDEBUGOVERLAY_H + +#ifdef _WIN32 +#pragma once +#endif + +class Vector; + +#define VDEBUG_OVERLAY_INTERFACE_VERSION "VDebugOverlay003" + +#define NDEBUG_PERSIST_TILL_NEXT_SERVER (0.0f) + +class OverlayText_t; + +abstract_class IVDebugOverlay +{ +public: + virtual void __unkn() = 0; + virtual void AddEntityTextOverlay(int ent_index, int line_offset, float duration, int r, int g, int b, int a, const char* format, ...) = 0; + virtual void AddBoxOverlay(const Vector& origin, const Vector& mins, const Vector& max, Vector const& orientation, int r, int g, int b, int a, float duration) = 0; + virtual void AddSphereOverlay(const Vector& vOrigin, float flRadius, int nTheta, int nPhi, int r, int g, int b, int a, float flDuration) = 0; + virtual void AddTriangleOverlay(const Vector& p1, const Vector& p2, const Vector& p3, int r, int g, int b, int a, bool noDepthTest, float duration) = 0; + virtual void AddLineOverlay(const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest, float duration) = 0; + virtual void AddTextOverlay(const Vector& origin, float duration, const char* format, ...) = 0; + virtual void AddTextOverlay(const Vector& origin, int line_offset, float duration, const char* format, ...) = 0; + virtual void AddScreenTextOverlay(float flXPos, float flYPos, float flDuration, int r, int g, int b, int a, const char* text) = 0; + virtual void AddSweptBoxOverlay(const Vector& start, const Vector& end, const Vector& mins, const Vector& max, const QAngle& angles, int r, int g, int b, int a, float flDuration) = 0; + virtual void AddGridOverlay(const Vector& origin) = 0; + virtual void AddCoordFrameOverlay(const matrix3x4_t& frame, float flScale, int vColorTable[3][3] = NULL) = 0; + virtual int ScreenPosition(const Vector& point, Vector& screen) = 0; + virtual int ScreenPosition(float flXPos, float flYPos, Vector& screen) = 0; + virtual OverlayText_t* GetFirst(void) = 0; + virtual OverlayText_t* GetNext(OverlayText_t* current) = 0; + virtual void ClearDeadOverlays(void) = 0; + virtual void ClearAllOverlays() = 0; + virtual void AddTextOverlayRGB(const Vector& origin, int line_offset, float duration, float r, float g, float b, float alpha, const char* format, ...) = 0; + virtual void AddTextOverlayRGB(const Vector& origin, int line_offset, float duration, int r, int g, int b, int a, const char* format, ...) = 0; + virtual void AddLineOverlayAlpha(const Vector& origin, const Vector& dest, int r, int g, int b, int a, bool noDepthTest, float duration) = 0; + virtual void AddBoxOverlay2(const Vector& origin, const Vector& mins, const Vector& max, QAngle const& orientation, const Color& faceColor, const Color& edgeColor, float duration) = 0; + virtual void PurgeTextOverlays() = 0; + virtual void DrawPill(const Vector& mins, const Vector& max, float& diameter, int r, int g, int b, int a, float duration) = 0; +}; +#endif \ No newline at end of file diff --git a/SpyCustom/iviewrender.h b/SpyCustom/iviewrender.h new file mode 100644 index 0000000..505f8dc --- /dev/null +++ b/SpyCustom/iviewrender.h @@ -0,0 +1,125 @@ +#if !defined( IVIEWRENDER_H ) +#define IVIEWRENDER_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "ivrenderview.h" + + +#define MAX_DEPTH_TEXTURE_SHADOWS 1 +#define MAX_DEPTH_TEXTURE_HIGHRES_SHADOWS 0 + +#define MAX_DEPTH_TEXTURE_SHADOWS_TOOLS 8 +#define MAX_DEPTH_TEXTURE_HIGHRES_SHADOWS_TOOLS 0 + + +enum DrawFlags_t +{ + DF_RENDER_REFRACTION = 0x1, + DF_RENDER_REFLECTION = 0x2, + + DF_CLIP_Z = 0x4, + DF_CLIP_BELOW = 0x8, + + DF_RENDER_UNDERWATER = 0x10, + DF_RENDER_ABOVEWATER = 0x20, + DF_RENDER_WATER = 0x40, + + DF_SSAO_DEPTH_PASS = 0x80, + + DF_RENDER_PSEUDO_TRANSLUCENT_WATER = 0x100, + DF_WATERHEIGHT = 0x200, + DF_DRAW_SSAO = 0x400, + DF_DRAWSKYBOX = 0x800, + + DF_FUDGE_UP = 0x1000, + + DF_DRAW_ENTITITES = 0x2000, + + DF_SKIP_WORLD = 0x4000, + DF_SKIP_WORLD_DECALS_AND_OVERLAYS = 0x8000, + + DF_UNUSED5 = 0x10000, + DF_SAVEGAMESCREENSHOT = 0x20000, + DF_CLIP_SKYBOX = 0x40000, + + DF_DRAW_SIMPLE_WORLD_MODEL = 0x80000, + + DF_SHADOW_DEPTH_MAP = 0x100000, + + DF_FAST_ENTITY_RENDERING = 0x200000, + DF_DRAW_SIMPLE_WORLD_MODEL_WATER = 0x400000, +}; + +class CViewSetup; +class C_BaseEntity; +struct vrect_t; +class C_BaseViewModel; + +abstract_class IViewRender +{ +public: + virtual void Init(void) = 0; + + virtual void LevelInit(void) = 0; + virtual void LevelShutdown(void) = 0; + + virtual void Shutdown(void) = 0; + + virtual void OnRenderStart() = 0; + + virtual void Render(vrect_t* rect) = 0; + + virtual void RenderView(const CViewSetup& view, const CViewSetup& hudViewSetup, int nClearFlags, int whatToDraw) = 0; + + virtual int GetDrawFlags() = 0; + + virtual void StartPitchDrift(void) = 0; + virtual void StopPitchDrift(void) = 0; + + virtual VPlane* GetFrustum() = 0; + + virtual bool ShouldDrawBrushModels(void) = 0; + + virtual const CViewSetup* GetPlayerViewSetup(int nSlot = -1) const = 0; + virtual const CViewSetup* GetViewSetup(void) const = 0; + + virtual void DisableVis(void) = 0; + + virtual int BuildWorldListsNumber() const = 0; + + virtual void SetCheapWaterStartDistance(float flCheapWaterStartDistance) = 0; + virtual void SetCheapWaterEndDistance(float flCheapWaterEndDistance) = 0; + + virtual void GetWaterLODParams(float& flCheapWaterStartDistance, float& flCheapWaterEndDistance) = 0; + + virtual void DriftPitch(void) = 0; + + virtual void SetScreenOverlayMaterial(IMaterial* pMaterial) = 0; + virtual IMaterial* GetScreenOverlayMaterial() = 0; + + virtual void WriteSaveGameScreenshot(const char* pFilename) = 0; + virtual void WriteSaveGameScreenshotOfSize(const char* pFilename, int width, int height) = 0; + + virtual void QueueOverlayRenderView(const CViewSetup& view, int nClearFlags, int whatToDraw) = 0; + + virtual float GetZNear() = 0; + virtual float GetZFar() = 0; + + virtual void GetScreenFadeDistances(float* pMin, float* pMax, float* pScale) = 0; + + virtual C_BaseEntity* GetCurrentlyDrawingEntity() = 0; + virtual void SetCurrentlyDrawingEntity(C_BaseEntity* pEnt) = 0; + + virtual bool UpdateShadowDepthTexture(ITexture* pRenderTarget, ITexture* pDepthTexture, const CViewSetup& shadowView, bool bRenderWorldAndObjects = true, bool bRenderViewModels = false) = 0; + + virtual void FreezeFrame(float flFreezeTime) = 0; + + virtual void InitFadeData(void) = 0; +}; + +extern IViewRender* view; + +#endif \ No newline at end of file diff --git a/SpyCustom/iviewrender_beams.h b/SpyCustom/iviewrender_beams.h new file mode 100644 index 0000000..73f17a2 --- /dev/null +++ b/SpyCustom/iviewrender_beams.h @@ -0,0 +1,144 @@ +#if !defined( IVIEWRENDER_BEAMS_H ) +#define IVIEWRENDER_BEAMS_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vector.h" +#include "beam_flags.h" +#include "tempentity.h" + +extern void SetBeamCreationAllowed(bool state); +extern bool BeamCreationAllowed(void); + + +class C_Beam; +class Beam_t; + +struct BeamTrail_t +{ + BeamTrail_t* next; + float die; + Vector org; + Vector vel; +}; + +struct BeamInfo_t +{ + int m_nType; + + C_BaseEntity* m_pStartEnt; + int m_nStartAttachment; + C_BaseEntity* m_pEndEnt; + int m_nEndAttachment; + + Vector m_vecStart; + Vector m_vecEnd; + + int m_nModelIndex; + const char* m_pszModelName; + + int m_nHaloIndex; + const char* m_pszHaloName; + float m_flHaloScale; + + float m_flLife; + float m_flWidth; + float m_flEndWidth; + float m_flFadeLength; + float m_flAmplitude; + + float m_flBrightness; + float m_flSpeed; + + int m_nStartFrame; + float m_flFrameRate; + + float m_flRed; + float m_flGreen; + float m_flBlue; + + bool m_bRenderable; + + int m_nSegments; + + int m_nFlags; + + Vector m_vecCenter; + float m_flStartRadius; + float m_flEndRadius; + + BeamInfo_t() + { + m_nType = TE_BEAMPOINTS; + m_nSegments = -1; + m_pszModelName = NULL; + m_pszHaloName = NULL; + m_nModelIndex = -1; + m_nHaloIndex = -1; + m_bRenderable = true; + m_nFlags = 0; + } +}; + + +abstract_class IViewRenderBeams +{ +public: +public: +public: + virtual void InitBeams(void) = 0; + virtual void ShutdownBeams(void) = 0; + virtual void ClearBeams(void) = 0; + + virtual void UpdateTempEntBeams() = 0; + + + virtual void DrawBeam(C_Beam* pbeam, ITraceFilter* pEntityBeamTraceFilter = NULL) = 0; + virtual void DrawBeam(Beam_t* pbeam) = 0; + + + virtual void KillDeadBeams(CBaseEntity* pEnt) = 0; + + virtual Beam_t* CreateBeamEnts(BeamInfo_t& beamInfo) = 0; + virtual Beam_t* CreateBeamEntPoint(BeamInfo_t& beamInfo) = 0; + virtual Beam_t* CreateBeamPoints(BeamInfo_t& beamInfo) = 0; + virtual Beam_t* CreateBeamRing(BeamInfo_t& beamInfo) = 0; + virtual Beam_t* CreateBeamRingPoint(BeamInfo_t& beamInfo) = 0; + virtual Beam_t* CreateBeamCirclePoints(BeamInfo_t& beamInfo) = 0; + virtual Beam_t* CreateBeamFollow(BeamInfo_t& beamInfo) = 0; + + virtual void FreeBeam(Beam_t* pBeam) = 0; + virtual void UpdateBeamInfo(Beam_t* pBeam, BeamInfo_t& beamInfo) = 0; + + virtual void CreateBeamEnts(int startEnt, int endEnt, int modelIndex, int haloIndex, float haloScale, + float life, float width, float m_nEndWidth, float m_nFadeLength, float amplitude, + float brightness, float speed, int startFrame, + float framerate, float r, float g, float b, int type = -1) = 0; + virtual void CreateBeamEntPoint(int nStartEntity, const Vector* pStart, int nEndEntity, const Vector* pEnd, + int modelIndex, int haloIndex, float haloScale, + float life, float width, float m_nEndWidth, float m_nFadeLength, float amplitude, + float brightness, float speed, int startFrame, + float framerate, float r, float g, float b) = 0; + virtual void CreateBeamPoints(Vector& start, Vector& end, int modelIndex, int haloIndex, float haloScale, + float life, float width, float m_nEndWidth, float m_nFadeLength, float amplitude, + float brightness, float speed, int startFrame, + float framerate, float r, float g, float b) = 0; + virtual void CreateBeamRing(int startEnt, int endEnt, int modelIndex, int haloIndex, float haloScale, + float life, float width, float m_nEndWidth, float m_nFadeLength, float amplitude, + float brightness, float speed, int startFrame, + float framerate, float r, float g, float b, int flags = 0) = 0; + virtual void CreateBeamRingPoint(const Vector& center, float start_radius, float end_radius, int modelIndex, int haloIndex, float haloScale, + float life, float width, float m_nEndWidth, float m_nFadeLength, float amplitude, + float brightness, float speed, int startFrame, + float framerate, float r, float g, float b, int flags = 0) = 0; + virtual void CreateBeamCirclePoints(int type, Vector& start, Vector& end, + int modelIndex, int haloIndex, float haloScale, float life, float width, + float m_nEndWidth, float m_nFadeLength, float amplitude, float brightness, float speed, + int startFrame, float framerate, float r, float g, float b) = 0; + virtual void CreateBeamFollow(int startEnt, int modelIndex, int haloIndex, float haloScale, + float life, float width, float m_nEndWidth, float m_nFadeLength, float r, float g, float b, + float brightness) = 0; +}; + +#endif diff --git a/SpyCustom/ivmodelinfo.h b/SpyCustom/ivmodelinfo.h new file mode 100644 index 0000000..f1f236a --- /dev/null +++ b/SpyCustom/ivmodelinfo.h @@ -0,0 +1,152 @@ +#ifndef IVMODELINFO_H +#define IVMODELINFO_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "platform.h" +#include "dbg.h" + +class IMaterial; +class KeyValues; +struct vcollide_t; +struct model_t; +class Vector; +class QAngle; +class CGameTrace; +struct cplane_t; +typedef CGameTrace trace_t; +struct studiohdr_t; +struct virtualmodel_t; +typedef unsigned char byte; +struct virtualterrainparams_t; +class CPhysCollide; +typedef unsigned short MDLHandle_t; +class CUtlBuffer; +class IClientRenderable; + +class CStudioHdr; +enum RenderableTranslucencyType_t +{ + RENDERABLE_IS_OPAQUE = 0, + RENDERABLE_IS_TRANSLUCENT, + RENDERABLE_IS_TWO_PASS, +}; + +abstract_class IModelLoadCallback +{ +public: + virtual void OnModelLoadComplete(const model_t * pModel) = 0; + +protected: + ~IModelLoadCallback(); +}; + + +class CRefCountedModelIndex +{ +private: + int m_nIndex; +public: + CRefCountedModelIndex() : m_nIndex(-1) { } + ~CRefCountedModelIndex() { Set(-1); } + + CRefCountedModelIndex(const CRefCountedModelIndex& src) : m_nIndex(-1) { Set(src.m_nIndex); } + CRefCountedModelIndex& operator=(const CRefCountedModelIndex& src) { Set(src.m_nIndex); return *this; } + + explicit CRefCountedModelIndex(int i) : m_nIndex(-1) { Set(i); } + CRefCountedModelIndex& operator=(int i) { Set(i); return *this; } + + int Get() const { return m_nIndex; } + void Set(int i); + void Clear() { Set(-1); } + + operator int() const { return m_nIndex; } +}; + + +#define VMODELINFO_CLIENT_INTERFACE_VERSION "VModelInfoClient006" +#define VMODELINFO_SERVER_INTERFACE_VERSION_3 "VModelInfoServer003" +#define VMODELINFO_SERVER_INTERFACE_VERSION "VModelInfoServer004" + +inline bool IsDynamicModelIndex(int modelindex) { return modelindex < -1; } +inline bool IsClientOnlyModelIndex(int modelindex) { return modelindex < -1 && (modelindex & 1); } + + +class IVModelInfo +{ +public: + virtual ~IVModelInfo(void) {} + virtual const model_t* GetModel(int modelindex) const = 0; + virtual int GetModelIndex(const char* name) const = 0; + virtual const char* GetModelName(const model_t* model) const = 0; + virtual vcollide_t* GetVCollide(const model_t* model) const = 0; + virtual vcollide_t* GetVCollide(int modelindex) const = 0; + virtual void GetModelBounds(const model_t* model, Vector& mins, Vector& maxs) const = 0; + virtual void GetModelRenderBounds(const model_t* model, Vector& mins, Vector& maxs) const = 0; + virtual int GetModelFrameCount(const model_t* model) const = 0; + virtual int GetModelType(const model_t* model) const = 0; + virtual void* GetModelExtraData(const model_t* model) = 0; + virtual bool ModelHasMaterialProxy(const model_t* model) const = 0; + virtual bool IsTranslucent(model_t const* model) const = 0; + virtual bool IsTranslucentTwoPass(const model_t* model) const = 0; + virtual void Unused0() {}; + virtual void UNUSED() = 0; + virtual void UNUSE11D() = 0; + virtual RenderableTranslucencyType_t ComputeTranslucencyType(const model_t* model, int nSkin, int nBody) = 0; + virtual int GetModelMaterialCount(const model_t* model) const = 0; + virtual void GetModelMaterials(const model_t* model, int count, IMaterial** ppMaterial) = 0; + virtual bool IsModelVertexLit(const model_t* model) const = 0; + virtual const char* GetModelKeyValueText(const model_t* model) = 0; + virtual bool GetModelKeyValue(const model_t* model, CUtlBuffer& buf) = 0; + virtual float GetModelRadius(const model_t* model) = 0; + virtual CStudioHdr* GetStudioHdr(MDLHandle_t handle) = 0; + virtual const studiohdr_t* FindModel(const studiohdr_t* pStudioHdr, void** cache, const char* modelname) const = 0; + virtual const studiohdr_t* FindModel(void* cache) const = 0; + virtual virtualmodel_t* GetVirtualModel(const studiohdr_t* pStudioHdr) const = 0; + virtual uint8_t* GetAnimBlock(const studiohdr_t* pStudioHdr, int iBlock) const = 0; + virtual void GetModelMaterialColorAndLighting(const model_t* model, Vector const& origin, QAngle const& angles, trace_t* pTrace, Vector& lighting, Vector& matColor) = 0; + virtual void GetIlluminationPoint(const model_t* model, IClientRenderable* pRenderable, Vector const& origin, QAngle const& angles, Vector* pLightingCenter) = 0; + virtual int GetModelContents(int modelIndex) const = 0; + virtual studiohdr_t* GetStudiomodel(const model_t* mod) = 0; + virtual int GetModelSpriteWidth(const model_t* model) const = 0; + virtual int GetModelSpriteHeight(const model_t* model) const = 0; + virtual void SetLevelScreenFadeRange(float flMinSize, float flMaxSize) = 0; + virtual void GetLevelScreenFadeRange(float* pMinArea, float* pMaxArea) const = 0; + virtual void SetViewScreenFadeRange(float flMinSize, float flMaxSize) = 0; + virtual unsigned char ComputeLevelScreenFade(const Vector& vecAbsOrigin, float flRadius, float flFadeScale) const = 0; + virtual unsigned char ComputeViewScreenFade(const Vector& vecAbsOrigin, float flRadius, float flFadeScale) const = 0; + virtual int GetAutoplayList(const studiohdr_t* pStudioHdr, unsigned short** pAutoplayList) const = 0; + virtual CPhysCollide* GetCollideForVirtualTerrain(int index) = 0; + virtual bool IsUsingFBTexture(const model_t* model, int nSkin, int nBody, IClientRenderable** pClientRenderable) const = 0; + virtual const model_t* FindOrLoadModel(const char* name) const = 0; + virtual MDLHandle_t GetCacheHandle(const model_t* model) const = 0; + virtual int GetBrushModelPlaneCount(const model_t* model) const = 0; + virtual void GetBrushModelPlane(const model_t* model, int nIndex, cplane_t& plane, Vector* pOrigin) const = 0; + virtual int GetSurfacepropsForVirtualTerrain(int index) = 0; + virtual bool UsesEnvCubemap(const model_t* model) const = 0; + virtual bool UsesStaticLighting(const model_t* model) const = 0; +}; + +typedef IVModelInfo IVModelInfo003; + + +abstract_class IVModelInfoClient : public IVModelInfo +{ +public: + virtual void OnDynamicModelsStringTableChange(int nStringIndex, const char* pString, const void* pData) = 0; + + virtual const model_t* FindOrLoadModel(const char* name) = 0; +}; + + +struct virtualterrainparams_t +{ + int index; +}; + + + + +#endif \ No newline at end of file diff --git a/SpyCustom/ivmodelrender.h b/SpyCustom/ivmodelrender.h new file mode 100644 index 0000000..56f17ca --- /dev/null +++ b/SpyCustom/ivmodelrender.h @@ -0,0 +1,131 @@ +#ifndef IVMODELRENDER_H +#define IVMODELRENDER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "interface.h" +#include "mathlib.h" +#include "istudiorender.h" +#include "idatacache.h" + +struct mstudioanimdesc_t; +struct mstudioseqdesc_t; +struct model_t; +class IClientRenderable; +class Vector; +struct studiohdr_t; +class IMaterial; +class CStudioHdr; +struct MaterialLightingState_t; + +FORWARD_DECLARE_HANDLE(LightCacheHandle_t); + + +struct DrawModelState_t +{ + studiohdr_t* m_pStudioHdr; + studiohwdata_t* m_pStudioHWData; + IClientRenderable* m_pRenderable; + const matrix3x4_t* m_pModelToWorld; + StudioDecalHandle_t m_decals; + int m_drawFlags; + int m_lod; +}; + + +#define VENGINE_HUDMODEL_INTERFACE_VERSION "VEngineModel016" + +typedef unsigned short ModelInstanceHandle_t; + +enum +{ + MODEL_INSTANCE_INVALID = (ModelInstanceHandle_t)~0 +}; + + +struct ModelRenderInfo_t +{ + Vector origin; + Vector angles; + char pad[4]; + IClientRenderable* pRenderable; + const model_t* pModel; + const matrix3x4_t* pModelToWorld; + const matrix3x4_t* pLightingOffset; + const Vector* pLightingOrigin; + int flags; + int entity_index; + int skin; + int body; + int hitboxset; + ModelInstanceHandle_t instance; + + ModelRenderInfo_t() + { + pModelToWorld = NULL; + pLightingOffset = NULL; + pLightingOrigin = NULL; + } +}; + +struct StaticPropRenderInfo_t +{ + const matrix3x4_t* pModelToWorld; + const model_t* pModel; + IClientRenderable* pRenderable; + Vector* pLightingOrigin; + short skin; + ModelInstanceHandle_t instance; +}; + +struct LightingQuery_t +{ +Vector m_LightingOrigin; +ModelInstanceHandle_t m_InstanceHandle; +bool m_bAmbientBoost; +}; + +struct StaticLightingQuery_t : public LightingQuery_t +{ +IClientRenderable * m_pRenderable; +}; +class IVModelRender +{ +public: + virtual int DrawModel(int flags, IClientRenderable* pRenderable, ModelInstanceHandle_t instance, int entity_index, const model_t* model, Vector const& origin, QAngle const& angles, int skin, int body, int hitboxset, const matrix3x4_t* modelToWorld = NULL, const matrix3x4_t* pLightingOffset = NULL) = 0; + virtual void ForcedMaterialOverride(IMaterial* newMaterial, OverrideType_t nOverrideType = OVERRIDE_NORMAL, int nOverrides = 0) = 0; + virtual bool IsForcedMaterialOverride(void) = 0; + virtual void SetViewTarget(const CStudioHdr* pStudioHdr, int nBodyIndex, const Vector& target) = 0; + virtual ModelInstanceHandle_t CreateInstance(IClientRenderable* pRenderable, LightCacheHandle_t* pCache = NULL) = 0; + virtual void DestroyInstance(ModelInstanceHandle_t handle) = 0; + virtual void SetStaticLighting(ModelInstanceHandle_t handle, LightCacheHandle_t* pHandle) = 0; + virtual LightCacheHandle_t GetStaticLighting(ModelInstanceHandle_t handle) = 0; + virtual bool ChangeInstance(ModelInstanceHandle_t handle, IClientRenderable* pRenderable) = 0; + virtual void AddDecal(ModelInstanceHandle_t handle, Ray_t const& ray, Vector const& decalUp, int decalIndex, int body, bool noPokeThru, int maxLODToDecal) = 0; + virtual void RemoveAllDecals(ModelInstanceHandle_t handle) = 0; + virtual bool ModelHasDecals(ModelInstanceHandle_t handle) = 0; + virtual void RemoveAllDecalsFromAllModels() = 0; + virtual matrix3x4_t* DrawModelShadowSetup(IClientRenderable* pRenderable, int body, int skin, DrawModelInfo_t* pInfo, matrix3x4_t* pCustomBoneToWorld = NULL) = 0; + virtual void DrawModelShadow(IClientRenderable* pRenderable, const DrawModelInfo_t& info, matrix3x4_t* pCustomBoneToWorld = NULL) = 0; + virtual bool RecomputeStaticLighting(ModelInstanceHandle_t handle) = 0; + virtual void ReleaseAllStaticPropColorData(void) = 0; + virtual void RestoreAllStaticPropColorData(void) = 0; + virtual int DrawModelEx(ModelRenderInfo_t& pInfo) = 0; + virtual int DrawModelExStaticProp(ModelRenderInfo_t& pInfo) = 0; + virtual bool DrawModelSetup(ModelRenderInfo_t& pInfo, DrawModelState_t* pState, matrix3x4_t** ppBoneToWorldOut) = 0; + virtual void DrawModelExecute(IMatRenderContext* ctx, const DrawModelState_t& state, const ModelRenderInfo_t& pInfo, matrix3x4_t* pCustomBoneToWorld = NULL) = 0; + virtual void SetupLighting(const Vector& vecCenter) = 0; + virtual int DrawStaticPropArrayFast(StaticPropRenderInfo_t* pProps, int count, bool bShadowDepth) = 0; + virtual void SuppressEngineLighting(bool bSuppress) = 0; + virtual void SetupColorMeshes(int nTotalVerts) = 0; + virtual void SetupLightingEx(const Vector& vecCenter, ModelInstanceHandle_t handle) = 0; + virtual bool GetBrightestShadowingLightSource(const Vector& vecCenter, Vector& lightPos, Vector& lightBrightness, bool bAllowNonTaggedLights) = 0; + virtual void ComputeLightingState(int nCount, const LightingQuery_t* pQuery, MaterialLightingState_t* pState, ITexture** ppEnvCubemapTexture) = 0; + virtual void GetModelDecalHandles(StudioDecalHandle_t* pDecals, int nDecalStride, int nCount, const ModelInstanceHandle_t* pHandles) = 0; + virtual void ComputeStaticLightingState(int nCount, const StaticLightingQuery_t* pQuery, MaterialLightingState_t* pState, MaterialLightingState_t* pDecalState, ColorMeshInfo_t** ppStaticLighting, ITexture** ppEnvCubemapTexture, DataCacheHandle_t* pColorMeshHandles) = 0; + virtual void CleanupStaticLightingState(int nCount, DataCacheHandle_t* pColorMeshHandles) = 0; +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/ivrenderview.h b/SpyCustom/ivrenderview.h new file mode 100644 index 0000000..12f031c --- /dev/null +++ b/SpyCustom/ivrenderview.h @@ -0,0 +1,310 @@ +#if !defined( IVRENDERVIEW_H ) +#define IVRENDERVIEW_H +#ifdef _WIN32 +#pragma once +#endif + +#include "basetypes.h" +#include "vplane.h" +#include "interface.h" +#include "imaterialsystem.h" +#include "const.h" +#include "vertexcolor.h" +#include "refcount.h" + + + +class CViewSetup; +class CEngineSprite; +class IClientEntity; +class IMaterial; +struct model_t; +class IClientRenderable; +class IMatRenderContext; +class CVolumeCuller; + + +enum +{ + DRAWWORLDLISTS_DRAW_STRICTLYABOVEWATER = 0x001, + DRAWWORLDLISTS_DRAW_STRICTLYUNDERWATER = 0x002, + DRAWWORLDLISTS_DRAW_INTERSECTSWATER = 0x004, + DRAWWORLDLISTS_DRAW_WATERSURFACE = 0x008, + DRAWWORLDLISTS_DRAW_SKYBOX = 0x010, + DRAWWORLDLISTS_DRAW_CLIPSKYBOX = 0x020, + DRAWWORLDLISTS_DRAW_SHADOWDEPTH = 0x040, + DRAWWORLDLISTS_DRAW_REFRACTION = 0x080, + DRAWWORLDLISTS_DRAW_REFLECTION = 0x100, + DRAWWORLDLISTS_DRAW_WORLD_GEOMETRY = 0x200, + DRAWWORLDLISTS_DRAW_DECALS_AND_OVERLAYS = 0x400, + DRAWWORLDLISTS_DRAW_SIMPLE_WORLD_MODEL = 0x800, + DRAWWORLDLISTS_DRAW_SIMPLE_WORLD_MODEL_WATER = 0x1000, + DRAWWORLDLISTS_DRAW_SKIP_DISPLACEMENTS = 0x2000, + DRAWWORLDLISTS_DRAW_SSAO = 0x4000, +}; + +enum +{ + MAT_SORT_GROUP_STRICTLY_ABOVEWATER = 0, + MAT_SORT_GROUP_STRICTLY_UNDERWATER, + MAT_SORT_GROUP_INTERSECTS_WATER_SURFACE, + MAT_SORT_GROUP_WATERSURFACE, + + MAX_MAT_SORT_GROUPS +}; + +enum ERenderDepthMode_t +{ + DEPTH_MODE_NORMAL = 0, + DEPTH_MODE_SHADOW = 1, + DEPTH_MODE_SSA0 = 2, + + DEPTH_MODE_MAX +}; + + +static const char* s_pMatSortGroupsString[] = +{ + "Sort: Abovewater", + "Sort: Underwater", + "Sort: IntersectsWater", + "Sort: WaterSurface", +}; + +typedef VPlane Frustum[FRUSTUM_NUMPLANES]; + + +typedef unsigned short LeafIndex_t; +enum +{ + INVALID_LEAF_INDEX = (LeafIndex_t)~0 +}; + + +#if 1 +struct WorldListLeafData_t +{ + LeafIndex_t leafIndex; + int16 waterData; + uint16 firstTranslucentSurface; + uint16 translucentSurfaceCount; +}; +#else +struct WorldListLeafData_t +{ + uint32 leafIndex; + int32 waterData; + uint32 firstTranslucentSurface; + uint32 translucentSurfaceCount; +}; +#endif +struct WorldListInfo_t +{ + int m_ViewFogVolume; + int m_LeafCount; + bool m_bHasWater; + WorldListLeafData_t* m_pLeafDataList; +}; + +class IWorldRenderList : public IRefCounted +{ +}; + +struct VisibleFogVolumeInfo_t +{ + int m_nVisibleFogVolume; + int m_nVisibleFogVolumeLeaf; + bool m_bEyeInFogVolume; + float m_flDistanceToWater; + float m_flWaterHeight; + IMaterial* m_pFogVolumeMaterial; +}; + + +struct BrushVertex_t +{ + Vector m_Pos; + Vector m_Normal; + Vector m_TangentS; + Vector m_TangentT; + Vector2D m_TexCoord; + Vector2D m_LightmapCoord; + +private: + BrushVertex_t(const BrushVertex_t& src); +}; + +struct VisOverrideData_t +{ + Vector m_vecVisOrigin; + float m_fDistToAreaPortalTolerance; + + Vector m_vPortalCorners[4]; + bool m_bTrimFrustumToPortalCorners; + + Vector m_vPortalOrigin; + Vector m_vPortalForward; + float m_flPortalRadius; + +}; + + +class IBrushSurface +{ +public: + virtual void ComputeTextureCoordinate(Vector const& worldPos, Vector2D& texCoord) = 0; + virtual void ComputeLightmapCoordinate(Vector const& worldPos, Vector2D& lightmapCoord) = 0; + + virtual int GetVertexCount() const = 0; + virtual void GetVertexData(BrushVertex_t* pVerts) = 0; + + virtual IMaterial* GetMaterial() = 0; +}; + + +class IBrushRenderer +{ +public: + virtual bool RenderBrushModelSurface(IClientEntity* pBaseEntity, IBrushSurface* pBrushSurface) = 0; +}; + + +#define MAX_VIS_LEAVES 32 +enum DrawBrushModelMode_t +{ + DBM_DRAW_ALL = 0, + DBM_DRAW_OPAQUE_ONLY, + DBM_DRAW_TRANSLUCENT_ONLY, +}; + + +struct BrushArrayInstanceData_t +{ + matrix3x4a_t* m_pBrushToWorld; + const model_t* m_pBrushModel; + Vector4D m_DiffuseModulation; + ShaderStencilState_t* m_pStencilState; +}; + + +class IVRenderView +{ +public: + + virtual void DrawBrushModel( + IClientEntity* baseentity, + model_t* model, + const Vector& origin, + const QAngle& angles, + bool bUnused) = 0; + + virtual void DrawIdentityBrushModel(IWorldRenderList* pList, model_t* model) = 0; + + virtual void TouchLight(struct dlight_t* light) = 0; + virtual void Draw3DDebugOverlays(void) = 0; + virtual void SetBlend(float blend) = 0; + virtual float GetBlend(void) = 0; + + virtual void SetColorModulation(float const* blend) = 0; + virtual void GetColorModulation(float* blend) = 0; + + virtual void SceneBegin(void) = 0; + virtual void SceneEnd(void) = 0; + + virtual void GetVisibleFogVolume(const Vector& eyePoint, const VisOverrideData_t* pVisOverrideData, VisibleFogVolumeInfo_t* pInfo) = 0; + + virtual IWorldRenderList* CreateWorldList() = 0; +#if defined(_PS3) + virtual IWorldRenderList* CreateWorldList_PS3(int viewID) = 0; + virtual void BuildWorldLists_PS3_Epilogue(IWorldRenderList* pList, WorldListInfo_t* pInfo, bool bShadowDepth) = 0; +#else + virtual void BuildWorldLists_Epilogue(IWorldRenderList* pList, WorldListInfo_t* pInfo, bool bShadowDepth) = 0; +#endif + virtual void BuildWorldLists(IWorldRenderList* pList, WorldListInfo_t* pInfo, int iForceFViewLeaf, const VisOverrideData_t* pVisData = NULL, bool bShadowDepth = false, float* pReflectionWaterHeight = NULL) = 0; + virtual void DrawWorldLists(IMatRenderContext* pRenderContext, IWorldRenderList* pList, unsigned long flags, float waterZAdjust) = 0; + virtual void GetWorldListIndicesInfo(WorldListIndicesInfo_t* pIndicesInfoOut, IWorldRenderList* pList, unsigned long nFlags) = 0; + + virtual void DrawTopView(bool enable) = 0; + virtual void TopViewNoBackfaceCulling(bool bDisable) = 0; + virtual void TopViewNoVisCheck(bool bDisable) = 0; + virtual void TopViewBounds(Vector2D const& mins, Vector2D const& maxs) = 0; + virtual void SetTopViewVolumeCuller(const CVolumeCuller* pVolumeCuller) = 0; + + virtual void DrawLights(void) = 0; + virtual void DrawMaskEntities(void) = 0; + + virtual void DrawTranslucentSurfaces(IMatRenderContext* pRenderContext, IWorldRenderList* pList, int* pSortList, int sortCount, unsigned long flags) = 0; + + virtual void DrawLineFile(void) = 0; + virtual void DrawLightmaps(IWorldRenderList* pList, int pageId) = 0; + virtual void ViewSetupVis(bool novis, int numorigins, const Vector origin[]) = 0; + + virtual bool AreAnyLeavesVisible(int* leafList, int nLeaves) = 0; + + virtual void VguiPaint(void) = 0; + virtual void ViewDrawFade(byte* color, IMaterial* pMaterial, bool mapFullTextureToScreen = true) = 0; + virtual void OLD_SetProjectionMatrix(float fov, float zNear, float zFar) = 0; + virtual colorVec GetLightAtPoint(Vector& pos) = 0; + virtual int GetViewEntity(void) = 0; + virtual bool IsViewEntity(int entindex) = 0; + virtual float GetFieldOfView(void) = 0; + virtual unsigned char** GetAreaBits(void) = 0; + + virtual void SetFogVolumeState(int nVisibleFogVolume, bool bUseHeightFog) = 0; + + virtual void InstallBrushSurfaceRenderer(IBrushRenderer* pBrushRenderer) = 0; + + virtual void DrawBrushModelShadow(IClientRenderable* pRenderable) = 0; + + virtual bool LeafContainsTranslucentSurfaces(IWorldRenderList* pList, int sortIndex, unsigned long flags) = 0; + + virtual bool DoesBoxIntersectWaterVolume(const Vector& mins, const Vector& maxs, int leafWaterDataID) = 0; + + virtual void SetAreaState( + unsigned char chAreaBits[MAX_AREA_STATE_BYTES], + unsigned char chAreaPortalBits[MAX_AREA_PORTAL_STATE_BYTES]) = 0; + + virtual void VGui_Paint(int mode) = 0; + + virtual void Push3DView(IMatRenderContext* pRenderContext, const CViewSetup& view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes) = 0; + virtual void Push2DView(IMatRenderContext* pRenderContext, const CViewSetup& view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes) = 0; + virtual void PopView(IMatRenderContext* pRenderContext, Frustum frustumPlanes) = 0; + + virtual void SetMainView(const Vector& vecOrigin, const QAngle& angles) = 0; + + enum + { + VIEW_SETUP_VIS_EX_RETURN_FLAGS_USES_RADIAL_VIS = 0x00000001 + }; + + virtual void ViewSetupVisEx(bool novis, int numorigins, const Vector origin[], unsigned int& returnFlags) = 0; + + virtual void OverrideViewFrustum(Frustum custom) = 0; + + virtual void DrawBrushModelShadowDepth(IClientEntity* baseentity, model_t* model, const Vector& origin, const QAngle& angles, ERenderDepthMode_t DepthMode) = 0; + virtual void UpdateBrushModelLightmap(model_t* model, IClientRenderable* pRenderable) = 0; + virtual void BeginUpdateLightmaps(void) = 0; + virtual void EndUpdateLightmaps() = 0; + virtual void OLD_SetOffCenterProjectionMatrix(float fov, float zNear, float zFar, float flAspectRatio, float flBottom, float flTop, float flLeft, float flRight) = 0; + virtual void OLD_SetProjectionMatrixOrtho(float left, float top, float right, float bottom, float zNear, float zFar) = 0; + virtual void Push3DView(IMatRenderContext* pRenderContext, const CViewSetup& view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes, ITexture* pDepthTexture) = 0; + virtual void GetMatricesForView(const CViewSetup& view, VMatrix* pWorldToView, VMatrix* pViewToProjection, VMatrix* pWorldToProjection, VMatrix* pWorldToPixels) = 0; + virtual void DrawBrushModelEx(IClientEntity* baseentity, model_t* model, const Vector& origin, const QAngle& angles, DrawBrushModelMode_t mode) = 0; + + virtual bool DoesBrushModelNeedPowerOf2Framebuffer(const model_t* model) = 0; + + virtual void DrawBrushModelArray(IMatRenderContext* pContext, int nCount, const BrushArrayInstanceData_t* pInstanceData, int nModelTypeFlags) = 0; +}; + +#define VENGINE_RENDERVIEW_INTERFACE_VERSION "VEngineRenderView014" + +#if defined(_STATIC_LINKED) && defined(CLIENT_DLL) +namespace Client +{ + extern IVRenderView* render; +} +#else +extern IVRenderView* render; +#endif + +#endif \ No newline at end of file diff --git a/SpyCustom/jobthread.h b/SpyCustom/jobthread.h new file mode 100644 index 0000000..d254370 --- /dev/null +++ b/SpyCustom/jobthread.h @@ -0,0 +1,1270 @@ +#include +#include "threadtools.h" +#include "refcount.h" +#include "utllinkedlist.h" +#include "utlvector.h" +#include "functors.h" + +#include "vstdlib.h" + +#ifndef JOBTHREAD_H +#define JOBTHREAD_H + +#ifdef AddJob +#undef AddJob +#undef GetJob +#endif + +#ifdef VSTDLIB_DLL_EXPORT +#define JOB_INTERFACE DLL_EXPORT +#define JOB_OVERLOAD DLL_GLOBAL_EXPORT +#define JOB_CLASS DLL_CLASS_EXPORT +#else +#define JOB_INTERFACE DLL_IMPORT +#define JOB_OVERLOAD DLL_GLOBAL_IMPORT +#define JOB_CLASS DLL_CLASS_IMPORT +#endif + +#if defined( _WIN32 ) +#pragma once +#endif + +class CJob; + +enum JobStatusEnum_t +{ + JOB_OK, + JOB_STATUS_PENDING, + JOB_STATUS_INPROGRESS, + JOB_STATUS_ABORTED, + JOB_STATUS_UNSERVICED, +}; + +typedef int JobStatus_t; + +enum JobFlags_t +{ + JF_IO = (1 << 0), + JF_BOOST_THREAD = (1 << 1), + JF_SERIAL = (1 << 2), + JF_QUEUE = (1 << 3), +}; + +enum JobPriority_t +{ + JP_LOW, + JP_NORMAL, + JP_HIGH, + JP_IMMEDIATE, + + JP_NUM_PRIORITIES, + + JP_FRAME = JP_NORMAL, + JP_FRAME_SEGMENT = JP_HIGH, +}; + +#define TP_MAX_POOL_THREADS 64 +struct ThreadPoolStartParams_t +{ + ThreadPoolStartParams_t(bool bIOThreads = false, unsigned nThreads = (unsigned)-1, int* pAffinities = NULL, ThreeState_t fDistribute = TRS_NONE, unsigned nStackSize = (unsigned)-1, int iThreadPriority = SHRT_MIN) + : bIOThreads(bIOThreads), nThreads(nThreads), nThreadsMax(-1), fDistribute(fDistribute), nStackSize(nStackSize), iThreadPriority(iThreadPriority) + { + bExecOnThreadPoolThreadsOnly = false; +#if defined( DEDICATED ) && IsPlatformLinux() + bEnableOnLinuxDedicatedServer = false; +#endif + + bUseAffinityTable = (pAffinities != NULL) && (fDistribute == TRS_TRUE) && (nThreads != (unsigned)-1); + if (bUseAffinityTable) + { + nThreads = MIN(TP_MAX_POOL_THREADS, nThreads); + for (unsigned int i = 0; i < nThreads; i++) + { + iAffinityTable[i] = pAffinities[i]; + } + } + } + + int nThreads; + int nThreadsMax; + ThreeState_t fDistribute; + int nStackSize; + int iThreadPriority; + int iAffinityTable[TP_MAX_POOL_THREADS]; + + bool bIOThreads : 1; + bool bUseAffinityTable : 1; + bool bExecOnThreadPoolThreadsOnly : 1; +#if defined( DEDICATED ) && IsPlatformLinux() + bool bEnableOnLinuxDedicatedServer : 1; +#endif +}; + +typedef bool (*JobFilter_t)(CJob*); + +enum ThreadPoolMessages_t +{ + TPM_EXIT, + TPM_SUSPEND, +}; + +#ifdef Yield +#undef Yield +#endif + +abstract_class IThreadPool : public IRefCounted +{ +public: + virtual ~IThreadPool() {}; + + virtual bool Start(const ThreadPoolStartParams_t& startParams = ThreadPoolStartParams_t()) = 0; + virtual bool Stop(int timeout = TT_INFINITE) = 0; + + virtual unsigned GetJobCount() = 0; + virtual int NumThreads() = 0; + virtual int NumIdleThreads() = 0; + + virtual int SuspendExecution() = 0; + virtual int ResumeExecution() = 0; + + virtual int YieldWait(CThreadEvent** pEvents, int nEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE) = 0; + virtual int YieldWait(CJob**, int nJobs, bool bWaitAll = true, unsigned timeout = TT_INFINITE) = 0; + virtual void Yield(unsigned timeout) = 0; + + bool YieldWait(CThreadEvent& event, unsigned timeout = TT_INFINITE); + bool YieldWait(CJob*, unsigned timeout = TT_INFINITE); + + virtual void AddJob(CJob*) = 0; + + virtual void AddFunctor(CFunctor* pFunctor, CJob** ppJob = NULL, const char* pszDescription = NULL, unsigned flags = 0) { AddFunctorInternal(RetAddRef(pFunctor), ppJob, pszDescription, flags); } + + virtual void ChangePriority(CJob* p, JobPriority_t priority) = 0; + + int ExecuteAll(JobFilter_t pfnFilter = NULL) { return ExecuteToPriority(JP_LOW, pfnFilter); } + virtual int ExecuteToPriority(JobPriority_t toPriority, JobFilter_t pfnFilter = NULL) = 0; + virtual int AbortAll() = 0; + + virtual void AddPerFrameJob(CJob*) = 0; + + #define DEFINE_NONMEMBER_ADD_CALL(N) \ + template \ + CJob *AddCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + #define DEFINE_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + #define DEFINE_CONST_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + #define DEFINE_REF_COUNTING_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + #define DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + #define DEFINE_NONMEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + #define DEFINE_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + #define DEFINE_CONST_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + #define DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + #define DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + \ + return pJob; \ + } + + FUNC_GENERATE_ALL(DEFINE_NONMEMBER_ADD_CALL); + FUNC_GENERATE_ALL(DEFINE_MEMBER_ADD_CALL); + FUNC_GENERATE_ALL(DEFINE_CONST_MEMBER_ADD_CALL); + FUNC_GENERATE_ALL(DEFINE_REF_COUNTING_MEMBER_ADD_CALL); + FUNC_GENERATE_ALL(DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL); + FUNC_GENERATE_ALL(DEFINE_NONMEMBER_QUEUE_CALL); + FUNC_GENERATE_ALL(DEFINE_MEMBER_QUEUE_CALL); + FUNC_GENERATE_ALL(DEFINE_CONST_MEMBER_QUEUE_CALL); + FUNC_GENERATE_ALL(DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL); + FUNC_GENERATE_ALL(DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL); + + #undef DEFINE_NONMEMBER_ADD_CALL + #undef DEFINE_MEMBER_ADD_CALL + #undef DEFINE_CONST_MEMBER_ADD_CALL + #undef DEFINE_REF_COUNTING_MEMBER_ADD_CALL + #undef DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL + #undef DEFINE_NONMEMBER_QUEUE_CALL + #undef DEFINE_MEMBER_QUEUE_CALL + #undef DEFINE_CONST_MEMBER_QUEUE_CALL + #undef DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL + #undef DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL + +private: + virtual void AddFunctorInternal(CFunctor*, CJob** = NULL, const char* pszDescription = NULL, unsigned flags = 0) = 0; + + friend class CJob; + + virtual CJob* GetDummyJob() = 0; + +public: + virtual void Distribute(bool bDistribute = true, int* pAffinityTable = NULL) = 0; + + virtual bool Start(const ThreadPoolStartParams_t& startParams, const char* pszNameOverride) = 0; + + virtual int YieldWaitPerFrameJobs() = 0; +}; + +JOB_INTERFACE IThreadPool* CreateNewThreadPool(); +JOB_INTERFACE void DestroyThreadPool(IThreadPool* pPool); + +JOB_INTERFACE void RunThreadPoolTests(); + +JOB_INTERFACE IThreadPool* g_pThreadPool; +#ifdef _X360 +JOB_INTERFACE IThreadPool* g_pAlternateThreadPool; +#endif + +DECLARE_POINTER_HANDLE(ThreadPoolData_t); +#define JOB_NO_DATA ((ThreadPoolData_t)-1) + +class CJob : public CRefCounted1 +{ +public: + CJob(JobPriority_t priority = JP_NORMAL) + : m_status(JOB_STATUS_UNSERVICED), + m_ThreadPoolData(JOB_NO_DATA), + m_priority(priority), + m_flags(0), + m_pThreadPool(NULL), + m_CompleteEvent(true), + m_iServicingThread(-1) + { + } + + void SetPriority(JobPriority_t priority) { m_priority = priority; } + JobPriority_t GetPriority() const { return m_priority; } + + void SetFlags(unsigned flags) { m_flags = flags; } + unsigned GetFlags() const { return m_flags; } + + void SetServiceThread(int iServicingThread) { m_iServicingThread = (char)iServicingThread; } + int GetServiceThread() const { return m_iServicingThread; } + void ClearServiceThread() { m_iServicingThread = -1; } + + bool Executed() const { return (m_status == JOB_OK); } + bool CanExecute() const { return (m_status == JOB_STATUS_PENDING || m_status == JOB_STATUS_UNSERVICED); } + bool IsFinished() const { return (m_status != JOB_STATUS_PENDING && m_status != JOB_STATUS_INPROGRESS && m_status != JOB_STATUS_UNSERVICED); } + JobStatus_t GetStatus() const { return m_status; } + + bool TryLock() { return m_mutex.TryLock(); } + void Lock() { m_mutex.Lock(); } + void Unlock() { m_mutex.Unlock(); } + + bool WaitForFinish(uint32 dwTimeout = TT_INFINITE) { if (!this) return true; return (!IsFinished()) ? g_pThreadPool->YieldWait(this, dwTimeout) : true; } + bool WaitForFinishAndRelease(uint32 dwTimeout = TT_INFINITE) { if (!this) return true; bool bResult = WaitForFinish(dwTimeout); Release(); return bResult; } + CThreadEvent* AccessEvent() { return &m_CompleteEvent; } + + JobStatus_t Execute(); + JobStatus_t TryExecute(); + JobStatus_t ExecuteAndRelease() { JobStatus_t status = Execute(); Release(); return status; } + JobStatus_t TryExecuteAndRelease() { JobStatus_t status = TryExecute(); Release(); return status; } + + JobStatus_t Abort(bool bDiscard = true); + + virtual char const* Describe() { return "Job"; } + +private: + friend class CThreadPool; + + JobStatus_t m_status; + JobPriority_t m_priority; + CThreadMutex m_mutex; + unsigned char m_flags; + char m_iServicingThread; + short m_reserved; + ThreadPoolData_t m_ThreadPoolData; + IThreadPool* m_pThreadPool; + CThreadEvent m_CompleteEvent; + +#if defined( THREAD_PARENT_STACK_TRACE_ENABLED ) + void* m_ParentStackTrace[THREAD_PARENT_STACK_TRACE_LENGTH]; +#endif + +private: + CJob(const CJob& fromRequest); + void operator=(const CJob& fromRequest); + + virtual JobStatus_t DoExecute() = 0; + virtual JobStatus_t DoAbort(bool bDiscard) { return JOB_STATUS_ABORTED; } + virtual void DoCleanup() {} +}; + +class CFunctorJob : public CJob +{ +public: + CFunctorJob(CFunctor* pFunctor, const char* pszDescription = NULL) + : m_pFunctor(pFunctor) + { + if (pszDescription) + { + Q_strncpy(m_szDescription, pszDescription, sizeof(m_szDescription)); + } + else + { + m_szDescription[0] = 0; + } + } + + virtual JobStatus_t DoExecute() + { + (*m_pFunctor)(); + return JOB_OK; + } + + const char* Describe() + { + return m_szDescription; + } + +private: + CRefPtr m_pFunctor; + char m_szDescription[16]; +}; + +class CJobSet +{ +public: + CJobSet(CJob* pJob = NULL) + { + if (pJob) + { + m_jobs.AddToTail(pJob); + } + } + + CJobSet(CJob** ppJobs, int nJobs) + { + if (ppJobs) + { + m_jobs.AddMultipleToTail(nJobs, ppJobs); + } + } + + ~CJobSet() + { + for (int i = 0; i < m_jobs.Count(); i++) + { + m_jobs[i]->Release(); + } + } + + void operator+=(CJob* pJob) + { + m_jobs.AddToTail(pJob); + } + + void operator-=(CJob* pJob) + { + m_jobs.FindAndRemove(pJob); + } + + void Execute(bool bRelease = true) + { + for (int i = 0; i < m_jobs.Count(); i++) + { + m_jobs[i]->Execute(); + if (bRelease) + { + m_jobs[i]->Release(); + } + } + + if (bRelease) + { + m_jobs.RemoveAll(); + } + } + + void Abort(bool bRelease = true) + { + for (int i = 0; i < m_jobs.Count(); i++) + { + m_jobs[i]->Abort(); + if (bRelease) + { + m_jobs[i]->Release(); + } + } + + if (bRelease) + { + m_jobs.RemoveAll(); + } + } + + void WaitForFinish(bool bRelease = true) + { + for (int i = 0; i < m_jobs.Count(); i++) + { + m_jobs[i]->WaitForFinish(); + if (bRelease) + { + m_jobs[i]->Release(); + } + } + + if (bRelease) + { + m_jobs.RemoveAll(); + } + } + + void WaitForFinish(IThreadPool* pPool, bool bRelease = true) + { + pPool->YieldWait(m_jobs.Base(), m_jobs.Count()); + + if (bRelease) + { + for (int i = 0; i < m_jobs.Count(); i++) + { + m_jobs[i]->Release(); + } + + m_jobs.RemoveAll(); + } + } + +private: + CUtlVectorFixed m_jobs; +}; + +#define ThreadExecute g_pThreadPool->QueueCall +#define ThreadExecuteRef g_pThreadPool->QueueRefCall + +#define BeginExecuteParallel() do { CJobSet jobSet +#define EndExecuteParallel() jobSet.WaitForFinish( g_pThreadPool ); } while (0) + +#define ExecuteParallel jobSet += g_pThreadPool->QueueCall +#define ExecuteRefParallel jobSet += g_pThreadPool->QueueCallRef + + +#pragma warning(push) +#pragma warning(disable:4389) +#pragma warning(disable:4018) +#pragma warning(disable:4701) + +#define DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL(N) \ + template \ + void IterRangeParallel(FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_SEPARATOR_##N FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + const int MAX_THREADS = 16; \ + int nIdle = g_pThreadPool->NumIdleThreads(); \ + ITERTYPE1 range = to - from; \ + int nThreads = min( nIdle + 1, range ); \ + if ( nThreads > MAX_THREADS ) \ + { \ + nThreads = MAX_THREADS; \ + } \ + if ( nThreads < 2 ) \ + { \ + FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + ITERTYPE1 nIncrement = range / nThreads; \ + \ + CJobSet jobSet; \ + while ( --nThreads ) \ + { \ + ITERTYPE2 thisTo = from + nIncrement; \ + jobSet += g_pThreadPool->AddCall( pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \ + from = thisTo; \ + } \ + FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + jobSet.WaitForFinish( g_pThreadPool ); \ + } \ + \ + } + +FUNC_GENERATE_ALL(DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL); + +#define DEFINE_MEMBER_ITER_RANGE_PARALLEL(N) \ + template \ + void IterRangeParallel(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_SEPARATOR_##N FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + const int MAX_THREADS = 16; \ + int nIdle = g_pThreadPool->NumIdleThreads(); \ + ITERTYPE1 range = to - from; \ + int nThreads = min( nIdle + 1, range ); \ + if ( nThreads > MAX_THREADS ) \ + { \ + nThreads = MAX_THREADS; \ + } \ + if ( nThreads < 2 ) \ + { \ + FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + ITERTYPE1 nIncrement = range / nThreads; \ + \ + CJobSet jobSet; \ + while ( --nThreads ) \ + { \ + ITERTYPE2 thisTo = from + nIncrement; \ + jobSet += g_pThreadPool->AddCall( pObject, pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \ + from = thisTo; \ + } \ + FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + jobSet.WaitForFinish( g_pThreadPool ); \ + } \ + \ + } + +FUNC_GENERATE_ALL(DEFINE_MEMBER_ITER_RANGE_PARALLEL); + + +template +class CJobItemProcessor +{ +public: + typedef T ItemType_t; + void Begin() {} + void End() {} +}; + +template +class CFuncJobItemProcessor : public CJobItemProcessor +{ +public: + void Init(void (*pfnProcess)(T&), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL) + { + m_pfnProcess = pfnProcess; + m_pfnBegin = pfnBegin; + m_pfnEnd = pfnEnd; + } + + void Begin() { if (m_pfnBegin) (*m_pfnBegin)(); } + void Process(T& item) { (*m_pfnProcess)(item); } + void End() { if (m_pfnEnd) (*m_pfnEnd)(); } + +protected: + void (*m_pfnProcess)(T&); + void (*m_pfnBegin)(); + void (*m_pfnEnd)(); +}; + +template +class CMemberFuncJobItemProcessor : public CJobItemProcessor +{ +public: + void Init(OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(T&), void (FUNCTION_CLASS::* pfnBegin)() = NULL, void (FUNCTION_CLASS::* pfnEnd)() = NULL) + { + m_pObject = pObject; + m_pfnProcess = pfnProcess; + m_pfnBegin = pfnBegin; + m_pfnEnd = pfnEnd; + } + + void Begin() { if (m_pfnBegin) ((*m_pObject).*m_pfnBegin)(); } + void Process(T& item) { ((*m_pObject).*m_pfnProcess)(item); } + void End() { if (m_pfnEnd) ((*m_pObject).*m_pfnEnd)(); } + +protected: + OBJECT_TYPE* m_pObject; + + void (FUNCTION_CLASS::* m_pfnProcess)(T&); + void (FUNCTION_CLASS::* m_pfnBegin)(); + void (FUNCTION_CLASS::* m_pfnEnd)(); +}; + +template +class CLoopFuncJobItemProcessor : public CJobItemProcessor +{ +public: + void Init(void (*pfnProcess)(T*, int, int), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL) + { + m_pfnProcess = pfnProcess; + m_pfnBegin = pfnBegin; + m_pfnEnd = pfnEnd; + } + + void Begin() { if (m_pfnBegin) (*m_pfnBegin)(); } + void Process(T* pContext, int nFirst, int nCount) { (*m_pfnProcess)(pContext, nFirst, nCount); } + void End() { if (m_pfnEnd) (*m_pfnEnd)(); } + +protected: + void (*m_pfnProcess)(T*, int, int); + void (*m_pfnBegin)(); + void (*m_pfnEnd)(); +}; + +template +class CLoopMemberFuncJobItemProcessor : public CJobItemProcessor +{ +public: + void Init(OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(T*, int, int), void (FUNCTION_CLASS::* pfnBegin)() = NULL, void (FUNCTION_CLASS::* pfnEnd)() = NULL) + { + m_pObject = pObject; + m_pfnProcess = pfnProcess; + m_pfnBegin = pfnBegin; + m_pfnEnd = pfnEnd; + } + + void Begin() { if (m_pfnBegin) ((*m_pObject).*m_pfnBegin)(); } + void Process(T* item, int nFirst, int nCount) { ((*m_pObject).*m_pfnProcess)(item, nFirst, nCount); } + void End() { if (m_pfnEnd) ((*m_pObject).*m_pfnEnd)(); } + +protected: + OBJECT_TYPE* m_pObject; + + void (FUNCTION_CLASS::* m_pfnProcess)(T*, int, int); + void (FUNCTION_CLASS::* m_pfnBegin)(); + void (FUNCTION_CLASS::* m_pfnEnd)(); +}; + + +#pragma warning(push) +#pragma warning(disable:4189) + +template +class CParallelProcessor +{ +public: + CParallelProcessor() + { + m_pItems = m_pLimit = 0; + } + + void Run(ITEM_TYPE* pItems, unsigned nItems, int nChunkSize = 1, int nMaxParallel = INT_MAX, IThreadPool* pThreadPool = NULL) + { + if (nItems == 0) + return; + +#if defined(_X360) + volatile int ignored = ID_TO_PREVENT_COMDATS_IN_PROFILES; +#endif + + m_nChunkSize = nChunkSize; + if (!pThreadPool) + { + pThreadPool = g_pThreadPool; + } + + m_pItems = pItems; + m_pLimit = pItems + nItems; + + int nJobs = nItems - 1; + + if (nJobs > nMaxParallel) + { + nJobs = nMaxParallel; + } + + if (!pThreadPool) + { + DoExecute(); + return; + } + + int nThreads = pThreadPool->NumThreads(); + if (nJobs > nThreads) + { + nJobs = nThreads; + } + + if (nJobs > 0) + { + CJob** jobs = (CJob**)stackalloc(nJobs * sizeof(CJob**)); + int i = nJobs; + + while (i--) + { + jobs[i] = pThreadPool->QueueCall(this, &CParallelProcessor::DoExecute); + } + + DoExecute(); + + for (i = 0; i < nJobs; i++) + { + jobs[i]->Abort(); + jobs[i]->Release(); + } + } + else + { + DoExecute(); + } + } + + ITEM_PROCESSOR_TYPE m_ItemProcessor; + +private: + void DoExecute() + { + if (m_pItems < m_pLimit) + { +#if defined(_X360) + volatile int ignored = ID_TO_PREVENT_COMDATS_IN_PROFILES; +#endif + m_ItemProcessor.Begin(); + + ITEM_TYPE* pLimit = m_pLimit; + + int nChunkSize = m_nChunkSize; + for (;;) + { + ITEM_TYPE* pCurrent = m_pItems.AtomicAdd(nChunkSize); + ITEM_TYPE* pLast = MIN(pLimit, pCurrent + nChunkSize); + while (pCurrent < pLast) + { + m_ItemProcessor.Process(*pCurrent); + pCurrent++; + } + if (pCurrent >= pLimit) + { + break; + } + } + m_ItemProcessor.End(); + } + } + CInterlockedPtr m_pItems; + ITEM_TYPE* m_pLimit; + int m_nChunkSize; + +}; + +#pragma warning(pop) + +template +inline void ParallelProcess(ITEM_TYPE* pItems, unsigned nItems, void (*pfnProcess)(ITEM_TYPE&), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelProcessor > processor; + processor.m_ItemProcessor.Init(pfnProcess, pfnBegin, pfnEnd); + processor.Run(pItems, nItems, 1, nMaxParallel); +} + +template +inline void ParallelProcess(ITEM_TYPE* pItems, unsigned nItems, OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(ITEM_TYPE&), void (FUNCTION_CLASS::* pfnBegin)() = NULL, void (FUNCTION_CLASS::* pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelProcessor > processor; + processor.m_ItemProcessor.Init(pObject, pfnProcess, pfnBegin, pfnEnd); + processor.Run(pItems, nItems, 1, nMaxParallel); +} + +template +inline void ParallelProcess(IThreadPool* pPool, ITEM_TYPE* pItems, unsigned nItems, void (*pfnProcess)(ITEM_TYPE&), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelProcessor > processor; + processor.m_ItemProcessor.Init(pfnProcess, pfnBegin, pfnEnd); + processor.Run(pItems, nItems, 1, nMaxParallel, pPool); +} + +template +inline void ParallelProcess(IThreadPool* pPool, ITEM_TYPE* pItems, unsigned nItems, OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(ITEM_TYPE&), void (FUNCTION_CLASS::* pfnBegin)() = NULL, void (FUNCTION_CLASS::* pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelProcessor > processor; + processor.m_ItemProcessor.Init(pObject, pfnProcess, pfnBegin, pfnEnd); + processor.Run(pItems, nItems, 1, nMaxParallel, pPool); +} + +template +inline void ParallelProcessChunks(ITEM_TYPE* pItems, unsigned nItems, void (*pfnProcess)(ITEM_TYPE&), int nChunkSize, int nMaxParallel = INT_MAX) +{ + CParallelProcessor > processor; + processor.m_ItemProcessor.Init(pfnProcess, NULL, NULL); + processor.Run(pItems, nItems, nChunkSize, nMaxParallel); +} + +template +inline void ParallelProcessChunks(ITEM_TYPE* pItems, unsigned nItems, OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(ITEM_TYPE&), int nChunkSize, int nMaxParallel = INT_MAX) +{ + CParallelProcessor > processor; + processor.m_ItemProcessor.Init(pObject, pfnProcess, NULL, NULL); + processor.Run(pItems, nItems, nChunkSize, nMaxParallel); +} + +template +inline void ParallelProcessChunks(IThreadPool* pPool, ITEM_TYPE* pItems, unsigned nItems, OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(ITEM_TYPE&), int nChunkSize, int nMaxParallel = INT_MAX) +{ + CParallelProcessor > processor; + processor.m_ItemProcessor.Init(pObject, pfnProcess, NULL, NULL); + processor.Run(pItems, nItems, nChunkSize, nMaxParallel, pPool); +} + + +template +class CParallelLoopProcessor +{ +public: + CParallelLoopProcessor() + { + m_nIndex = m_nLimit = 0; + m_nChunkCount = 0; + m_nActive = 0; + } + + void Run(CONTEXT_TYPE* pContext, int nBegin, int nItems, int nChunkCount, int nMaxParallel = INT_MAX, IThreadPool* pThreadPool = NULL) + { + if (!nItems) + return; + + if (!pThreadPool) + { + pThreadPool = g_pThreadPool; + } + + m_pContext = pContext; + m_nIndex = nBegin; + m_nLimit = nBegin + nItems; + nChunkCount = MAX(MIN(nItems, nChunkCount), 1); + m_nChunkCount = (nItems + nChunkCount - 1) / nChunkCount; + int nJobs = (nItems + m_nChunkCount - 1) / m_nChunkCount; + if (nJobs > nMaxParallel) + { + nJobs = nMaxParallel; + } + + if (!pThreadPool) + { + DoExecute(); + return; + } + + int nThreads = pThreadPool->NumThreads(); + if (nJobs > nThreads) + { + nJobs = nThreads; + } + + if (nJobs > 0) + { + CJob** jobs = (CJob**)stackalloc(nJobs * sizeof(CJob**)); + int i = nJobs; + + while (i--) + { + jobs[i] = pThreadPool->QueueCall(this, &CParallelLoopProcessor::DoExecute); + } + + DoExecute(); + + for (i = 0; i < nJobs; i++) + { + jobs[i]->Abort(); + jobs[i]->Release(); + } + } + else + { + DoExecute(); + } + } + + ITEM_PROCESSOR_TYPE m_ItemProcessor; + +private: + void DoExecute() + { + m_ItemProcessor.Begin(); + for (;;) + { + int nIndex = m_nIndex.AtomicAdd(m_nChunkCount); + if (nIndex < m_nLimit) + { + int nCount = MIN(m_nChunkCount, m_nLimit - nIndex); + m_ItemProcessor.Process(m_pContext, nIndex, nCount); + } + else + { + break; + } + } + m_ItemProcessor.End(); + --m_nActive; + } + + CONTEXT_TYPE* m_pContext; + CInterlockedInt m_nIndex; + int m_nLimit; + int m_nChunkCount; + CInterlockedInt m_nActive; +}; + +template < typename CONTEXT_TYPE > +inline void ParallelLoopProcess(IThreadPool* pPool, CONTEXT_TYPE* pContext, int nStart, int nCount, void (*pfnProcess)(CONTEXT_TYPE*, int, int), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelLoopProcessor< CONTEXT_TYPE, CLoopFuncJobItemProcessor< CONTEXT_TYPE > > processor; + processor.m_ItemProcessor.Init(pfnProcess, pfnBegin, pfnEnd); + processor.Run(pContext, nStart, nCount, 1, nMaxParallel, pPool); +} + +template < typename CONTEXT_TYPE, typename OBJECT_TYPE, typename FUNCTION_CLASS > +inline void ParallelLoopProcess(IThreadPool* pPool, CONTEXT_TYPE* pContext, int nStart, int nCount, OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(CONTEXT_TYPE*, int, int), void (FUNCTION_CLASS::* pfnBegin)() = NULL, void (FUNCTION_CLASS::* pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelLoopProcessor< CONTEXT_TYPE, CLoopMemberFuncJobItemProcessor > processor; + processor.m_ItemProcessor.Init(pObject, pfnProcess, pfnBegin, pfnEnd); + processor.Run(pContext, nStart, nCount, 1, nMaxParallel, pPool); +} + +template < typename CONTEXT_TYPE > +inline void ParallelLoopProcessChunks(IThreadPool* pPool, CONTEXT_TYPE* pContext, int nStart, int nCount, int nChunkSize, void (*pfnProcess)(CONTEXT_TYPE*, int, int), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelLoopProcessor< CONTEXT_TYPE, CLoopFuncJobItemProcessor< CONTEXT_TYPE > > processor; + processor.m_ItemProcessor.Init(pfnProcess, pfnBegin, pfnEnd); + processor.Run(pContext, nStart, nCount, nChunkSize, nMaxParallel, pPool); +} + +template < typename CONTEXT_TYPE, typename OBJECT_TYPE, typename FUNCTION_CLASS > +inline void ParallelLoopProcessChunks(IThreadPool* pPool, CONTEXT_TYPE* pContext, int nStart, int nCount, int nChunkSize, OBJECT_TYPE* pObject, void (FUNCTION_CLASS::* pfnProcess)(CONTEXT_TYPE*, int, int), void (FUNCTION_CLASS::* pfnBegin)() = NULL, void (FUNCTION_CLASS::* pfnEnd)() = NULL, int nMaxParallel = INT_MAX) +{ + CParallelLoopProcessor< CONTEXT_TYPE, CLoopMemberFuncJobItemProcessor > processor; + processor.m_ItemProcessor.Init(pObject, pfnProcess, pfnBegin, pfnEnd); + processor.Run(pContext, nStart, nCount, nChunkSize, nMaxParallel, pPool); +} + +template +class CParallelProcessorBase +{ +protected: + typedef CParallelProcessorBase ThisParallelProcessorBase_t; + typedef Derived ThisParallelProcessorDerived_t; + +public: + CParallelProcessorBase() + { + m_nActive = 0; + } + +protected: + void Run(int nMaxParallel = INT_MAX, int threadOverride = -1) + { + int i = g_pThreadPool->NumIdleThreads(); + + if (nMaxParallel < i) + { + i = nMaxParallel; + } + + while (i-- > 0) + { + if (threadOverride == -1 || i == threadOverride - 1) + { + ++m_nActive; + ThreadExecute(this, &ThisParallelProcessorBase_t::DoExecute)->Release(); + } + } + + if (threadOverride == -1 || threadOverride == 0) + { + ++m_nActive; + DoExecute(); + } + + while (m_nActive) + { + ThreadPause(); + } + } + +protected: + void OnBegin() {} + bool OnProcess() { return false; } + void OnEnd() {} + +private: + void DoExecute() + { + static_cast(this)->OnBegin(); + + while (static_cast(this)->OnProcess()) + continue; + + static_cast(this)->OnEnd(); + + --m_nActive; + } + + CInterlockedInt m_nActive; +}; + + + + +inline uintp FunctorExecuteThread(void* pParam) +{ + CFunctor* pFunctor = (CFunctor*)pParam; + (*pFunctor)(); + pFunctor->Release(); + return 0; +} + +inline ThreadHandle_t ThreadExecuteSoloImpl(CFunctor* pFunctor, const char* pszName = NULL); + + +inline ThreadHandle_t ThreadExecuteSolo(CJob* pJob) { return ThreadExecuteSoloImpl(CreateFunctor(pJob, &CJob::Execute), pJob->Describe()); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1) { return ThreadExecuteSoloImpl(CreateFunctor(a1), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1, T2 a2) { return ThreadExecuteSoloImpl(CreateFunctor(a1, a2), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1, T2 a2, T3 a3) { return ThreadExecuteSoloImpl(CreateFunctor(a1, a2, a3), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4) { return ThreadExecuteSoloImpl(CreateFunctor(a1, a2, a3, a4), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { return ThreadExecuteSoloImpl(CreateFunctor(a1, a2, a3, a4, a5), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) { return ThreadExecuteSoloImpl(CreateFunctor(a1, a2, a3, a4, a5, a6), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) { return ThreadExecuteSoloImpl(CreateFunctor(a1, a2, a3, a4, a5, a6, a7), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSolo(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) { return ThreadExecuteSoloImpl(CreateFunctor(a1, a2, a3, a4, a5, a6, a7, a8), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef(const char* pszName, T1 a1, T2 a2) { return ThreadExecuteSoloImpl(CreateRefCountingFunctor(a1, a2), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef(const char* pszName, T1 a1, T2 a2, T3 a3) { return ThreadExecuteSoloImpl(CreateRefCountingFunctor(a1, a2, a3), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4) { return ThreadExecuteSoloImpl(CreateRefCountingFunctor(a1, a2, a3, a4), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { return ThreadExecuteSoloImpl(CreateRefCountingFunctor(a1, a2, a3, a4, a5), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) { return ThreadExecuteSoloImpl(CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) { return ThreadExecuteSoloImpl(CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7), pszName); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef(const char* pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) { return ThreadExecuteSoloImpl(CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7, a8), pszName); } + +inline bool IThreadPool::YieldWait(CThreadEvent& theEvent, unsigned timeout) +{ + CThreadEvent* pEvent = &theEvent; + return (YieldWait(&pEvent, 1, true, timeout) != TW_TIMEOUT); +} + +inline bool IThreadPool::YieldWait(CJob* pJob, unsigned timeout) +{ + return (YieldWait(&pJob, 1, true, timeout) != TW_TIMEOUT); +} + +inline JobStatus_t CJob::Execute() +{ + if (IsFinished()) + { + return m_status; + } + + AUTO_LOCK(m_mutex); + AddRef(); + + JobStatus_t result; + + switch (m_status) + { + case JOB_STATUS_UNSERVICED: + case JOB_STATUS_PENDING: + { + m_status = JOB_STATUS_INPROGRESS; + +#if defined( THREAD_PARENT_STACK_TRACE_ENABLED ) + { + CStackTop_ReferenceParentStack stackTop(m_ParentStackTrace, ARRAYSIZE(m_ParentStackTrace)); + result = m_status = DoExecute(); + } +#else + result = m_status = DoExecute(); +#endif + + DoCleanup(); + m_CompleteEvent.Set(); + break; + } + + case JOB_STATUS_INPROGRESS: + AssertMsg(0, "Mutex Should have protected use while processing"); + case JOB_OK: + case JOB_STATUS_ABORTED: + result = m_status; + break; + + default: + AssertMsg(m_status < JOB_OK, "Unknown job state"); + result = m_status; + } + + Release(); + + return result; +} + + +inline JobStatus_t CJob::TryExecute() +{ + if (!IsFinished() && TryLock()) + { + Execute(); + Unlock(); + } + return m_status; +} + +inline JobStatus_t CJob::Abort(bool bDiscard) +{ + if (IsFinished()) + { + return m_status; + } + + AUTO_LOCK(m_mutex); + AddRef(); + + JobStatus_t result; + + switch (m_status) + { + case JOB_STATUS_UNSERVICED: + case JOB_STATUS_PENDING: + { + result = m_status = DoAbort(bDiscard); + if (bDiscard) + DoCleanup(); + m_CompleteEvent.Set(); + } + break; + + case JOB_STATUS_ABORTED: + case JOB_STATUS_INPROGRESS: + case JOB_OK: + result = m_status; + break; + + default: + AssertMsg(m_status < JOB_OK, "Unknown job state"); + result = m_status; + } + + Release(); + + return result; +} + +#endif \ No newline at end of file diff --git a/SpyCustom/keyvalues.h b/SpyCustom/keyvalues.h new file mode 100644 index 0000000..ad5c2d2 --- /dev/null +++ b/SpyCustom/keyvalues.h @@ -0,0 +1,420 @@ +#ifndef KEYVALUES_H +#define KEYVALUES_H + +#ifdef _WIN32 +#pragma once +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#include "utlvector.h" +#include "color.h" +#include "exprevaluator.h" + +#define TRACK_KV_ADD( ptr, name ) track.AddKv( ptr, name ) +#define SPLIT_3_BYTES_INTO_1_AND_2( x1, x2, x3 ) do { x1 = (uint8)(x3); x2 = (uint16)( (x3) >> 8 ); } while( 0 ) + + +#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \ + for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() ) + +#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \ + for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() ) + +#define FOR_EACH_VALUE( kvRoot, kvValue ) \ + for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() ) + + +class IBaseFileSystem; +class CUtlBuffer; +class Color; +class CKeyValuesTokenReader; +class KeyValues; +class IKeyValuesDumpContext; +typedef void* FileHandle_t; +class CKeyValuesGrowableStringTable; + + +#define KV_BINARY_POOLED_FORMAT 0xAA + + +#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \ + for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() ) + +#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \ + for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() ) + +#define FOR_EACH_VALUE( kvRoot, kvValue ) \ + for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() ) + + +class KeyValues +{ + friend class CKeyValuesTokenReader; + +public: + static void SetUseGrowableStringTable(bool bUseGrowableTable); + + explicit KeyValues(const char* setName); + + class AutoDelete + { + public: + explicit inline AutoDelete(KeyValues* pKeyValues) : m_pKeyValues(pKeyValues) {} + explicit inline AutoDelete(const char* pchKVName) : m_pKeyValues(new KeyValues(pchKVName)) {} + inline ~AutoDelete(void) { delete m_pKeyValues; } + inline void Assign(KeyValues* pKeyValues) { m_pKeyValues = pKeyValues; } + inline KeyValues* Detach() { KeyValues* retval = m_pKeyValues; Assign(NULL); return retval; } + KeyValues* operator->() { return m_pKeyValues; } + operator KeyValues* () { return m_pKeyValues; } + private: + AutoDelete(AutoDelete const& x); + AutoDelete& operator= (AutoDelete const& x); + protected: + KeyValues* m_pKeyValues; + }; + + class AutoDeleteInline : public AutoDelete + { + public: + explicit inline AutoDeleteInline(KeyValues* pKeyValues) : AutoDelete(pKeyValues) {} + inline operator KeyValues* () const { return m_pKeyValues; } + inline KeyValues* Get() const { return m_pKeyValues; } + }; + + KeyValues(const char* setName, const char* firstKey, const char* firstValue); + KeyValues(const char* setName, const char* firstKey, const wchar_t* firstValue); + KeyValues(const char* setName, const char* firstKey, int firstValue); + KeyValues(const char* setName, const char* firstKey, const char* firstValue, const char* secondKey, const char* secondValue); + KeyValues(const char* setName, const char* firstKey, int firstValue, const char* secondKey, int secondValue); + + ~KeyValues(); + + const char* GetName() const; + void SetName(const char* setName); + + int GetNameSymbol() const; + int GetNameSymbolCaseSensitive() const; + + void UsesEscapeSequences(bool state); + bool LoadFromFile(IBaseFileSystem* filesystem, const char* resourceName, const char* pathID = NULL); + + bool SaveToFile(IBaseFileSystem* filesystem, const char* resourceName, const char* pathID = NULL, bool bWriteEmptySubkeys = false); + + bool LoadFromBuffer(char const* resourceName, const char* pBuffer, IBaseFileSystem* pFileSystem = NULL, const char* pPathID = NULL); + + bool LoadFromBuffer(char const* resourceName, CUtlBuffer& buf, IBaseFileSystem* pFileSystem = NULL, const char* pPathID = NULL); + + + + KeyValues* FindKey(const char* keyName, bool bCreate = false); + KeyValues* FindKey(int keySymbol) const; + KeyValues* CreateNewKey(); + void AddSubKey(KeyValues* pSubkey); + void RemoveSubKey(KeyValues* subKey); + void InsertSubKey(int nIndex, KeyValues* pSubKey); + bool ContainsSubKey(KeyValues* pSubKey); + void SwapSubKey(KeyValues* pExistingSubKey, KeyValues* pNewSubKey); + void ElideSubKey(KeyValues* pSubKey); + KeyValues* CreateKey(const char* keyName); + KeyValues* CreatePeerKey(const char* keyName); + + KeyValues* GetFirstSubKey() { return m_pSub; } + KeyValues* GetNextKey() { return m_pPeer; } + void SetNextKey(KeyValues* pDat); + + KeyValues* FindLastSubKey(); + + KeyValues* GetFirstTrueSubKey(); + KeyValues* GetNextTrueSubKey(); + + KeyValues* GetFirstValue(); + KeyValues* GetNextValue(); + + + int GetInt(const char* keyName = NULL, int defaultValue = 0); + uint64 GetUint64(const char* keyName = NULL, uint64 defaultValue = 0); + float GetFloat(const char* keyName = NULL, float defaultValue = 0.0f); + const char* GetString(const char* keyName = NULL, const char* defaultValue = ""); + const wchar_t* GetWString(const char* keyName = NULL, const wchar_t* defaultValue = L""); + void* GetPtr(const char* keyName = NULL, void* defaultValue = (void*)0); + Color GetColor(const char* keyName = NULL, const Color& defaultColor = Color(0, 0, 0, 0)); + bool GetBool(const char* keyName = NULL, bool defaultValue = false) { return GetInt(keyName, defaultValue ? 1 : 0) ? true : false; } + bool IsEmpty(const char* keyName = NULL); + + int GetInt(int keySymbol, int defaultValue = 0); + uint64 GetUint64(int keySymbol, uint64 defaultValue = 0); + float GetFloat(int keySymbol, float defaultValue = 0.0f); + const char* GetString(int keySymbol, const char* defaultValue = ""); + const wchar_t* GetWString(int keySymbol, const wchar_t* defaultValue = L""); + void* GetPtr(int keySymbol, void* defaultValue = (void*)0); + Color GetColor(int keySymbol ); + bool GetBool(int keySymbol, bool defaultValue = false) { return GetInt(keySymbol, defaultValue ? 1 : 0) ? true : false; } + bool IsEmpty(int keySymbol); + + void SetWString(const char* keyName, const wchar_t* value); + void SetString(const char* keyName, const char* value); + void SetInt(const char* keyName, int value); + void SetUint64(const char* keyName, uint64 value); + void SetFloat(const char* keyName, float value); + void SetPtr(const char* keyName, void* value); + void SetColor(const char* keyName, Color value); + void SetBool(const char* keyName, bool value) { SetInt(keyName, value ? 1 : 0); } + + void* operator new(size_t iAllocSize); + void* operator new(size_t iAllocSize, int nBlockUse, const char* pFileName, int nLine); + void operator delete(void* pMem); + void operator delete(void* pMem, int nBlockUse, const char* pFileName, int nLine); + + KeyValues& operator=(KeyValues& src); + + bool IsEqual(KeyValues* pRHS); + + void ChainKeyValue(KeyValues* pChain); + + void RecursiveSaveToFile(CUtlBuffer& buf, int indentLevel); + + bool WriteAsBinary(CUtlBuffer& buffer) const; + bool ReadAsBinary(CUtlBuffer& buffer, int nStackDepth = 0); + + bool WriteAsBinaryFiltered(CUtlBuffer& buffer); + bool ReadAsBinaryFiltered(CUtlBuffer& buffer, int nStackDepth = 0); + + KeyValues* MakeCopy(void) const; + + void CopySubkeys(KeyValues* pParent) const; + + void Clear(void); + + enum types_t + { + TYPE_NONE = 0, + TYPE_STRING, + TYPE_INT, + TYPE_FLOAT, + TYPE_PTR, + TYPE_WSTRING, + TYPE_COLOR, + TYPE_UINT64, + TYPE_COMPILED_INT_BYTE, + TYPE_COMPILED_INT_0, + TYPE_COMPILED_INT_1, + TYPE_NUMTYPES, + }; + types_t GetDataType(const char* keyName = NULL); + types_t GetDataType() const; + + void deleteThis(); + + void SetStringValue(char const* strValue); + + void UnpackIntoStructure(struct KeyValuesUnpackStructure const* pUnpackTable, void* pDest); + + bool ProcessResolutionKeys(const char* pResString); + + bool Dump(IKeyValuesDumpContext* pDump, int nIndentLevel = 0); + + enum MergeKeyValuesOp_t + { + MERGE_KV_ALL, + MERGE_KV_UPDATE, + MERGE_KV_DELETE, + MERGE_KV_BORROW, + }; + void MergeFrom(KeyValues* kvMerge, MergeKeyValuesOp_t eOp = MERGE_KV_ALL); + + static KeyValues* FromString(char const* szName, char const* szStringVal, char const** ppEndOfParse = NULL); + + KeyValues* CreateKeyUsingKnownLastChild(const char* keyName, KeyValues* pLastChild); + void AddSubkeyUsingKnownLastChild(KeyValues* pSubKey, KeyValues* pLastChild); + + KeyValues(KeyValues&); + + + void RecursiveCopyKeyValues(KeyValues& src); + void RemoveEverything(); + void RecursiveSaveToFile(IBaseFileSystem* filesystem, FileHandle_t f, CUtlBuffer* pBuf, int indentLevel, bool bWriteEmptySubkeys = false); + void WriteConvertedString(IBaseFileSystem* filesystem, FileHandle_t f, CUtlBuffer* pBuf, const char* pszString); + + void RecursiveLoadFromBuffer(char const* resourceName, CUtlBuffer& buf); + + void AppendIncludedKeys(CUtlVector< KeyValues* >& includedKeys); + void ParseIncludedKeys(char const* resourceName, const char* filetoinclude, + IBaseFileSystem* pFileSystem, const char* pPathID, CUtlVector< KeyValues* >& includedKeys); + + void MergeBaseKeys(CUtlVector< KeyValues* >& baseKeys); + void RecursiveMergeKeyValues(KeyValues* baseKV); + + void InternalWrite(IBaseFileSystem* filesystem, FileHandle_t f, CUtlBuffer* pBuf, const void* pData, int len); + + void Init(); + const char* ReadToken(CUtlBuffer& buf, bool& wasQuoted, bool& wasConditional); + void WriteIndents(IBaseFileSystem* filesystem, FileHandle_t f, CUtlBuffer* pBuf, int indentLevel); + + void FreeAllocatedValue(); + void AllocateValueBlock(int size); + + bool ReadAsBinaryPooledFormat(CUtlBuffer& buf, IBaseFileSystem* pFileSystem, unsigned int poolKey, GetSymbolProc_t pfnEvaluateSymbolProc); + + bool EvaluateConditional(const char* str); + + uint32 m_iKeyName : 24; + uint32 m_iKeyNameCaseSensitive1 : 8; + + char* m_sValue; + wchar_t* m_wsValue; + + union + { + int m_iValue; + float m_flValue; + void* m_pValue; + unsigned char m_Color[4]; + }; + + char m_iDataType; + char m_bHasEscapeSequences; + uint16 m_iKeyNameCaseSensitive2; + + KeyValues* m_pPeer; + KeyValues* m_pSub; + KeyValues* m_pChain; + + GetSymbolProc_t m_pExpressionGetSymbolProc; + +private: + static int (*s_pfGetSymbolForString)(const char* name, bool bCreate); + static const char* (*s_pfGetStringForSymbol)(int symbol); + static CKeyValuesGrowableStringTable* s_pGrowableStringTable; + +public: + static int GetSymbolForStringClassic(const char* name, bool bCreate = true); + static const char* GetStringForSymbolClassic(int symbol); + + static int GetSymbolForStringGrowable(const char* name, bool bCreate = true); + static const char* GetStringForSymbolGrowable(int symbol); +}; + +typedef KeyValues::AutoDelete KeyValuesAD; + +enum KeyValuesUnpackDestinationTypes_t +{ + UNPACK_TYPE_FLOAT, + UNPACK_TYPE_VECTOR, + UNPACK_TYPE_VECTOR_COLOR, + UNPACK_TYPE_STRING, + UNPACK_TYPE_INT, + UNPACK_TYPE_FOUR_FLOATS, + UNPACK_TYPE_TWO_FLOATS, +}; + +#define UNPACK_FIXED( kname, kdefault, dtype, ofs ) { kname, kdefault, dtype, ofs, 0 } +#define UNPACK_VARIABLE( kname, kdefault, dtype, ofs, sz ) { kname, kdefault, dtype, ofs, sz } +#define UNPACK_END_MARKER { NULL, NULL, UNPACK_TYPE_FLOAT, 0 } + +struct KeyValuesUnpackStructure +{ + char const* m_pKeyName; + char const* m_pKeyDefault; + KeyValuesUnpackDestinationTypes_t m_eDataType; + size_t m_nFieldOffset; + size_t m_nFieldSize; +}; + +inline int KeyValues::GetInt(int keySymbol, int defaultValue) +{ + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->GetInt((const char*)NULL, defaultValue) : defaultValue; +} + +inline uint64 KeyValues::GetUint64(int keySymbol, uint64 defaultValue) +{ + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->GetUint64((const char*)NULL, defaultValue) : defaultValue; +} + +inline float KeyValues::GetFloat(int keySymbol, float defaultValue) +{ + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->GetFloat((const char*)NULL, defaultValue) : defaultValue; +} + +inline const char* KeyValues::GetString(int keySymbol, const char* defaultValue) +{ + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->GetString((const char*)NULL, defaultValue) : defaultValue; +} + +inline const wchar_t* KeyValues::GetWString(int keySymbol, const wchar_t* defaultValue) +{ + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->GetWString((const char*)NULL, defaultValue) : defaultValue; +} + +inline void* KeyValues::GetPtr(int keySymbol, void* defaultValue) +{ + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->GetPtr((const char*)NULL, defaultValue) : defaultValue; +} + +inline Color KeyValues::GetColor(int keySymbol) +{ + Color defaultValue(0, 0, 0, 0); + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->GetColor() : defaultValue; +} + +inline bool KeyValues::IsEmpty(int keySymbol) +{ + KeyValues* dat = FindKey(keySymbol); + return dat ? dat->IsEmpty() : true; +} + + +class IKeyValuesDumpContext +{ +public: + virtual bool KvBeginKey(KeyValues* pKey, int nIndentLevel) = 0; + virtual bool KvWriteValue(KeyValues* pValue, int nIndentLevel) = 0; + virtual bool KvEndKey(KeyValues* pKey, int nIndentLevel) = 0; +}; + +class IKeyValuesDumpContextAsText : public IKeyValuesDumpContext +{ +public: + virtual bool KvBeginKey(KeyValues* pKey, int nIndentLevel); + virtual bool KvWriteValue(KeyValues* pValue, int nIndentLevel); + virtual bool KvEndKey(KeyValues* pKey, int nIndentLevel); + +public: + virtual bool KvWriteIndent(int nIndentLevel); + virtual bool KvWriteText(char const* szText) = 0; +}; + +class CKeyValuesDumpContextAsDevMsg : public IKeyValuesDumpContextAsText +{ +public: + CKeyValuesDumpContextAsDevMsg(int nDeveloperLevel = 1) : m_nDeveloperLevel(nDeveloperLevel) {} + +public: + virtual bool KvBeginKey(KeyValues* pKey, int nIndentLevel); + virtual bool KvWriteText(char const* szText); + +protected: + int m_nDeveloperLevel; +}; + +inline bool KeyValuesDumpAsDevMsg(KeyValues* pKeyValues, int nIndentLevel = 0, int nDeveloperLevel = 1) +{ + CKeyValuesDumpContextAsDevMsg ctx(nDeveloperLevel); + return pKeyValues->Dump(&ctx, nIndentLevel); +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/l2cache.h b/SpyCustom/l2cache.h new file mode 100644 index 0000000..8e9d523 --- /dev/null +++ b/SpyCustom/l2cache.h @@ -0,0 +1,38 @@ +#ifndef CL2CACHE_H +#define CL2CACHE_H +#ifdef _WIN32 +#pragma once +#endif + +class P4Event_BSQ_cache_reference; + +class CL2Cache +{ +public: + + CL2Cache(); + ~CL2Cache(); + + void Start(void); + void End(void); + + int GetL2CacheMisses(void) + { + return m_iL2CacheMissCount; + } + +#ifdef DBGFLAG_VALIDATE + void Validate(CValidator& validator, tchar* pchName); +#endif + +private: + + int m_nID; + + P4Event_BSQ_cache_reference* m_pL2CacheEvent; + int64 m_i64Start; + int64 m_i64End; + int m_iL2CacheMissCount; +}; + +#endif diff --git a/SpyCustom/lerp_functions.h b/SpyCustom/lerp_functions.h new file mode 100644 index 0000000..659df5d --- /dev/null +++ b/SpyCustom/lerp_functions.h @@ -0,0 +1,157 @@ +#ifndef LERP_FUNCTIONS_H +#define LERP_FUNCTIONS_H +#ifdef _WIN32 +#pragma once +#endif + + +template +inline T LoopingLerp(float flPercent, T flFrom, T flTo) +{ + T s = flTo * flPercent + flFrom * (1.0f - flPercent); + return s; +} + +template <> +inline float LoopingLerp(float flPercent, float flFrom, float flTo) +{ + if (fabs(flTo - flFrom) >= 0.5f) + { + if (flFrom < flTo) + flFrom += 1.0f; + else + flTo += 1.0f; + } + + float s = flTo * flPercent + flFrom * (1.0f - flPercent); + + s = s - (int)(s); + if (s < 0.0f) + s = s + 1.0f; + + return s; +} + +template +inline T Lerp_Hermite(const T& , float t, const T& p0, const T& p1, const T& p2) +{ + T d1 = p1 - p0; + T d2 = p2 - p1; + + T output; + float tSqr = t * t; + float tCube = t * tSqr; + + output = p1 * (2 * tCube - 3 * tSqr + 1); + output += p2 * (-2 * tCube + 3 * tSqr); + output += d1 * (tCube - 2 * tSqr + t); + output += d2 * (tCube - tSqr); + + return output; +} + + +template +inline T Derivative_Hermite(float t, const T& p0, const T& p1, const T& p2) +{ + T d1 = p1 - p0; + T d2 = p2 - p1; + + T output; + float tSqr = t * t; + + output = p1 * (6 * tSqr - 6 * t); + output += p2 * (-6 * tSqr + 6 * t); + output += d1 * (3 * tSqr - 4 * t + 1); + output += d2 * (3 * tSqr - 2 * t); + + return output; +} + + +inline void Lerp_Clamp(int val) +{ +} + +inline void Lerp_Clamp(float val) +{ +} + +inline void Lerp_Clamp(const Vector& val) +{ +} + +inline void Lerp_Clamp(const QAngle& val) +{ +} + + +template< class T, int minValue, int maxValue, int startValue > +inline void Lerp_Clamp(CRangeCheckedVar& val) +{ + val.Clamp(); +} + + +template<> +inline QAngle Lerp_Hermite(const QAngle&, float t, const QAngle& p0, const QAngle& p1, const QAngle& p2) +{ + return Lerp(t, p1, p2); +} + +template +inline T LoopingLerp_Hermite(T current, float t, T p0, T p1, T p2) +{ + return Lerp_Hermite(current, t, p0, p1, p2); +} + +template <> +inline float LoopingLerp_Hermite(float , float t, float p0, float p1, float p2) +{ + if (fabs(p1 - p0) > 0.5f) + { + if (p0 < p1) + p0 += 1.0f; + else + p1 += 1.0f; + } + + if (fabs(p2 - p1) > 0.5f) + { + if (p1 < p2) + { + p1 += 1.0f; + + if (abs(p1 - p0) > 0.5) + { + if (p0 < p1) + p0 += 1.0f; + else + p1 += 1.0f; + } + } + else + { + p2 += 1.0f; + } + } + + float s = Lerp_Hermite( 0.0f, t, p0, p1, p2); + + s = s - (int)(s); + if (s < 0.0f) + { + s = s + 1.0f; + } + + return s; +} + +template< int minValue, int maxValue, int startValue > +inline CRangeCheckedVar LoopingLerp_Hermite(CRangeCheckedVar current, float t, CRangeCheckedVar p0, CRangeCheckedVar p1, CRangeCheckedVar p2) +{ + return LoopingLerp_Hermite((float)current, t, (float)p0, (float)p1, (float)p2); +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/lightdesc.h b/SpyCustom/lightdesc.h new file mode 100644 index 0000000..d896a31 --- /dev/null +++ b/SpyCustom/lightdesc.h @@ -0,0 +1,139 @@ +#ifndef LIGHTDESC_H +#define LIGHTDESC_H + +#include "ssemath.h" +#include "vector.h" + +enum LightType_t +{ + MATERIAL_LIGHT_DISABLE = 0, + MATERIAL_LIGHT_POINT, + MATERIAL_LIGHT_DIRECTIONAL, + MATERIAL_LIGHT_SPOT, +}; + +enum LightType_OptimizationFlags_t +{ + LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 = 1, + LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 = 2, + LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 = 4, + LIGHTTYPE_OPTIMIZATIONFLAGS_DERIVED_VALUES_CALCED = 8, +}; + +struct LightDesc_t +{ + LightType_t m_Type; + Vector m_Color; + Vector m_Position; + Vector m_Direction; + float m_Range; + float m_Falloff; + float m_Attenuation0; + float m_Attenuation1; + float m_Attenuation2; + float m_Theta; + float m_Phi; + + float m_ThetaDot; + float m_PhiDot; + unsigned int m_Flags; +protected: + float OneOver_ThetaDot_Minus_PhiDot; + float m_RangeSquared; +public: + + void RecalculateDerivedValues(void); + + LightDesc_t(void) + { + } + + LightDesc_t(const Vector& pos, const Vector& color) + { + InitPoint(pos, color); + } + + LightDesc_t(const Vector& pos, const Vector& color, const Vector& point_at, + float inner_cone_boundary, float outer_cone_boundary) + { + InitSpot(pos, color, point_at, inner_cone_boundary, outer_cone_boundary); + } + + void InitPoint(const Vector& pos, const Vector& color); + void InitDirectional(const Vector& dir, const Vector& color); + void InitSpot(const Vector& pos, const Vector& color, const Vector& point_at, + float inner_cone_boundary, float outer_cone_boundary); + + void ComputeLightAtPoints(const FourVectors& pos, const FourVectors& normal, + FourVectors& color, bool DoHalfLambert = false) const; + void ComputeNonincidenceLightAtPoints(const FourVectors& pos, FourVectors& color) const; + void ComputeLightAtPointsForDirectional(const FourVectors& pos, + const FourVectors& normal, + FourVectors& color, bool DoHalfLambert = false) const; + + void SetupOldStyleAttenuation(float fQuadatricAttn, float fLinearAttn, float fConstantAttn); + + void SetupNewStyleAttenuation(float fFiftyPercentDistance, float fZeroPercentDistance); + + + bool IsDirectionWithinLightCone(const Vector& rdir) const + { + return ((m_Type != MATERIAL_LIGHT_SPOT) || (rdir.Dot(m_Direction) >= m_PhiDot)); + } + + float OneOverThetaDotMinusPhiDot() const + { + return OneOver_ThetaDot_Minus_PhiDot; + } +}; + + +inline void LightDesc_t::InitPoint(const Vector& pos, const Vector& color) +{ + m_Type = MATERIAL_LIGHT_POINT; + m_Color = color; + m_Position = pos; + m_Range = 0.0; + m_Attenuation0 = 1.0; + m_Attenuation1 = 0; + m_Attenuation2 = 0; + RecalculateDerivedValues(); +} + + +inline void LightDesc_t::InitDirectional(const Vector& dir, const Vector& color) +{ + m_Type = MATERIAL_LIGHT_DIRECTIONAL; + m_Color = color; + m_Direction = dir; + m_Range = 0.0; + m_Attenuation0 = 1.0; + m_Attenuation1 = 0; + m_Attenuation2 = 0; + RecalculateDerivedValues(); +} + + +inline void LightDesc_t::InitSpot(const Vector& pos, const Vector& color, const Vector& point_at, + float inner_cone_boundary, float outer_cone_boundary) +{ + m_Type = MATERIAL_LIGHT_SPOT; + m_Color = color; + m_Position = pos; + m_Direction = point_at; + m_Direction -= pos; + VectorNormalizeFast(m_Direction); + m_Falloff = 5.0; + m_Theta = inner_cone_boundary; + m_Phi = outer_cone_boundary; + + m_Range = 0.0; + + m_Attenuation0 = 1.0; + m_Attenuation1 = 0; + m_Attenuation2 = 0; + RecalculateDerivedValues(); +} + + +#endif diff --git a/SpyCustom/localflexcontroller.h b/SpyCustom/localflexcontroller.h new file mode 100644 index 0000000..60f2c36 --- /dev/null +++ b/SpyCustom/localflexcontroller.h @@ -0,0 +1,21 @@ +#ifndef LOCALFLEXCONTROLLER_H +#define LOCALFLEXCONTROLLER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "platform.h" + +enum LocalFlexController_t +{ + DUMMY_FLEX_CONTROLLER = 0x7fffffff +}; + +inline LocalFlexController_t& operator++(LocalFlexController_t& a) { return a = LocalFlexController_t(int(a) + 1); } +inline LocalFlexController_t& operator--(LocalFlexController_t& a) { return a = LocalFlexController_t(int(a) - 1); } +inline LocalFlexController_t operator++(LocalFlexController_t& a, int) { LocalFlexController_t t = a; a = LocalFlexController_t(int(a) + 1); return t; } +inline LocalFlexController_t operator--(LocalFlexController_t& a, int) { LocalFlexController_t t = a; a = LocalFlexController_t(int(a) - 1); return t; } + + +#endif \ No newline at end of file diff --git a/SpyCustom/logging.h b/SpyCustom/logging.h new file mode 100644 index 0000000..a9fdfab --- /dev/null +++ b/SpyCustom/logging.h @@ -0,0 +1,421 @@ +#ifndef LOGGING_H +#define LOGGING_H + +#if !defined(__SPU__) + +#if defined( COMPILER_MSVC ) +#pragma once +#endif + +#include "color.h" +#include "icommandline.h" +#include + +#if defined( _X360 ) +#include "xbox/xbox_console.h" +#endif + +#if defined( _WIN32 ) || (defined(POSIX) && !defined(_GAMECONSOLE)) +#include "win32consoleio.h" +#endif + +class CLoggingSystem; +class CThreadFastMutex; + +const int MAX_LOGGING_MESSAGE_LENGTH = 2048; + +const int MAX_LOGGING_IDENTIFIER_LENGTH = 32; + +const int MAX_LOGGING_CHANNEL_COUNT = 256; + +const int MAX_LOGGING_TAG_COUNT = 1024; + +const int MAX_LOGGING_TAG_CHARACTER_COUNT = 8192; + +const int MAX_LOGGING_LISTENER_COUNT = 16; + +const Color UNSPECIFIED_LOGGING_COLOR(0, 0, 0, 0); + +typedef int LoggingChannelID_t; + +const LoggingChannelID_t INVALID_LOGGING_CHANNEL_ID = -1; + +enum LoggingSeverity_t +{ + LS_MESSAGE = 0, + + LS_WARNING = 1, + + LS_ASSERT = 2, + + LS_ERROR = 3, + + LS_HIGHEST_SEVERITY = 4, +}; + +enum LoggingResponse_t +{ + LR_CONTINUE, + LR_DEBUGGER, + LR_ABORT, +}; + +enum LoggingChannelFlags_t +{ + LCF_CONSOLE_ONLY = 0x00000001, + + LCF_DO_NOT_ECHO = 0x00000002, +}; + +typedef void (*RegisterTagsFunc)(); + +struct LoggingContext_t +{ + LoggingChannelID_t m_ChannelID; + LoggingChannelFlags_t m_Flags; + LoggingSeverity_t m_Severity; + Color m_Color; +}; + +class ILoggingListener +{ +public: + virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage) = 0; +}; + +class ILoggingResponsePolicy +{ +public: + virtual LoggingResponse_t OnLog(const LoggingContext_t* pContext) = 0; +}; + +class CSimpleLoggingListener : public ILoggingListener +{ +public: + CSimpleLoggingListener(bool bQuietPrintf = false, bool bQuietDebugger = false) : + m_bQuietPrintf(bQuietPrintf), + m_bQuietDebugger(bQuietDebugger) + { + } + + virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage) + { +#ifdef _X360 + if (!m_bQuietDebugger && XBX_IsConsoleConnected()) + { + XBX_DebugString(XMAKECOLOR(0, 0, 0), pMessage); + } + else +#endif + { +#if !defined( _CERT ) && !defined( DBGFLAG_STRINGS_STRIP ) + if (!m_bQuietPrintf) + { + _tprintf(_T("%s"), pMessage); + } +#endif + +#ifdef _WIN32 + if (!m_bQuietDebugger && Plat_IsInDebugSession()) + { + Plat_DebugString(pMessage); + } +#endif + } + } + + bool m_bQuietPrintf; + bool m_bQuietDebugger; +}; + +class CSimpleWindowsLoggingListener : public ILoggingListener +{ +public: + virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage) + { + if (Plat_IsInDebugSession()) + { + Plat_DebugString(pMessage); + } + if (pContext->m_Severity == LS_ERROR) + { + if (Plat_IsInDebugSession()) + DebuggerBreak(); + + Plat_MessageBox("Error", pMessage); + } + } +}; + + +#if !defined(_GAMECONSOLE) +class CColorizedLoggingListener : public CSimpleLoggingListener +{ +public: + CColorizedLoggingListener(bool bQuietPrintf = false, bool bQuietDebugger = false) : CSimpleLoggingListener(bQuietPrintf, bQuietDebugger) + { + InitWin32ConsoleColorContext(&m_ColorContext); + } + + virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage) + { + if (!m_bQuietPrintf) + { + int nPrevColor = -1; + + if (pContext->m_Color != UNSPECIFIED_LOGGING_COLOR) + { + nPrevColor = SetWin32ConsoleColor(&m_ColorContext, + pContext->m_Color.r(), pContext->m_Color.g(), pContext->m_Color.b(), + MAX(MAX(pContext->m_Color.r(), pContext->m_Color.g()), pContext->m_Color.b()) > 128); + } + + _tprintf(_T("%s"), pMessage); + + if (nPrevColor >= 0) + { + RestoreWin32ConsoleColor(&m_ColorContext, nPrevColor); + } + } + +#ifdef _WIN32 + if (!m_bQuietDebugger && Plat_IsInDebugSession()) + { + Plat_DebugString(pMessage); + } +#endif + } + + Win32ConsoleColorContext_t m_ColorContext; +}; +#endif + + +class CDefaultLoggingResponsePolicy : public ILoggingResponsePolicy +{ +public: + virtual LoggingResponse_t OnLog(const LoggingContext_t* pContext) + { + if (pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm("-noassert")) + { + return LR_DEBUGGER; + } + else if (pContext->m_Severity == LS_ERROR) + { + return LR_ABORT; + } + else + { + return LR_CONTINUE; + } + } +}; + +class CNonFatalLoggingResponsePolicy : public ILoggingResponsePolicy +{ +public: + virtual LoggingResponse_t OnLog(const LoggingContext_t* pContext) + { + if ((pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm("-noassert")) || pContext->m_Severity == LS_ERROR) + { + return LR_DEBUGGER; + } + else + { + return LR_CONTINUE; + } + } +}; + +class CLoggingSystem +{ +public: + struct LoggingChannel_t; + + CLoggingSystem(); + ~CLoggingSystem(); + + LoggingChannelID_t RegisterLoggingChannel(const char* pChannelName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t minimumSeverity = LS_MESSAGE, Color spewColor = UNSPECIFIED_LOGGING_COLOR); + + LoggingChannelID_t FindChannel(const char* pChannelName) const; + + int GetChannelCount() const { return m_nChannelCount; } + + LoggingChannel_t* GetChannel(LoggingChannelID_t channelID); + const LoggingChannel_t* GetChannel(LoggingChannelID_t channelID) const; + + bool HasTag(LoggingChannelID_t channelID, const char* pTag) const { return GetChannel(channelID)->HasTag(pTag); } + + bool IsValidChannelID(LoggingChannelID_t channelID) const { return (channelID >= 0) && (channelID < m_nChannelCount); } + + bool IsChannelEnabled(LoggingChannelID_t channelID, LoggingSeverity_t severity) const { return IsValidChannelID(channelID) && GetChannel(channelID)->IsEnabled(severity); } + + void SetChannelSpewLevel(LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity); + void SetChannelSpewLevelByName(const char* pName, LoggingSeverity_t minimumSeverity); + void SetChannelSpewLevelByTag(const char* pTag, LoggingSeverity_t minimumSeverity); + void SetGlobalSpewLevel(LoggingSeverity_t minimumSeverity); + + Color GetChannelColor(LoggingChannelID_t channelID) const { return GetChannel(channelID)->m_SpewColor; } + void SetChannelColor(LoggingChannelID_t channelID, Color color) { GetChannel(channelID)->m_SpewColor = color; } + + LoggingChannelFlags_t GetChannelFlags(LoggingChannelID_t channelID) const { return GetChannel(channelID)->m_Flags; } + void SetChannelFlags(LoggingChannelID_t channelID, LoggingChannelFlags_t flags) { GetChannel(channelID)->m_Flags = flags; } + + void AddTagToCurrentChannel(const char* pTagName); + + void PushLoggingState(bool bThreadLocal = false, bool bClearState = true); + void PopLoggingState(bool bThreadLocal = false); + + void RegisterLoggingListener(ILoggingListener* pListener); + + bool IsListenerRegistered(ILoggingListener* pListener); + + void ResetCurrentLoggingState(); + + void SetLoggingResponsePolicy(ILoggingResponsePolicy* pLoggingResponse); + + LoggingResponse_t LogDirect(LoggingChannelID_t channelID, LoggingSeverity_t severity, Color color, const tchar* pMessage); + + struct LoggingTag_t + { + const char* m_pTagName; + LoggingTag_t* m_pNextTag; + }; + + struct LoggingChannel_t + { + bool HasTag(const char* pTag) const + { + LoggingTag_t* pCurrentTag = m_pFirstTag; + while (pCurrentTag != NULL) + { + if (stricmp(pCurrentTag->m_pTagName, pTag) == 0) + { + return true; + } + pCurrentTag = pCurrentTag->m_pNextTag; + } + return false; + } + bool IsEnabled(LoggingSeverity_t severity) const { return severity >= m_MinimumSeverity; } + void SetSpewLevel(LoggingSeverity_t severity) { m_MinimumSeverity = severity; } + + LoggingChannelID_t m_ID; + LoggingChannelFlags_t m_Flags; + LoggingSeverity_t m_MinimumSeverity; + Color m_SpewColor; + char m_Name[MAX_LOGGING_IDENTIFIER_LENGTH]; + LoggingTag_t* m_pFirstTag; + }; + +private: + struct LoggingState_t + { + int m_nPreviousStackEntry; + + int m_nListenerCount; + ILoggingListener* m_RegisteredListeners[MAX_LOGGING_LISTENER_COUNT]; + + ILoggingResponsePolicy* m_pLoggingResponse; + }; + + LoggingState_t* GetCurrentState(); + const LoggingState_t* GetCurrentState() const; + + int FindUnusedStateIndex(); + LoggingTag_t* AllocTag(const char* pTagName); + + int m_nChannelCount; + LoggingChannel_t m_RegisteredChannels[MAX_LOGGING_CHANNEL_COUNT]; + + int m_nChannelTagCount; + LoggingTag_t m_ChannelTags[MAX_LOGGING_TAG_COUNT]; + + int m_nTagNamePoolIndex; + char m_TagNamePool[MAX_LOGGING_TAG_CHARACTER_COUNT]; + + CThreadFastMutex* m_pStateMutex; + + int m_nGlobalStateIndex; + + static const int MAX_LOGGING_STATE_COUNT = 16; + LoggingState_t m_LoggingStates[MAX_LOGGING_STATE_COUNT]; + + CDefaultLoggingResponsePolicy m_DefaultLoggingResponse; + + CSimpleLoggingListener m_DefaultLoggingListener; + +}; + +#ifdef DBGFLAG_STRINGS_STRIP +#define InternalMsg( Channel, Severity, ... ) do { if ( Severity == LS_ERROR && LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, ##__VA_ARGS__ ); } while( 0 ) +#else +#define InternalMsg( Channel, Severity, ... ) do { if ( LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, ##__VA_ARGS__ ); } while( 0 ) +#endif + +#define Log_Msg( Channel, ... ) InternalMsg( Channel, LS_MESSAGE, ##__VA_ARGS__ ) +#define Log_Warning( Channel, ... ) InternalMsg( Channel, LS_WARNING, ##__VA_ARGS__ ) +#define Log_Error( Channel, ... ) InternalMsg( Channel, LS_ERROR, ##__VA_ARGS__ ) +#ifdef DBGFLAG_STRINGS_STRIP +#define Log_Assert( ... ) LR_CONTINUE +#else +#define Log_Assert( Message, ... ) LoggingSystem_LogAssert( Message, ##__VA_ARGS__ ) +#endif + + +#define DECLARE_LOGGING_CHANNEL( Channel ) extern LoggingChannelID_t Channel + +#define DEFINE_LOGGING_CHANNEL_NO_TAGS( Channel, ChannelName, ... ) \ + LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, NULL, ##__VA_ARGS__ ) + +#define BEGIN_DEFINE_LOGGING_CHANNEL( Channel, ChannelName, ... ) \ + static void Register_##Channel##_Tags(); \ + LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, Register_##Channel##_Tags, ##__VA_ARGS__ ); \ + void Register_##Channel##_Tags() \ + { + +#define ADD_LOGGING_CHANNEL_TAG( Tag ) LoggingSystem_AddTagToCurrentChannel( Tag ) + +#define END_DEFINE_LOGGING_CHANNEL() \ + } + +PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_RegisterLoggingChannel(const char* pName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t severity = LS_MESSAGE, Color color = UNSPECIFIED_LOGGING_COLOR); + +PLATFORM_INTERFACE void LoggingSystem_RegisterLoggingListener(ILoggingListener* pListener); +PLATFORM_INTERFACE void LoggingSystem_UnregisterLoggingListener(ILoggingListener* pListener); +PLATFORM_INTERFACE void LoggingSystem_ResetCurrentLoggingState(); +PLATFORM_INTERFACE void LoggingSystem_SetLoggingResponsePolicy(ILoggingResponsePolicy* pResponsePolicy); +PLATFORM_INTERFACE void LoggingSystem_PushLoggingState(bool bThreadLocal = false, bool bClearState = true); +PLATFORM_INTERFACE void LoggingSystem_PopLoggingState(bool bThreadLocal = false); + +PLATFORM_INTERFACE void LoggingSystem_AddTagToCurrentChannel(const char* pTagName); + +PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_FindChannel(const char* pChannelName); +PLATFORM_INTERFACE int LoggingSystem_GetChannelCount(); +PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetFirstChannelID(); +PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetNextChannelID(LoggingChannelID_t channelID); +PLATFORM_INTERFACE const CLoggingSystem::LoggingChannel_t* LoggingSystem_GetChannel(LoggingChannelID_t channelID); + +PLATFORM_INTERFACE bool LoggingSystem_HasTag(LoggingChannelID_t channelID, const char* pTag); + +PLATFORM_INTERFACE bool LoggingSystem_IsChannelEnabled(LoggingChannelID_t channelID, LoggingSeverity_t severity); +PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevel(LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity); +PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByName(const char* pName, LoggingSeverity_t minimumSeverity); +PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByTag(const char* pTag, LoggingSeverity_t minimumSeverity); +PLATFORM_INTERFACE void LoggingSystem_SetGlobalSpewLevel(LoggingSeverity_t minimumSeverity); + +PLATFORM_INTERFACE int32 LoggingSystem_GetChannelColor(LoggingChannelID_t channelID); +PLATFORM_INTERFACE void LoggingSystem_SetChannelColor(LoggingChannelID_t channelID, int color); + +PLATFORM_INTERFACE LoggingChannelFlags_t LoggingSystem_GetChannelFlags(LoggingChannelID_t channelID); +PLATFORM_INTERFACE void LoggingSystem_SetChannelFlags(LoggingChannelID_t channelID, LoggingChannelFlags_t flags); + +PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_Log(LoggingChannelID_t channelID, LoggingSeverity_t severity, PRINTF_FORMAT_STRING const char* pMessageFormat, ...) FMTFUNCTION(3, 4); +PLATFORM_OVERLOAD LoggingResponse_t LoggingSystem_Log(LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, PRINTF_FORMAT_STRING const char* pMessageFormat, ...) FMTFUNCTION(4, 5); + +PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogDirect(LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char* pMessage); +PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogAssert(PRINTF_FORMAT_STRING const char* pMessageFormat, ...) FMTFUNCTION(1, 2); + +#endif + +#endif \ No newline at end of file diff --git a/SpyCustom/math_pfns.h b/SpyCustom/math_pfns.h new file mode 100644 index 0000000..52292fe --- /dev/null +++ b/SpyCustom/math_pfns.h @@ -0,0 +1,66 @@ +#ifndef _MATH_PFNS_H_ +#define _MATH_PFNS_H_ + +#if defined( _X360 ) +#include +#endif + +#if !defined( _X360 ) + +extern float (*pfSqrt)(float x); +extern float (*pfRSqrt)(float x); +extern float (*pfRSqrtFast)(float x); +extern void (*pfFastSinCos)(float x, float* s, float* c); +extern float (*pfFastCos)(float x); + +#define FastSqrt(x) (*pfSqrt)(x) +#define FastRSqrt(x) (*pfRSqrt)(x) +#define FastRSqrtFast(x) (*pfRSqrtFast)(x) +#define FastSinCos(x,s,c) (*pfFastSinCos)(x,s,c) +#define FastCos(x) (*pfFastCos)(x) + +#if defined(__i386__) || defined(_M_IX86) +#undef FastSqrt +#define FastSqrt(x) ::sqrtf(x) +#endif + +#endif + +#if defined( _X360 ) + +FORCEINLINE float _VMX_Sqrt(float x) +{ + return __fsqrts(x); +} + +FORCEINLINE float _VMX_RSqrt(float x) +{ + float rroot = __frsqrte(x); + + return (0.5f * rroot) * (3.0f - (x * rroot) * rroot); +} + +FORCEINLINE float _VMX_RSqrtFast(float x) +{ + return __frsqrte(x); +} + +FORCEINLINE void _VMX_SinCos(float a, float* pS, float* pC) +{ + XMScalarSinCos(pS, pC, a); +} + +FORCEINLINE float _VMX_Cos(float a) +{ + return XMScalarCos(a); +} + +#define FastSqrt(x) _VMX_Sqrt(x) +#define FastRSqrt(x) _VMX_RSqrt(x) +#define FastRSqrtFast(x) _VMX_RSqrtFast(x) +#define FastSinCos(x,s,c) _VMX_SinCos(x,s,c) +#define FastCos(x) _VMX_Cos(x) + +#endif + +#endif \ No newline at end of file diff --git a/SpyCustom/mathlib.h b/SpyCustom/mathlib.h new file mode 100644 index 0000000..9f32d71 --- /dev/null +++ b/SpyCustom/mathlib.h @@ -0,0 +1,1785 @@ +#ifndef MATH_LIB_H +#define MATH_LIB_H + +#include +#include "basetypes.h" +#include "commonmacros.h" +#include "vector.h" +#include "vector2d.h" +#include "dbg.h" + +#include "math_pfns.h" + +#if defined(__i386__) || defined(_M_IX86) +#include +#endif + +#undef clamp + + +#ifdef FP_EXCEPTIONS_ENABLED +#include +#endif + +class FPExceptionDisabler +{ +public: +#ifdef FP_EXCEPTIONS_ENABLED + FPExceptionDisabler(); + ~FPExceptionDisabler(); + +private: + unsigned int mOldValues; +#else + FPExceptionDisabler() {} + ~FPExceptionDisabler() {} +#endif + +private: + FPExceptionDisabler(const FPExceptionDisabler&); + FPExceptionDisabler& operator=(const FPExceptionDisabler&); +}; + +class FPExceptionEnabler +{ +public: +#ifdef FP_EXCEPTIONS_ENABLED + FPExceptionEnabler(unsigned int enableBits = _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + ~FPExceptionEnabler(); + +private: + unsigned int mOldValues; +#else + FPExceptionEnabler(unsigned int enableBits = 0) + { + } + ~FPExceptionEnabler() + { + } +#endif + +private: + FPExceptionEnabler(const FPExceptionEnabler&); + FPExceptionEnabler& operator=(const FPExceptionEnabler&); +}; + + + +#ifdef DEBUG +FORCEINLINE float clamp(float val, float minVal, float maxVal) +{ + if (maxVal < minVal) + return maxVal; + else if (val < minVal) + return minVal; + else if (val > maxVal) + return maxVal; + else + return val; +} +#else +FORCEINLINE float clamp(float val, float minVal, float maxVal) +{ +#if defined(__i386__) || defined(_M_IX86) + _mm_store_ss(&val, + _mm_min_ss( + _mm_max_ss( + _mm_load_ss(&val), + _mm_load_ss(&minVal)), + _mm_load_ss(&maxVal))); +#else + val = fpmax(minVal, val); + val = fpmin(maxVal, val); +#endif + return val; +} +#endif + +template< class T > +inline T clamp(T const& val, T const& minVal, T const& maxVal) +{ + if (maxVal < minVal) + return maxVal; + else if (val < minVal) + return minVal; + else if (val > maxVal) + return maxVal; + else + return val; +} + + +struct cplane_t +{ + Vector normal; + float dist; + byte type; + byte signbits; + byte pad[2]; + +#ifdef VECTOR_NO_SLOW_OPERATIONS + cplane_t() {} + +private: + cplane_t(const cplane_t& vOther); +#endif +}; + +#define CPLANE_NORMAL_X 0 +#define CPLANE_NORMAL_Y 4 +#define CPLANE_NORMAL_Z 8 +#define CPLANE_DIST 12 +#define CPLANE_TYPE 16 +#define CPLANE_SIGNBITS 17 +#define CPLANE_PAD0 18 +#define CPLANE_PAD1 19 + +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 + +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + + +enum +{ + FRUSTUM_RIGHT = 0, + FRUSTUM_LEFT = 1, + FRUSTUM_TOP = 2, + FRUSTUM_BOTTOM = 3, + FRUSTUM_NEARZ = 4, + FRUSTUM_FARZ = 5, + FRUSTUM_NUMPLANES = 6 +}; + +extern int SignbitsForPlane(cplane_t* out); + +class Frustum_t +{ +public: + void SetPlane(int i, int nType, const Vector& vecNormal, float dist) + { + m_Plane[i].normal = vecNormal; + m_Plane[i].dist = dist; + m_Plane[i].type = nType; + m_Plane[i].signbits = SignbitsForPlane(&m_Plane[i]); + m_AbsNormal[i].Init(fabs(vecNormal.x), fabs(vecNormal.y), fabs(vecNormal.z)); + } + + inline const cplane_t* GetPlane(int i) const { return &m_Plane[i]; } + inline const Vector& GetAbsNormal(int i) const { return m_AbsNormal[i]; } + +private: + cplane_t m_Plane[FRUSTUM_NUMPLANES]; + Vector m_AbsNormal[FRUSTUM_NUMPLANES]; +}; + +float CalcFovY(float flFovX, float flScreenAspect); +float CalcFovX(float flFovY, float flScreenAspect); + +void GeneratePerspectiveFrustum(const Vector& origin, const QAngle& angles, float flZNear, float flZFar, float flFovX, float flAspectRatio, Frustum_t& frustum); +void GeneratePerspectiveFrustum(const Vector& origin, const Vector& forward, const Vector& right, const Vector& up, float flZNear, float flZFar, float flFovX, float flFovY, Frustum_t& frustum); + +bool R_CullBox(const Vector& mins, const Vector& maxs, const Frustum_t& frustum); +bool R_CullBoxSkipNear(const Vector& mins, const Vector& maxs, const Frustum_t& frustum); + +struct matrix3x4_t +{ + matrix3x4_t() {} + matrix3x4_t( + float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23) + { + m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03; + m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13; + m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23; + } + + void Init(const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector& vecOrigin) + { + m_flMatVal[0][0] = xAxis.x; m_flMatVal[0][1] = yAxis.x; m_flMatVal[0][2] = zAxis.x; m_flMatVal[0][3] = vecOrigin.x; + m_flMatVal[1][0] = xAxis.y; m_flMatVal[1][1] = yAxis.y; m_flMatVal[1][2] = zAxis.y; m_flMatVal[1][3] = vecOrigin.y; + m_flMatVal[2][0] = xAxis.z; m_flMatVal[2][1] = yAxis.z; m_flMatVal[2][2] = zAxis.z; m_flMatVal[2][3] = vecOrigin.z; + } + + matrix3x4_t(const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector& vecOrigin) + { + Init(xAxis, yAxis, zAxis, vecOrigin); + } + + inline void Invalidate(void) + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 4; j++) + { + m_flMatVal[i][j] = VEC_T_NAN; + } + } + } + + float* operator[](int i) { Assert((i >= 0) && (i < 3)); return m_flMatVal[i]; } + const float* operator[](int i) const { Assert((i >= 0) && (i < 3)); return m_flMatVal[i]; } + float* Base() { return &m_flMatVal[0][0]; } + const float* Base() const { return &m_flMatVal[0][0]; } + + float m_flMatVal[3][4]; +}; + +#include "fltx4.h" + +class ALIGN16 matrix3x4a_t : public matrix3x4_t +{ +public: + matrix3x4a_t(const matrix3x4_t& src) { *this = src; }; + matrix3x4a_t& operator=(const matrix3x4_t& src) { memcpy(Base(), src.Base(), sizeof(float) * 3 * 4); return *this; }; + + matrix3x4a_t( + float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23) + { + AssertDbg(((size_t)Base() & 0xf) == 0); + m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03; + m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13; + m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23; + } + matrix3x4a_t() {} + + static FORCEINLINE bool TypeIsAlignedForSIMD(void) { return true; } + + + FORCEINLINE fltx4& SIMDRow(uint nIdx) { AssertDbg(nIdx < 3); return *((fltx4*)(&(m_flMatVal[nIdx]))); } + FORCEINLINE const fltx4& SIMDRow(uint nIdx) const { AssertDbg(nIdx < 3); return *((const fltx4*)(&(m_flMatVal[nIdx]))); } + +} ALIGN16_POST; + + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define M_PI_F ((float)(M_PI)) + +#ifndef RAD2DEG +#define RAD2DEG( x ) ( (float)(x) * (float)(180.f / M_PI_F) ) +#endif + +#ifndef DEG2RAD +#define DEG2RAD( x ) ( (float)(x) * (float)(M_PI_F / 180.f) ) +#endif + +#define SIDE_FRONT 0 +#define SIDE_BACK 1 +#define SIDE_ON 2 +#define SIDE_CROSS -2 + +#define ON_VIS_EPSILON 0.01 +#define EQUAL_EPSILON 0.001 + +extern bool s_bMathlibInitialized; + +extern const Vector vec3_origin; +extern const QAngle vec3_angle; +extern const Quaternion quat_identity; +extern const Vector vec3_invalid; +extern const int nanmask; + +#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) + +FORCEINLINE vec_t DotProduct(const vec_t* v1, const vec_t* v2) +{ + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; +} +FORCEINLINE void VectorSubtract(const vec_t* a, const vec_t* b, vec_t* c) +{ + c[0] = a[0] - b[0]; + c[1] = a[1] - b[1]; + c[2] = a[2] - b[2]; +} +FORCEINLINE void VectorAdd(const vec_t* a, const vec_t* b, vec_t* c) +{ + c[0] = a[0] + b[0]; + c[1] = a[1] + b[1]; + c[2] = a[2] + b[2]; +} +FORCEINLINE void VectorCopy(const vec_t* a, vec_t* b) +{ + b[0] = a[0]; + b[1] = a[1]; + b[2] = a[2]; +} +FORCEINLINE void VectorClear(vec_t* a) +{ + a[0] = a[1] = a[2] = 0; +} + +FORCEINLINE float VectorMaximum(const vec_t* v) +{ + return max(v[0], max(v[1], v[2])); +} + +FORCEINLINE float VectorMaximum(const Vector& v) +{ + return max(v.x, max(v.y, v.z)); +} + +FORCEINLINE void VectorScale(const float* in, vec_t scale, float* out) +{ + out[0] = in[0] * scale; + out[1] = in[1] * scale; + out[2] = in[2] * scale; +} + + +inline void VectorFill(vec_t* a, float b) +{ + a[0] = a[1] = a[2] = b; +} + +inline void VectorNegate(vec_t* a) +{ + a[0] = -a[0]; + a[1] = -a[1]; + a[2] = -a[2]; +} + + +#define Vector2Clear(x) {(x)[0]=(x)[1]=0;} +#define Vector2Negate(x) {(x)[0]=-((x)[0]);(x)[1]=-((x)[1]);} +#define Vector2Copy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];} +#define Vector2Subtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];} +#define Vector2Add(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];} +#define Vector2Scale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];} + +#define VECTOR_COPY( A, B ) do { (B)[0] = (A)[0]; (B)[1] = (A)[1]; (B)[2]=(A)[2]; } while(0) +#define DOT_PRODUCT( A, B ) ( (A)[0]*(B)[0] + (A)[1]*(B)[1] + (A)[2]*(B)[2] ) + +FORCEINLINE void VectorMAInline(const float* start, float scale, const float* direction, float* dest) +{ + dest[0] = start[0] + direction[0] * scale; + dest[1] = start[1] + direction[1] * scale; + dest[2] = start[2] + direction[2] * scale; +} + +FORCEINLINE void VectorMAInline(const Vector& start, float scale, const Vector& direction, Vector& dest) +{ + dest.x = start.x + direction.x * scale; + dest.y = start.y + direction.y * scale; + dest.z = start.z + direction.z * scale; +} + +FORCEINLINE void VectorMA(const Vector& start, float scale, const Vector& direction, Vector& dest) +{ + VectorMAInline(start, scale, direction, dest); +} + +FORCEINLINE void VectorMA(const float* start, float scale, const float* direction, float* dest) +{ + VectorMAInline(start, scale, direction, dest); +} + + +int VectorCompare(const float* v1, const float* v2); + +inline float VectorLength(const float* v) +{ + return FastSqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + FLT_EPSILON); +} + +void CrossProduct(const float* v1, const float* v2, float* cross); + +qboolean VectorsEqual(const float* v1, const float* v2); + +inline vec_t RoundInt(vec_t in) +{ + return floor(in + 0.5f); +} + +int Q_log2(int val); + +void inline SinCos(float radians, float* sine, float* cosine) +{ +#if defined( _X360 ) + XMScalarSinCos(sine, cosine, radians); +#elif defined( PLATFORM_WINDOWS_PC32 ) + _asm + { + fld DWORD PTR[radians] + fsincos + + mov edx, DWORD PTR[cosine] + mov eax, DWORD PTR[sine] + + fstp DWORD PTR[edx] + fstp DWORD PTR[eax] + } +#elif defined( PLATFORM_WINDOWS_PC64 ) + *sine = sin(radians); + *cosine = cos(radians); +#elif defined( POSIX ) + register double __cosr, __sinr; + __asm ("fsincos" : "=t" (__cosr), "=u" (__sinr) : "0" (radians)); + + *sine = __sinr; + *cosine = __cosr; +#endif +} + +#define SIN_TABLE_SIZE 256 +#define FTOIBIAS 12582912.f +extern float SinCosTable[SIN_TABLE_SIZE]; + +inline float TableCos(float theta) +{ + union + { + int i; + float f; + } ftmp; + + ftmp.f = theta * (float)(SIN_TABLE_SIZE / (2.0f * M_PI)) + (FTOIBIAS + (SIN_TABLE_SIZE / 4)); + return SinCosTable[ftmp.i & (SIN_TABLE_SIZE - 1)]; +} + +inline float TableSin(float theta) +{ + union + { + int i; + float f; + } ftmp; + + ftmp.f = theta * (float)(SIN_TABLE_SIZE / (2.0f * M_PI)) + FTOIBIAS; + return SinCosTable[ftmp.i & (SIN_TABLE_SIZE - 1)]; +} + +template +FORCEINLINE T Square(T const& a) +{ + return a * a; +} + + +FORCEINLINE uint SmallestPowerOfTwoGreaterOrEqual(uint x) +{ + x -= 1; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; +} + +FORCEINLINE uint LargestPowerOfTwoLessThanOrEqual(uint x) +{ + if (x >= 0x80000000) + return 0x80000000; + + return SmallestPowerOfTwoGreaterOrEqual(x + 1) >> 1; +} + + +void FloorDivMod(double numer, double denom, int* quotient, int* rem); +int GreatestCommonDivisor(int i1, int i2); + +bool IsDenormal(const float& val); + +enum +{ + PITCH = 0, + YAW, + ROLL +}; + +void MatrixAngles(const matrix3x4_t& matrix, float* angles); +void MatrixVectors(const matrix3x4_t& matrix, Vector* pForward, Vector* pRight, Vector* pUp); +void VectorTransform(const float* in1, const matrix3x4_t& in2, float* out); +void VectorITransform(const float* in1, const matrix3x4_t& in2, float* out); +void VectorRotate(const float* in1, const matrix3x4_t& in2, float* out); +void VectorRotate(const Vector& in1, const QAngle& in2, Vector& out); +void VectorRotate(const Vector& in1, const Quaternion& in2, Vector& out); +void VectorIRotate(const float* in1, const matrix3x4_t& in2, float* out); + +#ifndef VECTOR_NO_SLOW_OPERATIONS + +QAngle TransformAnglesToLocalSpace(const QAngle& angles, const matrix3x4_t& parentMatrix); +QAngle TransformAnglesToWorldSpace(const QAngle& angles, const matrix3x4_t& parentMatrix); + +#endif + +void MatrixInitialize(matrix3x4_t& mat, const Vector& vecOrigin, const Vector& vecXAxis, const Vector& vecYAxis, const Vector& vecZAxis); +void MatrixCopy(const matrix3x4_t& in, matrix3x4_t& out); +void MatrixInvert(const matrix3x4_t& in, matrix3x4_t& out); + +bool MatricesAreEqual(const matrix3x4_t& src1, const matrix3x4_t& src2, float flTolerance = 1e-5); + +void MatrixGetColumn(const matrix3x4_t& in, int column, Vector& out); +void MatrixSetColumn(const Vector& in, int column, matrix3x4_t& out); + +inline void MatrixGetTranslation(const matrix3x4_t& in, Vector& out) +{ + MatrixGetColumn(in, 3, out); +} + +inline void MatrixSetTranslation(const Vector& in, matrix3x4_t& out) +{ + MatrixSetColumn(in, 3, out); +} + +void MatrixScaleBy(const float flScale, matrix3x4_t& out); +void MatrixScaleByZero(matrix3x4_t& out); + +void ConcatRotations(const matrix3x4_t& in1, const matrix3x4_t& in2, matrix3x4_t& out); +void ConcatTransforms(const matrix3x4_t& in1, const matrix3x4_t& in2, matrix3x4_t& out); + +inline void MatrixMultiply(const matrix3x4_t& in1, const matrix3x4_t& in2, matrix3x4_t& out) +{ + ConcatTransforms(in1, in2, out); +} + +void QuaternionSlerp(const Quaternion& p, const Quaternion& q, float t, Quaternion& qt); +void QuaternionSlerpNoAlign(const Quaternion& p, const Quaternion& q, float t, Quaternion& qt); +void QuaternionBlend(const Quaternion& p, const Quaternion& q, float t, Quaternion& qt); +void QuaternionBlendNoAlign(const Quaternion& p, const Quaternion& q, float t, Quaternion& qt); +void QuaternionIdentityBlend(const Quaternion& p, float t, Quaternion& qt); +float QuaternionAngleDiff(const Quaternion& p, const Quaternion& q); +void QuaternionScale(const Quaternion& p, float t, Quaternion& q); +void QuaternionAlign(const Quaternion& p, const Quaternion& q, Quaternion& qt); +float QuaternionDotProduct(const Quaternion& p, const Quaternion& q); +void QuaternionConjugate(const Quaternion& p, Quaternion& q); +void QuaternionInvert(const Quaternion& p, Quaternion& q); +float QuaternionNormalize(Quaternion& q); +void QuaternionAdd(const Quaternion& p, const Quaternion& q, Quaternion& qt); +void QuaternionMult(const Quaternion& p, const Quaternion& q, Quaternion& qt); +void QuaternionMatrix(const Quaternion& q, matrix3x4_t& matrix); +void QuaternionMatrix(const Quaternion& q, const Vector& pos, matrix3x4_t& matrix); +void QuaternionAngles(const Quaternion& q, QAngle& angles); +void AngleQuaternion(const QAngle& angles, Quaternion& qt); +void QuaternionAngles(const Quaternion& q, RadianEuler& angles); +void AngleQuaternion(RadianEuler const& angles, Quaternion& qt); +void QuaternionAxisAngle(const Quaternion& q, Vector& axis, float& angle); +void AxisAngleQuaternion(const Vector& axis, float angle, Quaternion& q); +void BasisToQuaternion(const Vector& vecForward, const Vector& vecRight, const Vector& vecUp, Quaternion& q); +void MatrixQuaternion(const matrix3x4_t& mat, Quaternion& q); + +inline float MatrixRowDotProduct(const matrix3x4_t& in1, int row, const Vector& in2) +{ + Assert((row >= 0) && (row < 3)); + return DotProduct(in1[row], in2.Base()); +} + +inline float MatrixColumnDotProduct(const matrix3x4_t& in1, int col, const Vector& in2) +{ + Assert((col >= 0) && (col < 4)); + return in1[0][col] * in2[0] + in1[1][col] * in2[1] + in1[2][col] * in2[2]; +} + +int __cdecl BoxOnPlaneSide(const float* emins, const float* emaxs, const cplane_t* plane); + +inline float anglemod(float a) +{ + a = (360.f / 65536) * ((int)(a * (65536.f / 360.0f)) & 65535); + return a; +} + +inline float RemapVal(float val, float A, float B, float C, float D) +{ + if (A == B) + return val >= B ? D : C; + return C + (D - C) * (val - A) / (B - A); +} + +inline float RemapValClamped(float val, float A, float B, float C, float D) +{ + if (A == B) + return val >= B ? D : C; + float cVal = (val - A) / (B - A); + cVal = clamp(cVal, 0.0f, 1.0f); + + return C + (D - C) * cVal; +} + +template +FORCEINLINE T Lerp(float flPercent, T const& A, T const& B) +{ + return A + (B - A) * flPercent; +} + +FORCEINLINE float Sqr(float f) +{ + return f * f; +} + +static inline float FLerp(float f1, float f2, float i1, float i2, float x) +{ + return f1 + (f2 - f1) * (x - i1) / (i2 - i1); +} + + +#ifndef VECTOR_NO_SLOW_OPERATIONS + +template<> FORCEINLINE QAngle Lerp(float flPercent, const QAngle& q1, const QAngle& q2) +{ + if (q1 == q2) + return q1; + + Quaternion src, dest; + + AngleQuaternion(q1, src); + AngleQuaternion(q2, dest); + + Quaternion result; + + QuaternionSlerp(src, dest, flPercent, result); + + QAngle output; + QuaternionAngles(result, output); + return output; +} + +#else + +#pragma error + +template<> FORCEINLINE QAngleByValue Lerp(float flPercent, const QAngleByValue& q1, const QAngleByValue& q2) +{ + if (q1 == q2) + return q1; + + Quaternion src, dest; + + AngleQuaternion(q1, src); + AngleQuaternion(q2, dest); + + Quaternion result; + + QuaternionSlerp(src, dest, flPercent, result); + + QAngleByValue output; + QuaternionAngles(result, output); + return output; +} + +#endif + + +template +FORCEINLINE void V_swap(T& x, T& y) +{ + T temp = x; + x = y; + y = temp; +} + +template FORCEINLINE T AVG(T a, T b) +{ + return (a + b) / 2; +} + +#define NELEMS(x) ARRAYSIZE(x) + +#define XYZ(v) (v).x,(v).y,(v).z + + +inline float Sign(float x) +{ + return (x < 0.0f) ? -1.0f : 1.0f; +} + +inline int ClampArrayBounds(int n, unsigned maxindex) +{ + unsigned int inrangemask = 0xFFFFFFFF + (((unsigned)n) > maxindex); + unsigned int lessthan0mask = 0xFFFFFFFF + (n >= 0); + + int result = (inrangemask & n); + + result |= ((~inrangemask) & (~lessthan0mask)) & maxindex; + + return result; +} + + +#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ + (((p)->type < 3)? \ + ( \ + ((p)->dist <= (emins)[(p)->type])? \ + 1 \ + : \ + ( \ + ((p)->dist >= (emaxs)[(p)->type])?\ + 2 \ + : \ + 3 \ + ) \ + ) \ + : \ + BoxOnPlaneSide( (emins), (emaxs), (p))) + +void AngleVectors(const QAngle& angles, Vector* forward); +void AngleVectors(const QAngle& angles, Vector* forward, Vector* right, Vector* up); +void AngleVectorsTranspose(const QAngle& angles, Vector* forward, Vector* right, Vector* up); +void AngleMatrix(const QAngle& angles, matrix3x4_t& mat); +void AngleMatrix(const QAngle& angles, const Vector& position, matrix3x4_t& mat); +void AngleMatrix(const RadianEuler& angles, matrix3x4_t& mat); +void AngleMatrix(RadianEuler const& angles, const Vector& position, matrix3x4_t& mat); +void AngleIMatrix(const QAngle& angles, matrix3x4_t& mat); +void AngleIMatrix(const QAngle& angles, const Vector& position, matrix3x4_t& mat); +void AngleIMatrix(const RadianEuler& angles, matrix3x4_t& mat); +void VectorAngles(const Vector& forward, QAngle& angles); +void VectorAngles(const Vector& forward, const Vector& pseudoup, QAngle& angles); +void VectorMatrix(const Vector& forward, matrix3x4_t& mat); +void VectorVectors(const Vector& forward, Vector& right, Vector& up); +void SetIdentityMatrix(matrix3x4_t& mat); +void SetScaleMatrix(float x, float y, float z, matrix3x4_t& dst); +void MatrixBuildRotationAboutAxis(const Vector& vAxisOfRot, float angleDegrees, matrix3x4_t& dst); + +inline void SetScaleMatrix(float flScale, matrix3x4_t& dst) +{ + SetScaleMatrix(flScale, flScale, flScale, dst); +} + +inline void SetScaleMatrix(const Vector& scale, matrix3x4_t& dst) +{ + SetScaleMatrix(scale.x, scale.y, scale.z, dst); +} + +void MatrixTranspose(matrix3x4_t& mat); +void MatrixTranspose(const matrix3x4_t& src, matrix3x4_t& dst); +void MatrixInverseTranspose(const matrix3x4_t& src, matrix3x4_t& dst); + +inline void PositionMatrix(const Vector& position, matrix3x4_t& mat) +{ + MatrixSetColumn(position, 3, mat); +} + +inline void MatrixPosition(const matrix3x4_t& matrix, Vector& position) +{ + MatrixGetColumn(matrix, 3, position); +} + +inline void VectorRotate(const Vector& in1, const matrix3x4_t& in2, Vector& out) +{ + VectorRotate(&in1.x, in2, &out.x); +} + +inline void VectorIRotate(const Vector& in1, const matrix3x4_t& in2, Vector& out) +{ + VectorIRotate(&in1.x, in2, &out.x); +} + +inline void MatrixAngles(const matrix3x4_t& matrix, QAngle& angles) +{ + MatrixAngles(matrix, &angles.x); +} + +inline void MatrixAngles(const matrix3x4_t& matrix, QAngle& angles, Vector& position) +{ + MatrixAngles(matrix, angles); + MatrixPosition(matrix, position); +} + +inline void MatrixAngles(const matrix3x4_t& matrix, RadianEuler& angles) +{ + MatrixAngles(matrix, &angles.x); + + angles.Init(DEG2RAD(angles.z), DEG2RAD(angles.x), DEG2RAD(angles.y)); +} + +void MatrixAngles(const matrix3x4_t& mat, RadianEuler& angles, Vector& position); + +void MatrixAngles(const matrix3x4_t& mat, Quaternion& q, Vector& position); + +inline int VectorCompare(const Vector& v1, const Vector& v2) +{ + return v1 == v2; +} + +inline void VectorTransform(const Vector& in1, const matrix3x4_t& in2, Vector& out) +{ + VectorTransform(&in1.x, in2, &out.x); +} + +inline void VectorITransform(const Vector& in1, const matrix3x4_t& in2, Vector& out) +{ + VectorITransform(&in1.x, in2, &out.x); +} + +inline int BoxOnPlaneSide(const Vector& emins, const Vector& emaxs, const cplane_t* plane) +{ + return BoxOnPlaneSide(&emins.x, &emaxs.x, plane); +} + +inline void VectorFill(Vector& a, float b) +{ + a[0] = a[1] = a[2] = b; +} + +inline void VectorNegate(Vector& a) +{ + a[0] = -a[0]; + a[1] = -a[1]; + a[2] = -a[2]; +} + +inline vec_t VectorAvg(Vector& a) +{ + return (a[0] + a[1] + a[2]) / 3; +} + +inline int FASTCALL BoxOnPlaneSide2(const Vector& emins, const Vector& emaxs, const cplane_t* p, float tolerance = 0.f) +{ + Vector corners[2]; + + if (p->normal[0] < 0) + { + corners[0][0] = emins[0]; + corners[1][0] = emaxs[0]; + } + else + { + corners[1][0] = emins[0]; + corners[0][0] = emaxs[0]; + } + + if (p->normal[1] < 0) + { + corners[0][1] = emins[1]; + corners[1][1] = emaxs[1]; + } + else + { + corners[1][1] = emins[1]; + corners[0][1] = emaxs[1]; + } + + if (p->normal[2] < 0) + { + corners[0][2] = emins[2]; + corners[1][2] = emaxs[2]; + } + else + { + corners[1][2] = emins[2]; + corners[0][2] = emaxs[2]; + } + + int sides = 0; + + float dist1 = DotProduct(p->normal, corners[0]) - p->dist; + if (dist1 >= tolerance) + sides = 1; + + float dist2 = DotProduct(p->normal, corners[1]) - p->dist; + if (dist2 < -tolerance) + sides |= 2; + + return sides; +} + +void ClearBounds(Vector& mins, Vector& maxs); +void AddPointToBounds(const Vector& v, Vector& mins, Vector& maxs); + +void BuildGammaTable(float gamma, float texGamma, float brightness, int overbright); + +inline float TexLightToLinear(int c, int exponent) +{ + extern float power2_n[256]; + Assert(exponent >= -128 && exponent <= 127); + return (float)c * power2_n[exponent + 128]; +} + + +int LinearToTexture(float f); +int LinearToScreenGamma(float f); +float TextureToLinear(int c); + +struct ColorRGBExp32 +{ + byte r, g, b; + signed char exponent; +}; + +void ColorRGBExp32ToVector(const ColorRGBExp32& in, Vector& out); +void VectorToColorRGBExp32(const Vector& v, ColorRGBExp32& c); + +bool SolveQuadratic(float a, float b, float c, float& root1, float& root2); + +bool SolveInverseQuadratic(float x1, float y1, float x2, float y2, float x3, float y3, float& a, float& b, float& c); + +bool SolveInverseQuadraticMonotonic(float x1, float y1, float x2, float y2, + float x3, float y3, float& a, float& b, float& c); + + + + +bool SolveInverseReciprocalQuadratic(float x1, float y1, float x2, float y2, float x3, float y3, float& a, float& b, float& c); + +void VectorYawRotate(const Vector& in, float flYaw, Vector& out); + + +float Bias(float x, float biasAmt); + + +float Gain(float x, float biasAmt); + + +float SmoothCurve(float x); + + +float SmoothCurve_Tweak(float x, float flPeakPos = 0.5, float flPeakSharpness = 0.5); + + +inline float ExponentialDecay(float halflife, float dt) +{ + return expf(-0.69314718f / halflife * dt); +} + +inline float ExponentialDecay(float decayTo, float decayTime, float dt) +{ + return expf(logf(decayTo) / decayTime * dt); +} + +inline float ExponentialDecayIntegral(float decayTo, float decayTime, float dt) +{ + return (powf(decayTo, dt / decayTime) * decayTime - decayTime) / logf(decayTo); +} + +inline float SimpleSpline(float value) +{ + float valueSquared = value * value; + + return (3 * valueSquared - 2 * valueSquared * value); +} + +inline float SimpleSplineRemapVal(float val, float A, float B, float C, float D) +{ + if (A == B) + return val >= B ? D : C; + float cVal = (val - A) / (B - A); + return C + (D - C) * SimpleSpline(cVal); +} + +inline float SimpleSplineRemapValClamped(float val, float A, float B, float C, float D) +{ + if (A == B) + return val >= B ? D : C; + float cVal = (val - A) / (B - A); + cVal = clamp(cVal, 0.0f, 1.0f); + return C + (D - C) * SimpleSpline(cVal); +} + +FORCEINLINE int RoundFloatToInt(float f) +{ +#if defined(__i386__) || defined(_M_IX86) || defined( PLATFORM_WINDOWS_PC64 ) + return _mm_cvtss_si32(_mm_load_ss(&f)); +#elif defined( _X360 ) +#ifdef Assert + Assert(IsFPUControlWordSet()); +#endif + union + { + double flResult; + int pResult[2]; + }; + flResult = __fctiw(f); + return pResult[1]; +#else +#error Unknown architecture +#endif +} + +FORCEINLINE unsigned char RoundFloatToByte(float f) +{ + int nResult = RoundFloatToInt(f); +#ifdef Assert + Assert((nResult & ~0xFF) == 0); +#endif + return (unsigned char)nResult; +} + +FORCEINLINE unsigned long RoundFloatToUnsignedLong(float f) +{ +#if defined( _X360 ) +#ifdef Assert + Assert(IsFPUControlWordSet()); +#endif + union + { + double flResult; + int pIntResult[2]; + unsigned long pResult[2]; + }; + flResult = __fctiw(f); + Assert(pIntResult[1] >= 0); + return pResult[1]; +#else + +#if defined( PLATFORM_WINDOWS_PC64 ) + uint nRet = (uint)f; + if (nRet & 1) + { + if ((f - floor(f) >= 0.5)) + { + nRet++; + } + } + else + { + if ((f - floor(f) > 0.5)) + { + nRet++; + } + } + return nRet; +#else + unsigned char nResult[8]; + +#if defined( _WIN32 ) + __asm + { + fld f + fistp qword ptr nResult + } +#elif POSIX + __asm __volatile__( + "fistpl %0;": "=m" (nResult) : "t" (f) : "st" + ); +#endif + + return *((unsigned long*)nResult); +#endif +#endif +} + +FORCEINLINE bool IsIntegralValue(float flValue, float flTolerance = 0.001f) +{ + return fabs(RoundFloatToInt(flValue) - flValue) < flTolerance; +} + +FORCEINLINE int Float2Int(float a) +{ +#if defined( _X360 ) + union + { + double flResult; + int pResult[2]; + }; + flResult = __fctiwz(a); + return pResult[1]; +#else + return (int)a; +#endif +} + +inline int Floor2Int(float a) +{ + int RetVal; +#if defined( __i386__ ) + __m128 a128 = _mm_set_ss(a); + RetVal = _mm_cvtss_si32(a128); + __m128 rounded128 = _mm_cvt_si2ss(_mm_setzero_ps(), RetVal); + RetVal -= _mm_comigt_ss(rounded128, a128); +#else + RetVal = static_cast(floor(a)); +#endif + return RetVal; +} + +FORCEINLINE unsigned int FastFToC(float c) +{ +#if defined( __i386__ ) + union { float f; int i; } convert = { c * 255.0f + (float)(1 << 23) }; + return convert.i & 255; +#else + return Float2Int(c * 255.0f); +#endif +} + +FORCEINLINE int FastFloatToSmallInt(float c) +{ +#if defined( __i386__ ) + union { float f; int i; } convert = { c + (float)(3 << 22) }; + return (convert.i & ((1 << 23) - 1)) - (1 << 22); +#else + return Float2Int(c); +#endif +} + +inline float ClampToMsec(float in) +{ + int msec = Floor2Int(in * 1000.0f + 0.5f); + return 0.001f * msec; +} + +inline int Ceil2Int(float a) +{ + int RetVal; +#if defined( __i386__ ) + __m128 a128 = _mm_load_ss(&a); + RetVal = _mm_cvtss_si32(a128); + __m128 rounded128 = _mm_cvt_si2ss(_mm_setzero_ps(), RetVal); + RetVal += _mm_comilt_ss(rounded128, a128); +#else + RetVal = static_cast(ceil(a)); +#endif + return RetVal; +} + + +#define TriArea2D( A, B, C ) \ + ( 0.5f * ( ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ) ) ) + +#define TriArea2DTimesTwo( A, B, C ) \ + ( ( ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ) ) ) + + +inline void GetBarycentricCoords2D( + Vector2D const& A, + Vector2D const& B, + Vector2D const& C, + Vector2D const& pt, + float bcCoords[3]) +{ + float invTriArea = 1.0f / TriArea2DTimesTwo(A, B, C); + + bcCoords[0] = TriArea2DTimesTwo(B, C, pt) * invTriArea; + bcCoords[1] = TriArea2DTimesTwo(C, A, pt) * invTriArea; + bcCoords[2] = TriArea2DTimesTwo(A, B, pt) * invTriArea; +} + + +inline bool QuickBoxSphereTest( + const Vector& vOrigin, + float flRadius, + const Vector& bbMin, + const Vector& bbMax) +{ + return vOrigin.x - flRadius < bbMax.x&& vOrigin.x + flRadius > bbMin.x && + vOrigin.y - flRadius < bbMax.y&& vOrigin.y + flRadius > bbMin.y && + vOrigin.z - flRadius < bbMax.z&& vOrigin.z + flRadius > bbMin.z; +} + + +inline bool QuickBoxIntersectTest( + const Vector& vBox1Min, + const Vector& vBox1Max, + const Vector& vBox2Min, + const Vector& vBox2Max) +{ + return + vBox1Min.x < vBox2Max.x&& vBox1Max.x > vBox2Min.x && + vBox1Min.y < vBox2Max.y&& vBox1Max.y > vBox2Min.y && + vBox1Min.z < vBox2Max.z&& vBox1Max.z > vBox2Min.z; +} + + +extern float GammaToLinearFullRange(float gamma); +extern float LinearToGammaFullRange(float linear); +extern float GammaToLinear(float gamma); +extern float LinearToGamma(float linear); + +extern float SrgbGammaToLinear(float flSrgbGammaValue); +extern float SrgbLinearToGamma(float flLinearValue); +extern float X360GammaToLinear(float fl360GammaValue); +extern float X360LinearToGamma(float flLinearValue); +extern float SrgbGammaTo360Gamma(float flSrgbGammaValue); + +FORCEINLINE float LinearToVertexLight(float f) +{ + extern float lineartovertex[4096]; + + int i = RoundFloatToInt(f * 1024.f); + + if ((unsigned)i > 4095) + { + if (i < 0) + i = 0; + else + i = 4095; + } + + return lineartovertex[i]; +} + + +FORCEINLINE unsigned char LinearToLightmap(float f) +{ + extern unsigned char lineartolightmap[4096]; + + int i = RoundFloatToInt(f * 1024.f); + + if ((unsigned)i > 4095) + { + if (i < 0) + i = 0; + else + i = 4095; + } + + return lineartolightmap[i]; +} + +FORCEINLINE void ColorClamp(Vector& color) +{ + float maxc = max(color.x, max(color.y, color.z)); + if (maxc > 1.0f) + { + float ooMax = 1.0f / maxc; + color.x *= ooMax; + color.y *= ooMax; + color.z *= ooMax; + } + + if (color[0] < 0.f) color[0] = 0.f; + if (color[1] < 0.f) color[1] = 0.f; + if (color[2] < 0.f) color[2] = 0.f; +} + +inline void ColorClampTruncate(Vector& color) +{ + if (color[0] > 1.0f) color[0] = 1.0f; else if (color[0] < 0.0f) color[0] = 0.0f; + if (color[1] > 1.0f) color[1] = 1.0f; else if (color[1] < 0.0f) color[1] = 0.0f; + if (color[2] > 1.0f) color[2] = 1.0f; else if (color[2] < 0.0f) color[2] = 0.0f; +} + +void Catmull_Rom_Spline( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Catmull_Rom_Spline_Tangent( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Catmull_Rom_Spline_Integral( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Catmull_Rom_Spline_Integral( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + Vector& output); + +void Catmull_Rom_Spline_Normalize( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Catmull_Rom_Spline_Integral_Normalize( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Catmull_Rom_Spline_NormalizeX( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Catmull_Rom_Spline_NormalizeX( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Hermite_Spline( + const Vector& p1, + const Vector& p2, + const Vector& d1, + const Vector& d2, + float t, + Vector& output); + +float Hermite_Spline( + float p1, + float p2, + float d1, + float d2, + float t); + +void Hermite_Spline( + const Vector& p0, + const Vector& p1, + const Vector& p2, + float t, + Vector& output); + +float Hermite_Spline( + float p0, + float p1, + float p2, + float t); + + +void Hermite_SplineBasis(float t, float basis[]); + +void Hermite_Spline( + const Quaternion& q0, + const Quaternion& q1, + const Quaternion& q2, + float t, + Quaternion& output); + + +void Kochanek_Bartels_Spline( + float tension, + float bias, + float continuity, + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Kochanek_Bartels_Spline_NormalizeX( + float tension, + float bias, + float continuity, + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Cubic_Spline( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Cubic_Spline_NormalizeX( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void BSpline( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void BSpline_NormalizeX( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Parabolic_Spline( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +void Parabolic_Spline_NormalizeX( + const Vector& p1, + const Vector& p2, + const Vector& p3, + const Vector& p4, + float t, + Vector& output); + +FORCEINLINE float QuinticInterpolatingPolynomial(float t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +void GetInterpolationData(float const* pKnotPositions, + float const* pKnotValues, + int nNumValuesinList, + int nInterpolationRange, + float flPositionToInterpolateAt, + bool bWrap, + float* pValueA, + float* pValueB, + float* pInterpolationValue); + +float RangeCompressor(float flValue, float flMin, float flMax, float flBase); + +float CalcSqrDistanceToAABB(const Vector& mins, const Vector& maxs, const Vector& point); +void CalcClosestPointOnAABB(const Vector& mins, const Vector& maxs, const Vector& point, Vector& closestOut); +void CalcSqrDistAndClosestPointOnAABB(const Vector& mins, const Vector& maxs, const Vector& point, Vector& closestOut, float& distSqrOut); + +inline float CalcDistanceToAABB(const Vector& mins, const Vector& maxs, const Vector& point) +{ + float flDistSqr = CalcSqrDistanceToAABB(mins, maxs, point); + return sqrt(flDistSqr); +} + +void CalcClosestPointOnLine(const Vector& P, const Vector& vLineA, const Vector& vLineB, Vector& vClosest, float* t = 0); +float CalcDistanceToLine(const Vector& P, const Vector& vLineA, const Vector& vLineB, float* t = 0); +float CalcDistanceSqrToLine(const Vector& P, const Vector& vLineA, const Vector& vLineB, float* t = 0); + +void CalcClosestPointOnLineSegment(const Vector& P, const Vector& vLineA, const Vector& vLineB, Vector& vClosest, float* t = 0); +float CalcDistanceToLineSegment(const Vector& P, const Vector& vLineA, const Vector& vLineB, float* t = 0); +float CalcDistanceSqrToLineSegment(const Vector& P, const Vector& vLineA, const Vector& vLineB, float* t = 0); + +bool CalcLineToLineIntersectionSegment( + const Vector& p1, const Vector& p2, const Vector& p3, const Vector& p4, Vector* s1, Vector* s2, + float* t1, float* t2); + +void CalcClosestPointOnLine2D(Vector2D const& P, Vector2D const& vLineA, Vector2D const& vLineB, Vector2D& vClosest, float* t = 0); +float CalcDistanceToLine2D(Vector2D const& P, Vector2D const& vLineA, Vector2D const& vLineB, float* t = 0); +float CalcDistanceSqrToLine2D(Vector2D const& P, Vector2D const& vLineA, Vector2D const& vLineB, float* t = 0); +void CalcClosestPointOnLineSegment2D(Vector2D const& P, Vector2D const& vLineA, Vector2D const& vLineB, Vector2D& vClosest, float* t = 0); +float CalcDistanceToLineSegment2D(Vector2D const& P, Vector2D const& vLineA, Vector2D const& vLineB, float* t = 0); +float CalcDistanceSqrToLineSegment2D(Vector2D const& P, Vector2D const& vLineA, Vector2D const& vLineB, float* t = 0); + +void MathLib_Init(float gamma = 2.2f, float texGamma = 2.2f, float brightness = 0.0f, int overbright = 2.0f, bool bAllow3DNow = true, bool bAllowSSE = true, bool bAllowSSE2 = true, bool bAllowMMX = true); +bool MathLib_3DNowEnabled(void); +bool MathLib_MMXEnabled(void); +bool MathLib_SSEEnabled(void); +bool MathLib_SSE2Enabled(void); + +float Approach(float target, float value, float speed); +float ApproachAngle(float target, float value, float speed); +float AngleDiff(float destAngle, float srcAngle); +float AngleDistance(float next, float cur); +float AngleNormalize(float angle); + +float AngleNormalizePositive(float angle); + +bool AnglesAreEqual(float a, float b, float tolerance = 0.0f); + + +void RotationDeltaAxisAngle(const QAngle& srcAngles, const QAngle& destAngles, Vector& deltaAxis, float& deltaAngle); +void RotationDelta(const QAngle& srcAngles, const QAngle& destAngles, QAngle* out); + +void ComputeTrianglePlane(const Vector& v1, const Vector& v2, const Vector& v3, Vector& normal, float& intercept); +int PolyFromPlane(Vector* outVerts, const Vector& normal, float dist, float fHalfScale = 9000.0f); +int ClipPolyToPlane(Vector* inVerts, int vertCount, Vector* outVerts, const Vector& normal, float dist, float fOnPlaneEpsilon = 0.1f); +int ClipPolyToPlane_Precise(double* inVerts, int vertCount, double* outVerts, const double* normal, double dist, double fOnPlaneEpsilon = 0.1); + +void CalcTriangleTangentSpace(const Vector& p0, const Vector& p1, const Vector& p2, + const Vector2D& t0, const Vector2D& t1, const Vector2D& t2, + Vector& sVect, Vector& tVect); + +void TransformAABB(const matrix3x4_t& in1, const Vector& vecMinsIn, const Vector& vecMaxsIn, Vector& vecMinsOut, Vector& vecMaxsOut); + +void ITransformAABB(const matrix3x4_t& in1, const Vector& vecMinsIn, const Vector& vecMaxsIn, Vector& vecMinsOut, Vector& vecMaxsOut); + +void RotateAABB(const matrix3x4_t& in1, const Vector& vecMinsIn, const Vector& vecMaxsIn, Vector& vecMinsOut, Vector& vecMaxsOut); + +void IRotateAABB(const matrix3x4_t& in1, const Vector& vecMinsIn, const Vector& vecMaxsIn, Vector& vecMinsOut, Vector& vecMaxsOut); + +inline void MatrixTransformPlane(const matrix3x4_t& src, const cplane_t& inPlane, cplane_t& outPlane) +{ + VectorRotate(inPlane.normal, src, outPlane.normal); + outPlane.dist = inPlane.dist * DotProduct(outPlane.normal, outPlane.normal); + outPlane.dist += outPlane.normal.x * src[0][3] + outPlane.normal.y * src[1][3] + outPlane.normal.z * src[2][3]; +} + +inline void MatrixITransformPlane(const matrix3x4_t& src, const cplane_t& inPlane, cplane_t& outPlane) +{ + Vector vecTranslation; + MatrixGetColumn(src, 3, vecTranslation); + + Vector vecInvTranslation; + VectorIRotate(vecTranslation, src, vecInvTranslation); + + VectorIRotate(inPlane.normal, src, outPlane.normal); + outPlane.dist = inPlane.dist * DotProduct(outPlane.normal, outPlane.normal); + outPlane.dist -= outPlane.normal.x * vecInvTranslation[0] + outPlane.normal.y * vecInvTranslation[1] + outPlane.normal.z * vecInvTranslation[2]; +} + +int CeilPow2(int in); +int FloorPow2(int in); + +FORCEINLINE float* UnpackNormal_HEND3N(const unsigned int* pPackedNormal, float* pNormal) +{ + int temp[3]; + temp[0] = ((*pPackedNormal >> 0L) & 0x7ff); + if (temp[0] & 0x400) + { + temp[0] = 2048 - temp[0]; + } + temp[1] = ((*pPackedNormal >> 11L) & 0x7ff); + if (temp[1] & 0x400) + { + temp[1] = 2048 - temp[1]; + } + temp[2] = ((*pPackedNormal >> 22L) & 0x3ff); + if (temp[2] & 0x200) + { + temp[2] = 1024 - temp[2]; + } + pNormal[0] = (float)temp[0] * 1.0f / 1023.0f; + pNormal[1] = (float)temp[1] * 1.0f / 1023.0f; + pNormal[2] = (float)temp[2] * 1.0f / 511.0f; + return pNormal; +} + +FORCEINLINE unsigned int* PackNormal_HEND3N(const float* pNormal, unsigned int* pPackedNormal) +{ + int temp[3]; + + temp[0] = Float2Int(pNormal[0] * 1023.0f); + temp[1] = Float2Int(pNormal[1] * 1023.0f); + temp[2] = Float2Int(pNormal[2] * 511.0f); + + Assert(temp[0] >= -1023 && temp[0] <= 1023); + Assert(temp[1] >= -1023 && temp[1] <= 1023); + Assert(temp[2] >= -511 && temp[2] <= 511); + + *pPackedNormal = ((temp[2] & 0x3ff) << 22L) | + ((temp[1] & 0x7ff) << 11L) | + ((temp[0] & 0x7ff) << 0L); + return pPackedNormal; +} + +FORCEINLINE unsigned int* PackNormal_HEND3N(float nx, float ny, float nz, unsigned int* pPackedNormal) +{ + int temp[3]; + + temp[0] = Float2Int(nx * 1023.0f); + temp[1] = Float2Int(ny * 1023.0f); + temp[2] = Float2Int(nz * 511.0f); + + Assert(temp[0] >= -1023 && temp[0] <= 1023); + Assert(temp[1] >= -1023 && temp[1] <= 1023); + Assert(temp[2] >= -511 && temp[2] <= 511); + + *pPackedNormal = ((temp[2] & 0x3ff) << 22L) | + ((temp[1] & 0x7ff) << 11L) | + ((temp[0] & 0x7ff) << 0L); + return pPackedNormal; +} + +FORCEINLINE float* UnpackNormal_SHORT2(const unsigned int* pPackedNormal, float* pNormal, bool bIsTangent = FALSE) +{ + short iX = (*pPackedNormal & 0x0000FFFF); + short iY = (*pPackedNormal & 0xFFFF0000) >> 16; + + float zSign = +1; + if (iX < 0) + { + zSign = -1; + iX = -iX; + } + float tSign = +1; + if (iY < 0) + { + tSign = -1; + iY = -iY; + } + + pNormal[0] = (iX - 16384.0f) / 16384.0f; + pNormal[1] = (iY - 16384.0f) / 16384.0f; + pNormal[2] = zSign * sqrtf(1.0f - (pNormal[0] * pNormal[0] + pNormal[1] * pNormal[1])); + if (bIsTangent) + { + pNormal[3] = tSign; + } + + return pNormal; +} + +FORCEINLINE unsigned int* PackNormal_SHORT2(float nx, float ny, float nz, unsigned int* pPackedNormal, float binormalSign = +1.0f) +{ + nx += 1; + ny += 1; + nx *= 16384.0f; + ny *= 16384.0f; + + nx = max(nx, 1.0f); + ny = max(ny, 1.0f); + nx = min(nx, 32767.0f); + ny = min(ny, 32767.0f); + + if (nz < 0.0f) + nx = -nx; + + ny *= binormalSign; + + short sX = (short)nx; + short sY = (short)ny; + + *pPackedNormal = (sX & 0x0000FFFF) | (sY << 16); + + return pPackedNormal; +} + +FORCEINLINE unsigned int* PackNormal_SHORT2(const float* pNormal, unsigned int* pPackedNormal, float binormalSign = +1.0f) +{ + return PackNormal_SHORT2(pNormal[0], pNormal[1], pNormal[2], pPackedNormal, binormalSign); +} + +FORCEINLINE float* UnpackNormal_UBYTE4(const unsigned int* pPackedNormal, float* pNormal, bool bIsTangent = FALSE) +{ + unsigned char cX, cY; + if (bIsTangent) + { + cX = *pPackedNormal >> 16; + cY = *pPackedNormal >> 24; + } + else + { + cX = *pPackedNormal >> 0; + cY = *pPackedNormal >> 8; + } + + float x = cX - 128.0f; + float y = cY - 128.0f; + float z; + + float zSignBit = x < 0 ? 1.0f : 0.0f; + float tSignBit = y < 0 ? 1.0f : 0.0f; + float zSign = -(2 * zSignBit - 1); + float tSign = -(2 * tSignBit - 1); + + x = x * zSign - zSignBit; + y = y * tSign - tSignBit; + x = x - 64; + y = y - 64; + + float xSignBit = x < 0 ? 1.0f : 0.0f; + float ySignBit = y < 0 ? 1.0f : 0.0f; + float xSign = -(2 * xSignBit - 1); + float ySign = -(2 * ySignBit - 1); + + x = (x * xSign - xSignBit) / 63.0f; + y = (y * ySign - ySignBit) / 63.0f; + z = 1.0f - x - y; + + float oolen = 1.0f / sqrt(x * x + y * y + z * z); + x *= oolen * xSign; + y *= oolen * ySign; + z *= oolen * zSign; + + pNormal[0] = x; + pNormal[1] = y; + pNormal[2] = z; + if (bIsTangent) + { + pNormal[3] = tSign; + } + + return pNormal; +} + +FORCEINLINE unsigned int* PackNormal_UBYTE4(float nx, float ny, float nz, unsigned int* pPackedNormal, bool bIsTangent = false, float binormalSign = +1.0f) +{ + float xSign = nx < 0.0f ? -1.0f : 1.0f; + float ySign = ny < 0.0f ? -1.0f : 1.0f; + float zSign = nz < 0.0f ? -1.0f : 1.0f; + float tSign = binormalSign; + Assert((binormalSign == +1.0f) || (binormalSign == -1.0f)); + + float xSignBit = 0.5f * (1 - xSign); + float ySignBit = 0.5f * (1 - ySign); + float zSignBit = 0.5f * (1 - zSign); + float tSignBit = 0.5f * (1 - binormalSign); + + float absX = xSign * nx; + float absY = ySign * ny; + float absZ = zSign * nz; + + float xbits = absX / (absX + absY + absZ); + float ybits = absY / (absX + absY + absZ); + + xbits *= 63; + ybits *= 63; + + xbits = xbits * xSign - xSignBit; + ybits = ybits * ySign - ySignBit; + xbits += 64.0f; + ybits += 64.0f; + + xbits = xbits * zSign - zSignBit; + ybits = ybits * tSign - tSignBit; + + xbits += 128.0f; + ybits += 128.0f; + + unsigned char cX = (unsigned char)xbits; + unsigned char cY = (unsigned char)ybits; + + if (!bIsTangent) + *pPackedNormal = (cX << 0) | (cY << 8); + else + *pPackedNormal = (cX << 16) | (cY << 24); + + return pPackedNormal; +} + +FORCEINLINE unsigned int* PackNormal_UBYTE4(const float* pNormal, unsigned int* pPackedNormal, bool bIsTangent = false, float binormalSign = +1.0f) +{ + return PackNormal_UBYTE4(pNormal[0], pNormal[1], pNormal[2], pPackedNormal, bIsTangent, binormalSign); +} + + +void RGBtoHSV(const Vector& rgb, Vector& hsv); + + +void HSVtoRGB(const Vector& hsv, Vector& rgb); + + +float FastLog2(float i); +float FastPow2(float i); +float FastPow(float a, float b); +float FastPow10(float i); + +inline bool CloseEnough(float a, float b, float epsilon = EQUAL_EPSILON) +{ + return fabs(a - b) <= epsilon; +} + +inline bool CloseEnough(const Vector& a, const Vector& b, float epsilon = EQUAL_EPSILON) +{ + return fabs(a.x - b.x) <= epsilon && + fabs(a.y - b.y) <= epsilon && + fabs(a.z - b.z) <= epsilon; +} + +bool AlmostEqual(float a, float b, int maxUlps = 10); + +inline bool AlmostEqual(const Vector& a, const Vector& b, int maxUlps = 10) +{ + return AlmostEqual(a.x, b.x, maxUlps) && + AlmostEqual(a.y, b.y, maxUlps) && + AlmostEqual(a.z, b.z, maxUlps); +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/mem.h b/SpyCustom/mem.h new file mode 100644 index 0000000..fc1ae45 --- /dev/null +++ b/SpyCustom/mem.h @@ -0,0 +1,40 @@ +#ifndef TIER0_MEM_H +#define TIER0_MEM_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#ifdef LINUX +#undef offsetof +#define offsetof(s,m) (size_t)&(((s *)0)->m) +#endif + +#include "platform.h" + +#if !defined(STATIC_TIER0) && !defined(_STATIC_LINKED) + +#ifdef TIER0_DLL_EXPORT +# define MEM_INTERFACE DLL_EXPORT +#else +# define MEM_INTERFACE DLL_IMPORT +#endif + +#else + +#define MEM_INTERFACE extern + +#endif + + + +MEM_INTERFACE void* MemAllocScratch(int nMemSize); +MEM_INTERFACE void MemFreeScratch(); + +#ifdef _LINUX +MEM_INTERFACE void ZeroMemory(void* mem, size_t length); +#endif + + +#endif \ No newline at end of file diff --git a/SpyCustom/memalloc.h b/SpyCustom/memalloc.h new file mode 100644 index 0000000..a3463cc --- /dev/null +++ b/SpyCustom/memalloc.h @@ -0,0 +1,567 @@ +#ifndef TIER0_MEMALLOC_H +#define TIER0_MEMALLOC_H + +#ifdef _WIN32 +#pragma once +#endif + +#ifndef POSIX +#endif + +#if defined( _MEMTEST ) +#ifdef _WIN32 +#define USE_MEM_DEBUG 1 +#endif +#endif + +#define MEM_DEBUG_CLASSNAME 1 + +#include +#if defined( OSX ) +#include +#endif + +#include "mem.h" + +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + +struct _CrtMemState; + +#define MEMALLOC_VERSION 1 + +typedef size_t(*MemAllocFailHandler_t)(size_t); + +class IMemAlloc +{ +public: + virtual void* Alloc(size_t nSize) = 0; + virtual void* Realloc(void* pMem, size_t nSize) = 0; + virtual void Free(void* pMem) = 0; + virtual void* Expand_NoLongerSupported(void* pMem, size_t nSize) = 0; + + virtual void* Alloc(size_t nSize, const char* pFileName, int nLine) = 0; + virtual void* Realloc(void* pMem, size_t nSize, const char* pFileName, int nLine) = 0; + virtual void Free(void* pMem, const char* pFileName, int nLine) = 0; + virtual void* Expand_NoLongerSupported(void* pMem, size_t nSize, const char* pFileName, int nLine) = 0; + + virtual size_t GetSize(void* pMem) = 0; + + virtual void PushAllocDbgInfo(const char* pFileName, int nLine) = 0; + virtual void PopAllocDbgInfo() = 0; + + virtual long CrtSetBreakAlloc(long lNewBreakAlloc) = 0; + virtual int CrtSetReportMode(int nReportType, int nReportMode) = 0; + virtual int CrtIsValidHeapPointer(const void* pMem) = 0; + virtual int CrtIsValidPointer(const void* pMem, unsigned int size, int access) = 0; + virtual int CrtCheckMemory(void) = 0; + virtual int CrtSetDbgFlag(int nNewFlag) = 0; + virtual void CrtMemCheckpoint(_CrtMemState* pState) = 0; + + virtual void DumpStats() = 0; + virtual void DumpStatsFileBase(char const* pchFileBase) = 0; + + virtual void* CrtSetReportFile(int nRptType, void* hFile) = 0; + virtual void* CrtSetReportHook(void* pfnNewHook) = 0; + virtual int CrtDbgReport(int nRptType, const char* szFile, + int nLine, const char* szModule, const char* pMsg) = 0; + + virtual int heapchk() = 0; + + virtual bool IsDebugHeap() = 0; + + virtual void GetActualDbgInfo(const char*& pFileName, int& nLine) = 0; + virtual void RegisterAllocation(const char* pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime) = 0; + virtual void RegisterDeallocation(const char* pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime) = 0; + + virtual int GetVersion() = 0; + + virtual void CompactHeap() = 0; + + virtual MemAllocFailHandler_t SetAllocFailHandler(MemAllocFailHandler_t pfnMemAllocFailHandler) = 0; + + virtual void DumpBlockStats(void*) = 0; + +#if defined( _MEMTEST ) + virtual void SetStatsExtraInfo(const char* pMapName, const char* pComment) = 0; +#endif + + virtual size_t MemoryAllocFailed() = 0; + + virtual uint32 GetDebugInfoSize() = 0; + virtual void SaveDebugInfo(void* pvDebugInfo) = 0; + virtual void RestoreDebugInfo(const void* pvDebugInfo) = 0; + virtual void InitDebugInfo(void* pvDebugInfo, const char* pchRootFileName, int nLine) = 0; + + virtual void GlobalMemoryStatus(size_t* pUsedMemory, size_t* pFreeMemory) = 0; +}; + +MEM_INTERFACE IMemAlloc* g_pMemAlloc; + +#ifdef MEMALLOC_REGIONS +#ifndef MEMALLOC_REGION +#define MEMALLOC_REGION 0 +#endif +inline void* MemAlloc_Alloc(size_t nSize) +{ + return g_pMemAlloc->RegionAlloc(MEMALLOC_REGION, nSize); +} + +inline void* MemAlloc_Alloc(size_t nSize, const char* pFileName, int nLine) +{ + return g_pMemAlloc->RegionAlloc(MEMALLOC_REGION, nSize, pFileName, nLine); +} +#else +#undef MEMALLOC_REGION +inline void* MemAlloc_Alloc(size_t nSize) +{ + return g_pMemAlloc->Alloc(nSize); +} + +inline void* MemAlloc_Alloc(size_t nSize, const char* pFileName, int nLine) +{ + return g_pMemAlloc->Alloc(nSize, pFileName, nLine); +} +#endif +inline void MemAlloc_Free(void* ptr) +{ + g_pMemAlloc->Free(ptr); +} +inline void MemAlloc_Free(void* ptr, const char* pFileName, int nLine) +{ + g_pMemAlloc->Free(ptr, pFileName, nLine); +} + +inline bool ValueIsPowerOfTwo(size_t value) +{ + return (value & (value - 1)) == 0; +} + +inline void* MemAlloc_AllocAligned(size_t size, size_t align) +{ + unsigned char* pAlloc, * pResult; + + if (!IsPowerOfTwo(align)) + return NULL; + + align = (align > sizeof(void*) ? align : sizeof(void*)) - 1; + + if ((pAlloc = (unsigned char*)g_pMemAlloc->Alloc(sizeof(void*) + align + size)) == (unsigned char*)NULL) + return NULL; + + pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align); + ((unsigned char**)(pResult))[-1] = pAlloc; + + return (void*)pResult; +} + +inline void* MemAlloc_AllocAligned(size_t size, size_t align, const char* pszFile, int nLine) +{ + unsigned char* pAlloc, * pResult; + + if (!IsPowerOfTwo(align)) + return NULL; + + align = (align > sizeof(void*) ? align : sizeof(void*)) - 1; + + if ((pAlloc = (unsigned char*)g_pMemAlloc->Alloc(sizeof(void*) + align + size, pszFile, nLine)) == (unsigned char*)NULL) + return NULL; + + pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align); + ((unsigned char**)(pResult))[-1] = pAlloc; + + return (void*)pResult; +} + +inline void* MemAlloc_AllocAlignedUnattributed(size_t size, size_t align) +{ + unsigned char* pAlloc, * pResult; + + if (!ValueIsPowerOfTwo(align)) + return NULL; + + align = (align > sizeof(void*) ? align : sizeof(void*)) - 1; + + if ((pAlloc = (unsigned char*)MemAlloc_Alloc(sizeof(void*) + align + size)) == (unsigned char*)NULL) + return NULL; + + pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align); + ((unsigned char**)(pResult))[-1] = pAlloc; + + return (void*)pResult; +} + +inline void* MemAlloc_AllocAlignedFileLine(size_t size, size_t align, const char* pszFile, int nLine) +{ + unsigned char* pAlloc, * pResult; + + if (!ValueIsPowerOfTwo(align)) + return NULL; + + align = (align > sizeof(void*) ? align : sizeof(void*)) - 1; + + if ((pAlloc = (unsigned char*)MemAlloc_Alloc(sizeof(void*) + align + size, pszFile, nLine)) == (unsigned char*)NULL) + return NULL; + + pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align); + ((unsigned char**)(pResult))[-1] = pAlloc; + + return (void*)pResult; +} + +inline void* MemAlloc_ReallocAligned(void* ptr, size_t size, size_t align) +{ + if (!IsPowerOfTwo(align)) + return NULL; + + if (((size_t)ptr & (align - 1)) != 0) + return NULL; + + if (!ptr) + return MemAlloc_AllocAligned(size, align); + + void* pAlloc, * pResult; + + pAlloc = ptr; + pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*)); + pAlloc = *((void**)pAlloc); + + size_t nOffset = (size_t)ptr - (size_t)pAlloc; + size_t nOldSize = g_pMemAlloc->GetSize(pAlloc); + if (nOldSize >= size + nOffset) + return ptr; + + pResult = MemAlloc_AllocAligned(size, align); + memcpy(pResult, ptr, nOldSize - nOffset); + g_pMemAlloc->Free(pAlloc); + return pResult; +} + +inline void MemAlloc_FreeAligned(void* pMemBlock) +{ + void* pAlloc; + + if (pMemBlock == NULL) + return; + + pAlloc = pMemBlock; + + pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*)); + + pAlloc = *((void**)pAlloc); + g_pMemAlloc->Free(pAlloc); +} + +inline void MemAlloc_FreeAligned(void* pMemBlock, const char* pFileName, int nLine) +{ + void* pAlloc; + + if (pMemBlock == NULL) + return; + + pAlloc = pMemBlock; + + pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*)); + + pAlloc = *((void**)pAlloc); + g_pMemAlloc->Free(pAlloc, pFileName, nLine); +} + +inline size_t MemAlloc_GetSizeAligned(void* pMemBlock) +{ + void* pAlloc; + + if (pMemBlock == NULL) + return 0; + + pAlloc = pMemBlock; + + pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*)); + + pAlloc = *((void**)pAlloc); + return g_pMemAlloc->GetSize(pAlloc) - ((byte*)pMemBlock - (byte*)pAlloc); +} + +#if (defined(_DEBUG) || defined(USE_MEM_DEBUG)) +#define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction memAllocAttributeAlloction( tag, __LINE__ ) +#define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line ) +#define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo() +#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) +#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) +#else +#define MEM_ALLOC_CREDIT_(tag) ((void)0) +#define MemAlloc_PushAllocDbgInfo( pszFile, line ) ((void)0) +#define MemAlloc_PopAllocDbgInfo() ((void)0) +#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0) +#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0) +#endif + +#define MemAlloc_DumpStats() g_pMemAlloc->DumpStats() +#define MemAlloc_CompactHeap() g_pMemAlloc->CompactHeap() +#define MemAlloc_OutOfMemory() g_pMemAlloc->OutOfMemory() +#define MemAlloc_CompactIncremental() g_pMemAlloc->CompactIncremental() +#define MemAlloc_DumpStatsFileBase( _filename ) g_pMemAlloc->DumpStatsFileBase( _filename ) +#define MemAlloc_CrtCheckMemory() g_pMemAlloc->CrtCheckMemory() +#define MemAlloc_GlobalMemoryStatus( _usedMemory, _freeMemory ) g_pMemAlloc->GlobalMemoryStatus( _usedMemory, _freeMemory ) +#define MemAlloc_MemoryAllocFailed() g_pMemAlloc->MemoryAllocFailed() + +#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize() +#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo ) +#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo ) +#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) +#define MemAlloc_GetSize( x ) g_pMemAlloc->GetSize( x ); +class CMemAllocAttributeAlloction +{ +public: + CMemAllocAttributeAlloction(const char* pszFile, int line) + { + MemAlloc_PushAllocDbgInfo(pszFile, line); + } + + ~CMemAllocAttributeAlloction() + { + MemAlloc_PopAllocDbgInfo(); + } +}; + +#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__) + +#if defined(_WIN32) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) ) + +#pragma warning(disable:4290) +#pragma warning(push) +#include + +#if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME) +#define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( typeid(*this).name() ) +#define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name()) +#else +#define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( __FILE__ ) +#define MEM_ALLOC_CLASSNAME(type) (__FILE__) +#endif + +#ifdef _MSC_VER +#define MEM_ALLOC_CREDIT_FUNCTION() MEM_ALLOC_CREDIT_( __FUNCTION__ ) +#else +#define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__) +#endif + +#pragma warning(pop) +#else +#define MEM_ALLOC_CREDIT_CLASS() +#define MEM_ALLOC_CLASSNAME(type) NULL +#define MEM_ALLOC_CREDIT_FUNCTION() +#endif + +#if (defined(_DEBUG) || defined(USE_MEM_DEBUG)) +struct MemAllocFileLine_t +{ + const char* pszFile; + int line; +}; + +#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \ + static CUtlMap g_##tag##Allocs( DefLessFunc( void *) ); \ + static const char *g_psz##tag##Alloc = strcpy( (char *)g_pMemAlloc->Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" ); + +#define MemAlloc_RegisterExternalAllocation( tag, p, size ) \ + if ( !p ) \ + ; \ + else \ + { \ + MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \ + g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \ + if ( fileLine.pszFile != g_psz##tag##Alloc ) \ + { \ + g_##tag##Allocs.Insert( p, fileLine ); \ + } \ + \ + MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \ + } + +#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \ + if ( !p ) \ + ; \ + else \ + { \ + MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \ + CUtlMap::IndexType_t iRecordedFileLine = g_##tag##Allocs.Find( p ); \ + if ( iRecordedFileLine != g_##tag##Allocs.InvalidIndex() ) \ + { \ + fileLine = g_##tag##Allocs[iRecordedFileLine]; \ + g_##tag##Allocs.RemoveAt( iRecordedFileLine ); \ + } \ + \ + MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \ + } + +#else + +#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) +#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0) +#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0) + +#endif + +#elif defined( POSIX ) + +#if defined( OSX ) +inline void* memalign(size_t alignment, size_t size) { void* pTmp = NULL; pTmp = malloc(size); return pTmp; } +#endif + +inline void* _aligned_malloc(size_t nSize, size_t align) { return memalign(align, nSize); } +inline void _aligned_free(void* ptr) { free(ptr); } + +inline void* MemAlloc_Alloc(size_t nSize, const char* pFileName = NULL, int nLine = 0) { return malloc(nSize); } +inline void MemAlloc_Free(void* ptr, const char* pFileName = NULL, int nLine = 0) { free(ptr); } + +inline void* MemAlloc_AllocAligned(size_t size, size_t align, const char* pszFile = NULL, int nLine = 0) { return memalign(align, size); } +inline void* MemAlloc_AllocAlignedFileLine(size_t size, size_t align, const char* pszFile = NULL, int nLine = 0) { return memalign(align, size); } +inline void MemAlloc_FreeAligned(void* pMemBlock, const char* pszFile = NULL, int nLine = 0) { free(pMemBlock); } + +#if defined( OSX ) +inline size_t _msize(void* ptr) { return malloc_size(ptr); } +#else +inline size_t _msize(void* ptr) { return malloc_usable_size(ptr); } +#endif + +inline void* MemAlloc_ReallocAligned(void* ptr, size_t size, size_t align) +{ + void* ptr_new_aligned = memalign(align, size); + + if (ptr_new_aligned) + { + size_t old_size = _msize(ptr); + size_t copy_size = (size < old_size) ? size : old_size; + + memcpy(ptr_new_aligned, ptr, copy_size); + free(ptr); + } + + return ptr_new_aligned; +} +#else +#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize() +#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo ) +#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo ) +#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) + +#endif + +#if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE) + +#define MEM_ALLOC_CREDIT_(tag) ((void)0) +#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__) +#define MEM_ALLOC_CREDIT_FUNCTION() +#define MEM_ALLOC_CREDIT_CLASS() +#define MEM_ALLOC_CLASSNAME(type) NULL + +#define MemAlloc_PushAllocDbgInfo( pszFile, line ) +#define MemAlloc_PopAllocDbgInfo() +#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0) +#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0) +#define MemAlloc_DumpStats() ((void)0) +#define MemAlloc_CompactHeap() ((void)0) +#define MemAlloc_OutOfMemory() ((void)0) +#define MemAlloc_CompactIncremental() ((void)0) +#define MemAlloc_DumpStatsFileBase( _filename ) ((void)0) +inline bool MemAlloc_CrtCheckMemory() { return true; } +inline void MemAlloc_GlobalMemoryStatus(size_t* pusedMemory, size_t* pfreeMemory) +{ + *pusedMemory = 0; + *pfreeMemory = 0; +} +#define MemAlloc_MemoryAllocFailed() 0 + +#define MemAlloc_GetDebugInfoSize() 0 +#define MemAlloc_SaveDebugInfo( pvDebugInfo ) ((void)0) +#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) ((void)0) +#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) ((void)0) + + +#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) +#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0) +#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0) + +#endif + + + +#if defined( POSIX ) && !defined( NO_HOOK_MALLOC ) +PLATFORM_INTERFACE void MemoryLogMessage(char const* s); +PLATFORM_INTERFACE void EnableMemoryLogging(bool bOnOff); +PLATFORM_INTERFACE void DumpMemoryLog(int nThresh); +PLATFORM_INTERFACE void DumpMemorySummary(void); +PLATFORM_INTERFACE void SetMemoryMark(void); +PLATFORM_INTERFACE void DumpChangedMemory(int nThresh); + +#else +FORCEINLINE void MemoryLogMessage(char const* s) +{ +} + +FORCEINLINE void EnableMemoryLogging(bool bOnOff) +{ +} +FORCEINLINE void DumpMemoryLog(int nThresh) +{ +} +FORCEINLINE void DumpMemorySummary(void) +{ +} +FORCEINLINE void SetMemoryMark(void) +{ +} +FORCEINLINE void DumpChangedMemory(int nThresh) +{ +} + +#endif + +#ifdef POSIX +PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage(void); +#else +FORCEINLINE size_t ApproximateProcessMemoryUsage(void) +{ + return 0; +} + +#endif + +struct aligned_tmp_t +{ +}; + +template< int bytesAlignment = 16, class T = aligned_tmp_t > +class CAlignedNewDelete : public T +{ + +public: + void* operator new(size_t nSize) + { + return MemAlloc_AllocAligned(nSize, bytesAlignment); + } + + void* operator new(size_t nSize, int nBlockUse, const char* pFileName, int nLine) + { + return MemAlloc_AllocAlignedFileLine(nSize, bytesAlignment, pFileName, nLine); + } + + void operator delete(void* pData) + { + if (pData) + { + MemAlloc_FreeAligned(pData); + } + } + + void operator delete(void* pData, int nBlockUse, const char* pFileName, int nLine) + { + if (pData) + { + MemAlloc_FreeAligned(pData, pFileName, nLine); + } + } +}; + + +#endif \ No newline at end of file diff --git a/SpyCustom/memdbgoff.h b/SpyCustom/memdbgoff.h new file mode 100644 index 0000000..4c63e25 --- /dev/null +++ b/SpyCustom/memdbgoff.h @@ -0,0 +1,16 @@ +#ifdef MEM_OVERRIDE_ON + +#undef malloc +#undef realloc +#undef calloc +#undef free +#undef _expand +#undef _msize +#undef new +#undef _aligned_malloc +#undef _aligned_free +#undef _malloc_dbg + +#undef MEM_OVERRIDE_ON + +#endif \ No newline at end of file diff --git a/SpyCustom/memdbgon.h b/SpyCustom/memdbgon.h new file mode 100644 index 0000000..2a72ed9 --- /dev/null +++ b/SpyCustom/memdbgon.h @@ -0,0 +1,219 @@ +#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) + +#if defined(_DEBUG) && !defined(USE_MEM_DEBUG) +#define USE_MEM_DEBUG 1 +#endif + +#if defined(NO_HOOK_MALLOC) +#undef USE_MEM_DEBUG +#endif + +#if (defined(_DEBUG) || !defined(_INC_CRTDBG)) || defined(MEMDBGON_H) + +#include "basetypes.h" +#ifdef _WIN32 +#include +#else +#include +#endif +#include +#include +#include "commonmacros.h" +#include "memalloc.h" + +#if defined(USE_MEM_DEBUG) +#if defined( POSIX ) + +#define _NORMAL_BLOCK 1 + +#include +#include +#include +#include +#if !defined( DID_THE_OPERATOR_NEW ) +#define DID_THE_OPERATOR_NEW +void* operator new(size_t nSize, int blah, const char* pFileName, int nLine); +void* operator new[](size_t nSize, int blah, const char* pFileName, int nLine); +#endif + +#else + +#if !defined(_DEBUG) +#define _DEBUG 1 +#include +#undef _DEBUG +#else +#include +#endif + +#endif +#endif + +#include "memdbgoff.h" + +#define MEM_OVERRIDE_ON 1 + +#undef malloc +#undef realloc +#undef calloc +#undef _expand +#undef free +#undef _msize +#undef _aligned_malloc +#undef _aligned_free + +#ifndef MEMDBGON_H +inline void* MemAlloc_InlineCallocMemset(void* pMem, size_t nCount, size_t nElementSize) +{ + memset(pMem, 0, nElementSize * nCount); + return pMem; +} +#endif + +#define calloc(c, s) MemAlloc_InlineCallocMemset(malloc(c*s), c, s) +#define free(p) g_pMemAlloc->Free( p ) +#define _msize(p) g_pMemAlloc->GetSize( p ) +#define _expand(p, s) _expand_NoLongerSupported(p, s) +#define _aligned_free( p ) MemAlloc_FreeAligned( p ) + +#if defined(USE_MEM_DEBUG) + +#define malloc(s) g_pMemAlloc->Alloc( s, __FILE__, __LINE__) +#define realloc(p, s) g_pMemAlloc->Realloc( p, s, __FILE__, __LINE__ ) +#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a, __FILE__, __LINE__ ) + +#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s) + +#if !defined( LINUX ) +#if defined(__AFX_H__) && defined(DEBUG_NEW) +#define new DEBUG_NEW +#else +#undef new +#define MEMALL_DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) +#define new MEMALL_DEBUG_NEW +#endif +#endif + +#undef _strdup +#undef strdup +#undef _wcsdup +#undef wcsdup + +#define _strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__) +#define strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__) +#define _wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__) +#define wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__) + +#if !defined(MEMDBGON_H) + +inline char* MemAlloc_StrDup(const char* pString, const char* pFileName, unsigned nLine) +{ + char* pMemory; + + if (!pString) + return NULL; + + size_t len = strlen(pString) + 1; + if ((pMemory = (char*)g_pMemAlloc->Alloc(len, pFileName, nLine)) != NULL) + { + return strcpy(pMemory, pString); + } + + return NULL; +} + +inline wchar_t* MemAlloc_WcStrDup(const wchar_t* pString, const char* pFileName, unsigned nLine) +{ + wchar_t* pMemory; + + if (!pString) + return NULL; + + size_t len = (wcslen(pString) + 1); + if ((pMemory = (wchar_t*)g_pMemAlloc->Alloc(len * sizeof(wchar_t), pFileName, nLine)) != NULL) + { + return wcscpy(pMemory, pString); + } + + return NULL; +} + +#endif + +#else +#define malloc(s) g_pMemAlloc->Alloc( s ) +#define realloc(p, s) g_pMemAlloc->Realloc( p, s ) +#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a ) + +#ifndef _malloc_dbg +#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s) +#endif + +#undef new + +#undef _strdup +#undef strdup +#undef _wcsdup +#undef wcsdup + +#define _strdup(s) MemAlloc_StrDup(s) +#define strdup(s) MemAlloc_StrDup(s) +#define _wcsdup(s) MemAlloc_WcStrDup(s) +#define wcsdup(s) MemAlloc_WcStrDup(s) + +#if !defined(MEMDBGON_H) + +inline char* MemAlloc_StrDup(const char* pString) +{ + char* pMemory; + + if (!pString) + return NULL; + + size_t len = strlen(pString) + 1; + if ((pMemory = (char*)g_pMemAlloc->Alloc(len)) != NULL) + { + return strcpy(pMemory, pString); + } + + return NULL; +} + +inline wchar_t* MemAlloc_WcStrDup(const wchar_t* pString) +{ + wchar_t* pMemory; + + if (!pString) + return NULL; + + size_t len = (wcslen(pString) + 1); + if ((pMemory = (wchar_t*)g_pMemAlloc->Alloc(len * sizeof(wchar_t))) != NULL) + { + return wcscpy(pMemory, pString); + } + + return NULL; +} + +#endif + +#endif + +#define MEMDBGON_H + +#else + +#if defined(USE_MEM_DEBUG) +#ifndef _STATIC_LINKED +#pragma message ("Note: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build") +#else +#error "Error: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build. Not recoverable in static build" +#endif +#endif +#endif + +#else + +#include "memalloc.h" + +#endif \ No newline at end of file diff --git a/SpyCustom/mempool.h b/SpyCustom/mempool.h new file mode 100644 index 0000000..2de8dba --- /dev/null +++ b/SpyCustom/mempool.h @@ -0,0 +1,590 @@ +#ifndef MEMPOOL_H +#define MEMPOOL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "memalloc.h" +#include "tslist.h" +#include "platform.h" +#include "utlvector.h" +#include "utlrbtree.h" + +typedef void (*MemoryPoolReportFunc_t)(PRINTF_FORMAT_STRING char const* pMsg, ...); + +class CUtlMemoryPool +{ +public: + enum MemoryPoolGrowType_t + { + GROW_NONE = 0, + GROW_FAST = 1, + GROW_SLOW = 2 + }; + + CUtlMemoryPool(int blockSize, int numElements, int growMode = GROW_FAST, const char* pszAllocOwner = NULL, int nAlignment = 0); + ~CUtlMemoryPool(); + + void* Alloc(); + void* Alloc(size_t amount); + void* AllocZero(); + void* AllocZero(size_t amount); + void Free(void* pMem); + + void Clear(); + + static void SetErrorReportFunc(MemoryPoolReportFunc_t func); + + int Count() const { return m_BlocksAllocated; } + int PeakCount() const { return m_PeakAlloc; } + int BlockSize() const { return m_BlockSize; } + int Size() const; + + bool IsAllocationWithinPool(void* pMem) const; + +protected: + class CBlob + { + public: + CBlob* m_pPrev, * m_pNext; + int m_NumBytes; + char m_Data[1]; + char m_Padding[3]; + }; + + void Init(); + void AddNewBlob(); + void ReportLeaks(); + + int m_BlockSize; + int m_BlocksPerBlob; + + int m_GrowMode; + + int m_BlocksAllocated; + int m_PeakAlloc; + unsigned short m_nAlignment; + unsigned short m_NumBlobs; + void* m_pHeadOfFreeList; + const char* m_pszAllocOwner; + CBlob m_BlobHead; + + static MemoryPoolReportFunc_t g_ReportFunc; +}; + + +class CMemoryPoolMT : public CUtlMemoryPool +{ +public: + CMemoryPoolMT(int blockSize, int numElements, int growMode = GROW_FAST, const char* pszAllocOwner = NULL, int nAlignment = 0) : CUtlMemoryPool(blockSize, numElements, growMode, pszAllocOwner, nAlignment) {} + + + void* Alloc() { AUTO_LOCK(m_mutex); return CUtlMemoryPool::Alloc(); } + void* Alloc(size_t amount) { AUTO_LOCK(m_mutex); return CUtlMemoryPool::Alloc(amount); } + void* AllocZero() { AUTO_LOCK(m_mutex); return CUtlMemoryPool::AllocZero(); } + void* AllocZero(size_t amount) { AUTO_LOCK(m_mutex); return CUtlMemoryPool::AllocZero(amount); } + void Free(void* pMem) { AUTO_LOCK(m_mutex); CUtlMemoryPool::Free(pMem); } + + void Clear() { AUTO_LOCK(m_mutex); return CUtlMemoryPool::Clear(); } +private: + CThreadFastMutex m_mutex; +}; + + +template< class T > +class CClassMemoryPool : public CUtlMemoryPool +{ +public: + CClassMemoryPool(int numElements, int growMode = GROW_FAST, int nAlignment = 0) : + CUtlMemoryPool(sizeof(T), numElements, growMode, MEM_ALLOC_CLASSNAME(T), nAlignment) {} + + T* Alloc(); + T* AllocZero(); + void Free(T* pMem); + + void Clear(); +}; + +template +class CAlignedMemPool +{ + enum + { + BLOCK_SIZE = COMPILETIME_MAX(ALIGN_VALUE(ITEM_SIZE, ALIGNMENT), 8), + }; + +public: + CAlignedMemPool(); + + void* Alloc(); + void Free(void* p); + + static int __cdecl CompareChunk(void* const* ppLeft, void* const* ppRight); + void Compact(); + + int NumTotal() { AUTO_LOCK(m_mutex); return m_Chunks.Count() * (CHUNK_SIZE / BLOCK_SIZE); } + int NumAllocated() { AUTO_LOCK(m_mutex); return NumTotal() - m_nFree; } + int NumFree() { AUTO_LOCK(m_mutex); return m_nFree; } + + int BytesTotal() { AUTO_LOCK(m_mutex); return NumTotal() * BLOCK_SIZE; } + int BytesAllocated() { AUTO_LOCK(m_mutex); return NumAllocated() * BLOCK_SIZE; } + int BytesFree() { AUTO_LOCK(m_mutex); return NumFree() * BLOCK_SIZE; } + + int ItemSize() { return ITEM_SIZE; } + int BlockSize() { return BLOCK_SIZE; } + int ChunkSize() { return CHUNK_SIZE; } + +private: + struct FreeBlock_t + { + FreeBlock_t* pNext; + byte reserved[BLOCK_SIZE - sizeof(FreeBlock_t*)]; + }; + + CUtlVector m_Chunks; + FreeBlock_t* m_pFirstFree; + int m_nFree; + CAllocator m_Allocator; + double m_TimeLastCompact; + + CThreadFastMutex m_mutex; +}; + +template +class CObjectPool +{ +public: + CObjectPool() + { + int i = nInitialCount; + while (i-- > 0) + { + m_AvailableObjects.PushItem(new T); + } + } + + ~CObjectPool() + { + Purge(); + } + + int NumAvailable() + { + return m_AvailableObjects.Count(); + } + + void Purge() + { + T* p = NULL; + while (m_AvailableObjects.PopItem(&p)) + { + delete p; + } + } + + T* GetObject(bool bCreateNewIfEmpty = bDefCreateNewIfEmpty) + { + T* p = NULL; + if (!m_AvailableObjects.PopItem(&p)) + { + p = (bCreateNewIfEmpty) ? new T : NULL; + } + return p; + } + + void PutObject(T* p) + { + m_AvailableObjects.PushItem(p); + } + +private: + CTSList m_AvailableObjects; +}; + +template +class CFixedBudgetMemoryPool +{ +public: + CFixedBudgetMemoryPool() + { + m_pBase = m_pLimit = 0; + COMPILE_TIME_ASSERT(ITEM_SIZE % 4 == 0); + } + + bool Owns(void* p) + { + return (p >= m_pBase && p < m_pLimit); + } + + void* Alloc() + { + MEM_ALLOC_CREDIT_CLASS(); +#ifndef USE_MEM_DEBUG + if (!m_pBase) + { + LOCAL_THREAD_LOCK(); + if (!m_pBase) + { + byte* pMemory = m_pBase = (byte*)malloc(ITEM_COUNT * ITEM_SIZE); + m_pLimit = m_pBase + (ITEM_COUNT * ITEM_SIZE); + + for (int i = 0; i < ITEM_COUNT; i++) + { + m_freeList.Push((TSLNodeBase_t*)pMemory); + pMemory += ITEM_SIZE; + } + } + } + + void* p = m_freeList.Pop(); + if (p) + return p; +#endif + return malloc(ITEM_SIZE); + } + + void Free(void* p) + { +#ifndef USE_MEM_DEBUG + if (Owns(p)) + m_freeList.Push((TSLNodeBase_t*)p); + else +#endif + free(p); + } + + void Clear() + { +#ifndef USE_MEM_DEBUG + if (m_pBase) + { + free(m_pBase); + } + m_pBase = m_pLimit = 0; + Construct(&m_freeList); +#endif + } + + bool IsEmpty() + { +#ifndef USE_MEM_DEBUG + if (m_pBase && m_freeList.Count() != ITEM_COUNT) + return false; +#endif + return true; + } + + enum + { + ITEM_SIZE = ALIGN_VALUE(PROVIDED_ITEM_SIZE, TSLIST_NODE_ALIGNMENT) + }; + + CTSListBase m_freeList; + byte* m_pBase; + byte* m_pLimit; +}; + +#define BIND_TO_FIXED_BUDGET_POOL( poolName ) \ + inline void* operator new( size_t size ) { return poolName.Alloc(); } \ + inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { return poolName.Alloc(); } \ + inline void operator delete( void* p ) { poolName.Free(p); } \ + inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { poolName.Free(p); } + + +template< class T > +inline T* CClassMemoryPool::Alloc() +{ + T* pRet; + + { + MEM_ALLOC_CREDIT_CLASS(); + pRet = (T*)CUtlMemoryPool::Alloc(); + } + + if (pRet) + { + Construct(pRet); + } + return pRet; +} + +template< class T > +inline T* CClassMemoryPool::AllocZero() +{ + T* pRet; + + { + MEM_ALLOC_CREDIT_CLASS(); + pRet = (T*)CUtlMemoryPool::AllocZero(); + } + + if (pRet) + { + Construct(pRet); + } + return pRet; +} + +template< class T > +inline void CClassMemoryPool::Free(T* pMem) +{ + if (pMem) + { + Destruct(pMem); + } + + CUtlMemoryPool::Free(pMem); +} + +template< class T > +inline void CClassMemoryPool::Clear() +{ + CUtlRBTree freeBlocks; + SetDefLessFunc(freeBlocks); + + void* pCurFree = m_pHeadOfFreeList; + while (pCurFree != NULL) + { + freeBlocks.Insert(pCurFree); + pCurFree = *((void**)pCurFree); + } + + for (CBlob* pCur = m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur = pCur->m_pNext) + { + int nElements = pCur->m_NumBytes / this->m_BlockSize; + T* p = (T*)AlignValue(pCur->m_Data, this->m_nAlignment); + T* pLimit = p + nElements; + while (p < pLimit) + { + if (freeBlocks.Find(p) == freeBlocks.InvalidIndex()) + { + Destruct(p); + } + p++; + } + } + + CUtlMemoryPool::Clear(); +} + + + + + +#define DECLARE_FIXEDSIZE_ALLOCATOR( _class ) \ + public: \ + inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ + inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ + inline void operator delete( void* p ) { s_Allocator.Free(p); } \ + inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \ + private: \ + static CUtlMemoryPool s_Allocator + +#define DEFINE_FIXEDSIZE_ALLOCATOR( _class, _initsize, _grow ) \ + CUtlMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool") + +#define DEFINE_FIXEDSIZE_ALLOCATOR_ALIGNED( _class, _initsize, _grow, _alignment ) \ + CUtlMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool", _alignment ) + +#define DECLARE_FIXEDSIZE_ALLOCATOR_MT( _class ) \ + public: \ + inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ + inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ + inline void operator delete( void* p ) { s_Allocator.Free(p); } \ + inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \ + private: \ + static CMemoryPoolMT s_Allocator + +#define DEFINE_FIXEDSIZE_ALLOCATOR_MT( _class, _initsize, _grow ) \ + CMemoryPoolMT _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool") + +#define DECLARE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class ) \ + public: \ + inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \ + inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \ + inline void operator delete( void* p ) { s_pAllocator->Free(p); } \ + private: \ + static CUtlMemoryPool* s_pAllocator + +#define DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class, _allocator ) \ + CUtlMemoryPool* _class::s_pAllocator = _allocator + + +template +inline CAlignedMemPool::CAlignedMemPool() + : m_pFirstFree(0), + m_nFree(0), + m_TimeLastCompact(0) +{ + { COMPILE_TIME_ASSERT(sizeof(FreeBlock_t) >= BLOCK_SIZE); } + { COMPILE_TIME_ASSERT(ALIGN_VALUE(sizeof(FreeBlock_t), ALIGNMENT) == sizeof(FreeBlock_t)); } +} + +template +inline void* CAlignedMemPool::Alloc() +{ + AUTO_LOCK(m_mutex); + + if (!m_pFirstFree) + { + if (!GROWMODE && m_Chunks.Count()) + { + return NULL; + } + + FreeBlock_t* pNew = (FreeBlock_t*)m_Allocator.Alloc(CHUNK_SIZE); + Assert((unsigned)pNew % ALIGNMENT == 0); + m_Chunks.AddToTail(pNew); + m_nFree = CHUNK_SIZE / BLOCK_SIZE; + m_pFirstFree = pNew; + for (int i = 0; i < m_nFree - 1; i++) + { + pNew->pNext = pNew + 1; + pNew++; + } + pNew->pNext = NULL; + } + + void* p = m_pFirstFree; + m_pFirstFree = m_pFirstFree->pNext; + m_nFree--; + + return p; +} + +template +inline void CAlignedMemPool::Free(void* p) +{ + AUTO_LOCK(m_mutex); + + FreeBlock_t* pFree = ((FreeBlock_t*)p); + FreeBlock_t* pCur = m_pFirstFree; + FreeBlock_t* pPrev = NULL; + + while (pCur && pFree > pCur) + { + pPrev = pCur; + pCur = pCur->pNext; + } + + pFree->pNext = pCur; + + if (pPrev) + { + pPrev->pNext = pFree; + } + else + { + m_pFirstFree = pFree; + } + m_nFree++; + + if (m_nFree >= (CHUNK_SIZE / BLOCK_SIZE) * COMPACT_THRESHOLD) + { + double time = Plat_FloatTime(); + double compactTime = (m_nFree >= (CHUNK_SIZE / BLOCK_SIZE) * COMPACT_THRESHOLD * 4) ? 15.0 : 30.0; + if (m_TimeLastCompact > time || m_TimeLastCompact + compactTime < time) + { + Compact(); + m_TimeLastCompact = time; + } + } +} + +template +inline void CAlignedMemPool::Compact() +{ + FreeBlock_t* pCur = m_pFirstFree; + FreeBlock_t* pPrev = NULL; + + m_Chunks.Sort(CompareChunk); + +#ifdef VALIDATE_ALIGNED_MEM_POOL + { + FreeBlock_t* p = m_pFirstFree; + while (p) + { + if (p->pNext && p > p->pNext) + { + __asm { int 3 } + } + p = p->pNext; + } + + for (int i = 0; i < m_Chunks.Count(); i++) + { + if (i + 1 < m_Chunks.Count()) + { + if (m_Chunks[i] > m_Chunks[i + 1]) + { + __asm { int 3 } + } + } + } + } +#endif + + int i; + + for (i = 0; i < m_Chunks.Count(); i++) + { + int nBlocksPerChunk = CHUNK_SIZE / BLOCK_SIZE; + FreeBlock_t* pChunkLimit = ((FreeBlock_t*)m_Chunks[i]) + nBlocksPerChunk; + int nFromChunk = 0; + if (pCur == m_Chunks[i]) + { + FreeBlock_t* pFirst = pCur; + while (pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit) + { + pCur = pCur->pNext; + nFromChunk++; + } + pCur = pFirst; + + } + + while (pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit) + { + if (nFromChunk != nBlocksPerChunk) + { + if (pPrev) + { + pPrev->pNext = pCur; + } + else + { + m_pFirstFree = pCur; + } + pPrev = pCur; + } + else if (pPrev) + { + pPrev->pNext = NULL; + } + else + { + m_pFirstFree = NULL; + } + + pCur = pCur->pNext; + } + + if (nFromChunk == nBlocksPerChunk) + { + m_Allocator.Free(m_Chunks[i]); + m_nFree -= nBlocksPerChunk; + m_Chunks[i] = 0; + } + } + + for (i = m_Chunks.Count() - 1; i >= 0; i--) + { + if (!m_Chunks[i]) + { + m_Chunks.FastRemove(i); + } + } +} + +#endif diff --git a/SpyCustom/meshreader.h b/SpyCustom/meshreader.h new file mode 100644 index 0000000..6fa8d7a --- /dev/null +++ b/SpyCustom/meshreader.h @@ -0,0 +1,231 @@ +#ifndef MESHREADER_H +#define MESHREADER_H + +#ifdef _WIN32 +#pragma once +#endif + + +class CBaseMeshReader : protected MeshDesc_t +{ +public: + + CBaseMeshReader(); + ~CBaseMeshReader(); + + void BeginRead( + IMesh* pMesh, + int firstVertex = 0, + int numVertices = 0, + int firstIndex = 0, + int numIndices = 0); + + void EndRead(); + + void BeginRead_Direct(const MeshDesc_t& desc, int numVertices, int nIndices); + + void Reset(); + + +protected: + IMesh* m_pMesh; + int m_MaxVertices; + int m_MaxIndices; +}; + + +class CMeshReader : public CBaseMeshReader +{ +public: +public: + int NumIndices() const; + unsigned short Index(int index) const; + + const Vector& Position(int iVertex) const; + + unsigned int Color(int iVertex) const; + + const float* TexCoord(int iVertex, int stage) const; + void TexCoord2f(int iVertex, int stage, float& s, float& t) const; + const Vector2D& TexCoordVector2D(int iVertex, int stage) const; + + int NumBoneWeights() const; + float Wrinkle(int iVertex) const; + + const Vector& Normal(int iVertex) const; + void Normal(int iVertex, Vector& vNormal) const; + + const Vector& TangentS(int iVertex) const; + const Vector& TangentT(int iVertex) const; + float BoneWeight(int iVertex) const; + +#ifdef NEW_SKINNING + float* BoneMatrix(int iVertex) const; +#else + unsigned char* BoneMatrix(int iVertex) const; +#endif +}; + + +inline CBaseMeshReader::CBaseMeshReader() +{ + m_pMesh = NULL; +} + +inline CBaseMeshReader::~CBaseMeshReader() +{ + Assert(!m_pMesh); +} + +inline void CBaseMeshReader::BeginRead( + IMesh* pMesh, + int firstVertex, + int numVertices, + int firstIndex, + int numIndices) +{ + Assert(pMesh && (!m_pMesh)); + + if (numVertices < 0) + { + numVertices = pMesh->VertexCount(); + } + + if (numIndices < 0) + { + numIndices = pMesh->IndexCount(); + } + + m_pMesh = pMesh; + m_MaxVertices = numVertices; + m_MaxIndices = numIndices; + + VertexCompressionType_t compressionType = CompressionType(pMesh->GetVertexFormat()); + Assert(compressionType == VERTEX_COMPRESSION_NONE); + if (compressionType != VERTEX_COMPRESSION_NONE) + { + Warning("Cannot use CBaseMeshReader with compressed vertices! Will get junk data or a crash.\n"); + } + + pMesh->ModifyBeginEx(true, firstVertex, numVertices, firstIndex, numIndices, *this); + + Reset(); +} + +inline void CBaseMeshReader::EndRead() +{ + Assert(m_pMesh); + m_pMesh->ModifyEnd(*this); + m_pMesh = NULL; +} + +inline void CBaseMeshReader::BeginRead_Direct(const MeshDesc_t& desc, int nVertices, int nIndices) +{ + MeshDesc_t* pThis = this; + *pThis = desc; + m_MaxVertices = nVertices; + m_MaxIndices = nIndices; + + Assert(desc.m_CompressionType == VERTEX_COMPRESSION_NONE); + if (desc.m_CompressionType != VERTEX_COMPRESSION_NONE) + { + Warning("Cannot use CBaseMeshReader with compressed vertices!\n"); + } +} + +inline void CBaseMeshReader::Reset() +{ +} + + + + +inline int CMeshReader::NumIndices() const +{ + return m_MaxIndices; +} + +inline unsigned short CMeshReader::Index(int index) const +{ + Assert((index >= 0) && (index < m_MaxIndices)); + return m_pIndices[index * m_nIndexSize]; +} + +inline const Vector& CMeshReader::Position(int iVertex) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + return *(Vector*)((char*)m_pPosition + iVertex * m_VertexSize_Position); +} + +inline unsigned int CMeshReader::Color(int iVertex) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + unsigned char* pColor = m_pColor + iVertex * m_VertexSize_Color; + return (pColor[0] << 16) | (pColor[1] << 8) | (pColor[2]) | (pColor[3] << 24); +} + +inline const float* CMeshReader::TexCoord(int iVertex, int iStage) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + return (float*)((char*)m_pTexCoord[iStage] + iVertex * m_VertexSize_TexCoord[iStage]); +} + +inline void CMeshReader::TexCoord2f(int iVertex, int iStage, float& s, float& t) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + float* p = (float*)((char*)m_pTexCoord[iStage] + iVertex * m_VertexSize_TexCoord[iStage]); + s = p[0]; + t = p[1]; +} + +inline const Vector2D& CMeshReader::TexCoordVector2D(int iVertex, int iStage) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + Vector2D* p = (Vector2D*)((char*)m_pTexCoord[iStage] + iVertex * m_VertexSize_TexCoord[iStage]); + return *p; +} + +inline float CMeshReader::Wrinkle(int iVertex) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + return *(float*)((char*)m_pWrinkle + iVertex * m_VertexSize_Wrinkle); +} + +inline int CMeshReader::NumBoneWeights() const +{ + return m_NumBoneWeights; +} + +inline const Vector& CMeshReader::Normal(int iVertex) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + return *(const Vector*)(const float*)((char*)m_pNormal + iVertex * m_VertexSize_Normal); +} + +inline void CMeshReader::Normal(int iVertex, Vector& vNormal) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + const float* p = (const float*)((char*)m_pNormal + iVertex * m_VertexSize_Normal); + vNormal.Init(p[0], p[1], p[2]); +} + +inline const Vector& CMeshReader::TangentS(int iVertex) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + return *(const Vector*)((char*)m_pTangentS + iVertex * m_VertexSize_TangentS); +} + +inline const Vector& CMeshReader::TangentT(int iVertex) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + return *(const Vector*)((char*)m_pTangentT + iVertex * m_VertexSize_TangentT); +} + +inline float CMeshReader::BoneWeight(int iVertex) const +{ + Assert(iVertex >= 0 && iVertex < m_MaxVertices); + float* p = (float*)((char*)m_pBoneWeight + iVertex * m_VertexSize_BoneWeight); + return *p; +} + +#endif diff --git a/SpyCustom/meshutils.h b/SpyCustom/meshutils.h new file mode 100644 index 0000000..3c354eb --- /dev/null +++ b/SpyCustom/meshutils.h @@ -0,0 +1,16 @@ +#ifndef MESHUTILS_H +#define MESHUTILS_H + +#ifdef _WIN32 +#pragma once +#endif + + +void GenerateSequentialIndexBuffer(unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex); +void GenerateQuadIndexBuffer(unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex); +void GeneratePolygonIndexBuffer(unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex); +void GenerateLineStripIndexBuffer(unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex); +void GenerateLineLoopIndexBuffer(unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex); + + +#endif \ No newline at end of file diff --git a/SpyCustom/messagebox.h b/SpyCustom/messagebox.h new file mode 100644 index 0000000..9fec7a7 --- /dev/null +++ b/SpyCustom/messagebox.h @@ -0,0 +1,74 @@ +#ifndef MESSAGEBOX_H +#define MESSAGEBOX_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui.h" +#include "Frame.h" + +#ifdef MessageBox +#undef MessageBox +#endif + +namespace vgui +{ + + class MessageBox : public Frame + { + DECLARE_CLASS_SIMPLE(MessageBox, Frame); + + public: + MessageBox(const char* title, const char* text, Panel* parent = NULL); + MessageBox(const wchar_t* wszTitle, const wchar_t* wszText, Panel* parent = NULL); + ~MessageBox(); + + virtual void DoModal(Frame* pFrameOver = NULL); + + virtual void ShowWindow(Frame* pFrameOver = NULL); + + virtual void SetCommand(const char* command); + virtual void SetCommand(KeyValues* command); + + virtual void SetOKButtonVisible(bool state); + + virtual void SetOKButtonText(const char* buttonText); + virtual void SetOKButtonText(const wchar_t* wszButtonText); + + void SetCancelButtonVisible(bool state); + void SetCancelButtonText(const char* buttonText); + void SetCancelButtonText(const wchar_t* wszButtonText); + void SetCancelCommand(KeyValues* command); + + virtual void DisableCloseButton(bool state); + + virtual void OnCommand(const char* pCommand); + + void ShowMessageBoxOverCursor(bool bEnable); + + protected: + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme* pScheme); + + protected: + Button* m_pOkButton; + Button* m_pCancelButton; + Label* m_pMessageLabel; + + private: + MESSAGE_FUNC(OnShutdownRequest, "ShutdownRequest"); + + void Init(); + + KeyValues* m_OkCommand; + KeyValues* m_CancelCommand; + vgui::Frame* m_pFrameOver; + bool m_bNoAutoClose : 1; + bool m_bShowMessageBoxOverCursor : 1; + }; + +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/minidump.h b/SpyCustom/minidump.h new file mode 100644 index 0000000..5338a83 --- /dev/null +++ b/SpyCustom/minidump.h @@ -0,0 +1,57 @@ +#ifndef MINIDUMP_H +#define MINIDUMP_H +#ifdef _WIN32 +#pragma once +#endif + +#include "platform.h" + +PLATFORM_INTERFACE void SetMinidumpFilenamePrefix(const char* pszPrefix); + +PLATFORM_INTERFACE void SetMinidumpComment(const char* pszComment); + +PLATFORM_INTERFACE void WriteMiniDump(const char* pszFilenameSuffix = NULL); + +typedef void (*FnWMain)(int, tchar* []); +typedef void (*FnVoidPtrFn)(void*); + +#if defined(_WIN32) && !defined(_X360) + +typedef void (*FnWMain)(int, tchar* []); +typedef int (*FnWMainIntRet)(int, tchar* []); +typedef void (*FnVoidPtrFn)(void*); + +enum ECatchAndWriteMinidumpAction +{ + k_ECatchAndWriteMiniDumpAbort = 0, + k_ECatchAndWriteMiniDumpReThrow = 1, + k_ECatchAndWriteMiniDumpIgnore = 2, +}; + +PLATFORM_INTERFACE void CatchAndWriteMiniDump(FnWMain pfn, int argc, tchar* argv[]); +PLATFORM_INTERFACE void CatchAndWriteMiniDumpForVoidPtrFn(FnVoidPtrFn pfn, void* pv, bool bExitQuietly); + +PLATFORM_INTERFACE void CatchAndWriteMiniDumpEx(FnWMain pfn, int argc, tchar* argv[], ECatchAndWriteMinidumpAction eAction); +PLATFORM_INTERFACE int CatchAndWriteMiniDumpExReturnsInt(FnWMainIntRet pfn, int argc, tchar* argv[], ECatchAndWriteMinidumpAction eAction); +PLATFORM_INTERFACE void CatchAndWriteMiniDumpExForVoidPtrFn(FnVoidPtrFn pfn, void* pv, ECatchAndWriteMinidumpAction eAction); + +struct _EXCEPTION_POINTERS; + +typedef void (*FnMiniDump)(unsigned int uStructuredExceptionCode, _EXCEPTION_POINTERS* pExceptionInfo, const char* pszFilenameSuffix); +PLATFORM_INTERFACE FnMiniDump SetMiniDumpFunction(FnMiniDump pfn); + +PLATFORM_INTERFACE bool WriteMiniDumpUsingExceptionInfo( + unsigned int uStructuredExceptionCode, + _EXCEPTION_POINTERS* pExceptionInfo, + int minidumpType, + const char* pszFilenameSuffix = NULL, + tchar* ptchMinidumpFileNameBuffer = NULL +); + +PLATFORM_INTERFACE void MinidumpSetUnhandledExceptionFunction(FnMiniDump pfn); + +PLATFORM_INTERFACE void EnableCrashingOnCrashes(); + +#endif + +#endif \ No newline at end of file diff --git a/SpyCustom/modelloader.h b/SpyCustom/modelloader.h new file mode 100644 index 0000000..42c1a22 --- /dev/null +++ b/SpyCustom/modelloader.h @@ -0,0 +1,148 @@ +#if !defined( MOD_LOADER_H ) +#define MOD_LOADER_H +#ifdef _WIN32 +#pragma once +#endif + +struct model_t; +class IMaterial; +class IFileList; + + +#include "utlmemory.h" + + +abstract_class IModelLoader +{ +public: + enum REFERENCETYPE + { + FMODELLOADER_NOTLOADEDORREFERENCED = 0, + FMODELLOADER_LOADED = (1 << 0), + + FMODELLOADER_SERVER = (1 << 1), + FMODELLOADER_CLIENT = (1 << 2), + FMODELLOADER_CLIENTDLL = (1 << 3), + FMODELLOADER_STATICPROP = (1 << 4), + FMODELLOADER_DETAILPROP = (1 << 5), + FMODELLOADER_REFERENCEMASK = (FMODELLOADER_SERVER | FMODELLOADER_CLIENT | FMODELLOADER_CLIENTDLL | FMODELLOADER_STATICPROP | FMODELLOADER_DETAILPROP), + + FMODELLOADER_TOUCHED_BY_PRELOAD = (1 << 15), + FMODELLOADER_LOADED_BY_PRELOAD = (1 << 16), + FMODELLOADER_TOUCHED_MATERIALS = (1 << 17), + }; + + enum ReloadType_t + { + RELOAD_LOD_CHANGED = 0, + RELOAD_EVERYTHING, + RELOAD_REFRESH_MODELS, + }; + + virtual void Init(void) = 0; + virtual void Shutdown(void) = 0; + + virtual int GetCount(void) = 0; + virtual model_t* GetModelForIndex(int i) = 0; + + virtual const char* GetName(const model_t* model) = 0; + + virtual void* GetExtraData(model_t* model) = 0; + + virtual int GetModelFileSize(const char* name) = 0; + + virtual model_t* GetModelForName(const char* name, REFERENCETYPE referencetype) = 0; + virtual model_t* ReferenceModel(const char* name, REFERENCETYPE referencetype) = 0; + virtual void UnreferenceModel(model_t* model, REFERENCETYPE referencetype) = 0; + virtual void UnreferenceAllModels(REFERENCETYPE referencetype) = 0; + + virtual void UnloadUnreferencedModels(void) = 0; + virtual void PurgeUnusedModels(void) = 0; + + virtual bool Map_GetRenderInfoAllocated(void) = 0; + virtual void Map_SetRenderInfoAllocated(bool allocated) = 0; + + virtual void Map_LoadDisplacements(model_t* model, bool bRestoring) = 0; + + virtual void Print(void) = 0; + + virtual bool Map_IsValid(char const* mapname) = 0; + + virtual void RecomputeSurfaceFlags(model_t* mod) = 0; + + virtual void Studio_ReloadModels(ReloadType_t reloadType) = 0; + + virtual bool IsLoaded(const model_t* mod) = 0; + + virtual bool LastLoadedMapHasHDRLighting(void) = 0; + + virtual void ReloadFilesInList(IFileList* pFilesToReload) = 0; + + virtual const char* GetActiveMapName(void) = 0; +}; + +extern IModelLoader* modelloader; + +class CMapLoadHelper +{ +public: + CMapLoadHelper(int lumpToLoad); + ~CMapLoadHelper(void); + + byte* LumpBase(void); + int LumpSize(void); + int LumpOffset(void); + int LumpVersion() const; + const char* GetMapName(void); + char* GetLoadName(void); + char* GetDiskName(void); + struct worldbrushdata_t* GetMap(void); + + static void Init(model_t* pMapModel, const char* pLoadname); + static void InitFromMemory(model_t* pMapModel, const void* pData, int nDataSize); + static void Shutdown(void); + static int GetRefCount(void); + + static void FreeLightingLump(); + + static int LumpSize(int lumpId); + static int LumpOffset(int lumpId); + + void LoadLumpElement(int nElemIndex, int nElemSize, void* pData); + void LoadLumpData(int offset, int size, void* pData); + +private: + int m_nLumpSize; + int m_nLumpOffset; + int m_nLumpVersion; + byte* m_pRawData; + byte* m_pData; + byte* m_pUncompressedData; + + int m_nLumpID; + char m_szLumpFilename[MAX_PATH]; +}; + +void Mod_RecomputeTranslucency(model_t* mod, int nSkin, int nBody, void * pClientRenderable); + +int Mod_GameLumpSize(int lumpId); +int Mod_GameLumpVersion(int lumpId); +bool Mod_LoadGameLump(int lumpId, void* pBuffer, int size); + +int Mod_GetMaterialCount(model_t* mod); + +int Mod_GetModelMaterials(model_t* mod, int count, IMaterial** ppMaterial); + +bool Mod_MarkWaterSurfaces(model_t* pModel); + +void ConnectMDLCacheNotify(); +void DisconnectMDLCacheNotify(); + +void InitStudioModelState(model_t* pModel); + +char* GetMapNameOnDisk(char* pDiskName, const char* pFullMapName, unsigned int nDiskNameSize); + +extern bool g_bLoadedMapHasBakedPropLighting; +extern bool g_bBakedPropLightingNoSeparateHDR; + +#endif \ No newline at end of file diff --git a/SpyCustom/modes.h b/SpyCustom/modes.h new file mode 100644 index 0000000..21b91f5 --- /dev/null +++ b/SpyCustom/modes.h @@ -0,0 +1,15 @@ +#if !defined( MODES_H ) +#define MODES_H +#ifdef _WIN32 +#pragma once +#endif + +typedef struct vmode_s +{ + int width; + int height; + int bpp; + int refreshRate; +} vmode_t; + +#endif \ No newline at end of file diff --git a/SpyCustom/mouthinfo.h b/SpyCustom/mouthinfo.h new file mode 100644 index 0000000..42ba87d --- /dev/null +++ b/SpyCustom/mouthinfo.h @@ -0,0 +1,178 @@ +#if !defined( MOUTHINFO_H ) +#define MOUTHINFO_H +#ifdef _WIN32 +#pragma once +#endif + +class CAudioSource; + +#pragma pack(push,4) +class CVoiceData +{ +public: + CVoiceData(void) + { + m_flElapsed = 0.0f; + m_pAudioSource = NULL; + m_bIgnorePhonemes = false; + } + + void SetElapsedTime(float t) + { + m_flElapsed = t; + } + + float GetElapsedTime() const + { + return m_flElapsed; + } + + void SetSource(CAudioSource* source, bool bIgnorePhonemes) + { + m_pAudioSource = source; + m_bIgnorePhonemes = bIgnorePhonemes; + } + + bool ShouldIgnorePhonemes() const + { + return m_bIgnorePhonemes; + } + + CAudioSource* GetSource() + { + return m_pAudioSource; + } + +private: + float m_flElapsed; + CAudioSource* m_pAudioSource; + bool m_bIgnorePhonemes; +}; + +#define UNKNOWN_VOICE_SOURCE -1 + +class CMouthInfo +{ +public: + byte mouthopen; + byte sndcount; + int sndavg; + +public: + CMouthInfo(void) { m_nVoiceSources = 0; m_needsEnvelope = false; } + virtual ~CMouthInfo(void) { ClearVoiceSources(); } + + int GetNumVoiceSources(void); + CVoiceData* GetVoiceSource(int number); + + void ClearVoiceSources(void); + int GetIndexForSource(CAudioSource* source); + bool IsSourceReferenced(CAudioSource* source); + + CVoiceData* AddSource(CAudioSource* source, bool bIgnorePhonemes); + + void RemoveSource(CAudioSource* source); + void RemoveSourceByIndex(int index); + + bool IsActive(void); + bool NeedsEnvelope() { return m_needsEnvelope != 0; } + void ActivateEnvelope() { m_needsEnvelope = true; } + +private: + enum + { + MAX_VOICE_DATA = 4 + }; + + short m_nVoiceSources; + short m_needsEnvelope; + CVoiceData m_VoiceSources[MAX_VOICE_DATA]; +}; +#pragma pack(pop) + + +inline bool CMouthInfo::IsActive(void) +{ + return (GetNumVoiceSources() > 0) ? true : false; +} + +inline int CMouthInfo::GetNumVoiceSources(void) +{ + return m_nVoiceSources; +} + +inline CVoiceData* CMouthInfo::GetVoiceSource(int number) +{ + if (number < 0 || number >= m_nVoiceSources) + return NULL; + + return &m_VoiceSources[number]; +} + +inline void CMouthInfo::ClearVoiceSources(void) +{ + m_nVoiceSources = 0; +} + +inline int CMouthInfo::GetIndexForSource(CAudioSource* source) +{ + for (int i = 0; i < m_nVoiceSources; i++) + { + CVoiceData* v = &m_VoiceSources[i]; + if (!v) + continue; + + if (v->GetSource() == source) + return i; + } + + return UNKNOWN_VOICE_SOURCE; +} + +inline bool CMouthInfo::IsSourceReferenced(CAudioSource* source) +{ + if (GetIndexForSource(source) != UNKNOWN_VOICE_SOURCE) + return true; + + return false; +} + +inline void CMouthInfo::RemoveSource(CAudioSource* source) +{ + int idx = GetIndexForSource(source); + if (idx == UNKNOWN_VOICE_SOURCE) + return; + + RemoveSourceByIndex(idx); +} + +inline void CMouthInfo::RemoveSourceByIndex(int index) +{ + if (index < 0 || index >= m_nVoiceSources) + return; + + m_VoiceSources[index] = m_VoiceSources[--m_nVoiceSources]; +} + +inline CVoiceData* CMouthInfo::AddSource(CAudioSource* source, bool bIgnorePhonemes) +{ + int idx = GetIndexForSource(source); + if (idx == UNKNOWN_VOICE_SOURCE) + { + if (m_nVoiceSources < MAX_VOICE_DATA) + { + idx = m_nVoiceSources++; + } + else + { + return NULL; + } + } + + CVoiceData* data = &m_VoiceSources[idx]; + data->SetSource(source, bIgnorePhonemes); + data->SetElapsedTime(0.0f); + return data; +} + +#endif \ No newline at end of file diff --git a/SpyCustom/netchannel.hpp b/SpyCustom/netchannel.hpp new file mode 100644 index 0000000..1218b28 --- /dev/null +++ b/SpyCustom/netchannel.hpp @@ -0,0 +1,36 @@ +#pragma once + +typedef const void(__thiscall* pShutdown)(void*, void*, const char*); +pShutdown oShutdown; +void __fastcall hkShutdown(void* thisptr, void* unk1, void* unk2, const char* reason) noexcept +{ +#ifdef DEBUG + printf("shutdown (%x) HOOKED %s\n", thisptr, reason); +#endif + + if (*g_Options.discmsg_active) { +#ifdef DEBUG + printf("set new reason %s\n", g_Options.discmsg.value->mystring); +#endif + char customreason[256] = "#"; + strcat_s( customreason, MakeControlChars(g_Options.discmsg.value->mystring)); + + oShutdown(thisptr, nullptr, customreason); + } + else + oShutdown(thisptr, nullptr, reason); +} + +inline void HookNetchannel() +{ + DWORD ptrShutdown = *((DWORD*)iff.g_pEngineClient->GetNetChannelInfo()) + 36 * 4; + DWORD addrShutdown = *(DWORD*)ptrShutdown; + oShutdown = (pShutdown)DetourFunction( + (PBYTE)(addrShutdown), + (PBYTE)hkShutdown); +#ifdef DEBUG + printf("Detoured at %x\n", addrShutdown); +#endif + opt.netchannedlhooked = 1; +} + diff --git a/SpyCustom/netvars.cpp b/SpyCustom/netvars.cpp new file mode 100644 index 0000000..c404600 --- /dev/null +++ b/SpyCustom/netvars.cpp @@ -0,0 +1,110 @@ +#include "netvars.hpp" + +#include +#include + +#include "interfaces.hpp" + +void NetvarSys::Initialize() +{ + + m_tables.clear(); + + ClientClass* clientClass = iff.g_pClient->GetAllClasses(); + if (!clientClass) + return; + + while (clientClass) + { + RecvTable* recvTable = clientClass->m_pRecvTable; + m_tables.push_back(recvTable); + + clientClass = clientClass->m_pNext; + } + +} + + +#undef GetProp + +int NetvarSys::GetOffset(const char* tableName, const char* propName) +{ + int offset = this->GetProp(tableName, propName); + if (!offset) + { +#ifdef DEBUG + printf("%s not found!\n", propName); +#endif + return 0; + } +#ifdef DEBUG + printf("%s: 0x%02X\n", propName, offset); +#endif + return offset; +} + + +int NetvarSys::GetProp(const char* tableName, const char* propName, RecvProp** prop) +{ + RecvTable* recvTable = GetTable(tableName); + if (!recvTable) + return 0; + + int offset = this->GetProp(recvTable, propName, prop); + if (!offset) + return 0; + + return offset; +} + + +int NetvarSys::GetProp(RecvTable* recvTable, const char* propName, RecvProp** prop) +{ + int extraOffset = 0; + for (int i = 0; i < recvTable->m_nProps; ++i) + { + RecvProp* recvProp = &recvTable->m_pProps[i]; + RecvTable* child = recvProp->m_pDataTable; + + if (child && (child->m_nProps > 0)) + { + int tmp = this->GetProp(child, propName, prop); + if (tmp) + extraOffset += (recvProp->m_Offset + tmp); + } + + if (_stricmp(recvProp->m_pVarName, propName)) + continue; + + if (prop) + *prop = recvProp; + + return (recvProp->m_Offset + extraOffset); + } + + return extraOffset; +} + +RecvTable* NetvarSys::GetTable(const char* tableName) +{ + if (m_tables.empty()) + return 0; + + for (const auto& table : m_tables) + { + if (!table) + continue; + + if (_stricmp(table->m_pNetTableName, tableName) == 0) + return table; + } + + return 0; +} + + + + + + + diff --git a/SpyCustom/netvars.hpp b/SpyCustom/netvars.hpp new file mode 100644 index 0000000..ec2c533 --- /dev/null +++ b/SpyCustom/netvars.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +#include "dt_recv.h" +#include "Singleton.hpp" + +class NetvarSys + : public Singleton +{ +public: + void Initialize(); + + int GetOffset(const char* tableName, const char* propName); + + RecvTable* GetTable(const char* tableName); + std::vector m_tables; + +private: + int GetProp(const char* tableName, const char* propName, RecvProp** prop = 0); + int GetProp(RecvTable* recvTable, const char* propName, RecvProp** prop = 0); + +}; + + +#define NETVAR_OFFSET2(funcname, class_name, var_name, offset, ...) \ +auto funcname() -> std::add_lvalue_reference_t<__VA_ARGS__> \ +{ \ + static int netvar = NetvarSys::Get().GetOffset(class_name, var_name); \ + auto addr = std::uintptr_t(this) + offset + netvar; \ + return *reinterpret_cast>(addr); \ +} + +#define NETVAR2(funcname, class_name, var_name, ...) \ + NETVAR_OFFSET2(funcname, class_name, var_name, 0, __VA_ARGS__) diff --git a/SpyCustom/networkstringtabledefs.h b/SpyCustom/networkstringtabledefs.h new file mode 100644 index 0000000..396849a --- /dev/null +++ b/SpyCustom/networkstringtabledefs.h @@ -0,0 +1,63 @@ +#ifndef NETWORKSTRINGTABLEDEFS_H +#define NETWORKSTRINGTABLEDEFS_H +#ifdef _WIN32 +#pragma once +#endif + +typedef int TABLEID; + +#define INVALID_STRING_TABLE -1 +const unsigned short INVALID_STRING_INDEX = (unsigned short)-1; + +#define MAX_TABLES 32 + +#define INTERFACENAME_NETWORKSTRINGTABLESERVER "VEngineServerStringTable001" +#define INTERFACENAME_NETWORKSTRINGTABLECLIENT "VEngineClientStringTable001" + +class INetworkStringTable; + +typedef void (*pfnStringChanged)(void* object, INetworkStringTable* stringTable, int stringNumber, char const* newString, void const* newData); + +class INetworkStringTable +{ +public: + + virtual ~INetworkStringTable(void) {}; + + virtual const char* GetTableName(void) const = 0; + virtual TABLEID GetTableId(void) const = 0; + virtual int GetNumStrings(void) const = 0; + virtual int GetMaxStrings(void) const = 0; + virtual int GetEntryBits(void) const = 0; + + virtual void SetTick(int tick) = 0; + virtual bool ChangedSinceTick(int tick) const = 0; + + virtual int AddString(bool bIsServer, const char* value, int length = -1, const void* userdata = 0) = 0; + + virtual const char* GetString(int stringNumber) = 0; + virtual void SetStringUserData(int stringNumber, int length, const void* userdata) = 0; + virtual const void* GetStringUserData(int stringNumber, int* length) = 0; + virtual int FindStringIndex(char const* string) = 0; + + virtual void SetStringChangedCallback(void* object, pfnStringChanged changeFunc) = 0; +}; + +class INetworkStringTableContainer +{ +public: + + virtual ~INetworkStringTableContainer(void) {}; + + virtual INetworkStringTable* CreateStringTable(const char* tableName, int maxentries, int userdatafixedsize = 0, int userdatanetworkbits = 0) = 0; + virtual void RemoveAllTables(void) = 0; + + virtual INetworkStringTable* FindTable(const char* tableName) const = 0; + virtual INetworkStringTable* GetTable(TABLEID stringTable) const = 0; + virtual int GetNumTables(void) const = 0; + + virtual INetworkStringTable* CreateStringTableEx(const char* tableName, int maxentries, int userdatafixedsize = 0, int userdatanetworkbits = 0, bool bIsFilenames = false) = 0; + virtual void SetAllowClientSideAddString(INetworkStringTable* table, bool bAllowClientSideAddString) = 0; +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/networkvar.h b/SpyCustom/networkvar.h new file mode 100644 index 0000000..ff0b261 --- /dev/null +++ b/SpyCustom/networkvar.h @@ -0,0 +1,737 @@ +#ifndef NETWORKVAR_H +#define NETWORKVAR_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "dbg.h" +#include "convar.h" + +#if defined( CLIENT_DLL ) || defined( GAME_DLL ) +#include "basehandle.h" +#endif + + +#pragma warning( disable : 4284 ) + +#define MyOffsetOf( type, var ) ( (int)&((type*)0)->var ) + +#ifdef _DEBUG +extern bool g_bUseNetworkVars; +#define CHECK_USENETWORKVARS if(g_bUseNetworkVars) +#else +#define CHECK_USENETWORKVARS +#endif + + + +inline int InternalCheckDeclareClass(const char* pClassName, const char* pClassNameMatch, void* pTestPtr, void* pBasePtr) +{ + Assert(pTestPtr == pBasePtr); + + Assert((void*)pClassName == (void*)pClassNameMatch); + return 0; +} + + +template +inline int CheckDeclareClass_Access(T*, const char* pShouldBe) +{ + return T::CheckDeclareClass(pShouldBe); +} + +#ifndef _STATIC_LINKED +#ifdef _MSC_VER +#if defined(_DEBUG) && (_MSC_VER > 1200 ) +#define VALIDATE_DECLARE_CLASS 1 +#endif +#endif +#endif + +#ifdef VALIDATE_DECLARE_CLASS + +#define DECLARE_CLASS( className, baseClassName ) \ + typedef baseClassName BaseClass; \ + typedef className ThisClass; \ + template friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ + static int CheckDeclareClass( const char *pShouldBe ) \ + { \ + InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \ + return CheckDeclareClass_Access( (BaseClass *)NULL, #baseClassName ); \ + } + +#define DECLARE_CLASS_GAMEROOT( className, baseClassName ) \ + typedef baseClassName BaseClass; \ + typedef className ThisClass; \ + template friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ + static int CheckDeclareClass( const char *pShouldBe ) \ + { \ + return InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \ + } + +#define DECLARE_CLASS_NOFRIEND( className, baseClassName ) \ + DECLARE_CLASS( className, baseClassName ) + +#define DECLARE_CLASS_NOBASE( className ) \ + typedef className ThisClass; \ + template friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ + static int CheckDeclareClass( const char *pShouldBe ) \ + { \ + return InternalCheckDeclareClass( pShouldBe, #className, 0, 0 ); \ + } + +#else +#define DECLARE_CLASS( className, baseClassName ) \ + typedef baseClassName BaseClass; \ + typedef className ThisClass; + +#define DECLARE_CLASS_GAMEROOT( className, baseClassName ) DECLARE_CLASS( className, baseClassName ) +#define DECLARE_CLASS_NOFRIEND( className, baseClassName ) DECLARE_CLASS( className, baseClassName ) + +#define DECLARE_CLASS_NOBASE( className ) typedef className ThisClass; +#endif + + + + +class CBaseEntity; +class CAutoInitEntPtr +{ +public: + CAutoInitEntPtr() + { + m_pEnt = NULL; + } + CBaseEntity* m_pEnt; +}; + +#define DECLARE_NETWORKVAR_CHAIN() \ + CAutoInitEntPtr __m_pChainEntity; \ + void NetworkStateChanged() { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); } \ + void NetworkStateChanged( void *pVar ) { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); } + +#define IMPLEMENT_NETWORKVAR_CHAIN( varName ) \ + (varName)->__m_pChainEntity.m_pEnt = this; + + + +template< class T > +static inline void DispatchNetworkStateChanged(T* pObj) +{ + CHECK_USENETWORKVARS pObj->NetworkStateChanged(); +} +template< class T > +static inline void DispatchNetworkStateChanged(T* pObj, void* pVar) +{ + CHECK_USENETWORKVARS pObj->NetworkStateChanged(pVar); +} + + +#define DECLARE_EMBEDDED_NETWORKVAR() \ + template friend int ServerClassInit(T *); \ + template friend int ClientClassInit(T *); \ + virtual void NetworkStateChanged() {} virtual void NetworkStateChanged( void *pProp ) {} + +#define CNetworkVarEmbedded( type, name ) \ + class NetworkVar_##name; \ + friend class NetworkVar_##name; \ + static inline int GetOffset_##name() { return MyOffsetOf(ThisClass,name); } \ + typedef ThisClass ThisClass_##name; \ + class NetworkVar_##name : public type \ + { \ + template< class T > NetworkVar_##name& operator=( const T &val ) { *((type*)this) = val; return *this; } \ + public: \ + void CopyFrom( const type &src ) { *((type *)this) = src; NetworkStateChanged(); } \ + virtual void NetworkStateChanged() \ + { \ + DispatchNetworkStateChanged( (ThisClass_##name*)( ((char*)this) - GetOffset_##name() ) ); \ + } \ + virtual void NetworkStateChanged( void *pVar ) \ + { \ + DispatchNetworkStateChanged( (ThisClass_##name*)( ((char*)this) - GetOffset_##name() ), pVar ); \ + } \ + }; \ + NetworkVar_##name name; + +template +FORCEINLINE void NetworkVarConstruct(T& x) { x = T(0); } +FORCEINLINE void NetworkVarConstruct(color32_s& x) { x.r = x.g = x.b = x.a = 0; } + +template< class Type, class Changer > +class CNetworkVarBase +{ +public: + inline CNetworkVarBase() + { + NetworkVarConstruct(m_Value); + } + + template< class C > + const Type& operator=(const C& val) + { + return Set((const Type)val); + } + + template< class C > + const Type& operator=(const CNetworkVarBase< C, Changer >& val) + { + return Set((const Type)val.m_Value); + } + + const Type& Set(const Type& val) + { + if (memcmp(&m_Value, &val, sizeof(Type))) + { + NetworkStateChanged(); + m_Value = val; + } + return m_Value; + } + + Type& GetForModify() + { + NetworkStateChanged(); + return m_Value; + } + + template< class C > + const Type& operator+=(const C& val) + { + return Set(m_Value + (const Type)val); + } + + template< class C > + const Type& operator-=(const C& val) + { + return Set(m_Value - (const Type)val); + } + + template< class C > + const Type& operator/=(const C& val) + { + return Set(m_Value / (const Type)val); + } + + template< class C > + const Type& operator*=(const C& val) + { + return Set(m_Value * (const Type)val); + } + + template< class C > + const Type& operator^=(const C& val) + { + return Set(m_Value ^ (const Type)val); + } + + template< class C > + const Type& operator|=(const C& val) + { + return Set(m_Value | (const Type)val); + } + + const Type& operator++() + { + return (*this += 1); + } + + Type operator--() + { + return (*this -= 1); + } + + Type operator++(int) + { + Type val = m_Value; + (*this += 1); + return val; + } + + Type operator--(int) + { + Type val = m_Value; + (*this -= 1); + return val; + } + + template< class C > + const Type& operator&=(const C& val) + { + return Set(m_Value & (const Type)val); + } + + operator const Type& () const + { + return m_Value; + } + + const Type& Get() const + { + return m_Value; + } + + const Type* operator->() const + { + return &m_Value; + } + + Type m_Value; + +protected: + inline void NetworkStateChanged() + { + Changer::NetworkStateChanged(this); + } +}; + + +template< class Type, class Changer > +class CNetworkColor32Base : public CNetworkVarBase< Type, Changer > +{ +public: + inline void Init(byte rVal, byte gVal, byte bVal) + { + SetR(rVal); + SetG(gVal); + SetB(bVal); + } + inline void Init(byte rVal, byte gVal, byte bVal, byte aVal) + { + SetR(rVal); + SetG(gVal); + SetB(bVal); + SetA(aVal); + } + + const Type& operator=(const Type& val) + { + return this->Set(val); + } + + const Type& operator=(const CNetworkColor32Base& val) + { + return CNetworkVarBase::Set(val.m_Value); + } + + inline byte GetR() const { return CNetworkColor32Base::m_Value.r; } + inline byte GetG() const { return CNetworkColor32Base::m_Value.g; } + inline byte GetB() const { return CNetworkColor32Base::m_Value.b; } + inline byte GetA() const { return CNetworkColor32Base::m_Value.a; } + inline void SetR(byte val) { SetVal(CNetworkColor32Base::m_Value.r, val); } + inline void SetG(byte val) { SetVal(CNetworkColor32Base::m_Value.g, val); } + inline void SetB(byte val) { SetVal(CNetworkColor32Base::m_Value.b, val); } + inline void SetA(byte val) { SetVal(CNetworkColor32Base::m_Value.a, val); } + +protected: + inline void SetVal(byte& out, const byte& in) + { + if (out != in) + { + CNetworkVarBase< Type, Changer >::NetworkStateChanged(); + out = in; + } + } +}; + + +template< class Type, class Changer > +class CNetworkVectorBase : public CNetworkVarBase< Type, Changer > +{ +public: + inline void Init(float ix = 0, float iy = 0, float iz = 0) + { + SetX(ix); + SetY(iy); + SetZ(iz); + } + + const Type& operator=(const Type& val) + { + return CNetworkVarBase< Type, Changer >::Set(val); + } + + const Type& operator=(const CNetworkVectorBase& val) + { + return CNetworkVarBase::Set(val.m_Value); + } + + inline float GetX() const { return CNetworkVectorBase::m_Value.x; } + inline float GetY() const { return CNetworkVectorBase::m_Value.y; } + inline float GetZ() const { return CNetworkVectorBase::m_Value.z; } + inline float operator[](int i) const { return CNetworkVectorBase::m_Value[i]; } + + inline void SetX(float val) { DetectChange(CNetworkVectorBase::m_Value.x, val); } + inline void SetY(float val) { DetectChange(CNetworkVectorBase::m_Value.y, val); } + inline void SetZ(float val) { DetectChange(CNetworkVectorBase::m_Value.z, val); } + inline void Set(int i, float val) { DetectChange(CNetworkVectorBase::m_Value[i], val); } + + bool operator==(const Type& val) const + { + return CNetworkVectorBase::m_Value == (Type)val; + } + + bool operator!=(const Type& val) const + { + return CNetworkVectorBase::m_Value != (Type)val; + } + + const Type operator+(const Type& val) const + { + return CNetworkVectorBase::m_Value + val; + } + + const Type operator-(const Type& val) const + { + return CNetworkVectorBase::m_Value - val; + } + + const Type operator*(const Type& val) const + { + return CNetworkVectorBase::m_Value * val; + } + + const Type& operator*=(float val) + { + return CNetworkVarBase< Type, Changer >::Set(CNetworkVectorBase::m_Value * val); + } + + const Type operator*(float val) const + { + return CNetworkVectorBase::m_Value * val; + } + + const Type operator/(const Type& val) const + { + return CNetworkVectorBase::m_Value / val; + } + +private: + inline void DetectChange(float& out, float in) + { + if (out != in) + { + CNetworkVectorBase::NetworkStateChanged(); + out = in; + } + } +}; + + +template< class Type, class Changer > +class CNetworkQuaternionBase : public CNetworkVarBase< Type, Changer > +{ +public: + inline void Init(float ix = 0, float iy = 0, float iz = 0, float iw = 0) + { + SetX(ix); + SetY(iy); + SetZ(iz); + SetW(iw); + } + + const Type& operator=(const Type& val) + { + return CNetworkVarBase< Type, Changer >::Set(val); + } + + const Type& operator=(const CNetworkQuaternionBase& val) + { + return CNetworkVarBase::Set(val.m_Value); + } + + inline float GetX() const { return CNetworkQuaternionBase::m_Value.x; } + inline float GetY() const { return CNetworkQuaternionBase::m_Value.y; } + inline float GetZ() const { return CNetworkQuaternionBase::m_Value.z; } + inline float GetW() const { return CNetworkQuaternionBase::m_Value.w; } + inline float operator[](int i) const { return CNetworkQuaternionBase::m_Value[i]; } + + inline void SetX(float val) { DetectChange(CNetworkQuaternionBase::m_Value.x, val); } + inline void SetY(float val) { DetectChange(CNetworkQuaternionBase::m_Value.y, val); } + inline void SetZ(float val) { DetectChange(CNetworkQuaternionBase::m_Value.z, val); } + inline void SetW(float val) { DetectChange(CNetworkQuaternionBase::m_Value.w, val); } + inline void Set(int i, float val) { DetectChange(CNetworkQuaternionBase::m_Value[i], val); } + + bool operator==(const Type& val) const + { + return CNetworkQuaternionBase::m_Value == (Type)val; + } + + bool operator!=(const Type& val) const + { + return CNetworkQuaternionBase::m_Value != (Type)val; + } + + const Type operator+(const Type& val) const + { + return CNetworkQuaternionBase::m_Value + val; + } + + const Type operator-(const Type& val) const + { + return CNetworkQuaternionBase::m_Value - val; + } + + const Type operator*(const Type& val) const + { + return CNetworkQuaternionBase::m_Value * val; + } + + const Type& operator*=(float val) + { + return CNetworkQuaternionBase< Type, Changer >::Set(CNetworkQuaternionBase::m_Value * val); + } + + const Type operator*(float val) const + { + return CNetworkQuaternionBase::m_Value * val; + } + + const Type operator/(const Type& val) const + { + return CNetworkQuaternionBase::m_Value / val; + } + +private: + inline void DetectChange(float& out, float in) + { + if (out != in) + { + CNetworkQuaternionBase::NetworkStateChanged(); + out = in; + } + } +}; + + +#if defined( CLIENT_DLL ) || defined( GAME_DLL ) +inline void NetworkVarConstruct(CBaseHandle& x) {} + +template< class Type, class Changer > +class CNetworkHandleBase : public CNetworkVarBase< CBaseHandle, Changer > +{ +public: + const Type* operator=(const Type* val) + { + return Set(val); + } + + const Type& operator=(const CNetworkHandleBase& val) + { + const CBaseHandle& handle = CNetworkVarBase::Set(val.m_Value); + return *(const Type*)handle.Get(); + } + + bool operator !() const + { + return !CNetworkHandleBase::m_Value.Get(); + } + + operator Type* () const + { + return static_cast(CNetworkHandleBase::m_Value.Get()); + } + + const Type* Set(const Type* val) + { + if (CNetworkHandleBase::m_Value != val) + { + this->NetworkStateChanged(); + CNetworkHandleBase::m_Value = val; + } + return val; + } + + Type* Get() const + { + return static_cast(CNetworkHandleBase::m_Value.Get()); + } + + Type* operator->() const + { + return static_cast(CNetworkHandleBase::m_Value.Get()); + } + + bool operator==(const Type* val) const + { + return CNetworkHandleBase::m_Value == val; + } + + bool operator!=(const Type* val) const + { + return CNetworkHandleBase::m_Value != val; + } +}; + +#define CNetworkHandle( type, name ) CNetworkHandleInternal( type, name, NetworkStateChanged ) + +#define CNetworkHandleInternal( type, name, stateChangedFn ) \ + NETWORK_VAR_START( type, name ) \ + NETWORK_VAR_END( type, name, CNetworkHandleBase, stateChangedFn ) +#endif + + +#define CNetworkVar( type, name ) \ + NETWORK_VAR_START( type, name ) \ + NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged ) + + +#define CNetworkVarForDerived( type, name ) \ + virtual void NetworkStateChanged_##name() {} \ + virtual void NetworkStateChanged_##name( void *pVar ) {} \ + NETWORK_VAR_START( type, name ) \ + NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name ) + +#define CNetworkVectorForDerived( name ) \ + virtual void NetworkStateChanged_##name() {} \ + virtual void NetworkStateChanged_##name( void *pVar ) {} \ + CNetworkVectorInternal( Vector, name, NetworkStateChanged_##name ) + +#define CNetworkHandleForDerived( type, name ) \ + virtual void NetworkStateChanged_##name() {} \ + virtual void NetworkStateChanged_##name( void *pVar ) {} \ + CNetworkHandleInternal( type, name, NetworkStateChanged_##name ) + +#define CNetworkArrayForDerived( type, name, count ) \ + virtual void NetworkStateChanged_##name() {} \ + virtual void NetworkStateChanged_##name( void *pVar ) {} \ + CNetworkArrayInternal( type, name, count, NetworkStateChanged_##name ) + +#define IMPLEMENT_NETWORK_VAR_FOR_DERIVED( name ) \ + virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \ + virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); } + + +#define CNetworkVarForDerived_OnByDefault( type, name ) \ + virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \ + virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); } \ + NETWORK_VAR_START( type, name ) \ + NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name ) + +#define DISABLE_NETWORK_VAR_FOR_DERIVED( name ) \ + virtual void NetworkStateChanged_##name() {} \ + virtual void NetworkStateChanged_##name( void *pVar ) {} + + + +#define CNetworkVector( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged ) +#define CNetworkQAngle( name ) CNetworkVectorInternal( QAngle, name, NetworkStateChanged ) + +#define CNetworkVectorInternal( type, name, stateChangedFn ) \ + NETWORK_VAR_START( type, name ) \ + NETWORK_VAR_END( type, name, CNetworkVectorBase, stateChangedFn ) + +#define CNetworkQuaternion( name ) \ + NETWORK_VAR_START( Quaternion, name ) \ + NETWORK_VAR_END( Quaternion, name, CNetworkQuaternionBase, NetworkStateChanged ) + +#define CNetworkColor32( name ) \ + NETWORK_VAR_START( color32, name ) \ + NETWORK_VAR_END( color32, name, CNetworkColor32Base, NetworkStateChanged ) + + +#define CNetworkString( name, length ) \ + class NetworkVar_##name; \ + friend class NetworkVar_##name; \ + typedef ThisClass MakeANetworkVar_##name; \ + class NetworkVar_##name \ + { \ + public: \ + NetworkVar_##name() { m_Value[0] = '\0'; } \ + operator const char*() const { return m_Value; } \ + const char* Get() const { return m_Value; } \ + char* GetForModify() \ + { \ + NetworkStateChanged(); \ + return m_Value; \ + } \ + protected: \ + inline void NetworkStateChanged() \ + { \ + CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->NetworkStateChanged(); \ + } \ + private: \ + char m_Value[length]; \ + }; \ + NetworkVar_##name name; + + + + +#define CNetworkArrayInternal( type, name, count, stateChangedFn ) \ + class NetworkVar_##name; \ + friend class NetworkVar_##name; \ + typedef ThisClass MakeANetworkVar_##name; \ + class NetworkVar_##name \ + { \ + public: \ + inline NetworkVar_##name() \ + { \ + for ( int i = 0 ; i < count ; ++i ) \ + NetworkVarConstruct( m_Value[i] ); \ + } \ + template friend int ServerClassInit(T *); \ + const type& operator[]( int i ) const \ + { \ + return Get( i ); \ + } \ + \ + const type& Get( int i ) const \ + { \ + Assert( i >= 0 && i < count ); \ + return m_Value[i]; \ + } \ + \ + type& GetForModify( int i ) \ + { \ + Assert( i >= 0 && i < count ); \ + NetworkStateChanged( i ); \ + return m_Value[i]; \ + } \ + \ + void Set( int i, const type &val ) \ + { \ + Assert( i >= 0 && i < count ); \ + if( memcmp( &m_Value[i], &val, sizeof(type) ) ) \ + { \ + NetworkStateChanged( i ); \ + m_Value[i] = val; \ + } \ + } \ + const type* Base() const { return m_Value; } \ + int Count() const { return count; } \ + protected: \ + inline void NetworkStateChanged( int index ) \ + { \ + CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->stateChangedFn( &m_Value[index] ); \ + } \ + type m_Value[count]; \ + }; \ + NetworkVar_##name name; + + +#define CNetworkArray( type, name, count ) CNetworkArrayInternal( type, name, count, NetworkStateChanged ) + + +#define NETWORK_VAR_START( type, name ) \ + class NetworkVar_##name; \ + friend class NetworkVar_##name; \ + typedef ThisClass MakeANetworkVar_##name; \ + class NetworkVar_##name \ + { \ + public: \ + template friend int ServerClassInit(T *); + + +#define NETWORK_VAR_END( type, name, base, stateChangedFn ) \ + public: \ + static inline void NetworkStateChanged( void *ptr ) \ + { \ + CHECK_USENETWORKVARS ((ThisClass*)(((char*)ptr) - MyOffsetOf(ThisClass,name)))->stateChangedFn( ptr ); \ + } \ + }; \ + base< type, NetworkVar_##name > name; + + + +#endif \ No newline at end of file diff --git a/SpyCustom/particle_iterators.h b/SpyCustom/particle_iterators.h new file mode 100644 index 0000000..46e42fb --- /dev/null +++ b/SpyCustom/particle_iterators.h @@ -0,0 +1,222 @@ +#ifndef PARTICLE_ITERATORS_H +#define PARTICLE_ITERATORS_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "imesh.h" +#include "particledraw.h" + + +#define NUM_PARTICLES_PER_BATCH 200 +#ifndef _XBOX +#define MAX_TOTAL_PARTICLES 2048 +#else +#define MAX_TOTAL_PARTICLES 1024 +#endif + + +class CParticleRenderIterator +{ + friend class CParticleMgr; + friend class CParticleEffectBinding; +public: + CParticleRenderIterator(); + + const Particle* GetFirst(); + const Particle* GetNext(float sortKey); + + ParticleDraw* GetParticleDraw() const; + + +private: + + void TestFlushBatch(); + + +private: + CParticleEffectBinding* m_pEffectBinding; + CEffectMaterial* m_pMaterial; + ParticleDraw* m_pParticleDraw; + CMeshBuilder* m_pMeshBuilder; + IMesh* m_pMesh; + bool m_bBucketSort; + + float m_MinZ; + float m_MaxZ; + float m_zCoords[MAX_TOTAL_PARTICLES]; + int m_nZCoords; + + Particle* m_pCur; + bool m_bGotFirst; + float m_flPrevZ; + int m_nParticlesInCurrentBatch; +}; + + +class CParticleSimulateIterator +{ + friend class CParticleMgr; + friend class CParticleEffectBinding; +public: + CParticleSimulateIterator(); + + Particle* GetFirst(); + Particle* GetNext(); + float GetTimeDelta() const; + + void RemoveParticle(Particle* pParticle); + void RemoveAllParticles(); + +private: + CParticleEffectBinding* m_pEffectBinding; + CEffectMaterial* m_pMaterial; + float m_flTimeDelta; + + bool m_bGotFirst; + Particle* m_pNextParticle; +}; + + +inline CParticleRenderIterator::CParticleRenderIterator() +{ + m_pCur = NULL; + m_bGotFirst = false; + m_flPrevZ = 0; + m_nParticlesInCurrentBatch = 0; + m_MinZ = 1e24; + m_MaxZ = -1e24; + m_nZCoords = 0; +} + +inline const Particle* CParticleRenderIterator::GetFirst() +{ + Assert(!m_bGotFirst); + m_bGotFirst = true; + + m_pCur = m_pMaterial->m_Particles.m_pNext; + if (m_pCur == &m_pMaterial->m_Particles) + return NULL; + + m_pParticleDraw->m_pSubTexture = m_pCur->m_pSubTexture; + return m_pCur; +} + +inline void CParticleRenderIterator::TestFlushBatch() +{ + ++m_nParticlesInCurrentBatch; + if (m_nParticlesInCurrentBatch >= NUM_PARTICLES_PER_BATCH) + { + m_pMeshBuilder->End(false, true); + m_pMeshBuilder->Begin(m_pMesh, MATERIAL_QUADS, NUM_PARTICLES_PER_BATCH * 4); + + m_nParticlesInCurrentBatch = 0; + } +} + +inline const Particle* CParticleRenderIterator::GetNext(float sortKey) +{ + Assert(m_bGotFirst); + Assert(m_pCur); + + TestFlushBatch(); + + Particle* pNext = m_pCur->m_pNext; + + if (m_bBucketSort) + { + m_MinZ = MIN(sortKey, m_MinZ); + m_MaxZ = MAX(sortKey, m_MaxZ); + + m_zCoords[m_nZCoords] = sortKey; + ++m_nZCoords; + } + else + { + if (m_pCur != m_pMaterial->m_Particles.m_pNext && m_flPrevZ > sortKey) + { + SwapParticles(m_pCur->m_pPrev, m_pCur); + } + else + { + m_flPrevZ = sortKey; + } + } + + m_pCur = pNext; + if (m_pCur == &m_pMaterial->m_Particles) + return NULL; + + m_pParticleDraw->m_pSubTexture = m_pCur->m_pSubTexture; + return m_pCur; +} + +inline ParticleDraw* CParticleRenderIterator::GetParticleDraw() const +{ + return m_pParticleDraw; +} + + +inline CParticleSimulateIterator::CParticleSimulateIterator() +{ + m_pNextParticle = NULL; +#ifdef _DEBUG + m_bGotFirst = false; +#endif +} + +inline Particle* CParticleSimulateIterator::GetFirst() +{ +#ifdef _DEBUG + if (m_bGotFirst) + { + Assert(m_pNextParticle == &m_pMaterial->m_Particles); + } +#endif + + Particle* pRet = m_pMaterial->m_Particles.m_pNext; + if (pRet == &m_pMaterial->m_Particles) + return NULL; + +#ifdef _DEBUG + m_bGotFirst = true; +#endif + + m_pNextParticle = pRet->m_pNext; + return pRet; +} + +inline Particle* CParticleSimulateIterator::GetNext() +{ + Particle* pRet = m_pNextParticle; + + if (pRet == &m_pMaterial->m_Particles) + return NULL; + + m_pNextParticle = pRet->m_pNext; + return pRet; +} + +inline void CParticleSimulateIterator::RemoveParticle(Particle* pParticle) +{ + m_pEffectBinding->RemoveParticle(pParticle); +} + +inline void CParticleSimulateIterator::RemoveAllParticles() +{ + Particle* pParticle = GetFirst(); + while (pParticle) + { + RemoveParticle(pParticle); + pParticle = GetNext(); + } +} + +inline float CParticleSimulateIterator::GetTimeDelta() const +{ + return m_flTimeDelta; +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/particle_parse.h b/SpyCustom/particle_parse.h new file mode 100644 index 0000000..4a4c415 --- /dev/null +++ b/SpyCustom/particle_parse.h @@ -0,0 +1,66 @@ +#ifndef PARTICLE_PARSE_H +#define PARTICLE_PARSE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "utlvector.h" +#include "utlstring.h" +#include "ifilelist.h" + +enum ParticleAttachment_t +{ + PATTACH_ABSORIGIN = 0, + PATTACH_ABSORIGIN_FOLLOW, + PATTACH_CUSTOMORIGIN, + PATTACH_POINT, + PATTACH_POINT_FOLLOW, + + PATTACH_WORLDORIGIN, + + PATTACH_ROOTBONE_FOLLOW, + + MAX_PATTACH_TYPES, +}; + +extern int GetAttachTypeFromString(const char* pszString); + +#define PARTICLE_DISPATCH_FROM_ENTITY (1<<0) +#define PARTICLE_DISPATCH_RESET_PARTICLES (1<<1) + +struct te_tf_particle_effects_colors_t +{ + Vector m_vecColor1; + Vector m_vecColor2; +}; + +struct te_tf_particle_effects_control_point_t +{ + ParticleAttachment_t m_eParticleAttachment; + Vector m_vecOffset; +}; + +void ParseParticleEffects(bool bLoadSheets, bool bPrecache); +void ParseParticleEffectsMap(const char* pMapName, bool bLoadSheets, IFileList* pFilesToReload = NULL); + +void GetParticleManifest(CUtlVector& list); + +void PrecacheStandardParticleSystems(); + +class IFileList; +void ReloadParticleEffectsInList(IFileList* pFilesToReload); + +void DispatchParticleEffect(const char* pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity* pEntity, const char* pszAttachmentName, bool bResetAllParticlesOnEntity = false); +void DispatchParticleEffect(const char* pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity* pEntity = NULL, int iAttachmentPoint = -1, bool bResetAllParticlesOnEntity = false); +void DispatchParticleEffect(const char* pszParticleName, Vector vecOrigin, QAngle vecAngles, CBaseEntity* pEntity = NULL); +void DispatchParticleEffect(const char* pszParticleName, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity* pEntity = NULL); +void DispatchParticleEffect(int iEffectIndex, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity* pEntity = NULL); + +void DispatchParticleEffect(const char* pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity* pEntity, const char* pszAttachmentName, Vector vecColor1, Vector vecColor2, bool bUseColors = true, bool bResetAllParticlesOnEntity = false); +void DispatchParticleEffect(const char* pszParticleName, Vector vecOrigin, QAngle vecAngles, Vector vecColor1, Vector vecColor2, bool bUseColors = true, CBaseEntity* pEntity = NULL, int iAttachType = PATTACH_CUSTOMORIGIN); + + +void StopParticleEffects(CBaseEntity* pEntity); + + +#endif \ No newline at end of file diff --git a/SpyCustom/particle_property.h b/SpyCustom/particle_property.h new file mode 100644 index 0000000..43012c0 --- /dev/null +++ b/SpyCustom/particle_property.h @@ -0,0 +1,110 @@ +#ifndef PARTICLEPROPERTY_H +#define PARTICLEPROPERTY_H +#ifdef _WIN32 +#pragma once +#endif + +#include "smartptr.h" +#include "globalvars_base.h" +#include "particles_new.h" +#include "particle_parse.h" + +class CBaseEntity; +class CNewParticleEffect; + +#ifdef CLIENT_DLL +#define INVALID_PARTICLE_ATTACHMENT 0 +#else +#define INVALID_PARTICLE_ATTACHMENT -1 +#endif + +struct ParticleControlPoint_t +{ + ParticleControlPoint_t() + { + iControlPoint = 0; + iAttachType = PATTACH_ABSORIGIN_FOLLOW; + iAttachmentPoint = 0; + vecOriginOffset = vec3_origin; + } + + int iControlPoint; + ParticleAttachment_t iAttachType; + int iAttachmentPoint; + Vector vecOriginOffset; + EHANDLE hEntity; +}; + +struct ParticleEffectList_t +{ + ParticleEffectList_t() + { + pParticleEffect = NULL; + } + + CUtlVector pControlPoints; + CSmartPtr pParticleEffect; +}; + +extern int GetAttachTypeFromString(const char* pszString); + +class CParticleProperty +{ + DECLARE_CLASS_NOBASE(CParticleProperty); + DECLARE_EMBEDDED_NETWORKVAR(); + DECLARE_PREDICTABLE(); + DECLARE_DATADESC(); + +public: + CParticleProperty(); + ~CParticleProperty(); + + void Init(CBaseEntity* pEntity); + CBaseEntity* GetOuter(void) { return m_pOuter; } + + CNewParticleEffect* Create(const char* pszParticleName, ParticleAttachment_t iAttachType, const char* pszAttachmentName); + CNewParticleEffect* Create(const char* pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint = INVALID_PARTICLE_ATTACHMENT, Vector vecOriginOffset = vec3_origin); + void AddControlPoint(CNewParticleEffect* pEffect, int iPoint, C_BaseEntity* pEntity, ParticleAttachment_t iAttachType, const char* pszAttachmentName = NULL, Vector vecOriginOffset = vec3_origin); + void AddControlPoint(int iEffectIndex, int iPoint, C_BaseEntity* pEntity, ParticleAttachment_t iAttachType, int iAttachmentPoint = INVALID_PARTICLE_ATTACHMENT, Vector vecOriginOffset = vec3_origin); + + inline void SetControlPointParent(CNewParticleEffect* pEffect, int whichControlPoint, int parentIdx); + void SetControlPointParent(int iEffectIndex, int whichControlPoint, int parentIdx); + + void StopEmission(CNewParticleEffect* pEffect = NULL, bool bWakeOnStop = false, bool bDestroyAsleepSystems = false); + void StopEmissionAndDestroyImmediately(CNewParticleEffect* pEffect = NULL); + + void StopParticlesInvolving(CBaseEntity* pEntity); + void StopParticlesNamed(const char* pszEffectName, bool bForceRemoveInstantly = false); + void StopParticlesWithNameAndAttachment(const char* pszEffectName, int iAttachmentPoint, bool bForceRemoveInstantly = false); + + void OnParticleSystemUpdated(CNewParticleEffect* pEffect, float flTimeDelta); + void OnParticleSystemDeleted(CNewParticleEffect* pEffect); + +#ifdef CLIENT_DLL + void OwnerSetDormantTo(bool bDormant); +#endif + + void ReplaceParticleEffect(CNewParticleEffect* pOldEffect, CNewParticleEffect* pNewEffect); + + void DebugPrintEffects(void); + + int FindEffect(const char* pEffectName, int nStart = 0); + inline CNewParticleEffect* GetParticleEffectFromIdx(int idx); + +private: + int GetParticleAttachment(C_BaseEntity* pEntity, const char* pszAttachmentName, const char* pszParticleName); + int FindEffect(CNewParticleEffect* pEffect); + void UpdateParticleEffect(ParticleEffectList_t* pEffect, bool bInitializing = false, int iOnlyThisControlPoint = -1); + void UpdateControlPoint(ParticleEffectList_t* pEffect, int iPoint, bool bInitializing); + +private: + CBaseEntity* m_pOuter; + CUtlVector m_ParticleEffects; + int m_iDormancyChangedAtFrame; + + friend class CBaseEntity; +}; + +#include "particle_property_inlines.h" + +#endif \ No newline at end of file diff --git a/SpyCustom/particle_property_inlines.h b/SpyCustom/particle_property_inlines.h new file mode 100644 index 0000000..95ba40d --- /dev/null +++ b/SpyCustom/particle_property_inlines.h @@ -0,0 +1,25 @@ +#ifndef PARTICLEPROPERTY_H +#pragma message("Do not include particle_property_inlines.h from anywhere other than particle_property.h!") +#pragma error +#endif + +#ifndef PARTICLEPROPERTY_INLINES_H +#define PARTICLEPROPERTY_INLINES_H +#ifdef _WIN32 +#pragma once +#endif + + +void CParticleProperty::SetControlPointParent(CNewParticleEffect* pEffect, int whichControlPoint, int parentIdx) +{ + pEffect->SetControlPointParent(whichControlPoint, parentIdx); +} + +CNewParticleEffect* CParticleProperty::GetParticleEffectFromIdx(int idx) +{ + return m_ParticleEffects[idx].pParticleEffect.GetObject(); +} + + + +#endif \ No newline at end of file diff --git a/SpyCustom/particle_util.h b/SpyCustom/particle_util.h new file mode 100644 index 0000000..003c514 --- /dev/null +++ b/SpyCustom/particle_util.h @@ -0,0 +1,289 @@ +#ifndef PARTICLE_UTIL_H +#define PARTICLE_UTIL_H + +#include "IMesh.h" +#include "particledraw.h" +#include "particlemgr.h" +#include "cdll_client_int.h" +#include "timedevent.h" + + + +inline float FLerp(float minVal, float maxVal, float t) +{ + return minVal + (maxVal - minVal) * t; +} + +inline Vector VecLerp(const Vector& minVal, const Vector& maxVal, float t) +{ + return minVal + (maxVal - minVal) * t; +} + +inline float FRand(float minVal, float maxVal) +{ + return minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); +} + +inline void PhysicallySimulate(Vector& pos, Vector& velocity, const Vector& acceleration, const float fTimeDelta) +{ + pos = pos + (velocity + (acceleration * fTimeDelta * 0.5f)) * fTimeDelta; + velocity = velocity + acceleration * fTimeDelta; +} + + +inline Vector GetGravityVector() +{ + return Vector(0, 0, -150); +} + + +inline void RenderParticle_Color255SizeSpecularTCoord3( + ParticleDraw* pDraw, + const Vector& pos, + const Vector& color, + const float alpha, + const float size, + const unsigned char* specular, + const float tCoord +) +{ + if (alpha < 0.5f) + return; + + CMeshBuilder* pBuilder = pDraw->GetMeshBuilder(); + if (!pBuilder) + return; + + unsigned char ubColor[4]; + ubColor[0] = (unsigned char)RoundFloatToInt(color.x); + ubColor[1] = (unsigned char)RoundFloatToInt(color.y); + ubColor[2] = (unsigned char)RoundFloatToInt(color.z); + ubColor[3] = (unsigned char)RoundFloatToInt(alpha); + + pBuilder->Position3f(pos.x - size, pos.y - size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord3f(0, pDraw->m_pSubTexture->m_tCoordMins[0], pDraw->m_pSubTexture->m_tCoordMaxs[1], tCoord); + pBuilder->Specular3ubv(specular); + pBuilder->AdvanceVertex(); + + pBuilder->Position3f(pos.x - size, pos.y + size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord3f(0, pDraw->m_pSubTexture->m_tCoordMins[0], pDraw->m_pSubTexture->m_tCoordMins[1], tCoord); + pBuilder->Specular3ubv(specular); + pBuilder->AdvanceVertex(); + + pBuilder->Position3f(pos.x + size, pos.y + size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord3f(0, pDraw->m_pSubTexture->m_tCoordMaxs[0], pDraw->m_pSubTexture->m_tCoordMins[1], tCoord); + pBuilder->Specular3ubv(specular); + pBuilder->AdvanceVertex(); + + pBuilder->Position3f(pos.x + size, pos.y - size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord3f(0, pDraw->m_pSubTexture->m_tCoordMaxs[0], pDraw->m_pSubTexture->m_tCoordMaxs[1], tCoord); + pBuilder->Specular3ubv(specular); + pBuilder->AdvanceVertex(); +} + + +inline void RenderParticle_Color255Size( + ParticleDraw* pDraw, + const Vector& pos, + const Vector& color, + const float alpha, + const float size) +{ + if (alpha < 0.5f) + return; + + CMeshBuilder* pBuilder = pDraw->GetMeshBuilder(); + if (!pBuilder) + return; + + unsigned char ubColor[4]; + ubColor[0] = (unsigned char)RoundFloatToInt(color.x); + ubColor[1] = (unsigned char)RoundFloatToInt(color.y); + ubColor[2] = (unsigned char)RoundFloatToInt(color.z); + ubColor[3] = (unsigned char)RoundFloatToInt(alpha); + + pBuilder->Position3f(pos.x - size, pos.y - size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord2f(0, pDraw->m_pSubTexture->m_tCoordMins[0], pDraw->m_pSubTexture->m_tCoordMaxs[1]); + pBuilder->AdvanceVertex(); + + pBuilder->Position3f(pos.x - size, pos.y + size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord2f(0, pDraw->m_pSubTexture->m_tCoordMins[0], pDraw->m_pSubTexture->m_tCoordMins[1]); + pBuilder->AdvanceVertex(); + + pBuilder->Position3f(pos.x + size, pos.y + size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord2f(0, pDraw->m_pSubTexture->m_tCoordMaxs[0], pDraw->m_pSubTexture->m_tCoordMins[1]); + pBuilder->AdvanceVertex(); + + pBuilder->Position3f(pos.x + size, pos.y - size, pos.z); + pBuilder->Color4ubv(ubColor); + pBuilder->TexCoord2f(0, pDraw->m_pSubTexture->m_tCoordMaxs[0], pDraw->m_pSubTexture->m_tCoordMaxs[1]); + pBuilder->AdvanceVertex(); +} + + +inline void RenderParticle_Color255SizeNormal( + ParticleDraw* pDraw, + const Vector& pos, + const Vector& color, + const float alpha, + const float size, + const Vector& vNormal) +{ + if (alpha < 0.5f) + return; + + CMeshBuilder* pBuilder = pDraw->GetMeshBuilder(); + if (!pBuilder) + return; + + unsigned char ubColor[4]; + ubColor[0] = (unsigned char)RoundFloatToInt(color.x); + ubColor[1] = (unsigned char)RoundFloatToInt(color.y); + ubColor[2] = (unsigned char)RoundFloatToInt(color.z); + ubColor[3] = (unsigned char)RoundFloatToInt(alpha); + +} + + +inline void RenderParticle_Color255SizeNormalAngle( + ParticleDraw* pDraw, + const Vector& pos, + const Vector& color, + const float alpha, + const float size, + const Vector& vNormal, + const float angle) +{ + if (alpha < 0.5f) + return; + + CMeshBuilder* pBuilder = pDraw->GetMeshBuilder(); + if (!pBuilder) + return; + + unsigned char ubColor[4]; + ubColor[0] = (unsigned char)RoundFloatToInt(color.x); + ubColor[1] = (unsigned char)RoundFloatToInt(color.y); + ubColor[2] = (unsigned char)RoundFloatToInt(color.z); + ubColor[3] = (unsigned char)RoundFloatToInt(alpha); + + float ca = (float)cos(angle); + float sa = (float)sin(angle); + +} + + +inline void RenderParticle_ColorSize( + ParticleDraw* pDraw, + const Vector& pos, + const Vector& color, + const float alpha, + const float size +) +{ + if (alpha < 0.001f) + return; + + CMeshBuilder* pBuilder = pDraw->GetMeshBuilder(); + if (!pBuilder) + return; + + unsigned char ubColor[4]; + ubColor[0] = (unsigned char)RoundFloatToInt(color.x * 254.9f); + ubColor[1] = (unsigned char)RoundFloatToInt(color.y * 254.9f); + ubColor[2] = (unsigned char)RoundFloatToInt(color.z * 254.9f); + ubColor[3] = (unsigned char)RoundFloatToInt(alpha * 254.9f); + +} + + +inline void RenderParticle_ColorSizeAngle( + ParticleDraw* pDraw, + const Vector& pos, + const Vector& color, + const float alpha, + const float size, + const float angle) +{ + if (alpha < 0.001f) + return; + + CMeshBuilder* pBuilder = pDraw->GetMeshBuilder(); + if (!pBuilder) + return; + + unsigned char ubColor[4]; + ubColor[0] = (unsigned char)RoundFloatToInt(color.x * 254.9f); + ubColor[1] = (unsigned char)RoundFloatToInt(color.y * 254.9f); + ubColor[2] = (unsigned char)RoundFloatToInt(color.z * 254.9f); + ubColor[3] = (unsigned char)RoundFloatToInt(alpha * 254.9f); + + float sa, ca; + SinCos(angle, &sa, &ca); + +} + +inline void RenderParticle_ColorSizeAngles( + ParticleDraw* pDraw, + const Vector& pos, + const Vector& color, + const float alpha, + const float size, + const QAngle& angles) +{ + if (alpha < 0.001f) + return; + + CMeshBuilder* pBuilder = pDraw->GetMeshBuilder(); + if (!pBuilder) + return; + + unsigned char ubColor[4]; + ubColor[0] = (unsigned char)RoundFloatToInt(color.x * 254.9f); + ubColor[1] = (unsigned char)RoundFloatToInt(color.y * 254.9f); + ubColor[2] = (unsigned char)RoundFloatToInt(color.z * 254.9f); + ubColor[3] = (unsigned char)RoundFloatToInt(alpha * 254.9f); + + Vector vNorm, vWidth, vHeight; + AngleVectors(angles, &vNorm, &vWidth, &vHeight); + + Vector vVertex = pos; +} + +inline float GetAlphaDistanceFade( + const Vector& pos, + const float fadeNearDist, + const float fadeFarDist) +{ + if (-pos.z > fadeFarDist) + { + return 1; + } + else if (-pos.z > fadeNearDist) + { + return (-pos.z - fadeNearDist) / (fadeFarDist - fadeNearDist); + } + else + { + return 0; + } +} + + +inline Vector WorldGetLightForPoint(const Vector& vPos, bool bClamp) +{ +#if defined(PARTICLEPROTOTYPE_APP) + return Vector(1, 1, 1); +#else + return engine->GetLightForPoint(vPos, bClamp); +#endif +} + +#endif \ No newline at end of file diff --git a/SpyCustom/particledraw.h b/SpyCustom/particledraw.h new file mode 100644 index 0000000..f72b908 --- /dev/null +++ b/SpyCustom/particledraw.h @@ -0,0 +1,56 @@ +#ifndef PARTICLEDRAW_H +#define PARTICLEDRAW_H + + +class IMaterial; +class CMeshBuilder; +class CParticleSubTexture; + + +class ParticleDraw +{ + friend class CParticleEffectBinding; + +public: + + ParticleDraw(); + + void Init(CMeshBuilder* pMeshBuilder, IMaterial* pMaterial, float fTimeDelta); + + float GetTimeDelta() const; + + CMeshBuilder* GetMeshBuilder(); + + CParticleSubTexture* m_pSubTexture; + +private: + CMeshBuilder* m_pMeshBuilder; + IMaterial* m_pMaterial; + float m_fTimeDelta; +}; + + + +inline ParticleDraw::ParticleDraw() +{ + m_pMaterial = 0; +} + +inline void ParticleDraw::Init(CMeshBuilder* pMeshBuilder, IMaterial* pMaterial, float fTimeDelta) +{ + m_pMeshBuilder = pMeshBuilder; + m_pMaterial = pMaterial; + m_fTimeDelta = fTimeDelta; +} + +inline float ParticleDraw::GetTimeDelta() const +{ + return m_fTimeDelta; +} + +inline CMeshBuilder* ParticleDraw::GetMeshBuilder() +{ + return m_pMeshBuilder; +} + +#endif \ No newline at end of file diff --git a/SpyCustom/particlemgr.h b/SpyCustom/particlemgr.h new file mode 100644 index 0000000..0b12d4b --- /dev/null +++ b/SpyCustom/particlemgr.h @@ -0,0 +1,617 @@ + +#ifndef PARTICLEMGR_H +#define PARTICLEMGR_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "imaterial.h" +#include "imaterialsystem.h" +#include "vector.h" +#include "vmatrix.h" +#include "Mathlib.h" +#include "iclientrenderable.h" +#include "clientleafsystem.h" +#include "fasttimer.h" +#include "utllinkedlist.h" +#include "UtlDict.h" +#ifdef WIN32 +#include +#else +#include +#endif +#include "utlintrusivelist.h" +#include "utlobjectreference.h" +#include "utlstring.h" + + +class IParticleEffect; +class IClientParticleListener; +struct Particle; +class ParticleDraw; +class CMeshBuilder; +class CUtlMemoryPool; +class CEffectMaterial; +class CParticleSimulateIterator; +class CParticleRenderIterator; +class IThreadPool; +class CParticleSystemDefinition; +class CParticleMgr; +class CNewParticleEffect; +class CParticleCollection; + +#define INVALID_MATERIAL_HANDLE NULL + + + +class CParticleSubTexture; +class CParticleSubTextureGroup; + + +struct Particle +{ + Particle* m_pPrev, * m_pNext; + + CParticleSubTexture* m_pSubTexture; + + Vector m_Pos; +}; + + +typedef CParticleSubTexture* PMaterialHandle; + +class CEffectMaterial +{ +public: + CEffectMaterial(); + +public: + CParticleSubTextureGroup* m_pGroup; + + Particle m_Particles; + CEffectMaterial* m_pHashedNext; +}; + + +class CParticleSubTextureGroup +{ +public: + CParticleSubTextureGroup(); + ~CParticleSubTextureGroup(); + + IMaterial* m_pPageMaterial; +}; + +class CParticleSubTexture +{ +public: + CParticleSubTexture(); + + float m_tCoordMins[2]; + float m_tCoordMaxs[2]; + + CParticleSubTextureGroup* m_pGroup; + CParticleSubTextureGroup m_DefaultGroup; +#ifdef _DEBUG + char* m_szDebugName; +#endif + + IMaterial* m_pMaterial; +}; + + +abstract_class IParticleEffect +{ + public: + + virtual ~IParticleEffect() {} + + virtual void Update(float fTimeDelta) {} + + virtual void StartRender(VMatrix & effectMatrix) {} + + virtual bool ShouldSimulate() const = 0; + virtual void SetShouldSimulate(bool bSim) = 0; + virtual void SimulateParticles(CParticleSimulateIterator* pIterator) = 0; + + virtual void RenderParticles(CParticleRenderIterator* pIterator) = 0; + + virtual void NotifyRemove() {} + + virtual void NotifyDestroyParticle(Particle* pParticle) {} + + virtual const Vector& GetSortOrigin() = 0; + + virtual const Vector* GetParticlePosition(Particle* pParticle) { return &pParticle->m_Pos; } + + virtual const char* GetEffectName() { return "???"; } +}; + +#define REGISTER_EFFECT( effect ) \ + IParticleEffect* effect##_Factory() \ + { \ + return new effect; \ + } \ + struct effect##_RegistrationHelper \ + { \ + effect##_RegistrationHelper() \ + { \ + ParticleMgr()->RegisterEffect( typeid( effect ).name(), effect##_Factory ); \ + } \ + }; \ + static effect##_RegistrationHelper g_##effect##_RegistrationHelper + +#define REGISTER_EFFECT_USING_CREATE( effect ) \ + IParticleEffect* effect##_Factory() \ + { \ + return effect::Create( #effect ).GetObject(); \ + } \ + struct effect##_RegistrationHelper \ + { \ + effect##_RegistrationHelper() \ + { \ + ParticleMgr()->RegisterEffect( typeid( effect ).name(), effect##_Factory ); \ + } \ + }; \ + static effect##_RegistrationHelper g_##effect##_RegistrationHelper + + +class CParticleEffectBinding : public CDefaultClientRenderable +{ + friend class CParticleMgr; + friend class CParticleSimulateIterator; + friend class CNewParticleEffect; + +public: + CParticleEffectBinding(); + ~CParticleEffectBinding(); + + +public: + + void SimulateParticles(float flTimeDelta); + + PMaterialHandle FindOrAddMaterial(const char* pMaterialName); + + Particle* AddParticle(int sizeInBytes, PMaterialHandle pMaterial); + + void SetBBox(const Vector& bbMin, const Vector& bbMax, bool bDisableAutoUpdate = true); + void GetWorldspaceBounds(Vector* pMins, Vector* pMaxs); + + const matrix3x4_t& GetLocalSpaceTransform() const; + void SetLocalSpaceTransform(const matrix3x4_t& transform); + + bool EnlargeBBoxToContain(const Vector& pt); + + void SetDrawThruLeafSystem(int bDraw); + + void SetDrawBeforeViewModel(int bDraw); + + int GetRemoveFlag() { return GetFlag(FLAGS_REMOVE); } + void SetRemoveFlag() { SetFlag(FLAGS_REMOVE, 1); } + + int GetAlwaysSimulate() { return GetFlag(FLAGS_ALWAYSSIMULATE); } + void SetAlwaysSimulate(int bAlwaysSimulate) { SetFlag(FLAGS_ALWAYSSIMULATE, bAlwaysSimulate); } + + void SetIsNewParticleSystem(void) { SetFlag(FLAGS_NEW_PARTICLE_SYSTEM, 1); } + int WasDrawnPrevFrame() { return GetFlag(FLAGS_DRAWN_PREVFRAME); } + void SetWasDrawnPrevFrame(int bWasDrawnPrevFrame) { SetFlag(FLAGS_DRAWN_PREVFRAME, bWasDrawnPrevFrame); } + + int IsEffectCameraSpace() { return GetFlag(FLAGS_CAMERASPACE); } + void SetEffectCameraSpace(int bCameraSpace) { SetFlag(FLAGS_CAMERASPACE, bCameraSpace); } + + int GetAutoApplyLocalTransform() const { return GetFlag(FLAGS_AUTOAPPLYLOCALTRANSFORM); } + void SetAutoApplyLocalTransform(int b) { SetFlag(FLAGS_AUTOAPPLYLOCALTRANSFORM, b); } + + int GetAutoUpdateBBox() { return GetFlag(FLAGS_AUTOUPDATEBBOX); } + void SetAutoUpdateBBox(int bAutoUpdate) { SetFlag(FLAGS_AUTOUPDATEBBOX, bAutoUpdate); } + + int GetNumActiveParticles(); + + void SetParticleCullRadius(float flMaxParticleRadius); + + int GetActiveParticleList(int nCount, Particle** ppParticleList); + + void DetectChanges(); + +private: + void SetFlag(int flag, int bOn) { if (bOn) m_Flags |= flag; else m_Flags &= ~flag; } + int GetFlag(int flag) const { return m_Flags & flag; } + + void Init(CParticleMgr* pMgr, IParticleEffect* pSim); + void Term(); + + void RemoveParticle(Particle* pParticle); + + void StartDrawMaterialParticles( + CEffectMaterial* pMaterial, + float flTimeDelta, + IMesh*& pMesh, + CMeshBuilder& builder, + ParticleDraw& particleDraw, + bool bWireframe); + + int DrawMaterialParticles( + bool bBucketSort, + CEffectMaterial* pMaterial, + float flTimeDelta, + bool bWireframe + ); + + void GrowBBoxFromParticlePositions(CEffectMaterial* pMaterial, bool& bboxSet, Vector& bbMin, Vector& bbMax); + + void RenderStart(VMatrix& mTempModel, VMatrix& mTempView); + void RenderEnd(VMatrix& mModel, VMatrix& mView); + + void BBoxCalcStart(Vector& bbMin, Vector& bbMax); + void BBoxCalcEnd(bool bboxSet, Vector& bbMin, Vector& bbMax); + + void DoBucketSort( + CEffectMaterial* pMaterial, + float* zCoords, + int nZCoords, + float minZ, + float maxZ); + + int GetRemovalInProgressFlag() { return GetFlag(FLAGS_REMOVALINPROGRESS); } + void SetRemovalInProgressFlag() { SetFlag(FLAGS_REMOVALINPROGRESS, 1); } + + int GetNeedsBBoxUpdate() { return GetFlag(FLAGS_NEEDS_BBOX_UPDATE); } + void SetNeedsBBoxUpdate(int bFirstUpdate) { SetFlag(FLAGS_NEEDS_BBOX_UPDATE, bFirstUpdate); } + + int GetFirstFrameFlag() { return GetFlag(FLAGS_FIRST_FRAME); } + void SetFirstFrameFlag(int bFirstUpdate) { SetFlag(FLAGS_FIRST_FRAME, bFirstUpdate); } + + int WasDrawn() { return GetFlag(FLAGS_DRAWN); } + void SetDrawn(int bDrawn) { SetFlag(FLAGS_DRAWN, bDrawn); } + + bool RecalculateBoundingBox(); + + CEffectMaterial* GetEffectMaterial(CParticleSubTexture* pSubTexture); + +public: + + virtual const Vector& GetRenderOrigin(void); + virtual const QAngle& GetRenderAngles(void); + virtual const matrix3x4_t& RenderableToWorldTransform(); + virtual void GetRenderBounds(Vector& mins, Vector& maxs); + virtual bool ShouldDraw(void); + virtual int DrawModel(int flags, const RenderableInstance_t& instance); + +private: + enum + { + FLAGS_REMOVE = (1 << 0), + FLAGS_REMOVALINPROGRESS = (1 << 1), + FLAGS_NEEDS_BBOX_UPDATE = (1 << 2), + FLAGS_AUTOUPDATEBBOX = (1 << 3), + FLAGS_ALWAYSSIMULATE = (1 << 4), + FLAGS_DRAWN = (1 << 5), + FLAGS_DRAWN_PREVFRAME = (1 << 6), + FLAGS_CAMERASPACE = (1 << 7), + FLAGS_DRAW_THRU_LEAF_SYSTEM = (1 << 8), + FLAGS_DRAW_BEFORE_VIEW_MODEL = (1 << 9), + FLAGS_AUTOAPPLYLOCALTRANSFORM = (1 << 10), + FLAGS_FIRST_FRAME = (1 << 11), + FLAGS_NEW_PARTICLE_SYSTEM = (1 << 12) + }; + + + VMatrix m_LocalSpaceTransform; + bool m_bLocalSpaceTransformIdentity; + + Vector m_Min; + Vector m_Max; + + Vector m_LastMin; + Vector m_LastMax; + + float m_flParticleCullRadius; + + unsigned short m_nActiveParticles; + + unsigned short m_FrameCode; + + unsigned short m_ListIndex; + + IParticleEffect* m_pSim; + CParticleMgr* m_pParticleMgr; + + int m_Flags; + + enum { EFFECT_MATERIAL_HASH_SIZE = 8 }; + CEffectMaterial* m_EffectMaterialHash[EFFECT_MATERIAL_HASH_SIZE]; + +#ifdef INFESTED_PARTICLES +public: +#endif + CUtlLinkedList m_Materials; + + unsigned short m_UpdateBBoxCounter; +}; + + +class CParticleLightInfo +{ +public: + Vector m_vPos; + Vector m_vColor; + float m_flIntensity; +}; + +typedef IParticleEffect* (*CreateParticleEffectFN)(); + +enum +{ + TOOLPARTICLESYSTEMID_INVALID = -1, +}; + + +class CParticleCollection; + +class CNonDrawingParticleSystem +{ +public: + CNonDrawingParticleSystem* m_pNext; + CNonDrawingParticleSystem* m_pPrev; + CParticleCollection* m_pSystem; + + FORCEINLINE CParticleCollection* operator()(void) const + { + return m_pSystem; + } + + FORCEINLINE CParticleCollection* Get(void) const + { + return m_pSystem; + } + + ~CNonDrawingParticleSystem(void); +}; + + + + +class CClientTools; + +class CParticleMgr +{ + friend class CParticleEffectBinding; + friend class CParticleCollection; + friend class CNonDrawingParticleSystem; + friend class CClientTools; + +public: + + CParticleMgr(); + virtual ~CParticleMgr(); + + bool Init(unsigned long nPreallocatedParticles, IMaterialSystem* pMaterial); + + void Term(); + + void LevelInit(); + + void RegisterEffect(const char* pEffectType, CreateParticleEffectFN func); + IParticleEffect* CreateEffect(const char* pEffectType); + + bool AddEffect(CParticleEffectBinding* pEffect, IParticleEffect* pSim); + void RemoveEffect(CParticleEffectBinding* pEffect); + + void AddEffect(CNewParticleEffect* pEffect); + void RemoveEffect(CNewParticleEffect* pEffect); + + void RemoveAllEffects(); + + void IncrementFrameCode(); + + void Simulate(float fTimeDelta); + + void PostRender(); + + void DrawBeforeViewModelEffects(); + + VMatrix& GetModelView(); + + Particle* AllocParticle(int size); + void FreeParticle(Particle*); + + PMaterialHandle GetPMaterial(const char* pMaterialName); + IMaterial* PMaterialToIMaterial(PMaterialHandle hMaterial); + + void RepairPMaterial(PMaterialHandle hMaterial); + + void GetDirectionalLightInfo(CParticleLightInfo& info) const; + void SetDirectionalLightInfo(const CParticleLightInfo& info); + + void SpewInfo(bool bDetail); + + void AddEffectListener(IClientParticleListener* pListener); + void RemoveEffectListener(IClientParticleListener* pListener); + + int AllocateToolParticleEffectId(); + + void RemoveAllNewEffects(); + + CNewParticleEffect* FirstNewEffect(); + CNewParticleEffect* NextNewEffect(CNewParticleEffect* pEffect); + + void RenderParticleSystems(bool bEnable); + bool ShouldRenderParticleSystems() const; + + void RemoveOldParticleEffects(float flTime); + int GetNumParticles() const { return m_nCurrentParticlesAllocated; } + + + CNonDrawingParticleSystem* CreateNonDrawingEffect(const char* pEffectName); + +private: + struct RetireInfo_t + { + CParticleCollection* m_pCollection; + float m_flScreenArea; + bool m_bFirstFrame; + }; + + void UpdateAllEffects(float flTimeDelta); + + void UpdateNewEffects(float flTimeDelta); + + void SpewActiveParticleSystems(); + + CParticleSubTextureGroup* FindOrAddSubTextureGroup(IMaterial* pPageMaterial); + + int ComputeParticleDefScreenArea(int nInfoCount, RetireInfo_t* pInfo, float* pTotalArea, CParticleSystemDefinition* pDef, + const CViewSetup& view, const VMatrix& worldToPixels, float flFocalDist); + + bool RetireParticleCollections(CParticleSystemDefinition* pDef, int nCount, RetireInfo_t* pInfo, float flScreenArea, float flMaxTotalArea); + void BuildParticleSimList(CUtlVector< CNewParticleEffect* >& list); + bool EarlyRetireParticleSystems(int nCount, CNewParticleEffect** ppEffects); + static int RetireSort(const void* p1, const void* p2); + +private: + + int m_nCurrentParticlesAllocated; + + CParticleLightInfo m_DirectionalLight; + + unsigned short m_FrameCode; + + bool m_bUpdatingEffects; + bool m_bRenderParticleEffects; + + CUtlLinkedList m_Effects; + + CUtlIntrusiveDList< CNewParticleEffect > m_NewEffects; + CUtlIntrusiveDList< CNonDrawingParticleSystem > m_NonDrawingParticleSystems; + + + + CUtlVector< IClientParticleListener*> m_effectListeners; + + IMaterialSystem* m_pMaterialSystem; + + VMatrix m_mModelView; + + CUtlVector m_SubTextureGroups; + CUtlDict m_SubTextures; + CParticleSubTexture m_DefaultInvalidSubTexture; + + CUtlMap< const char*, CreateParticleEffectFN > m_effectFactories; + + int m_nToolParticleEffectId; + + IThreadPool* m_pThreadPool[2]; +}; + +inline int CParticleMgr::AllocateToolParticleEffectId() +{ + return m_nToolParticleEffectId++; +} + +class IClientParticleListener +{ +public: + virtual void OnParticleEffectAdded(IParticleEffect* pEffect) = 0; + virtual void OnParticleEffectRemoved(IParticleEffect* pEffect) = 0; +}; + + + +float Helper_GetTime(); +float Helper_GetFrameTime(); +float Helper_RandomFloat(float minVal, float maxVal); +int Helper_RandomInt(int minVal, int maxVal); + + + +inline VMatrix& CParticleMgr::GetModelView() +{ + return m_mModelView; +} + + + +inline const matrix3x4_t& CParticleEffectBinding::GetLocalSpaceTransform() const +{ + return m_LocalSpaceTransform.As3x4(); +} + + + +CParticleMgr* ParticleMgr(); + + + + +struct StandardParticle_t : public Particle +{ + void SetColor(float r, float g, float b); + void SetAlpha(float a); + + Vector m_Velocity; + + float m_Lifetime; + + unsigned char m_EffectData; + unsigned short m_EffectDataWord; + + unsigned char m_Color[4]; +}; + + +inline void TransformParticle(const VMatrix& vMat, const Vector& vIn, Vector& vOut) +{ + vOut.x = vMat.m[0][0] * vIn.x + vMat.m[0][1] * vIn.y + vMat.m[0][2] * vIn.z + vMat.m[0][3]; + vOut.y = vMat.m[1][0] * vIn.x + vMat.m[1][1] * vIn.y + vMat.m[1][2] * vIn.z + vMat.m[1][3]; + vOut.z = vMat.m[2][0] * vIn.x + vMat.m[2][1] * vIn.y + vMat.m[2][2] * vIn.z + vMat.m[2][3]; +} + + +inline void StandardParticle_t::SetColor(float r, float g, float b) +{ + m_Color[0] = (unsigned char)(r * 255.9f); + m_Color[1] = (unsigned char)(g * 255.9f); + m_Color[2] = (unsigned char)(b * 255.9f); +} + +inline void StandardParticle_t::SetAlpha(float a) +{ + m_Color[3] = (unsigned char)(a * 255.9f); +} + + + +inline void UnlinkParticle(Particle* pParticle) +{ + pParticle->m_pPrev->m_pNext = pParticle->m_pNext; + pParticle->m_pNext->m_pPrev = pParticle->m_pPrev; +} + +inline void InsertParticleBefore(Particle* pInsert, Particle* pNext) +{ + pInsert->m_pNext = pNext; + pInsert->m_pPrev = pNext->m_pPrev; + pInsert->m_pNext->m_pPrev = pInsert->m_pPrev->m_pNext = pInsert; +} + +inline void InsertParticleAfter(Particle* pInsert, Particle* pPrev) +{ + pInsert->m_pPrev = pPrev; + pInsert->m_pNext = pPrev->m_pNext; + + pInsert->m_pNext->m_pPrev = pInsert->m_pPrev->m_pNext = pInsert; +} + +inline void SwapParticles(Particle* pPrev, Particle* pCur) +{ + UnlinkParticle(pCur); + InsertParticleBefore(pCur, pPrev); +} + + +#include "particle_iterators.h" + + +#endif diff --git a/SpyCustom/particles.h b/SpyCustom/particles.h new file mode 100644 index 0000000..be72c49 --- /dev/null +++ b/SpyCustom/particles.h @@ -0,0 +1,1954 @@ +#ifndef PARTICLES_H +#define PARTICLES_H +#ifdef _WIN32 +#pragma once +#endif + +#include "mathlib.h" +#include "vector.h" +#include "ssemath.h" +#include "imaterialsystem.h" +#include "dmxelement.h" +#include "utlintrusivelist.h" +#include "random.h" +#include "utlobjectreference.h" +#include "UtlStringMap.h" +#include "utlmap.h" +#include "MaterialSystemUtil.h" +#include "trace.h" +#include "utlsoacontainer.h" + +#if defined( CLIENT_DLL ) +#include "c_pixel_visibility.h" +#endif + +struct DmxElementUnpackStructure_t; +class CParticleSystemDefinition; +class CParticleCollection; +class CParticleOperatorInstance; +class CParticleSystemDictionary; +class CUtlBuffer; +class IParticleOperatorDefinition; +class CSheet; +class CMeshBuilder; +extern float s_pRandomFloats[]; + + +#define MAX_RANDOM_FLOATS 4096 +#define RANDOM_FLOAT_MASK ( MAX_RANDOM_FLOATS - 1 ) + + +#define MAX_PARTICLE_ATTRIBUTES 32 + +#define DEFPARTICLE_ATTRIBUTE( name, bit ) \ + const int PARTICLE_ATTRIBUTE_##name##_MASK = (1 << bit); \ + const int PARTICLE_ATTRIBUTE_##name = bit; + +DEFPARTICLE_ATTRIBUTE(XYZ, 0); + +DEFPARTICLE_ATTRIBUTE(LIFE_DURATION, 1); + +DEFPARTICLE_ATTRIBUTE(PREV_XYZ, 2); + +DEFPARTICLE_ATTRIBUTE(RADIUS, 3); + +DEFPARTICLE_ATTRIBUTE(ROTATION, 4); + +DEFPARTICLE_ATTRIBUTE(ROTATION_SPEED, 5); + +DEFPARTICLE_ATTRIBUTE(TINT_RGB, 6); + +DEFPARTICLE_ATTRIBUTE(ALPHA, 7); + +DEFPARTICLE_ATTRIBUTE(CREATION_TIME, 8); + +DEFPARTICLE_ATTRIBUTE(SEQUENCE_NUMBER, 9); + +DEFPARTICLE_ATTRIBUTE(TRAIL_LENGTH, 10); + +DEFPARTICLE_ATTRIBUTE(PARTICLE_ID, 11); + +DEFPARTICLE_ATTRIBUTE(YAW, 12); + +DEFPARTICLE_ATTRIBUTE(SEQUENCE_NUMBER1, 13); + +DEFPARTICLE_ATTRIBUTE(HITBOX_INDEX, 14); + +DEFPARTICLE_ATTRIBUTE(HITBOX_RELATIVE_XYZ, 15); + +DEFPARTICLE_ATTRIBUTE(ALPHA2, 16); + +DEFPARTICLE_ATTRIBUTE(TRACE_P0, 17); +DEFPARTICLE_ATTRIBUTE(TRACE_P1, 18); +DEFPARTICLE_ATTRIBUTE(TRACE_HIT_T, 19); +DEFPARTICLE_ATTRIBUTE(TRACE_HIT_NORMAL, 20); + + +#define MAX_PARTICLE_CONTROL_POINTS 64 + +#define ATTRIBUTES_WHICH_ARE_VEC3S_MASK ( PARTICLE_ATTRIBUTE_TRACE_P0_MASK | PARTICLE_ATTRIBUTE_TRACE_P1_MASK | \ + PARTICLE_ATTRIBUTE_TRACE_HIT_NORMAL | PARTICLE_ATTRIBUTE_XYZ_MASK | \ + PARTICLE_ATTRIBUTE_PREV_XYZ_MASK | PARTICLE_ATTRIBUTE_TINT_RGB_MASK | \ + PARTICLE_ATTRIBUTE_HITBOX_RELATIVE_XYZ_MASK ) +#define ATTRIBUTES_WHICH_ARE_0_TO_1 (PARTICLE_ATTRIBUTE_ALPHA_MASK | PARTICLE_ATTRIBUTE_ALPHA2_MASK) +#define ATTRIBUTES_WHICH_ARE_ANGLES (PARTICLE_ATTRIBUTE_ROTATION_MASK | PARTICLE_ATTRIBUTE_YAW_MASK ) +#define ATTRIBUTES_WHICH_ARE_INTS (PARTICLE_ATTRIBUTE_PARTICLE_ID_MASK | PARTICLE_ATTRIBUTE_HITBOX_INDEX_MASK ) + +#if defined( _X360 ) +#define MAX_PARTICLES_IN_A_SYSTEM 2000 +#else +#define MAX_PARTICLES_IN_A_SYSTEM 5000 +#endif + +#define MEASURE_PARTICLE_PERF 0 + + +enum ParticleFunctionType_t +{ + FUNCTION_RENDERER = 0, + FUNCTION_OPERATOR, + FUNCTION_INITIALIZER, + FUNCTION_EMITTER, + FUNCTION_CHILDREN, + FUNCTION_FORCEGENERATOR, + FUNCTION_CONSTRAINT, + PARTICLE_FUNCTION_COUNT +}; + +struct CParticleVisibilityInputs +{ + float m_flCameraBias; + float m_flInputMin; + float m_flInputMax; + float m_flAlphaScaleMin; + float m_flAlphaScaleMax; + float m_flRadiusScaleMin; + float m_flRadiusScaleMax; + float m_flProxyRadius; + float m_flBBoxScale; + bool m_bUseBBox; + int m_nCPin; +}; + +struct ModelHitBoxInfo_t +{ + Vector m_vecBoxMins; + Vector m_vecBoxMaxes; + matrix3x4_t m_Transform; +}; + +class CModelHitBoxesInfo +{ +public: + float m_flLastUpdateTime; + float m_flPrevLastUpdateTime; + int m_nNumHitBoxes; + int m_nNumPrevHitBoxes; + ModelHitBoxInfo_t* m_pHitBoxes; + ModelHitBoxInfo_t* m_pPrevBoxes; + + bool CurAndPrevValid(void) const + { + return (m_nNumHitBoxes && (m_nNumPrevHitBoxes == m_nNumHitBoxes)); + } + + CModelHitBoxesInfo(void) + { + m_flLastUpdateTime = -1; + m_nNumHitBoxes = 0; + m_nNumPrevHitBoxes = 0; + m_pHitBoxes = NULL; + m_pPrevBoxes = NULL; + } + + ~CModelHitBoxesInfo(void) + { + if (m_pHitBoxes) + delete[] m_pHitBoxes; + if (m_pPrevBoxes) + delete[] m_pPrevBoxes; + } + +}; + + + + +#define PARTICLE_SYSTEM_QUERY_INTERFACE_VERSION "VParticleSystemQuery001" + +class IParticleSystemQuery : public IAppSystem +{ +public: + virtual void GetLightingAtPoint(const Vector& vecOrigin, Color& tint) = 0; + virtual void TraceLine(const Vector& vecAbsStart, + const Vector& vecAbsEnd, unsigned int mask, + const class IHandleEntity* ignore, + int collisionGroup, + CBaseTrace* ptr) = 0; + + virtual bool MovePointInsideControllingObject(CParticleCollection* pParticles, + void* pObject, + Vector* pPnt) + { + return true; + } + + virtual bool IsPointInControllingObjectHitBox( + CParticleCollection* pParticles, + int nControlPointNumber, Vector vecPos, bool bBBoxOnly = false) + { + return true; + } + + virtual int GetCollisionGroupFromName(const char* pszCollisionGroupName) + { + return 0; + } + + virtual void GetRandomPointsOnControllingObjectHitBox( + CParticleCollection* pParticles, + int nControlPointNumber, + int nNumPtsOut, + float flBBoxScale, + int nNumTrysToGetAPointInsideTheModel, + Vector* pPntsOut, + Vector vecDirectionBias, + Vector* pHitBoxRelativeCoordOut = NULL, + int* pHitBoxIndexOut = NULL) = 0; + + + virtual int GetControllingObjectHitBoxInfo( + CParticleCollection* pParticles, + int nControlPointNumber, + int nBufSize, + ModelHitBoxInfo_t* pHitBoxOutputBuffer) + { + return 0; + } + + virtual Vector GetLocalPlayerPos(void) + { + return vec3_origin; + } + + virtual void GetLocalPlayerEyeVectors(Vector* pForward, Vector* pRight = NULL, Vector* pUp = NULL) + { + *pForward = vec3_origin; + *pRight = vec3_origin; + *pUp = vec3_origin; + } + + virtual float GetPixelVisibility(int* pQueryHandle, const Vector& vecOrigin, float flScale) = 0; + + virtual void SetUpLightingEnvironment(const Vector& pos) + { + } +}; + + +typedef int ParticleSystemHandle_t; + +class CParticleSystemMgr +{ +public: + CParticleSystemMgr(); + ~CParticleSystemMgr(); + + bool Init(IParticleSystemQuery* pQuery); + + void AddBuiltinSimulationOperators(void); + void AddBuiltinRenderingOperators(void); + + + + void AddParticleOperator(ParticleFunctionType_t nOpType, IParticleOperatorDefinition* pOpFactory); + + bool ReadParticleConfigFile(const char* pFileName, bool bPrecache, bool bDecommitTempMemory = true); + bool ReadParticleConfigFile(CUtlBuffer& buf, bool bPrecache, bool bDecommitTempMemory = true, const char* pFileName = NULL); + void DecommitTempMemory(); + + bool WriteParticleConfigFile(const char* pParticleSystemName, CUtlBuffer& buf, bool bPreventNameBasedLookup = false); + bool WriteParticleConfigFile(const DmObjectId_t& id, CUtlBuffer& buf, bool bPreventNameBasedLookup = false); + + CParticleCollection* CreateParticleCollection(const char* pParticleSystemName, float flDelay = 0.0f, int nRandomSeed = 0); + + CParticleCollection* CreateParticleCollection(const DmObjectId_t& id, float flDelay = 0.0f, int nRandomSeed = 0); + + bool IsParticleSystemDefined(const char* pParticleSystemName); + bool IsParticleSystemDefined(const DmObjectId_t& id); + + ParticleSystemHandle_t GetParticleSystemIndex(const char* pParticleSystemName); + + const char* GetParticleSystemNameFromIndex(ParticleSystemHandle_t iIndex); + + int GetParticleSystemCount(void); + + CUtlVector< IParticleOperatorDefinition*>& GetAvailableParticleOperatorList(ParticleFunctionType_t nWhichList); + + const DmxElementUnpackStructure_t* GetParticleSystemDefinitionUnpackStructure(); + + void ShouldLoadSheets(bool bLoadSheets); + CSheet* FindOrLoadSheet(char const* pszFname, ITexture* pTexture); + CSheet* FindOrLoadSheet(IMaterial* pMaterial); + void FlushAllSheets(void); + + + void ResetRenderCache(void); + void AddToRenderCache(CParticleCollection* pParticles); + void DrawRenderCache(bool bShadowDepth); + + IParticleSystemQuery* Query(void) { return m_pQuery; } + + const char* GetParticleFieldName(int nParticleField) const; + + CParticleSystemDefinition* FindParticleSystem(const char* pName); + CParticleSystemDefinition* FindParticleSystem(const DmObjectId_t& id); + + void CommitProfileInformation(bool bCommit); + + void DumpProfileInformation(void); + + void PrecacheParticleSystem(const char* pName); + void UncacheAllParticleSystems(); + + void SetLastSimulationTime(float flTime); + float GetLastSimulationTime() const; + + int Debug_GetTotalParticleCount() const; + bool Debug_FrameWarningNeededTestAndReset(); + float ParticleThrottleScaling() const; + bool ParticleThrottleRandomEnable() const; + + void TallyParticlesRendered(int nVertexCount, int nIndexCount = 0); + +private: + struct RenderCache_t + { + IMaterial* m_pMaterial; + CUtlVector< CParticleCollection* > m_ParticleCollections; + }; + + struct BatchStep_t + { + CParticleCollection* m_pParticles; + CParticleOperatorInstance* m_pRenderer; + void* m_pContext; + int m_nFirstParticle; + int m_nParticleCount; + int m_nVertCount; + }; + + struct Batch_t + { + int m_nVertCount; + int m_nIndexCount; + CUtlVector< BatchStep_t > m_BatchStep; + }; + + bool ReadParticleDefinitions(CUtlBuffer& buf, const char* pFileName, bool bPrecache, bool bDecommitTempMemory); + void AddParticleSystem(CDmxElement* pParticleSystem); + + CDmxElement* CreateParticleDmxElement(const DmObjectId_t& id); + CDmxElement* CreateParticleDmxElement(const char* pParticleSystemName); + + bool WriteParticleConfigFile(CDmxElement* pParticleSystem, CUtlBuffer& buf, bool bPreventNameBasedLookup); + + void BuildBatchList(int iRenderCache, IMatRenderContext* pRenderContext, CUtlVector< Batch_t >& batches); + + CUtlVector m_ParticleOperators[PARTICLE_FUNCTION_COUNT]; + + CParticleSystemDictionary* m_pParticleSystemDictionary; + + typedef CUtlStringMap< CSheet* > SheetsCache_t; + SheetsCache_t m_SheetList; + + void AttachKillList(CParticleCollection* pParticles); + void DetachKillList(CParticleCollection* pParticles); + + CParticleCollection* m_pVisualizedParticles; + DmObjectId_t m_VisualizedOperatorId; + IParticleSystemQuery* m_pQuery; + CUtlVector< RenderCache_t > m_RenderCache; + IMaterial* m_pShadowDepthMaterial; + float m_flLastSimulationTime; + + bool m_bDidInit; + bool m_bUsingDefaultQuery; + bool m_bShouldLoadSheets; + + int m_nNumFramesMeasured; + + enum { c_nNumFramesTracked = 10 }; + int m_nParticleVertexCountHistory[c_nNumFramesTracked]; + float m_fParticleCountScaling; + int m_nParticleIndexCount; + int m_nParticleVertexCount; + bool m_bFrameWarningNeeded; + + friend class CParticleSystemDefinition; + friend class CParticleCollection; +}; + +extern CParticleSystemMgr* g_pParticleSystemMgr; + + +enum ParticleOperatorId_t +{ + OPERATOR_GENERIC = -2, + OPERATOR_SINGLETON = -1, + + OPERATOR_PI_POSITION, + OPERATOR_PI_RADIUS, + OPERATOR_PI_ALPHA, + OPERATOR_PI_TINT_RGB, + OPERATOR_PI_ROTATION, + OPERATOR_PI_YAW, + + OPERATOR_ID_COUNT, +}; + + +class IParticleOperatorDefinition +{ +public: + virtual const char* GetName() const = 0; + virtual CParticleOperatorInstance* CreateInstance(const DmObjectId_t& id) const = 0; + virtual const DmxElementUnpackStructure_t* GetUnpackStructure() const = 0; + virtual ParticleOperatorId_t GetId() const = 0; + virtual bool IsObsolete() const = 0; + virtual size_t GetClassSize() const = 0; + +#if MEASURE_PARTICLE_PERF + float m_flMaxExecutionTime; + float m_flTotalExecutionTime; + float m_flUncomittedTime; + + FORCEINLINE void RecordExecutionTime(float flETime) + { + m_flUncomittedTime += flETime; + m_flMaxExecutionTime = MAX(m_flMaxExecutionTime, flETime); + } + + FORCEINLINE float TotalRecordedExecutionTime(void) const + { + return m_flTotalExecutionTime; + } + + FORCEINLINE float MaximumRecordedExecutionTime(void) const + { + return m_flMaxExecutionTime; + } +#endif +}; + + +class CParticleOperatorInstance +{ +public: + void* operator new(size_t nSize); + void* operator new(size_t size, int nBlockUse, const char* pFileName, int nLine); + void operator delete(void* pData); + void operator delete(void* p, int nBlockUse, const char* pFileName, int nLine); + + virtual void InitParams(CParticleSystemDefinition* pDef, CDmxElement* pElement) + { + } + + virtual size_t GetRequiredContextBytes() const + { + return 0; + } + + virtual void InitializeContextData(CParticleCollection* pParticles, void* pContext) const + { + } + + virtual uint32 GetWrittenAttributes(void) const = 0; + virtual uint32 GetReadAttributes(void) const = 0; + virtual uint64 GetReadControlPointMask() const + { + return 0; + } + + virtual uint32 GetReadInitialAttributes(void) const + { + return 0; + } + + virtual void Operate(CParticleCollection* pParticles, float flOpStrength, void* pContext) const + { + } + + virtual void Render(IMatRenderContext* pRenderContext, + CParticleCollection* pParticles, void* pContext) const + { + } + + virtual bool IsBatchable() const + { + return true; + } + + virtual void RenderUnsorted(CParticleCollection* pParticles, void* pContext, IMatRenderContext* pRenderContext, CMeshBuilder& meshBuilder, int nVertexOffset, int nFirstParticle, int nParticleCount) const + { + } + + virtual int GetParticlesToRender(CParticleCollection* pParticles, void* pContext, int nFirstParticle, int nRemainingVertices, int nRemainingIndices, int* pVertsUsed, int* pIndicesUsed) const + { + *pVertsUsed = 0; + *pIndicesUsed = 0; + return 0; + } + + + virtual uint32 Emit(CParticleCollection* pParticles, float flOpCurStrength, + void* pContext) const + { + return 0; + } + + virtual void StopEmission(CParticleCollection* pParticles, void* pContext, bool bInfiniteOnly = false) const + { + } + virtual void StartEmission(CParticleCollection* pParticles, void* pContext, bool bInfiniteOnly = false) const + { + } + virtual void Restart(CParticleCollection* pParticles, void* pContext) {} + + virtual void InitParticleSystem(CParticleCollection* pParticles, void* pContext) const + { + } + + + virtual void AddForces(FourVectors* AccumulatedForces, + CParticleCollection* pParticles, + int nBlocks, + float flCurStrength, + void* pContext) const + { + } + + + virtual void SetupConstraintPerFrameData(CParticleCollection* pParticles, + void* pContext) const + { + } + + + virtual bool EnforceConstraint(int nStartBlock, + int nNumBlocks, + CParticleCollection* pParticles, + void* pContext, + int nNumValidParticlesInLastChunk) const + { + return false; + } + + virtual bool IsFinalConstraint(void) const + { + return false; + } + + virtual bool InitMultipleOverride() + { + return false; + } + + + virtual bool IsScrubSafe() + { + return false; + } + + virtual void InitNewParticlesScalar(CParticleCollection* pParticles, int nFirstParticle, int n_particles, int attribute_write_mask, void* pContext) const + { + } + + virtual void InitNewParticlesBlock(CParticleCollection* pParticles, int start_block, int n_blocks, int attribute_write_mask, void* pContext) const + { + InitNewParticlesScalar(pParticles, 4 * start_block, 4 * n_blocks, attribute_write_mask, pContext); + } + + void InitNewParticles(CParticleCollection* pParticles, int nFirstParticle, int n_particles, int attribute_write_mask, void* pContext) const; + + + virtual bool MayCreateMoreParticles(CParticleCollection* pParticles, void* pContext) const + { + return false; + } + + const IParticleOperatorDefinition* GetDefinition() + { + return m_pDef; + } + + virtual bool ShouldRunBeforeEmitters(void) const + { + return false; + } + + virtual bool RequiresOrderInvariance(void) const + { + return false; + } + + virtual void SkipToTime(float flTime, CParticleCollection* pParticles, void* pContext) const {} + + const DmObjectId_t& GetId() { return m_Id; } + + virtual void Render(CParticleCollection* pParticles) const {} + + int RandomInt(int nMin, int nMax) + { + Assert(0); + return 0; + } + + float RandomFloat(float flMinVal = 0.0f, float flMaxVal = 1.0f) + { + Assert(0); + return 0.0f; + } + + float RandomFloatExp(float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f) + { + Assert(0); + return 0.0f; + } + + float m_flOpStartFadeInTime; + float m_flOpEndFadeInTime; + float m_flOpStartFadeOutTime; + float m_flOpEndFadeOutTime; + float m_flOpFadeOscillatePeriod; + + virtual ~CParticleOperatorInstance(void) + { + } + +protected: + void InitScalarAttributeRandomRangeBlock(int nAttributeId, float fMinValue, float fMaxValue, + CParticleCollection* pParticles, int nStartBlock, int nBlockCount) const; + void InitScalarAttributeRandomRangeExpBlock(int nAttributeId, float fMinValue, float fMaxValue, float fExp, + CParticleCollection* pParticles, int nStartBlock, int nBlockCount) const; + void AddScalarAttributeRandomRangeBlock(int nAttributeId, float fMinValue, float fMaxValue, float fExp, + CParticleCollection* pParticles, int nStartBlock, int nBlockCount, bool bRandomlyInvert) const; + +private: + friend class CParticleCollection; + + const IParticleOperatorDefinition* m_pDef; + void SetDefinition(const IParticleOperatorDefinition* pDef, const DmObjectId_t& id) + { + m_pDef = pDef; + CopyUniqueId(id, &m_Id); + } + + DmObjectId_t m_Id; + + template friend class CParticleOperatorDefinition; +}; + +class CParticleRenderOperatorInstance : public CParticleOperatorInstance +{ +public: + + CParticleVisibilityInputs VisibilityInputs; +}; + +template < class T > +class CParticleOperatorDefinition : public IParticleOperatorDefinition +{ +public: + CParticleOperatorDefinition(const char* pFactoryName, ParticleOperatorId_t id, bool bIsObsolete) : m_pFactoryName(pFactoryName), m_Id(id) + { +#if MEASURE_PARTICLE_PERF + m_flTotalExecutionTime = 0.0f; + m_flMaxExecutionTime = 0.0f; + m_flUncomittedTime = 0.0f; +#endif + m_bIsObsolete = bIsObsolete; + } + + virtual const char* GetName() const + { + return m_pFactoryName; + } + + virtual ParticleOperatorId_t GetId() const + { + return m_Id; + } + + virtual CParticleOperatorInstance* CreateInstance(const DmObjectId_t& id) const + { + CParticleOperatorInstance* pOp = new T; + pOp->SetDefinition(this, id); + return pOp; + } + + virtual const DmxElementUnpackStructure_t* GetUnpackStructure() const + { + return m_pUnpackParams; + } + + virtual bool IsObsolete() const + { + return m_bIsObsolete; + } + + virtual size_t GetClassSize() const + { + return sizeof(T); + } + +private: + const char* m_pFactoryName; + ParticleOperatorId_t m_Id; + bool m_bIsObsolete; + static DmxElementUnpackStructure_t* m_pUnpackParams; +}; + +#define DECLARE_PARTICLE_OPERATOR( _className ) \ + DECLARE_DMXELEMENT_UNPACK() \ + friend class CParticleOperatorDefinition<_className > + +#define DEFINE_PARTICLE_OPERATOR( _className, _operatorName, _id ) \ + static CParticleOperatorDefinition<_className> s_##_className##Factory( _operatorName, _id, false ) + +#define DEFINE_PARTICLE_OPERATOR_OBSOLETE( _className, _operatorName, _id ) \ + static CParticleOperatorDefinition<_className> s_##_className##Factory( _operatorName, _id, true ) + +#define BEGIN_PARTICLE_OPERATOR_UNPACK( _className ) \ + BEGIN_DMXELEMENT_UNPACK( _className ) \ + DMXELEMENT_UNPACK_FIELD( "operator start fadein","0", float, m_flOpStartFadeInTime ) \ + DMXELEMENT_UNPACK_FIELD( "operator end fadein","0", float, m_flOpEndFadeInTime ) \ + DMXELEMENT_UNPACK_FIELD( "operator start fadeout","0", float, m_flOpStartFadeOutTime ) \ + DMXELEMENT_UNPACK_FIELD( "operator end fadeout","0", float, m_flOpEndFadeOutTime ) \ + DMXELEMENT_UNPACK_FIELD( "operator fade oscillate","0", float, m_flOpFadeOscillatePeriod ) + +#define END_PARTICLE_OPERATOR_UNPACK( _className ) \ + END_DMXELEMENT_UNPACK_TEMPLATE( _className, CParticleOperatorDefinition<_className>::m_pUnpackParams ) + +#define BEGIN_PARTICLE_RENDER_OPERATOR_UNPACK( _className ) \ + BEGIN_PARTICLE_OPERATOR_UNPACK( _className ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Proxy Input Control Point Number", "-1", int, VisibilityInputs.m_nCPin ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Proxy Radius", "1.0", float, VisibilityInputs.m_flProxyRadius ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility input minimum","0", float, VisibilityInputs.m_flInputMin ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility input maximum","1", float, VisibilityInputs.m_flInputMax ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Alpha Scale minimum","0", float, VisibilityInputs.m_flAlphaScaleMin ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Alpha Scale maximum","1", float, VisibilityInputs.m_flAlphaScaleMax ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Radius Scale minimum","1", float, VisibilityInputs.m_flRadiusScaleMin ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Radius Scale maximum","1", float, VisibilityInputs.m_flRadiusScaleMax ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Camera Depth Bias", "0", float, VisibilityInputs.m_flCameraBias ) + +#define REGISTER_PARTICLE_OPERATOR( _type, _className ) \ + g_pParticleSystemMgr->AddParticleOperator( _type, &s_##_className##Factory ) + + + +enum +{ + PCFLAGS_FIRST_FRAME = 0x1, + PCFLAGS_PREV_CONTROL_POINTS_INITIALIZED = 0x2, +}; + + + +#define DEBUG_PARTICLE_SORT 0 + +struct ParticleRenderData_t +{ + float m_flSortKey; + int m_nIndex; + float m_flRadius; +#if VALVE_LITTLE_ENDIAN + uint8 m_nAlpha; + uint8 m_nAlphaPad[3]; +#else + uint8 m_nAlphaPad[3]; + uint8 m_nAlpha; +#endif +}; + +struct ExtendedParticleRenderData_t : ParticleRenderData_t +{ + float m_flX; + float m_flY; + float m_flZ; + float m_flPad; +}; + + +typedef struct ALIGN16 _FourInts +{ + int32 m_nValue[4]; +} ALIGN16_POST FourInts; + + + +struct CPathParameters +{ + int m_nStartControlPointNumber; + int m_nEndControlPointNumber; + int m_nBulgeControl; + float m_flBulge; + float m_flMidPoint; + + void ClampControlPointIndices(void) + { + m_nStartControlPointNumber = MAX(0, MIN(MAX_PARTICLE_CONTROL_POINTS - 1, m_nStartControlPointNumber)); + m_nEndControlPointNumber = MAX(0, MIN(MAX_PARTICLE_CONTROL_POINTS - 1, m_nEndControlPointNumber)); + } +}; + +struct CParticleVisibilityData +{ + float m_flAlphaVisibility; + float m_flRadiusVisibility; + float m_flCameraBias; + bool m_bUseVisibility; +}; + +struct CParticleControlPoint +{ + Vector m_Position; + Vector m_PrevPosition; + + Vector m_ForwardVector; + Vector m_UpVector; + Vector m_RightVector; + + void* m_pObject; + + int m_nParent; +}; + + +struct CParticleSIMDTransformation +{ + FourVectors m_v4Origin; + FourVectors m_v4Fwd; + FourVectors m_v4Up; + FourVectors m_v4Right; + + + FORCEINLINE void VectorRotate(FourVectors& InPnt) + { + fltx4 fl4OutX = SubSIMD(AddSIMD(MulSIMD(InPnt.x, m_v4Fwd.x), MulSIMD(InPnt.z, m_v4Up.x)), MulSIMD(InPnt.y, m_v4Right.x)); + fltx4 fl4OutY = SubSIMD(AddSIMD(MulSIMD(InPnt.x, m_v4Fwd.y), MulSIMD(InPnt.z, m_v4Up.y)), MulSIMD(InPnt.y, m_v4Right.y)); + InPnt.z = SubSIMD(AddSIMD(MulSIMD(InPnt.x, m_v4Fwd.z), MulSIMD(InPnt.z, m_v4Up.z)), MulSIMD(InPnt.y, m_v4Right.z)); + InPnt.x = fl4OutX; + InPnt.y = fl4OutY; + } + + FORCEINLINE void VectorTransform(FourVectors& InPnt) + { + VectorRotate(InPnt); + InPnt.x = AddSIMD(InPnt.x, m_v4Origin.x); + InPnt.y = AddSIMD(InPnt.y, m_v4Origin.y); + InPnt.z = AddSIMD(InPnt.z, m_v4Origin.z); + } +}; + +#define NUM_COLLISION_CACHE_MODES 4 + +class CParticleCollection +{ +public: + ~CParticleCollection(void); + + void Restart(); + + void RecomputeBounds(void); + + void SetControlPoint(int nWhichPoint, const Vector& v); + void SetControlPointObject(int nWhichPoint, void* pObject); + + void SetControlPointOrientation(int nWhichPoint, const Vector& forward, + const Vector& right, const Vector& up); + void SetControlPointOrientation(int nWhichPoint, const Quaternion& q); + void SetControlPointForwardVector(int nWhichPoint, const Vector& v); + void SetControlPointUpVector(int nWhichPoint, const Vector& v); + void SetControlPointRightVector(int nWhichPoint, const Vector& v); + void SetControlPointParent(int nWhichPoint, int n); + + const float* GetFloatAttributePtr(int nAttribute, int nParticleNumber) const; + const int* GetIntAttributePtr(int nAttribute, int nParticleNumber) const; + const fltx4* GetM128AttributePtr(int nAttribute, size_t* pStrideOut) const; + const FourVectors* Get4VAttributePtr(int nAttribute, size_t* pStrideOut) const; + const FourInts* Get4IAttributePtr(int nAttribute, size_t* pStrideOut) const; + const int* GetIntAttributePtr(int nAttribute, size_t* pStrideOut) const; + + + int* GetIntAttributePtrForWrite(int nAttribute, int nParticleNumber); + + float* GetFloatAttributePtrForWrite(int nAttribute, int nParticleNumber); + fltx4* GetM128AttributePtrForWrite(int nAttribute, size_t* pStrideOut); + FourVectors* Get4VAttributePtrForWrite(int nAttribute, size_t* pStrideOut); + + const float* GetInitialFloatAttributePtr(int nAttribute, int nParticleNumber) const; + const fltx4* GetInitialM128AttributePtr(int nAttribute, size_t* pStrideOut) const; + const FourVectors* GetInitial4VAttributePtr(int nAttribute, size_t* pStrideOut) const; + float* GetInitialFloatAttributePtrForWrite(int nAttribute, int nParticleNumber); + fltx4* GetInitialM128AttributePtrForWrite(int nAttribute, size_t* pStrideOut); + + void Simulate(float dt, bool updateBboxOnly); + void SkipToTime(float t); + + void Render(IMatRenderContext* pRenderContext, bool bTranslucentOnly = false, void* pCameraObject = NULL); + + bool IsValid(void) const; + const char* GetName() const; + + bool IsFinished(void); + + bool IsValidAttributePtr(int nAttribute, const void* pPtr) const; + + void SwapPosAndPrevPos(void); + + void SetNActiveParticles(int nCount); + void KillParticle(int nPidx); + + void StopEmission(bool bInfiniteOnly = false, bool bRemoveAllParticles = false, bool bWakeOnStop = false); + void StartEmission(bool bInfiniteOnly = false); + void SetDormant(bool bDormant); + + const Vector& GetControlPointAtCurrentTime(int nControlPoint) const; + void GetControlPointOrientationAtCurrentTime(int nControlPoint, Vector* pForward, Vector* pRight, Vector* pUp) const; + void GetControlPointTransformAtCurrentTime(int nControlPoint, matrix3x4_t* pMat); + void GetControlPointTransformAtCurrentTime(int nControlPoint, VMatrix* pMat); + int GetControlPointParent(int nControlPoint) const; + + void GetControlPointAtTime(int nControlPoint, float flTime, Vector* pControlPoint) const; + void GetControlPointAtPrevTime(int nControlPoint, Vector* pControlPoint) const; + void GetControlPointOrientationAtTime(int nControlPoint, float flTime, Vector* pForward, Vector* pRight, Vector* pUp); + void GetControlPointTransformAtTime(int nControlPoint, float flTime, matrix3x4_t* pMat); + void GetControlPointTransformAtTime(int nControlPoint, float flTime, VMatrix* pMat); + void GetControlPointTransformAtTime(int nControlPoint, float flTime, CParticleSIMDTransformation* pXForm); + int GetHighestControlPoint(void) const; + + bool HasMoved() const; + + bool ReadsControlPoint(int nPoint) const; + + int RandomInt(int nMin, int nMax); + float RandomFloat(float flMin, float flMax); + float RandomFloatExp(float flMin, float flMax, float flExponent); + void RandomVector(float flMin, float flMax, Vector* pVector); + void RandomVector(const Vector& vecMin, const Vector& vecMax, Vector* pVector); + float RandomVectorInUnitSphere(Vector* pVector); + + int RandomInt(int nRandomSampleId, int nMin, int nMax); + float RandomFloat(int nRandomSampleId, float flMin, float flMax); + float RandomFloatExp(int nRandomSampleId, float flMin, float flMax, float flExponent); + void RandomVector(int nRandomSampleId, float flMin, float flMax, Vector* pVector); + void RandomVector(int nRandomSampleId, const Vector& vecMin, const Vector& vecMax, Vector* pVector); + float RandomVectorInUnitSphere(int nRandomSampleId, Vector* pVector); + + fltx4 RandomFloat(const FourInts& ParticleID, int nRandomSampleOffset); + + + int OperatorRandomSampleOffset() const; + + void GetBounds(Vector* pMin, Vector* pMax); + + void VisualizeOperator(const DmObjectId_t* pOpId = NULL); + + bool UsesPowerOfTwoFrameBufferTexture(bool bThisFrame) const; + + bool UsesFullFrameBufferTexture(bool bThisFrame) const; + + bool IsTranslucent() const; + + bool IsTwoPass() const; + + bool IsBatchable() const; + + int GetRendererCount() const; + CParticleOperatorInstance* GetRenderer(int i); + void* GetRendererContext(int i); + + + bool CheckIfOperatorShouldRun(CParticleOperatorInstance const* op, float* pflCurStrength = NULL); + + Vector TransformAxis(const Vector& SrcAxis, bool bLocalSpace, int nControlPointNumber = 0); + + const ParticleRenderData_t* GetRenderList(IMatRenderContext* pRenderContext, bool bSorted, int* pNparticles, CParticleVisibilityData* pVisibilityData); + + void CalculatePathValues(CPathParameters const& PathIn, + float flTimeStamp, + Vector* pStartPnt, + Vector* pMidPnt, + Vector* pEndPnt + ); + + int GetGroupID() const; + + void InitializeNewParticles(int nFirstParticle, int nParticleCount, uint32 nInittedMask); + + void UpdateHitBoxInfo(int nControlPointNumber); + + void UnlinkFromDefList(); + + CParticleCollection* GetNextCollectionUsingSameDef() { return m_pNextDef; } + + CUtlReference< CSheet > m_Sheet; + + + +protected: + CParticleCollection(); + + bool Init(const char* pParticleSystemName); + bool Init(CParticleSystemDefinition* pDef); + + void BloatBoundsUsingControlPoint(); + +private: + void GenerateSortedIndexList(Vector vecCameraPos, CParticleVisibilityData* pVisibilityData, bool bSorted); + + void Init(CParticleSystemDefinition* pDef, float flDelay, int nRandomSeed); + void InitStorage(CParticleSystemDefinition* pDef); + void InitParticleCreationTime(int nFirstParticle, int nNumToInit); + void CopyInitialAttributeValues(int nStartParticle, int nNumParticles); + void ApplyKillList(void); + void SetAttributeToConstant(int nAttribute, float fValue); + void SetAttributeToConstant(int nAttribute, float fValueX, float fValueY, float fValueZ); + void InitParticleAttributes(int nStartParticle, int nNumParticles, int nAttrsLeftToInit); + + void FillAttributeWithConstant(int nAttribute, float fValue); + + void UpdatePrevControlPoints(float dt); + + float* GetConstantAttributeMemory(int nAttribute); + + void SwapAdjacentParticles(int hParticle); + + void UnlinkParticle(int hParticle); + + void InsertParticleBefore(int hParticle, int hBefore); + + void MoveParticle(int nInitialIndex, int nNewIndex); + + float ComputeSqrDistanceToParticle(int hParticle, const Vector& vecPosition) const; + + void GrowDistSqrBounds(float flDistSqr); + + void SimulateFirstFrame(); + + bool SystemContainsParticlesWithBoolSet(bool CParticleCollection::* pField) const; + bool ContainsOpaqueCollections(); + bool ComputeUsesPowerOfTwoFrameBufferTexture(); + bool ComputeUsesFullFrameBufferTexture(); + bool ComputeIsTranslucent(); + bool ComputeIsTwoPass(); + bool ComputeIsBatchable(); + bool ComputeRequiresOrderInvariance(); + + void LabelTextureUsage(void); + + void LinkIntoDefList(); + +public: + fltx4 m_fl4CurTime; + + int m_nPaddedActiveParticles; + float m_flCurTime; + + int m_nActiveParticles; + float m_flDt; + float m_flPreviousDt; + float m_flNextSleepTime; + + CUtlReference< CParticleSystemDefinition > m_pDef; + int m_nAllocatedParticles; + int m_nMaxAllowedParticles; + bool m_bDormant; + bool m_bEmissionStopped; + bool m_bRequiresOrderInvariance; + + int m_LocalLightingCP; + Color m_LocalLighting; + + CParticleControlPoint m_ControlPoints[MAX_PARTICLE_CONTROL_POINTS]; + + CModelHitBoxesInfo m_ControlPointHitBoxes[MAX_PARTICLE_CONTROL_POINTS]; + + uint8* m_pOperatorContextData; + CParticleCollection* m_pNext; + CParticleCollection* m_pPrev; + + struct CWorldCollideContextData* m_pCollisionCacheData[NUM_COLLISION_CACHE_MODES]; + CParticleCollection* m_pParent; + + CUtlIntrusiveDList m_Children; + + void* operator new(size_t nSize); + void* operator new(size_t size, int nBlockUse, const char* pFileName, int nLine); + void operator delete(void* pData); + void operator delete(void* p, int nBlockUse, const char* pFileName, int nLine); + + +protected: + bool m_bBoundsValid; + Vector m_MinBounds; + Vector m_MaxBounds; + int m_nHighestCP; + +private: + + + unsigned char* m_pParticleMemory; + unsigned char* m_pParticleInitialMemory; + unsigned char* m_pConstantMemory; + + int m_nPerParticleInitializedAttributeMask; + int m_nPerParticleUpdatedAttributeMask; + int m_nPerParticleReadInitialAttributeMask; + float* m_pParticleAttributes[MAX_PARTICLE_ATTRIBUTES]; + float* m_pParticleInitialAttributes[MAX_PARTICLE_ATTRIBUTES]; + size_t m_nParticleFloatStrides[MAX_PARTICLE_ATTRIBUTES]; + size_t m_nParticleInitialFloatStrides[MAX_PARTICLE_ATTRIBUTES]; + + float* m_pConstantAttributes; + + uint64 m_nControlPointReadMask; + int m_nParticleFlags; + bool m_bIsScrubbable : 1; + bool m_bIsRunningInitializers : 1; + bool m_bIsRunningOperators : 1; + bool m_bIsTranslucent : 1; + bool m_bIsTwoPass : 1; + bool m_bAnyUsesPowerOfTwoFrameBufferTexture : 1; + bool m_bAnyUsesFullFrameBufferTexture : 1; + bool m_bIsBatchable : 1; + + bool m_bUsesPowerOfTwoFrameBufferTexture; + bool m_bUsesFullFrameBufferTexture; + + int m_nDrawnFrames; + int m_nSimulatedFrames; + + Vector m_Center; + + int m_nUniqueParticleId; + + int m_nRandomQueryCount; + int m_nRandomSeed; + int m_nOperatorRandomSampleOffset; + + float m_flMinDistSqr; + float m_flMaxDistSqr; + float m_flOOMaxDistSqr; + Vector m_vecLastCameraPos; + float m_flLastMinDistSqr; + float m_flLastMaxDistSqr; + + int m_nNumParticlesToKill; + int* m_pParticleKillList; + + CParticleCollection* m_pNextDef; + CParticleCollection* m_pPrevDef; + + void LoanKillListTo(CParticleCollection* pBorrower) const; + bool HasAttachedKillList(void) const; + + + CParticleOperatorInstance* m_pRenderOp; + friend class CParticleSystemMgr; + friend class CParticleOperatorInstance; +}; + + + +class CM128InitialAttributeIterator : public CStridedConstPtr +{ +public: + FORCEINLINE CM128InitialAttributeIterator(int nAttribute, CParticleCollection* pParticles) + { + m_pData = pParticles->GetInitialM128AttributePtr(nAttribute, &m_nStride); + } +}; + + +class CM128AttributeIterator : public CStridedConstPtr +{ +public: + FORCEINLINE CM128AttributeIterator(int nAttribute, CParticleCollection* pParticles) + { + m_pData = pParticles->GetM128AttributePtr(nAttribute, &m_nStride); + } +}; + +class C4IAttributeIterator : public CStridedConstPtr +{ +public: + FORCEINLINE C4IAttributeIterator(int nAttribute, CParticleCollection* pParticles) + { + m_pData = pParticles->Get4IAttributePtr(nAttribute, &m_nStride); + } +}; + +class CM128AttributeWriteIterator : public CStridedPtr +{ +public: + FORCEINLINE CM128AttributeWriteIterator(void) + { + } + FORCEINLINE void Init(int nAttribute, CParticleCollection* pParticles) + { + m_pData = pParticles->GetM128AttributePtrForWrite(nAttribute, &m_nStride); + } + FORCEINLINE CM128AttributeWriteIterator(int nAttribute, CParticleCollection* pParticles) + { + Init(nAttribute, pParticles); + } +}; + +class C4VAttributeIterator : public CStridedConstPtr +{ +public: + FORCEINLINE C4VAttributeIterator(int nAttribute, CParticleCollection* pParticles) + { + m_pData = pParticles->Get4VAttributePtr(nAttribute, &m_nStride); + } +}; + +class C4VInitialAttributeIterator : public CStridedConstPtr +{ +public: + FORCEINLINE C4VInitialAttributeIterator(int nAttribute, CParticleCollection* pParticles) + { + m_pData = pParticles->GetInitial4VAttributePtr(nAttribute, &m_nStride); + } +}; + +class C4VAttributeWriteIterator : public CStridedPtr +{ +public: + FORCEINLINE C4VAttributeWriteIterator(int nAttribute, CParticleCollection* pParticles) + { + m_pData = pParticles->Get4VAttributePtrForWrite(nAttribute, &m_nStride); + } +}; + + +inline bool CParticleCollection::HasAttachedKillList(void) const +{ + return m_pParticleKillList != NULL; +} + +inline bool CParticleCollection::ReadsControlPoint(int nPoint) const +{ + return (m_nControlPointReadMask & (1ULL << nPoint)) != 0; +} + +inline void CParticleCollection::SetNActiveParticles(int nCount) +{ + Assert(nCount <= m_nMaxAllowedParticles); + m_nActiveParticles = nCount; + m_nPaddedActiveParticles = (nCount + 3) / 4; +} + +inline void CParticleCollection::SwapPosAndPrevPos(void) +{ + Assert(m_nParticleFloatStrides[PARTICLE_ATTRIBUTE_XYZ] == m_nParticleFloatStrides[PARTICLE_ATTRIBUTE_PREV_XYZ]); + V_swap(m_pParticleAttributes[PARTICLE_ATTRIBUTE_XYZ], m_pParticleAttributes[PARTICLE_ATTRIBUTE_PREV_XYZ]); +} + +inline void CParticleCollection::LoanKillListTo(CParticleCollection* pBorrower) const +{ + Assert(!pBorrower->m_pParticleKillList); + pBorrower->m_nNumParticlesToKill = 0; + pBorrower->m_pParticleKillList = m_pParticleKillList; +} + +inline void CParticleCollection::SetAttributeToConstant(int nAttribute, float fValue) +{ + float* fconst = m_pConstantAttributes + 4 * 3 * nAttribute; + fconst[0] = fconst[1] = fconst[2] = fconst[3] = fValue; +} + +inline void CParticleCollection::SetAttributeToConstant(int nAttribute, float fValueX, float fValueY, float fValueZ) +{ + float* fconst = m_pConstantAttributes + 4 * 3 * nAttribute; + fconst[0] = fconst[1] = fconst[2] = fconst[3] = fValueX; + fconst[4] = fconst[5] = fconst[6] = fconst[7] = fValueY; + fconst[8] = fconst[9] = fconst[10] = fconst[11] = fValueZ; +} + +inline void CParticleCollection::SetControlPoint(int nWhichPoint, const Vector& v) +{ + Assert((nWhichPoint >= 0) && (nWhichPoint < MAX_PARTICLE_CONTROL_POINTS)); + m_nHighestCP = MAX(m_nHighestCP, nWhichPoint); + m_ControlPoints[nWhichPoint].m_Position = v; + for (CParticleCollection* i = m_Children.m_pHead; i; i = i->m_pNext) + { + i->SetControlPoint(nWhichPoint, v); + } +} + +inline void CParticleCollection::SetControlPointObject(int nWhichPoint, void* pObject) +{ + Assert((nWhichPoint >= 0) && (nWhichPoint < MAX_PARTICLE_CONTROL_POINTS)); + m_ControlPoints[nWhichPoint].m_pObject = pObject; + for (CParticleCollection* i = m_Children.m_pHead; i; i = i->m_pNext) + { + i->SetControlPointObject(nWhichPoint, pObject); + } +} + +inline void CParticleCollection::SetControlPointOrientation(int nWhichPoint, const Vector& forward, + const Vector& right, const Vector& up) +{ + Assert((nWhichPoint >= 0) && (nWhichPoint < MAX_PARTICLE_CONTROL_POINTS)); + + if (fabs(DotProduct(forward, up)) <= 0.1f + && fabs(DotProduct(forward, right)) <= 0.1f + && fabs(DotProduct(right, up)) <= 0.1f) + { + m_ControlPoints[nWhichPoint].m_ForwardVector = forward; + m_ControlPoints[nWhichPoint].m_UpVector = up; + m_ControlPoints[nWhichPoint].m_RightVector = right; + + for (CParticleCollection* i = m_Children.m_pHead; i; i = i->m_pNext) + { + i->SetControlPointOrientation(nWhichPoint, forward, right, up); + } + } + else + { + Warning("Attempt to set particle collection %s to invalid orientation matrix\n", GetName()); + } +} + +inline Vector CParticleCollection::TransformAxis(const Vector& SrcAxis, bool bLocalSpace, + int nControlPointNumber) +{ + if (bLocalSpace) + { + return + (SrcAxis.x * m_ControlPoints[nControlPointNumber].m_RightVector) + + (SrcAxis.y * m_ControlPoints[nControlPointNumber].m_ForwardVector) + + (SrcAxis.z * m_ControlPoints[nControlPointNumber].m_UpVector); + } + else + return SrcAxis; +} + + +inline void CParticleCollection::SetControlPointOrientation(int nWhichPoint, const Quaternion& q) +{ + matrix3x4_t mat; + Vector vecForward, vecUp, vecRight; + QuaternionMatrix(q, mat); + MatrixVectors(mat, &vecForward, &vecRight, &vecUp); + SetControlPointOrientation(nWhichPoint, vecForward, vecRight, vecUp); +} + +inline void CParticleCollection::SetControlPointForwardVector(int nWhichPoint, const Vector& v) +{ + Assert((nWhichPoint >= 0) && (nWhichPoint < MAX_PARTICLE_CONTROL_POINTS)); + m_ControlPoints[nWhichPoint].m_ForwardVector = v; + for (CParticleCollection* i = m_Children.m_pHead; i; i = i->m_pNext) + { + i->SetControlPointForwardVector(nWhichPoint, v); + } +} + +inline void CParticleCollection::SetControlPointUpVector(int nWhichPoint, const Vector& v) +{ + Assert((nWhichPoint >= 0) && (nWhichPoint < MAX_PARTICLE_CONTROL_POINTS)); + m_ControlPoints[nWhichPoint].m_UpVector = v; + for (CParticleCollection* i = m_Children.m_pHead; i; i = i->m_pNext) + { + i->SetControlPointUpVector(nWhichPoint, v); + } +} + +inline void CParticleCollection::SetControlPointRightVector(int nWhichPoint, const Vector& v) +{ + Assert((nWhichPoint >= 0) && (nWhichPoint < MAX_PARTICLE_CONTROL_POINTS)); + m_ControlPoints[nWhichPoint].m_RightVector = v; + for (CParticleCollection* i = m_Children.m_pHead; i; i = i->m_pNext) + { + i->SetControlPointRightVector(nWhichPoint, v); + } +} + +inline void CParticleCollection::SetControlPointParent(int nWhichPoint, int n) +{ + Assert((nWhichPoint >= 0) && (nWhichPoint < MAX_PARTICLE_CONTROL_POINTS)); + m_ControlPoints[nWhichPoint].m_nParent = n; + for (CParticleCollection* i = m_Children.m_pHead; i; i = i->m_pNext) + { + i->SetControlPointParent(nWhichPoint, n); + } +} + + +inline float* CParticleCollection::GetConstantAttributeMemory(int nAttribute) +{ + return m_pConstantAttributes + 3 * 4 * nAttribute; +} + +inline int CParticleCollection::OperatorRandomSampleOffset() const +{ + return m_nOperatorRandomSampleOffset; +} + +inline int CParticleCollection::RandomInt(int nRandomSampleId, int nMin, int nMax) +{ + float flRand = s_pRandomFloats[(m_nRandomSeed + nRandomSampleId) & RANDOM_FLOAT_MASK]; + flRand *= (nMax + 1 - nMin); + int nRand = (int)flRand + nMin; + return nRand; +} + +inline float CParticleCollection::RandomFloat(int nRandomSampleId, float flMin, float flMax) +{ + float flRand = s_pRandomFloats[(m_nRandomSeed + nRandomSampleId) & RANDOM_FLOAT_MASK]; + flRand *= (flMax - flMin); + flRand += flMin; + return flRand; +} + +inline fltx4 CParticleCollection::RandomFloat(const FourInts& ParticleID, int nRandomSampleOffset) +{ + fltx4 Retval; + int nOfs = m_nRandomSeed + nRandomSampleOffset; + SubFloat(Retval, 0) = s_pRandomFloats[(nOfs + ParticleID.m_nValue[0]) & RANDOM_FLOAT_MASK]; + SubFloat(Retval, 1) = s_pRandomFloats[(nOfs + ParticleID.m_nValue[1]) & RANDOM_FLOAT_MASK]; + SubFloat(Retval, 2) = s_pRandomFloats[(nOfs + ParticleID.m_nValue[2]) & RANDOM_FLOAT_MASK]; + SubFloat(Retval, 3) = s_pRandomFloats[(nOfs + ParticleID.m_nValue[3]) & RANDOM_FLOAT_MASK]; + return Retval; +} + + +inline float CParticleCollection::RandomFloatExp(int nRandomSampleId, float flMin, float flMax, float flExponent) +{ + float flRand = s_pRandomFloats[(m_nRandomSeed + nRandomSampleId) & RANDOM_FLOAT_MASK]; + flRand = powf(flRand, flExponent); + flRand *= (flMax - flMin); + flRand += flMin; + return flRand; +} + +inline void CParticleCollection::RandomVector(int nRandomSampleId, float flMin, float flMax, Vector* pVector) +{ + float flDelta = flMax - flMin; + int nBaseId = m_nRandomSeed + nRandomSampleId; + + pVector->x = s_pRandomFloats[nBaseId & RANDOM_FLOAT_MASK]; + pVector->x *= flDelta; + pVector->x += flMin; + + pVector->y = s_pRandomFloats[(nBaseId + 1) & RANDOM_FLOAT_MASK]; + pVector->y *= flDelta; + pVector->y += flMin; + + pVector->z = s_pRandomFloats[(nBaseId + 2) & RANDOM_FLOAT_MASK]; + pVector->z *= flDelta; + pVector->z += flMin; +} + +inline void CParticleCollection::RandomVector(int nRandomSampleId, const Vector& vecMin, const Vector& vecMax, Vector* pVector) +{ + int nBaseId = m_nRandomSeed + nRandomSampleId; + pVector->x = RandomFloat(nBaseId, vecMin.x, vecMax.x); + pVector->y = RandomFloat(nBaseId + 1, vecMin.y, vecMax.y); + pVector->z = RandomFloat(nBaseId + 2, vecMin.z, vecMax.z); +} + +inline int CParticleCollection::RandomInt(int nMin, int nMax) +{ + return RandomInt(m_nRandomQueryCount++, nMin, nMax); +} + +inline float CParticleCollection::RandomFloat(float flMin, float flMax) +{ + return RandomFloat(m_nRandomQueryCount++, flMin, flMax); +} + +inline float CParticleCollection::RandomFloatExp(float flMin, float flMax, float flExponent) +{ + return RandomFloatExp(m_nRandomQueryCount++, flMin, flMax, flExponent); +} + +inline void CParticleCollection::RandomVector(float flMin, float flMax, Vector* pVector) +{ + RandomVector(m_nRandomQueryCount++, flMin, flMax, pVector); +} + +inline void CParticleCollection::RandomVector(const Vector& vecMin, const Vector& vecMax, Vector* pVector) +{ + RandomVector(m_nRandomQueryCount++, vecMin, vecMax, pVector); +} + +inline float CParticleCollection::RandomVectorInUnitSphere(Vector* pVector) +{ + return RandomVectorInUnitSphere(m_nRandomQueryCount++, pVector); +} + + +inline const float* CParticleCollection::GetFloatAttributePtr(int nAttribute, int nParticleNumber) const +{ + Assert(nParticleNumber < m_nAllocatedParticles); + int block_ofs = nParticleNumber / 4; + return m_pParticleAttributes[nAttribute] + + m_nParticleFloatStrides[nAttribute] * block_ofs + + (nParticleNumber & 3); +} + +inline int* CParticleCollection::GetIntAttributePtrForWrite(int nAttribute, int nParticleNumber) +{ + return reinterpret_cast(GetFloatAttributePtrForWrite(nAttribute, nParticleNumber)); +} + +inline const int* CParticleCollection::GetIntAttributePtr(int nAttribute, int nParticleNumber) const +{ + return (int*)GetFloatAttributePtr(nAttribute, nParticleNumber); +} + +inline const fltx4* CParticleCollection::GetM128AttributePtr(int nAttribute, size_t* pStrideOut) const +{ + *(pStrideOut) = m_nParticleFloatStrides[nAttribute] / 4; + return reinterpret_cast(m_pParticleAttributes[nAttribute]); +} + +inline const FourInts* CParticleCollection::Get4IAttributePtr(int nAttribute, size_t* pStrideOut) const +{ + *(pStrideOut) = m_nParticleFloatStrides[nAttribute] / 4; + return reinterpret_cast(m_pParticleAttributes[nAttribute]); +} + +inline const int32* CParticleCollection::GetIntAttributePtr(int nAttribute, size_t* pStrideOut) const +{ + *(pStrideOut) = m_nParticleFloatStrides[nAttribute]; + return reinterpret_cast(m_pParticleAttributes[nAttribute]); +} + +inline const FourVectors* CParticleCollection::Get4VAttributePtr(int nAttribute, size_t* pStrideOut) const +{ + *(pStrideOut) = m_nParticleFloatStrides[nAttribute] / 12; + return reinterpret_cast(m_pParticleAttributes[nAttribute]); +} + +inline FourVectors* CParticleCollection::Get4VAttributePtrForWrite(int nAttribute, size_t* pStrideOut) +{ + *(pStrideOut) = m_nParticleFloatStrides[nAttribute] / 12; + return reinterpret_cast(m_pParticleAttributes[nAttribute]); +} + +inline const FourVectors* CParticleCollection::GetInitial4VAttributePtr(int nAttribute, size_t* pStrideOut) const +{ + *(pStrideOut) = m_nParticleInitialFloatStrides[nAttribute] / 12; + return reinterpret_cast(m_pParticleInitialAttributes[nAttribute]); +} + +inline float* CParticleCollection::GetFloatAttributePtrForWrite(int nAttribute, int nParticleNumber) +{ + Assert(!m_bIsRunningInitializers || (m_nPerParticleInitializedAttributeMask & (1 << nAttribute))); + Assert(!m_bIsRunningOperators || (m_nPerParticleUpdatedAttributeMask & (1 << nAttribute))); + + Assert(m_nParticleFloatStrides[nAttribute] != 0); + + Assert(nParticleNumber < m_nAllocatedParticles); + int block_ofs = nParticleNumber / 4; + return m_pParticleAttributes[nAttribute] + + m_nParticleFloatStrides[nAttribute] * block_ofs + + (nParticleNumber & 3); +} + +inline fltx4* CParticleCollection::GetM128AttributePtrForWrite(int nAttribute, size_t* pStrideOut) +{ + if (!HushAsserts()) + { + Assert(!m_bIsRunningInitializers || (m_nPerParticleInitializedAttributeMask & (1 << nAttribute))); + Assert(!m_bIsRunningOperators || (m_nPerParticleUpdatedAttributeMask & (1 << nAttribute))); + Assert(m_nParticleFloatStrides[nAttribute] != 0); + } + + *(pStrideOut) = m_nParticleFloatStrides[nAttribute] / 4; + return reinterpret_cast(m_pParticleAttributes[nAttribute]); +} + +inline const float* CParticleCollection::GetInitialFloatAttributePtr(int nAttribute, int nParticleNumber) const +{ + Assert(nParticleNumber < m_nAllocatedParticles); + int block_ofs = nParticleNumber / 4; + return m_pParticleInitialAttributes[nAttribute] + m_nParticleInitialFloatStrides[nAttribute] * block_ofs + (nParticleNumber & 3); +} + +inline const fltx4* CParticleCollection::GetInitialM128AttributePtr(int nAttribute, size_t* pStrideOut) const +{ + *(pStrideOut) = m_nParticleInitialFloatStrides[nAttribute] / 4; + return reinterpret_cast(m_pParticleInitialAttributes[nAttribute]); +} + +inline float* CParticleCollection::GetInitialFloatAttributePtrForWrite(int nAttribute, int nParticleNumber) +{ + Assert(nParticleNumber < m_nAllocatedParticles); + Assert(m_nPerParticleReadInitialAttributeMask & (1 << nAttribute)); + int block_ofs = nParticleNumber / 4; + return m_pParticleInitialAttributes[nAttribute] + m_nParticleInitialFloatStrides[nAttribute] * block_ofs + (nParticleNumber & 3); +} + +inline fltx4* CParticleCollection::GetInitialM128AttributePtrForWrite(int nAttribute, size_t* pStrideOut) +{ + Assert(m_nPerParticleReadInitialAttributeMask & (1 << nAttribute)); + *(pStrideOut) = m_nParticleInitialFloatStrides[nAttribute] / 4; + return reinterpret_cast(m_pParticleInitialAttributes[nAttribute]); +} + +inline bool CParticleCollection::IsValidAttributePtr(int nAttribute, const void* pPtr) const +{ + if (pPtr < m_pParticleAttributes[nAttribute]) + return false; + + size_t nArraySize = m_nParticleFloatStrides[nAttribute] * m_nAllocatedParticles / 4; + void* pMaxPtr = m_pParticleAttributes[nAttribute] + nArraySize; + return (pPtr <= pMaxPtr); +} + + +FORCEINLINE void CParticleCollection::KillParticle(int nPidx) +{ + Assert(nPidx < m_nActiveParticles + 4); + + Assert(m_nNumParticlesToKill < MAX_PARTICLES_IN_A_SYSTEM); + m_pParticleKillList[m_nNumParticlesToKill++] = nPidx; +} + +inline void CParticleCollection::FillAttributeWithConstant(int nAttribute, float fValue) +{ + size_t stride; + fltx4* pAttr = GetM128AttributePtrForWrite(nAttribute, &stride); + fltx4 fill = ReplicateX4(fValue); + for (int i = 0; i < m_nPaddedActiveParticles; i++) + { + *(pAttr) = fill; + pAttr += stride; + } +} + + +FORCEINLINE void SetVectorAttribute(float* pAttribute, float x, float y, float z) +{ + pAttribute[0] = x; + pAttribute[4] = y; + pAttribute[8] = z; +} + +FORCEINLINE void SetVectorAttribute(float* pAttribute, const Vector& v) +{ + pAttribute[0] = v.x; + pAttribute[4] = v.y; + pAttribute[8] = v.z; +} + +FORCEINLINE void SetVectorFromAttribute(Vector& v, const float* pAttribute) +{ + v.x = pAttribute[0]; + v.y = pAttribute[4]; + v.z = pAttribute[8]; +} + + +FORCEINLINE float CParticleCollection::ComputeSqrDistanceToParticle(int hParticle, const Vector& vecPosition) const +{ + const float* xyz = GetFloatAttributePtr(PARTICLE_ATTRIBUTE_XYZ, hParticle); + Vector vecParticlePosition(xyz[0], xyz[4], xyz[8]); + return vecParticlePosition.DistToSqr(vecPosition); +} + + +FORCEINLINE void CParticleCollection::GrowDistSqrBounds(float flDistSqr) +{ + if (m_flLastMinDistSqr > flDistSqr) + { + m_flLastMinDistSqr = flDistSqr; + } + else if (m_flLastMaxDistSqr < flDistSqr) + { + m_flLastMaxDistSqr = flDistSqr; + } +} + + + + +struct ParticleChildrenInfo_t +{ + DmObjectId_t m_Id; + CUtlString m_Name; + bool m_bUseNameBasedLookup; + float m_flDelay; +}; + + +class CParticleSystemDefinition +{ + DECLARE_DMXELEMENT_UNPACK(); + DECLARE_REFERENCED_CLASS(CParticleSystemDefinition); + + +public: + CParticleSystemDefinition(void); + ~CParticleSystemDefinition(void); + + void Read(CDmxElement* pElement); + CDmxElement* Write(); + + const char* MaterialName() const; + IMaterial* GetMaterial() const; + const char* GetName() const; + const DmObjectId_t& GetId() const; + + bool UsesPowerOfTwoFrameBufferTexture(); + + bool UsesFullFrameBufferTexture(); + + bool ShouldAlwaysPrecache() const; + + bool ShouldBatch() const; + + bool IsViewModelEffect() const; + + CParticleCollection* FirstCollection(); + + float GetCullRadius() const; + float GetCullFillCost() const; + int GetCullControlPoint() const; + const char* GetCullReplacementDefinition() const; + + bool HasRetirementBeenChecked(int nFrame) const; + void MarkRetirementCheck(int nFrame); + + void MarkReadsControlPoint(int nPoint); + bool ReadsControlPoint(int nPoint) const; + +private: + void Precache(); + void Uncache(); + bool IsPrecached() const; + + void UnlinkAllCollections(); + + void SetupContextData(); + void ParseChildren(CDmxElement* pElement); + void ParseOperators(const char* pszName, ParticleFunctionType_t nFunctionType, + CDmxElement* pElement, CUtlVector& out_list); + void WriteChildren(CDmxElement* pElement); + void WriteOperators(CDmxElement* pElement, const char* pOpKeyName, + const CUtlVector& inList); + CUtlVector* GetOperatorList(ParticleFunctionType_t type); + CParticleOperatorInstance* FindOperatorById(ParticleFunctionType_t type, const DmObjectId_t& id); + +private: + int m_nInitialParticles; + int m_nPerParticleUpdatedAttributeMask; + int m_nPerParticleInitializedAttributeMask; + int m_nInitialAttributeReadMask; + int m_nAttributeReadMask; + uint64 m_nControlPointReadMask; + Vector m_BoundingBoxMin; + Vector m_BoundingBoxMax; + char m_pszMaterialName[MAX_PATH]; + CMaterialReference m_Material; + CParticleCollection* m_pFirstCollection; + char m_pszCullReplacementName[128]; + float m_flCullRadius; + float m_flCullFillCost; + int m_nCullControlPoint; + int m_nRetireCheckFrame; + + Color m_ConstantColor; + float m_flConstantRadius; + float m_flConstantRotation; + float m_flConstantRotationSpeed; + int m_nConstantSequenceNumber; + int m_nConstantSequenceNumber1; + int m_nGroupID; + float m_flMaximumTimeStep; + float m_flMaximumSimTime; + float m_flMinimumSimTime; + int m_nMinimumFrames; + + + bool m_bViewModelEffect; + + + size_t m_nContextDataSize; + DmObjectId_t m_Id; + +public: + float m_flMaxDrawDistance; + float m_flNoDrawTimeToGoToSleep; + + int m_nMaxParticles; + int m_nSkipRenderControlPoint; + CUtlString m_Name; + + CUtlVector m_Operators; + CUtlVector m_Renderers; + CUtlVector m_Initializers; + CUtlVector m_Emitters; + CUtlVector m_ForceGenerators; + CUtlVector m_Constraints; + CUtlVector m_Children; + + CUtlVector m_nOperatorsCtxOffsets; + CUtlVector m_nRenderersCtxOffsets; + CUtlVector m_nInitializersCtxOffsets; + CUtlVector m_nEmittersCtxOffsets; + CUtlVector m_nForceGeneratorsCtxOffsets; + CUtlVector m_nConstraintsCtxOffsets; + + float m_flTotalSimTime; + float m_flUncomittedTotalSimTime; + float m_flMaxMeasuredSimTime; + int m_nMaximumActiveParticles; + bool m_bShouldSort; + bool m_bShouldBatch; + bool m_bIsPrecached : 1; + bool m_bAlwaysPrecache : 1; + + friend class CParticleCollection; + friend class CParticleSystemMgr; +}; + + +inline CParticleSystemDefinition::CParticleSystemDefinition(void) +{ + m_nControlPointReadMask = 0; + m_nInitialAttributeReadMask = 0; + m_nPerParticleInitializedAttributeMask = 0; + m_nPerParticleUpdatedAttributeMask = 0; + m_nAttributeReadMask = 0; + m_flTotalSimTime = 0.0; + m_flMaxMeasuredSimTime = 0.0; + m_nMaximumActiveParticles = 0; + m_bIsPrecached = false; + m_bAlwaysPrecache = false; + m_bShouldBatch = false; + m_bShouldSort = true; + m_pFirstCollection = NULL; + m_flCullRadius = 0.0f; + m_flCullFillCost = 1.0f; + m_nRetireCheckFrame = 0; +} + +inline CParticleSystemDefinition::~CParticleSystemDefinition(void) +{ + UnlinkAllCollections(); + m_Operators.PurgeAndDeleteElements(); + m_Renderers.PurgeAndDeleteElements(); + m_Initializers.PurgeAndDeleteElements(); + m_Emitters.PurgeAndDeleteElements(); + m_ForceGenerators.PurgeAndDeleteElements(); + m_Constraints.PurgeAndDeleteElements(); +} + +inline CParticleCollection* CParticleSystemDefinition::FirstCollection() +{ + return m_pFirstCollection; +} + +inline float CParticleSystemDefinition::GetCullRadius() const +{ + return m_flCullRadius; +} + +inline float CParticleSystemDefinition::GetCullFillCost() const +{ + return m_flCullFillCost; +} + +inline const char* CParticleSystemDefinition::GetCullReplacementDefinition() const +{ + return m_pszCullReplacementName; +} + +inline int CParticleSystemDefinition::GetCullControlPoint() const +{ + return m_nCullControlPoint; +} + +inline void CParticleSystemDefinition::MarkReadsControlPoint(int nPoint) +{ + m_nControlPointReadMask |= (1ULL << nPoint); +} + +inline bool CParticleSystemDefinition::ReadsControlPoint(int nPoint) const +{ + return (m_nControlPointReadMask & (1ULL << nPoint)) != 0; +} + +inline bool CParticleSystemDefinition::HasRetirementBeenChecked(int nFrame) const +{ + return m_nRetireCheckFrame == nFrame; +} + +inline void CParticleSystemDefinition::MarkRetirementCheck(int nFrame) +{ + m_nRetireCheckFrame = nFrame; +} + +inline bool CParticleSystemDefinition::ShouldBatch() const +{ + return m_bShouldBatch; +} + +inline bool CParticleSystemDefinition::IsViewModelEffect() const +{ + return m_bViewModelEffect; +} + +inline const char* CParticleSystemDefinition::MaterialName() const +{ + return m_pszMaterialName; +} + +inline const DmObjectId_t& CParticleSystemDefinition::GetId() const +{ + return m_Id; +} + +inline int CParticleCollection::GetGroupID(void) const +{ + return m_pDef->m_nGroupID; +} + +FORCEINLINE const Vector& CParticleCollection::GetControlPointAtCurrentTime(int nControlPoint) const +{ + Assert(nControlPoint <= GetHighestControlPoint()); + Assert(m_pDef->ReadsControlPoint(nControlPoint)); + return m_ControlPoints[nControlPoint].m_Position; +} + +FORCEINLINE void CParticleCollection::GetControlPointOrientationAtCurrentTime(int nControlPoint, Vector* pForward, Vector* pRight, Vector* pUp) const +{ + Assert(nControlPoint <= GetHighestControlPoint()); + Assert(m_pDef->ReadsControlPoint(nControlPoint)); + + *pForward = m_ControlPoints[nControlPoint].m_ForwardVector; + *pRight = m_ControlPoints[nControlPoint].m_RightVector; + *pUp = m_ControlPoints[nControlPoint].m_UpVector; +} + +FORCEINLINE int CParticleCollection::GetControlPointParent(int nControlPoint) const +{ + Assert(nControlPoint <= GetHighestControlPoint()); + Assert(m_pDef->ReadsControlPoint(nControlPoint)); + return m_ControlPoints[nControlPoint].m_nParent; +} + +FORCEINLINE bool CParticleCollection::IsValid(void) const +{ + return (m_pDef != NULL && m_pDef->GetMaterial()); +} + + +#endif \ No newline at end of file diff --git a/SpyCustom/particles_new.h b/SpyCustom/particles_new.h new file mode 100644 index 0000000..32abaf7 --- /dev/null +++ b/SpyCustom/particles_new.h @@ -0,0 +1,295 @@ +#ifndef PARTICLES_NEW_H +#define PARTICLES_NEW_H +#ifdef _WIN32 +#pragma once +#endif + +#include "particlemgr.h" +#include "particles.h" +#include "particlesphererenderer.h" +#include "smartptr.h" +#include "particles_simple.h" +#include "utlobjectreference.h" + + +class CNewParticleEffect : public IParticleEffect, public CParticleCollection, public CDefaultClientRenderable +{ +public: + DECLARE_CLASS_NOBASE(CNewParticleEffect); + DECLARE_REFERENCED_CLASS(CNewParticleEffect); + +public: + friend class CRefCountAccessor; + + CNewParticleEffect* m_pNext; + CNewParticleEffect* m_pPrev; + + void SetSortOrigin(const Vector& vSortOrigin); + bool ShouldDraw(void); + virtual bool IsTransparent(void); + virtual bool IsTwoPass(void); + virtual bool UsesPowerOfTwoFrameBufferTexture(void); + virtual bool UsesFullFrameBufferTexture(void); + const QAngle& GetRenderAngles(void); + const matrix3x4_t& RenderableToWorldTransform(); + void GetRenderBounds(Vector& mins, Vector& maxs); + + void DetectChanges(void); + const Vector& GetRenderOrigin(void); + PMaterialHandle GetPMaterial(const char* name); + bool RecalculateBoundingBox(); + Particle* AddParticle(unsigned int particleSize, PMaterialHandle material, const Vector& origin); + const char* GetEffectName(); + void SetDontRemove(bool bSet); + void SetDrawn(bool bDrawn); + void SetFirstFrameFlag(bool bFirst); + void SetNeedsBBoxUpdate(bool bNeedsUpdate); + void SetAutoUpdateBBox(bool bNeedsUpdate); + void SetRemoveFlag(void); + bool GetRemoveFlag(void); + bool GetFirstFrameFlag(void); + bool GetNeedsBBoxUpdate(void); + bool GetAutoUpdateBBox(void); + bool ShouldPerformCullCheck() const; + void MarkShouldPerformCullCheck(bool bEnable); + CBaseEntity* GetOwner(void) { return m_hOwner; } + void SetOwner(CBaseEntity* pOwner) { m_hOwner = pOwner; } + CNewParticleEffect* ReplaceWith(const char* pParticleSystemName); + + static CSmartPtr Create(CBaseEntity* pOwner, const char* pParticleSystemName, + const char* pDebugName = NULL); + static CSmartPtr Create(CBaseEntity* pOwner, CParticleSystemDefinition* pDef, + const char* pDebugName = NULL); + virtual int DrawModel(int flags); + + void DebugDrawBbox(bool bCulled); + +public: + void StopEmission(bool bInfiniteOnly = false, bool bRemoveAllParticles = false, bool bWakeOnStop = false); + void SetDormant(bool bDormant); + void SetControlPoint(int nWhichPoint, const Vector& v); + void SetControlPointEntity(int nWhichPoint, CBaseEntity* pEntity); + void SetControlPointOrientation(int nWhichPoint, const Quaternion& q); + void SetControlPointOrientation(int nWhichPoint, const Vector& forward, const Vector& right, const Vector& up); + void SetControlPointForwardVector(int nWhichPoint, const Vector& v); + void SetControlPointUpVector(int nWhichPoint, const Vector& v); + void SetControlPointRightVector(int nWhichPoint, const Vector& v); + + FORCEINLINE EHANDLE const& GetControlPointEntity(int nWhichPoint) + { + return m_hControlPointOwners[nWhichPoint]; + } + + +public: + + virtual void SimulateParticles(CParticleSimulateIterator* pIterator) + { + } + virtual void RenderParticles(CParticleRenderIterator* pIterator) + { + } + + virtual void SetParticleCullRadius(float radius); + virtual void NotifyRemove(void); + virtual const Vector& GetSortOrigin(void); + + virtual void Update(float flTimeDelta); + + void SetDynamicallyAllocated(bool bDynamic = true); + + virtual bool ShouldSimulate() const { return m_bSimulate; } + virtual void SetShouldSimulate(bool bSim) { m_bSimulate = bSim; } + + int AllocateToolParticleEffectId(); + int GetToolParticleEffectId() const; + CNewParticleEffect(CBaseEntity* pOwner, const char* pEffectName); + CNewParticleEffect(CBaseEntity* pOwner, CParticleSystemDefinition* pEffect); + virtual ~CNewParticleEffect(); + +protected: + int IsReleased(); + + const char* m_pDebugName; + + bool m_bDontRemove : 1; + bool m_bRemove : 1; + bool m_bDrawn : 1; + bool m_bNeedsBBoxUpdate : 1; + bool m_bIsFirstFrame : 1; + bool m_bAutoUpdateBBox : 1; + bool m_bAllocated : 1; + bool m_bSimulate : 1; + bool m_bShouldPerformCullCheck : 1; + + int m_nToolParticleEffectId; + Vector m_vSortOrigin; + EHANDLE m_hOwner; + EHANDLE m_hControlPointOwners[MAX_PARTICLE_CONTROL_POINTS]; + + Vector m_LastMin; + Vector m_LastMax; + +private: + void AddRef(); + void Release(); + void RecordControlPointOrientation(int nWhichPoint); + void Construct(); + + int m_RefCount; + CNewParticleEffect(const CNewParticleEffect&); +}; + + +inline int CNewParticleEffect::GetToolParticleEffectId() const +{ + return m_nToolParticleEffectId; +} + +inline int CNewParticleEffect::AllocateToolParticleEffectId() +{ + m_nToolParticleEffectId = ParticleMgr()->AllocateToolParticleEffectId(); + return m_nToolParticleEffectId; +} + +inline void CNewParticleEffect::SetSortOrigin(const Vector& vSortOrigin) +{ + m_vSortOrigin = vSortOrigin; +} + +inline const Vector& CNewParticleEffect::GetSortOrigin(void) +{ + return m_vSortOrigin; +} + +inline bool CNewParticleEffect::ShouldDraw(void) +{ + return true; +} + +inline bool CNewParticleEffect::IsTransparent(void) +{ + return CParticleCollection::IsTranslucent(); +} + +inline const QAngle& CNewParticleEffect::GetRenderAngles(void) +{ + return vec3_angle; +} + +inline const matrix3x4_t& CNewParticleEffect::RenderableToWorldTransform() +{ + static matrix3x4_t mat; + SetIdentityMatrix(mat); + PositionMatrix(GetRenderOrigin(), mat); + return mat; +} + +inline Vector const& CNewParticleEffect::GetRenderOrigin(void) +{ + return m_vSortOrigin; +} + +inline PMaterialHandle CNewParticleEffect::GetPMaterial(const char* name) +{ + Assert(0); + return NULL; +} + +inline Particle* CNewParticleEffect::AddParticle(unsigned int particleSize, PMaterialHandle material, const Vector& origin) +{ + Assert(0); + return NULL; +} + + +inline const char* CNewParticleEffect::GetEffectName() +{ + return GetName(); +} + +inline void CNewParticleEffect::SetDontRemove(bool bSet) +{ + m_bDontRemove = bSet; +} + +inline void CNewParticleEffect::SetDrawn(bool bDrawn) +{ + m_bDrawn = bDrawn; +} + +inline void CNewParticleEffect::SetFirstFrameFlag(bool bFirst) +{ + m_bIsFirstFrame = bFirst; +} + +inline void CNewParticleEffect::SetDynamicallyAllocated(bool bDynamic) +{ + m_bAllocated = bDynamic; +} + +inline void CNewParticleEffect::SetNeedsBBoxUpdate(bool bNeedsUpdate) +{ + m_bNeedsBBoxUpdate = bNeedsUpdate; +} + +inline void CNewParticleEffect::SetAutoUpdateBBox(bool bNeedsUpdate) +{ + m_bAutoUpdateBBox = bNeedsUpdate; +} + +inline void CNewParticleEffect::SetRemoveFlag(void) +{ + m_bRemove = true; +} + +inline bool CNewParticleEffect::GetRemoveFlag(void) +{ + return m_bRemove; +} + +inline bool CNewParticleEffect::GetFirstFrameFlag(void) +{ + return m_bIsFirstFrame; +} + +inline bool CNewParticleEffect::GetNeedsBBoxUpdate(void) +{ + return m_bNeedsBBoxUpdate; +} + +inline bool CNewParticleEffect::GetAutoUpdateBBox(void) +{ + return m_bAutoUpdateBBox; +} + +inline bool CNewParticleEffect::ShouldPerformCullCheck() const +{ + return m_bShouldPerformCullCheck; +} + +inline void CNewParticleEffect::MarkShouldPerformCullCheck(bool bEnable) +{ + m_bShouldPerformCullCheck = bEnable; +} + +inline CSmartPtr CNewParticleEffect::Create(CBaseEntity* pOwner, const char* pParticleSystemName, const char* pDebugName) +{ + CNewParticleEffect* pRet = new CNewParticleEffect(pOwner, pParticleSystemName); + pRet->m_pDebugName = pDebugName; + pRet->SetDynamicallyAllocated(true); + return pRet; +} + +inline CSmartPtr CNewParticleEffect::Create(CBaseEntity* pOwner, CParticleSystemDefinition* pDef, const char* pDebugName) +{ + CNewParticleEffect* pRet = new CNewParticleEffect(pOwner, pDef); + pRet->m_pDebugName = pDebugName; + pRet->SetDynamicallyAllocated(true); + return pRet; +} + +typedef CUtlReference HPARTICLEFFECT; + + +#endif \ No newline at end of file diff --git a/SpyCustom/particles_simple.h b/SpyCustom/particles_simple.h new file mode 100644 index 0000000..71ea268 --- /dev/null +++ b/SpyCustom/particles_simple.h @@ -0,0 +1,206 @@ +#ifndef PARTICLES_SIMPLE_H +#define PARTICLES_SIMPLE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "particlemgr.h" +#include "ParticleSphereRenderer.h" +#include "smartptr.h" + + +class CParticleEffect : public IParticleEffect +{ +public: + DECLARE_CLASS_NOBASE(CParticleEffect); + + friend class CRefCountAccessor; + + void SetSortOrigin(const Vector& vSortOrigin); + + PMaterialHandle GetPMaterial(const char* name); + + Particle* AddParticle(unsigned int particleSize, PMaterialHandle material, const Vector& origin); + + CParticleEffectBinding& GetBinding() { return m_ParticleEffect; } + + const char* GetEffectName(); + + void AddFlags(int iFlags) { m_Flags |= iFlags; } + void RemoveFlags(int iFlags) { m_Flags &= ~iFlags; } + + void SetDontRemove(bool bSet) + { + if (bSet) + AddFlags(FLAG_DONT_REMOVE); + else + RemoveFlags(FLAG_DONT_REMOVE); + } + +public: + + virtual void SetParticleCullRadius(float radius); + virtual void NotifyRemove(void); + virtual const Vector& GetSortOrigin(); + virtual void NotifyDestroyParticle(Particle* pParticle); + virtual void Update(float flTimeDelta); + + void SetDynamicallyAllocated(bool bDynamic = true); + + virtual bool ShouldSimulate() const { return m_bSimulate; } + virtual void SetShouldSimulate(bool bSim) { m_bSimulate = bSim; } + + int AllocateToolParticleEffectId(); + int GetToolParticleEffectId() const; +protected: + CParticleEffect(const char* pDebugName); + virtual ~CParticleEffect(); + + int IsReleased(); + + enum + { + FLAG_ALLOCATED = (1 << 1), + FLAG_DONT_REMOVE = (1 << 2), + }; + + char const* m_pDebugName; + + CParticleEffectBinding m_ParticleEffect; + Vector m_vSortOrigin; + + int m_Flags; + + bool m_bSimulate; + int m_nToolParticleEffectId; + +private: + void AddRef(); + void Release(); + + int m_RefCount; + CParticleEffect(const CParticleEffect&); +}; + +inline int CParticleEffect::GetToolParticleEffectId() const +{ + return m_nToolParticleEffectId; +} + +inline int CParticleEffect::AllocateToolParticleEffectId() +{ + m_nToolParticleEffectId = ParticleMgr()->AllocateToolParticleEffectId(); + return m_nToolParticleEffectId; +} + + +enum SimpleParticleFlag_t +{ + SIMPLE_PARTICLE_FLAG_WINDBLOWN = 0x1, + SIMPLE_PARTICLE_FLAG_NO_VEL_DECAY = 0x2 +}; + +class SimpleParticle : public Particle +{ +public: + SimpleParticle() : m_iFlags(0) {} + + Vector m_vecVelocity; + float m_flRoll; + float m_flDieTime; + float m_flLifetime; + unsigned char m_uchColor[3]; + unsigned char m_uchStartAlpha; + unsigned char m_uchEndAlpha; + unsigned char m_uchStartSize; + unsigned char m_uchEndSize; + unsigned char m_iFlags; + float m_flRollDelta; +}; + + + +class CSimpleEmitter : public CParticleEffect +{ +public: + + DECLARE_CLASS(CSimpleEmitter, CParticleEffect); + + static CSmartPtr Create(const char* pDebugName); + + virtual void SimulateParticles(CParticleSimulateIterator* pIterator); + virtual void RenderParticles(CParticleRenderIterator* pIterator); + + void SetNearClip(float nearClipMin, float nearClipMax); + + void SetDrawBeforeViewModel(bool state = true); + + SimpleParticle* AddSimpleParticle(PMaterialHandle hMaterial, const Vector& vOrigin, float flDieTime = 3, unsigned char uchSize = 10); + + void SetShouldDrawForSplitScreenUser(int nSlot); + +protected: + CSimpleEmitter(const char* pDebugName = NULL); + virtual ~CSimpleEmitter(); + + virtual float UpdateAlpha(const SimpleParticle* pParticle); + virtual float UpdateScale(const SimpleParticle* pParticle); + virtual float UpdateRoll(SimpleParticle* pParticle, float timeDelta); + virtual void UpdateVelocity(SimpleParticle* pParticle, float timeDelta); + virtual Vector UpdateColor(const SimpleParticle* pParticle); + + float m_flNearClipMin; + float m_flNearClipMax; + + int m_nSplitScreenPlayerSlot; + + +private: + CSimpleEmitter(const CSimpleEmitter&); +}; + +class CEmberEffect : public CSimpleEmitter +{ +public: + CEmberEffect(const char* pDebugName); + static CSmartPtr Create(const char* pDebugName); + + virtual void UpdateVelocity(SimpleParticle* pParticle, float timeDelta); + virtual Vector UpdateColor(const SimpleParticle* pParticle); + +private: + CEmberEffect(const CEmberEffect&); +}; + + +class CFireSmokeEffect : public CSimpleEmitter +{ +public: + CFireSmokeEffect(const char* pDebugName); + static CSmartPtr Create(const char* pDebugName); + + virtual void UpdateVelocity(SimpleParticle* pParticle, float timeDelta); + virtual float UpdateAlpha(const SimpleParticle* pParticle); + +protected: + VPlane m_planeClip; + +private: + CFireSmokeEffect(const CFireSmokeEffect&); +}; + + +class CFireParticle : public CSimpleEmitter +{ +public: + CFireParticle(const char* pDebugName); + static CSmartPtr Create(const char* pDebugName); + + virtual Vector UpdateColor(const SimpleParticle* pParticle); + +private: + CFireParticle(const CFireParticle&); +}; + + +#endif \ No newline at end of file diff --git a/SpyCustom/pbwrap.hpp b/SpyCustom/pbwrap.hpp new file mode 100644 index 0000000..d8a1d6d --- /dev/null +++ b/SpyCustom/pbwrap.hpp @@ -0,0 +1,779 @@ +#pragma once +#include +#include +#include +#include + +#define PBFIELD(number, type, name) \ + pbfield name() const { \ + return std::move(pbfield( fv_ )); \ + } + +#if defined(__GNUC__) +#include +#include + +#define __forceinline __attribute__((always_inline)) + +#define PBMSG_CTOR(class_name) \ + class_name() : pbmsg() {} \ + class_name(void* buf, size_t bytes) : pbmsg(buf, bytes) {} \ + class_name(const std::string& buf) : pbmsg(buf) {} + +#elif defined(_MSC_VER) +#define PBMSG_CTOR using pbmsg::pbmsg +#endif + +namespace pbwrap +{ + static constexpr int32_t k_invalid_id = -1; + + enum e_field_type + { + TYPE_DOUBLE = 1, + TYPE_FLOAT = 2, + TYPE_INT64 = 3, + TYPE_UINT64 = 4, + TYPE_INT32 = 5, + TYPE_FIXED64 = 6, + TYPE_FIXED32 = 7, + TYPE_BOOL = 8, + TYPE_STRING = 9, + TYPE_GROUP = 10, + TYPE_MESSAGE = 11, + TYPE_BYTES = 12, + TYPE_UINT32 = 13, + TYPE_ENUM = 14, + TYPE_SFIXED32 = 15, + TYPE_SFIXED64 = 16, + TYPE_SINT32 = 17, + TYPE_SINT64 = 18, + MAX_FIELD_TYPE = 18, + }; + + enum e_wire_type + { + WIRETYPE_VARINT = 0, + WIRETYPE_FIXED64 = 1, + WIRETYPE_LENGTH_DELIMITED = 2, + WIRETYPE_START_GROUP = 3, + WIRETYPE_END_GROUP = 4, + WIRETYPE_FIXED32 = 5, + }; + + static constexpr e_wire_type k_wire_type_for_field_type[MAX_FIELD_TYPE + 1] = { + static_cast(k_invalid_id), + WIRETYPE_FIXED64, + WIRETYPE_FIXED32, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + WIRETYPE_FIXED64, + WIRETYPE_FIXED32, + WIRETYPE_VARINT, + WIRETYPE_LENGTH_DELIMITED, + WIRETYPE_START_GROUP, + WIRETYPE_LENGTH_DELIMITED, + WIRETYPE_LENGTH_DELIMITED, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + WIRETYPE_FIXED32, + WIRETYPE_FIXED64, + WIRETYPE_VARINT, + WIRETYPE_VARINT, + }; + + namespace utils + { + static constexpr int k_tag_type_bits = 3; + static constexpr uint32_t k_tag_type_mask = (1 << k_tag_type_bits) - 1; + static constexpr int k_max_varint_bytes = 10; + static constexpr int k_max_varint32_bytes = 5; + + __forceinline auto make_tag(uint32_t field_number, uint32_t wire_type) -> uint32_t + { + return static_cast((field_number << k_tag_type_bits) | wire_type); + } + + static auto get_bytes_varint32(uint32_t value) -> std::string + { + uint8_t bytes[k_max_varint32_bytes]; + int size = 0; + while (value > 0x7F) + { + bytes[size++] = (static_cast(value) & 0x7F) | 0x80; + value >>= 7; + } + bytes[size++] = static_cast(value) & 0x7F; + return std::string{ reinterpret_cast(&bytes[0]), (size_t)size }; + } + + static auto get_bytes_varint64(uint64_t value) -> std::string + { + uint8_t bytes[k_max_varint_bytes]; + int size = 0; + while (value > 0x7F) + { + bytes[size++] = (static_cast(value) & 0x7F) | 0x80; + value >>= 7; + } + bytes[size++] = static_cast(value) & 0x7F; + return std::string{ reinterpret_cast(&bytes[0]), (size_t)size }; + } + + static auto read_varuint32(const void* data, size_t& bytes_read) -> uint32_t + { + auto ptr = reinterpret_cast(data); + auto value = 0u; + auto bytes = 0u; + + do + { + value |= static_cast(*ptr & 0x7f) << (7 * bytes); + bytes++; + } while (*(ptr++) & 0x80 && bytes <= 5); + + bytes_read = bytes; + return value; + } + + static auto read_varuint64(const void* data, size_t& bytes_read) -> uint64_t + { + auto ptr = reinterpret_cast(data); + auto value = 0ull; + auto bytes = 0u; + + do + { + value |= static_cast(*ptr & 0x7f) << (7 * bytes); + bytes++; + } while (*(ptr++) & 0x80 && bytes <= 10); + + bytes_read = bytes; + + return value; + } + + static auto read_field(const void* data, size_t& bytes_read) + -> std::tuple + { + uint32_t field = *reinterpret_cast(data); + uint32_t wire_type = field & k_tag_type_mask; + + if (field == 0xffff) + { + bytes_read = 0; + return std::make_tuple(k_invalid_id, k_invalid_id, "", ""); + } + + if (field & 0x80) + { + field = ((field & 0x7f) | ((field & 0xff00) >> 1)) >> k_tag_type_bits; + bytes_read = 2; + } + else + { + field = (field & 0xff) >> k_tag_type_bits; + bytes_read = 1; + } + + std::string value_bytes, full_bytes; + size_t length, size_delimited; + + switch (wire_type) + { + case WIRETYPE_VARINT: + read_varuint64((void*)((ptrdiff_t)data + bytes_read), length); + value_bytes = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytes_read)), length }; + full_bytes = std::string{ reinterpret_cast(data), bytes_read + length }; + bytes_read += length; + break; + case WIRETYPE_FIXED64: + value_bytes = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytes_read)), 8 }; + full_bytes = std::string{ reinterpret_cast(data), bytes_read + 8 }; + bytes_read += 8; + break; + case WIRETYPE_LENGTH_DELIMITED: + size_delimited = read_varuint32((void*)((ptrdiff_t)data + bytes_read), length); + value_bytes = std::string{ + reinterpret_cast((void*)((ptrdiff_t)data + bytes_read)), length + size_delimited + }; + full_bytes = std::string{ reinterpret_cast(data), bytes_read + length + size_delimited }; + bytes_read += length + size_delimited; + break; + case WIRETYPE_START_GROUP: + throw std::runtime_error("WIRETYPE_START_GROUP not implemented"); + break; + case WIRETYPE_END_GROUP: + throw std::runtime_error("WIRETYPE_END_GROUP not implemented"); + break; + case WIRETYPE_FIXED32: + value_bytes = std::string{ reinterpret_cast((void*)((ptrdiff_t)data + bytes_read)), 4 }; + full_bytes = std::string{ reinterpret_cast(data), bytes_read + 4 }; + bytes_read += 4; + break; + default: + throw std::runtime_error("Unknown wire type"); + break; + } + + return std::make_tuple(field, wire_type, std::move(value_bytes), std::move(full_bytes)); + } + + template + auto get_field_bytes(uint32_t field, uint32_t wire_type, T value) + -> std::pair + { + const auto tag = get_bytes_varint32(make_tag(field, wire_type)); + + std::string bytes{}; + switch (wire_type) + { + case WIRETYPE_VARINT: + bytes += get_bytes_varint64(static_cast(value)); + break; + case WIRETYPE_FIXED32: + bytes += std::string{ reinterpret_cast(&value), 4 }; + break; + case WIRETYPE_FIXED64: + bytes += std::string{ reinterpret_cast(&value), 8 }; + break; + } + + return { bytes, tag + bytes }; + } + + template <> + inline auto get_field_bytes(uint32_t field, uint32_t wire_type, std::string value) + -> std::pair + { + const auto tag = get_bytes_varint32(make_tag(field, wire_type)); + + std::string bytes{}; + bytes += get_bytes_varint32(value.size()); + bytes += value; + + return { bytes, tag + bytes }; + } + + template <> + inline auto get_field_bytes(uint32_t field, uint32_t wire_type, const char* value) + -> std::pair + { + const auto tag = get_bytes_varint32(make_tag(field, wire_type)); + + std::string bytes{}; + bytes += get_bytes_varint32(strlen(value)); + bytes += value; + + return { bytes, tag + bytes }; + } + } + + namespace types + { + struct Int32 + { + static constexpr e_field_type field_type = TYPE_INT32; + using type = int32_t; + + static __forceinline auto get(const std::string& value) -> int32_t + { + size_t bytes_read; + return utils::read_varuint32(value.data(), bytes_read); + } + }; + + struct Uint32 + { + static constexpr e_field_type field_type = TYPE_UINT32; + using type = uint32_t; + + static __forceinline auto get(const std::string& value) -> uint32_t + { + size_t bytes_read; + return utils::read_varuint32(value.data(), bytes_read); + } + }; + + struct Int64 + { + static constexpr e_field_type field_type = TYPE_INT64; + using type = int64_t; + + static __forceinline auto get(const std::string& value) -> int64_t + { + size_t bytes_read; + return utils::read_varuint64(value.data(), bytes_read); + } + }; + + struct Uint64 + { + static constexpr e_field_type field_type = TYPE_UINT64; + using type = uint64_t; + + static __forceinline auto get(const std::string& value) -> uint64_t + { + size_t bytes_read; + return utils::read_varuint64(value.data(), bytes_read); + } + }; + + struct Float + { + static constexpr e_field_type field_type = TYPE_FLOAT; + using type = float; + + static __forceinline auto get(const std::string& value) -> float + { + return *reinterpret_cast(value.data()); + } + }; + + struct Double + { + static constexpr e_field_type field_type = TYPE_DOUBLE; + using type = double; + + static __forceinline auto get(const std::string& value) -> double + { + return *reinterpret_cast(value.data()); + } + }; + + struct Fixed32 + { + static constexpr e_field_type field_type = TYPE_FIXED32; + using type = int32_t; + + static __forceinline auto get(const std::string& value) -> int32_t + { + return *reinterpret_cast(value.data()); + } + }; + + struct Fixed64 + { + static constexpr e_field_type field_type = TYPE_FIXED64; + using type = int64_t; + + static __forceinline auto get(const std::string& value) -> int64_t + { + return *reinterpret_cast(value.data()); + } + }; + + struct Bool + { + static constexpr e_field_type field_type = TYPE_BOOL; + using type = bool; + + static __forceinline auto get(const std::string& value) -> bool + { + size_t bytes_read; + return !!utils::read_varuint32(value.data(), bytes_read); + } + }; + + struct String + { + static constexpr e_field_type field_type = TYPE_STRING; + using type = std::string; + + static __forceinline auto get(const std::string& value) -> std::string + { + size_t bytes_read; + const auto length = utils::read_varuint32(value.data(), bytes_read); + auto result = std::string{ value.data() + bytes_read, length }; + return std::move(result); + } + }; + + struct Group : String + { + static constexpr e_field_type field_type = TYPE_GROUP; + }; + + struct Message : String + { + static constexpr e_field_type field_type = TYPE_MESSAGE; + }; + + struct Bytes : String + { + static constexpr e_field_type field_type = TYPE_BYTES; + }; + + struct Enum : Int32 + { + static constexpr e_field_type field_type = TYPE_ENUM; + }; + + struct Sfixed32 : Fixed32 + { + static constexpr e_field_type field_type = TYPE_SFIXED32; + }; + + struct Sfixed64 : Fixed64 + { + static constexpr e_field_type field_type = TYPE_SFIXED64; + }; + + struct Sint32 + { + static constexpr e_field_type field_type = TYPE_SINT32; + using type = int32_t; + }; + + struct Sint64 + { + static constexpr e_field_type field_type = TYPE_SINT64; + using type = int64_t; + }; + } + + namespace base + { + struct field_vector + { + using Entry = std::pair; + using Field = std::vector; + using Fields = std::vector; + + const std::shared_ptr fields; + const size_t max_size; + + explicit field_vector(const size_t max_size) : fields{ std::make_shared() }, max_size{ max_size + 1 } + { + fields->resize(this->max_size); + } + + auto clear(const uint32_t field) const -> void + { + if (field >= max_size) + throw std::runtime_error("field range error"); + + auto& fld = fields->at(field); + + if (!fld.empty()) + fld.clear(); + } + + auto has(const uint32_t field, const size_t index = 0) const -> bool + { + if (field >= max_size) + throw std::runtime_error("field range error"); + + auto& fld = fields->at(field); + + return fld.size() > index; + } + + auto count(const uint32_t field) const -> size_t + { + if (field >= max_size) + throw std::runtime_error("field range error"); + + auto& fld = fields->at(field); + + return fld.size(); + } + + auto add(const uint32_t field, const Entry& entry) const -> void + { + if (field >= max_size) + throw std::runtime_error("field range error"); + + fields->at(field).emplace_back(entry); + } + + auto set(const uint32_t field, const Entry& entry, const size_t index = 0) const -> void + { + if (field >= max_size) + throw std::runtime_error("field range error"); + + auto& fld = fields->at(field); + + if (index == 0 && fld.empty()) + { + fld.emplace_back(entry); + } + else + { + if (index >= fld.size()) + throw std::runtime_error("field range error"); + + fld.at(index) = entry; + } + } + + auto get(const uint32_t field, const size_t index = 0) const -> std::string + { + if (field >= max_size) + throw std::runtime_error("field range error"); + + const auto& fld = fields->at(field); + + if (index >= fld.size()) + throw std::runtime_error("field range error"); + + return fld.at(index).first; + } + + auto get_all(const uint32_t field) const -> std::vector + { + if (field >= max_size) + throw std::runtime_error("field range error"); + + const auto& fld = fields->at(field); + + std::vector ret; + + for (const auto& v : fld) + ret.emplace_back(v.first); + + return std::move(ret); + } + }; + + template + struct header + { + static constexpr uint32_t field = Field; + static constexpr e_field_type type = Type::field_type; + static constexpr e_wire_type wire_type = k_wire_type_for_field_type[type]; + }; + + struct msg + { + static constexpr e_field_type field_type = TYPE_STRING; + using type = std::string; + virtual ~msg() = default; + msg() = delete; + + explicit msg(const size_t max_size) : fv_{ field_vector(max_size) } + { + } + + auto serialize() const -> std::string + { + std::string result; + for (const auto& f0 : *fv_.fields) + for (const auto& f1 : f0) + result.append(f1.second); + + return std::move(result); + } + + auto parse(const uint8_t* buf, size_t bytes) -> void + { + if (buf == nullptr) + return; + + size_t pos = 0, bytes_read; + uint32_t field, wire_type; + std::string field_value_bytes, field_full_bytes; + + while (pos < bytes) + { + std::tie(field, wire_type, field_value_bytes, field_full_bytes) = utils::read_field(buf + pos, bytes_read); + + if (bytes_read == 0) + break; + + if (field >= fv_.max_size) + throw std::runtime_error("field range error"); + + fv_.fields->at(field).emplace_back(field_value_bytes, field_full_bytes); + pos += bytes_read; + } + } + + protected: + const field_vector fv_; + }; + + template + struct field + { + virtual ~field() = default; + + explicit field(const field_vector& fv) : fv_{ fv } + { + } + + auto clear() const -> void + { + fv_.clear(hdr.field); + } + + auto has(size_t index = 0) const -> bool + { + return fv_.has(hdr.field, index); + } + + auto count() const -> size_t + { + return fv_.count(hdr.field); + } + + protected: + static constexpr header hdr{}; + const field_vector fv_; + }; + } + + + template + struct pbfield; + + + template + struct pbfield::value>::type + > : base::field + { + virtual ~pbfield() = default; + + explicit pbfield(const base::field_vector& fv) : base::field{ fv } + { + } + + using type = typename Type::type; + + auto add(type&& value) const -> void + { + const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, value); + fv_.add(hdr.field, pair); + } + + auto set(type&& value, size_t index = 0) const -> void + { + const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, value); + fv_.set(hdr.field, pair, index); + } + + auto set(const type& value, size_t index = 0) const -> void + { + const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, value); + fv_.set(hdr.field, pair, index); + } + + auto set(std::vector&& values) const -> void + { + fv_.clear(hdr.field); + + for (auto& v : values) + { + const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v); + fv_.add(hdr.field, pair); + } + } + + auto set(std::vector& values) const -> void + { + fv_.clear(hdr.field); + + for (auto& v : values) + { + const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v); + fv_.add(hdr.field, pair); + } + } + + auto get_all() const -> std::vector + { + const auto values = fv_.get_all(hdr.field); + + std::vector ret; + + for (const auto& v : values) + ret.emplace_back(Type::get(v)); + + return std::move(ret); + } + + auto get(size_t index = 0) const -> type + { + const auto value = fv_.get(hdr.field, index); + return Type::get(value); + } + + private: + using base::field::hdr; + using base::field::fv_; + }; + + template + struct pbfield::value>::type + > : base::field + { + virtual ~pbfield() = default; + + explicit pbfield(const base::field_vector& fv) : base::field{ fv } + { + } + + using type = typename Type::type; + + auto add(const Type& value) const -> void + { + const auto v = value.serialize(); + const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v); + fv_.add(hdr.field, pair); + } + + auto set(const Type& value, size_t index = 0) const -> void + { + const auto v = value.serialize(); + const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v); + fv_.set(hdr.field, pair, index); + } + + auto get_all() const -> std::vector + { + const auto values = fv_.get_all(hdr.field); + + std::vector ret; + + for (const auto& v : values) + { + const auto s = types::String::get(v); + ret.emplace_back(s); + } + + return std::move(ret); + } + + auto get(size_t index = 0) const -> Type + { + const auto value = fv_.get(hdr.field, index); + const auto s = types::String::get(value); + return std::move(Type(s)); + } + + private: + using base::field::hdr; + using base::field::fv_; + }; + + template + struct pbmsg : base::msg + { + virtual ~pbmsg() = default; + + explicit pbmsg() : msg(MsgSize) + { + } + + explicit pbmsg(void* buf, size_t bytes) : msg(MsgSize) + { + parse(reinterpret_cast(buf), bytes); + } + + explicit pbmsg(const std::string& buf) : msg(MsgSize) + { + parse(reinterpret_cast(buf.data()), buf.size()); + } + }; +} diff --git a/SpyCustom/platform.h b/SpyCustom/platform.h new file mode 100644 index 0000000..5c4f3ed --- /dev/null +++ b/SpyCustom/platform.h @@ -0,0 +1,1280 @@ +#ifndef PLATFORM_H +#define PLATFORM_H + +#if defined( _X360 ) +#define NO_STEAM +#define NO_VOICE +#define _XBOX +#include +#include +#include +#include +#include +#include +#include +#undef _XBOX +#endif + +#include "wchartypes.h" +#include "basetypes.h" +#include "valve_off.h" + +#ifdef _DEBUG +#if !defined( PLAT_COMPILE_TIME_ASSERT ) +#define PLAT_COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;} +#endif +#else +#if !defined( PLAT_COMPILE_TIME_ASSERT ) +#define PLAT_COMPILE_TIME_ASSERT( pred ) +#endif +#endif + +#ifdef _WIN32 +#pragma once +#endif + +#define NEW_SOFTWARE_LIGHTING + +#ifdef POSIX +#include +#include +#include +#include +#endif + +#include +#include + + +#include + +#include "valve_minmax_on.h" + +#ifdef _RETAIL +#define IsRetail() true +#else +#define IsRetail() false +#endif + +#ifdef _DEBUG +#define IsRelease() false +#define IsDebug() true +#else +#define IsRelease() true +#define IsDebug() false +#endif + +#define IsXbox() false + +#ifdef _WIN32 +#define IsLinux() false +#define IsOSX() false +#define IsPosix() false +#define PLATFORM_WINDOWS 1 +#ifndef _X360 +#define IsWindows() true +#define IsPC() true +#define IsConsole() false +#define IsX360() false +#define IsPS3() false +#define IS_WINDOWS_PC +#define PLATFORM_WINDOWS_PC 1 +#ifdef _WIN64 +#define IsPlatformWindowsPC64() true +#define IsPlatformWindowsPC32() false +#define PLATFORM_WINDOWS_PC64 1 +#else +#define IsPlatformWindowsPC64() false +#define IsPlatformWindowsPC32() true +#define PLATFORM_WINDOWS_PC32 1 +#endif +#else +#define PLATFORM_X360 1 +#ifndef _CONSOLE +#define _CONSOLE +#endif +#define IsWindows() false +#define IsPC() false +#define IsConsole() true +#define IsX360() true +#define IsPS3() false +#endif +#if defined( DX_TO_GL_ABSTRACTION ) +#define IsPlatformOpenGL() true +#else +#define IsPlatformOpenGL() false +#endif +#elif defined(POSIX) +#define IsPC() true +#define IsWindows() false +#define IsConsole() false +#define IsX360() false +#define IsPS3() false +#if defined( LINUX ) +#define IsLinux() true +#else +#define IsLinux() false +#endif + +#if defined( OSX ) +#define IsOSX() true +#else +#define IsOSX() false +#endif + +#define IsPosix() true +#define IsPlatformOpenGL() true +#else +#error +#endif + +typedef unsigned char uint8; +typedef signed char int8; + +#if defined(__x86_64__) || defined(_WIN64) +#define X64BITS +#endif + +#if defined( _WIN32 ) + +typedef __int16 int16; +typedef unsigned __int16 uint16; +typedef __int32 int32; +typedef unsigned __int32 uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; + +#ifdef PLATFORM_64BITS +typedef __int64 intp; +typedef unsigned __int64 uintp; +#else +typedef __int32 intp; +typedef unsigned __int32 uintp; +#endif + +#if defined( _X360 ) +#ifdef __m128 +#undef __m128 +#endif +#define __m128 __vector4 +#endif + +#define OVERRIDE override + +#else + +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; +typedef long long int64; +typedef unsigned long long uint64; +#ifdef X64BITS +typedef long long intp; +typedef unsigned long long uintp; +#else +typedef int intp; +typedef unsigned int uintp; +#endif +typedef void* HWND; + +#undef OVERRIDE +#if defined(__clang__) +#define OVERRIDE override +#pragma GCC diagnostic ignored "-Wc++11-extensions" +#else +#define OVERRIDE +#endif + +#endif + +typedef uint32 RTime32; + +typedef float float32; +typedef double float64; + +typedef unsigned int uint; + +#ifdef _MSC_VER +#pragma once +#if _MSC_FULL_VER > 160000000 +#if _MSC_FULL_VER < 160040219 +#error You must install VS 2010 SP1 +#endif +#else +#if _MSC_FULL_VER < 140050727 +#error You must install VS 2005 SP1 +#endif +#endif +#endif + +#ifdef _MSC_VER +#define SINGLE_INHERITANCE __single_inheritance +#define MULTIPLE_INHERITANCE __multiple_inheritance +#else +#define SINGLE_INHERITANCE +#define MULTIPLE_INHERITANCE +#endif + +#ifdef _MSC_VER +#define NO_VTABLE __declspec( novtable ) +#else +#define NO_VTABLE +#endif + +#ifdef _MSC_VER +#define NORETURN __declspec( noreturn ) +#else +#define NORETURN +#endif + +#ifndef _X360 +#define abstract_class class +#else +#define abstract_class class NO_VTABLE +#endif + + +#define VALVE_RAND_MAX 0x7fff + + + +#if defined(_WIN32) && !defined(WINDED) + +#if defined(_M_IX86) +#define __i386__ 1 +#endif + +#elif POSIX +#if defined( OSX ) && defined( CARBON_WORKAROUND ) +#define DWORD unsigned int +#else +typedef unsigned int DWORD; +#endif +typedef unsigned short WORD; +typedef void* HINSTANCE; +#define _MAX_PATH PATH_MAX +#define __cdecl +#define __stdcall +#define __declspec + +#endif + + +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif + +#ifdef _WIN32 +#define MAX_UNICODE_PATH 32767 +#else +#define MAX_UNICODE_PATH MAX_PATH +#endif + +#define MAX_UNICODE_PATH_IN_UTF8 MAX_UNICODE_PATH*4 + +#ifdef GNUC +#undef offsetof +#define offsetof(s,m) (size_t)&(((s *)0)->m) +#else +#undef offsetof +#define offsetof(s,m) (size_t)&(((s *)0)->m) +#endif + + +#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) + +#if defined( _WIN32 ) && !defined( _X360 ) +#define DebuggerBreak() __debugbreak() +#elif defined( _X360 ) +#define DebuggerBreak() DebugBreak() +#else +#ifdef OSX +#define DebuggerBreak() if ( Plat_IsInDebugSession() ) { __asm ( "int $3" ); } else { raise(SIGTRAP); } +#else +#define DebuggerBreak() raise(SIGTRAP) +#endif +#endif +#define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak() + +#ifndef EXPORT +#ifdef _WIN32 +#define EXPORT _declspec( dllexport ) +#else +#define EXPORT +#endif +#endif + +#if defined __i386__ && !defined __linux__ +#define id386 1 +#else +#define id386 0 +#endif + +#ifdef _WIN32 +#define DECL_ALIGN(x) __declspec(align(x)) + +#elif GNUC +#define DECL_ALIGN(x) __attribute__((aligned(x))) +#else +#define DECL_ALIGN(x) +#endif + +#ifdef _MSC_VER +#define ALIGN4 DECL_ALIGN(4) +#define ALIGN8 DECL_ALIGN(8) +#define ALIGN16 DECL_ALIGN(16) +#define ALIGN32 DECL_ALIGN(32) +#define ALIGN128 DECL_ALIGN(128) + +#define ALIGN4_POST +#define ALIGN8_POST +#define ALIGN16_POST +#define ALIGN32_POST +#define ALIGN128_POST +#elif defined( GNUC ) +#define ALIGN4 +#define ALIGN8 +#define ALIGN16 +#define ALIGN32 +#define ALIGN128 + +#define ALIGN4_POST DECL_ALIGN(4) +#define ALIGN8_POST DECL_ALIGN(8) +#define ALIGN16_POST DECL_ALIGN(16) +#define ALIGN32_POST DECL_ALIGN(32) +#define ALIGN128_POST DECL_ALIGN(128) +#else +#error +#endif + +#ifdef __GNUC__ +#define COMPILE_TIME_ASSERT( pred ) typedef int UNIQUE_ID[ (pred) ? 1 : -1 ] +#else +#if _MSC_VER >= 1600 +#define COMPILE_TIME_ASSERT( pred ) static_assert( pred, "Compile time assert constraint is not true: " #pred ) +#else +#define COMPILE_TIME_ASSERT( pred ) typedef char compile_time_assert_type[(pred) ? 1 : -1]; +#endif +#endif +#define ASSERT_INVARIANT( pred ) COMPILE_TIME_ASSERT( pred ) + +#if defined( PLATFORM_WINDOWS_PC ) + void Plat_MessageBox(const char* pTitle, const tchar * pMessage); +#else +#define Plat_MessageBox( t, m ) ((void)0) +#endif +#define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak() +void Plat_GetModuleFilename(char* pOut, int nMaxBytes); +void Plat_ExitProcess(int nCode); + +void Plat_ExitProcessWithError(int nCode, bool bGenerateMinidump = false); +#if defined( PLATFORM_X360 ) || defined( _PS3 ) +#ifndef _GAMECONSOLE +#define _GAMECONSOLE +#endif +#define IsPC() 0 +#define IsGameConsole() 1 +#else +#define IsPC() 1 +#define IsGameConsole() 0 +#endif + + +inline int64 CastPtrToInt64(const void* p) +{ + return (int64)((uintp)p); +} + +#include "annotations.h" + +#define INT_TO_POINTER( i ) (void *)( ( i ) + (char *)NULL ) +#define POINTER_TO_INT( p ) ( (int)(uintp)( p ) ) + + +#if defined( GNUC ) +#define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) ) +#ifdef _LINUX +#define mallocsize( _p ) ( malloc_usable_size( _p ) ) +#elif defined(OSX) +#define mallocsize( _p ) ( malloc_size( _p ) ) +#else +#error +#endif +#elif defined ( _WIN32 ) +#define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) ) +#define mallocsize( _p ) ( _msize( _p ) ) +#endif + +#define stackfree( _p ) 0 + +#ifdef POSIX +#define CONSTRUCT_EARLY __attribute__((init_priority(101))) +#else +#define CONSTRUCT_EARLY +#endif + +#if defined(_MSC_VER) +#define SELECTANY __declspec(selectany) +#define RESTRICT __restrict +#define RESTRICT_FUNC __declspec(restrict) +#define FMTFUNCTION( a, b ) +#elif defined(GNUC) +#define SELECTANY __attribute__((weak)) +#if defined(LINUX) && !defined(DEDICATED) +#define RESTRICT +#else +#define RESTRICT __restrict +#endif +#define RESTRICT_FUNC +#define FMTFUNCTION( fmtargnumber, firstvarargnumber ) __attribute__ (( format( __printf__, fmtargnumber, firstvarargnumber ))) +#else +#define SELECTANY static +#define RESTRICT +#define RESTRICT_FUNC +#define FMTFUNCTION( a, b ) +#endif + +#if defined( _WIN32 ) + +#define DLL_EXPORT extern "C" __declspec( dllexport ) +#define DLL_IMPORT extern "C" __declspec( dllimport ) + +#define DLL_CLASS_EXPORT __declspec( dllexport ) +#define DLL_CLASS_IMPORT __declspec( dllimport ) + +#define DLL_GLOBAL_EXPORT extern __declspec( dllexport ) +#define DLL_GLOBAL_IMPORT extern __declspec( dllimport ) + +#define DLL_LOCAL + +#elif defined GNUC +#define DLL_EXPORT extern "C" __attribute__ ((visibility("default"))) +#define DLL_IMPORT extern "C" + +#define DLL_CLASS_EXPORT __attribute__ ((visibility("default"))) +#define DLL_CLASS_IMPORT + +#define DLL_GLOBAL_EXPORT extern __attribute ((visibility("default"))) +#define DLL_GLOBAL_IMPORT extern + +#define DLL_LOCAL __attribute__ ((visibility("hidden"))) + +#else +#error "Unsupported Platform." +#endif + +#if defined( _WIN32 ) && !defined( _X360 ) +#define STDCALL __stdcall +#define FASTCALL __fastcall +#define FORCEINLINE __forceinline +#define FORCEINLINE_TEMPLATE __forceinline +#elif defined( _X360 ) +#define STDCALL __stdcall +#ifdef FORCEINLINE +#undef FORCEINLINE +#endif +#define FORCEINLINE __forceinline +#define FORCEINLINE_TEMPLATE __forceinline +#else +#define STDCALL +#define FASTCALL +#ifdef _LINUX_DEBUGGABLE +#define FORCEINLINE +#else +#define FORCEINLINE inline __attribute__ ((always_inline)) +#endif +#define FORCEINLINE_TEMPLATE inline +#endif + +#define DONT_INLINE(a) (((int)(a)+1)?(a):(a)) + +#ifdef _MSC_VER +#define HINT(THE_HINT) __assume((THE_HINT)) +#else +#define HINT(THE_HINT) 0 +#endif + +#define UNREACHABLE() { Assert(0); HINT(0); } + +#define NO_DEFAULT default: UNREACHABLE(); + + +#ifdef _WIN32 + +#pragma warning(disable : 4514) +#pragma warning(disable : 4100) +#pragma warning(disable : 4127) +#pragma warning(disable : 4512) +#pragma warning(disable : 4611) +#pragma warning(disable : 4710) +#pragma warning(disable : 4702) +#pragma warning(disable : 4505) +#pragma warning(disable : 4239) +#pragma warning(disable : 4097) +#pragma warning(disable : 4324) +#pragma warning(disable : 4244) +#pragma warning(disable : 4305) +#pragma warning(disable : 4786) +#pragma warning(disable : 4250) +#pragma warning(disable : 4201) +#pragma warning(disable : 4481) +#pragma warning(disable : 4748) + +#if _MSC_VER >= 1300 +#pragma warning(disable : 4511) +#pragma warning(disable : 4121) +#pragma warning(disable : 4530) +#endif + +#if _MSC_VER >= 1400 +#pragma warning(disable : 4996) +#endif + + +#endif + +#if defined( LINUX ) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 +#define GCC_DIAG_STR(s) #s +#define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y) +#define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x) +#define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x) + +#define GCC_DIAG_PUSH_OFF(x) GCC_DIAG_PRAGMA(push) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) +#define GCC_DIAG_POP() GCC_DIAG_PRAGMA(pop) +#else +#define GCC_DIAG_PUSH_OFF(x) +#define GCC_DIAG_POP() +#endif + +#ifdef LINUX +#pragma GCC diagnostic ignored "-Wconversion-null" +#pragma GCC diagnostic ignored "-Wpointer-arith" +#pragma GCC diagnostic ignored "-Wswitch" +#endif + +#ifdef OSX +#pragma GCC diagnostic ignored "-Wconversion-null" +#pragma GCC diagnostic ignored "-Wnull-arithmetic" +#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch" +#endif + + +#if !defined( _WIN64 ) +#pragma warning( disable : 4267 ) +#pragma warning( disable : 4311 ) +#pragma warning( disable : 4312 ) +#endif + + +#ifdef POSIX +#define _stricmp stricmp +#define strcmpi stricmp +#define stricmp strcasecmp +#define _vsnprintf vsnprintf +#define _alloca alloca +#ifdef _snprintf +#undef _snprintf +#endif +#define _snprintf snprintf +#define GetProcAddress dlsym +#define _chdir chdir +#define _strnicmp strnicmp +#define strnicmp strncasecmp +#define _getcwd getcwd +#define _snwprintf swprintf +#define swprintf_s swprintf +#define wcsicmp _wcsicmp +#define _wcsicmp wcscmp +#define _finite finite +#define _tempnam tempnam +#define _unlink unlink +#define _access access +#define _mkdir(dir) mkdir( dir, S_IRWXU | S_IRWXG | S_IRWXO ) +#define _wtoi(arg) wcstol(arg, NULL, 10) +#define _wtoi64(arg) wcstoll(arg, NULL, 10) + +typedef uint32 HMODULE; +typedef void* HANDLE; +#endif + +#ifndef _X360 + +static FORCEINLINE float fsel(float fComparand, float fValGE, float fLT) +{ + return fComparand >= 0 ? fValGE : fLT; +} +static FORCEINLINE double fsel(double fComparand, double fValGE, double fLT) +{ + return fComparand >= 0 ? fValGE : fLT; +} + +#else + +#define fsel __fsel + +#endif + + +#if !defined( _X360 ) +#if defined( _MSC_VER ) + +#if defined( PLATFORM_WINDOWS_PC64 ) +inline void SetupFPUControlWord() +{ +} +#else +inline void SetupFPUControlWordForceExceptions() +{ + uint16 tmpCtrlW; + __asm + { + fnclex + fnstcw word ptr[tmpCtrlW] + and [tmpCtrlW], 0FCC0h + or [tmpCtrlW], 0230h + fldcw word ptr[tmpCtrlW] + } +} + +#ifdef CHECK_FLOAT_EXCEPTIONS + +inline void SetupFPUControlWord() +{ + SetupFPUControlWordForceExceptions(); +} + +#else + +inline void SetupFPUControlWord() +{ + uint16 tmpCtrlW; + __asm + { + fnstcw word ptr[tmpCtrlW] + and [tmpCtrlW], 0FCC0h + or [tmpCtrlW], 023Fh + fldcw word ptr[tmpCtrlW] + } +} + +#endif +#endif + +#else + +inline void SetupFPUControlWord() +{ + __volatile unsigned short int __cw; + __asm __volatile("fnstcw %0" : "=m" (__cw)); + __cw = __cw & 0x0FCC0; + __cw = __cw | 0x023F; + __asm __volatile("fldcw %0" : : "m" (__cw)); +} + +#endif + +#else + +#ifdef _DEBUG +FORCEINLINE bool IsFPUControlWordSet() +{ + float f = 0.996f; + union + { + double flResult; + int pResult[2]; + }; + flResult = __fctiw(f); + return (pResult[1] == 1); +} +#endif + +inline void SetupFPUControlWord() +{ + __emit(0xFF80010C); + + __vector4 a = { 0.0f, 0.0f, 0.0f, 0.0f }; + a; + __asm + { + mtvscr a; + } +} + +#endif + +template +inline T WordSwapC(T w) +{ + uint16 temp; + + temp = ((*((uint16*)&w) & 0xff00) >> 8); + temp |= ((*((uint16*)&w) & 0x00ff) << 8); + + return *((T*)&temp); +} + +template +inline T DWordSwapC(T dw) +{ + uint32 temp; + + temp = *((uint32*)&dw) >> 24; + temp |= ((*((uint32*)&dw) & 0x00FF0000) >> 8); + temp |= ((*((uint32*)&dw) & 0x0000FF00) << 8); + temp |= ((*((uint32*)&dw) & 0x000000FF) << 24); + + return *((T*)&temp); +} + +template +inline T QWordSwapC(T dw) +{ + PLAT_COMPILE_TIME_ASSERT(sizeof(dw) == sizeof(uint64)); + + uint64 temp; + + temp = *((uint64*)&dw) >> 56; + temp |= ((*((uint64*)&dw) & 0x00FF000000000000ull) >> 40); + temp |= ((*((uint64*)&dw) & 0x0000FF0000000000ull) >> 24); + temp |= ((*((uint64*)&dw) & 0x000000FF00000000ull) >> 8); + temp |= ((*((uint64*)&dw) & 0x00000000FF000000ull) << 8); + temp |= ((*((uint64*)&dw) & 0x0000000000FF0000ull) << 24); + temp |= ((*((uint64*)&dw) & 0x000000000000FF00ull) << 40); + temp |= ((*((uint64*)&dw) & 0x00000000000000FFull) << 56); + + return *((T*)&temp); +} + +#if defined( _X360 ) + +#define WordSwap WordSwap360Intr +#define DWordSwap DWordSwap360Intr + +template +inline T WordSwap360Intr(T w) +{ + T output; + __storeshortbytereverse(w, 0, &output); + return output; +} + +template +inline T DWordSwap360Intr(T dw) +{ + T output; + __storewordbytereverse(dw, 0, &output); + return output; +} + +#elif defined( _MSC_VER ) && !defined( PLATFORM_WINDOWS_PC64 ) + +#define WordSwap WordSwapAsm +#define DWordSwap DWordSwapAsm + +#pragma warning(push) +#pragma warning (disable:4035) + +template +inline T WordSwapAsm(T w) +{ + __asm + { + mov ax, w + xchg al, ah + } +} + +template +inline T DWordSwapAsm(T dw) +{ + __asm + { + mov eax, dw + bswap eax + } +} + +#pragma warning(pop) + +#else + +#define WordSwap WordSwapC +#define DWordSwap DWordSwapC + +#endif + +#define QWordSwap QWordSwapC + +#if defined(__i386__) && !defined(VALVE_LITTLE_ENDIAN) +#define VALVE_LITTLE_ENDIAN 1 +#endif + +#if defined( _SGI_SOURCE ) || defined( _X360 ) +#define VALVE_BIG_ENDIAN 1 +#endif + +#define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) )) + +#if defined(VALVE_LITTLE_ENDIAN) + +#define BigShort( val ) WordSwap( val ) +#define BigWord( val ) WordSwap( val ) +#define BigLong( val ) DWordSwap( val ) +#define BigDWord( val ) DWordSwap( val ) +#define LittleShort( val ) ( val ) +#define LittleWord( val ) ( val ) +#define LittleLong( val ) ( val ) +#define LittleDWord( val ) ( val ) +#define LittleQWord( val ) ( val ) +#define SwapShort( val ) BigShort( val ) +#define SwapWord( val ) BigWord( val ) +#define SwapLong( val ) BigLong( val ) +#define SwapDWord( val ) BigDWord( val ) + +#define BigFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn ) +#define LittleFloat( pOut, pIn ) ( *pOut = *pIn ) +#define SwapFloat( pOut, pIn ) BigFloat( pOut, pIn ) + +#elif defined(VALVE_BIG_ENDIAN) + +#define BigShort( val ) ( val ) +#define BigWord( val ) ( val ) +#define BigLong( val ) ( val ) +#define BigDWord( val ) ( val ) +#define LittleShort( val ) WordSwap( val ) +#define LittleWord( val ) WordSwap( val ) +#define LittleLong( val ) DWordSwap( val ) +#define LittleDWord( val ) DWordSwap( val ) +#define LittleQWord( val ) QWordSwap( val ) +#define SwapShort( val ) LittleShort( val ) +#define SwapWord( val ) LittleWord( val ) +#define SwapLong( val ) LittleLong( val ) +#define SwapDWord( val ) LittleDWord( val ) + +#define BigFloat( pOut, pIn ) ( *pOut = *pIn ) +#define LittleFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn ) +#define SwapFloat( pOut, pIn ) LittleFloat( pOut, pIn ) + +#else + +inline short BigShort(short val) { int test = 1; return (*(char*)&test == 1) ? WordSwap(val) : val; } +inline uint16 BigWord(uint16 val) { int test = 1; return (*(char*)&test == 1) ? WordSwap(val) : val; } +inline long BigLong(long val) { int test = 1; return (*(char*)&test == 1) ? DWordSwap(val) : val; } +inline uint32 BigDWord(uint32 val) { int test = 1; return (*(char*)&test == 1) ? DWordSwap(val) : val; } +inline short LittleShort(short val) { int test = 1; return (*(char*)&test == 1) ? val : WordSwap(val); } +inline uint16 LittleWord(uint16 val) { int test = 1; return (*(char*)&test == 1) ? val : WordSwap(val); } +inline long LittleLong(long val) { int test = 1; return (*(char*)&test == 1) ? val : DWordSwap(val); } +inline uint32 LittleDWord(uint32 val) { int test = 1; return (*(char*)&test == 1) ? val : DWordSwap(val); } +inline uint64 LittleQWord(uint64 val) { int test = 1; return (*(char*)&test == 1) ? val : QWordSwap(val); } +inline short SwapShort(short val) { return WordSwap(val); } +inline uint16 SwapWord(uint16 val) { return WordSwap(val); } +inline long SwapLong(long val) { return DWordSwap(val); } +inline uint32 SwapDWord(uint32 val) { return DWordSwap(val); } + +inline void BigFloat(float* pOut, const float* pIn) { int test = 1; (*(char*)&test == 1) ? SafeSwapFloat(pOut, pIn) : (*pOut = *pIn); } +inline void LittleFloat(float* pOut, const float* pIn) { int test = 1; (*(char*)&test == 1) ? (*pOut = *pIn) : SafeSwapFloat(pOut, pIn); } +inline void SwapFloat(float* pOut, const float* pIn) { SafeSwapFloat(pOut, pIn); } + +#endif + +#if _X360 +FORCEINLINE unsigned long LoadLittleDWord(const unsigned long* base, unsigned int dwordIndex) +{ + return __loadwordbytereverse(dwordIndex << 2, base); +} + +FORCEINLINE void StoreLittleDWord(unsigned long* base, unsigned int dwordIndex, unsigned long dword) +{ + __storewordbytereverse(dword, dwordIndex << 2, base); +} +#else +FORCEINLINE unsigned long LoadLittleDWord(const unsigned long* base, unsigned int dwordIndex) +{ + return LittleDWord(base[dwordIndex]); +} + +FORCEINLINE void StoreLittleDWord(unsigned long* base, unsigned int dwordIndex, unsigned long dword) +{ + base[dwordIndex] = LittleDWord(dword); +} +#endif + + +#ifndef STATIC_TIER0 + +#ifdef TIER0_DLL_EXPORT +#define PLATFORM_INTERFACE DLL_EXPORT +#define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT +#define PLATFORM_CLASS DLL_CLASS_EXPORT +#else +#define PLATFORM_INTERFACE DLL_IMPORT +#define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT +#define PLATFORM_CLASS DLL_CLASS_IMPORT +#endif + +#else + +#define PLATFORM_INTERFACE extern +#define PLATFORM_OVERLOAD +#define PLATFORM_CLASS + +#endif + + +PLATFORM_INTERFACE void Plat_SetBenchmarkMode(bool bBenchmarkMode); +PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode(); + + +PLATFORM_INTERFACE double Plat_FloatTime(); +PLATFORM_INTERFACE unsigned int Plat_MSTime(); +PLATFORM_INTERFACE char* Plat_asctime(const struct tm* tm, char* buf); +PLATFORM_INTERFACE char* Plat_ctime(const time_t* timep, char* buf, size_t bufsize); +PLATFORM_INTERFACE struct tm* Plat_gmtime(const time_t* timep, struct tm* result); +PLATFORM_INTERFACE time_t Plat_timegm(struct tm* timeptr); +PLATFORM_INTERFACE struct tm* Plat_localtime(const time_t* timep, struct tm* result); + +#if defined( _WIN32 ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) +extern "C" unsigned __int64 __rdtsc(); +#pragma intrinsic(__rdtsc) +#endif + +inline uint64 Plat_Rdtsc() +{ +#if defined( _X360 ) + return (uint64)__mftb32(); +#elif defined( _WIN64 ) + return (uint64)__rdtsc(); +#elif defined( _WIN32 ) +#if defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) + return (uint64)__rdtsc(); +#else + __asm rdtsc; + __asm ret; +#endif +#elif defined( __i386__ ) + uint64 val; + __asm__ __volatile__("rdtsc" : "=A" (val)); + return val; +#elif defined( __x86_64__ ) + uint32 lo, hi; + __asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi)); + return (((uint64)hi) << 32) | lo; +#else +#error +#endif +} + +#define Sys_FloatTime Plat_FloatTime + +#define DISALLOW_OPERATOR_EQUAL( _classname ) \ + private: \ + _classname &operator=( const _classname & ); \ + public: + +#define IMPLEMENT_OPERATOR_EQUAL( _classname ) \ + public: \ + _classname &operator=( const _classname &src ) \ + { \ + memcpy( this, &src, sizeof(_classname) ); \ + return *this; \ + } + +struct CPUInformation +{ + int m_Size; + + bool m_bRDTSC : 1, + m_bCMOV : 1, + m_bFCMOV : 1, + m_bSSE : 1, + m_bSSE2 : 1, + m_b3DNow : 1, + m_bMMX : 1, + m_bHT : 1; + + uint8 m_nLogicalProcessors; + uint8 m_nPhysicalProcessors; + + bool m_bSSE3 : 1, + m_bSSSE3 : 1, + m_bSSE4a : 1, + m_bSSE41 : 1, + m_bSSE42 : 1; + + int64 m_Speed; + + tchar* m_szProcessorID; + + CPUInformation() : m_Size(0) {} +}; + +PLATFORM_INTERFACE const CPUInformation* GetCPUInformation(); + +PLATFORM_INTERFACE float GetCPUUsage(); + +PLATFORM_INTERFACE void GetCurrentDate(int* pDay, int* pMonth, int* pYear); + +PLATFORM_INTERFACE void InitPME(); +PLATFORM_INTERFACE void ShutdownPME(); + +PLATFORM_INTERFACE void Plat_SetHardwareDataBreakpoint(const void* pAddress, int nWatchBytes, bool bBreakOnRead); + +PLATFORM_INTERFACE void Plat_ApplyHardwareDataBreakpointsToNewThread(unsigned long dwThreadID); + +PLATFORM_INTERFACE const tchar* Plat_GetCommandLine(); +#ifndef _WIN32 +PLATFORM_INTERFACE void Plat_SetCommandLine(const char* cmdLine); +#endif +PLATFORM_INTERFACE const char* Plat_GetCommandLineA(); + +PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyDriver(); + +PLATFORM_INTERFACE bool Plat_VerifyHardwareKey(); + +PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyPrompt(); + +PLATFORM_INTERFACE bool Plat_FastVerifyHardwareKey(); + +PLATFORM_INTERFACE void* Plat_SimpleLog(const tchar* file, int line); + +#if _X360 +#define Plat_FastMemset XMemSet +#define Plat_FastMemcpy XMemCpy +#else +#define Plat_FastMemset memset +#define Plat_FastMemcpy memcpy +#endif + +#if defined(_WIN32) || defined(LINUX) || defined(OSX) +PLATFORM_INTERFACE bool Plat_IsInDebugSession(bool bForceRecheck = false); +PLATFORM_INTERFACE void Plat_DebugString(const char*); +#else +inline bool Plat_IsInDebugSession(bool bForceRecheck = false) { return false; } +#define Plat_DebugString(s) ((void)0) +#endif + +PLATFORM_INTERFACE bool Is64BitOS(); + + +#define XBOX_DVD_SECTORSIZE 2048 +#define XBOX_DVD_ECC_SIZE 32768 +#define XBOX_HDD_SECTORSIZE 512 + +#define WM_XREMOTECOMMAND (WM_USER + 100) +#define WM_XCONTROLLER_KEY (WM_USER + 101) +#define WM_SYS_UI (WM_USER + 102) +#define WM_SYS_SIGNINCHANGED (WM_USER + 103) +#define WM_SYS_STORAGEDEVICESCHANGED (WM_USER + 104) +#define WM_SYS_PROFILESETTINGCHANGED (WM_USER + 105) +#define WM_SYS_MUTELISTCHANGED (WM_USER + 106) +#define WM_SYS_INPUTDEVICESCHANGED (WM_USER + 107) +#define WM_SYS_INPUTDEVICECONFIGCHANGED (WM_USER + 108) +#define WM_LIVE_CONNECTIONCHANGED (WM_USER + 109) +#define WM_LIVE_INVITE_ACCEPTED (WM_USER + 110) +#define WM_LIVE_LINK_STATE_CHANGED (WM_USER + 111) +#define WM_LIVE_CONTENT_INSTALLED (WM_USER + 112) +#define WM_LIVE_MEMBERSHIP_PURCHASED (WM_USER + 113) +#define WM_LIVE_VOICECHAT_AWAY (WM_USER + 114) +#define WM_LIVE_PRESENCE_CHANGED (WM_USER + 115) +#define WM_FRIENDS_PRESENCE_CHANGED (WM_USER + 116) +#define WM_FRIENDS_FRIEND_ADDED (WM_USER + 117) +#define WM_FRIENDS_FRIEND_REMOVED (WM_USER + 118) +#define WM_CUSTOM_GAMEBANNERPRESSED (WM_USER + 119) +#define WM_CUSTOM_ACTIONPRESSED (WM_USER + 120) +#define WM_XMP_STATECHANGED (WM_USER + 121) +#define WM_XMP_PLAYBACKBEHAVIORCHANGED (WM_USER + 122) +#define WM_XMP_PLAYBACKCONTROLLERCHANGED (WM_USER + 123) + +inline const char* GetPlatformExt(void) +{ + return IsX360() ? ".360" : ""; +} + +#define XBOX_PROCESSOR_0 ( 1<<0 ) +#define XBOX_PROCESSOR_1 ( 1<<1 ) +#define XBOX_PROCESSOR_2 ( 1<<2 ) +#define XBOX_PROCESSOR_3 ( 1<<3 ) +#define XBOX_PROCESSOR_4 ( 1<<4 ) +#define XBOX_PROCESSOR_5 ( 1<<5 ) + +#define XBOX_CORE_0_HWTHREAD_0 XBOX_PROCESSOR_0 +#define XBOX_CORE_0_HWTHREAD_1 XBOX_PROCESSOR_1 +#define XBOX_CORE_1_HWTHREAD_0 XBOX_PROCESSOR_2 +#define XBOX_CORE_1_HWTHREAD_1 XBOX_PROCESSOR_3 +#define XBOX_CORE_2_HWTHREAD_0 XBOX_PROCESSOR_4 +#define XBOX_CORE_2_HWTHREAD_1 XBOX_PROCESSOR_5 + +#include "fasttimer.h" + +#if defined( _X360 ) +#include "xbox/xbox_core.h" +#endif + +template +inline T* Construct(T* pMemory) +{ + return ::new(pMemory) T; +} + +template +inline T* Construct(T* pMemory, ARG1 a1) +{ + return ::new(pMemory) T(a1); +} + +template +inline T* Construct(T* pMemory, ARG1 a1, ARG2 a2) +{ + return ::new(pMemory) T(a1, a2); +} + +template +inline T* Construct(T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3) +{ + return ::new(pMemory) T(a1, a2, a3); +} + +template +inline T* Construct(T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4) +{ + return ::new(pMemory) T(a1, a2, a3, a4); +} + +template +inline T* Construct(T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4, ARG5 a5) +{ + return ::new(pMemory) T(a1, a2, a3, a4, a5); +} + +template +inline void ConstructOneArg(T* pMemory, P const& arg) +{ + ::new(pMemory) T(arg); +} + +template +inline void ConstructTwoArg(T* pMemory, P1 const& arg1, P2 const& arg2) +{ + ::new(pMemory) T(arg1, arg2); +} + +template +inline void ConstructThreeArg(T* pMemory, P1 const& arg1, P2 const& arg2, P3 const& arg3) +{ + ::new(pMemory) T(arg1, arg2, arg3); +} + +template +inline T* CopyConstruct(T* pMemory, T const& src) +{ + return ::new(pMemory) T(src); +} + +template +inline void Destruct(T* pMemory) +{ + pMemory->~T(); + +#ifdef _DEBUG + memset(reinterpret_cast(pMemory), 0xDD, sizeof(T)); +#endif +} + + +#define GET_OUTER( OuterType, OuterMember ) \ + ( ( OuterType * ) ( (uint8 *)this - offsetof( OuterType, OuterMember ) ) ) + + +PLATFORM_INTERFACE bool vtune(bool resume); + + +#define TEMPLATE_FUNCTION_TABLE(RETURN_TYPE, NAME, ARGS, COUNT) \ + \ +typedef RETURN_TYPE (FASTCALL *__Type_##NAME) ARGS; \ + \ +template \ +struct __Function_##NAME \ +{ \ + static RETURN_TYPE FASTCALL Run ARGS; \ +}; \ + \ +template \ +struct __MetaLooper_##NAME : __MetaLooper_##NAME \ +{ \ + __Type_##NAME func; \ + inline __MetaLooper_##NAME() { func = __Function_##NAME::Run; } \ +}; \ + \ +template<> \ +struct __MetaLooper_##NAME<0> \ +{ \ + __Type_##NAME func; \ + inline __MetaLooper_##NAME() { func = __Function_##NAME<0>::Run; } \ +}; \ + \ +class NAME \ +{ \ +private: \ + static const __MetaLooper_##NAME m; \ +public: \ + enum { count = COUNT }; \ + static const __Type_##NAME* functions; \ +}; \ +const __MetaLooper_##NAME NAME::m; \ +const __Type_##NAME* NAME::functions = (__Type_##NAME*)&m; \ +template \ +RETURN_TYPE FASTCALL __Function_##NAME::Run ARGS + + +#define LOOP_INTERCHANGE(BOOLEAN, CODE)\ + if( (BOOLEAN) )\ + {\ + CODE;\ + } else\ + {\ + CODE;\ + } + +#if 0 + +PLATFORM_INTERFACE void* Plat_GetProcAddress(const char* pszModule, const char* pszName); + +template +class CDynamicFunction +{ +public: + CDynamicFunction(const char* pszModule, const char* pszName, FUNCPTR_TYPE pfnFallback = NULL) + { + m_pfn = pfnFallback; + void* pAddr = Plat_GetProcAddress(pszModule, pszName); + if (pAddr) + { + m_pfn = (FUNCPTR_TYPE)pAddr; + } + } + + operator bool() { return m_pfn != NULL; } + bool operator !() { return !m_pfn; } + operator FUNCPTR_TYPE() { return m_pfn; } + +private: + FUNCPTR_TYPE m_pfn; +}; +#endif + + +#include "valve_on.h" + +#if defined(TIER0_DLL_EXPORT) +extern "C" int V_tier0_stricmp(const char* s1, const char* s2); +#undef stricmp +#undef strcmpi +#define stricmp(s1,s2) V_tier0_stricmp( s1, s2 ) +#define strcmpi(s1,s2) V_tier0_stricmp( s1, s2 ) +#endif + + +#endif \ No newline at end of file diff --git a/SpyCustom/playernet_vars.h b/SpyCustom/playernet_vars.h new file mode 100644 index 0000000..5de8c00 --- /dev/null +++ b/SpyCustom/playernet_vars.h @@ -0,0 +1,113 @@ +#ifndef PLAYERNET_VARS_H +#define PLAYERNET_VARS_H +#ifdef _WIN32 +#pragma once +#endif + +#include "shared_classnames.h" +#include "networkvar.h" +#include "datamap.h" + +#define NUM_AUDIO_LOCAL_SOUNDS 8 + +struct fogparams_t +{ + DECLARE_CLASS_NOBASE(fogparams_t); + DECLARE_EMBEDDED_NETWORKVAR(); + +#ifndef CLIENT_DLL + DECLARE_SIMPLE_DATADESC(); +#endif + + bool operator !=(const fogparams_t& other) const; + + CNetworkVector(dirPrimary); + CNetworkColor32(colorPrimary); + CNetworkColor32(colorSecondary); + CNetworkColor32(colorPrimaryLerpTo); + CNetworkColor32(colorSecondaryLerpTo); + CNetworkVar(float, start); + CNetworkVar(float, end); + CNetworkVar(float, farz); + CNetworkVar(float, maxdensity); + + CNetworkVar(float, startLerpTo); + CNetworkVar(float, endLerpTo); + CNetworkVar(float, lerptime); + CNetworkVar(float, duration); + CNetworkVar(bool, enable); + CNetworkVar(bool, blend); +}; + +#ifdef CLIENT_DLL +#define CFogController C_FogController +#endif + +class CFogController; + +struct fogplayerparams_t +{ + DECLARE_CLASS_NOBASE(fogplayerparams_t); + DECLARE_EMBEDDED_NETWORKVAR(); + +#ifndef CLIENT_DLL + DECLARE_SIMPLE_DATADESC(); +#endif + + CNetworkHandle(CFogController, m_hCtrl); + float m_flTransitionTime; + + color32 m_OldColor; + float m_flOldStart; + float m_flOldEnd; + + color32 m_NewColor; + float m_flNewStart; + float m_flNewEnd; + + fogplayerparams_t() + { + m_hCtrl.Set(NULL); + m_flTransitionTime = -1.0f; + m_OldColor.r = m_OldColor.g = m_OldColor.b = m_OldColor.a = 0; + m_flOldStart = 0.0f; + m_flOldEnd = 0.0f; + m_NewColor.r = m_NewColor.g = m_NewColor.b = m_NewColor.a = 0; + m_flNewStart = 0.0f; + m_flNewEnd = 0.0f; + } +}; + +struct sky3dparams_t +{ + DECLARE_CLASS_NOBASE(sky3dparams_t); + DECLARE_EMBEDDED_NETWORKVAR(); + +#ifndef CLIENT_DLL + DECLARE_SIMPLE_DATADESC(); +#endif + + CNetworkVar(int, scale); + CNetworkVector(origin); + CNetworkVar(int, area); + + CNetworkVarEmbedded(fogparams_t, fog); +}; + +struct audioparams_t +{ + DECLARE_CLASS_NOBASE(audioparams_t); + DECLARE_EMBEDDED_NETWORKVAR(); + +#ifndef CLIENT_DLL + DECLARE_SIMPLE_DATADESC(); +#endif + + CNetworkArray(Vector, localSound, NUM_AUDIO_LOCAL_SOUNDS) + CNetworkVar(int, soundscapeIndex); + CNetworkVar(int, localBits); + CNetworkHandle(CBaseEntity, ent); +}; + + +#endif \ No newline at end of file diff --git a/SpyCustom/precipitation_shared.h b/SpyCustom/precipitation_shared.h new file mode 100644 index 0000000..26a0e77 --- /dev/null +++ b/SpyCustom/precipitation_shared.h @@ -0,0 +1,22 @@ +#ifndef PRECIPITATION_SHARED_H +#define PRECIPITATION_SHARED_H +#ifdef _WIN32 +#pragma once +#endif + + +enum PrecipitationType_t +{ + PRECIPITATION_TYPE_RAIN = 0, + PRECIPITATION_TYPE_SNOW, + PRECIPITATION_TYPE_ASH, + PRECIPITATION_TYPE_SNOWFALL, + PRECIPITATION_TYPE_PARTICLERAIN, + PRECIPITATION_TYPE_PARTICLEASH, + PRECIPITATION_TYPE_PARTICLERAINSTORM, + PRECIPITATION_TYPE_PARTICLESNOW, + NUM_PRECIPITATION_TYPES +}; + + +#endif \ No newline at end of file diff --git a/SpyCustom/predictable_entity.h b/SpyCustom/predictable_entity.h new file mode 100644 index 0000000..38bcfb9 --- /dev/null +++ b/SpyCustom/predictable_entity.h @@ -0,0 +1,185 @@ +#ifndef PREDICTABLE_ENTITY_H +#define PREDICTABLE_ENTITY_H +#ifdef _WIN32 +#pragma once +#endif + +#include "platform.h" +#include "predictioncopy.h" +#include "shared_classnames.h" + +#ifndef NO_ENTITY_PREDICTION +#define UsePrediction() 1 +#else +#define UsePrediction() 0 +#endif + +#if defined( CLIENT_DLL ) + +#include "iclassmap.h" +#include "recvproxy.h" + +class SendTable; + +#else + +#include "sendproxy.h" + +#endif + +#if defined( CLIENT_DLL ) + +#define DECLARE_NETWORKCLASS() \ + DECLARE_CLIENTCLASS() + +#define DECLARE_NETWORKCLASS_NOBASE() \ + DECLARE_CLIENTCLASS_NOBASE() + +#else + +#define DECLARE_NETWORKCLASS() \ + DECLARE_SERVERCLASS() + +#define DECLARE_NETWORKCLASS_NOBASE() \ + DECLARE_SERVERCLASS_NOBASE() + +#endif + +#if defined( CLIENT_DLL ) + +#ifndef NO_ENTITY_PREDICTION +#define DECLARE_PREDICTABLE() \ + public: \ + static typedescription_t m_PredDesc[]; \ + static datamap_t m_PredMap; \ + virtual datamap_t *GetPredDescMap( void ); \ + template friend datamap_t *PredMapInit(T *) +#else +#define DECLARE_PREDICTABLE() template friend datamap_t *PredMapInit(T *) +#endif + +#ifndef NO_ENTITY_PREDICTION +#define BEGIN_PREDICTION_DATA( className ) \ + datamap_t className::m_PredMap = { 0, 0, #className, &BaseClass::m_PredMap }; \ + datamap_t *className::GetPredDescMap( void ) { return &m_PredMap; } \ + BEGIN_PREDICTION_DATA_GUTS( className ) + +#define BEGIN_PREDICTION_DATA_NO_BASE( className ) \ + datamap_t className::m_PredMap = { 0, 0, #className, NULL }; \ + datamap_t *className::GetPredDescMap( void ) { return &m_PredMap; } \ + BEGIN_PREDICTION_DATA_GUTS( className ) + +#define BEGIN_PREDICTION_DATA_GUTS( className ) \ + template datamap_t *PredMapInit(T *); \ + template <> datamap_t *PredMapInit( className * ); \ + namespace className##_PredDataDescInit \ + { \ + datamap_t *g_PredMapHolder = PredMapInit( (className *)NULL ); \ + } \ + \ + template <> datamap_t *PredMapInit( className * ) \ + { \ + typedef className classNameTypedef; \ + static typedescription_t predDesc[] = \ + { \ + { FIELD_VOID,0, {0,0},0,0,0,0,0,0}, + +#define END_PREDICTION_DATA() \ + }; \ + \ + if ( sizeof( predDesc ) > sizeof( predDesc[0] ) ) \ + { \ + classNameTypedef::m_PredMap.dataNumFields = ARRAYSIZE( predDesc ) - 1; \ + classNameTypedef::m_PredMap.dataDesc = &predDesc[1]; \ + } \ + else \ + { \ + classNameTypedef::m_PredMap.dataNumFields = 1; \ + classNameTypedef::m_PredMap.dataDesc = predDesc; \ + } \ + return &classNameTypedef::m_PredMap; \ + } +#else +#define BEGIN_PREDICTION_DATA( className ) \ + template <> inline datamap_t *PredMapInit( className * ) \ + { \ + if ( 0 ) \ + { \ + typedef className classNameTypedef; \ + typedescription_t predDesc[] = \ + { \ + { FIELD_VOID,0, {0,0},0,0,0,0,0,0}, + +#define BEGIN_PREDICTION_DATA_NO_BASE( className ) BEGIN_PREDICTION_DATA( className ) + +#define END_PREDICTION_DATA() \ + }; \ + predDesc[0].flags = 0; \ + } \ + } +#endif + +#else + +#define DECLARE_PREDICTABLE() +#define BEGIN_PREDICTION_DATA( className ) +#define END_PREDICTION_DATA() + +#endif + +#if defined( CLIENT_DLL ) + +#define LINK_ENTITY_TO_CLASS( localName, className ) \ + static C_BaseEntity *C##className##Factory( void ) \ + { \ + return static_cast< C_BaseEntity * >( new className ); \ + }; \ + class C##localName##Foo \ + { \ + public: \ + C##localName##Foo( void ) \ + { \ + GetClassMap().Add( #localName, #className, sizeof( className ), \ + &C##className##Factory ); \ + } \ + }; \ + static C##localName##Foo g_C##localName##Foo; + +#define BEGIN_NETWORK_TABLE( className, tableName ) BEGIN_RECV_TABLE( className, tableName ) +#define BEGIN_NETWORK_TABLE_NOBASE( className, tableName ) BEGIN_RECV_TABLE_NOBASE( className, tableName ) + +#define END_NETWORK_TABLE END_RECV_TABLE + +#define IMPLEMENT_NETWORKCLASS_ALIASED(className, dataTable) \ + IMPLEMENT_CLIENTCLASS( C_##className, dataTable, C##className ) +#define IMPLEMENT_NETWORKCLASS(className, dataTable) \ + IMPLEMENT_CLIENTCLASS(className, dataTable, className) +#define IMPLEMENT_NETWORKCLASS_DT(className, dataTable) \ + IMPLEMENT_CLIENTCLASS_DT(className, dataTable, className) + +#else + +#define BEGIN_NETWORK_TABLE( className, tableName ) BEGIN_SEND_TABLE( className, tableName ) +#define BEGIN_NETWORK_TABLE_NOBASE( className, tableName ) BEGIN_SEND_TABLE_NOBASE( className, tableName ) + +#define END_NETWORK_TABLE END_SEND_TABLE + +#define IMPLEMENT_NETWORKCLASS_ALIASED(className, dataTable) \ + IMPLEMENT_SERVERCLASS( C##className, dataTable ) +#define IMPLEMENT_NETWORKCLASS(className, dataTable) \ + IMPLEMENT_SERVERCLASS(className, dataTable) +#define IMPLEMENT_NETWORKCLASS_DT(className, dataTable) \ + IMPLEMENT_SERVERCLASS_ST(className, dataTable) + +#endif + +abstract_class IPredictableList +{ +public: + virtual CBaseEntity* GetPredictable(int slot) = 0; + virtual int GetPredictableCount(void) = 0; +}; + +extern IPredictableList* predictables; + +#endif \ No newline at end of file diff --git a/SpyCustom/predictableid.h b/SpyCustom/predictableid.h new file mode 100644 index 0000000..5ec7216 --- /dev/null +++ b/SpyCustom/predictableid.h @@ -0,0 +1,53 @@ +#ifndef PREDICTABLEID_H +#define PREDICTABLEID_H +#ifdef _WIN32 +#pragma once +#endif + +#if !defined( NO_ENTITY_PREDICTION ) +class CPredictableId +{ +public: + CPredictableId(void); + + static void ResetInstanceCounters(void); + + bool IsActive(void) const; + + void Init(int player, int command, const char* classname, const char* module, int line); + + int GetPlayer(void) const; + int GetHash(void) const; + int GetInstanceNumber(void) const; + int GetCommandNumber(void) const; + + void SetAcknowledged(bool ack); + bool GetAcknowledged(void) const; + + int GetRaw(void) const; + void SetRaw(int raw); + + char const* Describe(void) const; + + bool operator ==(const CPredictableId& other) const; + bool operator !=(const CPredictableId& other) const; +private: + void SetCommandNumber(int commandNumber); + void SetPlayer(int playerIndex); + void SetInstanceNumber(int counter); + + struct bitfields + { + unsigned int ack : 1; + unsigned int player : 5; + unsigned int command : 10; + unsigned int hash : 12; + unsigned int instance : 4; + } m_PredictableID; +}; + +FORCEINLINE void NetworkVarConstruct(CPredictableId& x) {} + +#endif + +#endif \ No newline at end of file diff --git a/SpyCustom/predictioncopy.h b/SpyCustom/predictioncopy.h new file mode 100644 index 0000000..ed24b7e --- /dev/null +++ b/SpyCustom/predictioncopy.h @@ -0,0 +1,278 @@ +#ifndef PREDICTIONCOPY_H +#define PREDICTIONCOPY_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include "datamap.h" +#include "ehandle.h" +#include "utlstring.h" + +#if defined( CLIENT_DLL ) +class C_BaseEntity; +typedef CHandle EHANDLE; + +#if defined( _DEBUG ) +class IGameSystem; +IGameSystem* GetPredictionCopyTester(void); +#endif + +#else +class CBaseEntity; +typedef CHandle EHANDLE; +#endif + +enum +{ + PC_EVERYTHING = 0, + PC_NON_NETWORKED_ONLY, + PC_NETWORKED_ONLY, +}; + +#define PC_DATA_PACKED true +#define PC_DATA_NORMAL false + +typedef void (*FN_FIELD_COMPARE)(const char* classname, const char* fieldname, const char* fieldtype, + bool networked, bool noterrorchecked, bool differs, bool withintolerance, const char* value); + +class CPredictionCopy +{ +public: + typedef enum + { + DIFFERS = 0, + IDENTICAL, + WITHINTOLERANCE, + } difftype_t; + + CPredictionCopy(int type, void* dest, bool dest_packed, void const* src, bool src_packed, + bool counterrors = false, bool reporterrors = false, bool performcopy = true, + bool describefields = false, FN_FIELD_COMPARE func = NULL); + + void CopyShort(difftype_t dt, short* outvalue, const short* invalue, int count); + void CopyInt(difftype_t dt, int* outvalue, const int* invalue, int count); + void CopyBool(difftype_t dt, bool* outvalue, const bool* invalue, int count); + void CopyFloat(difftype_t dt, float* outvalue, const float* invalue, int count); + void CopyString(difftype_t dt, char* outstring, const char* instring); + void CopyVector(difftype_t dt, Vector& outValue, const Vector& inValue); + void CopyVector(difftype_t dt, Vector* outValue, const Vector* inValue, int count); + void CopyQuaternion(difftype_t dt, Quaternion& outValue, const Quaternion& inValue); + void CopyQuaternion(difftype_t dt, Quaternion* outValue, const Quaternion* inValue, int count); + void CopyEHandle(difftype_t dt, EHANDLE* outvalue, EHANDLE const* invalue, int count); + + void FORCEINLINE CopyData(difftype_t dt, int size, char* outdata, const char* indata) + { + if (!m_bPerformCopy) + return; + + if (dt == IDENTICAL) + return; + + memcpy(outdata, indata, size); + } + + int TransferData(const char* operation, int entindex, datamap_t* dmap); + +private: + void TransferData_R(int chaincount, datamap_t* dmap); + + void DetermineWatchField(const char* operation, int entindex, datamap_t* dmap); + void DumpWatchField(typedescription_t* field); + void WatchMsg(PRINTF_FORMAT_STRING const char* fmt, ...); + + difftype_t CompareShort(short* outvalue, const short* invalue, int count); + difftype_t CompareInt(int* outvalue, const int* invalue, int count); + difftype_t CompareBool(bool* outvalue, const bool* invalue, int count); + difftype_t CompareFloat(float* outvalue, const float* invalue, int count); + difftype_t CompareData(int size, char* outdata, const char* indata); + difftype_t CompareString(char* outstring, const char* instring); + difftype_t CompareVector(Vector& outValue, const Vector& inValue); + difftype_t CompareVector(Vector* outValue, const Vector* inValue, int count); + difftype_t CompareQuaternion(Quaternion& outValue, const Quaternion& inValue); + difftype_t CompareQuaternion(Quaternion* outValue, const Quaternion* inValue, int count); + difftype_t CompareEHandle(EHANDLE* outvalue, EHANDLE const* invalue, int count); + + void DescribeShort(difftype_t dt, short* outvalue, const short* invalue, int count); + void DescribeInt(difftype_t dt, int* outvalue, const int* invalue, int count); + void DescribeBool(difftype_t dt, bool* outvalue, const bool* invalue, int count); + void DescribeFloat(difftype_t dt, float* outvalue, const float* invalue, int count); + void DescribeData(difftype_t dt, int size, char* outdata, const char* indata); + void DescribeString(difftype_t dt, char* outstring, const char* instring); + void DescribeVector(difftype_t dt, Vector& outValue, const Vector& inValue); + void DescribeVector(difftype_t dt, Vector* outValue, const Vector* inValue, int count); + void DescribeQuaternion(difftype_t dt, Quaternion& outValue, const Quaternion& inValue); + void DescribeQuaternion(difftype_t dt, Quaternion* outValue, const Quaternion* inValue, int count); + void DescribeEHandle(difftype_t dt, EHANDLE* outvalue, EHANDLE const* invalue, int count); + + void WatchShort(difftype_t dt, short* outvalue, const short* invalue, int count); + void WatchInt(difftype_t dt, int* outvalue, const int* invalue, int count); + void WatchBool(difftype_t dt, bool* outvalue, const bool* invalue, int count); + void WatchFloat(difftype_t dt, float* outvalue, const float* invalue, int count); + void WatchData(difftype_t dt, int size, char* outdata, const char* indata); + void WatchString(difftype_t dt, char* outstring, const char* instring); + void WatchVector(difftype_t dt, Vector& outValue, const Vector& inValue); + void WatchVector(difftype_t dt, Vector* outValue, const Vector* inValue, int count); + void WatchQuaternion(difftype_t dt, Quaternion& outValue, const Quaternion& inValue); + void WatchQuaternion(difftype_t dt, Quaternion* outValue, const Quaternion* inValue, int count); + void WatchEHandle(difftype_t dt, EHANDLE* outvalue, EHANDLE const* invalue, int count); + + void ReportFieldsDiffer(PRINTF_FORMAT_STRING const char* fmt, ...); + void DescribeFields(difftype_t dt, PRINTF_FORMAT_STRING const char* fmt, ...); + + bool CanCheck(void); + + void CopyFields(int chaincount, datamap_t* pMap, typedescription_t* pFields, int fieldCount); + +private: + + int m_nType; + void* m_pDest; + void const* m_pSrc; + int m_nDestOffsetIndex; + int m_nSrcOffsetIndex; + + + bool m_bErrorCheck; + bool m_bReportErrors; + bool m_bDescribeFields; + typedescription_t* m_pCurrentField; + char const* m_pCurrentClassName; + datamap_t* m_pCurrentMap; + bool m_bShouldReport; + bool m_bShouldDescribe; + int m_nErrorCount; + bool m_bPerformCopy; + + FN_FIELD_COMPARE m_FieldCompareFunc; + + typedescription_t* m_pWatchField; + char const* m_pOperation; +}; + +typedef void (*FN_FIELD_DESCRIPTION)(const char* classname, const char* fieldname, const char* fieldtype, + bool networked, const char* value); + +class CPredictionDescribeData +{ +public: + CPredictionDescribeData(void const* src, bool src_packed, FN_FIELD_DESCRIPTION func = 0); + + void DescribeShort(const short* invalue, int count); + void DescribeInt(const int* invalue, int count); + void DescribeBool(const bool* invalue, int count); + void DescribeFloat(const float* invalue, int count); + void DescribeData(int size, const char* indata); + void DescribeString(const char* instring); + void DescribeVector(const Vector& inValue); + void DescribeVector(const Vector* inValue, int count); + void DescribeQuaternion(const Quaternion& inValue); + void DescribeQuaternion(const Quaternion* inValue, int count); + void DescribeEHandle(EHANDLE const* invalue, int count); + + void DumpDescription(datamap_t* pMap); + +private: + void DescribeFields_R(int chain_count, datamap_t* pMap, typedescription_t* pFields, int fieldCount); + + void const* m_pSrc; + int m_nSrcOffsetIndex; + + void Describe(PRINTF_FORMAT_STRING const char* fmt, ...); + + typedescription_t* m_pCurrentField; + char const* m_pCurrentClassName; + datamap_t* m_pCurrentMap; + + bool m_bShouldReport; + + FN_FIELD_DESCRIPTION m_FieldDescFunc; +}; + +#if defined( CLIENT_DLL ) +class CValueChangeTracker +{ +public: + CValueChangeTracker(); + + void Reset(); + + void StartTrack(char const* pchContext); + void EndTrack(); + + bool IsActive() const; + + void SetupTracking(C_BaseEntity* ent, char const* pchFieldName); + void ClearTracking(); + + void Spew(); + + C_BaseEntity* GetEntity(); + +private: + + enum + { + eChangeTrackerBufSize = 128, + }; + + void GetValue(char* buf, size_t bufsize); + + bool m_bActive : 1; + bool m_bTracking : 1; + EHANDLE m_hEntityToTrack; + CUtlVector< typedescription_t* > m_FieldStack; + CUtlString m_strFieldName; + CUtlString m_strContext; + char m_OrigValueBuf[eChangeTrackerBufSize]; + CUtlVector< CUtlString > m_History; +}; + +extern CValueChangeTracker* g_pChangeTracker; + +class CValueChangeTrackerScope +{ +public: + CValueChangeTrackerScope(char const* pchContext) + { + m_bCallEndTrack = true; + g_pChangeTracker->StartTrack(pchContext); + } + + CValueChangeTrackerScope(C_BaseEntity* pEntity, char const* pchContext) + { + m_bCallEndTrack = g_pChangeTracker->GetEntity() == pEntity; + if (m_bCallEndTrack) + { + g_pChangeTracker->StartTrack(pchContext); + } + } + + ~CValueChangeTrackerScope() + { + if (m_bCallEndTrack) + { + g_pChangeTracker->EndTrack(); + } + } +private: + + bool m_bCallEndTrack; +}; + +#if defined( _DEBUG ) +#define PREDICTION_TRACKVALUECHANGESCOPE( context ) CValueChangeTrackerScope scope( context ); +#define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context ) CValueChangeTrackerScope scope( entity, context ); +#define PREDICTION_STARTTRACKVALUE( context ) g_pChangeTracker->StartTrack( context ); +#define PREDICTION_ENDTRACKVALUE() g_pChangeTracker->EndTrack(); +#define PREDICTION_SPEWVALUECHANGES() g_pChangeTracker->Spew(); +#else +#define PREDICTION_TRACKVALUECHANGESCOPE( context ) +#define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context ) +#define PREDICTION_STARTTRACKVALUE( context ) +#define PREDICTION_ENDTRACKVALUE() +#define PREDICTION_SPEWVALUECHANGES() +#endif + +#endif +#endif \ No newline at end of file diff --git a/SpyCustom/protobuffs.cpp b/SpyCustom/protobuffs.cpp new file mode 100644 index 0000000..3adefa5 --- /dev/null +++ b/SpyCustom/protobuffs.cpp @@ -0,0 +1,262 @@ +#include "Protobuffs.hpp" +#include "Interfaces.hpp" +#include "inventory_changer.h" + +extern Protobuffs ProtoFeatures; +#define CAST(cast, address, add) reinterpret_cast((uint32_t)address + (uint32_t)add) + +void Protobuffs::WritePacket(std::string packet, void* thisPtr, void* oldEBP, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize) +{ + if ((uint32_t)packet.size() <= cubDest - 8) + { + memcpy((void*)((DWORD)pubDest + 8), (void*)packet.data(), packet.size()); + *pcubMsgSize = packet.size() + 8; + } + else if (iff.g_pMemAlloc) + { + auto memPtr = *CAST(void**, thisPtr, 0x18); + auto memPtrSize = *CAST(uint32_t*, thisPtr, 0x1C); + auto newSize = (memPtrSize - cubDest) + packet.size() + 8; + + auto memory = iff.g_pMemAlloc->Realloc(memPtr, newSize + 4); + + *CAST(void**, thisPtr, 0x18) = memory; + *CAST(uint32_t*, thisPtr, 0x1C) = newSize; + *CAST(void**, oldEBP, -0x14) = memory; + + memcpy(CAST(void*, memory, 0x1C), (void*)packet.data(), packet.size()); + + *pcubMsgSize = packet.size() + 8; + } +} + +static bool onceChanger = false; + +void Protobuffs::ReceiveMessage(void* thisPtr, void* oldEBP, uint32_t messageType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize) +{ + if (messageType == k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello) + { +#ifdef DEBUG + printf("Packet == k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello\n"); +#endif + if (g_Options.profile_active) { + + MatchmakingGC2ClientHello msg((void*)((DWORD)pubDest + 8), *pcubMsgSize - 8); + MatchmakingGC2ClientHello::PlayerCommendationInfo commendations; + commendations.cmd_friendly().set(g_Options.comfriendly); + commendations.cmd_teaching().set(g_Options.comteacher); + commendations.cmd_leader().set(g_Options.comleader); + msg.commendation().set(commendations); + + msg.player_level().set(g_Options.level); + msg.player_cur_xp().set(g_Options.xp); + + if (g_Options.banduration != 0) { + msg.penalty_reason().set(g_Options.banreason); + msg.penalty_seconds().set(g_Options.banduration); + } + + msg.vac_banned().set(g_Options.vacban); + + MatchmakingGC2ClientHello::PlayerRankingInfo ranking; + ranking.account_id().set(iff.g_SteamUser->GetSteamID().GetAccountID()); + ranking.rank_type_id().set(6); + ranking.rank_id().set(g_Options.rankz.value->arr[0].rank); + ranking.wins().set(g_Options.rankz.value->arr[0].wins); + msg.ranking().set(ranking); + + auto packet = msg.serialize(); + WritePacket(packet, thisPtr, oldEBP, pubDest, cubDest, pcubMsgSize); + +#ifdef DEBUG + printf("send packet 0 6 rank %d wins %d\n", g_Options.rankz.value->arr[0].rank, g_Options.rankz.value->arr[0].wins); +#endif + } + + + + } + else if (messageType == k_EMsgGCCStrike15_v2_ClientGCRankUpdate) + { +#ifdef DEBUG + printf("Packet == k_EMsgGCCStrike15_v2_ClientGCRankUpdate\n"); +#endif + + if (g_Options.profile_active) { + CMsgGCCStrike15_v2_ClientGCRankUpdate msg((void*)((DWORD)pubDest + 8), *pcubMsgSize - 8); + + auto ranking = msg.ranking().get(); + + int ranktype = ranking.rank_type_id().get(); +#ifdef DEBUG + printf("ranktype = %d\n", ranktype); +#endif + int rankcount = 0; + if (ranktype == 7) rankcount = 1; + if (ranktype == 10) rankcount = 2; + + ranking.rank_id().set(g_Options.rankz.value->arr[rankcount].rank); + ranking.wins().set(g_Options.rankz.value->arr[rankcount].wins); + + msg.ranking().set(ranking); + + auto packet = msg.serialize(); + WritePacket(packet, thisPtr, oldEBP, pubDest, cubDest, pcubMsgSize); + + } + + } + else if (messageType == k_EMsgGCClientWelcome) + { +#ifdef DEBUG + printf("Packet == k_EMsgGCClientWelcome\n"); +#endif + auto packet = inventory_changer(pubDest, pcubMsgSize); + WritePacket(packet, thisPtr, oldEBP, pubDest, cubDest, pcubMsgSize); + + } +#ifdef DEBUG + printf(".GC Receive: %d\n", messageType); +#endif +} + +bool Protobuffs::PreSendMessage(uint32_t& unMsgType, void* pubData, uint32_t& cubData) +{ + uint32_t MessageType = unMsgType & 0x7FFFFFFF; +#ifdef DEBUG + printf(".GC Sent: %d\n", MessageType); +#endif + return true; +} + +bool Protobuffs::SendClientHello() +{ + CMsgClientHello msg; + msg.client_session_need().set(1); + auto packet = msg.serialize(); + + void* ptr = malloc(packet.size() + 8); + + if (!ptr) + return false; + + ((uint32_t*)ptr)[0] = k_EMsgGCClientHello | ((DWORD)1 << 31); + ((uint32_t*)ptr)[1] = 0; + + memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size()); + bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCClientHello | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK; + free(ptr); + + return result; +} + +bool Protobuffs::SendMatchmakingClient2GCHello() +{ + ProtoWriter msg(0); + auto packet = msg.serialize(); + void* ptr = malloc(packet.size() + 8); + + if (!ptr) + return false; + + ((uint32_t*)ptr)[0] = k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello | ((DWORD)1 << 31); + ((uint32_t*)ptr)[1] = 0; + + memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size()); + bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK; + free(ptr); + + return result; +} + +bool Protobuffs::SendClientGcRankUpdate() +{ + MatchmakingGC2ClientHello::PlayerRankingInfo rank_wingman; + rank_wingman.rank_type_id().set(7); + + CMsgGCCStrike15_v2_ClientGCRankUpdate msg; + msg.ranking().set(rank_wingman); + + auto packet = msg.serialize(); + + void* ptr = malloc(packet.size() + 8); + + if (!ptr) + return false; + + ((uint32_t*)ptr)[0] = k_EMsgGCCStrike15_v2_ClientGCRankUpdate | ((DWORD)1 << 31); + ((uint32_t*)ptr)[1] = 0; + + memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size()); + bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCCStrike15_v2_ClientGCRankUpdate | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK; + free(ptr); + + return result; +} + +bool Protobuffs::EquipWeapon(int weaponid, int classid, int slotid) +{ + CMsgAdjustItemEquippedState msg; + msg.item_id().set(START_ITEM_INDEX + weaponid); + msg.new_class().set(classid); + msg.new_slot().set(slotid); + msg.swap().set(true); + auto packet = msg.serialize(); + + void* ptr = malloc(packet.size() + 8); + + if (!ptr) + return false; + + ((uint32_t*)ptr)[0] = k_EMsgGCAdjustItemEquippedState | ((DWORD)1 << 31); + ((uint32_t*)ptr)[1] = 0; + + memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size()); + bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCAdjustItemEquippedState | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK; + free(ptr); + + return result; +} + + + + + +VMTHook* ProtoHook = nullptr; +Protobuffs ProtoFeatures; + + + +EGCResult __fastcall hkGCRetrieveMessage(void* ecx, void*, uint32_t* punMsgType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize) +{ + static auto oGCRetrieveMessage = ProtoHook->GetOriginal(2); + + auto status = oGCRetrieveMessage(ecx, punMsgType, pubDest, cubDest, pcubMsgSize); + + + if (status == k_EGCResultOK) + { + void* thisPtr = nullptr; + __asm mov thisPtr, ebx; + auto oldEBP = *reinterpret_cast((uint32_t)_AddressOfReturnAddress() - 4); + + uint32_t messageType = *punMsgType & 0x7FFFFFFF; + ProtoFeatures.ReceiveMessage(thisPtr, oldEBP, messageType, pubDest, cubDest, pcubMsgSize); + } + + + return status; +} + +EGCResult __fastcall hkGCSendMessage(void* ecx, void*, uint32_t unMsgType, const void* pubData, uint32_t cubData) +{ + static auto oGCSendMessage = ProtoHook->GetOriginal(0); + + bool sendMessage = ProtoFeatures.PreSendMessage(unMsgType, const_cast(pubData), cubData); + + if (!sendMessage) + return k_EGCResultOK; + + + return oGCSendMessage(ecx, unMsgType, const_cast(pubData), cubData); +} \ No newline at end of file diff --git a/SpyCustom/protobuffs.hpp b/SpyCustom/protobuffs.hpp new file mode 100644 index 0000000..7cbd9a2 --- /dev/null +++ b/SpyCustom/protobuffs.hpp @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +#include "VMT.hpp" + +#include "steam.h" +#include "intrin.h" + +extern VMTHook* ProtoHook; + +class Protobuffs +{ +public: + static void WritePacket(std::string packet, void* thisPtr, void* oldEBP, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize); + void ReceiveMessage(void* thisPtr, void* oldEBP, uint32_t messageType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize); + bool PreSendMessage(uint32_t& unMsgType, void* pubData, uint32_t& cubData); + bool SendClientHello(); + bool SendMatchmakingClient2GCHello(); + bool SendClientGcRankUpdate(); + bool EquipWeapon(int weaponid, int classid, int slotid); +}; + + +extern Protobuffs ProtoFeatures; + +EGCResult __fastcall hkGCRetrieveMessage(void* ecx, void*, uint32_t* punMsgType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize); +EGCResult __fastcall hkGCSendMessage(void* ecx, void*, uint32_t unMsgType, const void* pubData, uint32_t cubData); + + diff --git a/SpyCustom/proxies.hpp b/SpyCustom/proxies.hpp new file mode 100644 index 0000000..62f06d6 --- /dev/null +++ b/SpyCustom/proxies.hpp @@ -0,0 +1,195 @@ +#pragma once + + +RecvVarProxyFn fnSequenceProxyFn = NULL; + +void SetViewModelSequence(const CRecvProxyData* pDataConst, void* pStruct, void* pOut) { + + CRecvProxyData* pData = const_cast(pDataConst); + + C_BaseViewModel* pViewModel = (C_BaseViewModel*)pStruct; + + if (pViewModel) { + IClientEntity* pOwner = iff.g_pEntityList->GetClientEntityFromHandle(pViewModel->GetOwner()); + + if (pOwner && pOwner->GetIndex() == iff.g_pEngineClient->GetLocalPlayer()) { + + + + const model_t* pModel = iff.g_pMdlInfo->GetModel(pViewModel->GetModelIndex()); + const char* szModel = iff.g_pMdlInfo->GetModelName(pModel); + + int m_nSequence = pData->m_Value.m_Int; + + auto model = fnv2::hashRuntime(szModel); + + static int defknifethash = fnv2::hash("models/weapons/v_knife_default_t.mdl"); + static int defknifecthash = fnv2::hash("models/weapons/v_knife_default_ct.mdl"); + if (model == defknifethash || model == defknifecthash) model = fnv2::hash(g_Options.weapons.value->arr[0].model); + + for (int i = 2; i < g_Options.models.value->itemcount; i++) { + + if (model == g_Options.models.value->arr[i].vmodel_hash) + { + if (g_Options.models.value->arr[i].seq_active) + m_nSequence = g_Options.models.value->arr[i].seqs[m_nSequence].seq_repl; + break; + } + if (model == fnv2::hash(g_Options.models.value->arr[i].vmodel_orig)) + { + if (g_Options.models.value->arr[i].seq_active) + m_nSequence = g_Options.models.value->arr[i].seqs[m_nSequence].seq_repl; + + break; + } + } + + switch (model) { + case fnv2::hash("models/weapons/v_knife_butterfly.mdl"): + { + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_DRAW: + m_nSequence = random(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2); break; + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = random(SEQUENCE_BUTTERFLY_LOOKAT01, SEQUENCE_BUTTERFLY_LOOKAT03); break; + default: + m_nSequence++; + } + break; + } + + + case fnv2::hash("models/weapons/v_knife_falchion_advanced.mdl"): + { + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_IDLE2: + m_nSequence = SEQUENCE_FALCHION_IDLE1; break; + case SEQUENCE_DEFAULT_HEAVY_MISS1: + m_nSequence = random(SEQUENCE_FALCHION_HEAVY_MISS1, SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP); break; + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = random(SEQUENCE_FALCHION_LOOKAT01, SEQUENCE_FALCHION_LOOKAT02); break; + case SEQUENCE_DEFAULT_DRAW: + case SEQUENCE_DEFAULT_IDLE1: + m_nSequence = m_nSequence; break; + default: + m_nSequence--; + } + break; + } + + + case fnv2::hash("models/weapons/v_knife_push.mdl"): + { + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_IDLE2: + m_nSequence = SEQUENCE_DAGGERS_IDLE1; break; + case SEQUENCE_DEFAULT_LIGHT_MISS1: + case SEQUENCE_DEFAULT_LIGHT_MISS2: + m_nSequence = random(SEQUENCE_DAGGERS_LIGHT_MISS1, SEQUENCE_DAGGERS_LIGHT_MISS5); break; + case SEQUENCE_DEFAULT_HEAVY_MISS1: + m_nSequence = random(SEQUENCE_DAGGERS_HEAVY_MISS2, SEQUENCE_DAGGERS_HEAVY_MISS1); break; + case SEQUENCE_DEFAULT_HEAVY_HIT1: + case SEQUENCE_DEFAULT_HEAVY_BACKSTAB: + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = m_nSequence + 3; break; + case SEQUENCE_DEFAULT_DRAW: + case SEQUENCE_DEFAULT_IDLE1: + m_nSequence = m_nSequence; break; + default: + m_nSequence = m_nSequence + 2; + } + break; + } + + case fnv2::hash("models/weapons/v_knife_survival_bowie.mdl"): + { + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_DRAW: + case SEQUENCE_DEFAULT_IDLE1: + m_nSequence = m_nSequence; break; + case SEQUENCE_DEFAULT_IDLE2: + m_nSequence = SEQUENCE_BOWIE_IDLE1; break; + default: + m_nSequence = m_nSequence - 1; + } + break; + } + + case fnv2::hash("models/weapons/v_knife_ursus.mdl"): + case fnv2::hash("models/weapons/v_knife_skeleton.mdl"): + case fnv2::hash("models/weapons/v_knife_outdoor.mdl"): + case fnv2::hash("models/weapons/v_knife_cord.mdl"): + case fnv2::hash("models/weapons/v_knife_canis.mdl"): + { + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_DRAW: + m_nSequence = random(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2); break; + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = random(SEQUENCE_BUTTERFLY_LOOKAT01, 14); break; + default: + m_nSequence = m_nSequence + 1; + } + break; + } + + case fnv2::hash("models/weapons/v_knife_stiletto.mdl"): + { + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = random(12, 13); break; + } + break; + } + + case fnv2::hash("models/weapons/v_knife_widowmaker.mdl"): + { + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = random(14, 15); break; + } + break; + } + + case fnv2::hash("models/weapons/v_fists.mdl"): + case fnv2::hash("models/weapons/v_axe.mdl"): + case fnv2::hash("models/weapons/v_hammer.mdl"): + case fnv2::hash("models/weapons/v_spanner.mdl"): + { + static int lastpunch = 3; + switch (m_nSequence) + { + case SEQUENCE_DEFAULT_DRAW: + m_nSequence = 1; break; + case 1: + case 2: + case 12: + m_nSequence = 0; break; + default: + if (lastpunch == 3) lastpunch = 2; else lastpunch = 3; + m_nSequence = lastpunch; + } + + break; + } + + } + +#ifdef DEBUG + cout << "activ " << (char*)pViewModel->GetSequenceActivity(m_nSequence); + printf(" new seq %d (%s)\n ", m_nSequence, szModel); +#endif + + + pData->m_Value.m_Int = m_nSequence; + } + } + + fnSequenceProxyFn(pData, pStruct, pOut); +} \ No newline at end of file diff --git a/SpyCustom/ragdoll.h b/SpyCustom/ragdoll.h new file mode 100644 index 0000000..9a5de13 --- /dev/null +++ b/SpyCustom/ragdoll.h @@ -0,0 +1,111 @@ +#ifndef RAGDOLL_H +#define RAGDOLL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "ragdoll_shared.h" + +#define RAGDOLL_VISUALIZE 0 + +class C_BaseEntity; +class CStudioHdr; +struct mstudiobone_t; +class Vector; +class IPhysicsObject; +class CBoneAccessor; + +abstract_class IRagdoll +{ +public: + virtual ~IRagdoll() {} + + virtual void RagdollBone(C_BaseEntity * ent, mstudiobone_t * pbones, int boneCount, bool* boneSimulated, CBoneAccessor & pBoneToWorld) = 0; + virtual const Vector& GetRagdollOrigin() = 0; + virtual void GetRagdollBounds(Vector& mins, Vector& maxs) = 0; + virtual int RagdollBoneCount() const = 0; + virtual IPhysicsObject* GetElement(int elementNum) = 0; + virtual void DrawWireframe(void) = 0; + virtual void VPhysicsUpdate(IPhysicsObject* pObject) = 0; +}; + +class CRagdoll : public IRagdoll +{ +public: + CRagdoll(); + ~CRagdoll(void); + + DECLARE_SIMPLE_DATADESC(); + + void Init( + C_BaseEntity* ent, + CStudioHdr* pstudiohdr, + const Vector& forceVector, + int forceBone, + const matrix3x4_t* pDeltaBones0, + const matrix3x4_t* pDeltaBones1, + const matrix3x4_t* pCurrentBonePosition, + float boneDt); + + virtual void RagdollBone(C_BaseEntity* ent, mstudiobone_t* pbones, int boneCount, bool* boneSimulated, CBoneAccessor& pBoneToWorld); + virtual const Vector& GetRagdollOrigin(); + virtual void GetRagdollBounds(Vector& theMins, Vector& theMaxs); + void BuildRagdollBounds(C_BaseEntity* ent); + + virtual IPhysicsObject* GetElement(int elementNum); + virtual IPhysicsConstraintGroup* GetConstraintGroup() { return m_ragdoll.pGroup; } + virtual void DrawWireframe(); + virtual void VPhysicsUpdate(IPhysicsObject* pPhysics); + virtual int RagdollBoneCount() const { return m_ragdoll.listCount; } + + + void SetInitialBonePosition(CStudioHdr* pstudiohdr, const CBoneAccessor& pDesiredBonePosition); + + bool IsValid() { return m_ragdoll.listCount > 0; } + bool IsAsleep(void) const { return m_allAsleep; } + + void ResetRagdollSleepAfterTime(void); + float GetLastVPhysicsUpdateTime() const { return m_lastUpdate; } + +private: + + void CheckSettleStationaryRagdoll(); + void PhysForceRagdollToSleep(); + + ragdoll_t m_ragdoll; + Vector m_mins, m_maxs; + Vector m_origin; + float m_lastUpdate; + bool m_allAsleep; + Vector m_vecLastOrigin; + float m_flLastOriginChangeTime; + float m_flAwakeTime; + +#if RAGDOLL_VISUALIZE + matrix3x4_t m_savedBone1[MAXSTUDIOBONES]; + matrix3x4_t m_savedBone2[MAXSTUDIOBONES]; + matrix3x4_t m_savedBone3[MAXSTUDIOBONES]; +#endif + +public: + + ragdoll_t* GetRagdoll(void) { return &m_ragdoll; } +}; + + +CRagdoll* CreateRagdoll( + C_BaseEntity* ent, + CStudioHdr* pstudiohdr, + const Vector& forceVector, + int forceBone, + const matrix3x4_t* pDeltaBones0, + const matrix3x4_t* pDeltaBones1, + const matrix3x4_t* pCurrentBonePosition, + float boneDt); + + +void NoteRagdollCreationTick(C_BaseEntity* pRagdoll); +bool WasRagdollCreatedOnCurrentTick(C_BaseEntity* pRagdoll); + +#endif \ No newline at end of file diff --git a/SpyCustom/ragdoll_shared.h b/SpyCustom/ragdoll_shared.h new file mode 100644 index 0000000..ca5ed8a --- /dev/null +++ b/SpyCustom/ragdoll_shared.h @@ -0,0 +1,135 @@ +#ifndef RAGDOLL_SHARED_H +#define RAGDOLL_SHARED_H +#ifdef _WIN32 +#pragma once +#endif + +class IPhysicsObject; +class IPhysicsConstraint; +class IPhysicsConstraintGroup; +class IPhysicsCollision; +class IPhysicsEnvironment; +class IPhysicsSurfaceProps; +struct matrix3x4_t; + +struct vcollide_t; +struct studiohdr_t; +class CStudioHdr; +class CBoneAccessor; + +#include "vector.h" +#include "bone_accessor.h" + +#define RAGDOLL_MAX_ELEMENTS 24 +#define RAGDOLL_INDEX_BITS 5 + +#define CORE_DISSOLVE_FADE_START 0.2f +#define CORE_DISSOLVE_MODEL_FADE_START 0.1f +#define CORE_DISSOLVE_MODEL_FADE_LENGTH 0.05f +#define CORE_DISSOLVE_FADEIN_LENGTH 0.1f + +struct ragdollelement_t +{ + Vector originParentSpace; + IPhysicsObject* pObject; + IPhysicsConstraint* pConstraint; + int parentIndex; +}; + +struct ragdollanimatedfriction_t +{ + float flFrictionTimeIn; + float flFrictionTimeOut; + float flFrictionTimeHold; + int iMinAnimatedFriction; + int iMaxAnimatedFriction; +}; + +struct ragdoll_t +{ + int listCount; + bool allowStretch; + bool unused; + IPhysicsConstraintGroup* pGroup; + ragdollelement_t list[RAGDOLL_MAX_ELEMENTS]; + int boneIndex[RAGDOLL_MAX_ELEMENTS]; + ragdollanimatedfriction_t animfriction; +}; + +struct ragdollparams_t +{ + void* pGameData; + vcollide_t* pCollide; + CStudioHdr* pStudioHdr; + int modelIndex; + Vector forcePosition; + Vector forceVector; + int forceBoneIndex; + const matrix3x4_t* pCurrentBones; + float jointFrictionScale; + bool allowStretch; + bool fixedConstraints; +}; + +class CRagdollLRURetirement : public CAutoGameSystemPerFrame +{ +public: + CRagdollLRURetirement(char const* name) : CAutoGameSystemPerFrame(name) + { + } + + virtual void Update(float frametime); + virtual void FrameUpdatePostEntityThink(void); + + void MoveToTopOfLRU(CBaseAnimating* pRagdoll, bool bImportant = false); + void SetMaxRagdollCount(int iMaxCount) { m_iMaxRagdolls = iMaxCount; } + + virtual void LevelInitPreEntity(void); + int CountRagdolls(bool bOnlySimulatingRagdolls) { return bOnlySimulatingRagdolls ? m_iSimulatedRagdollCount : m_iRagdollCount; } + +private: + typedef CHandle CRagdollHandle; + CUtlLinkedList< CRagdollHandle > m_LRU; + CUtlLinkedList< CRagdollHandle > m_LRUImportantRagdolls; + + int m_iMaxRagdolls; + int m_iSimulatedRagdollCount; + int m_iRagdollCount; +}; + +extern CRagdollLRURetirement s_RagdollLRU; + +class CRagdollLowViolenceManager +{ +public: + CRagdollLowViolenceManager() { m_bLowViolence = false; } + void SetLowViolence(const char* pMapName); + bool IsLowViolence(void) { return m_bLowViolence; } + +private: + bool m_bLowViolence; +}; + +extern CRagdollLowViolenceManager g_RagdollLVManager; + + +bool RagdollCreate(ragdoll_t& ragdoll, const ragdollparams_t& params, IPhysicsEnvironment* pPhysEnv); + +void RagdollActivate(ragdoll_t& ragdoll, vcollide_t* pCollide, int modelIndex, bool bForceWake = true); +void RagdollSetupCollisions(ragdoll_t& ragdoll, vcollide_t* pCollide, int modelIndex); +void RagdollDestroy(ragdoll_t& ragdoll); + +bool RagdollGetBoneMatrix(const ragdoll_t& ragdoll, CBoneAccessor& pBoneToWorld, int objectIndex); + +int RagdollExtractBoneIndices(int* boneIndexOut, CStudioHdr* pStudioHdr, vcollide_t* pCollide); + +void RagdollComputeExactBbox(const ragdoll_t& ragdoll, const Vector& origin, Vector& outMins, Vector& outMaxs); +bool RagdollIsAsleep(const ragdoll_t& ragdoll); +void RagdollSetupAnimatedFriction(IPhysicsEnvironment* pPhysEnv, ragdoll_t* ragdoll, int iModelIndex); + +void RagdollApplyAnimationAsVelocity(ragdoll_t& ragdoll, const matrix3x4_t* pBoneToWorld); +void RagdollApplyAnimationAsVelocity(ragdoll_t& ragdoll, const matrix3x4_t* pPrevBones, const matrix3x4_t* pCurrentBones, float dt); + +void RagdollSolveSeparation(ragdoll_t& ragdoll, CBaseEntity* pEntity); + +#endif \ No newline at end of file diff --git a/SpyCustom/random.h b/SpyCustom/random.h new file mode 100644 index 0000000..8448e2d --- /dev/null +++ b/SpyCustom/random.h @@ -0,0 +1,77 @@ +#ifndef VSTDLIB_RANDOM_H +#define VSTDLIB_RANDOM_H + +#include "vstdlib.h" +#include "basetypes.h" +#include "threadtools.h" +#include "interface.h" + +#define NTAB 32 + +#pragma warning(push) +#pragma warning( disable:4251 ) + +class IUniformRandomStream +{ +public: + virtual void SetSeed(int iSeed) = 0; + + virtual float RandomFloat(float flMinVal = 0.0f, float flMaxVal = 1.0f) = 0; + virtual int RandomInt(int iMinVal, int iMaxVal) = 0; + virtual float RandomFloatExp(float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f) = 0; +}; + + +class VSTDLIB_CLASS CUniformRandomStream : public IUniformRandomStream +{ +public: + CUniformRandomStream(); + + virtual void SetSeed(int iSeed); + + virtual float RandomFloat(float flMinVal = 0.0f, float flMaxVal = 1.0f); + virtual int RandomInt(int iMinVal, int iMaxVal); + virtual float RandomFloatExp(float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f); + +private: + int GenerateRandomNumber(); + + int m_idum; + int m_iy; + int m_iv[NTAB]; + + CThreadFastMutex m_mutex; +}; + + +class VSTDLIB_CLASS CGaussianRandomStream +{ +public: + CGaussianRandomStream(IUniformRandomStream* pUniformStream = NULL); + + void AttachToStream(IUniformRandomStream* pUniformStream = NULL); + + float RandomFloat(float flMean = 0.0f, float flStdDev = 1.0f); + +private: + IUniformRandomStream* m_pUniformStream; + bool m_bHaveValue; + float m_flRandomValue; + + CThreadFastMutex m_mutex; +}; + + +VSTDLIB_INTERFACE void RandomSeed(int iSeed); +VSTDLIB_INTERFACE float RandomFloat(float flMinVal = 0.0f, float flMaxVal = 1.0f); +VSTDLIB_INTERFACE float RandomFloatExp(float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f); +VSTDLIB_INTERFACE int RandomInt(int iMinVal, int iMaxVal); +VSTDLIB_INTERFACE float RandomGaussianFloat(float flMean = 0.0f, float flStdDev = 1.0f); + + +VSTDLIB_INTERFACE void InstallUniformRandomStream(IUniformRandomStream* pStream); + + +#pragma warning(pop) + +#endif \ No newline at end of file diff --git a/SpyCustom/rangecheckedvar.h b/SpyCustom/rangecheckedvar.h new file mode 100644 index 0000000..9c07cb4 --- /dev/null +++ b/SpyCustom/rangecheckedvar.h @@ -0,0 +1,109 @@ +#ifndef RANGECHECKEDVAR_H +#define RANGECHECKEDVAR_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "dbg.h" +#include "threadtools.h" +#include "vector.h" +#include + + +class CDisableRangeChecks +{ +public: + CDisableRangeChecks(); + ~CDisableRangeChecks(); +}; + + +template< class T > +inline void RangeCheck(const T& value, int minValue, int maxValue) +{ +#ifdef _DEBUG + extern bool g_bDoRangeChecks; + if (ThreadInMainThread() && g_bDoRangeChecks) + { + Assert(_finite(value)); + } +#endif +} + +inline void RangeCheck(const Vector& value, int minValue, int maxValue) +{ +#ifdef _DEBUG + RangeCheck(value.x, minValue, maxValue); + RangeCheck(value.y, minValue, maxValue); + RangeCheck(value.z, minValue, maxValue); +#endif +} + + +template< class T, int minValue, int maxValue, int startValue > +class CRangeCheckedVar +{ +public: + + inline CRangeCheckedVar() + { + m_Val = startValue; + } + + inline CRangeCheckedVar(const T& value) + { + *this = value; + } + + T GetRaw() const + { + return m_Val; + } + + inline void Clamp() + { + if (m_Val < minValue) + m_Val = minValue; + else if (m_Val > maxValue) + m_Val = maxValue; + } + + inline operator const T& () const + { + return m_Val; + } + + inline CRangeCheckedVar& operator=(const T& value) + { + RangeCheck(value, minValue, maxValue); + m_Val = value; + return *this; + } + + inline CRangeCheckedVar& operator+=(const T& value) + { + return (*this = m_Val + value); + } + + inline CRangeCheckedVar& operator-=(const T& value) + { + return (*this = m_Val - value); + } + + inline CRangeCheckedVar& operator*=(const T& value) + { + return (*this = m_Val * value); + } + + inline CRangeCheckedVar& operator/=(const T& value) + { + return (*this = m_Val / value); + } + +private: + + T m_Val; +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/recvproxy.h b/SpyCustom/recvproxy.h new file mode 100644 index 0000000..412c8c4 --- /dev/null +++ b/SpyCustom/recvproxy.h @@ -0,0 +1,45 @@ +#ifndef RECVPROXY_H +#define RECVPROXY_H + + +class CRecvProxyData; + + +void RecvProxy_IntToEHandle(const CRecvProxyData* pData, void* pStruct, void* pOut); + +void RecvProxy_IntToMoveParent(const CRecvProxyData* pData, void* pStruct, void* pOut); +void RecvProxy_IntToColor32(const CRecvProxyData* pData, void* pStruct, void* pOut); +void RecvProxy_IntSubOne(const CRecvProxyData* pData, void* pStruct, void* pOut); +void RecvProxy_ShortSubOne(const CRecvProxyData* pData, void* pStruct, void* pOut); +void RecvProxy_InterpolationAmountChanged(const CRecvProxyData* pData, void* pStruct, void* pOut); + +RecvProp RecvPropTime( + char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE); + +#if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID ) +RecvProp RecvPropPredictableId( + char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE); +#endif + +RecvProp RecvPropEHandle( + char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE, + RecvVarProxyFn proxyFn = RecvProxy_IntToEHandle); + +RecvProp RecvPropBool( + char* pVarName, + int offset, + int sizeofVar); + +RecvProp RecvPropIntWithMinusOneFlag( + char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE, + RecvVarProxyFn proxyFn = RecvProxy_IntSubOne); + +#endif diff --git a/SpyCustom/refcount.h b/SpyCustom/refcount.h new file mode 100644 index 0000000..4f10d10 --- /dev/null +++ b/SpyCustom/refcount.h @@ -0,0 +1,320 @@ +#ifndef REFCOUNT_H +#define REFCOUNT_H + +#include "threadtools.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +class IRefCounted +{ +public: + virtual int AddRef() = 0; + virtual int Release() = 0; +}; + + +template +inline int SafeRelease(REFCOUNTED_ITEM_PTR& pRef) +{ + REFCOUNTED_ITEM_PTR* ppRef = &pRef; + if (*ppRef) + { + int result = (*ppRef)->Release(); + *ppRef = NULL; + return result; + } + return 0; +} + +template +class CAutoRef +{ +public: + CAutoRef(T* pRef) + : m_pRef(pRef) + { + if (m_pRef) + m_pRef->AddRef(); + } + + ~CAutoRef() + { + if (m_pRef) + m_pRef->Release(); + } + +private: + T* m_pRef; +}; + +#define RetAddRef( p ) ( (p)->AddRef(), (p) ) +#define InlineAddRef( p ) ( (p)->AddRef(), (p) ) + + +template +class CBaseAutoPtr +{ +public: + CBaseAutoPtr() : m_pObject(0) {} + CBaseAutoPtr(T* pFrom) : m_pObject(pFrom) {} + + operator const void* () const { return m_pObject; } + operator void* () { return m_pObject; } + + operator const T* () const { return m_pObject; } + operator const T* () { return m_pObject; } + operator T* () { return m_pObject; } + + int operator=(int i) { AssertMsg(i == 0, "Only NULL allowed on integer assign"); m_pObject = 0; return 0; } + T* operator=(T* p) { m_pObject = p; return p; } + + bool operator !() const { return (!m_pObject); } + bool operator!=(int i) const { AssertMsg(i == 0, "Only NULL allowed on integer compare"); return (m_pObject != NULL); } + bool operator==(const void* p) const { return (m_pObject == p); } + bool operator!=(const void* p) const { return (m_pObject != p); } + bool operator==(T* p) const { return operator==((void*)p); } + bool operator!=(T* p) const { return operator!=((void*)p); } + bool operator==(const CBaseAutoPtr& p) const { return operator==((const void*)p); } + bool operator!=(const CBaseAutoPtr& p) const { return operator!=((const void*)p); } + + T* operator->() { return m_pObject; } + T& operator *() { return *m_pObject; } + T** operator &() { return &m_pObject; } + + const T* operator->() const { return m_pObject; } + const T& operator *() const { return *m_pObject; } + T* const* operator &() const { return &m_pObject; } + +protected: + CBaseAutoPtr(const CBaseAutoPtr& from) : m_pObject(from.m_pObject) {} + void operator=(const CBaseAutoPtr& from) { m_pObject = from.m_pObject; } + + T* m_pObject; +}; + +template +class CRefPtr : public CBaseAutoPtr +{ + typedef CBaseAutoPtr BaseClass; +public: + CRefPtr() {} + CRefPtr(T* pInit) : BaseClass(pInit) {} + CRefPtr(const CRefPtr& from) : BaseClass(from) {} + ~CRefPtr() { if (BaseClass::m_pObject) BaseClass::m_pObject->Release(); } + + void operator=(const CRefPtr& from) { BaseClass::operator=(from); } + + int operator=(int i) { return BaseClass::operator=(i); } + T* operator=(T* p) { return BaseClass::operator=(p); } + + operator bool() const { return !BaseClass::operator!(); } + operator bool() { return !BaseClass::operator!(); } + + void SafeRelease() { if (BaseClass::m_pObject) BaseClass::m_pObject->Release(); BaseClass::m_pObject = 0; } + void AssignAddRef(T* pFrom) { SafeRelease(); if (pFrom) pFrom->AddRef(); BaseClass::m_pObject = pFrom; } + void AddRefAssignTo(T*& pTo) { ::SafeRelease(pTo); if (BaseClass::m_pObject) BaseClass::m_pObject->AddRef(); pTo = BaseClass::m_pObject; } +}; + + +class CRefMT +{ +public: + static int Increment(int* p) { return ThreadInterlockedIncrement((long*)p); } + static int Decrement(int* p) { return ThreadInterlockedDecrement((long*)p); } +}; + +class CRefST +{ +public: + static int Increment(int* p) { return ++(*p); } + static int Decrement(int* p) { return --(*p); } +}; + +template +class NO_VTABLE CRefCountServiceBase +{ +protected: + CRefCountServiceBase() + : m_iRefs(1) + { + } + + virtual ~CRefCountServiceBase() + { + } + + virtual bool OnFinalRelease() + { + return true; + } + + int GetRefCount() const + { + return m_iRefs; + } + + int DoAddRef() + { + return CRefThreading::Increment(&m_iRefs); + } + + int DoRelease() + { + int result = CRefThreading::Decrement(&m_iRefs); + if (result) + return result; + if (OnFinalRelease() && bSelfDelete) + delete this; + return 0; + } + +private: + int m_iRefs; +}; + +class CRefCountServiceNull +{ +protected: + static int DoAddRef() { return 1; } + static int DoRelease() { return 1; } +}; + +template +class NO_VTABLE CRefCountServiceDestruct +{ +protected: + CRefCountServiceDestruct() + : m_iRefs(1) + { + } + + virtual ~CRefCountServiceDestruct() + { + } + + int GetRefCount() const + { + return m_iRefs; + } + + int DoAddRef() + { + return CRefThreading::Increment(&m_iRefs); + } + + int DoRelease() + { + int result = CRefThreading::Decrement(&m_iRefs); + if (result) + return result; + this->~CRefCountServiceDestruct(); + return 0; + } + +private: + int m_iRefs; +}; + + +typedef CRefCountServiceBase CRefCountServiceST; +typedef CRefCountServiceBase CRefCountServiceNoDeleteST; + +typedef CRefCountServiceBase CRefCountServiceMT; +typedef CRefCountServiceBase CRefCountServiceNoDeleteMT; + +typedef CRefCountServiceNoDeleteMT CRefCountServiceNoDelete; +typedef CRefCountServiceMT CRefCountService; + +template < class REFCOUNT_SERVICE = CRefCountService > +class NO_VTABLE CRefCounted : public REFCOUNT_SERVICE +{ +public: + virtual ~CRefCounted() {} + int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } + int Release() { return REFCOUNT_SERVICE::DoRelease(); } +}; + +template < class BASE1, class REFCOUNT_SERVICE = CRefCountService > +class NO_VTABLE CRefCounted1 : public BASE1, + public REFCOUNT_SERVICE +{ +public: + virtual ~CRefCounted1() {} + int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } + int Release() { return REFCOUNT_SERVICE::DoRelease(); } +}; + +template < class BASE1, class BASE2, class REFCOUNT_SERVICE = CRefCountService > +class NO_VTABLE CRefCounted2 : public BASE1, public BASE2, + public REFCOUNT_SERVICE +{ +public: + virtual ~CRefCounted2() {} + int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } + int Release() { return REFCOUNT_SERVICE::DoRelease(); } +}; + +template < class BASE1, class BASE2, class BASE3, class REFCOUNT_SERVICE = CRefCountService > +class NO_VTABLE CRefCounted3 : public BASE1, public BASE2, public BASE3, + public REFCOUNT_SERVICE +{ + virtual ~CRefCounted3() {} + int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } + int Release() { return REFCOUNT_SERVICE::DoRelease(); } +}; + +template < class BASE1, class BASE2, class BASE3, class BASE4, class REFCOUNT_SERVICE = CRefCountService > +class NO_VTABLE CRefCounted4 : public BASE1, public BASE2, public BASE3, public BASE4, + public REFCOUNT_SERVICE +{ +public: + virtual ~CRefCounted4() {} + int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } + int Release() { return REFCOUNT_SERVICE::DoRelease(); } +}; + +template < class BASE1, class BASE2, class BASE3, class BASE4, class BASE5, class REFCOUNT_SERVICE = CRefCountService > +class NO_VTABLE CRefCounted5 : public BASE1, public BASE2, public BASE3, public BASE4, public BASE5, + public REFCOUNT_SERVICE +{ +public: + virtual ~CRefCounted5() {} + int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } + int Release() { return REFCOUNT_SERVICE::DoRelease(); } +}; + +template +class CRefDebug : public BASE_REFCOUNTED +{ +public: +#ifdef _DEBUG + CRefDebug() + { + AssertMsg(this->GetRefCount() == 1, "Expected initial ref count of 1"); + DevMsg("%s:create 0x%x\n", (pszName) ? pszName : "", this); + } + + virtual ~CRefDebug() + { + AssertDevMsg(this->GetRefCount() == FINAL_REFS, "Object still referenced on destroy?"); + DevMsg("%s:destroy 0x%x\n", (pszName) ? pszName : "", this); + } + + int AddRef() + { + DevMsg("%s:(0x%x)->AddRef() --> %d\n", (pszName) ? pszName : "", this, this->GetRefCount() + 1); + return BASE_REFCOUNTED::AddRef(); + } + + int Release() + { + DevMsg("%s:(0x%x)->Release() --> %d\n", (pszName) ? pszName : "", this, this->GetRefCount() - 1); + Assert(this->GetRefCount() > 0); + return BASE_REFCOUNTED::Release(); + } +#endif +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/resource.h b/SpyCustom/resource.h new file mode 100644 index 0000000..57db8dd --- /dev/null +++ b/SpyCustom/resource.h @@ -0,0 +1,11 @@ +#define IDR_WAVE1 101 +#define IDR_WAVE2 102 + +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/SpyCustom/sceneentity_shared.h b/SpyCustom/sceneentity_shared.h new file mode 100644 index 0000000..dc5e3d0 --- /dev/null +++ b/SpyCustom/sceneentity_shared.h @@ -0,0 +1,96 @@ +#ifndef SCENEENTITY_SHARED_H +#define SCENEENTITY_SHARED_H +#ifdef _WIN32 +#pragma once +#endif + +#if defined( CLIENT_DLL ) +#define CBaseFlex C_BaseFlex +#define CSceneEntity C_SceneEntity +#endif + +#include "iscenetokenprocessor.h" + +class CBaseFlex; + +class CChoreoEvent; +class CChoreoScene; +class CChoreoActor; +class CSceneEntity; + +class CSceneEventInfo +{ +public: + CSceneEventInfo() + : + m_pEvent(0), + m_pScene(0), + m_pActor(0), + m_bStarted(false), + m_iLayer(-1), + m_iPriority(0), + m_nSequence(0), + m_bIsGesture(false), + m_flWeight(0.0f), + m_hTarget(), + m_bIsMoving(false), + m_bHasArrived(false), + m_flInitialYaw(0.0f), + m_flTargetYaw(0.0f), + m_flFacingYaw(0.0f), + m_nType(0), + m_flNext(0.0f), + m_bClientSide(false) + { + } + + CChoreoEvent* m_pEvent; + + CChoreoScene* m_pScene; + + CChoreoActor* m_pActor; + + bool m_bStarted; + +public: + int m_iLayer; + int m_iPriority; + int m_nSequence; + bool m_bIsGesture; + float m_flWeight; + + EHANDLE m_hTarget; + bool m_bIsMoving; + bool m_bHasArrived; + float m_flInitialYaw; + float m_flTargetYaw; + float m_flFacingYaw; + + int m_nType; + float m_flNext; + + bool m_bClientSide; + + void InitWeight(CBaseFlex* pActor); + float UpdateWeight(CBaseFlex* pActor); +}; + +class CSceneTokenProcessor : public ISceneTokenProcessor +{ +public: + const char* CurrentToken(void); + bool GetToken(bool crossline); + bool TokenAvailable(void); + void Error(PRINTF_FORMAT_STRING const char* fmt, ...); + void SetBuffer(char* buffer); +private: + const char* m_pBuffer; + char m_szToken[1024]; +}; + +extern CSceneTokenProcessor g_TokenProcessor; + +void Scene_Printf(PRINTF_FORMAT_STRING const char* pFormat, ...); +extern ConVar scene_clientflex; + +#endif \ No newline at end of file diff --git a/SpyCustom/sdk_hud_chat.h b/SpyCustom/sdk_hud_chat.h new file mode 100644 index 0000000..cd9f6ac --- /dev/null +++ b/SpyCustom/sdk_hud_chat.h @@ -0,0 +1,79 @@ +#ifndef SDK_HUD_CHAT_H +#define SDK_HUD_CHAT_H +#ifdef _WIN32 +#pragma once +#endif + +#include "hud_basechat.h" + +#include "GetVFunc.hpp" + +class CHudChatLine : public CBaseHudChatLine +{ + DECLARE_CLASS_SIMPLE(CHudChatLine, CBaseHudChatLine); + +public: + CHudChatLine(vgui::Panel* parent, const char* panelName) : CBaseHudChatLine(parent, panelName) {} + + virtual void ApplySchemeSettings(vgui::IScheme* pScheme); + + void PerformFadeout(void); + + void MsgFunc_SayText(bf_read& msg); + +private: + CHudChatLine(const CHudChatLine&); +}; + +class CHudChatInputLine : public CBaseHudChatInputLine +{ + DECLARE_CLASS_SIMPLE(CHudChatInputLine, CBaseHudChatInputLine); + +public: + CHudChatInputLine(CBaseHudChat* parent, char const* panelName) : CBaseHudChatInputLine(parent, panelName) {} + + virtual void ApplySchemeSettings(vgui::IScheme* pScheme); +}; + +class CHudChat : public CBaseHudChat +{ + DECLARE_CLASS_SIMPLE(CHudChat, CBaseHudChat); + +public: + CHudChat(const char* pElementName); + + virtual void CreateChatInputLine(void); + virtual void CreateChatLines(void); + + virtual void Init(void); + virtual void Reset(void); + virtual void ApplySchemeSettings(vgui::IScheme* pScheme); + + void MsgFunc_SayText(bf_read& msg); + void MsgFunc_TextMsg(bf_read& msg); + + enum ChatFilters + { + CHAT_FILTER_NONE = 0, + CHAT_FILTER_JOINLEAVE = 0x000001, + CHAT_FILTER_NAMECHANGE = 0x000002, + CHAT_FILTER_PUBLICCHAT = 0x000004, + CHAT_FILTER_SERVERMSG = 0x000008, + CHAT_FILTER_TEAMCHANGE = 0x000010, + CHAT_FILTER_ACHIEVEMENT = 0x000020, + }; + + void ChatPrintf2(int iPlayerIndex, int iFilter, const char* fmt, ...) + { + char msg[1024]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, 1024, fmt, args); + getvfunc(this, 27)(this, iPlayerIndex, iFilter, fmt); + va_end(args); + } + + int GetChatInputOffset(void); +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/seemath.h b/SpyCustom/seemath.h new file mode 100644 index 0000000..118a2b0 --- /dev/null +++ b/SpyCustom/seemath.h @@ -0,0 +1,5073 @@ +#ifndef SSEMATH_H +#define SSEMATH_H + +#if defined( _X360 ) +#include +#elif defined ( _PS3 ) +#include +#include +#else +#include +#ifndef _LINUX +#include +#endif +#endif + +#ifndef SPU +#include "vector.h" +#include "mathlib.h" +#else +#include "mathlib/math_pfns.h" +#endif + +#include "fltx4.h" + +#ifdef _X360 +typedef __vector4 FLTX4; +#elif defined( _PS3 ) +typedef vec_float4 FLTX4; +#else +typedef const fltx4& FLTX4; +#endif + +struct ALIGN16 intx4 +{ + int32 m_i32[4]; + + inline int& operator[](int which) + { + return m_i32[which]; + } + + inline const int& operator[](int which) const + { + return m_i32[which]; + } + + inline int32* Base() { + return m_i32; + } + + inline const int32* Base() const + { + return m_i32; + } + + inline bool operator==(const intx4& other) const + { + return m_i32[0] == other.m_i32[0] && + m_i32[1] == other.m_i32[1] && + m_i32[2] == other.m_i32[2] && + m_i32[3] == other.m_i32[3]; + } +} ALIGN16_POST; + + +#if defined( _DEBUG ) && defined( _X360 ) +FORCEINLINE void TestVPUFlags() +{ + __vector4 a; + __asm + { + mfvscr a; + } + unsigned int* flags = (unsigned int*)&a; + unsigned int controlWord = flags[3]; + Assert(controlWord == 0); +} +#else +FORCEINLINE void TestVPUFlags() {} +#endif + + +#ifdef _X360 +#define Four_Zeros XMVectorZero() +#define Four_Ones XMVectorSplatOne() +extern const fltx4 Four_Twos; +extern const fltx4 Four_Threes; +extern const fltx4 Four_Fours; +extern const fltx4 Four_Point225s; +extern const fltx4 Four_PointFives; +extern const fltx4 Four_Thirds; +extern const fltx4 Four_TwoThirds; +extern const fltx4 Four_NegativeOnes; +extern const fltx4 Four_DegToRad; +#elif defined(SPU) +#define Four_Zeros spu_splats( 0.0f ) +#define Four_Ones spu_splats( 1.0f ) +#define Four_Twos spu_splats( 2.0f ) +#define Four_Threes spu_splats( 3.0f ) +#define Four_Fours spu_splats( 4.0f ) +#define Four_Point225s spu_splats( 0.225f ) +#define Four_PointFives spu_splats( 0.5f ) +#define Four_Thirds spu_splats( 0.33333333 ); +#define Four_TwoThirds spu_splats( 0.66666666 ); +#define Four_NegativeOnes spu_splats( -1.0f ) +#define Four_DegToRad spu_splats((float)(M_PI_F / 180.f)) +#else +extern const fltx4 Four_Zeros; +extern const fltx4 Four_Ones; +extern const fltx4 Four_Twos; +extern const fltx4 Four_Threes; +extern const fltx4 Four_Fours; +extern const fltx4 Four_Point225s; +extern const fltx4 Four_PointFives; +extern const fltx4 Four_Thirds; +extern const fltx4 Four_TwoThirds; +extern const fltx4 Four_NegativeOnes; +extern const fltx4 Four_DegToRad; +#endif +extern const fltx4 Four_Epsilons; +extern const fltx4 Four_2ToThe21s; +extern const fltx4 Four_2ToThe22s; +extern const fltx4 Four_2ToThe23s; +extern const fltx4 Four_2ToThe24s; +extern const fltx4 Four_Origin; +extern const fltx4 Four_FLT_MAX; +extern const fltx4 Four_Negative_FLT_MAX; +extern const fltx4 g_SIMD_0123; + + +extern const fltx4 Four_LinearToGammaCoefficients_A; +extern const fltx4 Four_LinearToGammaCoefficients_B; +extern const fltx4 Four_LinearToGammaCoefficients_C; +extern const fltx4 Four_LinearToGammaCoefficients_D; +extern const fltx4 Four_LinearToGammaCoefficients_E; + +extern const fltx4 Four_GammaToLinearCoefficients_A; +extern const fltx4 Four_GammaToLinearCoefficients_B; +extern const fltx4 Four_GammaToLinearCoefficients_C; +extern const fltx4 Four_GammaToLinearCoefficients_D; + + +#ifndef ALIGN16_POST +#define ALIGN16_POST +#endif +extern const ALIGN16 int32 g_SIMD_clear_signmask[] ALIGN16_POST; +extern const ALIGN16 int32 g_SIMD_signmask[] ALIGN16_POST; +extern const ALIGN16 int32 g_SIMD_lsbmask[] ALIGN16_POST; +extern const ALIGN16 int32 g_SIMD_clear_wmask[] ALIGN16_POST; +extern const ALIGN16 int32 g_SIMD_ComponentMask[4][4] ALIGN16_POST; +extern const ALIGN16 int32 g_SIMD_AllOnesMask[] ALIGN16_POST; +extern const fltx4 g_SIMD_Identity[4]; +extern const ALIGN16 int32 g_SIMD_Low16BitsMask[] ALIGN16_POST; + +extern const int32 ALIGN16 g_SIMD_SkipTailMask[4][4] ALIGN16_POST; + +extern const int32 ALIGN16 g_SIMD_EveryOtherMask[]; +#ifdef PLATFORM_PPC +#if defined(_X360) +#define PREFETCH360(address, offset) __dcbt(offset,address) +#elif defined(_PS3) +#define PREFETCH360(address, offset) __dcbt( reinterpret_cast< const char * >(address) + offset ) +#else +#error Prefetch not defined for this platform! +#endif +#else +#define PREFETCH360(x,y) +#endif + +template +inline T* AlignPointer(void* ptr) +{ +#if defined( __clang__ ) + uintp temp = (uintp)ptr; +#else + unsigned temp = ptr; +#endif + temp = ALIGN_VALUE(temp, sizeof(T)); + return (T*)temp; +} + +#ifdef _PS3 + +#define _VEC_CLEAR_SIGNMASK (__vector unsigned int) {0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff} +#define _VEC_SIGNMASK (__vector unsigned int) { 0x80000000, 0x80000000, 0x80000000, 0x80000000 } +#define _VEC_LSBMASK (__vector unsigned int) { 0xfffffffe, 0xfffffffe, 0xfffffffe, 0xfffffffe } +#define _VEC_CLEAR_WMASK (__vector unsigned int) {0xffffffff, 0xffffffff, 0xffffffff, 0} +#define _VEC_COMPONENT_MASK_0 (__vector unsigned int) {0xffffffff, 0, 0, 0} +#define _VEC_COMPONENT_MASK_1 (__vector unsigned int) {0, 0xffffffff, 0, 0} +#define _VEC_COMPONENT_MASK_2 (__vector unsigned int) {0, 0, 0xffffffff, 0} +#define _VEC_COMPONENT_MASK_3 (__vector unsigned int) {0, 0, 0, 0xffffffff} + +#define _VEC_SWIZZLE_WZYX (__vector unsigned char) { 0x0c,0x0d,0x0e,0x0f, 0x08,0x09,0x0a,0x0b, 0x04,0x05,0x06,0x07, 0x00,0x01,0x02,0x03 } +#define _VEC_SWIZZLE_ZWXY (__vector unsigned char) { 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f, 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07 } +#define _VEC_SWIZZLE_YXWZ (__vector unsigned char) { 0x04,0x05,0x06,0x07, 0x00,0x01,0x02,0x03, 0x0c,0x0d,0x0e,0x0f, 0x08,0x09,0x0a,0x0b } + +#define _VEC_ZERO (__vector unsigned int) {0,0,0,0} + +#define _VEC_FLTMAX (__vector float) {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX} +#define _VEC_FLTMIN (__vector float) {FLT_MIN,FLT_MIN,FLT_MIN,FLT_MIN} + +#define _VEC_ORIGIN (__vector unsigned int) { 0x00000000, 0x00000000, 0x00000000, 0xffffffff } + +#endif + +#if USE_STDC_FOR_SIMD + +FORCEINLINE float SubFloat(const fltx4& a, int idx) +{ + return a.m128_f32[idx]; +} + +FORCEINLINE float& SubFloat(fltx4& a, int idx) +{ + return a.m128_f32[idx]; +} + +FORCEINLINE uint32 SubInt(const fltx4& a, int idx) +{ + return a.m128_u32[idx]; +} + +FORCEINLINE uint32& SubInt(fltx4& a, int idx) +{ + return a.m128_u32[idx]; +} + +FORCEINLINE fltx4 LoadZeroSIMD(void) +{ + return Four_Zeros; +} + +FORCEINLINE fltx4 LoadOneSIMD(void) +{ + return Four_Ones; +} + +FORCEINLINE fltx4 SplatXSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = SubFloat(a, 0); + SubFloat(retVal, 1) = SubFloat(a, 0); + SubFloat(retVal, 2) = SubFloat(a, 0); + SubFloat(retVal, 3) = SubFloat(a, 0); + return retVal; +} + +FORCEINLINE fltx4 SplatYSIMD(fltx4 a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = SubFloat(a, 1); + SubFloat(retVal, 1) = SubFloat(a, 1); + SubFloat(retVal, 2) = SubFloat(a, 1); + SubFloat(retVal, 3) = SubFloat(a, 1); + return retVal; +} + +FORCEINLINE fltx4 SplatZSIMD(fltx4 a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = SubFloat(a, 2); + SubFloat(retVal, 1) = SubFloat(a, 2); + SubFloat(retVal, 2) = SubFloat(a, 2); + SubFloat(retVal, 3) = SubFloat(a, 2); + return retVal; +} + +FORCEINLINE fltx4 SplatWSIMD(fltx4 a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = SubFloat(a, 3); + SubFloat(retVal, 1) = SubFloat(a, 3); + SubFloat(retVal, 2) = SubFloat(a, 3); + SubFloat(retVal, 3) = SubFloat(a, 3); + return retVal; +} + +FORCEINLINE fltx4 SetXSIMD(const fltx4& a, const fltx4& x) +{ + fltx4 result = a; + SubFloat(result, 0) = SubFloat(x, 0); + return result; +} + +FORCEINLINE fltx4 SetYSIMD(const fltx4& a, const fltx4& y) +{ + fltx4 result = a; + SubFloat(result, 1) = SubFloat(y, 1); + return result; +} + +FORCEINLINE fltx4 SetZSIMD(const fltx4& a, const fltx4& z) +{ + fltx4 result = a; + SubFloat(result, 2) = SubFloat(z, 2); + return result; +} + +FORCEINLINE fltx4 SetWSIMD(const fltx4& a, const fltx4& w) +{ + fltx4 result = a; + SubFloat(result, 3) = SubFloat(w, 3); + return result; +} + +FORCEINLINE fltx4 SetComponentSIMD(const fltx4& a, int nComponent, float flValue) +{ + fltx4 result = a; + SubFloat(result, nComponent) = flValue; + return result; +} + + +FORCEINLINE fltx4 RotateLeft(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = SubFloat(a, 1); + SubFloat(retVal, 1) = SubFloat(a, 2); + SubFloat(retVal, 2) = SubFloat(a, 3); + SubFloat(retVal, 3) = SubFloat(a, 0); + return retVal; +} + +FORCEINLINE fltx4 RotateLeft2(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = SubFloat(a, 2); + SubFloat(retVal, 1) = SubFloat(a, 3); + SubFloat(retVal, 2) = SubFloat(a, 0); + SubFloat(retVal, 3) = SubFloat(a, 1); + return retVal; +} + +#define BINOP(op) \ + fltx4 retVal; \ + SubFloat( retVal, 0 ) = ( SubFloat( a, 0 ) op SubFloat( b, 0 ) ); \ + SubFloat( retVal, 1 ) = ( SubFloat( a, 1 ) op SubFloat( b, 1 ) ); \ + SubFloat( retVal, 2 ) = ( SubFloat( a, 2 ) op SubFloat( b, 2 ) ); \ + SubFloat( retVal, 3 ) = ( SubFloat( a, 3 ) op SubFloat( b, 3 ) ); \ + return retVal; + +#define IBINOP(op) \ + fltx4 retVal; \ + SubInt( retVal, 0 ) = ( SubInt( a, 0 ) op SubInt ( b, 0 ) ); \ + SubInt( retVal, 1 ) = ( SubInt( a, 1 ) op SubInt ( b, 1 ) ); \ + SubInt( retVal, 2 ) = ( SubInt( a, 2 ) op SubInt ( b, 2 ) ); \ + SubInt( retVal, 3 ) = ( SubInt( a, 3 ) op SubInt ( b, 3 ) ); \ + return retVal; + +FORCEINLINE fltx4 AddSIMD(const fltx4& a, const fltx4& b) +{ + BINOP(+); +} + +FORCEINLINE fltx4 SubSIMD(const fltx4& a, const fltx4& b) +{ + BINOP(-); +}; + +FORCEINLINE fltx4 MulSIMD(const fltx4& a, const fltx4& b) +{ + BINOP(*); +} + +FORCEINLINE fltx4 DivSIMD(const fltx4& a, const fltx4& b) +{ + BINOP(/ ); +} + +FORCEINLINE fltx4 DivEstSIMD(const fltx4& a, const fltx4& b) +{ + BINOP(/ ); +} + +FORCEINLINE fltx4 MaddSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return AddSIMD(MulSIMD(a, b), c); +} + +FORCEINLINE fltx4 MsubSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return SubSIMD(c, MulSIMD(a, b)); +}; + + +FORCEINLINE fltx4 SinSIMD(const fltx4& radians) +{ + fltx4 result; + SubFloat(result, 0) = sin(SubFloat(radians, 0)); + SubFloat(result, 1) = sin(SubFloat(radians, 1)); + SubFloat(result, 2) = sin(SubFloat(radians, 2)); + SubFloat(result, 3) = sin(SubFloat(radians, 3)); + return result; +} + +FORCEINLINE void SinCos3SIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + SinCos(SubFloat(radians, 0), &SubFloat(sine, 0), &SubFloat(cosine, 0)); + SinCos(SubFloat(radians, 1), &SubFloat(sine, 1), &SubFloat(cosine, 1)); + SinCos(SubFloat(radians, 2), &SubFloat(sine, 2), &SubFloat(cosine, 2)); +} + +FORCEINLINE void SinCosSIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + SinCos(SubFloat(radians, 0), &SubFloat(sine, 0), &SubFloat(cosine, 0)); + SinCos(SubFloat(radians, 1), &SubFloat(sine, 1), &SubFloat(cosine, 1)); + SinCos(SubFloat(radians, 2), &SubFloat(sine, 2), &SubFloat(cosine, 2)); + SinCos(SubFloat(radians, 3), &SubFloat(sine, 3), &SubFloat(cosine, 3)); +} + +FORCEINLINE fltx4 ArcSinSIMD(const fltx4& sine) +{ + fltx4 result; + SubFloat(result, 0) = asin(SubFloat(sine, 0)); + SubFloat(result, 1) = asin(SubFloat(sine, 1)); + SubFloat(result, 2) = asin(SubFloat(sine, 2)); + SubFloat(result, 3) = asin(SubFloat(sine, 3)); + return result; +} + +FORCEINLINE fltx4 ArcCosSIMD(const fltx4& cs) +{ + fltx4 result; + SubFloat(result, 0) = acos(SubFloat(cs, 0)); + SubFloat(result, 1) = acos(SubFloat(cs, 1)); + SubFloat(result, 2) = acos(SubFloat(cs, 2)); + SubFloat(result, 3) = acos(SubFloat(cs, 3)); + return result; +} + +FORCEINLINE fltx4 ArcTan2SIMD(const fltx4& a, const fltx4& b) +{ + fltx4 result; + SubFloat(result, 0) = atan2(SubFloat(a, 0), SubFloat(b, 0)); + SubFloat(result, 1) = atan2(SubFloat(a, 1), SubFloat(b, 1)); + SubFloat(result, 2) = atan2(SubFloat(a, 2), SubFloat(b, 2)); + SubFloat(result, 3) = atan2(SubFloat(a, 3), SubFloat(b, 3)); + return result; +} + +FORCEINLINE fltx4 MaxSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubFloat(retVal, 0) = max(SubFloat(a, 0), SubFloat(b, 0)); + SubFloat(retVal, 1) = max(SubFloat(a, 1), SubFloat(b, 1)); + SubFloat(retVal, 2) = max(SubFloat(a, 2), SubFloat(b, 2)); + SubFloat(retVal, 3) = max(SubFloat(a, 3), SubFloat(b, 3)); + return retVal; +} + +FORCEINLINE fltx4 MinSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubFloat(retVal, 0) = min(SubFloat(a, 0), SubFloat(b, 0)); + SubFloat(retVal, 1) = min(SubFloat(a, 1), SubFloat(b, 1)); + SubFloat(retVal, 2) = min(SubFloat(a, 2), SubFloat(b, 2)); + SubFloat(retVal, 3) = min(SubFloat(a, 3), SubFloat(b, 3)); + return retVal; +} + +FORCEINLINE fltx4 AndSIMD(const fltx4& a, const fltx4& b) +{ + IBINOP(&); +} + +FORCEINLINE fltx4 AndNotSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubInt(retVal, 0) = ~SubInt(a, 0) & SubInt(b, 0); + SubInt(retVal, 1) = ~SubInt(a, 1) & SubInt(b, 1); + SubInt(retVal, 2) = ~SubInt(a, 2) & SubInt(b, 2); + SubInt(retVal, 3) = ~SubInt(a, 3) & SubInt(b, 3); + return retVal; +} + +FORCEINLINE fltx4 XorSIMD(const fltx4& a, const fltx4& b) +{ + IBINOP(^); +} + +FORCEINLINE fltx4 OrSIMD(const fltx4& a, const fltx4& b) +{ + IBINOP(| ); +} + +FORCEINLINE fltx4 NegSIMD(const fltx4& a) +{ + fltx4 retval; + SubFloat(retval, 0) = -SubFloat(a, 0); + SubFloat(retval, 1) = -SubFloat(a, 1); + SubFloat(retval, 2) = -SubFloat(a, 2); + SubFloat(retval, 3) = -SubFloat(a, 3); + + return retval; +} + +FORCEINLINE bool IsAllZeros(const fltx4& a) +{ + return (SubFloat(a, 0) == 0.0) && + (SubFloat(a, 1) == 0.0) && + (SubFloat(a, 2) == 0.0) && + (SubFloat(a, 3) == 0.0); +} + + +FORCEINLINE bool IsAllGreaterThan(const fltx4& a, const fltx4& b) +{ + return SubFloat(a, 0) > SubFloat(b, 0) && + SubFloat(a, 1) > SubFloat(b, 1) && + SubFloat(a, 2) > SubFloat(b, 2) && + SubFloat(a, 3) > SubFloat(b, 3); +} + +FORCEINLINE bool IsAllGreaterThanOrEq(const fltx4& a, const fltx4& b) +{ + return SubFloat(a, 0) >= SubFloat(b, 0) && + SubFloat(a, 1) >= SubFloat(b, 1) && + SubFloat(a, 2) >= SubFloat(b, 2) && + SubFloat(a, 3) >= SubFloat(b, 3); +} + +FORCEINLINE bool IsAllEqual(const fltx4& a, const fltx4& b) +{ + return SubFloat(a, 0) == SubFloat(b, 0) && + SubFloat(a, 1) == SubFloat(b, 1) && + SubFloat(a, 2) == SubFloat(b, 2) && + SubFloat(a, 3) == SubFloat(b, 3); +} + +FORCEINLINE bool IsAnyEqual(const fltx4& a, const fltx4& b) +{ + return SubFloat(a, 0) == SubFloat(b, 0) || + SubFloat(a, 1) == SubFloat(b, 1) || + SubFloat(a, 2) == SubFloat(b, 2) || + SubFloat(a, 3) == SubFloat(b, 3); +} + +FORCEINLINE int TestSignSIMD(const fltx4& a) +{ + int nRet = 0; + + nRet |= (SubInt(a, 0) & 0x80000000) >> 31; + nRet |= (SubInt(a, 1) & 0x80000000) >> 30; + nRet |= (SubInt(a, 2) & 0x80000000) >> 29; + nRet |= (SubInt(a, 3) & 0x80000000) >> 28; + + return nRet; +} + +FORCEINLINE bool IsAnyNegative(const fltx4& a) +{ + return (0 != TestSignSIMD(a)); +} + +FORCEINLINE bool IsAnyTrue(const fltx4& a) +{ + return (0 != TestSignSIMD(a)); +} + +FORCEINLINE fltx4 CmpEqSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubInt(retVal, 0) = (SubFloat(a, 0) == SubFloat(b, 0)) ? ~0 : 0; + SubInt(retVal, 1) = (SubFloat(a, 1) == SubFloat(b, 1)) ? ~0 : 0; + SubInt(retVal, 2) = (SubFloat(a, 2) == SubFloat(b, 2)) ? ~0 : 0; + SubInt(retVal, 3) = (SubFloat(a, 3) == SubFloat(b, 3)) ? ~0 : 0; + return retVal; +} + +FORCEINLINE fltx4 CmpGtSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubInt(retVal, 0) = (SubFloat(a, 0) > SubFloat(b, 0)) ? ~0 : 0; + SubInt(retVal, 1) = (SubFloat(a, 1) > SubFloat(b, 1)) ? ~0 : 0; + SubInt(retVal, 2) = (SubFloat(a, 2) > SubFloat(b, 2)) ? ~0 : 0; + SubInt(retVal, 3) = (SubFloat(a, 3) > SubFloat(b, 3)) ? ~0 : 0; + return retVal; +} + +FORCEINLINE fltx4 CmpGeSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubInt(retVal, 0) = (SubFloat(a, 0) >= SubFloat(b, 0)) ? ~0 : 0; + SubInt(retVal, 1) = (SubFloat(a, 1) >= SubFloat(b, 1)) ? ~0 : 0; + SubInt(retVal, 2) = (SubFloat(a, 2) >= SubFloat(b, 2)) ? ~0 : 0; + SubInt(retVal, 3) = (SubFloat(a, 3) >= SubFloat(b, 3)) ? ~0 : 0; + return retVal; +} + +FORCEINLINE fltx4 CmpLtSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubInt(retVal, 0) = (SubFloat(a, 0) < SubFloat(b, 0)) ? ~0 : 0; + SubInt(retVal, 1) = (SubFloat(a, 1) < SubFloat(b, 1)) ? ~0 : 0; + SubInt(retVal, 2) = (SubFloat(a, 2) < SubFloat(b, 2)) ? ~0 : 0; + SubInt(retVal, 3) = (SubFloat(a, 3) < SubFloat(b, 3)) ? ~0 : 0; + return retVal; +} + +FORCEINLINE fltx4 CmpLeSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubInt(retVal, 0) = (SubFloat(a, 0) <= SubFloat(b, 0)) ? ~0 : 0; + SubInt(retVal, 1) = (SubFloat(a, 1) <= SubFloat(b, 1)) ? ~0 : 0; + SubInt(retVal, 2) = (SubFloat(a, 2) <= SubFloat(b, 2)) ? ~0 : 0; + SubInt(retVal, 3) = (SubFloat(a, 3) <= SubFloat(b, 3)) ? ~0 : 0; + return retVal; +} + +FORCEINLINE fltx4 CmpInBoundsSIMD(const fltx4& a, const fltx4& b) +{ + fltx4 retVal; + SubInt(retVal, 0) = (SubFloat(a, 0) <= SubFloat(b, 0) && SubFloat(a, 0) >= -SubFloat(b, 0)) ? ~0 : 0; + SubInt(retVal, 1) = (SubFloat(a, 1) <= SubFloat(b, 1) && SubFloat(a, 1) >= -SubFloat(b, 1)) ? ~0 : 0; + SubInt(retVal, 2) = (SubFloat(a, 2) <= SubFloat(b, 2) && SubFloat(a, 2) >= -SubFloat(b, 2)) ? ~0 : 0; + SubInt(retVal, 3) = (SubFloat(a, 3) <= SubFloat(b, 3) && SubFloat(a, 3) >= -SubFloat(b, 3)) ? ~0 : 0; + return retVal; +} + + +FORCEINLINE fltx4 MaskedAssign(const fltx4& ReplacementMask, const fltx4& NewValue, const fltx4& OldValue) +{ + return OrSIMD( + AndSIMD(ReplacementMask, NewValue), + AndNotSIMD(ReplacementMask, OldValue)); +} + +FORCEINLINE fltx4 ReplicateX4(float flValue) +{ + fltx4 retVal; + SubFloat(retVal, 0) = flValue; + SubFloat(retVal, 1) = flValue; + SubFloat(retVal, 2) = flValue; + SubFloat(retVal, 3) = flValue; + return retVal; +} + +FORCEINLINE fltx4 ReplicateIX4(int nValue) +{ + fltx4 retVal; + SubInt(retVal, 0) = nValue; + SubInt(retVal, 1) = nValue; + SubInt(retVal, 2) = nValue; + SubInt(retVal, 3) = nValue; + return retVal; + +} + +FORCEINLINE fltx4 CeilSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = ceil(SubFloat(a, 0)); + SubFloat(retVal, 1) = ceil(SubFloat(a, 1)); + SubFloat(retVal, 2) = ceil(SubFloat(a, 2)); + SubFloat(retVal, 3) = ceil(SubFloat(a, 3)); + return retVal; + +} + +FORCEINLINE fltx4 FloorSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = floor(SubFloat(a, 0)); + SubFloat(retVal, 1) = floor(SubFloat(a, 1)); + SubFloat(retVal, 2) = floor(SubFloat(a, 2)); + SubFloat(retVal, 3) = floor(SubFloat(a, 3)); + return retVal; + +} + +FORCEINLINE fltx4 SqrtEstSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = sqrt(SubFloat(a, 0)); + SubFloat(retVal, 1) = sqrt(SubFloat(a, 1)); + SubFloat(retVal, 2) = sqrt(SubFloat(a, 2)); + SubFloat(retVal, 3) = sqrt(SubFloat(a, 3)); + return retVal; +} + +FORCEINLINE fltx4 SqrtSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = sqrt(SubFloat(a, 0)); + SubFloat(retVal, 1) = sqrt(SubFloat(a, 1)); + SubFloat(retVal, 2) = sqrt(SubFloat(a, 2)); + SubFloat(retVal, 3) = sqrt(SubFloat(a, 3)); + return retVal; +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / sqrt(SubFloat(a, 0)); + SubFloat(retVal, 1) = 1.0 / sqrt(SubFloat(a, 1)); + SubFloat(retVal, 2) = 1.0 / sqrt(SubFloat(a, 2)); + SubFloat(retVal, 3) = 1.0 / sqrt(SubFloat(a, 3)); + return retVal; +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSaturateSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / sqrt(SubFloat(a, 0) != 0.0f ? SubFloat(a, 0) : FLT_EPSILON); + SubFloat(retVal, 1) = 1.0 / sqrt(SubFloat(a, 1) != 0.0f ? SubFloat(a, 1) : FLT_EPSILON); + SubFloat(retVal, 2) = 1.0 / sqrt(SubFloat(a, 2) != 0.0f ? SubFloat(a, 2) : FLT_EPSILON); + SubFloat(retVal, 3) = 1.0 / sqrt(SubFloat(a, 3) != 0.0f ? SubFloat(a, 3) : FLT_EPSILON); + return retVal; +} + +FORCEINLINE fltx4 ReciprocalSqrtSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / sqrt(SubFloat(a, 0)); + SubFloat(retVal, 1) = 1.0 / sqrt(SubFloat(a, 1)); + SubFloat(retVal, 2) = 1.0 / sqrt(SubFloat(a, 2)); + SubFloat(retVal, 3) = 1.0 / sqrt(SubFloat(a, 3)); + return retVal; +} + +FORCEINLINE fltx4 ReciprocalEstSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / SubFloat(a, 0); + SubFloat(retVal, 1) = 1.0 / SubFloat(a, 1); + SubFloat(retVal, 2) = 1.0 / SubFloat(a, 2); + SubFloat(retVal, 3) = 1.0 / SubFloat(a, 3); + return retVal; +} + +FORCEINLINE fltx4 ReciprocalSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / SubFloat(a, 0); + SubFloat(retVal, 1) = 1.0 / SubFloat(a, 1); + SubFloat(retVal, 2) = 1.0 / SubFloat(a, 2); + SubFloat(retVal, 3) = 1.0 / SubFloat(a, 3); + return retVal; +} + +FORCEINLINE fltx4 ReciprocalEstSaturateSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / (SubFloat(a, 0) == 0.0f ? FLT_EPSILON : SubFloat(a, 0)); + SubFloat(retVal, 1) = 1.0 / (SubFloat(a, 1) == 0.0f ? FLT_EPSILON : SubFloat(a, 1)); + SubFloat(retVal, 2) = 1.0 / (SubFloat(a, 2) == 0.0f ? FLT_EPSILON : SubFloat(a, 2)); + SubFloat(retVal, 3) = 1.0 / (SubFloat(a, 3) == 0.0f ? FLT_EPSILON : SubFloat(a, 3)); + return retVal; +} + +FORCEINLINE fltx4 ReciprocalSaturateSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / (SubFloat(a, 0) == 0.0f ? FLT_EPSILON : SubFloat(a, 0)); + SubFloat(retVal, 1) = 1.0 / (SubFloat(a, 1) == 0.0f ? FLT_EPSILON : SubFloat(a, 1)); + SubFloat(retVal, 2) = 1.0 / (SubFloat(a, 2) == 0.0f ? FLT_EPSILON : SubFloat(a, 2)); + SubFloat(retVal, 3) = 1.0 / (SubFloat(a, 3) == 0.0f ? FLT_EPSILON : SubFloat(a, 3)); + return retVal; +} + +FORCEINLINE fltx4 ExpSIMD(const fltx4& toPower) +{ + fltx4 retVal; + SubFloat(retVal, 0) = powf(2, SubFloat(toPower, 0)); + SubFloat(retVal, 1) = powf(2, SubFloat(toPower, 1)); + SubFloat(retVal, 2) = powf(2, SubFloat(toPower, 2)); + SubFloat(retVal, 3) = powf(2, SubFloat(toPower, 3)); + + return retVal; +} + +FORCEINLINE fltx4 Dot3SIMD(const fltx4& a, const fltx4& b) +{ + float flDot = SubFloat(a, 0) * SubFloat(b, 0) + + SubFloat(a, 1) * SubFloat(b, 1) + + SubFloat(a, 2) * SubFloat(b, 2); + return ReplicateX4(flDot); +} + +FORCEINLINE fltx4 Dot4SIMD(const fltx4& a, const fltx4& b) +{ + float flDot = SubFloat(a, 0) * SubFloat(b, 0) + + SubFloat(a, 1) * SubFloat(b, 1) + + SubFloat(a, 2) * SubFloat(b, 2) + + SubFloat(a, 3) * SubFloat(b, 3); + return ReplicateX4(flDot); +} + +FORCEINLINE fltx4 ClampVectorSIMD(FLTX4 in, FLTX4 min, FLTX4 max) +{ + return MaxSIMD(min, MinSIMD(max, in)); +} + +FORCEINLINE fltx4 SetWToZeroSIMD(const fltx4& a) +{ + fltx4 retval; + retval = a; + SubFloat(retval, 0) = 0; + return retval; +} + +FORCEINLINE fltx4 LoadUnalignedSIMD(const void* pSIMD) +{ + return *(reinterpret_cast (pSIMD)); +} + +FORCEINLINE fltx4 LoadUnaligned3SIMD(const void* pSIMD) +{ + return *(reinterpret_cast (pSIMD)); +} + +FORCEINLINE fltx4 LoadUnalignedFloatSIMD(const float* pFlt) +{ + fltx4 retval; + SubFloat(retval, 0) = *pFlt; + return retval; +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const void* pSIMD) +{ + return *(reinterpret_cast (pSIMD)); +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const VectorAligned& pSIMD) +{ + fltx4 retval = LoadAlignedSIMD(pSIMD.Base()); + SubInt(retval, 3) = 0; + return retval; +} + + +FORCEINLINE fltx4 LoadGatherSIMD(const float& x, const float& y, const float& z, const float& w) +{ + fltx4 retval = { x, y, z, w }; + return retval; +} + +FORCEINLINE void StoreAlignedSIMD(float* pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD)) = a; +} + +FORCEINLINE void StoreUnalignedSIMD(float* pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD)) = a; +} + +FORCEINLINE void StoreUnalignedFloat(float* pSingleFloat, const fltx4& a) +{ + *pSingleFloat = SubFloat(a, 0); +} + +FORCEINLINE void StoreUnaligned3SIMD(float* pSIMD, const fltx4& a) +{ + *pSIMD = SubFloat(a, 0); + *(pSIMD + 1) = SubFloat(a, 1); + *(pSIMD + 2) = SubFloat(a, 2); +} + + +FORCEINLINE void StoreAligned3SIMD(VectorAligned* RESTRICT pSIMD, const fltx4& a) +{ + StoreAlignedSIMD(pSIMD->Base(), a); +} + +FORCEINLINE void StoreFourUnalignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + StoreUnaligned3SIMD(pDestination->Base(), a); + StoreUnaligned3SIMD((pDestination + 1)->Base(), b); + StoreUnaligned3SIMD((pDestination + 2)->Base(), c); + StoreUnaligned3SIMD((pDestination + 3)->Base(), d); +} + +FORCEINLINE void StoreFourAlignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + StoreUnaligned3SIMD(pDestination->Base(), a); + StoreUnaligned3SIMD((pDestination + 1)->Base(), b); + StoreUnaligned3SIMD((pDestination + 2)->Base(), c); + StoreUnaligned3SIMD((pDestination + 3)->Base(), d); +} + + +FORCEINLINE void TransposeSIMD(fltx4& x, fltx4& y, fltx4& z, fltx4& w) +{ +#define SWAP_FLOATS( _a_, _ia_, _b_, _ib_ ) { float tmp = SubFloat( _a_, _ia_ ); SubFloat( _a_, _ia_ ) = SubFloat( _b_, _ib_ ); SubFloat( _b_, _ib_ ) = tmp; } + SWAP_FLOATS(x, 1, y, 0); + SWAP_FLOATS(x, 2, z, 0); + SWAP_FLOATS(x, 3, w, 0); + SWAP_FLOATS(y, 2, z, 1); + SWAP_FLOATS(y, 3, w, 1); + SWAP_FLOATS(z, 3, w, 2); +} + +FORCEINLINE fltx4 FindLowestSIMD3(const fltx4& a) +{ + float lowest = min(min(SubFloat(a, 0), SubFloat(a, 1)), SubFloat(a, 2)); + return ReplicateX4(lowest); +} + +FORCEINLINE fltx4 FindHighestSIMD3(const fltx4& a) +{ + float highest = max(max(SubFloat(a, 0), SubFloat(a, 1)), SubFloat(a, 2)); + return ReplicateX4(highest); +} + +FORCEINLINE void ConvertStoreAsIntsSIMD(intx4* RESTRICT pDest, const fltx4& vSrc) +{ + (*pDest)[0] = SubFloat(vSrc, 0); + (*pDest)[1] = SubFloat(vSrc, 1); + (*pDest)[2] = SubFloat(vSrc, 2); + (*pDest)[3] = SubFloat(vSrc, 3); +} + +FORCEINLINE fltx4 IntSetImmediateSIMD(int nValue) +{ + fltx4 retval; + SubInt(retval, 0) = SubInt(retval, 1) = SubInt(retval, 2) = SubInt(retval, 3) = nValue; + return retval; +} + +FORCEINLINE i32x4 LoadAlignedIntSIMD(const void* RESTRICT pSIMD) +{ + return *(reinterpret_cast (pSIMD)); +} + +FORCEINLINE i32x4 LoadUnalignedIntSIMD(const void* RESTRICT pSIMD) +{ + return *(reinterpret_cast (pSIMD)); +} + +FORCEINLINE void StoreAlignedIntSIMD(int32* pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD)) = a; +} + +FORCEINLINE void StoreAlignedIntSIMD(intx4& pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD.Base())) = a; +} + +FORCEINLINE void StoreUnalignedIntSIMD(int32* pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD)) = a; +} + +FORCEINLINE fltx4 LoadAndConvertUint16SIMD(const uint16* pInts) +{ + fltx4 retval; + SubFloat(retval, 0) = pInts[0]; + SubFloat(retval, 1) = pInts[1]; + SubFloat(retval, 2) = pInts[2]; + SubFloat(retval, 3) = pInts[3]; +} + + +FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD(const u32x4& vSrcA) +{ + Assert(0); + fltx4 retval; + SubFloat(retval, 0) = ((float)SubInt(vSrcA, 0)); + SubFloat(retval, 1) = ((float)SubInt(vSrcA, 1)); + SubFloat(retval, 2) = ((float)SubInt(vSrcA, 2)); + SubFloat(retval, 3) = ((float)SubInt(vSrcA, 3)); + return retval; +} + + +#if 0 +FORCEINLINE fltx4 SignedIntConvertToFltSIMD(const i32x4& vSrcA) +{ + fltx4 retval; + SubFloat(retval, 0) = ((float)(reinterpret_cast(&vSrcA.m128_s32[0]))); + SubFloat(retval, 1) = ((float)(reinterpret_cast(&vSrcA.m128_s32[1]))); + SubFloat(retval, 2) = ((float)(reinterpret_cast(&vSrcA.m128_s32[2]))); + SubFloat(retval, 3) = ((float)(reinterpret_cast(&vSrcA.m128_s32[3]))); + return retval; +} + + +FORCEINLINE i32x4 IntShiftLeftWordSIMD(const i32x4& vSrcA, const i32x4& vSrcB) +{ + i32x4 retval; + SubInt(retval, 0) = SubInt(vSrcA, 0) << SubInt(vSrcB, 0); + SubInt(retval, 1) = SubInt(vSrcA, 1) << SubInt(vSrcB, 1); + SubInt(retval, 2) = SubInt(vSrcA, 2) << SubInt(vSrcB, 2); + SubInt(retval, 3) = SubInt(vSrcA, 3) << SubInt(vSrcB, 3); + + + return retval; +} + +#endif + +#elif ( defined( _PS3 ) ) +#define SN_IMPROVED_INTRINSICS ( (( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 1 ) && ( __GNUC_PATCHLEVEL__ == 1 )) ||\ + (defined(__SN_VER__) && (__SN_VER__ > 25002)) ) + +FORCEINLINE float FloatSIMD(fltx4& a, int idx) +{ +#if SN_IMPROVED_INTRINSICS + return vec_extract(a, idx); +#else + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxf); + return a_union.m128_f32[idx]; +#endif +} + +FORCEINLINE unsigned int UIntSIMD(u32x4& a, int idx) +{ +#if SN_IMPROVED_INTRINSICS + return vec_extract(a, idx); +#else + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxui); + return a_union.m128_u32[idx]; +#endif +} + +FORCEINLINE fltx4 AddSIMD(const fltx4& a, const fltx4& b) +{ + return vec_add(a, b); +} + +FORCEINLINE fltx4 SubSIMD(const fltx4& a, const fltx4& b) +{ + return vec_sub(a, b); +} + +FORCEINLINE fltx4 MulSIMD(const fltx4& a, const fltx4& b) +{ + return vec_madd(a, b, _VEC_ZEROF); +} + +FORCEINLINE fltx4 MaddSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return vec_madd(a, b, c); +} + +FORCEINLINE fltx4 MsubSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return vec_nmsub(a, b, c); +}; + +FORCEINLINE fltx4 Dot3SIMD(const fltx4& a, const fltx4& b) +{ + fltx4 result; + + result = vec_madd(a, b, _VEC_ZEROF); + result = vec_madd(vec_sld(a, a, 4), vec_sld(b, b, 4), result); + result = vec_madd(vec_sld(a, a, 8), vec_sld(b, b, 8), result); + + result = vec_splat(result, 0); + + return result; +} + +FORCEINLINE fltx4 Dot4SIMD(const fltx4& a, const fltx4& b) +{ + fltx4 result; + + result = vec_madd(a, b, _VEC_ZEROF); + result = vec_madd(vec_sld(a, a, 4), vec_sld(b, b, 4), result); + result = vec_add(vec_sld(result, result, 8), result); + + result = vec_splat(result, 0); + + return result; +} + +FORCEINLINE fltx4 SinSIMD(const fltx4& radians) +{ + return sinf4(radians); +} + +FORCEINLINE void SinCos3SIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + sincosf4(radians, &sine, &cosine); +} + +FORCEINLINE void SinCosSIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + sincosf4(radians, &sine, &cosine); +} + +FORCEINLINE fltx4 ArcCosSIMD(const fltx4& cs) +{ + return acosf4(cs); +} + +FORCEINLINE fltx4 ArcTan2SIMD(const fltx4& a, const fltx4& b) +{ + return atan2f4(a, b); +} + +FORCEINLINE fltx4 ArcSinSIMD(const fltx4& sine) +{ + return asinf4(sine); +} + +FORCEINLINE fltx4 MaxSIMD(const fltx4& a, const fltx4& b) +{ + return vec_max(a, b); +} +FORCEINLINE fltx4 MinSIMD(const fltx4& a, const fltx4& b) +{ + return vec_min(a, b); +} + +FORCEINLINE fltx4 AndSIMD(const fltx4& a, const fltx4& b) +{ + return vec_and(a, b); +} +FORCEINLINE fltx4 AndSIMD(const bi32x4& a, const fltx4& b) +{ + return vec_and((fltx4)a, b); +} +FORCEINLINE fltx4 AndSIMD(const fltx4& a, const bi32x4& b) +{ + return vec_and(a, (fltx4)b); +} +FORCEINLINE bi32x4 AndSIMD(const bi32x4& a, const bi32x4& b) +{ + return vec_and(a, b); +} + +#if 0 +FORCEINLINE fltx4 AndNotSIMD(const fltx4& a, const fltx4& b) +{ + return vec_andc(b, a); +} +FORCEINLINE fltx4 AndNotSIMD(const bi32x4& a, const fltx4& b) +{ + return vec_andc(b, (fltx4)a); +} +FORCEINLINE fltx4 AndNotSIMD(const fltx4& a, const bi32x4& b) +{ + return (fltx4)vec_andc(b, (bi32x4)a); +} +FORCEINLINE bi32x4 AndNotSIMD(const bi32x4& a, const bi32x4& b) +{ + return vec_andc(b, a); +} +#else +template< typename T, typename U > +FORCEINLINE T AndNotSIMD(const T& a, const U& b) +{ + return vec_andc(b, (T)a); +} + +FORCEINLINE fltx4 AndNotSIMD(const bi32x4& a, const fltx4& b) +{ + return vec_andc(b, (fltx4)a); +} +#endif + +FORCEINLINE fltx4 XorSIMD(const fltx4& a, const fltx4& b) +{ + return vec_xor(a, b); +} +FORCEINLINE fltx4 XorSIMD(const bi32x4& a, const fltx4& b) +{ + return vec_xor((fltx4)a, b); +} +FORCEINLINE fltx4 XorSIMD(const fltx4& a, const bi32x4& b) +{ + return vec_xor(a, (fltx4)b); +} +FORCEINLINE bi32x4 XorSIMD(const bi32x4& a, const bi32x4& b) +{ + return vec_xor(a, b); +} + +FORCEINLINE fltx4 OrSIMD(const fltx4& a, const fltx4& b) +{ + return vec_or(a, b); +} +FORCEINLINE fltx4 OrSIMD(const bi32x4& a, const fltx4& b) +{ + return vec_or((fltx4)a, b); +} +FORCEINLINE fltx4 OrSIMD(const fltx4& a, const bi32x4& b) +{ + return vec_or(a, (fltx4)b); +} +FORCEINLINE i32x4 OrSIMD(const i32x4& a, const i32x4& b) +{ + return vec_or(a, b); +} +FORCEINLINE u32x4 OrSIMD(const u32x4& a, const u32x4& b) +{ + return vec_or(a, b); +} + +#if !defined(__SPU__) +FORCEINLINE bi32x4 OrSIMD(const bi32x4& a, const bi32x4& b) +{ + return vec_or(a, b); +} +#endif + +FORCEINLINE fltx4 NegSIMD(const fltx4& a) +{ + return(SubSIMD(_VEC_ZEROF, a)); + +} + +FORCEINLINE bool IsAnyZeros(const fltx4& a) +{ + return vec_any_eq(a, _VEC_ZEROF); +} + +FORCEINLINE bool IsAnyZeros(const bi32x4& a) +{ + return vec_any_eq((u32x4)a, _VEC_ZERO); +} + +FORCEINLINE bool IsAllZeros(const bi32x4& a) +{ + return vec_all_eq((u32x4)a, _VEC_ZERO); +} + +FORCEINLINE bool IsAnyXYZZero(const fltx4& a) +{ +#if SN_IMPROVED_INTRINSICS + + fltx4 b = vec_insert(1.0f, a, 3); + + return vec_any_eq(b, _VEC_ZEROF); +#else + fltx4 b = vec_perm(a, _VEC_ONEF, _VEC_PERMUTE_XYZ0W1); + return vec_any_eq(b, _VEC_ZEROF); +#endif +} + +FORCEINLINE bool IsAllGreaterThan(const fltx4& a, const fltx4& b) +{ + return vec_all_gt(a, b); +} + +FORCEINLINE bool IsAllGreaterThanOrEq(const fltx4& a, const fltx4& b) +{ + return vec_all_ge(a, b); +} + +FORCEINLINE bool IsAllEqual(const fltx4& a, const fltx4& b) +{ + return vec_all_eq(a, b); +} + + +FORCEINLINE int TestSignSIMD(const fltx4& a) +{ + int nRet = 0; + + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxf); + + nRet |= (a_union.m128_u32[0] & 0x80000000) >> 31; + nRet |= (a_union.m128_u32[1] & 0x80000000) >> 30; + nRet |= (a_union.m128_u32[2] & 0x80000000) >> 29; + nRet |= (a_union.m128_u32[3] & 0x80000000) >> 28; + + return nRet; +} +FORCEINLINE int TestSignSIMD(const bi32x4& a) +{ + int nRet = 0; + + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxbi); + + nRet |= (a_union.m128_u32[0] & 0x80000000) >> 31; + nRet |= (a_union.m128_u32[1] & 0x80000000) >> 30; + nRet |= (a_union.m128_u32[2] & 0x80000000) >> 29; + nRet |= (a_union.m128_u32[3] & 0x80000000) >> 28; + + return nRet; +} + +FORCEINLINE bool IsAnyNegative(const bi32x4& a) +{ + return (0 != TestSignSIMD(a)); +} + +FORCEINLINE fltx4 SetWToZeroSIMD(const fltx4& a) +{ + return (fltx4)vec_and((u32x4)a, _VEC_CLEAR_WMASK); +} +FORCEINLINE bi32x4 SetWToZeroSIMD(const bi32x4& a) +{ + return (bi32x4)vec_and((u32x4)a, _VEC_CLEAR_WMASK); +} + +FORCEINLINE bool IsAnyNegative(const fltx4& a) +{ + return vec_any_lt(a, _VEC_ZEROF); +} + +FORCEINLINE bool IsAnyTrue(const fltx4& a) +{ + return vec_any_ne(a, _VEC_ZEROF); +} + +#ifdef DIFFERENT_NATIVE_VECTOR_TYPES + +FORCEINLINE bool IsAnyTrue(const bi32x4& a) +{ + return vec_any_ne((vector unsigned int) a, _VEC_0L); +} + +#endif + +FORCEINLINE bi32x4 CmpEqSIMD(const fltx4& a, const fltx4& b) +{ + return (bi32x4)vec_cmpeq(a, b); +} +FORCEINLINE bi32x4 CmpEqSIMD(const i32x4& a, const i32x4& b) +{ + return (bi32x4)vec_cmpeq(a, b); +} +FORCEINLINE bi32x4 CmpEqSIMD(const u32x4& a, const u32x4& b) +{ + return (bi32x4)vec_cmpeq(a, b); +} + +FORCEINLINE bi32x4 CmpGtSIMD(const fltx4& a, const fltx4& b) +{ + return (bi32x4)vec_cmpgt(a, b); +} +FORCEINLINE bi32x4 CmpGtSIMD(const i32x4& a, const i32x4& b) +{ + return (bi32x4)vec_cmpgt(a, b); +} +FORCEINLINE bi32x4 CmpGtSIMD(const u32x4& a, const u32x4& b) +{ + return (bi32x4)vec_cmpgt(a, b); +} + +FORCEINLINE bi32x4 CmpGeSIMD(const fltx4& a, const fltx4& b) +{ + return (bi32x4)vec_cmpge(a, b); +} + + +FORCEINLINE bi32x4 CmpLtSIMD(const fltx4& a, const fltx4& b) +{ + return (bi32x4)vec_cmplt(a, b); +} + +FORCEINLINE bi32x4 CmpLeSIMD(const fltx4& a, const fltx4& b) +{ + return (bi32x4)vec_cmple(a, b); +} + + + +FORCEINLINE bi32x4 CmpInBoundsSIMD(const fltx4& a, const fltx4& b) +{ + i32x4 control; + control = vec_cmpb(a, b); + return (bi32x4)vec_cmpeq((u32x4)control, _VEC_ZERO); +} + +FORCEINLINE int CmpAnyLeSIMD(const fltx4& a, const fltx4& b) +{ + return vec_any_le(a, b); +} + +FORCEINLINE int CmpAnyGeSIMD(const fltx4& a, const fltx4& b) +{ + return vec_any_ge(a, b); +} + +FORCEINLINE int CmpAnyLtSIMD(const fltx4& a, const fltx4& b) +{ + return vec_any_lt(a, b); +} +FORCEINLINE int CmpAnyLtSIMD(const bi32x4& a, const i32x4& b) +{ + return vec_any_lt((i32x4)a, b); +} + +FORCEINLINE int CmpAnyGtSIMD(const fltx4& a, const fltx4& b) +{ + return vec_any_gt(a, b); +} + +FORCEINLINE int CmpAnyNeSIMD(const fltx4& a, const fltx4& b) +{ + return vec_any_ne(a, b); +} +FORCEINLINE int CmpAnyNeSIMD(const bi32x4& a, const bi32x4& b) +{ + return vec_any_ne(a, b); +} +FORCEINLINE int CmpAnyNeSIMD(const bi32x4& a, const i32x4& b) +{ + return vec_any_ne(a, (bi32x4)b); +} + +FORCEINLINE int CmpAllLeSIMD(const fltx4& a, const fltx4& b) +{ + return vec_all_le(a, b); +} + +FORCEINLINE fltx4 MaskedAssign(const bi32x4& ReplacementMask, const fltx4& NewValue, const fltx4& OldValue) +{ + return vec_sel(OldValue, NewValue, ReplacementMask); +} + +FORCEINLINE fltx4 MaskedAssign(const fltx4& ReplacementMask, const fltx4& NewValue, const fltx4& OldValue) +{ + return vec_sel(OldValue, NewValue, (const bi32x4)ReplacementMask); +} + +FORCEINLINE vector signed short MaskedAssign(const vector unsigned short& ReplacementMask, const vector signed short& NewValue, const vector signed short& OldValue) +{ + return vec_sel(OldValue, NewValue, ReplacementMask); +} + +FORCEINLINE fltx4 ReplicateX4(float flValue) +{ +#if SN_IMPROVED_INTRINSICS + return vec_splats(flValue); +#else + float* pValue = &flValue; + Assert(pValue); + Assert(((unsigned int)pValue & 3) == 0); + + fltx4 result; + + result = vec_ld(0, pValue); + result = vec_splat(vec_perm(result, result, vec_lvsl(0, pValue)), 0); + + return result; +#endif +} + +FORCEINLINE fltx4 ReplicateX4(const float* pValue) +{ +#if SN_IMPROVED_INTRINSICS + return vec_splats(*pValue); +#else + Assert(pValue); + fltx4 result; + + result = vec_ld(0, pValue); + result = vec_splat(vec_perm(result, result, vec_lvsl(0, pValue)), 0); + + return result; +#endif +} + +FORCEINLINE i32x4 ReplicateIX4(int nValue) +{ +#if SN_IMPROVED_INTRINSICS + return vec_splats(nValue); +#else + int* pValue = &nValue; + Assert(pValue); + Assert(((unsigned int)pValue & 3) == 0); + i32x4 result; + + result = vec_ld(0, pValue); + result = vec_splat(vec_perm(result, result, vec_lvsl(0, pValue)), 0); + + return result; +#endif +} + +FORCEINLINE fltx4 SqrtSIMD(const fltx4& a) +{ + return sqrtf4(a); +} + +FORCEINLINE fltx4 SqrtEstSIMD(const fltx4& a) +{ +#if defined( _PS3 ) && !defined( SPU ) + fltx4 vRecipSquareRoot = vec_rsqrte(a); + i32x4 vOne = vec_splat_s32(1); + i32x4 vAllOnes = vec_splat_s32(-1); + i32x4 vShiftLeft24 = vec_splat_s32(-8); + fltx4 vZero = (fltx4)vec_splat_s32(0); + u32x4 vInputShifted = vec_sl((u32x4)a, (u32x4)vOne); + u32x4 vInfinityShifted = vec_sl((u32x4)vAllOnes, (u32x4)vShiftLeft24); + bi32x4 vEqualsZero = vec_vcmpeqfp(a, vZero); + bi32x4 vEqualsInfinity = vec_vcmpequw(vInputShifted, vInfinityShifted); + fltx4 vSquareRoot = vec_madd(a, vRecipSquareRoot, _VEC_ZEROF); + bi32x4 vResultMask = vec_vcmpequw((u32x4)vEqualsInfinity, (u32x4)vEqualsZero); + fltx4 vCorrectedSquareRoot = vec_sel(a, vSquareRoot, vResultMask); + + return vCorrectedSquareRoot; +#else + return SqrtSIMD(a); +#endif +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSIMD(const fltx4& a) +{ + return vec_rsqrte(a); +} + +FORCEINLINE fltx4 ReciprocalSqrtSIMD(const fltx4& a) +{ + fltx4 result; + vmathV4RsqrtPerElem((VmathVector4*)&result, (const VmathVector4*)&a); + + return result; +} + +FORCEINLINE fltx4 ReciprocalEstSIMD(const fltx4& a) +{ + return vec_re(a); +} + +FORCEINLINE fltx4 ReciprocalEstSaturateSIMD(const fltx4& a) +{ + bi32x4 zero_mask = CmpEqSIMD(a, Four_Zeros); + fltx4 ret = OrSIMD(a, AndSIMD(Four_Epsilons, zero_mask)); + ret = ReciprocalEstSIMD(ret); + return ret; +} + + +FORCEINLINE fltx4 ReciprocalSIMD(const fltx4& a) +{ + fltx4 result; + vmathV4RecipPerElem((VmathVector4*)&result, (const VmathVector4*)&a); + + return result; +} + +FORCEINLINE fltx4 DivSIMD(const fltx4& a, const fltx4& b) +{ + return MulSIMD(ReciprocalSIMD(b), a); +} + +FORCEINLINE fltx4 DivEstSIMD(const fltx4& a, const fltx4& b) +{ + return MulSIMD(ReciprocalEstSIMD(b), a); +} + +FORCEINLINE fltx4 ReciprocalSaturateSIMD(const fltx4& a) +{ + bi32x4 zero_mask = CmpEqSIMD(a, _VEC_ZEROF); + fltx4 a_safe = OrSIMD(a, AndSIMD(_VEC_EPSILONF, zero_mask)); + return ReciprocalSIMD(a_safe); + +} + + +FORCEINLINE fltx4 ExpSIMD(const fltx4& toPower) +{ + return exp2f4(toPower); +} + +FORCEINLINE fltx4 Exp2EstSIMD(const fltx4& f) +{ + return exp2f4fast(f); +} + + +FORCEINLINE fltx4 ClampVectorSIMD(FLTX4 in, FLTX4 min, FLTX4 max) +{ + fltx4 result = vec_max(min, in); + return vec_min(max, result); +} + + +FORCEINLINE fltx4 LoadUnalignedSIMD(const void* pSIMD) +{ +#if SN_IMPROVED_INTRINSICS + + fltx4 v0, v1; + + Assert(pSIMD); + + + v0 = (fltx4)vec_lvlx(0, (float*)pSIMD); + v1 = (fltx4)vec_lvrx(16, (float*)pSIMD); + return vec_or(v0, v1); + +#else + + fltx4 v0, v1; + vector unsigned char permMask; + + Assert(pSIMD); + + v0 = vec_ld(0, pSIMD); + permMask = vec_lvsl(0, pSIMD); + v1 = vec_ld(15, pSIMD); + + return vec_perm(v0, v1, permMask); + +#endif +} + +FORCEINLINE fltx4 LoadUnsignedByte4SIMD(unsigned char* pBytes) +{ + +#if SN_IMPROVED_INTRINSICS + + __vector unsigned char res_uc; + __vector unsigned short res_us; + + __vector unsigned char vZero8 = (__vector unsigned char)vec_splat_u8(0); + __vector unsigned short vZero16 = (__vector unsigned short)vec_splat_u16(0); + + res_uc = (__vector unsigned char)vec_lvlx(0, pBytes); + res_uc = vec_mergeh(vZero8, res_uc); + res_us = vec_mergeh(vZero16, (__vector unsigned short)res_uc); + return vec_ctf((__vector unsigned int)res_us, 0); + +#else + + vector unsigned char v0, v1; + vector bool char res_uc; + vector unsigned char permMask; + vector bool short res_us; + + vector bool char vZero8 = (vector bool char)vec_splat_u8(0); + vector bool short vZero16 = (vector bool short)vec_splat_u16(0); + + v0 = vec_ld(0, pBytes); + permMask = vec_lvsl(0, pBytes); + v1 = vec_ld(3, pBytes); + res_uc = (vector bool char)vec_perm(v0, v1, permMask); + res_uc = vec_mergeh(vZero8, res_uc); + res_us = vec_mergeh(vZero16, (vector bool short)res_uc); + return vec_ctf((vector unsigned int)res_us, 0); + +#endif + +} + +FORCEINLINE fltx4 LoadSignedByte4SIMD(signed char* pBytes) +{ + +#if SN_IMPROVED_INTRINSICS + + vector signed char res_uc; + vector signed short res_us; + vector signed int res_ui; + + res_uc = (vector signed char)vec_lvlx(0, pBytes); + res_us = vec_unpackh(res_uc); + res_ui = vec_unpackh(res_us); + return vec_ctf(res_ui, 0); + +#else + + vector signed char v0, v1, res_uc; + vector unsigned char permMask; + vector signed short res_us; + vector signed int res_ui; + + v0 = vec_ld(0, pBytes); + permMask = vec_lvsl(0, pBytes); + v1 = vec_ld(3, pBytes); + res_uc = vec_perm(v0, v1, permMask); + res_us = vec_unpackh(res_uc); + res_ui = vec_unpackh(res_us); + return vec_ctf(res_ui, 0); + +#endif + +} + + +FORCEINLINE fltx4 LoadUnaligned3SIMD(const void* pSIMD) +{ + Assert(pSIMD); + + fltx4 v0 = vec_ld(0, (float*)(pSIMD)); + vector unsigned char permMask = vec_lvsl(0, (float*)(pSIMD)); + fltx4 v1 = vec_ld(11, (float*)(pSIMD)); + + return vec_perm(v0, v1, permMask); +} + + +FORCEINLINE fltx4 LoadUnalignedFloatSIMD(const float* pFlt) +{ + fltx4 v0 = vec_lde(0, const_cast(pFlt)); + vector unsigned char permMask = vec_lvsl(0, const_cast(pFlt)); + return vec_perm(v0, v0, permMask); +} + + +FORCEINLINE fltx4 LoadAlignedSIMD(const void* pSIMD) +{ + return vec_ld(0, (float*)pSIMD); +} + +#ifndef SPU +FORCEINLINE fltx4 LoadAlignedSIMD(const VectorAligned& pSIMD) +{ + fltx4 out; + out = vec_ld(0, pSIMD.Base()); + + return (fltx4)vec_and((u32x4)out, _VEC_CLEAR_WMASK); +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const VectorAligned* RESTRICT pSIMD) +{ + fltx4 out; + out = vec_ld(0, pSIMD->Base()); + + return (fltx4)vec_and((u32x4)out, _VEC_CLEAR_WMASK); +} + + +FORCEINLINE void StoreAligned3SIMD(VectorAligned* RESTRICT pSIMD, const fltx4& a) +{ + vec_st(a, 0, pSIMD->Base()); +} +#endif + +FORCEINLINE void StoreAlignedSIMD(float* pSIMD, const fltx4& a) +{ + vec_st(a, 0, pSIMD); +} + +FORCEINLINE void StoreUnalignedSIMD(float* pSIMD, const fltx4& a) +{ +#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 1 ) && ( __GNUC_PATCHLEVEL__ == 1 ) + vec_stvlx(a, 0, pSIMD); + vec_stvrx(a, 16, pSIMD); +#else + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxf); + pSIMD[0] = a_union.m128_f32[0]; + pSIMD[1] = a_union.m128_f32[1]; + pSIMD[2] = a_union.m128_f32[2]; + pSIMD[3] = a_union.m128_f32[3]; +#endif + +} + +FORCEINLINE void StoreUnaligned3SIMD(float* pSIMD, const fltx4& a) +{ + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxf); + pSIMD[0] = a_union.m128_f32[0]; + pSIMD[1] = a_union.m128_f32[1]; + pSIMD[2] = a_union.m128_f32[2]; +}; + + + +#ifndef SPU + +FORCEINLINE fltx4 Compress4SIMD(fltx4 const a, fltx4 const& b, fltx4 const& c, fltx4 const& d); +FORCEINLINE fltx4 LoadGatherSIMD(const float& x, const float& y, const float& z, const float& w) +{ +#if USING_POINTLESSLY_SLOW_SONY_CODE + return vmathV4MakeFromElems_V(x, y, z, w).vec128; +#else + fltx4 vx = vec_lvlx(0, &x); + fltx4 vy = vec_lvlx(0, &y); + fltx4 vz = vec_lvlx(0, &z); + fltx4 vw = vec_lvlx(0, &w); + return Compress4SIMD(vx, vy, vz, vw); +#endif +} + + +FORCEINLINE void StoreFourUnalignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + StoreUnaligned3SIMD(pDestination->Base(), a); + StoreUnaligned3SIMD((pDestination + 1)->Base(), b); + StoreUnaligned3SIMD((pDestination + 2)->Base(), c); + StoreUnaligned3SIMD((pDestination + 3)->Base(), d); +} + +FORCEINLINE void StoreFourAlignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + StoreUnaligned3SIMD(pDestination->Base(), a); + StoreUnaligned3SIMD((pDestination + 1)->Base(), b); + StoreUnaligned3SIMD((pDestination + 2)->Base(), c); + StoreUnaligned3SIMD((pDestination + 3)->Base(), d); +} +#endif + +FORCEINLINE void ConvertStoreAsIntsSIMD(intx4* RESTRICT pDest, const fltx4& vSrc) +{ + i32x4 asInt = vec_cts(vSrc, 0); + vec_st(asInt, 0, pDest->Base()); +} + +FORCEINLINE void TransposeSIMD(fltx4& x, fltx4& y, fltx4& z, fltx4& w) +{ + fltx4 p0, p1, p2, p3; + + p0 = vec_mergeh(x, z); + p1 = vec_mergeh(y, w); + p2 = vec_mergel(x, z); + p3 = vec_mergel(y, w); + + x = vec_mergeh(p0, p1); + y = vec_mergel(p0, p1); + z = vec_mergeh(p2, p3); + w = vec_mergel(p2, p3); +} + +FORCEINLINE fltx4 LoadZeroSIMD(void) +{ + return _VEC_ZEROF; +} +FORCEINLINE i32x4 LoadZeroISIMD(void) +{ + return vec_splat_s32(0); +} + + +FORCEINLINE fltx4 LoadOneSIMD(void) +{ + return _VEC_ONEF; +} +FORCEINLINE i32x4 LoadOneISIMD(void) +{ + return vec_splat_s32(1); +} + +FORCEINLINE fltx4 SplatXSIMD(fltx4 a) +{ + return vec_splat(a, 0); +} +FORCEINLINE fltx4 SplatYSIMD(fltx4 a) +{ + return vec_splat(a, 1); +} +FORCEINLINE fltx4 SplatZSIMD(fltx4 a) +{ + return vec_splat(a, 2); +} +FORCEINLINE fltx4 SplatWSIMD(fltx4 a) +{ + return vec_splat(a, 3); +} + +FORCEINLINE bi32x4 SplatXSIMD(bi32x4 a) +{ + return vec_splat(a, 0); +} +FORCEINLINE bi32x4 SplatYSIMD(bi32x4 a) +{ + return vec_splat(a, 1); +} +FORCEINLINE bi32x4 SplatZSIMD(bi32x4 a) +{ + return vec_splat(a, 2); +} +FORCEINLINE bi32x4 SplatWSIMD(bi32x4 a) +{ + return vec_splat(a, 3); +} + +FORCEINLINE fltx4 SetXSIMD(const fltx4& a, const fltx4& x) +{ + return vec_sel(a, x, _VEC_COMPONENT_MASK_0); +} + +FORCEINLINE fltx4 SetYSIMD(const fltx4& a, const fltx4& y) +{ + return vec_sel(a, y, _VEC_COMPONENT_MASK_1); +} + +FORCEINLINE fltx4 SetZSIMD(const fltx4& a, const fltx4& z) +{ + return vec_sel(a, z, _VEC_COMPONENT_MASK_2); +} + +FORCEINLINE fltx4 SetWSIMD(const fltx4& a, const fltx4& w) +{ + return vec_sel(a, w, _VEC_COMPONENT_MASK_3); +} + +FORCEINLINE fltx4 SetComponentSIMD(const fltx4& a, int nComponent, float flValue) +{ +#if SN_IMPROVED_INTRINSICS + return vec_insert(flValue, a, nComponent); +#else + fltx4_union a_union; + a_union.vmxf = vec_ld(0, &a); + a_union.m128_f32[nComponent] = flValue; + return a_union.vmxf; +#endif +} + +FORCEINLINE float GetComponentSIMD(const fltx4& a, int nComponent) +{ +#if SN_IMPROVED_INTRINSICS + return vec_extract(a, nComponent); +#else + fltx4_union a_union; + a_union.vmxf = vec_ld(0, &a); + return a_union.m128_f32[nComponent]; +#endif +} + + +FORCEINLINE fltx4 RotateLeft(const fltx4& a) +{ + return vec_sld(a, a, 4); +} + +FORCEINLINE fltx4 RotateLeft2(const fltx4& a) +{ + return vec_sld(a, a, 8); +} + +FORCEINLINE fltx4 RotateRight(const fltx4& a) +{ + return vec_sld(a, a, 12); +} + +FORCEINLINE fltx4 RotateRight2(const fltx4& a) +{ + return vec_sld(a, a, 8); +} + +template < uint nBits, typename T > +FORCEINLINE T ShiftLeftByBits(const T& a) +{ + if (nBits >= 128) + { + return (T)LoadZeroSIMD(); + } + else if (nBits == 0) + { + return a; + } + else if ((nBits > 7)) + { + T t = vec_sld(a, ((T)LoadZeroSIMD()), (nBits >> 3)); + return ShiftLeftByBits< (nBits & 0x7) >(t); + } + else + { + vector unsigned int shifter = (vector unsigned int) (vec_splat_s8(((signed char)(nBits & 0x7)))); + return (T)vec_sll((vector signed int) a, shifter); + } +} + +template < uint nBits, typename T > +FORCEINLINE T ShiftRightByBits(const T& a) +{ + if (nBits >= 128) + { + return (T)LoadZeroSIMD(); + } + else if (nBits == 0) + { + return a; + } + else if ((nBits > 7)) + { + T t = vec_sld(((T)LoadZeroSIMD()), a, 16 - (nBits >> 3)); + return ShiftRightByBits< (nBits & 0x7) >(t); + } + else + { + vector unsigned int shifter = (vector unsigned int) (vec_splat_s8(((signed char)(nBits & 0x7)))); + return (T)vec_srl((vector unsigned int) a, shifter); + } +} + + + + +FORCEINLINE fltx4 FindLowestSIMD3(const fltx4& a) +{ + fltx4 result; + fltx4 x = vec_splat(a, 0); + fltx4 y = vec_splat(a, 1); + fltx4 z = vec_splat(a, 2); + + if (vec_any_nan(a)) + { + x = vec_all_nan(x) ? _VEC_FLTMAX : x; + y = vec_all_nan(y) ? _VEC_FLTMAX : y; + z = vec_all_nan(z) ? _VEC_FLTMAX : z; + } + + result = vec_min(y, x); + result = vec_min(z, result); + + return result; + +} + +FORCEINLINE fltx4 FindHighestSIMD3(const fltx4& a) +{ + fltx4 result; + fltx4 x = vec_splat(a, 0); + fltx4 y = vec_splat(a, 1); + fltx4 z = vec_splat(a, 2); + + if (vec_any_nan(a)) + { + x = vec_all_nan(x) ? _VEC_FLTMIN : x; + y = vec_all_nan(y) ? _VEC_FLTMIN : y; + z = vec_all_nan(z) ? _VEC_FLTMIN : z; + } + + result = vec_max(y, x); + result = vec_max(z, result); + + return result; +} + + +FORCEINLINE i32x4 LoadAlignedIntSIMD(const int32* RESTRICT pSIMD) +{ + return vec_ld(0, const_cast(pSIMD)); +} + +FORCEINLINE i32x4 LoadUnalignedIntSIMD(const int32* RESTRICT pSIMD) +{ + i32x4 v0, v1; + vector unsigned char permMask; + + Assert(pSIMD); + + v0 = vec_ld(0, const_cast(pSIMD)); + permMask = vec_lvsl(0, const_cast(pSIMD)); + v1 = vec_ld(15, const_cast(pSIMD)); + + return vec_perm(v0, v1, permMask); + +} + +FORCEINLINE void StoreAlignedIntSIMD(int32* pSIMD, const i32x4& a) +{ + vec_st(a, 0, pSIMD); +} + +FORCEINLINE void StoreAlignedIntSIMD(int32* pSIMD, const fltx4& a) +{ + vec_st((i32x4)a, 0, pSIMD); +} + +FORCEINLINE void StoreAlignedIntSIMD(intx4& pSIMD, const i32x4& a) +{ + vec_st(a, 0, pSIMD.Base()); +} + +FORCEINLINE void StoreUnalignedIntSIMD(int32* pSIMD, const i32x4& a) +{ +#if SN_IMPROVED_INTRINSICS + + vec_stvlx(a, 0, pSIMD); + vec_stvrx(a, 16, pSIMD); + +#else + + fltx4_union tmp; + vec_st(a, 0, &tmp.vmxi); + + pSIMD[0] = tmp.m128_u32[0]; + pSIMD[1] = tmp.m128_u32[1]; + pSIMD[2] = tmp.m128_u32[2]; + pSIMD[3] = tmp.m128_u32[3]; + +#endif +} + +FORCEINLINE fltx4 CompressSIMD(fltx4 const& a, fltx4 const& b) +{ + const int32 ALIGN16 n4shuffleACXZ[4] ALIGN16_POST = { 0x00010203, 0x08090A0B, 0x10111213, 0x18191A1B }; + return vec_perm(a, b, (vec_uchar16)LoadAlignedIntSIMD(n4shuffleACXZ)); +} + +FORCEINLINE fltx4 Compress4SIMD(fltx4 const a, fltx4 const& b, fltx4 const& c, fltx4 const& d) +{ + fltx4 ab = vec_mergeh(a, b); + fltx4 cd = vec_mergeh(c, d); + static const int32 ALIGN16 shuffleABXY[4] ALIGN16_POST = { 0x00010203, 0x04050607, 0x10111213, 0x14151617 }; + + return vec_perm(ab, cd, (vec_uchar16)LoadAlignedIntSIMD(shuffleABXY)); +} + + +FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD(const i32x4& vSrcA) +{ + return vec_ctf(vSrcA, 0); +} + + +FORCEINLINE fltx4 SignedIntConvertToFltSIMD(const i32x4& vSrcA) +{ + return vec_ctf(vSrcA, 0); +} + +#define UnsignedFixedIntConvertToFltSIMD(vSrcA, uImmed) (vec_ctf( (vSrcA), (uImmed) )) + +#define SignedFixedIntConvertToFltSIMD(vSrcA, uImmed) (vec_ctf( (vSrcA), (uImmed) )) + +#define IntSetImmediateSIMD(x) (vec_splat_s32(x)) + + +FORCEINLINE u32x4 IntShiftLeftWordSIMD(u32x4 vSrcA, u32x4 vSrcB) +{ + return vec_sl(vSrcA, vSrcB); +} + + +FORCEINLINE float SubFloat(const fltx4& a, int idx) +{ +#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 1 ) && ( __GNUC_PATCHLEVEL__ == 1 ) + return(vec_extract(a, idx)); +#else + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxf); + return a_union.m128_f32[idx]; +#endif +} + +FORCEINLINE float& SubFloat(fltx4& a, int idx) +{ + fltx4_union& a_union = (fltx4_union&)a; + return a_union.m128_f32[idx]; +} + +FORCEINLINE uint32 SubInt(const u32x4& a, int idx) +{ +#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 1 ) && ( __GNUC_PATCHLEVEL__ == 1 ) + return(vec_extract(a, idx)); +#else + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxui); + return a_union.m128_u32[idx]; +#endif +} + +FORCEINLINE uint32 SubInt(const fltx4& a, int idx) +{ +#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 1 ) && ( __GNUC_PATCHLEVEL__ == 1 ) + return(vec_extract((u32x4)a, idx)); +#else + fltx4_union a_union; + vec_st(a, 0, &a_union.vmxf); + return a_union.m128_u32[idx]; +#endif +} + +FORCEINLINE uint32& SubInt(u32x4& a, int idx) +{ + fltx4_union& a_union = (fltx4_union&)a; + return a_union.m128_u32[idx]; +} + +FORCEINLINE uint32 SubFloatConvertToInt(const fltx4& a, int idx) +{ + +#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 1 ) && ( __GNUC_PATCHLEVEL__ == 1 ) + return(vec_extract(vec_ctu(a, 0), idx)); +#else + u32x4 t = vec_ctu(a, 0); + return SubInt(t, idx); +#endif + +} + +template< typename T, typename U > +FORCEINLINE T PermuteVMX(T a, T b, U swizzleMask) +{ + return vec_perm(a, b, (vec_uchar16)swizzleMask); +} + + +#if !defined(__SPU__) +#define fsel __fsel +#endif + +inline bool IsVector3LessThan(const fltx4& v1, const fltx4& v2) +{ + return vec_any_lt(v1, v2); +} + +inline bool IsVector3GreaterOrEqual(const fltx4& v1, const fltx4& v2) +{ + return !IsVector3LessThan(v1, v2); +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSaturateSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = 1.0 / sqrt(SubFloat(a, 0) != 0.0f ? SubFloat(a, 0) : FLT_EPSILON); + SubFloat(retVal, 1) = 1.0 / sqrt(SubFloat(a, 1) != 0.0f ? SubFloat(a, 1) : FLT_EPSILON); + SubFloat(retVal, 2) = 1.0 / sqrt(SubFloat(a, 2) != 0.0f ? SubFloat(a, 2) : FLT_EPSILON); + SubFloat(retVal, 3) = 1.0 / sqrt(SubFloat(a, 3) != 0.0f ? SubFloat(a, 3) : FLT_EPSILON); + return retVal; +} + +FORCEINLINE fltx4 FloorSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = floor(SubFloat(a, 0)); + SubFloat(retVal, 1) = floor(SubFloat(a, 1)); + SubFloat(retVal, 2) = floor(SubFloat(a, 2)); + SubFloat(retVal, 3) = floor(SubFloat(a, 3)); + return retVal; +} + +#elif ( defined( _X360 ) ) + +inline bool IsVector3LessThan(const fltx4& v1, const fltx4& v2) +{ + return !XMVector3GreaterOrEqual(v1, v2); +} + +inline BOOL IsVector3GreaterOrEqual(const fltx4& v1, const fltx4& v2) +{ + return XMVector3GreaterOrEqual(v1, v2); +} + + +FORCEINLINE float& FloatSIMD(fltx4& a, int idx) +{ + fltx4_union& a_union = (fltx4_union&)a; + return a_union.m128_f32[idx]; +} + +FORCEINLINE unsigned int& UIntSIMD(fltx4& a, int idx) +{ + fltx4_union& a_union = (fltx4_union&)a; + return a_union.m128_u32[idx]; +} + +FORCEINLINE fltx4 AddSIMD(const fltx4& a, const fltx4& b) +{ + return __vaddfp(a, b); +} + +FORCEINLINE fltx4 SubSIMD(const fltx4& a, const fltx4& b) +{ + return __vsubfp(a, b); +} + +FORCEINLINE fltx4 MulSIMD(const fltx4& a, const fltx4& b) +{ + return __vmulfp(a, b); +} + +FORCEINLINE fltx4 MaddSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return __vmaddfp(a, b, c); +} + +FORCEINLINE fltx4 MsubSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return __vnmsubfp(a, b, c); +}; + +FORCEINLINE fltx4 Dot3SIMD(const fltx4& a, const fltx4& b) +{ + return __vmsum3fp(a, b); +} + +FORCEINLINE fltx4 Dot4SIMD(const fltx4& a, const fltx4& b) +{ + return __vmsum4fp(a, b); +} + +FORCEINLINE fltx4 SinSIMD(const fltx4& radians) +{ + return XMVectorSin(radians); +} + +FORCEINLINE void SinCos3SIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + XMVectorSinCos(&sine, &cosine, radians); +} + +FORCEINLINE void SinCosSIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + XMVectorSinCos(&sine, &cosine, radians); +} + +FORCEINLINE void CosSIMD(fltx4& cosine, const fltx4& radians) +{ + cosine = XMVectorCos(radians); +} + +FORCEINLINE fltx4 ArcSinSIMD(const fltx4& sine) +{ + return XMVectorASin(sine); +} + +FORCEINLINE fltx4 ArcCosSIMD(const fltx4& cs) +{ + return XMVectorACos(cs); +} + +FORCEINLINE fltx4 ArcTan2SIMD(const fltx4& a, const fltx4& b) +{ + return XMVectorATan2(a, b); +} + +FORCEINLINE fltx4 MaxSIMD(const fltx4& a, const fltx4& b) +{ + return __vmaxfp(a, b); +} + +FORCEINLINE fltx4 MinSIMD(const fltx4& a, const fltx4& b) +{ + return __vminfp(a, b); +} + +FORCEINLINE fltx4 AndSIMD(const fltx4& a, const fltx4& b) +{ + return __vand(a, b); +} + +FORCEINLINE fltx4 AndNotSIMD(const fltx4& a, const fltx4& b) +{ + return __vandc(b, a); +} + +FORCEINLINE fltx4 XorSIMD(const fltx4& a, const fltx4& b) +{ + return __vxor(a, b); +} + +FORCEINLINE fltx4 OrSIMD(const fltx4& a, const fltx4& b) +{ + return __vor(a, b); +} + +FORCEINLINE fltx4 NegSIMD(const fltx4& a) +{ + return XMVectorNegate(a); +} + +FORCEINLINE bool IsAllZeros(const fltx4& a) +{ + unsigned int equalFlags = 0; + __vcmpeqfpR(a, Four_Zeros, &equalFlags); + return XMComparisonAllTrue(equalFlags); +} + +FORCEINLINE bool IsAnyZeros(const fltx4& a) +{ + unsigned int conditionregister; + XMVectorEqualR(&conditionregister, a, XMVectorZero()); + return XMComparisonAnyTrue(conditionregister); +} + +FORCEINLINE bool IsAnyXYZZero(const fltx4& a) +{ + fltx4 temp = __vrlimi(a, a, 1, 1); + unsigned int conditionregister; + XMVectorEqualR(&conditionregister, temp, XMVectorZero()); + return XMComparisonAnyTrue(conditionregister); +} + +FORCEINLINE bool IsAllGreaterThan(const fltx4& a, const fltx4& b) +{ + unsigned int cr; + XMVectorGreaterR(&cr, a, b); + return XMComparisonAllTrue(cr); +} + +FORCEINLINE bool IsAllGreaterThanOrEq(const fltx4& a, const fltx4& b) +{ + unsigned int cr; + XMVectorGreaterOrEqualR(&cr, a, b); + return XMComparisonAllTrue(cr); +} + +FORCEINLINE bool IsAnyGreaterThan(const fltx4& a, const fltx4& b) +{ + unsigned int cr; + XMVectorGreaterR(&cr, a, b); + return XMComparisonAnyTrue(cr); +} + +FORCEINLINE bool IsAnyGreaterThanOrEq(const fltx4& a, const fltx4& b) +{ + unsigned int cr; + XMVectorGreaterOrEqualR(&cr, a, b); + return XMComparisonAnyTrue(cr); +} + +FORCEINLINE bool IsAllEqual(const fltx4& a, const fltx4& b) +{ + unsigned int cr; + XMVectorEqualR(&cr, a, b); + return XMComparisonAllTrue(cr); +} + + +FORCEINLINE int TestSignSIMD(const fltx4& a) +{ + int nRet = 0; + + const fltx4_union& a_union = (const fltx4_union&)a; + nRet |= (a_union.m128_u32[0] & 0x80000000) >> 31; + nRet |= (a_union.m128_u32[1] & 0x80000000) >> 30; + nRet |= (a_union.m128_u32[2] & 0x80000000) >> 29; + nRet |= (a_union.m128_u32[3] & 0x80000000) >> 28; + + return nRet; +} + +FORCEINLINE fltx4 SetWToZeroSIMD(const fltx4& a) +{ + return __vrlimi(a, __vzero(), 1, 0); +} + +FORCEINLINE bool IsAnyNegative(const fltx4& a) +{ + unsigned int equalFlags = 0; + fltx4 signMask = __vspltisw(-1); + signMask = __vslw(signMask, signMask); + __vcmpequwR(Four_Zeros, __vand(signMask, a), &equalFlags); + return !XMComparisonAllTrue(equalFlags); +} + +FORCEINLINE bool IsAnyTrue(const fltx4& a) +{ + unsigned int equalFlags = 0; + __vcmpequwR(Four_Zeros, a, &equalFlags); + return XMComparisonAnyFalse(equalFlags); +} + +FORCEINLINE fltx4 CmpEqSIMD(const fltx4& a, const fltx4& b) +{ + return __vcmpeqfp(a, b); +} + + +FORCEINLINE fltx4 CmpGtSIMD(const fltx4& a, const fltx4& b) +{ + return __vcmpgtfp(a, b); +} + +FORCEINLINE fltx4 CmpGeSIMD(const fltx4& a, const fltx4& b) +{ + return __vcmpgefp(a, b); +} + +FORCEINLINE fltx4 CmpLtSIMD(const fltx4& a, const fltx4& b) +{ + return __vcmpgtfp(b, a); +} + +FORCEINLINE fltx4 CmpLeSIMD(const fltx4& a, const fltx4& b) +{ + return __vcmpgefp(b, a); +} + +FORCEINLINE fltx4 CmpInBoundsSIMD(const fltx4& a, const fltx4& b) +{ + return XMVectorInBounds(a, b); +} + +FORCEINLINE fltx4 MaskedAssign(const fltx4& ReplacementMask, const fltx4& NewValue, const fltx4& OldValue) +{ + return __vsel(OldValue, NewValue, ReplacementMask); +} + + +template< typename T, typename U > +FORCEINLINE T PermuteVMX(T a, T b, U swizzleMask) +{ + return __vperm(a, b, swizzleMask); +} + +FORCEINLINE fltx4 ReplicateX4(float flValue) +{ + float* pValue = &flValue; + Assert(pValue); + Assert(((unsigned int)pValue & 3) == 0); + return __vspltw(__lvlx(pValue, 0), 0); +} + +FORCEINLINE fltx4 ReplicateX4(const float* pValue) +{ + Assert(pValue); + return __vspltw(__lvlx(pValue, 0), 0); +} + +FORCEINLINE fltx4 ReplicateIX4(int nValue) +{ + int* pValue = &nValue; + Assert(pValue); + Assert(((unsigned int)pValue & 3) == 0); + return __vspltw(__lvlx(pValue, 0), 0); +} + +FORCEINLINE fltx4 CeilSIMD(const fltx4& a) +{ + return __vrfip(a); +} + +FORCEINLINE fltx4 RoundSIMD(const fltx4& a) +{ + return __vrfin(a); +} + +FORCEINLINE fltx4 FloorSIMD(const fltx4& a) +{ + return __vrfim(a); +} + +FORCEINLINE fltx4 SqrtEstSIMD(const fltx4& a) +{ + return XMVectorSqrtEst(a); +} + +FORCEINLINE fltx4 SqrtSIMD(const fltx4& a) +{ + return XMVectorSqrt(a); +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSIMD(const fltx4& a) +{ + return __vrsqrtefp(a); +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSaturateSIMD(const fltx4& a) +{ + fltx4 zero_mask = CmpEqSIMD(a, Four_Zeros); + fltx4 a_safe = OrSIMD(a, AndSIMD(Four_Epsilons, zero_mask)); + return ReciprocalSqrtEstSIMD(a_safe); +} + +FORCEINLINE fltx4 ReciprocalSqrtSIMD(const fltx4& a) +{ + return XMVectorReciprocalSqrt(a); +} + +FORCEINLINE fltx4 ReciprocalEstSIMD(const fltx4& a) +{ + return __vrefp(a); +} + +FORCEINLINE fltx4 ReciprocalSIMD(const fltx4& a) +{ + return XMVectorReciprocal(a); +} + +FORCEINLINE fltx4 DivSIMD(const fltx4& a, const fltx4& b) +{ + return MulSIMD(ReciprocalSIMD(b), a); +} + +FORCEINLINE fltx4 DivEstSIMD(const fltx4& a, const fltx4& b) +{ + return MulSIMD(ReciprocalEstSIMD(b), a); +} + +FORCEINLINE fltx4 ReciprocalEstSaturateSIMD(const fltx4& a) +{ + fltx4 zero_mask = CmpEqSIMD(a, Four_Zeros); + fltx4 a_safe = OrSIMD(a, AndSIMD(Four_Epsilons, zero_mask)); + return ReciprocalEstSIMD(a_safe); +} + +FORCEINLINE fltx4 ReciprocalSaturateSIMD(const fltx4& a) +{ + fltx4 zero_mask = CmpEqSIMD(a, Four_Zeros); + fltx4 a_safe = OrSIMD(a, AndSIMD(Four_Epsilons, zero_mask)); + return ReciprocalSIMD(a_safe); + +} + +FORCEINLINE fltx4 ExpSIMD(const fltx4& toPower) +{ + return XMVectorExp(toPower); +} + +FORCEINLINE fltx4 Exp2EstSIMD(const fltx4& f) +{ + return XMVectorExpEst(f); +} + +FORCEINLINE fltx4 ClampVectorSIMD(FLTX4 in, FLTX4 min, FLTX4 max) +{ + return XMVectorClamp(in, min, max); +} + +FORCEINLINE fltx4 LoadUnalignedSIMD(const void* pSIMD) +{ + return XMLoadVector4(pSIMD); +} + +FORCEINLINE fltx4 LoadUnaligned3SIMD(const void* pSIMD) +{ + return XMLoadVector3(pSIMD); +} + +FORCEINLINE fltx4 LoadUnalignedFloatSIMD(const float* pFlt) +{ + return __lvlx(pFlt, 0); +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const void* pSIMD) +{ + return *(reinterpret_cast (pSIMD)); +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const VectorAligned& pSIMD) +{ + fltx4 out = XMLoadVector3A(pSIMD.Base()); + return __vrlimi(out, __vzero(), 1, 0); +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const VectorAligned* RESTRICT pSIMD) +{ + fltx4 out = XMLoadVector3A(pSIMD); + return __vrlimi(out, __vzero(), 1, 0); +} + +FORCEINLINE void StoreAlignedSIMD(float* pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD)) = a; +} + +FORCEINLINE void StoreUnalignedSIMD(float* pSIMD, const fltx4& a) +{ + XMStoreVector4(pSIMD, a); +} + +FORCEINLINE void StoreUnaligned3SIMD(float* pSIMD, const fltx4& a) +{ + XMStoreVector3(pSIMD, a); +} + +FORCEINLINE void StoreAligned3SIMD(VectorAligned* RESTRICT pSIMD, const fltx4& a) +{ + XMStoreVector3A(pSIMD->Base(), a); +} + +FORCEINLINE void StoreFourUnalignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + b = __vrlimi(b, b, 15, 1); + c = __vrlimi(c, c, 15, 2); + + a = __vrlimi(a, b, 1, 0); + b = __vrlimi(b, c, 2 | 1, 0); + c = __vrlimi(c, d, 4 | 2 | 1, 3); + + float* RESTRICT pOut = pDestination->Base(); + StoreUnalignedSIMD(pOut + 0, a); + StoreUnalignedSIMD(pOut + 4, b); + StoreUnalignedSIMD(pOut + 8, c); +} + +FORCEINLINE void StoreFourAlignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + b = __vrlimi(b, b, 15, 1); + c = __vrlimi(c, c, 15, 2); + + a = __vrlimi(a, b, 1, 0); + b = __vrlimi(b, c, 2 | 1, 0); + c = __vrlimi(c, d, 4 | 2 | 1, 3); + + float* RESTRICT pOut = pDestination->Base(); + StoreAlignedSIMD(pOut + 0, a); + StoreAlignedSIMD(pOut + 4, b); + StoreAlignedSIMD(pOut + 8, c); +} + +FORCEINLINE void ConvertStoreAsIntsSIMD(intx4* RESTRICT pDest, const fltx4& vSrc) +{ + fltx4 asInt = __vctsxs(vSrc, 0); + XMStoreVector4A(pDest->Base(), asInt); +} + +FORCEINLINE void TransposeSIMD(fltx4& x, fltx4& y, fltx4& z, fltx4& w) +{ + XMMATRIX xyzwMatrix = _XMMATRIX(x, y, z, w); + xyzwMatrix = XMMatrixTranspose(xyzwMatrix); + x = xyzwMatrix.r[0]; + y = xyzwMatrix.r[1]; + z = xyzwMatrix.r[2]; + w = xyzwMatrix.r[3]; +} + +FORCEINLINE fltx4 LoadZeroSIMD(void) +{ + return XMVectorZero(); +} + +FORCEINLINE fltx4 LoadOneSIMD(void) +{ + return XMVectorSplatOne(); +} + +FORCEINLINE fltx4 SplatXSIMD(fltx4 a) +{ + return XMVectorSplatX(a); +} + +FORCEINLINE fltx4 SplatYSIMD(fltx4 a) +{ + return XMVectorSplatY(a); +} + +FORCEINLINE fltx4 SplatZSIMD(fltx4 a) +{ + return XMVectorSplatZ(a); +} + +FORCEINLINE fltx4 SplatWSIMD(fltx4 a) +{ + return XMVectorSplatW(a); +} + +FORCEINLINE fltx4 SetXSIMD(const fltx4& a, const fltx4& x) +{ + fltx4 result = __vrlimi(a, x, 8, 0); + return result; +} + +FORCEINLINE fltx4 SetYSIMD(const fltx4& a, const fltx4& y) +{ + fltx4 result = __vrlimi(a, y, 4, 0); + return result; +} + +FORCEINLINE fltx4 SetZSIMD(const fltx4& a, const fltx4& z) +{ + fltx4 result = __vrlimi(a, z, 2, 0); + return result; +} + +FORCEINLINE fltx4 SetWSIMD(const fltx4& a, const fltx4& w) +{ + fltx4 result = __vrlimi(a, w, 1, 0); + return result; +} + +FORCEINLINE fltx4 SetComponentSIMD(const fltx4& a, int nComponent, float flValue) +{ + static int s_nVrlimiMask[4] = { 8, 4, 2, 1 }; + fltx4 val = ReplicateX4(flValue); + fltx4 result = __vrlimi(a, val, s_nVrlimiMask[nComponent], 0); + return result; +} + +FORCEINLINE fltx4 RotateLeft(const fltx4& a) +{ + fltx4 compareOne = a; + return __vrlimi(compareOne, a, 8 | 4 | 2 | 1, 1); +} + +FORCEINLINE fltx4 RotateLeft2(const fltx4& a) +{ + fltx4 compareOne = a; + return __vrlimi(compareOne, a, 8 | 4 | 2 | 1, 2); +} + +FORCEINLINE fltx4 RotateRight(const fltx4& a) +{ + fltx4 compareOne = a; + return __vrlimi(compareOne, a, 8 | 4 | 2 | 1, 3); +} + +FORCEINLINE fltx4 RotateRight2(const fltx4& a) +{ + fltx4 compareOne = a; + return __vrlimi(compareOne, a, 8 | 4 | 2 | 1, 2); +} + + +template < uint nBits > +FORCEINLINE fltx4 ShiftLeftByBits(const fltx4& a) +{ + if (nBits >= 128) + { + return LoadZeroSIMD(); + } + else if (nBits == 0) + { + return a; + } + else if ((nBits > 7)) + { + fltx4 t = __vsldoi(a, (LoadZeroSIMD()), (nBits >> 3)); + return ShiftLeftByBits< (nBits & 0x7) >(t); + } + else + { + u32x4 shifter = u32x4(__vspltisb(((signed char)(nBits & 0x7)))); + return __vsl(a, shifter); + } +} + +template < uint nBits > +FORCEINLINE fltx4 ShiftRightByBits(const fltx4& a) +{ + if (nBits >= 128) + { + return LoadZeroSIMD(); + } + else if (nBits == 0) + { + return a; + } + else if ((nBits > 7)) + { + fltx4 t = __vsldoi((LoadZeroSIMD()), a, 16 - (nBits >> 3)); + return ShiftRightByBits< (nBits & 0x7) >(t); + } + else + { + u32x4 shifter = u32x4(__vspltisb(((signed char)(nBits & 0x7)))); + return __vsr(a, shifter); + } +} + +FORCEINLINE fltx4 FindLowestSIMD3(const fltx4& a) +{ + fltx4 compareOne = a; + compareOne = __vrlimi(compareOne, a, 8 | 4, 1); + fltx4 retval = MinSIMD(a, compareOne); + compareOne = __vrlimi(compareOne, a, 8, 2); + retval = MinSIMD(retval, compareOne); + return SplatXSIMD(retval); +} + +FORCEINLINE fltx4 FindHighestSIMD3(const fltx4& a) +{ + fltx4 compareOne = a; + compareOne = __vrlimi(compareOne, a, 8 | 4, 1); + fltx4 retval = MaxSIMD(a, compareOne); + compareOne = __vrlimi(compareOne, a, 8, 2); + retval = MaxSIMD(retval, compareOne); + return SplatXSIMD(retval); +} + + +void TransformManyPointsBy(VectorAligned* RESTRICT pVectors, unsigned int numVectors, FLTX4 mRow1, FLTX4 mRow2, FLTX4 mRow3); + +FORCEINLINE void TransformManyPointsBy(VectorAligned* RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& pMatrix) +{ + return TransformManyPointsBy(pVectors, numVectors, + LoadUnalignedSIMD(pMatrix[0]), LoadUnalignedSIMD(pMatrix[1]), LoadUnalignedSIMD(pMatrix[2])); +} + +FORCEINLINE void TransformManyPointsByA(VectorAligned* RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& pMatrix) +{ + return TransformManyPointsBy(pVectors, numVectors, + LoadAlignedSIMD(pMatrix[0]), LoadAlignedSIMD(pMatrix[1]), LoadAlignedSIMD(pMatrix[2])); +} + +FORCEINLINE i32x4 LoadAlignedIntSIMD(const void* RESTRICT pSIMD) +{ + return XMLoadVector4A(pSIMD); +} + +FORCEINLINE i32x4 LoadUnalignedIntSIMD(const void* RESTRICT pSIMD) +{ + return XMLoadVector4(pSIMD); +} + +FORCEINLINE void StoreAlignedIntSIMD(int32* pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD)) = a; +} + +FORCEINLINE void StoreAlignedIntSIMD(intx4& pSIMD, const fltx4& a) +{ + *(reinterpret_cast (pSIMD.Base())) = a; +} + +FORCEINLINE void StoreUnalignedIntSIMD(int32* pSIMD, const fltx4& a) +{ + XMStoreVector4(pSIMD, a); +} + +FORCEINLINE fltx4 LoadAndConvertUint16SIMD(const uint16* pInts) +{ + return XMLoadUShort4(reinterpret_cast(pInts)); +} + +FORCEINLINE fltx4 CompressSIMD(fltx4 const& a, fltx4 const& b) +{ + return XMVectorPermute(a, b, XMVectorPermuteControl(0, 2, 4, 6)); +} + +FORCEINLINE fltx4 Compress4SIMD(fltx4 const a, fltx4 const& b, fltx4 const& c, fltx4 const& d) +{ + fltx4 abcd = __vrlimi(a, b, 4, 3); + abcd = __vrlimi(abcd, c, 2, 2); + abcd = __vrlimi(abcd, d, 1, 1); + + return abcd; +} + + +FORCEINLINE fltx4 LoadGatherSIMD(const float& x, const float& y, const float& z, const float& w) +{ + fltx4 vx = __lvlx(&x, 0); + fltx4 vy = __lvlx(&y, 0); + fltx4 vz = __lvlx(&z, 0); + fltx4 vw = __lvlx(&w, 0); + return Compress4SIMD(vx, vy, vz, vw); +} + +FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD(const i32x4& vSrcA) +{ + return __vcfux(vSrcA, 0); +} + +FORCEINLINE fltx4 SignedIntConvertToFltSIMD(const i32x4& vSrcA) +{ + return __vcfsx(vSrcA, 0); +} + +#define UnsignedFixedIntConvertToFltSIMD(vSrcA, uImmed) (__vcfux( (vSrcA), (uImmed) )) + +#define SignedFixedIntConvertToFltSIMD(vSrcA, uImmed) (__vcfsx( (vSrcA), (uImmed) )) + +#define IntSetImmediateSIMD(x) (__vspltisw(x)) + +FORCEINLINE fltx4 IntShiftLeftWordSIMD(fltx4 vSrcA, fltx4 vSrcB) +{ + return __vslw(vSrcA, vSrcB); +} + +FORCEINLINE float SubFloat(const fltx4& a, int idx) +{ + const fltx4_union& a_union = (const fltx4_union&)a; + return a_union.m128_f32[idx]; +} + +FORCEINLINE float& SubFloat(fltx4& a, int idx) +{ + fltx4_union& a_union = (fltx4_union&)a; + return a_union.m128_f32[idx]; +} + +FORCEINLINE uint32 SubFloatConvertToInt(const fltx4& a, int idx) +{ + fltx4 t = __vctuxs(a, 0); + const fltx4_union& a_union = (const fltx4_union&)t; + return a_union.m128_u32[idx]; +} + + +FORCEINLINE uint32 SubInt(const fltx4& a, int idx) +{ + const fltx4_union& a_union = (const fltx4_union&)a; + return a_union.m128_u32[idx]; +} + +FORCEINLINE uint32& SubInt(fltx4& a, int idx) +{ + fltx4_union& a_union = (fltx4_union&)a; + return a_union.m128_u32[idx]; +} + +#else + +FORCEINLINE void StoreAlignedSIMD(float* RESTRICT pSIMD, const fltx4& a) +{ + _mm_store_ps(pSIMD, a); +} + +FORCEINLINE void StoreAlignedSIMD(short* RESTRICT pSIMD, const shortx8& a) +{ + _mm_store_si128((shortx8*)pSIMD, a); +} +FORCEINLINE void StoreUnalignedSIMD(float* RESTRICT pSIMD, const fltx4& a) +{ + _mm_storeu_ps(pSIMD, a); +} + +FORCEINLINE void StoreUnalignedSIMD(short* RESTRICT pSIMD, const shortx8& a) +{ + _mm_storeu_si128((shortx8*)pSIMD, a); +} + +FORCEINLINE void StoreUnalignedFloat(float* pSingleFloat, const fltx4& a) +{ + _mm_store_ss(pSingleFloat, a); +} + + +FORCEINLINE fltx4 RotateLeft(const fltx4& a); +FORCEINLINE fltx4 RotateLeft2(const fltx4& a); + +FORCEINLINE void StoreUnaligned3SIMD(float* pSIMD, const fltx4& a) +{ + _mm_store_ss(pSIMD, a); + _mm_store_ss(pSIMD + 1, RotateLeft(a)); + _mm_store_ss(pSIMD + 2, RotateLeft2(a)); +} + + +FORCEINLINE void StoreAligned3SIMD(VectorAligned* RESTRICT pSIMD, const fltx4& a) +{ + StoreAlignedSIMD(pSIMD->Base(), a); +} + +FORCEINLINE void StoreFourUnalignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + StoreUnaligned3SIMD(pDestination->Base(), a); + StoreUnaligned3SIMD((pDestination + 1)->Base(), b); + StoreUnaligned3SIMD((pDestination + 2)->Base(), c); + StoreUnaligned3SIMD((pDestination + 3)->Base(), d); +} + +FORCEINLINE void StoreFourAlignedVector3SIMD(fltx4 a, fltx4 b, fltx4 c, FLTX4 d, + Vector* const pDestination) +{ + StoreUnaligned3SIMD(pDestination->Base(), a); + StoreUnaligned3SIMD((pDestination + 1)->Base(), b); + StoreUnaligned3SIMD((pDestination + 2)->Base(), c); + StoreUnaligned3SIMD((pDestination + 3)->Base(), d); +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const void* pSIMD) +{ + return _mm_load_ps(reinterpret_cast (pSIMD)); +} + +FORCEINLINE shortx8 LoadAlignedShortSIMD(const void* pSIMD) +{ + return _mm_load_si128(reinterpret_cast (pSIMD)); +} + +FORCEINLINE shortx8 LoadUnalignedShortSIMD(const void* pSIMD) +{ + return _mm_loadu_si128(reinterpret_cast (pSIMD)); +} + +FORCEINLINE fltx4 AndSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_and_ps(a, b); +} + +FORCEINLINE fltx4 AndNotSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_andnot_ps(a, b); +} + +FORCEINLINE fltx4 XorSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_xor_ps(a, b); +} + +FORCEINLINE fltx4 OrSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_or_ps(a, b); +} + +FORCEINLINE fltx4 SetWToZeroSIMD(const fltx4& a) +{ + return AndSIMD(a, LoadAlignedSIMD(g_SIMD_clear_wmask)); +} + +FORCEINLINE fltx4 LoadAlignedSIMD(const VectorAligned& pSIMD) +{ + return SetWToZeroSIMD(LoadAlignedSIMD(pSIMD.Base())); +} + +FORCEINLINE fltx4 LoadUnalignedSIMD(const void* pSIMD) +{ + return _mm_loadu_ps(reinterpret_cast(pSIMD)); +} + +FORCEINLINE fltx4 LoadUnaligned3SIMD(const void* pSIMD) +{ + return _mm_loadu_ps(reinterpret_cast(pSIMD)); +} + +FORCEINLINE fltx4 LoadUnalignedFloatSIMD(const float* pFlt) +{ + return _mm_load_ss(pFlt); +} + +FORCEINLINE fltx4 ReplicateIX4(int i) +{ + fltx4 value = _mm_set_ss(*((float*)&i));; + return _mm_shuffle_ps(value, value, 0); +} + + +FORCEINLINE fltx4 ReplicateX4(float flValue) +{ + __m128 value = _mm_set_ss(flValue); + return _mm_shuffle_ps(value, value, 0); +} + +FORCEINLINE fltx4 ReplicateX4(const float* flValue) +{ + __m128 value = _mm_set_ss(*flValue); + return _mm_shuffle_ps(value, value, 0); +} + +FORCEINLINE float SubFloat(const fltx4& a, int idx) +{ +#ifndef POSIX + return a.m128_f32[idx]; +#else + return (reinterpret_cast(&a))[idx]; +#endif +} + +FORCEINLINE float& SubFloat(fltx4& a, int idx) +{ +#ifndef POSIX + return a.m128_f32[idx]; +#else + return (reinterpret_cast(&a))[idx]; +#endif +} + +FORCEINLINE uint32 SubFloatConvertToInt(const fltx4& a, int idx) +{ + return (uint32)SubFloat(a, idx); +} + +FORCEINLINE uint32 SubInt(const fltx4& a, int idx) +{ +#ifndef POSIX + return a.m128_u32[idx]; +#else + return (reinterpret_cast(&a))[idx]; +#endif +} + +FORCEINLINE uint32& SubInt(fltx4& a, int idx) +{ +#ifndef POSIX + return a.m128_u32[idx]; +#else + return (reinterpret_cast(&a))[idx]; +#endif +} + +FORCEINLINE fltx4 LoadZeroSIMD(void) +{ + return Four_Zeros; +} + +FORCEINLINE fltx4 LoadOneSIMD(void) +{ + return Four_Ones; +} + +FORCEINLINE fltx4 MaskedAssign(const fltx4& ReplacementMask, const fltx4& NewValue, const fltx4& OldValue) +{ + return OrSIMD( + AndSIMD(ReplacementMask, NewValue), + AndNotSIMD(ReplacementMask, OldValue)); +} + +#define MM_SHUFFLE_REV(a,b,c,d) _MM_SHUFFLE(d,c,b,a) + +FORCEINLINE fltx4 SplatXSIMD(fltx4 const& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(0, 0, 0, 0)); +} + +FORCEINLINE fltx4 SplatYSIMD(fltx4 const& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(1, 1, 1, 1)); +} + +FORCEINLINE fltx4 SplatZSIMD(fltx4 const& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(2, 2, 2, 2)); +} + +FORCEINLINE fltx4 SplatWSIMD(fltx4 const& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(3, 3, 3, 3)); +} + +FORCEINLINE fltx4 ShuffleXXYY(const fltx4& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(0, 0, 1, 1)); +} + +FORCEINLINE fltx4 ShuffleXYXY(const fltx4& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(0, 1, 0, 1)); +} + +FORCEINLINE fltx4 ShuffleZZWW(const fltx4& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(2, 2, 3, 3)); +} + + + + +FORCEINLINE fltx4 SetXSIMD(const fltx4& a, const fltx4& x) +{ + fltx4 result = MaskedAssign(LoadAlignedSIMD(g_SIMD_ComponentMask[0]), x, a); + return result; +} + +FORCEINLINE fltx4 SetYSIMD(const fltx4& a, const fltx4& y) +{ + fltx4 result = MaskedAssign(LoadAlignedSIMD(g_SIMD_ComponentMask[1]), y, a); + return result; +} + +FORCEINLINE fltx4 SetZSIMD(const fltx4& a, const fltx4& z) +{ + fltx4 result = MaskedAssign(LoadAlignedSIMD(g_SIMD_ComponentMask[2]), z, a); + return result; +} + +FORCEINLINE fltx4 SetWSIMD(const fltx4& a, const fltx4& w) +{ + fltx4 result = MaskedAssign(LoadAlignedSIMD(g_SIMD_ComponentMask[3]), w, a); + return result; +} + +FORCEINLINE fltx4 SetComponentSIMD(const fltx4& a, int nComponent, float flValue) +{ + fltx4 val = ReplicateX4(flValue); + fltx4 result = MaskedAssign(LoadAlignedSIMD(g_SIMD_ComponentMask[nComponent]), val, a); + return result; +} + +FORCEINLINE fltx4 RotateLeft(const fltx4& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(1, 2, 3, 0)); +} + +FORCEINLINE fltx4 RotateLeft2(const fltx4& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(2, 3, 0, 1)); +} + +FORCEINLINE fltx4 RotateRight(const fltx4& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(3, 0, 1, 2)); +} + +FORCEINLINE fltx4 RotateRight2(const fltx4& a) +{ + return _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(2, 3, 0, 1)); +} + +FORCEINLINE fltx4 AddSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_add_ps(a, b); +} + +FORCEINLINE fltx4 SubSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_sub_ps(a, b); +}; + +FORCEINLINE fltx4 MulSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_mul_ps(a, b); +}; + +FORCEINLINE fltx4 DivSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_div_ps(a, b); +}; + +fltx4 ReciprocalEstSIMD(const fltx4& a); +FORCEINLINE fltx4 DivEstSIMD(const fltx4& a, const fltx4& b) +{ + return MulSIMD(ReciprocalEstSIMD(b), a); +}; + +FORCEINLINE fltx4 MaddSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return AddSIMD(MulSIMD(a, b), c); +} + +FORCEINLINE fltx4 MsubSIMD(const fltx4& a, const fltx4& b, const fltx4& c) +{ + return SubSIMD(c, MulSIMD(a, b)); +}; + +FORCEINLINE fltx4 Dot3SIMD(const fltx4& a, const fltx4& b) +{ + fltx4 m = MulSIMD(a, b); + return AddSIMD(AddSIMD(SplatXSIMD(m), SplatYSIMD(m)), SplatZSIMD(m)); +} + +FORCEINLINE fltx4 Dot4SIMD(const fltx4& a, const fltx4& b) +{ + fltx4 fl4Product = MulSIMD(a, b); + fltx4 fl4YXWZ = _mm_shuffle_ps(fl4Product, fl4Product, MM_SHUFFLE_REV(1, 0, 3, 2)); + fltx4 fl4UUVV = AddSIMD(fl4Product, fl4YXWZ); + fltx4 fl4VVUU = RotateLeft2(fl4UUVV); + return AddSIMD(fl4UUVV, fl4VVUU); +} + +FORCEINLINE fltx4 SinSIMD(const fltx4& radians) +{ + fltx4 result; + SubFloat(result, 0) = sin(SubFloat(radians, 0)); + SubFloat(result, 1) = sin(SubFloat(radians, 1)); + SubFloat(result, 2) = sin(SubFloat(radians, 2)); + SubFloat(result, 3) = sin(SubFloat(radians, 3)); + return result; +} + +FORCEINLINE void SinCos3SIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + SinCos(SubFloat(radians, 0), &SubFloat(sine, 0), &SubFloat(cosine, 0)); + SinCos(SubFloat(radians, 1), &SubFloat(sine, 1), &SubFloat(cosine, 1)); + SinCos(SubFloat(radians, 2), &SubFloat(sine, 2), &SubFloat(cosine, 2)); +} + +FORCEINLINE void SinCosSIMD(fltx4& sine, fltx4& cosine, const fltx4& radians) +{ + SinCos(SubFloat(radians, 0), &SubFloat(sine, 0), &SubFloat(cosine, 0)); + SinCos(SubFloat(radians, 1), &SubFloat(sine, 1), &SubFloat(cosine, 1)); + SinCos(SubFloat(radians, 2), &SubFloat(sine, 2), &SubFloat(cosine, 2)); + SinCos(SubFloat(radians, 3), &SubFloat(sine, 3), &SubFloat(cosine, 3)); +} + +FORCEINLINE fltx4 ArcSinSIMD(const fltx4& sine) +{ + fltx4 result; + SubFloat(result, 0) = asin(SubFloat(sine, 0)); + SubFloat(result, 1) = asin(SubFloat(sine, 1)); + SubFloat(result, 2) = asin(SubFloat(sine, 2)); + SubFloat(result, 3) = asin(SubFloat(sine, 3)); + return result; +} + +FORCEINLINE fltx4 ArcCosSIMD(const fltx4& cs) +{ + fltx4 result; + SubFloat(result, 0) = acos(SubFloat(cs, 0)); + SubFloat(result, 1) = acos(SubFloat(cs, 1)); + SubFloat(result, 2) = acos(SubFloat(cs, 2)); + SubFloat(result, 3) = acos(SubFloat(cs, 3)); + return result; +} + +FORCEINLINE fltx4 ArcTan2SIMD(const fltx4& a, const fltx4& b) +{ + fltx4 result; + SubFloat(result, 0) = atan2(SubFloat(a, 0), SubFloat(b, 0)); + SubFloat(result, 1) = atan2(SubFloat(a, 1), SubFloat(b, 1)); + SubFloat(result, 2) = atan2(SubFloat(a, 2), SubFloat(b, 2)); + SubFloat(result, 3) = atan2(SubFloat(a, 3), SubFloat(b, 3)); + return result; +} + +FORCEINLINE fltx4 NegSIMD(const fltx4& a) +{ + return SubSIMD(LoadZeroSIMD(), a); +} + +FORCEINLINE int TestSignSIMD(const fltx4& a) +{ + return _mm_movemask_ps(a); +} + +FORCEINLINE bool IsAnyNegative(const fltx4& a) +{ + return (0 != TestSignSIMD(a)); +} + +FORCEINLINE bool IsAnyTrue(const fltx4& a) +{ + return (0 != TestSignSIMD(a)); +} + +FORCEINLINE fltx4 CmpEqSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_cmpeq_ps(a, b); +} + +FORCEINLINE fltx4 CmpGtSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_cmpgt_ps(a, b); +} + +FORCEINLINE fltx4 CmpGeSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_cmpge_ps(a, b); +} + +FORCEINLINE fltx4 CmpLtSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_cmplt_ps(a, b); +} + +FORCEINLINE fltx4 CmpLeSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_cmple_ps(a, b); +} + +FORCEINLINE bool IsAllGreaterThan(const fltx4& a, const fltx4& b) +{ + return TestSignSIMD(CmpLeSIMD(a, b)) == 0; +} + +FORCEINLINE bool IsAllGreaterThanOrEq(const fltx4& a, const fltx4& b) +{ + return TestSignSIMD(CmpLtSIMD(a, b)) == 0; +} + +FORCEINLINE bool IsAllEqual(const fltx4& a, const fltx4& b) +{ + return TestSignSIMD(CmpEqSIMD(a, b)) == 0xf; +} + +FORCEINLINE fltx4 CmpInBoundsSIMD(const fltx4& a, const fltx4& b) +{ + return AndSIMD(CmpLeSIMD(a, b), CmpGeSIMD(a, NegSIMD(b))); +} + +FORCEINLINE fltx4 MinSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_min_ps(a, b); +} + +FORCEINLINE fltx4 MaxSIMD(const fltx4& a, const fltx4& b) +{ + return _mm_max_ps(a, b); +} + + + +FORCEINLINE fltx4 CeilSIMD(const fltx4& a) +{ + fltx4 retVal; + SubFloat(retVal, 0) = ceil(SubFloat(a, 0)); + SubFloat(retVal, 1) = ceil(SubFloat(a, 1)); + SubFloat(retVal, 2) = ceil(SubFloat(a, 2)); + SubFloat(retVal, 3) = ceil(SubFloat(a, 3)); + return retVal; + +} + +fltx4 AbsSIMD(const fltx4& x); +fltx4 fabs(const fltx4& x); + +FORCEINLINE fltx4 FloorSIMD(const fltx4& val) +{ + fltx4 fl4Abs = fabs(val); + fltx4 ival = SubSIMD(AddSIMD(fl4Abs, Four_2ToThe23s), Four_2ToThe23s); + ival = MaskedAssign(CmpGtSIMD(ival, fl4Abs), SubSIMD(ival, Four_Ones), ival); + return XorSIMD(ival, XorSIMD(val, fl4Abs)); +} + + + +FORCEINLINE bool IsAnyZeros(const fltx4& a) +{ + return TestSignSIMD(CmpEqSIMD(a, Four_Zeros)) != 0; +} + +inline bool IsAllZeros(const fltx4& var) +{ + return TestSignSIMD(CmpEqSIMD(var, Four_Zeros)) == 0xF; +} + +FORCEINLINE fltx4 SqrtEstSIMD(const fltx4& a) +{ + return _mm_sqrt_ps(a); +} + +FORCEINLINE fltx4 SqrtSIMD(const fltx4& a) +{ + return _mm_sqrt_ps(a); +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSIMD(const fltx4& a) +{ + return _mm_rsqrt_ps(a); +} + +FORCEINLINE fltx4 ReciprocalSqrtEstSaturateSIMD(const fltx4& a) +{ + fltx4 zero_mask = CmpEqSIMD(a, Four_Zeros); + fltx4 ret = OrSIMD(a, AndSIMD(Four_Epsilons, zero_mask)); + ret = ReciprocalSqrtEstSIMD(ret); + return ret; +} + +FORCEINLINE fltx4 ReciprocalSqrtSIMD(const fltx4& a) +{ + fltx4 guess = ReciprocalSqrtEstSIMD(a); + guess = MulSIMD(guess, SubSIMD(Four_Threes, MulSIMD(a, MulSIMD(guess, guess)))); + guess = MulSIMD(Four_PointFives, guess); + return guess; +} + +FORCEINLINE fltx4 ReciprocalEstSIMD(const fltx4& a) +{ + return _mm_rcp_ps(a); +} + +FORCEINLINE fltx4 ReciprocalEstSaturateSIMD(const fltx4& a) +{ + fltx4 zero_mask = CmpEqSIMD(a, Four_Zeros); + fltx4 ret = OrSIMD(a, AndSIMD(Four_Epsilons, zero_mask)); + ret = ReciprocalEstSIMD(ret); + return ret; +} + +FORCEINLINE fltx4 ReciprocalSIMD(const fltx4& a) +{ + fltx4 ret = ReciprocalEstSIMD(a); + ret = SubSIMD(AddSIMD(ret, ret), MulSIMD(a, MulSIMD(ret, ret))); + return ret; +} + +FORCEINLINE fltx4 ReciprocalSaturateSIMD(const fltx4& a) +{ + fltx4 zero_mask = CmpEqSIMD(a, Four_Zeros); + fltx4 ret = OrSIMD(a, AndSIMD(Four_Epsilons, zero_mask)); + ret = ReciprocalSIMD(ret); + return ret; +} + +FORCEINLINE fltx4 ExpSIMD(const fltx4& toPower) +{ + fltx4 retval; + SubFloat(retval, 0) = powf(2, SubFloat(toPower, 0)); + SubFloat(retval, 1) = powf(2, SubFloat(toPower, 1)); + SubFloat(retval, 2) = powf(2, SubFloat(toPower, 2)); + SubFloat(retval, 3) = powf(2, SubFloat(toPower, 3)); + + return retval; +} + +FORCEINLINE fltx4 ClampVectorSIMD(FLTX4 in, FLTX4 min, FLTX4 max) +{ + return MaxSIMD(min, MinSIMD(max, in)); +} + +FORCEINLINE void TransposeSIMD(fltx4& x, fltx4& y, fltx4& z, fltx4& w) +{ + _MM_TRANSPOSE4_PS(x, y, z, w); +} + +FORCEINLINE fltx4 FindLowestSIMD3(const fltx4& a) +{ + fltx4 compareOne = RotateLeft(a); + fltx4 retval = MinSIMD(a, compareOne); + compareOne = RotateLeft2(a); + retval = MinSIMD(retval, compareOne); + return SplatXSIMD(retval); + +} + +FORCEINLINE fltx4 FindHighestSIMD3(const fltx4& a) +{ + fltx4 compareOne = RotateLeft(a); + fltx4 retval = MaxSIMD(a, compareOne); + compareOne = RotateLeft2(a); + retval = MaxSIMD(retval, compareOne); + return SplatXSIMD(retval); + +} + + +inline bool IsVector3LessThan(const fltx4& v1, const fltx4& v2) +{ + bi32x4 isOut = CmpLtSIMD(v1, v2); + return IsAnyNegative(isOut); +} + +inline bool IsVector4LessThan(const fltx4& v1, const fltx4& v2) +{ + bi32x4 isOut = CmpLtSIMD(v1, v2); + return IsAnyNegative(isOut); +} + + + +#if 0 +FORCEINLINE fltx4 IntSetImmediateSIMD(int to) +{ + fltx4 retval; + SubInt(retval, 0) = to; + SubInt(retval, 1) = to; + SubInt(retval, 2) = to; + SubInt(retval, 3) = to; + return retval; +} +#endif + +FORCEINLINE i32x4 LoadAlignedIntSIMD(const void* RESTRICT pSIMD) +{ + return _mm_load_ps(reinterpret_cast(pSIMD)); +} + +FORCEINLINE i32x4 LoadUnalignedIntSIMD(const void* RESTRICT pSIMD) +{ + return _mm_loadu_ps(reinterpret_cast(pSIMD)); +} + +FORCEINLINE void StoreAlignedIntSIMD(int32* RESTRICT pSIMD, const fltx4& a) +{ + _mm_store_ps(reinterpret_cast(pSIMD), a); +} + +FORCEINLINE void StoreAlignedIntSIMD(intx4& pSIMD, const fltx4& a) +{ + _mm_store_ps(reinterpret_cast(pSIMD.Base()), a); +} + +FORCEINLINE void StoreUnalignedIntSIMD(int32* RESTRICT pSIMD, const fltx4& a) +{ + _mm_storeu_ps(reinterpret_cast(pSIMD), a); +} + +FORCEINLINE fltx4 CompressSIMD(fltx4 const& a, fltx4 const& b) +{ + return _mm_shuffle_ps(a, b, MM_SHUFFLE_REV(0, 2, 0, 2)); +} + +FORCEINLINE fltx4 LoadAndConvertUint16SIMD(const uint16* pInts) +{ +#ifdef POSIX + fltx4 retval; + SubFloat(retval, 0) = pInts[0]; + SubFloat(retval, 1) = pInts[1]; + SubFloat(retval, 2) = pInts[2]; + SubFloat(retval, 3) = pInts[3]; + return retval; +#else + __m128i inA = _mm_loadl_epi64((__m128i const*) pInts); + inA = _mm_unpacklo_epi16(inA, _mm_setzero_si128()); + return _mm_cvtepi32_ps(inA); +#endif +} + + +FORCEINLINE fltx4 Compress4SIMD(fltx4 const a, fltx4 const& b, fltx4 const& c, fltx4 const& d) +{ + fltx4 aacc = _mm_shuffle_ps(a, c, MM_SHUFFLE_REV(0, 0, 0, 0)); + fltx4 bbdd = _mm_shuffle_ps(b, d, MM_SHUFFLE_REV(0, 0, 0, 0)); + return MaskedAssign(LoadAlignedSIMD(g_SIMD_EveryOtherMask), bbdd, aacc); +} + +FORCEINLINE void ExpandSIMD(fltx4 const& a, fltx4& fl4OutA, fltx4& fl4OutB) +{ + fl4OutA = _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(0, 0, 1, 1)); + fl4OutB = _mm_shuffle_ps(a, a, MM_SHUFFLE_REV(2, 2, 3, 3)); + +} + + +FORCEINLINE fltx4 LoadGatherSIMD(const float& x, const float& y, const float& z, const float& w) +{ + fltx4 vx = _mm_load_ss(&x); + fltx4 vy = _mm_load_ss(&y); + fltx4 vz = _mm_load_ss(&z); + fltx4 vw = _mm_load_ss(&w); + return Compress4SIMD(vx, vy, vz, vw); +} + +FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD(const u32x4& vSrcA) +{ + fltx4 retval; + SubFloat(retval, 0) = ((float)SubInt(retval, 0)); + SubFloat(retval, 1) = ((float)SubInt(retval, 1)); + SubFloat(retval, 2) = ((float)SubInt(retval, 2)); + SubFloat(retval, 3) = ((float)SubInt(retval, 3)); + return retval; +} + +FORCEINLINE fltx4 SignedIntConvertToFltSIMD(const i32x4& vSrcA) +{ + return _mm_cvtepi32_ps((const __m128i&)vSrcA); +} + +FORCEINLINE fltx4 SignedIntConvertToFltSIMD(const shortx8& vSrcA) +{ + return _mm_cvtepi32_ps(vSrcA); +} + +#if 0 +FORCEINLINE fltx4 SignedIntConvertToFltSIMD(const i32x4& vSrcA) +{ + fltx4 retval; + SubFloat(retval, 0) = ((float)(reinterpret_cast(&vSrcA)[0])); + SubFloat(retval, 1) = ((float)(reinterpret_cast(&vSrcA)[1])); + SubFloat(retval, 2) = ((float)(reinterpret_cast(&vSrcA)[2])); + SubFloat(retval, 3) = ((float)(reinterpret_cast(&vSrcA)[3])); + return retval; +} + +#endif + +FORCEINLINE i32x4 IntShiftLeftWordSIMD(const i32x4& vSrcA, const i32x4& vSrcB) +{ + i32x4 retval; + SubInt(retval, 0) = SubInt(vSrcA, 0) << SubInt(vSrcB, 0); + SubInt(retval, 1) = SubInt(vSrcA, 1) << SubInt(vSrcB, 1); + SubInt(retval, 2) = SubInt(vSrcA, 2) << SubInt(vSrcB, 2); + SubInt(retval, 3) = SubInt(vSrcA, 3) << SubInt(vSrcB, 3); + + + return retval; +} + + +FORCEINLINE void ConvertStoreAsIntsSIMD(intx4* RESTRICT pDest, const fltx4& vSrc) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1900 && defined(COMPILER_MSVC64) + (*pDest)[0] = (int)SubFloat(vSrc, 0); + (*pDest)[1] = (int)SubFloat(vSrc, 1); + (*pDest)[2] = (int)SubFloat(vSrc, 2); + (*pDest)[3] = (int)SubFloat(vSrc, 3); +#else + __m64 bottom = _mm_cvttps_pi32(vSrc); + __m64 top = _mm_cvttps_pi32(_mm_movehl_ps(vSrc, vSrc)); + + *reinterpret_cast<__m64*>(&(*pDest)[0]) = bottom; + *reinterpret_cast<__m64*>(&(*pDest)[2]) = top; + + _mm_empty(); +#endif +} + + + +#endif + +FORCEINLINE void RotateLeftDoubleSIMD(fltx4& a, fltx4& b) +{ + a = SetWSIMD(RotateLeft(a), SplatXSIMD(b)); + b = RotateLeft(b); +} + + +#if !defined(PLATFORM_PPC) && !defined( POSIX ) && !defined(SPU) +#if 1 +FORCEINLINE fltx4 operator+(FLTX4 a, FLTX4 b) +{ + return AddSIMD(a, b); +} + +FORCEINLINE fltx4 operator-(FLTX4 a, FLTX4 b) +{ + return SubSIMD(a, b); +} + +FORCEINLINE fltx4 operator*(FLTX4 a, FLTX4 b) +{ + return MulSIMD(a, b); +} + +FORCEINLINE fltx4 operator&(FLTX4 a, FLTX4 b) +{ + return AndSIMD(a, b); +} + +FORCEINLINE fltx4 operator|(FLTX4 a, FLTX4 b) +{ + return OrSIMD(a, b); +} + +FORCEINLINE fltx4 operator^(FLTX4 a, FLTX4 b) +{ + return XorSIMD(a, b); +} + +FORCEINLINE fltx4 operator-(FLTX4 a) +{ + return NegSIMD(a); +} +#endif +#endif + +#if defined(_X360) || defined(_PS3) +FORCEINLINE fltx4 VectorMergeHighSIMD(fltx4 fl4SrcA, fltx4 fl4SrcB) +{ +#if defined( _X360 ) + return __vmrghw(fl4SrcA, fl4SrcB); +#else + return vec_mergeh(fl4SrcA, fl4SrcB); +#endif +} + +FORCEINLINE fltx4 VectorMergeLowSIMD(fltx4 fl4SrcA, fltx4 fl4SrcB) +{ +#if defined( _X360 ) + return __vmrglw(fl4SrcA, fl4SrcB); +#else + return vec_mergel(fl4SrcA, fl4SrcB); +#endif +} +#endif + +#ifndef SPU +struct ALIGN16 fourplanes_t +{ + fltx4 nX; + fltx4 nY; + fltx4 nZ; + fltx4 dist; + bi32x4 xSign; + bi32x4 ySign; + bi32x4 zSign; + fltx4 nXAbs; + fltx4 nYAbs; + fltx4 nZAbs; + + void ComputeSignbits(); + + void Set4Planes(const VPlane* pPlanes); + void Set2Planes(const VPlane* pPlanes); + void Get4Planes(VPlane* pPlanesOut) const; + void Get2Planes(VPlane* pPlanesOut) const; + void GetPlane(int index, Vector* pNormal, float* pDist) const; + void SetPlane(int index, const Vector& vecNormal, float planeDist); +}; + +class ALIGN16 Frustum_t +{ +public: + Frustum_t(); + void SetPlane(int i, const Vector& vecNormal, float dist); + void GetPlane(int i, Vector* pNormalOut, float* pDistOut) const; + void SetPlanes(const VPlane* pPlanes); + void GetPlanes(VPlane* pPlanesOut) const; + bool CullBox(const Vector& mins, const Vector& maxs) const; + bool CullBoxCenterExtents(const Vector& center, const Vector& extents) const; + + bool CullBox(const fltx4& fl4Mins, const fltx4& fl4Maxs) const; + bool CullBoxCenterExtents(const fltx4& fl4Center, const fltx4& fl4Extents) const; + + + bool Contains(const Vector& mins, const Vector& maxs) const; + + bool Intersects(Frustum_t& otherFrustum) const; + + bool Intersects(const Vector& mins, const Vector& maxs) const; + bool IntersectsCenterExtents(const Vector& center, const Vector& extents) const; + + bool Intersects(const fltx4& fl4Mins, const fltx4& fl4Maxs) const; + bool IntersectsCenterExtents(const fltx4& fl4Center, const fltx4& fl4Extents) const; + + + void CreatePerspectiveFrustum(const Vector& origin, const Vector& forward, + const Vector& right, const Vector& up, float flZNear, float flZFar, + float flFovX, float flAspect); + + void CreatePerspectiveFrustumFLU(const Vector& vOrigin, const Vector& vForward, + const Vector& vLeft, const Vector& vUp, float flZNear, float flZFar, + float flFovX, float flAspect); + + void CreatePerspectiveFrustum(const Vector& origin, const QAngle& angles, float flZNear, + float flZFar, float flFovX, float flAspectRatio); + + void CreateOrthoFrustum(const Vector& origin, const Vector& forward, const Vector& right, const Vector& up, + float flLeft, float flRight, float flBottom, float flTop, float flZNear, float flZFar); + + void CreateOrthoFrustumFLU(const Vector& vOrigin, const Vector& vForward, const Vector& vLeft, const Vector& vUp, + float flLeft, float flRight, float flBottom, float flTop, float flZNear, float flZFar); + + bool GetCorners(Vector* pPoints) const; + + fourplanes_t planes[2]; +}; + +#endif + +class FourQuaternions; +class ALIGN16 FourVectors +{ +public: + fltx4 x, y, z; + + FourVectors(void) + { + } + + FourVectors(FourVectors const& src) + { + x = src.x; + y = src.y; + z = src.z; + } + + explicit FORCEINLINE FourVectors(float a) + { + fltx4 aReplicated = ReplicateX4(a); + x = y = z = aReplicated; + } + + FORCEINLINE void Init(void) + { + x = Four_Zeros; + y = Four_Zeros; + z = Four_Zeros; + } + + FORCEINLINE void Init(float flX, float flY, float flZ) + { + x = ReplicateX4(flX); + y = ReplicateX4(flY); + z = ReplicateX4(flZ); + } + + FORCEINLINE FourVectors(float flX, float flY, float flZ) + { + Init(flX, flY, flZ); + } + + FORCEINLINE void Init(fltx4 const& fl4X, fltx4 const& fl4Y, fltx4 const& fl4Z) + { + x = fl4X; + y = fl4Y; + z = fl4Z; + } + + FORCEINLINE FourVectors(fltx4 const& fl4X, fltx4 const& fl4Y, fltx4 const& fl4Z) + { + Init(fl4X, fl4Y, fl4Z); + } + + + + FORCEINLINE FourVectors(Vector const& a, Vector const& b, Vector const& c, Vector const& d) + { + LoadAndSwizzle(a, b, c, d); + } + + FORCEINLINE FourVectors(VectorAligned const& a, VectorAligned const& b, VectorAligned const& c, VectorAligned const& d) + { + LoadAndSwizzleAligned(a, b, c, d); + } + + FORCEINLINE FourVectors(const float* xs, const float* ys, const float* zs) : + x(LoadAlignedSIMD(xs)), y(LoadAlignedSIMD(ys)), z(LoadAlignedSIMD(zs)) + {}; + + FORCEINLINE void DuplicateVector(Vector const& v) + { + x = ReplicateX4(v.x); + y = ReplicateX4(v.y); + z = ReplicateX4(v.z); + } + + FORCEINLINE fltx4 const& operator[](int idx) const + { + return *((&x) + idx); + } + + FORCEINLINE fltx4& operator[](int idx) + { + return *((&x) + idx); + } + + FORCEINLINE void operator+=(FourVectors const& b) + { + x = AddSIMD(x, b.x); + y = AddSIMD(y, b.y); + z = AddSIMD(z, b.z); + } + + FORCEINLINE void operator-=(FourVectors const& b) + { + x = SubSIMD(x, b.x); + y = SubSIMD(y, b.y); + z = SubSIMD(z, b.z); + } + + FORCEINLINE void operator*=(FourVectors const& b) + { + x = MulSIMD(x, b.x); + y = MulSIMD(y, b.y); + z = MulSIMD(z, b.z); + } + + FORCEINLINE void operator*=(const fltx4& scale) + { + x = MulSIMD(x, scale); + y = MulSIMD(y, scale); + z = MulSIMD(z, scale); + } + + FORCEINLINE void operator*=(float scale) + { + fltx4 scalepacked = ReplicateX4(scale); + *this *= scalepacked; + } + + FORCEINLINE fltx4 operator*(FourVectors const& b) const + { + fltx4 dot = MulSIMD(x, b.x); + dot = MaddSIMD(y, b.y, dot); + dot = MaddSIMD(z, b.z, dot); + return dot; + } + + FORCEINLINE fltx4 operator*(Vector const& b) const + { + fltx4 dot = MulSIMD(x, ReplicateX4(b.x)); + dot = MaddSIMD(y, ReplicateX4(b.y), dot); + dot = MaddSIMD(z, ReplicateX4(b.z), dot); + return dot; + } + + FORCEINLINE FourVectors operator*(float b) const + { + fltx4 scalepacked = ReplicateX4(b); + FourVectors res; + res.x = MulSIMD(x, scalepacked); + res.y = MulSIMD(y, scalepacked); + res.z = MulSIMD(z, scalepacked); + return res; + } + + FORCEINLINE FourVectors operator*(FLTX4 fl4Scale) const + { + FourVectors res; + res.x = MulSIMD(x, fl4Scale); + res.y = MulSIMD(y, fl4Scale); + res.z = MulSIMD(z, fl4Scale); + return res; + } + + FORCEINLINE void VProduct(FourVectors const& b) + { + x = MulSIMD(x, b.x); + y = MulSIMD(y, b.y); + z = MulSIMD(z, b.z); + } + FORCEINLINE void MakeReciprocal(void) + { + x = ReciprocalSIMD(x); + y = ReciprocalSIMD(y); + z = ReciprocalSIMD(z); + } + + FORCEINLINE void MakeReciprocalSaturate(void) + { + x = ReciprocalSaturateSIMD(x); + y = ReciprocalSaturateSIMD(y); + z = ReciprocalSaturateSIMD(z); + } + + inline void RotateBy(const matrix3x4_t& matrix); + static void RotateManyBy(FourVectors* RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& rotationMatrix); + + static void RotateManyBy(FourVectors* RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& rotationMatrix, FourVectors* RESTRICT pOut); + + inline void TransformBy(const matrix3x4_t& matrix); + + static void TransformManyBy(FourVectors* RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& rotationMatrix, FourVectors* RESTRICT pOut); + + static void TransformManyBy(FourVectors* RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& rotationMatrix); + + static void CalcClosestPointOnLineSIMD(const FourVectors& P, const FourVectors& vLineA, const FourVectors& vLineB, FourVectors& vClosest, fltx4* outT = 0); + static fltx4 CalcClosestPointToLineTSIMD(const FourVectors& P, const FourVectors& vLineA, const FourVectors& vLineB, FourVectors& vDir); + + FORCEINLINE const float& X(int idx) const + { + return SubFloat((fltx4&)x, idx); + } + + FORCEINLINE const float& Y(int idx) const + { + return SubFloat((fltx4&)y, idx); + } + + FORCEINLINE const float& Z(int idx) const + { + return SubFloat((fltx4&)z, idx); + } + + FORCEINLINE float& X(int idx) + { + return SubFloat(x, idx); + } + + FORCEINLINE float& Y(int idx) + { + return SubFloat(y, idx); + } + + FORCEINLINE float& Z(int idx) + { + return SubFloat(z, idx); + } + + FORCEINLINE Vector Vec(int idx) const + { + return Vector(X(idx), Y(idx), Z(idx)); + } + + FORCEINLINE void operator=(FourVectors const& src) + { + x = src.x; + y = src.y; + z = src.z; + } + + FORCEINLINE void LoadAndSwizzle(Vector const& a, Vector const& b, Vector const& c, Vector const& d) + { +#if defined( _X360 ) || defined(_PS3) + fltx4 tx = LoadUnalignedSIMD(&a.x); + fltx4 ty = LoadUnalignedSIMD(&b.x); + fltx4 tz = LoadUnalignedSIMD(&c.x); + fltx4 tw = LoadUnalignedSIMD(&d.x); + fltx4 r0 = VectorMergeHighSIMD(tx, tz); + fltx4 r1 = VectorMergeHighSIMD(ty, tw); + fltx4 r2 = VectorMergeLowSIMD(tx, tz); + fltx4 r3 = VectorMergeLowSIMD(ty, tw); + + x = VectorMergeHighSIMD(r0, r1); + y = VectorMergeLowSIMD(r0, r1); + z = VectorMergeHighSIMD(r2, r3); +#else + x = LoadUnalignedSIMD(&(a.x)); + y = LoadUnalignedSIMD(&(b.x)); + z = LoadUnalignedSIMD(&(c.x)); + fltx4 w = LoadUnalignedSIMD(&(d.x)); + TransposeSIMD(x, y, z, w); +#endif + } + + FORCEINLINE void LoadAndSwizzle(Vector const& a) + { + LoadAndSwizzle(a, a, a, a); + } + + FORCEINLINE void Load(const float& a, const float& b, const float& c, const float& d) + { +#if defined( _X360 ) || defined( _PS3 ) + fltx4 temp[4]; + temp[0] = LoadUnalignedFloatSIMD(&a); + temp[1] = LoadUnalignedFloatSIMD(&b); + temp[2] = LoadUnalignedFloatSIMD(&c); + temp[3] = LoadUnalignedFloatSIMD(&d); + y = VectorMergeHighSIMD(temp[0], temp[2]); + z = VectorMergeHighSIMD(temp[1], temp[3]); + + x = VectorMergeHighSIMD(y, z); + y = x; + z = x; +#else + ALIGN16 float temp[4]; + temp[0] = a; temp[1] = b; temp[2] = c; temp[3] = d; + fltx4 v = LoadAlignedSIMD(temp); + x = v; + y = v; + z = v; +#endif + } + + FORCEINLINE void LoadAndSwizzle(FLTX4 a, FLTX4 b, FLTX4 c, FLTX4 d) + { +#if defined( _X360 ) || defined( _PS3 ) + fltx4 tx = a; + fltx4 ty = b; + fltx4 tz = c; + fltx4 tw = d; + fltx4 r0 = VectorMergeHighSIMD(tx, tz); + fltx4 r1 = VectorMergeHighSIMD(ty, tw); + fltx4 r2 = VectorMergeLowSIMD(tx, tz); + fltx4 r3 = VectorMergeLowSIMD(ty, tw); + + x = VectorMergeHighSIMD(r0, r1); + y = VectorMergeLowSIMD(r0, r1); + z = VectorMergeHighSIMD(r2, r3); +#else + x = a; + y = b; + z = c; + fltx4 w = d; + TransposeSIMD(x, y, z, w); +#endif + } + + FORCEINLINE void LoadAndSwizzleAligned(const float* RESTRICT a, const float* RESTRICT b, const float* RESTRICT c, const float* RESTRICT d) + { +#if defined( _X360 ) || defined( _PS3 ) + fltx4 tx = LoadAlignedSIMD(a); + fltx4 ty = LoadAlignedSIMD(b); + fltx4 tz = LoadAlignedSIMD(c); + fltx4 tw = LoadAlignedSIMD(d); + fltx4 r0 = VectorMergeHighSIMD(tx, tz); + fltx4 r1 = VectorMergeHighSIMD(ty, tw); + fltx4 r2 = VectorMergeLowSIMD(tx, tz); + fltx4 r3 = VectorMergeLowSIMD(ty, tw); + + x = VectorMergeHighSIMD(r0, r1); + y = VectorMergeLowSIMD(r0, r1); + z = VectorMergeHighSIMD(r2, r3); +#else + x = LoadAlignedSIMD(a); + y = LoadAlignedSIMD(b); + z = LoadAlignedSIMD(c); + fltx4 w = LoadAlignedSIMD(d); + TransposeSIMD(x, y, z, w); +#endif + } + + FORCEINLINE void LoadAndSwizzleAligned(Vector const& a, Vector const& b, Vector const& c, Vector const& d) + { + LoadAndSwizzleAligned(&a.x, &b.x, &c.x, &d.x); + } + + FORCEINLINE void TransposeOnto(fltx4& out0, fltx4& out1, fltx4& out2, fltx4& out3, FLTX4 w = Four_Zeros) const + { +#if defined( _X360 ) || defined(_PS3) + fltx4 r0 = VectorMergeHighSIMD(x, z); + fltx4 r1 = VectorMergeHighSIMD(y, w); + fltx4 r2 = VectorMergeLowSIMD(x, z); + fltx4 r3 = VectorMergeLowSIMD(y, w); + + out0 = VectorMergeHighSIMD(r0, r1); + out1 = VectorMergeLowSIMD(r0, r1); + out2 = VectorMergeHighSIMD(r2, r3); + out3 = VectorMergeLowSIMD(r2, r3); +#else + out0 = x; + out1 = y; + out2 = z; + out3 = w; + + TransposeSIMD(out0, out1, out2, out3); +#endif + } + +#if !defined(__SPU__) + FORCEINLINE void StoreUnalignedVector3SIMD(Vector* RESTRICT out0, Vector* RESTRICT out1, Vector* RESTRICT out2, Vector* RESTRICT out3) const; +#endif + + FORCEINLINE void StoreAlignedVectorSIMD(VectorAligned* RESTRICT out0, VectorAligned* RESTRICT out1, VectorAligned* RESTRICT out2, VectorAligned* RESTRICT out3) const; + +#if !defined(__SPU__) + FORCEINLINE void StoreUnalignedContigVector3SIMD(Vector* RESTRICT pDestination) + { + fltx4 a, b, c, d; + TransposeOnto(a, b, c, d); + StoreFourUnalignedVector3SIMD(a, b, c, d, pDestination); + } +#endif + +#if !defined(__SPU__) + FORCEINLINE void StoreAlignedContigVector3SIMD(Vector* RESTRICT pDestination) + { + fltx4 a, b, c, d; + TransposeOnto(a, b, c, d); + StoreFourAlignedVector3SIMD(a, b, c, d, pDestination); + } + + FORCEINLINE void StoreAlignedContigVectorASIMD(VectorAligned* RESTRICT pDestination) + { + StoreAlignedVectorSIMD(pDestination, pDestination + 1, pDestination + 2, pDestination + 3); + } +#endif + + FORCEINLINE fltx4 LengthSqr(void) const + { + const FourVectors& a = *this; + return a * a; + } + + FORCEINLINE fltx4 length2(void) const + { + return (*this) * (*this); + } + + FORCEINLINE fltx4 length(void) const + { + return SqrtEstSIMD(length2()); + } + + FORCEINLINE fltx4 Length(void) const + { + return SqrtSIMD(length2()); + } + + + FORCEINLINE void VectorNormalizeFast(void) + { + fltx4 mag_sq = (*this) * (*this); + (*this) *= ReciprocalSqrtEstSIMD(mag_sq); + } + + FORCEINLINE void VectorNormalize(void) + { + fltx4 mag_sq = (*this) * (*this); + (*this) *= ReciprocalSqrtSIMD(mag_sq); + } + + FORCEINLINE fltx4 DistToSqr(FourVectors const& pnt) + { + fltx4 fl4dX = SubSIMD(pnt.x, x); + fltx4 fl4dY = SubSIMD(pnt.y, y); + fltx4 fl4dZ = SubSIMD(pnt.z, z); + return AddSIMD(MulSIMD(fl4dX, fl4dX), AddSIMD(MulSIMD(fl4dY, fl4dY), MulSIMD(fl4dZ, fl4dZ))); + + } + + FORCEINLINE fltx4 TValueOfClosestPointOnLine(FourVectors const& p0, FourVectors const& p1) const + { + FourVectors lineDelta = p1; + lineDelta -= p0; + fltx4 OOlineDirDotlineDir = ReciprocalSIMD(p1 * p1); + FourVectors v4OurPnt = *this; + v4OurPnt -= p0; + return MulSIMD(OOlineDirDotlineDir, v4OurPnt * lineDelta); + } + + FORCEINLINE fltx4 DistSqrToLineSegment(FourVectors const& p0, FourVectors const& p1) const + { + FourVectors lineDelta = p1; + FourVectors v4OurPnt = *this; + v4OurPnt -= p0; + lineDelta -= p0; + + fltx4 OOlineDirDotlineDir = ReciprocalSIMD(lineDelta * lineDelta); + + fltx4 fl4T = MulSIMD(OOlineDirDotlineDir, v4OurPnt * lineDelta); + + fl4T = MinSIMD(fl4T, Four_Ones); + fl4T = MaxSIMD(fl4T, Four_Zeros); + lineDelta *= fl4T; + return v4OurPnt.DistToSqr(lineDelta); + } + FORCEINLINE FourVectors Normalized()const + { + fltx4 fl4LengthInv = ReciprocalSqrtSIMD(LengthSqr()); + FourVectors out; + out.x = x * fl4LengthInv; + out.y = y * fl4LengthInv; + out.z = z * fl4LengthInv; + return out; + } + + FORCEINLINE FourVectors NormalizedSafeX() const + { + fltx4 f4LenSqr = LengthSqr(); + fltx4 isBigEnough = CmpGeSIMD(f4LenSqr, Four_Epsilons); + fltx4 fl4LengthInv = ReciprocalSqrtSIMD(f4LenSqr); + FourVectors out; + out.x = MaskedAssign(isBigEnough, x * fl4LengthInv, Four_Ones); + out.y = AndSIMD(y * fl4LengthInv, isBigEnough); + out.z = AndSIMD(z * fl4LengthInv, isBigEnough); + return out; + } + FORCEINLINE FourVectors NormalizedSafeY() const + { + fltx4 f4LenSqr = LengthSqr(); + fltx4 isBigEnough = CmpGeSIMD(f4LenSqr, Four_Epsilons); + fltx4 fl4LengthInv = ReciprocalSqrtSIMD(f4LenSqr); + FourVectors out; + out.x = AndSIMD(x * fl4LengthInv, isBigEnough); + out.y = MaskedAssign(isBigEnough, y * fl4LengthInv, Four_Ones); + out.z = AndSIMD(z * fl4LengthInv, isBigEnough); + return out; + } + + FORCEINLINE FourVectors NormalizedSafeZ() const + { + fltx4 f4LenSqr = LengthSqr(); + fltx4 isBigEnough = CmpGeSIMD(f4LenSqr, Four_Epsilons); + fltx4 fl4LengthInv = ReciprocalSqrtSIMD(f4LenSqr); + FourVectors out; + out.x = AndSIMD(x * fl4LengthInv, isBigEnough); + out.y = AndSIMD(y * fl4LengthInv, isBigEnough); + out.z = MaskedAssign(isBigEnough, z * fl4LengthInv, Four_Ones); + return out; + } +}; + + +inline FourVectors CrossProduct(const FourVectors& a, const FourVectors& b) +{ + return FourVectors(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); +} + +inline fltx4 DotProduct(const FourVectors& a, const FourVectors& b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +inline FourVectors operator * (fltx4 left, const FourVectors& right) +{ + return right * left; +} + + +inline FourVectors Mul(const FourVectors& a, const fltx4& b) +{ + FourVectors ret; + ret.x = MulSIMD(a.x, b); + ret.y = MulSIMD(a.y, b); + ret.z = MulSIMD(a.z, b); + return ret; +} + +inline FourVectors Mul(const FourVectors& a, const FourVectors& b) +{ + FourVectors ret; + ret.x = MulSIMD(a.x, b.x); + ret.y = MulSIMD(a.y, b.y); + ret.z = MulSIMD(a.z, b.z); + return ret; +} + +inline FourVectors Madd(const FourVectors& a, const fltx4& b, const FourVectors& c) +{ + FourVectors ret; + ret.x = MaddSIMD(a.x, b, c.x); + ret.y = MaddSIMD(a.y, b, c.y); + ret.z = MaddSIMD(a.z, b, c.z); + return ret; +} + +inline FourVectors operator ^(const FourVectors& a, const FourVectors& b) +{ + FourVectors ret; + ret.x = SubSIMD(MulSIMD(a.y, b.z), MulSIMD(a.z, b.y)); + ret.y = SubSIMD(MulSIMD(a.z, b.x), MulSIMD(a.x, b.z)); + ret.z = SubSIMD(MulSIMD(a.x, b.y), MulSIMD(a.y, b.x)); + return ret; +} + +inline FourVectors operator-(const FourVectors& a, const FourVectors& b) +{ + FourVectors ret; + ret.x = SubSIMD(a.x, b.x); + ret.y = SubSIMD(a.y, b.y); + ret.z = SubSIMD(a.z, b.z); + return ret; +} + +inline FourVectors operator+(const FourVectors& a, const FourVectors& b) +{ + FourVectors ret; + ret.x = AddSIMD(a.x, b.x); + ret.y = AddSIMD(a.y, b.y); + ret.z = AddSIMD(a.z, b.z); + return ret; +} + +inline FourVectors maximum(const FourVectors& a, const FourVectors& b) +{ + FourVectors ret; + ret.x = MaxSIMD(a.x, b.x); + ret.y = MaxSIMD(a.y, b.y); + ret.z = MaxSIMD(a.z, b.z); + return ret; +} + +inline FourVectors minimum(const FourVectors& a, const FourVectors& b) +{ + FourVectors ret; + ret.x = MinSIMD(a.x, b.x); + ret.y = MinSIMD(a.y, b.y); + ret.z = MinSIMD(a.z, b.z); + return ret; +} + +FORCEINLINE FourVectors RotateLeft(const FourVectors& src) +{ + FourVectors ret; + ret.x = RotateLeft(src.x); + ret.y = RotateLeft(src.y); + ret.z = RotateLeft(src.z); + return ret; +} + +FORCEINLINE FourVectors RotateRight(const FourVectors& src) +{ + FourVectors ret; + ret.x = RotateRight(src.x); + ret.y = RotateRight(src.y); + ret.z = RotateRight(src.z); + return ret; +} +FORCEINLINE FourVectors MaskedAssign(const bi32x4& ReplacementMask, const FourVectors& NewValue, const FourVectors& OldValue) +{ + FourVectors ret; + ret.x = MaskedAssign(ReplacementMask, NewValue.x, OldValue.x); + ret.y = MaskedAssign(ReplacementMask, NewValue.y, OldValue.y); + ret.z = MaskedAssign(ReplacementMask, NewValue.z, OldValue.z); + return ret; +} + +FORCEINLINE FourVectors VectorReflect(const FourVectors& incident, const FourVectors& normal) +{ + FourVectors ret = incident; + fltx4 iDotNx2 = incident * normal; + iDotNx2 = AddSIMD(iDotNx2, iDotNx2); + FourVectors nPart = normal; + nPart *= iDotNx2; + ret -= nPart; + return ret; +} + +FORCEINLINE FourVectors VectorSlide(const FourVectors& incident, const FourVectors& normal) +{ + FourVectors ret = incident; + fltx4 iDotN = incident * normal; + FourVectors nPart = normal; + nPart *= iDotN; + ret -= nPart; + return ret; +} + +FORCEINLINE FourVectors VectorNormalizeFast(const FourVectors& src) +{ + fltx4 mag_sq = ReciprocalSqrtEstSIMD(src * src); + FourVectors result; + result.x = MulSIMD(src.x, mag_sq); + result.y = MulSIMD(src.y, mag_sq); + result.z = MulSIMD(src.z, mag_sq); + return result; +} + +#if !defined(__SPU__) +FORCEINLINE void FourVectors::StoreUnalignedVector3SIMD(Vector* RESTRICT out0, Vector* RESTRICT out1, Vector* RESTRICT out2, Vector* RESTRICT out3) const +{ +#ifdef _X360 + fltx4 x0, x1, x2, x3, y0, y1, y2, y3, z0, z1, z2, z3; + x0 = SplatXSIMD(x); + x1 = SplatYSIMD(x); + x2 = SplatZSIMD(x); + x3 = SplatWSIMD(x); + + y0 = SplatXSIMD(y); + y1 = SplatYSIMD(y); + y2 = SplatZSIMD(y); + y3 = SplatWSIMD(y); + + z0 = SplatXSIMD(z); + z1 = SplatYSIMD(z); + z2 = SplatZSIMD(z); + z3 = SplatWSIMD(z); + + __stvewx(x0, out0->Base(), 0); + __stvewx(y0, out0->Base(), 4); + __stvewx(z0, out0->Base(), 8); + + __stvewx(x1, out1->Base(), 0); + __stvewx(y1, out1->Base(), 4); + __stvewx(z1, out1->Base(), 8); + + __stvewx(x2, out2->Base(), 0); + __stvewx(y2, out2->Base(), 4); + __stvewx(z2, out2->Base(), 8); + + __stvewx(x3, out3->Base(), 0); + __stvewx(y3, out3->Base(), 4); + __stvewx(z3, out3->Base(), 8); +#else + fltx4 a, b, c, d; + TransposeOnto(a, b, c, d); + StoreUnaligned3SIMD(out0->Base(), a); + StoreUnaligned3SIMD(out1->Base(), b); + StoreUnaligned3SIMD(out2->Base(), c); + StoreUnaligned3SIMD(out3->Base(), d); +#endif +} + +FORCEINLINE void FourVectors::StoreAlignedVectorSIMD(VectorAligned* RESTRICT out0, VectorAligned* RESTRICT out1, VectorAligned* RESTRICT out2, VectorAligned* RESTRICT out3) const +{ + fltx4 a, b, c, d; + TransposeOnto(a, b, c, d); + StoreAligned3SIMD(out0, a); + StoreAligned3SIMD(out1, b); + StoreAligned3SIMD(out2, c); + StoreAligned3SIMD(out3, d); + +} +#endif + +#if !defined(__SPU__) +void FourVectors::RotateBy(const matrix3x4_t& matrix) +{ + fltx4 matSplat00, matSplat01, matSplat02, + matSplat10, matSplat11, matSplat12, + matSplat20, matSplat21, matSplat22; + + fltx4 matCol0 = LoadUnalignedSIMD(matrix[0]); + fltx4 matCol1 = LoadUnalignedSIMD(matrix[1]); + fltx4 matCol2 = LoadUnalignedSIMD(matrix[2]); + + matSplat00 = SplatXSIMD(matCol0); + matSplat01 = SplatYSIMD(matCol0); + matSplat02 = SplatZSIMD(matCol0); + + matSplat10 = SplatXSIMD(matCol1); + matSplat11 = SplatYSIMD(matCol1); + matSplat12 = SplatZSIMD(matCol1); + + matSplat20 = SplatXSIMD(matCol2); + matSplat21 = SplatYSIMD(matCol2); + matSplat22 = SplatZSIMD(matCol2); + + fltx4 outX, outY, outZ; + outX = AddSIMD(AddSIMD(MulSIMD(x, matSplat00), MulSIMD(y, matSplat01)), MulSIMD(z, matSplat02)); + outY = AddSIMD(AddSIMD(MulSIMD(x, matSplat10), MulSIMD(y, matSplat11)), MulSIMD(z, matSplat12)); + outZ = AddSIMD(AddSIMD(MulSIMD(x, matSplat20), MulSIMD(y, matSplat21)), MulSIMD(z, matSplat22)); + + x = outX; + y = outY; + z = outZ; +} + + +void FourVectors::TransformBy(const matrix3x4_t& matrix) +{ + fltx4 matSplat00, matSplat01, matSplat02, + matSplat10, matSplat11, matSplat12, + matSplat20, matSplat21, matSplat22; + + fltx4 matCol0 = LoadUnalignedSIMD(matrix[0]); + fltx4 matCol1 = LoadUnalignedSIMD(matrix[1]); + fltx4 matCol2 = LoadUnalignedSIMD(matrix[2]); + + matSplat00 = SplatXSIMD(matCol0); + matSplat01 = SplatYSIMD(matCol0); + matSplat02 = SplatZSIMD(matCol0); + + matSplat10 = SplatXSIMD(matCol1); + matSplat11 = SplatYSIMD(matCol1); + matSplat12 = SplatZSIMD(matCol1); + + matSplat20 = SplatXSIMD(matCol2); + matSplat21 = SplatYSIMD(matCol2); + matSplat22 = SplatZSIMD(matCol2); + + fltx4 outX, outY, outZ; + + outX = MaddSIMD(z, matSplat02, AddSIMD(MulSIMD(x, matSplat00), MulSIMD(y, matSplat01))); + outY = MaddSIMD(z, matSplat12, AddSIMD(MulSIMD(x, matSplat10), MulSIMD(y, matSplat11))); + outZ = MaddSIMD(z, matSplat22, AddSIMD(MulSIMD(x, matSplat20), MulSIMD(y, matSplat21))); + + x = AddSIMD(outX, ReplicateX4(matrix[0][3])); + y = AddSIMD(outY, ReplicateX4(matrix[1][3])); + z = AddSIMD(outZ, ReplicateX4(matrix[2][3])); +} +#endif + +fltx4 NoiseSIMD(FourVectors const& v); + +FourVectors DNoiseSIMD(FourVectors const& v); + +FourVectors CurlNoiseSIMD(FourVectors const& v); + + +fltx4 NoiseSIMD(const fltx4& x, const fltx4& y, const fltx4& z); + + +inline fltx4 fabs(const fltx4& x) +{ + return AndSIMD(x, LoadAlignedSIMD(g_SIMD_clear_signmask)); +} + +inline fltx4 AbsSIMD(const fltx4& x) +{ + return fabs(x); +} + +inline fltx4 fnegate(const fltx4& x) +{ + return XorSIMD(x, LoadAlignedSIMD(g_SIMD_signmask)); +} + +fltx4 Pow_FixedPoint_Exponent_SIMD(const fltx4& x, int exponent); + +inline fltx4 PowSIMD(const fltx4& x, float exponent) +{ + return Pow_FixedPoint_Exponent_SIMD(x, (int)(4.0 * exponent)); +} + +inline fltx4 LinearToGammaSIMD(fltx4 x) +{ + x = MaxSIMD(MinSIMD(Four_Ones, x), Four_Zeros); + return AddSIMD(Four_LinearToGammaCoefficients_E, + MulSIMD(x, AddSIMD(Four_LinearToGammaCoefficients_D, + MulSIMD(x, AddSIMD(Four_LinearToGammaCoefficients_C, + MulSIMD(x, AddSIMD(Four_LinearToGammaCoefficients_B, + MulSIMD(x, Four_LinearToGammaCoefficients_A)))))))); +} + + +inline fltx4 GammaToLinearSIMD(fltx4 x) +{ + x = MaxSIMD(x, Four_Zeros); + x = AddSIMD(Four_GammaToLinearCoefficients_D, + MulSIMD(x, AddSIMD(Four_GammaToLinearCoefficients_C, + MulSIMD(x, AddSIMD(Four_GammaToLinearCoefficients_B, + MulSIMD(x, Four_GammaToLinearCoefficients_A)))))); + return MinSIMD(x, Four_Ones); +} + +inline fltx4 GammaToLinearExtendedSIMD(fltx4 x) +{ + x = MaxSIMD(x, Four_Zeros); + fltx4 fl4Ret = AddSIMD(Four_GammaToLinearCoefficients_D, + MulSIMD(x, AddSIMD(Four_GammaToLinearCoefficients_C, + MulSIMD(x, AddSIMD(Four_GammaToLinearCoefficients_B, + MulSIMD(x, Four_GammaToLinearCoefficients_A)))))); + return MaskedAssign(CmpGeSIMD(x, Four_Ones), x, fl4Ret); +} + +void SeedRandSIMD(uint32 seed); +fltx4 RandSIMD(int nContext = 0); + +int GetSIMDRandContext(void); +void ReleaseSIMDRandContext(int nContext); + +FORCEINLINE fltx4 RandSignedSIMD(void) +{ + return SubSIMD(MulSIMD(Four_Twos, RandSIMD()), Four_Ones); +} + + +FORCEINLINE fltx4 LerpSIMD(const fltx4& percent, const fltx4& a, const fltx4& b) +{ + return AddSIMD(a, MulSIMD(SubSIMD(b, a), percent)); +} + +FORCEINLINE fltx4 RemapValClampedSIMD(const fltx4& val, const fltx4& a, const fltx4& b, const fltx4& c, const fltx4& d) +{ + fltx4 range = MaskedAssign(CmpEqSIMD(a, b), Four_Ones, SubSIMD(b, a)); + fltx4 cVal = MaxSIMD(Four_Zeros, MinSIMD(Four_Ones, DivSIMD(SubSIMD(val, a), range))); + return LerpSIMD(cVal, c, d); +} + +inline fltx4 SimpleSpline(const fltx4& value) +{ + fltx4 valueDoubled = MulSIMD(value, Four_Twos); + fltx4 valueSquared = MulSIMD(value, value); + + return SubSIMD( + MulSIMD(Four_Threes, valueSquared), + MulSIMD(valueDoubled, valueSquared)); +} + +inline fltx4 SimpleSplineRemapValWithDeltas(const fltx4& val, + const fltx4& A, const fltx4& BMinusA, + const fltx4& OneOverBMinusA, const fltx4& C, + const fltx4& DMinusC) +{ + fltx4 cVal = MulSIMD(SubSIMD(val, A), OneOverBMinusA); + return AddSIMD(C, MulSIMD(DMinusC, SimpleSpline(cVal))); +} + +inline fltx4 SimpleSplineRemapValWithDeltasClamped(const fltx4& val, + const fltx4& A, const fltx4& BMinusA, + const fltx4& OneOverBMinusA, const fltx4& C, + const fltx4& DMinusC) +{ + fltx4 cVal = MulSIMD(SubSIMD(val, A), OneOverBMinusA); + cVal = MinSIMD(Four_Ones, MaxSIMD(Four_Zeros, cVal)); + return AddSIMD(C, MulSIMD(DMinusC, SimpleSpline(cVal))); +} + +FORCEINLINE fltx4 FracSIMD(const fltx4& val) +{ + fltx4 fl4Abs = fabs(val); + fltx4 ival = SubSIMD(AddSIMD(fl4Abs, Four_2ToThe23s), Four_2ToThe23s); + ival = MaskedAssign(CmpGtSIMD(ival, fl4Abs), SubSIMD(ival, Four_Ones), ival); + return XorSIMD(SubSIMD(fl4Abs, ival), XorSIMD(val, fl4Abs)); +} + +#ifndef SPU +FORCEINLINE fltx4 Mod2SIMD(const fltx4& val) +{ + fltx4 fl4Abs = fabs(val); + fltx4 ival = SubSIMD(AndSIMD(LoadAlignedSIMD((float*)g_SIMD_lsbmask), AddSIMD(fl4Abs, Four_2ToThe23s)), Four_2ToThe23s); + ival = MaskedAssign(CmpGtSIMD(ival, fl4Abs), SubSIMD(ival, Four_Twos), ival); + return XorSIMD(SubSIMD(fl4Abs, ival), XorSIMD(val, fl4Abs)); +} +#endif + +FORCEINLINE fltx4 Mod2SIMDPositiveInput(const fltx4& val) +{ + fltx4 ival = SubSIMD(AndSIMD(LoadAlignedSIMD(g_SIMD_lsbmask), AddSIMD(val, Four_2ToThe23s)), Four_2ToThe23s); + ival = MaskedAssign(CmpGtSIMD(ival, val), SubSIMD(ival, Four_Twos), ival); + return SubSIMD(val, ival); +} + + +FORCEINLINE fltx4 _SinEst01SIMD(const fltx4& val) +{ + return MulSIMD(val, SubSIMD(Four_Fours, MulSIMD(val, Four_Fours))); +} + +FORCEINLINE fltx4 _Sin01SIMD(const fltx4& val) +{ + fltx4 fl4BadEst = MulSIMD(val, SubSIMD(Four_Fours, MulSIMD(val, Four_Fours))); + return AddSIMD(MulSIMD(Four_Point225s, SubSIMD(MulSIMD(fl4BadEst, fl4BadEst), fl4BadEst)), fl4BadEst); +} + +FORCEINLINE fltx4 SinEst01SIMD(const fltx4& val) +{ + fltx4 fl4Abs = fabs(val); + fltx4 fl4Reduced2 = Mod2SIMDPositiveInput(fl4Abs); + bi32x4 fl4OddMask = CmpGeSIMD(fl4Reduced2, Four_Ones); + fltx4 fl4val = SubSIMD(fl4Reduced2, AndSIMD(Four_Ones, fl4OddMask)); + fltx4 fl4Sin = _SinEst01SIMD(fl4val); + fl4Sin = XorSIMD(fl4Sin, AndSIMD(LoadAlignedSIMD(g_SIMD_signmask), XorSIMD(val, fl4OddMask))); + return fl4Sin; + +} + +FORCEINLINE fltx4 Sin01SIMD(const fltx4& val) +{ + fltx4 fl4Abs = fabs(val); + fltx4 fl4Reduced2 = Mod2SIMDPositiveInput(fl4Abs); + bi32x4 fl4OddMask = CmpGeSIMD(fl4Reduced2, Four_Ones); + fltx4 fl4val = SubSIMD(fl4Reduced2, AndSIMD(Four_Ones, fl4OddMask)); + fltx4 fl4Sin = _Sin01SIMD(fl4val); + fl4Sin = XorSIMD(fl4Sin, AndSIMD(LoadAlignedSIMD(g_SIMD_signmask), XorSIMD(val, fl4OddMask))); + return fl4Sin; + +} + +FORCEINLINE fltx4 NatExpSIMD(const fltx4& val) +{ + fltx4 fl4Result; + SubFloat(fl4Result, 0) = exp(SubFloat(val, 0)); + SubFloat(fl4Result, 1) = exp(SubFloat(val, 1)); + SubFloat(fl4Result, 2) = exp(SubFloat(val, 2)); + SubFloat(fl4Result, 3) = exp(SubFloat(val, 3)); + return fl4Result; +} + +FORCEINLINE fltx4 PreCalcBiasParameter(const fltx4& bias_parameter) +{ + return SubSIMD(ReciprocalSIMD(bias_parameter), Four_Twos); +} + +FORCEINLINE fltx4 BiasSIMD(const fltx4& val, const fltx4& precalc_param) +{ + return DivSIMD(val, AddSIMD(MulSIMD(precalc_param, SubSIMD(Four_Ones, val)), Four_Ones)); +} + +#ifndef SPU +FORCEINLINE int BoxOnPlaneSideSIMD(const fltx4& emins, const fltx4& emaxs, const cplane_t* p, float tolerance = 0.f) +{ + fltx4 corners[2]; + fltx4 normal = LoadUnalignedSIMD(p->normal.Base()); + fltx4 dist = ReplicateX4(-p->dist); + normal = SetWSIMD(normal, dist); + fltx4 t4 = ReplicateX4(tolerance); + fltx4 negt4 = ReplicateX4(-tolerance); + bi32x4 cmp = CmpGeSIMD(normal, Four_Zeros); + corners[0] = MaskedAssign(cmp, emaxs, emins); + corners[1] = MaskedAssign(cmp, emins, emaxs); + fltx4 dot1 = Dot4SIMD(normal, corners[0]); + fltx4 dot2 = Dot4SIMD(normal, corners[1]); + cmp = CmpGeSIMD(dot1, t4); + bi32x4 cmp2 = CmpGtSIMD(negt4, dot2); + fltx4 result = MaskedAssign(cmp, Four_Ones, Four_Zeros); + fltx4 result2 = MaskedAssign(cmp2, Four_Twos, Four_Zeros); + result = AddSIMD(result, result2); + intx4 sides; + ConvertStoreAsIntsSIMD(&sides, result); + return sides[0]; +} + + +class KDop32_t +{ +public: + fltx4 m_Mins[4]; + fltx4 m_Maxes[4]; + + FORCEINLINE bool Intersects(KDop32_t const& other) const; + + FORCEINLINE void operator|=(KDop32_t const& other); + + FORCEINLINE bool IsEmpty(void) const; + + FORCEINLINE void Init(void) + { + for (int i = 0; i < ARRAYSIZE(m_Mins); i++) + { + m_Mins[i] = Four_FLT_MAX; + m_Maxes[i] = Four_Negative_FLT_MAX; + } + } + + void AddPointSet(Vector const* pPoints, int nPnts); + + void CreateFromPointSet(Vector const* pPoints, int nPnts); +}; + +FORCEINLINE void KDop32_t::operator|=(KDop32_t const& other) +{ + m_Mins[0] = MinSIMD(m_Mins[0], other.m_Mins[0]); + m_Mins[1] = MinSIMD(m_Mins[1], other.m_Mins[1]); + m_Mins[2] = MinSIMD(m_Mins[2], other.m_Mins[2]); + m_Mins[3] = MinSIMD(m_Mins[3], other.m_Mins[3]); + + m_Maxes[0] = MaxSIMD(m_Maxes[0], other.m_Maxes[0]); + m_Maxes[1] = MaxSIMD(m_Maxes[1], other.m_Maxes[1]); + m_Maxes[2] = MaxSIMD(m_Maxes[2], other.m_Maxes[2]); + m_Maxes[3] = MaxSIMD(m_Maxes[3], other.m_Maxes[3]); + + +} + +FORCEINLINE bool KDop32_t::Intersects(KDop32_t const& other) const +{ + bi32x4 c00 = CmpLeSIMD(m_Mins[0], other.m_Maxes[0]); + bi32x4 c01 = CmpLeSIMD(m_Mins[1], other.m_Maxes[1]); + bi32x4 c02 = CmpLeSIMD(m_Mins[2], other.m_Maxes[2]); + bi32x4 c03 = CmpLeSIMD(m_Mins[3], other.m_Maxes[3]); + + bi32x4 c10 = CmpGeSIMD(m_Maxes[0], other.m_Mins[0]); + bi32x4 c11 = CmpGeSIMD(m_Maxes[1], other.m_Mins[1]); + bi32x4 c12 = CmpGeSIMD(m_Maxes[2], other.m_Mins[2]); + bi32x4 c13 = CmpGeSIMD(m_Maxes[3], other.m_Mins[3]); + + bi32x4 a0 = AndSIMD(AndSIMD(c00, c01), AndSIMD(c02, c03)); + bi32x4 a1 = AndSIMD(AndSIMD(c10, c11), AndSIMD(c12, c13)); + + return !(IsAnyZeros(AndSIMD(a1, a0))); +} + + +FORCEINLINE bool KDop32_t::IsEmpty(void) const +{ + bi32x4 c00 = CmpLtSIMD(m_Maxes[0], m_Mins[0]); + bi32x4 c01 = CmpLtSIMD(m_Maxes[1], m_Mins[1]); + bi32x4 c02 = CmpLtSIMD(m_Maxes[2], m_Mins[2]); + bi32x4 c03 = CmpLtSIMD(m_Maxes[3], m_Mins[3]); + + return IsAnyTrue(OrSIMD(OrSIMD(c00, c01), OrSIMD(c02, c03))); +} + + +extern const fltx4 g_KDop32XDirs[4]; +extern const fltx4 g_KDop32YDirs[4]; +extern const fltx4 g_KDop32ZDirs[4]; +#endif + +#if 0 + +#define _VEC_SWIZZLE_QUAT48_UNPACK (__vector unsigned char) { 16, 17, 0, 1, 16, 17, 2, 3, 16, 17, 4, 5, 16, 17, 6, 7 } +#define _VEC_SWIZZLE_QUAT48_UNPACK_SHIFT (__vector unsigned int ) { 0, 0, 1, 0 } + +FORCEINLINE fltx4 UnpackQuaternion48SIMD(const Quaternion48* RESTRICT pVec) +{ + fltx4 q16s = LoadUnaligned3SIMD((const float*)pVec); + + bool wneg = pVec->wneg; + + q16s = vec_perm(q16s, Four_Threes, _VEC_SWIZZLE_QUAT48_UNPACK); + + u32x4 tmp = IntShiftLeftWordSIMD(*(u32x4*)&q16s, _VEC_SWIZZLE_QUAT48_UNPACK_SHIFT); + q16s = *(fltx4*)&tmp; + + const fltx4 vUpkMul = SplatXSIMD(g_SIMD_Quat48_Unpack_Magic_Constants); + const fltx4 vUpkAdd = SplatYSIMD(g_SIMD_Quat48_Unpack_Magic_Constants); + + fltx4 ret = vec_madd(q16s, vUpkMul, vUpkAdd); + + fltx4 dotxyz = Dot3SIMD(ret, ret); + dotxyz = ClampVectorSIMD(dotxyz, Four_Zeros, Four_Ones); + + fltx4 ww = SubSIMD(Four_Ones, dotxyz); + ww = SqrtSIMD(ww); + if (wneg) + { + ret = SetWSIMD(ret, NegSIMD(ww)); + } + else + { + ret = SetWSIMD(ret, ww); + } + return ret; +} + +#endif + +FORCEINLINE fltx4 SetWFromXSIMD(const fltx4& a, const fltx4& x) +{ + fltx4 value = SplatXSIMD(x); + return SetWSIMD(a, value); +} + +FORCEINLINE fltx4 SetWFromYSIMD(const fltx4& a, const fltx4& y) +{ + fltx4 value = SplatYSIMD(y); + return SetWSIMD(a, value); +} + +FORCEINLINE fltx4 SetWFromZSIMD(const fltx4& a, const fltx4& z) +{ + fltx4 value = SplatZSIMD(z); + return SetWSIMD(a, value); +} + +FORCEINLINE fltx4 CrossProductSIMD(const fltx4& A, const fltx4& B) +{ +#if defined( _X360 ) + return XMVector3Cross(A, B); +#elif defined( _WIN32 ) + fltx4 A1 = _mm_shuffle_ps(A, A, MM_SHUFFLE_REV(1, 2, 0, 3)); + fltx4 B1 = _mm_shuffle_ps(B, B, MM_SHUFFLE_REV(2, 0, 1, 3)); + fltx4 Result1 = MulSIMD(A1, B1); + fltx4 A2 = _mm_shuffle_ps(A, A, MM_SHUFFLE_REV(2, 0, 1, 3)); + fltx4 B2 = _mm_shuffle_ps(B, B, MM_SHUFFLE_REV(1, 2, 0, 3)); + fltx4 Result2 = MulSIMD(A2, B2); + return SubSIMD(Result1, Result2); + +#elif defined(_PS3) + return _vmathVfCross(A, B); +#else + fltx4 CrossVal; + SubFloat(CrossVal, 0) = SubFloat(A, 1) * SubFloat(B, 2) - SubFloat(A, 2) * SubFloat(B, 1); + SubFloat(CrossVal, 1) = SubFloat(A, 2) * SubFloat(B, 0) - SubFloat(A, 0) * SubFloat(B, 2); + SubFloat(CrossVal, 2) = SubFloat(A, 0) * SubFloat(B, 1) - SubFloat(A, 1) * SubFloat(B, 0); + SubFloat(CrossVal, 3) = 0; + return CrossVal; +#endif +} + +inline const fltx4 Length3SIMD(const fltx4 vec) +{ + fltx4 scLengthSqr = Dot3SIMD(vec, vec); + bi32x4 isSignificant = CmpGtSIMD(scLengthSqr, Four_Epsilons); + fltx4 scLengthInv = ReciprocalSqrtSIMD(scLengthSqr); + return AndSIMD(isSignificant, MulSIMD(scLengthInv, scLengthSqr)); +} + +inline const fltx4 Normalized3SIMD(const fltx4 vec) +{ + fltx4 scLengthSqr = Dot3SIMD(vec, vec); + bi32x4 isSignificant = CmpGtSIMD(scLengthSqr, Four_Epsilons); + fltx4 scLengthInv = ReciprocalSqrtSIMD(scLengthSqr); + return AndSIMD(isSignificant, MulSIMD(vec, scLengthInv)); +} + + +#ifndef COMPILER_GCC + +FORCEINLINE fltx4 operator+=(fltx4& a, FLTX4 b) +{ + a = AddSIMD(a, b); + return a; +} + +FORCEINLINE fltx4 operator-=(fltx4& a, FLTX4 b) +{ + a = SubSIMD(a, b); + return a; +} + + +FORCEINLINE fltx4 operator*=(fltx4& a, FLTX4 b) +{ + a = MulSIMD(a, b); + return a; +} + +#endif +#endif \ No newline at end of file diff --git a/SpyCustom/sendproxy.h b/SpyCustom/sendproxy.h new file mode 100644 index 0000000..819f980 --- /dev/null +++ b/SpyCustom/sendproxy.h @@ -0,0 +1,52 @@ +#ifndef SENDPROXY_H +#define SENDPROXY_H + + +#include "dt_send.h" + + +class DVariant; + +void SendProxy_Color32ToInt(const SendProp* pProp, const void* pStruct, const void* pData, DVariant* pOut, int iElement, int objectID); +void SendProxy_EHandleToInt(const SendProp* pProp, const void* pStruct, const void* pVarData, DVariant* pOut, int iElement, int objectID); +void SendProxy_IntAddOne(const SendProp* pProp, const void* pStruct, const void* pVarData, DVariant* pOut, int iElement, int objectID); +void SendProxy_ShortAddOne(const SendProp* pProp, const void* pStruct, const void* pVarData, DVariant* pOut, int iElement, int objectID); + +SendProp SendPropBool( + const char* pVarName, + int offset, + int sizeofVar); + +SendProp SendPropEHandle( + const char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE, + int flags = 0, + SendVarProxyFn proxyFn = SendProxy_EHandleToInt); + +SendProp SendPropTime( + const char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE); + +#if !defined( NO_ENTITY_PREDICTION ) +SendProp SendPropPredictableId( + const char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE); +#endif + +SendProp SendPropIntWithMinusOneFlag( + const char* pVarName, + int offset, + int sizeofVar = SIZEOF_IGNORE, + int bits = -1, + SendVarProxyFn proxyFn = SendProxy_IntAddOne); + + +SendProp SendPropStringT(const char* pVarName, int offset, int sizeofVar); + +void* SendProxy_OnlyToTeam(const SendProp* pProp, const void* pStruct, const void* pVarData, CSendProxyRecipients* pRecipients, int objectID); + + +#endif \ No newline at end of file diff --git a/SpyCustom/sequence_Transitioner.h b/SpyCustom/sequence_Transitioner.h new file mode 100644 index 0000000..2140d78 --- /dev/null +++ b/SpyCustom/sequence_Transitioner.h @@ -0,0 +1,34 @@ +#ifndef SEQUENCE_TRANSITIONER_H +#define SEQUENCE_TRANSITIONER_H +#ifdef _WIN32 +#pragma once +#endif + + +class CSequenceTransitioner +{ +public: + void CheckForSequenceChange( + CStudioHdr* hdr, + int nCurSequence, + + bool bForceNewSequence, + + bool bInterpolate + ); + + void UpdateCurrent( + CStudioHdr* hdr, + int nCurSequence, + float flCurCycle, + float flCurPlaybackRate, + float flCurTime + ); + + void RemoveAll(void) { m_animationQueue.RemoveAll(); }; + +public: + CUtlVector< CAnimationLayer > m_animationQueue; +}; + +#endif \ No newline at end of file diff --git a/SpyCustom/shake.h b/SpyCustom/shake.h new file mode 100644 index 0000000..a82bf40 --- /dev/null +++ b/SpyCustom/shake.h @@ -0,0 +1,47 @@ +#ifndef SHAKE_H +#define SHAKE_H +#ifdef _WIN32 +#pragma once +#endif + + +struct ScreenShake_t +{ + int command; + float amplitude; + float frequency; + float duration; +}; + +enum ShakeCommand_t +{ + SHAKE_START = 0, + SHAKE_STOP, + SHAKE_AMPLITUDE, + SHAKE_FREQUENCY, + SHAKE_START_RUMBLEONLY, + SHAKE_START_NORUMBLE, +}; + + +extern int gmsgShake; + +extern int gmsgFade; + +#define FFADE_IN 0x0001 +#define FFADE_OUT 0x0002 +#define FFADE_MODULATE 0x0004 +#define FFADE_STAYOUT 0x0008 +#define FFADE_PURGE 0x0010 + +#define SCREENFADE_FRACBITS 9 +struct ScreenFade_t +{ + unsigned short duration; + unsigned short holdTime; + short fadeFlags; + byte r, g, b, a; +}; + + +#endif \ No newline at end of file diff --git a/SpyCustom/shared_classnames.h b/SpyCustom/shared_classnames.h new file mode 100644 index 0000000..c77784a --- /dev/null +++ b/SpyCustom/shared_classnames.h @@ -0,0 +1,17 @@ +#ifndef SHARED_CLASSNAMES_H +#define SHARED_CLASSNAMES_H +#ifdef _WIN32 +#pragma once +#endif + +#if defined( CLIENT_DLL ) + +#define CBaseEntity C_BaseEntity +#define CBaseCombatCharacter C_BaseCombatCharacter +#define CBaseAnimating C_BaseAnimating +#define CBasePlayer C_BasePlayer + +#endif + + +#endif \ No newline at end of file diff --git a/SpyCustom/shareddefs.h b/SpyCustom/shareddefs.h new file mode 100644 index 0000000..d3ec72c --- /dev/null +++ b/SpyCustom/shareddefs.h @@ -0,0 +1,838 @@ +#ifndef SHADERAPI_SHAREDDEFS_H +#define SHADERAPI_SHAREDDEFS_H + +#ifdef _WIN32 +#pragma once +#endif + + +enum ShaderShadeMode_t +{ + SHADER_FLAT = 0, + SHADER_SMOOTH +}; + +enum ShaderTexCoordComponent_t +{ + SHADER_TEXCOORD_S = 0, + SHADER_TEXCOORD_T, + SHADER_TEXCOORD_U +}; + +enum ShaderTexFilterMode_t +{ + SHADER_TEXFILTERMODE_NEAREST, + SHADER_TEXFILTERMODE_LINEAR, + SHADER_TEXFILTERMODE_NEAREST_MIPMAP_NEAREST, + SHADER_TEXFILTERMODE_LINEAR_MIPMAP_NEAREST, + SHADER_TEXFILTERMODE_NEAREST_MIPMAP_LINEAR, + SHADER_TEXFILTERMODE_LINEAR_MIPMAP_LINEAR, + SHADER_TEXFILTERMODE_ANISOTROPIC +}; + +enum ShaderTexWrapMode_t +{ + SHADER_TEXWRAPMODE_CLAMP, + SHADER_TEXWRAPMODE_REPEAT, + SHADER_TEXWRAPMODE_BORDER +}; + + +enum TextureStage_t +{ + SHADER_TEXTURE_STAGE0 = 0, + SHADER_TEXTURE_STAGE1, +}; + +enum Sampler_t +{ + SHADER_SAMPLER0 = 0, + SHADER_SAMPLER1, + SHADER_SAMPLER2, + SHADER_SAMPLER3, + SHADER_SAMPLER4, + SHADER_SAMPLER5, + SHADER_SAMPLER6, + SHADER_SAMPLER7, + SHADER_SAMPLER8, + SHADER_SAMPLER9, + SHADER_SAMPLER10, + SHADER_SAMPLER11, + SHADER_SAMPLER12, + SHADER_SAMPLER13, + SHADER_SAMPLER14, + SHADER_SAMPLER15, +}; + +enum VertexTextureSampler_t +{ + SHADER_VERTEXTEXTURE_SAMPLER0 = 0, + SHADER_VERTEXTEXTURE_SAMPLER1, + SHADER_VERTEXTEXTURE_SAMPLER2, + SHADER_VERTEXTEXTURE_SAMPLER3, +}; + + +#if defined( _X360 ) +#define REVERSE_DEPTH_ON_X360 +#endif + +#if defined( REVERSE_DEPTH_ON_X360 ) +#define ReverseDepthOnX360() true +#else +#define ReverseDepthOnX360() false +#endif + + + + + + +#include "bittools.h" + +#define TICK_INTERVAL (gpGlobals->interval_per_tick) + + +#define TIME_TO_TICKS( dt ) ( (int)( 0.5f + (float)(dt) / TICK_INTERVAL ) ) +#define TICKS_TO_TIME( t ) ( TICK_INTERVAL *( t ) ) +#define ROUND_TO_TICKS( t ) ( TICK_INTERVAL * TIME_TO_TICKS( t ) ) +#define TICK_NEVER_THINK (-1) + + +#define ANIMATION_CYCLE_BITS 15 + +#define ANIMATION_CYCLE_MINFRAC (1.0f / (1<GetViewVectors()->m_vView +#define VEC_HULL_MIN g_pGameRules->GetViewVectors()->m_vHullMin +#define VEC_HULL_MAX g_pGameRules->GetViewVectors()->m_vHullMax + +#define VEC_DUCK_HULL_MIN g_pGameRules->GetViewVectors()->m_vDuckHullMin +#define VEC_DUCK_HULL_MAX g_pGameRules->GetViewVectors()->m_vDuckHullMax +#define VEC_DUCK_VIEW g_pGameRules->GetViewVectors()->m_vDuckView + +#define VEC_OBS_HULL_MIN g_pGameRules->GetViewVectors()->m_vObsHullMin +#define VEC_OBS_HULL_MAX g_pGameRules->GetViewVectors()->m_vObsHullMax + +#define VEC_DEAD_VIEWHEIGHT g_pGameRules->GetViewVectors()->m_vDeadViewHeight + + +#define WATERJUMP_HEIGHT 8 + +#define MAX_CLIMB_SPEED 200 + + +#define TIME_TO_DUCK_MSECS 400 + +#define TIME_TO_UNDUCK_MSECS 200 + +inline float FractionDucked(int msecs) +{ + return clamp((float)msecs / (float)TIME_TO_DUCK_MSECS, 0.0f, 1.0f); +} + +inline float FractionUnDucked(int msecs) +{ + return clamp((float)msecs / (float)TIME_TO_UNDUCK_MSECS, 0.0f, 1.0f); +} + +#define MAX_WEAPON_SLOTS 6 +#define MAX_WEAPON_POSITIONS 20 +#define MAX_ITEM_TYPES 6 +#define MAX_WEAPONS 48 + +#define MAX_ITEMS 5 + +#define WEAPON_NOCLIP -1 + +#define MAX_AMMO_TYPES 32 +#define MAX_AMMO_SLOTS 32 + +#define HUD_PRINTNOTIFY 1 +#define HUD_PRINTCONSOLE 2 +#define HUD_PRINTTALK 3 +#define HUD_PRINTCENTER 4 + + +#define CLOSE_CAPTION_WARNIFMISSING ( 1<<0 ) +#define CLOSE_CAPTION_FROMPLAYER ( 1<<1 ) +#define CLOSE_CAPTION_GENDER_MALE ( 1<<2 ) +#define CLOSE_CAPTION_GENDER_FEMALE ( 1<<3 ) + +#define HIDEHUD_WEAPONSELECTION ( 1<<0 ) +#define HIDEHUD_FLASHLIGHT ( 1<<1 ) +#define HIDEHUD_ALL ( 1<<2 ) +#define HIDEHUD_HEALTH ( 1<<3 ) +#define HIDEHUD_PLAYERDEAD ( 1<<4 ) +#define HIDEHUD_NEEDSUIT ( 1<<5 ) +#define HIDEHUD_MISCSTATUS ( 1<<6 ) +#define HIDEHUD_CHAT ( 1<<7 ) +#define HIDEHUD_CROSSHAIR ( 1<<8 ) +#define HIDEHUD_VEHICLE_CROSSHAIR ( 1<<9 ) +#define HIDEHUD_INVEHICLE ( 1<<10 ) +#define HIDEHUD_BONUS_PROGRESS ( 1<<11 ) +#define HIDEHUD_RADAR ( 1<<12 ) + +#define HIDEHUD_BITCOUNT 13 + +#define bits_SUIT_DEVICE_SPRINT 0x00000001 +#define bits_SUIT_DEVICE_FLASHLIGHT 0x00000002 +#define bits_SUIT_DEVICE_BREATHER 0x00000004 + +#define MAX_SUIT_DEVICES 3 + + +#define MAX_PLAYERS 33 + + +#define MAX_PLACE_NAME_LENGTH 18 + +#define TEAM_ANY -1 +#define TEAM_INVALID -1 +#define TEAM_UNASSIGNED 0 +#define TEAM_SPECTATOR 1 +#define LAST_SHARED_TEAM TEAM_SPECTATOR + +#define FIRST_GAME_TEAM (LAST_SHARED_TEAM+1) + +#define MAX_TEAMS 32 +#define MAX_TEAM_NAME_LENGTH 32 + +#define WEAPON_NOT_CARRIED 0 +#define WEAPON_IS_CARRIED_BY_PLAYER 1 +#define WEAPON_IS_ACTIVE 2 + +#define SKILL_EASY 1 +#define SKILL_MEDIUM 2 +#define SKILL_HARD 3 + + +#define ITEM_FLAG_SELECTONEMPTY (1<<0) +#define ITEM_FLAG_NOAUTORELOAD (1<<1) +#define ITEM_FLAG_NOAUTOSWITCHEMPTY (1<<2) +#define ITEM_FLAG_LIMITINWORLD (1<<3) +#define ITEM_FLAG_EXHAUSTIBLE (1<<4) +#define ITEM_FLAG_DOHITLOCATIONDMG (1<<5) +#define ITEM_FLAG_NOAMMOPICKUPS (1<<6) +#define ITEM_FLAG_NOITEMPICKUP (1<<7) + +#define MAX_VIEWMODELS 2 + +#define MAX_BEAM_ENTS 10 + +#define TRACER_TYPE_DEFAULT 0x00000001 +#define TRACER_TYPE_GUNSHIP 0x00000002 +#define TRACER_TYPE_STRIDER 0x00000004 +#define TRACER_TYPE_GAUSS 0x00000008 +#define TRACER_TYPE_WATERBULLET 0x00000010 + +#define MUZZLEFLASH_TYPE_DEFAULT 0x00000001 +#define MUZZLEFLASH_TYPE_GUNSHIP 0x00000002 +#define MUZZLEFLASH_TYPE_STRIDER 0x00000004 + +enum +{ + MUZZLEFLASH_AR2 = 0, + MUZZLEFLASH_SHOTGUN, + MUZZLEFLASH_SMG1, + MUZZLEFLASH_SMG2, + MUZZLEFLASH_PISTOL, + MUZZLEFLASH_COMBINE, + MUZZLEFLASH_357, + MUZZLEFLASH_RPG, + MUZZLEFLASH_COMBINE_TURRET, + + MUZZLEFLASH_FIRSTPERSON = 0x100, +}; + +#define TRACER_FLAG_WHIZ 0x0001 +#define TRACER_FLAG_USEATTACHMENT 0x0002 + +#define TRACER_DONT_USE_ATTACHMENT -1 + +enum +{ + ENTITY_DISSOLVE_NORMAL = 0, + ENTITY_DISSOLVE_ELECTRICAL, + ENTITY_DISSOLVE_ELECTRICAL_LIGHT, + ENTITY_DISSOLVE_CORE, + + ENTITY_DISSOLVE_BITS = 3 +}; + +#define HITGROUP_GENERIC 0 +#define HITGROUP_HEAD 1 +#define HITGROUP_CHEST 2 +#define HITGROUP_STOMACH 3 +#define HITGROUP_LEFTARM 4 +#define HITGROUP_RIGHTARM 5 +#define HITGROUP_LEFTLEG 6 +#define HITGROUP_RIGHTLEG 7 +#define HITGROUP_GEAR 10 + +enum PLAYER_ANIM +{ + PLAYER_IDLE, + PLAYER_WALK, + PLAYER_JUMP, + PLAYER_SUPERJUMP, + PLAYER_DIE, + PLAYER_ATTACK1, + PLAYER_IN_VEHICLE, + + PLAYER_RELOAD, + PLAYER_START_AIMING, + PLAYER_LEAVE_AIMING, +}; + +#ifdef HL2_DLL +#define PLAYER_FATAL_FALL_SPEED 922.5f +#define PLAYER_MAX_SAFE_FALL_SPEED 526.5f +#define PLAYER_LAND_ON_FLOATING_OBJECT 173 +#define PLAYER_MIN_BOUNCE_SPEED 173 +#define PLAYER_FALL_PUNCH_THRESHOLD 303.0f +#else +#define PLAYER_FATAL_FALL_SPEED 1024 +#define PLAYER_MAX_SAFE_FALL_SPEED 580 +#define PLAYER_LAND_ON_FLOATING_OBJECT 200 +#define PLAYER_MIN_BOUNCE_SPEED 200 +#define PLAYER_FALL_PUNCH_THRESHOLD (float)350 +#endif +#define DAMAGE_FOR_FALL_SPEED 100.0f / ( PLAYER_FATAL_FALL_SPEED - PLAYER_MAX_SAFE_FALL_SPEED ) + + +#define AUTOAIM_2DEGREES 0.0348994967025 +#define AUTOAIM_5DEGREES 0.08715574274766 +#define AUTOAIM_8DEGREES 0.1391731009601 +#define AUTOAIM_10DEGREES 0.1736481776669 +#define AUTOAIM_20DEGREES 0.3490658503989 + +#define AUTOAIM_SCALE_DEFAULT 1.0f +#define AUTOAIM_SCALE_DIRECT_ONLY 0.0f + +#define DMG_GENERIC 0 +#define DMG_CRUSH (1 << 0) +#define DMG_BULLET (1 << 1) +#define DMG_SLASH (1 << 2) +#define DMG_BURN (1 << 3) +#define DMG_VEHICLE (1 << 4) +#define DMG_FALL (1 << 5) +#define DMG_BLAST (1 << 6) +#define DMG_CLUB (1 << 7) +#define DMG_SHOCK (1 << 8) +#define DMG_SONIC (1 << 9) +#define DMG_ENERGYBEAM (1 << 10) +#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) +#define DMG_NEVERGIB (1 << 12) +#define DMG_ALWAYSGIB (1 << 13) +#define DMG_DROWN (1 << 14) + + +#define DMG_PARALYZE (1 << 15) +#define DMG_NERVEGAS (1 << 16) +#define DMG_POISON (1 << 17) +#define DMG_RADIATION (1 << 18) +#define DMG_DROWNRECOVER (1 << 19) +#define DMG_ACID (1 << 20) +#define DMG_SLOWBURN (1 << 21) + +#define DMG_REMOVENORAGDOLL (1<<22) +#define DMG_PHYSGUN (1<<23) +#define DMG_PLASMA (1<<24) +#define DMG_AIRBOAT (1<<25) + +#define DMG_DISSOLVE (1<<26) +#define DMG_BLAST_SURFACE (1<<27) +#define DMG_DIRECT (1<<28) +#define DMG_BUCKSHOT (1<<29) + +#define DMG_LASTGENERICFLAG DMG_BUCKSHOT + + + +#define DAMAGE_NO 0 +#define DAMAGE_EVENTS_ONLY 1 +#define DAMAGE_YES 2 +#define DAMAGE_AIM 3 + +enum +{ + OBS_MODE_NONE = 0, + OBS_MODE_DEATHCAM, + OBS_MODE_FREEZECAM, + OBS_MODE_FIXED, + OBS_MODE_IN_EYE, + OBS_MODE_CHASE, + OBS_MODE_ROAMING, + + NUM_OBSERVER_MODES, +}; + +#define LAST_PLAYER_OBSERVERMODE OBS_MODE_ROAMING + +enum { + OBS_ALLOW_ALL = 0, + OBS_ALLOW_TEAM, + OBS_ALLOW_NONE, + + OBS_ALLOW_NUM_MODES, +}; + +enum +{ + TYPE_TEXT = 0, + TYPE_INDEX, + TYPE_URL, + TYPE_FILE, +}; + +enum +{ + VGUI_SCREEN_ACTIVE = 0x1, + VGUI_SCREEN_VISIBLE_TO_TEAMMATES = 0x2, + VGUI_SCREEN_ATTACHED_TO_VIEWMODEL = 0x4, + VGUI_SCREEN_TRANSPARENT = 0x8, + VGUI_SCREEN_ONLY_USABLE_BY_OWNER = 0x10, + + VGUI_SCREEN_MAX_BITS = 5 +}; + +typedef enum +{ + USE_OFF = 0, + USE_ON = 1, + USE_SET = 2, + USE_TOGGLE = 3 +} USE_TYPE; + +#define COLOR_RED Color(255, 64, 64, 255) +#define COLOR_BLUE Color(153, 204, 255, 255) +#define COLOR_YELLOW Color(255, 178, 0, 255) +#define COLOR_GREEN Color(153, 255, 153, 255) +#define COLOR_GREY Color(204, 204, 204, 255) + +enum +{ + DONT_BLEED = -1, + + BLOOD_COLOR_RED = 0, + BLOOD_COLOR_YELLOW, + BLOOD_COLOR_GREEN, + BLOOD_COLOR_MECH, + +#if defined( HL2_EPISODIC ) + BLOOD_COLOR_ANTLION, + BLOOD_COLOR_ZOMBIE, + BLOOD_COLOR_ANTLION_WORKER, + BLOOD_COLOR_BLOB, + BLOOD_COLOR_BLOB_FROZEN, +#endif + +#if defined( INFESTED_DLL ) + BLOOD_COLOR_BLOB, + BLOOD_COLOR_BLOB_FROZEN, +#endif + + BLOOD_COLOR_BRIGHTGREEN, +}; + +enum PassengerRole_t +{ + VEHICLE_ROLE_NONE = -1, + + VEHICLE_ROLE_DRIVER = 0, + + LAST_SHARED_VEHICLE_ROLE, +}; + +enum +{ + FX_WATER_IN_SLIME = 0x1, +}; + + +#define MAX_CONTEXT_LENGTH 32 +#define NO_THINK_CONTEXT -1 + +enum +{ + EFL_KILLME = (1 << 0), + EFL_DORMANT = (1 << 1), + EFL_NOCLIP_ACTIVE = (1 << 2), + EFL_SETTING_UP_BONES = (1 << 3), + EFL_KEEP_ON_RECREATE_ENTITIES = (1 << 4), + + EFL_DIRTY_SHADOWUPDATE = (1 << 5), + EFL_NOTIFY = (1 << 6), + + EFL_FORCE_CHECK_TRANSMIT = (1 << 7), + + EFL_BOT_FROZEN = (1 << 8), + EFL_SERVER_ONLY = (1 << 9), + EFL_NO_AUTO_EDICT_ATTACH = (1 << 10), + + EFL_DIRTY_ABSTRANSFORM = (1 << 11), + EFL_DIRTY_ABSVELOCITY = (1 << 12), + EFL_DIRTY_ABSANGVELOCITY = (1 << 13), + EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS = (1 << 14), + EFL_DIRTY_SPATIAL_PARTITION = (1 << 15), + EFL_HAS_PLAYER_CHILD = (1 << 16), + + EFL_IN_SKYBOX = (1 << 17), + EFL_USE_PARTITION_WHEN_NOT_SOLID = (1 << 18), + EFL_TOUCHING_FLUID = (1 << 19), + + EFL_IS_BEING_LIFTED_BY_BARNACLE = (1 << 20), + EFL_NO_ROTORWASH_PUSH = (1 << 21), + EFL_NO_THINK_FUNCTION = (1 << 22), + EFL_NO_GAME_PHYSICS_SIMULATION = (1 << 23), + + EFL_CHECK_UNTOUCH = (1 << 24), + EFL_DONTBLOCKLOS = (1 << 25), + EFL_DONTWALKON = (1 << 26), + EFL_NO_DISSOLVE = (1 << 27), + EFL_NO_MEGAPHYSCANNON_RAGDOLL = (1 << 28), + EFL_NO_WATER_VELOCITY_CHANGE = (1 << 29), + EFL_NO_PHYSCANNON_INTERACTION = (1 << 30), + EFL_NO_DAMAGE_FORCES = (1 << 31), +}; + +const int FX_BLOODSPRAY_DROPS = 0x01; +const int FX_BLOODSPRAY_GORE = 0x02; +const int FX_BLOODSPRAY_CLOUD = 0x04; +const int FX_BLOODSPRAY_ALL = 0xFF; + +#define MAX_SCREEN_OVERLAYS 10 + +enum +{ + GROUNDLINK = 0, + TOUCHLINK, + STEPSIMULATION, + MODELSCALE, + POSITIONWATCHER, + PHYSICSPUSHLIST, + VPHYSICSUPDATEAI, + VPHYSICSWATCHER, + + NUM_DATAOBJECT_TYPES, +}; + +class CBaseEntity; + +class CBaseEntity; + +enum FireBulletsFlags_t +{ + FIRE_BULLETS_FIRST_SHOT_ACCURATE = 0x1, + FIRE_BULLETS_DONT_HIT_UNDERWATER = 0x2, + FIRE_BULLETS_ALLOW_WATER_SURFACE_IMPACTS = 0x4, + FIRE_BULLETS_TEMPORARY_DANGER_SOUND = 0x8, + + FIRE_BULLETS_NO_PIERCING_SPARK = 0x16, + FIRE_BULLETS_HULL = 0x32, + FIRE_BULLETS_ANGULAR_SPREAD = 0x64, +}; + + +struct FireBulletsInfo_t +{ + FireBulletsInfo_t() + { + m_iShots = 1; + m_vecSpread.Init(0, 0, 0); + m_flDistance = 8192; + m_iTracerFreq = 4; + m_flDamage = 0.0f; + m_flPlayerDamage = 0.0f; + m_pAttacker = NULL; + m_nFlags = 0; + m_pAdditionalIgnoreEnt = NULL; + m_flDamageForceScale = 1.0f; + +#ifdef _DEBUG + m_iAmmoType = -1; + m_vecSrc.Init(VEC_T_NAN, VEC_T_NAN, VEC_T_NAN); + m_vecDirShooting.Init(VEC_T_NAN, VEC_T_NAN, VEC_T_NAN); +#endif + m_bPrimaryAttack = true; + } + + FireBulletsInfo_t(int nShots, const Vector& vecSrc, const Vector& vecDir, const Vector& vecSpread, float flDistance, int nAmmoType, bool bPrimaryAttack = true) + { + m_iShots = nShots; + m_vecSrc = vecSrc; + m_vecDirShooting = vecDir; + m_vecSpread = vecSpread; + m_flDistance = flDistance; + m_iAmmoType = nAmmoType; + m_iTracerFreq = 4; + m_flDamage = 0; + m_flPlayerDamage = 0; + m_pAttacker = NULL; + m_nFlags = 0; + m_pAdditionalIgnoreEnt = NULL; + m_flDamageForceScale = 1.0f; + m_bPrimaryAttack = bPrimaryAttack; + } + + int m_iShots; + Vector m_vecSrc; + Vector m_vecDirShooting; + Vector m_vecSpread; + float m_flDistance; + int m_iAmmoType; + int m_iTracerFreq; + float m_flDamage; + float m_flPlayerDamage; + int m_nFlags; + float m_flDamageForceScale; + CBaseEntity* m_pAttacker; + CBaseEntity* m_pAdditionalIgnoreEnt; + bool m_bPrimaryAttack; +}; + +struct StepSimulationStep +{ + int nTickCount; + Vector vecOrigin; + Quaternion qRotation; +}; + +struct StepSimulationData +{ + bool m_bOriginActive; + bool m_bAnglesActive; + + StepSimulationStep m_Previous2; + + StepSimulationStep m_Previous; + + StepSimulationStep m_Discontinuity; + + StepSimulationStep m_Next; + QAngle m_angNextRotation; + + int m_nLastProcessTickCount; + Vector m_vecNetworkOrigin; + int m_networkCell[3]; + QAngle m_angNetworkAngles; +}; + +struct ModelScale +{ + float m_flModelScaleStart; + float m_flModelScaleGoal; + float m_flModelScaleFinishTime; + float m_flModelScaleStartTime; +}; + +#include "soundflags.h" + +struct CSoundParameters; +typedef short HSOUNDSCRIPTHANDLE; +struct EmitSound_t +{ + EmitSound_t() : + m_nChannel(0), + m_pSoundName(0), + m_flVolume(VOL_NORM), + m_SoundLevel(SNDLVL_NONE), + m_nFlags(0), + m_nPitch(PITCH_NORM), + m_pOrigin(0), + m_flSoundTime(0.0f), + m_pflSoundDuration(0), + m_bEmitCloseCaption(true), + m_bWarnOnMissingCloseCaption(false), + m_bWarnOnDirectWaveReference(false), + m_nSpeakerEntity(-1), + m_UtlVecSoundOrigin(), + m_hSoundScriptHandle(-1) + { + } + + EmitSound_t(const CSoundParameters& src); + + int m_nChannel; + char const* m_pSoundName; + float m_flVolume; + soundlevel_t m_SoundLevel; + int m_nFlags; + int m_nPitch; + const Vector* m_pOrigin; + float m_flSoundTime; + float* m_pflSoundDuration; + bool m_bEmitCloseCaption; + bool m_bWarnOnMissingCloseCaption; + bool m_bWarnOnDirectWaveReference; + int m_nSpeakerEntity; + mutable CUtlVector< Vector > m_UtlVecSoundOrigin; + mutable HSOUNDSCRIPTHANDLE m_hSoundScriptHandle; +}; + +#define MAX_ACTORS_IN_SCENE 16 + +#define MAX_CONTROL_POINTS 8 +#define MAX_CONTROL_POINT_GROUPS 8 + +#define MAX_PREVIOUS_POINTS 3 + +#define MAX_CONTROL_POINT_TEAMS 8 + +#define MAX_CAPLAYOUT_LENGTH 32 + +#define MAX_ROUND_NAME 32 + +#define MAX_ROUND_IMAGE_NAME 64 + +#define TEAMPLAY_ROUND_WIN_SCORE 1 + +enum +{ + CP_WARN_NORMAL = 0, + CP_WARN_FINALCAP, + CP_WARN_NO_ANNOUNCEMENTS +}; + +#define PREDICTION_ERROR_CHECK_LEVEL 0 + +#define PREDICTION_ERROR_CHECK_STACKS_FOR_MISSING 0 + +enum +{ + RT_STATE_SETUP, + RT_STATE_NORMAL, +}; + +enum +{ + SIMULATION_TIME_WINDOW_BITS = 8, +}; + + +#define CELL_COUNT( bits ) ( (MAX_COORD_INTEGER*2) / (1 << (bits)) ) +#define CELL_COUNT_BITS( bits ) MINIMUM_BITS_NEEDED( CELL_COUNT( bits ) ) +#define CELL_BASEENTITY_ORIGIN_CELL_BITS 5 + + +#ifdef GAME_HAS_NO_USE_KEY +#define COMMENTARY_BUTTONS (IN_ATTACK | IN_ATTACK2 | IN_USE) +#else +#define COMMENTARY_BUTTONS (IN_USE) +#endif + +bool IsHeadTrackingEnabled(); + + +#define MAX_SPLITSCREEN_PLAYERS 1 + + +inline bool IsSplitScreenSupported() +{ + return (MAX_SPLITSCREEN_PLAYERS > 1) ? true : false; +} + +enum InvalidatePhysicsBits_t +{ + POSITION_CHANGED = 0x1, + ANGLES_CHANGED = 0x2, + VELOCITY_CHANGED = 0x4, + ANIMATION_CHANGED = 0x8, + BOUNDS_CHANGED = 0x10, + SEQUENCE_CHANGED = 0x20, +}; + +enum Class_T +{ + CLASS_NONE = 0, + CLASS_PLAYER, + CLASS_PLAYER_ALLY, + CLASS_PLAYER_ALLY_VITAL, + CLASS_ANTLION, + CLASS_BARNACLE, + CLASS_BLOB, + CLASS_BULLSEYE, + CLASS_CITIZEN_PASSIVE, + CLASS_CITIZEN_REBEL, + CLASS_COMBINE, + CLASS_COMBINE_GUNSHIP, + CLASS_CONSCRIPT, + CLASS_HEADCRAB, + CLASS_MANHACK, + CLASS_METROPOLICE, + CLASS_MILITARY, + CLASS_SCANNER, + CLASS_STALKER, + CLASS_VORTIGAUNT, + CLASS_ZOMBIE, + CLASS_PROTOSNIPER, + CLASS_MISSILE, + CLASS_FLARE, + CLASS_EARTH_FAUNA, + CLASS_HACKED_ROLLERMINE, + CLASS_COMBINE_HUNTER, + + LAST_SHARED_ENTITY_CLASS, +}; + +#define FACTION_NONE 0 +#define LAST_SHARED_FACTION (FACTION_NONE) +#define NUM_SHARED_FACTIONS (FACTION_NONE + 1) + + + + + + + + + + +#endif \ No newline at end of file