hlsdk-xash3d/game_shared/voice_status.cpp

851 lines
21 KiB
C++

//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
// There are hud.h's coming out of the woodwork so this ensures that we get the right one.
#include "../cl_dll/hud.h"
#include "../cl_dll/cl_util.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "../cl_dll/parsemsg.h"
#include "../cl_dll/hud_servers.h"
#include "../cl_dll/demo.h"
#include "demo_api.h"
#include "voice_status.h"
#include "r_efx.h"
#include "entity_types.h"
#include "VGUI_ActionSignal.h"
#include "VGUI_Scheme.h"
#include "VGUI_TextImage.h"
#include "vgui_loadtga.h"
#include "vgui_helpers.h"
#include "vgui_mousecode.h"
using namespace vgui;
extern int cam_thirdperson;
#define VOICE_MODEL_INTERVAL 0.3
#define SCOREBOARD_BLINK_FREQUENCY 0.3 // How often to blink the scoreboard icons.
#define SQUELCHOSCILLATE_PER_SECOND 2.0f
extern BitmapTGA *LoadTGA( const char* pImageName );
// ---------------------------------------------------------------------- //
// The voice manager for the client.
// ---------------------------------------------------------------------- //
CVoiceStatus g_VoiceStatus;
CVoiceStatus* GetClientVoiceMgr()
{
return &g_VoiceStatus;
}
// ---------------------------------------------------------------------- //
// CVoiceStatus.
// ---------------------------------------------------------------------- //
static CVoiceStatus *g_pInternalVoiceStatus = NULL;
int __MsgFunc_VoiceMask( const char *pszName, int iSize, void *pbuf )
{
if( g_pInternalVoiceStatus )
g_pInternalVoiceStatus->HandleVoiceMaskMsg( iSize, pbuf );
return 1;
}
int __MsgFunc_ReqState( const char *pszName, int iSize, void *pbuf )
{
if( g_pInternalVoiceStatus )
g_pInternalVoiceStatus->HandleReqStateMsg( iSize, pbuf );
return 1;
}
int g_BannedPlayerPrintCount;
void ForEachBannedPlayer( char id[16] )
{
char str[256];
sprintf( str, "Ban %d: %2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x\n",
g_BannedPlayerPrintCount++,
id[0], id[1], id[2], id[3],
id[4], id[5], id[6], id[7],
id[8], id[9], id[10], id[11],
id[12], id[13], id[14], id[15]
);
strupr( str );
gEngfuncs.pfnConsolePrint(str);
}
void ShowBannedCallback()
{
if( g_pInternalVoiceStatus )
{
g_BannedPlayerPrintCount = 0;
gEngfuncs.pfnConsolePrint("------- BANNED PLAYERS -------\n");
g_pInternalVoiceStatus->m_BanMgr.ForEachBannedPlayer( ForEachBannedPlayer );
gEngfuncs.pfnConsolePrint("------------------------------\n");
}
}
// ---------------------------------------------------------------------- //
// CVoiceStatus.
// ---------------------------------------------------------------------- //
CVoiceStatus::CVoiceStatus()
{
m_bBanMgrInitialized = false;
m_LastUpdateServerState = 0;
m_pSpeakerLabelIcon = NULL;
m_pScoreboardNeverSpoken = NULL;
m_pScoreboardNotSpeaking = NULL;
m_pScoreboardSpeaking = NULL;
m_pScoreboardSpeaking2 = NULL;
m_pScoreboardSquelch = NULL;
m_pScoreboardBanned = NULL;
m_pLocalBitmap = NULL;
m_pAckBitmap = NULL;
m_bTalking = m_bServerAcked = false;
memset( m_pBanButtons, 0, sizeof(m_pBanButtons) );
m_bServerModEnable = -1;
m_pchGameDir = NULL;
}
CVoiceStatus::~CVoiceStatus()
{
g_pInternalVoiceStatus = NULL;
for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ )
{
delete m_Labels[i].m_pLabel;
m_Labels[i].m_pLabel = NULL;
delete m_Labels[i].m_pIcon;
m_Labels[i].m_pIcon = NULL;
delete m_Labels[i].m_pBackground;
m_Labels[i].m_pBackground = NULL;
}
delete m_pLocalLabel;
m_pLocalLabel = NULL;
FreeBitmaps();
if( m_pchGameDir )
{
if( m_bBanMgrInitialized )
{
m_BanMgr.SaveState( m_pchGameDir );
}
free( m_pchGameDir );
}
}
int CVoiceStatus::Init( IVoiceStatusHelper *pHelper, Panel **pParentPanel )
{
// Setup the voice_modenable cvar.
gEngfuncs.pfnRegisterVariable( "voice_modenable", "1", FCVAR_ARCHIVE );
gEngfuncs.pfnRegisterVariable( "voice_clientdebug", "0", 0 );
gEngfuncs.pfnAddCommand( "voice_showbanned", ShowBannedCallback );
if( gEngfuncs.pfnGetGameDirectory() )
{
m_BanMgr.Init( gEngfuncs.pfnGetGameDirectory() );
m_bBanMgrInitialized = true;
}
assert( !g_pInternalVoiceStatus );
g_pInternalVoiceStatus = this;
m_BlinkTimer = 0;
m_VoiceHeadModel = NULL;
memset( m_Labels, 0, sizeof(m_Labels) );
for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ )
{
CVoiceLabel *pLabel = &m_Labels[i];
pLabel->m_pBackground = new Label( "" );
if( pLabel->m_pLabel = new Label( "" ) )
{
pLabel->m_pLabel->setVisible( true );
pLabel->m_pLabel->setFont( Scheme::sf_primary2 );
pLabel->m_pLabel->setTextAlignment( Label::a_east );
pLabel->m_pLabel->setContentAlignment( Label::a_east );
pLabel->m_pLabel->setParent( pLabel->m_pBackground );
}
if( pLabel->m_pIcon = new ImagePanel( NULL ) )
{
pLabel->m_pIcon->setVisible( true );
pLabel->m_pIcon->setParent( pLabel->m_pBackground );
}
pLabel->m_clientindex = -1;
}
m_pLocalLabel = new ImagePanel( NULL );
m_bInSquelchMode = false;
m_pHelper = pHelper;
m_pParentPanel = pParentPanel;
gHUD.AddHudElem( this );
m_iFlags = HUD_ACTIVE;
HOOK_MESSAGE( VoiceMask );
HOOK_MESSAGE( ReqState );
// Cache the game directory for use when we shut down
const char *pchGameDirT = gEngfuncs.pfnGetGameDirectory();
m_pchGameDir = (char *)malloc( strlen( pchGameDirT ) + 1 );
strcpy( m_pchGameDir, pchGameDirT );
return 1;
}
int CVoiceStatus::VidInit()
{
FreeBitmaps();
if( m_pLocalBitmap = vgui_LoadTGA( "gfx/vgui/icntlk_pl.tga" ) )
{
m_pLocalBitmap->setColor( Color( 255, 255, 255, 135 ) );
}
if( m_pAckBitmap = vgui_LoadTGA( "gfx/vgui/icntlk_sv.tga" ) )
{
m_pAckBitmap->setColor( Color( 255, 255, 255, 135 ) ); // Give just a tiny bit of translucency so software draws correctly.
}
m_pLocalLabel->setImage( m_pLocalBitmap );
m_pLocalLabel->setVisible( false );
if( m_pSpeakerLabelIcon = vgui_LoadTGANoInvertAlpha( "gfx/vgui/speaker4.tga" ) )
m_pSpeakerLabelIcon->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly.
if( m_pScoreboardNeverSpoken = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker1.tga" ) )
m_pScoreboardNeverSpoken->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly.
if( m_pScoreboardNotSpeaking = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker2.tga" ) )
m_pScoreboardNotSpeaking->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly.
if( m_pScoreboardSpeaking = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker3.tga" ) )
m_pScoreboardSpeaking->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly.
if( m_pScoreboardSpeaking2 = vgui_LoadTGANoInvertAlpha( "gfx/vgui/640_speaker4.tga" ) )
m_pScoreboardSpeaking2->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly.
if( m_pScoreboardSquelch = vgui_LoadTGA( "gfx/vgui/icntlk_squelch.tga" ) )
m_pScoreboardSquelch->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly.
if( m_pScoreboardBanned = vgui_LoadTGA( "gfx/vgui/640_voiceblocked.tga" ) )
m_pScoreboardBanned->setColor( Color( 255, 255, 255, 1 ) ); // Give just a tiny bit of translucency so software draws correctly.
// Figure out the voice head model height.
m_VoiceHeadModelHeight = 45;
char *pFile = (char *)gEngfuncs.COM_LoadFile( "scripts/voicemodel.txt", 5, NULL );
if( pFile )
{
char token[4096];
gEngfuncs.COM_ParseFile( pFile, token );
if( token[0] >= '0' && token[0] <= '9' )
{
m_VoiceHeadModelHeight = (float)atof( token );
}
gEngfuncs.COM_FreeFile( pFile );
}
m_VoiceHeadModel = gEngfuncs.pfnSPR_Load( "sprites/voiceicon.spr" );
return TRUE;
}
void CVoiceStatus::Frame( double frametime )
{
// check server banned players once per second
if( gEngfuncs.GetClientTime() - m_LastUpdateServerState > 1 )
{
UpdateServerState( false );
}
m_BlinkTimer += frametime;
// Update speaker labels.
if( m_pHelper->CanShowSpeakerLabels() )
{
for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ )
m_Labels[i].m_pBackground->setVisible( m_Labels[i].m_clientindex != -1 );
}
else
{
for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ )
m_Labels[i].m_pBackground->setVisible( false );
}
for( int i = 0; i < VOICE_MAX_PLAYERS; i++ )
UpdateBanButton(i);
}
void CVoiceStatus::CreateEntities()
{
if( !m_VoiceHeadModel )
return;
cl_entity_t *localPlayer = gEngfuncs.GetLocalPlayer();
int iOutModel = 0;
for( int i = 0; i < VOICE_MAX_PLAYERS; i++ )
{
if( !m_VoicePlayers[i] )
continue;
cl_entity_s *pClient = gEngfuncs.GetEntityByIndex( i + 1 );
// Don't show an icon if the player is not in our PVS.
if( !pClient || pClient->curstate.messagenum < localPlayer->curstate.messagenum )
continue;
// Don't show an icon for dead or spectating players (ie: invisible entities).
if( pClient->curstate.effects & EF_NODRAW )
continue;
// Don't show an icon for the local player unless we're in thirdperson mode.
if( pClient == localPlayer && !cam_thirdperson )
continue;
cl_entity_s *pEnt = &m_VoiceHeadModels[iOutModel];
++iOutModel;
memset( pEnt, 0, sizeof(*pEnt) );
pEnt->curstate.rendermode = kRenderTransAdd;
pEnt->curstate.renderamt = 255;
pEnt->baseline.renderamt = 255;
pEnt->curstate.renderfx = kRenderFxNoDissipation;
pEnt->curstate.framerate = 1;
pEnt->curstate.frame = 0;
pEnt->model = (struct model_s*)gEngfuncs.GetSpritePointer( m_VoiceHeadModel );
pEnt->angles[0] = pEnt->angles[1] = pEnt->angles[2] = 0;
pEnt->curstate.scale = 0.5f;
pEnt->origin[0] = pEnt->origin[1] = 0;
pEnt->origin[2] = 45;
VectorAdd( pEnt->origin, pClient->origin, pEnt->origin );
// Tell the engine.
gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, pEnt );
}
}
void CVoiceStatus::UpdateSpeakerStatus( int entindex, qboolean bTalking )
{
if( !*m_pParentPanel )
return;
if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") )
{
char msg[256];
sprintf( msg, "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking );
gEngfuncs.pfnConsolePrint( msg );
}
// Is it the local player talking?
if( entindex == -1 )
{
m_bTalking = !!bTalking;
if( bTalking )
{
// Enable voice for them automatically if they try to talk.
gEngfuncs.pfnClientCmd( "voice_modenable 1" );
}
}
else if( entindex == -2 )
{
m_bServerAcked = !!bTalking;
}
else if( entindex >= 0 && entindex <= VOICE_MAX_PLAYERS )
{
int iClient = entindex - 1;
if( iClient < 0 )
return;
CVoiceLabel *pLabel = FindVoiceLabel( iClient );
if( bTalking )
{
m_VoicePlayers[iClient] = true;
m_VoiceEnabledPlayers[iClient] = true;
// If we don't have a label for this guy yet, then create one.
if( !pLabel )
{
if( pLabel = GetFreeVoiceLabel() )
{
// Get the name from the engine.
hud_player_info_t info = {0};
GetPlayerInfo( entindex, &info );
char paddedName[512];
sprintf( paddedName, "%s ", info.name );
int color[3];
m_pHelper->GetPlayerTextColor( entindex, color );
if( pLabel->m_pBackground )
{
pLabel->m_pBackground->setBgColor( color[0], color[1], color[2], 135 );
pLabel->m_pBackground->setParent( *m_pParentPanel );
pLabel->m_pBackground->setVisible( m_pHelper->CanShowSpeakerLabels() );
}
if( pLabel->m_pLabel )
{
pLabel->m_pLabel->setFgColor( 255, 255, 255, 0 );
pLabel->m_pLabel->setBgColor( 0, 0, 0, 255 );
pLabel->m_pLabel->setText( paddedName );
}
pLabel->m_clientindex = iClient;
}
}
}
else
{
m_VoicePlayers[iClient] = false;
// If we have a label for this guy, kill it.
if( pLabel )
{
pLabel->m_pBackground->setVisible( false );
pLabel->m_clientindex = -1;
}
}
}
RepositionLabels();
}
void CVoiceStatus::UpdateServerState( bool bForce )
{
// Can't do anything when we're not in a level.
char const *pLevelName = gEngfuncs.pfnGetLevelName();
if( pLevelName[0] == 0 )
{
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: pLevelName[0]==0\n" );
}
return;
}
int bCVarModEnable = !!gEngfuncs.pfnGetCvarFloat( "voice_modenable" );
if( bForce || m_bServerModEnable != bCVarModEnable )
{
m_bServerModEnable = bCVarModEnable;
char str[256];
sprintf( str, "VModEnable %d", m_bServerModEnable );
ServerCmd( str );
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
char msg[256];
sprintf( msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str );
gEngfuncs.pfnConsolePrint( msg );
}
}
char str[2048] = "vban";
bool bChange = false;
for( unsigned long dw = 0; dw < VOICE_MAX_PLAYERS_DW; dw++ )
{
unsigned long serverBanMask = 0;
unsigned long banMask = 0;
for( unsigned long i = 0; i < 32; i++ )
{
char playerID[16];
if( !gEngfuncs.GetPlayerUniqueID( i + 1, playerID ) )
continue;
if( m_BanMgr.GetPlayerBan( playerID ) )
banMask |= 1 << i;
if( m_ServerBannedPlayers[dw * 32 + i] )
serverBanMask |= 1 << i;
}
if( serverBanMask != banMask )
bChange = true;
// Ok, the server needs to be updated.
char numStr[512];
sprintf(numStr, " %x", banMask);
strcat(str, numStr);
}
if( bChange || bForce )
{
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
char msg[256];
sprintf( msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str );
gEngfuncs.pfnConsolePrint( msg );
}
gEngfuncs.pfnServerCmdUnreliable( str ); // Tell the server..
}
else
{
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: no change\n" );
}
}
m_LastUpdateServerState = gEngfuncs.GetClientTime();
}
void CVoiceStatus::UpdateSpeakerImage( Label *pLabel, int iPlayer )
{
m_pBanButtons[iPlayer - 1] = pLabel;
UpdateBanButton(iPlayer - 1);
}
void CVoiceStatus::UpdateBanButton( int iClient )
{
Label *pPanel = m_pBanButtons[iClient];
if( !pPanel )
return;
char playerID[16];
extern bool HACK_GetPlayerUniqueID( int iPlayer, char playerID[16] );
if( !HACK_GetPlayerUniqueID( iClient + 1, playerID ) )
return;
// Figure out if it's blinking or not.
bool bBlink = fmod( m_BlinkTimer, SCOREBOARD_BLINK_FREQUENCY * 2 ) < SCOREBOARD_BLINK_FREQUENCY;
bool bTalking = !!m_VoicePlayers[iClient];
bool bBanned = m_BanMgr.GetPlayerBan( playerID );
bool bNeverSpoken = !m_VoiceEnabledPlayers[iClient];
// Get the appropriate image to display on the panel.
if( bBanned )
{
pPanel->setImage( m_pScoreboardBanned );
}
else if( bTalking )
{
if( bBlink )
{
pPanel->setImage( m_pScoreboardSpeaking2 );
}
else
{
pPanel->setImage( m_pScoreboardSpeaking );
}
pPanel->setFgColor( 255, 170, 0, 1 );
}
else if( bNeverSpoken )
{
pPanel->setImage( m_pScoreboardNeverSpoken );
pPanel->setFgColor( 100, 100, 100, 1 );
}
else
{
pPanel->setImage( m_pScoreboardNotSpeaking );
}
}
void CVoiceStatus::HandleVoiceMaskMsg( int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
unsigned long dw;
for( dw = 0; dw < VOICE_MAX_PLAYERS_DW; dw++ )
{
m_AudiblePlayers.SetDWord( dw, (unsigned long)READ_LONG() );
m_ServerBannedPlayers.SetDWord( dw, (unsigned long)READ_LONG() );
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
char str[256];
gEngfuncs.pfnConsolePrint( "CVoiceStatus::HandleVoiceMaskMsg\n" );
sprintf( str, " - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord( dw ) );
gEngfuncs.pfnConsolePrint( str );
sprintf( str, " - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord( dw ) );
gEngfuncs.pfnConsolePrint( str );
}
}
m_bServerModEnable = READ_BYTE();
}
void CVoiceStatus::HandleReqStateMsg( int iSize, void *pbuf )
{
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::HandleReqStateMsg\n" );
}
UpdateServerState( true );
}
void CVoiceStatus::StartSquelchMode()
{
if( m_bInSquelchMode )
return;
m_bInSquelchMode = true;
m_pHelper->UpdateCursorState();
}
void CVoiceStatus::StopSquelchMode()
{
m_bInSquelchMode = false;
m_pHelper->UpdateCursorState();
}
bool CVoiceStatus::IsInSquelchMode()
{
return m_bInSquelchMode;
}
CVoiceLabel *CVoiceStatus::FindVoiceLabel( int clientindex )
{
for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ )
{
if( m_Labels[i].m_clientindex == clientindex )
return &m_Labels[i];
}
return NULL;
}
CVoiceLabel *CVoiceStatus::GetFreeVoiceLabel()
{
return FindVoiceLabel( -1 );
}
void CVoiceStatus::RepositionLabels()
{
// find starting position to draw from, along right-hand side of screen
int y = ScreenHeight / 2;
int iconWide = 8, iconTall = 8;
if( m_pSpeakerLabelIcon )
{
m_pSpeakerLabelIcon->getSize( iconWide, iconTall );
}
// Reposition active labels.
for( int i = 0; i < MAX_VOICE_SPEAKERS; i++ )
{
CVoiceLabel *pLabel = &m_Labels[i];
if( pLabel->m_clientindex == -1 || !pLabel->m_pLabel )
{
if( pLabel->m_pBackground )
pLabel->m_pBackground->setVisible( false );
continue;
}
int textWide, textTall;
pLabel->m_pLabel->getContentSize( textWide, textTall );
// Don't let it stretch too far across their screen.
if( textWide > ( ScreenWidth * 2 ) / 3 )
textWide = ( ScreenWidth * 2 ) / 3;
// Setup the background label to fit everything in.
int border = 2;
int bgWide = textWide + iconWide + border * 3;
int bgTall = max( textTall, iconTall ) + border * 2;
pLabel->m_pBackground->setBounds( ScreenWidth - bgWide - 8, y, bgWide, bgTall );
// Put the text at the left.
pLabel->m_pLabel->setBounds( border, ( bgTall - textTall ) / 2, textWide, textTall );
// Put the icon at the right.
int iconLeft = border + textWide + border;
int iconTop = ( bgTall - iconTall ) / 2;
if( pLabel->m_pIcon )
{
pLabel->m_pIcon->setImage( m_pSpeakerLabelIcon );
pLabel->m_pIcon->setBounds( iconLeft, iconTop, iconWide, iconTall );
}
y += bgTall + 2;
}
if( m_pLocalBitmap && m_pAckBitmap && m_pLocalLabel && ( m_bTalking || m_bServerAcked ) )
{
m_pLocalLabel->setParent( *m_pParentPanel );
m_pLocalLabel->setVisible( true );
if( m_bServerAcked && !!gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
m_pLocalLabel->setImage( m_pAckBitmap );
else
m_pLocalLabel->setImage( m_pLocalBitmap );
int sizeX, sizeY;
m_pLocalBitmap->getSize( sizeX, sizeY );
int local_xPos = ScreenWidth - sizeX - 10;
int local_yPos = m_pHelper->GetAckIconHeight() - sizeY;
m_pLocalLabel->setPos( local_xPos, local_yPos );
}
else
{
m_pLocalLabel->setVisible( false );
}
}
void CVoiceStatus::FreeBitmaps()
{
// Delete all the images we have loaded.
delete m_pLocalBitmap;
m_pLocalBitmap = NULL;
delete m_pAckBitmap;
m_pAckBitmap = NULL;
delete m_pSpeakerLabelIcon;
m_pSpeakerLabelIcon = NULL;
delete m_pScoreboardNeverSpoken;
m_pScoreboardNeverSpoken = NULL;
delete m_pScoreboardNotSpeaking;
m_pScoreboardNotSpeaking = NULL;
delete m_pScoreboardSpeaking;
m_pScoreboardSpeaking = NULL;
delete m_pScoreboardSpeaking2;
m_pScoreboardSpeaking2 = NULL;
delete m_pScoreboardSquelch;
m_pScoreboardSquelch = NULL;
delete m_pScoreboardBanned;
m_pScoreboardBanned = NULL;
// Clear references to the images in panels.
for( int i = 0; i < VOICE_MAX_PLAYERS; i++ )
{
if( m_pBanButtons[i] )
{
m_pBanButtons[i]->setImage( NULL );
}
}
if( m_pLocalLabel )
m_pLocalLabel->setImage( NULL );
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the target client has been banned
// Input : playerID -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CVoiceStatus::IsPlayerBlocked( int iPlayer )
{
char playerID[16];
if( !gEngfuncs.GetPlayerUniqueID( iPlayer, playerID ) )
return false;
return m_BanMgr.GetPlayerBan( playerID );
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the player can't hear the other client due to game rules (eg. the other team)
// Input : playerID -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CVoiceStatus::IsPlayerAudible( int iPlayer )
{
return !!m_AudiblePlayers[iPlayer - 1];
}
//-----------------------------------------------------------------------------
// Purpose: blocks/unblocks the target client from being heard
// Input : playerID -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
void CVoiceStatus::SetPlayerBlockedState( int iPlayer, bool blocked )
{
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 1\n" );
}
char playerID[16];
if( !gEngfuncs.GetPlayerUniqueID( iPlayer, playerID ) )
return;
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 2\n" );
}
// Squelch or (try to) unsquelch this player.
if( gEngfuncs.pfnGetCvarFloat( "voice_clientdebug" ) )
{
char str[256];
sprintf( str, "CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan( playerID ) );
gEngfuncs.pfnConsolePrint( str );
}
m_BanMgr.SetPlayerBan( playerID, blocked );
UpdateServerState( false );
}