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.

279 lines
8.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "particles_simple.h"
  9. #include "c_tracer.h"
  10. #include "particle_collision.h"
  11. #include "view.h"
  12. #include "clienteffectprecachesystem.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. #define PLASMASPARK_LIFETIME 0.5
  16. #define SPRAYS_PER_THINK 12
  17. CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectPlasmaBeam )
  18. CLIENTEFFECT_MATERIAL( "sprites/plasmaember" )
  19. CLIENTEFFECT_REGISTER_END()
  20. class C_PlasmaBeamNode;
  21. //##################################################################
  22. //
  23. // > CPlasmaSpray
  24. //
  25. //##################################################################
  26. class CPlasmaSpray : public CSimpleEmitter
  27. {
  28. public:
  29. CPlasmaSpray( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
  30. static CSmartPtr<CPlasmaSpray> Create( const char *pDebugName );
  31. void Think( void );
  32. void UpdateVelocity( SimpleParticle *pParticle, float timeDelta );
  33. virtual void RenderParticles( CParticleRenderIterator *pIterator );
  34. virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
  35. EHANDLE m_pOwner;
  36. CParticleCollision m_ParticleCollision;
  37. private:
  38. CPlasmaSpray( const CPlasmaSpray & );
  39. };
  40. //##################################################################
  41. //
  42. // PlasmaBeamNode - generates plasma spray
  43. //
  44. //##################################################################
  45. class C_PlasmaBeamNode : public C_BaseEntity
  46. {
  47. public:
  48. DECLARE_CLASS( C_PlasmaBeamNode, C_BaseEntity );
  49. DECLARE_CLIENTCLASS();
  50. C_PlasmaBeamNode();
  51. ~C_PlasmaBeamNode(void);
  52. public:
  53. void ClientThink(void);
  54. void AddEntity( void );
  55. void OnDataChanged(DataUpdateType_t updateType);
  56. bool ShouldDraw();
  57. bool m_bSprayOn;
  58. CSmartPtr<CPlasmaSpray> m_pFirePlasmaSpray;
  59. };
  60. //##################################################################
  61. //
  62. // > CPlasmaSpray
  63. //
  64. //##################################################################
  65. //-----------------------------------------------------------------------------
  66. // Purpose:
  67. // Input : *pParticle -
  68. // timeDelta -
  69. // Output : float
  70. //-----------------------------------------------------------------------------
  71. CSmartPtr<CPlasmaSpray> CPlasmaSpray::Create( const char *pDebugName )
  72. {
  73. CPlasmaSpray *pRet = new CPlasmaSpray( pDebugName );
  74. return pRet;
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Purpose:
  78. // Input : fTimeDelta -
  79. // Output : Vector
  80. //-----------------------------------------------------------------------------
  81. void CPlasmaSpray::UpdateVelocity( SimpleParticle *pParticle, float timeDelta )
  82. {
  83. Vector vGravity = Vector(0,0,-1000);
  84. float flFrametime = gpGlobals->frametime;
  85. vGravity = flFrametime * vGravity;
  86. pParticle->m_vecVelocity += vGravity;
  87. }
  88. void CPlasmaSpray::SimulateParticles( CParticleSimulateIterator *pIterator )
  89. {
  90. float timeDelta = pIterator->GetTimeDelta();
  91. SimpleParticle *pParticle = (SimpleParticle*)pIterator->GetFirst();
  92. while ( pParticle )
  93. {
  94. //Should this particle die?
  95. pParticle->m_flLifetime += timeDelta;
  96. C_PlasmaBeamNode* pNode = (C_PlasmaBeamNode*)((C_BaseEntity*)m_pOwner);
  97. if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
  98. {
  99. pIterator->RemoveParticle( pParticle );
  100. }
  101. // If owner is gone or spray off remove me
  102. else if (pNode == NULL || !pNode->m_bSprayOn)
  103. {
  104. pIterator->RemoveParticle( pParticle );
  105. }
  106. //Simulate the movement with collision
  107. trace_t trace;
  108. m_ParticleCollision.MoveParticle( pParticle->m_Pos, pParticle->m_vecVelocity, NULL, timeDelta, &trace );
  109. pParticle = (SimpleParticle*)pIterator->GetNext();
  110. }
  111. }
  112. void CPlasmaSpray::RenderParticles( CParticleRenderIterator *pIterator )
  113. {
  114. const SimpleParticle *pParticle = (const SimpleParticle *)pIterator->GetFirst();
  115. while ( pParticle )
  116. {
  117. float scale = random->RandomFloat( 0.02, 0.08 );
  118. // NOTE: We need to do everything in screen space
  119. Vector delta;
  120. Vector start;
  121. TransformParticle(ParticleMgr()->GetModelView(), pParticle->m_Pos, start);
  122. float sortKey = start.z;
  123. Vector3DMultiply( CurrentWorldToViewMatrix(), pParticle->m_vecVelocity, delta );
  124. delta[0] *= scale;
  125. delta[1] *= scale;
  126. delta[2] *= scale;
  127. // See c_tracer.* for this method
  128. Tracer_Draw( pIterator->GetParticleDraw(), start, delta, random->RandomInt( 2, 8 ), 0 );
  129. pParticle = (const SimpleParticle *)pIterator->GetNext( sortKey );
  130. }
  131. }
  132. //##################################################################
  133. //
  134. // PlasmaBeamNode - generates plasma spray
  135. //
  136. //##################################################################
  137. //------------------------------------------------------------------------------
  138. // Purpose :
  139. // Input :
  140. // Output :
  141. //------------------------------------------------------------------------------
  142. C_PlasmaBeamNode::C_PlasmaBeamNode(void)
  143. {
  144. m_bSprayOn = false;
  145. m_pFirePlasmaSpray = CPlasmaSpray::Create( "C_PlasmaBeamNode" );
  146. }
  147. //------------------------------------------------------------------------------
  148. // Purpose :
  149. // Input :
  150. // Output :
  151. //------------------------------------------------------------------------------
  152. C_PlasmaBeamNode::~C_PlasmaBeamNode(void)
  153. {
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Purpose:
  157. //-----------------------------------------------------------------------------
  158. void C_PlasmaBeamNode::AddEntity( void )
  159. {
  160. m_pFirePlasmaSpray->SetSortOrigin( GetAbsOrigin() );
  161. }
  162. //------------------------------------------------------------------------------
  163. // Purpose :
  164. // Input :
  165. // Output :
  166. //------------------------------------------------------------------------------
  167. void C_PlasmaBeamNode::OnDataChanged(DataUpdateType_t updateType)
  168. {
  169. if (updateType == DATA_UPDATE_CREATED)
  170. {
  171. Vector vMoveDir = GetAbsVelocity();
  172. float flVel = VectorNormalize(vMoveDir);
  173. m_pFirePlasmaSpray->m_ParticleCollision.Setup( GetAbsOrigin(), &vMoveDir, 0.3,
  174. flVel-50, flVel+50, 800, 0.5 );
  175. SetNextClientThink(gpGlobals->curtime + 0.01);
  176. }
  177. C_BaseEntity::OnDataChanged(updateType);
  178. }
  179. //------------------------------------------------------------------------------
  180. // Purpose :
  181. // Input :
  182. // Output :
  183. //------------------------------------------------------------------------------
  184. bool C_PlasmaBeamNode::ShouldDraw()
  185. {
  186. return false;
  187. }
  188. //------------------------------------------------------------------------------
  189. // Purpose :
  190. // Input :
  191. // Output :
  192. //------------------------------------------------------------------------------
  193. void C_PlasmaBeamNode::ClientThink(void)
  194. {
  195. if (!m_bSprayOn)
  196. {
  197. return;
  198. }
  199. trace_t trace;
  200. Vector vEndTrace = GetAbsOrigin() + (0.3*GetAbsVelocity());
  201. UTIL_TraceLine( GetAbsOrigin(), vEndTrace, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &trace );
  202. if ( trace.fraction != 1.0f || trace.startsolid)
  203. {
  204. m_bSprayOn = false;
  205. return;
  206. }
  207. PMaterialHandle handle = m_pFirePlasmaSpray->GetPMaterial( "sprites/plasmaember" );
  208. for (int i=0;i<SPRAYS_PER_THINK;i++)
  209. {
  210. SimpleParticle *sParticle;
  211. //Make a new particle
  212. if ( random->RandomInt( 0, 2 ) == 0 )
  213. {
  214. float ranx = random->RandomFloat( -28.0f, 28.0f );
  215. float rany = random->RandomFloat( -28.0f, 28.0f );
  216. float ranz = random->RandomFloat( -28.0f, 28.0f );
  217. Vector vNewPos = GetAbsOrigin();
  218. Vector vAdd = Vector(GetAbsAngles().x,GetAbsAngles().y,GetAbsAngles().z)*random->RandomFloat(-60,120);
  219. vNewPos += vAdd;
  220. sParticle = (SimpleParticle *) m_pFirePlasmaSpray->AddParticle( sizeof(SimpleParticle), handle, vNewPos );
  221. sParticle->m_flLifetime = 0.0f;
  222. sParticle->m_flDieTime = PLASMASPARK_LIFETIME;
  223. sParticle->m_vecVelocity = GetAbsVelocity();
  224. sParticle->m_vecVelocity.x += ranx;
  225. sParticle->m_vecVelocity.y += rany;
  226. sParticle->m_vecVelocity.z += ranz;
  227. m_pFirePlasmaSpray->m_pOwner = this;
  228. }
  229. }
  230. SetNextClientThink(gpGlobals->curtime + 0.05);
  231. }
  232. IMPLEMENT_CLIENTCLASS_DT(C_PlasmaBeamNode, DT_PlasmaBeamNode, CPlasmaBeamNode )
  233. RecvPropVector (RECVINFO(m_vecVelocity), 0, RecvProxy_LocalVelocity),
  234. RecvPropInt (RECVINFO(m_bSprayOn)),
  235. END_RECV_TABLE()