rpgxef/code/cgame/fx_transporter.cpp

294 lines
7.1 KiB
C++

#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) )
-------------------------
*/
void FX_SPTransporterLensFlares( centity_t* cent, vec3_t headVector, int32_t startTime ) {
refEntity_t flare;
trace_t tr;
int32_t i;
int32_t direction = 1;
int32_t timeOffset = 0; //250 - time between first and second flares appearing;
float ratio;
float dlightRatio;
vec3_t origin, tempOrigin;
int32_t width;
int32_t height;
//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 );
}