]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/view.qc
Port another 10 stats
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / view.qc
index 5a6b2fe15fb0f9081cb612478d4823bfce8c1880..3b4e94cb479a366846eddb3b18a0e6ac935ed324 100644 (file)
@@ -1,33 +1,37 @@
-#include "_all.qh"
 
 #include "announcer.qh"
 #include "hook.qh"
-#include "hud.qh"
-#include "hud_config.qh"
+#include "hud/all.qh"
 #include "mapvoting.qh"
 #include "scoreboard.qh"
 #include "shownames.qh"
+#include "quickmenu.qh"
 
 #include "mutators/events.qh"
 
 #include "../common/constants.qh"
+#include "../common/debug.qh"
 #include "../common/mapinfo.qh"
-#include "../common/nades.qh"
+#include "../common/gamemodes/all.qh"
+#include "../common/nades/all.qh"
 #include "../common/stats.qh"
 #include "../common/triggers/target/music.qh"
 #include "../common/teams.qh"
-#include "../common/util.qh"
 
+#include "../common/vehicles/all.qh"
 #include "../common/weapons/all.qh"
+#include "../common/viewloc.qh"
+#include "../common/minigames/cl_minigames.qh"
+#include "../common/minigames/cl_minigames_hud.qh"
 
-#include "../csqcmodellib/cl_player.qh"
+#include "../lib/csqcmodel/cl_player.qh"
 
-#include "../warpzonelib/client.qh"
-#include "../warpzonelib/common.qh"
+#include "../lib/warpzone/client.qh"
+#include "../lib/warpzone/common.qh"
 
 entity porto;
 vector polyline[16];
-void Porto_Draw()
+void Porto_Draw(entity this)
 {
        vector p, dir, ang, q, nextdir;
        float portal_number, portal1_idx;
@@ -106,8 +110,8 @@ void Porto_Draw()
 
 void Porto_Init()
 {
-       porto = spawn();
-       porto.classname = "porto";
+       porto = new(porto);
+       make_pure(porto);
        porto.draw = Porto_Draw;
        porto.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
 }
@@ -131,6 +135,7 @@ vector GetCurrentFov(float fov)
 
        zoomdir = button_zoom;
        if(hud == HUD_NORMAL)
+       if(switchweapon == activeweapon)
        if((activeweapon == WEP_VORTEX.m_id && vortex_scope) || (activeweapon == WEP_RIFLE.m_id && rifle_scope)) // do NOT use switchweapon here
                zoomdir += button_attack2;
        if(spectatee_status > 0 || isdemo())
@@ -273,11 +278,11 @@ const float SHOTTYPE_HITENEMY = 4;
 
 void TrueAim_Init()
 {
-       trueaim = spawn();
-       trueaim.classname = "trueaim";
+       trueaim = new(trueaim);
+       make_pure(trueaim);
        trueaim.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-       trueaim_rifle = spawn();
-       trueaim_rifle.classname = "trueaim_rifle";
+       trueaim_rifle = new(trueaim_rifle);
+       make_pure(trueaim_rifle);
        trueaim_rifle.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
 }
 
@@ -320,6 +325,7 @@ float TrueAimCheck()
        {
                case WEP_TUBA.m_id: // no aim
                case WEP_PORTO.m_id: // shoots from eye
+               case WEP_NEXBALL.m_id: // shoots from eye
                case WEP_HOOK.m_id: // no trueaim
                case WEP_MORTAR.m_id: // toss curve
                        return SHOTTYPE_HITWORLD;
@@ -356,7 +362,7 @@ float TrueAimCheck()
 
        vector traceorigin = getplayerorigin(player_localentnum-1) + (eZ * getstati(STAT_VIEWHEIGHT));
 
-       vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
+       vecs = decompressShotOrigin(STAT(SHOTORG));
 
        traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
        trueaimpoint = trace_endpos;
@@ -392,9 +398,7 @@ float TrueAimCheck()
        return SHOTTYPE_HITWORLD;
 }
 
-void CSQC_common_hud(void);
-
-void PostInit(void);
+void PostInit();
 void CSQC_Demo_Camera();
 float HUD_WouldDrawScoreboard();
 float camera_mode;
@@ -426,7 +430,7 @@ vector liquidcolor_prev;
 float eventchase_current_distance;
 float eventchase_running;
 bool WantEventchase()
-{
+{SELFPARAM();
        if(autocvar_cl_orthoview)
                return false;
        if(intermission)
@@ -437,7 +441,9 @@ bool WantEventchase()
        {
                if(hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0))
                        return true;
-               if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_PORTO.m_id)))
+               if(MUTATOR_CALLHOOK(WantEventchase, self))
+                       return true;
+               if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_NEXBALL.m_id)))
                        return true;
                if(autocvar_cl_eventchase_death && (getstati(STAT_HEALTH) <= 0))
                {
@@ -453,25 +459,32 @@ bool WantEventchase()
        return false;
 }
 
-vector damage_blurpostprocess, content_blurpostprocess;
+void HUD_Crosshair_Vehicle()
+{
+       if(hud != HUD_BUMBLEBEE_GUN)
+       {
+               Vehicle info = get_vehicleinfo(hud);
+               info.vr_crosshair(info);
+       }
+}
 
-float checkfail[16];
+vector damage_blurpostprocess, content_blurpostprocess;
 
 float unaccounted_damage = 0;
 void UpdateDamage()
 {
        // accumulate damage with each stat update
        static float damage_total_prev = 0;
-       float damage_total = getstati(STAT_DAMAGE_DEALT_TOTAL);
+       float damage_total = STAT(DAMAGE_DEALT_TOTAL);
        float unaccounted_damage_new = COMPARE_INCREASING(damage_total, damage_total_prev);
        damage_total_prev = damage_total;
 
        static float damage_dealt_time_prev = 0;
-       float damage_dealt_time = getstatf(STAT_HIT_TIME);
+       float damage_dealt_time = STAT(HIT_TIME);
        if (damage_dealt_time != damage_dealt_time_prev)
        {
                unaccounted_damage += unaccounted_damage_new;
-               dprint("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")", "\n");
+               LOG_TRACE("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")", "\n");
        }
        damage_dealt_time_prev = damage_dealt_time;
 
@@ -482,7 +495,7 @@ void UpdateDamage()
        spectatee_status_prev = spectatee_status;
 }
 
-void UpdateHitsound()
+void HitSound()
 {
        // varying sound pitch
 
@@ -511,61 +524,46 @@ void UpdateHitsound()
                                pitch_shift = mirror_value + (mirror_value - pitch_shift);
                        }
 
-                       dprint("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift), "\n");
+                       LOG_TRACE("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift), "\n");
 
                        // todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
                        // todo: normalize sound pressure levels? seems unnecessary
 
-                       sound7(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
+                       sound7(world, CH_INFO, SND(HIT), VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
                }
                unaccounted_damage = 0;
                hitsound_time_prev = time;
        }
 
        static float typehit_time_prev = 0;
-       float typehit_time = getstatf(STAT_TYPEHIT_TIME);
+       float typehit_time = STAT(TYPEHIT_TIME);
        if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
        {
-               sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTN_NONE);
+               sound(world, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
                typehit_time_prev = typehit_time;
        }
 }
 
-void UpdateCrosshair()
-{
+void HUD_Crosshair()
+{SELFPARAM();
        static float rainbow_last_flicker;
-    static vector rainbow_prev_color;
+       static vector rainbow_prev_color;
        entity e = self;
        float f, i, j;
        vector v;
-       if(getstati(STAT_FROZEN))
-               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
-       else if (getstatf(STAT_HEALING_ORB)>time)
-               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, NADE_TYPE_HEAL.m_color, autocvar_hud_colorflash_alpha*getstatf(STAT_HEALING_ORB_ALPHA), DRAWFLAG_ADDITIVE);
-       if(!intermission)
-       if(getstatf(STAT_NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
-       {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * getstatf(STAT_NADE_TIMER)) - ('0 1 1' * getstatf(STAT_NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
-               drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
-       }
-       else if(getstatf(STAT_REVIVE_PROGRESS))
-       {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
-               drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
-       }
-
-       if(autocvar_r_letterbox == 0)
-               if(autocvar_viewsize < 120)
-                       CSQC_common_hud();
-
-       // crosshair goes VERY LAST
-       if(!scoreboard_active && !camera_active && intermission != 2 && 
-               spectatee_status != -1 && hud == HUD_NORMAL && !csqcplayer.viewloc &&
+       if(!scoreboard_active && !camera_active && intermission != 2 &&
+               spectatee_status != -1 && !csqcplayer.viewloc &&
                !HUD_MinigameMenu_IsOpened() )
        {
                if (!autocvar_crosshair_enabled) // main toggle for crosshair rendering
                        return;
 
+               if (hud != HUD_NORMAL)
+               {
+                       HUD_Crosshair_Vehicle();
+                       return;
+               }
+
                string wcross_style;
                float wcross_alpha, wcross_resolution;
                wcross_style = autocvar_crosshair;
@@ -714,7 +712,7 @@ void UpdateCrosshair()
 
                if(autocvar_crosshair_pickup)
                {
-                       float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
+                       float stat_pickup_time = STAT(LAST_PICKUP);
 
                        if(pickup_crosshair_time < stat_pickup_time)
                        {
@@ -821,18 +819,18 @@ void UpdateCrosshair()
                                ring_scale = autocvar_crosshair_ring_size;
 
                                float weapon_clipload, weapon_clipsize;
-                               weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
-                               weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
+                               weapon_clipload = STAT(WEAPON_CLIPLOAD);
+                               weapon_clipsize = STAT(WEAPON_CLIPSIZE);
 
                                float ok_ammo_charge, ok_ammo_chargepool;
                                ok_ammo_charge = getstatf(STAT_OK_AMMO_CHARGE);
                                ok_ammo_chargepool = getstatf(STAT_OK_AMMO_CHARGEPOOL);
 
                                float vortex_charge, vortex_chargepool;
-                               vortex_charge = getstatf(STAT_VORTEX_CHARGE);
-                               vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL);
+                               vortex_charge = STAT(VORTEX_CHARGE);
+                               vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
 
-                               float arc_heat = getstatf(STAT_ARC_HEAT);
+                               float arc_heat = STAT(ARC_HEAT);
 
                                if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
                                        vortex_charge_movingavg = vortex_charge;
@@ -861,14 +859,14 @@ void UpdateCrosshair()
                                }
                                else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER.m_id && 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_value = bound(0, 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_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if (activeweapon == WEP_HAGAR.m_id && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+                               else if (activeweapon == WEP_HAGAR.m_id && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
                                {
-                                       ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
+                                       ring_value = bound(0, STAT(HAGAR_LOAD) / hagar_maxrockets, 1);
                                        ring_alpha = autocvar_crosshair_ring_hagar_alpha;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
@@ -1005,6 +1003,48 @@ void UpdateCrosshair()
        }
 }
 
+void HUD_Draw()
+{
+       if(getstati(STAT_FROZEN))
+               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+       else if (getstatf(STAT_HEALING_ORB)>time)
+               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, NADE_TYPE_HEAL.m_color, autocvar_hud_colorflash_alpha*getstatf(STAT_HEALING_ORB_ALPHA), DRAWFLAG_ADDITIVE);
+       if(!intermission)
+       if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
+       {
+               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * STAT(NADE_TIMER)) - ('0 1 1' * STAT(NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
+       }
+       else if(getstatf(STAT_REVIVE_PROGRESS))
+       {
+               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
+       }
+
+       if(autocvar_r_letterbox == 0)
+               if(autocvar_viewsize < 120)
+               {
+                       if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS))
+                               Accuracy_LoadLevels();
+
+                       HUD_Main();
+                       HUD_DrawScoreboard();
+               }
+
+       // crosshair goes VERY LAST
+       UpdateDamage();
+       HUD_Crosshair();
+       HitSound();
+}
+
+bool ov_enabled;
+float oldr_nearclip;
+float oldr_farclip_base;
+float oldr_farclip_world;
+float oldr_novis;
+float oldr_useportalculling;
+float oldr_useinfinitefarclip;
+
 const int BUTTON_3 = 4;
 const int BUTTON_4 = 8;
 float cl_notice_run();
@@ -1013,11 +1053,10 @@ int lasthud;
 float vh_notice_time;
 void WaypointSprite_Load();
 void CSQC_UpdateView(float w, float h)
-{
+{SELFPARAM();
        entity e;
        float fov;
        float f;
-       int i;
        vector vf_size, vf_min;
        float a;
 
@@ -1025,7 +1064,8 @@ void CSQC_UpdateView(float w, float h)
 
        ++framecount;
 
-       hud = getstati(STAT_HUD);
+       stats_get();
+       hud = STAT(HUD);
 
        if(hud != HUD_NORMAL && lasthud == HUD_NORMAL)
                vh_notice_time = time + autocvar_cl_vehicles_notify_time;
@@ -1047,22 +1087,6 @@ void CSQC_UpdateView(float w, float h)
        button_attack2 = (input_buttons & BUTTON_3);
        button_zoom = (input_buttons & BUTTON_4);
 
-#define CHECKFAIL_ASSERT(flag,func,parm,val) do {                                                                   \
-       float checkfailv = (func)(parm);                                                                                \
-       if (checkfailv != (val)) {                                                                                      \
-               if (!checkfail[(flag)])                                                                                     \
-               localcmd(sprintf("\ncmd checkfail %s %s %d %d\n", #func, parm, val, checkfailv));                           \
-               checkfail[(flag)] = 1;                                                                                      \
-       }                                                                                                               \
-} while(0)
-       CHECKFAIL_ASSERT(0, cvar_type, "\{100}\{105}\{118}\{48}\{95}\{101}\{118}\{97}\{100}\{101}", 0);
-       CHECKFAIL_ASSERT(1, cvar_type, "\{97}\{97}\{95}\{101}\{110}\{97}\{98}\{108}\{101}", 0);
-       CHECKFAIL_ASSERT(2, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{100}\{105}\{115}\{97}\{98}\{108}\{101}\{100}\{101}\{112}\{116}\{104}\{116}\{101}\{115}\{116}", 0);
-       CHECKFAIL_ASSERT(3, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0);
-       CHECKFAIL_ASSERT(4, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{108}\{105}\{103}\{104}\{116}", 0);
-       CHECKFAIL_ASSERT(5, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{115}\{104}\{97}\{100}\{111}\{119}\{118}\{111}\{108}\{117}\{109}\{101}\{115}", 0);
-       CHECKFAIL_ASSERT(6, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0);
-
        vf_size = getpropertyvec(VF_SIZE);
        vf_min = getpropertyvec(VF_MIN);
        vid_width = vf_size.x;
@@ -1084,8 +1108,7 @@ void CSQC_UpdateView(float w, float h)
        if(myteam != prev_myteam)
        {
                myteamcolors = colormapPaletteColor(myteam, 1);
-               for(i = 0; i < HUD_PANEL_NUM; ++i)
-                       hud_panel[i].update_time = time;
+               FOREACH(hud_panels, true, LAMBDA(it.update_time = time));
                prev_myteam = myteam;
        }
 
@@ -1247,6 +1270,16 @@ void CSQC_UpdateView(float w, float h)
                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; }
 
+               if(!ov_enabled)
+               {
+                       oldr_nearclip = cvar("r_nearclip");
+                       oldr_farclip_base = cvar("r_farclip_base");
+                       oldr_farclip_world = cvar("r_farclip_world");
+                       oldr_novis = cvar("r_novis");
+                       oldr_useportalculling = cvar("r_useportalculling");
+                       oldr_useinfinitefarclip = cvar("r_useinfinitefarclip");
+               }
+
                cvar_settemp("r_nearclip", ftos(ov_nearest));
                cvar_settemp("r_farclip_base", ftos(ov_furthest));
                cvar_settemp("r_farclip_world", "0");
@@ -1257,8 +1290,10 @@ void CSQC_UpdateView(float w, float h)
                setproperty(VF_ORIGIN, ov_org);
                setproperty(VF_ANGLES, '90 0 0');
 
+               ov_enabled = true;
+
                #if 0
-               printf("OrthoView: org = %s, angles = %s, distance = %f, nearest = %f, furthest = %f\n",
+               LOG_INFOF("OrthoView: org = %s, angles = %s, distance = %f, nearest = %f, furthest = %f\n",
                        vtos(ov_org),
                        vtos(getpropertyvec(VF_ANGLES)),
                        ov_distance,
@@ -1266,6 +1301,19 @@ void CSQC_UpdateView(float w, float h)
                        ov_furthest);
                #endif
        }
+       else
+       {
+               if(ov_enabled)
+               {
+                       cvar_set("r_nearclip", ftos(oldr_nearclip));
+                       cvar_set("r_farclip_base", ftos(oldr_farclip_base));
+                       cvar_set("r_farclip_world", ftos(oldr_farclip_world));
+                       cvar_set("r_novis", ftos(oldr_novis));
+                       cvar_set("r_useportalculling", ftos(oldr_useportalculling));
+                       cvar_set("r_useinfinitefarclip", ftos(oldr_useinfinitefarclip));
+               }
+               ov_enabled = false;
+       }
 
        // Render the Scene
        view_origin = getpropertyvec(VF_ORIGIN);
@@ -1340,11 +1388,8 @@ void CSQC_UpdateView(float w, float h)
 
        ColorTranslateMode = autocvar_cl_stripcolorcodes;
 
-       // next WANTED weapon (for HUD)
-       switchweapon = getstati(STAT_SWITCHWEAPON);
-
        // currently switching-to weapon (for crosshair)
-       switchingweapon = getstati(STAT_SWITCHINGWEAPON);
+       switchingweapon = STAT(SWITCHINGWEAPON);
 
        // actually active weapon (for zoom)
        activeweapon = getstati(STAT_ACTIVEWEAPON);
@@ -1448,11 +1493,9 @@ void CSQC_UpdateView(float w, float h)
           mousepos = mousepos*0.5 + getmousepos();
         */
 
-       e = self;
-       for(self = world; (self = nextent(self)); )
-               if(self.draw)
-                       self.draw();
-       self = e;
+       for(entity e = NULL; (e = nextent(e)); ) if (e.draw) {
+               WITH(entity, self, e, e.draw(e));
+       }
 
        addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
        renderscene();
@@ -1471,13 +1514,11 @@ void CSQC_UpdateView(float w, float h)
 
                if(!nightvision_noise)
                {
-                       nightvision_noise = spawn();
-                       nightvision_noise.classname = "nightvision_noise";
+                       nightvision_noise = new(nightvision_noise);
                }
                if(!nightvision_noise2)
                {
-                       nightvision_noise2 = spawn();
-                       nightvision_noise2.classname = "nightvision_noise2";
+                       nightvision_noise2 = new(nightvision_noise2);
                }
 
                // color tint in yellow
@@ -1515,6 +1556,7 @@ void CSQC_UpdateView(float w, float h)
 
        if(autocvar_cl_reticle)
        {
+               Weapon wep = get_weaponinfo(activeweapon);
                // 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
@@ -1524,7 +1566,7 @@ void CSQC_UpdateView(float w, float h)
                        // no zoom reticle while dead
                        reticle_type = 0;
                }
-               else if(WEP_ACTION(activeweapon, WR_ZOOMRETICLE) && autocvar_cl_reticle_weapon)
+               else if(wep.wr_zoomreticle(wep) && autocvar_cl_reticle_weapon)
                {
                        if(reticle_image != "") { reticle_type = 2; }
                        else { reticle_type = 0; }
@@ -1695,16 +1737,15 @@ void CSQC_UpdateView(float w, float h)
                        if(autocvar_cl_gentle_damage == 2)
                        {
                                if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
-                               {
                                        myhealth_gentlergb = eX * random() + eY * random() + eZ * random();
-                               }
                        }
                        else
                                myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
 
-                       drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
+                       if(myhealth_flash_temp > 0)
+                               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
                }
-               else
+               else if(myhealth_flash_temp > 0)
                        drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
 
                if(autocvar_hud_postprocessing) // we still need to set this anyway even when chase_active is set, this way it doesn't get stuck on.
@@ -1752,7 +1793,7 @@ void CSQC_UpdateView(float w, float h)
                }
 
                // 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);
+               float sharpen_intensity = 0, strength_finished = STAT(STRENGTH_FINISHED), invincible_finished = STAT(INVINCIBLE_FINISHED);
                if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
                if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
 
@@ -1778,27 +1819,21 @@ void CSQC_UpdateView(float w, float h)
        else if(cvar("r_glsl_postprocess") == 2)
                cvar_set("r_glsl_postprocess", "0");
 
-       if(menu_visible)
-               menu_show();
-
        /*if(gametype == MAPINFO_TYPE_CTF)
          {
          ctf_view();
          } else */
 
        // draw 2D entities
-       e = self;
-       for(self = world; (self = nextent(self)); )
-               if(self.draw2d)
-                       self.draw2d();
-       self = e;
+       for (entity e = NULL; (e = nextent(e)); ) if (e.draw2d) {
+               WITH(entity, self, e, e.draw2d(e));
+       }
        Draw_ShowNames_All();
+       Debug_Draw();
 
        scoreboard_active = HUD_WouldDrawScoreboard();
 
-       UpdateDamage();
-       UpdateCrosshair();
-       UpdateHitsound();
+       HUD_Draw();
 
        if(NextFrameCommand)
        {
@@ -1842,12 +1877,6 @@ void CSQC_UpdateView(float w, float h)
        else
                HUD_Radar_Mouse();
 
-    if(hud && !intermission)
-    if(hud == HUD_BUMBLEBEE_GUN)
-       CSQC_BUMBLE_GUN_HUD();
-    else
-               VEH_ACTION(hud, VR_HUD);
-
        cl_notice_run();
 
        // let's reset the view back to normal for the end
@@ -1856,20 +1885,6 @@ void CSQC_UpdateView(float w, float h)
 }
 
 
-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();
-
-       // scoreboard/accuracy, map/gametype voting screen
-       if (scoreboard_active || intermission == 2)
-               HUD_Reset();
-}
-
-
 // following vectors must be global to allow seamless switching between camera modes
 vector camera_offset, current_camera_offset, mouse_angles, current_angles, current_origin, current_position;
 void CSQC_Demo_Camera()