// if coming from the player, update the start position
//if (b->entity == cl.viewentity)
// Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, b->start);
- if (cl_beams_relative.integer && b->entity && cl.entities[b->entity].state_current.active && b->relativestartvalid)
+ if (cl_beams_relative.integer >= 1 && b->entity && (b->entity == cl.viewentity || cl_beams_relative.integer >= 2) && cl.entities[b->entity].state_current.active && b->relativestartvalid)
{
entity_render_t *r = &cl.entities[b->entity].render;
//Matrix4x4_OriginFromMatrix(&r->matrix, origin);
void CL_LerpPlayer(float frac)
{
int i;
- float d;
cl.viewzoom = cl.mviewzoom[1] + frac * (cl.mviewzoom[0] - cl.mviewzoom[1]);
for (i = 0;i < 3;i++)
cl.punchvector[i] = cl.mpunchvector[1][i] + frac * (cl.mpunchvector[0][i] - cl.mpunchvector[1][i]);
cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
}
-
- if (cls.demoplayback)
- {
- // interpolate the angles
- for (i = 0;i < 3;i++)
- {
- d = cl.mviewangles[0][i] - cl.mviewangles[1][i];
- if (d > 180)
- d -= 360;
- else if (d < -180)
- d += 360;
- cl.viewangles[i] = cl.mviewangles[1][i] + frac * d;
- }
- }
}
void CSQC_RelinkAllEntities (int drawmask)
ent->persistent.muzzleflash = 0;
VectorCopy(ent->state_current.origin, ent->persistent.trail_origin);
}
- else if (cls.timedemo || cl_nolerp.integer || DotProduct(odelta, odelta) > 1000*1000)
+ else if (cls.timedemo || cl_nolerp.integer || DotProduct(odelta, odelta) > 1000*1000 || (cl.fixangle[0] && !cl.fixangle[1]))
{
// don't interpolate the move
+ // (the fixangle[] check detects teleports, but not constant fixangles
+ // such as when spectating)
ent->persistent.lerpdeltatime = 0;
ent->persistent.lerpstarttime = cl.mtime[1];
VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
cl.mtime[1] = cl.mtime[0];
cl.mtime[0] = realtime; // qw has no clock
cl.movement_needupdate = true;
+ // if true the cl.viewangles are interpolated from cl.mviewangles[]
+ // during this frame
+ // (makes spectating players much smoother and prevents mouse movement from turning)
+ cl.fixangle[1] = cl.fixangle[0];
+ cl.fixangle[0] = false;
+ if (!cls.demoplayback)
+ VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
// slightly kill qw player entities each frame
for (i = 1;i < cl.maxclients;i++)
case qw_svc_setangle:
for (i=0 ; i<3 ; i++)
cl.viewangles[i] = MSG_ReadAngle (cls.protocol);
+ if (!cls.demoplayback)
+ {
+ cl.fixangle[0] = true;
+ VectorCopy(cl.viewangles, cl.mviewangles[0]);
+ // disable interpolation if this is new
+ if (!cl.fixangle[1])
+ VectorCopy(cl.viewangles, cl.mviewangles[1]);
+ }
break;
case qw_svc_lightstyle:
cl.mtime[1] = cl.mtime[0];
cl.mtime[0] = MSG_ReadFloat ();
cl.movement_needupdate = true;
+ // if true the cl.viewangles are interpolated from cl.mviewangles[]
+ // during this frame
+ // (makes spectating players much smoother and prevents mouse movement from turning)
+ cl.fixangle[1] = cl.fixangle[0];
+ cl.fixangle[0] = false;
+ if (!cls.demoplayback)
+ VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
break;
case svc_clientdata:
case svc_setangle:
for (i=0 ; i<3 ; i++)
cl.viewangles[i] = MSG_ReadAngle (cls.protocol);
+ if (!cls.demoplayback)
+ {
+ cl.fixangle[0] = true;
+ VectorCopy(cl.viewangles, cl.mviewangles[0]);
+ // disable interpolation if this is new
+ if (!cl.fixangle[1])
+ VectorCopy(cl.viewangles, cl.mviewangles[1]);
+ }
break;
case svc_setview:
vec3_t mvelocity[2], velocity;
// update by server, can be used by mods for zooming
vec_t mviewzoom[2], viewzoom;
+ // if true interpolation the mviewangles and other interpolation of the
+ // player is disabled until the next network packet
+ // this is used primarily by teleporters, and when spectating players
+ // special checking of the old fixangle[1] is used to differentiate
+ // between teleporting and spectating
+ qboolean fixangle[2];
// client movement simulation
// these fields are only updated by CL_ClientMovement (called by CL_SendMove after parsing each network packet)
{
// ent is the view entity (visible when out of body)
ent = &cl.entities[cl.viewentity];
+ // player can look around, so take the origin from the entity,
+ // and the angles from the input system
+ Matrix4x4_OriginFromMatrix(&ent->render.matrix, vieworg);
+ VectorCopy(cl.viewangles, viewangles);
+ // interpolate the angles if playing a demo or spectating someone
+ if (cls.demoplayback || cl.fixangle[0])
+ {
+ int i;
+ float frac = bound(0, (cl.time - cl.mtime[1]) / (cl.mtime[0] - cl.mtime[1]), 1);
+ for (i = 0;i < 3;i++)
+ {
+ float d = cl.mviewangles[0][i] - cl.mviewangles[1][i];
+ if (d > 180)
+ d -= 360;
+ else if (d < -180)
+ d += 360;
+ viewangles[i] = cl.mviewangles[1][i] + frac * d;
+ }
+ }
if (cl.intermission)
{
// entity is a fixed camera, just copy the matrix
}
else
{
- // player can look around, so take the origin from the entity,
- // and the angles from the input system
- Matrix4x4_OriginFromMatrix(&ent->render.matrix, vieworg);
- VectorCopy(cl.viewangles, viewangles);
-
// apply qw weapon recoil effect (this did not work in QW)
// TODO: add a cvar to disable this
viewangles[PITCH] += cl.qw_weaponkick;