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.

351 lines
7.0 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 CWeaponM4A1 C_WeaponM4A1
  10. #include "c_cs_player.h"
  11. #else
  12. #include "cs_player.h"
  13. #endif
  14. class CWeaponM4A1 : public CWeaponCSBaseGun
  15. {
  16. public:
  17. DECLARE_CLASS( CWeaponM4A1, CWeaponCSBaseGun );
  18. DECLARE_NETWORKCLASS();
  19. DECLARE_PREDICTABLE();
  20. CWeaponM4A1();
  21. virtual void Spawn();
  22. virtual void Precache();
  23. virtual void SecondaryAttack();
  24. virtual void PrimaryAttack();
  25. virtual bool Deploy();
  26. virtual bool Reload();
  27. virtual void WeaponIdle();
  28. virtual bool Holster( CBaseCombatWeapon *pSwitchingTo );
  29. virtual void Drop( const Vector &vecVelocity );
  30. virtual float GetInaccuracy() const;
  31. virtual CSWeaponID GetWeaponID( void ) const { return WEAPON_M4A1; }
  32. // return true if this weapon has a silencer equipped
  33. virtual bool IsSilenced( void ) const { return m_bSilencerOn; }
  34. virtual Activity GetDeployActivity( void );
  35. #ifdef CLIENT_DLL
  36. virtual int GetMuzzleFlashStyle( void );
  37. #endif
  38. virtual const char *GetWorldModel( void ) const;
  39. virtual int GetWorldModelIndex( void );
  40. private:
  41. CWeaponM4A1( const CWeaponM4A1 & );
  42. void DoFireEffects();
  43. CNetworkVar( bool, m_bSilencerOn );
  44. CNetworkVar( float, m_flDoneSwitchingSilencer ); // soonest time switching the silencer will be complete
  45. int m_silencedModelIndex;
  46. bool m_inPrecache;
  47. };
  48. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponM4A1, DT_WeaponM4A1 )
  49. BEGIN_NETWORK_TABLE( CWeaponM4A1, DT_WeaponM4A1 )
  50. #ifdef CLIENT_DLL
  51. RecvPropBool( RECVINFO( m_bSilencerOn ) ),
  52. RecvPropTime( RECVINFO( m_flDoneSwitchingSilencer ) ),
  53. #else
  54. SendPropBool( SENDINFO( m_bSilencerOn ) ),
  55. SendPropTime( SENDINFO( m_flDoneSwitchingSilencer ) ),
  56. #endif
  57. END_NETWORK_TABLE()
  58. BEGIN_PREDICTION_DATA( CWeaponM4A1 )
  59. END_PREDICTION_DATA()
  60. LINK_ENTITY_TO_CLASS( weapon_m4a1, CWeaponM4A1 );
  61. PRECACHE_WEAPON_REGISTER( weapon_m4a1 );
  62. CWeaponM4A1::CWeaponM4A1()
  63. {
  64. m_bSilencerOn = false;
  65. m_flDoneSwitchingSilencer = 0.0f;
  66. m_inPrecache = false;
  67. }
  68. void CWeaponM4A1::Spawn( )
  69. {
  70. BaseClass::Spawn();
  71. m_bSilencerOn = false;
  72. m_weaponMode = Primary_Mode;
  73. m_flDoneSwitchingSilencer = 0.0f;
  74. m_bDelayFire = true;
  75. }
  76. void CWeaponM4A1::Precache()
  77. {
  78. m_inPrecache = true;
  79. BaseClass::Precache();
  80. m_silencedModelIndex = CBaseEntity::PrecacheModel( GetCSWpnData().m_szSilencerModel );
  81. m_inPrecache = false;
  82. }
  83. int CWeaponM4A1::GetWorldModelIndex( void )
  84. {
  85. if ( !m_bSilencerOn || m_inPrecache )
  86. {
  87. return m_iWorldModelIndex;
  88. }
  89. else
  90. {
  91. return m_silencedModelIndex;
  92. }
  93. }
  94. const char * CWeaponM4A1::GetWorldModel( void ) const
  95. {
  96. if ( !m_bSilencerOn || m_inPrecache )
  97. {
  98. return BaseClass::GetWorldModel();
  99. }
  100. else
  101. {
  102. return GetCSWpnData().m_szSilencerModel;
  103. }
  104. }
  105. bool CWeaponM4A1::Deploy()
  106. {
  107. bool ret = BaseClass::Deploy();
  108. m_flDoneSwitchingSilencer = 0.0f;
  109. m_bDelayFire = true;
  110. return ret;
  111. }
  112. Activity CWeaponM4A1::GetDeployActivity( void )
  113. {
  114. if( IsSilenced() )
  115. {
  116. return ACT_VM_DRAW_SILENCED;
  117. }
  118. else
  119. {
  120. return ACT_VM_DRAW;
  121. }
  122. }
  123. bool CWeaponM4A1::Holster( CBaseCombatWeapon *pSwitchingTo )
  124. {
  125. if ( gpGlobals->curtime < m_flDoneSwitchingSilencer )
  126. {
  127. // still switching the silencer. Cancel the switch.
  128. m_bSilencerOn = !m_bSilencerOn;
  129. m_weaponMode = m_bSilencerOn ? Secondary_Mode : Primary_Mode;
  130. SetWeaponModelIndex( GetWorldModel() );
  131. }
  132. return BaseClass::Holster( pSwitchingTo );
  133. }
  134. void CWeaponM4A1::Drop( const Vector &vecVelocity )
  135. {
  136. if ( gpGlobals->curtime < m_flDoneSwitchingSilencer )
  137. {
  138. // still switching the silencer. Cancel the switch.
  139. m_bSilencerOn = !m_bSilencerOn;
  140. m_weaponMode = m_bSilencerOn ? Secondary_Mode : Primary_Mode;
  141. SetWeaponModelIndex( GetWorldModel() );
  142. }
  143. BaseClass::Drop( vecVelocity );
  144. }
  145. void CWeaponM4A1::SecondaryAttack()
  146. {
  147. if ( m_bSilencerOn )
  148. {
  149. m_bSilencerOn = false;
  150. m_weaponMode = Primary_Mode;
  151. SendWeaponAnim( ACT_VM_DETACH_SILENCER );
  152. }
  153. else
  154. {
  155. m_bSilencerOn = true;
  156. m_weaponMode = Secondary_Mode;
  157. SendWeaponAnim( ACT_VM_ATTACH_SILENCER );
  158. }
  159. m_flDoneSwitchingSilencer = gpGlobals->curtime + 2;
  160. m_flNextSecondaryAttack = gpGlobals->curtime + 2;
  161. m_flNextPrimaryAttack = gpGlobals->curtime + 2;
  162. SetWeaponIdleTime( gpGlobals->curtime + 2 );
  163. SetWeaponModelIndex( GetWorldModel() );
  164. }
  165. float CWeaponM4A1::GetInaccuracy() const
  166. {
  167. if ( weapon_accuracy_model.GetInt() == 1 )
  168. {
  169. CCSPlayer *pPlayer = GetPlayerOwner();
  170. if ( !pPlayer )
  171. return 0.0f;
  172. if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
  173. {
  174. return 0.035f + 0.4f * m_flAccuracy;
  175. }
  176. else if (pPlayer->GetAbsVelocity().Length2D() > 140)
  177. {
  178. return 0.035f + 0.07f * m_flAccuracy;
  179. }
  180. else
  181. {
  182. if ( m_bSilencerOn )
  183. return 0.025f * m_flAccuracy;
  184. else
  185. return 0.02f * m_flAccuracy;
  186. }
  187. }
  188. else
  189. {
  190. return BaseClass::GetInaccuracy();
  191. }
  192. }
  193. void CWeaponM4A1::PrimaryAttack()
  194. {
  195. CCSPlayer *pPlayer = GetPlayerOwner();
  196. if ( !pPlayer )
  197. return;
  198. if ( !CSBaseGunFire( GetCSWpnData().m_flCycleTime, m_weaponMode ) )
  199. return;
  200. if ( m_bSilencerOn )
  201. SendWeaponAnim( ACT_VM_PRIMARYATTACK_SILENCED );
  202. pPlayer = GetPlayerOwner();
  203. // CSBaseGunFire can kill us, forcing us to drop our weapon, if we shoot something that explodes
  204. if ( !pPlayer )
  205. return;
  206. if (pPlayer->GetAbsVelocity().Length2D() > 5)
  207. pPlayer->KickBack (1.0, 0.45, 0.28, 0.045, 3.75, 3, 7);
  208. else if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
  209. pPlayer->KickBack (1.2, 0.5, 0.23, 0.15, 5.5, 3.5, 6);
  210. else if ( FBitSet( pPlayer->GetFlags(), FL_DUCKING ) )
  211. pPlayer->KickBack (0.6, 0.3, 0.2, 0.0125, 3.25, 2, 7);
  212. else
  213. pPlayer->KickBack (0.65, 0.35, 0.25, 0.015, 3.5, 2.25, 7);
  214. }
  215. void CWeaponM4A1::DoFireEffects()
  216. {
  217. if ( !m_bSilencerOn )
  218. {
  219. CCSPlayer *pPlayer = GetPlayerOwner();
  220. if ( pPlayer )
  221. {
  222. pPlayer->DoMuzzleFlash();
  223. }
  224. }
  225. }
  226. bool CWeaponM4A1::Reload()
  227. {
  228. CCSPlayer *pPlayer = GetPlayerOwner();
  229. if ( !pPlayer )
  230. return false;
  231. if (pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) <= 0)
  232. return false;
  233. int iResult = 0;
  234. if ( m_bSilencerOn )
  235. iResult = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD_SILENCED );
  236. else
  237. iResult = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
  238. if ( !iResult )
  239. return false;
  240. pPlayer->SetAnimation( PLAYER_RELOAD );
  241. if ((iResult) && (pPlayer->GetFOV() != pPlayer->GetDefaultFOV()))
  242. {
  243. pPlayer->SetFOV( pPlayer, pPlayer->GetDefaultFOV() );
  244. }
  245. m_flAccuracy = 0.2;
  246. pPlayer->m_iShotsFired = 0;
  247. m_bDelayFire = false;
  248. return true;
  249. }
  250. void CWeaponM4A1::WeaponIdle()
  251. {
  252. if (m_flTimeWeaponIdle > gpGlobals->curtime)
  253. return;
  254. // only idle if the slid isn't back
  255. if ( m_iClip1 != 0 )
  256. {
  257. SetWeaponIdleTime( gpGlobals->curtime + GetCSWpnData().m_flIdleInterval );
  258. if ( m_bSilencerOn )
  259. SendWeaponAnim( ACT_VM_IDLE_SILENCED );
  260. else
  261. SendWeaponAnim( ACT_VM_IDLE );
  262. }
  263. }
  264. #ifdef CLIENT_DLL
  265. int CWeaponM4A1::GetMuzzleFlashStyle( void )
  266. {
  267. if( m_bSilencerOn )
  268. {
  269. return CS_MUZZLEFLASH_NONE;
  270. }
  271. else
  272. {
  273. return CS_MUZZLEFLASH_X;
  274. }
  275. }
  276. #endif