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.

316 lines
6.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "weapon_csbase.h"
  8. #include "fx_cs_shared.h"
  9. #if defined( CLIENT_DLL )
  10. #define CWeaponElite C_WeaponElite
  11. #include "c_cs_player.h"
  12. #include "c_te_effect_dispatch.h"
  13. #else
  14. #include "cs_player.h"
  15. #endif
  16. class CWeaponElite : public CWeaponCSBase
  17. {
  18. public:
  19. DECLARE_CLASS( CWeaponElite, CWeaponCSBase );
  20. DECLARE_NETWORKCLASS();
  21. DECLARE_PREDICTABLE();
  22. CWeaponElite();
  23. virtual void Spawn();
  24. virtual void Precache();
  25. virtual void PrimaryAttack();
  26. virtual bool Deploy();
  27. virtual bool Reload();
  28. virtual void WeaponIdle();
  29. virtual float GetInaccuracy() const;
  30. virtual CSWeaponID GetWeaponID( void ) const { return WEAPON_ELITE; }
  31. #ifdef CLIENT_DLL
  32. virtual int GetMuzzleAttachment( void );
  33. virtual bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options );
  34. #endif
  35. virtual const char *GetWorldModel( void ) const;
  36. virtual int GetWorldModelIndex( void );
  37. protected:
  38. bool FiringLeft() const;
  39. private:
  40. CWeaponElite( const CWeaponElite & );
  41. float m_flLastFire;
  42. int m_droppedModelIndex;
  43. bool m_inPrecache;
  44. };
  45. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponElite, DT_WeaponElite )
  46. BEGIN_NETWORK_TABLE( CWeaponElite, DT_WeaponElite )
  47. END_NETWORK_TABLE()
  48. #if defined CLIENT_DLL
  49. BEGIN_PREDICTION_DATA( CWeaponElite )
  50. DEFINE_FIELD( m_flLastFire, FIELD_FLOAT ),
  51. END_PREDICTION_DATA()
  52. #endif
  53. LINK_ENTITY_TO_CLASS( weapon_elite, CWeaponElite );
  54. PRECACHE_WEAPON_REGISTER( weapon_elite );
  55. CWeaponElite::CWeaponElite()
  56. {
  57. m_flLastFire = gpGlobals->curtime;
  58. m_inPrecache = false;
  59. }
  60. void CWeaponElite::Spawn( )
  61. {
  62. m_flAccuracy = 0.88;
  63. BaseClass::Spawn();
  64. }
  65. void CWeaponElite::Precache()
  66. {
  67. m_inPrecache = true;
  68. BaseClass::Precache();
  69. PrecacheModel( "models/weapons/w_eq_eholster_elite.mdl" );
  70. PrecacheModel( "models/weapons/w_eq_eholster.mdl" );
  71. PrecacheModel( "models/weapons/w_pist_elite_single.mdl" );
  72. m_droppedModelIndex = CBaseEntity::PrecacheModel( GetCSWpnData().m_szDroppedModel );
  73. m_inPrecache = false;
  74. }
  75. bool CWeaponElite::Deploy( )
  76. {
  77. m_flAccuracy = 0.88;
  78. return BaseClass::Deploy();
  79. }
  80. int CWeaponElite::GetWorldModelIndex( void )
  81. {
  82. if ( GetOwner() || m_inPrecache )
  83. {
  84. return m_iWorldModelIndex;
  85. }
  86. else
  87. {
  88. return m_droppedModelIndex;
  89. }
  90. }
  91. const char * CWeaponElite::GetWorldModel( void ) const
  92. {
  93. if ( GetOwner() || m_inPrecache )
  94. {
  95. return BaseClass::GetWorldModel();
  96. }
  97. else
  98. {
  99. return GetCSWpnData().m_szDroppedModel;
  100. }
  101. }
  102. bool CWeaponElite::FiringLeft() const
  103. {
  104. // fire left-hand gun with even number of bullets left
  105. return (m_iClip1 & 1) == 0;
  106. }
  107. float CWeaponElite::GetInaccuracy() const
  108. {
  109. if ( weapon_accuracy_model.GetInt() == 1 )
  110. {
  111. CCSPlayer *pPlayer = GetPlayerOwner();
  112. if ( !pPlayer )
  113. return 0.0f;
  114. if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
  115. return 1.3f * (1 - m_flAccuracy);
  116. else if (pPlayer->GetAbsVelocity().Length2D() > 5)
  117. return 0.175f * (1 - m_flAccuracy);
  118. else if ( FBitSet( pPlayer->GetFlags(), FL_DUCKING ) )
  119. return 0.08f * (1 - m_flAccuracy);
  120. else
  121. return 0.1f * (1 - m_flAccuracy);
  122. }
  123. else
  124. return BaseClass::GetInaccuracy();
  125. }
  126. void CWeaponElite::PrimaryAttack()
  127. {
  128. CCSPlayer *pPlayer = GetPlayerOwner();
  129. if ( !pPlayer )
  130. return;
  131. // Mark the time of this shot and determine the accuracy modifier based on the last shot fired...
  132. m_flAccuracy -= (0.275)*(0.325 - (gpGlobals->curtime - m_flLastFire));
  133. if (m_flAccuracy > 0.88)
  134. m_flAccuracy = 0.88;
  135. else if (m_flAccuracy < 0.55)
  136. m_flAccuracy = 0.55;
  137. m_flLastFire = gpGlobals->curtime;
  138. if (m_iClip1 <= 0)
  139. {
  140. if ( m_bFireOnEmpty )
  141. {
  142. PlayEmptySound();
  143. m_flNextPrimaryAttack = gpGlobals->curtime + 0.1f;
  144. m_bFireOnEmpty = false;
  145. }
  146. return;
  147. }
  148. pPlayer->m_iShotsFired++;
  149. m_iClip1--;
  150. pPlayer->DoMuzzleFlash();
  151. //SetPlayerShieldAnim();
  152. // player "shoot" animation
  153. pPlayer->SetAnimation( PLAYER_ATTACK1 );
  154. FX_FireBullets(
  155. pPlayer->entindex(),
  156. pPlayer->Weapon_ShootPosition(),
  157. pPlayer->EyeAngles() + 2.0f * pPlayer->GetPunchAngle(),
  158. GetWeaponID(),
  159. FiringLeft() ? Secondary_Mode : Primary_Mode,
  160. CBaseEntity::GetPredictionRandomSeed() & 255,
  161. GetInaccuracy(),
  162. GetSpread());
  163. m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + GetCSWpnData().m_flCycleTime;
  164. if (!m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0)
  165. {
  166. // HEV suit - indicate out of ammo condition
  167. pPlayer->SetSuitUpdate("!HEV_AMO0", false, 0);
  168. }
  169. SetWeaponIdleTime( gpGlobals->curtime + 2.5 );
  170. if ( FiringLeft() )
  171. {
  172. if ( m_iClip1 > 0 )
  173. SendWeaponAnim( ACT_VM_SECONDARYATTACK );
  174. else
  175. SendWeaponAnim( ACT_VM_DRYFIRE );
  176. }
  177. else
  178. {
  179. if ( m_iClip1 > 1 )
  180. SendWeaponAnim( ACT_VM_PRIMARYATTACK );
  181. else
  182. SendWeaponAnim( ACT_VM_DRYFIRE_LEFT );
  183. }
  184. // update accuracy
  185. m_fAccuracyPenalty += GetCSWpnData().m_fInaccuracyImpulseFire[Primary_Mode];
  186. QAngle punchAngle = pPlayer->GetPunchAngle();
  187. punchAngle.x -= 2;
  188. pPlayer->SetPunchAngle( punchAngle );
  189. //ResetPlayerShieldAnim();
  190. }
  191. bool CWeaponElite::Reload()
  192. {
  193. if ( !DefaultPistolReload() )
  194. return false;
  195. m_flAccuracy = 0.88;
  196. return true;
  197. }
  198. void CWeaponElite::WeaponIdle()
  199. {
  200. if (m_flTimeWeaponIdle > gpGlobals->curtime)
  201. return;
  202. /*
  203. // switching to the idle with the slide back on the right pistol causes animation pops transitioning
  204. // from/to the depot/holster animations. The pop transition to the reload is less noticeable, so
  205. // we'll live with that one
  206. if ( m_iClip1 == 1 )
  207. {
  208. SendWeaponAnim( ACT_VM_IDLE_EMPTY_LEFT );
  209. }
  210. */
  211. // only idle if either slide isn't back
  212. if ( m_iClip1 >= 2 )
  213. {
  214. SendWeaponAnim( ACT_VM_IDLE );
  215. }
  216. }
  217. #ifdef CLIENT_DLL
  218. bool CWeaponElite::OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options )
  219. {
  220. if( event == 5001 )
  221. {
  222. C_CSPlayer *pPlayer = ToCSPlayer( GetOwner() );
  223. if( pPlayer && pPlayer->GetFOV() < pPlayer->GetDefaultFOV() && HideViewModelWhenZoomed() )
  224. return true;
  225. CEffectData data;
  226. data.m_fFlags = 0;
  227. data.m_hEntity = pViewModel->GetRefEHandle();
  228. data.m_nAttachmentIndex = FiringLeft() ? 1 : 2; // toggle muzzle flash
  229. data.m_flScale = GetCSWpnData().m_flMuzzleScale;
  230. DispatchEffect( "CS_MuzzleFlash", data );
  231. return true;
  232. }
  233. return BaseClass::OnFireEvent( pViewModel, origin, angles, event, options );
  234. }
  235. int CWeaponElite::GetMuzzleAttachment( void )
  236. {
  237. return LookupAttachment( FiringLeft() ? "muzzle_flash_l" : "muzzle_flash_r" );
  238. }
  239. #endif