]> icculus.org git repositories - divverent/darkplaces.git/blob - sbar.c
ea0ad96fe4691e528a8927b0bf9723f9d1b4859f
[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 (cls.protocol == PROTOCOL_QUAKEWORLD)
1392         {
1393                 if (s->qw_spectator)
1394                 {
1395                         if (s->qw_ping || s->qw_packetloss)
1396                                 DrawQ_ColoredString(x, y, va("%4i %3i %4i spectator  %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 );
1397                         else
1398                                 DrawQ_ColoredString(x, y, va("         %4i spectator  %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 );
1399                 }
1400                 else
1401                 {
1402                         // draw colors behind score
1403                         c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1404                         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);
1405                         c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1406                         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);
1407                         // print the text
1408                         //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);
1409                         if (s->qw_ping || s->qw_packetloss)
1410                                 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 );
1411                         else
1412                                 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 );
1413                 }
1414         }
1415         else
1416         {
1417                 if (s->qw_spectator)
1418                 {
1419                         if (s->qw_ping || s->qw_packetloss)
1420                                 DrawQ_ColoredString(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1421                         else
1422                                 DrawQ_ColoredString(x, y, va("         spect %c%s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1423                 }
1424                 else
1425                 {
1426                         // draw colors behind score
1427                         c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1428                         DrawQ_Pic(x + 9*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);
1429                         c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1430                         DrawQ_Pic(x + 9*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);
1431                         // print the text
1432                         //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);
1433                         if (s->qw_ping || s->qw_packetloss)
1434                                 DrawQ_ColoredString(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1435                         else
1436                                 DrawQ_ColoredString(x, y, va("         %5i %c%s", (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1437                 }
1438         }
1439         return 8;
1440 }
1441
1442 void Sbar_DeathmatchOverlay (void)
1443 {
1444         int i, x, y;
1445
1446         // request new ping times every two second
1447         if (cl.last_ping_request < realtime - 2 && cls.netcon)
1448         {
1449                 cl.last_ping_request = realtime;
1450                 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1451                 {
1452                         MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1453                         MSG_WriteString(&cls.netcon->message, "pings");
1454                 }
1455                 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)
1456                 {
1457                         // 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
1458                         cl.parsingtextexpectingpingforscores = true; // hide the output of the next ping report
1459                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1460                         MSG_WriteString(&cls.netcon->message, "ping");
1461                 }
1462                 else
1463                 {
1464                         // newer server definitely has pings command, so use it for more efficiency
1465                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1466                         MSG_WriteString(&cls.netcon->message, "pings");
1467                 }
1468         }
1469
1470         DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1471
1472         // scores
1473         Sbar_SortFrags ();
1474         // draw the text
1475         y = 40;
1476         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1477         {
1478                 x = (vid_conwidth.integer - (26 + 15) * 8) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1479                 DrawQ_ColoredString(x, y, va("ping pl%% time frags team  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1480         }
1481         else
1482         {
1483                 x = (vid_conwidth.integer - (16 + 15) * 8) / 2; // 16 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1484                 DrawQ_ColoredString(x, y, va("ping pl%% frags  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1485         }
1486         y += 8;
1487
1488         if (Sbar_IsTeammatch ())
1489         {
1490                 // show team scores first
1491                 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1492                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1493                 y += 5;
1494         }
1495
1496         for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1497                 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1498 }
1499
1500 /*
1501 ==================
1502 Sbar_DeathmatchOverlay
1503
1504 ==================
1505 */
1506 void Sbar_MiniDeathmatchOverlay (int x, int y)
1507 {
1508         int i, numlines;
1509
1510         // decide where to print
1511         if (gamemode == GAME_TRANSFUSION)
1512                 numlines = (vid_conwidth.integer - x + 127) / 128;
1513         else
1514                 numlines = (vid_conheight.integer - y + 7) / 8;
1515
1516         // give up if there isn't room
1517         if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1518                 return;
1519
1520         // scores
1521         Sbar_SortFrags ();
1522
1523         //find us
1524         for (i = 0; i < scoreboardlines; i++)
1525                 if (fragsort[i] == cl.playerentity - 1)
1526                         break;
1527
1528         // figure out start
1529         i -= numlines/2;
1530         i = min(i, scoreboardlines - numlines);
1531         i = max(i, 0);
1532
1533         if (gamemode == GAME_TRANSFUSION)
1534         {
1535                 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1536                         x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1537         }
1538         else
1539         {
1540                 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1541                         y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1542         }
1543 }
1544
1545 /*
1546 ==================
1547 Sbar_IntermissionOverlay
1548
1549 ==================
1550 */
1551 void Sbar_IntermissionOverlay (void)
1552 {
1553         int             dig;
1554         int             num;
1555
1556         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1557         //if (cl.gametype == GAME_DEATHMATCH)
1558         if (!cl.islocalgame)
1559         {
1560                 Sbar_DeathmatchOverlay ();
1561                 return;
1562         }
1563
1564         sbar_x = (vid_conwidth.integer - 320) >> 1;
1565         sbar_y = (vid_conheight.integer - 200) >> 1;
1566
1567         DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1568         DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1569
1570 // time
1571         dig = (int)cl.completed_time / 60;
1572         Sbar_DrawNum (160, 64, dig, 3, 0);
1573         num = (int)cl.completed_time - dig*60;
1574         if (gamemode != GAME_NEXUIZ)
1575                 Sbar_DrawPic (234,64,sb_colon);
1576         Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1577         Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1578
1579         Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1580         if (gamemode != GAME_NEXUIZ)
1581                 Sbar_DrawPic (232, 104, sb_slash);
1582         Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1583
1584         Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1585         if (gamemode != GAME_NEXUIZ)
1586                 Sbar_DrawPic (232, 144, sb_slash);
1587         Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1588
1589 }
1590
1591
1592 /*
1593 ==================
1594 Sbar_FinaleOverlay
1595
1596 ==================
1597 */
1598 void Sbar_FinaleOverlay (void)
1599 {
1600         DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1601 }
1602