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