├── 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 | - 
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
--------------------------------------------------------------------------------