1402 lines
36 KiB
C
1402 lines
36 KiB
C
// Copyright (C) 1999-2000 Id Software, Inc.
|
|
//
|
|
// cg_effects.c -- these functions generate localentities, usually as a result
|
|
// of event processing
|
|
|
|
#include "cg_local.h"
|
|
|
|
|
|
/*
|
|
==================
|
|
CG_BubbleTrail
|
|
|
|
Bullets shot underwater
|
|
==================
|
|
*/
|
|
void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ) {
|
|
vec3_t move;
|
|
vec3_t vec;
|
|
float len;
|
|
int i;
|
|
|
|
if ( cg_noProjectileTrail.integer ) {
|
|
return;
|
|
}
|
|
|
|
VectorCopy (start, move);
|
|
VectorSubtract (end, start, vec);
|
|
len = VectorNormalize (vec);
|
|
|
|
// advance a random amount first
|
|
i = rand() % (int)spacing;
|
|
VectorMA( move, i, vec, move );
|
|
|
|
VectorScale (vec, spacing, vec);
|
|
|
|
for ( ; i < len; i += spacing ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = LEF_PUFF_DONT_SCALE;
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 1000 + random() * 250;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
re = &le->refEntity;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->reType = RT_SPRITE;
|
|
re->rotation = 0;
|
|
re->radius = 3;
|
|
re->customShader = cgs.media.waterBubbleShader;
|
|
re->shaderRGBA[0] = 0xff;
|
|
re->shaderRGBA[1] = 0xff;
|
|
re->shaderRGBA[2] = 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
|
|
le->color[3] = 1.0;
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
VectorCopy( move, le->pos.trBase );
|
|
le->pos.trDelta[0] = crandom()*5;
|
|
le->pos.trDelta[1] = crandom()*5;
|
|
le->pos.trDelta[2] = crandom()*5 + 6;
|
|
|
|
VectorAdd (move, vec, move);
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
CG_SmokePuff
|
|
|
|
Adds a smoke puff or blood trail localEntity.
|
|
=====================
|
|
*/
|
|
localEntity_t *CG_SmokePuff( const vec3_t p, const vec3_t vel,
|
|
float radius,
|
|
float r, float g, float b, float a,
|
|
float duration,
|
|
int startTime,
|
|
int fadeInTime,
|
|
int leFlags,
|
|
qhandle_t hShader ) {
|
|
static int seed = 0x92;
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
// int fadeInTime = startTime + duration / 2;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = leFlags;
|
|
le->radius = radius;
|
|
|
|
re = &le->refEntity;
|
|
re->rotation = Q_random( &seed ) * 360;
|
|
re->radius = radius;
|
|
re->shaderTime = startTime / 1000.0f;
|
|
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
|
le->startTime = startTime;
|
|
le->fadeInTime = fadeInTime;
|
|
le->endTime = startTime + duration;
|
|
if ( fadeInTime > startTime ) {
|
|
le->lifeRate = 1.0 / ( le->endTime - le->fadeInTime );
|
|
}
|
|
else {
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
}
|
|
le->color[0] = r;
|
|
le->color[1] = g;
|
|
le->color[2] = b;
|
|
le->color[3] = a;
|
|
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = startTime;
|
|
VectorCopy( vel, le->pos.trDelta );
|
|
VectorCopy( p, le->pos.trBase );
|
|
|
|
VectorCopy( p, re->origin );
|
|
re->customShader = hShader;
|
|
|
|
// rage pro can't alpha fade, so use a different shader
|
|
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
|
|
re->customShader = cgs.media.smokePuffRageProShader;
|
|
re->shaderRGBA[0] = 0xff;
|
|
re->shaderRGBA[1] = 0xff;
|
|
re->shaderRGBA[2] = 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
} else {
|
|
re->shaderRGBA[0] = le->color[0] * 0xff;
|
|
re->shaderRGBA[1] = le->color[1] * 0xff;
|
|
re->shaderRGBA[2] = le->color[2] * 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
}
|
|
|
|
re->reType = RT_SPRITE;
|
|
re->radius = le->radius;
|
|
|
|
return le;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_SpawnEffect
|
|
|
|
Player teleporting in or out
|
|
==================
|
|
*/
|
|
void CG_SpawnEffect( vec3_t org ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->leType = LE_FADE_RGB;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 500;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
|
|
|
|
re = &le->refEntity;
|
|
|
|
re->reType = RT_MODEL;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
#ifndef MISSIONPACK
|
|
re->customShader = cgs.media.teleportEffectShader;
|
|
#endif
|
|
re->hModel = cgs.media.teleportEffectModel;
|
|
AxisClear( re->axis );
|
|
|
|
VectorCopy( org, re->origin );
|
|
#ifdef MISSIONPACK
|
|
re->origin[2] += 16;
|
|
#else
|
|
re->origin[2] -= 24;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_PersentrySpawnEffect
|
|
|
|
PKMOD - Ergodic 06/08/02 - add personal sentry teleport model
|
|
==================
|
|
*/
|
|
void CG_PersentrySpawnEffect( vec3_t org ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->leType = LE_FADE_RGB;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 500;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
|
|
|
|
re = &le->refEntity;
|
|
|
|
re->reType = RT_MODEL;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->hModel = cgs.media.persentry_teleportEffectModel;
|
|
AxisClear( re->axis );
|
|
|
|
VectorCopy( org, re->origin );
|
|
re->origin[2] -= 24;
|
|
}
|
|
|
|
|
|
#ifdef MISSIONPACK
|
|
/*
|
|
===============
|
|
CG_LightningBoltBeam
|
|
===============
|
|
*/
|
|
void CG_LightningBoltBeam( vec3_t start, vec3_t end ) {
|
|
localEntity_t *le;
|
|
refEntity_t *beam;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->leType = LE_SHOWREFENTITY;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 50;
|
|
|
|
beam = &le->refEntity;
|
|
|
|
VectorCopy( start, beam->origin );
|
|
// this is the end point
|
|
VectorCopy( end, beam->oldorigin );
|
|
|
|
beam->reType = RT_LIGHTNING;
|
|
beam->customShader = cgs.media.lightningShader;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_KamikazeEffect
|
|
==================
|
|
*/
|
|
void CG_KamikazeEffect( vec3_t org ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->leType = LE_KAMIKAZE;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 3000;//2250;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
|
|
|
|
VectorClear(le->angles.trBase);
|
|
|
|
re = &le->refEntity;
|
|
|
|
re->reType = RT_MODEL;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->hModel = cgs.media.kamikazeEffectModel;
|
|
|
|
VectorCopy( org, re->origin );
|
|
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_ObeliskExplode
|
|
==================
|
|
*/
|
|
void CG_ObeliskExplode( vec3_t org, int entityNum ) {
|
|
localEntity_t *le;
|
|
vec3_t origin;
|
|
|
|
// create an explosion
|
|
VectorCopy( org, origin );
|
|
origin[2] += 64;
|
|
le = CG_MakeExplosion( origin, vec3_origin,
|
|
cgs.media.dishFlashModel,
|
|
cgs.media.rocketExplosionShader,
|
|
600, qtrue );
|
|
le->light = 300;
|
|
le->lightColor[0] = 1;
|
|
le->lightColor[1] = 0.75;
|
|
le->lightColor[2] = 0.0;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_ObeliskPain
|
|
==================
|
|
*/
|
|
void CG_ObeliskPain( vec3_t org ) {
|
|
float r;
|
|
sfxHandle_t sfx;
|
|
|
|
// hit sound
|
|
r = rand() & 3;
|
|
if ( r < 2 ) {
|
|
sfx = cgs.media.obeliskHitSound1;
|
|
} else if ( r == 2 ) {
|
|
sfx = cgs.media.obeliskHitSound2;
|
|
} else {
|
|
sfx = cgs.media.obeliskHitSound3;
|
|
}
|
|
trap_S_StartSound ( org, ENTITYNUM_NONE, CHAN_BODY, sfx );
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
CG_InvulnerabilityImpact
|
|
==================
|
|
*/
|
|
void CG_InvulnerabilityImpact( vec3_t org, vec3_t angles ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
int r;
|
|
sfxHandle_t sfx;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->leType = LE_INVULIMPACT;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 1000;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
|
|
|
|
re = &le->refEntity;
|
|
|
|
re->reType = RT_MODEL;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->hModel = cgs.media.invulnerabilityImpactModel;
|
|
|
|
VectorCopy( org, re->origin );
|
|
AnglesToAxis( angles, re->axis );
|
|
|
|
r = rand() & 3;
|
|
if ( r < 2 ) {
|
|
sfx = cgs.media.invulnerabilityImpactSound1;
|
|
} else if ( r == 2 ) {
|
|
sfx = cgs.media.invulnerabilityImpactSound2;
|
|
} else {
|
|
sfx = cgs.media.invulnerabilityImpactSound3;
|
|
}
|
|
trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, sfx );
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_InvulnerabilityJuiced
|
|
==================
|
|
*/
|
|
void CG_InvulnerabilityJuiced( vec3_t org ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
vec3_t angles;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->leType = LE_INVULJUICED;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 10000;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
|
|
|
|
re = &le->refEntity;
|
|
|
|
re->reType = RT_MODEL;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->hModel = cgs.media.invulnerabilityJuicedModel;
|
|
|
|
VectorCopy( org, re->origin );
|
|
VectorClear(angles);
|
|
AnglesToAxis( angles, re->axis );
|
|
|
|
trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, cgs.media.invulnerabilityJuicedSound );
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
==================
|
|
CG_ScorePlum
|
|
==================
|
|
*/
|
|
void CG_ScorePlum( int client, vec3_t org, int score ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
vec3_t angles;
|
|
static vec3_t lastPos;
|
|
|
|
// only visualize for the client that scored
|
|
if (client != cg.predictedPlayerState.clientNum || cg_scorePlum.integer == 0) {
|
|
return;
|
|
}
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->leType = LE_SCOREPLUM;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 4000;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
|
|
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
|
|
le->radius = score;
|
|
|
|
VectorCopy( org, le->pos.trBase );
|
|
if (org[2] >= lastPos[2] - 20 && org[2] <= lastPos[2] + 20) {
|
|
le->pos.trBase[2] -= 20;
|
|
}
|
|
|
|
//CG_Printf( "Plum origin %i %i %i -- %i\n", (int)org[0], (int)org[1], (int)org[2], (int)Distance(org, lastPos));
|
|
VectorCopy(org, lastPos);
|
|
|
|
|
|
re = &le->refEntity;
|
|
|
|
re->reType = RT_SPRITE;
|
|
re->radius = 16;
|
|
|
|
VectorClear(angles);
|
|
AnglesToAxis( angles, re->axis );
|
|
}
|
|
|
|
|
|
/*
|
|
====================
|
|
CG_MakeExplosion
|
|
====================
|
|
*/
|
|
localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir,
|
|
qhandle_t hModel, qhandle_t shader,
|
|
int msec, qboolean isSprite ) {
|
|
float ang;
|
|
localEntity_t *ex;
|
|
int offset;
|
|
vec3_t tmpVec, newOrigin;
|
|
|
|
if ( msec <= 0 ) {
|
|
CG_Error( "CG_MakeExplosion: msec = %i", msec );
|
|
}
|
|
|
|
// skew the time a bit so they aren't all in sync
|
|
offset = rand() & 63;
|
|
|
|
ex = CG_AllocLocalEntity();
|
|
if ( isSprite ) {
|
|
ex->leType = LE_SPRITE_EXPLOSION;
|
|
|
|
// randomly rotate sprite orientation
|
|
ex->refEntity.rotation = rand() % 360;
|
|
VectorScale( dir, 16, tmpVec );
|
|
VectorAdd( tmpVec, origin, newOrigin );
|
|
} else {
|
|
ex->leType = LE_EXPLOSION;
|
|
VectorCopy( origin, newOrigin );
|
|
|
|
// set axis with random rotate
|
|
if ( !dir ) {
|
|
AxisClear( ex->refEntity.axis );
|
|
} else {
|
|
ang = rand() % 360;
|
|
VectorCopy( dir, ex->refEntity.axis[0] );
|
|
RotateAroundDirection( ex->refEntity.axis, ang );
|
|
}
|
|
}
|
|
|
|
ex->startTime = cg.time - offset;
|
|
ex->endTime = ex->startTime + msec;
|
|
|
|
// bias the time so all shader effects start correctly
|
|
ex->refEntity.shaderTime = ex->startTime / 1000.0f;
|
|
|
|
ex->refEntity.hModel = hModel;
|
|
ex->refEntity.customShader = shader;
|
|
|
|
// set origin
|
|
VectorCopy( newOrigin, ex->refEntity.origin );
|
|
VectorCopy( newOrigin, ex->refEntity.oldorigin );
|
|
|
|
ex->color[0] = ex->color[1] = ex->color[2] = 1.0;
|
|
|
|
return ex;
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
CG_Bleed
|
|
|
|
This is the spurt of blood when a character gets hit
|
|
=================
|
|
*/
|
|
void CG_Bleed( vec3_t origin, int entityNum ) {
|
|
localEntity_t *ex;
|
|
|
|
if ( !cg_blood.integer ) {
|
|
return;
|
|
}
|
|
|
|
ex = CG_AllocLocalEntity();
|
|
ex->leType = LE_EXPLOSION;
|
|
|
|
ex->startTime = cg.time;
|
|
ex->endTime = ex->startTime + 500;
|
|
|
|
VectorCopy ( origin, ex->refEntity.origin);
|
|
ex->refEntity.reType = RT_SPRITE;
|
|
ex->refEntity.rotation = rand() % 360;
|
|
ex->refEntity.radius = 24;
|
|
|
|
ex->refEntity.customShader = cgs.media.bloodExplosionShader;
|
|
|
|
// don't show player's own blood in view
|
|
if ( entityNum == cg.snap->ps.clientNum ) {
|
|
ex->refEntity.renderfx |= RF_THIRD_PERSON;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
==================
|
|
CG_LaunchGib
|
|
==================
|
|
*/
|
|
void CG_LaunchGib( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
re = &le->refEntity;
|
|
|
|
le->leType = LE_FRAGMENT;
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + 5000 + random() * 3000;
|
|
|
|
VectorCopy( origin, re->origin );
|
|
AxisCopy( axisDefault, re->axis );
|
|
re->hModel = hModel;
|
|
|
|
le->pos.trType = TR_GRAVITY;
|
|
VectorCopy( origin, le->pos.trBase );
|
|
VectorCopy( velocity, le->pos.trDelta );
|
|
le->pos.trTime = cg.time;
|
|
|
|
le->bounceFactor = 0.6f;
|
|
|
|
le->leBounceSoundType = LEBS_BLOOD;
|
|
le->leMarkType = LEMT_BLOOD;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
//PKMOD - Ergodic 12/14/00 - make gib less intensive
|
|
CG_LaunchGibAlternate
|
|
==================
|
|
*/
|
|
void CG_LaunchGibAlternate( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
re = &le->refEntity;
|
|
|
|
le->leType = LE_FRAGMENT;
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + 3000 + random() * 2500;
|
|
|
|
VectorCopy( origin, re->origin );
|
|
AxisCopy( axisDefault, re->axis );
|
|
re->hModel = hModel;
|
|
|
|
le->pos.trType = TR_GRAVITY;
|
|
VectorCopy( origin, le->pos.trBase );
|
|
VectorCopy( velocity, le->pos.trDelta );
|
|
le->pos.trTime = cg.time;
|
|
|
|
//PKMOD - Ergodic 12/16/00 - use "f" to force float
|
|
le->bounceFactor = 0.3f;
|
|
|
|
if ( random() > 0.4 ) {
|
|
le->leBounceSoundType = LEBS_BRASS;
|
|
le->leMarkType = LEMT_NONE;
|
|
}
|
|
else {
|
|
le->leBounceSoundType = LEBS_BLOOD;
|
|
le->leMarkType = LEMT_BLOOD;
|
|
}
|
|
}
|
|
|
|
/*
|
|
===================
|
|
CG_GibPlayer
|
|
|
|
Generated a bunch of gibs launching out from the bodies location
|
|
===================
|
|
*/
|
|
#define GIB_VELOCITY 250
|
|
#define GIB_JUMP 250
|
|
void CG_GibPlayer( vec3_t playerOrigin ) {
|
|
vec3_t origin, velocity;
|
|
|
|
if ( !cg_blood.integer ) {
|
|
return;
|
|
}
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
if ( rand() & 1 ) {
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibSkull );
|
|
} else {
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibBrain );
|
|
}
|
|
|
|
// allow gibs to be turned off for speed
|
|
if ( !cg_gibs.integer ) {
|
|
return;
|
|
}
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibAbdomen );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibArm );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibChest );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibFist );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibFoot );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibForearm );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibIntestine );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_LaunchGib
|
|
==================
|
|
*/
|
|
void CG_LaunchExplode( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
re = &le->refEntity;
|
|
|
|
le->leType = LE_FRAGMENT;
|
|
le->startTime = cg.time;
|
|
le->endTime = le->startTime + 10000 + random() * 6000;
|
|
|
|
VectorCopy( origin, re->origin );
|
|
AxisCopy( axisDefault, re->axis );
|
|
re->hModel = hModel;
|
|
|
|
le->pos.trType = TR_GRAVITY;
|
|
VectorCopy( origin, le->pos.trBase );
|
|
VectorCopy( velocity, le->pos.trDelta );
|
|
le->pos.trTime = cg.time;
|
|
|
|
le->bounceFactor = 0.1f;
|
|
|
|
le->leBounceSoundType = LEBS_BRASS;
|
|
le->leMarkType = LEMT_NONE;
|
|
}
|
|
|
|
#define EXP_VELOCITY 100
|
|
#define EXP_JUMP 150
|
|
/*
|
|
===================
|
|
CG_GibPlayer
|
|
|
|
Generated a bunch of gibs launching out from the bodies location
|
|
===================
|
|
*/
|
|
void CG_BigExplode( vec3_t playerOrigin ) {
|
|
vec3_t origin, velocity;
|
|
|
|
if ( !cg_blood.integer ) {
|
|
return;
|
|
}
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*EXP_VELOCITY;
|
|
velocity[1] = crandom()*EXP_VELOCITY;
|
|
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
|
|
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*EXP_VELOCITY;
|
|
velocity[1] = crandom()*EXP_VELOCITY;
|
|
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
|
|
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*EXP_VELOCITY*1.5;
|
|
velocity[1] = crandom()*EXP_VELOCITY*1.5;
|
|
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
|
|
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*EXP_VELOCITY*2.0;
|
|
velocity[1] = crandom()*EXP_VELOCITY*2.0;
|
|
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
|
|
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
|
|
|
|
VectorCopy( playerOrigin, origin );
|
|
velocity[0] = crandom()*EXP_VELOCITY*2.5;
|
|
velocity[1] = crandom()*EXP_VELOCITY*2.5;
|
|
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
|
|
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
|
|
}
|
|
|
|
//PKMOD - Ergodic 12/14/00 - add autosentry gib models
|
|
#define AUTOSENTRY_SHOWGIB 0.7 //show gib 70% of the time
|
|
//PKMOD - Ergodic 11/22/00 - autosentry death routine
|
|
//PKMOD - Ergodic 12/14/00 - add autosentry gib models
|
|
void CG_AutoSentryDie( vec3_t AutoSentryOrigin ) {
|
|
vec3_t origin, velocity;
|
|
|
|
//PKMOD Ergodic debug 12/14/00 inactive
|
|
// Com_Printf("CG_AutoSentryDie\n" );
|
|
|
|
|
|
VectorCopy( AutoSentryOrigin, origin );
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib1 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib2 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib3 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib4 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib5 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib6 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib7 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib8 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib9 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib10 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib11 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib12 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.pkasentry_gib13 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib14 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib15 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib16 );
|
|
}
|
|
|
|
if ( random() < AUTOSENTRY_SHOWGIB ) {
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGibAlternate( origin, velocity, cgs.media.pkasentry_gib17 );
|
|
}
|
|
|
|
}
|
|
|
|
//PMKOD - Ergodic - 05/26/00 - Beartrap death
|
|
/*
|
|
==================
|
|
CG_BearTrapDie
|
|
==================
|
|
*/
|
|
void CG_BearTrapDie( vec3_t BearTrapOrigin ) {
|
|
vec3_t origin, velocity;
|
|
int number_of_gibs;
|
|
|
|
VectorCopy( BearTrapOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.pkabeartrapgib1 );
|
|
|
|
VectorCopy( BearTrapOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.pkabeartrapgib2 );
|
|
|
|
VectorCopy( BearTrapOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.pkabeartrapgib3 );
|
|
|
|
number_of_gibs = random() * 5;
|
|
|
|
while (number_of_gibs > 0) {
|
|
VectorCopy( BearTrapOrigin, origin );
|
|
velocity[0] = crandom()*GIB_VELOCITY;
|
|
velocity[1] = crandom()*GIB_VELOCITY;
|
|
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
|
|
CG_LaunchGib( origin, velocity, cgs.media.pkabeartrapgib4 );
|
|
number_of_gibs--;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//PKMOD - Ergodic debug position
|
|
char *CG_vtos_2( const vec3_t v ) {
|
|
static int index;
|
|
static char str[8][32];
|
|
char *s;
|
|
|
|
// use an array so that multiple vtos won't collide
|
|
s = str[index];
|
|
index = (index + 1)&7;
|
|
|
|
Com_sprintf (s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]);
|
|
|
|
return s;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_Lightning_FX
|
|
|
|
Create a light flash effect
|
|
Note: effect must be turned off
|
|
==================
|
|
*/
|
|
//PKMOD - Ergodic 09/30/01 - event parm will send intensity
|
|
//PKMOD - Ergodic 10/01/01 - add mulitple points
|
|
#define MAX_LIGHTNING_POINTS 25
|
|
#define MEAN_LIGHTNING_DISTANCE 20
|
|
|
|
void CG_Lightning_FX( vec3_t position, int intensity ) {
|
|
int i, r, g, b;
|
|
int indx;
|
|
vec3_t hold_position;
|
|
|
|
//PKMOD Ergodic debug 07/19/00 (inactive)
|
|
//Com_Printf("CG_Lightning_FX - position>%s<, intensity>%d<\n", CG_vtos_2(position), intensity );
|
|
|
|
|
|
r = 255;
|
|
g = 255;
|
|
b = 255;
|
|
i = intensity;
|
|
for (indx = 1; indx < MAX_LIGHTNING_POINTS; indx++ ) {
|
|
hold_position[0] = position[0] + crandom() * MEAN_LIGHTNING_DISTANCE;
|
|
hold_position[1] = position[1] + crandom() * MEAN_LIGHTNING_DISTANCE;
|
|
hold_position[2] = position[2] + crandom() * MEAN_LIGHTNING_DISTANCE;
|
|
trap_R_AddLightToScene( hold_position, i, r, g, b );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
CG_Lightning_Water_Discharge
|
|
|
|
//PKMOD - Ergodic 01/15/01 - add Lightning Discharge in water
|
|
==================
|
|
*/
|
|
void CG_Lightning_Water_Discharge (vec3_t origin, int msec) {
|
|
|
|
localEntity_t *le;
|
|
|
|
if (msec <= 0)
|
|
msec = 300;
|
|
|
|
le = CG_SmokePuff ( origin, // where
|
|
vec3_origin, // where to
|
|
((48 + (msec * 10)) / 16), // radius
|
|
1, 1, 1, 1, // RGBA color shift
|
|
300 + msec, // duration
|
|
cg.time, // start when?
|
|
0, //fade in time
|
|
0, // flags (?)
|
|
trap_R_RegisterShader ("models/weaphits/electric.tga"));
|
|
|
|
le->leType = LE_SCALE_FADE;
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
CG_TootBubbles
|
|
//PKMOD - Ergodic 04/13/01 - Toots underwater
|
|
==================
|
|
*/
|
|
#define TootBubbleCount 10
|
|
//PKMOD - Ergodic 04/14/01 - Soft code
|
|
#define TootDisplacementMax 6 // displacement from center
|
|
#define TootDisplacementOffset 13 // 1 + 2 * TootDisplacementMax
|
|
#define Toot_H_VelocityMax 7 // horizontal velocity of bubbles
|
|
#define Toot_H_VelocityOffset 15 // 1 + 2 * Toot_H_VelocityMax
|
|
#define Toot_V_VelocityMax 20 // Vertical velocity of bubbles
|
|
|
|
|
|
void CG_TootBubbles( vec3_t start ) {
|
|
vec3_t hold_vec;
|
|
int i;
|
|
int bubbles;
|
|
|
|
bubbles = 10 + rand() % TootBubbleCount; //{10, 19}
|
|
VectorCopy ( start, hold_vec );
|
|
|
|
for ( i = 1; i < bubbles; i++ ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
VectorCopy ( start, hold_vec ); //random location neary the hiney
|
|
hold_vec[0] += TootDisplacementMax - rand() % TootDisplacementOffset; //{-6, 6}
|
|
hold_vec[1] += TootDisplacementMax - rand() % TootDisplacementOffset; //{-6, 6}
|
|
hold_vec[2] += TootDisplacementMax - rand() % TootDisplacementOffset; //{-6, 6}
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = LEF_PUFF_DONT_SCALE;
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + 1000 + random() * 250;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
re = &le->refEntity;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->reType = RT_SPRITE;
|
|
re->rotation = 0;
|
|
re->radius = 3;
|
|
re->customShader = cgs.media.waterBubbleShader;
|
|
re->shaderRGBA[0] = 0xff;
|
|
re->shaderRGBA[1] = 0xff;
|
|
re->shaderRGBA[2] = 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
|
|
le->color[3] = 1.0;
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
VectorCopy( hold_vec, le->pos.trBase );
|
|
|
|
le->pos.trDelta[0] = Toot_H_VelocityMax - rand() % Toot_H_VelocityOffset; //{-7, 7}
|
|
le->pos.trDelta[1] = Toot_H_VelocityMax - rand() % Toot_H_VelocityOffset; //{-7, 7}
|
|
le->pos.trDelta[2] = Toot_V_VelocityMax + rand() % Toot_V_VelocityMax; //{20, 39}
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
======================
|
|
CG_BeansToot
|
|
|
|
//PKMOD - Ergodic 04/13/01 - Renders fecal plumes or bubbles from eating beans
|
|
======================
|
|
*/
|
|
void CG_BeansToot( vec3_t origin ) {
|
|
int sourceContentType;
|
|
vec3_t hiney_location;
|
|
localEntity_t *smoke;
|
|
vec3_t up = {0, 0, 5};
|
|
|
|
VectorCopy( origin, hiney_location);
|
|
hiney_location[2] +=16; //waist displacement height
|
|
|
|
|
|
sourceContentType = trap_CM_PointContents( hiney_location, 0 );
|
|
|
|
if ( sourceContentType & CONTENTS_WATER ) {
|
|
CG_TootBubbles( hiney_location );
|
|
}
|
|
else {
|
|
//PKMOD - Ergodic 12/27/00 add beans shader
|
|
smoke = CG_SmokePuff( hiney_location, up,
|
|
32,
|
|
1, 1, 1, 0.33f,
|
|
1500,
|
|
cg.time, 0,
|
|
LEF_PUFF_DONT_SCALE,
|
|
cgs.media.pkafartPuffShader );
|
|
}
|
|
|
|
}
|
|
|
|
//PKMOD - Ergodic 01/05/04 - add quad farting logic for differing CG graphic sequence
|
|
/*
|
|
======================
|
|
CG_BeansToot
|
|
|
|
PKMOD - Ergodic 01/05/04 - add quad farting logic for differing CG graphic sequence
|
|
- Renders fecal plumes or bubbles from eating beans
|
|
Ergodic 01/12/04 - add in scaling function local entity
|
|
======================
|
|
*/
|
|
void CG_QuadBeansToot( vec3_t origin ) {
|
|
int sourceContentType;
|
|
vec3_t hiney_location;
|
|
localEntity_t *smoke;
|
|
// vec3_t up = {0, 0, 5};
|
|
|
|
|
|
//PKMOD - Ergodic 01/12/04 - debug quad fart activation (inactive)
|
|
//Com_Printf( "inside cg_quadbeanstoot\n" );
|
|
|
|
VectorCopy( origin, hiney_location);
|
|
hiney_location[2] +=16; //waist displacement height
|
|
|
|
|
|
sourceContentType = trap_CM_PointContents( hiney_location, 0 );
|
|
|
|
if ( sourceContentType & CONTENTS_WATER ) {
|
|
CG_TootBubbles( hiney_location );
|
|
}
|
|
|
|
smoke = CG_AllocLocalEntity();
|
|
|
|
smoke->leType = LE_SCALED_SPRITE_EXPLOSION;
|
|
|
|
smoke->startTime = cg.time;
|
|
smoke->endTime = smoke->startTime + 1100; //Keep in sync with cg_localents
|
|
|
|
// bias the time so all shader effects start correctly
|
|
smoke->refEntity.shaderTime = smoke->startTime / 1000.0f;
|
|
|
|
smoke->refEntity.hModel = cgs.media.pkaquadbeansModel;
|
|
smoke->refEntity.customShader = cgs.media.pkaquadbeansShader;
|
|
|
|
// set origin
|
|
VectorCopy( hiney_location, smoke->refEntity.origin );
|
|
VectorCopy( hiney_location, smoke->refEntity.oldorigin );
|
|
|
|
smoke->light = 300;
|
|
smoke->lightColor[0] = 1;
|
|
smoke->lightColor[1] = 0.75;
|
|
smoke->lightColor[2] = 0.0;
|
|
|
|
}
|
|
|
|
/*
|
|
==================
|
|
CG_Radiation
|
|
|
|
//PKMOD - Ergodic 10/14/01 - add radiation sparking effect
|
|
==================
|
|
*/
|
|
|
|
#define CG_RADIATION_COUNT 20
|
|
#define CG_RADIATION_MIN_RADIUS 10
|
|
#define CG_RADIATION_DELTA_RADIUS 25 //delta radius = max radius - min radius
|
|
#define CG_RADIATION_MIN_TIME 300
|
|
#define CG_RADIATION_DELTA_TIME 500 //delta time = max time - min time
|
|
void CG_Radiation( vec3_t start ) {
|
|
vec3_t move;
|
|
int i;
|
|
|
|
for ( i = 1; i < CG_RADIATION_COUNT; i++ ) {
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = LEF_PUFF_DONT_SCALE;
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
|
le->startTime = cg.time;
|
|
le->endTime = cg.time + CG_RADIATION_MIN_TIME + random() * CG_RADIATION_DELTA_TIME;
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
|
|
re = &le->refEntity;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->reType = RT_SPRITE;
|
|
re->rotation = 0;
|
|
re->radius = 2;
|
|
switch ( rand() % 6 ) { //random numbers: { 0, 1, 2, 3, 4, 5 }
|
|
case 0:
|
|
re->customShader = cgs.media.radiate1Shader;
|
|
break;
|
|
case 1:
|
|
re->customShader = cgs.media.radiate2Shader;
|
|
break;
|
|
case 2:
|
|
re->customShader = cgs.media.radiate3Shader;
|
|
break;
|
|
case 3:
|
|
re->customShader = cgs.media.radiate4Shader;
|
|
break;
|
|
case 4:
|
|
re->customShader = cgs.media.radiate5Shader;
|
|
break;
|
|
default:
|
|
re->customShader = cgs.media.radiate6Shader;
|
|
break;
|
|
}
|
|
re->shaderRGBA[0] = 0xff;
|
|
re->shaderRGBA[1] = 0xff;
|
|
re->shaderRGBA[2] = 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
|
|
le->color[3] = 1.0;
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = cg.time;
|
|
move[0] = start[0] + crandom() * ( CG_RADIATION_MIN_RADIUS + random() * CG_RADIATION_DELTA_RADIUS );
|
|
move[1] = start[1] + crandom() * ( CG_RADIATION_MIN_RADIUS + random() * CG_RADIATION_DELTA_RADIUS );
|
|
move[2] = start[2] + crandom() * ( CG_RADIATION_MIN_RADIUS + random() * CG_RADIATION_DELTA_RADIUS );
|
|
|
|
VectorCopy( move, le->pos.trBase );
|
|
le->pos.trDelta[0] = crandom()*10;
|
|
le->pos.trDelta[1] = crandom()*10;
|
|
le->pos.trDelta[2] = crandom()*10;
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
CG_RadiationTrail
|
|
|
|
PKMOD - Ergodic 11/30/01 - add radiation trail to infected player
|
|
=====================
|
|
*/
|
|
void CG_RadiationTrail0( const vec3_t p ) {
|
|
|
|
vec3_t vel;
|
|
static int seed = 0x92;
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = 0;
|
|
le->radius = 3;
|
|
|
|
re = &le->refEntity;
|
|
re->rotation = Q_random( &seed ) * 360;
|
|
re->radius = 3;
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
le->leType = LE_FALL_SCALE_FADE;
|
|
le->startTime = cg.time;
|
|
le->fadeInTime = 0;
|
|
le->endTime = cg.time + 1000 + (rand() % 1001);
|
|
if ( le->fadeInTime > le->startTime ) {
|
|
le->lifeRate = 1.0 / ( le->endTime - le->fadeInTime );
|
|
}
|
|
else {
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
}
|
|
le->color[0] = 1;
|
|
le->color[1] = 1;
|
|
le->color[2] = 1;
|
|
le->color[3] = 1;
|
|
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = le->startTime;
|
|
vel[0] = 25 - 2 * ( rand() % 25 );
|
|
vel[1] = 25 - 2 * ( rand() % 25 );
|
|
vel[2] = 25 - 2 * ( rand() % 25 );
|
|
VectorCopy( vel, le->pos.trDelta );
|
|
VectorCopy( p, le->pos.trBase );
|
|
|
|
VectorCopy( p, re->origin );
|
|
re->customShader = cgs.media.radiationTrailShader;
|
|
|
|
// rage pro can't alpha fade, so use a different shader
|
|
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
|
|
re->customShader = cgs.media.smokePuffRageProShader;
|
|
re->shaderRGBA[0] = 0xff;
|
|
re->shaderRGBA[1] = 0xff;
|
|
re->shaderRGBA[2] = 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
} else {
|
|
re->shaderRGBA[0] = le->color[0] * 0xff;
|
|
re->shaderRGBA[1] = le->color[1] * 0xff;
|
|
re->shaderRGBA[2] = le->color[2] * 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
}
|
|
|
|
re->reType = RT_SPRITE;
|
|
re->radius = le->radius;
|
|
|
|
// drop a total of 2 units over its lifetime
|
|
le->pos.trDelta[2] = 2;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
CG_RadiationTrail
|
|
|
|
PKMOD - Ergodic 11/30/01 - add radiation trail to infected player
|
|
=====================
|
|
*/
|
|
void CG_RadiationTrail( const vec3_t p, vec3_t vel,
|
|
float radius,
|
|
float r, float g, float b, float a,
|
|
float duration,
|
|
int startTime,
|
|
int fadeInTime,
|
|
int leFlags,
|
|
qhandle_t hShader ) {
|
|
// static int seed = 0x92;
|
|
localEntity_t *le;
|
|
refEntity_t *re;
|
|
// int fadeInTime = startTime + duration / 2;
|
|
|
|
le = CG_AllocLocalEntity();
|
|
le->leFlags = leFlags;
|
|
le->radius = radius;
|
|
|
|
re = &le->refEntity;
|
|
// re->rotation = Q_random( &seed ) * 360;
|
|
re->rotation = rand() % 360; //PKMOD - Ergodic 11/30/01
|
|
re->radius = radius;
|
|
re->shaderTime = startTime / 1000.0f;
|
|
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
|
le->startTime = startTime;
|
|
le->fadeInTime = fadeInTime;
|
|
le->endTime = startTime + duration;
|
|
if ( fadeInTime > startTime ) {
|
|
le->lifeRate = 1.0 / ( le->endTime - le->fadeInTime );
|
|
}
|
|
else {
|
|
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
|
}
|
|
le->color[0] = r;
|
|
le->color[1] = g;
|
|
le->color[2] = b;
|
|
le->color[3] = a;
|
|
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
le->pos.trTime = startTime;
|
|
VectorCopy( vel, le->pos.trDelta );
|
|
VectorCopy( p, le->pos.trBase );
|
|
|
|
VectorCopy( p, re->origin );
|
|
re->customShader = hShader;
|
|
|
|
// rage pro can't alpha fade, so use a different shader
|
|
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
|
|
re->customShader = cgs.media.smokePuffRageProShader;
|
|
re->shaderRGBA[0] = 0xff;
|
|
re->shaderRGBA[1] = 0xff;
|
|
re->shaderRGBA[2] = 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
} else {
|
|
re->shaderRGBA[0] = le->color[0] * 0xff;
|
|
re->shaderRGBA[1] = le->color[1] * 0xff;
|
|
re->shaderRGBA[2] = le->color[2] * 0xff;
|
|
re->shaderRGBA[3] = 0xff;
|
|
}
|
|
|
|
re->reType = RT_SPRITE;
|
|
re->radius = le->radius;
|
|
|
|
// drop a total of 5 units over its lifetime
|
|
le->pos.trDelta[2] = 20;
|
|
|
|
}
|
|
|