Counter Strike : Global Offensive Source Code
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.

1191 lines
38 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "fx.h"
  8. #include "fx_sparks.h"
  9. #include "precache_register.h"
  10. #include "particle_simple3d.h"
  11. #include "decals.h"
  12. #include "engine/IEngineSound.h"
  13. #include "c_te_particlesystem.h"
  14. #include "engine/ivmodelinfo.h"
  15. #include "particles_ez.h"
  16. #include "c_impact_effects.h"
  17. #include "engine/IStaticPropMgr.h"
  18. #include "tier0/vprof.h"
  19. #include "c_te_effect_dispatch.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. //Precahce the effects
  23. PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheEffectImpacts )
  24. PRECACHE( MATERIAL, "effects/fleck_cement1" )
  25. PRECACHE( MATERIAL, "effects/fleck_cement2" )
  26. PRECACHE( MATERIAL, "effects/fleck_antlion1" )
  27. PRECACHE( MATERIAL, "effects/fleck_antlion2" )
  28. PRECACHE( MATERIAL, "effects/fleck_wood1" )
  29. PRECACHE( MATERIAL, "effects/fleck_wood2" )
  30. PRECACHE( MATERIAL, "effects/blood" )
  31. PRECACHE( MATERIAL, "effects/blood2" )
  32. PRECACHE( MATERIAL, "sprites/bloodspray" )
  33. PRECACHE( MATERIAL, "particle/particle_noisesphere" )
  34. PRECACHE_REGISTER_END()
  35. // Cached handles to commonly used materials
  36. PMaterialHandle g_Mat_Fleck_Wood[2] = { NULL, NULL };
  37. PMaterialHandle g_Mat_Fleck_Cement[2] = { NULL, NULL };
  38. PMaterialHandle g_Mat_Fleck_Antlion[2] = { NULL, NULL };
  39. PMaterialHandle g_Mat_Fleck_Glass[2] = { NULL, NULL };
  40. PMaterialHandle g_Mat_Fleck_Tile[2] = { NULL, NULL };
  41. PMaterialHandle g_Mat_DustPuff[2] = { NULL, NULL };
  42. PMaterialHandle g_Mat_BloodPuff[2] = { NULL, NULL };
  43. PMaterialHandle g_Mat_SMG_Muzzleflash[4] = { NULL, NULL, NULL, NULL };
  44. PMaterialHandle g_Mat_Combine_Muzzleflash[3] = { NULL, NULL, NULL };
  45. static ConVar fx_drawimpactdebris( "fx_drawimpactdebris", "1", FCVAR_DEVELOPMENTONLY, "Draw impact debris effects." );
  46. static ConVar fx_drawimpactdust( "fx_drawimpactdust", "1", FCVAR_DEVELOPMENTONLY, "Draw impact dust effects." );
  47. PRECACHE_REGISTER_BEGIN( GLOBAL, FX_CacheMaterialHandles )
  48. #ifndef DOTA_DLL
  49. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_wood1", g_Mat_Fleck_Wood[0] )
  50. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_wood2", g_Mat_Fleck_Wood[1] )
  51. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_cement1", g_Mat_Fleck_Cement[0])
  52. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_cement2", g_Mat_Fleck_Cement[1] )
  53. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_antlion1", g_Mat_Fleck_Antlion[0] )
  54. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_antlion2", g_Mat_Fleck_Antlion[1] )
  55. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_glass1", g_Mat_Fleck_Glass[0] )
  56. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_glass2", g_Mat_Fleck_Glass[1] )
  57. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_tile1", g_Mat_Fleck_Tile[0] )
  58. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/fleck_tile2", g_Mat_Fleck_Tile[1] )
  59. PRECACHE_INDEX( PARTICLE_MATERIAL, "particle/particle_smokegrenade", g_Mat_DustPuff[0] )
  60. PRECACHE_INDEX( PARTICLE_MATERIAL, "particle/particle_noisesphere", g_Mat_DustPuff[1] )
  61. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/blood", g_Mat_BloodPuff[0] )
  62. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/blood2", g_Mat_BloodPuff[1] )
  63. #ifndef TF_CLIENT_DLL
  64. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/muzzleflash1", g_Mat_SMG_Muzzleflash[0] )
  65. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/muzzleflash2", g_Mat_SMG_Muzzleflash[1] )
  66. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/muzzleflash3", g_Mat_SMG_Muzzleflash[2] )
  67. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/muzzleflash4", g_Mat_SMG_Muzzleflash[3] )
  68. #if !defined( CSTRIKE_DLL )
  69. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/combinemuzzle1", g_Mat_Combine_Muzzleflash[0] )
  70. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/combinemuzzle2", g_Mat_Combine_Muzzleflash[1] )
  71. PRECACHE_INDEX( PARTICLE_MATERIAL, "effects/strider_muzzle", g_Mat_Combine_Muzzleflash[2] )
  72. #endif
  73. #endif
  74. #endif
  75. PRECACHE_REGISTER_END()
  76. extern PMaterialHandle g_Material_Spark;
  77. //-----------------------------------------------------------------------------
  78. // Purpose: Returns the color given trace information
  79. // Input : *trace - trace to get results for
  80. // *color - return color, gamma corrected (0.0f to 1.0f)
  81. //-----------------------------------------------------------------------------
  82. void GetColorForSurface( trace_t *trace, Vector *color )
  83. {
  84. Vector baseColor, diffuseColor;
  85. Vector end = trace->startpos + ( ( Vector )trace->endpos - ( Vector )trace->startpos ) * 1.1f;
  86. if ( trace->DidHitWorld() )
  87. {
  88. if ( trace->hitbox == 0 )
  89. {
  90. // If we hit the world, then ask the world for the fleck color
  91. engine->TraceLineMaterialAndLighting( trace->startpos, end, diffuseColor, baseColor );
  92. }
  93. else
  94. {
  95. // In this case we hit a static prop.
  96. staticpropmgr->GetStaticPropMaterialColorAndLighting( trace, trace->hitbox - 1, diffuseColor, baseColor );
  97. }
  98. }
  99. else
  100. {
  101. // In this case, we hit an entity. Find out the model associated with it
  102. C_BaseEntity *pEnt = trace->m_pEnt;
  103. if ( !pEnt )
  104. {
  105. Msg("Couldn't find surface in GetColorForSurface()\n");
  106. color->x = 255;
  107. color->y = 255;
  108. color->z = 255;
  109. return;
  110. }
  111. ICollideable *pCollide = pEnt->GetCollideable();
  112. int modelIndex = pCollide->GetCollisionModelIndex();
  113. model_t* pModel = const_cast<model_t*>(modelinfo->GetModel( modelIndex ));
  114. // Ask the model info about what we need to know
  115. modelinfo->GetModelMaterialColorAndLighting( pModel, pCollide->GetCollisionOrigin(),
  116. pCollide->GetCollisionAngles(), trace, diffuseColor, baseColor );
  117. }
  118. //Get final light value
  119. color->x = pow( diffuseColor[0], 1.0f/2.2f ) * baseColor[0];
  120. color->y = pow( diffuseColor[1], 1.0f/2.2f ) * baseColor[1];
  121. color->z = pow( diffuseColor[2], 1.0f/2.2f ) * baseColor[2];
  122. }
  123. //-----------------------------------------------------------------------------
  124. // This does the actual debris flecks
  125. //-----------------------------------------------------------------------------
  126. #define FLECK_MIN_SPEED 64.0f
  127. #define FLECK_MAX_SPEED 128.0f
  128. #define FLECK_GRAVITY 800.0f
  129. #define FLECK_DAMPEN 0.3f
  130. #define FLECK_ANGULAR_SPRAY 0.6f
  131. //
  132. // PC ONLY!
  133. //
  134. static void CreateFleckParticles( const Vector& origin, const Vector &color, trace_t *trace, char materialType, int iScale )
  135. {
  136. Vector spawnOffset = trace->endpos + ( trace->plane.normal * 1.0f );
  137. CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "FX_DebrisFlecks", spawnOffset, Vector(5,5,5) );
  138. if ( !fleckEmitter )
  139. return;
  140. // Handle increased scale
  141. float flMaxSpeed = FLECK_MAX_SPEED * iScale;
  142. float flAngularSpray = MAX( 0.2, FLECK_ANGULAR_SPRAY - ( (float)iScale * 0.2f) ); // More power makes the spray more controlled
  143. // Setup our collision information
  144. fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &trace->plane.normal, flAngularSpray, FLECK_MIN_SPEED, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );
  145. PMaterialHandle *hMaterial;
  146. switch ( materialType )
  147. {
  148. case CHAR_TEX_WOOD:
  149. hMaterial = g_Mat_Fleck_Wood;
  150. break;
  151. case CHAR_TEX_CONCRETE:
  152. case CHAR_TEX_TILE:
  153. default:
  154. hMaterial = g_Mat_Fleck_Cement;
  155. break;
  156. }
  157. Vector dir, end;
  158. float colorRamp;
  159. int numFlecks = random->RandomInt( 4, 16 ) * iScale;
  160. FleckParticle *pFleckParticle;
  161. //Dump out flecks
  162. int i;
  163. for ( i = 0; i < numFlecks; i++ )
  164. {
  165. pFleckParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), hMaterial[random->RandomInt(0,1)], spawnOffset );
  166. if ( pFleckParticle == NULL )
  167. break;
  168. pFleckParticle->m_flLifetime = 0.0f;
  169. pFleckParticle->m_flDieTime = 3.0f;
  170. dir[0] = trace->plane.normal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  171. dir[1] = trace->plane.normal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  172. dir[2] = trace->plane.normal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  173. pFleckParticle->m_uchSize = random->RandomInt( 1, 2 );
  174. pFleckParticle->m_vecVelocity = dir * ( random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed) * ( 3 - pFleckParticle->m_uchSize ) );
  175. pFleckParticle->m_flRoll = random->RandomFloat( 0, 360 );
  176. pFleckParticle->m_flRollDelta = random->RandomFloat( 0, 360 );
  177. colorRamp = random->RandomFloat( 0.75f, 1.25f );
  178. pFleckParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  179. pFleckParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  180. pFleckParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  181. }
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Purpose: Debris flecks caused by impacts
  185. // Input : origin - start
  186. // *trace - trace information
  187. // *materialName - material hit
  188. // materialType - type of material hit
  189. //-----------------------------------------------------------------------------
  190. void FX_DebrisFlecks( const Vector& origin, trace_t *tr, char materialType, int iScale, bool bNoFlecks )
  191. {
  192. VPROF_BUDGET( "FX_DebrisFlecks", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  193. if ( !fx_drawimpactdebris.GetBool() )
  194. return;
  195. Vector color;
  196. GetColorForSurface( tr, &color );
  197. if ( !bNoFlecks )
  198. {
  199. CreateFleckParticles( origin, color, tr, materialType, iScale );
  200. }
  201. //
  202. // Dust trail
  203. //
  204. Vector offset = tr->endpos + ( tr->plane.normal * 2.0f );
  205. SimpleParticle newParticle;
  206. int i;
  207. for ( i = 0; i < 2; i++ )
  208. {
  209. newParticle.m_Pos = offset;
  210. newParticle.m_flLifetime = 0.0f;
  211. newParticle.m_flDieTime = 1.0f;
  212. Vector dir;
  213. dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
  214. dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
  215. dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );
  216. newParticle.m_uchStartSize = random->RandomInt( 2, 4 ) * iScale;
  217. newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8 * iScale;
  218. newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f )*(i+1);
  219. newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 32.0f )*(i+1);
  220. newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 );
  221. newParticle.m_uchEndAlpha = 0;
  222. newParticle.m_flRoll = random->RandomFloat( 0, 360 );
  223. newParticle.m_flRollDelta = random->RandomFloat( -1, 1 );
  224. float colorRamp = random->RandomFloat( 0.5f, 1.25f );
  225. newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  226. newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  227. newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  228. AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
  229. }
  230. for ( i = 0; i < 4; i++ )
  231. {
  232. newParticle.m_Pos = offset;
  233. newParticle.m_flLifetime = 0.0f;
  234. newParticle.m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
  235. Vector dir;
  236. dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
  237. dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
  238. dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );
  239. newParticle.m_uchStartSize = random->RandomInt( 1, 4 );
  240. newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4;
  241. newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 32.0f );
  242. newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 64.0f );
  243. newParticle.m_uchStartAlpha = 255;
  244. newParticle.m_uchEndAlpha = 0;
  245. newParticle.m_flRoll = random->RandomFloat( 0, 360 );
  246. newParticle.m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
  247. float colorRamp = random->RandomFloat( 0.5f, 1.25f );
  248. newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  249. newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  250. newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  251. AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
  252. }
  253. //
  254. // Bullet hole capper
  255. //
  256. newParticle.m_Pos = offset;
  257. newParticle.m_flLifetime = 0.0f;
  258. newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f );
  259. Vector dir;
  260. dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
  261. dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
  262. dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );
  263. newParticle.m_uchStartSize = random->RandomInt( 4, 8 );
  264. newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f;
  265. newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f );
  266. newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );
  267. newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 );
  268. newParticle.m_uchEndAlpha = 0;
  269. newParticle.m_flRoll = random->RandomFloat( 0, 360 );
  270. newParticle.m_flRollDelta = random->RandomFloat( -2, 2 );
  271. float colorRamp = random->RandomFloat( 0.5f, 1.25f );
  272. newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  273. newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  274. newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  275. AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
  276. }
  277. #define GLASS_SHARD_MIN_LIFE 2.5f
  278. #define GLASS_SHARD_MAX_LIFE 5.0f
  279. #define GLASS_SHARD_NOISE 0.8
  280. #define GLASS_SHARD_GRAVITY 800
  281. #define GLASS_SHARD_DAMPING 0.3
  282. #define GLASS_SHARD_MIN_SPEED 1
  283. #define GLASS_SHARD_MAX_SPEED 300
  284. //-----------------------------------------------------------------------------
  285. // Purpose:
  286. //-----------------------------------------------------------------------------
  287. void GlassImpactCallback( const CEffectData &data )
  288. {
  289. VPROF_BUDGET( "GlassImpactCallback", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  290. Vector pos = data.m_vOrigin;
  291. Vector normal = data.m_vNormal;
  292. CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "FX_GlassImpact" );
  293. pGlassEmitter->SetSortOrigin( pos );
  294. Vector vecColor;
  295. engine->ComputeLighting( pos, NULL, true, vecColor );
  296. // HACK: Blend a little toward white to match the materials...
  297. VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor );
  298. float flShardSize = random->RandomFloat( 2.0f, 6.0f );
  299. unsigned char color[3] = { 200, 200, 210 };
  300. // ---------------------
  301. // Create glass shards
  302. // ----------------------
  303. int numShards = random->RandomInt( 2, 4 );
  304. for ( int i = 0; i < numShards; i++ )
  305. {
  306. Particle3D *pParticle;
  307. pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Glass[random->RandomInt(0,1)], pos );
  308. if ( pParticle )
  309. {
  310. pParticle->m_flLifeRemaining = random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE);
  311. pParticle->m_vecVelocity[0] = ( normal[0] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
  312. pParticle->m_vecVelocity[1] = ( normal[1] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
  313. pParticle->m_vecVelocity[2] = ( normal[2] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
  314. pParticle->m_uchSize = flShardSize + random->RandomFloat(-0.5*flShardSize,0.5*flShardSize);
  315. pParticle->m_vAngles = RandomAngle( 0, 360 );
  316. pParticle->m_flAngSpeed = random->RandomFloat(-800,800);
  317. pParticle->m_uchFrontColor[0] = (byte)(color[0] * vecColor.x);
  318. pParticle->m_uchFrontColor[1] = (byte)(color[1] * vecColor.y);
  319. pParticle->m_uchFrontColor[2] = (byte)(color[2] * vecColor.z);
  320. pParticle->m_uchBackColor[0] = (byte)(color[0] * vecColor.x);
  321. pParticle->m_uchBackColor[1] = (byte)(color[1] * vecColor.y);
  322. pParticle->m_uchBackColor[2] = (byte)(color[2] * vecColor.z);
  323. }
  324. }
  325. pGlassEmitter->m_ParticleCollision.Setup( pos, &normal, GLASS_SHARD_NOISE, GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING );
  326. color[0] = 64;
  327. color[1] = 64;
  328. color[2] = 92;
  329. // ---------------------------
  330. // Dust
  331. // ---------------------------
  332. Vector dir;
  333. Vector offset = pos + ( normal * 2.0f );
  334. float colorRamp;
  335. SimpleParticle newParticle;
  336. for ( int i = 0; i < 4; i++ )
  337. {
  338. newParticle.m_Pos = offset;
  339. newParticle.m_flLifetime= 0.0f;
  340. newParticle.m_flDieTime = random->RandomFloat( 0.1f, 0.25f );
  341. dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
  342. dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
  343. dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );
  344. newParticle.m_uchStartSize = random->RandomInt( 1, 4 );
  345. newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8;
  346. newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 16.0f )*(i+1);
  347. newParticle.m_vecVelocity[2] -= random->RandomFloat( 16.0f, 32.0f )*(i+1);
  348. newParticle.m_uchStartAlpha = random->RandomInt( 128, 255 );
  349. newParticle.m_uchEndAlpha = 0;
  350. newParticle.m_flRoll = random->RandomFloat( 0, 360 );
  351. newParticle.m_flRollDelta = random->RandomFloat( -1, 1 );
  352. colorRamp = random->RandomFloat( 0.5f, 1.25f );
  353. newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  354. newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  355. newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  356. AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
  357. }
  358. //
  359. // Bullet hole capper
  360. //
  361. newParticle.m_Pos = offset;
  362. newParticle.m_flLifetime = 0.0f;
  363. newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f );
  364. dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
  365. dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
  366. dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );
  367. newParticle.m_uchStartSize = random->RandomInt( 4, 8 );
  368. newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f;
  369. newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 8.0f );
  370. newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );
  371. newParticle.m_uchStartAlpha = random->RandomInt( 32, 64 );
  372. newParticle.m_uchEndAlpha = 0;
  373. newParticle.m_flRoll = random->RandomFloat( 0, 360 );
  374. newParticle.m_flRollDelta = random->RandomFloat( -2, 2 );
  375. colorRamp = random->RandomFloat( 0.5f, 1.25f );
  376. newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  377. newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  378. newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  379. AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
  380. }
  381. DECLARE_CLIENT_EFFECT( GlassImpact, GlassImpactCallback )
  382. //-----------------------------------------------------------------------------
  383. // Purpose:
  384. // Input : &pos -
  385. // *tr -
  386. //-----------------------------------------------------------------------------
  387. void FX_AntlionImpact( const Vector &pos, trace_t *trace )
  388. {
  389. #if defined( _GAMECONSOLE )
  390. return;
  391. #endif // _GAMECONSOLE
  392. VPROF_BUDGET( "FX_AntlionImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  393. CSmartPtr<CSimple3DEmitter> fleckEmitter = CSimple3DEmitter::Create( "FX_DebrisFlecks" );
  394. if ( fleckEmitter == NULL )
  395. return;
  396. Vector shotDir = ( trace->startpos - trace->endpos );
  397. VectorNormalize( shotDir );
  398. Vector spawnOffset = trace->endpos + ( shotDir * 2.0f );
  399. Vector vWorldMins, vWorldMaxs;
  400. if ( trace->m_pEnt )
  401. {
  402. float scale = trace->m_pEnt->CollisionProp()->BoundingRadius();
  403. vWorldMins[0] = spawnOffset[0] - scale;
  404. vWorldMins[1] = spawnOffset[1] - scale;
  405. vWorldMins[2] = spawnOffset[2] - scale;
  406. vWorldMaxs[0] = spawnOffset[0] + scale;
  407. vWorldMaxs[1] = spawnOffset[1] + scale;
  408. vWorldMaxs[2] = spawnOffset[2] + scale;
  409. }
  410. else
  411. {
  412. return;
  413. }
  414. fleckEmitter->SetSortOrigin( spawnOffset );
  415. fleckEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );
  416. // Handle increased scale
  417. float flMaxSpeed = 256.0f;
  418. float flAngularSpray = 1.0f;
  419. // Setup our collision information
  420. fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &shotDir, flAngularSpray, 8.0f, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );
  421. Vector dir, end;
  422. Vector color = Vector( 1, 0.9, 0.75 );
  423. float colorRamp;
  424. int numFlecks = random->RandomInt( 8, 16 );
  425. Particle3D *pFleckParticle;
  426. // Dump out flecks
  427. int i;
  428. for ( i = 0; i < numFlecks; i++ )
  429. {
  430. pFleckParticle = (Particle3D *) fleckEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Antlion[random->RandomInt(0,1)], spawnOffset );
  431. if ( pFleckParticle == NULL )
  432. break;
  433. pFleckParticle->m_flLifeRemaining = 3.0f;
  434. dir[0] = shotDir[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  435. dir[1] = shotDir[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  436. dir[2] = shotDir[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  437. pFleckParticle->m_uchSize = random->RandomInt( 1, 6 );
  438. pFleckParticle->m_vecVelocity = dir * random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed);
  439. pFleckParticle->m_vAngles.Random( 0, 360 );
  440. pFleckParticle->m_flAngSpeed = random->RandomFloat(-800,800);
  441. pFleckParticle->m_uchFrontColor[0] = 255;
  442. pFleckParticle->m_uchFrontColor[1] = 255;
  443. pFleckParticle->m_uchFrontColor[2] = 255;
  444. pFleckParticle->m_uchBackColor[0] = 128;
  445. pFleckParticle->m_uchBackColor[1] = 128;
  446. pFleckParticle->m_uchBackColor[2] = 128;
  447. }
  448. //
  449. // Dust trail
  450. //
  451. SimpleParticle *pParticle;
  452. CSmartPtr<CSimpleEmitter> dustEmitter = CSimpleEmitter::Create( "FX_DebrisFlecks" );
  453. if ( !dustEmitter )
  454. return;
  455. Vector offset = trace->endpos + ( shotDir * 4.0f );
  456. dustEmitter->SetSortOrigin( offset );
  457. dustEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );
  458. for ( i = 0; i < 4; i++ )
  459. {
  460. pParticle = (SimpleParticle *) dustEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], offset );
  461. if ( pParticle == NULL )
  462. break;
  463. pParticle->m_flLifetime = 0.0f;
  464. pParticle->m_flDieTime = 1.0f;
  465. dir[0] = shotDir[0] + random->RandomFloat( -0.8f, 0.8f );
  466. dir[1] = shotDir[1] + random->RandomFloat( -0.8f, 0.8f );
  467. dir[2] = shotDir[2] + random->RandomFloat( -0.8f, 0.8f );
  468. pParticle->m_uchStartSize = random->RandomInt( 8, 16 );
  469. pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4.0f;
  470. pParticle->m_vecVelocity = dir * random->RandomFloat( 4.0f, 64.0f );
  471. pParticle->m_uchStartAlpha = random->RandomInt( 32, 64);
  472. pParticle->m_uchEndAlpha = 0;
  473. pParticle->m_flRoll = random->RandomFloat( 0, 2.0f*M_PI );
  474. pParticle->m_flRollDelta = random->RandomFloat( -0.5f, 0.5f );
  475. colorRamp = random->RandomFloat( 0.5f, 1.0f );
  476. pParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  477. pParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  478. pParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  479. }
  480. CLocalPlayerFilter filter;
  481. C_BaseEntity::EmitSound( filter, 0, "FX_AntlionImpact.ShellImpact", &trace->endpos );
  482. }
  483. //-----------------------------------------------------------------------------
  484. // Purpose: Spurt out bug blood
  485. // Input : &pos -
  486. // &dir -
  487. //-----------------------------------------------------------------------------
  488. #define NUM_BUG_BLOOD 32
  489. #define NUM_BUG_BLOOD2 16
  490. #define NUM_BUG_SPLATS 16
  491. void FX_BugBlood( Vector &pos, Vector &dir, Vector &vWorldMins, Vector &vWorldMaxs )
  492. {
  493. VPROF_BUDGET( "FX_BugBlood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  494. CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_BugBlood" );
  495. if ( !pSimple )
  496. return;
  497. pSimple->SetSortOrigin( pos );
  498. pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true );
  499. pSimple->GetBinding().SetBBox( pos-Vector(32,32,32), pos+Vector(32,32,32), true );
  500. Vector vDir;
  501. vDir[0] = dir[0] + random->RandomFloat( -2.0f, 2.0f );
  502. vDir[1] = dir[1] + random->RandomFloat( -2.0f, 2.0f );
  503. vDir[2] = dir[2] + random->RandomFloat( -2.0f, 2.0f );
  504. VectorNormalize( vDir );
  505. int i;
  506. for ( i = 0; i < NUM_BUG_BLOOD; i++ )
  507. {
  508. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );
  509. if ( sParticle == NULL )
  510. return;
  511. sParticle->m_flLifetime = 0.0f;
  512. sParticle->m_flDieTime = 0.25f;
  513. float speed = random->RandomFloat( 32.0f, 150.0f );
  514. sParticle->m_vecVelocity = vDir * -speed;
  515. sParticle->m_vecVelocity[2] -= 32.0f;
  516. sParticle->m_uchColor[0] = 255;
  517. sParticle->m_uchColor[1] = 200;
  518. sParticle->m_uchColor[2] = 32;
  519. sParticle->m_uchStartAlpha = 255;
  520. sParticle->m_uchEndAlpha = 0;
  521. sParticle->m_uchStartSize = random->RandomInt( 1, 2 );
  522. sParticle->m_uchEndSize = sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
  523. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  524. sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
  525. }
  526. for ( i = 0; i < NUM_BUG_BLOOD2; i++ )
  527. {
  528. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );
  529. if ( sParticle == NULL )
  530. {
  531. return;
  532. }
  533. sParticle->m_flLifetime = 0.0f;
  534. sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
  535. float speed = random->RandomFloat( 8.0f, 255.0f );
  536. sParticle->m_vecVelocity = vDir * -speed;
  537. sParticle->m_vecVelocity[2] -= 16.0f;
  538. sParticle->m_uchColor[0] = 255;
  539. sParticle->m_uchColor[1] = 200;
  540. sParticle->m_uchColor[2] = 32;
  541. sParticle->m_uchStartAlpha = random->RandomInt( 16, 32 );
  542. sParticle->m_uchEndAlpha = 0;
  543. sParticle->m_uchStartSize = random->RandomInt( 1, 3 );
  544. sParticle->m_uchEndSize = sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
  545. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  546. sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
  547. }
  548. Vector offset;
  549. for ( i = 0; i < NUM_BUG_SPLATS; i++ )
  550. {
  551. offset.Random( -2, 2 );
  552. offset += pos;
  553. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], offset );
  554. if ( sParticle == NULL )
  555. {
  556. return;
  557. }
  558. sParticle->m_flLifetime = 0.0f;
  559. sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
  560. float speed = 75.0f * ((i/(float)NUM_BUG_SPLATS)+1);
  561. sParticle->m_vecVelocity.Random( -16.0f, 16.0f );
  562. sParticle->m_vecVelocity += vDir * -speed;
  563. sParticle->m_vecVelocity[2] -= ( 64.0f * ((i/(float)NUM_BUG_SPLATS)+1) );
  564. sParticle->m_uchColor[0] = 255;
  565. sParticle->m_uchColor[1] = 200;
  566. sParticle->m_uchColor[2] = 32;
  567. sParticle->m_uchStartAlpha = 255;
  568. sParticle->m_uchEndAlpha = 0;
  569. sParticle->m_uchStartSize = random->RandomInt( 1, 2 );
  570. sParticle->m_uchEndSize = sParticle->m_uchStartSize*4;
  571. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  572. sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
  573. }
  574. }
  575. //-----------------------------------------------------------------------------
  576. // Purpose: Blood puff
  577. //-----------------------------------------------------------------------------
  578. void FX_Blood( Vector &pos, Vector &dir, float r, float g, float b, float a )
  579. {
  580. VPROF_BUDGET( "FX_Blood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  581. // Cloud
  582. CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Blood" );
  583. if ( !pSimple )
  584. return;
  585. pSimple->SetSortOrigin( pos );
  586. Vector vDir;
  587. vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
  588. vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
  589. vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );
  590. VectorNormalize( vDir );
  591. int i;
  592. for ( i = 0; i < 2; i++ )
  593. {
  594. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );
  595. if ( sParticle == NULL )
  596. {
  597. return;
  598. }
  599. sParticle->m_flLifetime = 0.0f;
  600. sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
  601. float speed = random->RandomFloat( 2.0f, 8.0f );
  602. sParticle->m_vecVelocity = vDir * (speed*i);
  603. sParticle->m_vecVelocity[2] += random->RandomFloat( -32.0f, -16.0f );
  604. sParticle->m_uchColor[0] = r;
  605. sParticle->m_uchColor[1] = g;
  606. sParticle->m_uchColor[2] = b;
  607. sParticle->m_uchStartAlpha = a;
  608. sParticle->m_uchEndAlpha = 0;
  609. sParticle->m_uchStartSize = 2;
  610. sParticle->m_uchEndSize = sParticle->m_uchStartSize*4;
  611. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  612. sParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
  613. }
  614. for ( i = 0; i < 2; i++ )
  615. {
  616. SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );
  617. if ( sParticle == NULL )
  618. {
  619. return;
  620. }
  621. sParticle->m_flLifetime = 0.0f;
  622. sParticle->m_flDieTime = 0.5f;
  623. float speed = random->RandomFloat( 4.0f, 16.0f );
  624. sParticle->m_vecVelocity = vDir * (speed*i);
  625. sParticle->m_uchColor[0] = r;
  626. sParticle->m_uchColor[1] = g;
  627. sParticle->m_uchColor[2] = b;
  628. sParticle->m_uchStartAlpha = 128;
  629. sParticle->m_uchEndAlpha = 0;
  630. sParticle->m_uchStartSize = 2;
  631. sParticle->m_uchEndSize = sParticle->m_uchStartSize*4;
  632. sParticle->m_flRoll = random->RandomInt( 0, 360 );
  633. sParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f );
  634. }
  635. }
  636. //-----------------------------------------------------------------------------
  637. // Purpose: Dust impact
  638. // Input : &origin - position
  639. // &tr - trace information
  640. //-----------------------------------------------------------------------------
  641. void FX_DustImpact( const Vector &origin, trace_t *tr, int iScale )
  642. {
  643. if ( !fx_drawimpactdust.GetBool() )
  644. return;
  645. FX_DustImpact( origin, tr, (float)iScale );
  646. }
  647. void FX_DustImpact( const Vector &origin, trace_t *tr, float flScale )
  648. {
  649. //
  650. // PC version
  651. //
  652. VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  653. Vector offset;
  654. float spread = 0.2f;
  655. CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
  656. pSimple->SetSortOrigin( origin );
  657. SimpleParticle *pParticle;
  658. Vector color;
  659. float colorRamp;
  660. GetColorForSurface( tr, &color );
  661. int i;
  662. for ( i = 0; i < 4; i++ )
  663. {
  664. pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
  665. if ( pParticle != NULL )
  666. {
  667. pParticle->m_flLifetime = 0.0f;
  668. pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
  669. pParticle->m_vecVelocity.Random( -spread, spread );
  670. pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
  671. VectorNormalize( pParticle->m_vecVelocity );
  672. float fForce = random->RandomFloat( 250, 500 ) * i;
  673. // scaled
  674. pParticle->m_vecVelocity *= fForce * flScale;
  675. colorRamp = random->RandomFloat( 0.75f, 1.25f );
  676. pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
  677. pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
  678. pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
  679. // scaled
  680. pParticle->m_uchStartSize = ( unsigned char )( flScale * random->RandomInt( 3, 4 ) * (i+1) );
  681. // scaled
  682. pParticle->m_uchEndSize = ( unsigned char )( flScale * pParticle->m_uchStartSize * 4 );
  683. pParticle->m_uchStartAlpha = random->RandomInt( 32, 255 );
  684. pParticle->m_uchEndAlpha = 0;
  685. pParticle->m_flRoll = random->RandomInt( 0, 360 );
  686. pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f );
  687. }
  688. }
  689. //Dust specs
  690. for ( i = 0; i < 4; i++ )
  691. {
  692. pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
  693. if ( pParticle != NULL )
  694. {
  695. pParticle->m_flLifetime = 0.0f;
  696. pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.75f );
  697. pParticle->m_vecVelocity.Random( -spread, spread );
  698. pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );
  699. VectorNormalize( pParticle->m_vecVelocity );
  700. float fForce = random->RandomFloat( 250, 500 ) * i;
  701. pParticle->m_vecVelocity *= fForce;
  702. colorRamp = random->RandomFloat( 0.75f, 1.25f );
  703. pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
  704. pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
  705. pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
  706. pParticle->m_uchStartSize = random->RandomInt( 2, 4 ) * (i+1);
  707. pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2;
  708. pParticle->m_uchStartAlpha = 255;
  709. pParticle->m_uchEndAlpha = 0;
  710. pParticle->m_flRoll = random->RandomInt( 0, 360 );
  711. pParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
  712. }
  713. }
  714. //Impact hit
  715. for ( i = 0; i < 4; i++ )
  716. {
  717. pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
  718. if ( pParticle != NULL )
  719. {
  720. offset = origin;
  721. offset[0] += random->RandomFloat( -8.0f, 8.0f );
  722. offset[1] += random->RandomFloat( -8.0f, 8.0f );
  723. pParticle->m_flLifetime = 0.0f;
  724. pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
  725. spread = 1.0f;
  726. pParticle->m_vecVelocity.Random( -spread, spread );
  727. pParticle->m_vecVelocity += tr->plane.normal;
  728. VectorNormalize( pParticle->m_vecVelocity );
  729. float fForce = random->RandomFloat( 0, 50 );
  730. pParticle->m_vecVelocity *= fForce;
  731. colorRamp = random->RandomFloat( 0.75f, 1.25f );
  732. pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
  733. pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
  734. pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
  735. pParticle->m_uchStartSize = random->RandomInt( 1, 4 );
  736. pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4;
  737. pParticle->m_uchStartAlpha = random->RandomInt( 32, 64 );
  738. pParticle->m_uchEndAlpha = 0;
  739. pParticle->m_flRoll = random->RandomInt( 0, 360 );
  740. pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f );
  741. }
  742. }
  743. }
  744. //-----------------------------------------------------------------------------
  745. // Purpose:
  746. // Input : &pos -
  747. // &dir -
  748. // type -
  749. //-----------------------------------------------------------------------------
  750. void FX_GaussExplosion( const Vector &pos, const Vector &dir, int type )
  751. {
  752. Vector vDir;
  753. vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
  754. vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
  755. vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );
  756. VectorNormalize( vDir );
  757. int i;
  758. #if defined(_GAMECONSOLE)
  759. //
  760. // XBox version
  761. //
  762. CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_GaussExplosion" );
  763. if ( pSparkEmitter == NULL )
  764. {
  765. Assert(0);
  766. return;
  767. }
  768. if ( g_Material_Spark == NULL )
  769. {
  770. g_Material_Spark = pSparkEmitter->GetPMaterial( "effects/spark" );
  771. }
  772. pSparkEmitter->SetSortOrigin( pos );
  773. pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
  774. pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
  775. pSparkEmitter->GetBinding().SetBBox( pos - Vector( 32, 32, 32 ), pos + Vector( 32, 32, 32 ) );
  776. int numSparks = random->RandomInt( 8, 16 );
  777. TrailParticle *pParticle;
  778. // Dump out sparks
  779. for ( i = 0; i < numSparks; i++ )
  780. {
  781. pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), g_Material_Spark, pos );
  782. if ( pParticle == NULL )
  783. return;
  784. pParticle->m_flLifetime = 0.0f;
  785. vDir.Random( -0.6f, 0.6f );
  786. vDir += dir;
  787. VectorNormalize( vDir );
  788. pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f );
  789. pParticle->m_flLength = random->RandomFloat( 0.01f, 0.1f );
  790. pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
  791. pParticle->m_vecVelocity = vDir * random->RandomFloat( 128, 512 );
  792. Color32Init( pParticle->m_color, 255, 255, 255, 255 );
  793. }
  794. // End cap
  795. SimpleParticle particle;
  796. particle.m_Pos = pos;
  797. particle.m_flLifetime = 0.0f;
  798. particle.m_flDieTime = 0.1f;
  799. particle.m_vecVelocity.Init();
  800. particle.m_flRoll = random->RandomInt( 0, 360 );
  801. particle.m_flRollDelta = 0.0f;
  802. particle.m_uchColor[0] = 255;
  803. particle.m_uchColor[1] = 255;
  804. particle.m_uchColor[2] = 255;
  805. particle.m_uchStartAlpha = 255;
  806. particle.m_uchEndAlpha = 255;
  807. particle.m_uchStartSize = random->RandomInt( 24, 32 );
  808. particle.m_uchEndSize = 0;
  809. AddSimpleParticle( &particle, ParticleMgr()->GetPMaterial( "effects/yellowflare" ) );
  810. #else
  811. //
  812. // PC version
  813. //
  814. CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_ElectricSpark" );
  815. if ( !pSparkEmitter )
  816. {
  817. Assert(0);
  818. return;
  819. }
  820. PMaterialHandle hMaterial = pSparkEmitter->GetPMaterial( "effects/spark" );
  821. pSparkEmitter->SetSortOrigin( pos );
  822. pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
  823. pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN|bitsPARTICLE_TRAIL_COLLIDE );
  824. //Setup our collision information
  825. pSparkEmitter->m_ParticleCollision.Setup( pos, &vDir, 0.8f, 128, 512, 800, 0.3f );
  826. int numSparks = random->RandomInt( 16, 32 );
  827. TrailParticle *pParticle;
  828. // Dump out sparks
  829. for ( i = 0; i < numSparks; i++ )
  830. {
  831. pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, pos );
  832. if ( pParticle == NULL )
  833. return;
  834. pParticle->m_flLifetime = 0.0f;
  835. vDir.Random( -0.6f, 0.6f );
  836. vDir += dir;
  837. VectorNormalize( vDir );
  838. pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f );
  839. pParticle->m_flLength = random->RandomFloat( 0.01f, 0.1f );
  840. pParticle->m_flDieTime = random->RandomFloat( 0.25f, 1.0f );
  841. pParticle->m_vecVelocity = vDir * random->RandomFloat( 128, 512 );
  842. Color32Init( pParticle->m_color, 255, 255, 255, 255 );
  843. }
  844. FX_ElectricSpark( pos, 1, 1, &vDir );
  845. #endif
  846. }
  847. class C_TEGaussExplosion : public C_TEParticleSystem
  848. {
  849. public:
  850. DECLARE_CLASS( C_TEGaussExplosion, C_TEParticleSystem );
  851. DECLARE_CLIENTCLASS();
  852. C_TEGaussExplosion();
  853. virtual ~C_TEGaussExplosion();
  854. public:
  855. virtual void PostDataUpdate( DataUpdateType_t updateType );
  856. virtual bool ShouldDraw() { return true; }
  857. public:
  858. int m_nType;
  859. Vector m_vecDirection;
  860. };
  861. IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEGaussExplosion, DT_TEGaussExplosion, CTEGaussExplosion )
  862. RecvPropInt(RECVINFO(m_nType)),
  863. RecvPropVector(RECVINFO(m_vecDirection)),
  864. END_RECV_TABLE()
  865. //==================================================
  866. // C_TEGaussExplosion
  867. //==================================================
  868. C_TEGaussExplosion::C_TEGaussExplosion()
  869. {
  870. }
  871. C_TEGaussExplosion::~C_TEGaussExplosion()
  872. {
  873. }
  874. //-----------------------------------------------------------------------------
  875. // Purpose:
  876. // Input : bNewEntity - whether or not to start a new entity
  877. //-----------------------------------------------------------------------------
  878. void C_TEGaussExplosion::PostDataUpdate( DataUpdateType_t updateType )
  879. {
  880. FX_GaussExplosion( m_vecOrigin, m_vecDirection, m_nType );
  881. }
  882. //-----------------------------------------------------------------------------
  883. // Purpose:
  884. // Input : filter -
  885. // delay -
  886. // &pos -
  887. // &dir -
  888. // type -
  889. //-----------------------------------------------------------------------------
  890. void TE_GaussExplosion( IRecipientFilter& filter, float delay, const Vector &pos, const Vector &dir, int type )
  891. {
  892. FX_GaussExplosion( pos, dir, type );
  893. }