new trailstate system
te_lightning? and similar, and trail emit is no longer fps dependent timelimit particle field added te_*_end is still frame dependent and needs a resonable fix git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1062 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
181a88c471
commit
86f3912654
7 changed files with 250 additions and 71 deletions
|
@ -1568,15 +1568,7 @@ void CL_LinkPacketEntities (void)
|
|||
}
|
||||
if (i == cl_oldnumvisedicts)
|
||||
{
|
||||
trailstate_t *t;
|
||||
t = &cl.lerpents[s1->number].trailstate;
|
||||
t->lastdist = 0;
|
||||
if (t->lastbeam)
|
||||
{
|
||||
t->lastbeam->flags &= ~BS_LASTSEG;
|
||||
t->lastbeam->flags |= BS_NODRAW;
|
||||
}
|
||||
t->lastbeam = NULL;
|
||||
P_DelinkTrailstate(&(cl.lerpents[s1->number].trailstate));
|
||||
continue; // not in last message
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ typedef struct
|
|||
float alpha;
|
||||
vec3_t start, end;
|
||||
int particleeffect;
|
||||
trailstate_t *trailstate;
|
||||
} beam_t;
|
||||
|
||||
beam_t cl_beams[MAX_BEAMS];
|
||||
|
@ -1978,8 +1979,15 @@ void CL_UpdateBeams (void)
|
|||
// update lightning
|
||||
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
|
||||
{
|
||||
if (!b->model || b->endtime < cl.time)
|
||||
if (!b->model)
|
||||
continue;
|
||||
|
||||
if (b->endtime < cl.time)
|
||||
{
|
||||
P_DelinkTrailstate(&b->trailstate);
|
||||
b->model = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if coming from the player, update the start position
|
||||
if (b->flags & 1 && b->entity == (autocam[0]?spec_track[0]:(cl.playernum[0]+1))) // entity 0 is the world
|
||||
|
@ -2059,7 +2067,7 @@ void CL_UpdateBeams (void)
|
|||
// if (part_type[rt_lightning1].loaded)
|
||||
// if (!P_ParticleTrail(b->start, b->end, rt_lightning1, NULL))
|
||||
// continue;
|
||||
if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, NULL))
|
||||
if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, &b->trailstate))
|
||||
continue;
|
||||
|
||||
// add new entities for the lightning
|
||||
|
|
|
@ -389,7 +389,7 @@ typedef struct {
|
|||
float lerprate; //inverse rate...
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
trailstate_t trailstate; //when to next throw out a trail
|
||||
trailstate_t *trailstate; //when to next throw out a trail
|
||||
unsigned short frame;
|
||||
unsigned short tagent;
|
||||
unsigned short tagindex;
|
||||
|
|
|
@ -86,7 +86,7 @@ typedef struct q2centity_s
|
|||
|
||||
int serverframe; // if not current, this ent isn't in the frame
|
||||
|
||||
trailstate_t trailstate;
|
||||
trailstate_t *trailstate;
|
||||
// float trailcount; // for diminishing grenade trails
|
||||
vec3_t lerp_origin; // for trails (variable hz)
|
||||
|
||||
|
@ -823,7 +823,9 @@ void CLQ2_DeltaEntity (q2frame_t *frame, int newnum, entity_state_t *old, int bi
|
|||
|
||||
if (ent->serverframe != cl.q2frame.serverframe - 1)
|
||||
{ // wasn't in last update, so initialize some things
|
||||
ent->trailstate.lastdist = 0; // for diminishing rocket / grenade trails
|
||||
// clear trailstate
|
||||
P_DelinkTrailstate(&ent->trailstate);
|
||||
|
||||
// duplicate the current state so lerping doesn't hurt anything
|
||||
ent->prev = *state;
|
||||
if (state->event == Q2EV_OTHER_TELEPORT)
|
||||
|
|
|
@ -87,10 +87,11 @@ void D_DrawSparkTrans (particle_t *pparticle, vec3_t src, vec3_t dest);
|
|||
|
||||
void P_ReadPointFile_f (void);
|
||||
|
||||
#define MAX_BEAMS 2048 // default max # of beam segments
|
||||
#define MAX_BEAMSEGS 2048 // default max # of beam segments
|
||||
#define MAX_PARTICLES 32768 // default max # of particles at one
|
||||
// time
|
||||
#define MAX_DECALS 4096 // this is going to be expensive
|
||||
#define MAX_TRAILSTATES 512 // default max # of trailstates
|
||||
|
||||
//int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
|
||||
//int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
|
||||
|
@ -108,6 +109,10 @@ clippeddecal_t *free_decals;
|
|||
clippeddecal_t *decals;
|
||||
int r_numdecals;
|
||||
|
||||
trailstate_t *trailstates;
|
||||
int ts_cycle; // current cyclic index of trailstates
|
||||
int r_numtrailstates;
|
||||
|
||||
vec3_t r_pright, r_pup, r_ppn;
|
||||
|
||||
extern cvar_t r_bouncysparks;
|
||||
|
@ -163,6 +168,9 @@ typedef struct part_type_s {
|
|||
float offsetspreadvert;
|
||||
float randomvelvert;
|
||||
float randscale;
|
||||
|
||||
float timelimit;
|
||||
|
||||
enum {PT_NORMAL, PT_BEAM, PT_DECAL} type;
|
||||
enum {BM_MERGE, BM_ADD, BM_SUBTRACT} blendmode;
|
||||
|
||||
|
@ -661,6 +669,8 @@ void P_ParticleEffect_f(void)
|
|||
Con_DPrintf("isbeam is deprechiated, use type beam\n");
|
||||
ptype->type = PT_BEAM;
|
||||
}
|
||||
else if (!strcmp(var, "timelimit"))
|
||||
ptype->timelimit = atof(value);
|
||||
else if (!strcmp(var, "cliptype"))
|
||||
{
|
||||
assoc = P_ParticleTypeForName(value);//careful - this can realloc all the particle types
|
||||
|
@ -1086,18 +1096,24 @@ void P_InitParticles (void)
|
|||
r_numparticles = MAX_PARTICLES;
|
||||
}
|
||||
|
||||
r_numbeams = MAX_BEAMS;
|
||||
r_numbeams = MAX_BEAMSEGS;
|
||||
|
||||
r_numdecals = MAX_DECALS;
|
||||
|
||||
r_numtrailstates = MAX_TRAILSTATES;
|
||||
|
||||
particles = (particle_t *)
|
||||
Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
|
||||
|
||||
beams = (beamseg_t *)
|
||||
Hunk_AllocName (r_numbeams * sizeof(beamseg_t), "beams");
|
||||
Hunk_AllocName (r_numbeams * sizeof(beamseg_t), "beamsegs");
|
||||
|
||||
decals = (clippeddecal_t *)
|
||||
Hunk_AllocName (r_numdecals * sizeof(clippeddecal_t), "decals");
|
||||
|
||||
trailstates = (trailstate_t *)
|
||||
Hunk_AllocName (r_numtrailstates * sizeof(trailstate_t), "trailstates");
|
||||
ts_cycle = 0;
|
||||
|
||||
Cmd_AddCommand("pointfile", P_ReadPointFile_f); //load the leak info produced from qbsp into the particle system to show a line. :)
|
||||
|
||||
|
@ -1898,6 +1914,8 @@ int P_RunParticleEffectType (vec3_t org, vec3_t dir, float count, int typenum)
|
|||
p->alpha = ptype->alpha;
|
||||
p->color = 0;
|
||||
p->nextemit = particletime + ptype->emitstart - p->die;
|
||||
if (ptype->emittime < 0)
|
||||
p->trailstate = NULL;
|
||||
|
||||
p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand;
|
||||
p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand;
|
||||
|
@ -2296,15 +2314,81 @@ void CLQ2_RailTrail (vec3_t start, vec3_t end)
|
|||
P_ParticleTrail(start, end, rt_railtrail, NULL);
|
||||
}
|
||||
|
||||
int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
|
||||
// Trailstate functions
|
||||
void P_CleanTrailstate(trailstate_t *ts)
|
||||
{
|
||||
vec3_t vec, right, up, start;
|
||||
// clear LASTSEG flag from lastbeam so it can be reused
|
||||
if (ts->lastbeam)
|
||||
{
|
||||
ts->lastbeam->flags &= ~BS_LASTSEG;
|
||||
ts->lastbeam->flags |= BS_NODRAW;
|
||||
}
|
||||
|
||||
// clean structure
|
||||
memset(ts, 0, sizeof(trailstate_t));
|
||||
}
|
||||
|
||||
void P_DelinkTrailstate(trailstate_t **tsk)
|
||||
{
|
||||
trailstate_t *ts;
|
||||
trailstate_t *assoc;
|
||||
|
||||
if (*tsk == NULL)
|
||||
return; // not linked to a trailstate
|
||||
|
||||
ts = *tsk;
|
||||
|
||||
if (ts->key != tsk)
|
||||
return; // prevent overwrite
|
||||
|
||||
assoc = ts->assoc; // store assoc
|
||||
P_CleanTrailstate(ts); // clean directly linked trailstate
|
||||
|
||||
// clean trailstates assoc linked
|
||||
while (assoc)
|
||||
{
|
||||
ts = assoc->assoc;
|
||||
P_CleanTrailstate(assoc);
|
||||
assoc = ts;
|
||||
}
|
||||
|
||||
*tsk = NULL; // erase pointer
|
||||
}
|
||||
|
||||
trailstate_t *P_NewTrailstate(trailstate_t **key)
|
||||
{
|
||||
trailstate_t *ts;
|
||||
|
||||
// bounds check here in case r_numtrailstates changed
|
||||
if (ts_cycle >= r_numtrailstates)
|
||||
ts_cycle = 0;
|
||||
|
||||
// get trailstate
|
||||
ts = trailstates + ts_cycle;
|
||||
|
||||
// clear trailstate
|
||||
P_CleanTrailstate(ts);
|
||||
|
||||
// set key
|
||||
ts->key = key;
|
||||
|
||||
// advance index cycle
|
||||
ts_cycle++;
|
||||
|
||||
// return clean trailstate
|
||||
return ts;
|
||||
}
|
||||
|
||||
int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk)
|
||||
{
|
||||
vec3_t vec, vstep, right, up, start;
|
||||
float len;
|
||||
int tcount;
|
||||
particle_t *p;
|
||||
part_type_t *ptype = &part_type[type];
|
||||
beamseg_t *b;
|
||||
beamseg_t *bfirst;
|
||||
trailstate_t *ts;
|
||||
|
||||
float veladd = -ptype->veladd;
|
||||
float randvel = ptype->randomvel;
|
||||
|
@ -2316,21 +2400,51 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
|
|||
return 1;
|
||||
|
||||
VectorCopy(startpos, start);
|
||||
if (ptype->assoc>=0)
|
||||
|
||||
// trailstate allocation/deallocation
|
||||
if (tsk)
|
||||
{
|
||||
VectorCopy(start, vec);
|
||||
if (ts)
|
||||
// if *tsk = NULL get a new one
|
||||
if (*tsk == NULL)
|
||||
{
|
||||
trailstate_t nts;
|
||||
memcpy(&nts, ts, sizeof(nts));
|
||||
P_ParticleTrail(vec, end, ptype->assoc, &nts);
|
||||
ts = P_NewTrailstate(tsk);
|
||||
*tsk = ts;
|
||||
}
|
||||
else
|
||||
P_ParticleTrail(vec, end, ptype->assoc, NULL);
|
||||
}
|
||||
else if (!ptype->die)
|
||||
{
|
||||
ts = *tsk;
|
||||
|
||||
if (ts->key != tsk) // trailstate was overwritten
|
||||
{
|
||||
ts = P_NewTrailstate(tsk); // so get a new one
|
||||
*tsk = ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ts = NULL;
|
||||
|
||||
if (ptype->assoc>=0)
|
||||
{
|
||||
if (ts)
|
||||
P_ParticleTrail(start, end, ptype->assoc, &(ts->assoc));
|
||||
else
|
||||
P_ParticleTrail(start, end, ptype->assoc, NULL);
|
||||
}
|
||||
|
||||
// time limit for trails
|
||||
if (ptype->timelimit && ts)
|
||||
{
|
||||
if (ts->statetime > particletime)
|
||||
return 0; // timelimit still in effect
|
||||
|
||||
ts->statetime = particletime + ptype->timelimit; // record old time
|
||||
ts = NULL; // clear trailstate so we don't save length/lastseg
|
||||
}
|
||||
|
||||
if (!ptype->die)
|
||||
ts = NULL;
|
||||
|
||||
step = 1/ptype->count;
|
||||
|
||||
if (step < 0.01)
|
||||
|
@ -2338,6 +2452,7 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
|
|||
|
||||
VectorSubtract (end, start, vec);
|
||||
len = VectorNormalize (vec);
|
||||
VectorScale(vec, step, vstep);
|
||||
|
||||
// add offset
|
||||
start[2] += ptype->offsetup;
|
||||
|
@ -2351,16 +2466,11 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
|
|||
tdegree = 2*M_PI/ptype->spawnparam1; /* distance per rotation inversed */
|
||||
}
|
||||
|
||||
// store last stop here for lack of a better solution besides vectors
|
||||
if (ts)
|
||||
{
|
||||
stop = ts->lastdist + len; //when to stop
|
||||
ts->laststop = stop = ts->laststop + len; //when to stop
|
||||
len = ts->lastdist;
|
||||
|
||||
if (!len)
|
||||
{
|
||||
len = particletime;
|
||||
stop += len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2456,6 +2566,8 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
|
|||
|
||||
VectorCopy (vec3_origin, p->vel);
|
||||
p->nextemit = particletime + ptype->emitstart - p->die;
|
||||
if (ptype->emittime < 0)
|
||||
p->trailstate = NULL; // init trailstate
|
||||
|
||||
p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand;
|
||||
p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand;
|
||||
|
@ -2520,7 +2632,7 @@ int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t *ts)
|
|||
break;
|
||||
}
|
||||
|
||||
VectorMA (start, step, vec, start);
|
||||
VectorAdd (start, vstep, start);
|
||||
|
||||
p->die = particletime + ptype->die - p->die;
|
||||
}
|
||||
|
@ -3392,6 +3504,22 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
|
|||
if (type->type == PT_NORMAL)
|
||||
RQ_AddDistReorder(pdraw, p, type, p->org);
|
||||
|
||||
// make sure emitter runs at least once
|
||||
if (type->emit >= 0 && type->emitstart <= 0)
|
||||
P_RunParticleEffectType(p->org, p->vel, 1, type->emit);
|
||||
|
||||
// make sure stain effect runs
|
||||
if (type->stains && r_bloodstains.value)
|
||||
{
|
||||
if (traces-->0&&tr(oldorg, p->org, stop, normal))
|
||||
{
|
||||
R_AddStain(stop, (p->rgb[1]*-10+p->rgb[2]*-10),
|
||||
(p->rgb[0]*-10+p->rgb[2]*-10),
|
||||
(p->rgb[0]*-10+p->rgb[1]*-10),
|
||||
30*p->alpha*type->stains);
|
||||
}
|
||||
}
|
||||
|
||||
type->particles = p->next;
|
||||
// p->next = free_particles;
|
||||
// free_particles = p;
|
||||
|
@ -3452,36 +3580,15 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
|
|||
}
|
||||
|
||||
//kill off early ones.
|
||||
for ( ;; )
|
||||
if (type->emittime < 0)
|
||||
{
|
||||
kill = type->particles;
|
||||
if (kill && kill->die < particletime)
|
||||
for ( ;; )
|
||||
{
|
||||
type->particles = kill->next;
|
||||
// kill->next = free_particles;
|
||||
// free_particles = kill;
|
||||
kill->next = kill_list;
|
||||
kill_list = kill;
|
||||
if (!kill_first)
|
||||
kill_first = kill;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
grav = type->gravity*pframetime;
|
||||
VectorScale(type->friction, pframetime, friction);
|
||||
|
||||
for (p=type->particles ; p ; p=p->next)
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
kill = p->next;
|
||||
kill = type->particles;
|
||||
if (kill && kill->die < particletime)
|
||||
{
|
||||
p->next = kill->next;
|
||||
// kill->next = free_particles;
|
||||
// free_particles = kill;
|
||||
P_DelinkTrailstate(&kill->trailstate);
|
||||
type->particles = kill->next;
|
||||
kill->next = kill_list;
|
||||
kill_list = kill;
|
||||
if (!kill_first)
|
||||
|
@ -3490,6 +3597,66 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
kill = type->particles;
|
||||
if (kill && kill->die < particletime)
|
||||
{
|
||||
type->particles = kill->next;
|
||||
kill->next = kill_list;
|
||||
kill_list = kill;
|
||||
if (!kill_first)
|
||||
kill_first = kill;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
grav = type->gravity*pframetime;
|
||||
VectorScale(type->friction, pframetime, friction);
|
||||
|
||||
for (p=type->particles ; p ; p=p->next)
|
||||
{
|
||||
if (type->emittime < 0)
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
kill = p->next;
|
||||
if (kill && kill->die < particletime)
|
||||
{
|
||||
P_DelinkTrailstate(&kill->trailstate);
|
||||
p->next = kill->next;
|
||||
kill->next = kill_list;
|
||||
kill_list = kill;
|
||||
if (!kill_first)
|
||||
kill_first = kill;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
kill = p->next;
|
||||
if (kill && kill->die < particletime)
|
||||
{
|
||||
p->next = kill->next;
|
||||
kill->next = kill_list;
|
||||
kill_list = kill;
|
||||
if (!kill_first)
|
||||
kill_first = kill;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VectorCopy(p->org, oldorg);
|
||||
if (type->flags & PT_VELOCITY)
|
||||
{
|
||||
|
@ -3535,7 +3702,7 @@ void DrawParticleTypes (void texturedparticles(particle_t *,part_type_t*), void
|
|||
if (type->emit >= 0)
|
||||
{
|
||||
if (type->emittime < 0)
|
||||
P_ParticleTrail(oldorg, p->org, type->emit, NULL);
|
||||
P_ParticleTrail(oldorg, p->org, type->emit, &p->trailstate);
|
||||
else if (p->nextemit < particletime)
|
||||
{
|
||||
p->nextemit = particletime + type->emittime + frandom()*type->emitrand;
|
||||
|
|
|
@ -279,7 +279,6 @@ void CLQ2_BfgParticles(entity_t *ent);
|
|||
struct q2centity_s;
|
||||
void CLQ2_FlyEffect(struct q2centity_s *ent, vec3_t org);
|
||||
void CLQ2_DiminishingTrail(vec3_t oldorg, vec3_t neworg, struct q2centity_s *ent, unsigned int effects);
|
||||
void CLQ2_BlasterTrail(vec3_t oldorg, vec3_t neworg);
|
||||
void CLQ2_BlasterTrail2(vec3_t oldorg, vec3_t neworg);
|
||||
|
||||
void WritePCXfile (char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit.
|
||||
|
|
|
@ -59,6 +59,19 @@ extern int rt_rocket_trail,
|
|||
rt_bubbletrail;
|
||||
*/
|
||||
|
||||
struct beamseg_s;
|
||||
|
||||
typedef struct trailstate_s {
|
||||
struct trailstate_s **key; // key to check if ts has been overwriten
|
||||
struct trailstate_s *assoc; // assoc linked trail
|
||||
struct beamseg_s *lastbeam; // last beam pointer (flagged with BS_LASTSEG)
|
||||
union {
|
||||
float lastdist; // last distance used with particle effect
|
||||
float statetime; // time to emit effect again
|
||||
};
|
||||
float laststop; // last stopping point for particle effect
|
||||
} trailstate_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
typedef struct particle_s
|
||||
{
|
||||
|
@ -74,8 +87,10 @@ typedef struct particle_s
|
|||
|
||||
vec3_t vel; //renderer uses for sparks
|
||||
float angle;
|
||||
float nextemit;
|
||||
|
||||
union {
|
||||
float nextemit;
|
||||
trailstate_t *trailstate;
|
||||
};
|
||||
// drivers never touch the following fields
|
||||
float rotationspeed;
|
||||
} particle_t;
|
||||
|
@ -146,12 +161,8 @@ void P_BlobExplosion (vec3_t org); //tarbaby explosion or TF emp.
|
|||
void P_ParticleExplosion (vec3_t org); //rocket explosion (sprite is allocated seperatly :( )
|
||||
void P_LavaSplash (vec3_t org); //cthon dying, or a gas grenade.
|
||||
|
||||
typedef struct {
|
||||
float lastdist;
|
||||
struct beamseg_s *lastbeam; // last beam point
|
||||
} trailstate_t;
|
||||
//the core spawn function for trails. (trailstate can be null)
|
||||
int P_ParticleTrail (vec3_t start, vec3_t end, int type, trailstate_t *trailstate);
|
||||
int P_ParticleTrail (vec3_t start, vec3_t end, int type, trailstate_t **trailstate);
|
||||
|
||||
void P_DefaultTrail (struct model_s *model); //fills in the default particle properties for a loaded model. Should already have the model flags set.
|
||||
|
||||
|
|
Loading…
Reference in a new issue