- // 4. 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!
- highpass3(gunorg,
- frametime * autocvar_cl_followmodel_side_highpass,
- frametime * autocvar_cl_followmodel_side_highpass,
- frametime * autocvar_cl_followmodel_up_highpass,
- gunorg_adjustment_highpass, gunorg);
- lowpass3(gunorg,
- frametime * autocvar_cl_followmodel_side_lowpass,
- frametime * autocvar_cl_followmodel_side_lowpass,
- frametime * autocvar_cl_followmodel_up_lowpass,
- gunorg_adjustment_lowpass, gunorg);
- // we assume here: PITCH = 0, YAW = 1, ROLL = 2
- highpass3(gunangles,
- frametime * autocvar_cl_leanmodel_up_highpass,
- frametime * autocvar_cl_leanmodel_side_highpass,
- 0,
- gunangles_adjustment_highpass, gunangles);
- lowpass3(gunangles,
- frametime * autocvar_cl_leanmodel_up_lowpass,
- frametime * autocvar_cl_leanmodel_side_lowpass,
- 0,
- gunangles_adjustment_lowpass, gunangles);
- float xyspeed = bound(0, vlen(vec2(csqcplayer.velocity)), 400);
+ return gunangles;
+}
+
+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;
+
+ // 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)
+ {
+ if (time - hitgroundtime > 0.05)
+ bobmodel_scale = min(1, bobmodel_scale + frametime * 5);
+ }
+ else
+ bobmodel_scale = max(0, bobmodel_scale - frametime * 5);
+
+ 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;
+
+ return gunorg;
+}
+
+void viewmodel_animate(entity this)
+{
+ if (autocvar_chase_active) return;
+ if (STAT(HEALTH) <= 0) return;
+
+ entity view = CSQCModel_server2csqc(player_localentnum - 1);
+
+ if (autocvar_cl_followmodel)
+ {
+ calc_followmodel_ofs(view);
+ this.origin += cl_followmodel_ofs;
+ }
+
+ if (autocvar_cl_leanmodel)
+ this.angles += leanmodel_ofs(view);