Removed all calls to strcpy; most of them are now calls to strlcpy or memcpy.
[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                                 const char* teamname;
557
558                                 color = cl.scores[fragsort[i]].colors & 15;
559                                 teamlines++;
560
561                                 switch (color)
562                                 {
563                                         case 4:
564                                                 teamname = "^1Red Team";
565                                                 break;
566                                         case 13:
567                                                 teamname = "^4Blue Team";
568                                                 break;
569                                         case 9:
570                                                 teamname = "^6Pink Team";
571                                                 break;
572                                         case 12:
573                                                 teamname = "^3Yellow Team";
574                                                 break;
575                                         default:
576                                                 teamname = "Total Team Score";
577                                                 break;
578                                 }
579                                 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
580
581                                 teams[teamlines-1].frags = 0;
582                                 teams[teamlines-1].colors = color + 16 * color;
583                         }
584
585                         if (cl.scores[fragsort[i]].frags != -666)
586                         {
587                                 // do not add spedcators
588                                 // (ugly hack for nexuiz)
589                                 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
590                         }
591                 }
592
593                 // now sort teams by scores.
594                 for (i=0 ; i<teamlines ; i++)
595                         teamsort[i] = i;
596                 for (i=0 ; i<teamlines ; i++)
597                 {
598                         for (j=0 ; j<teamlines-1-i ; j++)
599                         {
600                                 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
601                                 {
602                                         k = teamsort[j];
603                                         teamsort[j] = teamsort[j+1];
604                                         teamsort[j+1] = k;
605                                 }
606                         }
607                 }
608         }
609 }
610
611 /*
612 ===============
613 Sbar_SoloScoreboard
614 ===============
615 */
616 void Sbar_SoloScoreboard (void)
617 {
618         char    str[80];
619         int             minutes, seconds, tens, units;
620         int             l;
621
622         if (gamemode != GAME_NEXUIZ) {
623                 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
624                 Sbar_DrawString (8, 4, str);
625
626                 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
627                 Sbar_DrawString (8, 12, str);
628         }
629
630 // time
631         minutes = (int)(cl.time / 60);
632         seconds = (int)(cl.time - 60*minutes);
633         tens = seconds / 10;
634         units = seconds - 10*tens;
635         sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
636         Sbar_DrawString (184, 4, str);
637
638 // draw level name
639         if (gamemode == GAME_NEXUIZ) {
640                 l = (int) strlen (cl.worldmodel->name);
641                 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
642         } else {
643                 l = (int) strlen (cl.levelname);
644                 Sbar_DrawString (232 - l*4, 12, cl.levelname);
645         }
646 }
647
648 /*
649 ===============
650 Sbar_DrawScoreboard
651 ===============
652 */
653 void Sbar_DrawScoreboard (void)
654 {
655         Sbar_SoloScoreboard ();
656         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
657         //if (cl.gametype == GAME_DEATHMATCH)
658         if (!cl.islocalgame)
659                 Sbar_DeathmatchOverlay ();
660 }
661
662 //=============================================================================
663
664 // AK to make DrawInventory smaller
665 static void Sbar_DrawWeapon(int nr, float fade, int active)
666 {
667         // width = 300, height = 100
668         const int w_width = 300, w_height = 100, w_space = 10;
669         const float w_scale = 0.4;
670
671         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);
672         //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);
673
674         if (active)
675                 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);
676 }
677
678 /*
679 ===============
680 Sbar_DrawInventory
681 ===============
682 */
683 void Sbar_DrawInventory (void)
684 {
685         int i;
686         char num[6];
687         float time;
688         int flashon;
689
690         if (gamemode == GAME_ROGUE)
691         {
692                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
693                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
694                 else
695                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
696         }
697         else
698                 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
699
700         // weapons
701         for (i=0 ; i<7 ; i++)
702         {
703                 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
704                 {
705                         time = cl.item_gettime[i];
706                         flashon = (int)((cl.time - time)*10);
707                         if (flashon >= 10)
708                         {
709                                 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i)  )
710                                         flashon = 1;
711                                 else
712                                         flashon = 0;
713                         }
714                         else
715                                 flashon = (flashon%5) + 2;
716
717                         Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
718                 }
719         }
720
721         // MED 01/04/97
722         // hipnotic weapons
723         if (gamemode == GAME_HIPNOTIC)
724         {
725                 int grenadeflashing=0;
726                 for (i=0 ; i<4 ; i++)
727                 {
728                         if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
729                         {
730                                 time = cl.item_gettime[hipweapons[i]];
731                                 flashon = (int)((cl.time - time)*10);
732                                 if (flashon >= 10)
733                                 {
734                                         if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i])  )
735                                                 flashon = 1;
736                                         else
737                                                 flashon = 0;
738                                 }
739                                 else
740                                         flashon = (flashon%5) + 2;
741
742                                 // check grenade launcher
743                                 if (i==2)
744                                 {
745                                         if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
746                                         {
747                                                 if (flashon)
748                                                 {
749                                                         grenadeflashing = 1;
750                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
751                                                 }
752                                         }
753                                 }
754                                 else if (i==3)
755                                 {
756                                         if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
757                                         {
758                                                 if (!grenadeflashing)
759                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
760                                         }
761                                         else
762                                                 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
763                                 }
764                                 else
765                                         Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
766                         }
767                 }
768         }
769
770         if (gamemode == GAME_ROGUE)
771         {
772                 // check for powered up weapon.
773                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
774                         for (i=0;i<5;i++)
775                                 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
776                                         Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
777         }
778
779         // ammo counts
780         for (i=0 ; i<4 ; i++)
781         {
782                 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
783                 if (num[0] != ' ')
784                         Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
785                 if (num[1] != ' ')
786                         Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
787                 if (num[2] != ' ')
788                         Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
789         }
790
791         // items
792         for (i=0 ; i<6 ; i++)
793                 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
794                 {
795                         //MED 01/04/97 changed keys
796                         if (gamemode != GAME_HIPNOTIC || (i>1))
797                                 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
798                 }
799
800         //MED 01/04/97 added hipnotic items
801         // hipnotic items
802         if (gamemode == GAME_HIPNOTIC)
803         {
804                 for (i=0 ; i<2 ; i++)
805                         if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
806                                 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
807         }
808
809         if (gamemode == GAME_ROGUE)
810         {
811                 // new rogue items
812                 for (i=0 ; i<2 ; i++)
813                         if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
814                                 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
815         }
816         else
817         {
818                 // sigils
819                 for (i=0 ; i<4 ; i++)
820                         if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
821                                 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
822         }
823 }
824
825 //=============================================================================
826
827 /*
828 ===============
829 Sbar_DrawFrags
830 ===============
831 */
832 void Sbar_DrawFrags (void)
833 {
834         int i, k, l, x, f;
835         char num[12];
836         scoreboard_t *s;
837         unsigned char *c;
838
839         Sbar_SortFrags ();
840
841         // draw the text
842         l = min(scoreboardlines, 4);
843
844         x = 23 * 8;
845
846         for (i = 0;i < l;i++)
847         {
848                 k = fragsort[i];
849                 s = &cl.scores[k];
850
851                 // draw background
852                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
853                 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);
854                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
855                 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);
856
857                 // draw number
858                 f = s->frags;
859                 sprintf (num, "%3i",f);
860
861                 if (k == cl.viewentity - 1)
862                 {
863                         Sbar_DrawCharacter ( x      + 2, -24, 16);
864                         Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
865                 }
866                 Sbar_DrawCharacter (x +  8, -24, num[0]);
867                 Sbar_DrawCharacter (x + 16, -24, num[1]);
868                 Sbar_DrawCharacter (x + 24, -24, num[2]);
869                 x += 32;
870         }
871 }
872
873 //=============================================================================
874
875
876 /*
877 ===============
878 Sbar_DrawFace
879 ===============
880 */
881 void Sbar_DrawFace (void)
882 {
883         int f;
884
885 // PGM 01/19/97 - team color drawing
886 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
887         if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
888         {
889                 char num[12];
890                 scoreboard_t *s;
891                 unsigned char *c;
892
893                 s = &cl.scores[cl.viewentity - 1];
894                 // draw background
895                 Sbar_DrawPic (112, 0, rsb_teambord);
896                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
897                 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);
898                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
899                 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);
900
901                 // draw number
902                 f = s->frags;
903                 sprintf (num, "%3i",f);
904
905                 if ((s->colors & 0xf0)==0)
906                 {
907                         if (num[0] != ' ')
908                                 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
909                         if (num[1] != ' ')
910                                 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
911                         if (num[2] != ' ')
912                                 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
913                 }
914                 else
915                 {
916                         Sbar_DrawCharacter ( 109, 3, num[0]);
917                         Sbar_DrawCharacter ( 116, 3, num[1]);
918                         Sbar_DrawCharacter ( 123, 3, num[2]);
919                 }
920
921                 return;
922         }
923 // PGM 01/19/97 - team color drawing
924
925         if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
926                 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
927         else if (cl.stats[STAT_ITEMS] & IT_QUAD)
928                 Sbar_DrawPic (112, 0, sb_face_quad );
929         else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
930                 Sbar_DrawPic (112, 0, sb_face_invis );
931         else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
932                 Sbar_DrawPic (112, 0, sb_face_invuln);
933         else
934         {
935                 f = cl.stats[STAT_HEALTH] / 20;
936                 f = bound(0, f, 4);
937                 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
938         }
939 }
940
941 void Sbar_ShowFPS(void)
942 {
943         float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
944         char fpsstring[32];
945         char timestring[32];
946         char datestring[32];
947         qboolean red = false;
948         fpsstring[0] = 0;
949         timestring[0] = 0;
950         datestring[0] = 0;
951         if (showfps.integer)
952         {
953                 float calc;
954                 static double nexttime = 0, lasttime = 0;
955                 static double framerate = 0;
956                 static int framecount = 0;
957                 double newtime;
958                 newtime = Sys_DoubleTime();
959                 if (newtime >= nexttime)
960                 {
961                         framerate = framecount / (newtime - lasttime);
962                         lasttime = newtime;
963                         nexttime = max(nexttime + 1, lasttime - 1);
964                         framecount = 0;
965                 }
966                 framecount++;
967                 calc = framerate;
968
969                 if ((red = (calc < 1.0f)))
970                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
971                 else
972                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
973         }
974         if (showtime.integer)
975                 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
976         if (showdate.integer)
977                 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
978         if (fpsstring[0] || timestring[0])
979         {
980                 fps_scalex = 12;
981                 fps_scaley = 12;
982                 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
983                 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
984                 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
985                 fps_y = vid_conheight.integer - fps_height;
986                 if (fpsstring[0])
987                 {
988                         fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
989                         DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
990                         if (red)
991                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
992                         else
993                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
994                         fps_y += fps_scaley;
995                 }
996                 if (timestring[0])
997                 {
998                         fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
999                         DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1000                         DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1001                         fps_y += fps_scaley;
1002                 }
1003                 if (datestring[0])
1004                 {
1005                         fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1006                         DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1007                         DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1008                         fps_y += fps_scaley;
1009                 }
1010         }
1011 }
1012
1013 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)
1014 {
1015         float r[5];
1016         c2 = bound(0, c2, 1);
1017         c1 = bound(0, c1, 1 - c2);
1018         r[0] = 0;
1019         r[1] = rangey + rangeheight * (c2 + c1);
1020         r[2] = rangey + rangeheight * (c2);
1021         r[3] = rangey;
1022         r[4] = height;
1023         if (r[1] > r[0])
1024                 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);
1025         if (r[2] > r[1])
1026                 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);
1027         if (r[3] > r[2])
1028                 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);
1029         if (r[4] > r[3])
1030                 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);
1031 }
1032
1033 /*
1034 ===============
1035 Sbar_Draw
1036 ===============
1037 */
1038 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1039 extern cvar_t v_kicktime;
1040 void Sbar_Draw (void)
1041 {
1042         cachepic_t *pic;
1043
1044         if(cl.csqc_vidvars.drawenginesbar)      //[515]: csqc drawsbar
1045         {
1046                 if (cl.intermission == 1)
1047                 {
1048                         Sbar_IntermissionOverlay();
1049                         return;
1050                 }
1051                 else if (cl.intermission == 2)
1052                 {
1053                         Sbar_FinaleOverlay();
1054                         return;
1055                 }
1056
1057                 if (gamemode == GAME_NETHERWORLD)
1058                 {
1059                 }
1060                 else if (gamemode == GAME_SOM)
1061                 {
1062                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1063                                 Sbar_DrawScoreboard ();
1064                         else if (sb_lines)
1065                         {
1066                                 // this is the top left of the sbar area
1067                                 sbar_x = 0;
1068                                 sbar_y = vid_conheight.integer - 24*3;
1069
1070                                 // armor
1071                                 if (cl.stats[STAT_ARMOR])
1072                                 {
1073                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1074                                                 Sbar_DrawPic(0, 0, somsb_armor[2]);
1075                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1076                                                 Sbar_DrawPic(0, 0, somsb_armor[1]);
1077                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1078                                                 Sbar_DrawPic(0, 0, somsb_armor[0]);
1079                                         Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1080                                 }
1081
1082                                 // health
1083                                 Sbar_DrawPic(0, 24, somsb_health);
1084                                 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1085
1086                                 // ammo icon
1087                                 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1088                                         Sbar_DrawPic(0, 48, somsb_ammo[0]);
1089                                 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1090                                         Sbar_DrawPic(0, 48, somsb_ammo[1]);
1091                                 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1092                                         Sbar_DrawPic(0, 48, somsb_ammo[2]);
1093                                 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1094                                         Sbar_DrawPic(0, 48, somsb_ammo[3]);
1095                                 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1096                                 if (cl.stats[STAT_SHELLS])
1097                                         Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1098                         }
1099                 }
1100                 else if (gamemode == GAME_NEXUIZ)
1101                 {
1102                         sbar_y = vid_conheight.integer - 47;
1103                         sbar_x = (vid_conwidth.integer - 640)/2;
1104
1105                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1106                         {
1107                                 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1108                                 Sbar_DrawScoreboard ();
1109                         }
1110                         else if (sb_lines)
1111                         {
1112                                 int i;
1113                                 double time;
1114                                 float fade;
1115
1116                                 // we have a max time 2s (min time = 0)
1117                                 if ((time = cl.time - cl.weapontime) < 2)
1118                                 {
1119                                         fade = (1.0 - 0.5 * time);
1120                                         fade *= fade;
1121                                         for (i = 0; i < 8;i++)
1122                                                 if (cl.stats[STAT_ITEMS] & (1 << i))
1123                                                         Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1124
1125                                         if((cl.stats[STAT_ITEMS] & (1<<12)))
1126                                                 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1127                                 }
1128
1129                                 //if (!cl.islocalgame)
1130                                 //      Sbar_DrawFrags ();
1131
1132                                 if (sb_lines > 24)
1133                                         Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1134                                 else
1135                                         Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1136
1137                                 // special items
1138                                 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1139                                 {
1140                                         // Nexuiz has no anum pics
1141                                         //Sbar_DrawNum (36, 0, 666, 3, 1);
1142                                         // Nexuiz has no disc pic
1143                                         //Sbar_DrawPic (0, 0, sb_disc);
1144                                 }
1145
1146                                 // armor
1147                                 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1148
1149                                 // health
1150                                 if(cl.stats[STAT_HEALTH] > 100)
1151                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1152                                 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1153                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1154                                 else
1155                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1156
1157                                 // AK dont draw ammo for the laser
1158                                 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1159                                 {
1160                                         if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1161                                                 Sbar_DrawPic (519, 0, sb_ammo[0]);
1162                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1163                                                 Sbar_DrawPic (519, 0, sb_ammo[1]);
1164                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1165                                                 Sbar_DrawPic (519, 0, sb_ammo[2]);
1166                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1167                                                 Sbar_DrawPic (519, 0, sb_ammo[3]);
1168
1169                                         if(cl.stats[STAT_AMMO] <= 10)
1170                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1171                                         else
1172                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1173
1174                                 }
1175
1176                                 if (sb_lines > 24)
1177                                         DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1178                         }
1179
1180                         //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1181                         //      Sbar_MiniDeathmatchOverlay (0, 17);
1182                 }
1183                 else if (gamemode == GAME_ZYMOTIC)
1184                 {
1185 #if 1
1186                         float scale = 64.0f / 256.0f;
1187                         float kickoffset[3];
1188                         VectorClear(kickoffset);
1189                         if (v_dmg_time > 0)
1190                         {
1191                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1192                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1193                         }
1194                         sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1195                         sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1196                         // left1 16, 48 : 126 -66
1197                         // left2 16, 128 : 196 -66
1198                         // right 176, 48 : 196 -136
1199                         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);
1200                         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);
1201                         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);
1202                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1203 #else
1204                         float scale = 128.0f / 256.0f;
1205                         float healthstart, healthheight, healthstarttc, healthendtc;
1206                         float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1207                         float ammostart, ammoheight, ammostarttc, ammoendtc;
1208                         float clipstart, clipheight, clipstarttc, clipendtc;
1209                         float kickoffset[3], offset;
1210                         VectorClear(kickoffset);
1211                         if (v_dmg_time > 0)
1212                         {
1213                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1214                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1215                         }
1216                         sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1217                         sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1218                         offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1219                         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);
1220                         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);
1221                         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);
1222                         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);
1223                         healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1224                         shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1225                         healthstart = 204 - healthheight;
1226                         shieldstart = healthstart - shieldheight;
1227                         healthstarttc = healthstart * (1.0f / 256.0f);
1228                         healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1229                         shieldstarttc = shieldstart * (1.0f / 256.0f);
1230                         shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1231                         ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1232                         ammostart = 114 - ammoheight;
1233                         ammostarttc = ammostart * (1.0f / 256.0f);
1234                         ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1235                         clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1236                         clipstart = 190 - clipheight;
1237                         clipstarttc = clipstart * (1.0f / 256.0f);
1238                         clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1239                         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);
1240                         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);
1241                         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);
1242                         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);
1243                         DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1244                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1245 #endif
1246                 }
1247                 else // Quake and others
1248                 {
1249                         sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1250                         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1251                         //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1252                         if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1253                                 sbar_x = 0;
1254                         else
1255                                 sbar_x = (vid_conwidth.integer - 320)/2;
1256
1257                         if (sb_lines > 24)
1258                         {
1259                                 if (gamemode != GAME_GOODVSBAD2)
1260                                         Sbar_DrawInventory ();
1261                                 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1262                                         Sbar_DrawFrags ();
1263                         }
1264
1265                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1266                         {
1267                                 if (gamemode != GAME_GOODVSBAD2)
1268                                         Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1269                                 Sbar_DrawScoreboard ();
1270                         }
1271                         else if (sb_lines)
1272                         {
1273                                 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1274
1275                                 // keys (hipnotic only)
1276                                 //MED 01/04/97 moved keys here so they would not be overwritten
1277                                 if (gamemode == GAME_HIPNOTIC)
1278                                 {
1279                                         if (cl.stats[STAT_ITEMS] & IT_KEY1)
1280                                                 Sbar_DrawPic (209, 3, sb_items[0]);
1281                                         if (cl.stats[STAT_ITEMS] & IT_KEY2)
1282                                                 Sbar_DrawPic (209, 12, sb_items[1]);
1283                                 }
1284                                 // armor
1285                                 if (gamemode != GAME_GOODVSBAD2)
1286                                 {
1287                                         if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1288                                         {
1289                                                 Sbar_DrawNum (24, 0, 666, 3, 1);
1290                                                 Sbar_DrawPic (0, 0, sb_disc);
1291                                         }
1292                                         else
1293                                         {
1294                                                 if (gamemode == GAME_ROGUE)
1295                                                 {
1296                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1297                                                         if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1298                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1299                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1300                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1301                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1302                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1303                                                 }
1304                                                 else
1305                                                 {
1306                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1307                                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1308                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1309                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1310                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1311                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1312                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1313                                                 }
1314                                         }
1315                                 }
1316
1317                                 // face
1318                                 Sbar_DrawFace ();
1319
1320                                 // health
1321                                 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1322
1323                                 // ammo icon
1324                                 if (gamemode == GAME_ROGUE)
1325                                 {
1326                                         if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1327                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1328                                         else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1329                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1330                                         else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1331                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1332                                         else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1333                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1334                                         else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1335                                                 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1336                                         else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1337                                                 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1338                                         else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1339                                                 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1340                                 }
1341                                 else
1342                                 {
1343                                         if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1344                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1345                                         else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1346                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1347                                         else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1348                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1349                                         else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1350                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1351                                 }
1352
1353                                 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1354
1355                         }
1356
1357                         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1358                         //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1359                         if (!cl.islocalgame && vid_conwidth.integer > 320)
1360                         {
1361                                 if (gamemode == GAME_TRANSFUSION)
1362                                         Sbar_MiniDeathmatchOverlay (0, 0);
1363                                 else
1364                                         Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1365                         }
1366                 }
1367         }
1368
1369         Sbar_ShowFPS();
1370
1371         if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1372                 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);
1373
1374         if (cl_prydoncursor.integer)
1375                 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);
1376 }
1377
1378 //=============================================================================
1379
1380 /*
1381 ==================
1382 Sbar_DeathmatchOverlay
1383
1384 ==================
1385 */
1386 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1387 {
1388         int minutes;
1389         unsigned char *c;
1390         minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1391         if (s->qw_spectator)
1392         {
1393                 if (s->qw_ping || s->qw_packetloss)
1394                         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 );
1395                 else
1396                         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 );
1397         }
1398         else
1399         {
1400                 // draw colors behind score
1401                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1402                 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);
1403                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1404                 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);
1405                 // print the text
1406                 //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);
1407                 if (s->qw_ping || s->qw_packetloss)
1408                         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 );
1409                 else
1410                         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 );
1411         }
1412         return 8;
1413 }
1414
1415 void Sbar_DeathmatchOverlay (void)
1416 {
1417         int i, x, y;
1418
1419         // request new ping times every two second
1420         if (cl.last_ping_request < realtime - 2 && cls.netcon)
1421         {
1422                 cl.last_ping_request = realtime;
1423                 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1424                 {
1425                         MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1426                         MSG_WriteString(&cls.netcon->message, "pings");
1427                 }
1428                 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)
1429                 {
1430                         // 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
1431                         cl.parsingtextexpectingpingforscores = true; // hide the output of the next ping report
1432                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1433                         MSG_WriteString(&cls.netcon->message, "ping");
1434                 }
1435                 else
1436                 {
1437                         // newer server definitely has pings command, so use it for more efficiency
1438                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1439                         MSG_WriteString(&cls.netcon->message, "pings");
1440                 }
1441         }
1442
1443         DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1444
1445         // scores
1446         Sbar_SortFrags ();
1447         // draw the text
1448         x = (vid_conwidth.integer - (6 + 18 + 15) * 8) / 2;
1449         y = 40;
1450         DrawQ_ColoredString(x, y, va("ping pl%% time frags team  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1451         y += 8;
1452
1453         if (Sbar_IsTeammatch ())
1454         {
1455                 // show team scores first
1456                 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1457                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1458                 y += 5;
1459         }
1460
1461         for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1462                 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1463 }
1464
1465 /*
1466 ==================
1467 Sbar_DeathmatchOverlay
1468
1469 ==================
1470 */
1471 void Sbar_MiniDeathmatchOverlay (int x, int y)
1472 {
1473         int i, numlines;
1474
1475         // decide where to print
1476         if (gamemode == GAME_TRANSFUSION)
1477                 numlines = (vid_conwidth.integer - x + 127) / 128;
1478         else
1479                 numlines = (vid_conheight.integer - y + 7) / 8;
1480
1481         // give up if there isn't room
1482         if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1483                 return;
1484
1485         // scores
1486         Sbar_SortFrags ();
1487
1488         //find us
1489         for (i = 0; i < scoreboardlines; i++)
1490                 if (fragsort[i] == cl.playerentity - 1)
1491                         break;
1492
1493         // figure out start
1494         i -= numlines/2;
1495         i = min(i, scoreboardlines - numlines);
1496         i = max(i, 0);
1497
1498         if (gamemode == GAME_TRANSFUSION)
1499         {
1500                 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1501                         x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1502         }
1503         else
1504         {
1505                 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1506                         y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1507         }
1508 }
1509
1510 /*
1511 ==================
1512 Sbar_IntermissionOverlay
1513
1514 ==================
1515 */
1516 void Sbar_IntermissionOverlay (void)
1517 {
1518         int             dig;
1519         int             num;
1520
1521         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1522         //if (cl.gametype == GAME_DEATHMATCH)
1523         if (!cl.islocalgame)
1524         {
1525                 Sbar_DeathmatchOverlay ();
1526                 return;
1527         }
1528
1529         sbar_x = (vid_conwidth.integer - 320) >> 1;
1530         sbar_y = (vid_conheight.integer - 200) >> 1;
1531
1532         DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1533         DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1534
1535 // time
1536         dig = (int)cl.completed_time / 60;
1537         Sbar_DrawNum (160, 64, dig, 3, 0);
1538         num = (int)cl.completed_time - dig*60;
1539         if (gamemode != GAME_NEXUIZ)
1540                 Sbar_DrawPic (234,64,sb_colon);
1541         Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1542         Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1543
1544         Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1545         if (gamemode != GAME_NEXUIZ)
1546                 Sbar_DrawPic (232, 104, sb_slash);
1547         Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1548
1549         Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1550         if (gamemode != GAME_NEXUIZ)
1551                 Sbar_DrawPic (232, 144, sb_slash);
1552         Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1553
1554 }
1555
1556
1557 /*
1558 ==================
1559 Sbar_FinaleOverlay
1560
1561 ==================
1562 */
1563 void Sbar_FinaleOverlay (void)
1564 {
1565         DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1566 }
1567