]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/notifications.qc
Make a separate "MSG_DEATH" notification category, cleans up stuff a bit
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / notifications.qc
index e8491da8452063832bb2e580464e2c9a7633c976..e0aab87a0469f745e82e6bc1b62182a19c763c85 100644 (file)
@@ -1,12 +1,13 @@
 // ================================================
 //  Unified notification system, written by Samual
 // ================================================
 //  Unified notification system, written by Samual
-//  Last updated: September, 2012
+//  Last updated: November, 2012
 // ================================================
 
 // main types/groups of notifications
 #define MSG_INFO 1 // "Global" information messages (sent to console, and notify panel if it has an icon)
 #define MSG_CENTER 2 // "Personal" centerprint messages
 #define MSG_WEAPON 3 // "Personal" weapon messages (like "You got the Nex", sent to weapon notify panel)
 // ================================================
 
 // main types/groups of notifications
 #define MSG_INFO 1 // "Global" information messages (sent to console, and notify panel if it has an icon)
 #define MSG_CENTER 2 // "Personal" centerprint messages
 #define MSG_WEAPON 3 // "Personal" weapon messages (like "You got the Nex", sent to weapon notify panel)
+#define MSG_DEATH 4 // "Personal" AND "Global" death messages 
 
 #define NO_STR_ARG ""
 #define NO_FL_ARG -12345
 
 #define NO_STR_ARG ""
 #define NO_FL_ARG -12345
 #define F_STRNUM 2
 #define F_FLNUM 3
 
 #define F_STRNUM 2
 #define F_FLNUM 3
 
-// allow sending of notifications to also pass through to spectators (specifically for centerprints)
-#ifdef SVQC
-#define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
-#define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
-#define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
-#endif
+#define BOT_PING -1
 
 
+// Since this is code uses macro processors to list notifications,
+// the normal compiler sees these checks as "constant" and throws
+// a warning. We have to get around this by using another function.
 #define NOTIF_MATCH(a,b) if(min(NOTIF_MAX, a) == b)
 #define NOTIF_MATCH(a,b) if(min(NOTIF_MAX, a) == b)
+
 #ifdef CSQC
 #ifdef CSQC
+/*
+ Acquire special information to generate for display in the
+ notification from variables networked to the client.
+ Macro descriptions:
+    PASS_KEY: find the keybind for "passing" or "dropping" in CTF game mode
+    FRAG_SPREE: find out if the player is on a kill spree/how many kills they have
+    FRAG_PING: show the ping of a player
+    FRAG_STATS: show health/armor/ping of a player
+    FRAG_POS: show score status and position in the match of a player
+    DEATH_TEAM: show the full name of the team a player is switching from
+*/
 string got_commandkey;
 string got_commandkey;
+#define PASS_KEY ((((got_commandkey = getcommandkey("pass", "+use")) != "pass") && !(strstrofs(got_commandkey, "not bound", 0) >= 0)) ? sprintf(CCR(_(" ^F1(Press %s)")), got_commandkey) : "")
+#define FRAG_SPREE (((f1 == 3) || (f1 == 5) || (f1 == 10) || (f1 == 15) || (f1 == 20) || (f1 == 25) || (f1 == 30)) ? sprintf(normal_or_gentle(_("%d kill spree! "), _("%d score spree! ")), f1) : "")
+#define FRAG_PING ((f2 != BOT_PING) ? sprintf(CCR(_("\n(Ping ^2%d^BG)")), f2) : "")
+#define FRAG_STATS sprintf(CCR(_("\n(Health ^1%d^BG / Armor ^2%d^BG)%s")), f1, f2, ((f3 != BOT_PING) ? sprintf(CCR(_(" (Ping ^2%d^BG)")), f3) : ""))
+//#define FRAG_POS ((Should_Print_Score_Pos(f1)) ? sprintf("\n^BG%s", Read_Score_Pos(f1)) : "")
+#define DEATH_TEAM Team_ColoredFullName(f1)
+
+// NO_CPID normally has a variable value, so we need to check and see
+// whether a notification uses it. If so, cancel out the centerprint ID.
+#define HANDLE_CPID(cpid) ((min(NOTIF_MAX, cpid) == NO_CPID) ? FALSE : cpid)
+
+// client-side handling of cvars
 #define ADD_CSQC_AUTOCVAR(name) var float autocvar_notification_##name = TRUE;
 #define ADD_CSQC_AUTOCVAR(name) var float autocvar_notification_##name = TRUE;
-var float autocvar_notification_ctf_capture_verbose = TRUE;
-var float autocvar_notification_ctf_pickup_team_verbose = TRUE;
-var float autocvar_notification_ctf_pickup_enemy_verbose = TRUE;
 #define CHECK_AUTOCVAR(name) if(autocvar_notification_##name)
 #define CHECK_AUTOCVAR(name) if(autocvar_notification_##name)
-#define HANDLE_CPID(cpid) ((min(NOTIF_MAX, cpid) == NO_CPID) ? FALSE : cpid)
-#define PASS_KEY ((((got_commandkey = getcommandkey("pass", "+use")) != "pass") && !(strstrofs(got_commandkey, "not bound", 0) >= 0)) ? sprintf(CCR(_(" ^F1(Press %s)")), got_commandkey) : "")
 #else
 #else
+
+// allow sending of notifications to also pass through to spectators (specifically for centerprints)
+#ifdef SVQC
+#define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
+#define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
+#define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
+#endif
+
+// do nothing for the other programs, they don't need cvars (those are just for the clients)
 #define ADD_CSQC_AUTOCVAR(name)
 #endif
 
 #define ADD_CSQC_AUTOCVAR(name)
 #endif
 
-string team_name_red = _("Red");
-string team_name_blue = _("Blue");
-string team_name_yellow = _("Yellow");
-string team_name_pink = _("Pink");
-string team_color_red = "^1";
-string team_color_blue = "^4";
-string team_color_yellow = "";
-string team_color_pink = "";
 
 
+/*
+       If BELOW negative maxplayers, you dropped a place lower
+       If below 0, you are tied for that place
+       If above 0, you are holding that place alone
+       If above positive maxplayers, you moved up a place
+* 
+float Should_Print_Score_Pos
+
+string Read_Score_Pos(float num)
+{
+       
+}
+
+float Form_Score_Pos(entity player)
+{
+       return 
+}*/
 
 // ====================================
 //  Notifications List and Information
 
 // ====================================
 //  Notifications List and Information
@@ -66,11 +102,13 @@ string team_color_pink = "";
     Normal message (string for sprintf when gentle messages are NOT enabled)
     Gentle message (string for sprintf when gentle messages ARE enabled)
 
     Normal message (string for sprintf when gentle messages are NOT enabled)
     Gentle message (string for sprintf when gentle messages ARE enabled)
 
- Messages have ^F1, ^F2, and ^BG in them-- these are replaced
- with colors according to the cvars the user has chosen.
-    ^F1 = highest priority, "primary"
-    ^F2 = next highest priority, "secondary"
-    ^BG = normal/less important priority, "tertiary"
+ Messages with ^F1, ^BG, ^TC, etc etc in them will replace those strings
+ with colors according to the cvars the user has chosen. This allows for
+ users to create unique color profiles for their HUD, giving more customization
+ options to HUD designers and end users who want such a feature.
+
+ Check out the function calls for string CCR(...) and
+ string TCR(...) to better understand how these codes work.
 
  Guidlines (please try and follow these):
     -ALWAYS start the string with a color, preferably background.
 
  Guidlines (please try and follow these):
     -ALWAYS start the string with a color, preferably background.
@@ -82,24 +120,25 @@ string team_color_pink = "";
      nothing too long for the name field... Abbreviations are your friend. :D
     -Keep the spacing as clean as possible... if the arguments are abnormally long,
       it's okay to go out of line a bit... but try and keep it clean still.
      nothing too long for the name field... Abbreviations are your friend. :D
     -Keep the spacing as clean as possible... if the arguments are abnormally long,
       it's okay to go out of line a bit... but try and keep it clean still.
-    -Keep the notifications in alphabetical order.
-    ARIRE unir frk jvgu lbhe bja zbgure. (gvc sbe zvxrrhfn) -- Don't pay attention to this ^_^
+    -Sort the notifications in the most appropriate order for their tasks.
+      TODO: ? centerprint IDs are given priority based on their order (first being highest priority going downwards)
+    -ARIRE unir frk jvgu lbhe bja zbgure. (gvc sbe zvxrrhfn) -- Don't pay attention to this ^_^
 */
 
 // weaponorder[f1].netname
 
 #define MULTITEAM_INFO(prefix,teams,strnum,flnum,args,hudargs,icon,normal,gentle) \
 */
 
 // weaponorder[f1].netname
 
 #define MULTITEAM_INFO(prefix,teams,strnum,flnum,args,hudargs,icon,normal,gentle) \
-       MSG_INFO_NOTIF(prefix##RED, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_red)), TCR(normal, team_color_red, strtoupper(team_name_red)), TCR(gentle, team_color_red, strtoupper(team_name_red))) \
-       MSG_INFO_NOTIF(prefix##BLUE, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_blue)), TCR(normal, team_color_blue, strtoupper(team_name_blue)), TCR(gentle, team_color_blue, strtoupper(team_name_blue))) \
+       MSG_INFO_NOTIF(prefix##RED, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_1)), TCR(normal, COL_TEAM_1, strtoupper(STR_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(STR_TEAM_1))) \
+       MSG_INFO_NOTIF(prefix##BLUE, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_2)), TCR(normal, COL_TEAM_2, strtoupper(STR_TEAM_2)), TCR(gentle, COL_TEAM_2, strtoupper(STR_TEAM_2))) \
        #if teams >= 3 \
        #if teams >= 3 \
-               MSG_INFO_NOTIF(prefix##YELLOW, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_yellow)), TCR(normal, team_color_yellow, strtoupper(team_name_yellow)), TCR(gentle, team_color_yellow, strtoupper(team_name_yellow))) \
+               MSG_INFO_NOTIF(prefix##YELLOW, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_3)), TCR(normal, COL_TEAM_3, strtoupper(STR_TEAM_3)), TCR(gentle, COL_TEAM_3, strtoupper(STR_TEAM_3))) \
        #endif \
        #if teams >= 4 \
        #endif \
        #if teams >= 4 \
-               MSG_INFO_NOTIF(prefix##PINK, strnum, flnum, args, hudargs, sprintf(icon, strtolower(team_name_pink)), TCR(normal, team_color_pink, strtoupper(team_name_pink)), TCR(gentle, team_color_pink, strtoupper(team_name_pink))) \
+               MSG_INFO_NOTIF(prefix##PINK, strnum, flnum, args, hudargs, sprintf(icon, strtolower(STR_TEAM_4)), TCR(normal, COL_TEAM_4, strtoupper(STR_TEAM_4)), TCR(gentle, COL_TEAM_4, strtoupper(STR_TEAM_4))) \
        #endif
 #define MSG_INFO_NOTIFICATIONS \
        MSG_INFO_NOTIF(INFO_EMPTY,                                                      0, 0, NO_STR_ARG, XPND2("", ""),                                        "", "", "") \
        #endif
 #define MSG_INFO_NOTIFICATIONS \
        MSG_INFO_NOTIF(INFO_EMPTY,                                                      0, 0, NO_STR_ARG, XPND2("", ""),                                        "", "", "") \
-       MULTITEAM_INFO(INFO_SCORES_, 2,                                         0, 0, NO_STR_ARG, XPND2("", ""),                                        "", _("^TC^TT ^BGteam scores!\n"), "") \
+       MULTITEAM_INFO(INFO_SCORES_, 4,                                         0, 0, NO_STR_ARG, XPND2("", ""),                                        "", _("^TC^TT ^BGteam scores!\n"), "") \
        MULTITEAM_INFO(INFO_CTF_FLAGRETURN_DROPPED_, 2,         0, 0, NO_STR_ARG, XPND2("", ""),                                        "", _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself\n"), "") \
        MULTITEAM_INFO(INFO_CTF_FLAGRETURN_DAMAGED_, 2,         0, 0, NO_STR_ARG, XPND2("", ""),                                        "", _("^BGThe ^TC^TT^BG flag was destroyed and returned to base\n"), "") \
        MULTITEAM_INFO(INFO_CTF_FLAGRETURN_SPEEDRUN_, 2,        0, 1, f1/100, XPND2("", ""),                                            "", _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself\n"), "") \
        MULTITEAM_INFO(INFO_CTF_FLAGRETURN_DROPPED_, 2,         0, 0, NO_STR_ARG, XPND2("", ""),                                        "", _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself\n"), "") \
        MULTITEAM_INFO(INFO_CTF_FLAGRETURN_DAMAGED_, 2,         0, 0, NO_STR_ARG, XPND2("", ""),                                        "", _("^BGThe ^TC^TT^BG flag was destroyed and returned to base\n"), "") \
        MULTITEAM_INFO(INFO_CTF_FLAGRETURN_SPEEDRUN_, 2,        0, 1, f1/100, XPND2("", ""),                                            "", _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself\n"), "") \
@@ -116,13 +155,13 @@ string team_color_pink = "";
        #undef MSG_INFO_NOTIF
 
 #define MULTITEAM_CENTER(prefix,teams,strnum,flnum,args,cpid,durcnt,normal,gentle) \
        #undef MSG_INFO_NOTIF
 
 #define MULTITEAM_CENTER(prefix,teams,strnum,flnum,args,cpid,durcnt,normal,gentle) \
-       MSG_CENTER_NOTIF(prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_red, strtoupper(team_name_red)), TCR(gentle, team_color_red, strtoupper(team_name_red))) \
-       MSG_CENTER_NOTIF(prefix##BLUE, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_blue, strtoupper(team_name_blue)), TCR(gentle, team_color_blue, strtoupper(team_name_blue))) \
+       MSG_CENTER_NOTIF(prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_1, strtoupper(STR_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(STR_TEAM_1))) \
+       MSG_CENTER_NOTIF(prefix##BLUE, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_2, strtoupper(STR_TEAM_2)), TCR(gentle, COL_TEAM_2, strtoupper(STR_TEAM_2))) \
        #if teams >= 3 \
        #if teams >= 3 \
-               MSG_CENTER_NOTIF(prefix##YELLOW, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_yellow, strtoupper(team_name_yellow)), TCR(gentle, team_color_yellow, strtoupper(team_name_yellow))) \
+               MSG_CENTER_NOTIF(prefix##YELLOW, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_3, strtoupper(STR_TEAM_3)), TCR(gentle, COL_TEAM_3, strtoupper(STR_TEAM_3))) \
        #endif \
        #if teams >= 4 \
        #endif \
        #if teams >= 4 \
-               MSG_CENTER_NOTIF(prefix##PINK, strnum, flnum, args, cpid, durcnt, TCR(normal, team_color_pink, strtoupper(team_name_pink)), TCR(gentle, team_color_pink, strtoupper(team_name_pink))) \
+               MSG_CENTER_NOTIF(prefix##PINK, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_4, strtoupper(STR_TEAM_4)), TCR(gentle, COL_TEAM_4, strtoupper(STR_TEAM_4))) \
        #endif
 #define MSG_CENTER_NOTIFICATIONS \
        MSG_CENTER_NOTIF(CENTER_EMPTY,                                                  0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), "", "") \
        #endif
 #define MSG_CENTER_NOTIFICATIONS \
        MSG_CENTER_NOTIF(CENTER_EMPTY,                                                  0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), "", "") \
@@ -149,6 +188,41 @@ string team_color_pink = "";
        MSG_WEAPON_NOTIF(DEATH_MARBLES_LOST3, 2, 1, XPND3(s1, s2, f1), _("^F1%s^BG lost their marbles against ^F1%s^BG using the ^F2%s^BG\n"), "") \
        #undef MSG_WEAPON_NOTIF
 
        MSG_WEAPON_NOTIF(DEATH_MARBLES_LOST3, 2, 1, XPND3(s1, s2, f1), _("^F1%s^BG lost their marbles against ^F1%s^BG using the ^F2%s^BG\n"), "") \
        #undef MSG_WEAPON_NOTIF
 
+#define MSG_DEATH_NOTIFICATIONS \
+       MSG_DEATH_NOTIF(DEATH_SELF_CUSTOM,                                              2, 0, XPND2(s1, s2),                    NO_CPID,                                XPND2(0, 0), _("^K1You were %s, %s"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_GENERIC,                                             0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1Watch your step!"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_SELFKILL,                                    0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You killed your own dumb self!"), _("^K1You need to be more careful!")) \
+       MSG_DEATH_NOTIF(DEATH_SELF_SUICIDE,                                             0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You committed suicide!"), _("^K1You ended it all!")) \
+       MSG_DEATH_NOTIF(DEATH_SELF_NOAMMO,                                              0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You were killed for running out of ammo..."), _("^K1You are reinserted into the game for running out of ammo...")) \
+       MSG_DEATH_NOTIF(DEATH_SELF_ROT,                                                 0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You grew too old without taking your medicine"), _("^K1You need to preserve your health")) \
+       MSG_DEATH_NOTIF(DEATH_SELF_CAMP,                                                0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1Die camper!"), _("^K1Reconsider your tactics, camper!")) \
+       MSG_DEATH_NOTIF(DEATH_SELF_BETRAYAL,                                    0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1Don't shoot your team mates!"), _("^K1Don't go against your team mates!")) \
+       MSG_DEATH_NOTIF(DEATH_SELF_TEAMCHANGE,                                  0, 1, DEATH_TEAM,                               NO_CPID,                                XPND2(0, 0), _("^BGYou are now on: %s"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_AUTOTEAMCHANGE,                              0, 1, DEATH_TEAM,                               NO_CPID,                                XPND2(0, 0), _("^BGYou have been moved into a different team to improve team balance\nYou are now on: %s"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_FALL,                                                0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You hit the ground with a bit too much force"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_DROWN,                                               0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You couldn't catch your breath in time!"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_LAVA,                                                0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You couldn't stand the heat!"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_SLIME,                                               0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You melted away in slime!"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_SHOOTING_STAR,                               0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You went faster than the speed of light!"), "") \
+       MSG_DEATH_NOTIF(DEATH_SELF_SWAMP,                                               0, 0, NO_STR_ARG,                               NO_CPID,                                XPND2(0, 0), _("^K1You got stuck in a swamp!"), "") \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAG,                                              1, 1, XPND2(FRAG_SPREE, s1),                                                    NO_CPID, XPND2(0, 0), _("^K3%sYou fragged ^BG%s"), _("^K3%sYou scored against ^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAGGED,                                   1, 0, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1You were fragged by ^BG%s"), _("^K1You were scored against by ^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAG,                                  1, 1, XPND2(FRAG_SPREE, s1),                                                    NO_CPID, XPND2(0, 0), _("^K1%sYou typefragged ^BG%s"), _("^K1%sYou scored against ^BG%s^K1 while they were typing")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAGGED,                               1, 0, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1You were typefragged by ^BG%s"), _("^K1You were scored against by ^BG%s^K1 while typing!")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAG_FIRST,                                1, 0, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K3First blood! You fragged ^BG%s"), _("^K3First score! You scored against ^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAGGED_FIRST,                             1, 0, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1First victim! You were fragged by ^BG%s"), _("^K1First casualty! You were scored against by ^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAG_FIRST,                    1, 0, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1First blood! You typefragged ^BG%s"), _("^K1First score! You scored against ^BG%s^K1 while they were typing")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAGGED_FIRST,                 1, 0, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1First victim! You were typefragged by ^BG%s"), _("^K1First casualty! You were scored against by ^BG%s^K1 while typing!")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAG_VERBOSE,                              1, 2, XPND3(FRAG_SPREE, s1, FRAG_PING),                                 NO_CPID, XPND2(0, 0), _("^K3You fragged ^BG%s^BG%s"), _("^K3You scored against ^BG%s^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAGGED_VERBOSE,                   1, 3, XPND2(s1, FRAG_STATS),                                                    NO_CPID, XPND2(0, 0), _("^K1You were fragged by ^BG%s^BG%s"), _("^K1You were scored against by ^BG%s^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAG_VERBOSE,                  1, 2, XPND3(FRAG_SPREE, s1, FRAG_PING),                                 NO_CPID, XPND2(0, 0), _("^K1You typefragged ^BG%s^BG%s"), _("^K1You scored against ^BG%s^K1 while they were typing^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAGGED_VERBOSE,               1, 3, XPND2(s1, FRAG_STATS),                                                    NO_CPID, XPND2(0, 0), _("^K1You were typefragged by ^BG%s^BG%s"), _("^K1You were scored against by ^BG%s^K1 while typing^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAG_FIRST_VERBOSE,                1, 1, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K3First blood! You fragged ^BG%s"), _("^K3First score! You scored against ^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_FRAGGED_FIRST_VERBOSE,             1, 3, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1First victim! You were fragged by ^BG%s"), _("^K1First casualty! You were scored against by ^BG%s")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAG_FIRST_VERBOSE,    1, 1, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1First blood! You typefragged ^BG%s"), _("^K1First score! You scored against ^BG%s^K1 while they were typing")) \
+       MSG_DEATH_NOTIF(DEATH_MURDER_TYPEFRAGGED_FIRST_VERBOSE, 1, 3, s1,                                                                                               NO_CPID, XPND2(0, 0), _("^K1First victim! You were typefragged by ^BG%s"), _("^K1First casualty! You were scored against by ^BG%s^K1 while typing!")) \
+       #undef MSG_DEATH_NOTIF
+
 
 // ====================================
 //  Initialization/Create Declarations
 
 // ====================================
 //  Initialization/Create Declarations
@@ -159,6 +233,7 @@ string team_color_pink = "";
 float NOTIF_INFO_COUNT;
 float NOTIF_CENTER_COUNT;
 float NOTIF_WEAPON_COUNT;
 float NOTIF_INFO_COUNT;
 float NOTIF_CENTER_COUNT;
 float NOTIF_WEAPON_COUNT;
+float NOTIF_DEATH_COUNT;
 float NOTIF_CPID_COUNT;
 
 #define MSG_INFO_NOTIF(name,strnum,flnum,args,icon,normal,gentle) \
 float NOTIF_CPID_COUNT;
 
 #define MSG_INFO_NOTIF(name,strnum,flnum,args,icon,normal,gentle) \
@@ -193,10 +268,21 @@ float NOTIF_CPID_COUNT;
        } \
        ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
        } \
        ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
+#define MSG_DEATH_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
+       ADD_CSQC_AUTOCVAR(name) \
+       float name; \
+       void RegisterNotification_##name() \
+       { \
+               SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_DEATH_COUNT) \
+               CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_DEATH_COUNT, "notifications") \
+       } \
+       ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
+
 // NOW we actually activate the declarations
 MSG_INFO_NOTIFICATIONS
 MSG_CENTER_NOTIFICATIONS
 MSG_WEAPON_NOTIFICATIONS
 // NOW we actually activate the declarations
 MSG_INFO_NOTIFICATIONS
 MSG_CENTER_NOTIFICATIONS
 MSG_WEAPON_NOTIFICATIONS
+MSG_DEATH_NOTIFICATIONS
 
 
 // ======================
 
 
 // ======================
@@ -206,14 +292,18 @@ MSG_WEAPON_NOTIFICATIONS
 // select between the normal or the gentle message string based on client (or server) settings
 string normal_or_gentle(string normal, string gentle)
 {
 // select between the normal or the gentle message string based on client (or server) settings
 string normal_or_gentle(string normal, string gentle)
 {
-       #ifdef CSQC
-       if(autocvar_cl_gentle || autocvar_cl_gentle_messages)
+       #ifndef MENUQC
+               #ifdef CSQC
+               if(autocvar_cl_gentle || autocvar_cl_gentle_messages)
+               #else
+               if(autocvar_sv_gentle)
+               #endif
+                       return ((gentle != "") ? gentle : normal);
+               else
+                       return normal;
        #else
        #else
-       if(autocvar_sv_gentle)
-       #endif
-               return ((gentle != "") ? gentle : normal);
-       else
                return normal;
                return normal;
+       #endif
 }
 
 float notif_stringcount(string s1, string s2)
 }
 
 float notif_stringcount(string s1, string s2)
@@ -266,6 +356,13 @@ string Get_Field_Value(float field, float net_type, float net_name)
                        MSG_WEAPON_NOTIFICATIONS
                        break;
                }
                        MSG_WEAPON_NOTIFICATIONS
                        break;
                }
+               case MSG_DEATH:
+               {
+                       #define MSG_DEATH_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
+                               { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } }
+                       MSG_DEATH_NOTIFICATIONS
+                       break;
+               }
        }
 
        #undef GET_FIELD_VALUE_OUTPUT
        }
 
        #undef GET_FIELD_VALUE_OUTPUT
@@ -283,16 +380,41 @@ string TCR(string input, string teamcolor, string teamtext)
 // color code replace, place inside of sprintf and parse the string
 string CCR(string input)
 {
 // color code replace, place inside of sprintf and parse the string
 string CCR(string input)
 {
-       input = strreplace("^F1", "^2", input); // autocvar_notification_colors_F1 
-       input = strreplace("^F2", "^3", input); // autocvar_notification_colors_F2
-       input = strreplace("^K1", "^1", input); // autocvar_notification_colors_K1
-       input = strreplace("^K2", "^3", input); // autocvar_notification_colors_K2
-       input = strreplace("^BG", "^7", input); // autocvar_notification_colors_BG
-       input = strreplace("^N", "^7", input); // "none"-- reset to white
+       // foreground/normal colors
+       input = strreplace("^F1", "^2", input); // primary priority (important names, etc)
+       input = strreplace("^F2", "^3", input); // secondary priority (items, locations, numbers, etc)
+
+       // "kill" colors
+       input = strreplace("^K1", "^1", input); // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
+       input = strreplace("^K2", "^3", input); // similar to above, but less important... OR, a highlight out of above message type
+       input = strreplace("^K3", "^4", input); // "good" or "beneficial" text (you fragging someone, etc)
+
+       // background colors
+       input = strreplace("^BG", "^7", input); // neutral/unimportant text
+       input = strreplace("^N", "^7", input); // "none"-- reset to white...
        return input;
 }
 
 
        return input;
 }
 
 
+// =============================
+//  Debug/Maintenance Functions
+// =============================
+
+#define NOTIF_Write(type,name,text) fputs(fh, (sprintf("seta %s 1 // %s - %s\n", name, type, strreplace("\n", "\\n", text))))
+void Dump_Notifications(float fh)
+{
+       #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) { NOTIF_Write("MSG_INFO", VAR_TO_TEXT(name), normal); }
+       #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) { NOTIF_Write("MSG_CENTER", VAR_TO_TEXT(name), normal); }
+       #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) { NOTIF_Write("MSG_WEAPON", VAR_TO_TEXT(name), normal); }
+       #define MSG_DEATH_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) { NOTIF_Write("MSG_DEATH", VAR_TO_TEXT(name), normal); }
+       MSG_INFO_NOTIFICATIONS
+       MSG_CENTER_NOTIFICATIONS
+       MSG_WEAPON_NOTIFICATIONS
+       MSG_DEATH_NOTIFICATIONS
+       return;
+}
+
+
 // ===============================
 //  Frontend Notification Pushing
 // ===============================
 // ===============================
 //  Frontend Notification Pushing
 // ===============================
@@ -334,24 +456,44 @@ void Local_Notification(float net_type, float net_name, string s1, string s2, fl
                case MSG_INFO:
                {
                        #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
                case MSG_INFO:
                {
                        #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \
-                               { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); if(strtolower(icon) != "") { HUD_Notify_Push(icon, hudargs); } } }
+                               { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
+                               { \
+                                       print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); \
+                                       if(strtolower(icon) != "") { HUD_Notify_Push(icon, hudargs); } \
+                               } }
                        MSG_INFO_NOTIFICATIONS
                        break;
                }
                case MSG_CENTER:
                {
                        #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
                        MSG_INFO_NOTIFICATIONS
                        break;
                }
                case MSG_CENTER:
                {
                        #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
-                               { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) { centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); } }
+                               { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
+                               { \
+                                       centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); \
+                               } }
                        MSG_CENTER_NOTIFICATIONS
                        break;
                }
                case MSG_WEAPON:
                {
                        #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
                        MSG_CENTER_NOTIFICATIONS
                        break;
                }
                case MSG_WEAPON:
                {
                        #define MSG_WEAPON_NOTIF(name,strnum,flnum,args,normal,gentle) \
-                               { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) { print("unhandled\n"); } }
+                               { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
+                               { \
+                                       print("unhandled\n"); \
+                               } }
                        MSG_WEAPON_NOTIFICATIONS
                        break;
                }
                        MSG_WEAPON_NOTIFICATIONS
                        break;
                }
+               case MSG_DEATH:
+               {
+                       #define MSG_DEATH_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
+                               { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \
+                               { \
+                                       centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); \
+                               } }
+                       MSG_DEATH_NOTIFICATIONS
+                       break;
+               }
        }
 }
 #endif
        }
 }
 #endif
@@ -380,7 +522,7 @@ void Read_Notification(void)
 #endif
 
 #ifdef SVQC
 #endif
 
 #ifdef SVQC
-void Send_Notification(entity client, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
+void Send_Notification(entity client, float broadcast, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
 {
        if(net_type && net_name)
        {
 {
        if(net_type && net_name)
        {
@@ -391,24 +533,27 @@ void Send_Notification(entity client, float net_type, float net_name, string s1,
                
                if(notif_stringcount(s1, s2) > stringcount) { backtrace("Too many string arguments for notification!\n"); return; }
                if(notif_floatcount(f1, f2, f3) > floatcount) { backtrace("Too many float arguments for notification!\n"); return; }
                
                if(notif_stringcount(s1, s2) > stringcount) { backtrace("Too many string arguments for notification!\n"); return; }
                if(notif_floatcount(f1, f2, f3) > floatcount) { backtrace("Too many float arguments for notification!\n"); return; }
-               
-               if(client && (clienttype(client) == CLIENTTYPE_REAL) && (client.flags & FL_CLIENT))
+
+               if(broadcast == MSG_ONE)
                {
                {
-                       // personal/direct notification sent to ONE person and their spectators
-                       msg_entity = client;
-                       WRITESPECTATABLE_MSG_ONE({
-                               WriteByte(MSG_ONE, SVC_TEMPENTITY);
-                               WriteByte(MSG_ONE, TE_CSQC_NOTIFICATION);
-                               WriteByte(MSG_ONE, net_type);
-                               WriteShort(MSG_ONE, net_name);
-                               if(stringcount >= 1) { WriteString(MSG_ONE, s1); }
-                               if(stringcount == 2) { WriteString(MSG_ONE, s2); }
-                               if(floatcount >= 1) { WriteLong(MSG_ONE, f1); }
-                               if(floatcount >= 2) { WriteLong(MSG_ONE, f2); }
-                               if(floatcount == 3) { WriteLong(MSG_ONE, f3); }
-                       });
+                       if(client && (clienttype(client) == CLIENTTYPE_REAL) && (client.flags & FL_CLIENT))
+                       {
+                               // personal/direct notification sent to ONE person and their spectators
+                               msg_entity = client;
+                               WRITESPECTATABLE_MSG_ONE({
+                                       WriteByte(MSG_ONE, SVC_TEMPENTITY);
+                                       WriteByte(MSG_ONE, TE_CSQC_NOTIFICATION);
+                                       WriteByte(MSG_ONE, net_type);
+                                       WriteShort(MSG_ONE, net_name);
+                                       if(stringcount >= 1) { WriteString(MSG_ONE, s1); }
+                                       if(stringcount == 2) { WriteString(MSG_ONE, s2); }
+                                       if(floatcount >= 1) { WriteLong(MSG_ONE, f1); }
+                                       if(floatcount >= 2) { WriteLong(MSG_ONE, f2); }
+                                       if(floatcount == 3) { WriteLong(MSG_ONE, f3); }
+                               });
+                       }
                }
                }
-               else
+               else if(broadcast == MSG_ALL)
                {
                        // global notification sent to EVERYONE
                        WriteByte(MSG_ALL, SVC_TEMPENTITY);
                {
                        // global notification sent to EVERYONE
                        WriteByte(MSG_ALL, SVC_TEMPENTITY);
@@ -421,6 +566,7 @@ void Send_Notification(entity client, float net_type, float net_name, string s1,
                        if(floatcount >= 2) { WriteLong(MSG_ALL, f2); }
                        if(floatcount == 3) { WriteLong(MSG_ALL, f3); }
                }
                        if(floatcount >= 2) { WriteLong(MSG_ALL, f2); }
                        if(floatcount == 3) { WriteLong(MSG_ALL, f3); }
                }
+               else { backtrace("Unknown MSG_ type to write with!\n"); }
 
                if(!server_is_local && (net_type == MSG_INFO))
                {
 
                if(!server_is_local && (net_type == MSG_INFO))
                {
@@ -441,12 +587,12 @@ void Send_Notification_ToTeam(float targetteam, entity except, float net_type, f
                if(tmp_entity.team == targetteam)
                if(tmp_entity != except)
                {
                if(tmp_entity.team == targetteam)
                if(tmp_entity != except)
                {
-                       Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
+                       Send_Notification(tmp_entity, MSG_ONE, net_type, net_name, s1, s2, f1, f2, f3);
                }
        }
 }
 
                }
        }
 }
 
-// WARNING: use this ONLY if you need exceptions or want to exclude spectators, otherwise use Send_Notification(..., world, ...)
+// WARNING: use this ONLY if you need exceptions or want to exclude spectators, otherwise use Send_Notification(world, MSG_ALL, ...)
 void Send_Notification_ToAll(entity except, float spectators, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
 {
        entity tmp_entity;
 void Send_Notification_ToAll(entity except, float spectators, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3)
 {
        entity tmp_entity;
@@ -455,7 +601,7 @@ void Send_Notification_ToAll(entity except, float spectators, float net_type, fl
                if((tmp_entity.classname == STR_PLAYER) || spectators)
                if(tmp_entity != except)
                {
                if((tmp_entity.classname == STR_PLAYER) || spectators)
                if(tmp_entity != except)
                {
-                       Send_Notification(tmp_entity, net_type, net_name, s1, s2, f1, f2, f3);
+                       Send_Notification(tmp_entity, MSG_ONE, net_type, net_name, s1, s2, f1, f2, f3);
                }
        }
 }
                }
        }
 }