forked from a1batross/Paranoia2_original
521 lines
13 KiB
C++
521 lines
13 KiB
C++
/***
|
||
*
|
||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||
*
|
||
* This product contains software technology licensed from Id
|
||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||
* All Rights Reserved.
|
||
*
|
||
* Use, distribution, and modification of this source code and/or resulting
|
||
* object code is restricted to non-commercial enhancements to products from
|
||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||
* without written permission from Valve LLC.
|
||
*
|
||
****/
|
||
//
|
||
// hud_redraw.cpp
|
||
//
|
||
#include <math.h>
|
||
#include "hud.h"
|
||
#include "cl_util.h"
|
||
#include "vgui_TeamFortressViewport.h"
|
||
#include "vgui_hud.h"
|
||
#include "triangleapi.h"
|
||
|
||
#ifndef M_PI
|
||
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
||
#endif
|
||
|
||
// buz: for IsHardware check
|
||
#include "r_studioint.h"
|
||
#include "com_model.h"
|
||
extern engine_studio_api_t IEngineStudio;
|
||
|
||
#include "vgui_TeamFortressViewport.h"
|
||
#include "vgui_paranoiatext.h"// buz
|
||
#include "gl_local.h"
|
||
#include "gl_decals.h"
|
||
|
||
#define MAX_LOGO_FRAMES 56
|
||
|
||
// buz: spread value
|
||
vec3_t g_vSpread;
|
||
int g_iGunMode = 0;
|
||
|
||
void DrawBlurTest(float frametime); // buz
|
||
extern int g_iVisibleMouse;
|
||
|
||
//float HUD_GetFOV( void ); buz
|
||
|
||
extern cvar_t *sensitivity;
|
||
|
||
// Think
|
||
void CHud::Think(void)
|
||
{
|
||
// buz: calc dead time
|
||
if (gHUD.m_Health.m_iHealth <= 0 && !m_flDeadTime)
|
||
{
|
||
m_flDeadTime = gEngfuncs.GetClientTime();
|
||
}
|
||
|
||
// Wargon: Исправление бага эффекта grayscale, остававшегося после загрузки из мертвого состояния.
|
||
if (gHUD.m_Health.m_iHealth > 0)
|
||
{
|
||
m_flDeadTime = 0;
|
||
}
|
||
|
||
float targetFOV;
|
||
HUDLIST *pList = m_pHudList;
|
||
static float lasttime = 0;
|
||
|
||
while (pList)
|
||
{
|
||
if (pList->p->m_iFlags & HUD_ACTIVE)
|
||
pList->p->Think();
|
||
pList = pList->pNext;
|
||
}
|
||
|
||
if( g_iGunMode == 3 )
|
||
targetFOV = 30;
|
||
else if( g_iGunMode == 2 )
|
||
targetFOV = 60;
|
||
else targetFOV = default_fov->value;
|
||
|
||
static float lastFixedFov = 0;
|
||
|
||
if( m_flFOV < 0 )
|
||
{
|
||
m_flFOV = targetFOV;
|
||
lasttime = gEngfuncs.GetClientTime();
|
||
lastFixedFov = m_flFOV;
|
||
}
|
||
else
|
||
{
|
||
float curtime = gEngfuncs.GetClientTime();
|
||
float mod = targetFOV - m_flFOV;
|
||
if( mod < 0 ) mod *= -1;
|
||
if( mod < 30 ) mod = 30;
|
||
|
||
if( g_iGunMode == 3 || lastFixedFov == 30 )
|
||
mod *= 2; // хаками халфа полнится (c)
|
||
mod /= 30;
|
||
|
||
if( m_flFOV < targetFOV )
|
||
{
|
||
m_flFOV += (curtime - lasttime) * m_pZoomSpeed->value * mod;
|
||
if( m_flFOV > targetFOV )
|
||
{
|
||
m_flFOV = targetFOV;
|
||
lastFixedFov = m_flFOV;
|
||
}
|
||
}
|
||
else if( m_flFOV > targetFOV )
|
||
{
|
||
m_flFOV -= (curtime - lasttime) * m_pZoomSpeed->value * mod;
|
||
|
||
if( m_flFOV < targetFOV )
|
||
{
|
||
m_flFOV = targetFOV;
|
||
lastFixedFov = m_flFOV;
|
||
}
|
||
}
|
||
lasttime = curtime;
|
||
}
|
||
|
||
m_iFOV = m_flFOV;
|
||
|
||
// Set a new sensitivity
|
||
if ( m_iFOV == default_fov->value )// buz: turn off
|
||
{
|
||
// reset to saved sensitivity
|
||
m_flMouseSensitivity = 0;
|
||
}
|
||
else
|
||
{
|
||
// set a new sensitivity that is proportional to the change from the FOV default
|
||
m_flMouseSensitivity = sensitivity->value * (m_flFOV / (float)90) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
|
||
}
|
||
}
|
||
|
||
//LRC - fog fading values
|
||
extern float g_fFadeDuration;
|
||
extern float g_fStartDist;
|
||
extern float g_fEndDist;
|
||
//extern int g_iFinalStartDist;
|
||
extern int g_iFinalEndDist;
|
||
|
||
void OrthoScope(void); // buz
|
||
void OrthoVGUI(void); // buz
|
||
extern vec3_t g_CrosshairAngle; // buz
|
||
|
||
#define CROSS_LENGTH 18.0f
|
||
|
||
// Redraw
|
||
// step through the local data, placing the appropriate graphics & text as appropriate
|
||
// returns 1 if they've changed, 0 otherwise
|
||
int CHud :: Redraw( float flTime, int intermission )
|
||
{
|
||
m_fOldTime = m_flTime; // save time of previous redraw
|
||
m_flTime = flTime;
|
||
m_flTimeDelta = (double)m_flTime - m_fOldTime;
|
||
static m_flShotTime = 0;
|
||
|
||
#if 0
|
||
// g-cont. disabled for users request
|
||
if( g_fRenderInitialized )
|
||
DrawBlurTest( m_flTimeDelta );
|
||
#endif
|
||
//LRC - handle fog fading effects. (is this the right place for it?)
|
||
if (g_fFadeDuration)
|
||
{
|
||
// Nicer might be to use some kind of logarithmic fade-in?
|
||
double fFraction = m_flTimeDelta/g_fFadeDuration;
|
||
// g_fStartDist -= (FOG_LIMIT - g_iFinalStartDist)*fFraction;
|
||
g_fEndDist -= (FOG_LIMIT - g_iFinalEndDist)*fFraction;
|
||
|
||
// CONPRINT("FogFading: %f - %f, frac %f, time %f, final %d\n", g_fStartDist, g_fEndDist, fFraction, flTime, g_iFinalEndDist);
|
||
|
||
// cap it
|
||
// if (g_fStartDist > FOG_LIMIT) g_fStartDist = FOG_LIMIT;
|
||
if (g_fEndDist > FOG_LIMIT) g_fEndDist = FOG_LIMIT;
|
||
// if (g_fStartDist < g_iFinalStartDist) g_fStartDist = g_iFinalStartDist;
|
||
if (g_fEndDist < g_iFinalEndDist) g_fEndDist = g_iFinalEndDist;
|
||
}
|
||
|
||
// Clock was reset, reset delta
|
||
if ( m_flTimeDelta < 0 )
|
||
m_flTimeDelta = 0;
|
||
|
||
if (g_iGunMode == 3) // buz: special sniper scope
|
||
{
|
||
if (IEngineStudio.IsHardware())
|
||
OrthoScope();
|
||
}
|
||
|
||
if (!IEngineStudio.IsHardware() && m_iHeadShieldState != 1 )
|
||
DrawHudString(XRES(10), YRES(350), XRES(600), "Using Head Shield", 180, 180, 180);
|
||
|
||
if( r_stats.debug_surface != NULL )
|
||
gEngfuncs.pfnDrawCharacter( XRES( 320 ), YRES( 240 ), '+', 128, 255, 92 );
|
||
|
||
OrthoVGUI(); // buz: panels background
|
||
|
||
// Bring up the scoreboard during intermission
|
||
if (gViewPort)
|
||
{
|
||
if ( m_iIntermission && !intermission )
|
||
{
|
||
// Have to do this here so the scoreboard goes away
|
||
m_iIntermission = intermission;
|
||
gViewPort->HideCommandMenu();
|
||
gViewPort->HideScoreBoard();
|
||
// gViewPort->UpdateSpectatorPanel();
|
||
}
|
||
else if ( !m_iIntermission && intermission )
|
||
{
|
||
m_iIntermission = intermission;
|
||
gViewPort->HideCommandMenu();
|
||
gViewPort->HideVGUIMenu();
|
||
gViewPort->ShowScoreBoard();
|
||
// gViewPort->UpdateSpectatorPanel();
|
||
|
||
// Take a screenshot if the client's got the cvar set
|
||
if ( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 )
|
||
m_flShotTime = flTime + 1.0; // Take a screenshot in a second
|
||
}
|
||
}
|
||
|
||
if (m_flShotTime && m_flShotTime < flTime)
|
||
{
|
||
gEngfuncs.pfnClientCmd("snapshot\n");
|
||
m_flShotTime = 0;
|
||
}
|
||
|
||
m_iIntermission = intermission;
|
||
|
||
// if no redrawing is necessary
|
||
// return 0;
|
||
|
||
if ( m_pCvarDraw->value )
|
||
{
|
||
HUDLIST *pList = m_pHudList;
|
||
|
||
while (pList)
|
||
{
|
||
if ( !intermission )
|
||
{
|
||
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;
|
||
}
|
||
}
|
||
|
||
// buz: draw crosshair
|
||
// Wargon: Прицел рисуется только если hud_draw = 1.
|
||
if(( g_vSpread[0] && g_iGunMode == 1 && m_SpecTank_on == 0 ) && gHUD.m_pCvarDraw->value && cv_crosshair->value )
|
||
{
|
||
if( gViewPort && gViewPort->m_pParanoiaText && gViewPort->m_pParanoiaText->isVisible( ))
|
||
return 1;
|
||
|
||
int barsize = XRES(g_iGunMode == 1 ? 9 : 6);
|
||
int hW = ScreenWidth / 2;
|
||
int hH = ScreenHeight / 2;
|
||
float mod = (1/(tan(M_PI/180*(m_iFOV/2))));
|
||
int dir = ((g_vSpread[0] * hW) / 500) * mod;
|
||
// gEngfuncs.Con_Printf("mod is %f, %d\n", mod, m_iFOV);
|
||
|
||
if (g_CrosshairAngle[0] != 0 || g_CrosshairAngle[1] != 0)
|
||
{
|
||
// adjust for autoaim
|
||
hW -= g_CrosshairAngle[1] * (ScreenWidth / m_iFOV);
|
||
hH -= g_CrosshairAngle[0] * (ScreenWidth / m_iFOV);
|
||
}
|
||
|
||
// g_vSpread[2] - is redish [0..500]
|
||
// gEngfuncs.Con_Printf("received spread: %f\n", g_vSpread[2]);
|
||
int c = 255 - (g_vSpread[2] * 0.5);
|
||
|
||
if( cv_crosshair->value > 1.0f )
|
||
{
|
||
// old Paranoia-style crosshair
|
||
FillRGBA(hW - dir - barsize, hH, barsize, 1, 255, c, c, 200);
|
||
FillRGBA(hW + dir, hH, barsize, 1, 255, c, c, 200);
|
||
FillRGBA(hW, hH - dir - barsize, 1, barsize, 255, c, c, 200);
|
||
FillRGBA(hW, hH + dir, 1, barsize, 255, c, c, 200);
|
||
}
|
||
else
|
||
{
|
||
// new crysis-style crosshair
|
||
float flColor = 255.0f - (g_vSpread[2] * 0.5f);
|
||
flColor = bound( 0.0f, flColor * (1.0f / 255.0f), 1.0f );
|
||
|
||
GL_TextureTarget( GL_NONE );
|
||
|
||
gEngfuncs.pTriAPI->RenderMode( kRenderTransColor );
|
||
gEngfuncs.pTriAPI->Color4f( 1.0f, flColor, flColor, 0.8f );
|
||
|
||
gEngfuncs.pTriAPI->Begin( TRI_LINES );
|
||
gEngfuncs.pTriAPI->Vertex3f( hW, hH - dir, 0.0f );
|
||
gEngfuncs.pTriAPI->Vertex3f( hW, hH - ( CROSS_LENGTH * 1.2f ) - dir, 0.0f );
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
gEngfuncs.pTriAPI->Begin( TRI_LINES );
|
||
gEngfuncs.pTriAPI->Vertex3f( hW + dir, hH + dir, 0.0f );
|
||
gEngfuncs.pTriAPI->Vertex3f( hW + CROSS_LENGTH + dir, hH + CROSS_LENGTH + dir, 0.0f );
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
gEngfuncs.pTriAPI->Begin( TRI_LINES );
|
||
gEngfuncs.pTriAPI->Vertex3f( hW - dir, hH + dir, 0.0f );
|
||
gEngfuncs.pTriAPI->Vertex3f( hW - CROSS_LENGTH - dir, hH + CROSS_LENGTH + dir, 0.0f );
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
GL_TextureTarget( GL_TEXTURE_2D );
|
||
}
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
void ScaleColors( int &r, int &g, int &b, int a )
|
||
{
|
||
float x = (float)a / 255;
|
||
r = (int)(r * x);
|
||
g = (int)(g * x);
|
||
b = (int)(b * x);
|
||
}
|
||
|
||
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 );
|
||
|
||
}
|
||
|
||
// draws a string from right to left (right-aligned)
|
||
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))
|
||
{
|
||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||
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))
|
||
{
|
||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||
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))
|
||
{
|
||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||
x += iWidth;
|
||
}
|
||
|
||
if (iFlags & (DHN_3DIGITS | DHN_2DIGITS))
|
||
{
|
||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||
x += iWidth;
|
||
}
|
||
|
||
// SPR_Draw ones
|
||
|
||
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;
|
||
|
||
}
|
||
|
||
// buz
|
||
void DrawBlurTest( float frametime )
|
||
{
|
||
static int blurstate = false;
|
||
|
||
if( gHUD.m_flBlurAmount > 0.0f && frametime )
|
||
{
|
||
if( !g_fRenderInitialized )
|
||
{
|
||
ALERT( at_error, "GL effects are not allowed\n" );
|
||
gHUD.m_flBlurAmount = 0.0f;
|
||
return;
|
||
}
|
||
|
||
GLint val_r, val_g, val_b;
|
||
pglGetIntegerv( GL_ACCUM_RED_BITS, &val_r );
|
||
pglGetIntegerv( GL_ACCUM_GREEN_BITS, &val_g );
|
||
pglGetIntegerv( GL_ACCUM_BLUE_BITS, &val_b );
|
||
|
||
if( !val_r || !val_g || !val_b )
|
||
{
|
||
ALERT( at_error, "Accumulation buffer is not present\n" );
|
||
gHUD.m_flBlurAmount = 0.0f;
|
||
return;
|
||
}
|
||
|
||
if( !blurstate )
|
||
{
|
||
// load entire screen first time
|
||
pglAccum( GL_LOAD, 1.0f );
|
||
}
|
||
else
|
||
{
|
||
float blur = ( 51.0f - ( gHUD.m_flBlurAmount * 50.0f ));
|
||
blur = bound( 0.0f, blur * frametime, 1.0f );
|
||
pglReadBuffer( GL_BACK );
|
||
pglAccum( GL_MULT, 1.0f - blur ); // scale contents of accumulation buffer
|
||
pglAccum( GL_ACCUM, blur ); // add screen contents
|
||
pglAccum( GL_RETURN, 1 ); // read result back
|
||
}
|
||
|
||
blurstate = true;
|
||
}
|
||
else
|
||
{
|
||
blurstate = false;
|
||
}
|
||
} |