cvar_t cl_movement_friction = {0, "cl_movement_friction", "4", "how fast you slow down (should match sv_friction)"};
cvar_t cl_movement_wallfriction = {0, "cl_movement_wallfriction", "1", "how fast you slow down while sliding along a wall (should match sv_wallfriction)"};
cvar_t cl_movement_waterfriction = {0, "cl_movement_waterfriction", "-1", "how fast you slow down (should match sv_waterfriction), if less than 0 the cl_movement_friction variable is used instead"};
-cvar_t cl_movement_edgefriction = {0, "cl_movement_edgefriction", "2", "how much to slow down when you may be about to fall off a ledge (should match edgefriction)"};
+cvar_t cl_movement_edgefriction = {0, "cl_movement_edgefriction", "1", "how much to slow down when you may be about to fall off a ledge (should match edgefriction)"};
cvar_t cl_movement_stepheight = {0, "cl_movement_stepheight", "18", "how tall a step you can step in one instant (should match sv_stepheight)"};
cvar_t cl_movement_accelerate = {0, "cl_movement_accelerate", "10", "how fast you accelerate (should match sv_accelerate)"};
cvar_t cl_movement_airaccelerate = {0, "cl_movement_airaccelerate", "-1", "how fast you accelerate while in the air (should match sv_airaccelerate), if less than 0 the cl_movement_accelerate variable is used instead"};
cl.cmd.upmove *= cl_movespeedkey.value;
}
- in_mouse_x = 0;
- in_mouse_y = 0;
-
// allow mice or other external controllers to add to the move
IN_Move ();
- // ignore a mouse move if mouse was activated/deactivated this frame
- if (cl_ignoremousemoves)
- {
- cl_ignoremousemoves--;
- in_mouse_x = 0;
- in_mouse_y = 0;
- }
-
// apply m_filter if it is on
mx = in_mouse_x;
my = in_mouse_y;
old_mouse_x = mx;
old_mouse_y = my;
+ // ignore a mouse move if mouse was activated/deactivated this frame
+ if (cl_ignoremousemoves)
+ {
+ cl_ignoremousemoves--;
+ in_mouse_x = old_mouse_x = 0;
+ in_mouse_y = old_mouse_y = 0;
+ }
+
// if not in menu, apply mouse move to viewangles/movement
- if (!cl.csqc_wantsmousemove && in_client_mouse)
+ if (!key_consoleactive && key_dest == key_game && !cl.csqc_wantsmousemove)
{
float modulatedsensitivity = sensitivity.value * cl.sensitivityscale;
if (cl_prydoncursor.integer)
if (s->waterjumptime <= 0)
{
// water friction
- f = 1 - s->cmd.frametime * cl.movevars_waterfriction * s->waterlevel;
+ f = 1 - s->cmd.frametime * cl.movevars_waterfriction * (cls.protocol == PROTOCOL_QUAKEWORLD ? s->waterlevel : 1);
f = bound(0, f, 1);
VectorScale(s->velocity, f, s->velocity);
CL_ClientMovement_Move(s);
}
+void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
+{
+ vec_t zspeed, speed, dot, k;
+
+ if(s->cmd.forwardmove == 0 || s->cmd.sidemove != 0)
+ return;
+
+ zspeed = s->velocity[2];
+ s->velocity[2] = 0;
+ speed = VectorNormalizeLength(s->velocity);
+
+ dot = DotProduct(s->velocity, wishdir);
+ k = 32;
+ k *= cl.movevars_aircontrol*dot*dot*s->cmd.frametime;
+
+ if(dot > 0) { // we can't change direction while slowing down
+ VectorMAM(speed, s->velocity, k, wishdir, s->velocity);
+ VectorNormalize(s->velocity);
+ }
+
+ VectorScale(s->velocity, speed, s->velocity);
+ s->velocity[2] = zspeed;
+}
+
void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
{
vec_t friction;
{
// apply edge friction
f = sqrt(s->velocity[0] * s->velocity[0] + s->velocity[1] * s->velocity[1]);
- friction = cl.movevars_friction;
- if (f > 0 && cl.movevars_edgefriction != 1)
+ if (f > 0)
{
- vec3_t neworigin2;
- vec3_t neworigin3;
- // note: QW uses the full player box for the trace, and yet still
- // uses s->origin[2] + s->mins[2], which is clearly an bug, but
- // this mimics it for compatibility
- VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]);
- VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34);
- if (cls.protocol == PROTOCOL_QUAKEWORLD)
- trace = CL_Move(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
- else
- trace = CL_Move(neworigin2, vec3_origin, vec3_origin, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
- if (trace.fraction == 1 && !trace.startsolid)
- friction *= cl.movevars_edgefriction;
+ friction = cl.movevars_friction;
+ if (cl.movevars_edgefriction != 1)
+ {
+ vec3_t neworigin2;
+ vec3_t neworigin3;
+ // note: QW uses the full player box for the trace, and yet still
+ // uses s->origin[2] + s->mins[2], which is clearly an bug, but
+ // this mimics it for compatibility
+ VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]);
+ VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34);
+ if (cls.protocol == PROTOCOL_QUAKEWORLD)
+ trace = CL_Move(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ else
+ trace = CL_Move(neworigin2, vec3_origin, vec3_origin, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ if (trace.fraction == 1 && !trace.startsolid)
+ friction *= cl.movevars_edgefriction;
+ }
+ // apply ground friction
+ f = 1 - s->cmd.frametime * friction * ((f < cl.movevars_stopspeed) ? (cl.movevars_stopspeed / f) : 1);
+ f = max(f, 0);
+ VectorScale(s->velocity, f, s->velocity);
}
- // apply ground friction
- f = 1 - s->cmd.frametime * friction * ((f < cl.movevars_stopspeed) ? (cl.movevars_stopspeed / f) : 1);
- f = max(f, 0);
- VectorScale(s->velocity, f, s->velocity);
addspeed = wishspeed - DotProduct(s->velocity, wishdir);
if (addspeed > 0)
{
vec_t vel_straight;
vec_t vel_z;
vec3_t vel_perpend;
+ float wishspeed2, accel;
// apply air speed limit
wishspeed = min(wishspeed, cl.movevars_maxairspeed);
+ accel = cl.movevars_airaccelerate;
+
+ // CPM: air control
+ wishspeed2 = wishspeed;
+ if(cl.movevars_airstopaccelerate != 0)
+ if(DotProduct(s->velocity, wishdir) < 0)
+ accel = cl.movevars_airstopaccelerate;
+ if(s->cmd.forwardmove == 0 && s->cmd.sidemove != 0)
+ {
+ if(cl.movevars_maxairstrafespeed)
+ if(wishspeed > cl.movevars_maxairstrafespeed)
+ wishspeed = cl.movevars_maxairstrafespeed;
+ if(cl.movevars_airstrafeaccelerate)
+ accel = cl.movevars_airstrafeaccelerate;
+ }
+ // !CPM
/*
addspeed = wishspeed - DotProduct(s->velocity, wishdir);
f = wishspeed - vel_straight;
if(f > 0)
- vel_straight += min(f, cl.movevars_airaccelerate * s->cmd.frametime * wishspeed) * cl.movevars_airaccel_qw;
+ vel_straight += min(f, accel * s->cmd.frametime * wishspeed) * cl.movevars_airaccel_qw;
if(wishspeed > 0)
- vel_straight += min(wishspeed, cl.movevars_airaccelerate * s->cmd.frametime * wishspeed) * (1 - cl.movevars_airaccel_qw);
+ vel_straight += min(wishspeed, accel * s->cmd.frametime * wishspeed) * (1 - cl.movevars_airaccel_qw);
VectorM(1 - (s->cmd.frametime * (wishspeed / cl.movevars_maxairspeed) * cl.movevars_airaccel_sideways_friction), vel_perpend, vel_perpend);
VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
s->velocity[2] += vel_z;
+
+ if(cl.movevars_aircontrol)
+ CL_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2);
}
s->velocity[2] -= cl.movevars_gravity * cl.movevars_entgravity * s->cmd.frametime;
CL_ClientMovement_Move(s);
cl.movevars_friction = cl.statsf[STAT_MOVEVARS_FRICTION];
cl.movevars_wallfriction = cl.statsf[STAT_MOVEVARS_WALLFRICTION];
cl.movevars_waterfriction = cl.statsf[STAT_MOVEVARS_WATERFRICTION];
+ cl.movevars_airstopaccelerate = cl.statsf[STAT_MOVEVARS_AIRSTOPACCELERATE];
+ cl.movevars_airstrafeaccelerate = cl.statsf[STAT_MOVEVARS_AIRSTRAFEACCELERATE];
+ cl.movevars_maxairstrafespeed = cl.statsf[STAT_MOVEVARS_MAXAIRSTRAFESPEED];
+ cl.movevars_aircontrol = cl.statsf[STAT_MOVEVARS_AIRCONTROL];
}
else
{
cl.movevars_stepheight = cl_movement_stepheight.value;
cl.movevars_airaccel_qw = cl_movement_airaccel_qw.value;
cl.movevars_airaccel_sideways_friction = cl_movement_airaccel_sideways_friction.value;
+ cl.movevars_airstopaccelerate = 0;
+ cl.movevars_airstrafeaccelerate = 0;
+ cl.movevars_maxairstrafespeed = 0;
+ cl.movevars_aircontrol = 0;
}
}
if (bits & QW_CM_ANGLE3)
MSG_WriteAngle16i(buf, to->viewangles[2]);
if (bits & QW_CM_FORWARD)
- MSG_WriteShort(buf, to->forwardmove);
+ MSG_WriteShort(buf, (short) to->forwardmove);
if (bits & QW_CM_SIDE)
- MSG_WriteShort(buf, to->sidemove);
+ MSG_WriteShort(buf, (short) to->sidemove);
if (bits & QW_CM_UP)
- MSG_WriteShort(buf, to->upmove);
+ MSG_WriteShort(buf, (short) to->upmove);
if (bits & QW_CM_BUTTONS)
MSG_WriteByte(buf, to->buttons);
if (bits & QW_CM_IMPULSE)
packettime = 0;
// always send if buttons changed or an impulse is pending
// even if it violates the rate limit!
- if (!cl_netimmediatebuttons.integer || (cl.movecmd[0].buttons == cl.movecmd[1].buttons && !cl.movecmd[0].impulse))
+ if (!cl.movecmd[0].impulse && (!cl_netimmediatebuttons.integer || cl.movecmd[0].buttons == cl.movecmd[1].buttons))
{
// don't choke the connection with packets (obey rate limit)
if ((cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon == SIGNONS) && !NetConn_CanSend(cls.netcon) && !cl.islocalgame)