diff --git a/advertisements/include/advertisements.sp b/advertisements/include/advertisements.sp new file mode 100644 index 00000000..57b6eef5 --- /dev/null +++ b/advertisements/include/advertisements.sp @@ -0,0 +1,216 @@ +StringMap g_hTopColors; + +void AddTopColors() +{ + if (!g_hTopColors) { + g_hTopColors = new StringMap(); + } + + AddTopColor("aliceblue", "F0F8FF"); + AddTopColor("allies", "4D7942"); + AddTopColor("ancient", "EB4B4B"); + AddTopColor("antiquewhite", "FAEBD7"); + AddTopColor("aqua", "00FFFF"); + AddTopColor("aquamarine", "7FFFD4"); + AddTopColor("arcana", "ADE55C"); + AddTopColor("axis", "FF4040"); + AddTopColor("azure", "007FFF"); + AddTopColor("beige", "F5F5DC"); + AddTopColor("bisque", "FFE4C4"); + AddTopColor("black", "000000"); + AddTopColor("blanchedalmond", "FFEBCD"); + AddTopColor("blue", "99CCFF"); + AddTopColor("blueviolet", "8A2BE2"); + AddTopColor("brown", "A52A2A"); + AddTopColor("burlywood", "DEB887"); + AddTopColor("cadetblue", "5F9EA0"); + AddTopColor("chartreuse", "7FFF00"); + AddTopColor("chocolate", "D2691E"); + AddTopColor("collectors", "AA0000"); + AddTopColor("common", "B0C3D9"); + AddTopColor("community", "70B04A"); + AddTopColor("coral", "FF7F50"); + AddTopColor("cornflowerblue", "6495ED"); + AddTopColor("cornsilk", "FFF8DC"); + AddTopColor("corrupted", "A32C2E"); + AddTopColor("crimson", "DC143C"); + AddTopColor("cyan", "00FFFF"); + AddTopColor("darkblue", "00008B"); + AddTopColor("darkcyan", "008B8B"); + AddTopColor("darkgoldenrod", "B8860B"); + AddTopColor("darkgray", "A9A9A9"); + AddTopColor("darkgrey", "A9A9A9"); + AddTopColor("darkgreen", "006400"); + AddTopColor("darkkhaki", "BDB76B"); + AddTopColor("darkmagenta", "8B008B"); + AddTopColor("darkolivegreen", "556B2F"); + AddTopColor("darkorange", "FF8C00"); + AddTopColor("darkorchid", "9932CC"); + AddTopColor("darkred", "8B0000"); + AddTopColor("darksalmon", "E9967A"); + AddTopColor("darkseagreen", "8FBC8F"); + AddTopColor("darkslateblue", "483D8B"); + AddTopColor("darkslategray", "2F4F4F"); + AddTopColor("darkslategrey", "2F4F4F"); + AddTopColor("darkturquoise", "00CED1"); + AddTopColor("darkviolet", "9400D3"); + AddTopColor("deeppink", "FF1493"); + AddTopColor("deepskyblue", "00BFFF"); + AddTopColor("dimgray", "696969"); + AddTopColor("dimgrey", "696969"); + AddTopColor("dodgerblue", "1E90FF"); + AddTopColor("exalted", "CCCCCD"); + AddTopColor("firebrick", "B22222"); + AddTopColor("floralwhite", "FFFAF0"); + AddTopColor("forestgreen", "228B22"); + AddTopColor("frozen", "4983B3"); + AddTopColor("fuchsia", "FF00FF"); + AddTopColor("fullblue", "0000FF"); + AddTopColor("fullred", "FF0000"); + AddTopColor("gainsboro", "DCDCDC"); + AddTopColor("genuine", "4D7455"); + AddTopColor("ghostwhite", "F8F8FF"); + AddTopColor("gold", "FFD700"); + AddTopColor("goldenrod", "DAA520"); + AddTopColor("gray", "CCCCCC"); + AddTopColor("grey", "CCCCCC"); + AddTopColor("green", "3EFF3E"); + AddTopColor("greenyellow", "ADFF2F"); + AddTopColor("haunted", "38F3AB"); + AddTopColor("honeydew", "F0FFF0"); + AddTopColor("hotpink", "FF69B4"); + AddTopColor("immortal", "E4AE33"); + AddTopColor("indianred", "CD5C5C"); + AddTopColor("indigo", "4B0082"); + AddTopColor("ivory", "FFFFF0"); + AddTopColor("khaki", "F0E68C"); + AddTopColor("lavender", "E6E6FA"); + AddTopColor("lavenderblush", "FFF0F5"); + AddTopColor("lawngreen", "7CFC00"); + AddTopColor("legendary", "D32CE6"); + AddTopColor("lemonchiffon", "FFFACD"); + AddTopColor("lightblue", "ADD8E6"); + AddTopColor("lightcoral", "F08080"); + AddTopColor("lightcyan", "E0FFFF"); + AddTopColor("lightgoldenrodyellow", "FAFAD2"); + AddTopColor("lightgray", "D3D3D3"); + AddTopColor("lightgrey", "D3D3D3"); + AddTopColor("lightgreen", "99FF99"); + AddTopColor("lightpink", "FFB6C1"); + AddTopColor("lightsalmon", "FFA07A"); + AddTopColor("lightseagreen", "20B2AA"); + AddTopColor("lightskyblue", "87CEFA"); + AddTopColor("lightslategray", "778899"); + AddTopColor("lightslategrey", "778899"); + AddTopColor("lightsteelblue", "B0C4DE"); + AddTopColor("lightyellow", "FFFFE0"); + AddTopColor("lime", "00FF00"); + AddTopColor("limegreen", "32CD32"); + AddTopColor("linen", "FAF0E6"); + AddTopColor("magenta", "FF00FF"); + AddTopColor("maroon", "800000"); + AddTopColor("mediumaquamarine", "66CDAA"); + AddTopColor("mediumblue", "0000CD"); + AddTopColor("mediumorchid", "BA55D3"); + AddTopColor("mediumpurple", "9370D8"); + AddTopColor("mediumseagreen", "3CB371"); + AddTopColor("mediumslateblue", "7B68EE"); + AddTopColor("mediumspringgreen", "00FA9A"); + AddTopColor("mediumturquoise", "48D1CC"); + AddTopColor("mediumvioletred", "C71585"); + AddTopColor("midnightblue", "191970"); + AddTopColor("mintcream", "F5FFFA"); + AddTopColor("mistyrose", "FFE4E1"); + AddTopColor("moccasin", "FFE4B5"); + AddTopColor("mythical", "8847FF"); + AddTopColor("navajowhite", "FFDEAD"); + AddTopColor("navy", "000080"); + AddTopColor("normal", "B2B2B2"); + AddTopColor("oldlace", "FDF5E6"); + AddTopColor("olive", "9EC34F"); + AddTopColor("olivedrab", "6B8E23"); + AddTopColor("orange", "FFA500"); + AddTopColor("orangered", "FF4500"); + AddTopColor("orchid", "DA70D6"); + AddTopColor("palegoldenrod", "EEE8AA"); + AddTopColor("palegreen", "98FB98"); + AddTopColor("paleturquoise", "AFEEEE"); + AddTopColor("palevioletred", "D87093"); + AddTopColor("papayawhip", "FFEFD5"); + AddTopColor("peachpuff", "FFDAB9"); + AddTopColor("peru", "CD853F"); + AddTopColor("pink", "FFC0CB"); + AddTopColor("plum", "DDA0DD"); + AddTopColor("powderblue", "B0E0E6"); + AddTopColor("purple", "800080"); + AddTopColor("rare", "4B69FF"); + AddTopColor("red", "FF4040"); + AddTopColor("rosybrown", "BC8F8F"); + AddTopColor("royalblue", "4169E1"); + AddTopColor("saddlebrown", "8B4513"); + AddTopColor("salmon", "FA8072"); + AddTopColor("sandybrown", "F4A460"); + AddTopColor("seagreen", "2E8B57"); + AddTopColor("seashell", "FFF5EE"); + AddTopColor("selfmade", "70B04A"); + AddTopColor("sienna", "A0522D"); + AddTopColor("silver", "C0C0C0"); + AddTopColor("skyblue", "87CEEB"); + AddTopColor("slateblue", "6A5ACD"); + AddTopColor("slategray", "708090"); + AddTopColor("slategrey", "708090"); + AddTopColor("snow", "FFFAFA"); + AddTopColor("springgreen", "00FF7F"); + AddTopColor("steelblue", "4682B4"); + AddTopColor("strange", "CF6A32"); + AddTopColor("tan", "D2B48C"); + AddTopColor("teal", "008080"); + AddTopColor("thistle", "D8BFD8"); + AddTopColor("tomato", "FF6347"); + AddTopColor("turquoise", "40E0D0"); + AddTopColor("uncommon", "B0C3D9"); + AddTopColor("unique", "FFD700"); + AddTopColor("unusual", "8650AC"); + AddTopColor("valve", "A50F79"); + AddTopColor("vintage", "476291"); + AddTopColor("violet", "EE82EE"); + AddTopColor("wheat", "F5DEB3"); + AddTopColor("white", "FFFFFF"); + AddTopColor("whitesmoke", "F5F5F5"); + AddTopColor("yellow", "FFFF00"); + AddTopColor("yellowgreen", "9ACD32"); +} + +void AddTopColor(const char[] sName, const char[] sColor) +{ + int aColor[4]; + ParseColor(sColor, aColor); + + g_hTopColors.SetArray(sName, aColor, sizeof(aColor)); +} + +void ParseColor(const char[] sColor, int aColor[4]) +{ + int iColor = StringToInt(sColor, 16); + aColor[0] = iColor >> 16; + aColor[1] = iColor >> 8 & 255; + aColor[2] = iColor & 255; + aColor[3] = 255; +} + +void ParseTopColor(const char[] sText, int &iStart, int aColor[4]) +{ + int iEnd = StrContains(sText, "}"); + if (sText[0] != '{' || iEnd == -1) { + return; + } + + char sColor[32]; + strcopy(sColor, iEnd, sText[1]); + if (sColor[0] == '#') { + ParseColor(sColor[1], aColor); + } else { + g_hTopColors.GetArray(sColor, aColor, sizeof(aColor)); + } + iStart = iEnd + 1; +} \ No newline at end of file diff --git a/advertisements/include/colorvariables.inc b/advertisements/include/colorvariables.inc new file mode 100644 index 00000000..6d709706 --- /dev/null +++ b/advertisements/include/colorvariables.inc @@ -0,0 +1,1034 @@ +#if defined _colorvariables_included + #endinput +#endif +#define _colorvariables_included "1.3" + +// Author: Raska aka KissLick + +// ---------------------------------------------------------------------------------------- +#define _CV_MAX_MESSAGE_LENGTH 1024 +#define _CV_MAX_VARIABLE_REDIRECTS 10 +#define _CV_CONFIG_DIRECTORY "configs/colorvariables" + +static bool:g_bInit = false; +static Handle:g_hColors = INVALID_HANDLE; +static String:g_sConfigGlobal[PLATFORM_MAX_PATH]; +static String:g_sConfig[PLATFORM_MAX_PATH]; +static String:g_sChatPrefix[64] = ""; + +static bool:g_bIgnorePrefix = false; +static g_iAuthor; +static bool:g_bSkipPlayers[MAXPLAYERS + 1] = {false, ...}; + +static Handle:g_hForwardedVariable; + +enum triple { + unknown = -1, + yes = true, + no = false +} +static triple:g_IsSource2009 = unknown; +// ---------------------------------------------------------------------------------------- + +forward COnForwardedVariable(String:sCode[], String:sData[], iDataSize, String:sColor[], iColorSize); + +stock CSetPrefix(const String:sPrefix[], any:...) +{ + VFormat(g_sChatPrefix, sizeof(g_sChatPrefix), sPrefix, 2); +} + +stock CSavePrefix(const String:sPrefix[], any:...) +{ + new String:m_sPrefix[64]; + VFormat(m_sPrefix, sizeof(m_sPrefix), sPrefix, 2); + + CAddVariable("&prefix", m_sPrefix, true); +} + +stock CSkipNextPrefix() +{ + g_bIgnorePrefix = true; +} + +stock CSetNextAuthor(iClient) +{ + if (iClient < 1 || iClient > MaxClients || !IsClientInGame(iClient)) { + ThrowError("Invalid client index %i", iClient); + } + g_iAuthor = iClient; +} + +stock CSkipNextClient(iClient) +{ + if (iClient < 1 || iClient > MaxClients) { + ThrowError("Invalid client index %i", iClient); + } + g_bSkipPlayers[iClient] = true; +} + +stock CPrintToChat(iClient, const String:sMessage[], any:...) +{ + if (iClient < 1 || iClient > MaxClients) { + ThrowError("Invalid client index %d", iClient); + } + + if (!IsClientInGame(iClient)) { + ThrowError("Client %d is not in game", iClient); + } + + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); + + AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); + g_bIgnorePrefix = false; + + CProcessVariables(sBuffer, sizeof(sBuffer)); + CAddWhiteSpace(sBuffer, sizeof(sBuffer)); + + SendPlayerMessage(iClient, sBuffer, g_iAuthor); + g_iAuthor = 0; +} + +stock CPrintToChatAll(const String:sMessage[], any:...) +{ + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; + + for (new iClient = 1; iClient <= MaxClients; iClient++) { + if (!IsClientInGame(iClient) || g_bSkipPlayers[iClient]) { + g_bSkipPlayers[iClient] = false; + continue; + } + + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 2); + + AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); + g_bIgnorePrefix = false; + + CProcessVariables(sBuffer, sizeof(sBuffer)); + CAddWhiteSpace(sBuffer, sizeof(sBuffer)); + + SendPlayerMessage(iClient, sBuffer, g_iAuthor); + } + g_iAuthor = 0; +} + +stock CPrintToChatTeam(iTeam, const String:sMessage[], any:...) +{ + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; + + for (new iClient = 1; iClient <= MaxClients; iClient++) { + if (!IsClientInGame(iClient) || GetClientTeam(iClient) != iTeam || g_bSkipPlayers[iClient]) { + g_bSkipPlayers[iClient] = false; + continue; + } + + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); + + AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); + g_bIgnorePrefix = false; + + CProcessVariables(sBuffer, sizeof(sBuffer)); + CAddWhiteSpace(sBuffer, sizeof(sBuffer)); + + SendPlayerMessage(iClient, sBuffer, g_iAuthor); + } + g_iAuthor = 0; +} + +stock CPrintToChatAdmins(iBitFlags, const String:sMessage[], any:...) +{ + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; + new AdminId:iAdminID; + + for (new iClient = 1; iClient <= MaxClients; iClient++) { + if (!IsClientInGame(iClient) || GetClientTeam(iClient) != iTeam || g_bSkipPlayers[iClient]) { + g_bSkipPlayers[iClient] = false; + continue; + } + + iAdminID = GetUserAdmin(iClient); + if (iAdminID == INVALID_ADMIN_ID || GetAdminFlags(iAdminID, Access_Effective) ~ iBitFlags) { + continue; + } + + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); + + AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); + g_bIgnorePrefix = false; + + CProcessVariables(sBuffer, sizeof(sBuffer)); + CAddWhiteSpace(sBuffer, sizeof(sBuffer)); + + SendPlayerMessage(iClient, sBuffer, g_iAuthor); + } + g_iAuthor = 0; +} + +stock CReplyToCommand(iClient, const String:sMessage[], any:...) +{ + if (iClient < 0 || iClient > MaxClients) { + ThrowError("Invalid client index %d", iClient); + } + + if (iClient != 0 && !IsClientInGame(iClient)) { + ThrowError("Client %d is not in game", iClient); + } + + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); + + AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer), "reply2cmd"); + g_bIgnorePrefix = false; + + if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { + CRemoveColors(sBuffer, sizeof(sBuffer)); + PrintToConsole(iClient, "%s", sBuffer); + } else { + CPrintToChat(iClient, "%s", sBuffer); + } +} + +stock CShowActivity(iClient, const String:sMessage[], any:...) +{ + if (iClient < 0 || iClient > MaxClients) { + ThrowError("Invalid client index %d", iClient); + } + + if (iClient != 0 && !IsClientInGame(iClient)) { + ThrowError("Client %d is not in game", iClient); + } + + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); + Format(sBuffer, sizeof(sBuffer), "{showactivity}%s", sBuffer); + CProcessVariables(sBuffer, sizeof(sBuffer)); + CAddWhiteSpace(sBuffer, sizeof(sBuffer)); + + ShowActivity(iClient, "%s", sBuffer); +} + +stock CShowActivityEx(iClient, const String:sTag[], const String:sMessage[], any:...) +{ + if (iClient < 0 || iClient > MaxClients) { + ThrowError("Invalid client index %d", iClient); + } + + if (iClient != 0 && !IsClientInGame(iClient)) { + ThrowError("Client %d is not in game", iClient); + } + + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH], String:sBufferTag[_CV_MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 4); + Format(sBuffer, sizeof(sBuffer), "{showactivity}%s", sBuffer); + CProcessVariables(sBuffer, sizeof(sBuffer)); + Format(sBufferTag, sizeof(sBufferTag), "{prefix}%s", sTag); + CProcessVariables(sBufferTag, sizeof(sBufferTag)); + CAddWhiteSpace(sBuffer, sizeof(sBuffer)); + CAddWhiteSpace(sBufferTag, sizeof(sBufferTag)); + + ShowActivityEx(iClient, sBufferTag, " %s", sBuffer); +} + +stock CShowActivity2(iClient, const String:sTag[], const String:sMessage[], any:...) +{ + if (iClient < 0 || iClient > MaxClients) { + ThrowError("Invalid client index %d", iClient); + } + + if (iClient != 0 && !IsClientInGame(iClient)) { + ThrowError("Client %d is not in game", iClient); + } + + decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH], String:sBufferTag[_CV_MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(iClient); + VFormat(sBuffer, sizeof(sBuffer), sMessage, 4); + Format(sBuffer, sizeof(sBuffer), "{showactivity}%s", sBuffer); + CProcessVariables(sBuffer, sizeof(sBuffer)); + Format(sBufferTag, sizeof(sBufferTag), "{prefix}%s", sTag); + CProcessVariables(sBufferTag, sizeof(sBufferTag)); + CAddWhiteSpace(sBuffer, sizeof(sBuffer)); + CAddWhiteSpace(sBufferTag, sizeof(sBufferTag)); + + ShowActivityEx(iClient, sBufferTag, " %s", sBuffer); +} + +stock CAddVariable(String:sName[], String:sValue[], bool:bOnlySaveToConfig = false) +{ + if (Init()) { + if (!FileExists(g_sConfig)) { + LogError("Cannot add color variable to '%s' - file doesn't exist!", g_sConfig); + return; + } + + new Handle:hKV = CreateKeyValues("colorvariables"); + + if (!FileToKeyValues(hKV, g_sConfig)) { + CloseHandle(hKV); + LogError("Cannot open file (for adding color variable) '%s' !", g_sConfig); + return; + } + + if (!KvJumpToKey(hKV, sName)) { + StringToLower(sName); + KvSetString(hKV, sName, sValue); + + if (!bOnlySaveToConfig) { + new Handle:hRedirect = CreateArray(64); + PushArrayString(hRedirect, sName); + SetTrieString(g_hColors, sName, sValue); + SolveRedirects(g_hColors, hRedirect); + CloseHandle(hRedirect); + } + } + + KvRewind(hKV); + KeyValuesToFile(hKV, g_sConfig); + CloseHandle(hKV); + } +} + +stock CLoadPluginConfig(const String:sPluginName[], bool:bAllowPrefix = true) +{ + if (Init()) { + new String:sConfig[PLATFORM_MAX_PATH]; + strcopy(sConfig, sizeof(sConfig), sPluginName); + ReplaceStringEx(sConfig, sizeof(sConfig), ".smx", ""); + BuildPath(Path_SM, sConfig, sizeof(sConfig), "%s/plugin.%s.cfg", _CV_CONFIG_DIRECTORY, sConfig); + + if (!FileExists(sConfig)) { + LogError("Cannot load color variables from file '%s' - file doesn't exist!", sConfig); + return; + } + + new Handle:hRedirect = CreateArray(64); + LoadConfigFile(g_hColors, sConfig, hRedirect, bAllowPrefix); + SolveRedirects(g_hColors, hRedirect); + CloseHandle(hRedirect); + } +} + +stock CLoadPluginVariables(const String:sPluginName[], const String:sVariables[][], iVariablesCount, bool:bAllowPrefix = true) +{ + if (Init() && iVariablesCount > 0) { + new String:sConfig[PLATFORM_MAX_PATH]; + strcopy(sConfig, sizeof(sConfig), sPluginName); + ReplaceStringEx(sConfig, sizeof(sConfig), ".smx", ""); + BuildPath(Path_SM, sConfig, sizeof(sConfig), "%s/plugin.%s.cfg", _CV_CONFIG_DIRECTORY, sConfig); + + if (!FileExists(sConfig)) { + LogError("Cannot load color variables from file '%s' - file doesn't exist!", sConfig); + return; + } + + new Handle:hVariables = CreateTrie(); + new Handle:hRedirect = CreateArray(64); + LoadConfigFile(hVariables, sConfig, hRedirect, bAllowPrefix); + SolveRedirects(hVariables, hRedirect); + ClearArray(hRedirect); + + new String:sCode[64], String:sColor[64]; + + for (new i = 0; i < iVariablesCount; i++) { + strcopy(sCode, sizeof(sCode), sVariables[i]); + StringToLower(sCode); + + if (GetTrieString(hVariables, sCode, sColor, sizeof(sColor))) { + SetTrieString(g_hColors, sCode, sColor); + PushArrayString(hRedirect, sCode); + } + } + + SolveRedirects(g_hColors, hRedirect); + CloseHandle(hRedirect); + CloseHandle(hVariables); + } +} + +stock CRemoveColors(String:sMsg[], iSize) +{ + CProcessVariables(sMsg, iSize, true); +} + +stock CProcessVariables(String:sMsg[], iSize, bool:bRemoveColors = false) +{ + if (!Init()) { + return; + } + + new String:sOut[iSize], String:sCode[iSize], String:sColor[iSize]; + new iOutPos = 0, iCodePos = -1; + new iMsgLen = strlen(sMsg); + + for (new i = 0; i < iMsgLen; i++) { + if (sMsg[i] == '{') { + iCodePos = 0; + } + + if (iCodePos > -1) { + sCode[iCodePos] = sMsg[i]; + sCode[iCodePos + 1] = '\0'; + + if (sMsg[i] == '}' || i == iMsgLen - 1) { + strcopy(sCode, strlen(sCode) - 1, sCode[1]); + StringToLower(sCode); + + if (CGetColor(sCode, sColor, iSize)) { + if (!bRemoveColors) { + StrCat(sOut, iSize, sColor); + iOutPos += strlen(sColor); + } + } else { + Format(sOut, iSize, "%s{%s}", sOut, sCode); + iOutPos += strlen(sCode) + 2; + } + + iCodePos = -1; + strcopy(sCode, iSize, ""); + strcopy(sColor, iSize, ""); + } else { + iCodePos++; + } + + continue; + } + + sOut[iOutPos] = sMsg[i]; + iOutPos++; + sOut[iOutPos] = '\0'; + } + + strcopy(sMsg, iSize, sOut); +} + +stock bool:CGetColor(const String:sName[], String:sColor[], iColorSize) +{ + if (sName[0] == '\0') + return false; + + if (sName[0] == '@') { + new iSpace; + new String:sData[64], String:m_sName[64]; + strcopy(m_sName, sizeof(m_sName), sName[1]); + + if ((iSpace = FindCharInString(m_sName, ' ')) != -1 && (iSpace + 1 < strlen(m_sName))) { + strcopy(m_sName, iSpace + 1, m_sName); + strcopy(sData, sizeof(sData), m_sName[iSpace + 1]); + } + + Call_StartForward(g_hForwardedVariable); + Call_PushString(m_sName); + Call_PushStringEx(sData, sizeof(sData), SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, 0); + Call_PushCell(sizeof(sData)); + Call_PushStringEx(sColor, iColorSize, SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); + Call_PushCell(iColorSize); + Call_Finish(); + + if (sColor[0] != '\0') { + return true; + } + + } else if (sName[0] == '#') { + if (strlen(sName) == 7) { + Format(sColor, iColorSize, "\x07%s", sName[1]); + return true; + } + if (strlen(sName) == 9) { + Format(sColor, iColorSize, "\x08%s", sName[1]); + return true; + } + } else if (StrContains(sName, "player ", false) == 0 && strlen(sName) > 7) { + new iClient = StringToInt(sName[7]); + + if (iClient < 1 || iClient > MaxClients || !IsClientInGame(iClient)) { + strcopy(sColor, iColorSize, "\x01"); + LogError("Invalid client index %d", iClient); + return false; + } + + strcopy(sColor, iColorSize, "\x01"); + switch (GetClientTeam(iClient)) { + case 1: {GetTrieString(g_hColors, "team0", sColor, iColorSize);} + case 2: {GetTrieString(g_hColors, "team1", sColor, iColorSize);} + case 3: {GetTrieString(g_hColors, "team2", sColor, iColorSize);} + } + return true; + } else { + return GetTrieString(g_hColors, sName, sColor, iColorSize); + } + + return false; +} + +stock bool:CExistColor(const String:sName[]) +{ + if (sName[0] == '\0' || sName[0] == '@' || sName[0] == '#') + return false; + + new String:sColor[64]; + return GetTrieString(g_hColors, sName, sColor, sizeof(sColor)); +} + +stock CSayText2(iClient, String:sMessage[], iAuthor) +{ + new Handle:hMsg = StartMessageOne("SayText2", iClient, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); + if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) { + PbSetInt(hMsg, "ent_idx", iAuthor); + PbSetBool(hMsg, "chat", true); + PbSetString(hMsg, "msg_name", sMessage); + PbAddString(hMsg, "params", ""); + PbAddString(hMsg, "params", ""); + PbAddString(hMsg, "params", ""); + PbAddString(hMsg, "params", ""); + } else { + BfWriteByte(hMsg, iAuthor); + BfWriteByte(hMsg, true); + BfWriteString(hMsg, sMessage); + } + EndMessage(); +} + +stock CAddWhiteSpace(String:sBuffer[], iSize) +{ + if (!IsSource2009()) { + Format(sBuffer, iSize, " %s", sBuffer); + } +} + +// ---------------------------------------------------------------------------------------- +// Private stuff +// ---------------------------------------------------------------------------------------- + +stock bool:Init() +{ + if (g_bInit) { + LoadColors(); + return true; + } + + new String:sPluginName[PLATFORM_MAX_PATH]; + new String:sDirectoryPath[PLATFORM_MAX_PATH]; + new Handle:hConfig = INVALID_HANDLE; + GetPluginFilename(INVALID_HANDLE, sPluginName, sizeof(sPluginName)); + ReplaceStringEx(sPluginName, sizeof(sPluginName), "\\", "/"); + new iSlash = FindCharInString(sPluginName, '/', true); + if (iSlash > -1) { + strcopy(sPluginName, sizeof(sPluginName), sPluginName[iSlash + 1]); + } + ReplaceStringEx(sPluginName, sizeof(sPluginName), ".smx", ""); + + BuildPath(Path_SM, sDirectoryPath, sizeof(sDirectoryPath), "%s/", _CV_CONFIG_DIRECTORY); + if (!DirExists(sDirectoryPath)) + CreateDirectory(sDirectoryPath, 511); + + new String:sGlobalVariableList[15][2][64] = { + {"prefix", "{engine 2}"}, + {"default", "{engine 1}"}, + {"reply2cmd", "{engine 1}"}, + {"showactivity", "{engine 1}"}, + {"", ""}, + {"error", "{engine 3}"}, + {"", ""}, + {"highlight", "{engine 2}"}, + {"player", "{engine 2}"}, + {"settings", "{engine 2}"}, + {"command", "{engine 2}"}, + {"", ""}, + {"team0", "{engine 8}"}, + {"team1", "{engine 9}"}, + {"team2", "{engine 11}"} + }; + + if (IsSource2009()) { + strcopy(sGlobalVariableList[12][1], 64, "{#cccccc}"); + strcopy(sGlobalVariableList[13][1], 64, "{#ff4040}"); + strcopy(sGlobalVariableList[14][1], 64, "{#4d7942}"); + } + + BuildPath(Path_SM, g_sConfigGlobal, sizeof(g_sConfigGlobal), "%s/global.cfg", _CV_CONFIG_DIRECTORY); + if (!FileExists(g_sConfigGlobal)) { + hConfig = OpenFile(g_sConfigGlobal, "w"); + if (hConfig == INVALID_HANDLE) { + LogError("Cannot create file '%s' !", g_sConfigGlobal); + return false; + } + + WriteFileLine(hConfig, "// Version: %s", _colorvariables_included); + WriteFileLine(hConfig, "\"colorvariables\""); + WriteFileLine(hConfig, "{"); + for (new i = 0; i < 15; i++) { + if (sGlobalVariableList[i][0][0] == '\0') { + WriteFileLine(hConfig, ""); + } else { + WriteFileLine(hConfig, "\t\"%s\" \"%s\"", sGlobalVariableList[i][0], sGlobalVariableList[i][1]); + } + } + WriteFileLine(hConfig, "}"); + + CloseHandle(hConfig); + hConfig = INVALID_HANDLE; + } else { + hConfig = OpenFile(g_sConfigGlobal, "r"); + if (hConfig == INVALID_HANDLE) { + LogError("Cannot read from file '%s' !", g_sConfigGlobal); + return false; + } + + new String:sVersionLine[64]; + ReadFileLine(hConfig, sVersionLine, sizeof(sVersionLine)); + CloseHandle(hConfig); + + TrimString(sVersionLine); + strcopy(sVersionLine, sizeof(sVersionLine), sVersionLine[FindCharInString(sVersionLine, ':') + 2]); + + if (StringToFloat(sVersionLine) < StringToFloat(_colorvariables_included)) { + new Handle:hKV = CreateKeyValues("colorvariables"); + + if (!FileToKeyValues(hKV, g_sConfigGlobal) || !KvGotoFirstSubKey(hKV, false)) { + CloseHandle(hKV); + LogError("Cannot read variables from file '%s' !", g_sConfigGlobal); + return false; + } + + for (new i = 0; i < 15; i++) { + if (sGlobalVariableList[i][0][0] == '\0') + continue; + + if (!KvJumpToKey(hKV, sGlobalVariableList[i][0])) + KvSetString(hKV, sGlobalVariableList[i][0], sGlobalVariableList[i][1]); + } + + hConfig = OpenFile(g_sConfigGlobal, "w"); + if (hConfig == INVALID_HANDLE) { + LogError("Cannot write to file '%s' !", g_sConfigGlobal); + return false; + } + + WriteFileLine(hConfig, "// Version: %s", _colorvariables_included); + WriteFileLine(hConfig, "\"colorvariables\""); + WriteFileLine(hConfig, "{"); + + new String:sCode[64], String:sColor[64]; + + KvGotoFirstSubKey(hKV, false); + do + { + KvGetSectionName(hKV, sCode, sizeof(sCode)); + KvGetString(hKV, NULL_STRING, sColor, sizeof(sColor)); + StringToLower(sCode); + StringToLower(sColor); + + WriteFileLine(hConfig, "\t\"%s\" \"%s\"", sCode, sColor); + } while (KvGotoNextKey(hKV, false)); + + WriteFileLine(hConfig, "}"); + + CloseHandle(hConfig); + CloseHandle(hKV); + } + } + + BuildPath(Path_SM, g_sConfig, sizeof(g_sConfig), "%s/plugin.%s.cfg", _CV_CONFIG_DIRECTORY, sPluginName); + if (!FileExists(g_sConfig)) { + hConfig = OpenFile(g_sConfig, "w"); + if (hConfig == INVALID_HANDLE) { + LogError("Cannot create file '%s' !", g_sConfig); + return false; + } + + WriteFileLine(hConfig, "\"colorvariables\"\n{\n}"); + CloseHandle(hConfig); + hConfig = INVALID_HANDLE; + } + + for (new iClient = 1; iClient <= MaxClients; iClient++) { + g_bSkipPlayers[iClient] = false; + } + + g_hForwardedVariable = CreateGlobalForward("COnForwardedVariable", ET_Ignore, Param_String, Param_String, Param_Cell, Param_String, Param_Cell); + + LoadColors(); + g_bInit = true; + return true; +} + +stock static LoadColors() +{ + if (g_hColors == INVALID_HANDLE) { + g_hColors = CreateTrie(); + new Handle:hRedirect = CreateArray(64); + + AddColors(g_hColors); + LoadConfigFile(g_hColors, g_sConfigGlobal, hRedirect); + LoadConfigFile(g_hColors, g_sConfig, hRedirect); + + SolveRedirects(g_hColors, hRedirect); + CloseHandle(hRedirect); + } +} + +stock static LoadConfigFile(Handle:hTrie, String:sPath[], Handle:hRedirect, bool:bAllowPrefix = true) +{ + if (!FileExists(sPath)) { + LogError("Cannot load color variables from file '%s' - file doesn't exist!", sPath); + return; + } + + new Handle:hKV = CreateKeyValues("colorvariables"); + + if (!FileToKeyValues(hKV, sPath)) { + CloseHandle(hKV); + LogError("Cannot load color variables from file '%s' !", sPath); + return; + } + + if (!KvGotoFirstSubKey(hKV, false)) { + CloseHandle(hKV); + return; + } + + new String:sCode[64], String:sColor[64]; + + do + { + KvGetSectionName(hKV, sCode, sizeof(sCode)); + KvGetString(hKV, NULL_STRING, sColor, sizeof(sColor)); + + if (bAllowPrefix && StrEqual(sCode, "&prefix", false)) { + CSetPrefix(sColor); + continue; + } + + StringToLower(sCode); + + if (HasBrackets(sColor) && sColor[1] == '@') { + LogError("Variables cannot be redirected to forwarded variables! (variable '%s')", sCode); + continue; + } + + if (HasBrackets(sColor)) { + if (sColor[1] == '#') { + Format(sColor, sizeof(sColor), "\x07%s", sColor[1]); + } else { + PushArrayString(hRedirect, sCode); + } + } + + SetTrieString(hTrie, sCode, sColor); + } while (KvGotoNextKey(hKV, false)); + + CloseHandle(hKV); +} + +stock static SolveRedirects(Handle:hTrie, Handle:hRedirect) +{ + new String:sCode[64], String:sRedirect[64], String:sColor[64], String:sFirstColor[64]; + new iRedirectLife, bool:bHasBrackets; + + for (new i = 0; i < GetArraySize(hRedirect); i++) { + GetArrayString(hRedirect, i, sRedirect, sizeof(sRedirect)); + strcopy(sCode, sizeof(sCode), sRedirect); + bHasBrackets = true; + + GetTrieString(hTrie, sRedirect, sColor, sizeof(sColor)); + strcopy(sFirstColor, sizeof(sFirstColor), sRedirect); + iRedirectLife = _CV_MAX_VARIABLE_REDIRECTS; + + do { + if (!HasBrackets(sColor)) { + strcopy(sRedirect, sizeof(sRedirect), sColor); + bHasBrackets = false; + break; + } + + strcopy(sColor, strlen(sColor) - 1, sColor[1]); + if (iRedirectLife > 0) { + strcopy(sRedirect, sizeof(sRedirect), sColor); + iRedirectLife--; + } else { + strcopy(sRedirect, sizeof(sRedirect), sFirstColor); + LogError("Too many redirects for variable '%s' !", sCode); + break; + } + } while (GetTrieString(hTrie, sRedirect, sColor, sizeof(sColor))); + + if (bHasBrackets) { + Format(sRedirect, sizeof(sRedirect), "{%s}", sRedirect); + } + + StringToLower(sCode); + StringToLower(sRedirect); + SetTrieString(hTrie, sCode, sRedirect); + } +} + +stock static HasBrackets(const String:sSource[]) +{ + return (sSource[0] == '{' && sSource[strlen(sSource) - 1] == '}'); +} + +stock static StringToLower(String:sSource[]) +{ + for (new i = 0; i < strlen(sSource); i++) { + if (sSource[i] == '\0') + break; + + sSource[i] = CharToLower(sSource[i]); + } +} + +stock static AddColors(Handle:hTrie) +{ + if (IsSource2009()) { + SetTrieString(hTrie, "default", "\x01"); + SetTrieString(hTrie, "teamcolor", "\x03"); + + SetTrieString(hTrie, "aliceblue", "\x07F0F8FF"); + SetTrieString(hTrie, "allies", "\x074D7942"); + SetTrieString(hTrie, "ancient", "\x07EB4B4B"); + SetTrieString(hTrie, "antiquewhite", "\x07FAEBD7"); + SetTrieString(hTrie, "aqua", "\x0700FFFF"); + SetTrieString(hTrie, "aquamarine", "\x077FFFD4"); + SetTrieString(hTrie, "arcana", "\x07ADE55C"); + SetTrieString(hTrie, "axis", "\x07FF4040"); + SetTrieString(hTrie, "azure", "\x07007FFF"); + SetTrieString(hTrie, "beige", "\x07F5F5DC"); + SetTrieString(hTrie, "bisque", "\x07FFE4C4"); + SetTrieString(hTrie, "black", "\x07000000"); + SetTrieString(hTrie, "blanchedalmond", "\x07FFEBCD"); + SetTrieString(hTrie, "blue", "\x0799CCFF"); + SetTrieString(hTrie, "blueviolet", "\x078A2BE2"); + SetTrieString(hTrie, "brown", "\x07A52A2A"); + SetTrieString(hTrie, "burlywood", "\x07DEB887"); + SetTrieString(hTrie, "cadetblue", "\x075F9EA0"); + SetTrieString(hTrie, "chartreuse", "\x077FFF00"); + SetTrieString(hTrie, "chocolate", "\x07D2691E"); + SetTrieString(hTrie, "collectors", "\x07AA0000"); + SetTrieString(hTrie, "common", "\x07B0C3D9"); + SetTrieString(hTrie, "community", "\x0770B04A"); + SetTrieString(hTrie, "coral", "\x07FF7F50"); + SetTrieString(hTrie, "cornflowerblue", "\x076495ED"); + SetTrieString(hTrie, "cornsilk", "\x07FFF8DC"); + SetTrieString(hTrie, "corrupted", "\x07A32C2E"); + SetTrieString(hTrie, "crimson", "\x07DC143C"); + SetTrieString(hTrie, "cyan", "\x0700FFFF"); + SetTrieString(hTrie, "darkblue", "\x0700008B"); + SetTrieString(hTrie, "darkcyan", "\x07008B8B"); + SetTrieString(hTrie, "darkgoldenrod", "\x07B8860B"); + SetTrieString(hTrie, "darkgray", "\x07A9A9A9"); + SetTrieString(hTrie, "darkgrey", "\x07A9A9A9"); + SetTrieString(hTrie, "darkgreen", "\x07006400"); + SetTrieString(hTrie, "darkkhaki", "\x07BDB76B"); + SetTrieString(hTrie, "darkmagenta", "\x078B008B"); + SetTrieString(hTrie, "darkolivegreen", "\x07556B2F"); + SetTrieString(hTrie, "darkorange", "\x07FF8C00"); + SetTrieString(hTrie, "darkorchid", "\x079932CC"); + SetTrieString(hTrie, "darkred", "\x078B0000"); + SetTrieString(hTrie, "darksalmon", "\x07E9967A"); + SetTrieString(hTrie, "darkseagreen", "\x078FBC8F"); + SetTrieString(hTrie, "darkslateblue", "\x07483D8B"); + SetTrieString(hTrie, "darkslategray", "\x072F4F4F"); + SetTrieString(hTrie, "darkslategrey", "\x072F4F4F"); + SetTrieString(hTrie, "darkturquoise", "\x0700CED1"); + SetTrieString(hTrie, "darkviolet", "\x079400D3"); + SetTrieString(hTrie, "deeppink", "\x07FF1493"); + SetTrieString(hTrie, "deepskyblue", "\x0700BFFF"); + SetTrieString(hTrie, "dimgray", "\x07696969"); + SetTrieString(hTrie, "dimgrey", "\x07696969"); + SetTrieString(hTrie, "dodgerblue", "\x071E90FF"); + SetTrieString(hTrie, "exalted", "\x07CCCCCD"); + SetTrieString(hTrie, "firebrick", "\x07B22222"); + SetTrieString(hTrie, "floralwhite", "\x07FFFAF0"); + SetTrieString(hTrie, "forestgreen", "\x07228B22"); + SetTrieString(hTrie, "frozen", "\x074983B3"); + SetTrieString(hTrie, "fuchsia", "\x07FF00FF"); + SetTrieString(hTrie, "fullblue", "\x070000FF"); + SetTrieString(hTrie, "fullred", "\x07FF0000"); + SetTrieString(hTrie, "gainsboro", "\x07DCDCDC"); + SetTrieString(hTrie, "genuine", "\x074D7455"); + SetTrieString(hTrie, "ghostwhite", "\x07F8F8FF"); + SetTrieString(hTrie, "gold", "\x07FFD700"); + SetTrieString(hTrie, "goldenrod", "\x07DAA520"); + SetTrieString(hTrie, "gray", "\x07CCCCCC"); + SetTrieString(hTrie, "grey", "\x07CCCCCC"); + SetTrieString(hTrie, "green", "\x073EFF3E"); + SetTrieString(hTrie, "greenyellow", "\x07ADFF2F"); + SetTrieString(hTrie, "haunted", "\x0738F3AB"); + SetTrieString(hTrie, "honeydew", "\x07F0FFF0"); + SetTrieString(hTrie, "hotpink", "\x07FF69B4"); + SetTrieString(hTrie, "immortal", "\x07E4AE33"); + SetTrieString(hTrie, "indianred", "\x07CD5C5C"); + SetTrieString(hTrie, "indigo", "\x074B0082"); + SetTrieString(hTrie, "ivory", "\x07FFFFF0"); + SetTrieString(hTrie, "khaki", "\x07F0E68C"); + SetTrieString(hTrie, "lavender", "\x07E6E6FA"); + SetTrieString(hTrie, "lavenderblush", "\x07FFF0F5"); + SetTrieString(hTrie, "lawngreen", "\x077CFC00"); + SetTrieString(hTrie, "legendary", "\x07D32CE6"); + SetTrieString(hTrie, "lemonchiffon", "\x07FFFACD"); + SetTrieString(hTrie, "lightblue", "\x07ADD8E6"); + SetTrieString(hTrie, "lightcoral", "\x07F08080"); + SetTrieString(hTrie, "lightcyan", "\x07E0FFFF"); + SetTrieString(hTrie, "lightgoldenrodyellow", "\x07FAFAD2"); + SetTrieString(hTrie, "lightgray", "\x07D3D3D3"); + SetTrieString(hTrie, "lightgrey", "\x07D3D3D3"); + SetTrieString(hTrie, "lightgreen", "\x0799FF99"); + SetTrieString(hTrie, "lightpink", "\x07FFB6C1"); + SetTrieString(hTrie, "lightsalmon", "\x07FFA07A"); + SetTrieString(hTrie, "lightseagreen", "\x0720B2AA"); + SetTrieString(hTrie, "lightskyblue", "\x0787CEFA"); + SetTrieString(hTrie, "lightslategray", "\x07778899"); + SetTrieString(hTrie, "lightslategrey", "\x07778899"); + SetTrieString(hTrie, "lightsteelblue", "\x07B0C4DE"); + SetTrieString(hTrie, "lightyellow", "\x07FFFFE0"); + SetTrieString(hTrie, "lime", "\x0700FF00"); + SetTrieString(hTrie, "limegreen", "\x0732CD32"); + SetTrieString(hTrie, "linen", "\x07FAF0E6"); + SetTrieString(hTrie, "magenta", "\x07FF00FF"); + SetTrieString(hTrie, "maroon", "\x07800000"); + SetTrieString(hTrie, "mediumaquamarine", "\x0766CDAA"); + SetTrieString(hTrie, "mediumblue", "\x070000CD"); + SetTrieString(hTrie, "mediumorchid", "\x07BA55D3"); + SetTrieString(hTrie, "mediumpurple", "\x079370D8"); + SetTrieString(hTrie, "mediumseagreen", "\x073CB371"); + SetTrieString(hTrie, "mediumslateblue", "\x077B68EE"); + SetTrieString(hTrie, "mediumspringgreen", "\x0700FA9A"); + SetTrieString(hTrie, "mediumturquoise", "\x0748D1CC"); + SetTrieString(hTrie, "mediumvioletred", "\x07C71585"); + SetTrieString(hTrie, "midnightblue", "\x07191970"); + SetTrieString(hTrie, "mintcream", "\x07F5FFFA"); + SetTrieString(hTrie, "mistyrose", "\x07FFE4E1"); + SetTrieString(hTrie, "moccasin", "\x07FFE4B5"); + SetTrieString(hTrie, "mythical", "\x078847FF"); + SetTrieString(hTrie, "navajowhite", "\x07FFDEAD"); + SetTrieString(hTrie, "navy", "\x07000080"); + SetTrieString(hTrie, "normal", "\x07B2B2B2"); + SetTrieString(hTrie, "oldlace", "\x07FDF5E6"); + SetTrieString(hTrie, "olive", "\x079EC34F"); + SetTrieString(hTrie, "olivedrab", "\x076B8E23"); + SetTrieString(hTrie, "orange", "\x07FFA500"); + SetTrieString(hTrie, "orangered", "\x07FF4500"); + SetTrieString(hTrie, "orchid", "\x07DA70D6"); + SetTrieString(hTrie, "palegoldenrod", "\x07EEE8AA"); + SetTrieString(hTrie, "palegreen", "\x0798FB98"); + SetTrieString(hTrie, "paleturquoise", "\x07AFEEEE"); + SetTrieString(hTrie, "palevioletred", "\x07D87093"); + SetTrieString(hTrie, "papayawhip", "\x07FFEFD5"); + SetTrieString(hTrie, "peachpuff", "\x07FFDAB9"); + SetTrieString(hTrie, "peru", "\x07CD853F"); + SetTrieString(hTrie, "pink", "\x07FFC0CB"); + SetTrieString(hTrie, "plum", "\x07DDA0DD"); + SetTrieString(hTrie, "powderblue", "\x07B0E0E6"); + SetTrieString(hTrie, "purple", "\x07800080"); + SetTrieString(hTrie, "rare", "\x074B69FF"); + SetTrieString(hTrie, "red", "\x07FF4040"); + SetTrieString(hTrie, "rosybrown", "\x07BC8F8F"); + SetTrieString(hTrie, "royalblue", "\x074169E1"); + SetTrieString(hTrie, "saddlebrown", "\x078B4513"); + SetTrieString(hTrie, "salmon", "\x07FA8072"); + SetTrieString(hTrie, "sandybrown", "\x07F4A460"); + SetTrieString(hTrie, "seagreen", "\x072E8B57"); + SetTrieString(hTrie, "seashell", "\x07FFF5EE"); + SetTrieString(hTrie, "selfmade", "\x0770B04A"); + SetTrieString(hTrie, "sienna", "\x07A0522D"); + SetTrieString(hTrie, "silver", "\x07C0C0C0"); + SetTrieString(hTrie, "skyblue", "\x0787CEEB"); + SetTrieString(hTrie, "slateblue", "\x076A5ACD"); + SetTrieString(hTrie, "slategray", "\x07708090"); + SetTrieString(hTrie, "slategrey", "\x07708090"); + SetTrieString(hTrie, "snow", "\x07FFFAFA"); + SetTrieString(hTrie, "springgreen", "\x0700FF7F"); + SetTrieString(hTrie, "steelblue", "\x074682B4"); + SetTrieString(hTrie, "strange", "\x07CF6A32"); + SetTrieString(hTrie, "tan", "\x07D2B48C"); + SetTrieString(hTrie, "teal", "\x07008080"); + SetTrieString(hTrie, "thistle", "\x07D8BFD8"); + SetTrieString(hTrie, "tomato", "\x07FF6347"); + SetTrieString(hTrie, "turquoise", "\x0740E0D0"); + SetTrieString(hTrie, "uncommon", "\x07B0C3D9"); + SetTrieString(hTrie, "unique", "\x07FFD700"); + SetTrieString(hTrie, "unusual", "\x078650AC"); + SetTrieString(hTrie, "valve", "\x07A50F79"); + SetTrieString(hTrie, "vintage", "\x07476291"); + SetTrieString(hTrie, "violet", "\x07EE82EE"); + SetTrieString(hTrie, "wheat", "\x07F5DEB3"); + SetTrieString(hTrie, "white", "\x07FFFFFF"); + SetTrieString(hTrie, "whitesmoke", "\x07F5F5F5"); + SetTrieString(hTrie, "yellow", "\x07FFFF00"); + SetTrieString(hTrie, "yellowgreen", "\x079ACD32"); + } else { + SetTrieString(hTrie, "default", "\x01"); + SetTrieString(hTrie, "teamcolor", "\x03"); + + SetTrieString(hTrie, "red", "\x07"); + SetTrieString(hTrie, "lightred", "\x0F"); + SetTrieString(hTrie, "darkred", "\x02"); + SetTrieString(hTrie, "bluegrey", "\x0A"); + SetTrieString(hTrie, "blue", "\x0B"); + SetTrieString(hTrie, "darkblue", "\x0C"); + SetTrieString(hTrie, "purple", "\x03"); + SetTrieString(hTrie, "orchid", "\x0E"); + SetTrieString(hTrie, "yellow", "\x09"); + SetTrieString(hTrie, "gold", "\x10"); + SetTrieString(hTrie, "lightgreen", "\x05"); + SetTrieString(hTrie, "green", "\x04"); + SetTrieString(hTrie, "lime", "\x06"); + SetTrieString(hTrie, "grey", "\x08"); + SetTrieString(hTrie, "grey2", "\x0D"); + } + + SetTrieString(hTrie, "engine 1", "\x01"); + SetTrieString(hTrie, "engine 2", "\x02"); + SetTrieString(hTrie, "engine 3", "\x03"); + SetTrieString(hTrie, "engine 4", "\x04"); + SetTrieString(hTrie, "engine 5", "\x05"); + SetTrieString(hTrie, "engine 6", "\x06"); + SetTrieString(hTrie, "engine 7", "\x07"); + SetTrieString(hTrie, "engine 8", "\x08"); + SetTrieString(hTrie, "engine 9", "\x09"); + SetTrieString(hTrie, "engine 10", "\x0A"); + SetTrieString(hTrie, "engine 11", "\x0B"); + SetTrieString(hTrie, "engine 12", "\x0C"); + SetTrieString(hTrie, "engine 13", "\x0D"); + SetTrieString(hTrie, "engine 14", "\x0E"); + SetTrieString(hTrie, "engine 15", "\x0F"); + SetTrieString(hTrie, "engine 16", "\x10"); +} + +stock static bool:IsSource2009() +{ + if (g_IsSource2009 == unknown) { + new EngineVersion:iEngineVersion = GetEngineVersion(); + g_IsSource2009 = (iEngineVersion == Engine_CSS || iEngineVersion == Engine_TF2 || iEngineVersion == Engine_HL2DM || iEngineVersion == Engine_DODS) ? yes : no; + } + + return bool:g_IsSource2009; +} + +stock static AddPrefixAndDefaultColor(String:sMessage[], iSize, String:sDefaultColor[] = "default", String:sPrefixColor[] = "prefix") +{ + if (g_sChatPrefix[0] != '\0' && !g_bIgnorePrefix) { + Format(sMessage, iSize, "{%s}[%s]{%s} %s", sPrefixColor, g_sChatPrefix, sDefaultColor, sMessage); + } else { + Format(sMessage, iSize, "{%s}%s", sDefaultColor, sMessage); + } +} + +stock static SendPlayerMessage(iClient, String:sMessage[], iAuthor = 0) +{ + if (iAuthor < 1 || iAuthor > MaxClients || !IsClientInGame(iAuthor)) { + PrintToChat(iClient, sMessage); + + if (iAuthor != 0) { + LogError("Client %d is not valid or in game", iAuthor); + } + } else { + CSayText2(iClient, sMessage, iAuthor); + } +} \ No newline at end of file diff --git a/advertisements/include/updater.inc b/advertisements/include/updater.inc new file mode 100644 index 00000000..68851328 --- /dev/null +++ b/advertisements/include/updater.inc @@ -0,0 +1,97 @@ +#if defined _updater_included + #endinput +#endif +#define _updater_included + +/** + * Adds your plugin to the updater. The URL will be updated if + * your plugin was previously added. + * + * @param url URL to your plugin's update file. + * @noreturn + */ +native Updater_AddPlugin(const String:url[]); + +/** + * Removes your plugin from the updater. This does not need to + * be called during OnPluginEnd. + * + * @noreturn + */ +native Updater_RemovePlugin(); + +/** + * Forces your plugin to be checked for updates. The behaviour + * of the update is dependant on the server's configuration. + * + * @return True if an update was triggered. False otherwise. + * @error Plugin not found in updater. + */ +native bool:Updater_ForceUpdate(); + +/** + * Called when your plugin is about to be checked for updates. + * + * @return Plugin_Handled to prevent checking, Plugin_Continue to allow it. + */ +forward Action:Updater_OnPluginChecking(); + +/** + * Called when your plugin is about to begin downloading an available update. + * + * @return Plugin_Handled to prevent downloading, Plugin_Continue to allow it. + */ +forward Action:Updater_OnPluginDownloading(); + +/** + * Called when your plugin's update files have been fully downloaded + * and are about to write to their proper location. This should be used + * to free read-only resources that require write access for your update. + * + * @note OnPluginUpdated will be called later during the same frame. + * + * @noreturn + */ +forward Updater_OnPluginUpdating(); + +/** + * Called when your plugin's update has been completed. It is safe + * to reload your plugin at this time. + * + * @noreturn + */ +forward Updater_OnPluginUpdated(); + +/** + * @brief Reloads a plugin. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @noreturn + */ +stock ReloadPlugin(Handle:plugin=INVALID_HANDLE) +{ + decl String:filename[64]; + GetPluginFilename(plugin, filename, sizeof(filename)); + ServerCommand("sm plugins reload %s", filename); +} + + +public SharedPlugin:__pl_updater = +{ + name = "updater", + file = "updater.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public __pl_updater_SetNTVOptional() +{ + MarkNativeAsOptional("Updater_AddPlugin"); + MarkNativeAsOptional("Updater_RemovePlugin"); + MarkNativeAsOptional("Updater_ForceUpdate"); +} +#endif \ No newline at end of file diff --git a/advertisements/scripting/advertisements.sp b/advertisements/scripting/advertisements.sp new file mode 100644 index 00000000..c07d22a6 --- /dev/null +++ b/advertisements/scripting/advertisements.sp @@ -0,0 +1,317 @@ +#include +#include +#undef REQUIRE_PLUGIN +#include +#include "topcolors.sp" + +#pragma newdecls required +#pragma semicolon 1 + +#define PL_VERSION "2.0.2" +#define UPDATE_URL "http://ErikMinekus.github.io/sm-advertisements/update.txt" + +public Plugin myinfo = +{ + name = "Advertisements", + author = "Tsunami", + description = "Display advertisements", + version = PL_VERSION, + url = "http://www.tsunami-productions.nl" +}; + + +/** + * Globals + */ +KeyValues g_hAdvertisements; +ConVar g_hEnabled; +ConVar g_hFile; +ConVar g_hInterval; +Handle g_hTimer; + + +/** + * Plugin Forwards + */ +public void OnPluginStart() +{ + CreateConVar("sm_advertisements_version", PL_VERSION, "Display advertisements", FCVAR_NOTIFY); + g_hEnabled = CreateConVar("sm_advertisements_enabled", "1", "Enable/disable displaying advertisements."); + g_hFile = CreateConVar("sm_advertisements_file", "advertisements.txt", "File to read the advertisements from."); + g_hInterval = CreateConVar("sm_advertisements_interval", "30", "Amount of seconds between advertisements."); + + g_hFile.AddChangeHook(ConVarChange_File); + g_hInterval.AddChangeHook(ConVarChange_Interval); + + RegServerCmd("sm_advertisements_reload", Command_ReloadAds, "Reload the advertisements"); + + AddTopColors(); + + if (LibraryExists("updater")) { + Updater_AddPlugin(UPDATE_URL); + } +} + +public void OnMapStart() +{ + ParseAds(); + + g_hTimer = CreateTimer(g_hInterval.IntValue * 1.0, Timer_DisplayAd, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); +} + +public void OnLibraryAdded(const char[] name) +{ + if (StrEqual(name, "updater")) { + Updater_AddPlugin(UPDATE_URL); + } +} + +public void ConVarChange_File(ConVar convar, const char[] oldValue, const char[] newValue) +{ + ParseAds(); +} + +public void ConVarChange_Interval(ConVar convar, const char[] oldValue, const char[] newValue) +{ + if (g_hTimer) { + KillTimer(g_hTimer); + } + + g_hTimer = CreateTimer(g_hInterval.IntValue * 1.0, Timer_DisplayAd, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); +} + + +/** + * Commands + */ +public Action Command_ReloadAds(int args) +{ + ParseAds(); + return Plugin_Handled; +} + + +/** + * Menu Handlers + */ +public int Handler_DoNothing(Menu menu, MenuAction action, int param1, int param2) {} + + +/** + * Timers + */ +public Action Timer_DisplayAd(Handle timer) +{ + if (!g_hEnabled.BoolValue) { + return; + } + + char sCenter[1024], sChat[1024], sHint[1024], sMenu[1024], sTop[1024], sFlags[16]; + g_hAdvertisements.GetString("center", sCenter, sizeof(sCenter)); + g_hAdvertisements.GetString("chat", sChat, sizeof(sChat)); + g_hAdvertisements.GetString("hint", sHint, sizeof(sHint)); + g_hAdvertisements.GetString("menu", sMenu, sizeof(sMenu)); + g_hAdvertisements.GetString("top", sTop, sizeof(sTop)); + g_hAdvertisements.GetString("flags", sFlags, sizeof(sFlags), "none"); + int iFlags = ReadFlagString(sFlags); + bool bAdmins = StrEqual(sFlags, ""), + bFlags = !StrEqual(sFlags, "none"); + + if (sCenter[0]) { + ProcessVariables(sCenter); + CRemoveColors(sCenter, sizeof(sCenter)); + + for (int i = 1; i <= MaxClients; i++) { + if (IsClientInGame(i) && !IsFakeClient(i) && + ((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) || + (bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) { + PrintCenterText(i, sCenter); + + DataPack hCenterAd; + CreateDataTimer(1.0, Timer_CenterAd, hCenterAd, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); + hCenterAd.WriteCell(i); + hCenterAd.WriteString(sCenter); + } + } + } + if (sHint[0]) { + ProcessVariables(sHint); + CRemoveColors(sHint, sizeof(sHint)); + + for (int i = 1; i <= MaxClients; i++) { + if (IsClientInGame(i) && !IsFakeClient(i) && + ((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) || + (bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) { + PrintHintText(i, sHint); + } + } + } + if (sMenu[0]) { + ProcessVariables(sMenu); + CRemoveColors(sMenu, sizeof(sMenu)); + + Panel hPl = new Panel(); + hPl.DrawText(sMenu); + hPl.CurrentKey = 10; + + for (int i = 1; i <= MaxClients; i++) { + if (IsClientInGame(i) && !IsFakeClient(i) && + ((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) || + (bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) { + hPl.Send(i, Handler_DoNothing, 10); + } + } + + delete hPl; + } + if (sChat[0]) { + bool bTeamColor = StrContains(sChat, "{teamcolor}", false) != -1; + + ProcessVariables(sChat); + CProcessVariables(sChat, sizeof(sChat)); + CAddWhiteSpace(sChat, sizeof(sChat)); + + for (int i = 1; i <= MaxClients; i++) { + if (IsClientInGame(i) && !IsFakeClient(i) && + ((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) || + (bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) { + if (bTeamColor) { + CSayText2(i, sChat, i); + } else { + PrintToChat(i, sChat); + } + } + } + } + if (sTop[0]) { + int iStart = 0, + aColor[4] = {255, 255, 255, 255}; + + ParseTopColor(sTop, iStart, aColor); + ProcessVariables(sTop[iStart]); + + KeyValues hKv = new KeyValues("Stuff", "title", sTop[iStart]); + hKv.SetColor4("color", aColor); + hKv.SetNum("level", 1); + hKv.SetNum("time", 10); + + for (int i = 1; i <= MaxClients; i++) { + if (IsClientInGame(i) && !IsFakeClient(i) && + ((!bAdmins && !(bFlags && (GetUserFlagBits(i) & (iFlags|ADMFLAG_ROOT)))) || + (bAdmins && (GetUserFlagBits(i) & (ADMFLAG_GENERIC|ADMFLAG_ROOT))))) { + CreateDialog(i, hKv, DialogType_Msg); + } + } + + delete hKv; + } + + if (!g_hAdvertisements.GotoNextKey()) { + g_hAdvertisements.Rewind(); + g_hAdvertisements.GotoFirstSubKey(); + } +} + +public Action Timer_CenterAd(Handle timer, DataPack pack) +{ + char sCenter[1024]; + static int iCount = 0; + + pack.Reset(); + int iClient = pack.ReadCell(); + pack.ReadString(sCenter, sizeof(sCenter)); + + if (!IsClientInGame(iClient) || ++iCount >= 5) { + iCount = 0; + return Plugin_Stop; + } + + PrintCenterText(iClient, sCenter); + return Plugin_Continue; +} + + +/** + * Stocks + */ +void ParseAds() +{ + delete g_hAdvertisements; + g_hAdvertisements = CreateKeyValues("Advertisements"); + + char sFile[64], sPath[PLATFORM_MAX_PATH]; + g_hFile.GetString(sFile, sizeof(sFile)); + BuildPath(Path_SM, sPath, sizeof(sPath), "configs/%s", sFile); + + if (!FileExists(sPath)) { + SetFailState("File Not Found: %s", sPath); + } + + g_hAdvertisements.ImportFromFile(sPath); + g_hAdvertisements.GotoFirstSubKey(); +} + +void ProcessVariables(char sText[1024]) +{ + char sBuffer[64]; + if (StrContains(sText, "\\n") != -1) { + Format(sBuffer, sizeof(sBuffer), "%c", 13); + ReplaceString(sText, sizeof(sText), "\\n", sBuffer); + } + + if (StrContains(sText, "{currentmap}", false) != -1) { + GetCurrentMap(sBuffer, sizeof(sBuffer)); + ReplaceString(sText, sizeof(sText), "{currentmap}", sBuffer, false); + } + + if (StrContains(sText, "{date}", false) != -1) { + FormatTime(sBuffer, sizeof(sBuffer), "%m/%d/%Y"); + ReplaceString(sText, sizeof(sText), "{date}", sBuffer, false); + } + + if (StrContains(sText, "{time}", false) != -1) { + FormatTime(sBuffer, sizeof(sBuffer), "%I:%M:%S%p"); + ReplaceString(sText, sizeof(sText), "{time}", sBuffer, false); + } + + if (StrContains(sText, "{time24}", false) != -1) { + FormatTime(sBuffer, sizeof(sBuffer), "%H:%M:%S"); + ReplaceString(sText, sizeof(sText), "{time24}", sBuffer, false); + } + + if (StrContains(sText, "{timeleft}", false) != -1) { + int iMins, iSecs, iTimeLeft; + if (GetMapTimeLeft(iTimeLeft) && iTimeLeft > 0) { + iMins = iTimeLeft / 60; + iSecs = iTimeLeft % 60; + } + + Format(sBuffer, sizeof(sBuffer), "%d:%02d", iMins, iSecs); + ReplaceString(sText, sizeof(sText), "{timeleft}", sBuffer, false); + } + + ConVar hConVar; + char sConVar[64], sSearch[64], sReplace[64]; + int iEnd = -1, iStart = StrContains(sText, "{"), iStart2; + while (iStart != -1) { + iEnd = StrContains(sText[iStart + 1], "}"); + if (iEnd == -1) { + break; + } + + strcopy(sConVar, iEnd + 1, sText[iStart + 1]); + Format(sSearch, sizeof(sSearch), "{%s}", sConVar); + + if ((hConVar = FindConVar(sConVar))) { + hConVar.GetString(sReplace, sizeof(sReplace)); + ReplaceString(sText, sizeof(sText), sSearch, sReplace, false); + } + + iStart2 = StrContains(sText[iStart + 1], "{"); + if (iStart2 == -1) { + break; + } + + iStart += iStart2 + 1; + } +} \ No newline at end of file