You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
533 lines
12 KiB
533 lines
12 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "dod_hud_chat.h" |
|
#include "c_dod_player.h" |
|
#include "c_dod_playerresource.h" |
|
#include "hud_macros.h" |
|
#include "text_message.h" |
|
#include "vguicenterprint.h" |
|
#include "vgui/ILocalize.h" |
|
#include "dodoverview.h" |
|
#include <voice_status.h> |
|
#include "menu.h" // for CHudMenu defs |
|
#include "dod_hud_freezepanel.h" |
|
|
|
ConVar cl_voicesubtitles( "cl_voicesubtitles", "1", 0, "Enable/disable subtitle printing on voice commands and hand signals." ); |
|
|
|
Color g_DoDColorGrey( 200, 200, 200, 255 ); |
|
|
|
#define DOD_MAX_CHAT_LENGTH 128 |
|
|
|
// Stuff for the Radio Menus |
|
static void voicemenu1_f( void ); |
|
static void voicemenu2_f( void ); |
|
static void voicemenu3_f( void ); |
|
|
|
static ConCommand voicemenu1( "voicemenu1", voicemenu1_f, "Opens a voice menu" ); |
|
static ConCommand voicemenu2( "voicemenu2", voicemenu2_f, "Opens a voice menu" ); |
|
static ConCommand voicemenu3( "voicemenu3", voicemenu3_f, "Opens a voice menu" ); |
|
|
|
|
|
// |
|
//-------------------------------------------------------------- |
|
// |
|
// These methods will bring up the radio menus from the client side. |
|
// They mimic the old server commands of the same name, which used |
|
// to require a round-trip causing latency and unreliability in |
|
// menu responses. Only 1 message is sent to the server now which |
|
// includes both the menu name and the selected item. The server |
|
// is never informed that the menu has been displayed. |
|
// |
|
//-------------------------------------------------------------- |
|
// |
|
|
|
static int g_ActiveVoiceMenu = 0; |
|
|
|
void OpenVoiceMenu( int index ) |
|
{ |
|
// do not show the menu if the player is dead or is an observer |
|
C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer(); |
|
if ( !pPlayer ) |
|
return; |
|
|
|
if ( !pPlayer->IsAlive() || pPlayer->IsObserver() ) |
|
return; |
|
|
|
CHudMenu *pMenu = (CHudMenu *) gHUD.FindElement( "CHudMenu" ); |
|
if ( !pMenu ) |
|
return; |
|
|
|
// if they hit the key again, close the menu |
|
if ( g_ActiveVoiceMenu == index ) |
|
{ |
|
pMenu->HideMenu(); |
|
g_ActiveVoiceMenu = 0; |
|
return; |
|
} |
|
|
|
switch( index ) |
|
{ |
|
case 1: |
|
case 2: |
|
case 3: |
|
{ |
|
char *pszNation; |
|
|
|
if( pPlayer->GetTeamNumber() == TEAM_ALLIES ) |
|
{ |
|
pszNation = "Amer"; |
|
} |
|
else |
|
{ |
|
pszNation = "Ger"; |
|
} |
|
|
|
char cMenuNumber = 'A' + index - 1; // map 1,2,3 to A,B,C |
|
|
|
char szMenu[128]; |
|
Q_snprintf( szMenu, sizeof(szMenu), "#Menu_%sVoice%c", pszNation, cMenuNumber ); |
|
|
|
pMenu->ShowMenu( szMenu, 0x3FF ); |
|
|
|
g_ActiveVoiceMenu = index; |
|
} |
|
break; |
|
case 0: |
|
default: |
|
g_ActiveVoiceMenu = 0; |
|
break; |
|
} |
|
} |
|
|
|
static void voicemenu1_f( void ) |
|
{ |
|
OpenVoiceMenu( 1 ); |
|
} |
|
|
|
static void voicemenu2_f( void ) |
|
{ |
|
OpenVoiceMenu( 2 ); |
|
} |
|
|
|
static void voicemenu3_f( void ) |
|
{ |
|
OpenVoiceMenu( 3 ); |
|
} |
|
|
|
CON_COMMAND( menuselect, "menuselect" ) |
|
{ |
|
if ( args.ArgC() < 2 ) |
|
return; |
|
|
|
int iSlot = atoi( args[1] ); |
|
|
|
switch( g_ActiveVoiceMenu ) |
|
{ |
|
case 1: //RadioA |
|
case 2: |
|
case 3: |
|
{ |
|
// check for cancel |
|
if( iSlot == 10 ) |
|
{ |
|
g_ActiveVoiceMenu = 0; |
|
return; |
|
} |
|
|
|
// find the voice command index from the menu and slot |
|
int iVoiceCommand = (g_ActiveVoiceMenu-1) * 9 + (iSlot-1); |
|
|
|
Assert( iVoiceCommand >= 0 && iVoiceCommand < (3*9) ); |
|
|
|
// emit a voice command |
|
engine->ClientCmd( g_VoiceCommands[iVoiceCommand].pszCommandName ); |
|
} |
|
break; |
|
case 0: |
|
default: |
|
// if we didn't have a menu open, maybe a plugin did. send it on to the server. |
|
const char *cmd = VarArgs( "menuselect %d", iSlot ); |
|
engine->ServerCmd( cmd ); |
|
break; |
|
} |
|
|
|
// reset menu |
|
g_ActiveVoiceMenu = 0; |
|
} |
|
|
|
DECLARE_HUDELEMENT( CHudChat ); |
|
|
|
DECLARE_HUD_MESSAGE( CHudChat, SayText ); |
|
DECLARE_HUD_MESSAGE( CHudChat, TextMsg ); |
|
DECLARE_HUD_MESSAGE( CHudChat, VoiceSubtitle ); |
|
DECLARE_HUD_MESSAGE( CHudChat, HandSignalSubtitle ); |
|
|
|
|
|
//===================== |
|
//CHudChatLine |
|
//===================== |
|
|
|
CHudChatLine::CHudChatLine( vgui::Panel *parent, const char *panelName ) : CBaseHudChatLine( parent, panelName ) |
|
{ |
|
m_text = NULL; |
|
} |
|
|
|
void CHudChatLine::ApplySchemeSettings(vgui::IScheme *pScheme) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
} |
|
|
|
//===================== |
|
//CHudChatInputLine |
|
//===================== |
|
|
|
void CHudChatInputLine::ApplySchemeSettings(vgui::IScheme *pScheme) |
|
{ |
|
BaseClass::ApplySchemeSettings(pScheme); |
|
} |
|
|
|
|
|
|
|
//===================== |
|
//CHudChat |
|
//===================== |
|
|
|
CHudChat::CHudChat( const char *pElementName ) : BaseClass( pElementName ) |
|
{ |
|
|
|
} |
|
|
|
void CHudChat::CreateChatInputLine( void ) |
|
{ |
|
m_pChatInput = new CHudChatInputLine( this, "ChatInputLine" ); |
|
m_pChatInput->SetVisible( false ); |
|
} |
|
|
|
void CHudChat::CreateChatLines( void ) |
|
{ |
|
m_ChatLine = new CHudChatLine( this, "ChatLine1" ); |
|
m_ChatLine->SetVisible( false ); |
|
} |
|
|
|
void CHudChat::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
} |
|
|
|
|
|
void CHudChat::Init( void ) |
|
{ |
|
BaseClass::Init(); |
|
|
|
HOOK_HUD_MESSAGE( CHudChat, SayText ); |
|
HOOK_HUD_MESSAGE( CHudChat, TextMsg ); |
|
HOOK_HUD_MESSAGE( CHudChat, VoiceSubtitle ); |
|
HOOK_HUD_MESSAGE( CHudChat, HandSignalSubtitle ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Overrides base reset to not cancel chat at round restart |
|
//----------------------------------------------------------------------------- |
|
void CHudChat::Reset( void ) |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pszName - |
|
// iSize - |
|
// *pbuf - |
|
//----------------------------------------------------------------------------- |
|
void CHudChat::MsgFunc_SayText( bf_read &msg ) |
|
{ |
|
// Got message during connection |
|
if ( !g_PR ) |
|
return; |
|
|
|
char szString[DOD_MAX_CHAT_LENGTH]; |
|
|
|
int client = msg.ReadByte(); |
|
msg.ReadString( szString, sizeof(szString) ); |
|
bool bWantsToChat = msg.ReadByte(); |
|
|
|
if ( GetClientVoiceMgr()->IsPlayerBlocked( client ) ) |
|
return; |
|
|
|
if ( client > 0 ) |
|
GetDODOverview()->PlayerChat( client ); |
|
|
|
if ( bWantsToChat ) |
|
{ |
|
int iFilter = CHAT_FILTER_NONE; |
|
|
|
if ( client > 0 && (g_PR->GetTeam( client ) != g_PR->GetTeam( GetLocalPlayerIndex() )) ) |
|
{ |
|
iFilter = CHAT_FILTER_PUBLICCHAT; |
|
} |
|
|
|
// Localize any words in the chat that start with # |
|
FindLocalizableSubstrings( szString, sizeof(szString) ); |
|
|
|
// print raw chat text |
|
ChatPrintf( client, iFilter, "%c%s", COLOR_USEOLDCOLORS, szString ); |
|
} |
|
else |
|
{ |
|
// try to lookup translated string |
|
Printf( GetFilterForString( szString ), "%s", hudtextmessage->LookupString( szString ) ); |
|
} |
|
|
|
Msg( "%s", szString ); |
|
} |
|
|
|
void CHudChat::MsgFunc_VoiceSubtitle( bf_read &msg ) |
|
{ |
|
// Got message during connection |
|
if ( !g_PR ) |
|
return; |
|
|
|
if ( !cl_showtextmsg.GetInt() ) |
|
return; |
|
|
|
if ( !cl_voicesubtitles.GetInt() ) |
|
return; |
|
|
|
char szString[2048]; |
|
char szPrefix[64]; //(Voice) |
|
wchar_t szBuf[128]; |
|
|
|
int client = msg.ReadByte(); |
|
|
|
if ( GetClientVoiceMgr()->IsPlayerBlocked( client ) ) |
|
return; |
|
|
|
if ( client > 0 ) |
|
GetDODOverview()->PlayerChat( client ); |
|
|
|
int iTeam = msg.ReadByte(); |
|
int iVoiceCommand = msg.ReadByte(); |
|
|
|
//Assert( iVoiceCommand <= ARRAYSIZE(g_VoiceCommands) ); |
|
Assert( iTeam == TEAM_ALLIES || iTeam == TEAM_AXIS ); |
|
|
|
const char *pszSubtitle = g_VoiceCommands[iVoiceCommand].pszAlliedSubtitle; |
|
|
|
if( iTeam == TEAM_AXIS && g_VoiceCommands[iVoiceCommand].pszAxisSubtitle != NULL ) |
|
pszSubtitle = g_VoiceCommands[iVoiceCommand].pszAxisSubtitle; |
|
|
|
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, g_PR->GetPlayerName( client ), COLOR_NORMAL, ConvertCRtoNL( szString ) ); |
|
} |
|
|
|
void CHudChat::MsgFunc_HandSignalSubtitle( bf_read &msg ) |
|
{ |
|
// Got message during connection |
|
if ( !g_PR ) |
|
return; |
|
|
|
if ( !cl_showtextmsg.GetInt() ) |
|
return; |
|
|
|
if ( !cl_voicesubtitles.GetInt() ) |
|
return; |
|
|
|
char szString[2048]; |
|
char szPrefix[64]; //(HandSignal) |
|
wchar_t szBuf[128]; |
|
|
|
int client = msg.ReadByte(); |
|
int iSignal = msg.ReadByte(); |
|
|
|
if ( GetClientVoiceMgr()->IsPlayerBlocked( client ) ) |
|
return; |
|
|
|
if ( client > 0 ) |
|
GetDODOverview()->PlayerChat( client ); |
|
|
|
const char *pszSubtitle = g_HandSignals[iSignal].pszSubtitle; |
|
|
|
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( "#HandSignal" ); |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( pVoicePrefix, szPrefix, sizeof(szPrefix) ); |
|
|
|
Assert( g_PR ); |
|
|
|
ChatPrintf( client, CHAT_FILTER_NONE, "%c(%s) %s%c: %s", COLOR_USEOLDCOLORS, szPrefix, g_PR->GetPlayerName( client ), COLOR_NORMAL, ConvertCRtoNL( szString ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CHudChat::GetChatInputOffset( void ) |
|
{ |
|
if ( m_pChatInput->IsVisible() ) |
|
{ |
|
return m_iFontHeight; |
|
} |
|
else |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
wchar_t* ReadLocalizedVoiceCommandString( bf_read &msg, wchar_t *pOut, int outSize, bool bStripNewline ) |
|
{ |
|
char szString[2048]; |
|
msg.ReadString( szString, sizeof(szString) ); |
|
|
|
const wchar_t *pBuf = g_pVGuiLocalize->Find( szString ); |
|
if ( pBuf ) |
|
{ |
|
wcsncpy( pOut, pBuf, outSize/sizeof(wchar_t) ); |
|
pOut[outSize/sizeof(wchar_t)-1] = 0; |
|
} |
|
else |
|
{ |
|
g_pVGuiLocalize->ConvertANSIToUnicode( szString, pOut, outSize ); |
|
} |
|
|
|
if ( bStripNewline ) |
|
StripEndNewlineFromString( pOut ); |
|
|
|
return pOut; |
|
} |
|
|
|
// Find words in the chat that can be localized and replace them with localized text |
|
void CHudChat::FindLocalizableSubstrings( char *szChat, int chatLength ) |
|
{ |
|
static char buf[DOD_MAX_CHAT_LENGTH]; |
|
buf[0] = '\0'; |
|
|
|
int pos = 0; |
|
|
|
static char szTemp[DOD_MAX_CHAT_LENGTH]; |
|
|
|
wchar_t *pwcLocalized; |
|
|
|
for ( char *pSrc = szChat; pSrc != NULL && *pSrc != 0 && pos < chatLength-1; pSrc++ ) |
|
{ |
|
// if its a # |
|
if ( *pSrc == '#' ) |
|
{ |
|
// trim into a word |
|
char *pWord = pSrc; |
|
int iWordPos = 0; |
|
while ( *pWord != ' ' && |
|
*pWord != '\0' && |
|
*pWord != '\n' ) |
|
{ |
|
szTemp[iWordPos] = *pWord; |
|
iWordPos++; |
|
pWord++; |
|
} |
|
|
|
szTemp[iWordPos] = '\0'; |
|
|
|
pwcLocalized = g_pVGuiLocalize->Find( szTemp ); |
|
|
|
// localize word |
|
|
|
if ( pwcLocalized ) |
|
{ |
|
// print it into the buf |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( pwcLocalized, szTemp, sizeof(szTemp) ); |
|
} |
|
|
|
// copy the string to chat |
|
buf[pos] = '\0'; |
|
Q_strncat( buf, szTemp, DOD_MAX_CHAT_LENGTH, COPY_ALL_CHARACTERS ); |
|
|
|
int remainingSpace = chatLength - pos - 2; // minus one for the NULL and one for the space |
|
pos += MIN( Q_strlen(szTemp), remainingSpace ); |
|
|
|
pSrc += iWordPos-1; // progress pSrc to the end of the word |
|
} |
|
else |
|
{ |
|
// copy each char across |
|
buf[pos] = *pSrc; |
|
pos++; |
|
} |
|
} |
|
|
|
buf[pos] = '\0'; |
|
pos++; |
|
|
|
//copy buf back to szChat |
|
Q_strncpy( szChat, buf, MIN(chatLength, pos) ); |
|
} |
|
|
|
Color CHudChat::GetDefaultTextColor( void ) |
|
{ |
|
return g_DoDColorGrey; |
|
} |
|
|
|
Color CHudChat::GetClientColor( int clientIndex ) |
|
{ |
|
// If player resource is bogus, return some obvious colour |
|
// or if we want a generic colour |
|
if ( !g_PR || clientIndex < 1 ) |
|
return GetDefaultTextColor(); |
|
|
|
return g_PR->GetTeamColor( g_PR->GetTeam( clientIndex ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CHudChat::IsVisible( void ) |
|
{ |
|
if ( IsTakingAFreezecamScreenshot() ) |
|
return false; |
|
|
|
return BaseClass::IsVisible(); |
|
} |