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