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:
Arkshine 2015-10-08 20:53:14 +02:00
parent d08e1357dd
commit a445e806ea
13 changed files with 635 additions and 376 deletions

View File

@ -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,52 +406,58 @@
}
}
"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
"itemid" "25" // CSW/I_FLASHBANG
"classid" "3" // CS_WEAPONCLASS_GRENADE
"price" "200"
}
"vest"
{
"itemid" "31" // CSW/I_VEST
"classname" "item_kevlar"
"itemid" "31" // CSW/I_VEST
"classname" "item_kevlar"
"price" "650"
}
"vesthelm"
{
"itemid" "32" // CSW/I_VESTHELM
"classname" "item_assaultsuit"
"itemid" "32" // CSW/I_VESTHELM
"classname" "item_assaultsuit"
"price" "1000"
}
"defuser"
{
"itemid" "33" // CSI_DEFUSER
"classname" "item_thighpack"
"itemid" "33" // CSI_DEFUSER
"classname" "item_thighpack"
"price" "200"
}
"nvgs"
{
"itemid" "34" // CSI_NVGS
"itemid" "34" // CSI_NVGS
"price" "1250"
}
"shield"
{
"itemid" "35" // CSI_SHIELD
"classid" "2" // CS_WEAPONCLASS_PISTOL
"classname" "weapon_shield"
"itemid" "35" // CSI_SHIELD
"classid" "2" // CS_WEAPONCLASS_PISTOL
"classname" "weapon_shield"
}
}
"BuyAmmo"
"BuyAmmoAlias"
{
"primammo"
{

View File

@ -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',

View File

@ -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

View File

@ -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;
@ -141,78 +159,40 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
}
else // Handling buy via alias
{
AliasInfo info;
if (ItemsManager.GetAliasInfosFromBuy(command, &info))
if (get_pdata<CUnifiedSignals>(pEdict, SignalsDesc.fieldOffset).GetState() & SIGNAL_BUY) // Are we inside the buy zone?
{
CurrentItemId = info.itemid;
AliasInfo info;
if (ItemsManager.GetAliasInfosFromBuy(command, &info))
{
CurrentItemId = info.itemid;
}
}
}
}
int client = ENTINDEX(pEdict);
auto client = TypeConversion.edict_to_id(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)
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;
return;
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)
if (BlockMoneyUpdate)
{
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:
{
return;
}
}
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))
{
CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, address);
}
if (!BuyGunAmmoDetour || !GiveNamedItemDetour || !AddAccountDetour || !CanPlayerBuyDetour || !CanBuyThisDetour)
{
if (!BuyGunAmmoDetour)
{
MF_Log("GiveShield is not available");
MF_Log("BuyGunAmmo is not available");
}
if (!GiveNamedItemDetour)
@ -470,84 +463,46 @@ 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("CreateNamedEntity", &address)) // cs_create_entity()
{
CS_CreateNamedEntity = reinterpret_cast<CreateNamedEntityFunc>(address);
}
if (MainConfig->GetMemSig("FindEntityByString", &address)) // cs_find_ent_by_class()
{
CS_UTIL_FindEntityByString = reinterpret_cast<UTIL_FindEntityByStringFunc>(address);
}
if (MainConfig->GetMemSig("GetWeaponInfo", &address)) // cs_get_weapon_info()
{
GetWeaponInfo = reinterpret_cast<GetWeaponInfoFunc>(address);
}
if (!CS_CreateNamedEntity)
{
MF_Log("CREATE_NAMED_ENITTY is not available - native cs_create_entity() has been disabled");
}
if (!CS_UTIL_FindEntityByString)
{
MF_Log("UTIL_FindEntByString is not available - native cs_find_ent_by_class() has been disabled");
}
if (!GetWeaponInfo)
{
MF_Log("GetWeaponInfo is not available - native cs_get_weapon_info() has been disabled");
}
if (MainConfig->GetMemSig("GiveDefaultItems", &address))
{
GiveDefaultItemsDetour = DETOUR_CREATE_MEMBER_FIXED(GiveDefaultItems, address);
@ -560,10 +515,66 @@ void CtrlDetours_Natives(bool set)
}
else
{
if (GiveDefaultItemsDetour)
{
GiveDefaultItemsDetour->Destroy();
}
DestroyDetour(GiveDefaultItemsDetour);
}
}
void InitFuncsAddresses()
{
void *address = nullptr;
if (MainConfig->GetMemSig("CreateNamedEntity", &address)) // cs_create_entity()
{
CS_CreateNamedEntity = reinterpret_cast<CreateNamedEntityFunc>(address);
}
if (MainConfig->GetMemSig("FindEntityByString", &address)) // cs_find_ent_by_class()
{
CS_UTIL_FindEntityByString = reinterpret_cast<UTIL_FindEntityByStringFunc>(address);
}
if (MainConfig->GetMemSig("GetWeaponInfo", &address)) // cs_get_weapon_info()
{
GetWeaponInfo = reinterpret_cast<GetWeaponInfoFunc>(address);
}
if (!CS_CreateNamedEntity)
{
MF_Log("CREATE_NAMED_ENITTY is not available - native cs_create_entity() has been disabled");
}
if (!CS_UTIL_FindEntityByString)
{
MF_Log("UTIL_FindEntByString is not available - native cs_find_ent_by_class() has been disabled");
}
if (!GetWeaponInfo)
{
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 (!TeamDesc.fieldOffset ||
!MenuDesc.fieldOffset ||
!NvgsDesc.fieldOffset ||
!DefuserDesc.fieldOffset ||
!SignalsDesc.fieldOffset ||
!MoneyDesc.fieldOffset)
{
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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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_

View File

@ -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);

View File

@ -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;
}

View File

@ -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:

View File

@ -110,6 +110,7 @@ bool UTIL_CheckForPublic(const char *publicname);
member = type.fieldOffset; \
}
class CUnifiedSignals
{
public:

View File

@ -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
};

View File

@ -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));