void FX_8472Teleport( vec3_t org, int parm )
{
	int		i, t;
	vec3_t	dir = {0,0,1}, start, end, vel, color;

	if ( parm )
	{
		// Beaming out
		for ( i = 0; i < 32; i++ )
		{
			// Pick a random direction..
			VectorSet( dir, crandom(), crandom(), crandom() );
			VectorNormalize( dir );
			
			start[0] = org[0] + dir[0] * 26;
			start[1] = org[1] + dir[1] * 26;
			start[2] = org[2] + fabs(dir[2] * 10) - 18;

			// Now build the velocity vector
			vel[0] = dir[0] * 8;
			vel[1] = dir[1] * 8;
			vel[2] = dir[2] * 6;

			FX_AddSprite( start, vel, NULL, 
						24 + random() * 8, -18, 
						1.0, 0.0, 
						crandom()*180,0, 
						1000, cgs.media.portalFlareShader, FXF_NON_LINEAR_FADE );
		}

		cgi_S_StartSound( org, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.speciesBeamoutSound );
	}
	else
	{
		// Beaming in
		VectorMA( org, 65, dir, start );
		VectorMA( org, -40, dir, end );

		FX_AddLine( start, end, 1.0f, 0.5f, 48.0f, 0.4f, 0.1f, 1500, cgs.media.speciesPortalShader, FXF_NON_LINEAR_FADE );

		for ( i = -1; i <= 1; i++ )
		{ 
			VectorCopy( org, start );
			start[2] += 10.0f + i * 16.0f;

			for ( t = -1; t <= 1; t++ ) 
			{
				// create a 3 x 3 grid of starting points for the effect
				VectorClear( vel );
				VectorMA( vel, t * 16, cg.refdef.viewaxis[1], vel );
				
				FX_AddSprite( start, vel, NULL, 56.0f, -10.0f, 0.3f, 0.0f, -90.0f, 0, 1800, cgs.media.portalFlareShader, FXF_NON_LINEAR_FADE );
			}
		}

		cgi_S_StartSound( org, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.speciesBeaminSound );
	}

	VectorSet( color, 1.0f, 1.0f, 0.7f );
	CG_AddTempLight( org, 200, color, 1000 );
}
Beispiel #2
0
void CG_Chunks( int owner, vec3_t origin, const vec3_t normal, const vec3_t mins, const vec3_t maxs, 
						float speed, int numChunks, material_t chunkType, int customChunk, float baseScale, int customSound = 0 )
{
	localEntity_t	*le;
	refEntity_t		*re;
	vec3_t			dir;
	int				i, j, k;
	int				chunkModel = 0;
	leBounceSound_t	bounce = LEBS_NONE;
	float			r, speedMod = 1.0f;
	qboolean		chunk = qfalse;

	if ( chunkType == MAT_NONE )
	{
		// Well, we should do nothing
		return;
	}

	if ( customSound )
	{
		if ( cgs.sound_precache[customSound] ) 
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.sound_precache[customSound] );
		}
	}
	// Set up our chunk sound info...breaking sounds are done here so they are done once on breaking..some return instantly because the chunks are done with effects instead of models
	switch( chunkType )
	{
	case MAT_GLASS:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.glassChunkSound );
		}
		return;
		break;
	case MAT_GRATE1:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.grateSound );
		}
		return;
		break;
	case MAT_ELECTRICAL:// (sparks)
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgi_S_RegisterSound (va("sound/ambience/spark%d.wav", Q_irand(1, 6))) );
		}
		return;
		break;
	case MAT_DRK_STONE:
	case MAT_LT_STONE:
	case MAT_GREY_STONE:
	case MAT_WHITE_METAL:  // not quite sure what this stuff is supposed to be...it's for Stu
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.rockBreakSound );
			bounce = LEBS_ROCK;
		}
		speedMod = 0.5f; // rock blows up less
		break;
	case MAT_GLASS_METAL:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.glassChunkSound ); // FIXME: should probably have a custom sound
			bounce = LEBS_METAL;
		}
		break;
	case MAT_CRATE1:
	case MAT_CRATE2:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.crateBreakSound[Q_irand(0,1)] );
		}
		break;
	case MAT_METAL:
	case MAT_METAL2:
	case MAT_METAL3:
	case MAT_ELEC_METAL:// FIXME: maybe have its own sound?
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.chunkSound );
			bounce = LEBS_METAL;
		}
		speedMod = 0.8f; // metal blows up a bit more
		break;
	case MAT_ROPE:
		/*
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgi_S_RegisterSound( "" ));  FIXME:  needs a sound
		}
		*/
		return;
		break;
	}

	if ( baseScale <= 0.0f )
	{
		baseScale = 1.0f;
	}

	// Chunks
	for( i = 0; i < numChunks; i++ )
	{
		if ( customChunk > 0 )
		{
			// Try to use a custom chunk.
			if ( cgs.model_draw[customChunk] )
			{
				chunk = qtrue;
				chunkModel = cgs.model_draw[customChunk];
			}
		}

		if ( !chunk )
		{
			// No custom chunk.  Pick a random chunk type at run-time so we don't get the same chunks
			switch( chunkType )
			{
			case MAT_METAL2: //bluegrey
				chunkModel = cgs.media.chunkModels[CHUNK_METAL2][Q_irand(0, 3)];
				break;
			case MAT_GREY_STONE://gray
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK1][Q_irand(0, 3)];
				break;
			case MAT_LT_STONE: //tan
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK2][Q_irand(0, 3)];
				break;
			case MAT_DRK_STONE://brown
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK3][Q_irand(0, 3)];
				break;
			case MAT_WHITE_METAL:
				chunkModel = cgs.media.chunkModels[CHUNK_WHITE_METAL][Q_irand(0, 3)];
				break;
			case MAT_CRATE1://yellow multi-colored crate chunks
				chunkModel = cgs.media.chunkModels[CHUNK_CRATE1][Q_irand(0, 3)];
				break;
			case MAT_CRATE2://red multi-colored crate chunks
				chunkModel = cgs.media.chunkModels[CHUNK_CRATE2][Q_irand(0, 3)];
				break;
			case MAT_ELEC_METAL:
			case MAT_GLASS_METAL:
			case MAT_METAL://grey
				chunkModel = cgs.media.chunkModels[CHUNK_METAL1][Q_irand(0, 3)];
				break;
			case MAT_METAL3:
				if ( rand() & 1 )
				{
					chunkModel = cgs.media.chunkModels[CHUNK_METAL1][Q_irand(0, 3)];
				}
				else
				{
					chunkModel = cgs.media.chunkModels[CHUNK_METAL2][Q_irand(0, 3)];
				}
				break;
			}
		}

		// It wouldn't look good to throw a bunch of RGB axis models...so make sure we have something to work with.
		if ( chunkModel )
		{
			le = CG_AllocLocalEntity();
			re = &le->refEntity;

			re->hModel = chunkModel;
			le->leType = LE_FRAGMENT;
			le->endTime = cg.time + 1300 + random() * 900;

			// spawn chunk roughly in the bbox of the thing...bias towards center in case thing blowing up doesn't complete fill its bbox.
			for( j = 0; j < 3; j++ )
			{
				r = random() * 0.8f + 0.1f;
				re->origin[j] = ( r * mins[j] + ( 1 - r ) * maxs[j] );
			}
			VectorCopy( re->origin, le->pos.trBase );

			// Move out from center of thing, otherwise you can end up things moving across the brush in an undesirable direction.  Visually looks wrong
			VectorSubtract( re->origin, origin, dir );
			VectorNormalize( dir );
			VectorScale( dir, Q_flrand( speed * 0.5f, speed * 1.25f ) * speedMod, le->pos.trDelta );

			// Angular Velocity
			VectorSet( le->angles.trBase, random() * 360, random() * 360, random() * 360 );

			le->angles.trDelta[0] = crandom();
			le->angles.trDelta[1] = crandom();
			le->angles.trDelta[2] = 0; // don't do roll

			VectorScale( le->angles.trDelta, random() * 600.0f + 200.0f, le->angles.trDelta );

			le->pos.trType = TR_GRAVITY;
			le->angles.trType = TR_LINEAR;
			le->pos.trTime = le->angles.trTime = cg.time;
			le->bounceFactor = 0.2f + random() * 0.2f;
			le->leFlags |= LEF_TUMBLE;
			le->ownerGentNum = owner;
			le->leBounceSoundType = bounce; 

			// Make sure that we have the desired start size set
			le->radius = Q_flrand( baseScale * 0.75f, baseScale * 1.25f );
			re->nonNormalizedAxes = qtrue;
			AxisCopy( axisDefault, re->axis ); // could do an angles to axis, but this is cheaper and works ok
			for( k = 0; k < 3; k++ )
			{
				VectorScale( re->axis[k], le->radius, re->axis[k] );
			}
		}
	}
}
void FX_Transporter( vec3_t org )//,qboolean replicator
{
	//FIXME: maybe find head tag and center of feet and make balls go between them (for horizontal people)
	FX_AddSpawner( org, NULL, NULL, NULL, 500, 0, 650, (void *) TransporterParticle );
	cgi_S_StartSound( org, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.transporterSound );
}