]> icculus.org git repositories - divverent/darkplaces.git/blob - sbar.c
changed how ping report hiding operates, so that it only hides one ping report for...
[divverent/darkplaces.git] / sbar.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sbar.c -- status bar code
21
22 #include "quakedef.h"
23
24 cachepic_t *sb_disc;
25
26 #define STAT_MINUS 10 // num frame for '-' stats digit
27 cachepic_t *sb_nums[2][11];
28 cachepic_t *sb_colon, *sb_slash;
29 cachepic_t *sb_ibar;
30 cachepic_t *sb_sbar;
31 cachepic_t *sb_scorebar;
32 // AK only used by NEX
33 cachepic_t *sb_sbar_minimal;
34 cachepic_t *sb_sbar_overlay;
35
36 // AK changed the bound to 9
37 cachepic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
38 cachepic_t *sb_ammo[4];
39 cachepic_t *sb_sigil[4];
40 cachepic_t *sb_armor[3];
41 cachepic_t *sb_items[32];
42
43 // 0-4 are based on health (in 20 increments)
44 // 0 is static, 1 is temporary animation
45 cachepic_t *sb_faces[5][2];
46
47 cachepic_t *sb_face_invis;
48 cachepic_t *sb_face_quad;
49 cachepic_t *sb_face_invuln;
50 cachepic_t *sb_face_invis_invuln;
51
52 qboolean sb_showscores;
53
54 int sb_lines;                   // scan lines to draw
55
56 cachepic_t *rsb_invbar[2];
57 cachepic_t *rsb_weapons[5];
58 cachepic_t *rsb_items[2];
59 cachepic_t *rsb_ammo[3];
60 cachepic_t *rsb_teambord;               // PGM 01/19/97 - team color border
61
62 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
63 cachepic_t *hsb_weapons[7][5];   // 0 is active, 1 is owned, 2-5 are flashes
64 //MED 01/04/97 added array to simplify weapon parsing
65 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
66 //MED 01/04/97 added hipnotic items array
67 cachepic_t *hsb_items[2];
68
69 //GAME_SOM stuff:
70 cachepic_t *somsb_health;
71 cachepic_t *somsb_ammo[4];
72 cachepic_t *somsb_armor[3];
73
74 cachepic_t *zymsb_crosshair_center;
75 cachepic_t *zymsb_crosshair_line;
76 cachepic_t *zymsb_crosshair_health;
77 cachepic_t *zymsb_crosshair_ammo;
78 cachepic_t *zymsb_crosshair_clip;
79 cachepic_t *zymsb_crosshair_background;
80 cachepic_t *zymsb_crosshair_left1;
81 cachepic_t *zymsb_crosshair_left2;
82 cachepic_t *zymsb_crosshair_right;
83
84 cachepic_t *sb_ranking;
85 cachepic_t *sb_complete;
86 cachepic_t *sb_inter;
87 cachepic_t *sb_finale;
88
89 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
90 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
91 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
92 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
93 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
94 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
95 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
96
97 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
98
99 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
100 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
101 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
102 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
103 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
104
105 void Sbar_MiniDeathmatchOverlay (int x, int y);
106 void Sbar_DeathmatchOverlay (void);
107 void Sbar_IntermissionOverlay (void);
108 void Sbar_FinaleOverlay (void);
109
110
111 /*
112 ===============
113 Sbar_ShowScores
114
115 Tab key down
116 ===============
117 */
118 void Sbar_ShowScores (void)
119 {
120         if (sb_showscores)
121                 return;
122         sb_showscores = true;
123 }
124
125 /*
126 ===============
127 Sbar_DontShowScores
128
129 Tab key up
130 ===============
131 */
132 void Sbar_DontShowScores (void)
133 {
134         sb_showscores = false;
135 }
136
137 void sbar_start(void)
138 {
139         int i;
140
141         if (gamemode == GAME_NETHERWORLD)
142         {
143         }
144         else if (gamemode == GAME_SOM)
145         {
146                 sb_disc = Draw_CachePic("gfx/disc", true);
147
148                 for (i = 0;i < 10;i++)
149                         sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
150
151                 somsb_health = Draw_CachePic("gfx/hud_health", true);
152                 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
153                 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
154                 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
155                 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
156                 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
157                 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
158                 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
159         }
160         else if (gamemode == GAME_NEXUIZ)
161         {
162                 for (i = 0;i < 10;i++)
163                         sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
164                 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
165
166                 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
167                 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
168                 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
169                 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
170
171                 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
172                 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
173                 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
174                 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
175
176                 sb_sbar = Draw_CachePic("gfx/sbar", true);
177                 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
178                 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
179
180                 for(i = 0; i < 9;i++)
181                         sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
182         }
183         else if (gamemode == GAME_ZYMOTIC)
184         {
185                 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
186                 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
187                 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
188                 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
189                 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
190                 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
191                 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
192                 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
193                 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
194         }
195         else
196         {
197                 sb_disc = Draw_CachePic("gfx/disc", true);
198
199                 for (i = 0;i < 10;i++)
200                 {
201                         sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
202                         sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
203                 }
204
205                 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
206                 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
207
208                 sb_colon = Draw_CachePic ("gfx/num_colon", true);
209                 sb_slash = Draw_CachePic ("gfx/num_slash", true);
210
211                 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
212                 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
213                 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
214                 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
215                 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
216                 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
217                 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
218
219                 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
220                 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
221                 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
222                 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
223                 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
224                 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
225                 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
226
227                 for (i = 0;i < 5;i++)
228                 {
229                         sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
230                         sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
231                         sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
232                         sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
233                         sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
234                         sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
235                         sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
236                 }
237
238                 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
239                 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
240                 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
241                 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
242
243                 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
244                 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
245                 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
246
247                 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
248                 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
249                 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
250                 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
251                 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
252                 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
253
254                 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
255                 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
256                 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
257                 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
258
259                 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
260                 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
261                 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
262                 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
263                 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
264                 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
265                 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
266                 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
267                 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
268                 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
269
270                 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
271                 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
272                 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
273                 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
274
275                 sb_sbar = Draw_CachePic ("gfx/sbar", true);
276                 sb_ibar = Draw_CachePic ("gfx/ibar", true);
277                 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
278
279         //MED 01/04/97 added new hipnotic weapons
280                 if (gamemode == GAME_HIPNOTIC)
281                 {
282                         hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
283                         hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
284                         hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
285                         hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
286                         hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
287
288                         hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
289                         hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
290                         hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
291                         hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
292                         hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
293
294                         for (i = 0;i < 5;i++)
295                         {
296                                 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
297                                 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
298                                 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
299                                 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
300                                 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
301                         }
302
303                         hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
304                         hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
305                 }
306                 else if (gamemode == GAME_ROGUE)
307                 {
308                         rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
309                         rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
310
311                         rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
312                         rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
313                         rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
314                         rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
315                         rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
316
317                         rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
318                         rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
319
320         // PGM 01/19/97 - team color border
321                         rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
322         // PGM 01/19/97 - team color border
323
324                         rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
325                         rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
326                         rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
327                 }
328         }
329
330         sb_ranking = Draw_CachePic ("gfx/ranking", true);
331         sb_complete = Draw_CachePic ("gfx/complete", true);
332         sb_inter = Draw_CachePic ("gfx/inter", true);
333         sb_finale = Draw_CachePic ("gfx/finale", true);
334 }
335
336 void sbar_shutdown(void)
337 {
338 }
339
340 void sbar_newmap(void)
341 {
342 }
343
344 void Sbar_Init (void)
345 {
346         Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
347         Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
348         Cvar_RegisterVariable(&showfps);
349         Cvar_RegisterVariable(&showtime);
350         Cvar_RegisterVariable(&showtime_format);
351         Cvar_RegisterVariable(&showdate);
352         Cvar_RegisterVariable(&showdate_format);
353         Cvar_RegisterVariable(&sbar_alpha_bg);
354         Cvar_RegisterVariable(&sbar_alpha_fg);
355         Cvar_RegisterVariable(&cl_deathscoreboard);
356
357         Cvar_RegisterVariable(&crosshair_color_red);
358         Cvar_RegisterVariable(&crosshair_color_green);
359         Cvar_RegisterVariable(&crosshair_color_blue);
360         Cvar_RegisterVariable(&crosshair_color_alpha);
361         Cvar_RegisterVariable(&crosshair_size);
362
363         R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
364 }
365
366
367 //=============================================================================
368
369 // drawing routines are relative to the status bar location
370
371 int sbar_x, sbar_y;
372
373 /*
374 =============
375 Sbar_DrawPic
376 =============
377 */
378 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
379 {
380         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
381 }
382
383 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
384 {
385         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
386 }
387
388 /*
389 ================
390 Sbar_DrawCharacter
391
392 Draws one solid graphics character
393 ================
394 */
395 void Sbar_DrawCharacter (int x, int y, int num)
396 {
397         DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
398 }
399
400 /*
401 ================
402 Sbar_DrawString
403 ================
404 */
405 void Sbar_DrawString (int x, int y, char *str)
406 {
407         DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
408 }
409
410 /*
411 =============
412 Sbar_DrawNum
413 =============
414 */
415 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
416 {
417         char str[32], *ptr;
418         int l, frame;
419
420         l = sprintf(str, "%i", num);
421         ptr = str;
422         if (l > digits)
423                 ptr += (l-digits);
424         if (l < digits)
425                 x += (digits-l)*24;
426
427         while (*ptr)
428         {
429                 if (*ptr == '-')
430                         frame = STAT_MINUS;
431                 else
432                         frame = *ptr -'0';
433
434                 Sbar_DrawPic (x, y, sb_nums[color][frame]);
435                 x += 24;
436
437                 ptr++;
438         }
439 }
440
441 /*
442 =============
443 Sbar_DrawXNum
444 =============
445 */
446
447 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
448 {
449         char str[32], *ptr;
450         int l, frame;
451
452         l = sprintf(str, "%i", num);
453         ptr = str;
454         if (l > digits)
455                 ptr += (l-digits);
456         if (l < digits)
457                 x += (digits-l) * lettersize;
458
459         while (*ptr)
460         {
461                 if (*ptr == '-')
462                         frame = STAT_MINUS;
463                 else
464                         frame = *ptr -'0';
465
466                 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
467                 x += lettersize;
468
469                 ptr++;
470         }
471 }
472
473 //=============================================================================
474
475
476 int Sbar_IsTeammatch()
477 {
478         // currently only nexuiz uses the team score board
479         return ((gamemode == GAME_NEXUIZ)
480                 && (teamplay.integer > 0));
481 }
482
483 /*
484 ===============
485 Sbar_SortFrags
486 ===============
487 */
488 static int fragsort[MAX_SCOREBOARD];
489 static int scoreboardlines;
490
491 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
492 int Sbar_GetPlayer (int index)
493 {
494         if(index < 0)
495         {
496                 index = -1-index;
497                 if(index >= scoreboardlines)
498                         return -1;
499                 index = fragsort[index];
500         }
501         if(index >= scoreboardlines)
502                 return -1;
503         return index;
504 }
505
506 static scoreboard_t teams[MAX_SCOREBOARD];
507 static int teamsort[MAX_SCOREBOARD];
508 static int teamlines;
509 void Sbar_SortFrags (void)
510 {
511         int i, j, k, color;
512
513         // sort by frags
514         scoreboardlines = 0;
515         for (i=0 ; i<cl.maxclients ; i++)
516         {
517                 if (cl.scores[i].name[0])
518                 {
519                         fragsort[scoreboardlines] = i;
520                         scoreboardlines++;
521                 }
522         }
523
524         for (i=0 ; i<scoreboardlines ; i++)
525                 for (j=0 ; j<scoreboardlines-1-i ; j++)
526                         if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
527                         {
528                                 k = fragsort[j];
529                                 fragsort[j] = fragsort[j+1];
530                                 fragsort[j+1] = k;
531                         }
532
533         teamlines = 0;
534         if (Sbar_IsTeammatch ())
535         {
536                 // now sort players by teams.
537                 for (i=0 ; i<scoreboardlines ; i++)
538                 {
539                         for (j=0 ; j<scoreboardlines-1-i ; j++)
540                         {
541                                 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
542                                 {
543                                         k = fragsort[j];
544                                         fragsort[j] = fragsort[j+1];
545                                         fragsort[j+1] = k;
546                                 }
547                         }
548                 }
549
550                 // calculate team scores
551                 color = -1;
552                 for (i=0 ; i<scoreboardlines ; i++)
553                 {
554                         if (color != (cl.scores[fragsort[i]].colors & 15))
555                         {
556                                 color = cl.scores[fragsort[i]].colors & 15;
557                                 teamlines++;
558
559                                 if (color == 4)
560                                         strcpy(teams[teamlines-1].name, "^1Red Team");
561                                 else if (color == 13)
562                                         strcpy(teams[teamlines-1].name, "^4Blue Team");
563                                 else if (color == 9)
564                                         strcpy(teams[teamlines-1].name, "^6Pink Team");
565                                 else if (color == 12)
566                                         strcpy(teams[teamlines-1].name, "^3Yellow Team");
567                                 else
568                                         strcpy(teams[teamlines-1].name, "Total Team Score");
569
570                                 teams[teamlines-1].frags = 0;
571                                 teams[teamlines-1].colors = color + 16 * color;
572                         }
573
574                         if (cl.scores[fragsort[i]].frags != -666)
575                         {
576                                 // do not add spedcators
577                                 // (ugly hack for nexuiz)
578                                 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
579                         }
580                 }
581
582                 // now sort teams by scores.
583                 for (i=0 ; i<teamlines ; i++)
584                         teamsort[i] = i;
585                 for (i=0 ; i<teamlines ; i++)
586                 {
587                         for (j=0 ; j<teamlines-1-i ; j++)
588                         {
589                                 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
590                                 {
591                                         k = teamsort[j];
592                                         teamsort[j] = teamsort[j+1];
593                                         teamsort[j+1] = k;
594                                 }
595                         }
596                 }
597         }
598 }
599
600 /*
601 ===============
602 Sbar_SoloScoreboard
603 ===============
604 */
605 void Sbar_SoloScoreboard (void)
606 {
607         char    str[80];
608         int             minutes, seconds, tens, units;
609         int             l;
610
611         if (gamemode != GAME_NEXUIZ) {
612                 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
613                 Sbar_DrawString (8, 4, str);
614
615                 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
616                 Sbar_DrawString (8, 12, str);
617         }
618
619 // time
620         minutes = (int)(cl.time / 60);
621         seconds = (int)(cl.time - 60*minutes);
622         tens = seconds / 10;
623         units = seconds - 10*tens;
624         sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
625         Sbar_DrawString (184, 4, str);
626
627 // draw level name
628         if (gamemode == GAME_NEXUIZ) {
629                 l = (int) strlen (cl.worldmodel->name);
630                 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
631         } else {
632                 l = (int) strlen (cl.levelname);
633                 Sbar_DrawString (232 - l*4, 12, cl.levelname);
634         }
635 }
636
637 /*
638 ===============
639 Sbar_DrawScoreboard
640 ===============
641 */
642 void Sbar_DrawScoreboard (void)
643 {
644         Sbar_SoloScoreboard ();
645         if (cl.gametype == GAME_DEATHMATCH)
646                 Sbar_DeathmatchOverlay ();
647 }
648
649 //=============================================================================
650
651 // AK to make DrawInventory smaller
652 static void Sbar_DrawWeapon(int nr, float fade, int active)
653 {
654         // width = 300, height = 100
655         const int w_width = 300, w_height = 100, w_space = 10;
656         const float w_scale = 0.4;
657
658         DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, sb_weapons[0][nr], w_width * w_scale, w_height * w_scale, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 1, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
659         //DrawQ_String(vid_conwidth.integer - (w_space + font_size ), (w_height + w_space) * w_scale * nr + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 0, 0, fade, 0);
660
661         if (active)
662                 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, NULL, w_width * w_scale, w_height * w_scale, 0.3, 0.3, 0.3, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
663 }
664
665 /*
666 ===============
667 Sbar_DrawInventory
668 ===============
669 */
670 void Sbar_DrawInventory (void)
671 {
672         int i;
673         char num[6];
674         float time;
675         int flashon;
676
677         if (gamemode == GAME_ROGUE)
678         {
679                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
680                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
681                 else
682                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
683         }
684         else
685                 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
686
687         // weapons
688         for (i=0 ; i<7 ; i++)
689         {
690                 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
691                 {
692                         time = cl.item_gettime[i];
693                         flashon = (int)((cl.time - time)*10);
694                         if (flashon >= 10)
695                         {
696                                 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i)  )
697                                         flashon = 1;
698                                 else
699                                         flashon = 0;
700                         }
701                         else
702                                 flashon = (flashon%5) + 2;
703
704                         Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
705                 }
706         }
707
708         // MED 01/04/97
709         // hipnotic weapons
710         if (gamemode == GAME_HIPNOTIC)
711         {
712                 int grenadeflashing=0;
713                 for (i=0 ; i<4 ; i++)
714                 {
715                         if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
716                         {
717                                 time = cl.item_gettime[hipweapons[i]];
718                                 flashon = (int)((cl.time - time)*10);
719                                 if (flashon >= 10)
720                                 {
721                                         if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i])  )
722                                                 flashon = 1;
723                                         else
724                                                 flashon = 0;
725                                 }
726                                 else
727                                         flashon = (flashon%5) + 2;
728
729                                 // check grenade launcher
730                                 if (i==2)
731                                 {
732                                         if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
733                                         {
734                                                 if (flashon)
735                                                 {
736                                                         grenadeflashing = 1;
737                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
738                                                 }
739                                         }
740                                 }
741                                 else if (i==3)
742                                 {
743                                         if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
744                                         {
745                                                 if (!grenadeflashing)
746                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
747                                         }
748                                         else
749                                                 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
750                                 }
751                                 else
752                                         Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
753                         }
754                 }
755         }
756
757         if (gamemode == GAME_ROGUE)
758         {
759                 // check for powered up weapon.
760                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
761                         for (i=0;i<5;i++)
762                                 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
763                                         Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
764         }
765
766         // ammo counts
767         for (i=0 ; i<4 ; i++)
768         {
769                 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
770                 if (num[0] != ' ')
771                         Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
772                 if (num[1] != ' ')
773                         Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
774                 if (num[2] != ' ')
775                         Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
776         }
777
778         // items
779         for (i=0 ; i<6 ; i++)
780                 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
781                 {
782                         //MED 01/04/97 changed keys
783                         if (gamemode != GAME_HIPNOTIC || (i>1))
784                                 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
785                 }
786
787         //MED 01/04/97 added hipnotic items
788         // hipnotic items
789         if (gamemode == GAME_HIPNOTIC)
790         {
791                 for (i=0 ; i<2 ; i++)
792                         if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
793                                 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
794         }
795
796         if (gamemode == GAME_ROGUE)
797         {
798                 // new rogue items
799                 for (i=0 ; i<2 ; i++)
800                         if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
801                                 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
802         }
803         else
804         {
805                 // sigils
806                 for (i=0 ; i<4 ; i++)
807                         if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
808                                 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
809         }
810 }
811
812 //=============================================================================
813
814 /*
815 ===============
816 Sbar_DrawFrags
817 ===============
818 */
819 void Sbar_DrawFrags (void)
820 {
821         int i, k, l, x, f;
822         char num[12];
823         scoreboard_t *s;
824         unsigned char *c;
825
826         Sbar_SortFrags ();
827
828         // draw the text
829         l = min(scoreboardlines, 4);
830
831         x = 23 * 8;
832
833         for (i = 0;i < l;i++)
834         {
835                 k = fragsort[i];
836                 s = &cl.scores[k];
837
838                 // draw background
839                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
840                 DrawQ_Pic (sbar_x + x + 10, sbar_y     - 23, NULL, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
841                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
842                 DrawQ_Pic (sbar_x + x + 10, sbar_y + 4 - 23, NULL, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
843
844                 // draw number
845                 f = s->frags;
846                 sprintf (num, "%3i",f);
847
848                 if (k == cl.viewentity - 1)
849                 {
850                         Sbar_DrawCharacter ( x      + 2, -24, 16);
851                         Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
852                 }
853                 Sbar_DrawCharacter (x +  8, -24, num[0]);
854                 Sbar_DrawCharacter (x + 16, -24, num[1]);
855                 Sbar_DrawCharacter (x + 24, -24, num[2]);
856                 x += 32;
857         }
858 }
859
860 //=============================================================================
861
862
863 /*
864 ===============
865 Sbar_DrawFace
866 ===============
867 */
868 void Sbar_DrawFace (void)
869 {
870         int f;
871
872 // PGM 01/19/97 - team color drawing
873 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
874         if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
875         {
876                 char num[12];
877                 scoreboard_t *s;
878                 unsigned char *c;
879
880                 s = &cl.scores[cl.viewentity - 1];
881                 // draw background
882                 Sbar_DrawPic (112, 0, rsb_teambord);
883                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
884                 DrawQ_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, NULL, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
885                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
886                 DrawQ_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, NULL, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
887
888                 // draw number
889                 f = s->frags;
890                 sprintf (num, "%3i",f);
891
892                 if ((s->colors & 0xf0)==0)
893                 {
894                         if (num[0] != ' ')
895                                 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
896                         if (num[1] != ' ')
897                                 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
898                         if (num[2] != ' ')
899                                 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
900                 }
901                 else
902                 {
903                         Sbar_DrawCharacter ( 109, 3, num[0]);
904                         Sbar_DrawCharacter ( 116, 3, num[1]);
905                         Sbar_DrawCharacter ( 123, 3, num[2]);
906                 }
907
908                 return;
909         }
910 // PGM 01/19/97 - team color drawing
911
912         if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
913                 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
914         else if (cl.stats[STAT_ITEMS] & IT_QUAD)
915                 Sbar_DrawPic (112, 0, sb_face_quad );
916         else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
917                 Sbar_DrawPic (112, 0, sb_face_invis );
918         else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
919                 Sbar_DrawPic (112, 0, sb_face_invuln);
920         else
921         {
922                 f = cl.stats[STAT_HEALTH] / 20;
923                 f = bound(0, f, 4);
924                 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
925         }
926 }
927
928 void Sbar_ShowFPS(void)
929 {
930         float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
931         char fpsstring[32];
932         char timestring[32];
933         char datestring[32];
934         qboolean red = false;
935         fpsstring[0] = 0;
936         timestring[0] = 0;
937         datestring[0] = 0;
938         if (showfps.integer)
939         {
940                 float calc;
941                 static double nexttime = 0, lasttime = 0;
942                 static double framerate = 0;
943                 static int framecount = 0;
944                 double newtime;
945                 newtime = Sys_DoubleTime();
946                 if (newtime >= nexttime)
947                 {
948                         framerate = framecount / (newtime - lasttime);
949                         lasttime = newtime;
950                         nexttime = max(nexttime + 1, lasttime - 1);
951                         framecount = 0;
952                 }
953                 framecount++;
954                 calc = framerate;
955
956                 if ((red = (calc < 1.0f)))
957                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
958                 else
959                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
960         }
961         if (showtime.integer)
962                 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
963         if (showdate.integer)
964                 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
965         if (fpsstring[0] || timestring[0])
966         {
967                 fps_scalex = 12;
968                 fps_scaley = 12;
969                 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
970                 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
971                 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
972                 fps_y = vid_conheight.integer - fps_height;
973                 if (fpsstring[0])
974                 {
975                         fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
976                         DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
977                         if (red)
978                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
979                         else
980                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
981                         fps_y += fps_scaley;
982                 }
983                 if (timestring[0])
984                 {
985                         fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
986                         DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
987                         DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
988                         fps_y += fps_scaley;
989                 }
990                 if (datestring[0])
991                 {
992                         fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
993                         DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
994                         DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
995                         fps_y += fps_scaley;
996                 }
997         }
998 }
999
1000 void Sbar_DrawGauge(float x, float y, cachepic_t *pic, float width, float height, float rangey, float rangeheight, float c1, float c2, float c1r, float c1g, float c1b, float c1a, float c2r, float c2g, float c2b, float c2a, float c3r, float c3g, float c3b, float c3a, int drawflags)
1001 {
1002         float r[5];
1003         c2 = bound(0, c2, 1);
1004         c1 = bound(0, c1, 1 - c2);
1005         r[0] = 0;
1006         r[1] = rangey + rangeheight * (c2 + c1);
1007         r[2] = rangey + rangeheight * (c2);
1008         r[3] = rangey;
1009         r[4] = height;
1010         if (r[1] > r[0])
1011                 DrawQ_SuperPic(x, y + r[0], pic, width, (r[1] - r[0]), 0,(r[0] / height), c3r,c3g,c3b,c3a, 1,(r[0] / height), c3r,c3g,c3b,c3a, 0,(r[1] / height), c3r,c3g,c3b,c3a, 1,(r[1] / height), c3r,c3g,c3b,c3a, drawflags);
1012         if (r[2] > r[1])
1013                 DrawQ_SuperPic(x, y + r[1], pic, width, (r[2] - r[1]), 0,(r[1] / height), c1r,c1g,c1b,c1a, 1,(r[1] / height), c1r,c1g,c1b,c1a, 0,(r[2] / height), c1r,c1g,c1b,c1a, 1,(r[2] / height), c1r,c1g,c1b,c1a, drawflags);
1014         if (r[3] > r[2])
1015                 DrawQ_SuperPic(x, y + r[2], pic, width, (r[3] - r[2]), 0,(r[2] / height), c2r,c2g,c2b,c2a, 1,(r[2] / height), c2r,c2g,c2b,c2a, 0,(r[3] / height), c2r,c2g,c2b,c2a, 1,(r[3] / height), c2r,c2g,c2b,c2a, drawflags);
1016         if (r[4] > r[3])
1017                 DrawQ_SuperPic(x, y + r[3], pic, width, (r[4] - r[3]), 0,(r[3] / height), c3r,c3g,c3b,c3a, 1,(r[3] / height), c3r,c3g,c3b,c3a, 0,(r[4] / height), c3r,c3g,c3b,c3a, 1,(r[4] / height), c3r,c3g,c3b,c3a, drawflags);
1018 }
1019
1020 /*
1021 ===============
1022 Sbar_Draw
1023 ===============
1024 */
1025 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1026 extern cvar_t v_kicktime;
1027 void Sbar_Draw (void)
1028 {
1029         cachepic_t *pic;
1030
1031         if(cl.csqc_vidvars.drawenginesbar)      //[515]: csqc drawsbar
1032         {
1033                 if (cl.intermission == 1)
1034                 {
1035                         Sbar_IntermissionOverlay();
1036                         return;
1037                 }
1038                 else if (cl.intermission == 2)
1039                 {
1040                         Sbar_FinaleOverlay();
1041                         return;
1042                 }
1043
1044                 if (gamemode == GAME_NETHERWORLD)
1045                 {
1046                 }
1047                 else if (gamemode == GAME_SOM)
1048                 {
1049                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1050                                 Sbar_DrawScoreboard ();
1051                         else if (sb_lines)
1052                         {
1053                                 // this is the top left of the sbar area
1054                                 sbar_x = 0;
1055                                 sbar_y = vid_conheight.integer - 24*3;
1056
1057                                 // armor
1058                                 if (cl.stats[STAT_ARMOR])
1059                                 {
1060                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1061                                                 Sbar_DrawPic(0, 0, somsb_armor[2]);
1062                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1063                                                 Sbar_DrawPic(0, 0, somsb_armor[1]);
1064                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1065                                                 Sbar_DrawPic(0, 0, somsb_armor[0]);
1066                                         Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1067                                 }
1068
1069                                 // health
1070                                 Sbar_DrawPic(0, 24, somsb_health);
1071                                 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1072
1073                                 // ammo icon
1074                                 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1075                                         Sbar_DrawPic(0, 48, somsb_ammo[0]);
1076                                 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1077                                         Sbar_DrawPic(0, 48, somsb_ammo[1]);
1078                                 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1079                                         Sbar_DrawPic(0, 48, somsb_ammo[2]);
1080                                 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1081                                         Sbar_DrawPic(0, 48, somsb_ammo[3]);
1082                                 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1083                                 if (cl.stats[STAT_SHELLS])
1084                                         Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1085                         }
1086                 }
1087                 else if (gamemode == GAME_NEXUIZ)
1088                 {
1089                         sbar_y = vid_conheight.integer - 47;
1090                         sbar_x = (vid_conwidth.integer - 640)/2;
1091
1092                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1093                         {
1094                                 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1095                                 Sbar_DrawScoreboard ();
1096                         }
1097                         else if (sb_lines)
1098                         {
1099                                 int i;
1100                                 double time;
1101                                 float fade;
1102
1103                                 // we have a max time 2s (min time = 0)
1104                                 if ((time = cl.time - cl.weapontime) < 2)
1105                                 {
1106                                         fade = (1.0 - 0.5 * time);
1107                                         fade *= fade;
1108                                         for (i = 0; i < 8;i++)
1109                                                 if (cl.stats[STAT_ITEMS] & (1 << i))
1110                                                         Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1111
1112                                         if((cl.stats[STAT_ITEMS] & (1<<12)))
1113                                                 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1114                                 }
1115
1116                                 //if (!cl.islocalgame)
1117                                 //      Sbar_DrawFrags ();
1118
1119                                 if (sb_lines > 24)
1120                                         Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1121                                 else
1122                                         Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1123
1124                                 // special items
1125                                 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1126                                 {
1127                                         // Nexuiz has no anum pics
1128                                         //Sbar_DrawNum (36, 0, 666, 3, 1);
1129                                         // Nexuiz has no disc pic
1130                                         //Sbar_DrawPic (0, 0, sb_disc);
1131                                 }
1132
1133                                 // armor
1134                                 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1135
1136                                 // health
1137                                 if(cl.stats[STAT_HEALTH] > 100)
1138                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1139                                 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1140                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1141                                 else
1142                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1143
1144                                 // AK dont draw ammo for the laser
1145                                 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1146                                 {
1147                                         if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1148                                                 Sbar_DrawPic (519, 0, sb_ammo[0]);
1149                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1150                                                 Sbar_DrawPic (519, 0, sb_ammo[1]);
1151                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1152                                                 Sbar_DrawPic (519, 0, sb_ammo[2]);
1153                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1154                                                 Sbar_DrawPic (519, 0, sb_ammo[3]);
1155
1156                                         if(cl.stats[STAT_AMMO] <= 10)
1157                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1158                                         else
1159                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1160
1161                                 }
1162
1163                                 if (sb_lines > 24)
1164                                         DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1165                         }
1166
1167                         //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1168                         //      Sbar_MiniDeathmatchOverlay (0, 17);
1169                 }
1170                 else if (gamemode == GAME_ZYMOTIC)
1171                 {
1172 #if 1
1173                         float scale = 64.0f / 256.0f;
1174                         float kickoffset[3];
1175                         VectorClear(kickoffset);
1176                         if (v_dmg_time > 0)
1177                         {
1178                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1179                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1180                         }
1181                         sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1182                         sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1183                         // left1 16, 48 : 126 -66
1184                         // left2 16, 128 : 196 -66
1185                         // right 176, 48 : 196 -136
1186                         Sbar_DrawGauge(sbar_x +  16 * scale, sbar_y +  48 * scale, zymsb_crosshair_left1, 64*scale,  80*scale, 78*scale,  -66*scale, cl.stats[STAT_AMMO]  * (1.0 / 200.0), cl.stats[STAT_SHELLS]  * (1.0 / 200.0), 0.8f,0.8f,0.0f,1.0f, 0.8f,0.5f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1187                         Sbar_DrawGauge(sbar_x +  16 * scale, sbar_y + 128 * scale, zymsb_crosshair_left2, 64*scale,  80*scale, 68*scale,  -66*scale, cl.stats[STAT_NAILS] * (1.0 / 200.0), cl.stats[STAT_ROCKETS] * (1.0 / 200.0), 0.8f,0.8f,0.0f,1.0f, 0.8f,0.5f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1188                         Sbar_DrawGauge(sbar_x + 176 * scale, sbar_y +  48 * scale, zymsb_crosshair_right, 64*scale, 160*scale, 148*scale, -136*scale, cl.stats[STAT_ARMOR]  * (1.0 / 300.0), cl.stats[STAT_HEALTH]  * (1.0 / 300.0), 0.0f,0.5f,1.0f,1.0f, 1.0f,0.0f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1189                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1190 #else
1191                         float scale = 128.0f / 256.0f;
1192                         float healthstart, healthheight, healthstarttc, healthendtc;
1193                         float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1194                         float ammostart, ammoheight, ammostarttc, ammoendtc;
1195                         float clipstart, clipheight, clipstarttc, clipendtc;
1196                         float kickoffset[3], offset;
1197                         VectorClear(kickoffset);
1198                         if (v_dmg_time > 0)
1199                         {
1200                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1201                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1202                         }
1203                         sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1204                         sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1205                         offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1206                         DrawQ_SuperPic(sbar_x +  120           * scale, sbar_y + ( 88 - offset) * scale, zymsb_crosshair_line, 16 * scale, 36 * scale, 0,0, 1,1,1,1, 1,0, 1,1,1,1, 0,1, 1,1,1,1, 1,1, 1,1,1,1, 0);
1207                         DrawQ_SuperPic(sbar_x + (132 + offset) * scale, sbar_y + 120            * scale, zymsb_crosshair_line, 36 * scale, 16 * scale, 0,1, 1,1,1,1, 0,0, 1,1,1,1, 1,1, 1,1,1,1, 1,0, 1,1,1,1, 0);
1208                         DrawQ_SuperPic(sbar_x +  120           * scale, sbar_y + (132 + offset) * scale, zymsb_crosshair_line, 16 * scale, 36 * scale, 1,1, 1,1,1,1, 0,1, 1,1,1,1, 1,0, 1,1,1,1, 0,0, 1,1,1,1, 0);
1209                         DrawQ_SuperPic(sbar_x + ( 88 - offset) * scale, sbar_y + 120            * scale, zymsb_crosshair_line, 36 * scale, 16 * scale, 1,0, 1,1,1,1, 1,1, 1,1,1,1, 0,0, 1,1,1,1, 0,1, 1,1,1,1, 0);
1210                         healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1211                         shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1212                         healthstart = 204 - healthheight;
1213                         shieldstart = healthstart - shieldheight;
1214                         healthstarttc = healthstart * (1.0f / 256.0f);
1215                         healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1216                         shieldstarttc = shieldstart * (1.0f / 256.0f);
1217                         shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1218                         ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1219                         ammostart = 114 - ammoheight;
1220                         ammostarttc = ammostart * (1.0f / 256.0f);
1221                         ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1222                         clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1223                         clipstart = 190 - clipheight;
1224                         clipstarttc = clipstart * (1.0f / 256.0f);
1225                         clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1226                         if (healthheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + healthstart * scale, zymsb_crosshair_health, 256 * scale, healthheight * scale, 0,healthstarttc, 1.0f,0.0f,0.0f,1.0f, 1,healthstarttc, 1.0f,0.0f,0.0f,1.0f, 0,healthendtc, 1.0f,0.0f,0.0f,1.0f, 1,healthendtc, 1.0f,0.0f,0.0f,1.0f, DRAWFLAG_NORMAL);
1227                         if (shieldheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + shieldstart * scale, zymsb_crosshair_health, 256 * scale, shieldheight * scale, 0,shieldstarttc, 0.0f,0.5f,1.0f,1.0f, 1,shieldstarttc, 0.0f,0.5f,1.0f,1.0f, 0,shieldendtc, 0.0f,0.5f,1.0f,1.0f, 1,shieldendtc, 0.0f,0.5f,1.0f,1.0f, DRAWFLAG_NORMAL);
1228                         if (ammoheight > 0)   DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + ammostart   * scale, zymsb_crosshair_ammo,   256 * scale, ammoheight   * scale, 0,ammostarttc,   0.8f,0.8f,0.0f,1.0f, 1,ammostarttc,   0.8f,0.8f,0.0f,1.0f, 0,ammoendtc,   0.8f,0.8f,0.0f,1.0f, 1,ammoendtc,   0.8f,0.8f,0.0f,1.0f, DRAWFLAG_NORMAL);
1229                         if (clipheight > 0)   DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + clipstart   * scale, zymsb_crosshair_clip,   256 * scale, clipheight   * scale, 0,clipstarttc,   1.0f,1.0f,0.0f,1.0f, 1,clipstarttc,   1.0f,1.0f,0.0f,1.0f, 0,clipendtc,   1.0f,1.0f,0.0f,1.0f, 1,clipendtc,   1.0f,1.0f,0.0f,1.0f, DRAWFLAG_NORMAL);
1230                         DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1231                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1232 #endif
1233                 }
1234                 else // Quake and others
1235                 {
1236                         sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1237                         if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1238                                 sbar_x = 0;
1239                         else
1240                                 sbar_x = (vid_conwidth.integer - 320)/2;
1241
1242                         if (sb_lines > 24)
1243                         {
1244                                 if (gamemode != GAME_GOODVSBAD2)
1245                                         Sbar_DrawInventory ();
1246                                 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1247                                         Sbar_DrawFrags ();
1248                         }
1249
1250                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1251                         {
1252                                 if (gamemode != GAME_GOODVSBAD2)
1253                                         Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1254                                 Sbar_DrawScoreboard ();
1255                         }
1256                         else if (sb_lines)
1257                         {
1258                                 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1259
1260                                 // keys (hipnotic only)
1261                                 //MED 01/04/97 moved keys here so they would not be overwritten
1262                                 if (gamemode == GAME_HIPNOTIC)
1263                                 {
1264                                         if (cl.stats[STAT_ITEMS] & IT_KEY1)
1265                                                 Sbar_DrawPic (209, 3, sb_items[0]);
1266                                         if (cl.stats[STAT_ITEMS] & IT_KEY2)
1267                                                 Sbar_DrawPic (209, 12, sb_items[1]);
1268                                 }
1269                                 // armor
1270                                 if (gamemode != GAME_GOODVSBAD2)
1271                                 {
1272                                         if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1273                                         {
1274                                                 Sbar_DrawNum (24, 0, 666, 3, 1);
1275                                                 Sbar_DrawPic (0, 0, sb_disc);
1276                                         }
1277                                         else
1278                                         {
1279                                                 if (gamemode == GAME_ROGUE)
1280                                                 {
1281                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1282                                                         if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1283                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1284                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1285                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1286                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1287                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1288                                                 }
1289                                                 else
1290                                                 {
1291                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1292                                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1293                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1294                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1295                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1296                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1297                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1298                                                 }
1299                                         }
1300                                 }
1301
1302                                 // face
1303                                 Sbar_DrawFace ();
1304
1305                                 // health
1306                                 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1307
1308                                 // ammo icon
1309                                 if (gamemode == GAME_ROGUE)
1310                                 {
1311                                         if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1312                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1313                                         else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1314                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1315                                         else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1316                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1317                                         else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1318                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1319                                         else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1320                                                 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1321                                         else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1322                                                 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1323                                         else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1324                                                 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1325                                 }
1326                                 else
1327                                 {
1328                                         if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1329                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1330                                         else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1331                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1332                                         else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1333                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1334                                         else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1335                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1336                                 }
1337
1338                                 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1339
1340                         }
1341
1342                         if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1343                         {
1344                                 if (gamemode == GAME_TRANSFUSION)
1345                                         Sbar_MiniDeathmatchOverlay (0, 0);
1346                                 else
1347                                         Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1348                         }
1349                 }
1350         }
1351
1352         Sbar_ShowFPS();
1353
1354         if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1355                 DrawQ_Pic((vid_conwidth.integer - pic->width * crosshair_size.value) * 0.5f, (vid_conheight.integer - pic->height * crosshair_size.value) * 0.5f, pic, pic->width * crosshair_size.value, pic->height * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0);
1356
1357         if (cl_prydoncursor.integer)
1358                 DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic(va("gfx/prydoncursor%03i", cl_prydoncursor.integer), true), 0, 0, 1, 1, 1, 1, 0);
1359 }
1360
1361 //=============================================================================
1362
1363 /*
1364 ==================
1365 Sbar_DeathmatchOverlay
1366
1367 ==================
1368 */
1369 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1370 {
1371         int minutes;
1372         unsigned char *c;
1373         minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1374         if (s->qw_spectator)
1375         {
1376                 if (s->qw_ping || s->qw_packetloss)
1377                         DrawQ_ColoredString(x, y, va("%4i %3i %4i spect %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1378                 else
1379                         DrawQ_ColoredString(x, y, va("         %4i spect %-4s %c%s", minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1380         }
1381         else
1382         {
1383                 // draw colors behind score
1384                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1385                 DrawQ_Pic(x + 14*8, y+1, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1386                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1387                 DrawQ_Pic(x + 14*8, y+4, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1388                 // print the text
1389                 //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1390                 if (s->qw_ping || s->qw_packetloss)
1391                         DrawQ_ColoredString(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1392                 else
1393                         DrawQ_ColoredString(x, y, va("         %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1394         }
1395         return 8;
1396 }
1397
1398 void Sbar_DeathmatchOverlay (void)
1399 {
1400         int i, x, y;
1401
1402         // request new ping times every two second
1403         if (cl.last_ping_request < realtime - 2 && cls.netcon)
1404         {
1405                 cl.last_ping_request = realtime;
1406                 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1407                 {
1408                         MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1409                         MSG_WriteString(&cls.netcon->message, "pings");
1410                 }
1411                 else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6 || cls.protocol == PROTOCOL_DARKPLACES7)
1412                 {
1413                         // these servers usually lack the pings command and so a less efficient "ping" command must be sent, which on modern DP servers will also reply with a pingplreport command after the ping listing
1414                         cl.parsingtextexpectingpingforscores = true; // hide the output of the next ping report
1415                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1416                         MSG_WriteString(&cls.netcon->message, "ping");
1417                 }
1418                 else
1419                 {
1420                         // newer server definitely has pings command, so use it for more efficiency
1421                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1422                         MSG_WriteString(&cls.netcon->message, "pings");
1423                 }
1424         }
1425
1426         DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1427
1428         // scores
1429         Sbar_SortFrags ();
1430         // draw the text
1431         x = (vid_conwidth.integer - (6 + 18 + 15) * 8) / 2;
1432         y = 40;
1433         DrawQ_ColoredString(x, y, va("ping pl%% time frags team  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1434         y += 8;
1435
1436         if (Sbar_IsTeammatch ())
1437         {
1438                 // show team scores first
1439                 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1440                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1441                 y += 5;
1442         }
1443
1444         for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1445                 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1446 }
1447
1448 /*
1449 ==================
1450 Sbar_DeathmatchOverlay
1451
1452 ==================
1453 */
1454 void Sbar_MiniDeathmatchOverlay (int x, int y)
1455 {
1456         int i, numlines;
1457
1458         // decide where to print
1459         if (gamemode == GAME_TRANSFUSION)
1460                 numlines = (vid_conwidth.integer - x + 127) / 128;
1461         else
1462                 numlines = (vid_conheight.integer - y + 7) / 8;
1463
1464         // give up if there isn't room
1465         if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1466                 return;
1467
1468         // scores
1469         Sbar_SortFrags ();
1470
1471         //find us
1472         for (i = 0; i < scoreboardlines; i++)
1473                 if (fragsort[i] == cl.playerentity - 1)
1474                         break;
1475
1476         // figure out start
1477         i -= numlines/2;
1478         i = min(i, scoreboardlines - numlines);
1479         i = max(i, 0);
1480
1481         if (gamemode == GAME_TRANSFUSION)
1482         {
1483                 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1484                         x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1485         }
1486         else
1487         {
1488                 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1489                         y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1490         }
1491 }
1492
1493 /*
1494 ==================
1495 Sbar_IntermissionOverlay
1496
1497 ==================
1498 */
1499 void Sbar_IntermissionOverlay (void)
1500 {
1501         int             dig;
1502         int             num;
1503
1504         if (cl.gametype == GAME_DEATHMATCH)
1505         {
1506                 Sbar_DeathmatchOverlay ();
1507                 return;
1508         }
1509
1510         sbar_x = (vid_conwidth.integer - 320) >> 1;
1511         sbar_y = (vid_conheight.integer - 200) >> 1;
1512
1513         DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1514         DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1515
1516 // time
1517         dig = (int)cl.completed_time / 60;
1518         Sbar_DrawNum (160, 64, dig, 3, 0);
1519         num = (int)cl.completed_time - dig*60;
1520         if (gamemode != GAME_NEXUIZ)
1521                 Sbar_DrawPic (234,64,sb_colon);
1522         Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1523         Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1524
1525         Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1526         if (gamemode != GAME_NEXUIZ)
1527                 Sbar_DrawPic (232, 104, sb_slash);
1528         Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1529
1530         Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1531         if (gamemode != GAME_NEXUIZ)
1532                 Sbar_DrawPic (232, 144, sb_slash);
1533         Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1534
1535 }
1536
1537
1538 /*
1539 ==================
1540 Sbar_FinaleOverlay
1541
1542 ==================
1543 */
1544 void Sbar_FinaleOverlay (void)
1545 {
1546         DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1547 }
1548