From f351e20de3da4ba9bd73cd23eed268fb03c5cbc4 Mon Sep 17 00:00:00 2001 From: Ruben Gonzalez Date: Sat, 8 Feb 2014 20:04:12 -0500 Subject: [PATCH] Update CStrike extension and gamedata on windows for latest CS:GO update (irc, r= psychonic) --- extensions/cstrike/forwards.cpp | 50 +++++++++++++- extensions/cstrike/natives.cpp | 82 +++++++++++++++++++--- extensions/cstrike/util_cstrike.cpp | 90 ++++++++++++++++++++++--- gamedata/sm-cstrike.games/game.csgo.txt | 30 ++++----- 4 files changed, 218 insertions(+), 34 deletions(-) diff --git a/extensions/cstrike/forwards.cpp b/extensions/cstrike/forwards.cpp index 83375a4b..2e7d4ffa 100644 --- a/extensions/cstrike/forwards.cpp +++ b/extensions/cstrike/forwards.cpp @@ -21,6 +21,13 @@ CDetour *DCSWeaponDrop = NULL; int weaponNameOffset = -1; +//Windows CS:GO +// int __userpurge HandleCommand_Buy_Internal(int a1, float a2, int a3, int a4, char a5) +// a1 - this +// a2 - CCSGameRules::GetWarmupPeriodEndTime(g_pGameRules) +// a3 - weapon +// a4 - unknown +// a5 - bRebuy #if SOURCE_ENGINE == SE_CSGO DETOUR_DECL_MEMBER3(DetourHandleBuy, int, const char *, weapon, int, iUnknown, bool, bRebuy) #else @@ -69,7 +76,7 @@ DETOUR_DECL_MEMBER2(DetourWeaponPrice, int, const char *, szAttribute, CEconItem { int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)(szAttribute, pEconItem); - if(lastclient == -1 || strcmp(szAttribute, "in_game_price") != 0) + if(lastclient == -1 || strcmp(szAttribute, "in game price") != 0) return price; const char *weapon_name = reinterpret_cast(this+weaponNameOffset); @@ -78,6 +85,7 @@ DETOUR_DECL_MEMBER2(DetourWeaponPrice, int, const char *, szAttribute, CEconItem } #endif +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason) { if (g_pIgnoreTerminateDetour) @@ -86,6 +94,30 @@ DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason) DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason); return; } +#else +//Windows CSGO +//char __userpurge TerminateRound(unsigned int a1, signed int a2, unsigned int a3, int a4) +// a1 - this +// a2 - unknown +// a3 - delay +// a4 - reason +DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason) +{ + float delay; + + if (g_pIgnoreTerminateDetour) + { + g_pIgnoreTerminateDetour = false; + return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason); + } + + //Save the delay + __asm + { + movss delay, xmm1 + } +#endif + float orgdelay = delay; int orgreason = reason; @@ -98,10 +130,26 @@ DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason) if (result >= Pl_Handled) return; +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) if (result == Pl_Changed) return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason); +#else + if (result == Pl_Changed) + { + __asm + { + movss xmm1, delay + } + return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason); + } + __asm + { + movss xmm1, orgdelay + } + return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgreason); +#endif } DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, something, bool, toss) diff --git a/extensions/cstrike/natives.cpp b/extensions/cstrike/natives.cpp index da7b23f2..a22c7cbe 100644 --- a/extensions/cstrike/natives.cpp +++ b/extensions/cstrike/natives.cpp @@ -46,6 +46,12 @@ int g_iPriceOffset = -1; code; \ g_RegNatives.Register(pWrapper); +#define GET_MEMSIG(name) \ + if (!g_pGameConf->GetMemSig(name, &addr) || !addr) \ + { \ + return pContext->ThrowNativeError("Failed to locate function"); \ + } + inline CBaseEntity *GetCBaseEntity(int num, bool isplayer) { edict_t *pEdict = gamehelpers->EdictOfIndex(num); @@ -150,6 +156,7 @@ static cell_t CS_RespawnPlayer(IPluginContext *pContext, const cell_t *params) static cell_t CS_SwitchTeam(IPluginContext *pContext, const cell_t *params) { +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) static ICallWrapper *pWrapper = NULL; if (!pWrapper) { @@ -174,6 +181,41 @@ static cell_t CS_SwitchTeam(IPluginContext *pContext, const cell_t *params) vptr += sizeof(CBaseEntity *); *(int *)vptr = params[2]; pWrapper->Execute(vstk, NULL); +#else + if (g_pSDKTools == NULL) + { + return pContext->ThrowNativeError("SDKTools interface not found. TerminateRound native disabled."); + } + + static void *addr = NULL; + if(!addr) + { + GET_MEMSIG("SwitchTeam"); + } + + void *gamerules = g_pSDKTools->GetGameRules(); + if (gamerules == NULL) + { + return pContext->ThrowNativeError("GameRules not available. SwitchTeam native disabled."); + } + + CBaseEntity *pEntity; + if (!(pEntity=GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + int team = params[2]; + + __asm + { + push team + mov ecx, pEntity + mov ebx, gamerules + + call addr + } +#endif return 1; } @@ -248,7 +290,7 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params) { if (g_pSDKTools == NULL) { - smutils->LogError(myself, "SDKTools interface not found. TerminateRound native disabled."); + return pContext->ThrowNativeError("SDKTools interface not found. TerminateRound native disabled."); } else if (g_pSDKTools->GetInterfaceVersion() < 2) { @@ -256,6 +298,13 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("SDKTools interface is outdated. TerminateRound native disabled."); } + void *gamerules = g_pSDKTools->GetGameRules(); + if (gamerules == NULL) + { + return pContext->ThrowNativeError("GameRules not available. TerminateRound native disabled."); + } + +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) static ICallWrapper *pWrapper = NULL; if (!pWrapper) @@ -271,12 +320,6 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params) pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 2)) } - void *gamerules = g_pSDKTools->GetGameRules(); - if (gamerules == NULL) - { - return pContext->ThrowNativeError("GameRules not available. TerminateRound native disabled."); - } - if (params[3] == 1 && g_pTerminateRoundDetoured) g_pIgnoreTerminateDetour = true; @@ -290,7 +333,30 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params) *(int*)vptr = params[2]; pWrapper->Execute(vstk, NULL); +#else + static void *addr = NULL; + if(!addr) + { + GET_MEMSIG("TerminateRound"); + } + + if (params[3] == 1 && g_pTerminateRoundDetoured) + g_pIgnoreTerminateDetour = true; + + float delay = sp_ctof(params[1]); + int reason = params[2]; + signed int unknown = 1;//We might want to find what this is? + __asm + { + push reason + movss xmm1, delay + mov edi, unknown + mov ecx, gamerules + call addr + } + +#endif return 1; } @@ -385,7 +451,7 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params) *(void **)vptr = info; vptr += sizeof(void *); - *(const char **)vptr = "in_game_price"; + *(const char **)vptr = "in game price"; vptr += sizeof(const char **); *(CEconItemView **)vptr = NULL; diff --git a/extensions/cstrike/util_cstrike.cpp b/extensions/cstrike/util_cstrike.cpp index b7a5cb6b..ad1c4b7c 100644 --- a/extensions/cstrike/util_cstrike.cpp +++ b/extensions/cstrike/util_cstrike.cpp @@ -44,8 +44,17 @@ code; \ g_RegNatives.Register(pWrapper); +#define GET_MEMSIG(name, defaultret) \ + if (!g_pGameConf->GetMemSig(name, &addr) || !addr) \ + { \ + g_pSM->LogError(myself, "Failed to locate function."); \ + return defaultret;\ + } + void *GetWeaponInfo(int weaponID) { + void *info; +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) static ICallWrapper *pWrapper = NULL; if (!pWrapper) { @@ -61,8 +70,6 @@ void *GetWeaponInfo(int weaponID) pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) } - void *info; - unsigned char vstk[sizeof(int)]; unsigned char *vptr = vstk; @@ -70,11 +77,30 @@ void *GetWeaponInfo(int weaponID) pWrapper->Execute(vstk, &info); + +#else + static void *addr = NULL; + + if(!addr) + { + GET_MEMSIG("GetWeaponInfo", 0); + } + + __asm + { + mov ecx, weaponID + call addr + mov info, eax + } +#endif return info; } const char *GetTranslatedWeaponAlias(const char *weapon) { + const char *alias = NULL; + +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) static ICallWrapper *pWrapper = NULL; if (!pWrapper) @@ -90,20 +116,35 @@ const char *GetTranslatedWeaponAlias(const char *weapon) retpass.size = sizeof(const char *); \ pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) } - const char *ret = NULL; unsigned char vstk[sizeof(const char *)]; unsigned char *vptr = vstk; *(const char **)vptr = weapon; - pWrapper->Execute(vstk, &ret); + pWrapper->Execute(vstk, &alias); +#else + static void *addr = NULL; - return ret; + if(!addr) + { + GET_MEMSIG("GetTranslatedWeaponAlias", weapon); + } + + __asm + { + mov ecx, weapon + call addr + mov alias, eax + } +#endif + return alias; } int AliasToWeaponID(const char *weapon) { + int weaponID = 0; +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) static ICallWrapper *pWrapper = NULL; if (!pWrapper) @@ -119,7 +160,6 @@ int AliasToWeaponID(const char *weapon) retpass.size = sizeof(int); \ pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) } - int weaponID = 0; unsigned char vstk[sizeof(const char *)]; unsigned char *vptr = vstk; @@ -127,12 +167,28 @@ int AliasToWeaponID(const char *weapon) *(const char **)vptr = weapon; pWrapper->Execute(vstk, &weaponID); +#else + static void *addr = NULL; + if(!addr) + { + GET_MEMSIG("AliasToWeaponID", 0); + } + + __asm + { + mov ecx, weapon + call addr + mov weaponID, eax + } +#endif return weaponID; } const char *WeaponIDToAlias(int weaponID) { + const char *alias = NULL; +#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) static ICallWrapper *pWrapper = NULL; if (!pWrapper) @@ -148,16 +204,30 @@ const char *WeaponIDToAlias(int weaponID) retpass.size = sizeof(const char *); \ pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) } - const char *ret = NULL; unsigned char vstk[sizeof(int)]; unsigned char *vptr = vstk; *(int *)vptr = GetRealWeaponID(weaponID); - pWrapper->Execute(vstk, &ret); - - return ret; + pWrapper->Execute(vstk, &alias); +#else + static void *addr = NULL; + + if(!addr) + { + GET_MEMSIG("WeaponIDToAlias", 0); + } + + int realWeaponID = GetRealWeaponID(weaponID); + __asm + { + mov ecx, realWeaponID + call addr + mov alias, eax + } +#endif + return alias; } int GetRealWeaponID(int weaponId) { diff --git a/gamedata/sm-cstrike.games/game.csgo.txt b/gamedata/sm-cstrike.games/game.csgo.txt index b2c46c27..e8fadae0 100644 --- a/gamedata/sm-cstrike.games/game.csgo.txt +++ b/gamedata/sm-cstrike.games/game.csgo.txt @@ -32,7 +32,7 @@ //Offset into CheckRestartRound "CTTeamScoreOffset" { - "windows" "97" + "windows" "98" "linux" "124" "mac" "150" } @@ -45,7 +45,7 @@ } "ClanTagOffset" { - "windows" "15" + "windows" "12" "linux" "41" "mac" "22" } @@ -55,49 +55,49 @@ "RoundRespawn" { "library" "server" - "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x8B\xF1\x8B\x0D\x2A\x2A\x2A\x2A\x57\xE8\x2A\x2A\x2A\x2A\x84\xC0\x0F" + "windows" "\x55\x8B\xEC\x83\xEC\x08\x56\x8B\xF1\x8B\x0D\x2A\x2A\x2A\x2A\x57\x8B\x01\xFF\x50\x2A\x83" "linux" "@_ZN9CCSPlayer12RoundRespawnEv" "mac" "@_ZN9CCSPlayer12RoundRespawnEv" } "SwitchTeam" { "library" "server" - "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x57\x8B\x7D\x2A\x57\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x83\xC4" + "windows" "\x55\x8B\xEC\x83\xEC\x0C\x56\x8B\x75\x2A\x57\x8B\xF9\x85\xF6\x0F\x88\x2A\x2A\x2A\x2A\x3B\x35\x2A\x2A\x2A\x2A\x0F\x8D\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x83" "linux" "@_ZN9CCSPlayer10SwitchTeamEi" "mac" "@_ZN9CCSPlayer10SwitchTeamEi" } "HandleCommand_Buy_Internal" { "library" "server" - "windows" "\x55\x8B\xEC\x81\x2A\x2A\x2A\x2A\x2A\x53\x56\x57\x6A\x00\x8B\xF1\xE8" + "windows" "\x55\x8B\xEC\x83\xE4\x2A\x81\xEC\x2A\x2A\x2A\x2A\x83\x3D\x2A\x2A\x2A\x2A\x00\x53\x56\x57\x8B\xF9" "linux" "@_ZN9CCSPlayer26HandleCommand_Buy_InternalEPKcib" "mac" "@_ZN9CCSPlayer26HandleCommand_Buy_InternalEPKcib" } "CSWeaponDrop"//Wildcard first 6 bytes for CS:S DM { "library" "server" - "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x53\x56\x57\x8B\x7D\x08\x6A\x00\x68" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x81\xEC\x2A\x2A\x2A\x2A\x56\x8B\x75\x2A\x57\x6A\x00\x68" "linux" "@_ZN9CCSPlayer12CSWeaponDropEP17CBaseCombatWeaponbb" "mac" "@_ZN9CCSPlayer12CSWeaponDropEP17CBaseCombatWeaponbb" } "TerminateRound" { "library" "server" - "windows" "\x55\x8B\xEC\x83\xEC\x2A\x53\x8B\xD9\x8B\x2A\x2A\x2A\x2A\x2A\x56\x57\x33\xFF\x89" + "windows" "\x55\x8B\xEC\x83\x2A\x2A\x83\x2A\x2A\x53\x56\x8B\xF1\xF3\x0F\x2A\x2A\x2A\x2A\x57\x33\xFF\x89\x2A\x2A\x2A\xC7\x2A\x2A\x2A\x00\x00\x00\x00" "linux" "@_ZN12CCSGameRules14TerminateRoundEfi" "mac" "@_ZN12CCSGameRules14TerminateRoundEfi" } "GetTranslatedWeaponAlias" { "library" "server" - "windows" "\x55\x8B\xEC\x56\x57\x8B\x2A\x2A\x33\xF6\x8D\x9B\x2A\x2A\x2A\x2A\x8B\x04\xF5\x2A\x2A\x2A\x2A\x57\x50\xE8\x2A\x2A\x2A\x2A\x83\xC4\x2A\x85\xC0\x74\x2A\x46\x83\xFE\x2A\x72\x2A\x8B\xC7\x5F\x5E\x5D\xC3" + "windows" "\x55\x8B\xEC\x83\xEC\x08\x53\x33\xC0\x89\x4D\xF8\x56\x57\x89\x45\xFC\x33\xDB\x8B\xB3\x2A\x2A\x2A\x2A\x3B\xF1\x74\x2A\x8B\xF9\x90\x0F\xB6\x06\x0F\xB6\x17\x3B\xC2\x75\x2A\x85\xC0\x75\x2A\x8B\x45\xFC\x5F\x5E\x5B\x8B\x04\xC5\x2A\x2A\x2A\x2A\x8B\xE5\x5D\xC3\x85\xD2\x74\x2A\x8D\x48\xBF\x83\xF9\x19\x77\x2A\x83\xC0\x20\x8D\x4A\xBF\x83\xF9\x19\x77\x2A\x83\xC2\x20\x3B\xC2\x75\x2A\x0F\xB6\x46\x01\x83\xC6\x02\x0F\xB6\x57\x01\x83\xC7\x02\x3B\xC2\x75\x2A\x85\xC0\x75\x2A\x8B\x45\xFC\x5F\x5E\x5B\x8B\x04\xC5\x2A\x2A\x2A\x2A\x8B\xE5\x5D\xC3\x85\xD2\x74\x2A\x8D\x48\xBF\x83\xF9\x19\x77\x2A\x83\xC0\x20\x8D\x4A\xBF\x83\xF9\x19\x77\x2A\x83\xC2\x20\x3B\xC2\x0F\x84\x2A\x2A\x2A\x2A\x2B\xC2\x85\xC0\x74\x2A\xFF\x45\xFC\x83\xC3\x08\x8B\x4D\xF8\x81\xFB\xC0\x00\x00\x00\x0F\x82\x2A\x2A\x2A\x2A\x5F\x5E\x8B\xC1\x5B\x8B\xE5\x5D\xC3" "linux" "@_Z24GetTranslatedWeaponAliasPKc" "mac" "@_Z24GetTranslatedWeaponAliasPKc" } "GetWeaponInfo" { "library" "server" - "windows" "\x55\x8B\xEC\x8B\x4D\x2A\x33\xC0\x85\xC9\x74" + "windows" "\x55\x8B\xEC\x83\xEC\x08\x33\xC0\xEB\x2A\x8D\x9B\x00\x00\x00\x00\x39\x0C\xC5\x2A\x2A\x2A\x2A\x74\x2A\x40\x83\xF8\x38\x72\x2A\x33\xC0" "linux" "@_Z13GetWeaponInfo10CSWeaponID" "mac" "@_Z13GetWeaponInfo10CSWeaponID" } @@ -105,28 +105,28 @@ "CheckWinLimit" { "library" "server" - "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\x81\xF9\x2A\x2A\x2A\x2A\x75\x2A\x8B" + "windows" "\x55\x8B\xEC\x83\xE4\xF8\x83\xEC\x64\x53\x56\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\x81\xF9" "linux" "@_ZN12CCSGameRules17CheckRestartRoundEv" "mac" "@_ZN12CCSGameRules17CheckRestartRoundEv" } "AliasToWeaponID" { "library" "server" - "windows" "\x55\x8B\xEC\x57\x8B\x2A\x2A\x85\xFF\x75\x2A\x33\xC0\x5F\x5D\xC3\x56\x33\xF6\x8B\x04\xF5" + "windows" "\x55\x8B\xEC\x83\xEC\x08\x57\x8B\xF9\x33\xC0" "linux" "@_Z15AliasToWeaponIDPKc" "mac" "@_Z15AliasToWeaponIDPKc" } "WeaponIDToAlias" { "library" "server" - "windows" "\x55\x8B\xEC\x8B\x4D\x08\x33\xC0\xEB\x2A\x8D\x9B\x00\x00\x00\x00\x39\x0C\xC5\x2A\x2A\x2A\x2A\x74\x2A\x40\x83\xF8\x38\x72\x2A\x33\xC0\x5D\xC3\x8B\x04\xC5\x2A\x2A\x2A\x2A\x6A\x5F" + "windows" "\x33\xC0\x39\x0C\xC5\x2A\x2A\x2A\x2A\x74\x2A\x40\x83\xF8\x38\x72\x2A\x33\xC0\xC3\x6A\x5F" "linux" "@_Z15WeaponIDToAliasi" "mac" "@_Z15WeaponIDToAliasi" } "SetClanTag" { "library" "server" - "windows" "\x55\x8B\xEC\x8B\x2A\x2A\x85\xC0\x74\x2A\x6A\x10\x50\x81\xC1\x2A\x2A\x2A\x2A\x51" + "windows" "\x55\x8B\xEC\x8B\x55\x08\x85\xD2\x74\x2A\x8D\x81\xDC\x1F\x00\x00" "linux" "@_ZN9CCSPlayer10SetClanTagEPKc" "mac" "@_ZN9CCSPlayer10SetClanTagEPKc" } @@ -134,14 +134,14 @@ "GetAttributeInt" { "library" "server" - "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x08\x56\x57\x8B\xF1\x50\x8D\x4D\xFC\x51\xE8\x2A\x2A\x2A\x2A\x8B\x4D\x0C\x0F\x57\xC0\x8B\x7D\xFC\x83\xC4\x08\xF3\x0F\x11\x45\x08\x85\xC9\x74\x2A\x80\x2A\x2A\x00\x74\x2A\x57\x8D\x55\x08\x52\xE8\x2A\x2A\x2A\x2A\x84\xC0\x75\x2A\x57\x8B\xCE\xE8\x2A\x2A\x2A\x2A\x83\xF8\xFF\x74\x2A\x83\xF8\xFF\x7E\x2A\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x04\x81\x83\x2A\x2A\x05" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\xEC\x1C\x53\x8B\x5D\x0C\xC7\x44\x24\x04\x00\x00\x00\x00\x56\x8B\xF1\x89\x74\x24\x0C\x57\x8B\x7D\x08\x85\xDB\x74\x2A\x80\x7B\x44\x00\x74\x2A\x57\xE8\x2A\x2A\x2A\x2A\x8B\xC8\xE8\x2A\x2A\x2A\x2A\x89\x44\x24\x14\xE8\x2A\x2A\x2A\x2A\x8B\x70\x08\xE8\x2A\x2A\x2A\x2A\x3B\x70\x08\x74\x2A\x57\xE8\x2A\x2A\x2A\x2A\x8B\xC8\xE8\x2A\x2A\x2A\x2A\xEB\x2A\x8B\x44\x24\x14\x85\xC0\x74\x2A\x89\x44\x24\x1C\x8D\x4C\x24\x18\x8D\x44\x24\x0C\xC7\x44\x24\x18\x2A\x2A\x2A\x2A\x89\x44\x24\x20\x8B\x03\x51\x8B\xCB\xC6\x44\x24\x28\x00\xFF\x50\x64\x80\x7C\x24\x24\x00\x74\x2A\x8B\x44\x24\x0C" "linux" "@_ZNK16FileWeaponInfo_t15GetAttributeIntEPKcPK13CEconItemView" "mac" "@_ZNK16FileWeaponInfo_t15GetAttributeIntEPKcPK13CEconItemView" } "SetModelFromClass" { "library" "server" - "windows" "\x55\x8B\xEC\x51\x53\x56\x8B\xF1\x57\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\xD8" + "windows" "\x55\x8B\xEC\x83\xEC\x08\x56\x57\x8B\xF9\xC7\x45\xFC\x2A\x2A\x2A\x2A\x8B\x87" "linux" "@_ZN9CCSPlayer17SetModelFromClassEv" "mac" "@_ZN9CCSPlayer17SetModelFromClassEv" }