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.

243 lines
5.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "weapon_csbasegun.h"
  8. #include "fx_cs_shared.h"
  9. #if defined( CLIENT_DLL )
  10. #define CWeaponFamas C_WeaponFamas
  11. #include "c_cs_player.h"
  12. #else
  13. #include "cs_player.h"
  14. #endif
  15. class CWeaponFamas : public CWeaponCSBaseGun
  16. {
  17. public:
  18. DECLARE_CLASS( CWeaponFamas, CWeaponCSBase );
  19. DECLARE_NETWORKCLASS();
  20. DECLARE_PREDICTABLE();
  21. CWeaponFamas();
  22. virtual void PrimaryAttack();
  23. virtual void SecondaryAttack();
  24. virtual bool Deploy();
  25. virtual float GetInaccuracy() const;
  26. virtual void ItemPostFrame();
  27. void FamasFire( float flSpread, bool bFireBurst );
  28. void FireRemaining();
  29. virtual CSWeaponID GetWeaponID( void ) const { return WEAPON_FAMAS; }
  30. private:
  31. CWeaponFamas( const CWeaponFamas & );
  32. CNetworkVar( bool, m_bBurstMode );
  33. CNetworkVar( int, m_iBurstShotsRemaining );
  34. float m_fNextBurstShot; // time to shoot the next bullet in burst fire mode
  35. };
  36. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponFamas, DT_WeaponFamas )
  37. BEGIN_NETWORK_TABLE( CWeaponFamas, DT_WeaponFamas )
  38. #ifdef CLIENT_DLL
  39. RecvPropBool( RECVINFO( m_bBurstMode ) ),
  40. RecvPropInt( RECVINFO( m_iBurstShotsRemaining ) ),
  41. #else
  42. SendPropBool( SENDINFO( m_bBurstMode ) ),
  43. SendPropInt( SENDINFO( m_iBurstShotsRemaining ) ),
  44. #endif
  45. END_NETWORK_TABLE()
  46. #if defined(CLIENT_DLL)
  47. BEGIN_PREDICTION_DATA( CWeaponFamas )
  48. DEFINE_PRED_FIELD( m_iBurstShotsRemaining, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  49. DEFINE_PRED_FIELD( m_fNextBurstShot, FIELD_FLOAT, 0 ),
  50. END_PREDICTION_DATA()
  51. #endif
  52. LINK_ENTITY_TO_CLASS( weapon_famas, CWeaponFamas );
  53. PRECACHE_WEAPON_REGISTER( weapon_famas );
  54. const float kFamasBurstCycleTime = 0.075f;
  55. CWeaponFamas::CWeaponFamas()
  56. {
  57. m_bBurstMode = false;
  58. }
  59. bool CWeaponFamas::Deploy( )
  60. {
  61. m_iBurstShotsRemaining = 0;
  62. m_fNextBurstShot = 0.0f;
  63. m_flAccuracy = 0.9f;
  64. return BaseClass::Deploy();
  65. }
  66. // Secondary attack could be three-round burst mode
  67. void CWeaponFamas::SecondaryAttack()
  68. {
  69. CCSPlayer *pPlayer = GetPlayerOwner();
  70. if ( !pPlayer )
  71. return;
  72. if ( m_bBurstMode )
  73. {
  74. ClientPrint( pPlayer, HUD_PRINTCENTER, "#Switch_To_FullAuto" );
  75. m_bBurstMode = false;
  76. m_weaponMode = Primary_Mode;
  77. }
  78. else
  79. {
  80. ClientPrint( pPlayer, HUD_PRINTCENTER, "#Switch_To_BurstFire" );
  81. m_bBurstMode = true;
  82. m_weaponMode = Secondary_Mode;
  83. }
  84. m_flNextSecondaryAttack = gpGlobals->curtime + 0.3;
  85. }
  86. float CWeaponFamas::GetInaccuracy() const
  87. {
  88. if ( weapon_accuracy_model.GetInt() == 1 )
  89. {
  90. float fAutoPenalty = m_bBurstMode ? 0.0f : 0.01f;
  91. CCSPlayer *pPlayer = GetPlayerOwner();
  92. if ( !pPlayer )
  93. return 0.0f;
  94. if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) ) // if player is in air
  95. return 0.03f + 0.3f * m_flAccuracy + fAutoPenalty;
  96. else if ( pPlayer->GetAbsVelocity().Length2D() > 140 ) // if player is moving
  97. return 0.03f + 0.07f * m_flAccuracy + fAutoPenalty;
  98. /* new code */
  99. else
  100. return 0.02f * m_flAccuracy + fAutoPenalty;
  101. }
  102. else
  103. return BaseClass::GetInaccuracy();
  104. }
  105. void CWeaponFamas::ItemPostFrame()
  106. {
  107. if ( m_iBurstShotsRemaining > 0 && gpGlobals->curtime >= m_fNextBurstShot )
  108. FireRemaining();
  109. BaseClass::ItemPostFrame();
  110. }
  111. // GOOSEMAN : FireRemaining used by Glock18
  112. void CWeaponFamas::FireRemaining()
  113. {
  114. m_iClip1--;
  115. if (m_iClip1 < 0)
  116. {
  117. m_iClip1 = 0;
  118. m_iBurstShotsRemaining = 0;
  119. m_fNextBurstShot = 0.0f;
  120. return;
  121. }
  122. CCSPlayer *pPlayer = GetPlayerOwner();
  123. if ( !pPlayer )
  124. Error( "!pPlayer" );
  125. // Famas burst mode
  126. FX_FireBullets(
  127. pPlayer->entindex(),
  128. pPlayer->Weapon_ShootPosition(),
  129. pPlayer->EyeAngles() + 2.0f * pPlayer->GetPunchAngle(),
  130. GetWeaponID(),
  131. Secondary_Mode,
  132. CBaseEntity::GetPredictionRandomSeed() & 255,
  133. GetInaccuracy(),
  134. GetSpread(),
  135. m_fNextBurstShot);
  136. SendWeaponAnim( ACT_VM_PRIMARYATTACK );
  137. pPlayer->DoMuzzleFlash();
  138. pPlayer->SetAnimation( PLAYER_ATTACK1 );
  139. pPlayer->m_iShotsFired++;
  140. --m_iBurstShotsRemaining;
  141. if ( m_iBurstShotsRemaining > 0 )
  142. m_fNextBurstShot += kFamasBurstCycleTime;
  143. else
  144. m_fNextBurstShot = 0.0f;
  145. // update accuracy
  146. m_fAccuracyPenalty += GetCSWpnData().m_fInaccuracyImpulseFire[Secondary_Mode];
  147. }
  148. void CWeaponFamas::PrimaryAttack()
  149. {
  150. CCSPlayer *pPlayer = GetPlayerOwner();
  151. if ( !pPlayer )
  152. return;
  153. // don't fire underwater
  154. if (pPlayer->GetWaterLevel() == 3)
  155. {
  156. PlayEmptySound( );
  157. m_flNextPrimaryAttack = gpGlobals->curtime + 0.15;
  158. return;
  159. }
  160. pPlayer = GetPlayerOwner();
  161. if ( !pPlayer )
  162. return;
  163. float flCycleTime = GetCSWpnData().m_flCycleTime;
  164. // change a few things if we're in burst mode
  165. if ( m_bBurstMode )
  166. {
  167. flCycleTime = 0.55f;
  168. m_iBurstShotsRemaining = 2;
  169. m_fNextBurstShot = gpGlobals->curtime + kFamasBurstCycleTime;
  170. }
  171. if ( !CSBaseGunFire( flCycleTime, m_weaponMode ) )
  172. return;
  173. if ( pPlayer->GetAbsVelocity().Length2D() > 5 )
  174. pPlayer->KickBack ( 1, 0.45, 0.275, 0.05, 4, 2.5, 7 );
  175. else if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
  176. pPlayer->KickBack ( 1.25, 0.45, 0.22, 0.18, 5.5, 4, 5 );
  177. else if ( FBitSet( pPlayer->GetFlags(), FL_DUCKING ) )
  178. pPlayer->KickBack ( 0.575, 0.325, 0.2, 0.011, 3.25, 2, 8 );
  179. else
  180. pPlayer->KickBack ( 0.625, 0.375, 0.25, 0.0125, 3.5, 2.25, 8 );
  181. }