From 97c58c6b32acaaa80d4d49320749c602dbe65c56 Mon Sep 17 00:00:00 2001 From: aixxe Date: Sat, 2 Jan 2016 16:14:13 +0000 Subject: [PATCH] Added m_nSequence hook to fix some knife animations. --- Chameleon/Chameleon.cpp | 62 ++++++---------- Chameleon/Chameleon.vcxproj | 1 + Chameleon/Chameleon.vcxproj.filters | 3 + Chameleon/Defines.h | 29 ++++++++ Chameleon/IClientEntity.h | 18 +++-- Chameleon/IClientEntityList.h | 1 - Chameleon/IVModelInfoClient.h | 8 +++ Chameleon/Proxies.h | 108 ++++++++++++++++++++++++++++ Chameleon/SDK.h | 18 +++-- 9 files changed, 195 insertions(+), 53 deletions(-) create mode 100644 Chameleon/Proxies.h diff --git a/Chameleon/Chameleon.cpp b/Chameleon/Chameleon.cpp index 15dff30..f171748 100644 --- a/Chameleon/Chameleon.cpp +++ b/Chameleon/Chameleon.cpp @@ -14,42 +14,13 @@ // Include the user defined skins. #include "Skins.h" +// Include the NetVar proxy functions. +#include "Proxies.h" + // Define the calling convention for the FrameStageNotify function. typedef void(__thiscall *FrameStageNotify)(void*, ClientFrameStage_t); FrameStageNotify fnOriginalFunction = NULL; -// Store the original proxy function for the 'm_nModelIndex' property. -RecvVarProxyFn fnOriginalProxyFn = NULL; - -// Function to change viewmodels. -void SetViewModelIndex(const CRecvProxyData *pDataConst, void *pStruct, void *pOut) { - // Ensure the model replacements are available. (called here so GetModelIndex returns valid IDs) - if (g_ViewModelCfg.size() == 0) - SetModelConfig(); - - // Make the incoming data editable. - CRecvProxyData* pData = const_cast(pDataConst); - - // Check for a model replacement in the global table. - if (g_ViewModelCfg.find(pData->m_Value.m_Int) != g_ViewModelCfg.end()) { - // Confirm that we are replacing our view model and not someone elses. - CBaseViewModel* pViewModel = (CBaseViewModel*)pStruct; - - if (pViewModel) { - // Compare the owner entity of this view model to the local player entity. - IClientEntity* pLocal = g_EntityList->GetClientEntity(g_EngineClient->GetLocalPlayer()); - - if (pLocal == g_EntityList->GetClientEntityFromHandle(pViewModel->GetOwner())) { - // Replace the view model with the user defined value. - pData->m_Value.m_Int = g_ViewModelCfg[pData->m_Value.m_Int]; - } - } - } - - // Call original function with the modified data. - fnOriginalProxyFn(pData, pStruct, pOut); -} - // Function to apply skin data to weapons. inline bool ApplyCustomSkin(CBaseAttributableItem* pWeapon) { // Get the weapons item definition index. @@ -178,16 +149,28 @@ void Initialise() { for (int nIndex = 0; nIndex < pClassTable->m_nProps; nIndex++) { RecvProp* pProp = &pClassTable->m_pProps[nIndex]; - if (!pProp || strcmp(pProp->m_pVarName, "m_nModelIndex")) + if (!pProp) continue; - // Store the original proxy function. - fnOriginalProxyFn = pProp->m_ProxyFn; + if (!strcmp(pProp->m_pVarName, "m_nModelIndex")) { + // Store the original proxy function. + fnModelIndexProxyFn = pProp->m_ProxyFn; - // Replace the proxy function with our model changer. - pProp->m_ProxyFn = (RecvVarProxyFn)SetViewModelIndex; + // Replace the proxy function with our model changer. + pProp->m_ProxyFn = (RecvVarProxyFn)SetViewModelIndex; + + continue; + } - break; + if (!strcmp(pProp->m_pVarName, "m_nSequence")) { + // Store the original proxy function. + fnSequenceProxyFn = pProp->m_ProxyFn; + + // Replace the proxy function with our sequence changer. + pProp->m_ProxyFn = (RecvVarProxyFn)SetViewModelSequence; + + continue; + } } break; @@ -196,9 +179,8 @@ void Initialise() { } bool __stdcall DllMain(HINSTANCE hDLLInstance, DWORD dwReason, LPVOID lpReserved) { - if (dwReason == DLL_PROCESS_ATTACH) { + if (dwReason == DLL_PROCESS_ATTACH) CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Initialise, 0, 0, 0); - } return true; } \ No newline at end of file diff --git a/Chameleon/Chameleon.vcxproj b/Chameleon/Chameleon.vcxproj index f5b427d..731d613 100644 --- a/Chameleon/Chameleon.vcxproj +++ b/Chameleon/Chameleon.vcxproj @@ -82,6 +82,7 @@ + diff --git a/Chameleon/Chameleon.vcxproj.filters b/Chameleon/Chameleon.vcxproj.filters index 92439eb..d3fd857 100644 --- a/Chameleon/Chameleon.vcxproj.filters +++ b/Chameleon/Chameleon.vcxproj.filters @@ -54,6 +54,9 @@ Header Files\Source SDK\Classes + + Header Files + diff --git a/Chameleon/Defines.h b/Chameleon/Defines.h index a6ec45c..a1a6f39 100644 --- a/Chameleon/Defines.h +++ b/Chameleon/Defines.h @@ -1,7 +1,36 @@ #pragma once +#define SEQUENCE_DEFAULT_DRAW 0 +#define SEQUENCE_DEFAULT_IDLE1 1 +#define SEQUENCE_DEFAULT_IDLE2 2 +#define SEQUENCE_DEFAULT_LIGHT_MISS1 3 +#define SEQUENCE_DEFAULT_LIGHT_MISS2 4 +#define SEQUENCE_DEFAULT_HEAVY_MISS1 9 +#define SEQUENCE_DEFAULT_HEAVY_HIT1 10 +#define SEQUENCE_DEFAULT_HEAVY_BACKSTAB 11 +#define SEQUENCE_DEFAULT_LOOKAT01 12 + +#define SEQUENCE_BUTTERFLY_DRAW 0 +#define SEQUENCE_BUTTERFLY_DRAW2 1 +#define SEQUENCE_BUTTERFLY_LOOKAT01 13 +#define SEQUENCE_BUTTERFLY_LOOKAT03 15 + +#define SEQUENCE_FALCHION_IDLE1 1 +#define SEQUENCE_FALCHION_HEAVY_MISS1 8 +#define SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP 9 +#define SEQUENCE_FALCHION_LOOKAT01 12 +#define SEQUENCE_FALCHION_LOOKAT02 13 + +#define SEQUENCE_DAGGERS_IDLE1 1 +#define SEQUENCE_DAGGERS_LIGHT_MISS1 2 +#define SEQUENCE_DAGGERS_LIGHT_MISS5 6 +#define SEQUENCE_DAGGERS_HEAVY_MISS2 11 +#define SEQUENCE_DAGGERS_HEAVY_MISS1 12 + #define LIFE_ALIVE 0 +#define RandomInt(nMin, nMax) (rand() % (nMax - nMin + 1) + nMin); + typedef struct player_info_s { private: DWORD __pad0[2]; diff --git a/Chameleon/IClientEntity.h b/Chameleon/IClientEntity.h index a34f112..52edc04 100644 --- a/Chameleon/IClientEntity.h +++ b/Chameleon/IClientEntity.h @@ -3,6 +3,9 @@ #define m_lifeState 0x25B #define m_hMyWeapons 0x49F8 +#define m_nModelIndex 0x254 +#define m_hOwner 0x45CC + #define m_AttributeManager 0x4980 #define m_Item 0x40 #define m_iItemDefinitionIndex 0x1D0 @@ -17,8 +20,6 @@ #define m_flFallbackWear 0x4D78 #define m_nFallbackStatTrak 0x4D7C -#define m_hOwner 0x45CC - class IClientEntity { public: inline BYTE GetLifeState() { @@ -32,15 +33,20 @@ class IClientEntity { } }; -class CBaseViewModel: IClientEntity { +class CBaseViewModel: public IClientEntity { public: + inline int* GetModelIndex() { + // DT_BaseViewModel -> m_nModelIndex + return (int*)((DWORD)this + m_nModelIndex); + } + inline DWORD GetOwner() { - // DT_PredictedViewModel -> m_hOwner - return *(DWORD*)((DWORD)this + m_hOwner); + // DT_BaseViewModel -> m_hOwner + return *(PDWORD)((DWORD)this + m_hOwner); } }; -class CBaseAttributableItem: IClientEntity { +class CBaseAttributableItem: public IClientEntity { public: inline int* GetItemDefinitionIndex() { // DT_BaseAttributableItem -> m_AttributeManager -> m_Item -> m_iItemDefinitionIndex diff --git a/Chameleon/IClientEntityList.h b/Chameleon/IClientEntityList.h index c541de4..af4091c 100644 --- a/Chameleon/IClientEntityList.h +++ b/Chameleon/IClientEntityList.h @@ -8,6 +8,5 @@ class IClientEntityList { inline IClientEntity* GetClientEntityFromHandle(DWORD Handle) { return CallVirtualFunction(this, 4)(this, Handle); - //return this->GetClientEntity(Handle & 0xFFFF); } }; \ No newline at end of file diff --git a/Chameleon/IVModelInfoClient.h b/Chameleon/IVModelInfoClient.h index bd5153b..0f0a8bd 100644 --- a/Chameleon/IVModelInfoClient.h +++ b/Chameleon/IVModelInfoClient.h @@ -2,7 +2,15 @@ class IVModelInfoClient { public: + inline void* GetModel(int Index) { + return CallVirtualFunction(this, 1)(this, Index); + } + inline int GetModelIndex(const char* Filename) { return CallVirtualFunction(this, 2)(this, Filename); } + + inline const char* GetModelName(const void* Model) { + return CallVirtualFunction(this, 3)(this, Model); + } }; \ No newline at end of file diff --git a/Chameleon/Proxies.h b/Chameleon/Proxies.h new file mode 100644 index 0000000..0eb526b --- /dev/null +++ b/Chameleon/Proxies.h @@ -0,0 +1,108 @@ +#pragma once + +// Store the original proxy functions. +RecvVarProxyFn fnModelIndexProxyFn = NULL; +RecvVarProxyFn fnSequenceProxyFn = NULL; + +// Function to change viewmodels. +void SetViewModelIndex(const CRecvProxyData *pDataConst, void *pStruct, void *pOut) { + // Ensure the model replacements are available. (called here so GetModelIndex returns valid IDs) + if (g_ViewModelCfg.size() == 0) + SetModelConfig(); + + // Make the incoming data editable. + CRecvProxyData* pData = const_cast(pDataConst); + + // Check for a model replacement in the global table. + if (g_ViewModelCfg.find(pData->m_Value.m_Int) != g_ViewModelCfg.end()) { + // Confirm that we are replacing our view model and not someone elses. + CBaseViewModel* pViewModel = (CBaseViewModel*)pStruct; + + if (pViewModel) { + // Compare the owner entity of this view model to the local player entity. + IClientEntity* pLocal = g_EntityList->GetClientEntity(g_EngineClient->GetLocalPlayer()); + + if (pLocal == g_EntityList->GetClientEntityFromHandle(pViewModel->GetOwner())) { + // Replace the view model with the user defined value. + pData->m_Value.m_Int = g_ViewModelCfg[pData->m_Value.m_Int]; + } + } + } + + // Call original function with the modified data. + fnModelIndexProxyFn(pData, pStruct, pOut); +} + +// Function to fix sequences for certain models. +void SetViewModelSequence(const CRecvProxyData *pDataConst, void *pStruct, void *pOut) { + // Make the incoming data editable. + CRecvProxyData* pData = const_cast(pDataConst); + + // Confirm that we are replacing our view model and not someone elses. + CBaseViewModel* pViewModel = (CBaseViewModel*)pStruct; + + // Compare the owner entity of this view model to the local player entity. + IClientEntity* pLocal = g_EntityList->GetClientEntity(g_EngineClient->GetLocalPlayer()); + + if (pLocal == g_EntityList->GetClientEntityFromHandle(pViewModel->GetOwner())) { + // Get the filename of the current view model. + void* pModel = g_ModelInfo->GetModel(*pViewModel->GetModelIndex()); + const char* szModel = g_ModelInfo->GetModelName(pModel); + + // Store the current sequence. + int m_nSequence = pData->m_Value.m_Int; + + if (!strcmp(szModel, "models/weapons/v_knife_butterfly.mdl")) { + // Fix animations for the Butterfly Knife. + switch (m_nSequence) { + case SEQUENCE_DEFAULT_DRAW: + m_nSequence = RandomInt(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2); break; + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = RandomInt(SEQUENCE_BUTTERFLY_LOOKAT01, SEQUENCE_BUTTERFLY_LOOKAT03); break; + default: + m_nSequence++; + } + } else if (!strcmp(szModel, "models/weapons/v_knife_falchion_advanced.mdl")) { + // Fix animations for the Falchion Knife. + switch (m_nSequence) { + case SEQUENCE_DEFAULT_IDLE2: + m_nSequence = SEQUENCE_FALCHION_IDLE1; break; + case SEQUENCE_DEFAULT_HEAVY_MISS1: + m_nSequence = RandomInt(SEQUENCE_FALCHION_HEAVY_MISS1, SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP); break; + case SEQUENCE_DEFAULT_LOOKAT01: + m_nSequence = RandomInt(SEQUENCE_FALCHION_LOOKAT01, SEQUENCE_FALCHION_LOOKAT02); break; + case SEQUENCE_DEFAULT_DRAW: + case SEQUENCE_DEFAULT_IDLE1: + break; + default: + m_nSequence--; + } + } else if (!strcmp(szModel, "models/weapons/v_knife_push.mdl")) { + // Fix animations for the Shadow Daggers. + 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 = RandomInt(SEQUENCE_DAGGERS_LIGHT_MISS1, SEQUENCE_DAGGERS_LIGHT_MISS5); break; + case SEQUENCE_DEFAULT_HEAVY_MISS1: + m_nSequence = RandomInt(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 += 3; break; + case SEQUENCE_DEFAULT_DRAW: + case SEQUENCE_DEFAULT_IDLE1: + break; + default: + m_nSequence += 2; + } + } + + // Set the fixed sequence. + pData->m_Value.m_Int = m_nSequence; + } + + // Call original function with the modified data. + fnSequenceProxyFn(pData, pStruct, pOut); +} \ No newline at end of file diff --git a/Chameleon/SDK.h b/Chameleon/SDK.h index f3a0ab5..735efff 100644 --- a/Chameleon/SDK.h +++ b/Chameleon/SDK.h @@ -3,16 +3,22 @@ #define WIN32_LEAN_AND_MEAN #include +class IBaseClientDLL; +class IVEngineClient; +class IClientEntityList; +class IVModelInfoClient; +class IClientEntity; + +IBaseClientDLL* g_BaseClient = nullptr; +IVEngineClient* g_EngineClient = nullptr; +IClientEntityList* g_EntityList = nullptr; +IVModelInfoClient* g_ModelInfo = nullptr; + #include "Defines.h" #include "DataTable.h" #include "ClientClass.h" -#include "IClientEntity.h" #include "IBaseClientDLL.h" #include "IVEngineClient.h" #include "IVModelInfoClient.h" #include "IClientEntityList.h" - -IBaseClientDLL* g_BaseClient = nullptr; -IVEngineClient* g_EngineClient = nullptr; -IClientEntityList* g_EntityList = nullptr; -IVModelInfoClient* g_ModelInfo = nullptr; \ No newline at end of file +#include "IClientEntity.h" \ No newline at end of file