/************************************************************************** * * * Colored Chat Functions * * Author: exvel, Editor: Popoklopsi, Powerlord, Bara * * Version: 2.0.0-MC * * * **************************************************************************/ #if defined _colors_included #endinput #endif #define _colors_included #define MAX_MESSAGE_LENGTH 250 #define MAX_COLORS 19 #define SERVER_INDEX 0 #define NO_INDEX -1 #define NO_PLAYER -2 #define CSGO_TEAM_T 2 #define CSGO_TEAM_CT 3 #define CSGO_TAG_T "{t}" #define CSGO_TAG_CT "{ct}" enum C_Colors { Color_Default = 0, Color_Darkred, Color_Green, Color_Lightgreen, Color_Red, Color_Blue, Color_Olive, Color_Lime, Color_Lightred, Color_Purple, Color_Grey, Color_Yellow, Color_Orange, Color_Bluegrey, Color_Lightblue, Color_Darkblue, Color_Grey2, Color_Orchid, Color_Lightred2 } /* C_Colors' properties */ char C_Tag[][] = {"{default}", "{darkred}", "{green}", "{lightgreen}", "{red}", "{blue}", "{olive}", "{lime}", "{lightred}", "{purple}", "{grey}", "{yellow}", "{orange}", "{bluegrey}", "{lightblue}", "{darkblue}", "{grey2}", "{orchid}", "{lightred2}"}; char C_TagCode[][] = {"\x01", "\x02", "\x04", "\x03", "\x03", "\x03", "\x05", "\x06", "\x07", "\x03", "\x08", "\x09", "\x10", "\x0A", "\x0B", "\x0C", "\x0D", "\x0E", "\x0F"}; bool C_TagReqSayText2[] = {false, false, false, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false}; bool C_EventIsHooked; bool C_SkipList[MAXPLAYERS+1]; /* Game default profile */ bool C_Profile_Colors[] = {true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; int C_Profile_TeamIndex[] = {NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX}; bool C_Profile_SayText2; static ConVar sm_show_activity; /** * Prints a message to a specific client in the chat area. * Supports color tags. * * @param client Client index. * @param szMessage Message (formatting rules). * @return No return * * On error/Errors: If the client is not connected an error will be thrown. */ stock void C_PrintToChat(int client, const char[] szMessage, any ...) { if (client <= 0 || client > MaxClients) { ThrowError("Invalid client index %d", client); } if (!IsClientInGame(client)) { ThrowError("Client %d is not in game", client); } char szBuffer[MAX_MESSAGE_LENGTH]; char szCMessage[MAX_MESSAGE_LENGTH]; SetGlobalTransTarget(client); Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); VFormat(szCMessage, sizeof(szCMessage), szBuffer, 3); int index = C_Format(szCMessage, sizeof(szCMessage)); if (index == NO_INDEX) { PrintToChat(client, "%s", szCMessage); } else { C_SayText2(client, index, szCMessage); } } /** * Reples to a message in a command. A client index of 0 will use PrintToServer(). * If the command was from the console, PrintToConsole() is used. If the command was from chat, C_PrintToChat() is used. * Supports color tags. * * @param client Client index, or 0 for server. * @param szMessage Formatting rules. * @param ... Variable number of format parameters. * @return No return * * On error/Errors: If the client is not connected or invalid. */ stock void C_ReplyToCommand(int client, const char[] szMessage, any ...) { char szCMessage[MAX_MESSAGE_LENGTH]; SetGlobalTransTarget(client); VFormat(szCMessage, sizeof(szCMessage), szMessage, 3); if (client == 0) { C_RemoveTags(szCMessage, sizeof(szCMessage)); PrintToServer("%s", szCMessage); } else if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { C_RemoveTags(szCMessage, sizeof(szCMessage)); PrintToConsole(client, "%s", szCMessage); } else { C_PrintToChat(client, "%s", szCMessage); } } /** * Reples to a message in a command. A client index of 0 will use PrintToServer(). * If the command was from the console, PrintToConsole() is used. If the command was from chat, C_PrintToChat() is used. * Supports color tags. * * @param client Client index, or 0 for server. * @param author Author index whose color will be used for teamcolor tag. * @param szMessage Formatting rules. * @param ... Variable number of format parameters. * @return No return * * On error/Errors: If the client is not connected or invalid. */ stock void C_ReplyToCommandEx(int client, int author, const char[] szMessage, any ...) { char szCMessage[MAX_MESSAGE_LENGTH]; SetGlobalTransTarget(client); VFormat(szCMessage, sizeof(szCMessage), szMessage, 4); if (client == 0) { C_RemoveTags(szCMessage, sizeof(szCMessage)); PrintToServer("%s", szCMessage); } else if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { C_RemoveTags(szCMessage, sizeof(szCMessage)); PrintToConsole(client, "%s", szCMessage); } else { C_PrintToChatEx(client, author, "%s", szCMessage); } } /** * Prints a message to all clients in the chat area. * Supports color tags. * * @param client Client index. * @param szMessage Message (formatting rules) * @return No return */ stock void C_PrintToChatAll(const char[] szMessage, any ...) { char szBuffer[MAX_MESSAGE_LENGTH]; for (int i = 1; i <= MaxClients; ++i) { if (IsClientInGame(i) && !IsFakeClient(i) && !C_SkipList[i]) { SetGlobalTransTarget(i); VFormat(szBuffer, sizeof(szBuffer), szMessage, 2); C_PrintToChat(i, "%s", szBuffer); } C_SkipList[i] = false; } } /** * Prints a message to a specific client in the chat area. * Supports color tags and teamcolor tag. * * @param client Client index. * @param author Author index whose color will be used for teamcolor tag. * @param szMessage Message (formatting rules). * @return No return * * On error/Errors: If the client or author are not connected an error will be thrown. */ stock void C_PrintToChatEx(int client, int author, const char[] szMessage, any ...) { if (client <= 0 || client > MaxClients) { ThrowError("Invalid client index %d", client); } if (!IsClientInGame(client)) { ThrowError("Client %d is not in game", client); } if (author < 0 || author > MaxClients) { ThrowError("Invalid client index %d", author); } char szBuffer[MAX_MESSAGE_LENGTH]; char szCMessage[MAX_MESSAGE_LENGTH]; SetGlobalTransTarget(client); Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); VFormat(szCMessage, sizeof(szCMessage), szBuffer, 4); int index = C_Format(szCMessage, sizeof(szCMessage), author); if (index == NO_INDEX) { PrintToChat(client, "%s", szCMessage); } else { C_SayText2(client, author, szCMessage); } } /** * Prints a message to all clients in the chat area. * Supports color tags and teamcolor tag. * * @param author Author index whos color will be used for teamcolor tag. * @param szMessage Message (formatting rules). * @return No return * * On error/Errors: If the author is not connected an error will be thrown. */ stock void C_PrintToChatAllEx(int author, const char[] szMessage, any ...) { if (author < 0 || author > MaxClients) { ThrowError("Invalid client index %d", author); } if (!IsClientInGame(author)) { ThrowError("Client %d is not in game", author); } char szBuffer[MAX_MESSAGE_LENGTH]; for (int i = 1; i <= MaxClients; ++i) { if (IsClientInGame(i) && !IsFakeClient(i) && !C_SkipList[i]) { SetGlobalTransTarget(i); VFormat(szBuffer, sizeof(szBuffer), szMessage, 3); C_PrintToChatEx(i, author, "%s", szBuffer); } C_SkipList[i] = false; } } /** * Removes color tags from the string. * * @param szMessage String. * @return No return */ stock void C_RemoveTags(char[] szMessage, int maxlength) { for (int i = 0; i < MAX_COLORS; i++) { ReplaceString(szMessage, maxlength, C_Tag[i], "", false); } ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); } /** * Checks whether a color is allowed or not * * @param tag Color Tag. * @return True when color is supported, otherwise false */ stock bool C_ColorAllowed(C_Colors color) { if (!C_EventIsHooked) { C_SetupProfile(); C_EventIsHooked = true; } return C_Profile_Colors[color]; } /** * Replace the color with another color * Handle with care! * * @param color color to replace. * @param newColor color to replace with. * @noreturn */ stock void C_ReplaceColor(C_Colors color, C_Colors newColor) { if (!C_EventIsHooked) { C_SetupProfile(); C_EventIsHooked = true; } C_Profile_Colors[color] = C_Profile_Colors[newColor]; C_Profile_TeamIndex[color] = C_Profile_TeamIndex[newColor]; C_TagReqSayText2[color] = C_TagReqSayText2[newColor]; Format(C_TagCode[color], sizeof(C_TagCode[]), C_TagCode[newColor]); } /** * This function should only be used right in front of * C_PrintToChatAll or C_PrintToChatAllEx and it tells * to those funcions to skip specified client when printing * message to all clients. After message is printed client will * no more be skipped. * * @param client Client index * @return No return */ stock void C_SkipNextClient(int client) { if (client <= 0 || client > MaxClients) { ThrowError("Invalid client index %d", client); } C_SkipList[client] = true; } /** * Replaces color tags in a string with color codes * * @param szMessage String. * @param maxlength Maximum length of the string buffer. * @return Client index that can be used for SayText2 author index * * On error/Errors: If there is more then one team color is used an error will be thrown. */ stock int C_Format(char[] szMessage, int maxlength, int author = NO_INDEX, bool csgofix = true) { /* Hook event for auto profile setup on map start */ if (!C_EventIsHooked) { C_SetupProfile(); HookEvent("server_spawn", C_Event_MapStart, EventHookMode_PostNoCopy); C_EventIsHooked = true; } int iRandomPlayer = NO_INDEX; EngineVersion engine = GetEngineVersion(); // On CS:GO set invisible precolor if (csgofix && engine == Engine_CSGO) { Format(szMessage, maxlength, " %s", szMessage); } /* If author was specified replace {teamcolor} tag */ if (author != NO_INDEX) { if (C_Profile_SayText2) { ReplaceString(szMessage, maxlength, "{teamcolor}", "\x03", false); iRandomPlayer = author; } /* If saytext2 is not supported by game replace {teamcolor} with green tag */ else { ReplaceString(szMessage, maxlength, "{teamcolor}", C_TagCode[Color_Green], false); } } else { ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); } /* For other color tags we need a loop */ for (int i = 0; i < MAX_COLORS; i++) { int iTagStatus = -1; if (StrContains(szMessage, C_Tag[i], false) != -1) { iTagStatus = 0; } /* On CS:GO {red} and {blue} name is so strange for team colors. */ if (engine == Engine_CSGO) { if ((C_Profile_TeamIndex[i] == CSGO_TEAM_T && StrContains(szMessage, CSGO_TAG_T, false) != -1) || (C_Profile_TeamIndex[i] == CSGO_TEAM_CT && StrContains(szMessage, CSGO_TAG_CT, false) != -1)) { iTagStatus = 1; } } /* If tag not found - skip */ if (iTagStatus == -1) { continue; } /* If tag is not supported by game replace it with green tag */ else if (!C_Profile_Colors[i]) { ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[Color_Green], false); } /* If tag doesn't need saytext2 simply replace */ else if (!C_TagReqSayText2[i]) { ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[i], false); } /* Tag needs saytext2 */ else { /* If saytext2 is not supported by game replace tag with green tag */ if (!C_Profile_SayText2) { ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[Color_Green], false); } /* Game supports saytext2 */ else { /* If random player for tag wasn't specified replace tag and find player */ if (iRandomPlayer == NO_INDEX) { /* Searching for valid client for tag */ iRandomPlayer = C_FindRandomPlayerByTeam(C_Profile_TeamIndex[i]); /* If player not found replace tag with green color tag */ if (iRandomPlayer == NO_PLAYER) { ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[Color_Green], false); if (iTagStatus == 1) ReplaceString(szMessage, maxlength, C_Profile_TeamIndex[i] == CSGO_TEAM_T ? CSGO_TAG_T : CSGO_TAG_CT, C_TagCode[Color_Green], false); } /* If player was found simply replace */ else { ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[i], false); if (iTagStatus == 1) ReplaceString(szMessage, maxlength, C_Profile_TeamIndex[i] == CSGO_TEAM_T ? CSGO_TAG_T : CSGO_TAG_CT, C_TagCode[i], false); } } /* If found another team color tag throw error */ else { //ReplaceString(szMessage, maxlength, C_Tag[i], ""); ThrowError("Using two team colors in one message is not allowed"); } } } } return iRandomPlayer; } /** * Finds a random player with specified team * * @param color_team Client team. * @return Client index or NO_PLAYER if no player found */ stock int C_FindRandomPlayerByTeam(int color_team) { if (color_team == SERVER_INDEX) { return 0; } int[] players = new int[MaxClients]; int num; for (int i = 1; i <= MaxClients; ++i) { if (IsClientInGame(i) && GetClientTeam(i) == color_team) { players[num++] = i; } } if (num) { return players[GetRandomInt(0, num-1)]; } return NO_PLAYER; } /** * Sends a SayText2 usermessage to a client * * @param szMessage Client index * @param maxlength Author index * @param szMessage Message * @return No return. */ stock void C_SayText2(int client, int author, const char[] szMessage) { Handle hBuffer = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) { Protobuf pb = UserMessageToProtobuf(hBuffer); pb.SetInt("ent_idx", author); pb.SetBool("chat", true); pb.SetString("msg_name", szMessage); pb.AddString("params", ""); pb.AddString("params", ""); pb.AddString("params", ""); pb.AddString("params", ""); } else { BfWrite bf = UserMessageToBfWrite(hBuffer); bf.WriteByte(author); bf.WriteByte(true); bf.WriteString(szMessage); } EndMessage(); } /** * Creates game color profile * This function must be edited if you want to add more games support * * @return No return. */ stock void C_SetupProfile() { EngineVersion engine = GetEngineVersion(); if (engine == Engine_CSS) { C_Profile_Colors[Color_Lightgreen] = true; C_Profile_Colors[Color_Red] = true; C_Profile_Colors[Color_Blue] = true; C_Profile_Colors[Color_Olive] = true; C_Profile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; C_Profile_TeamIndex[Color_Red] = 2; C_Profile_TeamIndex[Color_Blue] = 3; C_Profile_SayText2 = true; } else if (engine == Engine_CSGO) { C_Profile_Colors[Color_Red] = true; // \x03 (T Color via SayText2) C_Profile_Colors[Color_Blue] = true; // \x03 (CT Color via SayText2) // Color_Default // \x01 C_Profile_Colors[Color_Darkred] = true; // \x02 C_Profile_Colors[Color_Purple] = true; // \x03 // Color_Green // \x04 C_Profile_Colors[Color_Olive] = true; // \x05 C_Profile_Colors[Color_Lime] = true; // \x06 C_Profile_Colors[Color_Lightred] = true; // \x07 C_Profile_Colors[Color_Grey] = true; // \x08 C_Profile_Colors[Color_Yellow] = true; // \x09 C_Profile_Colors[Color_Bluegrey] = true; // \x0A C_Profile_Colors[Color_Lightblue] = true; // \x0B C_Profile_Colors[Color_Darkblue] = true; // \x0C C_Profile_Colors[Color_Grey2] = true; // \x0D C_Profile_Colors[Color_Orchid] = true; // \x0E C_Profile_Colors[Color_Lightred2] = true; // \x0F C_Profile_Colors[Color_Orange] = true; // \x10 C_Profile_TeamIndex[Color_Red] = 2; C_Profile_TeamIndex[Color_Blue] = 3; C_Profile_SayText2 = true; } else if (engine == Engine_TF2) { C_Profile_Colors[Color_Lightgreen] = true; C_Profile_Colors[Color_Red] = true; C_Profile_Colors[Color_Blue] = true; C_Profile_Colors[Color_Olive] = true; C_Profile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; C_Profile_TeamIndex[Color_Red] = 2; C_Profile_TeamIndex[Color_Blue] = 3; C_Profile_SayText2 = true; } else if (engine == Engine_Left4Dead || engine == Engine_Left4Dead2) { C_Profile_Colors[Color_Lightgreen] = true; C_Profile_Colors[Color_Red] = true; C_Profile_Colors[Color_Blue] = true; C_Profile_Colors[Color_Olive] = true; C_Profile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; C_Profile_TeamIndex[Color_Red] = 3; C_Profile_TeamIndex[Color_Blue] = 2; C_Profile_SayText2 = true; } else if (engine == Engine_HL2DM) { /* hl2mp profile is based on mp_teamplay convar */ if (GetConVarBool(FindConVar("mp_teamplay"))) { C_Profile_Colors[Color_Red] = true; C_Profile_Colors[Color_Blue] = true; C_Profile_Colors[Color_Olive] = true; C_Profile_TeamIndex[Color_Red] = 3; C_Profile_TeamIndex[Color_Blue] = 2; C_Profile_SayText2 = true; } else { C_Profile_SayText2 = false; C_Profile_Colors[Color_Olive] = true; } } else if (engine == Engine_DODS) { C_Profile_Colors[Color_Olive] = true; C_Profile_SayText2 = false; } /* Profile for other games */ else { if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) { C_Profile_SayText2 = false; } else { C_Profile_Colors[Color_Red] = true; C_Profile_Colors[Color_Blue] = true; C_Profile_TeamIndex[Color_Red] = 2; C_Profile_TeamIndex[Color_Blue] = 3; C_Profile_SayText2 = true; } } } public Action C_Event_MapStart(Event event, const char[] name, bool dontBroadcast) { C_SetupProfile(); for (int i = 1; i <= MaxClients; ++i) { C_SkipList[i] = false; } } /** * Displays usage of an admin command to users depending on the * setting of the sm_show_activity cvar. * * This version does not display a message to the originating client * if used from chat triggers or menus. If manual replies are used * for these cases, then this function will suffice. Otherwise, * C_ShowActivity2() is slightly more useful. * Supports color tags. * * @param client Client index doing the action, or 0 for server. * @param format Formatting rules. * @param ... Variable number of format parameters. * @noreturn * @error */ stock int C_ShowActivity(int client, const char[] format, any ...) { if (sm_show_activity == null) { sm_show_activity = FindConVar("sm_show_activity"); } char tag[] = "[SM] "; char szBuffer[MAX_MESSAGE_LENGTH]; //char szCMessage[MAX_MESSAGE_LENGTH]; int value = sm_show_activity.IntValue; ReplySource replyto = GetCmdReplySource(); char name[MAX_NAME_LENGTH] = "Console"; char sign[MAX_NAME_LENGTH] = "ADMIN"; bool display_in_chat = false; if (client != 0) { if (client < 0 || client > MaxClients || !IsClientConnected(client)) { ThrowError("Client index %d is invalid", client); } GetClientName(client, name, sizeof(name)); AdminId id = GetUserAdmin(client); if (id == INVALID_ADMIN_ID || !GetAdminFlag(id, Admin_Generic, Access_Effective)) { sign = "PLAYER"; } /* Display the message to the client? */ if (replyto == SM_REPLY_TO_CONSOLE) { SetGlobalTransTarget(client); VFormat(szBuffer, sizeof(szBuffer), format, 3); C_RemoveTags(szBuffer, sizeof(szBuffer)); PrintToConsole(client, "%s%s\n", tag, szBuffer); display_in_chat = true; } } else { SetGlobalTransTarget(LANG_SERVER); VFormat(szBuffer, sizeof(szBuffer), format, 3); C_RemoveTags(szBuffer, sizeof(szBuffer)); PrintToServer("%s%s\n", tag, szBuffer); } if (!value) { return 1; } for (int i = 1; i <= MaxClients; ++i) { if (!IsClientInGame(i) || IsFakeClient(i) || (display_in_chat && i == client)) { continue; } AdminId id = GetUserAdmin(i); SetGlobalTransTarget(i); if (id == INVALID_ADMIN_ID || !GetAdminFlag(id, Admin_Generic, Access_Effective)) { /* Treat this as a normal user. */ if ((value & 1) | (value & 2)) { char newsign[MAX_NAME_LENGTH]; if ((value & 2) || (i == client)) { newsign = name; } else { newsign = sign; } VFormat(szBuffer, sizeof(szBuffer), format, 3); C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); } } else { /* Treat this as an admin user */ bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); if ((value & 4) || (value & 8) || ((value & 16) && is_root)) { char newsign[MAX_NAME_LENGTH]; if ((value & 8) || ((value & 16) && is_root) || (i == client)) { newsign = name; } else { newsign = sign; } VFormat(szBuffer, sizeof(szBuffer), format, 3); C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); } } } return 1; } /** * Same as C_ShowActivity(), except the tag parameter is used instead of "[SM] " (note that you must supply any spacing). * Supports color tags. * * @param client Client index doing the action, or 0 for server. * @param tags Tag to display with. * @param format Formatting rules. * @param ... Variable number of format parameters. * @noreturn * @error */ stock int C_ShowActivityEx(int client, const char[] tag, const char[] format, any ...) { if (sm_show_activity == null) { sm_show_activity = FindConVar("sm_show_activity"); } char szBuffer[MAX_MESSAGE_LENGTH]; //char szCMessage[MAX_MESSAGE_LENGTH]; int value = sm_show_activity.IntValue; ReplySource replyto = GetCmdReplySource(); char name[MAX_NAME_LENGTH] = "Console"; char sign[MAX_NAME_LENGTH] = "ADMIN"; bool display_in_chat = false; if (client != 0) { if (client < 0 || client > MaxClients || !IsClientConnected(client)) { ThrowError("Client index %d is invalid", client); } GetClientName(client, name, sizeof(name)); AdminId id = GetUserAdmin(client); if (id == INVALID_ADMIN_ID || !GetAdminFlag(id, Admin_Generic, Access_Effective)) { sign = "PLAYER"; } /* Display the message to the client? */ if (replyto == SM_REPLY_TO_CONSOLE) { SetGlobalTransTarget(client); VFormat(szBuffer, sizeof(szBuffer), format, 4); C_RemoveTags(szBuffer, sizeof(szBuffer)); PrintToConsole(client, "%s%s\n", tag, szBuffer); display_in_chat = true; } } else { SetGlobalTransTarget(LANG_SERVER); VFormat(szBuffer, sizeof(szBuffer), format, 4); C_RemoveTags(szBuffer, sizeof(szBuffer)); PrintToServer("%s%s\n", tag, szBuffer); } if (!value) { return 1; } for (int i = 1; i <= MaxClients; ++i) { if (!IsClientInGame(i) || IsFakeClient(i) || (display_in_chat && i == client)) { continue; } AdminId id = GetUserAdmin(i); SetGlobalTransTarget(i); if (id == INVALID_ADMIN_ID || !GetAdminFlag(id, Admin_Generic, Access_Effective)) { /* Treat this as a normal user. */ if ((value & 1) | (value & 2)) { char newsign[MAX_NAME_LENGTH]; if ((value & 2) || (i == client)) { newsign = name; } else { newsign = sign; } VFormat(szBuffer, sizeof(szBuffer), format, 4); C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); } } else { /* Treat this as an admin user */ bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); if ((value & 4) || (value & 8) || ((value & 16) && is_root)) { char newsign[MAX_NAME_LENGTH]; if ((value & 8) || ((value & 16) && is_root) || (i == client)) { newsign = name; } else { newsign = sign; } VFormat(szBuffer, sizeof(szBuffer), format, 4); C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); } } } return 1; } /** * Displays usage of an admin command to users depending on the setting of the sm_show_activity cvar. * All users receive a message in their chat text, except for the originating client, * who receives the message based on the current ReplySource. * Supports color tags. * * @param client Client index doing the action, or 0 for server. * @param tags Tag to prepend to the message. * @param format Formatting rules. * @param ... Variable number of format parameters. * @noreturn * @error */ stock int C_ShowActivity2(int client, const char[] tag, const char[] format, any ...) { if (sm_show_activity == null) { sm_show_activity = FindConVar("sm_show_activity"); } char szBuffer[MAX_MESSAGE_LENGTH]; //char szCMessage[MAX_MESSAGE_LENGTH]; int value = sm_show_activity.IntValue; // ReplySource replyto = GetCmdReplySource(); char name[MAX_NAME_LENGTH] = "Console"; char sign[MAX_NAME_LENGTH] = "ADMIN"; if (client != 0) { if (client < 0 || client > MaxClients || !IsClientConnected(client)) { ThrowError("Client index %d is invalid", client); } GetClientName(client, name, sizeof(name)); AdminId id = GetUserAdmin(client); if (id == INVALID_ADMIN_ID || !GetAdminFlag(id, Admin_Generic, Access_Effective)) { sign = "PLAYER"; } SetGlobalTransTarget(client); VFormat(szBuffer, sizeof(szBuffer), format, 4); /* We don't display directly to the console because the chat text * simply gets added to the console, so we don't want it to print * twice. */ C_PrintToChatEx(client, client, "%s%s", tag, szBuffer); } else { SetGlobalTransTarget(LANG_SERVER); VFormat(szBuffer, sizeof(szBuffer), format, 4); C_RemoveTags(szBuffer, sizeof(szBuffer)); PrintToServer("%s%s\n", tag, szBuffer); } if (!value) { return 1; } for (int i = 1; i <= MaxClients; ++i) { if (!IsClientInGame(i) || IsFakeClient(i) || i == client) { continue; } AdminId id = GetUserAdmin(i); SetGlobalTransTarget(i); if (id == INVALID_ADMIN_ID || !GetAdminFlag(id, Admin_Generic, Access_Effective)) { /* Treat this as a normal user. */ if ((value & 1) | (value & 2)) { char newsign[MAX_NAME_LENGTH]; if ((value & 2)) { newsign = name; } else { newsign = sign; } VFormat(szBuffer, sizeof(szBuffer), format, 4); C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); } } else { /* Treat this as an admin user */ bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); if ((value & 4) || (value & 8) || ((value & 16) && is_root)) { char newsign[MAX_NAME_LENGTH]; if ((value & 8) || ((value & 16) && is_root)) { newsign = name; } else { newsign = sign; } VFormat(szBuffer, sizeof(szBuffer), format, 4); C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); } } } return 1; }