Fix CS_GetWeaponPrice returning incorrect value for M4A1 in CS:GO
--HG-- extra : amend_source : b4fa218795b59a82f98c0c8142e3bf36161f88d6
This commit is contained in:
parent
c5f496670d
commit
162c69bfda
@ -52,6 +52,7 @@ int CallPriceForward(int client, const char *weapon_name, int price);
|
|||||||
#define WEAPON_ASSAULTSUIT 51
|
#define WEAPON_ASSAULTSUIT 51
|
||||||
#define WEAPON_NIGHTVISION 52
|
#define WEAPON_NIGHTVISION 52
|
||||||
#define WEAPON_DEFUSER 53
|
#define WEAPON_DEFUSER 53
|
||||||
|
#define WEAPON_M4 16
|
||||||
#else
|
#else
|
||||||
#define WEAPON_C4 6
|
#define WEAPON_C4 6
|
||||||
#define WEAPON_KNIFE 28
|
#define WEAPON_KNIFE 28
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#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;
|
||||||
|
|
||||||
@ -426,6 +427,11 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
|||||||
return pContext->ThrowNativeError("Failed to get weaponinfo");
|
return pContext->ThrowNativeError("Failed to get weaponinfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBaseEntity *pEntity;
|
||||||
|
if (!(pEntity = GetCBaseEntity(params[1], true)))
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
|
||||||
|
}
|
||||||
#if SOURCE_ENGINE == SE_CSGO
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
static ICallWrapper *pWrapper = NULL;
|
static ICallWrapper *pWrapper = NULL;
|
||||||
|
|
||||||
@ -446,14 +452,91 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
|||||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &ret, pass, 2))
|
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &ret, pass, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
// v4 = *(int (__cdecl **)(_DWORD, _DWORD, _DWORD))(*(_DWORD *)(a1 + 9492) + 36); // offset 9
|
||||||
|
// v6 = v4(a1 + 9492, v5, a3);
|
||||||
|
// Windows v5 - CCSPlayer *pEntity a4 - ItemLoadoutSlot -1 use default loadoutslot:
|
||||||
|
// v8 = (*(int (__stdcall **)(_DWORD, int))(*(_DWORD *)(v5 + 9472) + 32))(*(_DWORD *)(v5 + 760), a4); // offset 8
|
||||||
|
// The function is CCSPlayerInventory::GetItemInLoadout(int, int)
|
||||||
|
// We can pass NULL view to the GetAttribute to use default loadoutslot.
|
||||||
|
// We only really care about m4a1/m4a4 as price differs between them
|
||||||
|
// thisPtrOffset = 9472/9492
|
||||||
|
|
||||||
|
static ICallWrapper *pGetView = NULL;
|
||||||
|
static int thisPtrOffset = -1;
|
||||||
|
CEconItemView *view = NULL;
|
||||||
|
|
||||||
|
if(!pGetView)
|
||||||
|
{
|
||||||
|
int offset = -1;
|
||||||
|
int byteOffset = -1;
|
||||||
|
void *pHandleCommandBuy = NULL;
|
||||||
|
if (!g_pGameConf->GetOffset("GetItemInLoadout", &offset) || offset == -1)
|
||||||
|
{
|
||||||
|
smutils->LogError(myself, "Failed to get GetItemInLoadout offset. Reverting to NULL ItemView");
|
||||||
|
}
|
||||||
|
else if (!g_pGameConf->GetOffset("CCSPlayerInventoryOffset", &byteOffset) || byteOffset == -1)
|
||||||
|
{
|
||||||
|
smutils->LogError(myself, "Failed to get CCSPlayerInventoryOffset offset. Reverting to NULL ItemView");
|
||||||
|
}
|
||||||
|
else if (!g_pGameConf->GetMemSig("HandleCommand_Buy_Internal", &pHandleCommandBuy) || !pHandleCommandBuy)
|
||||||
|
{
|
||||||
|
smutils->LogError(myself, "Failed to get HandleCommand_Buy_Internal function. Reverting to NULL ItemView");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thisPtrOffset = *(int *)((intptr_t)pHandleCommandBuy + byteOffset);
|
||||||
|
|
||||||
|
PassInfo pass[2];
|
||||||
|
PassInfo ret;
|
||||||
|
pass[0].flags = PASSFLAG_BYVAL;
|
||||||
|
pass[0].type = PassType_Basic;
|
||||||
|
pass[0].size = sizeof(int);
|
||||||
|
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(void *);
|
||||||
|
|
||||||
|
g_RegNatives.Register(pGetView);
|
||||||
|
pGetView = g_pBinTools->CreateVCall(offset, 0, 0, &ret, pass, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPlayerInfo *playerinfo = playerhelpers->GetGamePlayer(params[1])->GetPlayerInfo();
|
||||||
|
if(pGetView && thisPtrOffset != -1 && playerinfo)
|
||||||
|
{
|
||||||
|
//If the gun isnt an M4 we ignore this as M4 is the only one that differs in price based on Loadout item.
|
||||||
|
int iLoadoutSlot = -1;
|
||||||
|
if(id == WEAPON_M4)
|
||||||
|
{
|
||||||
|
iLoadoutSlot = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char vstk_view[sizeof(void *) + sizeof(int) * 2];
|
||||||
|
unsigned char *vptr_view = vstk_view;
|
||||||
|
|
||||||
|
*(void **)vptr_view = (void *)((intptr_t)pEntity + thisPtrOffset);
|
||||||
|
vptr_view += sizeof(void *);
|
||||||
|
*(int *)vptr_view = playerinfo->GetTeamIndex();
|
||||||
|
vptr_view += sizeof(int);
|
||||||
|
*(int *)vptr_view = iLoadoutSlot;
|
||||||
|
|
||||||
|
pGetView->Execute(vstk_view, &view);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char vstk[sizeof(void *) * 2 + sizeof(char *)];
|
unsigned char vstk[sizeof(void *) * 2 + sizeof(char *)];
|
||||||
unsigned char *vptr = vstk;
|
unsigned char *vptr = vstk;
|
||||||
|
|
||||||
*(void **)vptr = info;
|
*(void **)vptr = info;
|
||||||
vptr += sizeof(void *);
|
vptr += sizeof(void *);
|
||||||
*(const char **)vptr = "in game price";
|
*(const char **)vptr = "in game price";
|
||||||
vptr += sizeof(const char **);
|
vptr += sizeof(const char *);
|
||||||
*(CEconItemView **)vptr = NULL;
|
*(CEconItemView **)vptr = view;
|
||||||
|
|
||||||
int price = 0;
|
int price = 0;
|
||||||
pWrapper->Execute(vstk, &price);
|
pWrapper->Execute(vstk, &price);
|
||||||
@ -470,12 +553,6 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
|||||||
int price = *(int *)((intptr_t)info + g_iPriceOffset);
|
int price = *(int *)((intptr_t)info + g_iPriceOffset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CBaseEntity *pEntity;
|
|
||||||
if (!(pEntity = GetCBaseEntity(params[1], true)))
|
|
||||||
{
|
|
||||||
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params[3] || weaponNameOffset == -1)
|
if (params[3] || weaponNameOffset == -1)
|
||||||
return price;
|
return price;
|
||||||
|
|
||||||
|
@ -49,6 +49,19 @@
|
|||||||
"linux" "41"
|
"linux" "41"
|
||||||
"mac" "22"
|
"mac" "22"
|
||||||
}
|
}
|
||||||
|
//Offset into HandleCommand_Buy_Internal
|
||||||
|
"CCSPlayerInventoryOffset"
|
||||||
|
{
|
||||||
|
"windows" "285"
|
||||||
|
"linux" "87"
|
||||||
|
"mac" "109"
|
||||||
|
}
|
||||||
|
"GetItemInLoadout"
|
||||||
|
{
|
||||||
|
"windows" "8"
|
||||||
|
"linux" "9"
|
||||||
|
"mac" "9"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"Signatures"
|
"Signatures"
|
||||||
{
|
{
|
||||||
@ -66,10 +79,10 @@
|
|||||||
"linux" "@_ZN9CCSPlayer10SwitchTeamEi"
|
"linux" "@_ZN9CCSPlayer10SwitchTeamEi"
|
||||||
"mac" "@_ZN9CCSPlayer10SwitchTeamEi"
|
"mac" "@_ZN9CCSPlayer10SwitchTeamEi"
|
||||||
}
|
}
|
||||||
"HandleCommand_Buy_Internal"
|
"HandleCommand_Buy_Internal"//Wildcard first 6 bytes for getting address for weapon price.
|
||||||
{
|
{
|
||||||
"library" "server"
|
"library" "server"
|
||||||
"windows" "\x55\x8B\xEC\x83\xE4\x2A\x81\xEC\x2A\x2A\x2A\x2A\x83\x3D\x2A\x2A\x2A\x2A\x00\x53\x56\x57\x8B\xF9"
|
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x81\xEC\x2A\x2A\x2A\x2A\x83\x3D\x2A\x2A\x2A\x2A\x00\x53\x56\x57\x8B\xF9"
|
||||||
"linux" "@_ZN9CCSPlayer26HandleCommand_Buy_InternalEPKcib"
|
"linux" "@_ZN9CCSPlayer26HandleCommand_Buy_InternalEPKcib"
|
||||||
"mac" "@_ZN9CCSPlayer26HandleCommand_Buy_InternalEPKcib"
|
"mac" "@_ZN9CCSPlayer26HandleCommand_Buy_InternalEPKcib"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user