aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/in_joystick.cpp
diff options
context:
space:
mode:
authorNarendra Umate <[email protected]>2013-12-02 23:36:05 -0800
committerNarendra Umate <[email protected]>2013-12-02 23:36:05 -0800
commit8737f191f3b59f001a77bf6c08091109211c1c9f (patch)
treedbbf05c004d9b026f2c1f23f06600fe0add82c36 /mp/src/game/client/in_joystick.cpp
parentUpdate .gitignore. (diff)
parentMake .xcconfigs text files too. (diff)
downloadsource-sdk-2013-8737f191f3b59f001a77bf6c08091109211c1c9f.tar.xz
source-sdk-2013-8737f191f3b59f001a77bf6c08091109211c1c9f.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'mp/src/game/client/in_joystick.cpp')
-rw-r--r--mp/src/game/client/in_joystick.cpp1824
1 files changed, 912 insertions, 912 deletions
diff --git a/mp/src/game/client/in_joystick.cpp b/mp/src/game/client/in_joystick.cpp
index 8703bca8..2f0e3dad 100644
--- a/mp/src/game/client/in_joystick.cpp
+++ b/mp/src/game/client/in_joystick.cpp
@@ -1,912 +1,912 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Joystick handling function
-//
-// $Workfile: $
-// $Date: $
-// $NoKeywords: $
-//===========================================================================//
-
-#include "cbase.h"
-#include "basehandle.h"
-#include "utlvector.h"
-#include "cdll_client_int.h"
-#include "cdll_util.h"
-#include "kbutton.h"
-#include "usercmd.h"
-#include "iclientvehicle.h"
-#include "input.h"
-#include "iviewrender.h"
-#include "convar.h"
-#include "hud.h"
-#include "vgui/ISurface.h"
-#include "vgui_controls/Controls.h"
-#include "vgui/Cursor.h"
-#include "tier0/icommandline.h"
-#include "inputsystem/iinputsystem.h"
-#include "inputsystem/ButtonCode.h"
-#include "math.h"
-#include "tier1/convar_serverbounded.h"
-#include "cam_thirdperson.h"
-
-#if defined( _X360 )
-#include "xbox/xbox_win32stubs.h"
-#else
-#include "../common/xbox/xboxstubs.h"
-#endif
-
-#ifdef HL2_CLIENT_DLL
-// FIXME: Autoaim support needs to be moved from HL2_DLL to the client dll, so this include should be c_baseplayer.h
-#include "c_basehlplayer.h"
-#endif
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-// Control like a joystick
-#define JOY_ABSOLUTE_AXIS 0x00000000
-// Control like a mouse, spinner, trackball
-#define JOY_RELATIVE_AXIS 0x00000010
-
-// Axis mapping
-static ConVar joy_name( "joy_name", "joystick", FCVAR_ARCHIVE );
-static ConVar joy_advanced( "joy_advanced", "1", FCVAR_ARCHIVE );
-static ConVar joy_advaxisx( "joy_advaxisx", "4", FCVAR_ARCHIVE );
-static ConVar joy_advaxisy( "joy_advaxisy", "2", FCVAR_ARCHIVE );
-static ConVar joy_advaxisz( "joy_advaxisz", "0", FCVAR_ARCHIVE );
-static ConVar joy_advaxisr( "joy_advaxisr", "1", FCVAR_ARCHIVE );
-static ConVar joy_advaxisu( "joy_advaxisu", "3", FCVAR_ARCHIVE );
-static ConVar joy_advaxisv( "joy_advaxisv", "0", FCVAR_ARCHIVE );
-
-// Basic "dead zone" and sensitivity
-static ConVar joy_forwardthreshold( "joy_forwardthreshold", "0.15", FCVAR_ARCHIVE );
-static ConVar joy_sidethreshold( "joy_sidethreshold", "0.15", FCVAR_ARCHIVE );
-static ConVar joy_pitchthreshold( "joy_pitchthreshold", "0.15", FCVAR_ARCHIVE );
-static ConVar joy_yawthreshold( "joy_yawthreshold", "0.15", FCVAR_ARCHIVE );
-static ConVar joy_forwardsensitivity( "joy_forwardsensitivity", "-1", FCVAR_ARCHIVE );
-static ConVar joy_sidesensitivity( "joy_sidesensitivity", "1", FCVAR_ARCHIVE );
-static ConVar joy_pitchsensitivity( "joy_pitchsensitivity", "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX );
-static ConVar joy_yawsensitivity( "joy_yawsensitivity", "-1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX );
-
-// Advanced sensitivity and response
-static ConVar joy_response_move( "joy_response_move", "1", FCVAR_ARCHIVE, "'Movement' stick response mode: 0=Linear, 1=quadratic, 2=cubic, 3=quadratic extreme, 4=power function(i.e., pow(x,1/sensitivity)), 5=two-stage" );
-ConVar joy_response_move_vehicle("joy_response_move_vehicle", "6");
-static ConVar joy_response_look( "joy_response_look", "0", FCVAR_ARCHIVE, "'Look' stick response mode: 0=Default, 1=Acceleration Promotion" );
-static ConVar joy_lowend( "joy_lowend", "1", FCVAR_ARCHIVE );
-static ConVar joy_lowmap( "joy_lowmap", "1", FCVAR_ARCHIVE );
-static ConVar joy_accelscale( "joy_accelscale", "0.6", FCVAR_ARCHIVE);
-static ConVar joy_accelmax( "joy_accelmax", "1.0", FCVAR_ARCHIVE);
-static ConVar joy_autoaimdampenrange( "joy_autoaimdampenrange", "0", FCVAR_ARCHIVE, "The stick range where autoaim dampening is applied. 0 = off" );
-static ConVar joy_autoaimdampen( "joy_autoaimdampen", "0", FCVAR_ARCHIVE, "How much to scale user stick input when the gun is pointing at a valid target." );
-
-static ConVar joy_vehicle_turn_lowend("joy_vehicle_turn_lowend", "0.7");
-static ConVar joy_vehicle_turn_lowmap("joy_vehicle_turn_lowmap", "0.4");
-
-
-// Misc
-static ConVar joy_diagonalpov( "joy_diagonalpov", "0", FCVAR_ARCHIVE, "POV manipulator operates on diagonal axes, too." );
-static ConVar joy_display_input("joy_display_input", "0", FCVAR_ARCHIVE);
-static ConVar joy_wwhack2( "joy_wingmanwarrior_turnhack", "0", FCVAR_ARCHIVE, "Wingman warrior hack related to turn axes." );
-ConVar joy_autosprint("joy_autosprint", "0", 0, "Automatically sprint when moving with an analog joystick" );
-
-static ConVar joy_inverty("joy_inverty", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "Whether to invert the Y axis of the joystick for looking." );
-
-// XBox Defaults
-static ConVar joy_yawsensitivity_default( "joy_yawsensitivity_default", "-1.25", FCVAR_NONE );
-static ConVar joy_pitchsensitivity_default( "joy_pitchsensitivity_default", "-1.0", FCVAR_NONE );
-static ConVar option_duck_method_default( "option_duck_method_default", "1.0", FCVAR_NONE );
-static ConVar joy_inverty_default( "joy_inverty_default", "0", FCVAR_ARCHIVE_XBOX ); // Extracted & saved from profile
-static ConVar joy_movement_stick_default( "joy_movement_stick_default", "0", FCVAR_ARCHIVE_XBOX ); // Extracted & saved from profile
-static ConVar sv_stickysprint_default( "sv_stickysprint_default", "0", FCVAR_NONE );
-
-void joy_movement_stick_Callback( IConVar *var, const char *pOldString, float flOldValue )
-{
- engine->ClientCmd( "joyadvancedupdate" );
-}
-static ConVar joy_movement_stick("joy_movement_stick", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "Which stick controls movement (0 is left stick)", joy_movement_stick_Callback );
-
-static ConVar joy_xcontroller_cfg_loaded( "joy_xcontroller_cfg_loaded", "0", FCVAR_ARCHIVE, "If 0, the 360controller.cfg file will be executed on startup & option changes." );
-
-extern ConVar lookspring;
-extern ConVar cl_forwardspeed;
-extern ConVar lookstrafe;
-extern ConVar in_joystick;
-extern ConVar_ServerBounded *m_pitch;
-extern ConVar l_pitchspeed;
-extern ConVar cl_sidespeed;
-extern ConVar cl_yawspeed;
-extern ConVar cl_pitchdown;
-extern ConVar cl_pitchup;
-extern ConVar cl_pitchspeed;
-
-extern ConVar cam_idealpitch;
-extern ConVar cam_idealyaw;
-extern ConVar thirdperson_platformer;
-extern ConVar thirdperson_screenspace;
-
-//-----------------------------------------------------------------
-// Purpose: Returns true if there's an active joystick connected.
-//-----------------------------------------------------------------
-bool CInput::EnableJoystickMode()
-{
- return IsConsole() || in_joystick.GetBool();
-}
-
-
-//-----------------------------------------------
-// Response curve function for the move axes
-//-----------------------------------------------
-static float ResponseCurve( int curve, float x, int axis, float sensitivity )
-{
- switch ( curve )
- {
- case 1:
- // quadratic
- if ( x < 0 )
- return -(x*x) * sensitivity;
- return x*x * sensitivity;
-
- case 2:
- // cubic
- return x*x*x*sensitivity;
-
- case 3:
- {
- // quadratic extreme
- float extreme = 1.0f;
- if ( fabs( x ) >= 0.95f )
- {
- extreme = 1.5f;
- }
- if ( x < 0 )
- return -extreme * x*x*sensitivity;
- return extreme * x*x*sensitivity;
- }
- case 4:
- {
- float flScale = sensitivity < 0.0f ? -1.0f : 1.0f;
-
- sensitivity = clamp( fabs( sensitivity ), 1.0e-8f, 1000.0f );
-
- float oneOverSens = 1.0f / sensitivity;
-
- if ( x < 0.0f )
- {
- flScale = -flScale;
- }
-
- float retval = clamp( powf( fabs( x ), oneOverSens ), 0.0f, 1.0f );
- return retval * flScale;
- }
- break;
- case 5:
- {
- float out = x;
-
- if( fabs(out) <= 0.6f )
- {
- out *= 0.5f;
- }
-
- out = out * sensitivity;
- return out;
- }
- break;
- case 6: // Custom for driving a vehicle!
- {
- if( axis == YAW )
- {
- // This code only wants to affect YAW axis (the left and right axis), which
- // is used for turning in the car. We fall-through and use a linear curve on
- // the PITCH axis, which is the vehicle's throttle. REALLY, these are the 'forward'
- // and 'side' axes, but we don't have constants for those, so we re-use the same
- // axis convention as the look stick. (sjb)
- float sign = 1;
-
- if( x < 0.0 )
- sign = -1;
-
- x = fabs(x);
-
- if( x <= joy_vehicle_turn_lowend.GetFloat() )
- x = RemapVal( x, 0.0f, joy_vehicle_turn_lowend.GetFloat(), 0.0f, joy_vehicle_turn_lowmap.GetFloat() );
- else
- x = RemapVal( x, joy_vehicle_turn_lowend.GetFloat(), 1.0f, joy_vehicle_turn_lowmap.GetFloat(), 1.0f );
-
- return x * sensitivity * sign;
- }
- //else
- // fall through and just return x*sensitivity below (as if using default curve)
- }
- }
-
- // linear
- return x*sensitivity;
-}
-
-
-//-----------------------------------------------
-// If we have a valid autoaim target, dampen the
-// player's stick input if it is moving away from
-// the target.
-//
-// This assists the player staying on target.
-//-----------------------------------------------
-float AutoAimDampening( float x, int axis, float dist )
-{
- // FIXME: Autoaim support needs to be moved from HL2_DLL to the client dll, so all games can use it.
-#ifdef HL2_CLIENT_DLL
- // Help the user stay on target if the feature is enabled and the user
- // is not making a gross stick movement.
- if( joy_autoaimdampen.GetFloat() > 0.0f && fabs(x) < joy_autoaimdampenrange.GetFloat() )
- {
- // Get the HL2 player
- C_BaseHLPlayer *pLocalPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
-
- if( pLocalPlayer )
- {
- // Get the autoaim target
- if( pLocalPlayer->m_HL2Local.m_bAutoAimTarget )
- {
- return joy_autoaimdampen.GetFloat();
- }
- }
- }
-#endif
- return 1.0f;// No dampening.
-}
-
-
-//-----------------------------------------------
-// This structure holds persistent information used
-// to make decisions about how to modulate analog
-// stick input.
-//-----------------------------------------------
-typedef struct
-{
- float envelopeScale[2];
- bool peggedAxis[2];
- bool axisPeggedDir[2];
-} envelope_t;
-
-envelope_t controlEnvelope;
-
-//-----------------------------------------------
-// Response curve function specifically for the
-// 'look' analog stick.
-//
-// when AXIS == YAW, otherAxisValue contains the
-// value for the pitch of the control stick, and
-// vice-versa.
-//-----------------------------------------------
-ConVar joy_pegged("joy_pegged", "0.75");// Once the stick is pushed this far, it's assumed pegged.
-ConVar joy_virtual_peg("joy_virtual_peg", "0");
-static float ResponseCurveLookDefault( float x, int axis, float otherAxis, float dist, float frametime )
-{
- float input = x;
-
- bool bStickIsPhysicallyPegged = ( dist >= joy_pegged.GetFloat() );
-
- // Make X positive to make things easier, just remember whether we have to flip it back!
- bool negative = false;
- if( x < 0.0f )
- {
- negative = true;
- x *= -1;
- }
-
- if( axis == YAW && joy_virtual_peg.GetBool() )
- {
- if( x >= 0.95f )
- {
- // User has pegged the stick
- controlEnvelope.peggedAxis[axis] = true;
- controlEnvelope.axisPeggedDir[axis] = negative;
- }
-
- if( controlEnvelope.peggedAxis[axis] == true )
- {
- // User doesn't have the stick pegged on this axis, but they used to.
- // If the stick is physically pegged, pretend this axis is still pegged.
- if( bStickIsPhysicallyPegged && negative == controlEnvelope.axisPeggedDir[axis] )
- {
- // If the user still has the stick physically pegged and hasn't changed direction on
- // this axis, keep pretending they have the stick pegged on this axis.
- x = 1.0f;
- }
- else
- {
- controlEnvelope.peggedAxis[axis] = false;
- }
- }
- }
-
- // Perform the two-stage mapping.
- if( x > joy_lowend.GetFloat() )
- {
- float highmap = 1.0f - joy_lowmap.GetFloat();
- float xNormal = x - joy_lowend.GetFloat();
-
- float factor = xNormal / ( 1.0f - joy_lowend.GetFloat() );
- x = joy_lowmap.GetFloat() + (highmap * factor);
-
- // Accelerate.
- if( controlEnvelope.envelopeScale[axis] < 1.0f )
- {
- controlEnvelope.envelopeScale[axis] += ( frametime * joy_accelscale.GetFloat() );
- if( controlEnvelope.envelopeScale[axis] > 1.0f )
- {
- controlEnvelope.envelopeScale[axis] = 1.0f;
- }
- }
-
- float delta = x - joy_lowmap.GetFloat();
- x = joy_lowmap.GetFloat() + (delta * controlEnvelope.envelopeScale[axis]);
- }
- else
- {
- // Shut off acceleration
- controlEnvelope.envelopeScale[axis] = 0.0f;
- float factor = x / joy_lowend.GetFloat();
- x = joy_lowmap.GetFloat() * factor;
- }
-
- x *= AutoAimDampening( input, axis, dist );
-
- if( axis == YAW && x > 0.0f && joy_display_input.GetBool() )
- {
- Msg("In:%f Out:%f Frametime:%f\n", input, x, frametime );
- }
-
- if( negative )
- {
- x *= -1;
- }
-
- return x;
-}
-
-ConVar joy_accel_filter("joy_accel_filter", "0.2");// If the non-accelerated axis is pushed farther than this, then accelerate it, too.
-static float ResponseCurveLookAccelerated( float x, int axis, float otherAxis, float dist, float frametime )
-{
- float input = x;
-
- float flJoyDist = ( sqrt(x*x + otherAxis * otherAxis) );
- bool bIsPegged = ( flJoyDist>= joy_pegged.GetFloat() );
-
- // Make X positive to make arithmetic easier for the rest of this function, and
- // remember whether we have to flip it back!
- bool negative = false;
- if( x < 0.0f )
- {
- negative = true;
- x *= -1;
- }
-
- // Perform the two-stage mapping.
- bool bDoAcceleration = false;// Assume we won't accelerate the input
-
- if( bIsPegged && x > joy_accel_filter.GetFloat() )
- {
- // Accelerate this axis, since the stick is pegged and
- // this axis is pressed farther than the acceleration filter
- // Take the lowmap value, or the input, whichever is higher, since
- // we don't necesarily know whether this is the axis which is pegged
- x = MAX( joy_lowmap.GetFloat(), x );
- bDoAcceleration = true;
- }
- else
- {
- // Joystick is languishing in the low-end, turn off acceleration.
- controlEnvelope.envelopeScale[axis] = 0.0f;
- float factor = x / joy_lowend.GetFloat();
- x = joy_lowmap.GetFloat() * factor;
- }
-
- if( bDoAcceleration )
- {
- float flMax = joy_accelmax.GetFloat();
- if( controlEnvelope.envelopeScale[axis] < flMax )
- {
- float delta = x - joy_lowmap.GetFloat();
- x = joy_lowmap.GetFloat() + (delta * controlEnvelope.envelopeScale[axis]);
- controlEnvelope.envelopeScale[axis] += ( frametime * joy_accelscale.GetFloat() );
-
- if( controlEnvelope.envelopeScale[axis] > flMax )
- {
- controlEnvelope.envelopeScale[axis] = flMax;
- }
- }
- }
-
- x *= AutoAimDampening( input, axis, dist );
-
- if( axis == YAW && input != 0.0f && joy_display_input.GetBool() )
- {
- Msg("In:%f Out:%f Frametime:%f\n", input, x, frametime );
- }
-
- if( negative )
- {
- x *= -1;
- }
-
- return x;
-}
-
-//-----------------------------------------------
-//-----------------------------------------------
-static float ResponseCurveLook( int curve, float x, int axis, float otherAxis, float dist, float frametime )
-{
- switch( curve )
- {
- case 1://Promotion of acceleration
- return ResponseCurveLookAccelerated( x, axis, otherAxis, dist, frametime );
- break;
-
- default:
- return ResponseCurveLookDefault( x, axis, otherAxis, dist, frametime );
- break;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Advanced joystick setup
-//-----------------------------------------------------------------------------
-void CInput::Joystick_Advanced(void)
-{
- // called whenever an update is needed
- int i;
- DWORD dwTemp;
-
- if ( IsX360() )
- {
- // Xbox always uses a joystick
- in_joystick.SetValue( 1 );
- }
-
- // Initialize all the maps
- for ( i = 0; i < MAX_JOYSTICK_AXES; i++ )
- {
- m_rgAxes[i].AxisMap = GAME_AXIS_NONE;
- m_rgAxes[i].ControlMap = JOY_ABSOLUTE_AXIS;
- }
-
- if ( !joy_advanced.GetBool() )
- {
- // default joystick initialization
- // 2 axes only with joystick control
- m_rgAxes[JOY_AXIS_X].AxisMap = GAME_AXIS_YAW;
- m_rgAxes[JOY_AXIS_Y].AxisMap = GAME_AXIS_FORWARD;
- }
- else
- {
- if ( Q_stricmp( joy_name.GetString(), "joystick") != 0 )
- {
- // notify user of advanced controller
- Msg( "Using joystick '%s' configuration\n", joy_name.GetString() );
- }
-
- // advanced initialization here
- // data supplied by user via joy_axisn cvars
- dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisu.GetInt() : (DWORD)joy_advaxisx.GetInt();
- m_rgAxes[JOY_AXIS_X].AxisMap = dwTemp & 0x0000000f;
- m_rgAxes[JOY_AXIS_X].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
-
- DescribeJoystickAxis( "JOY_AXIS_X", &m_rgAxes[JOY_AXIS_X] );
-
- dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisr.GetInt() : (DWORD)joy_advaxisy.GetInt();
- m_rgAxes[JOY_AXIS_Y].AxisMap = dwTemp & 0x0000000f;
- m_rgAxes[JOY_AXIS_Y].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
-
- DescribeJoystickAxis( "JOY_AXIS_Y", &m_rgAxes[JOY_AXIS_Y] );
-
- dwTemp = (DWORD)joy_advaxisz.GetInt();
- m_rgAxes[JOY_AXIS_Z].AxisMap = dwTemp & 0x0000000f;
- m_rgAxes[JOY_AXIS_Z].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
-
- DescribeJoystickAxis( "JOY_AXIS_Z", &m_rgAxes[JOY_AXIS_Z] );
-
- dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisy.GetInt() : (DWORD)joy_advaxisr.GetInt();
- m_rgAxes[JOY_AXIS_R].AxisMap = dwTemp & 0x0000000f;
- m_rgAxes[JOY_AXIS_R].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
-
- DescribeJoystickAxis( "JOY_AXIS_R", &m_rgAxes[JOY_AXIS_R] );
-
- dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisx.GetInt() : (DWORD)joy_advaxisu.GetInt();
- m_rgAxes[JOY_AXIS_U].AxisMap = dwTemp & 0x0000000f;
- m_rgAxes[JOY_AXIS_U].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
-
- DescribeJoystickAxis( "JOY_AXIS_U", &m_rgAxes[JOY_AXIS_U] );
-
- dwTemp = (DWORD)joy_advaxisv.GetInt();
- m_rgAxes[JOY_AXIS_V].AxisMap = dwTemp & 0x0000000f;
- m_rgAxes[JOY_AXIS_V].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
-
- DescribeJoystickAxis( "JOY_AXIS_V", &m_rgAxes[JOY_AXIS_V] );
-
- Msg( "Advanced Joystick settings initialized\n" );
- }
-
- // If we have an xcontroller, load the cfg file if it hasn't been loaded.
- static ConVarRef var( "joy_xcontroller_found" );
- if ( var.IsValid() && var.GetBool() && in_joystick.GetBool() )
- {
- if ( joy_xcontroller_cfg_loaded.GetInt() < 2 )
- {
- engine->ClientCmd_Unrestricted( "exec 360controller.cfg" );
- if ( IsLinux () )
- {
- engine->ClientCmd_Unrestricted( "exec 360controller-linux.cfg" );
- }
- joy_xcontroller_cfg_loaded.SetValue( 2 );
- }
- }
- else if ( joy_xcontroller_cfg_loaded.GetInt() > 0 )
- {
- engine->ClientCmd_Unrestricted( "exec undo360controller.cfg" );
- joy_xcontroller_cfg_loaded.SetValue( 0 );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : index -
-// Output : char const
-//-----------------------------------------------------------------------------
-char const *CInput::DescribeAxis( int index )
-{
- switch ( index )
- {
- case GAME_AXIS_FORWARD:
- return "Forward";
- case GAME_AXIS_PITCH:
- return "Look";
- case GAME_AXIS_SIDE:
- return "Side";
- case GAME_AXIS_YAW:
- return "Turn";
- case GAME_AXIS_NONE:
- default:
- return "Unknown";
- }
-
- return "Unknown";
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *axis -
-// *mapping -
-//-----------------------------------------------------------------------------
-void CInput::DescribeJoystickAxis( char const *axis, joy_axis_t *mapping )
-{
- if ( !mapping->AxisMap )
- {
- Msg( "%s: unmapped\n", axis );
- }
- else
- {
- Msg( "%s: mapped to %s (%s)\n",
- axis,
- DescribeAxis( mapping->AxisMap ),
- mapping->ControlMap != 0 ? "relative" : "absolute" );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Allow joystick to issue key events
-// Not currently used - controller button events are pumped through the windprocs. KWD
-//-----------------------------------------------------------------------------
-void CInput::ControllerCommands( void )
-{
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Scales the raw analog value to lie withing the axis range (full range - deadzone )
-//-----------------------------------------------------------------------------
-float CInput::ScaleAxisValue( const float axisValue, const float axisThreshold )
-{
- // Xbox scales the range of all axes in the inputsystem. PC can't do that because each axis mapping
- // has a (potentially) unique threshold value. If all axes were restricted to a single threshold
- // as they are on the Xbox, this function could move to inputsystem and be slightly more optimal.
- float result = 0.f;
- if ( IsPC() )
- {
- if ( axisValue < -axisThreshold )
- {
- result = ( axisValue + axisThreshold ) / ( MAX_BUTTONSAMPLE - axisThreshold );
- }
- else if ( axisValue > axisThreshold )
- {
- result = ( axisValue - axisThreshold ) / ( MAX_BUTTONSAMPLE - axisThreshold );
- }
- }
- else
- {
- // IsXbox
- result = axisValue * ( 1.f / MAX_BUTTONSAMPLE );
- }
-
- return result;
-}
-
-
-void CInput::Joystick_SetSampleTime(float frametime)
-{
- m_flRemainingJoystickSampleTime = frametime;
-}
-
-float CInput::Joystick_GetForward( void )
-{
- return m_flPreviousJoystickForward;
-}
-
-float CInput::Joystick_GetSide( void )
-{
- return m_flPreviousJoystickSide;
-}
-
-float CInput::Joystick_GetPitch( void )
-{
- return m_flPreviousJoystickPitch;
-}
-
-float CInput::Joystick_GetYaw( void )
-{
- return m_flPreviousJoystickYaw;
-}
-
-//-----------------------------------------------------------------------------
-// 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 that the user wants to use the joystick
- if ( !in_joystick.GetInt() )
- return;
-
- // Reinitialize the 'advanced joystick' system if hotplugging has caused us toggle between some/none joysticks.
- bool haveJoysticks = ( inputsystem->GetJoystickCount() > 0 );
- if ( haveJoysticks != m_fHadJoysticks )
- {
- Joystick_Advanced();
- m_fHadJoysticks = haveJoysticks;
- }
-
- // Verify that a joystick is available
- if ( !haveJoysticks )
- 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;
- }
-
- m_flPreviousJoystickForward = ScaleAxisValue( gameAxes[GAME_AXIS_FORWARD].value, MAX_BUTTONSAMPLE * joy_forwardthreshold.GetFloat() );
- m_flPreviousJoystickSide = ScaleAxisValue( gameAxes[GAME_AXIS_SIDE].value, MAX_BUTTONSAMPLE * joy_sidethreshold.GetFloat() );
- m_flPreviousJoystickPitch = ScaleAxisValue( gameAxes[GAME_AXIS_PITCH].value, MAX_BUTTONSAMPLE * joy_pitchthreshold.GetFloat() );
- m_flPreviousJoystickYaw = ScaleAxisValue( gameAxes[GAME_AXIS_YAW].value, MAX_BUTTONSAMPLE * joy_yawthreshold.GetFloat() );
-
- // Skip out if vgui is active
- if ( vgui::surface()->IsCursorVisible() )
- return;
-
- // If we're inverting our joystick, do so
- if ( joy_inverty.GetBool() )
- {
- m_flPreviousJoystickPitch *= -1.0f;
- }
-
- // drive yaw, pitch and move like a screen relative platformer game
- if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
- {
- if ( m_flPreviousJoystickForward || m_flPreviousJoystickSide )
- {
- // apply turn control [ YAW ]
- // factor in the camera offset, so that the move direction is relative to the thirdperson camera
- viewangles[ YAW ] = RAD2DEG(atan2(-m_flPreviousJoystickSide, -m_flPreviousJoystickForward)) + g_ThirdPersonManager.GetCameraOffsetAngles()[ YAW ];
- engine->SetViewAngles( viewangles );
-
- // apply movement
- Vector2D moveDir( m_flPreviousJoystickForward, m_flPreviousJoystickSide );
- cmd->forwardmove += moveDir.Length() * cl_forwardspeed.GetFloat();
- }
-
- if ( m_flPreviousJoystickPitch || m_flPreviousJoystickYaw )
- {
- Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
-
- // look around with the camera
- vTempOffset[ PITCH ] += m_flPreviousJoystickPitch * joy_pitchsensitivity.GetFloat();
- vTempOffset[ YAW ] += m_flPreviousJoystickYaw * joy_yawsensitivity.GetFloat();
-
- g_ThirdPersonManager.SetCameraOffsetAngles( vTempOffset );
- }
-
- if ( m_flPreviousJoystickForward || m_flPreviousJoystickSide || m_flPreviousJoystickPitch || m_flPreviousJoystickYaw )
- {
- Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
-
- // update the ideal pitch and yaw
- cam_idealpitch.SetValue( vTempOffset[ PITCH ] - viewangles[ PITCH ] );
- cam_idealyaw.SetValue( vTempOffset[ 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, m_flPreviousJoystickForward, PITCH, joy_forwardsensitivity.GetFloat() );
- joyForwardMove += val * cl_forwardspeed.GetFloat();
- val = ResponseCurve( iResponseCurve, m_flPreviousJoystickSide, YAW, joy_sidesensitivity.GetFloat() );
- joySideMove += val * cl_sidespeed.GetFloat();
-
- Vector2D move( m_flPreviousJoystickYaw, m_flPreviousJoystickPitch );
- 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(), m_flPreviousJoystickYaw, YAW, m_flPreviousJoystickPitch, dist, frametime );
- angle = fAxisValue * joy_yawsensitivity.GetFloat() * aspeed * cl_yawspeed.GetFloat();
- }
- else
- {
- angle = m_flPreviousJoystickYaw * 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(), m_flPreviousJoystickPitch, PITCH, m_flPreviousJoystickYaw, dist, frametime );
- angle = fAxisValue * joy_pitchsensitivity.GetFloat() * aspeed * cl_pitchspeed.GetFloat();
- }
- else
- {
- angle = m_flPreviousJoystickPitch * joy_pitchsensitivity.GetFloat() * aspeed * 180.0;
- }
- viewangles[PITCH] += angle;
- cmd->mousedy = angle;
- view->StopPitchDrift();
- if( m_flPreviousJoystickPitch == 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 );
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Joystick handling function
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//===========================================================================//
+
+#include "cbase.h"
+#include "basehandle.h"
+#include "utlvector.h"
+#include "cdll_client_int.h"
+#include "cdll_util.h"
+#include "kbutton.h"
+#include "usercmd.h"
+#include "iclientvehicle.h"
+#include "input.h"
+#include "iviewrender.h"
+#include "convar.h"
+#include "hud.h"
+#include "vgui/ISurface.h"
+#include "vgui_controls/Controls.h"
+#include "vgui/Cursor.h"
+#include "tier0/icommandline.h"
+#include "inputsystem/iinputsystem.h"
+#include "inputsystem/ButtonCode.h"
+#include "math.h"
+#include "tier1/convar_serverbounded.h"
+#include "cam_thirdperson.h"
+
+#if defined( _X360 )
+#include "xbox/xbox_win32stubs.h"
+#else
+#include "../common/xbox/xboxstubs.h"
+#endif
+
+#ifdef HL2_CLIENT_DLL
+// FIXME: Autoaim support needs to be moved from HL2_DLL to the client dll, so this include should be c_baseplayer.h
+#include "c_basehlplayer.h"
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+// Control like a joystick
+#define JOY_ABSOLUTE_AXIS 0x00000000
+// Control like a mouse, spinner, trackball
+#define JOY_RELATIVE_AXIS 0x00000010
+
+// Axis mapping
+static ConVar joy_name( "joy_name", "joystick", FCVAR_ARCHIVE );
+static ConVar joy_advanced( "joy_advanced", "1", FCVAR_ARCHIVE );
+static ConVar joy_advaxisx( "joy_advaxisx", "4", FCVAR_ARCHIVE );
+static ConVar joy_advaxisy( "joy_advaxisy", "2", FCVAR_ARCHIVE );
+static ConVar joy_advaxisz( "joy_advaxisz", "0", FCVAR_ARCHIVE );
+static ConVar joy_advaxisr( "joy_advaxisr", "1", FCVAR_ARCHIVE );
+static ConVar joy_advaxisu( "joy_advaxisu", "3", FCVAR_ARCHIVE );
+static ConVar joy_advaxisv( "joy_advaxisv", "0", FCVAR_ARCHIVE );
+
+// Basic "dead zone" and sensitivity
+static ConVar joy_forwardthreshold( "joy_forwardthreshold", "0.15", FCVAR_ARCHIVE );
+static ConVar joy_sidethreshold( "joy_sidethreshold", "0.15", FCVAR_ARCHIVE );
+static ConVar joy_pitchthreshold( "joy_pitchthreshold", "0.15", FCVAR_ARCHIVE );
+static ConVar joy_yawthreshold( "joy_yawthreshold", "0.15", FCVAR_ARCHIVE );
+static ConVar joy_forwardsensitivity( "joy_forwardsensitivity", "-1", FCVAR_ARCHIVE );
+static ConVar joy_sidesensitivity( "joy_sidesensitivity", "1", FCVAR_ARCHIVE );
+static ConVar joy_pitchsensitivity( "joy_pitchsensitivity", "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX );
+static ConVar joy_yawsensitivity( "joy_yawsensitivity", "-1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX );
+
+// Advanced sensitivity and response
+static ConVar joy_response_move( "joy_response_move", "1", FCVAR_ARCHIVE, "'Movement' stick response mode: 0=Linear, 1=quadratic, 2=cubic, 3=quadratic extreme, 4=power function(i.e., pow(x,1/sensitivity)), 5=two-stage" );
+ConVar joy_response_move_vehicle("joy_response_move_vehicle", "6");
+static ConVar joy_response_look( "joy_response_look", "0", FCVAR_ARCHIVE, "'Look' stick response mode: 0=Default, 1=Acceleration Promotion" );
+static ConVar joy_lowend( "joy_lowend", "1", FCVAR_ARCHIVE );
+static ConVar joy_lowmap( "joy_lowmap", "1", FCVAR_ARCHIVE );
+static ConVar joy_accelscale( "joy_accelscale", "0.6", FCVAR_ARCHIVE);
+static ConVar joy_accelmax( "joy_accelmax", "1.0", FCVAR_ARCHIVE);
+static ConVar joy_autoaimdampenrange( "joy_autoaimdampenrange", "0", FCVAR_ARCHIVE, "The stick range where autoaim dampening is applied. 0 = off" );
+static ConVar joy_autoaimdampen( "joy_autoaimdampen", "0", FCVAR_ARCHIVE, "How much to scale user stick input when the gun is pointing at a valid target." );
+
+static ConVar joy_vehicle_turn_lowend("joy_vehicle_turn_lowend", "0.7");
+static ConVar joy_vehicle_turn_lowmap("joy_vehicle_turn_lowmap", "0.4");
+
+
+// Misc
+static ConVar joy_diagonalpov( "joy_diagonalpov", "0", FCVAR_ARCHIVE, "POV manipulator operates on diagonal axes, too." );
+static ConVar joy_display_input("joy_display_input", "0", FCVAR_ARCHIVE);
+static ConVar joy_wwhack2( "joy_wingmanwarrior_turnhack", "0", FCVAR_ARCHIVE, "Wingman warrior hack related to turn axes." );
+ConVar joy_autosprint("joy_autosprint", "0", 0, "Automatically sprint when moving with an analog joystick" );
+
+static ConVar joy_inverty("joy_inverty", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "Whether to invert the Y axis of the joystick for looking." );
+
+// XBox Defaults
+static ConVar joy_yawsensitivity_default( "joy_yawsensitivity_default", "-1.25", FCVAR_NONE );
+static ConVar joy_pitchsensitivity_default( "joy_pitchsensitivity_default", "-1.0", FCVAR_NONE );
+static ConVar option_duck_method_default( "option_duck_method_default", "1.0", FCVAR_NONE );
+static ConVar joy_inverty_default( "joy_inverty_default", "0", FCVAR_ARCHIVE_XBOX ); // Extracted & saved from profile
+static ConVar joy_movement_stick_default( "joy_movement_stick_default", "0", FCVAR_ARCHIVE_XBOX ); // Extracted & saved from profile
+static ConVar sv_stickysprint_default( "sv_stickysprint_default", "0", FCVAR_NONE );
+
+void joy_movement_stick_Callback( IConVar *var, const char *pOldString, float flOldValue )
+{
+ engine->ClientCmd( "joyadvancedupdate" );
+}
+static ConVar joy_movement_stick("joy_movement_stick", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "Which stick controls movement (0 is left stick)", joy_movement_stick_Callback );
+
+static ConVar joy_xcontroller_cfg_loaded( "joy_xcontroller_cfg_loaded", "0", FCVAR_ARCHIVE, "If 0, the 360controller.cfg file will be executed on startup & option changes." );
+
+extern ConVar lookspring;
+extern ConVar cl_forwardspeed;
+extern ConVar lookstrafe;
+extern ConVar in_joystick;
+extern ConVar_ServerBounded *m_pitch;
+extern ConVar l_pitchspeed;
+extern ConVar cl_sidespeed;
+extern ConVar cl_yawspeed;
+extern ConVar cl_pitchdown;
+extern ConVar cl_pitchup;
+extern ConVar cl_pitchspeed;
+
+extern ConVar cam_idealpitch;
+extern ConVar cam_idealyaw;
+extern ConVar thirdperson_platformer;
+extern ConVar thirdperson_screenspace;
+
+//-----------------------------------------------------------------
+// Purpose: Returns true if there's an active joystick connected.
+//-----------------------------------------------------------------
+bool CInput::EnableJoystickMode()
+{
+ return IsConsole() || in_joystick.GetBool();
+}
+
+
+//-----------------------------------------------
+// Response curve function for the move axes
+//-----------------------------------------------
+static float ResponseCurve( int curve, float x, int axis, float sensitivity )
+{
+ switch ( curve )
+ {
+ case 1:
+ // quadratic
+ if ( x < 0 )
+ return -(x*x) * sensitivity;
+ return x*x * sensitivity;
+
+ case 2:
+ // cubic
+ return x*x*x*sensitivity;
+
+ case 3:
+ {
+ // quadratic extreme
+ float extreme = 1.0f;
+ if ( fabs( x ) >= 0.95f )
+ {
+ extreme = 1.5f;
+ }
+ if ( x < 0 )
+ return -extreme * x*x*sensitivity;
+ return extreme * x*x*sensitivity;
+ }
+ case 4:
+ {
+ float flScale = sensitivity < 0.0f ? -1.0f : 1.0f;
+
+ sensitivity = clamp( fabs( sensitivity ), 1.0e-8f, 1000.0f );
+
+ float oneOverSens = 1.0f / sensitivity;
+
+ if ( x < 0.0f )
+ {
+ flScale = -flScale;
+ }
+
+ float retval = clamp( powf( fabs( x ), oneOverSens ), 0.0f, 1.0f );
+ return retval * flScale;
+ }
+ break;
+ case 5:
+ {
+ float out = x;
+
+ if( fabs(out) <= 0.6f )
+ {
+ out *= 0.5f;
+ }
+
+ out = out * sensitivity;
+ return out;
+ }
+ break;
+ case 6: // Custom for driving a vehicle!
+ {
+ if( axis == YAW )
+ {
+ // This code only wants to affect YAW axis (the left and right axis), which
+ // is used for turning in the car. We fall-through and use a linear curve on
+ // the PITCH axis, which is the vehicle's throttle. REALLY, these are the 'forward'
+ // and 'side' axes, but we don't have constants for those, so we re-use the same
+ // axis convention as the look stick. (sjb)
+ float sign = 1;
+
+ if( x < 0.0 )
+ sign = -1;
+
+ x = fabs(x);
+
+ if( x <= joy_vehicle_turn_lowend.GetFloat() )
+ x = RemapVal( x, 0.0f, joy_vehicle_turn_lowend.GetFloat(), 0.0f, joy_vehicle_turn_lowmap.GetFloat() );
+ else
+ x = RemapVal( x, joy_vehicle_turn_lowend.GetFloat(), 1.0f, joy_vehicle_turn_lowmap.GetFloat(), 1.0f );
+
+ return x * sensitivity * sign;
+ }
+ //else
+ // fall through and just return x*sensitivity below (as if using default curve)
+ }
+ }
+
+ // linear
+ return x*sensitivity;
+}
+
+
+//-----------------------------------------------
+// If we have a valid autoaim target, dampen the
+// player's stick input if it is moving away from
+// the target.
+//
+// This assists the player staying on target.
+//-----------------------------------------------
+float AutoAimDampening( float x, int axis, float dist )
+{
+ // FIXME: Autoaim support needs to be moved from HL2_DLL to the client dll, so all games can use it.
+#ifdef HL2_CLIENT_DLL
+ // Help the user stay on target if the feature is enabled and the user
+ // is not making a gross stick movement.
+ if( joy_autoaimdampen.GetFloat() > 0.0f && fabs(x) < joy_autoaimdampenrange.GetFloat() )
+ {
+ // Get the HL2 player
+ C_BaseHLPlayer *pLocalPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
+
+ if( pLocalPlayer )
+ {
+ // Get the autoaim target
+ if( pLocalPlayer->m_HL2Local.m_bAutoAimTarget )
+ {
+ return joy_autoaimdampen.GetFloat();
+ }
+ }
+ }
+#endif
+ return 1.0f;// No dampening.
+}
+
+
+//-----------------------------------------------
+// This structure holds persistent information used
+// to make decisions about how to modulate analog
+// stick input.
+//-----------------------------------------------
+typedef struct
+{
+ float envelopeScale[2];
+ bool peggedAxis[2];
+ bool axisPeggedDir[2];
+} envelope_t;
+
+envelope_t controlEnvelope;
+
+//-----------------------------------------------
+// Response curve function specifically for the
+// 'look' analog stick.
+//
+// when AXIS == YAW, otherAxisValue contains the
+// value for the pitch of the control stick, and
+// vice-versa.
+//-----------------------------------------------
+ConVar joy_pegged("joy_pegged", "0.75");// Once the stick is pushed this far, it's assumed pegged.
+ConVar joy_virtual_peg("joy_virtual_peg", "0");
+static float ResponseCurveLookDefault( float x, int axis, float otherAxis, float dist, float frametime )
+{
+ float input = x;
+
+ bool bStickIsPhysicallyPegged = ( dist >= joy_pegged.GetFloat() );
+
+ // Make X positive to make things easier, just remember whether we have to flip it back!
+ bool negative = false;
+ if( x < 0.0f )
+ {
+ negative = true;
+ x *= -1;
+ }
+
+ if( axis == YAW && joy_virtual_peg.GetBool() )
+ {
+ if( x >= 0.95f )
+ {
+ // User has pegged the stick
+ controlEnvelope.peggedAxis[axis] = true;
+ controlEnvelope.axisPeggedDir[axis] = negative;
+ }
+
+ if( controlEnvelope.peggedAxis[axis] == true )
+ {
+ // User doesn't have the stick pegged on this axis, but they used to.
+ // If the stick is physically pegged, pretend this axis is still pegged.
+ if( bStickIsPhysicallyPegged && negative == controlEnvelope.axisPeggedDir[axis] )
+ {
+ // If the user still has the stick physically pegged and hasn't changed direction on
+ // this axis, keep pretending they have the stick pegged on this axis.
+ x = 1.0f;
+ }
+ else
+ {
+ controlEnvelope.peggedAxis[axis] = false;
+ }
+ }
+ }
+
+ // Perform the two-stage mapping.
+ if( x > joy_lowend.GetFloat() )
+ {
+ float highmap = 1.0f - joy_lowmap.GetFloat();
+ float xNormal = x - joy_lowend.GetFloat();
+
+ float factor = xNormal / ( 1.0f - joy_lowend.GetFloat() );
+ x = joy_lowmap.GetFloat() + (highmap * factor);
+
+ // Accelerate.
+ if( controlEnvelope.envelopeScale[axis] < 1.0f )
+ {
+ controlEnvelope.envelopeScale[axis] += ( frametime * joy_accelscale.GetFloat() );
+ if( controlEnvelope.envelopeScale[axis] > 1.0f )
+ {
+ controlEnvelope.envelopeScale[axis] = 1.0f;
+ }
+ }
+
+ float delta = x - joy_lowmap.GetFloat();
+ x = joy_lowmap.GetFloat() + (delta * controlEnvelope.envelopeScale[axis]);
+ }
+ else
+ {
+ // Shut off acceleration
+ controlEnvelope.envelopeScale[axis] = 0.0f;
+ float factor = x / joy_lowend.GetFloat();
+ x = joy_lowmap.GetFloat() * factor;
+ }
+
+ x *= AutoAimDampening( input, axis, dist );
+
+ if( axis == YAW && x > 0.0f && joy_display_input.GetBool() )
+ {
+ Msg("In:%f Out:%f Frametime:%f\n", input, x, frametime );
+ }
+
+ if( negative )
+ {
+ x *= -1;
+ }
+
+ return x;
+}
+
+ConVar joy_accel_filter("joy_accel_filter", "0.2");// If the non-accelerated axis is pushed farther than this, then accelerate it, too.
+static float ResponseCurveLookAccelerated( float x, int axis, float otherAxis, float dist, float frametime )
+{
+ float input = x;
+
+ float flJoyDist = ( sqrt(x*x + otherAxis * otherAxis) );
+ bool bIsPegged = ( flJoyDist>= joy_pegged.GetFloat() );
+
+ // Make X positive to make arithmetic easier for the rest of this function, and
+ // remember whether we have to flip it back!
+ bool negative = false;
+ if( x < 0.0f )
+ {
+ negative = true;
+ x *= -1;
+ }
+
+ // Perform the two-stage mapping.
+ bool bDoAcceleration = false;// Assume we won't accelerate the input
+
+ if( bIsPegged && x > joy_accel_filter.GetFloat() )
+ {
+ // Accelerate this axis, since the stick is pegged and
+ // this axis is pressed farther than the acceleration filter
+ // Take the lowmap value, or the input, whichever is higher, since
+ // we don't necesarily know whether this is the axis which is pegged
+ x = MAX( joy_lowmap.GetFloat(), x );
+ bDoAcceleration = true;
+ }
+ else
+ {
+ // Joystick is languishing in the low-end, turn off acceleration.
+ controlEnvelope.envelopeScale[axis] = 0.0f;
+ float factor = x / joy_lowend.GetFloat();
+ x = joy_lowmap.GetFloat() * factor;
+ }
+
+ if( bDoAcceleration )
+ {
+ float flMax = joy_accelmax.GetFloat();
+ if( controlEnvelope.envelopeScale[axis] < flMax )
+ {
+ float delta = x - joy_lowmap.GetFloat();
+ x = joy_lowmap.GetFloat() + (delta * controlEnvelope.envelopeScale[axis]);
+ controlEnvelope.envelopeScale[axis] += ( frametime * joy_accelscale.GetFloat() );
+
+ if( controlEnvelope.envelopeScale[axis] > flMax )
+ {
+ controlEnvelope.envelopeScale[axis] = flMax;
+ }
+ }
+ }
+
+ x *= AutoAimDampening( input, axis, dist );
+
+ if( axis == YAW && input != 0.0f && joy_display_input.GetBool() )
+ {
+ Msg("In:%f Out:%f Frametime:%f\n", input, x, frametime );
+ }
+
+ if( negative )
+ {
+ x *= -1;
+ }
+
+ return x;
+}
+
+//-----------------------------------------------
+//-----------------------------------------------
+static float ResponseCurveLook( int curve, float x, int axis, float otherAxis, float dist, float frametime )
+{
+ switch( curve )
+ {
+ case 1://Promotion of acceleration
+ return ResponseCurveLookAccelerated( x, axis, otherAxis, dist, frametime );
+ break;
+
+ default:
+ return ResponseCurveLookDefault( x, axis, otherAxis, dist, frametime );
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Advanced joystick setup
+//-----------------------------------------------------------------------------
+void CInput::Joystick_Advanced(void)
+{
+ // called whenever an update is needed
+ int i;
+ DWORD dwTemp;
+
+ if ( IsX360() )
+ {
+ // Xbox always uses a joystick
+ in_joystick.SetValue( 1 );
+ }
+
+ // Initialize all the maps
+ for ( i = 0; i < MAX_JOYSTICK_AXES; i++ )
+ {
+ m_rgAxes[i].AxisMap = GAME_AXIS_NONE;
+ m_rgAxes[i].ControlMap = JOY_ABSOLUTE_AXIS;
+ }
+
+ if ( !joy_advanced.GetBool() )
+ {
+ // default joystick initialization
+ // 2 axes only with joystick control
+ m_rgAxes[JOY_AXIS_X].AxisMap = GAME_AXIS_YAW;
+ m_rgAxes[JOY_AXIS_Y].AxisMap = GAME_AXIS_FORWARD;
+ }
+ else
+ {
+ if ( Q_stricmp( joy_name.GetString(), "joystick") != 0 )
+ {
+ // notify user of advanced controller
+ Msg( "Using joystick '%s' configuration\n", joy_name.GetString() );
+ }
+
+ // advanced initialization here
+ // data supplied by user via joy_axisn cvars
+ dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisu.GetInt() : (DWORD)joy_advaxisx.GetInt();
+ m_rgAxes[JOY_AXIS_X].AxisMap = dwTemp & 0x0000000f;
+ m_rgAxes[JOY_AXIS_X].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
+
+ DescribeJoystickAxis( "JOY_AXIS_X", &m_rgAxes[JOY_AXIS_X] );
+
+ dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisr.GetInt() : (DWORD)joy_advaxisy.GetInt();
+ m_rgAxes[JOY_AXIS_Y].AxisMap = dwTemp & 0x0000000f;
+ m_rgAxes[JOY_AXIS_Y].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
+
+ DescribeJoystickAxis( "JOY_AXIS_Y", &m_rgAxes[JOY_AXIS_Y] );
+
+ dwTemp = (DWORD)joy_advaxisz.GetInt();
+ m_rgAxes[JOY_AXIS_Z].AxisMap = dwTemp & 0x0000000f;
+ m_rgAxes[JOY_AXIS_Z].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
+
+ DescribeJoystickAxis( "JOY_AXIS_Z", &m_rgAxes[JOY_AXIS_Z] );
+
+ dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisy.GetInt() : (DWORD)joy_advaxisr.GetInt();
+ m_rgAxes[JOY_AXIS_R].AxisMap = dwTemp & 0x0000000f;
+ m_rgAxes[JOY_AXIS_R].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
+
+ DescribeJoystickAxis( "JOY_AXIS_R", &m_rgAxes[JOY_AXIS_R] );
+
+ dwTemp = ( joy_movement_stick.GetBool() ) ? (DWORD)joy_advaxisx.GetInt() : (DWORD)joy_advaxisu.GetInt();
+ m_rgAxes[JOY_AXIS_U].AxisMap = dwTemp & 0x0000000f;
+ m_rgAxes[JOY_AXIS_U].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
+
+ DescribeJoystickAxis( "JOY_AXIS_U", &m_rgAxes[JOY_AXIS_U] );
+
+ dwTemp = (DWORD)joy_advaxisv.GetInt();
+ m_rgAxes[JOY_AXIS_V].AxisMap = dwTemp & 0x0000000f;
+ m_rgAxes[JOY_AXIS_V].ControlMap = dwTemp & JOY_RELATIVE_AXIS;
+
+ DescribeJoystickAxis( "JOY_AXIS_V", &m_rgAxes[JOY_AXIS_V] );
+
+ Msg( "Advanced Joystick settings initialized\n" );
+ }
+
+ // If we have an xcontroller, load the cfg file if it hasn't been loaded.
+ static ConVarRef var( "joy_xcontroller_found" );
+ if ( var.IsValid() && var.GetBool() && in_joystick.GetBool() )
+ {
+ if ( joy_xcontroller_cfg_loaded.GetInt() < 2 )
+ {
+ engine->ClientCmd_Unrestricted( "exec 360controller.cfg" );
+ if ( IsLinux () )
+ {
+ engine->ClientCmd_Unrestricted( "exec 360controller-linux.cfg" );
+ }
+ joy_xcontroller_cfg_loaded.SetValue( 2 );
+ }
+ }
+ else if ( joy_xcontroller_cfg_loaded.GetInt() > 0 )
+ {
+ engine->ClientCmd_Unrestricted( "exec undo360controller.cfg" );
+ joy_xcontroller_cfg_loaded.SetValue( 0 );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : index -
+// Output : char const
+//-----------------------------------------------------------------------------
+char const *CInput::DescribeAxis( int index )
+{
+ switch ( index )
+ {
+ case GAME_AXIS_FORWARD:
+ return "Forward";
+ case GAME_AXIS_PITCH:
+ return "Look";
+ case GAME_AXIS_SIDE:
+ return "Side";
+ case GAME_AXIS_YAW:
+ return "Turn";
+ case GAME_AXIS_NONE:
+ default:
+ return "Unknown";
+ }
+
+ return "Unknown";
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *axis -
+// *mapping -
+//-----------------------------------------------------------------------------
+void CInput::DescribeJoystickAxis( char const *axis, joy_axis_t *mapping )
+{
+ if ( !mapping->AxisMap )
+ {
+ Msg( "%s: unmapped\n", axis );
+ }
+ else
+ {
+ Msg( "%s: mapped to %s (%s)\n",
+ axis,
+ DescribeAxis( mapping->AxisMap ),
+ mapping->ControlMap != 0 ? "relative" : "absolute" );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Allow joystick to issue key events
+// Not currently used - controller button events are pumped through the windprocs. KWD
+//-----------------------------------------------------------------------------
+void CInput::ControllerCommands( void )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Scales the raw analog value to lie withing the axis range (full range - deadzone )
+//-----------------------------------------------------------------------------
+float CInput::ScaleAxisValue( const float axisValue, const float axisThreshold )
+{
+ // Xbox scales the range of all axes in the inputsystem. PC can't do that because each axis mapping
+ // has a (potentially) unique threshold value. If all axes were restricted to a single threshold
+ // as they are on the Xbox, this function could move to inputsystem and be slightly more optimal.
+ float result = 0.f;
+ if ( IsPC() )
+ {
+ if ( axisValue < -axisThreshold )
+ {
+ result = ( axisValue + axisThreshold ) / ( MAX_BUTTONSAMPLE - axisThreshold );
+ }
+ else if ( axisValue > axisThreshold )
+ {
+ result = ( axisValue - axisThreshold ) / ( MAX_BUTTONSAMPLE - axisThreshold );
+ }
+ }
+ else
+ {
+ // IsXbox
+ result = axisValue * ( 1.f / MAX_BUTTONSAMPLE );
+ }
+
+ return result;
+}
+
+
+void CInput::Joystick_SetSampleTime(float frametime)
+{
+ m_flRemainingJoystickSampleTime = frametime;
+}
+
+float CInput::Joystick_GetForward( void )
+{
+ return m_flPreviousJoystickForward;
+}
+
+float CInput::Joystick_GetSide( void )
+{
+ return m_flPreviousJoystickSide;
+}
+
+float CInput::Joystick_GetPitch( void )
+{
+ return m_flPreviousJoystickPitch;
+}
+
+float CInput::Joystick_GetYaw( void )
+{
+ return m_flPreviousJoystickYaw;
+}
+
+//-----------------------------------------------------------------------------
+// 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 that the user wants to use the joystick
+ if ( !in_joystick.GetInt() )
+ return;
+
+ // Reinitialize the 'advanced joystick' system if hotplugging has caused us toggle between some/none joysticks.
+ bool haveJoysticks = ( inputsystem->GetJoystickCount() > 0 );
+ if ( haveJoysticks != m_fHadJoysticks )
+ {
+ Joystick_Advanced();
+ m_fHadJoysticks = haveJoysticks;
+ }
+
+ // Verify that a joystick is available
+ if ( !haveJoysticks )
+ 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;
+ }
+
+ m_flPreviousJoystickForward = ScaleAxisValue( gameAxes[GAME_AXIS_FORWARD].value, MAX_BUTTONSAMPLE * joy_forwardthreshold.GetFloat() );
+ m_flPreviousJoystickSide = ScaleAxisValue( gameAxes[GAME_AXIS_SIDE].value, MAX_BUTTONSAMPLE * joy_sidethreshold.GetFloat() );
+ m_flPreviousJoystickPitch = ScaleAxisValue( gameAxes[GAME_AXIS_PITCH].value, MAX_BUTTONSAMPLE * joy_pitchthreshold.GetFloat() );
+ m_flPreviousJoystickYaw = ScaleAxisValue( gameAxes[GAME_AXIS_YAW].value, MAX_BUTTONSAMPLE * joy_yawthreshold.GetFloat() );
+
+ // Skip out if vgui is active
+ if ( vgui::surface()->IsCursorVisible() )
+ return;
+
+ // If we're inverting our joystick, do so
+ if ( joy_inverty.GetBool() )
+ {
+ m_flPreviousJoystickPitch *= -1.0f;
+ }
+
+ // drive yaw, pitch and move like a screen relative platformer game
+ if ( CAM_IsThirdPerson() && thirdperson_platformer.GetInt() )
+ {
+ if ( m_flPreviousJoystickForward || m_flPreviousJoystickSide )
+ {
+ // apply turn control [ YAW ]
+ // factor in the camera offset, so that the move direction is relative to the thirdperson camera
+ viewangles[ YAW ] = RAD2DEG(atan2(-m_flPreviousJoystickSide, -m_flPreviousJoystickForward)) + g_ThirdPersonManager.GetCameraOffsetAngles()[ YAW ];
+ engine->SetViewAngles( viewangles );
+
+ // apply movement
+ Vector2D moveDir( m_flPreviousJoystickForward, m_flPreviousJoystickSide );
+ cmd->forwardmove += moveDir.Length() * cl_forwardspeed.GetFloat();
+ }
+
+ if ( m_flPreviousJoystickPitch || m_flPreviousJoystickYaw )
+ {
+ Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
+
+ // look around with the camera
+ vTempOffset[ PITCH ] += m_flPreviousJoystickPitch * joy_pitchsensitivity.GetFloat();
+ vTempOffset[ YAW ] += m_flPreviousJoystickYaw * joy_yawsensitivity.GetFloat();
+
+ g_ThirdPersonManager.SetCameraOffsetAngles( vTempOffset );
+ }
+
+ if ( m_flPreviousJoystickForward || m_flPreviousJoystickSide || m_flPreviousJoystickPitch || m_flPreviousJoystickYaw )
+ {
+ Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles();
+
+ // update the ideal pitch and yaw
+ cam_idealpitch.SetValue( vTempOffset[ PITCH ] - viewangles[ PITCH ] );
+ cam_idealyaw.SetValue( vTempOffset[ 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, m_flPreviousJoystickForward, PITCH, joy_forwardsensitivity.GetFloat() );
+ joyForwardMove += val * cl_forwardspeed.GetFloat();
+ val = ResponseCurve( iResponseCurve, m_flPreviousJoystickSide, YAW, joy_sidesensitivity.GetFloat() );
+ joySideMove += val * cl_sidespeed.GetFloat();
+
+ Vector2D move( m_flPreviousJoystickYaw, m_flPreviousJoystickPitch );
+ 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(), m_flPreviousJoystickYaw, YAW, m_flPreviousJoystickPitch, dist, frametime );
+ angle = fAxisValue * joy_yawsensitivity.GetFloat() * aspeed * cl_yawspeed.GetFloat();
+ }
+ else
+ {
+ angle = m_flPreviousJoystickYaw * 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(), m_flPreviousJoystickPitch, PITCH, m_flPreviousJoystickYaw, dist, frametime );
+ angle = fAxisValue * joy_pitchsensitivity.GetFloat() * aspeed * cl_pitchspeed.GetFloat();
+ }
+ else
+ {
+ angle = m_flPreviousJoystickPitch * joy_pitchsensitivity.GetFloat() * aspeed * 180.0;
+ }
+ viewangles[PITCH] += angle;
+ cmd->mousedy = angle;
+ view->StopPitchDrift();
+ if( m_flPreviousJoystickPitch == 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 );
+}