Merge pull request #671 from alliedmodders/csgo-weaponpricefix

Fix CS_GetWeaponPrice returning incorrect weapon prices.
This commit is contained in:
Ruben Gonzalez 2017-09-04 08:49:33 -04:00 committed by GitHub
commit b4d34ef062
5 changed files with 82 additions and 73 deletions

View File

@ -26,16 +26,17 @@ int weaponNameOffset = -1;
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_CSGO
DETOUR_DECL_MEMBER3(DetourHandleBuy, int, int, iLoadoutSlot, void *, pWpnDataRef, bool, bRebuy) DETOUR_DECL_MEMBER3(DetourHandleBuy, int, int, iLoadoutSlot, void *, pWpnDataRef, bool, bRebuy)
{ {
int client = gamehelpers->EntityToBCompatRef(reinterpret_cast<CBaseEntity *>(this)); CBaseEntity *pEntity = reinterpret_cast<CBaseEntity *>(this);
int client = gamehelpers->EntityToBCompatRef(pEntity);
CEconItemView *pView = GetEconItemView(this, iLoadoutSlot); CEconItemView *pView = GetEconItemView(pEntity, iLoadoutSlot);
if (!pView) if (!pView)
{ {
return DETOUR_MEMBER_CALL(DetourHandleBuy)(iLoadoutSlot, pWpnDataRef, bRebuy); return DETOUR_MEMBER_CALL(DetourHandleBuy)(iLoadoutSlot, pWpnDataRef, bRebuy);
} }
void *pWpnData = GetCCSWeaponData(pView); CCSWeaponData *pWpnData = GetCCSWeaponData(pView);
if (!pWpnData) if (!pWpnData)
{ {

View File

@ -34,7 +34,6 @@
#include "forwards.h" #include "forwards.h"
#include "util_cstrike.h" #include "util_cstrike.h"
#include <server_class.h> #include <server_class.h>
#include <iplayerinfo.h>
int g_iPriceOffset = -1; int g_iPriceOffset = -1;
@ -456,38 +455,22 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Client index %d is not valid", params[1]); return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
} }
static const char *pPriceKey = NULL;
if (!pPriceKey)
{
pPriceKey = g_pGameConf->GetKeyValue("PriceKey");
if (!pPriceKey)
{
return pContext->ThrowNativeError("Failed to get PriceKey KeyValue.");
}
}
if (!IsValidWeaponID(params[2])) if (!IsValidWeaponID(params[2]))
return pContext->ThrowNativeError("Invalid WeaponID passed for this game"); return pContext->ThrowNativeError("Invalid WeaponID passed for this game");
static int iLoadoutSlotOffset = -1;
if (iLoadoutSlotOffset == -1)
{
if (!g_pGameConf->GetOffset("LoadoutSlotOffset", &iLoadoutSlotOffset) || iLoadoutSlotOffset == -1)
{
iLoadoutSlotOffset = -1;
return pContext->ThrowNativeError("Failed to get LoadoutSlotOffset offset.");
}
}
if (g_iPriceOffset == -1)
{
if (!g_pGameConf->GetOffset("WeaponPrice", &g_iPriceOffset) || g_iPriceOffset == -1)
{
g_iPriceOffset = -1;
return pContext->ThrowNativeError("Failed to get WeaponPrice offset");
}
}
int id = GetRealWeaponID(params[2]); int id = GetRealWeaponID(params[2]);
if (id == WEAPON_C4 || id == WEAPON_KNIFE || id == WEAPON_KNIFE_GG)
return 0;
else if (id == WEAPON_NIGHTVISION)
return 1250;
else if (id == WEAPON_DEFUSER)
return 400;
char classname[128]; char classname[128];
if (id < CSGOWeapon_KEVLAR) if (id < CSGOWeapon_KEVLAR)
@ -495,25 +478,21 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
else else
Q_snprintf(classname, sizeof(classname), "item_%s", WeaponIDToAlias(params[2])); Q_snprintf(classname, sizeof(classname), "item_%s", WeaponIDToAlias(params[2]));
void *pDef = GetItemDefintionByName(classname); CEconItemDefinition *pDef = GetItemDefintionByName(classname);
int iLoadoutSlot = *(int *)((intptr_t)pDef + iLoadoutSlotOffset); if (!pDef)
CEconItemView *pView = GetEconItemView(pEntity, iLoadoutSlot);
if (!pView)
{ {
return pContext->ThrowNativeError("Failed to get CEconItemVIiew for %s", classname); return pContext->ThrowNativeError("Failed to get CEconItemDefinition for %s", classname);
} }
void *pWpnData = GetCCSWeaponData(pView); KeyValues *pAttributes = pDef->m_pKv->FindKey("attributes", false);
if (!pWpnData) if (!pAttributes)
{ {
return pContext->ThrowNativeError("Failed to get CCSWeaponData for %s", classname); return pContext->ThrowNativeError("Failed to get item attributes keyvalue for %s", classname);
} }
int price = *(int *)((intptr_t)pWpnData + g_iPriceOffset); int price = pAttributes->GetInt(pPriceKey, 0);
if (params[3] || weaponNameOffset == -1) if (params[3] || weaponNameOffset == -1)
return price; return price;
@ -568,14 +547,11 @@ static cell_t CS_SetClientClanTag(IPluginContext *pContext, const cell_t *params
if (!pWrapper) if (!pWrapper)
{ {
REGISTER_NATIVE_ADDR("SetClanTag", REGISTER_NATIVE_ADDR("SetClanTag",
PassInfo pass[2]; \ PassInfo pass[1]; \
pass[0].flags = PASSFLAG_BYVAL; \ pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \ pass[0].type = PassType_Basic; \
pass[0].size = sizeof(CBaseEntity *); \ pass[0].size = sizeof(char *); \
pass[1].flags = PASSFLAG_BYVAL; \ pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 1))
pass[1].type = PassType_Basic; \
pass[1].size = sizeof(char *); \
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 2))
} }
CBaseEntity *pEntity; CBaseEntity *pEntity;
@ -618,6 +594,10 @@ static cell_t CS_AliasToWeaponID(IPluginContext *pContext, const cell_t *params)
{ {
return SMCSWeapon_M4A1; return SMCSWeapon_M4A1;
} }
else if (strstr(weapon, "revolver") != NULL)
{
return SMCSWeapon_DEAGLE;
}
#endif #endif
int id = GetFakeWeaponID(AliasToWeaponID(weapon)); int id = GetFakeWeaponID(AliasToWeaponID(weapon));

View File

@ -66,7 +66,7 @@
// We only really care about m4a1/m4a4 as price differs between them // We only really care about m4a1/m4a4 as price differs between them
// thisPtrOffset = 9472/9492 // thisPtrOffset = 9472/9492
CEconItemView *GetEconItemView(void *pEntity, int iSlot) CEconItemView *GetEconItemView(CBaseEntity *pEntity, int iSlot)
{ {
if (!pEntity) if (!pEntity)
return NULL; return NULL;
@ -116,7 +116,7 @@ CEconItemView *GetEconItemView(void *pEntity, int iSlot)
} }
} }
int client = gamehelpers->EntityToBCompatRef(reinterpret_cast<CBaseEntity *>(pEntity)); int client = gamehelpers->EntityToBCompatRef(pEntity);
IPlayerInfo *playerinfo = playerhelpers->GetGamePlayer(client)->GetPlayerInfo(); IPlayerInfo *playerinfo = playerhelpers->GetGamePlayer(client)->GetPlayerInfo();
@ -143,37 +143,33 @@ CEconItemView *GetEconItemView(void *pEntity, int iSlot)
return ret; return ret;
} }
void *GetCCSWeaponData(CEconItemView *view) CCSWeaponData *GetCCSWeaponData(CEconItemView *view)
{ {
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
if (!pWrapper) if (!pWrapper)
{ {
REGISTER_ADDR("GetCCSWeaponData", NULL, REGISTER_ADDR("GetCCSWeaponData", NULL,
PassInfo pass[1]; \
PassInfo retpass; \ PassInfo retpass; \
pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \
pass[0].size = sizeof(CEconItemView *); \
retpass.flags = PASSFLAG_BYVAL; \ retpass.flags = PASSFLAG_BYVAL; \
retpass.type = PassType_Basic; \ retpass.type = PassType_Basic; \
retpass.size = sizeof(void *); \ retpass.size = sizeof(CCSWeaponData *); \
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &retpass, pass, 1)) pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &retpass, NULL, 0))
} }
unsigned char vstk[sizeof(const char *)]; unsigned char vstk[sizeof(CEconItemView *)];
unsigned char *vptr = vstk; unsigned char *vptr = vstk;
*(CEconItemView **)vptr = view; *(CEconItemView **)vptr = view;
void *pDef = NULL; CCSWeaponData *pWpnData = NULL;
pWrapper->Execute(vstk, &pDef); pWrapper->Execute(vstk, &pWpnData);
return pDef; return pWpnData;
} }
void *GetItemSchema() CEconItemSchema *GetItemSchema()
{ {
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
@ -192,15 +188,15 @@ void *GetItemSchema()
//In windows this is actually ItemSystem() + 4 is ItemSchema //In windows this is actually ItemSystem() + 4 is ItemSchema
#ifdef WIN32 #ifdef WIN32
return (void *)((intptr_t)pSchema + 4); return (CEconItemSchema *)((intptr_t)pSchema + 4);
#else #else
return pSchema; return (CEconItemSchema *)pSchema;
#endif #endif
} }
void *GetItemDefintionByName(const char *classname) CEconItemDefinition *GetItemDefintionByName(const char *classname)
{ {
void *pSchema = GetItemSchema(); CEconItemSchema *pSchema = GetItemSchema();
if (!pSchema) if (!pSchema)
return NULL; return NULL;
@ -225,7 +221,7 @@ void *GetItemDefintionByName(const char *classname)
ret.flags = PASSFLAG_BYVAL; ret.flags = PASSFLAG_BYVAL;
ret.type = PassType_Basic; ret.type = PassType_Basic;
ret.size = sizeof(void *); ret.size = sizeof(CEconItemDefinition *);
pWrapper = g_pBinTools->CreateVCall(offset, 0, 0, &ret, pass, 1); pWrapper = g_pBinTools->CreateVCall(offset, 0, 0, &ret, pass, 1);
@ -239,7 +235,7 @@ void *GetItemDefintionByName(const char *classname)
vptr += sizeof(void *); vptr += sizeof(void *);
*(const char **)vptr = classname; *(const char **)vptr = classname;
void *pItemDef = NULL; CEconItemDefinition *pItemDef = NULL;
pWrapper->Execute(vstk, &pItemDef); pWrapper->Execute(vstk, &pItemDef);
return pItemDef; return pItemDef;

View File

@ -33,12 +33,39 @@
#define _INCLUDE_CSTRIKE_UTIL_H_ #define _INCLUDE_CSTRIKE_UTIL_H_
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_CSGO
class CEconItemView; #include "extension.h"
CEconItemView *GetEconItemView(void *pEntity, int iSlot); class CEconItemView;
void *GetCCSWeaponData(CEconItemView *view); class CCSWeaponData;
void *GetItemSchema(); class CEconItemSchema;
void *GetItemDefintionByName(const char *classname);
class CEconItemDefinition
{
public:
void **m_pVtable;
KeyValues *m_pKv;
uint16_t m_iDefinitionIndex;
int GetDefaultLoadoutSlot()
{
static int iLoadoutSlotOffset = -1;
if (iLoadoutSlotOffset == -1)
{
if (!g_pGameConf->GetOffset("LoadoutSlotOffset", &iLoadoutSlotOffset) || iLoadoutSlotOffset == -1)
{
iLoadoutSlotOffset = -1;
return -1;
}
}
return *(int *)((intptr_t)this + iLoadoutSlotOffset);
}
};
CEconItemView *GetEconItemView(CBaseEntity *pEntity, int iSlot);
CCSWeaponData *GetCCSWeaponData(CEconItemView *view);
CEconItemSchema *GetItemSchema();
CEconItemDefinition *GetItemDefintionByName(const char *classname);
static const char *szWeaponInfo[] = static const char *szWeaponInfo[] =
{ {

View File

@ -13,6 +13,10 @@
{ {
"#default" "#default"
{ {
"Keys"
{
"PriceKey" "in game price"
}
"Offsets" "Offsets"
{ {
// Offset of szClassName in CCSWeaponData, szDefaultName is @ 140 which returns the default weapon class for the loadoutslot ignoring the users inventory. // Offset of szClassName in CCSWeaponData, szDefaultName is @ 140 which returns the default weapon class for the loadoutslot ignoring the users inventory.
@ -143,6 +147,7 @@
"linux" "\x55\x89\xE5\x83\xEC\x28\x89\x5D\xF4\x8B\x5D\x08\x89\x75\xF8\x89\x7D\xFC\x89\x1C\x24\xE8\x2A\x2A\x2A\x2A\x83\xF8\x02" "linux" "\x55\x89\xE5\x83\xEC\x28\x89\x5D\xF4\x8B\x5D\x08\x89\x75\xF8\x89\x7D\xFC\x89\x1C\x24\xE8\x2A\x2A\x2A\x2A\x83\xF8\x02"
} }
//GetCCSWeaponData Found in HandleCommand_Buy_Internal //GetCCSWeaponData Found in HandleCommand_Buy_Internal
//Uses an econitemview
"GetCCSWeaponData" "GetCCSWeaponData"
{ {
"library" "server" "library" "server"