示例#1
0
/*
==============
CL_PredictMove
==============
*/
void
CL_PredictMove(void)
{
    int i;
    float f;
    frame_t *from, *to = NULL;
    int oldphysent;

    if (cl_pushlatency.value > 0)
	Cvar_Set("pushlatency", "0");

    if (cl.paused)
	return;

    cl.time = realtime - cls.latency - cl_pushlatency.value * 0.001;
    if (cl.time > realtime)
	cl.time = realtime;

    if (cl.intermission)
	return;

    if (!cl.validsequence)
	return;

    if (cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence >=
	UPDATE_BACKUP - 1)
	return;

    VectorCopy(cl.viewangles, cl.simangles);

    // this is the last frame received from the server
    from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];

    // we can now render a frame
    if (cls.state == ca_onserver) {	// first update is the final signon stage
	char text[1024];

	cls.state = ca_active;
	sprintf(text, "QuakeWorld: %s", cls.servername);
#ifdef _WIN32
	SetWindowText(mainwindow, text);
#endif
    }

    if (cl_nopred.value) {
	VectorCopy(from->playerstate[cl.playernum].velocity, cl.simvel);
	VectorCopy(from->playerstate[cl.playernum].origin, cl.simorg);
	return;
    }
    // predict forward until cl.time <= to->senttime
    oldphysent = pmove.numphysent;
    CL_SetSolidPlayers(cl.playernum);

//      to = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];

    for (i = 1; i < UPDATE_BACKUP - 1 && cls.netchan.incoming_sequence + i <
	 cls.netchan.outgoing_sequence; i++) {
	to = &cl.frames[(cls.netchan.incoming_sequence + i) & UPDATE_MASK];
	CL_PredictUsercmd(&from->playerstate[cl.playernum]
			  , &to->playerstate[cl.playernum], &to->cmd,
			  cl.spectator);
	if (to->senttime >= cl.time)
	    break;
	from = to;
    }

    pmove.numphysent = oldphysent;

    if (i == UPDATE_BACKUP - 1 || !to)
	return;			// net hasn't deliver packets in a long time...

    // now interpolate some fraction of the final frame
    if (to->senttime == from->senttime)
	f = 0;
    else {
	f = (cl.time - from->senttime) / (to->senttime - from->senttime);

	if (f < 0)
	    f = 0;
	if (f > 1)
	    f = 1;
    }

    for (i = 0; i < 3; i++)
	if (fabs(from->playerstate[cl.playernum].origin[i] - to->playerstate[cl.playernum].origin[i]) > 128) {	// teleported, so don't lerp
	    VectorCopy(to->playerstate[cl.playernum].velocity, cl.simvel);
	    VectorCopy(to->playerstate[cl.playernum].origin, cl.simorg);
	    return;
	}

    for (i = 0; i < 3; i++) {
	cl.simorg[i] = from->playerstate[cl.playernum].origin[i]
	    + f * (to->playerstate[cl.playernum].origin[i] -
		   from->playerstate[cl.playernum].origin[i]);
	cl.simvel[i] = from->playerstate[cl.playernum].velocity[i]
	    + f * (to->playerstate[cl.playernum].velocity[i] -
		   from->playerstate[cl.playernum].velocity[i]);
    }
}
示例#2
0
文件: cl_main.c 项目: Reedych/xash3d
/*
=================
CL_CreateCmd
=================
*/
void CL_CreateCmd( void )
{
	usercmd_t		cmd = { 0 };
	color24		color;
	vec3_t		angles;
	qboolean		active;
	int		ms;

	ms = host.frametime * 1000;
	if( ms > 250 ) ms = 100;	// time was unreasonable
	else if( ms <= 0 ) ms = 1; // keep time an actual

	// build list of all solid entities per next frame (exclude clients)
	CL_SetSolidEntities ();
	CL_SetSolidPlayers ( cl.playernum );
	VectorCopy( cl.refdef.cl_viewangles, angles );
	VectorCopy( cl.frame.local.client.origin, cl.data.origin );
	VectorCopy( cl.refdef.cl_viewangles, cl.data.viewangles );

	cl.data.iWeaponBits = cl.frame.local.client.weapons;

	if( cl.scr_fov < 1.0f || cl.scr_fov> 170.0f )
		cl.scr_fov = 90.0f;

	cl.data.fov = cl.scr_fov;

	clgame.dllFuncs.pfnUpdateClientData( &cl.data, cl.time );

	// grab changes
	VectorCopy( cl.data.viewangles, cl.refdef.cl_viewangles );
	cl.frame.local.client.weapons = cl.data.iWeaponBits;
	cl.scr_fov = cl.data.fov;
	if( cl.scr_fov < 1.0f || cl.scr_fov> 170.0f )
		cl.scr_fov = 90.0f;
	// allways dump the first ten messages,
	// because it may contain leftover inputs
	// from the last level
	if( ++cl.movemessages <= 10 )
	{
		if( !cls.demoplayback )
		{
			cl.refdef.cmd = &cl.cmds[cls.netchan.outgoing_sequence & CL_UPDATE_MASK];
			*cl.refdef.cmd = cmd;
		}
		return;
	}

	active = ( cls.state == ca_active && !cl.refdef.paused && !cls.demoplayback );
	clgame.dllFuncs.CL_CreateMove( cl.time - cl.oldtime, &cmd, active );

	// after command generated in client,
	// add motion events from engine controls
	IN_EngineAppendMove( host.frametime, &cmd, active);

	R_LightForPoint( cl.frame.local.client.origin, &color, false, false, 128.0f );
	cmd.lightlevel = (color.r + color.g + color.b) / 3;

	// never let client.dll calc frametime for player
	// because is potential backdoor for cheating
	cmd.msec = ms;
	cmd.lerp_msec = cl_interp->value * 1000;
	cmd.lerp_msec = bound( 0, cmd.lerp_msec, 250 ); 

	V_ProcessOverviewCmds( &cmd );
	V_ProcessShowTexturesCmds( &cmd );

	if(( cl.background && !cls.demoplayback ) || gl_overview->integer || cls.changelevel )
	{
		VectorCopy( angles, cl.refdef.cl_viewangles );
		VectorCopy( angles, cmd.viewangles );
		cmd.msec = 0;
	}

	// demo always have commands
	// so don't overwrite them
	if( !cls.demoplayback )
	{
		int frame = cls.netchan.outgoing_sequence & CL_UPDATE_MASK;

		cl.refdef.cmd = &cl.cmds[frame];
		*cl.refdef.cmd = cmd;

		cl.runfuncs[frame] = TRUE;
	}
}
示例#3
0
文件: cl_ents.c 项目: jrk/QuakeTM
/*
=============
CL_LinkPlayers

Create visible entities in the correct position
for all current players
=============
*/
void CL_LinkPlayers (void)
{
	int				j;
	player_info_t	*info;
	player_state_t	*state;
	player_state_t	exact;
	double			playertime;
	entity_t		*ent;
	int				msec;
	frame_t			*frame;
	int				oldphysent;

	playertime = realtime - cls.latency + 0.02;
	if (playertime > realtime)
		playertime = realtime;

	frame = &cl.frames[cl.parsecount&UPDATE_MASK];

	for (j=0, info=cl.players, state=frame->playerstate ; j < MAX_CLIENTS 
		; j++, info++, state++)
	{
		if (state->messagenum != cl.parsecount)
			continue;	// not present this frame

		// spawn light flashes, even ones coming from invisible objects
// #ifdef GLQUAKE
// 		if (!gl_flashblend.value || j != cl.playernum) {
// #endif
			if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED))
				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 3);
			else if (state->effects & EF_BLUE)
				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 1);
			else if (state->effects & EF_RED)
				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 2);
			else if (state->effects & EF_BRIGHTLIGHT)
				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (rand()&31), 0.1, 0);
			else if (state->effects & EF_DIMLIGHT)
				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 0);
// #ifdef GLQUAKE
// 		}
// #endif

		// the player object never gets added
		if (j == cl.playernum)
			continue;

		if (!state->modelindex)
			continue;

		if (!Cam_DrawPlayer(j))
			continue;

		// grab an entity to fill in
		if (cl_numvisedicts == MAX_VISEDICTS)
			break;		// object list is full
		ent = &cl_visedicts[cl_numvisedicts];
		cl_numvisedicts++;
		ent->keynum = 0;

		ent->model = cl.model_precache[state->modelindex];
		ent->skinnum = state->skinnum;
		ent->frame = state->frame;
		ent->colormap = info->translations;
		if (state->modelindex == cl_playerindex)
			ent->scoreboard = info;		// use custom skin
		else
			ent->scoreboard = NULL;

		//
		// angles
		//
		ent->angles[PITCH] = -state->viewangles[PITCH]/3;
		ent->angles[YAW] = state->viewangles[YAW];
		ent->angles[ROLL] = 0;
		ent->angles[ROLL] = V_CalcRoll (ent->angles, state->velocity)*4;

		// only predict half the move to minimize overruns
		msec = 500*(playertime - state->state_time);
		if (msec <= 0 || (!cl_predict_players.value && !cl_predict_players2.value))
		{
			VectorCopy (state->origin, ent->origin);
//Con_DPrintf ("nopredict\n");
		}
		else
		{
			// predict players movement
			if (msec > 255)
				msec = 255;
			state->command.msec = msec;
//Con_DPrintf ("predict: %i\n", msec);

			oldphysent = pmove.numphysent;
			CL_SetSolidPlayers (j);
			CL_PredictUsercmd (state, &exact, &state->command, false);
			pmove.numphysent = oldphysent;
			VectorCopy (exact.origin, ent->origin);
		}

		if (state->effects & EF_FLAG1)
			CL_AddFlagModels (ent, 0);
		else if (state->effects & EF_FLAG2)
			CL_AddFlagModels (ent, 1);

	}
}
示例#4
0
文件: cl_pmove.c 项目: fuzun/xash3d
/*
=================
CL_PredictMovement

Sets cl.predicted_origin and cl.predicted_angles
=================
*/
void CL_PredictMovement( void )
{
    double	time;
    int		frame = 1;
    int		ack, outgoing_command;
    int		current_command;
    int		current_command_mod;
    local_state_t *from = 0, *to = 0;

    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;

    pfnSetUpPlayerPrediction( false, false );

    // unpredicted pure angled values converted into axis
    AngleVectors( cl.refdef.cl_viewangles, cl.refdef.forward, cl.refdef.right, cl.refdef.up );

    ASSERT( cl.refdef.cmd != NULL );
    if( !cl_predict->integer || Host_IsLocalClient() )
    {
        // fake prediction code
        // we need to perform cl_lw prediction while cl_predict is disabled
        // because cl_lw is enabled by default in Half-Life
        if( !cl_lw->integer )
            return;

        ack = cls.netchan.incoming_acknowledged;
        outgoing_command = cls.netchan.outgoing_sequence;

        from = &cl.predict[cl.parsecountmod];
        from->playerstate = cl.frame.playerstate[cl.playernum];
        from->client = cl.frame.local.client;
        Q_memcpy( from->weapondata, cl.frame.local.weapondata, sizeof( from->weapondata ));

        time = cl.frame.time;

        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;

            to = &cl.predict[( cl.parsecountmod + frame ) & CL_UPDATE_MASK];

            CL_FakeUsercmd( from, to, &cl.cmds[current_command_mod],
                            cl.runfuncs[current_command_mod],
                            &time, cls.netchan.incoming_acknowledged + frame );

            cl.runfuncs[current_command_mod] = false;

            from = to;
            frame++;
        }

        if( to )
        {
            cl.predicted_viewmodel = to->client.viewmodel;
            cl.scr_fov = to->client.fov;
            if( cl.scr_fov < 1.0f || cl.scr_fov> 170.0f )
                cl.scr_fov = 90.0f;
        }
        return;
    }

    if( !CL_IsPredicted( ))
    {
        local_state_t t1, t2;
        Q_memset( &t1, 0, sizeof( local_state_t ));
        Q_memset( &t2, 0, sizeof( local_state_t ));
        clgame.dllFuncs.pfnPostRunCmd( &t1, &t2, cl.refdef.cmd, false, cl.time, cls.lastoutgoingcommand );

        cl.scr_fov = t2.client.fov;
        if( cl.scr_fov < 1.0f || cl.scr_fov> 170.0f )
            cl.scr_fov = 90.0f;
        return;
    }

    ack = cls.netchan.incoming_acknowledged;
    outgoing_command = cls.netchan.outgoing_sequence;

    from = &cl.predict[cl.parsecountmod];
    from->playerstate = cl.frame.playerstate[cl.playernum];
    from->client = cl.frame.local.client;
    Q_memcpy( from->weapondata, cl.frame.local.weapondata, sizeof( from->weapondata ));

    time = cl.frame.time;

    CL_SetSolidEntities ();
    CL_SetSolidPlayers ( cl.playernum );

    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;

        to = &cl.predict[( cl.parsecountmod + frame ) & CL_UPDATE_MASK];

        CL_RunUsercmd( from, to, &cl.cmds[current_command_mod],
                       cl.runfuncs[current_command_mod],
                       &time, cls.netchan.incoming_acknowledged + frame );

        cl.runfuncs[current_command_mod] = false;

        from = to;
        frame++;
    }

    if( to )
    {
        cl.predicted_viewmodel = to->client.viewmodel;
        cl.scr_fov = to->client.fov;
        if( cl.scr_fov < 1.0f || cl.scr_fov> 170.0f )
            cl.scr_fov = 90.0f;
        VectorCopy( to->playerstate.origin, cl.predicted_origin );
        VectorCopy( to->client.velocity, cl.predicted_velocity );
        VectorCopy( to->client.view_ofs, cl.predicted_viewofs );
        VectorCopy( to->client.punchangle, cl.predicted_punchangle );
    }
}