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.

363 lines
8.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "weapon_sdkbase.h"
  8. #include "gamerules.h"
  9. #include "npcevent.h"
  10. #include "engine/IEngineSound.h"
  11. #include "weapon_basesdkgrenade.h"
  12. #include "in_buttons.h"
  13. #ifdef CLIENT_DLL
  14. #include "c_sdk_player.h"
  15. #else
  16. #include "sdk_player.h"
  17. #include "items.h"
  18. #endif
  19. #define GRENADE_TIMER 1.5f //Seconds
  20. IMPLEMENT_NETWORKCLASS_ALIASED( BaseSDKGrenade, DT_BaseSDKGrenade )
  21. BEGIN_NETWORK_TABLE(CBaseSDKGrenade, DT_BaseSDKGrenade)
  22. #ifndef CLIENT_DLL
  23. SendPropBool( SENDINFO(m_bRedraw) ),
  24. SendPropBool( SENDINFO(m_bPinPulled) ),
  25. SendPropFloat( SENDINFO(m_fThrowTime), 0, SPROP_NOSCALE ),
  26. #else
  27. RecvPropBool( RECVINFO(m_bRedraw) ),
  28. RecvPropBool( RECVINFO(m_bPinPulled) ),
  29. RecvPropFloat( RECVINFO(m_fThrowTime) ),
  30. #endif
  31. END_NETWORK_TABLE()
  32. #ifdef CLIENT_DLL
  33. BEGIN_PREDICTION_DATA( CBaseSDKGrenade )
  34. DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
  35. DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
  36. END_PREDICTION_DATA()
  37. #endif
  38. LINK_ENTITY_TO_CLASS( weapon_basesdkgrenade, CBaseSDKGrenade );
  39. CBaseSDKGrenade::CBaseSDKGrenade()
  40. {
  41. m_bRedraw = false;
  42. m_bPinPulled = false;
  43. m_fThrowTime = 0;
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. //-----------------------------------------------------------------------------
  48. void CBaseSDKGrenade::Precache()
  49. {
  50. BaseClass::Precache();
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. //-----------------------------------------------------------------------------
  55. bool CBaseSDKGrenade::Deploy()
  56. {
  57. m_bRedraw = false;
  58. m_bPinPulled = false;
  59. m_fThrowTime = 0;
  60. return BaseClass::Deploy();
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Purpose:
  64. // Output : Returns true on success, false on failure.
  65. //-----------------------------------------------------------------------------
  66. bool CBaseSDKGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
  67. {
  68. m_bRedraw = false;
  69. m_bPinPulled = false; // when this is holstered make sure the pin isn�t pulled.
  70. m_fThrowTime = 0;
  71. #ifndef CLIENT_DLL
  72. // If they attempt to switch weapons before the throw animation is done,
  73. // allow it, but kill the weapon if we have to.
  74. CSDKPlayer *pPlayer = GetPlayerOwner();
  75. if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
  76. {
  77. CBaseCombatCharacter *pOwner = (CBaseCombatCharacter *)pPlayer;
  78. pOwner->Weapon_Drop( this );
  79. UTIL_Remove(this);
  80. }
  81. #endif
  82. return BaseClass::Holster( pSwitchingTo );
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Purpose:
  86. //-----------------------------------------------------------------------------
  87. void CBaseSDKGrenade::PrimaryAttack()
  88. {
  89. if ( m_bRedraw || m_bPinPulled )
  90. return;
  91. CSDKPlayer *pPlayer = GetPlayerOwner();
  92. if ( !pPlayer || pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
  93. return;
  94. // The pull pin animation has to finish, then we wait until they aren't holding the primary
  95. // attack button, then throw the grenade.
  96. SendWeaponAnim( ACT_VM_PULLPIN );
  97. m_bPinPulled = true;
  98. // Don't let weapon idle interfere in the middle of a throw!
  99. SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
  100. m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose:
  104. //-----------------------------------------------------------------------------
  105. void CBaseSDKGrenade::SecondaryAttack()
  106. {
  107. if ( m_bRedraw )
  108. return;
  109. CSDKPlayer *pPlayer = GetPlayerOwner();
  110. if ( pPlayer == NULL )
  111. return;
  112. //See if we're ducking
  113. if ( pPlayer->GetFlags() & FL_DUCKING )
  114. {
  115. //Send the weapon animation
  116. SendWeaponAnim( ACT_VM_SECONDARYATTACK );
  117. }
  118. else
  119. {
  120. //Send the weapon animation
  121. SendWeaponAnim( ACT_VM_HAULBACK );
  122. }
  123. // Don't let weapon idle interfere in the middle of a throw!
  124. SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
  125. m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Purpose:
  129. // Output : Returns true on success, false on failure.
  130. //-----------------------------------------------------------------------------
  131. bool CBaseSDKGrenade::Reload()
  132. {
  133. if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) )
  134. {
  135. //Redraw the weapon
  136. SendWeaponAnim( ACT_VM_DRAW );
  137. //Update our times
  138. m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
  139. m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
  140. SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
  141. }
  142. return true;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose:
  146. //-----------------------------------------------------------------------------
  147. void CBaseSDKGrenade::ItemPostFrame()
  148. {
  149. CSDKPlayer *pPlayer = GetPlayerOwner();
  150. if ( !pPlayer )
  151. return;
  152. CBaseViewModel *vm = pPlayer->GetViewModel( m_nViewModelIndex );
  153. if ( !vm )
  154. return;
  155. // If they let go of the fire button, they want to throw the grenade.
  156. if ( m_bPinPulled && !(pPlayer->m_nButtons & IN_ATTACK) )
  157. {
  158. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
  159. StartGrenadeThrow();
  160. DecrementAmmo( pPlayer );
  161. m_bPinPulled = false;
  162. SendWeaponAnim( ACT_VM_THROW );
  163. SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
  164. }
  165. else if ((m_fThrowTime > 0) && (m_fThrowTime < gpGlobals->curtime))
  166. {
  167. ThrowGrenade();
  168. }
  169. else if( m_bRedraw )
  170. {
  171. // Has the throw animation finished playing
  172. if( m_flTimeWeaponIdle < gpGlobals->curtime )
  173. {
  174. #ifdef GAME_DLL
  175. // if we're officially out of grenades, ditch this weapon
  176. if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
  177. {
  178. pPlayer->Weapon_Drop( this, NULL, NULL );
  179. UTIL_Remove(this);
  180. }
  181. else
  182. {
  183. pPlayer->SwitchToNextBestWeapon( this );
  184. }
  185. #endif
  186. return; //don't animate this grenade any more!
  187. }
  188. }
  189. else if( !m_bRedraw )
  190. {
  191. BaseClass::ItemPostFrame();
  192. }
  193. }
  194. #ifdef CLIENT_DLL
  195. void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
  196. {
  197. }
  198. void CBaseSDKGrenade::DropGrenade()
  199. {
  200. m_bRedraw = true;
  201. m_fThrowTime = 0.0f;
  202. }
  203. void CBaseSDKGrenade::ThrowGrenade()
  204. {
  205. m_bRedraw = true;
  206. m_fThrowTime = 0.0f;
  207. }
  208. void CBaseSDKGrenade::StartGrenadeThrow()
  209. {
  210. m_fThrowTime = gpGlobals->curtime + 0.1f;
  211. }
  212. #else
  213. BEGIN_DATADESC( CBaseSDKGrenade )
  214. DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ),
  215. END_DATADESC()
  216. int CBaseSDKGrenade::CapabilitiesGet()
  217. {
  218. return bits_CAP_WEAPON_RANGE_ATTACK1;
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose:
  222. // Input : *pOwner -
  223. //-----------------------------------------------------------------------------
  224. void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
  225. {
  226. pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
  227. }
  228. void CBaseSDKGrenade::StartGrenadeThrow()
  229. {
  230. m_fThrowTime = gpGlobals->curtime + 0.1f;
  231. }
  232. void CBaseSDKGrenade::ThrowGrenade()
  233. {
  234. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  235. if ( !pPlayer )
  236. {
  237. Assert( false );
  238. return;
  239. }
  240. QAngle angThrow = pPlayer->LocalEyeAngles();
  241. Vector vForward, vRight, vUp;
  242. if (angThrow.x < 90 )
  243. angThrow.x = -10 + angThrow.x * ((90 + 10) / 90.0);
  244. else
  245. {
  246. angThrow.x = 360.0f - angThrow.x;
  247. angThrow.x = -10 + angThrow.x * -((90 - 10) / 90.0);
  248. }
  249. float flVel = (90 - angThrow.x) * 6;
  250. if (flVel > 750)
  251. flVel = 750;
  252. AngleVectors( angThrow, &vForward, &vRight, &vUp );
  253. Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset();
  254. vecSrc += vForward * 16;
  255. Vector vecThrow = vForward * flVel + pPlayer->GetAbsVelocity();
  256. EmitGrenade( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer );
  257. m_bRedraw = true;
  258. m_fThrowTime = 0.0f;
  259. }
  260. void CBaseSDKGrenade::DropGrenade()
  261. {
  262. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  263. if ( !pPlayer )
  264. {
  265. Assert( false );
  266. return;
  267. }
  268. Vector vForward;
  269. pPlayer->EyeVectors( &vForward );
  270. Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset() + vForward * 16;
  271. Vector vecVel = pPlayer->GetAbsVelocity();
  272. EmitGrenade( vecSrc, vec3_angle, vecVel, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer );
  273. m_bRedraw = true;
  274. m_fThrowTime = 0.0f;
  275. }
  276. void CBaseSDKGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer )
  277. {
  278. Assert( 0 && "CBaseSDKGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" );
  279. }
  280. bool CBaseSDKGrenade::AllowsAutoSwitchFrom( void ) const
  281. {
  282. return !m_bPinPulled;
  283. }
  284. #endif