mirror of
https://github.com/nillerusr/source-engine.git
synced 2025-01-13 00:28:18 +00:00
1521 lines
45 KiB
C++
1521 lines
45 KiB
C++
|
#include "cbase.h"
|
||
|
#include "clientmode_asw.h"
|
||
|
#include "vgui_int.h"
|
||
|
#include "hud.h"
|
||
|
#include <vgui/IInput.h>
|
||
|
#include <vgui/IPanel.h>
|
||
|
#include <vgui/ISurface.h>
|
||
|
#include <vgui_controls/AnimationController.h>
|
||
|
#include "iinput.h"
|
||
|
#include "ienginevgui.h"
|
||
|
#include "hud_macros.h"
|
||
|
#include "view_shared.h"
|
||
|
#include "hud_basechat.h"
|
||
|
#include "achievementmgr.h"
|
||
|
#include "fmtstr.h"
|
||
|
// asw
|
||
|
#include "asw_input.h"
|
||
|
#include "c_asw_marine.h"
|
||
|
#include "c_asw_marine_resource.h"
|
||
|
#include "c_asw_game_resource.h"
|
||
|
#include "c_asw_player.h"
|
||
|
#include "c_asw_campaign_save.h"
|
||
|
#include "asw_remote_turret_shared.h"
|
||
|
#include "asw_gamerules.h"
|
||
|
#include "asw_util_shared.h"
|
||
|
#include "asw_campaign_info.h"
|
||
|
#include "techmarinefailpanel.h"
|
||
|
#include "FadeInPanel.h"
|
||
|
#include <vgui/IInput.h>
|
||
|
#include "ivieweffects.h"
|
||
|
#include "shake.h"
|
||
|
#include <vgui/ILocalize.h>
|
||
|
#include "c_playerresource.h"
|
||
|
#include "asw_medal_store.h"
|
||
|
#include "TechMarineFailPanel.h"
|
||
|
#include "vgui\asw_vgui_info_message.h"
|
||
|
//#include "keydefs.h"
|
||
|
#include "soundenvelope.h"
|
||
|
#include "ivmodemanager.h"
|
||
|
#include "voice_status.h"
|
||
|
#include "PanelMetaClassMgr.h"
|
||
|
#include "asw_loading_panel.h"
|
||
|
#include "asw_logo_panel.h"
|
||
|
#include "c_user_message_register.h"
|
||
|
#include "inetchannelinfo.h"
|
||
|
#include "engine/IVDebugOverlay.h"
|
||
|
#include "debugoverlay_shared.h"
|
||
|
#include "viewpostprocess.h"
|
||
|
#include "shaderapi/ishaderapi.h"
|
||
|
#include "tier2/renderutils.h"
|
||
|
#include "materialsystem/imaterial.h"
|
||
|
#include "materialsystem/imaterialvar.h"
|
||
|
#include "nb_header_footer.h"
|
||
|
#include "asw_briefing.h"
|
||
|
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
|
||
|
#define FAILED_CC_LOOKUP_FILENAME "materials/correction/cc_failed.raw"
|
||
|
#define FAILED_CC_FADE_TIME 1.0f
|
||
|
#define INFESTED_CC_LOOKUP_FILENAME "scripts/colorcorrection/infested_green.raw"
|
||
|
#define INFESTED_CC_FADE_TIME 0.5f
|
||
|
|
||
|
extern bool IsInCommentaryMode( void );
|
||
|
|
||
|
extern ConVar mat_object_motion_blur_enable;
|
||
|
|
||
|
// asw
|
||
|
ConVar asw_reconnect_after_outro( "asw_reconnect_after_outro", "0", 0, "If set, client will reconnect to server after outro" );
|
||
|
ConVar asw_hear_from_marine( "asw_hear_from_marine", "0", FCVAR_NONE, "Audio hearing position is at current marine's ears" );
|
||
|
ConVar asw_hear_pos_debug("asw_hear_pos_debug", "0", FCVAR_NONE, "Shows audio hearing position" );
|
||
|
ConVar asw_hear_height("asw_hear_height", "0", FCVAR_NONE, "If set, hearing audio position is this many units above the marine. If number is negative, then hear position is number of units below the camera." );
|
||
|
ConVar asw_hear_fixed("asw_hear_fixed", "0", FCVAR_NONE, "If set, hearing audio position is locked in place. Use asw_set_hear_pos to set the fixed position to the current audio location." );
|
||
|
|
||
|
Vector g_asw_vec_fixed_cam(-276.03076, -530.74951, -196.65625);
|
||
|
QAngle g_asw_ang_fixed_cam(42.610226, 90.289375, 0);
|
||
|
extern ConVar asw_vehicle_cam_height;
|
||
|
extern ConVar asw_vehicle_cam_pitch;
|
||
|
extern ConVar asw_vehicle_cam_dist;
|
||
|
|
||
|
Vector g_asw_vec_fixed_hear_pos = vec3_origin;
|
||
|
Vector g_asw_vec_last_hear_pos = vec3_origin;
|
||
|
|
||
|
ConVar default_fov( "default_fov", "75", FCVAR_CHEAT );
|
||
|
ConVar fov_desired( "fov_desired", "75", FCVAR_USERINFO, "Sets the base field-of-view.", true, 1.0, true, 75.0 );
|
||
|
|
||
|
vgui::HScheme g_hVGuiCombineScheme = 0;
|
||
|
|
||
|
vgui::DHANDLE<CASW_Logo_Panel> g_hLogoPanel;
|
||
|
|
||
|
static IClientMode *g_pClientMode[ MAX_SPLITSCREEN_PLAYERS ];
|
||
|
IClientMode *GetClientMode()
|
||
|
{
|
||
|
Assert( engine->IsLocalPlayerResolvable() );
|
||
|
return g_pClientMode[ engine->GetActiveSplitScreenPlayerSlot() ];
|
||
|
}
|
||
|
|
||
|
// Voice data
|
||
|
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( "voicerecord_toggle on\n" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
engine->ClientCmd( "voicerecord_toggle off\n" );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ConVar voice_vox( "voice_vox", "0", FCVAR_ARCHIVE, "Voice chat uses a vox-style always on", false, 0, true, 1, VoxCallback );
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
class CVoxManager : public CAutoGameSystem
|
||
|
{
|
||
|
public:
|
||
|
CVoxManager() : CAutoGameSystem( "VoxManager" ) { }
|
||
|
|
||
|
virtual void LevelInitPostEntity( void )
|
||
|
{
|
||
|
if ( voice_vox.GetBool() /*&& voice_modenable.GetBool()*/ )
|
||
|
{
|
||
|
engine->ClientCmd( "voicerecord_toggle on\n" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
virtual void LevelShutdownPreEntity( void )
|
||
|
{
|
||
|
if ( voice_vox.GetBool() )
|
||
|
{
|
||
|
engine->ClientCmd( "voicerecord_toggle off\n" );
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
static CVoxManager s_VoxManager;
|
||
|
|
||
|
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
// CASWModeManager.
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
|
||
|
class CASWModeManager : 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 CASWModeManager g_ModeManager;
|
||
|
IVModeManager *modemanager = ( IVModeManager * )&g_ModeManager;
|
||
|
|
||
|
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
// CASWModeManager implementation.
|
||
|
// --------------------------------------------------------------------------------- //
|
||
|
|
||
|
#define SCREEN_FILE "scripts/vgui_screens.txt"
|
||
|
|
||
|
void CASWModeManager::Init()
|
||
|
{
|
||
|
for( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; ++i )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( i );
|
||
|
g_pClientMode[ i ] = GetClientModeNormal();
|
||
|
}
|
||
|
|
||
|
PanelMetaClassMgr()->LoadMetaClassDefinitionFile( SCREEN_FILE );
|
||
|
|
||
|
GetClientVoiceMgr()->SetHeadLabelOffset( 40 );
|
||
|
}
|
||
|
|
||
|
void CASWModeManager::LevelInit( const char *newmap )
|
||
|
{
|
||
|
for( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; ++i )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( i );
|
||
|
GetClientMode()->LevelInit( newmap );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CASWModeManager::LevelShutdown( void )
|
||
|
{
|
||
|
for( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; ++i )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( i );
|
||
|
GetClientMode()->LevelShutdown();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ClientModeASW g_ClientModeNormal[ MAX_SPLITSCREEN_PLAYERS ];
|
||
|
|
||
|
IClientMode *GetClientModeNormal()
|
||
|
{
|
||
|
Assert( engine->IsLocalPlayerResolvable() );
|
||
|
return &g_ClientModeNormal[ engine->GetActiveSplitScreenPlayerSlot() ];
|
||
|
}
|
||
|
|
||
|
ClientModeASW* GetClientModeASW()
|
||
|
{
|
||
|
Assert( engine->IsLocalPlayerResolvable() );
|
||
|
return &g_ClientModeNormal[ engine->GetActiveSplitScreenPlayerSlot() ];
|
||
|
}
|
||
|
|
||
|
// these vgui panels will be closed at various times (e.g. when the level ends/starts)
|
||
|
static char const *s_CloseWindowNames[]={
|
||
|
"g_BriefingFrame",
|
||
|
"g_PlayerListFrame",
|
||
|
"m_CampaignFrame",
|
||
|
"ComputerFrame",
|
||
|
"ComputerContainer",
|
||
|
"m_MissionCompleteFrame",
|
||
|
"Credits",
|
||
|
"CainMail",
|
||
|
"TechFail",
|
||
|
"QueenHealthPanel",
|
||
|
"ForceReady",
|
||
|
"ReviveDialog",
|
||
|
"SkillToSpendDialog",
|
||
|
"InfoMessageWindow",
|
||
|
"SkipIntro",
|
||
|
"InGameBriefingContainer",
|
||
|
"HoldoutWaveAnnouncePanel",
|
||
|
"HoldoutWaveEndPanel",
|
||
|
"ResupplyFrame",
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: this is the viewport that contains all the hud elements
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CHudViewport : public CBaseViewport
|
||
|
{
|
||
|
private:
|
||
|
DECLARE_CLASS_SIMPLE( CHudViewport, CBaseViewport );
|
||
|
|
||
|
protected:
|
||
|
virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
GetHud().InitColors( pScheme );
|
||
|
|
||
|
SetPaintBackgroundEnabled( false );
|
||
|
}
|
||
|
|
||
|
virtual void CreateDefaultPanels( void ) { /* don't create any panels yet*/ };
|
||
|
};
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
// 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" );
|
||
|
|
||
|
class FullscreenASWViewport : public CHudViewport
|
||
|
{
|
||
|
private:
|
||
|
DECLARE_CLASS_SIMPLE( FullscreenASWViewport, CHudViewport );
|
||
|
|
||
|
private:
|
||
|
virtual void InitViewportSingletons( void )
|
||
|
{
|
||
|
SetAsFullscreenViewportInterface();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class ClientModeASWFullscreen : public ClientModeASW
|
||
|
{
|
||
|
DECLARE_CLASS_SIMPLE( ClientModeASWFullscreen, ClientModeASW );
|
||
|
public:
|
||
|
virtual void InitViewport()
|
||
|
{
|
||
|
// Skip over BaseClass!!!
|
||
|
BaseClass::BaseClass::InitViewport();
|
||
|
m_pViewport = new FullscreenASWViewport();
|
||
|
m_pViewport->Start( gameuifuncs, gameeventmanager );
|
||
|
}
|
||
|
virtual void Init()
|
||
|
{
|
||
|
CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory();
|
||
|
if ( gameUIFactory )
|
||
|
{
|
||
|
IGameUI *pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL );
|
||
|
if ( NULL != pGameUI )
|
||
|
{
|
||
|
// insert stats summary panel as the loading background dialog
|
||
|
CASW_Loading_Panel *pPanel = GASWLoadingPanel();
|
||
|
pPanel->InvalidateLayout( false, true );
|
||
|
pPanel->SetVisible( false );
|
||
|
pPanel->MakePopup( false );
|
||
|
pGameUI->SetLoadingBackgroundDialog( pPanel->GetVPanel() );
|
||
|
|
||
|
// add ASI logo to main menu
|
||
|
CASW_Logo_Panel *pLogo = new CASW_Logo_Panel( NULL, "ASILogo" );
|
||
|
vgui::VPANEL GameUIRoot = enginevgui->GetPanel( PANEL_GAMEUIDLL );
|
||
|
pLogo->SetParent( GameUIRoot );
|
||
|
g_hLogoPanel = pLogo;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//CASW_VGUI_Debug_Panel *pDebugPanel = new CASW_VGUI_Debug_Panel( GetViewport(), "ASW Debug Panel" );
|
||
|
//g_hDebugPanel = pDebugPanel;
|
||
|
|
||
|
// Skip over BaseClass!!!
|
||
|
BaseClass::BaseClass::Init();
|
||
|
|
||
|
// Load up the combine control panel scheme
|
||
|
if ( !g_hVGuiCombineScheme )
|
||
|
{
|
||
|
g_hVGuiCombineScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), IsXbox() ? "resource/ClientScheme.res" : "resource/CombinePanelScheme.res", "CombineScheme" );
|
||
|
if (!g_hVGuiCombineScheme)
|
||
|
{
|
||
|
Warning( "Couldn't load combine panel scheme!\n" );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void Shutdown()
|
||
|
{
|
||
|
DestroyASWLoadingPanel();
|
||
|
if (g_hLogoPanel.Get())
|
||
|
{
|
||
|
delete g_hLogoPanel.Get();
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
static ClientModeASWFullscreen g_FullscreenClientMode;
|
||
|
IClientMode *GetFullscreenClientMode( void )
|
||
|
{
|
||
|
return &g_FullscreenClientMode;
|
||
|
}
|
||
|
|
||
|
|
||
|
// gives the current marine some 'poison blur' (causes motion blur over his screen for the duration, making it harder to see)
|
||
|
static void __MsgFunc_ASWBlur( bf_read &msg )
|
||
|
{
|
||
|
float duration = msg.ReadShort() * 0.1f;
|
||
|
|
||
|
C_ASW_Player *local = C_ASW_Player::GetLocalASWPlayer();
|
||
|
if ( local )
|
||
|
{
|
||
|
C_ASW_Marine *marine = local->GetMarine();
|
||
|
if (marine)
|
||
|
{
|
||
|
marine->SetPoisoned(duration);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// we get this message when players proceed after completing the last mission in a campaign
|
||
|
static void __MsgFunc_ASWCampaignCompleted( bf_read &msg )
|
||
|
{
|
||
|
CASW_Player *pPlayer = CASW_Player::GetLocalASWPlayer();
|
||
|
// let our clientside medal store increase the number of completed campaigns by 1
|
||
|
if (pPlayer && ASWGameResource())
|
||
|
{
|
||
|
// count how many marines we have
|
||
|
C_ASW_Game_Resource *pGameResource = ASWGameResource();
|
||
|
int iMarines = 0;
|
||
|
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
|
||
|
{
|
||
|
C_ASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
|
||
|
if (pMR && pMR->GetCommanderIndex() == pPlayer->entindex())
|
||
|
{
|
||
|
iMarines++;
|
||
|
}
|
||
|
}
|
||
|
#ifdef USE_MEDAL_STORE
|
||
|
if (iMarines > 0 && GetMedalStore() && ASWGameRules() && !ASWGameRules()->m_bCheated
|
||
|
&& !engine->IsPlayingDemo())
|
||
|
GetMedalStore()->OnIncreaseCounts(0,1,0, (gpGlobals->maxClients <= 1));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef OUTRO_MAP
|
||
|
// check for changing to the outro map
|
||
|
//int iDedicated =
|
||
|
msg.ReadByte();
|
||
|
int iHostIndex = msg.ReadByte();
|
||
|
|
||
|
Msg("[C] __MsgFunc_ASWCampaignCompleted. playerindex=%d hostindex =%d offline=%d\n",
|
||
|
pPlayer ? pPlayer->entindex() : -1, iHostIndex, (gpGlobals->maxClients <= 1));
|
||
|
if (pPlayer && pPlayer->entindex() == iHostIndex)
|
||
|
{
|
||
|
// don't launch the outro map clientside if we're a server
|
||
|
Msg("[C] We're the host, so not doing client map outro\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// if we're a client, flag us for a reconnect once the outro is done
|
||
|
ConVar *var = (ConVar *)cvar->FindVar( "asw_reconnect_after_outro" );
|
||
|
if (var)
|
||
|
{
|
||
|
engine->ClientCmd("asw_save_server"); /// save the server we're on, so we can reconnect to it later
|
||
|
var->SetValue(1);
|
||
|
}
|
||
|
Msg("[C] Doing client map outro\n");
|
||
|
// find the outro map name
|
||
|
CASW_Campaign_Info *pCampaign = ASWGameRules() ? ASWGameRules()->GetCampaignInfo() : NULL;
|
||
|
Msg("[C] Campaign debug info:\n");
|
||
|
if (pCampaign)
|
||
|
pCampaign->DebugInfo();
|
||
|
const char *pszOutro = "outro_jacob"; // the default
|
||
|
if (pCampaign)
|
||
|
{
|
||
|
const char *pszCustomOutro = STRING(pCampaign->m_OutroMap);
|
||
|
if (pszCustomOutro && ( !Q_strnicmp( pszCustomOutro, "outro", 5 ) ))
|
||
|
{
|
||
|
pszOutro = pszCustomOutro;
|
||
|
Msg("[C] Using custom outro: %s\n", pszCustomOutro);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Msg("[C] No valid custom outro defined in campaign info, using default\n");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Msg("[C] Using default outro as we can't find the campaign info\n");
|
||
|
}
|
||
|
char buffer[256];
|
||
|
Q_snprintf(buffer, sizeof(buffer), "disconnect\nwait\nwait\nmaxplayers 1\nmap %s", pszOutro);
|
||
|
Msg("[C] Sending client outro command: %s\n", buffer);
|
||
|
engine->ClientCmd(buffer);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// we get this message after watching the outro
|
||
|
static void __MsgFunc_ASWReconnectAfterOutro( bf_read &msg )
|
||
|
{
|
||
|
if (ASWGameRules() && ASWGameRules()->IsOutroMap())
|
||
|
{
|
||
|
// clear the reconnect flag
|
||
|
ConVar *var = (ConVar *)cvar->FindVar( "asw_reconnect_after_outro" );
|
||
|
Msg("Client checking for reconnect\n");
|
||
|
if (var && var->GetInt() != 0)
|
||
|
{
|
||
|
var->SetValue(0);
|
||
|
|
||
|
Msg(" sending asw_retry_saved_server cmd\n");
|
||
|
// reconnect to the previous server
|
||
|
engine->ClientCmd("asw_retry_saved_server");
|
||
|
}
|
||
|
else // if we're not reconnecting to a server after watching the outro, go back to the main menu
|
||
|
{
|
||
|
if (gpGlobals->maxClients <= 1)
|
||
|
{
|
||
|
engine->ClientCmd("disconnect\nwait\nwait\nmap_background SwarmSelectionScreen");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// we get this message when the players have lost their only tech marine and are unable to complete the mission
|
||
|
static void __MsgFunc_ASWTechFailure( bf_read &msg )
|
||
|
{
|
||
|
GetClientModeASW()->m_bTechFailure = true;
|
||
|
//TechMarineFailPanel::ShowTechFailPanel();
|
||
|
}
|
||
|
|
||
|
ClientModeASW::ClientModeASW()
|
||
|
{
|
||
|
m_bTechFailure = false;
|
||
|
m_bLaunchedBriefing = false;
|
||
|
m_bLaunchedDebrief = false;
|
||
|
m_bLaunchedCampaignMap = false;
|
||
|
m_bLaunchedOutro = false;
|
||
|
m_hLastInfoMessage = NULL;
|
||
|
m_pBriefingMusic = NULL;
|
||
|
m_pGameUI = NULL;
|
||
|
m_bSpectator = false;
|
||
|
m_fNextProgressUpdate = 0;
|
||
|
m_aAwardedExperience.Purge();
|
||
|
|
||
|
m_pCurrentPostProcessController = NULL;
|
||
|
m_PostProcessLerpTimer.Invalidate();
|
||
|
m_pCurrentColorCorrection = NULL;
|
||
|
}
|
||
|
|
||
|
ClientModeASW::~ClientModeASW()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::Init()
|
||
|
{
|
||
|
BaseClass::Init();
|
||
|
|
||
|
gameeventmanager->AddListener( this, "asw_mission_restart", false );
|
||
|
gameeventmanager->AddListener( this, "game_newmap", false );
|
||
|
HOOK_MESSAGE( ASWBlur );
|
||
|
HOOK_MESSAGE( ASWCampaignCompleted );
|
||
|
HOOK_MESSAGE( ASWReconnectAfterOutro );
|
||
|
HOOK_MESSAGE( ASWTechFailure );
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::Shutdown()
|
||
|
{
|
||
|
if ( ASWBackgroundMovie() )
|
||
|
{
|
||
|
ASWBackgroundMovie()->ClearCurrentMovie();
|
||
|
}
|
||
|
DestroyASWLoadingPanel();
|
||
|
if (g_hLogoPanel.Get())
|
||
|
{
|
||
|
delete g_hLogoPanel.Get();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::InitViewport()
|
||
|
{
|
||
|
m_pViewport = new CHudViewport();
|
||
|
m_pViewport->Start( gameuifuncs, gameeventmanager );
|
||
|
}
|
||
|
|
||
|
// asw - let us drive the fixed camera position around
|
||
|
static bool s_bFixedInputActive = false;
|
||
|
static int s_nOldCursor[2] = {0, 0};
|
||
|
void ASW_Handle_Fixed_Input( bool active )
|
||
|
{
|
||
|
if ( s_bFixedInputActive ^ active )
|
||
|
{
|
||
|
if ( s_bFixedInputActive && !active )
|
||
|
{
|
||
|
// Restore mouse
|
||
|
vgui::input()->SetCursorPos( s_nOldCursor[0], s_nOldCursor[1] );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// todO: set the initial fixed vectors here..
|
||
|
vgui::input()->GetCursorPos( s_nOldCursor[0], s_nOldCursor[1] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( active )
|
||
|
{
|
||
|
float f = 0.0f;
|
||
|
float s = 0.0f;
|
||
|
float u = 0.0f;
|
||
|
|
||
|
bool shiftdown = vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT );
|
||
|
float movespeed = shiftdown ? 40.0f : 400.0f;
|
||
|
|
||
|
if ( vgui::input()->IsKeyDown( KEY_W ) )
|
||
|
{
|
||
|
f = movespeed * gpGlobals->frametime;
|
||
|
}
|
||
|
if ( vgui::input()->IsKeyDown( KEY_S ) )
|
||
|
{
|
||
|
f = -movespeed * gpGlobals->frametime;
|
||
|
}
|
||
|
if ( vgui::input()->IsKeyDown( KEY_A ) )
|
||
|
{
|
||
|
s = -movespeed * gpGlobals->frametime;
|
||
|
}
|
||
|
if ( vgui::input()->IsKeyDown( KEY_D ) )
|
||
|
{
|
||
|
s = movespeed * gpGlobals->frametime;
|
||
|
}
|
||
|
if ( vgui::input()->IsKeyDown( KEY_X ) )
|
||
|
{
|
||
|
u = movespeed * gpGlobals->frametime;
|
||
|
}
|
||
|
if ( vgui::input()->IsKeyDown( KEY_Z ) )
|
||
|
{
|
||
|
u = -movespeed * gpGlobals->frametime;
|
||
|
}
|
||
|
|
||
|
int mx, my;
|
||
|
int dx, dy;
|
||
|
|
||
|
vgui::input()->GetCursorPos( mx, my );
|
||
|
|
||
|
dx = mx - s_nOldCursor[0];
|
||
|
dy = my - s_nOldCursor[1];
|
||
|
|
||
|
vgui::input()->SetCursorPos( s_nOldCursor[0], s_nOldCursor[1] );
|
||
|
|
||
|
// Convert to pitch/yaw
|
||
|
|
||
|
float pitch = (float)dy * 0.22f;
|
||
|
float yaw = -(float)dx * 0.22;
|
||
|
|
||
|
// Apply mouse
|
||
|
g_asw_ang_fixed_cam.x += pitch;
|
||
|
|
||
|
g_asw_ang_fixed_cam.x = clamp( g_asw_ang_fixed_cam.x, -89.0f, 89.0f );
|
||
|
|
||
|
g_asw_ang_fixed_cam.y += yaw;
|
||
|
if ( g_asw_ang_fixed_cam.y > 180.0f )
|
||
|
{
|
||
|
g_asw_ang_fixed_cam.y -= 360.0f;
|
||
|
}
|
||
|
else if ( g_asw_ang_fixed_cam.y < -180.0f )
|
||
|
{
|
||
|
g_asw_ang_fixed_cam.y += 360.0f;
|
||
|
}
|
||
|
|
||
|
// Now apply forward, side, up
|
||
|
|
||
|
Vector fwd, side, up;
|
||
|
|
||
|
AngleVectors( g_asw_ang_fixed_cam, &fwd, &side, &up );
|
||
|
|
||
|
g_asw_vec_fixed_cam += fwd * f;
|
||
|
g_asw_vec_fixed_cam += side * s;
|
||
|
g_asw_vec_fixed_cam += up * u;
|
||
|
|
||
|
static Vector s_vecServerInformPos = Vector(0,0,0);
|
||
|
if ((s_vecServerInformPos - g_asw_vec_fixed_cam).Length() > 100.0f)
|
||
|
{
|
||
|
s_vecServerInformPos = g_asw_vec_fixed_cam;
|
||
|
char buffer[128];
|
||
|
Q_snprintf(buffer, sizeof(buffer), "cl_freecam %d %d %d", (int) g_asw_vec_fixed_cam.x, (int) g_asw_vec_fixed_cam.y, (int) g_asw_vec_fixed_cam.z);
|
||
|
engine->ClientCmd(buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s_bFixedInputActive = active;
|
||
|
}
|
||
|
|
||
|
ConVar asw_camera_shake( "asw_camera_shake", "1", FCVAR_NONE, "Enable camera shakes" );
|
||
|
ConVar asw_fix_cam( "asw_fix_cam", "-1", FCVAR_CHEAT, "Set to 1 to fix the camera in place." );
|
||
|
|
||
|
void ClientModeASW::OverrideView( CViewSetup *pSetup )
|
||
|
{
|
||
|
QAngle camAngles;
|
||
|
|
||
|
// Let the player override the view.
|
||
|
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||
|
if(!pPlayer)
|
||
|
return;
|
||
|
|
||
|
pPlayer->OverrideView( pSetup );
|
||
|
|
||
|
if( ::input->CAM_IsThirdPerson() )
|
||
|
{
|
||
|
int omx, omy;
|
||
|
ASWInput()->ASW_GetCameraLocation(pPlayer, pSetup->origin, pSetup->angles, omx, omy, true);
|
||
|
#ifdef CLIENT_DLL
|
||
|
if ( asw_camera_shake.GetBool() )
|
||
|
{
|
||
|
GetViewEffects()->ApplyShake( pSetup->origin, pSetup->angles, 1.0 );
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
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;
|
||
|
}
|
||
|
else // asw: make sure we're not tilted
|
||
|
{
|
||
|
pSetup->angles[ROLL] = 0;
|
||
|
}
|
||
|
|
||
|
if ( asw_fix_cam.GetInt() == 1 )
|
||
|
{
|
||
|
g_asw_vec_fixed_cam = pSetup->origin;
|
||
|
g_asw_ang_fixed_cam = pSetup->angles;
|
||
|
asw_fix_cam.SetValue( 0 );
|
||
|
}
|
||
|
else if ( asw_fix_cam.GetInt() == 0 )
|
||
|
{
|
||
|
pSetup->origin = g_asw_vec_fixed_cam;
|
||
|
pSetup->angles = g_asw_ang_fixed_cam;
|
||
|
|
||
|
ASW_Handle_Fixed_Input( vgui::input()->IsKeyDown( KEY_LSHIFT ) && vgui::input()->IsMouseDown( MOUSE_LEFT ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class MapDescription_t
|
||
|
{
|
||
|
public:
|
||
|
MapDescription_t( const char *szMapName, unsigned int nFileSize, unsigned int nEntityStringLength ) :
|
||
|
m_szMapName( szMapName ), m_nFileSize( nFileSize ), m_nEntityStringLength( nEntityStringLength )
|
||
|
{
|
||
|
}
|
||
|
const char *m_szMapName;
|
||
|
unsigned int m_nFileSize;
|
||
|
unsigned int m_nEntityStringLength;
|
||
|
};
|
||
|
|
||
|
static MapDescription_t s_OfficialMaps[]=
|
||
|
{
|
||
|
MapDescription_t( "maps/asi-jac1-landingbay_01.bsp", 45793676, 412634 ),
|
||
|
MapDescription_t( "maps/asi-jac1-landingbay_02.bsp", 25773204, 324141 ),
|
||
|
MapDescription_t( "maps/asi-jac2-deima.bsp", 44665212, 345367 ),
|
||
|
MapDescription_t( "maps/asi-jac3-rydberg.bsp", 27302616, 359228 ),
|
||
|
MapDescription_t( "maps/asi-jac4-residential.bsp", 31244468, 455840 ),
|
||
|
MapDescription_t( "maps/asi-jac6-sewerjunction.bsp", 18986884, 287554 ),
|
||
|
MapDescription_t( "maps/asi-jac7-timorstation.bsp", 37830468, 506193 ),
|
||
|
};
|
||
|
|
||
|
void ClientModeASW::LevelInit( const char *newmap )
|
||
|
{
|
||
|
// reset ambient light
|
||
|
static ConVarRef mat_ambient_light_r( "mat_ambient_light_r" );
|
||
|
static ConVarRef mat_ambient_light_g( "mat_ambient_light_g" );
|
||
|
static ConVarRef mat_ambient_light_b( "mat_ambient_light_b" );
|
||
|
|
||
|
if ( mat_ambient_light_r.IsValid() )
|
||
|
{
|
||
|
mat_ambient_light_r.SetValue( "0" );
|
||
|
}
|
||
|
|
||
|
if ( mat_ambient_light_g.IsValid() )
|
||
|
{
|
||
|
mat_ambient_light_g.SetValue( "0" );
|
||
|
}
|
||
|
|
||
|
if ( mat_ambient_light_b.IsValid() )
|
||
|
{
|
||
|
mat_ambient_light_b.SetValue( "0" );
|
||
|
}
|
||
|
|
||
|
// Load color correction lookup
|
||
|
m_CCFailedHandle = g_pColorCorrectionMgr->AddColorCorrection( FAILED_CC_LOOKUP_FILENAME );
|
||
|
if ( m_CCFailedHandle != INVALID_CLIENT_CCHANDLE )
|
||
|
{
|
||
|
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCFailedHandle, 0.0f );
|
||
|
}
|
||
|
m_fFailedCCWeight = 0.0f;
|
||
|
m_bTechFailure = false;
|
||
|
|
||
|
m_CCInfestedHandle = g_pColorCorrectionMgr->AddColorCorrection( INFESTED_CC_LOOKUP_FILENAME );
|
||
|
if ( m_CCInfestedHandle != INVALID_CLIENT_CCHANDLE )
|
||
|
{
|
||
|
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCInfestedHandle, 0.0f );
|
||
|
}
|
||
|
m_fInfestedCCWeight = 0.0f;
|
||
|
|
||
|
m_aAchievementsEarned.Purge();
|
||
|
|
||
|
BaseClass::LevelInit(newmap);
|
||
|
|
||
|
m_aAwardedExperience.Purge();
|
||
|
|
||
|
// asw make sure the camera is pointing right
|
||
|
if (engine->IsLevelMainMenuBackground())
|
||
|
{
|
||
|
::input->CAM_ToFirstPerson();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::input->CAM_ToThirdPerson();
|
||
|
// create a black panel to fade in
|
||
|
FadeInPanel *pFadeIn = dynamic_cast<FadeInPanel*>(GetViewport()->FindChildByName("FadeIn", true));
|
||
|
if (pFadeIn)
|
||
|
{
|
||
|
//Msg("Already have a fade in panel! (m_bSlowRemove=%d m_fIngameTime=%f cur=%f)\n", pFadeIn->m_bSlowRemove, pFadeIn->m_fIngameTime, gpGlobals->curtime);
|
||
|
if (UTIL_ASW_MissionHasBriefing(newmap) || (!Q_stricmp(newmap, "tutorial")))
|
||
|
{
|
||
|
pFadeIn->m_fIngameTime = 0;
|
||
|
pFadeIn->m_bSlowRemove = false;
|
||
|
pFadeIn->SetAlpha(255);
|
||
|
pFadeIn->MoveToFront();
|
||
|
vgui::GetAnimationController()->RunAnimationCommand(pFadeIn, "alpha", 255, 0.0f, 0.1f, vgui::AnimationController::INTERPOLATOR_LINEAR);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pFadeIn->SetVisible(false);
|
||
|
pFadeIn->MarkForDeletion();
|
||
|
}
|
||
|
}
|
||
|
if (!pFadeIn && UTIL_ASW_MissionHasBriefing(newmap)) // don't create one of these if there's already one around, or in a map that doesn't have briefing
|
||
|
{
|
||
|
//Msg("%f: creating fadein panel\n", gpGlobals->curtime);
|
||
|
new FadeInPanel(m_pViewport, "FadeIn");
|
||
|
}
|
||
|
else if (!pFadeIn && !Q_stricmp(newmap, "tutorial")) // give the tutorial a nice fade in
|
||
|
{
|
||
|
//Msg("tutorial creating fadein panel\n");
|
||
|
FadeInPanel *pTutorialFade = new FadeInPanel(m_pViewport, "FadeIn");
|
||
|
if (pTutorialFade)
|
||
|
pTutorialFade->AllowFastRemove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// asw: make sure no windows are left open from before
|
||
|
ASW_CloseAllWindows();
|
||
|
m_hMissionCompleteFrame = NULL;
|
||
|
m_hCampaignFrame = NULL;
|
||
|
m_hOutroFrame = NULL;
|
||
|
m_hInGameBriefingFrame = NULL;
|
||
|
m_bLaunchedBriefing = false;
|
||
|
m_bLaunchedDebrief = false;
|
||
|
m_bLaunchedCampaignMap = false;
|
||
|
m_bLaunchedOutro = false;
|
||
|
m_hLastInfoMessage = NULL;
|
||
|
|
||
|
// update keybinds shown on the HUD
|
||
|
engine->ClientCmd("asw_update_binds");
|
||
|
|
||
|
// clear any DSP effects
|
||
|
CLocalPlayerFilter filter;
|
||
|
enginesound->SetRoomType( filter, 0 );
|
||
|
enginesound->SetPlayerDSP( filter, 0, true );
|
||
|
|
||
|
if ( Briefing() )
|
||
|
{
|
||
|
Briefing()->ResetLastChatterTime();
|
||
|
}
|
||
|
|
||
|
const char *szMapName = engine->GetLevelName();
|
||
|
unsigned int nFileSize = g_pFullFileSystem->Size( szMapName, "GAME" );
|
||
|
|
||
|
unsigned int nEntityLen = Q_strlen( engine->GetMapEntitiesString() );
|
||
|
|
||
|
m_bOfficialMap = false;
|
||
|
for ( int i = 0; i < NELEMS( s_OfficialMaps ); i++ )
|
||
|
{
|
||
|
if ( !Q_stricmp( szMapName, s_OfficialMaps[i].m_szMapName ) )
|
||
|
{
|
||
|
m_bOfficialMap = ( ( s_OfficialMaps[i].m_nFileSize == nFileSize ) && ( s_OfficialMaps[i].m_nEntityStringLength == nEntityLen ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
Msg( "map %s file size is %d\n", szMapName, nFileSize );
|
||
|
Msg( " entity string is %d chars long\n", nEntityLen );
|
||
|
Msg( "Official map = %d\n", m_bOfficialMap );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::LevelShutdown( void )
|
||
|
{
|
||
|
BaseClass::LevelShutdown();
|
||
|
|
||
|
// asw:shutdown all vgui windows
|
||
|
ASW_CloseAllWindows();
|
||
|
m_hMissionCompleteFrame = NULL;
|
||
|
m_hCampaignFrame = NULL;
|
||
|
m_hOutroFrame = NULL;
|
||
|
m_bLaunchedBriefing = false;
|
||
|
m_bLaunchedDebrief = false;
|
||
|
m_bLaunchedCampaignMap = false;
|
||
|
m_bLaunchedOutro = false;
|
||
|
m_bTechFailure = false;
|
||
|
m_hLastInfoMessage = NULL;
|
||
|
m_hInGameBriefingFrame = NULL;
|
||
|
m_aAwardedExperience.Purge();
|
||
|
// asw make sure the cam is in third person mode, so we don't load new maps with long laggy first person view
|
||
|
::input->CAM_ToThirdPerson();
|
||
|
|
||
|
m_fNextProgressUpdate = 0;
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::FireGameEvent( IGameEvent *event )
|
||
|
{
|
||
|
const char *eventname = event->GetName();
|
||
|
|
||
|
if ( Q_strcmp( "asw_mission_restart", eventname ) == 0 )
|
||
|
{
|
||
|
ASW_CloseAllWindows();
|
||
|
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||
|
if (pPlayer)
|
||
|
{
|
||
|
pPlayer->OnMissionRestart();
|
||
|
}
|
||
|
}
|
||
|
else if ( Q_strcmp( "game_newmap", eventname ) == 0 )
|
||
|
{
|
||
|
engine->ClientCmd("exec newmapsettings\n");
|
||
|
}
|
||
|
|
||
|
if ( !Q_strcmp( "achievement_earned", eventname ) )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( GetSplitScreenPlayerSlot() );
|
||
|
|
||
|
CBaseHudChat *hudChat = CBaseHudChat::GetHudChat();
|
||
|
|
||
|
if ( this == GetFullscreenClientMode() )
|
||
|
return;
|
||
|
|
||
|
int iPlayerIndex = event->GetInt( "player" );
|
||
|
C_ASW_Player *pPlayer = ToASW_Player( UTIL_PlayerByIndex( iPlayerIndex ) );
|
||
|
///C_ASW_Marine *pMarine = pPlayer ? pPlayer->GetMarine() : NULL;
|
||
|
int iAchievement = event->GetInt( "achievement" );
|
||
|
|
||
|
if ( pPlayer == C_ASW_Player::GetLocalASWPlayer() )
|
||
|
{
|
||
|
m_aAchievementsEarned.AddToTail( iAchievement );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pPlayer->m_aNonLocalPlayerAchievementsEarned.AddToTail();
|
||
|
}
|
||
|
|
||
|
if ( !hudChat || !pPlayer )
|
||
|
return;
|
||
|
|
||
|
if ( !IsInCommentaryMode() )
|
||
|
{
|
||
|
CAchievementMgr *pAchievementMgr = dynamic_cast<CAchievementMgr *>( engine->GetAchievementMgr() );
|
||
|
if ( !pAchievementMgr )
|
||
|
return;
|
||
|
|
||
|
IAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievement, GetSplitScreenPlayerSlot() );
|
||
|
if ( pAchievement )
|
||
|
{
|
||
|
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 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BaseClass::FireGameEvent(event);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
extern vgui::DHANDLE<vgui::Frame> g_hBriefingFrame;
|
||
|
|
||
|
// Close all ASW specific VGUI windows that the player might have open
|
||
|
void ClientModeASW::ASW_CloseAllWindows()
|
||
|
{
|
||
|
ASW_CloseAllWindowsFrom(GetViewport());
|
||
|
|
||
|
g_hBriefingFrame = NULL;
|
||
|
|
||
|
// make sure we don't have a mission chooser up
|
||
|
//Msg("clientmode asw closing vote windows with asw_vote_chooser cc\n");
|
||
|
engine->ClientCmd("asw_vote_chooser -1");
|
||
|
}
|
||
|
|
||
|
// recursive search for matching window names
|
||
|
void ClientModeASW::ASW_CloseAllWindowsFrom(vgui::Panel* pPanel)
|
||
|
{
|
||
|
if (!pPanel)
|
||
|
return;
|
||
|
|
||
|
int num_names = NELEMS(s_CloseWindowNames);
|
||
|
|
||
|
for (int k=0;k<pPanel->GetChildCount();k++)
|
||
|
{
|
||
|
Panel *pChild = pPanel->GetChild(k);
|
||
|
if (pChild)
|
||
|
{
|
||
|
ASW_CloseAllWindowsFrom(pChild);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// When VGUI is shutting down (i.e. if the player closes the window), GetName() can return NULL
|
||
|
const char *pPanelName = pPanel->GetName();
|
||
|
if ( pPanelName != NULL )
|
||
|
{
|
||
|
for (int i=0;i<num_names;i++)
|
||
|
{
|
||
|
if ( !strcmp( pPanelName, s_CloseWindowNames[i] ) )
|
||
|
{
|
||
|
pPanel->SetVisible(false);
|
||
|
pPanel->MarkForDeletion();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void ClientModeASW::StartBriefingMusic()
|
||
|
{
|
||
|
CLocalPlayerFilter filter;
|
||
|
|
||
|
if (!m_pBriefingMusic)
|
||
|
{
|
||
|
m_pBriefingMusic = CSoundEnvelopeController::GetController().SoundCreate( filter, 0, "asw_song.briefing" );
|
||
|
}
|
||
|
|
||
|
if (m_pBriefingMusic)
|
||
|
{
|
||
|
CSoundEnvelopeController::GetController().Play( m_pBriefingMusic, 1.0, 100 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::StopBriefingMusic(bool bInstantly)
|
||
|
{
|
||
|
if (m_pBriefingMusic)
|
||
|
{
|
||
|
if (bInstantly)
|
||
|
{
|
||
|
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
||
|
controller.SoundDestroy( m_pBriefingMusic );
|
||
|
m_pBriefingMusic = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
||
|
controller.SoundFadeOut( m_pBriefingMusic, 1.0, true );
|
||
|
m_pBriefingMusic = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ClientModeASW::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
|
||
|
{
|
||
|
if ( engine->Con_IsVisible() )
|
||
|
return 1;
|
||
|
|
||
|
// annoyingly we can't intercept ESC here, it'll still bring up the gameui stuff
|
||
|
// but we'll use it for a couple of things anyway
|
||
|
if (keynum == KEY_ESCAPE)
|
||
|
{
|
||
|
// ESC can be used up to close an info message
|
||
|
if (CASW_VGUI_Info_Message::CloseInfoMessage())
|
||
|
return 0;
|
||
|
|
||
|
// or closing the F1 panel
|
||
|
if (GetViewport())
|
||
|
{
|
||
|
vgui::Panel *pPanel = GetViewport()->FindChildByName("g_PlayerListFrame", true);
|
||
|
if (pPanel)
|
||
|
{
|
||
|
pPanel->SetVisible(false);
|
||
|
pPanel->MarkForDeletion();
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vgui::Panel *pContainer = GetClientMode()->GetViewport()->FindChildByName("InGameBriefingContainer", true);
|
||
|
if (pContainer)
|
||
|
{
|
||
|
pContainer->SetVisible(false);
|
||
|
pContainer->MarkForDeletion();
|
||
|
pContainer = NULL;
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return BaseClass::KeyInput(down, keynum, pszCurrentBinding);
|
||
|
}
|
||
|
|
||
|
void asw_set_hear_pos_cc()
|
||
|
{
|
||
|
g_asw_vec_fixed_hear_pos = g_asw_vec_last_hear_pos;
|
||
|
}
|
||
|
ConCommand asw_set_hear_pos( "asw_set_hear_pos", asw_set_hear_pos_cc, "Sets fixed audio position to the current position", FCVAR_CHEAT );
|
||
|
|
||
|
void ClientModeASW::OverrideAudioState( AudioState_t *pAudioState )
|
||
|
{
|
||
|
// lower hearing origin since cam is so far from the action
|
||
|
Vector hear_pos = pAudioState->m_Origin;
|
||
|
if (::input->CAM_IsThirdPerson())
|
||
|
{
|
||
|
// put audio position on our current marine if we have one selected
|
||
|
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||
|
CASW_Marine *pMarine = NULL;
|
||
|
if ( pPlayer && ( asw_hear_from_marine.GetBool() || asw_hear_height.GetFloat() != 0 ) )
|
||
|
{
|
||
|
pMarine = pPlayer->GetSpectatingMarine();
|
||
|
if ( !pMarine )
|
||
|
{
|
||
|
pMarine = pPlayer->GetMarine();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pMarine )
|
||
|
{
|
||
|
if ( asw_hear_height.GetFloat() > 0 )
|
||
|
{
|
||
|
Vector vecForward;
|
||
|
AngleVectors( pAudioState->m_Angles, &vecForward );
|
||
|
pAudioState->m_Origin = pMarine->EyePosition() - vecForward * asw_hear_height.GetFloat();
|
||
|
}
|
||
|
else if ( asw_hear_height.GetFloat() < 0 )
|
||
|
{
|
||
|
Vector vecForward;
|
||
|
AngleVectors( pAudioState->m_Angles, &vecForward );
|
||
|
pAudioState->m_Origin -= (vecForward * asw_hear_height.GetFloat() );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Vector vecForward;
|
||
|
AngleVectors( pAudioState->m_Angles, &vecForward );
|
||
|
pAudioState->m_Origin += (vecForward * 412.0f * 0.7f); // hardcoded 412 is bad
|
||
|
}
|
||
|
}
|
||
|
|
||
|
g_asw_vec_last_hear_pos = pAudioState->m_Origin;
|
||
|
if ( asw_hear_fixed.GetBool() )
|
||
|
{
|
||
|
pAudioState->m_Origin = g_asw_vec_fixed_hear_pos;
|
||
|
}
|
||
|
|
||
|
if ( asw_hear_pos_debug.GetBool() )
|
||
|
{
|
||
|
float flBaseSize = 10;
|
||
|
float flHeight = 80;
|
||
|
Vector vForward, vRight, vUp;
|
||
|
AngleVectors( pAudioState->m_Angles, &vForward, &vRight, &vUp );
|
||
|
debugoverlay->AddTriangleOverlay( pAudioState->m_Origin+vRight*flBaseSize/2, pAudioState->m_Origin-vRight*flBaseSize/2, pAudioState->m_Origin+vForward*flHeight, 255, 255, 0, 255, false, 0.1 );
|
||
|
debugoverlay->AddTriangleOverlay( pAudioState->m_Origin+vForward*flHeight, pAudioState->m_Origin-vRight*flBaseSize/2, pAudioState->m_Origin+vRight*flBaseSize/2, 255, 255, 0, 255, false, 0.1 );
|
||
|
NDebugOverlay::Box( pAudioState->m_Origin, -Vector( 3, 3, 3 ), Vector( 3, 3, 3 ), 255, 64, 0, 255, 0.1f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::Update( void )
|
||
|
{
|
||
|
UpdatePostProcessingEffects();
|
||
|
|
||
|
engine->SetMouseWindowLock( ASWGameRules() && ASWGameRules()->GetGameState() == ASW_GS_INGAME && !enginevgui->IsGameUIVisible() );
|
||
|
|
||
|
#ifndef _X360
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::DoPostScreenSpaceEffects( const CViewSetup *pSetup )
|
||
|
{
|
||
|
CMatRenderContextPtr pRenderContext( materials );
|
||
|
|
||
|
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||
|
bool bSniperScope = ( pPlayer != NULL ) && ( pPlayer->IsSniperScopeActive() );
|
||
|
|
||
|
extern bool g_bRenderingGlows;
|
||
|
|
||
|
if ( bSniperScope )
|
||
|
{
|
||
|
DrawSniperScopeStencilMask();
|
||
|
}
|
||
|
|
||
|
if ( mat_object_motion_blur_enable.GetBool() )
|
||
|
{
|
||
|
DoObjectMotionBlur( pSetup );
|
||
|
}
|
||
|
|
||
|
// Render object glows and selectively-bloomed objects (under sniper scope)
|
||
|
g_bRenderingGlows = true;
|
||
|
g_GlowObjectManager.RenderGlowEffects( pSetup, GetSplitScreenPlayerSlot() );
|
||
|
g_bRenderingGlows = false;
|
||
|
|
||
|
if ( bSniperScope )
|
||
|
{
|
||
|
// Update full frame FB 0 with result of glow pass so it can be used by sniper scope
|
||
|
ITexture *pFullFrameFB = materials->FindTexture( "_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET );
|
||
|
pRenderContext->CopyRenderTargetToTexture( pFullFrameFB );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::OnColorCorrectionWeightsReset( void )
|
||
|
{
|
||
|
C_ColorCorrection *pNewColorCorrection = NULL;
|
||
|
C_ColorCorrection *pOldColorCorrection = m_pCurrentColorCorrection;
|
||
|
CASW_Player *pPlayer = CASW_Player::GetLocalASWPlayer();
|
||
|
if ( pPlayer )
|
||
|
{
|
||
|
pNewColorCorrection = pPlayer->GetActiveColorCorrection();
|
||
|
}
|
||
|
|
||
|
if ( m_CCFailedHandle != INVALID_CLIENT_CCHANDLE && ASWGameRules() )
|
||
|
{
|
||
|
m_fFailedCCWeight = Approach( TechMarineFailPanel::s_pTechPanel ? 1.0f : 0.0f, m_fFailedCCWeight, gpGlobals->frametime * ( 1.0f / FAILED_CC_FADE_TIME ) );
|
||
|
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCFailedHandle, m_fFailedCCWeight );
|
||
|
|
||
|
// If the mission was failed due to a dead tech, disable the environmental color correction in favor of the mission failed color correction
|
||
|
if ( m_fFailedCCWeight != 0.0f && m_pCurrentColorCorrection )
|
||
|
{
|
||
|
m_pCurrentColorCorrection->EnableOnClient( false );
|
||
|
m_pCurrentColorCorrection = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_CCInfestedHandle != INVALID_CLIENT_CCHANDLE && ASWGameRules() )
|
||
|
{
|
||
|
C_ASW_Marine *pMarine = C_ASW_Marine::GetLocalMarine();
|
||
|
m_fInfestedCCWeight = Approach( pMarine && pMarine->IsInfested() ? 1.0f : 0.0f, m_fInfestedCCWeight, gpGlobals->frametime * ( 1.0f / INFESTED_CC_FADE_TIME ) );
|
||
|
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCInfestedHandle, m_fInfestedCCWeight );
|
||
|
|
||
|
// If the mission was failed due to a dead tech, disable the environmental color correction in favor of the mission failed color correction
|
||
|
if ( m_fInfestedCCWeight != 0.0f && m_pCurrentColorCorrection )
|
||
|
{
|
||
|
m_pCurrentColorCorrection->EnableOnClient( false );
|
||
|
m_pCurrentColorCorrection = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Only blend between environmental color corrections if there is no failure/infested-induced color correction
|
||
|
if ( pNewColorCorrection != pOldColorCorrection && m_fFailedCCWeight == 0.0f && m_fInfestedCCWeight == 0.0f )
|
||
|
{
|
||
|
if ( pOldColorCorrection )
|
||
|
{
|
||
|
pOldColorCorrection->EnableOnClient( false );
|
||
|
}
|
||
|
if ( pNewColorCorrection )
|
||
|
{
|
||
|
pNewColorCorrection->EnableOnClient( true, pOldColorCorrection == NULL );
|
||
|
}
|
||
|
m_pCurrentColorCorrection = pNewColorCorrection;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::DrawSniperScopeStencilMask()
|
||
|
{
|
||
|
extern ConVar asw_sniper_scope_radius;
|
||
|
CMatRenderContextPtr pRenderContext( materials );
|
||
|
PIXEvent myEvent( pRenderContext, "SniperScopeStencil" );
|
||
|
|
||
|
int nCursorX, nCursorY;
|
||
|
ASWInput()->GetSimulatedFullscreenMousePos( &nCursorX, &nCursorY );
|
||
|
|
||
|
const int NUM_CIRCLE_POINTS = 40;
|
||
|
Vector2D vScreenSpaceCoordinates[ NUM_CIRCLE_POINTS ];
|
||
|
|
||
|
int nScreenWidth, nScreenHeight;
|
||
|
pRenderContext->GetRenderTargetDimensions( nScreenWidth, nScreenHeight );
|
||
|
Vector2D vScreenSize( nScreenWidth, nScreenHeight );
|
||
|
|
||
|
// Clear the screen stencil value to 1 to inhibit glows everywhere except in the sniper scope circle, where it will be set to 0
|
||
|
pRenderContext->ClearStencilBufferRectangle( 0, 0, nScreenWidth, nScreenHeight, 1 );
|
||
|
float width = asw_sniper_scope_radius.GetFloat() * ( float ) nScreenHeight / 480.0f;
|
||
|
float height = asw_sniper_scope_radius.GetFloat() * ( float ) nScreenHeight / 480.0f;
|
||
|
for ( int i = 0; i < NUM_CIRCLE_POINTS; i++ )
|
||
|
{
|
||
|
float flAngle = 2.0f * M_PI * ( (float) i / (float) NUM_CIRCLE_POINTS );
|
||
|
vScreenSpaceCoordinates[i] = Vector2D( nCursorX + width * cos( flAngle ), nCursorY + height * sin( flAngle ) );
|
||
|
vScreenSpaceCoordinates[i].x = vScreenSpaceCoordinates[i].x / vScreenSize.x * 2.0f - 1.0f;
|
||
|
vScreenSpaceCoordinates[i].y = 1.0f - vScreenSpaceCoordinates[i].y / vScreenSize.y * 2.0f;
|
||
|
}
|
||
|
|
||
|
ShaderStencilState_t stencilState;
|
||
|
stencilState.m_bEnable = true;
|
||
|
stencilState.m_nReferenceValue = 0;
|
||
|
stencilState.m_CompareFunc = SHADER_STENCILFUNC_ALWAYS;
|
||
|
stencilState.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE;
|
||
|
stencilState.m_FailOp = SHADER_STENCILOP_KEEP;
|
||
|
stencilState.m_ZFailOp = SHADER_STENCILOP_SET_TO_REFERENCE;
|
||
|
pRenderContext->SetStencilState( stencilState );
|
||
|
|
||
|
pRenderContext->OverrideDepthEnable( true, false );
|
||
|
IMaterial *pMaterial = materials->FindMaterial( "engine/writestencil", TEXTURE_GROUP_OTHER, true );
|
||
|
DrawNDCSpaceUntexturedPolygon( pMaterial, NUM_CIRCLE_POINTS, vScreenSpaceCoordinates, NULL );
|
||
|
pRenderContext->OverrideDepthEnable( false, false );
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::DoObjectMotionBlur( const CViewSetup *pSetup )
|
||
|
{
|
||
|
if ( g_ObjectMotionBlurManager.GetDrawableObjectCount() <= 0 )
|
||
|
return;
|
||
|
|
||
|
CMatRenderContextPtr pRenderContext( materials );
|
||
|
|
||
|
ITexture *pFullFrameFB1 = materials->FindTexture( "_rt_FullFrameFB1", TEXTURE_GROUP_RENDER_TARGET );
|
||
|
|
||
|
//
|
||
|
// Render Velocities into a full-frame FB1
|
||
|
//
|
||
|
IMaterial *pGlowColorMaterial = materials->FindMaterial( "dev/glow_color", TEXTURE_GROUP_OTHER, true );
|
||
|
|
||
|
pRenderContext->PushRenderTargetAndViewport();
|
||
|
pRenderContext->SetRenderTarget( pFullFrameFB1 );
|
||
|
pRenderContext->Viewport( 0, 0, pSetup->width, pSetup->height );
|
||
|
|
||
|
// Red and Green are x- and y- screen-space velocities biased and packed into the [0,1] range.
|
||
|
// A value of 127 gets mapped to 0, a value of 0 gets mapped to -1, and a value of 255 gets mapped to 1.
|
||
|
//
|
||
|
// Blue is set to 1 within the object's bounds and 0 outside, and is used as a mask to ensure that
|
||
|
// motion blur samples only pull from the core object itself and not surrounding pixels (even though
|
||
|
// the area being blurred is larger than the core object).
|
||
|
//
|
||
|
// Alpha is not used
|
||
|
pRenderContext->ClearColor4ub( 127, 127, 0, 0 );
|
||
|
// Clear only color, not depth & stencil
|
||
|
pRenderContext->ClearBuffers( true, false, false );
|
||
|
|
||
|
// Save off state
|
||
|
Vector vOrigColor;
|
||
|
render->GetColorModulation( vOrigColor.Base() );
|
||
|
|
||
|
// Use a solid-color unlit material to render velocity into the buffer
|
||
|
g_pStudioRender->ForcedMaterialOverride( pGlowColorMaterial );
|
||
|
g_ObjectMotionBlurManager.DrawObjects();
|
||
|
g_pStudioRender->ForcedMaterialOverride( NULL );
|
||
|
|
||
|
render->SetColorModulation( vOrigColor.Base() );
|
||
|
|
||
|
pRenderContext->PopRenderTargetAndViewport();
|
||
|
|
||
|
//
|
||
|
// Render full-screen pass
|
||
|
//
|
||
|
IMaterial *pMotionBlurMaterial;
|
||
|
IMaterialVar *pFBTextureVariable;
|
||
|
IMaterialVar *pVelocityTextureVariable;
|
||
|
bool bFound1 = false, bFound2 = false;
|
||
|
|
||
|
// Make sure our render target of choice has the results of the engine post-process pass
|
||
|
ITexture *pFullFrameFB = materials->FindTexture( "_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET );
|
||
|
pRenderContext->CopyRenderTargetToTexture( pFullFrameFB );
|
||
|
|
||
|
pMotionBlurMaterial = materials->FindMaterial( "effects/object_motion_blur", TEXTURE_GROUP_OTHER, true );
|
||
|
pFBTextureVariable = pMotionBlurMaterial->FindVar( "$fb_texture", &bFound1, true );
|
||
|
pVelocityTextureVariable = pMotionBlurMaterial->FindVar( "$velocity_texture", &bFound2, true );
|
||
|
if ( bFound1 && bFound2 )
|
||
|
{
|
||
|
pFBTextureVariable->SetTextureValue( pFullFrameFB );
|
||
|
|
||
|
pVelocityTextureVariable->SetTextureValue( pFullFrameFB1 );
|
||
|
|
||
|
int nWidth, nHeight;
|
||
|
pRenderContext->GetRenderTargetDimensions( nWidth, nHeight );
|
||
|
|
||
|
pRenderContext->DrawScreenSpaceRectangle( pMotionBlurMaterial, 0, 0, nWidth, nHeight, 0.0f, 0.0f, nWidth - 1, nHeight - 1, nWidth, nHeight );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::UpdatePostProcessingEffects()
|
||
|
{
|
||
|
C_PostProcessController *pNewPostProcessController = NULL;
|
||
|
CASW_Player *pPlayer = CASW_Player::GetLocalASWPlayer();
|
||
|
if ( pPlayer )
|
||
|
{
|
||
|
pNewPostProcessController = pPlayer->GetActivePostProcessController();
|
||
|
}
|
||
|
|
||
|
// Figure out new endpoints for parameter lerping
|
||
|
if ( pNewPostProcessController != m_pCurrentPostProcessController )
|
||
|
{
|
||
|
m_LerpStartPostProcessParameters = m_CurrentPostProcessParameters;
|
||
|
m_LerpEndPostProcessParameters = pNewPostProcessController ? pNewPostProcessController->m_PostProcessParameters : PostProcessParameters_t();
|
||
|
m_pCurrentPostProcessController = pNewPostProcessController;
|
||
|
|
||
|
float flFadeTime = pNewPostProcessController ? pNewPostProcessController->m_PostProcessParameters.m_flParameters[ PPPN_FADE_TIME ] : 0.0f;
|
||
|
if ( flFadeTime <= 0.0f )
|
||
|
{
|
||
|
flFadeTime = 0.001f;
|
||
|
}
|
||
|
m_PostProcessLerpTimer.Start( flFadeTime );
|
||
|
}
|
||
|
|
||
|
// Lerp between start and end
|
||
|
float flLerpFactor = 1.0f - m_PostProcessLerpTimer.GetRemainingRatio();
|
||
|
for ( int nParameter = 0; nParameter < POST_PROCESS_PARAMETER_COUNT; ++ nParameter )
|
||
|
{
|
||
|
m_CurrentPostProcessParameters.m_flParameters[ nParameter ] =
|
||
|
Lerp(
|
||
|
flLerpFactor,
|
||
|
m_LerpStartPostProcessParameters.m_flParameters[ nParameter ],
|
||
|
m_LerpEndPostProcessParameters.m_flParameters[ nParameter ] );
|
||
|
}
|
||
|
SetPostProcessParams( &m_CurrentPostProcessParameters );
|
||
|
}
|
||
|
|
||
|
bool ClientModeASW::HasAwardedExperience( C_ASW_Player *pPlayer )
|
||
|
{
|
||
|
return ( pPlayer && m_aAwardedExperience.Find( pPlayer->entindex() ) != m_aAwardedExperience.InvalidIndex() );
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::SetAwardedExperience( C_ASW_Player *pPlayer )
|
||
|
{
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
m_aAwardedExperience.AddToTail( pPlayer->entindex() );
|
||
|
}
|
||
|
|
||
|
void ClientModeASW::ToggleMessageMode()
|
||
|
{
|
||
|
if ( m_pChatElement->GetMessageMode() != MM_NONE )
|
||
|
{
|
||
|
m_pChatElement->StopMessageMode();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pChatElement->StartMessageMode( MM_SAY );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// BroadcastPatchAudio() - same as BroadcastAudio(), but play using a static array of CSoundPatch so we can
|
||
|
// fade, change pitch, etc
|
||
|
static const int MAX_BROADCAST_SOUND_PATCHES = 16;
|
||
|
static CSoundPatch *s_pBroadcastSoundPatches[ MAX_BROADCAST_SOUND_PATCHES ];
|
||
|
|
||
|
static int FindFreeSoundPatchIndex()
|
||
|
{
|
||
|
for( int i = 0; i < MAX_BROADCAST_SOUND_PATCHES; i++ )
|
||
|
{
|
||
|
if ( s_pBroadcastSoundPatches[ i ] == NULL )
|
||
|
{
|
||
|
return i;
|
||
|
}
|
||
|
if ( !CSoundEnvelopeController::GetController().SoundIsStillPlaying( s_pBroadcastSoundPatches[ i ] ) )
|
||
|
{
|
||
|
CSoundEnvelopeController::GetController().SoundDestroy( s_pBroadcastSoundPatches[ i ] );
|
||
|
s_pBroadcastSoundPatches[ i ] = NULL;
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
static int FindSoundPatchIndex( const char *szSoundScriptName )
|
||
|
{
|
||
|
for( int i = 0; i < MAX_BROADCAST_SOUND_PATCHES; i++ )
|
||
|
{
|
||
|
if ( s_pBroadcastSoundPatches[ i ] == NULL )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
if ( !CSoundEnvelopeController::GetController().SoundIsStillPlaying( s_pBroadcastSoundPatches[ i ] ) )
|
||
|
{
|
||
|
CSoundEnvelopeController::GetController().SoundDestroy( s_pBroadcastSoundPatches[ i ] );
|
||
|
s_pBroadcastSoundPatches[ i ] = NULL;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if( !Q_stricmp( CSoundEnvelopeController::GetController().SoundGetScriptName( s_pBroadcastSoundPatches[ i ] ), szSoundScriptName ) )
|
||
|
{
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void __MsgFunc_BroadcastPatchAudio( bf_read &msg )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
|
||
|
|
||
|
int nSoundPatchIndex = FindFreeSoundPatchIndex();
|
||
|
|
||
|
char szString[2048];
|
||
|
msg.ReadString( szString, sizeof(szString) );
|
||
|
|
||
|
if ( nSoundPatchIndex < 0 )
|
||
|
{
|
||
|
Warning( "%s(): Out of broadcast sound patches (MAX_BROADCAST_SOUND_PATCHES = %d)\n", __FUNCTION__, MAX_BROADCAST_SOUND_PATCHES );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CLocalPlayerFilter filter;
|
||
|
s_pBroadcastSoundPatches[ nSoundPatchIndex ] = CSoundEnvelopeController::GetController().SoundCreate( filter, SOUND_FROM_WORLD, szString );
|
||
|
CSoundEnvelopeController::GetController().Play( s_pBroadcastSoundPatches[ nSoundPatchIndex ], 1.0, 100 );
|
||
|
}
|
||
|
USER_MESSAGE_REGISTER( BroadcastPatchAudio );
|
||
|
|
||
|
void __MsgFunc_BroadcastStopPatchAudio( bf_read &msg )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
|
||
|
|
||
|
char szString[2048];
|
||
|
msg.ReadString( szString, sizeof(szString) );
|
||
|
|
||
|
int nSoundPatchIndex = FindSoundPatchIndex( szString );
|
||
|
|
||
|
if ( nSoundPatchIndex == -1 )
|
||
|
{
|
||
|
Warning( "%s(): Cannot find broadcast patch %s to stop\n", __FUNCTION__, szString );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float flFadeOutTime = msg.ReadFloat();
|
||
|
|
||
|
if ( flFadeOutTime == 0.0 )
|
||
|
{
|
||
|
CSoundEnvelopeController::GetController().SoundDestroy( s_pBroadcastSoundPatches[ nSoundPatchIndex ] );
|
||
|
s_pBroadcastSoundPatches[ nSoundPatchIndex ] = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CSoundEnvelopeController::GetController().SoundFadeOut( s_pBroadcastSoundPatches[ nSoundPatchIndex ], flFadeOutTime );
|
||
|
}
|
||
|
}
|
||
|
USER_MESSAGE_REGISTER( BroadcastStopPatchAudio );
|
||
|
|
||
|
void __MsgFunc_BroadcastAudio( bf_read &msg )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
|
||
|
|
||
|
char szString[2048];
|
||
|
msg.ReadString( szString, sizeof(szString) );
|
||
|
|
||
|
CLocalPlayerFilter filter;
|
||
|
C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, szString );
|
||
|
}
|
||
|
USER_MESSAGE_REGISTER( BroadcastAudio );
|
||
|
|
||
|
void __MsgFunc_BroadcastStopAudio( bf_read &msg )
|
||
|
{
|
||
|
ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
|
||
|
|
||
|
char szString[2048];
|
||
|
msg.ReadString( szString, sizeof(szString) );
|
||
|
|
||
|
C_BaseEntity::StopSound( SOUND_FROM_LOCAL_PLAYER, szString );
|
||
|
}
|
||
|
USER_MESSAGE_REGISTER( BroadcastStopAudio );
|