1 #ifndef NOTIFICATIONS_H
2 #define NOTIFICATIONS_H
4 #include "constants.qh"
8 // ================================================
9 // Unified notification system, written by Samual
10 // Last updated: March, 2013
11 // ================================================
13 // main types/groups of notifications
14 const int MSG_ANNCE = 1; // "Global" AND "personal" announcer messages
15 const int MSG_INFO = 2; // "Global" information messages
16 const int MSG_CENTER = 3; // "Personal" centerprint messages
17 const int MSG_CENTER_CPID = 4; // Kill centerprint message
18 const int MSG_MULTI = 5; // Subcall MSG_INFO and/or MSG_CENTER notifications
19 const int MSG_CHOICE = 6; // Choose which subcall wrapper to activate
21 // negative confirmations
22 const int NO_MSG = -12345; // allows various things to know when no information is added
23 const int NOTIF_ABORT = -1234; // allows Send_Notification to safely abort sending
25 #define EIGHT_VARS_TO_VARARGS_VARLIST \
27 VARITEM(2, 0, XPD(s1, s2)) \
28 VARITEM(3, 0, XPD(s1, s2, s3)) \
29 VARITEM(4, 0, XPD(s1, s2, s3, s4)) \
31 VARITEM(1, 1, XPD(s1, f1)) \
32 VARITEM(2, 1, XPD(s1, s2, f1)) \
33 VARITEM(3, 1, XPD(s1, s2, s3, f1)) \
34 VARITEM(4, 1, XPD(s1, s2, s3, s4, f1)) \
35 VARITEM(0, 2, XPD(f1, f2)) \
36 VARITEM(1, 2, XPD(s1, f1, f2)) \
37 VARITEM(2, 2, XPD(s1, s2, f1, f2)) \
38 VARITEM(3, 2, XPD(s1, s2, s3, f1, f2)) \
39 VARITEM(4, 2, XPD(s1, s2, s3, s4, f1, f2)) \
40 VARITEM(0, 3, XPD(f1, f2, f3)) \
41 VARITEM(1, 3, XPD(s1, f1, f2, f3)) \
42 VARITEM(2, 3, XPD(s1, s2, f1, f2, f3)) \
43 VARITEM(3, 3, XPD(s1, s2, s3, f1, f2, f3)) \
44 VARITEM(4, 3, XPD(s1, s2, s3, s4, f1, f2, f3)) \
45 VARITEM(0, 4, XPD(f1, f2, f3, f4)) \
46 VARITEM(1, 4, XPD(s1, f1, f2, f3, f4)) \
47 VARITEM(2, 4, XPD(s1, s2, f1, f2, f3, f4)) \
48 VARITEM(3, 4, XPD(s1, s2, s3, f1, f2, f3, f4)) \
49 VARITEM(4, 4, XPD(s1, s2, s3, s4, f1, f2, f3, f4))
51 void Destroy_All_Notifications(void);
52 void Create_Notification_Entity(
65 /* MSG_INFO & MSG_CENTER */
84 void Dump_Notifications(float fh, float alsoprint);
86 #ifdef NOTIFICATIONS_DEBUG
87 void Debug_Notification(string input);
90 void Local_Notification(int net_type, int net_name, ...count);
91 void Local_Notification_WOVA(
92 float net_type, float net_name,
93 float stringcount, float floatcount,
94 string s1, string s2, string s3, string s4,
95 float f1, float f2, float f3, float f4);
97 #ifdef CSQC // CLIENT ONLY
98 void Read_Notification(float is_new);
99 string prev_soundfile;
100 float prev_soundtime;
103 #ifdef SVQC // SERVER ONLY
104 const float NOTIF_ONE = 1;
105 const float NOTIF_ONE_ONLY = 2;
106 const float NOTIF_TEAM = 3;
107 const float NOTIF_TEAM_EXCEPT = 4;
108 const float NOTIF_ALL = 5;
109 const float NOTIF_ALL_EXCEPT = 6;
111 void Kill_Notification(
112 float broadcast, entity client,
113 float net_type, float net_name);
114 void Send_Notification(
115 float broadcast, entity client,
116 float net_type, float net_name,
118 void Send_Notification_WOVA(
119 float broadcast, entity client,
120 float net_type, float net_name,
121 float stringcount, float floatcount,
122 string s1, string s2, string s3, string s4,
123 float f1, float f2, float f3, float f4);
124 void Send_Notification_WOCOVA(
125 float broadcast, entity client,
126 float net_type, float net_name,
127 string s1, string s2, string s3, string s4,
128 float f1, float f2, float f3, float f4);
131 // ===========================
132 // Special CVAR Declarations
133 // ===========================
135 // MAKE SURE THIS IS ALWAYS SYNCHRONIZED WITH THE DUMP
136 // NOTIFICATIONS FUNCTION IN THE .QC FILE!
138 #define NOTIF_ADD_AUTOCVAR(name,default) float autocvar_notification_##name = default;
140 float autocvar_notification_show_location = false;
141 string autocvar_notification_show_location_string = ""; //_(" at the %s");
142 float autocvar_notification_show_sprees = true;
143 float autocvar_notification_show_sprees_info = 3; // 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker
144 float autocvar_notification_show_sprees_info_newline = true;
145 float autocvar_notification_show_sprees_info_specialonly = true;
146 float autocvar_notification_errors_are_fatal = true;
147 float autocvar_notification_lifetime_runtime = 0.5;
148 float autocvar_notification_lifetime_mapload = 10;
149 float autocvar_notification_debug = false;
153 void Notification_GetCvars(void);
154 float autocvar_notification_server_allows_location = 1; // 0 = no, 1 = yes
156 float autocvar_notification_item_centerprinttime = 1.5;
158 // 0 = no, 1 = yes, 2 = forced on for all MSG_INFO notifs
159 // DISABLED IN CODE, BUT ENABLED IN CONFIG FOR COMPATIBILITY WITH OLD CLIENTS
160 float autocvar_notification_allow_chatboxprint = 0;
162 float autocvar_notification_show_sprees_center = true;
163 float autocvar_notification_show_sprees_center_specialonly = true;
167 // ============================
168 // Notification Argument List
169 // ============================
171 These arguments get replaced with the Local_Notification_sprintf
172 and other such functions found in notifications.qc to supply data
173 from networked notifications to their usage in sprintf... It
174 allows for more dynamic data to be inferred by the local
175 notification parser, so that the server does not have to network
176 anything too crazy on a per-client/per-situation basis.
178 Pay attention to the CSQC/SVQC relations, some of these are redefined
179 in slightly different ways for different programs, this is because the
180 server does a more conservative approach to the notifs than the client.
182 All arguments are swapped into strings, so be sure that your
183 sprintf usage matches with proper %s placement.
185 Argument descriptions:
186 s1-s4: string arguments to be literally swapped into sprintf
187 s2loc: s2 string of locations of deaths or other events
188 s3loc: s3 string of locations of deaths or other events
189 f1-f4: float arguments expanded into strings to be swapped into sprintf
190 f1p2dec: f1 float to string with 2 decimal places
191 f2p2dec: f2 float to string with 2 decimal places
192 f2primsec: f2 float primary or secondary selection for weapons
193 f3primsec: f3 float primary or secondary selection for weapons
194 f1secs: count_seconds of f1
195 f1ord: count_ordinal of f1
196 f1time: process_time of f1
197 f1race_time: mmssss of f1
198 f2race_time: mmssss of f2
199 race_col: color of race time/position (i.e. good or bad)
200 race_diff: show time difference between f2 and f3
201 missing_teams: show which teams still need players
202 pass_key: find the keybind for "passing" or "dropping" in CTF game mode
203 frag_ping: show the ping of a player
204 frag_stats: show health/armor/ping of a player
205 frag_pos: show score status and position in the match of a player
206 spree_cen: centerprint notif for kill spree/how many kills they have
207 spree_inf: info notif for kill spree/how many kills they have
208 spree_end: placed at the end of murder messages to show ending of sprees
209 spree_lost: placed at the end of suicide messages to show losing of sprees
210 item_wepname: return full name of a weapon from weaponid
211 item_wepammo: ammo display for weapon from string
212 item_centime: amount of time to display weapon message in centerprint
213 item_buffname: return full name of a buff from buffid
214 death_team: show the full name of the team a player is switching from
215 minigame1_name: return human readable name of a minigame from its id(s1)
216 minigame1_d: return descriptor name of a minigame from its id(s1)
219 const float NOTIF_MAX_ARGS = 7;
220 const float NOTIF_MAX_HUDARGS = 2;
221 const float NOTIF_MAX_DURCNT = 2;
223 string arg_slot[NOTIF_MAX_ARGS];
225 const float ARG_CS_SV_HA = 1; // enabled on CSQC, SVQC, and Hudargs
226 const float ARG_CS_SV_DC = 2; // enabled on CSQC, SVQC, and durcnt centerprint
227 const float ARG_CS_SV = 3; // enabled on CSQC and SVQC
228 const float ARG_CS = 4; // unique result to CSQC
229 const float ARG_SV = 5; // unique result to SVQC
230 const float ARG_DC = 6; // unique result to durcnt/centerprint
232 // todo possible idea.... declare how many floats/strings each arg needs, and then dynamically increment the input
233 // this way, we don't need to have duplicates like i.e. s2loc and s3loc?
235 #define NOTIF_ARGUMENT_LIST \
236 ARG_CASE(ARG_CS_SV_HA, "s1", s1) \
237 ARG_CASE(ARG_CS_SV_HA, "s2", s2) \
238 ARG_CASE(ARG_CS_SV_HA, "s3", s3) \
239 ARG_CASE(ARG_CS_SV_HA, "s4", s4) \
240 ARG_CASE(ARG_CS_SV, "s2loc", ((autocvar_notification_show_location && (s2 != "")) ? sprintf(( ((tmp_s = autocvar_notification_show_location_string) != "") ? tmp_s : _(" (near %s)") ), s2) : "")) \
241 ARG_CASE(ARG_CS_SV, "s3loc", ((autocvar_notification_show_location && (s3 != "")) ? sprintf(( ((tmp_s = autocvar_notification_show_location_string) != "") ? tmp_s : _(" (near %s)") ), s3) : "")) \
242 ARG_CASE(ARG_CS_SV_DC, "f1", ftos(f1)) \
243 ARG_CASE(ARG_CS_SV_DC, "f2", ftos(f2)) \
244 ARG_CASE(ARG_CS_SV, "f3", ftos(f3)) \
245 ARG_CASE(ARG_CS_SV, "f4", ftos(f4)) \
246 ARG_CASE(ARG_CS_SV, "f1p2dec", ftos_decimals(f1/100, 2)) \
247 ARG_CASE(ARG_CS_SV, "f2p2dec", ftos_decimals(f2/100, 2)) \
248 ARG_CASE(ARG_CS, "f2primsec", (f2 ? _("secondary") : _("primary"))) \
249 ARG_CASE(ARG_CS, "f3primsec", (f3 ? _("secondary") : _("primary"))) \
250 ARG_CASE(ARG_CS, "f1secs", count_seconds(f1)) \
251 ARG_CASE(ARG_CS_SV, "f1ord", count_ordinal(f1)) \
252 ARG_CASE(ARG_CS, "f1time", process_time(2, f1)) \
253 ARG_CASE(ARG_CS_SV_HA, "f1race_time", mmssss(f1)) \
254 ARG_CASE(ARG_CS_SV_HA, "f2race_time", mmssss(f2)) \
255 ARG_CASE(ARG_CS_SV_HA, "f3race_time", mmssss(f3)) \
256 ARG_CASE(ARG_CS_SV, "race_col", CCR(((f1 == 1) ? "^F1" : "^F2"))) \
257 ARG_CASE(ARG_CS_SV, "race_diff", ((f2 > f3) ? sprintf(CCR("^1[+%s]"), mmssss(f2 - f3)) : sprintf(CCR("^2[-%s]"), mmssss(f3 - f2)))) \
258 ARG_CASE(ARG_CS, "missing_teams", notif_arg_missing_teams(f1)) \
259 ARG_CASE(ARG_CS, "pass_key", ((((tmp_s = getcommandkey("pass", "+use")) != "pass") && !(strstrofs(tmp_s, "not bound", 0) >= 0)) ? sprintf(CCR(_(" ^F1(Press %s)")), tmp_s) : "")) \
260 ARG_CASE(ARG_CS, "frag_ping", notif_arg_frag_ping(true, f2)) \
261 ARG_CASE(ARG_CS, "frag_stats", notif_arg_frag_stats(f2, f3, f4)) \
262 /*ARG_CASE(ARG_CS, "frag_pos", ((Should_Print_Score_Pos(f1)) ? sprintf("\n^BG%s", Read_Score_Pos(f1)) : ""))*/ \
263 ARG_CASE(ARG_CS, "spree_cen", (autocvar_notification_show_sprees ? notif_arg_spree_cen(f1) : "")) \
264 ARG_CASE(ARG_CS_SV, "spree_inf", (autocvar_notification_show_sprees ? notif_arg_spree_inf(1, input, s2, f2) : "")) \
265 ARG_CASE(ARG_CS_SV, "spree_end", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
266 ARG_CASE(ARG_CS_SV, "spree_lost", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
267 ARG_CASE(ARG_CS_SV, "item_wepname", WEP_NAME(f1)) \
268 ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(BUFFS[f1].m_color), BUFFS[f1].m_prettyName)) \
269 ARG_CASE(ARG_CS_SV, "f3buffname", sprintf("%s%s", rgb_to_hexcolor(BUFFS[f3].m_color), BUFFS[f3].m_prettyName)) \
270 ARG_CASE(ARG_CS_SV, "item_wepammo", (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
271 ARG_CASE(ARG_DC, "item_centime", ftos(autocvar_notification_item_centerprinttime)) \
272 ARG_CASE(ARG_SV, "death_team", Team_ColoredFullName(f1)) \
273 ARG_CASE(ARG_CS, "death_team", Team_ColoredFullName(f1 - 1)) \
274 ARG_CASE(ARG_CS_SV_HA, "minigame1_name",find(world,netname,s1).descriptor.message) \
275 ARG_CASE(ARG_CS_SV_HA, "minigame1_d", find(world,netname,s1).descriptor.netname)
277 #define NOTIF_HIT_MAX(count,funcname) do { \
278 if(sel_num == count) { backtrace(sprintf("%s: Hit maximum arguments!\n", funcname)); break; } \
280 #define NOTIF_HIT_UNKNOWN(token,funcname) { backtrace(sprintf("%s: Hit unknown token in selected string! '%s'\n", funcname, selected)); break; }
282 #define KILL_SPREE_LIST \
283 SPREE_ITEM(3, 03, _("TRIPLE FRAG! "), _("%s^K1 made a TRIPLE FRAG! %s^BG"), _("%s^K1 made a TRIPLE SCORE! %s^BG")) \
284 SPREE_ITEM(5, 05, _("RAGE! "), _("%s^K1 unlocked RAGE! %s^BG"), _("%s^K1 made FIVE SCORES IN A ROW! %s^BG")) \
285 SPREE_ITEM(10, 10, _("MASSACRE! "), _("%s^K1 started a MASSACRE! %s^BG"), _("%s^K1 made TEN SCORES IN A ROW! %s^BG")) \
286 SPREE_ITEM(15, 15, _("MAYHEM! "), _("%s^K1 executed MAYHEM! %s^BG"), _("%s^K1 made FIFTEEN SCORES IN A ROW! %s^BG")) \
287 SPREE_ITEM(20, 20, _("BERSERKER! "), _("%s^K1 is a BERSERKER! %s^BG"), _("%s^K1 made TWENTY SCORES IN A ROW! %s^BG")) \
288 SPREE_ITEM(25, 25, _("CARNAGE! "), _("%s^K1 inflicts CARNAGE! %s^BG"), _("%s^K1 made TWENTY FIVE SCORES IN A ROW! %s^BG")) \
289 SPREE_ITEM(30, 30, _("ARMAGEDDON! "), _("%s^K1 unleashes ARMAGEDDON! %s^BG"), _("%s^K1 made THIRTY SCORES IN A ROW! %s^BG"))
292 string notif_arg_frag_ping(float newline, float fping)
295 return sprintf(CCR(_("%s(^F1Bot^BG)")), (newline ? "\n" : " "));
297 return sprintf(CCR(_("%s(Ping ^F1%d^BG)")), (newline ? "\n" : " "), fping);
300 string notif_arg_frag_stats(float fhealth, float farmor, float fping)
303 return sprintf(CCR(_("\n(Health ^1%d^BG / Armor ^2%d^BG)%s")), fhealth, farmor, notif_arg_frag_ping(false, fping));
305 return sprintf(CCR(_("\n(^F4Dead^BG)%s")), notif_arg_frag_ping(false, fping));
308 string notif_arg_missing_teams(float f1)
310 return sprintf("%s%s%s%s",
312 sprintf("%s%s", Team_ColoredFullName(NUM_TEAM_1), ((f1 & (2 + 4 + 8)) ? ", " : ""))
317 sprintf("%s%s", Team_ColoredFullName(NUM_TEAM_2), ((f1 & (4 + 8)) ? ", " : ""))
322 sprintf("%s%s", Team_ColoredFullName(NUM_TEAM_3), ((f1 & 8) ? ", " : ""))
327 Team_ColoredFullName(NUM_TEAM_4)
334 string notif_arg_spree_cen(float spree)
336 // 0 = off, 1 = target (but only for first victim) and attacker
337 if(autocvar_notification_show_sprees_center)
341 #define SPREE_ITEM(counta,countb,center,normal,gentle) \
342 case counta: { return normal_or_gentle(center, sprintf(_("%d score spree! "), spree)); }
349 if (!autocvar_notification_show_sprees_center_specialonly)
354 _("%d frag spree! "),
355 _("%d score spree! ")
359 else { return ""; } // don't show spree information if it isn't an achievement
365 else if(spree == -1) // first blood
367 return normal_or_gentle(_("First blood! "), _("First score! "));
369 else if(spree == -2) // first victim
371 return normal_or_gentle(_("First victim! "), _("First casualty! "));
378 string notif_arg_spree_inf(float type, string input, string player, float spree)
382 case 1: // attacker kill spree
384 // 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker
385 // this conditional (& 2) is true for 2 and 3
386 if(autocvar_notification_show_sprees_info & 2)
389 string spree_newline =
390 ( autocvar_notification_show_sprees_info_newline ?
391 ((substring(input, 0, 1) == "\{3}") ? "\n\{3}" : "\n") : "" );
393 string spree_newline =
394 (autocvar_notification_show_sprees_info_newline ? "\n" : "");
399 #define SPREE_ITEM(counta,countb,center,normal,gentle) \
400 case counta: { return sprintf(CCR(normal_or_gentle(normal, gentle)), player, spree_newline); }
407 if (!autocvar_notification_show_sprees_info_specialonly)
411 CCR(normal_or_gentle(
412 _("%s^K1 has %d frags in a row! %s^BG"),
413 _("%s^K1 made %d scores in a row! %s^BG")
420 else { return ""; } // don't show spree information if it isn't an achievement
426 else if(spree == -1) // firstblood
430 CCR(normal_or_gentle(
431 _("%s^K1 drew first blood! %s^BG"),
432 _("%s^K1 got the first score! %s^BG")
442 case -1: // kill spree ended
444 if((spree > 1) && (autocvar_notification_show_sprees_info & 1))
447 sprintf(normal_or_gentle(
448 _(", ending their %d frag spree"),
449 _(", ending their %d score spree")
457 case -2: // kill spree lost
459 if((spree > 1) && (autocvar_notification_show_sprees_info & 1))
462 sprintf(normal_or_gentle(
463 _(", losing their %d frag spree"),
464 _(", losing their %d score spree")
476 // ====================================
477 // Initialization/Create Declarations
478 // ====================================
499 , CPID_MISSING_PLAYERS
500 , CPID_INSTAGIB_FINDAMMO
507 , CPID_RACE_FINISHLAP
511 , CPID_VEHICLES_OTHER
515 // notification counts
516 const float NOTIF_FIRST = 1;
517 float NOTIF_ANNCE_COUNT;
518 float NOTIF_INFO_COUNT;
519 float NOTIF_CENTER_COUNT;
520 float NOTIF_MULTI_COUNT;
521 float NOTIF_CHOICE_COUNT;
523 // notification limits -- INCREASE AS NECESSARY
524 const float NOTIF_ANNCE_MAX = 100;
525 const float NOTIF_INFO_MAX = 350;
526 const float NOTIF_CENTER_MAX = 250;
527 const float NOTIF_MULTI_MAX = 200;
528 const float NOTIF_CHOICE_MAX = 30;
530 // notification entities
531 entity msg_annce_notifs[NOTIF_ANNCE_MAX];
532 entity msg_info_notifs[NOTIF_INFO_MAX];
533 entity msg_center_notifs[NOTIF_CENTER_MAX];
534 entity msg_multi_notifs[NOTIF_MULTI_MAX];
535 entity msg_choice_notifs[NOTIF_CHOICE_MAX];
537 // common notification entity values
543 .int nent_stringcount;
544 .int nent_floatcount;
546 // MSG_ANNCE entity values
550 .float nent_position;
552 // MSG_INFO and MSG_CENTER entity values
553 .string nent_args; // used by both
554 .string nent_hudargs; // used by info
555 .string nent_icon; // used by info
556 .float nent_cpid; // used by center
557 .string nent_durcnt; // used by center
558 .string nent_string; // used by both
560 // MSG_MULTI entity values
561 .entity nent_msgannce;
562 .entity nent_msginfo;
563 .entity nent_msgcenter;
565 // MSG_CHOICE entity values
566 .float nent_challow_def;
567 .float nent_challow_var;
568 .entity nent_optiona;
569 .entity nent_optionb;
571 // networked notification entity values
572 .float nent_broadcast;
574 .float nent_net_type;
575 .float nent_net_name;
576 .string nent_strings[4];
577 .float nent_floats[4];
579 // other notification properties
580 .float msg_choice_choices[NOTIF_CHOICE_MAX]; // set on each player containing MSG_CHOICE choices
582 // initialization error detection
584 float notif_global_error;
586 #define MSG_ANNCE_NOTIF(default,name,channel,sound,volume,position) \
587 NOTIF_ADD_AUTOCVAR(name, default) \
589 void RegisterNotification_##name() \
591 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_ANNCE_COUNT) \
592 CHECK_MAX_COUNT(name, NOTIF_ANNCE_MAX, NOTIF_ANNCE_COUNT, "MSG_ANNCE") \
593 Create_Notification_Entity( \
594 /* COMMON ======================== */ \
595 default, /* var_default */ \
596 ACVNN(name), /* var_cvar */ \
597 MSG_ANNCE, /* typeId */ \
599 strtoupper(#name), /* namestring */ \
600 NO_MSG, /* strnum */ \
601 NO_MSG, /* flnum */ \
602 /* ANNCE ============= */ \
603 channel, /* channel */ \
606 position, /* position */ \
607 /* INFO & CENTER == */ \
615 /* MULTI ============= */ \
616 NO_MSG, /* anncename */ \
617 NO_MSG, /* infoname */ \
618 NO_MSG, /* centername */ \
619 /* MSG_CHOICE ========== */ \
620 NO_MSG, /* challow_def */ \
621 NO_MSG, /* challow_var */ \
622 NO_MSG, /* chtype */ \
623 NO_MSG, /* optiona */ \
624 NO_MSG); /* optionb */ \
626 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
628 #define MSG_INFO_NOTIF(default,name,strnum,flnum,args,hudargs,icon,normal,gentle) \
629 NOTIF_ADD_AUTOCVAR(name, default) \
631 void RegisterNotification_##name() \
633 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
634 CHECK_MAX_COUNT(name, NOTIF_INFO_MAX, NOTIF_INFO_COUNT, "MSG_INFO") \
635 Create_Notification_Entity( \
636 /* COMMON ======================== */ \
637 default, /* var_default */ \
638 ACVNN(name), /* var_cvar */ \
639 MSG_INFO, /* typeId */ \
641 strtoupper(#name), /* namestring */ \
642 strnum, /* strnum */ \
644 /* ANNCE =========== */ \
645 NO_MSG, /* channel */ \
648 NO_MSG, /* position */ \
649 /* INFO & CENTER === */ \
651 hudargs, /* hudargs */ \
655 normal, /* normal */ \
656 gentle, /* gentle */ \
657 /* MULTI ============= */ \
658 NO_MSG, /* anncename */ \
659 NO_MSG, /* infoname */ \
660 NO_MSG, /* centername */ \
661 /* CHOICE ============== */ \
662 NO_MSG, /* challow_def */ \
663 NO_MSG, /* challow_var */ \
664 NO_MSG, /* chtype */ \
665 NO_MSG, /* optiona */ \
666 NO_MSG); /* optionb */ \
668 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
670 .string nent_iconargs;
671 #define MULTIICON_INFO(default,name,strnum,flnum,args,hudargs,iconargs,icon,normal,gentle) \
672 NOTIF_ADD_AUTOCVAR(name, default) \
674 void RegisterNotification_##name() \
676 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
677 CHECK_MAX_COUNT(name, NOTIF_INFO_MAX, NOTIF_INFO_COUNT, "MSG_INFO") \
678 Create_Notification_Entity( \
679 /* COMMON ======================== */ \
680 default, /* var_default */ \
681 ACVNN(name), /* var_cvar */ \
682 MSG_INFO, /* typeid */ \
684 strtoupper(#name), /* namestring */ \
685 strnum, /* strnum */ \
687 /* ANNCE =========== */ \
688 NO_MSG, /* channel */ \
691 NO_MSG, /* position */ \
692 /* INFO & CENTER === */ \
694 hudargs, /* hudargs */ \
698 normal, /* normal */ \
699 gentle, /* gentle */ \
700 /* MULTI ============= */ \
701 NO_MSG, /* anncename */ \
702 NO_MSG, /* infoname */ \
703 NO_MSG, /* centername */ \
704 /* CHOICE ============== */ \
705 NO_MSG, /* challow_def */ \
706 NO_MSG, /* challow_var */ \
707 NO_MSG, /* chtype */ \
708 NO_MSG, /* optiona */ \
709 NO_MSG); /* optionb */ \
710 msg_info_notifs[name - 1].nent_iconargs = iconargs; \
712 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
714 #define MSG_CENTER_NOTIF(default,name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
715 NOTIF_ADD_AUTOCVAR(name, default) \
717 void RegisterNotification_##name() \
719 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CENTER_COUNT) \
720 CHECK_MAX_COUNT(name, NOTIF_CENTER_MAX, NOTIF_CENTER_COUNT, "MSG_CENTER") \
721 Create_Notification_Entity( \
722 /* COMMON ======================== */ \
723 default, /* var_default */ \
724 ACVNN(name), /* var_cvar */ \
725 MSG_CENTER, /* typeId */ \
727 strtoupper(#name), /* namestring */ \
728 strnum, /* strnum */ \
730 /* ANNCE =========== */ \
731 NO_MSG, /* channel */ \
734 NO_MSG, /* position */ \
735 /* INFO & CENTER == */ \
740 durcnt, /* durcnt */ \
741 normal, /* normal */ \
742 gentle, /* gentle */ \
743 /* MULTI ============= */ \
744 NO_MSG, /* anncename */ \
745 NO_MSG, /* infoname */ \
746 NO_MSG, /* centername */ \
747 /* CHOICE ============== */ \
748 NO_MSG, /* challow_def */ \
749 NO_MSG, /* challow_var */ \
750 NO_MSG, /* chtype */ \
751 NO_MSG, /* optiona */ \
752 NO_MSG); /* optionb */ \
754 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
756 #define MSG_MULTI_NOTIF(default,name,anncename,infoname,centername) \
757 NOTIF_ADD_AUTOCVAR(name, default) \
759 void RegisterNotification_##name() \
761 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_MULTI_COUNT) \
762 CHECK_MAX_COUNT(name, NOTIF_MULTI_MAX, NOTIF_MULTI_COUNT, "MSG_MULTI") \
763 Create_Notification_Entity( \
764 /* COMMON ======================== */ \
765 default, /* var_default */ \
766 ACVNN(name), /* var_cvar */ \
767 MSG_MULTI, /* typeId */ \
769 strtoupper(#name), /* namestring */ \
770 NO_MSG, /* strnum */ \
771 NO_MSG, /* flnum */ \
772 /* ANNCE =========== */ \
773 NO_MSG, /* channel */ \
776 NO_MSG, /* position */ \
777 /* INFO & CENTER == */ \
785 /* MULTI ================= */ \
786 anncename, /* anncename */ \
787 infoname, /* infoname */ \
788 centername, /* centername */ \
789 /* CHOICE ============== */ \
790 NO_MSG, /* challow_def */ \
791 NO_MSG, /* challow_var */ \
792 NO_MSG, /* chtype */ \
793 NO_MSG, /* optiona */ \
794 NO_MSG); /* optionb */ \
796 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
798 #define ACVNN(name) autocvar_notification_##name
800 #define MSG_CHOICE_NOTIF(default,challow,name,chtype,optiona,optionb) \
801 NOTIF_ADD_AUTOCVAR(name, default) \
802 NOTIF_ADD_AUTOCVAR(name##_ALLOWED, challow) \
804 void RegisterNotification_##name() \
806 SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CHOICE_COUNT) \
807 CHECK_MAX_COUNT(name, NOTIF_CHOICE_MAX, NOTIF_CHOICE_COUNT, "MSG_CHOICE") \
808 Create_Notification_Entity( \
809 /* COMMON ======================== */ \
810 default, /* var_default */ \
811 ACVNN(name), /* var_cvar */ \
812 MSG_CHOICE, /* typeId */ \
814 strtoupper(#name), /* namestring */ \
815 NO_MSG, /* strnum */ \
816 NO_MSG, /* flnum */ \
817 /* ANNCE =========== */ \
818 NO_MSG, /* channel */ \
821 NO_MSG, /* position */ \
822 /* INFO & CENTER == */ \
830 /* MULTI ============= */ \
831 NO_MSG, /* anncename */ \
832 NO_MSG, /* infoname */ \
833 NO_MSG, /* centername */ \
834 /* CHOICE ============================================= */ \
835 challow, /* challow_def */ \
836 autocvar_notification_##name##_ALLOWED, /* challow_var */ \
837 chtype, /* chtype */ \
838 optiona, /* optiona */ \
839 optionb); /* optionb */ \
841 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
843 void RegisterNotifications_First()
845 notif_global_error = false;
848 #define dedi (server_is_dedicated ? "a dedicated " : "")
853 LOG_INFOF("Beginning notification initialization on %s%s program...\n", dedi, PROGNAME);
856 // maybe do another implementation of this with checksums? for now, we don't need versioning
857 /*if(autocvar_notification_version != NOTIF_VERSION)
860 if(autocvar_notification_version_mismatch_client_error)
862 if(autocvar_notification_version_mismatch_server_error)
864 notif_global_error = true;
866 printf("^1NOTIFICATION VERSION MISMATCH: ^7program = %s, config = %d, code = %d.\n",
867 PROGNAME, autocvar_notification_version, NOTIF_VERSION);
871 void RegisterNotifications_Done()
873 if(notif_global_error)
875 // shit happened... stop the loading of the program now if this is unacceptable
876 if(autocvar_notification_errors_are_fatal)
877 error("Notification initialization failed! Read above and fix the errors!\n");
879 LOG_INFO("Notification initialization failed! Read above and fix the errors!\n");
881 else { LOG_INFO("Notification initialization successful!\n"); }
884 // NOW we actually activate the declarations
885 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_First)
886 #include "notifications.inc"
887 ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_Done)