diff --git a/extensions/cstrike/natives.cpp b/extensions/cstrike/natives.cpp index f04a7488aa..b084422414 100644 --- a/extensions/cstrike/natives.cpp +++ b/extensions/cstrike/natives.cpp @@ -521,80 +521,6 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params) } #endif -static cell_t CS_GetClientClanTag(IPluginContext *pContext, const cell_t *params) -{ - static void *addr; - if (!addr) - { - if (!g_pGameConf->GetMemSig("SetClanTag", &addr) || !addr) - { - return pContext->ThrowNativeError("Failed to locate function"); - } - } - - CBaseEntity *pEntity; - if (!(pEntity = GetCBaseEntity(params[1], true))) - { - return pContext->ThrowNativeError("Client index %d is not valid", params[1]); - } - - static int tagOffsetOffset = -1; - static int tagOffset; - - if (tagOffsetOffset == -1) - { - if (!g_pGameConf->GetOffset("ClanTagOffset", &tagOffsetOffset)) - { - tagOffsetOffset = -1; - return pContext->ThrowNativeError("Unable to find ClanTagOffset gamedata"); - } - - tagOffset = *(int *)((intptr_t)addr + tagOffsetOffset); - } - - size_t len; - - const char *src = (char *)((intptr_t)pEntity + tagOffset); - pContext->StringToLocalUTF8(params[2], params[3], src, &len); - - return len; -} - -static cell_t CS_SetClientClanTag(IPluginContext *pContext, const cell_t *params) -{ - static ICallWrapper *pWrapper = NULL; - - if (!pWrapper) - { - REGISTER_NATIVE_ADDR("SetClanTag", - PassInfo pass[1]; \ - pass[0].flags = PASSFLAG_BYVAL; \ - pass[0].type = PassType_Basic; \ - pass[0].size = sizeof(char *); \ - pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 1)) - } - - CBaseEntity *pEntity; - if (!(pEntity = GetCBaseEntity(params[1], true))) - { - return pContext->ThrowNativeError("Client index %d is not valid", params[1]); - } - - char *szNewTag; - pContext->LocalToString(params[2], &szNewTag); - - unsigned char vstk[sizeof(CBaseEntity *) + sizeof(char *)]; - unsigned char *vptr = vstk; - - *(CBaseEntity **)vptr = pEntity; - vptr += sizeof(CBaseEntity *); - *(char **)vptr = szNewTag; - - pWrapper->Execute(vstk, NULL); - - return 1; -} - static cell_t CS_AliasToWeaponID(IPluginContext *pContext, const cell_t *params) { #if SOURCE_ENGINE == SE_CSGO @@ -838,6 +764,136 @@ static inline cell_t SetPlayerVar(IPluginContext *pContext, const cell_t *params return 0; } +static inline cell_t GetPlayerStringVar(IPluginContext *pContext, const cell_t *params, const char *varName) +{ + CBaseEntity *pPlayer = GetCBaseEntity(params[1], true); + if (!pPlayer) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + char *pVar = GetPlayerVarAddressOrError(varName, pContext, pPlayer); + if (pVar) + { + size_t len; + pContext->StringToLocalUTF8(params[2], params[3], pVar, &len); + return len; + } + + return 0; +} + +static inline cell_t SetPlayerStringVar(IPluginContext *pContext, const cell_t *params, const char *varName) +{ + CBaseEntity *pPlayer = GetCBaseEntity(params[1], true); + if (!pPlayer) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + char szSizeName[128]; + g_pSM->Format(szSizeName, sizeof(szSizeName), "%sSize", varName); + + int maxlen = 0; + if(!g_pGameConf->GetOffset(szSizeName, &maxlen)) + { + return pContext->ThrowNativeError("Failed to locate %s offset in gamedata", szSizeName); + } + + char *pVar = GetPlayerVarAddressOrError(varName, pContext, pPlayer); + + if (pVar) + { + char *newValue; + pContext->LocalToString(params[2], &newValue); + Q_strncpy(pVar, newValue, maxlen); + } + + return 1; +} + +static cell_t CS_GetClientClanTag(IPluginContext *pContext, const cell_t *params) +{ +#if SOURCE_ENGINE == SE_CSGO + return GetPlayerStringVar(pContext, params, "ClanTag"); +#else + static void *addr; + if (!addr) + { + if (!g_pGameConf->GetMemSig("SetClanTag", &addr) || !addr) + { + return pContext->ThrowNativeError("Failed to locate function"); + } + } + + CBaseEntity *pEntity; + if (!(pEntity = GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + static int tagOffsetOffset = -1; + static int tagOffset; + + if (tagOffsetOffset == -1) + { + if (!g_pGameConf->GetOffset("ClanTagOffset", &tagOffsetOffset)) + { + tagOffsetOffset = -1; + return pContext->ThrowNativeError("Unable to find ClanTagOffset gamedata"); + } + + tagOffset = *(int *)((intptr_t)addr + tagOffsetOffset); + } + + size_t len; + + const char *src = (char *)((intptr_t)pEntity + tagOffset); + pContext->StringToLocalUTF8(params[2], params[3], src, &len); + + return len; +#endif +} + +static cell_t CS_SetClientClanTag(IPluginContext *pContext, const cell_t *params) +{ +#if SOURCE_ENGINE == SE_CSGO + return SetPlayerStringVar(pContext, params, "ClanTag"); +#else + static ICallWrapper *pWrapper = NULL; + + if (!pWrapper) + { + REGISTER_NATIVE_ADDR("SetClanTag", + PassInfo pass[1]; \ + pass[0].flags = PASSFLAG_BYVAL; \ + pass[0].type = PassType_Basic; \ + pass[0].size = sizeof(char *); \ + pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 1)) + } + + CBaseEntity *pEntity; + if (!(pEntity = GetCBaseEntity(params[1], true))) + { + return pContext->ThrowNativeError("Client index %d is not valid", params[1]); + } + + char *szNewTag; + pContext->LocalToString(params[2], &szNewTag); + + unsigned char vstk[sizeof(CBaseEntity *) + sizeof(char *)]; + unsigned char *vptr = vstk; + + *(CBaseEntity **)vptr = pEntity; + vptr += sizeof(CBaseEntity *); + *(char **)vptr = szNewTag; + + pWrapper->Execute(vstk, NULL); + + return 1; +#endif +} + static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params) { return SetPlayerVar(pContext, params, "MVPs"); diff --git a/gamedata/sm-cstrike.games/game.csgo.txt b/gamedata/sm-cstrike.games/game.csgo.txt index 840829c8e0..1d5b23b8b4 100644 --- a/gamedata/sm-cstrike.games/game.csgo.txt +++ b/gamedata/sm-cstrike.games/game.csgo.txt @@ -52,13 +52,6 @@ "linux64" "174" "mac64" "177" } - "ClanTagOffset" - { - "windows" "12" - "linux" "29" - "linux64" "13" - "mac64" "12" - } //Offset into HandleCommand_Buy_Internal "CCSPlayerInventoryOffset" { @@ -168,14 +161,6 @@ "linux64" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x58\x64\x48\x8B\x04\x25\x28\x00\x00\x00\x48\x89\x45\xC8\x31\xC0\x4C\x8B\x2D\x46\xD3\xBB\x00" "mac64" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x83\xEC\x58\x49\x89\xFD\x48\x8B\x1D\x85\x76\x60\x00" } - "SetClanTag" - { - "library" "server" - "windows" "\x55\x8B\xEC\x8B\x55\x08\x85\xD2\x74\x2A\x8D\x81\x5C\x25\x00\x00" - "linux" "\x55\x89\xE5\x83\xEC\x18\x8B\x45\x0C\x85\xC0\x74\x2A\x89\x44\x24\x04\x8B\x45\x08\xC7\x44\x24\x08\x10\x00\x00\x00" - "linux64" "\x55\x48\x85\xF6\x48\x89\xE5\x74\x2A\x5D\x48\x81\xC7\x90\x28\x00\x00" - "mac64" "\x55\x48\x89\xE5\x48\x85\xF6\x74\x2A\x48\x81\xC7\x88\x28\x00\x00" - } "SetModelFromClass" { "library" "server" @@ -253,4 +238,38 @@ } } } + + // Used for SetClanTag and GetClanTag + // to find the ClanTag offset start with the string "ClanTagChanged". Inside the function there is 2 KeyValues::GetString, one for "tag", and one for "name" + // The respective function underneath each are SetClanTag and SetClanName. + // To get the offset of the base (m_flGroundAccelLinearFracLastTime) unqiue string is "------- accelspeed = %f, flGoalSpeed = %f, flStoredAccel = %f\n" + // Inside that function right above the debug message is an if with a call to CBaseEntity::NetworkStateChanged and a member set with the same offset. + // Do math. + // Note: Second offset can be skipped by simply dumping the netprops instead on each os although the distance will probably be the same on all. + + "#default" + { + "Keys" + { + "ClanTagBase" "m_flGroundAccelLinearFracLastTime" + } + + "Offsets" + { + "ClanTagSize" + { + "windows" "16" + "linux" "16" + "linux64" "16" + "mac64" "16" + } + "ClanTag" + { + "windows" "140" + "linux" "140" + "linux64" "140" + "mac64" "140" + } + } + } }