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.

264 lines
6.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "npcevent.h"
  8. #include "in_buttons.h"
  9. #ifdef CLIENT_DLL
  10. #include "c_hl2mp_player.h"
  11. #else
  12. #include "grenade_ar2.h"
  13. #include "hl2mp_player.h"
  14. #include "basegrenade_shared.h"
  15. #endif
  16. #include "weapon_hl2mpbase.h"
  17. #include "weapon_hl2mpbase_machinegun.h"
  18. #ifdef CLIENT_DLL
  19. #define CWeaponSMG1 C_WeaponSMG1
  20. #endif
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. #define SMG1_GRENADE_DAMAGE 100.0f
  24. #define SMG1_GRENADE_RADIUS 250.0f
  25. class CWeaponSMG1 : public CHL2MPMachineGun
  26. {
  27. public:
  28. DECLARE_CLASS( CWeaponSMG1, CHL2MPMachineGun );
  29. CWeaponSMG1();
  30. DECLARE_NETWORKCLASS();
  31. DECLARE_PREDICTABLE();
  32. void Precache( void );
  33. void AddViewKick( void );
  34. void SecondaryAttack( void );
  35. int GetMinBurst() { return 2; }
  36. int GetMaxBurst() { return 5; }
  37. virtual void Equip( CBaseCombatCharacter *pOwner );
  38. bool Reload( void );
  39. float GetFireRate( void ) { return 0.075f; } // 13.3hz
  40. Activity GetPrimaryAttackActivity( void );
  41. virtual const Vector& GetBulletSpread( void )
  42. {
  43. static const Vector cone = VECTOR_CONE_5DEGREES;
  44. return cone;
  45. }
  46. const WeaponProficiencyInfo_t *GetProficiencyValues();
  47. #ifndef CLIENT_DLL
  48. DECLARE_ACTTABLE();
  49. #endif
  50. protected:
  51. Vector m_vecTossVelocity;
  52. float m_flNextGrenadeCheck;
  53. private:
  54. CWeaponSMG1( const CWeaponSMG1 & );
  55. };
  56. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponSMG1, DT_WeaponSMG1 )
  57. BEGIN_NETWORK_TABLE( CWeaponSMG1, DT_WeaponSMG1 )
  58. END_NETWORK_TABLE()
  59. BEGIN_PREDICTION_DATA( CWeaponSMG1 )
  60. END_PREDICTION_DATA()
  61. LINK_ENTITY_TO_CLASS( weapon_smg1, CWeaponSMG1 );
  62. PRECACHE_WEAPON_REGISTER(weapon_smg1);
  63. #ifndef CLIENT_DLL
  64. acttable_t CWeaponSMG1::m_acttable[] =
  65. {
  66. { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SMG1, false },
  67. { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SMG1, false },
  68. { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SMG1, false },
  69. { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SMG1, false },
  70. { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, false },
  71. { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SMG1, false },
  72. { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SMG1, false },
  73. { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, false },
  74. };
  75. IMPLEMENT_ACTTABLE(CWeaponSMG1);
  76. #endif
  77. //=========================================================
  78. CWeaponSMG1::CWeaponSMG1( )
  79. {
  80. m_fMinRange1 = 0;// No minimum range.
  81. m_fMaxRange1 = 1400;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose:
  85. //-----------------------------------------------------------------------------
  86. void CWeaponSMG1::Precache( void )
  87. {
  88. #ifndef CLIENT_DLL
  89. UTIL_PrecacheOther("grenade_ar2");
  90. #endif
  91. BaseClass::Precache();
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Purpose: Give this weapon longer range when wielded by an ally NPC.
  95. //-----------------------------------------------------------------------------
  96. void CWeaponSMG1::Equip( CBaseCombatCharacter *pOwner )
  97. {
  98. m_fMaxRange1 = 1400;
  99. BaseClass::Equip( pOwner );
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose:
  103. // Output : Activity
  104. //-----------------------------------------------------------------------------
  105. Activity CWeaponSMG1::GetPrimaryAttackActivity( void )
  106. {
  107. if ( m_nShotsFired < 2 )
  108. return ACT_VM_PRIMARYATTACK;
  109. if ( m_nShotsFired < 3 )
  110. return ACT_VM_RECOIL1;
  111. if ( m_nShotsFired < 4 )
  112. return ACT_VM_RECOIL2;
  113. return ACT_VM_RECOIL3;
  114. }
  115. //-----------------------------------------------------------------------------
  116. //-----------------------------------------------------------------------------
  117. bool CWeaponSMG1::Reload( void )
  118. {
  119. bool fRet;
  120. float fCacheTime = m_flNextSecondaryAttack;
  121. fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
  122. if ( fRet )
  123. {
  124. // Undo whatever the reload process has done to our secondary
  125. // attack timer. We allow you to interrupt reloading to fire
  126. // a grenade.
  127. m_flNextSecondaryAttack = GetOwner()->m_flNextAttack = fCacheTime;
  128. WeaponSound( RELOAD );
  129. }
  130. return fRet;
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Purpose:
  134. //-----------------------------------------------------------------------------
  135. void CWeaponSMG1::AddViewKick( void )
  136. {
  137. #define EASY_DAMPEN 0.5f
  138. #define MAX_VERTICAL_KICK 1.0f //Degrees
  139. #define SLIDE_LIMIT 2.0f //Seconds
  140. //Get the view kick
  141. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  142. if ( pPlayer == NULL )
  143. return;
  144. DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT );
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Purpose:
  148. //-----------------------------------------------------------------------------
  149. void CWeaponSMG1::SecondaryAttack( void )
  150. {
  151. // Only the player fires this way so we can cast
  152. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  153. if ( pPlayer == NULL )
  154. return;
  155. //Must have ammo
  156. if ( ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) || ( pPlayer->GetWaterLevel() == 3 ) )
  157. {
  158. SendWeaponAnim( ACT_VM_DRYFIRE );
  159. BaseClass::WeaponSound( EMPTY );
  160. m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f;
  161. return;
  162. }
  163. if( m_bInReload )
  164. m_bInReload = false;
  165. // MUST call sound before removing a round from the clip of a CMachineGun
  166. BaseClass::WeaponSound( WPN_DOUBLE );
  167. Vector vecSrc = pPlayer->Weapon_ShootPosition();
  168. Vector vecThrow;
  169. // Don't autoaim on grenade tosses
  170. AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow );
  171. VectorScale( vecThrow, 1000.0f, vecThrow );
  172. #ifndef CLIENT_DLL
  173. //Create the grenade
  174. CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, vec3_angle, pPlayer );
  175. pGrenade->SetAbsVelocity( vecThrow );
  176. pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) );
  177. pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
  178. pGrenade->SetThrower( GetOwner() );
  179. pGrenade->SetDamage( SMG1_GRENADE_DAMAGE );
  180. pGrenade->SetDamageRadius( SMG1_GRENADE_RADIUS );
  181. #endif
  182. SendWeaponAnim( ACT_VM_SECONDARYATTACK );
  183. // player "shoot" animation
  184. pPlayer->SetAnimation( PLAYER_ATTACK1 );
  185. // Decrease ammo
  186. pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType );
  187. // Can shoot again immediately
  188. m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f;
  189. // Can blow up after a short delay (so have time to release mouse button)
  190. m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f;
  191. }
  192. //-----------------------------------------------------------------------------
  193. const WeaponProficiencyInfo_t *CWeaponSMG1::GetProficiencyValues()
  194. {
  195. static WeaponProficiencyInfo_t proficiencyTable[] =
  196. {
  197. { 7.0, 0.75 },
  198. { 5.00, 0.75 },
  199. { 10.0/3.0, 0.75 },
  200. { 5.0/3.0, 0.75 },
  201. { 1.00, 1.0 },
  202. };
  203. COMPILE_TIME_ASSERT( ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1);
  204. return proficiencyTable;
  205. }