Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1079 lines
32 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "hud.h"
  9. #include "kbutton.h"
  10. #include "input.h"
  11. #ifdef PORTAL2
  12. #include "c_portal_player.h"
  13. #include "portal_shareddefs.h"
  14. #endif
  15. #include <vgui/IInput.h>
  16. #include "vgui_controls/Controls.h"
  17. #include "tier0/vprof.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. //-------------------------------------------------- Constants
  21. #define CAM_MIN_DIST 30.0
  22. #define CAM_ANGLE_MOVE .5
  23. #define MAX_ANGLE_DIFF 10.0
  24. #define PITCH_MAX 90.0
  25. #define PITCH_MIN 0
  26. #define YAW_MAX 135.0
  27. #define YAW_MIN -135.0
  28. #define DIST 2
  29. #define CAM_HULL_OFFSET 9.0 // the size of the bounding hull used for collision checking
  30. static Vector CAM_HULL_MIN(-CAM_HULL_OFFSET,-CAM_HULL_OFFSET,-CAM_HULL_OFFSET);
  31. static Vector CAM_HULL_MAX( CAM_HULL_OFFSET, CAM_HULL_OFFSET, CAM_HULL_OFFSET);
  32. //-------------------------------------------------- Global Variables
  33. static ConVar cam_snapto( "cam_snapto", "0", FCVAR_ARCHIVE ); // snap to thirdperson view
  34. static ConVar cam_ideallag( "cam_ideallag", "4.0", FCVAR_ARCHIVE, "Amount of lag used when matching offset to ideal angles in thirdperson view" );
  35. static ConVar cam_idealdelta( "cam_idealdelta", "4.0", FCVAR_ARCHIVE, "Controls the speed when matching offset to ideal angles in thirdperson view" );
  36. ConVar cam_idealyaw( "cam_idealyaw", "0", FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE ); // thirdperson yaw
  37. ConVar cam_idealpitch( "cam_idealpitch", "0", FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE ); // thirperson pitch
  38. ConVar cam_idealdist( "cam_idealdist", "150", FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE ); // thirdperson distance
  39. ConVar cam_idealdistright( "cam_idealdistright", "0", FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE ); // thirdperson distance right;
  40. ConVar cam_idealdistup( "cam_idealdistup", "0", FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE ); // thirdperson distance up;
  41. static ConVar cam_collision( "cam_collision", "1", FCVAR_ARCHIVE | FCVAR_SERVER_CAN_EXECUTE, "When in thirdperson and cam_collision is set to 1, an attempt is made to keep the camera from passing though walls." );
  42. static ConVar cam_showangles( "cam_showangles", "0", FCVAR_CHEAT, "When in thirdperson, print viewangles/idealangles/cameraoffsets to the console." );
  43. static ConVar c_maxpitch( "c_maxpitch", "90", FCVAR_ARCHIVE );
  44. static ConVar c_minpitch( "c_minpitch", "0", FCVAR_ARCHIVE );
  45. static ConVar c_maxyaw( "c_maxyaw", "135", FCVAR_ARCHIVE );
  46. static ConVar c_minyaw( "c_minyaw", "-135", FCVAR_ARCHIVE );
  47. static ConVar c_maxdistance( "c_maxdistance", "200", FCVAR_ARCHIVE );
  48. static ConVar c_mindistance( "c_mindistance", "30", FCVAR_ARCHIVE );
  49. static ConVar c_orthowidth( "c_orthowidth", "100", FCVAR_ARCHIVE );
  50. static ConVar c_orthoheight( "c_orthoheight", "100", FCVAR_ARCHIVE );
  51. static ConVar c_thirdpersonshoulder( "c_thirdpersonshoulder", "false", FCVAR_ARCHIVE ); // flag to indicate when we are using thirdperson-shoulder
  52. static ConVar c_thirdpersonshoulderoffset( "c_thirdpersonshoulderoffset", "20.0", FCVAR_ARCHIVE ); // camera right offset for thirdperson-shoulder
  53. static ConVar c_thirdpersonshoulderdist( "c_thirdpersonshoulderdist", "40.0", FCVAR_ARCHIVE ); // camera distance from the player when in thirdperson-shoulder
  54. static ConVar c_thirdpersonshoulderheight( "c_thirdpersonshoulderheight", "5.0", FCVAR_ARCHIVE ); // camera height above the player
  55. static ConVar c_thirdpersonshoulderaimdist( "c_thirdpersonshoulderaimdist", "120.0", FCVAR_ARCHIVE ); // the distance in front of the player to focus the camera
  56. static kbutton_t cam_pitchup, cam_pitchdown, cam_yawleft, cam_yawright;
  57. static kbutton_t cam_in, cam_out; // -- "cam_move" is unused
  58. extern const ConVar *sv_cheats;
  59. extern ConVar in_forceuser;
  60. extern ConVar sv_allow_thirdperson;
  61. CON_COMMAND_F( cam_command, "Tells camera to change modes", FCVAR_CHEAT )
  62. {
  63. if ( args.ArgC() < 2 )
  64. {
  65. Msg( "cam_command <0, 1, or 2>\n" );
  66. return;
  67. }
  68. input->CAM_Command( Q_atoi( args.Arg( 1 ) ) );
  69. }
  70. // ==============================
  71. // CAM_ToThirdPerson
  72. // ==============================
  73. void CAM_ToThirdPerson(void)
  74. {
  75. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  76. input->CAM_ToThirdPerson();
  77. // Let the local player know
  78. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  79. if ( localPlayer )
  80. {
  81. localPlayer->ThirdPersonSwitch( true );
  82. }
  83. }
  84. static bool & Is_CAM_ThirdPerson_MayaMode(void)
  85. {
  86. static bool s_b_CAM_ThirdPerson_MayaMode = false;
  87. return s_b_CAM_ThirdPerson_MayaMode;
  88. }
  89. void CAM_ToThirdPerson_MayaMode(void)
  90. {
  91. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  92. bool &rb = Is_CAM_ThirdPerson_MayaMode();
  93. rb = !rb;
  94. }
  95. // ==============================
  96. // CAM_ToFirstPerson
  97. // ==============================
  98. void CAM_ToFirstPerson(void)
  99. {
  100. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  101. input->CAM_ToFirstPerson();
  102. // Let the local player know
  103. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  104. if ( localPlayer )
  105. {
  106. localPlayer->ThirdPersonSwitch( false );
  107. }
  108. c_thirdpersonshoulder.SetValue( false );
  109. cam_idealdist.SetValue( cam_idealdist.GetDefault() );
  110. }
  111. /*
  112. ==============================
  113. CAM_ToThirdPersonShoulder
  114. ==============================
  115. */
  116. void CAM_ToThirdPersonShoulder(void)
  117. {
  118. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  119. input->CAM_ToThirdPersonShoulder();
  120. }
  121. void CInput::CAM_ToThirdPersonShoulder()
  122. {
  123. PerUserInput_t &user = GetPerUser();
  124. if( c_thirdpersonshoulder.GetBool() )
  125. {
  126. user.m_nCamCommand = 2; // CAM_COMMAND_TOFIRSTPERSON
  127. c_thirdpersonshoulder.SetValue( false );
  128. cam_idealdist.SetValue( cam_idealdist.GetDefault() );
  129. }
  130. else
  131. {
  132. user.m_nCamCommand = 1; // CAM_COMMAND_TOTHIRDPERSON
  133. c_thirdpersonshoulder.SetValue( true );
  134. cam_idealdist.SetValue( c_thirdpersonshoulderdist.GetFloat() );
  135. }
  136. }
  137. /*
  138. ==============================
  139. CAM_ToThirdPersonOverview
  140. ==============================
  141. */
  142. void CAM_ToThirdPersonOverview(void)
  143. {
  144. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  145. input->CAM_ToThirdPersonOverview();
  146. }
  147. void CInput::CAM_ToThirdPersonOverview()
  148. {
  149. // PerUserInput_t &user = GetPerUser();
  150. //
  151. // if( c_thirdpersonshoulder.GetBool() )
  152. // {
  153. // user.m_nCamCommand = 2; // CAM_COMMAND_TOFIRSTPERSON
  154. // c_thirdpersonshoulder.SetValue( false );
  155. // cam_idealdist.SetValue( cam_idealdist.GetDefault() );
  156. // }
  157. // else
  158. // {
  159. // user.m_nCamCommand = 1; // CAM_COMMAND_TOTHIRDPERSON
  160. // c_thirdpersonshoulder.SetValue( true );
  161. // cam_idealdist.SetValue( c_thirdpersonshoulderdist.GetFloat() );
  162. // }
  163. //m_CameraIsThirdPersonOverview
  164. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  165. PerUserInput_t &user = GetPerUser();
  166. if ( !user.m_fCameraInThirdPerson )
  167. {
  168. user.m_fCameraInThirdPerson = true;
  169. C_BaseEntity::UpdateVisibilityAllEntities();
  170. }
  171. user.m_CameraIsThirdPersonOverview = true;
  172. user.m_nCamCommand = 0;
  173. }
  174. bool CInput::CAM_IsThirdPersonOverview( int nSlot /*=-1*/ )
  175. {
  176. if ( !g_bEngineIsHLTV )
  177. return false;
  178. if ( nSlot == -1 )
  179. {
  180. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  181. PerUserInput_t &user = GetPerUser();
  182. return user.m_CameraIsThirdPersonOverview;
  183. }
  184. return m_PerUser[ nSlot ].m_CameraIsThirdPersonOverview;
  185. }
  186. //==============================
  187. // CAM_ToOrthographic
  188. // ==============================
  189. void CAM_ToOrthographic(void)
  190. {
  191. input->CAM_ToOrthographic();
  192. }
  193. void CAM_StartMouseMove( void )
  194. {
  195. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  196. input->CAM_StartMouseMove();
  197. }
  198. void CAM_EndMouseMove( void )
  199. {
  200. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  201. input->CAM_EndMouseMove();
  202. }
  203. void CAM_StartDistance( void )
  204. {
  205. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  206. input->CAM_StartDistance();
  207. }
  208. void CAM_EndDistance( void )
  209. {
  210. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  211. input->CAM_EndDistance();
  212. }
  213. void CAM_ToggleSnapto( void )
  214. {
  215. cam_snapto.SetValue( !cam_snapto.GetInt() );
  216. }
  217. float MoveToward( float cur, float goal, float lag )
  218. {
  219. if( cur != goal )
  220. {
  221. if( abs( cur - goal ) > 180.0 )
  222. {
  223. if( cur < goal )
  224. cur += 360.0;
  225. else
  226. cur -= 360.0;
  227. }
  228. if( cur < goal )
  229. {
  230. if( cur < goal - 1.0 )
  231. cur += ( goal - cur ) / lag;
  232. else
  233. cur = goal;
  234. }
  235. else
  236. {
  237. if( cur > goal + 1.0 )
  238. cur -= ( cur - goal ) / lag;
  239. else
  240. cur = goal;
  241. }
  242. }
  243. // bring cur back into range
  244. if( cur < 0 )
  245. cur += 360.0;
  246. else if( cur >= 360 )
  247. cur -= 360;
  248. return cur;
  249. }
  250. void CInput::CAM_Command( int command )
  251. {
  252. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  253. PerUserInput_t &user = GetPerUser();
  254. user.m_nCamCommand = command;
  255. }
  256. void CInput::CAM_Think( void )
  257. {
  258. VPROF( "CAM_Think" );
  259. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  260. PerUserInput_t &user = GetPerUser();
  261. if ( !sv_cheats )
  262. {
  263. sv_cheats = cvar->FindVar( "sv_cheats" );
  264. }
  265. // If cheats have been disabled, pull us back out of third-person view.
  266. if ( sv_cheats && !sv_cheats->GetBool() && user.m_fCameraInThirdPerson && GameRules() && !GameRules()->AllowThirdPersonCamera() )
  267. {
  268. CAM_ToFirstPerson();
  269. return;
  270. }
  271. if ( user.m_pCameraThirdData )
  272. {
  273. return CAM_CameraThirdThink();
  274. }
  275. Vector idealAngles;
  276. Vector camOffset;
  277. float flSensitivity;
  278. QAngle viewangles;
  279. switch( user.m_nCamCommand )
  280. {
  281. case CAM_COMMAND_TOTHIRDPERSON:
  282. CAM_ToThirdPerson();
  283. break;
  284. case CAM_COMMAND_TOFIRSTPERSON:
  285. CAM_ToFirstPerson();
  286. break;
  287. case CAM_COMMAND_NONE:
  288. default:
  289. break;
  290. }
  291. if( !user.m_fCameraInThirdPerson )
  292. return;
  293. C_BasePlayer* localPlayer = C_BasePlayer::GetLocalPlayer();
  294. // In Maya-mode
  295. if ( Is_CAM_ThirdPerson_MayaMode() )
  296. {
  297. // Unless explicitly moving the camera, don't move it
  298. user.m_fCameraInterceptingMouse = user.m_fCameraMovingWithMouse =
  299. vgui::input()->IsKeyDown( KEY_LALT ) || vgui::input()->IsKeyDown( KEY_RALT );
  300. //if ( !user.m_fCameraMovingWithMouse )
  301. // return;
  302. // Zero-out camera-control kbutton_t structures
  303. memset( &cam_pitchup, 0, sizeof( cam_pitchup ) );
  304. memset( &cam_pitchdown, 0, sizeof( cam_pitchdown ) );
  305. memset( &cam_yawleft, 0, sizeof( cam_yawleft ) );
  306. memset( &cam_yawright, 0, sizeof( cam_yawright ) );
  307. memset( &cam_in, 0, sizeof( cam_in ) );
  308. memset( &cam_out, 0, sizeof( cam_out ) );
  309. // Unless left or right mouse button is down, don't do anything
  310. if ( /* Left+Middle Button Down */ vgui::input()->IsMouseDown( MOUSE_LEFT ) && vgui::input()->IsMouseDown( MOUSE_MIDDLE ) )
  311. {
  312. // Do only zoom in/out camera adjustment
  313. user.m_fCameraDistanceMove = true;
  314. }
  315. else if ( /* Left Button Down */ vgui::input()->IsMouseDown( MOUSE_LEFT ) )
  316. {
  317. // Do only rotational camera movement
  318. user.m_fCameraDistanceMove = false;
  319. }
  320. else if ( /* Right Button Down */ vgui::input()->IsMouseDown( MOUSE_RIGHT ) )
  321. {
  322. // Do only zoom in/out camera adjustment
  323. user.m_fCameraDistanceMove = true;
  324. }
  325. else
  326. {
  327. // Neither left or right buttons down, don't do anything
  328. ResetMouse();
  329. //return;
  330. }
  331. }
  332. idealAngles[ PITCH ] = cam_idealpitch.GetFloat();
  333. idealAngles[ YAW ] = cam_idealyaw.GetFloat();
  334. idealAngles[ DIST ] = cam_idealdist.GetFloat();
  335. //
  336. //movement of the camera with the mouse
  337. //
  338. if ( user.m_fCameraMovingWithMouse )
  339. {
  340. int cpx, cpy;
  341. //get windows cursor position
  342. GetMousePos (cpx, cpy);
  343. user.m_nCameraX = cpx;
  344. user.m_nCameraY = cpy;
  345. //check for X delta values and adjust accordingly
  346. //eventually adjust YAW based on amount of movement
  347. //don't do any movement of the cam using YAW/PITCH if we are zooming in/out the camera
  348. if (!user.m_fCameraDistanceMove)
  349. {
  350. int x, y;
  351. GetWindowCenter( x, y );
  352. if ( Is_CAM_ThirdPerson_MayaMode() )
  353. {
  354. if (user.m_nCameraX>x)
  355. {
  356. idealAngles[ YAW ] += (CAM_ANGLE_MOVE)*((user.m_nCameraX-x)/2);
  357. }
  358. else if (user.m_nCameraX<x)
  359. {
  360. idealAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((x-user.m_nCameraX)/2);
  361. }
  362. if (user.m_nCameraY > y)
  363. {
  364. idealAngles[PITCH] +=(CAM_ANGLE_MOVE)* ((user.m_nCameraY-y)/2);
  365. }
  366. else if (user.m_nCameraY<y)
  367. {
  368. idealAngles[PITCH] -= (CAM_ANGLE_MOVE)*((y-user.m_nCameraY)/2);
  369. }
  370. }
  371. else
  372. {
  373. //keep the camera within certain limits around the player (ie avoid certain bad viewing angles)
  374. if (user.m_nCameraX>x)
  375. {
  376. //if ((idealAngles[YAW]>=225.0)||(idealAngles[YAW]<135.0))
  377. if (idealAngles[YAW]<c_maxyaw.GetFloat())
  378. {
  379. idealAngles[ YAW ] += (CAM_ANGLE_MOVE)*((user.m_nCameraX-x)/2);
  380. }
  381. if (idealAngles[YAW]>c_maxyaw.GetFloat())
  382. {
  383. idealAngles[YAW]=c_maxyaw.GetFloat();
  384. }
  385. }
  386. else if (user.m_nCameraX<x)
  387. {
  388. //if ((idealAngles[YAW]<=135.0)||(idealAngles[YAW]>225.0))
  389. if (idealAngles[YAW]>c_minyaw.GetFloat())
  390. {
  391. idealAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((x-user.m_nCameraX)/2);
  392. }
  393. if (idealAngles[YAW]<c_minyaw.GetFloat())
  394. {
  395. idealAngles[YAW]=c_minyaw.GetFloat();
  396. }
  397. }
  398. //check for y delta values and adjust accordingly
  399. //eventually adjust PITCH based on amount of movement
  400. //also make sure camera is within bounds
  401. if (user.m_nCameraY > y)
  402. {
  403. if(idealAngles[PITCH]<c_maxpitch.GetFloat())
  404. {
  405. idealAngles[PITCH] +=(CAM_ANGLE_MOVE)* ((user.m_nCameraY-y)/2);
  406. }
  407. if (idealAngles[PITCH]>c_maxpitch.GetFloat())
  408. {
  409. idealAngles[PITCH]=c_maxpitch.GetFloat();
  410. }
  411. }
  412. else if (user.m_nCameraY<y)
  413. {
  414. if (idealAngles[PITCH]>c_minpitch.GetFloat())
  415. {
  416. idealAngles[PITCH] -= (CAM_ANGLE_MOVE)*((y-user.m_nCameraY)/2);
  417. }
  418. if (idealAngles[PITCH]<c_minpitch.GetFloat())
  419. {
  420. idealAngles[PITCH]=c_minpitch.GetFloat();
  421. }
  422. }
  423. }
  424. //set old mouse coordinates to current mouse coordinates
  425. //since we are done with the mouse
  426. if ( ( flSensitivity = GetHud().GetSensitivity() ) != 0 )
  427. {
  428. user.m_nCameraOldX=user.m_nCameraX*flSensitivity;
  429. user.m_nCameraOldY=user.m_nCameraY*flSensitivity;
  430. }
  431. else
  432. {
  433. user.m_nCameraOldX=user.m_nCameraX;
  434. user.m_nCameraOldY=user.m_nCameraY;
  435. }
  436. ResetMouse();
  437. }
  438. }
  439. //Nathan code here
  440. if( input->KeyState( &cam_pitchup ) )
  441. idealAngles[ PITCH ] += cam_idealdelta.GetFloat();
  442. else if( input->KeyState( &cam_pitchdown ) )
  443. idealAngles[ PITCH ] -= cam_idealdelta.GetFloat();
  444. if( input->KeyState( &cam_yawleft ) )
  445. idealAngles[ YAW ] -= cam_idealdelta.GetFloat();
  446. else if( input->KeyState( &cam_yawright ) )
  447. idealAngles[ YAW ] += cam_idealdelta.GetFloat();
  448. if( input->KeyState( &cam_in ) )
  449. {
  450. idealAngles[ DIST ] -= 2*cam_idealdelta.GetFloat();
  451. if( idealAngles[ DIST ] < CAM_MIN_DIST )
  452. {
  453. // If we go back into first person, reset the angle
  454. idealAngles[ PITCH ] = 0;
  455. idealAngles[ YAW ] = 0;
  456. idealAngles[ DIST ] = CAM_MIN_DIST;
  457. }
  458. }
  459. else if( input->KeyState( &cam_out ) )
  460. idealAngles[ DIST ] += 2*cam_idealdelta.GetFloat();
  461. if (user.m_fCameraDistanceMove)
  462. {
  463. int x, y;
  464. GetWindowCenter( x, y );
  465. if (user.m_nCameraY>y)
  466. {
  467. if(idealAngles[ DIST ]<c_maxdistance.GetFloat())
  468. {
  469. idealAngles[ DIST ] +=cam_idealdelta.GetFloat() * ((user.m_nCameraY-y)/2);
  470. }
  471. if (idealAngles[ DIST ]>c_maxdistance.GetFloat())
  472. {
  473. idealAngles[ DIST ]=c_maxdistance.GetFloat();
  474. }
  475. }
  476. else if (user.m_nCameraY<y)
  477. {
  478. if (idealAngles[ DIST ]>c_mindistance.GetFloat())
  479. {
  480. idealAngles[ DIST ] -= (cam_idealdelta.GetFloat())*((y-user.m_nCameraY)/2);
  481. }
  482. if (idealAngles[ DIST ]<c_mindistance.GetFloat())
  483. {
  484. idealAngles[ DIST ]=c_mindistance.GetFloat();
  485. }
  486. }
  487. //set old mouse coordinates to current mouse coordinates
  488. //since we are done with the mouse
  489. user.m_nCameraOldX=user.m_nCameraX*GetHud().GetSensitivity();
  490. user.m_nCameraOldY=user.m_nCameraY*GetHud().GetSensitivity();
  491. ResetMouse();
  492. }
  493. // Obtain engine view angles and if they popped while the camera was static,
  494. // fix the camera angles as well
  495. engine->GetViewAngles( viewangles );
  496. static QAngle s_oldAngles = viewangles;
  497. if ( Is_CAM_ThirdPerson_MayaMode() && ( s_oldAngles != viewangles ) )
  498. {
  499. idealAngles[ PITCH ] += s_oldAngles[ PITCH ] - viewangles[ PITCH ];
  500. idealAngles[ YAW ] += s_oldAngles[ YAW ] - viewangles[ YAW ];
  501. s_oldAngles = viewangles;
  502. }
  503. // bring the pitch values back into a range that MoveToward can handle
  504. if ( idealAngles[ PITCH ] > 180 )
  505. idealAngles[ PITCH ] -= 360;
  506. else if ( idealAngles[ PITCH ] < -180 )
  507. idealAngles[ PITCH ] += 360;
  508. // bring the yaw values back into a range that MoveToward can handle
  509. // --
  510. // Vitaliy: going with >= 180 and <= -180.
  511. // This introduces a potential discontinuity when looking directly at model face
  512. // as camera yaw will be jumping from +180 to -180 and back, but when working with
  513. // the camera allows smooth rotational transitions from left to right and back.
  514. // Otherwise one of the transitions that has ">"-comparison will be locked.
  515. // --
  516. if ( idealAngles[ YAW ] >= 180 )
  517. idealAngles[ YAW ] -= 360;
  518. else if ( idealAngles[ YAW ] <= -180 )
  519. idealAngles[ YAW ] += 360;
  520. // clamp pitch, yaw and dist...
  521. if ( !Is_CAM_ThirdPerson_MayaMode() )
  522. {
  523. idealAngles[ PITCH ] = clamp( idealAngles[ PITCH ], c_minpitch.GetFloat(), c_maxpitch.GetFloat() );
  524. idealAngles[ YAW ] = clamp( idealAngles[ YAW ], c_minyaw.GetFloat(), c_maxyaw.GetFloat() );
  525. idealAngles[ DIST ] = clamp( idealAngles[ DIST ], c_mindistance.GetFloat(), c_maxdistance.GetFloat() );
  526. }
  527. // update ideal angles
  528. cam_idealpitch.SetValue( idealAngles[ PITCH ] );
  529. cam_idealyaw.SetValue( idealAngles[ YAW ] );
  530. cam_idealdist.SetValue( idealAngles[ DIST ] );
  531. // Move the CameraOffset "towards" the idealAngles
  532. // Note: CameraOffset = viewangle + idealAngle
  533. VectorCopy( user.m_vecCameraOffset, camOffset );
  534. if( cam_snapto.GetInt() )
  535. {
  536. camOffset[ YAW ] = cam_idealyaw.GetFloat() + viewangles[ YAW ];
  537. camOffset[ PITCH ] = cam_idealpitch.GetFloat() + viewangles[ PITCH ];
  538. camOffset[ DIST ] = cam_idealdist.GetFloat();
  539. }
  540. else
  541. {
  542. float lag = MAX( 1, 1 + cam_ideallag.GetFloat() );
  543. if( camOffset[ YAW ] - viewangles[ YAW ] != cam_idealyaw.GetFloat() )
  544. camOffset[ YAW ] = MoveToward( AngleNormalizePositive( camOffset[ YAW ] ), AngleNormalizePositive( cam_idealyaw.GetFloat() + viewangles[ YAW ] ), lag );
  545. if( camOffset[ PITCH ] - viewangles[ PITCH ] != cam_idealpitch.GetFloat() )
  546. camOffset[ PITCH ] = MoveToward( camOffset[ PITCH ], cam_idealpitch.GetFloat() + viewangles[ PITCH ], lag );
  547. if( abs( camOffset[ DIST ] - cam_idealdist.GetFloat() ) < 2.0 )
  548. camOffset[ DIST ] = cam_idealdist.GetFloat();
  549. else
  550. camOffset[ DIST ] += ( cam_idealdist.GetFloat() - camOffset[ DIST ] ) / lag;
  551. }
  552. // move the camera closer to the player if it hit something
  553. if ( cam_collision.GetInt() && localPlayer )
  554. {
  555. Vector camForward;
  556. // find our player's origin, and from there, the eye position
  557. Vector origin = localPlayer->GetLocalOrigin();
  558. origin += localPlayer->GetViewOffset();
  559. // get the forward vector
  560. AngleVectors( QAngle(camOffset[ PITCH ], camOffset[ YAW ], 0), &camForward, NULL, NULL );
  561. // use our previously #defined hull to collision trace
  562. trace_t trace;
  563. CTraceFilterSimple traceFilter( localPlayer, COLLISION_GROUP_NONE );
  564. UTIL_TraceHull( origin, origin - (camForward * camOffset[ DIST ]),
  565. CAM_HULL_MIN, CAM_HULL_MAX,
  566. MASK_SOLID, &traceFilter, &trace );
  567. // move the camera closer if it hit something
  568. if( trace.fraction < 1.0 )
  569. {
  570. camOffset[ DIST ] *= trace.fraction;
  571. }
  572. // For now, I'd rather see the insade of a player model than punch the camera through a wall
  573. // might try the fade out trick at some point
  574. //if( camOffset[ DIST ] < CAM_MIN_DIST )
  575. // camOffset[ DIST ] = CAM_MIN_DIST; // clamp up to minimum
  576. }
  577. if ( cam_showangles.GetInt() )
  578. {
  579. engine->Con_NPrintf( 4, "Pitch: %6.1f Yaw: %6.1f %38s", viewangles[ PITCH ], viewangles[ YAW ], "view angles" );
  580. 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" );
  581. engine->Con_NPrintf( 8, "Pitch: %6.1f Yaw: %6.1f Dist: %6.1f %16s", user.m_vecCameraOffset[ PITCH ], user.m_vecCameraOffset[ YAW ],user. m_vecCameraOffset[ DIST ], "camera offset" );
  582. }
  583. user.m_vecCameraOffset[ PITCH ] = camOffset[ PITCH ];
  584. user.m_vecCameraOffset[ YAW ] = camOffset[ YAW ];
  585. user.m_vecCameraOffset[ DIST ] = camOffset[ DIST ];
  586. }
  587. //------------------------------------------------------------------------------
  588. // Purpose:
  589. //------------------------------------------------------------------------------
  590. void ClampRange180( float &value )
  591. {
  592. if ( value >= 180.0f )
  593. {
  594. value -= 360.0f;
  595. }
  596. else if ( value <= -180.0f )
  597. {
  598. value += 360.0f;
  599. }
  600. }
  601. //------------------------------------------------------------------------------
  602. // Purpose:
  603. //------------------------------------------------------------------------------
  604. void CInput::CAM_SetCameraThirdData( CameraThirdData_t *pCameraData, const QAngle &vecCameraOffset )
  605. {
  606. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  607. PerUserInput_t &user = GetPerUser();
  608. user.m_pCameraThirdData = pCameraData;
  609. user.m_vecCameraOffset[PITCH] = vecCameraOffset[PITCH];
  610. user.m_vecCameraOffset[YAW] = vecCameraOffset[YAW];
  611. user.m_vecCameraOffset[DIST] = vecCameraOffset[DIST];
  612. }
  613. //------------------------------------------------------------------------------
  614. // Purpose:
  615. //------------------------------------------------------------------------------
  616. void CInput::CAM_CameraThirdThink( void )
  617. {
  618. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  619. PerUserInput_t &user = GetPerUser();
  620. // Verify data.
  621. if ( !user.m_pCameraThirdData )
  622. return;
  623. // Verify that we are in third person mode.
  624. if( !user.m_fCameraInThirdPerson )
  625. return;
  626. // Opting out of camera movement
  627. if ( user.m_pCameraThirdData->m_flLag == -1.0f )
  628. return;
  629. // Obtain engine view angles and if they popped while the camera was static, fix the camera angles as well.
  630. QAngle angView;
  631. engine->GetViewAngles( angView );
  632. // Move the CameraOffset "towards" the idealAngles, Note: CameraOffset = viewangle + idealAngle
  633. Vector vecCamOffset;
  634. VectorCopy( user.m_vecCameraOffset, vecCamOffset );
  635. // Move the camera.
  636. float flLag = MAX( 1, 1 + user.m_pCameraThirdData->m_flLag );
  637. if( vecCamOffset[PITCH] - angView[PITCH] != user.m_pCameraThirdData->m_flPitch )
  638. {
  639. vecCamOffset[PITCH] = MoveToward( vecCamOffset[PITCH], ( user.m_pCameraThirdData->m_flPitch + angView[PITCH] ), flLag );
  640. }
  641. if( vecCamOffset[YAW] - angView[YAW] != user.m_pCameraThirdData->m_flYaw )
  642. {
  643. vecCamOffset[YAW] = MoveToward( vecCamOffset[YAW], ( user.m_pCameraThirdData->m_flYaw + angView[YAW] ), flLag );
  644. }
  645. if( abs( vecCamOffset[DIST] - user.m_pCameraThirdData->m_flDist ) < 2.0 )
  646. {
  647. vecCamOffset[DIST] = user.m_pCameraThirdData->m_flDist;
  648. }
  649. else
  650. {
  651. vecCamOffset[DIST] += ( user.m_pCameraThirdData->m_flDist - vecCamOffset[DIST] ) / flLag;
  652. }
  653. C_BasePlayer* pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  654. if ( pLocalPlayer )
  655. {
  656. Vector vecForward;
  657. // Find our player's origin, and from there, the eye position.
  658. Vector vecOrigin = pLocalPlayer->GetThirdPersonViewPosition();
  659. // Get the forward vector
  660. AngleVectors( QAngle( vecCamOffset[PITCH], vecCamOffset[YAW], 0 ), &vecForward, NULL, NULL );
  661. // Collision trace and move the camera closer if we hit something.
  662. CTraceFilterSkipTwoEntities filter( pLocalPlayer, NULL );
  663. #ifdef PORTAL2
  664. C_Portal_Player *pPortalPlayer = static_cast< C_Portal_Player* >( pLocalPlayer );
  665. if ( pPortalPlayer->GetTeamTauntState() >= TEAM_TAUNT_HAS_PARTNER )
  666. {
  667. for( int i = 1; i <= gpGlobals->maxClients; ++i )
  668. {
  669. C_Portal_Player *pOtherPlayer = ToPortalPlayer( UTIL_PlayerByIndex( i ) );
  670. //If the other player does not exist or if the other player is the local player
  671. if( pOtherPlayer == NULL || pOtherPlayer == pPortalPlayer )
  672. continue;
  673. filter.SetPassEntity2( pOtherPlayer );
  674. return;
  675. }
  676. }
  677. #endif
  678. trace_t trace;
  679. UTIL_TraceHull( vecOrigin, vecOrigin - ( vecForward * vecCamOffset[DIST] ), user.m_pCameraThirdData->m_vecHullMin, user.m_pCameraThirdData->m_vecHullMax, MASK_SOLID, &filter, &trace );
  680. if( trace.fraction < 1.0 )
  681. {
  682. vecCamOffset[DIST] *= trace.fraction;
  683. }
  684. }
  685. ClampRange180( vecCamOffset[PITCH] );
  686. ClampRange180( vecCamOffset[YAW] );
  687. user.m_vecCameraOffset[PITCH] = vecCamOffset[PITCH];
  688. user.m_vecCameraOffset[YAW] = vecCamOffset[YAW];
  689. user.m_vecCameraOffset[DIST] = vecCamOffset[DIST];
  690. }
  691. void CAM_PitchUpDown( const CCommand &args ) { KeyDown( &cam_pitchup, args[1] ); }
  692. void CAM_PitchUpUp( const CCommand &args ) { KeyUp( &cam_pitchup, args[1] ); }
  693. void CAM_PitchDownDown( const CCommand &args ) { KeyDown( &cam_pitchdown, args[1] ); }
  694. void CAM_PitchDownUp( const CCommand &args ) { KeyUp( &cam_pitchdown, args[1] ); }
  695. void CAM_YawLeftDown( const CCommand &args ) { KeyDown( &cam_yawleft, args[1] ); }
  696. void CAM_YawLeftUp( const CCommand &args ) { KeyUp( &cam_yawleft, args[1] ); }
  697. void CAM_YawRightDown( const CCommand &args ) { KeyDown( &cam_yawright, args[1] ); }
  698. void CAM_YawRightUp( const CCommand &args ) { KeyUp( &cam_yawright, args[1] ); }
  699. void CAM_InDown( const CCommand &args ) { KeyDown( &cam_in, args[1] ); }
  700. void CAM_InUp( const CCommand &args ) { KeyUp( &cam_in, args[1] ); }
  701. void CAM_OutDown( const CCommand &args ) { KeyDown( &cam_out, args[1] ); }
  702. void CAM_OutUp( const CCommand &args ) { KeyUp( &cam_out, args[1] ); }
  703. void CInput::CAM_ToThirdPerson(void)
  704. {
  705. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  706. PerUserInput_t &user = GetPerUser();
  707. QAngle viewangles;
  708. engine->GetViewAngles( viewangles );
  709. if( !user.m_fCameraInThirdPerson )
  710. {
  711. user.m_fCameraInThirdPerson = true;
  712. user.m_vecCameraOffset[ YAW ] = viewangles[ YAW ];
  713. user.m_vecCameraOffset[ PITCH ] = viewangles[ PITCH ];
  714. user.m_vecCameraOffset[ DIST ] = CAM_MIN_DIST;
  715. C_BaseEntity::UpdateVisibilityAllEntities();
  716. }
  717. user.m_nCamCommand = 0;
  718. }
  719. void CInput::CAM_ToFirstPerson(void)
  720. {
  721. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  722. PerUserInput_t &user = GetPerUser();
  723. if ( user.m_fCameraInThirdPerson )
  724. {
  725. user.m_fCameraInThirdPerson = false;
  726. C_BaseEntity::UpdateVisibilityAllEntities();
  727. }
  728. user.m_nCamCommand = 0;
  729. }
  730. bool CInput::CAM_IsOrthographic(void) const
  731. {
  732. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  733. const PerUserInput_t &user = GetPerUser();
  734. return user.m_CameraIsOrthographic;
  735. }
  736. void CInput::CAM_OrthographicSize(float& w, float& h) const
  737. {
  738. w = c_orthowidth.GetFloat(); h = c_orthoheight.GetFloat();
  739. }
  740. void CInput::CAM_ToOrthographic(void)
  741. {
  742. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  743. PerUserInput_t &user = GetPerUser();
  744. if ( user.m_fCameraInThirdPerson )
  745. {
  746. user.m_fCameraInThirdPerson = false;
  747. C_BaseEntity::UpdateVisibilityAllEntities();
  748. }
  749. user.m_CameraIsOrthographic = true;
  750. user.m_nCamCommand = 0;
  751. }
  752. void CInput::CAM_StartMouseMove(void)
  753. {
  754. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  755. PerUserInput_t &user = GetPerUser();
  756. float flSensitivity;
  757. //only move the cam with mouse if we are in third person.
  758. if ( user.m_fCameraInThirdPerson )
  759. {
  760. //set appropriate flags and initialize the old mouse position
  761. //variables for mouse camera movement
  762. if (!user.m_fCameraMovingWithMouse)
  763. {
  764. int cpx, cpy;
  765. user.m_fCameraMovingWithMouse=true;
  766. user.m_fCameraInterceptingMouse=true;
  767. GetMousePos(cpx, cpy);
  768. user.m_nCameraX = cpx;
  769. user.m_nCameraY = cpy;
  770. if ( ( flSensitivity = GetHud().GetSensitivity() ) != 0 )
  771. {
  772. user.m_nCameraOldX=user.m_nCameraX*flSensitivity;
  773. user.m_nCameraOldY=user.m_nCameraY*flSensitivity;
  774. }
  775. else
  776. {
  777. user.m_nCameraOldX=user.m_nCameraX;
  778. user.m_nCameraOldY=user.m_nCameraY;
  779. }
  780. }
  781. }
  782. //we are not in 3rd person view..therefore do not allow camera movement
  783. else
  784. {
  785. user.m_fCameraMovingWithMouse=false;
  786. user.m_fCameraInterceptingMouse=false;
  787. }
  788. }
  789. /*
  790. ==============================
  791. CAM_EndMouseMove
  792. the key has been released for camera movement
  793. tell the engine that mouse camera movement is off
  794. ==============================
  795. */
  796. void CInput::CAM_EndMouseMove(void)
  797. {
  798. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  799. PerUserInput_t &user = GetPerUser();
  800. user.m_fCameraMovingWithMouse=false;
  801. user.m_fCameraInterceptingMouse=false;
  802. }
  803. /*
  804. ==============================
  805. CAM_StartDistance
  806. routines to start the process of moving the cam in or out
  807. using the mouse
  808. ==============================
  809. */
  810. void CInput::CAM_StartDistance(void)
  811. {
  812. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  813. PerUserInput_t &user = GetPerUser();
  814. //only move the cam with mouse if we are in third person.
  815. if ( user.m_fCameraInThirdPerson )
  816. {
  817. //set appropriate flags and initialize the old mouse position
  818. //variables for mouse camera movement
  819. if (!user.m_fCameraDistanceMove)
  820. {
  821. int cpx, cpy;
  822. user.m_fCameraDistanceMove=true;
  823. user.m_fCameraMovingWithMouse=true;
  824. user.m_fCameraInterceptingMouse=true;
  825. GetMousePos(cpx, cpy);
  826. user.m_nCameraX = cpx;
  827. user.m_nCameraY = cpy;
  828. user.m_nCameraOldX=user.m_nCameraX*GetHud().GetSensitivity();
  829. user.m_nCameraOldY=user.m_nCameraY*GetHud().GetSensitivity();
  830. }
  831. }
  832. //we are not in 3rd person view..therefore do not allow camera movement
  833. else
  834. {
  835. user.m_fCameraDistanceMove=false;
  836. user.m_fCameraMovingWithMouse=false;
  837. user.m_fCameraInterceptingMouse=false;
  838. }
  839. }
  840. /*
  841. ==============================
  842. CAM_EndDistance
  843. the key has been released for camera movement
  844. tell the engine that mouse camera movement is off
  845. ==============================
  846. */
  847. void CInput::CAM_EndDistance(void)
  848. {
  849. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  850. PerUserInput_t &user = GetPerUser();
  851. user.m_fCameraDistanceMove=false;
  852. user.m_fCameraMovingWithMouse=false;
  853. user.m_fCameraInterceptingMouse=false;
  854. }
  855. /*
  856. ==============================
  857. CAM_IsThirdPerson
  858. ==============================
  859. */
  860. int CInput::CAM_IsThirdPerson( int nSlot /*=-1*/ )
  861. {
  862. if ( nSlot == -1 )
  863. {
  864. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  865. if ( GetPerUser().m_fCameraInThirdPerson || GetPerUser().m_CameraIsThirdPersonOverview )
  866. return true;
  867. else
  868. return false;
  869. }
  870. if ( m_PerUser[ nSlot ].m_fCameraInThirdPerson || m_PerUser[ nSlot ].m_CameraIsThirdPersonOverview )
  871. return true;
  872. else
  873. return false;
  874. }
  875. /*
  876. ==============================
  877. CAM_GetCameraOffset
  878. ==============================
  879. */
  880. void CInput::CAM_GetCameraOffset( Vector& ofs )
  881. {
  882. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  883. PerUserInput_t &user = GetPerUser();
  884. VectorCopy( user.m_vecCameraOffset, ofs );
  885. }
  886. /*
  887. ==============================
  888. CAM_InterceptingMouse
  889. ==============================
  890. */
  891. int CInput::CAM_InterceptingMouse( void )
  892. {
  893. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  894. PerUserInput_t &user = GetPerUser();
  895. return user.m_fCameraInterceptingMouse;
  896. }
  897. static ConCommand startpitchup( "+campitchup", CAM_PitchUpDown );
  898. static ConCommand endpitcup( "-campitchup", CAM_PitchUpUp );
  899. static ConCommand startpitchdown( "+campitchdown", CAM_PitchDownDown );
  900. static ConCommand endpitchdown( "-campitchdown", CAM_PitchDownUp );
  901. static ConCommand startcamyawleft( "+camyawleft", CAM_YawLeftDown );
  902. static ConCommand endcamyawleft( "-camyawleft", CAM_YawLeftUp );
  903. static ConCommand startcamyawright( "+camyawright", CAM_YawRightDown );
  904. static ConCommand endcamyawright( "-camyawright", CAM_YawRightUp );
  905. static ConCommand startcamin( "+camin", CAM_InDown );
  906. static ConCommand endcamin( "-camin", CAM_InUp );
  907. static ConCommand startcamout( "+camout", CAM_OutDown );
  908. static ConCommand camout( "-camout", CAM_OutUp );
  909. static ConCommand thirdperson( "thirdperson", CAM_ToThirdPerson, "Switch to thirdperson camera.", FCVAR_CHEAT|FCVAR_SERVER_CAN_EXECUTE );
  910. static ConCommand thirdperson_mayamode( "thirdperson_mayamode", ::CAM_ToThirdPerson_MayaMode, "Switch to thirdperson Maya-like camera controls.", FCVAR_CHEAT );
  911. static ConCommand firstperson( "firstperson", CAM_ToFirstPerson, "Switch to firstperson camera.", FCVAR_SERVER_CAN_EXECUTE );
  912. static ConCommand thirdpersonshoulder( "thirdpersonshoulder", CAM_ToThirdPersonShoulder, "Switch to thirdperson-shoulder camera.", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
  913. static ConCommand thirdpersonoverview( "thirdpersonoverview", CAM_ToThirdPersonOverview, "Switch to thirdperson-overview camera.", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
  914. static ConCommand camortho( "camortho", CAM_ToOrthographic, "Switch to orthographic camera.", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
  915. static ConCommand startcammousemove( "+cammousemove",::CAM_StartMouseMove);
  916. static ConCommand endcammousemove( "-cammousemove",::CAM_EndMouseMove);
  917. static ConCommand startcamdistance( "+camdistance", ::CAM_StartDistance );
  918. static ConCommand endcamdistance( "-camdistance", ::CAM_EndDistance );
  919. static ConCommand snapto( "snapto", CAM_ToggleSnapto );
  920. /*
  921. ==============================
  922. Init_Camera
  923. ==============================
  924. */
  925. void CInput::Init_Camera( void )
  926. {
  927. for ( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; ++i )
  928. {
  929. m_PerUser[ i ].m_CameraIsOrthographic = false;
  930. m_PerUser[ i ].m_CameraIsThirdPersonOverview = false;
  931. }
  932. }