Exemple #1
0
/*
==============================
AdjustYaw

==============================
*/
void CInput::AdjustYaw( float speed, QAngle& viewangles )
{
	if ( !(in_strafe.state & 1) )
	{
		viewangles[YAW] -= speed*cl_yawspeed.GetFloat() * KeyState (&in_right);
		viewangles[YAW] += speed*cl_yawspeed.GetFloat() * KeyState (&in_left);
	}

	// thirdperson platformer mode
	// use movement keys to aim the player relative to the thirdperson camera
	if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
	{
		float side = KeyState(&in_moveleft) - KeyState(&in_moveright);
		float forward = KeyState(&in_forward) - KeyState(&in_back);

		if ( side || forward )
		{
			viewangles[YAW] = RAD2DEG(atan2(side, forward)) + g_ThirdPersonManager.GetCameraOffsetAngles()[ YAW ];
		}
		if ( side || forward || KeyState (&in_right) || KeyState (&in_left) )
		{
			cam_idealyaw.SetValue( g_ThirdPersonManager.GetCameraOffsetAngles()[ YAW ] - viewangles[ YAW ] );
		}
	}
}
Exemple #2
0
/*
==============================
ComputeSideMove

==============================
*/
void CInput::ComputeSideMove( CUserCmd *cmd )
{
	// thirdperson platformer movement
	if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
	{
		// no sideways movement in this mode
		return;
	}

	// thirdperson screenspace movement
	if ( CAM_IsThirdPerson() && thirdperson_screenspace.GetInt() )
	{
		float ideal_yaw = m_aCamIdealAngles[YAW];
		float ideal_sin = sin(DEG2RAD(ideal_yaw));
		float ideal_cos = cos(DEG2RAD(ideal_yaw));
		
		float movement = ideal_cos*KeyState(&in_moveright)
			+  ideal_sin*KeyState(&in_back)
			+ -ideal_cos*KeyState(&in_moveleft)
			+ -ideal_sin*KeyState(&in_forward);

		cmd->sidemove += cl_sidespeed.GetFloat() * movement;

		return;
	}

	// If strafing, check left and right keys and act like moveleft and moveright keys
	if ( in_strafe.state & 1 )
	{
		cmd->sidemove += cl_sidespeed.GetFloat() * KeyState (&in_right);
		cmd->sidemove -= cl_sidespeed.GetFloat() * KeyState (&in_left);
	}

	// Otherwise, check strafe keys

	C_SDKPlayer *pPlayer = ToSDKPlayer(C_BasePlayer::GetLocalPlayer());

	cmd->sidemove += cl_sidespeed.GetFloat() * KeyState (&in_moveright);
	cmd->sidemove -= cl_sidespeed.GetFloat() * KeyState (&in_moveleft);
}
Exemple #3
0
/*
==============================
ComputeForwardMove

==============================
*/
void CInput::ComputeForwardMove( CUserCmd *cmd )
{
	// thirdperson platformer movement
	if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
	{
		// movement is always forward in this mode
		float movement = KeyState(&in_forward)
			|| KeyState(&in_moveright)
			|| KeyState(&in_back)
			|| KeyState(&in_moveleft);

		cmd->forwardmove += cl_forwardspeed.GetFloat() * movement;

		return;
	}

	// thirdperson screenspace movement
	if ( CAM_IsThirdPerson() && thirdperson_screenspace.GetInt() )
	{
		float ideal_yaw = cam_idealyaw.GetFloat();
		float ideal_sin = sin(DEG2RAD(ideal_yaw));
		float ideal_cos = cos(DEG2RAD(ideal_yaw));
		
		float movement = ideal_cos*KeyState(&in_forward)
			+  ideal_sin*KeyState(&in_moveright)
			+ -ideal_cos*KeyState(&in_back)
			+ -ideal_sin*KeyState(&in_moveleft);

		cmd->forwardmove += cl_forwardspeed.GetFloat() * movement;

		return;
	}

	if ( !(in_klook.state & 1 ) )
	{	
		cmd->forwardmove += cl_forwardspeed.GetFloat() * KeyState (&in_forward);
		cmd->forwardmove -= cl_backspeed.GetFloat() * KeyState (&in_back);
	}	
}
//-----------------------------------------------------------------------------
// Purpose: ApplyMouse -- applies mouse deltas to CUserCmd
// Input  : viewangles - 
//			*cmd - 
//			mouse_x - 
//			mouse_y - 
//-----------------------------------------------------------------------------
void CInput::ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y )
{
	if ( !((in_strafe.state & 1) || lookstrafe.GetInt()) )
	{
#ifdef PORTAL
		if ( g_bUpsideDown )
		{
			viewangles[ YAW ] += m_yaw.GetFloat() * mouse_x;
		}
		else
#endif //#ifdef PORTAL
		{
			if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
			{
				if ( mouse_x )
				{
					// use the mouse to orbit the camera around the player, and update the idealAngle
					m_vecCameraOffset[ YAW ] -= m_yaw.GetFloat() * mouse_x;
					cam_idealyaw.SetValue( m_vecCameraOffset[ YAW ] - viewangles[ YAW ] );

					// why doesn't this work??? CInput::AdjustYaw is why
					//cam_idealyaw.SetValue( cam_idealyaw.GetFloat() - m_yaw.GetFloat() * mouse_x );
				}
			}
			else
			{
				// Otherwize, use mouse to spin around vertical axis
				viewangles[YAW] -= m_yaw.GetFloat() * mouse_x;
			}
		}
	}
	else
	{
		// If holding strafe key or mlooking and have lookstrafe set to true, then apply
		//  horizontal mouse movement to sidemove.
		cmd->sidemove += m_side.GetFloat() * mouse_x;
	}

	// If mouselooking and not holding strafe key, then use vertical mouse
	//  to adjust view pitch.
	if (!(in_strafe.state & 1))
	{
#ifdef PORTAL
		if ( g_bUpsideDown )
		{
			viewangles[PITCH] -= m_pitch->GetFloat() * mouse_y;
		}
		else
#endif //#ifdef PORTAL
		{
			if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
			{
				if ( mouse_y )
				{
					// use the mouse to orbit the camera around the player, and update the idealAngle
					m_vecCameraOffset[ PITCH ] += m_pitch->GetFloat() * mouse_y;
					cam_idealpitch.SetValue( m_vecCameraOffset[ PITCH ] - viewangles[ PITCH ] );

					// why doesn't this work??? CInput::AdjustYaw is why
					//cam_idealpitch.SetValue( cam_idealpitch.GetFloat() + m_pitch->GetFloat() * mouse_y );
				}
			}
			else
			{
				viewangles[PITCH] += m_pitch->GetFloat() * mouse_y;
			}

			// Check pitch bounds
			if (viewangles[PITCH] > cl_pitchdown.GetFloat())
			{
				viewangles[PITCH] = cl_pitchdown.GetFloat();
			}
			if (viewangles[PITCH] < -cl_pitchup.GetFloat())
			{
				viewangles[PITCH] = -cl_pitchup.GetFloat();
			}
		}
	}
	else
	{
		// Otherwise if holding strafe key and noclipping, then move upward
/*		if ((in_strafe.state & 1) && IsNoClipping() )
		{
			cmd->upmove -= m_forward.GetFloat() * mouse_y;
		} 
		else */
		{
			// Default is to apply vertical mouse movement as a forward key press.
			cmd->forwardmove -= m_forward.GetFloat() * mouse_y;
		}
	}

	// Finally, add mouse state to usercmd.
	// NOTE:  Does rounding to int cause any issues?  ywb 1/17/04
	cmd->mousedx = (int)mouse_x;
	cmd->mousedy = (int)mouse_y;
}
Exemple #5
0
//-----------------------------------------------------------------------------
// Purpose: ApplyMouse -- applies mouse deltas to CUserCmd
// Input  : viewangles - 
//			*cmd - 
//			mouse_x - 
//			mouse_y - 
//-----------------------------------------------------------------------------
void CInput::ApplyMouse( int nSlot, QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y )
{
	PerUserInput_t &user = GetPerUser( nSlot );

	//roll the view angles so roll is 0 (the HL2 assumed state) and mouse adjustments are relative to the screen.
	//Assuming roll is unchanging, we want mouse left to translate to screen left at all times (same for right, up, and down)
	


	if ( !((in_strafe.GetPerUser( nSlot ).state & 1) || lookstrafe.GetInt()) )
	{
		if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
		{
			if ( mouse_x )
			{
				// use the mouse to orbit the camera around the player, and update the idealAngle
				user.m_vecCameraOffset[ YAW ] -= m_yaw.GetFloat() * mouse_x;
				cam_idealyaw.SetValue( user.m_vecCameraOffset[ YAW ] - viewangles[ YAW ] );

				// why doesn't this work??? CInput::AdjustYaw is why
				//cam_idealyaw.SetValue( cam_idealyaw.GetFloat() - m_yaw.GetFloat() * mouse_x );
			}
		}
		else
		{
			// Otherwize, use mouse to spin around vertical axis


			{
				viewangles[YAW] -= m_yaw.GetFloat() * mouse_x;
			}
		}
	}
	else
	{
		// If holding strafe key or mlooking and have lookstrafe set to true, then apply
		//  horizontal mouse movement to sidemove.
		cmd->sidemove += m_side.GetFloat() * mouse_x;
	}

	// If mouselooking and not holding strafe key, then use vertical mouse
	//  to adjust view pitch.
	if (!(in_strafe.GetPerUser( nSlot ).state & 1))
	{
		if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
		{
			if ( mouse_y )
			{
				// use the mouse to orbit the camera around the player, and update the idealAngle
				user.m_vecCameraOffset[ PITCH ] += m_pitch->GetFloat() * mouse_y;
				cam_idealpitch.SetValue( user.m_vecCameraOffset[ PITCH ] - viewangles[ PITCH ] );

				// why doesn't this work??? CInput::AdjustYaw is why
				//cam_idealpitch.SetValue( cam_idealpitch.GetFloat() + m_pitch->GetFloat() * mouse_y );
			}
		}
		else
		{

			{
				viewangles[PITCH] += m_pitch->GetFloat() * mouse_y;
			}

			// Check pitch bounds
			if (viewangles[PITCH] > cl_pitchdown.GetFloat())
			{
				viewangles[PITCH] = cl_pitchdown.GetFloat();
			}
			if (viewangles[PITCH] < -cl_pitchup.GetFloat())
			{
				viewangles[PITCH] = -cl_pitchup.GetFloat();
			}
		}		
	}
	else
	{
		// Otherwise if holding strafe key and noclipping, then move upward
/*		if ((in_strafe.state & 1) && IsNoClipping() )
		{
			cmd->upmove -= m_forward.GetFloat() * mouse_y;
		} 
		else */
		{
			// Default is to apply vertical mouse movement as a forward key press.
			cmd->forwardmove -= m_forward.GetFloat() * mouse_y;
		}
	}

	// Finally, add mouse state to usercmd.
	// NOTE:  Does rounding to int cause any issues?  ywb 1/17/04
	cmd->mousedx = (int)mouse_x;
	cmd->mousedy = (int)mouse_y;
}
//-----------------------------------------------------------------------------
// Purpose: Apply joystick to CUserCmd creation
// Input  : frametime - 
//			*cmd - 
//-----------------------------------------------------------------------------
void CInput::JoyStickMove( float frametime, CUserCmd *cmd )
{
	// complete initialization if first time in ( needed as cvars are not available at initialization time )
	if ( !m_fJoystickAdvancedInit )
	{
		Joystick_Advanced();
		m_fJoystickAdvancedInit = true;
	}

	// verify joystick is available and that the user wants to use it
	if ( !in_joystick.GetInt() || 0 == inputsystem->GetJoystickCount() )
		return; 

	// Skip out if vgui is active
	if ( vgui::surface()->IsCursorVisible() )
		return;

	if ( m_flRemainingJoystickSampleTime <= 0 )
		return;
	frametime = MIN(m_flRemainingJoystickSampleTime, frametime);
	m_flRemainingJoystickSampleTime -= frametime;

	QAngle viewangles;

	// Get starting angles
	engine->GetViewAngles( viewangles );

	struct axis_t
	{
		float	value;
		int		controlType;
	};
	axis_t gameAxes[ MAX_GAME_AXES ];
	memset( &gameAxes, 0, sizeof(gameAxes) );

	// Get each joystick axis value, and normalize the range
	for ( int i = 0; i < MAX_JOYSTICK_AXES; ++i )
	{
		if ( GAME_AXIS_NONE == m_rgAxes[i].AxisMap )
			continue;

		float fAxisValue = inputsystem->GetAnalogValue( (AnalogCode_t)JOYSTICK_AXIS( 0, i ) );

		if (joy_wwhack2.GetInt() != 0 )
		{
			// this is a special formula for the Logitech WingMan Warrior
			// y=ax^b; where a = 300 and b = 1.3
			// also x values are in increments of 800 (so this is factored out)
			// then bounds check result to level out excessively high spin rates
			float fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3);
			if (fTemp > 14000.0)
				fTemp = 14000.0;
			// restore direction information
			fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp;
		}

		unsigned int idx = m_rgAxes[i].AxisMap;
		gameAxes[idx].value = fAxisValue;
		gameAxes[idx].controlType = m_rgAxes[i].ControlMap;
	}

	// Re-map the axis values if necessary, based on the joystick configuration
	if ( (joy_advanced.GetInt() == 0) && (in_jlook.state & 1) )
	{
		// user wants forward control to become pitch control
		gameAxes[GAME_AXIS_PITCH] = gameAxes[GAME_AXIS_FORWARD];
		gameAxes[GAME_AXIS_FORWARD].value = 0;

		// if mouse invert is on, invert the joystick pitch value
		// Note: only absolute control support here - joy_advanced = 0
		if ( m_pitch->GetFloat() < 0.0 )
		{
			gameAxes[GAME_AXIS_PITCH].value *= -1;
		}
	}

	if ( (in_strafe.state & 1) || lookstrafe.GetFloat() && (in_jlook.state & 1) )
	{
		// user wants yaw control to become side control
		gameAxes[GAME_AXIS_SIDE] = gameAxes[GAME_AXIS_YAW];
		gameAxes[GAME_AXIS_YAW].value = 0;
	}

	float forward	= ScaleAxisValue( gameAxes[GAME_AXIS_FORWARD].value, MAX_BUTTONSAMPLE * joy_forwardthreshold.GetFloat() );
	float side		= ScaleAxisValue( gameAxes[GAME_AXIS_SIDE].value, MAX_BUTTONSAMPLE * joy_sidethreshold.GetFloat()  );
	float pitch		= ScaleAxisValue( gameAxes[GAME_AXIS_PITCH].value, MAX_BUTTONSAMPLE * joy_pitchthreshold.GetFloat()  );
	float yaw		= ScaleAxisValue( gameAxes[GAME_AXIS_YAW].value, MAX_BUTTONSAMPLE * joy_yawthreshold.GetFloat()  );

	// If we're inverting our joystick, do so
	if ( joy_inverty.GetBool() )
	{
		pitch *= -1.0f;
	}

	// drive yaw, pitch and move like a screen relative platformer game
	if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
	{
		if ( forward || side )
		{
			// apply turn control [ YAW ]
			// factor in the camera offset, so that the move direction is relative to the thirdperson camera
			viewangles[ YAW ] = RAD2DEG(atan2(-side, -forward)) + m_vecCameraOffset[ YAW ];
			engine->SetViewAngles( viewangles );

			// apply movement
			Vector2D moveDir( forward, side );
			cmd->forwardmove += moveDir.Length() * cl_forwardspeed.GetFloat();
		}

		if ( pitch || yaw )
		{
			// look around with the camera
			m_vecCameraOffset[ PITCH ] += pitch * joy_pitchsensitivity.GetFloat();
			m_vecCameraOffset[ YAW ]   += yaw * joy_yawsensitivity.GetFloat();
		}

		if ( forward || side || pitch || yaw )
		{
			// update the ideal pitch and yaw
			cam_idealpitch.SetValue( m_vecCameraOffset[ PITCH ] - viewangles[ PITCH ] );
			cam_idealyaw.SetValue( m_vecCameraOffset[ YAW ] - viewangles[ YAW ] );
		}
		return;
	}

	float	joySideMove = 0.f;
	float	joyForwardMove = 0.f;
	float   aspeed = frametime * gHUD.GetFOVSensitivityAdjust();

	// apply forward and side control
	C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
	
	int iResponseCurve = 0;
	if ( pLocalPlayer && pLocalPlayer->IsInAVehicle() )
	{
		iResponseCurve = pLocalPlayer->GetVehicle() ? pLocalPlayer->GetVehicle()->GetJoystickResponseCurve() : joy_response_move_vehicle.GetInt();
	}
	else
	{
		iResponseCurve = joy_response_move.GetInt();
	}	
	
	float val = ResponseCurve( iResponseCurve, forward, PITCH, joy_forwardsensitivity.GetFloat() );
	joyForwardMove	+= val * cl_forwardspeed.GetFloat();
	val = ResponseCurve( iResponseCurve, side, YAW, joy_sidesensitivity.GetFloat() );
	joySideMove		+= val * cl_sidespeed.GetFloat();

	Vector2D move( yaw, pitch );
	float dist = move.Length();

	// apply turn control
	float angle = 0.f;

	if ( JOY_ABSOLUTE_AXIS == gameAxes[GAME_AXIS_YAW].controlType )
	{
		float fAxisValue = ResponseCurveLook( joy_response_look.GetInt(), yaw, YAW, pitch, dist, frametime );
		angle = fAxisValue * joy_yawsensitivity.GetFloat() * aspeed * cl_yawspeed.GetFloat();
	}
	else
	{
		angle = yaw * joy_yawsensitivity.GetFloat() * aspeed * 180.0;
	}
	viewangles[YAW] += angle;
	cmd->mousedx = angle;

	// apply look control
	if ( IsX360() || in_jlook.state & 1 )
	{
		float angle = 0;
		if ( JOY_ABSOLUTE_AXIS == gameAxes[GAME_AXIS_PITCH].controlType )
		{
			float fAxisValue = ResponseCurveLook( joy_response_look.GetInt(), pitch, PITCH, yaw, dist, frametime );
			angle = fAxisValue * joy_pitchsensitivity.GetFloat() * aspeed * cl_pitchspeed.GetFloat();
		}
		else
		{
			angle = pitch * joy_pitchsensitivity.GetFloat() * aspeed * 180.0;
		}
		viewangles[PITCH] += angle;
		cmd->mousedy = angle;
		view->StopPitchDrift();
		if( pitch == 0.f && lookspring.GetFloat() == 0.f )
		{
			// no pitch movement
			// disable pitch return-to-center unless requested by user
			// *** this code can be removed when the lookspring bug is fixed
			// *** the bug always has the lookspring feature on
			view->StopPitchDrift();
		}
	}

	// apply player motion relative to screen space
	if ( CAM_IsThirdPerson() && thirdperson_screenspace.GetInt() )
	{
		float ideal_yaw = cam_idealyaw.GetFloat();
		float ideal_sin = sin(DEG2RAD(ideal_yaw));
		float ideal_cos = cos(DEG2RAD(ideal_yaw));
		float side_movement = ideal_cos*joySideMove - ideal_sin*joyForwardMove;
		float forward_movement = ideal_cos*joyForwardMove + ideal_sin*joySideMove;
		cmd->forwardmove += forward_movement;
		cmd->sidemove += side_movement;
	}
	else
	{
		cmd->forwardmove += joyForwardMove;
		cmd->sidemove += joySideMove;
	}

	if ( IsPC() )
	{
		CCommand tmp;
		if ( FloatMakePositive(joyForwardMove) >= joy_autosprint.GetFloat() || FloatMakePositive(joySideMove) >= joy_autosprint.GetFloat() )
		{
			KeyDown( &in_joyspeed, NULL );
		}
		else
		{
			KeyUp( &in_joyspeed, NULL );
		}
	}

	// Bound pitch
	viewangles[PITCH] = clamp( viewangles[ PITCH ], -cl_pitchup.GetFloat(), cl_pitchdown.GetFloat() );

	engine->SetViewAngles( viewangles );
}
void CSDKInput::CAM_Think( void )
{
	VPROF("CAM_Think");

	Vector idealAngles;
	Vector camOffset;
	QAngle viewangles;
	
	if( !CAM_IsThirdPerson() )
		return;

	ConVarRef cam_idealpitch( "cam_idealpitch" );
	ConVarRef cam_idealyaw( "cam_idealyaw" );
	ConVarRef cam_idealdist( "cam_idealdist" );

	idealAngles[ PITCH ] = cam_idealpitch.GetFloat();
	idealAngles[ YAW ]   = cam_idealyaw.GetFloat();
	idealAngles[ DIST ]  = cam_idealdist.GetFloat();

	// Obtain engine view angles and if they popped while the camera was static,
	// fix the camera angles as well
	engine->GetViewAngles( viewangles );

	// bring the pitch values back into a range that MoveToward can handle
	if ( idealAngles[ PITCH ] > 180 )
		idealAngles[ PITCH ] -= 360;
	else if ( idealAngles[ PITCH ] < -180 )
		idealAngles[ PITCH ] += 360;

	// bring the yaw values back into a range that MoveToward can handle
	// --
	// Vitaliy: going with >= 180 and <= -180.
	// This introduces a potential discontinuity when looking directly at model face
	// as camera yaw will be jumping from +180 to -180 and back, but when working with
	// the camera allows smooth rotational transitions from left to right and back.
	// Otherwise one of the transitions that has ">"-comparison will be locked.
	// --
	if ( idealAngles[ YAW ] >= 180 )
		idealAngles[ YAW ] -= 360;
	else if ( idealAngles[ YAW ] <= -180 )
		idealAngles[ YAW ] += 360;

	ConVarRef c_minpitch( "c_minpitch" );
	ConVarRef c_maxpitch( "c_maxpitch" );
	ConVarRef c_minyaw( "c_minyaw" );
	ConVarRef c_maxyaw( "c_maxyaw" );
	ConVarRef c_mindistance( "c_mindistance" );
	ConVarRef c_maxdistance( "c_maxdistance" );

	// clamp pitch, yaw and dist...
	idealAngles[ PITCH ] = clamp( idealAngles[ PITCH ], c_minpitch.GetFloat(), c_maxpitch.GetFloat() );
	idealAngles[ YAW ]   = clamp( idealAngles[ YAW ], c_minyaw.GetFloat(), c_maxyaw.GetFloat() );
	idealAngles[ DIST ]  = clamp( idealAngles[ DIST ], c_mindistance.GetFloat(), c_maxdistance.GetFloat() );

	// update ideal angles
	cam_idealpitch.SetValue( idealAngles[ PITCH ] );
	cam_idealyaw.SetValue( idealAngles[ YAW ] );
	cam_idealdist.SetValue( idealAngles[ DIST ] );
	
	// Move the CameraOffset "towards" the idealAngles
	// Note: CameraOffset = viewangle + idealAngle
	CAM_GetCameraOffset( camOffset );

	ConVarRef cam_snapto( "cam_snapto" );
	if( cam_snapto.GetInt() )
	{
		camOffset[ YAW ] = cam_idealyaw.GetFloat() + viewangles[ YAW ];
		camOffset[ PITCH ] = cam_idealpitch.GetFloat() + viewangles[ PITCH ];
		camOffset[ DIST ] = cam_idealdist.GetFloat();
	}
	else
	{
		ConVarRef cam_ideallag( "cam_ideallag" );
		float lag = max( 1, 1 + cam_ideallag.GetFloat() );

		if( camOffset[ YAW ] - viewangles[ YAW ] != cam_idealyaw.GetFloat() )
			camOffset[ YAW ] = MoveToward( camOffset[ YAW ], cam_idealyaw.GetFloat() + viewangles[ YAW ], lag );
		
		if( camOffset[ PITCH ] - viewangles[ PITCH ] != cam_idealpitch.GetFloat() )
			camOffset[ PITCH ] = MoveToward( camOffset[ PITCH ], cam_idealpitch.GetFloat() + viewangles[ PITCH ], lag );
		
		if( abs( camOffset[ DIST ] - cam_idealdist.GetFloat() ) < 2.0 )
			camOffset[ DIST ] = cam_idealdist.GetFloat();
		else
			camOffset[ DIST ] += ( cam_idealdist.GetFloat() - camOffset[ DIST ] ) / lag;
	}

	// move the camera closer to the player if it hit something
	trace_t trace;
	C_BasePlayer* localPlayer = C_BasePlayer::GetLocalPlayer();

	if ( localPlayer )
	{
		Vector camForward;

		// find our player's origin, and from there, the eye position
		Vector origin = localPlayer->GetLocalOrigin();
		origin += localPlayer->GetViewOffset();

		// get the forward vector
		AngleVectors( QAngle(camOffset[ PITCH ], camOffset[ YAW ], 0), &camForward, NULL, NULL );

		// use our previously #defined hull to collision trace
		CTraceFilterSimple traceFilter( localPlayer, COLLISION_GROUP_NONE );
		UTIL_TraceHull( origin, origin - (camForward * camOffset[ DIST ]),
			Vector(-CAM_HULL_OFFSET, -CAM_HULL_OFFSET, -CAM_HULL_OFFSET), Vector(CAM_HULL_OFFSET, CAM_HULL_OFFSET, CAM_HULL_OFFSET),
			MASK_SOLID, &traceFilter, &trace );

		// move the camera closer if it hit something
		if( trace.fraction < 1.0 )
		{
			camOffset[ DIST ] *= trace.fraction;
		}

		// For now, I'd rather see the insade of a player model than punch the camera through a wall
		// might try the fade out trick at some point
		//if( camOffset[ DIST ] < CAM_MIN_DIST )
		//    camOffset[ DIST ] = CAM_MIN_DIST; // clamp up to minimum
	}

	ConVarRef cam_showangles( "cam_showangles" );
	if ( cam_showangles.GetInt() )
	{
		engine->Con_NPrintf( 4, "Pitch: %6.1f   Yaw: %6.1f %38s", viewangles[ PITCH ], viewangles[ YAW ], "view angles" );
		engine->Con_NPrintf( 6, "Pitch: %6.1f   Yaw: %6.1f   Dist: %6.1f %19s", cam_idealpitch.GetFloat(), cam_idealyaw.GetFloat(), cam_idealdist.GetFloat(), "ideal angles" );
		engine->Con_NPrintf( 8, "Pitch: %6.1f   Yaw: %6.1f   Dist: %6.1f %16s", camOffset[ PITCH ], camOffset[ YAW ], camOffset[ DIST ], "camera offset" );
	}

	QAngle angOffset;
	angOffset.x = camOffset.x;
	angOffset.y = camOffset.y;
	angOffset.z = camOffset.z;

	CAM_SetCameraThirdData(NULL, angOffset);
}