]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - sbar.c
server list: allow more AND and OR masks (except in DP_SMALLMEMORY profile)
[xonotic/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 #include "time.h"
24 #include "cl_collision.h"
25
26 cachepic_t *sb_disc;
27
28 #define STAT_MINUS 10 // num frame for '-' stats digit
29 cachepic_t *sb_nums[2][11];
30 cachepic_t *sb_colon, *sb_slash;
31 cachepic_t *sb_ibar;
32 cachepic_t *sb_sbar;
33 cachepic_t *sb_scorebar;
34 // AK only used by NEX
35 cachepic_t *sb_sbar_minimal;
36 cachepic_t *sb_sbar_overlay;
37
38 // AK changed the bound to 9
39 cachepic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
40 cachepic_t *sb_ammo[4];
41 cachepic_t *sb_sigil[4];
42 cachepic_t *sb_armor[3];
43 cachepic_t *sb_items[32];
44
45 // 0-4 are based on health (in 20 increments)
46 // 0 is static, 1 is temporary animation
47 cachepic_t *sb_faces[5][2];
48 cachepic_t *sb_health; // GAME_NEXUIZ
49
50 cachepic_t *sb_face_invis;
51 cachepic_t *sb_face_quad;
52 cachepic_t *sb_face_invuln;
53 cachepic_t *sb_face_invis_invuln;
54
55 qboolean sb_showscores;
56
57 int sb_lines;                   // scan lines to draw
58
59 cachepic_t *rsb_invbar[2];
60 cachepic_t *rsb_weapons[5];
61 cachepic_t *rsb_items[2];
62 cachepic_t *rsb_ammo[3];
63 cachepic_t *rsb_teambord;               // PGM 01/19/97 - team color border
64
65 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
66 cachepic_t *hsb_weapons[7][5];   // 0 is active, 1 is owned, 2-5 are flashes
67 //MED 01/04/97 added array to simplify weapon parsing
68 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
69 //MED 01/04/97 added hipnotic items array
70 cachepic_t *hsb_items[2];
71
72 //GAME_SOM stuff:
73 cachepic_t *somsb_health;
74 cachepic_t *somsb_ammo[4];
75 cachepic_t *somsb_armor[3];
76
77 cachepic_t *zymsb_crosshair_center;
78 cachepic_t *zymsb_crosshair_line;
79 cachepic_t *zymsb_crosshair_health;
80 cachepic_t *zymsb_crosshair_ammo;
81 cachepic_t *zymsb_crosshair_clip;
82 cachepic_t *zymsb_crosshair_background;
83 cachepic_t *zymsb_crosshair_left1;
84 cachepic_t *zymsb_crosshair_left2;
85 cachepic_t *zymsb_crosshair_right;
86
87 cachepic_t *sb_ranking;
88 cachepic_t *sb_complete;
89 cachepic_t *sb_inter;
90 cachepic_t *sb_finale;
91
92 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
93 cvar_t showsound = {CVAR_SAVE, "showsound", "0", "shows number of active sound sources, sound latency, and other statistics"};
94 cvar_t showblur = {CVAR_SAVE, "showblur", "0", "shows the current alpha level of motionblur"};
95 cvar_t showspeed = {CVAR_SAVE, "showspeed", "0", "shows your current speed (qu per second); number selects unit: 1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots"};
96 cvar_t showtopspeed = {CVAR_SAVE, "showtopspeed", "0", "shows your top speed (kept on screen for max 3 seconds); value -1 takes over the unit from showspeed, otherwise it's an unit number just like in showspeed"};
97 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
98 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
99 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
100 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
101 cvar_t showtex = {0, "showtex", "0", "shows the name of the texture on the crosshair (for map debugging)"};
102 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
103 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
104 cvar_t sbar_hudselector = {CVAR_SAVE, "sbar_hudselector", "0", "selects which of the builtin hud layouts to use (meaning is somewhat dependent on gamemode, so nexuiz has a very different set of hud layouts than quake for example)"};
105 cvar_t sbar_scorerank = {CVAR_SAVE, "sbar_scorerank", "1", "shows an overlay for your score (or team score) and rank in the scoreboard"};
106 cvar_t sbar_gametime = {CVAR_SAVE, "sbar_gametime", "1", "shows an overlay for the time left in the current match/level (or current game time if there is no timelimit set)"};
107 cvar_t sbar_miniscoreboard_size = {CVAR_SAVE, "sbar_miniscoreboard_size", "-1", "sets the size of the mini deathmatch overlay in items, or disables it when set to 0, or sets it to a sane default when set to -1"};
108 cvar_t sbar_flagstatus_right = {CVAR_SAVE, "sbar_flagstatus_right", "0", "moves Nexuiz flag status icons to the right"};
109 cvar_t sbar_flagstatus_pos = {CVAR_SAVE, "sbar_flagstatus_pos", "115", "pixel position of the Nexuiz flag status icons, from the bottom"};
110 cvar_t sbar_info_pos = {CVAR_SAVE, "sbar_info_pos", "0", "pixel position of the info strings (such as showfps), from the bottom"};
111
112 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
113
114 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
115 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
116 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
117 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
118 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
119
120 void Sbar_MiniDeathmatchOverlay (int x, int y);
121 void Sbar_DeathmatchOverlay (void);
122 void Sbar_IntermissionOverlay (void);
123 void Sbar_FinaleOverlay (void);
124
125 void CL_VM_UpdateShowingScoresState (int showingscores);
126
127
128 /*
129 ===============
130 Sbar_ShowScores
131
132 Tab key down
133 ===============
134 */
135 void Sbar_ShowScores (void)
136 {
137         if (sb_showscores)
138                 return;
139         sb_showscores = true;
140         CL_VM_UpdateShowingScoresState(sb_showscores);
141 }
142
143 /*
144 ===============
145 Sbar_DontShowScores
146
147 Tab key up
148 ===============
149 */
150 void Sbar_DontShowScores (void)
151 {
152         sb_showscores = false;
153         CL_VM_UpdateShowingScoresState(sb_showscores);
154 }
155
156 void sbar_start(void)
157 {
158         int i;
159
160         if (gamemode == GAME_DELUXEQUAKE || gamemode == GAME_BLOODOMNICIDE)
161         {
162         }
163         else if (gamemode == GAME_SOM)
164         {
165                 sb_disc = Draw_CachePic_Flags ("gfx/disc", CACHEPICFLAG_QUIET);
166
167                 for (i = 0;i < 10;i++)
168                         sb_nums[0][i] = Draw_CachePic_Flags (va("gfx/num_%i",i), CACHEPICFLAG_QUIET);
169
170                 somsb_health = Draw_CachePic_Flags ("gfx/hud_health", CACHEPICFLAG_QUIET);
171                 somsb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
172                 somsb_ammo[1] = Draw_CachePic_Flags ("gfx/sb_nails", CACHEPICFLAG_QUIET);
173                 somsb_ammo[2] = Draw_CachePic_Flags ("gfx/sb_rocket", CACHEPICFLAG_QUIET);
174                 somsb_ammo[3] = Draw_CachePic_Flags ("gfx/sb_cells", CACHEPICFLAG_QUIET);
175                 somsb_armor[0] = Draw_CachePic_Flags ("gfx/sb_armor1", CACHEPICFLAG_QUIET);
176                 somsb_armor[1] = Draw_CachePic_Flags ("gfx/sb_armor2", CACHEPICFLAG_QUIET);
177                 somsb_armor[2] = Draw_CachePic_Flags ("gfx/sb_armor3", CACHEPICFLAG_QUIET);
178         }
179         else if (gamemode == GAME_NEXUIZ)
180         {
181                 for (i = 0;i < 10;i++)
182                         sb_nums[0][i] = Draw_CachePic_Flags (va("gfx/num_%i",i), CACHEPICFLAG_QUIET);
183                 sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
184                 sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET);
185
186                 sb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
187                 sb_ammo[1] = Draw_CachePic_Flags ("gfx/sb_bullets", CACHEPICFLAG_QUIET);
188                 sb_ammo[2] = Draw_CachePic_Flags ("gfx/sb_rocket", CACHEPICFLAG_QUIET);
189                 sb_ammo[3] = Draw_CachePic_Flags ("gfx/sb_cells", CACHEPICFLAG_QUIET);
190
191                 sb_armor[0] = Draw_CachePic_Flags ("gfx/sb_armor", CACHEPICFLAG_QUIET);
192                 sb_armor[1] = NULL;
193                 sb_armor[2] = NULL;
194
195                 sb_health = Draw_CachePic_Flags ("gfx/sb_health", CACHEPICFLAG_QUIET);
196
197                 sb_items[2] = Draw_CachePic_Flags ("gfx/sb_slowmo", CACHEPICFLAG_QUIET);
198                 sb_items[3] = Draw_CachePic_Flags ("gfx/sb_invinc", CACHEPICFLAG_QUIET);
199                 sb_items[4] = Draw_CachePic_Flags ("gfx/sb_energy", CACHEPICFLAG_QUIET);
200                 sb_items[5] = Draw_CachePic_Flags ("gfx/sb_str", CACHEPICFLAG_QUIET);
201
202                 sb_items[11] = Draw_CachePic_Flags ("gfx/sb_flag_red_taken", CACHEPICFLAG_QUIET);
203                 sb_items[12] = Draw_CachePic_Flags ("gfx/sb_flag_red_lost", CACHEPICFLAG_QUIET);
204                 sb_items[13] = Draw_CachePic_Flags ("gfx/sb_flag_red_carrying", CACHEPICFLAG_QUIET);
205                 sb_items[14] = Draw_CachePic_Flags ("gfx/sb_key_carrying", CACHEPICFLAG_QUIET);
206                 sb_items[15] = Draw_CachePic_Flags ("gfx/sb_flag_blue_taken", CACHEPICFLAG_QUIET);
207                 sb_items[16] = Draw_CachePic_Flags ("gfx/sb_flag_blue_lost", CACHEPICFLAG_QUIET);
208                 sb_items[17] = Draw_CachePic_Flags ("gfx/sb_flag_blue_carrying", CACHEPICFLAG_QUIET);
209
210                 sb_sbar = Draw_CachePic_Flags ("gfx/sbar", CACHEPICFLAG_QUIET);
211                 sb_sbar_minimal = Draw_CachePic_Flags ("gfx/sbar_minimal", CACHEPICFLAG_QUIET);
212                 sb_sbar_overlay = Draw_CachePic_Flags ("gfx/sbar_overlay", CACHEPICFLAG_QUIET);
213
214                 for(i = 0; i < 9;i++)
215                         sb_weapons[0][i] = Draw_CachePic_Flags (va("gfx/inv_weapon%i",i), CACHEPICFLAG_QUIET);
216         }
217         else if (gamemode == GAME_ZYMOTIC)
218         {
219                 zymsb_crosshair_center = Draw_CachePic_Flags ("gfx/hud/crosshair_center", CACHEPICFLAG_QUIET);
220                 zymsb_crosshair_line = Draw_CachePic_Flags ("gfx/hud/crosshair_line", CACHEPICFLAG_QUIET);
221                 zymsb_crosshair_health = Draw_CachePic_Flags ("gfx/hud/crosshair_health", CACHEPICFLAG_QUIET);
222                 zymsb_crosshair_clip = Draw_CachePic_Flags ("gfx/hud/crosshair_clip", CACHEPICFLAG_QUIET);
223                 zymsb_crosshair_ammo = Draw_CachePic_Flags ("gfx/hud/crosshair_ammo", CACHEPICFLAG_QUIET);
224                 zymsb_crosshair_background = Draw_CachePic_Flags ("gfx/hud/crosshair_background", CACHEPICFLAG_QUIET);
225                 zymsb_crosshair_left1 = Draw_CachePic_Flags ("gfx/hud/crosshair_left1", CACHEPICFLAG_QUIET);
226                 zymsb_crosshair_left2 = Draw_CachePic_Flags ("gfx/hud/crosshair_left2", CACHEPICFLAG_QUIET);
227                 zymsb_crosshair_right = Draw_CachePic_Flags ("gfx/hud/crosshair_right", CACHEPICFLAG_QUIET);
228         }
229         else
230         {
231                 sb_disc = Draw_CachePic_Flags ("gfx/disc", CACHEPICFLAG_QUIET);
232
233                 for (i = 0;i < 10;i++)
234                 {
235                         sb_nums[0][i] = Draw_CachePic_Flags (va("gfx/num_%i",i), CACHEPICFLAG_QUIET);
236                         sb_nums[1][i] = Draw_CachePic_Flags (va("gfx/anum_%i",i), CACHEPICFLAG_QUIET);
237                 }
238
239                 sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
240                 sb_nums[1][10] = Draw_CachePic_Flags ("gfx/anum_minus", CACHEPICFLAG_QUIET);
241
242                 sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET);
243                 sb_slash = Draw_CachePic_Flags ("gfx/num_slash", CACHEPICFLAG_QUIET);
244
245                 sb_weapons[0][0] = Draw_CachePic_Flags ("gfx/inv_shotgun", CACHEPICFLAG_QUIET);
246                 sb_weapons[0][1] = Draw_CachePic_Flags ("gfx/inv_sshotgun", CACHEPICFLAG_QUIET);
247                 sb_weapons[0][2] = Draw_CachePic_Flags ("gfx/inv_nailgun", CACHEPICFLAG_QUIET);
248                 sb_weapons[0][3] = Draw_CachePic_Flags ("gfx/inv_snailgun", CACHEPICFLAG_QUIET);
249                 sb_weapons[0][4] = Draw_CachePic_Flags ("gfx/inv_rlaunch", CACHEPICFLAG_QUIET);
250                 sb_weapons[0][5] = Draw_CachePic_Flags ("gfx/inv_srlaunch", CACHEPICFLAG_QUIET);
251                 sb_weapons[0][6] = Draw_CachePic_Flags ("gfx/inv_lightng", CACHEPICFLAG_QUIET);
252
253                 sb_weapons[1][0] = Draw_CachePic_Flags ("gfx/inv2_shotgun", CACHEPICFLAG_QUIET);
254                 sb_weapons[1][1] = Draw_CachePic_Flags ("gfx/inv2_sshotgun", CACHEPICFLAG_QUIET);
255                 sb_weapons[1][2] = Draw_CachePic_Flags ("gfx/inv2_nailgun", CACHEPICFLAG_QUIET);
256                 sb_weapons[1][3] = Draw_CachePic_Flags ("gfx/inv2_snailgun", CACHEPICFLAG_QUIET);
257                 sb_weapons[1][4] = Draw_CachePic_Flags ("gfx/inv2_rlaunch", CACHEPICFLAG_QUIET);
258                 sb_weapons[1][5] = Draw_CachePic_Flags ("gfx/inv2_srlaunch", CACHEPICFLAG_QUIET);
259                 sb_weapons[1][6] = Draw_CachePic_Flags ("gfx/inv2_lightng", CACHEPICFLAG_QUIET);
260
261                 for (i = 0;i < 5;i++)
262                 {
263                         sb_weapons[2+i][0] = Draw_CachePic_Flags (va("gfx/inva%i_shotgun",i+1), CACHEPICFLAG_QUIET);
264                         sb_weapons[2+i][1] = Draw_CachePic_Flags (va("gfx/inva%i_sshotgun",i+1), CACHEPICFLAG_QUIET);
265                         sb_weapons[2+i][2] = Draw_CachePic_Flags (va("gfx/inva%i_nailgun",i+1), CACHEPICFLAG_QUIET);
266                         sb_weapons[2+i][3] = Draw_CachePic_Flags (va("gfx/inva%i_snailgun",i+1), CACHEPICFLAG_QUIET);
267                         sb_weapons[2+i][4] = Draw_CachePic_Flags (va("gfx/inva%i_rlaunch",i+1), CACHEPICFLAG_QUIET);
268                         sb_weapons[2+i][5] = Draw_CachePic_Flags (va("gfx/inva%i_srlaunch",i+1), CACHEPICFLAG_QUIET);
269                         sb_weapons[2+i][6] = Draw_CachePic_Flags (va("gfx/inva%i_lightng",i+1), CACHEPICFLAG_QUIET);
270                 }
271
272                 sb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
273                 sb_ammo[1] = Draw_CachePic_Flags ("gfx/sb_nails", CACHEPICFLAG_QUIET);
274                 sb_ammo[2] = Draw_CachePic_Flags ("gfx/sb_rocket", CACHEPICFLAG_QUIET);
275                 sb_ammo[3] = Draw_CachePic_Flags ("gfx/sb_cells", CACHEPICFLAG_QUIET);
276
277                 sb_armor[0] = Draw_CachePic_Flags ("gfx/sb_armor1", CACHEPICFLAG_QUIET);
278                 sb_armor[1] = Draw_CachePic_Flags ("gfx/sb_armor2", CACHEPICFLAG_QUIET);
279                 sb_armor[2] = Draw_CachePic_Flags ("gfx/sb_armor3", CACHEPICFLAG_QUIET);
280
281                 sb_items[0] = Draw_CachePic_Flags ("gfx/sb_key1", CACHEPICFLAG_QUIET);
282                 sb_items[1] = Draw_CachePic_Flags ("gfx/sb_key2", CACHEPICFLAG_QUIET);
283                 sb_items[2] = Draw_CachePic_Flags ("gfx/sb_invis", CACHEPICFLAG_QUIET);
284                 sb_items[3] = Draw_CachePic_Flags ("gfx/sb_invuln", CACHEPICFLAG_QUIET);
285                 sb_items[4] = Draw_CachePic_Flags ("gfx/sb_suit", CACHEPICFLAG_QUIET);
286                 sb_items[5] = Draw_CachePic_Flags ("gfx/sb_quad", CACHEPICFLAG_QUIET);
287
288                 sb_sigil[0] = Draw_CachePic_Flags ("gfx/sb_sigil1", CACHEPICFLAG_QUIET);
289                 sb_sigil[1] = Draw_CachePic_Flags ("gfx/sb_sigil2", CACHEPICFLAG_QUIET);
290                 sb_sigil[2] = Draw_CachePic_Flags ("gfx/sb_sigil3", CACHEPICFLAG_QUIET);
291                 sb_sigil[3] = Draw_CachePic_Flags ("gfx/sb_sigil4", CACHEPICFLAG_QUIET);
292
293                 sb_faces[4][0] = Draw_CachePic_Flags ("gfx/face1", CACHEPICFLAG_QUIET);
294                 sb_faces[4][1] = Draw_CachePic_Flags ("gfx/face_p1", CACHEPICFLAG_QUIET);
295                 sb_faces[3][0] = Draw_CachePic_Flags ("gfx/face2", CACHEPICFLAG_QUIET);
296                 sb_faces[3][1] = Draw_CachePic_Flags ("gfx/face_p2", CACHEPICFLAG_QUIET);
297                 sb_faces[2][0] = Draw_CachePic_Flags ("gfx/face3", CACHEPICFLAG_QUIET);
298                 sb_faces[2][1] = Draw_CachePic_Flags ("gfx/face_p3", CACHEPICFLAG_QUIET);
299                 sb_faces[1][0] = Draw_CachePic_Flags ("gfx/face4", CACHEPICFLAG_QUIET);
300                 sb_faces[1][1] = Draw_CachePic_Flags ("gfx/face_p4", CACHEPICFLAG_QUIET);
301                 sb_faces[0][0] = Draw_CachePic_Flags ("gfx/face5", CACHEPICFLAG_QUIET);
302                 sb_faces[0][1] = Draw_CachePic_Flags ("gfx/face_p5", CACHEPICFLAG_QUIET);
303
304                 sb_face_invis = Draw_CachePic_Flags ("gfx/face_invis", CACHEPICFLAG_QUIET);
305                 sb_face_invuln = Draw_CachePic_Flags ("gfx/face_invul2", CACHEPICFLAG_QUIET);
306                 sb_face_invis_invuln = Draw_CachePic_Flags ("gfx/face_inv2", CACHEPICFLAG_QUIET);
307                 sb_face_quad = Draw_CachePic_Flags ("gfx/face_quad", CACHEPICFLAG_QUIET);
308
309                 sb_sbar = Draw_CachePic_Flags ("gfx/sbar", CACHEPICFLAG_QUIET);
310                 sb_ibar = Draw_CachePic_Flags ("gfx/ibar", CACHEPICFLAG_QUIET);
311                 sb_scorebar = Draw_CachePic_Flags ("gfx/scorebar", CACHEPICFLAG_QUIET);
312
313         //MED 01/04/97 added new hipnotic weapons
314                 if (gamemode == GAME_HIPNOTIC)
315                 {
316                         hsb_weapons[0][0] = Draw_CachePic_Flags ("gfx/inv_laser", CACHEPICFLAG_QUIET);
317                         hsb_weapons[0][1] = Draw_CachePic_Flags ("gfx/inv_mjolnir", CACHEPICFLAG_QUIET);
318                         hsb_weapons[0][2] = Draw_CachePic_Flags ("gfx/inv_gren_prox", CACHEPICFLAG_QUIET);
319                         hsb_weapons[0][3] = Draw_CachePic_Flags ("gfx/inv_prox_gren", CACHEPICFLAG_QUIET);
320                         hsb_weapons[0][4] = Draw_CachePic_Flags ("gfx/inv_prox", CACHEPICFLAG_QUIET);
321
322                         hsb_weapons[1][0] = Draw_CachePic_Flags ("gfx/inv2_laser", CACHEPICFLAG_QUIET);
323                         hsb_weapons[1][1] = Draw_CachePic_Flags ("gfx/inv2_mjolnir", CACHEPICFLAG_QUIET);
324                         hsb_weapons[1][2] = Draw_CachePic_Flags ("gfx/inv2_gren_prox", CACHEPICFLAG_QUIET);
325                         hsb_weapons[1][3] = Draw_CachePic_Flags ("gfx/inv2_prox_gren", CACHEPICFLAG_QUIET);
326                         hsb_weapons[1][4] = Draw_CachePic_Flags ("gfx/inv2_prox", CACHEPICFLAG_QUIET);
327
328                         for (i = 0;i < 5;i++)
329                         {
330                                 hsb_weapons[2+i][0] = Draw_CachePic_Flags (va("gfx/inva%i_laser",i+1), CACHEPICFLAG_QUIET);
331                                 hsb_weapons[2+i][1] = Draw_CachePic_Flags (va("gfx/inva%i_mjolnir",i+1), CACHEPICFLAG_QUIET);
332                                 hsb_weapons[2+i][2] = Draw_CachePic_Flags (va("gfx/inva%i_gren_prox",i+1), CACHEPICFLAG_QUIET);
333                                 hsb_weapons[2+i][3] = Draw_CachePic_Flags (va("gfx/inva%i_prox_gren",i+1), CACHEPICFLAG_QUIET);
334                                 hsb_weapons[2+i][4] = Draw_CachePic_Flags (va("gfx/inva%i_prox",i+1), CACHEPICFLAG_QUIET);
335                         }
336
337                         hsb_items[0] = Draw_CachePic_Flags ("gfx/sb_wsuit", CACHEPICFLAG_QUIET);
338                         hsb_items[1] = Draw_CachePic_Flags ("gfx/sb_eshld", CACHEPICFLAG_QUIET);
339                 }
340                 else if (gamemode == GAME_ROGUE)
341                 {
342                         rsb_invbar[0] = Draw_CachePic_Flags ("gfx/r_invbar1", CACHEPICFLAG_QUIET);
343                         rsb_invbar[1] = Draw_CachePic_Flags ("gfx/r_invbar2", CACHEPICFLAG_QUIET);
344
345                         rsb_weapons[0] = Draw_CachePic_Flags ("gfx/r_lava", CACHEPICFLAG_QUIET);
346                         rsb_weapons[1] = Draw_CachePic_Flags ("gfx/r_superlava", CACHEPICFLAG_QUIET);
347                         rsb_weapons[2] = Draw_CachePic_Flags ("gfx/r_gren", CACHEPICFLAG_QUIET);
348                         rsb_weapons[3] = Draw_CachePic_Flags ("gfx/r_multirock", CACHEPICFLAG_QUIET);
349                         rsb_weapons[4] = Draw_CachePic_Flags ("gfx/r_plasma", CACHEPICFLAG_QUIET);
350
351                         rsb_items[0] = Draw_CachePic_Flags ("gfx/r_shield1", CACHEPICFLAG_QUIET);
352                         rsb_items[1] = Draw_CachePic_Flags ("gfx/r_agrav1", CACHEPICFLAG_QUIET);
353
354         // PGM 01/19/97 - team color border
355                         rsb_teambord = Draw_CachePic_Flags ("gfx/r_teambord", CACHEPICFLAG_QUIET);
356         // PGM 01/19/97 - team color border
357
358                         rsb_ammo[0] = Draw_CachePic_Flags ("gfx/r_ammolava", CACHEPICFLAG_QUIET);
359                         rsb_ammo[1] = Draw_CachePic_Flags ("gfx/r_ammomulti", CACHEPICFLAG_QUIET);
360                         rsb_ammo[2] = Draw_CachePic_Flags ("gfx/r_ammoplasma", CACHEPICFLAG_QUIET);
361                 }
362         }
363
364         sb_ranking = Draw_CachePic_Flags ("gfx/ranking", CACHEPICFLAG_QUIET);
365         sb_complete = Draw_CachePic_Flags ("gfx/complete", CACHEPICFLAG_QUIET);
366         sb_inter = Draw_CachePic_Flags ("gfx/inter", CACHEPICFLAG_QUIET);
367         sb_finale = Draw_CachePic_Flags ("gfx/finale", CACHEPICFLAG_QUIET);
368 }
369
370 void sbar_shutdown(void)
371 {
372 }
373
374 void sbar_newmap(void)
375 {
376 }
377
378 void Sbar_Init (void)
379 {
380         Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
381         Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
382         Cvar_RegisterVariable(&showfps);
383         Cvar_RegisterVariable(&showsound);
384         Cvar_RegisterVariable(&showblur);
385         Cvar_RegisterVariable(&showspeed);
386         Cvar_RegisterVariable(&showtopspeed);
387         Cvar_RegisterVariable(&showtime);
388         Cvar_RegisterVariable(&showtime_format);
389         Cvar_RegisterVariable(&showdate);
390         Cvar_RegisterVariable(&showdate_format);
391         Cvar_RegisterVariable(&showtex);
392         Cvar_RegisterVariable(&sbar_alpha_bg);
393         Cvar_RegisterVariable(&sbar_alpha_fg);
394         Cvar_RegisterVariable(&sbar_hudselector);
395         Cvar_RegisterVariable(&sbar_scorerank);
396         Cvar_RegisterVariable(&sbar_gametime);
397         Cvar_RegisterVariable(&sbar_miniscoreboard_size);
398         Cvar_RegisterVariable(&sbar_info_pos);
399         Cvar_RegisterVariable(&cl_deathscoreboard);
400
401         Cvar_RegisterVariable(&crosshair_color_red);
402         Cvar_RegisterVariable(&crosshair_color_green);
403         Cvar_RegisterVariable(&crosshair_color_blue);
404         Cvar_RegisterVariable(&crosshair_color_alpha);
405         Cvar_RegisterVariable(&crosshair_size);
406
407         Cvar_RegisterVariable(&sbar_flagstatus_right); // (GAME_NEXUZI ONLY)
408         Cvar_RegisterVariable(&sbar_flagstatus_pos); // (GAME_NEXUIZ ONLY)
409
410         R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap, NULL, NULL);
411 }
412
413
414 //=============================================================================
415
416 // drawing routines are relative to the status bar location
417
418 int sbar_x, sbar_y;
419
420 /*
421 =============
422 Sbar_DrawPic
423 =============
424 */
425 void Sbar_DrawStretchPic (int x, int y, cachepic_t *pic, float alpha, float overridewidth, float overrideheight)
426 {
427         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, overridewidth, overrideheight, 1, 1, 1, alpha, 0);
428 }
429
430 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
431 {
432         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
433 }
434
435 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
436 {
437         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
438 }
439
440 /*
441 ================
442 Sbar_DrawCharacter
443
444 Draws one solid graphics character
445 ================
446 */
447 void Sbar_DrawCharacter (int x, int y, int num)
448 {
449         DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true, FONT_SBAR);
450 }
451
452 /*
453 ================
454 Sbar_DrawString
455 ================
456 */
457 void Sbar_DrawString (int x, int y, char *str)
458 {
459         DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR);
460 }
461
462 /*
463 =============
464 Sbar_DrawNum
465 =============
466 */
467 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
468 {
469         char str[32], *ptr;
470         int l, frame;
471
472         l = dpsnprintf(str, sizeof(str), "%i", num);
473         ptr = str;
474         if (l > digits)
475                 ptr += (l-digits);
476         if (l < digits)
477                 x += (digits-l)*24;
478
479         while (*ptr)
480         {
481                 if (*ptr == '-')
482                         frame = STAT_MINUS;
483                 else
484                         frame = *ptr -'0';
485
486                 Sbar_DrawPic (x, y, sb_nums[color][frame]);
487                 x += 24;
488
489                 ptr++;
490         }
491 }
492
493 /*
494 =============
495 Sbar_DrawXNum
496 =============
497 */
498
499 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
500 {
501         char str[32], *ptr;
502         int l, frame;
503
504         if (digits < 0)
505         {
506                 digits = -digits;
507                 l = dpsnprintf(str, sizeof(str), "%0*i", digits, num);
508         }
509         else
510                 l = dpsnprintf(str, sizeof(str), "%i", num);
511         ptr = str;
512         if (l > digits)
513                 ptr += (l-digits);
514         if (l < digits)
515                 x += (digits-l) * lettersize;
516
517         while (*ptr)
518         {
519                 if (*ptr == '-')
520                         frame = STAT_MINUS;
521                 else
522                         frame = *ptr -'0';
523
524                 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
525                 x += lettersize;
526
527                 ptr++;
528         }
529 }
530
531 //=============================================================================
532
533
534 int Sbar_IsTeammatch(void)
535 {
536         // currently only nexuiz uses the team score board
537         return ((gamemode == GAME_NEXUIZ)
538                 && (teamplay.integer > 0));
539 }
540
541 /*
542 ===============
543 Sbar_SortFrags
544 ===============
545 */
546 static int fragsort[MAX_SCOREBOARD];
547 static int scoreboardlines;
548
549 int Sbar_GetSortedPlayerIndex (int index)
550 {
551         return index >= 0 && index < scoreboardlines ? fragsort[index] : -1;
552 }
553
554 static scoreboard_t teams[MAX_SCOREBOARD];
555 static int teamsort[MAX_SCOREBOARD];
556 static int teamlines;
557 void Sbar_SortFrags (void)
558 {
559         int i, j, k, color;
560
561         // sort by frags
562         scoreboardlines = 0;
563         for (i=0 ; i<cl.maxclients ; i++)
564         {
565                 if (cl.scores[i].name[0])
566                 {
567                         fragsort[scoreboardlines] = i;
568                         scoreboardlines++;
569                 }
570         }
571
572         for (i=0 ; i<scoreboardlines ; i++)
573                 for (j=0 ; j<scoreboardlines-1-i ; j++)
574                         if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
575                         {
576                                 k = fragsort[j];
577                                 fragsort[j] = fragsort[j+1];
578                                 fragsort[j+1] = k;
579                         }
580
581         teamlines = 0;
582         if (Sbar_IsTeammatch ())
583         {
584                 // now sort players by teams.
585                 for (i=0 ; i<scoreboardlines ; i++)
586                 {
587                         for (j=0 ; j<scoreboardlines-1-i ; j++)
588                         {
589                                 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
590                                 {
591                                         k = fragsort[j];
592                                         fragsort[j] = fragsort[j+1];
593                                         fragsort[j+1] = k;
594                                 }
595                         }
596                 }
597
598                 // calculate team scores
599                 color = -1;
600                 for (i=0 ; i<scoreboardlines ; i++)
601                 {
602                         if (color != (cl.scores[fragsort[i]].colors & 15))
603                         {
604                                 const char* teamname;
605
606                                 color = cl.scores[fragsort[i]].colors & 15;
607                                 teamlines++;
608
609                                 switch (color)
610                                 {
611                                         case 4:
612                                                 teamname = "^1Red Team";
613                                                 break;
614                                         case 13:
615                                                 teamname = "^4Blue Team";
616                                                 break;
617                                         case 9:
618                                                 teamname = "^6Pink Team";
619                                                 break;
620                                         case 12:
621                                                 teamname = "^3Yellow Team";
622                                                 break;
623                                         default:
624                                                 teamname = "Total Team Score";
625                                                 break;
626                                 }
627                                 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
628
629                                 teams[teamlines-1].frags = 0;
630                                 teams[teamlines-1].colors = color + 16 * color;
631                         }
632
633                         if (cl.scores[fragsort[i]].frags != -666)
634                         {
635                                 // do not add spedcators
636                                 // (ugly hack for nexuiz)
637                                 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
638                         }
639                 }
640
641                 // now sort teams by scores.
642                 for (i=0 ; i<teamlines ; i++)
643                         teamsort[i] = i;
644                 for (i=0 ; i<teamlines ; i++)
645                 {
646                         for (j=0 ; j<teamlines-1-i ; j++)
647                         {
648                                 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
649                                 {
650                                         k = teamsort[j];
651                                         teamsort[j] = teamsort[j+1];
652                                         teamsort[j+1] = k;
653                                 }
654                         }
655                 }
656         }
657 }
658
659 /*
660 ===============
661 Sbar_SoloScoreboard
662 ===============
663 */
664 void Sbar_SoloScoreboard (void)
665 {
666 #if 1
667         char    str[80], timestr[40];
668         int             max, timelen;
669         int             minutes, seconds;
670         double  t;
671
672         t = (cl.intermission ? cl.completed_time : cl.time);
673         minutes = (int)(t / 60);
674         seconds = (int)(t - 60*floor(t/60));
675
676         // monsters and secrets are now both on the top row
677         if (cl.stats[STAT_TOTALMONSTERS])
678                 Sbar_DrawString(8, 4, va("Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]));
679         else if (cl.stats[STAT_MONSTERS]) // LA: Display something if monsters_killed is non-zero, but total_monsters is zero
680                 Sbar_DrawString(8, 4, va("Monsters:%3i", cl.stats[STAT_MONSTERS]));
681
682         if (cl.stats[STAT_TOTALSECRETS])
683                 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
684         else if (cl.stats[STAT_SECRETS]) // LA: And similarly for secrets
685                 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i", cl.stats[STAT_SECRETS]));
686
687         // format is like this: e1m1:The Sligpate Complex
688         dpsnprintf(str, sizeof(str), "%s:%s", cl.worldbasename, cl.worldmessage);
689
690         // if there's a newline character, terminate the string there
691         if (strchr(str, '\n'))
692                 *(strchr(str, '\n')) = 0;
693
694         // make the time string
695         timelen = dpsnprintf(timestr, sizeof(timestr), " %i:%02i", minutes, seconds);
696
697         // truncate the level name if necessary to make room for time
698         max = 38 - timelen;
699         if ((int)strlen(str) > max)
700                 str[max] = 0;
701
702         // print the filename and message
703         Sbar_DrawString(8, 12, str);
704
705         // print the time
706         Sbar_DrawString(8 + max*8, 12, timestr);
707
708 #else
709         char    str[80];
710         int             minutes, seconds, tens, units;
711         int             l;
712
713         if (gamemode != GAME_NEXUIZ) {
714                 dpsnprintf (str, sizeof(str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
715                 Sbar_DrawString (8, 4, str);
716
717                 dpsnprintf (str, sizeof(str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
718                 Sbar_DrawString (8, 12, str);
719         }
720
721 // time
722         minutes = (int)(cl.time / 60);
723         seconds = (int)(cl.time - 60*minutes);
724         tens = seconds / 10;
725         units = seconds - 10*tens;
726         dpsnprintf (str, sizeof(str), "Time :%3i:%i%i", minutes, tens, units);
727         Sbar_DrawString (184, 4, str);
728
729 // draw level name
730         if (gamemode == GAME_NEXUIZ) {
731                 l = (int) strlen (cl.worldname);
732                 Sbar_DrawString (232 - l*4, 12, cl.worldname);
733         } else {
734                 l = (int) strlen (cl.worldmessage);
735                 Sbar_DrawString (232 - l*4, 12, cl.worldmessage);
736         }
737 #endif
738 }
739
740 /*
741 ===============
742 Sbar_DrawScoreboard
743 ===============
744 */
745 void Sbar_DrawScoreboard (void)
746 {
747         Sbar_SoloScoreboard ();
748         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
749         //if (cl.gametype == GAME_DEATHMATCH)
750         if (!cl.islocalgame)
751                 Sbar_DeathmatchOverlay ();
752 }
753
754 //=============================================================================
755
756 // AK to make DrawInventory smaller
757 static void Sbar_DrawWeapon(int nr, float fade, int active)
758 {
759         if (sbar_hudselector.integer == 1)
760         {
761                 // width = 300, height = 100
762                 const int w_width = 32, w_height = 12, w_space = 2, font_size = 8;
763
764                 DrawQ_Pic((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr, vid_conheight.integer - w_height, sb_weapons[0][nr], w_width, w_height, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 0.6, (active ? 1 : 0.6) * fade * sbar_alpha_fg.value, DRAWFLAG_NORMAL);
765                 // FIXME ??
766                 DrawQ_String((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr + w_space, vid_conheight.integer - w_height + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 1, 0, sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
767         }
768         else
769         {
770                 // width = 300, height = 100
771                 const int w_width = 300, w_height = 100, w_space = 10;
772                 const float w_scale = 0.4;
773
774                 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_NORMAL);
775                 //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, NULL, true, FONT_DEFAULT);
776         }
777 }
778
779 /*
780 ===============
781 Sbar_DrawInventory
782 ===============
783 */
784 void Sbar_DrawInventory (void)
785 {
786         int i;
787         char num[6];
788         float time;
789         int flashon;
790
791         if (gamemode == GAME_ROGUE)
792         {
793                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
794                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
795                 else
796                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
797         }
798         else
799                 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
800
801         // weapons
802         for (i=0 ; i<7 ; i++)
803         {
804                 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
805                 {
806                         time = cl.item_gettime[i];
807                         flashon = (int)(max(0, cl.time - time)*10);
808                         if (flashon >= 10)
809                         {
810                                 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i)  )
811                                         flashon = 1;
812                                 else
813                                         flashon = 0;
814                         }
815                         else
816                                 flashon = (flashon%5) + 2;
817
818                         Sbar_DrawPic (i*24, -16, sb_weapons[flashon][i]);
819                 }
820         }
821
822         // MED 01/04/97
823         // hipnotic weapons
824         if (gamemode == GAME_HIPNOTIC)
825         {
826                 int grenadeflashing=0;
827                 for (i=0 ; i<4 ; i++)
828                 {
829                         if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
830                         {
831                                 time = max(0, cl.item_gettime[hipweapons[i]]);
832                                 flashon = (int)((cl.time - time)*10);
833                                 if (flashon >= 10)
834                                 {
835                                         if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i])  )
836                                                 flashon = 1;
837                                         else
838                                                 flashon = 0;
839                                 }
840                                 else
841                                         flashon = (flashon%5) + 2;
842
843                                 // check grenade launcher
844                                 if (i==2)
845                                 {
846                                         if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
847                                         {
848                                                 if (flashon)
849                                                 {
850                                                         grenadeflashing = 1;
851                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
852                                                 }
853                                         }
854                                 }
855                                 else if (i==3)
856                                 {
857                                         if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
858                                         {
859                                                 if (!grenadeflashing)
860                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
861                                         }
862                                         else
863                                                 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
864                                 }
865                                 else
866                                         Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
867                         }
868                 }
869         }
870
871         if (gamemode == GAME_ROGUE)
872         {
873                 // check for powered up weapon.
874                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
875                         for (i=0;i<5;i++)
876                                 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
877                                         Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
878         }
879
880         // ammo counts
881         for (i=0 ; i<4 ; i++)
882         {
883                 dpsnprintf (num, sizeof(num), "%4i",cl.stats[STAT_SHELLS+i] );
884                 if (num[0] != ' ')
885                         Sbar_DrawCharacter ( (6*i+0)*8 - 2, -24, 18 + num[0] - '0');
886                 if (num[1] != ' ')
887                         Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[1] - '0');
888                 if (num[2] != ' ')
889                         Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[2] - '0');
890                 if (num[3] != ' ')
891                         Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[3] - '0');
892         }
893
894         // items
895         for (i=0 ; i<6 ; i++)
896                 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
897                 {
898                         //MED 01/04/97 changed keys
899                         if (gamemode != GAME_HIPNOTIC || (i>1))
900                                 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
901                 }
902
903         //MED 01/04/97 added hipnotic items
904         // hipnotic items
905         if (gamemode == GAME_HIPNOTIC)
906         {
907                 for (i=0 ; i<2 ; i++)
908                         if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
909                                 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
910         }
911
912         if (gamemode == GAME_ROGUE)
913         {
914                 // new rogue items
915                 for (i=0 ; i<2 ; i++)
916                         if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
917                                 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
918         }
919         else
920         {
921                 // sigils
922                 for (i=0 ; i<4 ; i++)
923                         if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
924                                 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
925         }
926 }
927
928 //=============================================================================
929
930 /*
931 ===============
932 Sbar_DrawFrags
933 ===============
934 */
935 void Sbar_DrawFrags (void)
936 {
937         int i, k, l, x, f;
938         char num[12];
939         scoreboard_t *s;
940         unsigned char *c;
941
942         Sbar_SortFrags ();
943
944         // draw the text
945         l = min(scoreboardlines, 4);
946
947         x = 23 * 8;
948
949         for (i = 0;i < l;i++)
950         {
951                 k = fragsort[i];
952                 s = &cl.scores[k];
953
954                 // draw background
955                 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
956                 DrawQ_Fill (sbar_x + x + 10, sbar_y     - 23, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
957                 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
958                 DrawQ_Fill (sbar_x + x + 10, sbar_y + 4 - 23, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
959
960                 // draw number
961                 f = s->frags;
962                 dpsnprintf (num, sizeof(num), "%3i",f);
963
964                 if (k == cl.viewentity - 1)
965                 {
966                         Sbar_DrawCharacter ( x      + 2, -24, 16);
967                         Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
968                 }
969                 Sbar_DrawCharacter (x +  8, -24, num[0]);
970                 Sbar_DrawCharacter (x + 16, -24, num[1]);
971                 Sbar_DrawCharacter (x + 24, -24, num[2]);
972                 x += 32;
973         }
974 }
975
976 //=============================================================================
977
978
979 /*
980 ===============
981 Sbar_DrawFace
982 ===============
983 */
984 void Sbar_DrawFace (void)
985 {
986         int f;
987
988 // PGM 01/19/97 - team color drawing
989 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
990         if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
991         {
992                 char num[12];
993                 scoreboard_t *s;
994                 unsigned char *c;
995
996                 s = &cl.scores[cl.viewentity - 1];
997                 // draw background
998                 Sbar_DrawPic (112, 0, rsb_teambord);
999                 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1000                 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1001                 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1002                 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1003
1004                 // draw number
1005                 f = s->frags;
1006                 dpsnprintf (num, sizeof(num), "%3i",f);
1007
1008                 if ((s->colors & 0xf0)==0)
1009                 {
1010                         if (num[0] != ' ')
1011                                 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
1012                         if (num[1] != ' ')
1013                                 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
1014                         if (num[2] != ' ')
1015                                 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
1016                 }
1017                 else
1018                 {
1019                         Sbar_DrawCharacter ( 109, 3, num[0]);
1020                         Sbar_DrawCharacter ( 116, 3, num[1]);
1021                         Sbar_DrawCharacter ( 123, 3, num[2]);
1022                 }
1023
1024                 return;
1025         }
1026 // PGM 01/19/97 - team color drawing
1027
1028         if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
1029                 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
1030         else if (cl.stats[STAT_ITEMS] & IT_QUAD)
1031                 Sbar_DrawPic (112, 0, sb_face_quad );
1032         else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
1033                 Sbar_DrawPic (112, 0, sb_face_invis );
1034         else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1035                 Sbar_DrawPic (112, 0, sb_face_invuln);
1036         else
1037         {
1038                 f = cl.stats[STAT_HEALTH] / 20;
1039                 f = bound(0, f, 4);
1040                 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
1041         }
1042 }
1043 double topspeed = 0;
1044 double topspeedxy = 0;
1045 time_t current_time = 3;
1046 time_t top_time = 0;
1047 time_t topxy_time = 0;
1048
1049 static void get_showspeed_unit(int unitnumber, double *conversion_factor, const char **unit)
1050 {
1051         if(unitnumber < 0)
1052                 unitnumber = showspeed.integer;
1053         switch(unitnumber)
1054         {
1055                 default:
1056                 case 1:
1057                         if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
1058                                 *unit = "in/s";
1059                         else
1060                                 *unit = "qu/s";
1061                         *conversion_factor = 1.0;
1062                         break;
1063                 case 2:
1064                         *unit = "m/s";
1065                         *conversion_factor = 0.0254;
1066                         if(gamemode != GAME_NEXUIZ && gamemode != GAME_XONOTIC) *conversion_factor *= 1.5;
1067                         // 1qu=1.5in is for non-Nexuiz/Xonotic only - Nexuiz/Xonotic players are overly large, but 1qu=1in fixes that
1068                         break;
1069                 case 3:
1070                         *unit = "km/h";
1071                         *conversion_factor = 0.0254 * 3.6;
1072                         if(gamemode != GAME_NEXUIZ && gamemode != GAME_XONOTIC) *conversion_factor *= 1.5;
1073                         break;
1074                 case 4:
1075                         *unit = "mph";
1076                         *conversion_factor = 0.0254 * 3.6 * 0.6213711922;
1077                         if(gamemode != GAME_NEXUIZ && gamemode != GAME_XONOTIC) *conversion_factor *= 1.5;
1078                         break;
1079                 case 5:
1080                         *unit = "knots";
1081                         *conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
1082                         if(gamemode != GAME_NEXUIZ && gamemode != GAME_XONOTIC) *conversion_factor *= 1.5;
1083                         break;
1084         }
1085 }
1086
1087 static double showfps_nexttime = 0, showfps_lasttime = -1;
1088 static double showfps_framerate = 0;
1089 static int showfps_framecount = 0;
1090
1091 void Sbar_ShowFPS_Update(void)
1092 {
1093         double interval = 1;
1094         double newtime;
1095         newtime = realtime;
1096         if (newtime >= showfps_nexttime)
1097         {
1098                 showfps_framerate = showfps_framecount / (newtime - showfps_lasttime);
1099                 if (showfps_nexttime < newtime - interval * 1.5)
1100                         showfps_nexttime = newtime;
1101                 showfps_lasttime = newtime;
1102                 showfps_nexttime += interval;
1103                 showfps_framecount = 0;
1104         }
1105         showfps_framecount++;
1106 }
1107
1108 void Sbar_ShowFPS(void)
1109 {
1110         float fps_x, fps_y, fps_scalex, fps_scaley, fps_strings = 0;
1111         char soundstring[32];
1112         char fpsstring[32];
1113         char timestring[32];
1114         char datestring[32];
1115         char timedemostring1[32];
1116         char timedemostring2[32];
1117         char speedstring[32];
1118         char blurstring[32];
1119         char topspeedstring[48];
1120         char texstring[MAX_QPATH];
1121         qboolean red = false;
1122         soundstring[0] = 0;
1123         fpsstring[0] = 0;
1124         timedemostring1[0] = 0;
1125         timedemostring2[0] = 0;
1126         timestring[0] = 0;
1127         datestring[0] = 0;
1128         speedstring[0] = 0;
1129         blurstring[0] = 0;
1130         texstring[0] = 0;
1131         topspeedstring[0] = 0;
1132         if (showfps.integer)
1133         {
1134                 red = (showfps_framerate < 1.0f);
1135                 if(showfps.integer == 2)
1136                         dpsnprintf(fpsstring, sizeof(fpsstring), "%7.3f mspf", (1000.0 / showfps_framerate));
1137                 else if (red)
1138                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0 / showfps_framerate + 0.5));
1139                 else
1140                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(showfps_framerate + 0.5));
1141                 fps_strings++;
1142                 if (cls.timedemo)
1143                 {
1144                         dpsnprintf(timedemostring1, sizeof(timedemostring1), "frame%4i %f", cls.td_frames, realtime - cls.td_starttime);
1145                         dpsnprintf(timedemostring2, sizeof(timedemostring2), "%i seconds %3.0f/%3.0f/%3.0f fps", cls.td_onesecondavgcount, cls.td_onesecondminfps, cls.td_onesecondavgfps / max(1, cls.td_onesecondavgcount), cls.td_onesecondmaxfps);
1146                         fps_strings++;
1147                         fps_strings++;
1148                 }
1149         }
1150         if (showtime.integer)
1151         {
1152                 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1153                 fps_strings++;
1154         }
1155         if (showdate.integer)
1156         {
1157                 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1158                 fps_strings++;
1159         }
1160         if (showblur.integer)
1161         {
1162                 dpsnprintf(blurstring, sizeof(blurstring), "%3i%% blur", (int)(cl.motionbluralpha * 100));
1163                 fps_strings++;
1164         }
1165         if (showsound.integer)
1166         {
1167                 dpsnprintf(soundstring, sizeof(soundstring), "%4i/4%i at %3ims", cls.soundstats.mixedsounds, cls.soundstats.totalsounds, cls.soundstats.latency_milliseconds);
1168                 fps_strings++;
1169         }
1170         if (showspeed.integer || showtopspeed.integer)
1171         {
1172                 double speed, speedxy, f;
1173                 const char *unit;
1174                 speed = VectorLength(cl.movement_velocity);
1175                 speedxy = sqrt(cl.movement_velocity[0] * cl.movement_velocity[0] + cl.movement_velocity[1] * cl.movement_velocity[1]);
1176                 if (showspeed.integer)
1177                 {
1178                         get_showspeed_unit(showspeed.integer, &f, &unit);
1179                         dpsnprintf(speedstring, sizeof(speedstring), "%.0f (%.0f) %s", f*speed, f*speedxy, unit);
1180                         fps_strings++;
1181                 }
1182                 if (showtopspeed.integer)
1183                 {
1184                         qboolean topspeed_latched = false, topspeedxy_latched = false;
1185                         get_showspeed_unit(showtopspeed.integer, &f, &unit);
1186                         if (speed >= topspeed || current_time - top_time > 3)
1187                         {
1188                                 topspeed = speed;
1189                                 time(&top_time);
1190                         }
1191                         else
1192                                 topspeed_latched = true;
1193                         if (speedxy >= topspeedxy || current_time - topxy_time > 3)
1194                         {
1195                                 topspeedxy = speedxy;
1196                                 time(&topxy_time);
1197                         }
1198                         else
1199                                 topspeedxy_latched = true;
1200                         dpsnprintf(topspeedstring, sizeof(topspeedstring), "%s%.0f%s (%s%.0f%s) %s",
1201                                 topspeed_latched ? "^1" : "^xf88", f*topspeed, "^xf88",
1202                                 topspeedxy_latched ? "^1" : "^xf88", f*topspeedxy, "^xf88",
1203                                 unit);
1204                         time(&current_time);
1205                         fps_strings++;
1206                 }
1207         }
1208         if (showtex.integer)
1209         {
1210                 vec3_t dest;
1211                 trace_t trace;
1212
1213                 VectorMA(r_refdef.view.origin, 65536, r_refdef.view.forward, dest);
1214                 trace.hittexture = NULL; // to make sure
1215                 // TODO change this trace to be stopped by anything "visible" (i.e. with a drawsurface), but not stuff like weapclip
1216                 // probably needs adding a new SUPERCONTENTS type
1217                 trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID, true, false, NULL, true, true);
1218                 if(trace.hittexture)
1219                         strlcpy(texstring, trace.hittexture->name, sizeof(texstring));
1220                 else
1221                         strlcpy(texstring, "(no texture hit)", sizeof(texstring));
1222                 fps_strings++;
1223         }
1224         if (fps_strings)
1225         {
1226                 fps_scalex = 12;
1227                 fps_scaley = 12;
1228                 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1229                 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_strings*fps_scaley);
1230                 fps_y = vid_conheight.integer - sbar_info_pos.integer - fps_strings*fps_scaley;
1231                 if (soundstring[0])
1232                 {
1233                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(soundstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1234                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1235                         DrawQ_String(fps_x, fps_y, soundstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1236                         fps_y += fps_scaley;
1237                 }
1238                 if (fpsstring[0])
1239                 {
1240                         r_draw2d_force = true;
1241                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(fpsstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1242                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1243                         if (red)
1244                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true, FONT_INFOBAR);
1245                         else
1246                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1247                         fps_y += fps_scaley;
1248                         r_draw2d_force = false;
1249                 }
1250                 if (timedemostring1[0])
1251                 {
1252                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(timedemostring1, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1253                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1254                         DrawQ_String(fps_x, fps_y, timedemostring1, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1255                         fps_y += fps_scaley;
1256                 }
1257                 if (timedemostring2[0])
1258                 {
1259                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(timedemostring2, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1260                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1261                         DrawQ_String(fps_x, fps_y, timedemostring2, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1262                         fps_y += fps_scaley;
1263                 }
1264                 if (timestring[0])
1265                 {
1266                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(timestring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1267                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1268                         DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1269                         fps_y += fps_scaley;
1270                 }
1271                 if (datestring[0])
1272                 {
1273                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(datestring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1274                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1275                         DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1276                         fps_y += fps_scaley;
1277                 }
1278                 if (speedstring[0])
1279                 {
1280                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(speedstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1281                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1282                         DrawQ_String(fps_x, fps_y, speedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1283                         fps_y += fps_scaley;
1284                 }
1285                 if (topspeedstring[0])
1286                 {
1287                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(topspeedstring, 0, fps_scalex, fps_scaley, false, FONT_INFOBAR);
1288                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1289                         DrawQ_String(fps_x, fps_y, topspeedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, false, FONT_INFOBAR);
1290                         fps_y += fps_scaley;
1291                 }
1292                 if (blurstring[0])
1293                 {
1294                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(blurstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1295                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1296                         DrawQ_String(fps_x, fps_y, blurstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1297                         fps_y += fps_scaley;
1298                 }
1299                 if (texstring[0])
1300                 {
1301                         fps_x = vid_conwidth.integer - DrawQ_TextWidth(texstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1302                         DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1303                         DrawQ_String(fps_x, fps_y, texstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1304                         fps_y += fps_scaley;
1305                 }
1306         }
1307 }
1308
1309 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)
1310 {
1311         float r[5];
1312         c2 = bound(0, c2, 1);
1313         c1 = bound(0, c1, 1 - c2);
1314         r[0] = 0;
1315         r[1] = rangey + rangeheight * (c2 + c1);
1316         r[2] = rangey + rangeheight * (c2);
1317         r[3] = rangey;
1318         r[4] = height;
1319         if (r[1] > r[0])
1320                 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);
1321         if (r[2] > r[1])
1322                 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);
1323         if (r[3] > r[2])
1324                 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);
1325         if (r[4] > r[3])
1326                 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);
1327 }
1328
1329 /*
1330 ===============
1331 Sbar_Draw
1332 ===============
1333 */
1334 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1335 extern cvar_t v_kicktime;
1336 void Sbar_Score (int margin);
1337 void Sbar_Draw (void)
1338 {
1339         cachepic_t *pic;
1340
1341         if(cl.csqc_vidvars.drawenginesbar)      //[515]: csqc drawsbar
1342         {
1343                 if (sb_showscores)
1344                         Sbar_DrawScoreboard ();
1345                 else if (cl.intermission == 1)
1346                 {
1347                         if(gamemode == GAME_NEXUIZ) // display full scoreboard (that is, show scores + map name)
1348                         {
1349                                 Sbar_DrawScoreboard();
1350                                 return;
1351                         }
1352                         Sbar_IntermissionOverlay();
1353                 }
1354                 else if (cl.intermission == 2)
1355                         Sbar_FinaleOverlay();
1356                 else if (gamemode == GAME_DELUXEQUAKE)
1357                 {
1358                 }
1359                 else if (gamemode == GAME_SOM)
1360                 {
1361                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1362                                 Sbar_DrawScoreboard ();
1363                         else if (sb_lines)
1364                         {
1365                                 // this is the top left of the sbar area
1366                                 sbar_x = 0;
1367                                 sbar_y = vid_conheight.integer - 24*3;
1368
1369                                 // armor
1370                                 if (cl.stats[STAT_ARMOR])
1371                                 {
1372                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1373                                                 Sbar_DrawPic(0, 0, somsb_armor[2]);
1374                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1375                                                 Sbar_DrawPic(0, 0, somsb_armor[1]);
1376                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1377                                                 Sbar_DrawPic(0, 0, somsb_armor[0]);
1378                                         Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1379                                 }
1380
1381                                 // health
1382                                 Sbar_DrawPic(0, 24, somsb_health);
1383                                 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1384
1385                                 // ammo icon
1386                                 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1387                                         Sbar_DrawPic(0, 48, somsb_ammo[0]);
1388                                 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1389                                         Sbar_DrawPic(0, 48, somsb_ammo[1]);
1390                                 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1391                                         Sbar_DrawPic(0, 48, somsb_ammo[2]);
1392                                 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1393                                         Sbar_DrawPic(0, 48, somsb_ammo[3]);
1394                                 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1395                                 if (cl.stats[STAT_SHELLS])
1396                                         Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1397                         }
1398                 }
1399                 else if (gamemode == GAME_NEXUIZ)
1400                 {
1401                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1402                         {
1403                                 sbar_x = (vid_conwidth.integer - 640)/2;
1404                                 sbar_y = vid_conheight.integer - 47;
1405                                 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1406                                 Sbar_DrawScoreboard ();
1407                         }
1408                         else if (sb_lines && sbar_hudselector.integer == 1)
1409                         {
1410                                 int i;
1411                                 float fade;
1412                                 int redflag, blueflag;
1413                                 float x;
1414
1415                                 sbar_x = (vid_conwidth.integer - 320)/2;
1416                                 sbar_y = vid_conheight.integer - 24 - 16;
1417
1418                                 // calculate intensity to draw weapons bar at
1419                                 fade = 3.2 - 2 * (cl.time - cl.weapontime);
1420                                 fade = bound(0.7, fade, 1);
1421                                 for (i = 0; i < 8;i++)
1422                                         if (cl.stats[STAT_ITEMS] & (1 << i))
1423                                                 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1424                                 if((cl.stats[STAT_ITEMS] & (1<<12)))
1425                                         Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1426
1427                                 // flag icons
1428                                 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1429                                 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1430                                 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1431                                 if (redflag == 3 && blueflag == 3)
1432                                 {
1433                                         // The Impossible Combination[tm]
1434                                         // Can only happen in Key Hunt mode...
1435                                         Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[14]);
1436                                 }
1437                                 else
1438                                 {
1439                                         if (redflag)
1440                                                 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 64)), sb_items[redflag+10]);
1441                                         if (blueflag)
1442                                                 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[blueflag+14]);
1443                                 }
1444
1445                                 // armor
1446                                 if (cl.stats[STAT_ARMOR] > 0)
1447                                 {
1448                                         Sbar_DrawStretchPic (72, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
1449                                         if(cl.stats[STAT_ARMOR] > 200)
1450                                                 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0,1,0,1,0);
1451                                         else if(cl.stats[STAT_ARMOR] > 100)
1452                                                 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.2,1,0.2,1,0);
1453                                         else if(cl.stats[STAT_ARMOR] > 50)
1454                                                 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.6,0.7,0.8,1,0);
1455                                         else if(cl.stats[STAT_ARMOR] > 25)
1456                                                 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,1,1,0.2,1,0);
1457                                         else
1458                                                 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.7,0,0,1,0);
1459                                 }
1460
1461                                 // health
1462                                 if (cl.stats[STAT_HEALTH] != 0)
1463                                 {
1464                                         Sbar_DrawStretchPic (184, 0, sb_health, sbar_alpha_fg.value, 24, 24);
1465                                         if(cl.stats[STAT_HEALTH] > 200)
1466                                                 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0,1,0,1,0);
1467                                         else if(cl.stats[STAT_HEALTH] > 100)
1468                                                 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.2,1,0.2,1,0);
1469                                         else if(cl.stats[STAT_HEALTH] > 50)
1470                                                 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1471                                         else if(cl.stats[STAT_HEALTH] > 25)
1472                                                 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,1,1,0.2,1,0);
1473                                         else
1474                                                 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1475                                 }
1476
1477                                 // ammo
1478                                 if ((cl.stats[STAT_ITEMS] & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || cl.stats[STAT_AMMO] != 0)
1479                                 {
1480                                         if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1481                                                 Sbar_DrawStretchPic (296, 0, sb_ammo[0], sbar_alpha_fg.value, 24, 24);
1482                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1483                                                 Sbar_DrawStretchPic (296, 0, sb_ammo[1], sbar_alpha_fg.value, 24, 24);
1484                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1485                                                 Sbar_DrawStretchPic (296, 0, sb_ammo[2], sbar_alpha_fg.value, 24, 24);
1486                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1487                                                 Sbar_DrawStretchPic (296, 0, sb_ammo[3], sbar_alpha_fg.value, 24, 24);
1488                                         if(cl.stats[STAT_AMMO] > 10)
1489                                                 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.6,0.7,0.8,1,0);
1490                                         else
1491                                                 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.7,0,0,1,0);
1492                                 }
1493
1494                                 if (sbar_x + 320 + 160 <= vid_conwidth.integer)
1495                                         Sbar_MiniDeathmatchOverlay (sbar_x + 320, sbar_y);
1496                                 if (sbar_x > 0)
1497                                         Sbar_Score(16);
1498                                         // The margin can be at most 8 to support 640x480 console size:
1499                                         //   320 + 2 * (144 + 16) = 640
1500                         }
1501                         else if (sb_lines)
1502                         {
1503                                 int i;
1504                                 float fade;
1505                                 int redflag, blueflag;
1506                                 float x;
1507
1508                                 sbar_x = (vid_conwidth.integer - 640)/2;
1509                                 sbar_y = vid_conheight.integer - 47;
1510
1511                                 // calculate intensity to draw weapons bar at
1512                                 fade = 3 - 2 * (cl.time - cl.weapontime);
1513                                 if (fade > 0)
1514                                 {
1515                                         fade = min(fade, 1);
1516                                         for (i = 0; i < 8;i++)
1517                                                 if (cl.stats[STAT_ITEMS] & (1 << i))
1518                                                         Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1519
1520                                         if((cl.stats[STAT_ITEMS] & (1<<12)))
1521                                                 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1522                                 }
1523
1524                                 //if (!cl.islocalgame)
1525                                 //      Sbar_DrawFrags ();
1526
1527                                 if (sb_lines > 24)
1528                                         Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1529                                 else
1530                                         Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1531
1532                                 // flag icons
1533                                 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1534                                 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1535                                 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1536                                 if (redflag == 3 && blueflag == 3)
1537                                 {
1538                                         // The Impossible Combination[tm]
1539                                         // Can only happen in Key Hunt mode...
1540                                         Sbar_DrawPic ((int) x, -179, sb_items[14]);
1541                                 }
1542                                 else
1543                                 {
1544                                         if (redflag)
1545                                                 Sbar_DrawPic ((int) x, -117, sb_items[redflag+10]);
1546                                         if (blueflag)
1547                                                 Sbar_DrawPic ((int) x, -177, sb_items[blueflag+14]);
1548                                 }
1549
1550                                 // armor
1551                                 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1552
1553                                 // health
1554                                 if(cl.stats[STAT_HEALTH] > 100)
1555                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1556                                 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1557                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1558                                 else
1559                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1560
1561                                 // AK dont draw ammo for the laser
1562                                 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1563                                 {
1564                                         if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1565                                                 Sbar_DrawPic (519, 0, sb_ammo[0]);
1566                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1567                                                 Sbar_DrawPic (519, 0, sb_ammo[1]);
1568                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1569                                                 Sbar_DrawPic (519, 0, sb_ammo[2]);
1570                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1571                                                 Sbar_DrawPic (519, 0, sb_ammo[3]);
1572
1573                                         if(cl.stats[STAT_AMMO] <= 10)
1574                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1575                                         else
1576                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1577
1578                                 }
1579
1580                                 if (sb_lines > 24)
1581                                         DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1582
1583                                 if (sbar_x + 600 + 160 <= vid_conwidth.integer)
1584                                         Sbar_MiniDeathmatchOverlay (sbar_x + 600, sbar_y);
1585
1586                                 if (sbar_x > 0)
1587                                         Sbar_Score(-16);
1588                                         // Because:
1589                                         //   Mini scoreboard uses 12*4 per other team, that is, 144
1590                                         //   pixels when there are four teams...
1591                                         //   Nexuiz by default sets vid_conwidth to 800... makes
1592                                         //   sbar_x == 80...
1593                                         //   so we need to shift it by 64 pixels to the right to fit
1594                                         //   BUT: then it overlaps with the image that gets drawn
1595                                         //   for viewsize 100! Therefore, just account for 3 teams,
1596                                         //   that is, 96 pixels mini scoreboard size, needing 16 pixels
1597                                         //   to the right!
1598                         }
1599                 }
1600                 else if (gamemode == GAME_ZYMOTIC)
1601                 {
1602 #if 1
1603                         float scale = 64.0f / 256.0f;
1604                         float kickoffset[3];
1605                         VectorClear(kickoffset);
1606                         if (v_dmg_time > 0)
1607                         {
1608                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1609                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1610                         }
1611                         sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1612                         sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1613                         // left1 16, 48 : 126 -66
1614                         // left2 16, 128 : 196 -66
1615                         // right 176, 48 : 196 -136
1616                         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);
1617                         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);
1618                         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);
1619                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1620 #else
1621                         float scale = 128.0f / 256.0f;
1622                         float healthstart, healthheight, healthstarttc, healthendtc;
1623                         float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1624                         float ammostart, ammoheight, ammostarttc, ammoendtc;
1625                         float clipstart, clipheight, clipstarttc, clipendtc;
1626                         float kickoffset[3], offset;
1627                         VectorClear(kickoffset);
1628                         if (v_dmg_time > 0)
1629                         {
1630                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1631                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1632                         }
1633                         sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1634                         sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1635                         offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1636                         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);
1637                         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);
1638                         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);
1639                         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);
1640                         healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1641                         shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1642                         healthstart = 204 - healthheight;
1643                         shieldstart = healthstart - shieldheight;
1644                         healthstarttc = healthstart * (1.0f / 256.0f);
1645                         healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1646                         shieldstarttc = shieldstart * (1.0f / 256.0f);
1647                         shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1648                         ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1649                         ammostart = 114 - ammoheight;
1650                         ammostarttc = ammostart * (1.0f / 256.0f);
1651                         ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1652                         clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1653                         clipstart = 190 - clipheight;
1654                         clipstarttc = clipstart * (1.0f / 256.0f);
1655                         clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1656                         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);
1657                         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);
1658                         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);
1659                         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);
1660                         DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1661                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1662 #endif
1663                 }
1664                 else // Quake and others
1665                 {
1666                         sbar_x = (vid_conwidth.integer - 320)/2;
1667                         sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1668                         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1669                         //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1670
1671                         if (sb_lines > 24)
1672                         {
1673                                 if (gamemode != GAME_GOODVSBAD2)
1674                                         Sbar_DrawInventory ();
1675                                 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1676                                         Sbar_DrawFrags ();
1677                         }
1678
1679                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1680                         {
1681                                 if (gamemode != GAME_GOODVSBAD2)
1682                                         Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1683                                 Sbar_DrawScoreboard ();
1684                         }
1685                         else if (sb_lines)
1686                         {
1687                                 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1688
1689                                 // keys (hipnotic only)
1690                                 //MED 01/04/97 moved keys here so they would not be overwritten
1691                                 if (gamemode == GAME_HIPNOTIC)
1692                                 {
1693                                         if (cl.stats[STAT_ITEMS] & IT_KEY1)
1694                                                 Sbar_DrawPic (209, 3, sb_items[0]);
1695                                         if (cl.stats[STAT_ITEMS] & IT_KEY2)
1696                                                 Sbar_DrawPic (209, 12, sb_items[1]);
1697                                 }
1698                                 // armor
1699                                 if (gamemode != GAME_GOODVSBAD2)
1700                                 {
1701                                         if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1702                                         {
1703                                                 Sbar_DrawNum (24, 0, 666, 3, 1);
1704                                                 Sbar_DrawPic (0, 0, sb_disc);
1705                                         }
1706                                         else
1707                                         {
1708                                                 if (gamemode == GAME_ROGUE)
1709                                                 {
1710                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1711                                                         if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1712                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1713                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1714                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1715                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1716                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1717                                                 }
1718                                                 else
1719                                                 {
1720                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1721                                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1722                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1723                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1724                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1725                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1726                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1727                                                 }
1728                                         }
1729                                 }
1730
1731                                 // face
1732                                 Sbar_DrawFace ();
1733
1734                                 // health
1735                                 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1736
1737                                 // ammo icon
1738                                 if (gamemode == GAME_ROGUE)
1739                                 {
1740                                         if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1741                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1742                                         else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1743                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1744                                         else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1745                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1746                                         else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1747                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1748                                         else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1749                                                 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1750                                         else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1751                                                 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1752                                         else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1753                                                 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1754                                 }
1755                                 else
1756                                 {
1757                                         if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1758                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1759                                         else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1760                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1761                                         else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1762                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1763                                         else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1764                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1765                                 }
1766
1767                                 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1768
1769                                 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1770                                 if ((!cl.islocalgame || cl.gametype != GAME_COOP))
1771                                 {
1772                                         if (gamemode == GAME_TRANSFUSION)
1773                                                 Sbar_MiniDeathmatchOverlay (0, 0);
1774                                         else
1775                                                 Sbar_MiniDeathmatchOverlay (sbar_x + 324, vid_conheight.integer - 8*8);
1776                                         Sbar_Score(24);
1777                                 }
1778                         }
1779                 }
1780         }
1781
1782         if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value)
1783         {
1784                 pic = Draw_CachePic (va("gfx/crosshair%i", crosshair.integer));
1785                 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);
1786         }
1787
1788         if (cl_prydoncursor.integer > 0)
1789                 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)), 0, 0, 1, 1, 1, 1, 0);
1790 }
1791
1792 //=============================================================================
1793
1794 /*
1795 ==================
1796 Sbar_DeathmatchOverlay
1797
1798 ==================
1799 */
1800 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1801 {
1802         int minutes;
1803         qboolean myself = false;
1804         unsigned char *c;
1805         minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1806
1807         if((s - cl.scores) == cl.playerentity - 1)
1808                 myself = true;
1809         if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1810                 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1811                         myself = true;
1812
1813         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1814         {
1815                 if (s->qw_spectator)
1816                 {
1817                         if (s->qw_ping || s->qw_packetloss)
1818                                 DrawQ_String(x, y, va("%4i %3i %4i spectator  %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1819                         else
1820                                 DrawQ_String(x, y, va("         %4i spectator  %c%s", minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1821                 }
1822                 else
1823                 {
1824                         // draw colors behind score
1825                         //
1826                         //
1827                         //
1828                         //
1829                         //
1830                         c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1831                         DrawQ_Fill(x + 14*8*FONT_SBAR->maxwidth, y+1, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1832                         c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1833                         DrawQ_Fill(x + 14*8*FONT_SBAR->maxwidth, y+4, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1834                         // print the text
1835                         //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
1836                         if (s->qw_ping || s->qw_packetloss)
1837                                 DrawQ_String(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 : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1838                         else
1839                                 DrawQ_String(x, y, va("         %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1840                 }
1841         }
1842         else
1843         {
1844                 if (s->qw_spectator)
1845                 {
1846                         if (s->qw_ping || s->qw_packetloss)
1847                                 DrawQ_String(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1848                         else
1849                                 DrawQ_String(x, y, va("         spect %c%s", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1850                 }
1851                 else
1852                 {
1853                         // draw colors behind score
1854                         c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1855                         DrawQ_Fill(x + 9*8*FONT_SBAR->maxwidth, y+1, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1856                         c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1857                         DrawQ_Fill(x + 9*8*FONT_SBAR->maxwidth, y+4, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1858                         // print the text
1859                         //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
1860                         if (s->qw_ping || s->qw_packetloss)
1861                                 DrawQ_String(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1862                         else
1863                                 DrawQ_String(x, y, va("         %5i %c%s", (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1864                 }
1865         }
1866         return 8;
1867 }
1868
1869 void Sbar_DeathmatchOverlay (void)
1870 {
1871         int i, y, xmin, xmax, ymin, ymax;
1872
1873         // request new ping times every two second
1874         if (cl.last_ping_request < realtime - 2 && cls.netcon)
1875         {
1876                 cl.last_ping_request = realtime;
1877                 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1878                 {
1879                         MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1880                         MSG_WriteString(&cls.netcon->message, "pings");
1881                 }
1882                 else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || 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*/)
1883                 {
1884                         // 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
1885                         static int ping_anyway_counter = 0;
1886                         if(cl.parsingtextexpectingpingforscores == 1)
1887                         {
1888                                 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1889                                 if(++ping_anyway_counter >= 5)
1890                                         cl.parsingtextexpectingpingforscores = 0;
1891                         }
1892                         if(cl.parsingtextexpectingpingforscores != 1)
1893                         {
1894                                 ping_anyway_counter = 0;
1895                                 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1896                                 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1897                                 MSG_WriteString(&cls.netcon->message, "ping");
1898                         }
1899                 }
1900                 else
1901                 {
1902                         // newer server definitely has pings command, so use it for more efficiency, avoids ping reports spamming the console if they are misparsed, and saves a little bandwidth
1903                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1904                         MSG_WriteString(&cls.netcon->message, "pings");
1905                 }
1906         }
1907
1908         // scores
1909         Sbar_SortFrags ();
1910
1911         ymin = 8;
1912         ymax = 40 + 8 + (Sbar_IsTeammatch() ? (teamlines * 8 + 5): 0) + scoreboardlines * 8 - 1;
1913
1914         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1915                 xmin = (int) (vid_conwidth.integer - (26 + 15) * 8 * FONT_SBAR->maxwidth) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1916         else
1917                 xmin = (int) (vid_conwidth.integer - (16 + 25) * 8 * FONT_SBAR->maxwidth) / 2; // 16 characters until name, then we assume 25 character names (they can be longer but usually aren't)
1918         xmax = vid_conwidth.integer - xmin;
1919
1920         if(gamemode == GAME_NEXUIZ)
1921                 DrawQ_Pic (xmin - 8, ymin - 8, 0, xmax-xmin+1 + 2*8, ymax-ymin+1 + 2*8, 0, 0, 0, sbar_alpha_bg.value, 0);
1922
1923         DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1924
1925         // draw the text
1926         y = 40;
1927         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1928         {
1929                 DrawQ_String(xmin, y, va("ping pl%% time frags team  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1930         }
1931         else
1932         {
1933                 DrawQ_String(xmin, y, va("ping pl%% frags  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1934         }
1935         y += 8;
1936
1937         if (Sbar_IsTeammatch ())
1938         {
1939                 // show team scores first
1940                 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1941                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), xmin, y);
1942                 y += 5;
1943         }
1944
1945         for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1946                 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], xmin, y);
1947 }
1948
1949 /*
1950 ==================
1951 Sbar_MiniDeathmatchOverlay
1952
1953 ==================
1954 */
1955 void Sbar_MiniDeathmatchOverlay (int x, int y)
1956 {
1957         int i, j, numlines, range_begin, range_end, myteam, teamsep;
1958
1959         // do not draw this if sbar_miniscoreboard_size is zero
1960         if(sbar_miniscoreboard_size.value == 0)
1961                 return;
1962         // adjust the given y if sbar_miniscoreboard_size doesn't indicate default (< 0)
1963         if(sbar_miniscoreboard_size.value > 0)
1964                 y = (int) (vid_conheight.integer - sbar_miniscoreboard_size.value * 8);
1965
1966         // scores
1967         Sbar_SortFrags ();
1968
1969         // decide where to print
1970         if (gamemode == GAME_TRANSFUSION)
1971                 numlines = (vid_conwidth.integer - x + 127) / 128;
1972         else
1973                 numlines = (vid_conheight.integer - y + 7) / 8;
1974
1975         // give up if there isn't room
1976         if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1977                 return;
1978
1979         //find us
1980         for (i = 0; i < scoreboardlines; i++)
1981                 if (fragsort[i] == cl.playerentity - 1)
1982                         break;
1983
1984         range_begin = 0;
1985         range_end = scoreboardlines;
1986         teamsep = 0;
1987
1988         if (gamemode != GAME_TRANSFUSION)
1989                 if (Sbar_IsTeammatch ())
1990                 {
1991                         // reserve space for the team scores
1992                         numlines -= teamlines;
1993
1994                         // find first and last player of my team (only draw the team totals and my own team)
1995                         range_begin = range_end = i;
1996                         myteam = cl.scores[fragsort[i]].colors & 15;
1997                         while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1998                                 --range_begin;
1999                         while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
2000                                 ++range_end;
2001
2002                         // looks better than two players
2003                         if(numlines == 2)
2004                         {
2005                                 teamsep = 8;
2006                                 numlines = 1;
2007                         }
2008                 }
2009
2010         // figure out start
2011         i -= numlines/2;
2012         i = min(i, range_end - numlines);
2013         i = max(i, range_begin);
2014
2015         if (gamemode == GAME_TRANSFUSION)
2016         {
2017                 for (;i < range_end && x < vid_conwidth.integer;i++)
2018                         x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
2019         }
2020         else
2021         {
2022                 if(range_end - i < numlines) // won't draw to bottom?
2023                         y += 8 * (numlines - (range_end - i)); // bottom align
2024                 // show team scores first
2025                 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
2026                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
2027                 y += teamsep;
2028                 for (;i < range_end && y < vid_conheight.integer;i++)
2029                         y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
2030         }
2031 }
2032
2033 int Sbar_TeamColorCompare(const void *t1_, const void *t2_)
2034 {
2035         static int const sortorder[16] =
2036         {
2037                 1001,
2038                 1002,
2039                 1003,
2040                 1004,
2041                 1, // red
2042                 1005,
2043                 1006,
2044                 1007,
2045                 1008,
2046                 4, // pink
2047                 1009,
2048                 1010,
2049                 3, // yellow
2050                 2, // blue
2051                 1011,
2052                 1012
2053         };
2054         const scoreboard_t *t1 = *(scoreboard_t **) t1_;
2055         const scoreboard_t *t2 = *(scoreboard_t **) t2_;
2056         int tc1 = sortorder[t1->colors & 15];
2057         int tc2 = sortorder[t2->colors & 15];
2058         return tc1 - tc2;
2059 }
2060
2061 void Sbar_Score (int margin)
2062 {
2063         int i, me, score, otherleader, place, distribution, minutes, seconds;
2064         double timeleft;
2065         int sbar_x_save = sbar_x;
2066         int sbar_y_save = sbar_y;
2067
2068
2069         sbar_y = (int) (vid_conheight.value - (32+12));
2070         sbar_x -= margin;
2071
2072         me = cl.playerentity - 1;
2073         if (sbar_scorerank.integer && me >= 0 && me < cl.maxclients)
2074         {
2075                 if(Sbar_IsTeammatch())
2076                 {
2077                         // Layout:
2078                         //
2079                         //   team1 team3 team4
2080                         //
2081                         //         TEAM2
2082
2083                         scoreboard_t *teamcolorsort[16];
2084
2085                         Sbar_SortFrags();
2086                         for(i = 0; i < teamlines; ++i)
2087                                 teamcolorsort[i] = &(teams[i]);
2088
2089                         // Now sort them by color
2090                         qsort(teamcolorsort, teamlines, sizeof(*teamcolorsort), Sbar_TeamColorCompare);
2091
2092                         // : margin
2093                         // -12*4: four digits space
2094                         place = (teamlines - 1) * (-12 * 4);
2095
2096                         for(i = 0; i < teamlines; ++i)
2097                         {
2098                                 int cindex = teamcolorsort[i]->colors & 15;
2099                                 unsigned char *c = palette_rgb_shirtscoreboard[cindex];
2100                                 float cm = max(max(c[0], c[1]), c[2]);
2101                                 float cr = c[0] / cm;
2102                                 float cg = c[1] / cm;
2103                                 float cb = c[2] / cm;
2104                                 if(cindex == (cl.scores[cl.playerentity - 1].colors & 15)) // my team
2105                                 {
2106                                         Sbar_DrawXNum(-32*4, 0, teamcolorsort[i]->frags, 4, 32, cr, cg, cb, 1, 0);
2107                                 }
2108                                 else // other team
2109                                 {
2110                                         Sbar_DrawXNum(place, -12, teamcolorsort[i]->frags, 4, 12, cr, cg, cb, 1, 0);
2111                                         place += 4 * 12;
2112                                 }
2113                         }
2114                 }
2115                 else
2116                 {
2117                         // Layout:
2118                         //
2119                         //   leading  place
2120                         //
2121                         //        FRAGS
2122                         //
2123                         // find leading score other than ourselves, to calculate distribution
2124                         // find our place in the scoreboard
2125                         score = cl.scores[me].frags;
2126                         for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
2127                         {
2128                                 if (cl.scores[i].name[0] && i != me)
2129                                 {
2130                                         if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
2131                                                 otherleader = i;
2132                                         if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
2133                                                 place++;
2134                                 }
2135                         }
2136                         distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
2137                         if (place == 1)
2138                                 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 1, 1, 0);
2139                         else if (place == 2)
2140                                 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 0, 1, 0);
2141                         else
2142                                 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 0, 0, 1, 0);
2143                         if (otherleader < 0)
2144                                 Sbar_DrawXNum(-32*4,   0, score, 4, 32, 1, 1, 1, 1, 0);
2145                         if (distribution >= 0)
2146                         {
2147                                 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
2148                                 Sbar_DrawXNum(-32*4,   0, score, 4, 32, 1, 1, 1, 1, 0);
2149                         }
2150                         else if (distribution >= -5)
2151                         {
2152                                 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
2153                                 Sbar_DrawXNum(-32*4,   0, score, 4, 32, 1, 1, 0, 1, 0);
2154                         }
2155                         else
2156                         {
2157                                 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
2158                                 Sbar_DrawXNum(-32*4,   0, score, 4, 32, 1, 0, 0, 1, 0);
2159                         }
2160                 }
2161         }
2162
2163         if (sbar_gametime.integer && cl.statsf[STAT_TIMELIMIT])
2164         {
2165                 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
2166                 minutes = (int)floor(timeleft / 60);
2167                 seconds = (int)(floor(timeleft) - minutes * 60);
2168                 if (minutes >= 5)
2169                 {
2170                         Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
2171                         if(sb_colon && sb_colon->tex != r_texture_notexture)
2172                                 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2173                         Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2174                 }
2175                 else if (minutes >= 1)
2176                 {
2177                         Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 0, 1, 0);
2178                         if(sb_colon && sb_colon->tex != r_texture_notexture)
2179                                 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 0, sbar_alpha_fg.value, 0);
2180                         Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
2181                 }
2182                 else if ((int)(timeleft * 4) & 1)
2183                         Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2184                 else
2185                         Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
2186         }
2187         else if (sbar_gametime.integer)
2188         {
2189                 minutes = (int)floor(cl.time / 60);
2190                 seconds = (int)(floor(cl.time) - minutes * 60);
2191                 Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
2192                 if(sb_colon && sb_colon->tex != r_texture_notexture)
2193                         DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2194                 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2195         }
2196
2197         sbar_x = sbar_x_save;
2198         sbar_y = sbar_y_save;
2199 }
2200
2201 /*
2202 ==================
2203 Sbar_IntermissionOverlay
2204
2205 ==================
2206 */
2207 void Sbar_IntermissionOverlay (void)
2208 {
2209         int             dig;
2210         int             num;
2211
2212         if (cl.gametype == GAME_DEATHMATCH)
2213         {
2214                 Sbar_DeathmatchOverlay ();
2215                 return;
2216         }
2217
2218         sbar_x = (vid_conwidth.integer - 320) >> 1;
2219         sbar_y = (vid_conheight.integer - 200) >> 1;
2220
2221         DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2222         DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2223
2224 // time
2225         dig = (int)cl.completed_time / 60;
2226         Sbar_DrawNum (160, 64, dig, 3, 0);
2227         num = (int)cl.completed_time - dig*60;
2228         Sbar_DrawPic (234,64,sb_colon);
2229         Sbar_DrawPic (246,64,sb_nums[0][num/10]);
2230         Sbar_DrawPic (266,64,sb_nums[0][num%10]);
2231
2232 // LA: Display as "a" instead of "a/b" if b is 0
2233         if(cl.stats[STAT_TOTALSECRETS])
2234         {
2235                 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
2236                 if (gamemode != GAME_NEXUIZ)
2237                         Sbar_DrawPic (232, 104, sb_slash);
2238                 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
2239         }
2240         else
2241         {
2242                 Sbar_DrawNum (240, 104, cl.stats[STAT_SECRETS], 3, 0);
2243         }
2244
2245         if(cl.stats[STAT_TOTALMONSTERS])
2246         {
2247                 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
2248                 if (gamemode != GAME_NEXUIZ)
2249                         Sbar_DrawPic (232, 144, sb_slash);
2250                 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
2251         }
2252         else
2253         {
2254                 Sbar_DrawNum (240, 144, cl.stats[STAT_MONSTERS], 3, 0);
2255         }
2256 }
2257
2258
2259 /*
2260 ==================
2261 Sbar_FinaleOverlay
2262
2263 ==================
2264 */
2265 void Sbar_FinaleOverlay (void)
2266 {
2267         DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2268 }
2269