//***************************************************************
//*	Standard Admin Color Chat v. 1.1.1 for AMXX 				*
//*	by Martin J. Van der Cal								*
//*												*
//*	Standard admin chat in color							*
//*												*
//*	Copyright (C) 2005, Martin J. Van der Cal					*
//*	This plugin is under the GNU General Public License, read		*
//*	"Std Admin Color Chat Readme.doc" for further information.		*
//*												*
//*	std_admin_color_chat.sma							*
//*												*
//***************************************************************

#include <amxmodx>

#define MAX_MESSAGE_SIZE			256
#define MAX_COMMAND_SIZE			10
#define AMX_CHAT_CHAR_RECOGNITION	'@'		// What character we look for when we decide if the message should go to the admins
#define AMX_PSAY_CHAR_RECOGNITION	'#'		// Character to look for when sending PMs

// Error Codes
#define TOO_MANY_MATCHED			-1
#define NONE_MATCHED				-2

#define AMX_PSAY_FINDNICK_ERROR_TOO_MANY	"^x04[ACC] says: Error <Too many found>"
#define AMX_PSAY_FINDNICK_ERROR_NONE		"^x04[ACC] says: Error <None found>"
#define AMX_PSAY_FINDNICK_ERROR_UNKNOWN		"^x04[ACC] says: Error <Unknown error>"

// Text defines, PREFIX is text before and SUFFIX is text after the username in a message.
// Feel free to change these. Also note that ^x01 and ^x04 is color codes.
#define AMX_CHAT_PREFIX					"^x04"				// Text before the username in amx_chat command
#define AMX_CHAT_SUFFIX					" tells admins: "	// Text after the username in amx_chat command
#define AMX_PSAY_SEND_PREFIX			"^x04"				// Text before the username in a PM that you send
#define AMX_PSAY_SEND_SUFFIX			" PMs you: ^x01"	// Text after the username in a PM that you send
#define AMX_PSAY_BACK_TO_SENDER_PREFIX	"^x04You PM "		// Text before the username in the confimation notice of the PM you send
#define AMX_PSAY_BACK_TO_SENDER_SUFFIX	": ^x01"			// Text after the username in the confimation notice of the PM you send
#define AMX_SAY_PREFIX					"^x04"				// Text before the username in the amx_say command
#define AMX_SAY_SUFFIX					" tells all: ^x01"	// Text after the username in the amx_say command
// E. g. an amx_chat message with the current settings will be as following example shows
// Command by player with the nick "Martin Van der Cal":
// amx_chat Hello admins
// Shows as:
// Martin Van der Cal tells admins: Hello admins
// Also note that with only the color code in the prefix the whole line will show as green to all admins


new gmsgSayText

public plugin_init()
{
	register_plugin("Std Admin Color Chat", "1.1.1", "Van der Cal")

	register_clcmd("say",		"SayHandler",		ADMIN_CHAT, "# <name or #userid> <message> - Sends a PM")
	register_clcmd("say_team",	"SayTeamHandler",	0,			"@ <message> - Displays message to admins")
	
	register_concmd("amx_say",	"ConCmdACCSay",		ADMIN_CHAT,	"<message> - Displays message to all players")
	register_concmd("amx_psay",	"ConCmdACCPM",		ADMIN_CHAT,	"# <name or #userid> <message> - Sends a PM");
	register_concmd("amx_chat",	"ConCmdACCAdmins",	ADMIN_CHAT,	"<message> - Displays message to admins");

	gmsgSayText = get_user_msgid("SayText")
}

// Runs if anything is said in say
public SayHandler(iPlayerID)
{
	new sTemp[MAX_MESSAGE_SIZE]
	new sMessage[MAX_MESSAGE_SIZE]
	new sCmd[MAX_COMMAND_SIZE]
	read_argv(1, sTemp, MAX_MESSAGE_SIZE - 1)
	
	// if the player has admin chat rights
	if ( get_user_flags(iPlayerID) & ADMIN_CHAT )
	{
		// if the chat starts with AMX_PSAY_CHAR_RECOGNITION. That is, if an admin wants to send a PM
		if ( sTemp[0] == AMX_PSAY_CHAR_RECOGNITION )
		{
//			server_print("[DEBUG] ")

			if (sTemp[1] == ' ')
			{
				// Remove the chat recognition chars
				strbreak(sTemp, sCmd, MAX_COMMAND_SIZE-1, sMessage, MAX_MESSAGE_SIZE-1)
			}
			else
			{
				// Remove the chat recognition chars without the space
				sTemp[0] = ' '
				trim(sTemp)
				copy(sMessage, MAX_MESSAGE_SIZE-1, sTemp)
			}
			
			// Now we have our nick and message only in sMessage and thus, time for the next stage
			BaseSendPM(sMessage, iPlayerID)
			
			return PLUGIN_HANDLED
		}
	}
	return PLUGIN_CONTINUE
}

// Runs if anything is said in team_say
public SayTeamHandler(iPlayerID)
{
	new sTemp[MAX_MESSAGE_SIZE]
	new sCmd[MAX_COMMAND_SIZE]
	new sMessage[MAX_MESSAGE_SIZE]
	read_argv(1, sTemp, MAX_MESSAGE_SIZE - 1)
	
	// if the chat starts with AMX_CHAT_CHAR_RECOGNITION then we are supposed to send it to all admins
	if ( sTemp[0] == AMX_CHAT_CHAR_RECOGNITION )
	{
		// Somehow I cant get trim to work as I want, so if there are a space after @, then I had to resort to using strbreak
		if (sTemp[1] == ' ')
		{
			// Remove the chat recognition chars, sMessage will contain the message and the message only
			strbreak(sTemp, sCmd, MAX_COMMAND_SIZE-1, sMessage, MAX_MESSAGE_SIZE-1)
		}
		else
		{
			// Remove the chat recognition chars without the space.
			sTemp[0] = ' '
			trim(sTemp)
			copy(sMessage, MAX_MESSAGE_SIZE-1, sTemp)
		}
		
		remove_quotes(sMessage)
		
		SendAdminMessage(sMessage, iPlayerID)
		
		return PLUGIN_HANDLED
	}
	else if ( get_user_flags(iPlayerID) & ADMIN_CHAT )
	{
		// if the chat starts with AMX_PSAY_CHAR_RECOGNITION. That is, if an admin wants to send a PM
		if ( sTemp[0] == AMX_PSAY_CHAR_RECOGNITION )
		{
			if (sTemp[1] == ' ')
			{
				// Remove the chat recognition chars
				strbreak(sTemp, sCmd, MAX_COMMAND_SIZE-1, sMessage, MAX_MESSAGE_SIZE-1)
			}
			else
			{
				// Remove the chat recognition chars without the space
				sTemp[0] = ' '
				trim(sTemp)
				copy(sMessage, MAX_MESSAGE_SIZE-1, sTemp)
			}
			
			BaseSendPM(sMessage, iPlayerID)

			return PLUGIN_HANDLED
		}
	}
	return PLUGIN_CONTINUE
}

// Console command, amx_say <message>
public ConCmdACCSay(iPlayerID)
{
	// if the user is an admin with ADMIN_CHAT flag
	if ( get_user_flags(iPlayerID) & ADMIN_CHAT )
	{
		new sMessage[MAX_MESSAGE_SIZE]
		read_args(sMessage, MAX_MESSAGE_SIZE-1)
		remove_quotes(sMessage)
		
		new sUser[MAX_MESSAGE_SIZE]
		get_user_name(iPlayerID, sUser, MAX_MESSAGE_SIZE-1)
		
		// The message that we will actually send
		new sRealMessage[MAX_MESSAGE_SIZE] = AMX_SAY_PREFIX
		add(sRealMessage, MAX_MESSAGE_SIZE-1, sUser)
		add(sRealMessage, MAX_MESSAGE_SIZE-1, AMX_SAY_SUFFIX)
		add(sRealMessage, MAX_MESSAGE_SIZE-1, sMessage, MAX_MESSAGE_SIZE-strlen(sRealMessage)-1)

		// Get the steamid for the sake of logging
		new sSendSteamID[MAX_MESSAGE_SIZE]
		get_user_authid(iPlayerID, sSendSteamID, MAX_MESSAGE_SIZE-1)
		
		// Get all current players
		new nCurPlayers
		new iArrCurPlayers[32]
		get_players(iArrCurPlayers, nCurPlayers, "c")
		
		// Log the message
		log_amx("Chat (ALL), From: ^"%s<%d><%s><>^" Message: ^"%s^"", sUser, iPlayerID, sSendSteamID, sMessage)
		log_message("^"%s<%d><%s><>^" triggered ^"amx_say^" (text ^"%s^")",sUser, iPlayerID, sSendSteamID, sMessage)
	
		// For every player
		for (new iID = 0; iID < nCurPlayers; iID++)
			SendMessage(sRealMessage, iArrCurPlayers[iID]) // Send the message to the player
	}
	return PLUGIN_HANDLED;
}

// Console command, amx_psay <nick or steamid> <message>
public ConCmdACCPM(iPlayerID)
{
	// if the user is an admin
	if ( get_user_flags(iPlayerID) & ADMIN_CHAT )
	{
		new sArgs[MAX_MESSAGE_SIZE]
		read_args(sArgs, MAX_MESSAGE_SIZE-1)

		BaseSendPM(sArgs, iPlayerID)
	}
	return PLUGIN_HANDLED
}

// Console Command, amx_chat <message>
public ConCmdACCAdmins(iPlayerID)
{
	new sArgs[MAX_MESSAGE_SIZE]
	read_args(sArgs, MAX_MESSAGE_SIZE-1)
	remove_quotes(sArgs)
	
	SendAdminMessage(sArgs, iPlayerID)

	return PLUGIN_HANDLED
}

// Returns the id of the player, IF and only IF it found ONLY one player with which contains the nick provided, otherwise it returns less than 0
FindPlayerWithNick(sNick[MAX_MESSAGE_SIZE])
{
	new iArrPlayers[32]
	new nPlayers
	new sUser[MAX_MESSAGE_SIZE]
	new iPlayerID = -100
	get_players(iArrPlayers, nPlayers, "c")
	
	// for every player
	for (new iID = 0; iID < nPlayers; iID++)
	{
		get_user_name(iArrPlayers[iID], sUser, MAX_MESSAGE_SIZE-1)

		// Check if their nick contains the nick part provided, ignore caps
		if ( containi(sUser, sNick) >= 0  || equali(sUser,sNick) )
		{
			// if we havent found anyone yet, else return we have found too many
			if (iPlayerID == -100)
				iPlayerID = iArrPlayers[iID]
			else
				return TOO_MANY_MATCHED
		}
	}
	if (iPlayerID == -100)
		return NONE_MATCHED
	else
		return iPlayerID
		
	return 0
}

// Returns the id of the player with the correct steamid if it find any, otherwise it returns less than 0
FindPlayerWithSteamID(sSteamID[MAX_MESSAGE_SIZE])
{
	new iArrPlayers[32]
	new nPlayers
	new sUser[MAX_MESSAGE_SIZE]
	new iResult
	get_players(iArrPlayers, nPlayers, "c")

	for (new iID = 0; iID < nPlayers; iID++)
	{
		get_user_authid(iArrPlayers[iID], sUser, MAX_MESSAGE_SIZE-1)
		// The steam id must be strictly equal
		iResult = equal(sUser, sSteamID)
		if ( iResult == 1 )
		{
			// Since steamid is unique, we dont have to check anyone else
			return iArrPlayers[iID]
		}
	}
	return NONE_MATCHED
}

// This is where we build the message to be sent, logs the message and find out who the admins are
SendAdminMessage(sMessage[], iSenderID)
{
	// The message that is going to be sent. ^x04 is green color
	new sRealMessage[MAX_MESSAGE_SIZE] = AMX_CHAT_PREFIX

	// Get the username of the sender
	new sUser[MAX_MESSAGE_SIZE]
	get_user_name(iSenderID, sUser, MAX_MESSAGE_SIZE - 1)
	
	// Add user, "user friendly text" and the message to the message we are going to send
	add(sRealMessage, MAX_MESSAGE_SIZE, sUser)
	add(sRealMessage, MAX_MESSAGE_SIZE, AMX_CHAT_SUFFIX)
	add( sRealMessage, MAX_MESSAGE_SIZE, (sMessage), (MAX_MESSAGE_SIZE-strlen(sRealMessage)-1) )

	// Get the steamid for the sake of logging
	new sSendSteamID[MAX_MESSAGE_SIZE]
	get_user_authid(iSenderID, sSendSteamID, MAX_MESSAGE_SIZE-1)
	
	// Get all current players
	new nCurPlayers
	new iArrCurPlayers[32]
	get_players(iArrCurPlayers, nCurPlayers, "c")
	
	// Log the message
	log_amx("ADMINS amx_chat, From: ^"%s<%d><%s><>^" Message: ^"%s^"", sUser, iSenderID, sSendSteamID, sMessage)
	log_message("^"%s<%d><%s><>^" triggered ^"amx_chat^" (text ^"%s^")",sUser, iSenderID, sSendSteamID, sMessage)

	// For every player
	for (new iID = 0; iID < nCurPlayers; iID++)
		if ( get_user_flags(iArrCurPlayers[iID]) & ADMIN_CHAT ) // If the player is an admin
			SendMessage(sRealMessage, iArrCurPlayers[iID]) // Send the message to the player(admin)
}

// This is where we prepare the PM, breaks out the nick and the message from the original message,
// finds who the reciever is and sends it. Also sends error if none or several matches found
BaseSendPM(sArgs[], iPlayerID)
{
	new sNick[MAX_MESSAGE_SIZE]
	new sMessage[MAX_MESSAGE_SIZE]
	
	// Get the nick/steamid
	strbreak(sArgs, sNick, MAX_MESSAGE_SIZE-1, sMessage, MAX_MESSAGE_SIZE-1)
	
	// Remove all those nasty quotes ! ! !
	remove_quotes(sNick)
	replace(sMessage, MAX_MESSAGE_SIZE-1, "^"", "")

	// Get the players id by comparing the players nick with the one the user supplied
	new iResult
	if ( equal(sNick, "STEAM_", 6) )
		iResult = FindPlayerWithSteamID(sNick)
	else
		iResult = FindPlayerWithNick(sNick)

	if ( iResult >= 0 ) // if we found "ONE" player with that nick, then we send the PM
	{
		SendPM(sMessage, iPlayerID, iResult)
	}
	else // if we found none or several with that nick. Then we send back an error message to the admin
	{
		new sSendSteamID[MAX_MESSAGE_SIZE]
		get_user_authid(iPlayerID, sSendSteamID, MAX_MESSAGE_SIZE-1)
		
		if ( iResult == TOO_MANY_MATCHED )
			format(sMessage, MAX_MESSAGE_SIZE-1, AMX_PSAY_FINDNICK_ERROR_TOO_MANY)
		else if ( iResult == NONE_MATCHED )
			format(sMessage, MAX_MESSAGE_SIZE-1, AMX_PSAY_FINDNICK_ERROR_NONE)
		else
			format(sMessage, MAX_MESSAGE_SIZE-1, AMX_PSAY_FINDNICK_ERROR_UNKNOWN)
		
		// if the sender is an admin or infact the server itself.
		if ( equal(sSendSteamID, "STEAM_", 6) )
			SendMessage(sMessage, iPlayerID)
		else
			server_print(sMessage)
	}
}

// Here we build the PM message, logs it and sends it
SendPM(sMessage[], iSenderID, iRecieverID)
{
	new sRealMessage[MAX_MESSAGE_SIZE] = AMX_PSAY_SEND_PREFIX

	// To the person
	new sUser[MAX_MESSAGE_SIZE]
	get_user_name(iSenderID, sUser, MAX_MESSAGE_SIZE - 1)
	
	add(sRealMessage, MAX_MESSAGE_SIZE-1, sUser)
	add(sRealMessage, MAX_MESSAGE_SIZE-1, AMX_PSAY_SEND_SUFFIX)
	add(sRealMessage, MAX_MESSAGE_SIZE-1, sMessage, MAX_MESSAGE_SIZE-strlen(sRealMessage)-1)

	new sRecvSteamID[MAX_MESSAGE_SIZE]
	new sSendSteamID[MAX_MESSAGE_SIZE]
	new sRecvName[MAX_MESSAGE_SIZE]
	
	get_user_authid(iSenderID, sSendSteamID, MAX_MESSAGE_SIZE-1)
	get_user_authid(iRecieverID, sRecvSteamID, MAX_MESSAGE_SIZE-1)

	get_user_name(iRecieverID, sRecvName, MAX_MESSAGE_SIZE - 1)
	
	log_amx("PM From: ^"%s<%d><%s><>^" To: ^"%s<%d><%s><>^" Message: ^"%s^"", sUser, iSenderID, sSendSteamID, sRecvName, iRecieverID, sRecvSteamID, sMessage)
	log_message("^"%s<%d><%s><>^" triggered ^"amx_psay^" against ^"%s<%d><%s><>^" (text ^"%s^")",
		sUser, iSenderID, sSendSteamID, sRecvName, iRecieverID, sRecvSteamID, sMessage)

	SendMessage(sRealMessage, iRecieverID)
	
	// And to the admin who sent it
	new sToAdmin[MAX_MESSAGE_SIZE] = AMX_PSAY_BACK_TO_SENDER_PREFIX
	add(sToAdmin, MAX_MESSAGE_SIZE-1, sRecvName)
	add(sToAdmin, MAX_MESSAGE_SIZE-1, AMX_PSAY_BACK_TO_SENDER_SUFFIX)
	add(sToAdmin, MAX_MESSAGE_SIZE-1, sMessage, MAX_MESSAGE_SIZE-strlen(sToAdmin)-1)

	// if the sender is an admin or infact the server
	if ( equal(sSendSteamID, "STEAM_", 6) )
		SendMessage(sToAdmin, iSenderID)
	else
		server_print(sToAdmin)
}

// General method for sending chat messages, params are the message to be sent and the id of the player who should get it
SendMessage(sMessage[], iRecieverID)
{
	message_begin(MSG_ONE, gmsgSayText, {0,0,0}, iRecieverID)
	write_byte(iRecieverID)
	write_string(sMessage)
	message_end()
}
// Text before the username in amx_chat command
#define AMX_CHAT_PREFIX "^x04"

// Text after the username in amx_chat command
#define AMX_CHAT_SUFFIX	" tells admins: "

// Text before the username in a PM that you send
#define AMX_PSAY_SEND_PREFIX "^x04"

// Text after the username in a PM that you send
#define AMX_PSAY_SEND_SUFFIX " PMs you: ^x01"

// Text before the username in the confimation notice of the PM you send
#define AMX_PSAY_BACK_TO_SENDER_PREFIX	"^x04You PM "

// Text after the username in the confimation notice of the PM you send
#define AMX_PSAY_BACK_TO_SENDER_SUFFIX	": ^x01"

// Text before the username in the amx_say command
#define AMX_SAY_PREFIX	"^x04"

// Text after the username in the amx_say command
#define AMX_SAY_SUFFIX	" tells all: ^x01"

// E. g. an amx_chat message with the current settings will be as following example shows
// Command by player with the nick "acer":
// amx_chat Hello admins
// Shows as:
// TnT-estonia[www.tntpub.clan.su] tells admins: Hello admins
// Also note that with only the color code in the prefix the whole line will show as green to all admins