]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sbar.c
Improving Doxyfile, adding GENERATE_TREEVIEW and SEARCHENGINE variable features
[xonotic/darkplaces.git] / sbar.c
diff --git a/sbar.c b/sbar.c
index 9cc3b870fb8bb4e432875b29fb50eca821a84aed..be13963350a42847b088fb9afd0c7aa9427a8ea9 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -53,7 +53,7 @@ cachepic_t *sb_face_quad;
 cachepic_t *sb_face_invuln;
 cachepic_t *sb_face_invis_invuln;
 
-qboolean sb_showscores;
+qbool sb_showscores;
 
 int sb_lines;                  // scan lines to draw
 
@@ -85,33 +85,35 @@ cachepic_t *sb_complete;
 cachepic_t *sb_inter;
 cachepic_t *sb_finale;
 
-cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
-cvar_t showsound = {CVAR_SAVE, "showsound", "0", "shows number of active sound sources, sound latency, and other statistics"};
-cvar_t showblur = {CVAR_SAVE, "showblur", "0", "shows the current alpha level of motionblur"};
-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"};
-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"};
-cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
-cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
-cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
-cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
-cvar_t showtex = {0, "showtex", "0", "shows the name of the texture on the crosshair (for map debugging)"};
-cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
-cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
-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)"};
-cvar_t sbar_scorerank = {CVAR_SAVE, "sbar_scorerank", "1", "shows an overlay for your score (or team score) and rank in the scoreboard"};
-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)"};
-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"};
-cvar_t sbar_flagstatus_right = {CVAR_SAVE, "sbar_flagstatus_right", "0", "moves Nexuiz flag status icons to the right"};
-cvar_t sbar_flagstatus_pos = {CVAR_SAVE, "sbar_flagstatus_pos", "115", "pixel position of the Nexuiz flag status icons, from the bottom"};
-cvar_t sbar_info_pos = {CVAR_SAVE, "sbar_info_pos", "0", "pixel position of the info strings (such as showfps), from the bottom"};
-
-cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
-
-cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
-cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
-cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
-cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
-cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
+cvar_t cl_showfps = {CF_CLIENT | CF_ARCHIVE, "cl_showfps", "0", "shows your rendered fps (frames per second)"};
+cvar_t cl_showsound = {CF_CLIENT | CF_ARCHIVE, "cl_showsound", "0", "shows number of active sound sources, sound latency, and other statistics"};
+cvar_t cl_showblur = {CF_CLIENT | CF_ARCHIVE, "cl_showblur", "0", "shows the current alpha level of motionblur"};
+cvar_t cl_showspeed = {CF_CLIENT | CF_ARCHIVE, "cl_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"};
+cvar_t cl_showspeed_factor = {CF_CLIENT | CF_ARCHIVE, "cl_showspeed_factor", "2.54", "multiplier of the centimeter for cl_showspeed. 1 unit = 1 inch in Quake, so this should be 2.54 for Quake, etc"};
+cvar_t cl_showtopspeed = {CF_CLIENT | CF_ARCHIVE, "cl_showtopspeed", "0", "shows your top speed (kept on screen for max 3 seconds); value -1 takes over the unit from cl_showspeed, otherwise it's an unit number just like in cl_showspeed"};
+cvar_t cl_showtime = {CF_CLIENT | CF_ARCHIVE, "cl_showtime", "0", "shows current time of day (useful on screenshots)"};
+cvar_t cl_showtime_format = {CF_CLIENT | CF_ARCHIVE, "cl_showtime_format", "%H:%M:%S", "format string for time of day"};
+cvar_t cl_showdate = {CF_CLIENT | CF_ARCHIVE, "cl_showdate", "0", "shows current date (useful on screenshots)"};
+cvar_t cl_showdate_format = {CF_CLIENT | CF_ARCHIVE, "cl_showdate_format", "%Y-%m-%d", "format string for date"};
+cvar_t cl_showtex = {CF_CLIENT, "cl_showtex", "0", "shows the name of the texture on the crosshair (for map debugging)"};
+
+cvar_t sbar_alpha_bg = {CF_CLIENT | CF_ARCHIVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
+cvar_t sbar_alpha_fg = {CF_CLIENT | CF_ARCHIVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
+cvar_t sbar_hudselector = {CF_CLIENT | CF_ARCHIVE, "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)"};
+cvar_t sbar_scorerank = {CF_CLIENT | CF_ARCHIVE, "sbar_scorerank", "1", "shows an overlay for your score (or team score) and rank in the scoreboard"};
+cvar_t sbar_gametime = {CF_CLIENT | CF_ARCHIVE, "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)"};
+cvar_t sbar_miniscoreboard_size = {CF_CLIENT | CF_ARCHIVE, "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"};
+cvar_t sbar_flagstatus_right = {CF_CLIENT | CF_ARCHIVE, "sbar_flagstatus_right", "0", "moves Nexuiz flag status icons to the right"};
+cvar_t sbar_flagstatus_pos = {CF_CLIENT | CF_ARCHIVE, "sbar_flagstatus_pos", "115", "pixel position of the Nexuiz flag status icons, from the bottom"};
+cvar_t sbar_info_pos = {CF_CLIENT | CF_ARCHIVE, "sbar_info_pos", "0", "pixel position of the info strings (such as showfps), from the bottom"};
+
+cvar_t cl_deathscoreboard = {CF_CLIENT, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
+
+cvar_t crosshair_color_red = {CF_CLIENT | CF_ARCHIVE, "crosshair_color_red", "1", "customizable crosshair color"};
+cvar_t crosshair_color_green = {CF_CLIENT | CF_ARCHIVE, "crosshair_color_green", "0", "customizable crosshair color"};
+cvar_t crosshair_color_blue = {CF_CLIENT | CF_ARCHIVE, "crosshair_color_blue", "0", "customizable crosshair color"};
+cvar_t crosshair_color_alpha = {CF_CLIENT | CF_ARCHIVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
+cvar_t crosshair_size = {CF_CLIENT | CF_ARCHIVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
 
 static void Sbar_MiniDeathmatchOverlay (int x, int y);
 static void Sbar_DeathmatchOverlay (void);
@@ -127,7 +129,7 @@ Sbar_ShowScores
 Tab key down
 ===============
 */
-static void Sbar_ShowScores (void)
+static void Sbar_ShowScores_f(cmd_state_t *cmd)
 {
        if (sb_showscores)
                return;
@@ -142,7 +144,7 @@ Sbar_DontShowScores
 Tab key up
 ===============
 */
-static void Sbar_DontShowScores (void)
+static void Sbar_DontShowScores_f(cmd_state_t *cmd)
 {
        sb_showscores = false;
        CL_VM_UpdateShowingScoresState(sb_showscores);
@@ -161,7 +163,7 @@ static void sbar_start(void)
                for (i = 0;i < 10;i++)
                        sb_nums[0][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/num_%i",i), CACHEPICFLAG_QUIET);
                sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
-               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET);
+               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET | CACHEPICFLAG_FAILONMISSING);
 
                sb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
                sb_ammo[1] = Draw_CachePic_Flags ("gfx/sb_bullets", CACHEPICFLAG_QUIET);
@@ -219,7 +221,7 @@ static void sbar_start(void)
                sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
                sb_nums[1][10] = Draw_CachePic_Flags ("gfx/anum_minus", CACHEPICFLAG_QUIET);
 
-               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET);
+               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET | CACHEPICFLAG_FAILONMISSING);
                sb_slash = Draw_CachePic_Flags ("gfx/num_slash", CACHEPICFLAG_QUIET);
 
                sb_weapons[0][0] = Draw_CachePic_Flags ("gfx/inv_shotgun", CACHEPICFLAG_QUIET);
@@ -357,18 +359,34 @@ static void sbar_newmap(void)
 
 void Sbar_Init (void)
 {
-       Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
-       Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
-       Cvar_RegisterVariable(&showfps);
-       Cvar_RegisterVariable(&showsound);
-       Cvar_RegisterVariable(&showblur);
-       Cvar_RegisterVariable(&showspeed);
-       Cvar_RegisterVariable(&showtopspeed);
-       Cvar_RegisterVariable(&showtime);
-       Cvar_RegisterVariable(&showtime_format);
-       Cvar_RegisterVariable(&showdate);
-       Cvar_RegisterVariable(&showdate_format);
-       Cvar_RegisterVariable(&showtex);
+       if(gamemode == GAME_NORMAL) // Workaround so Quake doesn't trample on Xonotic.
+       {
+               Cmd_AddCommand(CF_CLIENT, "+showscores", Sbar_ShowScores_f, "show scoreboard");
+               Cmd_AddCommand(CF_CLIENT, "-showscores", Sbar_DontShowScores_f, "hide scoreboard");
+       }
+       Cvar_RegisterVariable(&cl_showfps);
+       Cvar_RegisterVariable(&cl_showsound);
+       Cvar_RegisterVariable(&cl_showblur);
+       Cvar_RegisterVariable(&cl_showspeed);
+       Cvar_RegisterVariable(&cl_showspeed_factor);
+       Cvar_RegisterVariable(&cl_showtopspeed);
+       Cvar_RegisterVariable(&cl_showtime);
+       Cvar_RegisterVariable(&cl_showtime_format);
+       Cvar_RegisterVariable(&cl_showdate);
+       Cvar_RegisterVariable(&cl_showdate_format);
+       Cvar_RegisterVariable(&cl_showtex);
+       
+       Cvar_RegisterVirtual(&cl_showfps, "showfps");
+       Cvar_RegisterVirtual(&cl_showsound, "showsound");
+       Cvar_RegisterVirtual(&cl_showblur, "showblur");
+       Cvar_RegisterVirtual(&cl_showspeed, "showspeed");
+       Cvar_RegisterVirtual(&cl_showtopspeed, "showtopspeed");
+       Cvar_RegisterVirtual(&cl_showtime, "showtime");
+       Cvar_RegisterVirtual(&cl_showtime_format, "showtime_format");
+       Cvar_RegisterVirtual(&cl_showdate, "showdate");
+       Cvar_RegisterVirtual(&cl_showdate_format, "showdate_format");
+       Cvar_RegisterVirtual(&cl_showtex, "showtex");
+       
        Cvar_RegisterVariable(&sbar_alpha_bg);
        Cvar_RegisterVariable(&sbar_alpha_fg);
        Cvar_RegisterVariable(&sbar_hudselector);
@@ -727,7 +745,7 @@ Sbar_DrawScoreboard
 static void Sbar_DrawScoreboard (void)
 {
        Sbar_SoloScoreboard ();
-       // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
+       // LadyHavoc: changed to draw the deathmatch overlays in any multiplayer mode
        //if (cl.gametype == GAME_DEATHMATCH)
        if (!cl.islocalgame)
                Sbar_DeathmatchOverlay ();
@@ -1032,41 +1050,29 @@ time_t topxy_time = 0;
 static void get_showspeed_unit(int unitnumber, double *conversion_factor, const char **unit)
 {
        if(unitnumber < 0)
-               unitnumber = showspeed.integer;
+               unitnumber = cl_showspeed.integer;
        switch(unitnumber)
        {
                default:
                case 1:
-                       if(IS_NEXUIZ_DERIVED(gamemode))
-                               *unit = "in/s";
-                       else
-                               *unit = "qu/s";
+                       *unit = "qu/s";
                        *conversion_factor = 1.0;
                        break;
                case 2:
                        *unit = "m/s";
-                       *conversion_factor = 0.0254;
-                       if(!IS_NEXUIZ_DERIVED(gamemode))
-                               *conversion_factor *= 1.5;
-                       // 1qu=1.5in is for non-Nexuiz/Xonotic only - Nexuiz/Xonotic players are overly large, but 1qu=1in fixes that
+                       *conversion_factor = 1.0 * cl_showspeed_factor.value * 0.01;
                        break;
                case 3:
                        *unit = "km/h";
-                       *conversion_factor = 0.0254 * 3.6;
-                       if(!IS_NEXUIZ_DERIVED(gamemode))
-                               *conversion_factor *= 1.5;
+                       *conversion_factor = 1.0 * (cl_showspeed_factor.value * 0.01) * 3.6;
                        break;
                case 4:
                        *unit = "mph";
-                       *conversion_factor = 0.0254 * 3.6 * 0.6213711922;
-                       if(!IS_NEXUIZ_DERIVED(gamemode))
-                               *conversion_factor *= 1.5;
+                       *conversion_factor = 1.0 * (cl_showspeed_factor.value * 0.01 * 3.6) * 0.6213711922;
                        break;
                case 5:
                        *unit = "knots";
-                       *conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
-                       if(!IS_NEXUIZ_DERIVED(gamemode))
-                               *conversion_factor *= 1.5;
+                       *conversion_factor = 1.0 * (cl_showspeed_factor.value * 0.01 * 3.6) * 0.539957;
                        break;
        }
 }
@@ -1079,7 +1085,7 @@ void Sbar_ShowFPS_Update(void)
 {
        double interval = 1;
        double newtime;
-       newtime = realtime;
+       newtime = host.realtime;
        if (newtime >= showfps_nexttime)
        {
                showfps_framerate = showfps_framecount / (newtime - showfps_lasttime);
@@ -1105,7 +1111,8 @@ void Sbar_ShowFPS(void)
        char blurstring[32];
        char topspeedstring[48];
        char texstring[MAX_QPATH];
-       qboolean red = false;
+       char entstring[32];
+       qbool red = false;
        soundstring[0] = 0;
        fpsstring[0] = 0;
        timedemostring1[0] = 0;
@@ -1114,12 +1121,13 @@ void Sbar_ShowFPS(void)
        datestring[0] = 0;
        speedstring[0] = 0;
        blurstring[0] = 0;
-       texstring[0] = 0;
        topspeedstring[0] = 0;
-       if (showfps.integer)
+       texstring[0] = 0;
+       entstring[0] = 0;
+       if (cl_showfps.integer)
        {
                red = (showfps_framerate < 1.0f);
-               if(showfps.integer == 2)
+               if(cl_showfps.integer == 2)
                        dpsnprintf(fpsstring, sizeof(fpsstring), "%7.3f mspf", (1000.0 / showfps_framerate));
                else if (red)
                        dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0 / showfps_framerate + 0.5));
@@ -1128,48 +1136,48 @@ void Sbar_ShowFPS(void)
                fps_strings++;
                if (cls.timedemo)
                {
-                       dpsnprintf(timedemostring1, sizeof(timedemostring1), "frame%4i %f", cls.td_frames, realtime - cls.td_starttime);
+                       dpsnprintf(timedemostring1, sizeof(timedemostring1), "frame%4i %f", cls.td_frames, host.realtime - cls.td_starttime);
                        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);
                        fps_strings++;
                        fps_strings++;
                }
        }
-       if (showtime.integer)
+       if (cl_showtime.integer)
        {
-               strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
+               strlcpy(timestring, Sys_TimeString(cl_showtime_format.string), sizeof(timestring));
                fps_strings++;
        }
-       if (showdate.integer)
+       if (cl_showdate.integer)
        {
-               strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
+               strlcpy(datestring, Sys_TimeString(cl_showdate_format.string), sizeof(datestring));
                fps_strings++;
        }
-       if (showblur.integer)
+       if (cl_showblur.integer)
        {
                dpsnprintf(blurstring, sizeof(blurstring), "%3i%% blur", (int)(cl.motionbluralpha * 100));
                fps_strings++;
        }
-       if (showsound.integer)
+       if (cl_showsound.integer)
        {
                dpsnprintf(soundstring, sizeof(soundstring), "%4i/4%i at %3ims", cls.soundstats.mixedsounds, cls.soundstats.totalsounds, cls.soundstats.latency_milliseconds);
                fps_strings++;
        }
-       if (showspeed.integer || showtopspeed.integer)
+       if (cl_showspeed.integer || cl_showtopspeed.integer)
        {
                double speed, speedxy, f;
                const char *unit;
                speed = VectorLength(cl.movement_velocity);
                speedxy = sqrt(cl.movement_velocity[0] * cl.movement_velocity[0] + cl.movement_velocity[1] * cl.movement_velocity[1]);
-               if (showspeed.integer)
+               if (cl_showspeed.integer)
                {
-                       get_showspeed_unit(showspeed.integer, &f, &unit);
+                       get_showspeed_unit(cl_showspeed.integer, &f, &unit);
                        dpsnprintf(speedstring, sizeof(speedstring), "%.0f (%.0f) %s", f*speed, f*speedxy, unit);
                        fps_strings++;
                }
-               if (showtopspeed.integer)
+               if (cl_showtopspeed.integer)
                {
-                       qboolean topspeed_latched = false, topspeedxy_latched = false;
-                       get_showspeed_unit(showtopspeed.integer, &f, &unit);
+                       qbool topspeed_latched = false, topspeedxy_latched = false;
+                       get_showspeed_unit(cl_showtopspeed.integer, &f, &unit);
                        if (speed >= topspeed || current_time - top_time > 3)
                        {
                                topspeed = speed;
@@ -1192,25 +1200,56 @@ void Sbar_ShowFPS(void)
                        fps_strings++;
                }
        }
-       if (showtex.integer)
+       if (cl_showtex.integer)
        {
                vec3_t org;
                vec3_t dest;
                vec3_t temp;
-               trace_t trace;
+               trace_t svtrace, cltrace;
+               int hitnetentity = -1;
 
                Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, org);
                VectorSet(temp, 65536, 0, 0);
                Matrix4x4_Transform(&r_refdef.view.matrix, temp, dest);
-               trace.hittexture = NULL; // to make sure
-               // TODO change this trace to be stopped by anything "visible" (i.e. with a drawsurface), but not stuff like weapclip
-               // probably needs adding a new SUPERCONTENTS type
-               trace = CL_TraceLine(org, dest, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, true, true);
-               if(trace.hittexture)
-                       strlcpy(texstring, trace.hittexture->name, sizeof(texstring));
+               // clear the traces as we may or may not fill them out, and mark them with an invalid fraction so we know if we did
+               memset(&svtrace, 0, sizeof(svtrace));
+               memset(&cltrace, 0, sizeof(cltrace));
+               svtrace.fraction = 2.0;
+               cltrace.fraction = 2.0;
+               // ray hits models (even animated ones) and ignores translucent materials
+               if (SVVM_prog != NULL)
+                       svtrace = SV_TraceLine(org, dest, MOVE_HITMODEL, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value);
+               cltrace = CL_TraceLine(org, dest, MOVE_HITMODEL, NULL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT, collision_extendmovelength.value, true, false, &hitnetentity, true, true);
+               if (cltrace.hittexture)
+                       strlcpy(texstring, cltrace.hittexture->name, sizeof(texstring));
                else
                        strlcpy(texstring, "(no texture hit)", sizeof(texstring));
                fps_strings++;
+               if (svtrace.fraction < cltrace.fraction)
+               {
+                       if (svtrace.ent != NULL)
+                       {
+                               prvm_prog_t *prog = SVVM_prog;
+                               dpsnprintf(entstring, sizeof(entstring), "server entity %i", (int)PRVM_EDICT_TO_PROG(svtrace.ent));
+                       }
+                       else
+                               strlcpy(entstring, "(no entity hit)", sizeof(entstring));
+               }
+               else
+               {
+                       if (CLVM_prog != NULL && cltrace.ent != NULL)
+                       {
+                               prvm_prog_t *prog = CLVM_prog;
+                               dpsnprintf(entstring, sizeof(entstring), "client entity %i", (int)PRVM_EDICT_TO_PROG(cltrace.ent));
+                       }
+                       else if (hitnetentity > 0)
+                               dpsnprintf(entstring, sizeof(entstring), "network entity %i", hitnetentity);
+                       else if (hitnetentity == 0)
+                               strlcpy(entstring, "world entity", sizeof(entstring));
+                       else
+                               strlcpy(entstring, "(no entity hit)", sizeof(entstring));
+               }
+               fps_strings++;
        }
        if (fps_strings)
        {
@@ -1294,6 +1333,13 @@ void Sbar_ShowFPS(void)
                        DrawQ_String(fps_x, fps_y, texstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
                        fps_y += fps_scaley;
                }
+               if (entstring[0])
+               {
+                       fps_x = vid_conwidth.integer - DrawQ_TextWidth(entstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
+                       DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
+                       DrawQ_String(fps_x, fps_y, entstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
+                       fps_y += fps_scaley;
+               }
        }
 }
 
@@ -1617,7 +1663,7 @@ void Sbar_Draw (void)
                {
                        sbar_x = (vid_conwidth.integer - 320)/2;
                        sbar_y = vid_conheight.integer - SBAR_HEIGHT;
-                       // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
+                       // LadyHavoc: changed to draw the deathmatch overlays in any multiplayer mode
                        //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
 
                        if (sb_lines > 24)
@@ -1718,7 +1764,7 @@ void Sbar_Draw (void)
 
                                Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
 
-                               // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
+                               // LadyHavoc: changed to draw the deathmatch overlays in any multiplayer mode
                                if ((!cl.islocalgame || cl.gametype != GAME_COOP))
                                {
                                        if (gamemode == GAME_TRANSFUSION)
@@ -1734,7 +1780,7 @@ void Sbar_Draw (void)
        if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value)
        {
                pic = Draw_CachePic (va(vabuf, sizeof(vabuf), "gfx/crosshair%i", crosshair.integer));
-               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);
+               DrawQ_Pic((vid_conwidth.integer - Draw_GetPicWidth(pic) * crosshair_size.value) * 0.5f, (vid_conheight.integer - Draw_GetPicHeight(pic) * crosshair_size.value) * 0.5f, pic, Draw_GetPicWidth(pic) * crosshair_size.value, Draw_GetPicHeight(pic) * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0);
        }
 
        if (cl_prydoncursor.integer > 0)
@@ -1752,7 +1798,7 @@ Sbar_DeathmatchOverlay
 static float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
 {
        int minutes;
-       qboolean myself = false;
+       qbool myself = false;
        unsigned char *c;
        char vabuf[1024];
        minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
@@ -1825,9 +1871,9 @@ void Sbar_DeathmatchOverlay (void)
        char vabuf[1024];
 
        // request new ping times every two second
-       if (cl.last_ping_request < realtime - 2 && cls.netcon)
+       if (cl.last_ping_request < host.realtime - 2 && cls.netcon)
        {
-               cl.last_ping_request = realtime;
+               cl.last_ping_request = host.realtime;
                if (cls.protocol == PROTOCOL_QUAKEWORLD)
                {
                        MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
@@ -1874,7 +1920,7 @@ void Sbar_DeathmatchOverlay (void)
        if(IS_OLDNEXUIZ_DERIVED(gamemode))
                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);
 
-       DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
+       DrawQ_Pic ((vid_conwidth.integer - Draw_GetPicWidth(sb_ranking))/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
 
        // draw the text
        y = 40;
@@ -2122,14 +2168,14 @@ void Sbar_Score (int margin)
                if (minutes >= 5)
                {
                        Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
-                       if(sb_colon && sb_colon->tex != r_texture_notexture)
+                       if (Draw_IsPicLoaded(sb_colon))
                                DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
                        Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
                }
                else if (minutes >= 1)
                {
                        Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 0, 1, 0);
-                       if(sb_colon && sb_colon->tex != r_texture_notexture)
+                       if (Draw_IsPicLoaded(sb_colon))
                                DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 0, sbar_alpha_fg.value, 0);
                        Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
                }
@@ -2143,7 +2189,7 @@ void Sbar_Score (int margin)
                minutes = (int)floor(cl.time / 60);
                seconds = (int)(floor(cl.time) - minutes * 60);
                Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
-               if(sb_colon && sb_colon->tex != r_texture_notexture)
+               if (Draw_IsPicLoaded(sb_colon))
                        DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
                Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
        }
@@ -2218,6 +2264,6 @@ Sbar_FinaleOverlay
 */
 void Sbar_FinaleOverlay (void)
 {
-       DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
+       DrawQ_Pic((vid_conwidth.integer - Draw_GetPicWidth(sb_finale))/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
 }