968 lines
23 KiB
C
968 lines
23 KiB
C
// FX Library
|
|
|
|
#include "cg_local.h"
|
|
|
|
void FXE_Spray (vec3_t direction, float speed, float variation, float cone, vec3_t velocity)
|
|
{
|
|
vec3_t dir;
|
|
int i;
|
|
|
|
//Randomize the direction
|
|
for (i = 0; i < 3; i ++ )
|
|
{
|
|
dir[i] = direction[i] + (cone * crandom());
|
|
}
|
|
|
|
VectorNormalize(dir);
|
|
|
|
//set the speed
|
|
VectorScale( dir, speed + (variation * crandom()), velocity);
|
|
}
|
|
|
|
|
|
|
|
localEntity_t *FX_AddLine(vec3_t start, vec3_t end, float stScale, float scale, float dscale, float startalpha, float endalpha, float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddLine: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_LINE;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
le->data.line.width = scale;
|
|
le->data.line.dwidth = dscale;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
|
|
le->refEntity.data.line.stscale = stScale;
|
|
le->refEntity.data.line.width = scale;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( start, le->refEntity.origin);
|
|
VectorCopy ( end, le->refEntity.oldorigin );
|
|
|
|
AxisClear(le->refEntity.axis);
|
|
le->refEntity.shaderRGBA[0] = 0xff;
|
|
le->refEntity.shaderRGBA[1] = 0xff;
|
|
le->refEntity.shaderRGBA[2] = 0xff;
|
|
le->refEntity.shaderRGBA[3] = 0xff;
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = 1.0;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
return(le);
|
|
}
|
|
|
|
|
|
|
|
localEntity_t *FX_AddLine2(vec3_t start, vec3_t end, float stScale, float width1, float dwidth1, float width2, float dwidth2,
|
|
float startalpha, float endalpha, vec3_t startRGB, vec3_t endRGB, float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddLine2: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_LINE2;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
le->data.line2.width = width1;
|
|
le->data.line2.dwidth = dwidth1;
|
|
le->data.line2.width2 = width2;
|
|
le->data.line2.dwidth2 = dwidth2;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
VectorCopy(startRGB, le->data.line2.startRGB);
|
|
VectorSubtract(endRGB, startRGB, le->data.line2.dRGB);
|
|
|
|
le->refEntity.data.line.stscale = stScale;
|
|
le->refEntity.data.line.width = width1;
|
|
le->refEntity.data.line.width2 = width2;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( start, le->refEntity.origin);
|
|
VectorCopy ( end, le->refEntity.oldorigin );
|
|
|
|
AxisClear(le->refEntity.axis);
|
|
le->refEntity.shaderRGBA[0] = 0xff;
|
|
le->refEntity.shaderRGBA[1] = 0xff;
|
|
le->refEntity.shaderRGBA[2] = 0xff;
|
|
le->refEntity.shaderRGBA[3] = 0xff;
|
|
|
|
le->color[0] = startRGB[0];
|
|
le->color[1] = startRGB[1];
|
|
le->color[2] = startRGB[2];
|
|
le->color[3] = startalpha;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
return(le);
|
|
}
|
|
|
|
localEntity_t *FX_AddOrientedLine(vec3_t start, vec3_t end, vec3_t normal, float stScale, float scale,
|
|
float dscale, float startalpha, float endalpha, float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddLine: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_OLINE;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
le->data.line.width = scale;
|
|
le->data.line.dwidth = dscale;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
|
|
le->refEntity.data.line.stscale = stScale;
|
|
le->refEntity.data.line.width = scale;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( start, le->refEntity.origin);
|
|
VectorCopy ( end, le->refEntity.oldorigin );
|
|
|
|
AxisClear(le->refEntity.axis);
|
|
VectorCopy( normal, le->refEntity.axis[0] );
|
|
RotateAroundDirection( le->refEntity.axis, 0); // le->refEntity.data.sprite.rotation ); This is roll in quad land
|
|
|
|
le->refEntity.shaderRGBA[0] = 0xff;
|
|
le->refEntity.shaderRGBA[1] = 0xff;
|
|
le->refEntity.shaderRGBA[2] = 0xff;
|
|
le->refEntity.shaderRGBA[3] = 0xff;
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = 1.0;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
return(le);
|
|
}
|
|
|
|
localEntity_t *FX_AddTrail( vec3_t origin, vec3_t velocity, qboolean gravity, float length, float dlength,
|
|
float scale, float dscale, float startalpha, float endalpha,
|
|
float elasticity, float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddTrail: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_TRAIL;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.trail.width = scale;
|
|
le->data.trail.dwidth = dscale;
|
|
le->data.trail.length = length;
|
|
le->data.trail.dlength = dlength;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
VectorSet(le->data.trail.startRGB, 1, 1, 1);
|
|
VectorSet(le->data.trail.dRGB, 0, 0, 0);
|
|
|
|
le->refEntity.data.line.stscale = 1.0;
|
|
le->refEntity.data.line.width = scale;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
// kef -- extrapolate oldorigin based on length of trail and origin?
|
|
if (velocity)
|
|
{
|
|
vec3_t vel;
|
|
VectorNormalize2(velocity, vel);
|
|
VectorMA(origin, -length, vel, le->refEntity.oldorigin);
|
|
}
|
|
else
|
|
{
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
}
|
|
|
|
AxisClear(le->refEntity.axis);
|
|
le->refEntity.shaderRGBA[0] = 0xff;
|
|
le->refEntity.shaderRGBA[1] = 0xff;
|
|
le->refEntity.shaderRGBA[2] = 0xff;
|
|
le->refEntity.shaderRGBA[3] = 0xff*startalpha;
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = 1.0;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
if (velocity)
|
|
{
|
|
le->leFlags |= LEF_MOVE;
|
|
VectorCopy (origin, le->pos.trBase);
|
|
VectorCopy (velocity, le->pos.trDelta);
|
|
if (gravity)
|
|
le->pos.trType = TR_GRAVITY;
|
|
else
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
le->pos.trDuration = killTime;
|
|
|
|
if (elasticity > 0)
|
|
{
|
|
le->leFlags |= LEF_USE_COLLISION;
|
|
le->bounceFactor = elasticity;
|
|
}
|
|
}
|
|
|
|
return(le);
|
|
}
|
|
|
|
|
|
|
|
localEntity_t *FX_AddTrail2( vec3_t origin, vec3_t velocity, qboolean gravity, float length, float dlength,
|
|
float scale, float dscale, float startalpha, float endalpha, vec3_t startRGB, vec3_t endRGB,
|
|
float elasticity, float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddTrail: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_TRAIL;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.trail.width = scale;
|
|
le->data.trail.dwidth = dscale;
|
|
le->data.trail.length = length;
|
|
le->data.trail.dlength = dlength;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
VectorCopy(startRGB, le->data.trail.startRGB);
|
|
VectorSubtract(endRGB, startRGB, le->data.trail.dRGB);
|
|
|
|
le->refEntity.data.line.stscale = 1.0;
|
|
le->refEntity.data.line.width = scale;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
// kef -- extrapolate oldorigin based on length of trail and origin?
|
|
if (velocity)
|
|
{
|
|
vec3_t vel;
|
|
VectorNormalize2(velocity, vel);
|
|
VectorMA(origin, -length, vel, le->refEntity.oldorigin);
|
|
}
|
|
else
|
|
{
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
}
|
|
|
|
AxisClear(le->refEntity.axis);
|
|
le->refEntity.shaderRGBA[0] = 0xff*startRGB[0];
|
|
le->refEntity.shaderRGBA[1] = 0xff*startRGB[1];
|
|
le->refEntity.shaderRGBA[2] = 0xff*startRGB[2];
|
|
le->refEntity.shaderRGBA[3] = 0xff*startalpha;
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = 1.0;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
if (velocity)
|
|
{
|
|
le->leFlags |= LEF_MOVE;
|
|
VectorCopy (origin, le->pos.trBase);
|
|
VectorCopy (velocity, le->pos.trDelta);
|
|
if (gravity)
|
|
le->pos.trType = TR_GRAVITY;
|
|
else
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
le->pos.trDuration = killTime;
|
|
|
|
if (elasticity > 0)
|
|
{
|
|
le->leFlags |= LEF_USE_COLLISION;
|
|
le->bounceFactor = elasticity;
|
|
}
|
|
}
|
|
|
|
return(le);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
FX_AddSprite
|
|
|
|
Adds a view oriented sprite to the FX wrapper render list
|
|
===============
|
|
*/
|
|
|
|
localEntity_t *FX_AddSprite(vec3_t origin, vec3_t velocity, qboolean gravity, float scale, float dscale,
|
|
float startalpha, float endalpha, float roll, float elasticity,
|
|
float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddSprite: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
// Glow mark
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_VIEWSPRITE;
|
|
le->refEntity.data.sprite.rotation = roll;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.sprite.radius = scale;
|
|
le->data.sprite.dradius = dscale;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
VectorSet(le->data.sprite.startRGB, 1, 1, 1);
|
|
VectorSet(le->data.sprite.dRGB, 0, 0, 0);
|
|
|
|
// le->refEntity.hModel = 0;
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = startalpha;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
if (velocity)
|
|
{
|
|
le->leFlags |= LEF_MOVE;
|
|
VectorCopy (origin, le->pos.trBase);
|
|
VectorCopy (velocity, le->pos.trDelta);
|
|
if (gravity)
|
|
le->pos.trType = TR_GRAVITY;
|
|
else
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
le->pos.trDuration = killTime;
|
|
|
|
if (elasticity > 0)
|
|
{
|
|
le->leFlags |= LEF_USE_COLLISION;
|
|
le->bounceFactor = elasticity;
|
|
}
|
|
}
|
|
|
|
return(le);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
FX_AddSprite2
|
|
|
|
Adds a view oriented sprite to the FX wrapper render list
|
|
===============
|
|
*/
|
|
|
|
localEntity_t *FX_AddSprite2(vec3_t origin, vec3_t velocity, qboolean gravity, float scale, float dscale,
|
|
float startalpha, float endalpha, vec3_t startRGB, vec3_t endRGB, float roll, float elasticity,
|
|
float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddSprite: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
// Glow mark
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_VIEWSPRITE;
|
|
le->refEntity.data.sprite.rotation = roll;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.sprite.radius = scale;
|
|
le->data.sprite.dradius = dscale;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
VectorCopy(startRGB, le->data.sprite.startRGB);
|
|
VectorSubtract(endRGB, startRGB, le->data.sprite.dRGB);
|
|
|
|
// le->refEntity.hModel = 0;
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
|
|
le->color[0] = startRGB[0];
|
|
le->color[1] = startRGB[1];
|
|
le->color[2] = startRGB[2];
|
|
le->color[3] = startalpha;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
if (velocity)
|
|
{
|
|
le->leFlags |= LEF_MOVE;
|
|
VectorCopy (origin, le->pos.trBase);
|
|
VectorCopy (velocity, le->pos.trDelta);
|
|
if (gravity)
|
|
le->pos.trType = TR_GRAVITY;
|
|
else
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
le->pos.trDuration = killTime;
|
|
|
|
if (elasticity > 0)
|
|
{
|
|
le->leFlags |= LEF_USE_COLLISION;
|
|
le->bounceFactor = elasticity;
|
|
}
|
|
}
|
|
|
|
return(le);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
FX_AddBezier
|
|
|
|
Adds a Bezier curve to the FX wrapper render list
|
|
===============
|
|
*/
|
|
|
|
localEntity_t *FX_AddBezier(vec3_t start, vec3_t end, vec3_t cpoint1, vec3_t cpoint2, vec3_t cpointvel1, vec3_t cpointvel2,
|
|
vec3_t cpointacc1, vec3_t cpointacc2, float width, float killTime, qhandle_t shader)
|
|
{
|
|
localEntity_t *le = CG_AllocLocalEntity();
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddBezier: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
// just testing beziers
|
|
le->leType = LE_BEZIER;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
le->data.line.width = width;
|
|
|
|
le->alpha = 1.0;
|
|
le->dalpha = -1.0;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( start, le->refEntity.origin);
|
|
VectorCopy ( end, le->refEntity.oldorigin );
|
|
|
|
AxisClear(le->refEntity.axis);
|
|
le->refEntity.shaderRGBA[0] = 0xff;
|
|
le->refEntity.shaderRGBA[1] = 0xff;
|
|
le->refEntity.shaderRGBA[2] = 0xff;
|
|
le->refEntity.shaderRGBA[3] = 0xff;
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = 1.0;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
if (cpoint1)
|
|
{
|
|
VectorCopy(cpoint1, le->data.line.control1);
|
|
}
|
|
if (cpoint2)
|
|
{
|
|
VectorCopy(cpoint2, le->data.line.control2);
|
|
}
|
|
if (cpointvel1)
|
|
{
|
|
VectorCopy(cpointvel1, le->data.line.control1_velocity);
|
|
}
|
|
if (cpointvel2)
|
|
{
|
|
VectorCopy(cpointvel2, le->data.line.control2_velocity);
|
|
}
|
|
if (cpointacc1)
|
|
{
|
|
VectorCopy(cpointacc1, le->data.line.control1_acceleration);
|
|
}
|
|
if (cpointacc2)
|
|
{
|
|
VectorCopy(cpointacc2, le->data.line.control2_acceleration);
|
|
}
|
|
|
|
return le;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
FX_AddQuad
|
|
|
|
Adds a quad to the FX wrapper render list
|
|
===============
|
|
*/
|
|
|
|
localEntity_t *FX_AddQuad( vec3_t origin, vec3_t normal, float scale, float dscale,
|
|
float startalpha, float endalpha, float roll, float killTime, qhandle_t shader )
|
|
{
|
|
localEntity_t *le = CG_AllocLocalEntity();
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddQuad: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le->leType = LE_QUAD;
|
|
le->refEntity.data.sprite.rotation = roll;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.sprite.radius = scale;
|
|
le->data.sprite.dradius = dscale;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
VectorSet(le->data.sprite.startRGB, 1, 1, 1);
|
|
VectorSet(le->data.sprite.dRGB, 0, 0, 0);
|
|
|
|
// le->refEntity.hModel = 0;
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
|
|
VectorCopy( normal, le->refEntity.axis[0] );
|
|
RotateAroundDirection( le->refEntity.axis, le->refEntity.data.sprite.rotation );
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = startalpha;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
return(le);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
FX_AddQuad2
|
|
|
|
Adds a quad to the FX wrapper render list
|
|
===============
|
|
*/
|
|
|
|
localEntity_t *FX_AddQuad2( vec3_t origin, vec3_t normal, float scale, float dscale, float startalpha, float endalpha,
|
|
vec3_t startRGB, vec3_t endRGB, float roll, float killTime, qhandle_t shader )
|
|
{
|
|
localEntity_t *le = CG_AllocLocalEntity();
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddQuad: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le->leType = LE_QUAD;
|
|
le->refEntity.data.sprite.rotation = roll;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.sprite.radius = scale;
|
|
le->data.sprite.dradius = dscale;
|
|
VectorCopy(startRGB, le->data.sprite.startRGB);
|
|
VectorSubtract(endRGB, startRGB, le->data.sprite.dRGB);
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
|
|
// le->refEntity.hModel = 0;
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
|
|
VectorCopy( normal, le->refEntity.axis[0] );
|
|
RotateAroundDirection( le->refEntity.axis, le->refEntity.data.sprite.rotation );
|
|
|
|
le->color[0] = startRGB[0];
|
|
le->color[1] = startRGB[1];
|
|
le->color[2] = startRGB[2];
|
|
le->color[3] = startalpha;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
return(le);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
FX_AddCylinder
|
|
|
|
Adds a cylinder to the FX wrapper render list
|
|
Overloaded for RGB
|
|
===============
|
|
*/
|
|
|
|
//NOTENOTE: The reigning king of parameters!
|
|
#define DEFAULT_ST_SCALE 1.0f
|
|
|
|
localEntity_t *FX_AddCylinder( vec3_t start,
|
|
vec3_t normal,
|
|
float height,
|
|
float dheight,
|
|
float scale,
|
|
float dscale,
|
|
float scale2,
|
|
float dscale2,
|
|
float startalpha,
|
|
float endalpha,
|
|
float killTime,
|
|
qhandle_t shader,
|
|
float bias )
|
|
{
|
|
localEntity_t *le = CG_AllocLocalEntity();
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddCylinder: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le->leType = LE_CYLINDER;
|
|
le->refEntity.data.cylinder.height = height;
|
|
le->refEntity.data.cylinder.width = scale;
|
|
le->refEntity.data.cylinder.width2 = scale2;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.cylinder.height = height;
|
|
le->data.cylinder.dheight = dheight;
|
|
le->data.cylinder.width = scale;
|
|
le->data.cylinder.dwidth = dscale;
|
|
le->data.cylinder.width2 = scale2;
|
|
le->data.cylinder.dwidth2 = dscale2;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
le->refEntity.data.cylinder.bias = bias;
|
|
le->refEntity.data.cylinder.stscale = 1.0;
|
|
le->refEntity.data.cylinder.wrap = qtrue;
|
|
|
|
// set origin
|
|
VectorCopy ( start, le->refEntity.origin);
|
|
VectorCopy ( start, le->refEntity.oldorigin );
|
|
|
|
VectorCopy( normal, le->refEntity.axis[0] );
|
|
RotateAroundDirection( le->refEntity.axis, 0);
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = startalpha;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
return(le);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
FX_AddElectricity
|
|
|
|
Adds a electricity bolt to the scene
|
|
===============
|
|
*/
|
|
|
|
localEntity_t *FX_AddElectricity( vec3_t origin, vec3_t origin2, float stScale, float scale, float dscale,
|
|
float startalpha, float endalpha, float killTime, qhandle_t shader, float deviation )
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddElectricity: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_ELECTRICITY;
|
|
|
|
// set origin
|
|
VectorCopy (origin, le->refEntity.origin);
|
|
VectorCopy (origin2, le->refEntity.oldorigin );
|
|
|
|
le->refEntity.data.electricity.stscale = stScale;
|
|
le->refEntity.data.electricity.deviation = deviation;
|
|
le->data.electricity.width = scale;
|
|
le->data.electricity.dwidth = dscale;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->refEntity.customShader = shader;
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = startalpha;
|
|
|
|
return(le);
|
|
}
|
|
/*
|
|
===============
|
|
FX_AddParticle
|
|
|
|
Adds a particle (basically, a sprite with an optional think function) to the FX wrapper render list
|
|
===============
|
|
*/
|
|
|
|
localEntity_t *FX_AddParticle( vec3_t origin, vec3_t velocity, qboolean gravity, float scale, float dscale,
|
|
float startalpha, float endalpha, float roll, float elasticity,
|
|
float killTime, qhandle_t shader, qboolean (*thinkFn)(localEntity_t *le) )
|
|
{
|
|
localEntity_t *le;
|
|
|
|
#ifdef _DEBUG
|
|
if (!shader)
|
|
{
|
|
Com_Printf("FX_AddParticle: NULL shader\n");
|
|
}
|
|
#endif
|
|
|
|
// Glow mark
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leType = LE_PARTICLE;
|
|
le->refEntity.data.sprite.rotation = roll;
|
|
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + killTime;
|
|
|
|
le->data.particle.radius = scale;
|
|
le->data.particle.dradius = dscale;
|
|
|
|
le->alpha = startalpha;
|
|
le->dalpha = endalpha - startalpha;
|
|
|
|
// le->refEntity.hModel = 0;
|
|
le->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = startalpha;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
// wacky think function stuff
|
|
le->data.particle.thinkFn = thinkFn;
|
|
|
|
if (velocity)
|
|
{
|
|
le->leFlags |= LEF_MOVE;
|
|
VectorCopy (origin, le->pos.trBase);
|
|
VectorCopy (velocity, le->pos.trDelta);
|
|
if (gravity)
|
|
le->pos.trType = TR_GRAVITY;
|
|
else
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
le->pos.trDuration = killTime;
|
|
|
|
if (elasticity > 0)
|
|
{
|
|
le->leFlags |= LEF_USE_COLLISION;
|
|
le->bounceFactor = elasticity;
|
|
}
|
|
}
|
|
|
|
return(le);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
FX_AddSpawner
|
|
|
|
Adds a spawner -- basically, a local entity with a think function. Spawners don't have any rendered entities
|
|
associated with them inherently, but the spawner's think fn probably generates them.
|
|
===============
|
|
*/
|
|
localEntity_t *FX_AddSpawner( vec3_t origin, vec3_t dir, vec3_t velocity, vec3_t user, qboolean gravity, int delay,
|
|
float variance, float killTime, qboolean (*thinkFn)(localEntity_t *le), int radius )
|
|
{
|
|
localEntity_t *le = NULL;
|
|
|
|
if (NULL == thinkFn)
|
|
{
|
|
// a spawner with no think fn is silly. and useless.
|
|
return NULL;
|
|
}
|
|
le = CG_AllocLocalEntity();
|
|
|
|
le->leType = LE_SPAWNER;
|
|
|
|
le->data.spawner.data1 = radius;
|
|
le->data.spawner.delay = delay;
|
|
le->data.spawner.nextthink = cg.time + delay;
|
|
le->startTime = cg.time;
|
|
// if we want the spawner to hang around forever, we use a killtime of 0 and the think fn keeps adjusting it.
|
|
//thing is, we still need it to not get culled right here, so give it an arbitrary endTime somewhere in the future.
|
|
if (0 == killTime)
|
|
{
|
|
le->endTime = le->startTime + 10000;
|
|
le->data.spawner.dontDie = qtrue;
|
|
}
|
|
else
|
|
{
|
|
le->endTime = le->startTime + killTime;
|
|
}
|
|
|
|
le->data.spawner.variance = variance;
|
|
VectorCopy(dir, le->data.spawner.dir);
|
|
// set origin
|
|
VectorCopy ( origin, le->refEntity.origin);
|
|
VectorCopy ( origin, le->refEntity.oldorigin );
|
|
|
|
// maybe employ the user variable here, like in singleplayer? or in the think fn?
|
|
le->color[0] = 1.0;
|
|
le->color[1] = 1.0;
|
|
le->color[2] = 1.0;
|
|
le->color[3] = 1.0;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
// wacky think function stuff
|
|
le->data.spawner.thinkFn = thinkFn;
|
|
|
|
if (velocity)
|
|
{
|
|
le->leFlags |= LEF_MOVE;
|
|
VectorCopy (origin, le->pos.trBase);
|
|
VectorCopy (velocity, le->pos.trDelta);
|
|
if (gravity)
|
|
le->pos.trType = TR_GRAVITY;
|
|
else
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
// we better not ever have a spawner with a velocity that we expect to last forever, so just plain
|
|
//assigning killTime here _should_ be ok
|
|
le->pos.trDuration = killTime;
|
|
|
|
// if (elasticity > 0)
|
|
// {
|
|
// le->leFlags |= LEF_USE_COLLISION;
|
|
// le->bounceFactor = elasticity;
|
|
// }
|
|
}
|
|
|
|
return (le);
|
|
}
|
|
|
|
// provide the center of the circle, a normal out from it (normalized, please), and the radius.
|
|
//out will then become a random position on the radius of the circle.
|
|
void fxRandCircumferencePos(vec3_t center, vec3_t normal, float radius, vec3_t out)
|
|
{
|
|
float rnd = flrandom(0, 2*M_PI);
|
|
float s = sin(rnd);
|
|
float c = cos(rnd);
|
|
vec3_t vTemp, radialX, radialY;
|
|
|
|
vTemp[0]=0.57735;
|
|
vTemp[1]=0.57735;
|
|
vTemp[2]=0.57735;
|
|
CrossProduct(normal, vTemp, radialX);
|
|
CrossProduct(normal, radialX, radialY);
|
|
VectorScale(radialX, radius, radialX);
|
|
VectorScale(radialY, radius, radialY);
|
|
VectorMA(center, s, radialX, out);
|
|
VectorMA(out, c, radialY, out);
|
|
}
|