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.
2301 lines
68 KiB
2301 lines
68 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// The copyright to the contents herein is the property of Valve, L.L.C. |
|
// The contents may be used and/or copied only with the written permission of |
|
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in |
|
// the agreement/contract under which the contents have been supplied. |
|
// |
|
// $Header: $ |
|
// $NoKeywords: $ |
|
// |
|
//============================================================================= |
|
#include "cbase.h" |
|
#include "hud.h" |
|
#include "clientmode_tf.h" |
|
#include "cdll_client_int.h" |
|
#include "iinput.h" |
|
#include "iviewrender.h" |
|
#include "vgui/ISurface.h" |
|
#include "vgui/IPanel.h" |
|
#include "GameUI/IGameUI.h" |
|
#include <vgui_controls/AnimationController.h> |
|
#include "ivmodemanager.h" |
|
#include "buymenu.h" |
|
#include "filesystem.h" |
|
#include "vgui/IVGui.h" |
|
#include "hud_chat.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 "c_tf_player.h" |
|
#include "ienginevgui.h" |
|
#include "in_buttons.h" |
|
#include "voice_status.h" |
|
#include "tf_gamerules.h" |
|
#include "tf_hud_menu_engy_build.h" |
|
#include "tf_hud_menu_engy_destroy.h" |
|
#include "tf_hud_menu_spy_disguise.h" |
|
#include "tf_statsummary.h" |
|
#include "tf_hud_freezepanel.h" |
|
#include "item_quickswitch.h" |
|
#include "hud_macros.h" |
|
#include "vgui/ILocalize.h" |
|
#include "glow_outline_effect.h" |
|
#include "vgui/IInput.h" |
|
#include "tf_hud_mainmenuoverride.h" |
|
#include "tf_controls.h" |
|
#include "econ_notifications.h" |
|
#include "rtime.h" |
|
#include "econ_item_description.h" |
|
#include "c_tf_playerresource.h" |
|
#include "c_team.h" |
|
#include "tf_hud_menu_eureka_teleport.h" |
|
#include "tf_hud_menu_taunt_selection.h" |
|
#include "tf_hud_inspectpanel.h" |
|
#include "engine/IEngineSound.h" |
|
#ifdef STAGING_ONLY |
|
#include "tf_hud_menu_spy_build.h" |
|
#endif // STAGING_ONLY |
|
|
|
#include "quest_objective_manager.h" |
|
#include "econ_item_system.h" |
|
#include "tf_mann_vs_machine_stats.h" |
|
#include "tf_hud_mann_vs_machine_status.h" |
|
#include "player_vs_environment/c_tf_upgrades.h" |
|
|
|
#include "steam/isteamfriends.h" |
|
#include "steamworks_gamestats.h" |
|
#include "confirm_dialog.h" |
|
#include "ServerBrowser/blacklisted_server_manager.h" |
|
#include "tf_quickplay_shared.h" |
|
#include "sourcevr/isourcevirtualreality.h" |
|
#include "client_virtualreality.h" |
|
|
|
#include "econ_gcmessages.h" |
|
|
|
#if defined( _X360 ) |
|
#include "tf_clientscoreboard.h" |
|
#endif |
|
|
|
#include "gc_clientsystem.h" |
|
#include "tf_gcmessages.h" |
|
#include "tf_gc_client.h" |
|
|
|
#include "tf_wardata.h" |
|
|
|
#include "debugoverlay_shared.h" |
|
|
|
#include "hud_vote.h" |
|
#include "c_tf_notification.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
void __MsgFunc_AutoBalanceVolunteer( bf_read &msg ); |
|
void __MsgFunc_AutoBalanceVolunteer_Cancel( bf_read &msg ); |
|
void __MsgFunc_PlayerIgnitedInv( bf_read &msg ); |
|
void __MsgFunc_PlayerIgnited( bf_read &msg ); |
|
void __MsgFunc_Damage( bf_read &msg ); |
|
void __MsgFunc_HudArenaNotify( bf_read &msg ); |
|
void __MsgFunc_UpdateAchievement( bf_read &msg ); |
|
void __MsgFunc_DamageDodged( bf_read &msg ); |
|
void __MsgFunc_PlayerJarated( bf_read &msg ); |
|
void __MsgFunc_PlayerExtinguished( bf_read &msg ); |
|
void __MsgFunc_BreakModel( bf_read &msg ); |
|
void __MsgFunc_BreakModel_Pumpkin( bf_read &msg ); |
|
void __MsgFunc_BreakModelRocketDud( bf_read &msg ); |
|
void __MsgFunc_CheapBreakModel( bf_read &msg ); |
|
void __MsgFunc_PlayerJaratedFade( bf_read &msg ); |
|
void __MsgFunc_PlayerShieldBlocked( bf_read &msg ); |
|
void __MsgFunc_PlayerBonusPoints( bf_read &msg ); |
|
void __MsgFunc_SpawnFlyingBird( bf_read &msg ); |
|
void __MsgFunc_PlayerGodRayEffect( bf_read &msg ); |
|
void __MsgFunc_PlayerTeleportHomeEffect( bf_read &msg ); |
|
void __MsgFunc_RDTeamPointsChanged( bf_read &msg ); |
|
void __MsgFunc_PlayerLoadoutUpdated( bf_read &msg ); |
|
void __MsgFunc_PlayerTauntSoundLoopStart( bf_read &msg ); |
|
void __MsgFunc_PlayerTauntSoundLoopEnd( bf_read &msg ); |
|
void __MsgFunc_ForcePlayerViewAngles( bf_read &msg ); |
|
void __MsgFunc_BonusDucks( bf_read &msg ); |
|
void __MsgFunc_PlayerPickupWeapon( bf_read &msg ); |
|
void __MsgFunc_QuestObjectiveCompleted( bf_read &msg ); |
|
|
|
#if !defined(NO_STEAM) |
|
extern ConVar cl_steamscreenshots; |
|
#endif |
|
|
|
extern ISoundEmitterSystemBase *soundemitterbase; |
|
|
|
static Color colorEyeballBossText( 134, 80, 172, 255 ); |
|
static Color colorMerasmusText( 112, 176, 74, 255 ); |
|
|
|
ConVar default_fov( "default_fov", "75", FCVAR_CHEAT ); |
|
ConVar fov_desired( "fov_desired", "75", FCVAR_ARCHIVE | FCVAR_USERINFO, "Sets the base field-of-view.", true, 20.0, true, MAX_FOV ); |
|
|
|
#define TF_HIGHFIVE_HINT_MAXDIST 512.0f |
|
#define TF_HIGHFIVE_HINT_MAXHINTS 3 |
|
#define TF_HIGHFIVE_HINT_MINTIMEBETWEEN 10.0f |
|
ConVar tf_highfive_hintcount( "tf_highfive_hintcount", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD | FCVAR_ARCHIVE, "Counts the number of times the high five hint has been displayed", true, 0, false, 0 ); |
|
|
|
ConVar tf_taunt_always_show_hint( "tf_taunt_always_show_hint", "1", FCVAR_CLIENTDLL ); |
|
extern ConVar tf_allow_all_team_partner_taunt; |
|
extern ConVar tf_mvm_buybacks_method; |
|
extern ConVar tf_autobalance_query_lifetime; |
|
extern ConVar tf_autobalance_xp_bonus; |
|
extern ConVar cl_notifications_show_ingame; |
|
|
|
extern ConVar sc_look_sensitivity_scale; |
|
|
|
extern bool TournamentHudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); |
|
extern bool ArenaClassLayoutKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); |
|
extern bool CoachingHandlesKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); |
|
extern bool ItemTestHandlesKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); |
|
extern bool ShouldScoreBoardHandleKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ); |
|
|
|
static bool TrainingHandlesKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) |
|
{ |
|
if ( TFGameRules() != NULL && TFGameRules()->IsInTraining() && TFGameRules()->IsWaitingForTrainingContinue() ) |
|
{ |
|
if ( down && keynum == KEY_SPACE ) |
|
{ |
|
engine->ClientCmd_Unrestricted( "training_continue" ); |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
|
|
static bool HalloweenHandlesKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) |
|
{ |
|
C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() ); |
|
if ( pPlayer ) |
|
{ |
|
// don't do anything while dancing |
|
if ( pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_THRILLER ) ) |
|
{ |
|
return true; |
|
} |
|
|
|
// only allow +attack |
|
if ( pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE ) ) |
|
{ |
|
if ( pszCurrentBinding ) |
|
{ |
|
if ( FStrEq( pszCurrentBinding, "+attack" ) ) |
|
{ |
|
engine->ServerCmd( "boo" ); |
|
return true; |
|
} |
|
else if ( FStrEq( pszCurrentBinding, "+attack2" ) || FStrEq( pszCurrentBinding, "+attack3" ) ) |
|
{ |
|
return true; |
|
} |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
static bool TauntHandlesKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) |
|
{ |
|
static const char *pszStopTauntKeys[] = |
|
{ |
|
"+jump", |
|
"+taunt", |
|
"weapon_taunt", |
|
}; |
|
|
|
C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() ); |
|
if ( pPlayer ) |
|
{ |
|
if ( pPlayer->m_Shared.InCond( TF_COND_TAUNTING ) ) |
|
{ |
|
for ( int i=0; i<ARRAYSIZE( pszStopTauntKeys ); ++i ) |
|
{ |
|
if ( down && pszCurrentBinding && FStrEq( pszCurrentBinding, pszStopTauntKeys[i] ) ) |
|
{ |
|
// Halloween Hackery |
|
if ( i == 0 && pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_KART ) ) |
|
{ |
|
continue; |
|
} |
|
|
|
engine->ClientCmd( "stop_taunt" ); |
|
return true; |
|
} |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
// Sets convars to tag the current mapname and the player in your crosshairs. |
|
// The player tagged will be overridden for killcam shots to be the killer |
|
static void ScreenshotTaggingKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) |
|
{ |
|
if ( pszCurrentBinding && ( FStrEq( pszCurrentBinding, "screenshot" ) || FStrEq( pszCurrentBinding, "jpeg" ) ) ) |
|
{ |
|
// Tag the player in the crosshairs |
|
C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() ); |
|
if ( pPlayer ) |
|
{ |
|
C_TFPlayer *pCrosshairs = ToTFPlayer( UTIL_PlayerByIndex( pPlayer->GetIDTarget() ) ); |
|
if ( pCrosshairs ) |
|
{ |
|
CSteamID steamID; |
|
if ( pCrosshairs->GetSteamID( &steamID ) ) |
|
{ |
|
ConVarRef cl_screenshotusertag( "cl_screenshotusertag" ); |
|
if ( cl_screenshotusertag.IsValid() ) |
|
{ |
|
cl_screenshotusertag.SetValue( (int)steamID.GetAccountID() ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Tag the current map |
|
ConVarRef cl_screenshotlocation( "cl_screenshotlocation" ); |
|
if ( cl_screenshotlocation.IsValid() ) |
|
{ |
|
char szMapName[MAX_MAP_NAME]; |
|
Q_FileBase( engine->GetLevelName(), szMapName, sizeof(szMapName) ); |
|
Q_strlower( szMapName ); |
|
cl_screenshotlocation.SetValue( GetMapDisplayName( szMapName ) ); |
|
} |
|
} |
|
} |
|
|
|
|
|
static void EnableSteamScreenshots( bool bEnable ) |
|
{ |
|
#if !defined(NO_STEAM) |
|
if ( steamapicontext && steamapicontext->SteamScreenshots() ) |
|
{ |
|
ConVarRef cl_savescreenshotstosteam( "cl_savescreenshotstosteam" ); |
|
if ( cl_savescreenshotstosteam.IsValid() ) |
|
{ |
|
cl_savescreenshotstosteam.SetValue( bEnable ); |
|
steamapicontext->SteamScreenshots()->HookScreenshots( bEnable ); |
|
} |
|
} |
|
#endif |
|
} |
|
|
|
#if !defined(NO_STEAM) |
|
void SteamScreenshotsCallBack( IConVar *var, const char *pOldString, float flOldValue ) |
|
{ |
|
EnableSteamScreenshots( cl_steamscreenshots.GetBool() ); |
|
} |
|
ConVar cl_steamscreenshots( "cl_steamscreenshots", "1", FCVAR_ARCHIVE, "Enable/disable saving screenshots to Steam", SteamScreenshotsCallBack ); |
|
#endif |
|
|
|
|
|
void HUDMinModeChangedCallBack( IConVar *var, const char *pOldString, float flOldValue ) |
|
{ |
|
engine->ExecuteClientCmd( "hud_reloadscheme" ); |
|
} |
|
ConVar cl_hud_minmode( "cl_hud_minmode", "0", FCVAR_ARCHIVE, "Set to 1 to turn on the advanced minimalist HUD mode.", HUDMinModeChangedCallBack ); |
|
|
|
IClientMode *g_pClientMode = NULL; |
|
|
|
// --------------------------------------------------------------------------------- // |
|
// CTFModeManager. |
|
// --------------------------------------------------------------------------------- // |
|
|
|
class CTFModeManager : 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 CTFModeManager g_ModeManager; |
|
IVModeManager *modemanager = ( IVModeManager * )&g_ModeManager; |
|
|
|
|
|
// --------------------------------------------------------------------------------- // |
|
// CTFModeManager implementation. |
|
// --------------------------------------------------------------------------------- // |
|
|
|
#define SCREEN_FILE "scripts/vgui_screens.txt" |
|
|
|
void CTFModeManager::Init() |
|
{ |
|
g_pClientMode = GetClientModeNormal(); |
|
|
|
PanelMetaClassMgr()->LoadMetaClassDefinitionFile( SCREEN_FILE ); |
|
|
|
// Load the objects.txt file. |
|
LoadObjectInfos( ::filesystem ); |
|
|
|
GetClientVoiceMgr()->SetHeadLabelOffset( 40 ); |
|
|
|
EnableSteamScreenshots( true ); |
|
} |
|
|
|
void CTFModeManager::LevelInit( const char *newmap ) |
|
{ |
|
g_pClientMode->LevelInit( newmap ); |
|
|
|
ConVarRef voice_steal( "voice_steal" ); |
|
|
|
if ( voice_steal.IsValid() ) |
|
{ |
|
voice_steal.SetValue( 1 ); |
|
} |
|
} |
|
|
|
void CTFModeManager::LevelShutdown( void ) |
|
{ |
|
g_pClientMode->LevelShutdown(); |
|
|
|
extern void CL_Training_LevelShutdown(); |
|
extern void CL_Coaching_LevelShutdown(); |
|
extern void CL_Consumables_LevelShutdown(); |
|
extern void CL_Halloween_LevelShutdown(); |
|
CL_Training_LevelShutdown(); |
|
CL_Coaching_LevelShutdown(); |
|
CL_Consumables_LevelShutdown(); |
|
CL_Halloween_LevelShutdown(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
ClientModeTFNormal::ClientModeTFNormal() |
|
{ |
|
m_pMenuEngyBuild = NULL; |
|
m_pMenuEngyDestroy = NULL; |
|
m_pMenuSpyDisguise = NULL; |
|
m_pEurekaTeleportMenu = NULL; |
|
m_pMenuTauntSelection = NULL; |
|
#ifdef STAGING_ONLY |
|
m_pMenuSpyBuild = NULL; |
|
#endif // STAGING_ONLY |
|
m_pGameUI = NULL; |
|
m_pFreezePanel = NULL; |
|
m_pQuickSwitch = NULL; |
|
m_pInspectPanel = NULL; |
|
m_wasConnectedLastUpdate = false; |
|
m_lastServerIP = 0; |
|
m_lastServerPort = 0; |
|
m_lastServerName = NULL; |
|
m_lastServerConnectTime = 0; |
|
m_pTeamGoalTournament = NULL; |
|
|
|
#if defined( _X360 ) |
|
m_pScoreboard = NULL; |
|
#endif |
|
|
|
HOOK_MESSAGE( AutoBalanceVolunteer ); |
|
HOOK_MESSAGE( AutoBalanceVolunteer_Cancel ); |
|
|
|
// Hook global message handlers |
|
HOOK_MESSAGE( PlayerIgnited ); |
|
HOOK_MESSAGE( PlayerIgnitedInv ); |
|
HOOK_MESSAGE( Damage ); |
|
HOOK_MESSAGE( HudArenaNotify ); |
|
HOOK_MESSAGE( UpdateAchievement ); |
|
HOOK_MESSAGE( DamageDodged ); |
|
HOOK_MESSAGE( PlayerJarated ); |
|
HOOK_MESSAGE( PlayerExtinguished ); |
|
HOOK_MESSAGE( BreakModel ); |
|
HOOK_MESSAGE( CheapBreakModel ); |
|
HOOK_MESSAGE( BreakModel_Pumpkin ); |
|
HOOK_MESSAGE( BreakModelRocketDud ); |
|
HOOK_MESSAGE( PlayerJaratedFade ); |
|
HOOK_MESSAGE( PlayerShieldBlocked ); |
|
HOOK_MESSAGE( PlayerBonusPoints ); |
|
HOOK_MESSAGE( SpawnFlyingBird ); |
|
HOOK_MESSAGE( PlayerGodRayEffect ); |
|
HOOK_MESSAGE( PlayerTeleportHomeEffect ); |
|
HOOK_MESSAGE( RDTeamPointsChanged ); |
|
HOOK_MESSAGE( PlayerLoadoutUpdated ); |
|
HOOK_MESSAGE( PlayerTauntSoundLoopStart ); |
|
HOOK_MESSAGE( PlayerTauntSoundLoopEnd ); |
|
HOOK_MESSAGE( ForcePlayerViewAngles ); |
|
HOOK_MESSAGE( BonusDucks ); |
|
HOOK_MESSAGE( PlayerPickupWeapon ); |
|
HOOK_MESSAGE( QuestObjectiveCompleted ); |
|
|
|
#if !defined(NO_STEAM) |
|
m_CallbackScreenshotRequested.Register( this, &ClientModeTFNormal::OnScreenshotRequested ); |
|
#endif |
|
|
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: If you don't know what a destructor is by now, you are probably going to get fired |
|
//----------------------------------------------------------------------------- |
|
ClientModeTFNormal::~ClientModeTFNormal() |
|
{ |
|
} |
|
|
|
// See interface.h/.cpp for specifics: basically this ensures that we actually Sys_UnloadModule the dll and that we don't call Sys_LoadModule |
|
// over and over again. |
|
static CDllDemandLoader g_GameUI( "GameUI" ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void ClientModeTFNormal::Init() |
|
{ |
|
m_pMenuEngyBuild = ( CHudMenuEngyBuild * )GET_HUDELEMENT( CHudMenuEngyBuild ); |
|
Assert( m_pMenuEngyBuild ); |
|
|
|
m_pMenuEngyDestroy = ( CHudMenuEngyDestroy * )GET_HUDELEMENT( CHudMenuEngyDestroy ); |
|
Assert( m_pMenuEngyDestroy ); |
|
|
|
m_pMenuSpyDisguise = ( CHudMenuSpyDisguise * )GET_HUDELEMENT( CHudMenuSpyDisguise ); |
|
Assert( m_pMenuSpyDisguise ); |
|
|
|
m_pFreezePanel = ( CTFFreezePanel * )GET_HUDELEMENT( CTFFreezePanel ); |
|
Assert( m_pFreezePanel ); |
|
|
|
m_pQuickSwitch = ( CItemQuickSwitchPanel * )GET_HUDELEMENT( CItemQuickSwitchPanel ); |
|
Assert( m_pQuickSwitch ); |
|
|
|
m_pMenuTauntSelection = ( CHudMenuTauntSelection * )GET_HUDELEMENT( CHudMenuTauntSelection ); |
|
Assert( m_pMenuTauntSelection ); |
|
|
|
m_pMenuUpgradePanel = ( CHudUpgradePanel* )GET_HUDELEMENT( CHudUpgradePanel ); |
|
|
|
#ifdef STAGING_ONLY |
|
m_pMenuSpyBuild = ( CHudMenuSpyBuild * )GET_HUDELEMENT( CHudMenuSpyBuild ); |
|
Assert( m_pMenuSpyBuild ); |
|
#endif // STAGING_ONLY |
|
|
|
m_pMenuSpell = ( CHudSpellMenu * )GET_HUDELEMENT( CHudSpellMenu); |
|
Assert( m_pMenuSpell ); |
|
|
|
m_pEurekaTeleportMenu = ( CHudEurekaEffectTeleportMenu * )GET_HUDELEMENT( CHudEurekaEffectTeleportMenu ); |
|
Assert( m_pEurekaTeleportMenu ); |
|
|
|
m_pTeamGoalTournament = (CHudTeamGoalTournament *)GET_HUDELEMENT( CHudTeamGoalTournament ); |
|
Assert( m_pTeamGoalTournament ); |
|
|
|
m_pInspectPanel = (CHudInspectPanel *)GET_HUDELEMENT( CHudInspectPanel ); |
|
Assert( m_pInspectPanel ); |
|
|
|
m_wasConnectedLastUpdate = false; |
|
|
|
m_lastServerIP = 0; |
|
m_lastServerPort = 0; |
|
m_lastServerName = NULL; |
|
m_lastServerConnectTime = 0; |
|
|
|
m_flNextAllowedHighFiveHintTime = 0.0f; |
|
|
|
m_bInfoPanelShown = false; |
|
m_bRestrictInfoPanel = false; |
|
|
|
CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory(); |
|
if ( gameUIFactory ) |
|
{ |
|
m_pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL ); |
|
if ( NULL != m_pGameUI ) |
|
{ |
|
// insert stats summary panel as the loading background dialog |
|
CTFStatsSummaryPanel *pPanel = GStatsSummaryPanel(); |
|
pPanel->InvalidateLayout( false, true ); |
|
pPanel->SetVisible( false ); |
|
pPanel->MakePopup( false ); |
|
m_pGameUI->SetLoadingBackgroundDialog( pPanel->GetVPanel() ); |
|
|
|
IViewPortPanel *pMMOverride = ( gViewPortInterface->FindPanelByName( PANEL_MAINMENUOVERRIDE ) ); |
|
if ( pMMOverride ) |
|
{ |
|
((CHudMainMenuOverride*)pMMOverride)->AttachToGameUI(); |
|
} |
|
} |
|
} |
|
|
|
#if defined( _X360 ) |
|
m_pScoreboard = (CTFClientScoreBoardDialog *)( gViewPortInterface->FindPanelByName( PANEL_SCOREBOARD ) ); |
|
Assert( m_pScoreboard ); |
|
#endif |
|
|
|
ListenForGameEvent( "localplayer_changeclass" ); |
|
|
|
#ifdef TF_RAID_MODE |
|
ListenForGameEvent( "raid_spawn_mob" ); |
|
ListenForGameEvent( "raid_spawn_squad" ); |
|
#endif // TF_RAID_MODE |
|
|
|
ListenForGameEvent( "player_upgraded" ); |
|
ListenForGameEvent( "player_buyback" ); |
|
ListenForGameEvent( "player_death" ); |
|
ListenForGameEvent( "player_used_powerup_bottle" ); |
|
MannVsMachineStats_Init(); |
|
|
|
ListenForGameEvent( "pve_win_panel" ); |
|
|
|
ListenForGameEvent( "arena_win_panel" ); |
|
ListenForGameEvent( "teamplay_win_panel" ); |
|
ListenForGameEvent( "server_spawn" ); |
|
|
|
ListenForGameEvent( "pumpkin_lord_summoned" ); |
|
ListenForGameEvent( "pumpkin_lord_killed" ); |
|
ListenForGameEvent( "eyeball_boss_summoned" ); |
|
ListenForGameEvent( "eyeball_boss_stunned" ); |
|
ListenForGameEvent( "eyeball_boss_killed" ); |
|
ListenForGameEvent( "eyeball_boss_killer" ); |
|
ListenForGameEvent( "eyeball_boss_escape_imminent" ); |
|
ListenForGameEvent( "eyeball_boss_escaped" ); |
|
|
|
ListenForGameEvent( "merasmus_summoned" ); |
|
ListenForGameEvent( "merasmus_killed" ); |
|
ListenForGameEvent( "merasmus_escape_warning" ); |
|
ListenForGameEvent( "merasmus_escaped" ); |
|
|
|
ListenForGameEvent( "player_highfive_start" ); |
|
ListenForGameEvent( "player_highfive_cancel" ); |
|
ListenForGameEvent( "player_highfive_success" ); |
|
|
|
ListenForGameEvent( "client_beginconnect" ); |
|
|
|
ListenForGameEvent( "player_teleported" ); |
|
ListenForGameEvent( "scorestats_accumulated_reset" ); |
|
ListenForGameEvent( "scorestats_accumulated_update" ); |
|
|
|
extern void Training_Init(); |
|
Training_Init(); |
|
|
|
BaseClass::Init(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void ClientModeTFNormal::Shutdown() |
|
{ |
|
DestroyStatsSummaryPanel(); |
|
} |
|
|
|
void ClientModeTFNormal::InitViewport() |
|
{ |
|
m_pViewport = new TFViewport(); |
|
m_pViewport->Start( gameuifuncs, gameeventmanager ); |
|
} |
|
|
|
|
|
void ClientModeTFNormal::LevelInit( const char *newmap ) |
|
{ |
|
BaseClass::LevelInit( newmap ); |
|
|
|
m_bInfoPanelShown = false; |
|
} |
|
|
|
IClientMode *GetClientModeNormal() |
|
{ |
|
static ClientModeTFNormal g_ClientModeNormal; |
|
|
|
return &g_ClientModeNormal; |
|
} |
|
|
|
|
|
ClientModeTFNormal* GetClientModeTFNormal() |
|
{ |
|
Assert( dynamic_cast< ClientModeTFNormal* >( GetClientModeNormal() ) ); |
|
|
|
return static_cast< ClientModeTFNormal* >( GetClientModeNormal() ); |
|
} |
|
|
|
extern ConVar v_viewmodel_fov; |
|
ConVar v_viewmodel_fov_demo( "viewmodel_fov_demo", "54", FCVAR_ARCHIVE ); |
|
float ClientModeTFNormal::GetViewModelFOV( void ) |
|
{ |
|
// If we're playing back a demo, we clamp the viewmodel fov |
|
if ( engine->IsPlayingDemo() ) |
|
return v_viewmodel_fov_demo.GetFloat(); |
|
|
|
return v_viewmodel_fov.GetFloat(); |
|
} |
|
|
|
extern ConVar r_drawviewmodel; |
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::ShouldDrawViewModel() |
|
{ |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pPlayer ) |
|
{ |
|
if ( pPlayer->m_Shared.InCond( TF_COND_ZOOMED ) ) |
|
return false; |
|
} |
|
|
|
if ( !r_drawviewmodel.GetBool() ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
ConVar tf_hud_no_crosshair_on_scope_zoom( "tf_hud_no_crosshair_on_scope_zoom", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE ); |
|
|
|
bool ClientModeTFNormal::ShouldDrawCrosshair() |
|
{ |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( !pPlayer ) |
|
return false; |
|
|
|
if ( pPlayer->GetPlayerClass() && |
|
pPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_SNIPER && |
|
pPlayer->m_Shared.InCond( TF_COND_ZOOMED ) && |
|
tf_hud_no_crosshair_on_scope_zoom.GetBool() ) |
|
{ |
|
return false; |
|
} |
|
|
|
return ClientModeShared::ShouldDrawCrosshair(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// 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 ClientModeTFNormal::ShouldBlackoutAroundHUD() |
|
{ |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( !pPlayer ) |
|
return true; |
|
|
|
return ClientModeShared::ShouldBlackoutAroundHUD(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Allows the client mode to override mouse control stuff in sourcevr |
|
//----------------------------------------------------------------------------- |
|
HeadtrackMovementMode_t ClientModeTFNormal::ShouldOverrideHeadtrackControl() |
|
{ |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( !pPlayer ) |
|
return HMM_NOOVERRIDE; |
|
|
|
// TODO: check if these actually all work right. |
|
switch ( pPlayer->GetObserverMode() ) |
|
{ |
|
case OBS_MODE_DEATHCAM : // Turned into OBS_MODE_CHASE in VR |
|
case OBS_MODE_ROAMING : |
|
case OBS_MODE_FIXED : // Checked - works. |
|
case OBS_MODE_CHASE : // Checked - works. |
|
case OBS_MODE_POI : // PASSTIME NOT CHECKED |
|
case OBS_MODE_FREEZECAM : // Turned into OBS_MODE_CHASE in VR |
|
return HMM_SHOOTMOVEMOUSE_LOOKFACE; |
|
case OBS_MODE_IN_EYE : // Checked - works. |
|
return HMM_NOOVERRIDE; |
|
} |
|
|
|
return ClientModeShared::ShouldOverrideHeadtrackControl(); |
|
} |
|
|
|
|
|
int ClientModeTFNormal::GetDeathMessageStartHeight( void ) |
|
{ |
|
return m_pViewport->GetDeathMessageStartHeight(); |
|
} |
|
|
|
void ClientModeTFNormal::FireGameEvent( IGameEvent *event ) |
|
{ |
|
const char *eventname = event->GetName(); |
|
|
|
if ( !eventname || !eventname[0] ) |
|
return; |
|
|
|
CBaseHudChat *pHUDChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat ); |
|
if ( FStrEq( "player_changename", eventname ) ) |
|
{ |
|
return; // server sends a colorized text string for this |
|
} |
|
else if ( FStrEq( "localplayer_changeclass", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer && pLocalPlayer->GetPlayerClass() ) |
|
{ |
|
int iClass = pLocalPlayer->GetPlayerClass()->GetClassIndex(); |
|
|
|
// have the player to exec a <class>.cfg file for the class they have selected |
|
char szCmd[128]; |
|
Q_snprintf( szCmd, sizeof( szCmd ), "exec %s.cfg", GetPlayerClassData( iClass )->m_szClassName ); |
|
engine->ExecuteClientCmd( szCmd ); |
|
} |
|
} |
|
|
|
#ifdef TF_RAID_MODE |
|
else if ( FStrEq( "raid_spawn_mob", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Raid.MobSpawn" ); |
|
} |
|
} |
|
else if ( FStrEq( "raid_spawn_squad", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Raid.SquadSpawn" ); |
|
} |
|
} |
|
#endif // TF_RAID_MODE |
|
|
|
else if ( FStrEq( "player_connect_client", eventname ) || FStrEq( "player_disconnect", eventname ) ) |
|
{ |
|
// ignore these |
|
if ( TFGameRules() && TFGameRules()->IsPVEModeActive() && event->GetInt( "bot" ) != 0 ) |
|
return; |
|
} |
|
else if ( FStrEq( "server_cvar", eventname ) ) |
|
{ |
|
if ( TFGameRules() && TFGameRules()->IsPVEModeActive() && !Q_strcmp( event->GetString("cvarname"), "tf_bot_count" ) ) |
|
return; |
|
} |
|
else if ( FStrEq( "player_buyback", eventname ) ) |
|
{ |
|
int idxPlayer = event->GetInt( "player" ); |
|
KeyValuesAD pKeyValues( "data" ); |
|
if ( g_TF_PR ) |
|
{ |
|
const char *pszString = tf_mvm_buybacks_method.GetBool() ? "#TF_PVE_Player_BuyBack_Fixed" : "#TF_PVE_Player_BuyBack"; |
|
|
|
pKeyValues->SetString( "player", g_TF_PR->GetPlayerName( idxPlayer ) ); |
|
pKeyValues->SetInt( "credits", event->GetInt( "cost", 0 ) ); |
|
PrintTextToChatPlayer( idxPlayer, pszString, pKeyValues ); |
|
|
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "MVM.PlayerBoughtIn" ); |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "player_death", eventname ) ) |
|
{ |
|
// Make sure they're not doing a dead ringer fake death |
|
if ( ( event->GetInt( "death_flags" ) & TF_DEATH_FEIGN_DEATH ) == 0 ) |
|
{ |
|
if ( TFGameRules() && ( TFGameRules()->State_Get() == GR_STATE_RND_RUNNING ) && ( TFGameRules()->IsMannVsMachineMode() || TFGameRules()->IsCompetitiveMode() ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
int nVictimIndex = event->GetInt( "victim_entindex" ); |
|
int nVictimTeam = g_TF_PR->GetTeam( nVictimIndex ); |
|
|
|
// See if there are any other players still alive |
|
bool bSomeAlive = false; |
|
for ( int playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++ ) |
|
{ |
|
if ( !g_TF_PR->IsConnected( playerIndex ) ) |
|
continue; |
|
|
|
if ( nVictimIndex == playerIndex ) |
|
continue; |
|
|
|
if ( nVictimTeam != g_TF_PR->GetTeam( playerIndex ) ) |
|
continue; |
|
|
|
if ( g_TF_PR->IsAlive( playerIndex ) ) |
|
{ |
|
// Found one |
|
bSomeAlive = true; |
|
break; |
|
} |
|
} |
|
|
|
if ( !bSomeAlive ) |
|
{ |
|
if ( TFGameRules()->IsMannVsMachineMode() ) |
|
{ |
|
if ( nVictimTeam == TF_TEAM_PVE_DEFENDERS ) |
|
{ |
|
// Inform the team that everyone is dead |
|
pLocalPlayer->EmitSound( "Announcer.MVM_All_Dead" ); |
|
} |
|
} |
|
else |
|
{ |
|
const char *pszSound = NULL; |
|
|
|
if ( ( RandomInt( 1, 100 ) <= 20 ) || ( pLocalPlayer->GetTeamNumber() < FIRST_GAME_TEAM ) ) |
|
{ |
|
pszSound = ( nVictimTeam == TF_TEAM_RED ) ? "Announcer.TeamWipeRed" : "Announcer.TeamWipeBlu"; |
|
} |
|
else if ( pLocalPlayer->GetTeamNumber() == nVictimTeam ) |
|
{ |
|
pszSound = "Announcer.YourTeamWiped"; |
|
} |
|
else |
|
{ |
|
pszSound = "Announcer.TheirTeamWiped"; |
|
} |
|
|
|
if ( pszSound ) |
|
{ |
|
pLocalPlayer->EmitSound( pszSound ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "player_used_powerup_bottle", eventname ) ) |
|
{ |
|
int idxPlayer = event->GetInt( "player" ); |
|
KeyValuesAD pKeyValues( "data" ); |
|
if ( g_TF_PR ) |
|
{ |
|
pKeyValues->SetString( "player", g_TF_PR->GetPlayerName( idxPlayer ) ); |
|
const char *pText = NULL; |
|
switch ( event->GetInt( "type" ) ) |
|
{ |
|
case POWERUP_BOTTLE_CRITBOOST: pText = "#TF_PVE_Player_UsedCritsBottle"; break; |
|
case POWERUP_BOTTLE_UBERCHARGE: pText = "#TF_PVE_Player_UsedUberBottle"; break; |
|
case POWERUP_BOTTLE_RECALL: pText = "#TF_PVE_Player_UsedRecallBottle"; break; |
|
case POWERUP_BOTTLE_REFILL_AMMO: pText = "#TF_PVE_Player_UsedRefillAmmoBottle"; break; |
|
case POWERUP_BOTTLE_BUILDINGS_INSTANT_UPGRADE: pText = "#TF_PVE_Player_UsedBuildingUpgrade"; break; |
|
case POWERUP_BOTTLE_RADIUS_STEALTH: pText = "#TF_PVE_Player_UsedRadiusStealth"; break; |
|
#ifdef STAGING_ONLY |
|
case POWERUP_BOTTLE_SEE_CASH_THROUGH_WALL: pText = "#TF_PVE_Player_SeeCashThroughWall"; break; |
|
#endif |
|
} |
|
if ( pText != NULL ) |
|
{ |
|
PrintTextToChatPlayer( idxPlayer, pText, pKeyValues ); |
|
} |
|
|
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "MVM.PlayerUsedPowerup" ); |
|
} |
|
} |
|
} |
|
else if ( |
|
FStrEq( "pve_win_panel", eventname ) || |
|
FStrEq( "arena_win_panel", eventname ) || |
|
FStrEq( "teamplay_win_panel", eventname ) ) |
|
{ |
|
#if defined( REPLAY_ENABLED ) |
|
DisplayReplayReminder(); |
|
#endif |
|
} |
|
else if ( FStrEq( "server_spawn", eventname ) ) |
|
{ |
|
uint32 newServerIP = 0; |
|
int newServerPort = event->GetInt( "port" ); |
|
|
|
const char *pzAddress = event->GetString( "address" ); |
|
if ( pzAddress ) |
|
{ |
|
CUtlStringList IPs; |
|
V_SplitString( pzAddress, ".", IPs ); |
|
|
|
if ( IPs.Count() == 4 ) |
|
{ |
|
byte ip[4]; |
|
for ( int i=0; i<IPs.Count() && i<4; ++i ) |
|
{ |
|
ip[i] = (byte) Q_atoi( IPs[i] ); |
|
} |
|
newServerIP = (ip[0]<<24) + (ip[1]<<16) + (ip[2]<<8) + ip[3]; |
|
} |
|
} |
|
|
|
if ( m_lastServerConnectTime == 0 || newServerIP != m_lastServerIP || newServerPort != m_lastServerPort ) |
|
{ |
|
// we are connecting, or have connected to a different server |
|
m_lastServerIP = newServerIP; |
|
m_lastServerPort = newServerPort; |
|
|
|
const char *hostname = event->GetString( "hostname" ); |
|
if ( hostname ) |
|
{ |
|
if ( m_lastServerName ) |
|
{ |
|
delete [] m_lastServerName; |
|
m_lastServerName = NULL; |
|
} |
|
|
|
int hostnameLength = V_strlen( hostname )+1; |
|
|
|
m_lastServerName = new char[ hostnameLength ]; |
|
|
|
V_strncpy( m_lastServerName, hostname, hostnameLength ); |
|
} |
|
|
|
m_lastServerConnectTime = GetSteamWorksSGameStatsUploader().GetTimeSinceEpoch(); |
|
} |
|
|
|
m_flNextAllowedHighFiveHintTime = 0.0f; |
|
|
|
// Play Sound and flash window if joining a game from a lobby |
|
CTFGSLobby *pLobby = GTFGCClientSystem()->GetLobby(); |
|
if ( pLobby ) |
|
{ |
|
engine->FlashWindow(); |
|
|
|
// If minimized, Blink and play noise |
|
if ( engine->IsActiveApp() ) |
|
{ |
|
vgui::surface()->PlaySound( "ui/vote_started.wav" ); |
|
} |
|
else |
|
{ |
|
char fullpath[ 512 ]; |
|
g_pFullFileSystem->RelativePathToFullPath( "sound/ui/vote_started.wav", "GAME", fullpath, sizeof( fullpath ) ); |
|
PlayOutOfGameSound( fullpath ); |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "pumpkin_lord_summoned", eventname ) ) |
|
{ |
|
if ( !TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Halloween.HeadlessBossSpawn" ); |
|
} |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
pNotification->SetText( "#TF_Halloween_Boss_Appeared" ); |
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
} |
|
else if ( FStrEq( "pumpkin_lord_killed", eventname ) ) |
|
{ |
|
if ( !TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Halloween.HeadlessBossDeath" ); |
|
} |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
pNotification->SetText( "#TF_Halloween_Boss_Killed" ); |
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
} |
|
else if ( FStrEq( "eyeball_boss_summoned", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Halloween.MonoculusBossSpawn" ); |
|
} |
|
|
|
KeyValuesAD keyValues( "eyeball_boss" ); |
|
keyValues->SetColor( "custom_color", colorEyeballBossText ); |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
wchar_t *pszBaseString = g_pVGuiLocalize->Find( "TF_Halloween_Eyeball_Boss_LevelUp_Appeared" ); |
|
if ( pszBaseString ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
wchar_t wTemp[256]; |
|
g_pVGuiLocalize->ConstructString_safe( wTemp, pszBaseString, pKeyValues ); |
|
|
|
static char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wTemp, szAnsi, sizeof(szAnsi) ); |
|
|
|
pNotification->SetText( szAnsi ); |
|
} |
|
} |
|
else |
|
{ |
|
pNotification->SetText( "#TF_Halloween_Eyeball_Boss_Appeared" ); |
|
} |
|
|
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
pNotification->SetKeyValues( keyValues ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
else if ( FStrEq( "eyeball_boss_stunned", eventname ) ) |
|
{ |
|
int iPlayerIndex = event->GetInt( "player_entindex" ); |
|
if ( pHUDChat ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
if ( g_TF_PR ) |
|
{ |
|
pKeyValues->SetString( "player", g_TF_PR->GetPlayerName( iPlayerIndex ) ); |
|
|
|
pHUDChat->SetCustomColor( colorEyeballBossText ); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
if ( iLevel > 1 ) |
|
{ |
|
pKeyValues->SetInt( "level", iLevel ); |
|
PrintTextToChatPlayer( iPlayerIndex, "#TF_Halloween_Eyeball_Boss_LevelUp_Stun", pKeyValues ); |
|
} |
|
else |
|
{ |
|
PrintTextToChatPlayer( iPlayerIndex, "#TF_Halloween_Eyeball_Boss_Stun", pKeyValues ); |
|
} |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "eyeball_boss_killed", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Halloween.MonoculusBossDeath" ); |
|
} |
|
|
|
KeyValuesAD keyValues( "eyeball_boss" ); |
|
keyValues->SetColor( "custom_color", colorEyeballBossText ); |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
wchar_t *pszBaseString = g_pVGuiLocalize->Find( "TF_Halloween_Eyeball_Boss_LevelUp_Killed" ); |
|
if ( pszBaseString ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
wchar_t wTemp[256]; |
|
g_pVGuiLocalize->ConstructString_safe( wTemp, pszBaseString, pKeyValues ); |
|
|
|
static char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wTemp, szAnsi, sizeof(szAnsi) ); |
|
|
|
pNotification->SetText( szAnsi ); |
|
} |
|
} |
|
else |
|
{ |
|
pNotification->SetText( "#TF_Halloween_Eyeball_Boss_Killed" ); |
|
} |
|
|
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
pNotification->SetKeyValues( keyValues ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
else if ( FStrEq( "eyeball_boss_killer", eventname ) ) |
|
{ |
|
int iPlayerIndex = event->GetInt( "player_entindex" ); |
|
if ( pHUDChat ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
if ( g_TF_PR ) |
|
{ |
|
pKeyValues->SetString( "player", g_TF_PR->GetPlayerName( iPlayerIndex ) ); |
|
|
|
pHUDChat->SetCustomColor( colorEyeballBossText ); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
PrintTextToChatPlayer( iPlayerIndex, "#TF_Halloween_Eyeball_Boss_LevelUp_Killers", pKeyValues ); |
|
} |
|
else |
|
{ |
|
PrintTextToChatPlayer( iPlayerIndex, "#TF_Halloween_Eyeball_Boss_Killers", pKeyValues ); |
|
} |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "eyeball_boss_escape_imminent", eventname ) ) |
|
{ |
|
int nSecondsRemaining = event->GetInt( "time_remaining" ); |
|
|
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
if ( nSecondsRemaining <= 10 ) |
|
pLocalPlayer->EmitSound( "Halloween.EyeballBossEscapeImminent" ); |
|
else |
|
pLocalPlayer->EmitSound( "Halloween.EyeballBossEscapeSoon" ); |
|
} |
|
|
|
if ( pHUDChat ) |
|
{ |
|
char szEyeballBossEscaping[128]; |
|
pHUDChat->SetCustomColor( colorEyeballBossText ); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
V_sprintf_safe( szEyeballBossEscaping, "#TF_Halloween_Eyeball_Boss_LevelUp_Escaping_In_%i", nSecondsRemaining ); |
|
|
|
PrintTextToChat( szEyeballBossEscaping, pKeyValues ); |
|
} |
|
else |
|
{ |
|
V_sprintf_safe( szEyeballBossEscaping, "#TF_Halloween_Eyeball_Boss_Escaping_In_%i", nSecondsRemaining ); |
|
|
|
PrintTextToChat( szEyeballBossEscaping ); |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "eyeball_boss_escaped", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Halloween.EyeballBossEscaped" ); |
|
} |
|
|
|
KeyValuesAD keyValues( "eyeball_boss" ); |
|
keyValues->SetColor( "custom_color", colorEyeballBossText ); |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
wchar_t *pszBaseString = g_pVGuiLocalize->Find( "TF_Halloween_Eyeball_Boss_LevelUp_Escaped" ); |
|
if ( pszBaseString ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
wchar_t wTemp[256]; |
|
g_pVGuiLocalize->ConstructString_safe( wTemp, pszBaseString, pKeyValues ); |
|
|
|
static char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wTemp, szAnsi, sizeof(szAnsi) ); |
|
|
|
pNotification->SetText( szAnsi ); |
|
} |
|
} |
|
else |
|
{ |
|
pNotification->SetText( "#TF_Halloween_Eyeball_Boss_Escaped" ); |
|
} |
|
|
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
pNotification->SetKeyValues( keyValues ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
else if ( FStrEq( "merasmus_summoned", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Halloween.MerasmusBossSpawn" ); |
|
} |
|
|
|
KeyValuesAD keyValues( "merasmus" ); |
|
keyValues->SetColor( "custom_color", colorMerasmusText ); |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
wchar_t *pszBaseString = g_pVGuiLocalize->Find( "TF_Halloween_Merasmus_LevelUp_Appeared" ); |
|
if ( pszBaseString ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
wchar_t wTemp[256]; |
|
g_pVGuiLocalize->ConstructString_safe( wTemp, pszBaseString, pKeyValues ); |
|
|
|
static char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wTemp, szAnsi, sizeof(szAnsi) ); |
|
|
|
pNotification->SetText( szAnsi ); |
|
} |
|
} |
|
else |
|
{ |
|
pNotification->SetText( "#TF_Halloween_Merasmus_Appeared" ); |
|
} |
|
|
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
pNotification->SetKeyValues( keyValues ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
else if ( FStrEq( "merasmus_killed", eventname ) ) |
|
{ |
|
KeyValuesAD keyValues( "merasmus" ); |
|
keyValues->SetColor( "custom_color", colorMerasmusText ); |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
wchar_t *pszBaseString = g_pVGuiLocalize->Find( "TF_Halloween_Merasmus_LevelUp_Killed" ); |
|
if ( pszBaseString ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
wchar_t wTemp[256]; |
|
g_pVGuiLocalize->ConstructString_safe( wTemp, pszBaseString, pKeyValues ); |
|
|
|
static char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wTemp, szAnsi, sizeof(szAnsi) ); |
|
|
|
pNotification->SetText( szAnsi ); |
|
} |
|
} |
|
else |
|
{ |
|
pNotification->SetText( "#TF_Halloween_Merasmus_Killed" ); |
|
} |
|
|
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
pNotification->SetKeyValues( keyValues ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
else if ( FStrEq( "merasmus_escape_warning", eventname ) ) |
|
{ |
|
int nSecondsRemaining = event->GetInt( "time_remaining" ); |
|
|
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
if ( nSecondsRemaining <= 10 ) |
|
pLocalPlayer->EmitSound( "Halloween.EyeballBossEscapeImminent" ); |
|
else |
|
pLocalPlayer->EmitSound( "Halloween.EyeballBossEscapeSoon" ); |
|
} |
|
|
|
if ( pHUDChat ) |
|
{ |
|
char szEyeballBossEscaping[128]; |
|
pHUDChat->SetCustomColor( colorMerasmusText ); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
V_sprintf_safe( szEyeballBossEscaping, "#TF_Halloween_Merasmus_LevelUp_Escaping_In_%i", nSecondsRemaining ); |
|
|
|
PrintTextToChat( szEyeballBossEscaping, pKeyValues ); |
|
} |
|
else |
|
{ |
|
V_sprintf_safe( szEyeballBossEscaping, "#TF_Halloween_Merasmus_Escaping_In_%i", nSecondsRemaining ); |
|
|
|
PrintTextToChat( szEyeballBossEscaping ); |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "merasmus_escaped", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer ) |
|
{ |
|
pLocalPlayer->EmitSound( "Halloween.EyeballBossEscaped" ); |
|
} |
|
|
|
KeyValuesAD keyValues( "merasmus" ); |
|
keyValues->SetColor( "custom_color", colorMerasmusText ); |
|
|
|
CEconNotification *pNotification = new CEconNotification(); |
|
|
|
const int iLevel = event->GetInt( "level" ); |
|
|
|
if ( iLevel > 1 ) |
|
{ |
|
wchar_t *pszBaseString = g_pVGuiLocalize->Find( "TF_Halloween_Merasmus_LevelUp_Escaped" ); |
|
if ( pszBaseString ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "level", iLevel ); |
|
|
|
wchar_t wTemp[256]; |
|
g_pVGuiLocalize->ConstructString_safe( wTemp, pszBaseString, pKeyValues ); |
|
|
|
static char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wTemp, szAnsi, sizeof(szAnsi) ); |
|
|
|
pNotification->SetText( szAnsi ); |
|
} |
|
} |
|
else |
|
{ |
|
pNotification->SetText( "#TF_Halloween_Merasmus_Escaped" ); |
|
} |
|
|
|
pNotification->SetLifetime( 5.0f ); |
|
pNotification->SetSoundFilename( "vo/null.mp3" ); |
|
pNotification->SetKeyValues( keyValues ); |
|
NotificationQueue_Add( pNotification ); |
|
} |
|
else if ( FStrEq( "player_highfive_start", eventname ) ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
|
|
// Don't show a hint if we're dead, we've already done it the maximum amount of times, or if it's too soon. |
|
if ( pLocalPlayer && pLocalPlayer->IsAlive() && |
|
( tf_taunt_always_show_hint.GetBool() || |
|
( tf_highfive_hintcount.GetInt() < TF_HIGHFIVE_HINT_MAXHINTS && gpGlobals->curtime > m_flNextAllowedHighFiveHintTime ) ) ) |
|
{ |
|
int entindex = event->GetInt( "entindex" ); |
|
C_BasePlayer *pHighFiveInitiator = UTIL_PlayerByIndex( entindex ); |
|
if ( pHighFiveInitiator && pHighFiveInitiator != pLocalPlayer && ( pHighFiveInitiator->GetTeamNumber() == pLocalPlayer->GetTeamNumber() || tf_allow_all_team_partner_taunt.GetBool() ) ) |
|
{ |
|
// check that this player isn't too far away |
|
Vector vecStart = pLocalPlayer->EyePosition(); |
|
Vector vecEnd = pHighFiveInitiator->EyePosition(); |
|
float flLength = (vecEnd - vecStart).Length(); |
|
|
|
if ( flLength < TF_HIGHFIVE_HINT_MAXDIST ) |
|
{ |
|
// check that we have line of sight to this player |
|
trace_t tr; |
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, pLocalPlayer, COLLISION_GROUP_NONE, &tr ); |
|
|
|
if ( !tr.startsolid && tr.m_pEnt != NULL && tr.m_pEnt == pHighFiveInitiator ) |
|
{ |
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "show_annotation" ); |
|
if ( pEvent ) |
|
{ |
|
Vector location = pHighFiveInitiator->GetAbsOrigin(); |
|
|
|
pEvent->SetString( "text", "#TF_HighFive_Hint" ); |
|
pEvent->SetInt( "id", TF_HIGHFIVE_HINT_MASK | entindex ); |
|
pEvent->SetFloat( "worldPosX", location.x ); |
|
pEvent->SetFloat( "worldPosY", location.y ); |
|
pEvent->SetFloat( "worldPosZ", location.z + 48.0f ); |
|
pEvent->SetFloat( "lifetime", 10.0f ); |
|
pEvent->SetInt( "follow_entindex", entindex ); |
|
|
|
gameeventmanager->FireEventClientSide( pEvent ); |
|
tf_highfive_hintcount.SetValue( tf_highfive_hintcount.GetInt() + 1 ); |
|
|
|
m_flNextAllowedHighFiveHintTime = gpGlobals->curtime + TF_HIGHFIVE_HINT_MINTIMEBETWEEN; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else if ( FStrEq( "player_highfive_cancel", eventname ) ) |
|
{ |
|
int entindex = event->GetInt( "entindex" ); |
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "hide_annotation" ); |
|
if ( pEvent ) |
|
{ |
|
pEvent->SetInt( "id", TF_HIGHFIVE_HINT_MASK | entindex ); |
|
gameeventmanager->FireEventClientSide( pEvent ); |
|
} |
|
} |
|
else if ( FStrEq( "player_highfive_success", eventname ) ) |
|
{ |
|
int entindex = event->GetInt( "initiator_entindex" ); |
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "hide_annotation" ); |
|
if ( pEvent ) |
|
{ |
|
pEvent->SetInt( "id", TF_HIGHFIVE_HINT_MASK | entindex ); |
|
gameeventmanager->FireEventClientSide( pEvent ); |
|
} |
|
} |
|
else if ( FStrEq( "client_beginconnect", eventname ) ) |
|
{ |
|
const char *pchSource = event->GetString( "source" ); |
|
m_bRestrictInfoPanel = pchSource && ( FStrEq( "matchmaking", pchSource ) || !Q_strncmp( pchSource, "quickplay_", 10 ) ); |
|
|
|
m_bInfoPanelShown = false; |
|
} |
|
else if ( FStrEq( "player_teleported", eventname ) ) |
|
{ |
|
int iUserID = event->GetInt( "userid" ); |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if( pLocalPlayer && pLocalPlayer->GetUserID() == iUserID && UseVR() ) |
|
{ |
|
g_ClientVirtualReality.AlignTorsoAndViewToWeapon(); |
|
} |
|
} |
|
else if ( FStrEq( "scorestats_accumulated_reset", eventname ) ) |
|
{ |
|
if ( g_TF_PR && TFGameRules() && !TFGameRules()->IsMannVsMachineMode() ) |
|
{ |
|
g_TF_PR->ResetPlayerScoreStats(); |
|
} |
|
} |
|
else if ( FStrEq( "scorestats_accumulated_update", eventname ) ) |
|
{ |
|
if ( g_TF_PR && TFGameRules() && !TFGameRules()->IsMannVsMachineMode() ) |
|
{ |
|
g_TF_PR->UpdatePlayerScoreStats(); |
|
} |
|
} |
|
|
|
BaseClass::FireGameEvent( event ); |
|
} |
|
|
|
void ClientModeTFNormal::PostRenderVGui() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::CreateMove( float flInputSampleTime, CUserCmd *cmd ) |
|
{ |
|
return BaseClass::CreateMove( flInputSampleTime, cmd ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: See if hud elements want key input. Return 0 if the key is swallowed |
|
//----------------------------------------------------------------------------- |
|
int ClientModeTFNormal::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) |
|
{ |
|
// Let scoreboard handle input first because on X360 we need gamertags and |
|
// gamercards accessible at all times when gamertag is visible. |
|
#if defined( _X360 ) |
|
if ( m_pScoreboard ) |
|
{ |
|
if ( !m_pScoreboard->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
#endif |
|
|
|
// Applies basic tags if we're going to take a screenshot |
|
ScreenshotTaggingKeyInput( down, keynum, pszCurrentBinding ); |
|
|
|
if ( TrainingHandlesKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
|
|
if ( CoachingHandlesKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
|
|
if ( ItemTestHandlesKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
|
|
if ( HalloweenHandlesKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
|
|
if ( TauntHandlesKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
|
|
// check for hud menus |
|
if ( m_pMenuEngyBuild ) |
|
{ |
|
if ( !m_pMenuEngyBuild->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
if ( m_pMenuEngyDestroy ) |
|
{ |
|
if ( !m_pMenuEngyDestroy->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
if ( m_pMenuSpyDisguise ) |
|
{ |
|
if ( !m_pMenuSpyDisguise->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
if ( m_pFreezePanel ) |
|
{ |
|
m_pFreezePanel->HudElementKeyInput( down, keynum, pszCurrentBinding ); |
|
} |
|
|
|
if ( m_pQuickSwitch ) |
|
{ |
|
if ( !m_pQuickSwitch->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
if ( m_pMenuTauntSelection ) |
|
{ |
|
if ( !m_pMenuTauntSelection->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
#ifdef STAGING_ONLY |
|
if ( m_pMenuSpyBuild ) |
|
{ |
|
if ( !m_pMenuSpyBuild->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
#endif // STAGING_ONLY |
|
|
|
if ( m_pEurekaTeleportMenu ) |
|
{ |
|
if ( !m_pEurekaTeleportMenu->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
if ( m_pInspectPanel ) |
|
{ |
|
if ( !m_pInspectPanel->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
if ( m_pTeamGoalTournament ) |
|
{ |
|
if ( !m_pTeamGoalTournament->HudElementKeyInput( down, keynum, pszCurrentBinding ) ) |
|
{ |
|
return 0; |
|
} |
|
} |
|
|
|
if ( TournamentHudElementKeyInput( down, keynum, pszCurrentBinding ) == true ) |
|
return 0; |
|
|
|
if ( ArenaClassLayoutKeyInput( down, keynum, pszCurrentBinding ) == true ) |
|
return 0; |
|
|
|
#ifndef _X360 |
|
if ( ShouldScoreBoardHandleKeyInput( down, keynum, pszCurrentBinding ) ) |
|
return 0; |
|
#endif // !360 |
|
|
|
return BaseClass::HudElementKeyInput( down, keynum, pszCurrentBinding ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: See if spectator input occurred. Return 0 if the key is swallowed. |
|
//----------------------------------------------------------------------------- |
|
int ClientModeTFNormal::HandleSpectatorKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) |
|
{ |
|
#if defined( _X360 ) |
|
// On X360 when we have scoreboard up in spectator menu we cannot |
|
// steal any input because gamertags must be selectable and gamercards |
|
// must be accessible. |
|
// We cannot rely on any keybindings in this case since user could have |
|
// remapped everything. |
|
if ( m_pScoreboard && m_pScoreboard->IsVisible() ) |
|
{ |
|
return 1; |
|
} |
|
#endif |
|
|
|
// @note Tom Bui: Coaching, so override all input |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pLocalPlayer && pLocalPlayer->m_bIsCoaching ) |
|
{ |
|
if ( down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+jump" ) == 0 ) |
|
{ |
|
engine->ClientCmd( "spec_mode" ); |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
else |
|
{ |
|
return BaseClass::HandleSpectatorKeyInput( down, keynum, pszCurrentBinding ); |
|
} |
|
} |
|
|
|
bool ClientModeTFNormal::DoPostScreenSpaceEffects( const CViewSetup *pSetup ) |
|
{ |
|
if ( !BaseClass::DoPostScreenSpaceEffects( pSetup ) ) |
|
return false; |
|
|
|
if( IsInFreezeCam() ) |
|
return false; |
|
|
|
g_GlowObjectManager.RenderGlowEffects( pSetup, 0 ); |
|
|
|
return true; |
|
} |
|
|
|
#if !defined(NO_STEAM) |
|
void ClientModeTFNormal::OnScreenshotRequested( ScreenshotRequested_t *pParam ) |
|
{ |
|
// Steam has requested a screenshot, act as if the key currently bound to screenshots |
|
// has been pressed (we want tagging and the killcam screenshot behavior if applicable) |
|
HudElementKeyInput( 0, BUTTON_CODE_INVALID, "screenshot" ); |
|
engine->ClientCmd( "screenshot" ); |
|
} |
|
#endif |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------- |
|
ConVar cl_ask_favorite_min_session_duration( "cl_ask_favorite_min_session_duration", "600", 0, "If player stays on a server for longer than this time (in seconds) prompt to add server to favorites" ); |
|
ConVar cl_ask_favorite_opt_out( "cl_ask_favorite_opt_out", "0", FCVAR_ARCHIVE, "If nonzero, don't auto-ask to favorite servers" ); |
|
ConVar cl_ask_favorite_for_any_server( "cl_ask_favorite_for_any_server", "0", 0, "If nonzero, auto-ask for local/LAN servers (for debugging)" ); |
|
|
|
|
|
ConVar cl_ask_blacklist_max_session_duration( "cl_ask_blacklist_max_session_duration", "60", 0, "If player stays on a server for less than this time (in seconds) prompt to add server to blacklist" ); |
|
ConVar cl_ask_blacklist_opt_out( "cl_ask_blacklist_opt_out", "0", FCVAR_ARCHIVE, "If nonzero, don't auto-ask to blacklist servers" ); |
|
ConVar cl_ask_blacklist_for_any_server( "cl_ask_blacklist_for_any_server", "0", 0, "If nonzero, auto-ask for local/LAN servers (for debugging)" ); |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
void OnAskFavoriteDialogButtonPressed( bool bConfirm, void *pContext ) |
|
{ |
|
if ( bConfirm ) |
|
{ |
|
// add last server to our favorites |
|
steamapicontext->SteamMatchmaking()->AddFavoriteGame( steamapicontext->SteamUtils()->GetAppID(), |
|
GetClientModeTFNormal()->GetLastConnectedServerIP(), |
|
GetClientModeTFNormal()->GetLastConnectedServerPort(), |
|
GetClientModeTFNormal()->GetLastConnectedServerPort(), |
|
k_unFavoriteFlagFavorite, |
|
CRTime::RTime32TimeCur() ); |
|
|
|
// Send it to the GC |
|
GCSDK::CGCMsg< MsgGCServerBrowser_Server_t > msg( k_EMsgGCServerBrowser_FavoriteServer ); |
|
msg.Body().m_unIP = GetClientModeTFNormal()->GetLastConnectedServerIP(); |
|
msg.Body().m_usPort = GetClientModeTFNormal()->GetLastConnectedServerPort(); |
|
msg.Body().m_ubSource = k_EGCMsgServerBrowser_FromAutoAskDialog; |
|
GCClientSystem()->BSendMessage( msg ); |
|
} |
|
} |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
void OnAskBlacklistDialogButtonPressed( bool bConfirm, void *pContext ) |
|
{ |
|
if ( bConfirm ) |
|
{ |
|
// add last server to our blacklist |
|
CBlacklistedServerManager blackList; |
|
blackList.LoadServersFromFile( BLACKLIST_DEFAULT_SAVE_FILE, false ); |
|
|
|
blackList.AddServer( GetClientModeTFNormal()->GetLastConnectedServerName(), |
|
GetClientModeTFNormal()->GetLastConnectedServerIP(), |
|
GetClientModeTFNormal()->GetLastConnectedServerPort() ); |
|
|
|
blackList.SaveToFile( BLACKLIST_DEFAULT_SAVE_FILE ); |
|
|
|
// Send it to the GC |
|
GCSDK::CGCMsg< MsgGCServerBrowser_Server_t > msg( k_EMsgGCServerBrowser_BlacklistServer ); |
|
msg.Body().m_unIP = GetClientModeTFNormal()->GetLastConnectedServerIP(); |
|
msg.Body().m_usPort = GetClientModeTFNormal()->GetLastConnectedServerPort(); |
|
msg.Body().m_ubSource = k_EGCMsgServerBrowser_FromAutoAskDialog; |
|
GCClientSystem()->BSendMessage( msg ); |
|
} |
|
} |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
// If conditions are right, prompt the user to either favorite or blacklist |
|
// the last server they had connected to. |
|
void ClientModeTFNormal::AskFavoriteOrBlacklist() const |
|
{ |
|
// based on the time we spent on our last server, ask to favorite or blacklist it |
|
int sessionDuration = GetSteamWorksSGameStatsUploader().GetTimeSinceEpoch() - m_lastServerConnectTime; |
|
|
|
if ( sessionDuration > 0 ) |
|
{ |
|
// favorite? |
|
if ( !cl_ask_favorite_opt_out.GetBool() && sessionDuration > cl_ask_favorite_min_session_duration.GetFloat() ) |
|
{ |
|
// don't ask to favorite reserved addresses |
|
if ( !cl_ask_favorite_for_any_server.GetBool() ) |
|
{ |
|
netadr_t netAdr( GetLastConnectedServerIP(), GetLastConnectedServerPort() ); |
|
|
|
if ( !netAdr.IsValid() || netAdr.IsReservedAdr() ) |
|
return; |
|
|
|
// Don't offer this for Valve servers, either |
|
if ( GTFGCClientSystem()->BIsIPRecentMatchServer( netAdr ) ) |
|
{ |
|
return; |
|
} |
|
} |
|
|
|
// is this server already a favorite? |
|
for( int i=0; i<steamapicontext->SteamMatchmaking()->GetFavoriteGameCount(); ++i ) |
|
{ |
|
AppId_t appID = steamapicontext->SteamUtils()->GetAppID(); |
|
uint32 IP; |
|
uint16 connPort; |
|
uint16 queryPort; |
|
uint32 flags; |
|
uint32 time32LastPlayedOnServer; |
|
|
|
if ( steamapicontext->SteamMatchmaking()->GetFavoriteGame( i, &appID, &IP, &connPort, &queryPort, &flags, &time32LastPlayedOnServer ) ) |
|
{ |
|
if ( ( flags & k_unFavoriteFlagFavorite ) == false ) |
|
{ |
|
// not a favorite |
|
continue; |
|
} |
|
|
|
if ( ( appID == 0 || appID == steamapicontext->SteamUtils()->GetAppID() ) && |
|
IP == GetLastConnectedServerIP() && |
|
connPort == GetLastConnectedServerPort() ) |
|
{ |
|
// already have this server in our favorites - don't ask again |
|
return; |
|
} |
|
} |
|
} |
|
|
|
// new potential favorite - ask |
|
ShowConfirmOptOutDialog( "#TF_Serverlist_Ask_Favorite_Title", "#TF_Serverlist_Ask_Favorite_Text", |
|
"#TF_Serverlist_Ask_Yes", "#TF_Serverlist_Ask_No", |
|
"#TF_ServerList_Ask_Favorite_Opt_Out", "cl_ask_favorite_opt_out", |
|
OnAskFavoriteDialogButtonPressed, NULL ); |
|
} |
|
|
|
// blacklist? |
|
if ( !cl_ask_blacklist_opt_out.GetBool() && sessionDuration < cl_ask_blacklist_max_session_duration.GetFloat() ) |
|
{ |
|
// is this server already blacklisted? |
|
CBlacklistedServerManager blackList; |
|
blackList.LoadServersFromFile( BLACKLIST_DEFAULT_SAVE_FILE, false ); |
|
|
|
netadr_t lastServer( GetLastConnectedServerIP(), (unsigned short)GetLastConnectedServerPort() ); |
|
if ( ( !blackList.CanServerBeBlacklisted( lastServer.GetIPHostByteOrder(), lastServer.GetPort(), GetLastConnectedServerName() ) |
|
|| GTFGCClientSystem()->BIsIPRecentMatchServer( lastServer ) ) |
|
&& !cl_ask_blacklist_for_any_server.GetBool() ) |
|
{ |
|
// don't bother - this server is not blacklistable |
|
return; |
|
} |
|
|
|
if ( blackList.IsServerBlacklisted( GetLastConnectedServerIP(), GetLastConnectedServerPort(), GetLastConnectedServerName() ) ) |
|
{ |
|
// already marked as bad |
|
return; |
|
} |
|
|
|
// new potential blacklist - ask |
|
ShowConfirmOptOutDialog( "#TF_Serverlist_Ask_Blacklist_Title", "#TF_Serverlist_Ask_Blacklist_Text", |
|
"#TF_Serverlist_Ask_Yes", "#TF_Serverlist_Ask_No", |
|
"#TF_ServerList_Ask_Blacklist_Opt_Out", "cl_ask_blacklist_opt_out", |
|
OnAskBlacklistDialogButtonPressed, NULL ); |
|
} |
|
} |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
void ClientModeTFNormal::Update() |
|
{ |
|
BaseClass::Update(); |
|
|
|
TFModalStack()->Update(); |
|
|
|
NotificationQueue_Update(); |
|
|
|
// CHudVote *pHudVote = GET_HUDELEMENT( CHudVote ); |
|
// CTFHudMannVsMachineStatus *pMannVsMachineStatus = GET_HUDELEMENT( CTFHudMannVsMachineStatus ); |
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
|
|
// Update steam controller stuff if one is active |
|
if ( ::input->IsSteamControllerActive() ) |
|
{ |
|
// Walk through all the panels and HUD elements, see what kind of action set each one requests. |
|
bool bNeedMenu = false; |
|
bool bNeedHUD = false; |
|
bool bNeedSpectator = false; |
|
m_pViewport->ForEachPanel( [&] (IViewPortPanel* pPanel) { |
|
if ( pPanel && pPanel->IsVisible() ) |
|
{ |
|
auto actionset = pPanel->GetPreferredActionSet(); |
|
if ( actionset == GAME_ACTION_SET_MENUCONTROLS ) |
|
{ |
|
bNeedMenu = true; |
|
} |
|
else if ( actionset == GAME_ACTION_SET_IN_GAME_HUD ) |
|
{ |
|
bNeedHUD = true; |
|
} |
|
else if ( actionset == GAME_ACTION_SET_SPECTATOR ) |
|
{ |
|
bNeedSpectator = true; |
|
} |
|
} |
|
} ); |
|
|
|
gHUD.ForEachHudElement( [&]( CHudElement* pElement ) { |
|
if ( pElement && pElement->IsActive() ) |
|
{ |
|
auto actionset = pElement->GetPreferredActionSet(); |
|
if ( actionset == GAME_ACTION_SET_MENUCONTROLS ) |
|
{ |
|
bNeedMenu = true; |
|
} |
|
else if ( actionset == GAME_ACTION_SET_IN_GAME_HUD ) |
|
{ |
|
bNeedHUD = true; |
|
} |
|
else if ( actionset == GAME_ACTION_SET_SPECTATOR ) |
|
{ |
|
bNeedSpectator = true; |
|
} |
|
} |
|
} ); |
|
|
|
// Set the preferred action set. Requesting menu trumps hud, which trumps spectator, which trumps fps. |
|
if ( !engine->IsInGame() || !engine->IsConnected() || enginevgui->IsGameUIVisible() || bNeedMenu ) |
|
{ |
|
::input->SetPreferredGameActionSet( GAME_ACTION_SET_MENUCONTROLS ); |
|
} |
|
else if ( bNeedHUD ) |
|
{ |
|
::input->SetPreferredGameActionSet( GAME_ACTION_SET_IN_GAME_HUD ); |
|
} |
|
else if ( bNeedSpectator || (pLocalPlayer && pLocalPlayer->GetTeamNumber() == TEAM_SPECTATOR) ) |
|
{ |
|
::input->SetPreferredGameActionSet( GAME_ACTION_SET_SPECTATOR ); |
|
} |
|
else |
|
{ |
|
::input->SetPreferredGameActionSet( GAME_ACTION_SET_FPSCONTROLS ); |
|
} |
|
|
|
// Adjust look sensitivity down if the player is current using a zoomed-in weapon (typically sniper rifle). |
|
float look_sensitivity = 0.125f; |
|
if ( pLocalPlayer && pLocalPlayer->m_Shared.InCond( TF_COND_ZOOMED ) ) |
|
{ |
|
look_sensitivity = 0.035f; |
|
} |
|
|
|
// Set the flag for special action handling if we're taunting |
|
if ( pLocalPlayer && pLocalPlayer->m_Shared.InCond( TF_COND_TAUNTING ) ) |
|
{ |
|
::input->SetGameActionSetFlags( GAME_ACTION_SET_FLAGS_TAUNTING ); |
|
} |
|
else |
|
{ |
|
::input->SetGameActionSetFlags( GAME_ACTION_SET_FLAGS_NONE ); |
|
} |
|
|
|
sc_look_sensitivity_scale.SetValue( look_sensitivity ); |
|
} |
|
|
|
if ( !engine->IsInGame() ) |
|
{ |
|
// @note Tom Bui: we want this thing to always run, so we get animations at the main menu |
|
g_pClientMode->GetViewportAnimationController()->UpdateAnimations( gpGlobals->curtime ); |
|
} |
|
|
|
if ( !engine->IsConnected() ) |
|
{ |
|
if ( m_wasConnectedLastUpdate ) |
|
{ |
|
// just disconnected from a game |
|
m_wasConnectedLastUpdate = false; |
|
|
|
AskFavoriteOrBlacklist(); |
|
|
|
m_lastServerConnectTime = 0; |
|
} |
|
} |
|
else |
|
{ |
|
m_wasConnectedLastUpdate = true; |
|
} |
|
} |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
void ClientModeTFNormal::ComputeVguiResConditions( KeyValues *pkvConditions ) |
|
{ |
|
BaseClass::ComputeVguiResConditions( pkvConditions ); |
|
} |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsInfoPanelAllowed() |
|
{ |
|
if ( !BaseClass::IsInfoPanelAllowed() ) |
|
return false; |
|
|
|
return !m_bRestrictInfoPanel || !m_bInfoPanelShown; |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsHTMLInfoPanelAllowed() |
|
{ |
|
if ( !BaseClass::IsHTMLInfoPanelAllowed() ) |
|
return false; |
|
|
|
return !m_bRestrictInfoPanel; |
|
} |
|
|
|
|
|
//---------------------------------------------------------------------------- |
|
void ClientModeTFNormal::InfoPanelDisplayed() |
|
{ |
|
BaseClass::InfoPanelDisplayed(); |
|
|
|
m_bInfoPanelShown = true; |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsEngyBuildVisible() const |
|
{ |
|
return m_pMenuEngyBuild && m_pMenuEngyBuild->IsVisible(); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsEngyDestroyVisible() const |
|
{ |
|
return m_pMenuEngyDestroy && m_pMenuEngyDestroy->IsVisible(); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsEngyEurekaTeleportVisible() const |
|
{ |
|
return m_pEurekaTeleportMenu && m_pEurekaTeleportMenu->IsVisible(); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsSpyDisguiseVisible() const |
|
{ |
|
return m_pMenuSpyDisguise && m_pMenuSpyDisguise->IsVisible(); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsUpgradePanelVisible() const |
|
{ |
|
return m_pMenuUpgradePanel && m_pMenuUpgradePanel->IsVisible(); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
bool ClientModeTFNormal::IsTauntSelectPanelVisible() const |
|
{ |
|
return m_pMenuTauntSelection && m_pMenuTauntSelection->IsVisible(); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
void ClientModeTFNormal::PrintTextToChat( const char *pText, KeyValues *pKeyValues ) |
|
{ |
|
CBaseHudChat *pHUDChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat ); |
|
if ( pHUDChat ) |
|
{ |
|
wchar_t wszText[1024]=L""; |
|
g_pVGuiLocalize->ConstructString_safe( wszText, pText, pKeyValues ); |
|
char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wszText, szAnsi, sizeof(szAnsi) ); |
|
pHUDChat->Printf( CHAT_FILTER_NONE, "%s", szAnsi ); |
|
} |
|
} |
|
|
|
void ClientModeTFNormal::PrintTextToChatPlayer( int iPlayerIndex, const char *pText, KeyValues *pKeyValues ) |
|
{ |
|
CBaseHudChat *pHUDChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat ); |
|
if ( pHUDChat ) |
|
{ |
|
wchar_t wszText[1024]=L""; |
|
g_pVGuiLocalize->ConstructString_safe( wszText, pText, pKeyValues ); |
|
char szAnsi[1024]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( wszText, szAnsi, sizeof(szAnsi) ); |
|
pHUDChat->ChatPrintf( iPlayerIndex, CHAT_FILTER_NONE, "%s", szAnsi ); |
|
} |
|
} |
|
|
|
void ClientModeTFNormal::OnDemoRecordStart( char const* pDemoBaseName ) |
|
{ |
|
BaseClass::OnDemoRecordStart( pDemoBaseName ); |
|
} |
|
|
|
void ClientModeTFNormal::OnDemoRecordStop() |
|
{ |
|
IGameEvent *event = gameeventmanager->CreateEvent( "ds_stop" ); |
|
if ( event ) |
|
{ |
|
gameeventmanager->FireEventClientSide( event ); |
|
} |
|
|
|
BaseClass::OnDemoRecordStop(); |
|
} |
|
|
|
void __MsgFunc_PlayerBonusPoints( bf_read &msg ) |
|
{ |
|
int nPoints = (int) msg.ReadByte(); |
|
int iPlayerEntIndex = (int) msg.ReadByte(); |
|
int iSourceEntIndex = (int) msg.ReadByte(); |
|
|
|
IGameEvent *event = gameeventmanager->CreateEvent( "player_bonuspoints" ); |
|
if ( event ) |
|
{ |
|
event->SetInt( "points", nPoints ); |
|
event->SetInt( "player_entindex", iPlayerEntIndex ); |
|
event->SetInt( "source_entindex", iSourceEntIndex ); |
|
gameeventmanager->FireEventClientSide( event ); |
|
} |
|
} |
|
|
|
void __MsgFunc_PlayerGodRayEffect( bf_read &msg ) |
|
{ |
|
int iPlayerEntIndex = (int)msg.ReadByte(); |
|
|
|
CBasePlayer *player = UTIL_PlayerByIndex( iPlayerEntIndex ); |
|
if ( player ) |
|
{ |
|
player->ParticleProp()->Create( "god_rays", PATTACH_ABSORIGIN_FOLLOW ); |
|
} |
|
} |
|
|
|
void __MsgFunc_PlayerTeleportHomeEffect( bf_read &msg ) |
|
{ |
|
int iPlayerEntIndex = (int)msg.ReadByte(); |
|
|
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerEntIndex ); |
|
if ( pPlayer ) |
|
{ |
|
pPlayer->ParticleProp()->Create( "drg_wrenchmotron_teleport", PATTACH_ABSORIGIN ); |
|
} |
|
} |
|
|
|
void __MsgFunc_RDTeamPointsChanged( bf_read &msg ) |
|
{ |
|
int nPoints = (int)msg.ReadShort(); |
|
int nTeam = (int)msg.ReadByte(); |
|
int nMethod = (int)msg.ReadByte(); |
|
|
|
IGameEvent *event = gameeventmanager->CreateEvent( "rd_team_points_changed" ); |
|
if ( event ) |
|
{ |
|
event->SetInt( "points", nPoints ); |
|
event->SetInt( "team", nTeam ); |
|
event->SetInt( "method", nMethod ); |
|
gameeventmanager->FireEventClientSide( event ); |
|
} |
|
} |
|
|
|
void __MsgFunc_PlayerLoadoutUpdated( bf_read &msg ) |
|
{ |
|
int iPlayerEntIndex = (int)msg.ReadByte(); |
|
C_TFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerEntIndex ) ); |
|
if ( pPlayer ) |
|
{ |
|
CTFPlayerInventory *pInv = pPlayer->Inventory(); |
|
if ( pInv ) |
|
{ |
|
pInv->ClearClassLoadoutChangeTracking(); |
|
} |
|
} |
|
} |
|
|
|
void __MsgFunc_PlayerTauntSoundLoopStart( bf_read &msg ) |
|
{ |
|
int iPlayerEntIndex = (int)msg.ReadByte(); |
|
C_TFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerEntIndex ) ); |
|
if ( pPlayer ) |
|
{ |
|
char szTauntSoundLoopName[256]; |
|
msg.ReadString( szTauntSoundLoopName, sizeof(szTauntSoundLoopName) ); |
|
pPlayer->PlayTauntSoundLoop( szTauntSoundLoopName ); |
|
} |
|
} |
|
|
|
void __MsgFunc_PlayerTauntSoundLoopEnd( bf_read &msg ) |
|
{ |
|
int iPlayerEntIndex = (int)msg.ReadByte(); |
|
C_TFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerEntIndex ) ); |
|
if ( pPlayer ) |
|
{ |
|
pPlayer->StopTauntSoundLoop(); |
|
} |
|
} |
|
|
|
|
|
void __MsgFunc_ForcePlayerViewAngles( bf_read &msg ) |
|
{ |
|
// Read flag byte. Should be 1 right now. |
|
int iFlags = (int)msg.ReadByte(); |
|
NOTE_UNUSED( iFlags ); |
|
Assert( iFlags == 0x01 ); |
|
|
|
int iPlayerEntIndex = (int)msg.ReadByte(); |
|
C_TFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerEntIndex ) ); |
|
if ( pPlayer ) |
|
{ |
|
QAngle viewangles; |
|
msg.ReadBitAngles( viewangles ); |
|
|
|
// Set the magic angles here! |
|
pPlayer->SetLocalAngles( viewangles ); |
|
pPlayer->SetAbsAngles( viewangles ); |
|
pPlayer->SetTauntYaw( viewangles[YAW] ); |
|
pPlayer->m_Shared.SetVehicleMoveAngles( viewangles ); |
|
} |
|
} |
|
|
|
ConVar tf_halloween_bonus_ducks_cooldown( "tf_halloween_bonus_ducks_cooldown", "20", FCVAR_ARCHIVE ); |
|
void __MsgFunc_BonusDucks( bf_read &msg ) |
|
{ |
|
static float sflNextBonusDucks = 0.f; |
|
|
|
int iPlayerEntIndex = (int)msg.ReadByte(); |
|
int iIgnoreTimer = (int)msg.ReadByte(); |
|
|
|
if ( Plat_FloatTime() < sflNextBonusDucks && !iIgnoreTimer ) |
|
return; |
|
|
|
sflNextBonusDucks = Plat_FloatTime() + tf_halloween_bonus_ducks_cooldown.GetFloat(); |
|
|
|
|
|
C_TFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerEntIndex ) ); |
|
if ( pPlayer ) |
|
{ |
|
pPlayer->EmitSound( "sf14.Merasmus.DuckHunt.BonusDucks" ); |
|
} |
|
} |
|
|
|
void __MsgFunc_PlayerPickupWeapon( bf_read &msg ) |
|
{ |
|
IGameEvent *event = gameeventmanager->CreateEvent( "localplayer_pickup_weapon" ); |
|
gameeventmanager->FireEventClientSide( event ); |
|
} |
|
|
|
void __MsgFunc_AutoBalanceVolunteer( bf_read &msg ) |
|
{ |
|
KeyValuesAD pKeyValues( "data" ); |
|
pKeyValues->SetInt( "points", tf_autobalance_xp_bonus.GetInt() ); |
|
|
|
CAutobalanceVolunteerNotification *pNotification = new CAutobalanceVolunteerNotification(); |
|
pNotification->SetText( GTFGCClientSystem()->BConnectedToMatchServer( true ) ? "#TF_AutoBalanceVolunteerXPBonus" : "#TF_AutoBalanceVolunteer" ); |
|
pNotification->SetLifetime( tf_autobalance_query_lifetime.GetInt() ); |
|
pNotification->SetKeyValues( pKeyValues ); |
|
NotificationQueue_Add( pNotification ); |
|
|
|
if ( cl_notifications_show_ingame.GetInt() == 0 ) |
|
{ |
|
// player has turned off the in-game notifications so let's throw a chat |
|
// message to see if they will check their notifications in the main menu |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
CBaseHudChat *pHUDChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat ); |
|
if ( pPlayer && pHUDChat ) |
|
{ |
|
char szLocalized[100]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI(g_pVGuiLocalize->Find( "#TF_AutoBalanceVolunteer_ChatText" ), szLocalized, sizeof( szLocalized ) ); |
|
pHUDChat->ChatPrintf( pPlayer->entindex(), CHAT_FILTER_NONE, "%s ", szLocalized ); |
|
} |
|
} |
|
} |
|
|
|
void __MsgFunc_AutoBalanceVolunteer_Cancel( bf_read &msg ) |
|
{ |
|
NotificationQueue_Remove( &CAutobalanceVolunteerNotification::IsNotificationType ); |
|
} |
|
|
|
void __MsgFunc_QuestObjectiveCompleted( bf_read &msg ) |
|
{ |
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ ); |
|
|
|
itemid_t itemID = (itemid_t)msg.ReadLongLong(); |
|
uint16 nStandardPoints = msg.ReadWord(); |
|
uint16 nBonusPoints = msg.ReadWord(); |
|
uint32 nObjectiveDefIndex = msg.ReadWord(); |
|
|
|
QuestObjectiveManager()->UpdateFromServer( itemID, nStandardPoints, nBonusPoints ); |
|
QuestObjectiveManager()->EnsureTrackersForPlayer( steamapicontext->SteamUser()->GetSteamID() ); |
|
|
|
// Passing a -1 means this is a ninja update where we don't want the fanfare |
|
if ( nObjectiveDefIndex != (uint32)-1 ) |
|
{ |
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "quest_objective_completed" ); |
|
if ( pEvent ) |
|
{ |
|
pEvent->SetInt( "quest_item_id_low", itemID & 0xFFFFFFFF ); |
|
pEvent->SetInt( "quest_item_id_hi", itemID >> 32 ); |
|
pEvent->SetInt( "quest_objective_id", nObjectiveDefIndex ); |
|
gameeventmanager->FireEventClientSide( pEvent ); |
|
} |
|
} |
|
} |
|
|
|
float PlaySoundEntry( const char* pszSoundEntryName ) |
|
{ |
|
const char *pszSoundName = UTIL_GetRandomSoundFromEntry( pszSoundEntryName ); |
|
if ( pszSoundName && pszSoundName[0] ) |
|
{ |
|
vgui::surface()->PlaySound( pszSoundName ); |
|
return enginesound->GetSoundDuration( pszSoundName ); |
|
} |
|
|
|
return 0.f; |
|
} |
|
|
|
#ifdef _WIN32 |
|
|
|
#include "winlite.h" |
|
#pragma warning (push) |
|
#pragma warning(disable:4201) // nameless struct/union |
|
#include <mmsystem.h> |
|
#pragma warning (pop) |
|
#endif |
|
// |
|
void PlayOutOfGameSound( const char *pszSound ) |
|
{ |
|
#ifdef _WIN32 |
|
PlaySound( pszSound, NULL, SND_FILENAME | SND_ASYNC ); |
|
#endif |
|
}
|
|
|