Semi-tested fix for CS:GO GetWeaponPrice on Linux.
This commit is contained in:
parent
90cefa9daf
commit
c4487b74ee
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user