Beispiel #1
0
/*
================
CG_AddFuseSparkElements
================
*/
void CG_AddFuseSparkElements( localEntity_t *le ) {

float FUSE_SPARK_WIDTH		= 1.0;

	int step = 10;
	float	time;
	float	lifeFrac;
	static vec3_t	whiteColor = {1,1,1};

	time = (float)(le->lastTrailTime);

	while (time < cg.time) {

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

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

		//if (lifeFrac > 0.2) {
			// add a trail
			le->headJuncIndex = CG_AddTrailJunc( le->headJuncIndex, cgs.media.sparkParticleShader, time, STYPE_STRETCH, le->refEntity.origin, (int)(lifeFrac*(float)(le->endTime - le->startTime)/2.0),
				1.0/*(1.0 - lifeFrac)*/, 0.0, FUSE_SPARK_WIDTH*(1.0 - lifeFrac), FUSE_SPARK_WIDTH*(1.0 - lifeFrac), TJFL_SPARKHEADFLARE, whiteColor, whiteColor, 0, 0 );
		//}

		time += step;

		le->lastTrailTime = time;
	}

}
Beispiel #2
0
/*
================
CG_AddClientCritter
================
*/
void CG_AddClientCritter( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;
	int		time, step = 25, i;
	vec3_t	v, ang, v2, oDelta;
	localEntity_t backup;
	float	oldSpeed, enemyDist, of;
	vec3_t	enemyPos;
	float alpha;

	if (cg_entities[le->ownerNum].currentState.otherEntityNum2 == cg.snap->ps.clientNum) {
		VectorCopy( cg.snap->ps.origin, enemyPos );
		enemyPos[2] += cg.snap->ps.viewheight;
	} else {
		VectorCopy( cg_entities[le->ownerNum].currentState.origin2, enemyPos );
	}

	VectorCopy( le->pos.trDelta, oDelta );

	// vary the enemyPos to create a psuedo-randomness
	of = (float)cg.time + le->startTime;
	enemyPos[0] += 12 * (sin(of/100) * cos(of/78));
	enemyPos[1] += 12 * (sin(of/70) * cos(of/82));
	enemyPos[2] += 12 * (sin(of/67) * cos(of/98));

	time = le->lastTrailTime+step;

	while (time <= cg.time) {
		if (time > le->refEntity.fadeStartTime) {
			alpha = (float)(time - le->refEntity.fadeStartTime)/(float)(le->refEntity.fadeEndTime - le->refEntity.fadeStartTime);
			if (alpha < 0) alpha = 0;
			else if (alpha > 1) alpha = 1;
		} else {
			alpha = 1.0;
		}

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

		VectorSubtract( enemyPos, le->refEntity.origin, v );
		enemyDist = VectorNormalize( v );

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

		// if stuck, kill it
		if (trace.startsolid || (trace.fraction < 1.0)) {
			// kill it
			CG_FreeLocalEntity( le );
			return;
		}

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

		if (le->leType == LE_ZOMBIE_SPIRIT) {
			le->headJuncIndex = CG_AddTrailJunc( le->headJuncIndex,
												cgs.media.zombieSpiritTrailShader,
												time,
												STYPE_STRETCH,
												le->refEntity.origin,
												(int)le->effectWidth,	// trail life
												0.3 * alpha,
												0.0,
												le->radius,
												0,
												0,//TJFL_FIXDISTORT,
												colorWhite,
												colorWhite,
												1.0, 1 );
		}

		// tracking factor
		if (le->leType == LE_ZOMBIE_BAT)
			le->bounceFactor = 3.0*(float)step/1000.0;
		else
			le->bounceFactor = 5.0*(float)step/1000.0;
		oldSpeed = VectorLength( le->pos.trDelta );

		// track the enemy
		backup = *le;
		VectorSubtract( enemyPos, le->refEntity.origin, v );
		enemyDist = VectorNormalize( v );

		if (alpha > 0.5 && (le->lastSpiritDmgTime < time - 100) && enemyDist < 24) {
			// inflict the damage!
			CG_ClientDamage( cg_entities[le->ownerNum].currentState.otherEntityNum2, le->ownerNum, CLDMG_SPIRIT );
			le->lastSpiritDmgTime = time;
		}

		VectorMA( le->pos.trDelta, le->bounceFactor*oldSpeed, v, le->pos.trDelta );
		//VectorCopy( v, le->pos.trDelta );
		if (VectorLength(le->pos.trDelta) < 1) {
			CG_FreeLocalEntity( le );
			return;
		}

		le->bounceFactor = 5.0*(float)step/1000.0;	// avoidance factor

		// the intersection is a fraction of the frametime
		le->pos.trTime = time;
		VectorCopy( le->refEntity.origin, le->pos.trBase );
		VectorNormalize( le->pos.trDelta );
		VectorScale( le->pos.trDelta, oldSpeed, le->pos.trDelta );

		// now trace ahead of time, if we're going to hit something, then avoid it
		// only avoid dangers if we don't have direct sight to the enemy
		trap_CM_BoxTrace( &trace, le->refEntity.origin, enemyPos, NULL, NULL, 0, MASK_SOLID );
		if (trace.fraction < 1.0) {
			BG_EvaluateTrajectory( &le->pos, time+1000, newOrigin );

			// if we would go passed the enemy, don't bother
			if (VectorDistance( le->refEntity.origin, enemyPos) > VectorDistance( le->refEntity.origin, newOrigin )) {

				trap_CM_BoxTrace( &trace, le->refEntity.origin, newOrigin, NULL, NULL, 0, MASK_SOLID );

				if (trace.fraction < 1.0) {
					// make sure we are not heading away from the enemy too much
					VectorNormalize2( le->pos.trDelta, v2 );
					if (DotProduct( v, v2 ) > 0.7) {
						// avoid world geometry
						backup = *le;
						le->bounceFactor = (1.0 - trace.fraction)*10.0*(float)step/1000.0;	// tracking and avoidance factor
						// reflect the velocity on the trace plane
						VectorMA( le->pos.trDelta, le->bounceFactor*oldSpeed, trace.plane.normal, le->pos.trDelta );
						if (VectorLength(le->pos.trDelta) < 1) {
							CG_FreeLocalEntity( le );
							return;
						}
						// the intersection is a fraction of the frametime
						le->pos.trTime = time;
						VectorCopy( le->refEntity.origin, le->pos.trBase );
						VectorNormalize( le->pos.trDelta );
						VectorScale( le->pos.trDelta, oldSpeed, le->pos.trDelta );
						//
						// double check end velocity
						VectorNormalize2( le->pos.trDelta, v2 );
						if (DotProduct( v, v2 ) <= 0.2) {
							// restore
							*le = backup;
						}
					}
				}
			}
		}

		// set the angles
		VectorNormalize2( le->pos.trDelta, v );
		// HACK!!! skull model is back-to-front, need to fix
		if (le->leType == LE_ZOMBIE_SPIRIT)
			VectorInverse( v );
		vectoangles( v, ang );
		AnglesToAxis( ang, le->refEntity.axis );
		// lean when turning
		if (le->leType == LE_ZOMBIE_BAT) {
			VectorSubtract( le->pos.trDelta, oDelta, v2 );
			ang[ROLL] = -5.0 * DotProduct( le->refEntity.axis[1], v2 );
			if (fabs(ang[ROLL]) > 80) {
				if (ang[ROLL] > 80) ang[ROLL] = 80;
				else ang[ROLL] = -80;
			}
		}
		AnglesToAxis( ang, le->refEntity.axis );

		// HACK: the skull is slightly higher than the origin
		if (le->leType == LE_ZOMBIE_SPIRIT) {
			// set the size scale
			for (i=0; i<3; i++)
				VectorScale( le->refEntity.axis[i], 0.35, le->refEntity.axis[i] );
			VectorMA( le->refEntity.origin, -10, le->refEntity.axis[2], le->refEntity.origin );
		}

		le->lastTrailTime = time;
		time += step;
	}

	// Bats, set the frame
	if (le->leType == LE_ZOMBIE_BAT) {
		#define	BAT_ANIM_FRAMETIME	30
		le->refEntity.frame = (cg.time/BAT_ANIM_FRAMETIME+1)%19;
		le->refEntity.oldframe = (cg.time/BAT_ANIM_FRAMETIME)%19;
		le->refEntity.backlerp = 1.0 - ((float)(cg.time%BAT_ANIM_FRAMETIME)/(float)BAT_ANIM_FRAMETIME);
	}

	// add the sound
	if (le->loopingSound) {
		if (cg.time > le->refEntity.fadeStartTime)
			trap_S_AddLoopingSound( 0, le->refEntity.origin, vec3_origin, le->loopingSound, 255 - (int)(255.0 * (float)(cg.time - le->refEntity.fadeStartTime) / (float)(le->refEntity.fadeEndTime - le->refEntity.fadeStartTime)) );
		else if (le->startTime + 1000 > cg.time)
			trap_S_AddLoopingSound( 0, le->refEntity.origin, vec3_origin, le->loopingSound, (int)(255.0 * (float)(cg.time - le->startTime) / 1000.0) );
		else
			trap_S_AddLoopingSound( 0, le->refEntity.origin, vec3_origin, le->loopingSound, 255);
	}

	trap_R_AddRefEntityToScene( &le->refEntity );
/*
	// HACK: the skull is slightly higher than the origin
	if (le->leType == LE_ZOMBIE_SPIRIT) {
		// set the size scale
		for (i=0; i<3; i++)
			VectorScale( le->refEntity.axis[i], 1.0/0.35, le->refEntity.axis[i] );
		VectorMA( le->refEntity.origin,  10, le->refEntity.axis[2], le->refEntity.origin );
	}
*/
	// Bats, add the flame
	if (le->leType == LE_ZOMBIE_BAT) {
//		float lightSize, alpha;
		//
		le->refEntity.shaderRGBA[3] = 255;
		VectorNormalize2( le->pos.trDelta, v );
		VectorInverse( v );
		v[2] += 1;
		VectorNormalize2( v, le->refEntity.fireRiseDir );

		le->refEntity.customShader = cgs.media.onFireShader2;
		trap_R_AddRefEntityToScene( &le->refEntity );
		le->refEntity.shaderTime = 1434;
		trap_R_AddRefEntityToScene( &le->refEntity );
//		le->refEntity.customShader = cgs.media.onFireShader;
//		le->refEntity.shaderTime = 0;
//		trap_R_AddRefEntityToScene( &le->refEntity );

		le->refEntity.customShader = 0;
		le->refEntity.shaderTime = 0;
/*
		// drop a dlight
		lightSize = 1.0 + 0.2*(sin(1.0*cg.time/50.0) * cos(1.0*cg.time/43.0));
		alpha = 0.2 * (lightSize / 1.2);
		trap_R_AddLightToScene( le->refEntity.origin, 150.0 + 80.0*lightSize, 1.000000*alpha, 0.603922*alpha, 0.207843*alpha, 0 );
		// add some sound
		trap_S_AddLoopingSound( -1, le->refEntity.origin, vec3_origin, cgs.media.flameSound, 100 );
		trap_S_AddLoopingSound( -1, le->refEntity.origin, vec3_origin, cgs.media.flameBlowSound, 100 );
*/
	}
}
Beispiel #3
0
/*
===============
CG_DynamicLightningBolt
===============
*/
void CG_DynamicLightningBolt( qhandle_t shader, vec3_t start, vec3_t pend, int numBolts, float maxWidth, qboolean fade, float startAlpha, int recursion, int randseed ) {
	int i,j;
	float segMin, segMax, length;
	float thisSeg, distLeft, thisWidth;
	vec3_t pos, vec, end;
	int curJunc;
	vec3_t c, bc = {0.8,0.9,1};
	const float rndSize = 12.0;
	const float maxSTscale = 30.0;
	float stScale;
	float alpha, viewDist;
	const int trailLife = 1;
	int forks = 0;
	#define STYPE_LIGHTNING     STYPE_REPEAT    // ST mapping for trail
	#define FORK_CHANCE     0.5
	#define VIEW_SCALE_DIST 128

	VectorCopy( pend, end );    // need this so recursive calls don't override stacked endpoints

	// HACK, updated sprite, so downscale all widths
	maxWidth *= 0.6;

	length = Distance( start, end );
	//if (length > 128) {
	segMin = length / 10.0;
	if ( segMin < 8 ) {
		segMin = 8;
	}
	segMax = segMin * 1.2;
	//segMax = length / 30.0;
	//} else {
	//	segMin = length / 3.0;
	//	segMax = length / 1.5;
	//}

	if ( startAlpha > 1.0 ) {
		startAlpha = 1.0;
	}
	alpha = startAlpha; // change only if fading

	for ( i = 0; i < numBolts; i++ )
	{
		distLeft = length;
		VectorCopy( start, pos );
		// drop a start junction
		stScale = maxSTscale * ( 0.5 + lt_random( randseed,i + 1 ) * 0.5 );
		if ( fade ) {
			if ( startAlpha == 1.0 ) {
				alpha = startAlpha * ( distLeft / length );
			} else {
				alpha = 1.0 - 1.0 * fabs( ( 1.0 - ( distLeft / length ) ) - startAlpha );
				if ( alpha < 0 ) {
					alpha = 0;
				}
				if ( alpha > 1 ) {
					alpha = 1;
				}
			}
		}
		thisWidth = maxWidth * ( 0.5 + 0.5 * alpha );
		if ( ( viewDist = VectorDistance( pos, cg.refdef.vieworg ) ) < VIEW_SCALE_DIST ) {
			thisWidth *= 0.5 + ( 0.5 * ( viewDist / VIEW_SCALE_DIST ) );
			if ( thisWidth < 4.0 && thisWidth < maxWidth ) {
				thisWidth = 4.0;
			}
		} else {    // scale it wider with distance so it remains visible
			thisWidth *= 0.5 + ( 0.5 * ( viewDist / VIEW_SCALE_DIST ) );
			if ( thisWidth > maxWidth * 2 ) {
				// thisWidth > maxWidth*2;
				thisWidth = maxWidth * 2;
			}
		}
		//
		VectorScale( bc, alpha, c );
		c[2] *= 1.0 + ( 1.0 - alpha );
		if ( c[2] > 1.0 ) {
			c[2] = 1.0;
		}
		//
		curJunc = CG_AddTrailJunc( 0, shader, cg.time, STYPE_LIGHTNING, pos, trailLife, 1, 1, thisWidth, thisWidth, TJFL_NOCULL, c, c, stScale, 20.0 );
		while ( distLeft > 0 )
		{   // create this bolt
			thisSeg = segMin + ( segMax - segMin ) * lt_random( randseed,2 );
			thisWidth = maxWidth * ( 0.5 + 0.5 * alpha );
			if ( thisSeg >= distLeft - rndSize ) { // go directly to the end point
				VectorCopy( end, pos );
				thisWidth *= 0.6;
			} else if ( (float)distLeft / length < 0.3 ) {
				VectorSubtract( end, pos, vec );
				VectorNormalize( vec );
				VectorMA( pos, thisSeg, vec, pos );
				// randomize the position a bit
				thisSeg *= 0.05;
				if ( thisSeg > rndSize ) {
					thisSeg = rndSize;
				}
				for ( j = 0; j < 3; j++ ) {
					viewDist = lt_crandom( randseed * randseed,j * j + i * i + 3 );
					if ( fabs( viewDist ) < 0.5 ) {
						if ( viewDist > 0 ) {
							viewDist = 0.5;
						} else { viewDist = -0.5;}
					}
					pos[j] += viewDist * thisSeg;
				}
			} else {
				VectorSubtract( end, pos, vec );
				VectorNormalize( vec );
				VectorMA( pos, thisSeg, vec, pos );
				// randomize the position a bit
				thisSeg *= 0.25;
				if ( thisSeg > rndSize ) {
					thisSeg = rndSize;
				}
				for ( j = 0; j < 3; j++ ) {
					viewDist = lt_crandom( randseed,j * j + i * i + 3 );
					if ( fabs( viewDist ) < 0.5 ) {
						if ( viewDist > 0 ) {
							viewDist = 0.5;
						} else { viewDist = -0.5;}
					}
					pos[j] += viewDist * thisSeg;
				}
			}

			distLeft = Distance( pos, end );
			if ( fade ) {
				if ( startAlpha == 1.0 ) {
					alpha = startAlpha * ( distLeft / length );
				} else {
					alpha = 1.0 - 1.0 * fabs( ( 1.0 - ( distLeft / length ) ) - startAlpha );
					if ( alpha < 0 ) {
						alpha = 0;
					}
					if ( alpha > 1 ) {
						alpha = 1;
					}
				}
			}
			//thisWidth *= alpha;
			if ( ( viewDist = VectorDistance( pos, cg.refdef.vieworg ) ) < VIEW_SCALE_DIST ) {
				thisWidth *= 0.5 + ( 0.5 * ( viewDist / VIEW_SCALE_DIST ) );
				if ( thisWidth < 4.0 && thisWidth < maxWidth ) {
					thisWidth = 4.0;
				}
			} else {    // scale it wider with distance so it remains visible
				thisWidth *= 0.5 + ( 0.5 * ( viewDist / VIEW_SCALE_DIST ) );
				if ( thisWidth > maxWidth * 2 ) {
					// thisWidth > maxWidth*2;
					thisWidth = maxWidth * 2;
				}

			}
			//
			VectorScale( bc, alpha, c );
			c[2] *= 1.0 + ( 1.0 - alpha );
			if ( c[2] > 1.0 ) {
				c[2] = 1.0;
			}
			//
			//stScale = maxSTscale * (0.4 + lt_random(randseed,1)*0.6);
			curJunc = CG_AddTrailJunc( curJunc, shader, cg.time, STYPE_LIGHTNING, pos, trailLife, 1, 1, thisWidth, thisWidth, TJFL_NOCULL, c, c, stScale, 20.0 );

			// fork from here?
			if ( thisWidth < 4 && distLeft > 10 && recursion < 3 && forks < 3 && lt_random( randseed,383 + i + forks ) < FORK_CHANCE ) {
				vec3_t fend;
				forks++;
				VectorSet( fend,
						   distLeft * 0.3 * lt_crandom( randseed,56 + i + forks ),
						   distLeft * 0.3 * lt_crandom( randseed,160 + i + forks ),
						   distLeft * 0.3 * lt_crandom( randseed,190 + i + forks ) );
				VectorAdd( fend, end, fend );
				VectorSubtract( fend, pos, fend );
				VectorMA( pos, 0.2 + 0.7 * lt_random( randseed,6 + i + forks ), fend, fend );

				//if (recursion > 0 && recursion < 2) {
				//	CG_DynamicLightningBolt( cgs.media.lightningBoltShader, pos, fend, 1, maxWidth, qtrue, alpha, recursion, randseed );
				//	return;	// divert bolt rather than split
				//} else {
				CG_DynamicLightningBolt( shader, pos, fend, 1, maxWidth, qtrue, alpha, recursion + 1, randseed + 765 );
				//}
			}

			randseed++;

		}
	}
}
Beispiel #4
0
// use this to change between particle and trail code
//#define BLOOD_PARTICLE_TRAIL
void CG_BloodTrail( localEntity_t *le ) {
	int		t;
	int		t2;
	int		step;
	vec3_t	newOrigin;

#ifndef BLOOD_PARTICLE_TRAIL
	static vec3_t col = {1,1,1};
#endif

centity_t	*cent;
cent = &cg_entities[le->ownerNum];

	if ( !cg_blood.integer ) {
		return;
	}

	// step = 150;
#ifdef BLOOD_PARTICLE_TRAIL
	step = 10;
#else
	// time it takes to move 3 units
	step = (1000*3)/VectorLength(le->pos.trDelta);
#endif

	if (cent && cent->currentState.aiChar == AICHAR_ZOMBIE)
		step = 30;

	t = step * ( (cg.time - cg.frametime + step ) / step );
	t2 = step * ( cg.time / step );

	for ( ; t <= t2; t += step ) {
		BG_EvaluateTrajectory( &le->pos, t, newOrigin );
		
#ifdef BLOOD_PARTICLE_TRAIL
		CG_Particle_Bleed (cgs.media.smokePuffShader, newOrigin, vec3_origin, 0, 500+rand()%200);
#else	
		
		
		if (cent && cent->currentState.aiChar == AICHAR_ZOMBIE)
		{
			CG_Particle_Bleed (cgs.media.smokePuffShader, newOrigin, vec3_origin, 1, 500+rand()%200);
		}
		else
		// Ridah, blood trail using trail code (should be faster since we don't have to spawn as many)
		le->headJuncIndex = CG_AddTrailJunc( le->headJuncIndex,
									cgs.media.bloodTrailShader,
									t,
									STYPE_STRETCH,
									newOrigin,
									180,
									1.0,	// start alpha
									0.0,	// end alpha
									12.0,
									12.0,
									TJFL_NOCULL,
									col, col,
									0, 0 );
#endif

	}
}
Beispiel #5
0
// use this to change between particle and trail code
//#define BLOOD_PARTICLE_TRAIL
void CG_BloodTrail( localEntity_t *le )
{
	int           t;
	int           t2;
	int           step;
	vec3_t        newOrigin;
	float         vl; //bani

#ifndef BLOOD_PARTICLE_TRAIL
	static vec3_t col = { 1, 1, 1 };
#endif

	centity_t     *cent;

	cent = &cg_entities[ le->ownerNum ];

	if ( !cg_blood.integer )
	{
		return;
	}

	// step = 150;
#ifdef BLOOD_PARTICLE_TRAIL
	step = 10;
#else
	// time it takes to move 3 units
	vl = VectorLength( le->pos.trDelta );

	// rain - need to check FLT_EPSILON because floating-point math sucks <3
	if ( vl < FLT_EPSILON )
	{
		return;
	}

	step = ( 1000 * 3 ) / vl;

//bani - avoid another div by 0
//zinx - check against <= 0 instead of == 0, because it can still wrap; (3000 / (FLT_EPSILON*11.7f)) < 0
	if ( step <= 0 )
	{
		return;
	}

#endif

	t = step * ( ( cg.time - cg.frametime + step ) / step );
	t2 = step * ( cg.time / step );

	for ( ; t <= t2; t += step )
	{
		BG_EvaluateTrajectory( &le->pos, t, newOrigin, qfalse, -1 );

#ifdef BLOOD_PARTICLE_TRAIL
		CG_Particle_Bleed( cgs.media.smokePuffShader, newOrigin, vec3_origin, 0, 500 + rand() % 200 );
#else
		// Ridah, blood trail using trail code (should be faster since we don't have to spawn as many)
		le->headJuncIndex = CG_AddTrailJunc( le->headJuncIndex, le,  // rain - zinx's trail fix
		                                     cgs.media.bloodTrailShader, t, STYPE_STRETCH, newOrigin, 180, 1.0, // start alpha
		                                     0.0, // end alpha
		                                     12.0, 12.0, TJFL_NOCULL, col, col, 0, 0 );
#endif
	}
}