added perframe, undoes per frametime emitting (for flares)
added nostate, disables use of trailstate (also for flares, problems with assoc) added averageout, reaverages particles from start/end with trails (for beams) added nospreadfirst/nospreadlast, disables spawnvel/spawnorg on first/last particles (for beams) moved citracer to flag added ball/circle spawnmode to trails (slightly different distribution from standard box) added distball spawnmode git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1453 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
6523dc2235
commit
0751c774e9
1 changed files with 173 additions and 69 deletions
|
@ -182,7 +182,6 @@ typedef struct part_type_s {
|
|||
vec3_t rgbrand;
|
||||
int colorindex;
|
||||
int colorrand;
|
||||
qboolean citracer;
|
||||
float rgbchangetime;
|
||||
vec3_t rgbrandsync;
|
||||
float scale, alpha;
|
||||
|
@ -226,16 +225,18 @@ typedef struct part_type_s {
|
|||
|
||||
float offsetup; // make this into a vec3_t later with dir, possibly for mdls
|
||||
|
||||
enum {SM_BOX, SM_CIRCLE, SM_BALL, SM_SPIRAL, SM_TRACER, SM_TELEBOX, SM_LAVASPLASH, SM_UNICIRCLE, SM_FIELD} spawnmode;
|
||||
//box = even spread within the area
|
||||
//circle = around edge of a circle
|
||||
//ball = filled sphere
|
||||
//spiral = spiral trail
|
||||
//tracer = tracer trail
|
||||
//telebox = q1-style telebox
|
||||
//lavasplash = q1-style lavasplash
|
||||
//unicircle = uniform circle
|
||||
//field = synced field (brightfield, etc)
|
||||
enum {
|
||||
SM_BOX, //box = even spread within the area
|
||||
SM_CIRCLE, //circle = around edge of a circle
|
||||
SM_BALL, //ball = filled sphere
|
||||
SM_SPIRAL, //spiral = spiral trail
|
||||
SM_TRACER, //tracer = tracer trail
|
||||
SM_TELEBOX, //telebox = q1-style telebox
|
||||
SM_LAVASPLASH, //lavasplash = q1-style lavasplash
|
||||
SM_UNICIRCLE, //unicircle = uniform circle
|
||||
SM_FIELD, //field = synced field (brightfield, etc)
|
||||
SM_DISTBALL // uneven distributed ball
|
||||
} spawnmode;
|
||||
|
||||
float gravity;
|
||||
vec3_t friction;
|
||||
|
@ -253,9 +254,15 @@ typedef struct part_type_s {
|
|||
skytris_t *skytris;
|
||||
|
||||
unsigned int flags;
|
||||
#define PT_VELOCITY 1
|
||||
#define PT_FRICTION 2
|
||||
#define PT_CHANGESCOLOUR 4
|
||||
#define PT_VELOCITY 0x001
|
||||
#define PT_FRICTION 0x002
|
||||
#define PT_CHANGESCOLOUR 0x004
|
||||
#define PT_CITRACER 0x008 // Q1-style tracer behavior for colorindex
|
||||
#define PT_INVFRAMETIME 0x010 // apply inverse frametime to count (causes emits to be per frame)
|
||||
#define PT_AVERAGETRAIL 0x020 // average trail points from start to end, useful with t_lightning, etc
|
||||
#define PT_NOSTATE 0x040 // don't use trailstate for this emitter (careful with assoc...)
|
||||
#define PT_NOSPREADFIRST 0x080 // don't randomize org/vel for first generated particle
|
||||
#define PT_NOSPREADLAST 0x100 // don't randomize org/vel for last generated particle
|
||||
} part_type_t;
|
||||
int numparticletypes;
|
||||
part_type_t *part_type;
|
||||
|
@ -473,8 +480,6 @@ void P_ParticleEffect_f(void)
|
|||
ptype->colorindex = -1;
|
||||
ptype->rotationstartmin = -M_PI; //start with a random angle
|
||||
ptype->rotationstartrand = M_PI-ptype->rotationstartmin;
|
||||
ptype->rotationmin = 0; //but don't spin
|
||||
ptype->rotationrand = 0;
|
||||
ptype->spawnchance = 1;
|
||||
|
||||
while(1)
|
||||
|
@ -591,7 +596,7 @@ void P_ParticleEffect_f(void)
|
|||
else if (!strcmp(var, "colorrand"))
|
||||
ptype->colorrand = atoi(value);
|
||||
else if (!strcmp(var, "citracer"))
|
||||
ptype->citracer = true;
|
||||
ptype->flags |= PT_CITRACER;
|
||||
|
||||
else if (!strcmp(var, "red"))
|
||||
ptype->rgb[0] = atof(value)/255;
|
||||
|
@ -704,6 +709,8 @@ void P_ParticleEffect_f(void)
|
|||
ptype->spawnmode = SM_UNICIRCLE;
|
||||
else if (!strcmp(value, "syncfield"))
|
||||
ptype->spawnmode = SM_FIELD;
|
||||
else if (!strcmp(value, "distball"))
|
||||
ptype->spawnmode = SM_DISTBALL;
|
||||
else
|
||||
ptype->spawnmode = SM_BOX;
|
||||
|
||||
|
@ -894,6 +901,16 @@ void P_ParticleEffect_f(void)
|
|||
|
||||
ptype->rampindexes++;
|
||||
}
|
||||
else if (!strcmp(var, "perframe"))
|
||||
ptype->flags |= PT_INVFRAMETIME;
|
||||
else if (!strcmp(var, "averageout"))
|
||||
ptype->flags |= PT_AVERAGETRAIL;
|
||||
else if (!strcmp(var, "nostate"))
|
||||
ptype->flags |= PT_NOSTATE;
|
||||
else if (!strcmp(var, "nospreadfirst"))
|
||||
ptype->flags |= PT_NOSPREADFIRST;
|
||||
else if (!strcmp(var, "nospreadlast"))
|
||||
ptype->flags |= PT_NOSPREADLAST;
|
||||
else
|
||||
Con_DPrintf("%s is not a recognised particle type field (in %s)\n", var, ptype->name);
|
||||
}
|
||||
|
@ -902,7 +919,6 @@ void P_ParticleEffect_f(void)
|
|||
if (ptype->clipcount < 1)
|
||||
ptype->clipcount = 1;
|
||||
|
||||
ptype->flags = 0;
|
||||
//if there is a chance that it moves
|
||||
if (ptype->randomvel || ptype->gravity || ptype->veladd || ptype->offsetspread || ptype->offsetspreadvert)
|
||||
ptype->flags |= PT_VELOCITY;
|
||||
|
@ -1933,6 +1949,10 @@ int P_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum,
|
|||
ptype = &part_type[ptype->inwater];
|
||||
}
|
||||
|
||||
// eliminate trailstate if flag set
|
||||
if (ptype->flags & PT_NOSTATE)
|
||||
tsk = NULL;
|
||||
|
||||
// trailstate allocation/deallocation
|
||||
if (tsk)
|
||||
{
|
||||
|
@ -2083,6 +2103,8 @@ int P_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum,
|
|||
b = bfirst = NULL;
|
||||
spawnspc = 8;
|
||||
pcount = count*ptype->count;
|
||||
if (ptype->flags & PT_INVFRAMETIME)
|
||||
pcount /= host_frametime;
|
||||
if (ts)
|
||||
pcount += ts->emittime;
|
||||
|
||||
|
@ -2698,9 +2720,14 @@ static int P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype,
|
|||
float step;
|
||||
float stop;
|
||||
float tdegree = 2*M_PI/256; /* MSVC whine */
|
||||
float nrfirst, nrlast;
|
||||
|
||||
VectorCopy(startpos, start);
|
||||
|
||||
// eliminate trailstate if flag set
|
||||
if (ptype->flags & PT_NOSTATE)
|
||||
tsk = NULL;
|
||||
|
||||
// trailstate allocation/deallocation
|
||||
if (tsk)
|
||||
{
|
||||
|
@ -2749,6 +2776,7 @@ static int P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype,
|
|||
if (!ptype->die)
|
||||
ts = NULL;
|
||||
|
||||
// use ptype step to calc step vector and step size
|
||||
step = 1/ptype->count;
|
||||
|
||||
if (step < 0.01)
|
||||
|
@ -2756,8 +2784,19 @@ static int P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype,
|
|||
|
||||
VectorSubtract (end, start, vec);
|
||||
len = VectorNormalize (vec);
|
||||
VectorScale(vec, step, vstep);
|
||||
|
||||
if (ptype->flags & PT_AVERAGETRAIL)
|
||||
{
|
||||
float tavg;
|
||||
// mangle len/step to get last point to be at end
|
||||
tavg = len / step;
|
||||
tavg = tavg / ceil(tavg);
|
||||
step *= tavg;
|
||||
len += step;
|
||||
}
|
||||
|
||||
VectorScale(vec, step, vstep);
|
||||
|
||||
// add offset
|
||||
start[2] += ptype->offsetup;
|
||||
|
||||
|
@ -2786,6 +2825,16 @@ static int P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype,
|
|||
// len = (len - (int)len)*step;
|
||||
// VectorMA (start, -len, vec, start);
|
||||
|
||||
if (ptype->flags & PT_NOSPREADFIRST)
|
||||
nrfirst = len + step*1.5;
|
||||
else
|
||||
nrfirst = len;
|
||||
|
||||
if (ptype->flags & PT_NOSPREADLAST)
|
||||
nrlast = stop;
|
||||
else
|
||||
nrlast = stop + step;
|
||||
|
||||
b = bfirst = NULL;
|
||||
|
||||
while (len < stop)
|
||||
|
@ -2844,7 +2893,7 @@ static int P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype,
|
|||
{
|
||||
int cidx;
|
||||
cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0;
|
||||
if (ptype->citracer) // colorindex behavior as per tracers in std Q1
|
||||
if (ptype->flags & PT_CITRACER) // colorindex behavior as per tracers in std Q1
|
||||
cidx += ((tcount & 4) << 1);
|
||||
|
||||
cidx = ptype->colorindex + cidx;
|
||||
|
@ -2876,64 +2925,119 @@ static int P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype,
|
|||
p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand;
|
||||
p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand;
|
||||
|
||||
switch(ptype->spawnmode)
|
||||
if (len < nrfirst || len >= nrlast)
|
||||
{
|
||||
case SM_TRACER:
|
||||
if (tcount & 1)
|
||||
{
|
||||
p->vel[0] = vec[1]*ptype->offsetspread;
|
||||
p->vel[1] = -vec[0]*ptype->offsetspread;
|
||||
p->org[0] = vec[1]*ptype->areaspread;
|
||||
p->org[1] = -vec[0]*ptype->areaspread;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->vel[0] = -vec[1]*ptype->offsetspread;
|
||||
p->vel[1] = vec[0]*ptype->offsetspread;
|
||||
p->org[0] = -vec[1]*ptype->areaspread;
|
||||
p->org[1] = vec[0]*ptype->areaspread;
|
||||
}
|
||||
|
||||
p->vel[0] += vec[0]*veladd+crandom()*randvel;
|
||||
p->vel[1] += vec[1]*veladd+crandom()*randvel;
|
||||
// no offset or areaspread for these particles...
|
||||
p->vel[0] = vec[0]*veladd+crandom()*randvel;
|
||||
p->vel[1] = vec[1]*veladd+crandom()*randvel;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel;
|
||||
|
||||
p->org[0] += start[0];
|
||||
p->org[1] += start[1];
|
||||
p->org[2] = start[2];
|
||||
break;
|
||||
case SM_SPIRAL:
|
||||
VectorCopy(start, p->org);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(ptype->spawnmode)
|
||||
{
|
||||
float tsin, tcos;
|
||||
case SM_TRACER:
|
||||
if (tcount & 1)
|
||||
{
|
||||
p->vel[0] = vec[1]*ptype->offsetspread;
|
||||
p->vel[1] = -vec[0]*ptype->offsetspread;
|
||||
p->org[0] = vec[1]*ptype->areaspread;
|
||||
p->org[1] = -vec[0]*ptype->areaspread;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->vel[0] = -vec[1]*ptype->offsetspread;
|
||||
p->vel[1] = vec[0]*ptype->offsetspread;
|
||||
p->org[0] = -vec[1]*ptype->areaspread;
|
||||
p->org[1] = vec[0]*ptype->areaspread;
|
||||
}
|
||||
|
||||
tcos = cos(len*tdegree)*ptype->areaspread;
|
||||
tsin = sin(len*tdegree)*ptype->areaspread;
|
||||
p->vel[0] += vec[0]*veladd+crandom()*randvel;
|
||||
p->vel[1] += vec[1]*veladd+crandom()*randvel;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel;
|
||||
|
||||
p->org[0] = start[0] + right[0]*tcos + up[0]*tsin;
|
||||
p->org[1] = start[1] + right[1]*tcos + up[1]*tsin;
|
||||
p->org[2] = start[2] + right[2]*tcos + up[2]*tsin;
|
||||
p->org[0] += start[0];
|
||||
p->org[1] += start[1];
|
||||
p->org[2] = start[2];
|
||||
break;
|
||||
case SM_SPIRAL:
|
||||
{
|
||||
float tsin, tcos;
|
||||
|
||||
tcos = cos(len*tdegree)*ptype->offsetspread;
|
||||
tsin = sin(len*tdegree)*ptype->offsetspread;
|
||||
tcos = cos(len*tdegree)*ptype->areaspread;
|
||||
tsin = sin(len*tdegree)*ptype->areaspread;
|
||||
|
||||
p->vel[0] = vec[0]*veladd+crandom()*randvel + right[0]*tcos + up[0]*tsin;
|
||||
p->vel[1] = vec[1]*veladd+crandom()*randvel + right[1]*tcos + up[1]*tsin;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel + right[2]*tcos + up[2]*tsin;
|
||||
p->org[0] = start[0] + right[0]*tcos + up[0]*tsin;
|
||||
p->org[1] = start[1] + right[1]*tcos + up[1]*tsin;
|
||||
p->org[2] = start[2] + right[2]*tcos + up[2]*tsin;
|
||||
|
||||
tcos = cos(len*tdegree)*ptype->offsetspread;
|
||||
tsin = sin(len*tdegree)*ptype->offsetspread;
|
||||
|
||||
p->vel[0] = vec[0]*veladd+crandom()*randvel + right[0]*tcos + up[0]*tsin;
|
||||
p->vel[1] = vec[1]*veladd+crandom()*randvel + right[1]*tcos + up[1]*tsin;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel + right[2]*tcos + up[2]*tsin;
|
||||
}
|
||||
break;
|
||||
// TODO: directionalize SM_BALL/SM_CIRCLE/SM_DISTBALL
|
||||
case SM_BALL:
|
||||
case SM_CIRCLE:
|
||||
p->org[0] = crandom();
|
||||
p->org[1] = crandom();
|
||||
p->org[2] = crandom();
|
||||
VectorNormalize(p->org);
|
||||
if (ptype->spawnmode != SM_CIRCLE)
|
||||
VectorScale(p->org, frandom(), p->org);
|
||||
|
||||
p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread;
|
||||
p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel + p->org[2]*ptype->offsetspreadvert;
|
||||
|
||||
p->org[0] = p->org[0]*ptype->areaspread + start[0];
|
||||
p->org[1] = p->org[1]*ptype->areaspread + start[1];
|
||||
p->org[2] = p->org[2]*ptype->areaspreadvert + start[2];
|
||||
break;
|
||||
case SM_DISTBALL:
|
||||
{
|
||||
float rdist;
|
||||
|
||||
rdist = ptype->spawnparam2 - crandom()*(1-(crandom() * ptype->spawnparam1));
|
||||
|
||||
// this is a strange spawntype, which is based on the fact that
|
||||
// crandom()*crandom() provides something similar to an exponential
|
||||
// probability curve
|
||||
p->org[0] = crandom();
|
||||
p->org[1] = crandom();
|
||||
p->org[2] = crandom();
|
||||
|
||||
VectorNormalize(p->org);
|
||||
VectorScale(p->org, rdist, p->org);
|
||||
|
||||
p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread;
|
||||
p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel + p->org[2]*ptype->offsetspreadvert;
|
||||
|
||||
p->org[0] = p->org[0]*ptype->areaspread + start[0];
|
||||
p->org[1] = p->org[1]*ptype->areaspread + start[1];
|
||||
p->org[2] = p->org[2]*ptype->areaspreadvert + start[2];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
p->org[0] = crandom();
|
||||
p->org[1] = crandom();
|
||||
p->org[2] = crandom();
|
||||
|
||||
p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread;
|
||||
p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel + p->org[2]*ptype->offsetspreadvert;
|
||||
|
||||
p->org[0] = p->org[0]*ptype->areaspread + start[0];
|
||||
p->org[1] = p->org[1]*ptype->areaspread + start[1];
|
||||
p->org[2] = p->org[2]*ptype->areaspreadvert + start[2];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
p->org[0] = crandom();
|
||||
p->org[1] = crandom();
|
||||
p->org[2] = crandom();
|
||||
|
||||
p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread;
|
||||
p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread;
|
||||
p->vel[2] = vec[2]*veladd+crandom()*randvel + p->org[2]*ptype->offsetspreadvert;
|
||||
|
||||
p->org[0] = p->org[0]*ptype->areaspread + start[0];
|
||||
p->org[1] = p->org[1]*ptype->areaspread + start[1];
|
||||
p->org[2] = p->org[2]*ptype->areaspreadvert + start[2];
|
||||
break;
|
||||
}
|
||||
|
||||
VectorAdd (start, vstep, start);
|
||||
|
|
Loading…
Reference in a new issue