]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/notifications/all.qh
Merge branch 'master' into z411/bai-server
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / notifications / all.qh
index 8d882bf3ccede40ac09e28b75b614640c1a02acc..aa4ebc32c895cb7c0bff3df282a125038c2cce3e 100644 (file)
@@ -25,6 +25,8 @@ ENUMCLASS(MSG)
        CASE(MSG, CHOICE)
        /** Kill centerprint message @deprecated */
        CASE(MSG, CENTER_KILL)
+       /** Medal notification */
+       CASE(MSG, MEDAL)
 ENUMCLASS_END(MSG)
 
 string Get_Notif_TypeName(MSG net_type)
@@ -36,12 +38,13 @@ string Get_Notif_TypeName(MSG net_type)
                case MSG_CENTER: return "MSG_CENTER";
                case MSG_MULTI: return "MSG_MULTI";
                case MSG_CHOICE: return "MSG_CHOICE";
+               case MSG_MEDAL: return "MSG_MEDAL";
                case MSG_CENTER_KILL: return "MSG_CENTER_KILL";
        }
        LOG_WARNF("Get_Notif_TypeName(%d): Improper net type!", ORDINAL(net_type));
        return "";
 }
-
+//LegendGuard adds CASE(CPID, MMM) after TIMEIN for MMM 20-02-2021
 ENUMCLASS(CPID)
        CASE(CPID, ASSAULT_ROLE)
        CASE(CPID, ROUND)
@@ -61,9 +64,8 @@ ENUMCLASS(CPID)
        CASE(CPID, LMS)
        CASE(CPID, MISSING_TEAMS)
        CASE(CPID, MISSING_PLAYERS)
+       CASE(CPID, MISSING_READY)
        CASE(CPID, INSTAGIB_FINDAMMO)
-       CASE(CPID, CAMPAIGN_MESSAGE)
-       CASE(CPID, MOTD)
        CASE(CPID, NIX)
        CASE(CPID, ONSLAUGHT)
        CASE(CPID, ONS_CAPSHIELD)
@@ -73,6 +75,7 @@ ENUMCLASS(CPID)
        CASE(CPID, TEAMCHANGE)
        CASE(CPID, TIMEOUT)
        CASE(CPID, TIMEIN)
+       CASE(CPID, MMM)
        CASE(CPID, VEHICLES)
        CASE(CPID, VEHICLES_OTHER)
        /** always last */
@@ -125,7 +128,8 @@ void Create_Notification_Entity_Annce(entity notif,
                                                                                float channel,
                                                                                string snd,
                                                                                float vol,
-                                                                               float position);
+                                                                               float position,
+                                                                               float queuetime);
 
 void Create_Notification_Entity_InfoCenter(entity notif,
                                                                                        float var_cvar,
@@ -159,6 +163,13 @@ void Create_Notification_Entity_Choice(entity notif,
                                                                                Notification optiona,
                                                                                Notification optionb);
 
+void Create_Notification_Entity_Medal(entity notif,
+                                                                               float var_cvar,
+                                                                               string namestring,
+                                                                               /* MSG_MEDAL */
+                                                                               string icon,
+                                                                               Notification anncename);
+
 void Dump_Notifications(int fh, bool alsoprint);
 
 #define DEFAULT_FILENAME "notifications_dump.cfg"
@@ -251,10 +262,16 @@ ENUMCLASS(NOTIF)
        CASE(NOTIF, TEAM)
        /** send only to X team and their spectators, except for Y person and their spectators */
        CASE(NOTIF, TEAM_EXCEPT)
+       /** send only to X team; don't include spectators */
+       CASE(NOTIF, TEAM_ONLY)
+       /** send to team X team except for Y person; don't include spectators */
+       CASE(NOTIF, TEAM_ONLY_EXCEPT)
        /** send to everyone */
        CASE(NOTIF, ALL)
        /** send to everyone except X person and their spectators */
        CASE(NOTIF, ALL_EXCEPT)
+       /** send to all spectators **/
+       CASE(NOTIF, ALL_SPEC)
 ENUMCLASS_END(NOTIF)
 
 string Get_Notif_BroadcastName(NOTIF broadcast)
@@ -263,10 +280,13 @@ string Get_Notif_BroadcastName(NOTIF broadcast)
        {
                case NOTIF_ONE: return "NOTIF_ONE";
                case NOTIF_ONE_ONLY: return "NOTIF_ONE_ONLY";
+               case NOTIF_ALL_SPEC: return "NOTIF_ALL_SPEC";
                case NOTIF_ALL_EXCEPT: return "NOTIF_ALL_EXCEPT";
                case NOTIF_ALL: return "NOTIF_ALL";
                case NOTIF_TEAM: return "NOTIF_TEAM";
                case NOTIF_TEAM_EXCEPT: return "NOTIF_TEAM_EXCEPT";
+               case NOTIF_TEAM_ONLY: return "NOTIF_TEAM_ONLY";
+               case NOTIF_TEAM_ONLY_EXCEPT: return "NOTIF_TEAM_ONLY_EXCEPT";
        }
        LOG_WARNF("Get_Notif_BroadcastName(%d): Improper broadcast!", broadcast);
        return "";
@@ -359,8 +379,8 @@ float autocvar_notification_show_sprees_center_specialonly = true;
        f1points: point or points depending on f1
        f1ord: count_ordinal of f1
        f1time: process_time of f1
-       f1race_time: mmssth of f1
-       f2race_time: mmssth of f2
+       f1race_time: TIME_ENCODED_TOSTRING of f1
+       f2race_time: TIME_ENCODED_TOSTRING of f2
        race_col: color of race time/position (i.e. good or bad)
        race_diff: show time difference between f2 and f3
        missing_teams: show which teams still need players
@@ -386,6 +406,19 @@ const float NOTIF_MAX_ARGS = 7;
 const float NOTIF_MAX_HUDARGS = 2;
 const float NOTIF_MAX_DURCNT = 2;
 
+#ifdef CSQC
+const int NOTIF_QUEUE_MAX = 10;
+entity notif_queue_entity[NOTIF_QUEUE_MAX];
+MSG notif_queue_type[NOTIF_QUEUE_MAX];
+float notif_queue_time[NOTIF_QUEUE_MAX];
+float notif_queue_f1[NOTIF_QUEUE_MAX];
+
+float notif_queue_next_time;
+int notif_queue_length;
+
+void Local_Notification_Queue_Process();
+#endif
+
 string arg_slot[NOTIF_MAX_ARGS];
 
 const float ARG_CS_SV_HA = 1; // enabled on CSQC, SVQC, and Hudargs
@@ -419,18 +452,18 @@ string BUFF_NAME(int i);
        ARG_CASE(ARG_CS,        "f1points",      (f1 == 1 ? _("point") : _("points"))) \
        ARG_CASE(ARG_CS_SV,     "f1ord",         count_ordinal(f1)) \
        ARG_CASE(ARG_CS_SV,     "f1time",        process_time(2, f1)) \
-       ARG_CASE(ARG_CS_SV_HA,  "f1race_time",   mmssth(f1)) \
-       ARG_CASE(ARG_CS_SV_HA,  "f2race_time",   mmssth(f2)) \
-       ARG_CASE(ARG_CS_SV_HA,  "f3race_time",   mmssth(f3)) \
+       ARG_CASE(ARG_CS_SV_HA,  "f1race_time",   TIME_ENCODED_TOSTRING(f1, true)) \
+       ARG_CASE(ARG_CS_SV_HA,  "f2race_time",   TIME_ENCODED_TOSTRING(f2, true)) \
+       ARG_CASE(ARG_CS_SV_HA,  "f3race_time",   TIME_ENCODED_TOSTRING(f3, true)) \
        ARG_CASE(ARG_CS_SV,     "race_col",      CCR(((f1 == 1) ? "^F1" : "^F2"))) \
-       ARG_CASE(ARG_CS_SV,     "race_diff",     ((f2 > f3) ? sprintf(CCR("^1[+%s]"), mmssth(f2 - f3)) : sprintf(CCR("^2[-%s]"), mmssth(f3 - f2)))) \
+       ARG_CASE(ARG_CS_SV,     "race_diff",     ((f2 > f3) ? sprintf(CCR("^1[+%s]"), TIME_ENCODED_TOSTRING(f2 - f3, true)) : sprintf(CCR("^2[-%s]"), TIME_ENCODED_TOSTRING(f3 - f2, true)))) \
        ARG_CASE(ARG_CS,        "missing_teams", notif_arg_missing_teams(f1)) \
        ARG_CASE(ARG_CS,        "pass_key",      getcommandkey(_("drop flag"), "+use")) \
        ARG_CASE(ARG_CS,        "nade_key",      getcommandkey(_("throw nade"), "dropweapon")) \
        ARG_CASE(ARG_CS,        "join_key",      getcommandkey(_("jump"), "+jump")) \
        ARG_CASE(ARG_CS,        "frag_ping",     notif_arg_frag_ping(true, f2)) \
        ARG_CASE(ARG_CS,        "frag_stats",    notif_arg_frag_stats(f2, f3, f4)) \
-       /*ARG_CASE(ARG_CS,      "frag_pos",      ((Should_Print_Score_Pos(f1)) ? sprintf("\n^BG%s", Read_Score_Pos(f1)) : ""))*/ \
+       ARG_CASE(ARG_CS,        "frag_pos",      notif_arg_frag_pos(f2)) \
        ARG_CASE(ARG_CS,        "spree_cen",     (autocvar_notification_show_sprees ? notif_arg_spree_cen(f1) : "")) \
        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) : "")) \
@@ -456,11 +489,73 @@ MACRO_END
        SPREE_ITEM(5, 05, _("RAGE! "), _("%s^K1 unlocked RAGE! %s^BG"), _("%s^K1 made FIVE SCORES IN A ROW! %s^BG")) \
        SPREE_ITEM(10, 10, _("MASSACRE! "), _("%s^K1 started a MASSACRE! %s^BG"), _("%s^K1 made TEN SCORES IN A ROW! %s^BG")) \
        SPREE_ITEM(15, 15, _("MAYHEM! "), _("%s^K1 executed MAYHEM! %s^BG"), _("%s^K1 made FIFTEEN SCORES IN A ROW! %s^BG")) \
-       SPREE_ITEM(20, 20, _("BERSERKER! "), _("%s^K1 is a BERSERKER! %s^BG"), _("%s^K1 made TWENTY SCORES IN A ROW! %s^BG")) \
-       SPREE_ITEM(25, 25, _("CARNAGE! "), _("%s^K1 inflicts CARNAGE! %s^BG"), _("%s^K1 made TWENTY FIVE SCORES IN A ROW! %s^BG")) \
-       SPREE_ITEM(30, 30, _("ARMAGEDDON! "), _("%s^K1 unleashes ARMAGEDDON! %s^BG"), _("%s^K1 made THIRTY SCORES IN A ROW! %s^BG"))
 
 #ifdef CSQC
+// z411 TODO : This actually doesn't work very well.
+// This gets run before the client gets score updates so it works
+// fine when you're playing (because frags get updated first)
+// but it breaks a lot when you're spectating because
+// we sometimes get the new frag info at different times
+// (before or after we run this). A suggested fix would
+// be to do this sorting and comparison in the server.
+string notif_arg_frag_pos(int score)
+{
+       entity pl;
+       int place = 1;
+       string str, color, tail;
+       bool tied = false;
+       
+       for(pl = players.sort_next; pl; pl = pl.sort_next) {
+               if(pl.team == NUM_SPECTATOR) continue;
+               if(pl.(scores(SP_SCORE)) == score) break;
+               ++place;
+       }
+       
+       entity prev = pl.sort_prev;
+       entity next = pl.sort_next;
+       if(prev && prev.(scores(SP_SCORE)) == score) {
+               tied = true;
+               --place; // We're tied always for the best place
+       }
+       if(next && next.(scores(SP_SCORE)) == score) {
+               tied = true;
+       }
+       
+       switch(place) {
+               case 1:
+                       color = "^4";
+                       break;
+               case 2:
+                       color = "^1";
+                       break;
+               case 3:
+                       color = "^3";
+                       break;
+               default:
+                       color = "";
+       }
+       
+       switch(place % 10) {
+               case 1:
+                       tail = "st";
+                       break;
+               case 2:
+                       tail = "nd";
+                       break;
+               case 3:
+                       tail = "rd";
+                       break;
+               default:
+                       tail = "th";
+       }
+       
+       str = strcat(color, ftos(place), tail);
+       if(tied)
+               return strcat("Tied for ", str);
+       else
+               return str;
+}
+
 string notif_arg_frag_ping(bool newline, float fping)
 {
        string s = newline ? "\n" : " ";
@@ -667,6 +762,7 @@ string notif_arg_item_wepammo(float f1, float f2)
 .string nent_snd;
 .float nent_vol;
 .float nent_position;
+.float nent_queuetime;
 
 // MSG_INFO and MSG_CENTER entity values
 .string nent_args; // used by both
@@ -745,21 +841,22 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
        return it;
 }
 
-#define MSG_ANNCE_NOTIF_TEAM(teamnum, name, cvarname, defaultvalue, sound, channel, volume, position) \
-       MSG_ANNCE_NOTIF_(teamnum, ANNCE_##name, ANNCE_##cvarname, defaultvalue, sound, channel, volume, position)
+#define MSG_ANNCE_NOTIF_TEAM(teamnum, name, cvarname, defaultvalue, sound, channel, volume, position, queuetime) \
+       MSG_ANNCE_NOTIF_(teamnum, ANNCE_##name, ANNCE_##cvarname, defaultvalue, sound, channel, volume, position, queuetime)
 
-#define MSG_ANNCE_NOTIF(name, defaultvalue, sound, channel, volume, position) \
+#define MSG_ANNCE_NOTIF(name, defaultvalue, sound, channel, volume, position, queuetime) \
        NOTIF_ADD_AUTOCVAR(ANNCE_##name, defaultvalue) \
-       MSG_ANNCE_NOTIF_(0, ANNCE_##name, ANNCE_##name, defaultvalue, sound, channel, volume, position)
+       MSG_ANNCE_NOTIF_(0, ANNCE_##name, ANNCE_##name, defaultvalue, sound, channel, volume, position, queuetime)
 
-#define MSG_ANNCE_NOTIF_(teamnum, name, cvarname, defaultvalue, sound, channel, volume, position) \
+#define MSG_ANNCE_NOTIF_(teamnum, name, cvarname, defaultvalue, sound, channel, volume, position, queuetime) \
        REGISTER(Notifications, name, m_id, new_pure(msg_annce_notification)) { \
                Create_Notification_Entity      (this, defaultvalue, ACVNN(cvarname), MSG_ANNCE, strtoupper(#name), teamnum); \
                Create_Notification_Entity_Annce(this, ACVNN(cvarname), strtoupper(#name), \
-                       channel,   /* channel  */ \
-                       sound,     /* snd      */ \
-                       volume,    /* vol      */ \
-                       position); /* position */ \
+                       channel,    /* channel   */ \
+                       sound,      /* snd       */ \
+                       volume,     /* vol       */ \
+                       position,   /* position  */ \
+                       queuetime); /* queuetime */ \
        }
 
 #define MSG_INFO_NOTIF_TEAM(teamnum, name, cvarname, defaultvalue, strnum, flnum, args, hudargs, icon, normal, gentle) \
@@ -851,6 +948,18 @@ Notification Get_Notif_Ent(MSG net_type, int net_name)
                        optiona,                                 /* optiona     */ \
                        optionb);                                /* optionb     */ \
        }
+       
+#define MSG_MEDAL_NOTIF(name, defaultvalue, icon, anncename) \
+       NOTIF_ADD_AUTOCVAR(MEDAL_##name, defaultvalue) \
+       MSG_MEDAL_NOTIF_(0, MEDAL_##name, MEDAL_##name, defaultvalue, icon, anncename)
+
+#define MSG_MEDAL_NOTIF_(teamnum, name, cvarname, defaultvalue, icon, anncename) \
+       REGISTER(Notifications, name, m_id, new_pure(msg_medal_notification)) { \
+               Create_Notification_Entity      (this, defaultvalue, ACVNN(cvarname), MSG_MEDAL, strtoupper(#name), teamnum); \
+               Create_Notification_Entity_Medal(this, ACVNN(cvarname), strtoupper(#name), \
+                       icon, \
+                       anncename); \
+       }
 
 REGISTRY_BEGIN(Notifications)
 {