Purge client/defs.qh
[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         if (team_count)
85         {
86                 // show team scores in the first line
87                 float score_size = mySize.x / team_count;
88                 for(tm = teams.sort_next; tm; tm = tm.sort_next) {
89                         if(tm.team == NUM_SPECTATOR)
90                                 continue;
91                         if(!tm.team)
92                                 continue;
93
94                         if (tm.team == myteam)
95                                 drawfill(pos + eX * score_size * i, vec2(score_size, fontsize.y), '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
96                         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);
97                         ++i;
98                 }
99                 first_pl = 1;
100                 pos.y += fontsize.y;
101                 tm = teams.sort_next;
102         }
103         i = first_pl;
104
105         do
106         for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
107         {
108                 if ((team_count && pl.team != tm.team) || pl.team == NUM_SPECTATOR)
109                         continue;
110
111                 if (i == entries-1 && !me_printed && pl != me)
112                 if (autocvar_hud_panel_score_rankings == 1 && spectatee_status != -1)
113                 {
114                         for (pl = me.sort_next; pl; pl = pl.sort_next)
115                                 if (pl.team != NUM_SPECTATOR)
116                                         break;
117
118                         if (pl)
119                                 rgb = '1 1 0'; //not last but not among the leading players: yellow
120                         else
121                                 rgb = '1 0 0'; //last: red
122                         pl = me;
123                 }
124
125                 if (pl == me)
126                 {
127                         if (i == first_pl)
128                                 rgb = '0 1 0'; //first: green
129                         me_printed = true;
130                         drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
131                 }
132                 if (team_count)
133                         score_color = Team_ColorRGB(pl.team) * 0.8;
134                 s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
135                 drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
136                 drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores(ps_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
137                 pos.y += fontsize.y;
138                 ++i;
139         }
140         while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != NUM_SPECTATOR || (tm = tm.sort_next)));
141 }
142
143 void HUD_Score()
144 {
145         if(!autocvar__hud_configure)
146         {
147                 if(!autocvar_hud_panel_score) return;
148                 if(MUTATOR_CALLHOOK(HUD_Score_show)) return;
149         }
150
151         HUD_Panel_LoadCvars();
152         vector pos, mySize;
153         pos = panel_pos;
154         mySize = panel_size;
155
156         if (autocvar_hud_panel_score_dynamichud)
157                 HUD_Scale_Enable();
158         else
159                 HUD_Scale_Disable();
160         HUD_Panel_DrawBg();
161         if(panel_bg_padding)
162         {
163                 pos += '1 1 0' * panel_bg_padding;
164                 mySize -= '2 2 0' * panel_bg_padding;
165         }
166
167         float score, distribution = 0;
168         string sign;
169         vector distribution_color;
170         entity tm, pl, me;
171
172         me = playerslots[current_player];
173
174         if((scores_flags(ps_primary) & SFL_TIME) && !teamplay) { // race/cts record display on HUD
175                 string timer, distrtimer;
176
177                 pl = players.sort_next;
178                 if(pl == me)
179                         pl = pl.sort_next;
180                 if(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)
181                         if(pl.scores(ps_primary) == 0)
182                                 pl = NULL;
183
184                 score = me.(scores(ps_primary));
185                 timer = TIME_ENCODED_TOSTRING(score);
186
187                 draw_beginBoldFont();
188                 if (pl && ((!(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)) || score)) {
189                         // distribution display
190                         distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
191
192                         distrtimer = ftos_decimals(fabs(distribution/(10 ** TIME_DECIMALS)), TIME_DECIMALS);
193
194                         if (distribution <= 0) {
195                                 distribution_color = '0 1 0';
196                                 sign = "-";
197                         }
198                         else {
199                                 distribution_color = '1 0 0';
200                                 sign = "+";
201                         }
202                         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);
203                 }
204                 // race record display
205                 if (distribution <= 0)
206                         HUD_Panel_DrawHighlight(pos, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
207                 drawstring_aspect(pos, timer, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
208                 draw_endBoldFont();
209         } else if (!teamplay) { // non-teamgames
210                 if ((spectatee_status == -1 && !autocvar__hud_configure) || autocvar_hud_panel_score_rankings)
211                 {
212                         HUD_Score_Rankings(pos, mySize, me);
213                         return;
214                 }
215                 // me vector := [team/connected frags id]
216                 pl = players.sort_next;
217                 if(pl == me)
218                         pl = pl.sort_next;
219
220                 if(autocvar__hud_configure)
221                         distribution = 42;
222                 else if(pl)
223                         distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
224                 else
225                         distribution = 0;
226
227                 score = me.(scores(ps_primary));
228                 if(autocvar__hud_configure)
229                         score = 123;
230
231                 if(distribution >= 5)
232                         distribution_color = eY;
233                 else if(distribution >= 0)
234                         distribution_color = '1 1 1';
235                 else if(distribution >= -5)
236                         distribution_color = '1 1 0';
237                 else
238                         distribution_color = eX;
239
240                 string distribution_str;
241                 distribution_str = ftos(distribution);
242                 draw_beginBoldFont();
243                 if (distribution >= 0)
244                 {
245                         if (distribution > 0)
246                                 distribution_str = strcat("+", distribution_str);
247                         HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
248                 }
249                 drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize.x + eY * mySize.y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
250                 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);
251                 draw_endBoldFont();
252         } else { // teamgames
253                 float row, column, rows = 0, columns = 0;
254                 vector offset = '0 0 0';
255                 vector score_pos, score_size; //for scores other than myteam
256                 if(autocvar_hud_panel_score_rankings)
257                 {
258                         HUD_Score_Rankings(pos, mySize, me);
259                         return;
260                 }
261                 if(spectatee_status == -1)
262                 {
263                         rows = HUD_GetRowCount(team_count, mySize, 3);
264                         columns = ceil(team_count/rows);
265                         score_size = vec2(mySize.x / columns, mySize.y / rows);
266
267                         float newSize;
268                         if(score_size.x/score_size.y > 3)
269                         {
270                                 newSize = 3 * score_size.y;
271                                 offset.x = score_size.x - newSize;
272                                 pos.x += offset.x/2;
273                                 score_size.x = newSize;
274                         }
275                         else
276                         {
277                                 newSize = 1/3 * score_size.x;
278                                 offset.y = score_size.y - newSize;
279                                 pos.y += offset.y/2;
280                                 score_size.y = newSize;
281                         }
282                 }
283                 else
284                         score_size = vec2(mySize.x / 4, mySize.y / 3);
285
286                 float max_fragcount;
287                 max_fragcount = -99;
288                 draw_beginBoldFont();
289                 row = column = 0;
290                 for(tm = teams.sort_next; tm; tm = tm.sort_next) {
291                         if(tm.team == NUM_SPECTATOR)
292                                 continue;
293                         if(!tm.team)
294                                 continue;
295
296                         score = tm.(teamscores(ts_primary));
297                         if(autocvar__hud_configure)
298                                 score = 123;
299
300                         if (score > max_fragcount)
301                                 max_fragcount = score;
302
303                         if (spectatee_status == -1)
304                         {
305                                 score_pos = pos + vec2(column * (score_size.x + offset.x), row * (score_size.y + offset.y));
306                                 if (max_fragcount == score)
307                                         HUD_Panel_DrawHighlight(score_pos, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
308                                 drawstring_aspect(score_pos, ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
309                                 ++row;
310                                 if(row >= rows)
311                                 {
312                                         row = 0;
313                                         ++column;
314                                 }
315                         }
316                         else if(tm.team == myteam) {
317                                 if (max_fragcount == score)
318                                         HUD_Panel_DrawHighlight(pos, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
319                                 drawstring_aspect(pos, ftos(score), vec2(0.75 * mySize.x, mySize.y), Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
320                         } else {
321                                 if (max_fragcount == score)
322                                         HUD_Panel_DrawHighlight(pos + vec2(0.75 * mySize.x, (1/3) * rows * mySize.y), score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
323                                 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);
324                                 ++rows;
325                         }
326                 }
327                 draw_endBoldFont();
328         }
329 }