rpgxef/code/cgame/fx_transporter.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

293 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, int startTime ) {
refEntity_t flare;
trace_t tr;
int i;
int direction = 1;
int timeOffset = 0; //250 - time between first and second flares appearing;
float ratio;
float dlightRatio;
vec3_t origin, tempOrigin;
int width;
int 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 );
}