You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
557 lines
13 KiB
557 lines
13 KiB
3 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//
|
||
|
//===========================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "hud.h"
|
||
|
#include "clientmode_dod.h"
|
||
|
#include "cdll_client_int.h"
|
||
|
#include "iinput.h"
|
||
|
#include "vgui/ISurface.h"
|
||
|
#include "vgui/IPanel.h"
|
||
|
#include <vgui_controls/AnimationController.h>
|
||
|
#include "ivmodemanager.h"
|
||
|
#include "buymenu.h"
|
||
|
#include "filesystem.h"
|
||
|
#include "vgui/IVGui.h"
|
||
|
#include "hud_basechat.h"
|
||
|
#include "view_shared.h"
|
||
|
#include "view.h"
|
||
|
#include "ivrenderview.h"
|
||
|
#include "model_types.h"
|
||
|
#include "iefx.h"
|
||
|
#include "dlight.h"
|
||
|
#include <imapoverview.h>
|
||
|
#include "c_playerresource.h"
|
||
|
#include <KeyValues.h>
|
||
|
#include "text_message.h"
|
||
|
#include "panelmetaclassmgr.h"
|
||
|
#include "dod_shareddefs.h"
|
||
|
#include "c_dod_player.h"
|
||
|
#include "physpropclientside.h"
|
||
|
#include "engine/IEngineSound.h"
|
||
|
#include "bitbuf.h"
|
||
|
#include "usermessages.h"
|
||
|
#include "prediction.h"
|
||
|
#include "vgui/ILocalize.h"
|
||
|
#include "dod_hud_freezepanel.h"
|
||
|
#include "dod_hud_chat.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
class CHudChat;
|
||
|
|
||
|
ConVar default_fov( "default_fov", "90", FCVAR_CHEAT );
|
||
|
|
||
|
ConVar dod_playwinmusic( "dod_playwinmusic", "1", FCVAR_ARCHIVE );
|
||
|
|
||
|
IClientMode *g_pClientMode = NULL;
|
||
|
|
||
|
void MsgFunc_KillCam(bf_read &msg)
|
||
|
{
|
||
|
C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
int newMode = msg.ReadByte();
|
||
|
|
||
|
if ( newMode != g_nKillCamMode )
|
||
|
{
|
||
|
#if !defined( NO_ENTITY_PREDICTION )
|
||
|
if ( g_nKillCamMode == OBS_MODE_NONE )
|
||
|
{
|
||
|
// kill cam is switch on, turn off prediction
|
||
|
g_bForceCLPredictOff = true;
|
||
|
}
|
||
|
else if ( newMode == OBS_MODE_NONE )
|
||
|
{
|
||
|
// kill cam is switched off, restore old prediction setting is we switch back to normal mode
|
||
|
g_bForceCLPredictOff = false;
|
||
|
}
|
||
|
#endif
|
||
|
g_nKillCamMode = newMode;
|
||
|
}
|
||
|
|
||
|
g_nKillCamTarget1 = msg.ReadByte();
|
||
|
g_nKillCamTarget2 = msg.ReadByte();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
// CDODModeManager.
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
|
||
|
class CDODModeManager : public IVModeManager
|
||
|
{
|
||
|
public:
|
||
|
virtual void Init();
|
||
|
virtual void SwitchMode( bool commander, bool force ) {}
|
||
|
virtual void LevelInit( const char *newmap );
|
||
|
virtual void LevelShutdown( void );
|
||
|
virtual void ActivateMouse( bool isactive ) {}
|
||
|
};
|
||
|
|
||
|
static CDODModeManager g_ModeManager;
|
||
|
IVModeManager *modemanager = ( IVModeManager * )&g_ModeManager;
|
||
|
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
// CDODModeManager implementation.
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
|
||
|
#define SCREEN_FILE "scripts/vgui_screens.txt"
|
||
|
|
||
|
void CDODModeManager::Init()
|
||
|
{
|
||
|
g_pClientMode = GetClientModeNormal();
|
||
|
|
||
|
PanelMetaClassMgr()->LoadMetaClassDefinitionFile( SCREEN_FILE );
|
||
|
}
|
||
|
|
||
|
void CDODModeManager::LevelInit( const char *newmap )
|
||
|
{
|
||
|
g_pClientMode->LevelInit( newmap );
|
||
|
|
||
|
#if !defined( NO_ENTITY_PREDICTION )
|
||
|
if ( g_nKillCamMode > OBS_MODE_NONE )
|
||
|
{
|
||
|
g_bForceCLPredictOff = false;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
g_nKillCamMode = OBS_MODE_NONE;
|
||
|
g_nKillCamTarget1 = 0;
|
||
|
g_nKillCamTarget2 = 0;
|
||
|
}
|
||
|
|
||
|
void CDODModeManager::LevelShutdown( void )
|
||
|
{
|
||
|
g_pClientMode->LevelShutdown();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
ClientModeDODNormal::ClientModeDODNormal()
|
||
|
{
|
||
|
m_pFreezePanel = NULL;
|
||
|
}
|
||
|
|
||
|
void ClientModeDODNormal::Init()
|
||
|
{
|
||
|
BaseClass::Init();
|
||
|
|
||
|
ListenForGameEvent( "dod_round_start" );
|
||
|
ListenForGameEvent( "dod_broadcast_audio" );
|
||
|
ListenForGameEvent( "player_team" );
|
||
|
ListenForGameEvent( "dod_bomb_planted" );
|
||
|
ListenForGameEvent( "dod_bomb_defused" );
|
||
|
ListenForGameEvent( "dod_timer_flash" );
|
||
|
|
||
|
usermessages->HookMessage( "KillCam", MsgFunc_KillCam );
|
||
|
|
||
|
m_szLastRadioSound[0] = '\0';
|
||
|
|
||
|
m_pFreezePanel = ( CDODFreezePanel * )GET_HUDELEMENT( CDODFreezePanel );
|
||
|
Assert( m_pFreezePanel );
|
||
|
}
|
||
|
void ClientModeDODNormal::InitViewport()
|
||
|
{
|
||
|
m_pViewport = new DODViewport();
|
||
|
m_pViewport->Start( gameuifuncs, gameeventmanager );
|
||
|
}
|
||
|
|
||
|
ClientModeDODNormal g_ClientModeNormal;
|
||
|
|
||
|
IClientMode *GetClientModeNormal()
|
||
|
{
|
||
|
return &g_ClientModeNormal;
|
||
|
}
|
||
|
|
||
|
|
||
|
ClientModeDODNormal* GetClientModeDODNormal()
|
||
|
{
|
||
|
Assert( dynamic_cast< ClientModeDODNormal* >( GetClientModeNormal() ) );
|
||
|
|
||
|
return static_cast< ClientModeDODNormal* >( GetClientModeNormal() );
|
||
|
}
|
||
|
|
||
|
ConVar r_viewmodelfov( "r_viewmodelfov", "0", FCVAR_CHEAT );
|
||
|
|
||
|
float ClientModeDODNormal::GetViewModelFOV( void )
|
||
|
{
|
||
|
float flFov = 90.0f;
|
||
|
|
||
|
if( r_viewmodelfov.GetFloat() > 0 )
|
||
|
return r_viewmodelfov.GetFloat();
|
||
|
|
||
|
C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
|
||
|
if( !pPlayer )
|
||
|
return flFov;
|
||
|
|
||
|
CWeaponDODBase *pWpn = pPlayer->GetActiveDODWeapon();
|
||
|
|
||
|
if( pWpn )
|
||
|
{
|
||
|
flFov = pWpn->GetDODWpnData().m_flViewModelFOV;
|
||
|
}
|
||
|
|
||
|
return flFov;
|
||
|
}
|
||
|
|
||
|
int ClientModeDODNormal::GetDeathMessageStartHeight( void )
|
||
|
{
|
||
|
return m_pViewport->GetDeathMessageStartHeight();
|
||
|
}
|
||
|
|
||
|
void ClientModeDODNormal::FireGameEvent( IGameEvent * event)
|
||
|
{
|
||
|
const char *eventname = event->GetName();
|
||
|
|
||
|
if ( !eventname || !eventname[0] )
|
||
|
return;
|
||
|
|
||
|
if ( Q_strcmp( "dod_round_start", eventname ) == 0 )
|
||
|
{
|
||
|
// Just tell engine to clear decals
|
||
|
engine->ClientCmd( "r_cleardecals\n" );
|
||
|
|
||
|
// recreate all client side physics props
|
||
|
// check for physenv, because we sometimes crash on changelevel
|
||
|
// if we get this message before fully connecting
|
||
|
if ( physenv )
|
||
|
{
|
||
|
C_PhysPropClientside::RecreateAll();
|
||
|
}
|
||
|
}
|
||
|
else if( Q_strcmp( "dod_broadcast_audio", eventname ) == 0 )
|
||
|
{
|
||
|
CLocalPlayerFilter filter;
|
||
|
const char *pszSoundName = event->GetString("sound");
|
||
|
|
||
|
if ( dod_playwinmusic.GetBool() == false )
|
||
|
{
|
||
|
if ( FStrEq( pszSoundName, "Game.USWin" ) || FStrEq( pszSoundName, "Game.GermanWin" ) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, pszSoundName );
|
||
|
}
|
||
|
else if ( Q_strcmp( "dod_bomb_planted", eventname ) == 0 )
|
||
|
{
|
||
|
int defendingTeam = event->GetInt( "team" );
|
||
|
|
||
|
C_DODPlayer *pLocalPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
|
||
|
if ( !pLocalPlayer )
|
||
|
return;
|
||
|
|
||
|
const char *pszSound = "";
|
||
|
const char *pszMessage = "";
|
||
|
|
||
|
int localTeam = pLocalPlayer->GetTeamNumber();
|
||
|
|
||
|
const char *pPlanterName = NULL;
|
||
|
|
||
|
int iPlanterIndex = 0;
|
||
|
|
||
|
if ( defendingTeam == localTeam )
|
||
|
{
|
||
|
// play defend sound
|
||
|
switch( localTeam )
|
||
|
{
|
||
|
case TEAM_ALLIES:
|
||
|
{
|
||
|
pszSound = "Voice.US_C4EnemyPlanted";
|
||
|
pszMessage = "#dod_bomb_us_enemy_planted";
|
||
|
}
|
||
|
break;
|
||
|
case TEAM_AXIS:
|
||
|
{
|
||
|
pszSound = "Voice.German_C4EnemyPlanted";
|
||
|
pszMessage = "#dod_bomb_ger_enemy_planted";
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// play planting sound
|
||
|
switch( localTeam )
|
||
|
{
|
||
|
case TEAM_ALLIES:
|
||
|
{
|
||
|
pszSound = "Voice.US_C4TeamPlanted";
|
||
|
pszMessage = "#dod_bomb_us_team_planted";
|
||
|
}
|
||
|
break;
|
||
|
case TEAM_AXIS:
|
||
|
{
|
||
|
pszSound = "Voice.German_C4TeamPlanted";
|
||
|
pszMessage = "#dod_bomb_ger_team_planted";
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Only show the planter name if its a team plant, not enemy plant
|
||
|
iPlanterIndex = engine->GetPlayerForUserID( event->GetInt("userid") );
|
||
|
pPlanterName = g_PR->GetPlayerName( iPlanterIndex );
|
||
|
}
|
||
|
|
||
|
RadioMessage( pszSound, pszMessage, pPlanterName, iPlanterIndex );
|
||
|
}
|
||
|
else if ( Q_strcmp( "dod_bomb_defused", eventname ) == 0 )
|
||
|
{
|
||
|
int defusingTeam = event->GetInt( "team" );
|
||
|
|
||
|
C_DODPlayer *pLocalPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
|
||
|
if ( !pLocalPlayer )
|
||
|
return;
|
||
|
|
||
|
const char *pszSound = "";
|
||
|
const char *pszMessage = "";
|
||
|
|
||
|
int localTeam = pLocalPlayer->GetTeamNumber();
|
||
|
|
||
|
if ( defusingTeam == localTeam )
|
||
|
{
|
||
|
// play defused sound
|
||
|
switch( localTeam )
|
||
|
{
|
||
|
case TEAM_ALLIES:
|
||
|
{
|
||
|
pszSound = "Voice.US_C4Defused";
|
||
|
pszMessage = "#dod_bomb_us_defused";
|
||
|
}
|
||
|
break;
|
||
|
case TEAM_AXIS:
|
||
|
{
|
||
|
pszSound = "Voice.German_C4Defused";
|
||
|
pszMessage = "#dod_bomb_ger_defused";
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
int iDefuser = engine->GetPlayerForUserID( event->GetInt("userid") );
|
||
|
const char *pDefuserName = g_PR->GetPlayerName( iDefuser );
|
||
|
|
||
|
RadioMessage( pszSound, pszMessage, pDefuserName, iDefuser );
|
||
|
}
|
||
|
}
|
||
|
else if ( Q_strcmp( "player_team", eventname ) == 0 )
|
||
|
{
|
||
|
C_BasePlayer *pPlayer = USERID2PLAYER( event->GetInt("userid") );
|
||
|
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
bool bDisconnected = event->GetBool("disconnect");
|
||
|
|
||
|
if ( bDisconnected )
|
||
|
return;
|
||
|
|
||
|
int team = event->GetInt( "team" );
|
||
|
|
||
|
if ( pPlayer->IsLocalPlayer() )
|
||
|
{
|
||
|
// that's me
|
||
|
pPlayer->TeamChange( team );
|
||
|
}
|
||
|
|
||
|
CBaseHudChat *hudChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat );
|
||
|
|
||
|
if ( !hudChat )
|
||
|
return;
|
||
|
|
||
|
const char *pTemplate = NULL;
|
||
|
|
||
|
if ( team == TEAM_ALLIES )
|
||
|
{
|
||
|
pTemplate = "#game_joined_allies";
|
||
|
}
|
||
|
else if ( team == TEAM_AXIS )
|
||
|
{
|
||
|
pTemplate = "#game_joined_axis";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTemplate = "#game_joined_spectators";
|
||
|
}
|
||
|
|
||
|
wchar_t szPlayerName[MAX_PLAYER_NAME_LENGTH];
|
||
|
g_pVGuiLocalize->ConvertANSIToUnicode( pPlayer->GetPlayerName(), szPlayerName, sizeof(szPlayerName) );
|
||
|
|
||
|
wchar_t wszPrint[128];
|
||
|
char szPrint[128];
|
||
|
|
||
|
g_pVGuiLocalize->ConstructString( wszPrint, sizeof(wszPrint), g_pVGuiLocalize->Find(pTemplate), 1, szPlayerName );
|
||
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wszPrint, szPrint, sizeof(szPrint) );
|
||
|
|
||
|
hudChat->Printf( CHAT_FILTER_TEAMCHANGE, "%s",szPrint );
|
||
|
}
|
||
|
else if ( Q_strcmp( "dod_timer_flash", eventname ) == 0 )
|
||
|
{
|
||
|
C_DODPlayer *pLocalPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
|
||
|
if ( !pLocalPlayer )
|
||
|
return;
|
||
|
|
||
|
const char *pszSound = "";
|
||
|
const char *pszMessage = "";
|
||
|
|
||
|
int localTeam = pLocalPlayer->GetTeamNumber();
|
||
|
|
||
|
int iTimeRemaining = event->GetInt( "time_remaining", 0 );
|
||
|
|
||
|
switch( iTimeRemaining )
|
||
|
{
|
||
|
case 60:
|
||
|
switch( localTeam )
|
||
|
{
|
||
|
case TEAM_ALLIES:
|
||
|
{
|
||
|
pszSound = "Voice.US_OneMinute";
|
||
|
pszMessage = "#dod_time_remaining_us_1_min";
|
||
|
}
|
||
|
break;
|
||
|
case TEAM_AXIS:
|
||
|
{
|
||
|
pszSound = "Voice.German_OneMinute";
|
||
|
pszMessage = "#dod_time_remaining_ger_1_min";
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case 120:
|
||
|
switch( localTeam )
|
||
|
{
|
||
|
case TEAM_ALLIES:
|
||
|
{
|
||
|
pszSound = "Voice.US_TwoMinute";
|
||
|
pszMessage = "#dod_time_remaining_us_2_min";
|
||
|
}
|
||
|
break;
|
||
|
case TEAM_AXIS:
|
||
|
{
|
||
|
pszSound = "Voice.German_TwoMinute";
|
||
|
pszMessage = "#dod_time_remaining_ger_2_min";
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
RadioMessage( pszSound, pszMessage );
|
||
|
}
|
||
|
else
|
||
|
BaseClass::FireGameEvent( event );
|
||
|
}
|
||
|
|
||
|
|
||
|
void ClientModeDODNormal::PostRenderVGui()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool ClientModeDODNormal::ShouldDrawViewModel()
|
||
|
{
|
||
|
C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
|
||
|
CWeaponDODBase *pWpn = pPlayer->GetActiveDODWeapon();
|
||
|
|
||
|
if( pWpn && pWpn->ShouldDrawViewModel() == false )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return BaseClass::ShouldDrawViewModel();
|
||
|
}
|
||
|
|
||
|
void ClientModeDODNormal::RadioMessage( const char *pszSoundName, const char *pszSubtitle, const char *pszSender /* = NULL */, int iSenderIndex /* = 0 */ )
|
||
|
{
|
||
|
C_DODPlayer *pLocalPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
if ( !pLocalPlayer )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int color = COLOR_PLAYERNAME;
|
||
|
|
||
|
// stop the last played radio message
|
||
|
if ( Q_strlen( m_szLastRadioSound ) > 0 )
|
||
|
{
|
||
|
C_DODPlayer *pLocalPlayer = C_DODPlayer::GetLocalDODPlayer();
|
||
|
if ( pLocalPlayer )
|
||
|
{
|
||
|
pLocalPlayer->StopSound( m_szLastRadioSound );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Q_strncpy( m_szLastRadioSound, pszSoundName, sizeof(m_szLastRadioSound) );
|
||
|
|
||
|
// Play the radio alert
|
||
|
char szCmd[128];
|
||
|
Q_snprintf( szCmd, sizeof(szCmd), "playgamesound %s", pszSoundName );
|
||
|
|
||
|
engine->ClientCmd( szCmd );
|
||
|
|
||
|
// Print a message to chat
|
||
|
wchar_t wszPrint[128];
|
||
|
char szPrint[128];
|
||
|
|
||
|
g_pVGuiLocalize->ConstructString( wszPrint, sizeof(wszPrint), g_pVGuiLocalize->Find(pszSubtitle), 0 );
|
||
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wszPrint, szPrint, sizeof(szPrint) );
|
||
|
|
||
|
CBaseHudChat *hudChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat );
|
||
|
|
||
|
if ( !hudChat )
|
||
|
return;
|
||
|
|
||
|
wchar_t *pwLoc = g_pVGuiLocalize->Find( "#dod_radio_prefix" );
|
||
|
char szPrefix[16];
|
||
|
g_pVGuiLocalize->ConvertUnicodeToANSI( pwLoc, szPrefix, sizeof(szPrefix) );
|
||
|
|
||
|
pwLoc = g_pVGuiLocalize->Find( pszSubtitle );
|
||
|
char szSuffix[512];
|
||
|
g_pVGuiLocalize->ConvertUnicodeToANSI( pwLoc, szSuffix, sizeof(szSuffix) );
|
||
|
|
||
|
if ( pszSender )
|
||
|
{
|
||
|
hudChat->ChatPrintf( iSenderIndex, CHAT_FILTER_NONE, "%c%s %s %c: %s", COLOR_PLAYERNAME, szPrefix, g_PR->GetPlayerName( iSenderIndex ), COLOR_NORMAL, szSuffix );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hudChat->Printf( CHAT_FILTER_NONE, "%c%s %c: %s", color, szPrefix, COLOR_NORMAL, szSuffix );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: See if hud elements want key input. Return 0 if the key is swallowed
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int ClientModeDODNormal::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
|
||
|
{
|
||
|
if ( m_pFreezePanel )
|
||
|
{
|
||
|
m_pFreezePanel->HudElementKeyInput( down, keynum, pszCurrentBinding );
|
||
|
}
|
||
|
|
||
|
return BaseClass::HudElementKeyInput( down, keynum, pszCurrentBinding );
|
||
|
}
|