/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // cl_effects.c -- particle and decal effects parsing/generation #include "client.h" #include "particles.h" static vec3_t avelocities [NUMVERTEXNORMALS]; //================================================= /* =============== CL_LightningBeam =============== */ /*void CL_LightningBeam(vec3_t start, vec3_t end, int srcEnt, int dstEnt, float size) { cparticle_t *list; cparticle_t *p=NULL; for (list=active_particles; list; list=list->next) if (list->src_ent == srcEnt && list->dst_ent == dstEnt ) { p=list; p->time = cl.time; VectorCopy(start, p->angle); VectorCopy(end, p->org); if (p->link) { p->link->time = cl.time; VectorCopy(start, p->link->angle); VectorCopy(end, p->link->org); } else { p->link = CL_SetupParticle ( start[0], start[1], start[2], end[0], end[1], end[2], 0, 0, 0, 0, 0, 0, 150, 150, 255, 0, 0, 0, 1, -1.0, size, 0, particle_beam, PART_BEAM, NULL,0); } break; } if (p) return; p = CL_SetupParticle ( start[0], start[1], start[2], end[0], end[1], end[2], 0, 0, 0, 0, 0, 0, 115, 115, 255, 0, 0, 0, 1, -1.0, size, 0, particle_lightning, PART_LIGHTNING, NULL,0); p->src_ent=srcEnt; p->dst_ent=dstEnt; p->link = CL_SetupParticle ( start[0], start[1], start[2], end[0], end[1], end[2], 0, 0, 0, 0, 0, 0, 150, 150, 255, 0, 0, 0, 1, -1.0, size, 0, particle_beam, PART_BEAM, NULL,0); }*/ void CL_LightningBeam (vec3_t start, vec3_t end, int srcEnt, int dstEnt, float size) { cparticle_t *list; cparticle_t *p=NULL; for (list=active_particles; list; list=list->next) if (list->src_ent == srcEnt && list->dst_ent == dstEnt && list->image == particle_lightning) { p=list; /*p->start =*/ p->time = cl.time; VectorCopy(start, p->angle); VectorCopy(end, p->org); return; } p = CL_SetupParticle ( start[0], start[1], start[2], end[0], end[1], end[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 1, -2, GL_SRC_ALPHA, GL_ONE, size, 0, particle_lightning, PART_LIGHTNING, 0, false); if (!p) return; p->src_ent=srcEnt; p->dst_ent=dstEnt; } /* =============== CL_Explosion_Decal =============== */ void CL_Explosion_Decal (vec3_t org, float size, int decalnum) { if (r_decals->value) { int i, j, offset=8; //size/2 cparticle_t *p; vec3_t angle[6], ang; trace_t trace1, trace2; vec3_t end1, end2, normal, sorg, dorg; vec3_t planenormals[6]; VectorSet(angle[0], -1, 0, 0); VectorSet(angle[1], 1, 0, 0); VectorSet(angle[2], 0, 1, 0); VectorSet(angle[3], 0, -1, 0); VectorSet(angle[4], 0, 0, 1); VectorSet(angle[5], 0, 0, -1); for (i=0; i<6; i++) { VectorMA(org, -offset, angle[i], sorg); // move origin 8 units back VectorMA(sorg, size/2+offset, angle[i], end1); trace1 = CL_Trace (sorg, end1, 0, CONTENTS_SOLID); if (trace1.fraction < 1) // hit a surface { // make sure we haven't hit this plane before VectorCopy(trace1.plane.normal, planenormals[i]); for (j=0; jvalue, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, size, 0, decalnum, // particle_burnmark PART_SHADED|PART_DECAL|PART_ALPHACOLOR, CL_DecalAlphaThink, true); } /*VecToAngleRolled(angle[i], rand()%360, ang); p = CL_SetupParticle ( ang[0], ang[1], ang[2], org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 1, -0.001, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, size, 0, particle_burnmark, PART_SHADED|PART_DECAL|PART_ALPHACOLOR, CL_DecalAlphaThink, true);*/ } } } /* =============== CL_ExplosionThink =============== */ void CL_ExplosionThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { if (*alpha>.85) *image = particle_rexplosion1; else if (*alpha>.7) *image = particle_rexplosion2; else if (*alpha>.5) *image = particle_rexplosion3; else if (*alpha>.4) *image = particle_rexplosion4; else if (*alpha>.25) *image = particle_rexplosion5; else if (*alpha>.1) *image = particle_rexplosion6; else *image = particle_rexplosion7; *alpha *= 3.0; if (*alpha > 1.0) *alpha = 1; p->thinknext = true; } /* =============== CL_ExplosionBubbleThink =============== */ void CL_ExplosionBubbleThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { if (CM_PointContents(org,0) & MASK_WATER) p->thinknext = true; else { p->think = NULL; p->alpha = 0; } } /* =============== CL_Explosion_Particle Explosion effect =============== */ void CL_Explosion_Particle (vec3_t org, float size, qboolean rocket) { cparticle_t *p; p = CL_SetupParticle ( 0, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 1, (rocket)? -2 : -1.5, GL_SRC_ALPHA, GL_ONE, // GL_ONE, GL_ONE, (size != 0) ? size : (150 - ( (!rocket) ? 75 : 0)), 0, particle_rexplosion1, PART_DEPTHHACK_SHORT, CL_ExplosionThink, true); if (p) { // smooth color blend :D /* CL_AddParticleLight (p, 225, 0, 1, 0, 0); CL_AddParticleLight (p, 250, 0, 1, 0.3, 0); CL_AddParticleLight (p, 275, 0, 1, 0.6, 0); CL_AddParticleLight (p, 300, 0, 1, 1, 0);*/ // use just one, 4 lights kills the framerate CL_AddParticleLight (p, 300, 0, 1, 0.514, 0); } } /* =============== CL_Explosion_FlashParticle Explosion fash =============== */ void CL_Explosion_FlashParticle (vec3_t org, float size, qboolean large) { if (large) { CL_SetupParticle ( 0, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 255, 175, 100, 0, 0, 0, 1, -1.75, GL_SRC_ALPHA, GL_ONE, //GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, (size!=0)?size:50, -10, //100-(!rocket)?50:0, -10, particle_rflash, PART_DEPTHHACK_SHORT, NULL,0); } else { CL_SetupParticle ( 0, 0, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 255, 175, 100, 0, 0, 0, 1, -1.75, GL_SRC_ALPHA, GL_ONE, (size!=0)?size:50, -10, //100-(!rocket)?50:0, -10, particle_blaster, 0, NULL,0); } } /* =============== CL_ParticleExplosionSparksThink =============== */ void CL_ParticleExplosionSparksThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { int i; //setting up angle for sparks { float time1, time2; time1 = *time; time2 = time1*time1; for (i=0;i<2;i++) angle[i] = 0.25*(p->vel[i]*time1 + (p->accel[i])*time2); angle[2] = 0.25*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2); } p->thinknext = true; } /* =============== CL_Explosion_Sparks =============== */ void CL_Explosion_Sparks (vec3_t org, int size, int count) { int i; for (i=0; i < (count/max(cl_particle_scale->value, 1.0f)); i++) // was 256 { CL_SetupParticle ( 0, 0, 0, org[0] + ((rand()%size)-16), org[1] + ((rand()%size)-16), org[2] + ((rand()%size)-16), (rand()%150)-75, (rand()%150)-75, (rand()%150)-75, 0, 0, 0, 255, 100, 25, 0, 0, 0, 1, -0.8 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, size, size*-1.5f, // was 6, -9 particle_solid, PART_GRAVITY|PART_SPARK, CL_ParticleExplosionSparksThink, true); } } /* ===================== Blood effects ===================== */ void CL_ParticleBloodThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time); void CL_BloodPuff (vec3_t org, vec3_t dir, int count); #define MAXBLEEDSIZE 5 #define TIMEBLOODGROW 2.5f #define BLOOD_DECAL_CHANCE 0.5F /* =============== CL_ParticleBloodDecalThink =============== */ void CL_ParticleBloodDecalThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { // This REALLY slows things down /*if (*timeangle, org, len); { CL_CalcPartVelocity(p, 0.2, time, angle); length = VectorNormalize(angle); if (length>MAXBLEEDSIZE) length = MAXBLEEDSIZE; VectorScale(angle, -length, angle); } //now to trace for impact... CL_ParticleBloodThink (p, org, angle, alpha, size, image, time); } /* =============== CL_ParticleBloodPuffThink =============== */ void CL_ParticleBloodPuffThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { angle[2] = angle[0] + *time*angle[1] + *time**time*angle[2]; //now to trace for impact... CL_ParticleBloodThink (p, org, angle, alpha, size, image, time); } /* =============== CL_ParticleBloodThink =============== */ void CL_ParticleBloodThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { trace_t trace = CL_Trace (p->oldorg, org, 0, CONTENTS_SOLID); // was 0.1 qboolean became_decal = false; if (trace.fraction < 1.0) // delete and stain... { if (r_decals->value && (p->flags & PART_LEAVEMARK) && !VectorCompare(trace.plane.normal, vec3_origin) && !(CM_PointContents(p->oldorg,0) & MASK_WATER)) // no blood splatters underwater... { vec3_t normal, dir; int i; qboolean greenblood = false; qboolean timedout = false; if (p->color[1] > 0 && p->color[2] > 0) greenblood = true; // time cutoff for gib trails if (p->flags & PART_GRAVITY && !(p->flags & PART_DIRECTION)) { // gekk gibs go flyin faster... if ((greenblood) && (cl.time - p->time)*0.001 > 1.0F) timedout = true; if ((!greenblood) && (cl.time - p->time)*0.001 > 0.5F) timedout = true; } if (!timedout) { VectorNegate(trace.plane.normal, normal); VecToAngleRolled(normal, rand()%360, p->angle); VectorCopy(trace.endpos, p->org); VectorClear(p->vel); VectorClear(p->accel); p->image = CL_GetRandomBloodParticle(); p->blendfunc_src = GL_SRC_ALPHA; //GL_ZERO p->blendfunc_dst = GL_ONE_MINUS_SRC_ALPHA; //GL_ONE_MINUS_SRC_COLOR p->flags = PART_DECAL|PART_SHADED|PART_ALPHACOLOR; p->alpha = *alpha; p->alphavel = -1/r_decal_life->value; if (greenblood) p->color[1] = 210; else for (i=0; i<3; i++) p->color[i] *= 0.5; p->start = CL_NewParticleTime(); p->think = CL_ParticleBloodDecalThink; p->thinknext = true; p->size = MAXBLEEDSIZE*0.5*(random()*5.0+5); //p->size = *size*(random()*5.0+5); p->sizevel = 0; p->decalnum = 0; p->decal = NULL; AngleVectors (p->angle, dir, NULL, NULL); VectorNegate(dir, dir); CL_ClipDecal(p, p->size, -p->angle[2], p->org, dir); if (p->decalnum) became_decal = true; //else // Com_Printf(S_COLOR_YELLOW"Blood decal not clipped!\n"); } } if (!became_decal) { *alpha = 0; *size = 0; p->alpha = 0; } } VectorCopy(org, p->oldorg); p->thinknext = true; } /* =============== CL_BloodSmack =============== */ void CL_BloodSmack (vec3_t org, vec3_t dir) { cparticle_t *p; p = CL_SetupParticle ( crand()*180, crand()*100, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 0, 0, 255, 0, 0, 0, 0, 0, 1.0, -1 / (0.5 + frand()*0.3), //was -0.75 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 10, 0, particle_redblood, PART_SHADED|PART_OVERBRIGHT, CL_ParticleRotateThink,true); CL_BloodPuff(org, dir, 1); } /* =============== CL_BloodBleed =============== */ void CL_BloodBleed (vec3_t org, vec3_t dir, int count) { cparticle_t *p; vec3_t pos; int i; VectorScale(dir, 10, pos); for (i=0; ivalue-2)*0.01, dir[1]+random()*(cl_blood->value-2)*0.01, dir[2]+random()*(cl_blood->value-2)*0.01); VectorScale(pos, 10 + (cl_blood->value-2)*0.0001*random(), pos); p = CL_SetupParticle ( org[0], org[1], org[2], org[0] + ((rand()&7)-4) + dir[0], org[1] + ((rand()&7)-4) + dir[1], org[2] + ((rand()&7)-4) + dir[2], pos[0]*(random()*3+5), pos[1]*(random()*3+5), pos[2]*(random()*3+5), 0, 0, 0, 255, 0, 0, 0, 0, 0, 0.7, -0.25 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, MAXBLEEDSIZE*0.5, 0, particle_blooddrip, PART_SHADED|PART_DIRECTION|PART_GRAVITY|PART_OVERBRIGHT, CL_ParticleBloodDropThink,true); if (p && i == 0 && random() < BLOOD_DECAL_CHANCE) p->flags |= PART_LEAVEMARK; } } /* =============== CL_BloodPuff =============== */ void CL_BloodPuff (vec3_t org, vec3_t dir, int count) { cparticle_t *p; int i; float d; for (i=0; iflags |= PART_LEAVEMARK; } } /* =============== CL_BloodHit =============== */ void CL_BloodHit (vec3_t org, vec3_t dir) { if (cl_blood->value < 1) // disable blood option return; if (cl_blood->value == 2) // splat CL_BloodSmack(org, dir); else if (cl_blood->value == 3) // bleed CL_BloodBleed (org, dir, 6); else if (cl_blood->value == 4) // gore CL_BloodBleed (org, dir, 16); else // 1 = puff CL_BloodPuff(org, dir, 5); } /* ================== CL_GreenBloodHit green blood spray ================== */ void CL_GreenBloodHit (vec3_t org, vec3_t dir) { cparticle_t *p; int i; float d; if (cl_blood->value < 1) // disable blood option return; for (i=0;i<5;i++) { d = rand()&31; p = CL_SetupParticle ( crand()*180, crand()*100, 0, org[0] + ((rand()&7)-4) + d*dir[0], org[1] + ((rand()&7)-4) + d*dir[1], org[2] + ((rand()&7)-4) + d*dir[2], dir[0]*(crand()*3+5), dir[1]*(crand()*3+5), dir[2]*(crand()*3+5), 0, 0, -100, 255, 180, 50, 0, 0, 0, 1, -1.0, GL_SRC_ALPHA, GL_ONE, 10, 0, particle_blood, PART_SHADED|PART_OVERBRIGHT, CL_ParticleBloodPuffThink,true); if (p && i == 0 && random() < BLOOD_DECAL_CHANCE) p->flags |= PART_LEAVEMARK; } } /* =============== CL_ParticleEffect Wall impact puffs =============== */ void CL_ParticleEffect (vec3_t org, vec3_t dir, int color8, int count) { int i; float d; vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)}; for (i=0 ; iangle, org, len); // *size *= (float)(SplashSize/VectorLength(len)) * 0.5/((4-*size)); // if (*size > SplashSize) // *size = SplashSize; //setting up angle for sparks { float time1, time2; time1 = *time; time2 = time1*time1; for (i=0;i<2;i++) angle[i] = 0.5*(p->vel[i]*time1 + (p->accel[i])*time2); angle[2] = 0.5*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2); } p->thinknext = true; } /* =============== CL_ParticleEffectSplash Water Splashing =============== */ void CL_ParticleEffectSplash (vec3_t org, vec3_t dir, int color8, int count) { int i; float d; vec3_t color = {color8red(color8), color8green(color8), color8blue(color8)}; for (i=0 ; ivel[i]*time1 + (p->accel[i])*time2); angle[2] = 0.25*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2); } p->thinknext = true; } /* =============== CL_ParticleEffectSparks =============== */ void CL_ParticleEffectSparks (vec3_t org, vec3_t dir, vec3_t color, int count) { int i; float d; cparticle_t *p; for (i=0 ; i8)?130:65, 0, color[0]/255, color[1]/255, color[2]/255); } /* =============== CL_ParticleBulletDecal =============== */ #define DECAL_OFFSET 0.5f void CL_ParticleBulletDecal (vec3_t org, vec3_t dir, float size) { cparticle_t *p; vec3_t ang, angle, end, origin; trace_t tr; if (!r_decals->value) return; VectorMA(org, DECAL_OFFSET, dir, origin); VectorMA(org, -DECAL_OFFSET, dir, end); tr = CL_Trace (origin, end, 0, CONTENTS_SOLID); //tr = CL_Trace (origin, end, 1, 1); if (tr.fraction == 1) //if (!tr.allsolid) return; VectorNegate(tr.plane.normal, angle); //VectorNegate(dir, angle); VecToAngleRolled(angle, rand()%360, ang); VectorCopy(tr.endpos, origin); p = CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 1, -1/r_decal_life->value, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, size, 0, particle_bulletmark, PART_SHADED|PART_DECAL|PART_ALPHACOLOR, // was part_saturate CL_DecalAlphaThink, true); } /* =============== CL_ParticleRailDecal =============== */ #define RAIL_DECAL_OFFSET 2.0f void CL_ParticleRailDecal (vec3_t org, vec3_t dir, float size, qboolean isRed) { vec3_t ang, angle, end, origin; trace_t tr; if (!r_decals->value) return; VectorMA(org, -RAIL_DECAL_OFFSET, dir, origin); VectorMA(org, 2*RAIL_DECAL_OFFSET, dir, end); tr = CL_Trace (origin, end, 0, CONTENTS_SOLID); if (tr.fraction==1) return; if (VectorCompare(tr.plane.normal, vec3_origin)) return; VectorNegate(tr.plane.normal, angle); VecToAngleRolled(angle, rand()%360, ang); VectorCopy(tr.endpos, origin); CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 1, -1/r_decal_life->value, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, size, 0, particle_bulletmark, PART_SHADED|PART_DECAL|PART_ALPHACOLOR, CL_DecalAlphaThink, true); CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, (isRed)?255:cl_railred->value, (isRed)?20:cl_railgreen->value, (isRed)?20:cl_railblue->value, 0, 0, 0, 1, -0.25, GL_SRC_ALPHA, GL_ONE, size, 0, particle_generic, PART_DECAL, NULL, false); CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 1, -0.25, GL_SRC_ALPHA, GL_ONE, size*0.67, 0, particle_generic, PART_DECAL, NULL, false); } /* =============== CL_ParticleBlasterDecal =============== */ void CL_ParticleBlasterDecal (vec3_t org, vec3_t dir, float size, int red, int green, int blue) { cparticle_t *p; vec3_t ang, angle, end, origin; trace_t tr; if (!r_decals->value) return; VectorMA(org, DECAL_OFFSET, dir, origin); VectorMA(org, -DECAL_OFFSET, dir, end); tr = CL_Trace (origin, end, 0, CONTENTS_SOLID); if (tr.fraction==1) return; if (VectorCompare(tr.plane.normal, vec3_origin)) return; VectorNegate(tr.plane.normal, angle); VecToAngleRolled(angle, rand()%360, ang); VectorCopy(tr.endpos, origin); p = CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0.7, -1/r_decal_life->value, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, size, 0, particle_shadow, PART_SHADED|PART_DECAL, NULL, false); p = CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, red, green, blue, 0, 0, 0, 1, -0.3, GL_SRC_ALPHA, GL_ONE, size*0.4, 0, particle_generic, PART_SHADED|PART_DECAL, NULL, false); p = CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, red, green, blue, 0, 0, 0, 1, -0.6, GL_SRC_ALPHA, GL_ONE, size*0.3, 0, particle_generic, PART_SHADED|PART_DECAL, NULL, false); } /* =============== CL_ParticlePlasmaBeamDecal =============== */ void CL_ParticlePlasmaBeamDecal (vec3_t org, vec3_t dir, float size) { cparticle_t *p; vec3_t ang, angle, end, origin; trace_t tr; if (!r_decals->value) return; VectorMA(org, DECAL_OFFSET, dir, origin); VectorMA(org, -DECAL_OFFSET, dir, end); tr = CL_Trace (origin, end, 0, CONTENTS_SOLID); if (tr.fraction==1) return; if (VectorCompare(tr.plane.normal, vec3_origin)) return; VectorNegate(tr.plane.normal, angle); VecToAngleRolled(angle, rand()%360, ang); VectorCopy(tr.endpos, origin); p = CL_SetupParticle ( ang[0], ang[1], ang[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0.85, -1/r_decal_life->value, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, size, 0, particle_shadow, PART_SHADED|PART_DECAL, NULL, false); } /* =============== CL_TeleporterParticles =============== */ void CL_TeleporterParticles (entity_state_t *ent) { int i; for (i = 0; i < 8; i++) { CL_SetupParticle ( 0, 0, 0, ent->origin[0]-16+(rand()&31), ent->origin[1]-16+(rand()&31), ent->origin[2]-16+(rand()&31), crand()*14, crand()*14, 80 + (rand()&7), 0, 0, 0, 230+crand()*25, 125+crand()*25, 25+crand()*25, 0, 0, 0, 1, -0.5, GL_SRC_ALPHA, GL_ONE, 2, 0, particle_generic, PART_GRAVITY, NULL,0); } } /* =============== CL_LogoutEffect =============== */ void CL_LogoutEffect (vec3_t org, int type) { int i; vec3_t color; for (i=0 ; i<500 ; i++) { if (type == MZ_LOGIN)// green { color[0] = 20; color[1] = 200; color[2] = 20; } else if (type == MZ_LOGOUT)// red { color[0] = 200; color[1] = 20; color[2] = 20; } else// yellow { color[0] = 200; color[1] = 200; color[2] = 20; } CL_SetupParticle ( 0, 0, 0, org[0] - 16 + frand()*32, org[1] - 16 + frand()*32, org[2] - 24 + frand()*56, crand()*20, crand()*20, crand()*20, 0, 0, 0, color[0], color[1], color[2], 0, 0, 0, 1, -1.0 / (1.0 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 1, 0, particle_generic, PART_GRAVITY, NULL,0); } } /* =============== CL_ItemRespawnParticles =============== */ void CL_ItemRespawnParticles (vec3_t org) { int i; for (i=0 ; i<64 ; i++) { CL_SetupParticle ( 0, 0, 0, org[0] + crand()*8, org[1] + crand()*8, org[2] + crand()*8, crand()*8, crand()*8, crand()*8, 0, 0, PARTICLE_GRAVITY*0.2, 0, 150+rand()*25, 0, 0, 0, 0, 1, -1.0 / (1.0 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 1, 0, particle_generic, PART_GRAVITY, NULL,0); } } /* =============== CL_BigTeleportParticles =============== */ void CL_BigTeleportParticles (vec3_t org) { int i, index; float angle, dist; static int colortable0[4] = {10,50,150,50}; static int colortable1[4] = {150,150,50,10}; static int colortable2[4] = {50,10,10,150}; for (i=0; i<(1024/max(cl_particle_scale->value, 1.0f)); i++) // was 4096 { index = rand()&3; angle = M_PI*2*(rand()&1023)/1023.0; dist = rand()&31; CL_SetupParticle ( 0, 0, 0, org[0]+cos(angle)*dist, org[1] + sin(angle)*dist,org[2] + 8 + (rand()%90), cos(angle)*(70+(rand()&63)),sin(angle)*(70+(rand()&63)),-100 + (rand()&31), -cos(angle)*100, -sin(angle)*100,PARTICLE_GRAVITY*4, colortable0[index], colortable1[index], colortable2[index], 0, 0, 0, 1, -0.1 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 5, 0.15 / (0.5 + frand()*0.3), // was 2, 0.05 particle_generic, 0, NULL,0); } } /* =============== CL_ParticleBlasterThink Wall impact puffs =============== */ #define pBlasterMaxVelocity 100 #define pBlasterMinSize 1.0 #define pBlasterMaxSize 5.0 void CL_ParticleBlasterThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { vec_t length; vec3_t len; float clipsize = 1.0; VectorSubtract(p->angle, org, len); *size *= (float)(pBlasterMaxSize/VectorLength(len)) * 1.0/((4-*size)); *size += *time * p->sizevel; if (*size > pBlasterMaxSize) *size = pBlasterMaxSize; if (*size < pBlasterMinSize) *size = pBlasterMinSize; CL_ParticleBounceThink (p, org, angle, alpha, &clipsize, image, time); // was size length = VectorNormalize(p->vel); if (length>pBlasterMaxVelocity) VectorScale(p->vel, pBlasterMaxVelocity, p->vel); else VectorScale(p->vel, length, p->vel); /* vec3_t len; VectorSubtract(p->angle, org, len); *size *= (float)(pBlasterMaxSize/VectorLength(len)) * 1.0/((4-*size)); if (*size > pBlasterMaxSize) *size = pBlasterMaxSize; p->thinknext = true;*/ } /* =============== CL_BlasterParticles Wall impact puffs =============== */ void CL_BlasterParticles (vec3_t org, vec3_t dir, int count, float size, int red, int green, int blue, int reddelta, int greendelta, int bluedelta) { int i; float speed = .75; cparticle_t *p; vec3_t origin; for (i = 0; i < count; i++) { VectorSet(origin, org[0] + dir[0]*(1 + random()*3 + pBlasterMaxSize/2.0), org[1] + dir[1]*(1 + random()*3 + pBlasterMaxSize/2.0), org[2] + dir[2]*(1 + random()*3 + pBlasterMaxSize/2.0) ); p = CL_SetupParticle ( org[0], org[1], org[2], origin[0], origin[1], origin[2], (dir[0]*75 + crand()*40)*speed, (dir[1]*75 + crand()*40)*speed, (dir[2]*75 + crand()*40)*speed, 0, 0, 0, red, green, blue, reddelta, greendelta, bluedelta, 1, -0.5 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, size, size*-0.125, // was 4, -0.5 particle_generic, PART_GRAVITY, CL_ParticleBlasterThink,true); /* d = rand()&5; p = CL_SetupParticle ( org[0], org[1], org[2], org[0]+((rand()&5)-2)+d*dir[0], org[1]+((rand()&5)-2)+d*dir[1], org[2]+((rand()&5)-2)+d*dir[2], (dir[0]*50 + crand()*20)*speed, (dir[1]*50 + crand()*20)*speed, (dir[2]*50 + crand()*20)*speed, 0, 0, 0, red, green, blue, reddelta, greendelta, bluedelta, 1, -1.0 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 4, -1.0, particle_generic, PART_GRAVITY, CL_ParticleBlasterThink,true);*/ } if (p) // added light effect CL_AddParticleLight (p, 150, 0, ((float)red)/255, ((float)green)/255, ((float)blue)/255); } /* =============== CL_BlasterTrail =============== */ void CL_BlasterTrail (vec3_t start, vec3_t end, int red, int green, int blue, int reddelta, int greendelta, int bluedelta) { vec3_t move; vec3_t vec; float len; int dec; VectorCopy (start, move); // VectorSubtract (end, start, vec); VectorSubtract (start, end, vec); len = VectorNormalize (vec); VectorMA (move, -5.0f, vec, move); dec = 4 * cl_particle_scale->value; VectorScale (vec, dec, vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0] + crand(), move[1] + crand(), move[2] + crand(), crand()*5, crand()*5, crand()*5, 0, 0, 0, red, green, blue, reddelta, greendelta, bluedelta, 1, -1.0 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 3, -7, // was 4, -6; particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_HyperBlasterGlow Hyperblaster particle glow effect =============== */ #if 1 void CL_HyperBlasterGlow (vec3_t start, vec3_t end, int red, int green, int blue, int reddelta, int greendelta, int bluedelta) { vec3_t move, vec; float len, dec, size; int i; VectorCopy (start, move); VectorSubtract (start, end, vec); len = VectorNormalize (vec); VectorMA (move, -16.5f, vec, move); dec = 3.0f; // was 1, 5 VectorScale (vec, dec, vec); for (i = 0; i < 12; i++) // was 18 { size = 4.2f - (0.1f*(float)i); CL_SetupParticle ( 0, 0, 0, move[0] + 0.5*crand(), move[1] + 0.5*crand(), move[2] + 0.5*crand(), crand()*5, crand()*5, crand()*5, 0, 0, 0, red, green, blue, reddelta, greendelta, bluedelta, 1, INSTANT_PARTICLE, // was -16.0 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, size, 0, // was 3, -36; 5, -60 particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } #else void CL_HyperBlasterTrail (vec3_t start, vec3_t end, int red, int green, int blue, int reddelta, int greendelta, int bluedelta) { vec3_t move; vec3_t vec; float len; int dec; int i; VectorCopy (start, move); VectorSubtract (end, start, vec); VectorMA (move, 0.25, vec, move); // was 0.5 len = VectorNormalize (vec); dec = 5; // was 1 VectorScale (vec, dec, vec); for (i = 0; i < 5; i++) // was 18 { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0] + 0.5*crand(), move[1] + 0.5*crand(), move[2] + 0.5*crand(), crand()*5, crand()*5, crand()*5, 0, 0, 0, red, green, blue, reddelta, greendelta, bluedelta, 1, -16.0 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 5, -60, // was 3, -36 particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } #endif /* =============== CL_BlasterTracer =============== */ void CL_BlasterTracer (vec3_t origin, vec3_t angle, int red, int green, int blue, float len, float size) { // int i; vec3_t dir; AngleVectors (angle, dir, NULL, NULL); VectorScale (dir, len,dir); //for (i=0; i<3; i++) CL_SetupParticle ( dir[0], dir[1], dir[2], origin[0], origin[1], origin[2], 0, 0, 0, 0, 0, 0, red, green, blue, 0, 0, 0, 1, INSTANT_PARTICLE, GL_ONE, GL_ONE, // was GL_SRC_ALPHA, GL_ONE size, 0, particle_blasterblob, // was particle_generic PART_DIRECTION|PART_INSTANT|PART_OVERBRIGHT, NULL,0); } void CL_HyperBlasterEffect (vec3_t start, vec3_t end, vec3_t angle, int red, int green, int blue, int reddelta, int greendelta, int bluedelta, float len, float size) { if (cl_particle_scale->value < 2) // CL_HyperBlasterTrail (start, end, red, green, blue, reddelta, greendelta, bluedelta); CL_HyperBlasterGlow (start, end, red, green, blue, reddelta, greendelta, bluedelta); //else //if (cl_particle_scale->value >= 2) CL_BlasterTracer (end, angle, red, green, blue, len, size); } /* =============== CL_QuadTrail =============== */ void CL_QuadTrail (vec3_t start, vec3_t end) { vec3_t move; vec3_t vec; float len; int dec; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 5; VectorScale (vec, 5, vec); while (len > 0) { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0] + crand()*16, move[1] + crand()*16, move[2] + crand()*16, crand()*5, crand()*5, crand()*5, 0, 0, 0, 0, 0, 200, 0, 0, 0, 1, -1.0 / (0.8+frand()*0.2), GL_SRC_ALPHA, GL_ONE, 1, 0, particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_FlagTrail =============== */ void CL_FlagTrail (vec3_t start, vec3_t end, qboolean isred, qboolean isgreen) { vec3_t move; vec3_t vec; float len; int dec; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 5; VectorScale (vec, 5, vec); while (len > 0) { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0] + crand()*16, move[1] + crand()*16, move[2] + crand()*16, crand()*5, crand()*5, crand()*5, 0, 0, 0, (isred)?255:0, (isgreen)?255:0, (!isred && !isgreen)?255:0, 0, 0, 0, 1, -1.0 / (0.8+frand()*0.2), GL_SRC_ALPHA, GL_ONE, 1, 0, particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_DiminishingTrail =============== */ void CL_DiminishingTrail (vec3_t start, vec3_t end, centity_t *old, int flags) { cparticle_t *p; vec3_t move; vec3_t vec; float len, oldlen; float dec; float orgscale; float velscale; VectorCopy (start, move); VectorSubtract (end, start, vec); len = oldlen = VectorNormalize (vec); dec = (flags & EF_ROCKET) ? 10 : 2; dec *= cl_particle_scale->value; VectorScale (vec, dec, vec); if (old->trailcount > 900) { orgscale = 4; velscale = 15; } else if (old->trailcount > 800) { orgscale = 2; velscale = 10; } else { orgscale = 1; velscale = 5; } while (len > 0) { len -= dec; if (!free_particles) return; if (flags & EF_ROCKET) { if (CM_PointContents(move,0) & MASK_WATER) CL_SetupParticle ( 0, 0, crand()*360, move[0], move[1], move[2], crand()*9, crand()*9, crand()*9+5, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0.75, -0.2 / (1 + frand() * 0.2), GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1+random()*3, 1, particle_bubble, PART_TRANS|PART_SHADED, CL_ExplosionBubbleThink, true); else CL_SetupParticle ( crand()*180, crand()*100, 0, move[0], move[1], move[2], crand()*5, crand()*5, crand()*10, 0, 0, 5, 255, 255, 255, -50, -50, -50, 0.75, -0.75, // was 1, -0.5 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 5, 15, particle_smoke, PART_TRANS|PART_SHADED, CL_ParticleRotateThink, true); } else { // drop less particles as it flies if ((rand()&1023) < old->trailcount) { if (flags & EF_GIB) { if (cl_blood->value > 1) p = CL_SetupParticle ( 0, 0, random()*360, move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale, crand()*velscale, crand()*velscale, crand()*velscale, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0.75, -0.75 / (1+frand()*0.4), GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 3 + random()*2, 0, particle_blooddrop, PART_OVERBRIGHT|PART_GRAVITY|PART_SHADED, CL_ParticleBloodThink,true); //NULL,0); else p = CL_SetupParticle ( 0, 0, 0, move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale, crand()*velscale, crand()*velscale, crand()*velscale, 0, 0, 0, 255, 0, 0, 0, 0, 0, 1, -1.0 / (1+frand()*0.4), GL_SRC_ALPHA, GL_ONE, 5, -1, particle_blood, PART_GRAVITY|PART_SHADED, CL_ParticleBloodThink,true); //NULL,0); if ( p && (crand() < (double)0.0001F) ) p->flags |= PART_LEAVEMARK; } else if (flags & EF_GREENGIB) { p = CL_SetupParticle ( 0, 0, 0, move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale, crand()*velscale, crand()*velscale, crand()*velscale, 0, 0, 0, 255, 180, 50, 0, 0, 0, 1, -0.5 / (1+frand()*0.4), GL_SRC_ALPHA, GL_ONE, 5, -1, particle_blood, PART_OVERBRIGHT|PART_GRAVITY|PART_SHADED, CL_ParticleBloodThink,true); //NULL,0); if ( p && (crand() < (double)0.0001F) ) p->flags |= PART_LEAVEMARK; } else if (flags & EF_GRENADE) // no overbrights on grenade trails { if (CM_PointContents(move,0) & MASK_WATER) CL_SetupParticle ( 0, 0, crand()*360, move[0], move[1], move[2], crand()*9, crand()*9, crand()*9+5, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0.75, -0.2 / (1 + frand() * 0.2), GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1+random()*3, 1, particle_bubble, PART_TRANS|PART_SHADED, CL_ExplosionBubbleThink,true); else CL_SetupParticle ( crand()*180, crand()*50, 0, move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale, crand()*velscale, crand()*velscale, crand()*velscale, 0, 0, 20, 255, 255, 255, 0, 0, 0, 0.5, -0.5, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 5, 5, particle_smoke, PART_TRANS|PART_SHADED, CL_ParticleRotateThink,true); } else { CL_SetupParticle ( crand()*180, crand()*50, 0, move[0] + crand()*orgscale, move[1] + crand()*orgscale, move[2] + crand()*orgscale, crand()*velscale, crand()*velscale, crand()*velscale, 0, 0, 20, 255, 255, 255, 0, 0, 0, 0.5, -0.5, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 5, 5, particle_smoke, PART_OVERBRIGHT|PART_TRANS|PART_SHADED, CL_ParticleRotateThink,true); } } old->trailcount -= 5; if (old->trailcount < 100) old->trailcount = 100; } VectorAdd (move, vec, move); } } /* =============== CL_RocketTrail =============== */ void CL_RocketTrail (vec3_t start, vec3_t end, centity_t *old) { vec3_t move; vec3_t vec; float len, totallen; float dec; // smoke CL_DiminishingTrail (start, end, old, EF_ROCKET); // fire VectorCopy (start, move); VectorSubtract (end, start, vec); totallen = len = VectorNormalize (vec); dec = 1 * cl_particle_scale->value; VectorScale (vec, dec, vec); while (len > 0) { len -= dec; if (!free_particles) return; // falling particles if ( (rand()&7) == 0) { CL_SetupParticle ( 0, 0, 0, move[0] + crand()*5, move[1] + crand()*5, move[2] + crand()*5, crand()*20, crand()*20, crand()*20, 0, 0, 20, 255, 255, 200, 0, -50, 0, 1, -1.0 / (1+frand()*0.2), GL_SRC_ALPHA, GL_ONE, 2, -2, particle_blaster, PART_GRAVITY, NULL,0); } VectorAdd (move, vec, move); } VectorCopy (start, move); VectorSubtract (end, start, vec); totallen = len = VectorNormalize (vec); dec = 1.5 * cl_particle_scale->value; VectorScale (vec, dec, vec); /* len = totallen; VectorCopy (start, move); dec = 1.5;// * cl_particle_scale->value; VectorScale (vec, dec, vec);*/ while (len > 0) { len -= dec; // flame CL_SetupParticle ( crand()*180, crand()*100, 0, move[0], move[1], move[2], crand()*5, crand()*5, crand()*5, 0, 0, 5, 255, 225, 200, -50, -50, -50, 0.5, -2, // was 0.75, -3 GL_SRC_ALPHA, GL_ONE, 5, 5, particle_inferno, 0, CL_ParticleRotateThink, true); VectorAdd (move, vec, move); } } /* =============== CL_RailSprial =============== */ #define DEVRAILSTEPS 2 //this is the length of each piece... #define RAILTRAILSPACE 15 void CL_RailSprial (vec3_t start, vec3_t end, qboolean isRed) { vec3_t move; vec3_t vec; float len; vec3_t right, up; int i; float d, c, s; vec3_t dir; // Draw from closest point if (FartherPoint(start, end)) { VectorCopy (end, move); VectorSubtract (start, end, vec); } else { VectorCopy (start, move); VectorSubtract (end, start, vec); } len = VectorNormalize (vec); len = min (len, cl_rail_length->value); // cap length MakeNormalVectors (vec, right, up); VectorScale(vec, cl_rail_space->value * cl_particle_scale->value, vec); for (i=0; ivalue * cl_particle_scale->value) { d = i * 0.1; c = cos(d); s = sin(d); VectorScale (right, c, dir); VectorMA (dir, s, up, dir); CL_SetupParticle ( 0, 0, 0, move[0] + dir[0]*3, move[1] + dir[1]*3, move[2] + dir[2]*3, dir[0]*6, dir[1]*6, dir[2]*6, 0, 0, 0, (isRed)?255:cl_railred->value, (isRed)?20:cl_railgreen->value, (isRed)?20:cl_railblue->value, 0, 0, 0, 1, -1.0, GL_SRC_ALPHA, GL_ONE, 3, 0, particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_ParticleDevRailThink =============== */ void CL_ParticleDevRailThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { int i; vec3_t len; VectorSubtract(p->angle, org, len); *size *= (float)(SplashSize/VectorLength(len)) * 0.5/((4-*size)); if (*size > SplashSize) *size = SplashSize; //setting up angle for sparks { float time1, time2; time1 = *time; time2 = time1*time1; for (i=0;i<2;i++) angle[i] = 3*(p->vel[i]*time1 + (p->accel[i])*time2); angle[2] = 3*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2); } p->thinknext = true; } /* =============== CL_DevRailTrail =============== */ void CL_DevRailTrail (vec3_t start, vec3_t end, qboolean isRed) { vec3_t move; vec3_t vec, point; float len; int dec, i=0; // Draw from closest point if (FartherPoint(start, end)) { VectorCopy (end, move); VectorSubtract (start, end, vec); } else { VectorCopy (start, move); VectorSubtract (end, start, vec); } len = VectorNormalize (vec); len = min (len, cl_rail_length->value); // cap length VectorCopy(vec, point); dec = 4; VectorScale (vec, dec, vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= dec; i++; if (i>=DEVRAILSTEPS) { for (i=3;i>0;i--) CL_SetupParticle ( point[0], point[1], point[2], move[0], move[1], move[2], 0, 0, 0, 0, 0, 0, (isRed)?255:cl_railred->value, (isRed)?20:cl_railgreen->value, (isRed)?20:cl_railblue->value, 0, -90, -30, 0.75, -.75, GL_SRC_ALPHA, GL_ONE, dec*DEVRAILSTEPS*TWOTHIRDS, 0, particle_beam2, PART_DIRECTION, NULL,0); } CL_SetupParticle ( 0, 0, 0, move[0], move[1], move[2], crand()*10, crand()*10, crand()*10+20, 0, 0, 0, (isRed)?255:cl_railred->value, (isRed)?20:cl_railgreen->value, (isRed)?20:cl_railblue->value, 0, 0, 0, 1, -0.75 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 2, -0.25, particle_solid, PART_GRAVITY|PART_SPARK, CL_ParticleDevRailThink,true); CL_SetupParticle ( crand()*180, crand()*100, 0, move[0], move[1], move[2], crand()*10, crand()*10, crand()*10+20, 0, 0, 5, 255, 255, 255, 0, 0, 0, 0.25, -0.25, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 5, 10, particle_smoke, PART_TRANS|PART_GRAVITY|PART_OVERBRIGHT, CL_ParticleRotateThink, true); VectorAdd (move, vec, move); } } /* =============== CL_RailTrail =============== */ void CL_RailTrail (vec3_t start, vec3_t end, qboolean isRed) { vec3_t move, last; vec3_t vec, point; //vec3_t right, up; int i; int beamred, beamgreen, beamblue; float len;//, dec; qboolean colored = (cl_railtype->value!=0); VectorSubtract (end, start, vec); VectorNormalize(vec); CL_ParticleRailDecal (end, vec, 7, isRed); if (cl_railtype->value == 2) { CL_DevRailTrail (start, end, isRed); return; } // Draw from closest point if (FartherPoint(start, end)) { VectorCopy (end, move); VectorSubtract (start, end, vec); } else { VectorCopy (start, move); VectorSubtract (end, start, vec); } len = VectorNormalize (vec); if (cl_railtype->value == 0) len = min (len, cl_rail_length->value); // cap length VectorCopy (vec, point); VectorScale (vec, RAILTRAILSPACE, vec); //MakeNormalVectors (vec, right, up); if (colored) { if (isRed) { beamred = 255; beamgreen = beamblue = 20; } else { beamred = cl_railred->value; beamgreen = cl_railgreen->value; beamblue = cl_railblue->value; } } else beamred = beamgreen = beamblue = 255; while (len > 0) { VectorCopy (move, last); VectorAdd (move, vec, move); len -= RAILTRAILSPACE; for (i=0;i<3;i++) CL_SetupParticle ( last[0], last[1], last[2], move[0], move[1], move[2], 0, 0, 0, 0, 0, 0, beamred, beamgreen, beamblue, 0, 0, 0, 0.75, -0.75, GL_SRC_ALPHA, GL_ONE, RAILTRAILSPACE*TWOTHIRDS, (colored)?0:-5, particle_beam2, PART_BEAM, NULL,0); } if (cl_railtype->value == 0) CL_RailSprial (start, end, isRed); } // RAFAEL /* =============== CL_IonripperTrail =============== */ void CL_IonripperTrail (vec3_t start, vec3_t ent) { vec3_t move; vec3_t vec; vec3_t leftdir,up; float len; int dec; int left = 0; VectorCopy (start, move); VectorSubtract (ent, start, vec); len = VectorNormalize (vec); MakeNormalVectors (vec, leftdir, up); dec = 3 * cl_particle_scale->value; VectorScale (vec, dec, vec); while (len > 0) { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0], move[1], move[2], 0, 0, 0, 0, 0, 0, 255, 75, 0, 0, 0, 0, 0.75, -1.0 / (0.3 + frand() * 0.2), GL_SRC_ALPHA, GL_ONE, 3, 0, // was dec particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_BubbleTrail =============== */ void CL_BubbleTrail (vec3_t start, vec3_t end) { vec3_t move; vec3_t vec; float len; int i; float dec, size; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 32; VectorScale (vec, dec, vec); for (i=0 ; i0.25)? 1 : (frand()>0.5) ? 2 : (frand()>0.75) ? 3 : 4; CL_SetupParticle ( 0, 0, 0, move[0]+crand()*2, move[1]+crand()*2, move[2]+crand()*2, crand()*5, crand()*5, crand()*5+6, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0.75, -0.5 / (1 + frand() * 0.2), GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, size, 1, particle_bubble, PART_TRANS|PART_SHADED, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_FlyParticles =============== */ #define BEAMLENGTH 16 void CL_FlyParticles (vec3_t origin, int count) { int i; float angle; float sr, sp, sy, cr, cp, cy; vec3_t forward; float dist = 64; float ltime; if (count > NUMVERTEXNORMALS) count = NUMVERTEXNORMALS; if (!avelocities[0][0]) { for (i=0 ; ifly_stoptime < cl.time) { starttime = cl.time; ent->fly_stoptime = cl.time + 60000; } else { starttime = ent->fly_stoptime - 60000; } n = cl.time - starttime; if (n < 20000) count = n * 162 / 20000.0; else { n = ent->fly_stoptime - cl.time; if (n < 20000) count = n * 162 / 20000.0; else count = 162; } CL_FlyParticles (origin, count); } /* =============== CL_ParticleBFGThink =============== */ void CL_ParticleBFGThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { vec3_t len; VectorSubtract(p->angle, p->org, len); *size = (float)((300/VectorLength(len))*0.75); } #define BEAMLENGTH 16 /* =============== CL_BfgParticles =============== */ void CL_BfgParticles (entity_t *ent) { int i; cparticle_t *p; float angle; float sr, sp, sy, cr, cp, cy; vec3_t forward; float dist = 64, dist2; vec3_t v; float ltime; if (!avelocities[0][0]) { for (i=0 ; iorigin[0], ent->origin[1], ent->origin[2], ent->origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH,ent->origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH, ent->origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH, 0, 0, 0, 0, 0, 0, 50, 200*dist2, 20, 0, 0, 0, 1, -100, GL_SRC_ALPHA, GL_ONE, 1, 1, particle_generic, 0, CL_ParticleBFGThink, true); if (!p) return; VectorSubtract (p->org, ent->origin, v); dist = VectorLength(v) / 90.0; } } // RAFAEL /* =============== CL_TrapParticles =============== */ void CL_TrapParticles (entity_t *ent) { vec3_t move; vec3_t vec; vec3_t start, end; float len; int dec; ent->origin[2]-=14; VectorCopy (ent->origin, start); VectorCopy (ent->origin, end); end[2]+=64; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 5; VectorScale (vec, 5, vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0] + crand(), move[1] + crand(), move[2] + crand(), crand()*15, crand()*15, crand()*15, 0, 0, PARTICLE_GRAVITY, 230+crand()*25, 125+crand()*25, 25+crand()*25, 0, 0, 0, 1, -1.0 / (0.3+frand()*0.2), GL_SRC_ALPHA, GL_ONE, 3, -3, particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } { int i, j, k; float vel; vec3_t dir; vec3_t org; ent->origin[2]+=14; VectorCopy (ent->origin, org); for (i=-2 ; i<=2 ; i+=4) for (j=-2 ; j<=2 ; j+=4) for (k=-2 ; k<=4 ; k+=4) { dir[0] = j * 8; dir[1] = i * 8; dir[2] = k * 8; VectorNormalize (dir); vel = 50 + rand()&63; CL_SetupParticle ( 0, 0, 0, org[0] + i + ((rand()&23) * crand()), org[1] + j + ((rand()&23) * crand()), org[2] + k + ((rand()&23) * crand()), dir[0]*vel, dir[1]*vel, dir[2]*vel, 0, 0, 0, 230+crand()*25, 125+crand()*25, 25+crand()*25, 0, 0, 0, 1, -1.0 / (0.3+frand()*0.2), GL_SRC_ALPHA, GL_ONE, 1, 1, particle_generic, PART_GRAVITY, NULL,0); } } } /* =============== CL_BFGExplosionParticles =============== */ //FIXME combined with CL_ExplosionParticles void CL_BFGExplosionParticles (vec3_t org) { int i; for (i=0 ; i<256 ; i++) { CL_SetupParticle ( 0, 0, 0, org[0] + ((rand()%32)-16), org[1] + ((rand()%32)-16), org[2] + ((rand()%32)-16), (rand()%150)-75, (rand()%150)-75, (rand()%150)-75, 0, 0, 0, 50, 100+rand()*50, 0, //Knightmare- made more green 0, 0, 0, 1, -0.8 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 10, -10, particle_generic, PART_GRAVITY, NULL,0); } } /* =============== CL_TeleportParticles =============== */ void CL_TeleportParticles (vec3_t org) { int i, j, k; float vel; vec3_t dir; for (i=-16 ; i<=16 ; i+=4) for (j=-16 ; j<=16 ; j+=4) for (k=-16 ; k<=32 ; k+=4) { dir[0] = j*16; dir[1] = i*16; dir[2] = k*16; VectorNormalize (dir); vel = 150 + (rand()&63); CL_SetupParticle ( 0, 0, 0, org[0]+i+(rand()&3), org[1]+j+(rand()&3), org[2]+k+(rand()&3), dir[0]*vel, dir[1]*vel, dir[2]*vel, 0, 0, 0, 200 + 55*rand(), 200 + 55*rand(), 200 + 55*rand(), 0, 0, 0, 1, -1.0 / (0.3 + (rand()&7) * 0.02), GL_SRC_ALPHA, GL_ONE, 1, 3, particle_generic, PART_GRAVITY, NULL,0); } } /* =============== CL_Flashlight =============== */ void CL_Flashlight (int ent, vec3_t pos) { cdlight_t *dl; dl = CL_AllocDlight (ent); VectorCopy (pos, dl->origin); dl->radius = 400; dl->minlight = 250; dl->die = cl.time + 100; dl->color[0] = 1; dl->color[1] = 1; dl->color[2] = 1; } /* =============== CL_ColorFlash - flash of light =============== */ void CL_ColorFlash (vec3_t pos, int ent, int intensity, float r, float g, float b) { cdlight_t *dl; dl = CL_AllocDlight (ent); VectorCopy (pos, dl->origin); dl->radius = intensity; dl->minlight = 250; dl->die = cl.time + 100; dl->color[0] = r; dl->color[1] = g; dl->color[2] = b; } /* =============== CL_DebugTrail =============== */ void CL_DebugTrail (vec3_t start, vec3_t end) { vec3_t move; vec3_t vec; float len; float dec; vec3_t right, up; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); MakeNormalVectors (vec, right, up); dec = 8; // was 2 VectorScale (vec, dec, vec); VectorCopy (start, move); while (len > 0) { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0], move[1], move[2], 0, 0, 0, 0, 0, 0, 50, 50, 255, 0, 0, 0, 1, -0.75, GL_SRC_ALPHA, GL_ONE, 7.5, 0, particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_ForceWall =============== */ void CL_ForceWall (vec3_t start, vec3_t end, int color8) { vec3_t move; vec3_t vec; float len; vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)}; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); VectorScale (vec, 4, vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= 4; if (frand() > 0.3) CL_SetupParticle ( 0, 0, 0, move[0] + crand()*3, move[1] + crand()*3, move[2] + crand()*3, 0, 0, -40 - (crand()*10), 0, 0, 0, color[0]+5, color[1]+5, color[2]+5, 0, 0, 0, 1, -1.0 / (3.0+frand()*0.5), GL_SRC_ALPHA, GL_ONE, 5, 0, particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_BubbleTrail2 (lets you control the # of bubbles by setting the distance between the spawns) =============== */ void CL_BubbleTrail2 (vec3_t start, vec3_t end, int dist) { vec3_t move; vec3_t vec; float len; int i; float dec, size; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = dist; VectorScale (vec, dec, vec); for (i=0 ; i0.25)? 1 : (frand()>0.5) ? 2 : (frand()>0.75) ? 3 : 4; CL_SetupParticle ( 0, 0, 0, move[0]+crand()*2, move[1]+crand()*2, move[2]+crand()*2, crand()*5, crand()*5, crand()*5+6, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0.75, -0.5 / (1 + frand() * 0.2), GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, size, 1, particle_bubble, PART_TRANS|PART_SHADED, NULL,0); VectorAdd (move, vec, move); } } /* =============== CL_HeatbeamParticles =============== */ void CL_HeatbeamParticles (vec3_t start, vec3_t forward) { vec3_t move; vec3_t vec; float len; vec3_t right, up; int i; float c, s; vec3_t dir; float ltime; float step, rstep; float start_pt; float rot; float variance; float size; int maxsteps; vec3_t end; VectorMA (start, 4096, forward, end); VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); // FIXME - pmm - these might end up using old values? //MakeNormalVectors (vec, right, up); VectorCopy (cl.v_right, right); VectorCopy (cl.v_up, up); if (cg_thirdperson->integer) { ltime = (float) cl.time/250.0; step = 96; maxsteps = 10; variance = 1.2; size = 2; } else { ltime = (float) cl.time/1000.0; step = 32; maxsteps = 7; variance = 0.5; size = 1; } // this just misaligns rings with beam //VectorMA (move, -0.5, right, move); //VectorMA (move, -0.5, up, move); //ltime = (float) cl.time/1000.0; start_pt = fmod(ltime*96.0,step); VectorMA (move, start_pt, vec, move); VectorScale (vec, step, vec); //Com_Printf ("%f\n", ltime); rstep = M_PI/10.0 * min(cl_particle_scale->value, 2); for (i=start_pt; istep*maxsteps) // don't bother after the nth ring break; for (rot = 0; rot < M_PI*2; rot += rstep) { // variance = 0.5; c = cos(rot)*variance; s = sin(rot)*variance; // trim it so it looks like it's starting at the origin if (i < 10) { VectorScale (right, c*(i/10.0), dir); VectorMA (dir, s*(i/10.0), up, dir); } else { VectorScale (right, c, dir); VectorMA (dir, s, up, dir); } CL_SetupParticle ( 0, 0, 0, move[0]+dir[0]*2, move[1]+dir[1]*2, move[2]+dir[2]*2, //Knightmare- decreased radius 0, 0, 0, 0, 0, 0, 200+rand()*50, 200+rand()*25, rand()*50, 0, 0, 0, 0.25, -1000.0, // decreased alpha GL_SRC_ALPHA, GL_ONE, size, 1, // shrunk size particle_blaster, 0, NULL,0); } VectorAdd (move, vec, move); } } /* =============== CL_ParticleSteamEffect Puffs with velocity along direction, with some randomness thrown in =============== */ void CL_ParticleSteamEffect (vec3_t org, vec3_t dir, int red, int green, int blue, int reddelta, int greendelta, int bluedelta, int count, int magnitude) { int i; cparticle_t *p; float d; vec3_t r, u; //vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)}; //vectoangles2 (dir, angle_dir); //AngleVectors (angle_dir, f, r, u); MakeNormalVectors (dir, r, u); for (i=0 ; ivel); d = crand()*magnitude/3; VectorMA (p->vel, d, r, p->vel); d = crand()*magnitude/3; VectorMA (p->vel, d, u, p->vel); } } /* =============== CL_ParticleSteamEffect2 Puffs with velocity along direction, with some randomness thrown in =============== */ void CL_ParticleSteamEffect2 (cl_sustain_t *self) //vec3_t org, vec3_t dir, int color, int count, int magnitude) { int i; cparticle_t *p; float d; vec3_t r, u; vec3_t dir; int color8 = self->color + (rand()&7); vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)}; //vectoangles2 (dir, angle_dir); //AngleVectors (angle_dir, f, r, u); VectorCopy (self->dir, dir); MakeNormalVectors (dir, r, u); for (i=0; icount; i++) { p = CL_SetupParticle ( 0, 0, 0, self->org[0] + self->magnitude*0.1*crand(), self->org[1] + self->magnitude*0.1*crand(), self->org[2] + self->magnitude*0.1*crand(), 0, 0, 0, 0, 0, 0, color[0], color[1], color[2], 0, 0, 0, 1.0, -1.0 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 4, 0, particle_smoke, PART_GRAVITY, NULL,0); if (!p) return; VectorScale (dir, self->magnitude, p->vel); d = crand()*self->magnitude/3; VectorMA (p->vel, d, r, p->vel); d = crand()*self->magnitude/3; VectorMA (p->vel, d, u, p->vel); } self->nextthink += self->thinkinterval; } /* =============== CL_TrackerTrail =============== */ void CL_TrackerTrail (vec3_t start, vec3_t end) { vec3_t move; vec3_t vec; vec3_t forward,right,up,angle_dir; float len; cparticle_t *p; int dec; float dist; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); VectorCopy(vec, forward); vectoangles2 (forward, angle_dir); AngleVectors (angle_dir, forward, right, up); dec = 3 * max(cl_particle_scale->value/2, 1); VectorScale (vec, 3 * max(cl_particle_scale->value/2, 1), vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= dec; p = CL_SetupParticle ( 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, -2.0, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 2, 0, particle_generic, PART_TRANS, NULL,0); if (!p) return; dist = DotProduct(move, forward); VectorMA(move, 8 * cos(dist), up, p->org); VectorAdd (move, vec, move); } } /* =============== CL_TrackerShell =============== */ void CL_Tracker_Shell (vec3_t origin) { vec3_t dir; int i; cparticle_t *p; for(i=0; i < (300/max(cl_particle_scale->value, 1.0f)); i++) { p = CL_SetupParticle ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, -2.0, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0, //Knightmare- changed size particle_generic, PART_TRANS, NULL,0); if (!p) return; dir[0] = crand(); dir[1] = crand(); dir[2] = crand(); VectorNormalize(dir); VectorMA(origin, 40, dir, p->org); } } /* ====================== CL_MonsterPlasma_Shell ====================== */ void CL_MonsterPlasma_Shell(vec3_t origin) { vec3_t dir; int i; cparticle_t *p; for(i=0; i<40; i++) { p = CL_SetupParticle ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 140, 50, //Knightmare- this was all black 0, 0, 0, 1.0, INSTANT_PARTICLE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 2, 0, particle_generic, PART_TRANS|PART_INSTANT, NULL,0); if (!p) return; dir[0] = crand(); dir[1] = crand(); dir[2] = crand(); VectorNormalize(dir); VectorMA(origin, 10, dir, p->org); } } /* =============== CL_Widowbeamout =============== */ void CL_Widowbeamout (cl_sustain_t *self) { vec3_t dir; int i; static int colortable0[6] = {125, 255, 185, 125, 185, 255}; static int colortable1[6] = {185, 125, 255, 255, 125, 185}; static int colortable2[6] = {255, 185, 125, 185, 255, 125}; cparticle_t *p; float ratio; int index; ratio = 1.0 - (((float)self->endtime - (float)cl.time)/2100.0); for(i=0; i<300; i++) { index = rand()&5; p = CL_SetupParticle ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, colortable0[index], colortable1[index], colortable2[index], 0, 0, 0, 1.0, INSTANT_PARTICLE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 2, 0, particle_generic, PART_TRANS|PART_INSTANT, NULL,0); if (!p) return; dir[0] = crand(); dir[1] = crand(); dir[2] = crand(); VectorNormalize(dir); VectorMA(self->org, (45.0 * ratio), dir, p->org); } } /* ============ CL_Nukeblast ============ */ void CL_Nukeblast (cl_sustain_t *self) { vec3_t dir; int i; cparticle_t *p; static int colortable0[4] = {185, 155, 125, 95}; static int colortable1[4] = {185, 155, 125, 95}; static int colortable2[4] = {255, 255, 255, 255}; float ratio, size; int index; ratio = 1.0 - (((float)self->endtime - (float)cl.time)/1000.0); size = ratio*ratio; for(i=0; i<(700/max(cl_particle_scale->value, 1.0f)); i++) { index = rand()&3; p = CL_SetupParticle ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, colortable0[index], colortable1[index], colortable2[index], 0, 0, 0, 1-size, INSTANT_PARTICLE, GL_SRC_ALPHA, GL_ONE, 10*(0.5+ratio*0.5), -1, particle_generic, PART_INSTANT, NULL,0); if (!p) return; dir[0] = crand(); dir[1] = crand(); dir[2] = crand(); VectorNormalize(dir); VectorScale(dir, -1, p->angle); VectorMA(self->org, 200.0*size, dir, p->org); //was 100 VectorMA(vec3_origin, 400.0*size, dir, p->vel); //was 100 } } /* ============== CL_WidowSplash ============== */ void CL_WidowSplash (vec3_t org) { static int colortable[4] = {2*8,13*8,21*8,18*8}; int i; cparticle_t *p; vec3_t dir; for (i=0; i<256; i++) { p = CL_SetupParticle ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, rand()&255, rand()&255, rand()&255, 0, 0, 0, 1.0, -0.8 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 3, 0, particle_generic, 0, NULL,0); if (!p) return; dir[0] = crand(); dir[1] = crand(); dir[2] = crand(); VectorNormalize(dir); VectorMA(org, 45.0, dir, p->org); VectorMA(vec3_origin, 40.0, dir, p->vel); } } /* ================== CL_Tracker_Explode ================== */ void CL_Tracker_Explode (vec3_t origin) { vec3_t dir, backdir; int i; cparticle_t *p; for (i=0; i<(300/max(cl_particle_scale->value, 1.0f)); i++) { p = CL_SetupParticle ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -10, //was 20 0, 0, 0, 0, 0, 0, 1.0, -0.5, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 2, 0, particle_generic, PART_TRANS, NULL,0); if (!p) return; dir[0] = crand(); dir[1] = crand(); dir[2] = crand(); VectorNormalize(dir); VectorScale(dir, -1, backdir); VectorCopy (origin, p->org); //Knightmare- start at center, not edge // VectorMA(origin, 64, dir, p->org); VectorScale(dir, (crand()*128), p->vel); //was backdir, 64 } } /* =============== CL_TagTrail =============== */ void CL_TagTrail (vec3_t start, vec3_t end, int color8) { vec3_t move; vec3_t vec; float len; int dec; vec3_t color = { color8red(color8), color8green(color8), color8blue(color8)}; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 5; VectorScale (vec, 5, vec); while (len >= 0) { len -= dec; CL_SetupParticle ( 0, 0, 0, move[0] + crand()*16, move[1] + crand()*16, move[2] + crand()*16, crand()*5, crand()*5, crand()*5, 0, 0, 20, color[0], color[1], color[2], 0, 0, 0, 1.0, -1.0 / (0.8+frand()*0.2), GL_SRC_ALPHA, GL_ONE, 1.5, 0, particle_generic, 0, NULL,0); VectorAdd (move, vec, move); } } /* ========================== CL_ColorExplosionParticles ========================== */ void CL_ColorExplosionParticles (vec3_t org, int color8, int run) { int i; vec3_t color = {color8red(color8), color8green(color8), color8blue(color8)}; for (i=0 ; i<128 ; i++) { CL_SetupParticle ( 0, 0, 0, org[0] + ((rand()%32)-16), org[1] + ((rand()%32)-16), org[2] + ((rand()%32)-16), (rand()%256)-128, (rand()%256)-128, (rand()%256)-128, 0, 0, 20, color[0] + (rand() % run), color[1] + (rand() % run), color[2] + (rand() % run), 0, 0, 0, 1.0, -0.4 / (0.6 + frand()*0.2), GL_SRC_ALPHA, GL_ONE, 2, 1, particle_generic, 0, NULL,0); } } /* ======================= CL_ParticleSmokeEffect - like the steam effect, but unaffected by gravity ======================= */ void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, float size) { float alpha = fabs(crand())*0.25 + 0.750; CL_SetupParticle ( crand()*180, crand()*100, 0, org[0], org[1], org[2], dir[0], dir[1], dir[2], 0, 0, 10, 255, 255, 255, 0, 0, 0, alpha, -1.0, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, size, 5, particle_smoke, PART_TRANS|PART_SHADED|PART_OVERBRIGHT, CL_ParticleRotateThink,true); } /* =============== CL_ParticleElectricSparksThink =============== */ void CL_ParticleElectricSparksThink (cparticle_t *p, vec3_t org, vec3_t angle, float *alpha, float *size, int *image, float *time) { int i; //setting up angle for sparks { float time1, time2; time1 = *time; time2 = time1*time1; for (i=0;i<2;i++) angle[i] = 0.25*(p->vel[i]*time1 + (p->accel[i])*time2); angle[2] = 0.25*(p->vel[2]*time1 + (p->accel[2]-PARTICLE_GRAVITY)*time2); } p->thinknext = true; } /* =============== CL_ElectricParticles new sparks for Rogue turrets =============== */ void CL_ElectricParticles (vec3_t org, vec3_t dir, int count) { int i, j; vec3_t start; float d; for (i = 0; i < 40; i++) { d = rand()&31; for (j = 0; j < 3; j++) start[j] = org[j] + ((rand()&7)-4) + d*dir[j]; CL_SetupParticle ( 0, 0, 0, start[0], start[1], start[2], crand()*20, crand()*20, crand()*20, 0, 0, -PARTICLE_GRAVITY, 25, 100, 255, 50, 50, 50, 1, -1.0 / (0.5 + frand()*0.3), GL_SRC_ALPHA, GL_ONE, 6, -3, particle_solid, PART_GRAVITY|PART_SPARK, CL_ParticleElectricSparksThink, true); } } //Knightmare- removed for Psychospaz's enhanced particle code #if 0 /* =============== CL_SmokeTrail =============== */ void CL_SmokeTrail (vec3_t start, vec3_t end, int colorStart, int colorRun, int spacing) { vec3_t move; vec3_t vec; float len; int j; cparticle_t *p; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); VectorScale (vec, spacing, vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= spacing; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; VectorClear (p->accel); p->time = cl.time; p->alpha = 1.0; p->alphavel = -1.0 / (1+frand()*0.5); p->color = colorStart + (rand() % colorRun); for (j=0 ; j<3 ; j++) { p->org[j] = move[j] + crand()*3; p->accel[j] = 0; } p->vel[2] = 20 + crand()*5; VectorAdd (move, vec, move); } } /* =============== CL_FlameEffects =============== */ void CL_FlameEffects (centity_t *ent, vec3_t origin) { int n, count; int j; cparticle_t *p; count = rand() & 0xF; for(n=0;nnext; p->next = active_particles; active_particles = p; VectorClear (p->accel); p->time = cl.time; p->alpha = 1.0; p->alphavel = -1.0 / (1+frand()*0.2); p->color = 226 + (rand() % 4); for (j=0 ; j<3 ; j++) { p->org[j] = origin[j] + crand()*5; p->vel[j] = crand()*5; } p->vel[2] = crand() * -10; p->accel[2] = -PARTICLE_GRAVITY; } count = rand() & 0x7; for(n=0;nnext; p->next = active_particles; active_particles = p; VectorClear (p->accel); p->time = cl.time; p->alpha = 1.0; p->alphavel = -1.0 / (1+frand()*0.5); p->color = 0 + (rand() % 4); for (j=0 ; j<3 ; j++) { p->org[j] = origin[j] + crand()*3; } p->vel[2] = 20 + crand()*5; } } /* =============== CL_GenericParticleEffect =============== */ void CL_GenericParticleEffect (vec3_t org, vec3_t dir, int color, int count, int numcolors, int dirspread, float alphavel) { int i, j; cparticle_t *p; float d; for (i=0 ; inext; p->next = active_particles; active_particles = p; p->time = cl.time; if (numcolors > 1) p->color = color + (rand() & numcolors); else p->color = color; d = rand() & dirspread; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j]; p->vel[j] = crand()*20; } p->accel[0] = p->accel[1] = 0; p->accel[2] = -PARTICLE_GRAVITY; // VectorCopy (accel, p->accel); p->alpha = 1.0; p->alphavel = -1.0 / (0.5 + frand()*alphavel); // p->alphavel = alphavel; } } #endif //end Knightmare