diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 63707758f..4d12e50ee 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -911,34 +911,24 @@ CL_BaseMove Send the intended movement message to the server ================ */ -void CL_BaseMove (usercmd_t *cmd, int pnum, float priortime, float extratime) +static void CL_BaseMove (vec3_t moves, int pnum) { - float nscale = extratime?extratime / (extratime+priortime):0; - float oscale = 1 - nscale; - - cmd->fservertime = cl.time; - cmd->servertime = cl.time*1000; - + float scale; // // adjust for speed key // - if ((in_speed.state[pnum] & 1) ^ cl_run.ival) - nscale *= cl_movespeedkey.value; - - if (in_strafe.state[pnum] & 1) - cmd->sidemove = cmd->sidemove*oscale + nscale*cl_sidespeed.value * (CL_KeyState (&in_right, pnum, true) - CL_KeyState (&in_left, pnum, true)) * (in_xflip.ival?-1:1); - cmd->sidemove = cmd->sidemove*oscale + nscale*cl_sidespeed.value * (CL_KeyState (&in_moveright, pnum, true) - CL_KeyState (&in_moveleft, pnum, true)) * (in_xflip.ival?-1:1); - - cmd->upmove = cmd->upmove*oscale + nscale*cl_upspeed.value * (CL_KeyState (&in_up, pnum, true) - CL_KeyState (&in_down, pnum, true)); + scale = ((in_speed.state[pnum] & 1) ^ cl_run.ival)?cl_movespeedkey.value:1; + moves[0] = 0; if (! (in_klook.state[pnum] & 1) ) - { - cmd->forwardmove = cmd->forwardmove*oscale + nscale*(cl_forwardspeed.value * CL_KeyState (&in_forward, pnum, true) - - (*cl_backspeed.string?cl_backspeed.value:cl_forwardspeed.value) * CL_KeyState (&in_back, pnum, true)); + { + moves[0] += scale*(cl_forwardspeed.value * CL_KeyState (&in_forward, pnum, true) - + (*cl_backspeed.string?cl_backspeed.value:cl_forwardspeed.value) * CL_KeyState (&in_back, pnum, true)); } - - if (!priortime) //only gather buttons if we've not had any this frame. this avoids jump feeling weird with prediction. FIXME: should probably still allow +attack to reduce latency - CL_GatherButtons(cmd, pnum); + moves[1] = scale*cl_sidespeed.value * (CL_KeyState (&in_moveright, pnum, true) - CL_KeyState (&in_moveleft, pnum, true)) * (in_xflip.ival?-1:1); + if (in_strafe.state[pnum] & 1) + moves[1] += scale*cl_sidespeed.value * (CL_KeyState (&in_right, pnum, true) - CL_KeyState (&in_left, pnum, true)) * (in_xflip.ival?-1:1); + moves[2] = scale*cl_upspeed.value * (CL_KeyState (&in_up, pnum, true) - CL_KeyState (&in_down, pnum, true)); } void CL_ClampPitch (int pnum, float frametime) @@ -1215,6 +1205,53 @@ static void CL_FinishMove (usercmd_t *cmd, int pnum) } +static void CL_AccumlateInput(int plnum, float frametime/*extra contribution*/, float framemsecs/*total accumulated*/) +{ + usercmd_t *cmd = &cl_pendingcmd[plnum]; + int i; + static vec3_t mousemovements[MAX_SPLITS]; + vec3_t newmoves; + + float nscale = framemsecs?framemsecs / (framemsecs+cmd->msec):0; + float oscale = 1 - nscale; + + CL_BaseMove (newmoves, plnum); + + CL_AdjustAngles (plnum, frametime); + if (!cmd->msec) + VectorClear(mousemovements[plnum]); + IN_Move (mousemovements[plnum], newmoves, plnum, frametime); + CL_ClampPitch(plnum, frametime); + + for (i=0 ; i<3 ; i++) + cmd->angles[i] = ((int)(cl.playerview[plnum].viewangles[i]*65536.0/360)&65535); + + cmd->fservertime = cl.servertime; + cmd->servertime = cl.time*1000; +#ifdef CSQC_DAT + cmd->fclienttime = realtime - cl.mapstarttime; +#endif + + cmd->forwardmove = bound(-32768, cmd->forwardmove*oscale + newmoves[0]*nscale + mousemovements[plnum][0], 32767); + cmd->sidemove = bound(-32768, cmd->sidemove*oscale + newmoves[1]*nscale + mousemovements[plnum][1], 32767); + cmd->upmove = bound(-32768, cmd->upmove*oscale + newmoves[2]*nscale + mousemovements[plnum][2], 32767); + + if (!cmd->msec && framemsecs) + { + CL_GatherButtons(cmd, plnum); //buttons are from the initial state. don't blend them. + + CL_FinishMove(cmd, plnum); + Cbuf_Waited(); //its okay to stop waiting now + } + cmd->msec = framemsecs; + + // if we are spectator, try autocam +// if (cl.spectator) + Cam_Track(&cl.playerview[plnum], &cl_pendingcmd[plnum]); + Cam_FinishMove(&cl.playerview[plnum], &cl_pendingcmd[plnum]); +} + + static qboolean CLFTE_SendVRCmd (sizebuf_t *buf, unsigned int seats) { //compute the delay between receiving the frame we're acking and when we're sending the new frame @@ -2220,39 +2257,12 @@ void CL_SendCmd (double frametime, qboolean mainloop) } for (plnum = 0; plnum < cl.splitclients; plnum++) { - vec3_t mousemovements; playerview_t *pv = &cl.playerview[plnum]; cmd = &cl.outframes[i].cmd[plnum]; - memset(cmd, 0, sizeof(*cmd)); - msecs += frametime*1000; - if (msecs > 50) - msecs = 50; - cmd->msec = msecs; - msecs -= cmd->msec; - cl_pendingcmd[plnum].msec = 0; - - CL_AdjustAngles (plnum, frametime); - // get basic movement from keyboard - CL_BaseMove (cmd, plnum, 0, 1); - - // allow mice or other external controllers to add to the move - VectorClear(mousemovements); - IN_Move (mousemovements, plnum, frametime); - cl_pendingcmd[plnum].forwardmove += mousemovements[0]; - cl_pendingcmd[plnum].sidemove += mousemovements[1]; - cl_pendingcmd[plnum].upmove += mousemovements[2]; - CL_ClampPitch(plnum, frametime); - - // if we are spectator, try autocam - if (pv->spectator) - Cam_Track(pv, cmd); - - CL_FinishMove(cmd, plnum); - - VectorCopy(pv->aimangles, pv->simangles); - - Cam_FinishMove(pv, cmd); + CL_AccumlateInput(plnum, frametime, frametime*1000); + *cmd = cl_pendingcmd[plnum]; + memset(&cl_pendingcmd[plnum], 0, sizeof(*cmd)); //reset the pending for the next frame. #ifdef CSQC_DAT CSQC_Input_Frame(plnum, cmd); @@ -2279,7 +2289,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) cls.netchan.outgoing_sequence = cl.movesequence; } - IN_Move (NULL, 0, frametime); + IN_Move (NULL, NULL, 0, frametime); Cbuf_Waited(); //its okay to stop waiting now return; // sendcmds come from the demo @@ -2392,32 +2402,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) if (!CLHL_BuildUserInput(msecstouse, &cl_pendingcmd[0])) #endif for (plnum = 0; plnum < (cl.splitclients?cl.splitclients:1); plnum++) - { - vec3_t mousemovements; - CL_AdjustAngles (plnum, frametime); - VectorClear(mousemovements); - IN_Move (mousemovements, plnum, frametime); - CL_ClampPitch(plnum, frametime); - cl_pendingcmd[plnum].forwardmove += mousemovements[0]; //FIXME: this will get nuked by CL_BaseMove. - cl_pendingcmd[plnum].sidemove += mousemovements[1]; - cl_pendingcmd[plnum].upmove += mousemovements[2]; - - for (i=0 ; i<3 ; i++) - cl_pendingcmd[plnum].angles[i] = ((int)(cl.playerview[plnum].viewangles[i]*65536.0/360)&65535); - - CL_BaseMove (&cl_pendingcmd[plnum], plnum, cl_pendingcmd[plnum].msec, framemsecs); - if (!cl_pendingcmd[plnum].msec && framemsecs) - { - CL_FinishMove(&cl_pendingcmd[plnum], plnum); - Cbuf_Waited(); //its okay to stop waiting now - } - cl_pendingcmd[plnum].msec = framemsecs; - - // if we are spectator, try autocam - // if (cl.spectator) - Cam_Track(&cl.playerview[plnum], &cl_pendingcmd[plnum]); - Cam_FinishMove(&cl.playerview[plnum], &cl_pendingcmd[plnum]); - } + CL_AccumlateInput(plnum, frametime, framemsecs); //the main loop isn't allowed to send if (runningindepphys && mainloop) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 0556e7ce5..edc99a018 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -2009,6 +2009,7 @@ void CL_ClearState (qboolean gamestart) CL_ResetFog(FOGTYPE_WATER); CL_ResetFog(FOGTYPE_SKYROOM); + cl.mapstarttime = realtime; cl.gamespeed = 1; cl.protocol_qw = PROTOCOL_VERSION_QW; //until we get an svc_serverdata cl.allocated_client_slots = QWMAX_CLIENTS; diff --git a/engine/client/client.h b/engine/client/client.h index 17235787b..f48bd9c65 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -857,6 +857,7 @@ typedef struct // is rendering at. always <= realtime double lasttime; //cl.time from last frame. double lastlinktime; //cl.time from last frame. + double mapstarttime; //for computing csqc's cltime. float servertime; //current server time, bound between gametime and gametimemark float mtime; //server time as on the server when we last received a packet. not allowed to decrease. @@ -1265,7 +1266,6 @@ void CL_ReadPacket(void); int CL_ReadFromServer (void); void CL_WriteToServer (usercmd_t *cmd); -void CL_BaseMove (usercmd_t *cmd, int pnum, float priortime, float extratime); int Master_FindBestRoute(char *server, char *out, size_t outsize, int *directcost, int *chainedcost); diff --git a/engine/client/in_generic.c b/engine/client/in_generic.c index 72b5e4cdc..f42904d3e 100644 --- a/engine/client/in_generic.c +++ b/engine/client/in_generic.c @@ -1006,14 +1006,14 @@ void IN_MoveJoystick(struct joy_s *joy, float *movements, int pnum, float framet movements[2] += joy_movesens[2].value * mag*cl_upspeed.value * jstrafe[2]; } -void IN_Move (float *movements, int pnum, float frametime) +void IN_Move (float *nudgemovements, float *absmovements, int pnum, float frametime) { int i; for (i = 0; i < MAXPOINTERS; i++) - IN_MoveMouse(&ptr[i], movements, pnum, frametime); + IN_MoveMouse(&ptr[i], nudgemovements, pnum, frametime); for (i = 0; i < MAXJOYSTICKS; i++) - IN_MoveJoystick(&joy[i], movements, pnum, frametime); + IN_MoveJoystick(&joy[i], absmovements, pnum, frametime); } void IN_JoystickAxisEvent(unsigned int devid, int axis, float value) diff --git a/engine/client/input.h b/engine/client/input.h index b5e7542d2..e29920ed5 100644 --- a/engine/client/input.h +++ b/engine/client/input.h @@ -32,7 +32,7 @@ void IN_Commands (void); qboolean IN_MouseDevIsTouch(unsigned int devid); //check if a mouse devid is a touch screen, and thus if we should check the cursor and simulate a ui event or not int IN_TranslateMButtonPress(unsigned int devid); //allow the touchscreen code to swallow mouse1 as a begin-looking event -void IN_Move (float *movements, int pnum, float frametime); +void IN_Move (float *nudgemovements, float *absmovements, int pnum, float frametime); // add additional movement on top of the keyboard move cmd extern cvar_t in_xflip; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index dd82aaefe..3da6c54d4 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -59,8 +59,6 @@ static csqctreadstate_t *csqcthreads; qboolean csqc_resortfrags; world_t csqc_world; -float csqc_starttime; //reset on each csqc reload to restore lost precision of cltime on each map restart. - int csqc_playerseat; //can be negative. static playerview_t *csqc_playerview; qboolean csqc_dp_lastwas3d; //to emulate DP correctly, we need to track whether drawpic/drawfill or clearscene was called last. blame 515. @@ -311,7 +309,7 @@ static void CSQC_FindGlobals(qboolean nofuncs) if (csqcg.time) *csqcg.time = cl.servertime; if (csqcg.cltime) - *csqcg.cltime = realtime-csqc_starttime; + *csqcg.cltime = realtime-cl.mapstarttime; if (!csqcg.global_gravitydir) csqcg.global_gravitydir = defaultgravity; @@ -8257,7 +8255,7 @@ qboolean CSQC_Init (qboolean anycsqc, const char *csprogsname, unsigned int chec int csaddonnum = -1; in_sensitivityscale = 1; csqcmapentitydataloaded = true; - csqc_starttime = realtime; + cl.mapstarttime = realtime; csqcprogs = InitProgs(&csqcprogparms); csqc_world.progs = csqcprogs; csqc_world.usesolidcorpse = true; @@ -8904,7 +8902,7 @@ qboolean CSQC_DrawView(void) CL_PredictMove (); if (csqcg.cltime) - *csqcg.cltime = realtime-csqc_starttime; + *csqcg.cltime = realtime-cl.mapstarttime; if (csqcg.time) *csqcg.time = cl.servertime; if (csqcg.clientcommandframe) @@ -8993,7 +8991,7 @@ qboolean CSQC_DrawHud(playerview_t *pv) if (csqcg.frametime) *csqcg.frametime = host_frametime; if (csqcg.cltime) - *csqcg.cltime = realtime-csqc_starttime; + *csqcg.cltime = realtime-cl.mapstarttime; G_FLOAT(OFS_PARM0+0) = r_refdef.grect.width; G_FLOAT(OFS_PARM0+1) = r_refdef.grect.height; @@ -9037,7 +9035,7 @@ qboolean CSQC_DrawScores(playerview_t *pv) if (csqcg.frametime) *csqcg.frametime = host_frametime; if (csqcg.cltime) - *csqcg.cltime = realtime-csqc_starttime; + *csqcg.cltime = realtime-cl.mapstarttime; G_FLOAT(OFS_PARM0+0) = r_refdef.grect.width; G_FLOAT(OFS_PARM0+1) = r_refdef.grect.height; @@ -9493,7 +9491,7 @@ void CSQC_Input_Frame(int seat, usercmd_t *cmd) if (csqcg.time) *csqcg.time = cl.servertime; if (csqcg.cltime) - *csqcg.cltime = realtime-csqc_starttime; + *csqcg.cltime = realtime-cl.mapstarttime; if (csqcg.clientcommandframe) *csqcg.clientcommandframe = cl.movesequence; @@ -9607,7 +9605,7 @@ void CSQC_ParseEntities(qboolean sized) if (csqcg.time) //estimated server time *csqcg.time = cl.servertime; if (csqcg.cltime) //smooth client time. - *csqcg.cltime = realtime-csqc_starttime; + *csqcg.cltime = realtime-cl.mapstarttime; if (csqcg.servertime) *csqcg.servertime = cl.gametime; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index d2b4a88f1..ec2e03b97 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -1284,8 +1284,8 @@ typedef struct usercmd_s unsigned int buttons; //replaces buttons, but with more bits. unsigned int weapon;//q3 has a separate weapon field to supplement impulse. unsigned int servertime; //q3 networks the time in order to calculate msecs - float fservertime;//used as part of nq msec calcs - float fclienttime;//not used? + double fservertime;//used as part of nq msec calcs + double fclienttime;//not used? //prydon cursor crap vec2_t cursor_screen;