mirror of
https://github.com/UberGames/rpgxEF.git
synced 2024-11-15 01:11:25 +00:00
a39565b783
... 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)
434 lines
10 KiB
C
434 lines
10 KiB
C
#include "cg_local.h"
|
|
#include "cg_screenfx.h"
|
|
|
|
// this is the list of currently drawing fx and their start times and end times
|
|
screenFX_t theScreenFX;
|
|
|
|
int CG_GetScreenEffectEndTime(int event)
|
|
{
|
|
switch (event)
|
|
{
|
|
case SCREENFX_TRANSPORTER:
|
|
return cg.time + 1000;
|
|
case SCREENFX_SP_TRANSPORTER_IN:
|
|
return cg.time + 4000;
|
|
case SCREENFX_SP_TRANSPORTER_OUT:
|
|
return cg.time + 8000;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// maybe play a sound or something?
|
|
void CG_BeginScreenEffect(int event)
|
|
{
|
|
switch (event)
|
|
{
|
|
case SCREENFX_TRANSPORTER:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// when adding a new effect, we'll either take an empty slot in theScreenFX or
|
|
//overwrite the oldest effect
|
|
void CG_AddFullScreenEffect(int screenfx, int clientNum)
|
|
{
|
|
int i = 0, oldestTime = cg.time, oldestEffect = 0;
|
|
|
|
if (clientNum != cg.predictedPlayerState.clientNum)
|
|
{ // only add screen effects for our client
|
|
return;
|
|
}
|
|
for (i = 0; i < MAX_SCREENFX; i++)
|
|
{
|
|
// if we already have one of these effects going, just add to the duration of
|
|
//the existing one...don't create a new instance of the same effect
|
|
if (theScreenFX.events[i] == screenfx)
|
|
{
|
|
theScreenFX.cgStartTimes[i] = cg.time;
|
|
theScreenFX.cgEndTimes[i] = CG_GetScreenEffectEndTime(screenfx);
|
|
return;
|
|
}
|
|
else if (theScreenFX.cgStartTimes[i])
|
|
{
|
|
if (theScreenFX.cgStartTimes[i] < oldestTime)
|
|
{
|
|
oldestTime = theScreenFX.cgStartTimes[i];
|
|
oldestEffect = i;
|
|
}
|
|
}
|
|
//Hack-didily-ack - TiM: If were already one powerup, switch to the next
|
|
else if ( screenfx == SCREENFX_SP_TRANSPORTER_OUT ) {
|
|
if ( theScreenFX.events[i] == SCREENFX_SP_TRANSPORTER_IN ) {
|
|
theScreenFX.events[i] = 0;
|
|
theScreenFX.cgStartTimes[i] = 0;
|
|
theScreenFX.cgEndTimes[i] = 0;
|
|
}
|
|
}
|
|
else if ( screenfx == SCREENFX_SP_TRANSPORTER_IN ) {
|
|
if ( theScreenFX.events[i] == SCREENFX_SP_TRANSPORTER_OUT ) {
|
|
theScreenFX.events[i] = 0;
|
|
theScreenFX.cgStartTimes[i] = 0;
|
|
theScreenFX.cgEndTimes[i] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
oldestTime = theScreenFX.cgStartTimes[i];
|
|
oldestEffect = i;
|
|
}
|
|
}
|
|
theScreenFX.events[oldestEffect] = screenfx;
|
|
theScreenFX.cgStartTimes[oldestEffect] = cg.time;
|
|
theScreenFX.cgEndTimes[oldestEffect] = CG_GetScreenEffectEndTime(screenfx);
|
|
CG_BeginScreenEffect(screenfx);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
CG_DrawScreenQuad
|
|
|
|
===============
|
|
*/
|
|
|
|
|
|
static void CG_DrawScreenQuad(float alpha, qhandle_t screenshader)
|
|
{
|
|
refEntity_t ent;
|
|
float radius;
|
|
|
|
// ragePro systems can't fade blends, so don't obscure the screen
|
|
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
|
|
return;
|
|
}
|
|
|
|
if (cg.refdef.fov_x > 120)
|
|
{
|
|
return; // Too wide to show this.
|
|
}
|
|
else if (cg.refdef.fov_x > 80)
|
|
{
|
|
radius = 8.0 + (cg.refdef.fov_x - 80)*0.2;
|
|
}
|
|
else
|
|
{
|
|
radius = 8.0;
|
|
}
|
|
|
|
memset( &ent, 0, sizeof( ent ) );
|
|
ent.reType = RT_SPRITE;
|
|
ent.renderfx = RF_FIRST_PERSON;
|
|
|
|
VectorMA( cg.refdef.vieworg, 8, cg.refdef.viewaxis[0], ent.origin );
|
|
|
|
ent.data.sprite.radius = radius;
|
|
ent.customShader = screenshader;
|
|
ent.shaderRGBA[0] = alpha * 255;
|
|
ent.shaderRGBA[1] = alpha * 255;
|
|
ent.shaderRGBA[2] = alpha * 255;
|
|
ent.shaderRGBA[3] = 255;
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
}
|
|
|
|
/*
|
|
static void CG_DrawDirectionalScreenQuad(float alpha, qhandle_t screenshader)
|
|
{
|
|
refEntity_t ent;
|
|
vec3_t screencenter;
|
|
byte topleft, topright, lowleft, lowright, top, low, left, right;
|
|
float val;
|
|
|
|
// ragePro systems can't fade blends, so don't obscure the screen
|
|
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
|
|
return;
|
|
}
|
|
|
|
// Set up all the basic info about this refentity
|
|
VectorMA( cg.refdef.vieworg, 8, cg.refdef.viewaxis[0], screencenter);
|
|
|
|
memset( &ent, 0, sizeof( ent ) );
|
|
ent.reType = RT_ALPHAVERTPOLY;
|
|
ent.renderfx = RF_FIRST_PERSON;
|
|
|
|
ent.data.sprite.radius = 4;
|
|
ent.customShader = screenshader;
|
|
* (unsigned int *) ent.shaderRGBA = 0xffffffff;
|
|
* (unsigned int *) ent.data.sprite.vertRGBA[0] = 0xffffffff;
|
|
* (unsigned int *) ent.data.sprite.vertRGBA[1] = 0xffffffff;
|
|
* (unsigned int *) ent.data.sprite.vertRGBA[2] = 0xffffffff;
|
|
* (unsigned int *) ent.data.sprite.vertRGBA[3] = 0xffffffff;
|
|
|
|
// left
|
|
val = alpha*(0.5 + 0.5*(cg.damageX - fabs(cg.damageY)));
|
|
if (val<0)
|
|
left=0;
|
|
else if (val>1.0)
|
|
left=255;
|
|
else
|
|
left=255.0*val;
|
|
|
|
// upper left
|
|
val = alpha*(0.5*(cg.damageX + cg.damageY));
|
|
if (val<0)
|
|
topleft=0;
|
|
else if (val>1.0)
|
|
topleft=255;
|
|
else
|
|
topleft=255.0*val;
|
|
|
|
// top
|
|
val = alpha*(0.5 + 0.5*(-fabs(cg.damageX) + cg.damageY));
|
|
if (val<0)
|
|
top=0;
|
|
else if (val>1.0)
|
|
top=255;
|
|
else
|
|
top=255.0*val;
|
|
|
|
// upper right
|
|
val = alpha*(0.5*(-cg.damageX + cg.damageY));
|
|
if (val<0)
|
|
topright=0;
|
|
else if (val>1.0)
|
|
topright=255;
|
|
else
|
|
topright=255.0*val;
|
|
|
|
// right
|
|
val = alpha*(0.5 + 0.5*(-cg.damageX - fabs(cg.damageY)));
|
|
if (val<0)
|
|
right=0;
|
|
else if (val>1.0)
|
|
right=255;
|
|
else
|
|
right=255.0*val;
|
|
|
|
// lower right
|
|
val = alpha*(0.5*(-cg.damageX - cg.damageY));
|
|
if (val<0)
|
|
lowright=0;
|
|
else if (val>1.0)
|
|
lowright=255;
|
|
else
|
|
lowright=255.0*val;
|
|
|
|
// bottom
|
|
val = alpha*(0.5 + 0.5*(-fabs(cg.damageX) - cg.damageY));
|
|
if (val<0)
|
|
low=0;
|
|
else if (val>1.0)
|
|
low=255;
|
|
else
|
|
low=255.0*val;
|
|
|
|
// lower left
|
|
val = alpha*(0.5*(cg.damageX - cg.damageY));
|
|
if (val<0)
|
|
lowleft=0;
|
|
else if (val>1.0)
|
|
lowleft=255;
|
|
else
|
|
lowleft=255.0*val;
|
|
|
|
|
|
// Draw the upper left corner
|
|
VectorMA(screencenter, 4, cg.refdef.viewaxis[1], ent.origin);
|
|
VectorMA(ent.origin, 4, cg.refdef.viewaxis[2], ent.origin);
|
|
ent.data.sprite.vertRGBA[0][3] = topleft;
|
|
ent.data.sprite.vertRGBA[1][3] = top;
|
|
ent.data.sprite.vertRGBA[2][3] = 0;
|
|
ent.data.sprite.vertRGBA[3][3] = left;
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
|
|
|
|
// Draw topper right corner
|
|
VectorMA(screencenter, -4, cg.refdef.viewaxis[1], ent.origin);
|
|
VectorMA(ent.origin, 4, cg.refdef.viewaxis[2], ent.origin);
|
|
ent.data.sprite.vertRGBA[0][3] = top;
|
|
ent.data.sprite.vertRGBA[1][3] = topright;
|
|
ent.data.sprite.vertRGBA[2][3] = right;
|
|
ent.data.sprite.vertRGBA[3][3] = 0;
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
|
|
|
|
// Draw lower right corner
|
|
VectorMA(screencenter, -4, cg.refdef.viewaxis[1], ent.origin);
|
|
VectorMA(ent.origin, -4, cg.refdef.viewaxis[2], ent.origin);
|
|
ent.data.sprite.vertRGBA[0][3] = 0;
|
|
ent.data.sprite.vertRGBA[1][3] = right;
|
|
ent.data.sprite.vertRGBA[2][3] = lowright;
|
|
ent.data.sprite.vertRGBA[3][3] = low;
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
|
|
|
|
// Draw lower left corner
|
|
VectorMA(screencenter, 4, cg.refdef.viewaxis[1], ent.origin);
|
|
VectorMA(ent.origin, -4, cg.refdef.viewaxis[2], ent.origin);
|
|
ent.data.sprite.vertRGBA[0][3] = left;
|
|
ent.data.sprite.vertRGBA[1][3] = 0;
|
|
ent.data.sprite.vertRGBA[2][3] = low;
|
|
ent.data.sprite.vertRGBA[3][3] = lowleft;
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
|
|
}
|
|
*/
|
|
|
|
static void CG_DrawScreenBlob(float redalpha, float greenalpha)
|
|
{
|
|
refEntity_t ent;
|
|
float alphascale;
|
|
float bluealpha = 0;
|
|
|
|
// ragePro systems can't fade blends, so don't obscure the screen
|
|
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
|
|
return;
|
|
}
|
|
|
|
memset( &ent, 0, sizeof( ent ) );
|
|
ent.reType = RT_SPRITE;
|
|
ent.renderfx = RF_FIRST_PERSON;
|
|
|
|
// Available input:
|
|
// cg.damageValue: Range from 0 to 1, indicating the amount of damage.
|
|
// cg.damageX and cg_damageY: Range from -1 to 1, indicating the location of the damage.
|
|
|
|
VectorMA( cg.refdef.vieworg, 8, cg.refdef.viewaxis[0], ent.origin );
|
|
VectorMA( ent.origin, cg.damageX * -8, cg.refdef.viewaxis[1], ent.origin );
|
|
VectorMA( ent.origin, cg.damageY * 8, cg.refdef.viewaxis[2], ent.origin );
|
|
|
|
// Here's the scoop: The closer we are to the center, the more transparent this blob is.
|
|
alphascale = (2*fabs(cg.damageX)+fabs(cg.damageY))/3.0;
|
|
redalpha *= alphascale;
|
|
greenalpha *= alphascale;
|
|
|
|
if (redalpha > greenalpha)
|
|
{
|
|
ent.data.sprite.radius = cg.damageValue * 15 * redalpha;
|
|
}
|
|
else
|
|
{
|
|
ent.data.sprite.radius = cg.damageShieldValue * 15 * greenalpha;
|
|
}
|
|
|
|
/* if (redalpha < 0.01)
|
|
{ // Just shield damage
|
|
ent.customShader = cgs.media.shieldBlobShader;
|
|
// Set all colors to the same as green, since the shader is green
|
|
redalpha = bluealpha = greenalpha;
|
|
}
|
|
else*/ if (greenalpha < 0.01)
|
|
{ // Just pain damage
|
|
ent.customShader = cgs.media.painBlobShader;
|
|
// Set all colors to the same as red, since the shader is red
|
|
greenalpha = bluealpha = redalpha;
|
|
}
|
|
else
|
|
{ // Both
|
|
ent.customShader = cgs.media.painShieldBlobShader;
|
|
}
|
|
|
|
ent.shaderRGBA[0] = 0xff * redalpha;
|
|
ent.shaderRGBA[1] = 0xff * greenalpha;
|
|
ent.shaderRGBA[2] = 0xff * bluealpha;
|
|
ent.shaderRGBA[3] = 0xff;
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
}
|
|
|
|
|
|
|
|
void CG_DrawFullScreenEffect(int screenfx, int start, int end)
|
|
{
|
|
float alpha, alpha2 = 0.0; //TiM - second alpha
|
|
int end2, start2;
|
|
|
|
alpha = (float)(end-cg.time)/(float)(end-start);
|
|
|
|
switch (screenfx)
|
|
{
|
|
case SCREENFX_TRANSPORTER:
|
|
CG_DrawScreenQuad(alpha, cgs.media.teleportEffectShader);
|
|
break;
|
|
case SCREENFX_SP_TRANSPORTER_IN:
|
|
end2=end - 2500;
|
|
|
|
CG_DrawScreenQuad( alpha, cgs.media.teleportEffectShader);
|
|
//Fade in a white quad a little later
|
|
if (cg.time <= end2 ) {
|
|
alpha2 = (float)(end2-cg.time)/(float)(end2-start);
|
|
CG_DrawScreenQuad( alpha2, cgs.media.white2Shader);
|
|
}
|
|
break;
|
|
case SCREENFX_SP_TRANSPORTER_OUT:
|
|
start2=start+2500;
|
|
end2=end - 4000;
|
|
|
|
alpha = (float)(end2-cg.time)/(float)(end2-start);
|
|
CG_DrawScreenQuad(( 1.0f - alpha), cgs.media.teleportEffectShader);
|
|
if ( cg.time >= start2 ) {
|
|
alpha2 = (float)(end2-cg.time)/(float)(end2-start2);
|
|
if ( cg.time >= end2 )
|
|
alpha2=0.0f;
|
|
|
|
CG_DrawScreenQuad( ( 1.0f - alpha2), cgs.media.white2Shader);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void CG_DrawFullScreenFX( void )
|
|
{
|
|
int i = 0, t;
|
|
float alpha, redalpha, greenalpha;
|
|
|
|
if ( (cg.snap->ps.clientNum != cg.predictedPlayerState.clientNum) || cg.renderingThirdPerson )
|
|
{
|
|
return;
|
|
}
|
|
|
|
t = cg.time - cg.damageTime;
|
|
if ( t > 0 && t < DAMAGE_TIME)
|
|
{ // Draw the blobs.
|
|
alpha = 1.0 - ((float)t / (float)DAMAGE_TIME);
|
|
|
|
redalpha = alpha*cg.damageValue*1.5;
|
|
if (redalpha > 1.0)
|
|
{
|
|
redalpha = 1.0;
|
|
}
|
|
|
|
greenalpha = alpha*cg.damageShieldValue*1.5;
|
|
if (greenalpha > 1.0)
|
|
{
|
|
greenalpha = 1.0;
|
|
}
|
|
|
|
CG_DrawScreenBlob(redalpha, greenalpha);
|
|
}
|
|
|
|
for (i = 0; i < MAX_SCREENFX; i++)
|
|
{
|
|
if (theScreenFX.cgEndTimes[i])
|
|
{
|
|
if (theScreenFX.cgEndTimes[i] <= cg.time)
|
|
{
|
|
// remove this effect
|
|
theScreenFX.events[i] = 0;
|
|
theScreenFX.cgStartTimes[i] = 0;
|
|
theScreenFX.cgEndTimes[i] = 0;
|
|
}
|
|
else
|
|
{
|
|
// still drawing this effect
|
|
CG_DrawFullScreenEffect(theScreenFX.events[i],theScreenFX.cgStartTimes[i],theScreenFX.cgEndTimes[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|