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.

185 lines
5.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "c_ai_basenpc.h"
  9. #include "engine/ivdebugoverlay.h"
  10. #if defined( HL2_DLL ) || defined( HL2_EPISODIC )
  11. #include "c_basehlplayer.h"
  12. #endif
  13. #include "death_pose.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. #define PING_MAX_TIME 2.0
  17. IMPLEMENT_CLIENTCLASS_DT( C_AI_BaseNPC, DT_AI_BaseNPC, CAI_BaseNPC )
  18. RecvPropInt( RECVINFO( m_lifeState ) ),
  19. RecvPropBool( RECVINFO( m_bPerformAvoidance ) ),
  20. RecvPropBool( RECVINFO( m_bIsMoving ) ),
  21. RecvPropBool( RECVINFO( m_bFadeCorpse ) ),
  22. RecvPropInt( RECVINFO ( m_iDeathPose) ),
  23. RecvPropInt( RECVINFO( m_iDeathFrame) ),
  24. RecvPropInt( RECVINFO( m_iSpeedModRadius ) ),
  25. RecvPropInt( RECVINFO( m_iSpeedModSpeed ) ),
  26. RecvPropInt( RECVINFO( m_bSpeedModActive ) ),
  27. RecvPropBool( RECVINFO( m_bImportanRagdoll ) ),
  28. RecvPropFloat( RECVINFO( m_flTimePingEffect ) ),
  29. END_RECV_TABLE()
  30. extern ConVar cl_npc_speedmod_intime;
  31. bool NPC_IsImportantNPC( C_BaseAnimating *pAnimating )
  32. {
  33. C_AI_BaseNPC *pBaseNPC = dynamic_cast < C_AI_BaseNPC* > ( pAnimating );
  34. if ( pBaseNPC == NULL )
  35. return false;
  36. return pBaseNPC->ImportantRagdoll();
  37. }
  38. C_AI_BaseNPC::C_AI_BaseNPC()
  39. {
  40. }
  41. //-----------------------------------------------------------------------------
  42. // Makes ragdolls ignore npcclip brushes
  43. //-----------------------------------------------------------------------------
  44. unsigned int C_AI_BaseNPC::PhysicsSolidMaskForEntity( void ) const
  45. {
  46. // This allows ragdolls to move through npcclip brushes
  47. if ( !IsRagdoll() )
  48. {
  49. return MASK_NPCSOLID;
  50. }
  51. return MASK_SOLID;
  52. }
  53. void C_AI_BaseNPC::ClientThink( void )
  54. {
  55. BaseClass::ClientThink();
  56. #ifdef HL2_DLL
  57. C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
  58. if ( ShouldModifyPlayerSpeed() == true )
  59. {
  60. if ( pPlayer )
  61. {
  62. float flDist = (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr();
  63. if ( flDist <= GetSpeedModifyRadius() )
  64. {
  65. if ( pPlayer->m_hClosestNPC )
  66. {
  67. if ( pPlayer->m_hClosestNPC != this )
  68. {
  69. float flDistOther = (pPlayer->m_hClosestNPC->GetAbsOrigin() - pPlayer->GetAbsOrigin()).Length();
  70. //If I'm closer than the other NPC then replace it with myself.
  71. if ( flDist < flDistOther )
  72. {
  73. pPlayer->m_hClosestNPC = this;
  74. pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
  75. }
  76. }
  77. }
  78. else
  79. {
  80. pPlayer->m_hClosestNPC = this;
  81. pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
  82. }
  83. }
  84. }
  85. }
  86. #endif // HL2_DLL
  87. #ifdef HL2_EPISODIC
  88. C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
  89. if ( pPlayer && m_flTimePingEffect > gpGlobals->curtime )
  90. {
  91. float fPingEffectTime = m_flTimePingEffect - gpGlobals->curtime;
  92. if ( fPingEffectTime > 0.0f )
  93. {
  94. Vector vRight, vUp;
  95. Vector vMins, vMaxs;
  96. float fFade;
  97. if( fPingEffectTime <= 1.0f )
  98. {
  99. fFade = 1.0f - (1.0f - fPingEffectTime);
  100. }
  101. else
  102. {
  103. fFade = 1.0f;
  104. }
  105. GetRenderBounds( vMins, vMaxs );
  106. AngleVectors (pPlayer->GetAbsAngles(), NULL, &vRight, &vUp );
  107. Vector p1 = GetAbsOrigin() + vRight * vMins.x + vUp * vMins.z;
  108. Vector p2 = GetAbsOrigin() + vRight * vMaxs.x + vUp * vMins.z;
  109. Vector p3 = GetAbsOrigin() + vUp * vMaxs.z;
  110. int r = 0 * fFade;
  111. int g = 255 * fFade;
  112. int b = 0 * fFade;
  113. if ( debugoverlay )
  114. {
  115. debugoverlay->AddLineOverlay( p1, p2, r, g, b, true, 0.05f );
  116. debugoverlay->AddLineOverlay( p2, p3, r, g, b, true, 0.05f );
  117. debugoverlay->AddLineOverlay( p3, p1, r, g, b, true, 0.05f );
  118. }
  119. }
  120. }
  121. #endif
  122. }
  123. void C_AI_BaseNPC::OnDataChanged( DataUpdateType_t type )
  124. {
  125. BaseClass::OnDataChanged( type );
  126. if ( ( ShouldModifyPlayerSpeed() == true ) || ( m_flTimePingEffect > gpGlobals->curtime ) )
  127. {
  128. SetNextClientThink( CLIENT_THINK_ALWAYS );
  129. }
  130. }
  131. bool C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt )
  132. {
  133. bool bRet = true;
  134. if ( !ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ) )
  135. bRet = false;
  136. GetRagdollCurSequenceWithDeathPose( this, pDeltaBones1, gpGlobals->curtime, m_iDeathPose, m_iDeathFrame );
  137. float ragdollCreateTime = PhysGetSyncCreateTime();
  138. if ( ragdollCreateTime != gpGlobals->curtime )
  139. {
  140. // The next simulation frame begins before the end of this frame
  141. // so initialize the ragdoll at that time so that it will reach the current
  142. // position at curtime. Otherwise the ragdoll will simulate forward from curtime
  143. // and pop into the future a bit at this point of transition
  144. if ( !ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ) )
  145. bRet = false;
  146. }
  147. else
  148. {
  149. if ( !SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ) )
  150. bRet = false;
  151. }
  152. return bRet;
  153. }