Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

cg_effects.c (17147B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 //
     23 // cg_effects.c -- these functions generate localentities, usually as a result
     24 // of event processing
     25 
     26 #include "cg_local.h"
     27 
     28 
     29 /*
     30 ==================
     31 CG_BubbleTrail
     32 
     33 Bullets shot underwater
     34 ==================
     35 */
     36 void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ) {
     37 	vec3_t		move;
     38 	vec3_t		vec;
     39 	float		len;
     40 	int			i;
     41 
     42 	if ( cg_noProjectileTrail.integer ) {
     43 		return;
     44 	}
     45 
     46 	VectorCopy (start, move);
     47 	VectorSubtract (end, start, vec);
     48 	len = VectorNormalize (vec);
     49 
     50 	// advance a random amount first
     51 	i = rand() % (int)spacing;
     52 	VectorMA( move, i, vec, move );
     53 
     54 	VectorScale (vec, spacing, vec);
     55 
     56 	for ( ; i < len; i += spacing ) {
     57 		localEntity_t	*le;
     58 		refEntity_t		*re;
     59 
     60 		le = CG_AllocLocalEntity();
     61 		le->leFlags = LEF_PUFF_DONT_SCALE;
     62 		le->leType = LE_MOVE_SCALE_FADE;
     63 		le->startTime = cg.time;
     64 		le->endTime = cg.time + 1000 + random() * 250;
     65 		le->lifeRate = 1.0 / ( le->endTime - le->startTime );
     66 
     67 		re = &le->refEntity;
     68 		re->shaderTime = cg.time / 1000.0f;
     69 
     70 		re->reType = RT_SPRITE;
     71 		re->rotation = 0;
     72 		re->radius = 3;
     73 		re->customShader = cgs.media.waterBubbleShader;
     74 		re->shaderRGBA[0] = 0xff;
     75 		re->shaderRGBA[1] = 0xff;
     76 		re->shaderRGBA[2] = 0xff;
     77 		re->shaderRGBA[3] = 0xff;
     78 
     79 		le->color[3] = 1.0;
     80 
     81 		le->pos.trType = TR_LINEAR;
     82 		le->pos.trTime = cg.time;
     83 		VectorCopy( move, le->pos.trBase );
     84 		le->pos.trDelta[0] = crandom()*5;
     85 		le->pos.trDelta[1] = crandom()*5;
     86 		le->pos.trDelta[2] = crandom()*5 + 6;
     87 
     88 		VectorAdd (move, vec, move);
     89 	}
     90 }
     91 
     92 /*
     93 =====================
     94 CG_SmokePuff
     95 
     96 Adds a smoke puff or blood trail localEntity.
     97 =====================
     98 */
     99 localEntity_t *CG_SmokePuff( const vec3_t p, const vec3_t vel, 
    100 				   float radius,
    101 				   float r, float g, float b, float a,
    102 				   float duration,
    103 				   int startTime,
    104 				   int fadeInTime,
    105 				   int leFlags,
    106 				   qhandle_t hShader ) {
    107 	static int	seed = 0x92;
    108 	localEntity_t	*le;
    109 	refEntity_t		*re;
    110 //	int fadeInTime = startTime + duration / 2;
    111 
    112 	le = CG_AllocLocalEntity();
    113 	le->leFlags = leFlags;
    114 	le->radius = radius;
    115 
    116 	re = &le->refEntity;
    117 	re->rotation = Q_random( &seed ) * 360;
    118 	re->radius = radius;
    119 	re->shaderTime = startTime / 1000.0f;
    120 
    121 	le->leType = LE_MOVE_SCALE_FADE;
    122 	le->startTime = startTime;
    123 	le->fadeInTime = fadeInTime;
    124 	le->endTime = startTime + duration;
    125 	if ( fadeInTime > startTime ) {
    126 		le->lifeRate = 1.0 / ( le->endTime - le->fadeInTime );
    127 	}
    128 	else {
    129 		le->lifeRate = 1.0 / ( le->endTime - le->startTime );
    130 	}
    131 	le->color[0] = r;
    132 	le->color[1] = g; 
    133 	le->color[2] = b;
    134 	le->color[3] = a;
    135 
    136 
    137 	le->pos.trType = TR_LINEAR;
    138 	le->pos.trTime = startTime;
    139 	VectorCopy( vel, le->pos.trDelta );
    140 	VectorCopy( p, le->pos.trBase );
    141 
    142 	VectorCopy( p, re->origin );
    143 	re->customShader = hShader;
    144 
    145 	// rage pro can't alpha fade, so use a different shader
    146 	if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
    147 		re->customShader = cgs.media.smokePuffRageProShader;
    148 		re->shaderRGBA[0] = 0xff;
    149 		re->shaderRGBA[1] = 0xff;
    150 		re->shaderRGBA[2] = 0xff;
    151 		re->shaderRGBA[3] = 0xff;
    152 	} else {
    153 		re->shaderRGBA[0] = le->color[0] * 0xff;
    154 		re->shaderRGBA[1] = le->color[1] * 0xff;
    155 		re->shaderRGBA[2] = le->color[2] * 0xff;
    156 		re->shaderRGBA[3] = 0xff;
    157 	}
    158 
    159 	re->reType = RT_SPRITE;
    160 	re->radius = le->radius;
    161 
    162 	return le;
    163 }
    164 
    165 /*
    166 ==================
    167 CG_SpawnEffect
    168 
    169 Player teleporting in or out
    170 ==================
    171 */
    172 void CG_SpawnEffect( vec3_t org ) {
    173 	localEntity_t	*le;
    174 	refEntity_t		*re;
    175 
    176 	le = CG_AllocLocalEntity();
    177 	le->leFlags = 0;
    178 	le->leType = LE_FADE_RGB;
    179 	le->startTime = cg.time;
    180 	le->endTime = cg.time + 500;
    181 	le->lifeRate = 1.0 / ( le->endTime - le->startTime );
    182 
    183 	le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
    184 
    185 	re = &le->refEntity;
    186 
    187 	re->reType = RT_MODEL;
    188 	re->shaderTime = cg.time / 1000.0f;
    189 
    190 #ifndef MISSIONPACK
    191 	re->customShader = cgs.media.teleportEffectShader;
    192 #endif
    193 	re->hModel = cgs.media.teleportEffectModel;
    194 	AxisClear( re->axis );
    195 
    196 	VectorCopy( org, re->origin );
    197 #ifdef MISSIONPACK
    198 	re->origin[2] += 16;
    199 #else
    200 	re->origin[2] -= 24;
    201 #endif
    202 }
    203 
    204 
    205 #ifdef MISSIONPACK
    206 /*
    207 ===============
    208 CG_LightningBoltBeam
    209 ===============
    210 */
    211 void CG_LightningBoltBeam( vec3_t start, vec3_t end ) {
    212 	localEntity_t	*le;
    213 	refEntity_t		*beam;
    214 
    215 	le = CG_AllocLocalEntity();
    216 	le->leFlags = 0;
    217 	le->leType = LE_SHOWREFENTITY;
    218 	le->startTime = cg.time;
    219 	le->endTime = cg.time + 50;
    220 
    221 	beam = &le->refEntity;
    222 
    223 	VectorCopy( start, beam->origin );
    224 	// this is the end point
    225 	VectorCopy( end, beam->oldorigin );
    226 
    227 	beam->reType = RT_LIGHTNING;
    228 	beam->customShader = cgs.media.lightningShader;
    229 }
    230 
    231 /*
    232 ==================
    233 CG_KamikazeEffect
    234 ==================
    235 */
    236 void CG_KamikazeEffect( vec3_t org ) {
    237 	localEntity_t	*le;
    238 	refEntity_t		*re;
    239 
    240 	le = CG_AllocLocalEntity();
    241 	le->leFlags = 0;
    242 	le->leType = LE_KAMIKAZE;
    243 	le->startTime = cg.time;
    244 	le->endTime = cg.time + 3000;//2250;
    245 	le->lifeRate = 1.0 / ( le->endTime - le->startTime );
    246 
    247 	le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
    248 
    249 	VectorClear(le->angles.trBase);
    250 
    251 	re = &le->refEntity;
    252 
    253 	re->reType = RT_MODEL;
    254 	re->shaderTime = cg.time / 1000.0f;
    255 
    256 	re->hModel = cgs.media.kamikazeEffectModel;
    257 
    258 	VectorCopy( org, re->origin );
    259 
    260 }
    261 
    262 /*
    263 ==================
    264 CG_ObeliskExplode
    265 ==================
    266 */
    267 void CG_ObeliskExplode( vec3_t org, int entityNum ) {
    268 	localEntity_t	*le;
    269 	vec3_t origin;
    270 
    271 	// create an explosion
    272 	VectorCopy( org, origin );
    273 	origin[2] += 64;
    274 	le = CG_MakeExplosion( origin, vec3_origin,
    275 						   cgs.media.dishFlashModel,
    276 						   cgs.media.rocketExplosionShader,
    277 						   600, qtrue );
    278 	le->light = 300;
    279 	le->lightColor[0] = 1;
    280 	le->lightColor[1] = 0.75;
    281 	le->lightColor[2] = 0.0;
    282 }
    283 
    284 /*
    285 ==================
    286 CG_ObeliskPain
    287 ==================
    288 */
    289 void CG_ObeliskPain( vec3_t org ) {
    290 	float r;
    291 	sfxHandle_t sfx;
    292 
    293 	// hit sound
    294 	r = rand() & 3;
    295 	if ( r < 2 ) {
    296 		sfx = cgs.media.obeliskHitSound1;
    297 	} else if ( r == 2 ) {
    298 		sfx = cgs.media.obeliskHitSound2;
    299 	} else {
    300 		sfx = cgs.media.obeliskHitSound3;
    301 	}
    302 	trap_S_StartSound ( org, ENTITYNUM_NONE, CHAN_BODY, sfx );
    303 }
    304 
    305 
    306 /*
    307 ==================
    308 CG_InvulnerabilityImpact
    309 ==================
    310 */
    311 void CG_InvulnerabilityImpact( vec3_t org, vec3_t angles ) {
    312 	localEntity_t	*le;
    313 	refEntity_t		*re;
    314 	int				r;
    315 	sfxHandle_t		sfx;
    316 
    317 	le = CG_AllocLocalEntity();
    318 	le->leFlags = 0;
    319 	le->leType = LE_INVULIMPACT;
    320 	le->startTime = cg.time;
    321 	le->endTime = cg.time + 1000;
    322 	le->lifeRate = 1.0 / ( le->endTime - le->startTime );
    323 
    324 	le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
    325 
    326 	re = &le->refEntity;
    327 
    328 	re->reType = RT_MODEL;
    329 	re->shaderTime = cg.time / 1000.0f;
    330 
    331 	re->hModel = cgs.media.invulnerabilityImpactModel;
    332 
    333 	VectorCopy( org, re->origin );
    334 	AnglesToAxis( angles, re->axis );
    335 
    336 	r = rand() & 3;
    337 	if ( r < 2 ) {
    338 		sfx = cgs.media.invulnerabilityImpactSound1;
    339 	} else if ( r == 2 ) {
    340 		sfx = cgs.media.invulnerabilityImpactSound2;
    341 	} else {
    342 		sfx = cgs.media.invulnerabilityImpactSound3;
    343 	}
    344 	trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, sfx );
    345 }
    346 
    347 /*
    348 ==================
    349 CG_InvulnerabilityJuiced
    350 ==================
    351 */
    352 void CG_InvulnerabilityJuiced( vec3_t org ) {
    353 	localEntity_t	*le;
    354 	refEntity_t		*re;
    355 	vec3_t			angles;
    356 
    357 	le = CG_AllocLocalEntity();
    358 	le->leFlags = 0;
    359 	le->leType = LE_INVULJUICED;
    360 	le->startTime = cg.time;
    361 	le->endTime = cg.time + 10000;
    362 	le->lifeRate = 1.0 / ( le->endTime - le->startTime );
    363 
    364 	le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
    365 
    366 	re = &le->refEntity;
    367 
    368 	re->reType = RT_MODEL;
    369 	re->shaderTime = cg.time / 1000.0f;
    370 
    371 	re->hModel = cgs.media.invulnerabilityJuicedModel;
    372 
    373 	VectorCopy( org, re->origin );
    374 	VectorClear(angles);
    375 	AnglesToAxis( angles, re->axis );
    376 
    377 	trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, cgs.media.invulnerabilityJuicedSound );
    378 }
    379 
    380 #endif
    381 
    382 /*
    383 ==================
    384 CG_ScorePlum
    385 ==================
    386 */
    387 void CG_ScorePlum( int client, vec3_t org, int score ) {
    388 	localEntity_t	*le;
    389 	refEntity_t		*re;
    390 	vec3_t			angles;
    391 	static vec3_t lastPos;
    392 
    393 	// only visualize for the client that scored
    394 	if (client != cg.predictedPlayerState.clientNum || cg_scorePlum.integer == 0) {
    395 		return;
    396 	}
    397 
    398 	le = CG_AllocLocalEntity();
    399 	le->leFlags = 0;
    400 	le->leType = LE_SCOREPLUM;
    401 	le->startTime = cg.time;
    402 	le->endTime = cg.time + 4000;
    403 	le->lifeRate = 1.0 / ( le->endTime - le->startTime );
    404 
    405 	
    406 	le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
    407 	le->radius = score;
    408 	
    409 	VectorCopy( org, le->pos.trBase );
    410 	if (org[2] >= lastPos[2] - 20 && org[2] <= lastPos[2] + 20) {
    411 		le->pos.trBase[2] -= 20;
    412 	}
    413 
    414 	//CG_Printf( "Plum origin %i %i %i -- %i\n", (int)org[0], (int)org[1], (int)org[2], (int)Distance(org, lastPos));
    415 	VectorCopy(org, lastPos);
    416 
    417 
    418 	re = &le->refEntity;
    419 
    420 	re->reType = RT_SPRITE;
    421 	re->radius = 16;
    422 
    423 	VectorClear(angles);
    424 	AnglesToAxis( angles, re->axis );
    425 }
    426 
    427 
    428 /*
    429 ====================
    430 CG_MakeExplosion
    431 ====================
    432 */
    433 localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir, 
    434 								qhandle_t hModel, qhandle_t shader,
    435 								int msec, qboolean isSprite ) {
    436 	float			ang;
    437 	localEntity_t	*ex;
    438 	int				offset;
    439 	vec3_t			tmpVec, newOrigin;
    440 
    441 	if ( msec <= 0 ) {
    442 		CG_Error( "CG_MakeExplosion: msec = %i", msec );
    443 	}
    444 
    445 	// skew the time a bit so they aren't all in sync
    446 	offset = rand() & 63;
    447 
    448 	ex = CG_AllocLocalEntity();
    449 	if ( isSprite ) {
    450 		ex->leType = LE_SPRITE_EXPLOSION;
    451 
    452 		// randomly rotate sprite orientation
    453 		ex->refEntity.rotation = rand() % 360;
    454 		VectorScale( dir, 16, tmpVec );
    455 		VectorAdd( tmpVec, origin, newOrigin );
    456 	} else {
    457 		ex->leType = LE_EXPLOSION;
    458 		VectorCopy( origin, newOrigin );
    459 
    460 		// set axis with random rotate
    461 		if ( !dir ) {
    462 			AxisClear( ex->refEntity.axis );
    463 		} else {
    464 			ang = rand() % 360;
    465 			VectorCopy( dir, ex->refEntity.axis[0] );
    466 			RotateAroundDirection( ex->refEntity.axis, ang );
    467 		}
    468 	}
    469 
    470 	ex->startTime = cg.time - offset;
    471 	ex->endTime = ex->startTime + msec;
    472 
    473 	// bias the time so all shader effects start correctly
    474 	ex->refEntity.shaderTime = ex->startTime / 1000.0f;
    475 
    476 	ex->refEntity.hModel = hModel;
    477 	ex->refEntity.customShader = shader;
    478 
    479 	// set origin
    480 	VectorCopy( newOrigin, ex->refEntity.origin );
    481 	VectorCopy( newOrigin, ex->refEntity.oldorigin );
    482 
    483 	ex->color[0] = ex->color[1] = ex->color[2] = 1.0;
    484 
    485 	return ex;
    486 }
    487 
    488 
    489 /*
    490 =================
    491 CG_Bleed
    492 
    493 This is the spurt of blood when a character gets hit
    494 =================
    495 */
    496 void CG_Bleed( vec3_t origin, int entityNum ) {
    497 	localEntity_t	*ex;
    498 
    499 	if ( !cg_blood.integer ) {
    500 		return;
    501 	}
    502 
    503 	ex = CG_AllocLocalEntity();
    504 	ex->leType = LE_EXPLOSION;
    505 
    506 	ex->startTime = cg.time;
    507 	ex->endTime = ex->startTime + 500;
    508 	
    509 	VectorCopy ( origin, ex->refEntity.origin);
    510 	ex->refEntity.reType = RT_SPRITE;
    511 	ex->refEntity.rotation = rand() % 360;
    512 	ex->refEntity.radius = 24;
    513 
    514 	ex->refEntity.customShader = cgs.media.bloodExplosionShader;
    515 
    516 	// don't show player's own blood in view
    517 	if ( entityNum == cg.snap->ps.clientNum ) {
    518 		ex->refEntity.renderfx |= RF_THIRD_PERSON;
    519 	}
    520 }
    521 
    522 
    523 
    524 /*
    525 ==================
    526 CG_LaunchGib
    527 ==================
    528 */
    529 void CG_LaunchGib( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
    530 	localEntity_t	*le;
    531 	refEntity_t		*re;
    532 
    533 	le = CG_AllocLocalEntity();
    534 	re = &le->refEntity;
    535 
    536 	le->leType = LE_FRAGMENT;
    537 	le->startTime = cg.time;
    538 	le->endTime = le->startTime + 5000 + random() * 3000;
    539 
    540 	VectorCopy( origin, re->origin );
    541 	AxisCopy( axisDefault, re->axis );
    542 	re->hModel = hModel;
    543 
    544 	le->pos.trType = TR_GRAVITY;
    545 	VectorCopy( origin, le->pos.trBase );
    546 	VectorCopy( velocity, le->pos.trDelta );
    547 	le->pos.trTime = cg.time;
    548 
    549 	le->bounceFactor = 0.6f;
    550 
    551 	le->leBounceSoundType = LEBS_BLOOD;
    552 	le->leMarkType = LEMT_BLOOD;
    553 }
    554 
    555 /*
    556 ===================
    557 CG_GibPlayer
    558 
    559 Generated a bunch of gibs launching out from the bodies location
    560 ===================
    561 */
    562 #define	GIB_VELOCITY	250
    563 #define	GIB_JUMP		250
    564 void CG_GibPlayer( vec3_t playerOrigin ) {
    565 	vec3_t	origin, velocity;
    566 
    567 	if ( !cg_blood.integer ) {
    568 		return;
    569 	}
    570 
    571 	VectorCopy( playerOrigin, origin );
    572 	velocity[0] = crandom()*GIB_VELOCITY;
    573 	velocity[1] = crandom()*GIB_VELOCITY;
    574 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    575 	if ( rand() & 1 ) {
    576 		CG_LaunchGib( origin, velocity, cgs.media.gibSkull );
    577 	} else {
    578 		CG_LaunchGib( origin, velocity, cgs.media.gibBrain );
    579 	}
    580 
    581 	// allow gibs to be turned off for speed
    582 	if ( !cg_gibs.integer ) {
    583 		return;
    584 	}
    585 
    586 	VectorCopy( playerOrigin, origin );
    587 	velocity[0] = crandom()*GIB_VELOCITY;
    588 	velocity[1] = crandom()*GIB_VELOCITY;
    589 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    590 	CG_LaunchGib( origin, velocity, cgs.media.gibAbdomen );
    591 
    592 	VectorCopy( playerOrigin, origin );
    593 	velocity[0] = crandom()*GIB_VELOCITY;
    594 	velocity[1] = crandom()*GIB_VELOCITY;
    595 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    596 	CG_LaunchGib( origin, velocity, cgs.media.gibArm );
    597 
    598 	VectorCopy( playerOrigin, origin );
    599 	velocity[0] = crandom()*GIB_VELOCITY;
    600 	velocity[1] = crandom()*GIB_VELOCITY;
    601 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    602 	CG_LaunchGib( origin, velocity, cgs.media.gibChest );
    603 
    604 	VectorCopy( playerOrigin, origin );
    605 	velocity[0] = crandom()*GIB_VELOCITY;
    606 	velocity[1] = crandom()*GIB_VELOCITY;
    607 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    608 	CG_LaunchGib( origin, velocity, cgs.media.gibFist );
    609 
    610 	VectorCopy( playerOrigin, origin );
    611 	velocity[0] = crandom()*GIB_VELOCITY;
    612 	velocity[1] = crandom()*GIB_VELOCITY;
    613 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    614 	CG_LaunchGib( origin, velocity, cgs.media.gibFoot );
    615 
    616 	VectorCopy( playerOrigin, origin );
    617 	velocity[0] = crandom()*GIB_VELOCITY;
    618 	velocity[1] = crandom()*GIB_VELOCITY;
    619 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    620 	CG_LaunchGib( origin, velocity, cgs.media.gibForearm );
    621 
    622 	VectorCopy( playerOrigin, origin );
    623 	velocity[0] = crandom()*GIB_VELOCITY;
    624 	velocity[1] = crandom()*GIB_VELOCITY;
    625 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    626 	CG_LaunchGib( origin, velocity, cgs.media.gibIntestine );
    627 
    628 	VectorCopy( playerOrigin, origin );
    629 	velocity[0] = crandom()*GIB_VELOCITY;
    630 	velocity[1] = crandom()*GIB_VELOCITY;
    631 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    632 	CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
    633 
    634 	VectorCopy( playerOrigin, origin );
    635 	velocity[0] = crandom()*GIB_VELOCITY;
    636 	velocity[1] = crandom()*GIB_VELOCITY;
    637 	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
    638 	CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
    639 }
    640 
    641 /*
    642 ==================
    643 CG_LaunchGib
    644 ==================
    645 */
    646 void CG_LaunchExplode( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
    647 	localEntity_t	*le;
    648 	refEntity_t		*re;
    649 
    650 	le = CG_AllocLocalEntity();
    651 	re = &le->refEntity;
    652 
    653 	le->leType = LE_FRAGMENT;
    654 	le->startTime = cg.time;
    655 	le->endTime = le->startTime + 10000 + random() * 6000;
    656 
    657 	VectorCopy( origin, re->origin );
    658 	AxisCopy( axisDefault, re->axis );
    659 	re->hModel = hModel;
    660 
    661 	le->pos.trType = TR_GRAVITY;
    662 	VectorCopy( origin, le->pos.trBase );
    663 	VectorCopy( velocity, le->pos.trDelta );
    664 	le->pos.trTime = cg.time;
    665 
    666 	le->bounceFactor = 0.1f;
    667 
    668 	le->leBounceSoundType = LEBS_BRASS;
    669 	le->leMarkType = LEMT_NONE;
    670 }
    671 
    672 #define	EXP_VELOCITY	100
    673 #define	EXP_JUMP		150
    674 /*
    675 ===================
    676 CG_GibPlayer
    677 
    678 Generated a bunch of gibs launching out from the bodies location
    679 ===================
    680 */
    681 void CG_BigExplode( vec3_t playerOrigin ) {
    682 	vec3_t	origin, velocity;
    683 
    684 	if ( !cg_blood.integer ) {
    685 		return;
    686 	}
    687 
    688 	VectorCopy( playerOrigin, origin );
    689 	velocity[0] = crandom()*EXP_VELOCITY;
    690 	velocity[1] = crandom()*EXP_VELOCITY;
    691 	velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
    692 	CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
    693 
    694 	VectorCopy( playerOrigin, origin );
    695 	velocity[0] = crandom()*EXP_VELOCITY;
    696 	velocity[1] = crandom()*EXP_VELOCITY;
    697 	velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
    698 	CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
    699 
    700 	VectorCopy( playerOrigin, origin );
    701 	velocity[0] = crandom()*EXP_VELOCITY*1.5;
    702 	velocity[1] = crandom()*EXP_VELOCITY*1.5;
    703 	velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
    704 	CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
    705 
    706 	VectorCopy( playerOrigin, origin );
    707 	velocity[0] = crandom()*EXP_VELOCITY*2.0;
    708 	velocity[1] = crandom()*EXP_VELOCITY*2.0;
    709 	velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
    710 	CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
    711 
    712 	VectorCopy( playerOrigin, origin );
    713 	velocity[0] = crandom()*EXP_VELOCITY*2.5;
    714 	velocity[1] = crandom()*EXP_VELOCITY*2.5;
    715 	velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
    716 	CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
    717 }
    718