1 // ================================================
2 // Unified notification system, written by Samual
3 // Last updated: September, 2012
4 // ================================================
6 // main types/groups of notifications
7 #define MSG_INFO 1 // "Global" information messages (sent to console)
8 #define MSG_NOTIFY 2 // "Global" events to be sent to the notification panel
9 #define MSG_CENTER 3 // "Personal" centerprint messages
10 #define MSG_WEAPON 4 // "Personal" weapon messages (like "You got the Nex", sent to weapon notify panel)
12 // collapse multiple arguments into one argument
13 #define CLPS4(s1,s2,s3,s4) s1, s2, s3, s4
14 #define CLPS3(s1,s2,s3) s1, s2, s3
15 #define CLPS2(s1,s2) s1, s2
17 // accumulate functions for declarations
19 #define NOTIF_MAX 1024
20 float NOTIF_INFO_COUNT;
21 float NOTIF_NOTIFY_COUNT;
22 float NOTIF_CENTER_COUNT;
23 float NOTIF_WEAPON_COUNT;
24 float NOTIF_CPID_COUNT;
26 #define MSG_INFO_NOTIF(name,args,normal,gentle) \
28 void DecNotif_##name() { \
30 name = (NOTIF_FIRST + NOTIF_INFO_COUNT); \
31 ++NOTIF_INFO_COUNT; } } \
32 ACCUMULATE_FUNCTION(DecNotifs, DecNotif_##name)
34 #define MSG_NOTIFY_NOTIF(name,args,icon,normal,gentle) \
36 void DecNotif_##name() { \
38 name = (NOTIF_FIRST + NOTIF_NOTIFY_COUNT); \
39 ++NOTIF_NOTIFY_COUNT; } } \
40 ACCUMULATE_FUNCTION(DecNotifs, DecNotif_##name)
42 #define MSG_CENTER_NOTIF(name,args,cpid,normal,gentle) \
45 void DecNotif_##name() { \
47 name = (NOTIF_FIRST + NOTIF_CENTER_COUNT); \
48 ++NOTIF_CENTER_COUNT; } \
50 cpid = (NOTIF_FIRST + NOTIF_CPID_COUNT); \
51 ++NOTIF_CPID_COUNT; } } \
52 ACCUMULATE_FUNCTION(DecNotifs, DecNotif_##name)
54 #define MSG_WEAPON_NOTIF(name,args,normal,gentle) \
56 void DecNotif_##name() { \
58 name = (NOTIF_FIRST + NOTIF_WEAPON_COUNT); \
59 ++NOTIF_WEAPON_COUNT; } } \
60 ACCUMULATE_FUNCTION(DecNotifs, DecNotif_##name)
63 // ====================================
64 // Notifications List and Information
65 // ====================================
67 List of all notifications (including identifiers and display information)
68 Format: name, number, args, icon/CPID, normal, gentle
71 ID number of notification
72 Arguments for sprintf(string, args), if no args needed then use ""
74 MSG_NOTIFY: STRING: icon string name for the hud notify panel, "" if no icon is used
75 MSG_CENTER: FLOAT: centerprint ID number (CPID_*), NO_CPID if no CPID is needed
76 Normal message (string for sprintf when gentle messages are NOT enabled)
77 Gentle message (string for sprintf when gentle messages ARE enabled)
79 Messages have ^F1, ^F2, and ^BG in them-- these are replaced
80 with colors according to the cvars the user has chosen.
81 ^F1 = highest priority, "primary"
82 ^F2 = next highest priority, "secondary"
83 ^BG = normal/less important priority, "tertiary"
86 ALWAYS start the string with a color, preferably background
87 ALWAYS end messages with a new line
88 ARIRE unir frk jvgu lbhe bja zbgure (gvc sbe zvxrrhfn)
90 #define MSG_INFO_NOTIFICATIONS \
91 MSG_INFO_NOTIF(DEATH_MARBLES_LOST, CLPS3(s1, s2, s3), _("^F1%s^BG lost their marbles against ^F1%s^BG using the ^F2%s^BG\n"), "") \
94 #define MSG_NOTIFY_NOTIFICATIONS \
95 MSG_NOTIFY_NOTIF(DEATH_MARBLES_LOST2, CLPS3(s1, s2, s3), "notify_death", _("^F1%s^BG lost their marbles against ^F1%s^BG using the ^F2%s^BG\n"), "") \
96 #undef MSG_NOTIFY_NOTIF
98 #define MSG_CENTER_NOTIFICATIONS \
99 MSG_CENTER_NOTIF(CENTER_CTF_CAPTURESHIELD_SHIELDED, "", CPID_CTF_CAPTURESHIELD, _("^BGYou are now ^F1shielded^BG from the flag\n^BGfor ^F2too many unsuccessful attempts^BG to capture.\n^BGMake some defensive scores before trying again."), "") \
100 MSG_CENTER_NOTIF(CENTER_CTF_CAPTURESHIELD_FREE, "", CPID_CTF_CAPTURESHIELD, _("^BGYou are now free.\n^BGFeel free to ^F2try to capture^BG the flag again\n^BGif you think you will succeed."), "") \
101 MSG_CENTER_NOTIF(CENTER_CTF_EVENT_PASS, CLPS2(s1, s2, s3), CPID_CTF_PASS, _("^BG%s passed the ^F1%s^BG to %s"), "") \
102 MSG_CENTER_NOTIF(CENTER_CTF_EVENT_PASS_SENT, CLPS2(s1, s2), CPID_CTF_PASS, _("^BGYou passed the ^F1%s^BG to %s"), "") \
103 MSG_CENTER_NOTIF(CENTER_CTF_EVENT_PASS_RECEIVED, CLPS2(s1, s2), CPID_CTF_PASS, _("^BGYou received the ^F1%s^BG from %s"), "") \
104 MSG_CENTER_NOTIF(CENTER_CTF_EVENT_RETURN, s1, CPID_CTF_LOWPRIO, _("^BGYou returned the ^F1%s"), "") \
105 MSG_CENTER_NOTIF(CENTER_CTF_EVENT_CAPTURE, s1, NO_CPID, _("^BGYou captured the ^F1%s"), "") \
106 #undef MSG_CENTER_NOTIF
108 #define MSG_WEAPON_NOTIFICATIONS \
109 MSG_WEAPON_NOTIF(DEATH_MARBLES_LOST3, CLPS3(s1, s2, s3), _("^F1%s^BG lost their marbles against ^F1%s^BG using the ^F2%s^BG\n"), "") \
110 #undef MSG_WEAPON_NOTIF
112 // NOW we actually activate the declarations
113 MSG_INFO_NOTIFICATIONS
114 MSG_NOTIFY_NOTIFICATIONS
115 MSG_CENTER_NOTIFICATIONS
116 MSG_WEAPON_NOTIFICATIONS
119 // ======================
120 // Supporting Functions
121 // ======================
124 #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
125 #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
126 #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
129 #define HANDLE_CPID(cpid) ((min(NOTIF_MAX, cpid) == NO_CPID) ? FALSE : cpid)
131 string normal_or_gentle(string normal, string gentle)
134 if(autocvar_cl_gentle || autocvar_cl_gentle_messages)
136 if(autocvar_sv_gentle)
138 return ((gentle != "") ? gentle : normal);
143 string CCR(string input) // color code replace, place inside of sprintf and parse the string
145 input = strreplace("^F1", "^3", input);
146 input = strreplace("^F2", "^2", input);
147 input = strreplace("^BG", "^7", input);
149 input = strreplace("^N", "^7", input); // "none"-- reset to white
155 // ===============================
156 // Frontend Notification Pushing
157 // ===============================
160 // =========================
161 // Notification Networking
162 // =========================
165 void Read_Notification()
167 float net_type = ReadByte();
168 float net_name = ReadCoord(); // byte only has 256 selections, we need more than that
169 string s1 = ReadString();
170 string s2 = ReadString();
171 string s3 = ReadString();
177 #define MSG_INFO_NOTIF(name,args,normal,gentle) \
178 { if(min(NOTIF_MAX, name) == net_name) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); } }
180 MSG_INFO_NOTIFICATIONS
191 #define MSG_CENTER_NOTIF(name,args,cpid,normal,gentle) \
192 { if(min(NOTIF_MAX, name) == net_name) { centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), 0, 0); } }
194 MSG_CENTER_NOTIFICATIONS
206 void Send_Notification(float net_type, entity client, float net_name, string s1, string s2, string s3)
208 if(net_type && net_name)
210 if(client && (clienttype(client) == CLIENTTYPE_REAL) && (client.flags & FL_CLIENT))
213 WRITESPECTATABLE_MSG_ONE({
214 WriteByte(MSG_ONE, SVC_TEMPENTITY);
215 WriteByte(MSG_ONE, TE_CSQC_NOTIFICATION);
216 WriteByte(MSG_ONE, net_type);
217 WriteCoord(MSG_ONE, net_name);
218 WriteString(MSG_ONE, s1);
219 WriteString(MSG_ONE, s2);
220 WriteString(MSG_ONE, s3);
224 if(!server_is_local && ((net_type == MSG_INFO || net_type == MSG_NOTIFY) || client == world))
230 #define MSG_INFO_NOTIF(name,args,normal,gentle) \
231 { if(min(NOTIF_MAX, name) == net_name) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); } }
233 MSG_INFO_NOTIFICATIONS
244 else { backtrace("Incorrect usage of Send_Notification!\n"); }
247 // LEGACY NOTIFICATION SYSTEMS
248 void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
250 if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
253 WRITESPECTATABLE_MSG_ONE({
254 WriteByte(MSG_ONE, SVC_TEMPENTITY);
255 WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
256 WriteByte(MSG_ONE, id);
257 WriteString(MSG_ONE, s);
258 if (id != 0 && s != "")
260 WriteByte(MSG_ONE, duration);
261 WriteByte(MSG_ONE, countdown_num);
266 void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
268 Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);