]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/notifications.qc
Update the function calls to match the new sending system
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / notifications.qc
1 // ================================================
2 //  Unified notification system, written by Samual
3 //  Last updated: December, 2012
4 // ================================================
5
6 // ======================
7 //  Supporting Functions
8 // ======================
9
10 // team code replace
11 string TCR(string input, string teamcolor, string teamtext) // TODO: MOVE TO UTIL.QC
12 {
13         input = strreplace("^TC", teamcolor, input);
14         input = strreplace("^TT", teamtext, input);
15         return input;
16 }
17
18 // color code replace, place inside of sprintf and parse the string
19 string CCR(string input) // TODO: MOVE TO UTIL.QC
20 {
21         // foreground/normal colors
22         input = strreplace("^F1", "^2", input); // primary priority (important names, etc)
23         input = strreplace("^F2", "^3", input); // secondary priority (items, locations, numbers, etc)
24
25         // "kill" colors
26         input = strreplace("^K1", "^1", input); // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
27         input = strreplace("^K2", "^3", input); // similar to above, but less important... OR, a highlight out of above message type
28         input = strreplace("^K3", "^4", input); // "good" or "beneficial" text (you fragging someone, etc)
29
30         // background colors
31         input = strreplace("^BG", "^7", input); // neutral/unimportant text
32         input = strreplace("^N", "^7", input); // "none"-- reset to white...
33         return input;
34 }
35
36 #ifndef MENUQC
37 // select between the normal or the gentle message string based on client (or server) settings
38 string normal_or_gentle(string normal, string gentle)
39 {
40         #ifdef CSQC
41         if(autocvar_cl_gentle || autocvar_cl_gentle_messages)
42         #else
43         if(autocvar_sv_gentle)
44         #endif
45                 return ((gentle != "") ? gentle : normal);
46         else
47                 return normal;
48 }
49
50 float notif_checkstring(string input)
51 {
52         if not(input == "") { return TRUE; }
53         else { return FALSE; }
54 }
55
56 // get the actual name of a notification and return it as a string
57 string Get_Field_Value(float field, float net_type, float net_name)
58 {
59         string output = "";
60         
61         #define GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) \
62                 switch(field) { \
63                         case F_NAME: { output = VAR_TO_TEXT(name); break; } \
64                         case F_STRNUM: { output = ftos(strnum); break; } \
65                         case F_FLNUM: { output = ftos(flnum); break; } }
66         
67         switch(net_type)
68         {
69                 case MSG_INFO:
70                 {
71                         #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
72                                 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
73                         MSG_INFO_NOTIFICATIONS
74                         #undef MSG_INFO_NOTIF
75                         break;
76                 }
77                 case MSG_CENTER:
78                 {
79                         #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
80                                 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
81                         MSG_CENTER_NOTIFICATIONS
82                         #undef MSG_CENTER_NOTIF
83                         break;
84                 }
85                 case MSG_WEAPON:
86                 {
87                         #define MSG_WEAPON_NOTIF(name,infoname,centername) \
88                                 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name, \
89                                 max(stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername))), \
90                                 max(stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)))) } }
91                         MSG_WEAPON_NOTIFICATIONS
92                         #undef MSG_WEAPON_NOTIF
93                         break;
94                 }
95                 case MSG_DEATH:
96                 {
97                         #define MSG_DEATH_NOTIF(name,infoname,centername) \
98                                 { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name, \
99                                 max(stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername))), \
100                                 max(stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)))) } }
101                         MSG_DEATH_NOTIFICATIONS
102                         #undef MSG_DEATH_NOTIF
103                         break;
104                 }
105         }
106
107         #undef GET_FIELD_VALUE_OUTPUT
108         return output;
109 }
110 #endif // ifndef MENUQC
111
112
113 // ===============================
114 //  Frontend Notification Pushing
115 // ===============================
116
117 void Dump_Notifications(float fh, float alsoprint)
118 {
119         float MSG_INFO_NOTIFS = 0, MSG_CENTER_NOTIFS = 0, MSG_WEAPON_NOTIFS = 0, MSG_DEATH_NOTIFS = 0;
120         string notif_msg;
121
122         #define NOTIF_WRITE(type,name,text) notif_msg = sprintf("seta %s 1 // %s - %s\n", name, type, strreplace("\n", "\\n", text)); fputs(fh, notif_msg); if(alsoprint) { print(strreplace("^", "^^", notif_msg)); }
123         #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) { ++MSG_INFO_NOTIFS; NOTIF_WRITE("MSG_INFO", VAR_TO_TEXT(name), normal) }
124         #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) { ++MSG_CENTER_NOTIFS; NOTIF_WRITE("MSG_CENTER", VAR_TO_TEXT(name), normal) }
125         #define MSG_WEAPON_NOTIF(name,infoname,centername) { ++MSG_WEAPON_NOTIFS; NOTIF_WRITE("MSG_WEAPON", VAR_TO_TEXT(name),sprintf("infoname: %s, centername: %s", VAR_TO_TEXT(infoname), VAR_TO_TEXT(centername))) }
126         #define MSG_DEATH_NOTIF(name,infoname,centername) { ++MSG_DEATH_NOTIFS; NOTIF_WRITE("MSG_DEATH", VAR_TO_TEXT(name), sprintf("infoname: %s, centername: %s", VAR_TO_TEXT(infoname), VAR_TO_TEXT(centername))) }
127         MSG_INFO_NOTIFICATIONS
128         MSG_CENTER_NOTIFICATIONS
129         MSG_WEAPON_NOTIFICATIONS
130         MSG_DEATH_NOTIFICATIONS
131         #undef NOTIF_WRITE
132         #undef MSG_INFO_NOTIF
133         #undef MSG_CENTER_NOTIF
134         #undef MSG_WEAPON_NOTIF
135         #undef MSG_DEATH_NOTIF
136         
137         print(sprintf("Notification counts: MSG_INFO = %d, MSG_CENTER = %d, MSG_WEAPON = %d, MSG_DEATH = %d\n", MSG_INFO_NOTIFS, MSG_CENTER_NOTIFS, MSG_WEAPON_NOTIFS, MSG_DEATH_NOTIFS));
138         return;
139 }
140
141 #ifndef MENUQC
142 #ifdef CSQC
143 void HUD_Notify_Push(string icon, string attacker, string victim)
144 {
145         if(icon != "")
146         {
147                 --kn_index;
148                 if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
149                 killnotify_times[kn_index] = time;
150
151                 // icon
152                 if(killnotify_icon[kn_index]) { strunzone(killnotify_icon[kn_index]); }
153                 killnotify_icon[kn_index] = strzone(icon);
154
155                 // attacker
156                 if(killnotify_attackers[kn_index]) { strunzone(killnotify_attackers[kn_index]); }
157                 killnotify_attackers[kn_index] = strzone(attacker);
158
159                 // victim
160                 if(killnotify_victims[kn_index]) { strunzone(killnotify_victims[kn_index]); }
161                 killnotify_victims[kn_index] = strzone(victim);
162         }
163 }
164
165 void backtrace(string msg) // TODO: MOVE TO UTIL.QC
166 {
167     float dev, war;
168     dev = cvar("developer");
169     war = cvar("prvm_backtraceforwarnings");
170     cvar_set("developer", "1");
171     cvar_set("prvm_backtraceforwarnings", "1");
172     print("\n");
173     print("--- CUT HERE ---\nWARNING: ");
174     print(msg);
175     print("\n");
176     remove(world); // isn't there any better way to cause a backtrace?
177     print("\n--- CUT UNTIL HERE ---\n");
178     cvar_set("developer", ftos(dev));
179     cvar_set("prvm_backtraceforwarnings", ftos(war));
180 }
181 #endif // ifdef CSQC
182
183 void Local_Notification(float net_type, float net_name, ...count)
184 {
185         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
186         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
187
188         string s1 = ((0 < stringcount) ? ...(0, string) : NO_STR_ARG);
189         string s2 = ((1 < stringcount) ? ...(1, string) : NO_STR_ARG);
190         string s3 = ((2 < stringcount) ? ...(2, string) : NO_STR_ARG);
191         string s4 = ((3 < stringcount) ? ...(3, string) : NO_STR_ARG);
192         float f1 = ((stringcount < count) ? ...(stringcount, float) : NO_FL_ARG);
193         float f2 = (((stringcount + 1) < count) ? ...((stringcount + 1), float) : NO_FL_ARG);
194         float f3 = (((stringcount + 2) < count) ? ...((stringcount + 2), float) : NO_FL_ARG);
195         float f4 = (((stringcount + 3) < count) ? ...((stringcount + 3), float) : NO_FL_ARG);
196         
197         dprint("Local_Notification(", ftos(net_type), ", ", Get_Field_Value(F_NAME, net_type, net_name), strcat(", ", s1, ", ", s2, ", ", s3, ", ", s4, ", "), strcat(ftos(f1), strcat(", ", ftos(f2), ", ", ftos(f3), ", ", ftos(f4), ");\n")));
198         dprint("  ^--: stringcount: ", ftos(stringcount), ", floatcount: ", ftos(floatcount), ".\n");
199
200         if((stringcount + floatcount) > count) { backtrace(strcat("Not enough arguments for Local_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), ")"), " > count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; }
201         else if((stringcount + floatcount) < count) { backtrace(strcat("Too many arguments for Local_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), ")"), " < count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; }
202
203         switch(net_type)
204         {
205                 case MSG_INFO:
206                 {
207                         #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
208                                 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
209                                 { \
210                                         if(notif_checkstring(normal)) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); } \
211                                         #ifdef CSQC \
212                                                 if(notif_checkstring(icon)) { HUD_Notify_Push(icon, hudargs); } \
213                                         #endif \
214                                 } }
215                         MSG_INFO_NOTIFICATIONS
216                         #undef MSG_INFO_NOTIF
217                         break;
218                 }
219                 #ifdef CSQC
220                 case MSG_CENTER:
221                 {
222                         #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
223                                 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
224                                 { \
225                                         if(notif_checkstring(normal)) { centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); } \
226                                 } }
227                         MSG_CENTER_NOTIFICATIONS
228                         #undef MSG_CENTER_NOTIF
229                         break;
230                 }
231                 #endif
232                 case MSG_WEAPON:
233                 {
234                         #define MSG_WEAPON_NOTIF(name,infoname,centername) \
235                                 { NOTIF_MATCH(name, net_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                                 } }
252                         MSG_WEAPON_NOTIFICATIONS
253                         #undef MSG_WEAPON_NOTIF
254                         break;
255                 }
256                 case MSG_DEATH:
257                 {
258                         #define MSG_DEATH_NOTIF(name,infoname,centername) \
259                                 { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
260                                 { \
261                                         #if infoname != NO_MSG \
262                                                 Local_Notification_Without_VarArgs(MSG_INFO, infoname, \
263                                                         stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), \
264                                                         stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), \
265                                                         s1, s2, s3, s4, f1, f2, f3, f4); \
266                                         #endif \
267                                         #ifdef CSQC \
268                                                 #if centername != NO_MSG \
269                                                         Local_Notification_Without_VarArgs(MSG_CENTER, centername, \
270                                                                 stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername)), \
271                                                                 stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)), \
272                                                                 s1, s2, s3, s4, f1, f2, f3, f4); \
273                                                 #endif \
274                                         #endif \
275                                 } }
276                         MSG_DEATH_NOTIFICATIONS
277                         #undef MSG_DEATH_NOTIF
278                         break;
279                 }
280         }
281 }
282
283 void Local_Notification_Without_VarArgs(float net_type, float net_name, float stringcount, float floatcount, string s1, string s2, string s3, string s4, float f1, float f2, float f3, float f4)
284 {
285         #define VARITEM(stringc,floatc,args) if((stringcount == stringc) && (floatcount == floatc)) { Local_Notification(net_type, net_name, args); return; }
286         EIGHT_VARS_TO_VARARGS_VARLIST
287         #undef VARITEM
288
289         Local_Notification(net_type, net_name); // some notifications don't have any arguments at all
290 }
291
292
293 // =========================
294 //  Notification Networking
295 // =========================
296
297 #ifdef CSQC
298 void Read_Notification(float is_new)
299 {
300         float net_type = ReadByte();
301         float net_name = ReadShort();
302
303         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
304         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
305
306         string s1 = ((stringcount >= 1) ? ReadString() : NO_STR_ARG);
307         string s2 = ((stringcount >= 2) ? ReadString() : NO_STR_ARG);
308         string s3 = ((stringcount >= 3) ? ReadString() : NO_STR_ARG);
309         string s4 = ((stringcount == 4) ? ReadString() : NO_STR_ARG);
310         float f1 = ((floatcount >= 1) ? ReadLong() : NO_FL_ARG);
311         float f2 = ((floatcount >= 2) ? ReadLong() : NO_FL_ARG);
312         float f3 = ((floatcount >= 3) ? ReadLong() : NO_FL_ARG);
313         float f4 = ((floatcount == 4) ? ReadLong() : NO_FL_ARG);
314
315         if(is_new) { Local_Notification_Without_VarArgs(net_type, net_name, stringcount, floatcount, s1, s2, s3, s4, f1, f2, f3, f4); }
316         else { print("received old notification? net_name = ", ftos(net_name), ".\n"); }
317 }
318 #endif
319
320 #ifdef SVQC
321 float Write_Notification(entity client, float sf)
322 {
323         float i, send = FALSE;
324         
325         switch(self.nent_broadcast)
326         {
327                 case NOTIF_ONE: { if((client == self.nent_client) || (client.classname == STR_SPECTATOR && client.enemy == self.nent_client)) { send = TRUE; } break; }
328                 case NOTIF_ONE_ONLY: { if(client == self.nent_client) { send = TRUE; } break; }
329                 case NOTIF_TEAM: { if((client.team == self.nent_client.team) || (client.classname == STR_SPECTATOR && client.enemy.team == self.nent_client.team)) { send = TRUE; } break; }
330                 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; }
331                 case NOTIF_ANY: { send = TRUE; break; }
332                 case NOTIF_ANY_EXCEPT: { if((client != self.nent_client) && !(client.classname == STR_SPECTATOR && client.enemy == self.nent_client)) { send = TRUE; } break; }
333                 default: { send = FALSE; break; }
334         }
335
336         if(send)
337         {
338                 float stringcount = stof(Get_Field_Value(F_STRNUM, self.nent_net_type, self.nent_net_name));
339                 float floatcount = stof(Get_Field_Value(F_FLNUM, self.nent_net_type, self.nent_net_name));
340                 
341                 WriteByte(MSG_ENTITY, ENT_CLIENT_NOTIFICATION);
342                 WriteByte(MSG_ENTITY, self.nent_net_type);
343                 WriteShort(MSG_ENTITY, self.nent_net_name);
344                 for(i = 0; i < stringcount; ++i) { WriteString(MSG_ENTITY, self.nent_strings[i]); } 
345                 for(i = 0; i < floatcount; ++i) { WriteLong(MSG_ENTITY, self.nent_floats[stringcount + i]); }
346         }
347
348         return send; 
349 }
350
351 void Send_Notification(float broadcast, entity client, float net_type, float net_name, ...count)
352 {
353         if((broadcast == MSG_BROADCAST || broadcast == MSG_ONE) && net_type && net_name)
354         {
355                 float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
356                 float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
357                 float i, tmp_f;
358                 string tmp_s;
359
360                 dprint("Send_Notification(", ftos(broadcast), ", ", ftos(net_type), ", ", Get_Field_Value(F_NAME, net_type, net_name), strcat(", ", ftos(count), ");\n"));
361                 dprint("  ^--: stringcount: ", ftos(stringcount), ", floatcount: ", ftos(floatcount), ".\n");
362
363                 if((stringcount + floatcount) > count) { backtrace(strcat("Not enough arguments for Send_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), "),"), " > count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; }
364                 else if((stringcount + floatcount) < count) { backtrace(strcat("Too many arguments for Send_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), "),"), " < count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; }
365
366                 entity notif = spawn();
367                 notif.nent_broadcast = broadcast;
368                 notif.nent_client = client;
369                 notif.nent_net_type = net_type;
370                 notif.nent_net_name = net_name;
371                 for(i = 0; i < stringcount; ++i) { tmp_s = ...(i, string); notif.nent_strings[i] = tmp_s; dprint("WriteString(...(", ftos(i), ", string)); - ", tmp_s, "\n"); } 
372                 for(i = 0; i < floatcount; ++i) { tmp_f = ...((stringcount + i), float); notif.nent_floats[i] = tmp_f; dprint("WriteLong(...(", ftos((stringcount + i)), ", float)); - ", ftos(tmp_f), "\n"); }
373
374                 Net_LinkEntity(notif, FALSE, 0.5, Write_Notification);
375
376                 if(!server_is_local)
377                 {
378                         Local_Notification_Without_VarArgs(net_type, net_name, stringcount, floatcount, IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), IFFL(0), IFFL(1), IFFL(2), IFFL(3));
379                 }
380         }
381         else { backtrace("Incorrect usage of Send_Notification!\n"); }
382 }
383
384 void Send_Notification_Without_VarArgs(float broadcast, entity client, float net_type, float net_name, float stringcount, float floatcount, string s1, string s2, string s3, string s4, float f1, float f2, float f3, float f4)
385 {               
386         #define VARITEM(stringc,floatc,args) if((stringcount == stringc) && (floatcount == floatc)) { Send_Notification(broadcast, client, net_type, net_name, args); return; }
387         EIGHT_VARS_TO_VARARGS_VARLIST
388         #undef VARITEM
389
390         Send_Notification(broadcast, client, net_type, net_name); // some notifications don't have any arguments at all
391 }
392
393 void Send_Notification_Legacy_Wrapper(float broadcast, entity client, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
394 {
395         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
396         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
397         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);
398 }
399
400 /*void Send_Notification_ToTeam(float targetteam, entity except, float net_type, float net_name, ...count)
401 {
402         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
403         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
404         Send_Notification_Without_VarArgs(NOTIF_TEAM, tmp_entity, net_type, net_name, stringcount, floatcount, IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), IFFL(0), IFFL(1), IFFL(2), IFFL(3));
405 }
406
407 // WARNING: use this ONLY if you need exceptions or want to exclude spectators, otherwise use Send_Notification(world, MSG_BROADCAST, ...)
408 void Send_Notification_ToAll(entity except, float spectators, float net_type, float net_name, ...count)
409 {
410         float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name));
411         float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name));
412         
413         entity tmp_entity;
414         FOR_EACH_REALCLIENT(tmp_entity)
415         {
416                 if((tmp_entity.classname == STR_PLAYER) || spectators)
417                 if(tmp_entity != except)
418                 {
419                         Send_Notification_Without_VarArgs(tmp_entity, MSG_ONE, net_type, net_name, stringcount, floatcount, IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), IFFL(0), IFFL(1), IFFL(2), IFFL(3));
420                 }
421         }
422 }*/
423
424
425 // =============================
426 //  LEGACY NOTIFICATION SYSTEMS
427 // =============================
428
429 void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
430 {
431         if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
432         {
433                 msg_entity = e;
434                 WRITESPECTATABLE_MSG_ONE({
435                         WriteByte(MSG_ONE, SVC_TEMPENTITY);
436                         WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
437                         WriteByte(MSG_ONE, id);
438                         WriteString(MSG_ONE, s);
439                         if (id != 0 && s != "")
440                         {
441                                 WriteByte(MSG_ONE, duration);
442                                 WriteByte(MSG_ONE, countdown_num);
443                         }
444                 });
445         }
446 }
447 void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
448 {
449         Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);
450 }
451 #endif // ifdef SVQC
452 #endif // ifndef MENUQC