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.

232 lines
5.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "fx_dod_shared.h"
  8. #include "weapon_riflegrenade.h"
  9. #ifdef CLIENT_DLL
  10. #include "prediction.h"
  11. #endif
  12. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponBaseRifleGrenade, DT_WeaponBaseRifleGrenade )
  13. BEGIN_NETWORK_TABLE( CWeaponBaseRifleGrenade, DT_WeaponBaseRifleGrenade )
  14. END_NETWORK_TABLE()
  15. BEGIN_PREDICTION_DATA( CWeaponBaseRifleGrenade )
  16. END_PREDICTION_DATA()
  17. CWeaponBaseRifleGrenade::CWeaponBaseRifleGrenade()
  18. {
  19. }
  20. void CWeaponBaseRifleGrenade::Spawn()
  21. {
  22. BaseClass::Spawn();
  23. }
  24. void CWeaponBaseRifleGrenade::PrimaryAttack( void )
  25. {
  26. CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
  27. Assert( pPlayer );
  28. // Out of ammo?
  29. if ( m_iClip1 <= 0 )
  30. {
  31. if (m_bFireOnEmpty)
  32. {
  33. PlayEmptySound();
  34. m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
  35. }
  36. return;
  37. }
  38. if( pPlayer->GetWaterLevel() > 2 )
  39. {
  40. PlayEmptySound();
  41. m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
  42. return;
  43. }
  44. // decrement before calling PlayPrimaryAttackAnim, so we can play the empty anim if necessary
  45. m_iClip1--;
  46. SendWeaponAnim( ACT_VM_PRIMARYATTACK );
  47. // player "shoot" animation
  48. pPlayer->SetAnimation( PLAYER_ATTACK1 );
  49. #ifdef CLIENT_DLL
  50. if( pPlayer && !pPlayer->IsDormant() )
  51. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN );
  52. #else
  53. if( pPlayer )
  54. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN );
  55. #endif
  56. #ifndef CLIENT_DLL
  57. ShootGrenade();
  58. #endif
  59. WeaponSound( SINGLE );
  60. DoFireEffects();
  61. #ifdef CLIENT_DLL
  62. CDODPlayer *p = ToDODPlayer( GetPlayerOwner() );
  63. if ( prediction->IsFirstTimePredicted() )
  64. p->DoRecoil( GetWeaponID(), GetRecoil() );
  65. #endif
  66. m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + GetFireDelay();
  67. m_flTimeWeaponIdle = gpGlobals->curtime + m_pWeaponInfo->m_flTimeToIdleAfterFire;
  68. #ifndef CLIENT_DLL
  69. IGameEvent * event = gameeventmanager->CreateEvent( "dod_stats_weapon_attack" );
  70. if ( event )
  71. {
  72. event->SetInt( "attacker", pPlayer->GetUserID() );
  73. event->SetInt( "weapon", GetStatsWeaponID() );
  74. gameeventmanager->FireEvent( event );
  75. }
  76. #endif //CLIENT_DLL
  77. }
  78. Activity CWeaponBaseRifleGrenade::GetDrawActivity( void )
  79. {
  80. return ( (m_iClip1 <= 0 ) ? ACT_VM_DRAW_EMPTY : ACT_VM_DRAW );
  81. }
  82. Activity CWeaponBaseRifleGrenade::GetIdleActivity( void )
  83. {
  84. return ( (m_iClip1 <= 0 ) ? ACT_VM_IDLE_EMPTY : ACT_VM_IDLE );
  85. }
  86. bool CWeaponBaseRifleGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
  87. {
  88. #ifndef CLIENT_DLL
  89. // If they attempt to switch weapons before the throw animation is done,
  90. // allow it, but kill the weapon if we have to.
  91. CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
  92. if( pPlayer && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 && m_iClip1 <= 0 )
  93. {
  94. pPlayer->Weapon_Drop( this, NULL, NULL );
  95. UTIL_Remove(this);
  96. return true;
  97. }
  98. #endif
  99. return BaseClass::Holster( pSwitchingTo );
  100. }
  101. // weapon idle to destroy weapon if empty
  102. void CWeaponBaseRifleGrenade::WeaponIdle( void )
  103. {
  104. #ifndef CLIENT_DLL
  105. CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
  106. if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 && m_iClip1 <= 0)
  107. {
  108. pPlayer->Weapon_Drop( this, NULL, NULL );
  109. UTIL_Remove(this);
  110. return;
  111. }
  112. #endif
  113. BaseClass::WeaponIdle();
  114. }
  115. #define DOD_RIFLEGRENADE_SPEED 2000
  116. extern ConVar dod_grenadegravity;
  117. #ifndef CLIENT_DLL
  118. void CWeaponBaseRifleGrenade::ShootGrenade( void )
  119. {
  120. CDODPlayer *pPlayer = ToDODPlayer( GetOwner() );
  121. if ( !pPlayer )
  122. {
  123. Assert( false );
  124. return;
  125. }
  126. QAngle angThrow = pPlayer->LocalEyeAngles();
  127. Vector vForward, vRight, vUp;
  128. AngleVectors( angThrow, &vForward, &vRight, &vUp );
  129. Vector eyes = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset();
  130. Vector vecSrc = eyes;
  131. Vector vecThrow = vForward * DOD_RIFLEGRENADE_SPEED;
  132. // raise origin enough so that you can't shoot it straight down through the world
  133. if ( pPlayer->m_Shared.IsProne() )
  134. {
  135. vecSrc.z += 16;
  136. }
  137. SetCollisionGroup( COLLISION_GROUP_WEAPON );
  138. QAngle angles;
  139. VectorAngles( -vecThrow, angles );
  140. // estimate angular velocity based on initial conditions
  141. // uses a constant ang velocity instead of the derivative of the flight path, oh well.
  142. AngularImpulse angImpulse;
  143. angImpulse.Init();
  144. if ( vecThrow.z > 0 )
  145. angImpulse.y = -angles.x / ( sqrt( (-2 * vecThrow.z) / dod_grenadegravity.GetFloat() ));
  146. else
  147. angImpulse.y = -10;
  148. EmitGrenade( vecSrc, angles, vecThrow, angImpulse, pPlayer, RIFLEGRENADE_FUSE_LENGTH );
  149. }
  150. void CWeaponBaseRifleGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer, float flLifeTime )
  151. {
  152. Assert( !"Deriving classes should define this" );
  153. }
  154. #endif
  155. bool CWeaponBaseRifleGrenade::CanDeploy( void )
  156. {
  157. // does the player own the weapon that fires this grenade?
  158. CBasePlayer *pPlayer = GetPlayerOwner();
  159. if ( !pPlayer )
  160. return false;
  161. CBaseCombatWeapon *pOwnedWeapon = pPlayer->Weapon_OwnsThisType( GetCompanionWeaponName() );
  162. if ( pOwnedWeapon == NULL )
  163. return false;
  164. return BaseClass::CanDeploy();
  165. }
  166. const char *CWeaponBaseRifleGrenade::GetCompanionWeaponName( void )
  167. {
  168. Assert( !"Should not call this version. Inheriting classes must implement." );
  169. return "";
  170. }
  171. float CWeaponBaseRifleGrenade::GetRecoil( void )
  172. {
  173. CDODPlayer *p = ToDODPlayer( GetPlayerOwner() );
  174. if( p && p->m_Shared.IsInMGDeploy() )
  175. {
  176. return 0.0f;
  177. }
  178. return 10;
  179. }