]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/sbar.qc
add csqc_flags cvar for client compatibility
[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 vector sbar_fontsize;
6
7 entity sortedPlayers;
8 entity sortedTeams;
9
10 .float sb_frags;
11 .float sb_team;
12 .float sb_player;
13 .float sb_caps;
14
15 void Sbar_FinaleOverlay()
16 {
17         vector pos;
18         pos_x = (vid_conwidth - 1)/2;
19         pos_y = 16;
20         pos_z = 0;
21         drawpic(pos, "gfx/finale", '0 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL);
22 }
23
24 void Sbar_DrawWeapon(float nr, float fade, float active)
25 {
26         vector pos, vsize, color;
27         float value;
28         
29         value = (active) ? 1 : 0.6;
30         color_x = color_y = color_z = value;
31         
32         if(sbar_hudselector == 1)
33         {
34                 // width = 300, height = 100
35                 const float w_width = 32, w_height = 12, w_space = 2, font_size = 8;
36                 
37                 pos_x = (vid_conwidth - w_width * 9) * 0.5 + w_width * nr;
38                 pos_y = (vid_conheight - w_height);
39                 pos_z = 0;
40                 vsize_x = w_width;
41                 vsize_y = w_height;
42                 vsize_z = 0;
43                 drawpic(pos, strcat("gfx/inv_weapon", ftos(nr)), vsize, color, value * fade * sbar_alpha_fg, 0);
44                 pos_x += w_space;
45                 pos_y += w_space;
46                 vsize_x = font_size;
47                 vsize_y = font_size;
48                 vsize_z = 0;
49                 drawstring(pos, ftos(nr+1), vsize, '1 1 0', sbar_alpha_fg, 0);
50
51         }
52         else
53         {
54                 // width = 300, height = 100
55                 const float w2_width = 300, w2_height = 100, w2_space = 10;
56                 const float w2_scale = 0.4;
57
58                 pos_x = vid_conwidth - (w2_width + w2_space) * w2_scale;
59                 pos_y = (w2_height + w2_space) * w2_scale * nr + w2_space;
60                 pos_z = 0;
61                 vsize_x = w2_width * w2_scale;
62                 vsize_y = w2_height * w2_scale;
63                 vsize_z = 0;
64                 
65                 drawpic(pos, strcat("gfx/inv_weapon", ftos(nr)), vsize, color, value * fade * sbar_alpha_fg, 0);
66         }
67 }
68 void Sbar_DrawXNum (vector pos, float num, float digits, float lettersize, vector rgb, float a, float dflags)
69 {
70         float l, i;
71         string str, tmp;
72         float minus;
73         vector vsize;
74
75         vsize_x = vsize_y = lettersize;
76         vsize_z = 0;
77
78         if(num < 0)
79         {
80                 minus = true;
81                 num = -num;
82                 pos_x -= lettersize;
83         } else
84                 minus = false;
85         
86         if(digits < 0)
87         {
88                 tmp = ftos(num);
89                 digits = -digits;
90                 str = strcat(substring("0000000000", 0, digits - strlen(tmp)), tmp);
91         } else
92                 str = ftos(num);
93         
94         l = strlen(str);
95
96         if(l > digits)
97         {
98                 str = substring(str, l-digits, 999);
99                 l = strlen(str);
100         } else if(l < digits)
101                 pos_x += (digits-l) * lettersize;
102
103         if(minus)
104         {
105                 drawpic(sbar + pos, "gfx/num_minus", vsize, rgb, a * sbar_alpha_fg, dflags);
106                 pos_x += lettersize;
107         }
108
109         for(i = 0; i < l; ++i)
110         {
111                 drawpic(sbar + pos, strcat("gfx/num_", substring(str, i, 1)), vsize, rgb, a * sbar_alpha_fg, dflags);
112                 pos_x += lettersize;
113         }
114 }
115
116 float Sbar_PlayerCmp(entity l, entity r)
117 {
118         if(teamplay)
119         {
120                 if(l.sb_team > r.sb_team)
121                         return true;
122                 else if(l.sb_team > r.sb_team)
123                         return false;
124                 if(gametype == GAME_CTF)
125                 {
126                         if(l.sb_caps > r.sb_caps)
127                                 return true;
128                         else if(l.sb_caps < r.sb_caps)
129                                 return false;
130                 }
131         }
132         if(l.sb_frags > r.sb_frags)
133                 return true;
134         else if(l.sb_frags < r.sb_frags)
135                 return false;
136         return (l.sb_player > r.sb_player);
137 }
138 float Sbar_TeamCmp(entity l, entity r)
139 {
140         if(gametype == GAME_CTF)
141         {
142                 if(l.sb_caps > r.sb_caps)
143                         return true;
144                 else if(l.sb_caps < r.sb_caps)
145                         return false;
146         }
147         if(l.sb_frags > r.sb_frags)
148                 return true;
149         else if(l.sb_frags < r.sb_frags)
150                 return false;
151         return (l.sb_player > r.sb_player);
152 }
153
154 void Sbar_SortFrags()
155 {
156         float i;
157         entity tmp;
158         entity t1, t2, t3, t4, ts;
159         
160         Sort_Remove(sortedPlayers);
161         sortedPlayers = Sort_New(Sbar_PlayerCmp);
162
163         numteams = 0;
164         if(teamplay)
165         {
166                 Sort_Remove(sortedTeams);
167         
168                 t1 = spawn();
169                 t2 = spawn();
170                 t3 = spawn();
171                 t4 = spawn();
172                 ts = spawn();
173         
174                 t1.sb_team = COLOR_TEAM1;
175                 t2.sb_team = COLOR_TEAM2;
176                 t3.sb_team = COLOR_TEAM3;
177                 t4.sb_team = COLOR_TEAM4;
178                 ts.sb_team = COLOR_SPECTATOR;
179
180                 t1.sb_player = t2.sb_player = t3.sb_player = t4.sb_player = ts.sb_player = 0;
181                 t1.sb_frags = t2.sb_frags = t3.sb_frags = t4.sb_frags = 0;
182                 t1.sb_caps = caps_team1;
183                 t2.sb_caps = caps_team2;
184                 sortedTeams = Sort_New(Sbar_TeamCmp);
185                 
186                 for(i = 0; i < maxclients; ++i)
187                 {
188                         if(strlen(getplayerkey(i, "name")) <= 0)
189                                 continue;
190                 
191                         tmp = spawn();
192                         tmp.sb_player = i;
193                         tmp.sb_frags = stof(getplayerkey(i, "frags"));
194                         tmp.sb_caps = stof(bufstr_get(databuf, DATABUF_CAPTURES + tmp.sb_player));
195                         
196                         if(tmp.sb_frags == -666)
197                                 tmp.sb_team = COLOR_SPECTATOR;
198                         else
199                                 tmp.sb_team = GetPlayerColor(i);
200
201                         switch(tmp.sb_team)
202                         {
203                         case COLOR_TEAM1: t1.sb_frags += tmp.sb_frags; t1.sb_player++; break;
204                         case COLOR_TEAM2: t2.sb_frags += tmp.sb_frags; t2.sb_player++; break;
205                         case COLOR_TEAM3: t3.sb_frags += tmp.sb_frags; t3.sb_player++; break;
206                         case COLOR_TEAM4: t4.sb_frags += tmp.sb_frags; t4.sb_player++; break;
207                         case COLOR_SPECTATOR: ts.sb_frags += tmp.sb_frags; ts.sb_player++; break;
208                         }
209
210                         if(i == player_localentnum-1)
211                                 myteam = tmp.sb_team;
212
213                         Sort_Add(sortedPlayers, tmp);
214                 }
215                 if(t1.sb_player) ++numteams;
216                 if(t2.sb_player) ++numteams;
217                 if(t3.sb_player) ++numteams;
218                 if(t4.sb_player) ++numteams;
219
220                 Sort_Add(sortedTeams, t1);
221                 Sort_Add(sortedTeams, t2);
222                 Sort_Add(sortedTeams, t3);
223                 Sort_Add(sortedTeams, t4);
224                 Sort_Add(sortedTeams, ts);
225
226         } else {
227                 for(i = 0; i < maxclients; ++i)
228                 {
229                         if(strlen(getplayerkey(i, "name")) <= 0)
230                                 continue;
231                 
232                         tmp = spawn();
233                         tmp.sb_player = i;
234                         tmp.sb_frags = stof(getplayerkey(i, "frags"));
235                         if(tmp.sb_frags == -666)
236                                 tmp.sb_team = COLOR_SPECTATOR;
237                         else
238                                 tmp.sb_team = COLOR_TEAM1;
239                         Sort_Add(sortedPlayers, tmp);
240                 }
241         }
242 }
243
244 void Cmd_Sbar_Help(float argc)
245 {
246         print("You can modify the scoreboard using the\n");
247         print("^3|---------------------------------------------------------------|\n");
248         print("^2sbar_columns^7 cvar and the ^2sbar_columns_set command.\n");
249         print("^2sbar_columns^7             specifies the default layout and\n");
250         print("^2sbar_columns_set^7         actually changes the layout.\n");
251         print("You can call ^2sbar_columns_set^7 with the new layout\n");
252         print("as parameters, or eithout parameters it will read the cvar.\n\n");
253         print("Usage:\n");
254         print("^2sbar_columns_set ^7filed1 field2 ...\n");
255         print("Fields which are not relevant to the current gametype\n");
256         print("won't be displayed\n\n");
257         print("The following field names are recognized (case INsensitive):\n");
258         print("^3name^7 or ^3nick^7             Name of a player\n");
259         print("^3caps^7 or ^3captures^7         Number of flags captured\n");
260         print("^3rets^7 or ^3returns^7          Number of flags returned\n");
261         print("^3frags^7 or ^3kills^7           Frags\n");
262         print("^3deaths^7 or ^3dths^7           Number of deaths\n");
263         print("^3kd^7 or ^3kdr^7 or ^3kdratio^7 or ^3k/d\n");
264         print("                         The kill-death ratio\n");
265         print("^3ping^7                     Ping time\n\n");
266         print("You can use a ^3|^7 to start the right-aligned fields.\n");
267         print("Example: ping name | caps rets frags k/d\n");
268         print("This will put the ping and the name on the left side.\n");
269         print("The captures, returns, frags and kill-death ratio will be\n");
270         print("rendered beginning on the right side.\n");
271
272 }
273
274 #define MIN_NAMELEN 24
275 #define MAX_NAMELEN 24
276
277 void Cmd_Sbar_SetFields(float argc)
278 {
279         float i;
280         string str;
281         float digit;
282
283         if(argc < 2)
284                 argc = tokenize(strcat("x ", cvar_string("sbar_columns")));
285         
286         argc = min(MAX_SBAR_FIELDS, argc);
287         sbar_num_fields = 0;
288         drawfont = sbar_font;
289         digit = stringwidth("0123456789", FALSE) / 10;
290         for(i = 0; i < argc-1; ++i)
291         {
292                 str = argv(i+1);
293                 strunzone(sbar_title[i]);
294                 sbar_title[i] = strzone(str);
295                 sbar_size[i] = stringwidth(str, FALSE);
296                 str = strtolower(str);
297                 if(str == "ping") {
298                         sbar_field[i] = SBF_PING;
299                 } else if(str == "name" || str == "nick") {
300                         sbar_field[i] = SBF_NAME;
301                         sbar_size[i] = MIN_NAMELEN; // minimum size? any use?
302                 } else if(str == "caps" || str == "captures") {
303                         if(sbar_size[i] < 3*digit)
304                                 sbar_size[i] = 3*digit;
305                         sbar_field[i] = SBF_CAPS;
306                 } else if(str == "rets" || str == "returns") {
307                         if(sbar_size[i] < 3*digit)
308                                 sbar_size[i] = 3*digit;
309                         sbar_field[i] = SBF_RETS;
310                 } else if(str == "frags" || str == "kills") {
311                         if(sbar_size[i] < 5*digit)
312                                 sbar_size[i] = 5*digit;
313                         sbar_field[i] = SBF_FRAGS;
314                 } else if(str == "deaths" || str == "dths") {
315                         if(sbar_size[i] < 5*digit)
316                                 sbar_size[i] = 5*digit;
317                         sbar_field[i] = SBF_DEATHS;
318                 } else if(str == "kdratio") {
319                         sbar_field[i] = SBF_KDRATIO;
320                 } else if(str == "kdr" || str == "k/d") {
321                         sbar_field[i] = SBF_KDRATIO;
322                 } else if(str == "kd") {
323                         sbar_field[i] = SBF_KDRATIO;
324                 } else if(str == "|") {
325                         sbar_field[i] = SBF_SEPARATOR;
326                 } else {
327                         print(strcat("^1Error:^7 Unknown score field: '", str, "'\n"));
328                         --sbar_num_fields;
329                 }
330                 ++sbar_num_fields;
331         }
332         sbar_field[i] = SBF_END;
333 }
334
335 vector sbar_field_rgb;
336 string Sbar_GetField(entity pl, float field)
337 {
338         float tmp;
339         string str;
340         sbar_field_rgb = '1 1 1';
341         switch(field)
342         {
343         case SBF_PING:
344                 str = bufstr_get(databuf, DATABUF_PING + pl.sb_player);
345                 tmp = max(0, min(220, stof(str)-80)) / 220;
346                 sbar_field_rgb = '1 1 1' - '0 1 1'*tmp;
347                 return str;
348         case SBF_NAME: return getplayerkey(pl.sb_player, "name");
349         case SBF_CAPS: return ftos(pl.sb_caps);
350         case SBF_RETS: return bufstr_get(databuf, DATABUF_RETURNS + pl.sb_player);
351         case SBF_FRAGS: return ftos(pl.sb_frags);
352         case SBF_DEATHS: return bufstr_get(databuf, DATABUF_DEATHS + pl.sb_player);
353         case SBF_KDRATIO:
354                 tmp = stof(bufstr_get(databuf, DATABUF_DEATHS + pl.sb_player));
355                 if(tmp == 0) {
356                         sbar_field_rgb = '0 1 0';
357                         str = ftos(pl.sb_frags);
358                 } else if(pl.sb_frags <= 0) {
359                         sbar_field_rgb = '1 0 0';
360                         str = ftos(pl.sb_frags / tmp);
361                 } else
362                         str = ftos(pl.sb_frags / tmp);
363                 
364                 tmp = strstrofs(str, ".", 0);
365                 if(tmp > 0)
366                         str = substring(str, 0, tmp+2);
367                 return str;
368         }
369 }
370
371 float Sbar_IsFieldMasked(float field, float mask)
372 {
373         if(mask&1) // spectator
374                 return (field != SBF_NAME && field != SBF_PING);
375         if(gametype != GAME_CTF)
376         {
377                 if(field == SBF_CAPS || field == SBF_RETS)
378                         return true;
379         }
380         return false;
381 }
382
383 // shamelessly stolen from menu QC :P <- as if I would steal YOUR code pfft ;)
384 float textLengthUpToWidth(string theText, float maxWidth, float handleColors)
385 {
386         // STOP.
387         // The following function is SLOW.
388         // For your safety and for the protection of those around you...
389         // DO NOT CALL THIS AT HOME.
390         // No really, don't.
391         if(stringwidth(theText, handleColors) <= maxWidth)
392                 return strlen(theText); // yeah!
393
394         // binary search for right place to cut string
395         float left, right, middle; // this always works
396         left = 0;
397         right = strlen(theText); // this always fails
398         do
399         {
400                 middle = floor((left + right) / 2);
401                 if(stringwidth(substring(theText, 0, middle), handleColors) <= maxWidth)
402                         left = middle;
403                 else
404                         right = middle;
405         }
406         while(left < right - 1);
407
408         // NOTE: when color codes are involved, this binary search is,
409         // mathematically, BROKEN. However, it is obviously guaranteed to
410         // terminate, as the range still halves each time - but nevertheless, it is
411         // guaranteed that it finds ONE valid cutoff place (where "left" is in
412         // range, and "right" is outside).
413
414         return left;
415 }
416 string textShortenToWidth(string theText, float maxWidth, float handleColors)
417 {
418         if(stringwidth(theText, handleColors) <= maxWidth)
419                 return theText;
420         else
421                 return strcat(substring(theText, 0, textLengthUpToWidth(theText, maxWidth - stringwidth("...", handleColors), handleColors)), "...");
422 }
423
424 float xmin, xmax, ymin, ymax, sbwidth, sbheight;
425 void Sbar_PrintScoreboardItem(vector pos, entity pl, float is_self, float mask)
426 {
427         vector tmp;
428         string str, tempstr;
429         float i, field, len;
430
431         // Layout:
432         tmp_z = 0;
433         if(is_self)
434         {
435                 tmp_x = sbwidth;
436                 tmp_y = sbar_fontsize_y;
437                 drawfill(pos - '1 1', tmp + '2 2', '1 1 1', 0.3, DRAWFLAG_NORMAL);
438         }       
439         tmp_y = 0;
440         
441         for(i = 0; i < sbar_num_fields; ++i)
442         {
443                 field = sbar_field[i];
444                 if(field == SBF_SEPARATOR)
445                         break;
446                 if(Sbar_IsFieldMasked(field, mask))
447                         continue;
448
449                 str = Sbar_GetField(pl, field);
450
451                 if(field == SBF_NAME)
452                 {
453                         float realsize;
454                         float j;
455                         realsize = sbar_size[i];
456                         if(i+1 < sbar_num_fields)
457                                 if(sbar_field[i+1] == SBF_SEPARATOR)
458                                 {
459                                         realsize = (xmax - xmin) / sbar_fontsize_x;
460                                         for(j = 0; j < sbar_num_fields; ++j) if(j != i) if(sbar_field[j] != SBF_SEPARATOR)
461                                                 realsize -= sbar_size[j] + 1;
462                                         realsize += 1;
463                                 }
464                         str = textShortenToWidth(str, realsize, TRUE);
465                 }
466                 len = stringwidth(str, TRUE);
467                 
468                 if(sbar_size[i] < len)
469                         sbar_size[i] = len;
470
471                 pos_x += sbar_fontsize_x*sbar_size[i] + sbar_fontsize_x;
472                 if(field == SBF_NAME) {
473                         tmp_x = sbar_fontsize_x*sbar_size[i] + sbar_fontsize_x;
474                         drawcolorcodedstring(pos - tmp, str, sbar_fontsize, 1, DRAWFLAG_NORMAL);
475                 } else {
476                         tmp_x = len*sbar_fontsize_x + sbar_fontsize_x;
477                         drawstring(pos - tmp, str, sbar_fontsize, sbar_field_rgb, 1, DRAWFLAG_NORMAL);
478                 }
479         }
480         
481         if(sbar_field[i] == SBF_SEPARATOR)
482         {
483                 pos_x = xmax;
484                 for(i = sbar_num_fields-1; i > 0; --i)
485                 {
486                         field = sbar_field[i];
487                         if(field == SBF_SEPARATOR)
488                                 break;
489                         if(Sbar_IsFieldMasked(field, mask))
490                                 continue;
491                         
492                         str = Sbar_GetField(pl, field);
493
494                         if(field == SBF_NAME)
495                                 str = textShortenToWidth(str, sbar_size[i], TRUE);
496                         len = stringwidth(str, TRUE);
497
498                         if(sbar_size[i] < len)
499                                 sbar_size[i] = len;
500                         
501                         if(field == SBF_NAME) {
502                                 tmp_x = sbar_fontsize_x*len; // left or right aligned? let's put it right...
503                                 drawcolorcodedstring(pos - tmp, str, sbar_fontsize, 1, DRAWFLAG_NORMAL);
504                         } else {
505                                 tmp_x = sbar_fontsize_x*len; //strlen(str);
506                                 drawstring(pos - tmp, str, sbar_fontsize, sbar_field_rgb, 1, DRAWFLAG_NORMAL);
507                         }
508                         pos_x -= sbar_fontsize_x*sbar_size[i] + sbar_fontsize_x;
509                 }
510         }
511 }
512
513 void Sbar_DrawScoreboard()
514 {
515         //float xmin, ymin, xmax, ymax;
516         vector rgb, pos, tmp, sbar_save;
517         entity pl, tm;
518         float specs, i;
519         float center_x;
520         string str;
521
522         sbar_fontsize = Sbar_GetFontsize();
523         if(sbar_fontsize_x == 0)
524                 sbar_fontsize = '8 8 0';
525         if(sbar_fontsize_y == 0)
526                 sbar_fontsize_y = sbar_fontsize_x;
527         
528         xmin = vid_conwidth / 5;
529         ymin = 20;
530
531         xmax = vid_conwidth - xmin;
532         ymax = vid_conheight - 0.2*vid_conheight;
533
534         sbwidth = xmax - xmin;
535         sbheight = ymax - ymin;
536
537         center_x = xmin + 0.5*sbwidth;
538
539         //Sbar_UpdateFields();
540
541         // Initializes position
542         //pos_x = xmin;
543         pos_y = ymin;
544         pos_z = 0;
545
546         // Heading
547         drawfont = sbar_font;
548         pos_x = center_x - stringwidth("Scoreboard", TRUE)*0.5*24;
549         drawstring(pos, "Scoreboard", '24 24', '1 1 1', 1, DRAWFLAG_NORMAL);
550         pos_x = xmin;
551         pos_y += 24 + 4;
552
553         // Titlebar background:
554         tmp_x = sbwidth;
555         tmp_y = sbar_fontsize_y;
556         drawfill(pos - '1 1', tmp + '2 2', '0.5 0.5 0.5', 0.5, DRAWFLAG_NORMAL);
557         
558         for(i = 0; i < sbar_num_fields; ++i)
559         {
560                 if(Sbar_IsFieldMasked(sbar_field[i]))
561                         continue;
562                 if(sbar_field[i] == SBF_SEPARATOR)
563                         break;
564                 drawstring(pos, sbar_title[i], sbar_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
565                 pos_x += sbar_fontsize_x*sbar_size[i] + sbar_fontsize_x;
566         }
567         
568         if(sbar_field[i] == SBF_SEPARATOR)
569         {
570                 pos_x = xmax + sbar_fontsize_x;
571                 tmp_y = tmp_z = 0;
572                 for(i = sbar_num_fields-1; i > 0; --i)
573                 {
574                         if(Sbar_IsFieldMasked(sbar_field[i]))
575                                 continue;
576                         if(sbar_field[i] == SBF_SEPARATOR)
577                                 break;
578                         
579                         pos_x -= sbar_fontsize_x*sbar_size[i] + sbar_fontsize_x;
580                         /**
581                          * FTEQCC BUG!
582                          * Using the following line will fuck it all up:
583                          **
584                          * tmp_x = sbar_size[i] - strlen(sbar_title[i])*8;
585                          */
586                         tmp_x = sbar_fontsize_x*sbar_size[i];
587                         tmp_x -= stringwidth(sbar_title[i], FALSE)*sbar_fontsize_x;
588                         drawstring(pos + tmp, sbar_title[i], sbar_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
589                 }
590         }
591                 
592         pos_x = xmin;
593         pos_y += 1.5 * sbar_fontsize_y;
594
595         sbar_save = sbar;
596         sbar = '0 0 0';
597         
598         if(teamplay)
599         {
600                 for(tm = sortedTeams.sort_next; tm; tm = tm.sort_next)
601                 {
602                         if(!tm.sb_player || tm.sb_team == COLOR_SPECTATOR) // no players in it?
603                                 continue;
604
605                         rgb = GetTeamRGB(tm.sb_team);
606
607                         pos_x = xmin - 4*24;
608                         if(gametype == GAME_CTF)
609                         {
610                                 if(tm.sb_team == COLOR_TEAM1)
611                                         Sbar_DrawXNum(pos, caps_team1, 4, 24, rgb, 1, DRAWFLAG_NORMAL);
612                                 else if(tm.sb_team == COLOR_TEAM2)
613                                         Sbar_DrawXNum(pos, caps_team2, 4, 24, rgb, 1, DRAWFLAG_NORMAL);
614                                 pos_x = xmin - 4*10;
615                                 Sbar_DrawXNum(pos + '0 24', tm.sb_frags, 4, 10, rgb, 1, DRAWFLAG_NORMAL);
616                                 pos_x = xmin;
617                         } else
618                                 Sbar_DrawXNum(pos, tm.sb_frags, 4, 24, rgb, 1, DRAWFLAG_NORMAL);
619                         pos_x = xmin;
620
621                         // abuse specs as playerounter
622                         specs = 0;
623                         for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
624                         {
625                                 if(pl.sb_team == tm.sb_team)
626                                         ++specs;
627                         }
628
629                         if(specs < 2)
630                                 specs = 2;
631                         if(gametype == GAME_CTF && specs < 4)
632                                 specs = 4;
633                         
634                         tmp_x = sbwidth;
635                         tmp_y = 1.25 * sbar_fontsize_y * specs;
636                         drawfill(pos - '1 1', tmp + '2 0', rgb, 0.2, DRAWFLAG_NORMAL);
637                         
638                         for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
639                         {
640                                 if(pl.sb_team != tm.sb_team)
641                                         continue;
642                                 Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 0);
643                                 pos_y += 1.25 * sbar_fontsize_y;
644                                 tmp_y -= 1.25 * sbar_fontsize_y;
645                         }
646                         pos_y += tmp_y + 1.5 * sbar_fontsize_y;
647                 }
648                 // rgb := tempvector :)
649                 rgb = pos + '0 1.5 0' * sbar_fontsize_y;
650                 pos_y += 3 * sbar_fontsize_y;
651                 specs = 0;
652                 for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
653                 {
654                         if(pl.sb_team != COLOR_SPECTATOR)
655                                 continue;
656                         //drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
657                         Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 1);
658                         pos += '0 1.25 0' * sbar_fontsize_y;
659                         ++specs;
660                 }
661                         
662                 if(specs)
663                         drawstring(rgb, "Spectators", sbar_fontsize, '1 1 1', 1, 0);
664         } else {
665                 pos_x = xmin;
666                 for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
667                 {
668                         if(pl.sb_team == COLOR_SPECTATOR)
669                                 continue;
670                         Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 0);
671                         pos_y += 1.25 * sbar_fontsize_y;
672                         tmp_y -= 1.25 * sbar_fontsize_y;
673                 }
674                 pos_y += tmp_y + 1.5 * sbar_fontsize_y;
675
676                 // rgb := tempvector :)
677                 rgb = pos + '0 1.5 0' * sbar_fontsize_y;
678                 pos_y += 3 * sbar_fontsize_y;
679                 specs = 0;
680                 for(pl = sortedPlayers.sort_next; pl; pl = pl.sort_next)
681                 {
682                         if(pl.sb_team != COLOR_SPECTATOR)
683                                 continue;
684                         //drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
685                         Sbar_PrintScoreboardItem(pos, pl, (pl.sb_player == player_localentnum - 1), 1);
686                         pos += '0 1.25 0' * sbar_fontsize_y;
687                         ++specs;
688                 }
689                         
690                 if(specs)
691                         drawstring(rgb, "Spectators", sbar_fontsize, '1 1 1', 1, 0);
692         }
693         sbar = sbar_save;
694 }
695
696 void Sbar_Score(float margin)
697 {
698         float timelimit, timeleft, minutes, seconds, distribution, myplace;
699         vector sbar_save, place;
700         entity tm, pl, me;
701         sbar_save = sbar;
702
703         sbar_y = vid_conheight - (32+12);
704         sbar_x -= margin;
705         
706         place = '-48 -12 0';
707         if(teamplay)
708         {
709                 // Layout:
710                 //
711                 //   team1 team3 team4
712                 //
713                 //         TEAM2
714                 //for(i = 0; i < 4; ++i)
715                 for(tm = sortedTeams.sort_next; tm; tm = tm.sort_next)
716                 {
717                         if(tm.sb_team == COLOR_SPECTATOR || !tm.sb_player) // no players? don't display
718                                 continue;
719                         // -32*4 = -128
720                         if(tm.sb_team == myteam)
721                                 Sbar_DrawXNum('-128 0', tm.sb_frags, 4, 32, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
722                         else
723                         {
724                                 Sbar_DrawXNum(place, tm.sb_frags, 4, 12, GetTeamRGB(tm.sb_team), 1, DRAWFLAG_NORMAL);
725                                 place_x -= 4*12;
726                         }
727                 }
728         } else {
729                 // me vector := [team/connected frags id]
730                 myplace = 0;
731                 for(me = sortedPlayers.sort_next; me; me = me.sort_next)
732                 {
733                         if(me.sb_team != COLOR_SPECTATOR)
734                                 ++myplace;
735                         if(me.sb_player == player_localentnum - 1)
736                                 break;
737                 }
738                 pl = sortedPlayers.sort_next;
739                 if(pl == me)
740                         pl = pl.sort_next;
741                 
742                 if(pl && myplace != 1)
743                 {
744                         distribution = me.sb_frags - pl.sb_frags;
745                 } else if(pl) {
746                         distribution = me.sb_frags - pl.sb_frags;
747                 } else
748                         distribution = 0;
749                 
750                 if(myplace == 1)
751                         Sbar_DrawXNum('-36 -12', myplace, 3, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
752                 else if(myplace == 2)
753                         Sbar_DrawXNum('-36 -12', myplace, 3, 12, '1 1 0', 1, DRAWFLAG_NORMAL);
754                 else
755                         Sbar_DrawXNum('-36 -12', myplace, 3, 12, '1 0 0', 1, DRAWFLAG_NORMAL);
756
757                 if(distribution >= 0)
758                 {
759                         Sbar_DrawXNum('-84 -12', distribution, 4, 12, ' 1 1 1', 1, DRAWFLAG_NORMAL);
760                         Sbar_DrawXNum('-128 0', me.sb_frags, 4, 32, '1 1 1', 1, DRAWFLAG_NORMAL);
761                 } else if(distribution >= -5)
762                 {
763                         Sbar_DrawXNum('-84 -12', distribution, 4, 12, ' 1 1 0', 1, DRAWFLAG_NORMAL);
764                         Sbar_DrawXNum('-128 0', me.sb_frags, 4, 32, '1 1 0', 1, DRAWFLAG_NORMAL);
765                 } else {
766                         Sbar_DrawXNum('-84 -12', distribution, 4, 12, ' 1 0 0', 1, DRAWFLAG_NORMAL);
767                         Sbar_DrawXNum('-128 0', me.sb_frags, 4, 32, '1 0 0', 1, DRAWFLAG_NORMAL);
768                 }
769         }
770         timelimit = getstatf(STAT_TIMELIMIT);
771         if(timelimit)
772         {
773                 timeleft = max(0, timelimit * 60 - time);
774                 minutes = floor(timeleft / 60);
775                 seconds = floor(timeleft - minutes*60);
776                 if(minutes >= 5)
777                 {
778                         Sbar_DrawXNum('-72 32', minutes, 3, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
779                         drawpic(sbar + '-36 32', "gfx/num_colon", '12 12', '1 1 1', sbar_alpha_fg, 0);
780                         Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
781                 } else if(minutes >= 1)
782                 {
783                         Sbar_DrawXNum('-72 32', minutes, 3, 12, '1 1 0', 1, DRAWFLAG_NORMAL);
784                         drawpic(sbar + '-36 32', "gfx/num_colon", '12 12', '1 1 0', sbar_alpha_fg, 0);
785                         Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 1 0', 1, DRAWFLAG_NORMAL);
786                 } else {
787                         Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 0 0', 1, DRAWFLAG_NORMAL);
788                 }
789         } else {
790                 minutes = floor(time / 60);
791                 seconds = floor(time - minutes*60);
792                 Sbar_DrawXNum('-72 32', minutes, 3, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
793                 drawpic(sbar + '-36 32', "gfx/num_colon", '12 12', '1 1 1', sbar_alpha_fg, 0);
794                 Sbar_DrawXNum('-24 32', seconds, -2, 12, '1 1 1', 1, DRAWFLAG_NORMAL);
795         }
796         sbar = sbar_save;
797 }
798
799 void Sbar_MiniscoreItem(vector pos, entity pl, float is_self)
800 {
801         float x;
802         pos_x += 72;
803         
804         if(teamplay)
805                 drawfill(pos + '0 1 0', '40 6 0', GetTeamRGB(pl.sb_team)*0.5, 1, DRAWFLAG_NORMAL);
806         else
807                 drawfill(pos + '0 1 0', '40 6 0', '0.5 0.5 0.5', 0.5, DRAWFLAG_NORMAL);
808         x = pos_x;
809         pos_x += 5*8;
810         pos_x -= stringwidth(ftos(pl.sb_frags), FALSE)*8;
811         drawstring(pos, ftos(pl.sb_frags), '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
812         pos_x = x;
813         if(is_self)
814         {
815                 pos_x += 48;
816                 drawstring(pos, "\x0D", '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
817                 pos_x += 8;
818         } else
819                 pos_x += 56;
820         drawcolorcodedstring(pos, getplayerkey(pl.sb_player, "name"), '8 8 0', 1, 0);
821 }
822
823 void Sbar_MiniscoreTeamItem(vector pos, float color, float frags, float is_self)
824 {
825         float x;
826         pos_x += 72;
827         
828         if(teamplay)
829                 drawfill(pos + '0 1 0', '40 6 0', GetTeamRGB(color)*0.5, 1, DRAWFLAG_NORMAL);
830         else
831                 drawfill(pos + '0 1 0', '40 6 0', '0.5 0.5 0.5', 0.5, DRAWFLAG_NORMAL);
832         x = pos_x;
833         pos_x += 5*8;
834         pos_x -= stringwidth(ftos(frags), FALSE)*8;
835         drawstring(pos, ftos(frags), '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
836         pos_x = x;
837         if(is_self)
838         {
839                 pos_x += 48;
840                 drawstring(pos, "\x0D", '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
841                 pos_x += 8;
842         } else
843                 pos_x += 56;
844         drawstring(pos, GetTeamName(color), '8 8 0', '1 1 1', 1, DRAWFLAG_NORMAL);
845 }
846
847 void Sbar_MiniDeathmatchOverlay(vector pos)
848 {
849         float numlines, up, down;
850         entity me, tm, pl;
851         float miniscoreboard_size;
852         miniscoreboard_size = cvar("sbar_miniscoreboard_size");
853         
854         if(miniscoreboard_size == 0)
855                 return;
856         pos_y = vid_conheight - 8;
857         
858         if(miniscoreboard_size < 0)
859                 numlines = (vid_conheight - sbar_y + 7) / 8;
860         else
861                 numlines = miniscoreboard_size;
862
863         // give up if there isn't enough room
864         if(pos_x >= vid_conwidth || pos_y >= vid_conheight || numlines < 1)
865                 return;
866
867         // me vector := [team/connected frags id]
868         for(me = sortedPlayers.sort_next; me; me = me.sort_next)
869         {
870                 if(me.sb_player == player_localentnum - 1)
871                         break;
872         }
873
874         if(teamplay)
875                 numlines -= numteams;
876
877         // figure out how many players above and below we can show
878         up = floor(numlines/2);
879         down = up;
880         if((up + down) > numlines)
881                 down = numlines - up;
882
883         // render bottom-up
884         for(pl = me.sort_next; pl && down > 0; pl = pl.sort_next)
885         {
886                 if(pl.sb_team == COLOR_SPECTATOR)
887                         continue;
888                 Sbar_MiniscoreItem(pos, pl, false);
889                 pos_y -= 9;
890                 --down;
891         }
892         Sbar_MiniscoreItem(pos, me, true);
893         pos_y -= 9;
894         up += down; // if there weren't enough lines below... add them
895         for(pl = me.sort_prev; pl != sortedPlayers && up > 0; pl = pl.sort_prev)
896         {
897                 if(pl.sb_team == COLOR_SPECTATOR)
898                         continue;
899                 Sbar_MiniscoreItem(pos, pl, false);
900                 pos_y -= 9;
901                 --up;
902         }
903
904         if(teamplay)
905         {
906                 for(tm = sortedTeams.sort_next; tm.sort_next; tm = tm.sort_next);
907                 for(; tm != sortedTeams; tm = tm.sort_prev)
908                 {
909                         if(!tm.sb_player || tm.sb_team == COLOR_SPECTATOR) // no players?
910                                 continue;
911                         Sbar_MiniscoreTeamItem(pos, tm.sb_team, tm.sb_frags, (tm.sb_team == me.sb_team));
912                         pos_y -= 9;
913                 }
914         }
915 }
916
917 void Sbar_Draw (void)
918 {
919         float i;
920         float x, fade;
921         float stat_items;
922
923         Sbar_SortFrags();
924
925         sb_lines = 24;
926         
927         if (sb_showscores)
928                 Sbar_DrawScoreboard();
929         else if (intermission == 1)
930         {
931                 Sbar_DrawScoreboard();
932                 return;
933         }
934         else if (intermission == 2)
935                 Sbar_FinaleOverlay();
936         else
937         {
938                 if (sb_showscores || (getstati(STAT_HEALTH) <= 0 && cvar("cl_deathscoreboard")))
939                 {
940                         sbar_x = (vid_conwidth - 640.0)*0.5;
941                         sbar_y = vid_conheight - 47;
942                         //Sbar_DrawAlphaPic (sbar_x, sbar_y, sb_scorebar, sbar_alpha_bg.value);
943                         //drawpic('0 0', "gfx/scorebar", '0 0 0', '1 1 1', cvar("sbar_alpha_bg"), 0);
944                         Sbar_DrawScoreboard ();
945                 }
946                 else
947                 {
948                         if (sb_lines && sbar_hudselector == 1)
949                         {
950                                 stat_items = getstati(STAT_ITEMS);
951
952                                 sbar_x = (vid_conwidth - 320.0)*0.5;
953                                 sbar_y = vid_conheight - 24.0 - 16.0;
954                                 sbar_z = 0;
955                         
956                                 fade = 3.2 - 2 * (time - weapontime);
957                                 fade = bound(0.7, fade, 1);
958
959                                 x = 1.0;
960                                 for(i = 0; i < 8; ++i)
961                                 {
962                                         if(stat_items & x)
963                                         {
964                                                 Sbar_DrawWeapon(i+1, fade, (i + 2 == activeweapon));
965                                         }
966                                         x *= 2;
967                                 }
968                                 x *= 2*2*2*2;
969                                 if(stat_items & x)
970                                 {
971                                         Sbar_DrawWeapon(0, fade, (activeweapon == 1));
972                                 }
973
974                                 // armor
975                                 x = getstati(STAT_ARMOR);
976                                 if (x > 0)
977                                 {
978                                         // "gfx/sb_armor"
979                                         //Sbar_DrawStretchPic (72, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
980                                         drawpic(sbar + '72 0', "gfx/sb_armor", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
981                                         if(x > 200)
982                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0 1 0', 1, 0);
983                                         else if(x > 100)
984                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0.2 1 0', 1, 0);
985                                         else if(x > 50)
986                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
987                                         else if(x > 25)
988                                                 Sbar_DrawXNum('0 0', x, 3, 24, '1 1 0.2', 1, 0);
989                                         else
990                                                 Sbar_DrawXNum('0 0', x, 3, 24, '0.7 0 0', 1, 0);
991                                 }
992
993                                 // health
994                                 x = getstati(STAT_HEALTH);
995                                 if (x != 0)
996                                 {
997                                         // "gfx/sb_health"
998                                         //Sbar_DrawStretchPic (184, 0, sb_health, sbar_alpha_fg.value, 24, 24);
999                                         drawpic(sbar + '184 0', "gfx/sb_health", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
1000                                         if(x > 200)
1001                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0 1 0', 1, 0);
1002                                         else if(x > 100)
1003                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0.2 1 0', 1, 0);
1004                                         else if(x > 50)
1005                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
1006                                         else if(x > 25)
1007                                                 Sbar_DrawXNum('112 0', x, 3, 24, '1 1 0.2', 1, 0);
1008                                         else
1009                                                 Sbar_DrawXNum('112 0', x, 3, 24, '0.7 0 0', 1, 0);
1010                                 }
1011
1012                                 // ammo
1013                                 x = getstati(STAT_AMMO);
1014                                 if ((stat_items & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || x != 0)
1015                                 {
1016                                         if (stat_items & NEX_IT_SHELLS)
1017                                                 drawpic(sbar + '296 0', "gfx/sb_shells", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
1018                                         else if (stat_items & NEX_IT_BULLETS)
1019                                                 drawpic(sbar + '296 0', "gfx/sb_bullets", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
1020                                         else if (stat_items & NEX_IT_ROCKETS)
1021                                                 drawpic(sbar + '296 0', "gfx/sb_rocket", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
1022                                         else if (stat_items & NEX_IT_CELLS)
1023                                                 drawpic(sbar + '296 0', "gfx/sb_cells", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
1024                                         if(x > 10)
1025                                                 Sbar_DrawXNum('224 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
1026                                         else
1027                                                 Sbar_DrawXNum('224 0', x, 3, 24, '0.7 0 0', 1, 0);
1028                                 }
1029
1030                                 if (sbar_x + 320 + 160 <= vid_conwidth)
1031                                         Sbar_MiniDeathmatchOverlay(sbar + '320 0');
1032                                 if (sbar_x > 0)
1033                                         Sbar_Score(16);
1034                                 // The margin can be at most 8 to support 640x480 console size:
1035                                 //   320 + 2 * (144 + 16) = 640
1036                         }
1037                         else if (sb_lines)
1038                         {
1039                         
1040                                 stat_items = getstati(STAT_ITEMS);
1041                         
1042                                 sbar_x = (vid_conwidth - 640.0)*0.5;
1043                                 sbar_y = vid_conheight - 47;
1044                                 sbar_z = 0;
1045
1046                                 fade = 3 - 2 * (time - weapontime);
1047
1048                                 x = 1.0;
1049                                 for(i = 0; i < 8; ++i)
1050                                 {
1051                                         if(stat_items & x)
1052                                         {
1053                                                 Sbar_DrawWeapon(i+1, fade, (i + 2 == activeweapon));
1054                                         }
1055                                         x *= 2;
1056                                 }
1057                                 x *= 2*2*2*2;
1058                                 if(stat_items & x)
1059                                 {
1060                                         Sbar_DrawWeapon(0, fade, (activeweapon == 1));
1061                                 }
1062
1063                                 if (sb_lines > 24)
1064                                         drawpic(sbar, "gfx/sbar", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
1065                                 else
1066                                         drawpic(sbar, "gfx/sbar_minimal", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
1067
1068                                 // armor
1069                                 // (340-3*24) = 268
1070                                 Sbar_DrawXNum('268 12', getstati(STAT_ARMOR), 3, 24, '0.6 0.7 0.8', 1, 0);
1071
1072                                 // health
1073                                 // (154-3*24) = 82
1074                                 x = getstati(STAT_HEALTH);
1075                                 if(x > 100)
1076                                         Sbar_DrawXNum('82 12', x, 3, 24, '1 1 1', 1, 0);
1077                                 else if(x <= 25 && time - floor(time) > 0.5)
1078                                         Sbar_DrawXNum('82 12', x, 3, 24, '0.7 0 0', 1, 0);
1079                                 else
1080                                         Sbar_DrawXNum('81 12', x, 3, 24, '0.6 0.7 0.8', 1, 0);
1081
1082                                 // AK dont draw ammo for the laser
1083                                 x = getstati(STAT_AMMO);
1084                                 if(activeweapon != 12)
1085                                 {
1086                                         // (519-3*24) = 447
1087                                         if (stat_items & NEX_IT_SHELLS)
1088                                                 drawpic(sbar + '519 0', "gfx/sb_shells", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
1089                                         else if (stat_items & NEX_IT_BULLETS)
1090                                                 drawpic(sbar + '519 0', "gfx/sb_bullets", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
1091                                         else if (stat_items & NEX_IT_ROCKETS)
1092                                                 drawpic(sbar + '519 0', "gfx/sb_rocket", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
1093                                         else if (stat_items & NEX_IT_CELLS)
1094                                                 drawpic(sbar + '519 0', "gfx/sb_cells", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
1095                                         if(x > 10)
1096                                                 Sbar_DrawXNum('447 12', x, 3, 24, '0.6 0.7 0.8', 1, 0);
1097                                         else
1098                                                 Sbar_DrawXNum('447 12', x, 3, 24, '0.7 0 0', 1, 0);
1099                                 }
1100
1101                                 if (sb_lines > 24)
1102                                         drawpic(sbar, "gfx/sbar_overlay", '0 0 0', '1 1 1', 1, DRAWFLAG_MODULATE);
1103
1104                                 if (sbar_x + 600 + 160 <= vid_conwidth)
1105                                         Sbar_MiniDeathmatchOverlay (sbar + '600 0');
1106
1107                                 if (sbar_x > 0)
1108                                         Sbar_Score(-16);
1109                                 // Because:
1110                                 //   Mini scoreboard uses 12*4 per other team, that is, 144
1111                                 //   pixels when there are four teams...
1112                                 //   Nexuiz by default sets vid_conwidth to 800... makes
1113                                 //   sbar_x == 80...
1114                                 //   so we need to shift it by 64 pixels to the right to fit
1115                                 //   BUT: then it overlaps with the image that gets drawn
1116                                 //   for viewsize 100! Therefore, just account for 3 teams,
1117                                 //   that is, 96 pixels mini scoreboard size, needing 16 pixels
1118                                 //   to the right!
1119                         }
1120                 
1121                 
1122                         if(gametype == GAME_KEYHUNT)
1123                         {
1124                                 CSQC_kh_hud();
1125                         } else if(gametype == GAME_CTF)
1126                         {
1127                                 CSQC_ctf_hud();
1128                         }
1129                 }
1130         }
1131 }
1132
1133 void CSQC_ctf_hud(void)
1134 {
1135         // cvar("sbar_flagstatus_right") move the flag icons right
1136         // cvar("sbar_flagstatus_pos") pixel position of the nexuiz flagstatus icons
1137         float redflag, blueflag;
1138         float stat_items;
1139         vector pos;
1140         
1141         stat_items = getstati(STAT_ITEMS);
1142         redflag = (stat_items/32768) & 3;
1143         blueflag = (stat_items/131072) & 3;
1144
1145         /**
1146          * FTEQCC BUG!
1147          * For some reason now not even THAT works there...
1148          * Maybe the minus' precedence screws it up? The last one there, maybe I should use brackets
1149          **
1150          * pos_x = (cvar("sbar_flagstatus_right")) ? vid_conwidth - 10 - sbar_x - 64 : 10 - sbar_x;
1151          ** Should try those later:
1152          * pos_x = (cvar("sbar_flagstatus_right")) ? (vid_conwidth - 10 - sbar_x - 64) : (10 - sbar_x);
1153          * pos_x = ( (cvar("sbar_flagstatus_right")) ? vid_conwidth - 10 - 64 : 10 ) - sbar_x;
1154          */
1155         
1156         if(cvar("sbar_flagstatus_right"))
1157                 pos_x = vid_conwidth - 10 - sbar_x - 64;
1158         else
1159                 pos_x = 10 - sbar_x;
1160         
1161         pos_z = 0;
1162
1163         if(sbar_hudselector == 1)
1164                 pos_y = (vid_conheight - sbar_y) - cvar("sbar_flagstatus_pos") - 64;
1165         else
1166                 pos_y = -117;
1167
1168         pos += sbar;
1169
1170         switch(redflag)
1171         {
1172         case 1: drawpic(pos, "gfx/sb_flag_red_taken", '0 0 0', '1 1 1', 1, DRAWFLAG_NORMAL); break;
1173         case 2: drawpic(pos, "gfx/sb_flag_red_lost", '0 0 0', '1 1 1', 1, DRAWFLAG_NORMAL); break;
1174         case 3: drawpic(pos, "gfx/sb_flag_red_carrying", '0 0 0', '1 1 1', 1, DRAWFLAG_NORMAL); break;
1175         }
1176
1177         pos_y -= 64;
1178         
1179         switch(blueflag)
1180         {
1181         case 1: drawpic(pos, "gfx/sb_flag_blue_taken", '0 0 0', '1 1 1', 1, 0); break;
1182         case 2: drawpic(pos, "gfx/sb_flag_blue_lost", '0 0 0', '1 1 1', 1, 0); break;
1183         case 3: drawpic(pos, "gfx/sb_flag_blue_carrying", '0 0 0', '1 1 1', 1, 0); break;
1184         }
1185 }