rpgxef/code/cgame/fx_compression.c
Walter Julius Hennecke a39565b783 Integrated RPG-X2 rpgxEF edition into the rpgxEF repo
... not quite content with where the project files lie but it is ok for
now.
... compiling works fine so far (only tested mingw32 right now)
2012-08-04 12:54:37 +02:00

434 lines
11 KiB
C

//Compression rifle weapon effects
#include "cg_local.h"
#include "fx_local.h"
qboolean AltCompressionAftereffect(localEntity_t *le)
{
localEntity_t *cyl = NULL;
qhandle_t shader = cgs.media.compressionAltBlastShader;
float percentLife = 1.0 - (le->endTime - cg.time)*le->lifeRate;
float alpha = 0.6 - (0.6*percentLife);
float length = 20;
vec3_t vec2, dir2;
cyl = FX_AddCylinder( le->refEntity.origin,
le->data.spawner.dir,
length,// height,
0,// dheight,
10,//10+(30*(1-percentLife)),// scale,
210,// dscale,
10+(30*percentLife),// scale2,
210,// dscale2,
alpha,// startalpha,
0.0,// endalpha,
500,// killTime,
shader,
15);// bias );
cyl->leFlags |= LEF_ONE_FRAME;
VectorMA(le->refEntity.origin, length*2.0, le->data.spawner.dir, vec2);
VectorScale(le->data.spawner.dir, -1.0, dir2);
cyl = FX_AddCylinder( vec2,
dir2,
length,// height,
0,// dheight,
10,//10+(30*(1-percentLife)),// scale,
210,// dscale,
10+(30*percentLife),// scale2,
210,// dscale2,
alpha,// startalpha,
0.0,// endalpha,
500,// killTime,
shader,
15);// bias );
cyl->leFlags |= LEF_ONE_FRAME;
return qtrue;
}
/*
-------------------------
FX_CompressionShot
-------------------------
*/
#define MAXRANGE_CRIFLE 8192
void FX_CompressionShot( vec3_t start, vec3_t dir )
{
localEntity_t *le;
vec3_t end;
trace_t trace;
qboolean render_impact = qtrue;
centity_t *traceEnt = NULL;
int clientNum = -1;
VectorMA(start, MAXRANGE_CRIFLE, dir, end);
CG_Trace( &trace, start, NULL, NULL, end, 0, MASK_SHOT );
// draw the beam
le = FX_AddLine(start, trace.endpos, 1.0, 2.0, 0.0, 1.0, 1.0, 100.0, cgs.media.prifleBolt);
le->leFlags |= LEF_ONE_FRAME;
// draw an impact at the endpoint of the trace
// If the beam hits a skybox, etc. it would look foolish to add in an explosion
if ( trace.surfaceFlags & SURF_NOIMPACT )
{
render_impact = qfalse;
}
if ( render_impact )
{
traceEnt = &cg_entities[trace.entityNum];
clientNum = traceEnt->currentState.clientNum;
if ( (trace.entityNum != ENTITYNUM_WORLD) && (clientNum >= 0 || clientNum < MAX_CLIENTS) )
{
FX_CompressionHit(trace.endpos);
}
else
{
FX_CompressionExplosion(start, trace.endpos, trace.plane.normal, qfalse);
}
}
}
/*
-------------------------
FX_CompressionShot
-------------------------
*/
void FX_CompressionAltShot( vec3_t start, vec3_t dir )
{
vec3_t end, vel = {0,0,0};
trace_t trace;
qboolean render_impact = qtrue;
centity_t *traceEnt = NULL;
int clientNum = -1;
VectorMA(start, MAXRANGE_CRIFLE, dir, end);
CG_Trace( &trace, start, NULL, NULL, end, cg_entities[cg.predictedPlayerState.clientNum].currentState.number, MASK_SHOT );
// draw the beam
FX_AddLine( start, trace.endpos, 1.0f, 3.0f, 0.0f, 1.0f, 0.0f, 350/*125.0f*/, cgs.media.sparkShader );
FX_AddLine( start, trace.endpos, 1.0f, 6.0f, 20.0f, 0.6f, 0.0f, 800/*175.0f*/, cgs.media.phaserShader);//compressionAltBeamShader );
FX_AddSpawner( start, dir, vel, NULL, qfalse, 0,
0, 500, AltCompressionAftereffect, 10 );
// draw an impact at the endpoint of the trace
// If the beam hits a skybox, etc. it would look foolish to add in an explosion
if ( trace.surfaceFlags & SURF_NOIMPACT )
{
render_impact = qfalse;
}
if ( render_impact )
{
traceEnt = &cg_entities[trace.entityNum];
clientNum = traceEnt->currentState.clientNum;
if ( (trace.entityNum != ENTITYNUM_WORLD) && (clientNum >= 0 || clientNum < MAX_CLIENTS) )
{
FX_CompressionHit(trace.endpos);
}
else
{
FX_CompressionExplosion(start, trace.endpos, trace.plane.normal, qtrue);
}
}
}
/*
-------------------------
FX_CompressionExplosion
-------------------------
*/
void FX_CompressionExplosion( vec3_t start, vec3_t origin, vec3_t normal, qboolean altfire )
{
localEntity_t *le;
vec3_t dir;
vec3_t velocity; //, shot_dir;
vec3_t hitpos;
float scale, dscale;
int i, j, numSparks;
weaponInfo_t *weaponInfo = &cg_weapons[WP_6];
float distance;
vec3_t color = {0.7, 0.43, 0.44};
int size = 2;
//FX_CompressionHit( origin ); //TiM: let's test if the rifle doesn't make stuff explode when its shot :)
//return;
//Sparks
//TiM: Calc spark count off proximity to effect
VectorSubtract ( cg.refdef.vieworg, origin, dir );
distance = VectorNormalize( dir );
distance = 50 * ( 1.0f - (distance / 128) ) ;
distance = Com_Clamp( 25, 50, distance );
numSparks = distance + (random() * 4.0f); //4
if (altfire)
{
numSparks *= 1.5f;
}
for ( i = 0; i < numSparks; i++ )
{
scale = 10.0f + (random() * 1.0f); //.25
dscale = -scale;
//Randomize the direction
for (j = 0; j < 3; j ++ )
{
//if ( j !=5 )
//dir[j] = normal[j] + (0.75 * crandom());
//else
dir[j] = normal[j] + (-1 * crandom()); //0.75
}
VectorNormalize(dir);
//set the speed
VectorScale( dir, 200 + (50 * crandom()), velocity); //200
le = FX_AddTrail( origin,
velocity,
qtrue, //qtrue
12.0f,//4
-12.0f,//4
scale,
-scale,
1.0f,
1.0f,
0.5f,
1000.0f, //1000
cgs.media.orangeStarShader);
// FXE_Spray( normal, 200, 50, 0.4f, le);
}
VectorMA( origin, 8, normal, dir );
VectorSet(velocity, 0, 0, 8);
/*
FX_AddSprite( dir,
velocity,
qfalse,
(altfire?50.0f:32.0f),
16.0f,
1.0f,
0.0f,
random()*45.0f,
0.0f,
(altfire?1300.0f:1000.0f),
cgs.media.steamShader );
*/
//Orient the explosions to face the camera
VectorSubtract( cg.refdef.vieworg, origin, dir );
VectorNormalize( dir );
if (!altfire)
{
CG_InitLensFlare( origin,
350, 350,
color, 1.2, 2.0, 1600, 200,
color, 1600, 200, 800, 20, qtrue,
0, 0, qfalse, qtrue,
qfalse, 1.0, cg.time, 0, 0, 210);
VectorMA(origin, size, normal, hitpos);
FX_AddSprite( hitpos, NULL, qfalse, size * size * 15.0f, -150.0f,
1.0f, 0.0f, 360*random(), 0, 400, cgs.media.liteRedParticleShader );
FX_AddSprite( hitpos, NULL, qfalse, size * size * 25.0f, -150.0f,
1.0f, 0.0f, 0.0f, 0, 400, cgs.media.liteRedParticleStreakShader );
le = CG_MakeExplosion2( origin, dir, cgs.media.explosionModel, 5, cgs.media.electricalExplosionSlowShader,
475, qfalse, 1.2f + ( crandom() * 0.3f), LEF_NONE);
le->light = 150;
le->refEntity.renderfx |= RF_NOSHADOW;
VectorSet( le->lightColor, 0.8f, 0.8f, 1.0f );
CG_ImpactMark( cgs.media.compressionMarkShader, origin, normal, random()*360, 1,1,1,1, qfalse, 12, qfalse );
//Shake the camera
CG_ExplosionEffects( origin, 1, 200 );
}
else
{
le = CG_MakeExplosion2( origin, dir, cgs.media.explosionModel, 5, cgs.media.electricalExplosionSlowShader,
500, qfalse, 2.2f + ( crandom() * 0.4f), LEF_NONE);
le->light = 200;
le->refEntity.renderfx |= RF_NOSHADOW;
VectorSet( le->lightColor, 0.8f, 0.8f, 1.0f );
CG_ImpactMark( cgs.media.compressionMarkShader, origin, normal, random()*360, 1,1,1,1, qfalse, 28, qfalse );
//Shake the camera
CG_ExplosionEffects( origin, 2, 240 );
}
// nice explosion sound at the point of impact
trap_S_StartSound(origin, ENTITYNUM_WORLD, CHAN_AUTO, weaponInfo->mainHitSound);
}
/*
-------------------------
FX_CompressionHit
-------------------------
*/
void FX_CompressionHit( vec3_t origin )
{
FX_AddSprite( origin,
NULL,
qfalse,
32.0f,
-32.0f,
1.0f,
1.0f,
random()*360,
0.0f,
250.0f,
cgs.media.prifleImpactShader );
//FIXME: Play an impact sound with a body
// trap_S_StartSound (origin, NULL, 0, cgi_S_RegisterSound ("sound/weapons/prifle/fire.wav") );
}
void FX_PrifleBeamFire( vec3_t startpos, vec3_t endpos, vec3_t normal, qboolean spark, qboolean impact, qboolean empty )
{
refEntity_t beam;
sfxHandle_t sfx;
float size;
vec3_t velocity;
int sparks;
vec3_t rgb = { 1,0.9,0.6}, rgb2={1,0.3,0};
//vec3_t rgb3 = { 1.0, 1.0, 1.0 };
sfx = 0;
// Draw beam first.
memset( &beam, 0, sizeof( beam ) );
VectorCopy( startpos, beam.origin);
VectorCopy( endpos, beam.oldorigin );
beam.reType = RT_LINE;
if (empty)
{
beam.customShader = cgs.media.phaserEmptyShader;
}
else
{
beam.customShader = cgs.media.prifleBeam;
}
AxisClear( beam.axis );
beam.shaderRGBA[0] = 0xff;
beam.shaderRGBA[1] = 0xff;
beam.shaderRGBA[2] = 0xff;
beam.shaderRGBA[3] = 0xff;
if (empty)
{
beam.data.line.width = 1.0f + ( crandom() * 0.6f );
}
else
{
beam.data.line.width = 2.5f + ( crandom() * 0.6f );
}
beam.data.line.stscale = 5.0;
trap_R_AddRefEntityToScene( &beam );
// Now draw the hit graphic
// no explosion at LG impact, it is added with the beam
if ( sfx )
{
Com_Printf("playing %s\n", "phaser sound");
trap_S_StartSound( endpos, ENTITYNUM_WORLD, CHAN_AUTO, sfx );
}
//
// impact mark
//
if (impact)
{
if (!empty)
{ // normal.
CG_ImpactMark( cgs.media.scavMarkShader, endpos, normal, random()*360, 1,1,1,0.2, qfalse,
random() + 1, qfalse );
//VectorCopy( endpos, phaserFlare.worldCoord );
/*CG_InitLensFlare( endpos,
80,
80,
rgb,
1.2,
1.5,
1600,
200,
colorTable[CT_BLACK],
1600,
200,
80,
5,
qfalse,
5,
40,
qfalse,
qfalse,
qfalse,
1.0,
1.0,
200.0,
200.0,
200.0 );*/
//CG_InitLensFlare( endpos,
// 30, 30,
// rgb, 1.2, 2.0, 1600, 200,
// colorTable[CT_BLACK], 1600, 200, 410, 15, qfalse,
// 0, 0, qfalse, qtrue,
// qfalse, 1.0, cg.time, 0, 0, 50);
//TiM : Add your basic cheesy 'seen-way-too-much-in-movies-these-days' anamorphic lens streak :)
//CG_DrawLensFlare( &phaserFlare );
//FX_AddSprite( endpos, NULL, qfalse, random() * 1.25 + 5.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 50.0, cgs.media.blueParticleStreakShader ); //1.5f
//FX_AddQuad2( endpos, normal, random() * 1.25 + 8.0f, 0.0f, 1.0f, 1.0f, rgb3, rgb3, 270, 50.0, cgs.media.blueParticleStreakShader );
//eh... looked bad :P
FX_AddQuad2( endpos, normal, random() * 1.25 + 1.5f, 0.0f, 1.0f, 0.0f, rgb, rgb2, rand() % 360, 500 + random() * 200,
cgs.media.sunnyFlareShader );
}
else
{ // Wuss hit when empty.
FX_AddQuad2( endpos, normal, random() * .75 + 1.0f, 0.0f, 0.5f, 0.0f, rgb, rgb2, rand() % 360, 300 + random() * 200,
cgs.media.sunnyFlareShader );
}
}
// "Fun" sparks... Not when empty.
if ( spark && !empty)
{
sparks = (rand() & 1) + 1;
for(;sparks>0;sparks--)
{
size = 0.2f + (random() * 0.4);
FXE_Spray( normal, 200, 75, 0.8f, velocity);
if (rand() & LEF_USE_COLLISION)
{ // This spark bounces.
FX_AddTrail( endpos, velocity, qtrue, 5.0f, -15.0f,
size, -size, 1.0f, 0.5f, 0.4f, 500.0f, cgs.media.sparkShader);
}
else
{
FX_AddTrail( endpos, velocity, qtrue, 5.0f, -15.0f,
size, -size, 1.0f, 0.5f, 0.0, 500.0f, cgs.media.sparkShader);
}
}
}
}