//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_ExtinguisherJet::Start( void ) { SetupEntityRenderHandle( RENDER_GROUP_TRANSLUCENT_ENTITY ); m_ParticleSpawn.Init( 100 ); //Events per second //Create the basic emitter m_pEmitter = CSimpleEmitter::Create("C_ExtinguisherJet::m_pEmitter"); Assert( m_pEmitter.IsValid() ); if ( m_pEmitter.IsValid() ) { m_MaterialHandle = m_pEmitter->GetPMaterial( "particle/particle_smokegrenade" ); m_pEmitter->SetSortOrigin( GetAbsOrigin() ); } //Create the "ember" emitter for the smaller flecks m_pEmberEmitter = CEmberEffect::Create( "C_ExtinguisherJet::m_pEmberEmitter" ); Assert( m_pEmberEmitter.IsValid() ); if ( m_pEmberEmitter.IsValid() ) { m_EmberMaterialHandle = m_pEmberEmitter->GetPMaterial( "particle/particle_smokegrenade" ); m_pEmberEmitter->SetSortOrigin( GetAbsOrigin() ); } }
//----------------------------------------------------------------------------- // Purpose: Trail smoke //----------------------------------------------------------------------------- void CASW_Shotgun_Pellet_Predicted::ClientThink( void ) { return; CSmartPtr<CSimpleEmitter> pEmitter = CSimpleEmitter::Create( "CASW_Shotgun_Pellet_Predicted::Effect" ); PMaterialHandle hSphereMaterial = pEmitter->GetPMaterial( "sprites/chargeball" ); // Add particles at the target. float flCur = gpGlobals->frametime; while ( m_ParticleEvent.NextEvent( flCur ) ) { Vector vecOrigin = GetAbsOrigin() + RandomVector( -2,2 ); pEmitter->SetSortOrigin( vecOrigin ); SimpleParticle *pParticle = (SimpleParticle *) pEmitter->AddParticle( sizeof(SimpleParticle), hSphereMaterial, vecOrigin ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.3f ); pParticle->m_uchStartSize = random->RandomFloat(2,4); pParticle->m_uchEndSize = pParticle->m_uchStartSize + 2; pParticle->m_vecVelocity = vec3_origin; pParticle->m_uchStartAlpha = 128; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomFloat( 180, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -1, 1 ); pParticle->m_uchColor[0] = 128; pParticle->m_uchColor[1] = 128; pParticle->m_uchColor[2] = 128; } }
//----------------------------------------------------------------------------- // Purpose: // Input : bnewentity - //----------------------------------------------------------------------------- void C_EntityFlame::OnDataChanged( DataUpdateType_t updateType ) { if ( updateType == DATA_UPDATE_CREATED ) { SetupEntityRenderHandle( RENDER_GROUP_TRANSLUCENT_ENTITY ); C_BaseEntity *pEnt = m_hEntAttached; // FIXME: this should be IsBaseAnimating if (pEnt->IsBaseCombatCharacter()) { AttachToHitBoxes(); } else { m_ParticleSpawn.Init( 60 ); //Events per second m_pEmitter = CEmberEffect::Create("C_EntityFlame::Create"); Assert( m_pEmitter.IsValid() ); if ( m_pEmitter.IsValid() ) { for ( int i = 1; i < NUM_FLAMELETS+1; i++ ) { m_MaterialHandle[i-1] = m_pEmitter->GetPMaterial( VarArgs( "sprites/flamelet%d", i ) ); } m_pEmitter->SetSortOrigin( GetAbsOrigin() ); } } } }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &velocity - // scale - // numParticles - // *pColor - // iAlpha - // *pMaterial - // flRoll - // flRollDelta - //----------------------------------------------------------------------------- CSmartPtr<CSimpleEmitter> FX_Smoke( const Vector &origin, const Vector &velocity, float scale, int numParticles, float flDietime, unsigned char *pColor, int iAlpha, const char *pMaterial, float flRoll, float flRollDelta ) { VPROF_BUDGET( "FX_Smoke", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Smoke" ); pSimple->SetSortOrigin( origin ); SimpleParticle *pParticle; // Smoke for ( int i = 0; i < numParticles; i++ ) { PMaterialHandle hMaterial = pSimple->GetPMaterial( pMaterial ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, origin ); if ( pParticle == NULL ) return NULL; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = flDietime; pParticle->m_vecVelocity = velocity; for( int i = 0; i < 3; ++i ) { pParticle->m_uchColor[i] = pColor[i]; } pParticle->m_uchStartAlpha = iAlpha; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = scale; pParticle->m_uchEndSize = pParticle->m_uchStartSize*2; pParticle->m_flRoll = flRoll; pParticle->m_flRollDelta = flRollDelta; } return pSimple; }
//----------------------------------------------------------------------------- // Purpose: Callback to create a sparkle effect on the client // Input : &data - information about the effect //----------------------------------------------------------------------------- void SparkleCallback( const CEffectData &data ) { // Create a simple particle emitter CSmartPtr<CSimpleEmitter> pSparkleEmitter = CSimpleEmitter::Create( "Sparkle" ); if ( pSparkleEmitter == NULL ) return; // Make local versions of our passed in data Vector origin = data.m_vOrigin; float scale = data.m_flScale; // Set our sort origin to make the system cull properly pSparkleEmitter->SetSortOrigin( origin ); // Find the material handle we wish to use for these particles PMaterialHandle hMaterial = pSparkleEmitter->GetPMaterial( "effects/yellowflare" ); SimpleParticle *pParticle; // Make a group of particles in the world for ( int i = 0; i < 64; i++ ) { // Create a particle pParticle = pSparkleEmitter->AddSimpleParticle( hMaterial, origin ); if ( pParticle == NULL ) return; // Set our sizes pParticle->m_uchStartSize = (unsigned char) scale; pParticle->m_uchEndSize = 0; // Set our roll pParticle->m_flRoll = random->RandomFloat( 0, 2*M_PI ); pParticle->m_flRollDelta = random->RandomFloat( -DEG2RAD( 180 ), DEG2RAD( 180 ) ); // Set our color pParticle->m_uchColor[0] = 255; // Red pParticle->m_uchColor[1] = 255; // Green pParticle->m_uchColor[2] = 255; // Blue // Set our alpha pParticle->m_uchStartAlpha = 0; pParticle->m_uchEndAlpha = 255; // Create a random vector Vector velocity = RandomVector( -1.0f, 1.0f ); VectorNormalize( velocity ); // Find a random speed for the particle float speed = random->RandomFloat( 4.0f, 8.0f ) * scale; // Build and set the velocity of the particle pParticle->m_vecVelocity = velocity * speed; // Declare our lifetime pParticle->m_flDieTime = 1.0f; } }
void FX_MetalScrape(Vector &position, Vector &normal) { VPROF_BUDGET("FX_MetalScrape", VPROF_BUDGETGROUP_PARTICLE_RENDERING); Vector offset = position + (normal * 1.0f); CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create("FX_MetalScrape 1"); if (!sparkEmitter) return; sparkEmitter->SetSortOrigin(offset); //Setup our collision information sparkEmitter->Setup(offset, &normal, METAL_SCRAPE_SPREAD, METAL_SCRAPE_MINSPEED, METAL_SCRAPE_MAXSPEED, METAL_SCRAPE_GRAVITY, METAL_SCRAPE_DAMPEN, bitsPARTICLE_TRAIL_VELOCITY_DAMPEN); int numSparks = random->RandomInt(4, 8); if (g_Material_Spark == NULL) { g_Material_Spark = sparkEmitter->GetPMaterial("effects/spark"); } Vector dir; TrailParticle *pParticle; float length = 0.06f; //Dump out sparks for (int i = 0; i < numSparks; i++) { pParticle = (TrailParticle *) sparkEmitter->AddParticle(sizeof(TrailParticle), g_Material_Spark, offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; float spreadOfs = random->RandomFloat(0.0f, 2.0f); dir[0] = normal[0] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs)); dir[1] = normal[1] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs)); dir[2] = normal[2] + random->RandomFloat(-(METAL_SCRAPE_SPREAD*spreadOfs), (METAL_SCRAPE_SPREAD*spreadOfs)); pParticle->m_flWidth = random->RandomFloat(2.0f, 5.0f); pParticle->m_flLength = random->RandomFloat(length*0.25f, length); pParticle->m_flDieTime = random->RandomFloat(2.0f, 2.0f); pParticle->m_vecVelocity = dir * random->RandomFloat((METAL_SCRAPE_MINSPEED*(2.0f - spreadOfs)), (METAL_SCRAPE_MAXSPEED*(2.0f - spreadOfs))); Color32Init(pParticle->m_color, 255, 255, 255, 255); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_ObjectEMPGenerator::OnDataChanged( DataUpdateType_t updateType ) { BaseClass::OnDataChanged( updateType ); if ( updateType == DATA_UPDATE_CREATED ) { m_pEmitter = CSimpleEmitter::Create( "C_ObjectEMPGenerator" ); m_hParticleMaterial = m_pEmitter->GetPMaterial( "sprites/chargeball" ); } }
//----------------------------------------------------------------------------- // Chopper muzzle flashes //----------------------------------------------------------------------------- void MuzzleFlash_Chopper( ClientEntityHandle_t hEntity, int attachmentIndex ) { VPROF_BUDGET( "MuzzleFlash_Chopper", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); matrix3x4_t matAttachment; // If the client hasn't seen this entity yet, bail. if ( !FX_GetAttachmentTransform( hEntity, attachmentIndex, matAttachment ) ) return; CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash", hEntity, attachmentIndex ); SimpleParticle *pParticle; Vector forward(1,0,0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat( 2.5f, 4.5f ); // Flash for ( int i = 1; i < 7; i++ ) { offset = (forward * (i*2.0f*flScale)); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( VarArgs( "effects/combinemuzzle%d", random->RandomInt(1,2) ) ), offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.05f, 0.1f ); pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 128; pParticle->m_uchStartSize = ( (random->RandomFloat( 6.0f, 8.0f ) * (10-(i))/7) * flScale ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } // Grab the origin out of the transform for the attachment Vector origin; MatrixGetColumn( matAttachment, 3, &origin ); CreateMuzzleflashELight( origin, 6, 128, 256, hEntity ); }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void C_PlasmaBeamNode::ClientThink(void) { if (!m_bSprayOn) { return; } trace_t trace; Vector vEndTrace = GetAbsOrigin() + (0.3*GetAbsVelocity()); UTIL_TraceLine( GetAbsOrigin(), vEndTrace, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &trace ); if ( trace.fraction != 1.0f || trace.startsolid) { m_bSprayOn = false; return; } PMaterialHandle handle = m_pFirePlasmaSpray->GetPMaterial( "sprites/plasmaember" ); for (int i=0;i<SPRAYS_PER_THINK;i++) { SimpleParticle *sParticle; //Make a new particle if ( random->RandomInt( 0, 2 ) == 0 ) { float ranx = random->RandomFloat( -28.0f, 28.0f ); float rany = random->RandomFloat( -28.0f, 28.0f ); float ranz = random->RandomFloat( -28.0f, 28.0f ); Vector vNewPos = GetAbsOrigin(); Vector vAdd = Vector(GetAbsAngles().x,GetAbsAngles().y,GetAbsAngles().z)*random->RandomFloat(-60,120); vNewPos += vAdd; sParticle = (SimpleParticle *) m_pFirePlasmaSpray->AddParticle( sizeof(SimpleParticle), handle, vNewPos ); sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = PLASMASPARK_LIFETIME; sParticle->m_vecVelocity = GetAbsVelocity(); sParticle->m_vecVelocity.x += ranx; sParticle->m_vecVelocity.y += rany; sParticle->m_vecVelocity.z += ranz; m_pFirePlasmaSpray->m_pOwner = this; } } SetNextClientThink(gpGlobals->curtime + 0.05); }
//----------------------------------------------------------------------------- // Purpose: // Input : flPerc - //----------------------------------------------------------------------------- void C_MortarShell::AddRisingParticles( float flPerc ) { SimpleParticle *sParticle; Vector offset; float radius = m_flRadius * 0.25f * flPerc; float val = RemapValClamped( gpGlobals->curtime, m_flStarttime, m_flStarttime + m_flLifespan, 0.0f, 1.0f ); float flCur = gpGlobals->frametime; // Anime ground effects while ( m_ParticleEvent.NextEvent( flCur ) ) { offset.x = random->RandomFloat( -radius, radius ); offset.y = random->RandomFloat( -radius, radius ); offset.z = random->RandomFloat( -8.0f, 8.0f ); offset += GetAbsOrigin(); sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 32.0f, 256.0f ) * Bias( val, 0.25f ) ); sParticle->m_uchStartSize = random->RandomFloat( 4, 8 ) * flPerc; sParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); float alpha = 255 * flPerc; sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc ); sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchEndSize = 0; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_EnvStarfield::ClientThink( void ) { if ( !m_bOn || !m_flDensity ) return; PMaterialHandle hParticleMaterial = m_pEmitter->GetPMaterial( "effects/spark_noz" ); // Find a start & end point for the particle // Start particles straight ahead of the client Vector vecViewOrigin = MainViewOrigin(engine->GetActiveSplitScreenPlayerSlot()); // Determine the number of particles m_flNumParticles += 1.0 * (m_flDensity); int iNumParticles = floor(m_flNumParticles); m_flNumParticles -= iNumParticles; // Add particles for ( int i = 0; i < iNumParticles; i++ ) { float flDiameter = cl_starfield_diameter.GetFloat(); Vector vecStart = vecViewOrigin + (MainViewForward(engine->GetActiveSplitScreenPlayerSlot()) * cl_starfield_distance.GetFloat() ); Vector vecEnd = vecViewOrigin + (MainViewRight(engine->GetActiveSplitScreenPlayerSlot()) * RandomFloat(-flDiameter,flDiameter)) + (MainViewUp(engine->GetActiveSplitScreenPlayerSlot()) * RandomFloat(-flDiameter,flDiameter)); Vector vecDir = (vecEnd - vecStart); float flDistance = VectorNormalize( vecDir ); float flTravelTime = 2.0; // Start a random amount along the path vecStart += vecDir * ( RandomFloat(0.1,0.3) * flDistance ); TrailParticle *pParticle = (TrailParticle *) m_pEmitter->AddParticle( sizeof(TrailParticle), hParticleMaterial, vecStart ); if ( pParticle ) { pParticle->m_vecVelocity = vecDir * (flDistance / flTravelTime); pParticle->m_flDieTime = flTravelTime; pParticle->m_flLifetime = 0; pParticle->m_flWidth = RandomFloat( 1, 3 ); pParticle->m_flLength = RandomFloat( 0.05, 0.4 ); pParticle->m_color.r = 255; pParticle->m_color.g = 255; pParticle->m_color.b = 255; pParticle->m_color.a = 255; } } }
//----------------------------------------------------------------------------- // Purpose: // Input : flPerc - //----------------------------------------------------------------------------- void C_MortarShell::AddExplodingParticles( float flPerc ) { SimpleParticle *sParticle; Vector offset; float radius = 48.0f * flPerc; float flCur = gpGlobals->frametime; // Anime ground effects while ( m_ParticleEvent.NextEvent( flCur ) ) { offset.x = random->RandomFloat( -radius, radius ); offset.y = random->RandomFloat( -radius, radius ); offset.z = random->RandomFloat( -8.0f, 8.0f ); offset += GetAbsOrigin(); sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = RandomVector( -1.0f, 1.0f ) + Vector( 0, 0, 1 ); sParticle->m_vecVelocity *= ( 750.0f * flPerc ); sParticle->m_uchStartSize = random->RandomFloat( 2, 4 ) * flPerc; sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); float alpha = 255 * flPerc; sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc ); sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchEndSize = 0; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void FX_GunshipMuzzleEffect( const Vector &origin, const QAngle &angles, float scale, ClientEntityHandle_t hEntity, unsigned char *pFlashColor ) { VPROF_BUDGET( "FX_GunshipMuzzleEffect", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "MuzzleFlash" ); pSimple->SetSortOrigin( origin ); SimpleParticle *pParticle; Vector forward, offset; AngleVectors( angles, &forward ); // // Flash // offset = origin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/gunshipmuzzle" ), offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.15f; pParticle->m_vecVelocity.Init(); pParticle->m_uchStartSize = random->RandomFloat( 40.0, 50.0 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.15f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; }
//----------------------------------------------------------------------------- // Purpose: Warp effect that looks like it's sucking things to it //----------------------------------------------------------------------------- void FX_BuildWarpSuck( Vector &vecOrigin, QAngle &vecAngles, float flScale ) { CSmartPtr<CTrailParticles> pEmitter = CTrailParticles::Create( "BuildWarpSuck" ); PMaterialHandle hParticleMaterial = pEmitter->GetPMaterial( "effects/bluespark" ); pEmitter->Setup( (Vector &) vecOrigin, NULL, 0.0, 0, 64, 0, 0, bitsPARTICLE_TRAIL_VELOCITY_DAMPEN | bitsPARTICLE_TRAIL_FADE ); // Add particles int iNumParticles = 60; for ( int i = 0; i < iNumParticles; i++ ) { Vector vOffset = RandomVector( -1, 1 ); VectorNormalize( vOffset ); float flDistance = RandomFloat( 16, 64 ) * flScale; Vector vPos = vecOrigin + (vOffset * flDistance); TrailParticle *pParticle = (TrailParticle *) pEmitter->AddParticle( sizeof(TrailParticle), hParticleMaterial, vPos ); if ( pParticle ) { float flSpeed = RandomFloat(8,16) * (flScale * flScale * flScale); pParticle->m_vecVelocity = vOffset * -flSpeed; pParticle->m_flDieTime = min( 3, (flDistance / flSpeed) + RandomFloat(0.0, 0.2) ); pParticle->m_flLifetime = 0; pParticle->m_flWidth = RandomFloat( 2, 3 ) * flScale; pParticle->m_flLength = RandomFloat( 1, 2 ) * flScale; pParticle->m_color.r = 1.0f; pParticle->m_color.g = 1.0f; pParticle->m_color.b = 1.0f; pParticle->m_color.a = 1.0f; } } }
//----------------------------------------------------------------------------- // Purpose: Called when data changes on the server //----------------------------------------------------------------------------- void C_Sparkler::OnDataChanged( DataUpdateType_t updateType ) { // NOTE: We MUST call the base classes' implementation of this function BaseClass::OnDataChanged( updateType ); // Setup our entity's particle system on creation if ( updateType == DATA_UPDATE_CREATED ) { // Creat the emitter m_hEmitter = CSimpleEmitter::Create( "env_sparkler" ); // Obtain a reference handle to our particle's desired material if ( m_hEmitter.IsValid() ) { m_hMaterial = m_hEmitter->GetPMaterial( "effects/yellowflare" ); } // Spawn 128 particles per second m_tParticleTimer.Init( 128 ); // Call our ClientThink() function once every client frame SetNextClientThink( CLIENT_THINK_ALWAYS ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_WaterExplosionEffect::CreateDebris( void ) { if ( m_fFlags & TE_EXPLFLAG_NOPARTICLES ) return; // Must be in deep enough water if ( m_flDepth <= 128 ) return; Vector offset; int i; //Spread constricts as force rises float force = m_flForce; //Cap our force if ( force < EXPLOSION_FORCE_MIN ) force = EXPLOSION_FORCE_MIN; if ( force > EXPLOSION_FORCE_MAX ) force = EXPLOSION_FORCE_MAX; float spread = 1.0f - (0.15f*force); SimpleParticle *pParticle; CSmartPtr<CWaterExplosionParticle> pSimple = CWaterExplosionParticle::Create( "waterexp_bubbles" ); pSimple->SetSortOrigin( m_vecOrigin ); pSimple->SetNearClip( 64, 128 ); //FIXME: Better sampling area offset = m_vecOrigin + ( m_vecDirection * 64.0f ); //Find area ambient light color and use it to tint bubbles Vector worldLight; FX_GetSplashLighting( offset, &worldLight, NULL ); // // Smoke // CParticleSubTexture *pMaterial[2]; pMaterial[0] = pSimple->GetPMaterial( "effects/splash1" ); pMaterial[1] = pSimple->GetPMaterial( "effects/splash2" ); for ( i = 0; i < 16; i++ ) { offset.Random( -32.0f, 32.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pMaterial[random->RandomInt(0,1)], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; #ifdef INVASION_CLIENT_DLL pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); #else pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f ); #endif pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( m_vecDirection * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = 1500 * force; //Scale the force down as we fall away from our main direction ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread, &fForce ); pParticle->m_vecVelocity *= fForce; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif pParticle->m_uchColor[0] = m_vecColor.x * 255; pParticle->m_uchColor[1] = m_vecColor.y * 255; pParticle->m_uchColor[2] = m_vecColor.z * 255; pParticle->m_uchStartSize = random->RandomInt( 32, 64 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2; pParticle->m_uchStartAlpha = m_flLuminosity; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void FX_MuzzleEffect( const Vector &origin, const QAngle &angles, float scale, ClientEntityHandle_t hEntity, unsigned char *pFlashColor, bool bOneFrame ) { VPROF_BUDGET( "FX_MuzzleEffect", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "MuzzleFlash" ); pSimple->SetSortOrigin( origin ); SimpleParticle *pParticle; Vector forward, offset; AngleVectors( angles, &forward ); float flScale = random->RandomFloat( scale-0.25f, scale+0.25f ); if ( flScale < 0.5f ) { flScale = 0.5f; } else if ( flScale > 8.0f ) { flScale = 8.0f; } // // Flash // int i; for ( i = 1; i < 9; i++ ) { offset = origin + (forward * (i*2.0f*scale)); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( VarArgs( "effects/muzzleflash%d", random->RandomInt(1,4) ) ), offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = /*bOneFrame ? 0.0001f : */0.1f; pParticle->m_vecVelocity.Init(); if ( !pFlashColor ) { pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; } else { pParticle->m_uchColor[0] = pFlashColor[0]; pParticle->m_uchColor[1] = pFlashColor[1]; pParticle->m_uchColor[2] = pFlashColor[2]; } pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 128; pParticle->m_uchStartSize = (random->RandomFloat( 6.0f, 9.0f ) * (12-(i))/9) * flScale; pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = 0.0f; } // // Smoke // /* for ( i = 0; i < 4; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "particle/particle_smokegrenade" ), origin ); if ( pParticle == NULL ) return; alpha = random->RandomInt( 32, 84 ); color = random->RandomInt( 64, 164 ); pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); pParticle->m_vecVelocity.Random( -0.5f, 0.5f ); pParticle->m_vecVelocity += forward; VectorNormalize( pParticle->m_vecVelocity ); pParticle->m_vecVelocity *= random->RandomFloat( 16.0f, 32.0f ); pParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f ); pParticle->m_uchColor[0] = color; pParticle->m_uchColor[1] = color; pParticle->m_uchColor[2] = color; pParticle->m_uchStartAlpha = alpha; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = random->RandomInt( 4, 8 ) * flScale; pParticle->m_uchEndSize = pParticle->m_uchStartSize*2; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f ); } */ }
//----------------------------------------------------------------------------- // Purpose: // Input : percentage - //----------------------------------------------------------------------------- void C_AlyxEmpEffect::UpdateDischarging( void ) { // Emitters must be valid if ( SetupEmitters() == false ) return; // Reset our sort origin m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() ); float flScale = EMP_SCALE * 8.0f; Vector forward, right, up; AngleVectors( GetAbsAngles(), &forward, &right, &up ); SimpleParticle *sParticle; float dTime = gpGlobals->frametime; while ( m_tParticleSpawn.NextEvent( dTime ) ) { // Base of the core effect sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = vec3_origin; sParticle->m_flDieTime = 0.25f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; float alpha = 64; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = flScale * 4.0f; sParticle->m_uchEndSize = 0.0f; // Base of the core effect sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = vec3_origin; sParticle->m_flDieTime = 0.1f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; alpha = 128; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = 0.0f; sParticle->m_uchEndSize = flScale * 2.0f; // Make sure we encompass the complete particle here! m_pSimpleEmitter->SetParticleCullRadius( sParticle->m_uchEndSize ); // Do the core effects sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = RandomVector( -32.0f, 32.0f ); sParticle->m_flDieTime = 0.2f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; alpha = 255; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = flScale; sParticle->m_uchEndSize = 0.0f; } #if 0 // Do the charging particles m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() ); Vector offset; float dist; for ( i = 0; i < 4; i++ ) { dist = random->RandomFloat( 4.0f, 64.0f ); offset = forward * dist; dist = RemapValClamped( dist, 4.0f, 64.0f, 6.0f, 1.0f ); offset += right * random->RandomFloat( -2.0f * dist, 2.0f * dist ); offset += up * random->RandomFloat( -2.0f * dist, 2.0f * dist ); offset += GetAbsOrigin(); sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/combinemuzzle2_dark" ), offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = Vector(0,0,2); sParticle->m_flDieTime = 0.5f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; float alpha = 255; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = 1; sParticle->m_uchEndSize = 0; } #endif }
void FX_Tesla( const CTeslaInfo &teslaInfo ) { C_BaseEntity *pEntity = ClientEntityList().GetEnt( teslaInfo.m_nEntIndex ); // Send out beams around us int iNumBeamsAround = (teslaInfo.m_nBeams * 2) / 3; // (2/3 of the beams are placed around in a circle) int iNumRandomBeams = teslaInfo.m_nBeams - iNumBeamsAround; int iTotalBeams = iNumBeamsAround + iNumRandomBeams; float flYawOffset = RandomFloat(0,360); for ( int i = 0; i < iTotalBeams; i++ ) { // Make a couple of tries at it int iTries = -1; Vector vecForward; trace_t tr; do { iTries++; // Some beams are deliberatly aimed around the point, the rest are random. if ( i < iNumBeamsAround ) { QAngle vecTemp = teslaInfo.m_vAngles; vecTemp[YAW] += anglemod( flYawOffset + ((360 / iTotalBeams) * i) ); AngleVectors( vecTemp, &vecForward ); // Randomly angle it up or down vecForward.z = RandomFloat( -1, 1 ); } else { vecForward = RandomVector( -1, 1 ); } VectorNormalize( vecForward ); UTIL_TraceLine( teslaInfo.m_vPos, teslaInfo.m_vPos + (vecForward * teslaInfo.m_flRadius), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr ); } while ( tr.fraction >= 1.0 && iTries < 3 ); Vector vecEnd = tr.endpos - (vecForward * 8); // Only spark & glow if we hit something if ( tr.fraction < 1.0 ) { if ( !EffectOccluded( tr.endpos, 0 ) ) { // Move it towards the camera Vector vecFlash = tr.endpos; Vector vecForward; AngleVectors( MainViewAngles(), &vecForward ); vecFlash -= (vecForward * 8); g_pEffects->EnergySplash( vecFlash, -vecForward, false ); // End glow CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" ); pSimple->SetSortOrigin( vecFlash ); SimpleParticle *pParticle; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = RandomFloat( 0.5, 1 ); pParticle->m_vecVelocity = vec3_origin; Vector color( 1,1,1 ); float colorRamp = RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = RandomFloat( 6,13 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 10; pParticle->m_flRoll = RandomFloat( 0,360 ); pParticle->m_flRollDelta = 0; } } } // Build the tesla FX_BuildTesla( pEntity, teslaInfo.m_vPos, tr.endpos, teslaInfo.m_pszSpriteName, teslaInfo.m_flBeamWidth, teslaInfo.m_vColor, FBEAM_ONLYNOISEONCE, teslaInfo.m_flTimeVisible ); } }
void C_EnvPortalPathTrack::UpdateParticles_Active ( void ) { // Emitters must be valid if ( SetupEmitters() == false ) return; // Reset our sort origin m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() ); SimpleParticle *sParticle; // Do the charging particles m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() ); Vector forward, right, up; AngleVectors( GetAbsAngles(), &forward, &right, &up ); Vector offset; float dist; int numParticles = floor( 4.0f ); for ( int i = 0; i < numParticles; i++ ) { dist = random->RandomFloat( 4.0f, 64.0f ); offset = forward * dist; dist = RemapValClamped( dist, 4.0f, 64.0f, 6.0f, 1.0f ); offset += right * random->RandomFloat( -4.0f * dist, 4.0f * dist ); offset += up * random->RandomFloat( -4.0f * dist, 4.0f * dist ); offset += GetAbsOrigin(); sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/strider_muzzle" ), offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = Vector(0,0,8); sParticle->m_flDieTime = 0.5f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; float alpha = 255; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ); sParticle->m_uchEndSize = 0; } }
//----------------------------------------------------------------------------- // Purpose: // Input : &pos - // &dir - // type - //----------------------------------------------------------------------------- void FX_GaussExplosion( const Vector &pos, const Vector &dir, int type ) { Vector vDir; vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f ); vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f ); vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f ); VectorNormalize( vDir ); int i; #if defined(_XBOX) || defined(_X360) // // XBox version // CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_GaussExplosion" ); if ( pSparkEmitter == NULL ) { Assert(0); return; } if ( g_Material_Spark == NULL ) { g_Material_Spark = pSparkEmitter->GetPMaterial( "effects/spark" ); } pSparkEmitter->SetSortOrigin( pos ); pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f ); pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); pSparkEmitter->GetBinding().SetBBox( pos - Vector( 32, 32, 32 ), pos + Vector( 32, 32, 32 ) ); int numSparks = random->RandomInt( 8, 16 ); TrailParticle *pParticle; // Dump out sparks for ( i = 0; i < numSparks; i++ ) { pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), g_Material_Spark, pos ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; vDir.Random( -0.6f, 0.6f ); vDir += dir; VectorNormalize( vDir ); pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f ); pParticle->m_flLength = random->RandomFloat( 0.01f, 0.1f ); pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); pParticle->m_vecVelocity = vDir * random->RandomFloat( 128, 512 ); Color32Init( pParticle->m_color, 255, 255, 255, 255 ); } // End cap SimpleParticle particle; particle.m_Pos = pos; particle.m_flLifetime = 0.0f; particle.m_flDieTime = 0.1f; particle.m_vecVelocity.Init(); particle.m_flRoll = random->RandomInt( 0, 360 ); particle.m_flRollDelta = 0.0f; particle.m_uchColor[0] = 255; particle.m_uchColor[1] = 255; particle.m_uchColor[2] = 255; particle.m_uchStartAlpha = 255; particle.m_uchEndAlpha = 255; particle.m_uchStartSize = random->RandomInt( 24, 32 ); particle.m_uchEndSize = 0; AddSimpleParticle( &particle, ParticleMgr()->GetPMaterial( "effects/yellowflare" ) ); #else // // PC version // CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_ElectricSpark" ); if ( !pSparkEmitter ) { Assert(0); return; } PMaterialHandle hMaterial = pSparkEmitter->GetPMaterial( "effects/spark" ); pSparkEmitter->SetSortOrigin( pos ); pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f ); pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN|bitsPARTICLE_TRAIL_COLLIDE ); //Setup our collision information pSparkEmitter->m_ParticleCollision.Setup( pos, &vDir, 0.8f, 128, 512, 800, 0.3f ); int numSparks = random->RandomInt( 16, 32 ); TrailParticle *pParticle; // Dump out sparks for ( i = 0; i < numSparks; i++ ) { pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, pos ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; vDir.Random( -0.6f, 0.6f ); vDir += dir; VectorNormalize( vDir ); pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f ); pParticle->m_flLength = random->RandomFloat( 0.01f, 0.1f ); pParticle->m_flDieTime = random->RandomFloat( 0.25f, 1.0f ); pParticle->m_vecVelocity = vDir * random->RandomFloat( 128, 512 ); Color32Init( pParticle->m_color, 255, 255, 255, 255 ); } FX_ElectricSpark( pos, 1, 1, &vDir ); #endif }
//----------------------------------------------------------------------------- // Purpose: // Input : &pos - // &dir - // type - //----------------------------------------------------------------------------- void FX_GaussExplosion(const Vector &pos, const Vector &dir, int type) { Vector vDir; vDir[0] = dir[0] + random->RandomFloat(-1.0f, 1.0f); vDir[1] = dir[1] + random->RandomFloat(-1.0f, 1.0f); vDir[2] = dir[2] + random->RandomFloat(-1.0f, 1.0f); VectorNormalize(vDir); int i; // // PC version // CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create("FX_ElectricSpark"); if (!pSparkEmitter) { Assert(0); return; } PMaterialHandle hMaterial = pSparkEmitter->GetPMaterial("effects/spark"); pSparkEmitter->SetSortOrigin(pos); pSparkEmitter->m_ParticleCollision.SetGravity(800.0f); pSparkEmitter->SetFlag(bitsPARTICLE_TRAIL_VELOCITY_DAMPEN | bitsPARTICLE_TRAIL_COLLIDE); //Setup our collision information pSparkEmitter->m_ParticleCollision.Setup(pos, &vDir, 0.8f, 128, 512, 800, 0.3f); int numSparks = random->RandomInt(16, 32); TrailParticle *pParticle; // Dump out sparks for (i = 0; i < numSparks; i++) { pParticle = (TrailParticle *) pSparkEmitter->AddParticle(sizeof(TrailParticle), hMaterial, pos); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; vDir.Random(-0.6f, 0.6f); vDir += dir; VectorNormalize(vDir); pParticle->m_flWidth = random->RandomFloat(1.0f, 4.0f); pParticle->m_flLength = random->RandomFloat(0.01f, 0.1f); pParticle->m_flDieTime = random->RandomFloat(0.25f, 1.0f); pParticle->m_vecVelocity = vDir * random->RandomFloat(128, 512); Color32Init(pParticle->m_color, 255, 255, 255, 255); } FX_ElectricSpark(pos, 1, 1, &vDir); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_HopwireExplosion::AddParticles( void ) { // Make sure the emitters are setup properly if ( SetupEmitters() == false ) return; float tempDelta = gpGlobals->frametime; while( m_ParticleTimer.NextEvent( tempDelta ) ) { // ======================== // Attracted dust particles // ======================== // Update our attractor point m_pAttractorEmitter->SetAttractorOrigin( GetRenderOrigin() ); Vector offset; SimpleParticle *sParticle; offset = GetRenderOrigin() + RandomVector( -256.0f, 256.0f ); sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_Fleck_Cement[0], offset ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = Vector(0,0,8); sParticle->m_flDieTime = 0.5f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 1.0f; float alpha = random->RandomFloat( 128.0f, 200.0f ); sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = alpha; sParticle->m_uchStartSize = random->RandomInt( 1, 4 ); sParticle->m_uchEndSize = 0; // ======================== // Core effects // ======================== // Reset our sort origin m_pSimpleEmitter->SetSortOrigin( GetRenderOrigin() ); // Base of the core effect sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( "effects/strider_muzzle" ), GetRenderOrigin() ); if ( sParticle == NULL ) return; sParticle->m_vecVelocity = vec3_origin; sParticle->m_flDieTime = 0.2f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 4.0f; alpha = random->RandomInt( 32, 200 ); sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = 0; sParticle->m_uchEndAlpha = alpha; sParticle->m_uchStartSize = 255; sParticle->m_uchEndSize = 0; // Make sure we encompass the complete particle here! m_pSimpleEmitter->SetParticleCullRadius( sParticle->m_uchEndSize ); // ========================= // Dust ring effect // ========================= if ( random->RandomInt( 0, 5 ) != 1 ) return; Vector vecDustColor; vecDustColor.x = 0.35f; vecDustColor.y = 0.3f; vecDustColor.z = 0.25f; Vector color; int numRingSprites = 8; float yaw; Vector forward, vRight, vForward; vForward = Vector( 0, 1, 0 ); vRight = Vector( 1, 0, 0 ); float yawOfs = random->RandomFloat( 0, 359 ); for ( int i = 0; i < numRingSprites; i++ ) { yaw = ( (float) i / (float) numRingSprites ) * 360.0f; yaw += yawOfs; forward = ( vRight * sin( DEG2RAD( yaw) ) ) + ( vForward * cos( DEG2RAD( yaw ) ) ); VectorNormalize( forward ); trace_t tr; UTIL_TraceLine( GetRenderOrigin(), GetRenderOrigin()+(Vector(0, 0, -1024)), MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); offset = ( RandomVector( -4.0f, 4.0f ) + tr.endpos ) + ( forward * 512.0f ); sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset ); if ( sParticle != NULL ) { sParticle->m_flLifetime = 0.0f; sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); sParticle->m_vecVelocity = forward * -random->RandomFloat( 1000, 1500 ); sParticle->m_vecVelocity[2] += 128.0f; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + sParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif sParticle->m_uchColor[0] = vecDustColor.x * 255.0f; sParticle->m_uchColor[1] = vecDustColor.y * 255.0f; sParticle->m_uchColor[2] = vecDustColor.z * 255.0f; sParticle->m_uchStartSize = random->RandomInt( 32, 128 ); sParticle->m_uchEndSize = 200; sParticle->m_uchStartAlpha = random->RandomFloat( 16, 64 ); sParticle->m_uchEndAlpha = 0; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f ); } } } }
//----------------------------------------------------------------------------- // Purpose: // Input : fTimeDelta - //----------------------------------------------------------------------------- void C_ExtinguisherJet::Update( float fTimeDelta ) { if ( m_bEmit == false ) return; C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); if ( m_bUseMuzzlePoint ) { C_BaseViewModel *vm = player ? player->GetViewModel( 0 ) : NULL; if ( vm ) { int iAttachment = vm->LookupAttachment( "muzzle" ); Vector origin; QAngle angles; vm->GetAttachment( iAttachment, origin, angles ); Assert( !GetMoveParent() ); SetLocalOrigin( origin ); SetLocalAngles( angles ); } } trace_t tr; Vector shotDir, vRight, vUp; AngleVectors( GetAbsAngles(), &shotDir, &vRight, &vUp ); //FIXME: Muzzle point is incorrect on the model! if ( m_bUseMuzzlePoint ) { shotDir.Negate(); } Vector endPoint = GetAbsOrigin() + ( shotDir * 150.0f ); UTIL_TraceLine( GetAbsOrigin(), endPoint, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &tr ); bool hitWall = ( tr.fraction < 1.0f ); //Add normal jet if ( m_pEmitter.IsValid() ) { SimpleParticle *pParticle; m_pEmitter->SetSortOrigin( GetAbsOrigin() ); float tempDelta = fTimeDelta; //FIXME: All particles need to be within this loop while( m_ParticleSpawn.NextEvent( tempDelta ) ) { pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() ); if ( pParticle ) { pParticle->m_flDieTime = 0.2f; pParticle->m_flLifetime = 0.0f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f ); pParticle->m_uchStartSize = 1; pParticle->m_uchEndSize = random->RandomInt( 32, 48 ); pParticle->m_uchStartAlpha = random->RandomInt( 128, 164 ); pParticle->m_uchEndAlpha = 0; int cScale = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = cScale; pParticle->m_uchColor[1] = cScale; pParticle->m_uchColor[2] = cScale; Vector dir; QAngle ofsAngles; ofsAngles.Random( -8.0f, 8.0f ); ofsAngles += GetAbsAngles(); AngleVectors( ofsAngles, &dir ); if ( m_bUseMuzzlePoint ) { dir.Negate(); } pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 ); } //Add muzzle effect pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() ); if ( pParticle ) { pParticle->m_flDieTime = 0.1f; pParticle->m_flLifetime = 0.0f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f ); pParticle->m_uchStartSize = 1; pParticle->m_uchEndSize = random->RandomInt( 8, 16 ); pParticle->m_uchStartAlpha = random->RandomInt( 128, 255 ); pParticle->m_uchEndAlpha = 0; int cScale = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = cScale; pParticle->m_uchColor[1] = cScale; pParticle->m_uchColor[2] = cScale; Vector dir; QAngle ofsAngles; ofsAngles.Random( -64.0f, 64.0f ); ofsAngles += GetAbsAngles(); AngleVectors( ofsAngles, &dir ); if ( m_bUseMuzzlePoint ) { dir.Negate(); } pParticle->m_vecVelocity = dir * random->RandomInt( 32, 64 ); } //Add a wall effect if needed if ( hitWall ) { AddExtinguisherDecal( tr ); Vector offDir; offDir.Random( -16.0f, 16.0f ); pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, ( tr.endpos + ( tr.plane.normal * 8.0f ) ) + offDir ); if ( pParticle ) { pParticle->m_flDieTime = 0.4f; pParticle->m_flLifetime = 0.0f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta= random->RandomFloat( -2.0f, 2.0f ); pParticle->m_uchStartSize = random->RandomInt( 8, 16 ); pParticle->m_uchEndSize = random->RandomInt( 24, 32 ); pParticle->m_uchStartAlpha = random->RandomInt( 64, 128 ); pParticle->m_uchEndAlpha = 0; int cScale = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = cScale; pParticle->m_uchColor[1] = cScale; pParticle->m_uchColor[2] = cScale; Vector rDir; rDir = tr.plane.normal; rDir[0] += random->RandomFloat( -0.9f, 0.9f ); rDir[1] += random->RandomFloat( -0.9f, 0.9f ); rDir[2] += random->RandomFloat( -0.9f, 0.9f ); pParticle->m_vecVelocity = rDir * random->RandomInt( 32, 64 ); } } //Add small ember-like particles if ( random->RandomInt( 0, 1 ) == 0 ) { m_pEmberEmitter->SetSortOrigin( GetAbsOrigin() ); pParticle = (SimpleParticle *) m_pEmberEmitter->AddParticle( sizeof(SimpleParticle), m_pEmberEmitter->GetPMaterial( "particle/particle_smokegrenade" ), GetAbsOrigin() ); assert(pParticle); if ( pParticle ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 1.0f; pParticle->m_flRoll = 0; pParticle->m_flRollDelta = 0; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = 1; pParticle->m_uchEndSize = 0; Vector dir; QAngle ofsAngles; ofsAngles.Random( -8.0f, 8.0f ); ofsAngles += GetAbsAngles(); AngleVectors( ofsAngles, &dir ); if ( m_bUseMuzzlePoint ) { dir.Negate(); } pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 ); } } } } // Inner beam CBeamSegDraw beamDraw; CBeamSeg seg; const int numPoints = 4; Vector beamPoints[numPoints]; beamPoints[0] = GetAbsOrigin(); // Create our beam points int i; for ( i = 0; i < numPoints; i++ ) { beamPoints[i] = GetAbsOrigin() + ( shotDir * (32*i*i) ); beamPoints[i] += vRight * sin( gpGlobals->curtime * 4.0f ) * (2.0f*i); beamPoints[i] += vUp * sin( gpGlobals->curtime * 8.0f ) * (1.0f*i); beamPoints[i] += shotDir * sin( gpGlobals->curtime * (16.0f*i) ) * (1.0f*i); } IMaterial *pMat = materials->FindMaterial( "particle/particle_smokegrenade", NULL ); beamDraw.Start( numPoints, pMat ); //Setup and draw those points for( i = 0; i < numPoints; i++ ) { float t = (float) i / (numPoints - 1); float color = 1.0f * (1.0f - t); seg.m_vColor = Vector( color, color, color ); seg.m_vPos = beamPoints[i]; seg.m_flTexCoord = (float)i/(float)(numPoints-1) - ((gpGlobals->curtime - (int)gpGlobals->curtime) * 4.0f ); seg.m_flWidth = 4.0f + ( (64.0f*t) * (fabs( sin( gpGlobals->curtime * 16.0f ) )) ); seg.m_flAlpha = color; beamDraw.NextSeg( &seg ); } beamDraw.End(); }
//----------------------------------------------------------------------------- // Purpose: // Input : flags - // Output : int //----------------------------------------------------------------------------- int C_WeaponPhysCannon::DrawModel( int flags ) { // If we're not ugrading, don't do anything special if ( m_bIsCurrentlyUpgrading == false && m_bWasUpgraded == false ) return BaseClass::DrawModel( flags ); if ( gpGlobals->frametime == 0 ) return BaseClass::DrawModel( flags ); if ( !m_bReadyToDraw ) return 0; m_bWasUpgraded = true; // Create the particle emitter if it's not already if ( SetupEmitter() ) { // Add the power-up particles // See if we should draw if ( m_bReadyToDraw == false ) return 0; C_BaseAnimating *pAnimating = GetBaseAnimating(); if (!pAnimating) return 0; matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) ) return 0; studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() ); if (!pStudioHdr) return false; mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() ); if ( !set ) return false; int i; float fadePerc = 1.0f; if ( m_bIsCurrentlyUpgrading ) { Vector vecSkew = vec3_origin; // Skew the particles in front or in back of their targets vecSkew = CurrentViewForward() * 4.0f; float spriteScale = 1.0f; spriteScale = clamp( spriteScale, 0.75f, 1.0f ); SimpleParticle *sParticle; for ( i = 0; i < set->numhitboxes; ++i ) { Vector vecAbsOrigin, xvec, yvec; mstudiobbox_t *pBox = set->pHitbox(i); ComputeRenderInfo( pBox, *hitboxbones[pBox->bone], &vecAbsOrigin, &xvec, &yvec ); Vector offset; Vector xDir, yDir; xDir = xvec; float xScale = VectorNormalize( xDir ) * 0.75f; yDir = yvec; float yScale = VectorNormalize( yDir ) * 0.75f; int numParticles = clamp( 4.0f * fadePerc, 1, 3 ); for ( int j = 0; j < numParticles; j++ ) { offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f ); offset += vecSkew; sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/combinemuzzle1" ), vecAbsOrigin + offset ); if ( sParticle == NULL ) return 1; sParticle->m_vecVelocity = vec3_origin; sParticle->m_uchStartSize = 16.0f * spriteScale; sParticle->m_flDieTime = 0.2f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f ); float alpha = 40; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2; } } } } int attachment = LookupAttachment( "core" ); Vector coreOrigin; QAngle coreAngles; GetAttachment( attachment, coreOrigin, coreAngles ); SimpleParticle *sParticle; // Do the core effects for ( int i = 0; i < 4; i++ ) { sParticle = (SimpleParticle *) m_pLocalEmitter->AddParticle( sizeof(SimpleParticle), m_pLocalEmitter->GetPMaterial( "effects/strider_muzzle" ), vec3_origin ); if ( sParticle == NULL ) return 1; sParticle->m_vecVelocity = vec3_origin; sParticle->m_flDieTime = 0.1f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; float alpha = 255; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; if ( i < 2 ) { sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ) * (i+1); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f; } else { if ( random->RandomInt( 0, 20 ) == 0 ) { sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ) * (i+1); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 4.0f; sParticle->m_flDieTime = 0.25f; } else { sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ) * (i+1); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f; } } } if ( m_bWasUpgraded && m_bIsCurrentlyUpgrading ) { // Update our attractor point m_pAttractor->SetAttractorOrigin( coreOrigin ); Vector offset; for ( int i = 0; i < 4; i++ ) { offset = coreOrigin + RandomVector( -32.0f, 32.0f ); sParticle = (SimpleParticle *) m_pAttractor->AddParticle( sizeof(SimpleParticle), m_pAttractor->GetPMaterial( "effects/strider_muzzle" ), offset ); if ( sParticle == NULL ) return 1; sParticle->m_vecVelocity = Vector(0,0,8); sParticle->m_flDieTime = 0.5f; sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt( 0, 360 ); sParticle->m_flRollDelta = 0.0f; float alpha = 255; sParticle->m_uchColor[0] = alpha; sParticle->m_uchColor[1] = alpha; sParticle->m_uchColor[2] = alpha; sParticle->m_uchStartAlpha = alpha; sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ); sParticle->m_uchEndSize = 0; } } return BaseClass::DrawModel( flags ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_MegaBombExplosionEffect::CreateCore( void ) { if ( m_fFlags & TE_EXPLFLAG_NOFIREBALL ) return; Vector offset; int i; //Spread constricts as force rises float force = m_flForce; //Cap our force if ( force < EXPLOSION_FORCE_MIN ) force = EXPLOSION_FORCE_MIN; if ( force > EXPLOSION_FORCE_MAX ) force = EXPLOSION_FORCE_MAX; float spread = 1.0f - (0.15f*force); CSmartPtr<CExplosionParticle> pSimple = CExplosionParticle::Create( "exp_smoke" ); pSimple->SetSortOrigin( m_vecOrigin ); pSimple->SetNearClip( 32, 64 ); SimpleParticle *pParticle; if ( m_Material_FireCloud == NULL ) { m_Material_FireCloud = pSimple->GetPMaterial( "effects/fire_cloud2" ); } // // Fireballs // for ( i = 0; i < 32; i++ ) { offset.Random( -48.0f, 48.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_FireCloud, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.2f, 0.4f ); pParticle->m_vecVelocity.Random( -spread*0.75f, spread*0.75f ); pParticle->m_vecVelocity += m_vecDirection; VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 400.0f, 800.0f ); //Scale the force down as we fall away from our main direction float vDev = ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread ); pParticle->m_vecVelocity *= fForce * ( 16.0f * (vDev*vDev*0.5f) ); #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( 128, 255 ); pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = nColor; pParticle->m_uchStartSize = random->RandomInt( 32, 85 ) * vDev; pParticle->m_uchStartSize = clamp( pParticle->m_uchStartSize, 32, 85 ); pParticle->m_uchEndSize = (int)((float)pParticle->m_uchStartSize * 1.5f); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_RotorWashEmitter::ClientThink( void ) { SetNextClientThink( gpGlobals->curtime + ROTORWASH_THINK_INTERVAL ); trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin()+(Vector(0, 0, -1024)), (MASK_SOLID_BRUSHONLY|CONTENTS_WATER|CONTENTS_SLIME), NULL, COLLISION_GROUP_NONE, &tr ); if ( /*!m_bIgnoreSolid && */(tr.fraction == 1.0f || tr.startsolid || tr.allsolid) ) return; // If we hit the skybox, don't do it either if ( tr.surface.flags & SURF_SKY ) return; float heightScale = RemapValClamped( tr.fraction * 1024, 512, 1024, 1.0f, 0.0f ); Vector vecDustColor; if ( tr.contents & CONTENTS_WATER ) { vecDustColor.x = 0.8f; vecDustColor.y = 0.8f; vecDustColor.z = 0.75f; } else if ( tr.contents & CONTENTS_SLIME ) { vecDustColor.x = 0.6f; vecDustColor.y = 0.5f; vecDustColor.z = 0.15f; } else { vecDustColor.x = 0.35f; vecDustColor.y = 0.3f; vecDustColor.z = 0.25f; } #ifndef _XBOX InitSpawner(); if ( m_pSimple.IsValid() == false ) return; m_pSimple->SetSortOrigin( GetAbsOrigin() ); PMaterialHandle *hMaterial; // Cache and set our material based on the surface we're over (ie. water) if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) ) { if ( m_hWaterMaterial[0] == NULL ) { m_hWaterMaterial[0] = m_pSimple->GetPMaterial("effects/splash1"); m_hWaterMaterial[1] = m_pSimple->GetPMaterial("effects/splash2"); } hMaterial = m_hWaterMaterial; } else { hMaterial = g_Mat_DustPuff; } #endif // !XBOX // If we're above water, make ripples if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) ) { float flScale = random->RandomFloat( 7.5f, 8.5f ); Vector color = Vector( 0.8f, 0.8f, 0.75f ); Vector startPos = tr.endpos + Vector(0,0,8); Vector endPos = tr.endpos + Vector(0,0,-64); if ( tr.fraction < 1.0f ) { //Add a ripple quad to the surface FX_AddQuad( tr.endpos + ( tr.plane.normal * 0.5f ), tr.plane.normal, 64.0f * flScale, 128.0f * flScale, 0.8f, 0.75f * heightScale, 0.0f, 0.75f, random->RandomFloat( 0, 360 ), random->RandomFloat( -2.0f, 2.0f ), vecDustColor, 0.2f, "effects/splashwake3", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); } } #ifndef _XBOX int numRingSprites = 32; float yaw = random->RandomFloat( 0, 2*M_PI ); // Randomly placed on the unit circle float yawIncr = (2*M_PI) / numRingSprites; Vector vecForward; Vector offset; SimpleParticle *pParticle; // Draw the rings for ( int i = 0; i < numRingSprites; i++ ) { // Get our x,y on the unit circle SinCos( yaw, &vecForward.y, &vecForward.x ); // Increment ahead yaw += yawIncr; // @NOTE toml (3-28-07): broke out following expression because vc2005 optimizer was screwing up in presence of SinCos inline assembly. Would also // go away if offset were referenced below as in the AddLineOverlay() //offset = ( RandomVector( -4.0f, 4.0f ) + tr.endpos ) + ( vecForward * 128.0f ); offset = vecForward * 128.0f; offset += tr.endpos + RandomVector( -4.0f, 4.0f ); pParticle = (SimpleParticle *) m_pSimple->AddParticle( sizeof(SimpleParticle), hMaterial[random->RandomInt(0,1)], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.25f, 1.0f ); pParticle->m_vecVelocity = vecForward * random->RandomFloat( 1000, 1500 ); #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif if ( tr.contents & CONTENTS_SLIME ) { vecDustColor.x = random->RandomFloat( 0.4f, 0.6f ); vecDustColor.y = random->RandomFloat( 0.3f, 0.5f ); vecDustColor.z = random->RandomFloat( 0.1f, 0.2f ); } pParticle->m_uchColor[0] = vecDustColor.x * 255.0f; pParticle->m_uchColor[1] = vecDustColor.y * 255.0f; pParticle->m_uchColor[2] = vecDustColor.z * 255.0f; pParticle->m_uchStartSize = random->RandomInt( 16, 64 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomFloat( 16, 32 ) * heightScale; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f ); } } #endif // !XBOX }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseExplosionEffect::CreateCore( void ) { if ( m_fFlags & TE_EXPLFLAG_NOFIREBALL ) return; Vector offset; int i; //Spread constricts as force rises float force = m_flForce; //Cap our force if ( force < EXPLOSION_FORCE_MIN ) force = EXPLOSION_FORCE_MIN; if ( force > EXPLOSION_FORCE_MAX ) force = EXPLOSION_FORCE_MAX; float spread = 1.0f - (0.15f*force); SimpleParticle *pParticle; CSmartPtr<CExplosionParticle> pSimple = CExplosionParticle::Create( "exp_smoke" ); pSimple->SetSortOrigin( m_vecOrigin ); pSimple->SetNearClip( 64, 128 ); pSimple->GetBinding().SetBBox( m_vecOrigin - Vector( 128, 128, 128 ), m_vecOrigin + Vector( 128, 128, 128 ) ); if ( m_Material_Smoke == NULL ) { m_Material_Smoke = g_Mat_DustPuff[1]; } //FIXME: Better sampling area offset = m_vecOrigin + ( m_vecDirection * 32.0f ); //Find area ambient light color and use it to tint smoke Vector worldLight = WorldGetLightForPoint( offset, true ); Vector tint; float luminosity; if ( worldLight == vec3_origin ) { tint = vec3_origin; luminosity = 0.0f; } else { UTIL_GetNormalizedColorTintAndLuminosity( worldLight, &tint, &luminosity ); } // We only take a portion of the tint tint = (tint * 0.25f)+(Vector(0.75f,0.75f,0.75f)); // Rescale to a character range luminosity *= 255; if ( (m_fFlags & TE_EXPLFLAG_NOFIREBALLSMOKE) == 0 ) { // // Smoke - basic internal filler // for ( i = 0; i < 4; i++ ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Smoke, m_vecOrigin ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; #ifdef INVASION_CLIENT_DLL pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); #endif #ifdef _XBOX pParticle->m_flDieTime = 1.0f; #else pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f ); #endif pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( m_vecDirection * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 1, 750 ) * force; //Scale the force down as we fall away from our main direction ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread, &fForce ); pParticle->m_vecVelocity *= fForce; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( luminosity*0.5f, luminosity ); pParticle->m_uchColor[0] = ( worldLight[0] * nColor ); pParticle->m_uchColor[1] = ( worldLight[1] * nColor ); pParticle->m_uchColor[2] = ( worldLight[2] * nColor ); pParticle->m_uchStartSize = 72; pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f ); } } // // Inner core // #ifndef _XBOX for ( i = 0; i < 8; i++ ) { offset.Random( -16.0f, 16.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Smoke, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; #ifdef INVASION_CLIENT_DLL pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); #else pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); #endif pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( m_vecDirection * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 1, 2000 ) * force; //Scale the force down as we fall away from our main direction ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread, &fForce ); pParticle->m_vecVelocity *= fForce; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( luminosity*0.5f, luminosity ); pParticle->m_uchColor[0] = ( worldLight[0] * nColor ); pParticle->m_uchColor[1] = ( worldLight[1] * nColor ); pParticle->m_uchColor[2] = ( worldLight[2] * nColor ); pParticle->m_uchStartSize = random->RandomInt( 32, 64 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2; pParticle->m_uchStartAlpha = random->RandomFloat( 128, 255 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } #endif // !_XBOX // // Ground ring // Vector vRight, vUp; VectorVectors( m_vecDirection, vRight, vUp ); Vector forward; #ifndef INVASION_CLIENT_DLL #ifndef _XBOX int numRingSprites = 32; #else int numRingSprites = 8; #endif float flIncr = (2*M_PI) / (float) numRingSprites; // Radians float flYaw = 0.0f; for ( i = 0; i < numRingSprites; i++ ) { flYaw += flIncr; SinCos( flYaw, &forward.y, &forward.x ); forward.z = 0.0f; offset = ( RandomVector( -4.0f, 4.0f ) + m_vecOrigin ) + ( forward * random->RandomFloat( 8.0f, 16.0f ) ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Smoke, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.5f ); pParticle->m_vecVelocity = forward; float fForce = random->RandomFloat( 500, 2000 ) * force; //Scale the force down as we fall away from our main direction ScaleForceByDeviation( pParticle->m_vecVelocity, pParticle->m_vecVelocity, spread, &fForce ); pParticle->m_vecVelocity *= fForce; #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( luminosity*0.5f, luminosity ); pParticle->m_uchColor[0] = ( worldLight[0] * nColor ); pParticle->m_uchColor[1] = ( worldLight[1] * nColor ); pParticle->m_uchColor[2] = ( worldLight[2] * nColor ); pParticle->m_uchStartSize = random->RandomInt( 16, 32 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomFloat( 16, 32 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } #endif } #ifndef _XBOX // // Embers // if ( m_Material_Embers[0] == NULL ) { m_Material_Embers[0] = pSimple->GetPMaterial( "effects/fire_embers1" ); } if ( m_Material_Embers[1] == NULL ) { m_Material_Embers[1] = pSimple->GetPMaterial( "effects/fire_embers2" ); } for ( i = 0; i < 16; i++ ) { offset.Random( -32.0f, 32.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_Embers[random->RandomInt(0,1)], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 2.0f, 3.0f ); pParticle->m_vecVelocity.Random( -spread*2, spread*2 ); pParticle->m_vecVelocity += m_vecDirection; VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 1.0f, 400.0f ); //Scale the force down as we fall away from our main direction float vDev = ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread ); pParticle->m_vecVelocity *= fForce * ( 16.0f * (vDev*vDev*0.5f) ); #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = nColor; pParticle->m_uchStartSize = random->RandomInt( 8, 16 ) * vDev; pParticle->m_uchStartSize = clamp( pParticle->m_uchStartSize, 4, 32 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); } } #endif // !_XBOX // // Fireballs // if ( m_Material_FireCloud == NULL ) { m_Material_FireCloud = pSimple->GetPMaterial( "effects/fire_cloud2" ); } #ifndef _XBOX int numFireballs = 32; #else int numFireballs = 16; #endif for ( i = 0; i < numFireballs; i++ ) { offset.Random( -48.0f, 48.0f ); offset += m_vecOrigin; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), m_Material_FireCloud, offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.2f, 0.4f ); pParticle->m_vecVelocity.Random( -spread*0.75f, spread*0.75f ); pParticle->m_vecVelocity += m_vecDirection; VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 400.0f, 800.0f ); //Scale the force down as we fall away from our main direction float vDev = ScaleForceByDeviation( pParticle->m_vecVelocity, m_vecDirection, spread ); pParticle->m_vecVelocity *= fForce * ( 16.0f * (vDev*vDev*0.5f) ); #if __EXPLOSION_DEBUG debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 ); #endif int nColor = random->RandomInt( 128, 255 ); pParticle->m_uchColor[0] = pParticle->m_uchColor[1] = pParticle->m_uchColor[2] = nColor; pParticle->m_uchStartSize = random->RandomInt( 32, 85 ) * vDev; pParticle->m_uchStartSize = clamp( pParticle->m_uchStartSize, 32, 85 ); pParticle->m_uchEndSize = (int)((float)pParticle->m_uchStartSize * 1.5f); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f ); } } }
//----------------------------------------------------------------------------- // Purpose: Tesla effect //----------------------------------------------------------------------------- void C_EntityDissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset ) { Vector vecOrigin; QAngle vecAngles; MatrixGetColumn( hitboxToWorld, 3, vecOrigin ); MatrixAngles( hitboxToWorld, vecAngles.Base() ); C_BaseEntity *pEntity = GetMoveParent(); // Make a couple of tries at it int iTries = -1; Vector vecForward; trace_t tr; do { iTries++; // Some beams are deliberatly aimed around the point, the rest are random. if ( !bRandom ) { QAngle vecTemp = vecAngles; vecTemp[YAW] += flYawOffset; AngleVectors( vecTemp, &vecForward ); // Randomly angle it up or down vecForward.z = RandomFloat( -1, 1 ); } else { vecForward = RandomVector( -1, 1 ); } UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr ); } while ( tr.fraction >= 1.0 && iTries < 3 ); Vector vecEnd = tr.endpos - (vecForward * 8); // Only spark & glow if we hit something if ( tr.fraction < 1.0 ) { if ( !EffectOccluded( tr.endpos ) ) { // Move it towards the camera Vector vecFlash = tr.endpos; Vector vecForward; AngleVectors( MainViewAngles(), &vecForward ); vecFlash -= (vecForward * 8); g_pEffects->EnergySplash( vecFlash, -vecForward, false ); // End glow CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" ); pSimple->SetSortOrigin( vecFlash ); SimpleParticle *pParticle; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = RandomFloat( 0.5, 1 ); pParticle->m_vecVelocity = vec3_origin; Vector color( 1,1,1 ); float colorRamp = RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = RandomFloat( 6,13 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 10; pParticle->m_flRoll = RandomFloat( 0,360 ); pParticle->m_flRollDelta = 0; } } } // Build the tesla FX_BuildTesla( pEntity, vecOrigin, tr.endpos ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseExplosionEffect::CreateDebris( void ) { if ( m_fFlags & TE_EXPLFLAG_NOPARTICLES ) return; // // Sparks // CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "CreateDebris 1" ); if ( pSparkEmitter == NULL ) { assert(0); return; } if ( m_Material_FireCloud == NULL ) { m_Material_FireCloud = pSparkEmitter->GetPMaterial( "effects/fire_cloud2" ); } pSparkEmitter->SetSortOrigin( m_vecOrigin ); pSparkEmitter->m_ParticleCollision.SetGravity( 200.0f ); pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); pSparkEmitter->SetVelocityDampen( 8.0f ); // Set our bbox, don't auto-calculate it! pSparkEmitter->GetBinding().SetBBox( m_vecOrigin - Vector( 128, 128, 128 ), m_vecOrigin + Vector( 128, 128, 128 ) ); #ifndef _XBOX int numSparks = random->RandomInt( 8, 16 ); #else int numSparks = random->RandomInt( 2, 4 ); #endif Vector dir; float spread = 1.0f; TrailParticle *tParticle; // Dump out sparks int i; for ( i = 0; i < numSparks; i++ ) { tParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), m_Material_FireCloud, m_vecOrigin ); if ( tParticle == NULL ) break; tParticle->m_flLifetime = 0.0f; tParticle->m_flDieTime = random->RandomFloat( 0.1f, 0.15f ); dir.Random( -spread, spread ); dir += m_vecDirection; VectorNormalize( dir ); tParticle->m_flWidth = random->RandomFloat( 2.0f, 16.0f ); tParticle->m_flLength = random->RandomFloat( 0.05f, 0.1f ); tParticle->m_vecVelocity = dir * random->RandomFloat( 1500, 2500 ); Color32Init( tParticle->m_color, 255, 255, 255, 255 ); } #ifndef _XBOX // // Chunks // Vector offset; CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "CreateDebris 2", m_vecOrigin, Vector(128,128,128) ); if ( !fleckEmitter ) return; // Setup our collision information fleckEmitter->m_ParticleCollision.Setup( m_vecOrigin, &m_vecDirection, 0.9f, 512, 1024, 800, 0.5f ); #ifdef _XBOX int numFlecks = random->RandomInt( 8, 16 ); #else int numFlecks = random->RandomInt( 16, 32 ); #endif // _XBOX // Dump out flecks for ( i = 0; i < numFlecks; i++ ) { offset = m_vecOrigin + ( m_vecDirection * 16.0f ); offset[0] += random->RandomFloat( -8.0f, 8.0f ); offset[1] += random->RandomFloat( -8.0f, 8.0f ); offset[2] += random->RandomFloat( -8.0f, 8.0f ); FleckParticle *pParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), g_Mat_Fleck_Cement[random->RandomInt(0,1)], offset ); if ( pParticle == NULL ) break; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 3.0f; dir[0] = m_vecDirection[0] + random->RandomFloat( -1.0f, 1.0f ); dir[1] = m_vecDirection[1] + random->RandomFloat( -1.0f, 1.0f ); dir[2] = m_vecDirection[2] + random->RandomFloat( -1.0f, 1.0f ); pParticle->m_uchSize = random->RandomInt( 1, 3 ); VectorNormalize( dir ); float fForce = ( random->RandomFloat( 64, 256 ) * ( 4 - pParticle->m_uchSize ) ); float fDev = ScaleForceByDeviation( dir, m_vecDirection, 0.8f ); pParticle->m_vecVelocity = dir * ( fForce * ( 16.0f * (fDev*fDev*0.5f) ) ); pParticle->m_flRoll = random->RandomFloat( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( 0, 360 ); float colorRamp = random->RandomFloat( 0.5f, 1.5f ); pParticle->m_uchColor[0] = min( 1.0f, 0.25f*colorRamp )*255.0f; pParticle->m_uchColor[1] = min( 1.0f, 0.25f*colorRamp )*255.0f; pParticle->m_uchColor[2] = min( 1.0f, 0.25f*colorRamp )*255.0f; } #endif // !_XBOX }