Paranoia2/cl_dll/hud_redraw.cpp

523 lines
13 KiB
C++
Raw Normal View History

2020-08-31 18:50:41 +02:00
/***
*
* 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, остававшегося после загрузки из мертвого состояния.
2020-08-31 18:50:41 +02:00
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)
2020-08-31 18:50:41 +02:00
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;
2020-09-01 17:07:37 +02:00
static int m_flShotTime = 0;
2020-08-31 18:50:41 +02:00
#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.
2020-08-31 18:50:41 +02:00
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
2020-09-01 17:07:37 +02:00
char *szIt;
for ( szIt = szString; *szIt != 0; szIt++ )
2020-08-31 18:50:41 +02:00
{ // 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;
}
2020-09-01 17:07:37 +02:00
}