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.

223 lines
6.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #include "cbase.h"
  9. #include "c_te_particlesystem.h"
  10. #include "tier1/KeyValues.h"
  11. #include "toolframework_client.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. //-----------------------------------------------------------------------------
  15. // Purpose: Blood Stream TE
  16. //-----------------------------------------------------------------------------
  17. class C_TEBloodStream : public C_TEParticleSystem
  18. {
  19. public:
  20. DECLARE_CLASS( C_TEBloodStream, C_TEParticleSystem );
  21. DECLARE_CLIENTCLASS();
  22. C_TEBloodStream( void );
  23. virtual ~C_TEBloodStream( void );
  24. virtual void PostDataUpdate( DataUpdateType_t updateType );
  25. public:
  26. Vector m_vecDirection;
  27. int r, g, b, a;
  28. int m_nAmount;
  29. };
  30. //-----------------------------------------------------------------------------
  31. // Networking
  32. //-----------------------------------------------------------------------------
  33. IMPLEMENT_CLIENTCLASS_EVENT_DT(C_TEBloodStream, DT_TEBloodStream, CTEBloodStream)
  34. RecvPropVector( RECVINFO(m_vecDirection)),
  35. RecvPropInt( RECVINFO(r)),
  36. RecvPropInt( RECVINFO(g)),
  37. RecvPropInt( RECVINFO(b)),
  38. RecvPropInt( RECVINFO(a)),
  39. RecvPropInt( RECVINFO(m_nAmount)),
  40. END_RECV_TABLE()
  41. //-----------------------------------------------------------------------------
  42. // Purpose:
  43. //-----------------------------------------------------------------------------
  44. C_TEBloodStream::C_TEBloodStream( void )
  45. {
  46. m_vecOrigin.Init();
  47. m_vecDirection.Init();
  48. r = g = b = a = 0;
  49. m_nAmount = 0;
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Purpose:
  53. //-----------------------------------------------------------------------------
  54. C_TEBloodStream::~C_TEBloodStream( void )
  55. {
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Recording
  59. //-----------------------------------------------------------------------------
  60. static inline void RecordBloodStream( const Vector &start, const Vector &direction,
  61. int r, int g, int b, int a, int amount )
  62. {
  63. if ( !ToolsEnabled() )
  64. return;
  65. if ( clienttools->IsInRecordingMode() )
  66. {
  67. Color clr( r, g, b, a );
  68. KeyValues *msg = new KeyValues( "TempEntity" );
  69. msg->SetInt( "te", TE_BLOOD_STREAM );
  70. msg->SetString( "name", "TE_BloodStream" );
  71. msg->SetFloat( "time", gpGlobals->curtime );
  72. msg->SetFloat( "originx", start.x );
  73. msg->SetFloat( "originy", start.y );
  74. msg->SetFloat( "originz", start.z );
  75. msg->SetFloat( "directionx", direction.x );
  76. msg->SetFloat( "directiony", direction.y );
  77. msg->SetFloat( "directionz", direction.z );
  78. msg->SetColor( "color", clr );
  79. msg->SetInt( "amount", amount );
  80. ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
  81. msg->deleteThis();
  82. }
  83. }
  84. void TE_BloodStream( IRecipientFilter& filter, float delay,
  85. const Vector* org, const Vector* direction, int r, int g, int b, int a, int amount )
  86. {
  87. RecordBloodStream( *org, *direction, r, g, b, a, amount );
  88. CSmartPtr<CTEParticleRenderer> pRen = CTEParticleRenderer::Create( "TEBloodStream", *org );
  89. if( !pRen )
  90. return;
  91. // Add our particles.
  92. Vector dirCopy;
  93. float arc = 0.05;
  94. int count, count2;
  95. float num;
  96. float speedCopy = amount;
  97. Vector dir;
  98. VectorCopy( *direction, dir );
  99. VectorNormalize( dir );
  100. for (count=0 ; count<100 ; count++)
  101. {
  102. StandardParticle_t *p = pRen->AddParticle();
  103. if(p)
  104. {
  105. p->SetColor(r * random->RandomFloat(0.7, 1.0), g, b);
  106. p->SetAlpha(a);
  107. p->m_Pos = *org;
  108. pRen->SetParticleLifetime(p, 2);
  109. pRen->SetParticleType(p, pt_vox_grav);
  110. VectorCopy (dir, dirCopy);
  111. dirCopy[2] -= arc;
  112. arc -= 0.005;
  113. VectorScale (dirCopy, speedCopy, p->m_Velocity);
  114. speedCopy -= 0.00001;// so last few will drip
  115. }
  116. }
  117. // now a few rogue voxels
  118. arc = 0.075;
  119. for (count = 0 ; count < (amount/5); count ++)
  120. {
  121. StandardParticle_t *p = pRen->AddParticle();
  122. if(p)
  123. {
  124. pRen->SetParticleLifetime(p, 3);
  125. p->SetColor(r * random->RandomFloat(0.7, 1.0), g, b);
  126. p->SetAlpha(a);
  127. p->m_Pos = *org;
  128. pRen->SetParticleType(p, pt_vox_slowgrav);
  129. VectorCopy (dir, dirCopy);
  130. dirCopy[2] -= arc;
  131. arc -= 0.005;
  132. num = random->RandomFloat(0,1);
  133. speedCopy = amount * num;
  134. num *= 1.7;
  135. VectorScale (dirCopy, num, dirCopy);// randomize a bit
  136. p->m_Velocity = dirCopy * speedCopy;
  137. // add a few extra voxels directly adjacent to this one to give a
  138. // 'chunkier' appearance.
  139. for (count2 = 0; count2 < 2; count2++)
  140. {
  141. StandardParticle_t *pChunky = pRen->AddParticle();
  142. if( pChunky )
  143. {
  144. pRen->SetParticleLifetime( pChunky, 3);
  145. pChunky->SetColor(random->RandomFloat(0.7, 1.0), g, b);
  146. pChunky->SetAlpha(a);
  147. pChunky->m_Pos.Init(
  148. (*org)[0] + random->RandomFloat(-1,1),
  149. (*org)[1] + random->RandomFloat(-1,1),
  150. (*org)[2] + random->RandomFloat(-1,1));
  151. pRen->SetParticleType( pChunky, pt_vox_slowgrav);
  152. VectorCopy (dir, dirCopy);
  153. dirCopy[2] -= arc;
  154. VectorScale (dirCopy, num, dirCopy);// randomize a bit
  155. pChunky->m_Velocity = dirCopy * speedCopy;
  156. }
  157. }
  158. }
  159. }
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. void C_TEBloodStream::PostDataUpdate( DataUpdateType_t updateType )
  165. {
  166. CBroadcastRecipientFilter filter;
  167. TE_BloodStream( filter, 0.0f, &m_vecOrigin, &m_vecDirection, r, g, b, a, m_nAmount );
  168. }
  169. void TE_BloodStream( IRecipientFilter& filter, float delay, KeyValues *pKeyValues )
  170. {
  171. Vector vecOrigin, vecDirection;
  172. vecOrigin.x = pKeyValues->GetFloat( "originx" );
  173. vecOrigin.y = pKeyValues->GetFloat( "originy" );
  174. vecOrigin.z = pKeyValues->GetFloat( "originz" );
  175. vecDirection.x = pKeyValues->GetFloat( "directionx" );
  176. vecDirection.y = pKeyValues->GetFloat( "directiony" );
  177. vecDirection.z = pKeyValues->GetFloat( "directionz" );
  178. Color c = pKeyValues->GetColor( "color" );
  179. int nAmount = pKeyValues->GetInt( "amount" );
  180. TE_BloodStream( filter, 0.0f, &vecOrigin, &vecDirection, c.r(), c.g(), c.b(), c.a(), nAmount );
  181. }