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/clientmode_shared.cpp | 2788 +++++++++++++++--------------- 1 file changed, 1394 insertions(+), 1394 deletions(-) (limited to 'mp/src/game/client/clientmode_shared.cpp') diff --git a/mp/src/game/client/clientmode_shared.cpp b/mp/src/game/client/clientmode_shared.cpp index 31acc934..a1d1127d 100644 --- a/mp/src/game/client/clientmode_shared.cpp +++ b/mp/src/game/client/clientmode_shared.cpp @@ -1,1394 +1,1394 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: Normal HUD mode -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - - -#include "cbase.h" -#include "clientmode_shared.h" -#include "iinput.h" -#include "view_shared.h" -#include "iviewrender.h" -#include "hud_basechat.h" -#include "weapon_selection.h" -#include -#include -#include -#include -#include "engine/IEngineSound.h" -#include -#include -#include "vgui_int.h" -#include "hud_macros.h" -#include "hltvcamera.h" -#include "particlemgr.h" -#include "c_vguiscreen.h" -#include "c_team.h" -#include "c_rumble.h" -#include "fmtstr.h" -#include "achievementmgr.h" -#include "c_playerresource.h" -#include "cam_thirdperson.h" -#include -#include "hud_vote.h" -#include "ienginevgui.h" -#include "headtrack/isourcevirtualreality.h" -#if defined( _X360 ) -#include "xbox/xbox_console.h" -#endif - -#if defined( REPLAY_ENABLED ) -#include "replay/replaycamera.h" -#include "replay/ireplaysystem.h" -#include "replay/iclientreplaycontext.h" -#include "replay/ireplaymanager.h" -#include "replay/replay.h" -#include "replay/ienginereplay.h" -#include "replay/vgui/replayreminderpanel.h" -#include "replay/vgui/replaymessagepanel.h" -#include "econ/econ_controls.h" -#include "econ/confirm_dialog.h" -extern IClientReplayContext *g_pClientReplayContext; -extern ConVar replay_rendersetting_renderglow; -#endif - -#if defined USES_ECON_ITEMS -#include "econ_item_view.h" -#endif - -#if defined( TF_CLIENT_DLL ) -#include "c_tf_player.h" -#include "econ_item_description.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ACHIEVEMENT_ANNOUNCEMENT_MIN_TIME 10 - -class CHudWeaponSelection; -class CHudChat; -class CHudVote; - -static vgui::HContext s_hVGuiContext = DEFAULT_VGUI_CONTEXT; - -ConVar cl_drawhud( "cl_drawhud", "1", FCVAR_CHEAT, "Enable the rendering of the hud" ); -ConVar hud_takesshots( "hud_takesshots", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Auto-save a scoreboard screenshot at the end of a map." ); -ConVar hud_freezecamhide( "hud_freezecamhide", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Hide the HUD during freeze-cam" ); -ConVar cl_show_num_particle_systems( "cl_show_num_particle_systems", "0", FCVAR_CLIENTDLL, "Display the number of active particle systems." ); - -extern ConVar v_viewmodel_fov; -extern ConVar voice_modenable; - -extern bool IsInCommentaryMode( void ); - -#ifdef VOICE_VOX_ENABLE -void VoxCallback( IConVar *var, const char *oldString, float oldFloat ) -{ - if ( engine && engine->IsConnected() ) - { - ConVarRef voice_vox( var->GetName() ); - if ( voice_vox.GetBool() && voice_modenable.GetBool() ) - { - engine->ClientCmd_Unrestricted( "voicerecord_toggle on\n" ); - } - else - { - engine->ClientCmd_Unrestricted( "voicerecord_toggle off\n" ); - } - } -} -ConVar voice_vox( "voice_vox", "0", FCVAR_ARCHIVE, "Voice chat uses a vox-style always on", true, 0, true, 1, VoxCallback ); - -// --------------------------------------------------------------------------------- // -// CVoxManager. -// --------------------------------------------------------------------------------- // -class CVoxManager : public CAutoGameSystem -{ -public: - CVoxManager() : CAutoGameSystem( "VoxManager" ) - { - } - - virtual void LevelInitPostEntity( void ) - { - if ( voice_vox.GetBool() && voice_modenable.GetBool() ) - { - engine->ClientCmd_Unrestricted( "voicerecord_toggle on\n" ); - } - } - - virtual void LevelShutdownPreEntity( void ) - { - if ( voice_vox.GetBool() ) - { - engine->ClientCmd_Unrestricted( "voicerecord_toggle off\n" ); - } - } -}; - -static CVoxManager s_VoxManager; -// --------------------------------------------------------------------------------- // -#endif // VOICE_VOX_ENABLE - -CON_COMMAND( hud_reloadscheme, "Reloads hud layout and animation scripts." ) -{ - ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); - if ( !mode ) - return; - - mode->ReloadScheme(); -} - -#ifdef _DEBUG -CON_COMMAND_F( crash, "Crash the client. Optional parameter -- type of crash:\n 0: read from NULL\n 1: write to NULL\n 2: DmCrashDump() (xbox360 only)", FCVAR_CHEAT ) -{ - int crashtype = 0; - int dummy; - if ( args.ArgC() > 1 ) - { - crashtype = Q_atoi( args[1] ); - } - switch (crashtype) - { - case 0: - dummy = *((int *) NULL); - Msg("Crashed! %d\n", dummy); // keeps dummy from optimizing out - break; - case 1: - *((int *)NULL) = 42; - break; -#if defined( _X360 ) - case 2: - XBX_CrashDump(false); - break; -#endif - default: - Msg("Unknown variety of crash. You have now failed to crash. I hope you're happy.\n"); - break; - } -} -#endif // _DEBUG - -static void __MsgFunc_Rumble( bf_read &msg ) -{ - unsigned char waveformIndex; - unsigned char rumbleData; - unsigned char rumbleFlags; - - waveformIndex = msg.ReadByte(); - rumbleData = msg.ReadByte(); - rumbleFlags = msg.ReadByte(); - - RumbleEffect( waveformIndex, rumbleData, rumbleFlags ); -} - -static void __MsgFunc_VGUIMenu( bf_read &msg ) -{ - char panelname[2048]; - - msg.ReadString( panelname, sizeof(panelname) ); - - bool bShow = msg.ReadByte()!=0; - - IViewPortPanel *viewport = gViewPortInterface->FindPanelByName( panelname ); - - if ( !viewport ) - { - // DevMsg("VGUIMenu: couldn't find panel '%s'.\n", panelname ); - return; - } - - int count = msg.ReadByte(); - - if ( count > 0 ) - { - KeyValues *keys = new KeyValues("data"); - - for ( int i=0; iSetString( name, data ); - } - - viewport->SetData( keys ); - - keys->deleteThis(); - } - - // is the server telling us to show the scoreboard (at the end of a map)? - if ( Q_stricmp( panelname, "scores" ) == 0 ) - { - if ( hud_takesshots.GetBool() == true ) - { - gHUD.SetScreenShotTime( gpGlobals->curtime + 1.0 ); // take a screenshot in 1 second - } - } - - // is the server trying to show an MOTD panel? Check that it's allowed right now. - ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); - if ( Q_stricmp( panelname, PANEL_INFO ) == 0 && mode ) - { - if ( !mode->IsInfoPanelAllowed() ) - { - return; - } - else - { - mode->InfoPanelDisplayed(); - } - } - - gViewPortInterface->ShowPanel( viewport, bShow ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -ClientModeShared::ClientModeShared() -{ - m_pViewport = NULL; - m_pChatElement = NULL; - m_pWeaponSelection = NULL; - m_nRootSize[ 0 ] = m_nRootSize[ 1 ] = -1; - -#if defined( REPLAY_ENABLED ) - m_pReplayReminderPanel = NULL; - m_flReplayStartRecordTime = 0.0f; - m_flReplayStopRecordTime = 0.0f; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -ClientModeShared::~ClientModeShared() -{ - delete m_pViewport; -} - -void ClientModeShared::ReloadScheme( void ) -{ - m_pViewport->ReloadScheme( "resource/ClientScheme.res" ); - ClearKeyValuesCache(); -} - - -//---------------------------------------------------------------------------- -// Purpose: Let the client mode set some vgui conditions -//----------------------------------------------------------------------------- -void ClientModeShared::ComputeVguiResConditions( KeyValues *pkvConditions ) -{ - if ( UseVR() ) - { - pkvConditions->FindKey( "if_vr", true ); - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ClientModeShared::Init() -{ - m_pChatElement = ( CBaseHudChat * )GET_HUDELEMENT( CHudChat ); - Assert( m_pChatElement ); - - m_pWeaponSelection = ( CBaseHudWeaponSelection * )GET_HUDELEMENT( CHudWeaponSelection ); - Assert( m_pWeaponSelection ); - - KeyValuesAD pConditions( "conditions" ); - ComputeVguiResConditions( pConditions ); - - // Derived ClientMode class must make sure m_Viewport is instantiated - Assert( m_pViewport ); - m_pViewport->LoadControlSettings( "scripts/HudLayout.res", NULL, NULL, pConditions ); - -#if defined( REPLAY_ENABLED ) - m_pReplayReminderPanel = GET_HUDELEMENT( CReplayReminderPanel ); - Assert( m_pReplayReminderPanel ); -#endif - - ListenForGameEvent( "player_connect" ); - ListenForGameEvent( "player_disconnect" ); - ListenForGameEvent( "player_team" ); - ListenForGameEvent( "server_cvar" ); - ListenForGameEvent( "player_changename" ); - ListenForGameEvent( "teamplay_broadcast_audio" ); - ListenForGameEvent( "achievement_earned" ); - -#if defined( TF_CLIENT_DLL ) - ListenForGameEvent( "item_found" ); -#endif - -#if defined( REPLAY_ENABLED ) - ListenForGameEvent( "replay_startrecord" ); - ListenForGameEvent( "replay_endrecord" ); - ListenForGameEvent( "replay_replaysavailable" ); - ListenForGameEvent( "replay_servererror" ); - ListenForGameEvent( "game_newmap" ); -#endif - -#ifndef _XBOX - HLTVCamera()->Init(); -#if defined( REPLAY_ENABLED ) - ReplayCamera()->Init(); -#endif -#endif - - m_CursorNone = vgui::dc_none; - - HOOK_MESSAGE( VGUIMenu ); - HOOK_MESSAGE( Rumble ); -} - - -void ClientModeShared::InitViewport() -{ -} - - -void ClientModeShared::VGui_Shutdown() -{ - delete m_pViewport; - m_pViewport = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ClientModeShared::Shutdown() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : frametime - -// *cmd - -//----------------------------------------------------------------------------- -bool ClientModeShared::CreateMove( float flInputSampleTime, CUserCmd *cmd ) -{ - // Let the player override the view. - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); - if(!pPlayer) - return true; - - // Let the player at it - return pPlayer->CreateMove( flInputSampleTime, cmd ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSetup - -//----------------------------------------------------------------------------- -void ClientModeShared::OverrideView( CViewSetup *pSetup ) -{ - QAngle camAngles; - - // Let the player override the view. - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); - if(!pPlayer) - return; - - pPlayer->OverrideView( pSetup ); - - if( ::input->CAM_IsThirdPerson() ) - { - Vector cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles(); - Vector cam_ofs_distance = g_ThirdPersonManager.GetFinalCameraOffset(); - - cam_ofs_distance *= g_ThirdPersonManager.GetDistanceFraction(); - - camAngles[ PITCH ] = cam_ofs[ PITCH ]; - camAngles[ YAW ] = cam_ofs[ YAW ]; - camAngles[ ROLL ] = 0; - - Vector camForward, camRight, camUp; - - - if ( g_ThirdPersonManager.IsOverridingThirdPerson() == false ) - { - engine->GetViewAngles( camAngles ); - } - - // get the forward vector - AngleVectors( camAngles, &camForward, &camRight, &camUp ); - - VectorMA( pSetup->origin, -cam_ofs_distance[0], camForward, pSetup->origin ); - VectorMA( pSetup->origin, cam_ofs_distance[1], camRight, pSetup->origin ); - VectorMA( pSetup->origin, cam_ofs_distance[2], camUp, pSetup->origin ); - - // Override angles from third person camera - VectorCopy( camAngles, pSetup->angles ); - } - else if (::input->CAM_IsOrthographic()) - { - pSetup->m_bOrtho = true; - float w, h; - ::input->CAM_OrthographicSize( w, h ); - w *= 0.5f; - h *= 0.5f; - pSetup->m_OrthoLeft = -w; - pSetup->m_OrthoTop = -h; - pSetup->m_OrthoRight = w; - pSetup->m_OrthoBottom = h; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool ClientModeShared::ShouldDrawEntity(C_BaseEntity *pEnt) -{ - return true; -} - -bool ClientModeShared::ShouldDrawParticles( ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Allow weapons to override mouse input (for binoculars) -//----------------------------------------------------------------------------- -void ClientModeShared::OverrideMouseInput( float *x, float *y ) -{ - C_BaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ( pWeapon ) - { - pWeapon->OverrideMouseInput( x, y ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool ClientModeShared::ShouldDrawViewModel() -{ - return true; -} - -bool ClientModeShared::ShouldDrawDetailObjects( ) -{ - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if VR mode should black out everything outside the HUD. -// This is used for things like sniper scopes and full screen UI -//----------------------------------------------------------------------------- -bool ClientModeShared::ShouldBlackoutAroundHUD() -{ - return enginevgui->IsGameUIVisible(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows the client mode to override mouse control stuff in headtrack -//----------------------------------------------------------------------------- -HeadtrackMovementMode_t ClientModeShared::ShouldOverrideHeadtrackControl() -{ - return HMM_NOOVERRIDE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool ClientModeShared::ShouldDrawCrosshair( void ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Don't draw the current view entity if we are using the fake viewmodel instead -//----------------------------------------------------------------------------- -bool ClientModeShared::ShouldDrawLocalPlayer( C_BasePlayer *pPlayer ) -{ - if ( ( pPlayer->index == render->GetViewEntity() ) && !C_BasePlayer::ShouldDrawLocalPlayer() ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: The mode can choose to not draw fog -//----------------------------------------------------------------------------- -bool ClientModeShared::ShouldDrawFog( void ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ClientModeShared::AdjustEngineViewport( int& x, int& y, int& width, int& height ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ClientModeShared::PreRender( CViewSetup *pSetup ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ClientModeShared::PostRender() -{ - // Let the particle manager simulate things that haven't been simulated. - ParticleMgr()->PostRender(); -} - -void ClientModeShared::PostRenderVGui() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ClientModeShared::Update() -{ -#if defined( REPLAY_ENABLED ) - UpdateReplayMessages(); -#endif - - if ( m_pViewport->IsVisible() != cl_drawhud.GetBool() ) - { - m_pViewport->SetVisible( cl_drawhud.GetBool() ); - } - - UpdateRumbleEffects(); - - if ( cl_show_num_particle_systems.GetBool() ) - { - int nCount = 0; - - for ( int i = 0; i < g_pParticleSystemMgr->GetParticleSystemCount(); i++ ) - { - const char *pParticleSystemName = g_pParticleSystemMgr->GetParticleSystemNameFromIndex(i); - CParticleSystemDefinition *pParticleSystem = g_pParticleSystemMgr->FindParticleSystem( pParticleSystemName ); - if ( !pParticleSystem ) - continue; - - for ( CParticleCollection *pCurCollection = pParticleSystem->FirstCollection(); - pCurCollection != NULL; - pCurCollection = pCurCollection->GetNextCollectionUsingSameDef() ) - { - ++nCount; - } - } - - engine->Con_NPrintf( 0, "# Active particle systems: %i", nCount ); - } -} - -//----------------------------------------------------------------------------- -// This processes all input before SV Move messages are sent -//----------------------------------------------------------------------------- - -void ClientModeShared::ProcessInput(bool bActive) -{ - gHUD.ProcessInput( bActive ); -} - -//----------------------------------------------------------------------------- -// Purpose: We've received a keypress from the engine. Return 1 if the engine is allowed to handle it. -//----------------------------------------------------------------------------- -int ClientModeShared::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) -{ - if ( engine->Con_IsVisible() ) - return 1; - - // Should we start typing a message? - if ( pszCurrentBinding && - ( Q_strcmp( pszCurrentBinding, "messagemode" ) == 0 || - Q_strcmp( pszCurrentBinding, "say" ) == 0 ) ) - { - if ( down ) - { - StartMessageMode( MM_SAY ); - } - return 0; - } - else if ( pszCurrentBinding && - ( Q_strcmp( pszCurrentBinding, "messagemode2" ) == 0 || - Q_strcmp( pszCurrentBinding, "say_team" ) == 0 ) ) - { - if ( down ) - { - StartMessageMode( MM_SAY_TEAM ); - } - return 0; - } - - // If we're voting... -#ifdef VOTING_ENABLED - CHudVote *pHudVote = GET_HUDELEMENT( CHudVote ); - if ( pHudVote && pHudVote->IsVisible() ) - { - if ( !pHudVote->KeyInput( down, keynum, pszCurrentBinding ) ) - { - return 0; - } - } -#endif - - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); - - // if ingame spectator mode, let spectator input intercept key event here - if( pPlayer && - ( pPlayer->GetObserverMode() > OBS_MODE_DEATHCAM ) && - !HandleSpectatorKeyInput( down, keynum, pszCurrentBinding ) ) - { - return 0; - } - - // Let game-specific hud elements get a crack at the key input - if ( !HudElementKeyInput( down, keynum, pszCurrentBinding ) ) - { - return 0; - } - - C_BaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ( pWeapon ) - { - return pWeapon->KeyInput( down, keynum, pszCurrentBinding ); - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: See if spectator input occurred. Return 0 if the key is swallowed. -//----------------------------------------------------------------------------- -int ClientModeShared::HandleSpectatorKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) -{ - // we are in spectator mode, open spectator menu - if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+duck" ) == 0 ) - { - m_pViewport->ShowPanel( PANEL_SPECMENU, true ); - return 0; // we handled it, don't handle twice or send to server - } - else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+attack" ) == 0 ) - { - engine->ClientCmd( "spec_next" ); - return 0; - } - else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+attack2" ) == 0 ) - { - engine->ClientCmd( "spec_prev" ); - return 0; - } - else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+jump" ) == 0 ) - { - engine->ClientCmd( "spec_mode" ); - return 0; - } - else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+strafe" ) == 0 ) - { - HLTVCamera()->SetAutoDirector( true ); -#if defined( REPLAY_ENABLED ) - ReplayCamera()->SetAutoDirector( true ); -#endif - return 0; - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: See if hud elements want key input. Return 0 if the key is swallowed -//----------------------------------------------------------------------------- -int ClientModeShared::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) -{ - if ( m_pWeaponSelection ) - { - if ( !m_pWeaponSelection->KeyInput( down, keynum, pszCurrentBinding ) ) - { - return 0; - } - } - -#if defined( REPLAY_ENABLED ) - if ( m_pReplayReminderPanel ) - { - if ( m_pReplayReminderPanel->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) - { - return 0; - } - } -#endif - - return 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool ClientModeShared::DoPostScreenSpaceEffects( const CViewSetup *pSetup ) -{ -#if defined( REPLAY_ENABLED ) - if ( engine->IsPlayingDemo() ) - { - if ( !replay_rendersetting_renderglow.GetBool() ) - return false; - } -#endif - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : vgui::Panel -//----------------------------------------------------------------------------- -vgui::Panel *ClientModeShared::GetMessagePanel() -{ - if ( m_pChatElement && m_pChatElement->GetInputPanel() && m_pChatElement->GetInputPanel()->IsVisible() ) - return m_pChatElement->GetInputPanel(); - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: The player has started to type a message -//----------------------------------------------------------------------------- -void ClientModeShared::StartMessageMode( int iMessageModeType ) -{ - // Can only show chat UI in multiplayer!!! - if ( gpGlobals->maxClients == 1 ) - { - return; - } - if ( m_pChatElement ) - { - m_pChatElement->StartMessageMode( iMessageModeType ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *newmap - -//----------------------------------------------------------------------------- -void ClientModeShared::LevelInit( const char *newmap ) -{ - m_pViewport->GetAnimationController()->StartAnimationSequence("LevelInit"); - - // Tell the Chat Interface - if ( m_pChatElement ) - { - m_pChatElement->LevelInit( newmap ); - } - - // we have to fake this event clientside, because clients connect after that - IGameEvent *event = gameeventmanager->CreateEvent( "game_newmap" ); - if ( event ) - { - event->SetString("mapname", newmap ); - gameeventmanager->FireEventClientSide( event ); - } - - // Create a vgui context for all of the in-game vgui panels... - if ( s_hVGuiContext == DEFAULT_VGUI_CONTEXT ) - { - s_hVGuiContext = vgui::ivgui()->CreateContext(); - } - - // Reset any player explosion/shock effects - CLocalPlayerFilter filter; - enginesound->SetPlayerDSP( filter, 0, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ClientModeShared::LevelShutdown( void ) -{ - // Reset the third person camera so we don't crash - g_ThirdPersonManager.Init(); - - if ( m_pChatElement ) - { - m_pChatElement->LevelShutdown(); - } - if ( s_hVGuiContext != DEFAULT_VGUI_CONTEXT ) - { - vgui::ivgui()->DestroyContext( s_hVGuiContext ); - s_hVGuiContext = DEFAULT_VGUI_CONTEXT; - } - - // Reset any player explosion/shock effects - CLocalPlayerFilter filter; - enginesound->SetPlayerDSP( filter, 0, true ); -} - - -void ClientModeShared::Enable() -{ - vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();; - - // Add our viewport to the root panel. - if( pRoot != 0 ) - { - m_pViewport->SetParent( pRoot ); - } - - // All hud elements should be proportional - // This sets that flag on the viewport and all child panels - m_pViewport->SetProportional( true ); - - m_pViewport->SetCursor( m_CursorNone ); - vgui::surface()->SetCursor( m_CursorNone ); - - m_pViewport->SetVisible( true ); - if ( m_pViewport->IsKeyBoardInputEnabled() ) - { - m_pViewport->RequestFocus(); - } - - Layout(); -} - - -void ClientModeShared::Disable() -{ - vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();; - - // Remove our viewport from the root panel. - if( pRoot != 0 ) - { - m_pViewport->SetParent( (vgui::VPANEL)NULL ); - } - - m_pViewport->SetVisible( false ); -} - - -void ClientModeShared::Layout() -{ - vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel(); - int wide, tall; - - // Make the viewport fill the root panel. - if( pRoot != 0 ) - { - vgui::ipanel()->GetSize(pRoot, wide, tall); - - bool changed = wide != m_nRootSize[ 0 ] || tall != m_nRootSize[ 1 ]; - m_nRootSize[ 0 ] = wide; - m_nRootSize[ 1 ] = tall; - - m_pViewport->SetBounds(0, 0, wide, tall); - if ( changed ) - { - ReloadScheme(); - } - } -} - -float ClientModeShared::GetViewModelFOV( void ) -{ - return v_viewmodel_fov.GetFloat(); -} - -class CHudChat; - -bool PlayerNameNotSetYet( const char *pszName ) -{ - if ( pszName && pszName[0] ) - { - // Don't show "unconnected" if we haven't got the players name yet - if ( Q_strnicmp(pszName,"unconnected",11) == 0 ) - return true; - if ( Q_strnicmp(pszName,"NULLNAME",11) == 0 ) - return true; - } - - return false; -} - -void ClientModeShared::FireGameEvent( IGameEvent *event ) -{ - CBaseHudChat *hudChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat ); - - const char *eventname = event->GetName(); - - if ( Q_strcmp( "player_connect", eventname ) == 0 ) - { - if ( !hudChat ) - return; - if ( PlayerNameNotSetYet(event->GetString("name")) ) - return; - - if ( !IsInCommentaryMode() ) - { - wchar_t wszLocalized[100]; - wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("name"), wszPlayerName, sizeof(wszPlayerName) ); - g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_game" ), 1, wszPlayerName ); - - char szLocalized[100]; - g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); - - hudChat->Printf( CHAT_FILTER_JOINLEAVE, "%s", szLocalized ); - } - } - else if ( Q_strcmp( "player_disconnect", eventname ) == 0 ) - { - C_BasePlayer *pPlayer = USERID2PLAYER( event->GetInt("userid") ); - - if ( !hudChat || !pPlayer ) - return; - if ( PlayerNameNotSetYet(event->GetString("name")) ) - return; - - if ( !IsInCommentaryMode() ) - { - wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( pPlayer->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) ); - - wchar_t wszReason[64]; - const char *pszReason = event->GetString( "reason" ); - if ( pszReason && ( pszReason[0] == '#' ) && g_pVGuiLocalize->Find( pszReason ) ) - { - V_wcsncpy( wszReason, g_pVGuiLocalize->Find( pszReason ), sizeof( wszReason ) ); - } - else - { - g_pVGuiLocalize->ConvertANSIToUnicode( pszReason, wszReason, sizeof(wszReason) ); - } - - wchar_t wszLocalized[100]; - if (IsPC()) - { - g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_left_game" ), 2, wszPlayerName, wszReason ); - } - else - { - g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_left_game" ), 1, wszPlayerName ); - } - - char szLocalized[100]; - g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); - - hudChat->Printf( CHAT_FILTER_JOINLEAVE, "%s", szLocalized ); - } - } - else if ( Q_strcmp( "player_team", eventname ) == 0 ) - { - C_BasePlayer *pPlayer = USERID2PLAYER( event->GetInt("userid") ); - if ( !hudChat ) - return; - - bool bDisconnected = event->GetBool("disconnect"); - - if ( bDisconnected ) - return; - - int team = event->GetInt( "team" ); - bool bAutoTeamed = event->GetInt( "autoteam", false ); - bool bSilent = event->GetInt( "silent", false ); - - const char *pszName = event->GetString( "name" ); - if ( PlayerNameNotSetYet( pszName ) ) - return; - - if ( !bSilent ) - { - wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( pszName, wszPlayerName, sizeof(wszPlayerName) ); - - wchar_t wszTeam[64]; - C_Team *pTeam = GetGlobalTeam( team ); - if ( pTeam ) - { - g_pVGuiLocalize->ConvertANSIToUnicode( pTeam->Get_Name(), wszTeam, sizeof(wszTeam) ); - } - else - { - _snwprintf ( wszTeam, sizeof( wszTeam ) / sizeof( wchar_t ), L"%d", team ); - } - - if ( !IsInCommentaryMode() ) - { - wchar_t wszLocalized[100]; - if ( bAutoTeamed ) - { - g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_autoteam" ), 2, wszPlayerName, wszTeam ); - } - else - { - g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_team" ), 2, wszPlayerName, wszTeam ); - } - - char szLocalized[100]; - g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); - - hudChat->Printf( CHAT_FILTER_TEAMCHANGE, "%s", szLocalized ); - } - } - - if ( pPlayer && pPlayer->IsLocalPlayer() ) - { - // that's me - pPlayer->TeamChange( team ); - } - } - else if ( Q_strcmp( "player_changename", eventname ) == 0 ) - { - if ( !hudChat ) - return; - - const char *pszOldName = event->GetString("oldname"); - if ( PlayerNameNotSetYet(pszOldName) ) - return; - - wchar_t wszOldName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( pszOldName, wszOldName, sizeof(wszOldName) ); - - wchar_t wszNewName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString( "newname" ), wszNewName, sizeof(wszNewName) ); - - wchar_t wszLocalized[100]; - g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_changed_name" ), 2, wszOldName, wszNewName ); - - char szLocalized[100]; - g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); - - hudChat->Printf( CHAT_FILTER_NAMECHANGE, "%s", szLocalized ); - } - else if (Q_strcmp( "teamplay_broadcast_audio", eventname ) == 0 ) - { - int team = event->GetInt( "team" ); - - bool bValidTeam = false; - - if ( (GetLocalTeam() && GetLocalTeam()->GetTeamNumber() == team) ) - { - bValidTeam = true; - } - - //If we're in the spectator team then we should be getting whatever messages the person I'm spectating gets. - if ( bValidTeam == false ) - { - CBasePlayer *pSpectatorTarget = UTIL_PlayerByIndex( GetSpectatorTarget() ); - - if ( pSpectatorTarget && (GetSpectatorMode() == OBS_MODE_IN_EYE || GetSpectatorMode() == OBS_MODE_CHASE) ) - { - if ( pSpectatorTarget->GetTeamNumber() == team ) - { - bValidTeam = true; - } - } - } - - if ( team == 0 && GetLocalTeam() > 0 ) - { - bValidTeam = false; - } - - if ( team == 255 ) - { - bValidTeam = true; - } - - if ( bValidTeam == true ) - { - EmitSound_t et; - et.m_pSoundName = event->GetString("sound"); - et.m_nFlags = event->GetInt("additional_flags"); - - CLocalPlayerFilter filter; - C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, et ); - } - } - else if ( Q_strcmp( "server_cvar", eventname ) == 0 ) - { - if ( !IsInCommentaryMode() ) - { - wchar_t wszCvarName[64]; - g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("cvarname"), wszCvarName, sizeof(wszCvarName) ); - - wchar_t wszCvarValue[64]; - g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("cvarvalue"), wszCvarValue, sizeof(wszCvarValue) ); - - wchar_t wszLocalized[256]; - g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_server_cvar_changed" ), 2, wszCvarName, wszCvarValue ); - - char szLocalized[256]; - g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); - - hudChat->Printf( CHAT_FILTER_SERVERMSG, "%s", szLocalized ); - } - } - else if ( Q_strcmp( "achievement_earned", eventname ) == 0 ) - { - int iPlayerIndex = event->GetInt( "player" ); - C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex ); - int iAchievement = event->GetInt( "achievement" ); - - if ( !hudChat || !pPlayer ) - return; - - if ( !IsInCommentaryMode() ) - { - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - IAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievement ); - if ( pAchievement ) - { - if ( !pPlayer->IsDormant() && pPlayer->ShouldAnnounceAchievement() ) - { - pPlayer->SetNextAchievementAnnounceTime( gpGlobals->curtime + ACHIEVEMENT_ANNOUNCEMENT_MIN_TIME ); - - // no particle effect if the local player is the one with the achievement or the player is dead - if ( !pPlayer->IsLocalPlayer() && pPlayer->IsAlive() ) - { - //tagES using the "head" attachment won't work for CS and DoD - pPlayer->ParticleProp()->Create( "achieved", PATTACH_POINT_FOLLOW, "head" ); - } - - pPlayer->OnAchievementAchieved( iAchievement ); - } - - if ( g_PR ) - { - wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( g_PR->GetPlayerName( iPlayerIndex ), wszPlayerName, sizeof( wszPlayerName ) ); - - const wchar_t *pchLocalizedAchievement = ACHIEVEMENT_LOCALIZED_NAME_FROM_STR( pAchievement->GetName() ); - if ( pchLocalizedAchievement ) - { - wchar_t wszLocalizedString[128]; - g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), g_pVGuiLocalize->Find( "#Achievement_Earned" ), 2, wszPlayerName, pchLocalizedAchievement ); - - char szLocalized[128]; - g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) ); - - hudChat->ChatPrintf( iPlayerIndex, CHAT_FILTER_SERVERMSG, "%s", szLocalized ); - } - } - } - } - } -#if defined( TF_CLIENT_DLL ) - else if ( Q_strcmp( "item_found", eventname ) == 0 ) - { - int iPlayerIndex = event->GetInt( "player" ); - entityquality_t iItemQuality = event->GetInt( "quality" ); - int iMethod = event->GetInt( "method" ); - int iItemDef = event->GetInt( "itemdef" ); - C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex ); - const GameItemDefinition_t *pItemDefinition = dynamic_cast( GetItemSchema()->GetItemDefinition( iItemDef ) ); - - if ( !pPlayer || !pItemDefinition ) - return; - - if ( g_PR ) - { - wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; - g_pVGuiLocalize->ConvertANSIToUnicode( g_PR->GetPlayerName( iPlayerIndex ), wszPlayerName, sizeof( wszPlayerName ) ); - - if ( iMethod < 0 || iMethod >= ARRAYSIZE( g_pszItemFoundMethodStrings ) ) - { - iMethod = 0; - } - - const char *pszLocString = g_pszItemFoundMethodStrings[iMethod]; - if ( pszLocString ) - { - wchar_t wszItemFound[256]; - _snwprintf( wszItemFound, ARRAYSIZE( wszItemFound ), L"%ls", g_pVGuiLocalize->Find( pszLocString ) ); - - wchar_t *colorMarker = wcsstr( wszItemFound, L"::" ); - if ( colorMarker ) - { - const char *pszQualityColorString = EconQuality_GetColorString( (EEconItemQuality)iItemQuality ); - if ( pszQualityColorString ) - { - hudChat->SetCustomColor( pszQualityColorString ); - *(colorMarker+1) = COLOR_CUSTOM; - } - } - - // TODO: Update the localization strings to only have two format parameters since that's all we need. - wchar_t wszLocalizedString[256]; - g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), wszItemFound, 3, wszPlayerName, CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pItemDefinition, iItemQuality ).GetFullName(), L"" ); - - char szLocalized[256]; - g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) ); - - hudChat->ChatPrintf( iPlayerIndex, CHAT_FILTER_SERVERMSG, "%s", szLocalized ); - } - } - } -#endif -#if defined( REPLAY_ENABLED ) - else if ( !V_strcmp( "replay_servererror", eventname ) ) - { - DisplayReplayMessage( event->GetString( "error", "#Replay_DefaultServerError" ), replay_msgduration_error.GetFloat(), true, NULL, false ); - } - else if ( !V_strcmp( "replay_startrecord", eventname ) ) - { - m_flReplayStartRecordTime = gpGlobals->curtime; - } - else if ( !V_strcmp( "replay_endrecord", eventname ) ) - { - m_flReplayStopRecordTime = gpGlobals->curtime; - } - else if ( !V_strcmp( "replay_replaysavailable", eventname ) ) - { - DisplayReplayMessage( "#Replay_ReplaysAvailable", replay_msgduration_replaysavailable.GetFloat(), false, NULL, false ); - } - - else if ( !V_strcmp( "game_newmap", eventname ) ) - { - // Make sure the instance count is reset to 0. Sometimes the count stay in sync and we get replay messages displaying lower than they should. - CReplayMessagePanel::RemoveAll(); - } -#endif - - else - { - DevMsg( 2, "Unhandled GameEvent in ClientModeShared::FireGameEvent - %s\n", event->GetName() ); - } -} - -void ClientModeShared::UpdateReplayMessages() -{ -#if defined( REPLAY_ENABLED ) - // Received a replay_startrecord event? - if ( m_flReplayStartRecordTime != 0.0f ) - { - DisplayReplayMessage( "#Replay_StartRecord", replay_msgduration_startrecord.GetFloat(), true, "replay\\startrecord.mp3", false ); - - m_flReplayStartRecordTime = 0.0f; - m_flReplayStopRecordTime = 0.0f; - } - - // Received a replay_endrecord event? - if ( m_flReplayStopRecordTime != 0.0f ) - { - DisplayReplayMessage( "#Replay_EndRecord", replay_msgduration_stoprecord.GetFloat(), true, "replay\\stoprecord.wav", false ); - - // Hide the replay reminder - if ( m_pReplayReminderPanel ) - { - m_pReplayReminderPanel->Hide(); - } - - m_flReplayStopRecordTime = 0.0f; - } - - if ( !engine->IsConnected() ) - { - ClearReplayMessageList(); - } -#endif -} - -void ClientModeShared::ClearReplayMessageList() -{ -#if defined( REPLAY_ENABLED ) - CReplayMessagePanel::RemoveAll(); -#endif -} - -void ClientModeShared::DisplayReplayMessage( const char *pLocalizeName, float flDuration, bool bUrgent, - const char *pSound, bool bDlg ) -{ -#if defined( REPLAY_ENABLED ) - // Don't display during replay playback, and don't allow more than 4 at a time - const bool bInReplay = g_pEngineClientReplay->IsPlayingReplayDemo(); - if ( bInReplay || ( !bDlg && CReplayMessagePanel::InstanceCount() >= 4 ) ) - return; - - // Use default duration? - if ( flDuration == -1.0f ) - { - flDuration = replay_msgduration_misc.GetFloat(); - } - - // Display a replay message - if ( bDlg ) - { - if ( engine->IsInGame() ) - { - Panel *pPanel = new CReplayMessageDlg( pLocalizeName ); - pPanel->SetVisible( true ); - pPanel->MakePopup(); - pPanel->MoveToFront(); - pPanel->SetKeyBoardInputEnabled( true ); - pPanel->SetMouseInputEnabled( true ); -#if defined( TF_CLIENT_DLL ) - TFModalStack()->PushModal( pPanel ); -#endif - } - else - { - ShowMessageBox( "#Replay_GenericMsgTitle", pLocalizeName, "#GameUI_OK" ); - } - } - else - { - CReplayMessagePanel *pMsgPanel = new CReplayMessagePanel( pLocalizeName, flDuration, bUrgent ); - pMsgPanel->Show(); - } - - // Play a sound if appropriate - if ( pSound ) - { - surface()->PlaySound( pSound ); - } -#endif -} - -void ClientModeShared::DisplayReplayReminder() -{ -#if defined( REPLAY_ENABLED ) - if ( m_pReplayReminderPanel && g_pReplay->IsRecording() ) - { - // Only display the panel if we haven't already requested a replay for the given life - CReplay *pCurLifeReplay = static_cast< CReplay * >( g_pClientReplayContext->GetReplayManager()->GetReplayForCurrentLife() ); - if ( pCurLifeReplay && !pCurLifeReplay->m_bRequestedByUser && !pCurLifeReplay->m_bSaved ) - { - m_pReplayReminderPanel->Show(); - } - } -#endif -} - - -//----------------------------------------------------------------------------- -// In-game VGUI context -//----------------------------------------------------------------------------- -void ClientModeShared::ActivateInGameVGuiContext( vgui::Panel *pPanel ) -{ - vgui::ivgui()->AssociatePanelWithContext( s_hVGuiContext, pPanel->GetVPanel() ); - vgui::ivgui()->ActivateContext( s_hVGuiContext ); -} - -void ClientModeShared::DeactivateInGameVGuiContext() -{ - vgui::ivgui()->ActivateContext( DEFAULT_VGUI_CONTEXT ); -} - +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Normal HUD mode +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + + +#include "cbase.h" +#include "clientmode_shared.h" +#include "iinput.h" +#include "view_shared.h" +#include "iviewrender.h" +#include "hud_basechat.h" +#include "weapon_selection.h" +#include +#include +#include +#include +#include "engine/IEngineSound.h" +#include +#include +#include "vgui_int.h" +#include "hud_macros.h" +#include "hltvcamera.h" +#include "particlemgr.h" +#include "c_vguiscreen.h" +#include "c_team.h" +#include "c_rumble.h" +#include "fmtstr.h" +#include "achievementmgr.h" +#include "c_playerresource.h" +#include "cam_thirdperson.h" +#include +#include "hud_vote.h" +#include "ienginevgui.h" +#include "headtrack/isourcevirtualreality.h" +#if defined( _X360 ) +#include "xbox/xbox_console.h" +#endif + +#if defined( REPLAY_ENABLED ) +#include "replay/replaycamera.h" +#include "replay/ireplaysystem.h" +#include "replay/iclientreplaycontext.h" +#include "replay/ireplaymanager.h" +#include "replay/replay.h" +#include "replay/ienginereplay.h" +#include "replay/vgui/replayreminderpanel.h" +#include "replay/vgui/replaymessagepanel.h" +#include "econ/econ_controls.h" +#include "econ/confirm_dialog.h" +extern IClientReplayContext *g_pClientReplayContext; +extern ConVar replay_rendersetting_renderglow; +#endif + +#if defined USES_ECON_ITEMS +#include "econ_item_view.h" +#endif + +#if defined( TF_CLIENT_DLL ) +#include "c_tf_player.h" +#include "econ_item_description.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define ACHIEVEMENT_ANNOUNCEMENT_MIN_TIME 10 + +class CHudWeaponSelection; +class CHudChat; +class CHudVote; + +static vgui::HContext s_hVGuiContext = DEFAULT_VGUI_CONTEXT; + +ConVar cl_drawhud( "cl_drawhud", "1", FCVAR_CHEAT, "Enable the rendering of the hud" ); +ConVar hud_takesshots( "hud_takesshots", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Auto-save a scoreboard screenshot at the end of a map." ); +ConVar hud_freezecamhide( "hud_freezecamhide", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Hide the HUD during freeze-cam" ); +ConVar cl_show_num_particle_systems( "cl_show_num_particle_systems", "0", FCVAR_CLIENTDLL, "Display the number of active particle systems." ); + +extern ConVar v_viewmodel_fov; +extern ConVar voice_modenable; + +extern bool IsInCommentaryMode( void ); + +#ifdef VOICE_VOX_ENABLE +void VoxCallback( IConVar *var, const char *oldString, float oldFloat ) +{ + if ( engine && engine->IsConnected() ) + { + ConVarRef voice_vox( var->GetName() ); + if ( voice_vox.GetBool() && voice_modenable.GetBool() ) + { + engine->ClientCmd_Unrestricted( "voicerecord_toggle on\n" ); + } + else + { + engine->ClientCmd_Unrestricted( "voicerecord_toggle off\n" ); + } + } +} +ConVar voice_vox( "voice_vox", "0", FCVAR_ARCHIVE, "Voice chat uses a vox-style always on", true, 0, true, 1, VoxCallback ); + +// --------------------------------------------------------------------------------- // +// CVoxManager. +// --------------------------------------------------------------------------------- // +class CVoxManager : public CAutoGameSystem +{ +public: + CVoxManager() : CAutoGameSystem( "VoxManager" ) + { + } + + virtual void LevelInitPostEntity( void ) + { + if ( voice_vox.GetBool() && voice_modenable.GetBool() ) + { + engine->ClientCmd_Unrestricted( "voicerecord_toggle on\n" ); + } + } + + virtual void LevelShutdownPreEntity( void ) + { + if ( voice_vox.GetBool() ) + { + engine->ClientCmd_Unrestricted( "voicerecord_toggle off\n" ); + } + } +}; + +static CVoxManager s_VoxManager; +// --------------------------------------------------------------------------------- // +#endif // VOICE_VOX_ENABLE + +CON_COMMAND( hud_reloadscheme, "Reloads hud layout and animation scripts." ) +{ + ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); + if ( !mode ) + return; + + mode->ReloadScheme(); +} + +#ifdef _DEBUG +CON_COMMAND_F( crash, "Crash the client. Optional parameter -- type of crash:\n 0: read from NULL\n 1: write to NULL\n 2: DmCrashDump() (xbox360 only)", FCVAR_CHEAT ) +{ + int crashtype = 0; + int dummy; + if ( args.ArgC() > 1 ) + { + crashtype = Q_atoi( args[1] ); + } + switch (crashtype) + { + case 0: + dummy = *((int *) NULL); + Msg("Crashed! %d\n", dummy); // keeps dummy from optimizing out + break; + case 1: + *((int *)NULL) = 42; + break; +#if defined( _X360 ) + case 2: + XBX_CrashDump(false); + break; +#endif + default: + Msg("Unknown variety of crash. You have now failed to crash. I hope you're happy.\n"); + break; + } +} +#endif // _DEBUG + +static void __MsgFunc_Rumble( bf_read &msg ) +{ + unsigned char waveformIndex; + unsigned char rumbleData; + unsigned char rumbleFlags; + + waveformIndex = msg.ReadByte(); + rumbleData = msg.ReadByte(); + rumbleFlags = msg.ReadByte(); + + RumbleEffect( waveformIndex, rumbleData, rumbleFlags ); +} + +static void __MsgFunc_VGUIMenu( bf_read &msg ) +{ + char panelname[2048]; + + msg.ReadString( panelname, sizeof(panelname) ); + + bool bShow = msg.ReadByte()!=0; + + IViewPortPanel *viewport = gViewPortInterface->FindPanelByName( panelname ); + + if ( !viewport ) + { + // DevMsg("VGUIMenu: couldn't find panel '%s'.\n", panelname ); + return; + } + + int count = msg.ReadByte(); + + if ( count > 0 ) + { + KeyValues *keys = new KeyValues("data"); + + for ( int i=0; iSetString( name, data ); + } + + viewport->SetData( keys ); + + keys->deleteThis(); + } + + // is the server telling us to show the scoreboard (at the end of a map)? + if ( Q_stricmp( panelname, "scores" ) == 0 ) + { + if ( hud_takesshots.GetBool() == true ) + { + gHUD.SetScreenShotTime( gpGlobals->curtime + 1.0 ); // take a screenshot in 1 second + } + } + + // is the server trying to show an MOTD panel? Check that it's allowed right now. + ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); + if ( Q_stricmp( panelname, PANEL_INFO ) == 0 && mode ) + { + if ( !mode->IsInfoPanelAllowed() ) + { + return; + } + else + { + mode->InfoPanelDisplayed(); + } + } + + gViewPortInterface->ShowPanel( viewport, bShow ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +ClientModeShared::ClientModeShared() +{ + m_pViewport = NULL; + m_pChatElement = NULL; + m_pWeaponSelection = NULL; + m_nRootSize[ 0 ] = m_nRootSize[ 1 ] = -1; + +#if defined( REPLAY_ENABLED ) + m_pReplayReminderPanel = NULL; + m_flReplayStartRecordTime = 0.0f; + m_flReplayStopRecordTime = 0.0f; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +ClientModeShared::~ClientModeShared() +{ + delete m_pViewport; +} + +void ClientModeShared::ReloadScheme( void ) +{ + m_pViewport->ReloadScheme( "resource/ClientScheme.res" ); + ClearKeyValuesCache(); +} + + +//---------------------------------------------------------------------------- +// Purpose: Let the client mode set some vgui conditions +//----------------------------------------------------------------------------- +void ClientModeShared::ComputeVguiResConditions( KeyValues *pkvConditions ) +{ + if ( UseVR() ) + { + pkvConditions->FindKey( "if_vr", true ); + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeShared::Init() +{ + m_pChatElement = ( CBaseHudChat * )GET_HUDELEMENT( CHudChat ); + Assert( m_pChatElement ); + + m_pWeaponSelection = ( CBaseHudWeaponSelection * )GET_HUDELEMENT( CHudWeaponSelection ); + Assert( m_pWeaponSelection ); + + KeyValuesAD pConditions( "conditions" ); + ComputeVguiResConditions( pConditions ); + + // Derived ClientMode class must make sure m_Viewport is instantiated + Assert( m_pViewport ); + m_pViewport->LoadControlSettings( "scripts/HudLayout.res", NULL, NULL, pConditions ); + +#if defined( REPLAY_ENABLED ) + m_pReplayReminderPanel = GET_HUDELEMENT( CReplayReminderPanel ); + Assert( m_pReplayReminderPanel ); +#endif + + ListenForGameEvent( "player_connect" ); + ListenForGameEvent( "player_disconnect" ); + ListenForGameEvent( "player_team" ); + ListenForGameEvent( "server_cvar" ); + ListenForGameEvent( "player_changename" ); + ListenForGameEvent( "teamplay_broadcast_audio" ); + ListenForGameEvent( "achievement_earned" ); + +#if defined( TF_CLIENT_DLL ) + ListenForGameEvent( "item_found" ); +#endif + +#if defined( REPLAY_ENABLED ) + ListenForGameEvent( "replay_startrecord" ); + ListenForGameEvent( "replay_endrecord" ); + ListenForGameEvent( "replay_replaysavailable" ); + ListenForGameEvent( "replay_servererror" ); + ListenForGameEvent( "game_newmap" ); +#endif + +#ifndef _XBOX + HLTVCamera()->Init(); +#if defined( REPLAY_ENABLED ) + ReplayCamera()->Init(); +#endif +#endif + + m_CursorNone = vgui::dc_none; + + HOOK_MESSAGE( VGUIMenu ); + HOOK_MESSAGE( Rumble ); +} + + +void ClientModeShared::InitViewport() +{ +} + + +void ClientModeShared::VGui_Shutdown() +{ + delete m_pViewport; + m_pViewport = NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeShared::Shutdown() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : frametime - +// *cmd - +//----------------------------------------------------------------------------- +bool ClientModeShared::CreateMove( float flInputSampleTime, CUserCmd *cmd ) +{ + // Let the player override the view. + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if(!pPlayer) + return true; + + // Let the player at it + return pPlayer->CreateMove( flInputSampleTime, cmd ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSetup - +//----------------------------------------------------------------------------- +void ClientModeShared::OverrideView( CViewSetup *pSetup ) +{ + QAngle camAngles; + + // Let the player override the view. + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if(!pPlayer) + return; + + pPlayer->OverrideView( pSetup ); + + if( ::input->CAM_IsThirdPerson() ) + { + Vector cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles(); + Vector cam_ofs_distance = g_ThirdPersonManager.GetFinalCameraOffset(); + + cam_ofs_distance *= g_ThirdPersonManager.GetDistanceFraction(); + + camAngles[ PITCH ] = cam_ofs[ PITCH ]; + camAngles[ YAW ] = cam_ofs[ YAW ]; + camAngles[ ROLL ] = 0; + + Vector camForward, camRight, camUp; + + + if ( g_ThirdPersonManager.IsOverridingThirdPerson() == false ) + { + engine->GetViewAngles( camAngles ); + } + + // get the forward vector + AngleVectors( camAngles, &camForward, &camRight, &camUp ); + + VectorMA( pSetup->origin, -cam_ofs_distance[0], camForward, pSetup->origin ); + VectorMA( pSetup->origin, cam_ofs_distance[1], camRight, pSetup->origin ); + VectorMA( pSetup->origin, cam_ofs_distance[2], camUp, pSetup->origin ); + + // Override angles from third person camera + VectorCopy( camAngles, pSetup->angles ); + } + else if (::input->CAM_IsOrthographic()) + { + pSetup->m_bOrtho = true; + float w, h; + ::input->CAM_OrthographicSize( w, h ); + w *= 0.5f; + h *= 0.5f; + pSetup->m_OrthoLeft = -w; + pSetup->m_OrthoTop = -h; + pSetup->m_OrthoRight = w; + pSetup->m_OrthoBottom = h; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool ClientModeShared::ShouldDrawEntity(C_BaseEntity *pEnt) +{ + return true; +} + +bool ClientModeShared::ShouldDrawParticles( ) +{ + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Allow weapons to override mouse input (for binoculars) +//----------------------------------------------------------------------------- +void ClientModeShared::OverrideMouseInput( float *x, float *y ) +{ + C_BaseCombatWeapon *pWeapon = GetActiveWeapon(); + if ( pWeapon ) + { + pWeapon->OverrideMouseInput( x, y ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool ClientModeShared::ShouldDrawViewModel() +{ + return true; +} + +bool ClientModeShared::ShouldDrawDetailObjects( ) +{ + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns true if VR mode should black out everything outside the HUD. +// This is used for things like sniper scopes and full screen UI +//----------------------------------------------------------------------------- +bool ClientModeShared::ShouldBlackoutAroundHUD() +{ + return enginevgui->IsGameUIVisible(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Allows the client mode to override mouse control stuff in headtrack +//----------------------------------------------------------------------------- +HeadtrackMovementMode_t ClientModeShared::ShouldOverrideHeadtrackControl() +{ + return HMM_NOOVERRIDE; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ClientModeShared::ShouldDrawCrosshair( void ) +{ + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Don't draw the current view entity if we are using the fake viewmodel instead +//----------------------------------------------------------------------------- +bool ClientModeShared::ShouldDrawLocalPlayer( C_BasePlayer *pPlayer ) +{ + if ( ( pPlayer->index == render->GetViewEntity() ) && !C_BasePlayer::ShouldDrawLocalPlayer() ) + return false; + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: The mode can choose to not draw fog +//----------------------------------------------------------------------------- +bool ClientModeShared::ShouldDrawFog( void ) +{ + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeShared::AdjustEngineViewport( int& x, int& y, int& width, int& height ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeShared::PreRender( CViewSetup *pSetup ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeShared::PostRender() +{ + // Let the particle manager simulate things that haven't been simulated. + ParticleMgr()->PostRender(); +} + +void ClientModeShared::PostRenderVGui() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeShared::Update() +{ +#if defined( REPLAY_ENABLED ) + UpdateReplayMessages(); +#endif + + if ( m_pViewport->IsVisible() != cl_drawhud.GetBool() ) + { + m_pViewport->SetVisible( cl_drawhud.GetBool() ); + } + + UpdateRumbleEffects(); + + if ( cl_show_num_particle_systems.GetBool() ) + { + int nCount = 0; + + for ( int i = 0; i < g_pParticleSystemMgr->GetParticleSystemCount(); i++ ) + { + const char *pParticleSystemName = g_pParticleSystemMgr->GetParticleSystemNameFromIndex(i); + CParticleSystemDefinition *pParticleSystem = g_pParticleSystemMgr->FindParticleSystem( pParticleSystemName ); + if ( !pParticleSystem ) + continue; + + for ( CParticleCollection *pCurCollection = pParticleSystem->FirstCollection(); + pCurCollection != NULL; + pCurCollection = pCurCollection->GetNextCollectionUsingSameDef() ) + { + ++nCount; + } + } + + engine->Con_NPrintf( 0, "# Active particle systems: %i", nCount ); + } +} + +//----------------------------------------------------------------------------- +// This processes all input before SV Move messages are sent +//----------------------------------------------------------------------------- + +void ClientModeShared::ProcessInput(bool bActive) +{ + gHUD.ProcessInput( bActive ); +} + +//----------------------------------------------------------------------------- +// Purpose: We've received a keypress from the engine. Return 1 if the engine is allowed to handle it. +//----------------------------------------------------------------------------- +int ClientModeShared::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) +{ + if ( engine->Con_IsVisible() ) + return 1; + + // Should we start typing a message? + if ( pszCurrentBinding && + ( Q_strcmp( pszCurrentBinding, "messagemode" ) == 0 || + Q_strcmp( pszCurrentBinding, "say" ) == 0 ) ) + { + if ( down ) + { + StartMessageMode( MM_SAY ); + } + return 0; + } + else if ( pszCurrentBinding && + ( Q_strcmp( pszCurrentBinding, "messagemode2" ) == 0 || + Q_strcmp( pszCurrentBinding, "say_team" ) == 0 ) ) + { + if ( down ) + { + StartMessageMode( MM_SAY_TEAM ); + } + return 0; + } + + // If we're voting... +#ifdef VOTING_ENABLED + CHudVote *pHudVote = GET_HUDELEMENT( CHudVote ); + if ( pHudVote && pHudVote->IsVisible() ) + { + if ( !pHudVote->KeyInput( down, keynum, pszCurrentBinding ) ) + { + return 0; + } + } +#endif + + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + // if ingame spectator mode, let spectator input intercept key event here + if( pPlayer && + ( pPlayer->GetObserverMode() > OBS_MODE_DEATHCAM ) && + !HandleSpectatorKeyInput( down, keynum, pszCurrentBinding ) ) + { + return 0; + } + + // Let game-specific hud elements get a crack at the key input + if ( !HudElementKeyInput( down, keynum, pszCurrentBinding ) ) + { + return 0; + } + + C_BaseCombatWeapon *pWeapon = GetActiveWeapon(); + if ( pWeapon ) + { + return pWeapon->KeyInput( down, keynum, pszCurrentBinding ); + } + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: See if spectator input occurred. Return 0 if the key is swallowed. +//----------------------------------------------------------------------------- +int ClientModeShared::HandleSpectatorKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) +{ + // we are in spectator mode, open spectator menu + if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+duck" ) == 0 ) + { + m_pViewport->ShowPanel( PANEL_SPECMENU, true ); + return 0; // we handled it, don't handle twice or send to server + } + else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+attack" ) == 0 ) + { + engine->ClientCmd( "spec_next" ); + return 0; + } + else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+attack2" ) == 0 ) + { + engine->ClientCmd( "spec_prev" ); + return 0; + } + else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+jump" ) == 0 ) + { + engine->ClientCmd( "spec_mode" ); + return 0; + } + else if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+strafe" ) == 0 ) + { + HLTVCamera()->SetAutoDirector( true ); +#if defined( REPLAY_ENABLED ) + ReplayCamera()->SetAutoDirector( true ); +#endif + return 0; + } + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: See if hud elements want key input. Return 0 if the key is swallowed +//----------------------------------------------------------------------------- +int ClientModeShared::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) +{ + if ( m_pWeaponSelection ) + { + if ( !m_pWeaponSelection->KeyInput( down, keynum, pszCurrentBinding ) ) + { + return 0; + } + } + +#if defined( REPLAY_ENABLED ) + if ( m_pReplayReminderPanel ) + { + if ( m_pReplayReminderPanel->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) + { + return 0; + } + } +#endif + + return 1; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool ClientModeShared::DoPostScreenSpaceEffects( const CViewSetup *pSetup ) +{ +#if defined( REPLAY_ENABLED ) + if ( engine->IsPlayingDemo() ) + { + if ( !replay_rendersetting_renderglow.GetBool() ) + return false; + } +#endif + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : vgui::Panel +//----------------------------------------------------------------------------- +vgui::Panel *ClientModeShared::GetMessagePanel() +{ + if ( m_pChatElement && m_pChatElement->GetInputPanel() && m_pChatElement->GetInputPanel()->IsVisible() ) + return m_pChatElement->GetInputPanel(); + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: The player has started to type a message +//----------------------------------------------------------------------------- +void ClientModeShared::StartMessageMode( int iMessageModeType ) +{ + // Can only show chat UI in multiplayer!!! + if ( gpGlobals->maxClients == 1 ) + { + return; + } + if ( m_pChatElement ) + { + m_pChatElement->StartMessageMode( iMessageModeType ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *newmap - +//----------------------------------------------------------------------------- +void ClientModeShared::LevelInit( const char *newmap ) +{ + m_pViewport->GetAnimationController()->StartAnimationSequence("LevelInit"); + + // Tell the Chat Interface + if ( m_pChatElement ) + { + m_pChatElement->LevelInit( newmap ); + } + + // we have to fake this event clientside, because clients connect after that + IGameEvent *event = gameeventmanager->CreateEvent( "game_newmap" ); + if ( event ) + { + event->SetString("mapname", newmap ); + gameeventmanager->FireEventClientSide( event ); + } + + // Create a vgui context for all of the in-game vgui panels... + if ( s_hVGuiContext == DEFAULT_VGUI_CONTEXT ) + { + s_hVGuiContext = vgui::ivgui()->CreateContext(); + } + + // Reset any player explosion/shock effects + CLocalPlayerFilter filter; + enginesound->SetPlayerDSP( filter, 0, true ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeShared::LevelShutdown( void ) +{ + // Reset the third person camera so we don't crash + g_ThirdPersonManager.Init(); + + if ( m_pChatElement ) + { + m_pChatElement->LevelShutdown(); + } + if ( s_hVGuiContext != DEFAULT_VGUI_CONTEXT ) + { + vgui::ivgui()->DestroyContext( s_hVGuiContext ); + s_hVGuiContext = DEFAULT_VGUI_CONTEXT; + } + + // Reset any player explosion/shock effects + CLocalPlayerFilter filter; + enginesound->SetPlayerDSP( filter, 0, true ); +} + + +void ClientModeShared::Enable() +{ + vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();; + + // Add our viewport to the root panel. + if( pRoot != 0 ) + { + m_pViewport->SetParent( pRoot ); + } + + // All hud elements should be proportional + // This sets that flag on the viewport and all child panels + m_pViewport->SetProportional( true ); + + m_pViewport->SetCursor( m_CursorNone ); + vgui::surface()->SetCursor( m_CursorNone ); + + m_pViewport->SetVisible( true ); + if ( m_pViewport->IsKeyBoardInputEnabled() ) + { + m_pViewport->RequestFocus(); + } + + Layout(); +} + + +void ClientModeShared::Disable() +{ + vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();; + + // Remove our viewport from the root panel. + if( pRoot != 0 ) + { + m_pViewport->SetParent( (vgui::VPANEL)NULL ); + } + + m_pViewport->SetVisible( false ); +} + + +void ClientModeShared::Layout() +{ + vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel(); + int wide, tall; + + // Make the viewport fill the root panel. + if( pRoot != 0 ) + { + vgui::ipanel()->GetSize(pRoot, wide, tall); + + bool changed = wide != m_nRootSize[ 0 ] || tall != m_nRootSize[ 1 ]; + m_nRootSize[ 0 ] = wide; + m_nRootSize[ 1 ] = tall; + + m_pViewport->SetBounds(0, 0, wide, tall); + if ( changed ) + { + ReloadScheme(); + } + } +} + +float ClientModeShared::GetViewModelFOV( void ) +{ + return v_viewmodel_fov.GetFloat(); +} + +class CHudChat; + +bool PlayerNameNotSetYet( const char *pszName ) +{ + if ( pszName && pszName[0] ) + { + // Don't show "unconnected" if we haven't got the players name yet + if ( Q_strnicmp(pszName,"unconnected",11) == 0 ) + return true; + if ( Q_strnicmp(pszName,"NULLNAME",11) == 0 ) + return true; + } + + return false; +} + +void ClientModeShared::FireGameEvent( IGameEvent *event ) +{ + CBaseHudChat *hudChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat ); + + const char *eventname = event->GetName(); + + if ( Q_strcmp( "player_connect", eventname ) == 0 ) + { + if ( !hudChat ) + return; + if ( PlayerNameNotSetYet(event->GetString("name")) ) + return; + + if ( !IsInCommentaryMode() ) + { + wchar_t wszLocalized[100]; + wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("name"), wszPlayerName, sizeof(wszPlayerName) ); + g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_game" ), 1, wszPlayerName ); + + char szLocalized[100]; + g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); + + hudChat->Printf( CHAT_FILTER_JOINLEAVE, "%s", szLocalized ); + } + } + else if ( Q_strcmp( "player_disconnect", eventname ) == 0 ) + { + C_BasePlayer *pPlayer = USERID2PLAYER( event->GetInt("userid") ); + + if ( !hudChat || !pPlayer ) + return; + if ( PlayerNameNotSetYet(event->GetString("name")) ) + return; + + if ( !IsInCommentaryMode() ) + { + wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( pPlayer->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) ); + + wchar_t wszReason[64]; + const char *pszReason = event->GetString( "reason" ); + if ( pszReason && ( pszReason[0] == '#' ) && g_pVGuiLocalize->Find( pszReason ) ) + { + V_wcsncpy( wszReason, g_pVGuiLocalize->Find( pszReason ), sizeof( wszReason ) ); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode( pszReason, wszReason, sizeof(wszReason) ); + } + + wchar_t wszLocalized[100]; + if (IsPC()) + { + g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_left_game" ), 2, wszPlayerName, wszReason ); + } + else + { + g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_left_game" ), 1, wszPlayerName ); + } + + char szLocalized[100]; + g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); + + hudChat->Printf( CHAT_FILTER_JOINLEAVE, "%s", szLocalized ); + } + } + else if ( Q_strcmp( "player_team", eventname ) == 0 ) + { + C_BasePlayer *pPlayer = USERID2PLAYER( event->GetInt("userid") ); + if ( !hudChat ) + return; + + bool bDisconnected = event->GetBool("disconnect"); + + if ( bDisconnected ) + return; + + int team = event->GetInt( "team" ); + bool bAutoTeamed = event->GetInt( "autoteam", false ); + bool bSilent = event->GetInt( "silent", false ); + + const char *pszName = event->GetString( "name" ); + if ( PlayerNameNotSetYet( pszName ) ) + return; + + if ( !bSilent ) + { + wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( pszName, wszPlayerName, sizeof(wszPlayerName) ); + + wchar_t wszTeam[64]; + C_Team *pTeam = GetGlobalTeam( team ); + if ( pTeam ) + { + g_pVGuiLocalize->ConvertANSIToUnicode( pTeam->Get_Name(), wszTeam, sizeof(wszTeam) ); + } + else + { + _snwprintf ( wszTeam, sizeof( wszTeam ) / sizeof( wchar_t ), L"%d", team ); + } + + if ( !IsInCommentaryMode() ) + { + wchar_t wszLocalized[100]; + if ( bAutoTeamed ) + { + g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_autoteam" ), 2, wszPlayerName, wszTeam ); + } + else + { + g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_team" ), 2, wszPlayerName, wszTeam ); + } + + char szLocalized[100]; + g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); + + hudChat->Printf( CHAT_FILTER_TEAMCHANGE, "%s", szLocalized ); + } + } + + if ( pPlayer && pPlayer->IsLocalPlayer() ) + { + // that's me + pPlayer->TeamChange( team ); + } + } + else if ( Q_strcmp( "player_changename", eventname ) == 0 ) + { + if ( !hudChat ) + return; + + const char *pszOldName = event->GetString("oldname"); + if ( PlayerNameNotSetYet(pszOldName) ) + return; + + wchar_t wszOldName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( pszOldName, wszOldName, sizeof(wszOldName) ); + + wchar_t wszNewName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString( "newname" ), wszNewName, sizeof(wszNewName) ); + + wchar_t wszLocalized[100]; + g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_changed_name" ), 2, wszOldName, wszNewName ); + + char szLocalized[100]; + g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); + + hudChat->Printf( CHAT_FILTER_NAMECHANGE, "%s", szLocalized ); + } + else if (Q_strcmp( "teamplay_broadcast_audio", eventname ) == 0 ) + { + int team = event->GetInt( "team" ); + + bool bValidTeam = false; + + if ( (GetLocalTeam() && GetLocalTeam()->GetTeamNumber() == team) ) + { + bValidTeam = true; + } + + //If we're in the spectator team then we should be getting whatever messages the person I'm spectating gets. + if ( bValidTeam == false ) + { + CBasePlayer *pSpectatorTarget = UTIL_PlayerByIndex( GetSpectatorTarget() ); + + if ( pSpectatorTarget && (GetSpectatorMode() == OBS_MODE_IN_EYE || GetSpectatorMode() == OBS_MODE_CHASE) ) + { + if ( pSpectatorTarget->GetTeamNumber() == team ) + { + bValidTeam = true; + } + } + } + + if ( team == 0 && GetLocalTeam() > 0 ) + { + bValidTeam = false; + } + + if ( team == 255 ) + { + bValidTeam = true; + } + + if ( bValidTeam == true ) + { + EmitSound_t et; + et.m_pSoundName = event->GetString("sound"); + et.m_nFlags = event->GetInt("additional_flags"); + + CLocalPlayerFilter filter; + C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, et ); + } + } + else if ( Q_strcmp( "server_cvar", eventname ) == 0 ) + { + if ( !IsInCommentaryMode() ) + { + wchar_t wszCvarName[64]; + g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("cvarname"), wszCvarName, sizeof(wszCvarName) ); + + wchar_t wszCvarValue[64]; + g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("cvarvalue"), wszCvarValue, sizeof(wszCvarValue) ); + + wchar_t wszLocalized[256]; + g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_server_cvar_changed" ), 2, wszCvarName, wszCvarValue ); + + char szLocalized[256]; + g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) ); + + hudChat->Printf( CHAT_FILTER_SERVERMSG, "%s", szLocalized ); + } + } + else if ( Q_strcmp( "achievement_earned", eventname ) == 0 ) + { + int iPlayerIndex = event->GetInt( "player" ); + C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex ); + int iAchievement = event->GetInt( "achievement" ); + + if ( !hudChat || !pPlayer ) + return; + + if ( !IsInCommentaryMode() ) + { + CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); + if ( !pAchievementMgr ) + return; + + IAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievement ); + if ( pAchievement ) + { + if ( !pPlayer->IsDormant() && pPlayer->ShouldAnnounceAchievement() ) + { + pPlayer->SetNextAchievementAnnounceTime( gpGlobals->curtime + ACHIEVEMENT_ANNOUNCEMENT_MIN_TIME ); + + // no particle effect if the local player is the one with the achievement or the player is dead + if ( !pPlayer->IsLocalPlayer() && pPlayer->IsAlive() ) + { + //tagES using the "head" attachment won't work for CS and DoD + pPlayer->ParticleProp()->Create( "achieved", PATTACH_POINT_FOLLOW, "head" ); + } + + pPlayer->OnAchievementAchieved( iAchievement ); + } + + if ( g_PR ) + { + wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( g_PR->GetPlayerName( iPlayerIndex ), wszPlayerName, sizeof( wszPlayerName ) ); + + const wchar_t *pchLocalizedAchievement = ACHIEVEMENT_LOCALIZED_NAME_FROM_STR( pAchievement->GetName() ); + if ( pchLocalizedAchievement ) + { + wchar_t wszLocalizedString[128]; + g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), g_pVGuiLocalize->Find( "#Achievement_Earned" ), 2, wszPlayerName, pchLocalizedAchievement ); + + char szLocalized[128]; + g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) ); + + hudChat->ChatPrintf( iPlayerIndex, CHAT_FILTER_SERVERMSG, "%s", szLocalized ); + } + } + } + } + } +#if defined( TF_CLIENT_DLL ) + else if ( Q_strcmp( "item_found", eventname ) == 0 ) + { + int iPlayerIndex = event->GetInt( "player" ); + entityquality_t iItemQuality = event->GetInt( "quality" ); + int iMethod = event->GetInt( "method" ); + int iItemDef = event->GetInt( "itemdef" ); + C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex ); + const GameItemDefinition_t *pItemDefinition = dynamic_cast( GetItemSchema()->GetItemDefinition( iItemDef ) ); + + if ( !pPlayer || !pItemDefinition ) + return; + + if ( g_PR ) + { + wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH]; + g_pVGuiLocalize->ConvertANSIToUnicode( g_PR->GetPlayerName( iPlayerIndex ), wszPlayerName, sizeof( wszPlayerName ) ); + + if ( iMethod < 0 || iMethod >= ARRAYSIZE( g_pszItemFoundMethodStrings ) ) + { + iMethod = 0; + } + + const char *pszLocString = g_pszItemFoundMethodStrings[iMethod]; + if ( pszLocString ) + { + wchar_t wszItemFound[256]; + _snwprintf( wszItemFound, ARRAYSIZE( wszItemFound ), L"%ls", g_pVGuiLocalize->Find( pszLocString ) ); + + wchar_t *colorMarker = wcsstr( wszItemFound, L"::" ); + if ( colorMarker ) + { + const char *pszQualityColorString = EconQuality_GetColorString( (EEconItemQuality)iItemQuality ); + if ( pszQualityColorString ) + { + hudChat->SetCustomColor( pszQualityColorString ); + *(colorMarker+1) = COLOR_CUSTOM; + } + } + + // TODO: Update the localization strings to only have two format parameters since that's all we need. + wchar_t wszLocalizedString[256]; + g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), wszItemFound, 3, wszPlayerName, CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pItemDefinition, iItemQuality ).GetFullName(), L"" ); + + char szLocalized[256]; + g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) ); + + hudChat->ChatPrintf( iPlayerIndex, CHAT_FILTER_SERVERMSG, "%s", szLocalized ); + } + } + } +#endif +#if defined( REPLAY_ENABLED ) + else if ( !V_strcmp( "replay_servererror", eventname ) ) + { + DisplayReplayMessage( event->GetString( "error", "#Replay_DefaultServerError" ), replay_msgduration_error.GetFloat(), true, NULL, false ); + } + else if ( !V_strcmp( "replay_startrecord", eventname ) ) + { + m_flReplayStartRecordTime = gpGlobals->curtime; + } + else if ( !V_strcmp( "replay_endrecord", eventname ) ) + { + m_flReplayStopRecordTime = gpGlobals->curtime; + } + else if ( !V_strcmp( "replay_replaysavailable", eventname ) ) + { + DisplayReplayMessage( "#Replay_ReplaysAvailable", replay_msgduration_replaysavailable.GetFloat(), false, NULL, false ); + } + + else if ( !V_strcmp( "game_newmap", eventname ) ) + { + // Make sure the instance count is reset to 0. Sometimes the count stay in sync and we get replay messages displaying lower than they should. + CReplayMessagePanel::RemoveAll(); + } +#endif + + else + { + DevMsg( 2, "Unhandled GameEvent in ClientModeShared::FireGameEvent - %s\n", event->GetName() ); + } +} + +void ClientModeShared::UpdateReplayMessages() +{ +#if defined( REPLAY_ENABLED ) + // Received a replay_startrecord event? + if ( m_flReplayStartRecordTime != 0.0f ) + { + DisplayReplayMessage( "#Replay_StartRecord", replay_msgduration_startrecord.GetFloat(), true, "replay\\startrecord.mp3", false ); + + m_flReplayStartRecordTime = 0.0f; + m_flReplayStopRecordTime = 0.0f; + } + + // Received a replay_endrecord event? + if ( m_flReplayStopRecordTime != 0.0f ) + { + DisplayReplayMessage( "#Replay_EndRecord", replay_msgduration_stoprecord.GetFloat(), true, "replay\\stoprecord.wav", false ); + + // Hide the replay reminder + if ( m_pReplayReminderPanel ) + { + m_pReplayReminderPanel->Hide(); + } + + m_flReplayStopRecordTime = 0.0f; + } + + if ( !engine->IsConnected() ) + { + ClearReplayMessageList(); + } +#endif +} + +void ClientModeShared::ClearReplayMessageList() +{ +#if defined( REPLAY_ENABLED ) + CReplayMessagePanel::RemoveAll(); +#endif +} + +void ClientModeShared::DisplayReplayMessage( const char *pLocalizeName, float flDuration, bool bUrgent, + const char *pSound, bool bDlg ) +{ +#if defined( REPLAY_ENABLED ) + // Don't display during replay playback, and don't allow more than 4 at a time + const bool bInReplay = g_pEngineClientReplay->IsPlayingReplayDemo(); + if ( bInReplay || ( !bDlg && CReplayMessagePanel::InstanceCount() >= 4 ) ) + return; + + // Use default duration? + if ( flDuration == -1.0f ) + { + flDuration = replay_msgduration_misc.GetFloat(); + } + + // Display a replay message + if ( bDlg ) + { + if ( engine->IsInGame() ) + { + Panel *pPanel = new CReplayMessageDlg( pLocalizeName ); + pPanel->SetVisible( true ); + pPanel->MakePopup(); + pPanel->MoveToFront(); + pPanel->SetKeyBoardInputEnabled( true ); + pPanel->SetMouseInputEnabled( true ); +#if defined( TF_CLIENT_DLL ) + TFModalStack()->PushModal( pPanel ); +#endif + } + else + { + ShowMessageBox( "#Replay_GenericMsgTitle", pLocalizeName, "#GameUI_OK" ); + } + } + else + { + CReplayMessagePanel *pMsgPanel = new CReplayMessagePanel( pLocalizeName, flDuration, bUrgent ); + pMsgPanel->Show(); + } + + // Play a sound if appropriate + if ( pSound ) + { + surface()->PlaySound( pSound ); + } +#endif +} + +void ClientModeShared::DisplayReplayReminder() +{ +#if defined( REPLAY_ENABLED ) + if ( m_pReplayReminderPanel && g_pReplay->IsRecording() ) + { + // Only display the panel if we haven't already requested a replay for the given life + CReplay *pCurLifeReplay = static_cast< CReplay * >( g_pClientReplayContext->GetReplayManager()->GetReplayForCurrentLife() ); + if ( pCurLifeReplay && !pCurLifeReplay->m_bRequestedByUser && !pCurLifeReplay->m_bSaved ) + { + m_pReplayReminderPanel->Show(); + } + } +#endif +} + + +//----------------------------------------------------------------------------- +// In-game VGUI context +//----------------------------------------------------------------------------- +void ClientModeShared::ActivateInGameVGuiContext( vgui::Panel *pPanel ) +{ + vgui::ivgui()->AssociatePanelWithContext( s_hVGuiContext, pPanel->GetVPanel() ); + vgui::ivgui()->ActivateContext( s_hVGuiContext ); +} + +void ClientModeShared::DeactivateInGameVGuiContext() +{ + vgui::ivgui()->ActivateContext( DEFAULT_VGUI_CONTEXT ); +} + -- cgit v1.2.3