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