float smoothtime = bound(0, time - smooth_prevtime, 0.1);
smooth_prevtime = max(smooth_prevtime, drawtime); // drawtime is the previous frame's time at this point
- if(this.csqcmodel_teleported || !(this.pmove_flags & PMF_ONGROUND) || autocvar_cl_stairsmoothspeed <= 0)
+ if(this.csqcmodel_teleported || !(this.pmove_flags & PMF_ONGROUND) || autocvar_cl_stairsmoothspeed <= 0 || this.ground_networkentity)
stairsmoothz = v.z;
else
{
return v;
}
+// simplified copy of CSQCPlayer_ApplySmoothing for use on player models
+.float stairsmooth_offset;
+.float stairsmooth_prevtime;
+.float stairsmooth_drawtime; // holds the previous draw time
+vector CSQCModel_ApplyStairSmoothing(entity this, bool isonground, vector v)
+{
+ float smoothtime = bound(0, time - this.stairsmooth_prevtime, 0.1);
+ this.stairsmooth_prevtime = max(this.stairsmooth_prevtime, this.stairsmooth_drawtime); // stairsmooth_drawtime is the previous frame's time at this point
+
+ if(this.csqcmodel_teleported || !isonground || autocvar_cl_stairsmoothspeed <= 0 || this.ground_networkentity)
+ this.stairsmooth_offset = v.z;
+ else
+ {
+ if(this.stairsmooth_offset < v.z)
+ v.z = this.stairsmooth_offset = bound(v.z - PHYS_STEPHEIGHT(this), this.stairsmooth_offset + smoothtime * autocvar_cl_stairsmoothspeed, v.z);
+ else if(this.stairsmooth_offset > v.z)
+ v.z = this.stairsmooth_offset = bound(v.z, this.stairsmooth_offset - smoothtime * autocvar_cl_stairsmoothspeed, v.z + PHYS_STEPHEIGHT(this));
+ }
+
+ this.stairsmooth_prevtime = time;
+ this.stairsmooth_drawtime = drawtime;
+
+ return v;
+}
+
bool autocvar_v_deathtilt;
float autocvar_v_deathtiltangle;
void CSQCPlayer_ApplyDeathTilt(entity this)
float bob2_smooth;
vector CSQCPlayer_ApplyBobbing(entity this, vector v)
{
- if(this.csqcmodel_isdead)
+ if(this.csqcmodel_isdead || PHYS_INVEHICLE(this) || !(this.isplayermodel & ISPLAYER_PLAYER))
return v;
// bounded XY speed, used by several effects below
{
makevectors(view_angles);
forward = v_forward;
+ if(autocvar_chase_front && spectatee_status != -1)
+ forward = normalize(forward * -1);
// trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
float cdist = -autocvar_chase_back - 8;
chase_dest.x = v.x + forward.x * cdist;
chase_dest.y = v.y + forward.y * cdist;
chase_dest.z = v.z + forward.z * cdist + autocvar_chase_up;
- traceline(v, chase_dest, MOVE_NOMONSTERS, NULL);
+ if (this.move_movetype == MOVETYPE_NOCLIP)
+ {
+ // as if traceline hasn't hit anything
+ trace_endpos = chase_dest;
+ trace_plane_normal = '0 0 0';
+ }
+ else
+ {
+ traceline(v, chase_dest, MOVE_NOMONSTERS, NULL);
+ }
v.x = 1 * trace_endpos.x + 8 * forward.x + 4 * trace_plane_normal.x;
v.y = 1 * trace_endpos.y + 8 * forward.y + 4 * trace_plane_normal.y;
v.z = 1 * trace_endpos.z + 8 * forward.z + 4 * trace_plane_normal.z;
+
+ if(autocvar_chase_front && spectatee_status != -1)
+ {
+ // now flip the view so the player is looking at themselves
+ vector newang = vectoangles(forward);
+ view_angles.x = view_angles.x * -1; // inverse up-down looking direction
+ view_angles.y = newang.y;
+ }
}
#if 0
setproperty(VF_ANGLES, view_angles);
}
-bool autocvar_cl_useenginerefdef = false;
-
/** Called once per CSQC_UpdateView() */
void CSQCPlayer_SetCamera()
{
}
// relink
+ e.stairsmooth_drawtime = drawtime; // since drawtime is a frame old at this point, copy it now to avoid using a drawtime 2 frames old!
+ e.origin = CSQCModel_ApplyStairSmoothing(e, (e.pmove_flags & PMF_ONGROUND), e.origin);
setorigin(e, e.origin);
}
InterpolateOrigin_Do(view);
view.view_ofs = '0 0 1' * vh;
}
- if(autocvar_cl_useenginerefdef)
- {
- int refdefflags = 0;
- if (view.csqcmodel_teleported) refdefflags |= REFDEFFLAG_TELEPORTED;
- if (input_buttons & BIT(1)) refdefflags |= REFDEFFLAG_JUMPING;
- // note: these two only work in WIP2, but are harmless in WIP1
- if (PHYS_HEALTH(NULL) <= 0 && PHYS_HEALTH(NULL) != -666 && PHYS_HEALTH(NULL) != -2342) refdefflags |= REFDEFFLAG_DEAD;
- if (intermission) refdefflags |= REFDEFFLAG_INTERMISSION;
- V_CalcRefdef(view, refdefflags); // TODO? uses .health stat in the engine when this isn't called here, may be broken!
- }
- else
- {
- CSQCPlayer_CalcRefdef(view);
- }
+ CSQCPlayer_CalcRefdef(view);
}
else
{
if (this.entnum != player_localnum + 1) return false;
csqcplayer = this;
csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
- cvar_settemp("cl_movement_replay", "0");
+ if (cvar("cl_movement_replay"))
+ cvar_settemp("cl_movement_replay", "0");
this.entremove = CSQCPlayer_Remove;
return true;
}