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.

312 lines
8.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "npcevent.h"
  9. #ifdef CLIENT_DLL
  10. #include "c_hl2mp_player.h"
  11. #include "c_te_effect_dispatch.h"
  12. #else
  13. #include "hl2mp_player.h"
  14. #include "te_effect_dispatch.h"
  15. #include "prop_combine_ball.h"
  16. #endif
  17. #include "weapon_ar2.h"
  18. #include "effect_dispatch_data.h"
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. #ifndef CLIENT_DLL
  22. ConVar sk_weapon_ar2_alt_fire_radius( "sk_weapon_ar2_alt_fire_radius", "10" );
  23. ConVar sk_weapon_ar2_alt_fire_duration( "sk_weapon_ar2_alt_fire_duration", "4" );
  24. ConVar sk_weapon_ar2_alt_fire_mass( "sk_weapon_ar2_alt_fire_mass", "150" );
  25. #endif
  26. //=========================================================
  27. //=========================================================
  28. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponAR2, DT_WeaponAR2 )
  29. BEGIN_NETWORK_TABLE( CWeaponAR2, DT_WeaponAR2 )
  30. END_NETWORK_TABLE()
  31. BEGIN_PREDICTION_DATA( CWeaponAR2 )
  32. END_PREDICTION_DATA()
  33. LINK_ENTITY_TO_CLASS( weapon_ar2, CWeaponAR2 );
  34. PRECACHE_WEAPON_REGISTER(weapon_ar2);
  35. #ifndef CLIENT_DLL
  36. acttable_t CWeaponAR2::m_acttable[] =
  37. {
  38. { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false },
  39. { ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false },
  40. { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false },
  41. { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false },
  42. { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false },
  43. { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false },
  44. { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false },
  45. { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false },
  46. };
  47. IMPLEMENT_ACTTABLE(CWeaponAR2);
  48. #endif
  49. CWeaponAR2::CWeaponAR2( )
  50. {
  51. m_fMinRange1 = 65;
  52. m_fMaxRange1 = 2048;
  53. m_fMinRange2 = 256;
  54. m_fMaxRange2 = 1024;
  55. m_nShotsFired = 0;
  56. m_nVentPose = -1;
  57. }
  58. void CWeaponAR2::Precache( void )
  59. {
  60. BaseClass::Precache();
  61. #ifndef CLIENT_DLL
  62. UTIL_PrecacheOther( "prop_combine_ball" );
  63. UTIL_PrecacheOther( "env_entity_dissolver" );
  64. #endif
  65. }
  66. //-----------------------------------------------------------------------------
  67. // Purpose: Handle grenade detonate in-air (even when no ammo is left)
  68. //-----------------------------------------------------------------------------
  69. void CWeaponAR2::ItemPostFrame( void )
  70. {
  71. // See if we need to fire off our secondary round
  72. if ( m_bShotDelayed && gpGlobals->curtime > m_flDelayedFire )
  73. {
  74. DelayedAttack();
  75. }
  76. // Update our pose parameter for the vents
  77. CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
  78. if ( pOwner )
  79. {
  80. CBaseViewModel *pVM = pOwner->GetViewModel();
  81. if ( pVM )
  82. {
  83. if ( m_nVentPose == -1 )
  84. {
  85. m_nVentPose = pVM->LookupPoseParameter( "VentPoses" );
  86. }
  87. float flVentPose = RemapValClamped( m_nShotsFired, 0, 5, 0.0f, 1.0f );
  88. pVM->SetPoseParameter( m_nVentPose, flVentPose );
  89. }
  90. }
  91. BaseClass::ItemPostFrame();
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Purpose:
  95. // Output : Activity
  96. //-----------------------------------------------------------------------------
  97. Activity CWeaponAR2::GetPrimaryAttackActivity( void )
  98. {
  99. if ( m_nShotsFired < 2 )
  100. return ACT_VM_PRIMARYATTACK;
  101. if ( m_nShotsFired < 3 )
  102. return ACT_VM_RECOIL1;
  103. if ( m_nShotsFired < 4 )
  104. return ACT_VM_RECOIL2;
  105. return ACT_VM_RECOIL3;
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Purpose:
  109. // Input : &tr -
  110. // nDamageType -
  111. //-----------------------------------------------------------------------------
  112. void CWeaponAR2::DoImpactEffect( trace_t &tr, int nDamageType )
  113. {
  114. CEffectData data;
  115. data.m_vOrigin = tr.endpos + ( tr.plane.normal * 1.0f );
  116. data.m_vNormal = tr.plane.normal;
  117. DispatchEffect( "AR2Impact", data );
  118. BaseClass::DoImpactEffect( tr, nDamageType );
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose:
  122. //-----------------------------------------------------------------------------
  123. void CWeaponAR2::DelayedAttack( void )
  124. {
  125. m_bShotDelayed = false;
  126. CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
  127. if ( pOwner == NULL )
  128. return;
  129. // Deplete the clip completely
  130. SendWeaponAnim( ACT_VM_SECONDARYATTACK );
  131. m_flNextSecondaryAttack = pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration();
  132. // Register a muzzleflash for the AI
  133. pOwner->DoMuzzleFlash();
  134. WeaponSound( WPN_DOUBLE );
  135. // Fire the bullets
  136. Vector vecSrc = pOwner->Weapon_ShootPosition( );
  137. Vector vecAiming = pOwner->GetAutoaimVector( AUTOAIM_2DEGREES );
  138. Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH );
  139. // Fire the bullets
  140. Vector vecVelocity = vecAiming * 1000.0f;
  141. #ifndef CLIENT_DLL
  142. // Fire the combine ball
  143. CreateCombineBall( vecSrc,
  144. vecVelocity,
  145. sk_weapon_ar2_alt_fire_radius.GetFloat(),
  146. sk_weapon_ar2_alt_fire_mass.GetFloat(),
  147. sk_weapon_ar2_alt_fire_duration.GetFloat(),
  148. pOwner );
  149. // View effects
  150. color32 white = {255, 255, 255, 64};
  151. UTIL_ScreenFade( pOwner, white, 0.1, 0, FFADE_IN );
  152. #endif
  153. //Disorient the player
  154. QAngle angles = pOwner->GetLocalAngles();
  155. angles.x += random->RandomInt( -4, 4 );
  156. angles.y += random->RandomInt( -4, 4 );
  157. angles.z = 0;
  158. // pOwner->SnapEyeAngles( angles );
  159. pOwner->ViewPunch( QAngle( SharedRandomInt( "ar2pax", -8, -12 ), SharedRandomInt( "ar2pay", 1, 2 ), 0 ) );
  160. // Decrease ammo
  161. pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
  162. // Can shoot again immediately
  163. m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f;
  164. // Can blow up after a short delay (so have time to release mouse button)
  165. m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f;
  166. }
  167. //-----------------------------------------------------------------------------
  168. // Purpose:
  169. //-----------------------------------------------------------------------------
  170. void CWeaponAR2::SecondaryAttack( void )
  171. {
  172. if ( m_bShotDelayed )
  173. return;
  174. // Cannot fire underwater
  175. if ( GetOwner() && GetOwner()->GetWaterLevel() == 3 )
  176. {
  177. SendWeaponAnim( ACT_VM_DRYFIRE );
  178. BaseClass::WeaponSound( EMPTY );
  179. m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f;
  180. return;
  181. }
  182. m_bShotDelayed = true;
  183. m_flNextPrimaryAttack = m_flNextSecondaryAttack = m_flDelayedFire = gpGlobals->curtime + 0.5f;
  184. SendWeaponAnim( ACT_VM_FIDGET );
  185. WeaponSound( SPECIAL1 );
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Purpose: Override if we're waiting to release a shot
  189. // Output : Returns true on success, false on failure.
  190. //-----------------------------------------------------------------------------
  191. bool CWeaponAR2::CanHolster( void )
  192. {
  193. if ( m_bShotDelayed )
  194. return false;
  195. return BaseClass::CanHolster();
  196. }
  197. bool CWeaponAR2::Deploy( void )
  198. {
  199. m_bShotDelayed = false;
  200. m_flDelayedFire = 0.0f;
  201. return BaseClass::Deploy();
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Purpose: Override if we're waiting to release a shot
  205. //-----------------------------------------------------------------------------
  206. bool CWeaponAR2::Reload( void )
  207. {
  208. if ( m_bShotDelayed )
  209. return false;
  210. return BaseClass::Reload();
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Purpose:
  214. //-----------------------------------------------------------------------------
  215. void CWeaponAR2::AddViewKick( void )
  216. {
  217. #define EASY_DAMPEN 0.5f
  218. #define MAX_VERTICAL_KICK 8.0f //Degrees
  219. #define SLIDE_LIMIT 5.0f //Seconds
  220. //Get the view kick
  221. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  222. if (!pPlayer)
  223. return;
  224. DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT );
  225. }
  226. //-----------------------------------------------------------------------------
  227. const WeaponProficiencyInfo_t *CWeaponAR2::GetProficiencyValues()
  228. {
  229. static WeaponProficiencyInfo_t proficiencyTable[] =
  230. {
  231. { 7.0, 0.75 },
  232. { 5.00, 0.75 },
  233. { 3.0, 0.85 },
  234. { 5.0/3.0, 0.75 },
  235. { 1.00, 1.0 },
  236. };
  237. COMPILE_TIME_ASSERT( ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1);
  238. return proficiencyTable;
  239. }