Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
chat.qc File Reference
Include dependency graph for chat.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define NO_SLASH()
#define ON_SLASH()

Functions

string AmmoNameFromWeaponentity (entity this,.entity weaponentity)
ERASEABLE void DebugPrintToChat (entity client, string text)
 Print the string to the client's chat if the server cvar "developer" is not 0.
ERASEABLE void DebugPrintToChatAll (string text)
 Prints the string to all clients' chat if the server cvar "developer" is not 0.
ERASEABLE void DebugPrintToChatTeam (int team_num, string text)
 Print the string to chat of all clients of the specified team if the server cvar "developer" is not 0.
entity findnearest (vector point, bool checkitems, vector axismod)
string formatmessage (entity this, string msg)
string NearestLocation (vector p)
string PlayerHealth (entity this)
ERASEABLE void PrintToChat (entity client, string text)
 Print the string to the client's chat.
ERASEABLE void PrintToChatAll (string text)
 Prints the string to all clients' chat.
ERASEABLE void PrintToChatTeam (int team_num, string text)
 Print the string to chat of all clients of the specified team.
int Say (entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
 message "": do not say, just test flood control return value: 1 = accept 0 = reject -1 = fake accept
string WeaponNameFromWeaponentity (entity this,.entity weaponentity)

Macro Definition Documentation

◆ NO_SLASH

#define NO_SLASH ( )
Value:
MACRO_BEGIN if(escape_token == "\\") break; MACRO_END
#define MACRO_END
Definition macro.qh:7
#define MACRO_BEGIN
Definition macro.qh:6

Referenced by formatmessage().

◆ ON_SLASH

#define ON_SLASH ( )
Value:
MACRO_BEGIN warn_slash = false; if(escape_token != "\\") break; MACRO_END

Referenced by formatmessage().

Function Documentation

◆ AmmoNameFromWeaponentity()

string AmmoNameFromWeaponentity ( entity this,
.entity weaponentity )

Definition at line 480 of file chat.qc.

481{
482 entity wepent = this.(weaponentity);
483 string fallback = "N/A";
484 if(!wepent || !IS_PLAYER(this))
485 return fallback;
486 else if(wepent.m_weapon.ammo_type != RES_NONE)
487 return wepent.m_weapon.ammo_type.m_name;
488 else if(wepent.m_switchweapon.ammo_type != RES_NONE)
489 return wepent.m_switchweapon.ammo_type.m_name;
490 return fallback; // REGISTRY_GET(Weapons, wepent.cnt).ammo_type.m_name;
491}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
#define IS_PLAYER(s)
Definition player.qh:242

References entity(), and IS_PLAYER.

Referenced by formatmessage().

◆ DebugPrintToChat()

ERASEABLE void DebugPrintToChat ( entity client,
string text )

Print the string to the client's chat if the server cvar "developer" is not 0.

Parameters
[in]clientClient to print to.
[in]textText to print.

Definition at line 596 of file chat.qc.

597{
598 if (autocvar_developer > 0)
599 {
600 PrintToChat(client, text);
601 }
602}
noref int autocvar_developer
Definition log.qh:93
ERASEABLE void PrintToChat(entity client, string text)
Print the string to the client's chat.
Definition chat.qc:589

References autocvar_developer, entity(), and PrintToChat().

◆ DebugPrintToChatAll()

ERASEABLE void DebugPrintToChatAll ( string text)

Prints the string to all clients' chat if the server cvar "developer" is not 0.

Parameters
[in]textText to print.

Definition at line 612 of file chat.qc.

613{
614 if (autocvar_developer > 0)
615 {
616 PrintToChatAll(text);
617 }
618}
ERASEABLE void PrintToChatAll(string text)
Prints the string to all clients' chat.
Definition chat.qc:605

References autocvar_developer, and PrintToChatAll().

◆ DebugPrintToChatTeam()

ERASEABLE void DebugPrintToChatTeam ( int team_num,
string text )

Print the string to chat of all clients of the specified team if the server cvar "developer" is not 0.

Parameters
[in]team_numTeam to print to. See NUM_TEAM constants.
[in]textText to print.

Definition at line 634 of file chat.qc.

635{
636 if (autocvar_developer > 0)
637 {
638 PrintToChatTeam(team_num, text);
639 }
640}
ERASEABLE void PrintToChatTeam(int team_num, string text)
Print the string to chat of all clients of the specified team.
Definition chat.qc:621

References autocvar_developer, and PrintToChatTeam().

◆ findnearest()

entity findnearest ( vector point,
bool checkitems,
vector axismod )

Definition at line 369 of file chat.qc.

370{
371 vector dist;
372 int num_nearest = 0;
373
374 IntrusiveList list = ((checkitems) ? g_items : g_locations);
375 IL_EACH(list, (checkitems ? (it.target == "###item###") : (it.classname == "target_location")),
376 {
377 if ((it.items == IT_KEY1 || it.items == IT_KEY2) && it.target == "###item###")
378 dist = it.oldorigin;
379 else
380 dist = it.origin;
381 dist -= point;
382 dist = vec3(dist.x * axismod.x, dist.y * axismod.y, dist.z * axismod.z);
383 float len = vlen2(dist);
384
385 int l;
386 for (l = 0; l < num_nearest; ++l)
387 {
388 if (len < nearest_length[l])
389 break;
390 }
391
392 // now i tells us where to insert at
393 // INSERTION SORT! YOU'VE SEEN IT! RUN!
395 {
396 for (int j = NUM_NEAREST_ENTITIES - 2; j >= l; --j)
397 {
398 nearest_length[j + 1] = nearest_length[j];
399 nearest_entity[j + 1] = nearest_entity[j];
400 }
401 nearest_length[l] = len;
402 nearest_entity[l] = it;
403 if (num_nearest < NUM_NEAREST_ENTITIES)
404 ++num_nearest;
405 }
406 });
407
408 // now use the first one from our list that we can see
409 for (int j = 0; j < num_nearest; ++j)
410 {
411 traceline(point, nearest_entity[j].origin, true, NULL);
412 if (trace_fraction == 1)
413 {
414 if (j != 0)
415 {
416 LOG_TRACEF("Nearest point (%s) is not visible, using a visible one.",
418 }
419 return nearest_entity[j];
420 }
421 }
422
423 if (num_nearest == 0)
424 return NULL;
425
426 LOG_TRACE("Not seeing any location point, using nearest as fallback.");
427 /* DEBUGGING CODE:
428 dprint("Candidates were: ");
429 for(j = 0; j < num_nearest; ++j)
430 {
431 if(j != 0)
432 dprint(", ");
433 dprint(nearest_entity[j].netname);
434 }
435 dprint("\n");
436 */
437
438 return nearest_entity[0];
439}
limitations: NULL cannot be present elements can only be present once a maximum of IL_MAX lists can e...
string netname
Definition powerups.qc:20
vector origin
float trace_fraction
#define IL_EACH(this, cond, body)
IntrusiveList g_locations
Definition location.qh:4
#define LOG_TRACEF(...)
Definition log.qh:75
#define LOG_TRACE(...)
Definition log.qh:74
#define NULL
Definition post.qh:14
vector
Definition self.qh:96
entity nearest_entity[NUM_NEAREST_ENTITIES]
Definition chat.qh:23
float nearest_length[NUM_NEAREST_ENTITIES]
Definition chat.qh:24
const float NUM_NEAREST_ENTITIES
Definition chat.qh:22
IntrusiveList g_items
Definition items.qh:118
if(frag_attacker.flagcarried)
Definition sv_ctf.qc:2319

References entity(), g_items, g_locations, if(), IL_EACH, nearest_entity, nearest_length, NUM_NEAREST_ENTITIES, and vector.

Referenced by NearestLocation().

◆ formatmessage()

string formatmessage ( entity this,
string msg )

Definition at line 493 of file chat.qc.

494{
495 float p, p1, p2;
496 float n;
497 vector cursor = '0 0 0';
498 entity cursor_ent = NULL;
499 string escape,escape_token;
500 bool warn_slash = false;
501 string replacement;
502 p = 0;
503 n = 7;
504 bool traced = false;
505
506 MUTATOR_CALLHOOK(PreFormatMessage, this, msg);
507 msg = M_ARGV(1, string);
508
509 while (1) {
510 if (n < 1)
511 break; // too many replacements
512
513 --n;
514 p1 = strstrofs(msg, "%", p); // NOTE: this destroys msg as it's a tempstring!
515 p2 = strstrofs(msg, "\\", p); // NOTE: this destroys msg as it's a tempstring!
516
517 if (p1 < 0)
518 p1 = p2;
519
520 if (p2 < 0)
521 p2 = p1;
522
523 p = min(p1, p2);
524
525 if (p < 0)
526 break;
527
528 if(!traced)
529 {
531 cursor = trace_endpos;
532 cursor_ent = trace_ent;
533 traced = true;
534 }
535
536 replacement = substring(msg, p, 2);
537 escape_token = substring(msg, p, 1);
538 escape = substring(msg, p + 1, 1);
539
540 .entity weaponentity = weaponentities[0]; // TODO: unhardcode
541
542#define ON_SLASH() MACRO_BEGIN warn_slash = false; if(escape_token != "\\") break; MACRO_END
543#define NO_SLASH() MACRO_BEGIN if(escape_token == "\\") break; MACRO_END
544// TODO: remove warn_slash before next release (xonotic-v0.9.0)
545// this is only to warn users of backslash expansions for anything other than '\%', '\\' and '\n'
546 if(escape_token == "\\")
547 warn_slash = true;
548 else
549 warn_slash = false;
550 switch(escape)
551 {
552 case "%": replacement = "%"; warn_slash = false; break;
553 case "\\":ON_SLASH(); replacement = "\\"; break;
554 case "n": ON_SLASH(); replacement = "\n"; break;
555 case "a": NO_SLASH(); replacement = ftos(floor(GetResource(this, RES_ARMOR))); break;
556 case "h": NO_SLASH(); replacement = PlayerHealth(this); break;
557 case "l": NO_SLASH(); replacement = NearestLocation(this.origin); break;
558 case "y": NO_SLASH(); replacement = NearestLocation(cursor); break;
559 case "d": NO_SLASH(); replacement = NearestLocation(this.death_origin); break;
560 case "o": NO_SLASH(); replacement = vtos(this.origin); break;
561 case "O": NO_SLASH(); replacement = sprintf("'%f %f %f'", this.origin.x, this.origin.y, this.origin.z); break;
562 case "w": NO_SLASH(); replacement = WeaponNameFromWeaponentity(this, weaponentity); break;
563 case "W": NO_SLASH(); replacement = AmmoNameFromWeaponentity(this, weaponentity); break;
564 case "x": NO_SLASH(); replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
565 case "s": NO_SLASH(); replacement = ftos(vlen(this.velocity - this.velocity_z * '0 0 1')); break;
566 case "S": NO_SLASH(); replacement = ftos(vlen(this.velocity)); break;
567 case "t": NO_SLASH(); replacement = seconds_tostring(ceil(max(0, autocvar_timelimit * 60 + game_starttime - time))); break;
568 case "T": NO_SLASH(); replacement = seconds_tostring(floor(time - game_starttime)); break;
569 default:
570 {
571 warn_slash = false; // too noisy
572 NO_SLASH();
573 MUTATOR_CALLHOOK(FormatMessage, this, escape, replacement, msg);
574 replacement = M_ARGV(2, string);
575 break;
576 }
577 }
578#undef ON_SLASH
579#undef NO_SLASH
580 if(warn_slash)
581 PrintToChat(this, sprintf("^3WARNING: unsupported \"\\%s\" expansion, use \"%%%s\"", escape, escape));
582 msg = strcat(substring(msg, 0, p), replacement, substring(msg, p+2, strlen(msg) - (p+2)));
583 p += strlen(replacement);
584 }
585 return msg;
586}
#define MUTATOR_CALLHOOK(name,...)
Definition base.qh:186
#define M_ARGV(idx, type)
Definition base.qh:153
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
#define autocvar_timelimit
Definition stats.qh:92
float game_starttime
Definition stats.qh:82
entity trace_ent
vector velocity
float time
vector trace_endpos
vector death_origin
Definition damage.qh:67
#define strstrofs
#define strlen
RES_ARMOR
Definition ent_cs.qc:155
float ceil(float f)
string substring(string s, float start, float length)
float vlen(vector v)
string vtos(vector v)
float min(float f,...)
string ftos(float f)
float floor(float f)
float max(float f,...)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
string WeaponNameFromWeaponentity(entity this,.entity weaponentity)
Definition chat.qc:468
#define NO_SLASH()
string NearestLocation(vector p)
Definition chat.qc:441
#define ON_SLASH()
string PlayerHealth(entity this)
Definition chat.qc:456
string AmmoNameFromWeaponentity(entity this,.entity weaponentity)
Definition chat.qc:480
ERASEABLE string seconds_tostring(float seconds)
Definition string.qh:123
void WarpZone_crosshair_trace_plusvisibletriggers(entity pl)
Definition tracing.qc:579
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:16

References AmmoNameFromWeaponentity(), autocvar_timelimit, ceil(), death_origin, entity(), floor(), ftos(), game_starttime, GetResource(), M_ARGV, max(), min(), MUTATOR_CALLHOOK, NearestLocation(), NO_SLASH, NULL, ON_SLASH, origin, PlayerHealth(), PrintToChat(), RES_ARMOR, seconds_tostring(), strcat(), strlen, strstrofs, substring(), time, trace_endpos, trace_ent, vector, velocity, vlen(), vtos(), WarpZone_crosshair_trace_plusvisibletriggers(), weaponentities, and WeaponNameFromWeaponentity().

Referenced by Say().

◆ NearestLocation()

string NearestLocation ( vector p)

Definition at line 441 of file chat.qc.

442{
443 string ret = "somewhere";
444 entity loc = findnearest(p, false, '1 1 1');
445 if (loc)
446 ret = loc.message;
447 else
448 {
449 loc = findnearest(p, true, '1 1 4');
450 if (loc)
451 ret = loc.netname;
452 }
453 return ret;
454}
entity findnearest(vector point, bool checkitems, vector axismod)
Definition chat.qc:369

References entity(), findnearest(), and vector.

Referenced by formatmessage(), and Obituary().

◆ PlayerHealth()

string PlayerHealth ( entity this)

Definition at line 456 of file chat.qc.

457{
458 float myhealth = floor(GetResource(this, RES_HEALTH));
459 if(myhealth == -666)
460 return "spectating";
461 else if(myhealth == -2342 || (myhealth == 2342 && mapvote_initialized))
462 return "observing";
463 else if(myhealth <= 0 || IS_DEAD(this))
464 return "dead";
465 return ftos(myhealth);
466}
#define IS_DEAD(s)
Definition player.qh:244
bool mapvote_initialized
float myhealth
Definition view.qc:644

References entity(), floor(), ftos(), GetResource(), IS_DEAD, mapvote_initialized, and myhealth.

Referenced by formatmessage().

◆ PrintToChat()

ERASEABLE void PrintToChat ( entity client,
string text )

Print the string to the client's chat.

Parameters
[in]clientClient to print to.
[in]textText to print.

Definition at line 589 of file chat.qc.

590{
591 text = strcat("\{1}^7", text, "\n");
592 sprint(client, text);
593}
void sprint(float clientnum, string text,...)

References entity(), sprint(), and strcat().

Referenced by DebugPrintToChat(), and formatmessage().

◆ PrintToChatAll()

ERASEABLE void PrintToChatAll ( string text)

Prints the string to all clients' chat.

Parameters
[in]textText to print.

Definition at line 605 of file chat.qc.

606{
607 text = strcat("\{1}^7", text, "\n");
608 bprint(text);
609}
void bprint(string text,...)

References bprint(), and strcat().

Referenced by DebugPrintToChatAll().

◆ PrintToChatTeam()

ERASEABLE void PrintToChatTeam ( int team_num,
string text )

Print the string to chat of all clients of the specified team.

Parameters
[in]team_numTeam to print to. See NUM_TEAM constants.
[in]textText to print.

Definition at line 621 of file chat.qc.

622{
623 text = strcat("\{1}^7", text, "\n");
625 {
626 if (it.team == team_num)
627 {
628 sprint(it, text);
629 }
630 });
631}
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52

References FOREACH_CLIENT, IS_REAL_CLIENT, sprint(), and strcat().

Referenced by DebugPrintToChatTeam().

◆ Say()

int Say ( entity source,
int teamsay,
entity privatesay,
string msgin,
bool floodcontrol )

message "": do not say, just test flood control return value: 1 = accept 0 = reject -1 = fake accept

Definition at line 27 of file chat.qc.

28{
30 {
31 Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_DISABLED);
32 return 0;
33 }
34
35 if(!autocvar_g_chat_private_allowed && privatesay)
36 {
37 Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_PRIVATE_DISABLED);
38 return 0;
39 }
40
42 {
43 Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_SPECTATOR_DISABLED);
44 return 0;
45 }
46
47 if(!autocvar_g_chat_team_allowed && teamsay)
48 {
49 Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_TEAM_DISABLED);
50 return 0;
51 }
52
53 if (!teamsay && !privatesay && substring(msgin, 0, 1) == " ")
54 msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
55
56 if (source)
57 msgin = formatmessage(source, msgin);
58
59 string colorstr;
60 if (!(IS_PLAYER(source) || INGAME(source)))
61 colorstr = "^0"; // black for spectators
62 else if(teamplay)
63 colorstr = Team_ColorCode(source.team);
64 else
65 {
66 colorstr = "";
67 teamsay = false;
68 }
69
70 if (!source) {
71 colorstr = "";
72 teamsay = false;
73 }
74
75 if(msgin != "")
76 msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
77
78 /*
79 * using bprint solves this... me stupid
80 // how can we prevent the message from appearing in a listen server?
81 // for now, just give "say" back and only handle say_team
82 if(!teamsay)
83 {
84 clientcommand(source, strcat("say ", msgin));
85 return;
86 }
87 */
88
89 string namestr = "";
90 if (source)
91 namestr = playername(source.netname, source.team, (autocvar_g_chat_teamcolors && IS_PLAYER(source)));
92
94 namestr = strcat(namestr, " ^9#", itos(etof(source)), "^7");
95
96 string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
97
98 string msgstr = "", cmsgstr = "";
99 string privatemsgprefix = string_null;
100 int privatemsgprefixlen = 0;
101 if (msgin != "")
102 {
103 bool found_me = (substring(msgin, 0, 4) == "/me "); // only accept /me at the start of the string, to prevent imitating others
104 if(found_me)
105 {
106 string newnamestr = ((teamsay) ? strcat(colorstr, "(", colorprefix, namestr, colorstr, ")", "^7") : strcat(colorprefix, namestr, "^7"));
107 msgin = strcat(newnamestr, substring(msgin, 3, strlen(msgin) - 3));
108 }
109
110 if(privatesay)
111 {
112 msgstr = strcat("\{1}\{13}* ", colorprefix, namestr, "^3 tells you: ^7");
113 privatemsgprefixlen = strlen(msgstr);
114 msgstr = strcat(msgstr, msgin);
115 cmsgstr = strcat(colorstr, colorprefix, namestr, "^3 tells you:\n^7", msgin);
116 privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay.netname, privatesay.team, (autocvar_g_chat_teamcolors && IS_PLAYER(privatesay))), ": ^7");
117 }
118 else if(teamsay)
119 {
120 if(found_me)
121 {
122 //msgin = strreplace("/me", "", msgin);
123 //msgin = substring(msgin, 3, strlen(msgin));
124 //msgin = strreplace("/me", strcat(colorstr, "(", colorprefix, namestr, colorstr, ")^7"), msgin);
125 msgstr = strcat("\{1}\{13}^4* ", "^7", msgin);
126 }
127 else
128 msgstr = strcat("\{1}\{13}", colorstr, "(", colorprefix, namestr, colorstr, ") ^7", msgin);
129 cmsgstr = strcat(colorstr, "(", colorprefix, namestr, colorstr, ")\n^7", msgin);
130 }
131 else
132 {
133 if(found_me)
134 {
135 //msgin = strreplace("/me", "", msgin);
136 //msgin = substring(msgin, 3, strlen(msgin));
137 //msgin = strreplace("/me", strcat(colorprefix, namestr), msgin);
138 msgstr = strcat("\{1}^4* ^7", msgin);
139 }
140 else {
141 msgstr = "\{1}";
142 msgstr = strcat(msgstr, (namestr != "") ? strcat(colorprefix, namestr, "^7: ") : "^7");
143 msgstr = strcat(msgstr, msgin);
144 }
145 cmsgstr = "";
146 }
147 msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
148 }
149
150 string fullmsgstr = msgstr;
151 string fullcmsgstr = cmsgstr;
152 float mod_time = 0;
153
154 // FLOOD CONTROL
155 int flood = 0;
156 var .float flood_field = floodcontrol_chat;
157 if(floodcontrol && source)
158 {
159 float flood_spl, flood_burst, flood_lmax;
160 if(privatesay)
161 {
165 flood_field = floodcontrol_chattell;
166 }
167 else if(teamsay)
168 {
172 flood_field = floodcontrol_chatteam;
173 }
174 else
175 {
176 flood_spl = autocvar_g_chat_flood_spl;
177 flood_burst = autocvar_g_chat_flood_burst;
178 flood_lmax = autocvar_g_chat_flood_lmax;
179 flood_field = floodcontrol_chat;
180 }
181 // to match cvar descriptions, a value of 3 must allow three-line bursts and not four!
182 flood_burst = max(0, flood_burst - 1);
183
184 int lines = -1;
185 mod_time = gettime(GETTIME_FRAMESTART) + flood_burst * flood_spl;
186 // do flood control for the default line size
187 if(msgstr != "")
188 {
190 msgstr = "";
191 lines = 0;
192 while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
193 {
194 msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
195 ++lines;
196 }
197 msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
198
200 {
201 msgstr = strcat(msgstr, "\n");
202 flood = 2;
203 }
204 }
205
206 if (mod_time >= source.(flood_field))
207 {
208 if (lines > 1)
209 flood_spl *= lines;
210 source.(flood_field) = max(gettime(GETTIME_FRAMESTART), source.(flood_field)) + flood_spl;
211 }
212 else
213 {
214 if (lines >= 0) // if true msgstr was modified
215 msgstr = fullmsgstr;
216 flood = 1;
217 }
218 }
219
220 string sourcemsgstr, sourcecmsgstr;
221 if(flood == 2) // cannot happen for empty msgstr
222 {
224 {
225 sourcemsgstr = strcat(msgstr, "\n^3CHAT FLOOD CONTROL: ^7message too long, trimmed\n");
226 sourcecmsgstr = "";
227 }
228 else
229 {
230 sourcemsgstr = fullmsgstr;
231 sourcecmsgstr = fullcmsgstr;
232 }
233 cmsgstr = "";
234 }
235 else
236 {
237 sourcemsgstr = msgstr;
238 sourcecmsgstr = cmsgstr;
239 }
240
241 if (!privatesay && source && !(IS_PLAYER(source) || INGAME(source)) && !game_stopped
242 && (teamsay || CHAT_NOSPECTATORS()))
243 teamsay = -1; // spectators
244
245 if(flood)
246 LOG_INFO("NOTE: ", playername(source.netname, source.team, IS_PLAYER(source)), "^7 is flooding.");
247
248 // build sourcemsgstr by cutting off a prefix and replacing it by the other one
249 if(privatesay)
250 sourcemsgstr = strcat(privatemsgprefix, substring(sourcemsgstr, privatemsgprefixlen, -1));
251
252 int ret;
253 if(source && CS(source).muted)
254 {
255 // always fake the message
256 ret = -1;
257 }
258 else if(flood == 1)
259 {
261 {
262 sprint(source, strcat("^3CHAT FLOOD CONTROL: ^7wait ^1", ftos(source.(flood_field) - mod_time),
263 "^7 seconds\n"));
264 ret = 0;
265 }
266 else
267 ret = -1;
268 }
269 else
270 ret = 1;
271
272 if (privatesay && source && !(IS_PLAYER(source) || INGAME(source)) && !game_stopped
273 && (IS_PLAYER(privatesay) || INGAME(privatesay)) && CHAT_NOSPECTATORS())
274 ret = -1; // just hide the message completely
275
276 MUTATOR_CALLHOOK(ChatMessage, source, ret, msgin, privatesay, teamsay);
277 ret = M_ARGV(1, int);
278
279 string event_log_msg = "";
280
281 if(sourcemsgstr != "" && ret != 0)
282 {
283 if(ret < 0) // faked message, because the player is muted
284 {
285 sprint(source, sourcemsgstr);
286 if(sourcecmsgstr != "" && !privatesay)
287 centerprint(source, sourcecmsgstr);
288 }
289 else if(privatesay) // private message, between 2 people only
290 {
291 sprint(source, sourcemsgstr);
293 dedicated_print(msgstr); // send to server console too if "tellprivacy" is disabled
294 if(!MUTATOR_CALLHOOK(ChatMessageTo, privatesay, source))
295 {
296 if(IS_REAL_CLIENT(source) && ignore_playerinlist(privatesay, source))
297 return -1; // source is ignored by privatesay, no sending to this player, thank you very much
298
299 sprint(privatesay, msgstr);
300 if(cmsgstr != "")
301 centerprint(privatesay, cmsgstr);
302 }
303 }
304 else if ( teamsay && CS(source).active_minigame )
305 {
306 sprint(source, sourcemsgstr);
307 dedicated_print(msgstr); // send to server console too
308 FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
309 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
310 continue; // source is ignored by it, no sending to this player, thank you very much
311
312 sprint(it, msgstr);
313 });
314 event_log_msg = sprintf(":chat_minigame:%d:%s:%s", source.playerid, CS(source).active_minigame.netname, msgin);
315
316 }
317 else if(teamsay > 0) // team message, only sent to teammates
318 {
319 sprint(source, sourcemsgstr);
320 dedicated_print(msgstr); // send to server console too
321 if(sourcecmsgstr != "")
322 centerprint(source, sourcecmsgstr);
323 FOREACH_CLIENT((IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
324 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
325 continue; // source is ignored by it, no sending to this player, thank you very much
326
327 sprint(it, msgstr);
328 if(cmsgstr != "")
329 centerprint(it, cmsgstr);
330 });
331 event_log_msg = sprintf(":chat_team:%d:%d:%s", source.playerid, source.team, strreplace("\n", " ", msgin));
332 }
333 else if(teamsay < 0) // spectator message, only sent to spectators
334 {
335 sprint(source, sourcemsgstr);
336 dedicated_print(msgstr); // send to server console too
337 FOREACH_CLIENT(!(IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
338 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
339 continue; // source is ignored by it, no sending to this player, thank you very much
340
341 sprint(it, msgstr);
342 });
343 event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
344 }
345 else
346 {
347 if (source)
348 {
349 sprint(source, sourcemsgstr);
350 dedicated_print(msgstr); // send to server console too
351 MX_Say(strcat(playername(source.netname, source.team, IS_PLAYER(source)), "^7: ", msgin));
352 }
353 FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
354 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
355 continue; // source is ignored by it, no sending to this player, thank you very much
356
357 sprint(it, msgstr);
358 });
359 event_log_msg = sprintf(":chat:%d:%s", source.playerid, strreplace("\n", " ", msgin));
360 }
361 }
362
363 if (autocvar_sv_eventlog && (event_log_msg != ""))
364 GameLogEcho(event_log_msg);
365
366 return ret;
367}
entity active_minigame
bool ignore_playerinlist(entity this, entity pl)
Checks if pl is ignored by this (permanently or for the current match).
Definition cmd.qc:134
float game_stopped
Definition stats.qh:81
string playername(string thename, int teamid, bool team_colorize)
Definition util.qc:2180
string getWrappedLineLen(int maxLength, textLengthUpToLength_lenFunction_t tw)
Definition util.qc:1153
string getWrappedLine_remaining
Definition util.qh:154
float GETTIME_FRAMESTART
void GameLogEcho(string s)
Definition gamelog.qc:15
bool autocvar_sv_eventlog
Definition gamelog.qh:3
#define itos(i)
Definition int.qh:6
void MX_Say(string body)
Definition matrix.qc:207
#define LOG_INFO(...)
Definition log.qh:62
string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin)
Definition magicear.qc:149
float gettime(void)
void centerprint(string text,...)
#define etof(e)
Definition misc.qh:25
string string_null
Definition nil.qh:9
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1500
string formatmessage(entity this, string msg)
Definition chat.qc:493
bool autocvar_g_chat_allowed
Definition chat.qh:13
bool autocvar_g_chat_team_allowed
Definition chat.qh:16
bool autocvar_g_chat_flood_notify_flooder
Definition chat.qh:9
float autocvar_g_chat_flood_lmax
Definition chat.qh:6
float floodcontrol_chat
Definition chat.qh:26
float autocvar_g_chat_flood_burst_tell
Definition chat.qh:5
float autocvar_g_chat_flood_lmax_team
Definition chat.qh:7
bool autocvar_g_chat_show_playerid
Definition chat.qh:20
float autocvar_g_chat_flood_lmax_tell
Definition chat.qh:8
float autocvar_g_chat_flood_spl_tell
Definition chat.qh:12
bool autocvar_g_chat_teamcolors
Definition chat.qh:18
#define CHAT_NOSPECTATORS()
Definition chat.qh:30
float autocvar_g_chat_flood_spl
Definition chat.qh:10
float autocvar_g_chat_flood_spl_team
Definition chat.qh:11
bool autocvar_g_chat_spectator_allowed
Definition chat.qh:15
float autocvar_g_chat_flood_burst_team
Definition chat.qh:4
float floodcontrol_chattell
Definition chat.qh:28
bool autocvar_g_chat_tellprivacy
Definition chat.qh:19
float autocvar_g_chat_flood_burst
Definition chat.qh:3
bool autocvar_g_chat_private_allowed
Definition chat.qh:14
float floodcontrol_chatteam
Definition chat.qh:27
void dedicated_print(string input)
print(), but only print if the server is not local
Definition main.qc:233
ClientState CS(Client this)
Definition state.qh:47
#define INGAME(it)
Definition sv_rules.qh:24
bool teamplay
Definition teams.qh:59
string Team_ColorCode(int teamid)
Definition teams.qh:63
#define IS_OBSERVER(v)
Definition utils.qh:11

References active_minigame, autocvar_g_chat_allowed, autocvar_g_chat_flood_burst, autocvar_g_chat_flood_burst_team, autocvar_g_chat_flood_burst_tell, autocvar_g_chat_flood_lmax, autocvar_g_chat_flood_lmax_team, autocvar_g_chat_flood_lmax_tell, autocvar_g_chat_flood_notify_flooder, autocvar_g_chat_flood_spl, autocvar_g_chat_flood_spl_team, autocvar_g_chat_flood_spl_tell, autocvar_g_chat_private_allowed, autocvar_g_chat_show_playerid, autocvar_g_chat_spectator_allowed, autocvar_g_chat_team_allowed, autocvar_g_chat_teamcolors, autocvar_g_chat_tellprivacy, autocvar_sv_eventlog, centerprint(), CHAT_NOSPECTATORS, CS(), dedicated_print(), entity(), etof, floodcontrol_chat, floodcontrol_chatteam, floodcontrol_chattell, FOREACH_CLIENT, formatmessage(), ftos(), game_stopped, GameLogEcho(), gettime(), GETTIME_FRAMESTART, getWrappedLine_remaining, getWrappedLineLen(), ignore_playerinlist(), INGAME, IS_OBSERVER, IS_PLAYER, IS_REAL_CLIENT, itos, LOG_INFO, M_ARGV, max(), MUTATOR_CALLHOOK, MX_Say(), playername(), Send_Notification(), sprint(), strcat(), string_null, strlen, substring(), Team_ColorCode(), teamplay, and trigger_magicear_processmessage_forallears().

Referenced by ClientCommand_say(), ClientCommand_say_team(), ClientCommand_tell(), and MX_Handle().

◆ WeaponNameFromWeaponentity()

string WeaponNameFromWeaponentity ( entity this,
.entity weaponentity )

Definition at line 468 of file chat.qc.

469{
470 entity wepent = this.(weaponentity);
471 if(!wepent || !IS_PLAYER(this))
472 return "N/A";
473 else if(wepent.m_weapon != WEP_Null)
474 return wepent.m_weapon.m_name;
475 else if(wepent.m_switchweapon != WEP_Null)
476 return wepent.m_switchweapon.m_name;
477 return "none"; //REGISTRY_GET(Weapons, wepent.cnt).m_name;
478}

References entity(), and IS_PLAYER.

Referenced by formatmessage().