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.

413 lines
11 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 "baseparticleentity.h"
  10. #include "iefx.h"
  11. #include "decals.h"
  12. #include "beamdraw.h"
  13. #include "hud.h"
  14. #include "clienteffectprecachesystem.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. CLIENTEFFECT_REGISTER_BEGIN( PrecacheExtinguisher )
  18. CLIENTEFFECT_MATERIAL( "particle/particle_smokegrenade" )
  19. CLIENTEFFECT_REGISTER_END()
  20. class C_ExtinguisherJet : public C_BaseEntity
  21. {
  22. public:
  23. DECLARE_CLIENTCLASS();
  24. DECLARE_CLASS( C_ExtinguisherJet, C_BaseEntity );
  25. C_ExtinguisherJet();
  26. ~C_ExtinguisherJet();
  27. void OnDataChanged( DataUpdateType_t updateType );
  28. void Update( float fTimeDelta );
  29. void Start( void );
  30. int DrawModel( int flags );
  31. bool ShouldDraw( void ) { return m_bEmit; }
  32. protected:
  33. void AddExtinguisherDecal( trace_t &tr );
  34. bool m_bEmit;
  35. bool m_bUseMuzzlePoint;
  36. int m_nLength;
  37. int m_nSize;
  38. PMaterialHandle m_MaterialHandle;
  39. PMaterialHandle m_EmberMaterialHandle;
  40. TimedEvent m_ParticleSpawn;
  41. CSmartPtr<CSimpleEmitter> m_pEmitter;
  42. CSmartPtr<CEmberEffect> m_pEmberEmitter;
  43. private:
  44. C_ExtinguisherJet( const C_ExtinguisherJet & );
  45. };
  46. //Datatable
  47. IMPLEMENT_CLIENTCLASS_DT( C_ExtinguisherJet, DT_ExtinguisherJet, CExtinguisherJet )
  48. RecvPropInt(RECVINFO(m_bEmit), 0),
  49. RecvPropInt(RECVINFO(m_bUseMuzzlePoint), 0),
  50. RecvPropInt(RECVINFO(m_nLength), 0),
  51. RecvPropInt(RECVINFO(m_nSize), 0),
  52. END_RECV_TABLE()
  53. //-----------------------------------------------------------------------------
  54. // Purpose:
  55. //-----------------------------------------------------------------------------
  56. C_ExtinguisherJet::C_ExtinguisherJet( void )
  57. {
  58. m_bEmit = false;
  59. m_pEmitter = NULL;
  60. m_pEmberEmitter = NULL;
  61. }
  62. C_ExtinguisherJet::~C_ExtinguisherJet( void )
  63. {
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Purpose:
  67. // Input : bnewentity -
  68. //-----------------------------------------------------------------------------
  69. void C_ExtinguisherJet::OnDataChanged( DataUpdateType_t updateType )
  70. {
  71. C_BaseEntity::OnDataChanged(updateType);
  72. if( updateType == DATA_UPDATE_CREATED )
  73. {
  74. Start();
  75. }
  76. }
  77. //-----------------------------------------------------------------------------
  78. // Purpose:
  79. //-----------------------------------------------------------------------------
  80. void C_ExtinguisherJet::Start( void )
  81. {
  82. AddToLeafSystem( RENDER_GROUP_TRANSLUCENT_ENTITY );
  83. m_ParticleSpawn.Init( 100 ); //Events per second
  84. //Create the basic emitter
  85. m_pEmitter = CSimpleEmitter::Create("C_ExtinguisherJet::m_pEmitter");
  86. Assert( m_pEmitter.IsValid() );
  87. if ( m_pEmitter.IsValid() )
  88. {
  89. m_MaterialHandle = g_Mat_DustPuff[0];
  90. m_pEmitter->SetSortOrigin( GetAbsOrigin() );
  91. }
  92. //Create the "ember" emitter for the smaller flecks
  93. m_pEmberEmitter = CEmberEffect::Create( "C_ExtinguisherJet::m_pEmberEmitter" );
  94. Assert( m_pEmberEmitter.IsValid() );
  95. if ( m_pEmberEmitter.IsValid() )
  96. {
  97. m_EmberMaterialHandle = g_Mat_DustPuff[0];
  98. m_pEmberEmitter->SetSortOrigin( GetAbsOrigin() );
  99. }
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose:
  103. //-----------------------------------------------------------------------------
  104. void C_ExtinguisherJet::AddExtinguisherDecal( trace_t &tr )
  105. {
  106. C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
  107. if ( ent != NULL )
  108. {
  109. int index = decalsystem->GetDecalIndexForName( "Extinguish" );
  110. if ( index >= 0 )
  111. {
  112. Vector endpos;
  113. endpos.Random( -24.0f, 24.0f );
  114. endpos += tr.endpos;
  115. effects->DecalShoot( index, 0, ent->GetModel(), ent->GetAbsOrigin(), ent->GetAbsAngles(), endpos, 0, 0 );
  116. }
  117. }
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Purpose:
  121. // Input : fTimeDelta -
  122. //-----------------------------------------------------------------------------
  123. void C_ExtinguisherJet::Update( float fTimeDelta )
  124. {
  125. if ( m_bEmit == false )
  126. return;
  127. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  128. if ( m_bUseMuzzlePoint )
  129. {
  130. C_BaseViewModel *vm = player ? player->GetViewModel( 0 ) : NULL;
  131. if ( vm )
  132. {
  133. int iAttachment = vm->LookupAttachment( "muzzle" );
  134. Vector origin;
  135. QAngle angles;
  136. vm->GetAttachment( iAttachment, origin, angles );
  137. Assert( !GetMoveParent() );
  138. SetLocalOrigin( origin );
  139. SetLocalAngles( angles );
  140. }
  141. }
  142. trace_t tr;
  143. Vector shotDir, vRight, vUp;
  144. AngleVectors( GetAbsAngles(), &shotDir, &vRight, &vUp );
  145. //FIXME: Muzzle point is incorrect on the model!
  146. if ( m_bUseMuzzlePoint )
  147. {
  148. shotDir.Negate();
  149. }
  150. Vector endPoint = GetAbsOrigin() + ( shotDir * 150.0f );
  151. UTIL_TraceLine( GetAbsOrigin(), endPoint, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &tr );
  152. bool hitWall = ( tr.fraction < 1.0f );
  153. //Add normal jet
  154. if ( m_pEmitter.IsValid() )
  155. {
  156. SimpleParticle *pParticle;
  157. m_pEmitter->SetSortOrigin( GetAbsOrigin() );
  158. float tempDelta = fTimeDelta;
  159. //FIXME: All particles need to be within this loop
  160. while( m_ParticleSpawn.NextEvent( tempDelta ) )
  161. {
  162. pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() );
  163. if ( pParticle )
  164. {
  165. pParticle->m_flDieTime = 0.2f;
  166. pParticle->m_flLifetime = 0.0f;
  167. pParticle->m_flRoll = random->RandomInt( 0, 360 );
  168. pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f );
  169. pParticle->m_uchStartSize = 1;
  170. pParticle->m_uchEndSize = random->RandomInt( 32, 48 );
  171. pParticle->m_uchStartAlpha = random->RandomInt( 128, 164 );
  172. pParticle->m_uchEndAlpha = 0;
  173. int cScale = random->RandomInt( 192, 255 );
  174. pParticle->m_uchColor[0] = cScale;
  175. pParticle->m_uchColor[1] = cScale;
  176. pParticle->m_uchColor[2] = cScale;
  177. Vector dir;
  178. QAngle ofsAngles;
  179. ofsAngles.Random( -8.0f, 8.0f );
  180. ofsAngles += GetAbsAngles();
  181. AngleVectors( ofsAngles, &dir );
  182. if ( m_bUseMuzzlePoint )
  183. {
  184. dir.Negate();
  185. }
  186. pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 );
  187. }
  188. //Add muzzle effect
  189. pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() );
  190. if ( pParticle )
  191. {
  192. pParticle->m_flDieTime = 0.1f;
  193. pParticle->m_flLifetime = 0.0f;
  194. pParticle->m_flRoll = random->RandomInt( 0, 360 );
  195. pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f );
  196. pParticle->m_uchStartSize = 1;
  197. pParticle->m_uchEndSize = random->RandomInt( 8, 16 );
  198. pParticle->m_uchStartAlpha = random->RandomInt( 128, 255 );
  199. pParticle->m_uchEndAlpha = 0;
  200. int cScale = random->RandomInt( 192, 255 );
  201. pParticle->m_uchColor[0] = cScale;
  202. pParticle->m_uchColor[1] = cScale;
  203. pParticle->m_uchColor[2] = cScale;
  204. Vector dir;
  205. QAngle ofsAngles;
  206. ofsAngles.Random( -64.0f, 64.0f );
  207. ofsAngles += GetAbsAngles();
  208. AngleVectors( ofsAngles, &dir );
  209. if ( m_bUseMuzzlePoint )
  210. {
  211. dir.Negate();
  212. }
  213. pParticle->m_vecVelocity = dir * random->RandomInt( 32, 64 );
  214. }
  215. //Add a wall effect if needed
  216. if ( hitWall )
  217. {
  218. AddExtinguisherDecal( tr );
  219. Vector offDir;
  220. offDir.Random( -16.0f, 16.0f );
  221. pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, ( tr.endpos + ( tr.plane.normal * 8.0f ) ) + offDir );
  222. if ( pParticle )
  223. {
  224. pParticle->m_flDieTime = 0.4f;
  225. pParticle->m_flLifetime = 0.0f;
  226. pParticle->m_flRoll = random->RandomInt( 0, 360 );
  227. pParticle->m_flRollDelta= random->RandomFloat( -2.0f, 2.0f );
  228. pParticle->m_uchStartSize = random->RandomInt( 8, 16 );
  229. pParticle->m_uchEndSize = random->RandomInt( 24, 32 );
  230. pParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
  231. pParticle->m_uchEndAlpha = 0;
  232. int cScale = random->RandomInt( 192, 255 );
  233. pParticle->m_uchColor[0] = cScale;
  234. pParticle->m_uchColor[1] = cScale;
  235. pParticle->m_uchColor[2] = cScale;
  236. Vector rDir;
  237. rDir = tr.plane.normal;
  238. rDir[0] += random->RandomFloat( -0.9f, 0.9f );
  239. rDir[1] += random->RandomFloat( -0.9f, 0.9f );
  240. rDir[2] += random->RandomFloat( -0.9f, 0.9f );
  241. pParticle->m_vecVelocity = rDir * random->RandomInt( 32, 64 );
  242. }
  243. }
  244. //Add small ember-like particles
  245. if ( random->RandomInt( 0, 1 ) == 0 )
  246. {
  247. m_pEmberEmitter->SetSortOrigin( GetAbsOrigin() );
  248. pParticle = (SimpleParticle *) m_pEmberEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], GetAbsOrigin() );
  249. assert(pParticle);
  250. if ( pParticle )
  251. {
  252. pParticle->m_flLifetime = 0.0f;
  253. pParticle->m_flDieTime = 1.0f;
  254. pParticle->m_flRoll = 0;
  255. pParticle->m_flRollDelta = 0;
  256. pParticle->m_uchColor[0] = 255;
  257. pParticle->m_uchColor[1] = 255;
  258. pParticle->m_uchColor[2] = 255;
  259. pParticle->m_uchStartAlpha = 255;
  260. pParticle->m_uchEndAlpha = 0;
  261. pParticle->m_uchStartSize = 1;
  262. pParticle->m_uchEndSize = 0;
  263. Vector dir;
  264. QAngle ofsAngles;
  265. ofsAngles.Random( -8.0f, 8.0f );
  266. ofsAngles += GetAbsAngles();
  267. AngleVectors( ofsAngles, &dir );
  268. if ( m_bUseMuzzlePoint )
  269. {
  270. dir.Negate();
  271. }
  272. pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 );
  273. }
  274. }
  275. }
  276. }
  277. // Inner beam
  278. CBeamSegDraw beamDraw;
  279. CBeamSeg seg;
  280. const int numPoints = 4;
  281. Vector beamPoints[numPoints];
  282. beamPoints[0] = GetAbsOrigin();
  283. // Create our beam points
  284. int i;
  285. for ( i = 0; i < numPoints; i++ )
  286. {
  287. beamPoints[i] = GetAbsOrigin() + ( shotDir * (32*i*i) );
  288. beamPoints[i] += vRight * sin( gpGlobals->curtime * 4.0f ) * (2.0f*i);
  289. beamPoints[i] += vUp * sin( gpGlobals->curtime * 8.0f ) * (1.0f*i);
  290. beamPoints[i] += shotDir * sin( gpGlobals->curtime * (16.0f*i) ) * (1.0f*i);
  291. }
  292. IMaterial *pMat = materials->FindMaterial( "particle/particle_smokegrenade", TEXTURE_GROUP_PARTICLE );
  293. beamDraw.Start( numPoints, pMat );
  294. //Setup and draw those points
  295. for( i = 0; i < numPoints; i++ )
  296. {
  297. float t = (float) i / (numPoints - 1);
  298. float color = 1.0f * (1.0f - t);
  299. seg.m_vColor = Vector( color, color, color );
  300. seg.m_vPos = beamPoints[i];
  301. seg.m_flTexCoord = (float)i/(float)(numPoints-1) - ((gpGlobals->curtime - (int)gpGlobals->curtime) * 4.0f );
  302. seg.m_flWidth = 4.0f + ( (64.0f*t) * (fabs( sin( gpGlobals->curtime * 16.0f ) )) );
  303. seg.m_flAlpha = color;
  304. beamDraw.NextSeg( &seg );
  305. }
  306. beamDraw.End();
  307. }
  308. //-----------------------------------------------------------------------------
  309. // Purpose:
  310. // Input : flags -
  311. //-----------------------------------------------------------------------------
  312. int C_ExtinguisherJet::DrawModel( int flags )
  313. {
  314. if ( m_bEmit == false )
  315. return 1;
  316. Update( Helper_GetFrameTime() );
  317. return 1;
  318. }