2012-08-04 10:54:37 +00:00
|
|
|
|
|
|
|
#include "cg_local.h"
|
|
|
|
#include "fx_local.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
-------------------------
|
|
|
|
SPTransporterLensFlares
|
|
|
|
|
|
|
|
TiM: Judging from the title,
|
|
|
|
you just KNOW it's mine ;)
|
|
|
|
|
|
|
|
Anyway, the point of this
|
|
|
|
function is to render 4
|
|
|
|
sprites and then scale + move
|
|
|
|
them in a way reminisicant
|
|
|
|
of ST: Voyager's transporter FX.
|
|
|
|
|
|
|
|
I wrote this instead of using the
|
|
|
|
already made FX spawning functions
|
|
|
|
because they don't let u track an origin.
|
|
|
|
To stop the particle
|
|
|
|
from rendering within the character, I'm going to
|
|
|
|
use the DEPTHHACK renderflag, the flag
|
|
|
|
originally used for the weapon models
|
|
|
|
in first-person mode. :)
|
|
|
|
|
|
|
|
Planned timing:
|
|
|
|
|
|
|
|
0 - 500 : Flare spawns, and scales up to it's main size (width parameter)
|
|
|
|
500 - 1500 : Flare moves up the height/2 of model (height parameter)
|
|
|
|
1500 - 2000 : Flare scales down and disappears ( width * 1.0 - (timeScale) )
|
|
|
|
-------------------------
|
|
|
|
*/
|
|
|
|
|
2013-08-16 13:43:41 +00:00
|
|
|
void FX_SPTransporterLensFlares( centity_t* cent, vec3_t headVector, int32_t startTime ) {
|
2012-08-04 10:54:37 +00:00
|
|
|
refEntity_t flare;
|
|
|
|
trace_t tr;
|
2013-08-16 13:43:41 +00:00
|
|
|
int32_t i;
|
|
|
|
int32_t direction = 1;
|
|
|
|
int32_t timeOffset = 0; //250 - time between first and second flares appearing;
|
2012-08-04 10:54:37 +00:00
|
|
|
float ratio;
|
|
|
|
float dlightRatio;
|
|
|
|
|
|
|
|
vec3_t origin, tempOrigin;
|
2013-08-16 13:43:41 +00:00
|
|
|
int32_t width;
|
|
|
|
int32_t height;
|
2012-08-04 10:54:37 +00:00
|
|
|
|
|
|
|
//Hrmm... we have a glitch lol. Since DEPTHHACK is on, the flare will be drawn
|
|
|
|
//from ANYWHERE IN THE LEVEL! O_o
|
|
|
|
//So.... uh, we'll do a trace between ourselves and the entity this is attached
|
|
|
|
//to, and if they can't see each other, screw it. :P
|
|
|
|
if ( cg.predictedPlayerState.clientNum != cent->currentState.clientNum ) {
|
|
|
|
CG_Trace( &tr, cg.refdef.vieworg, NULL, NULL,
|
|
|
|
cent->lerpOrigin, cg.predictedPlayerState.clientNum, CONTENTS_SOLID );
|
|
|
|
if ( tr.fraction != 1 ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*else {
|
|
|
|
Com_Printf( "Origin: { %f, %f, %f }\n", cent->lerpOrigin[0], cent->lerpOrigin[1], cent->lerpOrigin[2] );
|
|
|
|
Com_Printf( "HeadVector: { %f, %f, %f }\n", headVector[0], headVector[1], headVector[2] );
|
|
|
|
return;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
//calculate the necessary data we need to place the origin in the direct center of the model
|
|
|
|
|
|
|
|
memset( &flare, 0, sizeof( flare ) );
|
|
|
|
|
|
|
|
//Bah. I thought lerpOrigin was at the base of the feet. Turns out it's at the knees O_o
|
|
|
|
//This little hack should help that
|
|
|
|
VectorCopy( cent->lerpOrigin, tempOrigin );
|
|
|
|
tempOrigin[2] -= 24;
|
|
|
|
|
|
|
|
//If the distance means we're not lying down
|
|
|
|
if ( ( headVector[2] - tempOrigin[2] ) > 8 ) {
|
|
|
|
//find the average between our lerp origin and headVector to find the center
|
|
|
|
//VectorAdd( headVector, tempOrigin, origin );
|
|
|
|
//VectorScale( origin, 0.5, origin );
|
|
|
|
VectorAverage( headVector, tempOrigin, origin );
|
|
|
|
|
|
|
|
width = 30;
|
|
|
|
height = (headVector[2] - tempOrigin[2]) / 2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
width = 30;
|
|
|
|
height = 4;
|
|
|
|
|
|
|
|
VectorCopy( cent->lerpOrigin, origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
flare.reType = RT_SPRITE;
|
|
|
|
flare.shaderRGBA[0] = 0xff;
|
|
|
|
flare.shaderRGBA[1] = 0xff;
|
|
|
|
flare.shaderRGBA[2] = 0xff;
|
|
|
|
flare.shaderRGBA[3] = 0xff;
|
|
|
|
|
|
|
|
flare.data.sprite.rotation = 0;
|
|
|
|
flare.nonNormalizedAxes = qtrue; //needed for effective scaling
|
|
|
|
|
|
|
|
flare.renderfx |= RF_DEPTHHACK; //DEPTHHACK renders the element over everything else. Useful in this lens flare simulation case :)
|
|
|
|
|
|
|
|
//loop 4 times = 4 flares. :)
|
|
|
|
for (i = 0; i < 4; i++ ) {
|
|
|
|
VectorClear( flare.origin );
|
|
|
|
VectorCopy( origin, flare.origin);
|
|
|
|
|
|
|
|
//the first two flares are the main ones
|
|
|
|
if ( i < 2 ) {
|
|
|
|
flare.customShader = cgs.media.transport1Shader; //1
|
|
|
|
timeOffset = startTime;
|
|
|
|
}
|
|
|
|
else { // the second two spawn a little later
|
|
|
|
flare.customShader = cgs.media.transport2Shader;
|
|
|
|
timeOffset = startTime + 650; //750
|
|
|
|
}
|
|
|
|
|
|
|
|
//the second flare each round goes down instead of up
|
|
|
|
if ( i % 2 == 0)
|
|
|
|
direction = 1;
|
|
|
|
else
|
|
|
|
direction = -1;
|
|
|
|
|
|
|
|
//===========================
|
|
|
|
|
|
|
|
if ( cg.time > timeOffset + 2000 ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Phase 1: flares get bigger
|
|
|
|
if ( cg.time < timeOffset + 500 ) {
|
|
|
|
ratio = ((float)(cg.time - timeOffset) * 0.002);
|
|
|
|
if (ratio < 0 )
|
|
|
|
ratio = 0.0f;
|
|
|
|
else if (ratio > 1 )
|
|
|
|
ratio = 1.0f;
|
|
|
|
|
|
|
|
flare.data.sprite.radius = (float)width * ratio;
|
|
|
|
/*if ( i ==0 )
|
|
|
|
Com_Printf( "Phase 1 Radius: %f\n", flare.data.sprite.radius );*/
|
|
|
|
}
|
|
|
|
//Phase 2: flares move up/down character
|
|
|
|
if ( ( cg.time < timeOffset + 1500 ) && ( cg.time >= timeOffset + 500 ) ) {
|
|
|
|
ratio = ( (float)(cg.time - (timeOffset + 500) ) * 0.001 );
|
|
|
|
if (ratio < 0 )
|
|
|
|
ratio = 0.0f;
|
|
|
|
else if (ratio > 1 )
|
|
|
|
ratio = 1.0f;
|
|
|
|
|
|
|
|
flare.data.sprite.radius = (float)width;
|
|
|
|
flare.origin[2] += (float)direction * (float)height * ratio;
|
|
|
|
/*if (i == 0 )
|
|
|
|
Com_Printf( "Phase 2 Location: %f\n", flare.origin[2] );*/
|
|
|
|
}
|
|
|
|
//Phase 3: flares get smaller
|
|
|
|
if ( ( cg.time < timeOffset + 2000 ) && ( cg.time >= timeOffset + 1500 ) ) {
|
|
|
|
ratio = 1.0f - (float)(cg.time - ( timeOffset + 1500 ) ) * 0,002;
|
|
|
|
if (ratio < 0 )
|
|
|
|
ratio = 0.0f;
|
|
|
|
else if (ratio > 1 )
|
|
|
|
ratio = 1.0f;
|
|
|
|
|
|
|
|
flare.origin[2] += ((float)height * (float)direction);
|
|
|
|
flare.data.sprite.radius = (float)width * ratio;
|
|
|
|
/*if ( i == 0 )
|
|
|
|
Com_Printf( "Phase 3 Radius: %f\n", flare.data.sprite.radius );*/
|
|
|
|
}
|
|
|
|
|
|
|
|
trap_R_AddRefEntityToScene( &flare );
|
|
|
|
}
|
|
|
|
|
|
|
|
//dynamic light calculation
|
|
|
|
if ( cg.time < ( startTime + 2000 ) ) {
|
|
|
|
dlightRatio = (float)( cg.time - startTime ) * 0,0005;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dlightRatio = 1.0f - (float)( cg.time - ( startTime + 2000 ) ) * 0,0005;
|
|
|
|
}
|
|
|
|
|
|
|
|
//dynamic light FX
|
|
|
|
trap_R_AddLightToScene( origin, 80.0f * dlightRatio, 0.345, 0.624, 0.835 );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
-------------------------
|
|
|
|
TransporterParticle
|
|
|
|
-------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
qboolean TransporterParticle( localEntity_t *le)
|
|
|
|
{
|
|
|
|
vec3_t org, velocity = { 0, 0, 68 };
|
|
|
|
vec3_t accel = { 0, 0, -12 };
|
|
|
|
float scale, dscale;
|
|
|
|
qhandle_t shader;
|
|
|
|
|
|
|
|
VectorCopy( le->refEntity.origin, org );
|
|
|
|
org[2] += 0;//38;
|
|
|
|
|
|
|
|
shader = ( le->data.spawner.dir[0] == 0 ) ? cgs.media.trans1Shader : cgs.media.trans2Shader;
|
|
|
|
scale = ( le->data.spawner.dir[0] == 0 ) ? 2.0 : 4.0;
|
|
|
|
dscale = ( le->data.spawner.dir[0] == 0 ) ? 4.0 : 24.0;
|
|
|
|
|
|
|
|
le->data.spawner.dir[0]++;
|
|
|
|
|
|
|
|
FX_AddSprite( org,
|
|
|
|
velocity,
|
|
|
|
qfalse,
|
|
|
|
scale,
|
|
|
|
dscale,
|
|
|
|
1.0f,
|
|
|
|
0.0f,
|
|
|
|
0,
|
|
|
|
0.0f,
|
|
|
|
450.0f,
|
|
|
|
shader );
|
|
|
|
|
|
|
|
VectorScale( velocity, -1, velocity );
|
|
|
|
VectorScale( accel, -1, accel );
|
|
|
|
|
|
|
|
FX_AddSprite( org,
|
|
|
|
velocity,
|
|
|
|
qfalse,
|
|
|
|
scale,
|
|
|
|
dscale,
|
|
|
|
1.0f,
|
|
|
|
0.0f,
|
|
|
|
0,
|
|
|
|
0.0f,
|
|
|
|
450.0f,
|
|
|
|
shader );
|
|
|
|
|
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
-------------------------
|
|
|
|
TransporterPad
|
|
|
|
-------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
qboolean TransporterPad( localEntity_t *le)
|
|
|
|
{
|
|
|
|
vec3_t org;
|
|
|
|
vec3_t up = {0,0,1};
|
|
|
|
float scale, dscale;
|
|
|
|
qhandle_t shader;
|
|
|
|
|
|
|
|
VectorCopy( le->refEntity.origin, org );
|
|
|
|
org[2] -= 3;
|
|
|
|
|
|
|
|
shader = cgs.media.trans1Shader;
|
|
|
|
scale = 20.0;
|
|
|
|
dscale = 2.0;
|
|
|
|
|
|
|
|
FX_AddQuad( org,
|
|
|
|
up,
|
|
|
|
scale,
|
|
|
|
dscale,
|
|
|
|
1.0f,
|
|
|
|
0.0f,
|
|
|
|
0,
|
|
|
|
950.0f,
|
|
|
|
shader );
|
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
-------------------------
|
|
|
|
FX_Transporter
|
|
|
|
-------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
void FX_Transporter( vec3_t origin )
|
|
|
|
{
|
|
|
|
vec3_t up = {0,0,1};
|
|
|
|
|
|
|
|
FX_AddSpawner( origin, up, NULL, NULL, qfalse, 0, 0, 200, TransporterParticle, 0 );
|
|
|
|
// trap_S_StartSound( origin, NULL, CHAN_AUTO, cgs.media.teleInSound );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
-------------------------
|
|
|
|
FX_TransporterPad
|
|
|
|
-------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
void FX_TransporterPad( vec3_t origin )
|
|
|
|
{
|
|
|
|
vec3_t up = {0,0,1};
|
|
|
|
|
|
|
|
FX_AddSpawner( origin, up, NULL, NULL, qfalse, 1000, 0, 0, TransporterPad, 0 );
|
|
|
|
}
|
|
|
|
|