diff options
Diffstat (limited to 'src/cgame')
| -rw-r--r-- | src/cgame/cg_event.c | 5 | ||||
| -rw-r--r-- | src/cgame/cg_local.h | 40 | ||||
| -rw-r--r-- | src/cgame/cg_main.c | 2 | ||||
| -rw-r--r-- | src/cgame/cg_particles.c | 2013 | ||||
| -rw-r--r-- | src/cgame/cg_servercmds.c | 5 | ||||
| -rw-r--r-- | src/cgame/cg_trails.c | 728 | ||||
| -rw-r--r-- | src/cgame/cg_view.c | 4 | ||||
| -rw-r--r-- | src/cgame/cg_weapons.c | 18 | 
8 files changed, 791 insertions, 2024 deletions
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index 7ea62220..1a28c2a8 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -959,12 +959,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )    case EV_TESLATRAIL:      DEBUGNAME("EV_TESLATRAIL");      cent->currentState.weapon = WP_TESLAGEN; -    // if the end was on a nomark surface, don't make an explosion      CG_TeslaTrail( es->origin2, es->pos.trBase ); -    if ( es->eventParm != 255 ) { -      ByteToDir( es->eventParm, dir ); -      CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT, 0 ); -    }      break;    case EV_BULLET_HIT_WALL: diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index dc9af0e9..184c3830 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -72,6 +72,19 @@  #define NUM_CROSSHAIRS      10 +//TA: ripped from wolf source +// Ridah, trails +#define	STYPE_STRETCH	0 +#define	STYPE_REPEAT	1 + +#define	TJFL_FADEIN		(1<<0) +#define	TJFL_CROSSOVER	(1<<1) +#define	TJFL_NOCULL		(1<<2) +#define	TJFL_FIXDISTORT	(1<<3) +#define TJFL_SPARKHEADFLARE (1<<4) +#define	TJFL_NOPOLYMERGE	(1<<5) +// done. +  #define TEAM_OVERLAY_MAXNAME_WIDTH  12  #define TEAM_OVERLAY_MAXLOCATION_WIDTH  16 @@ -213,6 +226,7 @@ typedef struct markPoly_s {  typedef enum {    LE_MARK,    LE_EXPLOSION, +  LE_LIGHTNING_BOLT, //wolf trail    LE_SPRITE_EXPLOSION,    LE_FRAGMENT,    LE_MOVE_SCALE_FADE, @@ -1025,6 +1039,8 @@ typedef struct {    sfxHandle_t wstbimpdSound;    sfxHandle_t wstbactvSound; +  //TA: for wolf trail effects +	qhandle_t	sparkFlareShader;  } cgMedia_t; @@ -1519,6 +1535,30 @@ localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir,                  qhandle_t hModel, qhandle_t shader, int msec,                  qboolean isSprite ); +//TA: wolf tesla effect +void CG_DynamicLightningBolt( qhandle_t shader, vec3_t start, vec3_t pend, +                              int numBolts, float maxWidth, qboolean fade, +                              float startAlpha, int recursion, int randseed ); + +// Ridah, trails +// +// cg_trails.c +// +int CG_AddTrailJunc( int headJuncIndex, qhandle_t shader, int spawnTime, +                     int sType, vec3_t pos, int trailLife, float alphaStart, +                     float alphaEnd, float startWidth, float endWidth, int flags, +                     vec3_t colorStart, vec3_t colorEnd, float sRatio, float animSpeed ); +int CG_AddSparkJunc( int headJuncIndex, qhandle_t shader, vec3_t pos, int trailLife, +                     float alphaStart, float alphaEnd, float startWidth, float endWidth ); +int CG_AddSmokeJunc( int headJuncIndex, qhandle_t shader, vec3_t pos, int trailLife, +                     float alpha, float startWidth, float endWidth );  +int CG_AddFireJunc( int headJuncIndex, qhandle_t shader, vec3_t pos, int trailLife, +                    float alpha, float startWidth, float endWidth ); +void CG_AddTrails( void ); +void CG_ClearTrails( void ); +// done. + +  //  // cg_snapshot.c  // diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index 9b874dcb..1ffc578f 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -893,8 +893,6 @@ static void CG_RegisterGraphics( void ) {      }      cgs.gameShaders[i] = trap_R_RegisterShader( shaderName );    } - -  CG_ClearParticles ();  } diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c deleted file mode 100644 index 697d6a7d..00000000 --- a/src/cgame/cg_particles.c +++ /dev/null @@ -1,2013 +0,0 @@ -// Rafael particles -// cg_particles.c   - -/* - *  Portions Copyright (C) 2000-2001 Tim Angus - * - *  This program is free software; you can redistribute it and/or modify it - *  under the terms of the OSML - Open Source Modification License v1.0 as - *  described in the file COPYING which is distributed with this source - *  code. - * - *  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. - */ -                     -#include "cg_local.h" - -#define BLOODRED	2 -#define EMISIVEFADE	3 -#define GREY75		4 - -typedef struct particle_s -{ -	struct particle_s	*next; - -	float		time; -	float		endtime; - -	vec3_t		org; -	vec3_t		vel; -	vec3_t		accel; -	int			color; -	float		colorvel; -	float		alpha; -	float		alphavel; -	int			type; -	qhandle_t	pshader; -	 -	float		height; -	float		width; -				 -	float		endheight; -	float		endwidth; -	 -	float		start; -	float		end; - -	float		startfade; -	qboolean	rotate; -	int			snum; -	 -	qboolean	link; - -	// Ridah -	int			shaderAnim; -	int			roll; - -	int			accumroll; - -} cparticle_t; - -typedef enum -{ -	P_NONE, -	P_WEATHER, -	P_FLAT, -	P_SMOKE, -	P_ROTATE, -	P_WEATHER_TURBULENT, -	P_ANIM,	// Ridah -	P_BAT, -	P_BLEED, -	P_FLAT_SCALEUP, -	P_FLAT_SCALEUP_FADE, -	P_WEATHER_FLURRY, -	P_SMOKE_IMPACT, -	P_BUBBLE, -	P_BUBBLE_TURBULENT, -	P_SPRITE -} particle_type_t; - -#define	MAX_SHADER_ANIMS		32 -#define	MAX_SHADER_ANIM_FRAMES	64 - -static char *shaderAnimNames[MAX_SHADER_ANIMS] = { -	"explode1", -	"blacksmokeanim", -	"twiltb2", -	"expblue", -	"blacksmokeanimb",	// uses 'explode1' sequence -	"blood", -	NULL -}; -static qhandle_t shaderAnims[MAX_SHADER_ANIMS][MAX_SHADER_ANIM_FRAMES]; -static int	shaderAnimCounts[MAX_SHADER_ANIMS] = { -	23, -	25, -	45, -	25, -	23, -	5, -}; -static float	shaderAnimSTRatio[MAX_SHADER_ANIMS] = { -	1.405f, -	1.0f, -	1.0f, -	1.0f, -	1.0f, -	1.0f, -}; -static int	numShaderAnims; -// done. - -#define		PARTICLE_GRAVITY	40 -#define		MAX_PARTICLES	1024 * 8 - -cparticle_t	*active_particles, *free_particles; -cparticle_t	particles[MAX_PARTICLES]; -int		cl_numparticles = MAX_PARTICLES; - -qboolean		initparticles = qfalse; -vec3_t			vforward, vright, vup; -vec3_t			rforward, rright, rup; - -float			oldtime; - -/* -=============== -CL_ClearParticles -=============== -*/ -void CG_ClearParticles (void) -{ -	int		i; - -	memset( particles, 0, sizeof(particles) ); - -	free_particles = &particles[0]; -	active_particles = NULL; - -	for (i=0 ;i<cl_numparticles ; i++) -	{ -		particles[i].next = &particles[i+1]; -		particles[i].type = 0; -	} -	particles[cl_numparticles-1].next = NULL; - -	oldtime = cg.time; - -	// Ridah, init the shaderAnims -	//for (i=0; shaderAnimNames[i]; i++) { -  //TA: figure out this thing works... -  i = 0; -	{ -		int j; - -		for (j=0; j<shaderAnimCounts[i]; j++) { -			shaderAnims[i][j] = trap_R_RegisterShader( va("%s%i", shaderAnimNames[i], j+1) ); -		} -	} -	numShaderAnims = i; -	// done. - -	initparticles = qtrue; -} - - -/* -===================== -CG_AddParticleToScene -===================== -*/ -void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) -{ - -	vec3_t		point; -	polyVert_t	verts[4]; -	float		width; -	float		height; -	float		time, time2; -	float		ratio; -	float		invratio; -	vec3_t		color; -	polyVert_t	TRIverts[3]; -	vec3_t		rright2, rup2; - -	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY -		|| p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) -	{// create a front facing polygon -			 -		if (p->type != P_WEATHER_FLURRY) -		{ -			if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) -			{ -				if (org[2] > p->end)			 -				{	 -					p->time = cg.time;	 -					VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground -									 -					p->org[2] = ( p->start + crandom () * 4 ); -					 -					 -					if (p->type == P_BUBBLE_TURBULENT) -					{ -						p->vel[0] = crandom() * 4; -						p->vel[1] = crandom() * 4; -					} -				 -				} -			} -			else -			{ -				if (org[2] < p->end)			 -				{	 -					p->time = cg.time;	 -					VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground -									 -					while (p->org[2] < p->end)  -					{ -						p->org[2] += (p->start - p->end);  -					} -					 -					 -					if (p->type == P_WEATHER_TURBULENT) -					{ -						p->vel[0] = crandom() * 16; -						p->vel[1] = crandom() * 16; -					} -				 -				} -			} -			 - -			// Rafael snow pvs check -			if (!p->link) -				return; - -			p->alpha = 1; -		} -		 -		// Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp -		if (Distance( cg.snap->ps.origin, org ) > 1024) { -			return; -		} -		// done. -	 -		if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) -		{ -			VectorMA (org, -p->height, vup, point);	 -			VectorMA (point, -p->width, vright, point);	 -			VectorCopy (point, verts[0].xyz);	 -			verts[0].st[0] = 0;	 -			verts[0].st[1] = 0;	 -			verts[0].modulate[0] = 255;	 -			verts[0].modulate[1] = 255;	 -			verts[0].modulate[2] = 255;	 -			verts[0].modulate[3] = 255 * p->alpha;	 - -			VectorMA (org, -p->height, vup, point);	 -			VectorMA (point, p->width, vright, point);	 -			VectorCopy (point, verts[1].xyz);	 -			verts[1].st[0] = 0;	 -			verts[1].st[1] = 1;	 -			verts[1].modulate[0] = 255;	 -			verts[1].modulate[1] = 255;	 -			verts[1].modulate[2] = 255;	 -			verts[1].modulate[3] = 255 * p->alpha;	 - -			VectorMA (org, p->height, vup, point);	 -			VectorMA (point, p->width, vright, point);	 -			VectorCopy (point, verts[2].xyz);	 -			verts[2].st[0] = 1;	 -			verts[2].st[1] = 1;	 -			verts[2].modulate[0] = 255;	 -			verts[2].modulate[1] = 255;	 -			verts[2].modulate[2] = 255;	 -			verts[2].modulate[3] = 255 * p->alpha;	 - -			VectorMA (org, p->height, vup, point);	 -			VectorMA (point, -p->width, vright, point);	 -			VectorCopy (point, verts[3].xyz);	 -			verts[3].st[0] = 1;	 -			verts[3].st[1] = 0;	 -			verts[3].modulate[0] = 255;	 -			verts[3].modulate[1] = 255;	 -			verts[3].modulate[2] = 255;	 -			verts[3].modulate[3] = 255 * p->alpha;	 -		} -		else -		{ -			VectorMA (org, -p->height, vup, point);	 -			VectorMA (point, -p->width, vright, point);	 -			VectorCopy( point, TRIverts[0].xyz ); -			TRIverts[0].st[0] = 1; -			TRIverts[0].st[1] = 0; -			TRIverts[0].modulate[0] = 255; -			TRIverts[0].modulate[1] = 255; -			TRIverts[0].modulate[2] = 255; -			TRIverts[0].modulate[3] = 255 * p->alpha;	 - -			VectorMA (org, p->height, vup, point);	 -			VectorMA (point, -p->width, vright, point);	 -			VectorCopy (point, TRIverts[1].xyz);	 -			TRIverts[1].st[0] = 0; -			TRIverts[1].st[1] = 0; -			TRIverts[1].modulate[0] = 255; -			TRIverts[1].modulate[1] = 255; -			TRIverts[1].modulate[2] = 255; -			TRIverts[1].modulate[3] = 255 * p->alpha;	 - -			VectorMA (org, p->height, vup, point);	 -			VectorMA (point, p->width, vright, point);	 -			VectorCopy (point, TRIverts[2].xyz);	 -			TRIverts[2].st[0] = 0; -			TRIverts[2].st[1] = 1; -			TRIverts[2].modulate[0] = 255; -			TRIverts[2].modulate[1] = 255; -			TRIverts[2].modulate[2] = 255; -			TRIverts[2].modulate[3] = 255 * p->alpha;	 -		} -	 -	} -	else if (p->type == P_SPRITE) -	{ -		vec3_t	rr, ru; -		vec3_t	rotate_ang; - -		VectorSet (color, 1.0, 1.0, 1.0); -		time = cg.time - p->time; -		time2 = p->endtime - p->time; -		ratio = time / time2; - -		width = p->width + ( ratio * ( p->endwidth - p->width) ); -		height = p->height + ( ratio * ( p->endheight - p->height) ); - -		if (p->roll) { -			vectoangles( cg.refdef.viewaxis[0], rotate_ang ); -			rotate_ang[ROLL] += p->roll; -			AngleVectors ( rotate_ang, NULL, rr, ru); -		} - -		if (p->roll) { -			VectorMA (org, -height, ru, point);	 -			VectorMA (point, -width, rr, point);	 -		} else { -			VectorMA (org, -height, vup, point);	 -			VectorMA (point, -width, vright, point);	 -		} -		VectorCopy (point, verts[0].xyz);	 -		verts[0].st[0] = 0;	 -		verts[0].st[1] = 0;	 -		verts[0].modulate[0] = 255;	 -		verts[0].modulate[1] = 255;	 -		verts[0].modulate[2] = 255;	 -		verts[0].modulate[3] = 255; - -		if (p->roll) { -			VectorMA (point, 2*height, ru, point);	 -		} else { -			VectorMA (point, 2*height, vup, point);	 -		} -		VectorCopy (point, verts[1].xyz);	 -		verts[1].st[0] = 0;	 -		verts[1].st[1] = 1;	 -		verts[1].modulate[0] = 255;	 -		verts[1].modulate[1] = 255;	 -		verts[1].modulate[2] = 255;	 -		verts[1].modulate[3] = 255;	 - -		if (p->roll) { -			VectorMA (point, 2*width, rr, point);	 -		} else { -			VectorMA (point, 2*width, vright, point);	 -		} -		VectorCopy (point, verts[2].xyz);	 -		verts[2].st[0] = 1;	 -		verts[2].st[1] = 1;	 -		verts[2].modulate[0] = 255;	 -		verts[2].modulate[1] = 255;	 -		verts[2].modulate[2] = 255;	 -		verts[2].modulate[3] = 255;	 - -		if (p->roll) { -			VectorMA (point, -2*height, ru, point);	 -		} else { -			VectorMA (point, -2*height, vup, point);	 -		} -		VectorCopy (point, verts[3].xyz);	 -		verts[3].st[0] = 1;	 -		verts[3].st[1] = 0;	 -		verts[3].modulate[0] = 255;	 -		verts[3].modulate[1] = 255;	 -		verts[3].modulate[2] = 255;	 -		verts[3].modulate[3] = 255;	 -	} -	else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT) -	{// create a front rotating facing polygon - -		if ( p->type == P_SMOKE_IMPACT && Distance( cg.snap->ps.origin, org ) > 1024) { -			return; -		} - -		if (p->color == BLOODRED) -			VectorSet (color, 0.22f, 0.0f, 0.0f); -		else if (p->color == GREY75) -		{ -			float	len; -			float	greyit; -			float	val; -			len = Distance (cg.snap->ps.origin, org); -			if (!len) -				len = 1; - -			val = 4096/len; -			greyit = 0.25 * val; -			if (greyit > 0.5) -				greyit = 0.5; - -			VectorSet (color, greyit, greyit, greyit); -		} -		else -			VectorSet (color, 1.0, 1.0, 1.0); - -		time = cg.time - p->time; -		time2 = p->endtime - p->time; -		ratio = time / time2; -		 -		if (cg.time > p->startfade) -		{ -			invratio = 1 - ( (cg.time - p->startfade) / (p->endtime - p->startfade) ); - -			if (p->color == EMISIVEFADE) -			{ -				float fval; -				fval = (invratio * invratio); -				if (fval < 0) -					fval = 0; -				VectorSet (color, fval , fval , fval ); -			} -			invratio *= p->alpha; -		} -		else  -			invratio = 1 * p->alpha; - -		if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) -			invratio = 1; - -		if (invratio > 1) -			invratio = 1; -	 -		width = p->width + ( ratio * ( p->endwidth - p->width) ); -		height = p->height + ( ratio * ( p->endheight - p->height) ); - -		if (p->type != P_SMOKE_IMPACT) -		{ -			vec3_t temp; - -			vectoangles (rforward, temp); -			p->accumroll += p->roll; -			temp[ROLL] += p->accumroll * 0.1; -			AngleVectors ( temp, NULL, rright2, rup2); -		} -		else -		{ -			VectorCopy (rright, rright2); -			VectorCopy (rup, rup2); -		} -		 -		if (p->rotate) -		{ -			VectorMA (org, -height, rup2, point);	 -			VectorMA (point, -width, rright2, point);	 -		} -		else -		{ -			VectorMA (org, -p->height, vup, point);	 -			VectorMA (point, -p->width, vright, point);	 -		} -		VectorCopy (point, verts[0].xyz);	 -		verts[0].st[0] = 0;	 -		verts[0].st[1] = 0;	 -		verts[0].modulate[0] = 255 * color[0];	 -		verts[0].modulate[1] = 255 * color[1];	 -		verts[0].modulate[2] = 255 * color[2];	 -		verts[0].modulate[3] = 255 * invratio;	 - -		if (p->rotate) -		{ -			VectorMA (org, -height, rup2, point);	 -			VectorMA (point, width, rright2, point);	 -		} -		else -		{ -			VectorMA (org, -p->height, vup, point);	 -			VectorMA (point, p->width, vright, point);	 -		} -		VectorCopy (point, verts[1].xyz);	 -		verts[1].st[0] = 0;	 -		verts[1].st[1] = 1;	 -		verts[1].modulate[0] = 255 * color[0];	 -		verts[1].modulate[1] = 255 * color[1];	 -		verts[1].modulate[2] = 255 * color[2];	 -		verts[1].modulate[3] = 255 * invratio;	 - -		if (p->rotate) -		{ -			VectorMA (org, height, rup2, point);	 -			VectorMA (point, width, rright2, point);	 -		} -		else -		{ -			VectorMA (org, p->height, vup, point);	 -			VectorMA (point, p->width, vright, point);	 -		} -		VectorCopy (point, verts[2].xyz);	 -		verts[2].st[0] = 1;	 -		verts[2].st[1] = 1;	 -		verts[2].modulate[0] = 255 * color[0];	 -		verts[2].modulate[1] = 255 * color[1];	 -		verts[2].modulate[2] = 255 * color[2];	 -		verts[2].modulate[3] = 255 * invratio;	 - -		if (p->rotate) -		{ -			VectorMA (org, height, rup2, point);	 -			VectorMA (point, -width, rright2, point);	 -		} -		else -		{ -			VectorMA (org, p->height, vup, point);	 -			VectorMA (point, -p->width, vright, point);	 -		} -		VectorCopy (point, verts[3].xyz);	 -		verts[3].st[0] = 1;	 -		verts[3].st[1] = 0;	 -		verts[3].modulate[0] = 255 * color[0];	 -		verts[3].modulate[1] = 255 * color[1];	 -		verts[3].modulate[2] = 255 * color[2];	 -		verts[3].modulate[3] = 255  * invratio;	 -		 -	} -	else if (p->type == P_BLEED) -	{ -		vec3_t	rr, ru; -		vec3_t	rotate_ang; -		float	alpha; - -		alpha = p->alpha; -		 -		if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) -			alpha = 1; - -		if (p->roll)  -		{ -			vectoangles( cg.refdef.viewaxis[0], rotate_ang ); -			rotate_ang[ROLL] += p->roll; -			AngleVectors ( rotate_ang, NULL, rr, ru); -		} -		else -		{ -			VectorCopy (vup, ru); -			VectorCopy (vright, rr); -		} - -		VectorMA (org, -p->height, ru, point);	 -		VectorMA (point, -p->width, rr, point);	 -		VectorCopy (point, verts[0].xyz);	 -		verts[0].st[0] = 0;	 -		verts[0].st[1] = 0;	 -		verts[0].modulate[0] = 111;	 -		verts[0].modulate[1] = 19;	 -		verts[0].modulate[2] = 9;	 -		verts[0].modulate[3] = 255 * alpha;	 - -		VectorMA (org, -p->height, ru, point);	 -		VectorMA (point, p->width, rr, point);	 -		VectorCopy (point, verts[1].xyz);	 -		verts[1].st[0] = 0;	 -		verts[1].st[1] = 1;	 -		verts[1].modulate[0] = 111;	 -		verts[1].modulate[1] = 19;	 -		verts[1].modulate[2] = 9;	 -		verts[1].modulate[3] = 255 * alpha;	 - -		VectorMA (org, p->height, ru, point);	 -		VectorMA (point, p->width, rr, point);	 -		VectorCopy (point, verts[2].xyz);	 -		verts[2].st[0] = 1;	 -		verts[2].st[1] = 1;	 -		verts[2].modulate[0] = 111;	 -		verts[2].modulate[1] = 19;	 -		verts[2].modulate[2] = 9;	 -		verts[2].modulate[3] = 255 * alpha;	 - -		VectorMA (org, p->height, ru, point);	 -		VectorMA (point, -p->width, rr, point);	 -		VectorCopy (point, verts[3].xyz);	 -		verts[3].st[0] = 1;	 -		verts[3].st[1] = 0;	 -		verts[3].modulate[0] = 111;	 -		verts[3].modulate[1] = 19;	 -		verts[3].modulate[2] = 9;	 -		verts[3].modulate[3] = 255 * alpha;	 - -	} -	else if (p->type == P_FLAT_SCALEUP) -	{ -		float width, height; -		float sinR, cosR; - -		if (p->color == BLOODRED) -			VectorSet (color, 1, 1, 1); -		else -			VectorSet (color, 0.5, 0.5, 0.5); -		 -		time = cg.time - p->time; -		time2 = p->endtime - p->time; -		ratio = time / time2; - -		width = p->width + ( ratio * ( p->endwidth - p->width) ); -		height = p->height + ( ratio * ( p->endheight - p->height) ); - -		if (width > p->endwidth) -			width = p->endwidth; - -		if (height > p->endheight) -			height = p->endheight; - -		sinR = height * sin(DEG2RAD(p->roll)) * sqrt(2); -		cosR = width * cos(DEG2RAD(p->roll)) * sqrt(2); - -		VectorCopy (org, verts[0].xyz);	 -		verts[0].xyz[0] -= sinR; -		verts[0].xyz[1] -= cosR; -		verts[0].st[0] = 0;	 -		verts[0].st[1] = 0;	 -		verts[0].modulate[0] = 255 * color[0];	 -		verts[0].modulate[1] = 255 * color[1];	 -		verts[0].modulate[2] = 255 * color[2];	 -		verts[0].modulate[3] = 255;	 - -		VectorCopy (org, verts[1].xyz);	 -		verts[1].xyz[0] -= cosR;	 -		verts[1].xyz[1] += sinR;	 -		verts[1].st[0] = 0;	 -		verts[1].st[1] = 1;	 -		verts[1].modulate[0] = 255 * color[0];	 -		verts[1].modulate[1] = 255 * color[1];	 -		verts[1].modulate[2] = 255 * color[2];	 -		verts[1].modulate[3] = 255;	 - -		VectorCopy (org, verts[2].xyz);	 -		verts[2].xyz[0] += sinR;	 -		verts[2].xyz[1] += cosR;	 -		verts[2].st[0] = 1;	 -		verts[2].st[1] = 1;	 -		verts[2].modulate[0] = 255 * color[0];	 -		verts[2].modulate[1] = 255 * color[1];	 -		verts[2].modulate[2] = 255 * color[2];	 -		verts[2].modulate[3] = 255;	 - -		VectorCopy (org, verts[3].xyz);	 -		verts[3].xyz[0] += cosR;	 -		verts[3].xyz[1] -= sinR;	 -		verts[3].st[0] = 1;	 -		verts[3].st[1] = 0;	 -		verts[3].modulate[0] = 255 * color[0];	 -		verts[3].modulate[1] = 255 * color[1];	 -		verts[3].modulate[2] = 255 * color[2];	 -		verts[3].modulate[3] = 255;		 -	} -	else if (p->type == P_FLAT) -	{ - -		VectorCopy (org, verts[0].xyz);	 -		verts[0].xyz[0] -= p->height;	 -		verts[0].xyz[1] -= p->width;	 -		verts[0].st[0] = 0;	 -		verts[0].st[1] = 0;	 -		verts[0].modulate[0] = 255;	 -		verts[0].modulate[1] = 255;	 -		verts[0].modulate[2] = 255;	 -		verts[0].modulate[3] = 255;	 - -		VectorCopy (org, verts[1].xyz);	 -		verts[1].xyz[0] -= p->height;	 -		verts[1].xyz[1] += p->width;	 -		verts[1].st[0] = 0;	 -		verts[1].st[1] = 1;	 -		verts[1].modulate[0] = 255;	 -		verts[1].modulate[1] = 255;	 -		verts[1].modulate[2] = 255;	 -		verts[1].modulate[3] = 255;	 - -		VectorCopy (org, verts[2].xyz);	 -		verts[2].xyz[0] += p->height;	 -		verts[2].xyz[1] += p->width;	 -		verts[2].st[0] = 1;	 -		verts[2].st[1] = 1;	 -		verts[2].modulate[0] = 255;	 -		verts[2].modulate[1] = 255;	 -		verts[2].modulate[2] = 255;	 -		verts[2].modulate[3] = 255;	 - -		VectorCopy (org, verts[3].xyz);	 -		verts[3].xyz[0] += p->height;	 -		verts[3].xyz[1] -= p->width;	 -		verts[3].st[0] = 1;	 -		verts[3].st[1] = 0;	 -		verts[3].modulate[0] = 255;	 -		verts[3].modulate[1] = 255;	 -		verts[3].modulate[2] = 255;	 -		verts[3].modulate[3] = 255;	 - -	} -	// Ridah -	else if (p->type == P_ANIM) { -		vec3_t	rr, ru; -		vec3_t	rotate_ang; -		int i, j; - -		time = cg.time - p->time; -		time2 = p->endtime - p->time; -		ratio = time / time2; -		if (ratio >= 1.0f) { -			ratio = 0.9999f; -		} - -		width = p->width + ( ratio * ( p->endwidth - p->width) ); -		height = p->height + ( ratio * ( p->endheight - p->height) ); - -		// if we are "inside" this sprite, don't draw -		if (Distance( cg.snap->ps.origin, org ) < width/1.5) { -			return; -		} - -		i = p->shaderAnim; -		j = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]); -		p->pshader = shaderAnims[i][j]; - -		if (p->roll) { -			vectoangles( cg.refdef.viewaxis[0], rotate_ang ); -			rotate_ang[ROLL] += p->roll; -			AngleVectors ( rotate_ang, NULL, rr, ru); -		} - -		if (p->roll) { -			VectorMA (org, -height, ru, point);	 -			VectorMA (point, -width, rr, point);	 -		} else { -			VectorMA (org, -height, vup, point);	 -			VectorMA (point, -width, vright, point);	 -		} -		VectorCopy (point, verts[0].xyz);	 -		verts[0].st[0] = 0;	 -		verts[0].st[1] = 0;	 -		verts[0].modulate[0] = 255;	 -		verts[0].modulate[1] = 255;	 -		verts[0].modulate[2] = 255;	 -		verts[0].modulate[3] = 255; - -		if (p->roll) { -			VectorMA (point, 2*height, ru, point);	 -		} else { -			VectorMA (point, 2*height, vup, point);	 -		} -		VectorCopy (point, verts[1].xyz);	 -		verts[1].st[0] = 0;	 -		verts[1].st[1] = 1;	 -		verts[1].modulate[0] = 255;	 -		verts[1].modulate[1] = 255;	 -		verts[1].modulate[2] = 255;	 -		verts[1].modulate[3] = 255;	 - -		if (p->roll) { -			VectorMA (point, 2*width, rr, point);	 -		} else { -			VectorMA (point, 2*width, vright, point);	 -		} -		VectorCopy (point, verts[2].xyz);	 -		verts[2].st[0] = 1;	 -		verts[2].st[1] = 1;	 -		verts[2].modulate[0] = 255;	 -		verts[2].modulate[1] = 255;	 -		verts[2].modulate[2] = 255;	 -		verts[2].modulate[3] = 255;	 - -		if (p->roll) { -			VectorMA (point, -2*height, ru, point);	 -		} else { -			VectorMA (point, -2*height, vup, point);	 -		} -		VectorCopy (point, verts[3].xyz);	 -		verts[3].st[0] = 1;	 -		verts[3].st[1] = 0;	 -		verts[3].modulate[0] = 255;	 -		verts[3].modulate[1] = 255;	 -		verts[3].modulate[2] = 255;	 -		verts[3].modulate[3] = 255;	 -	} -	// done. -	 -	if (!p->pshader) { -// (SA) temp commented out for DM -//		CG_Printf ("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type); -		return; -	} - -	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) -		trap_R_AddPolyToScene( p->pshader, 3, TRIverts ); -	else -		trap_R_AddPolyToScene( p->pshader, 4, verts ); - -} - -// Ridah, made this static so it doesn't interfere with other files -static float roll = 0.0; - -/* -=============== -CG_AddParticles -=============== -*/ -void CG_AddParticles (void) -{ -	cparticle_t		*p, *next; -	float			alpha; -	float			time, time2; -	vec3_t			org; -	int				color; -	cparticle_t		*active, *tail; -	int				type; -	vec3_t			rotate_ang; - -	if (!initparticles) -		CG_ClearParticles (); - -	VectorCopy( cg.refdef.viewaxis[0], vforward ); -	VectorCopy( cg.refdef.viewaxis[1], vright ); -	VectorCopy( cg.refdef.viewaxis[2], vup ); - -	vectoangles( cg.refdef.viewaxis[0], rotate_ang ); -	roll += ((cg.time - oldtime) * 0.1) ; -	rotate_ang[ROLL] += (roll*0.9); -	AngleVectors ( rotate_ang, rforward, rright, rup); -	 -	oldtime = cg.time; - -	active = NULL; -	tail = NULL; - -	for (p=active_particles ; p ; p=next) -	{ - -		next = p->next; - -		time = (cg.time - p->time)*0.001; - -		alpha = p->alpha + time*p->alphavel; -		if (alpha <= 0) -		{	// faded out -			p->next = free_particles; -			free_particles = p; -			p->type = 0; -			p->color = 0; -			p->alpha = 0; -			continue; -		} - -		if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT) -		{ -			if (cg.time > p->endtime) -			{ -				p->next = free_particles; -				free_particles = p; -				p->type = 0; -				p->color = 0; -				p->alpha = 0; -			 -				continue; -			} - -		} - -		if (p->type == P_WEATHER_FLURRY) -		{ -			if (cg.time > p->endtime) -			{ -				p->next = free_particles; -				free_particles = p; -				p->type = 0; -				p->color = 0; -				p->alpha = 0; -			 -				continue; -			} -		} - - -		if (p->type == P_FLAT_SCALEUP_FADE) -		{ -			if (cg.time > p->endtime) -			{ -				p->next = free_particles; -				free_particles = p; -				p->type = 0; -				p->color = 0; -				p->alpha = 0; -				continue; -			} - -		} - -		if ((p->type == P_BAT || p->type == P_SPRITE) && p->endtime < 0) { -			// temporary sprite -			CG_AddParticleToScene (p, p->org, alpha); -			p->next = free_particles; -			free_particles = p; -			p->type = 0; -			p->color = 0; -			p->alpha = 0; -			continue; -		} - -		p->next = NULL; -		if (!tail) -			active = tail = p; -		else -		{ -			tail->next = p; -			tail = p; -		} - -		if (alpha > 1.0) -			alpha = 1; - -		color = p->color; - -		time2 = time*time; - -		org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2; -		org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2; -		org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2; - -		type = p->type; - -		CG_AddParticleToScene (p, org, alpha); -	} - -	active_particles = active; -} - -/* -====================== -CG_AddParticles -====================== -*/ -void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) -{ -	cparticle_t	*p; -	qboolean turb = qtrue; - -	if (!pshader) -		CG_Printf ("CG_ParticleSnowFlurry pshader == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->color = 0; -	p->alpha = 0.90f; -	p->alphavel = 0; - -	p->start = cent->currentState.origin2[0]; -	p->end = cent->currentState.origin2[1]; -	 -	p->endtime = cg.time + cent->currentState.time; -	p->startfade = cg.time + cent->currentState.time2; -	 -	p->pshader = pshader; -	 -	if (rand()%100 > 90) -	{ -		p->height = 32; -		p->width = 32; -		p->alpha = 0.10f; -	} -	else -	{ -		p->height = 1; -		p->width = 1; -	} - -	p->vel[2] = -20; - -	p->type = P_WEATHER_FLURRY; -	 -	if (turb) -		p->vel[2] = -10; -	 -	VectorCopy(cent->currentState.origin, p->org); - -	p->org[0] = p->org[0]; -	p->org[1] = p->org[1]; -	p->org[2] = p->org[2]; - -	p->vel[0] = p->vel[1] = 0; -	 -	p->accel[0] = p->accel[1] = p->accel[2] = 0; - -	p->vel[0] += cent->currentState.angles[0] * 32 + (crandom() * 16); -	p->vel[1] += cent->currentState.angles[1] * 32 + (crandom() * 16); -	p->vel[2] += cent->currentState.angles[2]; - -	if (turb) -	{ -		p->accel[0] = crandom () * 16; -		p->accel[1] = crandom () * 16; -	} - -} - -void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) -{ -	cparticle_t	*p; - -	if (!pshader) -		CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->color = 0; -	p->alpha = 0.40f; -	p->alphavel = 0; -	p->start = origin[2]; -	p->end = origin2[2]; -	p->pshader = pshader; -	p->height = 1; -	p->width = 1; -	 -	p->vel[2] = -50; - -	if (turb) -	{ -		p->type = P_WEATHER_TURBULENT; -		p->vel[2] = -50 * 1.3; -	} -	else -	{ -		p->type = P_WEATHER; -	} -	 -	VectorCopy(origin, p->org); - -	p->org[0] = p->org[0] + ( crandom() * range); -	p->org[1] = p->org[1] + ( crandom() * range); -	p->org[2] = p->org[2] + ( crandom() * (p->start - p->end));  - -	p->vel[0] = p->vel[1] = 0; -	 -	p->accel[0] = p->accel[1] = p->accel[2] = 0; - -	if (turb) -	{ -		p->vel[0] = crandom() * 16; -		p->vel[1] = crandom() * 16; -	} - -	// Rafael snow pvs check -	p->snum = snum; -	p->link = qtrue; - -} - -void CG_ParticleBubble (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) -{ -	cparticle_t	*p; -	float		randsize; - -	if (!pshader) -		CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->color = 0; -	p->alpha = 0.40f; -	p->alphavel = 0; -	p->start = origin[2]; -	p->end = origin2[2]; -	p->pshader = pshader; -	 -	randsize = 1 + (crandom() * 0.5); -	 -	p->height = randsize; -	p->width = randsize; -	 -	p->vel[2] = 50 + ( crandom() * 10 ); - -	if (turb) -	{ -		p->type = P_BUBBLE_TURBULENT; -		p->vel[2] = 50 * 1.3; -	} -	else -	{ -		p->type = P_BUBBLE; -	} -	 -	VectorCopy(origin, p->org); - -	p->org[0] = p->org[0] + ( crandom() * range); -	p->org[1] = p->org[1] + ( crandom() * range); -	p->org[2] = p->org[2] + ( crandom() * (p->start - p->end));  - -	p->vel[0] = p->vel[1] = 0; -	 -	p->accel[0] = p->accel[1] = p->accel[2] = 0; - -	if (turb) -	{ -		p->vel[0] = crandom() * 4; -		p->vel[1] = crandom() * 4; -	} - -	// Rafael snow pvs check -	p->snum = snum; -	p->link = qtrue; - -} - -void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) -{ - -	// using cent->density = enttime -	//		 cent->frame = startfade -	cparticle_t	*p; - -	if (!pshader) -		CG_Printf ("CG_ParticleSmoke == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	 -	p->endtime = cg.time + cent->currentState.time; -	p->startfade = cg.time + cent->currentState.time2; -	 -	p->color = 0; -	p->alpha = 1.0; -	p->alphavel = 0; -	p->start = cent->currentState.origin[2]; -	p->end = cent->currentState.origin2[2]; -	p->pshader = pshader; -	p->rotate = qfalse; -	p->height = 8; -	p->width = 8; -	p->endheight = 32; -	p->endwidth = 32; -	p->type = P_SMOKE; -	 -	VectorCopy(cent->currentState.origin, p->org); - -	p->vel[0] = p->vel[1] = 0; -	p->accel[0] = p->accel[1] = p->accel[2] = 0; - -	p->vel[2] = 5; - -	if (cent->currentState.frame == 1)// reverse gravity	 -		p->vel[2] *= -1; - -	p->roll = 8 + (crandom() * 4); -} - - -void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) -{ - -	cparticle_t	*p; - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	 -	p->endtime = cg.time + duration; -	p->startfade = cg.time + duration/2; -	 -	p->color = EMISIVEFADE; -	p->alpha = 1.0; -	p->alphavel = 0; - -	p->height = 0.5; -	p->width = 0.5; -	p->endheight = 0.5; -	p->endwidth = 0.5; - -	p->pshader = cgs.media.tracerShader; - -	p->type = P_SMOKE; -	 -	VectorCopy(org, p->org); - -	p->vel[0] = vel[0]; -	p->vel[1] = vel[1]; -	p->vel[2] = vel[2]; -	p->accel[0] = p->accel[1] = p->accel[2] = 0; - -	p->accel[2] = -60; -	p->vel[2] += -20; -	 -} - -/* -====================== -CG_ParticleExplosion -====================== -*/ - -void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd) -{ -	cparticle_t	*p; -	int anim; - -	if (animStr < (char *)10) -		CG_Error( "CG_ParticleExplosion: animStr is probably an index rather than a string" ); - -	// find the animation string -	for (anim=0; shaderAnimNames[anim]; anim++) { -		if (!Q_stricmp( animStr, shaderAnimNames[anim] )) -			break; -	} -	if (!shaderAnimNames[anim]) { -		CG_Error("CG_ParticleExplosion: unknown animation string: %s\n", animStr); -		return; -	} - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->alpha = 1.0; -	p->alphavel = 0; - -	if (duration < 0) { -		duration *= -1; -		p->roll = 0; -	} else { -		p->roll = crandom()*179; -	} - -	p->shaderAnim = anim; - -	p->width = sizeStart; -	p->height = sizeStart*shaderAnimSTRatio[anim];	// for sprites that are stretch in either direction - -	p->endheight = sizeEnd; -	p->endwidth = sizeEnd*shaderAnimSTRatio[anim]; - -	p->endtime = cg.time + duration; - -	p->type = P_ANIM; - -	VectorCopy( origin, p->org ); -	VectorCopy( vel, p->vel ); -	VectorClear( p->accel ); - -} - -// Rafael Shrapnel -void CG_AddParticleShrapnel (localEntity_t *le) -{ -	return; -} -// done. - -int CG_NewParticleArea (int num) -{ -	// const char *str; -	char *str; -	char *token; -	int type; -	vec3_t origin, origin2; -	int		i; -	float range = 0; -	int turb; -	int	numparticles; -	int	snum; -	 -	str = (char *) CG_ConfigString (num); -	if (!str[0]) -		return (0); -	 -	// returns type 128 64 or 32 -	token = COM_Parse (&str); -	type = atoi (token); -	 -	if (type == 1) -		range = 128; -	else if (type == 2) -		range = 64; -	else if (type == 3) -		range = 32; -	else if (type == 0) -		range = 256; -	else if (type == 4) -		range = 8; -	else if (type == 5) -		range = 16; -	else if (type == 6) -		range = 32; -	else if (type == 7) -		range = 64; - - -	for (i=0; i<3; i++) -	{ -		token = COM_Parse (&str); -		origin[i] = atof (token); -	} - -	for (i=0; i<3; i++) -	{ -		token = COM_Parse (&str); -		origin2[i] = atof (token); -	} -		 -	token = COM_Parse (&str); -	numparticles = atoi (token); -	 -	token = COM_Parse (&str); -	turb = atoi (token); - -	token = COM_Parse (&str); -	snum = atoi (token); -	 -	for (i=0; i<numparticles; i++) -	{ -		if (type >= 4) -			CG_ParticleBubble (cgs.media.waterBubbleShader, origin, origin2, turb, range, snum); -		else -			CG_ParticleSnow (cgs.media.waterBubbleShader, origin, origin2, turb, range, snum); -	} - -	return (1); -} - -void	CG_SnowLink (centity_t *cent, qboolean particleOn) -{ -	cparticle_t		*p, *next; -	int id; - -	id = cent->currentState.frame; - -	for (p=active_particles ; p ; p=next) -	{ -		next = p->next; -		 -		if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT) -		{ -			if (p->snum == id) -			{ -				if (particleOn) -					p->link = qtrue; -				else -					p->link = qfalse; -			} -		} - -	} -} - -void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) -{ -	cparticle_t	*p; - -	if (!pshader) -		CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->alpha = 0.25; -	p->alphavel = 0; -	p->roll = crandom()*179; - -	p->pshader = pshader; - -	p->endtime = cg.time + 1000; -	p->startfade = cg.time + 100; - -	p->width = rand()%4 + 8; -	p->height = rand()%4 + 8; - -	p->endheight = p->height *2; -	p->endwidth = p->width * 2; - -	p->endtime = cg.time + 500; - -	p->type = P_SMOKE_IMPACT; - -	VectorCopy( origin, p->org ); -	VectorSet(p->vel, 0, 0, 20); -	VectorSet(p->accel, 0, 0, 20); - -	p->rotate = qtrue; -} - -void CG_Particle_Bleed (qhandle_t pshader, vec3_t start, vec3_t dir, int fleshEntityNum, int duration) -{ -	cparticle_t	*p; - -	if (!pshader) -		CG_Printf ("CG_Particle_Bleed pshader == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->alpha = 1.0; -	p->alphavel = 0; -	p->roll = 0; - -	p->pshader = pshader; - -	p->endtime = cg.time + duration; -	 -	if (fleshEntityNum) -		p->startfade = cg.time; -	else -		p->startfade = cg.time + 100; - -	p->width = 4; -	p->height = 4; - -	p->endheight = 4+rand()%3; -	p->endwidth = p->endheight; - -	p->type = P_SMOKE; - -	VectorCopy( start, p->org ); -	p->vel[0] = 0; -	p->vel[1] = 0; -	p->vel[2] = -20; -	VectorClear( p->accel ); - -	p->rotate = qfalse; - -	p->roll = rand()%179; -	 -	p->color = BLOODRED; -	p->alpha = 0.75; - -} - -void CG_Particle_OilParticle (qhandle_t pshader, centity_t *cent) -{ -	cparticle_t	*p; - -	int			time; -	int			time2; -	float		ratio; - -	float	duration = 1500; - -	time = cg.time; -	time2 = cg.time + cent->currentState.time; - -	ratio =(float)1 - ((float)time / (float)time2); - -	if (!pshader) -		CG_Printf ("CG_Particle_OilParticle == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->alpha = 1.0; -	p->alphavel = 0; -	p->roll = 0; - -	p->pshader = pshader; - -	p->endtime = cg.time + duration; -	 -	p->startfade = p->endtime; - -	p->width = 1; -	p->height = 3; - -	p->endheight = 3; -	p->endwidth = 1; - -	p->type = P_SMOKE; - -	VectorCopy(cent->currentState.origin, p->org );	 -	 -	p->vel[0] = (cent->currentState.origin2[0] * (16 * ratio)); -	p->vel[1] = (cent->currentState.origin2[1] * (16 * ratio)); -	p->vel[2] = (cent->currentState.origin2[2]); - -	p->snum = 1.0f; - -	VectorClear( p->accel ); - -	p->accel[2] = -20; - -	p->rotate = qfalse; - -	p->roll = rand()%179; -	 -	p->alpha = 0.75; - -} - - -void CG_Particle_OilSlick (qhandle_t pshader, centity_t *cent) -{ -	cparticle_t	*p; -	 -  	if (!pshader) -		CG_Printf ("CG_Particle_OilSlick == ZERO!\n"); - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	 -	if (cent->currentState.angles2[2]) -		p->endtime = cg.time + cent->currentState.angles2[2]; -	else -		p->endtime = cg.time + 60000; - -	p->startfade = p->endtime; - -	p->alpha = 1.0; -	p->alphavel = 0; -	p->roll = 0; - -	p->pshader = pshader; - -	if (cent->currentState.angles2[0] || cent->currentState.angles2[1]) -	{ -		p->width = cent->currentState.angles2[0]; -		p->height = cent->currentState.angles2[0]; - -		p->endheight = cent->currentState.angles2[1]; -		p->endwidth = cent->currentState.angles2[1]; -	} -	else -	{ -		p->width = 8; -		p->height = 8; - -		p->endheight = 16; -		p->endwidth = 16; -	} - -	p->type = P_FLAT_SCALEUP; - -	p->snum = 1.0; - -	VectorCopy(cent->currentState.origin, p->org ); -	 -	p->org[2]+= 0.55 + (crandom() * 0.5); - -	p->vel[0] = 0; -	p->vel[1] = 0; -	p->vel[2] = 0; -	VectorClear( p->accel ); - -	p->rotate = qfalse; - -	p->roll = rand()%179; -	 -	p->alpha = 0.75; - -} - -void CG_OilSlickRemove (centity_t *cent) -{ -	cparticle_t		*p, *next; -	int				id; - -	id = 1.0f; - -	if (!id) -		CG_Printf ("CG_OilSlickRevove NULL id\n"); - -	for (p=active_particles ; p ; p=next) -	{ -		next = p->next; -		 -		if (p->type == P_FLAT_SCALEUP) -		{ -			if (p->snum == id) -			{ -				p->endtime = cg.time + 100; -				p->startfade = p->endtime; -				p->type = P_FLAT_SCALEUP_FADE; - -			} -		} - -	} -} - -qboolean ValidBloodPool (vec3_t start) -{ -#define EXTRUDE_DIST	0.5 - -	vec3_t	angles; -	vec3_t	right, up; -	vec3_t	this_pos, x_pos, center_pos, end_pos; -	float	x, y; -	float	fwidth, fheight; -	trace_t	trace; -	vec3_t	normal; - -	fwidth = 16; -	fheight = 16; - -	VectorSet (normal, 0, 0, 1); - -	vectoangles (normal, angles); -	AngleVectors (angles, NULL, right, up); - -	VectorMA (start, EXTRUDE_DIST, normal, center_pos); - -	for (x= -fwidth/2; x<fwidth; x+= fwidth) -	{ -		VectorMA (center_pos, x, right, x_pos); - -		for (y= -fheight/2; y<fheight; y+= fheight) -		{ -			VectorMA (x_pos, y, up, this_pos); -			VectorMA (this_pos, -EXTRUDE_DIST*2, normal, end_pos); -			 -			CG_Trace (&trace, this_pos, NULL, NULL, end_pos, -1, CONTENTS_SOLID); - -			 -			if (trace.entityNum < (MAX_ENTITIES - 1)) // may only land on world -				return qfalse; - -			if (!(!trace.startsolid && trace.fraction < 1)) -				return qfalse; -		 -		} -	} - -	return qtrue; -} - -void CG_BloodPool (localEntity_t *le, qhandle_t pshader, trace_t *tr) -{	 -	cparticle_t	*p; -	qboolean	legit; -	vec3_t		start; -	float		rndSize; -	 -	if (!pshader) -		CG_Printf ("CG_BloodPool pshader == ZERO!\n"); - -	if (!free_particles) -		return; -	 -	VectorCopy (tr->endpos, start); -	legit = ValidBloodPool (start); - -	if (!legit)  -		return; - -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	 -	p->endtime = cg.time + 3000; -	p->startfade = p->endtime; - -	p->alpha = 1.0; -	p->alphavel = 0; -	p->roll = 0; - -	p->pshader = pshader; - -	rndSize = 0.4 + random()*0.6; - -	p->width = 8*rndSize; -	p->height = 8*rndSize; - -	p->endheight = 16*rndSize; -	p->endwidth = 16*rndSize; -	 -	p->type = P_FLAT_SCALEUP; - -	VectorCopy(start, p->org ); -	 -	p->vel[0] = 0; -	p->vel[1] = 0; -	p->vel[2] = 0; -	VectorClear( p->accel ); - -	p->rotate = qfalse; - -	p->roll = rand()%179; -	 -	p->alpha = 0.75; -	 -	p->color = BLOODRED; -} - -#define NORMALSIZE	16 -#define LARGESIZE	32 - -void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir) -{ -	float	length; -	float	dist; -	float	crittersize; -	vec3_t	angles, forward; -	vec3_t	point; -	cparticle_t	*p; -	int		i; -	 -	dist = 0; - -	length = VectorLength (dir); -	vectoangles (dir, angles); -	AngleVectors (angles, forward, NULL, NULL); - -	crittersize = LARGESIZE; - -	if (length) -		dist = length / crittersize; - -	if (dist < 1) -		dist = 1; - -	VectorCopy (origin, point); - -	for (i=0; i<dist; i++) -	{ -		VectorMA (point, crittersize, forward, point);	 -		 -		if (!free_particles) -			return; - -		p = free_particles; -		free_particles = p->next; -		p->next = active_particles; -		active_particles = p; - -		p->time = cg.time; -		p->alpha = 1.0; -		p->alphavel = 0; -		p->roll = 0; - -		p->pshader = cgs.media.smokePuffShader; - -		p->endtime = cg.time + 350 + (crandom() * 100); -		 -		p->startfade = cg.time; -		 -		p->width = LARGESIZE; -		p->height = LARGESIZE; -		p->endheight = LARGESIZE; -		p->endwidth = LARGESIZE; - -		p->type = P_SMOKE; - -		VectorCopy( origin, p->org ); -		 -		p->vel[0] = 0; -		p->vel[1] = 0; -		p->vel[2] = -1; -		 -		VectorClear( p->accel ); - -		p->rotate = qfalse; - -		p->roll = rand()%179; -		 -		p->color = BLOODRED; -		 -		p->alpha = 0.75; -		 -	} - -	 -} - -void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed) -{ -	cparticle_t	*p; - -	if (!free_particles) -		return; -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	 -	p->endtime = cg.time + duration; -	p->startfade = cg.time + duration/2; -	 -	p->color = EMISIVEFADE; -	p->alpha = 0.4f; -	p->alphavel = 0; - -	p->height = 0.5; -	p->width = 0.5; -	p->endheight = 0.5; -	p->endwidth = 0.5; - -	p->pshader = cgs.media.tracerShader; - -	p->type = P_SMOKE; -	 -	VectorCopy(org, p->org); - -	p->org[0] += (crandom() * x); -	p->org[1] += (crandom() * y); - -	p->vel[0] = vel[0]; -	p->vel[1] = vel[1]; -	p->vel[2] = vel[2]; - -	p->accel[0] = p->accel[1] = p->accel[2] = 0; - -	p->vel[0] += (crandom() * 4); -	p->vel[1] += (crandom() * 4); -	p->vel[2] += (20 + (crandom() * 10)) * speed;	 - -	p->accel[0] = crandom () * 4; -	p->accel[1] = crandom () * 4; -	 -} - -void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) -{ -	float	length; -	float	dist; -	float	crittersize; -	vec3_t	angles, forward; -	vec3_t	point; -	cparticle_t	*p; -	int		i; -	 -	dist = 0; - -	VectorNegate (dir, dir); -	length = VectorLength (dir); -	vectoangles (dir, angles); -	AngleVectors (angles, forward, NULL, NULL); - -	crittersize = LARGESIZE; - -	if (length) -		dist = length / crittersize; - -	if (dist < 1) -		dist = 1; - -	VectorCopy (origin, point); - -	for (i=0; i<dist; i++) -	{ -		VectorMA (point, crittersize, forward, point);	 -				 -		if (!free_particles) -			return; - -		p = free_particles; -		free_particles = p->next; -		p->next = active_particles; -		active_particles = p; - -		p->time = cg.time; -		p->alpha = 5.0; -		p->alphavel = 0; -		p->roll = 0; - -		p->pshader = cgs.media.smokePuffShader; - -		// RF, stay around for long enough to expand and dissipate naturally -		if (length) -			p->endtime = cg.time + 4500 + (crandom() * 3500); -		else -			p->endtime = cg.time + 750 + (crandom() * 500); -		 -		p->startfade = cg.time; -		 -		p->width = LARGESIZE; -		p->height = LARGESIZE; - -		// RF, expand while falling -		p->endheight = LARGESIZE*3.0; -		p->endwidth = LARGESIZE*3.0; - -		if (!length) -		{ -			p->width *= 0.2f; -			p->height *= 0.2f; - -			p->endheight = NORMALSIZE; -			p->endwidth = NORMALSIZE; -		} - -		p->type = P_SMOKE; - -		VectorCopy( point, p->org ); -		 -		p->vel[0] = crandom()*6; -		p->vel[1] = crandom()*6; -		p->vel[2] = random()*20; - -		// RF, add some gravity/randomness -		p->accel[0] = crandom()*3; -		p->accel[1] = crandom()*3; -		p->accel[2] = -PARTICLE_GRAVITY*0.4; - -		VectorClear( p->accel ); - -		p->rotate = qfalse; - -		p->roll = rand()%179; -		 -		p->alpha = 0.75; -		 -	} - -	 -} - -void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha) -{ -	cparticle_t	*p; - -	if (!pshader) -		CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); - -	if (!free_particles) -		return; - -	p = free_particles; -	free_particles = p->next; -	p->next = active_particles; -	active_particles = p; -	p->time = cg.time; -	p->alpha = 1.0; -	p->alphavel = 0; -	p->roll = rand()%179; - -	p->pshader = pshader; - -	if (duration > 0) -		p->endtime = cg.time + duration; -	else -		p->endtime = duration; - -	p->startfade = cg.time; - -	p->width = size; -	p->height = size; - -	p->endheight = size; -	p->endwidth = size; - -	p->type = P_SPRITE; - -	VectorCopy( origin, p->org ); - -	p->rotate = qfalse; -} diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c index 2ee0c2e5..6843c217 100644 --- a/src/cgame/cg_servercmds.c +++ b/src/cgame/cg_servercmds.c @@ -459,7 +459,10 @@ static void CG_MapRestart( void ) {    CG_InitLocalEntities();    CG_InitMarkPolys(); -  CG_ClearParticles (); + +	// Ridah, trails +	CG_ClearTrails (); +	// done.    // make sure the "3 frags left" warnings play again    cg.fraglimitWarnings = 0; diff --git a/src/cgame/cg_trails.c b/src/cgame/cg_trails.c new file mode 100644 index 00000000..9a2bc8a1 --- /dev/null +++ b/src/cgame/cg_trails.c @@ -0,0 +1,728 @@ +// Ridah, cg_trails.c - draws a trail using multiple junction points + +#include "cg_local.h" + +typedef struct trailJunc_s +{ +	struct trailJunc_s *nextGlobal, *prevGlobal;	// next junction in the global list it is in (free or used) +	struct trailJunc_s *nextJunc;					// next junction in the trail +	struct trailJunc_s *nextHead, *prevHead;		// next head junc in the world + +	qboolean	inuse, freed; +	int			ownerIndex; +	qhandle_t	shader; + +	int		sType; +	int		flags; +	float	sTex; +	vec3_t	pos; +	int		spawnTime, endTime; +	float	alphaStart, alphaEnd; +	vec3_t	colorStart, colorEnd; +	float	widthStart, widthEnd; + +	// current settings +	float	alpha; +	float	width; +	vec3_t	color; + +} trailJunc_t; + +#define MAX_TRAILJUNCS	4096 + +trailJunc_t trailJuncs[MAX_TRAILJUNCS]; +trailJunc_t *freeTrails, *activeTrails; +trailJunc_t	*headTrails; + +qboolean initTrails = qfalse; + +int numTrailsInuse; + +/* +=============== +CG_ClearTrails +=============== +*/ +void CG_ClearTrails (void) +{ +	int		i; + +	memset( trailJuncs, 0, sizeof(trailJunc_t) * MAX_TRAILJUNCS ); + +	freeTrails = trailJuncs; +	activeTrails = NULL; +	headTrails = NULL; + +	for (i=0 ;i<MAX_TRAILJUNCS ; i++) +	{ +		trailJuncs[i].nextGlobal = &trailJuncs[i+1]; + +		if (i>0) +			trailJuncs[i].prevGlobal = &trailJuncs[i-1]; +		else +			trailJuncs[i].prevGlobal = NULL; + +		trailJuncs[i].inuse = qfalse; +	} +	trailJuncs[MAX_TRAILJUNCS-1].nextGlobal = NULL; + +	initTrails = qtrue; +	numTrailsInuse = 0; +} + +/* +=============== +CG_SpawnTrailJunc +=============== +*/ +trailJunc_t *CG_SpawnTrailJunc( trailJunc_t *headJunc ) +{ +	trailJunc_t	*j; + +	if (!freeTrails) +		return NULL; + +	if ( cg_paused.integer ) +		return NULL; + +	// select the first free trail, and remove it from the list +	j = freeTrails; +	freeTrails = j->nextGlobal; +	if (freeTrails) +		freeTrails->prevGlobal = NULL; + +	j->nextGlobal = activeTrails; +	if (activeTrails) +		activeTrails->prevGlobal = j; +	activeTrails = j; +	j->prevGlobal = NULL; +	j->inuse = qtrue; +	j->freed = qfalse; + +	// if this owner has a headJunc, add us to the start +	if (headJunc) { +		// remove the headJunc from the list of heads +		if (headJunc == headTrails) { +			headTrails = headJunc->nextHead; +			if (headTrails) +				headTrails->prevHead = NULL; +		} else { +			if (headJunc->nextHead) +				headJunc->nextHead->prevHead = headJunc->prevHead; +			if (headJunc->prevHead) +				headJunc->prevHead->nextHead = headJunc->nextHead; +		} +		headJunc->prevHead = NULL; +		headJunc->nextHead = NULL; +	} +	// make us the headTrail +	if (headTrails) +		headTrails->prevHead = j; +	j->nextHead = headTrails; +	j->prevHead = NULL; +	headTrails = j; + +	j->nextJunc = headJunc;	// if headJunc is NULL, then we'll just be the end of the list + +	numTrailsInuse++; + +	// debugging +//	CG_Printf( "NumTrails: %i\n", numTrailsInuse ); + +	return j; +} + + +/* +=============== +CG_AddTrailJunc + +  returns the index of the trail junction created + +  Used for generic trails +=============== +*/ +int CG_AddTrailJunc(int headJuncIndex, qhandle_t shader, int spawnTime, int sType, vec3_t pos, int trailLife, float alphaStart, float alphaEnd, float startWidth, float endWidth, int flags, vec3_t colorStart, vec3_t colorEnd, float sRatio, float animSpeed) +{ +	trailJunc_t	*j, *headJunc; + +	if (headJuncIndex > 0) { +		headJunc = &trailJuncs[headJuncIndex-1]; + +		if (!headJunc->inuse) +			headJunc = NULL; +	} +	else +		headJunc = NULL; + +	j = CG_SpawnTrailJunc(headJunc); +	if (!j) { +//		CG_Printf("couldnt spawn trail junc\n"); +		return 0; +	} + +	if (alphaStart > 1.0) alphaStart = 1.0; +	if (alphaStart < 0.0) alphaStart = 0.0; +	if (alphaEnd > 1.0) alphaEnd = 1.0; +	if (alphaEnd < 0.0) alphaEnd = 0.0; + +	// setup the trail junction +	j->shader = shader; +	j->sType = sType; +	VectorCopy( pos, j->pos ); +	j->flags = flags; + +	j->spawnTime = spawnTime; +	j->endTime = spawnTime + trailLife; + +	VectorCopy( colorStart, j->colorStart ); +	VectorCopy( colorEnd, j->colorEnd ); + +	j->alphaStart = alphaStart; +	j->alphaEnd = alphaEnd; + +	j->widthStart = startWidth; +	j->widthEnd = endWidth; + +	if (sType == STYPE_REPEAT) { +		if (headJunc) { +			j->sTex = headJunc->sTex + ((Distance( headJunc->pos, pos ) / sRatio) / j->widthEnd); +		} else { +			// FIXME: need a way to specify offset timing +			j->sTex = (animSpeed * (1.0 - ((float)(cg.time%1000) / 1000.0))) / (sRatio); +//			j->sTex = 0; +		} +	} + +	return ((int)(j - trailJuncs) + 1); +} + +/* +=============== +CG_AddSparkJunc + +  returns the index of the trail junction created +=============== +*/ +int CG_AddSparkJunc(int headJuncIndex, qhandle_t shader, vec3_t pos, int trailLife, float alphaStart, float alphaEnd, float startWidth, float endWidth) +{ +	trailJunc_t	*j, *headJunc; + +	if (headJuncIndex > 0) { +		headJunc = &trailJuncs[headJuncIndex-1]; + +		if (!headJunc->inuse) +			headJunc = NULL; +	} +	else +		headJunc = NULL; + +	j = CG_SpawnTrailJunc(headJunc); +	if (!j) +		return 0; + +	// setup the trail junction +	j->shader = shader; +	j->sType = STYPE_STRETCH; +	VectorCopy( pos, j->pos ); +	j->flags = TJFL_NOCULL;		// don't worry about fading up close + +	j->spawnTime = cg.time; +	j->endTime = cg.time + trailLife; + +	VectorSet(j->colorStart, 1.0, 0.8 + 0.2 * alphaStart, 0.4 + 0.4 * alphaStart); +	VectorSet(j->colorEnd, 1.0, 0.8 + 0.2 * alphaEnd, 0.4 + 0.4 * alphaEnd); +//	VectorScale( j->colorStart, alphaStart, j->colorStart ); +//	VectorScale( j->colorEnd, alphaEnd, j->colorEnd ); + +	j->alphaStart = alphaStart*2; +	j->alphaEnd = alphaEnd*2; +//	j->alphaStart = 1.0; +//	j->alphaEnd = 1.0; + +	j->widthStart = startWidth; +	j->widthEnd = endWidth; + +	return ((int)(j - trailJuncs) + 1); +} + +/* +=============== +CG_AddSmokeJunc + +  returns the index of the trail junction created +=============== +*/ +int CG_AddSmokeJunc(int headJuncIndex, qhandle_t shader, vec3_t pos, int trailLife, float alpha, float startWidth, float endWidth) +{ +#define	ST_RATIO	4.0		// sprite image: width / height +	trailJunc_t	*j, *headJunc; + +	if (headJuncIndex > 0) { +		headJunc = &trailJuncs[headJuncIndex-1]; + +		if (!headJunc->inuse) +			headJunc = NULL; +	} +	else +		headJunc = NULL; + +	j = CG_SpawnTrailJunc(headJunc); +	if (!j) +		return 0; + +	// setup the trail junction +	j->shader = shader; +	j->sType = STYPE_REPEAT; +	VectorCopy( pos, j->pos ); +	j->flags = TJFL_FADEIN; + +	j->spawnTime = cg.time; +	j->endTime = cg.time + trailLife; + +	// VectorSet(j->colorStart, 0.2, 0.2, 0.2); +	VectorSet(j->colorStart, 0.0, 0.0, 0.0); +	// VectorSet(j->colorEnd, 0.1, 0.1, 0.1); +	VectorSet(j->colorEnd, 0.0, 0.0, 0.0); + +	j->alphaStart = alpha; +	j->alphaEnd = 0.0; + +	j->widthStart = startWidth; +	j->widthEnd = endWidth; + +	if (headJunc) { +		j->sTex = headJunc->sTex + ((Distance( headJunc->pos, pos ) / ST_RATIO) / j->widthEnd); +	} else { +		// first junction, so this will become the "tail" very soon, make it fade out +		j->sTex = 0; +		j->alphaStart = 0.0; +		j->alphaEnd = 0.0; +	} + +	return ((int)(j - trailJuncs) + 1); +} + +void CG_KillTrail( trailJunc_t *t ); + +/* +=========== +CG_FreeTrailJunc +=========== +*/ +void CG_FreeTrailJunc( trailJunc_t *junc ) +{ +	// kill any juncs after us, so they aren't left hanging +	if (junc->nextJunc) +		CG_KillTrail( junc ); + +	// make it non-active +	junc->inuse = qfalse; +	junc->freed = qtrue; +	if (junc->nextGlobal) +		junc->nextGlobal->prevGlobal = junc->prevGlobal; +	if (junc->prevGlobal) +		junc->prevGlobal->nextGlobal = junc->nextGlobal; +	if (junc == activeTrails) +		activeTrails = junc->nextGlobal; + +	// if it's a head, remove it +	if (junc == headTrails) +		headTrails = junc->nextHead; +	if (junc->nextHead) +		junc->nextHead->prevHead = junc->prevHead; +	if (junc->prevHead) +		junc->prevHead->nextHead = junc->nextHead; +	junc->nextHead = NULL; +	junc->prevHead = NULL; + +	// stick it in the free list +	junc->prevGlobal = NULL; +	junc->nextGlobal = freeTrails; +	if (freeTrails) +		freeTrails->prevGlobal = junc; +	freeTrails = junc; + +	numTrailsInuse--; +} + +/* +=========== +CG_KillTrail +=========== +*/ +void CG_KillTrail( trailJunc_t *t ) +{ +	trailJunc_t	*next; + +	next = t->nextJunc; + +	// kill the trail here +	t->nextJunc = NULL; + +	if (next) +		CG_FreeTrailJunc( next ); +} + +/* +============== +CG_AddTrailToScene + +  TODO: this can do with some major optimization +============== +*/ +static vec3_t vforward, vright, vup; + +//TA: staticised to please QVM +	#define	MAX_TRAIL_VERTS		2048 +static polyVert_t verts[MAX_TRAIL_VERTS]; +static polyVert_t outVerts[MAX_TRAIL_VERTS*3]; + +void CG_AddTrailToScene( trailJunc_t *trail, int iteration, int numJuncs ) +{ +	int		k, i, n, l, numOutVerts; +	polyVert_t	mid; +	float	mod[4]; +	float	sInc = 0.0f, s = 0.0f; // TTimo: init +	trailJunc_t	*j, *jNext; +	vec3_t	fwd, up, p, v; +	// clipping vars +	#define	TRAIL_FADE_CLOSE_DIST	64.0 +	#define	TRAIL_FADE_FAR_SCALE	4.0 +	vec3_t	viewProj; +	float	viewDist, fadeAlpha; + +	// add spark shader at head position +	if (trail->flags & TJFL_SPARKHEADFLARE) { +		j = trail; +		VectorCopy( j->pos, p ); +		VectorMA (p, -j->width*2, vup, p);	 +		VectorMA (p, -j->width*2, vright, p);	 +		VectorCopy (p, verts[0].xyz);	 +		verts[0].st[0] = 0;	 +		verts[0].st[1] = 0;	 +		verts[0].modulate[0] = 255;	 +		verts[0].modulate[1] = 255;	 +		verts[0].modulate[2] = 255;	 +		verts[0].modulate[3] = (unsigned char)(j->alpha*255.0); + +		VectorCopy( j->pos, p ); +		VectorMA (p, -j->width*2, vup, p);	 +		VectorMA (p, j->width*2, vright, p);	 +		VectorCopy (p, verts[1].xyz);	 +		verts[1].st[0] = 0;	 +		verts[1].st[1] = 1;	 +		verts[1].modulate[0] = 255;	 +		verts[1].modulate[1] = 255;	 +		verts[1].modulate[2] = 255;	 +		verts[1].modulate[3] = (unsigned char)(j->alpha*255.0);	 + +		VectorCopy( j->pos, p ); +		VectorMA (p, j->width*2, vup, p);	 +		VectorMA (p, j->width*2, vright, p);	 +		VectorCopy (p, verts[2].xyz);	 +		verts[2].st[0] = 1;	 +		verts[2].st[1] = 1;	 +		verts[2].modulate[0] = 255;	 +		verts[2].modulate[1] = 255;	 +		verts[2].modulate[2] = 255;	 +		verts[2].modulate[3] = (unsigned char)(j->alpha*255.0);	 + +		VectorCopy( j->pos, p ); +		VectorMA (p,  j->width*2, vup, p);	 +		VectorMA (p, -j->width*2, vright, p);	 +		VectorCopy (p, verts[3].xyz);	 +		verts[3].st[0] = 1;	 +		verts[3].st[1] = 0;	 +		verts[3].modulate[0] = 255;	 +		verts[3].modulate[1] = 255;	 +		verts[3].modulate[2] = 255;	 +		verts[3].modulate[3] = (unsigned char)(j->alpha*255.0);	 + +		trap_R_AddPolyToScene( cgs.media.sparkFlareShader, 4, verts ); +	} + +//	if (trail->flags & TJFL_CROSSOVER && iteration < 1) { +//		iteration = 1; +//	} + +	if (!numJuncs) { +		// first count the number of juncs in the trail +		j = trail; +		numJuncs = 0; +		sInc = 0; +		while (j) { +			numJuncs++; + +			// check for a dead next junc +			if (!j->inuse && j->nextJunc && !j->nextJunc->inuse) { +				CG_KillTrail( j ); +			} else if (j->nextJunc && j->nextJunc->freed) { +				// not sure how this can happen, but it does, and causes infinite loops +				j->nextJunc = NULL; +			} + +			if (j->nextJunc) +				sInc += VectorDistance( j->nextJunc->pos, j->pos ); + +			j = j->nextJunc; +		} +	} + +	if (numJuncs < 2) { +		return; +	} + +	if (trail->sType == STYPE_STRETCH) { +		//sInc = ((1.0 - 0.1) / (float)(numJuncs));	// hack, the end of funnel shows a bit of the start (looping) +		s = 0.05; +		//s = 0.05; +	} else if (trail->sType == STYPE_REPEAT) { +		s = trail->sTex; +	} + +	// now traverse the list +	j = trail; +	jNext = j->nextJunc; +	i = 0; +	while (jNext) { + +		// first get the directional vectors to the next junc +		VectorSubtract( jNext->pos, j->pos, fwd ); +		GetPerpendicularViewVector( cg.refdef.vieworg, j->pos, jNext->pos, up ); + +		// if it's a crossover, draw it twice +		if (j->flags & TJFL_CROSSOVER) { +			if (iteration > 0) { +				ProjectPointOntoVector( cg.refdef.vieworg, j->pos, jNext->pos, viewProj ); +				VectorSubtract( cg.refdef.vieworg, viewProj, v ); +				VectorNormalize( v ); + +				if (iteration == 1) { +					VectorMA( up, 0.3, v, up ); +				} else { +					VectorMA( up, -0.3, v, up ); +				} +				VectorNormalize( up ); +			} +		} +		// do fading when moving towards the projection point onto the trail segment vector +		else if (!(j->flags & TJFL_NOCULL) && (j->widthEnd > 4 || jNext->widthEnd > 4)) { +			ProjectPointOntoVector( cg.refdef.vieworg, j->pos, jNext->pos, viewProj ); +			viewDist = Distance( viewProj, cg.refdef.vieworg ); +			if (viewDist < (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE)) { +				if (viewDist < TRAIL_FADE_CLOSE_DIST) { +					fadeAlpha = 0.0; +				} else { +					fadeAlpha = (viewDist - TRAIL_FADE_CLOSE_DIST) / (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE); +				} +				if (fadeAlpha < j->alpha) { +					j->alpha = fadeAlpha; +				} +				if (fadeAlpha < jNext->alpha) { +					jNext->alpha = fadeAlpha; +				} +			} +		} + +		// now output the QUAD for this segment + +		// 1 ---- +		VectorMA( j->pos, 0.5*j->width, up, p ); +		VectorCopy( p, verts[i].xyz ); +		verts[i].st[0] = s; +		verts[i].st[1] = 1.0; +		for (k=0; k<3; k++) +			verts[i].modulate[k] = (unsigned char)(j->color[k]*255.0); +		verts[i].modulate[3] = (unsigned char)(j->alpha*255.0); + +		// blend this with the previous junc +		if (j != trail) { +			VectorAdd( verts[i].xyz, verts[i-1].xyz, verts[i].xyz ); +			VectorScale( verts[i].xyz, 0.5, verts[i].xyz ); +			VectorCopy( verts[i].xyz, verts[i-1].xyz ); +		} else if (j->flags & TJFL_FADEIN) { +			verts[i].modulate[3] = 0;	// fade in +		} + +		i++; + +		// 2 ---- +		VectorMA( p, -1*j->width, up, p ); +		VectorCopy( p, verts[i].xyz ); +		verts[i].st[0] = s; +		verts[i].st[1] = 0.0; +		for (k=0; k<3; k++) +			verts[i].modulate[k] = (unsigned char)(j->color[k]*255.0); +		verts[i].modulate[3] = (unsigned char)(j->alpha*255.0); + +		// blend this with the previous junc +		if (j != trail) { +			VectorAdd( verts[i].xyz, verts[i-3].xyz, verts[i].xyz ); +			VectorScale( verts[i].xyz, 0.5, verts[i].xyz ); +			VectorCopy( verts[i].xyz, verts[i-3].xyz ); +		} else if (j->flags & TJFL_FADEIN) { +			verts[i].modulate[3] = 0;	// fade in +		} + +		i++; + +		if (trail->sType == STYPE_REPEAT) +			s = jNext->sTex; +		else { +			//s += sInc; +			s += VectorDistance( j->pos, jNext->pos ) / sInc; +			if (s > 1.0) s = 1.0; +		} + +		// 3 ---- +		VectorMA( jNext->pos, -0.5*jNext->width, up, p ); +		VectorCopy( p, verts[i].xyz ); +		verts[i].st[0] = s; +		verts[i].st[1] = 0.0; +		for (k=0; k<3; k++) +			verts[i].modulate[k] = (unsigned char)(jNext->color[k]*255.0); +		verts[i].modulate[3] = (unsigned char)(jNext->alpha*255.0); +		i++; + +		// 4 ---- +		VectorMA( p, jNext->width, up, p ); +		VectorCopy( p, verts[i].xyz ); +		verts[i].st[0] = s; +		verts[i].st[1] = 1.0; +		for (k=0; k<3; k++) +			verts[i].modulate[k] = (unsigned char)(jNext->color[k]*255.0); +		verts[i].modulate[3] = (unsigned char)(jNext->alpha*255.0); +		i++; + +		if (i+4 > MAX_TRAIL_VERTS) +			break; + +		j = jNext; +		jNext = j->nextJunc; +	} + +	if (trail->flags & TJFL_FIXDISTORT) { +		// build the list of outVerts, by dividing up the QUAD's into 4 Tri's each, so as to allow +		//	any shaped (convex) Quad without bilinear distortion +		for (k=0, numOutVerts=0; k<i; k+=4) { +			VectorCopy(verts[k].xyz, mid.xyz); +			mid.st[0] = verts[k].st[0]; +			mid.st[1] = verts[k].st[1]; +			for (l=0; l<4; l++) { +				mod[l] = (float)verts[k].modulate[l]; +			} +			for (n=1; n<4; n++) { +				VectorAdd( verts[k+n].xyz, mid.xyz, mid.xyz ); +				mid.st[0] += verts[k+n].st[0]; +				mid.st[1] += verts[k+n].st[1]; +				for (l=0; l<4; l++) { +					mod[l] += (float)verts[k+n].modulate[l]; +				} +			} +			VectorScale( mid.xyz, 0.25, mid.xyz ); +			mid.st[0] *= 0.25; +			mid.st[1] *= 0.25; +			for (l=0; l<4; l++) { +				mid.modulate[l] = (unsigned char)(mod[l]/4.0); +			} + +			// now output the tri's +			for (n=0; n<4; n++) { +				outVerts[numOutVerts++] = verts[k+n]; +				outVerts[numOutVerts++] = mid; +				if (n<3) { +					outVerts[numOutVerts++] = verts[k+n+1]; +				} else { +					outVerts[numOutVerts++] = verts[k]; +				} +			} +			 +		} + +		if (!(trail->flags & TJFL_NOPOLYMERGE)) { +			trap_R_AddPolysToScene( trail->shader, 3, &outVerts[0], numOutVerts/3 ); +		} else { +			int k; +			for (k=0; k<numOutVerts/3; k++) { +				trap_R_AddPolyToScene( trail->shader, 3, &outVerts[k*3] ); +			} +		} +	} +	else +	{ +		// send the polygons +		// FIXME: is it possible to send a GL_STRIP here? We are actually sending 2x the verts we really need to +		if (!(trail->flags & TJFL_NOPOLYMERGE)) { +			trap_R_AddPolysToScene( trail->shader, 4, &verts[0], i/4 ); +		} else { +			int k; +			for (k=0; k<i/4; k++) { +				trap_R_AddPolyToScene( trail->shader, 4, &verts[k*4] ); +			} +		} +	} + +	// do we need to make another pass? +	if (trail->flags & TJFL_CROSSOVER) { +		if (iteration < 2) { +			CG_AddTrailToScene( trail, iteration + 1, numJuncs ); +		} +	} + +} + +/* +=============== +CG_AddTrails +=============== +*/ +void CG_AddTrails(void) +{ +	float	lifeFrac; +	trailJunc_t	*j, *jNext; + +	if (!initTrails) { +		CG_ClearTrails(); +	} + +	//AngleVectors( cg.snap->ps.viewangles, vforward, vright, vup ); +	VectorCopy( cg.refdef.viewaxis[0], vforward ); +	VectorCopy( cg.refdef.viewaxis[1], vright ); +	VectorCopy( cg.refdef.viewaxis[2], vup ); + +	// update the settings for each junc +	j = activeTrails; +	while (j) { +		lifeFrac = (float)(cg.time - j->spawnTime) / (float)(j->endTime - j->spawnTime); +		if (lifeFrac >= 1.0) { +			j->inuse = qfalse;			// flag it as dead +			j->width = j->widthEnd; +			j->alpha = j->alphaEnd; +			if (j->alpha > 1.0)	j->alpha = 1.0; +			else if (j->alpha < 0.0) j->alpha = 0.0; +			VectorCopy( j->colorEnd, j->color ); +		} else { +			j->width = j->widthStart + (j->widthEnd - j->widthStart) * lifeFrac; +			j->alpha = j->alphaStart + (j->alphaEnd - j->alphaStart) * lifeFrac; +			if (j->alpha > 1.0) j->alpha = 1.0; +			else if (j->alpha < 0.0) j->alpha = 0.0; +			VectorSubtract( j->colorEnd, j->colorStart, j->color ); +			VectorMA( j->colorStart, lifeFrac, j->color, j->color ); +		} + +		j = j->nextGlobal; +	} + +	// draw the trailHeads +	j = headTrails; +	while (j) { +		jNext = j->nextHead;		// in case it gets removed +		if (!j->inuse) { +			CG_FreeTrailJunc(j); +		} else { +			CG_AddTrailToScene( j, 0, 0 ); +		} +		j = jNext; +	} +} diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c index 489faa37..4d63074f 100644 --- a/src/cgame/cg_view.c +++ b/src/cgame/cg_view.c @@ -1152,8 +1152,10 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo    if ( !cg.hyperspace ) {      CG_AddPacketEntities();     // adter calcViewValues, so predicted player state is correct      CG_AddMarks(); -    CG_AddParticles ();      CG_AddLocalEntities(); + +    //TA: wolf trails stuff +		CG_AddTrails( );		// this must come last, so the trails dropped this frame get drawn    }    CG_AddViewWeapon( &cg.predictedPlayerState ); diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index 7245a870..0c24001a 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -288,7 +288,7 @@ void CG_TeslaTrail( vec3_t start, vec3_t end )    localEntity_t *le;    refEntity_t   *re; -  start[ 2 ] += 12; //nudge up a bit so the bolt comes from the sphere +/*  start[ 2 ] += 12; //nudge up a bit so the bolt comes from the sphere    //add a bunch of bolt segments    le = CG_AllocLocalEntity(); @@ -316,7 +316,21 @@ void CG_TeslaTrail( vec3_t start, vec3_t end )    le->color[2] = 1.0f;    le->color[3] = 1.0f; -  AxisClear( re->axis ); +  AxisClear( re->axis );*/ +   +  start[ 2 ] += 12; //nudge up a bit so the bolt comes from the sphere + +  //add a bunch of bolt segments +  le = CG_AllocLocalEntity(); +  re = &le->refEntity; + +  le->leType = LE_LIGHTNING_BOLT; +  le->startTime = cg.time; +  le->endTime = cg.time + cg_teslaTrailTime.value; +  le->lifeRate = 1.0 / ( le->endTime - le->startTime ); + +  VectorCopy( start, re->origin ); +  VectorCopy( end, re->oldorigin );  }  /*  | 
