stock const STEAM_PREFIX[] = "^1[^4STEAM^1] ";
new const TEAM_NAMES[CsTeams][] = {
log_error(AMX_ERR_NATIVE, "Invalid num of arguments %d. Expected %d", %1, %2); \
if (!is_user_connected(%1)) { \
log_error(AMX_ERR_NATIVE, "Invalid player %d", %1); \
native aes_get_player_stats(id,data[4]);
native aes_get_level_name(lvlnum,level[],len,idLang = 0);
new const AES_TAG_FORMAT[] = "^1[^3%s^1] ";
const ALIVE_SEE_DEAD = (1 << 0);
const DEAD_SEE_ALIVE = (1 << 1);
const TEAM_SEE_TEAM = (1 << 2);
enum _:FLAG_PREFIX_INFO {
m_Prefix[PREFIX_MAX_LENGTH]
new const g_TextChannels[][] = {
new g_sMessage[MESSAGE_LENGTH];
new const FILE_PREFIXES[] = "chatmanager_prefixes.ini";
new g_bCustomPrefix[33], g_sPlayerPrefix[33][PREFIX_MAX_LENGTH];
new Trie:g_tSteamPrefixes, g_iTrieSteamSize;
new Trie:g_tNamePrefixes, g_iTrieNameSize;
new Array:g_aFlagPrefixes, g_iArrayFlagSize;
new g_iForwards[Forwards];
new g_sNewMessage[MESSAGE_LENGTH];
register_plugin(PLUGIN, VERSION, AUTHOR);
register_concmd("cm_set_prefix", "concmd__set_prefix", ADMIN_RCON, "<name or #userid> <prefix>");
register_clcmd("say /ukr", "clcmd__lang_change");
register_clcmd("say /eng", "clcmd__lang_change");
register_clcmd("say", "clcmd__say_handler");
register_clcmd("say_team", "clcmd__say_handler");
register_message((g_SayText = get_user_msgid("SayText")), "message__say_text");
// cm_player_send_message(id, message[], team_chat);
g_iForwards[SEND_MESSAGE] = CreateMultiForward("cm_player_send_message", ET_STOP, FP_CELL, FP_STRING, FP_CELL);
new dir[] = "addons/amxmodx/logs/chatmanager";
new date[16]; get_time("%Y%m%d", date, charsmax(date));
formatex(g_szLogFile, charsmax(g_szLogFile), "%s/chatlog_%s.html", dir, date);
if(!file_exists(g_szLogFile)) {
write_file(g_szLogFile, "<meta charset=utf-8><title>ChatManager Log</title>");
register_dictionary("aes.txt");
new dir[128]; get_localinfo("amxx_configsdir", dir, charsmax(dir));
new file_name[128]; formatex(file_name, charsmax(file_name), "%s/%s", dir, FILE_PREFIXES);
if(!file_exists(file_name)) {
log_amx("Prefixes file doesn't exist!");
g_tSteamPrefixes = TrieCreate();
g_tNamePrefixes = TrieCreate();
g_aFlagPrefixes = ArrayCreate(FLAG_PREFIX_INFO);
new file = fopen(file_name, "rt");
new text[128], type[6], auth[32], prefix[PREFIX_MAX_LENGTH + COLOR_BUFFER], prefix_info[FLAG_PREFIX_INFO];
fgets(file, text, charsmax(text));
parse(text, type, charsmax(type), auth, charsmax(auth), prefix, charsmax(prefix));
if(!type[0] || type[0] == ';' || !auth[0] || !prefix[0]) continue;
replace_color_tag(prefix);
TrieSetString(g_tSteamPrefixes, auth, prefix);
TrieSetString(g_tNamePrefixes, auth, prefix);
prefix_info[m_Flag] = read_flags(auth);
copy(prefix_info[m_Prefix], charsmax(prefix_info[m_Prefix]), prefix);
ArrayPushArray(g_aFlagPrefixes, prefix_info);
register_native("cm_set_player_message", "native_set_player_message");
register_native("cm_set_prefix", "native_set_prefix");
register_native("cm_get_prefix", "native_get_prefix");
register_native("cm_reset_prefix", "native_reset_prefix");
public native_set_player_message(plugin, params)
enum { arg_new_message = 1 };
get_string(arg_new_message, g_sNewMessage, charsmax(g_sNewMessage));
public native_set_prefix(plugin, params)
CHECK_NATIVE_ARGS_NUM(params, arg_prefix, 0)
new player = get_param(arg_player);
CHECK_NATIVE_PLAYER(player, 0)
get_string(arg_prefix, g_sPlayerPrefix[player], charsmax(g_sPlayerPrefix[]));
g_bCustomPrefix[player] = true;
public native_get_prefix(plugin, params)
CHECK_NATIVE_ARGS_NUM(params, arg_length, 0)
new player = get_param(arg_player);
CHECK_NATIVE_PLAYER(player, 0)
if (!g_bCustomPrefix[player]) {
return set_string(arg_dest, g_sPlayerPrefix[player], get_param(arg_length));
public native_reset_prefix(plugin, params)
CHECK_NATIVE_ARGS_NUM(params, arg_player, 0)
new player = get_param(arg_player);
CHECK_NATIVE_PLAYER(player, 0)
arrayset(g_sPlayerPrefix[player], 0, sizeof g_sPlayerPrefix[]);
g_bCustomPrefix[player] = false;
public client_putinserver(id)
g_bTranslite[id] = false;
g_sPlayerPrefix[id] = "";
g_bCustomPrefix[id] = false;
get_user_authid(id, steamid, charsmax(steamid));
if(g_iTrieSteamSize && TrieKeyExists(g_tSteamPrefixes, steamid)) {
g_bCustomPrefix[id] = true;
TrieGetString(g_tSteamPrefixes, steamid, g_sPlayerPrefix[id], charsmax(g_sPlayerPrefix[]));
g_bSteamPlayer[id] = is_user_steam(id);
public concmd__set_prefix(id, level, cid)
if(!cmd_access(id, level, cid, 2)) {
new szArg[32]; read_argv(1, szArg, charsmax(szArg));
new player = cmd_target(id, szArg, CMDTARGET_ALLOW_SELF);
new prefix[PREFIX_MAX_LENGTH + COLOR_BUFFER];
read_argv(2, prefix, charsmax(prefix));
replace_color_tag(prefix);
console_print(id, "You changed player prefix from ^"%s^" to ^"%s^".", g_sPlayerPrefix[player], prefix);
copy(g_sPlayerPrefix[player], charsmax(g_sPlayerPrefix[]), prefix);
g_bCustomPrefix[player] = g_sPlayerPrefix[player][0] != EOS ? true : false;
public clcmd__lang_change(id)
g_bTranslite[id] = !g_bTranslite[id];
color_print(id, "^1[^3ChatManager^1] Ви змінили мову на ^3%s^1.", g_bTranslite[id] ? "ukr" : "eng");
public clcmd__say_handler(id)
if (!is_user_connected(id)) {
new message[TEXT_LENGTH];
read_argv(0, message, charsmax(message));
new is_team_msg = (message[3] == '_');
read_args(message, charsmax(message));
replace_wrong_simbols(message);
return PLUGIN_HANDLED_MAIN;
flags = get_user_flags(id);
get_user_name(id, name, charsmax(name));
if(!g_bCustomPrefix[id]) {
if(g_iTrieNameSize && TrieKeyExists(g_tNamePrefixes, name)) {
TrieGetString(g_tNamePrefixes, name, g_sPlayerPrefix[id], charsmax(g_sPlayerPrefix[]));
} else if(g_iArrayFlagSize) {
new prefix_info[FLAG_PREFIX_INFO], bFoundPrefix = false;
for(new i; i < g_iArrayFlagSize; i++) {
ArrayGetArray(g_aFlagPrefixes, i, prefix_info);
if(check_flags(flags, prefix_info[m_Flag])) {
copy(g_sPlayerPrefix[id], charsmax(g_sPlayerPrefix[]), prefix_info[m_Prefix]);
g_sPlayerPrefix[id] = "";
copy(message, charsmax(message), message[1]);
new translited[TEXT_LENGTH];
translite_string(translited, charsmax(translited), message);
copy(message, charsmax(message), translited);
new ret; ExecuteForward(g_iForwards[SEND_MESSAGE], ret, id, message, is_team_msg);
if(ret == MESSAGE_BLOCKED) {
copy(message, charsmax(message), g_sNewMessage);
new name_color = flags & ADMIN_FLAG ? ADMIN_NAME_COLOR : PLAYER_NAME_COLOR;
new chat_color = flags & ADMIN_FLAG ? ADMIN_CHAT_COLOR : PLAYER_CHAT_COLOR;
get_time("[%H:%M:%S] ", time_code, charsmax(time_code));
new is_sender_alive = is_user_alive(id);
new CsTeams:sender_team = cs_get_user_team(id);
new channel = get_user_text_channel(is_sender_alive, is_team_msg, sender_team);
FormatMessage(id, sender_team, channel, name_color, chat_color, time_code, name, message);
new players[32], players_num, player, is_player_alive, CsTeams:player_team, player_flags;
get_players(players, players_num, "ch");
for(new i; i < players_num; i++) {
is_player_alive = is_user_alive(player);
player_team = cs_get_user_team(player);
player_flags = get_user_flags(player) & ADMIN_FLAG ? ADMIN_CHAT_FLAGS : PLAYER_CHAT_FLAGS;
if(player_flags & ALIVE_SEE_DEAD && !is_sender_alive && is_player_alive && (!is_team_msg || is_team_msg && sender_team == player_team) //flag ALIVE_SEE_DEAD
|| player_flags & DEAD_SEE_ALIVE && is_sender_alive && !is_player_alive && (!is_team_msg || is_team_msg && sender_team == player_team) //flag DEAD_SEE_ALIVE
|| player_flags & TEAM_SEE_TEAM && is_team_msg && sender_team != player_team) //flag TEAM_SEE_TEAM
emessage_begin(MSG_ONE, g_SayText, _, player);
ewrite_string(g_TextChannels[channel]);
static const team_color[CsTeams][] = {"gray", "red", "blue", "gray"};
formatex(log_msg, charsmax(log_msg), "<br><font color=black>%s %s %s <font color=%s><b>%s</b> </font>:</font><font color=%s> %s </font>", time_code, is_sender_alive ? "" : (_:sender_team == 1 || _:sender_team == 2 ? "*DEAD*" : "*SPEC*"), is_team_msg ? "(TEAM)" : "", team_color[sender_team], name, chat_color == GREEN ? "green" : "#FFB41E", message);
write_file(g_szLogFile, log_msg);
public FormatMessage(sender, CsTeams:sender_team, channel, name_color, chat_color, time_code[], name[], message[])
new text[MESSAGE_LENGTH], len = 1;
len += formatex(text[len], charsmax(text) - len, "%s", channel != 7 ? "*DEAD*" : "*SPEC*");
if(channel > 1 && channel < 7) {
len += formatex(text[len], charsmax(text) - len, "%s ", TEAM_NAMES[sender_team]);
len += formatex(text[len], charsmax(text) - len, " ");
len += formatex(text[len], charsmax(text) - len, "%s", time_code);
if(g_bSteamPlayer[sender]) {
len += formatex(text[len], charsmax(text) - len, "%s", STEAM_PREFIX);
new data[4], szAesTag[AES_MAX_LENGTH]; aes_get_player_stats(sender, data); aes_get_level_name(data[1], szAesTag, charsmax(szAesTag));
len += formatex(text[len], charsmax(text) - len, AES_TAG_FORMAT, szAesTag);
len += formatex(text[len], charsmax(text) - len, "%s", g_sPlayerPrefix[sender]);
len += formatex(text[len], charsmax(text) - len, "%c%s^1 :%c %s", name_color, name, chat_color, message);
copy(g_sMessage, charsmax(g_sMessage), text);
public message__say_text(msgid, dest, receiver)
if(get_msg_args() != 4) {
get_msg_arg_string(2, str2, charsmax(str2));
channel = get_msg_channel(str2);
get_msg_arg_string(3, str3, charsmax(str3));
set_msg_arg_string(2, "%s");
set_msg_arg_string(2, "#Spec_PlayerItem");
set_msg_arg_string(3, g_sMessage);
set_msg_arg_string(4, "");
for(new i; i < sizeof(g_TextChannels); i++) {
if(equal(str, g_TextChannels[i])) {
stock get_user_text_channel(is_sender_alive, is_team_msg, CsTeams:sender_team)
return is_sender_alive ? 2 : 3;
return is_sender_alive ? 4 : 5;
return is_sender_alive ? 0 : (sender_team == CS_TEAM_SPECTATOR ? 7 : 1);
stock replace_wrong_simbols(string[])
for(new i; string[i] != EOS; i++) {
if(/* string[i] == '%' || string[i] == '#' || */ 0x01 <= string[i] <= 0x04) {
string[len++] = string[i];
replace_color_tag(string[])
for (new i; string[i] != EOS; i++) {
case 'd': string[len++] = 0x01;
case 't': string[len++] = 0x03;
case 'g': string[len++] = 0x04;
default: string[len++] = string[i];
string[len++] = string[i];
stock translite_string(string[], size, source[])
static const table[][] = {
"Э", "#", ";", "%", "?", "э", "(", ")", "*", "+", "б", "-", "ю", ".", "0", "1", "2", "3", "4",
"5", "6", "7", "8", "9", "Ж", "ж", "Б", "=", "Ю", ",", "^"", "Ф", "И", "С", "В", "У", "А", "П",
"Р", "Ш", "О", "Л", "Д", "Ь", "Т", "Щ", "З", "Й", "К", "І", "Е", "Г", "М", "Ц", "Ч", "Н", "Я",
"х", "\", "ъ", ":", "_", "ё", "ф", "и", "с", "в", "у", "а", "п", "р", "ш", "о", "л", "д", "ь",
"т", "щ", "з", "й", "к", "і", "е", "г", "м", "ц", "ч", "н", "я", "Х", "/", "Ъ", "Ё"
for (new i = 0; source[i] != EOS && len < size; i++) {
string[len++] = table[ch][0];
if (table[ch][1] != EOS) {
string[len++] = table[ch][1];
stock color_print(id, text[], any:...)
new formated[190]; vformat(formated, charsmax(formated), text, 3);
message_begin(id ? MSG_ONE : MSG_ALL, g_SayText, _, id);
stock check_flags(flags, need_flags)
return ((flags & need_flags) == need_flags) ? 1 : 0;
if(dp_pointer || (dp_pointer = get_cvar_pointer("dp_r_id_provider"))) {
server_cmd("dp_clientinfo %d", id); server_exec();
return (get_pcvar_num(dp_pointer) == 2) ? true : false;