/* Copyright (C) 1996-1997 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. */ #include "quakedef.h" #include "r_local.h" //#define MAX_PARTICLES 8192 // default max # of particles at one // time #define MAX_PARTICLES 16384 // default max # of particles at one #define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's // on the command line #define ZEROPROPERTIES (p->scale = 1; p->scaley = p->scale; p->blend = 0; p->alpha = 1; p->frame = 0; p->alphavel = 0;p->scalexvel = 0;p->scaleyvel = 0;p->anglevel[0] = 0;p->anglevel[1] = 0;p->anglevel[2] = 0;); int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; int ramp4[8] = {239, 236, 231, 227, 224, 0, 0, 0}; float defaultscale = 0.4f; particle_t *active_particles, *free_particles; particle_t *particles; extern flare_t *currentflare; flare_t *active_flares, *free_flares; flare_t *flares; int r_numparticles; int r_numflares; vec3_t r_pright, r_pup, r_ppn; void R_NormalFromHerePlease (vec3_t org, vec3_t steer); extern int particlespray; extern int particleblood; extern int particleset; extern int particlelit; int sprity = 1; // enabled if particle.spr exists and if r_particlesprite is enabled extern qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace); static trace_t Particle_TraceLine(vec3_t start, vec3_t end) { trace_t trace; memset(&trace, 0, sizeof(trace)); trace.fraction = 1.0f; trace.allsolid = true; VectorCopy(end, trace.endpos); trace.color = 4; SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); return trace; } /* =============== R_InitParticles =============== */ void R_InitParticles (void) { int i; i = COM_CheckParm ("-particles"); if (i) { r_numparticles = (int)(Q_atoi(com_argv[i+1])); if (r_numparticles < ABSOLUTE_MIN_PARTICLES) r_numparticles = ABSOLUTE_MIN_PARTICLES; } else { r_numparticles = MAX_PARTICLES; } particles = (particle_t *) Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles"); } void R_InitFlares (void) { int i; i = COM_CheckParm ("-flares"); if (i) { r_numflares = (int)(Q_atoi(com_argv[i+1])); if (r_numflares < ABSOLUTE_MIN_PARTICLES) r_numflares = ABSOLUTE_MIN_PARTICLES; } else { r_numflares = 256; } flares = (flare_t *) Hunk_AllocName (r_numparticles * sizeof(flare_t), "flares"); } /* =============== R_EntityParticles =============== */ #define NUMVERTEXNORMALS 162 extern float r_avertexnormals[NUMVERTEXNORMALS][3]; vec3_t avelocities[NUMVERTEXNORMALS]; float beamlength = 16; vec3_t avelocity = {23, 7, 3}; float partstep = 0.01; float timescale = 0.01; void R_EntityParticles (entity_t *ent) { // int count; // 2001-12-10 Reduced compiler warnings by Jeff Ford int i; particle_t *p; float angle; float sp, sy, cp, cy; //sr, cr, // 2001-12-10 Reduced compiler warnings by Jeff Ford vec3_t forward; float dist; dist = 64; // count = 50; // 2001-12-10 Reduced compiler warnings by Jeff Ford if (!avelocities[0][0]) { for (i=0 ; inext; p->next = active_particles; active_particles = p; p->frame = 0; // p->owner = NULL; p->die = cl.time + 0.01; p->polor = 0x6f; p->type = pt_explode; p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength; p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength; p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength; } } // an entity on fire! void R_EntityFireParticles (entity_t *ent, vec3_t org, float sizefix) { // int count; // 2001-12-10 Reduced compiler warnings by Jeff Ford int i, g; particle_t *p; float angle; float sp, sy, cp, cy, sr, cr; // 2001-12-10 Reduced compiler warnings by Jeff Ford vec3_t forward, right; float dist; float langth; int moed; langth = 5; dist = 1; // count = 50; // 2001-12-10 Reduced compiler warnings by Jeff Ford moed = 1; if (!avelocities[0][0]) { for (i=0 ; ipartfinished) return; if (!sizefix) sizefix = 1.0f; ent->partfinished = cl.time + 0.1; for (g=0 ; g<3 ; g++) { angle = cl.time * avelocities[g][0]; sy = sin(angle); cy = cos(angle); angle = cl.time * avelocities[g][1]; sp = sin(angle); cp = cos(angle); angle = cl.time * avelocities[g][2]; sr = sin(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford cr = cos(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford forward[0] = cp*cy; forward[1] = cp*sy; forward[2] = -sp; right[0] = cp*cr; right[1] = cp*sr; right[2] = -sr; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->die = cl.time + 0.8; p->type = pt_smoke; p->blend = 8; p->frame = 1; p->alpha = 1.4f; p->scale = 0.2f; p->scaley = 0.2f; p->alphavel = -1.4; p->sprtype = SPR_VP_PARALLEL_ORIENTED; p->scalexvel = 1.7; p->scaleyvel = 1.2; p->angles[PITCH] = 0; p->angles[YAW] = 0; p->angles[ROLL] = rand()&360; p->ramp = 0; p->org[0] = org[0]; p->org[1] = org[1]; p->org[2] = org[2]; p->vel[2] = 35 + rand()%66; p->angles[0] += ent->angles[0]; p->angles[1] += ent->angles[1]; p->angles[2] += ent->angles[2]; p->polor = 237; // p->polor = ramp4[(int)p->ramp]; // p->type = pt_fire6; } // flutter streamer for (i=0 ; i<11 ; i++) { angle = cl.time * avelocities[i][0]; sy = sin(angle); cy = cos(angle); angle = cl.time * avelocities[i][1]; sp = sin(angle); cp = cos(angle); angle = cl.time * avelocities[i][2]; sr = sin(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford cr = cos(angle); // 2001-12-10 Reduced compiler warnings by Jeff Ford forward[0] = cp*cy; forward[1] = cp*sy; forward[2] = -sp; right[0] = cp*cr; right[1] = cp*sr; right[2] = -sr; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->die = cl.time + 0.8; //p->polor = 0x6f; p->polor = 44; p->type = pt_smoke; p->blend = 8; p->frame = 1; p->alpha = 1.0f; p->scale = 0.5f; p->scaley = 0.5f; p->alphavel = -0.8; p->sprtype = SPR_ORIENTED; p->scalexvel = 0.4; p->scaleyvel = -1.7; p->angles[PITCH] = 90; p->angles[YAW] = rand()&720 - 360; p->angles[ROLL] = rand()&360; p->anglevel[PITCH] = -180; //p->anglevel[YAW] = -180; p->anglevel[ROLL] = rand()&720 - 360; //p->vel[2] = 655; p->ramp = 0; // p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*langth; // p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*langth; // p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*langth; p->org[0] = org[0] + r_avertexnormals[i][0]*dist + forward[0]*langth; p->org[1] = org[1] + r_avertexnormals[i][1]*dist + forward[1]*langth; p->org[2] = org[2] + r_avertexnormals[i][2]*dist + forward[2]*langth; p->vel[2] = 77; p->angles[0] += ent->angles[0]; p->angles[1] += ent->angles[1]; p->angles[2] += ent->angles[2]; p->polor = 232; // p->polor = ramp4[(int)p->ramp]; // p->type = pt_fire6; } } // leilei - sprite versions! void R_FireTrail (vec3_t start, vec3_t end, entity_t *ent) { vec3_t vec; float len; int j; particle_t *p; int dec; static int tracercount; VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 1; // if (len < 0) // { // R_EntityFireParticles (ent, ent->origin); // if not moving, go to the still fire effect // return; // } while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; VectorCopy (vec3_origin, p->vel); p->die = cl.time + 2; p->sprtype = 4; p->blend = 0; p->scalexvel = 0; p->trail = 0; // damnit p->scaleyvel = 0; p->alphavel = 0; p->scale = 0.3f; p->scaley = p->scale; p->anglevel[0] = 0; p->anglevel[1] = 0; p->anglevel[2] = 0; p->alpha = 1.7f; p->type = pt_smoke; p->frame = 1; p->angles[2] = rand()&450; p->alphavel = -1.3f; p->blend = 8; p->die = cl.time + 0.1f; p->scalexvel = -2.3; p->polor = 235; p->scaleyvel = -2.3; p->anglevel[2] = rand()&666 - 333; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%2)-1); if (len > 3){ // embers p->scale = 0.1f; p->scaley = 0.1f; p->alphavel = -0.6f - (rand()%7 * 0.1); p->scalexvel = -0.1f; p->scaleyvel = -0.1f; p->polor = 234; p->die = cl.time + 0.8; p->sprtype = SPR_ORIENTED; for (j=0 ; j<3 ; j++){ p->org[j] = start[j] + ((rand()%5)-2); p->vel[j] = rand()%12 - 6; p->angles[j] = rand()*1024; } p->vel[2] += 17; } VectorAdd (start, vec, start); } } /* =============== R_ClearParticles =============== */ void R_ClearParticles (void) { int i; free_particles = &particles[0]; active_particles = NULL; for (i=0 ;inext; p->next = active_particles; active_particles = p; p->frame = 0; // p->owner = NULL; p->die = 99999; p->polor = (-c)&15; p->type = pt_static; VectorCopy (vec3_origin, p->vel); VectorCopy (org, p->org); } fclose (f); Con_Printf ("%i points read\n", c); } /* =============== R_ParseParticleEffect Parse an effect out of the server message =============== */ void R_ParseParticleEffect (void) { vec3_t org, dir; int i, count, msgcount, color; for (i=0 ; i<3 ; i++) org[i] = MSG_ReadCoord (); for (i=0 ; i<3 ; i++) dir[i] = MSG_ReadChar () * (1.0/16); msgcount = MSG_ReadByte (); color = MSG_ReadByte (); if (msgcount == 255) count = 1024; else count = msgcount; if (particlespray) R_RunWarticleEffect (org, dir, color, count); else R_RunParticleEffect (org, dir, color, count); } /* =============== R_ParticleExplosion =============== */ void R_ParticleExplosion (vec3_t org) { int i, j; particle_t *p; for (i=0 ; i<1024 ; i++) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->frame = 0; p->die = cl.time + 5; p->polor = ramp1[0]; p->ramp = rand()&3; if (i & 1) { p->type = pt_explode; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } else { p->type = pt_explode2; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } } } extern cvar_t *temp2; // leilei's redo void R_NormalFromHerePlease (vec3_t org, vec3_t steer); void R_ParticleExplosionSpritey (vec3_t org) { int i, j; particle_t *p; flare_t *f; for (i=0 ; i<2 ; i++) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->frame = 0; p->die = cl.time + 4.7; // Fireball if (i < 2){ p->frame = 11; p->scale = 0.1; p->scalexvel = 4; p->scaleyvel = 0; p->blend = 1; p->alpha = 1.0f; p->alphavel = -0.9f; p->angles[2] = rand()&360; p->anglevel[2] = rand()&360 - 180; p->sprtype = 4; p->scaley = p->scale; p->type = pt_smoke; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%64)-32; } } else { p->frame = 12; p->scale = 0.1; p->scalexvel = 0; p->scaleyvel = 0; p->polor = 15; p->die = cl.time + 2.7; p->blend = 8; p->polor = 56 + (rand()%15); VectorCopy(org, p->org); // R_NormalFromHerePlease(p->org,p->angles); p->scaley = p->scale; p->alpha = 2.0f; p->alphavel = -1.2f - rand()%2; p->angles[2] = rand()&360; p->type = pt_sparkvel; //p->sprtype = 1; // for directional sprites! p->sprtype = 1; // for directional sprites! //p->scaley = 4; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = rand()% 1800 - 900; } // p->vel[2] = (rand()%356)-128; } } // then the flare. // else /* if (!free_flares) return; f = free_flares; free_flares = f->next; f->next = active_flares; active_flares = f; f->frame = 12; f->scale = 0.2; f->scalexvel = 6; p->scaleyvel = 0; f->blend = 3; f->polor = 79; // f->alpha = 1.2f; f->die = cl.time + 0.3; f->alphavel = -1.9f; f->angles[2] = 0; f->anglevel[2] = 0; f->sprtype = 5; for (j=0 ; j<3 ; j++) { f->org[j] = org[j]; f->vel[j] = 0; } { trace_t tarce; tarce = Particle_TraceLine(org, r_refdef.vieworg); if(tarce.fraction < 1) f->alpha = 0; else f->alpha = 1; } */ } extern cvar_t *r_particletrails; /* =============== R_ParticleTrail =============== */ void R_ParticleTrail (vec3_t org, vec3_t veloc, int trl, float tim, int coll, float alf, int blend) { int i, j; particle_t *p; if (!free_particles) return; if (!r_particletrails->value) return; if ((cl.time - cl.oldtime) < 0.01) // you're too fast return; if ((cl.time - cl.oldtime) > 0.3) // you're slow return; return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->die = cl.time + tim; p->frame = 0; //p->die = cl.time + ( cl.time - cl.oldtime); p->polor = coll; p->type = pt_trail; p->trail = trl - 1; p->alpha = alf; p->blend = blend; for (j=0 ; j<3 ; j++) { p->org[j] = org[j]; p->vel[j] = veloc[j] * -0.5; } } /* =============== R_ParticleBloodSplash for blood drip maybe =============== */ extern sfx_t *cl_sfx_wizhit; extern sfx_t *cl_sfx_bloodhit1; extern sfx_t *cl_sfx_bloodhit2; extern sfx_t *cl_sfx_bloodhit3; void R_ParticleBloodSplash (vec3_t org, int veel, int col) { int i, j; float wa; particle_t *p; wa = veel; if (wa > 0.6) wa = 0.6; if (wa < 0) wa = 0.1; veel = veel * -0.2; S_StartSound2 (-1, 0, cl_sfx_wizhit, org, 0.2, 3.7, (rand()%12) + 4); for (i=0 ; i<3 ; i++) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->die = cl.time + 0.6; p->polor = col; p->ramp = rand()&3; p->trail = 3; if (particleset == 2){ p->frame = 7; p->scale = 0.02f; p->scaley = 0.02f; p->scalexvel = 1; p->scaleyvel = 0; p->alphavel = -0.3; p->blend = 0; p->alpha = 0.5f; p->trail = 0; } else { p->alpha = 1; p->alphavel = 0; p->scalexvel = 0; p->scaleyvel = 0; p->frame = 0; p->scale = 1; p->scaley = 1; } { if (p->polor > 63 && p->polor < 80) p->type = pt_bloodsplat; else p->type = pt_fastgrav; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%2)-1); p->vel[j] = (rand()%32)-16; } p->vel[2] += (rand()%veel); } } } void R_ParticleWat (vec3_t org, int colr) { int i, j; particle_t *p; for (i=0 ; i<2 ; i++) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->die = cl.time + 0.02; p->polor = colr; { p->type = pt_static; for (j=0 ; j<3 ; j++) { p->org[j] = org[j]; p->vel[j] = (rand()%64)-32; } } } } /* =============== R_ParticleExplosion2 =============== */ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength) { int i, j; particle_t *p; int colorMod = 0; for (i=0; i<512; i++) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; // p->owner = NULL; p->frame = 0; p->die = cl.time + 0.3; p->polor = colorStart + (colorMod % colorLength); colorMod++; p->type = pt_blob; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } } void R_ParticleBloodSpewism (vec3_t org, int much) { int i, j; vec3_t fe; int colorMod = 0; for (i=1; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; p->die = cl.time + 1 + (rand()&8)*0.05; if (i & 1) { p->type = pt_blob; p->polor = 66 + rand()%6; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } else { p->type = pt_blob2; p->polor = 150 + rand()%6; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } } } /* =============== R_PlasmaExplosion used by TE_TEI_PLASMAHIT =============== */ void R_PlasmaExplosion (vec3_t org, int colorStart, int colorLength, int count) { int i, j; particle_t *p; int colorMod = 0; for (i=0; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; // TODO: Implement Spark Trail type p->die = cl.time + 0.4; p->frame = 0; p->polor = colorStart + (colorMod % colorLength); colorMod++; p->type = pt_decel; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%4)-2); p->vel[j] = (rand()%1500)-750; } } } /* =============== R_RunParticleEffect =============== */ // // The original Quack particles // extern cvar_t *r_particlesparks; extern cvar_t *r_particletrails; extern cvar_t *r_particlebloodfade; extern cvar_t *temp2; extern cvar_t *s_blood; void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) { int i, j; particle_t *p; int density; if (particleset == 2) //density = (1 * (count / 5)); // reduce the spraying for sprites density = 8; // reduce the spraying for sprites else density = 1; if (particleblood < 0 && (color > 63) && (color < 80) && count != 1024) return; //we disable the blood! if (particleblood > 1 && (color > 63) && (color < 80) && count != 1024){ int o, m, f, g; vec3_t shoo, ting, tha, tway; // Blood Spurt of some sort. // sound hack if (s_blood->value){ if (count < 15) S_StartSound2 (-1, 0, cl_sfx_bloodhit3, org, 0.2, 3.1, (12 / count )); else if (count > 44) S_StartSound2 (-1, 0, cl_sfx_bloodhit2, org, 0.6, 3.1, (20 / count )); else S_StartSound2 (-1, 0, cl_sfx_bloodhit3, org, 0.4, 3.1, (44 / count )); } o = (particleblood * 0.3)* count; m = o; for (j=0 ; j<3 ; j++) { shoo[j] = dir[j] + (rand()%5)-2.5 * -1; ting[j] = dir[j] + (rand()%5)-2.5; tha[j] = dir[j] + (rand()%5)-2.5; tway[j] = dir[j] + (rand()%5)-2.5; } for (i=-3 ; inext; //p->flat = 1; // testing p->frame = 0; p->scale = 0.4f; p->scaley = 0.4f; p->alpha = 1.0f; p->alphavel = -0.5f; p->scalexvel = 0.15f * (count / 2.4); // scale upper p->scaleyvel = 0.0f; // don't do sticky drop... p->next = active_particles; if (particleset == 2){ p->frame = 8 - rand()%4; p->blend = 10; p->scale = 0.23f; p->scaley = p->scale; p->angles[2] = rand()&360; p->anglevel[2] = rand()&500-250; p->sprtype = 4; } // p->owner = NULL; active_particles = p; { p->die = cl.time + 0.6*(rand()%32); p->polor = 79 - (rand()&6); if (particleblood > 2){ p->die = cl.time + 0.6*(rand()%32); p->type = pt_bloodsplat; } else { p->type = pt_slowgrav; p->die = cl.time + 0.6*(rand()%2); } if (i<12){ for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + (rand()%4)-2; p->vel[j] = dir[j]*(rand()*(count*0.5))-(count); //p->polor = (color&~7) + (rand()&7); // p->polor = 66 + (rand()&12); } } else if (i<28){ for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + (rand()&((count/8))-(count/16)); p->vel[j] = dir[j]*(i * 0.8); p->vel[2] += (i / 5); } } else if (i<96){ for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + (rand()&((count/8))-(count/16)); // Prydon had a problem with this (fixed now though) p->vel[j] = shoo[j]*(i * 0.2); p->vel[2] += (i / 5); } } else if (i<112){ for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + (rand()&((count/8))-(count/16)); p->vel[j] = ting[j]*(i * 0.2); p->vel[2] += (i / 5); } } else if (i<128){ for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + (rand()&((count/8))-(count/16)); p->vel[j] = tha[j]*(i * 0.2); p->vel[2] += (i / 5); } } else if (i<132){ for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + (rand()&((count/8))-(count/16)); p->vel[j] = tway[j]*(i * 0.2); p->vel[2] += (i / 5); } } else if (i>200){ for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + (rand()&((count/8))-(count/16)); p->vel[j] = dir[j]* (rand()%i)-(i*0.5); } } else { for (j=0 ; j<3 ; j++) { p->org[j] = org[j]; p->vel[j] = dir[j]*(i * 0.3); p->vel[2] *= 2; } } } } if (particleset == 2){ p->scale = count / 48; p->scalexvel = p->scale * 0.4; p->scaleyvel = 0; } return; } if (r_particlesparks->value && (color > 224)){ for (i=0 ; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; p->trail = 14; // testing p->blend = 1; p->frame = 0; p->die = cl.time + 0.8*(rand()%5); p->alphavel = -1; p->polor = (color&~7) + (rand()&7); //p->polor = color; p->type = pt_spark; for (j=0 ; j<3 ; j++) { // p->org[j] = org[j] + ((rand()&15)-8); p->org[j] = org[j];//+ ((rand()&15)-8); p->vel[j] = dir[j]*16656 + (rand()%300)-150 ; } } return; } for (i=0 ; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; // p->trail = 6; // testing // p->splatter = 0; p->frame = 0; if (count == 1024) { // rocket explosion p->die = cl.time + 5; p->polor = ramp1[0]; ; p->ramp = rand()&3; if (particleset == 2){ R_ParticleExplosionSpritey(org); return; } if (i & 1) { p->type = pt_explode; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } else { p->type = pt_explode2; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } } else { p->die = cl.time + 0.1*(rand()%5); p->polor = (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;// + (rand()%300)-150; } if (particleblood){ if ((color > 63) && (color < 80)){ //p->lit = 1; p->type = pt_blood; } } if (particleset == 2){ p->alpha = 1.0f; p->frame = 1; p->blend = 8; p->scalexvel = 3; p->scaleyvel = 0; p->alphavel = -2.9f; p->scale = 0.01f;p->scaley = p->scale; p->angles[2] = rand()&360; p->anglevel[2] = rand()&800-400; p->sprtype = 4; } } } } // different alternate 'additive' method // origin is smaller and velocity is more random // it also fades and prefers scale over quantity (to be implemented) // using it depends on your taste. void R_RunWarticleEffect (vec3_t org, vec3_t dir, int color, int count) { int i, j; particle_t *p; for (i=0 ; inext; p->next = active_particles; active_particles = p; // p->owner = NULL; p->frame = 0; { p->die = cl.time + 0.2*(rand()%5); p->polor = color; p->type = pt_bloodsplat; for (j=0 ; j<3 ; j++) { p->org[j] = org[j]; p->vel[j] = dir[j]*15 + (rand()%50)-25; } } } } // -------------------- // Used by TE_TEI_SMOKE // -------------------- void R_Smoke (vec3_t org, vec3_t dir, int color, int count) { int i, j; particle_t *p; int nexte = 1; if (sprity) nexte = 8; for (i=0 ; inext; p->next = active_particles; active_particles = p; // p->owner = NULL; p->type = pt_smoke; p->frame = 1; p->blend = 1; R_NormalFromHerePlease(p->org, p->angles); // p->vel[0] = p->angles[0]; // p->vel[1] = p->angles[1]; // p->vel[2] = p->angles[2]; // p->splatter = 0; p->sprtype = 4; p->angles[2] = rand()&555; p->alpha = 1.0f; p->scale = 0.02f; p->scaley = p->scale; p->alphavel = -0.5; p->trail = 0; p->scalexvel = 0.7; p->scaleyvel = 0.5; p->anglevel[2] = rand()&1000 - 500; { if (sprity) p->die = cl.time + 2.6*(rand()%5); else p->die = cl.time + 0.1*(rand()%5); p->polor = (color&~7) + (rand()&7); for (j=0 ; j<3 ; j++) { if (sprity) p->org[j] = org[j] + ((rand()%2)-1); else p->org[j] = org[j] + ((rand()%6)-3); p->vel[j] = (rand()%50)-25; } } } } void vectoangles2 (vec3_t value1, vec3_t angles); void vectoangles(vec3_t vec, vec3_t ang) { float forward; float yaw, pitch; if (vec[1] == 0 && vec[0] == 0) { yaw = 0; if (vec[2] > 0) pitch = 90; else pitch = 270; } else { yaw = (int) (atan2(vec[1], vec[0]) * 180 / M_PI); if (yaw < 0) yaw += 360; forward = sqrt (vec[0]*vec[0] + vec[1]*vec[1]); pitch = (int) (atan2(vec[2], forward) * 180 / M_PI); if (pitch < 0) pitch += 360; } ang[0] = pitch; ang[1] = yaw; ang[2] = 0; } // partially butchered from Darkplaces' CL_SpawnDecalParticleForPoint void R_Decal (vec3_t org, int decframe, int blend, float sceel, int splat) { int i, j; particle_t *p; int nexte = 1; int count = 1; trace_t trace; float bestfrac, bestorg[3], bestnormal[3]; float org2[3]; float fraccy = 0; vec3_t heer; vec3_t nermal; vec3_t teer; int besthitent = 0, hitent; int maxdist = 9; bestfrac = 10; //decframe = 4; for (i = 0;i < 32;i++) { org2[0] = rand()%4 - rand()%2; org2[1] = rand()%4 - rand()%2; org2[2] = rand()%4 - rand()%2; VectorMA(org, maxdist, org2, org2); trace = Particle_TraceLine(org, org2); // take the closest trace result that doesn't end up hitting a NOMARKS // surface (sky for example) if (bestfrac > trace.fraction) { bestfrac = trace.fraction; // besthitent = hitent; VectorCopy(trace.endpos, bestorg); VectorCopy(trace.plane.normal, bestnormal); } } if (bestfrac < 1) // it's time to create. { for (i=0 ; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; p->type = pt_decal; p->frame = decframe; p->blend = blend; // p->splatter = 0; p->sprtype = 3; p->alpha = 8.0f; if (!sceel) p->scale = 0.4f; else p->scale = sceel; p->scaley = p->scale; p->alphavel = 0; p->scalexvel = 0; p->scaleyvel = 0; p->anglevel[0] = 0; p->trail = 0; p->anglevel[1] = 0; p->anglevel[2] = 0; p->die = cl.time + 76; p->angles[0] = -bestnormal[0]; p->angles[1] = -bestnormal[1]; p->angles[2] = -bestnormal[2]; p->angles[2] *= -1; if (splat){ p->type = pt_bloodrun; p->blend = blend; } // Con_Printf("%f yes\n",p->angles[2]); vectoangles(p->angles, p->angles); for (j=0 ; j<3 ; j++) { p->org[j] = bestorg[j]; p->vel[j] = 0; } } } } void R_NormalFromHerePlease (vec3_t org, vec3_t steer) { int i, j; particle_t *p; int nexte = 1; int count = 1; trace_t trace; float bestfrac, bestorg[3], bestnormal[3]; float org2[3]; float org4[3]; float fraccy = 0; vec3_t heer; vec3_t nermal; vec3_t teer; int besthitent = 0, hitent; int maxdist = 9; bestfrac = 10; //decframe = 4; org4[0] = org[0]; org4[1] = org[1]; org4[2] = org[2]; for (i = 0;i < 32;i++) { org2[0] = rand()%4 - rand()%2; org2[1] = rand()%4 - rand()%2; org2[2] = rand()%4 - rand()%2; VectorMA(org4, maxdist, org2, org2); trace = Particle_TraceLine(org4, org2); // take the closest trace result that doesn't end up hitting a NOMARKS // surface (sky for example) if (bestfrac > trace.fraction) { bestfrac = trace.fraction; // besthitent = hitent; VectorCopy(trace.endpos, bestorg); VectorCopy(trace.plane.normal, bestnormal); } } if (bestfrac < 1) // it's time to create. { steer[0] = bestnormal[0]; steer[1] = bestnormal[1]; steer[2] = bestnormal[2]; //steer[2] *= -1; //org[0] = bestorg[0]; // don't return orgies if we don't want them //org[1] = bestorg[1]; //org[2] = bestorg[2]; vectoangles(steer, steer); } } int R_GimmeTheColorOfThisWall (vec3_t org) { int i, j; particle_t *p; int nexte = 1; int count = 1; int color; trace_t trace; float bestfrac, bestorg[3], bestnormal[3]; float org2[3]; float fraccy = 0; vec3_t heer; vec3_t nermal; vec3_t teer; int besthitent = 0, hitent; int maxdist = 9; bestfrac = 10; //decframe = 4; for (i = 0;i < 32;i++) { org2[0] = rand()%4 - rand()%2; org2[1] = rand()%4 - rand()%2; org2[2] = rand()%4 - rand()%2; VectorMA(org, maxdist, org2, org2); trace = Particle_TraceLine(org, org2); if (bestfrac > trace.fraction) { bestfrac = trace.fraction; } } if (bestfrac < 1) // it's time to create. { color = trace.color; return color; } } void R_FlareInstant (vec3_t org, int decframe, int colr, int colg, int colb, int tayp) { int i, j; particle_t *p; int nexte = 1; int count = 1; int gmcol; for (i=0 ; i<1 ; i++) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = decframe; p->blend = 5; gmcol = BestColor(colr, colg, colb, 12, 222); // determine color from bestcoloring p->polor = gmcol; p->color = gmcol; // determine initial visibility first so we don't see exploded flares on spawn p->sprtype = tayp; p->angles[2] = 0; // will random these. //p->alpha = 1.0f; p->alpha = 1.0f; // we are drawing in front of everything anyway. p->alphavel = 0; p->scalexvel = 0; p->scaleyvel = 0; p->anglevel[0] = 0; p->anglevel[1] = 0; p->anglevel[2] = 0; p->type = pt_flare_will_die; p->scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + (p->org[2] - r_origin[2])*vpn[2]; if (p->scale < 40) p->scale = 0.3; else p->scale = 0.3 + p->scale * 0.004; } p->scaley = p->scale; { p->die = cl.time + 0.08; // for now for (j=0 ; j<3 ; j++) { p->org[j] = org[j]; p->vel[j] = 0; } } } extern cvar_t *r_flares; // leilei - experimental unr**l-style flares void R_FlareTest (vec3_t org, int decframe, int colr, int colg, int colb, float gonnjardie, entity_t *ownme) { int i, j; flare_t *p; int nexte = 1; int count = 1; int gmcol; int ownin; int gonnadie = 0; float initialalpha; trace_t tarce; if (!r_flares->value) return; // don't draw flares if we don't want flares. decframe = 12; if (cls.demoplayback) return; // because my checks for visibility cause a crash in demo playback. :( if (ownme == NULL) ownin = 0; else ownin = 1; if (ownin && ownme->ourparticle) return; //we got one. // determine if we've spawned in a wall like an idiot would do. mleaf_t *o; o = Mod_PointInLeaf (org, cl.worldmodel); if (o->contents != CONTENTS_EMPTY ) return; // place each flare with their personal values! for (i=0 ; inext; p->next = active_flares; p->owner = NULL; active_flares = p; p->frame = decframe; p->blend = 5; D_TestOurFlare(p); if(!p->amiseen) initialalpha = 0; else{ if (gonnjardie) initialalpha = gonnjardie; else initialalpha = 1; } // determine color. we are going to use gelmaps for flares. gmcol = BestColor(colr, colg, colb, 12, 222); // determine color from bestcoloring p->polor = gmcol; p->color = gmcol; if (ownin){ p->owner = ownme; } // determine initial visibility first so we don't see exploded flares on spawn if((Traceline(p->org, r_refdef.vieworg, NULL, NULL))) p->alpha = 1.0f; else p->alpha = 0.02f; p->blend = 5; p->sprtype = 5; p->angles[2] = 0; // will random these. p->alpha = initialalpha; if (ownin){ p->owner = ownme; ownme->ourparticle = p; p->owned = 1; // OWNED. } p->alphavel = 0; p->scalexvel = 0; p->scaleyvel = 0; p->anglevel[0] = 0; p->anglevel[1] = 0; p->anglevel[2] = 0; p->type = pt_flare; p->scale = 0; p->scaley = p->scale; p->die = cl.time + 7500; // for EVER! for (j=0 ; j<3 ; j++) { p->org[j] = org[j]; p->vel[j] = 0; } } } // -------------------- // Used for the engine splash calls (by r_particle_splash) // -------------------- void R_Splash (vec3_t org, vec3_t dir, int color, int count, int power) { int i, j; particle_t *p; for (i=0 ; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; // p->splatter = 0; p->frame = 0; p->trail = 0; if (count == 1024) { // rocket explosion p->die = cl.time + 5; p->polor = ramp1[0]; p->ramp = rand()&3; if (i & 1) { p->type = pt_smoke; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } else { p->type = pt_smoke; for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((rand()%32)-16); p->vel[j] = (rand()%512)-256; } } } else { p->die = cl.time + 0.4*(rand()%5); p->polor = color; p->type = pt_blob; for (j=0 ; j<3 ; j++) { p->org[j] = org[j]; p->vel[j] = (rand()%350)-(125); } } } } /* =============== R_LavaSplash =============== */ void R_LavaSplash (vec3_t org) { int i, j, k; particle_t *p; float vel; vec3_t dir; for (i=-16 ; i<16 ; i++) for (j=-16 ; j<16 ; j++) for (k=0 ; k<1 ; k++) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->die = cl.time + 2 + (rand()&31) * 0.02; p->polor = 224 + (rand()&7); p->type = pt_slowgrav; p->frame = 0; dir[0] = j*8 + (rand()&7); dir[1] = i*8 + (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); } } /* =============== R_Blood =============== */ void R_Blood(int count, vec3_t mins, vec3_t maxs, vec3_t vel_mins, vec3_t vel_maxs) { const int color = 73; int idist[3], vdist[3]; int i, j; particle_t *p; for (i = 0; i < 3; i++) { idist[i] = (int)(maxs[i] - mins[i] + 0.1f); vdist[i] = (int)(vel_maxs[i] - vel_mins[i] + 0.1f); if (idist[i] < 1) idist[i] = 1; if (vdist[i] < 1) vdist[i] = 1; } for (i = 0; i < count; i++) { if (!free_particles) break; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; //p->die = cl.time + 0.1*(rand()%5); p->die = cl.time + 0.1*(rand()%65); p->polor = (float)((color&~7) + (rand()&7)); //p->splatter = 3; //p->lit = 1; p->type = pt_bloodsplat; for (j = 0; j < 3; j++) { p->org[j] = mins[j] + rand() % idist[j] + ((rand()&15)-8); p->vel[j] = vel_mins[j] + rand() % vdist[j]; } } } /* =============== R_Rain Tomazquake code adopted =============== */ void R_Rain (vec3_t min, vec3_t max, int drops) { int i; vec3_t difference; particle_t *p; for (i=0 ; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; VectorSubtract(max, min, difference); p->die = cl.time + 10; p->alpha = 0.4f; p->polor = 8; if (particleset == 2) p->trail = 0; else p->trail = 6; p->type = pt_drip; p->scale = 0.01f; p->scaley = 2; p->scalexvel = 0; p->scaleyvel = 3; p->frame = 3; p->blend = 1; p->sprtype = 3; p->org[0] = difference[0] * (rand () & 2047) * 0.00048828125 + min[0]; // Tomaz - Speed p->org[1] = difference[1] * (rand () & 2047) * 0.00048828125 + min[1]; // Tomaz - Speed p->org[2] = max[2] - 10; p->vel[0] = 0; p->vel[1] = 0; p->vel[2] = -400 - (rand() & 600); } } void R_Snow (vec3_t min, vec3_t max, int drops) { int i; vec3_t difference; particle_t *p; for (i=0 ; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; VectorSubtract(max, min, difference); p->die = cl.time + 10; p->alpha = 0.4f; p->polor = 14; p->trail = 0; p->alpha = 0.27f; p->blend = 1; p->type = pt_snow; if (particleset == 2){ p->scale = 0.05f; p->scaley = 0.05f; p->scalexvel = 0; p->scaleyvel = 0; p->frame = 3; p->blend = 1; } p->org[0] = difference[0] * (rand () & 2047) * 0.00048828125 + min[0]; // Tomaz - Speed p->org[1] = difference[1] * (rand () & 2047) * 0.00048828125 + min[1]; // Tomaz - Speed p->org[2] = max[2] - 10; p->vel[0] = 0; p->vel[1] = 0; p->vel[2] = -40; } } /* =============== R_TeleportSplash =============== */ void R_TeleportSplash (vec3_t org) { int i, j, k; particle_t *p; float vel; vec3_t dir; for (i=-16 ; i<16 ; i+=4) for (j=-16 ; j<16 ; j+=4) for (k=-24 ; k<32 ; k+=4) { if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; p->alpha = 1.0f; // leilei - don't alpha! active_particles = p; p->frame = 0; p->die = cl.time + 0.2 + (rand()&7) * 0.02; p->polor = 7 + (rand()&7); p->type = pt_slowgrav; dir[0] = j*8; dir[1] = i*8; dir[2] = k*8; 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); vel = 50 + (rand()&63); VectorScale (dir, vel, p->vel); } } /* ====== QUAKE2 SOURCE vectoangles2 - this is duplicated in the game DLL, but I need it here. ====== */ void vectoangles2 (vec3_t value1, vec3_t angles) { float forward; float yaw, pitch; if (value1[1] == 0 && value1[0] == 0) { yaw = 0; if (value1[2] > 0) pitch = 90; else pitch = 270; } else { // PMM - fixed to correct for pitch of 0 if (value1[0]) yaw = (atan2(value1[1], value1[0]) * 180 / M_PI); else if (value1[1] > 0) yaw = 90; else yaw = 270; if (yaw < 0) yaw += 360; forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); pitch = (atan2(value1[2], forward) * 180 / M_PI); if (pitch < 0) pitch += 360; } angles[PITCH] = -pitch; angles[YAW] = yaw; angles[ROLL] = 0; } /* =============== QUAKE2 SOURCE R_CurlyBloodTrail Adapted from Quake2's CL_TrackerTrail for the unused Disintegrator/Disruptor weapon for q2 rogue =============== */ void R_CurlyBloodTrail (vec3_t start, vec3_t end, int particleColor) { vec3_t move; vec3_t vec; vec3_t forward,right,up,angle_dir; float len; int j; particle_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; VectorScale (vec, 3, vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; VectorClear (p->vel); p->frame = 0; p->die = cl.time + 7.5; p->type = pt_bloodsplat; p->alpha = 1.0; p->blend = 0; if (particleset == 2) p->frame = 7; //p->alphavel = -2.0; p->alphavel = 0;p->scalexvel = 0;p->scaleyvel = 0;p->anglevel[0] = 0;p->anglevel[1] = 0;p->anglevel[2] = 0; p->polor = 75; p->scaley = p->scale; dist = DotProduct(move, forward); VectorMA(move, 7 * cos(dist), up, p->org); VectorMA(move, 7 * cos(dist), right, p->org); p->scalexvel = 0.3f; for (j=0 ; j<3 ; j++) { // p->org[j] = start[j] + ((rand()%6)-3); //p->vel[j] = 100 * cos(dist) + (100 * sin(dist)); // p->vel[j] = 0; //p->accel[j] = 0; } p->vel[0] += 22 * sin(dist); p->vel[1] += 22 * sin(dist); p->vel[2] += 22 * cos(dist); //p->vel[2] = 5; VectorAdd (move, vec, move); } } // f;or the plarticle blood vlariable void R_GusherizeCurlyBloodTrail (vec3_t start, vec3_t end, int particleColor) { vec3_t move; vec3_t vec; vec3_t forward,right,up,angle_dir; float len; int j; particle_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 = (56 / particleblood); VectorScale (vec, 3, vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; VectorClear (p->vel); p->alpha = 1; p->scale = defaultscale; p->alphavel = 0;p->scalexvel = 0;p->scaleyvel = 0;p->anglevel[0] = 0;p->anglevel[1] = 0;p->anglevel[2] = 0; p->scaley = p->scale; p->die = cl.time + 7.5; p->type = pt_bloodsplat; p->alpha = 1.0; p->frame = 0; if (particleset == 2) p->frame = 7; //p->alphavel = -2.0; p->polor = 75; dist = DotProduct(move, forward); VectorMA(move, len * 5 * cos(dist), up, p->org); VectorMA(move, len * 5 * cos(dist), right, p->org); p->blend = 10; p->alphavel = -0.5f; for (j=0 ; j<3 ; j++) { // p->org[j] = start[j] + ((rand()len)-(len * 0.5)); //p->vel[j] = 100 * cos(dist) + (100 * sin(dist)); // p->vel[j] = 0; //p->accel[j] = 0; } p->vel[0] += 12 * sin(dist); p->vel[1] += 12 * sin(dist); p->vel[2] += 12 * cos(dist); p->vel[0] *= vec[0]; p->vel[1] *= vec[1]; p->vel[2] *= vec[2]; p->scalexvel = p->vel[2] * 0.08; p->scaleyvel = 0; //p->vel[2] = 5; VectorAdd (move, vec, move); } } void R_RocketTrail (vec3_t start, vec3_t end, int type) { vec3_t vec; float len; int j; particle_t *p; int dec; static int tracercount; VectorSubtract (end, start, vec); len = VectorNormalize (vec); if (type < 128) dec = 3; else if (type == 7) dec = 1; else if (type == 2 && particleblood) dec = 1; else { dec = 1; type -= 128; } while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; p->trail = 0; p->scale = 1; p->scaley = p->scale; p->scalexvel = 0; p->scaleyvel = 0; VectorCopy (vec3_origin, p->vel); p->die = cl.time + 2; switch (type) { case 0: // rocket trail p->ramp = (rand()&3); p->polor = ramp3[(int)p->ramp]; p->type = pt_fire; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); break; case 1: // smoke smoke p->ramp = (rand()&3) + 2; p->polor = ramp3[(int)p->ramp]; p->type = pt_fire; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); break; case 2: // blood if (particleblood < 0) break; if (particleset == 2) p->frame = 7; if (particleblood > 2){ p->type = pt_bloodsplat; p->polor = 77 + (rand()&3); p->die = cl.time + (1 *(rand()%6)); if (len < 1){ for (j=0 ; j<3 ; j++){ p->org[j] = start[j] + ((rand()&4)-2); p->vel[j] = ((rand()%100)-50) * (len * 2); } p->vel[2] *= len; } else { for (j=0 ; j<3 ; j++){ p->org[j] = start[j] + ((rand()*(len))-(len*0.5)); //p->vel[j] += len; p->die = cl.time + 0.6*(rand()%5); } // p->vel[2] -= len * 2; } } else { p->type = pt_grav; p->polor = 67 + (rand()&3); for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); } break; case 3: case 5: // tracer p->die = cl.time + 0.5; p->type = pt_static; if (type == 3) p->polor = 52 + ((tracercount&4)<<1); else p->polor = 230 + ((tracercount&4)<<1); tracercount++; VectorCopy (start, p->org); if (tracercount & 1) { p->vel[0] = 30*vec[1]; p->vel[1] = 30*-vec[0]; } else { p->vel[0] = 30*-vec[1]; p->vel[1] = 30*vec[0]; } break; case 4: // slight blood if (particleblood < 0) break; else { if (particleset == 2) p->frame = 7; p->type = pt_grav; p->polor = 67 + (rand()&3); for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); len -= 3; } break; case 6: // voor trail p->polor = 9*16 + 8 + (rand()&3); p->type = pt_static; p->die = cl.time + 0.3; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()&15)-8); break; case 7: // rail trail smoke p->ramp = (rand()&3) + 2; p->polor = ramp3[(int)p->ramp]; p->alpha = 1; p->alphavel = -3.7 - rand()%1; p->type = pt_staticfade; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); break; } VectorAdd (start, vec, start); } } // leilei - sprite versions! void R_RocketTrailSprites (vec3_t start, vec3_t end, int type) { vec3_t vec; float len; int j; particle_t *p; int dec; static int tracercount; VectorSubtract (end, start, vec); len = VectorNormalize (vec); if (type < 128) dec = 32; else if (type == 7) dec = 6; else if (type == 2 && particleblood) dec = 7; else { dec = 1; type -= 128; } while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; VectorCopy (vec3_origin, p->vel); p->die = cl.time + 2; p->sprtype = 4; p->blend = 0; p->scalexvel = 0; p->trail = 0; // damnit p->scaleyvel = 0; p->alphavel = 0; p->scale = 0.2f; p->scaley = p->scale; p->anglevel[0] = 0; p->anglevel[1] = 0; p->anglevel[2] = 0; p->alpha = 1.0f; switch (type) { case 0: // rocket trail // p->ramp = (rand()&3); // p->polor = ramp3[(int)p->ramp]; p->type = pt_smoke; p->frame = 1; p->angles[2] = rand()&450; p->scale = 0.03f; p->blend = 1; p->alphavel = -0.37f; p->scalexvel = 0.7; p->anglevel[2] = rand()&666 - 333; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); break; case 1: // smoke smoke // p->ramp = (rand()&3); // p->polor = ramp3[(int)p->ramp]; p->type = pt_smoke; p->frame = 1; p->angles[2] = rand()&450; p->alphavel = -0.37f; p->blend = 1; p->scale = 0.03f; p->scalexvel = 0.5; p->anglevel[2] = rand()&666 - 333; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); break; case 2: // blood if (particleblood < 0) break; if (particleblood > 2){ p->type = pt_bloodsplat; if (particleset == 2) p->frame = 7; p->polor = 77 + (rand()&3); p->blend = 0; p->die = cl.time + (1 *(rand()%6)); if (len < 1){ for (j=0 ; j<3 ; j++){ p->org[j] = start[j] + ((rand()&4)-2); p->vel[j] = ((rand()%100)-50) * (len * 2); } p->vel[2] *= len; } else { for (j=0 ; j<3 ; j++){ p->org[j] = start[j] + ((rand()*(len))-(len*0.5)); //p->vel[j] += len; p->die = cl.time + 0.6*(rand()%5); } // p->vel[2] -= len * 2; } } else { p->type = pt_grav; p->polor = 67 + (rand()&3); for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); } break; case 3: case 5: // tracer p->die = cl.time + 0.5; p->type = pt_static; if (type == 3) p->polor = 52 + ((tracercount&4)<<1); else p->polor = 230 + ((tracercount&4)<<1); tracercount++; VectorCopy (start, p->org); if (tracercount & 1) { p->vel[0] = 30*vec[1]; p->vel[1] = 30*-vec[0]; } else { p->vel[0] = 30*-vec[1]; p->vel[1] = 30*vec[0]; } break; case 4: // slight blood if (particleblood < 0) break; else { if (particleset == 2) p->frame = 7; p->blend = 0; p->type = pt_grav; p->polor = 67 + (rand()&3); for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); len -= 3; } break; case 6: // voor trail p->polor = 9*16 + 8 + (rand()&3); p->type = pt_static; p->die = cl.time + 0.3; if (particleset == 2){ p->frame = 1; p->scalexvel = 2; p->alphavel = -0.4; p->anglevel[2] = rand()&600-300; p->angles[2] = rand()&360; p->blend = 8; } for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()&15)-8); break; case 7: // rail trail smoke p->ramp = (rand()&3) + 2; p->polor = ramp3[(int)p->ramp]; p->alpha = 1; p->alphavel = -3.7 - rand()%1; p->type = pt_staticfade; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%6)-3); break; } VectorAdd (start, vec, start); } } // LEI - particle trails 2 void R_ParticleTrail2 (vec3_t start, vec3_t end, int type, int blend, int color, float alpha) { vec3_t vec; float len; int j; particle_t *p; int dec; static int tracercount; int thetrail; thetrail = r_particletrails->value; if (!thetrail) return; if (thetrail) { D_DrawSparkTrans(start,end,alpha,color, blend); return; } VectorSubtract (end, start, vec); len = VectorNormalize (vec); { dec = 8; type -= 128; } while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; VectorCopy (vec3_origin, p->vel); p->die = cl.time + 0.02; p->frame = 0; p->type = pt_static; p->polor = color; p->blend = blend; p->trail = 0; // do not ecurse p->alpha = len * 0.3; for (j=0 ; j<3 ; j++) p->org[j] = start[j]; len -= 6; VectorAdd (start, vec, start); } } // LEI - lame particle beam // (TODO: Quake2 polygon beam) void R_ParticleBeam (vec3_t start, vec3_t end, int thecol) { vec3_t vec; float len; int j; particle_t *p; int dec; static int tracercount; int wat; //int thecol; VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 1; while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; VectorCopy (vec3_origin, p->vel); p->die = cl.time; // wat = rand()&2; { /* if (wat == 2){ // Outer Glow p->polor = thecol; p->type = pt_staticfadeadd; p->die = cl.time + 2; p->alpha = 0.6; p->alphavel = -0.7; for (j=0 ; j<3 ; j++) p->org[j] = start[j] + ((rand()%4)-2); } else */ { // Inner Line p->polor = thecol; p->type = pt_staticfadeadd; p->die = cl.time + 0.01; p->alpha = 1; p->alphavel = -0.9; for (j=0 ; j<3 ; j++) p->org[j] = start[j]; } } VectorAdd (start, vec, start); } } // uses the beam texture void R_BeamBeam (vec3_t start, vec3_t end, int thecol, float thesize) { vec3_t vec; float len; int j; particle_t *p; int dec; static int tracercount; //int thecol; vec3_t angel; VectorSubtract (end, start, vec); len = VectorNormalize (vec); dec = 1; vectoangles2 (vec, angel); while (len > 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; p->frame = 0; VectorCopy (vec3_origin, p->vel); p->die = cl.time; p->frame = 18; p->blend = 8; p->sprtype = 98; p->angles[0] = angel[0] + 90; p->angles[1] = angel[1]; p->angles[2] = angel[2]; //p->angles[0] = 0; //p->angles[1] = 0; //p->angles[2] = 0; p->scale = 0.03f; { p->polor = thecol; p->type = pt_staticfadeadd; p->die = cl.time + 0.01; p->alpha = 1; p->alphavel = -0.9; for (j=0 ; j<3 ; j++) p->org[j] = start[j]; } VectorAdd (start, vec, start); } } // uses the beam texture void R_LightningBeam (vec3_t start, vec3_t end, float sized) { vec3_t vec; vec3_t vec2; float len; float len2; int j; particle_t *p; int dec; static int tracercount; int thecol = 214; float dert; float dert2; vec3_t angel; vec3_t divert; VectorSubtract (end, start, vec); VectorSubtract (start, end, vec2); len = VectorNormalize (vec); len2 = VectorNormalize (vec2); if (!sized) sized = 1; dec = 1; vectoangles2 (vec, angel); while (len > 0) { len -= dec; //dert = sin(len2); //dert2 = 1 - (len / len2); dert = (len / len2); dert2 = 1 - dert; if (dert > 1)dert = 1; if (dert2 > 1)dert2 = 1; if (dert2 < 0)dert2 = 0; if (dert < 0)dert = 0; divert[0] += rand()%160 - 80; divert[1] += rand()%160 - 80; divert[2] += rand()%160 - 80; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; p->frame = 0; VectorCopy (vec3_origin, p->vel); p->die = cl.time; p->frame = 12; p->blend = 8; p->sprtype = 1; p->angles[0] = angel[0] + 90; p->angles[1] = angel[1]; p->vel[0] = 0; p->vel[1] = 0; p->vel[2] = 0; p->angles[2] = angel[2]; //p->angles[0] = 0; //p->angles[1] = 0; //p->angles[2] = 0; p->scale = 0.3f * sized * dert * dert2; p->scalexvel = -0.7f; p->scaleyvel = -0.7f; p->scaley = p->scale; { p->polor = thecol; p->type = pt_staticfadeadd; p->die = cl.time + 0.03; p->alpha = 1.0f; //p->alphavel = -0.9; for (j=0 ; j<3 ; j++){ p->org[j] = start[j]; p->vel[j] += (divert[j] * dert2 * dert); p->org[j] += (divert[j] * (dert2 * dert * 0.03f)); } } VectorAdd (start, vec, start); } } /* =============== R_RailTrail Used by TE_RAILTRAIL i'm a quake2 function short and stout =============== */ void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up) { float d; // this rotate and negat guarantees a vector // not colinear with the original right[1] = -forward[0]; right[2] = forward[1]; right[0] = forward[2]; d = DotProduct (right, forward); VectorMA (right, -d, forward, right); VectorNormalize (right); CrossProduct (right, forward, up); } void R_RailTrail (vec3_t start, vec3_t end) { vec3_t move; vec3_t vec; float len; int j; particle_t *p; float dec; vec3_t right, up; int i; float d, c, s; vec3_t dir; byte clr = 40; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); MakeNormalVectors (vec, right, up); for (i=0 ; inext; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; p->die = cl.time + 2.0; VectorClear (p->vel); d = i * 0.1; c = cos(d); s = sin(d); VectorScale (right, c, dir); VectorMA (dir, s, up, dir); p->type = pt_staticfadeadd; p->alpha = 1.0; // p->alphavel = -1.0 / (1+frand()*0.2); p->alphavel = -1.0; p->polor = clr + (rand()&7); for (j=0 ; j<3 ; j++) { p->org[j] = move[j] + dir[j]*3; p->vel[j] = dir[j]*6; } VectorAdd (move, vec, move); } dec = 0.75; VectorScale (vec, dec, vec); VectorCopy (start, move); } void R_SpiralBloodTrail (vec3_t start, vec3_t end) { vec3_t move; vec3_t vec; float len; int j; particle_t *p; float dec; vec3_t right, up; int i; float d, c, s; vec3_t dir; byte clr = 40; VectorCopy (start, move); VectorSubtract (end, start, vec); len = VectorNormalize (vec); len *= 4; MakeNormalVectors (vec, right, up); dec = 24; // for (i=0 ; i 0) { len -= dec; if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; // p->owner = NULL; active_particles = p; p->frame = 0; p->die = cl.time + 2.0; VectorClear (p->vel); i = len * 6; d = i * 0.1; c = cos(d); s = sin(d); VectorScale (right, c, dir); VectorMA (dir, s, up, dir); p->type = pt_bloodsplat; p->alpha = 1.0; p->scale = 0.1; p->blend = 0; if (particleset == 2){ // p->alphavel = -1.0 / (1+frand()*0.2); p->scalexvel = 0.8; p->alphavel = -3.0; p->frame = 7; } p->polor = 71; for (j=0 ; j<3 ; j++) { p->org[j] = move[j] + dir[j]*1; p->vel[j] = dir[j]* (len * 5); } VectorAdd (move, vec, move); } // dec = 8; VectorScale (vec, dec, vec); VectorCopy (start, move); } /* =============== R_DrawParticles =============== */ extern cvar_t *sv_gravity; extern int currentparticlepass; extern cvar_t *r_particletrans; extern cvar_t *r_particlesprite; extern byte remapmap[256]; // For translating an old palette to new on load extern int particletypeonly; extern particle_t *currentparticle; void R_DrawParticles (void) { particle_t *p, *kill; entity_t *ent; float grav; int i; int forg; float time2, time3; float time1; int polor; float dvel; float frametime; int where; vec3_t whare; int liftoff; // hexen 2 mleaf_t *l; mleaf_t *o; vec3_t diff; vec3_t below; qboolean in_solid; #ifdef GLQUAKE vec3_t up, right; float scale; GL_Bind(particletexture); glEnable (GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBegin (GL_TRIANGLES); VectorScale (vup, 8.5, up); VectorScale (vright, 8.5, right); #else D_StartParticles (); VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); #endif frametime = cl.time - cl.oldtime; time3 = frametime * 15; time2 = frametime * 10; // 15; time1 = frametime * 5; grav = frametime * sv_gravity->value * 0.05; dvel = 4*frametime; for ( ;; ) { kill = active_particles; if (kill && kill->die < cl.time) { active_particles = kill->next; kill->next = free_particles; free_particles = kill; continue; } break; } for (p=active_particles ; p ; p=p->next) { for ( ;; ) { kill = p->next; if (kill && kill->die < cl.time) { p->next = kill->next; kill->next = free_particles; free_particles = kill; continue; } break; } /* if (particletypeonly == 1 && p->sprtype == 5) { model_t *hello; if ((p->model = Mod_ForName("particle.spr", false))) { currentparticle = p; VectorCopy(p->org, r_entorigin); VectorSubtract(r_origin, r_entorigin, modelorg); R_DrawSprite2(); return; } }*/ #ifdef GLQUAKE // hack a scale up to keep particles from disapearing scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + (p->org[2] - r_origin[2])*vpn[2]; if (scale < 20) scale = 1; else scale = 1 + scale * 0.004; glColor3ubv ((byte *)&d_8to24table[(int)p->polor]); glTexCoord2f (0,0); glVertex3fv (p->org); glTexCoord2f (1,0); glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); glTexCoord2f (0,1); glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); #else if (p->blend == 5) p->blend = 1; if (p->sprtype == 5) p->sprtype = 4; // if (p->stickable == 2){ // VectorCopy(p->vstuck1, p->org); // // } if (particleset == 1){ p->frame = 3; // glquake style particle hack p->anglevel[2] = 0; p->angles[2] = 0; p->scale = 0.3f; p->scaley = p->scale; p->blend = 3; p->alphavel = 0; p->scalexvel = 0; p->scaleyvel = 0; p->sprtype = 2; } // COLOR PRECALCULATE /* // LIT PARTICLES if (p->lit){ int la, ra, ga, ba; float lightvec[3]; float rlightvec[3]; float glightvec[3]; float blightvec[3]; float rlightvec2[3]; float glightvec2[3]; float blightvec2[3]; vec3_t dist; float add; float radd; float gadd; float badd; int lnum; dlight_t *dl; vec3_t t; vec3_t ar; vec3_t ag; vec3_t ab; la = R_LightPoint(p->org); // add dynamic lights for (lnum=0 ; lnumradius) continue; if (dl->die < cl.time) continue; if (dl->unmark) // leilei - skip world light continue; VectorSubtract (p->org, dl->origin, dist); add = dl->radius - Length(dist); radd = dl->radius * dl->color[0] - Length(dist) ; gadd = dl->radius * dl->color[1] - Length(dist) ; badd = dl->radius * dl->color[2] - Length(dist) ; if (add > 0) { float scale = 1.0-(Length(dist)/dl->radius); scale *= scale; // scale ^ 2 la += add*(scale); ra += radd*(scale); ga += gadd*(scale); ba += badd*(scale); } if (radd > 0) { float scale = 1.0-(Length(dist)/dl->radius); scale *= scale; // scale ^ 2 ra += radd*(scale); VectorScale (dist, scale, dist); } if (gadd > 0) { float scale = 1.0-(Length(dist)/dl->radius); scale *= scale; // scale ^ 2 ga += gadd*(scale); VectorScale (dist, scale, dist); } if (badd > 0) { float scale = 1.0-(Length(dist)/dl->radius); scale *= scale; // scale ^ 2 ba += badd*(scale); VectorScale (dist, scale, dist); } } la *= -64; la += 16300; if (la < 0) la = 0; polor = ((byte *)host_colormap)[p->polor + (la & 0xFF00)]; } else */ polor = p->polor; // FOGGED PARTICLES if (foguse){ vec3_t local, transformed; float zi; int izi; // transform point VectorSubtract (p->org, r_origin, local); transformed[0] = DotProduct(local, r_pright); transformed[1] = DotProduct(local, r_pup); transformed[2] = DotProduct(local, r_ppn); zi = 1.0 / transformed[2]; izi = (int)(zi * 0x8000); forg = (float)izi * -128 + 32768; if (forg > 32764) forg = 32764; if (forg < 0) forg = 0; p->color = (int)host_fogmap [(int)polor + (forg >> 2 & 0xFF00)]; p->trail = 0; // don't do trails if we are fogged (covering up a visual bug that needs to be fixed) } else{ // PALETTE REMAPPED PARTICLES if (rmap_ready) polor= coltranslate[polor]; p->color = polor; //we got it. } if (!p->trail && !p->frame && !particletypeonly){ if (r_particletrans->value){ if (p->blend == 1) // Additive map case D_DrawParticle_Add (p); // else if (p->blend == 2) // Gelmap case // D_DrawParticle_Gel (p); else if (p->alpha < 0.33f) D_DrawParticle_A33 (p); else if (p->alpha < 0.66f) D_DrawParticle_A66 (p); else D_DrawParticle (p); } else D_DrawParticle (p); } #endif// PARTICLE COLLISION CODE FROM HEXEN II! (It used to be for snow now it's for everything!) // BEIGN // leilei - particle sprites if (p->frame && r_particlesprite->value && !particletypeonly) { model_t *hello; if ((p->model = Mod_ForName("particle.spr", false))) { currentparticle = p; VectorCopy(p->org, r_entorigin); VectorSubtract(r_origin, r_entorigin, modelorg); currentparticlepass = 3; R_DrawSprite2(); // Subtractives first (i.e. decals!) currentparticlepass = 1; R_DrawSprite2(); // Alphas second.... currentparticlepass = 2; R_DrawSprite2(); // Additives last } } if(!r_particletrails->value) p->trail = 0; // terminate trails //else if (p->die < cl.time - 0.1) p->trail = 0; // don't trail... // if (p->die > cl.time - 0.03) // leilei - hook up a trail if (p->trail && particleset != 2) { if (!p->org[0]) return; // apparently there isnt VectorMA(p->org, -p->trail/(Length(p->vel)), p->vel, whare); // Since Lines are drawn after particles, we also have to calculate fog. AGAIN! if (foguse){ vec3_t local, transformed; float zi; int izi; // transform point VectorSubtract (whare, r_origin, local); transformed[0] = DotProduct(local, r_pright); transformed[1] = DotProduct(local, r_pup); transformed[2] = DotProduct(local, r_ppn); zi = 1.0 / transformed[2]; izi = (int)(zi * 0x8000); forg = (float)izi * -128 + 32768; if (forg > 32764) forg = 32764; if (forg < 0) forg = 0; polor = (int)host_fogmap [(int)p->polor + (forg >> 2 & 0xFF00)]; } else polor = p->polor; //we got it. // VectorMA(p->org, -p->trail/(Length(p->vel)), p->vel, whare); D_DrawSparkTrans(p->org,whare,polor, p->blend); } // make 'em move #ifndef GLQUAKE if (reflectpass || particletypeonly) break; #else if (particletypeonly) break; #endif if(particletypeonly == 0){ p->org[0] += p->vel[0] * frametime; p->org[1] += p->vel[1] * frametime; p->org[2] += p->vel[2] * frametime; p->alpha += frametime*p->alphavel; p->scale += frametime*p->scalexvel; p->scaley += frametime*p->scaleyvel; p->angles[0] += frametime*p->anglevel[0]; p->angles[1] += frametime*p->anglevel[1]; p->angles[2] += frametime*p->anglevel[2]; if (p->alpha < 0.06 && p->alphavel && !(p->type==pt_flare)) p->die = -1; else if (p->alpha < 0.06 && p->alphavel && (p->type==pt_flare)) p->alpha = 0.06; if (p->alpha > 1.1) p->alpha = 1.1; } if (p->stickable != 2) p->stickable = 0; // don't stick........ switch (p->type) { case pt_static: p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_bloodsplatten: // leilei - blood hitting the world. We check for where in the world and how to treat it right. p->alpha = 1;p->blend = 0;p->lit = 1; if (!p->stickable) p->stickable = 1; //p->trail = 0; // check floor p->scalexvel = 0.0f; p->scaleyvel = 0.0f; if (p->scale > 3) p->die = -1; // leilei - too much blood... // does this actually work??? { trace_t trace; vec3_t nah; vec3_t there; VectorAdd(p->org, p->vel, there); VectorAdd(p->org, p->vel, there); VectorAdd(p->org, p->vel, there); VectorAdd(p->org, p->vel, there); VectorAdd(p->org, p->vel, there); } whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] - 6; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 5; else where = 6; // check sky (relaly quick) whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] + 12; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents == CONTENTS_SKY){ where = 54; p->die = -1; // die particle! hahaha } // check ceil (relaly quick) whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] + 2; o = Mod_PointInLeaf (whare, cl.worldmodel); if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 1; // check walls... whare[0] = p->org[0] + 4; whare[1] = p->org[1]; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; whare[0] = p->org[0] - 4; whare[1] = p->org[1]; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; whare[0] = p->org[0]; whare[1] = p->org[1] + 4; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; whare[0] = p->org[0]; whare[1] = p->org[1] - 4; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] + 32; o = Mod_PointInLeaf (whare, cl.worldmodel); if (where == 7 && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) { where = 2; // nothing over us (assumed on a wall now) } // Check the floor again whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] - 6; o = Mod_PointInLeaf (whare, cl.worldmodel); if ((where == 7) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 5; whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] + 24; o = Mod_PointInLeaf (whare, cl.worldmodel); if ((where == 6) && o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) { where = 1; // nothing under us... // p->polor = 15; } // Case processing if (where == 7) { // A Wall (Run down the wall) p->type = pt_bloodrun; p->scalexvel = -0.3f; p->scaleyvel = 0.5f; if (particleset == 2){ R_Decal (p->org, 6+rand()%3, 6, 0.8f, 1); // splatify. p->die = -1; } else { p->trail = 3; // the linesy line method i teased before. } p->die += 5; p->alphavel = -r_particlebloodfade->value; // decal instead? if (particleset == 2){ // if (rand()%8 > 7) if (p->vel[2] > 0) // if it's going up, stick up R_Decal (p->org, 6+rand()%3, 6, 0.8f, 0); } } else if (where == 1){ // A Ceiling // p->polor = 15; //p->type = pt_blooddrip; p->sprtype = 1; p->angles[0] = 0; p->angles[1] = 0; p->angles[2] = 0; p->scalexvel = -0.2f; p->scaleyvel = 0.6f; // gravity pulls it downer... p->sprtype = 3; p->frame = 5; if(p->die < cl.time + 1 || p->scale < 0.4){ p->type = pt_blooddrip; p->trail = 10; p->die += 5; // it's time to drip! p->scaley = 5; p->sprtype = 3; // decal instead? if (particleset == 2){ R_Decal (p->org, 6+rand()%3, 6, 1.2f, 0); p->frame = 5; p->trail = 0; p->alpha = 0; } } } else if (where == 5){ // Floor p->type = pt_bloodfloor; p->trail = 0; p->alphavel = -r_particlebloodfade->value; p->scalexvel = 0.0f; p->scaleyvel = 0.0f; // decal instead? if (particleset == 2){ p->die = -1; if (rand()%8 > 4) R_Decal (p->org, 6+rand()%3, 6, 0.7f, 0);// } } p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_blooddrip: // leilei - Blood dripping from the ceiling. p->alpha = 1;p->blend = 0;p->lit = 1;p->trail = 5; //p->flat = 1; if (!p->stickable) p->stickable = 1; p->sprtype = 1; p->angles[0] = 0; p->angles[1] = 0; p->angles[2] = 0; if (p->scale > 1){ p->scaley = p->scale; // leilei - too much blood. p->scale = 1; } // p->scalexvel = -0.1f; if (p->scale < 0.2) p->scale = 0.2; p->scaleyvel = 1; //.. leilei - drip vertically fast if (p->scaley > 4) p->scaley = 4; if (!p->vel[2]) p->vel[2] = -70; // give an initial gravity pull as the drop gets off the ceiling. p->vel[2] -= grav * 17; // check floor whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] - 6; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 5; else where = 6; // check sky (relaly quick) whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] + 12; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents == CONTENTS_SKY){ where = 54; p->die = -1; // die particle! hahaha } // Case processing if (where == 5){ // Floor R_ParticleBloodSplash(p->org, p->vel[2], p->polor); // splat! p->type = pt_bloodfloor; if (particleset == 2){ R_Decal (p->org, 6+rand()%3, 6, 0.8f, 0); // splatify. p->die = -1; } //p->die = -1; // terminate the drop } break; case pt_drip: // leilei - generic dripping p->lit = 0; p->sprtype = 1; p->angles[0] = 0; p->angles[1] = 0; p->angles[2] = 0; if (p->scale > 1){ p->scaley = p->scale; p->scale = 1; } // p->scalexvel = -0.1f; if (p->scale < 0.2) p->scale = 0.2; p->scaleyvel = 5; //.. leilei - drip vertically fast if (p->scaley > 4) p->scaley = 4; if (!p->vel[2]) p->vel[2] = -70; // give an initial gravity pull as the drop gets off the ceiling. p->vel[2] -= grav * 17; // check floor whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] - 6; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 5; else where = 6; // check sky (relaly quick) whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] + 12; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents == CONTENTS_SKY){ where = 54; p->die = -1; // die particle! hahaha } // Case processing if (where == 5){ // Floor if (particleset == 2){ p->die = -1; } //p->die = -1; // terminate the drop } break; case pt_bloodrun: // leilei - Blood running down the wall. //p->flat = 1; //p->alpha += frametime*p->alphavel; // p->scalexvel = -0.03f; //p->scaleyvel = 0.3f; p->scalexvel = p->vel[2] * 0.02; p->scaleyvel = p->vel[2] * -0.2; if (p->scaley > 1.7){ p->scaley = 1.7; p->vel[0] = 0; p->vel[1] = 0; p->vel[2] = 0; p->scalexvel = 0; p->scaleyvel = 0; break; } if (p->scale > 1) p->die = -1; // leilei - too much blood... if (p->alpha <= 0) p->die = -1; // TODO: Add a trail if (!p->vel[2]) p->vel[2] = grav * -7; //- (rand()*55); // check floor whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] - 1; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 5; else where = 6; // check walls... whare[0] = p->org[0] + 4; whare[1] = p->org[1]; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; whare[0] = p->org[0] - 4; whare[1] = p->org[1]; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; whare[0] = p->org[0]; whare[1] = p->org[1] + 4; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; whare[0] = p->org[0]; whare[1] = p->org[1] - 4; whare[2] = p->org[2]; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 7; // Case processing if (where == 5){ // Floor p->trail = 0; p->type = pt_bloodfloor; // Become a drip } else if (where != 7){ // Not on a wall p->trail = 6; p->type = pt_blooddrip; // Become a drip p->sprtype = 3; } //p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_bloodfloor: // leilei - Blood is drying up on that floor. p->blend = 0;p->lit = 0;p->trail = 0; p->alpha += frametime*p->alphavel; if (p->scale > 4) p->die = -1; // leilei - too much blood... if (p->alpha <= 0) p->die = -1; // check floor whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] - 6; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents != CONTENTS_EMPTY && ( o->contents != CONTENTS_WATER || o->contents != CONTENTS_LAVA || o->contents != CONTENTS_SLIME)) where = 5; else where = 6; // check sky (relaly quick) whare[0] = p->org[0]; whare[1] = p->org[1]; whare[2] = p->org[2] + 12; o = Mod_PointInLeaf (whare, cl.worldmodel); if (o->contents == CONTENTS_SKY){ where = 54; p->die = -1; // die particle! hahaha } // Case processing if (where == 6){ // Not the Floor p->type = pt_blooddrip; // move off incase it's a platform maybe p->die = cl.time + 2; } p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_fire: p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0; p->ramp += time1; if (p->ramp >= 6) p->die = -1; else p->polor = ramp3[(int)p->ramp]; p->vel[2] += grav; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_explode: p->ramp += time2; // p->splatter = 0; if (p->ramp >=8) p->die = -1; else p->polor = ramp1[(int)p->ramp]; for (i=0 ; i<3 ; i++) p->vel[i] += p->vel[i]*dvel; p->vel[2] -= grav; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_explode2: p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0; p->ramp += time3; // p->splatter = 0; if (p->ramp >=8) p->die = -1; else p->polor = ramp2[(int)p->ramp]; for (i=0 ; i<3 ; i++) p->vel[i] -= p->vel[i]*frametime; p->vel[2] -= grav; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_blob: p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0; for (i=0 ; i<3 ; i++) p->vel[i] += p->vel[i]*dvel; p->vel[2] -= grav; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_blob2: p->alpha = 1;p->blend = 0;p->lit = 0;p->trail = 0; for (i=0 ; i<2 ; i++) p->vel[i] -= p->vel[i]*dvel; p->vel[2] -= grav; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_grav: p->vel[2] -= grav * 12; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; // huge blood crap case pt_bloodsplat: //p->blend = 0; p->lit = 0; //p->alpha += frametime*p->alphavel; //p->scalexvel = 0; p->stickable = 1; //p->anglevel[2] = 0; if (p->scale > 2) p->scale = 2;; // leilei - too much blood. l = Mod_PointInLeaf (p->org, cl.worldmodel); if (l->contents == CONTENTS_WATER || l->contents == CONTENTS_LAVA || l->contents == CONTENTS_SLIME) // in a liquid { p->type = pt_bloodsplat; p->alphavel = -0.4 * (rand()&8); p->vel[0] *= 0.96; p->vel[1] *= 0.96; p->vel[2] *= 0.96; p->vel[0] += (rand()%4-2); p->vel[1] += (rand()%4-2); // disperse, dissolve, dissipate p->vel[2] += (rand()%4-2); p->vel[0] *= p->alpha; p->vel[1] *= p->alpha; p->vel[2] *= p->alpha; p->scalexvel = 3.1; p->scaleyvel = 3.1; // p->alphavel = -0.2; p->anglevel[2] *= 0.93; // reduce angle velocity as well, stop blood from spining p->blend = 1; // additive because we get alpha in that } else if (l->contents != CONTENTS_EMPTY && ( l->contents != CONTENTS_WATER || l->contents != CONTENTS_LAVA || l->contents != CONTENTS_SLIME)) // || in_solid == true { p->type = pt_bloodsplatten; p->alphavel = -0.1 * (rand()&8); p->vel[0] = 0; p->vel[1] = 0; p->vel[2] = 0; p->anglevel[2] = 0; } else { // p->vel[2] -= grav * 6; VectorScale(p->vel, frametime, diff); VectorAdd(p->org, diff, p->org); // WHERE THE HITTING HAPPENS // if hit solid, go to last position, // no velocity, fade out. l = Mod_PointInLeaf (p->org, cl.worldmodel); if (l->contents != CONTENTS_EMPTY && ( l->contents != CONTENTS_WATER || l->contents != CONTENTS_LAVA || l->contents != CONTENTS_SLIME)) // || in_solid == true { VectorScale(diff, 0.2, p->vel); i = 6; while (l->contents != CONTENTS_EMPTY && ( l->contents != CONTENTS_WATER || l->contents != CONTENTS_LAVA || l->contents != CONTENTS_SLIME)) { VectorNormalize(p->vel); p->org[0] -= p->vel[0]*3; p->org[1] -= p->vel[1]*3; p->org[2] -= p->vel[2]*3; p->scalexvel = 0; p->scaleyvel = 0; p->anglevel[2] = 0; //p->die += 1; i--; //no infinite loops if (!i) { p->die = -1; //should never happen now! break; } l = Mod_PointInLeaf (p->org, cl.worldmodel); } p->vel[0] = p->vel[1] = p->vel[2] = 0; p->anglevel[2] = 0; if (particleset == 2){ p->die = -1; R_Decal (p->org, p->frame, 6, p->scale, rand()%2); } p->ramp = 0; p->trail = 0; p->scalexvel = 0; p->scaleyvel = 0; p->anglevel[2] = 0; p->type = pt_bloodsplatten; } else { //p->alpha = 1; // leileileilei p->trail = 0; // p->vel[2] -= grav * 4; p->vel[2] -= grav * 10; } p->scaley = p->scale; // there are some types you don't want a vertical scale for // END CODE of stupid hexen 2 particle collision break; case pt_slowgrav: p->vel[2] -= grav; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_fastgrav: p->vel[2] -= grav * 15; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_spark: p->blend = 1;p->lit = 0; p->vel[2] -= grav * 12; // VectorMA(p->org, -8/(Length(p->vel)), p->vel, whare); // R_ParticleTrail2(p->org,whare,0,p->blend,p->polor); p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_sparkvel: p->vel[2] -= grav * 12; p->vel[0] *= 0.9; p->vel[1] *= 0.9; p->vel[2] *= 0.9; { vec3_t vec, forward, angle_dir; float lengthe; // lengthe = Length(p->vel) * 0.0006; //VectorCopy(vec, forward); vectoangles2 (p->vel, angle_dir); p->angles[0] = angle_dir[0]; p->angles[1] = angle_dir[2]; p->angles[2] = angle_dir[1] - 90; // p->angles[2] *= 3; p->sprtype = 44; p->scaley = lengthe; // there are some types you don't want a vertical scale for //p->scaley = 3; // there are some types you do want a vertical scale for } break; case pt_blood: p->lit = 1;p->trail = 0; p->stickable = 1; p->vel[2] -= grav * 12; //p->scaley = p->scale; // there are some types you don't want a vertical scale for break; // leilei - flares case pt_flare: p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_flare_will_die: // for entities..... p->scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + (p->org[2] - r_origin[2])*vpn[2]; if (p->scale < 40) p->scale = 0.1; else p->scale = 0.1 + p->scale * 0.004; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_smoke: p->scaley = p->scale; // there are some types you don't want a vertical scale for p->alpha += frametime*p->alphavel; if (sprity){ p->vel[0] *= 0.96; p->vel[1] *= 0.96; p->vel[2] += (grav * 0.7); } else p->vel[2] += grav; p->anglevel[2] *= 0.96; break; // TomazQuake case pt_snow: if (cl.time > p->die) { p->die = cl.time + (rand() & 3) * 0.1; p->vel[0] = (rand() & 64) - 32; p->vel[1] = (rand() & 64) - 32; } p->scaley = p->scale; // there are some types you don't want a vertical scale for break; // TomazQuake case pt_trail: p->trail = 0; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_add: p->trail = 0; if(p->alpha < 0.02) p->alpha = 1; else p->alpha -= 0.5; p->alpha = 0.5; p->blend = 2;p->lit = 0; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_decel: p->alpha = 1;p->trail = 0; p->blend = 0;p->lit = 0; for (i=0 ; i<3 ; i++) p->vel[i] += p->vel[i]* -dvel; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_staticfade: p->alpha += frametime*p->alphavel;p->trail = 0; p->alpha -= cl.time*(0.001 +(rand() % 6 * 0.006)); p->blend = 0;p->lit = 0; if (p->alpha <= 0) p->die = -1; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_staticfadeadd: p->alpha += frametime*p->alphavel;p->trail = 0; //p->blend = 2;p->lit = 0; p->vel[0] *= 0.8f; p->vel[1] *= 0.8f; p->vel[2] *= 0.8f; if (p->alpha <= 0) p->die = -1; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; case pt_slowgravaddfade: p->alpha += frametime*p->alphavel;p->trail = 0; p->blend = 2;p->lit = 0; p->vel[2] -= grav; if (p->alpha <= 0) p->die = -1; p->scaley = p->scale; // there are some types you don't want a vertical scale for break; } } #ifdef GLQUAKE glEnd (); glDisable (GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); #else D_EndParticles (); #endif } } // test visibility of flares first.... void R_TestFlares (void) { flare_t *p, *kill; entity_t *ent; float grav; int i; float time2, time3; float time1; float frametime; int liftoff; int amiseen; #ifndef GLQUAKE VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); #else // VectorScale (vright, xscale, r_pright); // VectorScale (vup, yscale, r_pup); // VectorCopy (vpn, r_ppn); #endif for ( ;; ) { kill = active_flares; if (kill && kill->die < cl.time) { active_flares = kill->next; kill->next = free_flares; free_flares = kill; continue; } break; } for (p=active_flares ; p ; p=p->next) { for ( ;; ) { kill = p->next; if (kill && kill->die < cl.time) { p->next = kill->next; kill->next = free_flares; free_flares = kill; continue; } break; } { int there; int u1, v1, z1; int eh; int u2, v2, z2 = 88; vec3_t hi; trace_t yourface; vec3_t forward, left, up; AngleVectors(r_refdef.viewangles, forward, left, up); VectorCompare(yourface.endpos,r_refdef.vieworg); p->amiseen = 0; // reset to 0. when not seen. always. Stops a PVS bug where you saw a flare // turn your back towards it, move to next room, then turn back to see it // fade away late D_TestOurFlare(p); // lets do it } } } void R_DrawFlares (void) { flare_t *p, *kill; entity_t *ent; float grav; int i; float time2, time3; float time1; float frametime; int liftoff; int amiseen; VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); frametime = cl.time - cl.oldtime; time3 = frametime * 15; time2 = frametime * 10; // 15; time1 = frametime * 5; grav = frametime * sv_gravity->value * 0.05; for ( ;; ) { kill = active_flares; if (kill && kill->die < cl.time) { active_flares = kill->next; kill->next = free_flares; free_flares = kill; continue; } break; } for (p=active_flares ; p ; p=p->next) { for ( ;; ) { kill = p->next; if (kill && kill->die < cl.time) { p->next = kill->next; kill->next = free_flares; free_flares = kill; continue; } break; } p->org[0] += p->vel[0] * frametime; p->org[1] += p->vel[1] * frametime; p->org[2] += p->vel[2] * frametime; p->alpha += frametime*p->alphavel; p->scale += frametime*p->scalexvel; p->scaley += frametime*p->scaleyvel; p->angles[2] += frametime*p->anglevel[2]; if (p->alpha < 0.06 && p->alphavel && !(p->type==pt_flare)) p->die = -1; else if (p->alpha < 0.06 && p->alphavel && (p->type==pt_flare)) p->alpha = 0.06; if (p->alpha > 1.1) p->alpha = 1.1; if (p->scale < 0) p->die = -1; if (p->scaley < 0) p->die = -1; int there; int u1, v1, z1; int eh; int u2, v2, z2 = 88; vec3_t hi; trace_t yourface; vec3_t forward, left, up; AngleVectors(r_refdef.viewangles, forward, left, up); VectorCompare(yourface.endpos,r_refdef.vieworg); // Removing an entity's flare if (p->owned && p->owner){ if (p->oldmodel != p->owner->model){ p->owner->gotaflare = 0; p->owner->ourparticle = NULL; p->owner = NULL; p->die = -1; // oh.....noooooooooo } p->org[0] = p->owner->origin[0]; p->org[1] = p->owner->origin[1]; p->org[2] = p->owner->origin[2]; } for(eh=0; eh<3; eh++){ forward[eh] *= 350; left[eh] *= -380; // 380 up[eh] *= 135; } if (reflectpass) { p->scale = (p->org[0] - r_refdef.vieworg[0])*vpn[0] + (p->org[1] - r_refdef.vieworg[1])*vpn[1] + (p->org[2] - r_refdef.vieworg[2])*vpn[2]; if (p->scale < 50) p->scale = 0.06f; else p->scale = 0.02f + p->scale * 0.001; p->scaley = p->scale * 5; p->sprtype = SPR_VP_PARALLEL_UPRIGHT; } else { p->scale = (p->org[0] - r_refdef.vieworg[0])*vpn[0] + (p->org[1] - r_refdef.vieworg[1])*vpn[1] + (p->org[2] - r_refdef.vieworg[2])*vpn[2]; if (p->scale < 50) p->scale = 0.12f; else p->scale = 0.02f + p->scale * 0.002; p->scaley = p->scale; p->sprtype = 5; } // new z check if (p->amiseen) { int sweetch; sweetch = R_LightPoint (p->org); if (sweetch < 16) p->alphavel = -1.74; else p->alphavel = 1.8; } else { p->alphavel = -1.74; } model_t *hello; if ((p->model = Mod_ForName("particle.spr", false))) { currentflare = p; VectorCopy(p->org, r_entorigin); VectorSubtract(r_origin, r_entorigin, modelorg); R_DrawSprite3(); } } } // Stupid function for entities with instant flares to try and fade them out like normal flares!! void R_FlareEntityAlphaMakeCheckDoStuff (vec3_t checkhere, float fe, float fi) { trace_t tarce; float time1; float frametime; frametime = cl.time - cl.oldtime; time1 = frametime * 5; if (!fe) fe = 1.0f; //if (currententity->flalpha < 0.06 && currententity->flalphavel) // currententity->flalpha = 0.01; if (fe < 0.06) fe = 0.06; if (fe > 1.1) fe = 1.1; tarce = Particle_TraceLine(checkhere, r_refdef.vieworg); if(tarce.fraction < 1) fi = -1.74; else{ fi = 1.8; } fe += frametime*fi; }