This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/client/hud/hud.cpp

452 lines
10 KiB
C++

//=======================================================================
// Copyright (C) XashXT Group 2007
//=======================================================================
#include "extdll.h"
#include "utils.h"
#include "hud.h"
#include "triangle_api.h"
#define MAX_LOGO_FRAMES 56
int grgLogoFrame[MAX_LOGO_FRAMES] =
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 14, 15,
16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 30, 31
};
void CHud :: Init( void )
{
InitMessages();
m_Ammo.Init();
m_Health.Init();
m_SayText.Init();
m_Geiger.Init();
m_Train.Init();
m_Battery.Init();
m_Flash.Init();
m_Message.Init();
m_Scoreboard.Init();
m_StatusBar.Init();
m_DeathNotice.Init();
m_AmmoSecondary.Init();
m_TextMessage.Init();
m_StatusIcons.Init();
m_Menu.Init();
m_MOTD.Init();
MsgFunc_ResetHUD( 0, 0, NULL );
}
CHud :: ~CHud( void )
{
delete [] m_rghSprites;
delete [] m_rgrcRects;
delete [] m_rgszSpriteNames;
if( m_pHudList )
{
HUDLIST *pList;
while( m_pHudList )
{
pList = m_pHudList;
m_pHudList = m_pHudList->pNext;
FREE( pList );
}
m_pHudList = NULL;
}
}
int CHud :: GetSpriteIndex( const char *SpriteName )
{
// look through the loaded sprite name list for SpriteName
for( int i = 0; i < m_iSpriteCount; i++ )
{
if(!strncmp( SpriteName, m_rgszSpriteNames + (i * MAX_SPRITE_NAME_LENGTH), MAX_SPRITE_NAME_LENGTH ))
return i;
}
return -1; // invalid sprite
}
void CHud :: VidInit( void )
{
// ----------
// Load Sprites
// ---------
m_hsprLogo = 0;
m_hsprCursor = 0;
m_hHudError = 0;
spot = NULL; // clear intermission spot
ClearAllFades ();
if( CVAR_GET_FLOAT( "hud_scale" ))
m_scrinfo.iFlags = SCRINFO_VIRTUALSPACE;
else m_scrinfo.iFlags = 0;
// setup screen info
GetScreenInfo( &m_scrinfo );
if( ActualWidth < 640 )
m_iRes = 320;
else m_iRes = 640;
// Only load this once
if ( !m_pSpriteList )
{
// we need to load the hud.txt, and all sprites within
m_pSpriteList = SPR_GetList( "sprites/hud.txt", &m_iSpriteCountAllRes );
if( m_pSpriteList )
{
// count the number of sprites of the appropriate res
m_iSpriteCount = 0;
client_sprite_t *p = m_pSpriteList;
for ( int j = 0; j < m_iSpriteCountAllRes; j++ )
{
if ( p->iRes == m_iRes )
m_iSpriteCount++;
p++;
}
// allocated memory for sprite handle arrays
m_rghSprites = new HSPRITE[m_iSpriteCount];
m_rgrcRects = new wrect_t[m_iSpriteCount];
m_rgszSpriteNames = new char[m_iSpriteCount * MAX_SPRITE_NAME_LENGTH];
p = m_pSpriteList;
int index = 0;
for ( j = 0; j < m_iSpriteCountAllRes; j++ )
{
if ( p->iRes == m_iRes )
{
char sz[256];
sprintf(sz, "sprites/%s.spr", p->szSprite);
m_rghSprites[index] = SPR_Load(sz);
m_rgrcRects[index] = p->rc;
strncpy( &m_rgszSpriteNames[index * MAX_SPRITE_NAME_LENGTH], p->szName, MAX_SPRITE_NAME_LENGTH );
index++;
}
p++;
}
}
else
{
Con_Printf( "Warning: hud.txt couldn't load\n" );
CVAR_SET_FLOAT( "hud_draw", 0 );
return;
}
}
else
{
// we have already have loaded the sprite reference from hud.txt, but
// we need to make sure all the sprites have been loaded (we've gone through a transition, or loaded a save game)
client_sprite_t *p = m_pSpriteList;
int index = 0;
for ( int j = 0; j < m_iSpriteCountAllRes; j++ )
{
if ( p->iRes == m_iRes )
{
char sz[256];
sprintf( sz, "sprites/%s.spr", p->szSprite );
m_rghSprites[index] = SPR_Load(sz);
index++;
}
p++;
}
}
// assumption: number_1, number_2, etc, are all listed and loaded sequentially
m_HUD_number_0 = GetSpriteIndex( "number_0" );
m_iFontHeight = GetSpriteRect( m_HUD_number_0 ).bottom - GetSpriteRect( m_HUD_number_0 ).top;
// loading error sprite
m_HUD_error = GetSpriteIndex( "error" );
m_hHudError = GetSprite( m_HUD_error );
m_Ammo.VidInit();
m_Health.VidInit();
m_Geiger.VidInit();
m_Train.VidInit();
m_Battery.VidInit();
m_Flash.VidInit();
m_MOTD.VidInit();
m_Message.VidInit();
m_Scoreboard.VidInit();
m_StatusBar.VidInit();
m_DeathNotice.VidInit();
m_SayText.VidInit();
m_Menu.VidInit();
m_AmmoSecondary.VidInit();
m_TextMessage.VidInit();
m_StatusIcons.VidInit();
}
void CHud :: Think( void )
{
HUDLIST *pList = m_pHudList;
while( pList )
{
if (pList->p->m_iFlags & HUD_ACTIVE)
pList->p->Think();
pList = pList->pNext;
}
// think about default fov
float def_fov = CVAR_GET_FLOAT( "default_fov" );
if( m_flFOV == 0.0f ) m_flFOV = max( CVAR_GET_FLOAT( "default_fov" ), 90 );
// change sensitivity
if( m_flFOV == def_fov )
{
m_flMouseSensitivity = 0;
}
else
{
// set a new sensitivity that is proportional to the change from the FOV default
m_flMouseSensitivity = CVAR_GET_FLOAT( "sensitivity" ) * ( m_flFOV / def_fov );
m_flMouseSensitivity *= CVAR_GET_FLOAT( "zoom_sensitivity_ratio" ); // apply zoom factor
}
}
int CHud :: UpdateClientData( client_data_t *cdata, float time )
{
cl_entity_t *pClient = GetLocalPlayer ();
memcpy( m_vecOrigin, cdata->origin, sizeof( vec3_t ));
memcpy( m_vecAngles, cdata->viewangles, sizeof( vec3_t ));
if( pClient )
{
// TEMPORARY HACK
m_iNoClip = (pClient->curstate.movetype == MOVETYPE_NOCLIP) ? 1 : 0;
}
m_iKeyBits = CL_ButtonBits( 0 );
m_iWeaponBits = cdata->iWeaponBits;
// in_fov = cdata->fov;
Think();
// cdata->fov = m_iFOV;
v_idlescale = m_iConcussionEffect;
CL_ResetButtonBits( m_iKeyBits );
return 1;
}
int CHud :: Redraw( float flTime )
{
m_fOldTime = m_flTime; // save time of previous redraw
m_flTime = flTime;
m_flTimeDelta = (double)m_flTime - m_fOldTime;
static float m_flShotTime;
// clock was reset, reset delta
if( m_flTimeDelta < 0 ) m_flTimeDelta = 0;
// draw screen fade before hud
DrawScreenFade();
// take a screenshot if the client's got the cvar set
if( m_flShotTime && m_flShotTime < flTime )
{
CLIENT_COMMAND( "screenshot\n" );
m_flShotTime = 0;
}
if( CVAR_GET_FLOAT( "hud_draw" ))
{
HUDLIST *pList = m_pHudList;
while( pList )
{
if( !m_iIntermission )
{
if(( pList->p->m_iFlags & HUD_ACTIVE ) && !(m_iHideHUDDisplay & HIDEHUD_ALL ))
pList->p->Draw( flTime );
}
else
{
// it's an intermission, so only draw hud elements
// that are set to draw during intermissions
if( pList->p->m_iFlags & HUD_INTERMISSION )
pList->p->Draw( flTime );
}
pList = pList->pNext;
}
}
// are we in demo mode? do we need to draw the logo in the top corner?
if (m_iLogo)
{
int x, y, i;
if (m_hsprLogo == 0)
m_hsprLogo = LoadSprite("sprites/%d_logo.spr");
SPR_Set(m_hsprLogo, 250, 250, 250 );
x = SPR_Width(m_hsprLogo, 0);
x = ScreenWidth - x;
y = SPR_Height(m_hsprLogo, 0)/2;
// Draw the logo at 20 fps
int iFrame = (int)(flTime * 20) % MAX_LOGO_FRAMES;
i = grgLogoFrame[iFrame] - 1;
SPR_DrawAdditive(i, x, y, NULL);
}
return 1;
}
int CHud :: DrawHudString( int xpos, int ypos, int iMaxX, char *szIt, int r, int g, int b )
{
// draw the string until we hit the null character or a newline character
for( ; *szIt != 0 && *szIt != '\n'; szIt++ )
{
int next = xpos + gHUD.m_scrinfo.charWidths[*szIt]; // variable-width fonts look cool
if ( next > iMaxX )
return xpos;
TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
xpos = next;
}
return xpos;
}
int CHud :: DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b )
{
char szString[32];
sprintf( szString, "%d", iNumber );
return DrawHudStringReverse( xpos, ypos, iMinX, szString, r, g, b );
}
int CHud :: DrawHudStringReverse( int xpos, int ypos, int iMinX, char *szString, int r, int g, int b )
{
// find the end of the string
for ( char *szIt = szString; *szIt != 0; szIt++ )
{ // we should count the length?
}
// iterate throug the string in reverse
for( szIt--; szIt != (szString-1); szIt-- )
{
int next = xpos - gHUD.m_scrinfo.charWidths[ *szIt ]; // variable-width fonts look cool
if( next < iMinX )
return xpos;
xpos = next;
TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
}
return xpos;
}
int CHud :: DrawHudNumber( int x, int y, int iFlags, int iNumber, int r, int g, int b )
{
int iWidth = GetSpriteRect( m_HUD_number_0 ).right - GetSpriteRect( m_HUD_number_0 ).left;
int k;
if( iNumber > 0 )
{
// SPR_Draw 100's
if( iNumber >= 100 )
{
k = iNumber / 100;
SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
x += iWidth;
}
else if( iFlags & DHN_3DIGITS )
{
x += iWidth;
}
// SPR_Draw 10's
if( iNumber >= 10 )
{
k = (iNumber % 100)/10;
SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
x += iWidth;
}
else if( iFlags & (DHN_3DIGITS|DHN_2DIGITS))
{
x += iWidth;
}
// SPR_Draw ones
k = iNumber % 10;
SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
x += iWidth;
}
else if( iFlags & DHN_DRAWZERO )
{
SPR_Set(GetSprite(m_HUD_number_0), r, g, b );
// SPR_Draw 100's
if( iFlags & DHN_3DIGITS )
{
x += iWidth;
}
if( iFlags & (DHN_3DIGITS|DHN_2DIGITS)) x += iWidth;
SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0));
x += iWidth;
}
return x;
}
int CHud::GetNumWidth( int iNumber, int iFlags )
{
if( iFlags & (DHN_3DIGITS)) return 3;
if( iFlags & (DHN_2DIGITS)) return 2;
if( iNumber <= 0 )
{
if( iFlags & (DHN_DRAWZERO))
return 1;
else return 0;
}
if( iNumber < 10 ) return 1;
if( iNumber < 100 ) return 2;
return 3;
}
void CHud::AddHudElem( CHudBase *phudelem )
{
HUDLIST *pdl, *ptemp;
if( !phudelem ) return;
pdl = (HUDLIST *)CALLOC( sizeof( HUDLIST ), 1 );
pdl->p = phudelem;
if( !m_pHudList )
{
m_pHudList = pdl;
return;
}
ptemp = m_pHudList;
while( ptemp->pNext )
ptemp = ptemp->pNext;
ptemp->pNext = pdl;
}