Team Fortress 2 Source Code as on 22/4/2020
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.

696 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "weapon_ifmsteadycam.h"
  9. #include "in_buttons.h"
  10. #include "usercmd.h"
  11. #include "dt_shared.h"
  12. #ifdef CLIENT_DLL
  13. #include "vgui_controls/Controls.h"
  14. #include "vgui/ISurface.h"
  15. #include "vgui/IScheme.h"
  16. #include "vgui/ILocalize.h"
  17. #include "vgui/VGUI.h"
  18. #include "tier1/KeyValues.h"
  19. #include "toolframework/itoolframework.h"
  20. #endif
  21. //-----------------------------------------------------------------------------
  22. // CWeaponIFMSteadyCam tables.
  23. //-----------------------------------------------------------------------------
  24. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponIFMSteadyCam, DT_WeaponIFMSteadyCam )
  25. LINK_ENTITY_TO_CLASS( weapon_ifm_steadycam, CWeaponIFMSteadyCam );
  26. #if !( defined( TF_CLIENT_DLL ) || defined( TF_DLL ) )
  27. PRECACHE_WEAPON_REGISTER( weapon_ifm_steadycam );
  28. #endif
  29. BEGIN_NETWORK_TABLE( CWeaponIFMSteadyCam, DT_WeaponIFMSteadyCam )
  30. END_NETWORK_TABLE()
  31. #ifdef CLIENT_DLL
  32. BEGIN_PREDICTION_DATA( CWeaponIFMSteadyCam )
  33. DEFINE_PRED_FIELD( m_bIsLocked, FIELD_BOOLEAN, 0 ),
  34. DEFINE_PRED_FIELD( m_bInSpringMode, FIELD_BOOLEAN, 0 ),
  35. DEFINE_PRED_FIELD( m_bInDirectMode, FIELD_BOOLEAN, 0 ),
  36. DEFINE_PRED_FIELD( m_vecOffset, FIELD_VECTOR, 0 ),
  37. DEFINE_PRED_FIELD( m_hLockTarget, FIELD_EHANDLE, 0 ),
  38. DEFINE_PRED_FIELD( m_vec2DVelocity, FIELD_VECTOR, 0 ),
  39. DEFINE_PRED_FIELD( m_vecActualViewOffset, FIELD_VECTOR, 0 ),
  40. DEFINE_PRED_FIELD( m_vecViewOffset, FIELD_VECTOR, 0 ),
  41. DEFINE_PRED_FIELD( m_flFOVOffsetY, FIELD_FLOAT, 0 ),
  42. END_PREDICTION_DATA()
  43. #endif
  44. #ifdef GAME_DLL
  45. BEGIN_DATADESC( CWeaponIFMSteadyCam )
  46. DEFINE_FIELD( m_hLockTarget, FIELD_EHANDLE ),
  47. END_DATADESC()
  48. #endif
  49. //-----------------------------------------------------------------------------
  50. // CWeaponIFMSteadyCam implementation.
  51. //-----------------------------------------------------------------------------
  52. CWeaponIFMSteadyCam::CWeaponIFMSteadyCam()
  53. {
  54. #ifdef CLIENT_DLL
  55. m_bIsLocked = false;
  56. m_bInDirectMode = false;
  57. m_bInSpringMode = true;
  58. m_vec2DVelocity.Init();
  59. m_vecActualViewOffset.Init();
  60. m_vecViewOffset.Init();
  61. m_flFOVOffsetY = 0.0f;
  62. m_vecOffset.Init();
  63. m_hFont = vgui::INVALID_FONT;
  64. m_nTextureId = -1;
  65. #endif
  66. }
  67. CWeaponIFMSteadyCam::~CWeaponIFMSteadyCam()
  68. {
  69. #ifdef CLIENT_DLL
  70. if ( vgui::surface() && m_nTextureId != -1 )
  71. {
  72. vgui::surface()->DestroyTextureID( m_nTextureId );
  73. m_nTextureId = -1;
  74. }
  75. #endif
  76. }
  77. //-----------------------------------------------------------------------------
  78. //
  79. // Specific methods on the client
  80. //
  81. //-----------------------------------------------------------------------------
  82. #ifdef CLIENT_DLL
  83. //-----------------------------------------------------------------------------
  84. // Computes a matrix given a forward direction
  85. //-----------------------------------------------------------------------------
  86. void CWeaponIFMSteadyCam::MatrixFromForwardDirection( const Vector &vecForward, matrix3x4_t &mat )
  87. {
  88. // Convert desired to quaternion
  89. Vector vecLeft( -vecForward.y, vecForward.x, 0.0f );
  90. if ( VectorNormalize( vecLeft ) < 1e-3 )
  91. {
  92. vecLeft.Init( 1.0f, 0.0f, 0.0f );
  93. }
  94. Vector vecUp;
  95. CrossProduct( vecForward, vecLeft, vecUp );
  96. MatrixInitialize( mat, m_vecRelativePosition, vecForward, vecLeft, vecUp );
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Updates the relative orientation of the camera, spring mode
  100. //-----------------------------------------------------------------------------
  101. void CWeaponIFMSteadyCam::ComputeMouseRay( const VMatrix &steadyCamToPlayer, Vector &vecForward )
  102. {
  103. // Create a ray in steadycam space
  104. float flMaxD = 1.0f / tan( M_PI * m_flFOV / 360.0f );
  105. // Remap offsets into normalized space
  106. int w, h;
  107. GetViewportSize( w, h );
  108. float flViewX = ( w != 0 ) ? m_vecViewOffset.x / ( w / 2 ) : 0.0f;
  109. float flViewY = ( h != 0 ) ? m_vecViewOffset.y / ( h / 2 ) : 0.0f;
  110. flViewX *= flMaxD;
  111. flViewY *= flMaxD;
  112. Vector vecSelectionDir( 1.0f, -flViewX, -flViewY );
  113. VectorNormalize( vecSelectionDir );
  114. // Rotate the ray into player coordinates
  115. Vector3DMultiply( steadyCamToPlayer, vecSelectionDir, vecForward );
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Updates the relative orientation of the camera, spring mode
  119. //-----------------------------------------------------------------------------
  120. void CWeaponIFMSteadyCam::UpdateDirectRelativeOrientation()
  121. {
  122. // Compute a player to steadycam matrix
  123. VMatrix steadyCamToPlayer;
  124. MatrixFromAngles( m_angRelativeAngles, steadyCamToPlayer );
  125. MatrixSetColumn( steadyCamToPlayer, 3, m_vecRelativePosition );
  126. // Compute a forward direction
  127. Vector vecCurrentForward;
  128. MatrixGetColumn( steadyCamToPlayer, 0, &vecCurrentForward );
  129. // Before any updating occurs, sample the current
  130. // world-space direction of the mouse
  131. Vector vecDesiredDirection;
  132. ComputeMouseRay( steadyCamToPlayer, vecDesiredDirection );
  133. // rebuild a roll-less orientation based on that direction vector
  134. matrix3x4_t mat;
  135. MatrixFromForwardDirection( vecDesiredDirection, mat );
  136. MatrixAngles( mat, m_angRelativeAngles );
  137. Assert( m_angRelativeAngles.IsValid() );
  138. m_vecActualViewOffset -= m_vecViewOffset;
  139. m_vecViewOffset.Init();
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Updates the relative orientation of the camera when locked
  143. //-----------------------------------------------------------------------------
  144. void CWeaponIFMSteadyCam::UpdateLockedRelativeOrientation()
  145. {
  146. CBasePlayer *pPlayer = GetPlayerOwner();
  147. if ( !pPlayer )
  148. return;
  149. Vector vecDesiredDirection = m_vecOffset;
  150. CBaseEntity *pLock = m_hLockTarget.Get();
  151. if ( pLock )
  152. {
  153. vecDesiredDirection += pLock->GetAbsOrigin();
  154. }
  155. Vector vecAbsOrigin;
  156. QAngle angAbsRotation;
  157. ComputeAbsCameraTransform( vecAbsOrigin, angAbsRotation );
  158. vecDesiredDirection -= vecAbsOrigin;
  159. VectorNormalize( vecDesiredDirection );
  160. matrix3x4_t mat;
  161. MatrixFromForwardDirection( vecDesiredDirection, mat );
  162. MatrixAngles( mat, m_angRelativeAngles );
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Updates the relative orientation of the camera
  166. //-----------------------------------------------------------------------------
  167. static ConVar ifm_steadycam_rotaterate( "ifm_steadycam_rotaterate", "60", FCVAR_ARCHIVE );
  168. static ConVar ifm_steadycam_zoomspeed( "ifm_steadycam_zoomspeed", "1.0", FCVAR_ARCHIVE );
  169. static ConVar ifm_steadycam_zoomdamp( "ifm_steadycam_zoomdamp", "0.95", FCVAR_ARCHIVE );
  170. static ConVar ifm_steadycam_armspeed( "ifm_steadycam_armspeed", "0.5", FCVAR_ARCHIVE );
  171. static ConVar ifm_steadycam_rotatedamp( "ifm_steadycam_rotatedamp", "0.95", FCVAR_ARCHIVE );
  172. static ConVar ifm_steadycam_mousefactor( "ifm_steadycam_mousefactor", "1.0", FCVAR_ARCHIVE );
  173. static ConVar ifm_steadycam_mousepower( "ifm_steadycam_mousepower", "1.0", FCVAR_ARCHIVE );
  174. void CWeaponIFMSteadyCam::UpdateRelativeOrientation()
  175. {
  176. if ( m_bIsLocked )
  177. return;
  178. if ( m_bInDirectMode )
  179. {
  180. UpdateDirectRelativeOrientation();
  181. return;
  182. }
  183. if ( ( m_vecViewOffset.x == 0.0f ) && ( m_vecViewOffset.y == 0.0f ) )
  184. return;
  185. // Compute a player to steadycam matrix
  186. VMatrix steadyCamToPlayer;
  187. MatrixFromAngles( m_angRelativeAngles, steadyCamToPlayer );
  188. MatrixSetColumn( steadyCamToPlayer, 3, m_vecRelativePosition );
  189. Vector vecCurrentForward;
  190. MatrixGetColumn( steadyCamToPlayer, 0, &vecCurrentForward );
  191. // Create a ray in steadycam space
  192. float flMaxD = 1.0f / tan( M_PI * m_flFOV / 360.0f );
  193. // Remap offsets into normalized space
  194. float flViewX = m_vecViewOffset.x / ( 384 / 2 );
  195. float flViewY = m_vecViewOffset.y / ( 288 / 2 );
  196. flViewX *= flMaxD * ifm_steadycam_mousefactor.GetFloat();
  197. flViewY *= flMaxD * ifm_steadycam_mousefactor.GetFloat();
  198. Vector vecSelectionDir( 1.0f, -flViewX, -flViewY );
  199. VectorNormalize( vecSelectionDir );
  200. // Rotate the ray into player coordinates
  201. Vector vecDesiredDirection;
  202. Vector3DMultiply( steadyCamToPlayer, vecSelectionDir, vecDesiredDirection );
  203. float flDot = DotProduct( vecDesiredDirection, vecCurrentForward );
  204. flDot = clamp( flDot, -1.0f, 1.0f );
  205. float flAngle = 180.0f * acos( flDot ) / M_PI;
  206. if ( flAngle < 1e-3 )
  207. {
  208. matrix3x4_t mat;
  209. MatrixFromForwardDirection( vecDesiredDirection, mat );
  210. MatrixAngles( mat, m_angRelativeAngles );
  211. return;
  212. }
  213. Vector vecAxis;
  214. CrossProduct( vecCurrentForward, vecDesiredDirection, vecAxis );
  215. VectorNormalize( vecAxis );
  216. float flRotateRate = ifm_steadycam_rotaterate.GetFloat();
  217. if ( flRotateRate < 1.0f )
  218. {
  219. flRotateRate = 1.0f;
  220. }
  221. float flRateFactor = flAngle / flRotateRate;
  222. flRateFactor *= flRateFactor * flRateFactor;
  223. float flRate = flRateFactor * 30.0f;
  224. float flMaxAngle = gpGlobals->frametime * flRate;
  225. flAngle = clamp( flAngle, 0.0f, flMaxAngle );
  226. Vector vecNewForard;
  227. VMatrix rotation;
  228. MatrixBuildRotationAboutAxis( rotation, vecAxis, flAngle );
  229. Vector3DMultiply( rotation, vecCurrentForward, vecNewForard );
  230. matrix3x4_t mat;
  231. MatrixFromForwardDirection( vecNewForard, mat );
  232. MatrixAngles( mat, m_angRelativeAngles );
  233. Assert( m_angRelativeAngles.IsValid() );
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Toggles to springy camera
  237. //-----------------------------------------------------------------------------
  238. void CWeaponIFMSteadyCam::ToggleDirectMode()
  239. {
  240. m_vecViewOffset.Init();
  241. m_vecActualViewOffset.Init();
  242. m_vec2DVelocity.Init();
  243. m_bInDirectMode = !m_bInDirectMode;
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Targets the camera to always look at a point
  247. //-----------------------------------------------------------------------------
  248. void CWeaponIFMSteadyCam::LockCamera()
  249. {
  250. m_vecViewOffset.Init();
  251. m_vecActualViewOffset.Init();
  252. m_vec2DVelocity.Init();
  253. m_bIsLocked = !m_bIsLocked;
  254. if ( !m_bIsLocked )
  255. {
  256. UpdateLockedRelativeOrientation();
  257. return;
  258. }
  259. CBasePlayer *pPlayer = GetPlayerOwner();
  260. if ( !pPlayer )
  261. return;
  262. Vector vTraceStart, vTraceEnd, vTraceDir;
  263. QAngle angles;
  264. BaseClass::ComputeAbsCameraTransform( vTraceStart, angles );
  265. AngleVectors( angles, &vTraceDir );
  266. VectorMA( vTraceStart, 10000.0f, vTraceDir, vTraceEnd);
  267. trace_t tr;
  268. UTIL_TraceLine( vTraceStart, vTraceEnd, MASK_ALL, GetPlayerOwner(), COLLISION_GROUP_NONE, &tr );
  269. if ( tr.fraction == 1.0f )
  270. {
  271. m_bIsLocked = false;
  272. UpdateLockedRelativeOrientation();
  273. return;
  274. }
  275. m_hLockTarget = tr.m_pEnt;
  276. m_vecOffset = tr.endpos;
  277. if ( tr.m_pEnt )
  278. {
  279. m_vecOffset -= tr.m_pEnt->GetAbsOrigin();
  280. }
  281. }
  282. //-----------------------------------------------------------------------------
  283. // Gets the abs orientation of the camera
  284. //-----------------------------------------------------------------------------
  285. void CWeaponIFMSteadyCam::ComputeAbsCameraTransform( Vector &vecAbsOrigin, QAngle &angAbsRotation )
  286. {
  287. CBaseEntity *pLock = m_bIsLocked ? m_hLockTarget.Get() : NULL;
  288. CBasePlayer *pPlayer = GetPlayerOwner();
  289. if ( !pLock || !pPlayer )
  290. {
  291. BaseClass::ComputeAbsCameraTransform( vecAbsOrigin, angAbsRotation );
  292. return;
  293. }
  294. Vector vecDesiredDirection = m_vecOffset;
  295. if ( pLock )
  296. {
  297. vecDesiredDirection += pLock->GetAbsOrigin();
  298. }
  299. BaseClass::ComputeAbsCameraTransform( vecAbsOrigin, angAbsRotation );
  300. vecDesiredDirection -= vecAbsOrigin;
  301. VectorNormalize( vecDesiredDirection );
  302. matrix3x4_t mat;
  303. MatrixFromForwardDirection( vecDesiredDirection, mat );
  304. MatrixAngles( mat, angAbsRotation );
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Computes the view offset from the actual view offset
  308. //-----------------------------------------------------------------------------
  309. static ConVar ifm_steadycam_2dspringconstant( "ifm_steadycam_2dspringconstant", "33.0", FCVAR_ARCHIVE );
  310. static ConVar ifm_steadycam_2ddragconstant( "ifm_steadycam_2ddragconstant", "11.0", FCVAR_ARCHIVE );
  311. void CWeaponIFMSteadyCam::ComputeViewOffset()
  312. {
  313. // Update 2D spring
  314. if ( !m_bInSpringMode )
  315. {
  316. m_vecViewOffset = m_vecActualViewOffset;
  317. return;
  318. }
  319. Vector2D dir;
  320. Vector2DSubtract( m_vecViewOffset.AsVector2D(), m_vecActualViewOffset.AsVector2D(), dir );
  321. float flDist = Vector2DNormalize( dir );
  322. Vector2D vecForce;
  323. Vector2DMultiply( dir, -flDist * ifm_steadycam_2dspringconstant.GetFloat(), vecForce );
  324. Vector2DMA( vecForce, -ifm_steadycam_2ddragconstant.GetFloat(), m_vec2DVelocity.AsVector2D(), vecForce );
  325. Vector2DMA( m_vecViewOffset.AsVector2D(), gpGlobals->frametime, m_vec2DVelocity.AsVector2D(), m_vecViewOffset.AsVector2D() );
  326. Vector2DMA( m_vec2DVelocity.AsVector2D(), gpGlobals->frametime, vecForce, m_vec2DVelocity.AsVector2D() );
  327. }
  328. //-----------------------------------------------------------------------------
  329. // Camera control
  330. //-----------------------------------------------------------------------------
  331. static ConVar ifm_steadycam_noise( "ifm_steadycam_noise", "0.0", FCVAR_ARCHIVE | FCVAR_REPLICATED );
  332. static ConVar ifm_steadycam_sensitivity( "ifm_steadycam_sensitivity", "1.0", FCVAR_ARCHIVE | FCVAR_REPLICATED );
  333. void CWeaponIFMSteadyCam::ItemPostFrame()
  334. {
  335. CBasePlayer *pPlayer = GetPlayerOwner();
  336. if ( !pPlayer )
  337. return;
  338. float flSensitivity = ifm_steadycam_sensitivity.GetFloat();
  339. Vector2D vecOldActualViewOffset = m_vecActualViewOffset.AsVector2D();
  340. if ( pPlayer->m_nButtons & IN_ATTACK )
  341. {
  342. const CUserCmd *pUserCmd = pPlayer->GetCurrentUserCommand();
  343. m_vecActualViewOffset.x += pUserCmd->mousedx * flSensitivity;
  344. m_vecActualViewOffset.y += pUserCmd->mousedy * flSensitivity;
  345. }
  346. else
  347. {
  348. if ( !m_bIsLocked && !m_bInDirectMode )
  349. {
  350. float flDamp = ifm_steadycam_rotatedamp.GetFloat();
  351. m_vecActualViewOffset.x *= flDamp;
  352. m_vecActualViewOffset.y *= flDamp;
  353. }
  354. }
  355. // Add noise
  356. if ( !m_bIsLocked )
  357. {
  358. float flNoise = ifm_steadycam_noise.GetFloat();
  359. if ( flNoise > 0.0f )
  360. {
  361. CUniformRandomStream stream;
  362. stream.SetSeed( (int)(gpGlobals->curtime * 100) );
  363. CGaussianRandomStream gauss( &stream );
  364. float dx = gauss.RandomFloat( 0.0f, flNoise );
  365. float dy = gauss.RandomFloat( 0.0f, flNoise );
  366. m_vecActualViewOffset.x += dx;
  367. m_vecActualViewOffset.y += dy;
  368. }
  369. }
  370. ComputeViewOffset();
  371. if ( pPlayer->m_nButtons & IN_ZOOM )
  372. {
  373. const CUserCmd *pUserCmd = pPlayer->GetCurrentUserCommand();
  374. m_flFOVOffsetY += pUserCmd->mousedy * flSensitivity;
  375. }
  376. else
  377. {
  378. float flDamp = ifm_steadycam_zoomdamp.GetFloat();
  379. m_flFOVOffsetY *= flDamp;
  380. }
  381. m_flFOV += m_flFOVOffsetY * ifm_steadycam_zoomspeed.GetFloat() / 1000.0f;
  382. m_flFOV = clamp( m_flFOV, 0.5f, 160.0f );
  383. if ( pPlayer->m_nButtons & IN_WALK )
  384. {
  385. const CUserCmd *pUserCmd = pPlayer->GetCurrentUserCommand();
  386. m_flArmLength -= ifm_steadycam_armspeed.GetFloat() * pUserCmd->mousedy;
  387. }
  388. if ( pPlayer->GetImpulse() == 87 )
  389. {
  390. ToggleDirectMode();
  391. }
  392. if ( pPlayer->GetImpulse() == 89 )
  393. {
  394. m_bInSpringMode = !m_bInSpringMode;
  395. }
  396. if ( pPlayer->m_afButtonPressed & IN_USE )
  397. {
  398. LockCamera();
  399. }
  400. if ( pPlayer->m_afButtonPressed & IN_ATTACK2 )
  401. {
  402. m_bFullScreen = !m_bFullScreen;
  403. }
  404. if ( pPlayer->GetImpulse() == 88 )
  405. {
  406. // Make the view angles exactly match the player
  407. m_vecViewOffset.Init();
  408. m_vecActualViewOffset.Init();
  409. m_vecOffset.Init();
  410. m_vec2DVelocity.Init();
  411. m_hLockTarget.Set( NULL );
  412. m_flArmLength = 0.0f;
  413. if ( m_bIsLocked )
  414. {
  415. LockCamera();
  416. }
  417. m_angRelativeAngles = pPlayer->EyeAngles();
  418. m_flFOV = pPlayer->GetFOV();
  419. }
  420. UpdateRelativeOrientation();
  421. TransmitRenderInfo();
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Records the state for the IFM
  425. //-----------------------------------------------------------------------------
  426. void CWeaponIFMSteadyCam::GetToolRecordingState( KeyValues *msg )
  427. {
  428. BaseClass::GetToolRecordingState( msg );
  429. static CameraRecordingState_t state;
  430. state.m_flFOV = m_flFOV;
  431. ComputeAbsCameraTransform( state.m_vecEyePosition, state.m_vecEyeAngles );
  432. msg->SetPtr( "camera", &state );
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Slams view angles if the mouse is down
  436. //-----------------------------------------------------------------------------
  437. void CWeaponIFMSteadyCam::CreateMove( float flInputSampleTime, CUserCmd *pCmd, const QAngle &vecOldViewAngles )
  438. {
  439. BaseClass::CreateMove( flInputSampleTime, pCmd, vecOldViewAngles );
  440. // Block angular movement when IN_ATTACK is pressed
  441. if ( pCmd->buttons & (IN_ATTACK | IN_WALK | IN_ZOOM) )
  442. {
  443. VectorCopy( vecOldViewAngles, pCmd->viewangles );
  444. }
  445. }
  446. //-----------------------------------------------------------------------------
  447. // Purpose: Draw the weapon's crosshair
  448. //-----------------------------------------------------------------------------
  449. void CWeaponIFMSteadyCam::DrawArmLength( int x, int y, int w, int h, Color clr )
  450. {
  451. // Draw a readout for the arm length
  452. if ( m_hFont == vgui::INVALID_FONT )
  453. {
  454. vgui::HScheme hScheme = vgui::scheme()->GetScheme( "ClientScheme" );
  455. vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( hScheme );
  456. m_hFont = pScheme->GetFont("DefaultVerySmall", false );
  457. Assert( m_hFont != vgui::INVALID_FONT );
  458. }
  459. // Create our string
  460. char szString[256];
  461. Q_snprintf( szString, sizeof(szString), "Arm Length: %.2f\n", m_flArmLength );
  462. // Convert it to localize friendly unicode
  463. wchar_t wcString[256];
  464. g_pVGuiLocalize->ConvertANSIToUnicode( szString, wcString, sizeof(wcString) );
  465. int tw, th;
  466. vgui::surface()->GetTextSize( m_hFont, wcString, tw, th );
  467. vgui::surface()->DrawSetTextFont( m_hFont ); // set the font
  468. vgui::surface()->DrawSetTextColor( clr ); // white
  469. vgui::surface()->DrawSetTextPos( x + w - tw - 10, y + 10 ); // x,y position
  470. vgui::surface()->DrawPrintText( wcString, wcslen(wcString) ); // print text
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Purpose: Draw the FOV
  474. //-----------------------------------------------------------------------------
  475. void CWeaponIFMSteadyCam::DrawFOV( int x, int y, int w, int h, Color clrEdges, Color clrTriangle )
  476. {
  477. if ( m_nTextureId == -1 )
  478. {
  479. m_nTextureId = vgui::surface()->CreateNewTextureID();
  480. vgui::surface()->DrawSetTextureFile( m_nTextureId, "vgui/white", true, false );
  481. }
  482. // This is the fov
  483. int nSize = 30;
  484. int fx = x + w - 10 - nSize;
  485. int fy = y + h - 10;
  486. int fh = nSize * cos( M_PI * m_flFOV / 360.0f );
  487. int fw = nSize * sin( M_PI * m_flFOV / 360.0f );
  488. vgui::Vertex_t v[3];
  489. v[0].m_Position.Init( fx, fy );
  490. v[0].m_TexCoord.Init( 0.0f, 0.0f );
  491. v[1].m_Position.Init( fx-fw, fy-fh );
  492. v[1].m_TexCoord.Init( 0.0f, 0.0f );
  493. v[2].m_Position.Init( fx+fw, fy-fh );
  494. v[2].m_TexCoord.Init( 0.0f, 0.0f );
  495. vgui::surface()->DrawSetTexture( m_nTextureId );
  496. vgui::surface()->DrawSetColor( clrTriangle );
  497. vgui::surface()->DrawTexturedPolygon( 3, v );
  498. vgui::surface()->DrawSetColor( clrEdges );
  499. vgui::surface()->DrawLine( fx, fy, fx - fw, fy - fh );
  500. vgui::surface()->DrawLine( fx, fy, fx + fw, fy - fh );
  501. }
  502. //-----------------------------------------------------------------------------
  503. // Purpose: Draw the weapon's crosshair
  504. //-----------------------------------------------------------------------------
  505. void CWeaponIFMSteadyCam::DrawCrosshair( void )
  506. {
  507. BaseClass::DrawCrosshair();
  508. int x, y, w, h;
  509. GetOverlayBounds( x, y, w, h );
  510. // Draw the targeting zone around the crosshair
  511. int r, g, b, a;
  512. gHUD.m_clrYellowish.GetColor( r, g, b, a );
  513. Color gray( 255, 255, 255, 192 );
  514. Color light( r, g, b, 255 );
  515. Color dark( r, g, b, 128 );
  516. Color red( 255, 0, 0, 128 );
  517. DrawArmLength( x, y, w, h, light );
  518. DrawFOV( x, y, w, h, light, dark );
  519. int cx, cy;
  520. cx = x + ( w / 2 );
  521. cy = y + ( h / 2 );
  522. // This is the crosshair
  523. vgui::surface()->DrawSetColor( gray );
  524. vgui::surface()->DrawFilledRect( cx-10, cy-1, cx-3, cy+1 );
  525. vgui::surface()->DrawFilledRect( cx+3, cy-1, cx+10, cy+1 );
  526. vgui::surface()->DrawFilledRect( cx-1, cy-10, cx+1, cy-3 );
  527. vgui::surface()->DrawFilledRect( cx-1, cy+3, cx+1, cy+10 );
  528. // This is the yellow aiming dot
  529. if ( ( m_vecViewOffset.x != 0.0f ) || ( m_vecViewOffset.y != 0.0f ) )
  530. {
  531. int ax, ay;
  532. ax = cx + m_vecViewOffset.x;
  533. ay = cy + m_vecViewOffset.y;
  534. vgui::surface()->DrawSetColor( light );
  535. vgui::surface()->DrawFilledRect( ax-2, ay-2, ax+2, ay+2 );
  536. }
  537. // This is the red actual dot
  538. if ( ( m_vecActualViewOffset.x != 0.0f ) || ( m_vecActualViewOffset.y != 0.0f ) )
  539. {
  540. int ax, ay;
  541. ax = cx + m_vecActualViewOffset.x;
  542. ay = cy + m_vecActualViewOffset.y;
  543. vgui::surface()->DrawSetColor( red );
  544. vgui::surface()->DrawFilledRect( ax-2, ay-2, ax+2, ay+2 );
  545. }
  546. // This is the purple fov dot
  547. if ( m_flFOVOffsetY != 0.0f )
  548. {
  549. Color purple( 255, 0, 255, 255 );
  550. int vy = cy + m_flFOVOffsetY;
  551. vgui::surface()->DrawSetColor( purple );
  552. vgui::surface()->DrawFilledRect( cx-2, vy-2, cx+2, vy+2 );
  553. }
  554. }
  555. #endif // CLIENT_DLL
  556. //-----------------------------------------------------------------------------
  557. //
  558. // Specific methods on the server
  559. //
  560. //-----------------------------------------------------------------------------
  561. #ifdef GAME_DLL
  562. void CWeaponIFMSteadyCam::ItemPostFrame()
  563. {
  564. }
  565. #endif // GAME_DLL