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.

167 lines
4.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "c_ai_basenpc.h"
  8. #include "bone_setup.h"
  9. // Must be the last file included
  10. #include "memdbgon.h"
  11. extern ConVar r_sequence_debug;
  12. class C_NPC_Puppet : public C_AI_BaseNPC
  13. {
  14. DECLARE_CLASS( C_NPC_Puppet, C_AI_BaseNPC );
  15. public:
  16. virtual void ClientThink( void );
  17. virtual void OnDataChanged( DataUpdateType_t updateType );
  18. virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
  19. virtual void AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime );
  20. EHANDLE m_hAnimationTarget;
  21. int m_nTargetAttachment;
  22. DECLARE_CLIENTCLASS();
  23. };
  24. IMPLEMENT_CLIENTCLASS_DT( C_NPC_Puppet, DT_NPC_Puppet, CNPC_Puppet )
  25. RecvPropEHandle( RECVINFO(m_hAnimationTarget) ),
  26. RecvPropInt( RECVINFO(m_nTargetAttachment) ),
  27. END_RECV_TABLE()
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. void C_NPC_Puppet::OnDataChanged( DataUpdateType_t updateType )
  32. {
  33. BaseClass::OnDataChanged( updateType );
  34. if ( updateType == DATA_UPDATE_CREATED )
  35. {
  36. SetNextClientThink( CLIENT_THINK_ALWAYS );
  37. }
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Purpose: We need to slam our position!
  41. //-----------------------------------------------------------------------------
  42. void C_NPC_Puppet::BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed )
  43. {
  44. if ( m_hAnimationTarget && m_nTargetAttachment != -1 )
  45. {
  46. C_BaseAnimating *pTarget = m_hAnimationTarget->GetBaseAnimating();
  47. if ( pTarget )
  48. {
  49. matrix3x4_t matTarget;
  50. pTarget->GetAttachment( m_nTargetAttachment, matTarget );
  51. MatrixCopy( matTarget, GetBoneForWrite( 0 ) );
  52. boneComputed.ClearAll(); // FIXME: Why is this calculated already?
  53. boneComputed.MarkBone( 0 );
  54. }
  55. }
  56. // Call the baseclass
  57. BaseClass::BuildTransformations( pStudioHdr, pos, q, cameraTransform, boneMask, boneComputed );
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose:
  61. //-----------------------------------------------------------------------------
  62. void C_NPC_Puppet::ClientThink( void )
  63. {
  64. if ( m_hAnimationTarget == NULL )
  65. return;
  66. C_BaseAnimating *pTarget = m_hAnimationTarget->GetBaseAnimating();
  67. if ( pTarget == NULL )
  68. return;
  69. int nTargetSequence = pTarget->GetSequence();
  70. const char *pSequenceName = pTarget->GetSequenceName( nTargetSequence );
  71. int nSequence = LookupSequence( pSequenceName );
  72. if ( nSequence >= 0 )
  73. {
  74. if ( nSequence != GetSequence() )
  75. {
  76. SetSequence( nSequence );
  77. UpdateVisibility();
  78. }
  79. SetCycle( pTarget->GetCycle() );
  80. SetPlaybackRate( pTarget->GetPlaybackRate() );
  81. }
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose:
  85. //-----------------------------------------------------------------------------
  86. void C_NPC_Puppet::AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime )
  87. {
  88. if ( m_hAnimationTarget == NULL )
  89. return;
  90. C_BaseAnimatingOverlay *pTarget = dynamic_cast<C_BaseAnimatingOverlay *>( m_hAnimationTarget->GetBaseAnimating() );
  91. if ( pTarget == NULL )
  92. return;
  93. // resort the layers
  94. int layer[MAX_OVERLAYS];
  95. int i;
  96. for (i = 0; i < MAX_OVERLAYS; i++)
  97. {
  98. layer[i] = MAX_OVERLAYS;
  99. }
  100. for (i = 0; i < pTarget->m_AnimOverlay.Count(); i++)
  101. {
  102. if (pTarget->m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS)
  103. {
  104. layer[pTarget->m_AnimOverlay[i].m_nOrder] = i;
  105. }
  106. }
  107. int j;
  108. for (j = 0; j < MAX_OVERLAYS; j++)
  109. {
  110. i = layer[ j ];
  111. if (i < pTarget->m_AnimOverlay.Count())
  112. {
  113. float fWeight = pTarget->m_AnimOverlay[i].m_flWeight;
  114. if (fWeight > 0)
  115. {
  116. const char *pSequenceName = pTarget->GetSequenceName( pTarget->m_AnimOverlay[i].m_nSequence );
  117. int nSequence = LookupSequence( pSequenceName );
  118. if ( nSequence >= 0 )
  119. {
  120. float fCycle = pTarget->m_AnimOverlay[ i ].m_flCycle;
  121. fCycle = ClampCycle( fCycle, IsSequenceLooping( nSequence ) );
  122. if (fWeight > 1)
  123. fWeight = 1;
  124. boneSetup.AccumulatePose( pos, q, nSequence, fCycle, fWeight, currentTime, NULL );
  125. #if _DEBUG
  126. if (Q_stristr( boneSetup.GetStudioHdr()->pszName(), r_sequence_debug.GetString()) != NULL)
  127. {
  128. DevMsgRT( "%6.2f : %30s : %5.3f : %4.2f : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( nSequence ).pszLabel(), fCycle, fWeight, i );
  129. }
  130. #endif
  131. }
  132. }
  133. }
  134. }
  135. }