]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
cl_movement: hit CSQC entities if solid (rationale: if you don't want this in your...
[xonotic/darkplaces.git] / cl_input.c
index 8fe0d4cbeffc5dd513a1ae86c855836b135339f1..a0a29575608beb057fcaae2be3fa336540d328cb 100644 (file)
@@ -457,6 +457,8 @@ cvar_t cl_netimmediatebuttons = {CVAR_SAVE, "cl_netimmediatebuttons", "1", "send
 
 cvar_t cl_nodelta = {0, "cl_nodelta", "0", "disables delta compression of non-player entities in QW network protocol"};
 
+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;
 
 /*
@@ -516,6 +518,7 @@ CL_Input
 Send the intended movement message to the server
 ================
 */
+extern qboolean CL_VM_InputEvent (int eventtype, int x, int y);
 void CL_Input (void)
 {
        float mx, my;
@@ -562,6 +565,27 @@ void CL_Input (void)
        // allow mice or other external controllers to add to the move
        IN_Move ();
 
+       // send mouse move to csqc
+       if (cl.csqc_loaded && cl_csqc_generatemousemoveevents.integer)
+       {
+               if (cl.csqc_wantsmousemove)
+               {
+                       // event type 3 is a DP_CSQC thing
+                       static int oldwindowmouse[2];
+                       if (oldwindowmouse[0] != in_windowmouse_x || oldwindowmouse[1] != in_windowmouse_y)
+                       {
+                               CL_VM_InputEvent(3, in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height);
+                               oldwindowmouse[0] = in_windowmouse_x;
+                               oldwindowmouse[1] = in_windowmouse_y;
+                       }
+               }
+               else
+               {
+                       if (in_mouse_x || in_mouse_y)
+                               CL_VM_InputEvent(2, in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height);
+               }
+       }
+
        // apply m_accelerate if it is on
        if(m_accelerate.value > 1)
        {
@@ -847,7 +871,7 @@ 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, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false).startsolid)
+               if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true).startsolid)
                {
                        VectorCopy(neworigin, s->origin);
                        return true;
@@ -859,6 +883,7 @@ qboolean CL_ClientMovement_Unstick(cl_clientmovement_state_t *s)
 
 void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
 {
+       vec_t f;
        vec3_t origin1, origin2;
        trace_t trace;
 
@@ -878,7 +903,7 @@ 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, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                       trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
                        if (!trace.startsolid)
                                s->crouched = false;
                }
@@ -897,8 +922,18 @@ 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, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
-       s->onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7;
+       trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
+       if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
+       {
+               s->onground = true;
+
+               // this code actually "predicts" an impact; so let's clip velocity first
+               f = DotProduct(s->velocity, trace.plane.normal);
+               if(f < 0) // only if moving downwards actually
+                       VectorMA(s->velocity, -f, trace.plane.normal, s->velocity);
+       }
+       else
+               s->onground = false;
 
        // set watertype/waterlevel
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1);
@@ -939,20 +974,20 @@ 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, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+               trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 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, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                       trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 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, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                               trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 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)
@@ -1305,7 +1340,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
        // released at least once since the last jump
        if (s->cmd.jump)
        {
-               if (s->onground && (s->cmd.canjump || !cl_movement_track_canjump.integer)) // FIXME remove this cvar again when canjump logic actually works, or maybe keep it for mods that allow "pogo-ing"
+               if (s->onground && (s->cmd.canjump || !cl_movement_track_canjump.integer))
                {
                        s->velocity[2] += cl.movevars_jumpvelocity;
                        s->onground = false;
@@ -1348,9 +1383,9 @@ 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, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                                       trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
                                else
-                                       trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false, false);
+                                       trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true, false);
                                if (trace.fraction == 1 && !trace.startsolid)
                                        friction *= cl.movevars_edgefriction;
                        }
@@ -1586,6 +1621,7 @@ void CL_ClientMovement_Replay(void)
                        s.cmd = cl.movecmd[i];
                        if (i < CL_MAX_USERCMDS - 1)
                                s.cmd.canjump = cl.movecmd[i+1].canjump;
+
                        // if a move is more than 50ms, do it as two moves (matching qwsv)
                        //Con_Printf("%i ", s.cmd.msec);
                        if(s.cmd.frametime > 0.0005)
@@ -1596,8 +1632,14 @@ void CL_ClientMovement_Replay(void)
                                        CL_ClientMovement_PlayerMove(&s);
                                }
                                CL_ClientMovement_PlayerMove(&s);
-                               cl.movecmd[i].canjump = s.cmd.canjump;
                        }
+                       else
+                       {
+                               // we REALLY need this handling to happen, even if the move is not executed
+                               if (!s.cmd.jump)
+                                       s.cmd.canjump = true;
+                       }
+                       cl.movecmd[i].canjump = s.cmd.canjump;
                }
                //Con_Printf("\n");
                CL_ClientMovement_UpdateStatus(&s);
@@ -2234,5 +2276,7 @@ void CL_InitInput (void)
        Cvar_RegisterVariable(&cl_netimmediatebuttons);
 
        Cvar_RegisterVariable(&cl_nodelta);
+
+       Cvar_RegisterVariable(&cl_csqc_generatemousemoveevents);
 }