Ejemplo n.º 1
0
/*
================
CG_PointContents
================
*/
int		CG_PointContents( const vec3_t point, int passEntityNum ) {
	int			i;
	entityState_t	*ent;
	centity_t	*cent;
	clipHandle_t cmodel;
	int			contents;

	contents = trap_CM_PointContents (point, 0);

	for ( i = 0 ; i < cg_numSolidEntities ; i++ ) {
		cent = cg_solidEntities[ i ];

		ent = &cent->currentState;

		if ( ent->number == passEntityNum ) {
			continue;
		}

		if ( ent->collisionType != CT_SUBMODEL ) {
			continue;
		}

		cmodel = trap_CM_InlineModel( ent->modelindex );
		if ( !cmodel ) {
			continue;
		}

		contents |= trap_CM_TransformedPointContents( point, cmodel, cent->lerpOrigin, cent->lerpAngles );
	}

	return contents;
}
Ejemplo n.º 2
0
/*
================
CG_AddFireEffect
================
*/
static void CG_AddFireEffect( localEntity_t *le ) {
	refEntity_t			*re;
	trace_t				trace;

	re = &le->refEntity;

	if ( le->pos.trType == TR_STATIONARY ) {
		if ( le->leFlags & LEF_LESSOVERDRAW ) {
			// avoid too much overdraw
			if ( CG_NearbyDrawnLeCount( le, re->origin, le->leType, 52 + !!cg_lowDetailEffects.integer * 24 ) > 0 ) return;
		}
		// add to refresh list
		trap_R_AddRefEntityToScene( re );
		return;
	}

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

	// 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;
	}

	// 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( trace.endpos, re->origin );
		VectorCopy( trace.endpos, re->oldorigin );

		// hit something
		if ( trace.fraction < 1.0 ) {
			// free le if another one is nearby, otherwise make it stationary
			if ( CG_CheckDistance( re->origin, le->leType, TR_STATIONARY, re->customShader, 200, 32 ) ) { 
				CG_FreeLocalEntity( le );
				return;
			} else {
				le->pos.trType = TR_STATIONARY;
			}
		}
	}

	if ( le->leFlags & LEF_LESSOVERDRAW ) {
		// avoid too much overdraw
		if ( CG_NearbyDrawnLeCount( le, re->origin, le->leType, 52 + !!cg_lowDetailEffects.integer * 24 ) > 0 ) return;
	}

	// add to refresh list
	trap_R_AddRefEntityToScene( re );
}
Ejemplo n.º 3
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;
	}
}
Ejemplo n.º 4
0
void CG_AddGore( 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;
		
		CG_FreeLocalEntity( le ); // kill it

		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_SmallBloodTrail( 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_GoreMark( le, &trace );

	// do a juicy sound
	CG_SplatSound( le, &trace );

	CG_JustSplat( le, &trace );

	trap_R_AddRefEntityToScene( &le->refEntity );
}
Ejemplo n.º 5
0
/*
	The only difference is that this will account for water friction
*/
void CG_LE_EvaluateTrajectory(const trajectory_t * tr, int atTime, vec3_t result)
{
	float deltaTime;
	float phase;
	float friction = 1.0f;

	switch (tr->trType) {
	case TR_STATIONARY:
	case TR_INTERPOLATE:
		VectorCopy(tr->trBase, result);
		break;
	case TR_LINEAR:
		deltaTime = (atTime - tr->trTime) * 0.001;	// milliseconds to seconds
		VectorMA(tr->trBase, deltaTime, tr->trDelta, result);
		break;
	case TR_SINE:
		deltaTime = (atTime - tr->trTime) / (float) tr->trDuration;
		phase = sin(deltaTime * M_PI * 2);
		VectorMA(tr->trBase, phase, tr->trDelta, result);
		break;
	case TR_LINEAR_STOP:
		if (atTime > tr->trTime + tr->trDuration) {
			atTime = tr->trTime + tr->trDuration;
		}
		deltaTime = (atTime - tr->trTime) * 0.001;	// milliseconds to seconds
		if (deltaTime < 0) {
			deltaTime = 0;
		}
		VectorMA(tr->trBase, deltaTime, tr->trDelta, result);
		break;
	case TR_GRAVITY:
		if (trap_CM_PointContents(tr->trBase, 0) & CONTENTS_WATER)
			friction = 0.3f;
		deltaTime = (atTime - tr->trTime) * 0.001;	// milliseconds to seconds
		VectorMA(tr->trBase, deltaTime * friction, tr->trDelta, result);
		result[2] -= 0.5 * cg_gravity.value * friction * deltaTime * deltaTime;
		break;
	default:
		Com_Error(ERR_DROP, "CG_LE_EvaluateTrajectory: unknown trType: %i", tr->trTime);
		break;
	}
}
Ejemplo n.º 6
0
void CG_LE_EvaluateTrajectoryDelta(const trajectory_t * tr, int atTime, vec3_t result)
{
	float deltaTime;
	float phase;
	float friction = 1.0f;

	switch (tr->trType) {
	case TR_STATIONARY:
	case TR_INTERPOLATE:
		VectorClear(result);
		break;
	case TR_LINEAR:
		VectorCopy(tr->trDelta, result);
		break;
	case TR_SINE:
		deltaTime = (atTime - tr->trTime) / (float) tr->trDuration;
		phase = cos(deltaTime * M_PI * 2);	// derivative of sin = cos
		phase *= 0.5;
		VectorScale(tr->trDelta, phase, result);
		break;
	case TR_LINEAR_STOP:
		if (atTime > tr->trTime + tr->trDuration) {
			VectorClear(result);
			return;
		}
		VectorCopy(tr->trDelta, result);
		break;
	case TR_GRAVITY:
		if (trap_CM_PointContents(tr->trBase, 0) & CONTENTS_WATER)
			friction = 0.3f;
		deltaTime = (atTime - tr->trTime) * 0.001;	// milliseconds to seconds
		VectorScale(tr->trDelta, friction, result);
		result[2] -= cg_gravity.value * friction * deltaTime;
		break;
	default:
		Com_Error(ERR_DROP, "CG_LE_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime);
		break;
	}
}
Ejemplo n.º 7
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 );
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
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 ) {
			vec3_t angles;

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

		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 );
}
Ejemplo n.º 10
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 );
		}

		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 );
	}
}
Ejemplo n.º 11
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 );
}
Ejemplo n.º 12
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 );
}
Ejemplo n.º 13
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 );
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
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 );
}