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