]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/hud/panel/score.qc
Added place indicator in duel frag notification
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / score.qc
1 #include "score.qh"
2
3 #include <client/draw.qh>
4 #include <client/hud/panel/scoreboard.qh>
5 #include <common/ent_cs.qh>
6 #include <common/scores.qh>
7
8 // Score (#7)
9
10 void HUD_Score_Export(int fh)
11 {
12         // allow saving cvars that aesthetically change the panel into hud skin files
13         HUD_Write_Cvar("hud_panel_score_rankings");
14 }
15
16 void HUD_Score_Rankings(vector pos, vector mySize, entity me)
17 {       
18         float score;
19         entity tm = NULL, pl;
20         int SCOREPANEL_MAX_ENTRIES = 6;
21         float SCOREPANEL_ASPECTRATIO = 2;
22         int entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize.y/mySize.x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
23         vector fontsize = '1 1 0' * (mySize.y/entries);
24
25         vector rgb, score_color;
26         rgb = '1 1 1';
27         score_color = '1 1 1';
28
29         float name_size = mySize.x*0.75;
30         float spacing_size = mySize.x*0.04;
31         const float highlight_alpha = 0.2;
32         int i = 0, first_pl = 0;
33         bool me_printed = false;
34         string s;
35         if (autocvar__hud_configure)
36         {
37                 float players_per_team = 0;
38                 if (team_count)
39                 {
40                         // show team scores in the first line
41                         float score_size = mySize.x / team_count;
42                         players_per_team = max(2, ceil((entries - 1) / team_count));
43                         for(i=0; i<team_count; ++i) {
44                                 if (i == floor((entries - 2) / players_per_team) || (entries == 1 && i == 0))
45                                         HUD_Panel_DrawHighlight(pos + eX * score_size * i, vec2(score_size, fontsize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
46                                 drawstring_aspect(pos + eX * score_size * i, ftos(175 - 23*i), vec2(score_size, fontsize.y), Team_ColorRGB(ColorByTeam(i)) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
47                         }
48                         first_pl = 1;
49                         pos.y += fontsize.y;
50                 }
51                 score = 10 + SCOREPANEL_MAX_ENTRIES * 3;
52                 for (i=first_pl; i<entries; ++i)
53                 {
54                         //simulate my score is lower than all displayed players,
55                         //so that I don't appear at all showing pure rankings.
56                         //This is to better show the difference between the 2 ranking views
57                         if (i == entries-1 && autocvar_hud_panel_score_rankings == 1)
58                         {
59                                 rgb = '1 1 0';
60                                 drawfill(pos, vec2(mySize.x, fontsize.y), rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
61                                 s = entcs_GetName(player_localnum);
62                                 score = 7;
63                         }
64                         else
65                         {
66                                 s = sprintf(_("Player %d"), i + 1 - first_pl);
67                                 score -= 3;
68                         }
69
70                         if (team_count)
71                                 score_color = Team_ColorRGB(ColorByTeam(floor((i - first_pl) / players_per_team))) * 0.8;
72                         s = textShortenToWidth(s, name_size, fontsize, stringwidth_colors);
73                         drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
74                         drawstring(pos + eX * (name_size + spacing_size), ftos(score), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
75                         pos.y += fontsize.y;
76                 }
77                 return;
78         }
79         
80         /*
81         if (team_count)
82         {
83                 // show team scores in the first line
84                 float score_size = mySize.x / team_count;
85                 for(tm = teams.sort_next; tm; tm = tm.sort_next) {
86                         if(tm.team == NUM_SPECTATOR)
87                                 continue;
88                         if(!tm.team)
89                                 continue;
90
91                         if (tm.team == myteam)
92                                 drawfill(pos + eX * score_size * i, vec2(score_size, fontsize.y), '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
93                         drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores(ts_primary))), vec2(score_size, fontsize.y), Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
94                         ++i;
95                 }
96                 first_pl = 1;
97                 pos.y += fontsize.y;
98                 tm = teams.sort_next;
99         }*/
100         
101         
102         // z411 Basic team stats
103         if (team_count)
104         {
105                 i = 0;
106                 for(tm = teams.sort_next; tm; tm = tm.sort_next) {
107                         if(tm.team == NUM_SPECTATOR)
108                                 continue;
109                         if(!tm.team)
110                                 continue;
111
112                         /*if (tm.team == myteam)
113                                 drawfill(pos + eX * score_size * i, vec2(score_size, fontsize.y), '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
114                         drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores(ts_primary))), vec2(score_size, fontsize.y), Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
115                         ++i;*/
116                         
117                         if (tm.team == myteam)
118                         {
119                                 if (i == 0)
120                                         rgb = '0 1 0'; //first: green
121                                 me_printed = true;
122                                 drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
123                         }
124                         
125                         score_color = Team_ColorRGB(tm.team) * 0.8;
126                         
127                         // TODO secondary scores test, remove
128                         if(gametype.m_modscores)
129                         {
130                                 string icon;
131                                 if(tm.team == NUM_TEAM_1)
132                                         icon = "gfx/hud/luma/player_red";
133                                 else if(tm.team == NUM_TEAM_2)
134                                         icon = "gfx/hud/luma/player_blue";
135                                 else
136                                         icon = "gfx/hud/luma/player_neutral";
137                                 
138                                 vector icon_sz = draw_getimagesize(icon);
139                                 vector icon_sz_new = vec2(fontsize.y*(icon_sz.x/icon_sz.y), fontsize.y);
140                                 
141                                 s = ftos(gametype.m_modscores(tm.team));
142                                 float s_width = stringwidth(s, false, fontsize) + icon_sz_new.x;
143                                 
144                                 //drawfill(pos, eX * s_width + eY * fontsize.y, score_color, panel_fg_alpha * 0.3, DRAWFLAG_NORMAL);
145                                 drawpic(pos, icon, icon_sz_new, '1 1 1', panel_fg_alpha * 0.7, DRAWFLAG_NORMAL);
146                                 drawstring(pos + eX * icon_sz_new.x, s, fontsize, '1 1 1', panel_fg_alpha * 0.7, DRAWFLAG_NORMAL);
147                                 
148                                 s = textShortenToWidth(Team_CustomName(tm.team), name_size - s_width, fontsize, stringwidth_colors);
149                         } else
150                                 s = textShortenToWidth(Team_CustomName(tm.team), name_size, fontsize, stringwidth_colors);
151                         // TODO end
152                         
153                         drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
154                         
155                         draw_beginBoldFont();
156                         drawstring(pos + eX * (name_size + spacing_size), ftos(tm.(teamscores(ts_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
157                         draw_endBoldFont();
158                         
159                         pos.y += fontsize.y;
160                         ++i;
161                 }
162         } else {
163                 i = first_pl;
164                 
165                 do
166                 for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
167                 {
168                         if ((team_count && pl.team != tm.team) || pl.team == NUM_SPECTATOR)
169                                 continue;
170
171                         if (i == entries-1 && !me_printed && pl != me)
172                         if (autocvar_hud_panel_score_rankings == 1 && spectatee_status != -1)
173                         {
174                                 for (pl = me.sort_next; pl; pl = pl.sort_next)
175                                         if (pl.team != NUM_SPECTATOR)
176                                                 break;
177
178                                 if (pl)
179                                         rgb = '1 1 0'; //not last but not among the leading players: yellow
180                                 else
181                                         rgb = '1 0 0'; //last: red
182                                 pl = me;
183                         }
184                 
185                         if (team_count)
186                                 score_color = Team_ColorRGB(pl.team) * 0.8;
187                         
188                         if (pl == me)
189                         {
190                                 if (i == first_pl)
191                                         rgb = '0 1 0'; //first: green
192                                 me_printed = true;
193                                 drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
194                         }
195                         
196                         s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
197                         drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
198                         drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores(ps_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
199                         pos.y += fontsize.y;
200                         ++i;
201                 }
202                 while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != NUM_SPECTATOR || (tm = tm.sort_next)));
203         }
204 }
205
206 void HUD_Score()
207 {
208         if(!autocvar__hud_configure)
209         {
210                 if(!autocvar_hud_panel_score) return;
211                 if(MUTATOR_CALLHOOK(HUD_Score_show)) return;
212         }
213         
214         if (!scoreboard_fade_alpha) // the scoreboard too calls Scoreboard_UpdatePlayerTeams
215                 Scoreboard_UpdatePlayerTeams();
216         
217         if(spectatee_status) {
218                 if(teamplay && autocvar_hud_spectatorteamdisplay) return;
219                 if(gametype == MAPINFO_TYPE_DUEL && autocvar_hud_spectatordueldisplay) return;
220         }
221
222         HUD_Panel_LoadCvars();
223         vector pos, mySize;
224         pos = panel_pos;
225         mySize = panel_size;
226
227         if (autocvar_hud_panel_score_dynamichud)
228                 HUD_Scale_Enable();
229         else
230                 HUD_Scale_Disable();
231         HUD_Panel_DrawBg();
232         if(panel_bg_padding)
233         {
234                 pos += '1 1 0' * panel_bg_padding;
235                 mySize -= '2 2 0' * panel_bg_padding;
236         }
237
238         float score, distribution = 0;
239         string sign;
240         vector distribution_color;
241         entity tm, pl, me;
242
243         me = playerslots[current_player];
244
245         if((scores_flags(ps_primary) & SFL_TIME) && !teamplay) { // race/cts record display on HUD
246                 string timer, distrtimer;
247
248                 pl = players.sort_next;
249                 if(pl == me)
250                         pl = pl.sort_next;
251                 if(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)
252                         if(pl.scores(ps_primary) == 0)
253                                 pl = NULL;
254
255                 score = me.(scores(ps_primary));
256                 timer = TIME_ENCODED_TOSTRING(score);
257
258                 draw_beginBoldFont();
259                 if (pl && ((!(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)) || score)) {
260                         // distribution display
261                         distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
262
263                         distrtimer = ftos_decimals(fabs(distribution/(10 ** TIME_DECIMALS)), TIME_DECIMALS);
264
265                         if (distribution <= 0) {
266                                 distribution_color = '0 1 0';
267                                 sign = "-";
268                         }
269                         else {
270                                 distribution_color = '1 0 0';
271                                 sign = "+";
272                         }
273                         drawstring_aspect(pos + eX * 0.75 * mySize.x, strcat(sign, distrtimer), vec2(0.25 * mySize.x, (1/3) * mySize.y), distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
274                 }
275                 // race record display
276                 if (distribution <= 0)
277                         HUD_Panel_DrawHighlight(pos, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
278                 drawstring_aspect(pos, timer, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
279                 draw_endBoldFont();
280         } else if (!teamplay) { // non-teamgames
281                 if ((spectatee_status == -1 && !autocvar__hud_configure) || autocvar_hud_panel_score_rankings)
282                 {
283                         HUD_Score_Rankings(pos, mySize, me);
284                         return;
285                 }
286                 // me vector := [team/connected frags id]
287                 pl = players.sort_next;
288                 if(pl == me)
289                         pl = pl.sort_next;
290
291                 if(autocvar__hud_configure)
292                         distribution = 42;
293                 else if(pl)
294                         distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
295                 else
296                         distribution = 0;
297
298                 score = me.(scores(ps_primary));
299                 if(autocvar__hud_configure)
300                         score = 123;
301
302                 if(distribution >= 5)
303                         distribution_color = eY;
304                 else if(distribution >= 0)
305                         distribution_color = '1 1 1';
306                 else if(distribution >= -5)
307                         distribution_color = '1 1 0';
308                 else
309                         distribution_color = eX;
310
311                 string distribution_str;
312                 distribution_str = ftos(distribution);
313                 draw_beginBoldFont();
314                 if (distribution >= 0)
315                 {
316                         if (distribution > 0)
317                                 distribution_str = strcat("+", distribution_str);
318                         HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
319                 }
320                 drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize.x + eY * mySize.y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
321                 drawstring_aspect(pos + eX * 0.75 * mySize.x, distribution_str, vec2(0.25 * mySize.x, (1/3) * mySize.y), distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
322                 draw_endBoldFont();
323         } else { // teamgames
324                 float row, column, rows = 0, columns = 0;
325                 vector offset = '0 0 0';
326                 vector score_pos, score_size; //for scores other than myteam
327                 if(autocvar_hud_panel_score_rankings)
328                 {
329                         HUD_Score_Rankings(pos, mySize, me);
330                         return;
331                 }
332                 if(spectatee_status == -1)
333                 {
334                         rows = HUD_GetRowCount(team_count, mySize, 3);
335                         columns = ceil(team_count/rows);
336                         score_size = vec2(mySize.x / columns, mySize.y / rows);
337
338                         float newSize;
339                         if(score_size.x/score_size.y > 3)
340                         {
341                                 newSize = 3 * score_size.y;
342                                 offset.x = score_size.x - newSize;
343                                 pos.x += offset.x/2;
344                                 score_size.x = newSize;
345                         }
346                         else
347                         {
348                                 newSize = 1/3 * score_size.x;
349                                 offset.y = score_size.y - newSize;
350                                 pos.y += offset.y/2;
351                                 score_size.y = newSize;
352                         }
353                 }
354                 else
355                         score_size = vec2(mySize.x / 4, mySize.y / 3);
356
357                 float max_fragcount;
358                 max_fragcount = -99;
359                 draw_beginBoldFont();
360                 row = column = 0;
361                 for(tm = teams.sort_next; tm; tm = tm.sort_next) {
362                         if(tm.team == NUM_SPECTATOR)
363                                 continue;
364                         if(!tm.team)
365                                 continue;
366
367                         score = tm.(teamscores(ts_primary));
368                         if(autocvar__hud_configure)
369                                 score = 123;
370
371                         if (score > max_fragcount)
372                                 max_fragcount = score;
373
374                         if (spectatee_status == -1)
375                         {
376                                 score_pos = pos + vec2(column * (score_size.x + offset.x), row * (score_size.y + offset.y));
377                                 if (max_fragcount == score)
378                                         HUD_Panel_DrawHighlight(score_pos, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
379                                 drawstring_aspect(score_pos, ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
380                                 ++row;
381                                 if(row >= rows)
382                                 {
383                                         row = 0;
384                                         ++column;
385                                 }
386                         }
387                         else if(tm.team == myteam) {
388                                 if (max_fragcount == score)
389                                         HUD_Panel_DrawHighlight(pos, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
390                                 drawstring_aspect(pos, ftos(score), vec2(0.75 * mySize.x, mySize.y), Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
391                         } else {
392                                 if (max_fragcount == score)
393                                         HUD_Panel_DrawHighlight(pos + vec2(0.75 * mySize.x, (1/3) * rows * mySize.y), score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
394                                 drawstring_aspect(pos + vec2(0.75 * mySize.x, (1/3) * rows * mySize.y), ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
395                                 ++rows;
396                         }
397                 }
398                 draw_endBoldFont();
399         }
400 }