Merge pull request #278 from Arkshine/feature/cstrike-update-2

Update cstrike module - 2
This commit is contained in:
Vincent Herbet 2015-11-21 00:19:01 +01:00
commit 664c85106f
23 changed files with 2257 additions and 457 deletions

View File

@ -382,6 +382,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\..\plugins\include\cellstack.inc" />
<None Include="..\..\plugins\include\cstrike_const.inc" />
<None Include="..\..\plugins\include\cvars.inc" />
<None Include="..\..\plugins\include\datapack.inc" />
<None Include="..\..\plugins\include\gameconfig.inc" />

View File

@ -600,6 +600,9 @@
<None Include="..\..\plugins\include\gameconfig.inc">
<Filter>Pawn Includes</Filter>
</None>
<None Include="..\..\plugins\include\cstrike_const.inc">
<Filter>Pawn Includes</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Object Include="..\Jit\helpers-x86.obj">

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"
@ -62,6 +78,30 @@
"linux" "@_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_"
"mac" "@_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_"
}
"GetWeaponInfo" // WeaponInfoStruct *GetWeaponInfo(int id);
{
"library" "server"
"windows" "\x8B\x2A\x2A\x2A\x2A\x2A\x33\x2A\x85\x2A\x56\x74\x2A\x8B"
"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"
}
}
}
@ -99,5 +139,344 @@
}
}
}
"#default"
{
"ItemInfos"
{
"CommonAlias"
{
"p228"
{
"itemid" "1" // CSW/I_P228
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"scout"
{
"itemid" "3" // CSW/I_SCOUT
"classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE
}
"xm1014"
{
"itemid" "5" // CSW/I_XM1014
"classid" "5" // CS_WEAPONCLASS_SHOTGUN
}
"mac10"
{
"itemid" "7" // CSW/I_MAC10
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"aug"
{
"itemid" "8" // CSW/I_AUG
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"elites"
{
"itemid" "10" // CSW/I_ELITE
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"fn57"
{
"itemid" "11" // CSW/I_FIVESEVEN
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"ump45"
{
"itemid" "12" // CSW/I_UMP45
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"sg550"
{
"itemid" "13" // CSW/I_SG550
"classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE
}
"galil"
{
"itemid" "14" // CSW/I_GALIL
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"famas"
{
"itemid" "15" // CSW/I_FAMAS
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"usp"
{
"itemid" "16" // CSW/I_USP
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"glock"
{
"itemid" "17" // CSW/I_GLOCK18
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"awp"
{
"itemid" "18" // CSW/I_AWP
"classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE
}
"mp5"
{
"itemid" "19" // CSW/I_MP5NAVY
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"m249"
{
"itemid" "20" // CSW/I_M249
"classid" "6" // CS_WEAPONCLASS_MACHINEGUN
}
"m3"
{
"itemid" "21" // CSW/I_M3
"classid" "5" // CS_WEAPONCLASS_SHOTGUN
}
"m4a1"
{
"itemid" "22" // CSW/I_M4A1
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"tmp"
{
"itemid" "23" // CSW/I_TMP
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"g3sg1"
{
"itemid" "24" // CSW/I_G3SG1
"classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE
}
"deagle"
{
"itemid" "26" // CSW/I_DEAGLE
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"sg552"
{
"itemid" "27" // CSW/I_SG552
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"ak47"
{
"itemid" "28" // CSW/I_AK47
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"p90"
{
"itemid" "30" // CSW/I_P90
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"fiveseven"
{
"itemid" "11" // CSW/I_FIVESEVEN
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
}
"WeaponAlias"
{
"grenade"
{
"itemid" "4" // CSW/I_HEGRENADE
"classid" "3" // CS_WEAPONCLASS_GRENADE
}
"hegrenade"
{
"itemid" "4" // CSW/I_HEGRENADE
"classid" "3" // CS_WEAPONCLASS_GRENADE
}
"c4"
{
"itemid" "6" // CSW/I_C4
"classid" "3" // CS_WEAPONCLASS_GRENADE
}
"elite"
{
"itemid" "10" // CSW/I_ELITE
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"glock18"
{
"itemid" "17" // CSW/I_GLOCK18
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"mp5navy"
{
"itemid" "19" // CSW/I_MP5NAVY
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"knife"
{
"itemid" "29" // CSW/I_KNIFE
"classid" "1" // CS_WEAPONCLASS_KNIFE
}
}
"BuyAlias"
{
"228compact"
{
"itemid" "1" // CSW/I_P228
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"autoshotgun"
{
"itemid" "5" // CSW/I_XM1014
"classid" "5" // CS_WEAPONCLASS_SHOTGUN
}
"bullpup"
{
"itemid" "8" // CSW/I_AUG
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"sg550"
{
"itemid" "13" // CSW/I_SG550
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"krieg550"
{
"itemid" "13" // CSW/I_SG550
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"defender"
{
"itemid" "14" // CSW/I_GALIL
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"clarion"
{
"itemid" "15" // CSW/I_FAMAS
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"km45"
{
"itemid" "16" // CSW/I_USP
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"9x19mm"
{
"itemid" "17" // CSW/I_GLOCK18
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"magnum"
{
"itemid" "18" // CSW/I_AWP
"classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE
}
"smg"
{
"itemid" "19" // CSW/I_MP5NAVY
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"12gauge"
{
"itemid" "21" // CSW/I_M3
"classid" "5" // CS_WEAPONCLASS_SHOTGUN
}
"mp"
{
"itemid" "23" // CSW/I_TMP
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
"d3au1"
{
"itemid" "24" // CSW/I_G3SG1
"classid" "8" // CS_WEAPONCLASS_SNIPERRIFLE
}
"nighthawk"
{
"itemid" "26" // CSW/I_DEAGLE
"classid" "2" // CS_WEAPONCLASS_PISTOL
}
"krieg552"
{
"itemid" "27" // CSW/I_SG552
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"cv47"
{
"itemid" "28" // CSW/I_AK47
"classid" "7" // CS_WEAPONCLASS_RIFLE
}
"c90"
{
"itemid" "30" // CSW/I_P90
"classid" "4" // CS_WEAPONCLASS_SUBMACHINEGUN
}
}
"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"
{
"itemid" "35" // CSI_SHIELD
"classid" "2" // CS_WEAPONCLASS_PISTOL
"classname" "weapon_shield"
}
}
"BuyAmmoAlias"
{
"primammo"
{
"itemid" "36" // CSI_PRIAMMO
}
"secammo"
{
"itemid" "37" // CSI_SECAMMO
}
"buyammo1"
{
"itemid" "36" // CSI_PRIAMMO
}
"buyammo2"
{
"itemid" "37" // CSI_SECAMMO
}
}
}
}
}

View File

@ -15,6 +15,7 @@ binary.sources = [
'CstrikeHacks.cpp',
'CstrikeUtils.cpp',
'CstrikeUserMessages.cpp',
'CstrikeItemsInfos.cpp',
'../../../public/memtools/MemoryUtils.cpp',
'../../../public/memtools/CDetour/detours.cpp',
'../../../public/memtools/CDetour/asm/asm.c',

View File

@ -17,6 +17,7 @@
/**
* Weapon Ids for use with CS_OnBuyAttempt(), CS_OnBuy().
*/
#define CSI_NONE CSW_NONE
#define CSI_P228 CSW_P228
#define CSI_SCOUT CSW_SCOUT
#define CSI_HEGRENADE CSW_HEGRENADE
@ -50,15 +51,27 @@
#define CSI_VESTHELM CSW_VESTHELM // Custom
#define CSI_DEFUSER 33 // Custom
#define CSI_NVGS 34 // Custom
#define CSI_SHIELD 35 // Custom - The value passed by the forward, more convenient for plugins.
#define CSI_PRIAMMO 36 // Custom
#define CSI_SECAMMO 37 // Custom
#define CSI_SHIELD 38 // Custom - The value passed by the forward, more convenient for plugins.
#define CSI_MAX_COUNT 38
#define CSI_LAST_WEAPON CSW_LAST_WEAPON
#define BITS_PISTOLS (1<<CSI_GLOCK18 | 1<<CSI_USP | 1<<CSI_P228 | 1<<CSI_DEAGLE | 1<<CSI_ELITE | 1<<CSI_FIVESEVEN)
#define CSI_ALL_WEAPONS CSW_ALL_WEAPONS
#define CSI_ALL_PISTOLS CSW_ALL_PISTOLS
#define CSI_ALL_SHOTGUNS CSW_ALL_SHOTGUNS
#define CSI_ALL_SMGS CSW_ALL_SMGS
#define CSI_ALL_RIFLES CSW_ALL_RIFLES
#define CSI_ALL_SNIPERRIFLES CSW_ALL_SNIPERRIFLES
#define CSI_ALL_MACHINEGUNS CSW_ALL_MACHINEGUNS
#define CSI_ALL_GRENADES CSW_ALL_GRENADES
#define CSI_ALL_ARMORS CSW_ALL_ARMORS
#define CSI_ALL_GUNS CSW_ALL_GUNS
/**
* Weapons Ids.
*/
#define CSW_NONE 0
#define CSW_P228 1
#define CSW_SCOUT 3
#define CSW_HEGRENADE 4
@ -91,6 +104,18 @@
#define CSW_VEST 31 // Brand new invention!
#define CSW_VESTHELM 32 // Brand new invention!
#define CSW_SHIELDGUN 99
#define CSW_LAST_WEAPON CSW_P90
#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_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)
/**
* Armoury entity ids for use with cs_get/set_armoury_type().
@ -278,4 +303,98 @@ typedef enum
} Menu;
/**
* Weapon class types.
*/
enum CsWeaponClassType
{
CS_WEAPONCLASS_NONE = 0,
CS_WEAPONCLASS_KNIFE = 1,
CS_WEAPONCLASS_PISTOL = 2,
CS_WEAPONCLASS_GRENADE = 3,
CS_WEAPONCLASS_SUBMACHINEGUN = 4,
CS_WEAPONCLASS_SHOTGUN = 5,
CS_WEAPONCLASS_MACHINEGUN = 6,
CS_WEAPONCLASS_RIFLE = 7,
CS_WEAPONCLASS_SNIPERRIFLE = 8,
CS_WEAPONCLASS_MAX_COUNT = 9,
};
/**
* Weapon infos.
*/
typedef struct
{
int id;
int cost;
int clipCost;
int buyClipSize;
int gunClipSize;
int maxRounds;
int ammoType;
char *entityName;
}
WeaponInfoStruct;
/**
* Weapon infos for use with cs_get_weapon_info().
*/
enum CsWeaponInfo
{
CS_WEAPONINFO_COST = 0,
CS_WEAPONINFO_CLIP_COST = 1,
CS_WEAPONINFO_BUY_CLIP_SIZE = 2,
CS_WEAPONINFO_GUN_CLIP_SIZE = 3,
CS_WEAPONINFO_MAX_ROUNDS = 4,
CS_WEAPONINFO_AMMO_TYPE = 5,
};
/**
* 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,25 +31,47 @@ CDetour *ClientCommandDetour;
CDetour *GiveShieldDetour;
CDetour *GiveNamedItemDetour;
CDetour *AddAccountDetour;
CDetour *CanPlayerBuyDetour;
CDetour *CanBuyThisDetour;
CDetour *GiveDefaultItemsDetour;
CDetour *BuyGunAmmoDetour;
CreateNamedEntityFunc CS_CreateNamedEntity;
UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString;
GetWeaponInfoFunc GetWeaponInfo;
int CurrentItemId;
StringHashMap<int> ItemAliasList;
bool TriggeredFromCommand;
bool BlockMoneyUpdate;
bool BlockAmmosUpdate;
// 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();
}
@ -77,37 +99,26 @@ const char *CMD_ARGV(int i)
return g_engfuncs.pfnCmd_Argv(i);
}
void OnEmitSound(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch)
{
// If shield is blocked with CS_OnBuy, we need to block the pickup sound ("items/gunpickup2.wav")
// as well played right after. Why this sound is not contained in GiveShield()?
g_pengfuncsTable->pfnEmitSound = nullptr;
RETURN_META(MRES_SUPERCEDE);
}
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
{
const char *command = CMD_ARGV(0);
// A new command is triggered, reset variable, always.
CurrentItemId = 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 OnBuy* forwards.
if ((ForwardOnBuyAttempt != -1 || ForwardOnBuy != -1) && command && *command)
// to be used in CS_OnBuy* forwards.
if ((HasOnBuyAttemptForward || HasOnBuyForward) && command && *command)
{
int itemId = 0;
int itemId = CSI_NONE;
// Handling buy via menu.
if (!strcmp(command, "menuselect"))
if (!strcmp(command, "menuselect"))
{
int slot = atoi(CMD_ARGV(1));
if (slot > 0 && slot < 9)
{
static const int menuItemsTe[][9] =
static const int menuItemsTe[][9] =
{
/* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIAMMO, CSI_SECAMMO, 0 },
/* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_ELITE, 0, 0, 0 },
@ -118,7 +129,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
/* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, 0, 0 }
};
static const int menuItemsCt[][9] =
static const int menuItemsCt[][9] =
{
/* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIAMMO, CSI_SECAMMO, 0 },
/* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_FIVESEVEN, 0, 0, 0 },
@ -126,7 +137,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
/* Menu_BuyMachineGun */ { 0, CSI_M249, 0, 0, 0, 0, 0, 0, 0 },
/* Menu_BuyShotgun */ { 0, CSI_M3, CSI_XM1014, 0, 0, 0, 0, 0, 0 },
/* Menu_BuySubMachineGun */ { 0, CSI_TMP, CSI_MP5NAVY, CSI_UMP45, CSI_P90, 0, 0, 0, 0 },
/* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELDGUN }
/* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELD }
};
int menuId = get_pdata<int>(pEdict, MenuDesc.fieldOffset);
@ -148,39 +159,40 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
}
else // Handling buy via alias
{
if (ItemAliasList.retrieve(command, &itemId))
if (get_pdata<CUnifiedSignals>(pEdict, SignalsDesc.fieldOffset).GetState() & SIGNAL_BUY) // Are we inside the buy zone?
{
CurrentItemId = 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;
}
if (HasOnBuyAttemptForward && CurrentItemId && MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuyAttempt, client, CurrentItemId) > 0)
{
return;
}
TriggeredFromCommand = CurrentItemId != CSI_NONE;
DETOUR_STATIC_CALL(C_ClientCommand)(pEdict);
TriggeredFromCommand = BlockMoneyUpdate = BlockAmmosUpdate = false;
}
edict_s* OnCreateNamedEntity(int classname)
{
if (NoKifesMode)
if (NoKnivesMode)
{
if (!strcmp(STRING(classname), "weapon_knife"))
{
@ -192,12 +204,12 @@ edict_s* OnCreateNamedEntity(int classname)
g_pengfuncsTable->pfnCreateNamedEntity = nullptr;
}
RETURN_META_VALUE(MRES_IGNORED, 0);
RETURN_META_VALUE(MRES_IGNORED, nullptr);
}
DETOUR_DECL_MEMBER0(GiveDefaultItems, void) // void CBasePlayer::GiveDefaultItems(void)
{
if (NoKifesMode)
if (NoKnivesMode)
{
g_pengfuncsTable->pfnCreateNamedEntity = OnCreateNamedEntity;
}
@ -207,65 +219,143 @@ DETOUR_DECL_MEMBER0(GiveDefaultItems, void) // void CBasePlayer::GiveDefaultIte
g_pengfuncsTable->pfnCreateNamedEntity = nullptr;
}
DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlayer::GiveNamedItem(const char *pszName)
DETOUR_DECL_MEMBER1(CanPlayerBuy, bool, bool, display) // bool CBasePlayer::CanPlayerBuy(bool display)
{
// If the current item id is not null, this means player has triggers a buy command.
if (CurrentItemId)
{
int client = TypeConversion.cbase_to_id(this);
auto canBuy = DETOUR_MEMBER_CALL(CanPlayerBuy)(display);
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), static_cast<cell>(CurrentItemId)) > 0)
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:
{
return;
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;
}
}
// From here, forward is not blocked, resetting this
// to ignore code in AddAccount which is called right after.
CurrentItemId = 0;
if (allowedToBuy && MF_ExecuteForward(ForwardOnBuy, playerId, CurrentItemId) > 0)
{
canBuy = false;
}
// Give me my item!
DETOUR_MEMBER_CALL(GiveNamedItem)(pszName);
return canBuy;
}
DETOUR_DECL_MEMBER1(GiveShield, void, bool, bRetire) // void CBasePlayer::GiveShield(bool bRetire)
DETOUR_DECL_STATIC2(CanBuyThis, bool, void*, pvPlayer, int, weaponId) // bool CanBuyThis(CBasePlayer *pPlayer, int weaponId)
{
// Special case for shield. Game doesn't use GiveNamedItem() to give a shield.
if (CurrentItemId == CSI_SHIELDGUN)
{
int client = TypeConversion.cbase_to_id(this);
auto canBuy = DETOUR_STATIC_CALL(CanBuyThis)(pvPlayer, weaponId);
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_SHIELDGUN) > 0)
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)
{
return;
canBuy = false;
}
}
// From here, forward is not blocked, resetting this
// to ignore code in AddAccount which is called right after.
CurrentItemId = 0;
return canBuy;
}
// Give me my shield!
DETOUR_MEMBER_CALL(GiveShield)(bRetire);
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)
{
switch (CurrentItemId)
{
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_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void CBasePlayer::AddAccount(int amount, bool bTrackChange)
{
// No buy command or forward not blocked.
// Resuming game flow.
if (!CurrentItemId)
if (BlockMoneyUpdate)
{
DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
}
// Shield is blocked.
// We need to hook EmitSound to block pickup sound played right after.
else if (CurrentItemId == CSI_SHIELDGUN)
{
g_pengfuncsTable->pfnEmitSound = OnEmitSound;
BlockMoneyUpdate = false;
return;
}
// Let's reset this right away to avoid issues.
CurrentItemId = 0;
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;
}
}
@ -273,116 +363,55 @@ 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();
}
ItemAliasList.clear();
DestroyDetour(ClientCommandDetour);
}
}
void ToggleDetour_ClientCommands(bool enable)
{
if (ClientCommandDetour)
{
(enable) ? ClientCommandDetour->EnableDetour() : ClientCommandDetour->DisableDetour();
}
if (enable)
{
// Build the item alias list.
// Used in ClientCommand to check and get fastly item id from alias name.
typedef struct
{
const char *alias;
int id;
} itemBuyAliasInfo;
itemBuyAliasInfo aliasToId[] =
{
{ "p228" , CSI_P228 }, { "228compact" , CSI_P228 },
{ "scout" , CSI_SCOUT }, { "hegren" , CSI_HEGRENADE },
{ "xm1014" , CSI_XM1014 }, { "autoshotgun", CSI_XM1014 },
{ "mac10" , CSI_MAC10 }, { "aug" , CSI_AUG },
{ "bullpup" , CSI_AUG }, { "sgren" , CSI_SMOKEGRENADE },
{ "elites" , CSI_ELITE }, { "fn57" , CSI_FIVESEVEN },
{ "fiveseven" , CSI_FIVESEVEN }, { "ump45" , CSI_UMP45 },
{ "sg550" , CSI_SG550 }, { "krieg550" , CSI_SG550 },
{ "galil" , CSI_GALIL }, { "defender" , CSI_GALIL },
{ "famas" , CSI_FAMAS }, { "clarion" , CSI_FAMAS },
{ "usp" , CSI_USP }, { "km45" , CSI_USP },
{ "glock" , CSI_GLOCK18 }, { "9x19mm" , CSI_GLOCK18 },
{ "awp" , CSI_AWP }, { "magnum" , CSI_AWP },
{ "mp5" , CSI_MP5NAVY }, { "smg" , CSI_MP5NAVY },
{ "m249" , CSI_M249 }, { "m3" , CSI_M3 },
{ "12gauge" , CSI_M3 }, { "m4a1" , CSI_M4A1 },
{ "tmp" , CSI_TMP }, { "mp" , CSI_TMP },
{ "g3sg1" , CSI_G3SG1 }, { "d3au1" , CSI_G3SG1 },
{ "flash" , CSI_FLASHBANG }, { "deagle" , CSI_DEAGLE },
{ "nighthawk" , CSI_DEAGLE }, { "sg552" , CSI_SG552 },
{ "krieg552" , CSI_SG552 }, { "ak47" , CSI_AK47 },
{ "cv47" , CSI_AK47 }, { "p90" , CSI_P90 },
{ "c90" , CSI_P90 }, { "vest" , CSI_VEST },
{ "vesthelm" , CSI_VESTHELM }, { "defuser" , CSI_DEFUSER },
{ "nvgs" , CSI_NVGS }, { "shield" , CSI_SHIELDGUN },
{ "buyammo1" , CSI_PRIAMMO }, { "primammo" , CSI_PRIAMMO },
{ "buyammo2" , CSI_SECAMMO }, { "secammo" , CSI_SECAMMO },
{ nullptr , 0 }
};
for (size_t i = 0; aliasToId[i].alias != nullptr; ++i)
{
ItemAliasList.insert(aliasToId[i].alias, aliasToId[i].id);
}
}
else
{
ItemAliasList.clear();
}
ToggleDetour(ClientCommandDetour, enable);
}
@ -392,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))
@ -406,12 +435,22 @@ 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)
@ -424,74 +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();
}
ItemAliasList.clear();
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 (!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 (MainConfig->GetMemSig("GiveDefaultItems", &address))
{
GiveDefaultItemsDetour = DETOUR_CREATE_MEMBER_FIXED(GiveDefaultItems, address);
@ -504,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);
}
}
@ -515,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)
@ -550,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

@ -18,10 +18,18 @@
#include <IGameConfigs.h>
#include <CDetour/detours.h>
#include <engine_strucs.h>
#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);
@ -34,18 +42,36 @@ 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);
extern CreateNamedEntityFunc CS_CreateNamedEntity;
extern UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString;
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

@ -0,0 +1,277 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//
// Counter-Strike Module
//
#include "CstrikeItemsInfos.h"
#include "CstrikeHacks.h"
CsItemInfo ItemsManager;
char WeaponNameList[MAX_WEAPONS][64];
#define PSTATE_ALIASES_TYPE 0
#define PSTATE_ALIASES_ALIAS 1
#define PSTATE_ALIASES_ALIAS_DEFS 2
CsItemInfo::CsItemInfo()
:
m_ParseState(PSTATE_ALIASES_TYPE),
m_List(nullptr),
m_ListsRetrievedFromConfig(false)
{}
CsItemInfo::~CsItemInfo()
{
Clear();
}
void CsItemInfo::Clear()
{
m_CommonAliasesList.clear();
m_WeaponAliasesList.clear();
m_BuyAliasesList.clear();
}
bool CsItemInfo::HasConfigError()
{
return !m_ListsRetrievedFromConfig;
}
SMCResult CsItemInfo::ReadSMC_NewSection(const SMCStates *states, const char *name)
{
switch (m_ParseState)
{
case PSTATE_ALIASES_TYPE:
{
m_List = nullptr;
if (!strcmp(name, "CommonAlias"))
{
m_List = &m_CommonAliasesList;
}
else if (!strcmp(name, "WeaponAlias"))
{
m_List = &m_WeaponAliasesList;
}
else if (!strcmp(name, "BuyAlias") || !strcmp(name, "BuyEquipAlias") || !strcmp(name, "BuyAmmoAlias"))
{
m_List = &m_BuyAliasesList;
}
if (m_List)
{
m_ParseState = PSTATE_ALIASES_ALIAS;
}
break;
}
case PSTATE_ALIASES_ALIAS:
{
m_AliasInfo.clear();
m_Alias = name;
m_ParseState = PSTATE_ALIASES_ALIAS_DEFS;
break;
}
}
return SMCResult_Continue;
}
SMCResult CsItemInfo::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{
switch (m_ParseState)
{
case PSTATE_ALIASES_ALIAS_DEFS:
{
if (!strcmp(key, "itemid"))
{
m_AliasInfo.itemid = atoi(value);
if (m_AliasInfo.itemid < CSI_NONE || m_AliasInfo.itemid >= CSI_MAX_COUNT)
{
m_AliasInfo.itemid = CSI_NONE;
}
}
else if (!strcmp(key, "classid"))
{
m_AliasInfo.classid = atoi(value);
if (m_AliasInfo.classid < CS_WEAPONCLASS_NONE || m_AliasInfo.classid >= CS_WEAPONCLASS_MAX_COUNT)
{
m_AliasInfo.classid = CS_WEAPONCLASS_NONE;
}
}
else if (!strcmp(key, "classname"))
{
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;
}
}
return SMCResult_Continue;
}
SMCResult CsItemInfo::ReadSMC_LeavingSection(const SMCStates *states)
{
switch (m_ParseState)
{
case PSTATE_ALIASES_ALIAS:
{
m_ParseState = PSTATE_ALIASES_TYPE;
break;
}
case PSTATE_ALIASES_ALIAS_DEFS:
{
m_List->replace(m_Alias.chars(), m_AliasInfo);
m_WeaponIdToClass[m_AliasInfo.itemid] = static_cast<CsWeaponClassType>(m_AliasInfo.classid);
m_AliasInfo.clear();
m_ParseState = PSTATE_ALIASES_ALIAS;
break;
}
}
return SMCResult_Continue;
}
void CsItemInfo::ReadSMC_ParseEnd(bool halted, bool failed)
{
if (!halted && !failed)
{
m_ListsRetrievedFromConfig = true;
}
}
bool CsItemInfo::GetAliasInfos(const char *alias, AliasInfo *info)
{
if (GetAliasInfosFromBuy(alias, info) || m_WeaponAliasesList.retrieve(alias, info))
{
return true;
}
return false;
}
bool CsItemInfo::GetAliasInfosFromBuy(const char *alias, AliasInfo *info)
{
if (m_CommonAliasesList.retrieve(alias, info) || m_BuyAliasesList.retrieve(alias, info))
{
return true;
}
return false;
}
bool CsItemInfo::GetAliasInfosFromName(const char *name, AliasInfo *info)
{
static const char prefix_weapon[] = "weapon_";
static const char prefix_item[] = "item_";
const char *alias = name;
if (strstr(name, prefix_weapon) && strcmp(name + sizeof(prefix_weapon) - 1, "shield"))
{
for (size_t id = 0; id < ARRAYSIZE(WeaponNameList); ++id)
{
if (!strcmp(name, WeaponNameList[id]))
{
info->classname = name;
info->itemid = id;
info->classid = WeaponIdToClass(id);
return true;
}
}
alias = name + sizeof(prefix_weapon) - 1;
}
else if (strstr(name, prefix_item))
{
for (auto iter = m_BuyAliasesList.iter(); !iter.empty(); iter.next())
{
if (iter->value.classname.length() && !iter->value.classname.compare(name))
{
*info = iter->value;
return true;
}
}
alias = name + sizeof(prefix_item) - 1;
}
if (GetAliasInfos(alias, info))
{
return true;
}
return false;
}
CsWeaponClassType CsItemInfo::WeaponIdToClass(int id)
{
if ((id > CSI_NONE && id <= CSI_P90) || id == CSI_SHIELD || id == CSI_SHIELDGUN)
{
if (id == CSI_SHIELDGUN)
{
id = CSI_SHIELD;
}
return m_WeaponIdToClass[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

@ -0,0 +1,106 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//
// Counter-Strike Module
//
#ifndef _CSTRIKE_WEAPONS_INFOS_H_
#define _CSTRIKE_WEAPONS_INFOS_H_
#include <amxxmodule.h>
#include "CstrikeDatas.h"
#include <ITextParsers.h>
#include <amtl/am-string.h>
#include <sm_stringhashmap.h>
struct AliasInfo
{
AliasInfo()
{
clear();
}
void clear()
{
itemid = CSI_NONE;
classid = CS_WEAPONCLASS_NONE;
}
int itemid;
int classid;
ke::AString classname;
};
enum class Equipments
{
None,
Vest,
Vesthelm,
Flashbang,
HEGrenade,
SmokeGrenade,
Nvg,
Defuser,
Count
};
class CsItemInfo : public ITextListener_SMC
{
public:
CsItemInfo();
virtual ~CsItemInfo();
public:
void Clear();
bool HasConfigError();
public:
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name) override;
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) override;
SMCResult ReadSMC_LeavingSection(const SMCStates *states) override;
void ReadSMC_ParseEnd(bool halted, bool failed) override;
public:
bool GetAliasInfos(const char *alias, AliasInfo *info);
bool GetAliasInfosFromBuy(const char *alias, AliasInfo *info);
bool GetAliasInfosFromName(const char *classname, AliasInfo *info);
CsWeaponClassType WeaponIdToClass(int id);
int GetItemPrice(int id);
private: // Retrieved datas
typedef StringHashMap<AliasInfo> AliasMap;
AliasMap m_CommonAliasesList;
AliasMap m_WeaponAliasesList;
AliasMap m_BuyAliasesList;
CsWeaponClassType m_WeaponIdToClass[CSI_MAX_COUNT];
private: // Config parsing
int m_ParseState;
AliasMap* m_List;
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;
@ -38,18 +40,18 @@ void OnAmxxAttach()
ConfigManager = MF_GetConfigManager();
char error[256];
error[0] = '\0';
char error[256] = "";
ConfigManager->AddUserConfigHook("ItemInfos", &ItemsManager);
if (!ConfigManager->LoadGameConfigFile("modules.games", &MainConfig, error, sizeof(error)) && error[0] != '\0')
if (!ConfigManager->LoadGameConfigFile("modules.games", &MainConfig, error, sizeof(error)) && *error)
{
MF_Log("Could not read module.games gamedata: %s", error);
return;
}
error[0] = '\0';
*error = '\0';
if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof(error)) && error[0] != '\0')
if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof(error)) && *error)
{
MF_Log("Could not read common.games gamedata: %s", error);
return;
@ -60,31 +62,57 @@ 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;
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)
{
// Used to catch WeaponList message at map change.
EnableMessageHooks();
}
void OnServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
{
DisableMessageHooks();
}
void OnPluginsUnloaded()
{
// 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("ItemInfos", &ItemsManager);
ConfigManager->CloseGameConfigFile(MainConfig);
ConfigManager->CloseGameConfigFile(CommonConfig);

View File

@ -16,10 +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;
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)
@ -257,7 +258,7 @@ static cell AMX_NATIVE_CALL cs_set_weapon_silenced(AMX *amx, cell *params)
GET_OFFSET("CBasePlayerWeapon", m_flNextPrimaryAttack);
char animExt[12];
float time;
float time = 0.0f;
switch (weaponType)
{
@ -405,7 +406,7 @@ static cell AMX_NATIVE_CALL cs_set_user_armor(AMX *amx, cell *params)
pPlayer->v.armorvalue = armor;
set_pdata<int>(pPlayer, m_iKevlar, type);
if (type == CS_ARMOR_KEVLAR || type == CS_ARMOR_ASSAULTSUIT)
{
MESSAGE_BEGIN(MSG_ONE, MessageIdArmorType, nullptr, pPlayer);
@ -488,7 +489,7 @@ static cell AMX_NATIVE_CALL cs_set_user_vip(AMX *amx, cell *params)
WRITE_BYTE(index);
WRITE_BYTE(scoreattrib);
MESSAGE_END();
}
}
return 1;
}
@ -500,7 +501,7 @@ static cell AMX_NATIVE_CALL cs_get_user_team(AMX *amx, cell *params)
GET_OFFSET("CBasePlayer", m_iTeam);
int index = params[1];
CHECK_PLAYER(index);
edict_t *pPlayer = MF_GetPlayerEdict(index);
@ -537,7 +538,7 @@ static cell AMX_NATIVE_CALL cs_set_user_team(AMX *amx, cell *params)
{
Players[index].ResetModel(pPlayer);
}
bool sendTeamInfo = true;
if (*params / sizeof(cell) >= 4)
@ -578,7 +579,7 @@ static cell AMX_NATIVE_CALL cs_get_user_inside_buyzone(AMX *amx, cell *params)
CHECK_PLAYER(index);
edict_t *pPlayer = MF_GetPlayerEdict(index);
if (get_pdata<CUnifiedSignals>(pPlayer, m_signals).GetState() & SIGNAL_BUY)
{
return 1;
@ -634,7 +635,7 @@ static cell AMX_NATIVE_CALL cs_set_user_plant(AMX *amx, cell *params)
if (plant)
{
if (icon)
if (icon)
{
MESSAGE_BEGIN(MSG_ONE, MessageIdStatusIcon, nullptr, pPlayer);
WRITE_BYTE(1);
@ -645,7 +646,7 @@ static cell AMX_NATIVE_CALL cs_set_user_plant(AMX *amx, cell *params)
MESSAGE_END();
}
}
else
else
{
MESSAGE_BEGIN(MSG_ONE, MessageIdStatusIcon, nullptr, pPlayer);
WRITE_BYTE(0);
@ -684,14 +685,14 @@ static cell AMX_NATIVE_CALL cs_set_user_defusekit(AMX *amx, cell *params)
CHECK_PLAYER(index);
edict_t *pPlayer = MF_GetPlayerEdict(index);
set_pdata<bool>(pPlayer, m_bHasDefuser, kit);
pPlayer->v.body = kit ? 1 : 0;
if (kit)
{
int colour[3] = {DEFUSER_COLOUR_R, DEFUSER_COLOUR_G, DEFUSER_COLOUR_B};
for (int i = 0; i < 3; i++)
{
if (params[i + 3] != -1)
@ -707,7 +708,7 @@ static cell AMX_NATIVE_CALL cs_set_user_defusekit(AMX *amx, cell *params)
int length;
icon = MF_GetAmxString(amx, params[6], 1, &length);
}
MESSAGE_BEGIN(MSG_ONE, MessageIdStatusIcon, nullptr, pPlayer);
WRITE_BYTE(params[7] == 1 ? 2 : 1);
WRITE_STRING(icon);
@ -716,7 +717,7 @@ static cell AMX_NATIVE_CALL cs_set_user_defusekit(AMX *amx, cell *params)
WRITE_BYTE(colour[2]);
MESSAGE_END();
}
else
else
{
MESSAGE_BEGIN(MSG_ONE, MessageIdStatusIcon, nullptr, pPlayer);
WRITE_BYTE(0);
@ -762,7 +763,7 @@ static cell AMX_NATIVE_CALL cs_get_user_backpackammo(AMX *amx, cell *params)
pItem = get_pdata<uintptr_t*>(pItem, m_pNext);
}
}
return 0;
}
@ -803,7 +804,7 @@ static cell AMX_NATIVE_CALL cs_set_user_backpackammo(AMX *amx, cell *params)
pItem = get_pdata<uintptr_t*>(pItem, m_pNext);
}
}
return 0;
}
@ -868,7 +869,7 @@ static cell AMX_NATIVE_CALL cs_set_user_model(AMX *amx, cell *params)
CHECK_PLAYER(index);
edict_t *pPlayer = MF_GetPlayerEdict(index);
if (model == -1)
if (model == -1)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid model %d", params[2]);
return 0;
@ -1072,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);
@ -1080,13 +1081,13 @@ static cell AMX_NATIVE_CALL cs_set_no_knives(AMX *amx, cell *params)
{
if (!GiveDefaultItemsDetour)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_set_no_knives() is disabled");
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_set_no_knives() is disabled. Check your amxx logs.");
return 0;
}
NoKifesMode = params[1] != 0;
NoKnivesMode = params[1] != 0;
if (NoKifesMode)
if (NoKnivesMode)
{
GiveDefaultItemsDetour->EnableDetour();
}
@ -1100,7 +1101,7 @@ static cell AMX_NATIVE_CALL cs_set_no_knives(AMX *amx, cell *params)
// native cs_get_user_tked(index);
static cell AMX_NATIVE_CALL cs_get_user_tked(AMX *amx, cell *params)
{
{
GET_OFFSET("CBasePlayer", m_bJustKilledTeammate);
int index = params[1];
@ -1118,7 +1119,7 @@ static cell AMX_NATIVE_CALL cs_get_user_tked(AMX *amx, cell *params)
// native cs_set_user_tked(index, tk = 1, subtract = 1);
static cell AMX_NATIVE_CALL cs_set_user_tked(AMX *amx, cell *params)
{
{
GET_OFFSET("CBasePlayer", m_bJustKilledTeammate);
GET_OFFSET("CBasePlayer", m_iTeam);
GET_OFFSET("CBasePlayer", m_iDeaths);
@ -1133,7 +1134,7 @@ static cell AMX_NATIVE_CALL cs_set_user_tked(AMX *amx, cell *params)
set_pdata<bool>(pPlayer, m_bJustKilledTeammate, tk != 0);
if (subtract > 0)
{
{
pPlayer->v.frags -= subtract;
MESSAGE_BEGIN(MSG_ALL, MessageIdScoreInfo);
@ -1142,15 +1143,15 @@ static cell AMX_NATIVE_CALL cs_set_user_tked(AMX *amx, cell *params)
WRITE_SHORT(get_pdata<int>(pPlayer, m_iDeaths));
WRITE_SHORT(0);
WRITE_SHORT(get_pdata<int>(pPlayer, m_iTeam));
MESSAGE_END();
}
MESSAGE_END();
}
return 1;
return 1;
}
// native cs_get_user_driving(index);
static cell AMX_NATIVE_CALL cs_get_user_driving(AMX *amx, cell *params)
{
{
GET_OFFSET("CBasePlayer", m_iTrain);
int index = params[1];
@ -1162,8 +1163,8 @@ static cell AMX_NATIVE_CALL cs_get_user_driving(AMX *amx, cell *params)
}
// native cs_get_user_stationary(index);
static cell AMX_NATIVE_CALL cs_get_user_stationary(AMX *amx, cell *params)
{
static cell AMX_NATIVE_CALL cs_get_user_stationary(AMX *amx, cell *params)
{
GET_OFFSET("CBasePlayer", m_iClientHideHUD);
int index = params[1];
@ -1183,13 +1184,13 @@ static cell AMX_NATIVE_CALL cs_get_user_shield(AMX *amx, cell *params)
CHECK_PLAYER(index);
edict_t *pPlayer = MF_GetPlayerEdict(index);
if (get_pdata<bool>(pPlayer, m_bOwnsShield))
{
return 1;
}
return 0;
return 0;
}
// native cs_user_spawn(player);
@ -1203,7 +1204,7 @@ static cell AMX_NATIVE_CALL cs_user_spawn(AMX *amx, cell *params)
pPlayer->v.deadflag = DEAD_RESPAWNABLE;
MDLL_Think(pPlayer);
if (MF_IsPlayerBot(index) && pPlayer->v.deadflag == DEAD_RESPAWNABLE)
if (MF_IsPlayerBot(index) && pPlayer->v.deadflag == DEAD_RESPAWNABLE)
{
MDLL_Spawn(pPlayer);
}
@ -1221,7 +1222,7 @@ static cell AMX_NATIVE_CALL cs_get_armoury_type(AMX *amx, cell *params)
CHECK_NONPLAYER(index);
edict_t *pArmoury = INDEXENT(index);
if (strcmp(STRING(pArmoury->v.classname), "armoury_entity"))
if (strcmp(STRING(pArmoury->v.classname), "armoury_entity"))
{
MF_LogError(amx, AMX_ERR_NATIVE, "Not an armoury_entity! (%d)", index);
return 0;
@ -1230,7 +1231,7 @@ static cell AMX_NATIVE_CALL cs_get_armoury_type(AMX *amx, cell *params)
int weapontype = get_pdata<int>(pArmoury, m_iItem);;
int weapontype_out = 0;
switch (weapontype)
switch (weapontype)
{
case CSA_MP5NAVY: weapontype_out = CSW_MP5NAVY; break;
case CSA_TMP: weapontype_out = CSW_TMP; break;
@ -1265,7 +1266,7 @@ static cell AMX_NATIVE_CALL cs_get_armoury_type(AMX *amx, cell *params)
*MF_GetAmxAddr(amx, params[2]) = get_pdata<int>(pArmoury, m_iCount);
}
return weapontype_out;
return weapontype_out;
}
// native cs_set_armoury_type(index, type, count = -1);
@ -1356,8 +1357,14 @@ static cell AMX_NATIVE_CALL cs_set_user_zoom(AMX *amx, cell *params)
int type = params[2];
int mode = params[3];
int weapon = *static_cast<int *>(MF_PlayerPropAddr(index, Player_CurrentWeapon));
Players[index].ResetZoom();
CPlayer& player = Players[index];
if (player.GetZoom())
{
DisableMessageHooks();
player.ResetZoom();
}
if (type == CS_RESET_ZOOM)
{
@ -1405,7 +1412,7 @@ static cell AMX_NATIVE_CALL cs_set_user_zoom(AMX *amx, cell *params)
if (!mode)
{
Players[index].SetZoom(value);
player.SetZoom(value);
EnableMessageHooks();
}
@ -1481,7 +1488,7 @@ static cell AMX_NATIVE_CALL cs_get_user_lastactivity(AMX *amx, cell *params)
CHECK_PLAYER(index);
edict_t *pPlayer = MF_GetPlayerEdict(index);
return amx_ftoc(get_pdata<float>(pPlayer, m_fLastMovement));
}
@ -1494,7 +1501,7 @@ static cell AMX_NATIVE_CALL cs_set_user_lastactivity(AMX *amx, cell *params)
CHECK_PLAYER(index);
edict_t *pPlayer = MF_GetPlayerEdict(index);
set_pdata<float>(pPlayer, m_fLastMovement, amx_ctof(params[2]));
return 1;
@ -1535,12 +1542,12 @@ static cell AMX_NATIVE_CALL cs_get_hostage_lastuse(AMX *amx, cell *params)
GET_OFFSET("CHostage", m_improv);
int index = params[1];
CHECK_NONPLAYER(index);
edict_t *pHostage = INDEXENT(index);
CHECK_HOSTAGE(pHostage);
void *pImprov = get_pdata<void*>(pHostage, m_improv);
if (pImprov) // Specific to CZ
@ -1566,7 +1573,7 @@ static cell AMX_NATIVE_CALL cs_set_hostage_lastuse(AMX *amx, cell *params)
edict_t *pHostage = INDEXENT(index);
CHECK_HOSTAGE(pHostage);
void *pImprov = get_pdata<void*>(pHostage, m_improv);
if (pImprov) // Specific to CZ
@ -1593,7 +1600,7 @@ static cell AMX_NATIVE_CALL cs_get_hostage_nextuse(AMX* amx, cell* params)
edict_t *pHostage = INDEXENT(index);
CHECK_HOSTAGE(pHostage);
return amx_ftoc(get_pdata<float>(pHostage, m_flNextChange));
}
@ -1699,7 +1706,7 @@ static cell AMX_NATIVE_CALL cs_create_entity(AMX* amx, cell* params)
{
if (CS_CreateNamedEntity <= 0)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_create_entity() is disabled");
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_create_entity() is disabled. Check your amxx logs.");
return 0;
}
@ -1721,7 +1728,7 @@ static cell AMX_NATIVE_CALL cs_find_ent_by_class(AMX* amx, cell* params)
{
if (CS_UTIL_FindEntityByString <= 0)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_find_ent_by_class() is disabled");
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_find_ent_by_class() is disabled. Check your amxx logs.");
return 0;
}
@ -1739,7 +1746,165 @@ static cell AMX_NATIVE_CALL cs_find_ent_by_class(AMX* amx, cell* params)
return 0;
}
AMX_NATIVE_INFO CstrikeNatives[] =
// cs_find_ent_by_owner(start_index, const classname[], owner)
static cell AMX_NATIVE_CALL cs_find_ent_by_owner(AMX* amx, cell* params)
{
if (CS_UTIL_FindEntityByString <= 0)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_find_ent_by_owner() is disabled. Check your amxx logs.");
return 0;
}
int owner = params[3];
CHECK_ENTITY_SIMPLE(owner);
int length;
void* pEntity = TypeConversion.id_to_cbase(params[1]);
const char* value = MF_GetAmxString(amx, params[2], 0, &length);
edict_t *pOwner = TypeConversion.id_to_edict(owner);
while ((pEntity = CS_UTIL_FindEntityByString(pEntity, "classname", value)))
{
edict_t *pev = TypeConversion.cbase_to_edict(pEntity);
if (!FNullEnt(pev) && pev->v.owner == pOwner)
{
int index = TypeConversion.edict_to_id(pev);
if (index != -1)
{
return index;
}
}
}
return 0;
}
// native any:cs_get_item_id(const name[], &CsWeaponClassType:classid = CS_WEAPONCLASS_NONE);
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 because of corrupted or missing gamedata");
return 0;
}
int length;
char *name = MF_GetAmxString(amx, params[1], 0, &length);
cell *classid = MF_GetAmxAddr(amx, params[2]);
if (length)
{
AliasInfo info;
if (ItemsManager.GetAliasInfosFromName(name, &info))
{
*classid = info.classid;
return info.itemid;
}
}
return CSI_NONE;
}
// native bool:cs_get_translated_item_alias(const alias[], itemname[], maxlength);
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 corrupted or missing gamedata");
return 0;
}
int length;
const char *alias = MF_GetAmxString(amx, params[1], 0, &length);
const char *name = alias;
AliasInfo info;
if (length && ItemsManager.GetAliasInfos(alias, &info) && info.itemid != CSI_NONE)
{
switch (info.itemid)
{
case CSI_VEST:
case CSI_VESTHELM:
case CSI_DEFUSER:
case CSI_SHIELD:
{
// Special item_* defined in gamdata file as game
// doesn't give us really a way to know about their classname
// and I don't want to hard code them in module.
name = info.classname.chars();
break;
}
default:
{
// weapon_* retrieved from WeaponList messages at map change.
name = WeaponNameList[info.itemid];
break;
}
}
}
MF_SetAmxString(amx, params[2], alias, params[3]);
return info.itemid != CSI_NONE;
}
// native cs_get_weapon_info(weapon_id, CsWeaponInfo:type);
static cell AMX_NATIVE_CALL cs_get_weapon_info(AMX* amx, cell* params)
{
if (GetWeaponInfo <= 0)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_weapon_info() is disabled. Check your amxx logs.");
return 0;
}
int weapon_id = params[1];
if (weapon_id <= CSW_NONE || weapon_id == CSW_C4 || weapon_id == CSW_KNIFE || weapon_id > CSW_LAST_WEAPON)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid weapon id: %d", weapon_id);
return 0;
}
int info_type = params[2];
switch (info_type)
{
case CS_WEAPONINFO_COST:
{
return GetWeaponInfo(weapon_id)->cost;
}
case CS_WEAPONINFO_CLIP_COST:
{
return GetWeaponInfo(weapon_id)->clipCost;
}
case CS_WEAPONINFO_BUY_CLIP_SIZE:
{
return GetWeaponInfo(weapon_id)->buyClipSize;
}
case CS_WEAPONINFO_GUN_CLIP_SIZE:
{
return GetWeaponInfo(weapon_id)->gunClipSize;
}
case CS_WEAPONINFO_MAX_ROUNDS:
{
return GetWeaponInfo(weapon_id)->maxRounds;
}
case CS_WEAPONINFO_AMMO_TYPE:
{
return GetWeaponInfo(weapon_id)->ammoType;
}
}
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid info type: %d", info_type);
return 0;
}
AMX_NATIVE_INFO CstrikeNatives[] =
{
{"cs_set_user_money", cs_set_user_money},
{"cs_get_user_money", cs_get_user_money},
@ -1801,8 +1966,11 @@ AMX_NATIVE_INFO CstrikeNatives[] =
{"cs_set_c4_explode_time", cs_set_c4_explode_time},
{"cs_get_c4_defusing", cs_get_c4_defusing},
{"cs_set_c4_defusing", cs_set_c4_defusing},
{"cs_create_entity", cs_create_entity },
{"cs_find_ent_by_class", cs_find_ent_by_class},
{"cs_create_entity", cs_create_entity },
{"cs_find_ent_by_class", cs_find_ent_by_class},
{"cs_find_ent_by_owner", cs_find_ent_by_owner},
{"cs_get_item_id", cs_get_item_id},
{"cs_get_translated_item_alias",cs_get_translated_item_alias},
{"cs_get_weapon_info", cs_get_weapon_info},
{nullptr, nullptr}
};

View File

@ -11,16 +11,22 @@
// Counter-Strike Module
//
#include <amxxmodule.h>
#include "CstrikeUserMessages.h"
#include "CstrikeUtils.h"
#include "CstrikeHacks.h"
#include "CstrikePlayer.h"
#include "CstrikeItemsInfos.h"
#include <amtl/am-string.h>
bool ShouldBlock;
bool ShouldBlockHLTV;
bool ShouldDisableHooks;
bool RetrieveWeaponName;
ke::AString CurrentWeaponName;
int ArgPosition;
int MessageIdArmorType;
int MessageIdItemStatus;
int MessageIdHLTV;
int MessageIdMoney;
int MessageIdResetHUD;
@ -30,6 +36,10 @@ int MessageIdSetFOV;
int MessageIdStatusIcon;
int MessageIdTeamInfo;
int MessageIdTextMsg;
int MessageIdWeaponList;
extern bool OnMessageStatusIcon(edict_t *pPlayer);
extern bool OnMessageItemStatus(edict_t *pPlayer);
struct UserMsg
{
@ -40,6 +50,7 @@ struct UserMsg
UserMsg MessagesList[] =
{
{ "ArmorType" , &MessageIdArmorType },
{ "ItemStatus" , &MessageIdItemStatus },
{ "HLTV" , &MessageIdHLTV },
{ "Money" , &MessageIdMoney },
{ "ResetHUD" , &MessageIdResetHUD },
@ -49,6 +60,7 @@ UserMsg MessagesList[] =
{ "StatusIcon" , &MessageIdStatusIcon },
{ "TeamInfo" , &MessageIdTeamInfo },
{ "TextMsg" , &MessageIdTextMsg },
{ "WeaponList" , &MessageIdWeaponList },
{ nullptr , nullptr }
};
@ -98,7 +110,10 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
int index = ENTINDEX(pEntity);
if (Players[index].GetZoom())
{
Players[index].ResetZoom();
DisableMessageHooks();
}
}
break;
}
@ -113,6 +128,13 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
}
break;
}
case MSG_INIT:
{
if (msg_type == MessageIdWeaponList)
{
RetrieveWeaponName = true;
}
}
}
if (ShouldBlockHLTV)
@ -123,13 +145,33 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
RETURN_META(MRES_IGNORED);
}
void OnWriteByte(int iValue)
void OnWriteByte(int value)
{
if (ShouldBlock)
if (ShouldBlock)
{
RETURN_META(MRES_SUPERCEDE);
}
if (RetrieveWeaponName && ++ArgPosition == 7 && value >= 0 && value < MAX_WEAPONS)
{
strncopy(WeaponNameList[value], CurrentWeaponName.chars(), sizeof(WeaponNameList[value]));
}
RETURN_META(MRES_IGNORED);
}
void OnWriteString(const char *value)
{
if (ShouldBlock)
{
RETURN_META(MRES_SUPERCEDE);
}
if (RetrieveWeaponName)
{
CurrentWeaponName = value;
}
RETURN_META(MRES_IGNORED);
}
@ -138,18 +180,52 @@ void OnMessageEnd(void)
if (ShouldBlock)
{
ShouldBlock = false;
if (ShouldDisableHooks)
{
ShouldDisableHooks = false;
DisableMessageHooks();
}
RETURN_META(MRES_SUPERCEDE);
}
if (RetrieveWeaponName)
{
RetrieveWeaponName = false;
ArgPosition = 0;
}
RETURN_META(MRES_IGNORED);
}
size_t RefCount;
void EnableMessageHooks()
{
++RefCount;
if (!g_pengfuncsTable->pfnMessageBegin)
{
g_pengfuncsTable->pfnMessageBegin = OnMessageBegin;
g_pengfuncsTable->pfnWriteByte = OnWriteByte;
g_pengfuncsTable->pfnWriteString = OnWriteString;
g_pengfuncsTable->pfnMessageEnd = OnMessageEnd;
}
}
void DisableMessageHooks(bool force)
{
if (force)
{
RefCount = 1;
}
if (--RefCount == 0)
{
g_pengfuncsTable->pfnMessageBegin = nullptr;
g_pengfuncsTable->pfnWriteByte = nullptr;
g_pengfuncsTable->pfnWriteString = nullptr;
g_pengfuncsTable->pfnMessageEnd = nullptr;
}
}

View File

@ -26,5 +26,6 @@ extern int MessageIdTeamInfo;
extern int MessageIdTextMsg;
void EnableMessageHooks();
void DisableMessageHooks(bool force = false);
#endif // CSTRIKE_USER_MESSAGES_H

View File

@ -27,6 +27,17 @@ bool UTIL_CheckForPublic(const char *publicname);
#define GETCLIENTKEYVALUE (*g_engfuncs.pfnInfoKeyValue)
#define CREATENAMEDENTITY (*g_engfuncs.pfnCreateNamedEntity)
#define CHECK_ENTITY_SIMPLE(x) \
if (x < 0 || x > gpGlobals->maxEntities) { \
MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \
return 0; \
} else { \
if (x != 0 && FNullEnt(INDEXENT(x))) { \
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid entity %d", x); \
return 0; \
} \
}
#define CHECK_ENTITY(x) \
if (x < 0 || x > gpGlobals->maxEntities) { \
MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \
@ -99,6 +110,7 @@ bool UTIL_CheckForPublic(const char *publicname);
member = type.fieldOffset; \
}
class CUnifiedSignals
{
public:
@ -109,17 +121,17 @@ class CUnifiedSignals
m_flSignal = 0;
}
void Signal(int flags)
void Signal(int flags)
{
m_flSignal |= flags;
}
int GetSignal(void)
int GetSignal(void)
{
return m_flSignal;
}
int GetState(void)
int GetState(void)
{
return m_flState;
}

View File

@ -80,7 +80,7 @@
//#define FN_AMXX_PLUGINSUNLOADING OnPluginsUnloading
/** All plugins are now unloaded */
//#define FN_AMXX_PLUGINSUNLOADED OnPluginsUnloaded
#define FN_AMXX_PLUGINSUNLOADED OnPluginsUnloaded
/**** METAMOD ****/
@ -123,7 +123,7 @@
// #define FN_ClientPutInServer ClientPutInServer /* pfnClientPutInServer() (wd) Client is entering the game */
// #define FN_ClientCommand ClientCommand /* pfnClientCommand() (wd) Player has sent a command (typed or from a bind) */
// #define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */
// #define FN_ServerActivate ServerActivate /* pfnServerActivate() (wd) Server is starting a new map */
#define FN_ServerActivate OnServerActivate /* pfnServerActivate() (wd) Server is starting a new map */
// #define FN_ServerDeactivate ServerDeactivate /* pfnServerDeactivate() (wd) Server is leaving the map (shutdown or changelevel); SDK2 */
// #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */
// #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */
@ -175,7 +175,7 @@
// #define FN_ClientPutInServer_Post ClientPutInServer_Post
// #define FN_ClientCommand_Post ClientCommand_Post
// #define FN_ClientUserInfoChanged_Post ClientUserInfoChanged_Post
// #define FN_ServerActivate_Post ServerActivate_Post
#define FN_ServerActivate_Post OnServerActivate_Post
// #define FN_ServerDeactivate_Post ServerDeactivate_Post
// #define FN_PlayerPreThink_Post PlayerPreThink_Post
// #define FN_PlayerPostThink_Post PlayerPostThink_Post

View File

@ -151,12 +151,14 @@
<ClCompile Include="..\CstrikeUserMessages.cpp" />
<ClCompile Include="..\CstrikeUtils.cpp" />
<ClCompile Include="..\..\..\..\public\sdk\amxxmodule.cpp" />
<ClCompile Include="..\CstrikeItemsInfos.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\public\memtools\CDetour\asm\asm.h" />
<ClInclude Include="..\..\..\..\public\memtools\CDetour\detourhelpers.h" />
<ClInclude Include="..\..\..\..\public\memtools\CDetour\detours.h" />
<ClInclude Include="..\..\..\..\public\memtools\MemoryUtils.h" />
<ClInclude Include="..\CstrikeItemsInfos.h" />
<ClInclude Include="..\CstrikeDatas.h" />
<ClInclude Include="..\CstrikeHacks.h" />
<ClInclude Include="..\CstrikePlayer.h" />
@ -167,6 +169,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\..\plugins\include\cstrike.inc" />
<None Include="..\..\..\..\plugins\include\cstrike_const.inc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -59,6 +59,9 @@
<ClCompile Include="..\CstrikeMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\CstrikeItemsInfos.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\CstrikePlayer.h">
@ -94,10 +97,16 @@
<ClInclude Include="..\CstrikeUserMessages.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\CstrikeItemsInfos.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\..\plugins\include\cstrike.inc">
<Filter>Pawn Includes</Filter>
</None>
<None Include="..\..\..\..\plugins\include\cstrike_const.inc">
<Filter>Pawn Includes</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -118,43 +118,6 @@ public stock const Float:NULL_VECTOR[3];
#define PLUGIN_HANDLED 1 /* stop other plugins */
#define PLUGIN_HANDLED_MAIN 2 /* to use in client_command(), continue all plugins but stop the command */
/**
* IDs of weapons in CS
*/
#define CSW_P228 1
#define CSW_SCOUT 3
#define CSW_HEGRENADE 4
#define CSW_XM1014 5
#define CSW_C4 6
#define CSW_MAC10 7
#define CSW_AUG 8
#define CSW_SMOKEGRENADE 9
#define CSW_ELITE 10
#define CSW_FIVESEVEN 11
#define CSW_UMP45 12
#define CSW_SG550 13
#define CSW_GALI 14
#define CSW_GALIL 14
#define CSW_FAMAS 15
#define CSW_USP 16
#define CSW_GLOCK18 17
#define CSW_AWP 18
#define CSW_MP5NAVY 19
#define CSW_M249 20
#define CSW_M3 21
#define CSW_M4A1 22
#define CSW_TMP 23
#define CSW_G3SG1 24
#define CSW_FLASHBANG 25
#define CSW_DEAGLE 26
#define CSW_SG552 27
#define CSW_AK47 28
#define CSW_KNIFE 29
#define CSW_P90 30
#define CSW_VEST 31 // Custom
#define CSW_VESTHELM 32 // Custom
#define CSW_SHIELDGUN 99
/**
* HI weapon constants
*/
@ -187,6 +150,7 @@ public stock const Float:NULL_VECTOR[3];
#define HIT_RIGHTARM 5
#define HIT_LEFTLEG 6
#define HIT_RIGHTLEG 7
#define HIT_SHIELD 8 // CS only
/**
* @section emit_sound() constants
@ -485,3 +449,5 @@ enum HashType
Hash_Keccak_384, // Provides Keccak 384 bit hashing
Hash_Keccak_512 // Provides Keccak 512 bit hashing
};
#include <cstrike_const> // To keep backward compatibility

View File

@ -21,121 +21,7 @@
#pragma loadlib cstrike
#endif
/**
* @section Team and team model constants, used by cs_[get|set]_user_team().
*/
/**
* Internal Counter-Strike model id constants.
*
* @note Model ids starting with CZ_ are only valid in Condition Zero.
*/
enum CsInternalModel
{
CS_NORESET = -1,
CS_DONTCHANGE = 0,
CS_CT_URBAN = 1,
CS_T_TERROR = 2,
CS_T_LEET = 3,
CS_T_ARCTIC = 4,
CS_CT_GSG9 = 5,
CS_CT_GIGN = 6,
CS_CT_SAS = 7,
CS_T_GUERILLA = 8,
CS_CT_VIP = 9,
CZ_T_MILITIA = 10,
CZ_CT_SPETSNAZ = 11,
};
/**
* Counter-Strike team id constants.
*/
enum CsTeams
{
CS_TEAM_UNASSIGNED = 0,
CS_TEAM_T = 1,
CS_TEAM_CT = 2,
CS_TEAM_SPECTATOR = 3,
};
/**
* @endsection
*/
/**
* Counter-Strike armor types for use with cs_[get|set]_user_armor().
*/
enum CsArmorType
{
CS_ARMOR_NONE = 0, // no armor
CS_ARMOR_KEVLAR = 1, // body vest only
CS_ARMOR_VESTHELM = 2, // vest and helmet
};
/**
* Map zone flags returned by cs_get_user_mapzones().
*/
#define CS_MAPZONE_BUY (1<<0) // Buyzone
#define CS_MAPZONE_BOMBTARGET (1<<1) // Bomb target zone
#define CS_MAPZONE_HOSTAGE_RESCUE (1<<2) // Hostage rescue zone
#define CS_MAPZONE_ESCAPE (1<<3) // Terrorist escape zone
#define CS_MAPZONE_VIP_SAFETY (1<<4) // VIP escape zone
/**
* Constants used for cs_[get|set]_user_zoom().
*/
enum
{
CS_RESET_ZOOM = 0, // Reset any zoom blocking (mode has no effect)
CS_SET_NO_ZOOM, // Disable any sort of zoom
CS_SET_FIRST_ZOOM, // Set first zoom level (AWP style)
CS_SET_SECOND_ZOOM, // Set second zoom level (AWP style)
CS_SET_AUGSG552_ZOOM, // Set AUG/SG552 zoom style
};
/**
* Constants used for the CS_OnBuy() and CS_OnBuyAttempt() forwards.
*
* @note While these mostly overlap with the CSW_* constants the CSI_* constants
* contain custom AMXX values that do not correspond to any real value in
* the game. The CSI_* constants should therefore be used for consistency.
*/
#define CSI_P228 CSW_P228
#define CSI_SCOUT CSW_SCOUT
#define CSI_HEGRENADE CSW_HEGRENADE
#define CSI_XM1014 CSW_XM1014
#define CSI_C4 CSW_C4
#define CSI_MAC10 CSW_MAC10
#define CSI_AUG CSW_AUG
#define CSI_SMOKEGRENADE CSW_SMOKEGRENADE
#define CSI_ELITE CSW_ELITE
#define CSI_FIVESEVEN CSW_FIVESEVEN
#define CSI_UMP45 CSW_UMP45
#define CSI_SG550 CSW_SG550
#define CSI_GALIL CSW_GALIL
#define CSI_FAMAS CSW_FAMAS
#define CSI_USP CSW_USP
#define CSI_GLOCK18 CSW_GLOCK18
#define CSI_AWP CSW_AWP
#define CSI_MP5NAVY CSW_MP5NAVY
#define CSI_M249 CSW_M249
#define CSI_M3 CSW_M3
#define CSI_M4A1 CSW_M4A1
#define CSI_TMP CSW_TMP
#define CSI_G3SG1 CSW_G3SG1
#define CSI_FLASHBANG CSW_FLASHBANG
#define CSI_DEAGLE CSW_DEAGLE
#define CSI_SG552 CSW_SG552
#define CSI_AK47 CSW_AK47
#define CSI_P90 CSW_P90
#define CSI_SHIELDGUN CSW_SHIELDGUN // The real CS value, use CSI_SHELD instead.
#define CSI_VEST CSW_VEST // Custom
#define CSI_VESTHELM CSW_VESTHELM // Custom
#define CSI_DEFUSER 33 // Custom
#define CSI_NVGS 34 // Custom
#define CSI_PRIAMMO 36 // Custom
#define CSI_SECAMMO 37 // Custom
#define CSI_SHIELD 38 // Custom - The value passed by the forward, more convenient for plugins.
#include <cstrike_const>
/**
* Returns client's deaths.
@ -1139,6 +1025,157 @@ native cs_create_entity(const classname[]);
*/
native cs_find_ent_by_class(start_index, const classname[]);
/**
* Finds an entity in the world using Counter-Strike's custom FindEntityByString
* wrapper, matching by owner.
*
* @note Unlike other mods CS keeps track of entities using a custom hashtable.
* This function utilizes the hasthable and allows for considerably faster
* classname lookup compared to the default FindEntityByString (used by
* find_ent_by_owner() for example).
* @note This exclusively considers entities in the hashtable, created by the
* game itself or using cs_create_entity().
*
* @param start_index Entity index to start searching from. -1 to start from
* the first entity
* @param classname Classname to search for
* @param owner Entity index to search for entity's owner
*
* @return Entity index > 0 if found, 0 otherwise
*/
native cs_find_ent_by_owner(start_index, const classname[], owner);
/**
* Returns the item id associated with an item name and its aliases.
*
* @note The item name is case sensitive an can be with or without
* weapon_ and item_ prefixes. This can be a command alias as well.
* Values examples: ak47, weapon_ak47, kevlar, item_kevlar, vest, bullpup, ...
*
* @param name Alias or classname
* @param classid If item is a weapon, variable to store the associated
* weapon class id in (CS_WEAPONCLASS_* constants)
*
* @return Item id (CSI_* constants)
*/
native any:cs_get_item_id(const name[], &CsWeaponClassType:classid = CS_WEAPONCLASS_NONE);
/**
* Returns an item name associated with a command alias.
*
* @note The alias is case sensitive.
* @note If not an alias to a weapon, buffer will be set with the original alias.
*
* @param alias Alias name
* @param itemname Buffer to store item name to
* @param maxlength Maximum buffer size
*
* @return True if alias is translated, false otherwise
*/
native bool:cs_get_translated_item_alias(const alias[], itemname[], maxlength);
/**
* Returns some information about a weapon.
*
* @param weapon_id Weapon id, see CSW_* constants
* @param type Info type, see CS_WEAPONINFO_* constants
*
* @return Weapon information value
* @error If weapon_id and type are out of bound, an error will be thrown.
*/
native any:cs_get_weapon_info(weapon_id, CsWeaponInfo:type);
/**
* Returns a weapon class id associated with a weapon id.
*
* @param weapon_id Weapon id (CSI_* constants)
*
* @return Weapon class id (CS_WEAPONCLASS_* constants)
*/
stock CsWeaponClassType:cs_get_weapon_class(weapon_id)
{
new CsWeaponClassType:type = CS_WEAPONCLASS_NONE;
if (cs_is_valid_itemid(weapon_id, .weapon_only = true) || weapon_id == CSI_SHIELD)
{
switch (weapon_id)
{
case CSI_SHIELDGUN, CSI_SHIELD:
{
type = CS_WEAPONCLASS_PISTOL;
}
case CSI_KNIFE:
{
type = CS_WEAPONCLASS_KNIFE;
}
default:
{
new const bits = (1 << weapon_id);
if(bits & CSI_ALL_PISTOLS)
{
type = CS_WEAPONCLASS_PISTOL;
}
else if(bits & CSI_ALL_GRENADES)
{
type = CS_WEAPONCLASS_GRENADE;
}
else if(bits & CSI_ALL_SMGS)
{
type = CS_WEAPONCLASS_SUBMACHINEGUN;
}
else if(bits & CSI_ALL_SHOTGUNS)
{
type = CS_WEAPONCLASS_SHOTGUN;
}
else if(bits & CSI_ALL_MACHINEGUNS)
{
type = CS_WEAPONCLASS_MACHINEGUN;
}
else if(bits & CSI_ALL_RIFLES)
{
type = CS_WEAPONCLASS_RIFLE;
}
else if(bits & CSI_ALL_SNIPERRIFLES)
{
type = CS_WEAPONCLASS_SNIPERRIFLE;
}
}
}
}
return type;
}
/**
* Checks whether an item id is not out of bounds.
*
* @param id Item id (CSI_* constants)
* @param weapon_only If true, only the real weapon ids will be checked,
* including shield as well
*
* @return True if item id is valid, false otherwise
*/
stock bool:cs_is_valid_itemid(id, bool:weapon_only = false)
{
if (id <= CSI_NONE)
{
return false;
}
if (id > CSI_LAST_WEAPON && id != CSI_SHIELDGUN && weapon_only)
{
return false;
}
if (id >= CSI_MAX_COUNT)
{
return false;
}
return true;
}
/**
* Called when CS internally fires a command to a player.
*

View File

@ -0,0 +1,487 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//
// Counter-Strike Functions
//
#if defined _cstrike_const_included
#endinput
#endif
#define _cstrike_const_included
/**
* IDs of weapons in CS
*/
#define CSW_NONE 0
#define CSW_P228 1
#define CSW_SCOUT 3
#define CSW_HEGRENADE 4
#define CSW_XM1014 5
#define CSW_C4 6
#define CSW_MAC10 7
#define CSW_AUG 8
#define CSW_SMOKEGRENADE 9
#define CSW_ELITE 10
#define CSW_FIVESEVEN 11
#define CSW_UMP45 12
#define CSW_SG550 13
#define CSW_GALI 14
#define CSW_GALIL 14
#define CSW_FAMAS 15
#define CSW_USP 16
#define CSW_GLOCK18 17
#define CSW_AWP 18
#define CSW_MP5NAVY 19
#define CSW_M249 20
#define CSW_M3 21
#define CSW_M4A1 22
#define CSW_TMP 23
#define CSW_G3SG1 24
#define CSW_FLASHBANG 25
#define CSW_DEAGLE 26
#define CSW_SG552 27
#define CSW_AK47 28
#define CSW_KNIFE 29
#define CSW_P90 30
#define CSW_VEST 31 // Custom
#define CSW_VESTHELM 32 // Custom
#define CSW_SHIELDGUN 99
#define CSW_LAST_WEAPON CSW_P90
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().
*/
/**
* Internal Counter-Strike model id constants.
*
* @note Model ids starting with CZ_ are only valid in Condition Zero.
*/
enum CsInternalModel
{
CS_DONTCHANGE = 0,
CS_UNASSIGNED = 0,
CS_CT_URBAN = 1,
CS_T_TERROR = 2,
CS_T_LEET = 3,
CS_T_ARCTIC = 4,
CS_CT_GSG9 = 5,
CS_CT_GIGN = 6,
CS_CT_SAS = 7,
CS_T_GUERILLA = 8,
CS_CT_VIP = 9,
CZ_T_MILITIA = 10,
CZ_CT_SPETSNAZ = 11,
};
/**
* Counter-Strike team id constants.
*/
enum CsTeams
{
CS_TEAM_UNASSIGNED = 0,
CS_TEAM_T = 1,
CS_TEAM_CT = 2,
CS_TEAM_SPECTATOR = 3,
};
/**
* @endsection
*/
/**
* Counter-Strike armor types for use with cs_[get|set]_user_armor().
*/
enum CsArmorType
{
CS_ARMOR_NONE = 0, // no armor
CS_ARMOR_KEVLAR = 1, // body vest only
CS_ARMOR_VESTHELM = 2, // vest and helmet
};
/**
* Map zone flags returned by cs_get_user_mapzones().
*/
#define CS_MAPZONE_BUY (1<<0) // Buyzone
#define CS_MAPZONE_BOMBTARGET (1<<1) // Bomb target zone
#define CS_MAPZONE_HOSTAGE_RESCUE (1<<2) // Hostage rescue zone
#define CS_MAPZONE_ESCAPE (1<<3) // Terrorist escape zone
#define CS_MAPZONE_VIP_SAFETY (1<<4) // VIP escape zone
/**
* Constants used for cs_[get|set]_user_zoom().
*/
enum
{
CS_RESET_ZOOM = 0, // Reset any zoom blocking (mode has no effect)
CS_SET_NO_ZOOM, // Disable any sort of zoom
CS_SET_FIRST_ZOOM, // Set first zoom level (AWP style)
CS_SET_SECOND_ZOOM, // Set second zoom level (AWP style)
CS_SET_AUGSG552_ZOOM, // Set AUG/SG552 zoom style
};
/**
* Constants used for the CS_OnBuy() and CS_OnBuyAttempt() forwards.
*
* @note While these mostly overlap with the CSW_* constants the CSI_* constants
* contain custom AMXX values that do not correspond to any real value in
* the game. The CSI_* constants should therefore be used for consistency.
*/
#define CSI_NONE CSW_NONE
#define CSI_P228 CSW_P228
#define CSI_SCOUT CSW_SCOUT
#define CSI_HEGRENADE CSW_HEGRENADE
#define CSI_XM1014 CSW_XM1014
#define CSI_C4 CSW_C4
#define CSI_MAC10 CSW_MAC10
#define CSI_AUG CSW_AUG
#define CSI_SMOKEGRENADE CSW_SMOKEGRENADE
#define CSI_ELITE CSW_ELITE
#define CSI_FIVESEVEN CSW_FIVESEVEN
#define CSI_UMP45 CSW_UMP45
#define CSI_SG550 CSW_SG550
#define CSI_GALIL CSW_GALIL
#define CSI_FAMAS CSW_FAMAS
#define CSI_USP CSW_USP
#define CSI_GLOCK18 CSW_GLOCK18
#define CSI_AWP CSW_AWP
#define CSI_MP5NAVY CSW_MP5NAVY
#define CSI_M249 CSW_M249
#define CSI_M3 CSW_M3
#define CSI_M4A1 CSW_M4A1
#define CSI_TMP CSW_TMP
#define CSI_G3SG1 CSW_G3SG1
#define CSI_FLASHBANG CSW_FLASHBANG
#define CSI_DEAGLE CSW_DEAGLE
#define CSI_SG552 CSW_SG552
#define CSI_AK47 CSW_AK47
#define CSI_KNIFE CSW_KNIFE
#define CSI_P90 CSW_P90
#define CSI_SHIELDGUN CSW_SHIELDGUN // The real CS value, use CSI_SHELD instead.
#define CSI_VEST CSW_VEST // Custom
#define CSI_VESTHELM CSW_VESTHELM // Custom
#define CSI_DEFUSER 33 // Custom
#define CSI_NVGS 34 // Custom
#define CSI_SHIELD 35 // Custom - The value passed by the forward, more convenient for plugins.
#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
#define CSI_ALL_SHOTGUNS CSW_ALL_SHOTGUNS
#define CSI_ALL_SMGS CSW_ALL_SMGS
#define CSI_ALL_RIFLES CSW_ALL_RIFLES
#define CSI_ALL_SNIPERRIFLES CSW_ALL_SNIPERRIFLES
#define CSI_ALL_MACHINEGUNS CSW_ALL_MACHINEGUNS
#define CSI_ALL_GRENADES CSW_ALL_GRENADES
#define CSI_ALL_ARMORS CSW_ALL_ARMORS
#define CSI_ALL_GUNS CSW_ALL_GUNS
/**
* Player's movements constants.
*/
#define CS_PLAYER_FATAL_FALL_SPEED 1100.0
#define CS_PLAYER_MAX_SAFE_FALL_SPEED 500.0
#define CS_DAMAGE_FOR_FALL_SPEED 100.0 / (CS_PLAYER_FATAL_FALL_SPEED - CS_PLAYER_MAX_SAFE_FALL_SPEED)
#define CS_PLAYER_MIN_BOUNCE_SPEED 350
#define CS_PLAYER_FALL_PUNCH_THRESHHOLD 250.0
/**
* Hint message flags for use with m_flDisplayHistory.
*/
#define CS_HINT_ROUND_STARTED (1<<1)
#define CS_HINT_HOSTAGE_SEEN_FAR (1<<2)
#define CS_HINT_HOSTAGE_SEEN_NEAR (1<<3)
#define CS_HINT_HOSTAGE_USED (1<<4)
#define CS_HINT_HOSTAGE_INJURED (1<<5)
#define CS_HINT_HOSTAGE_KILLED (1<<6)
#define CS_HINT_FRIEND_SEEN (1<<7)
#define CS_HINT_ENEMY_SEEN (1<<8)
#define CS_HINT_FRIEND_INJURED (1<<9)
#define CS_HINT_FRIEND_KILLED (1<<10)
#define CS_HINT_ENEMY_KILLED (1<<11)
#define CS_HINT_BOMB_RETRIEVED (1<<12)
#define CS_HINT_AMMO_EXHAUSTED (1<<15)
#define CS_HINT_IN_TARGET_ZONE (1<<16)
#define CS_HINT_IN_RESCUE_ZONE (1<<17)
#define CS_HINT_IN_ESCAPE_ZONE (1<<18)
#define CS_HINT_IN_VIPSAFETY_ZONE (1<<19)
#define CS_HINT_NIGHTVISION (1<<20)
#define CS_HINT_HOSTAGE_CTMOVE (1<<21)
#define CS_HINT_SPEC_DUCK (1<<22)
/**
* Constants for use with m_iIgnoreGlobalChat (ignoremsg client's command)
*/
#define CS_IGNOREMSG_NONE 0
#define CS_IGNOREMSG_ENEMY 1
#define CS_IGNOREMSG_TEAM 2
/**
* Player's gait animation constants.
*/
enum CsPlayerAnim
{
CS_PLAYER_IDLE = 0,
CS_PLAYER_WALK = 1,
CS_PLAYER_JUMP = 2,
CS_PLAYER_SUPERJUMP = 3,
CS_PLAYER_DIE = 4,
CS_PLAYER_ATTACK1 = 5,
CS_PLAYER_ATTACK2 = 6,
CS_PLAYER_FLINCH = 7,
CS_PLAYER_LARGE_FLINCH = 8,
CS_PLAYER_RELOAD = 9,
CS_PLAYER_HOLDBOMB = 10,
};
/**
* Player's menu states for use with m_iMenu.
*/
enum CsMenu
{
CS_Menu_OFF = 0,
CS_Menu_ChooseTeam = 1,
CS_Menu_IGChooseTeam = 2,
CS_Menu_ChooseAppearance = 3,
CS_Menu_Buy = 4,
CS_Menu_BuyPistol = 5,
CS_Menu_BuyRifle = 6,
CS_Menu_BuyMachineGun = 7,
CS_Menu_BuyShotgun = 8,
CS_Menu_BuySubMachineGun = 9,
CS_Menu_BuyItem = 10,
CS_Menu_Radio1 = 11,
CS_Menu_Radio2 = 12,
CS_Menu_Radio3 = 13,
CS_Menu_ClientBuy = 14,
};
/**
* Player's join states for use with m_iJointState.
*/
enum CsJoinState
{
CS_STATE_JOINED = 0,
CS_STATE_SHOW_LTEXT = 1,
CS_STATE_READING_LTEXT = 2,
CS_STATE_SHOW_TEAM_SELECT = 3,
CS_STATE_PICKING_TEAM = 4,
CS_STATE_GET_INTO_GAME = 5,
};
/**
* Player's throw direction on killed for use with m_iThrowDirection.
*/
enum CsThrowDirection
{
CS_THROW_NONE = 0,
CS_THROW_FORWARD = 1,
CS_THROW_BACKWARD = 2,
CS_THROW_HITVEL = 3,
CS_THROW_BOMB = 4,
CS_THROW_GRENADE = 5,
CS_THROW_HITVEL_MINUS_AIRVEL = 6,
};
/**
* @section Player's status bar constants.
*/
/**
* Constants associated with mp_playerid server cvar.
*/
#define CS_PLAYERID_EVERYONE 0
#define CS_PLAYERID_TEAMONLY 1
#define CS_PLAYERID_OFF 2
/**
* Maximum range a status bar can be displayed.
*/
#define CS_MAX_ID_RANGE 2048
#define CS_MAX_SPECTATOR_ID_RANGE 8192
/**
* Maximum buffer length of a status bar message.
*/
#define CS_SBAR_STRING_SIZE 128
/**
* Constants associated to CS_SBAR_ID_TARGETTYPE.
*/
#define CS_SBAR_TARGETTYPE_TEAMMATE 1
#define CS_SBAR_TARGETTYPE_ENEMY 2
#define CS_SBAR_TARGETTYPE_HOSTAGE 3
/**
* Status bar states.
*/
enum CsStatusBar
{
CS_SBAR_ID_TARGETTYPE = 1,
CS_SBAR_ID_TARGETNAME = 2,
CS_SBAR_ID_TARGETHEALTH = 3,
};
/**
* @endsection
*/
/**
* Weapon slot types.
*/
#define CS_WEAPONSLOT_PRIMARY 1
#define CS_WEAPONSLOT_SECONDARY 2
#define CS_WEAPONSLOT_KNIFE 3
#define CS_WEAPONSLOT_GRENADE 4
#define CS_WEAPONSLOT_C4 5
/**
* Weapon class types.
*/
enum CsWeaponClassType
{
CS_WEAPONCLASS_NONE = 0,
CS_WEAPONCLASS_KNIFE = 1,
CS_WEAPONCLASS_PISTOL = 2,
CS_WEAPONCLASS_GRENADE = 3,
CS_WEAPONCLASS_SUBMACHINEGUN = 4,
CS_WEAPONCLASS_SHOTGUN = 5,
CS_WEAPONCLASS_MACHINEGUN = 6,
CS_WEAPONCLASS_RIFLE = 7,
CS_WEAPONCLASS_SNIPERRIFLE = 8,
};
/**
* Weapon autobuy class types.
*/
enum CsAutoBuyClassType
{
CS_AUTOBUYCLASS_PRIMARY = (1<<0),
CS_AUTOBUYCLASS_SECONDARY = (1<<1),
CS_AUTOBUYCLASS_AMMO = (1<<2),
CS_AUTOBUYCLASS_ARMOR = (1<<3),
CS_AUTOBUYCLASS_DEFUSER = (1<<4),
CS_AUTOBUYCLASS_PISTOL = (1<<5),
CS_AUTOBUYCLASS_SMG = (1<<6),
CS_AUTOBUYCLASS_RIFLE = (1<<7),
CS_AUTOBUYCLASS_SNIPERRIFLE = (1<<8),
CS_AUTOBUYCLASS_SHOTGUN = (1<<9),
CS_AUTOBUYCLASS_MACHINEGUN = (1<<10),
CS_AUTOBUYCLASS_GRENADE = (1<<11),
CS_AUTOBUYCLASS_NIGHTVISION = (1<<12),
CS_AUTOBUYCLASS_SHIELD = (1<<13),
};
/**
* Ammo types for use with cs_get_weapon_info().
*/
enum CsAmmoType
{
CS_AMMO_BUCKSHOT = 0,
CS_AMMO_9MM = 1,
CS_AMMO_556NATO = 2,
CS_AMMO_556NATOBOX = 3,
CS_AMMO_762NATO = 4,
CS_AMMO_45ACP = 5,
CS_AMMO_50AE = 6,
CS_AMMO_338MAGNUM = 7,
CS_AMMO_57MM = 8,
CS_AMMO_357SIG = 9,
};
/**
* Weapon info types for use with cs_get_weapon_info().
*/
enum CsWeaponInfo
{
CS_WEAPONINFO_COST = 0,
CS_WEAPONINFO_CLIP_COST = 1,
CS_WEAPONINFO_BUY_CLIP_SIZE = 2,
CS_WEAPONINFO_GUN_CLIP_SIZE = 3,
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

@ -653,6 +653,15 @@
#define HLW_SUIT 31
#define HLW_ALLWEAPONS (~(1<<HLW_SUIT))
/**
* Item's flags
*/
#define ITEM_FLAG_SELECTONEMPTY (1<<0)
#define ITEM_FLAG_NOAUTORELOAD (1<<1)
#define ITEM_FLAG_NOAUTOSWITCHEMPTY (1<<2)
#define ITEM_FLAG_LIMITINWORLD (1<<3)
#define ITEM_FLAG_EXHAUSTIBLE (1<<4)
#define FEV_NOTHOST (1<<0) // Skip local host for event send.
#define FEV_RELIABLE (1<<1) // Send the event reliably. You must specify the origin and angles

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

View File

@ -273,6 +273,7 @@ scripting_files = [
'include/core.inc',
'include/csstats.inc',
'include/cstrike.inc',
'include/cstrike_const.inc',
'include/csx.inc',
'include/cvars.inc',
'include/datapack.inc',