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 485 of file chat.qc.

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

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 601 of file chat.qc.

602{
603 if (autocvar_developer > 0)
604 {
605 PrintToChat(client, text);
606 }
607}
noref int autocvar_developer
Definition log.qh:96
ERASEABLE void PrintToChat(entity client, string text)
Print the string to the client's chat.
Definition chat.qc:594

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 617 of file chat.qc.

618{
619 if (autocvar_developer > 0)
620 {
621 PrintToChatAll(text);
622 }
623}
ERASEABLE void PrintToChatAll(string text)
Prints the string to all clients' chat.
Definition chat.qc:610

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 639 of file chat.qc.

640{
641 if (autocvar_developer > 0)
642 {
643 PrintToChatTeam(team_num, text);
644 }
645}
ERASEABLE void PrintToChatTeam(int team_num, string text)
Print the string to chat of all clients of the specified team.
Definition chat.qc:626

References autocvar_developer, and PrintToChatTeam().

◆ findnearest()

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

Definition at line 374 of file chat.qc.

375{
376 vector dist;
377 int num_nearest = 0;
378
379 IntrusiveList list = ((checkitems) ? g_items : g_locations);
380 IL_EACH(list, (checkitems ? (it.target == "###item###") : (it.classname == "target_location")),
381 {
382 if ((it.items == IT_KEY1 || it.items == IT_KEY2) && it.target == "###item###")
383 dist = it.oldorigin;
384 else
385 dist = it.origin;
386 dist = dist - point;
387 dist = vec3(dist.x * axismod.x, dist.y * axismod.y, dist.z * axismod.z);
388 float len = vlen2(dist);
389
390 int l;
391 for (l = 0; l < num_nearest; ++l)
392 {
393 if (len < nearest_length[l])
394 break;
395 }
396
397 // now i tells us where to insert at
398 // INSERTION SORT! YOU'VE SEEN IT! RUN!
400 {
401 for (int j = NUM_NEAREST_ENTITIES - 2; j >= l; --j)
402 {
403 nearest_length[j + 1] = nearest_length[j];
404 nearest_entity[j + 1] = nearest_entity[j];
405 }
406 nearest_length[l] = len;
407 nearest_entity[l] = it;
408 if (num_nearest < NUM_NEAREST_ENTITIES)
409 num_nearest = num_nearest + 1;
410 }
411 });
412
413 // now use the first one from our list that we can see
414 for (int j = 0; j < num_nearest; ++j)
415 {
416 traceline(point, nearest_entity[j].origin, true, NULL);
417 if (trace_fraction == 1)
418 {
419 if (j != 0)
420 {
421 LOG_TRACEF("Nearest point (%s) is not visible, using a visible one.",
423 }
424 return nearest_entity[j];
425 }
426 }
427
428 if (num_nearest == 0)
429 return NULL;
430
431 LOG_TRACE("Not seeing any location point, using nearest as fallback.");
432 /* DEBUGGING CODE:
433 dprint("Candidates were: ");
434 for(j = 0; j < num_nearest; ++j)
435 {
436 if(j != 0)
437 dprint(", ");
438 dprint(nearest_entity[j].netname);
439 }
440 dprint("\n");
441 */
442
443 return nearest_entity[0];
444}
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:77
#define LOG_TRACE(...)
Definition log.qh:76
#define NULL
Definition post.qh:14
vector
Definition self.qh:92
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:125
if(frag_attacker.flagcarried)
Definition sv_ctf.qc:2325

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 498 of file chat.qc.

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

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 446 of file chat.qc.

447{
448 string ret = "somewhere";
449 entity loc = findnearest(p, false, '1 1 1');
450 if (loc)
451 ret = loc.message;
452 else
453 {
454 loc = findnearest(p, true, '1 1 4');
455 if (loc)
456 ret = loc.netname;
457 }
458 return ret;
459}
entity findnearest(vector point, bool checkitems, vector axismod)
Definition chat.qc:374

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

Referenced by formatmessage(), and Obituary().

◆ PlayerHealth()

string PlayerHealth ( entity this)

Definition at line 461 of file chat.qc.

462{
463 float myhealth = floor(GetResource(this, RES_HEALTH));
464 if(myhealth == -666)
465 return "spectating";
466 else if(myhealth == -2342 || (myhealth == 2342 && mapvote_initialized))
467 return "observing";
468 else if(myhealth <= 0 || IS_DEAD(this))
469 return "dead";
470 return ftos(myhealth);
471}
#define IS_DEAD(s)
Definition player.qh:245
float mapvote_initialized
Definition mapvoting.qh:46
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 594 of file chat.qc.

595{
596 text = strcat("\{1}^7", text, "\n");
597 sprint(client, text);
598}
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 610 of file chat.qc.

611{
612 text = strcat("\{1}^7", text, "\n");
613 bprint(text);
614}
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 626 of file chat.qc.

627{
628 text = strcat("\{1}^7", text, "\n");
630 {
631 if (it.team == team_num)
632 {
633 sprint(it, text);
634 }
635 });
636}
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50

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 {
244 teamsay = -1; // spectators
245 }
246
247 if(flood)
248 LOG_INFO("NOTE: ", playername(source.netname, source.team, IS_PLAYER(source)), "^7 is flooding.");
249
250 // build sourcemsgstr by cutting off a prefix and replacing it by the other one
251 if(privatesay)
252 sourcemsgstr = strcat(privatemsgprefix, substring(sourcemsgstr, privatemsgprefixlen, -1));
253
254 int ret;
255 if(source && CS(source).muted)
256 {
257 // always fake the message
258 ret = -1;
259 }
260 else if(flood == 1)
261 {
263 {
264 sprint(source, strcat("^3CHAT FLOOD CONTROL: ^7wait ^1",
265 ftos(source.(flood_field) - mod_time), "^3 seconds\n"));
266 ret = 0;
267 }
268 else
269 ret = -1;
270 }
271 else
272 {
273 ret = 1;
274 }
275
276 if (privatesay && source && !(IS_PLAYER(source) || INGAME(source)) && !game_stopped
277 && (IS_PLAYER(privatesay) || INGAME(privatesay)) && CHAT_NOSPECTATORS())
278 {
279 ret = -1; // just hide the message completely
280 }
281
282 MUTATOR_CALLHOOK(ChatMessage, source, ret, sourcemsgstr);
283 ret = M_ARGV(1, int);
284
285 string event_log_msg = "";
286
287 if(sourcemsgstr != "" && ret != 0)
288 {
289 if(ret < 0) // faked message, because the player is muted
290 {
291 sprint(source, sourcemsgstr);
292 if(sourcecmsgstr != "" && !privatesay)
293 centerprint(source, sourcecmsgstr);
294 }
295 else if(privatesay) // private message, between 2 people only
296 {
297 sprint(source, sourcemsgstr);
298 if (!autocvar_g_chat_tellprivacy) { dedicated_print(msgstr); } // send to server console too if "tellprivacy" is disabled
299 if(!MUTATOR_CALLHOOK(ChatMessageTo, privatesay, source))
300 {
301 if(IS_REAL_CLIENT(source) && ignore_playerinlist(privatesay, source))
302 return -1; // source is ignored by privatesay, no sending to this player, thank you very much
303
304 sprint(privatesay, msgstr);
305 if(cmsgstr != "")
306 centerprint(privatesay, cmsgstr);
307 }
308 }
309 else if ( teamsay && CS(source).active_minigame )
310 {
311 sprint(source, sourcemsgstr);
312 dedicated_print(msgstr); // send to server console too
313 FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
314 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
315 continue; // source is ignored by it, no sending to this player, thank you very much
316
317 sprint(it, msgstr);
318 });
319 event_log_msg = sprintf(":chat_minigame:%d:%s:%s", source.playerid, CS(source).active_minigame.netname, msgin);
320
321 }
322 else if(teamsay > 0) // team message, only sent to teammates
323 {
324 sprint(source, sourcemsgstr);
325 dedicated_print(msgstr); // send to server console too
326 if(sourcecmsgstr != "")
327 centerprint(source, sourcecmsgstr);
328 FOREACH_CLIENT((IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
329 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
330 continue; // source is ignored by it, no sending to this player, thank you very much
331
332 sprint(it, msgstr);
333 if(cmsgstr != "")
334 centerprint(it, cmsgstr);
335 });
336 event_log_msg = sprintf(":chat_team:%d:%d:%s", source.playerid, source.team, strreplace("\n", " ", msgin));
337 }
338 else if(teamsay < 0) // spectator message, only sent to spectators
339 {
340 sprint(source, sourcemsgstr);
341 dedicated_print(msgstr); // send to server console too
342 FOREACH_CLIENT(!(IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
343 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
344 continue; // source is ignored by it, no sending to this player, thank you very much
345
346 sprint(it, msgstr);
347 });
348 event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
349 }
350 else
351 {
352 if (source) {
353 sprint(source, sourcemsgstr);
354 dedicated_print(msgstr); // send to server console too
355 MX_Say(strcat(playername(source.netname, source.team, IS_PLAYER(source)), "^7: ", msgin));
356 }
357 FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
358 if(IS_REAL_CLIENT(source) && ignore_playerinlist(it, source))
359 continue; // source is ignored by it, no sending to this player, thank you very much
360
361 sprint(it, msgstr);
362 });
363 event_log_msg = sprintf(":chat:%d:%s", source.playerid, strreplace("\n", " ", msgin));
364 }
365 }
366
367 if (autocvar_sv_eventlog && (event_log_msg != "")) {
368 GameLogEcho(event_log_msg);
369 }
370
371 return ret;
372}
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:2082
string getWrappedLineLen(int maxLength, textLengthUpToLength_lenFunction_t tw)
Definition util.qc:1033
string getWrappedLine_remaining
Definition util.qh:147
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:187
#define LOG_INFO(...)
Definition log.qh:65
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:1573
string formatmessage(entity this, string msg)
Definition chat.qc:498
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 473 of file chat.qc.

474{
475 entity wepent = this.(weaponentity);
476 if(!wepent || !IS_PLAYER(this))
477 return "N/A";
478 else if(wepent.m_weapon != WEP_Null)
479 return wepent.m_weapon.m_name;
480 else if(wepent.m_switchweapon != WEP_Null)
481 return wepent.m_switchweapon.m_name;
482 return "none"; //REGISTRY_GET(Weapons, wepent.cnt).m_name;
483}

References entity(), and IS_PLAYER.

Referenced by formatmessage().