/* =============== CL_ColorExplosionParticles =============== */ void CL_ColorExplosionParticles (vec3_t org, int color, int run) { int i, j; cparticle_t *p; for (i=0 ; i<128 ; i++) { p = CL_AllocParticle(); if (!p) return; p->time = cl.time; p->color = color + (rand() % run); for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%256)-128; } p->accel[0] = p->accel[1] = 0; p->accel[2] = -PARTICLE_GRAVITY; p->alpha = 1.0; p->alphavel = -0.4 / (0.6 + frand()*0.2); } }
/* =============== ParticleEffect PARTICLE_EFFECT on server =============== */ void CL_RunParticleEffect( const vec3_t org, const vec3_t dir, int color, int count ) { particle_t *p; int i, j; if( count == 1024 ) { // Quake hack: count == 255 it's a RocketExplode CL_ParticleExplosion( org ); return; } for( i = 0; i < count; i++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += Com_RandomFloat( 0.0f, 0.5f ); p->color = ( color & ~7 ) + Com_RandomLong( 0, 8 ); p->type = pt_slowgrav; for( j = 0; j < 3; j++ ) { p->org[j] = org[j] + Com_RandomFloat( -8, 8 ); p->vel[j] = dir[j] * 15; } } }
/* =============== CL_ParticleBurst =============== */ void CL_ParticleBurst( const vec3_t org, int size, int color, float life ) { particle_t *p; float vel; vec3_t dir; int i, j, k; for( i = -size; i < size; i++ ) { for( j = -size; j < size; j++ ) { for( k = 0; k < 1; k++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += life + Com_RandomFloat( 0.0f, 0.1f ); p->color = color; p->type = pt_slowgrav; dir[0] = j * 8 + Com_RandomLong( 0, 8 ); dir[1] = i * 8 + Com_RandomLong( 0, 8 ); dir[2] = 256; p->org[0] = org[0] + dir[0]; p->org[1] = org[1] + dir[1]; p->org[2] = org[2] + Com_RandomLong( 0, 64 ); VectorNormalize( dir ); vel = 50 + Com_RandomLong( 0, 64 ); VectorScale( dir, vel, p->vel ); } } } }
/* =============== CL_TracerEffect =============== */ void CL_TracerEffect( const vec3_t start, const vec3_t end ) { particle_t *p; byte *color; vec3_t dir; float life, dist; p = CL_AllocParticle( CL_BulletTracerDraw ); if( !p ) return; // get out shot direction and length VectorSubtract( end, start, dir ); VectorCopy( dir, p->vel ); dist = VectorNormalizeLength( dir ); // don't make small tracers if( dist <= traceroffset->value ) return; p->ramp = Com_RandomFloat( 200.0f, 256.0f ) * tracerlength->value; color = gTracerColors[4]; life = ( dist + p->ramp ) / ( max( 1.0f, tracerspeed->value )); p->color = CL_LookupColor( color[0], color[1], color[2] ); VectorCopy( start, p->org ); p->type = pt_tracer; p->die += life; }
/* =============== CL_EntityParticles set EF_BRIGHTFIELD effect =============== */ void CL_EntityParticles( cl_entity_t *ent ) { float angle; float sr, sp, sy, cr, cp, cy; vec3_t forward; particle_t *p; int i; for( i = 0; i < NUMVERTEXNORMALS; i++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; angle = cl.time * cl_avelocities[i][0]; SinCos( angle, &sy, &cy ); angle = cl.time * cl_avelocities[i][1]; SinCos( angle, &sp, &cp ); angle = cl.time * cl_avelocities[i][2]; SinCos( angle, &sr, &cr ); VectorSet( forward, cp * cy, cp * sy, -sp ); p->die += 0.01f; p->color = 111; // yellow p->type = pt_explode; p->org[0] = ent->origin[0] + cl_avertexnormals[i][0] * 64.0f + forward[0] * 16.0f; p->org[1] = ent->origin[1] + cl_avertexnormals[i][1] * 64.0f + forward[1] * 16.0f; p->org[2] = ent->origin[2] + cl_avertexnormals[i][2] * 64.0f + forward[2] * 16.0f; } }
/* =============== CL_LavaSplash =============== */ void CL_LavaSplash( const vec3_t org ) { particle_t *p; float vel; vec3_t dir; int i, j, k; for( i = -16; i < 16; i++ ) { for( j = -16; j <16; j++ ) { for( k = 0; k < 1; k++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += 2.0f + (rand() & 31) * 0.02f; p->color = 224 + (rand() & 7); p->type = pt_slowgrav; dir[0] = j * 8.0f + (rand() & 7); dir[1] = i * 8.0f + (rand() & 7); dir[2] = 256; p->org[0] = org[0] + dir[0]; p->org[1] = org[1] + dir[1]; p->org[2] = org[2] + (rand() & 63); VectorNormalize( dir ); vel = 50 + (rand() & 63); VectorScale( dir, vel, p->vel ); } } } }
/* =============== CL_TeleportSplash =============== */ void CL_TeleportSplash( const vec3_t org ) { particle_t *p; vec3_t dir; int i, j, k; for( i = -16; i < 16; i += 4 ) { for( j = -16; j < 16; j += 4 ) { for( k = -24; k < 32; k += 4 ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += 0.2f + (rand() & 7) * 0.02f; p->color = 7 + (rand() & 7); p->type = pt_slowgrav; dir[0] = j * 8.0f; dir[1] = i * 8.0f; dir[2] = k * 8.0f; p->org[0] = org[0] + i + (rand() & 3); p->org[1] = org[1] + j + (rand() & 3); p->org[2] = org[2] + k + (rand() & 3); VectorNormalize( dir ); VectorScale( dir, (50 + (rand() & 63)), p->vel ); } } } }
void CLQ2_BigTeleportParticles( vec3_t origin ) { static int colortable[ 4 ] = {2 * 8, 13 * 8, 21 * 8, 18 * 8}; for ( int i = 0; i < 4096; i++ ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; p->color = colortable[ rand() & 3 ]; float angle = idMath::TWO_PI * ( rand() & 1023 ) / 1023.0; float dist = rand() & 31; p->org[ 0 ] = origin[ 0 ] + cos( angle ) * dist; p->vel[ 0 ] = cos( angle ) * ( 70 + ( rand() & 63 ) ); p->accel[ 0 ] = -cos( angle ) * 100; p->org[ 1 ] = origin[ 1 ] + sin( angle ) * dist; p->vel[ 1 ] = sin( angle ) * ( 70 + ( rand() & 63 ) ); p->accel[ 1 ] = -sin( angle ) * 100; p->org[ 2 ] = origin[ 2 ] + 8 + ( rand() % 90 ); p->vel[ 2 ] = -100 + ( rand() & 31 ); p->accel[ 2 ] = PARTICLE_GRAVITY * 4; p->alpha = 1.0; p->alphavel = -0.3 / ( 0.5 + frand() * 0.3 ); } }
void CLQ2_BlasterTrail( vec3_t start, vec3_t end ) { vec3_t move; VectorCopy( start, move ); vec3_t vec; VectorSubtract( end, start, vec ); float len = VectorNormalize( vec ); int dec = 5; VectorScale( vec, 5, vec ); // FIXME: this is a really silly way to have a loop while ( len > 0 ) { len -= dec; cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; VectorClear( p->accel ); p->alpha = 1.0; p->alphavel = -1.0 / ( 0.3 + frand() * 0.2 ); p->color = 0xe0; for ( int j = 0; j < 3; j++ ) { p->org[ j ] = move[ j ] + crand(); p->vel[ j ] = crand() * 5; p->accel[ j ] = 0; } VectorAdd( move, vec, move ); } }
void CLQ2_Tracker_Explode( vec3_t origin ) { for ( int i = 0; i < 300; i++ ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; VectorClear( p->accel ); p->alpha = 1.0; p->alphavel = -1.0; p->color = 0; vec3_t dir; dir[ 0 ] = crand(); dir[ 1 ] = crand(); dir[ 2 ] = crand(); VectorNormalize( dir ); vec3_t backdir; VectorScale( dir, -1, backdir ); VectorMA( origin, 64, dir, p->org ); VectorScale( backdir, 64, p->vel ); } }
void CLQ2_ItemRespawnParticles( vec3_t origin ) { for ( int i = 0; i < 64; i++ ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; p->color = 0xd4 + ( rand() & 3 ); // green p->org[ 0 ] = origin[ 0 ] + crand() * 8; p->org[ 1 ] = origin[ 1 ] + crand() * 8; p->org[ 2 ] = origin[ 2 ] + crand() * 8; for ( int j = 0; j < 3; j++ ) { p->vel[ j ] = crand() * 8; } p->accel[ 0 ] = p->accel[ 1 ] = 0; p->accel[ 2 ] = -PARTICLE_GRAVITY * 0.2; p->alpha = 1.0; p->alphavel = -1.0 / ( 1.0 + frand() * 0.3 ); } }
void CLQ2_WidowSplash( vec3_t origin ) { static int colortable[ 4 ] = {2 * 8, 13 * 8, 21 * 8, 18 * 8}; for ( int i = 0; i < 256; i++ ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; p->color = colortable[ rand() & 3 ]; vec3_t dir; dir[ 0 ] = crand(); dir[ 1 ] = crand(); dir[ 2 ] = crand(); VectorNormalize( dir ); VectorMA( origin, 45.0, dir, p->org ); VectorMA( oldvec3_origin, 40.0, dir, p->vel ); p->accel[ 0 ] = p->accel[ 1 ] = 0; p->alpha = 1.0; p->alphavel = -0.8 / ( 0.5 + frand() * 0.3 ); } }
/* =============== CL_BlasterParticles2 Wall impact puffs (Green) =============== */ void CL_BlasterParticles2 (vec3_t org, vec3_t dir, unsigned int color) { int i, j; cparticle_t *p; float d; int count; count = 40; for (i=0 ; i<count ; i++) { p = CL_AllocParticle(); if (!p) return; p->time = cl.time; p->color = color + (rand()&7); d = rand()&15; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j]; p->vel[j] = dir[j] * 30 + crand()*40; } p->accel[0] = p->accel[1] = 0; p->accel[2] = -PARTICLE_GRAVITY; p->alpha = 1.0; p->alphavel = -1.0 / (0.5 + frand()*0.3); } }
/* =============== CL_ParticleSmokeEffect - like the steam effect, but unaffected by gravity =============== */ void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude) { int i, j; cparticle_t *p; float d; vec3_t r, u; MakeNormalVectors (dir, r, u); for (i=0 ; i<count ; i++) { p = CL_AllocParticle(); if (!p) return; p->time = cl.time; p->color = color + (rand()&7); for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + magnitude*0.1*crand(); // p->vel[j] = dir[j]*magnitude; } VectorScale (dir, magnitude, p->vel); d = crand()*magnitude/3; VectorMA (p->vel, d, r, p->vel); d = crand()*magnitude/3; VectorMA (p->vel, d, u, p->vel); p->accel[0] = p->accel[1] = p->accel[2] = 0; p->alpha = 1.0; p->alphavel = -1.0 / (0.5 + frand()*0.3); } }
/* ================== CL_ParseParticles ================== */ void CL_ParseParticles( sizebuf_t *msg ) { vec3_t org, dir; int i, count, color; float life; BF_ReadVec3Coord( msg, org ); for( i = 0; i < 3; i++ ) dir[i] = BF_ReadChar( msg ) * (1.0f / 16); count = BF_ReadByte( msg ); color = BF_ReadByte( msg ); if( count == 255 ) count = 1024; life = BF_ReadByte( msg ) * 0.125f; if( life != 0.0f && count == 1 ) { particle_t *p; p = CL_AllocParticle( NULL ); if( !p ) return; p->die += life; p->color = color; p->type = pt_static; VectorCopy( org, p->org ); VectorCopy( dir, p->vel ); } else CL_RunParticleEffect( org, dir, color, count ); }
void CLQ2_FlagTrail( vec3_t start, vec3_t end, float colour ) { vec3_t move; VectorCopy( start, move ); vec3_t vec; VectorSubtract( end, start, vec ); float len = VectorNormalize( vec ); int dec = 5; VectorScale( vec, 5, vec ); while ( len > 0 ) { len -= dec; cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; VectorClear( p->accel ); p->alpha = 1.0; p->alphavel = -1.0 / ( 0.8 + frand() * 0.2 ); p->color = colour; for ( int j = 0; j < 3; j++ ) { p->org[ j ] = move[ j ] + crand() * 16; p->vel[ j ] = crand() * 5; p->accel[ j ] = 0; } VectorAdd( move, vec, move ); } }
/* =============== ParticleEffect PARTICLE_EFFECT on server =============== */ void CL_RunParticleEffect( const vec3_t org, const vec3_t dir, int color, int count ) { particle_t *p; int i, j; if( count == 1024 ) { // Quake hack: count == 255 it's a RocketExplode CL_ParticleExplosion( org ); return; } for( i = 0; i < count; i++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += 0.1f * (rand() % 5); p->color = (color & ~7) + (rand() & 7); p->type = pt_slowgrav; for( j = 0; j < 3; j++ ) { p->org[j] = org[j] + ((rand() & 15) - 8); p->vel[j] = dir[j] * 15; } } }
void CLQ2_TeleportParticles( vec3_t origin ) { for ( int i = -16; i <= 16; i += 4 ) { for ( int j = -16; j <= 16; j += 4 ) { for ( int k = -16; k <= 32; k += 4 ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; p->color = 7 + ( rand() & 7 ); p->alpha = 1.0; p->alphavel = -1.0 / ( 0.3 + ( rand() & 7 ) * 0.02 ); p->org[ 0 ] = origin[ 0 ] + i + ( rand() & 3 ); p->org[ 1 ] = origin[ 1 ] + j + ( rand() & 3 ); p->org[ 2 ] = origin[ 2 ] + k + ( rand() & 3 ); vec3_t dir; dir[ 0 ] = j * 8; dir[ 1 ] = i * 8; dir[ 2 ] = k * 8; VectorNormalize( dir ); float vel = 50 + ( rand() & 63 ); VectorScale( dir, vel, p->vel ); p->accel[ 0 ] = p->accel[ 1 ] = 0; p->accel[ 2 ] = -PARTICLE_GRAVITY; } } } }
/* =============== CL_ParticleBurst =============== */ void CL_ParticleBurst( const vec3_t org, int size, int color, float life ) { particle_t *p; float vel; vec3_t dir; int i, j, k; for( i = -size; i < size; i++ ) { for( j = -size; j < size; j++ ) { for( k = 0; k < 1; k++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += life + (rand() & 31) * 0.02f; p->color = color; p->type = pt_slowgrav; dir[0] = j * 8.0f + (rand() & 7); dir[1] = i * 8.0f + (rand() & 7); dir[2] = 256; p->org[0] = org[0] + dir[0]; p->org[1] = org[1] + dir[1]; p->org[2] = org[2] + (rand() & 63); VectorNormalize( dir ); vel = 50 + (rand() & 63); VectorScale( dir, vel, p->vel ); } } } }
void CLQ2_DebugTrail( vec3_t start, vec3_t end ) { vec3_t move; VectorCopy( start, move ); vec3_t vec; VectorSubtract( end, start, vec ); float len = VectorNormalize( vec ); vec3_t right, up; MakeNormalVectors( vec, right, up ); float dec = 3; VectorScale( vec, dec, vec ); VectorCopy( start, move ); while ( len > 0 ) { len -= dec; cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; VectorClear( p->accel ); VectorClear( p->vel ); p->alpha = 1.0; p->alphavel = -0.1; p->color = 0x74 + ( rand() & 7 ); VectorCopy( move, p->org ); VectorAdd( move, vec, move ); } }
/* ================ CL_DrawLine ================ */ static void CL_DrawLine( const vec3_t start, const vec3_t end, int pcolor, float life, float gap ) { particle_t *p; float len, curdist; vec3_t diff; int i; // Determine distance; VectorSubtract( end, start, diff ); len = VectorNormalizeLength( diff ); curdist = 0; while( curdist <= len ) { p = CL_AllocParticle( NULL ); if( !p ) return; for( i = 0; i < 3; i++ ) p->org[i] = start[i] + curdist * diff[i]; p->color = pcolor; p->type = pt_static; p->die += life; curdist += gap; } }
void CLQ2_ForceWall( vec3_t start, vec3_t end, int colour ) { vec3_t move; VectorCopy( start, move ); vec3_t vec; VectorSubtract( end, start, vec ); float len = VectorNormalize( vec ); VectorScale( vec, 4, vec ); while ( len > 0 ) { len -= 4; if ( frand() > 0.3 ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; VectorClear( p->accel ); p->alpha = 1.0; p->alphavel = -1.0 / ( 3.0 + frand() * 0.5 ); p->color = colour; for ( int j = 0; j < 3; j++ ) { p->org[ j ] = move[ j ] + crand() * 3; p->accel[ j ] = 0; } p->vel[ 0 ] = 0; p->vel[ 1 ] = 0; p->vel[ 2 ] = -40 - ( crand() * 10 ); } VectorAdd( move, vec, move ); } }
/* =============== CL_TracerEffect =============== */ void CL_UserTracerParticle( float *org, float *vel, float life, int colorIndex, float length, byte deathcontext, void (*deathfunc)( particle_t *p )) { particle_t *p; byte *color; p = CL_AllocParticle( CL_BulletTracerDraw ); if( !p ) return; if( colorIndex > ( sizeof( gTracerColors ) / sizeof( gTracerColors[0] ))) { p->color = bound( 0, colorIndex, 255 ); } else { color = gTracerColors[colorIndex]; p->color = CL_LookupColor( color[0], color[1], color[2] ); } VectorCopy( org, p->org ); VectorCopy( vel, p->vel ); p->ramp = length; // ramp used as length p->context = deathcontext; p->deathfunc = deathfunc; p->type = pt_tracer; p->die += life; }
// (lets you control the # of bubbles by setting the distance between the spawns) void CLQ2_BubbleTrail2( vec3_t start, vec3_t end, int distance ) { vec3_t move; VectorCopy( start, move ); vec3_t vec; VectorSubtract( end, start, vec ); float len = VectorNormalize( vec ); float dec = distance; VectorScale( vec, dec, vec ); for ( int i = 0; i < len; i += dec ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; VectorClear( p->accel ); p->alpha = 1.0; p->alphavel = -1.0 / ( 1 + frand() * 0.1 ); p->color = 4 + ( rand() & 7 ); for ( int j = 0; j < 3; j++ ) { p->org[ j ] = move[ j ] + crand() * 2; p->vel[ j ] = crand() * 10; } p->org[ 2 ] -= 4; p->vel[ 2 ] += 20; VectorAdd( move, vec, move ); } }
/* =============== CL_ParticleExplosion2 =============== */ void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength ) { int i, j; int colorMod = 0; particle_t *p; int hSound; if( !org ) return; hSound = S_RegisterSound( "weapons/explode3.wav" ); S_StartSound( org, 0, CHAN_AUTO, hSound, VOL_NORM, ATTN_NORM, PITCH_NORM, 0 ); for( i = 0; i < 512; i++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += 0.3f; p->color = colorStart + ( colorMod % colorLength ); colorMod++; p->type = pt_blob; for( j = 0; j < 3; j++ ) { p->org[j] = org[j] + Com_RandomFloat( -16.0f, 16.0f ); p->vel[j] = Com_RandomFloat( -256.0f, 256.0f ); } } }
void CLQ2_TeleporterParticles( vec3_t origin ) { for ( int i = 0; i < 8; i++ ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; p->color = 0xdb; for ( int j = 0; j < 2; j++ ) { p->org[ j ] = origin[ j ] - 16 + ( rand() & 31 ); p->vel[ j ] = crand() * 14; } p->org[ 2 ] = origin[ 2 ] - 8 + ( rand() & 7 ); p->vel[ 2 ] = 80 + ( rand() & 7 ); p->accel[ 0 ] = p->accel[ 1 ] = 0; p->accel[ 2 ] = -PARTICLE_GRAVITY; p->alpha = 1.0; p->alphavel = -0.5; } }
/* =============== CL_LavaSplash =============== */ void CL_LavaSplash( const vec3_t org ) { particle_t *p; float vel; vec3_t dir; int i, j, k; for( i = -16; i < 16; i++ ) { for( j = -16; j <16; j++ ) { for( k = 0; k < 1; k++ ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += 2.0f + Com_RandomFloat( 0.0f, 0.65f ); p->color = 224 + Com_RandomLong( 0, 8 ); p->type = pt_slowgrav; dir[0] = j * 8 + Com_RandomLong( 0, 8 ); dir[1] = i * 8 + Com_RandomLong( 0, 8 ); dir[2] = 256; p->org[0] = org[0] + dir[0]; p->org[1] = org[1] + dir[1]; p->org[2] = org[2] + Com_RandomLong( 0, 64 ); VectorNormalize( dir ); vel = 50 + Com_RandomLong( 0, 64 ); VectorScale( dir, vel, p->vel ); } } } }
// Puffs with velocity along direction, with some randomness thrown in void CLQ2_ParticleSteamEffect( vec3_t org, vec3_t dir, int color, int count, int magnitude ) { vec3_t r, u; MakeNormalVectors( dir, r, u ); for ( int i = 0; i < count; i++ ) { cparticle_t* p = CL_AllocParticle(); if ( !p ) { return; } p->type = pt_q2static; p->color = color + ( rand() & 7 ); for ( int j = 0; j < 3; j++ ) { p->org[ j ] = org[ j ] + magnitude * 0.1 * crand(); } VectorScale( dir, magnitude, p->vel ); float d = crand() * magnitude / 3; VectorMA( p->vel, d, r, p->vel ); d = crand() * magnitude / 3; VectorMA( p->vel, d, u, p->vel ); p->accel[ 0 ] = p->accel[ 1 ] = 0; p->accel[ 2 ] = -PARTICLE_GRAVITY / 2; p->alpha = 1.0; p->alphavel = -1.0 / ( 0.5 + frand() * 0.3 ); } }
/* =============== CL_TeleportSplash =============== */ void CL_TeleportSplash( const vec3_t org ) { particle_t *p; vec3_t dir; int i, j, k; for( i = -16; i < 16; i += 4 ) { for( j = -16; j < 16; j += 4 ) { for( k = -24; k < 32; k += 4 ) { p = CL_AllocParticle( NULL ); if( !p ) return; p->die += Com_RandomFloat( 0.2f, 0.36f ); p->color = Com_RandomLong( 7, 14 ); p->type = pt_slowgrav; dir[0] = j * 8; dir[1] = i * 8; dir[2] = k * 8; p->org[0] = org[0] + i + Com_RandomFloat( -4.0f, 4.0f ); p->org[1] = org[1] + j + Com_RandomFloat( -4.0f, 4.0f ); p->org[2] = org[2] + k + Com_RandomFloat( -4.0f, 4.0f ); VectorNormalize( dir ); VectorScale( dir, Com_RandomLong( 50, 114 ), p->vel ); } } } }
void CL_Tracker_Explode(vec3_t origin) { vec3_t dir, backdir; int i; cparticle_t *p; for(i=0; i<300; i++) { p = CL_AllocParticle(); if (!p) return; VectorClear (p->accel); p->time = cl.time; p->alpha = 1.0; p->alphavel = -1.0; p->color = 0; dir[0] = crand(); dir[1] = crand(); dir[2] = crand(); VectorNormalize(dir); VectorScale(dir, -1, backdir); VectorMA(origin, 64, dir, p->org); VectorScale(backdir, 64, p->vel); } }