]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sbar.c
another patch from div0 to improve ping parsing behavior in the event that multiple...
[xonotic/darkplaces.git] / sbar.c
diff --git a/sbar.c b/sbar.c
index e3445d85197ee012baa7f52becf8b37703241f9f..809c6044a0b24762fe97d953150e0396003f8aa8 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -96,6 +96,12 @@ cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the s
 
 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"};
+
 void Sbar_MiniDeathmatchOverlay (int x, int y);
 void Sbar_DeathmatchOverlay (void);
 void Sbar_IntermissionOverlay (void);
@@ -167,6 +173,13 @@ void sbar_start(void)
                sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
                sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
 
+               sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken", true);
+               sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost", true);
+               sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying", true);
+               sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken", true);
+               sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost", true);
+               sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying", true);
+
                sb_sbar = Draw_CachePic("gfx/sbar", true);
                sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
                sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
@@ -337,16 +350,22 @@ 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 (&showtime);
-       Cvar_RegisterVariable (&showtime_format);
-       Cvar_RegisterVariable (&showdate);
-       Cvar_RegisterVariable (&showdate_format);
-       Cvar_RegisterVariable (&sbar_alpha_bg);
-       Cvar_RegisterVariable (&sbar_alpha_fg);
-       Cvar_RegisterVariable (&cl_deathscoreboard);
+       Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
+       Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
+       Cvar_RegisterVariable(&showfps);
+       Cvar_RegisterVariable(&showtime);
+       Cvar_RegisterVariable(&showtime_format);
+       Cvar_RegisterVariable(&showdate);
+       Cvar_RegisterVariable(&showdate_format);
+       Cvar_RegisterVariable(&sbar_alpha_bg);
+       Cvar_RegisterVariable(&sbar_alpha_fg);
+       Cvar_RegisterVariable(&cl_deathscoreboard);
+
+       Cvar_RegisterVariable(&crosshair_color_red);
+       Cvar_RegisterVariable(&crosshair_color_green);
+       Cvar_RegisterVariable(&crosshair_color_blue);
+       Cvar_RegisterVariable(&crosshair_color_alpha);
+       Cvar_RegisterVariable(&crosshair_size);
 
        R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
 }
@@ -541,19 +560,30 @@ void Sbar_SortFrags (void)
                {
                        if (color != (cl.scores[fragsort[i]].colors & 15))
                        {
+                               const char* teamname;
+
                                color = cl.scores[fragsort[i]].colors & 15;
                                teamlines++;
 
-                               if (color == 4)
-                                       strcpy(teams[teamlines-1].name, "^1Red Team");
-                               else if (color == 13)
-                                       strcpy(teams[teamlines-1].name, "^4Blue Team");
-                               else if (color == 9)
-                                       strcpy(teams[teamlines-1].name, "^6Pink Team");
-                               else if (color == 12)
-                                       strcpy(teams[teamlines-1].name, "^3Yellow Team");
-                               else
-                                       strcpy(teams[teamlines-1].name, "Total Team Score");
+                               switch (color)
+                               {
+                                       case 4:
+                                               teamname = "^1Red Team";
+                                               break;
+                                       case 13:
+                                               teamname = "^4Blue Team";
+                                               break;
+                                       case 9:
+                                               teamname = "^6Pink Team";
+                                               break;
+                                       case 12:
+                                               teamname = "^3Yellow Team";
+                                               break;
+                                       default:
+                                               teamname = "Total Team Score";
+                                               break;
+                               }
+                               strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
 
                                teams[teamlines-1].frags = 0;
                                teams[teamlines-1].colors = color + 16 * color;
@@ -630,7 +660,9 @@ Sbar_DrawScoreboard
 void Sbar_DrawScoreboard (void)
 {
        Sbar_SoloScoreboard ();
-       if (cl.gametype == GAME_DEATHMATCH)
+       // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
+       //if (cl.gametype == GAME_DEATHMATCH)
+       if (!cl.islocalgame)
                Sbar_DeathmatchOverlay ();
 }
 
@@ -935,7 +967,7 @@ void Sbar_ShowFPS(void)
                {
                        framerate = framecount / (newtime - lasttime);
                        lasttime = newtime;
-                       nexttime = max(nexttime + 0.1, lasttime - 0.1);
+                       nexttime = max(nexttime + 1, lasttime - 1);
                        framecount = 0;
                }
                framecount++;
@@ -1014,6 +1046,8 @@ extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
 extern cvar_t v_kicktime;
 void Sbar_Draw (void)
 {
+       cachepic_t *pic;
+
        if(cl.csqc_vidvars.drawenginesbar)      //[515]: csqc drawsbar
        {
                if (cl.intermission == 1)
@@ -1085,6 +1119,7 @@ void Sbar_Draw (void)
                                int i;
                                double time;
                                float fade;
+                               int redflag, blueflag;
 
                                // we have a max time 2s (min time = 0)
                                if ((time = cl.time - cl.weapontime) < 2)
@@ -1107,14 +1142,13 @@ void Sbar_Draw (void)
                                else
                                        Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
 
-                               // special items
-                               if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
-                               {
-                                       // Nexuiz has no anum pics
-                                       //Sbar_DrawNum (36, 0, 666, 3, 1);
-                                       // Nexuiz has no disc pic
-                                       //Sbar_DrawPic (0, 0, sb_disc);
-                               }
+                               // flag icons
+                               redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
+                               if (redflag)
+                                       Sbar_DrawPic (10, -85, sb_items[redflag+10]);
+                               blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
+                               if (blueflag)
+                                       Sbar_DrawPic (10, -145, sb_items[blueflag+14]);
 
                                // armor
                                Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
@@ -1220,7 +1254,9 @@ void Sbar_Draw (void)
                else // Quake and others
                {
                        sbar_y = vid_conheight.integer - SBAR_HEIGHT;
-                       if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
+                       // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
+                       //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
+                       if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
                                sbar_x = 0;
                        else
                                sbar_x = (vid_conwidth.integer - 320)/2;
@@ -1325,7 +1361,9 @@ void Sbar_Draw (void)
 
                        }
 
-                       if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
+                       // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
+                       //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
+                       if (!cl.islocalgame && vid_conwidth.integer > 320)
                        {
                                if (gamemode == GAME_TRANSFUSION)
                                        Sbar_MiniDeathmatchOverlay (0, 0);
@@ -1337,8 +1375,8 @@ void Sbar_Draw (void)
 
        Sbar_ShowFPS();
 
-       if(cl.csqc_vidvars.drawcrosshair)
-               R_Draw2DCrosshair();
+       if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[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);
 
        if (cl_prydoncursor.integer)
                DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic(va("gfx/prydoncursor%03i", cl_prydoncursor.integer), true), 0, 0, 1, 1, 1, 1, 0);
@@ -1356,28 +1394,54 @@ float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
 {
        int minutes;
        unsigned char *c;
+       minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
        if (cls.protocol == PROTOCOL_QUAKEWORLD)
        {
-               minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : realtime - s->qw_entertime) / 60.0);
-               // draw colors behind score
-               c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
-               DrawQ_Pic(x + 14*8, y+1, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
-               c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
-               DrawQ_Pic(x + 14*8, y+4, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
-               // print the text
-               //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
-               DrawQ_ColoredString(x, y, va("%c%4i %2i %4i %4i %-4s %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+               if (s->qw_spectator)
+               {
+                       if (s->qw_ping || s->qw_packetloss)
+                               DrawQ_ColoredString(x, y, va("%4i %3i %4i spectator  %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+                       else
+                               DrawQ_ColoredString(x, y, va("         %4i spectator  %c%s", minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+               }
+               else
+               {
+                       // draw colors behind score
+                       c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
+                       DrawQ_Pic(x + 14*8, y+1, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
+                       c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
+                       DrawQ_Pic(x + 14*8, y+4, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
+                       // print the text
+                       //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
+                       if (s->qw_ping || s->qw_packetloss)
+                               DrawQ_ColoredString(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+                       else
+                               DrawQ_ColoredString(x, y, va("         %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+               }
        }
        else
        {
-               // draw colors behind score
-               c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
-               DrawQ_Pic(x + 1*8, y+1, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
-               c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
-               DrawQ_Pic(x + 1*8, y+4, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
-               // print the text
-               //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
-               DrawQ_ColoredString(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+               if (s->qw_spectator)
+               {
+                       if (s->qw_ping || s->qw_packetloss)
+                               DrawQ_ColoredString(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+                       else
+                               DrawQ_ColoredString(x, y, va("         spect %c%s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+               }
+               else
+               {
+                       // draw colors behind score
+                       c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
+                       DrawQ_Pic(x + 9*8, y+1, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
+                       c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
+                       DrawQ_Pic(x + 9*8, y+4, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
+                       // print the text
+                       //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
+                       if (s->qw_ping || s->qw_packetloss)
+                               DrawQ_ColoredString(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+                       else
+                               DrawQ_ColoredString(x, y, va("         %5i %c%s", (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+               }
        }
        return 8;
 }
@@ -1387,7 +1451,7 @@ void Sbar_DeathmatchOverlay (void)
        int i, x, y;
 
        // request new ping times every two second
-       if (cl.last_ping_request < realtime - 2)
+       if (cl.last_ping_request < realtime - 2 && cls.netcon)
        {
                cl.last_ping_request = realtime;
                if (cls.protocol == PROTOCOL_QUAKEWORLD)
@@ -1395,6 +1459,30 @@ void Sbar_DeathmatchOverlay (void)
                        MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
                        MSG_WriteString(&cls.netcon->message, "pings");
                }
+               else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6 || cls.protocol == PROTOCOL_DARKPLACES7)
+               {
+                       // 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
+                       static int ping_anyway_counter = 0;
+                       if(cl.parsingtextexpectingpingforscores == 1)
+                       {
+                               Con_DPrintf("want to send ping, but still waiting for other reply\n");
+                               if(++ping_anyway_counter >= 5)
+                                       cl.parsingtextexpectingpingforscores = 0;
+                       }
+                       if(cl.parsingtextexpectingpingforscores != 1)
+                       {
+                               ping_anyway_counter = 0;
+                               cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
+                               MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+                               MSG_WriteString(&cls.netcon->message, "ping");
+                       }
+               }
+               else
+               {
+                       // newer server definitely has pings command, so use it for more efficiency
+                       MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+                       MSG_WriteString(&cls.netcon->message, "pings");
+               }
        }
 
        DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
@@ -1402,11 +1490,18 @@ void Sbar_DeathmatchOverlay (void)
        // scores
        Sbar_SortFrags ();
        // draw the text
+       y = 40;
        if (cls.protocol == PROTOCOL_QUAKEWORLD)
-               x = (vid_conwidth.integer - (6 + 17 + 15) * 8) / 2;
+       {
+               x = (vid_conwidth.integer - (26 + 15) * 8) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't)
+               DrawQ_ColoredString(x, y, va("ping pl%% time frags team  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+       }
        else
-               x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
-       y = 40;
+       {
+               x = (vid_conwidth.integer - (16 + 15) * 8) / 2; // 16 characters until name, then we assume 15 character names (they can be longer but usually aren't)
+               DrawQ_ColoredString(x, y, va("ping pl%% frags  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+       }
+       y += 8;
 
        if (Sbar_IsTeammatch ())
        {
@@ -1476,7 +1571,9 @@ void Sbar_IntermissionOverlay (void)
        int             dig;
        int             num;
 
-       if (cl.gametype == GAME_DEATHMATCH)
+       // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
+       //if (cl.gametype == GAME_DEATHMATCH)
+       if (!cl.islocalgame)
        {
                Sbar_DeathmatchOverlay ();
                return;