-#define particle(ptype, porientation, pcolor1, pcolor2, ptex, plight, pblendmode, pscalex, pscaley, palpha, palphafade, ptime, pgravity, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\
-{\
- if (cl_numparticles < cl_maxparticles)\
- {\
- particle_t *part;\
- int ptempcolor, ptempcolor2, pcr1, pcg1, pcb1, pcr2, pcg2, pcb2;\
- ptempcolor = (pcolor1);\
- ptempcolor2 = (pcolor2);\
- pcr2 = ((ptempcolor2) >> 16) & 0xFF;\
- pcg2 = ((ptempcolor2) >> 8) & 0xFF;\
- pcb2 = (ptempcolor2) & 0xFF;\
- if (ptempcolor != ptempcolor2)\
- {\
- pcr1 = ((ptempcolor) >> 16) & 0xFF;\
- pcg1 = ((ptempcolor) >> 8) & 0xFF;\
- pcb1 = (ptempcolor) & 0xFF;\
- ptempcolor = rand() & 0xFF;\
- pcr2 = (((pcr2 - pcr1) * ptempcolor) >> 8) + pcr1;\
- pcg2 = (((pcg2 - pcg1) * ptempcolor) >> 8) + pcg1;\
- pcb2 = (((pcb2 - pcb1) * ptempcolor) >> 8) + pcb1;\
- }\
- part = &particles[cl_numparticles++];\
- memset(part, 0, sizeof(*part));\
- part->type = (ptype);\
- part->color[0] = pcr2;\
- part->color[1] = pcg2;\
- part->color[2] = pcb2;\
- part->color[3] = 0xFF;\
- part->orientation = porientation;\
- part->texnum = ptex;\
- part->blendmode = pblendmode;\
- part->scalex = (pscalex);\
- part->scaley = (pscaley);\
- part->alpha = (palpha);\
- part->alphafade = (palphafade);\
- part->die = cl.time + (ptime);\
- part->gravity = (pgravity);\
- part->bounce = (pbounce);\
- part->org[0] = (px);\
- part->org[1] = (py);\
- part->org[2] = (pz);\
- part->vel[0] = (pvx);\
- part->vel[1] = (pvy);\
- part->vel[2] = (pvz);\
- part->time2 = (ptime2);\
- part->vel2[0] = (pvx2);\
- part->vel2[1] = (pvy2);\
- part->vel2[2] = (pvz2);\
- part->friction = (pfriction);\
- part->pressure = (ppressure);\
- }\
+// list of all 26 parameters:
+// ptype - any of the pt_ enum values (pt_static, pt_blood, etc), see ptype_t near the top of this file
+// pcolor1,pcolor2 - minimum and maximum ranges of color, randomly interpolated to decide particle color
+// ptex - any of the tex_ values such as tex_smoke[rand()&7] or tex_particle
+// psize - size of particle (or thickness for PARTICLE_SPARK and PARTICLE_BEAM)
+// palpha - opacity of particle as 0-255 (can be more than 255)
+// palphafade - rate of fade per second (so 256 would mean a 256 alpha particle would fade to nothing in 1 second)
+// ptime - how long the particle can live (note it is also removed if alpha drops to nothing)
+// pgravity - how much effect gravity has on the particle (0-1)
+// pbounce - how much bounce the particle has when it hits a surface (0-1), -1 makes a blood splat when it hits a surface, 0 does not even check for collisions
+// px,py,pz - starting origin of particle
+// pvx,pvy,pvz - starting velocity of particle
+// pfriction - how much the particle slows down per second (0-1 typically, can slowdown faster than 1)
+particle_t *particle(particletype_t *ptype, int pcolor1, int pcolor2, int ptex, float psize, float palpha, float palphafade, float pgravity, float pbounce, float px, float py, float pz, float pvx, float pvy, float pvz, float pfriction)
+{
+ particle_t *part;
+ int ptempcolor, ptempcolor2, pcr1, pcg1, pcb1, pcr2, pcg2, pcb2;
+ ptempcolor = (pcolor1);
+ ptempcolor2 = (pcolor2);
+ pcr2 = ((ptempcolor2) >> 16) & 0xFF;
+ pcg2 = ((ptempcolor2) >> 8) & 0xFF;
+ pcb2 = (ptempcolor2) & 0xFF;
+ if (ptempcolor != ptempcolor2)
+ {
+ pcr1 = ((ptempcolor) >> 16) & 0xFF;
+ pcg1 = ((ptempcolor) >> 8) & 0xFF;
+ pcb1 = (ptempcolor) & 0xFF;
+ ptempcolor = rand() & 0xFF;
+ pcr2 = (((pcr2 - pcr1) * ptempcolor) >> 8) + pcr1;
+ pcg2 = (((pcg2 - pcg1) * ptempcolor) >> 8) + pcg1;
+ pcb2 = (((pcb2 - pcb1) * ptempcolor) >> 8) + pcb1;
+ }
+ for (;cl_freeparticle < cl_maxparticles && particles[cl_freeparticle].type;cl_freeparticle++);
+ if (cl_freeparticle >= cl_maxparticles)
+ return NULL;
+ part = &particles[cl_freeparticle++];
+ if (cl_numparticles < cl_freeparticle)
+ cl_numparticles = cl_freeparticle;
+ memset(part, 0, sizeof(*part));
+ part->type = (ptype);
+ part->color[0] = pcr2;
+ part->color[1] = pcg2;
+ part->color[2] = pcb2;
+ part->color[3] = 0xFF;
+ part->texnum = ptex;
+ part->size = (psize);
+ part->alpha = (palpha);
+ part->alphafade = (palphafade);
+ part->gravity = (pgravity);
+ part->bounce = (pbounce);
+ part->org[0] = (px);
+ part->org[1] = (py);
+ part->org[2] = (pz);
+ part->vel[0] = (pvx);
+ part->vel[1] = (pvy);
+ part->vel[2] = (pvz);
+ part->time2 = 0;
+ part->friction = (pfriction);
+ return part;
+}
+
+void CL_SpawnDecalParticleForSurface(void *hitent, const vec3_t org, const vec3_t normal, int color1, int color2, int texnum, float size, float alpha)
+{
+ particle_t *p;
+ if (!cl_decals.integer)
+ return;
+ p = particle(particletype + pt_decal, color1, color2, texnum, size, alpha, 0, 0, 0, org[0] + normal[0], org[1] + normal[1], org[2] + normal[2], normal[0], normal[1], normal[2], 0);
+ if (p)
+ {
+ p->time2 = cl.time;
+#ifndef WORKINGLQUAKE
+ p->owner = hitent;
+ p->ownermodel = p->owner->model;
+ Matrix4x4_Transform(&p->owner->inversematrix, org, p->relativeorigin);
+ Matrix4x4_Transform3x3(&p->owner->inversematrix, normal, p->relativedirection);
+ VectorAdd(p->relativeorigin, p->relativedirection, p->relativeorigin);
+#endif
+ }
+}
+
+void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size, float alpha, int texnum, int color1, int color2)
+{
+ int i;
+ float bestfrac, bestorg[3], bestnormal[3];
+ float frac, v[3], normal[3], org2[3];
+#ifdef WORKINGLQUAKE
+ void *besthitent = NULL, *hitent;
+#else
+ entity_render_t *besthitent = NULL, *hitent;
+#endif
+ bestfrac = 10;
+ for (i = 0;i < 32;i++)
+ {
+ VectorRandom(org2);
+ VectorMA(org, maxdist, org2, org2);
+ frac = CL_TraceLine(org, org2, v, normal, true, &hitent, SUPERCONTENTS_SOLID);
+ if (bestfrac > frac)
+ {
+ bestfrac = frac;
+ besthitent = hitent;
+ VectorCopy(v, bestorg);
+ VectorCopy(normal, bestnormal);
+ }
+ }
+ if (bestfrac < 1)
+ CL_SpawnDecalParticleForSurface(besthitent, bestorg, bestnormal, color1, color2, texnum, size, alpha);