X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=cl_input.c;h=a0a29575608beb057fcaae2be3fa336540d328cb;hp=8c38c69d9ee23aa7c0630fc030013fd6f97cfeff;hb=70da4b9c6dd36d17b055cfa8ca1d89e6121fb08d;hpb=1c1d251ba80d985f8b7f641f3e9baa0584eb2a86 diff --git a/cl_input.c b/cl_input.c index 8c38c69d..a0a29575 100644 --- a/cl_input.c +++ b/cl_input.c @@ -423,6 +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_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"}; cvar_t cl_movement_track_canjump = {CVAR_SAVE, "cl_movement_track_canjump", "1", "track if the player released the jump key between two jumps to decide if he is able to jump or not; when off, this causes some \"sliding\" slightly above the floor when the jump key is held too long; if the mod allows repeated jumping by holding space all the time, this has to be set to zero too"}; @@ -456,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; /* @@ -515,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; @@ -561,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) { @@ -587,14 +612,7 @@ void CL_Input (void) } else { - /* - f = log(averagespeed); - mi = log(mi); - ma = log(ma); - */ f = averagespeed; - mi = mi; - ma = ma; f = (f - mi) / (ma - mi) * (m_accelerate.value - 1) + 1; } @@ -853,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; @@ -865,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; @@ -884,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; } @@ -903,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); @@ -945,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) @@ -1160,7 +1189,7 @@ float CL_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor) bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1); } -void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t sidefric, vec_t speedlimit) +void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t stretchfactor, vec_t sidefric, vec_t speedlimit) { vec_t vel_straight; vec_t vel_z; @@ -1169,10 +1198,16 @@ void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_ vec3_t vel_xy; vec_t vel_xy_current; vec_t vel_xy_backward, vel_xy_forward; - qboolean speedclamp; + vec_t speedclamp; - speedclamp = (accelqw < 0); - if(speedclamp) + if(stretchfactor > 0) + speedclamp = stretchfactor; + else if(accelqw < 0) + speedclamp = 1; + else + speedclamp = -1; // no clamping + + if(accelqw < 0) accelqw = -accelqw; if(cl.moveflags & MOVEFLAG_Q2AIRACCELERATE) @@ -1219,13 +1254,15 @@ void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_ VectorMA(vel_perpend, vel_straight, wishdir, s->velocity); - if(speedclamp) + if(speedclamp >= 0) { - vel_xy_current = min(VectorLength(s->velocity), vel_xy_forward); - if(vel_xy_current > 0) // prevent division by zero + vec_t vel_xy_preclamp; + vel_xy_preclamp = VectorLength(s->velocity); + if(vel_xy_preclamp > 0) // prevent division by zero { - VectorNormalize(s->velocity); - VectorScale(s->velocity, vel_xy_current, s->velocity); + vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp; + if(vel_xy_current < vel_xy_preclamp) + VectorScale(s->velocity, (vel_xy_current / vel_xy_preclamp), s->velocity); } } @@ -1303,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; @@ -1346,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); + 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; } @@ -1421,7 +1458,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s) if(cl.movevars_warsowbunny_turnaccel && accelerating && s->cmd.sidemove == 0 && s->cmd.forwardmove != 0) CL_ClientMovement_Physics_PM_AirAccelerate(s, wishdir, wishspeed2); else - CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed, cl.movevars_airspeedlimit_nonqw); + CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, cl.movevars_airaccel_qw_stretchfactor, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed, cl.movevars_airspeedlimit_nonqw); if(cl.movevars_aircontrol) CL_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2); @@ -1475,6 +1512,7 @@ void CL_UpdateMoveVars(void) cl.movevars_maxairspeed = cl.statsf[STAT_MOVEVARS_MAXAIRSPEED]; cl.movevars_stepheight = cl.statsf[STAT_MOVEVARS_STEPHEIGHT]; cl.movevars_airaccel_qw = cl.statsf[STAT_MOVEVARS_AIRACCEL_QW]; + cl.movevars_airaccel_qw_stretchfactor = cl.statsf[STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR]; cl.movevars_airaccel_sideways_friction = cl.statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION]; cl.movevars_friction = cl.statsf[STAT_MOVEVARS_FRICTION]; cl.movevars_wallfriction = cl.statsf[STAT_MOVEVARS_WALLFRICTION]; @@ -1514,6 +1552,7 @@ void CL_UpdateMoveVars(void) cl.movevars_maxairspeed = cl_movement_maxairspeed.value; cl.movevars_stepheight = cl_movement_stepheight.value; cl.movevars_airaccel_qw = cl_movement_airaccel_qw.value; + cl.movevars_airaccel_qw_stretchfactor = 0; cl.movevars_airaccel_sideways_friction = cl_movement_airaccel_sideways_friction.value; cl.movevars_airstopaccelerate = 0; cl.movevars_airstrafeaccelerate = 0; @@ -1549,6 +1588,9 @@ void CL_ClientMovement_Replay(void) if (cl.movement_predicted && !cl.movement_replay) return; + if (!cl_movement_replay.integer) + return; + // set up starting state for the series of moves memset(&s, 0, sizeof(s)); VectorCopy(cl.entities[cl.playerentity].state_current.origin, s.origin); @@ -1579,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) @@ -1589,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); @@ -1693,6 +1742,25 @@ void CL_NewFrameReceived(int num) cl.latestframenumsposition = (cl.latestframenumsposition + 1) % LATESTFRAMENUMS; } +void CL_RotateMoves(const matrix4x4_t *m) +{ + // rotate viewangles in all previous moves + vec3_t v; + vec3_t f, r, u; + int i; + for (i = 0;i < CL_MAX_USERCMDS;i++) + { + if (cl.movecmd[i].sequence > cls.servermovesequence) + { + usercmd_t *c = &cl.movecmd[i]; + AngleVectors(c->viewangles, f, r, u); + Matrix4x4_Transform(m, f, v); VectorCopy(v, f); + Matrix4x4_Transform(m, u, v); VectorCopy(v, u); + AnglesFromVectors(c->viewangles, f, u, false); + } + } +} + /* ============== CL_SendMove @@ -1910,9 +1978,17 @@ void CL_SendMove(void) // 5 bytes MSG_WriteByte (&buf, clc_move); MSG_WriteFloat (&buf, cl.cmd.time); // last server packet time - // 3 bytes - for (i = 0;i < 3;i++) - MSG_WriteAngle8i (&buf, cl.cmd.viewangles[i]); + // 3 bytes (6 bytes in proquake) + if (cls.proquake_servermod == 1) // MOD_PROQUAKE + { + for (i = 0;i < 3;i++) + MSG_WriteAngle16i (&buf, cl.cmd.viewangles[i]); + } + else + { + for (i = 0;i < 3;i++) + MSG_WriteAngle8i (&buf, cl.cmd.viewangles[i]); + } // 6 bytes MSG_WriteCoord16i (&buf, cl.cmd.forwardmove); MSG_WriteCoord16i (&buf, cl.cmd.sidemove); @@ -2168,6 +2244,7 @@ void CL_InitInput (void) Cvar_RegisterVariable(&cl_movecliptokeyboard); Cvar_RegisterVariable(&cl_movement); + Cvar_RegisterVariable(&cl_movement_replay); Cvar_RegisterVariable(&cl_movement_nettimeout); Cvar_RegisterVariable(&cl_movement_minping); Cvar_RegisterVariable(&cl_movement_track_canjump); @@ -2199,5 +2276,7 @@ void CL_InitInput (void) Cvar_RegisterVariable(&cl_netimmediatebuttons); Cvar_RegisterVariable(&cl_nodelta); + + Cvar_RegisterVariable(&cl_csqc_generatemousemoveevents); }