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.

277 lines
7.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: TF Base Rockets.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "tf_wearable_item_demoshield.h"
  8. #include "tf_gamerules.h"
  9. #include "engine/ivdebugoverlay.h"
  10. #include "tf_weapon_medigun.h"
  11. #ifdef CLIENT_DLL
  12. #include "tf_weapon_sword.h"
  13. #include "renamed_recvtable_compat.h"
  14. NOTE_RENAMED_RECVTABLE( DT_TFWearableItemDemoShield, DT_TFWearableDemoShield )
  15. #endif
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. LINK_ENTITY_TO_CLASS( tf_wearable_demoshield, CTFWearableDemoShield );
  19. IMPLEMENT_NETWORKCLASS_ALIASED( TFWearableDemoShield, DT_TFWearableDemoShield )
  20. // Network Table --
  21. BEGIN_NETWORK_TABLE( CTFWearableDemoShield, DT_TFWearableDemoShield )
  22. #if defined( GAME_DLL )
  23. #else
  24. #endif // GAME_DLL
  25. END_NETWORK_TABLE()
  26. // -- Network Table
  27. // Data Desc --
  28. BEGIN_DATADESC( CTFWearableDemoShield )
  29. END_DATADESC()
  30. // -- Data Desc
  31. //-----------------------------------------------------------------------------
  32. // Purpose:
  33. //-----------------------------------------------------------------------------
  34. CTFWearableDemoShield::CTFWearableDemoShield() : CTFWearable()
  35. {
  36. #ifdef GAME_DLL
  37. m_bImpactedSomething = false;
  38. #endif
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. //-----------------------------------------------------------------------------
  43. void CTFWearableDemoShield::Precache()
  44. {
  45. BaseClass::Precache();
  46. PrecacheScriptSound( "DemoCharge.HitWorld" );
  47. PrecacheScriptSound( "DemoCharge.HitFlesh" );
  48. PrecacheScriptSound( "DemoCharge.HitFleshRange" );
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Purpose:
  52. //-----------------------------------------------------------------------------
  53. void CTFWearableDemoShield::DoSpecialAction( CTFPlayer *pPlayer )
  54. {
  55. if ( CanCharge( pPlayer ) )
  56. {
  57. DoCharge( pPlayer );
  58. return;
  59. }
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Purpose:
  63. //-----------------------------------------------------------------------------
  64. void CTFWearableDemoShield::EndSpecialAction( CTFPlayer *pPlayer )
  65. {
  66. int nAttackNotCancelCharge = 0;
  67. CALL_ATTRIB_HOOK_INT( nAttackNotCancelCharge, attack_not_cancel_charge );
  68. if ( nAttackNotCancelCharge > 0 )
  69. {
  70. return;
  71. }
  72. if ( pPlayer->m_Shared.InCond( TF_COND_SHIELD_CHARGE ) )
  73. {
  74. pPlayer->m_Shared.CalcChargeCrit();
  75. pPlayer->m_Shared.SetDemomanChargeMeter( 0 );
  76. pPlayer->m_Shared.RemoveCond( TF_COND_SHIELD_CHARGE );
  77. }
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Purpose:
  81. //-----------------------------------------------------------------------------
  82. bool CTFWearableDemoShield::CanCharge( CTFPlayer *pPlayer )
  83. {
  84. // 6/14/2011 - Demos can now charge while in the air to counter pyro control.
  85. // if ( !(pPlayer->GetFlags() & FL_ONGROUND) )
  86. // return false;
  87. if ( TFGameRules() && (TFGameRules()->State_Get() == GR_STATE_PREROUND) )
  88. return false;
  89. if ( pPlayer->m_Shared.IsLoser() )
  90. return false;
  91. if ( pPlayer->m_Shared.InCond( TF_COND_STUNNED ) )
  92. return false;
  93. if ( pPlayer->IsTaunting() )
  94. return false;
  95. if ( pPlayer->GetGrapplingHookTarget() )
  96. return false;
  97. if ( pPlayer->m_Shared.GetDemomanChargeMeter() == 100.f )
  98. return true;
  99. if ( TFGameRules() && TFGameRules()->IsPasstimeMode() && pPlayer->m_Shared.HasPasstimeBall() )
  100. return false;
  101. return false;
  102. }
  103. //-----------------------------------------------------------------------------
  104. // Purpose:
  105. //-----------------------------------------------------------------------------
  106. void CTFWearableDemoShield::DoCharge( CTFPlayer *pPlayer )
  107. {
  108. #ifdef GAME_DLL
  109. float flChargeTime = 1.5f;
  110. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pPlayer, flChargeTime, mod_charge_time );
  111. pPlayer->m_Shared.AddCond( TF_COND_SHIELD_CHARGE, flChargeTime );
  112. m_bImpactedSomething = false;
  113. #endif
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Purpose:
  117. //-----------------------------------------------------------------------------
  118. void CTFWearableDemoShield::ShieldBash( CTFPlayer *pPlayer, float flCurrentChargeMeter )
  119. {
  120. CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() );
  121. if ( !pOwner )
  122. return;
  123. #ifdef GAME_DLL
  124. if ( m_bImpactedSomething )
  125. return;
  126. m_bImpactedSomething = true;
  127. // Setup the swing range.
  128. Vector vecForward;
  129. AngleVectors( pOwner->EyeAngles(), &vecForward );
  130. Vector vecStart = pOwner->Weapon_ShootPosition();
  131. Vector vecEnd = vecStart + vecForward * 48;
  132. // See if we hit anything.
  133. trace_t trace;
  134. UTIL_TraceHull( vecStart, vecEnd, -Vector(24,24,24), Vector(24,24,24),
  135. MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &trace );
  136. // Play an impact sound.
  137. bool bImpactDamage = false;
  138. if ( trace.m_pEnt )
  139. {
  140. const char* pszSoundName = "";
  141. if ( trace.m_pEnt->IsPlayer() )
  142. {
  143. bImpactDamage = true;
  144. pszSoundName = "DemoCharge.HitFleshRange";
  145. }
  146. else
  147. {
  148. pszSoundName = "DemoCharge.HitWorld";
  149. }
  150. pOwner->EmitSound( pszSoundName );
  151. }
  152. // Apply impact damage, if any.
  153. if ( bImpactDamage )
  154. {
  155. float flBashDamage = CalculateChargeDamage( flCurrentChargeMeter );
  156. CTakeDamageInfo info;
  157. info.SetAttacker( pOwner );
  158. info.SetInflictor( this );
  159. info.SetWeapon( this );
  160. info.SetDamage( flBashDamage );
  161. info.SetDamageCustom( TF_DMG_CUSTOM_CHARGE_IMPACT );
  162. info.SetDamageForce( GetShieldDamageForce( flCurrentChargeMeter ) );
  163. info.SetDamagePosition( trace.endpos );
  164. info.SetDamageType( DMG_CLUB );
  165. Vector dir;
  166. AngleVectors( pOwner->GetAbsAngles(), &dir );
  167. trace.m_pEnt->DispatchTraceAttack( info, dir, &trace );
  168. ApplyMultiDamage();
  169. // Calculate charge crit if we did any bash damage
  170. pOwner->m_Shared.CalcChargeCrit();
  171. }
  172. UTIL_ScreenShake( pOwner->WorldSpaceCenter(), 25.0, 150.0, 1.0, 750, SHAKE_START );
  173. #endif
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Purpose:
  177. //-----------------------------------------------------------------------------
  178. float CTFWearableDemoShield::CalculateChargeDamage( float flCurrentChargeMeter )
  179. {
  180. float flImpactDamage = RemapValClamped( flCurrentChargeMeter, 90.0f, 40.0f, 15.0f, 50.0f );
  181. CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() );
  182. if ( !pOwner )
  183. return flImpactDamage;
  184. // Cap at 5 decapitations for dmg bonus
  185. int iDecaps = Min( pOwner->m_Shared.GetDecapitations(), 5 );
  186. if ( iDecaps > 0 )
  187. {
  188. flImpactDamage *= (1.0f + iDecaps * 0.1f );
  189. }
  190. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pOwner, flImpactDamage, charge_impact_damage );
  191. return flImpactDamage;
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Purpose:
  195. //-----------------------------------------------------------------------------
  196. Vector CTFWearableDemoShield::GetShieldDamageForce( float flCurrentChargeMeter )
  197. {
  198. Vector vecVelocity = GetAbsVelocity();
  199. IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
  200. if ( pPhysicsObject )
  201. {
  202. pPhysicsObject->GetVelocity( &vecVelocity, NULL );
  203. VectorNormalize( vecVelocity );
  204. }
  205. return (vecVelocity * CalculateChargeDamage( flCurrentChargeMeter ) );
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Purpose: Attaches the item to the player.
  209. //-----------------------------------------------------------------------------
  210. void CTFWearableDemoShield::Equip( CBasePlayer* pOwner )
  211. {
  212. BaseClass::Equip( pOwner );
  213. if ( !CanEquip( pOwner ) )
  214. return;
  215. CTFPlayer *pTFPlayer = ToTFPlayer( pOwner );
  216. if ( pTFPlayer )
  217. {
  218. pTFPlayer->m_Shared.SetShieldEquipped( true );
  219. }
  220. }
  221. //-----------------------------------------------------------------------------
  222. // Purpose: Remove item from the player.
  223. //-----------------------------------------------------------------------------
  224. void CTFWearableDemoShield::UnEquip( CBasePlayer* pOwner )
  225. {
  226. BaseClass::UnEquip( pOwner );
  227. CTFPlayer *pTFPlayer = ToTFPlayer( pOwner );
  228. if ( pTFPlayer )
  229. {
  230. pTFPlayer->m_Shared.SetShieldEquipped( false );
  231. }
  232. }