Cstrike: Refactor - Simplify forwards logic, fix and improve few things
- The logic around CS_OnBuy forward has been simplified. Since there is no way to have a consistent way to hook/block for all items, the new logic is to have as less as possible code, especially in blocking mode where we want to avoid to do extra stuffs (e.g blocking sound, event, etc). * All guns + shield -> CanBuyThis() * Nvgs and Fefuser only -> CanPlayerBuy() * The others items -> GiveNamedItem() + AddAccount() * Ammos -> -> BuyGunAmmo() + GiveNamedItem() + AddAccount() - Fixed missing buyzone check when alias from console are used (CS_OnBUy* were incorrectly fired). - Fixed an infinite loop when buying of ammos are blocked. Sorted by hooking BuyGunAmmo(). - Fixed blocking mode for some items. Some game behaviors were not blocked (e.g. weapon drop). - Fixed forwards being triggered even though errors were found. Detours are now a destroyed and associated variables resetted when necessary. Toggling forwards state is now based on detours state. - Moved things in its own functions (game functions to execute, class members retrieval) - Renamed CommandAliases -> ItemInfos (more generic)
This commit is contained in:
parent
d08e1357dd
commit
a445e806ea
|
@ -15,6 +15,22 @@
|
|||
{
|
||||
"Signatures"
|
||||
{
|
||||
"CanPlayerBuy" // bool CBasePlayer::CanPlayerBuy(bool display)
|
||||
{
|
||||
"library" "server"
|
||||
"windows" "\x51\x53\x55\x56\x57\x8B\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x8B\x2A\xFF"
|
||||
"linux" "@_ZN11CBasePlayer12CanPlayerBuyEb"
|
||||
"mac" "@_ZN11CBasePlayer12CanPlayerBuyEb"
|
||||
}
|
||||
|
||||
"CanBuyThis" // bool CanBuyThis(CBasePlayer *pPlayer, int weaponId)
|
||||
{
|
||||
"library" "server"
|
||||
"windows" "\x53\x8B\x2A\x2A\x2A\x2A\x2A\x56\x8B\x2A\x2A\x2A\x57\x8B"
|
||||
"linux" "@_Z10CanBuyThisP11CBasePlayeri"
|
||||
"mac" "@_Z10CanBuyThisP11CBasePlayeri"
|
||||
}
|
||||
|
||||
"AddAccount" // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
|
||||
{
|
||||
"library" "server"
|
||||
|
@ -70,6 +86,22 @@
|
|||
"linux" "@_Z13GetWeaponInfoi"
|
||||
"mac" "@_Z13GetWeaponInfoi"
|
||||
}
|
||||
|
||||
"GetAmmoIndex" // int CBasePlayer::GetAmmoIndex(const char *psz)
|
||||
{
|
||||
"library" "server"
|
||||
"windows" "\x56\x57\x8B\x2A\x2A\x2A\x85\x2A\x74\x2A\xBE"
|
||||
"linux" "@_ZN11CBasePlayer12GetAmmoIndexEPKc"
|
||||
"mac" "@_ZN11CBasePlayer12GetAmmoIndexEPKc"
|
||||
}
|
||||
|
||||
"BuyGunAmmo" // bool BuyGunAmmo(CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney)
|
||||
{
|
||||
"library" "server"
|
||||
"windows" "\x56\x57\x8B\x2A\x2A\x2A\x6A\x2A\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x84\x2A\x0F"
|
||||
"linux" "@_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb"
|
||||
"mac" "@_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,9 +142,9 @@
|
|||
|
||||
"#default"
|
||||
{
|
||||
"CommandsAliases"
|
||||
"ItemInfos"
|
||||
{
|
||||
"Common"
|
||||
"CommonAlias"
|
||||
{
|
||||
"p228"
|
||||
{
|
||||
|
@ -241,7 +273,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
"Weapon"
|
||||
"WeaponAlias"
|
||||
{
|
||||
"grenade"
|
||||
{
|
||||
|
@ -280,7 +312,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
"Buy"
|
||||
"BuyAlias"
|
||||
{
|
||||
"228compact"
|
||||
{
|
||||
|
@ -374,42 +406,48 @@
|
|||
}
|
||||
}
|
||||
|
||||
"BuyEquip"
|
||||
"BuyEquipAlias"
|
||||
{
|
||||
"hegren"
|
||||
{
|
||||
"itemid" "4" // CSW/I_HEGRENADE
|
||||
"classid" "3" // CS_WEAPONCLASS_GRENADE
|
||||
"price" "300"
|
||||
}
|
||||
"sgren"
|
||||
{
|
||||
"itemid" "9" // CSW/I_SMOKEGRENADE
|
||||
"classid" "3" // CS_WEAPONCLASS_GRENADE
|
||||
"price" "300"
|
||||
}
|
||||
"flash"
|
||||
{
|
||||
"itemid" "25" // CSW/I_FLASHBANG
|
||||
"classid" "3" // CS_WEAPONCLASS_GRENADE
|
||||
"price" "200"
|
||||
}
|
||||
"vest"
|
||||
{
|
||||
"itemid" "31" // CSW/I_VEST
|
||||
"classname" "item_kevlar"
|
||||
"price" "650"
|
||||
}
|
||||
"vesthelm"
|
||||
{
|
||||
"itemid" "32" // CSW/I_VESTHELM
|
||||
"classname" "item_assaultsuit"
|
||||
"price" "1000"
|
||||
}
|
||||
"defuser"
|
||||
{
|
||||
"itemid" "33" // CSI_DEFUSER
|
||||
"classname" "item_thighpack"
|
||||
"price" "200"
|
||||
}
|
||||
"nvgs"
|
||||
{
|
||||
"itemid" "34" // CSI_NVGS
|
||||
|
||||
"price" "1250"
|
||||
}
|
||||
"shield"
|
||||
{
|
||||
|
@ -419,7 +457,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
"BuyAmmo"
|
||||
"BuyAmmoAlias"
|
||||
{
|
||||
"primammo"
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ binary.sources = [
|
|||
'CstrikeHacks.cpp',
|
||||
'CstrikeUtils.cpp',
|
||||
'CstrikeUserMessages.cpp',
|
||||
'CstrikeitemsInfos.cpp',
|
||||
'CstrikeItemsInfos.cpp',
|
||||
'../../../public/memtools/MemoryUtils.cpp',
|
||||
'../../../public/memtools/CDetour/detours.cpp',
|
||||
'../../../public/memtools/CDetour/asm/asm.c',
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#define CSI_PRIAMMO 36 // Custom
|
||||
#define CSI_SECAMMO 37 // Custom
|
||||
#define CSI_MAX_COUNT 38
|
||||
#define CSI_LAST_WEAPON CSW_LAST_WEAPON
|
||||
|
||||
#define CSI_ALL_WEAPONS CSW_ALL_WEAPONS
|
||||
#define CSI_ALL_PISTOLS CSW_ALL_PISTOLS
|
||||
|
@ -107,12 +108,12 @@
|
|||
|
||||
#define CSW_ALL_WEAPONS (~(1 << CSW_VEST))
|
||||
#define CSW_ALL_PISTOLS (1 << CSW_P228 | 1 << CSW_ELITE | 1 << CSW_FIVESEVEN | 1 << CSW_USP | 1 << CSW_GLOCK18 | 1 << CSW_DEAGLE)
|
||||
#define CSW_ALL_SHOTGUNS (1 << CSW_M3 | 1 << CSW_XM1014))
|
||||
#define CSW_ALL_SMGS (1 << CSW_MAC10 | 1 << CSW_UMP45 | 1 << CSW_MP5NAVY | 1 << CSW_TMP | 1 << CSW_P90))
|
||||
#define CSW_ALL_RIFLES (1 << CSW_AUG | 1 << CSW_GALIL | 1 << CSW_FAMAS | 1 << CSW_M4A1 | 1 << CSW_AK47 | 1 << CSW_SG552))
|
||||
#define CSW_ALL_SNIPERRIFLES (1 << CSW_SCOUT | 1 << CSW_AWP | 1 << CSW_G3SG1 | 1 << CSW_SG550))
|
||||
#define CSW_ALL_MACHINEGUNS (1 << CSW_M249))
|
||||
#define CSW_ALL_GRENADES (1 << CSW_HEGRENADE | 1 << CSW_SMOKEGRENADE | 1 << CSW_FLASHBANG))
|
||||
#define CSW_ALL_SHOTGUNS (1 << CSW_M3 | 1 << CSW_XM1014)
|
||||
#define CSW_ALL_SMGS (1 << CSW_MAC10 | 1 << CSW_UMP45 | 1 << CSW_MP5NAVY | 1 << CSW_TMP | 1 << CSW_P90)
|
||||
#define CSW_ALL_RIFLES (1 << CSW_AUG | 1 << CSW_GALIL | 1 << CSW_FAMAS | 1 << CSW_M4A1 | 1 << CSW_AK47 | 1 << CSW_SG552)
|
||||
#define CSW_ALL_SNIPERRIFLES (1 << CSW_SCOUT | 1 << CSW_AWP | 1 << CSW_G3SG1 | 1 << CSW_SG550)
|
||||
#define CSW_ALL_MACHINEGUNS (1 << CSW_M249)
|
||||
#define CSW_ALL_GRENADES (1 << CSW_HEGRENADE | 1 << CSW_SMOKEGRENADE | 1 << CSW_FLASHBANG)
|
||||
#define CSW_ALL_ARMORS (1 << CSW_VEST | 1 << CSW_VESTHELM)
|
||||
#define CSW_ALL_GUNS (CSW_ALL_PISTOLS | CSW_ALL_SHOTGUNS | CSW_ALL_SMGS | CSW_ALL_RIFLES | CSW_ALL_SNIPERRIFLES | CSW_ALL_MACHINEGUNS)
|
||||
|
||||
|
@ -349,6 +350,51 @@ enum CsWeaponInfo
|
|||
CS_WEAPONINFO_AMMO_TYPE = 5,
|
||||
};
|
||||
|
||||
extern char WeaponNameList[MAX_WEAPONS][64];
|
||||
/**
|
||||
* Weapon default cost.
|
||||
*/
|
||||
enum WeaponCostType
|
||||
{
|
||||
AK47_PRICE = 2500,
|
||||
AWP_PRICE = 4750,
|
||||
DEAGLE_PRICE = 650,
|
||||
G3SG1_PRICE = 5000,
|
||||
SG550_PRICE = 4200,
|
||||
GLOCK18_PRICE = 400,
|
||||
M249_PRICE = 5750,
|
||||
M3_PRICE = 1700,
|
||||
M4A1_PRICE = 3100,
|
||||
AUG_PRICE = 3500,
|
||||
MP5NAVY_PRICE = 1500,
|
||||
P228_PRICE = 600,
|
||||
P90_PRICE = 2350,
|
||||
UMP45_PRICE = 1700,
|
||||
MAC10_PRICE = 1400,
|
||||
SCOUT_PRICE = 2750,
|
||||
SG552_PRICE = 3500,
|
||||
TMP_PRICE = 1250,
|
||||
USP_PRICE = 500,
|
||||
ELITE_PRICE = 800,
|
||||
FIVESEVEN_PRICE = 750,
|
||||
XM1014_PRICE = 3000,
|
||||
GALIL_PRICE = 2000,
|
||||
FAMAS_PRICE = 2250,
|
||||
SHIELDGUN_PRICE = 2200
|
||||
};
|
||||
|
||||
/**
|
||||
* Equipment default cost.
|
||||
*/
|
||||
enum ItemCostType
|
||||
{
|
||||
ASSAULTSUIT_PRICE = 1000,
|
||||
FLASHBANG_PRICE = 200,
|
||||
HEGRENADE_PRICE = 300,
|
||||
SMOKEGRENADE_PRICE = 300,
|
||||
KEVLAR_PRICE = 650,
|
||||
HELMET_PRICE = 350,
|
||||
NVG_PRICE = 1250,
|
||||
DEFUSEKIT_PRICE = 200
|
||||
};
|
||||
|
||||
#endif // CSTRIKE_DATA_H
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
#include "CstrikeDatas.h"
|
||||
#include "CstrikeUtils.h"
|
||||
#include "CstrikeHacks.h"
|
||||
#include <sm_stringhashmap.h>
|
||||
|
||||
void CtrlDetours_ClientCommand(bool set);
|
||||
void CtrlDetours_BuyCommands(bool set);
|
||||
void CtrlDetours_Natives(bool set);
|
||||
#include "CstrikeItemsInfos.h"
|
||||
|
||||
int ForwardInternalCommand = -1;
|
||||
int ForwardOnBuy = -1;
|
||||
int ForwardOnBuyAttempt = -1;
|
||||
|
||||
bool HasInternalCommandForward;
|
||||
bool HasOnBuyAttemptForward;
|
||||
bool HasOnBuyForward;
|
||||
|
||||
int *UseBotArgs;
|
||||
const char **BotArgs;
|
||||
|
||||
|
@ -31,7 +31,10 @@ CDetour *ClientCommandDetour;
|
|||
CDetour *GiveShieldDetour;
|
||||
CDetour *GiveNamedItemDetour;
|
||||
CDetour *AddAccountDetour;
|
||||
CDetour *CanPlayerBuyDetour;
|
||||
CDetour *CanBuyThisDetour;
|
||||
CDetour *GiveDefaultItemsDetour;
|
||||
CDetour *BuyGunAmmoDetour;
|
||||
|
||||
CreateNamedEntityFunc CS_CreateNamedEntity;
|
||||
UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString;
|
||||
|
@ -39,21 +42,36 @@ GetWeaponInfoFunc GetWeaponInfo;
|
|||
|
||||
int CurrentItemId;
|
||||
bool TriggeredFromCommand;
|
||||
bool BlockMoneyUpdate;
|
||||
bool BlockAmmosUpdate;
|
||||
|
||||
// m_iTeam and m_iMenu from CBasePlayer.
|
||||
// CBasePlayer members.
|
||||
TypeDescription TeamDesc;
|
||||
TypeDescription MenuDesc;
|
||||
TypeDescription NvgsDesc;
|
||||
TypeDescription DefuserDesc;
|
||||
TypeDescription SignalsDesc;
|
||||
TypeDescription MoneyDesc;
|
||||
|
||||
// GameRules members.
|
||||
TypeDescription BombTargetDesc;
|
||||
|
||||
// Engine global variables.
|
||||
server_static_t *ServerStatic;
|
||||
server_t *Server;
|
||||
|
||||
// Mod global variable
|
||||
void **GameRules;
|
||||
|
||||
|
||||
void InitializeHacks()
|
||||
{
|
||||
CtrlDetours_ClientCommand(true);
|
||||
CtrlDetours_BuyCommands(true);
|
||||
CtrlDetours_Natives(true);
|
||||
|
||||
InitFuncsAddresses();
|
||||
InitClassMembers();
|
||||
InitGlobalVars();
|
||||
}
|
||||
|
||||
|
@ -83,13 +101,13 @@ const char *CMD_ARGV(int i)
|
|||
|
||||
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
|
||||
{
|
||||
const char *command = CMD_ARGV(0);
|
||||
auto command = CMD_ARGV(0);
|
||||
|
||||
CurrentItemId = CSI_NONE;
|
||||
|
||||
// Purpose is to retrieve an item id based on alias name or selected item from menu,
|
||||
// to be used in CS_OnBuy* forwards.
|
||||
if ((ForwardOnBuyAttempt != -1 || ForwardOnBuy != -1) && command && *command)
|
||||
if ((HasOnBuyAttemptForward || HasOnBuyForward) && command && *command)
|
||||
{
|
||||
int itemId = CSI_NONE;
|
||||
|
||||
|
@ -140,6 +158,8 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
|
|||
}
|
||||
}
|
||||
else // Handling buy via alias
|
||||
{
|
||||
if (get_pdata<CUnifiedSignals>(pEdict, SignalsDesc.fieldOffset).GetState() & SIGNAL_BUY) // Are we inside the buy zone?
|
||||
{
|
||||
AliasInfo info;
|
||||
|
||||
|
@ -149,70 +169,30 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
int client = ENTINDEX(pEdict);
|
||||
|
||||
if (ForwardInternalCommand != -1 && *UseBotArgs)
|
||||
{
|
||||
const char *args = *BotArgs;
|
||||
|
||||
if (MF_ExecuteForward(ForwardInternalCommand, static_cast<cell>(client), args) > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ForwardOnBuyAttempt != -1 &&
|
||||
CurrentItemId &&
|
||||
MF_IsPlayerAlive(client) &&
|
||||
MF_ExecuteForward(ForwardOnBuyAttempt, static_cast<cell>(client), static_cast<cell>(CurrentItemId)) > 0)
|
||||
auto client = TypeConversion.edict_to_id(pEdict);
|
||||
|
||||
if (HasInternalCommandForward && *UseBotArgs && MF_ExecuteForward(ForwardInternalCommand, client, *BotArgs) > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// CS_OnBuy()
|
||||
// -
|
||||
// This forward should be called right before game gives the item.
|
||||
// All items except shield, defuser and nvgs, games executes in the following order:
|
||||
// GiveNamedItem -> AddAccount
|
||||
// Forward is fired on GiveNamedItem.
|
||||
// Shield only:
|
||||
// GiveShield -> AddAccount -> EmitSound
|
||||
// Forward is fired on GiveShield.
|
||||
// Defusal kit only:
|
||||
// m_bHasDefuser(true) -> StatusIcon -> pev_body(1) -> AddAccount -> EmitSound -> ItemStatus
|
||||
// Forward is fired on StatusIcon.
|
||||
// Nightvision only:
|
||||
// EmitSound -> m_bHasNightVision(true) -> AddAccount -> ItemStatus
|
||||
// Forward is fired on EmitSound.
|
||||
if (HasOnBuyAttemptForward && CurrentItemId && MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuyAttempt, client, CurrentItemId) > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TriggeredFromCommand = CurrentItemId != CSI_NONE;
|
||||
|
||||
if (TriggeredFromCommand)
|
||||
{
|
||||
if (CurrentItemId == CSI_NVGS)
|
||||
{
|
||||
g_pengfuncsTable->pfnEmitSound = OnEmitSound;
|
||||
}
|
||||
else if (CurrentItemId == CSI_DEFUSER)
|
||||
{
|
||||
GET_OFFSET_NO_ERROR("CBasePlayer", m_bHasDefuser);
|
||||
|
||||
if (!get_pdata<bool>(pEdict, m_bHasDefuser))
|
||||
{
|
||||
EnableMessageHooks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DETOUR_STATIC_CALL(C_ClientCommand)(pEdict);
|
||||
|
||||
TriggeredFromCommand = false;
|
||||
TriggeredFromCommand = BlockMoneyUpdate = BlockAmmosUpdate = false;
|
||||
}
|
||||
|
||||
edict_s* OnCreateNamedEntity(int classname)
|
||||
{
|
||||
if (NoKifesMode)
|
||||
if (NoKnivesMode)
|
||||
{
|
||||
if (!strcmp(STRING(classname), "weapon_knife"))
|
||||
{
|
||||
|
@ -224,75 +204,12 @@ edict_s* OnCreateNamedEntity(int classname)
|
|||
g_pengfuncsTable->pfnCreateNamedEntity = nullptr;
|
||||
}
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, 0);
|
||||
}
|
||||
|
||||
void OnEmitSound(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch)
|
||||
{
|
||||
if (TriggeredFromCommand)
|
||||
{
|
||||
switch (CurrentItemId)
|
||||
{
|
||||
case CSI_NVGS:
|
||||
{
|
||||
auto client = ENTINDEX(entity);
|
||||
|
||||
if (!MF_IsPlayerAlive(client) || MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_NVGS) <= 0)
|
||||
{
|
||||
g_pengfuncsTable->pfnEmitSound = nullptr;
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
}
|
||||
case CSI_DEFUSER:
|
||||
case CSI_SHIELD:
|
||||
{
|
||||
g_pengfuncsTable->pfnEmitSound = nullptr;
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
bool OnMessageItemStatus(edict_t *pPlayer)
|
||||
{
|
||||
if (TriggeredFromCommand && (CurrentItemId == CSI_DEFUSER || CurrentItemId == CSI_NVGS))
|
||||
{
|
||||
if (!g_pengfuncsTable->pfnEmitSound)
|
||||
{
|
||||
return true; // Block message
|
||||
}
|
||||
|
||||
DisableMessageHooks();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OnMessageStatusIcon(edict_t *pPlayer)
|
||||
{
|
||||
if (TriggeredFromCommand && CurrentItemId == CSI_DEFUSER)
|
||||
{
|
||||
auto client = ENTINDEX(pPlayer);
|
||||
|
||||
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_DEFUSER) > 0)
|
||||
{
|
||||
GET_OFFSET_NO_ERROR_RET("CBasePlayer", m_bHasDefuser);
|
||||
set_pdata<bool>(pPlayer, m_bHasDefuser, false);
|
||||
|
||||
return true; // Block message
|
||||
}
|
||||
|
||||
DisableMessageHooks();
|
||||
}
|
||||
|
||||
return false;
|
||||
RETURN_META_VALUE(MRES_IGNORED, nullptr);
|
||||
}
|
||||
|
||||
DETOUR_DECL_MEMBER0(GiveDefaultItems, void) // void CBasePlayer::GiveDefaultItems(void)
|
||||
{
|
||||
if (NoKifesMode)
|
||||
if (NoKnivesMode)
|
||||
{
|
||||
g_pengfuncsTable->pfnCreateNamedEntity = OnCreateNamedEntity;
|
||||
}
|
||||
|
@ -302,133 +219,199 @@ DETOUR_DECL_MEMBER0(GiveDefaultItems, void) // void CBasePlayer::GiveDefaultIte
|
|||
g_pengfuncsTable->pfnCreateNamedEntity = nullptr;
|
||||
}
|
||||
|
||||
DETOUR_DECL_MEMBER1(CanPlayerBuy, bool, bool, display) // bool CBasePlayer::CanPlayerBuy(bool display)
|
||||
{
|
||||
auto canBuy = DETOUR_MEMBER_CALL(CanPlayerBuy)(display);
|
||||
|
||||
if (!canBuy || !TriggeredFromCommand || !(CurrentItemId == CSI_NVGS || CurrentItemId == CSI_DEFUSER))
|
||||
{
|
||||
return canBuy;
|
||||
}
|
||||
|
||||
auto pPlayer = TypeConversion.cbase_to_edict(this);
|
||||
auto playerId = TypeConversion.edict_to_id(pPlayer);
|
||||
|
||||
if (!MF_IsPlayerAlive(playerId))
|
||||
{
|
||||
return canBuy;
|
||||
}
|
||||
|
||||
auto allowedToBuy = false;
|
||||
auto itemPrice = ItemsManager.GetItemPrice(CurrentItemId);
|
||||
|
||||
switch (CurrentItemId)
|
||||
{
|
||||
case CSI_NVGS:
|
||||
{
|
||||
allowedToBuy = !get_pdata<bool>(pPlayer, NvgsDesc.fieldOffset) &&
|
||||
get_pdata<int>(pPlayer, MoneyDesc.fieldOffset) >= itemPrice;
|
||||
break;
|
||||
}
|
||||
case CSI_DEFUSER:
|
||||
{
|
||||
allowedToBuy = !get_pdata<bool>(pPlayer, DefuserDesc.fieldOffset) &&
|
||||
get_pdata<int>(pPlayer, TeamDesc.fieldOffset) == TEAM_CT &&
|
||||
get_pdata<bool>(*GameRules, BombTargetDesc.fieldOffset) &&
|
||||
get_pdata<int>(pPlayer, MoneyDesc.fieldOffset) >= itemPrice;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allowedToBuy && MF_ExecuteForward(ForwardOnBuy, playerId, CurrentItemId) > 0)
|
||||
{
|
||||
canBuy = false;
|
||||
}
|
||||
|
||||
return canBuy;
|
||||
}
|
||||
|
||||
DETOUR_DECL_STATIC2(CanBuyThis, bool, void*, pvPlayer, int, weaponId) // bool CanBuyThis(CBasePlayer *pPlayer, int weaponId)
|
||||
{
|
||||
auto canBuy = DETOUR_STATIC_CALL(CanBuyThis)(pvPlayer, weaponId);
|
||||
|
||||
if (!canBuy || !TriggeredFromCommand || !((1 << CurrentItemId & CSI_ALL_GUNS) || CurrentItemId == CSI_SHIELD))
|
||||
{
|
||||
return canBuy;
|
||||
}
|
||||
|
||||
auto playerId = TypeConversion.cbase_to_id(pvPlayer);
|
||||
|
||||
if (MF_IsPlayerAlive(playerId) && get_pdata<int>(pvPlayer, MoneyDesc.fieldOffset) >= ItemsManager.GetItemPrice(CurrentItemId))
|
||||
{
|
||||
if (MF_ExecuteForward(ForwardOnBuy, playerId, CurrentItemId) > 0)
|
||||
{
|
||||
canBuy = false;
|
||||
}
|
||||
}
|
||||
|
||||
return canBuy;
|
||||
}
|
||||
|
||||
DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, player, int, nSlot, bool, bBlinkMoney) // bool BuyGunAmmo(CBasePlayer *player, int nSlot, bool bBlinkMoney)
|
||||
{
|
||||
auto result = DETOUR_STATIC_CALL(BuyGunAmmo)(player, nSlot, bBlinkMoney);
|
||||
|
||||
if (result && BlockAmmosUpdate)
|
||||
{
|
||||
BlockAmmosUpdate = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlayer::GiveNamedItem(const char *pszName)
|
||||
{
|
||||
if (TriggeredFromCommand)
|
||||
{
|
||||
int client = TypeConversion.cbase_to_id(this);
|
||||
|
||||
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), static_cast<cell>(CurrentItemId)) > 0)
|
||||
switch (CurrentItemId)
|
||||
{
|
||||
// Reset this to not call AddAccount() called right after.
|
||||
CurrentItemId = CSI_NONE;
|
||||
case CSI_VEST:
|
||||
case CSI_VESTHELM:
|
||||
case CSI_FLASHBANG:
|
||||
case CSI_HEGRENADE:
|
||||
case CSI_SMOKEGRENADE:
|
||||
case CSI_PRIAMMO:
|
||||
case CSI_SECAMMO:
|
||||
{
|
||||
auto playerId = TypeConversion.cbase_to_id(this);
|
||||
|
||||
if (MF_IsPlayerAlive(playerId) && MF_ExecuteForward(ForwardOnBuy, playerId, CurrentItemId) > 0)
|
||||
{
|
||||
BlockAmmosUpdate = CurrentItemId == CSI_PRIAMMO || CurrentItemId == CSI_SECAMMO;
|
||||
BlockMoneyUpdate = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DETOUR_MEMBER_CALL(GiveNamedItem)(pszName);
|
||||
}
|
||||
|
||||
DETOUR_DECL_MEMBER1(GiveShield, void, bool, bRetire) // void CBasePlayer::GiveShield(bool bRetire)
|
||||
{
|
||||
if (TriggeredFromCommand && CurrentItemId == CSI_SHIELD)
|
||||
{
|
||||
int client = TypeConversion.cbase_to_id(this);
|
||||
|
||||
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_SHIELD) > 0)
|
||||
{
|
||||
// If shield blocked, we need to hook EmitSound to block pickup sound played right after.
|
||||
g_pengfuncsTable->pfnEmitSound = OnEmitSound;
|
||||
|
||||
// Reset this to not call AddAccount() called right after.
|
||||
CurrentItemId = CSI_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DETOUR_MEMBER_CALL(GiveShield)(bRetire);
|
||||
}
|
||||
|
||||
DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
|
||||
{
|
||||
if (TriggeredFromCommand)
|
||||
{
|
||||
switch (CurrentItemId)
|
||||
{
|
||||
case CSI_DEFUSER:
|
||||
{
|
||||
G_HL_TypeConversion.cbase_to_entvar(this)->body = 0;
|
||||
g_pengfuncsTable->pfnEmitSound = OnEmitSound; // To block pickup sound.
|
||||
EnableMessageHooks(); // To block ItemStatus
|
||||
break;
|
||||
}
|
||||
case CSI_NVGS:
|
||||
{
|
||||
GET_OFFSET_NO_ERROR("CBasePlayer", m_bHasNightVision);
|
||||
set_pdata<bool>(G_HL_TypeConversion.cbase_to_edict(this), m_bHasNightVision, false);
|
||||
EnableMessageHooks(); // To block ItemStatus
|
||||
break;
|
||||
}
|
||||
case CSI_NONE:
|
||||
if (BlockMoneyUpdate)
|
||||
{
|
||||
BlockMoneyUpdate = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
|
||||
}
|
||||
|
||||
|
||||
void ToggleDetour(CDetour *detour, bool enable)
|
||||
{
|
||||
if (detour)
|
||||
{
|
||||
(enable) ? detour->EnableDetour() : detour->DisableDetour();
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyDetour(CDetour *&detour)
|
||||
{
|
||||
if (detour)
|
||||
{
|
||||
detour->Destroy();
|
||||
detour = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CtrlDetours_ClientCommand(bool set)
|
||||
{
|
||||
if (set)
|
||||
{
|
||||
void *base = reinterpret_cast<void *>(MDLL_ClientCommand);
|
||||
auto base = reinterpret_cast<void *>(MDLL_ClientCommand);
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(KE_WINDOWS)
|
||||
|
||||
TypeDescription type;
|
||||
|
||||
if (MainConfig->GetOffset("UseBotArgs", &type))
|
||||
{
|
||||
UseBotArgs = get_pdata<int*>(base, type.fieldOffset);
|
||||
UseBotArgs = get_pdata<decltype(UseBotArgs)>(base, type.fieldOffset);
|
||||
}
|
||||
|
||||
if (MainConfig->GetOffset("BotArgs", &type))
|
||||
{
|
||||
BotArgs = get_pdata<const char**>(base, type.fieldOffset);
|
||||
BotArgs = get_pdata<decltype(BotArgs)>(base, type.fieldOffset);
|
||||
}
|
||||
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
|
||||
#else
|
||||
void *address = nullptr;
|
||||
|
||||
if (MainConfig->GetMemSig("UseBotArgs", &address))
|
||||
{
|
||||
UseBotArgs = reinterpret_cast<int *>(address);
|
||||
UseBotArgs = reinterpret_cast<decltype(UseBotArgs)>(address);
|
||||
}
|
||||
|
||||
if (MainConfig->GetMemSig("BotArgs", &address))
|
||||
{
|
||||
BotArgs = reinterpret_cast<const char **>(address);
|
||||
BotArgs = reinterpret_cast<decltype(BotArgs)>(address);
|
||||
}
|
||||
#endif
|
||||
ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, base);
|
||||
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_iTeam", &TeamDesc);
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_iMenu", &MenuDesc);
|
||||
|
||||
if (!ClientCommandDetour || !UseBotArgs || !BotArgs || !TeamDesc.fieldOffset || !MenuDesc.fieldOffset)
|
||||
if (!ClientCommandDetour)
|
||||
{
|
||||
MF_Log("ClientCommand is not available - forward client_command has been disabled");
|
||||
MF_Log("ClientCommand is not available - forwards CS_InternalCommand and CS_OnBuy[Attempt] have been disabled");
|
||||
CtrlDetours_ClientCommand(false);
|
||||
}
|
||||
else if (!UseBotArgs || !BotArgs)
|
||||
{
|
||||
MF_Log("UseBotArgs or BotArgs is not available - forward CS_InternalCommand has been disabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ClientCommandDetour)
|
||||
{
|
||||
ClientCommandDetour->Destroy();
|
||||
}
|
||||
DestroyDetour(ClientCommandDetour);
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleDetour_ClientCommands(bool enable)
|
||||
{
|
||||
if (ClientCommandDetour)
|
||||
{
|
||||
(enable) ? ClientCommandDetour->EnableDetour() : ClientCommandDetour->DisableDetour();
|
||||
}
|
||||
ToggleDetour(ClientCommandDetour, enable);
|
||||
}
|
||||
|
||||
|
||||
|
@ -438,9 +421,9 @@ void CtrlDetours_BuyCommands(bool set)
|
|||
{
|
||||
void *address = nullptr;
|
||||
|
||||
if (MainConfig->GetMemSig("GiveShield", &address))
|
||||
if (MainConfig->GetMemSig("BuyGunAmmo", &address))
|
||||
{
|
||||
GiveShieldDetour = DETOUR_CREATE_MEMBER_FIXED(GiveShield, address);
|
||||
BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, address);
|
||||
}
|
||||
|
||||
if (MainConfig->GetMemSig("GiveNamedItem", &address))
|
||||
|
@ -453,11 +436,21 @@ void CtrlDetours_BuyCommands(bool set)
|
|||
AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, address);
|
||||
}
|
||||
|
||||
if (!GiveShieldDetour || !GiveNamedItemDetour || !AddAccountDetour)
|
||||
if (MainConfig->GetMemSig("CanPlayerBuy", &address))
|
||||
{
|
||||
if (!GiveShieldDetour)
|
||||
CanPlayerBuyDetour = DETOUR_CREATE_MEMBER_FIXED(CanPlayerBuy, address);
|
||||
}
|
||||
|
||||
if (MainConfig->GetMemSig("CanBuyThis", &address))
|
||||
{
|
||||
MF_Log("GiveShield is not available");
|
||||
CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, address);
|
||||
}
|
||||
|
||||
if (!BuyGunAmmoDetour || !GiveNamedItemDetour || !AddAccountDetour || !CanPlayerBuyDetour || !CanBuyThisDetour)
|
||||
{
|
||||
if (!BuyGunAmmoDetour)
|
||||
{
|
||||
MF_Log("BuyGunAmmo is not available");
|
||||
}
|
||||
|
||||
if (!GiveNamedItemDetour)
|
||||
|
@ -470,52 +463,67 @@ void CtrlDetours_BuyCommands(bool set)
|
|||
MF_Log("AddAccount is not available");
|
||||
}
|
||||
|
||||
MF_Log("Some functions are not available - forward CS_OnBuyAttempt and CS_OnBuy have been disabled");
|
||||
if (!CanPlayerBuyDetour)
|
||||
{
|
||||
MF_Log("CanPlayerBuy is not available");
|
||||
}
|
||||
|
||||
if (!CanBuyThisDetour)
|
||||
{
|
||||
MF_Log("CanBuyThis is not available");
|
||||
}
|
||||
|
||||
MF_Log("Some functions are not available - forwards CS_OnBuy[Attempt] have been disabled");
|
||||
ToggleDetour_BuyCommands(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GiveShieldDetour)
|
||||
{
|
||||
GiveShieldDetour->Destroy();
|
||||
}
|
||||
|
||||
if (GiveNamedItemDetour)
|
||||
{
|
||||
GiveNamedItemDetour->Destroy();
|
||||
}
|
||||
|
||||
if (AddAccountDetour)
|
||||
{
|
||||
AddAccountDetour->Destroy();
|
||||
}
|
||||
DestroyDetour(BuyGunAmmoDetour);
|
||||
DestroyDetour(GiveNamedItemDetour);
|
||||
DestroyDetour(AddAccountDetour);
|
||||
DestroyDetour(CanPlayerBuyDetour);
|
||||
DestroyDetour(CanBuyThisDetour);
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleDetour_BuyCommands(bool enable)
|
||||
{
|
||||
if (GiveShieldDetour)
|
||||
{
|
||||
(enable) ? GiveShieldDetour->EnableDetour() : GiveShieldDetour->DisableDetour();
|
||||
}
|
||||
|
||||
if (GiveNamedItemDetour)
|
||||
{
|
||||
(enable) ? GiveNamedItemDetour->EnableDetour() : GiveNamedItemDetour->DisableDetour();
|
||||
}
|
||||
|
||||
if (AddAccountDetour)
|
||||
{
|
||||
(enable) ? AddAccountDetour->EnableDetour() : AddAccountDetour->DisableDetour();
|
||||
}
|
||||
ToggleDetour(BuyGunAmmoDetour, enable);
|
||||
ToggleDetour(GiveNamedItemDetour, enable);
|
||||
ToggleDetour(AddAccountDetour, enable);
|
||||
ToggleDetour(CanPlayerBuyDetour, enable);
|
||||
ToggleDetour(CanBuyThisDetour, enable);
|
||||
}
|
||||
|
||||
|
||||
void CtrlDetours_Natives(bool set)
|
||||
{
|
||||
if (set)
|
||||
{
|
||||
void *address = nullptr;
|
||||
|
||||
if (MainConfig->GetMemSig("GiveDefaultItems", &address))
|
||||
{
|
||||
GiveDefaultItemsDetour = DETOUR_CREATE_MEMBER_FIXED(GiveDefaultItems, address);
|
||||
}
|
||||
|
||||
if (!GiveDefaultItemsDetour)
|
||||
{
|
||||
MF_Log("GiveDefaultItems is not available - native cs_set_no_knives has been disabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyDetour(GiveDefaultItemsDetour);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InitFuncsAddresses()
|
||||
{
|
||||
void *address = nullptr;
|
||||
|
||||
if (MainConfig->GetMemSig("CreateNamedEntity", &address)) // cs_create_entity()
|
||||
{
|
||||
CS_CreateNamedEntity = reinterpret_cast<CreateNamedEntityFunc>(address);
|
||||
|
@ -544,26 +552,29 @@ void CtrlDetours_Natives(bool set)
|
|||
|
||||
if (!GetWeaponInfo)
|
||||
{
|
||||
MF_Log("GetWeaponInfo is not available - native cs_get_weapon_info() has been disabled");
|
||||
MF_Log("GetWeaponInfo is not available - native cs_get_weapon_info() and forward CS_OnBuy have been disabled");
|
||||
CtrlDetours_BuyCommands(false);
|
||||
}
|
||||
}
|
||||
|
||||
void InitClassMembers()
|
||||
{
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_iTeam" , &TeamDesc );
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_iMenu" , &MenuDesc );
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_bHasNightVision", &NvgsDesc );
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_bHasDefuser" , &DefuserDesc);
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_signals" , &SignalsDesc);
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_iAccount" , &MoneyDesc );
|
||||
|
||||
if (MainConfig->GetMemSig("GiveDefaultItems", &address))
|
||||
if (!TeamDesc.fieldOffset ||
|
||||
!MenuDesc.fieldOffset ||
|
||||
!NvgsDesc.fieldOffset ||
|
||||
!DefuserDesc.fieldOffset ||
|
||||
!SignalsDesc.fieldOffset ||
|
||||
!MoneyDesc.fieldOffset)
|
||||
{
|
||||
GiveDefaultItemsDetour = DETOUR_CREATE_MEMBER_FIXED(GiveDefaultItems, address);
|
||||
}
|
||||
|
||||
if (!GiveDefaultItemsDetour)
|
||||
{
|
||||
MF_Log("GiveDefaultItems is not available - native cs_set_no_knives has been disabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GiveDefaultItemsDetour)
|
||||
{
|
||||
GiveDefaultItemsDetour->Destroy();
|
||||
}
|
||||
MF_Log("Invalid or missing entity gamedata files - forwards CS_OnBuy[Attempt] have been disabled");
|
||||
CtrlDetours_BuyCommands(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,30 +582,43 @@ void InitGlobalVars()
|
|||
{
|
||||
void *address = nullptr;
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(KE_WINDOWS)
|
||||
|
||||
TypeDescription typeDesc;
|
||||
|
||||
if (CommonConfig->GetOffset("svs", &typeDesc))
|
||||
{
|
||||
uintptr_t base = *reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(g_engfuncs.pfnGetCurrentPlayer) + typeDesc.fieldOffset);
|
||||
ServerStatic = reinterpret_cast<server_static_t*>(base - 4);
|
||||
ServerStatic = reinterpret_cast<decltype(ServerStatic)>(base - 4);
|
||||
}
|
||||
|
||||
if (CommonConfig->GetAddress("sv", &address))
|
||||
{
|
||||
Server = *reinterpret_cast<server_t**>(address);
|
||||
Server = *reinterpret_cast<decltype(Server)*>(address);
|
||||
}
|
||||
|
||||
if (CommonConfig->GetAddress("g_pGameRules", &address))
|
||||
{
|
||||
GameRules = *reinterpret_cast<decltype(GameRules)*>(address);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (CommonConfig->GetMemSig("svs", &address))
|
||||
{
|
||||
ServerStatic = reinterpret_cast<server_static_t*>(address);
|
||||
ServerStatic = reinterpret_cast<decltype(ServerStatic)>(address);
|
||||
}
|
||||
|
||||
if (CommonConfig->GetMemSig("sv", &address))
|
||||
{
|
||||
Server = reinterpret_cast<server_t*>(address);
|
||||
Server = reinterpret_cast<decltype(Server)>(address);
|
||||
}
|
||||
|
||||
if (CommonConfig->GetMemSig("g_pGameRules", &address))
|
||||
{
|
||||
GameRules = reinterpret_cast<decltype(GameRules)>(address);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!ServerStatic)
|
||||
|
@ -606,4 +630,10 @@ void InitGlobalVars()
|
|||
{
|
||||
MF_Log("sv global variable is not available");
|
||||
}
|
||||
|
||||
if (!GameRules)
|
||||
{
|
||||
MF_Log("g_pGameRules is not available - Forward CS_OnBuy has been disabled");
|
||||
CtrlDetours_BuyCommands(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,17 @@
|
|||
#include "CstrikeDatas.h"
|
||||
|
||||
void InitializeHacks();
|
||||
void InitFuncsAddresses();
|
||||
void InitClassMembers();
|
||||
void InitGlobalVars();
|
||||
void ShutdownHacks();
|
||||
|
||||
void CtrlDetours_ClientCommand(bool set);
|
||||
void CtrlDetours_BuyCommands(bool set);
|
||||
void CtrlDetours_Natives(bool set);
|
||||
|
||||
void ToggleDetour_ClientCommands(bool enable);
|
||||
void ToggleDetour_BuyCommands(bool enable);
|
||||
void OnEmitSound(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch);
|
||||
|
||||
extern AMX_NATIVE_INFO CstrikeNatives[];
|
||||
|
||||
|
@ -36,6 +42,18 @@ extern int ForwardInternalCommand;
|
|||
extern int ForwardOnBuy;
|
||||
extern int ForwardOnBuyAttempt;
|
||||
|
||||
extern bool HasInternalCommandForward;
|
||||
extern bool HasOnBuyAttemptForward;
|
||||
extern bool HasOnBuyForward;
|
||||
|
||||
extern CDetour *ClientCommandDetour;
|
||||
extern CDetour *GiveNamedItemDetour;
|
||||
extern CDetour *AddAccountDetour;
|
||||
extern CDetour *CanPlayerBuyDetour;
|
||||
extern CDetour *CanBuyThisDetour;
|
||||
extern CDetour *GiveDefaultItemsDetour;
|
||||
extern CDetour *BuyGunAmmoDetour;
|
||||
|
||||
typedef edict_t* (*CreateNamedEntityFunc)(string_t iszClassname);
|
||||
typedef void* (*UTIL_FindEntityByStringFunc)(void* pStartEntity, const char *szKeyword, const char *szValue);
|
||||
typedef WeaponInfoStruct* (*GetWeaponInfoFunc)(int id);
|
||||
|
@ -47,9 +65,13 @@ extern GetWeaponInfoFunc GetWeaponInfo;
|
|||
extern CDetour *GiveDefaultItemsDetour;
|
||||
extern enginefuncs_t *g_pengfuncsTable;
|
||||
extern DLL_FUNCTIONS *g_pFunctionTable;
|
||||
extern bool NoKifesMode;
|
||||
extern bool NoKnivesMode;
|
||||
|
||||
extern server_static_t *ServerStatic;
|
||||
extern server_t *Server;
|
||||
extern void **GameRules;
|
||||
|
||||
extern int *UseBotArgs;
|
||||
extern const char **BotArgs;
|
||||
|
||||
#endif // CSTRIKE_HACKS_H
|
||||
|
|
|
@ -12,9 +12,10 @@
|
|||
//
|
||||
|
||||
#include "CstrikeItemsInfos.h"
|
||||
#include <amxxmodule.h>
|
||||
#include "CstrikeHacks.h"
|
||||
|
||||
CsItemInfo ItemsManager;
|
||||
char WeaponNameList[MAX_WEAPONS][64];
|
||||
|
||||
#define PSTATE_ALIASES_TYPE 0
|
||||
#define PSTATE_ALIASES_ALIAS 1
|
||||
|
@ -52,15 +53,15 @@ SMCResult CsItemInfo::ReadSMC_NewSection(const SMCStates *states, const char *na
|
|||
{
|
||||
m_List = nullptr;
|
||||
|
||||
if (!strcmp(name, "Common"))
|
||||
if (!strcmp(name, "CommonAlias"))
|
||||
{
|
||||
m_List = &m_CommonAliasesList;
|
||||
}
|
||||
else if (!strcmp(name, "Weapon"))
|
||||
else if (!strcmp(name, "WeaponAlias"))
|
||||
{
|
||||
m_List = &m_WeaponAliasesList;
|
||||
}
|
||||
else if (!strcmp(name, "Buy") || !strcmp(name, "BuyEquip") || !strcmp(name, "BuyAmmo"))
|
||||
else if (!strcmp(name, "BuyAlias") || !strcmp(name, "BuyEquipAlias") || !strcmp(name, "BuyAmmoAlias"))
|
||||
{
|
||||
m_List = &m_BuyAliasesList;
|
||||
}
|
||||
|
@ -113,6 +114,21 @@ SMCResult CsItemInfo::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
|||
{
|
||||
m_AliasInfo.classname = value;
|
||||
}
|
||||
else if (!strcmp(key, "price"))
|
||||
{
|
||||
static int equipmentsList[static_cast<size_t>(Equipments::Count)] =
|
||||
{
|
||||
CSI_NONE, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_LENGTH(equipmentsList); ++i)
|
||||
{
|
||||
if (m_AliasInfo.itemid == equipmentsList[i])
|
||||
{
|
||||
m_EquipmentsPrice[i] = atoi(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -231,3 +247,31 @@ CsWeaponClassType CsItemInfo::WeaponIdToClass(int id)
|
|||
|
||||
return CS_WEAPONCLASS_NONE;
|
||||
}
|
||||
|
||||
int CsItemInfo::GetItemPrice(int itemId)
|
||||
{
|
||||
if (itemId <= CSI_NONE || itemId > CSI_SHIELD)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Equipments id = Equipments::None;
|
||||
|
||||
switch (itemId)
|
||||
{
|
||||
case CSI_VEST: id = Equipments::Vest; break;
|
||||
case CSI_VESTHELM: id = Equipments::Vesthelm; break;
|
||||
case CSI_HEGRENADE: id = Equipments::HEGrenade; break;
|
||||
case CSI_SMOKEGRENADE: id = Equipments::SmokeGrenade; break;
|
||||
case CSI_FLASHBANG: id = Equipments::Flashbang; break;
|
||||
case CSI_NVGS: id = Equipments::Nvg; break;
|
||||
case CSI_DEFUSER: id = Equipments::Defuser; break;
|
||||
}
|
||||
|
||||
if (id != Equipments::None)
|
||||
{
|
||||
return m_EquipmentsPrice[static_cast<size_t>(id)];
|
||||
}
|
||||
|
||||
return GetWeaponInfo(itemId == CSI_SHIELD ? CSI_SHIELDGUN : itemId)->cost;
|
||||
}
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
#ifndef _CSTRIKE_WEAPONS_INFOS_H_
|
||||
#define _CSTRIKE_WEAPONS_INFOS_H_
|
||||
|
||||
#include <amxxmodule.h>
|
||||
#include "CstrikeDatas.h"
|
||||
#include <ITextParsers.h>
|
||||
#include <am-string.h>
|
||||
#include <amtl/am-string.h>
|
||||
#include <sm_stringhashmap.h>
|
||||
|
||||
struct AliasInfo
|
||||
|
@ -37,12 +38,25 @@ struct AliasInfo
|
|||
ke::AString classname;
|
||||
};
|
||||
|
||||
enum class Equipments
|
||||
{
|
||||
None,
|
||||
Vest,
|
||||
Vesthelm,
|
||||
Flashbang,
|
||||
HEGrenade,
|
||||
SmokeGrenade,
|
||||
Nvg,
|
||||
Defuser,
|
||||
Count
|
||||
};
|
||||
|
||||
class CsItemInfo : public ITextListener_SMC
|
||||
{
|
||||
public:
|
||||
|
||||
CsItemInfo();
|
||||
~CsItemInfo();
|
||||
virtual ~CsItemInfo();
|
||||
|
||||
public:
|
||||
|
||||
|
@ -64,6 +78,8 @@ class CsItemInfo : public ITextListener_SMC
|
|||
|
||||
CsWeaponClassType WeaponIdToClass(int id);
|
||||
|
||||
int GetItemPrice(int id);
|
||||
|
||||
private: // Retrieved datas
|
||||
|
||||
typedef StringHashMap<AliasInfo> AliasMap;
|
||||
|
@ -81,8 +97,10 @@ class CsItemInfo : public ITextListener_SMC
|
|||
ke::AString m_Alias;
|
||||
AliasInfo m_AliasInfo;
|
||||
bool m_ListsRetrievedFromConfig;
|
||||
int m_EquipmentsPrice[static_cast<size_t>(Equipments::Count)];
|
||||
};
|
||||
|
||||
extern char WeaponNameList[MAX_WEAPONS][64];
|
||||
extern CsItemInfo ItemsManager;
|
||||
|
||||
#endif // _CSTRIKE_WEAPONS_INFOS_H_
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "amxxmodule.h"
|
||||
#include "CstrikeUtils.h"
|
||||
#include "CstrikeHacks.h"
|
||||
#include "CstrikeItemsInfos.h"
|
||||
#include "CstrikeUserMessages.h"
|
||||
#include <IGameConfigs.h>
|
||||
|
||||
IGameConfig *MainConfig;
|
||||
|
@ -39,7 +41,7 @@ void OnAmxxAttach()
|
|||
ConfigManager = MF_GetConfigManager();
|
||||
|
||||
char error[256] = "";
|
||||
ConfigManager->AddUserConfigHook("CommandsAliases", &ItemsManager);
|
||||
ConfigManager->AddUserConfigHook("ItemInfos", &ItemsManager);
|
||||
|
||||
if (!ConfigManager->LoadGameConfigFile("modules.games", &MainConfig, error, sizeof(error)) && *error)
|
||||
{
|
||||
|
@ -48,6 +50,7 @@ void OnAmxxAttach()
|
|||
}
|
||||
|
||||
*error = '\0';
|
||||
|
||||
if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof(error)) && *error)
|
||||
{
|
||||
MF_Log("Could not read common.games gamedata: %s", error);
|
||||
|
@ -59,27 +62,29 @@ void OnAmxxAttach()
|
|||
|
||||
void OnPluginsLoaded()
|
||||
{
|
||||
TypeConversion.init();
|
||||
|
||||
ForwardInternalCommand = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, 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);
|
||||
|
||||
// Checking whether such public forwards are used in plugins.
|
||||
// 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; }
|
||||
if (!ClientCommandDetour) // All CS_* forwards requires ClientCommand. Unlikely to fail.
|
||||
{
|
||||
ToggleDetour_ClientCommands(false);
|
||||
ToggleDetour_BuyCommands(false);
|
||||
|
||||
// And enable/disable detours when necessary.
|
||||
ToggleDetour_ClientCommands(ForwardInternalCommand != -1 || ForwardOnBuy != -1 || ForwardOnBuyAttempt != -1);
|
||||
ToggleDetour_BuyCommands(ForwardOnBuy != -1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Search pev/vtable offset automatically.
|
||||
TypeConversion.init();
|
||||
auto haveBotDetours = UseBotArgs && BotArgs;
|
||||
auto haveBuyDetours = BuyGunAmmoDetour && GiveNamedItemDetour && AddAccountDetour && CanPlayerBuyDetour && CanBuyThisDetour;
|
||||
|
||||
// Used with model natives, enabled on demand.
|
||||
g_pengfuncsTable->pfnSetClientKeyValue = nullptr;
|
||||
g_pFunctionTable->pfnClientUserInfoChanged = nullptr;
|
||||
g_pFunctionTable->pfnStartFrame = nullptr;
|
||||
HasInternalCommandForward = haveBotDetours && UTIL_CheckForPublic("CS_InternalCommand");
|
||||
HasOnBuyAttemptForward = haveBuyDetours && UTIL_CheckForPublic("CS_OnBuyAttempt");
|
||||
HasOnBuyForward = haveBuyDetours && UTIL_CheckForPublic("CS_OnBuy");
|
||||
|
||||
ToggleDetour_ClientCommands(HasInternalCommandForward || HasOnBuyAttemptForward || HasOnBuyForward);
|
||||
ToggleDetour_BuyCommands(HasOnBuyForward);
|
||||
}
|
||||
|
||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
|
@ -95,13 +100,18 @@ void OnServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
|
|||
|
||||
void OnPluginsUnloaded()
|
||||
{
|
||||
// Force to disable all hooks at map change.
|
||||
// Used with model natives, enabled on demand.
|
||||
g_pengfuncsTable->pfnSetClientKeyValue = nullptr;
|
||||
g_pFunctionTable->pfnClientUserInfoChanged = nullptr;
|
||||
g_pFunctionTable->pfnStartFrame = nullptr;
|
||||
|
||||
// Force to disable all event hooks at map change.
|
||||
DisableMessageHooks(true);
|
||||
}
|
||||
|
||||
void OnAmxxDetach()
|
||||
{
|
||||
ConfigManager->RemoveUserConfigHook("CommandsAliases", &ItemsManager);
|
||||
ConfigManager->RemoveUserConfigHook("ItemInfos", &ItemsManager);
|
||||
|
||||
ConfigManager->CloseGameConfigFile(MainConfig);
|
||||
ConfigManager->CloseGameConfigFile(CommonConfig);
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#include "CstrikeUtils.h"
|
||||
#include "CstrikeHacks.h"
|
||||
#include "CstrikeUserMessages.h"
|
||||
#include "CstrikeItemsInfos.h"
|
||||
#include <CDetour/detours.h>
|
||||
#include <amtl/am-string.h>
|
||||
|
||||
bool NoKifesMode = false;
|
||||
char WeaponNameList[MAX_WEAPONS][64];
|
||||
bool NoKnivesMode = false;
|
||||
|
||||
// native cs_set_user_money(index, money, flash = 1);
|
||||
static cell AMX_NATIVE_CALL cs_set_user_money(AMX *amx, cell *params)
|
||||
|
@ -1073,7 +1073,7 @@ static cell AMX_NATIVE_CALL cs_get_user_hasprimary(AMX *amx, cell *params)
|
|||
// native cs_get_no_knives();
|
||||
static cell AMX_NATIVE_CALL cs_get_no_knives(AMX *amx, cell *params)
|
||||
{
|
||||
return NoKifesMode ? 1 : 0;
|
||||
return NoKnivesMode ? 1 : 0;
|
||||
}
|
||||
|
||||
// native cs_set_no_knives(noknives = 0);
|
||||
|
@ -1085,9 +1085,9 @@ static cell AMX_NATIVE_CALL cs_set_no_knives(AMX *amx, cell *params)
|
|||
return 0;
|
||||
}
|
||||
|
||||
NoKifesMode = params[1] != 0;
|
||||
NoKnivesMode = params[1] != 0;
|
||||
|
||||
if (NoKifesMode)
|
||||
if (NoKnivesMode)
|
||||
{
|
||||
GiveDefaultItemsDetour->EnableDetour();
|
||||
}
|
||||
|
@ -1756,21 +1756,21 @@ static cell AMX_NATIVE_CALL cs_find_ent_by_owner(AMX* amx, cell* params)
|
|||
}
|
||||
|
||||
int owner = params[3];
|
||||
CHECK_ENTITY_SIMPLE(params[3]);
|
||||
CHECK_ENTITY_SIMPLE(owner);
|
||||
|
||||
int length;
|
||||
void* pEntity = G_HL_TypeConversion.id_to_cbase(params[1]);
|
||||
void* pEntity = TypeConversion.id_to_cbase(params[1]);
|
||||
const char* value = MF_GetAmxString(amx, params[2], 0, &length);
|
||||
|
||||
edict_t *pOwner = GETEDICT(owner);
|
||||
edict_t *pOwner = TypeConversion.id_to_edict(owner);
|
||||
|
||||
while ((pEntity = CS_UTIL_FindEntityByString(pEntity, "classname", value)))
|
||||
{
|
||||
edict_t *pev = G_HL_TypeConversion.cbase_to_edict(pEntity);
|
||||
edict_t *pev = TypeConversion.cbase_to_edict(pEntity);
|
||||
|
||||
if (!FNullEnt(pev) && pev->v.owner == pOwner)
|
||||
{
|
||||
int index = ENTINDEX(pev);
|
||||
int index = TypeConversion.edict_to_id(pev);
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
|
@ -1787,7 +1787,7 @@ static cell AMX_NATIVE_CALL cs_get_item_id(AMX* amx, cell* params)
|
|||
{
|
||||
if (ItemsManager.HasConfigError())
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_item_id() is disabled disabled because of missing gamedata");
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_item_id() is disabled because of corrupted or missing gamedata");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1814,7 +1814,7 @@ static cell AMX_NATIVE_CALL cs_get_translated_item_alias(AMX* amx, cell* params)
|
|||
{
|
||||
if (ItemsManager.HasConfigError())
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_translated_item_alias() is disabled because of missing gamedata");
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_translated_item_alias() is disabled because of corrupted or missing gamedata");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,13 +11,12 @@
|
|||
// Counter-Strike Module
|
||||
//
|
||||
|
||||
#include <amxxmodule.h>
|
||||
#include "CstrikeUserMessages.h"
|
||||
#include "CstrikeUtils.h"
|
||||
#include "CstrikeHacks.h"
|
||||
#include "CstrikePlayer.h"
|
||||
#include "CstrikeDatas.h"
|
||||
#include <am-string.h>
|
||||
#include "CstrikeItemsInfos.h"
|
||||
#include <amtl/am-string.h>
|
||||
|
||||
bool ShouldBlock;
|
||||
bool ShouldBlockHLTV;
|
||||
|
@ -116,26 +115,6 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
|
|||
DisableMessageHooks();
|
||||
}
|
||||
}
|
||||
else if (msg_type == MessageIdStatusIcon)
|
||||
{
|
||||
if (OnMessageStatusIcon(pEntity))
|
||||
{
|
||||
ShouldBlock = true;
|
||||
ShouldDisableHooks = true;
|
||||
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
else if (msg_type == MessageIdItemStatus)
|
||||
{
|
||||
if (OnMessageItemStatus(pEntity))
|
||||
{
|
||||
ShouldBlock = true;
|
||||
ShouldDisableHooks = true;
|
||||
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SPEC:
|
||||
|
|
|
@ -110,6 +110,7 @@ bool UTIL_CheckForPublic(const char *publicname);
|
|||
member = type.fieldOffset; \
|
||||
}
|
||||
|
||||
|
||||
class CUnifiedSignals
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -55,16 +55,16 @@
|
|||
#define CSW_SHIELDGUN 99
|
||||
#define CSW_LAST_WEAPON CSW_P90
|
||||
|
||||
stock const CSW_ALL_WEAPONS = (~(1<<CSW_VEST));
|
||||
stock const CSW_ALL_PISTOLS = (1<<CSW_P228 | 1<<CSW_ELITE | 1<<CSW_FIVESEVEN | 1<<CSW_USP | 1<<CSW_GLOCK18 | 1<<CSW_DEAGLE);
|
||||
stock const CSW_ALL_SHOTGUNS = (1<<CSW_M3 | 1<<CSW_XM1014);
|
||||
stock const CSW_ALL_SMGS = (1<<CSW_MAC10 | 1<<CSW_UMP45 | 1<<CSW_MP5NAVY | 1<<CSW_TMP | 1<<CSW_P90);
|
||||
stock const CSW_ALL_RIFLES = (1<<CSW_AUG | 1<<CSW_GALIL | 1<<CSW_FAMAS | 1<<CSW_M4A1 | 1<<CSW_AK47 | 1<<CSW_SG552);
|
||||
stock const CSW_ALL_SNIPERRIFLES = (1<<CSW_SCOUT | 1<<CSW_AWP | 1<<CSW_G3SG1 | 1<<CSW_SG550);
|
||||
stock const CSW_ALL_MACHINEGUNS = (1<<CSW_M249);
|
||||
stock const CSW_ALL_GRENADES = (1<<CSW_HEGRENADE | 1<<CSW_SMOKEGRENADE | 1<<CSW_FLASHBANG);
|
||||
stock const CSW_ALL_ARMORS = (1<<CSW_VEST | 1<<CSW_VESTHELM);
|
||||
stock const CSW_ALL_GUNS = (CSW_ALL_PISTOLS | CSW_ALL_SHOTGUNS | CSW_ALL_SMGS | CSW_ALL_RIFLES | CSW_ALL_SNIPERRIFLES | CSW_ALL_MACHINEGUNS);
|
||||
const CSW_ALL_WEAPONS = (~(1<<CSW_VEST));
|
||||
const CSW_ALL_PISTOLS = (1<<CSW_P228 | 1<<CSW_ELITE | 1<<CSW_FIVESEVEN | 1<<CSW_USP | 1<<CSW_GLOCK18 | 1<<CSW_DEAGLE);
|
||||
const CSW_ALL_SHOTGUNS = (1<<CSW_M3 | 1<<CSW_XM1014);
|
||||
const CSW_ALL_SMGS = (1<<CSW_MAC10 | 1<<CSW_UMP45 | 1<<CSW_MP5NAVY | 1<<CSW_TMP | 1<<CSW_P90);
|
||||
const CSW_ALL_RIFLES = (1<<CSW_AUG | 1<<CSW_GALIL | 1<<CSW_FAMAS | 1<<CSW_M4A1 | 1<<CSW_AK47 | 1<<CSW_SG552);
|
||||
const CSW_ALL_SNIPERRIFLES = (1<<CSW_SCOUT | 1<<CSW_AWP | 1<<CSW_G3SG1 | 1<<CSW_SG550);
|
||||
const CSW_ALL_MACHINEGUNS = (1<<CSW_M249);
|
||||
const CSW_ALL_GRENADES = (1<<CSW_HEGRENADE | 1<<CSW_SMOKEGRENADE | 1<<CSW_FLASHBANG);
|
||||
const CSW_ALL_ARMORS = (1<<CSW_VEST | 1<<CSW_VESTHELM);
|
||||
const CSW_ALL_GUNS = (CSW_ALL_PISTOLS | CSW_ALL_SHOTGUNS | CSW_ALL_SMGS | CSW_ALL_RIFLES | CSW_ALL_SNIPERRIFLES | CSW_ALL_MACHINEGUNS);
|
||||
|
||||
/**
|
||||
* @section Team and team model constants, used by cs_[get|set]_user_team().
|
||||
|
@ -394,7 +394,7 @@ enum CsAutoBuyClassType
|
|||
};
|
||||
|
||||
/**
|
||||
* Ammo types.
|
||||
* Ammo types for use with cs_get_weapon_info().
|
||||
*/
|
||||
enum CsAmmoType
|
||||
{
|
||||
|
@ -410,6 +410,9 @@ enum CsAmmoType
|
|||
CS_AMMO_357SIG = 9,
|
||||
};
|
||||
|
||||
/**
|
||||
* Weapon info types for use with cs_get_weapon_info().
|
||||
*/
|
||||
enum CsWeaponInfo
|
||||
{
|
||||
CS_WEAPONINFO_COST = 0,
|
||||
|
@ -419,3 +422,66 @@ enum CsWeaponInfo
|
|||
CS_WEAPONINFO_MAX_ROUNDS = 4,
|
||||
CS_WEAPONINFO_AMMO_TYPE = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* Weapon default cost.
|
||||
*/
|
||||
enum CsWeaponCostType
|
||||
{
|
||||
CS_AK47_PRICE = 2500,
|
||||
CS_AWP_PRICE = 4750,
|
||||
CS_DEAGLE_PRICE = 650,
|
||||
CS_G3SG1_PRICE = 5000,
|
||||
CS_SG550_PRICE = 4200,
|
||||
CS_GLOCK18_PRICE = 400,
|
||||
CS_M249_PRICE = 5750,
|
||||
CS_M3_PRICE = 1700,
|
||||
CS_M4A1_PRICE = 3100,
|
||||
CS_AUG_PRICE = 3500,
|
||||
CS_MP5NAVY_PRICE = 1500,
|
||||
CS_P228_PRICE = 600,
|
||||
CS_P90_PRICE = 2350,
|
||||
CS_UMP45_PRICE = 1700,
|
||||
CS_MAC10_PRICE = 1400,
|
||||
CS_SCOUT_PRICE = 2750,
|
||||
CS_SG552_PRICE = 3500,
|
||||
CS_TMP_PRICE = 1250,
|
||||
CS_USP_PRICE = 500,
|
||||
CS_ELITE_PRICE = 800,
|
||||
CS_FIVESEVEN_PRICE = 750,
|
||||
CS_XM1014_PRICE = 3000,
|
||||
CS_GALIL_PRICE = 2000,
|
||||
CS_FAMAS_PRICE = 2250,
|
||||
CS_SHIELDGUN_PRICE = 2200
|
||||
};
|
||||
|
||||
/**
|
||||
* Equipment default cost.
|
||||
*/
|
||||
enum CsItemCostType
|
||||
{
|
||||
CS_ASSAULTSUIT_PRICE = 1000,
|
||||
CS_FLASHBANG_PRICE = 200,
|
||||
CS_HEGRENADE_PRICE = 300,
|
||||
CS_SMOKEGRENADE_PRICE = 300,
|
||||
CS_KEVLAR_PRICE = 650,
|
||||
CS_HELMET_PRICE = 350,
|
||||
CS_NVG_PRICE = 1250,
|
||||
CS_DEFUSEKIT_PRICE = 200
|
||||
};
|
||||
|
||||
/**
|
||||
* Ammo default cost.
|
||||
*/
|
||||
enum CsAmmoCostType
|
||||
{
|
||||
CS_AMMO_338MAG_PRICE = 125,
|
||||
CS_AMMO_357SIG_PRICE = 50,
|
||||
CS_AMMO_45ACP_PRICE = 25,
|
||||
CS_AMMO_50AE_PRICE = 40,
|
||||
CS_AMMO_556NATO_PRICE = 60,
|
||||
CS_AMMO_57MM_PRICE = 50,
|
||||
CS_AMMO_762NATO_PRICE = 80,
|
||||
CS_AMMO_9MM_PRICE = 20,
|
||||
CS_AMMO_BUCKSHOT_PRICE = 65
|
||||
};
|
||||
|
|
|
@ -150,6 +150,11 @@ class HLTypeConversion
|
|||
return get_pdata<entvars_t*>(cbase, m_PevOffset);
|
||||
}
|
||||
|
||||
edict_t* cbase_to_edict(void *cbase)
|
||||
{
|
||||
return entvar_to_edict(cbase_to_entvar(cbase));
|
||||
}
|
||||
|
||||
int cbase_to_id(void *cbase)
|
||||
{
|
||||
return entvars_to_id(cbase_to_entvar(cbase));
|
||||
|
|
Loading…
Reference in New Issue
Block a user