1 // ================================================
2 // Unified notification system, written by Samual
3 // Last updated: September, 2012
4 // ================================================
6 // main types/groups of notifications
7 #define MSG_INFO 1 // "Global" information messages (sent to console, and notify panel if it has an icon)
8 #define MSG_CENTER 2 // "Personal" centerprint messages
9 #define MSG_WEAPON 3 // "Personal" weapon messages (like "You got the Nex", sent to weapon notify panel)
12 #define NO_FL_ARG -12345
18 // allow sending of notifications to also pass through to spectators (specifically for centerprints)
20 #define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
21 #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
22 #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
25 #define NOTIF_MATCH(a,b) if(min(NOTIF_MAX, a) == b)
27 string got_commandkey;
28 #define ADD_CSQC_AUTOCVAR(name) var float autocvar_notification_##name = TRUE;
29 var float autocvar_notification_ctf_capture_verbose = TRUE;
30 var float autocvar_notification_ctf_pickup_team_verbose = TRUE;
31 var float autocvar_notification_ctf_pickup_enemy_verbose = TRUE;
32 #define CHECK_AUTOCVAR(name) if(autocvar_notification_##name)
33 #define HANDLE_CPID(cpid) ((min(NOTIF_MAX, cpid) == NO_CPID) ? FALSE : cpid)
34 #define PASS_KEY ((((got_commandkey = getcommandkey("pass", "+use")) != "pass") && !(strstrofs(got_commandkey, "not bound", 0) >= 0)) ? sprintf(CCR(_(" ^F1(Press %s)")), got_commandkey) : "")
36 #define ADD_CSQC_AUTOCVAR(name)
39 string team_name_red = _("Red");
40 string team_name_blue = _("Blue");
41 string team_name_yellow = _("Yellow");
42 string team_name_pink = _("Pink");
43 string team_color_red = "^1";
44 string team_color_blue = "^4";
45 string team_color_yellow = "";
46 string team_color_pink = "";
49 // ====================================
50 // Notifications List and Information
51 // ====================================
53 List of all notifications (including identifiers and display information)
54 Format: name, strnum, flnum, args, *icon/CPID, *durcnt, normal, gentle
55 Asterisked fields are not present in all notification types.
58 Number of STRING arguments (so that networking knows how many to send/receive)
59 Number of FLOAT arguments (so that networking knows how many to send/receive)
60 Arguments for sprintf(string, args), if no args needed then use ""
62 MSG_INFO: STRING: icon string name for the hud notify panel, "" if no icon is used
63 MSG_CENTER: FLOAT: centerprint ID number (CPID_*), NO_CPID if no CPID is needed
65 MSG_CENTER: XPND2(FLOAT, FLOAT): extra arguments for centerprint messages
66 Normal message (string for sprintf when gentle messages are NOT enabled)
67 Gentle message (string for sprintf when gentle messages ARE enabled)
69 Messages have ^F1, ^F2, and ^BG in them-- these are replaced
70 with colors according to the cvars the user has chosen.
71 ^F1 = highest priority, "primary"
72 ^F2 = next highest priority, "secondary"
73 ^BG = normal/less important priority, "tertiary"
75 Guidlines (please try and follow these):
76 -ALWAYS start the string with a color, preferably background.
77 -ALWAYS reset a color after a name (this way they don't set it for the whole string).
78 -NEVER re-declare an event twice.
79 -NEVER add or remove fields from the format, it SHOULD already work.
80 -MSG_INFO messages must ALWAYS end with a new line: \n
81 -Be clean and simple with your notification naming,
82 nothing too long for the name field... Abbreviations are your friend. :D
83 -Keep the spacing as clean as possible... if the arguments are abnormally long,
84 it's okay to go out of line a bit... but try and keep it clean still.
85 -Keep the notifications in alphabetical order.
86 ARIRE unir frk jvgu lbhe bja zbgure. (gvc sbe zvxrrhfn) -- Don't pay attention to this ^_^
89 // weaponorder[f1].netname
91 #define MULTITEAM_INFO(prefix,teams,strnum,flnum,args,hudargs,icon,normal,gentle) \
92 MSG_INFO_NOTIF(prefix##RED, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_red)), TCR(normal, team_color_red, strtoupper(team_name_red)), TCR(gentle, team_color_red, strtoupper(team_name_red))) \
93 MSG_INFO_NOTIF(prefix##BLUE, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_blue)), TCR(normal, team_color_blue, strtoupper(team_name_blue)), TCR(gentle, team_color_blue, strtoupper(team_name_blue))) \
95 MSG_INFO_NOTIF(prefix##YELLOW, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_yellow)), TCR(normal, team_color_yellow, strtoupper(team_name_yellow)), TCR(gentle, team_color_yellow, strtoupper(team_name_yellow))) \
98 MSG_INFO_NOTIF(prefix##PINK, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_pink)), TCR(normal, team_color_pink, strtoupper(team_name_pink)), TCR(gentle, team_color_pink, strtoupper(team_name_pink))) \
100 #define MSG_INFO_NOTIFICATIONS \
101 MSG_INFO_NOTIF(INFO_EMPTY, 0, 0, NO_STR_ARG, XPND2("", ""), "", "", "") \
102 MULTITEAM_INFO(INFO_SCORES_, 2, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^TC^TT ^BGteam scores!\n"), "") \
103 MULTITEAM_INFO(INFO_CTF_FLAGRETURN_DROPPED_, 2, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself\n"), "") \
104 MULTITEAM_INFO(INFO_CTF_FLAGRETURN_DAMAGED_, 2, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^BGThe ^TC^TT^BG flag was destroyed and returned to base\n"), "") \
105 MULTITEAM_INFO(INFO_CTF_FLAGRETURN_SPEEDRUN_, 2, 0, 1, f1/100, XPND2("", ""), "", _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself\n"), "") \
106 MULTITEAM_INFO(INFO_CTF_FLAGRETURN_NEEDKILL_, 2, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to base\n"), "") \
107 MULTITEAM_INFO(INFO_CTF_FLAGRETURN_ABORTRUN_, 2, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^BGThe ^TC^TT^BG flag was returned to base by its owner\n"), "") \
108 MULTITEAM_INFO(INFO_CTF_FLAGRETURN_TIMEOUT_, 2, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^BGThe ^TC^TT^BG flag has returned to the base\n"), "") \
109 MULTITEAM_INFO(INFO_CTF_PICKUP_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_taken", _("^BG%s^BG got the ^TC^TT^BG flag\n"), "") \
110 MULTITEAM_INFO(INFO_CTF_RETURN_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_returned", _("^BG%s^BG returned the ^TC^TT^BG flag\n"), "") \
111 MULTITEAM_INFO(INFO_CTF_LOST_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_lost", _("^BG%s^BG lost the ^TC^TT^BG flag\n"), "") \
112 MULTITEAM_INFO(INFO_CTF_CAPTURE_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag\n"), "") \
113 MULTITEAM_INFO(INFO_CTF_CAPTURE_TIME_, 2, 1, 1, XPND2(s1, f1/100), XPND2(s1, ""), "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%.2f^BG seconds\n"), "") \
114 MULTITEAM_INFO(INFO_CTF_CAPTURE_BROKEN_, 2, 2, 2, XPND4(s1, f1/100, s2, f2/100), XPND2(s1, ""), "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%.2f^BG seconds, breaking ^BG%s^BG's previous record of ^F2%.2f^BG seconds\n"), "") \
115 MULTITEAM_INFO(INFO_CTF_CAPTURE_UNBROKEN_, 2, 2, 2, XPND4(s1, f1/100, s2, f2/100), XPND2(s1, ""), "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F2%.2f^BG seconds, failing to break ^BG%s^BG's previous record of ^F1%.2f^BG seconds\n"), "") \
116 #undef MSG_INFO_NOTIF
118 #define MULTITEAM_CENTER(prefix,teams,strnum,flnum,args,cpid,durcnt,normal,gentle) \
119 MSG_CENTER_NOTIF(prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_red, strtoupper(team_name_red)), TCR(gentle, team_color_red, strtoupper(team_name_red))) \
120 MSG_CENTER_NOTIF(prefix##BLUE, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_blue, strtoupper(team_name_blue)), TCR(gentle, team_color_blue, strtoupper(team_name_blue))) \
122 MSG_CENTER_NOTIF(prefix##YELLOW, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_yellow, strtoupper(team_name_yellow)), TCR(gentle, team_color_yellow, strtoupper(team_name_yellow))) \
125 MSG_CENTER_NOTIF(prefix##PINK, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_pink, strtoupper(team_name_pink)), TCR(gentle, team_color_pink, strtoupper(team_name_pink))) \
127 #define MSG_CENTER_NOTIFICATIONS \
128 MSG_CENTER_NOTIF(CENTER_EMPTY, 0, 0, NO_STR_ARG, NO_CPID, XPND2(0, 0), "", "") \
129 MSG_CENTER_NOTIF(CENTER_CTF_CAPTURESHIELD_SHIELDED, 0, 0, NO_STR_ARG, CPID_CTF_CAPSHIELD, XPND2(0, 0), _("^BGYou are now ^F1shielded^BG from the flag\n^BGfor ^F2too many unsuccessful attempts^BG to capture.\n^BGMake some defensive scores before trying again."), "") \
130 MSG_CENTER_NOTIF(CENTER_CTF_CAPTURESHIELD_FREE, 0, 0, NO_STR_ARG, CPID_CTF_CAPSHIELD, XPND2(0, 0), _("^BGYou are now free.\n^BGFeel free to ^F2try to capture^BG the flag again\n^BGif you think you will succeed."), "") \
131 MULTITEAM_CENTER(CENTER_CTF_PASS_OTHER_, 2, 2, 0, XPND2(s1, s2), CPID_CTF_PASS, XPND2(0, 0), _("^BG%s^BG passed the ^TC^TT^BG flag to %s"), "") \
132 MULTITEAM_CENTER(CENTER_CTF_PASS_SENT_, 2, 1, 0, s1, CPID_CTF_PASS, XPND2(0, 0), _("^BGYou passed the ^TC^TT^BG flag to %s"), "") \
133 MULTITEAM_CENTER(CENTER_CTF_PASS_RECEIVED_, 2, 1, 0, s1, CPID_CTF_PASS, XPND2(0, 0), _("^BGYou received the ^TC^TT^BG flag from %s"), "") \
134 MSG_CENTER_NOTIF(CENTER_CTF_PASS_REQUESTING, 1, 0, s1, CPID_CTF_PASS, XPND2(0, 0), _("^BGRequesting %s^BG to pass you the flag"), "") \
135 MSG_CENTER_NOTIF(CENTER_CTF_PASS_REQUESTED, 1, 0, XPND2(s1, PASS_KEY), CPID_CTF_PASS, XPND2(0, 0), _("^BG%s^BG requests you to pass the flag%s"), "") \
136 MULTITEAM_CENTER(CENTER_CTF_RETURN_, 2, 0, 0, NO_STR_ARG, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYou returned the ^TC^TT^BG flag!"), "") \
137 MULTITEAM_CENTER(CENTER_CTF_CAPTURE_, 2, 0, 0, NO_STR_ARG, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYou captured the ^TC^TT^BG flag!"), "") \
138 MULTITEAM_CENTER(CENTER_CTF_PICKUP_, 2, 0, 0, NO_STR_ARG, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYou got the ^TC^TT^BG flag!"), "") \
139 MSG_CENTER_NOTIF(CENTER_CTF_PICKUP_TEAM, 1, 0, s1, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYour %steam mate^BG got the flag! Protect them!"), "") \
140 MSG_CENTER_NOTIF(CENTER_CTF_PICKUP_TEAM_VERBOSE, 2, 0, XPND3(s1, s2, s1), CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYour %steam mate (^BG%s%s)^BG got the flag! Protect them!"), "") \
141 MSG_CENTER_NOTIF(CENTER_CTF_PICKUP_ENEMY, 1, 0, s1, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGThe %senemy^BG got your flag! Retrieve it!"), "") \
142 MSG_CENTER_NOTIF(CENTER_CTF_PICKUP_ENEMY_VERBOSE, 2, 0, XPND3(s1, s2, s1), CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGThe %senemy (^BG%s%s)^BG got your flag! Retrieve it!"), "") \
143 MSG_CENTER_NOTIF(CENTER_CTF_STALEMATE_CARRIER, 0, 0, NO_STR_ARG, CPID_STALEMATE, XPND2(0, 0), _("^BGStalemate! Enemies can now see you on radar!"), "") \
144 MSG_CENTER_NOTIF(CENTER_CTF_STALEMATE_OTHER, 0, 0, NO_STR_ARG, CPID_STALEMATE, XPND2(0, 0), _("^BGStalemate! Flag carriers can now be seen by enemies on radar!"), "") \
145 MSG_CENTER_NOTIF(CENTER_CTF_FLAG_THROW_PUNISH, 0, 1, f1, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGToo many flag throws! Throwing disabled for %d seconds."), "") \
146 #undef MSG_CENTER_NOTIF
148 #define MSG_WEAPON_NOTIFICATIONS \
149 MSG_WEAPON_NOTIF(DEATH_MARBLES_LOST3, 2, 1, XPND3(s1, s2, f1), _("^F1%s^BG lost their marbles against ^F1%s^BG using the ^F2%s^BG\n"), "") \
150 #undef MSG_WEAPON_NOTIF
153 // ====================================
154 // Initialization/Create Declarations
155 // ====================================
157 #define NOTIF_FIRST 1
158 #define NOTIF_MAX 1024 // limit of recursive functions with ACCUMULATE_FUNCTION
159 float NOTIF_INFO_COUNT;
160 float NOTIF_CENTER_COUNT;
161 float NOTIF_WEAPON_COUNT;
162 float NOTIF_CPID_COUNT;
164 #define MSG_INFO_NOTIF(name,strnum,flnum,args,icon,normal,gentle) \
165 ADD_CSQC_AUTOCVAR(name) \
167 void RegisterNotification_##name() \
169 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
170 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_INFO_COUNT, "notifications") \
172 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
174 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
175 ADD_CSQC_AUTOCVAR(name) \
178 void RegisterNotification_##name() \
180 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CENTER_COUNT) \
181 SET_FIELD_COUNT(cpid, NOTIF_FIRST, NOTIF_CPID_COUNT) \
182 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_CENTER_COUNT, "notifications") \
184 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
186 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
187 ADD_CSQC_AUTOCVAR(name) \
189 void RegisterNotification_##name() \
191 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_WEAPON_COUNT) \
192 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_WEAPON_COUNT, "notifications") \
194 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
196 // NOW we actually activate the declarations
197 MSG_INFO_NOTIFICATIONS
198 MSG_CENTER_NOTIFICATIONS
199 MSG_WEAPON_NOTIFICATIONS
202 // ======================
203 // Supporting Functions
204 // ======================
206 // select between the normal or the gentle message string based on client (or server) settings
207 string normal_or_gentle(string normal, string gentle)
210 if(autocvar_cl_gentle || autocvar_cl_gentle_messages)
212 if(autocvar_sv_gentle)
214 return ((gentle != "") ? gentle : normal);
219 float notif_stringcount(string s1, string s2)
222 if(s1 != NO_STR_ARG) ++stringcount;
223 if(s2 != NO_STR_ARG) ++stringcount;
227 float notif_floatcount(float f1, float f2, float f3)
230 if(f1 != NO_FL_ARG) ++floatcount;
231 if(f2 != NO_FL_ARG) ++floatcount;
232 if(f3 != NO_FL_ARG) ++floatcount;
236 // get the actual name of a notification and return it as a string
237 string Get_Field_Value(float field, float net_type, float net_name)
241 #define GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) \
242 if(field == F_NAME) { output = VAR_TO_TEXT(name); } \
243 else if(field == F_STRNUM) { output = ftos(strnum); } \
244 else if(field == F_FLNUM) { output = ftos(flnum); }
250 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
251 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
252 MSG_INFO_NOTIFICATIONS
257 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
258 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
259 MSG_CENTER_NOTIFICATIONS
264 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
265 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
266 MSG_WEAPON_NOTIFICATIONS
271 #undef GET_FIELD_VALUE_OUTPUT
276 string TCR(string input, string teamcolor, string teamtext)
278 input = strreplace("^TC", teamcolor, input);
279 input = strreplace("^TT", teamtext, input);
283 // color code replace, place inside of sprintf and parse the string
284 string CCR(string input)
286 input = strreplace("^F1", "^2", input); // autocvar_notification_colors_F1
287 input = strreplace("^F2", "^3", input); // autocvar_notification_colors_F2
288 input = strreplace("^K1", "^1", input); // autocvar_notification_colors_K1
289 input = strreplace("^K2", "^3", input); // autocvar_notification_colors_K2
290 input = strreplace("^BG", "^7", input); // autocvar_notification_colors_BG
291 input = strreplace("^N", "^7", input); // "none"-- reset to white
296 // ===============================
297 // Frontend Notification Pushing
298 // ===============================
301 #define KN_MAX_ENTRIES 10
303 float killnotify_times[KN_MAX_ENTRIES];
304 string killnotify_icon[KN_MAX_ENTRIES];
305 string killnotify_attackers[KN_MAX_ENTRIES];
306 string killnotify_victims[KN_MAX_ENTRIES];
307 // 0 = "Y [used by] X", 1 = "X [did action to] Y"
308 void HUD_Notify_Push(string icon, string attacker, string victim)
313 if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
314 killnotify_times[kn_index] = time;
317 if(killnotify_icon[kn_index]) { strunzone(killnotify_icon[kn_index]); }
318 killnotify_icon[kn_index] = strzone(icon);
321 if(killnotify_attackers[kn_index]) { strunzone(killnotify_attackers[kn_index]); }
322 killnotify_attackers[kn_index] = strzone(attacker);
325 if(killnotify_victims[kn_index]) { strunzone(killnotify_victims[kn_index]); }
326 killnotify_victims[kn_index] = strzone(victim);
330 void Local_Notification(float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
336 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
337 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); if(strtolower(icon) != "") { HUD_Notify_Push(icon, hudargs); } } }
338 MSG_INFO_NOTIFICATIONS
343 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
344 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) { centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); } }
345 MSG_CENTER_NOTIFICATIONS
350 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
351 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) { print("unhandled\n"); } }
352 MSG_WEAPON_NOTIFICATIONS
360 // =========================
361 // Notification Networking
362 // =========================
365 void Read_Notification(void)
367 float net_type = ReadByte();
368 float net_name = ReadShort();
370 float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
371 float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
373 Local_Notification(net_type, net_name,
374 ((stringcount >= 1) ? ReadString() : ""),
375 ((stringcount == 2) ? ReadString() : ""),
376 ((floatcount >= 1) ? ReadLong() : 0),
377 ((floatcount >= 2) ? ReadLong() : 0),
378 ((floatcount == 3) ? ReadLong() : 0));
383 void Send_Notification(entity client, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
385 if(net_type && net_name)
387 //print("notification: ", Get_Field_Value(F_NAME, net_type, net_name), ": ", ftos(net_name), ".\n");
389 float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
390 float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
392 if(notif_stringcount(s1, s2) > stringcount) { backtrace("Too many string arguments for notification!\n"); return; }
393 if(notif_floatcount(f1, f2, f3) > floatcount) { backtrace("Too many float arguments for notification!\n"); return; }
395 if(client && (clienttype(client) == CLIENTTYPE_REAL) && (client.flags & FL_CLIENT))
397 // personal/direct notification sent to ONE person and their spectators
399 WRITESPECTATABLE_MSG_ONE({
400 WriteByte(MSG_ONE, SVC_TEMPENTITY);
401 WriteByte(MSG_ONE, TE_CSQC_NOTIFICATION);
402 WriteByte(MSG_ONE, net_type);
403 WriteShort(MSG_ONE, net_name);
404 if(stringcount >= 1) { WriteString(MSG_ONE, s1); }
405 if(stringcount == 2) { WriteString(MSG_ONE, s2); }
406 if(floatcount >= 1) { WriteLong(MSG_ONE, f1); }
407 if(floatcount >= 2) { WriteLong(MSG_ONE, f2); }
408 if(floatcount == 3) { WriteLong(MSG_ONE, f3); }
413 // global notification sent to EVERYONE
414 WriteByte(MSG_ALL, SVC_TEMPENTITY);
415 WriteByte(MSG_ALL, TE_CSQC_NOTIFICATION);
416 WriteByte(MSG_ALL, net_type);
417 WriteShort(MSG_ALL, net_name);
418 if(stringcount >= 1) { WriteString(MSG_ALL, s1); }
419 if(stringcount == 2) { WriteString(MSG_ALL, s2); }
420 if(floatcount >= 1) { WriteLong(MSG_ALL, f1); }
421 if(floatcount >= 2) { WriteLong(MSG_ALL, f2); }
422 if(floatcount == 3) { WriteLong(MSG_ALL, f3); }
425 if(!server_is_local && (net_type == MSG_INFO))
427 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
428 { NOTIF_MATCH(name, net_name) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); } }
429 MSG_INFO_NOTIFICATIONS
432 else { backtrace("Incorrect usage of Send_Notification!\n"); }
435 void Send_Notification_ToTeam(float targetteam, entity except, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
438 FOR_EACH_REALCLIENT(tmp_entity)
440 if(tmp_entity.classname == STR_PLAYER)
441 if(tmp_entity.team == targetteam)
442 if(tmp_entity != except)
444 Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
449 // WARNING: use this ONLY if you need exceptions or want to exclude spectators, otherwise use Send_Notification(..., world, ...)
450 void Send_Notification_ToAll(entity except, float spectators, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
453 FOR_EACH_REALCLIENT(tmp_entity)
455 if((tmp_entity.classname == STR_PLAYER) || spectators)
456 if(tmp_entity != except)
458 Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
464 // =============================
465 // LEGACY NOTIFICATION SYSTEMS
466 // =============================
468 void Send_KillNotification(string s1, string s2, string s3, float msg, float type)
470 WriteByte(MSG_ALL, SVC_TEMPENTITY);
471 WriteByte(MSG_ALL, TE_CSQC_KILLNOTIFY);
472 WriteString(MSG_ALL, s1);
473 WriteString(MSG_ALL, s2);
474 WriteString(MSG_ALL, s3);
475 WriteShort(MSG_ALL, msg);
476 WriteByte(MSG_ALL, type);
479 // Function is used to send a generic centerprint whose content CSQC gets to decide (gentle version or not in the below cases)
480 void Send_CSQC_KillCenterprint(entity e, string s1, string s2, float msg, float type)
482 if (clienttype(e) == CLIENTTYPE_REAL)
485 WRITESPECTATABLE_MSG_ONE({
486 WriteByte(MSG_ONE, SVC_TEMPENTITY);
487 WriteByte(MSG_ONE, TE_CSQC_KILLCENTERPRINT);
488 WriteString(MSG_ONE, s1);
489 WriteString(MSG_ONE, s2);
490 WriteShort(MSG_ONE, msg);
491 WriteByte(MSG_ONE, type);
496 void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
498 if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
501 WRITESPECTATABLE_MSG_ONE({
502 WriteByte(MSG_ONE, SVC_TEMPENTITY);
503 WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
504 WriteByte(MSG_ONE, id);
505 WriteString(MSG_ONE, s);
506 if (id != 0 && s != "")
508 WriteByte(MSG_ONE, duration);
509 WriteByte(MSG_ONE, countdown_num);
514 void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
516 Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);