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.

486 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "particles_simple.h"
  8. #include "citadel_effects_shared.h"
  9. #include "particles_attractor.h"
  10. class C_AlyxEmpEffect : public C_BaseEntity
  11. {
  12. DECLARE_CLASS( C_AlyxEmpEffect, C_BaseEntity );
  13. DECLARE_CLIENTCLASS();
  14. public:
  15. void OnDataChanged( DataUpdateType_t updateType );
  16. RenderGroup_t GetRenderGroup( void );
  17. void ClientThink( void );
  18. void NotifyShouldTransmit( ShouldTransmitState_t state );
  19. void UpdateIdle( float percentage );
  20. void UpdateCharging( float percentage );
  21. void UpdateDischarging( void );
  22. private:
  23. bool SetupEmitters( void );
  24. inline float GetStateDurationPercentage( void );
  25. int m_nState;
  26. float m_flDuration;
  27. float m_flStartTime;
  28. TimedEvent m_tParticleSpawn;
  29. CSmartPtr<CSimpleEmitter> m_pSimpleEmitter;
  30. CSmartPtr<CParticleAttractor> m_pAttractorEmitter;
  31. };
  32. IMPLEMENT_CLIENTCLASS_DT( C_AlyxEmpEffect, DT_AlyxEmpEffect, CAlyxEmpEffect )
  33. RecvPropInt( RECVINFO(m_nState) ),
  34. RecvPropFloat( RECVINFO(m_flDuration) ),
  35. RecvPropFloat( RECVINFO(m_flStartTime) ),
  36. END_RECV_TABLE()
  37. //-----------------------------------------------------------------------------
  38. // Purpose:
  39. // Output : RenderGroup_t
  40. //-----------------------------------------------------------------------------
  41. RenderGroup_t C_AlyxEmpEffect::GetRenderGroup( void )
  42. {
  43. return RENDER_GROUP_TRANSLUCENT_ENTITY;
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. // Input : updateType -
  48. //-----------------------------------------------------------------------------
  49. void C_AlyxEmpEffect::OnDataChanged( DataUpdateType_t updateType )
  50. {
  51. BaseClass::OnDataChanged( updateType );
  52. if ( updateType == DATA_UPDATE_CREATED )
  53. {
  54. m_tParticleSpawn.Init( 32 );
  55. SetNextClientThink( CLIENT_THINK_ALWAYS );
  56. SetupEmitters();
  57. }
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose:
  61. //-----------------------------------------------------------------------------
  62. bool C_AlyxEmpEffect::SetupEmitters( void )
  63. {
  64. // Setup the basic core emitter
  65. if ( m_pSimpleEmitter.IsValid() == false )
  66. {
  67. m_pSimpleEmitter = CSimpleEmitter::Create( "energycore" );
  68. if ( m_pSimpleEmitter.IsValid() == false )
  69. return false;
  70. }
  71. // Setup the attractor emitter
  72. if ( m_pAttractorEmitter.IsValid() == false )
  73. {
  74. m_pAttractorEmitter = CParticleAttractor::Create( GetAbsOrigin(), "energyattractor" );
  75. if ( m_pAttractorEmitter.IsValid() == false )
  76. return false;
  77. }
  78. return true;
  79. }
  80. #define EMP_SCALE 0.5f
  81. #define EMP_PARTICLES "effects/ar2_altfire1b"
  82. //-----------------------------------------------------------------------------
  83. // Purpose:
  84. // Input : percentage -
  85. //-----------------------------------------------------------------------------
  86. void C_AlyxEmpEffect::UpdateIdle( float percentage )
  87. {
  88. #if 0
  89. // Must be active
  90. if ( percentage >= 1.0f )
  91. return;
  92. // Emitters must be valid
  93. if ( SetupEmitters() == false )
  94. return;
  95. // Reset our sort origin
  96. m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
  97. SimpleParticle *sParticle;
  98. // Do the charging particles
  99. m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
  100. Vector forward, right, up;
  101. AngleVectors( GetAbsAngles(), &forward, &right, &up );
  102. Vector offset;
  103. float dist;
  104. int numParticles = floor( 4.0f * percentage );
  105. float dTime = gpGlobals->frametime;
  106. while ( m_tParticleSpawn.NextEvent( dTime ) )
  107. {
  108. for ( int i = 0; i < numParticles; i++ )
  109. {
  110. dist = random->RandomFloat( 4.0f * EMP_SCALE * percentage, 64.0f * EMP_SCALE * percentage );
  111. offset = forward * dist;
  112. dist = RemapValClamped( dist, 4.0f * EMP_SCALE * percentage, 64.0f * EMP_SCALE * percentage, 6.0f, 1.0f );
  113. offset += right * random->RandomFloat( -4.0f * EMP_SCALE * dist, 4.0f * EMP_SCALE * dist );
  114. offset += up * random->RandomFloat( -4.0f * EMP_SCALE * dist, 4.0f * EMP_SCALE * dist );
  115. offset += GetAbsOrigin();
  116. sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( EMP_PARTICLES ), offset );
  117. if ( sParticle == NULL )
  118. return;
  119. sParticle->m_vecVelocity = Vector(0,0,8);
  120. sParticle->m_flDieTime = 0.5f;
  121. sParticle->m_flLifetime = 0.0f;
  122. sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
  123. sParticle->m_flRollDelta = 0.0f;
  124. float alpha = 255 * percentage;
  125. sParticle->m_uchColor[0] = alpha;
  126. sParticle->m_uchColor[1] = alpha;
  127. sParticle->m_uchColor[2] = alpha;
  128. sParticle->m_uchStartAlpha = alpha;
  129. sParticle->m_uchEndAlpha = 0;
  130. sParticle->m_uchStartSize = random->RandomFloat( 1, 2 );
  131. sParticle->m_uchEndSize = 0;
  132. }
  133. }
  134. #endif
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose:
  138. // Input : percentage -
  139. //-----------------------------------------------------------------------------
  140. void C_AlyxEmpEffect::UpdateCharging( float percentage )
  141. {
  142. // Emitters must be valid
  143. if ( SetupEmitters() == false )
  144. return;
  145. if ( percentage <= 0.0f )
  146. return;
  147. // Reset our sort origin
  148. m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
  149. float flScale = 4.0f * EMP_SCALE * percentage;
  150. SimpleParticle *sParticle;
  151. float dTime = gpGlobals->frametime;
  152. while ( m_tParticleSpawn.NextEvent( dTime ) )
  153. {
  154. // Do the core effects
  155. sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
  156. if ( sParticle == NULL )
  157. return;
  158. sParticle->m_vecVelocity = vec3_origin;
  159. sParticle->m_flDieTime = 0.1f;
  160. sParticle->m_flLifetime = 0.0f;
  161. sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
  162. sParticle->m_flRollDelta = 0.0f;
  163. float alpha = 255 * percentage;
  164. sParticle->m_uchColor[0] = alpha;
  165. sParticle->m_uchColor[1] = alpha;
  166. sParticle->m_uchColor[2] = alpha;
  167. sParticle->m_uchStartAlpha = alpha;
  168. sParticle->m_uchEndAlpha = 0;
  169. sParticle->m_uchStartSize = flScale;
  170. sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
  171. }
  172. #if 0
  173. // Do the charging particles
  174. m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
  175. Vector forward, right, up;
  176. AngleVectors( GetAbsAngles(), &forward, &right, &up );
  177. Vector offset;
  178. float dist;
  179. int numParticles = floor( 4.0f * percentage );
  180. for ( i = 0; i < numParticles; i++ )
  181. {
  182. dist = random->RandomFloat( 4.0f * percentage, 64.0f * percentage );
  183. offset = forward * dist;
  184. dist = RemapValClamped( dist, 4.0f * percentage, 64.0f * percentage, 6.0f, 1.0f );
  185. offset += right * random->RandomFloat( -4.0f * dist, 4.0f * dist );
  186. offset += up * random->RandomFloat( -4.0f * dist, 4.0f * dist );
  187. offset += GetAbsOrigin();
  188. sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( EMP_PARTICLES ), offset );
  189. if ( sParticle == NULL )
  190. return;
  191. sParticle->m_vecVelocity = Vector(0,0,8);
  192. sParticle->m_flDieTime = 0.5f;
  193. sParticle->m_flLifetime = 0.0f;
  194. sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
  195. sParticle->m_flRollDelta = 0.0f;
  196. float alpha = 255 * percentage;
  197. sParticle->m_uchColor[0] = alpha;
  198. sParticle->m_uchColor[1] = alpha;
  199. sParticle->m_uchColor[2] = alpha;
  200. sParticle->m_uchStartAlpha = alpha;
  201. sParticle->m_uchEndAlpha = 0;
  202. sParticle->m_uchStartSize = random->RandomFloat( 1, 2 );
  203. sParticle->m_uchEndSize = 0;
  204. }
  205. #endif
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Purpose:
  209. // Input : percentage -
  210. //-----------------------------------------------------------------------------
  211. void C_AlyxEmpEffect::UpdateDischarging( void )
  212. {
  213. // Emitters must be valid
  214. if ( SetupEmitters() == false )
  215. return;
  216. // Reset our sort origin
  217. m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
  218. float flScale = EMP_SCALE * 8.0f;
  219. Vector forward, right, up;
  220. AngleVectors( GetAbsAngles(), &forward, &right, &up );
  221. SimpleParticle *sParticle;
  222. float dTime = gpGlobals->frametime;
  223. while ( m_tParticleSpawn.NextEvent( dTime ) )
  224. {
  225. // Base of the core effect
  226. sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
  227. if ( sParticle == NULL )
  228. return;
  229. sParticle->m_vecVelocity = vec3_origin;
  230. sParticle->m_flDieTime = 0.25f;
  231. sParticle->m_flLifetime = 0.0f;
  232. sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
  233. sParticle->m_flRollDelta = 0.0f;
  234. float alpha = 64;
  235. sParticle->m_uchColor[0] = alpha;
  236. sParticle->m_uchColor[1] = alpha;
  237. sParticle->m_uchColor[2] = alpha;
  238. sParticle->m_uchStartAlpha = alpha;
  239. sParticle->m_uchEndAlpha = 0;
  240. sParticle->m_uchStartSize = flScale * 4.0f;
  241. sParticle->m_uchEndSize = 0.0f;
  242. // Base of the core effect
  243. sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
  244. if ( sParticle == NULL )
  245. return;
  246. sParticle->m_vecVelocity = vec3_origin;
  247. sParticle->m_flDieTime = 0.1f;
  248. sParticle->m_flLifetime = 0.0f;
  249. sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
  250. sParticle->m_flRollDelta = 0.0f;
  251. alpha = 128;
  252. sParticle->m_uchColor[0] = alpha;
  253. sParticle->m_uchColor[1] = alpha;
  254. sParticle->m_uchColor[2] = alpha;
  255. sParticle->m_uchStartAlpha = alpha;
  256. sParticle->m_uchEndAlpha = 0;
  257. sParticle->m_uchStartSize = 0.0f;
  258. sParticle->m_uchEndSize = flScale * 2.0f;
  259. // Make sure we encompass the complete particle here!
  260. m_pSimpleEmitter->SetParticleCullRadius( sParticle->m_uchEndSize );
  261. // Do the core effects
  262. sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
  263. if ( sParticle == NULL )
  264. return;
  265. sParticle->m_vecVelocity = RandomVector( -32.0f, 32.0f );
  266. sParticle->m_flDieTime = 0.2f;
  267. sParticle->m_flLifetime = 0.0f;
  268. sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
  269. sParticle->m_flRollDelta = 0.0f;
  270. alpha = 255;
  271. sParticle->m_uchColor[0] = alpha;
  272. sParticle->m_uchColor[1] = alpha;
  273. sParticle->m_uchColor[2] = alpha;
  274. sParticle->m_uchStartAlpha = alpha;
  275. sParticle->m_uchEndAlpha = 0;
  276. sParticle->m_uchStartSize = flScale;
  277. sParticle->m_uchEndSize = 0.0f;
  278. }
  279. #if 0
  280. // Do the charging particles
  281. m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
  282. Vector offset;
  283. float dist;
  284. for ( i = 0; i < 4; i++ )
  285. {
  286. dist = random->RandomFloat( 4.0f, 64.0f );
  287. offset = forward * dist;
  288. dist = RemapValClamped( dist, 4.0f, 64.0f, 6.0f, 1.0f );
  289. offset += right * random->RandomFloat( -2.0f * dist, 2.0f * dist );
  290. offset += up * random->RandomFloat( -2.0f * dist, 2.0f * dist );
  291. offset += GetAbsOrigin();
  292. sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/combinemuzzle2_dark" ), offset );
  293. if ( sParticle == NULL )
  294. return;
  295. sParticle->m_vecVelocity = Vector(0,0,2);
  296. sParticle->m_flDieTime = 0.5f;
  297. sParticle->m_flLifetime = 0.0f;
  298. sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
  299. sParticle->m_flRollDelta = 0.0f;
  300. float alpha = 255;
  301. sParticle->m_uchColor[0] = alpha;
  302. sParticle->m_uchColor[1] = alpha;
  303. sParticle->m_uchColor[2] = alpha;
  304. sParticle->m_uchStartAlpha = alpha;
  305. sParticle->m_uchEndAlpha = 0;
  306. sParticle->m_uchStartSize = 1;
  307. sParticle->m_uchEndSize = 0;
  308. }
  309. #endif
  310. }
  311. //-----------------------------------------------------------------------------
  312. // Purpose:
  313. // Output : inline float
  314. //-----------------------------------------------------------------------------
  315. inline float C_AlyxEmpEffect::GetStateDurationPercentage( void )
  316. {
  317. if ( m_flDuration == 0 )
  318. return 0.0f;
  319. return RemapValClamped( ( gpGlobals->curtime - m_flStartTime ), 0, m_flDuration, 0, 1.0f );;
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Purpose:
  323. //-----------------------------------------------------------------------------
  324. void C_AlyxEmpEffect::NotifyShouldTransmit( ShouldTransmitState_t state )
  325. {
  326. BaseClass::NotifyShouldTransmit( state );
  327. // Turn off
  328. if ( state == SHOULDTRANSMIT_END )
  329. {
  330. SetNextClientThink( CLIENT_THINK_NEVER );
  331. }
  332. // Turn on
  333. if ( state == SHOULDTRANSMIT_START )
  334. {
  335. SetNextClientThink( CLIENT_THINK_ALWAYS );
  336. }
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Purpose:
  340. //-----------------------------------------------------------------------------
  341. void C_AlyxEmpEffect::ClientThink( void )
  342. {
  343. if ( gpGlobals->frametime <= 0.0f )
  344. return;
  345. float flDuration = GetStateDurationPercentage();
  346. switch( m_nState )
  347. {
  348. case ENERGYCORE_STATE_OFF:
  349. UpdateIdle( 1.0f - flDuration );
  350. break;
  351. case ENERGYCORE_STATE_CHARGING:
  352. UpdateCharging( flDuration );
  353. break;
  354. case ENERGYCORE_STATE_DISCHARGING:
  355. UpdateDischarging( );
  356. break;
  357. }
  358. }