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)
40 // ====================================
41 // Notifications List and Information
42 // ====================================
44 List of all notifications (including identifiers and display information)
45 Format: name, strnum, flnum, args, *icon/CPID, *durcnt, normal, gentle
46 Asterisked fields are not present in all notification types.
49 Number of STRING arguments (so that networking knows how many to send/receive)
50 Number of FLOAT arguments (so that networking knows how many to send/receive)
51 Arguments for sprintf(string, args), if no args needed then use ""
53 MSG_INFO: STRING: icon string name for the hud notify panel, "" if no icon is used
54 MSG_CENTER: FLOAT: centerprint ID number (CPID_*), NO_CPID if no CPID is needed
56 MSG_CENTER: XPND2(FLOAT, FLOAT): extra arguments for centerprint messages
57 Normal message (string for sprintf when gentle messages are NOT enabled)
58 Gentle message (string for sprintf when gentle messages ARE enabled)
60 Messages have ^F1, ^F2, and ^BG in them-- these are replaced
61 with colors according to the cvars the user has chosen.
62 ^F1 = highest priority, "primary"
63 ^F2 = next highest priority, "secondary"
64 ^BG = normal/less important priority, "tertiary"
66 Guidlines (please try and follow these):
67 -ALWAYS start the string with a color, preferably background.
68 -ALWAYS reset a color after a name (this way they don't set it for the whole string).
69 -NEVER re-declare an event twice.
70 -NEVER add or remove fields from the format, it SHOULD already work.
71 -MSG_INFO messages must ALWAYS end with a new line: \n
72 -Be clean and simple with your notification naming,
73 nothing too long for the name field... Abbreviations are your friend. :D
74 -Keep the spacing as clean as possible... if the arguments are abnormally long,
75 it's okay to go out of line a bit... but try and keep it clean still.
76 -Keep the notifications in alphabetical order.
77 ARIRE unir frk jvgu lbhe bja zbgure. (gvc sbe zvxrrhfn) -- Don't pay attention to this ^_^
80 // weaponorder[f1].netname
82 #define MULTITEAM_INFO(prefix,teams,strnum,flnum,args,hudargs,icon,normal,gentle) \
83 MSG_INFO_NOTIF(prefix##RED, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_1)), TCR(normal, COL_TEAM_1, strtoupper(STR_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(STR_TEAM_1))) \
84 MSG_INFO_NOTIF(prefix##BLUE, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_2)), TCR(normal, COL_TEAM_2, strtoupper(STR_TEAM_2)), TCR(gentle, COL_TEAM_2, strtoupper(STR_TEAM_2))) \
86 MSG_INFO_NOTIF(prefix##YELLOW, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_3)), TCR(normal, COL_TEAM_3, strtoupper(STR_TEAM_3)), TCR(gentle, COL_TEAM_3, strtoupper(STR_TEAM_3))) \
89 MSG_INFO_NOTIF(prefix##PINK, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_4)), TCR(normal, COL_TEAM_4, strtoupper(STR_TEAM_4)), TCR(gentle, COL_TEAM_4, strtoupper(STR_TEAM_4))) \
91 #define MSG_INFO_NOTIFICATIONS \
92 MSG_INFO_NOTIF(INFO_EMPTY, 0, 0, NO_STR_ARG, XPND2("", ""), "", "", "") \
93 MULTITEAM_INFO(INFO_SCORES_, 4, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^TC^TT ^BGteam scores!\n"), "") \
94 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"), "") \
95 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"), "") \
96 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"), "") \
97 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"), "") \
98 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"), "") \
99 MULTITEAM_INFO(INFO_CTF_FLAGRETURN_TIMEOUT_, 2, 0, 0, NO_STR_ARG, XPND2("", ""), "", _("^BGThe ^TC^TT^BG flag has returned to the base\n"), "") \
100 MULTITEAM_INFO(INFO_CTF_PICKUP_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_taken", _("^BG%s^BG got the ^TC^TT^BG flag\n"), "") \
101 MULTITEAM_INFO(INFO_CTF_RETURN_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_returned", _("^BG%s^BG returned the ^TC^TT^BG flag\n"), "") \
102 MULTITEAM_INFO(INFO_CTF_LOST_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_lost", _("^BG%s^BG lost the ^TC^TT^BG flag\n"), "") \
103 MULTITEAM_INFO(INFO_CTF_CAPTURE_, 2, 1, 0, s1, XPND2(s1, ""), "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag\n"), "") \
104 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"), "") \
105 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"), "") \
106 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"), "") \
107 #undef MSG_INFO_NOTIF
109 #define MULTITEAM_CENTER(prefix,teams,strnum,flnum,args,cpid,durcnt,normal,gentle) \
110 MSG_CENTER_NOTIF(prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_1, strtoupper(STR_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(STR_TEAM_1))) \
111 MSG_CENTER_NOTIF(prefix##BLUE, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_2, strtoupper(STR_TEAM_2)), TCR(gentle, COL_TEAM_2, strtoupper(STR_TEAM_2))) \
113 MSG_CENTER_NOTIF(prefix##YELLOW, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_3, strtoupper(STR_TEAM_3)), TCR(gentle, COL_TEAM_3, strtoupper(STR_TEAM_3))) \
116 MSG_CENTER_NOTIF(prefix##PINK, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_4, strtoupper(STR_TEAM_4)), TCR(gentle, COL_TEAM_4, strtoupper(STR_TEAM_4))) \
118 #define MSG_CENTER_NOTIFICATIONS \
119 MSG_CENTER_NOTIF(CENTER_EMPTY, 0, 0, NO_STR_ARG, NO_CPID, XPND2(0, 0), "", "") \
120 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."), "") \
121 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."), "") \
122 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"), "") \
123 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"), "") \
124 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"), "") \
125 MSG_CENTER_NOTIF(CENTER_CTF_PASS_REQUESTING, 1, 0, s1, CPID_CTF_PASS, XPND2(0, 0), _("^BGRequesting %s^BG to pass you the flag"), "") \
126 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"), "") \
127 MULTITEAM_CENTER(CENTER_CTF_RETURN_, 2, 0, 0, NO_STR_ARG, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYou returned the ^TC^TT^BG flag!"), "") \
128 MULTITEAM_CENTER(CENTER_CTF_CAPTURE_, 2, 0, 0, NO_STR_ARG, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYou captured the ^TC^TT^BG flag!"), "") \
129 MULTITEAM_CENTER(CENTER_CTF_PICKUP_, 2, 0, 0, NO_STR_ARG, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGYou got the ^TC^TT^BG flag!"), "") \
130 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!"), "") \
131 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!"), "") \
132 MSG_CENTER_NOTIF(CENTER_CTF_PICKUP_ENEMY, 1, 0, s1, CPID_CTF_LOWPRIO, XPND2(0, 0), _("^BGThe %senemy^BG got your flag! Retrieve it!"), "") \
133 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!"), "") \
134 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!"), "") \
135 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!"), "") \
136 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."), "") \
137 #undef MSG_CENTER_NOTIF
139 #define MSG_WEAPON_NOTIFICATIONS \
140 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"), "") \
141 #undef MSG_WEAPON_NOTIF
144 // ====================================
145 // Initialization/Create Declarations
146 // ====================================
148 #define NOTIF_FIRST 1
149 #define NOTIF_MAX 1024 // limit of recursive functions with ACCUMULATE_FUNCTION
150 float NOTIF_INFO_COUNT;
151 float NOTIF_CENTER_COUNT;
152 float NOTIF_WEAPON_COUNT;
153 float NOTIF_CPID_COUNT;
155 #define MSG_INFO_NOTIF(name,strnum,flnum,args,icon,normal,gentle) \
156 ADD_CSQC_AUTOCVAR(name) \
158 void RegisterNotification_##name() \
160 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
161 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_INFO_COUNT, "notifications") \
163 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
165 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
166 ADD_CSQC_AUTOCVAR(name) \
169 void RegisterNotification_##name() \
171 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CENTER_COUNT) \
172 SET_FIELD_COUNT(cpid, NOTIF_FIRST, NOTIF_CPID_COUNT) \
173 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_CENTER_COUNT, "notifications") \
175 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
177 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
178 ADD_CSQC_AUTOCVAR(name) \
180 void RegisterNotification_##name() \
182 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_WEAPON_COUNT) \
183 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_WEAPON_COUNT, "notifications") \
185 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
187 // NOW we actually activate the declarations
188 MSG_INFO_NOTIFICATIONS
189 MSG_CENTER_NOTIFICATIONS
190 MSG_WEAPON_NOTIFICATIONS
193 // ======================
194 // Supporting Functions
195 // ======================
197 // select between the normal or the gentle message string based on client (or server) settings
198 string normal_or_gentle(string normal, string gentle)
201 if(autocvar_cl_gentle || autocvar_cl_gentle_messages)
203 if(autocvar_sv_gentle)
205 return ((gentle != "") ? gentle : normal);
210 float notif_stringcount(string s1, string s2)
213 if(s1 != NO_STR_ARG) ++stringcount;
214 if(s2 != NO_STR_ARG) ++stringcount;
218 float notif_floatcount(float f1, float f2, float f3)
221 if(f1 != NO_FL_ARG) ++floatcount;
222 if(f2 != NO_FL_ARG) ++floatcount;
223 if(f3 != NO_FL_ARG) ++floatcount;
227 // get the actual name of a notification and return it as a string
228 string Get_Field_Value(float field, float net_type, float net_name)
232 #define GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) \
233 if(field == F_NAME) { output = VAR_TO_TEXT(name); } \
234 else if(field == F_STRNUM) { output = ftos(strnum); } \
235 else if(field == F_FLNUM) { output = ftos(flnum); }
241 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
242 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
243 MSG_INFO_NOTIFICATIONS
248 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
249 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
250 MSG_CENTER_NOTIFICATIONS
255 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
256 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
257 MSG_WEAPON_NOTIFICATIONS
262 #undef GET_FIELD_VALUE_OUTPUT
267 string TCR(string input, string teamcolor, string teamtext)
269 input = strreplace("^TC", teamcolor, input);
270 input = strreplace("^TT", teamtext, input);
274 // color code replace, place inside of sprintf and parse the string
275 string CCR(string input)
277 input = strreplace("^F1", "^2", input); // autocvar_notification_colors_F1
278 input = strreplace("^F2", "^3", input); // autocvar_notification_colors_F2
279 input = strreplace("^K1", "^1", input); // autocvar_notification_colors_K1
280 input = strreplace("^K2", "^3", input); // autocvar_notification_colors_K2
281 input = strreplace("^BG", "^7", input); // autocvar_notification_colors_BG
282 input = strreplace("^N", "^7", input); // "none"-- reset to white
287 // ===============================
288 // Frontend Notification Pushing
289 // ===============================
292 #define KN_MAX_ENTRIES 10
294 float killnotify_times[KN_MAX_ENTRIES];
295 string killnotify_icon[KN_MAX_ENTRIES];
296 string killnotify_attackers[KN_MAX_ENTRIES];
297 string killnotify_victims[KN_MAX_ENTRIES];
298 // 0 = "Y [used by] X", 1 = "X [did action to] Y"
299 void HUD_Notify_Push(string icon, string attacker, string victim)
304 if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
305 killnotify_times[kn_index] = time;
308 if(killnotify_icon[kn_index]) { strunzone(killnotify_icon[kn_index]); }
309 killnotify_icon[kn_index] = strzone(icon);
312 if(killnotify_attackers[kn_index]) { strunzone(killnotify_attackers[kn_index]); }
313 killnotify_attackers[kn_index] = strzone(attacker);
316 if(killnotify_victims[kn_index]) { strunzone(killnotify_victims[kn_index]); }
317 killnotify_victims[kn_index] = strzone(victim);
321 void Local_Notification(float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
327 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
328 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
330 print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); \
331 if(strtolower(icon) != "") { HUD_Notify_Push(icon, hudargs); } \
333 MSG_INFO_NOTIFICATIONS
338 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
339 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
341 centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); \
343 MSG_CENTER_NOTIFICATIONS
348 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
349 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
351 print("unhandled\n"); \
353 MSG_WEAPON_NOTIFICATIONS
361 // =========================
362 // Notification Networking
363 // =========================
366 void Read_Notification(void)
368 float net_type = ReadByte();
369 float net_name = ReadShort();
371 float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
372 float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
374 Local_Notification(net_type, net_name,
375 ((stringcount >= 1) ? ReadString() : ""),
376 ((stringcount == 2) ? ReadString() : ""),
377 ((floatcount >= 1) ? ReadLong() : 0),
378 ((floatcount >= 2) ? ReadLong() : 0),
379 ((floatcount == 3) ? ReadLong() : 0));
384 void Send_Notification(entity client, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
386 if(net_type && net_name)
388 //print("notification: ", Get_Field_Value(F_NAME, net_type, net_name), ": ", ftos(net_name), ".\n");
390 float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
391 float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
393 if(notif_stringcount(s1, s2) > stringcount) { backtrace("Too many string arguments for notification!\n"); return; }
394 if(notif_floatcount(f1, f2, f3) > floatcount) { backtrace("Too many float arguments for notification!\n"); return; }
396 if(client && (clienttype(client) == CLIENTTYPE_REAL) && (client.flags & FL_CLIENT))
398 // personal/direct notification sent to ONE person and their spectators
400 WRITESPECTATABLE_MSG_ONE({
401 WriteByte(MSG_ONE, SVC_TEMPENTITY);
402 WriteByte(MSG_ONE, TE_CSQC_NOTIFICATION);
403 WriteByte(MSG_ONE, net_type);
404 WriteShort(MSG_ONE, net_name);
405 if(stringcount >= 1) { WriteString(MSG_ONE, s1); }
406 if(stringcount == 2) { WriteString(MSG_ONE, s2); }
407 if(floatcount >= 1) { WriteLong(MSG_ONE, f1); }
408 if(floatcount >= 2) { WriteLong(MSG_ONE, f2); }
409 if(floatcount == 3) { WriteLong(MSG_ONE, f3); }
414 // global notification sent to EVERYONE
415 WriteByte(MSG_ALL, SVC_TEMPENTITY);
416 WriteByte(MSG_ALL, TE_CSQC_NOTIFICATION);
417 WriteByte(MSG_ALL, net_type);
418 WriteShort(MSG_ALL, net_name);
419 if(stringcount >= 1) { WriteString(MSG_ALL, s1); }
420 if(stringcount == 2) { WriteString(MSG_ALL, s2); }
421 if(floatcount >= 1) { WriteLong(MSG_ALL, f1); }
422 if(floatcount >= 2) { WriteLong(MSG_ALL, f2); }
423 if(floatcount == 3) { WriteLong(MSG_ALL, f3); }
426 if(!server_is_local && (net_type == MSG_INFO))
428 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
429 { NOTIF_MATCH(name, net_name) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); } }
430 MSG_INFO_NOTIFICATIONS
433 else { backtrace("Incorrect usage of Send_Notification!\n"); }
436 void Send_Notification_ToTeam(float targetteam, entity except, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
439 FOR_EACH_REALCLIENT(tmp_entity)
441 if(tmp_entity.classname == STR_PLAYER)
442 if(tmp_entity.team == targetteam)
443 if(tmp_entity != except)
445 Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
450 // WARNING: use this ONLY if you need exceptions or want to exclude spectators, otherwise use Send_Notification(..., world, ...)
451 void Send_Notification_ToAll(entity except, float spectators, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
454 FOR_EACH_REALCLIENT(tmp_entity)
456 if((tmp_entity.classname == STR_PLAYER) || spectators)
457 if(tmp_entity != except)
459 Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
465 // =============================
466 // LEGACY NOTIFICATION SYSTEMS
467 // =============================
469 void Send_KillNotification(string s1, string s2, string s3, float msg, float type)
471 WriteByte(MSG_ALL, SVC_TEMPENTITY);
472 WriteByte(MSG_ALL, TE_CSQC_KILLNOTIFY);
473 WriteString(MSG_ALL, s1);
474 WriteString(MSG_ALL, s2);
475 WriteString(MSG_ALL, s3);
476 WriteShort(MSG_ALL, msg);
477 WriteByte(MSG_ALL, type);
480 // Function is used to send a generic centerprint whose content CSQC gets to decide (gentle version or not in the below cases)
481 void Send_CSQC_KillCenterprint(entity e, string s1, string s2, float msg, float type)
483 if (clienttype(e) == CLIENTTYPE_REAL)
486 WRITESPECTATABLE_MSG_ONE({
487 WriteByte(MSG_ONE, SVC_TEMPENTITY);
488 WriteByte(MSG_ONE, TE_CSQC_KILLCENTERPRINT);
489 WriteString(MSG_ONE, s1);
490 WriteString(MSG_ONE, s2);
491 WriteShort(MSG_ONE, msg);
492 WriteByte(MSG_ONE, type);
497 void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
499 if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
502 WRITESPECTATABLE_MSG_ONE({
503 WriteByte(MSG_ONE, SVC_TEMPENTITY);
504 WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
505 WriteByte(MSG_ONE, id);
506 WriteString(MSG_ONE, s);
507 if (id != 0 && s != "")
509 WriteByte(MSG_ONE, duration);
510 WriteByte(MSG_ONE, countdown_num);
515 void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
517 Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);