Xonotic
score.qc
Go to the documentation of this file.
1 #include "score.qh"
2 
3 #include <client/draw.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;
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  if (!scoreboard_fade_alpha) // the scoreboard too calls Scoreboard_UpdatePlayerTeams
82  if (team_count)
83  {
84  // show team scores in the first line
85  float score_size = mySize.x / team_count;
86  for(tm = teams.sort_next; tm; tm = tm.sort_next) {
87  if(tm.team == NUM_SPECTATOR)
88  continue;
89  if(!tm.team)
90  continue;
91 
92  if (tm.team == myteam)
93  drawfill(pos + eX * score_size * i, vec2(score_size, fontsize.y), '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
94  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);
95  ++i;
96  }
97  first_pl = 1;
98  pos.y += fontsize.y;
99  tm = teams.sort_next;
100  }
101  i = first_pl;
102 
103  do
104  for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
105  {
106  if ((team_count && pl.team != tm.team) || pl.team == NUM_SPECTATOR)
107  continue;
108 
109  if (i == entries-1 && !me_printed && pl != me)
111  {
112  for (pl = me.sort_next; pl; pl = pl.sort_next)
113  if (pl.team != NUM_SPECTATOR)
114  break;
115 
116  if (pl)
117  rgb = '1 1 0'; //not last but not among the leading players: yellow
118  else
119  rgb = '1 0 0'; //last: red
120  pl = me;
121  }
122 
123  if (pl == me)
124  {
125  if (i == first_pl)
126  rgb = '0 1 0'; //first: green
127  me_printed = true;
128  drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
129  }
130  if (team_count)
131  score_color = Team_ColorRGB(pl.team) * 0.8;
132  s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
133  drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
134  drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores(ps_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
135  pos.y += fontsize.y;
136  ++i;
137  }
138  while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != NUM_SPECTATOR || (tm = tm.sort_next)));
139 }
140 
141 void HUD_Score()
142 {
144  {
145  if(!autocvar_hud_panel_score) return;
146  if(MUTATOR_CALLHOOK(HUD_Score_show)) return;
147  }
148 
150  vector pos, mySize;
151  pos = panel_pos;
152  mySize = panel_size;
153 
156  else
159  if(panel_bg_padding)
160  {
161  pos += '1 1 0' * panel_bg_padding;
162  mySize -= '2 2 0' * panel_bg_padding;
163  }
164 
165  float score, distribution = 0;
166  string sign;
167  vector distribution_color;
168  entity tm, pl, me;
169 
171 
172  if((scores_flags(ps_primary) & SFL_TIME) && !teamplay) { // race/cts record display on HUD
173  string timer, distrtimer;
174 
175  pl = players.sort_next;
176  if(pl == me)
177  pl = pl.sort_next;
179  if(pl.scores(ps_primary) == 0)
180  pl = NULL;
181 
182  score = me.(scores(ps_primary));
183  timer = TIME_ENCODED_TOSTRING(score);
184 
186  if (pl && ((!(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)) || score)) {
187  // distribution display
188  distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
189 
190  distrtimer = ftos_decimals(fabs(distribution/(10 ** TIME_DECIMALS)), TIME_DECIMALS);
191 
192  if (distribution <= 0) {
193  distribution_color = '0 1 0';
194  sign = "-";
195  }
196  else {
197  distribution_color = '1 0 0';
198  sign = "+";
199  }
200  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);
201  }
202  // race record display
203  if (distribution <= 0)
204  HUD_Panel_DrawHighlight(pos, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
205  drawstring_aspect(pos, timer, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
207  } else if (!teamplay) { // non-teamgames
209  {
210  HUD_Score_Rankings(pos, mySize, me);
211  return;
212  }
213  // me vector := [team/connected frags id]
214  pl = players.sort_next;
215  if(pl == me)
216  pl = pl.sort_next;
217 
219  distribution = 42;
220  else if(pl)
221  distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
222  else
223  distribution = 0;
224 
225  score = me.(scores(ps_primary));
227  score = 123;
228 
229  if(distribution >= 5)
230  distribution_color = eY;
231  else if(distribution >= 0)
232  distribution_color = '1 1 1';
233  else if(distribution >= -5)
234  distribution_color = '1 1 0';
235  else
236  distribution_color = eX;
237 
238  string distribution_str;
239  distribution_str = ftos(distribution);
241  if (distribution >= 0)
242  {
243  if (distribution > 0)
244  distribution_str = strcat("+", distribution_str);
245  HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
246  }
247  drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize.x + eY * mySize.y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
248  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);
250  } else { // teamgames
251  float row, column, rows = 0, columns = 0;
252  vector offset = '0 0 0';
253  vector score_pos, score_size; //for scores other than myteam
255  {
256  HUD_Score_Rankings(pos, mySize, me);
257  return;
258  }
259  if(spectatee_status == -1)
260  {
261  rows = HUD_GetRowCount(team_count, mySize, 3);
262  columns = ceil(team_count/rows);
263  score_size = vec2(mySize.x / columns, mySize.y / rows);
264 
265  float newSize;
266  if(score_size.x/score_size.y > 3)
267  {
268  newSize = 3 * score_size.y;
269  offset.x = score_size.x - newSize;
270  pos.x += offset.x/2;
271  score_size.x = newSize;
272  }
273  else
274  {
275  newSize = 1/3 * score_size.x;
276  offset.y = score_size.y - newSize;
277  pos.y += offset.y/2;
278  score_size.y = newSize;
279  }
280  }
281  else
282  score_size = vec2(mySize.x / 4, mySize.y / 3);
283 
284  float max_fragcount;
285  max_fragcount = -99;
287  row = column = 0;
288  for(tm = teams.sort_next; tm; tm = tm.sort_next) {
289  if(tm.team == NUM_SPECTATOR)
290  continue;
291  if(!tm.team)
292  continue;
293 
294  score = tm.(teamscores(ts_primary));
296  score = 123;
297 
298  if (score > max_fragcount)
299  max_fragcount = score;
300 
301  if (spectatee_status == -1)
302  {
303  score_pos = pos + vec2(column * (score_size.x + offset.x), row * (score_size.y + offset.y));
304  if (max_fragcount == score)
305  HUD_Panel_DrawHighlight(score_pos, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
306  drawstring_aspect(score_pos, ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
307  ++row;
308  if(row >= rows)
309  {
310  row = 0;
311  ++column;
312  }
313  }
314  else if(tm.team == myteam) {
315  if (max_fragcount == score)
316  HUD_Panel_DrawHighlight(pos, vec2(0.75 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
317  drawstring_aspect(pos, ftos(score), vec2(0.75 * mySize.x, mySize.y), Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
318  } else {
319  if (max_fragcount == score)
320  HUD_Panel_DrawHighlight(pos + vec2(0.75 * mySize.x, (1/3) * rows * mySize.y), score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
321  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);
322  ++rows;
323  }
324  }
326  }
327 }
#define draw_endBoldFont()
Definition: draw.qh:5
float panel_fg_alpha
Definition: hud.qh:166
ERASEABLE string ftos_decimals(float number, int decimals)
converts a number to a string with the indicated number of decimals
Definition: string.qh:450
float current_player
Definition: hud.qh:182
const int NUM_SPECTATOR
Definition: teams.qh:23
void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag)
Definition: hud.qc:377
void drawstring_aspect(vector pos, string text, vector sz, vector color, float theAlpha, float drawflag)
Definition: draw.qc:102
const vector eY
Definition: vector.qh:45
float HUD_GetRowCount(int item_count, vector size, float item_aspect)
Definition: hud.qc:165
void HUD_Score_Rankings(vector pos, vector mySize, entity me)
Definition: score.qc:16
bool autocvar__hud_configure
Definition: hud_config.qh:3
#define stringwidth
Definition: csprogsdefs.qh:29
#define draw_beginBoldFont()
Definition: draw.qh:4
vector Team_ColorRGB(int teamid)
Definition: teams.qh:76
vector panel_size
Definition: hud.qh:160
entity() spawn
void HUD_Scale_Disable()
Definition: hud.qc:83
string textShortenToWidth(string theText, float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition: util.qc:956
entity playerslots[255]
Definition: main.qh:70
#define SFL_ZERO_IS_WORST
Definition: scores.qh:121
#define TIME_ENCODED_TOSTRING(n)
Definition: util.qh:57
entity teams
Definition: main.qh:44
bool autocvar_hud_panel_score
Definition: score.qh:4
#define HUD_Panel_DrawBg()
Definition: hud.qh:54
void HUD_Score_Export(int fh)
Definition: score.qc:10
void HUD_Scale_Enable()
Definition: hud.qc:90
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
void HUD_Score()
Definition: score.qc:141
#define NULL
Definition: post.qh:17
const float DRAWFLAG_NORMAL
Definition: csprogsdefs.qc:317
vector panel_pos
Definition: hud.qh:159
float teamplay
Definition: progsdefs.qc:31
#define scores_flags(this)
Definition: scores.qh:140
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define ColorByTeam(number)
Definition: teams.qh:219
entity players
Definition: main.qh:43
float spectatee_status
Definition: main.qh:166
const vector eX
Definition: vector.qh:44
float team_count
Definition: main.qh:45
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
#define vec2(...)
Definition: vector.qh:90
PlayerScoreField ps_primary
Definition: hud.qh:116
void Scoreboard_UpdatePlayerTeams()
Definition: scoreboard.qc:210
#define HUD_Write_Cvar(cvar)
Definition: hud_config.qh:38
int ts_primary
Definition: hud.qh:117
const int TIME_DECIMALS
Definition: util.qh:55
float player_localnum
Definition: csprogsdefs.qc:20
bool autocvar_hud_panel_score_rankings
Definition: score.qh:6
bool autocvar_hud_panel_score_dynamichud
Definition: score.qh:5
const int SFL_TIME
Display as mm:ss.s, value is stored as 10ths of a second (AND 0 is the worst possible value!) ...
Definition: scores.qh:118
float scoreboard_fade_alpha
Definition: scoreboard.qh:10
void HUD_Panel_LoadCvars()
Definition: hud.qc:216
float panel_bg_padding
Definition: hud.qh:171