Cstrike: Add cs_get_item_id() and cs_get_translated_item_alias() natives

This commit is contained in:
Arkshine 2015-07-24 09:57:10 +02:00
parent c6628f22ee
commit e6a2434887
16 changed files with 877 additions and 67 deletions

View File

@ -99,5 +99,338 @@
} }
} }
} }
"#default"
{
"CommandsAliases"
{
"Common"
{
"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
}
}
"Weapon"
{
"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
}
}
"Buy"
{
"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
}
}
"BuyEquip"
{
"hegren"
{
"itemid" "4" // CSW/I_HEGRENADE
"classid" "3" // CS_WEAPONCLASS_GRENADE
}
"sgren"
{
"itemid" "9" // CSW/I_SMOKEGRENADE
"classid" "3" // CS_WEAPONCLASS_GRENADE
}
"flash"
{
"itemid" "25" // CSW/I_FLASHBANG
"classid" "3" // CS_WEAPONCLASS_GRENADE
}
"vest"
{
"itemid" "31" // CSW/I_VEST
"classname" "item_kevlar"
}
"vesthelm"
{
"itemid" "32" // CSW/I_VESTHELM
"classname" "item_assaultsuit"
}
"defuser"
{
"itemid" "33" // CSI_DEFUSER
"classname" "item_thighpack"
}
"nvgs"
{
"itemid" "34" // CSI_NVGS
}
"shield"
{
"itemid" "35" // CSI_SHIELD
"classid" "2" // CS_WEAPONCLASS_PISTOL
"classname" "weapon_shield"
}
}
"BuyAmmo"
{
"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', 'CstrikeHacks.cpp',
'CstrikeUtils.cpp', 'CstrikeUtils.cpp',
'CstrikeUserMessages.cpp', 'CstrikeUserMessages.cpp',
'CstrikeitemsInfos.cpp',
'../../../public/memtools/MemoryUtils.cpp', '../../../public/memtools/MemoryUtils.cpp',
'../../../public/memtools/CDetour/detours.cpp', '../../../public/memtools/CDetour/detours.cpp',
'../../../public/memtools/CDetour/asm/asm.c', '../../../public/memtools/CDetour/asm/asm.c',

View File

@ -17,6 +17,7 @@
/** /**
* Weapon Ids for use with CS_OnBuyAttempt(), CS_OnBuy(). * Weapon Ids for use with CS_OnBuyAttempt(), CS_OnBuy().
*/ */
#define CSI_NONE CSW_NONE
#define CSI_P228 CSW_P228 #define CSI_P228 CSW_P228
#define CSI_SCOUT CSW_SCOUT #define CSI_SCOUT CSW_SCOUT
#define CSI_HEGRENADE CSW_HEGRENADE #define CSI_HEGRENADE CSW_HEGRENADE
@ -50,15 +51,17 @@
#define CSI_VESTHELM CSW_VESTHELM // Custom #define CSI_VESTHELM CSW_VESTHELM // Custom
#define CSI_DEFUSER 33 // Custom #define CSI_DEFUSER 33 // Custom
#define CSI_NVGS 34 // 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_PRIAMMO 36 // Custom
#define CSI_SECAMMO 37 // 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 BITS_PISTOLS (1<<CSI_GLOCK18 | 1<<CSI_USP | 1<<CSI_P228 | 1<<CSI_DEAGLE | 1<<CSI_ELITE | 1<<CSI_FIVESEVEN) #define BITS_PISTOLS (1<<CSI_GLOCK18 | 1<<CSI_USP | 1<<CSI_P228 | 1<<CSI_DEAGLE | 1<<CSI_ELITE | 1<<CSI_FIVESEVEN)
/** /**
* Weapons Ids. * Weapons Ids.
*/ */
#define CSW_NONE 0
#define CSW_P228 1 #define CSW_P228 1
#define CSW_SCOUT 3 #define CSW_SCOUT 3
#define CSW_HEGRENADE 4 #define CSW_HEGRENADE 4
@ -278,4 +281,24 @@ typedef enum
} Menu; } 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,
};
extern char WeaponNameList[MAX_WEAPONS][64];
#endif // CSTRIKE_DATA_H #endif // CSTRIKE_DATA_H

View File

@ -37,6 +37,7 @@ CreateNamedEntityFunc CS_CreateNamedEntity;
UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString; UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString;
int CurrentItemId; int CurrentItemId;
StringHashMap<int> ItemAliasList; StringHashMap<int> ItemAliasList;
TypeDescription TeamDesc; TypeDescription TeamDesc;
TypeDescription MenuDesc; TypeDescription MenuDesc;
@ -148,9 +149,11 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
} }
else // Handling buy via alias else // Handling buy via alias
{ {
if (ItemAliasList.retrieve(command, &itemId)) AliasInfo info;
if (ItemsManager.GetAliasInfosFromBuy(command, &info))
{ {
CurrentItemId = itemId; CurrentItemId = info.itemid;
} }
} }
} }
@ -319,8 +322,6 @@ void CtrlDetours_ClientCommand(bool set)
{ {
ClientCommandDetour->Destroy(); ClientCommandDetour->Destroy();
} }
ItemAliasList.clear();
} }
} }
@ -330,59 +331,6 @@ void ToggleDetour_ClientCommands(bool enable)
{ {
(enable) ? ClientCommandDetour->EnableDetour() : ClientCommandDetour->DisableDetour(); (enable) ? ClientCommandDetour->EnableDetour() : ClientCommandDetour->DisableDetour();
} }
if (enable)
{
// Build the item alias list.
// Used in ClientCommand to check and get fastly item id from alias name.
typedef struct
{
const char *alias;
int id;
} itemBuyAliasInfo;
itemBuyAliasInfo aliasToId[] =
{
{ "p228" , CSI_P228 }, { "228compact" , CSI_P228 },
{ "scout" , CSI_SCOUT }, { "hegren" , CSI_HEGRENADE },
{ "xm1014" , CSI_XM1014 }, { "autoshotgun", CSI_XM1014 },
{ "mac10" , CSI_MAC10 }, { "aug" , CSI_AUG },
{ "bullpup" , CSI_AUG }, { "sgren" , CSI_SMOKEGRENADE },
{ "elites" , CSI_ELITE }, { "fn57" , CSI_FIVESEVEN },
{ "fiveseven" , CSI_FIVESEVEN }, { "ump45" , CSI_UMP45 },
{ "sg550" , CSI_SG550 }, { "krieg550" , CSI_SG550 },
{ "galil" , CSI_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();
}
} }
@ -443,8 +391,6 @@ void CtrlDetours_BuyCommands(bool set)
{ {
AddAccountDetour->Destroy(); AddAccountDetour->Destroy();
} }
ItemAliasList.clear();
} }
} }

View File

@ -18,6 +18,7 @@
#include <IGameConfigs.h> #include <IGameConfigs.h>
#include <CDetour/detours.h> #include <CDetour/detours.h>
#include <engine_strucs.h> #include <engine_strucs.h>
#include "CstrikeDatas.h"
void InitializeHacks(); void InitializeHacks();
void InitGlobalVars(); void InitGlobalVars();

View File

@ -0,0 +1,241 @@
// 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"
CsItemInfo ItemsManager;
#define PSTATE_NONE
#define PSTATE_ALIASES_TYPE 0
#define PSTATE_ALIASES_ALIAS 1
#define PSTATE_ALIASES_ALIAS_DEFS 2
CsItemInfo::CsItemInfo()
:
m_ParseState(0),
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, "Common"))
{
m_List = &m_CommonAliasesList;
}
else if (!strcmp(name, "Weapon"))
{
m_List = &m_WeaponAliasesList;
}
else if (strstr(name, "Buy"))
{
m_List = &m_BuyAliasesList;
}
else
{
return SMCResult_HaltFail;
}
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
{
return SMCResult_HaltFail;
}
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)
{
MF_Log("Invalid or missing key in \"%s\" section. Please check your gamedata files.", m_Alias.chars());
return;
}
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;
}

View File

@ -0,0 +1,87 @@
// 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 "CstrikeDatas.h"
#include <ITextParsers.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;
};
class CsItemInfo : public ITextListener_SMC
{
public:
CsItemInfo();
~CsItemInfo();
public:
void Clear();
bool HasConfigError();
public:
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
void ReadSMC_ParseEnd(bool halted, bool failed);
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);
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;
};
extern CsItemInfo ItemsManager;
#endif // _CSTRIKE_WEAPONS_INFOS_H_

View File

@ -41,6 +41,8 @@ void OnAmxxAttach()
char error[256]; char error[256];
error[0] = '\0'; error[0] = '\0';
ConfigManager->AddUserConfigHook("CommandsAliases", &ItemsManager);
if (!ConfigManager->LoadGameConfigFile("modules.games", &MainConfig, error, sizeof(error)) && error[0] != '\0') if (!ConfigManager->LoadGameConfigFile("modules.games", &MainConfig, error, sizeof(error)) && error[0] != '\0')
{ {
MF_Log("Could not read module.games gamedata: %s", error); MF_Log("Could not read module.games gamedata: %s", error);
@ -83,8 +85,21 @@ void OnPluginsLoaded()
g_pFunctionTable->pfnStartFrame = nullptr; g_pFunctionTable->pfnStartFrame = nullptr;
} }
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 OnAmxxDetach() void OnAmxxDetach()
{ {
ConfigManager->RemoveUserConfigHook("CommandsAliases", &ItemsManager);
ConfigManager->CloseGameConfigFile(MainConfig); ConfigManager->CloseGameConfigFile(MainConfig);
ConfigManager->CloseGameConfigFile(CommonConfig); ConfigManager->CloseGameConfigFile(CommonConfig);

View File

@ -20,6 +20,7 @@
#include <amtl/am-string.h> #include <amtl/am-string.h>
bool NoKifesMode = false; bool NoKifesMode = false;
char WeaponNameList[MAX_WEAPONS][64];
// native cs_set_user_money(index, money, flash = 1); // native cs_set_user_money(index, money, flash = 1);
static cell AMX_NATIVE_CALL cs_set_user_money(AMX *amx, cell *params) static cell AMX_NATIVE_CALL cs_set_user_money(AMX *amx, cell *params)
@ -1739,6 +1740,77 @@ static cell AMX_NATIVE_CALL cs_find_ent_by_class(AMX* amx, cell* params)
return 0; 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");
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");
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;
}
AMX_NATIVE_INFO CstrikeNatives[] = AMX_NATIVE_INFO CstrikeNatives[] =
{ {
{"cs_set_user_money", cs_set_user_money}, {"cs_set_user_money", cs_set_user_money},
@ -1803,6 +1875,8 @@ AMX_NATIVE_INFO CstrikeNatives[] =
{"cs_set_c4_defusing", cs_set_c4_defusing}, {"cs_set_c4_defusing", cs_set_c4_defusing},
{"cs_create_entity", cs_create_entity }, {"cs_create_entity", cs_create_entity },
{"cs_find_ent_by_class", cs_find_ent_by_class}, {"cs_find_ent_by_class", cs_find_ent_by_class},
{"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} {nullptr, nullptr}
}; };

View File

@ -16,9 +16,14 @@
#include "CstrikeUtils.h" #include "CstrikeUtils.h"
#include "CstrikeHacks.h" #include "CstrikeHacks.h"
#include "CstrikePlayer.h" #include "CstrikePlayer.h"
#include "CstrikeDatas.h"
#include <am-string.h>
bool ShouldBlock; bool ShouldBlock;
bool ShouldBlockHLTV; bool ShouldBlockHLTV;
bool RetrieveWeaponName;
ke::AString CurrentWeaponName;
int ArgPosition;
int MessageIdArmorType; int MessageIdArmorType;
int MessageIdHLTV; int MessageIdHLTV;
@ -30,6 +35,7 @@ int MessageIdSetFOV;
int MessageIdStatusIcon; int MessageIdStatusIcon;
int MessageIdTeamInfo; int MessageIdTeamInfo;
int MessageIdTextMsg; int MessageIdTextMsg;
int MessageIdWeaponList;
struct UserMsg struct UserMsg
{ {
@ -49,6 +55,7 @@ UserMsg MessagesList[] =
{ "StatusIcon" , &MessageIdStatusIcon }, { "StatusIcon" , &MessageIdStatusIcon },
{ "TeamInfo" , &MessageIdTeamInfo }, { "TeamInfo" , &MessageIdTeamInfo },
{ "TextMsg" , &MessageIdTextMsg }, { "TextMsg" , &MessageIdTextMsg },
{ "WeaponList" , &MessageIdWeaponList },
{ nullptr , nullptr } { nullptr , nullptr }
}; };
@ -113,6 +120,13 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
} }
break; break;
} }
case MSG_INIT:
{
if (msg_type == MessageIdWeaponList)
{
RetrieveWeaponName = true;
}
}
} }
if (ShouldBlockHLTV) if (ShouldBlockHLTV)
@ -123,12 +137,26 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
void OnWriteByte(int iValue) void OnWriteByte(int value)
{ {
if (ShouldBlock) if (ShouldBlock)
{ {
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
else 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 (RetrieveWeaponName)
{
CurrentWeaponName = value;
}
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@ -140,6 +168,11 @@ void OnMessageEnd(void)
ShouldBlock = false; ShouldBlock = false;
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
else if (RetrieveWeaponName)
{
RetrieveWeaponName = false;
ArgPosition = 0;
}
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@ -150,6 +183,15 @@ void EnableMessageHooks()
{ {
g_pengfuncsTable->pfnMessageBegin = OnMessageBegin; g_pengfuncsTable->pfnMessageBegin = OnMessageBegin;
g_pengfuncsTable->pfnWriteByte = OnWriteByte; g_pengfuncsTable->pfnWriteByte = OnWriteByte;
g_pengfuncsTable->pfnWriteString = OnWriteString;
g_pengfuncsTable->pfnMessageEnd = OnMessageEnd; g_pengfuncsTable->pfnMessageEnd = OnMessageEnd;
} }
} }
void DisableMessageHooks()
{
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; extern int MessageIdTextMsg;
void EnableMessageHooks(); void EnableMessageHooks();
void DisableMessageHooks();
#endif // CSTRIKE_USER_MESSAGES_H #endif // CSTRIKE_USER_MESSAGES_H

View File

@ -123,7 +123,7 @@
// #define FN_ClientPutInServer ClientPutInServer /* pfnClientPutInServer() (wd) Client is entering the game */ // #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_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_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_ServerDeactivate ServerDeactivate /* pfnServerDeactivate() (wd) Server is leaving the map (shutdown or changelevel); SDK2 */
// #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */ // #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */
// #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */ // #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */
@ -175,7 +175,7 @@
// #define FN_ClientPutInServer_Post ClientPutInServer_Post // #define FN_ClientPutInServer_Post ClientPutInServer_Post
// #define FN_ClientCommand_Post ClientCommand_Post // #define FN_ClientCommand_Post ClientCommand_Post
// #define FN_ClientUserInfoChanged_Post ClientUserInfoChanged_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_ServerDeactivate_Post ServerDeactivate_Post
// #define FN_PlayerPreThink_Post PlayerPreThink_Post // #define FN_PlayerPreThink_Post PlayerPreThink_Post
// #define FN_PlayerPostThink_Post PlayerPostThink_Post // #define FN_PlayerPostThink_Post PlayerPostThink_Post

View File

@ -151,12 +151,14 @@
<ClCompile Include="..\CstrikeUserMessages.cpp" /> <ClCompile Include="..\CstrikeUserMessages.cpp" />
<ClCompile Include="..\CstrikeUtils.cpp" /> <ClCompile Include="..\CstrikeUtils.cpp" />
<ClCompile Include="..\..\..\..\public\sdk\amxxmodule.cpp" /> <ClCompile Include="..\..\..\..\public\sdk\amxxmodule.cpp" />
<ClCompile Include="..\CstrikeItemsInfos.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\..\..\public\memtools\CDetour\asm\asm.h" /> <ClInclude Include="..\..\..\..\public\memtools\CDetour\asm\asm.h" />
<ClInclude Include="..\..\..\..\public\memtools\CDetour\detourhelpers.h" /> <ClInclude Include="..\..\..\..\public\memtools\CDetour\detourhelpers.h" />
<ClInclude Include="..\..\..\..\public\memtools\CDetour\detours.h" /> <ClInclude Include="..\..\..\..\public\memtools\CDetour\detours.h" />
<ClInclude Include="..\..\..\..\public\memtools\MemoryUtils.h" /> <ClInclude Include="..\..\..\..\public\memtools\MemoryUtils.h" />
<ClInclude Include="..\CstrikeItemsInfos.h" />
<ClInclude Include="..\CstrikeDatas.h" /> <ClInclude Include="..\CstrikeDatas.h" />
<ClInclude Include="..\CstrikeHacks.h" /> <ClInclude Include="..\CstrikeHacks.h" />
<ClInclude Include="..\CstrikePlayer.h" /> <ClInclude Include="..\CstrikePlayer.h" />

View File

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

View File

@ -1025,6 +1025,43 @@ native cs_create_entity(const classname[]);
*/ */
native cs_find_ent_by_class(start_index, const classname[]); native cs_find_ent_by_class(start_index, const classname[]);
/**
* 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);
/**
*
*/
stock cs_get_weapon_class(weapon_id)
{
}
/** /**
* Called when CS internally fires a command to a player. * Called when CS internally fires a command to a player.
* *

View File

@ -129,9 +129,10 @@ enum
#define CSI_VESTHELM CSW_VESTHELM // Custom #define CSI_VESTHELM CSW_VESTHELM // Custom
#define CSI_DEFUSER 33 // Custom #define CSI_DEFUSER 33 // Custom
#define CSI_NVGS 34 // 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_PRIAMMO 36 // Custom
#define CSI_SECAMMO 37 // 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
/** /**
* Player's movements constants. * Player's movements constants.