Use keyvalue to get weapon price, change void * to appropriate class names.
This commit is contained in:
parent
22033c21f2
commit
0e7a3b0173
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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,37 +455,21 @@ 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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidWeaponID(params[2]))
|
static const char *pPriceKey = NULL;
|
||||||
return pContext->ThrowNativeError("Invalid WeaponID passed for this game");
|
|
||||||
|
|
||||||
/*static int iLoadoutSlotOffset = -1;
|
if (!pPriceKey)
|
||||||
|
|
||||||
if (iLoadoutSlotOffset == -1)
|
|
||||||
{
|
{
|
||||||
if (!g_pGameConf->GetOffset("LoadoutSlotOffset", &iLoadoutSlotOffset) || iLoadoutSlotOffset == -1)
|
pPriceKey = g_pGameConf->GetKeyValue("PriceKey");
|
||||||
|
if (!pPriceKey)
|
||||||
{
|
{
|
||||||
iLoadoutSlotOffset = -1;
|
return pContext->ThrowNativeError("Failed to get PriceKey KeyValue.");
|
||||||
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]);
|
if (!IsValidWeaponID(params[2]))
|
||||||
|
return pContext->ThrowNativeError("Invalid WeaponID passed for this game");
|
||||||
|
|
||||||
if (id == WEAPON_C4 || id == WEAPON_KNIFE || id == WEAPON_KNIFE_GG)
|
int id = GetRealWeaponID(params[2]);
|
||||||
return 0;
|
|
||||||
else if (id == WEAPON_NIGHTVISION)
|
|
||||||
return 1250;
|
|
||||||
else if (id == WEAPON_DEFUSER)
|
|
||||||
return 400;
|
|
||||||
|
|
||||||
char classname[128];
|
char classname[128];
|
||||||
|
|
||||||
@ -495,16 +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);
|
||||||
|
|
||||||
void *pWpnData = GetCCSWpnDataFromItemDef(pDef);
|
if (!pDef)
|
||||||
|
|
||||||
if (!pWpnData)
|
|
||||||
{
|
{
|
||||||
return pContext->ThrowNativeError("Failed to get CCSWeaponData for %s", classname);
|
return pContext->ThrowNativeError("Failed to get CEconItemDefinition for %s", classname);
|
||||||
}
|
}
|
||||||
|
|
||||||
int price = *(int *)((intptr_t)pWpnData + g_iPriceOffset);
|
KeyValues *pAttributes = pDef->m_pKv->FindKey("attributes", false);
|
||||||
|
|
||||||
|
if (!pAttributes)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Failed to get item attributes keyvalue for %s", classname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int price = pAttributes->GetInt(pPriceKey, 0);
|
||||||
|
|
||||||
if (params[3] || weaponNameOffset == -1)
|
if (params[3] || weaponNameOffset == -1)
|
||||||
return price;
|
return price;
|
||||||
@ -559,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;
|
||||||
|
@ -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(void *)];
|
unsigned char vstk[sizeof(CEconItemView *)];
|
||||||
unsigned char *vptr = vstk;
|
unsigned char *vptr = vstk;
|
||||||
|
|
||||||
*(CEconItemView **)vptr = view;
|
*(CEconItemView **)vptr = view;
|
||||||
|
|
||||||
void *pWpnData = NULL;
|
CCSWeaponData *pWpnData = NULL;
|
||||||
|
|
||||||
pWrapper->Execute(vstk, &pWpnData);
|
pWrapper->Execute(vstk, &pWpnData);
|
||||||
|
|
||||||
return pWpnData;
|
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,45 +235,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *GetCCSWpnDataFromItemDef(void *pItemDef)
|
|
||||||
{
|
|
||||||
if (!pItemDef)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
static ICallWrapper *pWrapper = NULL;
|
|
||||||
|
|
||||||
if (!pWrapper)
|
|
||||||
{
|
|
||||||
// In windows this is a sig to the inlined code in GetCCSWeaponData
|
|
||||||
// We abuse the fact that the ItemDef is stored in ecx
|
|
||||||
REGISTER_ADDR("GetCCSWeaponDataFromDef", NULL,
|
|
||||||
PassInfo pass[1]; \
|
|
||||||
PassInfo retpass; \
|
|
||||||
pass[0].flags = PASSFLAG_BYVAL; \
|
|
||||||
pass[0].type = PassType_Basic; \
|
|
||||||
pass[0].size = sizeof(void *); \
|
|
||||||
retpass.flags = PASSFLAG_BYVAL; \
|
|
||||||
retpass.type = PassType_Basic; \
|
|
||||||
retpass.size = sizeof(void *); \
|
|
||||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &retpass, pass, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char vstk[sizeof(void *)];
|
|
||||||
unsigned char *vptr = vstk;
|
|
||||||
|
|
||||||
*(void **)vptr = pItemDef;
|
|
||||||
|
|
||||||
void *pWpnData = NULL;
|
|
||||||
pWrapper->Execute(vstk, &pWpnData);
|
|
||||||
|
|
||||||
return pWpnData;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_CSGO
|
#if SOURCE_ENGINE != SE_CSGO
|
||||||
|
@ -33,13 +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);
|
|
||||||
void *GetCCSWpnDataFromItemDef(void *pItemDef);
|
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[] =
|
||||||
{
|
{
|
||||||
|
@ -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.
|
||||||
@ -150,14 +154,6 @@
|
|||||||
"windows" "\x85\xC9\x75\x2A\x33\xC0\xC3\xE8\x2A\x2A\x2A\x2A\x8B"
|
"windows" "\x85\xC9\x75\x2A\x33\xC0\xC3\xE8\x2A\x2A\x2A\x2A\x8B"
|
||||||
"linux" "\x55\x89\xE5\x83\xEC\x18\x8B\x45\x08\x85\xC0\x74\x2A\x89\x04\x24"
|
"linux" "\x55\x89\xE5\x83\xEC\x18\x8B\x45\x08\x85\xC0\x74\x2A\x89\x04\x24"
|
||||||
}
|
}
|
||||||
//In windows this is to inlined code.
|
|
||||||
//It is within GetCCSWeaponData
|
|
||||||
"GetCCSWeaponDataFromDef"
|
|
||||||
{
|
|
||||||
"library" "server"
|
|
||||||
"windows" "\x8B\x01\x56\x8B\x35\x2A\x2A\x2A\x2A\xFF\x10\x0F\xB7\xC0\xB9\x2A\x2A\x2A\x2A\x50\xFF\x56\x08\x5E\xC3"
|
|
||||||
"linux" "\x55\x31\xC0\x89\xE5\x53\x83\xEC\x14\x8B\x55\x08\x85\xD2"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user