902 lines
19 KiB
C++
902 lines
19 KiB
C++
//=======================================================================
|
|
// Copyright XashXT Group 2008 ©
|
|
// utils.cpp - client game utilities code
|
|
//=======================================================================
|
|
|
|
#include "extdll.h"
|
|
#include "utils.h"
|
|
#include "hud.h"
|
|
|
|
static const float bytedirs[NUMVERTEXNORMALS][3] =
|
|
{
|
|
#include "anorms.h"
|
|
};
|
|
|
|
Vector BitsToDir( int bits )
|
|
{
|
|
Vector dir;
|
|
|
|
if( bits < 0 || bits >= NUMVERTEXNORMALS )
|
|
return Vector( 0, 0, 0 );
|
|
|
|
dir.x = bytedirs[bits][0];
|
|
dir.y = bytedirs[bits][1];
|
|
dir.z = bytedirs[bits][2];
|
|
|
|
return dir;
|
|
}
|
|
|
|
// NOTE: modify these functions with caution
|
|
|
|
typedef struct
|
|
{
|
|
char *name;
|
|
byte *buf;
|
|
int size;
|
|
int read;
|
|
BOOL badRead;
|
|
char string[2048]; // using for store strings
|
|
} user_message_t;
|
|
|
|
static user_message_t gMsg;
|
|
|
|
void BEGIN_READ( const char *pszName, int iSize, void *pBuf )
|
|
{
|
|
memset( &gMsg, 0, sizeof( gMsg ));
|
|
|
|
gMsg.size = iSize;
|
|
gMsg.buf = (byte *)pBuf;
|
|
}
|
|
|
|
void END_READ( void )
|
|
{
|
|
if( gMsg.badRead )
|
|
{
|
|
ALERT( at_console, "%s was received with errors\n", gMsg.name );
|
|
}
|
|
}
|
|
|
|
int READ_CHAR( void )
|
|
{
|
|
int c;
|
|
|
|
if( gMsg.read + 1 > gMsg.size )
|
|
{
|
|
gMsg.badRead = true;
|
|
return -1;
|
|
}
|
|
|
|
c = (signed char)gMsg.buf[gMsg.read];
|
|
gMsg.read++;
|
|
|
|
return c;
|
|
}
|
|
|
|
int READ_BYTE( void )
|
|
{
|
|
int c;
|
|
|
|
if( gMsg.read+1 > gMsg.size )
|
|
{
|
|
gMsg.badRead = true;
|
|
return -1;
|
|
}
|
|
|
|
c = (unsigned char)gMsg.buf[gMsg.read];
|
|
gMsg.read++;
|
|
|
|
return c;
|
|
}
|
|
|
|
int READ_SHORT( void )
|
|
{
|
|
int c;
|
|
|
|
if( gMsg.read + 2 > gMsg.size )
|
|
{
|
|
gMsg.badRead = true;
|
|
return -1;
|
|
}
|
|
|
|
c = (short)( gMsg.buf[gMsg.read] + ( gMsg.buf[gMsg.read+1] << 8 ));
|
|
gMsg.read += 2;
|
|
|
|
return c;
|
|
}
|
|
|
|
int READ_WORD( void ) { return READ_SHORT(); }
|
|
|
|
int READ_LONG( void )
|
|
{
|
|
int c;
|
|
|
|
if( gMsg.read + 4 > gMsg.size )
|
|
{
|
|
gMsg.badRead = true;
|
|
return -1;
|
|
}
|
|
c = gMsg.buf[gMsg.read]+(gMsg.buf[gMsg.read+1]<<8)+(gMsg.buf[gMsg.read+2]<<16)+(gMsg.buf[gMsg.read+3]<<24);
|
|
gMsg.read += 4;
|
|
|
|
return c;
|
|
}
|
|
|
|
float READ_FLOAT( void )
|
|
{
|
|
union { float f; int l; } dat;
|
|
|
|
dat.l = READ_LONG();
|
|
return dat.f;
|
|
}
|
|
|
|
char* READ_STRING( void )
|
|
{
|
|
int l, c;
|
|
|
|
gMsg.string[0] = 0;
|
|
|
|
l = 0;
|
|
do
|
|
{
|
|
if( gMsg.read+1 > gMsg.size ) break; // no more characters
|
|
|
|
c = READ_CHAR();
|
|
if( c == -1 || c == '\0' )
|
|
break;
|
|
|
|
// translate all fmt spec to avoid crash bugs
|
|
if( c == '%' ) c = '.';
|
|
|
|
gMsg.string[l] = c;
|
|
l++;
|
|
} while( l < sizeof( gMsg.string ) - 1 );
|
|
|
|
gMsg.string[l] = 0; // terminator
|
|
|
|
return gMsg.string;
|
|
}
|
|
|
|
//
|
|
// Xash3D network specs. Don't modify!
|
|
//
|
|
float READ_COORD( void )
|
|
{
|
|
return READ_FLOAT();
|
|
}
|
|
|
|
float READ_ANGLE( void )
|
|
{
|
|
return (float)(READ_SHORT() * (360.0 / 65536));
|
|
}
|
|
|
|
Vector READ_DIR( void )
|
|
{
|
|
return BitsToDir( READ_BYTE() );
|
|
}
|
|
|
|
//
|
|
// Sprites draw stuff
|
|
//
|
|
typedef struct
|
|
{
|
|
// temp handle
|
|
HSPRITE hSprite;
|
|
HSPRITE hPause; // pause pic
|
|
|
|
// crosshair members
|
|
HSPRITE hCrosshair;
|
|
wrect_t rcCrosshair;
|
|
byte rgbCrosshair[3];
|
|
bool noCrosshair;
|
|
} draw_stuff_t;
|
|
|
|
static draw_stuff_t ds;
|
|
|
|
int SPR_Frames( HSPRITE hPic )
|
|
{
|
|
int Frames;
|
|
|
|
GetParms( NULL, NULL, &Frames, 0, hPic );
|
|
|
|
return Frames;
|
|
}
|
|
|
|
int SPR_Height( HSPRITE hPic, int frame )
|
|
{
|
|
int Height;
|
|
|
|
GetParms( NULL, &Height, NULL, frame, hPic );
|
|
|
|
return Height;
|
|
}
|
|
|
|
int SPR_Width( HSPRITE hPic, int frame )
|
|
{
|
|
int Width;
|
|
|
|
GetParms( &Width, NULL, NULL, frame, hPic );
|
|
|
|
return Width;
|
|
}
|
|
|
|
void Draw_VidInit( void )
|
|
{
|
|
memset( &ds, 0, sizeof( ds ));
|
|
}
|
|
|
|
/*
|
|
====================
|
|
SPRITE_GetList
|
|
|
|
====================
|
|
*/
|
|
void ParseHudSprite( const char **pfile, char *psz, client_sprite_t *result )
|
|
{
|
|
int x = 0, y = 0, width = 0, height = 0;
|
|
client_sprite_t p;
|
|
int section = 0;
|
|
char *token;
|
|
|
|
memset( &p, 0, sizeof( client_sprite_t ));
|
|
|
|
while(( token = COM_ParseToken( pfile )) != NULL )
|
|
{
|
|
if( !stricmp( token, psz ))
|
|
{
|
|
token = COM_ParseToken( pfile );
|
|
if( !stricmp( token, "{" )) section = 1;
|
|
}
|
|
if( section ) // parse section
|
|
{
|
|
if( !stricmp( token, "}" )) break; // end section
|
|
|
|
if( !stricmp( token, "file" ))
|
|
{
|
|
token = COM_ParseToken( pfile );
|
|
strncpy( p.szSprite, token, 64 );
|
|
|
|
// fill structure at default
|
|
p.hSprite = SPR_Load( p.szSprite );
|
|
width = SPR_Width( p.hSprite, 0 );
|
|
height = SPR_Height( p.hSprite, 0 );
|
|
x = y = 0;
|
|
}
|
|
else if ( !stricmp( token, "name" ))
|
|
{
|
|
token = COM_ParseToken( pfile );
|
|
strncpy( p.szName, token, 64 );
|
|
}
|
|
else if ( !stricmp( token, "x" ))
|
|
{
|
|
token = COM_ParseToken( pfile );
|
|
x = atoi( token );
|
|
}
|
|
else if ( !stricmp( token, "y" ))
|
|
{
|
|
token = COM_ParseToken( pfile );
|
|
y = atoi( token );
|
|
}
|
|
else if ( !stricmp( token, "width" ))
|
|
{
|
|
token = COM_ParseToken( pfile );
|
|
width = atoi( token );
|
|
}
|
|
else if ( !stricmp( token, "height" ))
|
|
{
|
|
token = COM_ParseToken( pfile );
|
|
height = atoi( token );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !section ) return; // data not found
|
|
|
|
// calculate sprite position
|
|
p.rc.left = x;
|
|
p.rc.right = x + width;
|
|
p.rc.top = y;
|
|
p.rc.bottom = y + height;
|
|
|
|
memcpy( result, &p, sizeof( client_sprite_t ));
|
|
}
|
|
|
|
client_sprite_t *SPR_GetList( const char *psz, int *piCount )
|
|
{
|
|
char *pfile = (char *)LOAD_FILE( psz, NULL );
|
|
int iSprCount = 0;
|
|
|
|
if( !pfile )
|
|
{
|
|
*piCount = iSprCount;
|
|
return NULL;
|
|
}
|
|
|
|
char *token;
|
|
const char *plist = pfile;
|
|
int depth = 0;
|
|
|
|
while(( token = COM_ParseToken( &plist )) != NULL ) // calculate count of sprites
|
|
{
|
|
if( !stricmp( token, "{" )) depth++;
|
|
else if( !stricmp( token, "}" )) depth--;
|
|
else if( depth == 0 && !strcmp( token, "hudsprite" ))
|
|
iSprCount++;
|
|
}
|
|
|
|
client_sprite_t *phud;
|
|
plist = pfile;
|
|
|
|
phud = new client_sprite_t[iSprCount];
|
|
|
|
if( depth != 0 ) ALERT( at_console, "%s EOF without closing brace\n", psz );
|
|
|
|
for( int i = 0; i < iSprCount; i++ ) //parse structures
|
|
{
|
|
ParseHudSprite( &plist, "hudsprite", &phud[i] );
|
|
}
|
|
|
|
if( !iSprCount ) ALERT( at_console, "SPR_GetList: %s doesn't have sprites\n", psz );
|
|
FREE_FILE( pfile );
|
|
|
|
*piCount = iSprCount;
|
|
return phud;
|
|
}
|
|
|
|
void SPR_Set( HSPRITE hPic, int r, int g, int b )
|
|
{
|
|
ds.hSprite = hPic;
|
|
SetColor( r, g, b, 255 );
|
|
}
|
|
|
|
void SPR_Set( HSPRITE hPic, int r, int g, int b, int a )
|
|
{
|
|
ds.hSprite = hPic;
|
|
SetColor( r, g, b, a );
|
|
}
|
|
|
|
inline static void SPR_AdjustSize( float *x, float *y, float *w, float *h )
|
|
{
|
|
if( !x && !y && !w && !h ) return;
|
|
|
|
// scale for screen sizes
|
|
float xscale = gHUD.m_scrinfo.iRealWidth / (float)gHUD.m_scrinfo.iWidth;
|
|
float yscale = gHUD.m_scrinfo.iRealHeight / (float)gHUD.m_scrinfo.iHeight;
|
|
|
|
if( x ) *x *= xscale;
|
|
if( y ) *y *= yscale;
|
|
if( w ) *w *= xscale;
|
|
if( h ) *h *= yscale;
|
|
}
|
|
|
|
inline static void SPR_DrawChar( HSPRITE hFont, int xpos, int ypos, int width, int height, int ch )
|
|
{
|
|
float size, frow, fcol;
|
|
float ax, ay, aw, ah;
|
|
int fontWidth, fontHeight;
|
|
|
|
ch &= 255;
|
|
|
|
if( ch == ' ' ) return;
|
|
if( ypos < -height ) return;
|
|
|
|
ax = xpos;
|
|
ay = ypos;
|
|
aw = width;
|
|
ah = height;
|
|
|
|
SPR_AdjustSize( &ax, &ay, &aw, &ah );
|
|
GetParms( &fontWidth, &fontHeight, NULL, 0, hFont );
|
|
|
|
frow = (ch >> 4) * 0.0625f + (0.5f / (float)fontWidth);
|
|
fcol = (ch & 15) * 0.0625f + (0.5f / (float)fontHeight);
|
|
size = 0.0625f - (1.0f / (float)fontWidth);
|
|
|
|
DrawImageExt( hFont, ax, ay, aw, ah, fcol, frow, fcol + size, frow + size );
|
|
}
|
|
|
|
inline static void SPR_DrawGeneric( int frame, float x, float y, float width, float height, const wrect_t *prc )
|
|
{
|
|
float s1, s2, t1, t2;
|
|
|
|
if( width == -1 && height == -1 )
|
|
{
|
|
int w, h;
|
|
GetParms( &w, &h, NULL, frame, ds.hSprite );
|
|
width = w;
|
|
height = h;
|
|
}
|
|
|
|
if( prc )
|
|
{
|
|
// calc rectangle
|
|
s1 = (float)prc->left / width;
|
|
t1 = (float)prc->top / height;
|
|
s2 = (float)prc->right / width;
|
|
t2 = (float)prc->bottom / height;
|
|
width = prc->right - prc->left;
|
|
height = prc->bottom - prc->top;
|
|
}
|
|
else
|
|
{
|
|
s1 = t1 = 0.0f;
|
|
s2 = t2 = 1.0f;
|
|
}
|
|
|
|
// scale for screen sizes
|
|
SPR_AdjustSize( &x, &y, &width, &height );
|
|
DrawImageExt( ds.hSprite, x, y, width, height, s1, t1, s2, t2 );
|
|
}
|
|
|
|
void TextMessageDrawChar( int xpos, int ypos, int number, int r, int g, int b )
|
|
{
|
|
// tune char size by taste
|
|
SetColor( r, g, b, 255 );
|
|
SPR_DrawChar( gHUD.m_hHudFont, xpos, ypos, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, number );
|
|
}
|
|
|
|
void FillRGBA( float x, float y, float width, float height, int r, int g, int b, int a )
|
|
{
|
|
SPR_AdjustSize( &x, &y, &width, &height );
|
|
g_engfuncs.pfnFillRGBA( x, y, width, height, r, g, b, a );
|
|
}
|
|
|
|
void SPR_Draw( int frame, int x, int y, const wrect_t *prc )
|
|
{
|
|
SetParms( ds.hSprite, kRenderNormal, frame );
|
|
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
|
|
}
|
|
|
|
void SPR_Draw( int frame, int x, int y, int width, int height )
|
|
{
|
|
SetParms( ds.hSprite, kRenderNormal, frame );
|
|
SPR_DrawGeneric( frame, x, y, width, height, NULL );
|
|
}
|
|
|
|
void SPR_DrawTransColor( int frame, int x, int y, const wrect_t *prc )
|
|
{
|
|
SetParms( ds.hSprite, kRenderTransColor, frame );
|
|
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
|
|
}
|
|
|
|
void SPR_DrawTransColor( int frame, int x, int y, int width, int height )
|
|
{
|
|
SetParms( ds.hSprite, kRenderTransColor, frame );
|
|
SPR_DrawGeneric( frame, x, y, width, height, NULL );
|
|
}
|
|
|
|
void SPR_DrawHoles( int frame, int x, int y, const wrect_t *prc )
|
|
{
|
|
SetParms( ds.hSprite, kRenderTransAlpha, frame );
|
|
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
|
|
}
|
|
|
|
void SPR_DrawHoles( int frame, int x, int y, int width, int height )
|
|
{
|
|
SetParms( ds.hSprite, kRenderTransAlpha, frame );
|
|
SPR_DrawGeneric( frame, x, y, width, height, NULL );
|
|
}
|
|
|
|
void SPR_DrawAdditive( int frame, int x, int y, const wrect_t *prc )
|
|
{
|
|
SetParms( ds.hSprite, kRenderTransAdd, frame );
|
|
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
|
|
}
|
|
|
|
void SPR_DrawAdditive( int frame, int x, int y, int width, int height )
|
|
{
|
|
SetParms( ds.hSprite, kRenderTransAdd, frame );
|
|
SPR_DrawGeneric( frame, x, y, width, height, NULL );
|
|
}
|
|
|
|
void SetCrosshair( HSPRITE hspr, wrect_t rc, int r, int g, int b )
|
|
{
|
|
ds.rgbCrosshair[0] = (byte)r;
|
|
ds.rgbCrosshair[1] = (byte)g;
|
|
ds.rgbCrosshair[2] = (byte)b;
|
|
ds.hCrosshair = hspr;
|
|
ds.rcCrosshair = rc;
|
|
}
|
|
|
|
void HideCrosshair( bool hide )
|
|
{
|
|
ds.noCrosshair = hide;
|
|
}
|
|
|
|
void DrawCrosshair( void )
|
|
{
|
|
if( ds.hCrosshair == 0 || ds.noCrosshair || !CVAR_GET_FLOAT( "cl_crosshair" ))
|
|
return;
|
|
|
|
int x = (ScreenWidth - (ds.rcCrosshair.right - ds.rcCrosshair.left)) / 2;
|
|
int y = (ScreenHeight - (ds.rcCrosshair.bottom - ds.rcCrosshair.top)) / 2;
|
|
|
|
// FIXME: apply crosshair angles properly
|
|
x += gHUD.m_CrosshairAngles.x;
|
|
y += gHUD.m_CrosshairAngles.y;
|
|
|
|
ds.hSprite = ds.hCrosshair;
|
|
SetParms( ds.hCrosshair, kRenderTransAlpha, 0 );
|
|
SetColor( ds.rgbCrosshair[0], ds.rgbCrosshair[1], ds.rgbCrosshair[2], 255 );
|
|
SPR_DrawGeneric( 0, x, y, -1, -1, &ds.rcCrosshair );
|
|
}
|
|
|
|
void DrawPause( void )
|
|
{
|
|
// pause image
|
|
if( !v_paused ) return;
|
|
DrawImageBar( 100, "m_pause" ); // HACKHACK
|
|
}
|
|
|
|
void DrawImageRectangle( HSPRITE hImage )
|
|
{
|
|
DrawImageExt( hImage, 0, 0, ActualWidth, ActualHeight, 0, 0, 1, 1 );
|
|
}
|
|
|
|
void DrawImageBar( float percent, const char *szSpriteName )
|
|
{
|
|
int m_loading = gHUD.GetSpriteIndex( szSpriteName );
|
|
wrect_t rcSize = gHUD.GetSpriteRect( m_loading );
|
|
|
|
int w = rcSize.right - rcSize.left;
|
|
int h = rcSize.bottom - rcSize.top;
|
|
DrawImageBar( percent, szSpriteName, (ScreenWidth - w)/2, (ScreenHeight - h)/2 );
|
|
}
|
|
|
|
void DrawImageBar( float percent, const char *szSpriteName, int x, int y )
|
|
{
|
|
int m_loading = gHUD.GetSpriteIndex( szSpriteName );
|
|
HSPRITE hLoading = gHUD.GetSprite( m_loading );
|
|
wrect_t rcBar, rcBack;
|
|
float step;
|
|
|
|
rcBar = rcBack = gHUD.GetSpriteRect( m_loading );
|
|
step = (float)(rcBack.right - rcBack.left) / 100;
|
|
rcBar.right = rcBar.left + (int)ceil(percent * step);
|
|
|
|
SPR_Set( hLoading, 128, 128, 128 );
|
|
SPR_DrawAdditive( 0, x, y, &rcBack ); // background
|
|
|
|
SPR_Set( hLoading, 255, 160, 0 );
|
|
SPR_DrawAdditive( 0, x, y, &rcBar ); // progress bar
|
|
}
|
|
|
|
//
|
|
// 27/12/08 moved here from cl_view.c
|
|
//
|
|
void DrawProgressBar( void )
|
|
{
|
|
if( !gHUD.m_iDrawPlaque ) return;
|
|
DrawImageBar( CVAR_GET_FLOAT( "scr_loading" ), "m_loading" );
|
|
|
|
if( !CVAR_GET_FLOAT( "scr_download" )) return;
|
|
DrawImageBar( CVAR_GET_FLOAT( "scr_download" ), "m_download", (ScreenWidth-128)/2, ScreenHeight-60 );
|
|
}
|
|
|
|
//
|
|
// hl2 fade - this supports multiple fading
|
|
// FIXME: make Class CHudFade instead of C-style code?
|
|
//
|
|
void SetScreenFade( Vector fadeColor, float alpha, float duration, float holdTime, int fadeFlags )
|
|
{
|
|
ScreenFade *sf = NULL;
|
|
|
|
for( int i = 0; i < HUD_MAX_FADES; i++ )
|
|
{
|
|
// search for free spot
|
|
if( gHUD.m_FadeList[i].fadeFlags == 0 )
|
|
{
|
|
sf = &gHUD.m_FadeList[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !sf ) return; // no free fades found
|
|
|
|
sf->fadeEnd = duration;
|
|
sf->fadeReset = holdTime;
|
|
sf->fadeColor = fadeColor;
|
|
sf->fadeAlpha = alpha;
|
|
sf->fadeFlags = fadeFlags;
|
|
sf->fadeSpeed = 0;
|
|
|
|
// calc fade speed
|
|
if( duration > 0 )
|
|
{
|
|
if( fadeFlags & FFADE_OUT )
|
|
{
|
|
if( sf->fadeEnd )
|
|
{
|
|
sf->fadeSpeed = -(float)sf->fadeAlpha / sf->fadeEnd;
|
|
}
|
|
|
|
sf->fadeEnd += gHUD.m_flTime;
|
|
sf->fadeReset += sf->fadeEnd;
|
|
}
|
|
else
|
|
{
|
|
if( sf->fadeEnd )
|
|
{
|
|
sf->fadeSpeed = (float)sf->fadeAlpha / sf->fadeEnd;
|
|
}
|
|
|
|
sf->fadeReset += gHUD.m_flTime;
|
|
sf->fadeEnd += sf->fadeReset;
|
|
}
|
|
}
|
|
|
|
if( fadeFlags & FFADE_PURGE )
|
|
{
|
|
ClearAllFades();
|
|
}
|
|
}
|
|
|
|
void DrawScreenFade( void )
|
|
{
|
|
int i, numFades = 0;
|
|
|
|
// Cycle through all fades and remove any that have finished (work backwards)
|
|
for( i = HUD_MAX_FADES - 1; i >= 0; i-- )
|
|
{
|
|
ScreenFade *pFade = &gHUD.m_FadeList[i];
|
|
|
|
if( pFade->fadeFlags == 0 ) continue; // free slot
|
|
|
|
// Keep pushing reset time out indefinitely
|
|
if( pFade->fadeFlags & FFADE_STAYOUT )
|
|
{
|
|
pFade->fadeReset = gHUD.m_flTime + 0.1f;
|
|
}
|
|
|
|
// All done?
|
|
if(( gHUD.m_flTime > pFade->fadeReset ) && ( gHUD.m_flTime > pFade->fadeEnd ))
|
|
{
|
|
// remove this Fade from the list
|
|
memset( pFade, 0, sizeof( ScreenFade ));
|
|
}
|
|
}
|
|
|
|
gHUD.m_bModulate = false;
|
|
gHUD.m_vFadeColor = Vector( 0, 0, 0 );
|
|
gHUD.m_fFadeAlpha = 0.0f;
|
|
|
|
// Cycle through all fades in the list and calculate the overall color/alpha
|
|
for ( i = 0; i < HUD_MAX_FADES; i++ )
|
|
{
|
|
ScreenFade *pFade = &gHUD.m_FadeList[i];
|
|
|
|
if( pFade->fadeFlags == 0 ) continue; // free slot
|
|
|
|
// Color
|
|
gHUD.m_vFadeColor += pFade->fadeColor;
|
|
|
|
// Fading...
|
|
int iFadeAlpha;
|
|
if( pFade->fadeFlags & ( FFADE_OUT|FFADE_IN ))
|
|
{
|
|
iFadeAlpha = pFade->fadeSpeed * ( pFade->fadeEnd - gHUD.m_flTime );
|
|
if( pFade->fadeFlags & FFADE_OUT )
|
|
{
|
|
iFadeAlpha += pFade->fadeAlpha;
|
|
}
|
|
iFadeAlpha = min( iFadeAlpha, pFade->fadeAlpha );
|
|
iFadeAlpha = max( 0, iFadeAlpha );
|
|
}
|
|
else
|
|
{
|
|
iFadeAlpha = pFade->fadeAlpha;
|
|
}
|
|
|
|
// Use highest alpha
|
|
if( iFadeAlpha > gHUD.m_fFadeAlpha )
|
|
{
|
|
gHUD.m_fFadeAlpha = iFadeAlpha;
|
|
}
|
|
|
|
// Modulate?
|
|
if( pFade->fadeFlags & FFADE_MODULATE )
|
|
{
|
|
gHUD.m_bModulate = true;
|
|
}
|
|
numFades++;
|
|
}
|
|
|
|
// Divide colors
|
|
if( numFades ) gHUD.m_vFadeColor /= numFades;
|
|
|
|
if( gHUD.m_vFadeColor == Vector( 0, 0, 0 )) return;
|
|
const float *RGB = gHUD.m_vFadeColor;
|
|
|
|
FillRGBA( 0, 0, ScreenWidth, ScreenHeight, RGB[0], RGB[1], RGB[2], gHUD.m_fFadeAlpha );
|
|
}
|
|
|
|
void ClearPermanentFades( void )
|
|
{
|
|
for( int i = HUD_MAX_FADES - 1; i >= 0; i-- )
|
|
{
|
|
ScreenFade *pFade = &gHUD.m_FadeList[i];
|
|
if( pFade->fadeFlags == 0 ) continue; // free slot
|
|
|
|
if( pFade->fadeFlags & FFADE_STAYOUT )
|
|
{
|
|
// remove this Fade from the list
|
|
memset( pFade, 0, sizeof( ScreenFade ));
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClearAllFades( void )
|
|
{
|
|
memset( gHUD.m_FadeList, 0, sizeof( gHUD.m_FadeList ));
|
|
}
|
|
|
|
/*
|
|
====================
|
|
Sys LoadGameDLL
|
|
|
|
====================
|
|
*/
|
|
BOOL Sys_LoadLibrary( const char* dllname, dllhandle_t* handle, const dllfunction_t *fcts )
|
|
{
|
|
const dllfunction_t *gamefunc;
|
|
dllhandle_t dllhandle = 0;
|
|
|
|
if( handle == NULL ) return false;
|
|
|
|
// Initializations
|
|
for( gamefunc = fcts; gamefunc && gamefunc->name != NULL; gamefunc++ )
|
|
*gamefunc->funcvariable = NULL;
|
|
|
|
dllhandle = (dllhandle_t)LOAD_LIBRARY( dllname );
|
|
|
|
// No DLL found
|
|
if( !dllhandle ) return false;
|
|
|
|
// Get the function adresses
|
|
for( gamefunc = fcts; gamefunc && gamefunc->name != NULL; gamefunc++ )
|
|
{
|
|
if(!( *gamefunc->funcvariable = (void *) Sys_GetProcAddress( dllhandle, gamefunc->name )))
|
|
{
|
|
Sys_UnloadLibrary( &dllhandle );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ALERT( at_loading, "%s loaded succesfully!\n", dllname );
|
|
*handle = dllhandle;
|
|
return true;
|
|
}
|
|
|
|
void Sys_UnloadLibrary( dllhandle_t *handle )
|
|
{
|
|
if( handle == NULL || *handle == NULL )
|
|
return;
|
|
|
|
FREE_LIBRARY( *handle );
|
|
*handle = NULL;
|
|
}
|
|
|
|
void* Sys_GetProcAddress( dllhandle_t handle, const char* name )
|
|
{
|
|
return (void *)GET_PROC_ADDRESS( handle, name );
|
|
}
|
|
|
|
/*
|
|
============
|
|
va
|
|
|
|
does a varargs printf into a temp buffer, so I don't need to have
|
|
varargs versions of all text functions.
|
|
FIXME: make this buffer size safe someday
|
|
============
|
|
*/
|
|
char *va( const char *format, ... )
|
|
{
|
|
va_list argptr;
|
|
static char string[32][1024], *s;
|
|
static int stringindex = 0;
|
|
|
|
s = string[stringindex];
|
|
stringindex = (stringindex + 1) & 31;
|
|
va_start( argptr, format );
|
|
_vsnprintf( s, sizeof( string[0] ), format, argptr );
|
|
va_end( argptr );
|
|
return s;
|
|
}
|
|
|
|
/*
|
|
==============
|
|
COM_ParseToken
|
|
|
|
Parse a token out of a string
|
|
==============
|
|
*/
|
|
char *COM_ParseToken( const char **data_p )
|
|
{
|
|
int c;
|
|
int len = 0;
|
|
const char *data;
|
|
static char token[512];
|
|
|
|
token[0] = 0;
|
|
data = *data_p;
|
|
|
|
if( !data )
|
|
{
|
|
*data_p = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
// skip whitespace
|
|
skipwhite:
|
|
while(( c = *data) <= ' ' )
|
|
{
|
|
if( c == 0 )
|
|
{
|
|
*data_p = NULL;
|
|
return NULL; // end of file;
|
|
}
|
|
data++;
|
|
}
|
|
|
|
// skip // comments
|
|
if( c=='/' && data[1] == '/' )
|
|
{
|
|
while( *data && *data != '\n' )
|
|
data++;
|
|
goto skipwhite;
|
|
}
|
|
|
|
// skip /* comments
|
|
if( c=='/' && data[1] == '*' )
|
|
{
|
|
while( data[1] && (data[0] != '*' || data[1] != '/' ))
|
|
data++;
|
|
data += 2;
|
|
goto skipwhite;
|
|
}
|
|
|
|
|
|
// handle quoted strings specially
|
|
if( *data == '\"' || *data == '\'' )
|
|
{
|
|
data++;
|
|
while( 1 )
|
|
{
|
|
c = *data++;
|
|
if( c=='\"' || c=='\0' )
|
|
{
|
|
token[len] = 0;
|
|
*data_p = data;
|
|
return token;
|
|
}
|
|
token[len] = c;
|
|
len++;
|
|
}
|
|
}
|
|
|
|
// parse single characters
|
|
if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' || c == ',' )
|
|
{
|
|
token[len] = c;
|
|
data++;
|
|
len++;
|
|
token[len] = 0;
|
|
*data_p = data;
|
|
return token;
|
|
}
|
|
|
|
// parse a regular word
|
|
do
|
|
{
|
|
token[len] = c;
|
|
data++;
|
|
len++;
|
|
c = *data;
|
|
if( c == '{' || c == '}'|| c == ')'|| c == '(' || c == '\'' || c == ':' || c == ',' )
|
|
break;
|
|
} while( c > 32 );
|
|
|
|
token[len] = 0;
|
|
*data_p = data;
|
|
return token;
|
|
} |