Свързване на Chat Manager със Knife Menu

В този раздел можете да подавате всякакви заявки за намиране, изработка или преработка на плъгини/модове.
Аватар
Leonardo Da Vinci
Извън линия
Потребител
Потребител
Мнения: 67
Регистриран на: 30 Мар 2018, 20:55
Местоположение: #include <amxmodx>

Свързване на Chat Manager със Knife Menu

Мнение от Leonardo Da Vinci » 04 Мар 2019, 17:57

Добър ден! Използвам двата от плъгините на OciXCroM.

Единият е Chat Manager:

Код за потвърждение: Избери целия код

#include <amxmodx>
#include <amxmisc>
#include <cromchat>
#include <cstrike>

#define PLUGIN_VERSION "4.3.1"
#define DELAY_ON_REGISTER 1.0
#define DELAY_ON_CONNECT 1.0
#define DELAY_ON_CHANGE 0.1
#define PLACEHOLDER_LENGTH 64
#define WRITTEN_MESSAGE_SIZE 120
#define FULL_MESSAGE_SIZE 180
#define ERROR_FILE "chatmanager_errors.log"

#if defined replace_string
	#define replace_all replace_string
#endif

/* 	You can comment placeholders you don't need from the lines below and that will completely deactivate them.
	You can also activate the additional ones if you want to use them.
	Feel free to experiment in making your custom ones as well. */
	
#define ARG_ADMIN_PREFIX 		"$admin_prefix$"
#define ARG_DEAD_PREFIX 		"$dead_prefix$"
#define ARG_TEAM 				"$team$"
#define ARG_NAME 				"$name$"
#define ARG_CUSTOM_NAME			"$custom_name$"
#define ARG_IP 					"$ip$"
#define ARG_STEAM 				"$steam$"
#define ARG_USERID 				"$userid$"
#define ARG_CHAT_COLOR 			"$chat_color$"
#define ARG_MESSAGE 			"$message$"
#define ARG_TIME 				"$time$"
#define ARG_RANK 				"$rank$"
//#define ARG_CURRENT_XP 		"$current_xp$"
//#define ARG_NEXT_XP 			"$next_xp$"
//#define ARG_LEVEL 			"$level$"
//#define ARG_NEXT_LEVEL 		"$next_level$"
//#define ARG_NEXT_RANK 		"$next_rank$"
//#define ARG_HEALTH 			"$health$"
//#define ARG_ARMOR 			"$armor$"
//#define ARG_FRAGS 			"$frags$"
//#define ARG_DEATHS 			"$deaths$"
//#define ARG_CITY 				"$city$"
//#define ARG_COUNTRY 			"$country$"
//#define ARG_COUNTRY_CODE 		"$country_code$"
//#define ARG_CONTINENT 		"$continent$"
//#define ARG_CONTINENT_CODE 	"$continent_code$"

/*	The settings end here. Don't modify anything below this if you don't know what you're doing. */

#if defined ARG_CITY || defined ARG_COUNTRY || defined ARG_COUNTRY_CODE || defined ARG_CONTINENT || defined ARG_CONTINENT_CODE
	#include <geoip>
#endif

#if defined ARG_XP
	native crxranks_get_user_xp(id)
#endif

#if defined ARG_NEXT_XP
	native crxranks_get_user_next_xp(id)
#endif

#if defined ARG_NEXT_LEVEL
	native crxranks_get_user_next_level(id)
#endif

#if defined ARG_RANK
	native crxranks_get_user_rank(id, buffer[], len)
#endif

#if defined ARG_NEXT_RANK
	native crxranks_get_user_next_rank(id, buffer[], len)
#endif

native crxranks_get_user_level(id)
forward crxranks_user_level_updated(id, level, bool:levelup)

enum
{
	SECTION_NONE,
	SECTION_MAIN_SETTINGS,
	SECTION_ADMIN_PREFIXES,
	SECTION_CHAT_COLORS,
	SECTION_NAME_CUSTOMIZATION,
	SECTION_FORMAT_DEFINITIONS,
	SECTION_SAY_FORMATS
}

enum
{
	INFOTYPE_NONE,
	INFOTYPE_FLAG,
	INFOTYPE_NAME,
	INFOTYPE_IP,
	INFOTYPE_STEAM,
	INFOTYPE_ANY_FLAG,
	INFOTYPE_NO_PREFIX,
	INFOTYPE_LEVEL
}

enum
{
	ALLCHAT_NONE = 0,
	ALLCHAT_NO_TEAM,
	ALLCHAT_SEE_TEAM
}

enum _:PlayerInfo
{
	INFO_TYPE,
	INFO[35],
	DATA[32],
	DATA2[32]
}

enum _:Settings
{
	ALL_CHAT,
	ADMIN_LISTEN_FLAGS[32],
	DEAD_PREFIX[32],
	ALIVE_PREFIX[32],
	TEAM_PREFIX_T[32],
	TEAM_PREFIX_CT[32],
	TEAM_PREFIX_SPEC[32],
	ERROR_TEXT[32],
	FORMAT_TIME[32],
	CHAT_LOG_FILE[64],
	CHAT_LOG_SAY_FORMAT[32],
	CHAT_LOG_TEAM_FORMAT[32],
	SAY_SOUND[128],
	SAY_TEAM_SOUND[128]
}

enum _:PlayerData
{
	PDATA_NAME[32],
	PDATA_CUSTOM_NAME[32],
	PDATA_IP[16],
	PDATA_STEAM[35],
	PDATA_USERID[10],
	PDATA_PREFIX[32],
	PDATA_CHAT_COLOR[6],
	PDATA_SAY_FORMAT[32],
	PDATA_SAY_TEAM_FORMAT[32],
	PDATA_ADMIN_FLAGS,
	bool:PDATA_ADMIN_LISTEN,
	bool:PDATA_PREFIX_ENABLED,
	bool:PDATA_CHAT_COLOR_ENABLED,
	bool:PDATA_CUSTOM_NAME_ENABLED
}

new g_eSettings[Settings],
	g_ePlayerData[33][PlayerData],
	Array:g_aAdminPrefixes,
	Array:g_aChatColors,
	Array:g_aNameCustomization,
	Array:g_aSayFormats,
	Trie:g_tBlockFirst,
	Trie:g_tFormatDefinitions,
	bool:g_bFileWasRead,
	bool:g_bRankSystem,
	g_szConfigsName[256],
	g_szFilename[256],
	g_iAdminPrefixes,
	g_iChatColors,
	g_iNameCustomization,
	g_iSayFormats

public plugin_init()
{
	register_plugin("Chat Manager", PLUGIN_VERSION, "OciXCrom")
	register_cvar("CRXChatManager", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED)		
	set_task(DELAY_ON_REGISTER, "RegisterCommands")
}

public plugin_end()
{
	ArrayDestroy(g_aAdminPrefixes)
	ArrayDestroy(g_aChatColors)
	ArrayDestroy(g_aNameCustomization)
	ArrayDestroy(g_aSayFormats)
	TrieDestroy(g_tBlockFirst)
	TrieDestroy(g_tFormatDefinitions)
}

public plugin_precache()
{
	g_aAdminPrefixes = ArrayCreate(PlayerInfo)
	g_aChatColors = ArrayCreate(PlayerInfo)
	g_aNameCustomization = ArrayCreate(PlayerInfo)
	g_aSayFormats = ArrayCreate(PlayerInfo)
	g_tBlockFirst = TrieCreate()
	g_tFormatDefinitions = TrieCreate()
	get_configsdir(g_szConfigsName, charsmax(g_szConfigsName))
	formatex(g_szFilename, charsmax(g_szFilename), "%s/ChatManager.ini", g_szConfigsName)
	
	if(LibraryExists("crxranks", LibType_Library))
		g_bRankSystem = true
		
	ReadFile()
}

public RegisterCommands()
{
	register_clcmd("say", "Hook_Say")
	register_clcmd("say_team", "Hook_Say")
	register_concmd("cm_reload", "Cmd_Reload", ADMIN_RCON, "-- reloads the configuration file")
}

public client_putinserver(id)
{
	get_user_name(id, g_ePlayerData[id][PDATA_NAME], charsmax(g_ePlayerData[][PDATA_NAME]))
	copy(g_ePlayerData[id][PDATA_CUSTOM_NAME], charsmax(g_ePlayerData[][PDATA_CUSTOM_NAME]), g_ePlayerData[id][PDATA_NAME])
	get_user_ip(id, g_ePlayerData[id][PDATA_IP], charsmax(g_ePlayerData[][PDATA_IP]), 1)
	get_user_authid(id, g_ePlayerData[id][PDATA_STEAM], charsmax(g_ePlayerData[][PDATA_STEAM]))
	num_to_str(get_user_userid(id), g_ePlayerData[id][PDATA_USERID], charsmax(g_ePlayerData[][PDATA_USERID]))
	g_ePlayerData[id][PDATA_PREFIX_ENABLED] = true
	g_ePlayerData[id][PDATA_CHAT_COLOR_ENABLED] = true
	g_ePlayerData[id][PDATA_CUSTOM_NAME_ENABLED] = true
	set_task(DELAY_ON_CONNECT, "UpdateData", id)
}

public client_infochanged(id)
{
	if(!is_user_connected(id))
		return
		
	static szNewName[32]
	get_user_info(id, "name", szNewName, charsmax(szNewName))
	
	if(!equal(szNewName, g_ePlayerData[id][PDATA_NAME]))
	{
		copy(g_ePlayerData[id][PDATA_NAME], charsmax(g_ePlayerData[][PDATA_NAME]), szNewName)
		copy(g_ePlayerData[id][PDATA_CUSTOM_NAME], charsmax(g_ePlayerData[][PDATA_CUSTOM_NAME]), szNewName)
		set_task(DELAY_ON_CHANGE, "UpdateData", id)
	}
}

public crxranks_user_level_updated(id, iLevel)
	set_task(DELAY_ON_CHANGE, "UpdateData", id)
	
public UpdateData(id)
{
	static eItem[PlayerInfo], i
	g_ePlayerData[id][PDATA_PREFIX][0] = EOS
	g_ePlayerData[id][PDATA_CHAT_COLOR][0] = EOS
	g_ePlayerData[id][PDATA_SAY_FORMAT][0] = EOS
	g_ePlayerData[id][PDATA_SAY_TEAM_FORMAT][0] = EOS
	g_ePlayerData[id][PDATA_ADMIN_FLAGS] = get_user_flags(id)
	g_ePlayerData[id][PDATA_ADMIN_LISTEN] = g_eSettings[ADMIN_LISTEN_FLAGS][0] ? (bool:(g_ePlayerData[id][PDATA_ADMIN_FLAGS] & read_flags(g_eSettings[ADMIN_LISTEN_FLAGS])) ? true : false) : false
	copy(g_ePlayerData[id][PDATA_CUSTOM_NAME], charsmax(g_ePlayerData[][PDATA_CUSTOM_NAME]), g_ePlayerData[id][PDATA_NAME])
	
	if(g_iAdminPrefixes)
	{
		for(i = 0; i < g_iAdminPrefixes; i++)
		{
			ArrayGetArray(g_aAdminPrefixes, i, eItem)
			
			if(meets_requirements(id, eItem[INFO_TYPE], eItem[INFO]))
			{
				copy(g_ePlayerData[id][PDATA_PREFIX], charsmax(g_ePlayerData[][PDATA_PREFIX]), eItem[DATA])
				break
			}
		}
	}
	
	if(g_iChatColors)
	{
		for(i = 0; i < g_iChatColors; i++)
		{
			ArrayGetArray(g_aChatColors, i, eItem)
			
			if(meets_requirements(id, eItem[INFO_TYPE], eItem[INFO]))
			{
				copy(g_ePlayerData[id][PDATA_CHAT_COLOR], charsmax(g_ePlayerData[][PDATA_CHAT_COLOR]), eItem[DATA])
				break
			}
		}
	}
	
	if(g_iNameCustomization)
	{
		for(i = 0; i < g_iNameCustomization; i++)
		{
			ArrayGetArray(g_aNameCustomization, i, eItem)
			
			if(meets_requirements(id, eItem[INFO_TYPE], eItem[INFO]))
			{
				copy(g_ePlayerData[id][PDATA_CUSTOM_NAME], charsmax(g_ePlayerData[][PDATA_CUSTOM_NAME]), eItem[DATA])
				break
			}
		}
	}
	
	if(g_iSayFormats)
	{
		for(i = 0; i < g_iSayFormats; i++)
		{
			ArrayGetArray(g_aSayFormats, i, eItem)
			
			if(meets_requirements(id, eItem[INFO_TYPE], eItem[INFO]))
			{
				copy(g_ePlayerData[id][PDATA_SAY_FORMAT], charsmax(g_ePlayerData[][PDATA_SAY_FORMAT]), eItem[DATA])
				copy(g_ePlayerData[id][PDATA_SAY_TEAM_FORMAT], charsmax(g_ePlayerData[][PDATA_SAY_TEAM_FORMAT]), eItem[DATA2])
				break
			}
		}
	}
}

ReadFile()
{
	if(g_bFileWasRead)
	{
		g_iAdminPrefixes = 0
		g_iChatColors = 0
		g_iNameCustomization = 0
		g_iSayFormats = 0
		ArrayClear(g_aAdminPrefixes)
		ArrayClear(g_aChatColors)
		ArrayClear(g_aNameCustomization)
		ArrayClear(g_aSayFormats)
		TrieClear(g_tBlockFirst)
		TrieClear(g_tFormatDefinitions)
	}
	
	new iFilePointer = fopen(g_szFilename, "rt")
	
	if(iFilePointer)
	{
		new szData[192], szValue[160], szKey[32], eItem[PlayerInfo], iSection = SECTION_NONE, iChatLogSayLine, iChatLogTeamLine, iSize, iLine
		
		while(!feof(iFilePointer))
		{
			iLine++
			fgets(iFilePointer, szData, charsmax(szData))
			trim(szData)
			
			switch(szData[0])
			{
				case EOS, '#', ';': continue
				case '[':
				{
					iSize = strlen(szData)
					
					if(szData[iSize - 1] == ']')
					{
						switch(szData[1])
						{
							case 'M', 'm': iSection = SECTION_MAIN_SETTINGS
							case 'A', 'a': iSection = SECTION_ADMIN_PREFIXES
							case 'C', 'c': iSection = SECTION_CHAT_COLORS
							case 'N', 'n': iSection = SECTION_NAME_CUSTOMIZATION
							case 'F', 'f': iSection = SECTION_FORMAT_DEFINITIONS
							case 'S', 's': iSection = SECTION_SAY_FORMATS
							default:
							{
								log_config_error(iLine, "Unknown section name: %s", szData)
								iSection = SECTION_NONE
							}
						}
					}
					else
					{
						log_config_error(iLine, "Unclosed section name: %s", szData)
						continue
					}
				}
				default:
				{
					switch(iSection)
					{
						case SECTION_NONE: log_config_error(iLine, "Data is not in any section: %s", szData)
						case SECTION_MAIN_SETTINGS:
						{
							strtok(szData, szKey, charsmax(szKey), szValue, charsmax(szValue), '=')
							trim(szKey); trim(szValue)
							
							if(!szValue[0])
								continue
								
							if(equal(szKey, "ALL_CHAT"))
								g_eSettings[ALL_CHAT] = clamp(str_to_num(szValue), ALLCHAT_NONE, ALLCHAT_SEE_TEAM)
							else if(equal(szKey, "ADMIN_LISTEN_FLAGS"))
								copy(g_eSettings[ADMIN_LISTEN_FLAGS], charsmax(g_eSettings[ADMIN_LISTEN_FLAGS]), szValue)
							else if(equal(szKey, "BLOCK_FIRST_SYMBOLS"))
							{
								while(szValue[0] != 0 && strtok(szValue, szKey, charsmax(szKey), szValue, charsmax(szValue), ','))
								{
									trim(szKey); trim(szValue)
									TrieSetCell(g_tBlockFirst, szKey, 1)
								}
							}
							else if(equal(szKey, "DEAD_PREFIX"))
								copy(g_eSettings[DEAD_PREFIX], charsmax(g_eSettings[DEAD_PREFIX]), szValue)
							else if(equal(szKey, "ALIVE_PREFIX"))
								copy(g_eSettings[ALIVE_PREFIX], charsmax(g_eSettings[ALIVE_PREFIX]), szValue)
							else if(equal(szKey, "TEAM_PREFIX_T"))
								copy(g_eSettings[TEAM_PREFIX_T], charsmax(g_eSettings[TEAM_PREFIX_T]), szValue)
							else if(equal(szKey, "TEAM_PREFIX_CT"))
								copy(g_eSettings[TEAM_PREFIX_CT], charsmax(g_eSettings[TEAM_PREFIX_CT]), szValue)
							else if(equal(szKey, "TEAM_PREFIX_SPEC"))
								copy(g_eSettings[TEAM_PREFIX_SPEC], charsmax(g_eSettings[TEAM_PREFIX_SPEC]), szValue)
							else if(equal(szKey, "ERROR_TEXT"))
								copy(g_eSettings[ERROR_TEXT], charsmax(g_eSettings[ERROR_TEXT]), szValue)
							else if(equal(szKey, "FORMAT_TIME"))
								copy(g_eSettings[FORMAT_TIME], charsmax(g_eSettings[FORMAT_TIME]), szValue)
							else if(equal(szKey, "CHAT_LOG_FILE"))
								copy(g_eSettings[CHAT_LOG_FILE], charsmax(g_eSettings[CHAT_LOG_FILE]), szValue)
							else if(equal(szKey, "CHAT_LOG_SAY_FORMAT"))
							{
								iChatLogSayLine = iLine
								copy(g_eSettings[CHAT_LOG_SAY_FORMAT], charsmax(g_eSettings[CHAT_LOG_SAY_FORMAT]), szValue)
							}
							else if(equal(szKey, "CHAT_LOG_TEAM_FORMAT"))
							{
								iChatLogTeamLine = iLine
								copy(g_eSettings[CHAT_LOG_TEAM_FORMAT], charsmax(g_eSettings[CHAT_LOG_TEAM_FORMAT]), szValue)
							}
							else if(equal(szKey, "SAY_SOUND") && !g_bFileWasRead)
							{
								precache_sound(szValue)
								copy(g_eSettings[SAY_SOUND], charsmax(g_eSettings[SAY_SOUND]), szValue)
							}
							else if(equal(szKey, "SAY_TEAM_SOUND") && !g_bFileWasRead)
							{
								precache_sound(szValue)
								copy(g_eSettings[SAY_TEAM_SOUND], charsmax(g_eSettings[SAY_TEAM_SOUND]), szValue)
							}
						}
						case SECTION_ADMIN_PREFIXES:
						{
							parse(szData, szKey, charsmax(szKey), eItem[INFO], charsmax(eItem[INFO]), eItem[DATA], charsmax(eItem[DATA]))
							eItem[INFO_TYPE] = get_info_type(szKey)
								
							if(invalid_info_type(eItem[INFO_TYPE], szKey, iLine))
								continue
							
							ArrayPushArray(g_aAdminPrefixes, eItem)
							g_iAdminPrefixes++
						}
						case SECTION_CHAT_COLORS:
						{
							parse(szData, szKey, charsmax(szKey), eItem[INFO], charsmax(eItem[INFO]), eItem[DATA], charsmax(eItem[DATA]))
							eItem[INFO_TYPE] = get_info_type(szKey)
							
							if(invalid_info_type(eItem[INFO_TYPE], szKey, iLine))
								continue
							
							ArrayPushArray(g_aChatColors, eItem)
							g_iChatColors++
						}
						case SECTION_NAME_CUSTOMIZATION:
						{
							parse(szData, szKey, charsmax(szKey), eItem[INFO], charsmax(eItem[INFO]), eItem[DATA], charsmax(eItem[DATA]))
							eItem[INFO_TYPE] = get_info_type(szKey)
							
							if(invalid_info_type(eItem[INFO_TYPE], szKey, iLine))
								continue
							
							ArrayPushArray(g_aNameCustomization, eItem)
							g_iNameCustomization++
						}
						case SECTION_FORMAT_DEFINITIONS:
						{
							strtok(szData, szKey, charsmax(szKey), szValue, charsmax(szValue), '=')
							trim(szKey); trim(szValue)
							TrieSetString(g_tFormatDefinitions, szKey, szValue)
						}
						case SECTION_SAY_FORMATS:
						{
							parse(szData, szKey, charsmax(szKey), eItem[INFO], charsmax(eItem[INFO]), eItem[DATA], charsmax(eItem[DATA]), eItem[DATA2], charsmax(eItem[DATA2]))
							
							if(!TrieKeyExists(g_tFormatDefinitions, eItem[DATA]))
							{
								log_config_error(iLine, "Format definition ^"%s^" doesn't exist.", eItem[DATA])
								continue
							}
							
							if(!TrieKeyExists(g_tFormatDefinitions, eItem[DATA2]))
							{
								log_config_error(iLine, "Format definition ^"%s^" doesn't exist.", eItem[DATA2])
								continue
							}
							
							eItem[INFO_TYPE] = get_info_type(szKey)
							
							if(invalid_info_type(eItem[INFO_TYPE], szKey, iLine))
								continue
							
							ArrayPushArray(g_aSayFormats, eItem)
							g_iSayFormats++
						}
					}
				}
			}
		}
		
		fclose(iFilePointer)
		
		if(g_eSettings[CHAT_LOG_FILE][0])
		{
			if(!TrieKeyExists(g_tFormatDefinitions, g_eSettings[CHAT_LOG_SAY_FORMAT]))
			{
				g_eSettings[CHAT_LOG_FILE][0] = EOS
				format_doesnt_exist(iChatLogSayLine, g_eSettings[CHAT_LOG_SAY_FORMAT])
			}
			
			if(!TrieKeyExists(g_tFormatDefinitions, g_eSettings[CHAT_LOG_TEAM_FORMAT]))
			{
				g_eSettings[CHAT_LOG_FILE][0] = EOS
				format_doesnt_exist(iChatLogTeamLine, g_eSettings[CHAT_LOG_TEAM_FORMAT])
			}
		}
		
		if(g_bFileWasRead)
		{
			new iPlayers[32], iPnum
			get_players(iPlayers, iPnum)
			
			for(new i; i < iPnum; i++)
				UpdateData(iPlayers[i])
		}
		
		g_bFileWasRead = true
	}
}

public Cmd_Reload(id, iLevel, iCid)
{
	if(!cmd_access(id, iLevel, iCid, 1))
		return PLUGIN_HANDLED
		
	ReadFile()
	client_print(id, print_console, "Reload successful!")
	log_amx("%s [ %s | %s ] has reloaded the configuration file.", g_ePlayerData[id][PDATA_NAME], g_ePlayerData[id][PDATA_IP], g_ePlayerData[id][PDATA_STEAM])
	return PLUGIN_HANDLED
}

public Hook_Say(id)
{
	if(!is_user_connected(id))
		return PLUGIN_HANDLED
		
	static szArgs[WRITTEN_MESSAGE_SIZE]
	read_args(szArgs, charsmax(szArgs)); remove_quotes(szArgs)
	CC_RemoveColors(szArgs, charsmax(szArgs))
	
	static szFirstChar[2]
	szFirstChar[0] = szArgs[0]
	
	if(!szArgs[0] || TrieKeyExists(g_tBlockFirst, szFirstChar))
		return PLUGIN_HANDLED
		
	static iFlags
	iFlags = get_user_flags(id)
	
	if(g_ePlayerData[id][PDATA_ADMIN_FLAGS] != iFlags)
	{
		UpdateData(id)
		g_ePlayerData[id][PDATA_ADMIN_FLAGS] = iFlags
	}
		
	static szCommand[5]
	read_argv(0, szCommand, charsmax(szCommand))
	
	static szMessage[FULL_MESSAGE_SIZE + 32], szSound[128], iPlayers[32], iPnum, bool:bTeam, iAlive, CsTeams:iTeam
	bTeam = szCommand[3] == '_'
	iAlive = is_user_alive(id)
	iTeam = cs_get_user_team(id)
	
	if(bTeam && g_eSettings[SAY_TEAM_SOUND][0])
		copy(szSound, charsmax(szSound), g_eSettings[SAY_TEAM_SOUND])
	else if(!bTeam && g_eSettings[SAY_SOUND][0])
		copy(szSound, charsmax(szSound), g_eSettings[SAY_SOUND])
	else szSound[0] = EOS
	
	apply_replacements(g_ePlayerData[id][bTeam ? PDATA_SAY_TEAM_FORMAT : PDATA_SAY_FORMAT], id, iAlive, iTeam, szArgs, szMessage, charsmax(szMessage))
	get_players(iPlayers, iPnum, "ch")
	
	if(g_eSettings[ALL_CHAT] == ALLCHAT_SEE_TEAM)
	{	
		CC_SendMatched(0, id, szMessage)
		
		if(szSound[0])
			client_cmd(0, "spk ^"%s^"", szSound)
	}
	else
	{
		static iPlayer, i
		
		for(i = 0; i < iPnum; i++)
		{
			iPlayer = iPlayers[i]
			
			if(g_ePlayerData[iPlayer][PDATA_ADMIN_LISTEN] || (bTeam && iTeam == cs_get_user_team(iPlayer) && iAlive == is_user_alive(iPlayer)) || (!bTeam && (g_eSettings[ALL_CHAT] == 1 || iAlive == is_user_alive(iPlayer))))
			{
				CC_SendMatched(iPlayer, id, szMessage)
				
				if(szSound[0])
					client_cmd(iPlayer, "spk ^"%s^"", szSound)
			}
		}
	}
	
	if(g_eSettings[CHAT_LOG_FILE][0])
	{
		apply_replacements(g_eSettings[bTeam ? CHAT_LOG_TEAM_FORMAT : CHAT_LOG_SAY_FORMAT], id, iAlive, iTeam, szArgs, szMessage, charsmax(szMessage))
		log_to_file(g_eSettings[CHAT_LOG_FILE], szMessage)
	}
	
	return PLUGIN_HANDLED
}

apply_replacements(const szFormat[], const id, const iAlive, const CsTeams:iTeam, const szArgs[], szMessage[], const iLen)
{
	static szPlaceHolder[PLACEHOLDER_LENGTH]
	TrieGetString(g_tFormatDefinitions, szFormat, szMessage, iLen)
	
	#if defined ARG_ADMIN_PREFIX
	if(g_ePlayerData[id][PDATA_PREFIX_ENABLED])
		replace_all(szMessage, iLen, ARG_ADMIN_PREFIX, g_ePlayerData[id][PDATA_PREFIX])
	else
		replace_all(szMessage, iLen, ARG_ADMIN_PREFIX, "")
	#endif
	
	#if defined ARG_DEAD_PREFIX
	replace_all(szMessage, iLen, ARG_DEAD_PREFIX, g_eSettings[iAlive ? ALIVE_PREFIX : DEAD_PREFIX])
	#endif
	
	#if defined ARG_TEAM
	replace_all(szMessage, iLen, ARG_TEAM, g_eSettings[iTeam == CS_TEAM_CT ? TEAM_PREFIX_CT : iTeam == CS_TEAM_T ? TEAM_PREFIX_T : TEAM_PREFIX_SPEC])
	#endif
	
	#if defined ARG_NAME
	replace_all(szMessage, iLen, ARG_NAME, g_ePlayerData[id][PDATA_NAME])
	#endif
	
	#if defined ARG_CUSTOM_NAME
	replace_all(szMessage, iLen, ARG_CUSTOM_NAME, g_ePlayerData[id][g_ePlayerData[id][PDATA_CUSTOM_NAME_ENABLED] ? PDATA_CUSTOM_NAME : PDATA_NAME])
	#endif
	
	#if defined ARG_IP
	replace_all(szMessage, iLen, ARG_IP, g_ePlayerData[id][PDATA_IP])
	#endif
	
	#if defined ARG_STEAM
	replace_all(szMessage, iLen, ARG_STEAM, g_ePlayerData[id][PDATA_STEAM])
	#endif
	
	#if defined ARG_USERID
	replace_all(szMessage, iLen, ARG_USERID, g_ePlayerData[id][PDATA_USERID])
	#endif
	
	#if defined ARG_CHAT_COLOR
	if(g_ePlayerData[id][PDATA_CHAT_COLOR_ENABLED])
		replace_all(szMessage, iLen, ARG_CHAT_COLOR, g_ePlayerData[id][PDATA_CHAT_COLOR])
	else
		replace_all(szMessage, iLen, ARG_CHAT_COLOR, "")
	#endif
	
	#if defined ARG_TIME
	if(has_argument(szMessage, ARG_TIME))
	{
		get_time(g_eSettings[FORMAT_TIME], szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_TIME, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_CURRENT_XP
	if(g_bRankSystem && has_argument(szMessage, ARG_CURRENT_XP))
	{
		num_to_str(crxranks_get_user_xp(id), szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_CURRENT_XP, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_NEXT_XP
	if(g_bRankSystem && has_argument(szMessage, ARG_NEXT_XP))
	{
		num_to_str(crxranks_get_user_next_xp(id), szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_NEXT_XP, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_LEVEL
	if(g_bRankSystem && has_argument(szMessage, ARG_LEVEL))
	{
		num_to_str(crxranks_get_user_level(id), szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_LEVEL, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_NEXT_LEVEL
	if(g_bRankSystem && has_argument(szMessage, ARG_NEXT_LEVEL))
	{
		num_to_str(crxranks_get_user_next_level(id), szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_NEXT_LEVEL, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_RANK
	if(g_bRankSystem && has_argument(szMessage, ARG_RANK))
	{
		crxranks_get_user_rank(id, szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_RANK, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_NEXT_RANK
	if(g_bRankSystem && has_argument(szMessage, ARG_NEXT_RANK))
	{
		crxranks_get_user_next_rank(id, szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_NEXT_RANK, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_HEALTH
	if(has_argument(szMessage, ARG_HEALTH))
	{
		num_to_str(iAlive ? get_user_health(id) : 0, szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_HEALTH, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_ARMOR
	if(has_argument(szMessage, ARG_ARMOR))
	{
		num_to_str(iAlive ? get_user_armor(id) : 0, szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_ARMOR, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_FRAGS
	if(has_argument(szMessage, ARG_FRAGS))
	{
		num_to_str(get_user_frags(id), szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_FRAGS, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_DEATHS
	if(has_argument(szMessage, ARG_DEATHS))
	{
		num_to_str(cs_get_user_deaths(id), szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_DEATHS, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_CITY
	if(has_argument(szMessage, ARG_CITY))
	{
		geoip_city(g_ePlayerData[id][PDATA_IP], szPlaceHolder, charsmax(szPlaceHolder))
		check_validity(szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_CITY, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_COUNTRY
	if(has_argument(szMessage, ARG_COUNTRY))
	{
		#if defined geoip_country_ex
		geoip_country_ex(g_ePlayerData[id][PDATA_IP], szPlaceHolder, charsmax(szPlaceHolder))
		#else
		geoip_country(g_ePlayerData[id][PDATA_IP], szPlaceHolder, charsmax(szPlaceHolder))
		#endif
		
		check_validity(szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_COUNTRY, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_COUNTRY_CODE
	if(has_argument(szMessage, ARG_COUNTRY_CODE))
	{
		new szCountryCode[3]
		
		#if defined geoip_code2_ex
		geoip_code2_ex(g_ePlayerData[id][PDATA_IP], szCountryCode)
		#else
		geoip_code2(g_ePlayerData[id][PDATA_IP], szCountryCode)
		#endif
		
		check_validity(szCountryCode, charsmax(szCountryCode))
		replace_all(szMessage, iLen, ARG_COUNTRY_CODE, szCountryCode)
	}
	#endif
	
	#if defined ARG_CONTINENT
	if(has_argument(szMessage, ARG_CONTINENT))
	{
		geoip_continent_name(g_ePlayerData[id][PDATA_IP], szPlaceHolder, charsmax(szPlaceHolder))
		check_validity(szPlaceHolder, charsmax(szPlaceHolder))
		replace_all(szMessage, iLen, ARG_CONTINENT, szPlaceHolder)
	}
	#endif
	
	#if defined ARG_CONTINENT_CODE
	if(has_argument(szMessage, ARG_CONTINENT_CODE))
	{
		new szContinentCode[3]
		geoip_continent_code(g_ePlayerData[id][PDATA_IP], szContinentCode)
		check_validity(szContinentCode, charsmax(szContinentCode))
		replace_all(szMessage, iLen, ARG_CONTINENT_CODE, szContinentCode)
	}
	#endif
	
	replace_all(szMessage, iLen, "  ", " ")
	
	#if defined ARG_MESSAGE
	replace_all(szMessage, iLen, ARG_MESSAGE, szArgs)
	#endif
	
	trim(szMessage)
}

stock bool:has_argument(const szMessage[], const szArgument[])
	return contain(szMessage, szArgument) != -1

stock check_validity(szText[], const iLen)
{
	if(!szText[0])
		copy(szText, iLen, g_eSettings[ERROR_TEXT])
}

bool:invalid_info_type(const iInfoType, const szInfoType[], const iLine)
{
	if(iInfoType == INFOTYPE_NONE)
	{
		log_config_error(iLine, "Invalid info type: %s", szInfoType)
		return true
	}
	
	if(!g_bRankSystem && iInfoType == INFOTYPE_LEVEL)
	{
		log_config_error(iLine, "Can't use info type ^"%s^" because OciXCrom's Rank System isn't running.", szInfoType)
		return true
	}
	
	return false
}

bool:meets_requirements(const id, const iInfoType, const szInfo[])
{
	switch(iInfoType)
	{
		case INFOTYPE_FLAG:
		{
			static iFlags
			iFlags = read_flags(szInfo)
			
			if(g_ePlayerData[id][PDATA_ADMIN_FLAGS] & iFlags == iFlags)
				return true
		}
		case INFOTYPE_NAME:
		{
			if(equali(g_ePlayerData[id][PDATA_NAME], szInfo))
				return true
		}
		case INFOTYPE_IP:
		{
			if(equal(g_ePlayerData[id][PDATA_IP], szInfo))
				return true
		}
		case INFOTYPE_STEAM:
		{
			if(equal(g_ePlayerData[id][PDATA_STEAM], szInfo))
				return true
		}
		case INFOTYPE_ANY_FLAG:
		{
			if(g_ePlayerData[id][PDATA_ADMIN_FLAGS] & read_flags(szInfo))
				return true
		}
		case INFOTYPE_NO_PREFIX:
		{
			if(!g_ePlayerData[id][PDATA_PREFIX][0] || !g_ePlayerData[id][PDATA_PREFIX_ENABLED])
				return true
		}
		case INFOTYPE_LEVEL:
		{
			if(crxranks_get_user_level(id) >= str_to_num(szInfo))
				return true
		}
	}
	
	return false
}

log_config_error(const iLine, const szText[], any:...)
{
	static szError[192]
	vformat(szError, charsmax(szError), szText, 3)
	log_to_file(ERROR_FILE, "Line %i: %s", iLine, szError)
}

format_doesnt_exist(const iLine, const szFormat[])
	log_config_error(iLine, "Format definition ^"%s^" doesn't exist.", szFormat)

get_info_type(const szText[])
{
	static iInfoType
	iInfoType = INFOTYPE_NONE
	
	switch(szText[0])
	{
		case 'F', 'f': iInfoType = INFOTYPE_FLAG
		case 'N', 'n':
		{
			switch(szText[1])
			{
				case 'A', 'a': iInfoType = INFOTYPE_NAME
				case 'O', 'o': iInfoType = INFOTYPE_NO_PREFIX
			}
		}
		case 'I', 'i': iInfoType = INFOTYPE_IP
		case 'S', 's': iInfoType = INFOTYPE_STEAM
		case 'A', 'a': iInfoType = INFOTYPE_ANY_FLAG
		case 'L', 'l': iInfoType = INFOTYPE_LEVEL
	}
	
	return iInfoType
}

public plugin_natives()
{
	register_library("chatmanager")
	register_native("cm_get_admin_listen_flags", 		"_cm_get_admin_listen_flags")
	register_native("cm_get_chat_color_by_num", 		"_cm_get_chat_color_by_num")
	register_native("cm_get_prefix_by_num", 			"_cm_get_prefix_by_num")
	register_native("cm_get_user_chat_color", 			"_cm_get_user_chat_color")
	register_native("cm_get_user_chat_color_status", 	"_cm_get_user_chat_color_status")
	register_native("cm_get_user_custom_name",			"_cm_get_user_custom_name")
	register_native("cm_get_user_custom_name_status",	"_cm_get_user_custom_name_status")
	register_native("cm_get_user_prefix", 				"_cm_get_user_prefix")
	register_native("cm_get_user_prefix_status", 		"_cm_get_user_prefix_status")
	register_native("cm_has_user_admin_listen", 		"_cm_has_user_admin_listen")
	register_native("cm_reload_config_file", 			"_cm_reload_config_file")
	register_native("cm_set_user_chat_color", 			"_cm_set_user_chat_color")
	register_native("cm_set_user_chat_color_status", 	"_cm_set_user_chat_color_status")
	register_native("cm_set_user_custom_name_status", 	"_cm_set_user_custom_name_status")
	register_native("cm_set_user_prefix", 				"_cm_set_user_prefix")
	register_native("cm_set_user_prefix_status", 		"_cm_set_user_prefix_status")
	register_native("cm_set_user_say_format", 			"_cm_set_user_say_format")
	register_native("cm_total_chat_colors", 			"_cm_total_chat_colors")
	register_native("cm_total_prefixes", 				"_cm_total_chat_colors")
	register_native("cm_total_say_formats", 			"_cm_total_say_formats")
	register_native("cm_update_player_data", 			"_cm_update_player_data")
	set_native_filter("native_filter")
}
	
public native_filter(const szNative[], id, iTrap)
{
	if(!iTrap)
	{
		if(equal(szNative, "crxranks_get_user_level") || equal(szNative, "crxranks_user_level_updated"))
			return PLUGIN_HANDLED
		
		#if defined ARG_XP
		if(equal(szNative, "crxranks_get_user_xp"))
			return PLUGIN_HANDLED
		#endif
		
		#if defined ARG_NEXT_XP
		if(equal(szNative, "crxranks_get_user_next_xp"))
			return PLUGIN_HANDLED
		#endif
		
		#if defined ARG_NEXT_LEVEL
		if(equal(szNative, "crxranks_get_user_next_level"))
			return PLUGIN_HANDLED
		#endif
		
		#if defined ARG_RANK
		if(equal(szNative, "crxranks_get_user_rank"))
			return PLUGIN_HANDLED
		#endif
		
		#if defined ARG_NEXT_RANK
		if(equal(szNative, "crxranks_get_user_next_rank"))
			return PLUGIN_HANDLED
		#endif
	}
	
	return PLUGIN_CONTINUE
}

public _cm_get_admin_listen_flags(iPlugin, iParams)
	set_string(1, g_eSettings[ADMIN_LISTEN_FLAGS], get_param(2))
	
public _cm_get_chat_color_by_num(iPlugin, iParams)
{
	new iNum = get_param(1)
	
	if(iNum < 0 || iNum >= g_iChatColors)
		return 0
	
	new szColor[32]
	ArrayGetString(g_aChatColors, iNum, szColor, charsmax(szColor))
	set_string(2, szColor, get_param(3))
	return 1
}

public _cm_get_prefix_by_num(iPlugin, iParams)
{
	new iNum = get_param(1)
	
	if(iNum < 0 || iNum >= g_iAdminPrefixes)
		return 0
	
	new szPrefix[32]
	ArrayGetString(g_aAdminPrefixes, iNum, szPrefix, charsmax(szPrefix))
	set_string(2, szPrefix, get_param(3))
	return 1
}
	
public _cm_get_user_chat_color(iPlugin, iParams)
	set_string(2, g_ePlayerData[get_param(1)][PDATA_CHAT_COLOR], get_param(3))

public bool:_cm_get_user_chat_color_status(iPlugin, iParams)
	return g_ePlayerData[get_param(1)][PDATA_CHAT_COLOR_ENABLED]

public _cm_get_user_custom_name(iPlugin, iParams)
	set_string(2, g_ePlayerData[get_param(1)][PDATA_CUSTOM_NAME], get_param(3))
	
public bool:_cm_get_user_custom_name_status(iPlugin, iParams)
	return g_ePlayerData[get_param(1)][PDATA_CUSTOM_NAME_ENABLED]
	
public _cm_get_user_prefix(iPlugin, iParams)
	set_string(2, g_ePlayerData[get_param(1)][PDATA_PREFIX], get_param(3))

public bool:_cm_get_user_prefix_status(iPlugin, iParams)
	return g_ePlayerData[get_param(1)][PDATA_PREFIX_ENABLED]

public bool:_cm_has_user_admin_listen(iPlugin, iParams)
	return g_ePlayerData[get_param(1)][PDATA_ADMIN_LISTEN]
	
public _cm_reload_config_file(iPlugin, iParams)
	ReadFile()
	
public _cm_set_user_chat_color(iPlugin, iParams)
	get_string(2, g_ePlayerData[get_param(1)][PDATA_CHAT_COLOR], charsmax(g_ePlayerData[][PDATA_CHAT_COLOR]))
	
public _cm_set_user_chat_color_status(iPlugin, iParams)
	g_ePlayerData[get_param(1)][PDATA_CHAT_COLOR_ENABLED] = _:get_param(2)

public _cm_set_user_custom_name_status(iPlugin, iParams)
	g_ePlayerData[get_param(1)][PDATA_CUSTOM_NAME_ENABLED] = _:get_param(2)
	
public _cm_set_user_prefix(iPlugin, iParams)
	get_string(2, g_ePlayerData[get_param(1)][PDATA_PREFIX], charsmax(g_ePlayerData[][PDATA_PREFIX]))
	
public _cm_set_user_prefix_status(iPlugin, iParams)
{
	static id; id = get_param(1)
	g_ePlayerData[id][PDATA_PREFIX_ENABLED] = _:get_param(2)
	
	if(get_param(3))
		UpdateData(id)
}

public _cm_set_user_say_format(iPlugin, iParams)
{
	static szFormat[32], id
	id = get_param(1)
	
	get_string(2, szFormat, charsmax(szFormat))
	
	if(TrieKeyExists(g_tFormatDefinitions, szFormat))
		copy(g_ePlayerData[id][PDATA_SAY_FORMAT], charsmax(g_ePlayerData[][PDATA_SAY_FORMAT]), szFormat)
	else return 0
	
	get_string(3, szFormat, charsmax(szFormat))
	
	if(TrieKeyExists(g_tFormatDefinitions, szFormat))
		copy(g_ePlayerData[id][PDATA_SAY_TEAM_FORMAT], charsmax(g_ePlayerData[][PDATA_SAY_TEAM_FORMAT]), szFormat)
	else return 0
	
	return 1
}
	
public _cm_total_chat_colors(iPlugin, iParams)
	return g_iChatColors
	
public _cm_total_prefixes(iPlugin, iParams)
	return g_iAdminPrefixes
	
public _cm_total_say_formats(iPlugin, iParams)
	return g_iSayFormats
	
public _cm_update_player_data(iPlugin, iParams)
	UpdateData(get_param(1))
Вторият е Knife Models:

Код за потвърждение: Избери целия код

#include <amxmodx>
#include <amxmisc>
#include <crxknives_const>
#include <cromchat>
#include <fakemeta>
#include <hamsandwich>
#include <nvault>

native crxranks_get_max_levels()
native crxranks_get_rank_by_level(level, buffer[], len)
native crxranks_get_user_level(id)
native crxranks_get_user_xp(id)

new const g_szNatives[][] =
{
	"crxranks_get_max_levels",
	"crxranks_get_rank_by_level",
	"crxranks_get_user_level",
	"crxranks_get_user_xp"
}

#if !defined m_pPlayer
const m_pPlayer = 41
#endif

#if !defined client_disconnected
	#define client_disconnected client_disconnect
#endif

new const PLUGIN_VERSION[] = "3.0"

#if !defined MAX_AUTHID_LENGTH
const MAX_AUTHID_LENGTH = 35
#endif

#if !defined MAX_NAME_LENGTH
const MAX_NAME_LENGTH = 32
#endif

#if !defined MAX_PLAYERS
const MAX_PLAYERS = 32
#endif

enum
{
	SOUND_NONE = 0,
	SOUND_DEPLOY,
	SOUND_HIT,
	SOUND_HITWALL,
	SOUND_SLASH,
	SOUND_STAB
}

enum _:Knives
{
	NAME[MAX_NAME_LENGTH],
	V_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
	P_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
	DEPLOY_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	HIT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	HITWALL_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	SLASH_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	STAB_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	SELECT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	FLAG,
	LEVEL,
	XP,
	SELECT_MESSAGES_NUM,
	bool:SHOW_RANK,
	bool:HAS_CUSTOM_SOUND,
	Array:SELECT_MESSAGES,
	Trie:ATTRIBUTES
}

enum _:CvarsReg
{
	cvar_km_open_at_spawn,
	cvar_km_save_choice,
	cvar_km_only_dead,
	cvar_km_select_message,
	cvar_km_knife_only_skills
}

enum _:Cvars
{
	km_open_at_spawn,
	km_save_choice,
	km_only_dead,
	km_select_message,
	km_knife_only_skills
}

new Array:g_aKnives,
	bool:g_bFirstTime[MAX_PLAYERS + 1],
	bool:g_bRankSystem,
	bool:g_bGetLevel,
	bool:g_bGetXP,
	g_eCvars[Cvars],
	g_eCvarsReg[CvarsReg],
	g_eKnife[MAX_PLAYERS + 1][Knives],
	g_szAuth[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH],
	g_iKnife[MAX_PLAYERS + 1],
	g_fwdKnifeUpdated,
	g_fwdAttemptChange,
	g_iMenuFlags,
	g_iKnivesNum,
	g_iCallback,
	g_iVault

public plugin_init()
{
	register_plugin("Knife Models", PLUGIN_VERSION, "OciXCrom")
	register_cvar("CRXKnifeModels", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED)

	if(!g_iKnivesNum)
	{
		set_fail_state("No knives found in the configuration file.")
	}

	register_dictionary("KnifeModels.txt")

	RegisterHam(Ham_Spawn, "player", "OnPlayerSpawn", 1)
	register_forward(FM_EmitSound,	"OnEmitSound")
	RegisterHam(Ham_Item_Deploy, "weapon_knife", "OnSelectKnife", 1)

	register_clcmd("say /knife",       "Cmd_Knife")
	register_clcmd("say_team /knife",  "Cmd_Knife")
	register_clcmd("crxknives_select", "Cmd_Select", _, "<knife id>")

	g_fwdKnifeUpdated  = CreateMultiForward("crxknives_knife_updated",  ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
	g_fwdAttemptChange = CreateMultiForward("crxknives_attempt_change", ET_STOP,   FP_CELL, FP_CELL)

	g_iCallback = menu_makecallback("CheckKnifeAccess")

	g_eCvarsReg[cvar_km_open_at_spawn]     = register_cvar("km_open_at_spawn",     "0")
	g_eCvarsReg[cvar_km_save_choice]       = register_cvar("km_save_choice",       "1")
	g_eCvarsReg[cvar_km_only_dead]         = register_cvar("km_only_dead",         "0")
	g_eCvarsReg[cvar_km_select_message]    = register_cvar("km_select_message",    "1")
	g_eCvarsReg[cvar_km_knife_only_skills] = register_cvar("km_knife_only_skills", "1")
}

public plugin_precache()
{
	if(LibraryExists("crxranks", LibType_Library))
	{
		g_bRankSystem = true
	}

	g_aKnives = ArrayCreate(Knives)
	ReadFile()
}

public plugin_cfg()
{
	g_eCvars[km_save_choice]       = get_pcvar_num(g_eCvarsReg[cvar_km_save_choice])
	g_eCvars[km_open_at_spawn]     = get_pcvar_num(g_eCvarsReg[cvar_km_open_at_spawn])
	g_eCvars[km_only_dead]         = get_pcvar_num(g_eCvarsReg[cvar_km_only_dead])
	g_eCvars[km_select_message]    = get_pcvar_num(g_eCvarsReg[cvar_km_select_message])
	g_eCvars[km_knife_only_skills] = get_pcvar_num(g_eCvarsReg[cvar_km_knife_only_skills])

	if(g_eCvars[km_save_choice])
	{
		g_iVault = nvault_open("KnifeModels")
	}
}

public plugin_end()
{
	for(new eKnife[Knives], i; i < g_iKnivesNum; i++)
	{
		ArrayGetArray(g_aKnives, i, eKnife)
		ArrayDestroy(eKnife[SELECT_MESSAGES])
		TrieDestroy(eKnife[ATTRIBUTES])
	}

	ArrayDestroy(g_aKnives)

	if(g_eCvars[km_save_choice])
	{
		nvault_close(g_iVault)
	}
}

ReadFile()
{
	new szFilename[256]
	get_configsdir(szFilename, charsmax(szFilename))
	add(szFilename, charsmax(szFilename), "/KnifeModels.ini")
	new iFilePointer = fopen(szFilename, "rt")

	if(iFilePointer)
	{
		new szData[160], szKey[32], szValue[128], szSound[128], iMaxLevels
		new eKnife[Knives], bool:bCustom

		if(g_bRankSystem)
		{
			iMaxLevels = crxranks_get_max_levels()
		}

		while(!feof(iFilePointer))
		{
			fgets(iFilePointer, szData, charsmax(szData))
			trim(szData)

			switch(szData[0])
			{
				case EOS, '#', ';': continue
				case '[':
				{
					if(szData[strlen(szData) - 1] == ']')
					{
						if(g_iKnivesNum)
						{
							push_knife(eKnife)
						}

						g_iKnivesNum++
						replace(szData, charsmax(szData), "[", "")
						replace(szData, charsmax(szData), "]", "")
						copy(eKnife[NAME], charsmax(eKnife[NAME]), szData)

						eKnife[V_MODEL][0] = EOS
						eKnife[P_MODEL][0] = EOS
						eKnife[DEPLOY_SOUND][0] = EOS
						eKnife[HIT_SOUND][0] = EOS
						eKnife[HITWALL_SOUND][0] = EOS
						eKnife[SLASH_SOUND][0] = EOS
						eKnife[STAB_SOUND][0] = EOS
						eKnife[SELECT_SOUND][0] = EOS
						eKnife[FLAG] = ADMIN_ALL
						eKnife[HAS_CUSTOM_SOUND] = false
						eKnife[SELECT_MESSAGES_NUM] = 0
						eKnife[SELECT_MESSAGES] = _:ArrayCreate(CRXKNIVES_MAX_MESSAGE_LENGTH)
						eKnife[ATTRIBUTES] = _:TrieCreate()

						if(g_bRankSystem)
						{
							eKnife[LEVEL] = 0
							eKnife[SHOW_RANK] = false
							eKnife[XP] = 0
						}

						static const ATTRIBUTE_NAME[] = "NAME"
						TrieSetString(eKnife[ATTRIBUTES], ATTRIBUTE_NAME, szData)
					}
					else continue
				}
				default:
				{
					strtok(szData, szKey, charsmax(szKey), szValue, charsmax(szValue), '=')
					trim(szKey); trim(szValue)
					bCustom = true

					TrieSetString(eKnife[ATTRIBUTES], szKey, szValue)

					if(equal(szKey, "FLAG"))
					{
						eKnife[FLAG] = read_flags(szValue)
						g_iMenuFlags |= eKnife[FLAG]
					}
					else if(equal(szKey, "LEVEL") && g_bRankSystem)
					{
						eKnife[LEVEL] = clamp(str_to_num(szValue), 0, iMaxLevels)

						if(!g_bGetLevel)
						{
							g_bGetLevel = true
						}
					}
					else if(equal(szKey, "SHOW_RANK") && g_bRankSystem)
					{
						eKnife[SHOW_RANK] = _:clamp(str_to_num(szValue), false, true)
					}
					else if(equal(szKey, "XP") && g_bRankSystem)
					{
						eKnife[XP] = _:clamp(str_to_num(szValue), 0)

						if(!g_bGetXP)
						{
							g_bGetXP = true
						}
					}
					else if(equal(szKey, "V_MODEL"))
					{
						copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), szValue)
					}
					else if(equal(szKey, "P_MODEL"))
					{
						copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), szValue)
					}
					else if(equal(szKey, "DEPLOY_SOUND"))
					{
						copy(eKnife[DEPLOY_SOUND], charsmax(eKnife[DEPLOY_SOUND]), szValue)
					}
					else if(equal(szKey, "HIT_SOUND"))
					{
						copy(eKnife[HIT_SOUND], charsmax(eKnife[HIT_SOUND]), szValue)
					}
					else if(equal(szKey, "HITWALL_SOUND"))
					{
						copy(eKnife[HITWALL_SOUND], charsmax(eKnife[HITWALL_SOUND]), szValue)
					}
					else if(equal(szKey, "SLASH_SOUND"))
					{
						copy(eKnife[SLASH_SOUND], charsmax(eKnife[SLASH_SOUND]), szValue)
					}
					else if(equal(szKey, "STAB_SOUND"))
					{
						copy(eKnife[STAB_SOUND], charsmax(eKnife[STAB_SOUND]), szValue)
					}
					else if(equal(szKey, "SELECT_SOUND"))
					{
						bCustom = false
						copy(eKnife[SELECT_SOUND], charsmax(eKnife[SELECT_SOUND]), szValue)
					}
					else if(equal(szKey, "SELECT_MESSAGE"))
					{
						ArrayPushString(eKnife[SELECT_MESSAGES], szValue)
						eKnife[SELECT_MESSAGES_NUM]++
					}
					else continue

					static const szModelArg[] = "_MODEL"
					static const szSoundArg[] = "_SOUND"

					if(contain(szKey, szModelArg) != -1)
					{
						if(!file_exists(szValue))
						{
							log_amx("ERROR: model ^"%s^" not found!", szValue)
						}
						else
						{
							precache_model(szValue)
						}
					}
					else if(contain(szKey, szSoundArg) != -1)
					{
						formatex(szSound, charsmax(szSound), "sound/%s", szValue)

						if(!file_exists(szSound))
						{
							log_amx("ERROR: sound ^"%s^" not found!", szSound)
						}
						else
						{
							precache_sound(szValue)
						}

						if(bCustom)
						{
							eKnife[HAS_CUSTOM_SOUND] = true
						}
					}
				}
			}
		}

		if(g_iKnivesNum)
		{
			push_knife(eKnife)
		}

		fclose(iFilePointer)
	}
}

public client_connect(id)
{
	g_bFirstTime[id] = true
	ArrayGetArray(g_aKnives, 0, g_eKnife[id])
	g_iKnife[id] = 0

	new iReturn
	ExecuteForward(g_fwdKnifeUpdated, iReturn, id, g_iKnife[id], true)

	if(g_eCvars[km_save_choice])
	{
		get_user_authid(id, g_szAuth[id], charsmax(g_szAuth[]))
		use_vault(id, false)
	}
}

public client_disconnected(id)
{
	if(g_eCvars[km_save_choice])
	{
		use_vault(id, true)
	}
}

public OnEmitSound(id, iChannel, const szSample[])
{
	if(!is_user_connected(id) || !g_eKnife[id][HAS_CUSTOM_SOUND] || !is_knife_sound(szSample))
	{
		return FMRES_IGNORED
	}

	switch(detect_knife_sound(szSample))
	{
		case SOUND_DEPLOY: 		if(g_eKnife[id][DEPLOY_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][DEPLOY_SOUND][0]);      return FMRES_SUPERCEDE; }
		case SOUND_HIT: 		if(g_eKnife[id][HIT_SOUND][0]) 			{ play_knife_sound(id, g_eKnife[id][HIT_SOUND][0]);         return FMRES_SUPERCEDE; }
		case SOUND_HITWALL:		if(g_eKnife[id][HITWALL_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][HITWALL_SOUND][0]);     return FMRES_SUPERCEDE; }
		case SOUND_SLASH: 		if(g_eKnife[id][SLASH_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][SLASH_SOUND][0]);       return FMRES_SUPERCEDE; }
		case SOUND_STAB: 		if(g_eKnife[id][STAB_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][STAB_SOUND][0]);        return FMRES_SUPERCEDE; }
	}

	return FMRES_IGNORED
}

public Cmd_Knife(id)
{
	if(g_eCvars[km_only_dead] && is_user_alive(id))
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_ONLY_DEAD")
		return PLUGIN_HANDLED
	}

	static eKnife[Knives]
	new szTitle[128], szItem[128], iLevel, iXP
	formatex(szTitle, charsmax(szTitle), "%L", id, "KM_MENU_TITLE")

	if(g_bGetLevel)
	{
		iLevel = crxranks_get_user_level(id)
	}

	if(g_bGetXP)
	{
		iXP = crxranks_get_user_xp(id)
	}

	new iMenu = menu_create(szTitle, "MenuHandler")

	for(new iFlags = get_user_flags(id), i; i < g_iKnivesNum; i++)
	{
		ArrayGetArray(g_aKnives, i, eKnife)
		copy(szItem, charsmax(szItem), eKnife[NAME])

		if(g_bRankSystem)
		{
			if(eKnife[LEVEL] && iLevel < eKnife[LEVEL])
			{
				if(eKnife[SHOW_RANK])
				{
					static szRank[32]
					crxranks_get_rank_by_level(eKnife[LEVEL], szRank, charsmax(szRank))
					format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_RANK", szRank)
				}
				else
				{
					format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_LEVEL", eKnife[LEVEL])
				}
			}

			if(eKnife[XP] && iXP < eKnife[XP])
			{
				format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_XP", eKnife[XP])
			}
		}

		if(eKnife[FLAG] != ADMIN_ALL && !(iFlags & eKnife[FLAG]))
		{
			format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_VIP_ONLY")
		}

		if(g_iKnife[id] == i)
		{
			format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_SELECTED")
		}

		menu_additem(iMenu, szItem, eKnife[NAME], eKnife[FLAG], g_iCallback)
	}

	if(menu_pages(iMenu) > 1)
	{
		formatex(szItem, charsmax(szItem), "%s%L", szTitle, id, "KM_MENU_TITLE_PAGE")
		menu_setprop(iMenu, MPROP_TITLE, szItem)
	}

	menu_display(id, iMenu)
	return PLUGIN_HANDLED
}

public Cmd_Select(id, iLevel, iCid)
{
	if(!cmd_access(id, iLevel, iCid, 2))
	{
		return PLUGIN_HANDLED
	}

	if(g_eCvars[km_only_dead] && is_user_alive(id))
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_ONLY_DEAD")
		return PLUGIN_HANDLED
	}

	new szKnife[4]
	read_argv(1, szKnife, charsmax(szKnife))

	new iKnife = str_to_num(szKnife)

	if(!is_knife_valid(iKnife))
	{
		console_print(id, "%l", "KM_INVALID_KNIFE", g_iKnivesNum - 1)
		return PLUGIN_HANDLED
	}

	if(!has_knife_access(id, iKnife))
	{
		console_print(id, "%l", "KM_NO_ACCESS")
		return PLUGIN_HANDLED
	}

	select_knife(id, iKnife)
	return PLUGIN_HANDLED
}

public MenuHandler(id, iMenu, iItem)
{
	if(g_eCvars[km_only_dead] && is_user_alive(id))
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_ONLY_DEAD")
		goto @MENU_DESTROY
	}

	if(!is_user_connected(id))
	{
		goto @MENU_DESTROY
	}

	if(iItem != MENU_EXIT)
	{
		select_knife(id, iItem)
	}

	@MENU_DESTROY:
	menu_destroy(iMenu)
	return PLUGIN_HANDLED
}

select_knife(id, iKnife)
{
	new iReturn
	ExecuteForward(g_fwdAttemptChange, iReturn, id, iKnife)

	if(iReturn == PLUGIN_HANDLED)
	{
		return
	}

	g_iKnife[id] = iKnife
	ArrayGetArray(g_aKnives, iKnife, g_eKnife[id])
	ExecuteForward(g_fwdKnifeUpdated, iReturn, id, iKnife, false)

	if(is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
	{
		refresh_knife_model(id)
	}

	if(g_eCvars[km_select_message])
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_CHAT_SELECTED", g_eKnife[id][NAME])
	}

	if(g_eKnife[id][SELECT_MESSAGES_NUM])
	{
		for(new i; i < g_eKnife[id][SELECT_MESSAGES_NUM]; i++)
		{
			CC_SendMessage(id, "%a", ArrayGetStringHandle(g_eKnife[id][SELECT_MESSAGES], i))
		}
	}

	if(g_eKnife[id][SELECT_SOUND][0])
	{
		play_knife_sound(id, g_eKnife[id][SELECT_SOUND])
	}
}

public CheckKnifeAccess(id, iMenu, iItem)
{
	return ((g_iKnife[id] == iItem) || !has_knife_access(id, iItem)) ? ITEM_DISABLED : ITEM_ENABLED
}

public OnPlayerSpawn(id)
{
	if(is_user_alive(id) && g_eCvars[km_open_at_spawn] && !g_iKnife[id] && g_bFirstTime[id] && (g_iMenuFlags & ADMIN_USER || get_user_flags(id) & g_iMenuFlags))
	{
		g_bFirstTime[id] = false
		Cmd_Knife(id)
	}
}

public OnSelectKnife(iEnt)
{
	new id = get_pdata_cbase(iEnt, m_pPlayer, 4)

	if(is_user_connected(id))
	{
		refresh_knife_model(id)
	}
}

refresh_knife_model(const id)
{
	set_pev(id, pev_viewmodel2, g_eKnife[id][V_MODEL])
	set_pev(id, pev_weaponmodel2, g_eKnife[id][P_MODEL])
}

push_knife(eKnife[Knives])
{
	if(!eKnife[V_MODEL][0])
	{
		copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), CRXKNIVES_DEFAULT_V)
	}

	if(!eKnife[P_MODEL][0])
	{
		copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), CRXKNIVES_DEFAULT_P)
	}

	if(!eKnife[FLAG])
	{
		g_iMenuFlags |= ADMIN_USER
	}

	ArrayPushArray(g_aKnives, eKnife)
}

bool:has_knife_access(const id, const iKnife)
{
	static eKnife[Knives]
	ArrayGetArray(g_aKnives, iKnife, eKnife)

	if(g_bRankSystem)
	{
		if(eKnife[LEVEL] && crxranks_get_user_level(id) < eKnife[LEVEL])
		{
			return false
		}

		if(eKnife[XP] && crxranks_get_user_xp(id) < eKnife[XP])
		{
			return false
		}
	}

	if(eKnife[FLAG] != ADMIN_ALL && !(get_user_flags(id) & eKnife[FLAG]))
	{
		return false
	}

	return true
}

bool:is_knife_sound(const szSample[])
{
	return bool:equal(szSample[8], "kni", 3)
}

detect_knife_sound(const szSample[])
{
	static iSound
	iSound = SOUND_NONE

	if(equal(szSample, "weapons/knife_deploy1.wav"))
	{
		iSound = SOUND_DEPLOY
	}
	else if(equal(szSample[14], "hit", 3))
	{
		iSound = szSample[17] == 'w' ? SOUND_HITWALL : SOUND_HIT
	}
	else if(equal(szSample[14], "sla", 3))
	{
		iSound = SOUND_SLASH
	}
	else if(equal(szSample[14], "sta", 3))
	{
		iSound = SOUND_STAB
	}

	return iSound
}

use_vault(const id, const bool:bSave)
{
	if(bSave)
	{
		new szData[4]
		num_to_str(g_iKnife[id], szData, charsmax(szData))
		nvault_set(g_iVault, g_szAuth[id], szData)
	}
	else
	{
		new iKnife
		iKnife = nvault_get(g_iVault, g_szAuth[id])

		if(!is_knife_valid(iKnife))
		{
			iKnife = 0
		}
		else if(has_knife_access(id, iKnife))
		{
			g_iKnife[id] = iKnife

			new iReturn
			ArrayGetArray(g_aKnives, iKnife, g_eKnife[id])
			ExecuteForward(g_fwdKnifeUpdated, iReturn, id, iKnife, false)

			if(is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
			{
				refresh_knife_model(id)
			}
		}
	}
}

play_knife_sound(const id, const szSound[])
{
	engfunc(EngFunc_EmitSound, id, CHAN_AUTO, szSound, 1.0, ATTN_NORM, 0, PITCH_NORM)
}

bool:is_knife_valid(const iKnife)
{
	return 0 <= iKnife < g_iKnivesNum
}

public plugin_natives()
{
	register_library("crxknives")
	register_native("crxknives_can_use_skill",       "_crxknives_can_use_skill")
	register_native("crxknives_get_attribute_int",   "_crxknives_get_attribute_int")
	register_native("crxknives_get_attribute_float", "_crxknives_get_attribute_float")
	register_native("crxknives_get_attribute_str",   "_crxknives_get_attribute_str")
	register_native("crxknives_get_knives_num",      "_crxknives_get_knives_num")
	register_native("crxknives_get_user_knife",      "_crxknives_get_user_knife")
	register_native("crxknives_has_knife_access",    "_crxknives_has_knife_access")
	register_native("crxknives_is_knife_valid",      "_crxknives_is_knife_valid")
	set_native_filter("native_filter")
}

public native_filter(const szNative[], id, iTrap)
{
	if(!iTrap)
	{
		static i

		for(i = 0; i < sizeof(g_szNatives); i++)
		{
			if(equal(szNative, g_szNatives[i]))
			{
				return PLUGIN_HANDLED
			}
		}
	}

	return PLUGIN_CONTINUE
}

public bool:_crxknives_can_use_skill(iPlugin, iParams)
{
	return !g_eCvars[km_knife_only_skills] || (get_user_weapon(get_param(1)) == CSW_KNIFE)
}

public bool:_crxknives_get_attribute_int(iPlugin, iParams)
{
	static szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
	get_string(2, szAttribute, charsmax(szAttribute))
	id = get_param(1)

	if(!get_param(4))
	{
		if(!is_knife_valid(id))
		{
			return false
		}

		static eKnife[Knives]
		ArrayGetArray(g_aKnives, id, eKnife)

		if(!TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
		{
			return false
		}

		TrieGetString(eKnife[ATTRIBUTES], szAttribute, szValue, charsmax(szValue))
		goto @SET_ATTRIBUTE
	}

	if(!TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
	{
		return false
	}

	TrieGetString(g_eKnife[id][ATTRIBUTES], szAttribute, szValue, charsmax(szValue))

	@SET_ATTRIBUTE:
	set_param_byref(3, str_to_num(szValue))
	return true
}

public bool:_crxknives_get_attribute_float(iPlugin, iParams)
{
	static szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
	get_string(2, szAttribute, charsmax(szAttribute))
	id = get_param(1)

	if(!get_param(4))
	{
		if(!is_knife_valid(id))
		{
			return false
		}

		static eKnife[Knives]
		ArrayGetArray(g_aKnives, id, eKnife)

		if(!TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
		{
			return false
		}

		TrieGetString(eKnife[ATTRIBUTES], szAttribute, szValue, charsmax(szValue))
		goto @SET_ATTRIBUTE
	}

	if(!TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
	{
		return false
	}

	TrieGetString(g_eKnife[id][ATTRIBUTES], szAttribute, szValue, charsmax(szValue))

	@SET_ATTRIBUTE:
	set_float_byref(3, str_to_float(szValue))
	return true
}

public bool:_crxknives_get_attribute_str(iPlugin, iParams)
{
	static szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
	get_string(2, szAttribute, charsmax(szAttribute))
	id = get_param(1)

	if(!get_param(5))
	{
		if(!is_knife_valid(id))
		{
			return false
		}

		static eKnife[Knives]
		ArrayGetArray(g_aKnives, id, eKnife)

		if(!TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
		{
			return false
		}

		TrieGetString(eKnife[ATTRIBUTES], szAttribute, szValue, charsmax(szValue))
		goto @SET_ATTRIBUTE
	}

	if(!TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
	{
		return false
	}

	TrieGetString(g_eKnife[id][ATTRIBUTES], szAttribute, szValue, charsmax(szValue))

	@SET_ATTRIBUTE:
	set_string(3, szValue, get_param(4))
	return true
}

public _crxknives_get_knives_num(iPlugin, iParams)
{
	return g_iKnivesNum
}

public _crxknives_get_user_knife(iPlugin, iParams)
{
	return g_iKnife[get_param(1)]
}

public bool:_crxknives_has_knife_access(iPlugin, iParams)
{
	return has_knife_access(get_param(1), get_param(2))
}

public bool:_crxknives_is_knife_valid(iPlugin, iParams)
{
	return is_knife_valid(get_param(1))
}
Имайте предвид, че съм прикачил и Ранк Системата към менюто с ножовете.

При Knife Models можеш да зададеш някой нож до който имат достъп само играчи с определените флагове записани в KnifeModels.ini ,но каквито и флагове да сложиш, винаги след името на ножа пише: ~ VIP ~

Трябват ми други suffix-ове на ножовете във менюто, според флаговете, които съм записал във ChatManager.ini (например играчите с флаг b например получават prefix - VIP). Ако сложа още флагове, например за ранг "VIP+", в Knife Menu-то си пише пак "~ VIP ~".

Обясних го малко преплетено, но не мога по-добре.
Betrayal stings like salt on a wound.

Аватар
OciXCrom
Извън линия
Администратор
Администратор
Мнения: 7206
Регистриран на: 06 Окт 2016, 19:20
Местоположение: /resetscore
Се отблагодари: 117 пъти
Получена благодарност: 1295 пъти
Обратна връзка:

Свързване на Chat Manager със Knife Menu

Мнение от OciXCrom » 04 Мар 2019, 20:29

Не ми се занимава да ги свързвам и да взима точния префикс от Chat Manager, обаче добавих нова настройка за ножовете - FLAG_SUFFIX - тук можеш да напишеш самия suffix, който ще се показва вместо стандардното ~ VIP ~. Ако не е въведена такава настройка за ножа, отново ще си показва ~ VIP ~.

Пример:

Код за потвърждение: Избери целия код

[My Knife]
FLAG = b
FLAG_SUFFIX = ~ Premium ~

Код за потвърждение: Избери целия код

#include <amxmodx>
#include <amxmisc>
#include <crxknives_const>
#include <cromchat>
#include <fakemeta>
#include <hamsandwich>
#include <nvault>

native crxranks_get_max_levels()
native crxranks_get_rank_by_level(level, buffer[], len)
native crxranks_get_user_level(id)
native crxranks_get_user_xp(id)

new const g_szNatives[][] =
{
	"crxranks_get_max_levels",
	"crxranks_get_rank_by_level",
	"crxranks_get_user_level",
	"crxranks_get_user_xp"
}

#if !defined m_pPlayer
const m_pPlayer = 41
#endif

#if !defined client_disconnected
	#define client_disconnected client_disconnect
#endif

new const PLUGIN_VERSION[] = "3.0+suffix"

#if !defined MAX_AUTHID_LENGTH
const MAX_AUTHID_LENGTH = 35
#endif

#if !defined MAX_NAME_LENGTH
const MAX_NAME_LENGTH = 32
#endif

#if !defined MAX_PLAYERS
const MAX_PLAYERS = 32
#endif

enum
{
	SOUND_NONE = 0,
	SOUND_DEPLOY,
	SOUND_HIT,
	SOUND_HITWALL,
	SOUND_SLASH,
	SOUND_STAB
}

enum _:Knives
{
	NAME[MAX_NAME_LENGTH],
	V_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
	P_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
	DEPLOY_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	HIT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	HITWALL_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	SLASH_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	STAB_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	SELECT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
	FLAG,
	FLAG_SUFFIX[MAX_NAME_LENGTH],
	LEVEL,
	XP,
	SELECT_MESSAGES_NUM,
	bool:SHOW_RANK,
	bool:HAS_CUSTOM_SOUND,
	Array:SELECT_MESSAGES,
	Trie:ATTRIBUTES
}

enum _:CvarsReg
{
	cvar_km_open_at_spawn,
	cvar_km_save_choice,
	cvar_km_only_dead,
	cvar_km_select_message,
	cvar_km_knife_only_skills
}

enum _:Cvars
{
	km_open_at_spawn,
	km_save_choice,
	km_only_dead,
	km_select_message,
	km_knife_only_skills
}

new Array:g_aKnives,
	bool:g_bFirstTime[MAX_PLAYERS + 1],
	bool:g_bRankSystem,
	bool:g_bGetLevel,
	bool:g_bGetXP,
	g_eCvars[Cvars],
	g_eCvarsReg[CvarsReg],
	g_eKnife[MAX_PLAYERS + 1][Knives],
	g_szAuth[MAX_PLAYERS + 1][MAX_AUTHID_LENGTH],
	g_iKnife[MAX_PLAYERS + 1],
	g_fwdKnifeUpdated,
	g_fwdAttemptChange,
	g_iMenuFlags,
	g_iKnivesNum,
	g_iCallback,
	g_iVault

public plugin_init()
{
	register_plugin("Knife Models", PLUGIN_VERSION, "OciXCrom")
	register_cvar("CRXKnifeModels", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED)

	if(!g_iKnivesNum)
	{
		set_fail_state("No knives found in the configuration file.")
	}

	register_dictionary("KnifeModels.txt")

	RegisterHam(Ham_Spawn, "player", "OnPlayerSpawn", 1)
	register_forward(FM_EmitSound,	"OnEmitSound")
	RegisterHam(Ham_Item_Deploy, "weapon_knife", "OnSelectKnife", 1)

	register_clcmd("say /knife",       "Cmd_Knife")
	register_clcmd("say_team /knife",  "Cmd_Knife")
	register_clcmd("crxknives_select", "Cmd_Select", _, "<knife id>")

	g_fwdKnifeUpdated  = CreateMultiForward("crxknives_knife_updated",  ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
	g_fwdAttemptChange = CreateMultiForward("crxknives_attempt_change", ET_STOP,   FP_CELL, FP_CELL)

	g_iCallback = menu_makecallback("CheckKnifeAccess")

	g_eCvarsReg[cvar_km_open_at_spawn]     = register_cvar("km_open_at_spawn",     "0")
	g_eCvarsReg[cvar_km_save_choice]       = register_cvar("km_save_choice",       "1")
	g_eCvarsReg[cvar_km_only_dead]         = register_cvar("km_only_dead",         "0")
	g_eCvarsReg[cvar_km_select_message]    = register_cvar("km_select_message",    "1")
	g_eCvarsReg[cvar_km_knife_only_skills] = register_cvar("km_knife_only_skills", "1")
}

public plugin_precache()
{
	if(LibraryExists("crxranks", LibType_Library))
	{
		g_bRankSystem = true
	}

	g_aKnives = ArrayCreate(Knives)
	ReadFile()
}

public plugin_cfg()
{
	g_eCvars[km_save_choice]       = get_pcvar_num(g_eCvarsReg[cvar_km_save_choice])
	g_eCvars[km_open_at_spawn]     = get_pcvar_num(g_eCvarsReg[cvar_km_open_at_spawn])
	g_eCvars[km_only_dead]         = get_pcvar_num(g_eCvarsReg[cvar_km_only_dead])
	g_eCvars[km_select_message]    = get_pcvar_num(g_eCvarsReg[cvar_km_select_message])
	g_eCvars[km_knife_only_skills] = get_pcvar_num(g_eCvarsReg[cvar_km_knife_only_skills])

	if(g_eCvars[km_save_choice])
	{
		g_iVault = nvault_open("KnifeModels")
	}
}

public plugin_end()
{
	for(new eKnife[Knives], i; i < g_iKnivesNum; i++)
	{
		ArrayGetArray(g_aKnives, i, eKnife)
		ArrayDestroy(eKnife[SELECT_MESSAGES])
		TrieDestroy(eKnife[ATTRIBUTES])
	}

	ArrayDestroy(g_aKnives)

	if(g_eCvars[km_save_choice])
	{
		nvault_close(g_iVault)
	}
}

ReadFile()
{
	new szFilename[256]
	get_configsdir(szFilename, charsmax(szFilename))
	add(szFilename, charsmax(szFilename), "/KnifeModels.ini")
	new iFilePointer = fopen(szFilename, "rt")

	if(iFilePointer)
	{
		new szData[160], szKey[32], szValue[128], szSound[128], iMaxLevels
		new eKnife[Knives], bool:bCustom

		if(g_bRankSystem)
		{
			iMaxLevels = crxranks_get_max_levels()
		}

		while(!feof(iFilePointer))
		{
			fgets(iFilePointer, szData, charsmax(szData))
			trim(szData)

			switch(szData[0])
			{
				case EOS, '#', ';': continue
				case '[':
				{
					if(szData[strlen(szData) - 1] == ']')
					{
						if(g_iKnivesNum)
						{
							push_knife(eKnife)
						}

						g_iKnivesNum++
						replace(szData, charsmax(szData), "[", "")
						replace(szData, charsmax(szData), "]", "")
						copy(eKnife[NAME], charsmax(eKnife[NAME]), szData)

						eKnife[V_MODEL][0] = EOS
						eKnife[P_MODEL][0] = EOS
						eKnife[DEPLOY_SOUND][0] = EOS
						eKnife[HIT_SOUND][0] = EOS
						eKnife[HITWALL_SOUND][0] = EOS
						eKnife[SLASH_SOUND][0] = EOS
						eKnife[STAB_SOUND][0] = EOS
						eKnife[SELECT_SOUND][0] = EOS
						eKnife[FLAG] = ADMIN_ALL
						eKnife[FLAG_SUFFIX][0] = EOS
						eKnife[HAS_CUSTOM_SOUND] = false
						eKnife[SELECT_MESSAGES_NUM] = 0
						eKnife[SELECT_MESSAGES] = _:ArrayCreate(CRXKNIVES_MAX_MESSAGE_LENGTH)
						eKnife[ATTRIBUTES] = _:TrieCreate()

						if(g_bRankSystem)
						{
							eKnife[LEVEL] = 0
							eKnife[SHOW_RANK] = false
							eKnife[XP] = 0
						}

						static const ATTRIBUTE_NAME[] = "NAME"
						TrieSetString(eKnife[ATTRIBUTES], ATTRIBUTE_NAME, szData)
					}
					else continue
				}
				default:
				{
					strtok(szData, szKey, charsmax(szKey), szValue, charsmax(szValue), '=')
					trim(szKey); trim(szValue)
					bCustom = true

					TrieSetString(eKnife[ATTRIBUTES], szKey, szValue)

					if(equal(szKey, "FLAG"))
					{
						eKnife[FLAG] = read_flags(szValue)
						g_iMenuFlags |= eKnife[FLAG]
					}
					else if(equal(szKey, "FLAG_SUFFIX"))
					{
						copy(eKnife[FLAG_SUFFIX], charsmax(eKnife[FLAG_SUFFIX]), szValue)
					}
					else if(equal(szKey, "LEVEL") && g_bRankSystem)
					{
						eKnife[LEVEL] = clamp(str_to_num(szValue), 0, iMaxLevels)

						if(!g_bGetLevel)
						{
							g_bGetLevel = true
						}
					}
					else if(equal(szKey, "SHOW_RANK") && g_bRankSystem)
					{
						eKnife[SHOW_RANK] = _:clamp(str_to_num(szValue), false, true)
					}
					else if(equal(szKey, "XP") && g_bRankSystem)
					{
						eKnife[XP] = _:clamp(str_to_num(szValue), 0)

						if(!g_bGetXP)
						{
							g_bGetXP = true
						}
					}
					else if(equal(szKey, "V_MODEL"))
					{
						copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), szValue)
					}
					else if(equal(szKey, "P_MODEL"))
					{
						copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), szValue)
					}
					else if(equal(szKey, "DEPLOY_SOUND"))
					{
						copy(eKnife[DEPLOY_SOUND], charsmax(eKnife[DEPLOY_SOUND]), szValue)
					}
					else if(equal(szKey, "HIT_SOUND"))
					{
						copy(eKnife[HIT_SOUND], charsmax(eKnife[HIT_SOUND]), szValue)
					}
					else if(equal(szKey, "HITWALL_SOUND"))
					{
						copy(eKnife[HITWALL_SOUND], charsmax(eKnife[HITWALL_SOUND]), szValue)
					}
					else if(equal(szKey, "SLASH_SOUND"))
					{
						copy(eKnife[SLASH_SOUND], charsmax(eKnife[SLASH_SOUND]), szValue)
					}
					else if(equal(szKey, "STAB_SOUND"))
					{
						copy(eKnife[STAB_SOUND], charsmax(eKnife[STAB_SOUND]), szValue)
					}
					else if(equal(szKey, "SELECT_SOUND"))
					{
						bCustom = false
						copy(eKnife[SELECT_SOUND], charsmax(eKnife[SELECT_SOUND]), szValue)
					}
					else if(equal(szKey, "SELECT_MESSAGE"))
					{
						ArrayPushString(eKnife[SELECT_MESSAGES], szValue)
						eKnife[SELECT_MESSAGES_NUM]++
					}
					else continue

					static const szModelArg[] = "_MODEL"
					static const szSoundArg[] = "_SOUND"

					if(contain(szKey, szModelArg) != -1)
					{
						if(!file_exists(szValue))
						{
							log_amx("ERROR: model ^"%s^" not found!", szValue)
						}
						else
						{
							precache_model(szValue)
						}
					}
					else if(contain(szKey, szSoundArg) != -1)
					{
						formatex(szSound, charsmax(szSound), "sound/%s", szValue)

						if(!file_exists(szSound))
						{
							log_amx("ERROR: sound ^"%s^" not found!", szSound)
						}
						else
						{
							precache_sound(szValue)
						}

						if(bCustom)
						{
							eKnife[HAS_CUSTOM_SOUND] = true
						}
					}
				}
			}
		}

		if(g_iKnivesNum)
		{
			push_knife(eKnife)
		}

		fclose(iFilePointer)
	}
}

public client_connect(id)
{
	g_bFirstTime[id] = true
	ArrayGetArray(g_aKnives, 0, g_eKnife[id])
	g_iKnife[id] = 0

	new iReturn
	ExecuteForward(g_fwdKnifeUpdated, iReturn, id, g_iKnife[id], true)

	if(g_eCvars[km_save_choice])
	{
		get_user_authid(id, g_szAuth[id], charsmax(g_szAuth[]))
		use_vault(id, false)
	}
}

public client_disconnected(id)
{
	if(g_eCvars[km_save_choice])
	{
		use_vault(id, true)
	}
}

public OnEmitSound(id, iChannel, const szSample[])
{
	if(!is_user_connected(id) || !g_eKnife[id][HAS_CUSTOM_SOUND] || !is_knife_sound(szSample))
	{
		return FMRES_IGNORED
	}

	switch(detect_knife_sound(szSample))
	{
		case SOUND_DEPLOY: 		if(g_eKnife[id][DEPLOY_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][DEPLOY_SOUND][0]);      return FMRES_SUPERCEDE; }
		case SOUND_HIT: 		if(g_eKnife[id][HIT_SOUND][0]) 			{ play_knife_sound(id, g_eKnife[id][HIT_SOUND][0]);         return FMRES_SUPERCEDE; }
		case SOUND_HITWALL:		if(g_eKnife[id][HITWALL_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][HITWALL_SOUND][0]);     return FMRES_SUPERCEDE; }
		case SOUND_SLASH: 		if(g_eKnife[id][SLASH_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][SLASH_SOUND][0]);       return FMRES_SUPERCEDE; }
		case SOUND_STAB: 		if(g_eKnife[id][STAB_SOUND][0]) 		{ play_knife_sound(id, g_eKnife[id][STAB_SOUND][0]);        return FMRES_SUPERCEDE; }
	}

	return FMRES_IGNORED
}

public Cmd_Knife(id)
{
	if(g_eCvars[km_only_dead] && is_user_alive(id))
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_ONLY_DEAD")
		return PLUGIN_HANDLED
	}

	static eKnife[Knives]
	new szTitle[128], szItem[128], iLevel, iXP
	formatex(szTitle, charsmax(szTitle), "%L", id, "KM_MENU_TITLE")

	if(g_bGetLevel)
	{
		iLevel = crxranks_get_user_level(id)
	}

	if(g_bGetXP)
	{
		iXP = crxranks_get_user_xp(id)
	}

	new iMenu = menu_create(szTitle, "MenuHandler")

	for(new iFlags = get_user_flags(id), i; i < g_iKnivesNum; i++)
	{
		ArrayGetArray(g_aKnives, i, eKnife)
		copy(szItem, charsmax(szItem), eKnife[NAME])

		if(g_bRankSystem)
		{
			if(eKnife[LEVEL] && iLevel < eKnife[LEVEL])
			{
				if(eKnife[SHOW_RANK])
				{
					static szRank[32]
					crxranks_get_rank_by_level(eKnife[LEVEL], szRank, charsmax(szRank))
					format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_RANK", szRank)
				}
				else
				{
					format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_LEVEL", eKnife[LEVEL])
				}
			}

			if(eKnife[XP] && iXP < eKnife[XP])
			{
				format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_XP", eKnife[XP])
			}
		}

		if(eKnife[FLAG] != ADMIN_ALL && !(iFlags & eKnife[FLAG]))
		{
			if(eKnife[FLAG_SUFFIX][0])
			{
				format(szItem, charsmax(szItem), "%s %s", szItem, eKnife[FLAG_SUFFIX])
			}
			else
			{
				format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_VIP_ONLY")
			}
		}

		if(g_iKnife[id] == i)
		{
			format(szItem, charsmax(szItem), "%s %L", szItem, id, "KM_MENU_SELECTED")
		}

		menu_additem(iMenu, szItem, eKnife[NAME], eKnife[FLAG], g_iCallback)
	}

	if(menu_pages(iMenu) > 1)
	{
		formatex(szItem, charsmax(szItem), "%s%L", szTitle, id, "KM_MENU_TITLE_PAGE")
		menu_setprop(iMenu, MPROP_TITLE, szItem)
	}

	menu_display(id, iMenu)
	return PLUGIN_HANDLED
}

public Cmd_Select(id, iLevel, iCid)
{
	if(!cmd_access(id, iLevel, iCid, 2))
	{
		return PLUGIN_HANDLED
	}

	if(g_eCvars[km_only_dead] && is_user_alive(id))
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_ONLY_DEAD")
		return PLUGIN_HANDLED
	}

	new szKnife[4]
	read_argv(1, szKnife, charsmax(szKnife))

	new iKnife = str_to_num(szKnife)

	if(!is_knife_valid(iKnife))
	{
		console_print(id, "%l", "KM_INVALID_KNIFE", g_iKnivesNum - 1)
		return PLUGIN_HANDLED
	}

	if(!has_knife_access(id, iKnife))
	{
		console_print(id, "%l", "KM_NO_ACCESS")
		return PLUGIN_HANDLED
	}

	select_knife(id, iKnife)
	return PLUGIN_HANDLED
}

public MenuHandler(id, iMenu, iItem)
{
	if(g_eCvars[km_only_dead] && is_user_alive(id))
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_ONLY_DEAD")
		goto @MENU_DESTROY
	}

	if(!is_user_connected(id))
	{
		goto @MENU_DESTROY
	}

	if(iItem != MENU_EXIT)
	{
		select_knife(id, iItem)
	}

	@MENU_DESTROY:
	menu_destroy(iMenu)
	return PLUGIN_HANDLED
}

select_knife(id, iKnife)
{
	new iReturn
	ExecuteForward(g_fwdAttemptChange, iReturn, id, iKnife)

	if(iReturn == PLUGIN_HANDLED)
	{
		return
	}

	g_iKnife[id] = iKnife
	ArrayGetArray(g_aKnives, iKnife, g_eKnife[id])
	ExecuteForward(g_fwdKnifeUpdated, iReturn, id, iKnife, false)

	if(is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
	{
		refresh_knife_model(id)
	}

	if(g_eCvars[km_select_message])
	{
		CC_SendMessage(id, "%l %l", "KM_CHAT_PREFIX", "KM_CHAT_SELECTED", g_eKnife[id][NAME])
	}

	if(g_eKnife[id][SELECT_MESSAGES_NUM])
	{
		for(new i; i < g_eKnife[id][SELECT_MESSAGES_NUM]; i++)
		{
			CC_SendMessage(id, "%a", ArrayGetStringHandle(g_eKnife[id][SELECT_MESSAGES], i))
		}
	}

	if(g_eKnife[id][SELECT_SOUND][0])
	{
		play_knife_sound(id, g_eKnife[id][SELECT_SOUND])
	}
}

public CheckKnifeAccess(id, iMenu, iItem)
{
	return ((g_iKnife[id] == iItem) || !has_knife_access(id, iItem)) ? ITEM_DISABLED : ITEM_ENABLED
}

public OnPlayerSpawn(id)
{
	if(is_user_alive(id) && g_eCvars[km_open_at_spawn] && !g_iKnife[id] && g_bFirstTime[id] && (g_iMenuFlags & ADMIN_USER || get_user_flags(id) & g_iMenuFlags))
	{
		g_bFirstTime[id] = false
		Cmd_Knife(id)
	}
}

public OnSelectKnife(iEnt)
{
	new id = get_pdata_cbase(iEnt, m_pPlayer, 4)

	if(is_user_connected(id))
	{
		refresh_knife_model(id)
	}
}

refresh_knife_model(const id)
{
	set_pev(id, pev_viewmodel2, g_eKnife[id][V_MODEL])
	set_pev(id, pev_weaponmodel2, g_eKnife[id][P_MODEL])
}

push_knife(eKnife[Knives])
{
	if(!eKnife[V_MODEL][0])
	{
		copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), CRXKNIVES_DEFAULT_V)
	}

	if(!eKnife[P_MODEL][0])
	{
		copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), CRXKNIVES_DEFAULT_P)
	}

	if(!eKnife[FLAG])
	{
		g_iMenuFlags |= ADMIN_USER
	}

	ArrayPushArray(g_aKnives, eKnife)
}

bool:has_knife_access(const id, const iKnife)
{
	static eKnife[Knives]
	ArrayGetArray(g_aKnives, iKnife, eKnife)

	if(g_bRankSystem)
	{
		if(eKnife[LEVEL] && crxranks_get_user_level(id) < eKnife[LEVEL])
		{
			return false
		}

		if(eKnife[XP] && crxranks_get_user_xp(id) < eKnife[XP])
		{
			return false
		}
	}

	if(eKnife[FLAG] != ADMIN_ALL && !(get_user_flags(id) & eKnife[FLAG]))
	{
		return false
	}

	return true
}

bool:is_knife_sound(const szSample[])
{
	return bool:equal(szSample[8], "kni", 3)
}

detect_knife_sound(const szSample[])
{
	static iSound
	iSound = SOUND_NONE

	if(equal(szSample, "weapons/knife_deploy1.wav"))
	{
		iSound = SOUND_DEPLOY
	}
	else if(equal(szSample[14], "hit", 3))
	{
		iSound = szSample[17] == 'w' ? SOUND_HITWALL : SOUND_HIT
	}
	else if(equal(szSample[14], "sla", 3))
	{
		iSound = SOUND_SLASH
	}
	else if(equal(szSample[14], "sta", 3))
	{
		iSound = SOUND_STAB
	}

	return iSound
}

use_vault(const id, const bool:bSave)
{
	if(bSave)
	{
		new szData[4]
		num_to_str(g_iKnife[id], szData, charsmax(szData))
		nvault_set(g_iVault, g_szAuth[id], szData)
	}
	else
	{
		new iKnife
		iKnife = nvault_get(g_iVault, g_szAuth[id])

		if(!is_knife_valid(iKnife))
		{
			iKnife = 0
		}
		else if(has_knife_access(id, iKnife))
		{
			g_iKnife[id] = iKnife

			new iReturn
			ArrayGetArray(g_aKnives, iKnife, g_eKnife[id])
			ExecuteForward(g_fwdKnifeUpdated, iReturn, id, iKnife, false)

			if(is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
			{
				refresh_knife_model(id)
			}
		}
	}
}

play_knife_sound(const id, const szSound[])
{
	engfunc(EngFunc_EmitSound, id, CHAN_AUTO, szSound, 1.0, ATTN_NORM, 0, PITCH_NORM)
}

bool:is_knife_valid(const iKnife)
{
	return 0 <= iKnife < g_iKnivesNum
}

public plugin_natives()
{
	register_library("crxknives")
	register_native("crxknives_can_use_skill",       "_crxknives_can_use_skill")
	register_native("crxknives_get_attribute_int",   "_crxknives_get_attribute_int")
	register_native("crxknives_get_attribute_float", "_crxknives_get_attribute_float")
	register_native("crxknives_get_attribute_str",   "_crxknives_get_attribute_str")
	register_native("crxknives_get_knives_num",      "_crxknives_get_knives_num")
	register_native("crxknives_get_user_knife",      "_crxknives_get_user_knife")
	register_native("crxknives_has_knife_access",    "_crxknives_has_knife_access")
	register_native("crxknives_is_knife_valid",      "_crxknives_is_knife_valid")
	set_native_filter("native_filter")
}

public native_filter(const szNative[], id, iTrap)
{
	if(!iTrap)
	{
		static i

		for(i = 0; i < sizeof(g_szNatives); i++)
		{
			if(equal(szNative, g_szNatives[i]))
			{
				return PLUGIN_HANDLED
			}
		}
	}

	return PLUGIN_CONTINUE
}

public bool:_crxknives_can_use_skill(iPlugin, iParams)
{
	return !g_eCvars[km_knife_only_skills] || (get_user_weapon(get_param(1)) == CSW_KNIFE)
}

public bool:_crxknives_get_attribute_int(iPlugin, iParams)
{
	static szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
	get_string(2, szAttribute, charsmax(szAttribute))
	id = get_param(1)

	if(!get_param(4))
	{
		if(!is_knife_valid(id))
		{
			return false
		}

		static eKnife[Knives]
		ArrayGetArray(g_aKnives, id, eKnife)

		if(!TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
		{
			return false
		}

		TrieGetString(eKnife[ATTRIBUTES], szAttribute, szValue, charsmax(szValue))
		goto @SET_ATTRIBUTE
	}

	if(!TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
	{
		return false
	}

	TrieGetString(g_eKnife[id][ATTRIBUTES], szAttribute, szValue, charsmax(szValue))

	@SET_ATTRIBUTE:
	set_param_byref(3, str_to_num(szValue))
	return true
}

public bool:_crxknives_get_attribute_float(iPlugin, iParams)
{
	static szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
	get_string(2, szAttribute, charsmax(szAttribute))
	id = get_param(1)

	if(!get_param(4))
	{
		if(!is_knife_valid(id))
		{
			return false
		}

		static eKnife[Knives]
		ArrayGetArray(g_aKnives, id, eKnife)

		if(!TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
		{
			return false
		}

		TrieGetString(eKnife[ATTRIBUTES], szAttribute, szValue, charsmax(szValue))
		goto @SET_ATTRIBUTE
	}

	if(!TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
	{
		return false
	}

	TrieGetString(g_eKnife[id][ATTRIBUTES], szAttribute, szValue, charsmax(szValue))

	@SET_ATTRIBUTE:
	set_float_byref(3, str_to_float(szValue))
	return true
}

public bool:_crxknives_get_attribute_str(iPlugin, iParams)
{
	static szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
	get_string(2, szAttribute, charsmax(szAttribute))
	id = get_param(1)

	if(!get_param(5))
	{
		if(!is_knife_valid(id))
		{
			return false
		}

		static eKnife[Knives]
		ArrayGetArray(g_aKnives, id, eKnife)

		if(!TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
		{
			return false
		}

		TrieGetString(eKnife[ATTRIBUTES], szAttribute, szValue, charsmax(szValue))
		goto @SET_ATTRIBUTE
	}

	if(!TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
	{
		return false
	}

	TrieGetString(g_eKnife[id][ATTRIBUTES], szAttribute, szValue, charsmax(szValue))

	@SET_ATTRIBUTE:
	set_string(3, szValue, get_param(4))
	return true
}

public _crxknives_get_knives_num(iPlugin, iParams)
{
	return g_iKnivesNum
}

public _crxknives_get_user_knife(iPlugin, iParams)
{
	return g_iKnife[get_param(1)]
}

public bool:_crxknives_has_knife_access(iPlugin, iParams)
{
	return has_knife_access(get_param(1), get_param(2))
}

public bool:_crxknives_is_knife_valid(iPlugin, iParams)
{
	return is_knife_valid(get_param(1))
}
Най-вероятно ще добавя настройката и в следващия ъпдейт на плъгина.

Публикувай отговор
  • Подобни теми
    Отговори
    Преглеждания
     Последно мнение

Обратно към “Заявки за плъгини”

Кой е на линия

Потребители разглеждащи този форум: Google [Bot] и 15 госта