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.

414 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Flare effects
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "clienteffectprecachesystem.h"
  9. #include "particles_simple.h"
  10. #include "iefx.h"
  11. #include "dlight.h"
  12. #include "view.h"
  13. #include "fx.h"
  14. #include "clientsideeffects.h"
  15. #include "c_pixel_visibility.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. //Precahce the effects
  19. CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectFlares )
  20. CLIENTEFFECT_MATERIAL( "effects/redflare" )
  21. CLIENTEFFECT_MATERIAL( "effects/yellowflare" )
  22. CLIENTEFFECT_MATERIAL( "effects/yellowflare_noz" )
  23. CLIENTEFFECT_REGISTER_END()
  24. class C_Flare : public C_BaseCombatCharacter, CSimpleEmitter
  25. {
  26. public:
  27. DECLARE_CLASS( C_Flare, C_BaseCombatCharacter );
  28. DECLARE_CLIENTCLASS();
  29. C_Flare();
  30. void OnDataChanged( DataUpdateType_t updateType );
  31. void Update( float timeDelta );
  32. void NotifyDestroyParticle( Particle* pParticle );
  33. void NotifyShouldTransmit( ShouldTransmitState_t state );
  34. void RestoreResources( void );
  35. float m_flTimeBurnOut;
  36. float m_flScale;
  37. bool m_bLight;
  38. bool m_bSmoke;
  39. bool m_bPropFlare;
  40. pixelvis_handle_t m_queryHandle;
  41. private:
  42. C_Flare( const C_Flare & );
  43. TimedEvent m_teSmokeSpawn;
  44. int m_iAttachment;
  45. SimpleParticle *m_pParticle[2];
  46. };
  47. IMPLEMENT_CLIENTCLASS_DT( C_Flare, DT_Flare, CFlare )
  48. RecvPropFloat( RECVINFO( m_flTimeBurnOut ) ),
  49. RecvPropFloat( RECVINFO( m_flScale ) ),
  50. RecvPropInt( RECVINFO( m_bLight ) ),
  51. RecvPropInt( RECVINFO( m_bSmoke ) ),
  52. RecvPropInt( RECVINFO( m_bPropFlare ) ),
  53. END_RECV_TABLE()
  54. //-----------------------------------------------------------------------------
  55. // Constructor
  56. //-----------------------------------------------------------------------------
  57. C_Flare::C_Flare() : CSimpleEmitter( "C_Flare" )
  58. {
  59. m_pParticle[0] = NULL;
  60. m_pParticle[1] = NULL;
  61. m_flTimeBurnOut = 0.0f;
  62. m_bLight = true;
  63. m_bSmoke = true;
  64. m_bPropFlare = false;
  65. SetDynamicallyAllocated( false );
  66. m_queryHandle = 0;
  67. m_iAttachment = -1;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Purpose:
  71. // Input : state -
  72. //-----------------------------------------------------------------------------
  73. void C_Flare::NotifyShouldTransmit( ShouldTransmitState_t state )
  74. {
  75. if ( state == SHOULDTRANSMIT_END )
  76. {
  77. AddEffects( EF_NODRAW );
  78. }
  79. else if ( state == SHOULDTRANSMIT_START )
  80. {
  81. RemoveEffects( EF_NODRAW );
  82. }
  83. BaseClass::NotifyShouldTransmit( state );
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Purpose:
  87. // Input : bool -
  88. //-----------------------------------------------------------------------------
  89. void C_Flare::OnDataChanged( DataUpdateType_t updateType )
  90. {
  91. if ( updateType == DATA_UPDATE_CREATED )
  92. {
  93. SetSortOrigin( GetAbsOrigin() );
  94. if ( m_bSmoke )
  95. {
  96. m_teSmokeSpawn.Init( 8 );
  97. }
  98. }
  99. BaseClass::OnDataChanged( updateType );
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose:
  103. //-----------------------------------------------------------------------------
  104. void C_Flare::RestoreResources( void )
  105. {
  106. if ( m_pParticle[0] == NULL )
  107. {
  108. m_pParticle[0] = (SimpleParticle *) AddParticle( sizeof( SimpleParticle ), GetPMaterial( "effects/redflare" ), GetAbsOrigin() );
  109. if ( m_pParticle[0] != NULL )
  110. {
  111. m_pParticle[0]->m_uchColor[0] = m_pParticle[0]->m_uchColor[1] = m_pParticle[0]->m_uchColor[2] = 0;
  112. m_pParticle[0]->m_flRoll = random->RandomInt( 0, 360 );
  113. m_pParticle[0]->m_flRollDelta = random->RandomFloat( 1.0f, 4.0f );
  114. m_pParticle[0]->m_flLifetime = 0.0f;
  115. m_pParticle[0]->m_flDieTime = 10.0f;
  116. }
  117. else
  118. {
  119. Assert(0);
  120. }
  121. }
  122. if ( m_pParticle[1] == NULL )
  123. {
  124. m_pParticle[1] = (SimpleParticle *) AddParticle( sizeof( SimpleParticle ), GetPMaterial( "effects/yellowflare_noz" ), GetAbsOrigin() );
  125. if ( m_pParticle[1] != NULL )
  126. {
  127. m_pParticle[1]->m_uchColor[0] = m_pParticle[1]->m_uchColor[1] = m_pParticle[1]->m_uchColor[2] = 0;
  128. m_pParticle[1]->m_flRoll = random->RandomInt( 0, 360 );
  129. m_pParticle[1]->m_flRollDelta = random->RandomFloat( 1.0f, 4.0f );
  130. m_pParticle[1]->m_flLifetime = 0.0f;
  131. m_pParticle[1]->m_flDieTime = 10.0f;
  132. }
  133. else
  134. {
  135. Assert(0);
  136. }
  137. }
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Purpose:
  141. // Input : pParticle -
  142. //-----------------------------------------------------------------------------
  143. void C_Flare::NotifyDestroyParticle( Particle* pParticle )
  144. {
  145. if ( pParticle == m_pParticle[0] )
  146. {
  147. m_pParticle[0] = NULL;
  148. }
  149. if ( pParticle == m_pParticle[1] )
  150. {
  151. m_pParticle[1] = NULL;
  152. }
  153. CSimpleEmitter::NotifyDestroyParticle( pParticle );
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Purpose:
  157. // Input : timeDelta -
  158. //-----------------------------------------------------------------------------
  159. void C_Flare::Update( float timeDelta )
  160. {
  161. if ( !IsVisible() )
  162. return;
  163. CSimpleEmitter::Update( timeDelta );
  164. //Make sure our stored resources are up to date
  165. RestoreResources();
  166. //Don't do this if the console is down
  167. if ( timeDelta <= 0.0f )
  168. return;
  169. //Check for LOS
  170. pixelvis_queryparams_t params;
  171. params.Init(GetAbsOrigin());
  172. params.proxySize = 8.0f; // Inches
  173. float visible = PixelVisibility_FractionVisible( params, &m_queryHandle );
  174. float fColor;
  175. #ifdef HL2_CLIENT_DLL
  176. float baseScale = m_flScale;
  177. #else
  178. // NOTE!!! This is bigger by a factor of 1.2 to deal with fixing a bug from HL2. See dlight_t.h
  179. float baseScale = m_flScale * 1.2f;
  180. #endif
  181. //Account for fading out
  182. if ( ( m_flTimeBurnOut != -1.0f ) && ( ( m_flTimeBurnOut - gpGlobals->curtime ) <= 10.0f ) )
  183. {
  184. baseScale *= ( ( m_flTimeBurnOut - gpGlobals->curtime ) / 10.0f );
  185. }
  186. bool bVisible = (baseScale < 0.01f || visible == 0.0f) ? false : true;
  187. //Clamp the scale if vanished
  188. if ( !bVisible )
  189. {
  190. if ( m_pParticle[0] != NULL )
  191. {
  192. m_pParticle[0]->m_flDieTime = gpGlobals->curtime;
  193. m_pParticle[0]->m_uchStartSize = m_pParticle[0]->m_uchEndSize = 0;
  194. m_pParticle[0]->m_uchColor[0] = 0;
  195. m_pParticle[0]->m_uchColor[1] = 0;
  196. m_pParticle[0]->m_uchColor[2] = 0;
  197. }
  198. if ( m_pParticle[1] != NULL )
  199. {
  200. m_pParticle[1]->m_flDieTime = gpGlobals->curtime;
  201. m_pParticle[1]->m_uchStartSize = m_pParticle[1]->m_uchEndSize = 0;
  202. m_pParticle[1]->m_uchColor[0] = 0;
  203. m_pParticle[1]->m_uchColor[1] = 0;
  204. m_pParticle[1]->m_uchColor[2] = 0;
  205. }
  206. }
  207. if ( baseScale < 0.01f )
  208. return;
  209. //
  210. // Dynamic light
  211. //
  212. if ( m_bLight )
  213. {
  214. dlight_t *dl= effects->CL_AllocDlight( index );
  215. if ( m_bPropFlare == false )
  216. {
  217. dl->origin = GetAbsOrigin();
  218. dl->color.r = 255;
  219. dl->die = gpGlobals->curtime + 0.1f;
  220. dl->radius = baseScale * random->RandomFloat( 110.0f, 128.0f );
  221. dl->color.g = dl->color.b = random->RandomInt( 32, 64 );
  222. }
  223. else
  224. {
  225. if ( m_iAttachment == -1 )
  226. {
  227. m_iAttachment = LookupAttachment( "fuse" );
  228. }
  229. if ( m_iAttachment != -1 )
  230. {
  231. Vector effect_origin;
  232. QAngle effect_angles;
  233. GetAttachment( m_iAttachment, effect_origin, effect_angles );
  234. //Raise the light a little bit away from the flare so it lights it up better.
  235. dl->origin = effect_origin + Vector( 0, 0, 4 );
  236. dl->color.r = 255;
  237. dl->die = gpGlobals->curtime + 0.1f;
  238. dl->radius = baseScale * random->RandomFloat( 245.0f, 256.0f );
  239. dl->color.g = dl->color.b = random->RandomInt( 95, 128 );
  240. dlight_t *el= effects->CL_AllocElight( index );
  241. el->origin = effect_origin;
  242. el->color.r = 255;
  243. el->color.g = dl->color.b = random->RandomInt( 95, 128 );
  244. el->radius = baseScale * random->RandomFloat( 260.0f, 290.0f );
  245. el->die = gpGlobals->curtime + 0.1f;
  246. }
  247. }
  248. }
  249. //
  250. // Smoke
  251. //
  252. float dt = timeDelta;
  253. if ( m_bSmoke )
  254. {
  255. while ( m_teSmokeSpawn.NextEvent( dt ) )
  256. {
  257. Vector smokeOrg = GetAbsOrigin();
  258. Vector flareScreenDir = ( smokeOrg - MainViewOrigin() );
  259. VectorNormalize( flareScreenDir );
  260. smokeOrg = smokeOrg + ( flareScreenDir * 2.0f );
  261. smokeOrg[2] += baseScale * 4.0f;
  262. SimpleParticle *sParticle = (SimpleParticle *) AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[1], smokeOrg );
  263. if ( sParticle == NULL )
  264. return;
  265. sParticle->m_flLifetime = 0.0f;
  266. sParticle->m_flDieTime = 1.0f;
  267. sParticle->m_vecVelocity = Vector( random->RandomFloat( -16.0f, 16.0f ), random->RandomFloat( -16.0f, 16.0f ), random->RandomFloat( 8.0f, 16.0f ) + 32.0f );
  268. if ( m_bPropFlare )
  269. {
  270. sParticle->m_uchColor[0] = 255;
  271. sParticle->m_uchColor[1] = 100;
  272. sParticle->m_uchColor[2] = 100;
  273. }
  274. else
  275. {
  276. sParticle->m_uchColor[0] = 255;
  277. sParticle->m_uchColor[1] = 48;
  278. sParticle->m_uchColor[2] = 48;
  279. }
  280. sParticle->m_uchStartAlpha = random->RandomInt( 64, 90 );
  281. sParticle->m_uchEndAlpha = 0;
  282. sParticle->m_uchStartSize = random->RandomInt( 2, 4 );
  283. sParticle->m_uchEndSize = sParticle->m_uchStartSize * 8.0f;
  284. sParticle->m_flRoll = random->RandomInt( 0, 2*M_PI );
  285. sParticle->m_flRollDelta = random->RandomFloat( -(M_PI/6.0f), M_PI/6.0f );
  286. }
  287. }
  288. if ( !bVisible )
  289. return;
  290. //
  291. // Outer glow
  292. //
  293. Vector offset;
  294. //Cause the base of the effect to shake
  295. offset.Random( -0.5f * baseScale, 0.5f * baseScale );
  296. offset += GetAbsOrigin();
  297. if ( m_pParticle[0] != NULL )
  298. {
  299. m_pParticle[0]->m_Pos = offset;
  300. m_pParticle[0]->m_flLifetime = 0.0f;
  301. m_pParticle[0]->m_flDieTime = 2.0f;
  302. m_pParticle[0]->m_vecVelocity.Init();
  303. fColor = random->RandomInt( 100.0f, 128.0f ) * visible;
  304. m_pParticle[0]->m_uchColor[0] = fColor;
  305. m_pParticle[0]->m_uchColor[1] = fColor;
  306. m_pParticle[0]->m_uchColor[2] = fColor;
  307. m_pParticle[0]->m_uchStartAlpha = fColor;
  308. m_pParticle[0]->m_uchEndAlpha = fColor;
  309. m_pParticle[0]->m_uchStartSize = baseScale * (float) random->RandomInt( 32, 48 );
  310. m_pParticle[0]->m_uchEndSize = m_pParticle[0]->m_uchStartSize;
  311. m_pParticle[0]->m_flRollDelta = 0.0f;
  312. if ( random->RandomInt( 0, 4 ) == 3 )
  313. {
  314. m_pParticle[0]->m_flRoll += random->RandomInt( 2, 8 );
  315. }
  316. }
  317. //
  318. // Inner core
  319. //
  320. //Cause the base of the effect to shake
  321. offset.Random( -1.0f * baseScale, 1.0f * baseScale );
  322. offset += GetAbsOrigin();
  323. if ( m_pParticle[1] != NULL )
  324. {
  325. m_pParticle[1]->m_Pos = offset;
  326. m_pParticle[1]->m_flLifetime = 0.0f;
  327. m_pParticle[1]->m_flDieTime = 2.0f;
  328. m_pParticle[1]->m_vecVelocity.Init();
  329. fColor = 255 * visible;
  330. m_pParticle[1]->m_uchColor[0] = fColor;
  331. m_pParticle[1]->m_uchColor[1] = fColor;
  332. m_pParticle[1]->m_uchColor[2] = fColor;
  333. m_pParticle[1]->m_uchStartAlpha = fColor;
  334. m_pParticle[1]->m_uchEndAlpha = fColor;
  335. m_pParticle[1]->m_uchStartSize = baseScale * (float) random->RandomInt( 2, 4 );
  336. m_pParticle[1]->m_uchEndSize = m_pParticle[0]->m_uchStartSize;
  337. m_pParticle[1]->m_flRoll = random->RandomInt( 0, 360 );
  338. }
  339. }