/* ================= CL_PredictMovement Sets cl.predicted_origin and cl.predicted_angles ================= */ void CL_PredictMovement( void ) { int frame = 1; int ack, outgoing_command; int current_command; int current_command_mod; cl_entity_t *player, *viewent; clientdata_t *cd; if( cls.state != ca_active ) return; if( cls.demoplayback && cl.refdef.cmd != NULL ) { // restore viewangles from cmd.angles VectorCopy( cl.refdef.cmd->viewangles, cl.refdef.cl_viewangles ); } if( cl.refdef.paused || cls.key_dest == key_menu ) return; player = CL_GetLocalPlayer (); viewent = CL_GetEntityByIndex( cl.refdef.viewentity ); cd = &cl.frame.local.client; // unpredicted pure angled values converted into axis AngleVectors( cl.refdef.cl_viewangles, cl.refdef.forward, cl.refdef.right, cl.refdef.up ); if( !CL_IsPredicted( )) { // run commands even if client predicting is disabled - client expected it clgame.pmove->runfuncs = true; CL_PostRunCmd( cl.refdef.cmd, cls.lastoutgoingcommand ); return; } ack = cls.netchan.incoming_acknowledged; outgoing_command = cls.netchan.outgoing_sequence; ASSERT( cl.refdef.cmd != NULL ); // setup initial pmove state CL_SetupPMove( clgame.pmove, cd, &player->curstate, cl.refdef.cmd ); clgame.pmove->runfuncs = false; while( 1 ) { // we've run too far forward if( frame >= CL_UPDATE_BACKUP - 1 ) break; // Incoming_acknowledged is the last usercmd the server acknowledged having acted upon current_command = ack + frame; current_command_mod = current_command & CL_UPDATE_MASK; // we've caught up to the current command. if( current_command >= outgoing_command ) break; clgame.pmove->cmd = cl.cmds[current_command_mod]; // motor! clgame.dllFuncs.pfnPlayerMove( clgame.pmove, false ); // run frames clgame.pmove->runfuncs = ( current_command > outgoing_command - 1 ) ? true : false; frame++; } CL_PostRunCmd( cl.refdef.cmd, frame ); // copy results out for rendering VectorCopy( clgame.pmove->view_ofs, cl.predicted_viewofs ); VectorCopy( clgame.pmove->origin, cl.predicted_origin ); VectorCopy( clgame.pmove->velocity, cl.predicted_velocity ); }
/* ================= CL_PredictMovement Sets cl.predicted_origin and cl.predicted_angles ================= */ void CL_PredictMovement() { int frame; int ack, outgoing_command; int current_command; int current_command_mod; cl_entity_t *player, *viewent; clientdata_t *cd; if( cls.state != ca_active ) return; if( cls.demoplayback && cl.refdef.cmd != NULL ) VectorCopy( cl.refdef.cmd->viewangles, cl.refdef.cl_viewangles ); // restore viewangles from cmd.angles if(cl.refdef.paused /*|| cls.key_dest == key_menu*/) //return; player = CL_GetLocalPlayer (); viewent = CL_GetEntityByIndex( cl.refdef.viewentity ); cd = &cl.frame.local.client; // unpredicted pure angled values converted into axis AngleVectors( cl.refdef.cl_viewangles, cl.refdef.forward, cl.refdef.right, cl.refdef.up ); if( !CL_IsPredicted( )) { // run commands even if client predicting is disabled - client expect it clgame.pmove->runfuncs = true; CL_PostRunCmd( cl.refdef.cmd, cls.lastoutgoingcommand ); return; }; ack = cls.netchan.incoming_acknowledged; outgoing_command = cls.netchan.outgoing_sequence; // if we are too far out of date, just freeze if(outgoing_command - ack >= CL_UPDATE_BACKUP) { //if(cl_showmiss->value) //Com_Printf ("exceeded CL_UPDATE_BACKUP\n"); return; }; ASSERT( cl.refdef.cmd != NULL ); // setup initial pmove state CL_SetupPMove( clgame.pmove, cd, &player->curstate, cl.refdef.cmd ); clgame.pmove->runfuncs = false; frame = 0; while(++ack < outgoing_command) { // we've run too far forward //if( frame >= CL_UPDATE_BACKUP - 1 ) // break; frame = ack & (CL_UPDATE_BACKUP - 1); // Incoming_acknowledged is the last usercmd the server acknowledged having acted upon current_command = ack + frame; current_command_mod = current_command & CL_UPDATE_MASK; // we've caught up to the current command // this was the most up to date command if(current_command >= outgoing_command) break; clgame.pmove->cmd = cl.cmds[current_command_mod]; // Call the client dll player movement function (and it will call the PM_Move()) clgame.dllFuncs.pfnPlayerMove(clgame.pmove, false); // run frames clgame.pmove->runfuncs = ( current_command > outgoing_command - 1 ) ? true : false; // Prevent to play sounds/etc more that once frame++; }; CL_PostRunCmd( cl.refdef.cmd, cls.lastoutgoingcommand ); // copy results out for rendering VectorCopy( clgame.pmove->view_ofs, cl.predicted_viewofs ); VectorCopy( clgame.pmove->origin, cl.predicted_origin ); VectorCopy( clgame.pmove->velocity, cl.predicted_velocity ); };