Counter Strike : Global Offensive Source Code
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.

332 lines
9.9 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Client explosions
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "tempentity.h" // FLAGS
  9. #include "c_te_particlesystem.h"
  10. #include "ragdollexplosionenumerator.h"
  11. #include "glow_overlay.h"
  12. #include "fx_explosion.h"
  13. #include "engine/ivdebugoverlay.h"
  14. #include "tier1/keyvalues.h"
  15. #include "toolframework_client.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. #define OLD_EXPLOSION 0
  19. // Enumator class for ragdolls being affected by explosive forces
  20. CRagdollExplosionEnumerator::CRagdollExplosionEnumerator( Vector origin, float radius, float magnitude )
  21. {
  22. m_vecOrigin = origin;
  23. m_flMagnitude = magnitude;
  24. m_flRadius = radius;
  25. }
  26. // Actual work code
  27. IterationRetval_t CRagdollExplosionEnumerator::EnumElement( IHandleEntity *pHandleEntity )
  28. {
  29. C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() );
  30. if ( pEnt == NULL )
  31. return ITERATION_CONTINUE;
  32. C_BaseAnimating *pModel = static_cast< C_BaseAnimating * >( pEnt );
  33. // If the ragdoll was created on this tick, then the forces were already applied on the server
  34. if ( pModel == NULL || WasRagdollCreatedOnCurrentTick( pEnt ) )
  35. return ITERATION_CONTINUE;
  36. m_Entities.AddToTail( pEnt );
  37. return ITERATION_CONTINUE;
  38. }
  39. CRagdollExplosionEnumerator::~CRagdollExplosionEnumerator()
  40. {
  41. for (int i = 0; i < m_Entities.Count(); i++ )
  42. {
  43. C_BaseEntity *pEnt = m_Entities[i];
  44. C_BaseAnimating *pModel = static_cast< C_BaseAnimating * >( pEnt );
  45. Vector position = pEnt->CollisionProp()->GetCollisionOrigin();
  46. Vector dir = position - m_vecOrigin;
  47. float dist = VectorNormalize( dir );
  48. float force = m_flMagnitude - ( ( m_flMagnitude / m_flRadius ) * dist );
  49. if ( force <= 1.0f )
  50. continue;
  51. trace_t tr;
  52. UTIL_TraceLine( m_vecOrigin, position, MASK_SHOT_HULL, NULL, COLLISION_GROUP_NONE, &tr );
  53. // debugoverlay->AddLineOverlay( m_vecOrigin, position, 0,255,0, true, 18.0 );
  54. if ( tr.fraction < 1.0f && tr.m_pEnt != pModel )
  55. continue;
  56. dir *= force; // scale force
  57. // tricky, adjust tr.start so end-start->= force
  58. tr.startpos = tr.endpos - dir;
  59. // move expolsion center a bit down, so things fly higher
  60. tr.startpos.z -= 32.0f;
  61. pModel->ImpactTrace( &tr, DMG_BLAST, NULL );
  62. }
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Explosion TE
  66. //-----------------------------------------------------------------------------
  67. class C_TEExplosion : public C_TEParticleSystem
  68. {
  69. public:
  70. DECLARE_CLASS( C_TEExplosion, C_TEParticleSystem );
  71. DECLARE_CLIENTCLASS();
  72. C_TEExplosion( void );
  73. virtual ~C_TEExplosion( void );
  74. virtual void PostDataUpdate( DataUpdateType_t updateType );
  75. virtual void RenderParticles( CParticleRenderIterator *pIterator );
  76. virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
  77. private:
  78. // Recording
  79. void RecordExplosion( );
  80. public:
  81. void AffectRagdolls( void );
  82. int m_nModelIndex;
  83. float m_fScale;
  84. int m_nFrameRate;
  85. int m_nFlags;
  86. Vector m_vecNormal;
  87. char m_chMaterialType;
  88. int m_nRadius;
  89. int m_nMagnitude;
  90. //CParticleCollision m_ParticleCollision;
  91. CParticleMgr *m_pParticleMgr;
  92. PMaterialHandle m_MaterialHandle;
  93. bool m_bShouldAffectRagdolls;
  94. };
  95. //-----------------------------------------------------------------------------
  96. // Networking
  97. //-----------------------------------------------------------------------------
  98. IMPLEMENT_CLIENTCLASS_EVENT_DT(C_TEExplosion, DT_TEExplosion, CTEExplosion)
  99. RecvPropInt( RECVINFO(m_nModelIndex)),
  100. RecvPropFloat( RECVINFO(m_fScale )),
  101. RecvPropInt( RECVINFO(m_nFrameRate)),
  102. RecvPropInt( RECVINFO(m_nFlags)),
  103. RecvPropVector( RECVINFO(m_vecNormal)),
  104. RecvPropInt( RECVINFO(m_chMaterialType)),
  105. RecvPropInt( RECVINFO(m_nRadius)),
  106. RecvPropInt( RECVINFO(m_nMagnitude)),
  107. END_RECV_TABLE()
  108. //-----------------------------------------------------------------------------
  109. // Purpose:
  110. //-----------------------------------------------------------------------------
  111. C_TEExplosion::C_TEExplosion( void )
  112. {
  113. m_bShouldAffectRagdolls = true;
  114. m_nModelIndex = 0;
  115. m_fScale = 0;
  116. m_nFrameRate = 0;
  117. m_nFlags = 0;
  118. m_vecNormal.Init();
  119. m_chMaterialType = 'C';
  120. m_nRadius = 0;
  121. m_nMagnitude = 0;
  122. m_pParticleMgr = NULL;
  123. m_MaterialHandle = INVALID_MATERIAL_HANDLE;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose:
  127. //-----------------------------------------------------------------------------
  128. C_TEExplosion::~C_TEExplosion( void )
  129. {
  130. }
  131. //-----------------------------------------------------------------------------
  132. // Purpose:
  133. //-----------------------------------------------------------------------------
  134. void C_TEExplosion::AffectRagdolls( void )
  135. {
  136. if ( ( m_nRadius == 0 ) || ( m_nMagnitude == 0 ) || (!m_bShouldAffectRagdolls) )
  137. return;
  138. CRagdollExplosionEnumerator ragdollEnum( m_vecOrigin, m_nRadius, m_nMagnitude );
  139. ::partition->EnumerateElementsInSphere( PARTITION_CLIENT_RESPONSIVE_EDICTS, m_vecOrigin, m_nRadius, false, &ragdollEnum );
  140. }
  141. //
  142. // CExplosionOverlay
  143. //
  144. bool CExplosionOverlay::Update( void )
  145. {
  146. m_flLifetime += gpGlobals->frametime;
  147. const float flTotalLifetime = 0.1f;
  148. if ( m_flLifetime < flTotalLifetime )
  149. {
  150. float flColorScale = 1.0f - ( m_flLifetime / flTotalLifetime );
  151. for( int i=0; i < m_nSprites; i++ )
  152. {
  153. m_Sprites[i].m_vColor = m_vBaseColors[i] * flColorScale;
  154. m_Sprites[i].m_flHorzSize += 16.0f * gpGlobals->frametime;
  155. m_Sprites[i].m_flVertSize += 16.0f * gpGlobals->frametime;
  156. }
  157. return true;
  158. }
  159. return false;
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Recording
  163. //-----------------------------------------------------------------------------
  164. void C_TEExplosion::RecordExplosion( )
  165. {
  166. if ( !ToolsEnabled() )
  167. return;
  168. if ( clienttools->IsInRecordingMode() )
  169. {
  170. const model_t* pModel = (m_nModelIndex != 0) ? modelinfo->GetModel( m_nModelIndex ) : NULL;
  171. const char *pModelName = pModel ? modelinfo->GetModelName( pModel ) : "";
  172. KeyValues *msg = new KeyValues( "TempEntity" );
  173. msg->SetInt( "te", TE_EXPLOSION );
  174. msg->SetString( "name", "TE_Explosion" );
  175. msg->SetFloat( "time", gpGlobals->curtime );
  176. msg->SetFloat( "originx", m_vecOrigin.x );
  177. msg->SetFloat( "originy", m_vecOrigin.y );
  178. msg->SetFloat( "originz", m_vecOrigin.z );
  179. msg->SetFloat( "directionx", m_vecNormal.x );
  180. msg->SetFloat( "directiony", m_vecNormal.y );
  181. msg->SetFloat( "directionz", m_vecNormal.z );
  182. msg->SetString( "model", pModelName );
  183. msg->SetFloat( "scale", m_fScale );
  184. msg->SetInt( "framerate", m_nFrameRate );
  185. msg->SetInt( "flags", m_nFlags );
  186. msg->SetInt( "materialtype", m_chMaterialType );
  187. msg->SetInt( "radius", m_nRadius );
  188. msg->SetInt( "magnitude", m_nMagnitude );
  189. ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
  190. msg->deleteThis();
  191. }
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Purpose:
  195. // Input : bool -
  196. //-----------------------------------------------------------------------------
  197. void C_TEExplosion::PostDataUpdate( DataUpdateType_t updateType )
  198. {
  199. RecordExplosion();
  200. AffectRagdolls();
  201. // Filter out a water explosion
  202. if ( UTIL_PointContents( m_vecOrigin, MASK_WATER ) & CONTENTS_WATER )
  203. {
  204. WaterExplosionEffect().Create( m_vecOrigin, m_nMagnitude, m_fScale, m_nFlags );
  205. return;
  206. }
  207. if ( !( m_nFlags & TE_EXPLFLAG_NOFIREBALL ) )
  208. {
  209. if ( CExplosionOverlay *pOverlay = new CExplosionOverlay )
  210. {
  211. pOverlay->m_flLifetime = 0;
  212. pOverlay->m_vPos = m_vecOrigin;
  213. pOverlay->m_nSprites = 1;
  214. pOverlay->m_vBaseColors[0].Init( 1.0f, 0.9f, 0.7f );
  215. pOverlay->m_Sprites[0].m_flHorzSize = 0.05f;
  216. pOverlay->m_Sprites[0].m_flVertSize = pOverlay->m_Sprites[0].m_flHorzSize*0.5f;
  217. pOverlay->Activate();
  218. }
  219. }
  220. BaseExplosionEffect().Create( m_vecOrigin, m_nMagnitude, m_fScale, m_nFlags );
  221. }
  222. void C_TEExplosion::RenderParticles( CParticleRenderIterator *pIterator )
  223. {
  224. }
  225. void C_TEExplosion::SimulateParticles( CParticleSimulateIterator *pIterator )
  226. {
  227. pIterator->RemoveAllParticles();
  228. }
  229. void TE_Explosion( IRecipientFilter& filter, float delay,
  230. const Vector& pos, int modelindex, float scale, int framerate, int flags, int radius, int magnitude,
  231. const Vector& normal, unsigned char materialType = 'C', bool bShouldAffectRagdolls = true )
  232. {
  233. // Major hack to access singleton object for doing this event (simulate receiving network message)
  234. __g_C_TEExplosion.m_nModelIndex = modelindex;
  235. __g_C_TEExplosion.m_fScale = scale;
  236. __g_C_TEExplosion.m_nFrameRate = framerate;
  237. __g_C_TEExplosion.m_nFlags = flags;
  238. __g_C_TEExplosion.m_vecOrigin = pos;
  239. __g_C_TEExplosion.m_vecNormal = normal;
  240. __g_C_TEExplosion.m_chMaterialType = materialType;
  241. __g_C_TEExplosion.m_nRadius = radius;
  242. __g_C_TEExplosion.m_nMagnitude = magnitude;
  243. __g_C_TEExplosion.m_bShouldAffectRagdolls = bShouldAffectRagdolls;
  244. __g_C_TEExplosion.PostDataUpdate( DATA_UPDATE_CREATED );
  245. }
  246. void TE_Explosion( IRecipientFilter& filter, float delay, KeyValues *pKeyValues )
  247. {
  248. Vector vecOrigin, vecNormal;
  249. vecOrigin.x = pKeyValues->GetFloat( "originx" );
  250. vecOrigin.y = pKeyValues->GetFloat( "originy" );
  251. vecOrigin.z = pKeyValues->GetFloat( "originz" );
  252. vecNormal.x = pKeyValues->GetFloat( "directionx" );
  253. vecNormal.y = pKeyValues->GetFloat( "directiony" );
  254. vecNormal.z = pKeyValues->GetFloat( "directionz" );
  255. const char *pModelName = pKeyValues->GetString( "model" );
  256. int nModelIndex = pModelName[0] ? modelinfo->GetModelIndex( pModelName ) : 0;
  257. float flScale = pKeyValues->GetFloat( "scale" );
  258. int nFrameRate = pKeyValues->GetInt( "framerate" );
  259. int nFlags = pKeyValues->GetInt( "flags" );
  260. int nMaterialType = pKeyValues->GetInt( "materialtype" );
  261. int nRadius = pKeyValues->GetInt( "radius" );
  262. int nMagnitude = pKeyValues->GetInt( "magnitude" );
  263. TE_Explosion( filter, 0.0f, vecOrigin, nModelIndex, flScale, nFrameRate,
  264. nFlags, nRadius, nMagnitude, vecNormal, (unsigned char)nMaterialType, false );
  265. }