void FX_GrenadeAltThink( centity_t *cent, const struct weaponInfo_s *weapon ) { vec3_t dir, org; VectorCopy( cent->gent->s.pos.trDelta, dir ); VectorNormalize( dir ); // Move away from the ent origin so that the glow doesn't clip into the model so much. VectorMA( cent->lerpOrigin, 1.4, dir, org ); FX_AddQuad( org, dir, NULL, NULL, 12.0f + random() * 32.0f, 0.0f, 0.75f, 0.75f, 0, 0, 0.0f, 1, cgs.media.dkorangeParticleShader ); if ( rand() & 1 ) FX_AddQuad( org, dir, NULL, NULL, 28.0f + random() * 32.0f, 0.0f, 0.5f, 0.5f, 0, 0, 0.0f, 1, cgs.media.yellowParticleShader ); if ( cent->gent ) { vec3_t rgb = { 1.0f, 1.0f, 0.4f }, rgb2 = { 1.0f, 0.5f, 0.0f }; // This flag controls whether or not the thing was initial fire, or shrapnel if ( cent->gent->trigger_formation ) // Shot from first person so beef it up a bit... FX_AddLine( cent->lerpOrigin, cent->gent->pos2, 1.0f, 4.0f, 8.0f, 0.7f, 0.1f, rgb, rgb2, 200, cgs.media.whiteLaserShader ); else FX_AddLine( cent->lerpOrigin, cent->gent->pos2, 1.0f, 16.0f, 4.0f, 0.2f, 0.1f, rgb, rgb2, 100, cgs.media.whiteLaserShader ); VectorCopy( cent->lerpOrigin, cent->gent->pos2 ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &normal - // scale - //----------------------------------------------------------------------------- void FX_WaterRipple( const Vector &origin, float scale, Vector *pColor, float flLifetime, float flAlpha ) { VPROF_BUDGET( "FX_WaterRipple", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); trace_t tr; Vector color = pColor ? *pColor : Vector( 0.8f, 0.8f, 0.75f ); Vector startPos = origin + Vector(0,0,8); Vector endPos = origin + Vector(0,0,-64); UTIL_TraceLine( startPos, endPos, MASK_WATER, NULL, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction < 1.0f ) { //Add a ripple quad to the surface FX_AddQuad( tr.endpos + ( tr.plane.normal * 0.5f ), tr.plane.normal, 16.0f*scale, 128.0f*scale, 0.7f, flAlpha, // start alpha 0.0f, // end alpha 0.25f, random->RandomFloat( 0, 360 ), random->RandomFloat( -16.0f, 16.0f ), color, flLifetime, "effects/splashwake1", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); } }
//----------------------------------------------------------------------------- // Purpose: Parameter heavy version //----------------------------------------------------------------------------- void FX_AddQuad( const Vector &origin, const Vector &normal, float startSize, float endSize, float sizeBias, float startAlpha, float endAlpha, float alphaBias, float yaw, float deltaYaw, const Vector &color, float lifeTime, const char *shader, unsigned int flags ) { FXQuadData_t data; //Setup the data data.SetAlpha( startAlpha, endAlpha ); data.SetScale( startSize, endSize ); data.SetFlags( flags ); data.SetMaterial( shader ); data.SetNormal( normal ); data.SetOrigin( origin ); data.SetLifeTime( lifeTime ); data.SetColor( color[0], color[1], color[2] ); data.SetScaleBias( sizeBias ); data.SetAlphaBias( alphaBias ); data.SetYaw( yaw, deltaYaw ); //Output it FX_AddQuad( data ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int C_MortarShell::DrawModel( int flags ) { if ( gpGlobals->frametime <= 0.0f ) return 0; float flPerc; bool ending; // See if we're in the beginning phase if ( gpGlobals->curtime < ( m_flStarttime + m_flLifespan ) ) { flPerc = GetStartPerc(); ending = false; } else { flPerc = GetEndPerc(); ending = true; } float flAlpha = ALPHA_MIN + ( ( ALPHA_MAX - ALPHA_MIN ) * flPerc ); float flScale = ( ending ) ? m_flRadius : ( (m_flRadius*0.1f)+ ( ( m_flRadius - (m_flRadius*0.1f) ) * flPerc ) ); // Do the ground effect FX_AddQuad( GetAbsOrigin() + ( m_vecSurfaceNormal * 2.0f ), m_vecSurfaceNormal, flScale, flScale, 1.0f, flAlpha, flAlpha, 1.0f, 0, 0, Vector( 1.0f, 1.0f, 1.0f ), 0.0001f, "effects/combinemuzzle2_nocull", 0 ); if ( !ending ) { // Add extra effects on startup AddRisingParticles( flPerc ); } else { // Add exploding particles after the impact AddExplodingParticles( flPerc ); } return 1; }
//----------------------------------------------------------------------------- // Purpose: // Input : &data - //----------------------------------------------------------------------------- void CombineBallImpactCallback( const CEffectData &data ) { // Quick flash FX_AddQuad( data.m_vOrigin, data.m_vNormal, data.m_flRadius * 10.0f, 0, 0.75f, 1.0f, 0.0f, 0.4f, random->RandomInt( 0, 360 ), 0, Vector( 1.0f, 1.0f, 1.0f ), 0.25f, "effects/combinemuzzle1_nocull", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); // Lingering burn FX_AddQuad( data.m_vOrigin, data.m_vNormal, data.m_flRadius * 2.0f, data.m_flRadius * 4.0f, 0.75f, 1.0f, 0.0f, 0.4f, random->RandomInt( 0, 360 ), 0, Vector( 1.0f, 1.0f, 1.0f ), 0.5f, "effects/combinemuzzle2_nocull", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); // Throw sparks FX_ElectricSpark( data.m_vOrigin, 2, 1, &data.m_vNormal ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &data - //----------------------------------------------------------------------------- void AR2ImpactCallback( const CEffectData &data ) { FX_AddQuad( data.m_vOrigin, data.m_vNormal, random->RandomFloat( 24, 32 ), 0, 0.75f, 1.0f, 0.0f, 0.4f, random->RandomInt( 0, 360 ), 0, Vector( 1.0f, 1.0f, 1.0f ), 0.25f, "effects/combinemuzzle2_nocull", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); }
void FX_BlowBits( vec3_t start, vec3_t end, vec3_t dir, vec3_t user ) { vec3_t diff, org; float len; FXLine *fx; VectorSubtract( end, start, diff ); len = VectorNormalize( diff ) * ( 0.2 + random() * 0.3 ); VectorMA( start, len, diff, org ); fx = FX_AddLine( end, start, (int)(random() * 3.2f), 2.0f + random() * 2, 0, 0.5f, 0.1f, 150 + random() * 150, cgs.media.orangeTrailShader ); if ( fx == NULL ) return; fx->SetFlags( FXF_SHRINK ); FX_AddQuad( end, dir, NULL, NULL, 1.0f, 64.0f, 1.0, 0.0, random() * 360.0f, 0.0f, 0.0, 200, cgs.media.orangeRingShader ); // FX_AddQuad( end, dir, NULL, NULL, 20.0, -15.0, 0.6, 0.4, 0.0,0.0,0.0,450, cgs.media.borgEyeFlareShader ); }
void FX_GrenadeExplode( vec3_t origin, vec3_t normal ) { localEntity_t *le; FXTrail *fx; vec3_t direction, org; VectorSet( direction, 0,0,1 ); // Add an explosion and tag a light to it le = CG_MakeExplosion( origin, direction, cgs.media.nukeModel, 5, NULL, 250, qfalse, 25.0f, LEF_FADE_RGB ); le->light = 150; le->refEntity.renderfx |= RF_NOSHADOW; VectorSet( le->lightColor, 1.0f, 0.6f, 0.2f ); // Ground ring FX_AddQuad( origin, normal, NULL, NULL, 5, 330, 1.0, 0.0, random() * 360, 0, 0, 300, cgs.media.bigShockShader ); // Flare VectorMA( origin, 12, direction, org ); FX_AddSprite( org, NULL, NULL, 160.0, -540.0, 1.0, 0.0, 0.0, 0.0, 200, cgs.media.sunnyFlareShader ); for ( int i = 0; i < 12; i++) { fx = FX_AddTrail( origin, NULL, NULL, 24.0f + random() * 12, -40.0f, 0.5 + random() * 2, -3.0, 1.0f, 1.0f, 0.5f, 1000.0f, cgs.media.orangeTrailShader, rand() & FXF_BOUNCE ); if ( fx == NULL ) return; FXE_Spray( normal, 470, 325, 0.5f, 700, (FXPrimitive *) fx ); } cgi_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.grenadeExplodeSnd ); // Smoke and impact CG_ImpactMark( cgs.media.compressionMarkShader, origin, normal, random()*360, 1,1,1,1.0, qfalse, random() * 16 + 48, qfalse ); CG_ExplosionEffects( origin, 3.0f, 400 ); }
//----------------------------------------------------------------------------- // Purpose: Draw a cheap glow quad at our impact point (with sparks) //----------------------------------------------------------------------------- void StunstickImpactCallback( const CEffectData &data ) { float scale = random->RandomFloat( 16, 32 ); FX_AddQuad( data.m_vOrigin, data.m_vNormal, scale, scale*2.0f, 1.0f, 1.0f, 0.0f, 0.0f, random->RandomInt( 0, 360 ), 0, Vector( 1.0f, 1.0f, 1.0f ), 0.1f, "sprites/light_glow02_add", 0 ); FX_Sparks( data.m_vOrigin, 1, 2, data.m_vNormal, 6, 64, 256 ); }
void FX_GrenadeExplode( vec3_t origin, vec3_t normal ) { localEntity_t *le; qhandle_t null = 0; vec3_t direction, org, vel; int i; VectorSet( direction, 0,0,1 ); // Add an explosion and tag a light to it le = CG_MakeExplosion2( origin, direction, cgs.media.nukeModel, 5, null, 250, qfalse, 25.0f, LEF_FADE_RGB); le->light = 150; le->refEntity.renderfx |= RF_NOSHADOW; VectorSet( le->lightColor, 1.0f, 0.6f, 0.2f ); // Ground ring FX_AddQuad( origin, normal, 5, 100, 1.0, 0.0, random() * 360, 300, cgs.media.bigShockShader ); // Flare VectorMA( origin, 12, direction, org ); FX_AddSprite( org, NULL, qfalse, 160.0, -160.0, 1.0, 0.0, 0.0, 0.0, 200, cgs.media.sunnyFlareShader );//, FXF_NON_LINEAR_FADE ); for (i = 0; i < 12; i++) { float width, length; FXE_Spray( normal, 470, 325, 0.5f, vel); length = 24.0 + random() * 12; width = 0.5 + random() * 2; FX_AddTrail( origin, vel, qtrue, length, -length, width, -width, 1.0f, 1.0f, 0.5f, 1000.0f, cgs.media.orangeTrailShader); } trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.grenadeExplodeSound ); // Smoke and impact // FX_AddSpawner( origin, normal, NULL, NULL, 100, 25.0f, 2000.0f, (void *) CG_SmokeSpawn, NULL, 1024 ); CG_ImpactMark( cgs.media.compressionMarkShader, origin, normal, random()*360, 1,1,1,1.0, qfalse, random() * 16 + 48, qfalse ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &normal - // scale - //----------------------------------------------------------------------------- void FX_AirboatGunImpact( const Vector &origin, const Vector &normal, float scale ) { #ifdef _XBOX Vector offset = origin + ( normal * 1.0f ); CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create( "FX_MetalSpark 1" ); if ( sparkEmitter == NULL ) return; //Setup our information sparkEmitter->SetSortOrigin( offset ); sparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN ); sparkEmitter->SetVelocityDampen( 8.0f ); sparkEmitter->SetGravity( 800.0f ); sparkEmitter->SetCollisionDamped( 0.25f ); sparkEmitter->GetBinding().SetBBox( offset - Vector( 32, 32, 32 ), offset + Vector( 32, 32, 32 ) ); int numSparks = random->RandomInt( 4, 8 ); TrailParticle *pParticle; PMaterialHandle hMaterial = sparkEmitter->GetPMaterial( "effects/spark" ); Vector dir; float length = 0.1f; //Dump out sparks for ( int i = 0; i < numSparks; i++ ) { pParticle = (TrailParticle *) sparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, offset ); if ( pParticle == NULL ) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.05f, 0.1f ); float spreadOfs = random->RandomFloat( 0.0f, 2.0f ); dir[0] = normal[0] + random->RandomFloat( -(0.5f*spreadOfs), (0.5f*spreadOfs) ); dir[1] = normal[1] + random->RandomFloat( -(0.5f*spreadOfs), (0.5f*spreadOfs) ); dir[2] = normal[2] + random->RandomFloat( -(0.5f*spreadOfs), (0.5f*spreadOfs) ); VectorNormalize( dir ); pParticle->m_flWidth = random->RandomFloat( 1.0f, 4.0f ); pParticle->m_flLength = random->RandomFloat( length*0.25f, length ); pParticle->m_vecVelocity = dir * random->RandomFloat( (128.0f*(2.0f-spreadOfs)), (512.0f*(2.0f-spreadOfs)) ); Color32Init( pParticle->m_color, 255, 255, 255, 255 ); } #else // Normal metal spark FX_MetalSpark( origin, normal, normal, (int) scale ); #endif // _XBOX // Add a quad to highlite the hit point FX_AddQuad( origin, normal, random->RandomFloat( 16, 32 ), random->RandomFloat( 32, 48 ), 0.75f, 1.0f, 0.0f, 0.4f, random->RandomInt( 0, 360 ), 0, Vector( 1.0f, 1.0f, 1.0f ), 0.05f, "effects/combinemuzzle2_nocull", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_WaterExplosionEffect::CreateCore( void ) { if ( m_fFlags & TE_EXPLFLAG_NOFIREBALL ) return; // Get our lighting information for the water surface Vector color; float luminosity; FX_GetSplashLighting( m_vecWaterSurface + Vector( 0, 0, 8 ), &color, &luminosity ); float lifetime = random->RandomFloat( 0.8f, 1.0f ); // Ground splash FX_AddQuad( m_vecWaterSurface + Vector(0,0,2), Vector(0,0,1), 64, 64 * 4.0f, 0.85f, luminosity, 0.0f, 0.25f, random->RandomInt( 0, 360 ), random->RandomFloat( -4, 4 ), color, 2.0f, "effects/splashwake1", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); Vector vRight, vUp; VectorVectors( Vector(0,0,1) , vRight, vUp ); Vector start, end; float radius = 50.0f; unsigned int flags; // Base vertical shaft FXLineData_t lineData; start = m_vecWaterSurface; end = start + ( Vector( 0, 0, 1 ) * random->RandomFloat( radius, radius*1.5f ) ); if ( random->RandomInt( 0, 1 ) ) { flags |= FXSTATICLINE_FLIP_HORIZONTAL; } else { flags = 0; } lineData.m_flDieTime = lifetime * 0.5f; lineData.m_flStartAlpha= luminosity; lineData.m_flEndAlpha = 0.0f; lineData.m_flStartScale = radius*0.5f; lineData.m_flEndScale = radius*2; lineData.m_pMaterial = materials->FindMaterial( "effects/splash3", 0, 0 ); lineData.m_vecStart = start; lineData.m_vecStartVelocity = vec3_origin; lineData.m_vecEnd = end; lineData.m_vecEndVelocity = Vector(0,0,random->RandomFloat( 650, 750 )); FX_AddLine( lineData ); // Inner filler shaft start = m_vecWaterSurface; end = start + ( Vector(0,0,1) * random->RandomFloat( 32, 64 ) ); if ( random->RandomInt( 0, 1 ) ) { flags |= FXSTATICLINE_FLIP_HORIZONTAL; } else { flags = 0; } lineData.m_flDieTime = lifetime * 0.5f; lineData.m_flStartAlpha= luminosity; lineData.m_flEndAlpha = 0.0f; lineData.m_flStartScale = radius; lineData.m_flEndScale = radius*2; lineData.m_pMaterial = materials->FindMaterial( "effects/splash3", 0, 0 ); lineData.m_vecStart = start; lineData.m_vecStartVelocity = vec3_origin; lineData.m_vecEnd = end; lineData.m_vecEndVelocity = Vector(0,0,1) * random->RandomFloat( 64, 128 ); FX_AddLine( lineData ); }
void FX_MetalSpark(const Vector &position, const Vector &direction, const Vector &surfaceNormal, int iScale) { VPROF_BUDGET("FX_MetalSpark", VPROF_BUDGETGROUP_PARTICLE_RENDERING); if (!fx_drawmetalspark.GetBool()) return; // // Emitted particles // Vector offset = position + (surfaceNormal * 1.0f); CSmartPtr<CTrailParticles> sparkEmitter = CTrailParticles::Create("FX_MetalSpark 1"); if (sparkEmitter == NULL) return; //Setup our information sparkEmitter->SetSortOrigin(offset); sparkEmitter->SetFlag(bitsPARTICLE_TRAIL_VELOCITY_DAMPEN); sparkEmitter->SetVelocityDampen(8.0f); sparkEmitter->SetGravity(METAL_SPARK_GRAVITY); sparkEmitter->SetCollisionDamped(METAL_SPARK_DAMPEN); sparkEmitter->GetBinding().SetBBox(offset - Vector(32, 32, 32), offset + Vector(32, 32, 32)); int numSparks = random->RandomInt(4, 8) * (iScale * 2); numSparks = (int) (0.5f + (float) numSparks * g_pParticleSystemMgr->ParticleThrottleScaling()); if (g_Material_Spark == NULL) { g_Material_Spark = sparkEmitter->GetPMaterial("effects/spark"); } TrailParticle *pParticle; Vector dir; float length = 0.1f; //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; if (iScale > 1 && i % 3 == 0) { // Every third spark goes flying far if we're having a big batch of sparks. pParticle->m_flDieTime = random->RandomFloat(0.15f, 0.25f); } else { pParticle->m_flDieTime = random->RandomFloat(0.05f, 0.1f); } float spreadOfs = random->RandomFloat(0.0f, 2.0f); dir[0] = direction[0] + random->RandomFloat(-(METAL_SPARK_SPREAD*spreadOfs), (METAL_SPARK_SPREAD*spreadOfs)); dir[1] = direction[1] + random->RandomFloat(-(METAL_SPARK_SPREAD*spreadOfs), (METAL_SPARK_SPREAD*spreadOfs)); dir[2] = direction[2] + random->RandomFloat(-(METAL_SPARK_SPREAD*spreadOfs), (METAL_SPARK_SPREAD*spreadOfs)); VectorNormalize(dir); pParticle->m_flWidth = random->RandomFloat(1.0f, 4.0f); pParticle->m_flLength = random->RandomFloat(length*0.25f, length); pParticle->m_vecVelocity = dir * random->RandomFloat((METAL_SPARK_MINSPEED*(2.0f - spreadOfs)), (METAL_SPARK_MAXSPEED*(2.0f - spreadOfs))); Color32Init(pParticle->m_color, 255, 255, 255, 255); } // // Impact point glow // FXQuadData_t data; data.SetMaterial("effects/yellowflare"); data.SetColor(1.0f, 1.0f, 1.0f); data.SetOrigin(offset); data.SetNormal(surfaceNormal); data.SetAlpha(1.0f, 0.0f); data.SetLifeTime(0.1f); data.SetYaw(random->RandomInt(0, 360)); int scale = random->RandomInt(24, 28); data.SetScale(scale, 0); FX_AddQuad(data); }
void FX_PhaserAltFire( vec3_t start, vec3_t end, vec3_t normal, qboolean spark, qboolean impact, qboolean empty ) { float scale = flrandom(13.0f, 17.0f), scale2 = flrandom(2.0f, 6.0f); vec3_t vel, diff, end2; int i = 0, sparks = 0; refEntity_t beam; vec3_t rgb = { 1,0.6,0.5}, rgb2={1,0.3,0}; float len; int color; VectorSubtract(end, start, diff); len = VectorNormalize(diff); color = 0xff * flrandom(0.75, 1.0); if (empty) { // More faint and shaky line. scale *= flrandom(0.25,0.75); } if (len > PHASER_ALT_CONE_LEN) { // Draw beam in two parts... // Draw main beam first. VectorMA(start, PHASER_ALT_CONE_LEN, diff, end2); // Draw starting cone memset( &beam, 0, sizeof( beam ) ); VectorCopy( start, beam.origin); VectorCopy( end2, beam.oldorigin ); beam.reType = RT_LINE2; if (empty) { beam.customShader = cgs.media.phaserAltEmptyShader; } else { beam.customShader = cgs.media.phaserAltShader; } AxisClear( beam.axis ); beam.shaderRGBA[0] = 0xff; beam.shaderRGBA[1] = 0xff*0.3; beam.shaderRGBA[2] = 0; beam.shaderRGBA[3] = 0xff; beam.data.line.width = scale*0.1; beam.data.line.width2 = scale; beam.data.line.stscale = 1.0; trap_R_AddRefEntityToScene( &beam ); // Draw big thick normal beam for the rest. memset( &beam, 0, sizeof( beam ) ); VectorCopy( end2, beam.oldorigin); VectorCopy( end, beam.origin ); beam.reType = RT_LINE; if (empty) { beam.customShader = cgs.media.phaserAltEmptyShader; } else { beam.customShader = cgs.media.phaserAltShader; } AxisClear( beam.axis ); beam.shaderRGBA[0] = 0xff; beam.shaderRGBA[1] = 0xff*0.3; beam.shaderRGBA[2] = 0; beam.shaderRGBA[3] = 0xff; beam.data.line.width = scale; beam.data.line.stscale = 1.0; trap_R_AddRefEntityToScene( &beam ); // Draw beam core, all one bit. memset( &beam, 0, sizeof( beam ) ); VectorCopy( start, beam.origin); VectorCopy( end, beam.oldorigin ); beam.reType = RT_LINE2; beam.customShader = cgs.media.phaserShader; AxisClear( beam.axis ); beam.shaderRGBA[0] = color*0.75f; beam.shaderRGBA[1] = 0xff*0.5f; beam.shaderRGBA[2] = 0xff*0.5f; beam.shaderRGBA[3] = 0xff; beam.data.line.width = scale2*0.2; beam.data.line.width2 = scale2; beam.data.line.stscale = 1.0; trap_R_AddRefEntityToScene( &beam ); } else { // Draw beam in two parts... // Draw beam first. memset( &beam, 0, sizeof( beam ) ); VectorCopy( start, beam.origin); VectorCopy( end, beam.oldorigin ); beam.reType = RT_LINE2; beam.customShader = cgs.media.phaserAltShader; AxisClear( beam.axis ); beam.shaderRGBA[0] = 0xff; beam.shaderRGBA[1] = 0xff*0.3; beam.shaderRGBA[2] = 0; beam.shaderRGBA[3] = 0xff; beam.data.line.width = scale*0.1; beam.data.line.width2 = scale; beam.data.line.stscale = 1.0; trap_R_AddRefEntityToScene( &beam ); // just one beam is never enough memset( &beam, 0, sizeof( beam ) ); VectorCopy( start, beam.origin); VectorCopy( end, beam.oldorigin ); beam.reType = RT_LINE2; beam.customShader = cgs.media.phaserShader; AxisClear( beam.axis ); beam.shaderRGBA[0] = color*0.75f; beam.shaderRGBA[1] = 0xff*0.5f; beam.shaderRGBA[2] = 0xff*0.5f; beam.shaderRGBA[3] = 0xff; beam.data.line.width = scale2*0.2; beam.data.line.width2 = scale2; beam.data.line.stscale = 1.0; trap_R_AddRefEntityToScene( &beam ); } // Phaser beam // FX_AddLine( start, end, 1.0f, scale, 0.0f, 0.9f, 0.9f, 2, cgs.media.phaserShader ); // FX_AddLine( start, end, 1.0f, scale * 0.5f, 0.0f, 0.8f, 0.8f, 2, cgs.media.phaserShader ); // Per frame impact mark FX_AddQuad( end, normal, random() * 1.5 + 1.75f, 0.0f, 1.0f, 0.0f, 0.0f, 1, cgs.media.sparkShader ); FX_AddQuad( end, normal, random() * 5 + 2.75f, 0.0f, 1.0f, 0.0f, 0.0f, 1, cgs.media.yellowParticleShader ); // Multi frame impacts--never do this when it hits a player because it will just look stupid if ( impact ) { FX_AddQuad2( end, normal, random() * 2.0 + 5.0f, 2.5f, 0.6f, 0.0f, rgb, rgb2, 0.0f, 500 + random() * 200, cgs.media.sunnyFlareShader ); CG_ImpactMark( cgs.media.scavMarkShader, end, normal, random()*360, 1,1,1,0.1, qfalse, random() + 6.0, qfalse ); } // "Fun" sparks if ( spark ) { // kef -- fixme. dunno what the deal is with this velocity vector VectorClear(vel); sparks = (rand() & 3) + 1; // Set random starting pos... end2[0] = flrandom(-1.0, 1.0) + end[0]; end2[1] = flrandom(-1.0, 1.0) + end[1]; end2[2] = flrandom(-1.0, 1.0) + end[2]; for( i = 0; i < sparks; i++ ) { scale = 0.5f + (random() * 0.5); FXE_Spray( normal, 200, 75, 0.8f, /*1024*/vel); FX_AddTrail2( end2, vel, qfalse, 8.0f, -8.0f, scale, -scale, 0.5f, 0.0f, rgb, rgb2, 0.4f, 500.0f, cgs.media.sparkShader ); } VectorMA(end, -8, diff, end2); // Add a hit sprite over everything... memset( &beam, 0, sizeof( beam ) ); VectorCopy( end2, beam.origin); beam.reType = RT_SPRITE; beam.customShader = cgs.media.sunnyFlareShader; AxisClear( beam.axis ); beam.shaderRGBA[0] = 0xff*1.0f; beam.shaderRGBA[1] = 0xff*0.9f; beam.shaderRGBA[2] = 0xff*0.8f; beam.shaderRGBA[3] = 0xff; beam.data.sprite.radius = random()*2.0 + 9.0; trap_R_AddRefEntityToScene( &beam ); } }
void FX_EnergySplash(const Vector &pos, const Vector &normal, int nFlags) { VPROF_BUDGET("FX_EnergySplash", VPROF_BUDGETGROUP_PARTICLE_RENDERING); Vector offset = pos + (normal * 2.0f); // Quick flash FX_AddQuad(pos, normal, 64.0f, 0, 0.75f, 1.0f, 0.0f, 0.4f, random->RandomInt(0, 360), 0, Vector(1.0f, 1.0f, 1.0f), 0.25f, "effects/combinemuzzle1_nocull", (FXQUAD_BIAS_SCALE | FXQUAD_BIAS_ALPHA)); // Lingering burn FX_AddQuad(pos, normal, 16, 32, 0.75f, 1.0f, 0.0f, 0.4f, random->RandomInt(0, 360), 0, Vector(1.0f, 1.0f, 1.0f), 0.5f, "effects/combinemuzzle2_nocull", (FXQUAD_BIAS_SCALE | FXQUAD_BIAS_ALPHA)); SimpleParticle *sParticle; CSmartPtr<CSimpleEmitter> pEmitter; pEmitter = CSimpleEmitter::Create("C_EntityDissolve"); pEmitter->SetSortOrigin(pos); if (g_Material_Spark == NULL) { g_Material_Spark = pEmitter->GetPMaterial("effects/spark"); } // Anime ground effects for (int j = 0; j < 8; j++) { offset.x = random->RandomFloat(-8.0f, 8.0f); offset.y = random->RandomFloat(-8.0f, 8.0f); offset.z = random->RandomFloat(0.0f, 4.0f); offset += pos; sParticle = (SimpleParticle *) pEmitter->AddParticle(sizeof(SimpleParticle), g_Material_Spark, offset); if (sParticle == NULL) return; sParticle->m_vecVelocity = Vector(Helper_RandomFloat(-4.0f, 4.0f), Helper_RandomFloat(-4.0f, 4.0f), Helper_RandomFloat(16.0f, 64.0f)); sParticle->m_uchStartSize = random->RandomFloat(2, 4); sParticle->m_flDieTime = random->RandomFloat(0.4f, 0.6f); sParticle->m_flLifetime = 0.0f; sParticle->m_flRoll = Helper_RandomInt(0, 360); float alpha = 255; sParticle->m_flRollDelta = Helper_RandomFloat(-4.0f, 4.0f); 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: // Input : &data - //----------------------------------------------------------------------------- void AR2ExplosionCallback( const CEffectData &data ) { float lifetime = random->RandomFloat( 0.4f, 0.75f ); // Ground splash FX_AddQuad( data.m_vOrigin, data.m_vNormal, data.m_flRadius, data.m_flRadius * 4.0f, 0.85f, 1.0f, 0.0f, 0.25f, random->RandomInt( 0, 360 ), random->RandomFloat( -4, 4 ), Vector( 1.0f, 1.0f, 1.0f ), lifetime, "effects/combinemuzzle1", (FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) ); Vector vRight, vUp; VectorVectors( data.m_vNormal, vRight, vUp ); Vector start, end; float radius = data.m_flRadius * 0.15f; // Base vertical shaft FXLineData_t lineData; start = data.m_vOrigin; end = start + ( data.m_vNormal * random->RandomFloat( radius*2.0f, radius*4.0f ) ); lineData.m_flDieTime = lifetime; lineData.m_flStartAlpha= 1.0f; lineData.m_flEndAlpha = 0.0f; lineData.m_flStartScale = radius*4; lineData.m_flEndScale = radius*5; lineData.m_pMaterial = materials->FindMaterial( "effects/ar2ground2", 0, 0 ); lineData.m_vecStart = start; lineData.m_vecStartVelocity = vec3_origin; lineData.m_vecEnd = end; lineData.m_vecEndVelocity = data.m_vNormal * random->RandomFloat( 200, 350 ); FX_AddLine( lineData ); // Inner filler shaft start = data.m_vOrigin; end = start + ( data.m_vNormal * random->RandomFloat( 16, radius*0.25f ) ); lineData.m_flDieTime = lifetime - 0.1f; lineData.m_flStartAlpha= 1.0f; lineData.m_flEndAlpha = 0.0f; lineData.m_flStartScale = radius*2; lineData.m_flEndScale = radius*4; lineData.m_pMaterial = materials->FindMaterial( "effects/ar2ground2", 0, 0 ); lineData.m_vecStart = start; lineData.m_vecStartVelocity = vec3_origin; lineData.m_vecEnd = end; lineData.m_vecEndVelocity = data.m_vNormal * random->RandomFloat( 64, 128 ); FX_AddLine( lineData ); }
//------------------------------------------------ void FX_ParasiteAcidHitWall( vec3_t origin, vec3_t dir ) //------------------------------------------------ { FXTrail *particle; float detail; vec3_t rgb={0.2f,0.8f,0.0f}; int i; // Spawn some smoke from the acid burn for ( i = 0; i < 4; i ++ ) { CG_Smoke( origin, dir, random() * 4.0f + 8.0f, random() * 16.0f + 2.0f, cgs.media.steamShader ); } FX_AddQuad( origin, dir, NULL, NULL, 4.0, 6.0, 0.5, 0.0, rgb, rgb, 0.0, 0.0, 0.0, 550, cgs.media.waterDropShader ); // Leave a melted spot CG_ImpactMark( cgs.media.bulletmarksShader, origin, dir, random()*360, 1,1,1,0.2f, qfalse, random() * 3.0f + 8.0, qfalse ); //Sound cgi_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cg_weapons[WP_PARASITE].missileHitSound ); // See if it's worth doing a splash detail = FX_DetailLevel( origin, 16, 400 ); if (detail == 0) return; // splash the acid for ( i = 0; i < 10; i++ ) { particle = FX_AddTrail( origin, NULL, NULL, 3.0f, -1.0f, 2.0, -1.0, 0.3f, 0.1f, rgb, rgb, 0.4f, 500.0f, cgs.media.waterDropShader, rand() & FXF_BOUNCE ); if ( particle != NULL ) { FXE_Spray( dir, 80, 100, 0.95f, 512, (FXPrimitive *) particle ); } } // Make a real splash vec3_t org; FXSprite *fx; vec3_t moveDir; vec3_t accel = { 0, 0, -400 }; for ( i = 0; i < 6; i++ ) { VectorSet( org, origin[0] + crandom() * 2.5f, origin[1] + crandom() * 2.5f, origin[2] + crandom() * 2.5f ); for ( int j = 0; j < 3; j++ ) { moveDir[j] = crandom() * 55.0; } moveDir[2] += 120.0f; VectorSet( rgb, random() * 0.3f + 0.2f, random() * 0.4f + 0.5f, random() * 0.2f + 0.05f ); fx = FX_AddSprite( org, moveDir, accel, 2.0f + ( random() * 1.0f ), -2.0f, 1.0f, 1.0f, rgb, rgb, 0, 0.0f, 400 + random() * 700, cgs.media.spooShader ); if ( fx == NULL ) return; fx->SetRoll( 0 ); } }
void FX_ProtonExplosion( vec3_t end, vec3_t dir ) { vec3_t org; // Move me away from the wall a bit so that I don't z-buffer into it VectorMA( end, 0.5, dir, org ); // Expanding rings // FX_AddQuad( org, dir, NULL, NULL, 1, 24, 0.8f, 0.2f, random() * 360, 360, 0, 400, cgs.media.protonRingShader ); // FX_AddQuad( org, dir, NULL, NULL, 1, 60, 0.8f, 0.2f, random() * 360, -360, 0, 300, cgs.media.protonRingShader ); // Impact effect // FX_AddQuad( org, dir, NULL, NULL, 7, 35, 1.0, 0.0, random() * 360, 0, 0, 500, cgs.media.blueParticleShader ); // FX_AddQuad( org, dir, NULL, NULL, 5, 25, 1.0, 0.0, random() * 360, 0, 0, 420, cgs.media.ltblueParticleShader ); // Test of using the ripple shader...... FX_AddQuad( org, dir, NULL, NULL, 13, 16, 1.0f, 0.1f, random() * 360, 360, 0, 400, cgs.media.rippleShader ); FX_AddQuad( org, dir, NULL, NULL, 9, 20, 0.8f, 0.1f, random() * 360, -360, 0, 300, cgs.media.rippleShader ); FX_AddQuad( org, dir, NULL, NULL, 20, 8, 1.0f, 0.1f, random() * 360, 0, 0, 300, cgs.media.rippleShader ); FX_AddQuad( org, dir, NULL, NULL, 30, -20, 1.0f, 0.8f, random() * 360, 0, 0, 300, cgs.media.waterDropShader ); /* localEntity_t *le; FXTrail *particle; vec3_t direction, new_org; vec3_t velocity = { 0, 0, 8 }; float scale, dscale; int i, numSparks; //Sparks numSparks = 4 + (random() * 4.0f); for ( i = 0; i < numSparks; i++ ) { scale = 0.25f + (random() * 2.0f); dscale = -scale * 0.5f; particle = FX_AddTrail( origin, NULL, NULL, 16.0f, -32.0f, scale, -scale, 1.0f, 1.0f, 0.25f, 2000.0f, cgs.media.sparkShader, rand() & FXF_BOUNCE ); if ( particle == NULL ) return; FXE_Spray( normal, 200, 50, 0.5f, 512, (FXPrimitive *) particle ); } // Smoke puff VectorMA( origin, 8, normal, new_org ); FX_AddSprite( new_org, velocity, NULL, 16.0f, 16.0f, 1.0f, 0.0f, random()*45.0f, 0.0f, 1000.0f, cgs.media.steamShader ); scale = 0.4f + ( random() * 0.2f); //Orient the explosions to face the camera VectorSubtract( cg.refdef.vieworg, origin, direction ); VectorNormalize( direction ); // Add in the explosion and tag it with a light le = CG_MakeExplosion( origin, direction, cgs.media.explosionModel, 6, cgs.media.electricalExplosionSlowShader, 475, qfalse, scale ); le->light = 150; le->refEntity.renderfx |= RF_NOSHADOW; VectorSet( le->lightColor, 0.8f, 0.8f, 1.0f ); // Scorch mark CG_ImpactMark( cgs.media.compressionMarkShader, origin, normal, random()*360, 1,1,1,1, qfalse, 4, qfalse ); CG_ExplosionEffects( origin, 1.0f, 150 ); */ }
//----------------------------------------------------------------------------- // 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 }
void FX_DisruptorWeaponHitWall( vec3_t origin, vec3_t dir, int size ) { vec3_t vel, /*accel,*/ hitpos, direction, org; //int i, t; weaponInfo_t *weaponInfo = &cg_weapons[WP_10]; CG_InitLensFlare( origin, 375, 375, colorTable[CT_GREEN], 1.2, 2.0, 1600, 200, colorTable[CT_GREEN], 1600, 200, 800, 20, qtrue, 0, 0, qfalse, qtrue, qfalse, 1.0, cg.time, 0, 0, 200); // Generate "crawling" electricity // eh, don't it doesn't look that great. FX_DisruptorDischarge( origin, dir, NUM_DISCHARGES, DISCHARGE_DIST, DISCHARGE_SIDE_DIST ); VectorMA(origin, size, dir, hitpos); // Set an oriented residual glow effect FX_AddQuad( hitpos, dir, size * size * 15.0f, -150.0f, 1.0f, 0.0f, 0, 300, cgs.media.greenParticleShader ); CG_ImpactMark( cgs.media.scavMarkShader, origin, dir, random()*360, 1,1,1,0.6, qfalse, size * 12 + 1, qfalse ); FX_AddSprite( hitpos, NULL, qfalse, size * size * 15.0f, -150.0f, 1.0f, 0.0f, 360*random(), 0, 400, cgs.media.greenParticleShader ); /* FX_AddSprite( hitpos, NULL, qfalse, size * size * 15.0f, -150.0f, 1.0f, 0.0f, 360*random(), 0, 400, cgs.media.greenParticleStreakShader ); */ FX_AddSprite( hitpos, NULL, qfalse, size * size * 25.0f, -150.0f, 1.0f, 0.0f, 0.0f, 0, 400, cgs.media.greenParticleStreakShader ); VectorSubtract( cg.refdef.vieworg, origin, direction ); VectorNormalize( direction ); VectorMA( origin, 12, direction, org ); VectorMA( org, 8, dir, direction ); VectorSet(vel, 0, 0, 32 ); //8 FX_AddSprite( origin, vel, qfalse, random() * 4 + 2, 12, 0.6 + random() * 0.4, 0.0, random() * 180, 0.0, random() * 200 + 1200, //300 cgs.media.steamShader ); //FX_AddSprite( // Only play the impact sound and throw off the purple particles when it's the main projectile /* if ( size < 3 ) return; for ( i = 0; i < 4; i++ ) { for ( t = 0; t < 3; t++ ) vel[t] = ( dir[t] + crandom() * 0.9 ) * ( random() * 100 + 250 ); VectorScale( vel, -2.2, accel ); FX_AddSprite( hitpos, vel, qfalse, random() * 8 + 8, 0, 1.0, 0.0, 0.0, 0.0, 200, cgs.media.purpleParticleShader ); }*/ trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, weaponInfo->mainHitSound ); }