]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/hud/panel/notify.qc
Notify panel: improve scoreboard area detection
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / notify.qc
1 #include "notify.qh"
2
3 #include <client/draw.qh>
4 #include <client/hud/panel/scoreboard.qh>
5 #include <client/view.qh>
6
7 // Notifications (#4)
8
9 void HUD_Notify_Export(int fh)
10 {
11         // allow saving cvars that aesthetically change the panel into hud skin files
12         HUD_Write_Cvar("hud_panel_notify_flip");
13         HUD_Write_Cvar("hud_panel_notify_fontsize");
14         HUD_Write_Cvar("hud_panel_notify_time");
15         HUD_Write_Cvar("hud_panel_notify_fadetime");
16         HUD_Write_Cvar("hud_panel_notify_icon_aspect");
17 }
18
19 void HUD_Notify_Push(string icon, string attacker, string victim)
20 {
21         if (icon == "")
22                 return;
23
24         ++notify_count;
25         --notify_index;
26
27         if (notify_index == -1)
28                 notify_index = NOTIFY_MAX_ENTRIES-1;
29
30         // Free old strings
31         if (notify_attackers[notify_index])
32                 strunzone(notify_attackers[notify_index]);
33
34         if (notify_victims[notify_index])
35                 strunzone(notify_victims[notify_index]);
36
37         if (notify_icons[notify_index])
38                 strunzone(notify_icons[notify_index]);
39
40         // Allocate new strings
41         if (victim != "")
42         {
43                 notify_attackers[notify_index] = strzone(attacker);
44                 notify_victims[notify_index] = strzone(victim);
45         }
46         else
47         {
48                 // In case of a notification without a victim, the attacker
49                 // is displayed on the victim's side. Instead of special
50                 // treatment later on, we can simply switch them here.
51                 notify_attackers[notify_index] = string_null;
52                 notify_victims[notify_index] = strzone(attacker);
53         }
54
55         notify_icons[notify_index] = strzone(icon);
56         notify_times[notify_index] = time;
57 }
58
59 void HUD_Notify()
60 {
61         if (!autocvar__hud_configure)
62                 if (!autocvar_hud_panel_notify)
63                         return;
64
65         HUD_Panel_LoadCvars();
66
67         if (scoreboard_fade_alpha)
68         {
69                 float minalpha = 1;
70                 if (notify_count == 0)
71                         minalpha = 0; // hide if empty
72                 else if (boxesoverlap(panel_pos, panel_pos + panel_size,
73                         eX * scoreboard_left + eY * scoreboard_top, eX * scoreboard_right + eY * scoreboard_bottom))
74                 {
75                         minalpha = 0.5; // transparent if it may overlap the scoreboard
76                 }
77                 float f = max(minalpha, (1 - scoreboard_fade_alpha));
78                 if (f <= 0)
79                         return;
80                 panel_bg_alpha *= f;
81                 panel_fg_alpha *= f;
82         }
83
84         if (autocvar_hud_panel_notify_dynamichud)
85                 HUD_Scale_Enable();
86         else
87                 HUD_Scale_Disable();
88         HUD_Panel_DrawBg();
89
90         if (!autocvar__hud_configure)
91                 if (notify_count == 0)
92                         return;
93
94         vector pos, size;
95         pos  = panel_pos;
96         size = panel_size;
97
98         if (panel_bg_padding)
99         {
100                 pos  += '1 1 0' * panel_bg_padding;
101                 size -= '2 2 0' * panel_bg_padding;
102         }
103
104         float fade_start = max(0, autocvar_hud_panel_notify_time);
105         if (intermission) // fade out in half the time
106                 fade_start -= (time - intermission_time);
107         float fade_time = max(0, autocvar_hud_panel_notify_fadetime);
108         float icon_aspect = max(1, autocvar_hud_panel_notify_icon_aspect);
109
110         int entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size.y / size.x), NOTIFY_MAX_ENTRIES);
111         float entry_height = size.y / entry_count;
112
113         float panel_width_half = size.x * 0.5;
114         float icon_width_half = entry_height * icon_aspect / 2;
115         float name_maxwidth = panel_width_half - icon_width_half - size.x * NOTIFY_ICON_MARGIN;
116
117         vector font_size = '0.5 0.5 0' * entry_height * autocvar_hud_panel_notify_fontsize;
118         vector icon_size = vec2(icon_aspect, 1) * entry_height;
119         vector icon_left = eX * (panel_width_half - icon_width_half);
120         vector attacker_right = eX * name_maxwidth;
121         vector victim_left = eX * (size.x - name_maxwidth);
122
123         vector attacker_pos, victim_pos, icon_pos;
124         string attacker, victim, icon;
125         int i, j, count, step, limit;
126         float alpha;
127
128         if (autocvar_hud_panel_notify_flip)
129         {
130                 // Order items from the top down
131                 i = 0;
132                 step = +1;
133                 limit = entry_count;
134         }
135         else
136         {
137                 // Order items from the bottom up
138                 i = entry_count - 1;
139                 step = -1;
140                 limit = -1;
141         }
142
143         for (j = notify_index, count = 0; i != limit; i += step, ++j, ++count)
144         {
145                 if(autocvar__hud_configure)
146                 {
147                         attacker = sprintf(_("Player %d"), count + 1);
148                         victim = sprintf(_("Player %d"), count + 2);
149                         icon = REGISTRY_GET(Weapons, min(WEP_FIRST + count * 2, WEP_LAST)).model2;
150                         alpha = bound(0, 1.2 - count / entry_count, 1);
151                 }
152                 else
153                 {
154                         if (j == NOTIFY_MAX_ENTRIES)
155                                 j = 0;
156
157                         if (notify_times[j] + fade_start > time)
158                                 alpha = 1;
159                         else if (fade_time != 0)
160                         {
161                                 alpha = bound(0, (notify_times[j] + fade_start + fade_time - time) / fade_time, 1);
162                                 if (alpha == 0)
163                                         break;
164                         }
165                         else
166                                 break;
167
168                         attacker = notify_attackers[j];
169                         victim = notify_victims[j];
170                         icon = notify_icons[j];
171                 }
172
173                 if (icon != "" && victim != "")
174                 {
175                         vector name_top = eY * (i * entry_height + 0.5 * (entry_height - font_size.y));
176
177                         icon_pos = pos + icon_left + eY * i * entry_height;
178                         drawpic_aspect_skin(icon_pos, icon, icon_size, '1 1 1', panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
179
180                         victim = textShortenToWidth(ColorTranslateRGB(victim), name_maxwidth, font_size, stringwidth_colors);
181                         victim_pos = pos + victim_left + name_top;
182                         drawcolorcodedstring(victim_pos, victim, font_size, panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
183
184                         if (attacker != "")
185                         {
186                                 attacker = textShortenToWidth(ColorTranslateRGB(attacker), name_maxwidth, font_size, stringwidth_colors);
187                                 attacker_pos = pos + attacker_right - eX * stringwidth(attacker, true, font_size) + name_top;
188                                 drawcolorcodedstring(attacker_pos, attacker, font_size, panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
189                         }
190                 }
191         }
192
193         notify_count = count;
194 }