Cstrike: Make CS_OnBuy forward more reliable - part 2

Purpose is to have the forward be called only on actual buying.
This has been requested on the forum.
This commit is contained in:
Arkshine 2014-07-03 19:40:30 +02:00
parent 6e50a0effd
commit 0cf39307e0
5 changed files with 182 additions and 18 deletions

View File

@ -3,6 +3,10 @@ import os.path
binary = AMXX.MetaModule(builder, 'cstrike')
binary.compiler.defines += [
'HAVE_STDINT_H',
]
binary.sources = [
'sdk/amxxmodule.cpp',
'amxx_api.cpp',

View File

@ -64,6 +64,7 @@
#define OFFSET_INTERNALMODEL 126 + EXTRAOFFSET
#define OFFSET_NVGOGGLES 129 + EXTRAOFFSET
#define OFFSET_DEFUSE_PLANT 193 + EXTRAOFFSET
#define OFFSET_MENU 205 + EXTRAOFFSET
#define OFFSET_VIP 209 + EXTRAOFFSET
#define OFFSET_TK 216 + EXTRAOFFSET // 040926
#define OFFSET_HOSTAGEKILLS 217 + EXTRAOFFSET
@ -353,4 +354,24 @@ enum
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

View File

@ -33,6 +33,9 @@
#include "CstrikeDatas.h"
#include "CstrikeUtils.h"
#include "CDetour/detours.h"
#include <sm_stringhashmap.h>
using namespace SourceMod; // hashmap
void CtrlDetours_ClientCommand(bool set);
void CtrlDetours_BuyCommands(bool set);
@ -50,6 +53,9 @@ CDetour *g_BuyGunAmmoDetour = NULL;
CDetour *g_GiveNamedItemDetour = NULL;
CDetour *g_AddAccountDetour = NULL;
int g_CurrentItemId = 0;
StringHashMap<int> g_ItemAliasList;
void InitializeHacks()
{
#if defined AMD64
@ -66,9 +72,92 @@ void ShutdownHacks()
CtrlDetours_BuyCommands(false);
}
#undef CMD_ARGV
const char *CMD_ARGV(int i)
{
if (*g_UseBotArgs)
{
if (i < 4)
{
return g_BotArgs[i];
}
return NULL;
}
return g_engfuncs.pfnCmd_Argv(i);
}
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
{
const char *command = CMD_ARGV(0);
// A new command is triggered, reset current item.
g_CurrentItemId = 0;
// Purpose is to retrieve an item id based on alias name or selected item from menu,
// to be used in OnBuy* forwards.
if (command && *command)
{
int itemId = 0;
// Handling 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)
{
g_CurrentItemId = itemId;
}
}
}
}
// Handling via alias
else
{
if (g_ItemAliasList.retrieve(command, &itemId))
{
g_CurrentItemId = itemId;
}
}
}
if (*g_UseBotArgs)
{
int client = ENTINDEX(pEdict);
@ -89,9 +178,9 @@ DETOUR_DECL_STATIC2(CanBuyThis, bool, void*, pvPlayer, int, weaponId) // bool Ca
{
int player = PrivateToIndex(pvPlayer);
if (MF_IsPlayerAlive(player) && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(player), static_cast<cell>(weaponId)) > 0)
if (MF_IsPlayerAlive(player))
{
return false;
g_CurrentItemId = weaponId;
}
}
@ -106,9 +195,9 @@ DETOUR_DECL_STATIC2(BuyItem, void, void*, pvPlayer, int, iSlot) // void BuyItem(
{
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)
if (iSlot >= 1 && iSlot <= 8)
{
return;
g_CurrentItemId = itemSlotToWeaponId[iSlot];
}
}
@ -128,10 +217,7 @@ DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bB
int weaponId = *((int *)pWeapon->pvPrivateData + OFFSET_WEAPONTYPE);
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;
}
g_CurrentItemId = ammoId;
}
}
@ -140,12 +226,25 @@ DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bB
DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlayer::GiveNamedItem(const char *pszName)
{
if (g_CurrentItemId && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast<cell>(PrivateToIndex(this)), static_cast<cell>(g_CurrentItemId)) > 0)
{
return;
}
g_CurrentItemId = 0;
DETOUR_MEMBER_CALL(GiveNamedItem)(pszName);
}
DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
{
if (g_CurrentItemId)
{
g_CurrentItemId = 0;
return;
}
DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
}
@ -212,6 +311,52 @@ void CtrlDetours_BuyCommands(bool set)
{
MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward.");
}
// Build the item alias list.
// Used in ClientCommand to check and get fastly item id from aiias name.
typedef struct
{
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)
{
g_ItemAliasList.insert(aliasToId[i].alias, aliasToId[i].id);
}
}
else
{
@ -229,6 +374,8 @@ void CtrlDetours_BuyCommands(bool set)
if (g_AddAccountDetour)
g_AddAccountDetour->Destroy();
g_ItemAliasList.clear();
}
}

View File

@ -3,14 +3,6 @@
//////////////////////////////////////////////////////////////////////
#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()
//////////////////////////////////////////////////////////////////////

View File

@ -63,7 +63,7 @@
<ClCompile>
<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>
<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>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
@ -106,7 +106,7 @@
<Optimization>MaxSpeed</Optimization>
<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>
<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>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>