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.

471 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "hud.h"
  10. #include "hudelement.h"
  11. #include "iclientmode.h"
  12. #include "c_basehlplayer.h"
  13. #include "view_scene.h"
  14. #include "engine/IEngineSound.h"
  15. #include "vgui_controls/AnimationController.h"
  16. #include "vgui_controls/Controls.h"
  17. #include "vgui_controls/Panel.h"
  18. #include "vgui/ISurface.h"
  19. #include "iviewrender.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. ConVar hud_draw_active_reticle("hud_draw_active_reticle", "0" );
  23. ConVar hud_draw_fixed_reticle("hud_draw_fixed_reticle", "0", FCVAR_ARCHIVE );
  24. ConVar hud_autoaim_scale_icon( "hud_autoaim_scale_icon", "0" );
  25. ConVar hud_autoaim_method( "hud_autoaim_method", "1" );
  26. ConVar hud_reticle_scale("hud_reticle_scale", "1.0" );
  27. ConVar hud_reticle_minalpha( "hud_reticle_minalpha", "125" );
  28. ConVar hud_reticle_maxalpha( "hud_reticle_maxalpha", "255" );
  29. ConVar hud_alpha_speed("hud_reticle_alpha_speed", "700" );
  30. ConVar hud_magnetism("hud_magnetism", "0.3" );
  31. enum
  32. {
  33. AUTOAIM_METHOD_RETICLE = 1,
  34. AUTOAIM_METHOD_DRIFT,
  35. };
  36. using namespace vgui;
  37. class CHUDAutoAim : public CHudElement, public vgui::Panel
  38. {
  39. DECLARE_CLASS_SIMPLE( CHUDAutoAim, vgui::Panel );
  40. public:
  41. CHUDAutoAim( const char *pElementName );
  42. virtual ~CHUDAutoAim( void );
  43. void ApplySchemeSettings( IScheme *scheme );
  44. void Init( void );
  45. void VidInit( void );
  46. bool ShouldDraw( void );
  47. virtual void OnThink();
  48. virtual void Paint();
  49. private:
  50. void ResetAlpha() { m_alpha = 0; }
  51. void ResetScale() { m_scale = 1.0f; }
  52. void ResetPosition()
  53. {
  54. m_vecPos.x = ScreenWidth() / 2;
  55. m_vecPos.y = ScreenHeight() / 2;
  56. m_vecPos.z = 0;
  57. }
  58. Vector m_vecPos;
  59. float m_alpha;
  60. float m_scale;
  61. float m_alphaFixed; // alpha value for the fixed element.
  62. int m_textureID_ActiveReticle;
  63. int m_textureID_FixedReticle;
  64. };
  65. DECLARE_HUDELEMENT( CHUDAutoAim );
  66. CHUDAutoAim::CHUDAutoAim( const char *pElementName ) :
  67. CHudElement( pElementName ), BaseClass( NULL, "HUDAutoAim" )
  68. {
  69. vgui::Panel *pParent = g_pClientMode->GetViewport();
  70. SetParent( pParent );
  71. SetHiddenBits( HIDEHUD_CROSSHAIR );
  72. m_textureID_ActiveReticle = -1;
  73. m_textureID_FixedReticle = -1;
  74. }
  75. CHUDAutoAim::~CHUDAutoAim( void )
  76. {
  77. if ( vgui::surface() )
  78. {
  79. if ( m_textureID_ActiveReticle != -1 )
  80. {
  81. vgui::surface()->DestroyTextureID( m_textureID_ActiveReticle );
  82. m_textureID_ActiveReticle = -1;
  83. }
  84. if ( m_textureID_FixedReticle != -1 )
  85. {
  86. vgui::surface()->DestroyTextureID( m_textureID_FixedReticle );
  87. m_textureID_FixedReticle = -1;
  88. }
  89. }
  90. }
  91. void CHUDAutoAim::ApplySchemeSettings( IScheme *scheme )
  92. {
  93. BaseClass::ApplySchemeSettings( scheme );
  94. SetPaintBackgroundEnabled( false );
  95. }
  96. void CHUDAutoAim::Init( void )
  97. {
  98. ResetPosition();
  99. ResetAlpha();
  100. ResetScale();
  101. }
  102. void CHUDAutoAim::VidInit( void )
  103. {
  104. SetAlpha( 255 );
  105. Init();
  106. if ( m_textureID_ActiveReticle == -1 )
  107. {
  108. m_textureID_ActiveReticle = vgui::surface()->CreateNewTextureID();
  109. vgui::surface()->DrawSetTextureFile( m_textureID_ActiveReticle, "vgui/hud/autoaim", true, false );
  110. }
  111. if ( m_textureID_FixedReticle == -1 )
  112. {
  113. m_textureID_FixedReticle = vgui::surface()->CreateNewTextureID();
  114. vgui::surface()->DrawSetTextureFile( m_textureID_FixedReticle, "vgui/hud/xbox_reticle", true, false );
  115. }
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Purpose: Save CPU cycles by letting the HUD system early cull
  119. // costly traversal. Called per frame, return true if thinking and
  120. // painting need to occur.
  121. //-----------------------------------------------------------------------------
  122. bool CHUDAutoAim::ShouldDraw( void )
  123. {
  124. #ifndef HL1_CLIENT_DLL
  125. C_BaseHLPlayer *pLocalPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
  126. if ( pLocalPlayer )
  127. {
  128. if( !pLocalPlayer->m_HL2Local.m_bDisplayReticle )
  129. {
  130. return false;
  131. }
  132. }
  133. #endif
  134. return ( (hud_draw_fixed_reticle.GetBool() || hud_draw_active_reticle.GetBool()) && CHudElement::ShouldDraw() && !engine->IsDrawingLoadingImage() );
  135. }
  136. #define AUTOAIM_ALPHA_UP_SPEED 1000
  137. #define AUTOAIM_ALPHA_DOWN_SPEED 300
  138. #define AUTOAIM_MAX_ALPHA 120
  139. #define AUTOAIM_MAX_SCALE 1.0f
  140. #define AUTOAIM_MIN_SCALE 0.5f
  141. #define AUTOAIM_SCALE_SPEED 10.0f
  142. #define AUTOAIM_ONTARGET_CROSSHAIR_SPEED (ScreenWidth() / 3) // Can cross the whole screen in 3 seconds.
  143. #define AUTOAIM_OFFTARGET_CROSSHAIR_SPEED (ScreenWidth() / 4)
  144. void CHUDAutoAim::OnThink()
  145. {
  146. int wide, tall;
  147. GetSize( wide, tall );
  148. BaseClass::OnThink();
  149. // Get the HL2 player
  150. C_BaseHLPlayer *pLocalPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
  151. if ( pLocalPlayer == NULL )
  152. {
  153. // Just turn the autoaim crosshair off.
  154. ResetPosition();
  155. ResetAlpha();
  156. ResetScale();
  157. m_alphaFixed = 0.0f;
  158. return;
  159. }
  160. // Get the autoaim target.
  161. CBaseEntity *pTarget = pLocalPlayer->m_HL2Local.m_hAutoAimTarget.Get();
  162. // Fixed element stuff
  163. float flFixedAlphaGoal;
  164. if( pTarget )
  165. {
  166. flFixedAlphaGoal = hud_reticle_maxalpha.GetFloat();
  167. }
  168. else
  169. {
  170. flFixedAlphaGoal = hud_reticle_minalpha.GetFloat();
  171. }
  172. if( pLocalPlayer->m_HL2Local.m_bZooming || pLocalPlayer->m_HL2Local.m_bWeaponLowered )
  173. {
  174. flFixedAlphaGoal = 0.0f;
  175. }
  176. m_alphaFixed = Approach( flFixedAlphaGoal, m_alphaFixed, (hud_alpha_speed.GetFloat() * gpGlobals->frametime) );
  177. switch( hud_autoaim_method.GetInt() )
  178. {
  179. case AUTOAIM_METHOD_RETICLE:
  180. {
  181. if( pLocalPlayer->m_HL2Local.m_hAutoAimTarget.Get() && pLocalPlayer->m_HL2Local.m_bStickyAutoAim )
  182. {
  183. if( !pLocalPlayer->IsInAVehicle() )
  184. {
  185. Vector vecLook;
  186. pLocalPlayer->EyeVectors( &vecLook, NULL, NULL );
  187. Vector vecMove = pLocalPlayer->GetAbsVelocity();
  188. float flSpeed = VectorNormalize( vecMove );
  189. float flDot = DotProduct( vecLook, vecMove );
  190. if( flSpeed >= 100 && fabs(flDot) <= 0.707f )
  191. {
  192. QAngle viewangles;
  193. QAngle targetangles;
  194. QAngle delta;
  195. engine->GetViewAngles( viewangles );
  196. Vector vecDir = pLocalPlayer->m_HL2Local.m_vecAutoAimPoint - pLocalPlayer->EyePosition();
  197. VectorNormalize(vecDir);
  198. VectorAngles( vecDir, targetangles );
  199. float magnetism = hud_magnetism.GetFloat();
  200. delta[0] = ApproachAngle( targetangles[0], viewangles[0], magnetism );
  201. delta[1] = ApproachAngle( targetangles[1], viewangles[1], magnetism );
  202. delta[2] = targetangles[2];
  203. //viewangles[PITCH] = clamp( viewangles[ PITCH ], -cl_pitchup.GetFloat(), cl_pitchdown.GetFloat() );
  204. engine->SetViewAngles( delta );
  205. }
  206. }
  207. }
  208. #if 0
  209. bool doScaling = hud_autoaim_scale_icon.GetBool();
  210. // These are the X & Y coords of where the crosshair should be. Default to
  211. // returning to the center of the screen if there is no target.
  212. int goalx = ScreenWidth() / 2;
  213. int goaly = ScreenHeight() / 2;
  214. int goalalpha = 0;
  215. float goalscale = AUTOAIM_MIN_SCALE;
  216. float speed = AUTOAIM_OFFTARGET_CROSSHAIR_SPEED;
  217. if( pTarget )
  218. {
  219. // Get the autoaim crosshair onto the target.
  220. Vector screen;
  221. // Center the crosshair on the entity.
  222. if( doScaling )
  223. {
  224. // Put the crosshair over the center of the target.
  225. ScreenTransform( pTarget->WorldSpaceCenter(), screen );
  226. }
  227. else
  228. {
  229. // Put the crosshair exactly where the player is aiming.
  230. ScreenTransform( pLocalPlayer->m_HL2Local.m_vecAutoAimPoint, screen );
  231. }
  232. // Set Goal Position and speed.
  233. goalx += 0.5f * screen[0] * ScreenWidth() + 0.5f;
  234. goaly -= 0.5f * screen[1] * ScreenHeight() + 0.5f;
  235. speed = AUTOAIM_ONTARGET_CROSSHAIR_SPEED;
  236. goalalpha = AUTOAIM_MAX_ALPHA;
  237. if( doScaling )
  238. {
  239. // Scale the crosshair to envelope the entity's bounds on screen.
  240. Vector vecMins, vecMaxs;
  241. Vector vecScreenMins, vecScreenMaxs;
  242. // Get mins and maxs in world space
  243. vecMins = pTarget->GetAbsOrigin() + pTarget->WorldAlignMins();
  244. vecMaxs = pTarget->GetAbsOrigin() + pTarget->WorldAlignMaxs();
  245. // Project them to screen
  246. ScreenTransform( vecMins, vecScreenMins );
  247. ScreenTransform( vecMaxs, vecScreenMaxs );
  248. vecScreenMins.y = (ScreenWidth()/2) - 0.5f * vecScreenMins.y * ScreenWidth() + 0.5f;
  249. vecScreenMaxs.y = (ScreenWidth()/2) - 0.5f * vecScreenMaxs.y * ScreenWidth() + 0.5f;
  250. float screenSize = vecScreenMins.y - vecScreenMaxs.y;
  251. // Set goal scale
  252. goalscale = screenSize / 64.0f; // 64 is the width of the crosshair art.
  253. }
  254. else
  255. {
  256. goalscale = 1.0f;
  257. }
  258. }
  259. // Now approach the goal, alpha, and scale
  260. Vector vecGoal( goalx, goaly, 0 );
  261. Vector vecDir = vecGoal - m_vecPos;
  262. float flDistRemaining = VectorNormalize( vecDir );
  263. m_vecPos += vecDir * min(flDistRemaining, (speed * gpGlobals->frametime) );
  264. // Lerp and Clamp scale
  265. float scaleDelta = fabs( goalscale - m_scale );
  266. float scaleMove = MIN( AUTOAIM_SCALE_SPEED * gpGlobals->frametime, scaleDelta );
  267. if( m_scale < goalscale )
  268. {
  269. m_scale += scaleMove;
  270. }
  271. else if( m_scale > goalscale )
  272. {
  273. m_scale -= scaleMove;
  274. }
  275. if( m_scale > AUTOAIM_MAX_SCALE )
  276. {
  277. m_scale = AUTOAIM_MAX_SCALE;
  278. }
  279. else if( m_scale < AUTOAIM_MIN_SCALE )
  280. {
  281. m_scale = AUTOAIM_MIN_SCALE;
  282. }
  283. if( goalalpha > m_alpha )
  284. {
  285. m_alpha += AUTOAIM_ALPHA_UP_SPEED * gpGlobals->frametime;
  286. }
  287. else if( goalalpha < m_alpha )
  288. {
  289. m_alpha -= AUTOAIM_ALPHA_DOWN_SPEED * gpGlobals->frametime;
  290. }
  291. // Clamp alpha
  292. if( m_alpha < 0 )
  293. {
  294. m_alpha = 0;
  295. }
  296. else if( m_alpha > AUTOAIM_MAX_ALPHA )
  297. {
  298. m_alpha = AUTOAIM_MAX_ALPHA;
  299. }
  300. #endif
  301. }
  302. break;
  303. case AUTOAIM_METHOD_DRIFT:
  304. {
  305. if( pLocalPlayer->m_HL2Local.m_hAutoAimTarget.Get() )
  306. {
  307. QAngle viewangles;
  308. engine->GetViewAngles( viewangles );
  309. Vector vecDir = pLocalPlayer->m_HL2Local.m_vecAutoAimPoint - pLocalPlayer->EyePosition();
  310. VectorNormalize(vecDir);
  311. VectorAngles( vecDir, viewangles );
  312. //viewangles[PITCH] = clamp( viewangles[ PITCH ], -cl_pitchup.GetFloat(), cl_pitchdown.GetFloat() );
  313. engine->SetViewAngles( viewangles );
  314. }
  315. }
  316. break;
  317. }
  318. }
  319. void CHUDAutoAim::Paint()
  320. {
  321. if( hud_draw_active_reticle.GetBool() )
  322. {
  323. int xCenter = m_vecPos.x;
  324. int yCenter = m_vecPos.y;
  325. int width, height;
  326. float xMod, yMod;
  327. vgui::surface()->DrawSetTexture( m_textureID_ActiveReticle );
  328. vgui::surface()->DrawSetColor( 255, 255, 255, m_alpha );
  329. vgui::surface()->DrawGetTextureSize( m_textureID_ActiveReticle, width, height );
  330. float uv1 = 0.5f / width, uv2 = 1.0f - uv1;
  331. vgui::Vertex_t vert[4];
  332. Vector2D uv11( uv1, uv1 );
  333. Vector2D uv12( uv1, uv2 );
  334. Vector2D uv21( uv2, uv1 );
  335. Vector2D uv22( uv2, uv2 );
  336. xMod = width;
  337. yMod = height;
  338. xMod *= m_scale;
  339. yMod *= m_scale;
  340. xMod /= 2;
  341. yMod /= 2;
  342. vert[0].Init( Vector2D( xCenter + xMod, yCenter + yMod ), uv21 );
  343. vert[1].Init( Vector2D( xCenter - xMod, yCenter + yMod ), uv11 );
  344. vert[2].Init( Vector2D( xCenter - xMod, yCenter - yMod ), uv12 );
  345. vert[3].Init( Vector2D( xCenter + xMod, yCenter - yMod ), uv22 );
  346. vgui::surface()->DrawTexturedPolygon( 4, vert );
  347. }
  348. if( hud_draw_fixed_reticle.GetBool() )
  349. {
  350. int width, height;
  351. float xMod, yMod;
  352. vgui::surface()->DrawSetTexture( m_textureID_FixedReticle );
  353. vgui::surface()->DrawGetTextureSize( m_textureID_FixedReticle, width, height );
  354. int xCenter = ScreenWidth() / 2;
  355. int yCenter = ScreenHeight() / 2;
  356. vgui::Vertex_t vert[4];
  357. Vector2D uv11( 0, 0 );
  358. Vector2D uv12( 0, 1 );
  359. Vector2D uv21( 1, 0 );
  360. Vector2D uv22( 1, 1 );
  361. xMod = width;
  362. yMod = height;
  363. xMod /= 2;
  364. yMod /= 2;
  365. vert[0].Init( Vector2D( xCenter + xMod, yCenter + yMod ), uv21 );
  366. vert[1].Init( Vector2D( xCenter - xMod, yCenter + yMod ), uv11 );
  367. vert[2].Init( Vector2D( xCenter - xMod, yCenter - yMod ), uv12 );
  368. vert[3].Init( Vector2D( xCenter + xMod, yCenter - yMod ), uv22 );
  369. Color clr;
  370. clr = gHUD.m_clrNormal;
  371. int r,g,b,a;
  372. clr.GetColor( r,g,b,a );
  373. C_BaseHLPlayer *pLocalPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer();
  374. if( pLocalPlayer && pLocalPlayer->m_HL2Local.m_hAutoAimTarget.Get() )
  375. {
  376. r = 250;
  377. g = 138;
  378. b = 4;
  379. }
  380. clr.SetColor( r,g,b,m_alphaFixed);
  381. vgui::surface()->DrawSetColor( clr );
  382. vgui::surface()->DrawTexturedPolygon( 4, vert );
  383. }
  384. }