Esempio n. 1
0
static void CG_AddSpawner( localEntity_t *le ) 
{
	refEntity_t	*re;
	vec3_t		dir;
	trace_t		trace;

	re = &le->refEntity;
	if (le->leFlags & LEF_MOVE)
	{
		// kef -- do these two lines _before_ copying origin into oldorigin
		VectorSubtract(re->oldorigin, re->origin, dir);
		VectorNormalize(dir);

		VectorCopy(re->origin, re->oldorigin);
		BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );

		if (le->leFlags & LEF_USE_COLLISION)
		{
			// trace a line from previous position to new position
			CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, -1, CONTENTS_SOLID );

			if ( trace.fraction != 1.0 ) 
			{	// Hit something.
				// if it is in a nodrop zone, remove it
				// this keeps gibs from waiting at the bottom of pits of death
				// and floating levels
				if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
					CG_FreeLocalEntity( le );
					return;
				}

				// reflect the velocity on the trace plane
				CG_ReflectVelocity( le, &trace );
			}
			VectorSubtract(re->oldorigin, re->origin, dir);
			VectorNormalize(dir);
		}
	}

	// kef -- here's where I, in my infinite wisdom, have decided to emulate the singleplayer
	//particle think function
	if (cg.time < le->data.spawner.nextthink)
	{
		return;
	}
	le->data.spawner.nextthink = cg.time + (le->data.spawner.delay + 
		(le->data.spawner.delay*flrandom(-le->data.spawner.variance,le->data.spawner.variance)));

	if (le->data.spawner.thinkFn)
	{
		le->data.spawner.thinkFn(le);
	}
	if (le->data.spawner.dontDie)
	{
		le->endTime = le->endTime + 10000;
	}
}
Esempio n. 2
0
/*
================
CG_AddBloodElements
================
*/
void CG_AddBloodElements( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;
	float	time;
	float	lifeFrac;

	time = (float)(cg.time - cg.frametime);

	while (1) {
		// calculate new position
		BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

		// trace a line from previous position to new position
		CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, MASK_SHOT );

		// if stuck, kill it
		if (trace.startsolid) {
			// HACK, some walls screw up, so just pass through if starting in a solid
			VectorCopy( newOrigin, trace.endpos );
			trace.fraction = 1.0;
		}

		// moved some distance
		VectorCopy( trace.endpos, le->refEntity.origin );
		time += cg.frametime * trace.fraction;

		lifeFrac = (float)(cg.time - le->startTime) / (float)(le->endTime - le->startTime);

		// add a trail
		le->headJuncIndex = CG_AddSparkJunc( le->headJuncIndex,
									cgs.media.bloodTrailShader,
									le->refEntity.origin,
									200,
									1.0 - lifeFrac,	// start alpha
									1.0 - lifeFrac,	// end alpha
									3.0,
									5.0 );

		if (trace.fraction < 1.0) {
			// reflect the velocity on the trace plane
			CG_ReflectVelocity( le, &trace );

			// TODO: spawn a blood decal here?

			// the intersection is a fraction of the frametime
			le->pos.trTime = (int)time;
		}

		if ( trace.fraction == 1.0 || time >= (float)cg.time ) {
			return;
		}
	}

}
Esempio n. 3
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;

	if (le->forceAlpha)
	{
		le->refEntity.renderfx |= RF_FORCE_ENT_ALPHA;
		le->refEntity.shaderRGBA[3] = le->forceAlpha;
	}

	if ( le->pos.trType == TR_STATIONARY ) {
		// sink into the ground if near the removal time
		int		t;
		float	t_e;
		
		t = le->endTime - cg.time;
		if ( t < (SINK_TIME*2) ) {
			le->refEntity.renderfx |= RF_FORCE_ENT_ALPHA;
			t_e = (float)((float)(le->endTime - cg.time)/(SINK_TIME*2));
			t_e = (int)((t_e)*255);

			if (t_e > 255)
			{
				t_e = 255;
			}
			if (t_e < 1)
			{
				t_e = 1;
			}

			if (le->refEntity.shaderRGBA[3] && t_e > le->refEntity.shaderRGBA[3])
			{
				t_e = le->refEntity.shaderRGBA[3];
			}

			le->refEntity.shaderRGBA[3] = t_e;

			trap->R_AddRefEntityToScene( &le->refEntity );
		} else {
			trap->R_AddRefEntityToScene( &le->refEntity );
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
			ScaleModelAxis(&le->refEntity);
		}

		trap->R_AddRefEntityToScene( &le->refEntity );

		// add a blood trail
		if ( le->leBounceSoundType == LEBS_BLOOD ) {
			CG_BloodTrail( le );
		}

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( trap->CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	if (!trace.startsolid)
	{
		// leave a mark
		CG_FragmentBounceMark( le, &trace );

		// do a bouncy sound
		CG_FragmentBounceSound( le, &trace );

		if (le->bounceSound)
		{ //specified bounce sound (debris)
			trap->S_StartSound(le->pos.trBase, ENTITYNUM_WORLD, CHAN_AUTO, le->bounceSound);
		}

		// reflect the velocity on the trace plane
		CG_ReflectVelocity( le, &trace );

		trap->R_AddRefEntityToScene( &le->refEntity );
	}
}
Esempio n. 4
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) 
{
	vec3_t	newOrigin;
	trace_t	trace;
	// used to sink into the ground, but it looks better to maybe just fade them out
	int		t;
	
	t = le->endTime - cg.time;

	if ( t < FRAG_FADE_TIME ) 
	{
		le->refEntity.renderfx |= RF_ALPHA_FADE;
		le->refEntity.shaderRGBA[0] = le->refEntity.shaderRGBA[1] = le->refEntity.shaderRGBA[2] = 255;
		le->refEntity.shaderRGBA[3] = ((float)t / FRAG_FADE_TIME) * 255.0f;
	}

	if ( le->pos.trType == TR_STATIONARY ) 
	{
		if ( !(cgi_CM_PointContents( le->refEntity.origin, 0 ) & CONTENTS_SOLID )) 
		{
			// thing is no longer in solid, so let gravity take it back
			VectorCopy( le->refEntity.origin, le->pos.trBase );
			VectorClear( le->pos.trDelta );
			le->pos.trTime = cg.time;
			le->pos.trType = TR_GRAVITY;
		}

		cgi_R_AddRefEntityToScene( &le->refEntity );

		return;
	}

	// calculate new position
	EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
	VectorCopy( newOrigin, le->refEntity.lightingOrigin );
	
	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, le->ownerGentNum, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
			for(int k = 0; k < 3; k++)
			{
				VectorScale(le->refEntity.axis[k], le->radius, le->refEntity.axis[k]);
			}

		}

		cgi_R_AddRefEntityToScene( &le->refEntity );

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( cgi_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) 
	{
		CG_FreeLocalEntity( le );
		return;
	}

	// do a bouncy sound
	CG_FragmentBounceSound( le, &trace );

	// reflect the velocity on the trace plane
	CG_ReflectVelocity( le, &trace );
	//FIXME: if LEF_TUMBLE, change avelocity too?

	cgi_R_AddRefEntityToScene( &le->refEntity );
}
Esempio n. 5
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;

	if ( le->pos.trType == TR_STATIONARY ) {
		// sink into the ground if near the removal time
		int		t;
		float	oldZ;
		
		t = le->endTime - cg.time;
		if ( t < SINK_TIME ) {
			// we must use an explicit lighting origin, otherwise the
			// lighting would be lost as soon as the origin went
			// into the ground
			VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
			le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
			oldZ = le->refEntity.origin[2];
			le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
			CG_AddRefEntityWithMinLight( &le->refEntity );
			le->refEntity.origin[2] = oldZ;
		} else {
			CG_AddRefEntityWithMinLight( &le->refEntity );
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
		}

		CG_AddRefEntityWithMinLight( &le->refEntity );

		// add a blood trail
		if ( le->leBounceSoundType == LEBS_BLOOD ) {
			CG_BloodTrail( le );
		}

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( CG_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// leave a mark
	CG_FragmentBounceMark( le, &trace );

	// do a bouncy sound
	CG_FragmentBounceSound( le, &trace );

	// reflect the velocity on the trace plane
	CG_ReflectVelocity( le, &trace );

	CG_AddRefEntityWithMinLight( &le->refEntity );
}
Esempio n. 6
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;
	refEntity_t		*re;
	float	flameAlpha = 0.0; // TTimo: init
	vec3_t	flameDir;
	qboolean	hasFlame = qfalse;
	int i;

	// Ridah
	re = &le->refEntity;
	if (!re->fadeStartTime || re->fadeEndTime < le->endTime) {
		if (le->endTime - cg.time > 5000) {
			re->fadeStartTime = le->endTime - 5000;
		} else {
			re->fadeStartTime = le->endTime - 1000;
		}
		re->fadeEndTime = le->endTime;
	}

	// Ridah, flaming gibs
	if (le->onFireStart && (le->onFireStart < cg.time && le->onFireEnd > cg.time)) {
		hasFlame = qtrue;
		// calc the alpha
		flameAlpha = 1.0 - ((float)(cg.time - le->onFireStart)/(float)(le->onFireEnd - le->onFireStart));
		if (flameAlpha < 0.0) flameAlpha = 0.0;
		if (flameAlpha > 1.0) flameAlpha = 1.0;
		trap_S_AddLoopingSound( -1, le->refEntity.origin, vec3_origin, cgs.media.flameCrackSound, (int)(20.0*flameAlpha) );
	}

//----(SA)	added
	if(le->leFlags & LEF_SMOKING) {
		float		alpha;
		refEntity_t	flash;

		// create a little less smoke

		//	TODO: FIXME: this is not quite right, because it'll become fps dependant - in a bad way.
		//		the slower the fps, the /more/ smoke there'll be, probably driving the fps lower.
		if(!(rand()%5)) {
			alpha = 1.0 - ((float)(cg.time - le->startTime)/(float)(le->endTime - le->startTime));
			alpha *= 0.25f;
			memset (&flash, 0, sizeof (flash));
			CG_PositionEntityOnTag( &flash, &le->refEntity, "tag_flash", 0, NULL);
			CG_ParticleImpactSmokePuffExtended(cgs.media.smokeParticleShader, flash.origin, 1000, 8, 20, 20, alpha);
		}
	}
//----(SA)	end

	if ( le->pos.trType == TR_STATIONARY ) {
		int		t;

		// Ridah, add the flame
		if (hasFlame) {
			refEntity_t backupEnt;

			backupEnt = le->refEntity;

			VectorClear( flameDir );
			flameDir[2] = 1;

			le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha);
			VectorCopy( flameDir, le->refEntity.fireRiseDir );
			le->refEntity.customShader = cgs.media.onFireShader;
			trap_R_AddRefEntityToScene( &le->refEntity );
			le->refEntity.customShader = cgs.media.onFireShader2;
			trap_R_AddRefEntityToScene( &le->refEntity );

			le->refEntity = backupEnt;
		}
		
		t = le->endTime - cg.time;
		trap_R_AddRefEntityToScene( &le->refEntity );

		return;

	} else if ( le->pos.trType == TR_GRAVITY_PAUSED ) {
		int		t;

		// Ridah, add the flame
		if (hasFlame) {
			refEntity_t backupEnt;

			backupEnt = le->refEntity;

			VectorClear( flameDir );
			flameDir[2] = 1;

			le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha);
			VectorCopy( flameDir, le->refEntity.fireRiseDir );
			le->refEntity.customShader = cgs.media.onFireShader;
			trap_R_AddRefEntityToScene( &le->refEntity );
			le->refEntity.customShader = cgs.media.onFireShader2;
			trap_R_AddRefEntityToScene( &le->refEntity );

			le->refEntity = backupEnt;
		}
		
		t = le->endTime - cg.time;
		trap_R_AddRefEntityToScene( &le->refEntity );


		// trace a line from previous position down, to see if I should start falling again

		VectorCopy(le->refEntity.origin, newOrigin);
		newOrigin [2] -= 5;
		CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_MISSILECLIP );

		if(trace.fraction == 1.0)	// it's clear, start moving again
		{
			VectorClear(le->pos.trDelta);
			VectorClear(le->angles.trDelta);
			le->pos.trType = TR_GRAVITY;	// nothing below me, start falling again
		}

		else
			return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	if (hasFlame) {
		// calc the flame dir
		VectorSubtract( le->refEntity.origin, newOrigin, flameDir );
		if (VectorLength( flameDir ) == 0) {
			flameDir[2] = 1;
			// play a burning sound when not moving
			trap_S_AddLoopingSound( 0, newOrigin, vec3_origin, cgs.media.flameSound, (int)(0.3*255.0*flameAlpha) );
		} else {
			VectorNormalize( flameDir );
			// play a flame blow sound when moving
			trap_S_AddLoopingSound( 0, newOrigin, vec3_origin, cgs.media.flameBlowSound, (int)(0.3*255.0*flameAlpha) );
		}
	}


	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE || le->angles.trType == TR_LINEAR) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
			if (le->sizeScale && le->sizeScale != 1.0) {
				for (i=0;i<3;i++) VectorScale( le->refEntity.axis[i], le->sizeScale, le->refEntity.axis[i] );
			}
		}

		// Ridah, add the flame
		if (hasFlame) {
			refEntity_t backupEnt;

			backupEnt = le->refEntity;

			le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha);
			VectorCopy( flameDir, le->refEntity.fireRiseDir );
			le->refEntity.customShader = cgs.media.onFireShader;
			trap_R_AddRefEntityToScene( &le->refEntity );
			le->refEntity.customShader = cgs.media.onFireShader2;
			trap_R_AddRefEntityToScene( &le->refEntity );

			le->refEntity = backupEnt;
		}

		trap_R_AddRefEntityToScene( &le->refEntity );

		// add a blood trail
		if ( le->leBounceSoundType == LEBS_BLOOD ) {
			CG_BloodTrail( le );
		}
		
		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// do a bouncy sound
	CG_FragmentBounceSound( le, &trace );

	// reflect the velocity on the trace plane
	CG_ReflectVelocity( le, &trace );

	// break on contact?
	if (le->breakCount) {
		clientInfo_t	*ci;
		int				clientNum;
		localEntity_t	*nle;
		vec3_t			dir;

		clientNum = le->ownerNum;
		if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) {
			CG_Error( "Bad clientNum on player entity");
		}
		ci = &cgs.clientinfo[ clientNum ];

		// spawn some new fragments
		for (i=0;i<=le->breakCount;i++) {
			nle = CG_AllocLocalEntity();
			memcpy( &(nle->leType), &(le->leType), sizeof(localEntity_t) - 2*sizeof(localEntity_t *) );
			if (nle->breakCount-- < 2)
				nle->refEntity.hModel = ci->gibModels[rand()%2];
			else
				nle->refEntity.hModel = ci->gibModels[rand()%4];
			// make it smaller
			nle->endTime = cg.time + 5000 + rand()%2000;
			nle->sizeScale *= 0.8;
			if (nle->sizeScale < 0.7) {
				nle->sizeScale = 0.7;
				nle->leBounceSoundType = 0;
			}
			// move us a bit
			VectorNormalize2( nle->pos.trDelta, dir );
			VectorMA( trace.endpos, 4.0*le->sizeScale*i, dir, nle->pos.trBase );
			// randomize vel a bit
			VectorMA( nle->pos.trDelta, VectorLength(nle->pos.trDelta)*0.3, bytedirs[rand()%NUMVERTEXNORMALS], nle->pos.trDelta );
		}
		// we're done
		CG_FreeLocalEntity( le );
		return;
	}

	if (le->pos.trType == TR_STATIONARY && le->leMarkType == LEMT_BLOOD) 
	{
		// RF, disabled for performance reasons in boss1
		//if (le->leBounceSoundType)
		//	CG_BloodPool (le, cgs.media.bloodPool, &trace);		
				
		// leave a mark
		if (le->leMarkType)
			CG_FragmentBounceMark( le, &trace );
	}

	// Ridah, add the flame
	if (hasFlame) {
		refEntity_t backupEnt;

		backupEnt = le->refEntity;

		le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha);
		VectorCopy( flameDir, le->refEntity.fireRiseDir );
		le->refEntity.customShader = cgs.media.onFireShader;
		trap_R_AddRefEntityToScene( &le->refEntity );
		le->refEntity.customShader = cgs.media.onFireShader2;
		trap_R_AddRefEntityToScene( &le->refEntity );

		le->refEntity = backupEnt;
	}

	trap_R_AddRefEntityToScene( &le->refEntity );
}
Esempio n. 7
0
/*
================
CG_AddDebrisElements
================
*/
void CG_AddDebrisElements( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;
	float	lifeFrac;
	int		t, step = 50;

	for (t = le->lastTrailTime + step; t < cg.time; t += step) {
		// calculate new position
		BG_EvaluateTrajectory( &le->pos, t, newOrigin );

		// trace a line from previous position to new position
		CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, MASK_SHOT );

		// if stuck, kill it
		if (trace.startsolid) {
			// HACK, some walls screw up, so just pass through if starting in a solid
			VectorCopy( newOrigin, trace.endpos );
			trace.fraction = 1.0;
		}

		// moved some distance
		VectorCopy( trace.endpos, le->refEntity.origin );

		// add a trail
		lifeFrac = (float)(t - le->startTime) / (float)(le->endTime - le->startTime);

#if 0
		// fire
#if 1	// flame
		if (le->effectWidth > 0) {
			le->headJuncIndex = CG_AddSparkJunc( le->headJuncIndex,
										cgs.media.fireTrailShader,
										le->refEntity.origin,
										(int)(500.0 * (0.5 + 0.5*(1.0 - lifeFrac))),	// trail life
										1.0,	// alpha
										0.5,	// end alpha
										3,		// start width
										le->effectWidth );	// end width
#else	// spark line
		if (le->effectWidth > 0) {
			le->headJuncIndex = CG_AddSparkJunc( le->headJuncIndex,
										cgs.media.sparkParticleShader,
										le->refEntity.origin,
										(int)(600.0 * (0.5 + 0.5*(0.5 - lifeFrac))),	// trail life
										1.0 - lifeFrac*2,	// alpha
										0.5 * (1.0 - lifeFrac),	// end alpha
										5.0 * (1.0 - lifeFrac),	// start width
										5.0 * (1.0 - lifeFrac) );	// end width
#endif
		}
#endif

		// smoke
		if (le->effectFlags & 1)
		{
			le->headJuncIndex2 = CG_AddSmokeJunc( le->headJuncIndex2,
										cgs.media.smokeTrailShader,
										le->refEntity.origin,
										(int)(2000.0 * (0.5 + 0.5*(1.0 - lifeFrac))),	// trail life
										1.0 * (trace.fraction == 1.0) * (0.5 + 0.5 * (1.0 - lifeFrac)),	// alpha
										1,		// start width
										(int)(60.0 * (0.5 + 0.5*(1.0 - lifeFrac))) );	// end width
		}

		// if it is in a nodrop zone, remove it
		// this keeps gibs from waiting at the bottom of pits of death
		// and floating levels
//		if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
//			CG_FreeLocalEntity( le );
//			return;
//		}

		if (trace.fraction < 1.0) {
			// reflect the velocity on the trace plane
			CG_ReflectVelocity( le, &trace );
			if (VectorLength(le->pos.trDelta) < 1) {
				CG_FreeLocalEntity( le );
				return;
			}
			// the intersection is a fraction of the frametime
			le->pos.trTime = t;
		}

		le->lastTrailTime = t;
	}

}

// Rafael Shrapnel
/*
===============
CG_AddShrapnel
===============
*/
void CG_AddShrapnel (localEntity_t *le) 
{
	vec3_t	newOrigin;
	trace_t	trace;

	if ( le->pos.trType == TR_STATIONARY ) {
		// sink into the ground if near the removal time
		int		t;
		float	oldZ;
		
		t = le->endTime - cg.time;
		if ( t < SINK_TIME ) {
			// we must use an explicit lighting origin, otherwise the
			// lighting would be lost as soon as the origin went
			// into the ground
			VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
			le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
			oldZ = le->refEntity.origin[2];
			le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
			trap_R_AddRefEntityToScene( &le->refEntity );
			le->refEntity.origin[2] = oldZ;
		} else {
			trap_R_AddRefEntityToScene( &le->refEntity );
			CG_AddParticleShrapnel (le);
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
		}

		trap_R_AddRefEntityToScene( &le->refEntity );
		CG_AddParticleShrapnel (le);
		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// leave a mark
	CG_FragmentBounceMark( le, &trace );

	// do a bouncy sound
	CG_FragmentBounceSound( le, &trace );

	// reflect the velocity on the trace plane
	CG_ReflectVelocity( le, &trace );

	trap_R_AddRefEntityToScene( &le->refEntity );
	CG_AddParticleShrapnel (le);
}
Esempio n. 8
0
/*
===================
CG_AddParticle

For trek, special explosion stuff sometimes wants these
===================
*/
static void CG_AddParticle( localEntity_t *le ) 
{
	refEntity_t	*re;
	float		frac, alpha;
	vec3_t		delta, dir;
	float		len;
	trace_t		trace;

	re = &le->refEntity;

	//safety check - since this renders over all, make sure we can't see this thru a wall
	if ( re->renderfx & RF_DEPTHHACK ) {
		CG_Trace( &trace, re->origin, NULL, NULL, cg.refdef.vieworg, cg.predictedPlayerState.clientNum, MASK_SOLID );

		if ( trace.fraction != 1.0 )
			return;

	}

	frac = ( cg.time - le->startTime ) / ( float ) ( le->endTime - le->startTime );
	if ( le->leFlags & LEF_SINE_SCALE ) {
		//frac = 1.0-(0.5f * sin( 4.0f * frac + 0.75f ) + 0.5f); //TiM: Sine calc //+ 1.5f
		frac = 1.0-(0.65 * sin(  3.0 * frac +0.75 ) + 0.35);
	}

	if ( frac > 1 )
		frac = 1.0;	// can happen during connection problems
	else if (frac < 0)
		frac = 0.0;

	//CG_Printf( "%f\n", frac );

	// Use the liferate to set the scale over time.
	if ( !(le->leFlags & LEF_REVERSE_SCALE) ) 
		re->data.sprite.radius = le->data.particle.radius + (le->data.particle.dradius*frac);
	else
		re->data.sprite.radius = le->data.particle.radius - (le->data.particle.dradius*frac);
	if (re->data.sprite.radius <= 0)
	{
		CG_FreeLocalEntity( le );
		return;
	}

	if (le->leFlags & LEF_MOVE)
	{
		// kef -- do these two lines _before_ copying origin into oldorigin
		VectorSubtract(re->oldorigin, re->origin, dir);
		VectorNormalize(dir);

		VectorCopy(re->origin, re->oldorigin);
		BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );

		if (le->leFlags & LEF_USE_COLLISION)
		{
			// trace a line from previous position to new position
			CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, -1, CONTENTS_SOLID );

			if ( trace.fraction != 1.0 ) 
			{	// Hit something.
				// if it is in a nodrop zone, remove it
				// this keeps gibs from waiting at the bottom of pits of death
				// and floating levels
				if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
					CG_FreeLocalEntity( le );
					return;
				}

				// reflect the velocity on the trace plane
				CG_ReflectVelocity( le, &trace );
			}
			VectorSubtract(re->oldorigin, re->origin, dir);
			VectorNormalize(dir);
		}
	}

	// if the view would be "inside" the sprite, kill the sprite
	// so it doesn't add too much overdraw
	VectorSubtract( re->origin, cg.refdef.vieworg, delta );
	len = VectorLength( delta );
	if ( len < le->data.particle.radius ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// kef -- here's where I, in my infinite wisdom, have decided to emulate the singleplayer
	//particle think function
	VectorNegate(dir, le->data.particle.dir);
	if (le->data.particle.thinkFn)
	{
		le->data.particle.thinkFn(le);
	}

	// Calculate the current alpha.
	alpha = le->alpha + (le->dalpha * frac);
	re->shaderRGBA[0] = 0xff * alpha;
	re->shaderRGBA[1] = 0xff * alpha;
	re->shaderRGBA[2] = 0xff * alpha;
	re->shaderRGBA[3] = 0xff;	

	re->reType = RT_SPRITE;

	trap_R_AddRefEntityToScene( re );
}
Esempio n. 9
0
/*
===================
CG_AddViewSprite

For trek, view sprites like smoke and the like.
===================
*/
void CG_AddViewSprite( localEntity_t *le )
{
	refEntity_t	*re;
	float		frac, alpha;
	vec3_t		delta;
	float		len;
	trace_t		trace;
	vec3_t		curRGB;

	re = &le->refEntity;

	frac = ( cg.time - le->startTime ) / ( float ) ( le->endTime - le->startTime );
	if ( frac > 1 )
		frac = 1.0;	// can happen during connection problems
	else if (frac < 0)
		frac = 0.0;

	// Use the liferate to set the scale over time.
	re->data.sprite.radius = le->data.sprite.radius + (le->data.sprite.dradius*frac);
	if (re->data.sprite.radius <= 0)
	{
		CG_FreeLocalEntity( le );
		return;
	}

	if (le->leFlags & LEF_MOVE)
	{
		VectorCopy(re->origin, re->oldorigin);
		BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );

		if (le->leFlags & LEF_USE_COLLISION)
		{
			// trace a line from previous position to new position
			CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, -1, CONTENTS_SOLID );

			if ( trace.fraction != 1.0 ) 
			{	// Hit something.
				// if it is in a nodrop zone, remove it
				// this keeps gibs from waiting at the bottom of pits of death
				// and floating levels
				if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
					CG_FreeLocalEntity( le );
					return;
				}

				// reflect the velocity on the trace plane
				CG_ReflectVelocity( le, &trace );
			}
		}
	}

	// if the view would be "inside" the sprite, kill the sprite
	// so it doesn't add too much overdraw
	VectorSubtract( re->origin, cg.refdef.vieworg, delta );
	len = VectorLength( delta );
	if ( len < le->data.sprite.radius ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// Calculate the current alpha.
	alpha = le->alpha + (le->dalpha * frac);
	VectorMA(le->data.sprite.startRGB, frac, le->data.sprite.dRGB, curRGB);
	re->shaderRGBA[0] = 0xff * alpha * curRGB[0];
	re->shaderRGBA[1] = 0xff * alpha * curRGB[1];
	re->shaderRGBA[2] = 0xff * alpha * curRGB[2];
	re->shaderRGBA[3] = 0xff;	

	re->reType = RT_SPRITE;

	trap_R_AddRefEntityToScene( re );
}
Esempio n. 10
0
/*
===================
CG_AddTrail

For trek, for sparks and the like.
===================
*/
void CG_AddTrail( localEntity_t *le ) 
{
	refEntity_t	*re;
	float frac, length, alpha;
	vec3_t	dir;
	trace_t	trace;
	vec3_t	curRGB;

	re = &le->refEntity;

	frac = (cg.time - le->startTime) / ( float ) ( le->endTime - le->startTime );
	if ( frac > 1 ) 
		frac = 1.0;	// can happen during connection problems
	else if (frac < 0)
		frac = 0.0;

	// Use the liferate to set the scale over time.
	re->data.line.width = le->data.trail.width + (le->data.trail.dwidth * frac);
	if (re->data.line.width <= 0)
	{
		CG_FreeLocalEntity( le );
		return;
	}

	if (!(le->leFlags & LEF_MOVE))
	{
		return;
	}

	// kef -- do these two lines _before_ copying origin into oldorigin
	VectorSubtract(re->oldorigin, re->origin, dir);
	VectorNormalize(dir);

	VectorCopy(re->origin, re->oldorigin);
	BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );

	if (le->leFlags & LEF_USE_COLLISION)
	{
		// trace a line from previous position to new position
		CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, -1, CONTENTS_SOLID );

		if ( trace.fraction != 1.0 ) 
		{	// Hit something.
			// if it is in a nodrop zone, remove it
			// this keeps gibs from waiting at the bottom of pits of death
			// and floating levels
			if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
				CG_FreeLocalEntity( le );
				return;
			}

			// reflect the velocity on the trace plane
			CG_ReflectVelocity( le, &trace );
		}
		VectorSubtract(re->oldorigin, re->origin, dir);
		VectorNormalize(dir);
	}

	// Set the length based on the velocity of the bit.
	length = le->data.trail.length + (le->data.trail.dlength * frac);
	if (length <= 0)
	{
		CG_FreeLocalEntity( le );
		return;
	}

	VectorMA(re->origin, length, dir, re->oldorigin);

	// We will assume here that we want additive transparency effects.
	alpha = le->alpha + (le->dalpha * frac);
	VectorMA(le->data.trail.startRGB, frac, le->data.trail.dRGB, curRGB);
	re->shaderRGBA[0] = 0xff * alpha * curRGB[0];
	re->shaderRGBA[1] = 0xff * alpha * curRGB[1];
	re->shaderRGBA[2] = 0xff * alpha * curRGB[2];
	re->shaderRGBA[3] = 0xff;	// Yes, we could apply c to this too, but fading the color is better for lines.

	re->reType = RT_LINE;

	trap_R_AddRefEntityToScene( re );
}
Esempio n. 11
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;
	int k;

	if ( le->pos.trType == TR_STATIONARY ) {
		// sink into the ground if near the removal time
		int		t;
		float	oldZ;
		
		t = le->endTime - cg.time;
		if ( t < SINK_TIME ) {
			// we must use an explicit lighting origin, otherwise the
			// lighting would be lost as soon as the origin went
			// into the ground
			VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
			le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
			oldZ = le->refEntity.origin[2];
			le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
			trap_R_AddRefEntityToScene( &le->refEntity );
			le->refEntity.origin[2] = oldZ;
		} else {
			trap_R_AddRefEntityToScene( &le->refEntity );
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, 0 /*le->ownerGentNum*/, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
			for(k = 0; k < 3; k++)
			{
				VectorScale(le->refEntity.axis[k], le->data.fragment.radius, le->refEntity.axis[k]);
			}

		}

		trap_R_AddRefEntityToScene( &le->refEntity );

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// reflect the velocity on the trace plane
	CG_ReflectVelocity( le, &trace );
	//FIXME: if LEF_TUMBLE, change avelocity too?

	trap_R_AddRefEntityToScene( &le->refEntity );
}
Esempio n. 12
0
/*
=======================================================================================================================================
CG_AddFragment
=======================================================================================================================================
*/
void CG_AddFragment(localEntity_t *le) {
	vec3_t newOrigin, angles;
	trace_t trace;

	if (le->pos.trType == TR_STATIONARY) {
		// sink into the ground if near the removal time
		int t;
		float oldZ;

		CG_AdjustPositionForMover(le->refEntity.origin, le->groundEntityNum, le->pos.trTime, cg.time, le->refEntity.origin, le->angles.trBase, le->angles.trBase);
		AnglesToAxis(le->angles.trBase, le->refEntity.axis);

		le->pos.trTime = cg.time;
		t = le->endTime - cg.time;

		if (t < SINK_TIME) {
			// we must use an explicit lighting origin, otherwise the lighting would be lost as soon as the origin went into the ground
			VectorCopy(le->refEntity.origin, le->refEntity.lightingOrigin);

			le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
			oldZ = le->refEntity.origin[2];
			le->refEntity.origin[2] -= 16 * (1.0 - (float)t / SINK_TIME);

			trap_R_AddRefEntityToScene(&le->refEntity);

			le->refEntity.origin[2] = oldZ;
		} else {
			trap_R_AddRefEntityToScene(&le->refEntity);
		}

		return;
	}
	// never free fragments while they're flying
	if (le->endTime < cg.time + 2000) {
		le->endTime = cg.time + 2000;
	}
	// calculate new position
	BG_EvaluateTrajectory(&le->pos, cg.time, newOrigin);
	// trace a line from previous position to new position
	CG_Trace(&trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID);

	if (trace.fraction == 1.0) {
		// still in free fall
		VectorCopy(newOrigin, le->refEntity.origin);
		VectorClear(angles);

		switch (le->leFlags) {
			case LEF_TUMBLE:
				BG_EvaluateTrajectory(&le->angles, cg.time, angles);
				break;
			case LEF_GIBS:
				angles[1] = ((cg.time & 2047) * 360 / 2048.0 + 120);
				angles[0] = ((cg.time & 2047) * 360 / 2048.0);
				angles[2] = ((cg.time & 2047) * 360 / 2048.0 + 240);
				break;
			default:
				break;
		}

		AnglesToAxis(angles, le->refEntity.axis);
		trap_R_AddRefEntityToScene(&le->refEntity);
		// add a blood trail
		if (le->leBounceSoundType == LEBS_BLOOD) {
			CG_BloodTrail(le);
		}

		return;
	}
	// fragment inside mover, find the direction/origin of impact
	if (trace.allsolid && cg_entities[trace.entityNum].currentState.eType == ET_MOVER) {
		vec3_t origin, angles, dir;
		float dist;
		int oldTime;
		trace_t tr;

		// get last location
		if (cg.time == le->pos.trTime) {
			// fragment was added this frame. no good way to fix this.
			CG_FreeLocalEntity(le);
			return;
		} else {
			oldTime = le->pos.trTime;
		}

		BG_EvaluateTrajectory(&le->pos, oldTime, origin);
		VectorClear(angles);
		// add the distance mover has moved since then
		CG_AdjustPositionForMover(origin, trace.entityNum, oldTime, cg.time, origin, angles, angles);
		// nudge the origin farther to avoid being co-planar
		VectorSubtract(origin, newOrigin, dir);

		dist = VectorNormalize(dir);

		VectorMA(origin, dist, dir, origin);
		CG_Trace(&tr, origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID);
		// found impact. restore allsolid because trace fraction won't work correct in CG_ReflectVelocity
		if (!tr.allsolid) {
			trace = tr;
			trace.allsolid = qtrue;
		}
	}
	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death and floating levels
	if (CG_PointContents(trace.endpos, 0) & CONTENTS_NODROP) {
		CG_FreeLocalEntity(le);
		return;
	}
	// leave a mark
	CG_FragmentBounceMark(le, &trace);
	// do a bouncy sound
	CG_FragmentBounceSound(le, &trace);
	// reflect the velocity on the trace plane
	CG_ReflectVelocity(le, &trace);
	trap_R_AddRefEntityToScene(&le->refEntity);
}
Esempio n. 13
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment(localEntity_t * le)
{
	vec3_t          newOrigin;
	trace_t         trace;

	if(le->pos.trType == TR_STATIONARY)
	{
		// sink into the ground if near the removal time
		int             t;
		float           oldZ;

		t = le->endTime - cg.time;
		if(t < SINK_TIME)
		{
			// we must use an explicit lighting origin, otherwise the
			// lighting would be lost as soon as the origin went
			// into the ground
			VectorCopy(le->refEntity.origin, le->refEntity.lightingOrigin);
			le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
			oldZ = le->refEntity.origin[2];
			le->refEntity.origin[2] -= 16 * (1.0 - (float)t / SINK_TIME);
			trap_R_AddRefEntityToScene(&le->refEntity);
			le->refEntity.origin[2] = oldZ;
		}
		else
		{
			trap_R_AddRefEntityToScene(&le->refEntity);
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory(&le->pos, cg.time, newOrigin);

	// trace a line from previous position to new position
	CG_Trace(&trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID);
	if(trace.fraction == 1.0)
	{
		// still in free fall
		VectorCopy(newOrigin, le->refEntity.origin);

		if(le->leFlags & LEF_TUMBLE)
		{
#if 0
			vec3_t          angles;

			BG_EvaluateTrajectory(&le->angles, cg.time, angles);
			AnglesToAxis(angles, le->refEntity.axis);
#else
			// Tr3B - new quaternion code
			quat_t          qrot;

			// angular rotation for this frame
			float           angle = le->angVel * (cg.time - le->angles.trTime) * 0.001 / 2;

			// create the rotation quaternion
			qrot[3] = cos(angle);	// real part
			VectorScale(le->rotAxis, sin(angle), qrot);	// imaginary part
			QuatNormalize(qrot);

			// create the new orientation
			QuatMultiply0(le->quatOrient, qrot);

			// apply the combined previous rotations around other axes
			QuatMultiply1(le->quatOrient, le->quatRot, qrot);

			// convert the orientation into the form the renderer wants
			QuatToAxis(qrot, le->refEntity.axis);
			le->angles.trTime = cg.time;
#endif
		}

		trap_R_AddRefEntityToScene(&le->refEntity);

		// add a blood trail
		if(le->leBounceSoundType == LEBS_BLOOD)
		{
			CG_BloodTrail(le);
		}

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if(trap_CM_PointContents(trace.endpos, 0) & CONTENTS_NODROP)
	{
		CG_FreeLocalEntity(le);
		return;
	}

	// leave a mark
	CG_FragmentBounceMark(le, &trace);

	// do a bouncy sound
	CG_FragmentBounceSound(le, &trace);

	// reflect the velocity on the trace plane
	CG_ReflectVelocity(le, &trace);

	trap_R_AddRefEntityToScene(&le->refEntity);
}
Esempio n. 14
0
/*
================
CG_AddMissile
================
*/
static void CG_AddMissile( localEntity_t *le ) {
	refEntity_t			*re;
	const weaponInfo_t	*weapon;
	trace_t				trace;
	centity_t			*other;
	qboolean			inWater;

	// just existing for server entity deletion
	if ( le->leFlags & LEF_FINISHED ) {
		return;
	}

	// get weapon info
	if ( le->ti.weapon > WP_NUM_WEAPONS ) {
		le->ti.weapon = 0;
	}
	weapon = &cg_weapons[le->ti.weapon];

	re = &le->refEntity;

	// calculate position
	BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );

	// special case for flames
	if ( re->reType == RT_SPRITE ) {
		int deltaTime;

		// check for water
		if ( trap_CM_PointContents( re->origin, 0 ) & CONTENTS_WATER ) {
			// do a trace to get water surface normals
			CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_WATER );
			CG_FreeLocalEntity( le );

			CG_MakeExplosion( trace.endpos, trace.plane.normal, 
				cgs.media.ringFlashModel, cgs.media.vaporShader,
				500, qfalse, qtrue );
			return;
		}

		// change radius over time
		deltaTime = cg.time - le->startTime;
		re->radius = deltaTime * deltaTime * ( random()*0.4f + 0.8f ) / 2000.0f + 9;

		// do a trace sometimes
		if ( le->ti.trailTime++ > 5 ) {
			le->ti.trailTime = 0;

			CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_SHOT );
			VectorCopy( re->origin, re->oldorigin );

			// hit something
			if ( trace.fraction < 1.0 ) {
				CG_MissileHitWall( le->ti.weapon, 0, trace.endpos, trace.plane.normal, IMPACTSOUND_DEFAULT );
				CG_FreeLocalEntity( le );
				return;
			}
		}

		// add to refresh list
		trap_R_AddRefEntityToScene( re );
		return;
	}

	// add trails
	if ( weapon->missileTrailFunc ) weapon->missileTrailFunc( &le->ti, cg.time );

	// add dynamic light
	if ( weapon->missileDlight ) {
		trap_R_AddLightToScene( re->origin, weapon->missileDlight, 
			weapon->missileDlightColor[0], weapon->missileDlightColor[1], weapon->missileDlightColor[2] );
	}

	// flicker between two skins
	re->skinNum = cg.clientFrame & 1;

	// convert direction of travel into axis
	if ( VectorNormalize2( le->pos.trDelta, re->axis[0] ) == 0 ) {
		re->axis[0][2] = 1;
	}

	// spin as it moves
	if ( le->pos.trType != TR_STATIONARY ) {
		if ( le->pos.trType == TR_GRAVITY ) {
			RotateAroundDirection( re->axis, cg.time / 4 );
		} else if ( le->pos.trType == TR_WATER_GRAVITY ) {
			RotateAroundDirection( re->axis, cg.time / 8 );
		} else {
			RotateAroundDirection( re->axis, cg.time );
		}
	} else {
		RotateAroundDirection( re->axis, 0 );
	}

	// trace a line from previous position to new position
	CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_SHOT );
	VectorCopy( re->origin, re->oldorigin );

	// draw BIG grenades
	if ( weLi[le->ti.weapon].category == CT_EXPLOSIVE ) {
		AxisScale( re->axis, GRENADE_SCALE, re->axis );
	}

	if ( trace.fraction != 1.0 ) {
		// hit the sky or something like that
		if ( trace.surfaceFlags & SURF_NOIMPACT ) {
			le->leFlags |= LEF_FINISHED;
			le->endTime = cg.time + 500;
			return;
		}

		// impact
		other = &cg_entities[trace.entityNum];

		if ( le->bounceFactor > 0 && ( le->bounceFactor == BOUNCE_FACTOR_HALF || other->currentState.eType != ET_PLAYER ) ) {
			// reflect the velocity on the trace plane
			CG_ReflectVelocity( le, &trace );
			if ( cg.predictedImpacts < MAX_PREDICTED_IMPACTS ) {
				cg.predictedImpacts++;
				cg.predictedImpactsDecTime = cg.time;
			}

			// do bounce sound
			if ( rand() & 1 ) {
				trap_S_StartSound( le->pos.trBase, 0, CHAN_AUTO, cgs.media.hgrenb1aSound );
			} else {
				trap_S_StartSound( le->pos.trBase, 0, CHAN_AUTO, cgs.media.hgrenb2aSound );
			}
		} else {
			// explode missile
			if ( cg.predictedImpacts < MAX_PREDICTED_IMPACTS ) {
				cg.predictedImpacts++;
				cg.predictedImpactsDecTime = cg.time;
			}

			if ( other->currentState.eType == ET_PLAYER ) {
				CG_MissileHitPlayer( le->ti.weapon, 0, trace.endpos, trace.plane.normal, trace.entityNum );
			} else if ( !(trace.surfaceFlags & SURF_NOIMPACT) ) {
				CG_MissileHitWall( le->ti.weapon, 0, trace.endpos, trace.plane.normal, 
					(trace.surfaceFlags & SURF_METALSTEPS) ? IMPACTSOUND_METAL : IMPACTSOUND_DEFAULT );
			}
			// store the entity for deleting the server entity
			le->leFlags |= LEF_FINISHED;
			le->endTime = cg.time + 500;
			return;
		}
	}

	// check for medium change
	if ( trap_CM_PointContents( re->origin, 0 ) & CONTENTS_WATER ) inWater = qtrue;
	else inWater = qfalse;

	if (  ( !inWater && le->pos.trType == TR_WATER_GRAVITY )
		|| ( inWater && le->pos.trType == TR_GRAVITY ) ) {
		// setup new tr
		vec3_t	newDelta;

		BG_EvaluateTrajectoryDelta( &le->pos, cg.time, newDelta );
		VectorCopy( re->origin, le->pos.trBase );
		VectorCopy( newDelta, le->pos.trDelta );
		le->pos.trTime = cg.time;
		if ( inWater ) le->pos.trType = TR_WATER_GRAVITY;
		else le->pos.trType = TR_GRAVITY;
	}	

	// add to refresh list
	trap_R_AddRefEntityToScene( re );
}
Esempio n. 15
0
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;

	if ( le->pos.trType == TR_STATIONARY ) {
		// sink into the ground if near the removal time
		int		t;
		float	oldZ;
		
		t = le->endTime - cg.time;
		if ( t < SINK_TIME ) {
			// we must use an explicit lighting origin, otherwise the
			// lighting would be lost as soon as the origin went
			// into the ground
			VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
			le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
			oldZ = le->refEntity.origin[2];
			le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
			trap_R_AddRefEntityToScene( &le->refEntity );
			le->refEntity.origin[2] = oldZ;
		} else {
			trap_R_AddRefEntityToScene( &le->refEntity );
		}

		return;
	}

	// calculate new position
	BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );

	// trace a line from previous position to new position
	CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
	if ( trace.fraction == 1.0 ) {
		qboolean	inWater;
		vec3_t		newDelta;

		// still in free fall
		VectorCopy( newOrigin, le->refEntity.origin );

		// check for water
		inWater = CG_PointContents( newOrigin, -1 ) & CONTENTS_WATER;

		if ( inWater && le->pos.trType == TR_GRAVITY ) {
			BG_EvaluateTrajectoryDelta( &le->pos, cg.time, newDelta );
			le->pos.trType = TR_WATER_GRAVITY;
			VectorCopy( newOrigin, le->pos.trBase );
			VectorCopy( newDelta, le->pos.trDelta );
			le->pos.trTime = cg.time;
		}
		if ( !inWater && le->pos.trType == TR_WATER_GRAVITY ) {
			BG_EvaluateTrajectoryDelta( &le->pos, cg.time, newDelta );
			le->pos.trType = TR_GRAVITY;
			VectorCopy( newOrigin, le->pos.trBase );
			VectorCopy( newDelta, le->pos.trDelta );
			le->pos.trTime = cg.time;
		}

		if ( le->leFlags & LEF_TUMBLE ) {
			vec3_t angles;

			BG_EvaluateTrajectory( &le->angles, cg.time, angles );
			AnglesToAxis( angles, le->refEntity.axis );
		}

		trap_R_AddRefEntityToScene( &le->refEntity );

		// add a fire trail
		// CG_FireTrail( le );

		return;
	}

	// if it is in a nodrop zone, remove it
	// this keeps gibs from waiting at the bottom of pits of death
	// and floating levels
	if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
		CG_FreeLocalEntity( le );
		return;
	}

	// stop rotation
	le->angles.trType = TR_STATIONARY;

	// leave a mark
	CG_FragmentBounceMark( le, &trace );

	// reflect the velocity on the trace plane
	CG_ReflectVelocity( le, &trace );

	trap_R_AddRefEntityToScene( &le->refEntity );
}