diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/clientmode_shared.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/clientmode_shared.cpp')
| -rw-r--r-- | mp/src/game/client/clientmode_shared.cpp | 2788 |
1 files changed, 1394 insertions, 1394 deletions
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 <vgui/IVGui.h>
-#include <vgui/Cursor.h>
-#include <vgui/IPanel.h>
-#include <vgui/IInput.h>
-#include "engine/IEngineSound.h"
-#include <KeyValues.h>
-#include <vgui_controls/AnimationController.h>
-#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 <vgui/ILocalize.h>
-#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; i<count; i++)
- {
- char name[255];
- char data[255];
-
- msg.ReadString( name, sizeof(name) );
- msg.ReadString( data, sizeof(data) );
-
- keys->SetString( 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<CAchievementMgr *>( 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<GameItemDefinition_t *>( 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 <vgui/IVGui.h> +#include <vgui/Cursor.h> +#include <vgui/IPanel.h> +#include <vgui/IInput.h> +#include "engine/IEngineSound.h" +#include <KeyValues.h> +#include <vgui_controls/AnimationController.h> +#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 <vgui/ILocalize.h> +#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; i<count; i++) + { + char name[255]; + char data[255]; + + msg.ReadString( name, sizeof(name) ); + msg.ReadString( data, sizeof(data) ); + + keys->SetString( 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<CAchievementMgr *>( 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<GameItemDefinition_t *>( 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 ); +} + |