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.

268 lines
7.6 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Dissolve entity to be attached to target entity. Serves two purposes:
  4. //
  5. // 1) An entity that can be placed by a level designer and triggered
  6. // to ignite a target entity.
  7. //
  8. // 2) An entity that can be created at runtime to ignite a target entity.
  9. //
  10. //=============================================================================//
  11. #include "cbase.h"
  12. #include "RagdollBoogie.h"
  13. #include "physics_prop_ragdoll.h"
  14. #include "effect_dispatch_data.h"
  15. #include "te_effect_dispatch.h"
  16. #include "IEffects.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. //-----------------------------------------------------------------------------
  20. // Make electriciy every so often
  21. //-----------------------------------------------------------------------------
  22. static const char *s_pZapContext = "ZapContext";
  23. //-----------------------------------------------------------------------------
  24. // Save/load
  25. //-----------------------------------------------------------------------------
  26. BEGIN_DATADESC( CRagdollBoogie )
  27. DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
  28. DEFINE_FIELD( m_flBoogieLength, FIELD_FLOAT ),
  29. DEFINE_FIELD( m_flMagnitude, FIELD_FLOAT ),
  30. // Think this should be handled by StartTouch/etc.
  31. // DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ),
  32. DEFINE_FUNCTION( BoogieThink ),
  33. DEFINE_FUNCTION( ZapThink ),
  34. END_DATADESC()
  35. LINK_ENTITY_TO_CLASS( env_ragdoll_boogie, CRagdollBoogie );
  36. //-----------------------------------------------------------------------------
  37. // Purpose: Creates a flame and attaches it to a target entity.
  38. // Input : pTarget -
  39. //-----------------------------------------------------------------------------
  40. CRagdollBoogie *CRagdollBoogie::Create( CBaseEntity *pTarget, float flMagnitude,
  41. float flStartTime, float flLengthTime, int nSpawnFlags )
  42. {
  43. CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pTarget );
  44. if ( !pRagdoll )
  45. return NULL;
  46. CRagdollBoogie *pBoogie = (CRagdollBoogie *)CreateEntityByName( "env_ragdoll_boogie" );
  47. if ( pBoogie == NULL )
  48. return NULL;
  49. pBoogie->AddSpawnFlags( nSpawnFlags );
  50. pBoogie->AttachToEntity( pTarget );
  51. pBoogie->SetBoogieTime( flStartTime, flLengthTime );
  52. pBoogie->SetMagnitude( flMagnitude );
  53. pBoogie->Spawn();
  54. return pBoogie;
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Spawn
  58. //-----------------------------------------------------------------------------
  59. void CRagdollBoogie::Spawn()
  60. {
  61. BaseClass::Spawn();
  62. SetThink( &CRagdollBoogie::BoogieThink );
  63. SetNextThink( gpGlobals->curtime + 0.01f );
  64. if ( HasSpawnFlags( SF_RAGDOLL_BOOGIE_ELECTRICAL ) )
  65. {
  66. SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext );
  67. }
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Zap!
  71. //-----------------------------------------------------------------------------
  72. void CRagdollBoogie::ZapThink()
  73. {
  74. if ( !GetMoveParent() )
  75. return;
  76. CBaseAnimating *pRagdoll = GetMoveParent()->GetBaseAnimating();
  77. if ( !pRagdoll )
  78. return;
  79. // Make electricity on the client
  80. CStudioHdr *pStudioHdr = pRagdoll->GetModelPtr( );
  81. if (!pStudioHdr)
  82. return;
  83. mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pRagdoll->GetHitboxSet() );
  84. if ( set->numhitboxes == 0 )
  85. return;
  86. if ( m_nSuppressionCount == 0 )
  87. {
  88. CEffectData data;
  89. data.m_nEntIndex = GetMoveParent()->entindex();
  90. data.m_flMagnitude = 4;
  91. data.m_flScale = HasSpawnFlags(SF_RAGDOLL_BOOGIE_ELECTRICAL_NARROW_BEAM) ? 1.0f : 2.0f;
  92. DispatchEffect( "TeslaHitboxes", data );
  93. }
  94. #ifdef HL2_EPISODIC
  95. EmitSound( "RagdollBoogie.Zap" );
  96. #endif
  97. SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext );
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Suppression count
  101. //-----------------------------------------------------------------------------
  102. void CRagdollBoogie::IncrementSuppressionCount( CBaseEntity *pTarget )
  103. {
  104. // Look for other boogies on the ragdoll + kill them
  105. for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
  106. {
  107. CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
  108. if ( !pBoogie )
  109. continue;
  110. ++pBoogie->m_nSuppressionCount;
  111. }
  112. }
  113. void CRagdollBoogie::DecrementSuppressionCount( CBaseEntity *pTarget )
  114. {
  115. // Look for other boogies on the ragdoll + kill them
  116. CBaseEntity *pNext;
  117. for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
  118. {
  119. pNext = pChild->NextMovePeer();
  120. CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
  121. if ( !pBoogie )
  122. continue;
  123. if ( --pBoogie->m_nSuppressionCount <= 0 )
  124. {
  125. pBoogie->m_nSuppressionCount = 0;
  126. float dt = gpGlobals->curtime - pBoogie->m_flStartTime;
  127. if ( dt >= pBoogie->m_flBoogieLength )
  128. {
  129. PhysCallbackRemove( pBoogie->NetworkProp() );
  130. }
  131. }
  132. }
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Attach to an entity
  136. //-----------------------------------------------------------------------------
  137. void CRagdollBoogie::AttachToEntity( CBaseEntity *pTarget )
  138. {
  139. m_nSuppressionCount = 0;
  140. // Look for other boogies on the ragdoll + kill them
  141. CBaseEntity *pNext;
  142. for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext )
  143. {
  144. pNext = pChild->NextMovePeer();
  145. CRagdollBoogie *pBoogie = dynamic_cast<CRagdollBoogie*>(pChild);
  146. if ( !pBoogie )
  147. continue;
  148. m_nSuppressionCount = pBoogie->m_nSuppressionCount;
  149. UTIL_Remove( pChild );
  150. }
  151. FollowEntity( pTarget );
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Purpose:
  155. // Input : lifetime -
  156. //-----------------------------------------------------------------------------
  157. void CRagdollBoogie::SetBoogieTime( float flStartTime, float flLengthTime )
  158. {
  159. m_flStartTime = flStartTime;
  160. m_flBoogieLength = flLengthTime;
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Purpose: Burn targets around us
  164. //-----------------------------------------------------------------------------
  165. void CRagdollBoogie::SetMagnitude( float flMagnitude )
  166. {
  167. m_flMagnitude = flMagnitude;
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose: Burn targets around us
  171. //-----------------------------------------------------------------------------
  172. void CRagdollBoogie::BoogieThink( void )
  173. {
  174. CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( GetMoveParent() );
  175. if ( !pRagdoll )
  176. {
  177. UTIL_Remove( this );
  178. return;
  179. }
  180. float flMagnitude = m_flMagnitude;
  181. if ( m_flBoogieLength != 0 )
  182. {
  183. float dt = gpGlobals->curtime - m_flStartTime;
  184. if ( dt >= m_flBoogieLength )
  185. {
  186. // Don't remove while suppressed... this helps if we try to start another boogie
  187. if ( m_nSuppressionCount == 0 )
  188. {
  189. UTIL_Remove( this );
  190. }
  191. SetThink( NULL );
  192. return;
  193. }
  194. if ( dt < 0 )
  195. {
  196. SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
  197. return;
  198. }
  199. flMagnitude = SimpleSplineRemapVal( dt, 0.0f, m_flBoogieLength, m_flMagnitude, 0.0f );
  200. }
  201. #ifndef _XBOX
  202. if ( m_nSuppressionCount == 0 )
  203. {
  204. ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( );
  205. for ( int j = 0; j < pRagdollPhys->listCount; ++j )
  206. {
  207. float flMass = pRagdollPhys->list[j].pObject->GetMass();
  208. float flForce = m_flMagnitude * flMass;
  209. Vector vecForce;
  210. vecForce = RandomVector( -flForce, flForce );
  211. pRagdollPhys->list[j].pObject->ApplyForceCenter( vecForce );
  212. }
  213. }
  214. #endif // !_XBOX
  215. SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
  216. }