]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/notifications.qc
Clean up a ton of code, plus create NOTIFICATIONS_DEBUG flag
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / notifications.qc
1 // ================================================
2 //  Unified notification system, written by Samual
3 //  Last updated: February, 2013
4 // ================================================
5
6 #ifndef MENUQC
7 // get the actual name of a notification and return it as a string
8 string Get_Field_Value(float field, float net_type, float net_name)
9 {
10         #ifdef NOTIFICATIONS_DEBUG
11                 dprint(sprintf("Get_Field_Value(%d, %d, %d);\n", field, net_type, net_name));
12         #endif
13         
14         #define GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) switch(field) { \
15                         case F_NAME: { return VAR_TO_TEXT(name); } \
16                         case F_STRNUM: { return ftos(strnum); } \
17                         case F_FLNUM: { return ftos(flnum); } }
18
19         #define GET_FIELD_VALUE_OUTPUT_PAIR(field,name,infoname,centername,strnum,flnum) switch(field) { \
20                         case F_NAME: { return VAR_TO_TEXT(name); } \
21                         case F_INFNAME: { return VAR_TO_TEXT(infoname); } \
22                         case F_CENNAME: { return VAR_TO_TEXT(centername); } \
23                         case F_INFVAL: { return ftos(infoname); } \
24                         case F_CENVAL: { return ftos(centername); } \
25                         case F_STRNUM: { return ftos(strnum); } \
26                         case F_FLNUM: { return ftos(flnum); } }
27
28         #define CLPSE_GETVALUE(name,arg,earg) \
29                 #if name != NO_MSG \
30                         arg \
31                 #else \
32                         earg \
33                 #endif
34
35         switch(net_type)
36         {
37                 case MSG_INFO:
38                 {
39                         #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) case name: { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) }
40                         NOTIF_SWITCH_LIST(MSG_INFO, net_name, return "")
41                         #undef MSG_INFO_NOTIF
42                         break;
43                 }
44                 case MSG_CENTER:
45                 {
46                         #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) case name: { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) }
47                         NOTIF_SWITCH_LIST(MSG_CENTER, net_name, return "")
48                         #undef MSG_CENTER_NOTIF
49                         break;
50                 }
51                 case MSG_WEAPON:
52                 {
53                         #define MSG_WEAPON_NOTIF(name,infoname,centername) case name: { GET_FIELD_VALUE_OUTPUT_PAIR(field,name, \
54                                 CLPSE_GETVALUE(infoname, infoname, NO_MSG), CLPSE_GETVALUE(centername, centername, NO_MSG), \
55                                 max(CLPSE_GETVALUE(infoname, stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), 0), CLPSE_GETVALUE(centername, stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername)), 0)), \
56                                 max(CLPSE_GETVALUE(infoname, stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), 0), CLPSE_GETVALUE(centername, stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)), 0))) }
57                         NOTIF_SWITCH_LIST(MSG_WEAPON, net_name, return "")
58                         #undef MSG_WEAPON_NOTIF
59                         break;
60                 }
61                 case MSG_DEATH:
62                 {
63                         #define MSG_DEATH_NOTIF(name,infoname,centername) case name: { GET_FIELD_VALUE_OUTPUT_PAIR(field,name, \
64                                 CLPSE_GETVALUE(infoname, infoname, NO_MSG), CLPSE_GETVALUE(centername, centername, NO_MSG), \
65                                 max(CLPSE_GETVALUE(infoname, stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), 0), CLPSE_GETVALUE(centername, stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername)), 0)), \
66                                 max(CLPSE_GETVALUE(infoname, stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), 0), CLPSE_GETVALUE(centername, stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)), 0))) }
67                         NOTIF_SWITCH_LIST(MSG_DEATH, net_name, return "")
68                         #undef MSG_DEATH_NOTIF
69                         break;
70                 }
71         }
72
73         #undef GET_FIELD_VALUE_OUTPUT
74         #undef GET_FIELD_VALUE_OUTPUT_PAIR
75         #undef CLPSE_GETVALUE
76         return "";
77 }
78 #endif // ifndef MENUQC
79
80
81 // ===============================
82 //  Frontend Notification Pushing
83 // ===============================
84
85 void Dump_Notifications(float fh, float alsoprint)
86 {
87         float MSG_INFO_NOTIFS = 0, MSG_CENTER_NOTIFS = 0, MSG_WEAPON_NOTIFS = 0, MSG_DEATH_NOTIFS = 0;
88         string notif_msg;
89
90         #define NOTIF_WRITE(type,name,text) { \
91                 ++##type##_NOTIFS; \
92                 notif_msg = sprintf("seta %s 1 // %s - %s\n", #name, #type, strreplace("\n", "\\n", text)); \
93                 fputs(fh, notif_msg); \
94                 if(alsoprint) { print(strreplace("^", "^^", notif_msg)); } }
95         
96         #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) NOTIF_WRITE(MSG_INFO, name, normal)
97         MSG_INFO_NOTIFICATIONS
98         #undef MSG_INFO_NOTIF
99         
100         #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) NOTIF_WRITE(MSG_CENTER, name, normal)
101         MSG_CENTER_NOTIFICATIONS
102         #undef MSG_CENTER_NOTIF
103         
104         #define MSG_WEAPON_NOTIF(name,infoname,centername) NOTIF_WRITE(MSG_WEAPON, name, \
105                 sprintf("infoname: %s, centername: %s", VAR_TO_TEXT(infoname), VAR_TO_TEXT(centername)))
106         MSG_WEAPON_NOTIFICATIONS
107         #undef MSG_WEAPON_NOTIF
108         
109         #define MSG_DEATH_NOTIF(name,infoname,centername) NOTIF_WRITE(MSG_DEATH, name, \
110                 sprintf("infoname: %s, centername: %s", VAR_TO_TEXT(infoname), VAR_TO_TEXT(centername)))
111         MSG_DEATH_NOTIFICATIONS
112         #undef MSG_DEATH_NOTIF
113         
114         print(sprintf("Notification counts: MSG_INFO = %d, MSG_CENTER = %d, MSG_WEAPON = %d, MSG_DEATH = %d\n",
115                 MSG_INFO_NOTIFS, MSG_CENTER_NOTIFS, MSG_WEAPON_NOTIFS, MSG_DEATH_NOTIFS));
116         
117         return;
118         #undef NOTIF_WRITE
119 }
120
121 #ifndef MENUQC
122 #ifdef CSQC
123 void HUD_Notify_Push(string icon, string attacker, string victim)
124 {
125         if(icon != "")
126         {
127                 --kn_index;
128                 if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
129                 killnotify_times[kn_index] = time;
130
131                 // icon
132                 if(killnotify_icon[kn_index]) { strunzone(killnotify_icon[kn_index]); }
133                 killnotify_icon[kn_index] = strzone(icon);
134
135                 // attacker
136                 if(killnotify_attackers[kn_index]) { strunzone(killnotify_attackers[kn_index]); }
137                 killnotify_attackers[kn_index] = strzone(attacker);
138
139                 // victim
140                 if(killnotify_victims[kn_index]) { strunzone(killnotify_victims[kn_index]); }
141                 killnotify_victims[kn_index] = strzone(victim);
142         }
143 }
144 #endif // ifdef CSQC
145
146 void Local_Notification(float net_type, float net_name, ...count)
147 {
148         // check supplied type and name for errors
149         #ifdef NOTIFICATIONS_DEBUG
150         {
151                 #define CHECKARG_TYPENAME(type) case MSG_##type##: \
152                         { if(!net_name || (net_name > NOTIF_##type##_COUNT)) \
153                         { checkargs = sprintf("Improper name: %d!", net_name); } break; }
154                         
155                 string checkargs = "";
156                 switch(net_type)
157                 {
158                         CHECKARG_TYPENAME(INFO)
159                         CHECKARG_TYPENAME(CENTER)
160                         CHECKARG_TYPENAME(WEAPON)
161                         CHECKARG_TYPENAME(DEATH)
162                         
163                         default: { checkargs = sprintf("Improper type: %d!", checkargs, net_type); break; }
164                 }
165                 #undef CHECKARG_TYPENAME
166
167                 if(checkargs != "") { backtrace(sprintf("Incorrect usage of Local_Notification: %s\n", checkargs)); return; }
168         }
169         #endif
170         
171         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
172         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
173
174         string s1 = ((0 < stringcount) ? ...(0, string) : NO_STR_ARG);
175         string s2 = ((1 < stringcount) ? ...(1, string) : NO_STR_ARG);
176         string s3 = ((2 < stringcount) ? ...(2, string) : NO_STR_ARG);
177         string s4 = ((3 < stringcount) ? ...(3, string) : NO_STR_ARG);
178         float f1 = ((stringcount < count) ? ...(stringcount, float) : NO_FL_ARG);
179         float f2 = (((stringcount + 1) < count) ? ...((stringcount + 1), float) : NO_FL_ARG);
180         float f3 = (((stringcount + 2) < count) ? ...((stringcount + 2), float) : NO_FL_ARG);
181         float f4 = (((stringcount + 3) < count) ? ...((stringcount + 3), float) : NO_FL_ARG);
182
183         #ifdef NOTIFICATIONS_DEBUG
184         {
185                 dprint(sprintf("Local_Notification(%d, %s, %s, %s, %s, %s, %d, %d, %d, %d);\n",
186                         net_type, Get_Field_Value(F_NAME, net_type, net_name),
187                         s1, s2, s3, s4, f1, f2, f3, f4));
188
189                 if((stringcount + floatcount) > count)
190                         { backtrace(sprintf("Not enough arguments for Local_Notification! stringcount(%d) + floatcount(%d) > count(%d) \
191                         \nCheck the notification definition and function call for accuracy...?\n", stringcount, floatcount, count)); return; }
192                 else if((stringcount + floatcount) < count)
193                         { backtrace(sprintf("Too many arguments for Local_Notification! stringcount(%d) + floatcount(%d) < count(%d) \
194                         \nCheck the notification definition and function call for accuracy...?\n", stringcount, floatcount, count)); return; }
195         }
196         #endif
197         
198
199         switch(net_type)
200         {
201                 case MSG_INFO:
202                 {
203                         #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
204                                 case name: { CHECK_AUTOCVAR(name) \
205                                 { \
206                                         print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); \
207                                         #ifdef CSQC \
208                                                 if(icon != "") { HUD_Notify_Push(icon, hudargs); } \
209                                         #endif \
210                                 } return; }
211                                 
212                         NOTIF_SWITCH_LIST(MSG_INFO, net_name, return)
213                         
214                         #undef MSG_INFO_NOTIF
215                         break;
216                 }
217                 #ifdef CSQC
218                 case MSG_CENTER:
219                 {
220                         #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
221                                 case name: { CHECK_AUTOCVAR(name) \
222                                 { \
223                                         centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); \
224                                 } return; }
225
226                         NOTIF_SWITCH_LIST(MSG_CENTER, net_name, return)
227                         
228                         #undef MSG_CENTER_NOTIF
229                         break;
230                 }
231                 #endif
232                 case MSG_WEAPON:
233                 {
234                         #define MSG_WEAPON_NOTIF(name,infoname,centername) \
235                                 case name: { CHECK_AUTOCVAR(name) \
236                                 { \
237                                         #if infoname != NO_MSG \
238                                                 Local_Notification_Without_VarArgs(MSG_INFO, infoname, \
239                                                         stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), \
240                                                         stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), \
241                                                         s1, s2, s3, s4, f1, f2, f3, f4); \
242                                         #endif \
243                                         #ifdef CSQC \
244                                                 #if centername != NO_MSG \
245                                                         Local_Notification_Without_VarArgs(MSG_CENTER, centername, \
246                                                                 stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername)), \
247                                                                 stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)), \
248                                                                 s1, s2, s3, s4, f1, f2, f3, f4); \
249                                                 #endif \
250                                         #endif \
251                                 } return; }
252
253                         NOTIF_SWITCH_LIST(MSG_WEAPON, net_name, return)
254                         
255                         #undef MSG_WEAPON_NOTIF
256                         break;
257                 }
258                 case MSG_DEATH:
259                 {
260                         #define MSG_DEATH_NOTIF(name,infoname,centername) \
261                                 case name: { CHECK_AUTOCVAR(name) \
262                                 { \
263                                         #if infoname != NO_MSG \
264                                                 Local_Notification_Without_VarArgs(MSG_INFO, infoname, \
265                                                         stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), \
266                                                         stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), \
267                                                         s1, s2, s3, s4, f1, f2, f3, f4); \
268                                         #endif \
269                                         #ifdef CSQC \
270                                                 #if centername != NO_MSG \
271                                                         Local_Notification_Without_VarArgs(MSG_CENTER, centername, \
272                                                                 stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername)), \
273                                                                 stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)), \
274                                                                 s1, s2, s3, s4, f1, f2, f3, f4); \
275                                                 #endif \
276                                         #endif \
277                                 } return; } 
278
279                         NOTIF_SWITCH_LIST(MSG_DEATH, net_name, return)
280                         
281                         #undef MSG_DEATH_NOTIF
282                         break;
283                 }
284         }
285 }
286
287 void Local_Notification_Without_VarArgs(float net_type, float net_name,
288         float stringcount, float floatcount,
289         string s1, string s2, string s3, string s4,
290         float f1, float f2, float f3, float f4)
291 {
292         #define VARITEM(stringc,floatc,args) if((stringcount == stringc) && (floatcount == floatc)) { Local_Notification(net_type, net_name, args); return; }
293         EIGHT_VARS_TO_VARARGS_VARLIST
294         #undef VARITEM
295
296         Local_Notification(net_type, net_name); // some notifications don't have any arguments at all
297 }
298
299
300 // =========================
301 //  Notification Networking
302 // =========================
303
304 #ifdef CSQC
305 void Read_Notification(float is_new)
306 {
307         float net_type = ReadByte();
308         float net_name = ReadShort();
309
310         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
311         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
312
313         string s1 = ((stringcount >= 1) ? ReadString() : NO_STR_ARG);
314         string s2 = ((stringcount >= 2) ? ReadString() : NO_STR_ARG);
315         string s3 = ((stringcount >= 3) ? ReadString() : NO_STR_ARG);
316         string s4 = ((stringcount == 4) ? ReadString() : NO_STR_ARG);
317         float f1 = ((floatcount >= 1) ? ReadLong() : NO_FL_ARG);
318         float f2 = ((floatcount >= 2) ? ReadLong() : NO_FL_ARG);
319         float f3 = ((floatcount >= 3) ? ReadLong() : NO_FL_ARG);
320         float f4 = ((floatcount == 4) ? ReadLong() : NO_FL_ARG);
321
322         #ifdef NOTIFICATIONS_DEBUG
323                 dprint(sprintf("Read_Notification(%d) at %d: net_name = %s.\n", is_new, time, Get_Field_Value(F_NAME, net_type, net_name)));
324         #endif
325         
326         if(is_new) { Local_Notification_Without_VarArgs(net_type, net_name, stringcount, floatcount, s1, s2, s3, s4, f1, f2, f3, f4); }
327 }
328 #endif
329
330 #ifdef SVQC
331 void Notification_Remove()
332 {
333         float i;
334         for(i = 0; i < 4; ++i) { if(self.nent_strings[i]) { strunzone(self.nent_strings[i]); } }
335         remove(self);
336 }
337
338 float Write_Notification(entity client, float sf)
339 {
340         float i, send = FALSE;
341         
342         switch(self.nent_broadcast)
343         {
344                 case NOTIF_ONE: { if((client == self.nent_client) || (client.classname == STR_SPECTATOR && client.enemy == self.nent_client)) { send = TRUE; } break; }
345                 case NOTIF_ONE_ONLY: { if(client == self.nent_client) { send = TRUE; } break; }
346                 case NOTIF_TEAM: { if((client.team == self.nent_client.team) || (client.classname == STR_SPECTATOR && client.enemy.team == self.nent_client.team)) { send = TRUE; } break; }
347                 case NOTIF_TEAM_EXCEPT: { if(((client != self.nent_client) && (client.team == self.nent_client.team) && !(client.classname == STR_SPECTATOR && client.enemy == self.nent_client))) { send = TRUE; } break; }
348                 case NOTIF_ANY: { send = TRUE; break; }
349                 case NOTIF_ANY_EXCEPT: { if((client != self.nent_client) && !(client.classname == STR_SPECTATOR && client.enemy == self.nent_client)) { send = TRUE; } break; }
350                 default: { send = FALSE; break; }
351         }
352
353         if(send)
354         {               
355                 WriteByte(MSG_ENTITY, ENT_CLIENT_NOTIFICATION);
356                 WriteByte(MSG_ENTITY, self.nent_net_type);
357                 WriteShort(MSG_ENTITY, self.nent_net_name);
358                 for(i = 0; i < self.nent_stringcount; ++i) { WriteString(MSG_ENTITY, self.nent_strings[i]); } 
359                 for(i = 0; i < self.nent_floatcount; ++i) { WriteLong(MSG_ENTITY, self.nent_floats[i]); }
360         }
361
362         return send; 
363 }
364
365 void Send_Notification(float broadcast, entity client,
366         float net_type, float net_name, ...count)
367 {
368         // check supplied broadcast, target, type, and name for errors
369         #ifdef NOTIFICATIONS_DEBUG
370         {
371                 #define CHECKARG_TYPENAME(type) case MSG_##type##: \
372                         { if(!net_name || (net_name > NOTIF_##type##_COUNT)) \
373                         { checkargs = sprintf("Improper name: %d!", net_name); } break; }
374                         
375                 string checkargs = "";
376                 switch(net_type)
377                 {
378                         CHECKARG_TYPENAME(INFO)
379                         CHECKARG_TYPENAME(CENTER)
380                         CHECKARG_TYPENAME(WEAPON)
381                         CHECKARG_TYPENAME(DEATH)
382                         
383                         default: { checkargs = sprintf("Improper type: %d!", checkargs, net_type); break; }
384                 }
385                 #undef CHECKARG_TYPENAME
386                 
387                 if(checkargs != "") { checkargs = strcat(checkargs, " "); }
388                 switch(broadcast)
389                 {
390                         case NOTIF_ONE:
391                         case NOTIF_ONE_ONLY: { if(clienttype(client) == CLIENTTYPE_NOTACLIENT) { checkargs = sprintf("%sNo client provided!", checkargs); } break; }
392                         case NOTIF_ANY_EXCEPT: { if(clienttype(client) == CLIENTTYPE_NOTACLIENT) { checkargs = sprintf("%sException can't be a non-client!", checkargs); } break; }
393                         case NOTIF_ANY: { if(client) { checkargs = sprintf("%sEntity provided when world was required!", checkargs); } break; }
394                         
395                         case NOTIF_TEAM:
396                         case NOTIF_TEAM_EXCEPT:
397                         {
398                                 if not(teamplay) { checkargs = sprintf("%sTeamplay not active!", checkargs); }
399                                 else if(clienttype(client) == CLIENTTYPE_NOTACLIENT)
400                                 {
401                                         if(broadcast == NOTIF_TEAM) { checkargs = sprintf("%sNo client provided!", checkargs); }
402                                         else { checkargs = sprintf("%sException can't be a non-client!", checkargs); }
403                                 }
404                                 break;
405                         }
406                         
407                         default: { checkargs = sprintf("%sImproper broadcast: %d!", checkargs, broadcast); break; }
408                 }
409                 
410                 if(checkargs != "") { backtrace(sprintf("Incorrect usage of Send_Notification: %s\n", checkargs)); return; }
411         }
412         #endif
413
414         // retreive counts for the arguments of this notification
415         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
416         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
417
418         #ifdef NOTIFICATIONS_DEBUG
419         {
420                 dprint(sprintf("Send_Notification(%d, %d, %s, stringcount: %d, floatcount: %d, varargs: %d);\n",
421                         broadcast, net_type, Get_Field_Value(F_NAME, net_type, net_name), stringcount, floatcount, count));
422
423                 if((stringcount + floatcount) > count)
424                         { backtrace(sprintf("Not enough arguments for Send_Notification! stringcount(%d) + floatcount(%d) > count(%d) \
425                         \nCheck the notification definition and function call for accuracy...?\n", stringcount, floatcount, count)); return; }
426                 else if((stringcount + floatcount) < count)
427                         { backtrace(sprintf("Too many arguments for Send_Notification! stringcount(%d) + floatcount(%d) < count(%d) \
428                         \nCheck the notification definition and function call for accuracy...?\n", stringcount, floatcount, count)); return; }
429         }
430         #endif
431
432         entity notif = spawn();
433         notif.nent_broadcast = broadcast;
434         notif.nent_client = client;
435         notif.nent_net_type = net_type;
436         notif.nent_net_name = net_name;
437         notif.nent_stringcount = stringcount;
438         notif.nent_floatcount = floatcount;
439         
440         float i;
441         
442         for(i = 0; i < stringcount; ++i) { notif.nent_strings[i] = strzone(...(i, string)); }
443         for(i = 0; i < floatcount; ++i) { notif.nent_floats[i] = ...((stringcount + i), float); }
444         
445         notif.think = Notification_Remove;
446         notif.nextthink = (time + 0.5); 
447
448         Net_LinkEntity(notif, FALSE, 0, Write_Notification);
449
450         if((!server_is_local) && (broadcast == NOTIF_ANY || broadcast == NOTIF_ANY_EXCEPT) && (net_type != MSG_CENTER))
451                 { Local_Notification_Without_VarArgs(net_type, net_name, stringcount, floatcount,
452                         IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), IFFL(0), IFFL(1), IFFL(2), IFFL(3)); }
453 }
454
455 void Send_Notification_Without_VarArgs(float broadcast, entity client,
456         float net_type, float net_name,
457         float stringcount, float floatcount,
458         string s1, string s2, string s3, string s4,
459         float f1, float f2, float f3, float f4)
460 {               
461         #define VARITEM(stringc,floatc,args) if((stringcount == stringc) && (floatcount == floatc)) { Send_Notification(broadcast, client, net_type, net_name, args); return; }
462         EIGHT_VARS_TO_VARARGS_VARLIST
463         #undef VARITEM
464
465         Send_Notification(broadcast, client, net_type, net_name); // some notifications don't have any arguments at all
466 }
467
468 void Send_Notification_Legacy_Wrapper(float broadcast, entity client,
469         float net_type, float net_name,
470         string s1, string s2,
471         float f1, float f2, float f3)
472 {
473         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
474         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
475         Send_Notification_Without_VarArgs(broadcast, client, net_type, net_name, stringcount, floatcount, s1, s2, NO_STR_ARG, NO_STR_ARG, f1, f2, f3, NO_FL_ARG);
476 }
477
478
479 // =============================
480 //  LEGACY NOTIFICATION SYSTEMS
481 // =============================
482
483 void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
484 {
485         if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
486         {
487                 msg_entity = e;
488                 WRITESPECTATABLE_MSG_ONE({
489                         WriteByte(MSG_ONE, SVC_TEMPENTITY);
490                         WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
491                         WriteByte(MSG_ONE, id);
492                         WriteString(MSG_ONE, s);
493                         if (id != 0 && s != "")
494                         {
495                                 WriteByte(MSG_ONE, duration);
496                                 WriteByte(MSG_ONE, countdown_num);
497                         }
498                 });
499         }
500 }
501 void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
502 {
503         Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);
504 }
505 #endif // ifdef SVQC
506 #endif // ifndef MENUQC