]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/notifications.qh
Notifications: strong references
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / notifications.qh
index ff5d85c2a3b178a05731e72125e018d76218a277..4df13ac90b25606ee884a27591e55f92a7ce6df7 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef NOTIFICATIONS_H
 #define NOTIFICATIONS_H
 
-#include "command/all.qh"
+#include <common/command/all.qh>
 
 #include "constants.qh"
 #include "teams.qh"
@@ -20,9 +20,16 @@ const int MSG_CENTER_CPID = 4; // Kill centerprint message
 const int MSG_MULTI = 5; // Subcall MSG_INFO and/or MSG_CENTER notifications
 const int MSG_CHOICE = 6; // Choose which subcall wrapper to activate
 
+typedef entity Notification;
+
 // negative confirmations
-const int NO_MSG = -12345;  // allows various things to know when no information is added
-const int NOTIF_ABORT = -1234;   // allows Send_Notification to safely abort sending
+/** allows various things to know when no information is added */
+Notification NO_MSG;
+STATIC_INIT(NO_MSG) { NO_MSG = new(Notification); }
+const int NO_MSG_ = -12345;
+/** allows Send_Notification to safely abort sending */
+Notification NOTIF_ABORT;
+STATIC_INIT(NOTIF_ABORT) { NOTIF_ABORT = new(Notification); }
 
 #define EIGHT_VARS_TO_VARARGS_VARLIST \
     VARITEM(1, 0, s1) \
@@ -50,38 +57,53 @@ const int NOTIF_ABORT = -1234;   // allows Send_Notification to safely abort sen
     VARITEM(3, 4, XPD(s1, s2, s3, f1, f2, f3, f4)) \
     VARITEM(4, 4, XPD(s1, s2, s3, s4, f1, f2, f3, f4))
 
-void Destroy_All_Notifications(void);
-void Create_Notification_Entity(
+void Destroy_All_Notifications();
+void Create_Notification_Entity(entity notif,
     float var_default,
     float var_cvar,
     float typeId,
     float nameid,
-    string namestring,
-    int strnum,
-    int flnum,
-    /* MSG_ANNCE */
-    float channel,
-    string snd,
-    float vol,
-    float position,
-    /* MSG_INFO & MSG_CENTER */
-    string args,
-    string hudargs,
-    string icon,
-    float cpid,
-    string durcnt,
-    string normal,
-    string gentle,
-    /* MSG_MULTI */
-    float anncename,
-    float infoname,
-    float centername,
-    /* MSG_CHOICE */
-    float challow_def,
-    float challow_var,
-    float chtype,
-    float optiona,
-    float optionb);
+    string namestring);
+void Create_Notification_Entity_Annce(entity notif,
+                                       float var_cvar,
+                                       string namestring,
+                                       /* MSG_ANNCE */
+                                       float channel,
+                                       string snd,
+                                       float vol,
+                                       float position);
+
+void Create_Notification_Entity_InfoCenter(entity notif,
+                                               float var_cvar,
+                                               string namestring,
+                                               int strnum,
+                                               int flnum,
+                                               /* MSG_INFO & MSG_CENTER */
+                                               string args,
+                                               string hudargs,
+                                               string icon,
+                                               float cpid,
+                                               string durcnt,
+                                               string normal,
+                                               string gentle);
+
+void Create_Notification_Entity_Multi(entity notif,
+                                       float var_cvar,
+                                       string namestring,
+                                       /* MSG_MULTI */
+                                       Notification anncename,
+                                       Notification infoname,
+                                       Notification centername);
+
+void Create_Notification_Entity_Choice(entity notif,
+                                               float var_cvar,
+                                               string namestring,
+                                               /* MSG_CHOICE */
+                                               float challow_def,
+                                               float challow_var,
+                                               int chtype,
+                                               Notification optiona,
+                                               Notification optionb);
 
 void Dump_Notifications(float fh, float alsoprint);
 
@@ -140,43 +162,44 @@ GENERIC_COMMAND(dumpnotifs, "Dump all notifications into notifications_dump.txt"
 void Debug_Notification(string input);
 #endif
 
-void Local_Notification(int net_type, int net_name, ...count);
+void Local_Notification(int net_type, Notification net_name, ...count);
 void Local_Notification_WOVA(
-    float net_type, float net_name,
+    float net_type, Notification net_name,
     float stringcount, float floatcount,
     string s1, string s2, string s3, string s4,
     float f1, float f2, float f3, float f4);
 
 #ifdef CSQC // CLIENT ONLY
-void Read_Notification(float is_new);
 string prev_soundfile;
 float prev_soundtime;
 #endif
 
 #ifdef SVQC // SERVER ONLY
-const float NOTIF_ONE = 1;
-const float NOTIF_ONE_ONLY = 2;
-const float NOTIF_TEAM = 3;
-const float NOTIF_TEAM_EXCEPT = 4;
-const float NOTIF_ALL = 5;
-const float NOTIF_ALL_EXCEPT = 6;
+ENUMCLASS(NOTIF)
+    CASE(NOTIF, ONE)
+    CASE(NOTIF, ONE_ONLY)
+    CASE(NOTIF, TEAM)
+    CASE(NOTIF, TEAM_EXCEPT)
+    CASE(NOTIF, ALL)
+    CASE(NOTIF, ALL_EXCEPT)
+ENUMCLASS_END(NOTIF)
 
 void Kill_Notification(
-    float broadcast, entity client,
+    NOTIF broadcast, entity client,
     float net_type, float net_name);
 void Send_Notification(
-    float broadcast, entity client,
-    float net_type, float net_name,
+    NOTIF broadcast, entity client,
+    float net_type, Notification net_name,
     ...count);
 void Send_Notification_WOVA(
-    float broadcast, entity client,
-    float net_type, float net_name,
+    NOTIF broadcast, entity client,
+    float net_type, Notification net_name,
     float stringcount, float floatcount,
     string s1, string s2, string s3, string s4,
     float f1, float f2, float f3, float f4);
 void Send_Notification_WOCOVA(
-    float broadcast, entity client,
-    float net_type, float net_name,
+    NOTIF broadcast, entity client,
+    float net_type, Notification net_name,
     string s1, string s2, string s3, string s4,
     float f1, float f2, float f3, float f4);
 #endif
@@ -203,7 +226,7 @@ float autocvar_notification_debug = false;
 
 #ifdef SVQC
 .float FRAG_VERBOSE;
-void Notification_GetCvars(void);
+void Notification_GetCvars();
 float autocvar_notification_server_allows_location = 1; // 0 = no, 1 = yes
 #else
 float autocvar_notification_item_centerprinttime = 1.5;
@@ -245,6 +268,7 @@ float autocvar_notification_show_sprees_center_specialonly = true;
     f2primsec: f2 float primary or secondary selection for weapons
     f3primsec: f3 float primary or secondary selection for weapons
     f1secs: count_seconds of f1
+    f1points: point or points depending on f1
     f1ord: count_ordinal of f1
     f1time: process_time of f1
     f1race_time: mmssss of f1
@@ -285,6 +309,8 @@ const float ARG_DC = 6; // unique result to durcnt/centerprint
 // todo possible idea.... declare how many floats/strings each arg needs, and then dynamically increment the input
 // this way, we don't need to have duplicates like i.e. s2loc and s3loc?
 
+string BUFF_NAME(int i);
+
 #define NOTIF_ARGUMENT_LIST \
     ARG_CASE(ARG_CS_SV_HA,  "s1",            s1) \
     ARG_CASE(ARG_CS_SV_HA,  "s2",            s2) \
@@ -301,6 +327,7 @@ const float ARG_DC = 6; // unique result to durcnt/centerprint
     ARG_CASE(ARG_CS,        "f2primsec",     (f2 ? _("secondary") : _("primary"))) \
     ARG_CASE(ARG_CS,        "f3primsec",     (f3 ? _("secondary") : _("primary"))) \
     ARG_CASE(ARG_CS,        "f1secs",        count_seconds(f1)) \
+    ARG_CASE(ARG_CS,        "f1points",      (f1 == 1 ? _("point") : _("points"))) \
     ARG_CASE(ARG_CS_SV,     "f1ord",         count_ordinal(f1)) \
     ARG_CASE(ARG_CS,        "f1time",        process_time(2, f1)) \
     ARG_CASE(ARG_CS_SV_HA,  "f1race_time",   mmssss(f1)) \
@@ -317,9 +344,9 @@ const float ARG_DC = 6; // unique result to durcnt/centerprint
     ARG_CASE(ARG_CS_SV,     "spree_inf",     (autocvar_notification_show_sprees ? notif_arg_spree_inf(1, input, s2, f2) : "")) \
     ARG_CASE(ARG_CS_SV,     "spree_end",     (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
     ARG_CASE(ARG_CS_SV,     "spree_lost",    (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
-    ARG_CASE(ARG_CS_SV,     "item_wepname",  WEP_NAME(f1)) \
-    ARG_CASE(ARG_CS_SV,     "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buffs[f1].m_color), Buffs[f1].m_prettyName)) \
-    ARG_CASE(ARG_CS_SV,     "f3buffname",    sprintf("%s%s", rgb_to_hexcolor(Buffs[f3].m_color), Buffs[f3].m_prettyName)) \
+    ARG_CASE(ARG_CS_SV,     "item_wepname",  Weapons_from(f1).m_name) \
+    ARG_CASE(ARG_CS_SV,     "item_buffname", BUFF_NAME(f1)) \
+    ARG_CASE(ARG_CS_SV,     "f3buffname",    BUFF_NAME(f3)) \
     ARG_CASE(ARG_CS_SV,     "item_wepammo",  (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
     ARG_CASE(ARG_DC,        "item_centime",  ftos(autocvar_notification_item_centerprinttime)) \
     ARG_CASE(ARG_SV,        "death_team",    Team_ColoredFullName(f1)) \
@@ -327,9 +354,9 @@ const float ARG_DC = 6; // unique result to durcnt/centerprint
     ARG_CASE(ARG_CS_SV_HA,  "minigame1_name",find(world,netname,s1).descriptor.message) \
     ARG_CASE(ARG_CS_SV_HA,  "minigame1_d",   find(world,netname,s1).descriptor.netname)
 
-#define NOTIF_HIT_MAX(count,funcname) do { \
+#define NOTIF_HIT_MAX(count,funcname) MACRO_BEGIN { \
     if(sel_num == count) { backtrace(sprintf("%s: Hit maximum arguments!\n", funcname)); break; } \
-} while(0)
+} MACRO_END
 #define NOTIF_HIT_UNKNOWN(token,funcname) { backtrace(sprintf("%s: Hit unknown token in selected string! '%s'\n", funcname, selected)); break; }
 
 #define KILL_SPREE_LIST \
@@ -344,7 +371,7 @@ const float ARG_DC = 6; // unique result to durcnt/centerprint
 #ifdef CSQC
 string notif_arg_frag_ping(float newline, float fping)
 {
-    if(fping == NO_MSG)
+    if(fping == NO_MSG_)
         return sprintf(CCR(_("%s(^F1Bot^BG)")), (newline ? "\n" : " "));
     else
         return sprintf(CCR(_("%s(Ping ^F1%d^BG)")), (newline ? "\n" : " "), fping);
@@ -574,11 +601,11 @@ float NOTIF_MULTI_COUNT;
 float NOTIF_CHOICE_COUNT;
 
 // notification limits -- INCREASE AS NECESSARY
-const float NOTIF_ANNCE_MAX   = 200;
-const float NOTIF_INFO_MAX    = 350;
-const float NOTIF_CENTER_MAX  = 250;
-const float NOTIF_MULTI_MAX   = 200;
-const float NOTIF_CHOICE_MAX  = 30;
+const float NOTIF_ANNCE_MAX   = 400;
+const float NOTIF_INFO_MAX    = 450;
+const float NOTIF_CENTER_MAX  = 350;
+const float NOTIF_MULTI_MAX   = 300;
+const float NOTIF_CHOICE_MAX  = 50;
 
 // notification entities
 entity msg_annce_notifs[NOTIF_ANNCE_MAX];
@@ -622,7 +649,9 @@ entity msg_choice_notifs[NOTIF_CHOICE_MAX];
 .entity nent_optionb;
 
 // networked notification entity values
-.float nent_broadcast;
+#ifdef SVQC
+.NOTIF nent_broadcast;
+#endif
 .entity nent_client;
 .float nent_net_type;
 .float nent_net_name;
@@ -632,259 +661,134 @@ entity msg_choice_notifs[NOTIF_CHOICE_MAX];
 // other notification properties
 .float msg_choice_choices[NOTIF_CHOICE_MAX]; // set on each player containing MSG_CHOICE choices
 
+#define ACVNN(name) autocvar_notification_##name
+
 // initialization error detection
 float notif_error;
 float notif_global_error;
 
-#define MSG_ANNCE_NOTIF(default,name,channel,sound,volume,position) \
+#define MSG_ANNCE_NOTIF(name, default, sound, channel, volume, position) \
+    MSG_ANNCE_NOTIF_(ANNCE_##name, default, sound, channel, volume, position)
+#define MSG_ANNCE_NOTIF_(name, default, sound, channel, volume, position) \
     NOTIF_ADD_AUTOCVAR(name, default) \
-    float name; \
+    Notification name; \
     void RegisterNotification_##name() \
     { \
-        SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_ANNCE_COUNT) \
-        CHECK_MAX_COUNT(name, NOTIF_ANNCE_MAX, NOTIF_ANNCE_COUNT, "MSG_ANNCE") \
-        Create_Notification_Entity( \
-            /* COMMON ======================== */ \
-            default,            /* var_default */ \
-            ACVNN(name),        /* var_cvar    */ \
-            MSG_ANNCE,          /* typeId      */ \
-            name,               /* nameid      */ \
-            strtoupper(#name),  /* namestring  */ \
-            NO_MSG,             /* strnum      */ \
-            NO_MSG,             /* flnum       */ \
-            /* ANNCE ============= */ \
+        int name##_ = 0; \
+        SET_FIELD_COUNT(name##_, NOTIF_FIRST, NOTIF_ANNCE_COUNT) \
+        CHECK_MAX_COUNT(name##_, NOTIF_ANNCE_MAX, NOTIF_ANNCE_COUNT, "MSG_ANNCE") \
+        entity this = name = msg_annce_notifs[name##_ - 1] = new_pure(msg_annce_notification); \
+        Create_Notification_Entity      (this, default, ACVNN(name), MSG_ANNCE, name##_, strtoupper(#name)); \
+        Create_Notification_Entity_Annce(this, ACVNN(name), strtoupper(#name), \
             channel,   /* channel  */ \
             sound,     /* snd      */ \
             volume,    /* vol      */ \
-            position,  /* position */ \
-            /* INFO & CENTER == */ \
-            "",      /* args    */ \
-            "",      /* hudargs */ \
-            "",      /* icon    */ \
-            NO_MSG,  /* cpid    */ \
-            "",      /* durcnt  */ \
-            "",      /* normal  */ \
-            "",      /* gentle  */ \
-            /* MULTI ============= */ \
-            NO_MSG,  /* anncename  */ \
-            NO_MSG,  /* infoname   */ \
-            NO_MSG,  /* centername */ \
-            /* MSG_CHOICE ========== */ \
-            NO_MSG,   /* challow_def */ \
-            NO_MSG,   /* challow_var */ \
-            NO_MSG,   /* chtype      */ \
-            NO_MSG,   /* optiona     */ \
-            NO_MSG);  /* optionb     */ \
+            position); /* position */ \
     } \
     ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
-#define MSG_INFO_NOTIF(default,name,strnum,flnum,args,hudargs,icon,normal,gentle) \
+#define MSG_INFO_NOTIF(name, default, strnum, flnum, args, hudargs, icon, normal, gentle) \
+    MSG_INFO_NOTIF_(INFO_##name, default, strnum, flnum, args, hudargs, icon, normal, gentle)
+#define MSG_INFO_NOTIF_(name, default, strnum, flnum, args, hudargs, icon, normal, gentle) \
     NOTIF_ADD_AUTOCVAR(name, default) \
-    int name; \
+    Notification name; \
     void RegisterNotification_##name() \
     { \
-        SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
-        CHECK_MAX_COUNT(name, NOTIF_INFO_MAX, NOTIF_INFO_COUNT, "MSG_INFO") \
-        Create_Notification_Entity( \
-            /* COMMON ======================== */ \
-            default,            /* var_default */ \
-            ACVNN(name),        /* var_cvar    */ \
-            MSG_INFO,           /* typeId      */ \
-            name,               /* nameid      */ \
-            strtoupper(#name),  /* namestring  */ \
-            strnum,             /* strnum      */ \
-            flnum,              /* flnum       */ \
-            /* ANNCE =========== */ \
-            NO_MSG,  /* channel  */ \
-            "",      /* snd      */ \
-            NO_MSG,  /* vol      */ \
-            NO_MSG,  /* position */ \
-            /* INFO & CENTER === */ \
+        int name##_ = 0; \
+        SET_FIELD_COUNT(name##_, NOTIF_FIRST, NOTIF_INFO_COUNT) \
+        CHECK_MAX_COUNT(name##_, NOTIF_INFO_MAX, NOTIF_INFO_COUNT, "MSG_INFO") \
+        entity this = name = msg_info_notifs[name##_ - 1] = new_pure(msg_info_notification); \
+        Create_Notification_Entity           (this, default, ACVNN(name), MSG_INFO, name##_, strtoupper(#name)); \
+        Create_Notification_Entity_InfoCenter(this, ACVNN(name), strtoupper(#name), strnum, flnum, \
             args,     /* args    */ \
             hudargs,  /* hudargs */ \
             icon,     /* icon    */ \
-            NO_MSG  /* cpid    */ \
+            NO_MSG_,  /* cpid    */ \
             "",       /* durcnt  */ \
             normal,   /* normal  */ \
-            gentle,   /* gentle  */ \
-            /* MULTI ============= */ \
-            NO_MSG,  /* anncename  */ \
-            NO_MSG,  /* infoname   */ \
-            NO_MSG,  /* centername */ \
-            /* CHOICE ============== */ \
-            NO_MSG,   /* challow_def */ \
-            NO_MSG,   /* challow_var */ \
-            NO_MSG,   /* chtype      */ \
-            NO_MSG,   /* optiona     */ \
-            NO_MSG);  /* optionb     */ \
+            gentle);  /* gentle  */ \
     } \
     ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
 .string nent_iconargs;
-#define MULTIICON_INFO(default,name,strnum,flnum,args,hudargs,iconargs,icon,normal,gentle) \
+#define MULTIICON_INFO(name, default, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle) \
+    MULTIICON_INFO_(INFO_##name, default, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle)
+#define MULTIICON_INFO_(name, default, strnum, flnum, args, hudargs, iconargs, icon, normal, gentle) \
     NOTIF_ADD_AUTOCVAR(name, default) \
-    int name; \
+    Notification name; \
     void RegisterNotification_##name() \
     { \
-        SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
-        CHECK_MAX_COUNT(name, NOTIF_INFO_MAX, NOTIF_INFO_COUNT, "MSG_INFO") \
-        Create_Notification_Entity( \
-            /* COMMON ======================== */ \
-            default,            /* var_default */ \
-            ACVNN(name),        /* var_cvar    */ \
-            MSG_INFO,           /* typeid      */ \
-            name,               /* nameid      */ \
-            strtoupper(#name),  /* namestring  */ \
-            strnum,             /* strnum      */ \
-            flnum,              /* flnum       */ \
-            /* ANNCE =========== */ \
-            NO_MSG,  /* channel  */ \
-            "",      /* snd      */ \
-            NO_MSG,  /* vol      */ \
-            NO_MSG,  /* position */ \
-            /* INFO & CENTER === */ \
+        int name##_ = 0; \
+        SET_FIELD_COUNT(name##_, NOTIF_FIRST, NOTIF_INFO_COUNT) \
+        CHECK_MAX_COUNT(name##_, NOTIF_INFO_MAX, NOTIF_INFO_COUNT, "MSG_INFO") \
+        entity this = name = msg_info_notifs[name##_ - 1] = new_pure(msg_info_notification); \
+        Create_Notification_Entity           (this, default, ACVNN(name), MSG_INFO, name##_, strtoupper(#name)); \
+        Create_Notification_Entity_InfoCenter(this, ACVNN(name), strtoupper(#name), strnum, flnum, \
             args,     /* args    */ \
             hudargs,  /* hudargs */ \
             icon,     /* icon    */ \
-            NO_MSG  /* cpid    */ \
+            NO_MSG_,  /* cpid    */ \
             "",       /* durcnt  */ \
             normal,   /* normal  */ \
-            gentle,   /* gentle  */ \
-            /* MULTI ============= */ \
-            NO_MSG,  /* anncename  */ \
-            NO_MSG,  /* infoname   */ \
-            NO_MSG,  /* centername */ \
-            /* CHOICE ============== */ \
-            NO_MSG,   /* challow_def */ \
-            NO_MSG,   /* challow_var */ \
-            NO_MSG,   /* chtype      */ \
-            NO_MSG,   /* optiona     */ \
-            NO_MSG);  /* optionb     */ \
-        msg_info_notifs[name - 1].nent_iconargs = iconargs; \
+            gentle);  /* gentle  */ \
+        this.nent_iconargs = iconargs; \
     } \
     ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
-#define MSG_CENTER_NOTIF(default,name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
+#define MSG_CENTER_NOTIF(name, default, strnum, flnum, args, cpid, durcnt, normal, gentle) \
+    MSG_CENTER_NOTIF_(CENTER_##name, default, strnum, flnum, args, cpid, durcnt, normal, gentle)
+#define MSG_CENTER_NOTIF_(name, default, strnum, flnum, args, cpid, durcnt, normal, gentle) \
     NOTIF_ADD_AUTOCVAR(name, default) \
-    float name; \
+    Notification name; \
     void RegisterNotification_##name() \
     { \
-        SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CENTER_COUNT) \
-        CHECK_MAX_COUNT(name, NOTIF_CENTER_MAX, NOTIF_CENTER_COUNT, "MSG_CENTER") \
-        Create_Notification_Entity( \
-            /* COMMON ======================== */ \
-            default,            /* var_default */ \
-            ACVNN(name),        /* var_cvar    */ \
-            MSG_CENTER,         /* typeId      */ \
-            name,               /* nameid      */ \
-            strtoupper(#name),  /* namestring  */ \
-            strnum,             /* strnum      */ \
-            flnum,              /* flnum       */ \
-            /* ANNCE =========== */ \
-            NO_MSG,  /* channel  */ \
-            "",      /* snd      */ \
-            NO_MSG,  /* vol      */ \
-            NO_MSG,  /* position */ \
-            /* INFO & CENTER == */ \
+        int name##_ = 0; \
+        SET_FIELD_COUNT(name##_, NOTIF_FIRST, NOTIF_CENTER_COUNT) \
+        CHECK_MAX_COUNT(name##_, NOTIF_CENTER_MAX, NOTIF_CENTER_COUNT, "MSG_CENTER") \
+        entity this = name = msg_center_notifs[name##_ - 1] = new_pure(msg_center_notification); \
+        Create_Notification_Entity           (this, default, ACVNN(name), MSG_CENTER, name##_, strtoupper(#name)); \
+        Create_Notification_Entity_InfoCenter(this, ACVNN(name), strtoupper(#name), strnum, flnum, \
             args,    /* args    */ \
             "",      /* hudargs */ \
             "",      /* icon    */ \
             cpid,    /* cpid    */ \
             durcnt,  /* durcnt  */ \
             normal,  /* normal  */ \
-            gentle,  /* gentle  */ \
-            /* MULTI ============= */ \
-            NO_MSG,  /* anncename  */ \
-            NO_MSG,  /* infoname   */ \
-            NO_MSG,  /* centername */ \
-            /* CHOICE ============== */ \
-            NO_MSG,   /* challow_def */ \
-            NO_MSG,   /* challow_var */ \
-            NO_MSG,   /* chtype      */ \
-            NO_MSG,   /* optiona     */ \
-            NO_MSG);  /* optionb     */ \
+            gentle); /* gentle  */ \
     } \
     ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
-#define MSG_MULTI_NOTIF(default,name,anncename,infoname,centername) \
+#define MSG_MULTI_NOTIF(name, default, anncename, infoname, centername) \
     NOTIF_ADD_AUTOCVAR(name, default) \
-    int name; \
+    Notification name; \
     void RegisterNotification_##name() \
     { \
-        SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_MULTI_COUNT) \
-        CHECK_MAX_COUNT(name, NOTIF_MULTI_MAX, NOTIF_MULTI_COUNT, "MSG_MULTI") \
-        Create_Notification_Entity( \
-            /* COMMON ======================== */ \
-            default,            /* var_default */ \
-            ACVNN(name),        /* var_cvar    */ \
-            MSG_MULTI,          /* typeId      */ \
-            name,               /* nameid      */ \
-            strtoupper(#name),  /* namestring  */ \
-            NO_MSG,             /* strnum      */ \
-            NO_MSG,             /* flnum       */ \
-            /* ANNCE =========== */ \
-            NO_MSG,  /* channel  */ \
-            "",      /* snd      */ \
-            NO_MSG,  /* vol      */ \
-            NO_MSG,  /* position */ \
-            /* INFO & CENTER == */ \
-            "",      /* args    */ \
-            "",      /* hudargs */ \
-            "",      /* icon    */ \
-            NO_MSG,  /* cpid    */ \
-            "",      /* durcnt  */ \
-            "",      /* normal  */ \
-            "",      /* gentle  */ \
-            /* MULTI ================= */ \
+        int name##_ = 0; \
+        SET_FIELD_COUNT(name##_, NOTIF_FIRST, NOTIF_MULTI_COUNT) \
+        CHECK_MAX_COUNT(name##_, NOTIF_MULTI_MAX, NOTIF_MULTI_COUNT, "MSG_MULTI") \
+        entity this = name = msg_multi_notifs[name##_ - 1] = new_pure(msg_multi_notification); \
+        Create_Notification_Entity      (this, default, ACVNN(name), MSG_MULTI, name##_, strtoupper(#name)); \
+        Create_Notification_Entity_Multi(this, ACVNN(name), strtoupper(#name), \
             anncename,   /* anncename  */ \
             infoname,    /* infoname   */ \
-            centername,  /* centername */ \
-            /* CHOICE ============== */ \
-            NO_MSG,   /* challow_def */ \
-            NO_MSG,   /* challow_var */ \
-            NO_MSG,   /* chtype      */ \
-            NO_MSG,   /* optiona     */ \
-            NO_MSG);  /* optionb     */ \
+            centername); /* centername */ \
     } \
     ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
-#define ACVNN(name) autocvar_notification_##name
-
-#define MSG_CHOICE_NOTIF(default,challow,name,chtype,optiona,optionb) \
+#define MSG_CHOICE_NOTIF(name, default, challow, chtype, optiona, optionb) \
+    MSG_CHOICE_NOTIF_(CHOICE_##name, default, challow, chtype, optiona, optionb)
+#define MSG_CHOICE_NOTIF_(name, default, challow, chtype, optiona, optionb) \
     NOTIF_ADD_AUTOCVAR(name, default) \
     NOTIF_ADD_AUTOCVAR(name##_ALLOWED, challow) \
-    float name; \
+    Notification name; \
     void RegisterNotification_##name() \
     { \
-        SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CHOICE_COUNT) \
-        CHECK_MAX_COUNT(name, NOTIF_CHOICE_MAX, NOTIF_CHOICE_COUNT, "MSG_CHOICE") \
-        Create_Notification_Entity( \
-            /* COMMON ======================== */ \
-            default,            /* var_default */ \
-            ACVNN(name),        /* var_cvar    */ \
-            MSG_CHOICE,         /* typeId      */ \
-            name,               /* nameid      */ \
-            strtoupper(#name),  /* namestring  */ \
-            NO_MSG,             /* strnum      */ \
-            NO_MSG,             /* flnum       */ \
-            /* ANNCE =========== */ \
-            NO_MSG,  /* channel  */ \
-            "",      /* snd      */ \
-            NO_MSG,  /* vol      */ \
-            NO_MSG,  /* position */ \
-            /* INFO & CENTER == */ \
-            "",      /* args    */ \
-            "",      /* hudargs */ \
-            "",      /* icon    */ \
-            NO_MSG,  /* cpid    */ \
-            "",      /* durcnt  */ \
-            "",      /* normal  */ \
-            "",      /* gentle  */ \
-            /* MULTI ============= */ \
-            NO_MSG,  /* anncename  */ \
-            NO_MSG,  /* infoname   */ \
-            NO_MSG,  /* centername */ \
-            /* CHOICE ============================================= */ \
+        int name##_ = 0; \
+        SET_FIELD_COUNT(name##_, NOTIF_FIRST, NOTIF_CHOICE_COUNT) \
+        CHECK_MAX_COUNT(name##_, NOTIF_CHOICE_MAX, NOTIF_CHOICE_COUNT, "MSG_CHOICE") \
+        entity this = name = msg_choice_notifs[name##_ - 1] = new_pure(msg_choice_notification); \
+        Create_Notification_Entity       (this, default, ACVNN(name), MSG_CHOICE, name##_, strtoupper(#name)); \
+        Create_Notification_Entity_Choice(this, ACVNN(name), strtoupper(#name), \
             challow,                                 /* challow_def */ \
             autocvar_notification_##name##_ALLOWED,  /* challow_var */ \
             chtype,                                  /* chtype      */ \
@@ -896,29 +800,6 @@ float notif_global_error;
 void RegisterNotifications_First()
 {
     notif_global_error = false;
-
-    #ifdef SVQC
-    #define dedi (server_is_dedicated ? "a dedicated " : "")
-    #else
-    #define dedi ""
-    #endif
-
-    LOG_INFOF("Beginning notification initialization on %s%s program...\n", dedi, PROGNAME);
-    #undef dedi
-
-    // maybe do another implementation of this with checksums? for now, we don't need versioning
-    /*if(autocvar_notification_version != NOTIF_VERSION)
-    {
-        #ifdef CSQC
-        if(autocvar_notification_version_mismatch_client_error)
-        #else
-        if(autocvar_notification_version_mismatch_server_error)
-        #endif
-            notif_global_error = true;
-
-        printf("^1NOTIFICATION VERSION MISMATCH: ^7program = %s, config = %d, code = %d.\n",
-            PROGNAME, autocvar_notification_version, NOTIF_VERSION);
-    }*/
 }
 
 void RegisterNotifications_Done()
@@ -927,11 +808,10 @@ void RegisterNotifications_Done()
     {
         // shit happened... stop the loading of the program now if this is unacceptable
         if(autocvar_notification_errors_are_fatal)
-            error("Notification initialization failed! Read above and fix the errors!\n");
+            LOG_FATAL("Notification initialization failed! Read above and fix the errors!\n");
         else
-            LOG_INFO("Notification initialization failed! Read above and fix the errors!\n");
+            LOG_SEVERE("Notification initialization failed! Read above and fix the errors!\n");
     }
-    else { LOG_INFO("Notification initialization successful!\n"); }
 }
 
 // NOW we actually activate the declarations