]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
Add GL_ExtensionSupported in vid_null.c because vid_shared.c relies on
[xonotic/darkplaces.git] / cl_input.c
index 91da154c562a6a95cd850d11e8d147f8f0541866..cae0e1250aabd5d6c9501123222d28d110920f9d 100644 (file)
@@ -423,7 +423,7 @@ cvar_t cl_pitchspeed = {CVAR_SAVE, "cl_pitchspeed","150","keyboard pitch turning
 
 cvar_t cl_anglespeedkey = {CVAR_SAVE, "cl_anglespeedkey","1.5","how much +speed multiplies keyboard turning speed"};
 
-cvar_t cl_movement = {CVAR_SAVE, "cl_movement", "0", "enables clientside prediction of your player movement"};
+cvar_t cl_movement = {CVAR_SAVE, "cl_movement", "0", "enables clientside prediction of your player movement on DP servers (use cl_nopred for QWSV servers)"};
 cvar_t cl_movement_replay = {0, "cl_movement_replay", "1", "use engine prediction"};
 cvar_t cl_movement_nettimeout = {CVAR_SAVE, "cl_movement_nettimeout", "0.3", "stops predicting moves when server is lagging badly (avoids major performance problems), timeout in seconds"};
 cvar_t cl_movement_minping = {CVAR_SAVE, "cl_movement_minping", "0", "whether to use prediction when ping is lower than this value in milliseconds"};
@@ -442,6 +442,7 @@ cvar_t cl_movement_wateraccelerate = {0, "cl_movement_wateraccelerate", "-1", "h
 cvar_t cl_movement_jumpvelocity = {0, "cl_movement_jumpvelocity", "270", "how fast you move upward when you begin a jump (should match the quakec code)"};
 cvar_t cl_movement_airaccel_qw = {0, "cl_movement_airaccel_qw", "1", "ratio of QW-style air control as opposed to simple acceleration (reduces speed gain when zigzagging) (should match sv_airaccel_qw); when < 0, the speed is clamped against the maximum allowed forward speed after the move"};
 cvar_t cl_movement_airaccel_sideways_friction = {0, "cl_movement_airaccel_sideways_friction", "0", "anti-sideways movement stabilization (should match sv_airaccel_sideways_friction); when < 0, only so much friction is applied that braking (by accelerating backwards) cannot be stronger"};
+cvar_t cl_nopred = {CVAR_SAVE, "cl_nopred", "0", "(QWSV only) disables player movement prediction when playing on QWSV servers (this setting is separate from cl_movement because player expectations are different when playing on DP vs QW servers)"};
 
 cvar_t in_pitch_min = {0, "in_pitch_min", "-90", "how far you can aim upward (quake used -70)"};
 cvar_t in_pitch_max = {0, "in_pitch_max", "90", "how far you can aim downward (quake used 80)"};
@@ -461,24 +462,6 @@ cvar_t cl_nodelta = {0, "cl_nodelta", "0", "disables delta compression of non-pl
 cvar_t cl_csqc_generatemousemoveevents = {0, "cl_csqc_generatemousemoveevents", "1", "enables calls to CSQC_InputEvent with type 2, for compliance with EXT_CSQC spec"};
 
 extern cvar_t v_flipped;
-extern cvar_t v_yshearing;
-
-static void IN_AddToPitch(float angle)
-{
-       // In Duke3D mode, aiming up/down looks like scrolling - so let input
-       // modify the pitch slope instead of the pitch angle to compensate.
-       // This can be turned off by v_yshearing 2.
-       if (v_yshearing.integer == 1)
-       {
-               float tp = tanf(cl.viewangles[PITCH] * M_PI / 180);
-               tp += angle * M_PI / 180;
-               cl.viewangles[PITCH] = atanf(tp) * 180 / M_PI;
-       }
-       else
-       {
-               cl.viewangles[PITCH] += angle;
-       }
-}
 
 /*
 ================
@@ -505,15 +488,15 @@ static void CL_AdjustAngles (void)
        if (in_klook.state & 1)
        {
                V_StopPitchDrift ();
-               IN_AddToPitch(-speed*cl_pitchspeed.value * CL_KeyState (&in_forward));
-               IN_AddToPitch(speed*cl_pitchspeed.value * CL_KeyState (&in_back));
+               cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
+               cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
        }
 
        up = CL_KeyState (&in_lookup);
        down = CL_KeyState(&in_lookdown);
 
-       IN_AddToPitch(-speed*cl_pitchspeed.value * up);
-       IN_AddToPitch(-speed*cl_pitchspeed.value * down);
+       cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
+       cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
 
        if (up || down)
                V_StopPitchDrift ();
@@ -524,6 +507,8 @@ static void CL_AdjustAngles (void)
                cl.viewangles[YAW] -= 360;
        if (cl.viewangles[PITCH] >= 180)
                cl.viewangles[PITCH] -= 360;
+        // TODO: honor serverinfo minpitch and maxpitch values in PROTOCOL_QUAKEWORLD
+        // TODO: honor proquake pq_fullpitch cvar when playing on proquake server (server stuffcmd's this to 0 usually)
        cl.viewangles[PITCH] = bound(in_pitch_min.value, cl.viewangles[PITCH], in_pitch_max.value);
        cl.viewangles[ROLL] = bound(-180, cl.viewangles[ROLL], 180);
 }
@@ -679,7 +664,7 @@ void CL_Input (void)
                                cl.cmd.sidemove += m_side.value * in_mouse_x * modulatedsensitivity;
                        else
                                cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * modulatedsensitivity * cl.viewzoom;
-                       IN_AddToPitch(m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom);
+                       cl.viewangles[PITCH] += m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom;
                }
                else
                {
@@ -793,12 +778,12 @@ static void CL_UpdatePrydonCursor(void)
        }
        if (cl.cmd.cursor_screen[1] < -1)
        {
-               IN_AddToPitch(m_pitch.value * (cl.cmd.cursor_screen[1] - -1) * vid.height * sensitivity.value * cl.viewzoom);
+               cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - -1) * vid.height * sensitivity.value * cl.viewzoom;
                cl.cmd.cursor_screen[1] = -1;
        }
        if (cl.cmd.cursor_screen[1] > 1)
        {
-               IN_AddToPitch(m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.height * sensitivity.value * cl.viewzoom);
+               cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.height * sensitivity.value * cl.viewzoom;
                cl.cmd.cursor_screen[1] = 1;
        }
        */
@@ -854,7 +839,7 @@ static qboolean CL_ClientMovement_Unstick(cl_clientmovement_state_t *s)
        for (i = 0;i < NUMOFFSETS;i++)
        {
                VectorAdd(offsets[i], s->origin, neworigin);
-               if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true).startsolid)
+               if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true).startsolid)
                {
                        VectorCopy(neworigin, s->origin);
                        return true;
@@ -886,7 +871,7 @@ static void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
                // low ceiling first
                if (s->crouched)
                {
-                       trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
+                       trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
                        if (!trace.startsolid)
                                s->crouched = false;
                }
@@ -905,7 +890,7 @@ static void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
        // set onground
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1);
        VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 1); // -2 causes clientside doublejump bug at above 150fps, raising that to 300fps :)
-       trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
+       trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
        if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
        {
                s->onground = true;
@@ -921,16 +906,16 @@ static void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
        // set watertype/waterlevel
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1);
        s->waterlevel = WATERLEVEL_NONE;
-       s->watertype = CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
+       s->watertype = CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
        if (s->watertype)
        {
                s->waterlevel = WATERLEVEL_WETFEET;
                origin1[2] = s->origin[2] + (s->mins[2] + s->maxs[2]) * 0.5f;
-               if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+               if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
                {
                        s->waterlevel = WATERLEVEL_SWIMMING;
                        origin1[2] = s->origin[2] + 22;
-                       if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+                       if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
                                s->waterlevel = WATERLEVEL_SUBMERGED;
                }
        }
@@ -957,20 +942,20 @@ static void CL_ClientMovement_Move(cl_clientmovement_state_t *s)
        for (bump = 0, t = s->cmd.frametime;bump < 8 && VectorLength2(s->velocity) > 0;bump++)
        {
                VectorMA(s->origin, t, s->velocity, neworigin);
-               trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
+               trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
                if (trace.fraction < 1 && trace.plane.normal[2] == 0)
                {
                        // may be a step or wall, try stepping up
                        // first move forward at a higher level
                        VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + cl.movevars_stepheight);
                        VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + cl.movevars_stepheight);
-                       trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
+                       trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
                        if (!trace2.startsolid)
                        {
                                // then move down from there
                                VectorCopy(trace2.endpos, currentorigin2);
                                VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], s->origin[2]);
-                               trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
+                               trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
                                //Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]);
                                // accept the new trace if it made some progress
                                if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125)
@@ -1024,10 +1009,10 @@ static void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
                AngleVectors(yawangles, forward, NULL, NULL);
                VectorMA(s->origin, 24, forward, spot);
                spot[2] += 8;
-               if (CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsolid)
+               if (CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsolid)
                {
                        spot[2] += 24;
-                       if (!CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsolid)
+                       if (!CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsolid)
                        {
                                VectorScale(forward, 50, s->velocity);
                                s->velocity[2] = 310;
@@ -1277,9 +1262,9 @@ static void CL_ClientMovement_Physics_PM_AirAccelerate(cl_clientmovement_state_t
 
     if( wishspeed > curspeed * 1.01f )
     {
-        float accelspeed = curspeed + airforwardaccel * cl.movevars_maxairspeed * s->cmd.frametime;
-        if( accelspeed < wishspeed )
-            wishspeed = accelspeed;
+        float faccelspeed = curspeed + airforwardaccel * cl.movevars_maxairspeed * s->cmd.frametime;
+        if( faccelspeed < wishspeed )
+            wishspeed = faccelspeed;
     }
     else
     {
@@ -1370,9 +1355,9 @@ static void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                                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_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
+                                       trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
                                else
-                                       trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true, false);
+                                       trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true, false);
                                if (trace.fraction == 1 && !trace.startsolid)
                                        friction *= cl.movevars_edgefriction;
                        }
@@ -1830,7 +1815,20 @@ void CL_SendMove(void)
                cl.cmd.msec = 100;
        cl.cmd.frametime = cl.cmd.msec * (1.0 / 1000.0);
 
-       cl.cmd.predicted = cl_movement.integer != 0;
+       switch(cls.protocol)
+       {
+       case PROTOCOL_QUAKEWORLD:
+               // quakeworld uses a different cvar with opposite meaning, for compatibility
+               cl.cmd.predicted = cl_nopred.integer == 0;
+               break;
+       case PROTOCOL_DARKPLACES6:
+       case PROTOCOL_DARKPLACES7:
+               cl.cmd.predicted = cl_movement.integer != 0;
+               break;
+       default:
+               cl.cmd.predicted = false;
+               break;
+       }
 
        // movement is set by input code (forwardmove/sidemove/upmove)
        // always dump the first two moves, because they may contain leftover inputs from the last level
@@ -2077,7 +2075,6 @@ void CL_SendMove(void)
                // if cl_netrepeatinput is 1 and client framerate matches server
                // framerate, this is 10 bytes, if client framerate is lower this
                // will be more...
-               int i, j;
                unsigned int oldsequence = cl.cmd.sequence;
                unsigned int delta = bound(1, cl_netrepeatinput.integer + 1, 3);
                if (oldsequence > delta)
@@ -2257,6 +2254,7 @@ void CL_InitInput (void)
        Cvar_RegisterVariable(&cl_movement_jumpvelocity);
        Cvar_RegisterVariable(&cl_movement_airaccel_qw);
        Cvar_RegisterVariable(&cl_movement_airaccel_sideways_friction);
+       Cvar_RegisterVariable(&cl_nopred);
 
        Cvar_RegisterVariable(&in_pitch_min);
        Cvar_RegisterVariable(&in_pitch_max);