mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 14:25:38 +03:00
Merge pull request #68 from Arkshine/feature-improve-client-buy
Improve client buy forward
This commit is contained in:
commit
7d69a78d06
@ -3,6 +3,10 @@ import os.path
|
|||||||
|
|
||||||
binary = AMXX.MetaModule(builder, 'cstrike')
|
binary = AMXX.MetaModule(builder, 'cstrike')
|
||||||
|
|
||||||
|
binary.compiler.defines += [
|
||||||
|
'HAVE_STDINT_H',
|
||||||
|
]
|
||||||
|
|
||||||
binary.sources = [
|
binary.sources = [
|
||||||
'sdk/amxxmodule.cpp',
|
'sdk/amxxmodule.cpp',
|
||||||
'amxx_api.cpp',
|
'amxx_api.cpp',
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#define OFFSET_INTERNALMODEL 126 + EXTRAOFFSET
|
#define OFFSET_INTERNALMODEL 126 + EXTRAOFFSET
|
||||||
#define OFFSET_NVGOGGLES 129 + EXTRAOFFSET
|
#define OFFSET_NVGOGGLES 129 + EXTRAOFFSET
|
||||||
#define OFFSET_DEFUSE_PLANT 193 + EXTRAOFFSET
|
#define OFFSET_DEFUSE_PLANT 193 + EXTRAOFFSET
|
||||||
|
#define OFFSET_MENU 205 + EXTRAOFFSET
|
||||||
#define OFFSET_VIP 209 + EXTRAOFFSET
|
#define OFFSET_VIP 209 + EXTRAOFFSET
|
||||||
#define OFFSET_TK 216 + EXTRAOFFSET // 040926
|
#define OFFSET_TK 216 + EXTRAOFFSET // 040926
|
||||||
#define OFFSET_HOSTAGEKILLS 217 + EXTRAOFFSET
|
#define OFFSET_HOSTAGEKILLS 217 + EXTRAOFFSET
|
||||||
@ -162,19 +163,19 @@
|
|||||||
* CS_OnBuy forward
|
* CS_OnBuy forward
|
||||||
*/
|
*/
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#define CS_IDENT_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri"
|
#define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb"
|
||||||
#define CS_IDENT_BUYITEM "_Z7BuyItemP11CBasePlayeri"
|
#define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc"
|
||||||
#define CS_IDENT_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb"
|
#define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib"
|
||||||
#define CS_IDENT_HIDDEN_STATE false
|
#define CS_IDENT_HIDDEN_STATE false
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#define CS_IDENT_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri"
|
#define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb"
|
||||||
#define CS_IDENT_BUYITEM "_Z7BuyItemP11CBasePlayeri"
|
#define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc"
|
||||||
#define CS_IDENT_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb"
|
#define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib"
|
||||||
#define CS_IDENT_HIDDEN_STATE true
|
#define CS_IDENT_HIDDEN_STATE true
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
#define CS_IDENT_CANBUYTHIS "\\x53\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x2A\\x2A\\x57"
|
#define CS_IDENT_GIVENSHIELD "\\x56\\x8B\\x2A\\x57\\x33\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\xB0"
|
||||||
#define CS_IDENT_BUYITEM "\\x53\\x56\\x8B\\x2A\\x2A\\x2A\\xBB\\x2A\\x2A\\x2A\\x2A\\x57\\x53"
|
#define CS_IDENT_GIVENAMEDITEM "\\x8B\\x2A\\x2A\\x2A\\x56\\x57\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x2B"
|
||||||
#define CS_IDENT_BUYGUNAMMO "\\x56\\x57\\x8B\\x2A\\x2A\\x2A\\x6A\\x2A\\x8B\\x2A\\xE8\\x2A\\x2A\\x2A\\x2A\\x84\\x2A\\x0F"
|
#define CS_IDENT_ADDACCOUNT "\\x8B\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x03"
|
||||||
#define CS_IDENT_HIDDEN_STATE false
|
#define CS_IDENT_HIDDEN_STATE false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -347,4 +348,24 @@ enum
|
|||||||
CS_SET_AUGSG552_ZOOM,
|
CS_SET_AUGSG552_ZOOM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
Menu_OFF,
|
||||||
|
Menu_ChooseTeam,
|
||||||
|
Menu_IGChooseTeam,
|
||||||
|
Menu_ChooseAppearance,
|
||||||
|
Menu_Buy,
|
||||||
|
Menu_BuyPistol,
|
||||||
|
Menu_BuyRifle,
|
||||||
|
Menu_BuyMachineGun,
|
||||||
|
Menu_BuyShotgun,
|
||||||
|
Menu_BuySubMachineGun,
|
||||||
|
Menu_BuyItem,
|
||||||
|
Menu_Radio1,
|
||||||
|
Menu_Radio2,
|
||||||
|
Menu_Radio3,
|
||||||
|
Menu_ClientBuy
|
||||||
|
|
||||||
|
} Menu;
|
||||||
|
|
||||||
#endif // CSTRIKE_DATA_H
|
#endif // CSTRIKE_DATA_H
|
@ -33,21 +33,27 @@
|
|||||||
#include "CstrikeDatas.h"
|
#include "CstrikeDatas.h"
|
||||||
#include "CstrikeUtils.h"
|
#include "CstrikeUtils.h"
|
||||||
#include "CDetour/detours.h"
|
#include "CDetour/detours.h"
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
|
using namespace SourceMod; // hashmap
|
||||||
|
|
||||||
void CtrlDetours_ClientCommand(bool set);
|
void CtrlDetours_ClientCommand(bool set);
|
||||||
void CtrlDetours_BuyCommands(bool set);
|
void CtrlDetours_BuyCommands(bool set);
|
||||||
|
|
||||||
int g_CSCliCmdFwd = -1;
|
int ForwardInternalCommand = -1;
|
||||||
int g_CSBuyCmdFwd = -1;
|
int ForwardOnBuy = -1;
|
||||||
|
int ForwardOnBuyAttempt = -1;
|
||||||
|
|
||||||
int *g_UseBotArgs = NULL;
|
int *UseBotArgs = NULL;
|
||||||
const char **g_BotArgs = NULL;
|
const char **BotArgs = NULL;
|
||||||
|
|
||||||
CDetour *g_ClientCommandDetour = NULL;
|
CDetour *ClientCommandDetour = NULL;
|
||||||
CDetour *g_CanBuyThisDetour = NULL;
|
CDetour *GiveShieldDetour = NULL;
|
||||||
CDetour *g_BuyItemDetour = NULL;
|
CDetour *GiveNamedItemDetour = NULL;
|
||||||
CDetour *g_BuyGunAmmoDetour = NULL;
|
CDetour *AddAccountDetour = NULL;
|
||||||
|
|
||||||
|
int CurrentItemId = 0;
|
||||||
|
StringHashMap<int> ItemAliasList;
|
||||||
|
|
||||||
void InitializeHacks()
|
void InitializeHacks()
|
||||||
{
|
{
|
||||||
@ -65,76 +71,170 @@ void ShutdownHacks()
|
|||||||
CtrlDetours_BuyCommands(false);
|
CtrlDetours_BuyCommands(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef CMD_ARGV
|
||||||
|
|
||||||
|
const char *CMD_ARGV(int i)
|
||||||
|
{
|
||||||
|
if (*UseBotArgs)
|
||||||
|
{
|
||||||
|
if (i < 4)
|
||||||
|
{
|
||||||
|
return BotArgs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_engfuncs.pfnCmd_Argv(i);
|
||||||
|
}
|
||||||
|
|
||||||
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
|
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
|
||||||
{
|
{
|
||||||
if (*g_UseBotArgs)
|
const char *command = CMD_ARGV(0);
|
||||||
{
|
|
||||||
int client = ENTINDEX(pEdict);
|
// A new command is triggered, reset variable, always.
|
||||||
const char *args = *g_BotArgs;
|
CurrentItemId = 0;
|
||||||
|
|
||||||
if (MF_ExecuteForward(g_CSCliCmdFwd, static_cast<cell>(client), args) > 0)
|
// Purpose is to retrieve an item id based on alias name or selected item from menu,
|
||||||
|
// to be used in OnBuy* forwards.
|
||||||
|
if ((ForwardOnBuyAttempt != -1 || ForwardOnBuy != -1) && command && *command)
|
||||||
|
{
|
||||||
|
// Just for safety.
|
||||||
|
command = UTIL_StringToLower((char *)command);
|
||||||
|
|
||||||
|
int itemId = 0;
|
||||||
|
|
||||||
|
// Handling buy via menu.
|
||||||
|
if (!strcmp(command, "menuselect"))
|
||||||
|
{
|
||||||
|
int slot = atoi(CMD_ARGV(1));
|
||||||
|
|
||||||
|
if (slot > 0 && slot < 9)
|
||||||
|
{
|
||||||
|
static const int menuItemsTe[][9] =
|
||||||
|
{
|
||||||
|
/* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIMAMMO, CSI_SECAMMO, 0 },
|
||||||
|
/* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_ELITE, 0, 0, 0 },
|
||||||
|
/* Menu_BuyRifle */ { 0, CSI_GALI, CSI_AK47, CSI_SCOUT, CSI_SG552, CSI_AWP, CSI_G3SG1, 0, 0 },
|
||||||
|
/* Menu_BuyMachineGun */ { 0, CSI_M249, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
/* Menu_BuyShotgun */ { 0, CSI_M3, CSI_XM1014, 0, 0, 0, 0, 0, 0 },
|
||||||
|
/* Menu_BuySubMachineGun */ { 0, CSI_MAC10, CSI_MP5NAVY, CSI_UMP45, CSI_P90, 0, 0, 0, 0 },
|
||||||
|
/* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int menuItemsCt[][9] =
|
||||||
|
{
|
||||||
|
/* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIMAMMO, CSI_SECAMMO, 0 },
|
||||||
|
/* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_FIVESEVEN, 0, 0, 0 },
|
||||||
|
/* Menu_BuyRifle */ { 0, CSI_FAMAS, CSI_SCOUT, CSI_M4A1, CSI_AUG, CSI_SG550, CSI_AWP, 0, 0 },
|
||||||
|
/* Menu_BuyMachineGun */ { 0, CSI_M249, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
/* Menu_BuyShotgun */ { 0, CSI_M3, CSI_XM1014, 0, 0, 0, 0, 0, 0 },
|
||||||
|
/* Menu_BuySubMachineGun */ { 0, CSI_TMP, CSI_MP5NAVY, CSI_UMP45, CSI_P90, 0, 0, 0, 0 },
|
||||||
|
/* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELDGUN }
|
||||||
|
};
|
||||||
|
|
||||||
|
int menuId = *((int *)pEdict->pvPrivateData + OFFSET_MENU);
|
||||||
|
if (menuId >= Menu_Buy && menuId <= Menu_BuyItem)
|
||||||
|
{
|
||||||
|
int team = *((int *)pEdict->pvPrivateData + OFFSET_TEAM);
|
||||||
|
switch (team)
|
||||||
|
{
|
||||||
|
case TEAM_T: itemId = menuItemsTe[menuId - 4][slot]; break; // -4 because array is zero-based and Menu_Buy* constants starts from 4.
|
||||||
|
case TEAM_CT:itemId = menuItemsCt[menuId - 4][slot]; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemId)
|
||||||
|
{
|
||||||
|
CurrentItemId = itemId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Handling buy via alias
|
||||||
|
{
|
||||||
|
if (ItemAliasList.retrieve(command, &itemId))
|
||||||
|
{
|
||||||
|
CurrentItemId = itemId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int client = ENTINDEX(pEdict);
|
||||||
|
|
||||||
|
if (ForwardInternalCommand != -1 && *UseBotArgs)
|
||||||
|
{
|
||||||
|
const char *args = *BotArgs;
|
||||||
|
|
||||||
|
if (MF_ExecuteForward(ForwardInternalCommand, static_cast<cell>(client), args) > 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ForwardOnBuyAttempt != -1 &&
|
||||||
|
CurrentItemId &&
|
||||||
|
MF_IsPlayerAlive(client) &&
|
||||||
|
MF_ExecuteForward(ForwardOnBuyAttempt, static_cast<cell>(client), static_cast<cell>(CurrentItemId)) > 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DETOUR_STATIC_CALL(C_ClientCommand)(pEdict);
|
DETOUR_STATIC_CALL(C_ClientCommand)(pEdict);
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_DECL_STATIC2(CanBuyThis, bool, void*, pvPlayer, int, weaponId) // bool CanBuyThis(CBasePlayer *pPlayer, int weaponId)
|
DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlayer::GiveNamedItem(const char *pszName)
|
||||||
{
|
{
|
||||||
if (weaponId != CSI_SHIELDGUN) // This will be handled before with BuyItem. Avoiding duplicated call.
|
// If the current item id is not null, this means player has triggers a buy command.
|
||||||
|
if (CurrentItemId)
|
||||||
{
|
{
|
||||||
int player = PrivateToIndex(pvPlayer);
|
int client = PrivateToIndex(this);
|
||||||
|
|
||||||
if (MF_IsPlayerAlive(player) && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(player), static_cast<cell>(weaponId)) > 0)
|
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), static_cast<cell>(CurrentItemId)) > 0)
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DETOUR_STATIC_CALL(CanBuyThis)(pvPlayer, weaponId);
|
|
||||||
}
|
|
||||||
|
|
||||||
DETOUR_DECL_STATIC2(BuyItem, void, void*, pvPlayer, int, iSlot) // void BuyItem(CBasePlayer *pPlayer, int iSlot)
|
|
||||||
{
|
|
||||||
int player = PrivateToIndex(pvPlayer);
|
|
||||||
|
|
||||||
if (MF_IsPlayerAlive(player))
|
|
||||||
{
|
|
||||||
static const int itemSlotToWeaponId[] = {-1, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELDGUN};
|
|
||||||
|
|
||||||
if (iSlot >= 1 && iSlot <= 8 && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(player), static_cast<cell>(itemSlotToWeaponId[iSlot])) > 0)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_STATIC_CALL(BuyItem)(pvPlayer, iSlot);
|
// From here, forward is not blocked, resetting this
|
||||||
|
// to ignore code in AddAccount which is called right after.
|
||||||
|
CurrentItemId = 0;
|
||||||
|
|
||||||
|
// Give me my item!
|
||||||
|
DETOUR_MEMBER_CALL(GiveNamedItem)(pszName);
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bBlinkMoney) // bool BuyGunAmmo(CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney)
|
DETOUR_DECL_MEMBER1(GiveShield, void, bool, bRetire) // void CBasePlayer::GiveShield(bool bRetire)
|
||||||
{
|
{
|
||||||
int player = PrivateToIndex(pvPlayer);
|
// Special case for shield. Game doesn't use GiveNamedItem() to give a shield.
|
||||||
|
if (CurrentItemId == CSI_SHIELDGUN)
|
||||||
if (MF_IsPlayerAlive(player))
|
|
||||||
{
|
{
|
||||||
edict_t *pWeapon = PrivateToEdict(pvWeapon);
|
int client = PrivateToIndex(this);
|
||||||
|
|
||||||
if (pWeapon)
|
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_SHIELDGUN) > 0)
|
||||||
{
|
{
|
||||||
int weaponId = *((int *)pWeapon->pvPrivateData + OFFSET_WEAPONTYPE);
|
return;
|
||||||
int ammoId = (1<<weaponId & BITS_PISTOLS) ? CSI_SECAMMO : CSI_PRIMAMMO;
|
|
||||||
|
|
||||||
if (MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(player), static_cast<cell>(ammoId)) > 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DETOUR_STATIC_CALL(BuyGunAmmo)(pvPlayer, pvWeapon, bBlinkMoney);
|
// From here, forward is not blocked, resetting this
|
||||||
|
// to ignore code in AddAccount which is called right after.
|
||||||
|
CurrentItemId = 0;
|
||||||
|
|
||||||
|
// Give me my shield!
|
||||||
|
DETOUR_MEMBER_CALL(GiveShield)(bRetire);
|
||||||
|
}
|
||||||
|
|
||||||
|
DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
|
||||||
|
{
|
||||||
|
// No buy command or forward not blocked.
|
||||||
|
// Resuming game flow.
|
||||||
|
if (!CurrentItemId)
|
||||||
|
{
|
||||||
|
DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's reset this right away to avoid issues.
|
||||||
|
CurrentItemId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -146,33 +246,88 @@ void CtrlDetours_ClientCommand(bool set)
|
|||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
|
|
||||||
g_UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS);
|
UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS);
|
||||||
g_BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS);
|
BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS);
|
||||||
|
|
||||||
#elif defined(__linux__) || defined(__APPLE__)
|
#elif defined(__linux__) || defined(__APPLE__)
|
||||||
|
|
||||||
g_UseBotArgs = (int *)UTIL_FindAddressFromEntry(CS_IDENT_USEBOTARGS, CS_IDENT_HIDDEN_STATE);
|
UseBotArgs = (int *)UTIL_FindAddressFromEntry(CS_IDENT_USEBOTARGS, CS_IDENT_HIDDEN_STATE);
|
||||||
g_BotArgs = (const char **)UTIL_FindAddressFromEntry(CS_IDENT_BOTARGS, CS_IDENT_HIDDEN_STATE);
|
BotArgs = (const char **)UTIL_FindAddressFromEntry(CS_IDENT_BOTARGS, CS_IDENT_HIDDEN_STATE);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target);
|
ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target);
|
||||||
|
|
||||||
if (g_ClientCommandDetour == NULL)
|
if (ClientCommandDetour == NULL)
|
||||||
{
|
{
|
||||||
MF_Log("No Client Commands detour could be initialized - Disabled Client Command forward.");
|
MF_Log("No Client Commands detour could be initialized - Disabled Client Command forward.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (g_ClientCommandDetour)
|
if (ClientCommandDetour)
|
||||||
g_ClientCommandDetour->Destroy();
|
ClientCommandDetour->Destroy();
|
||||||
|
|
||||||
|
ItemAliasList.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleDetour_ClientCommands(bool enable)
|
void ToggleDetour_ClientCommands(bool enable)
|
||||||
{
|
{
|
||||||
if (g_ClientCommandDetour)
|
if (ClientCommandDetour)
|
||||||
(enable) ? g_ClientCommandDetour->EnableDetour() : g_ClientCommandDetour->DisableDetour();
|
(enable) ? ClientCommandDetour->EnableDetour() : ClientCommandDetour->DisableDetour();
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
// Build the item alias list.
|
||||||
|
// Used in ClientCommand to check and get fastly item id from alias name.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *alias;
|
||||||
|
int id;
|
||||||
|
|
||||||
|
} itemBuyAliasInfo;
|
||||||
|
|
||||||
|
itemBuyAliasInfo aliasToId[] =
|
||||||
|
{
|
||||||
|
{ "p228" , CSI_P228 }, { "228compact" , CSI_P228 },
|
||||||
|
{ "scout" , CSI_SCOUT }, { "hegren" , CSI_HEGRENADE },
|
||||||
|
{ "xm1014" , CSI_XM1014 }, { "autoshotgun", CSI_XM1014 },
|
||||||
|
{ "mac10" , CSI_MAC10 }, { "aug" , CSI_AUG },
|
||||||
|
{ "bullpup" , CSI_AUG }, { "sgren" , CSI_SMOKEGRENADE },
|
||||||
|
{ "elites" , CSI_ELITE }, { "fn57" , CSI_FIVESEVEN },
|
||||||
|
{ "fiveseven" , CSI_FIVESEVEN }, { "ump45" , CSI_UMP45 },
|
||||||
|
{ "sg550" , CSI_SG550 }, { "krieg550" , CSI_SG550 },
|
||||||
|
{ "galil" , CSI_GALI }, { "defender" , CSI_GALI },
|
||||||
|
{ "famas" , CSI_FAMAS }, { "clarion" , CSI_FAMAS },
|
||||||
|
{ "usp" , CSI_USP }, { "km45" , CSI_USP },
|
||||||
|
{ "glock" , CSI_GLOCK18 }, { "9x19mm" , CSI_GLOCK18 },
|
||||||
|
{ "awp" , CSI_AWP }, { "magnum" , CSI_AWP },
|
||||||
|
{ "mp5" , CSI_MP5NAVY }, { "smg" , CSI_MP5NAVY },
|
||||||
|
{ "m249" , CSI_M249 }, { "m3" , CSI_M3 },
|
||||||
|
{ "12gauge" , CSI_M3 }, { "m4a1" , CSI_M4A1 },
|
||||||
|
{ "tmp" , CSI_TMP }, { "mp" , CSI_TMP },
|
||||||
|
{ "g3sg1" , CSI_G3SG1 }, { "d3au1" , CSI_G3SG1 },
|
||||||
|
{ "flash" , CSI_FLASHBANG }, { "deagle" , CSI_DEAGLE },
|
||||||
|
{ "nighthawk" , CSI_DEAGLE }, { "sg552" , CSI_SG552 },
|
||||||
|
{ "krieg552" , CSI_SG552 }, { "ak47" , CSI_AK47 },
|
||||||
|
{ "cv47" , CSI_AK47 }, { "p90" , CSI_P90 },
|
||||||
|
{ "c90" , CSI_P90 }, { "vest" , CSI_VEST },
|
||||||
|
{ "vesthelm" , CSI_VESTHELM }, { "defuser" , CSI_DEFUSER },
|
||||||
|
{ "nvgs" , CSI_NVGS }, { "shield" , CSI_SHIELDGUN },
|
||||||
|
{ "buyammo1" , CSI_PRIMAMMO }, { "primammo" , CSI_PRIMAMMO },
|
||||||
|
{ "buyammo2" , CSI_SECAMMO }, { "secammo" , CSI_SECAMMO },
|
||||||
|
{ NULL , 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; aliasToId[i].alias != NULL; ++i)
|
||||||
|
{
|
||||||
|
ItemAliasList.insert(aliasToId[i].alias, aliasToId[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ItemAliasList.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -180,40 +335,42 @@ void CtrlDetours_BuyCommands(bool set)
|
|||||||
{
|
{
|
||||||
if (set)
|
if (set)
|
||||||
{
|
{
|
||||||
void *canBuyThisAddress = UTIL_FindAddressFromEntry(CS_IDENT_CANBUYTHIS, CS_IDENT_HIDDEN_STATE);
|
void *giveShieldAddress = UTIL_FindAddressFromEntry(CS_IDENT_GIVENSHIELD , CS_IDENT_HIDDEN_STATE);
|
||||||
void *buyItemAddress = UTIL_FindAddressFromEntry(CS_IDENT_BUYITEM, CS_IDENT_HIDDEN_STATE);
|
void *giveNamedItemAddress = UTIL_FindAddressFromEntry(CS_IDENT_GIVENAMEDITEM, CS_IDENT_HIDDEN_STATE);
|
||||||
void *buyGunAmmoAddress = UTIL_FindAddressFromEntry(CS_IDENT_BUYGUNAMMO, CS_IDENT_HIDDEN_STATE);
|
void *addAccountAddress = UTIL_FindAddressFromEntry(CS_IDENT_ADDACCOUNT , CS_IDENT_HIDDEN_STATE);
|
||||||
|
|
||||||
g_CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, canBuyThisAddress);
|
GiveShieldDetour = DETOUR_CREATE_MEMBER_FIXED(GiveShield, giveShieldAddress);
|
||||||
g_BuyItemDetour = DETOUR_CREATE_STATIC_FIXED(BuyItem, buyItemAddress);
|
GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, giveNamedItemAddress);
|
||||||
g_BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, buyGunAmmoAddress);
|
AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, addAccountAddress);
|
||||||
|
|
||||||
if (g_CanBuyThisDetour == NULL || g_BuyItemDetour == NULL || g_BuyGunAmmoDetour == NULL)
|
if (GiveNamedItemDetour == NULL || AddAccountDetour == NULL)
|
||||||
{
|
{
|
||||||
MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward.");
|
MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (g_CanBuyThisDetour)
|
if (GiveShieldDetour)
|
||||||
g_CanBuyThisDetour->Destroy();
|
GiveShieldDetour->Destroy();
|
||||||
|
|
||||||
if (g_BuyItemDetour)
|
if (GiveNamedItemDetour)
|
||||||
g_BuyItemDetour->Destroy();
|
GiveNamedItemDetour->Destroy();
|
||||||
|
|
||||||
if (g_BuyGunAmmoDetour)
|
if (AddAccountDetour)
|
||||||
g_BuyGunAmmoDetour->Destroy();
|
AddAccountDetour->Destroy();
|
||||||
|
|
||||||
|
ItemAliasList.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleDetour_BuyCommands(bool enable)
|
void ToggleDetour_BuyCommands(bool enable)
|
||||||
{
|
{
|
||||||
if (g_CanBuyThisDetour)
|
if (GiveShieldDetour)
|
||||||
(enable) ? g_CanBuyThisDetour->EnableDetour() : g_CanBuyThisDetour->DisableDetour();
|
(enable) ? GiveShieldDetour->EnableDetour() : GiveShieldDetour->DisableDetour();
|
||||||
|
|
||||||
if (g_BuyItemDetour)
|
if (GiveNamedItemDetour)
|
||||||
(enable) ? g_BuyItemDetour->EnableDetour() : g_BuyItemDetour->DisableDetour();
|
(enable) ? GiveNamedItemDetour->EnableDetour() : GiveNamedItemDetour->DisableDetour();
|
||||||
|
|
||||||
if (g_BuyGunAmmoDetour)
|
if (AddAccountDetour)
|
||||||
(enable) ? g_BuyGunAmmoDetour->EnableDetour() : g_BuyGunAmmoDetour->DisableDetour();
|
(enable) ? AddAccountDetour->EnableDetour() : AddAccountDetour->DisableDetour();
|
||||||
}
|
}
|
@ -1749,7 +1749,7 @@ static cell AMX_NATIVE_CALL not_on_64(AMX* amx, cell* params)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
AMX_NATIVE_INFO cstrikeNatives[] = {
|
AMX_NATIVE_INFO CstrikeNatives[] = {
|
||||||
{"cs_set_user_money", cs_set_user_money},
|
{"cs_set_user_money", cs_set_user_money},
|
||||||
{"cs_get_user_money", cs_get_user_money},
|
{"cs_get_user_money", cs_get_user_money},
|
||||||
{"cs_get_user_deaths", cs_get_user_deaths},
|
{"cs_get_user_deaths", cs_get_user_deaths},
|
||||||
|
@ -3,14 +3,6 @@
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "CstrikePlayer.h"
|
#include "CstrikePlayer.h"
|
||||||
|
|
||||||
#if defined _MSC_VER
|
|
||||||
#if _MSC_VER >= 1400
|
|
||||||
// MSVC8 - disable deprecation warnings for "unsafe" CRT functions
|
|
||||||
#define _CRT_SECURE_NO_DEPRECATE
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h> // strcpy()
|
#include <string.h> // strcpy()
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -139,4 +139,15 @@ bool UTIL_CheckForPublic(const char *publicname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *UTIL_StringToLower(char *str)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
for (p = str; *p != '\0'; ++p)
|
||||||
|
{
|
||||||
|
*p = tolower(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
@ -37,6 +37,7 @@ bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer);
|
|||||||
void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message);
|
void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message);
|
||||||
void *UTIL_FindAddressFromEntry(const char *entry, bool isHidden = false, const char *library = "mod");
|
void *UTIL_FindAddressFromEntry(const char *entry, bool isHidden = false, const char *library = "mod");
|
||||||
bool UTIL_CheckForPublic(const char *publicname);
|
bool UTIL_CheckForPublic(const char *publicname);
|
||||||
|
char *UTIL_StringToLower(char *str);
|
||||||
|
|
||||||
#define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer)
|
#define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer)
|
||||||
#define SETCLIENTKEYVALUE (*g_engfuncs.pfnSetClientKeyValue)
|
#define SETCLIENTKEYVALUE (*g_engfuncs.pfnSetClientKeyValue)
|
||||||
|
@ -33,10 +33,11 @@
|
|||||||
#include "amxxmodule.h"
|
#include "amxxmodule.h"
|
||||||
#include "CstrikeUtils.h"
|
#include "CstrikeUtils.h"
|
||||||
|
|
||||||
extern AMX_NATIVE_INFO cstrikeNatives[];
|
extern AMX_NATIVE_INFO CstrikeNatives[];
|
||||||
|
|
||||||
extern int g_CSCliCmdFwd;
|
extern int ForwardInternalCommand;
|
||||||
extern int g_CSBuyCmdFwd;
|
extern int ForwardOnBuy;
|
||||||
|
extern int ForwardOnBuyAttempt;
|
||||||
|
|
||||||
void InitializeHacks();
|
void InitializeHacks();
|
||||||
void ShutdownHacks();
|
void ShutdownHacks();
|
||||||
@ -56,17 +57,25 @@ int AmxxCheckGame(const char *game)
|
|||||||
|
|
||||||
void OnAmxxAttach()
|
void OnAmxxAttach()
|
||||||
{
|
{
|
||||||
MF_AddNatives(cstrikeNatives);
|
MF_AddNatives(CstrikeNatives);
|
||||||
InitializeHacks();
|
InitializeHacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnPluginsLoaded()
|
void OnPluginsLoaded()
|
||||||
{
|
{
|
||||||
g_CSCliCmdFwd = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE);
|
ForwardInternalCommand = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE);
|
||||||
g_CSBuyCmdFwd = MF_RegisterForward("CS_OnBuy", ET_STOP, FP_CELL, FP_CELL, FP_DONE);
|
ForwardOnBuy = MF_RegisterForward("CS_OnBuy" , ET_STOP, FP_CELL, FP_CELL, FP_DONE);
|
||||||
|
ForwardOnBuyAttempt = MF_RegisterForward("CS_OnBuyAttempt" , ET_STOP, FP_CELL, FP_CELL, FP_DONE);
|
||||||
|
|
||||||
ToggleDetour_ClientCommands(UTIL_CheckForPublic("CS_InternalCommand"));
|
// Checking whether such public forwards are used in plugins.
|
||||||
ToggleDetour_BuyCommands(UTIL_CheckForPublic("CS_OnBuy"));
|
// Resetting variable to -1 to avoid running unnecessary code in ClientCommand.
|
||||||
|
if (!UTIL_CheckForPublic("CS_InternalCommand")) { ForwardInternalCommand = -1; }
|
||||||
|
if (!UTIL_CheckForPublic("CS_OnBuy")) { ForwardOnBuy = -1; }
|
||||||
|
if (!UTIL_CheckForPublic("CS_OnBuyAttempt")) { ForwardOnBuyAttempt = -1; }
|
||||||
|
|
||||||
|
// And enable/disable detours when necessary.
|
||||||
|
ToggleDetour_ClientCommands(ForwardInternalCommand != -1 || ForwardOnBuy != -1 || ForwardOnBuy != -1);
|
||||||
|
ToggleDetour_BuyCommands(ForwardOnBuy != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAmxxDetach()
|
void OnAmxxDetach()
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<AdditionalIncludeDirectories>..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HAVE_STDINT_H;_CRT_SECURE_NO_DEPRECATE;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||||
@ -106,7 +106,7 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
<AdditionalIncludeDirectories>..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;HAVE_STDINT_H;_CRT_SECURE_NO_DEPRECATE;CSTRIKE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<StringPooling>true</StringPooling>
|
<StringPooling>true</StringPooling>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
@ -357,7 +357,7 @@ forward CS_InternalCommand(id, const cmd[]);
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The following constants are used with CS_OnBuy forward.
|
* The following constants are used with CS_OnBuy[Attempt] forwards.
|
||||||
*/
|
*/
|
||||||
#define CSI_P228 CSW_P228
|
#define CSI_P228 CSW_P228
|
||||||
#define CSI_SCOUT CSW_SCOUT
|
#define CSI_SCOUT CSW_SCOUT
|
||||||
@ -397,9 +397,22 @@ forward CS_InternalCommand(id, const cmd[]);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a player attempts to purchase an item.
|
* Called when a player attempts to purchase an item.
|
||||||
* Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny.
|
* This is ususally called right away on buy commands issued by a player.
|
||||||
|
*
|
||||||
|
* @note Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny.
|
||||||
*
|
*
|
||||||
* @param index Player index.
|
* @param index Player index.
|
||||||
* @param item Item index, see CSI_* constants.
|
* @param item Item index, see CSI_* constants.
|
||||||
*/
|
*/
|
||||||
forward CS_OnBuy(index, item);
|
forward CS_OnBuyAttempt(index, item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a player purchases an item.
|
||||||
|
* This usually called right before a player gets the purchased item.
|
||||||
|
*
|
||||||
|
* @note Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny.
|
||||||
|
*
|
||||||
|
* @param index Player index.
|
||||||
|
* @param item Item index, see CSI_* constants.
|
||||||
|
*/
|
||||||
|
forward CS_OnBuy(index, item);
|
@ -136,6 +136,7 @@ ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name
|
|||||||
#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual
|
#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual
|
||||||
|
|
||||||
#define DETOUR_CREATE_MEMBER(name, gamedata, target) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata, target);
|
#define DETOUR_CREATE_MEMBER(name, gamedata, target) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata, target);
|
||||||
|
#define DETOUR_CREATE_MEMBER_FIXED(name, address) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), address);
|
||||||
#define DETOUR_CREATE_STATIC(name, gamedata, target) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata, target);
|
#define DETOUR_CREATE_STATIC(name, gamedata, target) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata, target);
|
||||||
#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address);
|
#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user