Initial CSGO GetWeaponPrice fixes
This commit is contained in:
@@ -61,9 +61,21 @@ DETOUR_DECL_MEMBER1(DetourHandleBuy, int, const char *, weapon)
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
|
||||
#elif defined(WIN32)
|
||||
DETOUR_DECL_MEMBER2(DetourWeaponPrice, int, CEconItemView *, pEconItem, int, iUnknown)
|
||||
#else
|
||||
DETOUR_DECL_MEMBER3(DetourWeaponPrice, int, CEconItemView *, pEconItem, int, iUnknown, float, fUnknown)
|
||||
#endif
|
||||
{
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)();
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)();
|
||||
#elif defined(WIN32)
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)(pEconItem, iUnknown);
|
||||
#else
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)(pEconItem, iUnknown, fUnknown);
|
||||
#endif
|
||||
|
||||
if (lastclient == -1)
|
||||
return price;
|
||||
|
||||
@@ -71,19 +83,6 @@ DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
|
||||
|
||||
return CallPriceForward(lastclient, weapon_name, price);
|
||||
}
|
||||
#else
|
||||
DETOUR_DECL_MEMBER2(DetourWeaponPrice, int, const char *, szAttribute, CEconItemView *, pEconItem)
|
||||
{
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)(szAttribute, pEconItem);
|
||||
|
||||
if(lastclient == -1 || strcmp(szAttribute, "in game price") != 0)
|
||||
return price;
|
||||
|
||||
const char *weapon_name = reinterpret_cast<char *>(this+weaponNameOffset);
|
||||
|
||||
return CallPriceForward(lastclient, weapon_name, price);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32)
|
||||
DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
|
||||
@@ -201,8 +200,15 @@ bool CreateWeaponPriceDetour()
|
||||
}
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
DWeaponPrice = DETOUR_CREATE_MEMBER(DetourWeaponPrice, "GetAttributeInt");
|
||||
#if SOURCE_ENGINE == SE_CSGO && defined(WIN32)
|
||||
void *pGetWeaponPriceAddress = GetWeaponPriceFunction();
|
||||
|
||||
if(!pGetWeaponPriceAddress)
|
||||
{
|
||||
g_pSM->LogError(myself, "GetWeaponPrice detour could not be initialized - Disabled OnGetWeaponPrice forward.");
|
||||
}
|
||||
|
||||
DWeaponPrice = DETOUR_CREATE_MEMBER(DetourWeaponPrice, pGetWeaponPriceAddress);
|
||||
#else
|
||||
DWeaponPrice = DETOUR_CREATE_MEMBER(DetourWeaponPrice, "GetWeaponPrice");
|
||||
#endif
|
||||
|
||||
@@ -419,6 +419,7 @@ static cell_t CS_GetTranslatedWeaponAlias(IPluginContext *pContext, const cell_t
|
||||
|
||||
static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
|
||||
if (!IsValidWeaponID(params[2]))
|
||||
return pContext->ThrowNativeError("Invalid WeaponID passed for this game");
|
||||
|
||||
@@ -426,6 +427,7 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
//Hard code return values for weapons that dont call GetWeaponPrice and always use default value.
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
|
||||
if (id == WEAPON_C4 || id == WEAPON_KNIFE || id == WEAPON_KNIFE_GG)
|
||||
return 0;
|
||||
#else
|
||||
@@ -458,23 +460,49 @@ 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();
|
||||
if(!pGetWeaponPrice)
|
||||
{
|
||||
return pContext->ThrowNativeError("Failed to locate function");
|
||||
}
|
||||
|
||||
PassInfo pass[2];
|
||||
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);
|
||||
ret.flags = PASSFLAG_BYVAL;
|
||||
ret.type = PassType_Basic;
|
||||
ret.size = sizeof(int);
|
||||
pWrapper = g_pBinTools->CreateCall(pGetWeaponPrice, CallConv_ThisCall, &ret, pass, 2);
|
||||
}
|
||||
#else
|
||||
if (!pWrapper)
|
||||
{
|
||||
REGISTER_NATIVE_ADDR("GetAttributeInt",
|
||||
PassInfo pass[2]; \
|
||||
REGISTER_NATIVE_ADDR("GetWeaponPrice",
|
||||
PassInfo pass[3]; \
|
||||
PassInfo ret; \
|
||||
pass[0].flags = PASSFLAG_BYVAL; \
|
||||
pass[0].type = PassType_Basic; \
|
||||
pass[0].size = sizeof(char *); \
|
||||
pass[0].size = sizeof(CEconItemView *); \
|
||||
pass[1].flags = PASSFLAG_BYVAL; \
|
||||
pass[1].type = PassType_Basic; \
|
||||
pass[1].size = sizeof(CEconItemView *); \
|
||||
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, 2))
|
||||
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:
|
||||
@@ -552,14 +580,22 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
||||
pGetView->Execute(vstk_view, &view);
|
||||
}
|
||||
|
||||
unsigned char vstk[sizeof(void *) * 2 + sizeof(char *)];
|
||||
#if defined(WIN32)
|
||||
unsigned char vstk[sizeof(void *) * 2 + sizeof(int)];
|
||||
#else
|
||||
unsigned char vstk[sizeof(void *) * 2 + sizeof(int) + sizeof(float)];
|
||||
#endif
|
||||
unsigned char *vptr = vstk;
|
||||
|
||||
*(void **)vptr = info;
|
||||
vptr += sizeof(void *);
|
||||
*(const char **)vptr = "in game price";
|
||||
vptr += sizeof(const char *);
|
||||
*(CEconItemView **)vptr = view;
|
||||
vptr += sizeof(CEconItemView *);
|
||||
*(int *)vptr = 0;
|
||||
#if !defined(WIN32)
|
||||
vptr += sizeof(int);
|
||||
*(float *)vptr = 1.0;
|
||||
#endif
|
||||
|
||||
int price = 0;
|
||||
pWrapper->Execute(vstk, &price);
|
||||
|
||||
@@ -229,6 +229,56 @@ const char *WeaponIDToAlias(int weaponID)
|
||||
#endif
|
||||
return alias;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO && defined(WIN32)
|
||||
void *GetWeaponPriceFunction()
|
||||
{
|
||||
static void *pGetWeaponPriceAddress = NULL;
|
||||
|
||||
if(pGetWeaponPriceAddress == NULL)
|
||||
{
|
||||
void *pAddress = NULL;
|
||||
int offset = 0;
|
||||
int callOffset = 0;
|
||||
const char* byteCheck = NULL;
|
||||
|
||||
if(!g_pGameConf->GetMemSig("GetWeaponPrice", &pAddress) || pAddress == NULL)
|
||||
{
|
||||
g_pSM->LogError(myself, "Failed to get GetWeaponPrice address.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!g_pGameConf->GetOffset("GetWeaponPriceFunc", &offset))
|
||||
{
|
||||
g_pSM->LogError(myself, "Failed to get GetWeaponPriceFunc offset.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
byteCheck = g_pGameConf->GetKeyValue("GetWeaponPriceByteCheck");
|
||||
|
||||
if(byteCheck == NULL)
|
||||
{
|
||||
g_pSM->LogError(myself, "Failed to get GetWeaponPriceByteCheck keyvalue.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t iByte = strtoul(byteCheck, NULL, 16);
|
||||
|
||||
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);
|
||||
|
||||
pGetWeaponPriceAddress = (void *)((intptr_t)pAddress + offset + callOffset + sizeof(int));
|
||||
}
|
||||
|
||||
return pGetWeaponPriceAddress;
|
||||
}
|
||||
#endif
|
||||
|
||||
int GetRealWeaponID(int weaponId)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
|
||||
@@ -165,4 +165,6 @@ int GetFakeWeaponID(int weaponId);
|
||||
|
||||
bool IsValidWeaponID(int weaponId);
|
||||
|
||||
void *GetWeaponPriceFunction();
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user