diff --git a/extensions/cstrike/natives.cpp b/extensions/cstrike/natives.cpp index 75773f07..3a0efff8 100644 --- a/extensions/cstrike/natives.cpp +++ b/extensions/cstrike/natives.cpp @@ -466,7 +466,6 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params) #if SOURCE_ENGINE == SE_CSGO static ICallWrapper *pWrapper = NULL; -#if defined(WIN32) if(!pWrapper) { void *pGetWeaponPrice = GetWeaponPriceFunction(); @@ -475,7 +474,13 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Failed to locate function"); } - PassInfo pass[2]; + +#ifdef _WIN32 + const size_t GWP_ARGC = 2; +#else + const size_t GWP_ARGC = 3; +#endif + PassInfo pass[GWP_ARGC]; PassInfo ret; pass[0].flags = PASSFLAG_BYVAL; pass[0].type = PassType_Basic; @@ -483,32 +488,17 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params) pass[1].flags = PASSFLAG_BYVAL; pass[1].type = PassType_Basic; pass[1].size = sizeof(int); +#ifndef _WIN32 + pass[2].flags = PASSFLAG_BYVAL; + pass[2].type = PassType_Float; + pass[2].size = sizeof(float); +#endif ret.flags = PASSFLAG_BYVAL; ret.type = PassType_Basic; ret.size = sizeof(int); - pWrapper = g_pBinTools->CreateCall(pGetWeaponPrice, CallConv_ThisCall, &ret, pass, 2); + pWrapper = g_pBinTools->CreateCall(pGetWeaponPrice, CallConv_ThisCall, &ret, pass, GWP_ARGC); } -#else - if (!pWrapper) - { - REGISTER_NATIVE_ADDR("GetWeaponPrice", - PassInfo pass[3]; \ - PassInfo ret; \ - pass[0].flags = PASSFLAG_BYVAL; \ - pass[0].type = PassType_Basic; \ - pass[0].size = sizeof(CEconItemView *); \ - pass[1].flags = PASSFLAG_BYVAL; \ - pass[1].type = PassType_Basic; \ - pass[1].size = sizeof(int); \ - pass[2].flags = PASSFLAG_BYVAL; \ - pass[2].type = PassType_Float; \ - pass[2].size = sizeof(float); \ - ret.flags = PASSFLAG_BYVAL; \ - ret.type = PassType_Basic; \ - ret.size = sizeof(int); \ - pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &ret, pass, 3)) - } -#endif + // Get a CEconItemView for the m4 // Found in CCSPlayer::HandleCommand_Buy_Internal // Linux a1 - CCSPlayer *pEntity, v5 - Player Team, a3 - ItemLoadoutSlot -1 use default loadoutslot: diff --git a/extensions/cstrike/util_cstrike.cpp b/extensions/cstrike/util_cstrike.cpp index 58e0573f..9306dd93 100644 --- a/extensions/cstrike/util_cstrike.cpp +++ b/extensions/cstrike/util_cstrike.cpp @@ -230,50 +230,58 @@ const char *WeaponIDToAlias(int weaponID) return alias; } -#if SOURCE_ENGINE == SE_CSGO && defined(WIN32) +#if SOURCE_ENGINE == SE_CSGO void *GetWeaponPriceFunction() { - static void *pGetWeaponPriceAddress = NULL; - - if(pGetWeaponPriceAddress == NULL) + static void *pGetWeaponPriceAddress = nullptr; + if (pGetWeaponPriceAddress) { - void *pAddress = NULL; - int offset = 0; - int callOffset = 0; - const char* byteCheck = NULL; + return pGetWeaponPriceAddress; + } - if(!g_pGameConf->GetMemSig("GetWeaponPrice", &pAddress) || pAddress == NULL) - { - g_pSM->LogError(myself, "Failed to get GetWeaponPrice address."); - return NULL; - } + void *pAddress = nullptr; + int offset = 0; + int callOffset = 0; + const char* byteCheck = nullptr; - if(!g_pGameConf->GetOffset("GetWeaponPriceFunc", &offset)) - { - g_pSM->LogError(myself, "Failed to get GetWeaponPriceFunc offset."); - return NULL; - } + if (!g_pGameConf->GetMemSig("GetWeaponPrice", &pAddress) || !pAddress) + { + g_pSM->LogError(myself, "Failed to get GetWeaponPrice address."); + return nullptr; + } - byteCheck = g_pGameConf->GetKeyValue("GetWeaponPriceByteCheck"); + if (!g_pGameConf->GetOffset("GetWeaponPriceFunc", &offset)) + { + // If no offset specified, assume that GetWeaponPrice is the func we want, and not just our + // helper to find the real one. + pGetWeaponPriceAddress = pAddress; + return pGetWeaponPriceAddress; + } - if(byteCheck == NULL) - { - g_pSM->LogError(myself, "Failed to get GetWeaponPriceByteCheck keyvalue."); - return NULL; - } +#if defined( _WIN32 ) + byteCheck = g_pGameConf->GetKeyValue("GetWeaponPriceByteCheck"); +#elif defined( _LINUX ) + byteCheck = g_pGameConf->GetKeyValue("GetWeaponPriceByteCheck_Linux"); +#else + // We don't compile for csgo on mac anymore + #error Unsupported platform +#endif + if (byteCheck == nullptr) + { + g_pSM->LogError(myself, "Failed to get GetWeaponPriceByteCheck keyvalue."); + return nullptr; + } - uint8_t iByte = strtoul(byteCheck, NULL, 16); + uint8_t iByte = strtoul(byteCheck, nullptr, 16); + if (iByte != *(uint8_t *)((intptr_t)pAddress + (offset-1))) + { + g_pSM->LogError(myself, "GetWeaponPrice Byte check failed."); + return nullptr; + } - if(iByte != *(uint8_t *)((intptr_t)pAddress + (offset-1))) - { - g_pSM->LogError(myself, "GetWeaponPrice Byte check failed."); - return NULL; - } + callOffset = *(uint32_t *)((intptr_t)pAddress + offset); - callOffset = *(uint32_t *)((intptr_t)pAddress + offset); - - pGetWeaponPriceAddress = (void *)((intptr_t)pAddress + offset + callOffset + sizeof(int)); - } + pGetWeaponPriceAddress = (void *)((intptr_t)pAddress + offset + callOffset + sizeof(int)); return pGetWeaponPriceAddress; } diff --git a/gamedata/sm-cstrike.games/game.csgo.txt b/gamedata/sm-cstrike.games/game.csgo.txt index ed19952e..2ba7780e 100644 --- a/gamedata/sm-cstrike.games/game.csgo.txt +++ b/gamedata/sm-cstrike.games/game.csgo.txt @@ -16,6 +16,7 @@ "Keys" { "GetWeaponPriceByteCheck" "E9" + "GetWeaponPriceByteCheck_Linux" "E8" } "Offsets" { @@ -69,11 +70,13 @@ "GetWeaponPriceFunc" { "windows" "98" + "linux" "139" } //This is GetWeaponPriceFunc offset -1 (only used by GDC) "GetWeaponPriceFuncGDC" { "windows" "97" + "windows" "138" } } "Signatures" @@ -145,7 +148,8 @@ "windows" "\x55\x8B\xEC\x8B\x55\x08\x85\xD2\x74\x28\x8D\x81\x2A\x2A\x2A\x2A\x56\x8D\x70\x0F\x3B\xC6\x73\x16\x2B\xD0\x8D" "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" } - //In windows this is CCSPlayer::GetWeaponPrice NOT CCSWeaponInfo::GetWeaponPrice + // Since it's not possible to make a unique signature for CCSWeaponInfo::GetWeaponInfo, this is instead a signature to a + // function that calls it. The offset from the signature to the CCSWeaponInfo func offset is the GetWeaponPriceFunc offset. "GetWeaponPrice" { "library" "server"