├── README.md ├── addons └── sourcemod │ └── scripting │ └── includes │ └── colorvariables.inc └── csgo colors.png /README.md: -------------------------------------------------------------------------------- 1 | # ColorVariables 2 | ColorVariables moves setting the colors in chat messages from plugin developers to server masters. It allows server masters to set colors for all plugins (with ColorVariables) in one simple step. 3 | For example, changing chat prefix color requires to edit just one line in `colorvariables/global.cfg` config. And it works for one or all plugins with ColorVariables. 4 | 5 | **In layman's terms:** Plugin developers are not supposed to use actual colors, but variables which can be easily set by server masters. 6 | 7 | --- 8 | 9 | ### How does it work? 10 | 11 | ##### Server master: 12 | 1. Instal plugin 13 | 2. *Optional:* Edit `colorvariables/global.cfg` to set global variables for all plugins with ColorVariables (recommended with first ColorVariables plugin) 14 | 3. *Optional:* Edit `colorvariables/plugin.PLUGIN_NAME.cfg` to set plugin's "local" variables as you wish 15 | - `"{newcolor}" "{darkred}"` 16 | - **NOT** `"{newcolor}" "darkred"` 17 | - `"{newcolor}" "{#FF0000}"` 18 | - **NOT** `"{newcolor}" "#FF0000"` 19 | 20 | ##### Plugin developer: 21 | 1. Create a plugin with ColorVariables 22 | 2. Use color variables in chat messages and not actual colors 23 | 3. *Optional:* If you need some new variables, create them with `CAddVariable` 24 | 4. *Optional:* If you want, you can create a forwarded variable for other plugins to use (like `{@isRebel CLIENT_INDEX}`, `{@isZombie CLIENT_INDEX}`, `{@rainbow}` etc.) 25 | 5. *Optional:* If you want to use variables from other plugins, load them with `CLoadPluginConfig` or `CLoadPluginVariables` (If server master renamed plugin binary, this won't work!) 26 | 27 | **Quick example:**
28 | Normal: `PrintToChatAll("\x02[prefix]\x01 %N gave you \x03AK-47\x01!", client)`
29 | CV: `CPrintToChatAll("%N gave you {highlight}AK-47{default}!", client)`
30 | 31 | 32 | **ColorVariables plugin example:** 33 | ```SourcePawn 34 | #include 35 | 36 | public OnPluginStart() 37 | { 38 | CSetPrefix("KillInfo"); // Set plugin chat prefix to "KillInfo" (will be used in every print function) 39 | 40 | HookEvent("player_death", Event_PlayerDeath); 41 | } 42 | 43 | public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) 44 | { 45 | new victim = GetClientOfUserId(GetEventInt(event, "userid")); 46 | new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); 47 | 48 | CPrintToChatAll("{player %d}%N {default} killed {player %d}%N", attacker, attacker, victim, victim); 49 | // {prefix}[KillInfo] {teamcolor}Will {default}killed {teamcolor}Mark 50 | 51 | CPrintToChat(victim, "{highlight}Player {player %d}%N {highlight}killed you!", attacker, attacker); 52 | // {prefix}[KillInfo] {highlight}Player {teamcolor}Will {highlight}killed you! 53 | 54 | return Plugin_Continue; 55 | } 56 | 57 | ``` 58 | 59 | ### Configs & variables loading order 60 | 61 | 1. Predefined variables (viz. [Predefined variables](#predefined_engine-variables)) 62 | 2. `colorvariables/global.cfg` 63 | - Global config loaded by every plugin 64 | - Cannot contain redirects outside of `global.cfg` or predefined variables 65 | 3. `colorvariables/plugin.PLUGIN_NAME.cfg` 66 | - `CAddVariable` and `CSavePrefix` write to this config 67 | - Can be loaded by 3rd party plugins with `CLoadPluginConfig` or `CLoadPluginVariables` 68 | 4. Optional: `CAddVariable`, `CLoadPluginConfig` and `CLoadPluginVariables` 69 | 70 | Newer variables declarations overwrites the older ones. 71 | 72 | 73 | 74 | ### Redirecting variables 75 | 76 | - Every variable can be redirected to another (except direct colors and forwarded variables) 77 | - `"mycolor" "{nicecolor}"` 78 | - Variable can be redirected 10x at max 79 | 80 | 81 | ### Direct colors 82 | 83 | - Starts with `#` 84 | - Has two different "mods", RGB `{#RRGGBB}` and RGBA `{#RRGGBBAA}` 85 | - Works only in older versions of engine (CS:S, TF2, HL2, DOD:S, ...) - **NOT CS:GO!** 86 | - Of course, direct color cannot be redirected 87 | 88 | 89 | ### Forwarded variables - *"Clever" variables* 90 | 91 | - Name starts with `@` and cannot contain whitespace 92 | - Can pass a single argument `{@playerteam 15}` separated by a whitespace 93 | - `PrintToChatAll("Player {@playerteam %d}%N {defalut}has died!", client, client);` 94 | - Won't work if their parental plugin is not loaded 95 | - For parental plugin: 96 | - Use forward `public COnForwardedVariable(String:sCode[], String:sData[], iDataSize, String:sColor[], iColorSize)` to catch your variable 97 | - Must return actual color code - cannot be redirected (use `CGetColor` to get actual color code) 98 | 99 | 100 | ### Chat prefix 101 | 102 | - No prefix by default, could be set with `CSetPrefix` 103 | - Works in `CPrintToChat`, `CPrintToChatAll`, `CPrintToChatTeam`, `CPrintToChatAdmins` and `CReplyToCommand` 104 | - Message format: `"{prefix}[Prefix] {default}Message"` (`{reply2cmd}` in case of `CReplyToCommand`) 105 | - Could be turned off for the next use with `CSkipNextPrefix` 106 | - Could be set saved to plugin config file with `CSavePrefix` (other plugins can load it via `CLoadPluginConfig`) 107 | 108 | 109 | ### Message author 110 | 111 | - No author by default 112 | - Works in `CPrintToChat`, `CPrintToChatAll`, `CPrintToChatTeam` and `CPrintToChatAdmins` 113 | - Must by set with `CSetNextAuthor` to use in next message 114 | 115 | ### Predefined & Engine variables 116 | Variable | Usage 117 | ---------------- | ------------- 118 | `{prefix}` | Chat prefix color 119 | `{default}` | Chat message color 120 | `{reply2cmd}` | Reply to command message color 121 | `{showactivity}` | Show activity message color 122 | ---------------- | ------------- 123 | `{error}` | Error content color 124 | `{highlight}` | Highlighted content color 125 | `{player}` | Highlight player in message (could be used as `{player CLIENT_INDEX}` to get a player's team color) 126 | `{settings}` | Settings content color 127 | `{command}` | Highlight command in message 128 | ---------------- | ------------- 129 | `{team0}` | Spectator color 130 | `{team1}` | Terrorists, Red team color 131 | `{team2}` | Counter-Terrorists, Blue team color 132 | 133 | - Older engine versions (CS:S, TF2, HL2, DOD:S, ...) 134 | - [Dr. McKay's More Colors](https://www.doctormckay.com/morecolors.php) 135 | - Newer engine versions (CS:GO, ...) 136 | - ![CS:GO colors](https://raw.githubusercontent.com/KissLick/ColorVariables/master/csgo%20colors.png) 137 | - Engine colors (usability depends on engine version) 138 | - `{engine 1}`, `{engine 2}`, `{engine 3}`, ..., `{engine 16}` 139 | -------------------------------------------------------------------------------- /addons/sourcemod/scripting/includes/colorvariables.inc: -------------------------------------------------------------------------------- 1 | #if defined _colorvariables_included 2 | #endinput 3 | #endif 4 | #define _colorvariables_included "1.3" 5 | 6 | // Author: Raska aka KissLick 7 | 8 | // ---------------------------------------------------------------------------------------- 9 | #define _CV_MAX_MESSAGE_LENGTH 1024 10 | #define _CV_MAX_VARIABLE_REDIRECTS 10 11 | #define _CV_CONFIG_DIRECTORY "configs/colorvariables" 12 | 13 | static bool:g_bInit = false; 14 | static Handle:g_hColors = INVALID_HANDLE; 15 | static String:g_sConfigGlobal[PLATFORM_MAX_PATH]; 16 | static String:g_sConfig[PLATFORM_MAX_PATH]; 17 | static String:g_sChatPrefix[64] = ""; 18 | 19 | static bool:g_bIgnorePrefix = false; 20 | static g_iAuthor; 21 | static bool:g_bSkipPlayers[MAXPLAYERS + 1] = {false, ...}; 22 | 23 | static Handle:g_hForwardedVariable; 24 | 25 | enum triple { 26 | unknown = -1, 27 | yes = true, 28 | no = false 29 | } 30 | static triple:g_IsSource2009 = unknown; 31 | // ---------------------------------------------------------------------------------------- 32 | 33 | forward COnForwardedVariable(String:sCode[], String:sData[], iDataSize, String:sColor[], iColorSize); 34 | 35 | stock CSetPrefix(const String:sPrefix[], any:...) 36 | { 37 | VFormat(g_sChatPrefix, sizeof(g_sChatPrefix), sPrefix, 2); 38 | } 39 | 40 | stock CSavePrefix(const String:sPrefix[], any:...) 41 | { 42 | new String:m_sPrefix[64]; 43 | VFormat(m_sPrefix, sizeof(m_sPrefix), sPrefix, 2); 44 | 45 | CAddVariable("&prefix", m_sPrefix, true); 46 | } 47 | 48 | stock CSkipNextPrefix() 49 | { 50 | g_bIgnorePrefix = true; 51 | } 52 | 53 | stock CSetNextAuthor(iClient) 54 | { 55 | if (iClient < 1 || iClient > MaxClients || !IsClientInGame(iClient)) { 56 | ThrowError("Invalid client index %i", iClient); 57 | } 58 | g_iAuthor = iClient; 59 | } 60 | 61 | stock CSkipNextClient(iClient) 62 | { 63 | if (iClient < 1 || iClient > MaxClients) { 64 | ThrowError("Invalid client index %i", iClient); 65 | } 66 | g_bSkipPlayers[iClient] = true; 67 | } 68 | 69 | stock CPrintToChat(iClient, const String:sMessage[], any:...) 70 | { 71 | if (iClient < 1 || iClient > MaxClients) { 72 | ThrowError("Invalid client index %d", iClient); 73 | } 74 | 75 | if (!IsClientInGame(iClient)) { 76 | ThrowError("Client %d is not in game", iClient); 77 | } 78 | 79 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; 80 | SetGlobalTransTarget(iClient); 81 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); 82 | 83 | AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); 84 | g_bIgnorePrefix = false; 85 | 86 | CProcessVariables(sBuffer, sizeof(sBuffer)); 87 | CAddWhiteSpace(sBuffer, sizeof(sBuffer)); 88 | 89 | SendPlayerMessage(iClient, sBuffer, g_iAuthor); 90 | g_iAuthor = 0; 91 | } 92 | 93 | stock CPrintToChatAll(const String:sMessage[], any:...) 94 | { 95 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; 96 | 97 | for (new iClient = 1; iClient <= MaxClients; iClient++) { 98 | if (!IsClientInGame(iClient) || g_bSkipPlayers[iClient]) { 99 | g_bSkipPlayers[iClient] = false; 100 | continue; 101 | } 102 | 103 | SetGlobalTransTarget(iClient); 104 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 2); 105 | 106 | AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); 107 | g_bIgnorePrefix = false; 108 | 109 | CProcessVariables(sBuffer, sizeof(sBuffer)); 110 | CAddWhiteSpace(sBuffer, sizeof(sBuffer)); 111 | 112 | SendPlayerMessage(iClient, sBuffer, g_iAuthor); 113 | } 114 | g_iAuthor = 0; 115 | } 116 | 117 | stock CPrintToChatTeam(iTeam, const String:sMessage[], any:...) 118 | { 119 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; 120 | 121 | for (new iClient = 1; iClient <= MaxClients; iClient++) { 122 | if (!IsClientInGame(iClient) || GetClientTeam(iClient) != iTeam || g_bSkipPlayers[iClient]) { 123 | g_bSkipPlayers[iClient] = false; 124 | continue; 125 | } 126 | 127 | SetGlobalTransTarget(iClient); 128 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); 129 | 130 | AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); 131 | g_bIgnorePrefix = false; 132 | 133 | CProcessVariables(sBuffer, sizeof(sBuffer)); 134 | CAddWhiteSpace(sBuffer, sizeof(sBuffer)); 135 | 136 | SendPlayerMessage(iClient, sBuffer, g_iAuthor); 137 | } 138 | g_iAuthor = 0; 139 | } 140 | 141 | stock CPrintToChatAdmins(iBitFlags, const String:sMessage[], any:...) 142 | { 143 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; 144 | new AdminId:iAdminID; 145 | 146 | for (new iClient = 1; iClient <= MaxClients; iClient++) { 147 | if (!IsClientInGame(iClient) || g_bSkipPlayers[iClient]) { 148 | g_bSkipPlayers[iClient] = false; 149 | continue; 150 | } 151 | 152 | iAdminID = GetUserAdmin(iClient); 153 | if (iAdminID == INVALID_ADMIN_ID || !(GetAdminFlags(iAdminID, Access_Effective) & iBitFlags)) { 154 | continue; 155 | } 156 | 157 | SetGlobalTransTarget(iClient); 158 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); 159 | 160 | AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer)); 161 | g_bIgnorePrefix = false; 162 | 163 | CProcessVariables(sBuffer, sizeof(sBuffer)); 164 | CAddWhiteSpace(sBuffer, sizeof(sBuffer)); 165 | 166 | SendPlayerMessage(iClient, sBuffer, g_iAuthor); 167 | } 168 | g_iAuthor = 0; 169 | } 170 | 171 | stock CReplyToCommand(iClient, const String:sMessage[], any:...) 172 | { 173 | if (iClient < 0 || iClient > MaxClients) { 174 | ThrowError("Invalid client index %d", iClient); 175 | } 176 | 177 | if (iClient != 0 && !IsClientInGame(iClient)) { 178 | ThrowError("Client %d is not in game", iClient); 179 | } 180 | 181 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; 182 | SetGlobalTransTarget(iClient); 183 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); 184 | 185 | AddPrefixAndDefaultColor(sBuffer, sizeof(sBuffer), "reply2cmd"); 186 | g_bIgnorePrefix = false; 187 | 188 | if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { 189 | CRemoveColors(sBuffer, sizeof(sBuffer)); 190 | PrintToConsole(iClient, "%s", sBuffer); 191 | } else { 192 | CPrintToChat(iClient, "%s", sBuffer); 193 | } 194 | } 195 | 196 | stock CShowActivity(iClient, const String:sMessage[], any:...) 197 | { 198 | if (iClient < 0 || iClient > MaxClients) { 199 | ThrowError("Invalid client index %d", iClient); 200 | } 201 | 202 | if (iClient != 0 && !IsClientInGame(iClient)) { 203 | ThrowError("Client %d is not in game", iClient); 204 | } 205 | 206 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH]; 207 | SetGlobalTransTarget(iClient); 208 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 3); 209 | Format(sBuffer, sizeof(sBuffer), "{showactivity}%s", sBuffer); 210 | CProcessVariables(sBuffer, sizeof(sBuffer)); 211 | CAddWhiteSpace(sBuffer, sizeof(sBuffer)); 212 | 213 | ShowActivity(iClient, "%s", sBuffer); 214 | } 215 | 216 | stock CShowActivityEx(iClient, const String:sTag[], const String:sMessage[], any:...) 217 | { 218 | if (iClient < 0 || iClient > MaxClients) { 219 | ThrowError("Invalid client index %d", iClient); 220 | } 221 | 222 | if (iClient != 0 && !IsClientInGame(iClient)) { 223 | ThrowError("Client %d is not in game", iClient); 224 | } 225 | 226 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH], String:sBufferTag[_CV_MAX_MESSAGE_LENGTH]; 227 | SetGlobalTransTarget(iClient); 228 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 4); 229 | Format(sBuffer, sizeof(sBuffer), "{showactivity}%s", sBuffer); 230 | CProcessVariables(sBuffer, sizeof(sBuffer)); 231 | Format(sBufferTag, sizeof(sBufferTag), "{prefix}%s", sTag); 232 | CProcessVariables(sBufferTag, sizeof(sBufferTag)); 233 | CAddWhiteSpace(sBuffer, sizeof(sBuffer)); 234 | CAddWhiteSpace(sBufferTag, sizeof(sBufferTag)); 235 | 236 | ShowActivityEx(iClient, sBufferTag, " %s", sBuffer); 237 | } 238 | 239 | stock CShowActivity2(iClient, const String:sTag[], const String:sMessage[], any:...) 240 | { 241 | if (iClient < 0 || iClient > MaxClients) { 242 | ThrowError("Invalid client index %d", iClient); 243 | } 244 | 245 | if (iClient != 0 && !IsClientInGame(iClient)) { 246 | ThrowError("Client %d is not in game", iClient); 247 | } 248 | 249 | decl String:sBuffer[_CV_MAX_MESSAGE_LENGTH], String:sBufferTag[_CV_MAX_MESSAGE_LENGTH]; 250 | SetGlobalTransTarget(iClient); 251 | VFormat(sBuffer, sizeof(sBuffer), sMessage, 4); 252 | Format(sBuffer, sizeof(sBuffer), "{showactivity}%s", sBuffer); 253 | CProcessVariables(sBuffer, sizeof(sBuffer)); 254 | Format(sBufferTag, sizeof(sBufferTag), "{prefix}%s", sTag); 255 | CProcessVariables(sBufferTag, sizeof(sBufferTag)); 256 | CAddWhiteSpace(sBuffer, sizeof(sBuffer)); 257 | CAddWhiteSpace(sBufferTag, sizeof(sBufferTag)); 258 | 259 | ShowActivityEx(iClient, sBufferTag, " %s", sBuffer); 260 | } 261 | 262 | stock CAddVariable(String:sName[], String:sValue[], bool:bOnlySaveToConfig = false) 263 | { 264 | if (Init()) { 265 | if (!FileExists(g_sConfig)) { 266 | LogError("Cannot add color variable to '%s' - file doesn't exist!", g_sConfig); 267 | return; 268 | } 269 | 270 | new Handle:hKV = CreateKeyValues("colorvariables"); 271 | 272 | if (!FileToKeyValues(hKV, g_sConfig)) { 273 | CloseHandle(hKV); 274 | LogError("Cannot open file (for adding color variable) '%s' !", g_sConfig); 275 | return; 276 | } 277 | 278 | if (!KvJumpToKey(hKV, sName)) { 279 | StringToLower(sName); 280 | KvSetString(hKV, sName, sValue); 281 | 282 | if (!bOnlySaveToConfig) { 283 | new Handle:hRedirect = CreateArray(64); 284 | PushArrayString(hRedirect, sName); 285 | SetTrieString(g_hColors, sName, sValue); 286 | SolveRedirects(g_hColors, hRedirect); 287 | CloseHandle(hRedirect); 288 | } 289 | } 290 | 291 | KvRewind(hKV); 292 | KeyValuesToFile(hKV, g_sConfig); 293 | CloseHandle(hKV); 294 | } 295 | } 296 | 297 | stock CLoadPluginConfig(const String:sPluginName[], bool:bAllowPrefix = true) 298 | { 299 | if (Init()) { 300 | new String:sConfig[PLATFORM_MAX_PATH]; 301 | strcopy(sConfig, sizeof(sConfig), sPluginName); 302 | ReplaceStringEx(sConfig, sizeof(sConfig), ".smx", ""); 303 | BuildPath(Path_SM, sConfig, sizeof(sConfig), "%s/plugin.%s.cfg", _CV_CONFIG_DIRECTORY, sConfig); 304 | 305 | if (!FileExists(sConfig)) { 306 | LogError("Cannot load color variables from file '%s' - file doesn't exist!", sConfig); 307 | return; 308 | } 309 | 310 | new Handle:hRedirect = CreateArray(64); 311 | LoadConfigFile(g_hColors, sConfig, hRedirect, bAllowPrefix); 312 | SolveRedirects(g_hColors, hRedirect); 313 | CloseHandle(hRedirect); 314 | } 315 | } 316 | 317 | stock CLoadPluginVariables(const String:sPluginName[], const String:sVariables[][], iVariablesCount, bool:bAllowPrefix = true) 318 | { 319 | if (Init() && iVariablesCount > 0) { 320 | new String:sConfig[PLATFORM_MAX_PATH]; 321 | strcopy(sConfig, sizeof(sConfig), sPluginName); 322 | ReplaceStringEx(sConfig, sizeof(sConfig), ".smx", ""); 323 | BuildPath(Path_SM, sConfig, sizeof(sConfig), "%s/plugin.%s.cfg", _CV_CONFIG_DIRECTORY, sConfig); 324 | 325 | if (!FileExists(sConfig)) { 326 | LogError("Cannot load color variables from file '%s' - file doesn't exist!", sConfig); 327 | return; 328 | } 329 | 330 | new Handle:hVariables = CreateTrie(); 331 | new Handle:hRedirect = CreateArray(64); 332 | LoadConfigFile(hVariables, sConfig, hRedirect, bAllowPrefix); 333 | SolveRedirects(hVariables, hRedirect); 334 | ClearArray(hRedirect); 335 | 336 | new String:sCode[64], String:sColor[64]; 337 | 338 | for (new i = 0; i < iVariablesCount; i++) { 339 | strcopy(sCode, sizeof(sCode), sVariables[i]); 340 | StringToLower(sCode); 341 | 342 | if (GetTrieString(hVariables, sCode, sColor, sizeof(sColor))) { 343 | SetTrieString(g_hColors, sCode, sColor); 344 | PushArrayString(hRedirect, sCode); 345 | } 346 | } 347 | 348 | SolveRedirects(g_hColors, hRedirect); 349 | CloseHandle(hRedirect); 350 | CloseHandle(hVariables); 351 | } 352 | } 353 | 354 | stock CRemoveColors(String:sMsg[], iSize) 355 | { 356 | CProcessVariables(sMsg, iSize, true); 357 | } 358 | 359 | stock CProcessVariables(String:sMsg[], iSize, bool:bRemoveColors = false) 360 | { 361 | if (!Init()) { 362 | return; 363 | } 364 | 365 | new String:sOut[iSize], String:sCode[iSize], String:sColor[iSize]; 366 | new iOutPos = 0, iCodePos = -1; 367 | new iMsgLen = strlen(sMsg); 368 | 369 | for (new i = 0; i < iMsgLen; i++) { 370 | if (sMsg[i] == '{') { 371 | iCodePos = 0; 372 | } 373 | 374 | if (iCodePos > -1) { 375 | sCode[iCodePos] = sMsg[i]; 376 | sCode[iCodePos + 1] = '\0'; 377 | 378 | if (sMsg[i] == '}' || i == iMsgLen - 1) { 379 | strcopy(sCode, strlen(sCode) - 1, sCode[1]); 380 | StringToLower(sCode); 381 | 382 | if (CGetColor(sCode, sColor, iSize)) { 383 | if (!bRemoveColors) { 384 | StrCat(sOut, iSize, sColor); 385 | iOutPos += strlen(sColor); 386 | } 387 | } else { 388 | Format(sOut, iSize, "%s{%s}", sOut, sCode); 389 | iOutPos += strlen(sCode) + 2; 390 | } 391 | 392 | iCodePos = -1; 393 | strcopy(sCode, iSize, ""); 394 | strcopy(sColor, iSize, ""); 395 | } else { 396 | iCodePos++; 397 | } 398 | 399 | continue; 400 | } 401 | 402 | sOut[iOutPos] = sMsg[i]; 403 | iOutPos++; 404 | sOut[iOutPos] = '\0'; 405 | } 406 | 407 | strcopy(sMsg, iSize, sOut); 408 | } 409 | 410 | stock bool:CGetColor(const String:sName[], String:sColor[], iColorSize) 411 | { 412 | if (sName[0] == '\0') 413 | return false; 414 | 415 | if (sName[0] == '@') { 416 | new iSpace; 417 | new String:sData[64], String:m_sName[64]; 418 | strcopy(m_sName, sizeof(m_sName), sName[1]); 419 | 420 | if ((iSpace = FindCharInString(m_sName, ' ')) != -1 && (iSpace + 1 < strlen(m_sName))) { 421 | strcopy(m_sName, iSpace + 1, m_sName); 422 | strcopy(sData, sizeof(sData), m_sName[iSpace + 1]); 423 | } 424 | 425 | Call_StartForward(g_hForwardedVariable); 426 | Call_PushString(m_sName); 427 | Call_PushStringEx(sData, sizeof(sData), SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, 0); 428 | Call_PushCell(sizeof(sData)); 429 | Call_PushStringEx(sColor, iColorSize, SM_PARAM_STRING_UTF8|SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); 430 | Call_PushCell(iColorSize); 431 | Call_Finish(); 432 | 433 | if (sColor[0] != '\0') { 434 | return true; 435 | } 436 | 437 | } else if (sName[0] == '#') { 438 | if (strlen(sName) == 7) { 439 | Format(sColor, iColorSize, "\x07%s", sName[1]); 440 | return true; 441 | } 442 | if (strlen(sName) == 9) { 443 | Format(sColor, iColorSize, "\x08%s", sName[1]); 444 | return true; 445 | } 446 | } else if (StrContains(sName, "player ", false) == 0 && strlen(sName) > 7) { 447 | new iClient = StringToInt(sName[7]); 448 | 449 | if (iClient < 1 || iClient > MaxClients || !IsClientInGame(iClient)) { 450 | strcopy(sColor, iColorSize, "\x01"); 451 | LogError("Invalid client index %d", iClient); 452 | return false; 453 | } 454 | 455 | strcopy(sColor, iColorSize, "\x01"); 456 | switch (GetClientTeam(iClient)) { 457 | case 1: {GetTrieString(g_hColors, "team0", sColor, iColorSize);} 458 | case 2: {GetTrieString(g_hColors, "team1", sColor, iColorSize);} 459 | case 3: {GetTrieString(g_hColors, "team2", sColor, iColorSize);} 460 | } 461 | return true; 462 | } else { 463 | return GetTrieString(g_hColors, sName, sColor, iColorSize); 464 | } 465 | 466 | return false; 467 | } 468 | 469 | stock bool:CExistColor(const String:sName[]) 470 | { 471 | if (sName[0] == '\0' || sName[0] == '@' || sName[0] == '#') 472 | return false; 473 | 474 | new String:sColor[64]; 475 | return GetTrieString(g_hColors, sName, sColor, sizeof(sColor)); 476 | } 477 | 478 | stock CSayText2(iClient, String:sMessage[], iAuthor) 479 | { 480 | new Handle:hMsg = StartMessageOne("SayText2", iClient, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); 481 | if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) { 482 | PbSetInt(hMsg, "ent_idx", iAuthor); 483 | PbSetBool(hMsg, "chat", true); 484 | PbSetString(hMsg, "msg_name", sMessage); 485 | PbAddString(hMsg, "params", ""); 486 | PbAddString(hMsg, "params", ""); 487 | PbAddString(hMsg, "params", ""); 488 | PbAddString(hMsg, "params", ""); 489 | } else { 490 | BfWriteByte(hMsg, iAuthor); 491 | BfWriteByte(hMsg, true); 492 | BfWriteString(hMsg, sMessage); 493 | } 494 | EndMessage(); 495 | } 496 | 497 | stock CAddWhiteSpace(String:sBuffer[], iSize) 498 | { 499 | if (!IsSource2009()) { 500 | Format(sBuffer, iSize, " %s", sBuffer); 501 | } 502 | } 503 | 504 | // ---------------------------------------------------------------------------------------- 505 | // Private stuff 506 | // ---------------------------------------------------------------------------------------- 507 | 508 | stock bool:Init() 509 | { 510 | if (g_bInit) { 511 | LoadColors(); 512 | return true; 513 | } 514 | 515 | new String:sPluginName[PLATFORM_MAX_PATH]; 516 | new String:sDirectoryPath[PLATFORM_MAX_PATH]; 517 | new Handle:hConfig = INVALID_HANDLE; 518 | GetPluginFilename(INVALID_HANDLE, sPluginName, sizeof(sPluginName)); 519 | ReplaceStringEx(sPluginName, sizeof(sPluginName), "\\", "/"); 520 | new iSlash = FindCharInString(sPluginName, '/', true); 521 | if (iSlash > -1) { 522 | strcopy(sPluginName, sizeof(sPluginName), sPluginName[iSlash + 1]); 523 | } 524 | ReplaceStringEx(sPluginName, sizeof(sPluginName), ".smx", ""); 525 | 526 | BuildPath(Path_SM, sDirectoryPath, sizeof(sDirectoryPath), "%s/", _CV_CONFIG_DIRECTORY); 527 | if (!DirExists(sDirectoryPath)) 528 | CreateDirectory(sDirectoryPath, 511); 529 | 530 | new String:sGlobalVariableList[15][2][64] = { 531 | {"prefix", "{engine 2}"}, 532 | {"default", "{engine 1}"}, 533 | {"reply2cmd", "{engine 1}"}, 534 | {"showactivity", "{engine 1}"}, 535 | {"", ""}, 536 | {"error", "{engine 3}"}, 537 | {"", ""}, 538 | {"highlight", "{engine 2}"}, 539 | {"player", "{engine 2}"}, 540 | {"settings", "{engine 2}"}, 541 | {"command", "{engine 2}"}, 542 | {"", ""}, 543 | {"team0", "{engine 8}"}, 544 | {"team1", "{engine 9}"}, 545 | {"team2", "{engine 11}"} 546 | }; 547 | 548 | if (IsSource2009()) { 549 | strcopy(sGlobalVariableList[12][1], 64, "{#cccccc}"); 550 | strcopy(sGlobalVariableList[13][1], 64, "{#ff4040}"); 551 | strcopy(sGlobalVariableList[14][1], 64, "{#4d7942}"); 552 | } 553 | 554 | BuildPath(Path_SM, g_sConfigGlobal, sizeof(g_sConfigGlobal), "%s/global.cfg", _CV_CONFIG_DIRECTORY); 555 | if (!FileExists(g_sConfigGlobal)) { 556 | hConfig = OpenFile(g_sConfigGlobal, "w"); 557 | if (hConfig == INVALID_HANDLE) { 558 | LogError("Cannot create file '%s' !", g_sConfigGlobal); 559 | return false; 560 | } 561 | 562 | WriteFileLine(hConfig, "// Version: %s", _colorvariables_included); 563 | WriteFileLine(hConfig, "\"colorvariables\""); 564 | WriteFileLine(hConfig, "{"); 565 | for (new i = 0; i < 15; i++) { 566 | if (sGlobalVariableList[i][0][0] == '\0') { 567 | WriteFileLine(hConfig, ""); 568 | } else { 569 | WriteFileLine(hConfig, "\t\"%s\" \"%s\"", sGlobalVariableList[i][0], sGlobalVariableList[i][1]); 570 | } 571 | } 572 | WriteFileLine(hConfig, "}"); 573 | 574 | CloseHandle(hConfig); 575 | hConfig = INVALID_HANDLE; 576 | } else { 577 | hConfig = OpenFile(g_sConfigGlobal, "r"); 578 | if (hConfig == INVALID_HANDLE) { 579 | LogError("Cannot read from file '%s' !", g_sConfigGlobal); 580 | return false; 581 | } 582 | 583 | new String:sVersionLine[64]; 584 | ReadFileLine(hConfig, sVersionLine, sizeof(sVersionLine)); 585 | CloseHandle(hConfig); 586 | 587 | TrimString(sVersionLine); 588 | strcopy(sVersionLine, sizeof(sVersionLine), sVersionLine[FindCharInString(sVersionLine, ':') + 2]); 589 | 590 | if (StringToFloat(sVersionLine) < StringToFloat(_colorvariables_included)) { 591 | new Handle:hKV = CreateKeyValues("colorvariables"); 592 | 593 | if (!FileToKeyValues(hKV, g_sConfigGlobal) || !KvGotoFirstSubKey(hKV, false)) { 594 | CloseHandle(hKV); 595 | LogError("Cannot read variables from file '%s' !", g_sConfigGlobal); 596 | return false; 597 | } 598 | 599 | for (new i = 0; i < 15; i++) { 600 | if (sGlobalVariableList[i][0][0] == '\0') 601 | continue; 602 | 603 | if (!KvJumpToKey(hKV, sGlobalVariableList[i][0])) 604 | KvSetString(hKV, sGlobalVariableList[i][0], sGlobalVariableList[i][1]); 605 | } 606 | 607 | hConfig = OpenFile(g_sConfigGlobal, "w"); 608 | if (hConfig == INVALID_HANDLE) { 609 | LogError("Cannot write to file '%s' !", g_sConfigGlobal); 610 | return false; 611 | } 612 | 613 | WriteFileLine(hConfig, "// Version: %s", _colorvariables_included); 614 | WriteFileLine(hConfig, "\"colorvariables\""); 615 | WriteFileLine(hConfig, "{"); 616 | 617 | new String:sCode[64], String:sColor[64]; 618 | 619 | KvGotoFirstSubKey(hKV, false); 620 | do 621 | { 622 | KvGetSectionName(hKV, sCode, sizeof(sCode)); 623 | KvGetString(hKV, NULL_STRING, sColor, sizeof(sColor)); 624 | StringToLower(sCode); 625 | StringToLower(sColor); 626 | 627 | WriteFileLine(hConfig, "\t\"%s\" \"%s\"", sCode, sColor); 628 | } while (KvGotoNextKey(hKV, false)); 629 | 630 | WriteFileLine(hConfig, "}"); 631 | 632 | CloseHandle(hConfig); 633 | CloseHandle(hKV); 634 | } 635 | } 636 | 637 | BuildPath(Path_SM, g_sConfig, sizeof(g_sConfig), "%s/plugin.%s.cfg", _CV_CONFIG_DIRECTORY, sPluginName); 638 | if (!FileExists(g_sConfig)) { 639 | hConfig = OpenFile(g_sConfig, "w"); 640 | if (hConfig == INVALID_HANDLE) { 641 | LogError("Cannot create file '%s' !", g_sConfig); 642 | return false; 643 | } 644 | 645 | WriteFileLine(hConfig, "\"colorvariables\"\n{\n}"); 646 | CloseHandle(hConfig); 647 | hConfig = INVALID_HANDLE; 648 | } 649 | 650 | for (new iClient = 1; iClient <= MaxClients; iClient++) { 651 | g_bSkipPlayers[iClient] = false; 652 | } 653 | 654 | g_hForwardedVariable = CreateGlobalForward("COnForwardedVariable", ET_Ignore, Param_String, Param_String, Param_Cell, Param_String, Param_Cell); 655 | 656 | LoadColors(); 657 | g_bInit = true; 658 | return true; 659 | } 660 | 661 | stock static LoadColors() 662 | { 663 | if (g_hColors == INVALID_HANDLE) { 664 | g_hColors = CreateTrie(); 665 | new Handle:hRedirect = CreateArray(64); 666 | 667 | AddColors(g_hColors); 668 | LoadConfigFile(g_hColors, g_sConfigGlobal, hRedirect); 669 | LoadConfigFile(g_hColors, g_sConfig, hRedirect); 670 | 671 | SolveRedirects(g_hColors, hRedirect); 672 | CloseHandle(hRedirect); 673 | } 674 | } 675 | 676 | stock static LoadConfigFile(Handle:hTrie, String:sPath[], Handle:hRedirect, bool:bAllowPrefix = true) 677 | { 678 | if (!FileExists(sPath)) { 679 | LogError("Cannot load color variables from file '%s' - file doesn't exist!", sPath); 680 | return; 681 | } 682 | 683 | new Handle:hKV = CreateKeyValues("colorvariables"); 684 | 685 | if (!FileToKeyValues(hKV, sPath)) { 686 | CloseHandle(hKV); 687 | LogError("Cannot load color variables from file '%s' !", sPath); 688 | return; 689 | } 690 | 691 | if (!KvGotoFirstSubKey(hKV, false)) { 692 | CloseHandle(hKV); 693 | return; 694 | } 695 | 696 | new String:sCode[64], String:sColor[64]; 697 | 698 | do 699 | { 700 | KvGetSectionName(hKV, sCode, sizeof(sCode)); 701 | KvGetString(hKV, NULL_STRING, sColor, sizeof(sColor)); 702 | 703 | if (bAllowPrefix && StrEqual(sCode, "&prefix", false)) { 704 | CSetPrefix(sColor); 705 | continue; 706 | } 707 | 708 | StringToLower(sCode); 709 | 710 | if (HasBrackets(sColor) && sColor[1] == '@') { 711 | LogError("Variables cannot be redirected to forwarded variables! (variable '%s')", sCode); 712 | continue; 713 | } 714 | 715 | if (HasBrackets(sColor)) { 716 | if (sColor[1] == '#') { 717 | Format(sColor, sizeof(sColor), "\x07%s", sColor[1]); 718 | } else { 719 | PushArrayString(hRedirect, sCode); 720 | } 721 | } 722 | 723 | SetTrieString(hTrie, sCode, sColor); 724 | } while (KvGotoNextKey(hKV, false)); 725 | 726 | CloseHandle(hKV); 727 | } 728 | 729 | stock static SolveRedirects(Handle:hTrie, Handle:hRedirect) 730 | { 731 | new String:sCode[64], String:sRedirect[64], String:sColor[64], String:sFirstColor[64]; 732 | new iRedirectLife, bool:bHasBrackets; 733 | 734 | for (new i = 0; i < GetArraySize(hRedirect); i++) { 735 | GetArrayString(hRedirect, i, sRedirect, sizeof(sRedirect)); 736 | strcopy(sCode, sizeof(sCode), sRedirect); 737 | bHasBrackets = true; 738 | 739 | GetTrieString(hTrie, sRedirect, sColor, sizeof(sColor)); 740 | strcopy(sFirstColor, sizeof(sFirstColor), sRedirect); 741 | iRedirectLife = _CV_MAX_VARIABLE_REDIRECTS; 742 | 743 | do { 744 | if (!HasBrackets(sColor)) { 745 | strcopy(sRedirect, sizeof(sRedirect), sColor); 746 | bHasBrackets = false; 747 | break; 748 | } 749 | 750 | strcopy(sColor, strlen(sColor) - 1, sColor[1]); 751 | if (iRedirectLife > 0) { 752 | strcopy(sRedirect, sizeof(sRedirect), sColor); 753 | iRedirectLife--; 754 | } else { 755 | strcopy(sRedirect, sizeof(sRedirect), sFirstColor); 756 | LogError("Too many redirects for variable '%s' !", sCode); 757 | break; 758 | } 759 | } while (GetTrieString(hTrie, sRedirect, sColor, sizeof(sColor))); 760 | 761 | if (bHasBrackets) { 762 | Format(sRedirect, sizeof(sRedirect), "{%s}", sRedirect); 763 | } 764 | 765 | StringToLower(sCode); 766 | StringToLower(sRedirect); 767 | SetTrieString(hTrie, sCode, sRedirect); 768 | } 769 | } 770 | 771 | stock static HasBrackets(const String:sSource[]) 772 | { 773 | return (sSource[0] == '{' && sSource[strlen(sSource) - 1] == '}'); 774 | } 775 | 776 | stock static StringToLower(String:sSource[]) 777 | { 778 | for (new i = 0; i < strlen(sSource); i++) { 779 | if (sSource[i] == '\0') 780 | break; 781 | 782 | sSource[i] = CharToLower(sSource[i]); 783 | } 784 | } 785 | 786 | stock static AddColors(Handle:hTrie) 787 | { 788 | if (IsSource2009()) { 789 | SetTrieString(hTrie, "default", "\x01"); 790 | SetTrieString(hTrie, "teamcolor", "\x03"); 791 | 792 | SetTrieString(hTrie, "aliceblue", "\x07F0F8FF"); 793 | SetTrieString(hTrie, "allies", "\x074D7942"); 794 | SetTrieString(hTrie, "ancient", "\x07EB4B4B"); 795 | SetTrieString(hTrie, "antiquewhite", "\x07FAEBD7"); 796 | SetTrieString(hTrie, "aqua", "\x0700FFFF"); 797 | SetTrieString(hTrie, "aquamarine", "\x077FFFD4"); 798 | SetTrieString(hTrie, "arcana", "\x07ADE55C"); 799 | SetTrieString(hTrie, "axis", "\x07FF4040"); 800 | SetTrieString(hTrie, "azure", "\x07007FFF"); 801 | SetTrieString(hTrie, "beige", "\x07F5F5DC"); 802 | SetTrieString(hTrie, "bisque", "\x07FFE4C4"); 803 | SetTrieString(hTrie, "black", "\x07000000"); 804 | SetTrieString(hTrie, "blanchedalmond", "\x07FFEBCD"); 805 | SetTrieString(hTrie, "blue", "\x0799CCFF"); 806 | SetTrieString(hTrie, "blueviolet", "\x078A2BE2"); 807 | SetTrieString(hTrie, "brown", "\x07A52A2A"); 808 | SetTrieString(hTrie, "burlywood", "\x07DEB887"); 809 | SetTrieString(hTrie, "cadetblue", "\x075F9EA0"); 810 | SetTrieString(hTrie, "chartreuse", "\x077FFF00"); 811 | SetTrieString(hTrie, "chocolate", "\x07D2691E"); 812 | SetTrieString(hTrie, "collectors", "\x07AA0000"); 813 | SetTrieString(hTrie, "common", "\x07B0C3D9"); 814 | SetTrieString(hTrie, "community", "\x0770B04A"); 815 | SetTrieString(hTrie, "coral", "\x07FF7F50"); 816 | SetTrieString(hTrie, "cornflowerblue", "\x076495ED"); 817 | SetTrieString(hTrie, "cornsilk", "\x07FFF8DC"); 818 | SetTrieString(hTrie, "corrupted", "\x07A32C2E"); 819 | SetTrieString(hTrie, "crimson", "\x07DC143C"); 820 | SetTrieString(hTrie, "cyan", "\x0700FFFF"); 821 | SetTrieString(hTrie, "darkblue", "\x0700008B"); 822 | SetTrieString(hTrie, "darkcyan", "\x07008B8B"); 823 | SetTrieString(hTrie, "darkgoldenrod", "\x07B8860B"); 824 | SetTrieString(hTrie, "darkgray", "\x07A9A9A9"); 825 | SetTrieString(hTrie, "darkgrey", "\x07A9A9A9"); 826 | SetTrieString(hTrie, "darkgreen", "\x07006400"); 827 | SetTrieString(hTrie, "darkkhaki", "\x07BDB76B"); 828 | SetTrieString(hTrie, "darkmagenta", "\x078B008B"); 829 | SetTrieString(hTrie, "darkolivegreen", "\x07556B2F"); 830 | SetTrieString(hTrie, "darkorange", "\x07FF8C00"); 831 | SetTrieString(hTrie, "darkorchid", "\x079932CC"); 832 | SetTrieString(hTrie, "darkred", "\x078B0000"); 833 | SetTrieString(hTrie, "darksalmon", "\x07E9967A"); 834 | SetTrieString(hTrie, "darkseagreen", "\x078FBC8F"); 835 | SetTrieString(hTrie, "darkslateblue", "\x07483D8B"); 836 | SetTrieString(hTrie, "darkslategray", "\x072F4F4F"); 837 | SetTrieString(hTrie, "darkslategrey", "\x072F4F4F"); 838 | SetTrieString(hTrie, "darkturquoise", "\x0700CED1"); 839 | SetTrieString(hTrie, "darkviolet", "\x079400D3"); 840 | SetTrieString(hTrie, "deeppink", "\x07FF1493"); 841 | SetTrieString(hTrie, "deepskyblue", "\x0700BFFF"); 842 | SetTrieString(hTrie, "dimgray", "\x07696969"); 843 | SetTrieString(hTrie, "dimgrey", "\x07696969"); 844 | SetTrieString(hTrie, "dodgerblue", "\x071E90FF"); 845 | SetTrieString(hTrie, "exalted", "\x07CCCCCD"); 846 | SetTrieString(hTrie, "firebrick", "\x07B22222"); 847 | SetTrieString(hTrie, "floralwhite", "\x07FFFAF0"); 848 | SetTrieString(hTrie, "forestgreen", "\x07228B22"); 849 | SetTrieString(hTrie, "frozen", "\x074983B3"); 850 | SetTrieString(hTrie, "fuchsia", "\x07FF00FF"); 851 | SetTrieString(hTrie, "fullblue", "\x070000FF"); 852 | SetTrieString(hTrie, "fullred", "\x07FF0000"); 853 | SetTrieString(hTrie, "gainsboro", "\x07DCDCDC"); 854 | SetTrieString(hTrie, "genuine", "\x074D7455"); 855 | SetTrieString(hTrie, "ghostwhite", "\x07F8F8FF"); 856 | SetTrieString(hTrie, "gold", "\x07FFD700"); 857 | SetTrieString(hTrie, "goldenrod", "\x07DAA520"); 858 | SetTrieString(hTrie, "gray", "\x07CCCCCC"); 859 | SetTrieString(hTrie, "grey", "\x07CCCCCC"); 860 | SetTrieString(hTrie, "green", "\x073EFF3E"); 861 | SetTrieString(hTrie, "greenyellow", "\x07ADFF2F"); 862 | SetTrieString(hTrie, "haunted", "\x0738F3AB"); 863 | SetTrieString(hTrie, "honeydew", "\x07F0FFF0"); 864 | SetTrieString(hTrie, "hotpink", "\x07FF69B4"); 865 | SetTrieString(hTrie, "immortal", "\x07E4AE33"); 866 | SetTrieString(hTrie, "indianred", "\x07CD5C5C"); 867 | SetTrieString(hTrie, "indigo", "\x074B0082"); 868 | SetTrieString(hTrie, "ivory", "\x07FFFFF0"); 869 | SetTrieString(hTrie, "khaki", "\x07F0E68C"); 870 | SetTrieString(hTrie, "lavender", "\x07E6E6FA"); 871 | SetTrieString(hTrie, "lavenderblush", "\x07FFF0F5"); 872 | SetTrieString(hTrie, "lawngreen", "\x077CFC00"); 873 | SetTrieString(hTrie, "legendary", "\x07D32CE6"); 874 | SetTrieString(hTrie, "lemonchiffon", "\x07FFFACD"); 875 | SetTrieString(hTrie, "lightblue", "\x07ADD8E6"); 876 | SetTrieString(hTrie, "lightcoral", "\x07F08080"); 877 | SetTrieString(hTrie, "lightcyan", "\x07E0FFFF"); 878 | SetTrieString(hTrie, "lightgoldenrodyellow", "\x07FAFAD2"); 879 | SetTrieString(hTrie, "lightgray", "\x07D3D3D3"); 880 | SetTrieString(hTrie, "lightgrey", "\x07D3D3D3"); 881 | SetTrieString(hTrie, "lightgreen", "\x0799FF99"); 882 | SetTrieString(hTrie, "lightpink", "\x07FFB6C1"); 883 | SetTrieString(hTrie, "lightsalmon", "\x07FFA07A"); 884 | SetTrieString(hTrie, "lightseagreen", "\x0720B2AA"); 885 | SetTrieString(hTrie, "lightskyblue", "\x0787CEFA"); 886 | SetTrieString(hTrie, "lightslategray", "\x07778899"); 887 | SetTrieString(hTrie, "lightslategrey", "\x07778899"); 888 | SetTrieString(hTrie, "lightsteelblue", "\x07B0C4DE"); 889 | SetTrieString(hTrie, "lightyellow", "\x07FFFFE0"); 890 | SetTrieString(hTrie, "lime", "\x0700FF00"); 891 | SetTrieString(hTrie, "limegreen", "\x0732CD32"); 892 | SetTrieString(hTrie, "linen", "\x07FAF0E6"); 893 | SetTrieString(hTrie, "magenta", "\x07FF00FF"); 894 | SetTrieString(hTrie, "maroon", "\x07800000"); 895 | SetTrieString(hTrie, "mediumaquamarine", "\x0766CDAA"); 896 | SetTrieString(hTrie, "mediumblue", "\x070000CD"); 897 | SetTrieString(hTrie, "mediumorchid", "\x07BA55D3"); 898 | SetTrieString(hTrie, "mediumpurple", "\x079370D8"); 899 | SetTrieString(hTrie, "mediumseagreen", "\x073CB371"); 900 | SetTrieString(hTrie, "mediumslateblue", "\x077B68EE"); 901 | SetTrieString(hTrie, "mediumspringgreen", "\x0700FA9A"); 902 | SetTrieString(hTrie, "mediumturquoise", "\x0748D1CC"); 903 | SetTrieString(hTrie, "mediumvioletred", "\x07C71585"); 904 | SetTrieString(hTrie, "midnightblue", "\x07191970"); 905 | SetTrieString(hTrie, "mintcream", "\x07F5FFFA"); 906 | SetTrieString(hTrie, "mistyrose", "\x07FFE4E1"); 907 | SetTrieString(hTrie, "moccasin", "\x07FFE4B5"); 908 | SetTrieString(hTrie, "mythical", "\x078847FF"); 909 | SetTrieString(hTrie, "navajowhite", "\x07FFDEAD"); 910 | SetTrieString(hTrie, "navy", "\x07000080"); 911 | SetTrieString(hTrie, "normal", "\x07B2B2B2"); 912 | SetTrieString(hTrie, "oldlace", "\x07FDF5E6"); 913 | SetTrieString(hTrie, "olive", "\x079EC34F"); 914 | SetTrieString(hTrie, "olivedrab", "\x076B8E23"); 915 | SetTrieString(hTrie, "orange", "\x07FFA500"); 916 | SetTrieString(hTrie, "orangered", "\x07FF4500"); 917 | SetTrieString(hTrie, "orchid", "\x07DA70D6"); 918 | SetTrieString(hTrie, "palegoldenrod", "\x07EEE8AA"); 919 | SetTrieString(hTrie, "palegreen", "\x0798FB98"); 920 | SetTrieString(hTrie, "paleturquoise", "\x07AFEEEE"); 921 | SetTrieString(hTrie, "palevioletred", "\x07D87093"); 922 | SetTrieString(hTrie, "papayawhip", "\x07FFEFD5"); 923 | SetTrieString(hTrie, "peachpuff", "\x07FFDAB9"); 924 | SetTrieString(hTrie, "peru", "\x07CD853F"); 925 | SetTrieString(hTrie, "pink", "\x07FFC0CB"); 926 | SetTrieString(hTrie, "plum", "\x07DDA0DD"); 927 | SetTrieString(hTrie, "powderblue", "\x07B0E0E6"); 928 | SetTrieString(hTrie, "purple", "\x07800080"); 929 | SetTrieString(hTrie, "rare", "\x074B69FF"); 930 | SetTrieString(hTrie, "red", "\x07FF4040"); 931 | SetTrieString(hTrie, "rosybrown", "\x07BC8F8F"); 932 | SetTrieString(hTrie, "royalblue", "\x074169E1"); 933 | SetTrieString(hTrie, "saddlebrown", "\x078B4513"); 934 | SetTrieString(hTrie, "salmon", "\x07FA8072"); 935 | SetTrieString(hTrie, "sandybrown", "\x07F4A460"); 936 | SetTrieString(hTrie, "seagreen", "\x072E8B57"); 937 | SetTrieString(hTrie, "seashell", "\x07FFF5EE"); 938 | SetTrieString(hTrie, "selfmade", "\x0770B04A"); 939 | SetTrieString(hTrie, "sienna", "\x07A0522D"); 940 | SetTrieString(hTrie, "silver", "\x07C0C0C0"); 941 | SetTrieString(hTrie, "skyblue", "\x0787CEEB"); 942 | SetTrieString(hTrie, "slateblue", "\x076A5ACD"); 943 | SetTrieString(hTrie, "slategray", "\x07708090"); 944 | SetTrieString(hTrie, "slategrey", "\x07708090"); 945 | SetTrieString(hTrie, "snow", "\x07FFFAFA"); 946 | SetTrieString(hTrie, "springgreen", "\x0700FF7F"); 947 | SetTrieString(hTrie, "steelblue", "\x074682B4"); 948 | SetTrieString(hTrie, "strange", "\x07CF6A32"); 949 | SetTrieString(hTrie, "tan", "\x07D2B48C"); 950 | SetTrieString(hTrie, "teal", "\x07008080"); 951 | SetTrieString(hTrie, "thistle", "\x07D8BFD8"); 952 | SetTrieString(hTrie, "tomato", "\x07FF6347"); 953 | SetTrieString(hTrie, "turquoise", "\x0740E0D0"); 954 | SetTrieString(hTrie, "uncommon", "\x07B0C3D9"); 955 | SetTrieString(hTrie, "unique", "\x07FFD700"); 956 | SetTrieString(hTrie, "unusual", "\x078650AC"); 957 | SetTrieString(hTrie, "valve", "\x07A50F79"); 958 | SetTrieString(hTrie, "vintage", "\x07476291"); 959 | SetTrieString(hTrie, "violet", "\x07EE82EE"); 960 | SetTrieString(hTrie, "wheat", "\x07F5DEB3"); 961 | SetTrieString(hTrie, "white", "\x07FFFFFF"); 962 | SetTrieString(hTrie, "whitesmoke", "\x07F5F5F5"); 963 | SetTrieString(hTrie, "yellow", "\x07FFFF00"); 964 | SetTrieString(hTrie, "yellowgreen", "\x079ACD32"); 965 | } else { 966 | SetTrieString(hTrie, "default", "\x01"); 967 | SetTrieString(hTrie, "teamcolor", "\x03"); 968 | 969 | SetTrieString(hTrie, "red", "\x07"); 970 | SetTrieString(hTrie, "lightred", "\x0F"); 971 | SetTrieString(hTrie, "darkred", "\x02"); 972 | SetTrieString(hTrie, "bluegrey", "\x0A"); 973 | SetTrieString(hTrie, "blue", "\x0B"); 974 | SetTrieString(hTrie, "darkblue", "\x0C"); 975 | SetTrieString(hTrie, "purple", "\x03"); 976 | SetTrieString(hTrie, "orchid", "\x0E"); 977 | SetTrieString(hTrie, "yellow", "\x09"); 978 | SetTrieString(hTrie, "gold", "\x10"); 979 | SetTrieString(hTrie, "lightgreen", "\x05"); 980 | SetTrieString(hTrie, "green", "\x04"); 981 | SetTrieString(hTrie, "lime", "\x06"); 982 | SetTrieString(hTrie, "grey", "\x08"); 983 | SetTrieString(hTrie, "grey2", "\x0D"); 984 | } 985 | 986 | SetTrieString(hTrie, "engine 1", "\x01"); 987 | SetTrieString(hTrie, "engine 2", "\x02"); 988 | SetTrieString(hTrie, "engine 3", "\x03"); 989 | SetTrieString(hTrie, "engine 4", "\x04"); 990 | SetTrieString(hTrie, "engine 5", "\x05"); 991 | SetTrieString(hTrie, "engine 6", "\x06"); 992 | SetTrieString(hTrie, "engine 7", "\x07"); 993 | SetTrieString(hTrie, "engine 8", "\x08"); 994 | SetTrieString(hTrie, "engine 9", "\x09"); 995 | SetTrieString(hTrie, "engine 10", "\x0A"); 996 | SetTrieString(hTrie, "engine 11", "\x0B"); 997 | SetTrieString(hTrie, "engine 12", "\x0C"); 998 | SetTrieString(hTrie, "engine 13", "\x0D"); 999 | SetTrieString(hTrie, "engine 14", "\x0E"); 1000 | SetTrieString(hTrie, "engine 15", "\x0F"); 1001 | SetTrieString(hTrie, "engine 16", "\x10"); 1002 | } 1003 | 1004 | stock static bool:IsSource2009() 1005 | { 1006 | if (g_IsSource2009 == unknown) { 1007 | new EngineVersion:iEngineVersion = GetEngineVersion(); 1008 | g_IsSource2009 = (iEngineVersion == Engine_CSS || iEngineVersion == Engine_TF2 || iEngineVersion == Engine_HL2DM || iEngineVersion == Engine_DODS) ? yes : no; 1009 | } 1010 | 1011 | return bool:g_IsSource2009; 1012 | } 1013 | 1014 | stock static AddPrefixAndDefaultColor(String:sMessage[], iSize, String:sDefaultColor[] = "default", String:sPrefixColor[] = "prefix") 1015 | { 1016 | if (g_sChatPrefix[0] != '\0' && !g_bIgnorePrefix) { 1017 | Format(sMessage, iSize, "{%s}[%s]{%s} %s", sPrefixColor, g_sChatPrefix, sDefaultColor, sMessage); 1018 | } else { 1019 | Format(sMessage, iSize, "{%s}%s", sDefaultColor, sMessage); 1020 | } 1021 | } 1022 | 1023 | stock static SendPlayerMessage(iClient, String:sMessage[], iAuthor = 0) 1024 | { 1025 | if (iAuthor < 1 || iAuthor > MaxClients || !IsClientInGame(iAuthor)) { 1026 | PrintToChat(iClient, sMessage); 1027 | 1028 | if (iAuthor != 0) { 1029 | LogError("Client %d is not valid or in game", iAuthor); 1030 | } 1031 | } else { 1032 | CSayText2(iClient, sMessage, iAuthor); 1033 | } 1034 | } 1035 | -------------------------------------------------------------------------------- /csgo colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PremyslTalich/ColorVariables/351b09bfc1ad70a9539bd3b72ae47a92735b7f50/csgo colors.png --------------------------------------------------------------------------------