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.

306 lines
6.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "weapon_csbasegun.h"
  8. #if defined( CLIENT_DLL )
  9. #define CWeaponAWP C_WeaponAWP
  10. #include "c_cs_player.h"
  11. #else
  12. #include "cs_player.h"
  13. #include "KeyValues.h"
  14. #endif
  15. #define SNIPER_ZOOM_CONTEXT "SniperRifleThink"
  16. const int cAWPMidZoomFOV = 40;
  17. const int cAWPMaxZoomFOV = 10;
  18. #ifdef AWP_UNZOOM
  19. ConVar sv_awpunzoomdelay(
  20. "sv_awpunzoomdelay",
  21. "1.0",
  22. 0,
  23. "how many seconds to zoom the zoom up after firing",
  24. true, 0, // min value
  25. false, 0 // max value
  26. );
  27. #endif
  28. class CWeaponAWP : public CWeaponCSBaseGun
  29. {
  30. public:
  31. DECLARE_CLASS( CWeaponAWP, CWeaponCSBaseGun );
  32. DECLARE_NETWORKCLASS();
  33. DECLARE_PREDICTABLE();
  34. #ifndef CLIENT_DLL
  35. DECLARE_DATADESC();
  36. #endif
  37. CWeaponAWP();
  38. virtual void Spawn();
  39. virtual void PrimaryAttack();
  40. virtual void SecondaryAttack();
  41. virtual float GetInaccuracy() const;
  42. virtual float GetMaxSpeed() const;
  43. virtual bool IsAwp() const;
  44. virtual bool Reload();
  45. virtual bool Deploy();
  46. virtual CSWeaponID GetWeaponID( void ) const { return WEAPON_AWP; }
  47. private:
  48. #ifdef AWP_UNZOOM
  49. void UnzoomThink( void );
  50. #endif
  51. CWeaponAWP( const CWeaponAWP & );
  52. };
  53. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponAWP, DT_WeaponAWP )
  54. BEGIN_NETWORK_TABLE( CWeaponAWP, DT_WeaponAWP )
  55. END_NETWORK_TABLE()
  56. BEGIN_PREDICTION_DATA( CWeaponAWP )
  57. END_PREDICTION_DATA()
  58. LINK_ENTITY_TO_CLASS( weapon_awp, CWeaponAWP );
  59. PRECACHE_WEAPON_REGISTER( weapon_awp );
  60. #ifndef CLIENT_DLL
  61. BEGIN_DATADESC( CWeaponAWP )
  62. #ifdef AWP_UNZOOM
  63. DEFINE_THINKFUNC( UnzoomThink ),
  64. #endif
  65. END_DATADESC()
  66. #endif
  67. CWeaponAWP::CWeaponAWP()
  68. {
  69. }
  70. void CWeaponAWP::Spawn()
  71. {
  72. Precache();
  73. BaseClass::Spawn();
  74. }
  75. void CWeaponAWP::SecondaryAttack()
  76. {
  77. const float kZoomTime = 0.10f;
  78. CCSPlayer *pPlayer = GetPlayerOwner();
  79. if ( pPlayer == NULL )
  80. {
  81. Assert( pPlayer != NULL );
  82. return;
  83. }
  84. if ( pPlayer->GetFOV() == pPlayer->GetDefaultFOV() )
  85. {
  86. pPlayer->SetFOV( pPlayer, cAWPMidZoomFOV, kZoomTime );
  87. m_weaponMode = Secondary_Mode;
  88. m_fAccuracyPenalty += GetCSWpnData().m_fInaccuracyAltSwitch;
  89. }
  90. else if ( pPlayer->GetFOV() == cAWPMidZoomFOV )
  91. {
  92. pPlayer->SetFOV( pPlayer, cAWPMaxZoomFOV, kZoomTime );
  93. m_weaponMode = Secondary_Mode;
  94. }
  95. else
  96. {
  97. pPlayer->SetFOV( pPlayer, pPlayer->GetDefaultFOV(), kZoomTime );
  98. m_weaponMode = Primary_Mode;
  99. }
  100. #ifndef CLIENT_DLL
  101. // If this isn't guarded, the sound will be emitted twice, once by the server and once by the client.
  102. // Let the server play it since if only the client plays it, it's liable to get played twice cause of
  103. // a prediction error. joy.
  104. //=============================================================================
  105. // HPE_BEGIN:
  106. // [tj] Playing this from the player so that we don't try to play the sound outside the level.
  107. //=============================================================================
  108. if ( GetPlayerOwner() )
  109. {
  110. GetPlayerOwner()->EmitSound( "Default.Zoom" );
  111. }
  112. //=============================================================================
  113. // HPE_END
  114. //=============================================================================
  115. // let the bots hear the rifle zoom
  116. IGameEvent * event = gameeventmanager->CreateEvent( "weapon_zoom" );
  117. if ( event )
  118. {
  119. event->SetInt( "userid", pPlayer->GetUserID() );
  120. gameeventmanager->FireEvent( event );
  121. }
  122. #endif
  123. m_flNextSecondaryAttack = gpGlobals->curtime + 0.3f;
  124. m_zoomFullyActiveTime = gpGlobals->curtime + 0.15; // The worst zoom time from above.
  125. }
  126. float CWeaponAWP::GetInaccuracy() const
  127. {
  128. if ( weapon_accuracy_model.GetInt() == 1 )
  129. {
  130. CCSPlayer *pPlayer = GetPlayerOwner();
  131. if ( !pPlayer )
  132. return 0.0f;
  133. float fSpread = 0.0f;
  134. if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
  135. fSpread = 0.85f;
  136. else if ( pPlayer->GetAbsVelocity().Length2D() > 140 )
  137. fSpread = 0.25f;
  138. else if ( pPlayer->GetAbsVelocity().Length2D() > 10 )
  139. fSpread = 0.10f;
  140. else if ( FBitSet( pPlayer->GetFlags(), FL_DUCKING ) )
  141. fSpread = 0.0f;
  142. else
  143. fSpread = 0.001f;
  144. // If we are not zoomed in, or we have very recently zoomed and are still transitioning, the bullet diverts more.
  145. if (pPlayer->GetFOV() == pPlayer->GetDefaultFOV() || (gpGlobals->curtime < m_zoomFullyActiveTime))
  146. {
  147. fSpread += 0.08f;
  148. }
  149. return fSpread;
  150. }
  151. else
  152. {
  153. return BaseClass::GetInaccuracy();
  154. }
  155. }
  156. void CWeaponAWP::PrimaryAttack()
  157. {
  158. CCSPlayer *pPlayer = GetPlayerOwner();
  159. if ( !pPlayer )
  160. return;
  161. if ( !CSBaseGunFire( GetCSWpnData().m_flCycleTime, m_weaponMode ) )
  162. return;
  163. if ( m_weaponMode == Secondary_Mode )
  164. {
  165. float midFOVdistance = fabs( pPlayer->GetFOV() - (float)cAWPMidZoomFOV );
  166. float farFOVdistance = fabs( pPlayer->GetFOV() - (float)cAWPMaxZoomFOV );
  167. if ( midFOVdistance < farFOVdistance )
  168. {
  169. pPlayer->m_iLastZoom = cAWPMidZoomFOV;
  170. }
  171. else
  172. {
  173. pPlayer->m_iLastZoom = cAWPMaxZoomFOV;
  174. }
  175. #ifdef AWP_UNZOOM
  176. SetContextThink( &CWeaponAWP::UnzoomThink, gpGlobals->curtime + sv_awpunzoomdelay.GetFloat(), SNIPER_ZOOM_CONTEXT );
  177. #else
  178. pPlayer->m_bResumeZoom = true;
  179. pPlayer->SetFOV( pPlayer, pPlayer->GetDefaultFOV(), 0.1f );
  180. m_weaponMode = Primary_Mode;
  181. #endif
  182. }
  183. QAngle angle = pPlayer->GetPunchAngle();
  184. angle.x -= 2;
  185. pPlayer->SetPunchAngle( angle );
  186. }
  187. #ifdef AWP_UNZOOM
  188. void CWeaponAWP::UnzoomThink( void )
  189. {
  190. CCSPlayer *pPlayer = GetPlayerOwner();
  191. if (pPlayer == NULL)
  192. {
  193. Assert(pPlayer != NULL);
  194. return;
  195. }
  196. pPlayer->SetFOV( pPlayer, pPlayer->GetDefaultFOV(), 0.1f );
  197. }
  198. #endif
  199. float CWeaponAWP::GetMaxSpeed() const
  200. {
  201. CCSPlayer *pPlayer = GetPlayerOwner();
  202. if (pPlayer == NULL)
  203. {
  204. Assert(pPlayer != NULL);
  205. return BaseClass::GetMaxSpeed();
  206. }
  207. if ( pPlayer->GetFOV() == pPlayer->GetDefaultFOV() )
  208. {
  209. return BaseClass::GetMaxSpeed();
  210. }
  211. else
  212. {
  213. // Slower speed when zoomed in.
  214. return 150;
  215. }
  216. }
  217. bool CWeaponAWP::IsAwp() const
  218. {
  219. return true;
  220. }
  221. bool CWeaponAWP::Reload()
  222. {
  223. m_weaponMode = Primary_Mode;
  224. return BaseClass::Reload();
  225. }
  226. bool CWeaponAWP::Deploy()
  227. {
  228. // don't allow weapon switching to shortcut cycle time (quickswitch exploit)
  229. float fOldNextPrimaryAttack = m_flNextPrimaryAttack;
  230. float fOldNextSecondaryAttack = m_flNextSecondaryAttack;
  231. if ( !BaseClass::Deploy() )
  232. return false;
  233. m_weaponMode = Primary_Mode;
  234. m_flNextPrimaryAttack = MAX( m_flNextPrimaryAttack, fOldNextPrimaryAttack );
  235. m_flNextSecondaryAttack = MAX( m_flNextSecondaryAttack, fOldNextSecondaryAttack );
  236. return true;
  237. }