Beispiel #1
0
void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u) {
	// split up very long moves
	if (u->msec > 50) {
		player_state_t temp;
		usercmd_t split;

		split = *u;
		split.msec /= 2;

		CL_PredictUsercmd (from, &temp, &split);
		CL_PredictUsercmd (&temp, to, &split);
		return;
	}

	VectorCopy (from->origin, pmove.origin);
	VectorCopy (u->angles, pmove.angles);
	VectorCopy (from->velocity, pmove.velocity);

	pmove.jump_msec = (cl.z_ext & Z_EXT_PM_TYPE) ? 0 : from->jump_msec;
	pmove.jump_held = from->jump_held;
	pmove.waterjumptime = from->waterjumptime;
	pmove.pm_type = from->pm_type;
	pmove.onground = from->onground;
	pmove.cmd = *u;

#ifdef JSS_CAM
	if (cam_lockdir.value) {
		VectorCopy (saved_angles, pmove.cmd.angles);
		VectorCopy (saved_angles, pmove.angles);
	}
	else
		VectorCopy (pmove.cmd.angles, saved_angles);
#endif

	movevars.entgravity = cl.entgravity;
	movevars.maxspeed = cl.maxspeed;
	movevars.bunnyspeedcap = cl.bunnyspeedcap;

	PM_PlayerMove ();

	to->waterjumptime = pmove.waterjumptime;
	to->pm_type = pmove.pm_type;
	to->jump_held = pmove.jump_held;
	to->jump_msec = pmove.jump_msec;
	pmove.jump_msec = 0;

	VectorCopy (pmove.origin, to->origin);
	VectorCopy (pmove.angles, to->viewangles);
	VectorCopy (pmove.velocity, to->velocity);
	to->onground = pmove.onground;

	to->weaponframe = from->weaponframe;
}
Beispiel #2
0
/*
===
Calculate the new position of players, without other player clipping

We do this to set up real player prediction.
Players are predicted twice, first without clipping other players,
then with clipping against them.
This sets up the first phase.
===
*/
void CL_SetUpPlayerPrediction(qboolean dopred)
{
	int				j;
	player_state_t	*state;
	player_state_t	exact;
	double			playertime;
	int				msec;
	frame_t			*frame;
	struct predicted_player *pplayer;

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

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

	for (j=0, pplayer = predicted_players, state=frame->playerstate; 
		j < MAX_CLIENTS;
		j++, pplayer++, state++) {

		pplayer->active = false;

		if (state->messagenum != cl.parsecount)
			continue;	// not present this frame

		if (!state->modelindex)
			continue;

		pplayer->active = true;
		pplayer->flags = state->flags;

		// note that the local player is special, since he moves locally
		// we use his last predicted postition
		if (j == cl.playernum) {
			VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum].origin,
				pplayer->origin);
		} else {
			// 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) ||
				!dopred)
			{
				VectorCopy (state->origin, pplayer->origin);
	//Con_DPrintf ("nopredict\n");
			}
			else
			{
				// predict players movement
				if (msec > 255)
					msec = 255;
				state->command.msec = msec;
	//Con_DPrintf ("predict: %i\n", msec);

				CL_PredictUsercmd (state, &exact, &state->command, false);
				VectorCopy (exact.origin, pplayer->origin);
			}
		}
	}
}
Beispiel #3
0
/*
==============
CL_PredictUsercmd
==============
*/
void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u)
{
	// split up very long moves
	if (u->msec > 50)
	{
		player_state_t	temp;
		usercmd_t	split;

		split = *u;
		split.msec /= 2;

		CL_PredictUsercmd (from, &temp, &split);
		CL_PredictUsercmd (&temp, to, &split);
		return;
	}

	VectorCopy (from->origin, cl.pmove.origin);
//	VectorCopy (from->viewangles, pmove.angles);
	VectorCopy (u->angles, cl.pmove.angles);
	VectorCopy (from->velocity, cl.pmove.velocity);

	if (cl.z_ext & Z_EXT_PM_TYPE)
		cl.pmove.jump_msec = 0;
	else
		cl.pmove.jump_msec = from->jump_msec;
	cl.pmove.jump_held = from->jump_held;
	cl.pmove.waterjumptime = from->waterjumptime;
	cl.pmove.pm_type = from->pm_type;
	cl.pmove.onground = from->onground;
	cl.pmove.cmd = *u;

	PM_PlayerMove (&cl.pmove, &cl.movevars);

	to->waterjumptime = cl.pmove.waterjumptime;
	to->pm_type = cl.pmove.pm_type;
	to->jump_held = cl.pmove.jump_held;
	to->jump_msec = cl.pmove.jump_msec;
	cl.pmove.jump_msec = 0;

	VectorCopy (cl.pmove.origin, to->origin);
	VectorCopy (cl.pmove.angles, to->viewangles);
	VectorCopy (cl.pmove.velocity, to->velocity);
	to->onground = cl.pmove.onground;

	to->weaponframe = from->weaponframe;
}
Beispiel #4
0
/*
==============
CL_PredictUsercmd
==============
*/
void
CL_PredictUsercmd(player_state_t *from, player_state_t *to, usercmd_t *u,
		  qboolean spectator)
{
    // split up very long moves
    if (u->msec > 50) {
	player_state_t temp;
	usercmd_t split;

	split = *u;
	split.msec /= 2;

	CL_PredictUsercmd(from, &temp, &split, spectator);
	CL_PredictUsercmd(&temp, to, &split, spectator);
	return;
    }

    VectorCopy(from->origin, pmove.origin);
//      VectorCopy (from->viewangles, pmove.angles);
    VectorCopy(u->angles, pmove.angles);
    VectorCopy(from->velocity, pmove.velocity);

    pmove.oldbuttons = from->oldbuttons;
    pmove.waterjumptime = from->waterjumptime;
    pmove.dead = cl.stats[STAT_HEALTH] <= 0;
    pmove.spectator = spectator;

    pmove.cmd = *u;

    PlayerMove();
//for (i=0 ; i<3 ; i++)
//pmove.origin[i] = ((int)(pmove.origin[i]*8))*0.125;
    to->waterjumptime = pmove.waterjumptime;
    to->oldbuttons = pmove.cmd.buttons;
    VectorCopy(pmove.origin, to->origin);
    VectorCopy(pmove.angles, to->viewangles);
    VectorCopy(pmove.velocity, to->velocity);
    to->onground = onground;

    to->weaponframe = from->weaponframe;
}
Beispiel #5
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]);
    }
}
Beispiel #6
0
/*
=============
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);

	}
}