]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/sbar.qc
Changed keyhunt keystates to use a stat var instead of sending cvars.
[divverent/nexuiz.git] / data / qcsrc / client / sbar.qc
1
2 float sb_lines; // still don't know what to do with that NOTE: check dp's sbar.c to see what that should be
3
4 vector sbar;
5
6 entity sortedPlayers;
7 entity sortedTeams;
8
9 .float sb_frags;
10 .float sb_team;
11 .float sb_player;
12
13 void Sbar_FinaleOverlay()
14 {
15         vector pos;
16         pos_x = (vid_conwidth - 1)/2;
17         pos_y = 16;
18         pos_z = 0;
19         drawpic(pos, "gfx/finale", '0 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);
20 }
21
22 void Sbar_DrawWeapon(float nr, float fade, float active)
23 {
24         vector pos, vsize, color;
25         float value;
26         
27         value = (active) ? 1 : 0.6;
28         color_x = color_y = color_z = value;
29         
30         if(sbar_hudselector == 1)
31         {
32                 // width = 300, height = 100
33                 const float w_width = 32, w_height = 12, w_space = 2, font_size = 8;
34                 
35                 pos_x = (vid_conwidth - w_width * 9) * 0.5 + w_width * nr;
36                 pos_y = (vid_conheight - w_height);
37                 pos_z = 0;
38                 vsize_x = w_width;
39                 vsize_y = w_height;
40                 vsize_z = 0;
41                 drawpic(pos, strcat("gfx/inv_weapon", ftos(nr)), vsize, color, value * fade * sbar_alpha_fg, 0);
42                 pos_x += w_space;
43                 pos_y += w_space;
44                 vsize_x = font_size;
45                 vsize_y = font_size;
46                 vsize_z = 0;
47                 drawstring(pos, ftos(nr+1), vsize, '1 1 0', sbar_alpha_fg, 0);
48
49         }
50         else
51         {
52                 // width = 300, height = 100
53                 const float w2_width = 300, w2_height = 100, w2_space = 10;
54                 const float w2_scale = 0.4;
55
56                 pos_x = vid_conwidth - (w2_width + w2_space) * w2_scale;
57                 pos_y = (w2_height + w2_space) * w2_scale * nr + w2_space;
58                 pos_z = 0;
59                 vsize_x = w2_width * w2_scale;
60                 vsize_y = w2_height * w2_scale;
61                 vsize_z = 0;
62                 
63                 drawpic(pos, strcat("gfx/inv_weapon", ftos(nr)), vsize, color, value * fade * sbar_alpha_fg, 0);
64         }
65 }
66 void Sbar_DrawXNum (vector pos, float num, float digits, float lettersize, vector rgb, float a, float dflags)
67 {
68         float l, i;
69         string str, tmp;
70         float minus;
71         vector vsize;
72
73         vsize_x = vsize_y = lettersize;
74         vsize_z = 0;
75
76         if(num < 0)
77         {
78                 minus = true;
79                 num = -num;
80                 pos_x -= lettersize;
81         } else
82                 minus = false;
83         
84         if(digits < 0)
85         {
86                 tmp = ftos(num);
87                 digits = -digits;
88                 str = strcat(substring("0000000000", 0, digits - strlen(tmp)), tmp);
89         } else
90                 str = ftos(num);
91         
92         l = strlen(str);
93
94         if(l > digits)
95         {
96                 str = substring(str, l-digits, 999);
97                 l = strlen(str);
98         } else if(l < digits)
99                 pos_x += (digits-l) * lettersize;
100
101         if(minus)
102         {
103                 drawpic(sbar + pos, "gfx/num_minus", vsize, rgb, a * sbar_alpha_fg, dflags);
104                 pos_x += lettersize;
105         }
106
107         for(i = 0; i < l; ++i)
108         {
109                 drawpic(sbar + pos, strcat("gfx/num_", substring(str, i, 1)), vsize, rgb, a * sbar_alpha_fg, dflags);
110                 pos_x += lettersize;
111         }
112 }
113
114 float Sbar_PlayerCmp(entity l, entity r)
115 {
116         if(teamplay)
117         {
118                 if(l.sb_team < r.sb_team)
119                         return true;
120                 else if(l.sb_team > r.sb_team)
121                         return false;
122         }
123         if(l.sb_frags > r.sb_frags)
124                 return true;
125         else if(l.sb_frags < r.sb_frags)
126                 return false;
127         return (l.sb_player > r.sb_player);
128 }
129 float Sbar_TeamCmp(entity l, entity r)
130 {
131         if(l.sb_frags > r.sb_frags)
132                 return true;
133         else if(l.sb_frags < r.sb_frags)
134                 return false;
135         return (l.sb_player > r.sb_player);
136 }
137
138 void Sbar_SortFrags()
139 {
140         float i;
141         entity tmp;
142         entity t1, t2, t3, t4, ts;
143         
144         Sort_Remove(sortedPlayers);
145         sortedPlayers = Sort_New(Sbar_PlayerCmp);
146
147         numteams = 0;
148         if(teamplay)
149         {
150                 Sort_Remove(sortedTeams);
151         
152                 t1 = spawn();
153                 t2 = spawn();
154                 t3 = spawn();
155                 t4 = spawn();
156                 ts = spawn();
157         
158                 t1.sb_team = COLOR_TEAM1;
159                 t2.sb_team = COLOR_TEAM2;
160                 t3.sb_team = COLOR_TEAM3;
161                 t4.sb_team = COLOR_TEAM4;
162                 ts.sb_team = COLOR_SPECTATOR;
163
164                 t1.sb_player = t2.sb_player = t3.sb_player = t4.sb_player = ts.sb_player = 0;
165                 t1.sb_frags = t2.sb_frags = t3.sb_frags = t4.sb_frags = 0;
166                 sortedTeams = Sort_New(Sbar_TeamCmp);
167                 
168                 for(i = 0; i < maxclients; ++i)
169                 {
170                         if(strlen(getplayerkey(i, "name")) <= 0)
171                                 continue;
172                 
173                         tmp = spawn();
174                         tmp.sb_player = i;
175                         tmp.sb_frags = stof(getplayerkey(i, "frags"));
176                         if(tmp.sb_frags == -666)
177                                 tmp.sb_team = COLOR_SPECTATOR;
178                         else
179                                 tmp.sb_team = GetPlayerColor(i);
180
181                         switch(tmp.sb_team)
182                         {
183                         case COLOR_TEAM1: t1.sb_frags += tmp.sb_frags; t1.sb_player++; break;
184                         case COLOR_TEAM2: t2.sb_frags += tmp.sb_frags; t2.sb_player++; break;
185                         case COLOR_TEAM3: t3.sb_frags += tmp.sb_frags; t3.sb_player++; break;
186                         case COLOR_TEAM4: t4.sb_frags += tmp.sb_frags; t4.sb_player++; break;
187                         case COLOR_SPECTATOR: ts.sb_frags += tmp.sb_frags; ts.sb_player++; break;
188                         }
189
190                         if(i == player_localentnum-1)
191                                 myteam = tmp.sb_team;
192
193                         Sort_Add(sortedPlayers, tmp);
194                 }
195                 if(t1.sb_player) ++numteams;
196                 if(t2.sb_player) ++numteams;
197                 if(t3.sb_player) ++numteams;
198                 if(t4.sb_player) ++numteams;
199
200                 Sort_Add(sortedTeams, t1);
201                 Sort_Add(sortedTeams, t2);
202                 Sort_Add(sortedTeams, t3);
203                 Sort_Add(sortedTeams, t4);
204                 Sort_Add(sortedTeams, ts);
205
206         } else {
207                 for(i = 0; i < maxclients; ++i)
208                 {
209                         if(strlen(getplayerkey(i, "name")) <= 0)
210                                 continue;
211                 
212                         tmp = spawn();
213                         tmp.sb_player = i;
214                         tmp.sb_frags = stof(getplayerkey(i, "frags"));
215                         if(tmp.sb_frags == -666)
216                                 tmp.sb_team = COLOR_SPECTATOR;
217                         else
218                                 tmp.sb_team = COLOR_TEAM1;
219                         Sort_Add(sortedPlayers, tmp);
220                 }
221         }
222 }
223
224 void Sbar_PrintScoreboardItem(vector pos, entity pl, float is_self, float mask)
225 {
226         vector tmp;
227         string str;
228         
229         tmp_y = tmp_z = 0;
230         pos_x += 56;
231
232         str = bufstr_get(databuf, DATABUF_PING + pl.sb_player);
233         tmp_x = 4*8 - strlen(str) * 8 - 56;
234         drawstring(pos + tmp, str, '8 8 0', '0.8 0.8 0.8', 0.8, 0);
235
236         if(!(mask & 1))
237         {
238                 str = ftos(pl.sb_frags);
239                 tmp_x = 4*8 - strlen(str) * 8;
240                 drawstring(pos + tmp, str, '8 8 0', '1 1 1', 1, 0);
241         }
242
243         if(is_self)
244                 drawstring(pos + '40 0 0', "\x0D", '8 8 0', '1 1 1', 1, 0);
245         str = getplayerkey(pl.sb_player, "name");
246         tmp_x = 5*8 - strlen(str) * 8 + 56;
247         drawcolorcodedstring(pos + '48 0 0', str, '8 8 0', 1, 0);
248 }
249 void Sbar_PrintScoreboardTeamItem(vector pos, entity tm, vector rgb, string name)
250 {
251         vector tmp;
252         string str;
253         
254         tmp_y = tmp_z = 0;
255         pos_x += 56;
256
257         str = ftos(tm.sb_frags);
258         tmp_x = 4*8 - strlen(str) * 8;
259         drawstring(pos + tmp, str, '8 8 0', '1 1 1', 1, 0);
260
261         rgb += '0.3 0.3 0.3';
262         rgb = normalize(rgb * 5);
263         drawstring(pos + '48 0 0', name, '8 8 0', rgb, 1, 0);
264 }
265
266 void Sbar_DrawScoreboard()
267 {
268         // Assume: frags are already sorted
269         float xmin, xmax, ymin, ymax, plcount;
270         vector pos, teammin, teammax, rgb;
271         entity pl, tm;
272         float specs;
273         specs = false;
274
275         xmin = vid_conwidth / 4;
276         xmax = vid_conwidth - xmin;
277         ymin = 48 - 26;
278         ymax = vid_conheight - 50;
279
280         pos_y = ymin;
281         pos_z = 0;
282
283         teammin = teammax = '0 0 0';
284         teammin_x = xmin - 2;
285         teammax_x = xmax - 2;
286
287         pos_x = 0.5 * (xmin + xmax) - (24*5);
288         drawfont = FONT_USER+0;
289         drawstring(pos, "Scoreboard", '24 24 0', '1 1 1', 1, DRAWFLAG_NORMAL);
290         drawfont = 0;
291         pos_x = xmin;
292         pos_y += 26;
293
294         drawstring(pos, "ping", '8 8 0', '1 1 1', 1, 0);
295         drawstring(pos + '48 0 0', "frags", '8 8 0', '1 1 1', 1, 0);
296         drawstring(pos + '104 0 0', "name", '8 8 0', '1 1 1', 1, 0);
297         pos_y += 16;
298         
299         if(teamplay)
300         {
301                 /*teampos_z = 0;
302                 teampos_y = pos_y - 40;
303                 teampos_x = (vid_conwidth * 0.5) - (numteams*6*12);*/
304                 for(tm = sortedTeams.sort_next; tm; tm = tm.sort_next)
305                 {
306                         if(!tm.sb_player || tm.sb_team == COLOR_SPECTATOR) // no players in it?
307                                 continue;
308
309                         //Sbar_DrawXNum(teampos-sbar, tm.sb_frags, -4, 24, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
310                         //teampos_x += 6*24;
311                         Sbar_DrawXNum(pos-'106 0 0'-sbar, tm.sb_frags, 4, 24, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
312
313                         teammin_y = pos_y - 2;
314                         teammax_y = pos_y + 2 + 10 * (tm.sb_player);
315                         rgb = GetTeamRGB(tm.sb_team);
316                         drawfill(teammin, teammax - teammin, rgb, 0.2, DRAWFLAG_NORMAL);
317                         /*Sbar_PrintScoreboardTeamItem(pos, tm, rgb, GetTeamName(tm.sb_team));
318                         pos_y += 12;*/
319                         //for(i = 0; i < maxclients; ++i)
320                         plcount = 0;
321                         for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
322                         {
323                                 if(pl.sb_team != tm.sb_team)
324                                         continue;
325                                 Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 0);
326                                 pos_y += 10;
327                                 ++plcount;
328                         }
329                         pos_y += 12;
330                         if(plcount < 2)
331                                 pos_y += 12;
332                 }
333
334                 // rgb := tempvector :)
335                 rgb = pos + '0 12 0';
336                 //pos += '64 24 0';
337                 pos_y += 24;
338                 //for(i = 0; i < maxclients; ++i)
339                 for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
340                 {
341                         if(pl.sb_team != COLOR_SPECTATOR)
342                                 continue;
343                         //drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
344                         Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 1);
345                         pos += '0 10 0';
346                         specs = true;
347                 }
348                         
349                 if(specs)
350                         drawstring(rgb, "Spectators", '8 8 0', '1 1 1', 1, 0);
351         } else {
352                 //for(i = 0; i < maxclients; ++i)
353                 for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
354                 {
355                         if(pl.sb_team != COLOR_TEAM1)
356                                 continue;
357                         //drawstring(pos, ftos(pl.sb_frags), '8 8 0', '1 1 1', 1, 0);
358                         //drawcolorcodedstring(pos + '64 0 0', getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
359                         Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 0);
360                         pos += '0 12 0';
361                 }
362                 rgb = pos + '0 12 0';
363                 //pos += '64 24 0';
364                 pos_y += 24;
365                 for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
366                 {
367                         if(pl.sb_team != COLOR_SPECTATOR)
368                                 continue;
369                         specs = true;
370                         //drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
371                         Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 1);
372                         pos += '0 12 0';
373                 }
374                 if(specs)
375                         drawstring(rgb, "Spectators", '8 8 0', '1 1 1', 1, 0);
376         }
377 }
378
379
380 void Sbar_Score(float margin)
381 {
382         float timelimit, timeleft, minutes, seconds, distribution, myplace;
383         vector sbar_save, place;
384         entity tm, pl, me;
385         sbar_save = sbar;
386
387         sbar_y = vid_conheight - (32+12);
388         sbar_x -= margin;
389         
390         place = '-48 -12 0';
391         if(teamplay)
392         {
393                 // Layout:
394                 //
395                 //   team1 team3 team4
396                 //
397                 //         TEAM2
398                 //for(i = 0; i < 4; ++i)
399                 for(tm = sortedTeams.sort_next; tm; tm = tm.sort_next)
400                 {
401                         if(tm.sb_team == COLOR_SPECTATOR || !tm.sb_player) // no players? don't display
402                                 continue;
403                         // -32*4 = -128
404                         if(tm.sb_team == myteam)
405                                 Sbar_DrawXNum('-128 0', tm.sb_frags, 4, 32, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
406                         else
407                         {
408                                 Sbar_DrawXNum(place, tm.sb_frags, 4, 12, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
409                                 place_x -= 4*12;
410                         }
411                 }
412         } else {
413                 // me vector := [team/connected frags id]
414                 myplace = 0;
415                 for(me = sortedPlayers.sort_next; me; me = me.sort_next)
416                 {
417                         if(me.sb_team != COLOR_SPECTATOR)
418                                 ++myplace;
419                         if(me.sb_player == player_localentnum - 1)
420                                 break;
421                 }
422                 pl = sortedPlayers.sort_next;
423                 if(pl == me)
424                         pl = pl.sort_next;
425                 
426                 if(pl && myplace != 1)
427                 {
428                         distribution = me.sb_frags - pl.sb_frags;
429                 } else if(pl) {
430                         distribution = me.sb_frags - pl.sb_frags;
431                 } else
432                         distribution = 0;
433                 
434                 if(myplace == 1)
435                         Sbar_DrawXNum('-36 -12', myplace, 3, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
436                 else if(myplace == 2)
437                         Sbar_DrawXNum('-36 -12', myplace, 3, 12, '1 1 0', 1, DRAWFLAG_NORMAL);
438                 else
439                         Sbar_DrawXNum('-36 -12', myplace, 3, 12, '1 0 0', 1, DRAWFLAG_NORMAL);
440
441                 if(distribution >= 0)
442                 {
443                         Sbar_DrawXNum('-84 -12', distribution, 4, 12, ' 1 1 1', 1, DRAWFLAG_NORMAL);
444                         Sbar_DrawXNum('-128 0', me.sb_frags, 4, 32, '1 1 1', 1, DRAWFLAG_NORMAL);
445                 } else if(distribution >= -5)
446                 {
447                         Sbar_DrawXNum('-84 -12', distribution, 4, 12, ' 1 1 0', 1, DRAWFLAG_NORMAL);
448                         Sbar_DrawXNum('-128 0', me.sb_frags, 4, 32, '1 1 0', 1, DRAWFLAG_NORMAL);
449                 } else {
450                         Sbar_DrawXNum('-84 -12', distribution, 4, 12, ' 1 0 0', 1, DRAWFLAG_NORMAL);
451                         Sbar_DrawXNum('-128 0', me.sb_frags, 4, 32, '1 0 0', 1, DRAWFLAG_NORMAL);
452                 }
453         }
454         timelimit = getstatf(STAT_TIMELIMIT);
455         if(timelimit)
456         {
457                 timeleft = max(0, timelimit * 60 - time);
458                 minutes = floor(timeleft / 60);
459                 seconds = floor(timeleft - minutes*60);
460                 if(minutes >= 5)
461                 {
462                         Sbar_DrawXNum('-72 32', minutes, 3, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
463                         drawpic(sbar + '-36 32', "gfx/num_colon", '12 12', '1 1 1', sbar_alpha_fg, 0);
464                         Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
465                 } else if(minutes >= 1)
466                 {
467                         Sbar_DrawXNum('-72 32', minutes, 3, 12, '1 1 0', 1, DRAWFLAG_NORMAL);
468                         drawpic(sbar + '-36 32', "gfx/num_colon", '12 12', '1 1 0', sbar_alpha_fg, 0);
469                         Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 1 0', 1, DRAWFLAG_NORMAL);
470                 } else {
471                         Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 0 0', 1, DRAWFLAG_NORMAL);
472                 }
473         } else {
474                 minutes = floor(time / 60);
475                 seconds = floor(time - minutes*60);
476                 Sbar_DrawXNum('-72 32', minutes, 3, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
477                 drawpic(sbar + '-36 32', "gfx/num_colon", '12 12', '1 1 1', sbar_alpha_fg, 0);
478                 Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
479         }
480         sbar = sbar_save;
481 }
482
483 void Sbar_MiniscoreItem(vector pos, entity pl, float is_self)
484 {
485         float x;
486         pos_x += 72;
487         
488         if(teamplay)
489                 drawfill(pos + '0 1 0', '40 6 0', GetTeamRGB(pl.sb_team)*0.5, 1, DRAWFLAG_NORMAL);
490         else
491                 drawfill(pos + '0 1 0', '40 6 0', '0.5 0.5 0.5', 0.5, DRAWFLAG_NORMAL);
492         x = pos_x;
493         pos_x += 5*8;
494         pos_x -= strlen(ftos(pl.sb_frags))*8;
495         drawstring(pos, ftos(pl.sb_frags), '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
496         pos_x = x;
497         if(is_self)
498         {
499                 pos_x += 48;
500                 drawstring(pos, "\x0D", '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
501                 pos_x += 8;
502         } else
503                 pos_x += 56;
504         drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
505 }
506
507 void Sbar_MiniscoreTeamItem(vector pos, float color, float frags, float is_self)
508 {
509         float x;
510         pos_x += 72;
511         
512         if(teamplay)
513                 drawfill(pos + '0 1 0', '40 6 0', GetTeamRGB(color)*0.5, 1, DRAWFLAG_NORMAL);
514         else
515                 drawfill(pos + '0 1 0', '40 6 0', '0.5 0.5 0.5', 0.5, DRAWFLAG_NORMAL);
516         x = pos_x;
517         pos_x += 5*8;
518         pos_x -= strlen(ftos(frags))*8;
519         drawstring(pos, ftos(frags), '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
520         pos_x = x;
521         if(is_self)
522         {
523                 pos_x += 48;
524                 drawstring(pos, "\x0D", '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
525                 pos_x += 8;
526         } else
527                 pos_x += 56;
528         drawstring(pos, GetTeamName(color), '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
529 }
530
531 void Sbar_MiniDeathmatchOverlay(vector pos)
532 {
533         float numlines, up, down;
534         entity me, tm, pl;
535         float miniscoreboard_size;
536         miniscoreboard_size = cvar("sbar_miniscoreboard_size");
537         
538         if(miniscoreboard_size == 0)
539                 return;
540         pos_y = vid_conheight - 8;
541         
542         if(miniscoreboard_size < 0)
543                 numlines = (vid_conheight - sbar_y + 7) / 8;
544         else
545                 numlines = miniscoreboard_size;
546
547         // give up if there isn't enough room
548         if(pos_x >= vid_conwidth || pos_y >= vid_conheight || numlines < 1)
549                 return;
550
551         // me vector := [team/connected frags id]
552         for(me = sortedPlayers.sort_next; me; me = me.sort_next)
553         {
554                 if(me.sb_player == player_localentnum - 1)
555                         break;
556         }
557
558         if(teamplay)
559                 numlines -= numteams;
560
561         // figure out how many players above and below we can show
562         up = floor(numlines/2);
563         down = up;
564         if((up + down) > numlines)
565                 down = numlines - up;
566
567         // render bottom-up
568         for(pl = me.sort_next; pl && down > 0; pl = pl.sort_next)
569         {
570                 if(pl.sb_team == COLOR_SPECTATOR)
571                         continue;
572                 Sbar_MiniscoreItem(pos, pl, false);
573                 pos_y -= 9;
574                 --down;
575         }
576         Sbar_MiniscoreItem(pos, me, true);
577         pos_y -= 9;
578         up += down; // if there weren't enough lines below... add them
579         for(pl = me.sort_prev; pl != sortedPlayers && up > 0; pl = pl.sort_prev)
580         {
581                 if(pl.sb_team == COLOR_SPECTATOR)
582                         continue;
583                 Sbar_MiniscoreItem(pos, pl, false);
584                 pos_y -= 9;
585                 --up;
586         }
587
588         if(teamplay)
589         {
590                 for(tm = sortedTeams.sort_next; tm.sort_next; tm = tm.sort_next);
591                 for(; tm != sortedTeams; tm = tm.sort_prev)
592                 {
593                         if(!tm.sb_player || tm.sb_team == COLOR_SPECTATOR) // no players?
594                                 continue;
595                         Sbar_MiniscoreTeamItem(pos, tm.sb_team, tm.sb_frags, (tm.sb_team == me.sb_team));
596                         pos_y -= 9;
597                 }
598         }
599 }
600
601 void Sbar_Draw (void)
602 {
603         float i;
604         float x, fade;
605         float stat_items;
606
607         Sbar_SortFrags();
608
609         sb_lines = 24;
610         
611         if (sb_showscores)
612                 Sbar_DrawScoreboard();
613         else if (intermission == 1)
614         {
615                 Sbar_DrawScoreboard();
616                 return;
617         }
618         else if (intermission == 2)
619                 Sbar_FinaleOverlay();
620         else
621         {
622                 if (sb_showscores || (getstati(STAT_HEALTH) <= 0 && cvar("cl_deathscoreboard")))
623                 {
624                         sbar_x = (vid_conwidth - 640.0)*0.5;
625                         sbar_y = vid_conheight - 47;
626                         //Sbar_DrawAlphaPic (sbar_x, sbar_y, sb_scorebar, sbar_alpha_bg.value);
627                         //drawpic('0 0', "gfx/scorebar", '0 0 0', '1 1 1', cvar("sbar_alpha_bg"), 0);
628                         Sbar_DrawScoreboard ();
629                 }
630                 else
631                 {
632                         if (sb_lines && sbar_hudselector == 1)
633                         {
634                                 stat_items = getstati(STAT_ITEMS);
635
636                                 sbar_x = (vid_conwidth - 320.0)*0.5;
637                                 sbar_y = vid_conheight - 24.0 - 16.0;
638                                 sbar_z = 0;
639                         
640                                 fade = 3.2 - 2 * (time - weapontime);
641                                 fade = bound(0.7, fade, 1);
642
643                                 x = 1.0;
644                                 for(i = 0; i < 8; ++i)
645                                 {
646                                         if(stat_items & x)
647                                         {
648                                                 Sbar_DrawWeapon(i+1, fade, (i + 2 == activeweapon));
649                                         }
650                                         x *= 2;
651                                 }
652                                 x *= 2*2*2*2;
653                                 if(stat_items & x)
654                                 {
655                                         Sbar_DrawWeapon(0, fade, (activeweapon == 1));
656                                 }
657
658                                 // armor
659                                 x = getstati(STAT_ARMOR);
660                                 if (x > 0)
661                                 {
662                                         // "gfx/sb_armor"
663                                         //Sbar_DrawStretchPic (72, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
664                                         drawpic(sbar + '72 0', "gfx/sb_armor", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
665                                         if(x > 200)
666                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0 1 0', 1, 0);
667                                         else if(x > 100)
668                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0.2 1 0', 1, 0);
669                                         else if(x > 50)
670                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
671                                         else if(x > 25)
672                                                 Sbar_DrawXNum('0 0', x, 3, 24, '1 1 0.2', 1, 0);
673                                         else
674                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0.7 0 0', 1, 0);
675                                 }
676
677                                 // health
678                                 x = getstati(STAT_HEALTH);
679                                 if (x != 0)
680                                 {
681                                         // "gfx/sb_health"
682                                         //Sbar_DrawStretchPic (184, 0, sb_health, sbar_alpha_fg.value, 24, 24);
683                                         drawpic(sbar + '184 0', "gfx/sb_health", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
684                                         if(x > 200)
685                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0 1 0', 1, 0);
686                                         else if(x > 100)
687                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0.2 1 0', 1, 0);
688                                         else if(x > 50)
689                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
690                                         else if(x > 25)
691                                                 Sbar_DrawXNum('112 0', x, 3, 24, '1 1 0.2', 1, 0);
692                                         else
693                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0.7 0 0', 1, 0);
694                                 }
695
696                                 // ammo
697                                 x = getstati(STAT_AMMO);
698                                 if ((stat_items & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || x != 0)
699                                 {
700                                         if (stat_items & NEX_IT_SHELLS)
701                                                 drawpic(sbar + '296 0', "gfx/sb_shells", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
702                                         else if (stat_items & NEX_IT_BULLETS)
703                                                 drawpic(sbar + '296 0', "gfx/sb_bullets", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
704                                         else if (stat_items & NEX_IT_ROCKETS)
705                                                 drawpic(sbar + '296 0', "gfx/sb_rocket", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
706                                         else if (stat_items & NEX_IT_CELLS)
707                                                 drawpic(sbar + '296 0', "gfx/sb_cells", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
708                                         if(x > 10)
709                                                 Sbar_DrawXNum('224 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
710                                         else
711                                                 Sbar_DrawXNum('224 0', x, 3, 24, '0.7 0 0', 1, 0);
712                                 }
713
714                                 if (sbar_x + 320 + 160 <= vid_conwidth)
715                                         Sbar_MiniDeathmatchOverlay(sbar + '320 0');
716                                 if (sbar_x > 0)
717                                         Sbar_Score(16);
718                                 // The margin can be at most 8 to support 640x480 console size:
719                                 //   320 + 2 * (144 + 16) = 640
720                         }
721                         else if (sb_lines)
722                         {
723                         
724                                 stat_items = getstati(STAT_ITEMS);
725                         
726                                 sbar_x = (vid_conwidth - 640.0)*0.5;
727                                 sbar_y = vid_conheight - 47;
728                                 sbar_z = 0;
729
730                                 fade = 3 - 2 * (time - weapontime);
731
732                                 x = 1.0;
733                                 for(i = 0; i < 8; ++i)
734                                 {
735                                         if(stat_items & x)
736                                         {
737                                                 Sbar_DrawWeapon(i+1, fade, (i + 2 == activeweapon));
738                                         }
739                                         x *= 2;
740                                 }
741                                 x *= 2*2*2*2;
742                                 if(stat_items & x)
743                                 {
744                                         Sbar_DrawWeapon(0, fade, (activeweapon == 1));
745                                 }
746
747                                 if (sb_lines > 24)
748                                         drawpic(sbar, "gfx/sbar", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
749                                 else
750                                         drawpic(sbar, "gfx/sbar_minimal", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
751
752                                 // armor
753                                 // (340-3*24) = 268
754                                 Sbar_DrawXNum('268 12', getstati(STAT_ARMOR), 3, 24, '0.6 0.7 0.8', 1, 0);
755
756                                 // health
757                                 // (154-3*24) = 82
758                                 x = getstati(STAT_HEALTH);
759                                 if(x > 100)
760                                         Sbar_DrawXNum('82 12', x, 3, 24, '1 1 1', 1, 0);
761                                 else if(x <= 25 && time - floor(time) > 0.5)
762                                         Sbar_DrawXNum('82 12', x, 3, 24, '0.7 0 0', 1, 0);
763                                 else
764                                         Sbar_DrawXNum('81 12', x, 3, 24, '0.6 0.7 0.8', 1, 0);
765
766                                 // AK dont draw ammo for the laser
767                                 x = getstati(STAT_AMMO);
768                                 if(activeweapon != 12)
769                                 {
770                                         // (519-3*24) = 447
771                                         if (stat_items & NEX_IT_SHELLS)
772                                                 drawpic(sbar + '519 0', "gfx/sb_shells", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
773                                         else if (stat_items & NEX_IT_BULLETS)
774                                                 drawpic(sbar + '519 0', "gfx/sb_bullets", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
775                                         else if (stat_items & NEX_IT_ROCKETS)
776                                                 drawpic(sbar + '519 0', "gfx/sb_rocket", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
777                                         else if (stat_items & NEX_IT_CELLS)
778                                                 drawpic(sbar + '519 0', "gfx/sb_cells", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
779                                         if(x > 10)
780                                                 Sbar_DrawXNum('447 12', x, 3, 24, '0.6 0.7 0.8', 1, 0);
781                                         else
782                                                 Sbar_DrawXNum('447 12', x, 3, 24, '0.7 0 0', 1, 0);
783                                 }
784
785                                 if (sb_lines > 24)
786                                         drawpic(sbar, "gfx/sbar_overlay", '0 0 0', '1 1 1', 1, DRAWFLAG_MODULATE);
787
788                                 if (sbar_x + 600 + 160 <= vid_conwidth)
789                                         Sbar_MiniDeathmatchOverlay (sbar + '600 0');
790
791                                 if (sbar_x > 0)
792                                         Sbar_Score(-16);
793                                 // Because:
794                                 //   Mini scoreboard uses 12*4 per other team, that is, 144
795                                 //   pixels when there are four teams...
796                                 //   Nexuiz by default sets vid_conwidth to 800... makes
797                                 //   sbar_x == 80...
798                                 //   so we need to shift it by 64 pixels to the right to fit
799                                 //   BUT: then it overlaps with the image that gets drawn
800                                 //   for viewsize 100! Therefore, just account for 3 teams,
801                                 //   that is, 96 pixels mini scoreboard size, needing 16 pixels
802                                 //   to the right!
803                         }
804                 
805                 
806                         if(gametype == GAME_KEYHUNT)
807                         {
808                                 CSQC_kh_hud();
809                         } else if(gametype == GAME_CTF)
810                         {
811                                 CSQC_ctf_hud();
812                         }
813                 }
814         }
815 }
816
817 void CSQC_ctf_hud(void)
818 {
819         // cvar("sbar_flagstatus_right") move the flag icons right
820         // cvar("sbar_flagstatus_pos") pixel position of the nexuiz flagstatus icons
821         float redflag, blueflag;
822         float stat_items;
823         vector pos;
824         
825         stat_items = getstati(STAT_ITEMS);
826         redflag = (stat_items/32768) & 3;
827         blueflag = (stat_items/131072) & 3;
828
829         pos_x = (cvar("sbar_flagstatus_right")) ? vid_conwidth - 10 - sbar_x - 64 : 10 - sbar_x;
830         pos_z = 0;
831
832         if(sbar_hudselector == 1)
833                 pos_y = (vid_conheight - sbar_y) - cvar("sbar_flagstatus_pos") - 64;
834         else
835                 pos_y = -117;
836
837         pos += sbar;
838
839         switch(redflag)
840         {
841         case 1: drawpic(pos, "gfx/sb_flag_red_taken", '0 0 0', '1 1 1', 1, DRAWFLAG_NORMAL); break;
842         case 2: drawpic(pos, "gfx/sb_flag_red_lost", '0 0 0', '1 1 1', 1, DRAWFLAG_NORMAL); break;
843         case 3: drawpic(pos, "gfx/sb_flag_red_carrying", '0 0 0', '1 1 1', 1, DRAWFLAG_NORMAL); break;
844         }
845
846         pos_y -= 64;
847         
848         switch(blueflag)
849         {
850         case 1: drawpic(pos, "gfx/sb_flag_blue_taken", '0 0 0', '1 1 1', 1, 0); break;
851         case 2: drawpic(pos, "gfx/sb_flag_blue_lost", '0 0 0', '1 1 1', 1, 0); break;
852         case 3: drawpic(pos, "gfx/sb_flag_blue_carrying", '0 0 0', '1 1 1', 1, 0); break;
853         }
854 }