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 MSG_CENTER_NOTIF(CENTER_EMPTY, 0, 0, NO_STR_ARG, NO_CPID, XPND2(0, 0), "", "") \
138 #undef MSG_CENTER_NOTIF
140 #define MSG_WEAPON_NOTIFICATIONS \
141 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"), "") \
142 #undef MSG_WEAPON_NOTIF
145 // ====================================
146 // Initialization/Create Declarations
147 // ====================================
149 #define NOTIF_FIRST 1
150 #define NOTIF_MAX 1024 // limit of recursive functions with ACCUMULATE_FUNCTION
151 float NOTIF_INFO_COUNT;
152 float NOTIF_CENTER_COUNT;
153 float NOTIF_WEAPON_COUNT;
154 float NOTIF_CPID_COUNT;
156 #define MSG_INFO_NOTIF(name,strnum,flnum,args,icon,normal,gentle) \
157 ADD_CSQC_AUTOCVAR(name) \
159 void RegisterNotification_##name() \
161 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
162 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_INFO_COUNT, "notifications") \
164 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
166 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
167 ADD_CSQC_AUTOCVAR(name) \
170 void RegisterNotification_##name() \
172 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CENTER_COUNT) \
173 SET_FIELD_COUNT(cpid, NOTIF_FIRST, NOTIF_CPID_COUNT) \
174 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_CENTER_COUNT, "notifications") \
176 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
178 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
179 ADD_CSQC_AUTOCVAR(name) \
181 void RegisterNotification_##name() \
183 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_WEAPON_COUNT) \
184 CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_WEAPON_COUNT, "notifications") \
186 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
188 // NOW we actually activate the declarations
189 MSG_INFO_NOTIFICATIONS
190 MSG_CENTER_NOTIFICATIONS
191 MSG_WEAPON_NOTIFICATIONS
194 // ======================
195 // Supporting Functions
196 // ======================
198 // select between the normal or the gentle message string based on client (or server) settings
199 string normal_or_gentle(string normal, string gentle)
203 if(autocvar_cl_gentle || autocvar_cl_gentle_messages)
205 if(autocvar_sv_gentle)
207 return ((gentle != "") ? gentle : normal);
215 float notif_stringcount(string s1, string s2)
218 if(s1 != NO_STR_ARG) ++stringcount;
219 if(s2 != NO_STR_ARG) ++stringcount;
223 float notif_floatcount(float f1, float f2, float f3)
226 if(f1 != NO_FL_ARG) ++floatcount;
227 if(f2 != NO_FL_ARG) ++floatcount;
228 if(f3 != NO_FL_ARG) ++floatcount;
232 // get the actual name of a notification and return it as a string
233 string Get_Field_Value(float field, float net_type, float net_name)
237 #define GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) \
238 if(field == F_NAME) { output = VAR_TO_TEXT(name); } \
239 else if(field == F_STRNUM) { output = ftos(strnum); } \
240 else if(field == F_FLNUM) { output = ftos(flnum); }
246 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
247 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
248 MSG_INFO_NOTIFICATIONS
253 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
254 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
255 MSG_CENTER_NOTIFICATIONS
260 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
261 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
262 MSG_WEAPON_NOTIFICATIONS
267 #undef GET_FIELD_VALUE_OUTPUT
272 string TCR(string input, string teamcolor, string teamtext)
274 input = strreplace("^TC", teamcolor, input);
275 input = strreplace("^TT", teamtext, input);
279 // color code replace, place inside of sprintf and parse the string
280 string CCR(string input)
282 input = strreplace("^F1", "^2", input); // autocvar_notification_colors_F1
283 input = strreplace("^F2", "^3", input); // autocvar_notification_colors_F2
284 input = strreplace("^K1", "^1", input); // autocvar_notification_colors_K1
285 input = strreplace("^K2", "^3", input); // autocvar_notification_colors_K2
286 input = strreplace("^BG", "^7", input); // autocvar_notification_colors_BG
287 input = strreplace("^N", "^7", input); // "none"-- reset to white
292 // =============================
293 // Debug/Maintenance Functions
294 // =============================
296 #define NOTIF_Write(type,name,text) fputs(fh, (sprintf("seta %s 1 // %s - %s\n", name, type, strreplace("\n", "\\n", text))))
297 void Dump_Notifications(float fh)
299 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) { NOTIF_Write("MSG_INFO", VAR_TO_TEXT(name), normal); }
300 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) { NOTIF_Write("MSG_CENTER", VAR_TO_TEXT(name), normal); }
301 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) { NOTIF_Write("MSG_WEAPON", VAR_TO_TEXT(name), normal); }
302 MSG_INFO_NOTIFICATIONS
303 MSG_CENTER_NOTIFICATIONS
304 MSG_WEAPON_NOTIFICATIONS
309 // ===============================
310 // Frontend Notification Pushing
311 // ===============================
314 #define KN_MAX_ENTRIES 10
316 float killnotify_times[KN_MAX_ENTRIES];
317 string killnotify_icon[KN_MAX_ENTRIES];
318 string killnotify_attackers[KN_MAX_ENTRIES];
319 string killnotify_victims[KN_MAX_ENTRIES];
320 // 0 = "Y [used by] X", 1 = "X [did action to] Y"
321 void HUD_Notify_Push(string icon, string attacker, string victim)
326 if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
327 killnotify_times[kn_index] = time;
330 if(killnotify_icon[kn_index]) { strunzone(killnotify_icon[kn_index]); }
331 killnotify_icon[kn_index] = strzone(icon);
334 if(killnotify_attackers[kn_index]) { strunzone(killnotify_attackers[kn_index]); }
335 killnotify_attackers[kn_index] = strzone(attacker);
338 if(killnotify_victims[kn_index]) { strunzone(killnotify_victims[kn_index]); }
339 killnotify_victims[kn_index] = strzone(victim);
343 void Local_Notification(float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
349 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
350 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
352 print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); \
353 if(strtolower(icon) != "") { HUD_Notify_Push(icon, hudargs); } \
355 MSG_INFO_NOTIFICATIONS
360 #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
361 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
363 centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); \
365 MSG_CENTER_NOTIFICATIONS
370 #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
371 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
373 print("unhandled\n"); \
375 MSG_WEAPON_NOTIFICATIONS
383 // =========================
384 // Notification Networking
385 // =========================
388 void Read_Notification(void)
390 float net_type = ReadByte();
391 float net_name = ReadShort();
393 float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
394 float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
396 Local_Notification(net_type, net_name,
397 ((stringcount >= 1) ? ReadString() : ""),
398 ((stringcount == 2) ? ReadString() : ""),
399 ((floatcount >= 1) ? ReadLong() : 0),
400 ((floatcount >= 2) ? ReadLong() : 0),
401 ((floatcount == 3) ? ReadLong() : 0));
406 void Send_Notification(entity client, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
408 if(net_type && net_name)
410 //print("notification: ", Get_Field_Value(F_NAME, net_type, net_name), ": ", ftos(net_name), ".\n");
412 float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
413 float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
415 if(notif_stringcount(s1, s2) > stringcount) { backtrace("Too many string arguments for notification!\n"); return; }
416 if(notif_floatcount(f1, f2, f3) > floatcount) { backtrace("Too many float arguments for notification!\n"); return; }
418 if(client && (clienttype(client) == CLIENTTYPE_REAL) && (client.flags & FL_CLIENT))
420 // personal/direct notification sent to ONE person and their spectators
422 WRITESPECTATABLE_MSG_ONE({
423 WriteByte(MSG_ONE, SVC_TEMPENTITY);
424 WriteByte(MSG_ONE, TE_CSQC_NOTIFICATION);
425 WriteByte(MSG_ONE, net_type);
426 WriteShort(MSG_ONE, net_name);
427 if(stringcount >= 1) { WriteString(MSG_ONE, s1); }
428 if(stringcount == 2) { WriteString(MSG_ONE, s2); }
429 if(floatcount >= 1) { WriteLong(MSG_ONE, f1); }
430 if(floatcount >= 2) { WriteLong(MSG_ONE, f2); }
431 if(floatcount == 3) { WriteLong(MSG_ONE, f3); }
436 // global notification sent to EVERYONE
437 WriteByte(MSG_ALL, SVC_TEMPENTITY);
438 WriteByte(MSG_ALL, TE_CSQC_NOTIFICATION);
439 WriteByte(MSG_ALL, net_type);
440 WriteShort(MSG_ALL, net_name);
441 if(stringcount >= 1) { WriteString(MSG_ALL, s1); }
442 if(stringcount == 2) { WriteString(MSG_ALL, s2); }
443 if(floatcount >= 1) { WriteLong(MSG_ALL, f1); }
444 if(floatcount >= 2) { WriteLong(MSG_ALL, f2); }
445 if(floatcount == 3) { WriteLong(MSG_ALL, f3); }
448 if(!server_is_local && (net_type == MSG_INFO))
450 #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
451 { NOTIF_MATCH(name, net_name) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); } }
452 MSG_INFO_NOTIFICATIONS
455 else { backtrace("Incorrect usage of Send_Notification!\n"); }
458 void Send_Notification_ToTeam(float targetteam, entity except, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
461 FOR_EACH_REALCLIENT(tmp_entity)
463 if(tmp_entity.classname == STR_PLAYER)
464 if(tmp_entity.team == targetteam)
465 if(tmp_entity != except)
467 Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
472 // WARNING: use this ONLY if you need exceptions or want to exclude spectators, otherwise use Send_Notification(..., world, ...)
473 void Send_Notification_ToAll(entity except, float spectators, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
476 FOR_EACH_REALCLIENT(tmp_entity)
478 if((tmp_entity.classname == STR_PLAYER) || spectators)
479 if(tmp_entity != except)
481 Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
487 // =============================
488 // LEGACY NOTIFICATION SYSTEMS
489 // =============================
491 void Send_KillNotification(string s1, string s2, string s3, float msg, float type)
493 WriteByte(MSG_ALL, SVC_TEMPENTITY);
494 WriteByte(MSG_ALL, TE_CSQC_KILLNOTIFY);
495 WriteString(MSG_ALL, s1);
496 WriteString(MSG_ALL, s2);
497 WriteString(MSG_ALL, s3);
498 WriteShort(MSG_ALL, msg);
499 WriteByte(MSG_ALL, type);
502 // Function is used to send a generic centerprint whose content CSQC gets to decide (gentle version or not in the below cases)
503 void Send_CSQC_KillCenterprint(entity e, string s1, string s2, float msg, float type)
505 if (clienttype(e) == CLIENTTYPE_REAL)
508 WRITESPECTATABLE_MSG_ONE({
509 WriteByte(MSG_ONE, SVC_TEMPENTITY);
510 WriteByte(MSG_ONE, TE_CSQC_KILLCENTERPRINT);
511 WriteString(MSG_ONE, s1);
512 WriteString(MSG_ONE, s2);
513 WriteShort(MSG_ONE, msg);
514 WriteByte(MSG_ONE, type);
519 void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
521 if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
524 WRITESPECTATABLE_MSG_ONE({
525 WriteByte(MSG_ONE, SVC_TEMPENTITY);
526 WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
527 WriteByte(MSG_ONE, id);
528 WriteString(MSG_ONE, s);
529 if (id != 0 && s != "")
531 WriteByte(MSG_ONE, duration);
532 WriteByte(MSG_ONE, countdown_num);
537 void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
539 Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);