]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/hud_code_cleanup
authorterencehill <piuntn@gmail.com>
Mon, 6 Jan 2014 00:07:02 +0000 (01:07 +0100)
committerterencehill <piuntn@gmail.com>
Mon, 6 Jan 2014 00:07:02 +0000 (01:07 +0100)
Conflicts:
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/common/items.qh

1  2 
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/client/autocvars.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/client/hud_config.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/scoreboard.qc
qcsrc/common/items.qh

diff --combined qcsrc/client/Main.qc
index bfabfd4e49bdcc23506349282ac22e507be91fac,3206e923c37bd2a1d284bb337db11420905cbac8..8fb6e51f576fe1270350d69af2262d9de8040fae
@@@ -5,7 -5,7 +5,7 @@@
  entity clearentity_ent;
  void clearentity(entity e)
  {
-       if not(clearentity_ent)
+       if (!clearentity_ent)
        {
                clearentity_ent = spawn();
                clearentity_ent.classname = "clearentity";
@@@ -32,55 -32,6 +32,6 @@@ void menu_sub_null(
  float __engine_check;
  #endif
  
- void precache_playermodel(string m)
- {
-       string f;
-       if(substring(m, -9,5) == "_lod1")
-               return;
-       if(substring(m, -9,5) == "_lod2")
-               return;
-       precache_model(m);
-       f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1));
-       if(fexists(f))
-               precache_model(f);
-       f = strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1));
-       if(fexists(f))
-               precache_model(f);
-       /*
-       float globhandle, i, n;
-       globhandle = search_begin(strcat(m, "_*.sounds"), TRUE, FALSE);
-       if (globhandle < 0)
-               return;
-       n = search_getsize(globhandle);
-       for (i = 0; i < n; ++i)
-       {
-               //print(search_getfilename(globhandle, i), "\n");
-               f = search_getfilename(globhandle, i);
-               PrecachePlayerSounds(f);
-       }
-       search_end(globhandle);
-       */
- }
- void precache_all_playermodels(string pattern)
- {
-       float globhandle, i, n;
-       string f;
-       globhandle = search_begin(pattern, TRUE, FALSE);
-       if (globhandle < 0)
-               return;
-       n = search_getsize(globhandle);
-       for (i = 0; i < n; ++i)
-       {
-               //print(search_getfilename(globhandle, i), "\n");
-               f = search_getfilename(globhandle, i);
-               precache_playermodel(f);
-       }
-       search_end(globhandle);
- }
  string forcefog;
  void WaypointSprite_Load();
  void ConsoleCommand_macro_init();
@@@ -102,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;
        //registercommand("hud_configure");
        //registercommand("hud_save");
        //registercommand("menu_action");
-       
        ConsoleCommand_macro_init();
  
        registercvar("hud_usecsqc", "1");
        precache_model("null");
        precache_sound("misc/hit.wav");
        precache_sound("misc/typehit.wav");
-       if (autocvar_cl_precacheplayermodels)
-       {
-               precache_all_playermodels("models/player/*.zym");
-               precache_all_playermodels("models/player/*.dpm");
-               precache_all_playermodels("models/player/*.md3");
-               precache_all_playermodels("models/player/*.psk");
-               precache_all_playermodels("models/player/*.iqm");
-       }
  
        Projectile_Precache();
        Hook_Precache();
        turrets_precache();
        Tuba_Precache();
        CSQCPlayer_Precache();
-       
        if(autocvar_cl_reticle)
        {
                if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); }
                if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); }
        }
-       
        get_mi_min_max_texcoords(1); // try the CLEVER way first
        minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
        shortmapname = mi_shortname;
@@@ -244,11 -187,11 +187,11 @@@ void Shutdown(void
        if(autocvar_chase_active < 0)
                cvar_set("chase_active", "0");
  
-       if not(isdemo())
+       if (!isdemo())
        {
-               if not(calledhooks & HOOK_START)
+               if (!(calledhooks & HOOK_START))
                        localcmd("\n_cl_hook_gamestart nop\n");
-               if not(calledhooks & HOOK_END)
+               if (!(calledhooks & HOOK_END))
                        localcmd("\ncl_hook_gameend\n");
        }
  }
@@@ -270,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;
        }
        else
        {
-               if not(o.has_team)
+               if (!o.has_team)
                {
                        o.team = Team;
                        tm = GetTeam(Team, true);
@@@ -345,10 -288,10 +288,10 @@@ void Playerchecker_Think(
                }
                else
                {
-                       if not(e.sort_prev)
+                       if (!e.sort_prev)
                        {
                                // player connected
-                               if not(e)
+                               if (!e)
                                        playerslots[i] = e = spawn();
                                e.sv_entnum = i;
                                e.ping = 0;
@@@ -481,7 -424,7 +424,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;
  
        self.sv_entnum = n;
  
-       if not(playerslots[self.sv_entnum])
+       if (!(playerslots[self.sv_entnum]))
                playerslots[self.sv_entnum] = spawn();
        o = self.owner = playerslots[self.sv_entnum];
        o.sv_entnum = self.sv_entnum;
        o.gotscores = 1;
  
-       //if not(o.sort_prev)
+       //if (!o.sort_prev)
        //      RegisterPlayer(o);
        //playerchecker will do this for us later, if it has not already done so
  
@@@ -645,7 -588,7 +588,7 @@@ void Ent_Nagger(
                {
                        f = ReadByte();
                        for(j = i-1, b = 1; b < 256; b *= 2, ++j)
-                               if not(f & b)
+                               if (!(f & b))
                                        if(playerslots[j])
                                                playerslots[j].ready = 0;
                }
@@@ -708,7 -651,7 +651,7 @@@ void Ent_ReadSpawnPoint(float is_new) /
        spn_origin_x = ReadShort();
        spn_origin_y = ReadShort();
        spn_origin_z = ReadShort();
-       
        if(is_new)
        {
                self.origin = spn_origin;
                                }
                        }
                        else { self.cnt = particleeffectnum("spawn_point_neutral"); }
-                       
                        self.draw = Spawn_Draw;
                }
        }
  
-       //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)
        // this way the server can disable the sending of
        // spawn origin or such to clients if wanted.
        float entnum = ReadByte();
-       
        if(entnum)
        {
                self.origin_x = ReadShort();
                        }
                        if(autocvar_cl_spawn_event_sound)
                        {
-                               sound(self, CH_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTN_NORM);
+                               sound(self, CH_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTEN_NORM);
                        }
                }
        }
-       
        // local spawn actions
        if(is_new && (!entnum || (entnum == player_localentnum)))
        {
                        button_zoom = FALSE;
                }
        }
-       
-       //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.
@@@ -810,7 -753,7 +753,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;
                }
        }
                case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break;
                case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
                case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
-               case ENT_CLIENT_TURRET: ent_turret(); break; 
+               case ENT_CLIENT_TURRET: ent_turret(); break;
                case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
-               case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;  
+               case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
                case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
                case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
                case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
@@@ -925,7 -868,7 +868,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))
        {
  
  void Gamemode_Init()
  {
-       if not(isdemo())
+       if (!isdemo())
        {
                if(!(calledhooks & HOOK_START))
                        localcmd("\n_cl_hook_gamestart ", MapInfo_Type_ToString(gametype), "\n");
  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);
  }
@@@ -978,8 -921,10 +921,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();
@@@ -988,7 -933,6 +933,7 @@@ void Ent_ScoresInfo(
        float i;
        self.classname = "ent_client_scores_info";
        gametype = ReadInt24_t();
 +      HUD_ModIcons_SetFunc();
        for(i = 0; i < MAX_SCORE; ++i)
        {
                scores_label[i] = strzone(ReadString());
@@@ -1217,7 -1161,7 +1162,7 @@@ void Net_ReadPingPLReport(
        pi = ReadShort();
        pl = ReadByte();
        ml = ReadByte();
-       if not(playerslots[e])
+       if (!(playerslots[e]))
                return;
        playerslots[e].ping = pi;
        playerslots[e].ping_packetloss = pl / 255.0;
@@@ -1257,7 -1201,7 +1202,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 ac897d395464aff9f24aa68bdbf25663a8d05858,41cec30bf011b78d3c8968f714c3b206523070a3..85dfe547c15518ca455ff455bdd2dfe4cade9904
@@@ -1,10 -1,5 +1,5 @@@
  entity porto;
  vector polyline[16];
- float Q3SURFACEFLAG_SLICK = 2; // low friction surface
- float DPCONTENTS_SOLID = 1; // blocks player movement
- float DPCONTENTS_BODY = 32; // blocks player movement
- float DPCONTENTS_CORPSE = 64; // blocks player movement
- float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
  void Porto_Draw()
  {
        vector p, dir, ang, q, nextdir;
@@@ -132,8 -127,8 +127,8 @@@ vector GetCurrentFov(float fov
        else if(autocvar_cl_spawnzoom && zoomin_effect)
        {
                float spawnzoomfactor = bound(1, autocvar_cl_spawnzoom_factor, 16);
-               
-               current_viewzoom += (autocvar_cl_spawnzoom_speed * (spawnzoomfactor - current_viewzoom) * drawframetime); 
+               current_viewzoom += (autocvar_cl_spawnzoom_speed * (spawnzoomfactor - current_viewzoom) * drawframetime);
                current_viewzoom = bound(1 / spawnzoomfactor, current_viewzoom, 1);
                if(current_viewzoom == 1) { zoomin_effect = 0; }
        }
                setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity));
        else
                setsensitivityscale(1);
-               
        makevectors(view_angles);
  
        if(autocvar_cl_velocityzoom && autocvar_cl_velocityzoom_type) // _type = 0 disables velocity zoom too
        {
-               v = pmove_vel;
-               if(csqcplayer)
-                       v = csqcplayer.velocity;
-               switch(autocvar_cl_velocityzoom_type)
+               if(intermission) { curspeed = 0; }
+               else
                {
-                       case 3: curspeed = max(0, v_forward * v); break;
-                       case 2: curspeed = (v_forward * v); break;
-                       case 1: default: curspeed = vlen(v); break;
+                       v = pmove_vel;
+                       if(csqcplayer)
+                               v = csqcplayer.velocity;
+                       switch(autocvar_cl_velocityzoom_type)
+                       {
+                               case 3: curspeed = max(0, v_forward * v); break;
+                               case 2: curspeed = (v_forward * v); break;
+                               case 1: default: curspeed = vlen(v); break;
+                       }
                }
-               
                velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoom_time), 1); // speed at which the zoom adapts to player velocity
                avgspeed = avgspeed * (1 - velocityzoom) + (curspeed / autocvar_cl_velocityzoom_speed) * velocityzoom;
                velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom / 1) * 1);
-               
                //print(ftos(avgspeed), " avgspeed, ", ftos(curspeed), " curspeed, ", ftos(velocityzoom), " return\n"); // for debugging
        }
        else
        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;
  
@@@ -308,13 -318,15 +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
@@@ -350,8 -362,8 +362,8 @@@ void PostInit(void)
  void CSQC_Demo_Camera();
  float HUD_WouldDrawScoreboard();
  float camera_mode;
- float CAMERA_FREE = 1;
- float CAMERA_CHASE = 2;
const float CAMERA_FREE = 1;
const float CAMERA_CHASE = 2;
  float reticle_type;
  string NextFrameCommand;
  void CSQC_SPIDER_HUD();
@@@ -480,10 -492,18 +492,18 @@@ 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) + autocvar_cl_eventchase_viewoffset);
+                       vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
+                       // detect maximum viewoffset and use it
+                       if(autocvar_cl_eventchase_viewoffset)
+                       {
+                               WarpZone_TraceLine(current_view_origin, current_view_origin + autocvar_cl_eventchase_viewoffset + ('0 0 1' * autocvar_cl_eventchase_maxs_z), MOVE_WORLDONLY, self);
+                               if(trace_fraction == 1) { current_view_origin += autocvar_cl_eventchase_viewoffset; }
+                               else { current_view_origin_z += max(0, (trace_endpos_z - current_view_origin_z) - autocvar_cl_eventchase_maxs_z); }
+                       }
  
                        // We must enable chase_active to get a third person view (weapon viewmodel hidden and own player model showing).
                        // Ideally, there should be another way to enable third person cameras, such as through setproperty()
        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)
        drawstring('0 0 0', "", '1 1 0', '1 1 1', 0, 0);
  
        if(autocvar_r_fakelight >= 2 || autocvar_r_fullbright)
-       if not(serverflags & SERVERFLAG_ALLOW_FULLBRIGHT)
+       if (!(serverflags & SERVERFLAG_ALLOW_FULLBRIGHT))
        {
                // apply night vision effect
                vector tc_00, tc_01, tc_10, tc_11;
                R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
                R_EndPolygon();
        }
-         
        // Draw the aiming reticle for weapons that use it
        // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
        // It must be a persisted float for fading out to work properly (you let go of the zoom button for
        // the view to go back to normal, so reticle_type would become 0 as we fade out)
        if(spectatee_status || is_dead || hud != HUD_NORMAL)
                reticle_type = 0; // prevent reticle from showing during the respawn zoom effect or for spectators
-       else if(activeweapon == WEP_NEX && (button_zoom || zoomscript_caught) || activeweapon == WEP_RIFLE && (button_zoom || zoomscript_caught) || activeweapon == WEP_MINSTANEX && (button_zoom || zoomscript_caught))
+       else if((activeweapon == WEP_NEX || activeweapon == WEP_RIFLE || activeweapon == WEP_MINSTANEX) && (button_zoom || zoomscript_caught))
                reticle_type = 2; // nex zoom
        else if(button_zoom || zoomscript_caught)
                reticle_type = 1; // normal zoom
-       else if(activeweapon == WEP_NEX && button_attack2 || activeweapon == WEP_RIFLE && button_attack2)
+       else if((activeweapon == WEP_NEX) && button_attack2)
                reticle_type = 2; // nex zoom
-     
        if(reticle_type && autocvar_cl_reticle)
        {
                if(autocvar_cl_reticle_stretch)
                        old_bluralpha = 0;
                }
  
-               // edge detection postprocess handling done second (used by hud_powerup) 
+               // edge detection postprocess handling done second (used by hud_powerup)
                float sharpen_intensity = 0, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED);
                if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
                if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
-               
                sharpen_intensity = bound(0, ((getstati(STAT_HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds.
-               
                if(autocvar_hud_powerup && sharpen_intensity > 0)
                {
                        if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible
        if(hit_time > nextsound_hit_time && autocvar_cl_hitsound)
        {
                if(time - hit_time < MAX_TIME_DIFF) // don't play the sound if it's too old.
-                       sound(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTN_NONE);
-                       
+                       sound(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTEN_NONE);
                nextsound_hit_time = time + autocvar_cl_hitsound_antispam_time;
        }
        typehit_time = getstatf(STAT_TYPEHIT_TIME);
-       if(typehit_time > nextsound_typehit_time) 
+       if(typehit_time > nextsound_typehit_time)
        {
                if(time - typehit_time < MAX_TIME_DIFF) // don't play the sound if it's too old.
-                       sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTN_NONE);
-                       
+                       sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTEN_NONE);
                nextsound_typehit_time = time + autocvar_cl_hitsound_antispam_time;
        }
  
                                CSQC_common_hud();
  
                // crosshair goes VERY LAST
-               if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1 && hud == HUD_NORMAL) 
+               if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1 && hud == HUD_NORMAL)
                {
-                       if not(autocvar_crosshair_enabled) // main toggle for crosshair rendering
+                       if (!autocvar_crosshair_enabled) // main toggle for crosshair rendering
                                return;
-                               
                        string wcross_style;
                        float wcross_alpha, wcross_resolution;
                        wcross_style = autocvar_crosshair;
                                }
                        }
  
-                       //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_crosshair_pickup)
                        {
                                float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
-                               
                                if(pickup_crosshair_time < stat_pickup_time)
                                {
                                        if(time - stat_pickup_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old
                                                pickup_crosshair_size = 1;
-                                               
                                        pickup_crosshair_time = stat_pickup_time;
                                }
  
                        if(autocvar_crosshair_hitindication)
                        {
                                vector hitindication_color = ((autocvar_crosshair_color_special == 1) ? stov(autocvar_crosshair_hitindication_per_weapon_color) : stov(autocvar_crosshair_hitindication_color));
-                               
                                if(hitindication_crosshair_time < hit_time)
                                {
                                        if(time - hit_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old
                                                hitindication_crosshair_size = 1;
-                                               
                                        hitindication_crosshair_time = hit_time;
                                }
  
                                        // handle the values
                                        if (autocvar_crosshair_ring && activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex
                                        {
-                                               if (nex_chargepool || use_nex_chargepool) { 
-                                                       use_nex_chargepool = 1; 
+                                               if (nex_chargepool || use_nex_chargepool) {
+                                                       use_nex_chargepool = 1;
                                                        ring_inner_value = nex_chargepool;
-                                               } else { 
+                                               } else {
                                                        nex_charge_movingavg = (1 - autocvar_crosshair_ring_nex_currentcharge_movingavg_rate) * nex_charge_movingavg + autocvar_crosshair_ring_nex_currentcharge_movingavg_rate * nex_charge;
-                                                       ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1); 
+                                                       ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1);
                                                }
  
                                                ring_inner_alpha = autocvar_crosshair_ring_nex_inner_alpha;
                                                ring_rgb = wcross_color;
                                                ring_image = "gfx/crosshair_ring_nexgun.tga";
                                        }
-                                       else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer) 
+                                       else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
                                        {
                                                ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
                                                ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
                                                ring_image = "gfx/crosshair_ring.tga";
                                        }
  
-                                       if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring 
+                                       if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
                                        {
                                                ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
                                                ring_scale = autocvar_crosshair_ring_reload_size;
                                        if(autocvar_crosshair_effect_time > 0)
                                        {
                                                f = (time - wcross_name_changestarttime) / autocvar_crosshair_effect_time;
-                                               if not(f < 1)
+                                               if (!(f < 1))
                                                {
                                                        wcross_ring_prev = ((ring_image) ? TRUE : FALSE);
                                                }
-                                               
                                                if(wcross_ring_prev)
                                                {
                                                        if(f < 1)
                                {
                                        vector wcross_color_old;
                                        wcross_color_old = wcross_color;
-                                       
                                        if((autocvar_crosshair_dot_color_custom) && (autocvar_crosshair_dot_color != "0"))
                                                wcross_color = stov(autocvar_crosshair_dot_color);
-                                               
                                        CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha);
                                        // FIXME why don't we use wcross_alpha here?cl_notice_run();
                                        wcross_color = wcross_color_old;
  
        if(autocvar__hud_configure)
                HUD_Panel_Mouse();
-     
      if(hud && !intermission)
-     {        
+     {
          if(hud == HUD_SPIDERBOT)
              CSQC_SPIDER_HUD();
          else if(hud == HUD_WAKIZASHI)
          else if(hud == HUD_BUMBLEBEE_GUN)
              CSQC_BUMBLE_GUN_HUD();
      }
-       
        cl_notice_run();
-       
        // let's reset the view back to normal for the end
        setproperty(VF_MIN, '0 0 0');
        setproperty(VF_SIZE, '1 0 0' * w + '0 1 0' * h);
@@@ -1585,16 -1660,32 +1660,16 @@@ void CSQC_common_hud(void
        if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS))
                Accuracy_LoadLevels();
  
 -    HUD_Main(); // always run these functions for alpha checks
 -    HUD_DrawScoreboard();
 +      HUD_Main(); // always run these functions for alpha checks
 +      HUD_DrawScoreboard();
  
 -    if (scoreboard_active) // scoreboard/accuracy
 -        HUD_Reset();
 -    else if (intermission == 2) // map voting screen
 -    {
 -        HUD_FinaleOverlay();
 -        HUD_Reset();
 -    }
 -      /*
 -      switch(hud)
 +      if (scoreboard_active) // scoreboard/accuracy
 +              HUD_Reset();
 +      else if (intermission == 2) // map voting screen
        {
 -              case HUD_SPIDERBOT:
 -                      CSQC_SPIDER_HUD();
 -                      break;
 -
 -              case HUD_WAKIZASHI:
 -                      CSQC_WAKIZASHI_HUD();
 -                      break;
 -
 -        case HUD_BUMBLEBEE:
 -            CSQC_BUMBLE_HUD();
 -            break;
 +              MapVote_Draw();
 +              HUD_Reset();
        }
 -      */
  }
  
  
index eeeff8201e4a878e6f57b13df03a8ad0205977ee,43aab6ae44c73f3c2b0c598bbe4ae3d72014248e..5ba321ae17d89456f3411c36eff91d8144fcdf65
@@@ -54,6 -54,8 +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;
@@@ -337,19 -339,9 +339,19 @@@ float autocvar_hud_panel_weapons_timeou
  float autocvar_hud_panel_weapons_timeout_effect;
  float autocvar_hud_panel_weapons_timeout_fadebgmin;
  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_in = 0.25;
  var float autocvar_hud_panel_weapons_timeout_speed_out = 0.75;
 +vector autocvar_hud_progressbar_acceleration_color;
 +vector autocvar_hud_progressbar_acceleration_neg_color;
  float autocvar_hud_progressbar_alpha;
 +vector autocvar_hud_progressbar_armor_color;
 +vector autocvar_hud_progressbar_fuel_color;
 +vector autocvar_hud_progressbar_health_color;
 +vector autocvar_hud_progressbar_nexball_color;
 +vector autocvar_hud_progressbar_shield_color;
 +vector autocvar_hud_progressbar_speed_color;
 +vector autocvar_hud_progressbar_strength_color;
 +vector autocvar_hud_progressbar_superweapons_color;
  float autocvar_hud_showbinds;
  float autocvar_hud_showbinds_limit;
  float autocvar__hud_showbinds_reload;
@@@ -434,7 -426,6 +436,6 @@@ float autocvar_cl_forcemyplayercolors
  float autocvar__cl_color;
  float autocvar__cl_playerskin;
  string autocvar__cl_playermodel;
- float autocvar_cl_precacheplayermodels;
  float autocvar_cl_deathglow;
  float autocvar_developer_csqcentities;
  float autocvar_g_jetpack_attenuation;
index e6bd3c8d88424670c70af4de4a1c711090410cac,6f008fb541a118c53c2a10cf0513d64fffe61dd9..120b6658df8792443433fc40d7192bc89c4e809b
@@@ -93,7 -93,7 +93,7 @@@ string forceplayermodels_goodmodel
  float forceplayermodels_goodmodelindex;
  
  .vector glowmod;
- .vector old_glowmod; 
+ .vector old_glowmod;
  
  void CSQCPlayer_ModelAppearance_PreUpdate(void)
  {
@@@ -114,14 -114,14 +114,14 @@@ void CSQCPlayer_ModelAppearance_PostUpd
                self.forceplayermodels_isgoodmodel = fexists(self.forceplayermodels_savemodel);
                self.forceplayermodels_isgoodmodel_mdl = self.forceplayermodels_savemodel;
                if(!self.forceplayermodels_isgoodmodel)
-                       print(sprintf("Warning: missing model %s has been used\n", self.forceplayermodels_savemodel));
+                       printf("Warning: missing model %s has been used\n", self.forceplayermodels_savemodel);
        }
  }
  void CSQCPlayer_ModelAppearance_Apply(float islocalplayer)
  {
        // FORCEMODEL
        // which one is ALWAYS good?
-       if not(forceplayermodels_goodmodel)
+       if (!forceplayermodels_goodmodel)
        {
                entity e;
                e = spawn();
        float isfriend;
        float cm;
        cm = self.forceplayermodels_savecolormap;
-       cm = (cm >= 1024) ? cm : (stof(getplayerkeyvalue(self.colormap - 1, "colors")) + 1024);
+       cm = (cm >= 1024) ? cm : (stof(getplayerkeyvalue(cm - 1, "colors")) + 1024);
  
        if(teamplay)
                isfriend = (cm == 1024 + 17 * myteam);
                // own team's color is never forced
                float forcecolor_friend = 0;
                float forcecolor_enemy = 0;
 -              float teams_count = 0;
                entity tm;
  
 -              for(tm = teams.sort_next; tm; tm = tm.sort_next)
 -                      if(tm.team != NUM_SPECTATOR)
 -                              ++teams_count;
 -
                if(autocvar_cl_forcemyplayercolors)
                        forcecolor_friend = 1024 + autocvar_cl_forcemyplayercolors;
 -              if(autocvar_cl_forceplayercolors && teams_count == 2)
 +              if(autocvar_cl_forceplayercolors && team_count == 2)
                        forcecolor_enemy = 1024 + autocvar__cl_color;
  
                if(forcecolor_enemy && !forcecolor_friend)
                        // Fade out to black now...
                        if(self.old_glowmod == '0 0 0') { self.old_glowmod = self.glowmod; }
                        self.colormap = 0;
-                       
                        self.glowmod = self.old_glowmod * bound(0, 1 - (time - self.death_time) / autocvar_cl_deathglow, 1);
                        self.glowmod_x = max(self.glowmod_x, 0.0001);
                        self.glowmod_y = max(self.glowmod_y, 0.0001);
                else if(self.old_glowmod != '0 0 0') { self.old_glowmod = '0 0 0'; }
        }
  
-       //print(sprintf("CSQCPlayer_ModelAppearance_Apply(): state = %s, colormap = %f, glowmod = %s\n", (self.csqcmodel_isdead ? "DEAD" : "ALIVE"), self.colormap, vtos(self.glowmod)));
+       //printf("CSQCPlayer_ModelAppearance_Apply(): state = %s, colormap = %f, glowmod = %s\n", (self.csqcmodel_isdead ? "DEAD" : "ALIVE"), self.colormap, vtos(self.glowmod));
  }
  
  // FEATURE: fallback frames
@@@ -357,7 -362,7 +357,7 @@@ float CSQCPlayer_FallbackFrame(float f
                case 29: return 4; // anim_duckwalkbackright -> anim_duckwalk
                case 30: return 4; // anim_duckwalkbackleft -> anim_duckwalk
        }
-       print(sprintf("Frame %d missing in model %s, and we have no fallback - FAIL!\n", f, self.model));
+       printf("Frame %d missing in model %s, and we have no fallback - FAIL!\n", f, self.model);
        return f;
  }
  void CSQCPlayer_FallbackFrame_Apply(void)
@@@ -447,22 -452,22 +447,22 @@@ void CSQCModel_AutoTagIndex_Apply(void
  }
  
  // FEATURE: EF_NODRAW workalike
float EF_BRIGHTFIELD  = 1;
float EF_BRIGHTLIGHT  = 4;
float EF_DIMLIGHT     = 8;
- float EF_DOUBLESIDED = 32768;
- float EF_NOSELFSHADOW = 65536;
- float EF_DYNAMICMODELLIGHT = 131072;
- float EF_RESTARTANIM_BIT = 1048576;
- float EF_TELEPORT_BIT = 2097152;
- float MF_ROCKET  =   1; // leave a trail
- float MF_GRENADE =   2; // leave a trail
- float MF_GIB     =   4; // leave a trail
- float MF_ROTATE  =   8; // rotate (bonus items)
- float MF_TRACER  =  16; // green split trail
- float MF_ZOMGIB  =  32; // small blood trail
- float MF_TRACER2 =  64; // orange split trail
- float MF_TRACER3 = 128; // purple trail
const float EF_BRIGHTFIELD    = 1;
const float EF_BRIGHTLIGHT    = 4;
const float EF_DIMLIGHT       = 8;
const float EF_DOUBLESIDED = 32768;
const float EF_NOSELFSHADOW = 65536;
const float EF_DYNAMICMODELLIGHT = 131072;
const float EF_RESTARTANIM_BIT = 1048576;
const float EF_TELEPORT_BIT = 2097152;
const float MF_ROCKET  =   1; // leave a trail
const float MF_GRENADE =   2; // leave a trail
const float MF_GIB     =   4; // leave a trail
const float MF_ROTATE  =   8; // rotate (bonus items)
const float MF_TRACER  =  16; // green split trail
const float MF_ZOMGIB  =  32; // small blood trail
const float MF_TRACER2 =  64; // orange split trail
const float MF_TRACER3 = 128; // purple trail
  .float csqcmodel_effects;
  .float csqcmodel_modelflags;
  void CSQCModel_Effects_PreUpdate(void)
@@@ -483,12 -488,12 +483,12 @@@ void CSQCModel_Effects_PostUpdate(void
  void CSQCModel_Effects_Apply(void)
  {
        float eff = self.csqcmodel_effects;
-       eff &~= CSQCMODEL_EF_RESPAWNGHOST;
+       eff &= ~CSQCMODEL_EF_RESPAWNGHOST;
  
-       self.renderflags &~= (RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS);
+       self.renderflags &= ~(RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS);
        self.effects = 0;
        self.traileffect = 0;
-                       
        if(eff & EF_BRIGHTFIELD)
                self.traileffect = particleeffectnum("TR_NEXUIZPLASMA");
        // ignoring EF_MUZZLEFLASH
@@@ -605,7 -610,22 +605,22 @@@ void CSQCModel_Hook_PreDraw(float ispla
                CSQCPlayer_ModelAppearance_Apply(self.entnum == player_localnum + 1);
                CSQCPlayer_LOD_Apply();
                if(!isplayer)
+               {
+                       skeleton_loadinfo(self);
+                       float doblend = (self.bone_upperbody >= 0);
                        CSQCPlayer_FallbackFrame_Apply();
+                       if(doblend)
+                       {
+                               skeleton_from_frames(self, self.csqcmodel_isdead);
+                       }
+                       else
+                       {
+                               free_skeleton_from_frames(self);
+                               // just in case, clear these (we're animating in frame and frame3)
+                               self.lerpfrac = 0;
+                               self.lerpfrac4 = 0;
+                       }
+               }
                else
                {
                        // we know that frame3 and frame4 fields, used by InterpolateAnimation, are left alone - but that is all we know!
diff --combined qcsrc/client/hud.qc
index 365496e7767d860ede359ca63441752bc2422a9f,252142506f88731b28e21e679c0bd5d84b7d52b2..d5f74f22a726c64ecf2c721b8aac958446b62614
@@@ -142,16 -142,16 +142,16 @@@ float stringwidth_nocolors(string s, ve
        return stringwidth(s, FALSE, theSize);
  }
  
- void drawstringright(vector position, string text, vector scale, vector rgb, float theAlpha, float flag)
+ void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
  {
-       position_x -= 2 / 3 * strlen(text) * scale_x;
-       drawstring(position, text, scale, rgb, theAlpha, flag);
+       position_x -= 2 / 3 * strlen(text) * theScale_x;
+       drawstring(position, text, theScale, rgb, theAlpha, flag);
  }
  
- void drawstringcenter(vector position, string text, vector scale, vector rgb, float theAlpha, float flag)
+ void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
  {
-       position_x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * scale_x);
-       drawstring(position, text, scale, rgb, theAlpha, flag);
+       position_x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale_x);
+       drawstring(position, text, theScale, rgb, theAlpha, flag);
  }
  
  // return the string of the onscreen race timer
@@@ -242,7 -242,7 +242,7 @@@ float GetPlayerColorForce(float i
  
  float GetPlayerColor(float i)
  {
-       if not(playerslots[i].gotscores) // unconnected
+       if(!playerslots[i].gotscores) // unconnected
                return NUM_SPECTATOR;
        else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
                return NUM_SPECTATOR;
@@@ -264,8 -264,8 +264,8 @@@ HUD panel
  
  // draw the background/borders
  #define HUD_Panel_DrawBg(theAlpha)\
 -if(panel_bg != "0" && panel_bg != "")\
 -      draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * theAlpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER))
 +if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")\
 +      draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel.current_panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * theAlpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER))
  
  //basically the same code of draw_ButtonPicture and draw_VertButtonPicture for the menu
  void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, float vertical, float baralign, vector theColor, float theAlpha, float drawflag)
@@@ -447,8 -447,7 +447,7 @@@ float GetAmmoTypeForWep(float i
  void HUD_Weapons(void)
  {
        // declarations
-       WEPSET_DECLARE_A(weapons_stat);
-       WEPSET_COPY_AS(weapons_stat);
+       WepSet weapons_stat = WepSet_GetFromStat();
        float i, f, a;
        float screen_ar, center_x = 0, center_y;
        float weapon_count, weapon_id;
  
        // update generic hud functions
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        draw_beginBoldFont();
  
        {
                if(autocvar__hud_configure)
                {
-                       if (WEPSET_EMPTY_A(weapons_stat))
+                       if (!weapons_stat)
                                for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
-                                       WEPSET_OR_AW(weapons_stat, i);
+                                       weapons_stat |= WepSet_FromWeapon(i);
  
                        if(menu_enabled != 2)
                                HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
                // do we own this weapon?
                weapon_count = 0;
                for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
-                       if(WEPSET_CONTAINS_AW(weapons_stat, weaponorder[i].weapon))
+                       if(weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon))
                                ++weapon_count;
  
                // add it anyway if weaponcomplain is shown
  
                // skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon
                if(autocvar_hud_panel_weapons_onlyowned)
-               if not(WEPSET_CONTAINS_AW(weapons_stat, self.weapon) || (self.weapon == complain_weapon))
+               if (!((weapons_stat & WepSet_FromWeapon(self.weapon)) || (self.weapon == complain_weapon)))
                        continue;
  
                // figure out the drawing position of weapon
-               weapon_pos = (panel_pos 
-                       + eX * column * weapon_size_x 
+               weapon_pos = (panel_pos
+                       + eX * column * weapon_size_x
                        + eY * row * weapon_size_y);
  
                // draw background behind currently selected weapon
                }
  
                // drawing all the weapon items
-               if(WEPSET_CONTAINS_AW(weapons_stat, self.weapon))
+               if(weapons_stat & WepSet_FromWeapon(self.weapon))
                {
                        // draw the weapon image
                        drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
@@@ -941,7 -941,7 +940,7 @@@ void DrawAmmoItem(vector myPos, vector 
  
  void HUD_Ammo(void)
  {
 -    if(hud != HUD_NORMAL) return;
 +      if(hud != HUD_NORMAL) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_ammo) return;
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        draw_beginBoldFont();
  
                mySize -= '2 2 0' * panel_bg_padding;
        }
  
 +      const float AMMO_COUNT = 4;
        float rows = 0, columns, row, column;
        vector ammo_size;
        if (autocvar_hud_panel_ammo_onlycurrent)
@@@ -1133,7 -1133,7 +1132,7 @@@ void HUD_Powerups(void
        {
                if(!autocvar_hud_panel_powerups) return;
                if(spectatee_status == -1) return;
-               if not(getstati(STAT_ITEMS, 0, 24) & (IT_STRENGTH | IT_INVINCIBLE | IT_SUPERWEAPON)) return;
+               if(!(getstati(STAT_ITEMS, 0, 24) & (IT_STRENGTH | IT_INVINCIBLE | IT_SUPERWEAPON))) return;
                if (getstati(STAT_HEALTH) <= 0) return;
  
                strength_time = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99);
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        draw_beginBoldFont();
  
                const float maxshield = 30;
                float shield = ceil(shield_time);
                if(autocvar_hud_panel_powerups_progressbar)
 -              {
 -                      HUD_Panel_GetProgressBarColor(shield);
 -                      HUD_Panel_DrawProgressBar(pos + shield_offset, mySize, autocvar_hud_panel_powerups_progressbar_shield, shield/maxshield, is_vertical, shield_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -              }
 +                      HUD_Panel_DrawProgressBar(pos + shield_offset, mySize, autocvar_hud_panel_powerups_progressbar_shield, shield/maxshield, is_vertical, shield_baralign, autocvar_hud_progressbar_shield_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                if(autocvar_hud_panel_powerups_text)
                {
                        if(shield > 1)
                const float maxstrength = 30;
                float strength = ceil(strength_time);
                if(autocvar_hud_panel_powerups_progressbar)
 -              {
 -                      HUD_Panel_GetProgressBarColor(strength);
 -                      HUD_Panel_DrawProgressBar(pos + strength_offset, mySize, autocvar_hud_panel_powerups_progressbar_strength, strength/maxstrength, is_vertical, strength_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -              }
 +                      HUD_Panel_DrawProgressBar(pos + strength_offset, mySize, autocvar_hud_panel_powerups_progressbar_strength, strength/maxstrength, is_vertical, strength_baralign, autocvar_hud_progressbar_strength_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                if(autocvar_hud_panel_powerups_text)
                {
                        if(strength > 1)
                const float maxsuperweapons = 30;
                float superweapons = ceil(superweapons_time);
                if(autocvar_hud_panel_powerups_progressbar)
 -              {
 -                      HUD_Panel_GetProgressBarColor(superweapons);
 -                      HUD_Panel_DrawProgressBar(pos + superweapons_offset, mySize, autocvar_hud_panel_powerups_progressbar_superweapons, superweapons/maxsuperweapons, is_vertical, superweapons_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -              }
 +                      HUD_Panel_DrawProgressBar(pos + superweapons_offset, mySize, autocvar_hud_panel_powerups_progressbar_superweapons, superweapons/maxsuperweapons, is_vertical, superweapons_baralign, autocvar_hud_progressbar_superweapons_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                if(autocvar_hud_panel_powerups_text)
                {
                        if(superweapons > 1)
@@@ -1386,6 -1396,7 +1385,6 @@@ void HUD_HealthArmor(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
        if(autocvar_hud_panel_healtharmor == 2) // combined health and armor display
        {
                vector v;
-               v = healtharmor_maxdamage(health, armor, armorblockpercent);
+               v = healtharmor_maxdamage(health, armor, armorblockpercent, DEATH_WEAPON);
  
                float x;
                x = floor(v_x + 1);
                {
                        biggercount = "health";
                        if(autocvar_hud_panel_healtharmor_progressbar)
 -                      {
 -                              HUD_Panel_GetProgressBarColor(health);
 -                              HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_health, x/maxtotal, 0, (baralign == 1 || baralign == 2), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -                      }
 +                              HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_health, x/maxtotal, 0, (baralign == 1 || baralign == 2), autocvar_hud_progressbar_health_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                        if(armor)
              if(autocvar_hud_panel_healtharmor_text)
                                drawpic_aspect_skin(pos + eX * mySize_x - eX * 0.5 * mySize_y, "armor", '0.5 0.5 0' * mySize_y, '1 1 1', panel_fg_alpha * armor / health, DRAWFLAG_NORMAL);
                {
                        biggercount = "armor";
                        if(autocvar_hud_panel_healtharmor_progressbar)
 -                      {
 -                              HUD_Panel_GetProgressBarColor(armor);
 -                              HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, x/maxtotal, 0, (baralign == 1 || baralign == 2), progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -                      }
 +                              HUD_Panel_DrawProgressBar(pos, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, x/maxtotal, 0, (baralign == 1 || baralign == 2), autocvar_hud_progressbar_armor_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                        if(health)
              if(autocvar_hud_panel_healtharmor_text)
                                drawpic_aspect_skin(pos + eX * mySize_x - eX * 0.5 * mySize_y, "health", '0.5 0.5 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                        DrawNumIcon(pos, mySize, x, biggercount, 0, iconalign, HUD_Get_Num_Color(x, maxtotal), 1);
  
                if(fuel)
 -              {
 -                      HUD_Panel_GetProgressBarColor(fuel);
 -                      HUD_Panel_DrawProgressBar(pos, eX * mySize_x + eY * 0.2 * mySize_y, "progressbar", fuel/100, 0, (baralign == 1 || baralign == 3), progressbar_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
 -              }
 +                      HUD_Panel_DrawProgressBar(pos, eX * mySize_x + eY * 0.2 * mySize_y, "progressbar", fuel/100, 0, (baralign == 1 || baralign == 3), autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
        }
        else
        {
                {
                        if(autocvar_hud_panel_healtharmor_progressbar)
                        {
 -                              HUD_Panel_GetProgressBarColor(health);
                                float p_health, pain_health_alpha;
                                p_health = health;
                                pain_health_alpha = 1;
                                                if (time - health_damagetime < 1)
                                                {
                                                        float health_damagealpha = 1 - (time - health_damagetime)*(time - health_damagetime);
 -                                                      HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, health_beforedamage/maxhealth, is_vertical, health_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * health_damagealpha, DRAWFLAG_NORMAL);
 +                                                      HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, health_beforedamage/maxhealth, is_vertical, health_baralign, autocvar_hud_progressbar_health_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * health_damagealpha, DRAWFLAG_NORMAL);
                                                }
                                        }
                                        prev_health = health;
                                        {
                                                float BLINK_FACTOR = 0.15;
                                                float BLINK_BASE = 0.85;
-                                               float BLINK_FREQ = 9; 
+                                               float BLINK_FREQ = 9;
                                                pain_health_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
                                        }
                                }
 -                              HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, p_health/maxhealth, is_vertical, health_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * pain_health_alpha, DRAWFLAG_NORMAL);
 +                              HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, p_health/maxhealth, is_vertical, health_baralign, autocvar_hud_progressbar_health_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * pain_health_alpha, DRAWFLAG_NORMAL);
                        }
                        if(autocvar_hud_panel_healtharmor_text)
                                DrawNumIcon(pos + health_offset, mySize, health, "health", is_vertical, health_iconalign, HUD_Get_Num_Color(health, maxhealth), 1);
                {
                        if(autocvar_hud_panel_healtharmor_progressbar)
                        {
 -                              HUD_Panel_GetProgressBarColor(armor);
                                float p_armor;
                                p_armor = armor;
                                if (autocvar_hud_panel_healtharmor_progressbar_gfx)
                                                if (time - armor_damagetime < 1)
                                                {
                                                        float armor_damagealpha = 1 - (time - armor_damagetime)*(time - armor_damagetime);
 -                                                      HUD_Panel_DrawProgressBar(pos + armor_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, armor_beforedamage/maxarmor, is_vertical, armor_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * armor_damagealpha, DRAWFLAG_NORMAL);
 +                                                      HUD_Panel_DrawProgressBar(pos + armor_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, armor_beforedamage/maxarmor, is_vertical, armor_baralign, autocvar_hud_progressbar_armor_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * armor_damagealpha, DRAWFLAG_NORMAL);
                                                }
                                        }
                                        prev_armor = armor;
                                }
 -                              HUD_Panel_DrawProgressBar(pos + armor_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, p_armor/maxarmor, is_vertical, armor_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 +                              HUD_Panel_DrawProgressBar(pos + armor_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_armor, p_armor/maxarmor, is_vertical, armor_baralign, autocvar_hud_progressbar_armor_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                        }
                        if(autocvar_hud_panel_healtharmor_text)
                                DrawNumIcon(pos + armor_offset, mySize, armor, "armor", is_vertical, armor_iconalign, HUD_Get_Num_Color(armor, maxarmor), 1);
                                mySize_x *= 2; //restore full panel size
                        else if (panel_ar < 1/4)
                                mySize_y *= 2; //restore full panel size
 -                      HUD_Panel_GetProgressBarColor(fuel);
 -                      HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", fuel/100, is_vertical, fuel_baralign, progressbar_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
 +                      HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", fuel/100, is_vertical, fuel_baralign, autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
                }
        }
  }
@@@ -1626,6 -1649,7 +1625,6 @@@ void HUD_Notify(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
        float entries, height;
        entries = bound(1, floor(KN_MAX_ENTRIES * mySize_y/mySize_x), KN_MAX_ENTRIES);
        height = mySize_y/entries;
-       
        vector fontsize;
        float fontheight = height * autocvar_hud_panel_notify_fontsize;
        fontsize = '0.5 0.5 0' * fontheight;
                        {
                                break;
                        }
-                       
                        attacker = notify_attackers[j];
                        victim = notify_victims[j];
                        icon = notify_icon[j];
@@@ -1762,6 -1786,7 +1761,6 @@@ void HUD_Timer(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        draw_beginBoldFont();
  
@@@ -1829,6 -1854,7 +1828,6 @@@ void HUD_Radar(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        float f = 0;
  
                panel_pos_x = (vid_conwidth - panel_size_x) / 2;
                panel_pos_y = (vid_conheight - panel_size_y) / 2;
  
 +              string panel_bg;
                panel_bg = strcat(hud_skin_path, "/border_default"); // always use the default border when maximized
 -              if(precache_pic(panel_bg) == "") { panel_bg = "gfx/hud/default/border_default"; } // fallback
 +              if(precache_pic(panel_bg) == "")
 +                      panel_bg = "gfx/hud/default/border_default"; // fallback
 +              if(panel.current_panel_bg)
 +                      strunzone(panel.current_panel_bg);
 +              panel.current_panel_bg = strzone(panel_bg);
  
                switch(hud_panel_radar_maximized_zoommode)
                {
                                f = 1;
                                break;
                }
-               
                switch(hud_panel_radar_maximized_rotation)
                {
                        case 0:
                                f = 1;
                                break;
                }
-               
                switch(hud_panel_radar_rotation)
                {
                        case 0:
  // Score (#7)
  //
  void HUD_UpdatePlayerTeams();
 -void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
 +void HUD_Score_Rankings(vector pos, vector mySize, entity me)
  {
        float score;
        entity tm = world, pl;
@@@ -2125,6 -2146,7 +2124,6 @@@ void HUD_Score(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
        } else if (!teamplay) { // non-teamgames
                if ((spectatee_status == -1 && !autocvar__hud_configure) || autocvar_hud_panel_score_rankings)
                {
 -                      HUD_Score_Rankings(pos, mySize, me, 0);
 +                      HUD_Score_Rankings(pos, mySize, me);
                        return;
                }
                // me vector := [team/connected frags id]
                drawstring_aspect(pos + eX * 0.75 * mySize_x, distribution_str, eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                draw_endBoldFont();
        } else { // teamgames
 -              float scores_count = 0, row, column, rows = 0, columns = 0;
 +              float row, column, rows = 0, columns = 0;
                local noref vector offset = '0 0 0';
                vector score_pos, score_size; //for scores other than myteam
 -              if (spectatee_status == -1 || autocvar_hud_panel_score_rankings)
 +              if(autocvar_hud_panel_score_rankings)
 +              {
 +                      HUD_Score_Rankings(pos, mySize, me);
 +                      return;
 +              }
 +              if(spectatee_status == -1)
                {
 -                      for(tm = teams.sort_next; tm, tm.team != NUM_SPECTATOR; tm = tm.sort_next)
 -                              ++scores_count;
 -                      if (autocvar_hud_panel_score_rankings)
 -                      {
 -                              HUD_Score_Rankings(pos, mySize, me, scores_count);
 -                              return;
 -                      }
                        rows = mySize_y/mySize_x;
 -                      rows = bound(1, floor((sqrt(4 * (3/1) * rows * scores_count + rows * rows) + rows + 0.5) / 2), scores_count);
 +                      rows = bound(1, floor((sqrt(4 * (3/1) * rows * team_count + rows * rows) + rows + 0.5) / 2), team_count);
                        //                               ^^^ ammo item aspect goes here
  
 -                      columns = ceil(scores_count/rows);
 +                      columns = ceil(team_count/rows);
  
                        score_size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
  
                        score = tm.(teamscores[ts_primary]);
                        if(autocvar__hud_configure)
                                score = 123;
-                       
                        if (score > max_fragcount)
                                max_fragcount = score;
  
@@@ -2317,6 -2341,7 +2316,6 @@@ void HUD_RaceTimer (void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        draw_beginBoldFont();
  
@@@ -2517,6 -2542,7 +2516,6 @@@ void HUD_Vote(void
                return;
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        if(uid2name_dialog)
        {
@@@ -2667,6 -2693,11 +2666,6 @@@ void DrawCAItem(vector myPos, vector my
  void HUD_Mod_CA(vector myPos, vector mySize)
  {
        mod_active = 1; // required in each mod function that always shows something
 -      entity tm;
 -      float teams_count = 0;
 -      for(tm = teams.sort_next; tm; tm = tm.sort_next)
 -              if(tm.team != NUM_SPECTATOR)
 -                      ++teams_count;
  
        float layout;
        if(gametype == MAPINFO_TYPE_CA)
        float rows, columns, aspect_ratio;
        rows = mySize_y/mySize_x;
        aspect_ratio = (layout) ? 2 : 1;
 -      rows = bound(1, floor((sqrt((4 * aspect_ratio * teams_count + rows) * rows) + rows + 0.5) / 2), teams_count);
 -      columns = ceil(teams_count/rows);
 +      rows = bound(1, floor((sqrt((4 * aspect_ratio * team_count + rows) * rows) + rows + 0.5) / 2), team_count);
 +      columns = ceil(team_count/rows);
  
        int i;
        float row = 0, column = 0;
        vector pos, itemSize;
        itemSize = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
 -      for(i=0; i<teams_count; ++i)
 +      for(i=0; i<team_count; ++i)
        {
                pos = myPos + eX * column * itemSize_x + eY * row * itemSize_y;
  
@@@ -2721,7 -2752,7 +2720,7 @@@ void HUD_Mod_CTF(vector pos, vector myS
        stat_items = getstati(STAT_ITEMS, 0, 24);
        redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3;
        blueflag = (stat_items/IT_BLUE_FLAG_TAKEN) & 3;
-       
        if(redflag || blueflag)
                mod_active = 1;
        else
@@@ -2998,29 -3029,29 +2997,29 @@@ void HUD_Mod_KH(vector pos, vector mySi
  float kaball_prevstatus; // last remembered status
  float kaball_statuschange_time; // time when the status changed
  
- // we don't need to reset for keepaway since it immediately 
+ // we don't need to reset for keepaway since it immediately
  // autocorrects prevstatus as to if the player has the ball or not
  
  void HUD_Mod_Keepaway(vector pos, vector mySize)
  {
        mod_active = 1; // keepaway should always show the mod HUD
-       
        float BLINK_FACTOR = 0.15;
        float BLINK_BASE = 0.85;
-       float BLINK_FREQ = 5; 
+       float BLINK_FREQ = 5;
        float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
-       
        float stat_items = getstati(STAT_ITEMS, 0, 24);
        float kaball = (stat_items/IT_KEY1) & 1;
-       
        if(kaball != kaball_prevstatus)
        {
                kaball_statuschange_time = time;
                kaball_prevstatus = kaball;
        }
-       
        vector kaball_pos, kaball_size;
-       
        if(mySize_x > mySize_y) {
                kaball_pos = pos + eX * 0.25 * mySize_x;
                kaball_size = eX * 0.5 * mySize_x + eY * mySize_y;
                kaball_pos = pos + eY * 0.25 * mySize_y;
                kaball_size = eY * 0.5 * mySize_y + eX * mySize_x;
        }
-       
        float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
        float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
-       
        if(kaball_prevstatus && f < 1)
                drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
-       
        if(kaball)
                drawpic_aspect_skin(pos, "keepawayball_carrying", eX * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
  }
@@@ -3062,7 -3093,12 +3061,7 @@@ void HUD_Mod_NexBall(vector pos, vecto
                if (p > 1)
                        p = 2 - p;
  
 -              //Draw the filling
 -              HUD_Panel_GetProgressBarColor(nexball);
 -              if(mySize_x > mySize_y)
 -                      HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, 0, 0, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -              else
 -                      HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, 1, 0, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 +              HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, (mySize_x <= mySize_y), 0, autocvar_hud_progressbar_nexball_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
        }
  
        if (stat_items & IT_KEY1)
@@@ -3087,7 -3123,7 +3086,7 @@@ void HUD_Mod_Race(vector pos, vector my
        float f; // yet another function has this
        score = me.(scores[ps_primary]);
  
-       if not((scores_flags[ps_primary] & SFL_TIME) && !teamplay) // race/cts record display on HUD
+       if(!(scores_flags[ps_primary] & SFL_TIME) || teamplay) // race/cts record display on HUD
                return; // no records in the actual race
  
        // clientside personal record
                if(autocvar_cl_autodemo_delete_keeprecords)
                {
                        f = autocvar_cl_autodemo_delete;
-                       f &~= 1;
+                       f &= ~1;
                        cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
                }
        }
@@@ -3288,19 -3324,24 +3287,19 @@@ void DrawDomItem(vector myPos, vector m
  void HUD_Mod_Dom(vector myPos, vector mySize)
  {
        mod_active = 1; // required in each mod function that always shows something
 -      entity tm;
 -      float teams_count = 0;
 -      for(tm = teams.sort_next; tm; tm = tm.sort_next)
 -              if(tm.team != NUM_SPECTATOR)
 -                      ++teams_count;
  
        float layout = autocvar_hud_panel_modicons_dom_layout;
        float rows, columns, aspect_ratio;
        rows = mySize_y/mySize_x;
        aspect_ratio = (layout) ? 3 : 1;
 -      rows = bound(1, floor((sqrt((4 * aspect_ratio * teams_count + rows) * rows) + rows + 0.5) / 2), teams_count);
 -      columns = ceil(teams_count/rows);
 +      rows = bound(1, floor((sqrt((4 * aspect_ratio * team_count + rows) * rows) + rows + 0.5) / 2), team_count);
 +      columns = ceil(team_count/rows);
  
        int i;
        float row = 0, column = 0;
        vector pos, itemSize;
        itemSize = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
 -      for(i=0; i<teams_count; ++i)
 +      for(i=0; i<team_count; ++i)
        {
                pos = myPos + eX * column * itemSize_x + eY * row * itemSize_y;
  
        }
  }
  
 +void HUD_ModIcons_SetFunc()
 +{
 +      switch(gametype)
 +      {
 +              case MAPINFO_TYPE_KEYHUNT:              HUD_ModIcons_GameType = HUD_Mod_KH; break;
 +              case MAPINFO_TYPE_CTF:                  HUD_ModIcons_GameType = HUD_Mod_CTF; break;
 +              case MAPINFO_TYPE_NEXBALL:              HUD_ModIcons_GameType = HUD_Mod_NexBall; break;
 +              case MAPINFO_TYPE_CTS:
 +              case MAPINFO_TYPE_RACE:         HUD_ModIcons_GameType = HUD_Mod_Race; break;
 +              case MAPINFO_TYPE_CA:
 +              case MAPINFO_TYPE_FREEZETAG:    HUD_ModIcons_GameType = HUD_Mod_CA; break;
 +              case MAPINFO_TYPE_DOMINATION:   HUD_ModIcons_GameType = HUD_Mod_Dom; break;
 +              case MAPINFO_TYPE_KEEPAWAY:     HUD_ModIcons_GameType = HUD_Mod_Keepaway; break;
 +      }
 +}
 +
  float mod_prev; // previous state of mod_active to check for a change
  float mod_alpha;
  float mod_change; // "time" when mod_active changed
@@@ -3340,13 -3365,18 +3339,13 @@@ void HUD_ModIcons(void
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_modicons) return;
 -              if (gametype != MAPINFO_TYPE_CTF && gametype != MAPINFO_TYPE_KEYHUNT && gametype != MAPINFO_TYPE_NEXBALL && gametype != MAPINFO_TYPE_CTS && gametype != MAPINFO_TYPE_RACE && gametype != MAPINFO_TYPE_CA && gametype != MAPINFO_TYPE_FREEZETAG && gametype != MAPINFO_TYPE_KEEPAWAY && gametype != MAPINFO_TYPE_DOMINATION) return;
 +              if(!HUD_ModIcons_GameType) return;
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        draw_beginBoldFont();
  
 -      vector pos, mySize;
 -      pos = panel_pos;
 -      mySize = panel_size;
 -
        if(mod_active != mod_prev) {
                mod_change = time;
                mod_prev = mod_active;
  
        if(panel_bg_padding)
        {
 -              pos += '1 1 0' * panel_bg_padding;
 -              mySize -= '2 2 0' * panel_bg_padding;
 +              panel_pos += '1 1 0' * panel_bg_padding;
 +              panel_size -= '2 2 0' * panel_bg_padding;
        }
  
 -      // these MUST be ran in order to update mod_active
 -      if(gametype == MAPINFO_TYPE_KEYHUNT)
 -              HUD_Mod_KH(pos, mySize);
 -      else if(gametype == MAPINFO_TYPE_CTF || autocvar__hud_configure)
 -              HUD_Mod_CTF(pos, mySize); // forcealpha only needed for ctf icons, as only they are shown in config mode
 -      else if(gametype == MAPINFO_TYPE_NEXBALL)
 -              HUD_Mod_NexBall(pos, mySize);
 -      else if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE)
 -              HUD_Mod_Race(pos, mySize);
 -      else if(gametype == MAPINFO_TYPE_CA || gametype == MAPINFO_TYPE_FREEZETAG)
 -              HUD_Mod_CA(pos, mySize);
 -      else if(gametype == MAPINFO_TYPE_DOMINATION)
 -              HUD_Mod_Dom(pos, mySize);
 -      else if(gametype == MAPINFO_TYPE_KEEPAWAY)
 -              HUD_Mod_Keepaway(pos, mySize);
 +      if(autocvar__hud_configure)
 +              HUD_Mod_CTF(panel_pos, panel_size);
 +      else
 +              HUD_ModIcons_GameType(panel_pos, panel_size);
  
        draw_endBoldFont();
  }
@@@ -3385,6 -3426,7 +3384,6 @@@ void HUD_PressedKeys(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
@@@ -3456,20 -3498,20 +3455,20 @@@ void HUD_Chat(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        if(autocvar__con_chat_maximized && !autocvar__hud_configure) // draw at full screen height if maximized
        {
                panel_pos_y = panel_bg_border;
                panel_size_y = vid_conheight - panel_bg_border * 2;
 -              if(panel_bg == "0") // force a border when maximized
 +              if(panel.current_panel_bg == "0") // force a border when maximized
                {
 -                      if(precache_pic(panel_bg) == "") {
 -                              panel_bg = strcat(hud_skin_path, "/border_default");
 -                              if(precache_pic(panel_bg) == "") {
 -                                      panel_bg = "gfx/hud/default/border_default";
 -                              }
 -                      }
 +                      string panel_bg;
 +                      panel_bg = strcat(hud_skin_path, "/border_default");
 +                      if(precache_pic(panel_bg) == "")
 +                              panel_bg = "gfx/hud/default/border_default";
 +                      if(panel.current_panel_bg)
 +                              strunzone(panel.current_panel_bg);
 +                      panel.current_panel_bg = strzone(panel_bg);
                }
                panel_bg_alpha = max(0.75, panel_bg_alpha); // force an theAlpha of at least 0.75
        }
@@@ -3530,6 -3572,7 +3529,6 @@@ void HUD_EngineInfo(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
                frametimeavg = (frametimeavg + frametimeavg1 + frametimeavg2 + currentframetime)/4; // average three frametimes into framecounter for slightly more stable fps readings :P
                frametimeavg2 = frametimeavg1;
                frametimeavg1 = frametimeavg;
-               
                float weight;
                weight = cvar("hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight");
                if(currentframetime > 0.0001) // filter out insane values which sometimes seem to occur and throw off the average? If you are getting 10,000 fps or more, then you don't need a framerate counter.
@@@ -3590,6 -3633,7 +3589,6 @@@ void HUD_InfoMessages(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
  
        vector fontsize;
        fontsize = '0.20 0.20 0' * mySize_y;
-       
        float a;
        a = panel_fg_alpha;
  
                        s = sprintf(_("^1Press ^3%s^1 for gamemode info"), getcommandkey("server info", "+show_info"));
                        drawInfoMessage(s)
  
-                       if(gametype == MAPINFO_TYPE_ARENA)
-                               s = _("^1Wait for your turn to join");
-                       else if(gametype == MAPINFO_TYPE_LMS)
+                       if(gametype == MAPINFO_TYPE_LMS)
                        {
                                entity sk;
                                sk = playerslots[player_localnum];
                        }
                }
        }
-       else 
+       else
        {
                s = _("^7Press ^3ESC ^7to show HUD options.");
                drawInfoMessage(s)
@@@ -3778,6 -3820,7 +3775,6 @@@ void HUD_Physics(void
        }
  
        HUD_Panel_UpdateCvars();
 -      HUD_Panel_ApplyFadeAlpha();
  
        draw_beginBoldFont();
  
                        conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
                        break;
        }
-       
        vector vel = (csqcplayer ? csqcplayer.velocity : pmove_vel);
  
        float max_speed = floor( autocvar_hud_panel_physics_speed_max * conversion_factor + 0.5 );
                        acceleration = (vlen(vel) - vlen(acc_prevspeed));
                else
                        acceleration = (vlen(vel - '0 0 1' * vel_z) - vlen(acc_prevspeed - '0 0 1' * acc_prevspeed_z));
-               
                acceleration = acceleration * (1 / max(0.0001, f)) * (0.0254 / 9.80665);
-               
                acc_prevspeed = vel;
                acc_prevtime = time;
  
        //draw speed
        if(speed)
        if(autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 2)
 -      {
 -              HUD_Panel_GetProgressBarColor(speed);
 -              HUD_Panel_DrawProgressBar(panel_pos + speed_offset, panel_size, "progressbar", speed/max_speed, 0, speed_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -      }
 +              HUD_Panel_DrawProgressBar(panel_pos + speed_offset, panel_size, "progressbar", speed/max_speed, 0, speed_baralign, autocvar_hud_progressbar_speed_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
        vector tmp_offset = '0 0 0', tmp_size = '0 0 0';
        if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 2)
        {
                                        peak_offset_x = (1 - min(top_speed, max_speed)/max_speed) * panel_size_x;
                  else // if (speed_baralign == 2)
                      peak_offset_x = min(top_speed, max_speed)/max_speed * panel_size_x * 0.5;
 -                              //if speed is not 0 the speed progressbar already fetched the color
 -                              if (speed == 0)
 -                                      HUD_Panel_GetProgressBarColor(speed);
                                peak_size_x = floor(panel_size_x * 0.01 + 1.5);
                  peak_size_y = panel_size_y;
                  if (speed_baralign == 2) // draw two peaks, on both sides
                  {
 -                    drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size_x + peak_offset_x - peak_size_x), peak_size, progressbar_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -                    drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size_x - peak_offset_x + peak_size_x), peak_size, progressbar_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 +                    drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size_x + peak_offset_x - peak_size_x), peak_size, autocvar_hud_progressbar_speed_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 +                    drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size_x - peak_offset_x + peak_size_x), peak_size, autocvar_hud_progressbar_speed_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                  }
                  else
 -                    drawfill(panel_pos + speed_offset + eX * (peak_offset_x - peak_size_x), peak_size, progressbar_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 +                    drawfill(panel_pos + speed_offset + eX * (peak_offset_x - peak_size_x), peak_size, autocvar_hud_progressbar_speed_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                        }
  
                        //top speed
        if(acceleration)
        if(autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 3)
        {
 -              if (acceleration < 0)
 -                      HUD_Panel_GetProgressBarColor(acceleration_neg);
 +              vector progressbar_color;
 +              if(acceleration < 0)
 +                      progressbar_color = autocvar_hud_progressbar_acceleration_neg_color;
                else
 -                      HUD_Panel_GetProgressBarColor(acceleration);
 +                      progressbar_color = autocvar_hud_progressbar_acceleration_color;
  
                f = acceleration/autocvar_hud_panel_physics_acceleration_max;
                if (autocvar_hud_panel_physics_acceleration_progressbar_nonlinear)
@@@ -4047,7 -4095,7 +4044,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)
@@@ -4158,7 -4206,7 +4155,7 @@@ void HUD_CenterPrint (void
                        float r;
                        r = random();
                        if (r > 0.9)
-                               centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: %d"), 1, 10);
+                               centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
                        else if (r > 0.8)
                                centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
                        else
                }
        }
  
 +      // this panel fades only when the menu does
 +      float hud_fade_alpha_save = 0;
 +      if(scoreboard_fade_alpha)
 +      {
 +              hud_fade_alpha_save = hud_fade_alpha;
 +              hud_fade_alpha = 1 - autocvar__menu_alpha;
 +      }
        HUD_Panel_UpdateCvars();
  
 -      // this panel doesn't fade when showing the scoreboard
 -      if(autocvar__menu_alpha)
 -              HUD_Panel_ApplyFadeAlpha();
 -
        if(scoreboard_fade_alpha)
        {
 +              hud_fade_alpha = hud_fade_alpha_save;
 +
                // move the panel below the scoreboard
                if (scoreboard_bottom >= 0.96 * vid_conheight)
                        return;
                vector target_pos;
-               
                target_pos = eY * scoreboard_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
-               
                if(target_pos_y > panel_pos_y)
                {
                        panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha);
        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)
+               // fade the centerprint_hud in/out
+               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); 
-               
+               sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
                // also fade it based on positioning
                if(autocvar_hud_panel_centerprint_fade_subsequent)
                {
                        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)); 
+               sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize));
                drawfontscale = sz * '1 1 0';
-               
                if (centerprint_countdown_num[j])
                        n = tokenizebyseparator(strreplace("^COUNT", count_seconds(centerprint_countdown_num[j]), centerprint_messages[j]), "\n");
                else
                                {
                                        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
                        }
                }
  
-               ++g; // move next position number up 
-               
+               ++g; // move next position number up
                msg_size = pos_y - msg_size;
                if (autocvar_hud_panel_centerprint_flip)
                {
                        pos_y = current_msg_pos_y - CENTERPRINT_SPACING * fontsize_y;
                        if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages
                                pos_y += (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz));
-                               
                        if (pos_y < panel_pos_y) // check if the next message can be shown
                        {
                                drawfontscale = '1 1 0';
                        pos_y += CENTERPRINT_SPACING * fontsize_y;
                        if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages
                                pos_y -= (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz));
-                               
                        if(pos_y > panel_pos_y + panel_size_y - fontsize_y) // check if the next message can be shown
                        {
                                drawfontscale = '1 1 0';
                }
        }
        drawfontscale = '1 1 0';
-       if (n == -1)
+       if (all_messages_expired)
        {
                centerprint_showing = FALSE;
                reset_centerprint_messages();
@@@ -4372,13 -4420,21 +4374,13 @@@ void HUD_Main (void
        if(scoreboard_fade_alpha)
                hud_fade_alpha = (1 - scoreboard_fade_alpha);
  
 -      if(autocvar__hud_configure)
 -              if(isdemo())
 -                      HUD_Configure_Exit_Force();
 +      HUD_Configure_Frame();
  
        if(intermission == 2) // no hud during mapvote
 -      {
 -              if (autocvar__hud_configure)
 -                      HUD_Configure_Exit_Force();
                hud_fade_alpha = 0;
 -      }
 -      else if(autocvar__menu_alpha == 0 && scoreboard_fade_alpha == 0)
 -              hud_fade_alpha = 1;
  
        // panels that we want to be active together with the scoreboard
 -      // they must call HUD_Panel_ApplyFadeAlpha(); only when showing the menu
 +      // they must fade only when the menu does
        if(scoreboard_fade_alpha == 1)
        {
                (panel = HUD_PANEL(CENTERPRINT)).panel_draw();
                hud_skin_prev = strzone(autocvar_hud_skin);
        }
  
 -      // HUD configure visible grid
 -      if(autocvar__hud_configure && autocvar_hud_configure_grid && autocvar_hud_configure_grid_alpha)
 -      {
 -              hud_configure_gridSize_x = bound(0.005, cvar("hud_configure_grid_xsize"), 0.2);
 -              hud_configure_gridSize_y = bound(0.005, cvar("hud_configure_grid_ysize"), 0.2);
 -              hud_configure_realGridSize_x = hud_configure_gridSize_x * vid_conwidth;
 -              hud_configure_realGridSize_y = hud_configure_gridSize_y * vid_conheight;
 -              vector s;
 -              // x-axis
 -              s = eX + eY * vid_conheight;
 -              for(i = 1; i < 1/hud_configure_gridSize_x; ++i)
 -                      drawfill(eX * i * hud_configure_realGridSize_x, s, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL);
 -              // y-axis
 -              s = eY + eX * vid_conwidth;
 -              for(i = 1; i < 1/hud_configure_gridSize_y; ++i)
 -                      drawfill(eY * i * hud_configure_realGridSize_y, s, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL);
 -      }
 -
  #ifdef COMPAT_XON050_ENGINE
      current_player = (spectatee_status > 0) ? spectatee_status : player_localentnum;
  #else
        if(autocvar__con_chat_maximized)
                (panel = HUD_PANEL(CHAT)).panel_draw();
  
 -      if(autocvar__hud_configure)
 -      {
 -              if(tab_panel)
 -              {
 -                      panel = tab_panel;
 -                      HUD_Panel_UpdatePosSize()
 -                      drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .2, DRAWFLAG_NORMAL);
 -              }
 -              if(highlightedPanel)
 -              {
 -                      panel = highlightedPanel;
 -                      HUD_Panel_UpdatePosSize()
 -                      HUD_Panel_HlBorder(panel_bg_border + 1.5 * hlBorderSize, '0 0.5 1', 0.25 * (1 - autocvar__menu_alpha));
 -              }
 -              if(!hud_configure_prev || hud_configure_prev == -1)
 -              {
 -                      if(autocvar_hud_cursormode) { setcursormode(1); }
 -                      hudShiftState = 0;
 -                      for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
 -                              hud_panel[panel_order[i]].update_time = time;
 -              }
 -      }
 -      else if(hud_configure_prev && hud_configure_prev != -1 && autocvar_hud_cursormode)
 -              setcursormode(0);
 +      HUD_Configure_PostDraw();
  
        hud_configure_prev = autocvar__hud_configure;
 -
 -      if (!autocvar__hud_configure) // hud config mode disabled, enable normal theAlpha stuff again
 -              if (menu_enabled)
 -                      menu_enabled = 0;
  }
diff --combined qcsrc/client/hud.qh
index 12b3919b8e4fb6c254cb8a63fc59d87feb97c9a5,c2432b97c78191d5d8b38304cf14c414bf66b707..840e802148dfc8659613fa2eb6465c49b80a0351
@@@ -47,6 -47,7 +47,6 @@@ const float S_CTRL = 2
  const float S_ALT = 4;
  
  float menu_enabled; // 1 showing the entire HUD, 2 showing only the clicked panel
 -float menu_enabled_time;
  
  float hud_fade_alpha;
  
@@@ -55,6 -56,8 +55,6 @@@ string hud_skin_prev
  
  vector myteamcolors;
  
 -var vector progressbar_color;
 -
  entity highlightedPanel_backup;
  var vector panel_pos_backup;
  var vector panel_size_backup;
@@@ -77,6 -80,7 +77,6 @@@ entity panel
  var float panel_enabled;
  var vector panel_pos;
  var vector panel_size;
 -var string panel_bg;
  var string panel_bg_str; // "_str" vars contain the raw value of the cvar, non-"_str" contains what hud.qc code should use
  var vector panel_bg_color;
  var string panel_bg_color_str;
@@@ -128,7 -132,7 +128,7 @@@ float current_player
                hud_panelent.panel_draw = ##draw_func; \
                ++HUD_PANEL_NUM; \
        } \
-       ACCUMULATE_FUNCTION(RegisterHUD_Panels, RegisterHUD_Panel_##NAME)
+       ACCUMULATE_FUNCTION(RegisterHUD_Panels, RegisterHUD_Panel_##NAME);
  
  HUD_PANELS
  #undef HUD_PANEL
  // ----------------------
  // Little help for the poor people who have to make sense of this: Start from the bottom ;)
  
 -#define HUD_Panel_GetProgressBarColor(item) \
 -              progressbar_color = stov(cvar_string("hud_progressbar_" #item "_color"))
 -#define HUD_Panel_GetProgressBarColorForString(item) \
 -switch(item) {\
 -      case "health": HUD_Panel_GetProgressBarColor(health); break;\
 -      case "armor": HUD_Panel_GetProgressBarColor(armor); break;\
 -      case "strength": HUD_Panel_GetProgressBarColor(strength); break;\
 -      case "shield": HUD_Panel_GetProgressBarColor(shield); break;\
 -      case "fuel": HUD_Panel_GetProgressBarColor(fuel); break;\
 -      case "nexball": HUD_Panel_GetProgressBarColor(nexball); break;\
 -      case "speed": HUD_Panel_GetProgressBarColor(speed); break;\
 -      case "acceleration": HUD_Panel_GetProgressBarColor(acceleration); break;\
 -      case "acceleration_neg": HUD_Panel_GetProgressBarColor(acceleration_neg); break;\
 -} ENDS_WITH_CURLY_BRACE
 -
 -// Get value for panel_bg: if "" fetch default, else use panel_bg_str
 +// Get value for panel.current_panel_bg: if "" fetch default, else use panel_bg_str
  // comment on last line of macro: // we probably want to see a background in config mode at all times...
  #define HUD_Panel_GetBg()\
 +string panel_bg;\
  if(!autocvar__hud_configure && panel_bg_str == "0") {\
        panel_bg = "0";\
  } else {\
                        }\
                }\
        }\
 -}
 +}\
 +if(panel.current_panel_bg)\
 +      strunzone(panel.current_panel_bg);\
 +panel.current_panel_bg = strzone(panel_bg);
  
  // Get value for panel_bg_color: if "" fetch default, else use panel_bg_color. Convert pants, shirt or teamcolor into a vector.
  #define HUD_Panel_GetColor()\
@@@ -201,6 -216,14 +201,6 @@@ if(panel_bg_color_team_str == "") {
        panel_bg_color_team = stof(panel_bg_color_team_str);\
  }
  
 -// the check doesn't allow to fade this panel when showing the panel-specific menu dialog
 -#define HUD_Panel_ApplyFadeAlpha()\
 -if(!(menu_enabled == 2 && panel == highlightedPanel))\
 -{\
 -      panel_bg_alpha *= hud_fade_alpha;\
 -      panel_fg_alpha *= hud_fade_alpha;\
 -} ENDS_WITH_CURLY_BRACE
 -
  // Get value for panel_bg_alpha: if "" fetch default, else use panel_bg_alpha. Also do various menu dialog fadeout/in checks, and minalpha checks
  // comment on line 3 of macro: // do not set a minalpha cap when showing the config dialog for this panel
  #define HUD_Panel_GetBgAlpha()\
@@@ -232,6 -255,13 +232,6 @@@ if(panel_bg_border_str == "") {
        panel_bg_border = stof(panel_bg_border_str);\
  } ENDS_WITH_CURLY_BRACE
  
 -// Scale the pos and size vectors to absolute coordinates
 -#define HUD_Panel_GetScaledVectors()\
 -panel_pos_x *= vid_conwidth;\
 -panel_pos_y *= vid_conheight;\
 -panel_size_x *= vid_conwidth;\
 -panel_size_y *= vid_conheight;
 -
  // Get padding. See comments above, it's similar.
  // last line is a port of the old function, basically always make sure the panel contents are at least 5 pixels tall/wide, to disallow extreme padding values
  #define HUD_Panel_GetPadding()\
@@@ -242,12 -272,36 +242,12 @@@ if(panel_bg_padding_str == "") {
  }\
  panel_bg_padding = min(min(panel_size_x, panel_size_y)/2 - 5, panel_bg_padding);
  
 -// Point to the macros above (stupid max macro length)
 -#define HUD_Panel_GetStringVars()\
 -HUD_Panel_GetBg()\
 -if (panel_bg != "0") {\
 -      HUD_Panel_GetColorTeam()\
 -      HUD_Panel_GetColor()\
 -      HUD_Panel_GetBgAlpha()\
 -      HUD_Panel_GetBorder()\
 -}\
 -HUD_Panel_GetFgAlpha()\
 -HUD_Panel_GetScaledVectors()\
 -HUD_Panel_GetPadding()
 -
 -// return smoothly faded pos of given panel when a dialog is active
 -var vector menu_enable_panelpos;
 -#define HUD_Panel_GetMenuPos() \
 -if(panel_size_x > panel_size_y)\
 -      menu_enable_panelpos = eX * 0.5 * vid_conwidth - eX * 0.5 * panel_size_x + eY * 0.82 * vid_conheight;\
 -else\
 -      menu_enable_panelpos = eY * 0.5 * vid_conheight - eY * 0.5 * panel_size_y + eX * 0.7 * vid_conwidth;\
 -panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * menu_enable_panelpos;
 -
 -// return smoothly faded size of given panel when a dialog is active
 -//var vector menu_enable_maxsize;
 -var float menu_enable_maxsize_x;
 -var float menu_enable_maxsize_y;
 -var vector menu_enable_size;
 -#define HUD_Panel_GetMenuSize()\
 -menu_enable_maxsize_x = 0.3 * vid_conwidth;\
 -menu_enable_maxsize_y = 0.18 * vid_conheight;\
 +// return smoothly faded pos and size of given panel when a dialog is active
 +#define HUD_Panel_UpdatePosSize_ForMenu()\
 +vector menu_enable_pos;\
 +vector menu_enable_size = '0 0 0';\
 +float menu_enable_maxsize_x = 0.3 * vid_conwidth;\
 +float menu_enable_maxsize_y = 0.18 * vid_conheight;\
  if(panel_size_x > panel_size_y)\
  {\
        if(panel_size_y > menu_enable_maxsize_y)\
                menu_enable_size_x = panel_size_x * (menu_enable_maxsize_y/panel_size_y);\
                panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size;\
        }\
 +      menu_enable_pos = eX * 0.5 * vid_conwidth - eX * 0.5 * panel_size_x + eY * (vid_conheight - menu_enable_maxsize_y);\
  }\
  else\
  {\
                menu_enable_size_y = panel_size_y * (menu_enable_maxsize_x/panel_size_x);\
                panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size;\
        }\
 -}
 +      menu_enable_pos = eY * 0.5 * vid_conheight - eY * 0.5 * panel_size_y + eX * (vid_conwidth - menu_enable_maxsize_x);\
 +}\
 +panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * menu_enable_pos;
 +
 +// Scale the pos and size vectors to absolute coordinates
 +#define HUD_Panel_ScalePosSize()\
 +panel_pos_x *= vid_conwidth; panel_pos_y *= vid_conheight;\
 +panel_size_x *= vid_conwidth; panel_size_y *= vid_conheight;
  
  // NOTE: in hud_configure mode cvars must be reloaded every frame
  #define HUD_Panel_UpdateCvars() \
@@@ -281,56 -327,59 +281,55 @@@ if(panel.update_time <= time) { 
        if(autocvar__hud_configure) panel_enabled = cvar(strcat("hud_panel_", panel.panel_name)); \
        panel_pos = stov(cvar_string(strcat("hud_panel_", panel.panel_name, "_pos"))); \
        panel_size = stov(cvar_string(strcat("hud_panel_", panel.panel_name, "_size"))); \
 +      HUD_Panel_ScalePosSize() \
        panel_bg_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg")); \
        panel_bg_color_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_color")); \
        panel_bg_color_team_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_color_team")); \
        panel_bg_alpha_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_alpha")); \
        panel_bg_border_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_border")); \
        panel_bg_padding_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_padding")); \
 -      HUD_Panel_GetStringVars()\
 +      HUD_Panel_GetBg()\
 +      if (panel.current_panel_bg != "0") {\
 +              HUD_Panel_GetColorTeam()\
 +              HUD_Panel_GetColor()\
 +              HUD_Panel_GetBgAlpha()\
 +              HUD_Panel_GetBorder()\
 +      }\
 +      HUD_Panel_GetFgAlpha()\
 +      HUD_Panel_GetPadding()\
 +      panel.current_panel_bg_alpha = panel_bg_alpha; \
 +      panel.current_panel_fg_alpha = panel_fg_alpha; \
        if(menu_enabled == 2 && panel == highlightedPanel) {\
 -              HUD_Panel_GetMenuSize()\
 -              HUD_Panel_GetMenuPos()\
 -      } \
 +              HUD_Panel_UpdatePosSize_ForMenu()\
 +      } else {\
 +              panel_bg_alpha *= hud_fade_alpha;\
 +              panel_fg_alpha *= hud_fade_alpha;\
 +      }\
        panel.current_panel_pos = panel_pos; \
        panel.current_panel_size = panel_size; \
 -      if(panel.current_panel_bg) \
 -              strunzone(panel.current_panel_bg); \
 -      if(panel_bg == "")\
 -      {\
 -              /*printf("^xf08 %s panel: panel_bg is empty\n", panel.panel_name);*/\
 -              panel_bg = "0";\
 -      }\
 -      panel.current_panel_bg = strzone(panel_bg); \
--      panel.current_panel_bg_alpha = panel_bg_alpha; \
        panel.current_panel_bg_border = panel_bg_border; \
        panel.current_panel_bg_color = panel_bg_color; \
        panel.current_panel_bg_color_team = panel_bg_color_team; \
        panel.current_panel_bg_padding = panel_bg_padding; \
 -      panel.current_panel_fg_alpha = panel_fg_alpha; \
        panel.update_time = (autocvar__hud_configure) ? time : time + autocvar_hud_panel_update_interval; \
  } else { \
        panel_pos = panel.current_panel_pos; \
        panel_size = panel.current_panel_size; \
 -      panel_bg = panel.current_panel_bg; \
 -      if(panel.current_panel_bg == "")\
 -      {\
 -              /*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; \
 +      panel_bg_alpha = panel.current_panel_bg_alpha * hud_fade_alpha; \
        panel_bg_border = panel.current_panel_bg_border; \
        panel_bg_color = panel.current_panel_bg_color; \
        panel_bg_color_team = panel.current_panel_bg_color_team; \
        panel_bg_padding = panel.current_panel_bg_padding; \
 -      panel_fg_alpha = panel.current_panel_fg_alpha; \
 +      panel_fg_alpha = panel.current_panel_fg_alpha * hud_fade_alpha; \
  } ENDS_WITH_CURLY_BRACE
  
  #define HUD_Panel_UpdatePosSize() {\
  panel_enabled = cvar(strcat("hud_panel_", panel.panel_name)); \
  panel_pos = stov(cvar_string(strcat("hud_panel_", panel.panel_name, "_pos"))); \
  panel_size = stov(cvar_string(strcat("hud_panel_", panel.panel_name, "_size"))); \
 -HUD_Panel_GetScaledVectors()\
 +HUD_Panel_ScalePosSize()\
  if(menu_enabled == 2 && panel == highlightedPanel) {\
 -      HUD_Panel_GetMenuSize()\
 -      HUD_Panel_GetMenuPos()\
 +      HUD_Panel_UpdatePosSize_ForMenu()\
  }\
  panel_bg_border_str = cvar_string(strcat("hud_panel_", panel.panel_name, "_bg_border")); \
  HUD_Panel_GetBorder() \
@@@ -345,6 -394,3 +344,6 @@@ string notify_icon[KN_MAX_ENTRIES]
  string notify_attackers[KN_MAX_ENTRIES];
  string notify_victims[KN_MAX_ENTRIES];
  void HUD_Notify_Push(string icon, string attacker, string victim);
 +
 +var void HUD_ModIcons_GameType(vector pos, vector size);
 +void HUD_ModIcons_SetFunc();
index 82866b07f7855c128c4f99f3f5f5ef398bbff9e6,d361454843feea745f877ba898872a4dd2ea467a..810da2d27692bdc8a9d5c85f6eeff3fdd93ea72b
@@@ -131,7 -131,7 +131,7 @@@ void HUD_Panel_ExportCfg(string cfgname
                                        HUD_Write_PanelCvar_q("_maximized_scale");
                                        HUD_Write_PanelCvar_q("_maximized_size");
                                        HUD_Write_PanelCvar_q("_maximized_rotation");
-                                       HUD_Write_PanelCvar_q("_maximized_zoommode"); 
+                                       HUD_Write_PanelCvar_q("_maximized_zoommode");
                                        break;
                                case HUD_PANEL_SCORE:
                                        HUD_Write_PanelCvar_q("_rankings");
                }
                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()
@@@ -721,6 -721,7 +721,6 @@@ float HUD_Panel_InputEvent(float bInput
                if (bInputType == 1)
                        return true;
                menu_enabled = 1;
 -              menu_enabled_time = time;
                localcmd("menu_showhudexit\n");
        }
        else if(nPrimary == K_BACKSPACE && hudShiftState & S_CTRL)
@@@ -977,7 -978,7 +977,7 @@@ void HUD_Panel_FirstInDrawQ(float id
        }
        // now save the new top id
        panel_order[0] = id;
-       
        // let's save them into the cvar by some strcat trickery
        string s = "";
        for(i = 0; i < HUD_PANEL_NUM; ++i)
@@@ -1067,18 -1068,29 +1067,18 @@@ void HUD_Panel_Highlight(float allow_mo
  void HUD_Panel_EnableMenu()
  {
        menu_enabled = 2;
 -      menu_enabled_time = time;
        localcmd("menu_showhudoptions ", highlightedPanel.panel_name, "\n");
  }
  float mouse_over_panel;
  void HUD_Panel_Mouse()
  {
 -      // TODO: needs better check... is there any float that contains the current state of the menu? _menu_alpha isn't apparently updated the frame the menu gets enabled
 -      if (autocvar__menu_alpha == 0 && time - menu_enabled_time > 0.5)
 -              menu_enabled = 0;
 -
 -      /*
 -      print("menu_enabled: ", ftos(menu_enabled), "\n");
 -      print("Highlighted: ", ftos(highlightedPanel), "\n");
 -      print("Menu theAlpha: ", ftos(autocvar__menu_alpha), "\n");
 -      */
 -
        if(autocvar__menu_alpha == 1)
                return;
  
-       if not(autocvar_hud_cursormode)
+       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);
        }
  
        prevMouseClicked = mouseClicked;
  }
 +void HUD_Configure_DrawGrid()
 +{
 +      float i;
 +      if(autocvar_hud_configure_grid && autocvar_hud_configure_grid_alpha)
 +      {
 +              hud_configure_gridSize_x = bound(0.005, cvar("hud_configure_grid_xsize"), 0.2);
 +              hud_configure_gridSize_y = bound(0.005, cvar("hud_configure_grid_ysize"), 0.2);
 +              hud_configure_realGridSize_x = hud_configure_gridSize_x * vid_conwidth;
 +              hud_configure_realGridSize_y = hud_configure_gridSize_y * vid_conheight;
 +              vector s;
 +              // x-axis
 +              s = eX + eY * vid_conheight;
 +              for(i = 1; i < 1/hud_configure_gridSize_x; ++i)
 +                      drawfill(eX * i * hud_configure_realGridSize_x, s, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL);
 +              // y-axis
 +              s = eY + eX * vid_conwidth;
 +              for(i = 1; i < 1/hud_configure_gridSize_y; ++i)
 +                      drawfill(eY * i * hud_configure_realGridSize_y, s, '0.5 0.5 0.5', autocvar_hud_configure_grid_alpha, DRAWFLAG_NORMAL);
 +      }
 +}
 +
 +float _menu_alpha_prev;
 +void HUD_Configure_Frame()
 +{
 +      float i;
 +      if(autocvar__hud_configure)
 +      {
 +              if(isdemo() || intermission == 2)
 +              {
 +                      HUD_Configure_Exit_Force();
 +                      return;
 +              }
 +
 +              if(!hud_configure_prev || hud_configure_prev == -1)
 +              {
 +                      if(autocvar_hud_cursormode)
 +                              setcursormode(1);
 +                      hudShiftState = 0;
 +                      for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
 +                              hud_panel[panel_order[i]].update_time = time;
 +              }
 +
 +              // NOTE this check is necessary because _menu_alpha isn't updated the frame the menu gets enabled
 +              if(autocvar__menu_alpha != _menu_alpha_prev)
 +              {
 +                      if(autocvar__menu_alpha == 0)
 +                              menu_enabled = 0;
 +                      _menu_alpha_prev = autocvar__menu_alpha;
 +              }
 +
 +              HUD_Configure_DrawGrid();
 +      }
 +      else if(hud_configure_prev)
 +      {
 +              if(menu_enabled)
 +                      menu_enabled = 0;
 +              if(autocvar_hud_cursormode)
 +                      setcursormode(0);
 +      }
 +}
  
  const float hlBorderSize = 4;
  const string hlBorder = "gfx/hud/default/border_highlighted";
@@@ -1257,22 -1209,3 +1257,22 @@@ void HUD_Panel_HlBorder(float myBorder
        drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * hlBorderSize, hlBorder2, '1 8 0' * hlBorderSize, eY * (panel_size_y + 2 * myBorder - 2 * hlBorderSize) + eX * hlBorderSize, color, theAlpha, DRAWFLAG_NORMAL);
        drawpic_tiled(panel_pos - '1 1 0' * myBorder + eY * hlBorderSize + eX * (panel_size_x + 2 * myBorder - hlBorderSize), hlBorder2, '1 8 0' * hlBorderSize, eY * (panel_size_y + 2 * myBorder - 2 * hlBorderSize) + eX * hlBorderSize, color, theAlpha, DRAWFLAG_NORMAL);
  }
 +
 +void HUD_Configure_PostDraw()
 +{
 +      if(autocvar__hud_configure)
 +      {
 +              if(tab_panel)
 +              {
 +                      panel = tab_panel;
 +                      HUD_Panel_UpdatePosSize()
 +                      drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .2, DRAWFLAG_NORMAL);
 +              }
 +              if(highlightedPanel)
 +              {
 +                      panel = highlightedPanel;
 +                      HUD_Panel_UpdatePosSize()
 +                      HUD_Panel_HlBorder(panel_bg_border + 1.5 * hlBorderSize, '0 0.5 1', 0.25 * (1 - autocvar__menu_alpha));
 +              }
 +      }
 +}
index 89da2da2ebdb800d11854264ad15edfa83b44e1e,61e527cf1fbc69ade54b71368eb0e0c6fa563ab7..fbdbc45f3a3c25a0c5f4f650c7cba9cfe2349b53
@@@ -1,6 -1,5 +1,6 @@@
  entity players;
  entity teams;
 +var float team_count; // real teams
  
  void AuditLists()
  {
@@@ -82,8 -81,6 +82,8 @@@ float RegisterTeam(entity Team
        if(teams.sort_next)
                teams.sort_next.sort_prev = Team;
        teams.sort_next = Team;
 +      if(Team.team && Team.team != NUM_SPECTATOR)
 +              ++team_count;
        AuditLists();
        return true;
  }
@@@ -104,8 -101,6 +104,8 @@@ void RemoveTeam(entity Team
        parent.sort_next = Team.sort_next;
        if(Team.sort_next)
                Team.sort_next.sort_prev = parent;
 +      if(Team.team && Team.team != NUM_SPECTATOR)
 +              --team_count;
        AuditLists();
  }
  
@@@ -116,7 -111,7 +116,7 @@@ entity GetTeam(float Team, float add
        num = (Team == NUM_SPECTATOR) ? 16 : Team;
        if(teamslots[num])
                return teamslots[num];
-       if not(add)
+       if (!add)
                return world;
        tm = spawn();
        tm.team = Team;
@@@ -307,18 -302,18 +307,18 @@@ var string _drawpic_picpath
                _drawpic_picpath = string_null;\
        } while(0)
  
- void drawpic_aspect_skin_expanding(vector position, string pic, vector scale, vector rgb, float theAlpha, float flag, float fadelerp)
+ void drawpic_aspect_skin_expanding(vector position, string pic, vector theScale, vector rgb, float theAlpha, float flag, float fadelerp)
  {
        float sz;
        sz = expandingbox_sizefactor_from_fadelerp(fadelerp);
  
-       drawpic_aspect_skin(position + expandingbox_resize_centered_box_offset(sz, scale, 1), pic, scale * sz, rgb, theAlpha * (1 - fadelerp), flag);
+       drawpic_aspect_skin(position + expandingbox_resize_centered_box_offset(sz, theScale, 1), pic, theScale * sz, rgb, theAlpha * (1 - fadelerp), flag);
  }
  
- void drawpic_aspect_skin_expanding_two(vector position, string pic, vector scale, vector rgb, float theAlpha, float flag, float fadelerp)
+ void drawpic_aspect_skin_expanding_two(vector position, string pic, vector theScale, vector rgb, float theAlpha, float flag, float fadelerp)
  {
-       drawpic_aspect_skin_expanding(position, pic, scale, rgb, theAlpha, flag, fadelerp);
-       drawpic_skin(position, pic, scale, rgb, theAlpha * fadelerp, flag);
+       drawpic_aspect_skin_expanding(position, pic, theScale, rgb, theAlpha, flag, fadelerp);
+       drawpic_skin(position, pic, theScale, rgb, theAlpha * fadelerp, flag);
  }
  #define SET_POS_AND_SZ_Y_ASPECT(allow_colors)\
        float textaspect, oldsz;\
@@@ -346,14 -341,14 +346,14 @@@ void drawcolorcodedstring_aspect(vecto
  }
  
  vector drawfontscale;
- void drawstring_expanding(vector position, string text, vector scale, vector rgb, float theAlpha, float flag, float fadelerp)
+ void drawstring_expanding(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag, float fadelerp)
  {
        float sz;
        sz = expandingbox_sizefactor_from_fadelerp(fadelerp);
  
        drawfontscale = sz * '1 1 0';
        dummyfunction(0, 0, 0, 0, 0, 0, 0, 0);
-       drawstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, FALSE, scale * (sz / drawfontscale_x)) / (scale_x * sz)), text, scale * (sz / drawfontscale_x), rgb, theAlpha * (1 - fadelerp), flag);
+       drawstring(position + expandingbox_resize_centered_box_offset(sz, theScale, stringwidth(text, FALSE, theScale * (sz / drawfontscale_x)) / (theScale_x * sz)), text, theScale * (sz / drawfontscale_x), rgb, theAlpha * (1 - fadelerp), flag);
        // width parameter:
        //    (scale_x * sz / drawfontscale_x) * drawfontscale_x * SIZE1 / (scale_x * sz)
        //    SIZE1
@@@ -366,14 -361,14 +366,14 @@@ void drawstring_aspect_expanding(vecto
        drawstring_expanding(pos, text, '1 1 0' * sz_y, color, theAlpha, drawflag, fadelerp);
  }
  
- void drawcolorcodedstring_expanding(vector position, string text, vector scale, float theAlpha, float flag, float fadelerp)
+ void drawcolorcodedstring_expanding(vector position, string text, vector theScale, float theAlpha, float flag, float fadelerp)
  {
        float sz;
        sz = expandingbox_sizefactor_from_fadelerp(fadelerp);
  
        drawfontscale = sz * '1 1 0';
        dummyfunction(0, 0, 0, 0, 0, 0, 0, 0);
-       drawcolorcodedstring(position + expandingbox_resize_centered_box_offset(sz, scale, stringwidth(text, TRUE, scale * (sz / drawfontscale_x)) / (scale_x * sz)), text, scale * (sz / drawfontscale_x), theAlpha * (1 - fadelerp), flag);
+       drawcolorcodedstring(position + expandingbox_resize_centered_box_offset(sz, theScale, stringwidth(text, TRUE, theScale * (sz / drawfontscale_x)) / (theScale_x * sz)), text, theScale * (sz / drawfontscale_x), theAlpha * (1 - fadelerp), flag);
        drawfontscale = '1 1 0';
  }
  
@@@ -390,7 -385,7 +390,7 @@@ float PolyDrawModelSurface(entity e, fl
        vector tri;
        string tex;
        tex = getsurfacetexture(e, i_s);
-       if not(tex)
+       if (!tex)
                return 0; // this is beyond the last one
        n_t = getsurfacenumtriangles(e, i_s);
        for(i_t = 0; i_t < n_t; ++i_t)
@@@ -578,14 -573,25 +578,25 @@@ vector getplayerorigin(float pl
        return GETPLAYERORIGIN_ERROR;
  }
  
+ float getplayeralpha(float pl)
+ {
+       entity e;
+       e = CSQCModel_server2csqc(pl + 1);
+       if(e)
+               return e.alpha;
+       return 1;
+ }
  float getplayerisdead(float pl)
  {
        entity e;
-       
        e = CSQCModel_server2csqc(pl + 1);
        if(e)
                return e.csqcmodel_isdead;
-       
        return FALSE;
  }
  
@@@ -606,7 -612,7 +617,7 @@@ void URI_Get_Callback(float id, float s
        }
        else
        {
-               print(sprintf(_("Received HTTP request data for an invalid id %d.\n"), id));
+               printf("Received HTTP request data for an invalid id %d.\n", id);
        }
  }
  
index 6bfc3bba10624fce0d8e7fab23ac621f814e1a5b,8a7d3fd49fd8976d83dc2651cfc0ad5bce69e749..4389b8a747608b25910c7f5bc58af7d91cab1c7f
@@@ -9,7 -9,7 +9,7 @@@ float scoreboard_alpha_name_self
  void drawstringright(vector, string, vector, vector, float, float);
  void drawstringcenter(vector, string, vector, vector, float, float);
  
- float SCOREBOARD_OFFSET = 50;
const float SCOREBOARD_OFFSET = 50;
  
  // wrapper to put all possible scores titles through gettext
  string TranslateScoresLabel(string l)
@@@ -36,6 -36,7 +36,7 @@@
                case "lives": return CTX(_("SCO^lives"));
                case "losses": return CTX(_("SCO^losses"));
                case "name": return CTX(_("SCO^name"));
+               case "sum": return CTX(_("SCO^sum"));
                case "nick": return CTX(_("SCO^nick"));
                case "objectives": return CTX(_("SCO^objectives"));
                case "pickups": return CTX(_("SCO^pickups"));
        }
  }
  
 -void MapVote_Draw();
 -void HUD_FinaleOverlay()
 -{
 -      /*vector pos;
 -      pos_x = (vid_conwidth - 1)/2;
 -      pos_y = 16;
 -      pos_z = 0;*/
 -
 -      //drawpic(pos, "gfx/finale", '0 0 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
 -
 -      //drawstring(pos, "END", hud_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
 -      MapVote_Draw();
 -}
 -
  void Cmd_HUD_SetFields(float argc);
  void HUD_InitScores()
  {
@@@ -249,6 -264,7 +250,7 @@@ void Cmd_HUD_Help(
        print(_("^3suicides^7                 Number of suicides\n"));
        print(_("^3frags^7                    kills - suicides\n"));
        print(_("^3kd^7                       The kill-death ratio\n"));
+       print(_("^3sum^7                      frags - deaths\n"));
        print(_("^3caps^7                     How often a flag (CTF) or a key (KeyHunt) was captured\n"));
        print(_("^3pickups^7                  How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
        print(_("^3captime^7                  Time of fastest cap (CTF)\n"));
@@@ -290,6 -306,7 +292,7 @@@ string HUD_DefaultColumnLayout(
        return strcat( // fteqcc sucks
                "ping pl name | ",
                "-teams,race,lms/kills +freezetag/kills -teams,lms/deaths +freezetag/deaths -teams,lms,race,ka/suicides +freezetag/suicides -race,dm,tdm,ka,freezetag/frags ", // tdm already has this in "score"
+               "+tdm/kills +tdm/deaths +tdm/suicides ",
                "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
                "+lms/lives +lms/rank ",
                "+kh/caps +kh/pushes +kh/destroyed ",
@@@ -358,7 -375,7 +361,7 @@@ void Cmd_HUD_SetFields(float argc
                        pattern = substring(str, 0, slash);
                        str = substring(str, slash + 1, strlen(str) - (slash + 1));
  
-                       if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
+                       if (!isGametypeInFilter(gametype, teamplay, FALSE, pattern))
                                continue;
                }
  
                        hud_field[hud_num_fields] = SP_PL;
                } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
                        hud_field[hud_num_fields] = SP_KDRATIO;
+               } else if(str == "sum" || str == "diff" || str == "f-d") {
+                       hud_field[hud_num_fields] = SP_SUM;
                } else if(str == "name" || str == "nick") {
                        hud_field[hud_num_fields] = SP_NAME;
                        have_name = 1;
                        }
                        else
                        {
-                               if not(nocomplain)
-                                       print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
+                               if (!nocomplain)
+                                       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]);
                }
        }
  
@@@ -507,7 -526,7 +512,7 @@@ string HUD_GetField(entity pl, float fi
        switch(field)
        {
                case SP_PING:
-                       if not(pl.gotscores)
+                       if (!pl.gotscores)
                                return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
                        //str = getplayerkeyvalue(pl.sv_entnum, "ping");
                        f = pl.ping;
                        return ftos(f);
  
                case SP_PL:
-                       if not(pl.gotscores)
+                       if (!pl.gotscores)
                                return _("N/A");
                        f = pl.ping_packetloss;
                        tmp = pl.ping_movementloss;
                                str = sprintf("%.1f", num/denom);
                        return str;
  
+               case SP_SUM:
+                       f = pl.(scores[SP_KILLS]);
+                       f -= pl.(scores[SP_DEATHS]);
+                       if(f > 0) {
+                               hud_field_rgb = '0 1 0';
+                       } else if(f == 0) {
+                               hud_field_rgb = '1 1 1';
+                       } else {
+                               hud_field_rgb = '1 0 0';
+                       }
+                       return ftos(f);
                default:
                        tmp = pl.(scores[field]);
                        f = scores_flags[field];
@@@ -992,7 -1024,7 +1010,7 @@@ vector HUD_DrawScoreboardAccuracyStats(
        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
        {
                self = get_weaponinfo(i);
-               if not(self.weapon)
+               if (!self.weapon)
                        continue;
                if ((i == WEP_NEX && g_minstagib) || i == WEP_PORTO || (i == WEP_MINSTANEX && !g_minstagib) || i == WEP_TUBA) // skip port-o-launch, nex || minstanex and tuba
                        continue;
@@@ -1049,7 -1081,7 +1067,7 @@@ vector HUD_DrawKeyValue(vector pos, str
        drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
        pos_x = px;
        pos_y+= hud_fontsize_y;
-       
        return pos;
  }
  
@@@ -1066,14 -1098,14 +1084,14 @@@ vector HUD_DrawMapStats(vector pos, vec
        rows = (stat_secrets_total ? 1 : 0);
  
        // if no rows, return
-       if not(rows)
+       if (!rows)
                return pos;
  
        //  draw table header
        drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
        pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
-       
-       // draw table   
+       // draw table
        vector tmp = '0 0 0';
        tmp_x = sbwidth;
        tmp_y = hud_fontsize_y * rows;
        // draw secrets
        val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
        pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
-       
        // update position
        pos_y += 1.25 * hud_fontsize_y;
        return pos;
@@@ -1175,7 -1207,7 +1193,7 @@@ void HUD_DrawScoreboard(
                        scoreboard_fade_alpha = 0;
        }
  
-       if not(scoreboard_fade_alpha)
+       if (!scoreboard_fade_alpha)
                return;
  
        HUD_UpdatePlayerTeams();
                        pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
        }
  
-               
        if(teamplay)
                pos = HUD_DrawMapStats(pos, Team_ColorRGB(myteam), bg_size);
        else
                                str = strcat(str, _(" or"));
                        if(teamplay)
                        {
-                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl), 
+                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
                                        (teamscores_label[ts_primary] == "score")   ? CTX(_("SCO^points")) :
                                        (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
                                        TranslateScoresLabel(teamscores_label[ts_primary])));
                        }
                        else
                        {
-                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl), 
+                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
                                        (scores_label[ps_primary] == "score")   ? CTX(_("SCO^points")) :
                                        (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
                                        TranslateScoresLabel(scores_label[ps_primary])));
                                str = strcat(str, _(" or"));
                        if(teamplay)
                        {
-                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll), 
+                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
                                        (teamscores_label[ts_primary] == "score")   ? CTX(_("SCO^points")) :
                                        (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
                                        TranslateScoresLabel(teamscores_label[ts_primary])));
                        }
                        else
                        {
-                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll), 
+                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
                                        (scores_label[ps_primary] == "score")   ? CTX(_("SCO^points")) :
                                        (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
                                        TranslateScoresLabel(scores_label[ps_primary])));
                        // a negative number means we are awaiting respawn, time value is still the same
                        respawn_time *= -1; // remove mark now that we checked it
                        respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
-                       
                        str = sprintf(_("^1Respawning in ^3%s^1..."),
                                (autocvar_scoreboard_respawntime_decimals ?
                                        count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
diff --combined qcsrc/common/items.qh
index 0bf8fd8efff5e08a1a534022c82401de61c37eab,35cc00232bfd329eab32beeb5907f6707852f7aa..264c9ca73bd56070b6a41d69e0a359ea0f1503db
@@@ -1,56 -1,58 +1,56 @@@
float BOT_PICKUP_RATING_LOW   = 2500;
float BOT_PICKUP_RATING_MID   = 5000;
float BOT_PICKUP_RATING_HIGH  = 10000;
float WEP_TYPE_OTHER        =  0x00; // not for damaging people
float WEP_TYPE_SPLASH       =  0x01; // splash damage
float WEP_TYPE_HITSCAN              =  0x02; // hitscan
- float WEP_TYPEMASK            =  0x0F;
- float WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
- float WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
- float WEP_FLAG_HIDDEN         =  0x40; // hides from menu
- float WEP_FLAG_RELOADABLE     =  0x80; // can has reload
- float WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
- float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
float IT_UNLIMITED_WEAPON_AMMO     = 1;
const float BOT_PICKUP_RATING_LOW     = 2500;
const float BOT_PICKUP_RATING_MID     = 5000;
const float BOT_PICKUP_RATING_HIGH    = 10000;
const float WEP_TYPE_OTHER          =  0x00; // not for damaging people
const float WEP_TYPE_SPLASH         =  0x01; // splash damage
const float WEP_TYPE_HITSCAN        =  0x02; // hitscan
const float WEP_TYPEMASK            =  0x0F;
const float WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
const float WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
const float WEP_FLAG_HIDDEN         =  0x40; // hides from menu
const float WEP_FLAG_RELOADABLE     =  0x80; // can has reload
const float WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
const float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
const float   IT_UNLIMITED_WEAPON_AMMO     = 1;
  // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
float IT_UNLIMITED_SUPERWEAPONS    = 2;
const float   IT_UNLIMITED_SUPERWEAPONS    = 2;
  // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
- float   IT_CTF_SHIELDED              = 4; // set for the flag shield
- float   IT_USING_JETPACK             = 8; // confirmation that button is pressed
- float   IT_JETPACK                   = 16; // actual item
- float   IT_FUEL_REGEN                = 32; // fuel regeneration trigger
- float   IT_SHELLS                    = 256;
- float   IT_NAILS                     = 512;
- float   IT_ROCKETS                   = 1024;
- float   IT_CELLS                     = 2048;
- float   IT_SUPERWEAPON               = 4096;
- float   IT_FUEL                      = 128;
- float   IT_STRENGTH                  = 8192;
- float   IT_INVINCIBLE                = 16384;
- float   IT_HEALTH                    = 32768;
const float   IT_CTF_SHIELDED              = 4; // set for the flag shield
const float   IT_USING_JETPACK             = 8; // confirmation that button is pressed
const float   IT_JETPACK                   = 16; // actual item
const float   IT_FUEL_REGEN                = 32; // fuel regeneration trigger
WANT_CONST float   IT_SHELLS                    = 256;
WANT_CONST float   IT_NAILS                     = 512;
WANT_CONST float   IT_ROCKETS                   = 1024;
WANT_CONST float   IT_CELLS                     = 2048;
const float   IT_SUPERWEAPON               = 4096;
const float   IT_FUEL                      = 128;
const float   IT_STRENGTH                  = 8192;
const float   IT_INVINCIBLE                = 16384;
const float   IT_HEALTH                    = 32768;
  // union:
        // for items:
-       float   IT_KEY1                                 = 131072;
-       float   IT_KEY2                                 = 262144;
+       WANT_CONST float        IT_KEY1                                 = 131072;
+       WANT_CONST float        IT_KEY2                                 = 262144;
        // for players:
-       float   IT_RED_FLAG_TAKEN               = 32768;
-       float   IT_RED_FLAG_LOST                = 65536;
-       float   IT_RED_FLAG_CARRYING            = 98304;
-       float   IT_BLUE_FLAG_TAKEN              = 131072;
-       float   IT_BLUE_FLAG_LOST               = 262144;
-       float   IT_BLUE_FLAG_CARRYING   = 393216;
+       const float     IT_RED_FLAG_TAKEN               = 32768;
+       const float     IT_RED_FLAG_LOST                = 65536;
+       const float     IT_RED_FLAG_CARRYING            = 98304;
+       const float     IT_BLUE_FLAG_TAKEN              = 131072;
+       const float     IT_BLUE_FLAG_LOST               = 262144;
+       const float     IT_BLUE_FLAG_CARRYING   = 393216;
  // end
- float   IT_5HP                       = 524288;
- float   IT_25HP                      = 1048576;
- float   IT_ARMOR_SHARD               = 2097152;
- float   IT_ARMOR                     = 4194304;
const float   IT_5HP                       = 524288;
const float   IT_25HP                      = 1048576;
const float   IT_ARMOR_SHARD               = 2097152;
const float   IT_ARMOR                     = 4194304;
  
- float   IT_AMMO                      = 3968; // IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_FUEL;
- float   IT_PICKUPMASK                = 51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
- float   IT_UNLIMITED_AMMO            = 3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
const float   IT_AMMO                      = 3968; // IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_FUEL;
const float   IT_PICKUPMASK                = 51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
const float   IT_UNLIMITED_AMMO            = 3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
  
 -const float AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
 -
  // variables:
  string weaponorder_byid;
  
@@@ -68,8 -70,29 +68,29 @@@ string W_NumberWeaponOrder(string order
  .float ammo_fuel;
  .float ammo_batteries; // dummy
  
+ // Weapon sets
+ typedef vector WepSet;
+ WepSet WepSet_FromWeapon(float a);
+ #ifdef SVQC
+ void WepSet_AddStat();
+ void WriteWepSet(float dest, WepSet w);
+ #endif
+ #ifdef CSQC
+ WepSet WepSet_GetFromStat();
+ WepSet ReadWepSet();
+ #endif
+ // Weapon name macros
+ #define WEP_FIRST 1
+ #define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much.
+ float WEP_COUNT;
+ float WEP_LAST;
+ WepSet WEPSET_ALL;
+ WepSet WEPSET_SUPERWEAPONS;
  // entity properties of weaponinfo:
  .float weapon; // WEP_...
+ .WepSet weapons; // WEPSET_...
  .string netname; // short name
  .string message; // human readable name
  .float items; // IT_...
  .float bot_pickupbasevalue; // bot weapon priority
  .string model2; // wpn- sprite name
  ..float ammo_field; // main ammo field
- // also, weaponinfo ents can act as a WEPSET
  
  // dynamic weapon adding
  float w_null(float dummy);
- void register_weapon(float id, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname);
+ void register_weapon(float id, WepSet bit, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname);
  void register_weapons_done();
  
- #define WEP_FIRST 1
- float WEP_COUNT;
- float WEP_LAST;
- #if 1
- # define WEP_MAXCOUNT 24
- // default storage
- .float _WS_weapons;
- # define WEPSET_BIT(a)                  power2of((a) - WEP_FIRST)
- # define WEPSET_DECLARE_A(a)            float _WS_##a
- # define WEPSET_CLEAR_E(e)              ((e)._WS_weapons = 0)
- # define WEPSET_CLEAR_A(a)              (_WS_##a = 0)
- # define WEPSET_EMPTY_E(e)              ((e)._WS_weapons == 0)
- # define WEPSET_EMPTY_A(a)              (_WS_##a == 0)
- # define WEPSET_COPY_AS(a)              (_WS_##a = getstati(STAT_WEAPONS))
- # define WEPSET_ADDSTAT()               addstat(STAT_WEAPONS, AS_INT, _WS_weapons)
- # define WEPSET_WRITE_E(dest,a)         WriteInt24_t(dest, (a)._WS_weapons)
- # define WEPSET_WRITE_A(dest,a)         WriteInt24_t(dest, _WS_##a)
- # define WEPSET_WRITE_W(dest,a)         WriteInt24_t(dest, WEPSET_BIT(a))
- # define WEPSET_READ_E(a)               (a)._WS_weapons = ReadInt24_t()
- # define WEPSET_READ_A(a)               (_WS_##a) = ReadInt24_t()
- # define WEPSET_OP1_EE(a,b,mergeop,x)   ((a)._WS_weapons x (b)._WS_weapons)
- # define WEPSET_OP2_EE(a,b,mergeop,x,y) ((a)._WS_weapons x (b)._WS_weapons y (a)._WS_weapons)
- # define WEPSET_OP1_EA(a,b,mergeop,x)   ((a)._WS_weapons x _WS_##b)
- # define WEPSET_OP2_EA(a,b,mergeop,x,y) ((a)._WS_weapons x _WS_##b y (a)._WS_weapons)
- # define WEPSET_OP1_EW(a,b,mergeop,x)   ((a)._WS_weapons x WEPSET_BIT(b))
- # define WEPSET_OP2_EW(a,b,mergeop,x,y) ((a)._WS_weapons x WEPSET_BIT(b) y (a)._WS_weapons)
- # define WEPSET_OP1_AE(a,b,mergeop,x)   (_WS_##a x (b)._WS_weapons)
- # define WEPSET_OP2_AE(a,b,mergeop,x,y) (_WS_##a x (b)._WS_weapons y _WS_##a)
- # define WEPSET_OP1_AA(a,b,mergeop,x)   (_WS_##a x _WS_##b)
- # define WEPSET_OP2_AA(a,b,mergeop,x,y) (_WS_##a x _WS_##b y _WS_##a)
- # define WEPSET_OP1_AW(a,b,mergeop,x)   (_WS_##a x WEPSET_BIT(b))
- # define WEPSET_OP2_AW(a,b,mergeop,x,y) (_WS_##a x WEPSET_BIT(b) y _WS_##a)
- #else
- # define WEP_MAXCOUNT 48
- # define WEP_FIRST2 25
- .float _WS1_weapons;
- .float _WS2_weapons;
- # define WEPSET_BIT1(a)                 (((a) < WEP_FIRST2) ? power2of((a) - WEP_FIRST) : 0)
- # define WEPSET_BIT2(a)                 (((a) >= WEP_FIRST2) ? power2of((a) - WEP_FIRST2) : 0)
- # define WEPSET_DECLARE_A(a)            float _WS1_##a, _WS2_##a
- # define WEPSET_CLEAR_E(e)              ((e)._WS1_weapons = (e)._WS2_weapons = 0)
- # define WEPSET_CLEAR_A(a)              ((_WS1_##a) = (_WS2_##a) = 0)
- # define WEPSET_EMPTY_E(e)              ((e)._WS1_weapons == 0 && (e)._WS2_weapons == 0)
- # define WEPSET_EMPTY_A(a)              ((_WS1_##a) == 0 && (_WS2_##a) == 0)
- # define WEPSET_COPY_AS(a)              ((_WS1_##a) = getstati(STAT_WEAPONS), (_WS2_##a) = getstati(STAT_WEAPONS2))
- # define WEPSET_ADDSTAT()               addstat(STAT_WEAPONS, AS_INT, _WS1_weapons); addstat(STAT_WEAPONS2, AS_INT, _WS2_weapons)
- # define WEPSET_WRITE_E(dest,a)         WriteInt24_t(dest, (a)._WS1_weapons); WriteInt24_t(dest, (a)._WS2_weapons)
- # define WEPSET_WRITE_A(dest,a)         WriteInt24_t(dest, _WS1_##a); WriteInt24_t(dest, _WS2_##a)
- # define WEPSET_WRITE_W(dest,a)         WriteInt24_t(dest, WEPSET_BIT1(a)); WriteInt24_t(dest, WEPSET_BIT2(a))
- # define WEPSET_READ_E(a)               (a)._WS1_weapons = ReadInt24_t(); (a)._WS2_weapons = ReadInt24_t()
- # define WEPSET_READ_A(a)               (_WS1_##a) = ReadInt24_t(); (_WS2_##a) = ReadInt24_t()
- # define WEPSET_OP1_EE(a,b,mergeop,x)   (((a)._WS1_weapons x (b)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons))
- # define WEPSET_OP2_EE(a,b,mergeop,x,y) (((a)._WS1_weapons x (b)._WS1_weapons y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons y (a)._WS2_weapons))
- # define WEPSET_OP1_EA(a,b,mergeop,x)   (((a)._WS1_weapons x _WS1_##b) mergeop ((a)._WS2_weapons x _WS2_##b))
- # define WEPSET_OP2_EA(a,b,mergeop,x,y) (((a)._WS1_weapons x _WS1_##b y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x _WS2_##b y (a)._WS2_weapons))
- # define WEPSET_OP1_EW(a,b,mergeop,x)   (((a)._WS1_weapons x WEPSET_BIT1(b)) mergeop ((a)._WS2_weapons x WEPSET_BIT2(b)))
- # define WEPSET_OP2_EW(a,b,mergeop,x,y) (((a)._WS1_weapons x WEPSET_BIT1(b) y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x WEPSET_BIT2(b) y (a)._WS2_weapons))
- # define WEPSET_OP1_AE(a,b,mergeop,x)   ((_WS1_##a x (b)._WS1_weapons) mergeop (_WS2_##a x (b)._WS2_weapons))
- # define WEPSET_OP2_AE(a,b,mergeop,x,y) ((_WS1_##a x (b)._WS1_weapons y _WS1_##a) mergeop (_WS2_##a x (b)._WS2_weapons y _WS2_##a))
- # define WEPSET_OP1_AA(a,b,mergeop,x)   ((_WS1_##a x _WS1_##b) mergeop (_WS2_##a x _WS2_##b))
- # define WEPSET_OP2_AA(a,b,mergeop,x,y) ((_WS1_##a x _WS1_##b y _WS1_##a) mergeop (_WS2_##a x _WS2_##b y _WS2_##a))
- # define WEPSET_OP1_AW(a,b,mergeop,x)   ((_WS1_##a x WEPSET_BIT1(b)) mergeop (_WS2_##a x WEPSET_BIT2(b)))
- # define WEPSET_OP2_AW(a,b,mergeop,x,y) ((_WS1_##a x WEPSET_BIT1(b) y _WS1_##a) mergeop (_WS2_##a x WEPSET_BIT2(b) y _WS2_##a))
- #endif
- #define XX ,
- #define WEPSET_COPY_EE(a,b)            WEPSET_OP1_EE(a,b,XX,=)
- #define WEPSET_EQ_EE(a,b)              WEPSET_OP1_EE(a,b,&&,==)
- #define WEPSET_OR_EE(a,b)              WEPSET_OP1_EE(a,b,XX,|=)
- #define WEPSET_AND_EE(a,b)             WEPSET_OP2_EE(a,b,XX,=,&)
- #define WEPSET_ANDNOT_EE(a,b)          WEPSET_OP1_EE(a,b,XX,&~=)
- #define WEPSET_CONTAINS_ANY_EE(a,b) !!(WEPSET_OP1_EE(a,b,||,&))
- #define WEPSET_CONTAINS_ALL_EE(a,b)    WEPSET_OP2_EE(b,a,&&,==,&)
- #define WEPSET_COPY_EA(a,b)            WEPSET_OP1_EA(a,b,XX,=)
- #define WEPSET_EQ_EA(a,b)              WEPSET_OP1_EA(a,b,&&,==)
- #define WEPSET_OR_EA(a,b)              WEPSET_OP1_EA(a,b,XX,|=)
- #define WEPSET_AND_EA(a,b)             WEPSET_OP2_EA(a,b,XX,=,&)
- #define WEPSET_ANDNOT_EA(a,b)          WEPSET_OP1_EA(a,b,XX,&~=)
- #define WEPSET_CONTAINS_ANY_EA(a,b) !!(WEPSET_OP1_EA(a,b,||,&))
- #define WEPSET_CONTAINS_ALL_EA(a,b)    WEPSET_OP2_EA(b,a,&&,==,&)
- #define WEPSET_COPY_EW(a,b)            WEPSET_OP1_EW(a,b,XX,=)
- #define WEPSET_EQ_EW(a,b)              WEPSET_OP1_EW(a,b,&&,==)
- #define WEPSET_OR_EW(a,b)              WEPSET_OP1_EW(a,b,XX,|=)
- #define WEPSET_AND_EW(a,b)             WEPSET_OP2_EW(a,b,XX,=,&)
- #define WEPSET_ANDNOT_EW(a,b)          WEPSET_OP1_EW(a,b,XX,&~=)
- #define WEPSET_CONTAINS_EW(a,b)     !!(WEPSET_OP1_EW(a,b,||,&))
- #define WEPSET_COPY_AE(a,b)            WEPSET_OP1_AE(a,b,XX,=)
- #define WEPSET_EQ_AE(a,b)              WEPSET_OP1_AE(a,b,&&,==)
- #define WEPSET_OR_AE(a,b)              WEPSET_OP1_AE(a,b,XX,|=)
- #define WEPSET_AND_AE(a,b)             WEPSET_OP2_AE(a,b,XX,=,&)
- #define WEPSET_ANDNOT_AE(a,b)          WEPSET_OP1_AE(a,b,XX,&~=)
- #define WEPSET_CONTAINS_ANY_AE(a,b) !!(WEPSET_OP1_AE(a,b,||,&))
- #define WEPSET_CONTAINS_ALL_AE(a,b)    WEPSET_OP2_AE(b,a,&&,==,&)
- #define WEPSET_COPY_AA(a,b)            WEPSET_OP1_AA(a,b,XX,=)
- #define WEPSET_EQ_AA(a,b)              WEPSET_OP1_AA(a,b,&&,==)
- #define WEPSET_OR_AA(a,b)              WEPSET_OP1_AA(a,b,XX,|=)
- #define WEPSET_AND_AA(a,b)             WEPSET_OP2_AA(a,b,XX,=,&)
- #define WEPSET_ANDNOT_AA(a,b)          WEPSET_OP1_AA(a,b,XX,&~=)
- #define WEPSET_CONTAINS_ANY_AA(a,b) !!(WEPSET_OP1_AA(a,b,||,&))
- #define WEPSET_CONTAINS_ALL_AA(a,b)    WEPSET_OP2_AA(b,a,&&,==,&)
- #define WEPSET_COPY_AW(a,b)            WEPSET_OP1_AW(a,b,XX,=)
- #define WEPSET_EQ_AW(a,b)              WEPSET_OP1_AW(a,b,&&,==)
- #define WEPSET_OR_AW(a,b)              WEPSET_OP1_AW(a,b,XX,|=)
- #define WEPSET_AND_AW(a,b)             WEPSET_OP2_AW(a,b,XX,=,&)
- #define WEPSET_ANDNOT_AW(a,b)          WEPSET_OP1_AW(a,b,XX,&~=)
- #define WEPSET_CONTAINS_AW(a,b)     !!(WEPSET_OP1_AW(a,b,||,&))
- WEPSET_DECLARE_A(WEPBIT_ALL);
- WEPSET_DECLARE_A(WEPBIT_SUPERWEAPONS);
- // note: the fabs call is just there to hide "if result is constant" warning
- #define REGISTER_WEAPON_2(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
+ #define REGISTER_WEAPON_2(id,bit,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
        float id; \
+       WepSet bit; \
        float func(float); \
        void RegisterWeapons_##id() \
        { \
                WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \
-               WEPSET_OR_AW(WEPBIT_ALL, id); \
-               if(fabs(weapontype & WEP_FLAG_SUPERWEAPON)) \
-                       WEPSET_OR_AW(WEPBIT_SUPERWEAPONS, id); \
+               bit = WepSet_FromWeapon(id); \
+               WEPSET_ALL |= bit; \
+               if((weapontype) & WEP_FLAG_SUPERWEAPON) \
+                       WEPSET_SUPERWEAPONS |= bit; \
                ++WEP_COUNT; \
-               register_weapon(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname); \
+               register_weapon(id,bit,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname); \
        } \
        ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id)
  #ifdef MENUQC
  #define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
-       REGISTER_WEAPON_2(WEP_##id,w_null,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
+       REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,w_null,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
  #else
  #define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
-       REGISTER_WEAPON_2(WEP_##id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
+       REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
  #endif
  
  #include "../server/w_all.qc"
  
  #undef REGISTER_WEAPON
- ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done)
+ ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done);
  
  
  string W_FixWeaponOrder(string order, float complete);