]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote-tracking branch 'origin/Mario/quickmenu_merge' into terencehill/quickmen...
authorterencehill <piuntn@gmail.com>
Mon, 6 Jan 2014 01:00:59 +0000 (02:00 +0100)
committerterencehill <piuntn@gmail.com>
Mon, 6 Jan 2014 01:00:59 +0000 (02:00 +0100)
1  2 
defaultXonotic.cfg
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/client/autocvars.qh
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/client/hud_config.qc
qcsrc/client/scoreboard.qc
qcsrc/common/util.qh

diff --combined defaultXonotic.cfg
index 2814738e764f9f5a21be5d55d91ffe1584246356,0849d871376923ab38d012365dc67a63c97730be..7ddd012fcab226427ef37271e4651fcced9e41e7
@@@ -141,9 -141,6 +141,9 @@@ set rpn_linear_to_sRGB "dup 1.0 2.4 di
  // q3map_skylight 9.32523632 3
  alias skybox_nosRGB_to_sRGB "rpn $3 402.123 $4 div div $rpn_sRGB_to_linear 402.123 $4 div mul /new_skylight: $3 402.123 $4 div div $1 256 div $2 0.017453 mul sin mul add $rpn_sRGB_to_linear $3 402.123 $4 div div $rpn_sRGB_to_linear sub 256 mul $2 0.017453 mul sin div /new_sunlight:"
  
 +set cl_orthoview 0 "enable top-down view of the map- meant to be used for radar map images (note: orthoview sets cvars temporarily, requires restart to return them to normal)"
 +set cl_orthoview_nofog 1 "disable fog while in orthoview-- note, should not be enabled on ALL maps, i.e. oilrig works fine with this disabled"
 +
  // these settings determine how much the view is affected by movement/damage
  cl_smoothviewheight 0.05 // time of the averaging to the viewheight value so that it creates a smooth transition for crouching and such. 0 for instant transition
  cl_deathfade 0 // fade screen to dark red when dead, value represents how fast the fade is (higher is faster)
@@@ -687,6 -684,8 +687,8 @@@ bind F11 disconnec
  bind F12 screenshot
  bind F4 ready
  bind ALT +showaccuracy
+ alias quickmenu "cl_cmd hud quickmenu"
+ bind b quickmenu
  
  // Gamepad defaults. Tested with Logitech Rumblepad 2, I hope similar ones works as well.
  bind JOY1 "+crouch"
@@@ -1192,9 -1191,32 +1194,9 @@@ set g_showweaponspawns 1       "display sprit
  //   Quake-Joule:  1 qJ  = 1 qN * 1 qu
  //   Quake-Pascal: 1 qPa = 1 qN / 1 qu^2
  
 -set g_ballistics_materialconstant 1414213562
 -set g_ballistics_mindistance 16
 +set g_ballistics_mindistance 2 // enable ballistics starting from 2 qu
  set g_ballistics_density_player 0.50 // players are 2x as easy to pass as walls
  set g_ballistics_density_corpse 0.10 // corpses are 10x as easy to pass as walls
 -// unit: qJ / qu^3 (energy needed per volume unit of solid to push/burn away
 -// parameter: bullet constant: mass / area in g/qu^2
 -// = mass / (pi/4 * caliber^2)
 -// with caliber in inches, mass in grams:
 -// = 1.273239544735163 * mass / caliber^2
 -// with caliber in inches, mass in grains:
 -// = 0.082633246453312 * mass / caliber^2
 -
 -// bullet max travel distance inside solid:
 -//   0.5 * v^2 * bulletconstant / g_ballistics_materialconstant
 -
 -// some bullet constants:
 -//   http://hypertextbook.com/facts/2000/ShantayArmstrong.shtml
 -//     second bullet: caliber .45, mass 16.2g, bullet constant 101.859163578813
 -//     third bullet: caliber .338, mass 16.2g, bullet constant 180.5476053421592
 -//     fourth bullet: caliber .25, mass 2.3g, bullet constant 46.85521524625399
 -//   http://en.wikipedia.org/wiki/.50_BMG
 -//     caliber .5, 360 grains, bullet constant 118.9918748927693
 -//   AK-47:
 -//     caliber .3, 62 grains, bullet constant 56.92512533450383
 -//   .3 winchester magnum:
 -//     caliber .3, 150 grains, bullet constant 137.7220774221867
  
  set cl_stripcolorcodes 0      "experimental feature (notes: strips ALL color codes from messages!)"
  
diff --combined qcsrc/client/Main.qc
index 3206e923c37bd2a1d284bb337db11420905cbac8,130a18c31b1d5e9b304c52ca5a1dfe2123480988..eecd478568fd790208020ef2c9d22b63182a9666
@@@ -53,7 -53,7 +53,7 @@@ void CSQC_Init(void
        check_unacceptable_compiler_bugs();
  
  #ifdef WATERMARK
 -      print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK));
 +      printf(_("^4CSQC Build information: ^1%s\n"), WATERMARK);
  #endif
  
        float i;
@@@ -213,7 -213,7 +213,7 @@@ float SetTeam(entity o, float Team
                        default:
                                if(GetTeam(Team, false) == world)
                                {
 -                                      print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
 +                                      printf(_("trying to switch to unsupported team %d\n"), Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
                        default:
                                if(GetTeam(Team, false) == world)
                                {
 -                                      print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
 +                                      printf(_("trying to switch to unsupported team %d\n"), Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
@@@ -341,6 -341,9 +341,9 @@@ float CSQC_InputEvent(float bInputType
        if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
                return true;
  
+       if (HUD_QuickMenu_InputEvent(bInputType, nPrimary, nSecondary))
+               return true;
        if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
                return true;
  
@@@ -424,7 -427,7 +427,7 @@@ void Ent_ReadPlayerScore(
        if(!isNew && n != self.sv_entnum)
        {
                //print("A CSQC entity changed its owner!\n");
 -              print(sprintf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname));
 +              printf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname);
                isNew = true;
                Ent_Remove();
                self.enttype = ENT_CLIENT_SCORES;
@@@ -687,7 -690,7 +690,7 @@@ void Ent_ReadSpawnPoint(float is_new) /
                }
        }
  
 -      //print(sprintf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt));
 +      //printf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt);
  }
  
  void Ent_ReadSpawnEvent(float is_new)
                }
        }
  
 -      //print(sprintf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum));
 +      //printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
  }
  
  // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
@@@ -753,7 -756,7 +756,7 @@@ void CSQC_Ent_Update(float bIsNewEntity
        t = ReadByte();
  
        if(autocvar_developer_csqcentities)
 -              print(sprintf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t));
 +              printf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
  
        // set up the "time" global for received entities to be correct for interpolation purposes
        savetime = time;
                if(t != self.enttype || bIsNewEntity)
                {
                        //print("A CSQC entity changed its type!\n");
 -                      print(sprintf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t));
 +                      printf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
                        Ent_Remove();
                        clearentity(self);
                        bIsNewEntity = 1;
        {
                if(!bIsNewEntity)
                {
 -                      print(sprintf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t));
 +                      printf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
                        bIsNewEntity = 1;
                }
        }
@@@ -868,7 -871,7 +871,7 @@@ void Ent_Remove(
  void CSQC_Ent_Remove()
  {
        if(autocvar_developer_csqcentities)
 -              print(sprintf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype));
 +              printf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
  
        if(wasfreed(self))
        {
@@@ -893,7 -896,7 +896,7 @@@ void Gamemode_Init(
  void CSQC_Parse_StuffCmd(string strMessage)
  {
        if(autocvar_developer_csqcentities)
 -              print(sprintf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage));
 +              printf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
  
        localcmd(strMessage);
  }
  void CSQC_Parse_Print(string strMessage)
  {
        if(autocvar_developer_csqcentities)
 -              print(sprintf("CSQC_Parse_Print(\"%s\")\n", strMessage));
 +              printf("CSQC_Parse_Print(\"%s\")\n", strMessage);
  
        print(ColorTranslateRGB(strMessage));
  }
  void CSQC_Parse_CenterPrint(string strMessage)
  {
        if(autocvar_developer_csqcentities)
 -              print(sprintf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage));
 +              printf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
  
        centerprint_hud(strMessage);
  }
@@@ -921,10 -924,8 +924,10 @@@ void Fog_Force(
  {
        // TODO somehow thwart prvm_globalset client ...
  
 -      if(forcefog != "")
 -              localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2));
 +      if(autocvar_cl_orthoview && autocvar_cl_orthoview_nofog)
 +              { localcmd("\nr_drawfog 0\n"); }
 +      else if(forcefog != "")
 +              { localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2)); }
  }
  
  void Gamemode_Init();
@@@ -1201,7 -1202,7 +1204,7 @@@ float CSQC_Parse_TempEntity(
                nTEID = ReadByte();
  
        if(autocvar_developer_csqcentities)
 -              print(sprintf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID));
 +              printf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
  
                // NOTE: Could just do return instead of break...
        switch(nTEID)
                        Net_ReadRace();
                        bHandled = true;
                        break;
 -              case TE_CSQC_ZCURVEPARTICLES:
 -                      Net_ReadZCurveParticles();
 -                      bHandled = true;
 -                      break;
                case TE_CSQC_NEXGUNBEAMPARTICLE:
                        Net_ReadNexgunBeamParticle();
                        bHandled = true;
diff --combined qcsrc/client/View.qc
index 41cec30bf011b78d3c8968f714c3b206523070a3,55ea5192eca0e0739b21dff6ca61612c042119ff..82454e5a88e7cc7dd4e423485fa763d9023ef1b4
@@@ -199,17 -199,6 +199,17 @@@ vector GetCurrentFov(float fov
        return '1 0 0' * fovx + '0 1 0' * fovy;
  }
  
 +vector GetOrthoviewFOV(vector ov_worldmin, vector ov_worldmax, vector ov_mid, vector ov_org)
 +{
 +      float fovx, fovy;
 +      float width = (ov_worldmax_x - ov_worldmin_x);
 +      float height = (ov_worldmax_y - ov_worldmin_y);
 +      float distance_to_middle_of_world = vlen(ov_mid - ov_org);
 +      fovx = atan2(width/2, distance_to_middle_of_world) / M_PI * 360.0;
 +      fovy = atan2(height/2, distance_to_middle_of_world) / M_PI * 360.0;
 +      return '1 0 0' * fovx + '0 1 0' * fovy;
 +}
 +
  // this function must match W_SetupShot!
  float zoomscript_caught;
  
@@@ -318,15 -307,13 +318,15 @@@ float TrueAimCheck(
                        break;
        }
  
 +      vector traceorigin = getplayerorigin(player_localentnum-1) + (eZ * getstati(STAT_VIEWHEIGHT));
 +
        vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
  
 -      traceline(view_origin, view_origin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
 +      traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
        trueaimpoint = trace_endpos;
  
 -      if(vlen(trueaimpoint - view_origin) < g_trueaim_minrange)
 -              trueaimpoint = view_origin + view_forward * g_trueaim_minrange;
 +      if(vlen(trueaimpoint - traceorigin) < g_trueaim_minrange)
 +              trueaimpoint = traceorigin + view_forward * g_trueaim_minrange;
  
        if(vecs_x > 0)
                vecs_y = -vecs_y;
                vecs = '0 0 0';
  
        dv = view_right * vecs_y + view_up * vecs_z;
 -      w_shotorg = view_origin + dv;
 +      w_shotorg = traceorigin + dv;
  
        // now move the vecs forward as much as requested if possible
        tracebox(w_shotorg, mi, ma, w_shotorg + view_forward * (vecs_x + nudge), MOVE_NORMAL, ta); // FIXME this MOVE_NORMAL part will misbehave a little in csqc
@@@ -492,7 -479,7 +492,7 @@@ void CSQC_UpdateView(float w, float h
        // event chase camera
        if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
        {
 -              if((spectatee_status >= 0 && (autocvar_cl_eventchase_death && is_dead)) || intermission)
 +              if(((spectatee_status >= 0 && (autocvar_cl_eventchase_death && is_dead)) || intermission) && !autocvar_cl_orthoview)
                {
                        // make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
                        vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
        }
  
        // do lockview after event chase camera so that it still applies whenever necessary.
-       if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1)))
+       if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1 || HUD_QuickMenu_IsOpened())))
        {
                setproperty(VF_ORIGIN, freeze_org);
                setproperty(VF_ANGLES, freeze_ang);
        WarpZone_FixView();
        //WarpZone_FixPMove();
  
 +      vector ov_org = '0 0 0';
 +      vector ov_mid = '0 0 0';
 +      vector ov_worldmin = '0 0 0';
 +      vector ov_worldmax = '0 0 0';
 +      if(autocvar_cl_orthoview)
 +      {
 +              ov_worldmin = mi_picmin;
 +              ov_worldmax = mi_picmax;
 +
 +              float ov_width = (ov_worldmax_x - ov_worldmin_x);
 +              float ov_height = (ov_worldmax_y - ov_worldmin_y);
 +              float ov_distance = (max(vid_width, vid_height) * max(ov_width, ov_height));
 +
 +              ov_mid = ((ov_worldmax + ov_worldmin) * 0.5);
 +              ov_org = vec3(ov_mid_x, ov_mid_y, (ov_mid_z + ov_distance));
 +
 +              float ov_nearest = vlen(ov_org - vec3(
 +                      bound(ov_worldmin_x, ov_org_x, ov_worldmax_x),
 +                      bound(ov_worldmin_y, ov_org_y, ov_worldmax_y),
 +                      bound(ov_worldmin_z, ov_org_z, ov_worldmax_z)
 +              ));
 +
 +              float ov_furthest = 0;
 +              float dist = 0;
 +
 +              if((dist = vlen(vec3(ov_worldmin_x, ov_worldmin_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +              if((dist = vlen(vec3(ov_worldmax_x, ov_worldmin_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +              if((dist = vlen(vec3(ov_worldmin_x, ov_worldmax_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +              if((dist = vlen(vec3(ov_worldmin_x, ov_worldmin_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +              if((dist = vlen(vec3(ov_worldmax_x, ov_worldmax_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +              if((dist = vlen(vec3(ov_worldmin_x, ov_worldmax_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +              if((dist = vlen(vec3(ov_worldmax_x, ov_worldmin_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +              if((dist = vlen(vec3(ov_worldmax_x, ov_worldmax_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
 +
 +              cvar_settemp("r_nearclip", ftos(ov_nearest));
 +              cvar_settemp("r_farclip_base", ftos(ov_furthest));
 +              cvar_settemp("r_farclip_world", "0");
 +              cvar_settemp("r_novis", "1");
 +              cvar_settemp("r_useportalculling", "0");
 +              cvar_settemp("r_useinfinitefarclip", "0");
 +
 +              setproperty(VF_ORIGIN, ov_org);
 +              setproperty(VF_ANGLES, '90 0 0');
 +
 +              #if 0
 +              printf("OrthoView: org = %s, angles = %s, distance = %f, nearest = %f, furthest = %f\n",
 +                      vtos(ov_org),
 +                      vtos(getpropertyvec(VF_ANGLES)),
 +                      ov_distance,
 +                      ov_nearest,
 +                      ov_furthest);
 +              #endif
 +      }
 +
        // Render the Scene
        view_origin = getpropertyvec(VF_ORIGIN);
        view_angles = getpropertyvec(VF_ANGLES);
        vid_conheight = autocvar_vid_conheight;
        vid_pixelheight = autocvar_vid_pixelheight;
  
 -      setproperty(VF_FOV, GetCurrentFov(fov));
 +      if(autocvar_cl_orthoview) { setproperty(VF_FOV, GetOrthoviewFOV(ov_worldmin, ov_worldmax, ov_mid, ov_org)); }
 +      else { setproperty(VF_FOV, GetCurrentFov(fov)); }
  
        // Camera for demo playback
        if(camera_active)
                                }
                        }
  
 -                      //print(sprintf("crosshair style: %s\n", wcross_style));
 +                      //printf("crosshair style: %s\n", wcross_style);
                        wcross_name = strcat("gfx/crosshair", wcross_style);
  
                        // MAIN CROSSHAIR COLOR DECISION
  
        if(autocvar__hud_configure)
                HUD_Panel_Mouse();
+       else if(HUD_QuickMenu_IsOpened())
+               HUD_QuickMenu_Mouse();
  
-     if(hud && !intermission)
+       if(hud && !intermission)
      {
          if(hud == HUD_SPIDERBOT)
              CSQC_SPIDER_HUD();
index 43aab6ae44c73f3c2b0c598bbe4ae3d72014248e,32641494bb69114e632e38f3099976c6c27e165e..b0fb996798b493160d89c983f6caa7513f806247
@@@ -54,8 -54,6 +54,8 @@@ float autocvar_cl_gunalign
  float autocvar_cl_hidewaypoints;
  float autocvar_cl_lockview;
  float autocvar_cl_nogibs;
 +float autocvar_cl_orthoview;
 +float autocvar_cl_orthoview_nofog;
  float autocvar_cl_particlegibs;
  float autocvar_cl_particles_oldnexbeam;
  float autocvar_cl_particles_quality;
@@@ -297,6 -295,7 +297,7 @@@ float autocvar_hud_panel_powerups_text
  float autocvar_hud_panel_pressedkeys;
  float autocvar_hud_panel_pressedkeys_aspect;
  float autocvar_hud_panel_pressedkeys_attack;
+ string autocvar_hud_panel_quickmenu_file;
  float autocvar_hud_panel_racetimer;
  float autocvar_hud_panel_radar;
  float autocvar_hud_panel_radar_foreground_alpha;
@@@ -341,6 -340,8 +342,8 @@@ float autocvar_hud_panel_weapons_timeou
  float autocvar_hud_panel_weapons_timeout_fadefgmin;
  var float autocvar_hud_panel_weapons_timeout_speed_in = 0.25;
  var float autocvar_hud_panel_weapons_timeout_speed_out = 0.75;
+ //float autocvar_hud_panel_quickmenu;
+ float autocvar_hud_panel_quickmenu_align;
  float autocvar_hud_progressbar_alpha;
  float autocvar_hud_showbinds;
  float autocvar_hud_showbinds_limit;
diff --combined qcsrc/client/hud.qc
index 252142506f88731b28e21e679c0bd5d84b7d52b2,90f4df32a08c407c71aed4c3a808512492c2a7f5..72458cf4b4b4d9a3fbf74fb3d546b6a7ca738f48
@@@ -4095,7 -4095,7 +4095,7 @@@ float centerprint_showing
  
  void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
  {
 -      //print(sprintf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num));
 +      //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
        float i, j;
  
        if(strMessage == "" && new_id == 0)
@@@ -4261,7 -4261,8 +4261,7 @@@ void HUD_CenterPrint (void
        float a, sz, align, current_msg_pos_y = 0, msg_size;
        vector pos;
        string ts;
 -
 -      n = -1; // if no msg will be displayed, n stays -1
 +      float all_messages_expired = TRUE;
  
        pos = panel_pos;
        if (autocvar_hud_panel_centerprint_flip)
                                continue;
                }
  
 +              all_messages_expired = FALSE;
  
                // fade the centerprint_hud in/out
 -              if(centerprint_time[j] < 0)
 -                      a = bound(0, (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
 -              else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)
 -                      a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
 -              else if(centerprint_expire_time[j] > time)
 +              if(centerprint_time[j] < 0)  // Expired but forced. Expire time is the fade-in time.
 +                      a = (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
 +              else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)  // Regularily printed. Not fading out yet.
 +                      a = (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
 +              else // Expiring soon, so fade it out.
                        a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out);
 -              else
 -                      a = 0;
 +
 +              if (a <= 0.5/255.0)  // Guaranteed invisible - don't show.
 +                      continue;
 +              if (a > 1)
 +                      a = 1;
  
                // set the size from fading in/out before subsequent fading
                sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
                        a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half theAlpha
                        a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower theAlpha even more for each message
                }
 +              a *= panel_fg_alpha;
  
                // finally set the size based on the new theAlpha from subsequent fading
                sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize));
                                {
                                        if (align)
                                                pos_x = panel_pos_x + (panel_size_x - stringwidth(ts, TRUE, fontsize)) * align;
 -                                      drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a * panel_fg_alpha, DRAWFLAG_NORMAL);
 +                                      if (a > 0.5/255.0)  // Otherwise guaranteed invisible - don't show. This is checked a second time after some multiplications with other factors were done so temporary changes of these cannot cause flicker.
 +                                              drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a, DRAWFLAG_NORMAL);
                                        pos_y += fontsize_y;
                                }
                                else
                }
        }
        drawfontscale = '1 1 0';
 -      if (n == -1)
 +      if (all_messages_expired)
        {
                centerprint_showing = FALSE;
                reset_centerprint_messages();
        }
  }
  
+ // QuickMenu (#17)
+ //
+ // QUICKMENU_MAXLINES must be <= 10
+ #define QUICKMENU_MAXLINES 10
+ #define QUICKMENU_MAXENTRIES 256
+ string QuickMenu_Command[QUICKMENU_MAXLINES];
+ string QuickMenu_Description[QUICKMENU_MAXLINES];
+ float QuickMenu_CurrentPage;
+ float QuickMenu_IsLastPage;
+ var float QuickMenu_Buffer = -1;
+ float QuickMenu_Buffer_Size;
+ float QuickMenu_Buffer_Index;
+ string QuickMenu_CurrentSubMenu;
+ float QuickMenu_CurrentPage_FirstEntry;
+ var float QuickMenu_Entries;
+ void HUD_QuickMenu_load_entry(float i, string s, string s1)
+ {
+       //print(sprintf("^xc80 entry %d: %s, %s\n", i, s, s1));
+       if (QuickMenu_Description[i])
+               strunzone(QuickMenu_Description[i]);
+       QuickMenu_Description[i] = strzone(s);
+       if (QuickMenu_Command[i])
+               strunzone(QuickMenu_Command[i]);
+       QuickMenu_Command[i] = strzone(s1);
+ }
+ void HUD_QuickMenu_clear_entry(float i)
+ {
+       if (QuickMenu_Description[i])
+               strunzone(QuickMenu_Description[i]);
+       QuickMenu_Description[i] = string_null;
+       if (QuickMenu_Command[i])
+               strunzone(QuickMenu_Command[i]);
+       QuickMenu_Command[i] = string_null;
+ }
+ float HUD_QuickMenu_Buffer_Init()
+ {
+       float fh, i;
+       string s;
+       fh = fopen(autocvar_hud_panel_quickmenu_file, FILE_READ);
+       if(fh < 0)
+       {
+               print(sprintf(_("Error: Couldn't open file %s!\n"), autocvar_hud_panel_quickmenu_file));
+               return false;
+       }
+       QuickMenu_Buffer = buf_create();
+       if (QuickMenu_Buffer < 0)
+       {
+               fclose(fh);
+               return false;
+       }
+       i = 0;
+       while((s = fgets(fh)) && i < QUICKMENU_MAXENTRIES)
+       {
+               // first skip invalid entries, so we don't check them anymore
+               float argc;
+               argc = tokenize_console(s);
+               if(argc == 0 || argc > 2)
+                       continue;
+               bufstr_set(QuickMenu_Buffer, i, s);
+               ++i;
+       }
+       QuickMenu_Buffer_Size = i;
+       if (QuickMenu_Buffer_Size <= 0)
+       {
+               buf_del(QuickMenu_Buffer);
+               QuickMenu_Buffer = -1;
+       }
+       fclose(fh);
+       return true;
+ }
+ void HUD_QuickMenu_Buffer_Close()
+ {
+       if (QuickMenu_Buffer >= 0)
+       {
+               buf_del(QuickMenu_Buffer);
+               QuickMenu_Buffer = -1;
+               QuickMenu_Buffer_Size = 0;
+       }
+ }
+ void HUD_QuickMenu_Close()
+ {
+       if (QuickMenu_CurrentSubMenu)
+               strunzone(QuickMenu_CurrentSubMenu);
+       QuickMenu_CurrentSubMenu = string_null;
+       float i;
+       for (i = 0; i < QUICKMENU_MAXLINES; ++i)
+               HUD_QuickMenu_clear_entry(i);
+       QuickMenu_Entries = 0;
+       hud_panel_quickmenu = 0;
+       mouseClicked = 0;
+       prevMouseClicked = 0;
+       HUD_QuickMenu_Buffer_Close();
+       if(autocvar_hud_cursormode)
+       if(!mv_active)
+               setcursormode(0);
+ }
+ // It assumes submenu open tag is already detected
+ void HUD_QuickMenu_skip_submenu(string submenu)
+ {
+       string s, z_submenu;
+       z_submenu = strzone(submenu);
+       for(++QuickMenu_Buffer_Index ; QuickMenu_Buffer_Index < QuickMenu_Buffer_Size; ++QuickMenu_Buffer_Index)
+       {
+               s = bufstr_get(QuickMenu_Buffer, QuickMenu_Buffer_Index);
+               float argc;
+               argc = tokenize_console(s);
+               if(argc == 2)
+                       continue;
+               if (argv(0) == "")
+                       continue;
+               if (argv(0) == z_submenu) // submenu end
+                       break;
+               HUD_QuickMenu_skip_submenu(argv(0));
+       }
+       strunzone(z_submenu);
+ }
+ float HUD_QuickMenu_IsOpened()
+ {
+       return (QuickMenu_Entries > 0);
+ }
+ // new_page 0 means page 0, new_page != 0 means next page
+ float QuickMenu_Buffer_Index_Prev;
+ float HUD_QuickMenu_Page(string target_submenu, float new_page)
+ {
+       string s, z_submenu;
+       if (new_page == 0)
+               QuickMenu_CurrentPage = 0;
+       else
+               ++QuickMenu_CurrentPage;
+       QuickMenu_CurrentPage_FirstEntry = QuickMenu_CurrentPage * (QUICKMENU_MAXLINES - 2);
+       z_submenu = strzone(target_submenu);
+       if (QuickMenu_CurrentSubMenu)
+               strunzone(QuickMenu_CurrentSubMenu);
+       QuickMenu_CurrentSubMenu = strzone(z_submenu);
+       QuickMenu_IsLastPage = TRUE;
+       QuickMenu_Entries = 0;
+       QuickMenu_Buffer_Index = 0;
+       if (z_submenu != "")
+       {
+               // skip everything until the submenu open tag is found
+               for( ; QuickMenu_Buffer_Index < QuickMenu_Buffer_Size; ++QuickMenu_Buffer_Index)
+               {
+                       s = bufstr_get(QuickMenu_Buffer, QuickMenu_Buffer_Index);
+                       if (tokenize_console(s) == 1 && argv(0) == z_submenu)
+                       {
+                               // print(sprintf("^3 beginning of %s\n", z_submenu));
+                               ++QuickMenu_Buffer_Index;
+                               break;
+                       }
+                       // print(sprintf("^1 skipping %s\n", s));
+               }
+       }
+       float total = 0;
+       for( ; QuickMenu_Buffer_Index < QuickMenu_Buffer_Size; ++QuickMenu_Buffer_Index)
+       {
+               s = bufstr_get(QuickMenu_Buffer, QuickMenu_Buffer_Index);
+               float argc;
+               argc = tokenize_console(s);
+               if (z_submenu != "" && z_submenu == argv(0))
+               {
+                       // print(sprintf("^3 end of %s\n", z_submenu));
+                       break;
+               }
+               if (total - QuickMenu_CurrentPage_FirstEntry >= 0)
+               {
+                       ++QuickMenu_Entries;
+                       if(QuickMenu_Entries == QUICKMENU_MAXLINES - 2)
+                               QuickMenu_Buffer_Index_Prev = QuickMenu_Buffer_Index;
+                       else if(QuickMenu_Entries == QUICKMENU_MAXLINES)
+                       {
+                               HUD_QuickMenu_clear_entry(QUICKMENU_MAXLINES - 1);
+                               QuickMenu_Buffer_Index = QuickMenu_Buffer_Index_Prev;
+                               QuickMenu_IsLastPage = FALSE;
+                               break;
+                       }
+               }
+               // NOTE: entries are loaded starting from 1, not from 0
+               if (argc == 1 && argv(0) != "") // submenu
+               {
+                       if (total - QuickMenu_CurrentPage_FirstEntry >= 0)
+                               HUD_QuickMenu_load_entry(QuickMenu_Entries, argv(0), "");
+                       HUD_QuickMenu_skip_submenu(argv(0));
+               }
+               else if (total - QuickMenu_CurrentPage_FirstEntry >= 0)
+                       HUD_QuickMenu_load_entry(QuickMenu_Entries, argv(0), argv(1));
+               ++total;
+       }
+       strunzone(z_submenu);
+       if (QuickMenu_Entries == 0)
+       {
+               HUD_QuickMenu_Close();
+               return 0;
+       }
+       return 1;
+ }
+ void HUD_QuickMenu_Open()
+ {
+       if(!HUD_QuickMenu_Buffer_Init()) return;
+       hud_panel_quickmenu = 1;
+       if(autocvar_hud_cursormode)
+               setcursormode(1);
+       hudShiftState = 0;
+       HUD_QuickMenu_Page("", 0);
+ }
+ float HUD_QuickMenu_ActionForNumber(float num)
+ {
+       if (!QuickMenu_IsLastPage)
+       {
+               if (num < 0 || num >= QUICKMENU_MAXLINES)
+                       return 0;
+               if (num == QUICKMENU_MAXLINES - 1)
+                       return 0;
+               if (num == 0)
+               {
+                       HUD_QuickMenu_Page(QuickMenu_CurrentSubMenu, +1);
+                       return 0;
+               }
+       } else if (num <= 0 || num > QuickMenu_Entries)
+               return 0;
+       if (QuickMenu_Command[num] != "")
+       {
+               localcmd(strcat("\n", QuickMenu_Command[num], "\n"));
+               return 1;
+       }
+       if (QuickMenu_Description[num] != "")
+               HUD_QuickMenu_Page(QuickMenu_Description[num], 0);
+       return 0;
+ }
+ float HUD_QuickMenu_InputEvent(float bInputType, float nPrimary, float nSecondary)
+ {
+       // we only care for keyboard events
+       if(bInputType == 2)
+               return false;
+       if(!HUD_QuickMenu_IsOpened() || autocvar__hud_configure || mv_active)
+               return false;
+       if(bInputType == 3)
+       {
+               mousepos_x = nPrimary;
+               mousepos_y = nSecondary;
+               return true;
+       }
+       // allow console bind to work
+       string con_keys;
+       float keys;
+       con_keys = findkeysforcommand("toggleconsole", 0);
+       keys = tokenize(con_keys); // findkeysforcommand returns data for this
+       float hit_con_bind = 0, i;
+       for (i = 0; i < keys; ++i)
+       {
+               if(nPrimary == stof(argv(i)))
+                       hit_con_bind = 1;
+       }
+       if(bInputType == 0) {
+               if(nPrimary == K_ALT) hudShiftState |= S_ALT;
+               if(nPrimary == K_CTRL) hudShiftState |= S_CTRL;
+               if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
+       }
+       else if(bInputType == 1) {
+               if(nPrimary == K_ALT) hudShiftState -= (hudShiftState & S_ALT);
+               if(nPrimary == K_CTRL) hudShiftState -= (hudShiftState & S_CTRL);
+               if(nPrimary == K_SHIFT) hudShiftState -= (hudShiftState & S_SHIFT);
+       }
+       if(nPrimary == K_ESCAPE)
+       {
+               if (bInputType == 1)
+                       return true;
+               HUD_QuickMenu_Close();
+       }
+       else if(nPrimary >= '0' && nPrimary <= '9')
+       {
+               if (bInputType == 1)
+                       return true;
+               HUD_QuickMenu_ActionForNumber(stof(chr2str(nPrimary)));
+       }
+       if(nPrimary == K_MOUSE1)
+       {
+               if(bInputType == 0) // key pressed
+                       mouseClicked |= S_MOUSE1;
+               else if(bInputType == 1) // key released
+                       mouseClicked -= (mouseClicked & S_MOUSE1);
+       }
+       else if(nPrimary == K_MOUSE2)
+       {
+               if(bInputType == 0) // key pressed
+                       mouseClicked |= S_MOUSE2;
+               else if(bInputType == 1) // key released
+                       mouseClicked -= (mouseClicked & S_MOUSE2);
+       }
+       else if(hit_con_bind)
+               return false;
+       return true;
+ }
+ void HUD_QuickMenu_Mouse()
+ {
+       if(mv_active) return;
+       if(!mouseClicked)
+       if(prevMouseClicked & S_MOUSE2)
+       {
+               HUD_QuickMenu_Close();
+               return;
+       }
+       if(!autocvar_hud_cursormode)
+       {
+               mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
+               mousepos_x = bound(0, mousepos_x, vid_conwidth);
+               mousepos_y = bound(0, mousepos_y, vid_conheight);
+       }
+       HUD_Panel_UpdateCvars()
+       if(panel_bg_padding)
+       {
+               panel_pos += '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
+       }
+       float first_entry_pos, entries_height;
+       vector fontsize;
+       fontsize = '1 1 0' * (panel_size_y / QUICKMENU_MAXLINES);
+       first_entry_pos = panel_pos_y + ((QUICKMENU_MAXLINES - QuickMenu_Entries) * fontsize_y) / 2;
+       entries_height = panel_size_y - ((QUICKMENU_MAXLINES - QuickMenu_Entries) * fontsize_y);
+       if (mousepos_x >= panel_pos_x && mousepos_y >= first_entry_pos && mousepos_x <= panel_pos_x + panel_size_x && mousepos_y <= first_entry_pos + entries_height)
+       {
+               float entry_num;
+               entry_num = floor((mousepos_y - first_entry_pos) / fontsize_y);
+               if (QuickMenu_IsLastPage || entry_num != QUICKMENU_MAXLINES - 2)
+               {
+                       panel_pos_y = first_entry_pos + entry_num * fontsize_y;
+                       vector color;
+                       if(mouseClicked & S_MOUSE1)
+                               color = '0.5 1 0.5';
+                       else if(hudShiftState & S_CTRL)
+                               color = '1 1 0.3';
+                       else
+                               color = '1 1 1';
+                       drawfill(panel_pos, eX * panel_size_x + eY * fontsize_y, color, .2, DRAWFLAG_NORMAL);
+                       if(!mouseClicked && (prevMouseClicked & S_MOUSE1))
+                       {
+                               float f;
+                               if (entry_num < QUICKMENU_MAXLINES - 1)
+                                       f = HUD_QuickMenu_ActionForNumber(entry_num + 1);
+                               else
+                                       f = HUD_QuickMenu_ActionForNumber(0);
+                               if(f && !(hudShiftState & S_CTRL))
+                                       HUD_QuickMenu_Close();
+                       }
+               }
+       }
+       const vector cursorsize = '32 32 0';
+       drawpic(mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursorsize, '1 1 1', 0.8, DRAWFLAG_NORMAL);
+       prevMouseClicked = mouseClicked;
+ }
+ void HUD_QuickMenu_DrawEntry(vector pos, string s, vector fontsize)
+ {
+       string entry;
+       float offset;
+       entry = textShortenToWidth(s, panel_size_x, fontsize, stringwidth_colors);
+       if (autocvar_hud_panel_quickmenu_align > 0)
+       {
+               offset = (panel_size_x - stringwidth_colors(entry, fontsize)) * min(autocvar_hud_panel_quickmenu_align, 1);
+               drawcolorcodedstring(pos + eX * offset, entry, fontsize, panel_fg_alpha, DRAWFLAG_ADDITIVE);
+       }
+       else
+               drawcolorcodedstring(pos, entry, fontsize, panel_fg_alpha, DRAWFLAG_ADDITIVE);
+ }
+ void HUD_QuickMenu(void)
+ {
+       if(!autocvar__hud_configure)
+       {
+               if (hud_configure_prev && hud_configure_prev != -1)
+                       HUD_QuickMenu_Close();
+               if(!hud_draw_maximized) return;
+               if(mv_active) return;
+               //if(!autocvar_hud_panel_quickmenu) return; // autocvar exists only for conformity with other panels
+               if(!hud_panel_quickmenu) return;
+       }
+       else
+       {
+               if(!HUD_QuickMenu_IsOpened())
+               {
+                       QuickMenu_Entries = 1;
+                       HUD_QuickMenu_load_entry(QuickMenu_Entries, sprintf(_("Submenu%d"), QuickMenu_Entries), "");
+                       ++QuickMenu_Entries;
+                       HUD_QuickMenu_load_entry(QuickMenu_Entries, sprintf(_("Submenu%d"), QuickMenu_Entries), "");
+                       ++QuickMenu_Entries;
+                       // although real command doesn't matter here, it must not be empty
+                       // otherwise the entry is displayed like a submenu
+                       for (; QuickMenu_Entries < QUICKMENU_MAXLINES - 1; ++QuickMenu_Entries)
+                               HUD_QuickMenu_load_entry(QuickMenu_Entries, sprintf(_("Command%d"), QuickMenu_Entries), "-");
+                       ++QuickMenu_Entries;
+                       HUD_QuickMenu_clear_entry(QuickMenu_Entries);
+                       QuickMenu_IsLastPage = FALSE;
+               }
+       }
+       HUD_Panel_UpdateCvars();
+       HUD_Panel_ApplyFadeAlpha();
+       HUD_Panel_DrawBg(1);
+       if(panel_bg_padding)
+       {
+               panel_pos += '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
+       }
+       float i;
+       vector fontsize;
+       string color;
+       fontsize = '1 1 0' * (panel_size_y / QUICKMENU_MAXLINES);
+       if (!QuickMenu_IsLastPage)
+       {
+               color = "^5";
+               HUD_QuickMenu_DrawEntry(panel_pos + eY * (panel_size_y - fontsize_y), sprintf("%d: %s%s", 0, color, _("Continue...")), fontsize);
+       }
+       else
+               panel_pos_y += ((QUICKMENU_MAXLINES - QuickMenu_Entries) * fontsize_y) / 2;
+       for (i = 1; i <= QuickMenu_Entries; ++i) {
+               if (QuickMenu_Description[i] == "")
+                       break;
+               if (QuickMenu_Command[i] == "")
+                       color = "^4";
+               else
+                       color = "^3";
+               HUD_QuickMenu_DrawEntry(panel_pos, sprintf("%d: %s%s", i, color, QuickMenu_Description[i]), fontsize);
+               panel_pos_y += fontsize_y;
+       }
+ }
  /*
  ==================
  Main HUD system
@@@ -4572,6 -5038,8 +5043,8 @@@ void HUD_Main (void
                (panel = HUD_PANEL(RADAR)).panel_draw();
        if(autocvar__con_chat_maximized)
                (panel = HUD_PANEL(CHAT)).panel_draw();
+       if(hud_panel_quickmenu)
+               (panel = HUD_PANEL(QUICKMENU)).panel_draw();
  
        if(autocvar__hud_configure)
        {
diff --combined qcsrc/client/hud.qh
index c2432b97c78191d5d8b38304cf14c414bf66b707,711929066cb4cf16b08a148be392a5292e80bbf0..c86eb91b833895cb752121b660ec43d2236f6e1a
@@@ -9,6 -9,7 +9,7 @@@ string hud_panelorder_prev
  
  float hud_draw_maximized;
  float hud_panel_radar_maximized;
+ float hud_panel_quickmenu;
  
  vector mousepos;
  vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
@@@ -98,6 -99,8 +99,8 @@@ var string panel_bg_padding_str
  
  float current_player;
  
+ float mv_active;
  
  #define HUD_PANELS \
        HUD_PANEL(WEAPONS      , HUD_Weapons      , weapons) \
        HUD_PANEL(ENGINEINFO   , HUD_EngineInfo   , engineinfo) \
        HUD_PANEL(INFOMESSAGES , HUD_InfoMessages , infomessages) \
        HUD_PANEL(PHYSICS      , HUD_Physics      , physics) \
-       HUD_PANEL(CENTERPRINT  , HUD_CenterPrint  , centerprint)
+       HUD_PANEL(CENTERPRINT  , HUD_CenterPrint  , centerprint) \
+       HUD_PANEL(QUICKMENU    , HUD_QuickMenu    , quickmenu) 
  
  #define HUD_PANEL(NAME,draw_func,name) \
        float HUD_PANEL_##NAME; \
@@@ -344,7 -348,7 +348,7 @@@ if(panel.update_time <= time) { 
                strunzone(panel.current_panel_bg); \
        if(panel_bg == "")\
        {\
 -              /*print(sprintf("^xf08 %s panel: panel_bg is empty\n", panel.panel_name));*/\
 +              /*printf("^xf08 %s panel: panel_bg is empty\n", panel.panel_name);*/\
                panel_bg = "0";\
        }\
        panel.current_panel_bg = strzone(panel_bg); \
        panel_bg = panel.current_panel_bg; \
        if(panel.current_panel_bg == "")\
        {\
 -              /*print(sprintf("^xf08 %s panel: panel.current_panel_bg is empty\n", panel.panel_name));*/\
 +              /*printf("^xf08 %s panel: panel.current_panel_bg is empty\n", panel.panel_name);*/\
                panel_bg = "0";\
        }\
        panel_bg_alpha = panel.current_panel_bg_alpha; \
index d361454843feea745f877ba898872a4dd2ea467a,9ceec5de005851a45f3d31a4506caf8b5ec473d4..92e33653c0c193513272b306413f1b4aaf627d71
@@@ -188,16 -188,19 +188,19 @@@ void HUD_Panel_ExportCfg(string cfgname
                                        HUD_Write_PanelCvar_q("_fade_subsequent_minfontsize");
                                        HUD_Write_PanelCvar_q("_fade_minfontsize");
                                        break;
+                               case HUD_PANEL_QUICKMENU:
+                                       HUD_Write_PanelCvar_q("_align");
+                                       break;
                        }
                        HUD_Write("\n");
                }
                HUD_Write("menu_sync\n"); // force the menu to reread the cvars, so that the dialogs are updated
  
 -              print(sprintf(_("^2Successfully exported to %s! (Note: It's saved in data/data/)\n"), filename));
 +              printf(_("^2Successfully exported to %s! (Note: It's saved in data/data/)\n"), filename);
                fclose(fh);
        }
        else
 -              print(sprintf(_("^1Couldn't write to %s\n"), filename));
 +              printf(_("^1Couldn't write to %s\n"), filename);
  }
  
  void HUD_Configure_Exit_Force()
index 8a7d3fd49fd8976d83dc2651cfc0ad5bce69e749,055e3b5cc145e023730ec905b58037c4d7ae5e5b..0d2cd934ead26dcaa799f65ff1310267059d0da8
@@@ -410,7 -410,7 +410,7 @@@ void Cmd_HUD_SetFields(float argc
                        else
                        {
                                if (!nocomplain)
 -                                      print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
 +                                      printf("^1Error:^7 Unknown score field: '%s'\n", str);
                                continue;
                        }
  :found
                        hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
                        hud_field[hud_num_fields] = ps_secondary;
                        ++hud_num_fields;
 -                      print(sprintf("fixed missing field '%s'\n", scores_label[ps_secondary]));
 +                      printf("fixed missing field '%s'\n", scores_label[ps_secondary]);
                }
                if(!have_primary)
                {
                        hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
                        hud_field[hud_num_fields] = ps_primary;
                        ++hud_num_fields;
 -                      print(sprintf("fixed missing field '%s'\n", scores_label[ps_primary]));
 +                      printf("fixed missing field '%s'\n", scores_label[ps_primary]);
                }
        }
  
@@@ -952,6 -952,8 +952,8 @@@ vector HUD_Scoreboard_MakeTable(vector 
  float HUD_WouldDrawScoreboard() {
        if (autocvar__hud_configure)
                return 0;
+       else if (HUD_QuickMenu_IsOpened())
+               return 0;
        else if (scoreboard_showscores)
                return 1;
        else if (intermission == 1)
diff --combined qcsrc/common/util.qh
index e4ce0230903c820f7d81568fcb06d7cdde2cc76a,21897346b1f02231058a6e8156af7f606848fb12..dc3cf6f8c8fe44a7b39b96034efa31249ceb2c4c
@@@ -281,7 -281,6 +281,6 @@@ float get_model_parameters_bone_aimweig
  float get_model_parameters_fixbone;
  string get_model_parameters_desc;
  float get_model_parameters(string mod, float skn); // call with string_null to clear; skin -1 means mod is the filename of the txt file and is to be split
  vector vec2(vector v);
  
  #ifndef MENUQC
@@@ -367,12 -366,6 +366,12 @@@ void FindConnectedComponent(entity e, .
  // expand multiple arguments into one argument by stripping parenthesis
  #define XPD(...) __VA_ARGS__
  
 +// Some common varargs functions. Lowercase as they match C.
 +#define printf(...) print(sprintf(__VA_ARGS__))
 +#define dprintf(...) dprint(sprintf(__VA_ARGS__))
 +#define fprintf(file, ...) fputs(file, sprintf(__VA_ARGS__))
 +#define bprintf(...) bprint(sprintf(__VA_ARGS__))
 +
  #ifndef MENUQC
  void backtrace(string msg);
  #endif