]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/view.qc
Merge branch 'master' into terencehill/dynamic_hud
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / view.qc
index ed675fc6b7cdd34409fabefd05378f44ce0eeec2..6ea2bb91b42a79b8d406b08b04c849bd804ca670 100644 (file)
@@ -114,117 +114,152 @@ float autocvar_cl_leanmodel_lowpass = 0.05;
        highpass(value.z, frac, ref_store.z, ref_out.z); \
 } MACRO_END
 
-void viewmodel_animate(entity this)
+void calc_followmodel_ofs(entity view)
 {
-       static float prevtime;
-       float frametime = (time - prevtime);
-       prevtime = time;
+       if(cl_followmodel_time == time)
+               return; // cl_followmodel_ofs already calculated for this frame
 
-       if (autocvar_chase_active) return;
-       if (STAT(HEALTH) <= 0) return;
+       float frac;
+       vector gunorg = '0 0 0';
+       static vector vel_average;
+       static vector gunorg_prev = '0 0 0';
+       static vector gunorg_adjustment_highpass;
+       static vector gunorg_adjustment_lowpass;
+
+       vector vel;
+       if (autocvar_cl_followmodel_velocity_absolute)
+               vel = view.velocity;
+       else
+       {
+               vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
+               MAKEVECTORS(makevectors, view_angles, forward, right, up);
+               vel.x = view.velocity * forward;
+               vel.y = view.velocity * right * -1;
+               vel.z = view.velocity * up;
+       }
 
-       entity view = CSQCModel_server2csqc(player_localentnum - 1);
+       vel.x = bound(vel_average.x - autocvar_cl_followmodel_limit, vel.x, vel_average.x + autocvar_cl_followmodel_limit);
+       vel.y = bound(vel_average.y - autocvar_cl_followmodel_limit, vel.y, vel_average.y + autocvar_cl_followmodel_limit);
+       vel.z = bound(vel_average.z - autocvar_cl_followmodel_limit, vel.z, vel_average.z + autocvar_cl_followmodel_limit);
 
-       bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
-       static bool oldonground;
-       static float hitgroundtime;
-       if (clonground)
+       frac = avg_factor(autocvar_cl_followmodel_velocity_lowpass);
+       lowpass3(vel, frac, vel_average, gunorg);
+
+       gunorg *= -autocvar_cl_followmodel_speed * 0.042;
+
+       // perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
+       // trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
+       frac = avg_factor(autocvar_cl_followmodel_highpass);
+       highpass3(gunorg, frac, gunorg_adjustment_highpass, gunorg);
+       frac = avg_factor(autocvar_cl_followmodel_lowpass);
+       lowpass3(gunorg, frac, gunorg_adjustment_lowpass, gunorg);
+
+       if (autocvar_cl_followmodel_velocity_absolute)
        {
-               float f = time; // cl.movecmd[0].time
-               if (!oldonground)
-                       hitgroundtime = f;
+               vector fixed_gunorg;
+               vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
+               MAKEVECTORS(makevectors, view_angles, forward, right, up);
+               fixed_gunorg.x = gunorg * forward;
+               fixed_gunorg.y = gunorg * right * -1;
+               fixed_gunorg.z = gunorg * up;
+               gunorg = fixed_gunorg;
        }
-       oldonground = clonground;
 
+       cl_followmodel_ofs = gunorg;
+       cl_followmodel_time = time;
+}
 
-       bool teleported = view.csqcmodel_teleported;
-
+vector leanmodel_ofs(entity view)
+{
        float frac;
-       if(autocvar_cl_followmodel)
-       {
-               vector gunorg = '0 0 0';
-               static vector vel_average;
-               static vector gunorg_prev = '0 0 0';
-               static vector gunorg_adjustment_highpass;
-               static vector gunorg_adjustment_lowpass;
+       vector gunangles = '0 0 0';
+       static vector gunangles_prev = '0 0 0';
+       static vector gunangles_highpass = '0 0 0';
+       static vector gunangles_adjustment_highpass;
+       static vector gunangles_adjustment_lowpass;
 
-               vector vel;
-               if(autocvar_cl_followmodel_velocity_absolute)
-                       vel = view.velocity;
-               else
-               {
-                       vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
-                       MAKEVECTORS(makevectors, view_angles, forward, right, up);
-                       vel.x = view.velocity * forward;
-                       vel.y = view.velocity * right * -1;
-                       vel.z = view.velocity * up;
-               }
+       if (view.csqcmodel_teleported)
+               gunangles_prev = view_angles;
 
-               vel.x = bound(vel_average.x - autocvar_cl_followmodel_limit, vel.x, vel_average.x + autocvar_cl_followmodel_limit);
-               vel.y = bound(vel_average.y - autocvar_cl_followmodel_limit, vel.y, vel_average.y + autocvar_cl_followmodel_limit);
-               vel.z = bound(vel_average.z - autocvar_cl_followmodel_limit, vel.z, vel_average.z + autocvar_cl_followmodel_limit);
+       // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
+       gunangles_highpass += gunangles_prev;
+       PITCH(gunangles_highpass) += 360 * floor((PITCH(view_angles) - PITCH(gunangles_highpass)) / 360 + 0.5);
+       YAW(gunangles_highpass) += 360 * floor((YAW(view_angles) - YAW(gunangles_highpass)) / 360 + 0.5);
+       ROLL(gunangles_highpass) += 360 * floor((ROLL(view_angles) - ROLL(gunangles_highpass)) / 360 + 0.5);
+       frac = avg_factor(autocvar_cl_leanmodel_highpass1);
+       highpass2_limited(view_angles, frac, autocvar_cl_leanmodel_limit, gunangles_highpass, gunangles);
+       gunangles_prev = view_angles;
+       gunangles_highpass -= gunangles_prev;
 
-               frac = avg_factor(autocvar_cl_followmodel_velocity_lowpass);
-               lowpass3(vel, frac, vel_average, gunorg);
+       PITCH(gunangles) *= -autocvar_cl_leanmodel_speed;
+       YAW(gunangles) *= -autocvar_cl_leanmodel_speed;
 
-               gunorg *= -autocvar_cl_followmodel_speed * 0.042;
+       // we assume here: PITCH = 0, YAW = 1, ROLL = 2
+       frac = avg_factor(autocvar_cl_leanmodel_highpass);
+       highpass2(gunangles, frac, gunangles_adjustment_highpass, gunangles);
+       frac = avg_factor(autocvar_cl_leanmodel_lowpass);
+       lowpass2(gunangles, frac, gunangles_adjustment_lowpass, gunangles);
 
-               // perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
-               // trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
-               frac = avg_factor(autocvar_cl_followmodel_highpass);
-               highpass3(gunorg, frac, gunorg_adjustment_highpass, gunorg);
-               frac = avg_factor(autocvar_cl_followmodel_lowpass);
-               lowpass3(gunorg, frac, gunorg_adjustment_lowpass, gunorg);
+       gunangles.x = -gunangles.x; // pitch was inverted, now that actually matters
 
-               if(autocvar_cl_followmodel_velocity_absolute)
-               {
-                       vector fixed_gunorg;
-                       vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
-                       MAKEVECTORS(makevectors, view_angles, forward, right, up);
-                       fixed_gunorg.x = gunorg * forward;
-                       fixed_gunorg.y = gunorg * right * -1;
-                       fixed_gunorg.z = gunorg * up;
-                       gunorg = fixed_gunorg;
-               }
+       return gunangles;
+}
 
-               this.origin += gunorg;
+vector bobmodel_ofs(entity view)
+{
+       bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
+       static bool oldonground;
+       static float hitgroundtime;
+       if (clonground)
+       {
+               float f = time; // cl.movecmd[0].time
+               if (!oldonground)
+                       hitgroundtime = f;
        }
+       oldonground = clonground;
 
-       if(autocvar_cl_leanmodel)
+       // calculate for swinging gun model
+       // the gun bobs when running on the ground, but doesn't bob when you're in the air.
+       vector gunorg = '0 0 0';
+       static float bobmodel_scale = 0;
+       static float time_ofs = 0; // makes the effect always restart in the same way
+       if (clonground)
        {
-               vector gunangles = '0 0 0';
-               static vector gunangles_prev = '0 0 0';
-               static vector gunangles_highpass = '0 0 0';
-               static vector gunangles_adjustment_highpass;
-               static vector gunangles_adjustment_lowpass;
+               if (time - hitgroundtime > 0.05)
+                       bobmodel_scale = min(1, bobmodel_scale + frametime * 5);
+       }
+       else
+               bobmodel_scale = max(0, bobmodel_scale - frametime * 5);
 
-               if (teleported)
-                       gunangles_prev = view_angles;
+       float xyspeed = bound(0, vlen(vec2(view.velocity)), 400);
+       if (bobmodel_scale && xyspeed)
+       {
+               float bspeed = xyspeed * 0.01 * autocvar_cl_viewmodel_scale * bobmodel_scale;
+               float s = (time - time_ofs) * autocvar_cl_bobmodel_speed;
+               gunorg.y = bspeed * autocvar_cl_bobmodel_side * sin(s);
+               gunorg.z = bspeed * autocvar_cl_bobmodel_up * cos(s * 2);
+       }
+       else
+               time_ofs = time;
 
-               // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
-               gunangles_highpass += gunangles_prev;
-               PITCH(gunangles_highpass) += 360 * floor((PITCH(view_angles) - PITCH(gunangles_highpass)) / 360 + 0.5);
-               YAW(gunangles_highpass) += 360 * floor((YAW(view_angles) - YAW(gunangles_highpass)) / 360 + 0.5);
-               ROLL(gunangles_highpass) += 360 * floor((ROLL(view_angles) - ROLL(gunangles_highpass)) / 360 + 0.5);
-               frac = avg_factor(autocvar_cl_leanmodel_highpass1);
-               highpass2_limited(view_angles, frac, autocvar_cl_leanmodel_limit, gunangles_highpass, gunangles);
-               gunangles_prev = view_angles;
-               gunangles_highpass -= gunangles_prev;
+       return gunorg;
+}
 
-               PITCH(gunangles) *= -autocvar_cl_leanmodel_speed;
-               YAW(gunangles) *= -autocvar_cl_leanmodel_speed;
+void viewmodel_animate(entity this)
+{
+       if (autocvar_chase_active) return;
+       if (STAT(HEALTH) <= 0) return;
 
-               // we assume here: PITCH = 0, YAW = 1, ROLL = 2
-               frac = avg_factor(autocvar_cl_leanmodel_highpass);
-               highpass2(gunangles, frac, gunangles_adjustment_highpass, gunangles);
-               frac = avg_factor(autocvar_cl_leanmodel_lowpass);
-               lowpass2(gunangles, frac, gunangles_adjustment_lowpass, gunangles);
+       entity view = CSQCModel_server2csqc(player_localentnum - 1);
 
-               gunangles.x = -gunangles.x; // pitch was inverted, now that actually matters
-               this.angles += gunangles;
+       if (autocvar_cl_followmodel)
+       {
+               calc_followmodel_ofs(view);
+               this.origin += cl_followmodel_ofs;
        }
 
-       float xyspeed = bound(0, vlen(vec2(view.velocity)), 400);
+       if (autocvar_cl_leanmodel)
+               this.angles += leanmodel_ofs(view);
 
        // vertical view bobbing code
        // TODO: cl_bob
@@ -238,31 +273,7 @@ void viewmodel_animate(entity this)
 
        // gun model bobbing code
        if (autocvar_cl_bobmodel)
-       {
-               // calculate for swinging gun model
-               // the gun bobs when running on the ground, but doesn't bob when you're in the air.
-               static float bobmodel_scale = 0;
-               static float time_ofs = 0; // makes the effect always restart in the same way
-               if (clonground)
-               {
-                       if (time - hitgroundtime > 0.05)
-                               bobmodel_scale = min(1, bobmodel_scale + frametime * 5);
-               }
-               else
-                       bobmodel_scale = max(0, bobmodel_scale - frametime * 5);
-               if(bobmodel_scale && xyspeed)
-               {
-                       float bspeed = xyspeed * 0.01 * autocvar_cl_viewmodel_scale * bobmodel_scale;
-                       float s = (time - time_ofs) * autocvar_cl_bobmodel_speed;
-                       vector gunorg = '0 0 0';
-                       gunorg.y = bspeed * autocvar_cl_bobmodel_side * sin(s);
-                       gunorg.z = bspeed * autocvar_cl_bobmodel_up * cos(s * 2);
-
-                       this.origin += gunorg;
-               }
-               else
-                       time_ofs = time;
-       }
+               this.origin += bobmodel_ofs(view);
 }
 
 .vector viewmodel_origin, viewmodel_angles;
@@ -272,7 +283,7 @@ void viewmodel_animate(entity this)
 
 void viewmodel_draw(entity this)
 {
-       if(!activeweapon)
+       if(!activeweapon || !autocvar_r_drawviewmodel)
                return;
        int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
        float a = this.alpha;
@@ -1337,6 +1348,7 @@ void HUD_Draw()
 
                        HUD_Main();
                        HUD_DrawScoreboard();
+                       HUD_Scale_Disable();
                }
 
        // crosshair goes VERY LAST
@@ -1379,6 +1391,8 @@ void CSQC_UpdateView(float w, float h)
 
        lasthud = hud;
 
+       HUD_Scale_Disable();
+
        if(autocvar__hud_showbinds_reload) // menu can set this one
        {
                db_close(binddb);
@@ -1468,13 +1482,13 @@ void CSQC_UpdateView(float w, float h)
                        if(!gen)
                                ons_roundlost = false; // don't enforce the 3rd person camera if there is no dead generator to show
                }
-               if(WantEventchase(self) || (!autocvar_cl_orthoview && ons_roundlost))
+               if(WantEventchase(this) || (!autocvar_cl_orthoview && ons_roundlost))
                {
                        eventchase_running = true;
 
                        entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1));
                        if(!local_player)
-                               local_player = self; // fall back!
+                               local_player = this; // fall back!
 
                        // 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);
@@ -1493,7 +1507,7 @@ void CSQC_UpdateView(float w, float h)
 
                        if(view_offset)
                        {
-                               WarpZone_TraceLine(current_view_origin, current_view_origin + view_offset + ('0 0 1' * autocvar_cl_eventchase_maxs.z), MOVE_WORLDONLY, self);
+                               WarpZone_TraceLine(current_view_origin, current_view_origin + view_offset + ('0 0 1' * autocvar_cl_eventchase_maxs.z), MOVE_WORLDONLY, this);
                                if(trace_fraction == 1) { current_view_origin += view_offset; }
                                else { current_view_origin.z += max(0, (trace_endpos.z - current_view_origin.z) - autocvar_cl_eventchase_maxs.z); }
                        }
@@ -1522,14 +1536,14 @@ void CSQC_UpdateView(float w, float h)
                        makevectors(view_angles);
 
                        vector eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
-                       WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, self);
+                       WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, this);
 
                        // If the boxtrace fails, revert back to line tracing.
                        if(!local_player.viewloc)
                        if(trace_startsolid)
                        {
                                eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
-                               WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, self);
+                               WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, this);
                                setproperty(VF_ORIGIN, (trace_endpos - (v_forward * autocvar_cl_eventchase_mins.z)));
                        }
                        else { setproperty(VF_ORIGIN, trace_endpos); }