X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=cl_input.c;h=8fe0d4cbeffc5dd513a1ae86c855836b135339f1;hb=fc7a6cd8936ce095824fbe9aeca99331322a8f6a;hp=804a40438e4431e53e1add038ef285315dd42d3e;hpb=53733530ea84c8bf61961462dd8d67c497e6459c;p=xonotic%2Fdarkplaces.git diff --git a/cl_input.c b/cl_input.c index 804a4043..8fe0d4cb 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"}; @@ -587,14 +588,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; } @@ -622,17 +616,10 @@ void CL_Input (void) } // if not in menu, apply mouse move to viewangles/movement - if (!key_consoleactive && key_dest == key_game && !cl.csqc_wantsmousemove) + if (!key_consoleactive && key_dest == key_game && !cl.csqc_wantsmousemove && cl_prydoncursor.integer <= 0) { float modulatedsensitivity = sensitivity.value * cl.sensitivityscale; - if (cl_prydoncursor.integer > 0) - { - // mouse interacting with the scene, mostly stationary view - V_StopPitchDrift(); - cl.cmd.cursor_screen[0] += in_mouse_x * modulatedsensitivity / vid.width; - cl.cmd.cursor_screen[1] += in_mouse_y * modulatedsensitivity / vid.height; - } - else if (in_strafe.state & 1) + if (in_strafe.state & 1) { // strafing mode, all looking is movement V_StopPitchDrift(); @@ -660,7 +647,13 @@ void CL_Input (void) } } else // don't pitch drift when csqc is controlling the mouse + { + // mouse interacting with the scene, mostly stationary view V_StopPitchDrift(); + // update prydon cursor + cl.cmd.cursor_screen[0] = in_windowmouse_x * 2.0 / vid.width - 1.0; + cl.cmd.cursor_screen[1] = in_windowmouse_y * 2.0 / vid.height - 1.0; + } if(v_flipped.integer) { @@ -1075,7 +1068,7 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s) s->velocity[2] = 80; else { - if (gamemode == GAME_NEXUIZ) + if (gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC) s->velocity[2] = 200; else s->velocity[2] = 100; @@ -1142,7 +1135,9 @@ void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, v dot = DotProduct(s->velocity, wishdir); if(dot > 0) { // we can't change direction while slowing down - k *= cl.movevars_aircontrol*pow(dot, cl.movevars_aircontrol_power)*s->cmd.frametime; + k *= pow(dot, cl.movevars_aircontrol_power)*s->cmd.frametime; + speed = max(0, speed - cl.movevars_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32); + k *= cl.movevars_aircontrol; VectorMAM(speed, s->velocity, k, wishdir, s->velocity); VectorNormalize(s->velocity); } @@ -1151,7 +1146,15 @@ void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, v s->velocity[2] = zspeed; } -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) +float CL_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor) +{ + return + (accelqw < 0 ? -1 : +1) + * + 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 stretchfactor, vec_t sidefric, vec_t speedlimit) { vec_t vel_straight; vec_t vel_z; @@ -1160,10 +1163,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) @@ -1177,6 +1186,8 @@ void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_ step = accel * s->cmd.frametime * wishspeed0; vel_xy_current = VectorLength(vel_xy); + if(speedlimit > 0) + accelqw = CL_ClientMovement_Physics_AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed)); vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw); vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw); if(vel_xy_backward < 0) @@ -1208,13 +1219,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); } } @@ -1337,7 +1350,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s) 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); 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, false, false); if (trace.fraction == 1 && !trace.startsolid) friction *= cl.movevars_edgefriction; } @@ -1387,8 +1400,14 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s) // CPM: air control if(cl.movevars_airstopaccelerate != 0) - if(DotProduct(s->velocity, wishdir) < 0) - accel = cl.movevars_airstopaccelerate; + { + vec3_t curdir; + curdir[0] = s->velocity[0]; + curdir[1] = s->velocity[1]; + curdir[2] = 0; + VectorNormalize(curdir); + accel = accel + (cl.movevars_airstopaccelerate - accel) * max(0, -DotProduct(curdir, wishdir)); + } strafity = CL_IsMoveInDirection(s->cmd.forwardmove, s->cmd.sidemove, -90) + CL_IsMoveInDirection(s->cmd.forwardmove, s->cmd.sidemove, +90); // if one is nonzero, other is always zero if(cl.movevars_maxairstrafespeed) wishspeed = min(wishspeed, CL_GeomLerp(cl.movevars_maxairspeed, strafity, cl.movevars_maxairstrafespeed)); @@ -1404,7 +1423,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_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); @@ -1458,6 +1477,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]; @@ -1468,11 +1488,13 @@ void CL_UpdateMoveVars(void) cl.movevars_airstrafeaccel_qw = cl.statsf[STAT_MOVEVARS_AIRSTRAFEACCEL_QW]; cl.movevars_aircontrol = cl.statsf[STAT_MOVEVARS_AIRCONTROL]; cl.movevars_aircontrol_power = cl.statsf[STAT_MOVEVARS_AIRCONTROL_POWER]; + cl.movevars_aircontrol_penalty = cl.statsf[STAT_MOVEVARS_AIRCONTROL_PENALTY]; cl.movevars_warsowbunny_airforwardaccel = cl.statsf[STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL]; cl.movevars_warsowbunny_accel = cl.statsf[STAT_MOVEVARS_WARSOWBUNNY_ACCEL]; cl.movevars_warsowbunny_topspeed = cl.statsf[STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED]; cl.movevars_warsowbunny_turnaccel = cl.statsf[STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL]; cl.movevars_warsowbunny_backtosideratio = cl.statsf[STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO]; + cl.movevars_airspeedlimit_nonqw = cl.statsf[STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW]; } else { @@ -1495,6 +1517,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; @@ -1502,11 +1525,13 @@ void CL_UpdateMoveVars(void) cl.movevars_airstrafeaccel_qw = 0; cl.movevars_aircontrol = 0; cl.movevars_aircontrol_power = 2; + cl.movevars_aircontrol_penalty = 0; cl.movevars_warsowbunny_airforwardaccel = 0; cl.movevars_warsowbunny_accel = 0; cl.movevars_warsowbunny_topspeed = 0; cl.movevars_warsowbunny_turnaccel = 0; cl.movevars_warsowbunny_backtosideratio = 0; + cl.movevars_airspeedlimit_nonqw = 0; } if(!(cl.moveflags & MOVEFLAG_VALID)) @@ -1516,7 +1541,7 @@ void CL_UpdateMoveVars(void) } if(cl.movevars_aircontrol_power <= 0) - cl.movevars_aircontrol = 2; // CPMA default + cl.movevars_aircontrol_power = 2; // CPMA default } void CL_ClientMovement_Replay(void) @@ -1528,6 +1553,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); @@ -1672,6 +1700,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 @@ -1729,10 +1776,13 @@ void CL_SendMove(void) if (in_button16.state & 3) bits |= 262144; // button bits 19-31 unused currently // rotate/zoom view serverside if PRYDON_CLIENTCURSOR cursor is at edge of screen - if (cl.cmd.cursor_screen[0] <= -1) bits |= 8; - if (cl.cmd.cursor_screen[0] >= 1) bits |= 16; - if (cl.cmd.cursor_screen[1] <= -1) bits |= 32; - if (cl.cmd.cursor_screen[1] >= 1) bits |= 64; + if(cl_prydoncursor.integer > 0) + { + if (cl.cmd.cursor_screen[0] <= -1) bits |= 8; + if (cl.cmd.cursor_screen[0] >= 1) bits |= 16; + if (cl.cmd.cursor_screen[1] <= -1) bits |= 32; + if (cl.cmd.cursor_screen[1] >= 1) bits |= 64; + } // set buttons and impulse cl.cmd.buttons = bits; @@ -1774,7 +1824,7 @@ void CL_SendMove(void) break; case PROTOCOL_DARKPLACES6: case PROTOCOL_DARKPLACES7: - // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz specific + // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz/Xonotic specific cl.cmd.crouch = (cl.cmd.buttons & 16) != 0; break; case PROTOCOL_UNKNOWN: @@ -1886,9 +1936,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); @@ -2144,6 +2202,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);