From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/game/client/hud_basechat.cpp | 3662 +++++++++++++++++------------------ 1 file changed, 1831 insertions(+), 1831 deletions(-) (limited to 'mp/src/game/client/hud_basechat.cpp') diff --git a/mp/src/game/client/hud_basechat.cpp b/mp/src/game/client/hud_basechat.cpp index 9a50e062..69d67862 100644 --- a/mp/src/game/client/hud_basechat.cpp +++ b/mp/src/game/client/hud_basechat.cpp @@ -1,1832 +1,1832 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "hud_basechat.h" - -#include -#include -#include "iclientmode.h" -#include "hud_macros.h" -#include "engine/IEngineSound.h" -#include "text_message.h" -#include -#include "vguicenterprint.h" -#include "vgui/KeyCode.h" -#include -#include "ienginevgui.h" -#include "c_playerresource.h" -#include "ihudlcd.h" -#include "vgui/IInput.h" -#include "vgui/ILocalize.h" -#include "multiplay_gamerules.h" - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define CHAT_WIDTH_PERCENTAGE 0.6f - -#ifndef _XBOX -ConVar hud_saytext_time( "hud_saytext_time", "12", 0 ); -ConVar cl_showtextmsg( "cl_showtextmsg", "1", 0, "Enable/disable text messages printing on the screen." ); -ConVar cl_chatfilters( "cl_chatfilters", "63", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Stores the chat filter settings " ); -ConVar cl_chatfilter_version( "cl_chatfilter_version", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE | FCVAR_HIDDEN, "Stores the chat filter version" ); - -const int kChatFilterVersion = 1; - -Color g_ColorBlue( 153, 204, 255, 255 ); -Color g_ColorRed( 255, 63, 63, 255 ); -Color g_ColorGreen( 153, 255, 153, 255 ); -Color g_ColorDarkGreen( 64, 255, 64, 255 ); -Color g_ColorYellow( 255, 178, 0, 255 ); -Color g_ColorGrey( 204, 204, 204, 255 ); - - -// removes all color markup characters, so Msg can deal with the string properly -// returns a pointer to str -char* RemoveColorMarkup( char *str ) -{ - char *out = str; - for ( char *in = str; *in != 0; ++in ) - { - if ( *in > 0 && *in < COLOR_MAX ) - { - if ( *in == COLOR_HEXCODE || *in == COLOR_HEXCODE_ALPHA ) - { - // skip the next six or eight characters - const int nSkip = ( *in == COLOR_HEXCODE ? 6 : 8 ); - for ( int i = 0; i < nSkip && *in != 0; i++ ) - { - ++in; - } - - // if we reached the end of the string first, then back up - if ( *in == 0 ) - { - --in; - } - } - - continue; - } - *out = *in; - ++out; - } - *out = 0; - - return str; -} - -// converts all '\r' characters to '\n', so that the engine can deal with the properly -// returns a pointer to str -char* ConvertCRtoNL( char *str ) -{ - for ( char *ch = str; *ch != 0; ch++ ) - if ( *ch == '\r' ) - *ch = '\n'; - return str; -} - -// converts all '\r' characters to '\n', so that the engine can deal with the properly -// returns a pointer to str -wchar_t* ConvertCRtoNL( wchar_t *str ) -{ - for ( wchar_t *ch = str; *ch != 0; ch++ ) - if ( *ch == L'\r' ) - *ch = L'\n'; - return str; -} - -void StripEndNewlineFromString( char *str ) -{ - int s = strlen( str ) - 1; - if ( s >= 0 ) - { - if ( str[s] == '\n' || str[s] == '\r' ) - str[s] = 0; - } -} - -void StripEndNewlineFromString( wchar_t *str ) -{ - int s = wcslen( str ) - 1; - if ( s >= 0 ) - { - if ( str[s] == L'\n' || str[s] == L'\r' ) - str[s] = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Reads a string from the current message and checks if it is translatable -//----------------------------------------------------------------------------- -wchar_t* ReadLocalizedString( bf_read &msg, OUT_Z_BYTECAP(outSizeInBytes) wchar_t *pOut, int outSizeInBytes, bool bStripNewline, OUT_Z_CAP(originalSize) char *originalString, int originalSize ) -{ - char szString[2048]; - szString[0] = 0; - msg.ReadString( szString, sizeof(szString) ); - - if ( originalString ) - { - Q_strncpy( originalString, szString, originalSize ); - } - - const wchar_t *pBuf = g_pVGuiLocalize->Find( szString ); - if ( pBuf ) - { - V_wcsncpy( pOut, pBuf, outSizeInBytes ); - } - else - { - g_pVGuiLocalize->ConvertANSIToUnicode( szString, pOut, outSizeInBytes ); - } - - if ( bStripNewline ) - StripEndNewlineFromString( pOut ); - - return pOut; -} - -//----------------------------------------------------------------------------- -// Purpose: Reads a string from the current message, converts it to unicode, and strips out color codes -//----------------------------------------------------------------------------- -wchar_t* ReadChatTextString( bf_read &msg, OUT_Z_BYTECAP(outSizeInBytes) wchar_t *pOut, int outSizeInBytes ) -{ - char szString[2048]; - szString[0] = 0; - msg.ReadString( szString, sizeof(szString) ); - - g_pVGuiLocalize->ConvertANSIToUnicode( szString, pOut, outSizeInBytes ); - - StripEndNewlineFromString( pOut ); - - // converts color control characters into control characters for the normal color - for ( wchar_t *test = pOut; test && *test; ++test ) - { - if ( *test && (*test < COLOR_MAX ) ) - { - if ( *test == COLOR_HEXCODE || *test == COLOR_HEXCODE_ALPHA ) - { - // mark the next seven or nine characters. one for the control character and six or eight for the code itself. - const int nSkip = ( *test == COLOR_HEXCODE ? 7 : 9 ); - for ( int i = 0; i < nSkip && *test != 0; i++, test++ ) - { - *test = COLOR_NORMAL; - } - - // if we reached the end of the string first, then back up - if ( *test == 0 ) - { - --test; - } - } - else - { - *test = COLOR_NORMAL; - } - } - } - - return pOut; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *parent - -// *panelName - -//----------------------------------------------------------------------------- -CBaseHudChatLine::CBaseHudChatLine( vgui::Panel *parent, const char *panelName ) : - vgui::RichText( parent, panelName ) -{ - m_hFont = m_hFontMarlett = 0; - m_flExpireTime = 0.0f; - m_flStartTime = 0.0f; - m_iNameLength = 0; - m_text = NULL; - - SetPaintBackgroundEnabled( true ); - - SetVerticalScrollbar( false ); -} - -CBaseHudChatLine::~CBaseHudChatLine() -{ - if ( m_text ) - { - delete[] m_text; - m_text = NULL; - } -} - - -void CBaseHudChatLine::ApplySchemeSettings(vgui::IScheme *pScheme) -{ - BaseClass::ApplySchemeSettings(pScheme); - - m_hFont = pScheme->GetFont( "Default" ); - -#ifdef HL1_CLIENT_DLL - SetBgColor( Color( 0, 0, 0, 0 ) ); - SetFgColor( Color( 0, 0, 0, 0 ) ); - - SetBorder( NULL ); -#else - SetBgColor( Color( 0, 0, 0, 100 ) ); -#endif - - - m_hFontMarlett = pScheme->GetFont( "Marlett" ); - - m_clrText = pScheme->GetColor( "FgColor", GetFgColor() ); - SetFont( m_hFont ); -} - - -void CBaseHudChatLine::PerformFadeout( void ) -{ - // Flash + Extra bright when new - float curtime = gpGlobals->curtime; - - int lr = m_clrText[0]; - int lg = m_clrText[1]; - int lb = m_clrText[2]; - - if ( curtime >= m_flStartTime && curtime < m_flStartTime + CHATLINE_FLASH_TIME ) - { - float frac1 = ( curtime - m_flStartTime ) / CHATLINE_FLASH_TIME; - float frac = frac1; - - frac *= CHATLINE_NUM_FLASHES; - frac *= 2 * M_PI; - - frac = cos( frac ); - - frac = clamp( frac, 0.0f, 1.0f ); - - frac *= (1.0f-frac1); - - int r = lr, g = lg, b = lb; - - r = r + ( 255 - r ) * frac; - g = g + ( 255 - g ) * frac; - b = b + ( 255 - b ) * frac; - - // Draw a right facing triangle in red, faded out over time - int alpha = 63 + 192 * (1.0f - frac1 ); - alpha = clamp( alpha, 0, 255 ); - - wchar_t wbuf[4096]; - GetText(0, wbuf, sizeof(wbuf)); - - SetText( "" ); - - InsertColorChange( Color( r, g, b, 255 ) ); - InsertString( wbuf ); - } - else if ( curtime <= m_flExpireTime && curtime > m_flExpireTime - CHATLINE_FADE_TIME ) - { - float frac = ( m_flExpireTime - curtime ) / CHATLINE_FADE_TIME; - - int alpha = frac * 255; - alpha = clamp( alpha, 0, 255 ); - - wchar_t wbuf[4096]; - GetText(0, wbuf, sizeof(wbuf)); - - SetText( "" ); - - InsertColorChange( Color( lr * frac, lg * frac, lb * frac, alpha ) ); - InsertString( wbuf ); - } - else - { - wchar_t wbuf[4096]; - GetText(0, wbuf, sizeof(wbuf)); - - SetText( "" ); - - InsertColorChange( Color( lr, lg, lb, 255 ) ); - InsertString( wbuf ); - } - - OnThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -//----------------------------------------------------------------------------- -void CBaseHudChatLine::SetExpireTime( void ) -{ - m_flStartTime = gpGlobals->curtime; - m_flExpireTime = m_flStartTime + hud_saytext_time.GetFloat(); - m_nCount = CBaseHudChat::m_nLineCounter++; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseHudChatLine::GetCount( void ) -{ - return m_nCount; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHudChatLine::IsReadyToExpire( void ) -{ - // Engine disconnected, expire right away - if ( !engine->IsInGame() && !engine->IsConnected() ) - return true; - - if ( gpGlobals->curtime >= m_flExpireTime ) - return true; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CBaseHudChatLine::GetStartTime( void ) -{ - return m_flStartTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHudChatLine::Expire( void ) -{ - SetVisible( false ); - - // Spit out label text now -// char text[ 256 ]; -// GetText( text, 256 ); - -// Msg( "%s\n", text ); -} -#endif // _XBOX - -//----------------------------------------------------------------------------- -// Purpose: The prompt and text entry area for chat messages -//----------------------------------------------------------------------------- -#ifndef _XBOX -CBaseHudChatInputLine::CBaseHudChatInputLine( vgui::Panel *parent, char const *panelName ) : - vgui::Panel( parent, panelName ) -{ - SetMouseInputEnabled( false ); - - m_pPrompt = new vgui::Label( this, "ChatInputPrompt", L"Enter text:" ); - - m_pInput = new CBaseHudChatEntry( this, "ChatInput", parent ); - m_pInput->SetMaximumCharCount( 127 ); -} - -void CBaseHudChatInputLine::ApplySchemeSettings(vgui::IScheme *pScheme) -{ - BaseClass::ApplySchemeSettings(pScheme); - - // FIXME: Outline - vgui::HFont hFont = pScheme->GetFont( "ChatFont" ); - - m_pPrompt->SetFont( hFont ); - m_pInput->SetFont( hFont ); - - m_pInput->SetFgColor( pScheme->GetColor( "Chat.TypingText", pScheme->GetColor( "Panel.FgColor", Color( 255, 255, 255, 255 ) ) ) ); - - SetPaintBackgroundEnabled( true ); - m_pPrompt->SetPaintBackgroundEnabled( true ); - m_pPrompt->SetContentAlignment( vgui::Label::a_west ); - m_pPrompt->SetTextInset( 2, 0 ); - - m_pInput->SetMouseInputEnabled( true ); - -#ifdef HL1_CLIENT_DLL - m_pInput->SetBgColor( Color( 255, 255, 255, 0 ) ); -#endif - - SetBgColor( Color( 0, 0, 0, 0) ); - -} - -void CBaseHudChatInputLine::SetPrompt( const wchar_t *prompt ) -{ - Assert( m_pPrompt ); - m_pPrompt->SetText( prompt ); - InvalidateLayout(); -} - -void CBaseHudChatInputLine::ClearEntry( void ) -{ - Assert( m_pInput ); - SetEntry( L"" ); -} - -void CBaseHudChatInputLine::SetEntry( const wchar_t *entry ) -{ - Assert( m_pInput ); - Assert( entry ); - - m_pInput->SetText( entry ); -} - -void CBaseHudChatInputLine::GetMessageText( OUT_Z_BYTECAP(buffersizebytes) wchar_t *buffer, int buffersizebytes ) -{ - m_pInput->GetText( buffer, buffersizebytes); -} - -void CBaseHudChatInputLine::PerformLayout() -{ - BaseClass::PerformLayout(); - - int wide, tall; - GetSize( wide, tall ); - - int w,h; - m_pPrompt->GetContentSize( w, h); - m_pPrompt->SetBounds( 0, 0, w, tall ); - - m_pInput->SetBounds( w + 2, 0, wide - w - 2 , tall ); -} - -vgui::Panel *CBaseHudChatInputLine::GetInputPanel( void ) -{ - return m_pInput; -} -#endif //_XBOX - - -CHudChatFilterButton::CHudChatFilterButton( vgui::Panel *pParent, const char *pName, const char *pText ) : -BaseClass( pParent, pName, pText ) -{ -} - -CHudChatFilterCheckButton::CHudChatFilterCheckButton( vgui::Panel *pParent, const char *pName, const char *pText, int iFlag ) : -BaseClass( pParent, pName, pText ) -{ - m_iFlag = iFlag; -} - - -CHudChatFilterPanel::CHudChatFilterPanel( vgui::Panel *pParent, const char *pName ) : BaseClass ( pParent, pName ) -{ - pParent->SetSize( 10, 10 ); // Quiet "parent not sized yet" spew - SetParent( pParent ); - - new CHudChatFilterCheckButton( this, "joinleave_button", "Sky is blue?", CHAT_FILTER_JOINLEAVE ); - new CHudChatFilterCheckButton( this, "namechange_button", "Sky is blue?", CHAT_FILTER_NAMECHANGE ); - new CHudChatFilterCheckButton( this, "publicchat_button", "Sky is blue?", CHAT_FILTER_PUBLICCHAT ); - new CHudChatFilterCheckButton( this, "servermsg_button", "Sky is blue?", CHAT_FILTER_SERVERMSG ); - new CHudChatFilterCheckButton( this, "teamchange_button", "Sky is blue?", CHAT_FILTER_TEAMCHANGE ); - //============================================================================= - // HPE_BEGIN: - // [tj]Added a new filter checkbox for achievement announces. - // Also. Yes. Sky is blue. - //============================================================================= - - new CHudChatFilterCheckButton( this, "achivement_button", "Sky is blue?", CHAT_FILTER_ACHIEVEMENT); - - //============================================================================= - // HPE_END - //============================================================================= - -} - -void CHudChatFilterPanel::ApplySchemeSettings(vgui::IScheme *pScheme) -{ - LoadControlSettings( "resource/UI/ChatFilters.res" ); - - BaseClass::ApplySchemeSettings( pScheme ); - - Color cColor = pScheme->GetColor( "DullWhite", GetBgColor() ); - SetBgColor( Color ( cColor.r(), cColor.g(), cColor.b(), CHAT_HISTORY_ALPHA ) ); - - SetFgColor( pScheme->GetColor( "Blank", GetFgColor() ) ); -} - -void CHudChatFilterPanel::OnFilterButtonChecked( vgui::Panel *panel ) -{ - CHudChatFilterCheckButton *pButton = dynamic_cast < CHudChatFilterCheckButton * > ( panel ); - - if ( pButton && GetChatParent() && IsVisible() ) - { - if ( pButton->IsSelected() ) - { - GetChatParent()->SetFilterFlag( GetChatParent()->GetFilterFlags() | pButton->GetFilterFlag() ); - } - else - { - GetChatParent()->SetFilterFlag( GetChatParent()->GetFilterFlags() & ~ pButton->GetFilterFlag() ); - } - } -} - -void CHudChatFilterPanel::SetVisible(bool state) -{ - if ( state == true ) - { - for (int i = 0; i < GetChildCount(); i++) - { - CHudChatFilterCheckButton *pButton = dynamic_cast < CHudChatFilterCheckButton * > ( GetChild(i) ); - - if ( pButton ) - { - if ( cl_chatfilters.GetInt() & pButton->GetFilterFlag() ) - { - pButton->SetSelected( true ); - } - else - { - pButton->SetSelected( false ); - } - } - } - } - - BaseClass::SetVisible( state ); -} - -void CHudChatFilterButton::DoClick( void ) -{ - BaseClass::DoClick(); - - CBaseHudChat *pChat = dynamic_cast < CBaseHudChat * > (GetParent() ); - - if ( pChat ) - { - pChat->GetChatInput()->RequestFocus(); - - if ( pChat->GetChatFilterPanel() ) - { - if ( pChat->GetChatFilterPanel()->IsVisible() ) - { - pChat->GetChatFilterPanel()->SetVisible( false ); - } - else - { - pChat->GetChatFilterPanel()->SetVisible( true ); - pChat->GetChatFilterPanel()->MakePopup(); - pChat->GetChatFilterPanel()->SetMouseInputEnabled( true ); - } - } - } -} - -CHudChatHistory::CHudChatHistory( vgui::Panel *pParent, const char *panelName ) : BaseClass( pParent, "HudChatHistory" ) -{ - vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ChatScheme.res", "ChatScheme"); - SetScheme(scheme); - - InsertFade( -1, -1 ); -} - -void CHudChatHistory::ApplySchemeSettings( vgui::IScheme *pScheme ) -{ - BaseClass::ApplySchemeSettings( pScheme ); - - SetFont( pScheme->GetFont( "ChatFont" ) ); - SetAlpha( 255 ); -} - -int CBaseHudChat::m_nLineCounter = 1; -//----------------------------------------------------------------------------- -// Purpose: Text chat input/output hud element -//----------------------------------------------------------------------------- -CBaseHudChat::CBaseHudChat( const char *pElementName ) -: CHudElement( pElementName ), BaseClass( NULL, "HudChat" ) -{ - vgui::Panel *pParent = g_pClientMode->GetViewport(); - SetParent( pParent ); - - vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ChatScheme.res", "ChatScheme" ); - SetScheme(scheme); - - g_pVGuiLocalize->AddFile( "resource/chat_%language%.txt" ); - - m_nMessageMode = 0; - - vgui::ivgui()->AddTickSignal( GetVPanel() ); - - // (We don't actually want input until they bring up the chat line). - MakePopup(); - SetZPos( -30 ); - - SetHiddenBits( HIDEHUD_CHAT ); - - m_pFiltersButton = new CHudChatFilterButton( this, "ChatFiltersButton", "Filters" ); - - if ( m_pFiltersButton ) - { - m_pFiltersButton->SetScheme( scheme ); - m_pFiltersButton->SetVisible( true ); - m_pFiltersButton->SetEnabled( true ); - m_pFiltersButton->SetMouseInputEnabled( true ); - m_pFiltersButton->SetKeyBoardInputEnabled( false ); - } - - m_pChatHistory = new CHudChatHistory( this, "HudChatHistory" ); - - CreateChatLines(); - CreateChatInputLine(); - GetChatFilterPanel(); - - m_iFilterFlags = cl_chatfilters.GetInt(); -} - -void CBaseHudChat::CreateChatInputLine( void ) -{ -#ifndef _XBOX - m_pChatInput = new CBaseHudChatInputLine( this, "ChatInputLine" ); - m_pChatInput->SetVisible( false ); - - if ( GetChatHistory() ) - { - GetChatHistory()->SetMaximumCharCount( 127 * 100 ); - GetChatHistory()->SetVisible( true ); - } -#endif -} - -void CBaseHudChat::CreateChatLines( void ) -{ -#ifndef _XBOX - m_ChatLine = new CBaseHudChatLine( this, "ChatLine1" ); - m_ChatLine->SetVisible( false ); - -#endif -} - - -#define BACKGROUND_BORDER_WIDTH 20 - -CHudChatFilterPanel *CBaseHudChat::GetChatFilterPanel( void ) -{ - if ( m_pFilterPanel == NULL ) - { - m_pFilterPanel = new CHudChatFilterPanel( this, "HudChatFilterPanel" ); - - if ( m_pFilterPanel ) - { - vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ChatScheme.res", "ChatScheme"); - - m_pFilterPanel->SetScheme( scheme ); - m_pFilterPanel->InvalidateLayout( true, true ); - m_pFilterPanel->SetMouseInputEnabled( true ); - m_pFilterPanel->SetPaintBackgroundType( 2 ); - m_pFilterPanel->SetPaintBorderEnabled( true ); - m_pFilterPanel->SetVisible( false ); - } - } - - return m_pFilterPanel; -} - -void CBaseHudChat::ApplySchemeSettings( vgui::IScheme *pScheme ) -{ - LoadControlSettings( "resource/UI/BaseChat.res" ); - - BaseClass::ApplySchemeSettings( pScheme ); - - SetPaintBackgroundType( 2 ); - SetPaintBorderEnabled( true ); - SetPaintBackgroundEnabled( true ); - - SetKeyBoardInputEnabled( false ); - SetMouseInputEnabled( false ); - m_nVisibleHeight = 0; - -#ifdef HL1_CLIENT_DLL - SetBgColor( Color( 0, 0, 0, 0 ) ); - SetFgColor( Color( 0, 0, 0, 0 ) ); -#endif - - Color cColor = pScheme->GetColor( "DullWhite", GetBgColor() ); - SetBgColor( Color ( cColor.r(), cColor.g(), cColor.b(), CHAT_HISTORY_ALPHA ) ); - - GetChatHistory()->SetVerticalScrollbar( false ); -} - -void CBaseHudChat::Reset( void ) -{ -#ifndef HL1_CLIENT_DLL - m_nVisibleHeight = 0; - Clear(); -#endif -} - -#ifdef _XBOX -bool CBaseHudChat::ShouldDraw() -{ - // never think, never draw - return false; -} -#endif - -void CBaseHudChat::Paint( void ) -{ -#ifndef _XBOX - if ( m_nVisibleHeight == 0 ) - return; -#endif -} - -CHudChatHistory *CBaseHudChat::GetChatHistory( void ) -{ - return m_pChatHistory; -} - - - -void CBaseHudChat::Init( void ) -{ - if ( IsXbox() ) - return; - - ListenForGameEvent( "hltv_chat" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pszName - -// iSize - -// *pbuf - -//----------------------------------------------------------------------------- -void CBaseHudChat::MsgFunc_SayText( bf_read &msg ) -{ - char szString[256]; - - int client = msg.ReadByte(); - msg.ReadString( szString, sizeof(szString) ); - bool bWantsToChat = msg.ReadByte(); - - if ( bWantsToChat ) - { - // print raw chat text - ChatPrintf( client, CHAT_FILTER_NONE, "%s", szString ); - } - else - { - // try to lookup translated string - Printf( CHAT_FILTER_NONE, "%s", hudtextmessage->LookupString( szString ) ); - } - - CLocalPlayerFilter filter; - C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "HudChat.Message" ); - - Msg( "%s", szString ); -} - -int CBaseHudChat::GetFilterForString( const char *pString ) -{ - if ( !Q_stricmp( pString, "#HL_Name_Change" ) ) - { - return CHAT_FILTER_NAMECHANGE; - } - - return CHAT_FILTER_NONE; -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads in a player's Chat text from the server -//----------------------------------------------------------------------------- -void CBaseHudChat::MsgFunc_SayText2( bf_read &msg ) -{ - // Got message during connection - if ( !g_PR ) - return; - - int client = msg.ReadByte(); - bool bWantsToChat = msg.ReadByte(); - - wchar_t szBuf[6][256]; - char untranslated_msg_text[256]; - wchar_t *msg_text = ReadLocalizedString( msg, szBuf[0], sizeof( szBuf[0] ), false, untranslated_msg_text, sizeof( untranslated_msg_text ) ); - - // keep reading strings and using C format strings for subsituting the strings into the localised text string - ReadChatTextString ( msg, szBuf[1], sizeof( szBuf[1] ) ); // player name - ReadChatTextString ( msg, szBuf[2], sizeof( szBuf[2] ) ); // chat text - ReadLocalizedString( msg, szBuf[3], sizeof( szBuf[3] ), true ); - ReadLocalizedString( msg, szBuf[4], sizeof( szBuf[4] ), true ); - - g_pVGuiLocalize->ConstructString( szBuf[5], sizeof( szBuf[5] ), msg_text, 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); - - char ansiString[512]; - g_pVGuiLocalize->ConvertUnicodeToANSI( ConvertCRtoNL( szBuf[5] ), ansiString, sizeof( ansiString ) ); - - if ( bWantsToChat ) - { - int iFilter = CHAT_FILTER_NONE; - - if ( client > 0 && (g_PR->GetTeam( client ) != g_PR->GetTeam( GetLocalPlayerIndex() )) ) - { - iFilter = CHAT_FILTER_PUBLICCHAT; - } - - // print raw chat text - ChatPrintf( client, iFilter, "%s", ansiString ); - - Msg( "%s\n", RemoveColorMarkup(ansiString) ); - - CLocalPlayerFilter filter; - C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "HudChat.Message" ); - } - else - { - // print raw chat text - ChatPrintf( client, GetFilterForString( untranslated_msg_text), "%s", ansiString ); - } -} - -//----------------------------------------------------------------------------- -// Message handler for text messages -// displays a string, looking them up from the titles.txt file, which can be localised -// parameters: -// byte: message direction ( HUD_PRINTCONSOLE, HUD_PRINTNOTIFY, HUD_PRINTCENTER, HUD_PRINTTALK ) -// string: message -// optional parameters: -// string: message parameter 1 -// string: message parameter 2 -// string: message parameter 3 -// string: message parameter 4 -// any string that starts with the character '#' is a message name, and is used to look up the real message in titles.txt -// the next (optional) one to four strings are parameters for that string (which can also be message names if they begin with '#') -//----------------------------------------------------------------------------- -void CBaseHudChat::MsgFunc_TextMsg( bf_read &msg ) -{ - char szString[2048]; - int msg_dest = msg.ReadByte(); - - wchar_t szBuf[5][256]; - wchar_t outputBuf[256]; - - for ( int i=0; i<5; ++i ) - { - msg.ReadString( szString, sizeof(szString) ); - char *tmpStr = hudtextmessage->LookupString( szString, &msg_dest ); - const wchar_t *pBuf = g_pVGuiLocalize->Find( tmpStr ); - if ( pBuf ) - { - // Copy pBuf into szBuf[i]. - int nMaxChars = sizeof( szBuf[i] ) / sizeof( wchar_t ); - wcsncpy( szBuf[i], pBuf, nMaxChars ); - szBuf[i][nMaxChars-1] = 0; - } - else - { - if ( i ) - { - StripEndNewlineFromString( tmpStr ); // these strings are meant for subsitution into the main strings, so cull the automatic end newlines - } - g_pVGuiLocalize->ConvertANSIToUnicode( tmpStr, szBuf[i], sizeof(szBuf[i]) ); - } - } - - if ( !cl_showtextmsg.GetInt() ) - return; - - int len; - switch ( msg_dest ) - { - case HUD_PRINTCENTER: - g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); - internalCenterPrint->Print( ConvertCRtoNL( outputBuf ) ); - break; - - case HUD_PRINTNOTIFY: - g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); - g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); - len = strlen( szString ); - if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) - { - Q_strncat( szString, "\n", sizeof(szString), 1 ); - } - Msg( "%s", ConvertCRtoNL( szString ) ); - break; - - case HUD_PRINTTALK: - g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); - g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); - len = strlen( szString ); - if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) - { - Q_strncat( szString, "\n", sizeof(szString), 1 ); - } - Printf( CHAT_FILTER_NONE, "%s", ConvertCRtoNL( szString ) ); - Msg( "%s", ConvertCRtoNL( szString ) ); - break; - - case HUD_PRINTCONSOLE: - g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); - g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); - len = strlen( szString ); - if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) - { - Q_strncat( szString, "\n", sizeof(szString), 1 ); - } - Msg( "%s", ConvertCRtoNL( szString ) ); - break; - } -} - -void CBaseHudChat::MsgFunc_VoiceSubtitle( bf_read &msg ) -{ - // Got message during connection - if ( !g_PR ) - return; - - if ( !cl_showtextmsg.GetInt() ) - return; - - char szString[2048]; - char szPrefix[64]; //(Voice) - wchar_t szBuf[128]; - - int client = msg.ReadByte(); - int iMenu = msg.ReadByte(); - int iItem = msg.ReadByte(); - - const char *pszSubtitle = ""; - - CGameRules *pGameRules = GameRules(); - - CMultiplayRules *pMultiRules = dynamic_cast< CMultiplayRules * >( pGameRules ); - - Assert( pMultiRules ); - - if ( pMultiRules ) - { - pszSubtitle = pMultiRules->GetVoiceCommandSubtitle( iMenu, iItem ); - } - - SetVoiceSubtitleState( true ); - - const wchar_t *pBuf = g_pVGuiLocalize->Find( pszSubtitle ); - if ( pBuf ) - { - // Copy pBuf into szBuf[i]. - int nMaxChars = sizeof( szBuf ) / sizeof( wchar_t ); - wcsncpy( szBuf, pBuf, nMaxChars ); - szBuf[nMaxChars-1] = 0; - } - else - { - g_pVGuiLocalize->ConvertANSIToUnicode( pszSubtitle, szBuf, sizeof(szBuf) ); - } - - int len; - g_pVGuiLocalize->ConvertUnicodeToANSI( szBuf, szString, sizeof(szString) ); - len = strlen( szString ); - if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) - { - Q_strncat( szString, "\n", sizeof(szString), 1 ); - } - - const wchar_t *pVoicePrefix = g_pVGuiLocalize->Find( "#Voice" ); - g_pVGuiLocalize->ConvertUnicodeToANSI( pVoicePrefix, szPrefix, sizeof(szPrefix) ); - - ChatPrintf( client, CHAT_FILTER_NONE, "%c(%s) %s%c: %s", COLOR_PLAYERNAME, szPrefix, GetDisplayedSubtitlePlayerName( client ), COLOR_NORMAL, ConvertCRtoNL( szString ) ); - - SetVoiceSubtitleState( false ); -} - -const char *CBaseHudChat::GetDisplayedSubtitlePlayerName( int clientIndex ) -{ - return g_PR->GetPlayerName( clientIndex ); -} - -#ifndef _XBOX -static int __cdecl SortLines( void const *line1, void const *line2 ) -{ - CBaseHudChatLine *l1 = *( CBaseHudChatLine ** )line1; - CBaseHudChatLine *l2 = *( CBaseHudChatLine ** )line2; - - // Invisible at bottom - if ( l1->IsVisible() && !l2->IsVisible() ) - return -1; - else if ( !l1->IsVisible() && l2->IsVisible() ) - return 1; - - // Oldest start time at top - if ( l1->GetStartTime() < l2->GetStartTime() ) - return -1; - else if ( l1->GetStartTime() > l2->GetStartTime() ) - return 1; - - // Otherwise, compare counter - if ( l1->GetCount() < l2->GetCount() ) - return -1; - else if ( l1->GetCount() > l2->GetCount() ) - return 1; - - return 0; -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Allow inheriting classes to change this spacing behavior -//----------------------------------------------------------------------------- -int CBaseHudChat::GetChatInputOffset( void ) -{ - return m_iFontHeight; -} - -//----------------------------------------------------------------------------- -// Purpose: Do respositioning here to avoid latency due to repositioning of vgui -// voice manager icon panel -//----------------------------------------------------------------------------- -void CBaseHudChat::OnTick( void ) -{ -#ifndef _XBOX - m_nVisibleHeight = 0; - - CBaseHudChatLine *line = m_ChatLine; - - if ( line ) - { - vgui::HFont font = line->GetFont(); - m_iFontHeight = vgui::surface()->GetFontTall( font ) + 2; - - // Put input area at bottom - - int iChatX, iChatY, iChatW, iChatH; - int iInputX, iInputY, iInputW, iInputH; - - m_pChatInput->GetBounds( iInputX, iInputY, iInputW, iInputH ); - GetBounds( iChatX, iChatY, iChatW, iChatH ); - - m_pChatInput->SetBounds( iInputX, iChatH - (m_iFontHeight * 1.75), iInputW, m_iFontHeight ); - - //Resize the History Panel so it fits more lines depending on the screen resolution. - int iChatHistoryX, iChatHistoryY, iChatHistoryW, iChatHistoryH; - - GetChatHistory()->GetBounds( iChatHistoryX, iChatHistoryY, iChatHistoryW, iChatHistoryH ); - - iChatHistoryH = (iChatH - (m_iFontHeight * 2.25)) - iChatHistoryY; - - GetChatHistory()->SetBounds( iChatHistoryX, iChatHistoryY, iChatHistoryW, iChatHistoryH ); - } - - FadeChatHistory(); - -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : width - -// *text - -// textlen - -// Output : int -//----------------------------------------------------------------------------- -int CBaseHudChat::ComputeBreakChar( int width, const char *text, int textlen ) -{ -#ifndef _XBOX - CBaseHudChatLine *line = m_ChatLine; - vgui::HFont font = line->GetFont(); - - int currentlen = 0; - int lastbreak = textlen; - for (int i = 0; i < textlen ; i++) - { - char ch = text[i]; - - if ( ch <= 32 ) - { - lastbreak = i; - } - - wchar_t wch[2]; - - g_pVGuiLocalize->ConvertANSIToUnicode( &ch, wch, sizeof( wch ) ); - - int a,b,c; - - vgui::surface()->GetCharABCwide(font, wch[0], a, b, c); - currentlen += a + b + c; - - if ( currentlen >= width ) - { - // If we haven't found a whitespace char to break on before getting - // to the end, but it's still too long, break on the character just before - // this one - if ( lastbreak == textlen ) - { - lastbreak = MAX( 0, i - 1 ); - } - break; - } - } - - if ( currentlen >= width ) - { - return lastbreak; - } - return textlen; -#else - return 0; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fmt - -// ... - -//----------------------------------------------------------------------------- -void CBaseHudChat::Printf( int iFilter, const char *fmt, ... ) -{ - va_list marker; - char msg[4096]; - - va_start(marker, fmt); - Q_vsnprintf(msg, sizeof( msg), fmt, marker); - va_end(marker); - - ChatPrintf( 0, iFilter, "%s", msg ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHudChat::StartMessageMode( int iMessageModeType ) -{ -#ifndef _XBOX - m_nMessageMode = iMessageModeType; - - m_pChatInput->ClearEntry(); - - const wchar_t *pszPrompt = ( m_nMessageMode == MM_SAY ) ? g_pVGuiLocalize->Find( "#chat_say" ) : g_pVGuiLocalize->Find( "#chat_say_team" ); - if ( pszPrompt ) - { - m_pChatInput->SetPrompt( pszPrompt ); - } - else - { - if ( m_nMessageMode == MM_SAY ) - { - m_pChatInput->SetPrompt( L"Say :" ); - } - else - { - m_pChatInput->SetPrompt( L"Say (TEAM) :" ); - } - } - - if ( GetChatHistory() ) - { - GetChatHistory()->SetMouseInputEnabled( true ); - GetChatHistory()->SetKeyBoardInputEnabled( false ); - GetChatHistory()->SetVerticalScrollbar( true ); - GetChatHistory()->ResetAllFades( true ); - GetChatHistory()->SetPaintBorderEnabled( true ); - GetChatHistory()->SetVisible( true ); - } - - vgui::SETUP_PANEL( this ); - SetKeyBoardInputEnabled( true ); - SetMouseInputEnabled( true ); - m_pChatInput->SetVisible( true ); - vgui::surface()->CalculateMouseVisible(); - m_pChatInput->RequestFocus(); - m_pChatInput->SetPaintBorderEnabled( true ); - m_pChatInput->SetMouseInputEnabled( true ); - - //Place the mouse cursor near the text so people notice it. - int x, y, w, h; - GetChatHistory()->GetBounds( x, y, w, h ); - vgui::input()->SetCursorPos( x + ( w/2), y + (h/2) ); - - m_flHistoryFadeTime = gpGlobals->curtime + CHAT_HISTORY_FADE_TIME; - - m_pFilterPanel->SetVisible( false ); - - engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" ); - -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHudChat::StopMessageMode( void ) -{ -#ifndef _XBOX - - engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" ); - - SetKeyBoardInputEnabled( false ); - SetMouseInputEnabled( false ); - - if ( GetChatHistory() ) - { - GetChatHistory()->SetPaintBorderEnabled( false ); - GetChatHistory()->GotoTextEnd(); - GetChatHistory()->SetMouseInputEnabled( false ); - GetChatHistory()->SetVerticalScrollbar( false ); - GetChatHistory()->ResetAllFades( false, true, CHAT_HISTORY_FADE_TIME ); - GetChatHistory()->SelectNoText(); - } - - //Clear the entry since we wont need it anymore. - m_pChatInput->ClearEntry(); - - //hide filter panel - m_pFilterPanel->SetVisible( false ); - - m_flHistoryFadeTime = gpGlobals->curtime + CHAT_HISTORY_FADE_TIME; - - m_nMessageMode = MM_NONE; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHudChat::OnChatEntrySend( void ) -{ - Send(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHudChat::OnChatEntryStopMessageMode( void ) -{ - StopMessageMode(); -} - -void CBaseHudChat::FadeChatHistory( void ) -{ - float frac = ( m_flHistoryFadeTime - gpGlobals->curtime ) / CHAT_HISTORY_FADE_TIME; - - int alpha = frac * CHAT_HISTORY_ALPHA; - alpha = clamp( alpha, 0, CHAT_HISTORY_ALPHA ); - - if ( alpha >= 0 ) - { - if ( GetChatHistory() ) - { - if ( IsMouseInputEnabled() ) - { - SetAlpha( 255 ); - GetChatHistory()->SetBgColor( Color( 0, 0, 0, CHAT_HISTORY_ALPHA - alpha ) ); - m_pChatInput->GetPrompt()->SetAlpha( (CHAT_HISTORY_ALPHA*2) - alpha ); - m_pChatInput->GetInputPanel()->SetAlpha( (CHAT_HISTORY_ALPHA*2) - alpha ); - SetBgColor( Color( GetBgColor().r(), GetBgColor().g(), GetBgColor().b(), CHAT_HISTORY_ALPHA - alpha ) ); - m_pFiltersButton->SetAlpha( (CHAT_HISTORY_ALPHA*2) - alpha ); - } - else - { - GetChatHistory()->SetBgColor( Color( 0, 0, 0, alpha ) ); - SetBgColor( Color( GetBgColor().r(), GetBgColor().g(), GetBgColor().b(), alpha ) ); - - m_pChatInput->GetPrompt()->SetAlpha( alpha ); - m_pChatInput->GetInputPanel()->SetAlpha( alpha ); - m_pFiltersButton->SetAlpha( alpha ); - } - } - } -} - -void CBaseHudChat::SetFilterFlag( int iFilter ) -{ - m_iFilterFlags = iFilter; - - cl_chatfilters.SetValue( m_iFilterFlags ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Color CBaseHudChat::GetTextColorForClient( TextColor colorNum, int clientIndex ) -{ - Color c; - switch ( colorNum ) - { - case COLOR_CUSTOM: - c = m_ColorCustom; - break; - - case COLOR_PLAYERNAME: - c = GetClientColor( clientIndex ); - break; - - case COLOR_LOCATION: - c = g_ColorDarkGreen; - break; - - case COLOR_ACHIEVEMENT: - { - vgui::IScheme *pSourceScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "SourceScheme" ) ); - if ( pSourceScheme ) - { - c = pSourceScheme->GetColor( "SteamLightGreen", GetBgColor() ); - } - else - { - c = GetDefaultTextColor(); - } - } - break; - - default: - c = GetDefaultTextColor(); - } - - return Color( c[0], c[1], c[2], 255 ); -} - -//----------------------------------------------------------------------------- -void CBaseHudChat::SetCustomColor( const char *pszColorName ) -{ - vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "ClientScheme" ) ); - SetCustomColor( pScheme->GetColor( pszColorName, Color(255,255,255,255) ) ); -} - -//----------------------------------------------------------------------------- -Color CBaseHudChat::GetDefaultTextColor( void ) -{ - return g_ColorYellow; -} - -//----------------------------------------------------------------------------- -Color CBaseHudChat::GetClientColor( int clientIndex ) -{ - if ( clientIndex == 0 ) // console msg - { - return g_ColorGreen; - } - else if( g_PR ) - { - return g_ColorGrey; - } - - return g_ColorYellow; -} - -//----------------------------------------------------------------------------- -// Purpose: Parses a line of text for color markup and inserts it via Colorize() -//----------------------------------------------------------------------------- -void CBaseHudChatLine::InsertAndColorizeText( wchar_t *buf, int clientIndex ) -{ - if ( m_text ) - { - delete[] m_text; - m_text = NULL; - } - m_textRanges.RemoveAll(); - - m_text = CloneWString( buf ); - - CBaseHudChat *pChat = dynamic_cast(GetParent() ); - - if ( pChat == NULL ) - return; - - wchar_t *txt = m_text; - int lineLen = wcslen( m_text ); - Color colCustom; - if ( m_text[0] == COLOR_PLAYERNAME || m_text[0] == COLOR_LOCATION || m_text[0] == COLOR_NORMAL || m_text[0] == COLOR_ACHIEVEMENT || m_text[0] == COLOR_CUSTOM || m_text[0] == COLOR_HEXCODE || m_text[0] == COLOR_HEXCODE_ALPHA ) - { - while ( txt && *txt ) - { - TextRange range; - bool bFoundColorCode = false; - bool bDone = false; - int nBytesIn = txt - m_text; - - switch ( *txt ) - { - case COLOR_CUSTOM: - case COLOR_PLAYERNAME: - case COLOR_LOCATION: - case COLOR_ACHIEVEMENT: - case COLOR_NORMAL: - { - // save this start - range.start = nBytesIn + 1; - range.color = pChat->GetTextColorForClient( (TextColor)(*txt), clientIndex ); - range.end = lineLen; - bFoundColorCode = true; - } - ++txt; - break; - case COLOR_HEXCODE: - case COLOR_HEXCODE_ALPHA: - { - bool bReadAlpha = ( *txt == COLOR_HEXCODE_ALPHA ); - const int nCodeBytes = ( bReadAlpha ? 8 : 6 ); - range.start = nBytesIn + nCodeBytes + 1; - range.end = lineLen; - range.preserveAlpha = bReadAlpha; - ++txt; - - if ( range.end > range.start ) - { - int r = V_nibble( txt[0] ) << 4 | V_nibble( txt[1] ); - int g = V_nibble( txt[2] ) << 4 | V_nibble( txt[3] ); - int b = V_nibble( txt[4] ) << 4 | V_nibble( txt[5] ); - int a = 255; - - if ( bReadAlpha ) - { - a = V_nibble( txt[6] ) << 4 | V_nibble( txt[7] ); - } - - range.color = Color( r, g, b, a ); - bFoundColorCode = true; - - txt += nCodeBytes; - } - else - { - // Not enough characters remaining for a hex code. Skip the rest of the string. - bDone = true; - } - } - break; - default: - ++txt; - } - - if ( bDone ) - { - break; - } - - if ( bFoundColorCode ) - { - int count = m_textRanges.Count(); - if ( count ) - { - m_textRanges[count-1].end = nBytesIn; - } - - m_textRanges.AddToTail( range ); - } - } - } - - if ( !m_textRanges.Count() && m_iNameLength > 0 && m_text[0] == COLOR_USEOLDCOLORS ) - { - TextRange range; - range.start = 0; - range.end = m_iNameStart; - range.color = pChat->GetTextColorForClient( COLOR_NORMAL, clientIndex ); - m_textRanges.AddToTail( range ); - - range.start = m_iNameStart; - range.end = m_iNameStart + m_iNameLength; - range.color = pChat->GetTextColorForClient( COLOR_PLAYERNAME, clientIndex ); - m_textRanges.AddToTail( range ); - - range.start = range.end; - range.end = wcslen( m_text ); - range.color = pChat->GetTextColorForClient( COLOR_NORMAL, clientIndex ); - m_textRanges.AddToTail( range ); - } - - if ( !m_textRanges.Count() ) - { - TextRange range; - range.start = 0; - range.end = wcslen( m_text ); - range.color = pChat->GetTextColorForClient( COLOR_NORMAL, clientIndex ); - m_textRanges.AddToTail( range ); - } - - for ( int i=0; i 0 && *start < COLOR_MAX ) - { - Assert( *start != COLOR_HEXCODE && *start != COLOR_HEXCODE_ALPHA ); - m_textRanges[i].start += 1; - } - } - - Colorize(); -} - -//----------------------------------------------------------------------------- -// Purpose: Inserts colored text into the RichText control at the given alpha -//----------------------------------------------------------------------------- -void CBaseHudChatLine::Colorize( int alpha ) -{ - // clear out text - SetText( "" ); - - CBaseHudChat *pChat = dynamic_cast(GetParent() ); - - if ( pChat && pChat->GetChatHistory() ) - { - pChat->GetChatHistory()->InsertString( "\n" ); - } - - wchar_t wText[4096]; - Color color; - for ( int i=0; i 1 && len <= ARRAYSIZE( wText ) ) - { - wcsncpy( wText, start, len ); - wText[len-1] = 0; - color = m_textRanges[i].color; - if ( !m_textRanges[i].preserveAlpha ) - { - color[3] = alpha; - } - - InsertColorChange( color ); - InsertString( wText ); - - CBaseHudChat *pChat = dynamic_cast(GetParent() ); - - if ( pChat && pChat->GetChatHistory() ) - { - pChat->GetChatHistory()->InsertColorChange( color ); - pChat->GetChatHistory()->InsertString( wText ); - pChat->GetChatHistory()->InsertFade( hud_saytext_time.GetFloat(), CHAT_HISTORY_IDLE_FADE_TIME ); - - if ( i == m_textRanges.Count()-1 ) - { - pChat->GetChatHistory()->InsertFade( -1, -1 ); - } - } - - } - } - - InvalidateLayout( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseHudChatLine -//----------------------------------------------------------------------------- -CBaseHudChatLine *CBaseHudChat::FindUnusedChatLine( void ) -{ -#ifndef _XBOX - return m_ChatLine; -#else - return NULL; -#endif -} - -void CBaseHudChat::Send( void ) -{ -#ifndef _XBOX - wchar_t szTextbuf[128]; - - m_pChatInput->GetMessageText( szTextbuf, sizeof( szTextbuf ) ); - - char ansi[128]; - g_pVGuiLocalize->ConvertUnicodeToANSI( szTextbuf, ansi, sizeof( ansi ) ); - - int len = Q_strlen(ansi); - - /* -This is a very long string that I am going to attempt to paste into the cs hud chat entry and we will see if it gets cropped or not. - */ - - // remove the \n - if ( len > 0 && - ansi[ len - 1 ] == '\n' ) - { - ansi[ len - 1 ] = '\0'; - } - - if( len > 0 ) - { - // Let the game rules at it - if ( GameRules() ) - { - GameRules()->ModifySentChat( ansi, ARRAYSIZE(ansi) ); - } - - char szbuf[144]; // more than 128 - Q_snprintf( szbuf, sizeof(szbuf), "%s \"%s\"", m_nMessageMode == MM_SAY ? "say" : "say_team", ansi ); - - engine->ClientCmd_Unrestricted(szbuf); - } - - m_pChatInput->ClearEntry(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : vgui::Panel -//----------------------------------------------------------------------------- -vgui::Panel *CBaseHudChat::GetInputPanel( void ) -{ -#ifndef _XBOX - return m_pChatInput->GetInputPanel(); -#else - return NULL; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHudChat::Clear( void ) -{ -#ifndef _XBOX - // Kill input prompt - StopMessageMode(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *newmap - -//----------------------------------------------------------------------------- -void CBaseHudChat::LevelInit( const char *newmap ) -{ - Clear(); - - //============================================================================= - // HPE_BEGIN: - // [pfreese] initialize new chat filters to defaults. We do this because - // unused filter bits are zero, and we might want them on for new filters that - // are added. - // - // Also, we have to do this here instead of somewhere more sensible like the - // c'tor or Init() method, because cvars are currently loaded twice: once - // during initialization from the local file, and later (after HUD elements - // have been construction and initialized) from Steam Cloud remote storage. - //============================================================================= - - switch ( cl_chatfilter_version.GetInt() ) - { - case 0: - m_iFilterFlags |= CHAT_FILTER_ACHIEVEMENT; - // fall through - case kChatFilterVersion: - break; - } - - if ( cl_chatfilter_version.GetInt() != kChatFilterVersion ) - { - cl_chatfilters.SetValue( m_iFilterFlags ); - cl_chatfilter_version.SetValue( kChatFilterVersion ); - } - - //============================================================================= - // HPE_END - //============================================================================= -} - -void CBaseHudChat::LevelShutdown( void ) -{ - Clear(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fmt - -// ... - -//----------------------------------------------------------------------------- -void CBaseHudChat::ChatPrintf( int iPlayerIndex, int iFilter, const char *fmt, ... ) -{ - va_list marker; - char msg[4096]; - - va_start(marker, fmt); - Q_vsnprintf(msg, sizeof( msg), fmt, marker); - va_end(marker); - - // Strip any trailing '\n' - if ( strlen( msg ) > 0 && msg[ strlen( msg )-1 ] == '\n' ) - { - msg[ strlen( msg ) - 1 ] = 0; - } - - // Strip leading \n characters ( or notify/color signifiers ) for empty string check - char *pmsg = msg; - while ( *pmsg && ( *pmsg == '\n' || ( *pmsg > 0 && *pmsg < COLOR_MAX ) ) ) - { - pmsg++; - } - - if ( !*pmsg ) - return; - - // Now strip just newlines, since we want the color info for printing - pmsg = msg; - while ( *pmsg && ( *pmsg == '\n' ) ) - { - pmsg++; - } - - if ( !*pmsg ) - return; - - CBaseHudChatLine *line = (CBaseHudChatLine *)FindUnusedChatLine(); - if ( !line ) - { - line = (CBaseHudChatLine *)FindUnusedChatLine(); - } - - if ( !line ) - { - return; - } - - if ( iFilter != CHAT_FILTER_NONE ) - { - if ( !(iFilter & GetFilterFlags() ) ) - return; - } - - if ( *pmsg < 32 ) - { - hudlcd->AddChatLine( pmsg + 1 ); - } - else - { - hudlcd->AddChatLine( pmsg ); - } - - line->SetText( "" ); - - int iNameStart = 0; - int iNameLength = 0; - - player_info_t sPlayerInfo; - if ( iPlayerIndex == 0 ) - { - Q_memset( &sPlayerInfo, 0, sizeof(player_info_t) ); - Q_strncpy( sPlayerInfo.name, "Console", sizeof(sPlayerInfo.name) ); - } - else - { - engine->GetPlayerInfo( iPlayerIndex, &sPlayerInfo ); - } - - int bufSize = (strlen( pmsg ) + 1 ) * sizeof(wchar_t); - wchar_t *wbuf = static_cast( _alloca( bufSize ) ); - if ( wbuf ) - { - Color clrNameColor = GetClientColor( iPlayerIndex ); - - line->SetExpireTime(); - - g_pVGuiLocalize->ConvertANSIToUnicode( pmsg, wbuf, bufSize); - - // find the player's name in the unicode string, in case there is no color markup - const char *pName = sPlayerInfo.name; - - if ( pName ) - { - wchar_t wideName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( pName, wideName, sizeof( wideName ) ); - - const wchar_t *nameInString = wcsstr( wbuf, wideName ); - - if ( nameInString ) - { - iNameStart = (nameInString - wbuf); - iNameLength = wcslen( wideName ); - } - } - - line->SetVisible( false ); - line->SetNameStart( iNameStart ); - line->SetNameLength( iNameLength ); - line->SetNameColor( clrNameColor ); - - line->InsertAndColorizeText( wbuf, iPlayerIndex ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHudChat::FireGameEvent( IGameEvent *event ) -{ -#ifndef _XBOX - const char *eventname = event->GetName(); - - if ( Q_strcmp( "hltv_chat", eventname ) == 0 ) - { - C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); - - if ( !player ) - return; - - ChatPrintf( player->entindex(), CHAT_FILTER_NONE, "(SourceTV) %s", event->GetString( "text" ) ); - } -#endif +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "hud_basechat.h" + +#include +#include +#include "iclientmode.h" +#include "hud_macros.h" +#include "engine/IEngineSound.h" +#include "text_message.h" +#include +#include "vguicenterprint.h" +#include "vgui/KeyCode.h" +#include +#include "ienginevgui.h" +#include "c_playerresource.h" +#include "ihudlcd.h" +#include "vgui/IInput.h" +#include "vgui/ILocalize.h" +#include "multiplay_gamerules.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define CHAT_WIDTH_PERCENTAGE 0.6f + +#ifndef _XBOX +ConVar hud_saytext_time( "hud_saytext_time", "12", 0 ); +ConVar cl_showtextmsg( "cl_showtextmsg", "1", 0, "Enable/disable text messages printing on the screen." ); +ConVar cl_chatfilters( "cl_chatfilters", "63", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Stores the chat filter settings " ); +ConVar cl_chatfilter_version( "cl_chatfilter_version", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE | FCVAR_HIDDEN, "Stores the chat filter version" ); + +const int kChatFilterVersion = 1; + +Color g_ColorBlue( 153, 204, 255, 255 ); +Color g_ColorRed( 255, 63, 63, 255 ); +Color g_ColorGreen( 153, 255, 153, 255 ); +Color g_ColorDarkGreen( 64, 255, 64, 255 ); +Color g_ColorYellow( 255, 178, 0, 255 ); +Color g_ColorGrey( 204, 204, 204, 255 ); + + +// removes all color markup characters, so Msg can deal with the string properly +// returns a pointer to str +char* RemoveColorMarkup( char *str ) +{ + char *out = str; + for ( char *in = str; *in != 0; ++in ) + { + if ( *in > 0 && *in < COLOR_MAX ) + { + if ( *in == COLOR_HEXCODE || *in == COLOR_HEXCODE_ALPHA ) + { + // skip the next six or eight characters + const int nSkip = ( *in == COLOR_HEXCODE ? 6 : 8 ); + for ( int i = 0; i < nSkip && *in != 0; i++ ) + { + ++in; + } + + // if we reached the end of the string first, then back up + if ( *in == 0 ) + { + --in; + } + } + + continue; + } + *out = *in; + ++out; + } + *out = 0; + + return str; +} + +// converts all '\r' characters to '\n', so that the engine can deal with the properly +// returns a pointer to str +char* ConvertCRtoNL( char *str ) +{ + for ( char *ch = str; *ch != 0; ch++ ) + if ( *ch == '\r' ) + *ch = '\n'; + return str; +} + +// converts all '\r' characters to '\n', so that the engine can deal with the properly +// returns a pointer to str +wchar_t* ConvertCRtoNL( wchar_t *str ) +{ + for ( wchar_t *ch = str; *ch != 0; ch++ ) + if ( *ch == L'\r' ) + *ch = L'\n'; + return str; +} + +void StripEndNewlineFromString( char *str ) +{ + int s = strlen( str ) - 1; + if ( s >= 0 ) + { + if ( str[s] == '\n' || str[s] == '\r' ) + str[s] = 0; + } +} + +void StripEndNewlineFromString( wchar_t *str ) +{ + int s = wcslen( str ) - 1; + if ( s >= 0 ) + { + if ( str[s] == L'\n' || str[s] == L'\r' ) + str[s] = 0; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Reads a string from the current message and checks if it is translatable +//----------------------------------------------------------------------------- +wchar_t* ReadLocalizedString( bf_read &msg, OUT_Z_BYTECAP(outSizeInBytes) wchar_t *pOut, int outSizeInBytes, bool bStripNewline, OUT_Z_CAP(originalSize) char *originalString, int originalSize ) +{ + char szString[2048]; + szString[0] = 0; + msg.ReadString( szString, sizeof(szString) ); + + if ( originalString ) + { + Q_strncpy( originalString, szString, originalSize ); + } + + const wchar_t *pBuf = g_pVGuiLocalize->Find( szString ); + if ( pBuf ) + { + V_wcsncpy( pOut, pBuf, outSizeInBytes ); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode( szString, pOut, outSizeInBytes ); + } + + if ( bStripNewline ) + StripEndNewlineFromString( pOut ); + + return pOut; +} + +//----------------------------------------------------------------------------- +// Purpose: Reads a string from the current message, converts it to unicode, and strips out color codes +//----------------------------------------------------------------------------- +wchar_t* ReadChatTextString( bf_read &msg, OUT_Z_BYTECAP(outSizeInBytes) wchar_t *pOut, int outSizeInBytes ) +{ + char szString[2048]; + szString[0] = 0; + msg.ReadString( szString, sizeof(szString) ); + + g_pVGuiLocalize->ConvertANSIToUnicode( szString, pOut, outSizeInBytes ); + + StripEndNewlineFromString( pOut ); + + // converts color control characters into control characters for the normal color + for ( wchar_t *test = pOut; test && *test; ++test ) + { + if ( *test && (*test < COLOR_MAX ) ) + { + if ( *test == COLOR_HEXCODE || *test == COLOR_HEXCODE_ALPHA ) + { + // mark the next seven or nine characters. one for the control character and six or eight for the code itself. + const int nSkip = ( *test == COLOR_HEXCODE ? 7 : 9 ); + for ( int i = 0; i < nSkip && *test != 0; i++, test++ ) + { + *test = COLOR_NORMAL; + } + + // if we reached the end of the string first, then back up + if ( *test == 0 ) + { + --test; + } + } + else + { + *test = COLOR_NORMAL; + } + } + } + + return pOut; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// *panelName - +//----------------------------------------------------------------------------- +CBaseHudChatLine::CBaseHudChatLine( vgui::Panel *parent, const char *panelName ) : + vgui::RichText( parent, panelName ) +{ + m_hFont = m_hFontMarlett = 0; + m_flExpireTime = 0.0f; + m_flStartTime = 0.0f; + m_iNameLength = 0; + m_text = NULL; + + SetPaintBackgroundEnabled( true ); + + SetVerticalScrollbar( false ); +} + +CBaseHudChatLine::~CBaseHudChatLine() +{ + if ( m_text ) + { + delete[] m_text; + m_text = NULL; + } +} + + +void CBaseHudChatLine::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + m_hFont = pScheme->GetFont( "Default" ); + +#ifdef HL1_CLIENT_DLL + SetBgColor( Color( 0, 0, 0, 0 ) ); + SetFgColor( Color( 0, 0, 0, 0 ) ); + + SetBorder( NULL ); +#else + SetBgColor( Color( 0, 0, 0, 100 ) ); +#endif + + + m_hFontMarlett = pScheme->GetFont( "Marlett" ); + + m_clrText = pScheme->GetColor( "FgColor", GetFgColor() ); + SetFont( m_hFont ); +} + + +void CBaseHudChatLine::PerformFadeout( void ) +{ + // Flash + Extra bright when new + float curtime = gpGlobals->curtime; + + int lr = m_clrText[0]; + int lg = m_clrText[1]; + int lb = m_clrText[2]; + + if ( curtime >= m_flStartTime && curtime < m_flStartTime + CHATLINE_FLASH_TIME ) + { + float frac1 = ( curtime - m_flStartTime ) / CHATLINE_FLASH_TIME; + float frac = frac1; + + frac *= CHATLINE_NUM_FLASHES; + frac *= 2 * M_PI; + + frac = cos( frac ); + + frac = clamp( frac, 0.0f, 1.0f ); + + frac *= (1.0f-frac1); + + int r = lr, g = lg, b = lb; + + r = r + ( 255 - r ) * frac; + g = g + ( 255 - g ) * frac; + b = b + ( 255 - b ) * frac; + + // Draw a right facing triangle in red, faded out over time + int alpha = 63 + 192 * (1.0f - frac1 ); + alpha = clamp( alpha, 0, 255 ); + + wchar_t wbuf[4096]; + GetText(0, wbuf, sizeof(wbuf)); + + SetText( "" ); + + InsertColorChange( Color( r, g, b, 255 ) ); + InsertString( wbuf ); + } + else if ( curtime <= m_flExpireTime && curtime > m_flExpireTime - CHATLINE_FADE_TIME ) + { + float frac = ( m_flExpireTime - curtime ) / CHATLINE_FADE_TIME; + + int alpha = frac * 255; + alpha = clamp( alpha, 0, 255 ); + + wchar_t wbuf[4096]; + GetText(0, wbuf, sizeof(wbuf)); + + SetText( "" ); + + InsertColorChange( Color( lr * frac, lg * frac, lb * frac, alpha ) ); + InsertString( wbuf ); + } + else + { + wchar_t wbuf[4096]; + GetText(0, wbuf, sizeof(wbuf)); + + SetText( "" ); + + InsertColorChange( Color( lr, lg, lb, 255 ) ); + InsertString( wbuf ); + } + + OnThink(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : time - +//----------------------------------------------------------------------------- +void CBaseHudChatLine::SetExpireTime( void ) +{ + m_flStartTime = gpGlobals->curtime; + m_flExpireTime = m_flStartTime + hud_saytext_time.GetFloat(); + m_nCount = CBaseHudChat::m_nLineCounter++; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CBaseHudChatLine::GetCount( void ) +{ + return m_nCount; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CBaseHudChatLine::IsReadyToExpire( void ) +{ + // Engine disconnected, expire right away + if ( !engine->IsInGame() && !engine->IsConnected() ) + return true; + + if ( gpGlobals->curtime >= m_flExpireTime ) + return true; + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CBaseHudChatLine::GetStartTime( void ) +{ + return m_flStartTime; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseHudChatLine::Expire( void ) +{ + SetVisible( false ); + + // Spit out label text now +// char text[ 256 ]; +// GetText( text, 256 ); + +// Msg( "%s\n", text ); +} +#endif // _XBOX + +//----------------------------------------------------------------------------- +// Purpose: The prompt and text entry area for chat messages +//----------------------------------------------------------------------------- +#ifndef _XBOX +CBaseHudChatInputLine::CBaseHudChatInputLine( vgui::Panel *parent, char const *panelName ) : + vgui::Panel( parent, panelName ) +{ + SetMouseInputEnabled( false ); + + m_pPrompt = new vgui::Label( this, "ChatInputPrompt", L"Enter text:" ); + + m_pInput = new CBaseHudChatEntry( this, "ChatInput", parent ); + m_pInput->SetMaximumCharCount( 127 ); +} + +void CBaseHudChatInputLine::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + // FIXME: Outline + vgui::HFont hFont = pScheme->GetFont( "ChatFont" ); + + m_pPrompt->SetFont( hFont ); + m_pInput->SetFont( hFont ); + + m_pInput->SetFgColor( pScheme->GetColor( "Chat.TypingText", pScheme->GetColor( "Panel.FgColor", Color( 255, 255, 255, 255 ) ) ) ); + + SetPaintBackgroundEnabled( true ); + m_pPrompt->SetPaintBackgroundEnabled( true ); + m_pPrompt->SetContentAlignment( vgui::Label::a_west ); + m_pPrompt->SetTextInset( 2, 0 ); + + m_pInput->SetMouseInputEnabled( true ); + +#ifdef HL1_CLIENT_DLL + m_pInput->SetBgColor( Color( 255, 255, 255, 0 ) ); +#endif + + SetBgColor( Color( 0, 0, 0, 0) ); + +} + +void CBaseHudChatInputLine::SetPrompt( const wchar_t *prompt ) +{ + Assert( m_pPrompt ); + m_pPrompt->SetText( prompt ); + InvalidateLayout(); +} + +void CBaseHudChatInputLine::ClearEntry( void ) +{ + Assert( m_pInput ); + SetEntry( L"" ); +} + +void CBaseHudChatInputLine::SetEntry( const wchar_t *entry ) +{ + Assert( m_pInput ); + Assert( entry ); + + m_pInput->SetText( entry ); +} + +void CBaseHudChatInputLine::GetMessageText( OUT_Z_BYTECAP(buffersizebytes) wchar_t *buffer, int buffersizebytes ) +{ + m_pInput->GetText( buffer, buffersizebytes); +} + +void CBaseHudChatInputLine::PerformLayout() +{ + BaseClass::PerformLayout(); + + int wide, tall; + GetSize( wide, tall ); + + int w,h; + m_pPrompt->GetContentSize( w, h); + m_pPrompt->SetBounds( 0, 0, w, tall ); + + m_pInput->SetBounds( w + 2, 0, wide - w - 2 , tall ); +} + +vgui::Panel *CBaseHudChatInputLine::GetInputPanel( void ) +{ + return m_pInput; +} +#endif //_XBOX + + +CHudChatFilterButton::CHudChatFilterButton( vgui::Panel *pParent, const char *pName, const char *pText ) : +BaseClass( pParent, pName, pText ) +{ +} + +CHudChatFilterCheckButton::CHudChatFilterCheckButton( vgui::Panel *pParent, const char *pName, const char *pText, int iFlag ) : +BaseClass( pParent, pName, pText ) +{ + m_iFlag = iFlag; +} + + +CHudChatFilterPanel::CHudChatFilterPanel( vgui::Panel *pParent, const char *pName ) : BaseClass ( pParent, pName ) +{ + pParent->SetSize( 10, 10 ); // Quiet "parent not sized yet" spew + SetParent( pParent ); + + new CHudChatFilterCheckButton( this, "joinleave_button", "Sky is blue?", CHAT_FILTER_JOINLEAVE ); + new CHudChatFilterCheckButton( this, "namechange_button", "Sky is blue?", CHAT_FILTER_NAMECHANGE ); + new CHudChatFilterCheckButton( this, "publicchat_button", "Sky is blue?", CHAT_FILTER_PUBLICCHAT ); + new CHudChatFilterCheckButton( this, "servermsg_button", "Sky is blue?", CHAT_FILTER_SERVERMSG ); + new CHudChatFilterCheckButton( this, "teamchange_button", "Sky is blue?", CHAT_FILTER_TEAMCHANGE ); + //============================================================================= + // HPE_BEGIN: + // [tj]Added a new filter checkbox for achievement announces. + // Also. Yes. Sky is blue. + //============================================================================= + + new CHudChatFilterCheckButton( this, "achivement_button", "Sky is blue?", CHAT_FILTER_ACHIEVEMENT); + + //============================================================================= + // HPE_END + //============================================================================= + +} + +void CHudChatFilterPanel::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + LoadControlSettings( "resource/UI/ChatFilters.res" ); + + BaseClass::ApplySchemeSettings( pScheme ); + + Color cColor = pScheme->GetColor( "DullWhite", GetBgColor() ); + SetBgColor( Color ( cColor.r(), cColor.g(), cColor.b(), CHAT_HISTORY_ALPHA ) ); + + SetFgColor( pScheme->GetColor( "Blank", GetFgColor() ) ); +} + +void CHudChatFilterPanel::OnFilterButtonChecked( vgui::Panel *panel ) +{ + CHudChatFilterCheckButton *pButton = dynamic_cast < CHudChatFilterCheckButton * > ( panel ); + + if ( pButton && GetChatParent() && IsVisible() ) + { + if ( pButton->IsSelected() ) + { + GetChatParent()->SetFilterFlag( GetChatParent()->GetFilterFlags() | pButton->GetFilterFlag() ); + } + else + { + GetChatParent()->SetFilterFlag( GetChatParent()->GetFilterFlags() & ~ pButton->GetFilterFlag() ); + } + } +} + +void CHudChatFilterPanel::SetVisible(bool state) +{ + if ( state == true ) + { + for (int i = 0; i < GetChildCount(); i++) + { + CHudChatFilterCheckButton *pButton = dynamic_cast < CHudChatFilterCheckButton * > ( GetChild(i) ); + + if ( pButton ) + { + if ( cl_chatfilters.GetInt() & pButton->GetFilterFlag() ) + { + pButton->SetSelected( true ); + } + else + { + pButton->SetSelected( false ); + } + } + } + } + + BaseClass::SetVisible( state ); +} + +void CHudChatFilterButton::DoClick( void ) +{ + BaseClass::DoClick(); + + CBaseHudChat *pChat = dynamic_cast < CBaseHudChat * > (GetParent() ); + + if ( pChat ) + { + pChat->GetChatInput()->RequestFocus(); + + if ( pChat->GetChatFilterPanel() ) + { + if ( pChat->GetChatFilterPanel()->IsVisible() ) + { + pChat->GetChatFilterPanel()->SetVisible( false ); + } + else + { + pChat->GetChatFilterPanel()->SetVisible( true ); + pChat->GetChatFilterPanel()->MakePopup(); + pChat->GetChatFilterPanel()->SetMouseInputEnabled( true ); + } + } + } +} + +CHudChatHistory::CHudChatHistory( vgui::Panel *pParent, const char *panelName ) : BaseClass( pParent, "HudChatHistory" ) +{ + vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ChatScheme.res", "ChatScheme"); + SetScheme(scheme); + + InsertFade( -1, -1 ); +} + +void CHudChatHistory::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + SetFont( pScheme->GetFont( "ChatFont" ) ); + SetAlpha( 255 ); +} + +int CBaseHudChat::m_nLineCounter = 1; +//----------------------------------------------------------------------------- +// Purpose: Text chat input/output hud element +//----------------------------------------------------------------------------- +CBaseHudChat::CBaseHudChat( const char *pElementName ) +: CHudElement( pElementName ), BaseClass( NULL, "HudChat" ) +{ + vgui::Panel *pParent = g_pClientMode->GetViewport(); + SetParent( pParent ); + + vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ChatScheme.res", "ChatScheme" ); + SetScheme(scheme); + + g_pVGuiLocalize->AddFile( "resource/chat_%language%.txt" ); + + m_nMessageMode = 0; + + vgui::ivgui()->AddTickSignal( GetVPanel() ); + + // (We don't actually want input until they bring up the chat line). + MakePopup(); + SetZPos( -30 ); + + SetHiddenBits( HIDEHUD_CHAT ); + + m_pFiltersButton = new CHudChatFilterButton( this, "ChatFiltersButton", "Filters" ); + + if ( m_pFiltersButton ) + { + m_pFiltersButton->SetScheme( scheme ); + m_pFiltersButton->SetVisible( true ); + m_pFiltersButton->SetEnabled( true ); + m_pFiltersButton->SetMouseInputEnabled( true ); + m_pFiltersButton->SetKeyBoardInputEnabled( false ); + } + + m_pChatHistory = new CHudChatHistory( this, "HudChatHistory" ); + + CreateChatLines(); + CreateChatInputLine(); + GetChatFilterPanel(); + + m_iFilterFlags = cl_chatfilters.GetInt(); +} + +void CBaseHudChat::CreateChatInputLine( void ) +{ +#ifndef _XBOX + m_pChatInput = new CBaseHudChatInputLine( this, "ChatInputLine" ); + m_pChatInput->SetVisible( false ); + + if ( GetChatHistory() ) + { + GetChatHistory()->SetMaximumCharCount( 127 * 100 ); + GetChatHistory()->SetVisible( true ); + } +#endif +} + +void CBaseHudChat::CreateChatLines( void ) +{ +#ifndef _XBOX + m_ChatLine = new CBaseHudChatLine( this, "ChatLine1" ); + m_ChatLine->SetVisible( false ); + +#endif +} + + +#define BACKGROUND_BORDER_WIDTH 20 + +CHudChatFilterPanel *CBaseHudChat::GetChatFilterPanel( void ) +{ + if ( m_pFilterPanel == NULL ) + { + m_pFilterPanel = new CHudChatFilterPanel( this, "HudChatFilterPanel" ); + + if ( m_pFilterPanel ) + { + vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ChatScheme.res", "ChatScheme"); + + m_pFilterPanel->SetScheme( scheme ); + m_pFilterPanel->InvalidateLayout( true, true ); + m_pFilterPanel->SetMouseInputEnabled( true ); + m_pFilterPanel->SetPaintBackgroundType( 2 ); + m_pFilterPanel->SetPaintBorderEnabled( true ); + m_pFilterPanel->SetVisible( false ); + } + } + + return m_pFilterPanel; +} + +void CBaseHudChat::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + LoadControlSettings( "resource/UI/BaseChat.res" ); + + BaseClass::ApplySchemeSettings( pScheme ); + + SetPaintBackgroundType( 2 ); + SetPaintBorderEnabled( true ); + SetPaintBackgroundEnabled( true ); + + SetKeyBoardInputEnabled( false ); + SetMouseInputEnabled( false ); + m_nVisibleHeight = 0; + +#ifdef HL1_CLIENT_DLL + SetBgColor( Color( 0, 0, 0, 0 ) ); + SetFgColor( Color( 0, 0, 0, 0 ) ); +#endif + + Color cColor = pScheme->GetColor( "DullWhite", GetBgColor() ); + SetBgColor( Color ( cColor.r(), cColor.g(), cColor.b(), CHAT_HISTORY_ALPHA ) ); + + GetChatHistory()->SetVerticalScrollbar( false ); +} + +void CBaseHudChat::Reset( void ) +{ +#ifndef HL1_CLIENT_DLL + m_nVisibleHeight = 0; + Clear(); +#endif +} + +#ifdef _XBOX +bool CBaseHudChat::ShouldDraw() +{ + // never think, never draw + return false; +} +#endif + +void CBaseHudChat::Paint( void ) +{ +#ifndef _XBOX + if ( m_nVisibleHeight == 0 ) + return; +#endif +} + +CHudChatHistory *CBaseHudChat::GetChatHistory( void ) +{ + return m_pChatHistory; +} + + + +void CBaseHudChat::Init( void ) +{ + if ( IsXbox() ) + return; + + ListenForGameEvent( "hltv_chat" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pszName - +// iSize - +// *pbuf - +//----------------------------------------------------------------------------- +void CBaseHudChat::MsgFunc_SayText( bf_read &msg ) +{ + char szString[256]; + + int client = msg.ReadByte(); + msg.ReadString( szString, sizeof(szString) ); + bool bWantsToChat = msg.ReadByte(); + + if ( bWantsToChat ) + { + // print raw chat text + ChatPrintf( client, CHAT_FILTER_NONE, "%s", szString ); + } + else + { + // try to lookup translated string + Printf( CHAT_FILTER_NONE, "%s", hudtextmessage->LookupString( szString ) ); + } + + CLocalPlayerFilter filter; + C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "HudChat.Message" ); + + Msg( "%s", szString ); +} + +int CBaseHudChat::GetFilterForString( const char *pString ) +{ + if ( !Q_stricmp( pString, "#HL_Name_Change" ) ) + { + return CHAT_FILTER_NAMECHANGE; + } + + return CHAT_FILTER_NONE; +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads in a player's Chat text from the server +//----------------------------------------------------------------------------- +void CBaseHudChat::MsgFunc_SayText2( bf_read &msg ) +{ + // Got message during connection + if ( !g_PR ) + return; + + int client = msg.ReadByte(); + bool bWantsToChat = msg.ReadByte(); + + wchar_t szBuf[6][256]; + char untranslated_msg_text[256]; + wchar_t *msg_text = ReadLocalizedString( msg, szBuf[0], sizeof( szBuf[0] ), false, untranslated_msg_text, sizeof( untranslated_msg_text ) ); + + // keep reading strings and using C format strings for subsituting the strings into the localised text string + ReadChatTextString ( msg, szBuf[1], sizeof( szBuf[1] ) ); // player name + ReadChatTextString ( msg, szBuf[2], sizeof( szBuf[2] ) ); // chat text + ReadLocalizedString( msg, szBuf[3], sizeof( szBuf[3] ), true ); + ReadLocalizedString( msg, szBuf[4], sizeof( szBuf[4] ), true ); + + g_pVGuiLocalize->ConstructString( szBuf[5], sizeof( szBuf[5] ), msg_text, 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + + char ansiString[512]; + g_pVGuiLocalize->ConvertUnicodeToANSI( ConvertCRtoNL( szBuf[5] ), ansiString, sizeof( ansiString ) ); + + if ( bWantsToChat ) + { + int iFilter = CHAT_FILTER_NONE; + + if ( client > 0 && (g_PR->GetTeam( client ) != g_PR->GetTeam( GetLocalPlayerIndex() )) ) + { + iFilter = CHAT_FILTER_PUBLICCHAT; + } + + // print raw chat text + ChatPrintf( client, iFilter, "%s", ansiString ); + + Msg( "%s\n", RemoveColorMarkup(ansiString) ); + + CLocalPlayerFilter filter; + C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "HudChat.Message" ); + } + else + { + // print raw chat text + ChatPrintf( client, GetFilterForString( untranslated_msg_text), "%s", ansiString ); + } +} + +//----------------------------------------------------------------------------- +// Message handler for text messages +// displays a string, looking them up from the titles.txt file, which can be localised +// parameters: +// byte: message direction ( HUD_PRINTCONSOLE, HUD_PRINTNOTIFY, HUD_PRINTCENTER, HUD_PRINTTALK ) +// string: message +// optional parameters: +// string: message parameter 1 +// string: message parameter 2 +// string: message parameter 3 +// string: message parameter 4 +// any string that starts with the character '#' is a message name, and is used to look up the real message in titles.txt +// the next (optional) one to four strings are parameters for that string (which can also be message names if they begin with '#') +//----------------------------------------------------------------------------- +void CBaseHudChat::MsgFunc_TextMsg( bf_read &msg ) +{ + char szString[2048]; + int msg_dest = msg.ReadByte(); + + wchar_t szBuf[5][256]; + wchar_t outputBuf[256]; + + for ( int i=0; i<5; ++i ) + { + msg.ReadString( szString, sizeof(szString) ); + char *tmpStr = hudtextmessage->LookupString( szString, &msg_dest ); + const wchar_t *pBuf = g_pVGuiLocalize->Find( tmpStr ); + if ( pBuf ) + { + // Copy pBuf into szBuf[i]. + int nMaxChars = sizeof( szBuf[i] ) / sizeof( wchar_t ); + wcsncpy( szBuf[i], pBuf, nMaxChars ); + szBuf[i][nMaxChars-1] = 0; + } + else + { + if ( i ) + { + StripEndNewlineFromString( tmpStr ); // these strings are meant for subsitution into the main strings, so cull the automatic end newlines + } + g_pVGuiLocalize->ConvertANSIToUnicode( tmpStr, szBuf[i], sizeof(szBuf[i]) ); + } + } + + if ( !cl_showtextmsg.GetInt() ) + return; + + int len; + switch ( msg_dest ) + { + case HUD_PRINTCENTER: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + internalCenterPrint->Print( ConvertCRtoNL( outputBuf ) ); + break; + + case HUD_PRINTNOTIFY: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); + len = strlen( szString ); + if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) + { + Q_strncat( szString, "\n", sizeof(szString), 1 ); + } + Msg( "%s", ConvertCRtoNL( szString ) ); + break; + + case HUD_PRINTTALK: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); + len = strlen( szString ); + if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) + { + Q_strncat( szString, "\n", sizeof(szString), 1 ); + } + Printf( CHAT_FILTER_NONE, "%s", ConvertCRtoNL( szString ) ); + Msg( "%s", ConvertCRtoNL( szString ) ); + break; + + case HUD_PRINTCONSOLE: + g_pVGuiLocalize->ConstructString( outputBuf, sizeof(outputBuf), szBuf[0], 4, szBuf[1], szBuf[2], szBuf[3], szBuf[4] ); + g_pVGuiLocalize->ConvertUnicodeToANSI( outputBuf, szString, sizeof(szString) ); + len = strlen( szString ); + if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) + { + Q_strncat( szString, "\n", sizeof(szString), 1 ); + } + Msg( "%s", ConvertCRtoNL( szString ) ); + break; + } +} + +void CBaseHudChat::MsgFunc_VoiceSubtitle( bf_read &msg ) +{ + // Got message during connection + if ( !g_PR ) + return; + + if ( !cl_showtextmsg.GetInt() ) + return; + + char szString[2048]; + char szPrefix[64]; //(Voice) + wchar_t szBuf[128]; + + int client = msg.ReadByte(); + int iMenu = msg.ReadByte(); + int iItem = msg.ReadByte(); + + const char *pszSubtitle = ""; + + CGameRules *pGameRules = GameRules(); + + CMultiplayRules *pMultiRules = dynamic_cast< CMultiplayRules * >( pGameRules ); + + Assert( pMultiRules ); + + if ( pMultiRules ) + { + pszSubtitle = pMultiRules->GetVoiceCommandSubtitle( iMenu, iItem ); + } + + SetVoiceSubtitleState( true ); + + const wchar_t *pBuf = g_pVGuiLocalize->Find( pszSubtitle ); + if ( pBuf ) + { + // Copy pBuf into szBuf[i]. + int nMaxChars = sizeof( szBuf ) / sizeof( wchar_t ); + wcsncpy( szBuf, pBuf, nMaxChars ); + szBuf[nMaxChars-1] = 0; + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode( pszSubtitle, szBuf, sizeof(szBuf) ); + } + + int len; + g_pVGuiLocalize->ConvertUnicodeToANSI( szBuf, szString, sizeof(szString) ); + len = strlen( szString ); + if ( len && szString[len-1] != '\n' && szString[len-1] != '\r' ) + { + Q_strncat( szString, "\n", sizeof(szString), 1 ); + } + + const wchar_t *pVoicePrefix = g_pVGuiLocalize->Find( "#Voice" ); + g_pVGuiLocalize->ConvertUnicodeToANSI( pVoicePrefix, szPrefix, sizeof(szPrefix) ); + + ChatPrintf( client, CHAT_FILTER_NONE, "%c(%s) %s%c: %s", COLOR_PLAYERNAME, szPrefix, GetDisplayedSubtitlePlayerName( client ), COLOR_NORMAL, ConvertCRtoNL( szString ) ); + + SetVoiceSubtitleState( false ); +} + +const char *CBaseHudChat::GetDisplayedSubtitlePlayerName( int clientIndex ) +{ + return g_PR->GetPlayerName( clientIndex ); +} + +#ifndef _XBOX +static int __cdecl SortLines( void const *line1, void const *line2 ) +{ + CBaseHudChatLine *l1 = *( CBaseHudChatLine ** )line1; + CBaseHudChatLine *l2 = *( CBaseHudChatLine ** )line2; + + // Invisible at bottom + if ( l1->IsVisible() && !l2->IsVisible() ) + return -1; + else if ( !l1->IsVisible() && l2->IsVisible() ) + return 1; + + // Oldest start time at top + if ( l1->GetStartTime() < l2->GetStartTime() ) + return -1; + else if ( l1->GetStartTime() > l2->GetStartTime() ) + return 1; + + // Otherwise, compare counter + if ( l1->GetCount() < l2->GetCount() ) + return -1; + else if ( l1->GetCount() > l2->GetCount() ) + return 1; + + return 0; +} +#endif + +//----------------------------------------------------------------------------- +// Purpose: Allow inheriting classes to change this spacing behavior +//----------------------------------------------------------------------------- +int CBaseHudChat::GetChatInputOffset( void ) +{ + return m_iFontHeight; +} + +//----------------------------------------------------------------------------- +// Purpose: Do respositioning here to avoid latency due to repositioning of vgui +// voice manager icon panel +//----------------------------------------------------------------------------- +void CBaseHudChat::OnTick( void ) +{ +#ifndef _XBOX + m_nVisibleHeight = 0; + + CBaseHudChatLine *line = m_ChatLine; + + if ( line ) + { + vgui::HFont font = line->GetFont(); + m_iFontHeight = vgui::surface()->GetFontTall( font ) + 2; + + // Put input area at bottom + + int iChatX, iChatY, iChatW, iChatH; + int iInputX, iInputY, iInputW, iInputH; + + m_pChatInput->GetBounds( iInputX, iInputY, iInputW, iInputH ); + GetBounds( iChatX, iChatY, iChatW, iChatH ); + + m_pChatInput->SetBounds( iInputX, iChatH - (m_iFontHeight * 1.75), iInputW, m_iFontHeight ); + + //Resize the History Panel so it fits more lines depending on the screen resolution. + int iChatHistoryX, iChatHistoryY, iChatHistoryW, iChatHistoryH; + + GetChatHistory()->GetBounds( iChatHistoryX, iChatHistoryY, iChatHistoryW, iChatHistoryH ); + + iChatHistoryH = (iChatH - (m_iFontHeight * 2.25)) - iChatHistoryY; + + GetChatHistory()->SetBounds( iChatHistoryX, iChatHistoryY, iChatHistoryW, iChatHistoryH ); + } + + FadeChatHistory(); + +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : width - +// *text - +// textlen - +// Output : int +//----------------------------------------------------------------------------- +int CBaseHudChat::ComputeBreakChar( int width, const char *text, int textlen ) +{ +#ifndef _XBOX + CBaseHudChatLine *line = m_ChatLine; + vgui::HFont font = line->GetFont(); + + int currentlen = 0; + int lastbreak = textlen; + for (int i = 0; i < textlen ; i++) + { + char ch = text[i]; + + if ( ch <= 32 ) + { + lastbreak = i; + } + + wchar_t wch[2]; + + g_pVGuiLocalize->ConvertANSIToUnicode( &ch, wch, sizeof( wch ) ); + + int a,b,c; + + vgui::surface()->GetCharABCwide(font, wch[0], a, b, c); + currentlen += a + b + c; + + if ( currentlen >= width ) + { + // If we haven't found a whitespace char to break on before getting + // to the end, but it's still too long, break on the character just before + // this one + if ( lastbreak == textlen ) + { + lastbreak = MAX( 0, i - 1 ); + } + break; + } + } + + if ( currentlen >= width ) + { + return lastbreak; + } + return textlen; +#else + return 0; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *fmt - +// ... - +//----------------------------------------------------------------------------- +void CBaseHudChat::Printf( int iFilter, const char *fmt, ... ) +{ + va_list marker; + char msg[4096]; + + va_start(marker, fmt); + Q_vsnprintf(msg, sizeof( msg), fmt, marker); + va_end(marker); + + ChatPrintf( 0, iFilter, "%s", msg ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseHudChat::StartMessageMode( int iMessageModeType ) +{ +#ifndef _XBOX + m_nMessageMode = iMessageModeType; + + m_pChatInput->ClearEntry(); + + const wchar_t *pszPrompt = ( m_nMessageMode == MM_SAY ) ? g_pVGuiLocalize->Find( "#chat_say" ) : g_pVGuiLocalize->Find( "#chat_say_team" ); + if ( pszPrompt ) + { + m_pChatInput->SetPrompt( pszPrompt ); + } + else + { + if ( m_nMessageMode == MM_SAY ) + { + m_pChatInput->SetPrompt( L"Say :" ); + } + else + { + m_pChatInput->SetPrompt( L"Say (TEAM) :" ); + } + } + + if ( GetChatHistory() ) + { + GetChatHistory()->SetMouseInputEnabled( true ); + GetChatHistory()->SetKeyBoardInputEnabled( false ); + GetChatHistory()->SetVerticalScrollbar( true ); + GetChatHistory()->ResetAllFades( true ); + GetChatHistory()->SetPaintBorderEnabled( true ); + GetChatHistory()->SetVisible( true ); + } + + vgui::SETUP_PANEL( this ); + SetKeyBoardInputEnabled( true ); + SetMouseInputEnabled( true ); + m_pChatInput->SetVisible( true ); + vgui::surface()->CalculateMouseVisible(); + m_pChatInput->RequestFocus(); + m_pChatInput->SetPaintBorderEnabled( true ); + m_pChatInput->SetMouseInputEnabled( true ); + + //Place the mouse cursor near the text so people notice it. + int x, y, w, h; + GetChatHistory()->GetBounds( x, y, w, h ); + vgui::input()->SetCursorPos( x + ( w/2), y + (h/2) ); + + m_flHistoryFadeTime = gpGlobals->curtime + CHAT_HISTORY_FADE_TIME; + + m_pFilterPanel->SetVisible( false ); + + engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" ); + +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseHudChat::StopMessageMode( void ) +{ +#ifndef _XBOX + + engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" ); + + SetKeyBoardInputEnabled( false ); + SetMouseInputEnabled( false ); + + if ( GetChatHistory() ) + { + GetChatHistory()->SetPaintBorderEnabled( false ); + GetChatHistory()->GotoTextEnd(); + GetChatHistory()->SetMouseInputEnabled( false ); + GetChatHistory()->SetVerticalScrollbar( false ); + GetChatHistory()->ResetAllFades( false, true, CHAT_HISTORY_FADE_TIME ); + GetChatHistory()->SelectNoText(); + } + + //Clear the entry since we wont need it anymore. + m_pChatInput->ClearEntry(); + + //hide filter panel + m_pFilterPanel->SetVisible( false ); + + m_flHistoryFadeTime = gpGlobals->curtime + CHAT_HISTORY_FADE_TIME; + + m_nMessageMode = MM_NONE; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseHudChat::OnChatEntrySend( void ) +{ + Send(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseHudChat::OnChatEntryStopMessageMode( void ) +{ + StopMessageMode(); +} + +void CBaseHudChat::FadeChatHistory( void ) +{ + float frac = ( m_flHistoryFadeTime - gpGlobals->curtime ) / CHAT_HISTORY_FADE_TIME; + + int alpha = frac * CHAT_HISTORY_ALPHA; + alpha = clamp( alpha, 0, CHAT_HISTORY_ALPHA ); + + if ( alpha >= 0 ) + { + if ( GetChatHistory() ) + { + if ( IsMouseInputEnabled() ) + { + SetAlpha( 255 ); + GetChatHistory()->SetBgColor( Color( 0, 0, 0, CHAT_HISTORY_ALPHA - alpha ) ); + m_pChatInput->GetPrompt()->SetAlpha( (CHAT_HISTORY_ALPHA*2) - alpha ); + m_pChatInput->GetInputPanel()->SetAlpha( (CHAT_HISTORY_ALPHA*2) - alpha ); + SetBgColor( Color( GetBgColor().r(), GetBgColor().g(), GetBgColor().b(), CHAT_HISTORY_ALPHA - alpha ) ); + m_pFiltersButton->SetAlpha( (CHAT_HISTORY_ALPHA*2) - alpha ); + } + else + { + GetChatHistory()->SetBgColor( Color( 0, 0, 0, alpha ) ); + SetBgColor( Color( GetBgColor().r(), GetBgColor().g(), GetBgColor().b(), alpha ) ); + + m_pChatInput->GetPrompt()->SetAlpha( alpha ); + m_pChatInput->GetInputPanel()->SetAlpha( alpha ); + m_pFiltersButton->SetAlpha( alpha ); + } + } + } +} + +void CBaseHudChat::SetFilterFlag( int iFilter ) +{ + m_iFilterFlags = iFilter; + + cl_chatfilters.SetValue( m_iFilterFlags ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Color CBaseHudChat::GetTextColorForClient( TextColor colorNum, int clientIndex ) +{ + Color c; + switch ( colorNum ) + { + case COLOR_CUSTOM: + c = m_ColorCustom; + break; + + case COLOR_PLAYERNAME: + c = GetClientColor( clientIndex ); + break; + + case COLOR_LOCATION: + c = g_ColorDarkGreen; + break; + + case COLOR_ACHIEVEMENT: + { + vgui::IScheme *pSourceScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "SourceScheme" ) ); + if ( pSourceScheme ) + { + c = pSourceScheme->GetColor( "SteamLightGreen", GetBgColor() ); + } + else + { + c = GetDefaultTextColor(); + } + } + break; + + default: + c = GetDefaultTextColor(); + } + + return Color( c[0], c[1], c[2], 255 ); +} + +//----------------------------------------------------------------------------- +void CBaseHudChat::SetCustomColor( const char *pszColorName ) +{ + vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "ClientScheme" ) ); + SetCustomColor( pScheme->GetColor( pszColorName, Color(255,255,255,255) ) ); +} + +//----------------------------------------------------------------------------- +Color CBaseHudChat::GetDefaultTextColor( void ) +{ + return g_ColorYellow; +} + +//----------------------------------------------------------------------------- +Color CBaseHudChat::GetClientColor( int clientIndex ) +{ + if ( clientIndex == 0 ) // console msg + { + return g_ColorGreen; + } + else if( g_PR ) + { + return g_ColorGrey; + } + + return g_ColorYellow; +} + +//----------------------------------------------------------------------------- +// Purpose: Parses a line of text for color markup and inserts it via Colorize() +//----------------------------------------------------------------------------- +void CBaseHudChatLine::InsertAndColorizeText( wchar_t *buf, int clientIndex ) +{ + if ( m_text ) + { + delete[] m_text; + m_text = NULL; + } + m_textRanges.RemoveAll(); + + m_text = CloneWString( buf ); + + CBaseHudChat *pChat = dynamic_cast(GetParent() ); + + if ( pChat == NULL ) + return; + + wchar_t *txt = m_text; + int lineLen = wcslen( m_text ); + Color colCustom; + if ( m_text[0] == COLOR_PLAYERNAME || m_text[0] == COLOR_LOCATION || m_text[0] == COLOR_NORMAL || m_text[0] == COLOR_ACHIEVEMENT || m_text[0] == COLOR_CUSTOM || m_text[0] == COLOR_HEXCODE || m_text[0] == COLOR_HEXCODE_ALPHA ) + { + while ( txt && *txt ) + { + TextRange range; + bool bFoundColorCode = false; + bool bDone = false; + int nBytesIn = txt - m_text; + + switch ( *txt ) + { + case COLOR_CUSTOM: + case COLOR_PLAYERNAME: + case COLOR_LOCATION: + case COLOR_ACHIEVEMENT: + case COLOR_NORMAL: + { + // save this start + range.start = nBytesIn + 1; + range.color = pChat->GetTextColorForClient( (TextColor)(*txt), clientIndex ); + range.end = lineLen; + bFoundColorCode = true; + } + ++txt; + break; + case COLOR_HEXCODE: + case COLOR_HEXCODE_ALPHA: + { + bool bReadAlpha = ( *txt == COLOR_HEXCODE_ALPHA ); + const int nCodeBytes = ( bReadAlpha ? 8 : 6 ); + range.start = nBytesIn + nCodeBytes + 1; + range.end = lineLen; + range.preserveAlpha = bReadAlpha; + ++txt; + + if ( range.end > range.start ) + { + int r = V_nibble( txt[0] ) << 4 | V_nibble( txt[1] ); + int g = V_nibble( txt[2] ) << 4 | V_nibble( txt[3] ); + int b = V_nibble( txt[4] ) << 4 | V_nibble( txt[5] ); + int a = 255; + + if ( bReadAlpha ) + { + a = V_nibble( txt[6] ) << 4 | V_nibble( txt[7] ); + } + + range.color = Color( r, g, b, a ); + bFoundColorCode = true; + + txt += nCodeBytes; + } + else + { + // Not enough characters remaining for a hex code. Skip the rest of the string. + bDone = true; + } + } + break; + default: + ++txt; + } + + if ( bDone ) + { + break; + } + + if ( bFoundColorCode ) + { + int count = m_textRanges.Count(); + if ( count ) + { + m_textRanges[count-1].end = nBytesIn; + } + + m_textRanges.AddToTail( range ); + } + } + } + + if ( !m_textRanges.Count() && m_iNameLength > 0 && m_text[0] == COLOR_USEOLDCOLORS ) + { + TextRange range; + range.start = 0; + range.end = m_iNameStart; + range.color = pChat->GetTextColorForClient( COLOR_NORMAL, clientIndex ); + m_textRanges.AddToTail( range ); + + range.start = m_iNameStart; + range.end = m_iNameStart + m_iNameLength; + range.color = pChat->GetTextColorForClient( COLOR_PLAYERNAME, clientIndex ); + m_textRanges.AddToTail( range ); + + range.start = range.end; + range.end = wcslen( m_text ); + range.color = pChat->GetTextColorForClient( COLOR_NORMAL, clientIndex ); + m_textRanges.AddToTail( range ); + } + + if ( !m_textRanges.Count() ) + { + TextRange range; + range.start = 0; + range.end = wcslen( m_text ); + range.color = pChat->GetTextColorForClient( COLOR_NORMAL, clientIndex ); + m_textRanges.AddToTail( range ); + } + + for ( int i=0; i 0 && *start < COLOR_MAX ) + { + Assert( *start != COLOR_HEXCODE && *start != COLOR_HEXCODE_ALPHA ); + m_textRanges[i].start += 1; + } + } + + Colorize(); +} + +//----------------------------------------------------------------------------- +// Purpose: Inserts colored text into the RichText control at the given alpha +//----------------------------------------------------------------------------- +void CBaseHudChatLine::Colorize( int alpha ) +{ + // clear out text + SetText( "" ); + + CBaseHudChat *pChat = dynamic_cast(GetParent() ); + + if ( pChat && pChat->GetChatHistory() ) + { + pChat->GetChatHistory()->InsertString( "\n" ); + } + + wchar_t wText[4096]; + Color color; + for ( int i=0; i 1 && len <= ARRAYSIZE( wText ) ) + { + wcsncpy( wText, start, len ); + wText[len-1] = 0; + color = m_textRanges[i].color; + if ( !m_textRanges[i].preserveAlpha ) + { + color[3] = alpha; + } + + InsertColorChange( color ); + InsertString( wText ); + + CBaseHudChat *pChat = dynamic_cast(GetParent() ); + + if ( pChat && pChat->GetChatHistory() ) + { + pChat->GetChatHistory()->InsertColorChange( color ); + pChat->GetChatHistory()->InsertString( wText ); + pChat->GetChatHistory()->InsertFade( hud_saytext_time.GetFloat(), CHAT_HISTORY_IDLE_FADE_TIME ); + + if ( i == m_textRanges.Count()-1 ) + { + pChat->GetChatHistory()->InsertFade( -1, -1 ); + } + } + + } + } + + InvalidateLayout( true ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CBaseHudChatLine +//----------------------------------------------------------------------------- +CBaseHudChatLine *CBaseHudChat::FindUnusedChatLine( void ) +{ +#ifndef _XBOX + return m_ChatLine; +#else + return NULL; +#endif +} + +void CBaseHudChat::Send( void ) +{ +#ifndef _XBOX + wchar_t szTextbuf[128]; + + m_pChatInput->GetMessageText( szTextbuf, sizeof( szTextbuf ) ); + + char ansi[128]; + g_pVGuiLocalize->ConvertUnicodeToANSI( szTextbuf, ansi, sizeof( ansi ) ); + + int len = Q_strlen(ansi); + + /* +This is a very long string that I am going to attempt to paste into the cs hud chat entry and we will see if it gets cropped or not. + */ + + // remove the \n + if ( len > 0 && + ansi[ len - 1 ] == '\n' ) + { + ansi[ len - 1 ] = '\0'; + } + + if( len > 0 ) + { + // Let the game rules at it + if ( GameRules() ) + { + GameRules()->ModifySentChat( ansi, ARRAYSIZE(ansi) ); + } + + char szbuf[144]; // more than 128 + Q_snprintf( szbuf, sizeof(szbuf), "%s \"%s\"", m_nMessageMode == MM_SAY ? "say" : "say_team", ansi ); + + engine->ClientCmd_Unrestricted(szbuf); + } + + m_pChatInput->ClearEntry(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : vgui::Panel +//----------------------------------------------------------------------------- +vgui::Panel *CBaseHudChat::GetInputPanel( void ) +{ +#ifndef _XBOX + return m_pChatInput->GetInputPanel(); +#else + return NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseHudChat::Clear( void ) +{ +#ifndef _XBOX + // Kill input prompt + StopMessageMode(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *newmap - +//----------------------------------------------------------------------------- +void CBaseHudChat::LevelInit( const char *newmap ) +{ + Clear(); + + //============================================================================= + // HPE_BEGIN: + // [pfreese] initialize new chat filters to defaults. We do this because + // unused filter bits are zero, and we might want them on for new filters that + // are added. + // + // Also, we have to do this here instead of somewhere more sensible like the + // c'tor or Init() method, because cvars are currently loaded twice: once + // during initialization from the local file, and later (after HUD elements + // have been construction and initialized) from Steam Cloud remote storage. + //============================================================================= + + switch ( cl_chatfilter_version.GetInt() ) + { + case 0: + m_iFilterFlags |= CHAT_FILTER_ACHIEVEMENT; + // fall through + case kChatFilterVersion: + break; + } + + if ( cl_chatfilter_version.GetInt() != kChatFilterVersion ) + { + cl_chatfilters.SetValue( m_iFilterFlags ); + cl_chatfilter_version.SetValue( kChatFilterVersion ); + } + + //============================================================================= + // HPE_END + //============================================================================= +} + +void CBaseHudChat::LevelShutdown( void ) +{ + Clear(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *fmt - +// ... - +//----------------------------------------------------------------------------- +void CBaseHudChat::ChatPrintf( int iPlayerIndex, int iFilter, const char *fmt, ... ) +{ + va_list marker; + char msg[4096]; + + va_start(marker, fmt); + Q_vsnprintf(msg, sizeof( msg), fmt, marker); + va_end(marker); + + // Strip any trailing '\n' + if ( strlen( msg ) > 0 && msg[ strlen( msg )-1 ] == '\n' ) + { + msg[ strlen( msg ) - 1 ] = 0; + } + + // Strip leading \n characters ( or notify/color signifiers ) for empty string check + char *pmsg = msg; + while ( *pmsg && ( *pmsg == '\n' || ( *pmsg > 0 && *pmsg < COLOR_MAX ) ) ) + { + pmsg++; + } + + if ( !*pmsg ) + return; + + // Now strip just newlines, since we want the color info for printing + pmsg = msg; + while ( *pmsg && ( *pmsg == '\n' ) ) + { + pmsg++; + } + + if ( !*pmsg ) + return; + + CBaseHudChatLine *line = (CBaseHudChatLine *)FindUnusedChatLine(); + if ( !line ) + { + line = (CBaseHudChatLine *)FindUnusedChatLine(); + } + + if ( !line ) + { + return; + } + + if ( iFilter != CHAT_FILTER_NONE ) + { + if ( !(iFilter & GetFilterFlags() ) ) + return; + } + + if ( *pmsg < 32 ) + { + hudlcd->AddChatLine( pmsg + 1 ); + } + else + { + hudlcd->AddChatLine( pmsg ); + } + + line->SetText( "" ); + + int iNameStart = 0; + int iNameLength = 0; + + player_info_t sPlayerInfo; + if ( iPlayerIndex == 0 ) + { + Q_memset( &sPlayerInfo, 0, sizeof(player_info_t) ); + Q_strncpy( sPlayerInfo.name, "Console", sizeof(sPlayerInfo.name) ); + } + else + { + engine->GetPlayerInfo( iPlayerIndex, &sPlayerInfo ); + } + + int bufSize = (strlen( pmsg ) + 1 ) * sizeof(wchar_t); + wchar_t *wbuf = static_cast( _alloca( bufSize ) ); + if ( wbuf ) + { + Color clrNameColor = GetClientColor( iPlayerIndex ); + + line->SetExpireTime(); + + g_pVGuiLocalize->ConvertANSIToUnicode( pmsg, wbuf, bufSize); + + // find the player's name in the unicode string, in case there is no color markup + const char *pName = sPlayerInfo.name; + + if ( pName ) + { + wchar_t wideName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( pName, wideName, sizeof( wideName ) ); + + const wchar_t *nameInString = wcsstr( wbuf, wideName ); + + if ( nameInString ) + { + iNameStart = (nameInString - wbuf); + iNameLength = wcslen( wideName ); + } + } + + line->SetVisible( false ); + line->SetNameStart( iNameStart ); + line->SetNameLength( iNameLength ); + line->SetNameColor( clrNameColor ); + + line->InsertAndColorizeText( wbuf, iPlayerIndex ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseHudChat::FireGameEvent( IGameEvent *event ) +{ +#ifndef _XBOX + const char *eventname = event->GetName(); + + if ( Q_strcmp( "hltv_chat", eventname ) == 0 ) + { + C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); + + if ( !player ) + return; + + ChatPrintf( player->entindex(), CHAT_FILTER_NONE, "(SourceTV) %s", event->GetString( "text" ) ); + } +#endif } \ No newline at end of file -- cgit v1.2.3