示例#1
0
/*
==============
V_CalcViewRoll

Roll is induced by movement and damage
==============
*/
void V_CalcViewRoll (void)
{
	float	side;
	float	adjspeed;
	
	side = V_CalcRoll (cl.simangles, cl.simvel);
	adjspeed = 20 * bound (2, fabs(cl_rollangle.value), 45);
	if (side > cl.rollangle) {
		cl.rollangle += cls.frametime * adjspeed;
		if (cl.rollangle > side)
			cl.rollangle = side;
	}
	else if (side < cl.rollangle)
	{
		cl.rollangle -= cls.frametime * adjspeed;
		if (cl.rollangle < side)
			cl.rollangle = side;
	}
	r_refdef2.viewangles[ROLL] += cl.rollangle;

	if (v_dmg_time > 0 && v_kicktime.value > 0)
	{
		r_refdef2.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
		r_refdef2.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
		v_dmg_time -= cls.frametime;
	}
}
示例#2
0
/*
===================
SV_ClientThink

the move fields specify an intended velocity in pix/sec
the angle fields specify an exact angular motion in degrees
===================
*/
void SV_ClientThink (void)
{
	vec3_t		v_angle;

	if (sv_player->v.movetype == MOVETYPE_NONE)
		return;

	onground = (int)sv_player->v.flags & FL_ONGROUND;

	origin = sv_player->v.origin;
	velocity = sv_player->v.velocity;

	DropPunchAngle ();

//
// if dead, behave differently
//
	if (sv_player->v.health <= 0)
		return;

//
// angles
// show 1/3 the pitch angle and all the roll angle
	cmd = host_client->cmd;
	angles = sv_player->v.angles;

	VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle);
	angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
	if (!sv_player->v.fixangle)
	{
		angles[PITCH] = -v_angle[PITCH]/3;
		angles[YAW] = v_angle[YAW];
	}

	if ( (int)sv_player->v.flags & FL_WATERJUMP )
	{
		SV_WaterJump ();
		return;
	}
//
// walk
//
	if ( (sv_player->v.waterlevel >= 2)
	&& (sv_player->v.movetype != MOVETYPE_NOCLIP) )
	{
		SV_WaterMove ();
		return;
	}

	SV_AirMove ();
}
示例#3
0
void V_CalcViewRoll ( struct ref_params_s *pparams )
{
	float		side;
	cl_entity_t *viewentity;
	
	viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity );
	if ( !viewentity )
		return;

	// Fograin92: cl_rollangle/cl_rollspeed feature restoration. (Thanks to: L453rh4wk)
	pparams->viewangles[ROLL] = V_CalcRoll (pparams->viewangles, pparams->simvel, cl_rollangle->value, cl_rollspeed->value ) * 4;

	side = V_CalcRoll ( viewentity->angles, pparams->simvel, pparams->movevars->rollangle, pparams->movevars->rollspeed );

	pparams->viewangles[ROLL] += side;

	if ( pparams->health <= 0 && ( pparams->viewheight[2] != 0 ) )
	{
		// only roll the view if the player is dead and the viewheight[2] is nonzero 
		// this is so deadcam in multiplayer will work.
		pparams->viewangles[ROLL] = 80;	// dead view angle
		return;
	}
}
示例#4
0
/*
==============
V_CalcViewRoll

Roll is induced by movement and damage
==============
*/
void V_CalcViewRoll ( struct ref_params_s *pparams )
{
	cl_entity_t *viewentity;
	
	viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity );
	if ( !viewentity )
		return;

	//Roll the angles when strafing Quake style!
	pparams->viewangles[ROLL] = V_CalcRoll (pparams->viewangles, pparams->simvel, cl_rollangle->value, cl_rollspeed->value ) * 4;

	if ( pparams->health <= 0 && ( pparams->viewheight[2] != 0 ) )
	{
		// only roll the view if the player is dead and the viewheight[2] is nonzero 
		// this is so deadcam in multiplayer will work.
		pparams->viewangles[ROLL] = 80;	// dead view angle
		return;
	}
}
示例#5
0
文件: view.c 项目: ericwa/Quakespasm
/*
==============
V_CalcViewRoll

Roll is induced by movement and damage
==============
*/
void V_CalcViewRoll (void)
{
	float		side;

	side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity);
	r_refdef.viewangles[ROLL] += side;

	if (v_dmg_time > 0)
	{
		r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
		r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
		v_dmg_time -= host_frametime;
	}

	if (cl.stats[STAT_HEALTH] <= 0)
	{
		r_refdef.viewangles[ROLL] = 80;	// dead view angle
		return;
	}
}
示例#6
0
/*
==============
V_CalcViewRoll

Roll is induced by movement and damage
==============
*/
void V_CalcViewRoll(struct ref_params_s *pparams)
{
	float        side;
	cl_entity_t *viewentity;

	viewentity = gEngfuncs.GetEntityByIndex(pparams->viewentity);
	if(!viewentity)
		return;

	side = V_CalcRoll(viewentity->angles, pparams->simvel, pparams->movevars->rollangle, pparams->movevars->rollspeed);

	pparams->viewangles[ROLL] += side;

	if(pparams->health <= 0 && (pparams->viewheight[2] != 0))
	{
		// only roll the view if the player is dead and the viewheight[2] is nonzero
		// this is so deadcam in multiplayer will work.
		pparams->viewangles[ROLL] = 80; // dead view angle
		return;
	}
}
示例#7
0
/*
	V_CalcViewRoll

	Roll is induced by movement and damage
*/
static void
V_CalcViewRoll (void)
{
	float       side;
	vec_t      *angles = cl.simangles;
	vec_t      *velocity = cl.simvel;

	side = V_CalcRoll (angles, velocity);
	r_data->refdef->viewangles[ROLL] += side;

	if (v_dmg_time > 0) {
		r_data->refdef->viewangles[ROLL] +=
			v_dmg_time / v_kicktime->value * v_dmg_roll;
		r_data->refdef->viewangles[PITCH] +=
			v_dmg_time / v_kicktime->value * v_dmg_pitch;
		v_dmg_time -= host_frametime;
	}

	if (view_message->pls.flags & PF_DEAD)		// PF_GIB will also set PF_DEAD
		r_data->refdef->viewangles[ROLL] = 80;	// dead view angle
}
示例#8
0
/*
===================
SV_ClientThink

the move fields specify an intended velocity in pix/sec
the angle fields specify an exact angular motion in degrees
===================
*/
static void
SV_ClientThink(client_t *client)
{
    edict_t *player = client->edict;
    vec3_t v_angle;

    if (player->v.movetype == MOVETYPE_NONE)
	return;

    DropPunchAngle(player->v.punchangle);

    /* if dead, behave differently */
    if (player->v.health <= 0)
	return;

    /* angles - show 1/3 the pitch angle and all the roll angle */
    VectorAdd(player->v.v_angle, player->v.punchangle, v_angle);
    player->v.angles[ROLL] = V_CalcRoll(player->v.angles, player->v.velocity) * 4;
    if (!player->v.fixangle) {
	player->v.angles[PITCH] = -v_angle[PITCH] / 3;
	player->v.angles[YAW] = v_angle[YAW];
    }

    if ((int)player->v.flags & FL_WATERJUMP) {
	SV_WaterJump(player);
	return;
    }

    /* walk */
    if (player->v.waterlevel >= 2 && player->v.movetype != MOVETYPE_NOCLIP) {
	SV_WaterMove(&client->cmd, player);
	return;
    }

    SV_AirMove(&client->cmd, player);
}
示例#9
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);

	}
}
示例#10
0
文件: sv_user.c 项目: Blzut3/Engoo
void SV_ClientThink (void)
{
	vec3_t		v_angle;
	int yeahdead;

	if (sv_player->v.movetype == MOVETYPE_NONE)
		return;

	if (cl.stats[STAT_HEALTH] <= 0) {	
		
			yeahdead = 1;
		
			if (!deathcam_yesiamdead){

				deathcam_angles[PITCH] = 50;
			//	deathcam_angles[YAW] = 20;
				deathcam_angles[ROLL] = 0;
				deathcam_whenidied = sv.time;
				//Con_Printf("I died at %f. sob.\n", deathcam_whenidied);
			}

			if (cl_diecam->value)
			deathcam_yesiamdead = cl_diecam->value;

	}
	else	
	{
			yeahdead = 0;
			deathcam_yesiamdead = 0;
	}

	onground = (int)sv_player->v.flags & FL_ONGROUND;

	origin = sv_player->v.origin;
	velocity = sv_player->v.velocity;


		

	DropPunchAngle ();


//
// if dead, behave differently
//

	// leilei - standstill hack
	if (sv_standstill->value)
	{
		float sample1, sample2, sample3, sample4, sample5;
		float divided;

		if (sv_maxspeed->value)
		divided = 1 / sv_maxspeed->value * sv_standstill->value;
		else
		divided = 1;	// avoiding a div0......

		sample1 = cmd.forwardmove * divided;
		sample2 = cmd.sidemove * divided;
		sample3 = cmd.upmove  * divided;
		sample4 = amouse_x * divided;
		sample5 = amouse_y * divided;
		
		if (sample1 < 0) sample1 *= -1;
		if (sample2 < 0) sample2 *= -1;
		if (sample3 < 0) sample3 *= -1;
		if (sample4 < 0) sample4 *= -1;
		if (sample5 < 0) sample5 *= -1;
		
		thestandstill = sample1 + sample2 + sample3 + sample4 + sample5 * 0.5;
		if (thestandstill > 1)
			thestandstill = 1;
		
		Cvar_SetValue (host_timescale,thestandstill); // slow it down!
	}


	if (sv_player->v.health <= 0)
		return;

//
// angles
// show 1/3 the pitch angle and all the roll angle
	cmd = host_client->cmd;


	angles = sv_player->v.angles;
	// leilei - aim lock
	if (aimlock){
		if ((lockedangle[YAW] + aimlockangle) > 360){
//			Con_Printf("goddamnit.\n");
			if (cl.viewangles[YAW] > (lockedangle[YAW] + aimlockangle > 360)) sv_player->v.angles[YAW] -= 360;
			if (cl.viewangles[YAW] > lockedangle[YAW] + aimlockangle) cl.viewangles[YAW] = lockedangle[YAW] + aimlockangle;
		}
		else
			if (cl.viewangles[YAW] > lockedangle[YAW] + aimlockangle) cl.viewangles[YAW] = lockedangle[YAW] + aimlockangle;
			if ((lockedangle[YAW] - aimlockangle) < 0){
			if (cl.viewangles[YAW] < lockedangle[YAW] - aimlockangle) cl.viewangles[YAW] = lockedangle[YAW] - aimlockangle + 360;
			if (cl.viewangles[YAW] < lockedangle[YAW] - aimlockangle) cl.viewangles[YAW] = lockedangle[YAW] - aimlockangle;
	//		Con_Printf("mother\n");
			}
			else
			if (cl.viewangles[YAW] < lockedangle[YAW] - aimlockangle) cl.viewangles[YAW] = lockedangle[YAW] - aimlockangle;

			// TODO: wrap angle, wrapangle
		if (cl.viewangles[PITCH] < lockedangle[PITCH] - aimlockangle) cl.viewangles[PITCH] = lockedangle[PITCH] - aimlockangle;
		if (cl.viewangles[PITCH] > lockedangle[PITCH] + aimlockangle) cl.viewangles[PITCH] = lockedangle[PITCH] + aimlockangle;
//		if (cl.viewangles[YAW] < lockedangle[YAW] - aimlockangle) cl.viewangles[YAW] = lockedangle[YAW] - aimlockangle;
//		if (cl.viewangles[YAW] > lockedangle[YAW] + aimlockangle) cl.viewangles[YAW] = lockedangle[YAW] + aimlockangle;
	

	}

	
	VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle);
	angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;


	 if (!sv_player->v.fixangle)
	{
		angles[PITCH] = -v_angle[PITCH]/3;
		angles[YAW] = v_angle[YAW];

	}

	if ( (int)sv_player->v.flags & FL_WATERJUMP )
	{
		SV_WaterJump ();
		return;
	}
//
// walk
//
	if ( (sv_player->v.waterlevel >= 2)
	&& (sv_player->v.movetype != MOVETYPE_NOCLIP) )
	{
		SV_WaterMove ();
		return;
	}


	SV_AirMove ();
}
示例#11
0
文件: view.c 项目: DrBeef/QuakeGVR
/*
 * State:
 *   cl.bob2_smooth
 *   cl.bobfall_speed
 *   cl.bobfall_swing
 *   cl.gunangles_adjustment_highpass
 *   cl.gunangles_adjustment_lowpass
 *   cl.gunangles_highpass
 *   cl.gunangles_prev
 *   cl.gunorg_adjustment_highpass
 *   cl.gunorg_adjustment_lowpass
 *   cl.gunorg_highpass
 *   cl.gunorg_prev
 *   cl.hitgroundtime
 *   cl.lastongroundtime
 *   cl.oldongrounbd
 *   cl.stairsmoothtime
 *   cl.stairsmoothz
 *   cl.calcrefdef_prevtime
 * Extra input:
 *   cl.movecmd[0].time
 *   cl.movevars_stepheight
 *   cl.movevars_timescale
 *   cl.oldtime
 *   cl.punchangle
 *   cl.punchvector
 *   cl.qw_intermission_angles
 *   cl.qw_intermission_origin
 *   cl.qw_weaponkick
 *   cls.protocol
 *   cl.time
 * Output:
 *   cl.csqc_viewanglesfromengine
 *   cl.csqc_viewmodelmatrixfromengine
 *   cl.csqc_vieworiginfromengine
 *   r_refdef.view.matrix
 *   viewmodelmatrix_nobob
 *   viewmodelmatrix_withbob
 */
void V_CalcRefdefUsing (const matrix4x4_t *entrendermatrix, const vec3_t clviewangles, qboolean teleported, qboolean clonground, qboolean clcmdjump, float clstatsviewheight, qboolean cldead, qboolean clintermission, const vec3_t clvelocity)
{
	float vieworg[3], viewangles[3], smoothtime;
	float gunorg[3], gunangles[3];
	matrix4x4_t tmpmatrix;
	
	static float viewheightavg;
	float viewheight;	
#if 0
// begin of chase camera bounding box size for proper collisions by Alexander Zubov
	vec3_t camboxmins = {-3, -3, -3};
	vec3_t camboxmaxs = {3, 3, 3};
// end of chase camera bounding box size for proper collisions by Alexander Zubov
#endif
	trace_t trace;

	// react to clonground state changes (for gun bob)
	if (clonground)
	{
		if (!cl.oldonground)
			cl.hitgroundtime = cl.movecmd[0].time;
		cl.lastongroundtime = cl.movecmd[0].time;
	}
	cl.oldonground = clonground;
	cl.calcrefdef_prevtime = max(cl.calcrefdef_prevtime, cl.oldtime);

	VectorClear(gunorg);
	viewmodelmatrix_nobob = identitymatrix;
	viewmodelmatrix_withbob = identitymatrix;
	r_refdef.view.matrix = identitymatrix;

	// player can look around, so take the origin from the entity,
	// and the angles from the input system
	Matrix4x4_OriginFromMatrix(entrendermatrix, vieworg);
	VectorCopy(clviewangles, viewangles);

	// calculate how much time has passed since the last V_CalcRefdef
	smoothtime = bound(0, cl.time - cl.stairsmoothtime, 0.1);
	cl.stairsmoothtime = cl.time;

	// fade damage flash
	if (v_dmg_time > 0)
		v_dmg_time -= bound(0, smoothtime, 0.1);

	if (clintermission)
	{
		// entity is a fixed camera, just copy the matrix
		if (cls.protocol == PROTOCOL_QUAKEWORLD)
			Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.qw_intermission_origin[0], cl.qw_intermission_origin[1], cl.qw_intermission_origin[2], cl.qw_intermission_angles[0], cl.qw_intermission_angles[1], cl.qw_intermission_angles[2], 1);
		else
		{
			r_refdef.view.matrix = *entrendermatrix;
			Matrix4x4_AdjustOrigin(&r_refdef.view.matrix, 0, 0, clstatsviewheight);
		}
		Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
		Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);
		Matrix4x4_Copy(&viewmodelmatrix_withbob, &viewmodelmatrix_nobob);

		VectorCopy(vieworg, cl.csqc_vieworiginfromengine);
		VectorCopy(viewangles, cl.csqc_viewanglesfromengine);

		Matrix4x4_Invert_Simple(&tmpmatrix, &r_refdef.view.matrix);
		Matrix4x4_CreateScale(&cl.csqc_viewmodelmatrixfromengine, cl_viewmodel_scale.value);
	}
	else
	{
		// smooth stair stepping, but only if clonground and enabled
		if (!clonground || cl_stairsmoothspeed.value <= 0 || teleported)
			cl.stairsmoothz = vieworg[2];
		else
		{
			if (cl.stairsmoothz < vieworg[2])
				vieworg[2] = cl.stairsmoothz = bound(vieworg[2] - cl.movevars_stepheight, cl.stairsmoothz + smoothtime * cl_stairsmoothspeed.value, vieworg[2]);
			else if (cl.stairsmoothz > vieworg[2])
				vieworg[2] = cl.stairsmoothz = bound(vieworg[2], cl.stairsmoothz - smoothtime * cl_stairsmoothspeed.value, vieworg[2] + cl.movevars_stepheight);
		}

		// apply qw weapon recoil effect (this did not work in QW)
		// TODO: add a cvar to disable this
		viewangles[PITCH] += cl.qw_weaponkick;

		// apply the viewofs (even if chasecam is used)
		// Samual: Lets add smoothing for this too so that things like crouching are done with a transition.
		viewheight = bound(0, (cl.time - cl.calcrefdef_prevtime) / max(0.0001, cl_smoothviewheight.value), 1);
		viewheightavg = viewheightavg * (1 - viewheight) + clstatsviewheight * viewheight;
		vieworg[2] += viewheightavg;

		if (chase_active.value)
		{
			// observing entity from third person. Added "campitch" by Alexander "motorsep" Zubov
			vec_t camback, camup, dist, campitch, forward[3], chase_dest[3];

			camback = chase_back.value;
			camup = chase_up.value;
			campitch = chase_pitchangle.value;

			AngleVectors(viewangles, forward, NULL, NULL);

			if (chase_overhead.integer)
			{
#if 1
				vec3_t offset;
				vec3_t bestvieworg;
#endif
				vec3_t up;
				viewangles[PITCH] = 0;
				AngleVectors(viewangles, forward, NULL, up);
				// trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
				chase_dest[0] = vieworg[0] - forward[0] * camback + up[0] * camup;
				chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup;
				chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup;
#if 0
#if 1
				//trace = CL_TraceLine(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
				trace = CL_TraceLine(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#else
				//trace = CL_TraceBox(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
				trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#endif
				VectorCopy(trace.endpos, vieworg);
				vieworg[2] -= 8;
#else
				// trace from first person view location to our chosen third person view location
#if 1
				trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
#else
				trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#endif
				VectorCopy(trace.endpos, bestvieworg);
				offset[2] = 0;
				for (offset[0] = -16;offset[0] <= 16;offset[0] += 8)
				{
					for (offset[1] = -16;offset[1] <= 16;offset[1] += 8)
					{
						AngleVectors(viewangles, NULL, NULL, up);
						chase_dest[0] = vieworg[0] - forward[0] * camback + up[0] * camup + offset[0];
						chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup + offset[1];
						chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup + offset[2];
#if 1
						trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
#else
						trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#endif
						if (bestvieworg[2] > trace.endpos[2])
							bestvieworg[2] = trace.endpos[2];
					}
				}
				bestvieworg[2] -= 8;
				VectorCopy(bestvieworg, vieworg);
#endif
				viewangles[PITCH] = campitch;
			}
			else
			{
				if (gamemode == GAME_GOODVSBAD2 && chase_stevie.integer)
				{
					// look straight down from high above
					viewangles[PITCH] = 90;
					camback = 2048;
					VectorSet(forward, 0, 0, -1);
				}

				// trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
				dist = -camback - 8;
				chase_dest[0] = vieworg[0] + forward[0] * dist;
				chase_dest[1] = vieworg[1] + forward[1] * dist;
				chase_dest[2] = vieworg[2] + forward[2] * dist + camup;
				trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
				VectorMAMAM(1, trace.endpos, 8, forward, 4, trace.plane.normal, vieworg);
			}
		}
		else
		{
			// first person view from entity
			// angles
			if (cldead && v_deathtilt.integer)
				viewangles[ROLL] = v_deathtiltangle.value;

			if (cl_weaponrecoil.integer > 0)
				VectorAdd(viewangles, cl.punchangle, viewangles);
			viewangles[ROLL] += V_CalcRoll(clviewangles, clvelocity);
			if (v_dmg_time > 0)
			{
				viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
				viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
			}
			// origin
			if (cl_weaponrecoil.integer > 0)
            	VectorAdd(vieworg, cl.punchvector, vieworg);
			if (!cldead)
			{
				double xyspeed, bob, bobfall;
				float cycle;
				vec_t frametime;

				frametime = (cl.time - cl.calcrefdef_prevtime) * cl.movevars_timescale;

				// 1. if we teleported, clear the frametime... the lowpass will recover the previous value then
				if(teleported)
				{
					// try to fix the first highpass; result is NOT
					// perfect! TODO find a better fix
					VectorCopy(viewangles, cl.gunangles_prev);
					VectorCopy(vieworg, cl.gunorg_prev);
				}

				// 2. for the gun origin, only keep the high frequency (non-DC) parts, which is "somewhat like velocity"
				VectorAdd(cl.gunorg_highpass, cl.gunorg_prev, cl.gunorg_highpass);
				highpass3_limited(vieworg, frametime*cl_followmodel_side_highpass1.value, cl_followmodel_side_limit.value, frametime*cl_followmodel_side_highpass1.value, cl_followmodel_side_limit.value, frametime*cl_followmodel_up_highpass1.value, cl_followmodel_up_limit.value, cl.gunorg_highpass, gunorg);
				VectorCopy(vieworg, cl.gunorg_prev);
				VectorSubtract(cl.gunorg_highpass, cl.gunorg_prev, cl.gunorg_highpass);

				// in the highpass, we _store_ the DIFFERENCE to the actual view angles...
				VectorAdd(cl.gunangles_highpass, cl.gunangles_prev, cl.gunangles_highpass);
				cl.gunangles_highpass[PITCH] += 360 * floor((viewangles[PITCH] - cl.gunangles_highpass[PITCH]) / 360 + 0.5);
				cl.gunangles_highpass[YAW] += 360 * floor((viewangles[YAW] - cl.gunangles_highpass[YAW]) / 360 + 0.5);
				cl.gunangles_highpass[ROLL] += 360 * floor((viewangles[ROLL] - cl.gunangles_highpass[ROLL]) / 360 + 0.5);
				highpass3_limited(viewangles, frametime*cl_leanmodel_up_highpass1.value, cl_leanmodel_up_limit.value, frametime*cl_leanmodel_side_highpass1.value, cl_leanmodel_side_limit.value, 0, 0, cl.gunangles_highpass, gunangles);
				VectorCopy(viewangles, cl.gunangles_prev);
				VectorSubtract(cl.gunangles_highpass, cl.gunangles_prev, cl.gunangles_highpass);

				// 3. calculate the RAW adjustment vectors
				gunorg[0] *= (cl_followmodel.value ? -cl_followmodel_side_speed.value : 0);
				gunorg[1] *= (cl_followmodel.value ? -cl_followmodel_side_speed.value : 0);
				gunorg[2] *= (cl_followmodel.value ? -cl_followmodel_up_speed.value : 0);

				gunangles[PITCH] *= (cl_leanmodel.value ? -cl_leanmodel_up_speed.value : 0);
				gunangles[YAW] *= (cl_leanmodel.value ? -cl_leanmodel_side_speed.value : 0);
				gunangles[ROLL] = 0;

				// 4. perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
				//    trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
				highpass3(gunorg, frametime*cl_followmodel_side_highpass.value, frametime*cl_followmodel_side_highpass.value, frametime*cl_followmodel_up_highpass.value, cl.gunorg_adjustment_highpass, gunorg);
				lowpass3(gunorg, frametime*cl_followmodel_side_lowpass.value, frametime*cl_followmodel_side_lowpass.value, frametime*cl_followmodel_up_lowpass.value, cl.gunorg_adjustment_lowpass, gunorg);
				// we assume here: PITCH = 0, YAW = 1, ROLL = 2
				highpass3(gunangles, frametime*cl_leanmodel_up_highpass.value, frametime*cl_leanmodel_side_highpass.value, 0, cl.gunangles_adjustment_highpass, gunangles);
				lowpass3(gunangles, frametime*cl_leanmodel_up_lowpass.value, frametime*cl_leanmodel_side_lowpass.value, 0, cl.gunangles_adjustment_lowpass, gunangles);

				// 5. use the adjusted vectors
				VectorAdd(vieworg, gunorg, gunorg);
				VectorAdd(viewangles, gunangles, gunangles);

				// bounded XY speed, used by several effects below
				xyspeed = bound (0, sqrt(clvelocity[0]*clvelocity[0] + clvelocity[1]*clvelocity[1]), 400);

				// vertical view bobbing code
				if (cl_bob.value && cl_bobcycle.value)
				{
					// LordHavoc: this code is *weird*, but not replacable (I think it
					// should be done in QC on the server, but oh well, quake is quake)
					// LordHavoc: figured out bobup: the time at which the sin is at 180
					// degrees (which allows lengthening or squishing the peak or valley)
					cycle = cl.time / cl_bobcycle.value;
					cycle -= (int) cycle;
					if (cycle < cl_bobup.value)
						cycle = sin(M_PI * cycle / cl_bobup.value);
					else
						cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
					// bob is proportional to velocity in the xy plane
					// (don't count Z, or jumping messes it up)
					bob = xyspeed * bound(0, cl_bob.value, 0.05);
					bob = bob*0.3 + bob*0.7*cycle;
					vieworg[2] += bob;
					// we also need to adjust gunorg, or this appears like pushing the gun!
					// In the old code, this was applied to vieworg BEFORE copying to gunorg,
					// but this is not viable with the new followmodel code as that would mean
					// that followmodel would work on the munged-by-bob vieworg and do feedback
					gunorg[2] += bob;
				}

				// horizontal view bobbing code
				if (cl_bob2.value && cl_bob2cycle.value)
				{
					vec3_t bob2vel;
					vec3_t forward, right, up;
					float side, front;

					cycle = cl.time / cl_bob2cycle.value;
					cycle -= (int) cycle;
					if (cycle < 0.5)
						cycle = cos(M_PI * cycle / 0.5); // cos looks better here with the other view bobbing using sin
					else
						cycle = cos(M_PI + M_PI * (cycle-0.5)/0.5);
					bob = bound(0, cl_bob2.value, 0.05) * cycle;

					// this value slowly decreases from 1 to 0 when we stop touching the ground.
					// The cycle is later multiplied with it so the view smooths back to normal
					if (clonground && !clcmdjump) // also block the effect while the jump button is pressed, to avoid twitches when bunny-hopping
						cl.bob2_smooth = 1;
					else
					{
						if(cl.bob2_smooth > 0)
							cl.bob2_smooth -= bound(0, cl_bob2smooth.value, 1);
						else
							cl.bob2_smooth = 0;
					}

					// calculate the front and side of the player between the X and Y axes
					AngleVectors(viewangles, forward, right, up);
					// now get the speed based on those angles. The bounds should match the same value as xyspeed's
					side = bound(-400, DotProduct (clvelocity, right) * cl.bob2_smooth, 400);
					front = bound(-400, DotProduct (clvelocity, forward) * cl.bob2_smooth, 400);
					VectorScale(forward, bob, forward);
					VectorScale(right, bob, right);
					// we use side with forward and front with right, so the bobbing goes
					// to the side when we walk forward and to the front when we strafe
					VectorMAMAM(side, forward, front, right, 0, up, bob2vel);
					vieworg[0] += bob2vel[0];
					vieworg[1] += bob2vel[1];
					// we also need to adjust gunorg, or this appears like pushing the gun!
					// In the old code, this was applied to vieworg BEFORE copying to gunorg,
					// but this is not viable with the new followmodel code as that would mean
					// that followmodel would work on the munged-by-bob vieworg and do feedback
					gunorg[0] += bob2vel[0];
					gunorg[1] += bob2vel[1];
				}

				// fall bobbing code
				// causes the view to swing down and back up when touching the ground
				if (cl_bobfall.value && cl_bobfallcycle.value)
				{
					if (!clonground)
					{
						cl.bobfall_speed = bound(-400, clvelocity[2], 0) * bound(0, cl_bobfall.value, 0.1);
						if (clvelocity[2] < -cl_bobfallminspeed.value)
							cl.bobfall_swing = 1;
						else
							cl.bobfall_swing = 0; // TODO really?
					}
					else
					{
						cl.bobfall_swing = max(0, cl.bobfall_swing - cl_bobfallcycle.value * frametime);

						bobfall = sin(M_PI * cl.bobfall_swing) * cl.bobfall_speed;
						vieworg[2] += bobfall;
						gunorg[2] += bobfall;
					}
				}

				// gun model bobbing code
				if (cl_bobmodel.value)
				{
					// calculate for swinging gun model
					// the gun bobs when running on the ground, but doesn't bob when you're in the air.
					// Sajt: I tried to smooth out the transitions between bob and no bob, which works
					// for the most part, but for some reason when you go through a message trigger or
					// pick up an item or anything like that it will momentarily jolt the gun.
					vec3_t forward, right, up;
					float bspeed;
					float s;
					float t;

					s = cl.time * cl_bobmodel_speed.value;
					if (clonground)
					{
						if (cl.time - cl.hitgroundtime < 0.2)
						{
							// just hit the ground, speed the bob back up over the next 0.2 seconds
							t = cl.time - cl.hitgroundtime;
							t = bound(0, t, 0.2);
							t *= 5;
						}
						else
							t = 1;
					}
					else
					{
						// recently left the ground, slow the bob down over the next 0.2 seconds
						t = cl.time - cl.lastongroundtime;
						t = 0.2 - bound(0, t, 0.2);
						t *= 5;
					}

					bspeed = xyspeed * 0.01f;
					AngleVectors (gunangles, forward, right, up);
					bob = bspeed * cl_bobmodel_side.value * cl_viewmodel_scale.value * sin (s) * t;
					VectorMA (gunorg, bob, right, gunorg);
					bob = bspeed * cl_bobmodel_up.value * cl_viewmodel_scale.value * cos (s * 2) * t;
					VectorMA (gunorg, bob, up, gunorg);
				}
			}
		}
		// calculate a view matrix for rendering the scene
		if (v_idlescale.value)
		{
			viewangles[0] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
			viewangles[1] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
			viewangles[2] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
		}
		Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2], 1);

		// calculate a viewmodel matrix for use in view-attached entities
		Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
		Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);

		Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix_withbob, gunorg[0], gunorg[1], gunorg[2], gunangles[0], gunangles[1], gunangles[2], cl_viewmodel_scale.value);
		VectorCopy(vieworg, cl.csqc_vieworiginfromengine);
		VectorCopy(viewangles, cl.csqc_viewanglesfromengine);

		Matrix4x4_Invert_Simple(&tmpmatrix, &r_refdef.view.matrix);
		Matrix4x4_Concat(&cl.csqc_viewmodelmatrixfromengine, &tmpmatrix, &viewmodelmatrix_withbob);
	}

	cl.calcrefdef_prevtime = cl.time;
}
示例#12
0
/*
===========
SV_RunCmd
===========
*/
static void SV_RunCmd (usercmd_t *ucmd)
{
	edict_t		*ent;
	int			i, n;
	int			oldmsec;

	cmd = *ucmd;

	// chop up very long commands
	if (cmd.msec > 50)
	{
		oldmsec = ucmd->msec;
		cmd.msec = oldmsec/2;
		SV_RunCmd (&cmd);
		cmd.msec = oldmsec/2;
		cmd.impulse = 0;
		SV_RunCmd (&cmd);
		return;
	}

	if (!sv_player->v.fixangle)
		VectorCopy (ucmd->angles, sv_player->v.v_angle);

	sv_player->v.button0 = ucmd->buttons & 1;
	sv_player->v.button2 = (ucmd->buttons & 2)>>1;

	if (ucmd->buttons & 4 || sv_player->v.playerclass == CLASS_DWARF) // crouched?
		sv_player->v.flags2 = ((int)sv_player->v.flags2) | FL2_CROUCHED;
	else
		sv_player->v.flags2 = ((int)sv_player->v.flags2) & (~FL2_CROUCHED);

	if (ucmd->impulse)
		sv_player->v.impulse = ucmd->impulse;

//
// angles
// show 1/3 the pitch angle and all the roll angle
	if (sv_player->v.health > 0)
	{
		if (!sv_player->v.fixangle)
		{
			sv_player->v.angles[PITCH] = -sv_player->v.v_angle[PITCH]/3;
			sv_player->v.angles[YAW] = sv_player->v.v_angle[YAW];
		}
		sv_player->v.angles[ROLL] = 
				V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
	}

	host_frametime = ucmd->msec * 0.001;
	if (host_frametime > HX_FRAME_TIME)
		host_frametime = HX_FRAME_TIME;

	if (!host_client->spectator)
	{
		pr_global_struct->frametime = host_frametime;

		pr_global_struct->time = sv.time;
		pr_global_struct->self = EDICT_TO_PROG(sv_player);
		PR_ExecuteProgram (pr_global_struct->PlayerPreThink);

		SV_RunThink (sv_player);
	}

	for (i = 0; i < 3; i++)
		pmove.origin[i] = sv_player->v.origin[i] + (sv_player->v.mins[i] - player_mins[i]);

	VectorCopy (sv_player->v.velocity, pmove.velocity);
	VectorCopy (sv_player->v.v_angle, pmove.angles);

	pmove.spectator = host_client->spectator;
//	pmove.waterjumptime = sv_player->v.teleport_time;
	pmove.numphysent = 1;
	pmove.physents[0].model = sv.worldmodel;
	pmove.cmd = *ucmd;
	pmove.dead = sv_player->v.health <= 0;
	pmove.oldbuttons = host_client->oldbuttons;
	pmove.hasted = sv_player->v.hasted;
	pmove.movetype = sv_player->v.movetype;
	pmove.crouched = (sv_player->v.hull == HULL_CROUCH);
	pmove.teleport_time = realtime + (sv_player->v.teleport_time - sv.time);

//	movevars.entgravity = host_client->entgravity;
	movevars.entgravity = sv_player->v.gravity;
	movevars.maxspeed = host_client->maxspeed;

	for (i = 0; i < 3; i++)
	{
		pmove_mins[i] = pmove.origin[i] - 256;
		pmove_maxs[i] = pmove.origin[i] + 256;
	}
#if 1
	AddLinksToPmove ( sv_areanodes );
#else
	AddAllEntsToPmove ();
#endif

#if 0
	{
		int	before, after;

		before = PM_TestPlayerPosition (pmove.origin);
		PlayerMove ();
		after = PM_TestPlayerPosition (pmove.origin);

		if (sv_player->v.health > 0 && before && !after )
			Con_Printf ("player %s got stuck in playermove!!!!\n", host_client->name);
	}
#else
	PlayerMove ();
#endif

	host_client->oldbuttons = pmove.oldbuttons;
//	sv_player->v.teleport_time = pmove.waterjumptime;
	sv_player->v.waterlevel = waterlevel;
	sv_player->v.watertype = watertype;
	if (onground != -1)
	{
		sv_player->v.flags = (int)sv_player->v.flags | FL_ONGROUND;
		sv_player->v.groundentity = EDICT_TO_PROG(EDICT_NUM(pmove.physents[onground].info));
	}
	else
		sv_player->v.flags = (int)sv_player->v.flags & ~FL_ONGROUND;

	for (i = 0; i < 3; i++)
		sv_player->v.origin[i] = pmove.origin[i] - (sv_player->v.mins[i] - player_mins[i]);

#if 0
	// truncate velocity the same way the net protocol will
	for (i = 0; i < 3; i++)
		sv_player->v.velocity[i] = (int)pmove.velocity[i];
#else
	VectorCopy (pmove.velocity, sv_player->v.velocity);
#endif

	VectorCopy (pmove.angles, sv_player->v.v_angle);

	if (!host_client->spectator)
	{
		// link into place and touch triggers
		SV_LinkEdict (sv_player, true);

		// touch other objects
		for (i = 0; i < pmove.numtouch; i++)
		{
			n = pmove.physents[pmove.touchindex[i]].info;
			ent = EDICT_NUM(n);

		// Why not just do an SV_Impact here?
		//	SV_Impact(sv_player,ent);

			if (sv_player->v.touch)
			{
				pr_global_struct->self = EDICT_TO_PROG(sv_player);
				pr_global_struct->other = EDICT_TO_PROG(ent);
				PR_ExecuteProgram (sv_player->v.touch);
			}
			if (!ent->v.touch || (playertouch[n/8]&(1<<(n%8))))
				continue;
			pr_global_struct->self = EDICT_TO_PROG(ent);
			pr_global_struct->other = EDICT_TO_PROG(sv_player);
			PR_ExecuteProgram (ent->v.touch);
			playertouch[n/8] |= 1 << (n%8);
		}
	}
}