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.

242 lines
6.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #if defined( CLIENT_DLL )
  8. #include "c_hl2mp_player.h"
  9. #else
  10. #include "hl2mp_player.h"
  11. #endif
  12. #include "weapon_hl2mpbase_machinegun.h"
  13. #include "in_buttons.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. IMPLEMENT_NETWORKCLASS_ALIASED( HL2MPMachineGun, DT_HL2MPMachineGun )
  17. BEGIN_NETWORK_TABLE( CHL2MPMachineGun, DT_HL2MPMachineGun )
  18. END_NETWORK_TABLE()
  19. BEGIN_PREDICTION_DATA( CHL2MPMachineGun )
  20. END_PREDICTION_DATA()
  21. //=========================================================
  22. // >> CHLSelectFireMachineGun
  23. //=========================================================
  24. BEGIN_DATADESC( CHL2MPMachineGun )
  25. DEFINE_FIELD( m_nShotsFired, FIELD_INTEGER ),
  26. DEFINE_FIELD( m_flNextSoundTime, FIELD_TIME ),
  27. END_DATADESC()
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. CHL2MPMachineGun::CHL2MPMachineGun( void )
  32. {
  33. }
  34. const Vector &CHL2MPMachineGun::GetBulletSpread( void )
  35. {
  36. static Vector cone = VECTOR_CONE_3DEGREES;
  37. return cone;
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Purpose:
  41. //
  42. //
  43. //-----------------------------------------------------------------------------
  44. void CHL2MPMachineGun::PrimaryAttack( void )
  45. {
  46. // Only the player fires this way so we can cast
  47. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  48. if (!pPlayer)
  49. return;
  50. // Abort here to handle burst and auto fire modes
  51. if ( (UsesClipsForAmmo1() && m_iClip1 == 0) || ( !UsesClipsForAmmo1() && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) )
  52. return;
  53. m_nShotsFired++;
  54. pPlayer->DoMuzzleFlash();
  55. // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems,
  56. // especially if the weapon we're firing has a really fast rate of fire.
  57. int iBulletsToFire = 0;
  58. float fireRate = GetFireRate();
  59. while ( m_flNextPrimaryAttack <= gpGlobals->curtime )
  60. {
  61. // MUST call sound before removing a round from the clip of a CHLMachineGun
  62. WeaponSound(SINGLE, m_flNextPrimaryAttack);
  63. m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
  64. iBulletsToFire++;
  65. }
  66. // Make sure we don't fire more than the amount in the clip, if this weapon uses clips
  67. if ( UsesClipsForAmmo1() )
  68. {
  69. if ( iBulletsToFire > m_iClip1 )
  70. iBulletsToFire = m_iClip1;
  71. m_iClip1 -= iBulletsToFire;
  72. }
  73. CHL2MP_Player *pHL2MPPlayer = ToHL2MPPlayer( pPlayer );
  74. // Fire the bullets
  75. FireBulletsInfo_t info;
  76. info.m_iShots = iBulletsToFire;
  77. info.m_vecSrc = pHL2MPPlayer->Weapon_ShootPosition( );
  78. info.m_vecDirShooting = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
  79. info.m_vecSpread = pHL2MPPlayer->GetAttackSpread( this );
  80. info.m_flDistance = MAX_TRACE_LENGTH;
  81. info.m_iAmmoType = m_iPrimaryAmmoType;
  82. info.m_iTracerFreq = 2;
  83. FireBullets( info );
  84. //Factor in the view kick
  85. AddViewKick();
  86. if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
  87. {
  88. // HEV suit - indicate out of ammo condition
  89. pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
  90. }
  91. SendWeaponAnim( GetPrimaryAttackActivity() );
  92. pPlayer->SetAnimation( PLAYER_ATTACK1 );
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose:
  96. // Input : &info -
  97. //-----------------------------------------------------------------------------
  98. void CHL2MPMachineGun::FireBullets( const FireBulletsInfo_t &info )
  99. {
  100. if(CBasePlayer *pPlayer = ToBasePlayer ( GetOwner() ) )
  101. {
  102. pPlayer->FireBullets(info);
  103. }
  104. }
  105. //-----------------------------------------------------------------------------
  106. // Purpose:
  107. //-----------------------------------------------------------------------------
  108. void CHL2MPMachineGun::DoMachineGunKick( CBasePlayer *pPlayer, float dampEasy, float maxVerticleKickAngle, float fireDurationTime, float slideLimitTime )
  109. {
  110. #define KICK_MIN_X 0.2f //Degrees
  111. #define KICK_MIN_Y 0.2f //Degrees
  112. #define KICK_MIN_Z 0.1f //Degrees
  113. QAngle vecScratch;
  114. int iSeed = CBaseEntity::GetPredictionRandomSeed() & 255;
  115. //Find how far into our accuracy degradation we are
  116. float duration = ( fireDurationTime > slideLimitTime ) ? slideLimitTime : fireDurationTime;
  117. float kickPerc = duration / slideLimitTime;
  118. // do this to get a hard discontinuity, clear out anything under 10 degrees punch
  119. pPlayer->ViewPunchReset( 10 );
  120. //Apply this to the view angles as well
  121. vecScratch.x = -( KICK_MIN_X + ( maxVerticleKickAngle * kickPerc ) );
  122. vecScratch.y = -( KICK_MIN_Y + ( maxVerticleKickAngle * kickPerc ) ) / 3;
  123. vecScratch.z = KICK_MIN_Z + ( maxVerticleKickAngle * kickPerc ) / 8;
  124. RandomSeed( iSeed );
  125. //Wibble left and right
  126. if ( RandomInt( -1, 1 ) >= 0 )
  127. vecScratch.y *= -1;
  128. iSeed++;
  129. //Wobble up and down
  130. if ( RandomInt( -1, 1 ) >= 0 )
  131. vecScratch.z *= -1;
  132. //Clip this to our desired min/max
  133. UTIL_ClipPunchAngleOffset( vecScratch, pPlayer->m_Local.m_vecPunchAngle, QAngle( 24.0f, 3.0f, 1.0f ) );
  134. //Add it to the view punch
  135. // NOTE: 0.5 is just tuned to match the old effect before the punch became simulated
  136. pPlayer->ViewPunch( vecScratch * 0.5 );
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Purpose: Reset our shots fired
  140. //-----------------------------------------------------------------------------
  141. bool CHL2MPMachineGun::Deploy( void )
  142. {
  143. m_nShotsFired = 0;
  144. return BaseClass::Deploy();
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Purpose: Make enough sound events to fill the estimated think interval
  148. // returns: number of shots needed
  149. //-----------------------------------------------------------------------------
  150. int CHL2MPMachineGun::WeaponSoundRealtime( WeaponSound_t shoot_type )
  151. {
  152. int numBullets = 0;
  153. // ran out of time, clamp to current
  154. if (m_flNextSoundTime < gpGlobals->curtime)
  155. {
  156. m_flNextSoundTime = gpGlobals->curtime;
  157. }
  158. // make enough sound events to fill up the next estimated think interval
  159. float dt = clamp( m_flAnimTime - m_flPrevAnimTime, 0, 0.2 );
  160. if (m_flNextSoundTime < gpGlobals->curtime + dt)
  161. {
  162. WeaponSound( SINGLE_NPC, m_flNextSoundTime );
  163. m_flNextSoundTime += GetFireRate();
  164. numBullets++;
  165. }
  166. if (m_flNextSoundTime < gpGlobals->curtime + dt)
  167. {
  168. WeaponSound( SINGLE_NPC, m_flNextSoundTime );
  169. m_flNextSoundTime += GetFireRate();
  170. numBullets++;
  171. }
  172. return numBullets;
  173. }
  174. //-----------------------------------------------------------------------------
  175. // Purpose:
  176. //-----------------------------------------------------------------------------
  177. void CHL2MPMachineGun::ItemPostFrame( void )
  178. {
  179. CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
  180. if ( pOwner == NULL )
  181. return;
  182. // Debounce the recoiling counter
  183. if ( ( pOwner->m_nButtons & IN_ATTACK ) == false )
  184. {
  185. m_nShotsFired = 0;
  186. }
  187. BaseClass::ItemPostFrame();
  188. }