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