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.

203 lines
6.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Crowbar - an old favorite
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "basehlcombatweapon.h"
  9. #include "player.h"
  10. #include "gamerules.h"
  11. #include "ammodef.h"
  12. #include "mathlib/mathlib.h"
  13. #include "in_buttons.h"
  14. #include "soundent.h"
  15. #include "basebludgeonweapon.h"
  16. #include "vstdlib/random.h"
  17. #include "npcevent.h"
  18. #include "ai_basenpc.h"
  19. #include "weapon_crowbar.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. ConVar sk_plr_dmg_crowbar ( "sk_plr_dmg_crowbar","0");
  23. ConVar sk_npc_dmg_crowbar ( "sk_npc_dmg_crowbar","0");
  24. //-----------------------------------------------------------------------------
  25. // CWeaponCrowbar
  26. //-----------------------------------------------------------------------------
  27. IMPLEMENT_SERVERCLASS_ST(CWeaponCrowbar, DT_WeaponCrowbar)
  28. END_SEND_TABLE()
  29. #ifndef HL2MP
  30. LINK_ENTITY_TO_CLASS( weapon_crowbar, CWeaponCrowbar );
  31. PRECACHE_WEAPON_REGISTER( weapon_crowbar );
  32. #endif
  33. acttable_t CWeaponCrowbar::m_acttable[] =
  34. {
  35. { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true },
  36. { ACT_IDLE, ACT_IDLE_ANGRY_MELEE, false },
  37. { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, false },
  38. };
  39. IMPLEMENT_ACTTABLE(CWeaponCrowbar);
  40. //-----------------------------------------------------------------------------
  41. // Constructor
  42. //-----------------------------------------------------------------------------
  43. CWeaponCrowbar::CWeaponCrowbar( void )
  44. {
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Purpose: Get the damage amount for the animation we're doing
  48. // Input : hitActivity - currently played activity
  49. // Output : Damage amount
  50. //-----------------------------------------------------------------------------
  51. float CWeaponCrowbar::GetDamageForActivity( Activity hitActivity )
  52. {
  53. if ( ( GetOwner() != NULL ) && ( GetOwner()->IsPlayer() ) )
  54. return sk_plr_dmg_crowbar.GetFloat();
  55. return sk_npc_dmg_crowbar.GetFloat();
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose: Add in a view kick for this weapon
  59. //-----------------------------------------------------------------------------
  60. void CWeaponCrowbar::AddViewKick( void )
  61. {
  62. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  63. if ( pPlayer == NULL )
  64. return;
  65. QAngle punchAng;
  66. punchAng.x = random->RandomFloat( 1.0f, 2.0f );
  67. punchAng.y = random->RandomFloat( -2.0f, -1.0f );
  68. punchAng.z = 0.0f;
  69. pPlayer->ViewPunch( punchAng );
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!)
  73. //-----------------------------------------------------------------------------
  74. ConVar sk_crowbar_lead_time( "sk_crowbar_lead_time", "0.9" );
  75. int CWeaponCrowbar::WeaponMeleeAttack1Condition( float flDot, float flDist )
  76. {
  77. // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!)
  78. CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer();
  79. CBaseEntity *pEnemy = pNPC->GetEnemy();
  80. if (!pEnemy)
  81. return COND_NONE;
  82. Vector vecVelocity;
  83. vecVelocity = pEnemy->GetSmoothedVelocity( );
  84. // Project where the enemy will be in a little while
  85. float dt = sk_crowbar_lead_time.GetFloat();
  86. dt += random->RandomFloat( -0.3f, 0.2f );
  87. if ( dt < 0.0f )
  88. dt = 0.0f;
  89. Vector vecExtrapolatedPos;
  90. VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos );
  91. Vector vecDelta;
  92. VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta );
  93. if ( fabs( vecDelta.z ) > 70 )
  94. {
  95. return COND_TOO_FAR_TO_ATTACK;
  96. }
  97. Vector vecForward = pNPC->BodyDirection2D( );
  98. vecDelta.z = 0.0f;
  99. float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() );
  100. if ((flDist > 64) && (flExtrapolatedDist > 64))
  101. {
  102. return COND_TOO_FAR_TO_ATTACK;
  103. }
  104. float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() );
  105. if ((flDot < 0.7) && (flExtrapolatedDot < 0.7))
  106. {
  107. return COND_NOT_FACING_ATTACK;
  108. }
  109. return COND_CAN_MELEE_ATTACK1;
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Animation event handlers
  113. //-----------------------------------------------------------------------------
  114. void CWeaponCrowbar::HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
  115. {
  116. // Trace up or down based on where the enemy is...
  117. // But only if we're basically facing that direction
  118. Vector vecDirection;
  119. AngleVectors( GetAbsAngles(), &vecDirection );
  120. CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL;
  121. if ( pEnemy )
  122. {
  123. Vector vecDelta;
  124. VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta );
  125. VectorNormalize( vecDelta );
  126. Vector2D vecDelta2D = vecDelta.AsVector2D();
  127. Vector2DNormalize( vecDelta2D );
  128. if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f )
  129. {
  130. vecDirection = vecDelta;
  131. }
  132. }
  133. Vector vecEnd;
  134. VectorMA( pOperator->Weapon_ShootPosition(), 50, vecDirection, vecEnd );
  135. CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd,
  136. Vector(-16,-16,-16), Vector(36,36,36), sk_npc_dmg_crowbar.GetFloat(), DMG_CLUB, 0.75 );
  137. // did I hit someone?
  138. if ( pHurt )
  139. {
  140. // play sound
  141. WeaponSound( MELEE_HIT );
  142. // Fake a trace impact, so the effects work out like a player's crowbaw
  143. trace_t traceHit;
  144. UTIL_TraceLine( pOperator->Weapon_ShootPosition(), pHurt->GetAbsOrigin(), MASK_SHOT_HULL, pOperator, COLLISION_GROUP_NONE, &traceHit );
  145. ImpactEffect( traceHit );
  146. }
  147. else
  148. {
  149. WeaponSound( MELEE_MISS );
  150. }
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Animation event
  154. //-----------------------------------------------------------------------------
  155. void CWeaponCrowbar::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
  156. {
  157. switch( pEvent->event )
  158. {
  159. case EVENT_WEAPON_MELEE_HIT:
  160. HandleAnimEventMeleeHit( pEvent, pOperator );
  161. break;
  162. default:
  163. BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
  164. break;
  165. }
  166. }