diff --git a/sp/src/game/client/clientmode_shared.cpp b/sp/src/game/client/clientmode_shared.cpp index f2e6e31dc55..0e932e9cf0c 100644 --- a/sp/src/game/client/clientmode_shared.cpp +++ b/sp/src/game/client/clientmode_shared.cpp @@ -317,7 +317,38 @@ void ClientModeShared::ReloadScheme( void ) { m_pViewport->ReloadScheme( "resource/ClientScheme.res" ); ClearKeyValuesCache(); +#ifdef MAPBASE + m_bResetSchemeOnReload = false; +#endif +} + +#ifdef MAPBASE +void ClientModeShared::SetCustomClientScheme( const char *pszFile ) +{ + m_pViewport->ReloadScheme( pszFile ); + ClearKeyValuesCache(); + m_bResetSchemeOnReload = true; +} + +void ClientModeShared::SetCustomHudLayout( const char *pszFile ) +{ + m_pViewport->SetCustomHUDLayout( pszFile ); + if ( pszFile != NULL ) + m_bResetSchemeOnReload = true; +} + +bool ClientModeShared::LoadCustomHudAnimations( const char *pszFile ) +{ + m_bResetSchemeOnReload = true; + return m_pViewport->LoadCustomHudAnimations( pszFile ); +} + +bool ClientModeShared::LoadCustomHudAnimationsManifest( const char *pszFile ) +{ + m_bResetSchemeOnReload = true; + return m_pViewport->LoadCustomHudAnimationsManifest( pszFile ); } +#endif //---------------------------------------------------------------------------- @@ -898,6 +929,16 @@ void ClientModeShared::LevelInit( const char *newmap ) #ifdef DEMO_AUTORECORD AutoRecord(newmap); #endif + +#ifdef MAPBASE + if ( m_bResetSchemeOnReload ) + { + // Restore default HUD + // (note that there is currently no way to destruct the old scheme) + m_pViewport->SetCustomHUDLayout( NULL ); + ReloadScheme(); + } +#endif } #ifdef DEMO_AUTORECORD diff --git a/sp/src/game/client/clientmode_shared.h b/sp/src/game/client/clientmode_shared.h index 20288db8f79..f2a115688cc 100644 --- a/sp/src/game/client/clientmode_shared.h +++ b/sp/src/game/client/clientmode_shared.h @@ -75,6 +75,12 @@ class ClientModeShared : public IClientMode, public CGameEventListener virtual void Layout(); virtual void ReloadScheme( void ); +#ifdef MAPBASE + virtual void SetCustomClientScheme( const char *pszFile ); + virtual void SetCustomHudLayout( const char *pszFile ); + virtual bool LoadCustomHudAnimations( const char *pszFile ); + virtual bool LoadCustomHudAnimationsManifest( const char *pszFile ); +#endif virtual void OverrideView( CViewSetup *pSetup ); virtual bool ShouldDrawDetailObjects( ); virtual bool ShouldDrawEntity(C_BaseEntity *pEnt); @@ -179,6 +185,9 @@ class ClientModeShared : public IClientMode, public CGameEventListener CountdownTimer m_PostProcessLerpTimer; CHandle m_pCurrentColorCorrection; + + // When using a custom client scheme + bool m_bResetSchemeOnReload; #endif }; diff --git a/sp/src/game/client/game_controls/baseviewport.cpp b/sp/src/game/client/game_controls/baseviewport.cpp index a098662094e..30615c03268 100644 --- a/sp/src/game/client/game_controls/baseviewport.cpp +++ b/sp/src/game/client/game_controls/baseviewport.cpp @@ -170,6 +170,68 @@ bool CBaseViewport::LoadCustomHudAnimations( const char *pszFile ) { return m_pAnimController->SetScriptFile( GetVPanel(), pszFile, true ); } + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CBaseViewport::LoadCustomHudAnimationsManifest( const char *pszFile ) +{ + // First load the custom manifest + KeyValues *manifest = new KeyValues( pszFile ); + if ( manifest->LoadFromFile( g_pFullFileSystem, pszFile, "GAME" ) == false ) + { + manifest->deleteThis(); + return false; + } + + // Then load the default manifest + const char *HUDANIMATION_MANIFEST_FILE = "scripts/hudanimations_manifest.txt"; + KeyValues *defaultManifest = new KeyValues( HUDANIMATION_MANIFEST_FILE ); + if ( defaultManifest->LoadFromFile( g_pFullFileSystem, HUDANIMATION_MANIFEST_FILE, "GAME" ) == false ) + { + defaultManifest->deleteThis(); + manifest->deleteThis(); + return false; + } + + bool bClearScript = true; + + // Load each file defined in the text + for ( KeyValues *sub = defaultManifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) + { + if ( !Q_stricmp( sub->GetName(), "file" ) ) + { + const char *pszLoadFile = sub->GetString(); + + // Check if this is remapped by the custom manifest + for ( KeyValues *csub = manifest->GetFirstSubKey(); csub != NULL; csub = csub->GetNextKey() ) + { + if ( Q_strstr( pszLoadFile, csub->GetName() ) ) + { + // Use the custom manifest's file instead + pszLoadFile = csub->GetString(); + break; + } + } + + if ( !pszLoadFile || !*pszLoadFile ) + continue; + + // Add it + if ( m_pAnimController->SetScriptFile( GetVPanel(), pszLoadFile, bClearScript ) == false ) + { + Assert( 0 ); + } + + bClearScript = false; + continue; + } + } + + defaultManifest->deleteThis(); + manifest->deleteThis(); + return true; +} #endif //================================================================ @@ -692,12 +754,23 @@ void CBaseViewport::ReloadScheme(const char *fromFile) CETWScope timer( "CBaseViewport::ReloadScheme" ); // See if scheme should change + + bool bSchemeChange = false; if ( fromFile != NULL ) { // "resource/ClientScheme.res" vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), fromFile, "HudScheme" ); +#ifdef MAPBASE + if ( scheme != GetScheme() ) + { + // If this is a different scheme from what we had before, then we need to re-apply default settings for stuff like fonts + SetApplyDefaultSettings( true ); + bSchemeChange = true; + } +#endif + SetScheme(scheme); SetProportional( true ); m_pAnimController->SetScheme(scheme); @@ -719,6 +792,11 @@ void CBaseViewport::ReloadScheme(const char *fromFile) g_pClientMode->ComputeVguiResConditions( pConditions ); // reload the .res file from disk +#ifdef MAPBASE + if ( m_szCustomHUDLayout[0] ) + LoadControlSettings( m_szCustomHUDLayout, NULL, NULL, pConditions ); + else +#endif LoadControlSettings( "scripts/HudLayout.res", NULL, NULL, pConditions ); gHUD.RefreshHudTextures(); @@ -726,9 +804,33 @@ void CBaseViewport::ReloadScheme(const char *fromFile) InvalidateLayout( true, true ); // reset the hud +#ifdef MAPBASE + if ( bSchemeChange ) + { + // Need to initialize values + gHUD.VidInit(); + } + else +#endif gHUD.ResetHUD(); } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseViewport::SetCustomHUDLayout( const char *pszHUDLayout ) +{ + if ( !pszHUDLayout ) + { + m_szCustomHUDLayout[0] = NULL; + return; + } + + V_strncpy( m_szCustomHUDLayout, pszHUDLayout, sizeof( m_szCustomHUDLayout ) ); +} +#endif + int CBaseViewport::GetDeathMessageStartHeight( void ) { return YRES(2); diff --git a/sp/src/game/client/game_controls/baseviewport.h b/sp/src/game/client/game_controls/baseviewport.h index cbc602a0ed9..9b2c8ebf9aa 100644 --- a/sp/src/game/client/game_controls/baseviewport.h +++ b/sp/src/game/client/game_controls/baseviewport.h @@ -49,6 +49,9 @@ class CBaseViewport : public vgui::EditablePanel, public IViewPort, public IGame virtual void SetParent(vgui::VPANEL parent); virtual void ReloadScheme(const char *fromFile); +#ifdef MAPBASE + virtual void SetCustomHUDLayout( const char *pszHUDLayout ); +#endif virtual void ActivateClientUI(); virtual void HideClientUI(); virtual bool AllowedToPrintText( void ); @@ -75,6 +78,7 @@ class CBaseViewport : public vgui::EditablePanel, public IViewPort, public IGame #ifdef MAPBASE bool LoadCustomHudAnimations( const char *pszFile ); + bool LoadCustomHudAnimationsManifest( const char *pszFile ); void ReloadHudAnimations( void ); #endif @@ -146,6 +150,10 @@ class CBaseViewport : public vgui::EditablePanel, public IViewPort, public IGame vgui::HCursor m_hCursorNone; vgui::AnimationController *m_pAnimController; int m_OldSize[2]; + +#ifdef MAPBASE + char m_szCustomHUDLayout[MAX_PATH]; +#endif }; diff --git a/sp/src/game/client/hl2/c_basehlplayer.cpp b/sp/src/game/client/hl2/c_basehlplayer.cpp index 461990c0dff..5020e218923 100644 --- a/sp/src/game/client/hl2/c_basehlplayer.cpp +++ b/sp/src/game/client/hl2/c_basehlplayer.cpp @@ -11,6 +11,10 @@ #include "c_ai_basenpc.h" #include "in_buttons.h" #include "collisionutils.h" +#ifdef MAPBASE +#include "mapbase/protagonist_system.h" +#include "clientmode_shared.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -83,7 +87,7 @@ C_BaseHLPlayer::C_BaseHLPlayer() ConVarRef scissor("r_flashlightscissor"); scissor.SetValue("0"); - m_nProtagonistIndex = -1; + m_nProtagonistIndex = m_nOldProtagonistIndex = -1; #endif } @@ -99,6 +103,14 @@ void C_BaseHLPlayer::OnDataChanged( DataUpdateType_t updateType ) SetNextClientThink( CLIENT_THINK_ALWAYS ); } +#ifdef MAPBASE + if ( m_nProtagonistIndex != m_nOldProtagonistIndex ) + { + OnChangeProtagonist(); + m_nOldProtagonistIndex = m_nProtagonistIndex; + } +#endif + #ifdef SP_ANIM_STATE if (m_flAnimRenderYaw != FLT_MAX) { @@ -694,6 +706,69 @@ void C_BaseHLPlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quatern } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_BaseHLPlayer::ModifyEmitSoundParams( EmitSound_t ¶ms ) +{ + BaseClass::ModifyEmitSoundParams( params ); + + if ( m_nProtagonistIndex != -1 ) + { + const char *pszSoundOverride = g_ProtagonistSystem.GetProtagonist_SoundOverride( this, params.m_pSoundName ); + if ( pszSoundOverride ) + params.m_pSoundName = pszSoundOverride; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_BaseHLPlayer::OnChangeProtagonist() +{ + g_ProtagonistSystem.PrecacheProtagonist( this, m_nProtagonistIndex ); + + // Check if this protagonist has a custom HUD + const char *pszClientScheme = g_ProtagonistSystem.GetProtagonist_ClientScheme( this ); + if ( pszClientScheme ) + { + ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); + if ( !mode ) + return; + + CBaseViewport *pViewport = ( CBaseViewport * )mode->GetViewport(); + if ( pViewport ) + { + mode->SetCustomHudLayout( g_ProtagonistSystem.GetProtagonist_HUDLayout( this ) ); + mode->SetCustomClientScheme( pszClientScheme ); + + const char *pszHUDAnims = g_ProtagonistSystem.GetProtagonist_HUDAnims( this ); + if ( pszHUDAnims ) + pViewport->LoadCustomHudAnimationsManifest( pszHUDAnims ); + } + } + else if ( m_nOldProtagonistIndex != -1 ) + { + // Check if the previous protagonist had a custom HUD. If it did, then load the default scheme + pszClientScheme = g_ProtagonistSystem.GetProtagonist_ClientScheme( m_nOldProtagonistIndex ); + if ( pszClientScheme ) + { + ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); + if ( !mode ) + return; + + CBaseViewport *pViewport = ( CBaseViewport * )mode->GetViewport(); + if ( pViewport ) + { + mode->SetCustomHudLayout( NULL ); + mode->ReloadScheme(); + } + } + } +} +#endif + #ifdef SP_ANIM_STATE //----------------------------------------------------------------------------- // Purpose: diff --git a/sp/src/game/client/hl2/c_basehlplayer.h b/sp/src/game/client/hl2/c_basehlplayer.h index 3bdc7015e49..961ecdfcbad 100644 --- a/sp/src/game/client/hl2/c_basehlplayer.h +++ b/sp/src/game/client/hl2/c_basehlplayer.h @@ -64,7 +64,10 @@ class C_BaseHLPlayer : public C_BasePlayer bool IsWeaponLowered( void ) { return m_HL2Local.m_bWeaponLowered; } #ifdef MAPBASE + virtual void ModifyEmitSoundParams( EmitSound_t ¶ms ); + int GetProtagonistIndex() const { return m_nProtagonistIndex; } + virtual void OnChangeProtagonist(); #endif #ifdef SP_ANIM_STATE @@ -96,6 +99,7 @@ class C_BaseHLPlayer : public C_BasePlayer #ifdef MAPBASE int m_nProtagonistIndex; + int m_nOldProtagonistIndex; #endif #ifdef MAPBASE_MP diff --git a/sp/src/game/client/hl2/clientmode_hlnormal.cpp b/sp/src/game/client/hl2/clientmode_hlnormal.cpp index dc1415af213..110e8e26497 100644 --- a/sp/src/game/client/hl2/clientmode_hlnormal.cpp +++ b/sp/src/game/client/hl2/clientmode_hlnormal.cpp @@ -13,6 +13,10 @@ #include #include "iinput.h" #include "ienginevgui.h" +#ifdef MAPBASE +#include "c_basehlplayer.h" +#include "mapbase/protagonist_system.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -95,5 +99,27 @@ bool ClientModeHLNormal::ShouldDrawCrosshair( void ) return ( g_bRollingCredits == false ); } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ClientModeHLNormal::ReloadScheme() +{ + C_BaseHLPlayer *pPlayer = static_cast( C_BasePlayer::GetLocalPlayer() ); + if ( pPlayer && pPlayer->GetProtagonistIndex() != -1 ) + { + // Use the protagonist's scheme instead, if it exists + const char *pszClientScheme = g_ProtagonistSystem.GetProtagonist_ClientScheme( pPlayer ); + if ( pszClientScheme != NULL ) + { + SetCustomClientScheme( pszClientScheme ); + return; + } + } + + BaseClass::ReloadScheme(); +} +#endif + diff --git a/sp/src/game/client/hl2/clientmode_hlnormal.h b/sp/src/game/client/hl2/clientmode_hlnormal.h index 623da4335de..774f9e6bdb1 100644 --- a/sp/src/game/client/hl2/clientmode_hlnormal.h +++ b/sp/src/game/client/hl2/clientmode_hlnormal.h @@ -37,6 +37,10 @@ class ClientModeHLNormal : public ClientModeShared virtual void Init(); virtual bool ShouldDrawCrosshair( void ); + +#ifdef MAPBASE + virtual void ReloadScheme( void ); +#endif }; extern IClientMode *GetClientModeNormal(); diff --git a/sp/src/game/client/hl2/hud_ammo.cpp b/sp/src/game/client/hl2/hud_ammo.cpp index 9e9e913991c..e274d4021f5 100644 --- a/sp/src/game/client/hl2/hud_ammo.cpp +++ b/sp/src/game/client/hl2/hud_ammo.cpp @@ -77,16 +77,6 @@ void CHudAmmo::Init( void ) m_iAmmo2 = -1; m_iconPrimaryAmmo = NULL; - - wchar_t *tempString = g_pVGuiLocalize->Find("#Valve_Hud_AMMO"); - if (tempString) - { - SetLabelText(tempString); - } - else - { - SetLabelText(L"AMMO"); - } } //----------------------------------------------------------------------------- @@ -109,6 +99,17 @@ void CHudAmmo::Reset() m_iAmmo2 = 0; UpdateAmmoDisplays(); + + // Moved from CHudAmmo::Init so that it can be reset on HUD reload + wchar_t *tempString = g_pVGuiLocalize->Find("#Valve_Hud_AMMO"); + if (tempString) + { + SetLabelText(tempString); + } + else + { + SetLabelText(L"AMMO"); + } } //----------------------------------------------------------------------------- diff --git a/sp/src/game/client/hl2/hud_battery.cpp b/sp/src/game/client/hl2/hud_battery.cpp index c07943c1038..490d3fd5bae 100644 --- a/sp/src/game/client/hl2/hud_battery.cpp +++ b/sp/src/game/client/hl2/hud_battery.cpp @@ -83,6 +83,12 @@ void CHudBattery::Reset( void ) void CHudBattery::VidInit( void ) { Reset(); + +#ifdef MAPBASE + // If the HUD was reloaded, then the battery indicator's alpha will be reset + // Resetting m_iBat allows OnThink() to run and set the correct visibility + m_iBat = INIT_BAT; +#endif } //----------------------------------------------------------------------------- diff --git a/sp/src/game/client/hl2/hud_weaponselection.cpp b/sp/src/game/client/hl2/hud_weaponselection.cpp index b83d6429abc..eecf398ab68 100644 --- a/sp/src/game/client/hl2/hud_weaponselection.cpp +++ b/sp/src/game/client/hl2/hud_weaponselection.cpp @@ -914,12 +914,19 @@ void CHudWeaponSelection::DrawLargeWeaponBox( C_BaseCombatWeapon *pWeapon, bool // draw text col = m_TextColor; +#ifndef MAPBASE // Unused const FileWeaponInfo_t &weaponInfo = pWeapon->GetWpnData(); +#endif if ( bSelected ) { wchar_t text[128]; +#ifdef MAPBASE + // Allows derived classes to override + wchar_t *tempString = g_pVGuiLocalize->Find( pWeapon->GetPrintName() ); +#else wchar_t *tempString = g_pVGuiLocalize->Find(weaponInfo.szPrintName); +#endif // setup our localized string if ( tempString ) @@ -934,7 +941,12 @@ void CHudWeaponSelection::DrawLargeWeaponBox( C_BaseCombatWeapon *pWeapon, bool else { // string wasn't found by g_pVGuiLocalize->Find() +#ifdef MAPBASE + // Allows derived classes to override + g_pVGuiLocalize->ConvertANSIToUnicode(pWeapon->GetPrintName(), text, sizeof(text)); +#else g_pVGuiLocalize->ConvertANSIToUnicode(weaponInfo.szPrintName, text, sizeof(text)); +#endif } surface()->DrawSetTextColor( col ); diff --git a/sp/src/game/client/hud_numericdisplay.cpp b/sp/src/game/client/hud_numericdisplay.cpp index de9c84f1b13..966be2f27b3 100644 --- a/sp/src/game/client/hud_numericdisplay.cpp +++ b/sp/src/game/client/hud_numericdisplay.cpp @@ -13,6 +13,9 @@ #include #include #include +#ifdef MAPBASE +#include +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -81,6 +84,12 @@ void CHudNumericDisplay::SetShouldDisplaySecondaryValue(bool state) //----------------------------------------------------------------------------- void CHudNumericDisplay::SetLabelText(const wchar_t *text) { +#ifdef MAPBASE + // Refuse further inputs from the code if the control settings have their own definition + if ( m_bOverrideLabel ) + return; +#endif + wcsncpy(m_LabelText, text, sizeof(m_LabelText) / sizeof(wchar_t)); m_LabelText[(sizeof(m_LabelText) / sizeof(wchar_t)) - 1] = 0; } @@ -145,6 +154,37 @@ void CHudNumericDisplay::PaintNumbers(HFont font, int xpos, int ypos, int value) surface()->DrawUnicodeString( unicode ); } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudNumericDisplay::ApplySettings( KeyValues *inResourceData ) +{ + BaseClass::ApplySettings( inResourceData ); + + m_bOverrideLabel = false; + + const char *text = inResourceData->GetString( "text", NULL ); + if (text) + { + // Override label text + wchar_t *tempString = g_pVGuiLocalize->Find( text ); + if ( tempString ) + { + SetLabelText( tempString ); + } + else + { + wchar_t szText[128]; + V_UTF8ToUnicode( text, szText, sizeof( szText ) ); + SetLabelText( szText ); + } + + m_bOverrideLabel = true; + } +} +#endif + //----------------------------------------------------------------------------- // Purpose: draws the text //----------------------------------------------------------------------------- diff --git a/sp/src/game/client/hud_numericdisplay.h b/sp/src/game/client/hud_numericdisplay.h index b004f91826b..79c305d98e5 100644 --- a/sp/src/game/client/hud_numericdisplay.h +++ b/sp/src/game/client/hud_numericdisplay.h @@ -43,6 +43,10 @@ class CHudNumericDisplay : public vgui::Panel virtual void PaintNumbers(vgui::HFont font, int xpos, int ypos, int value); +#ifdef MAPBASE + virtual void ApplySettings( KeyValues *inResourceData ); +#endif + protected: int m_iValue; @@ -52,6 +56,11 @@ class CHudNumericDisplay : public vgui::Panel bool m_bIndent; bool m_bIsTime; +#ifdef MAPBASE + // Label is defined by control settings instead of code + bool m_bOverrideLabel; +#endif + CPanelAnimationVar( float, m_flBlur, "Blur", "0" ); CPanelAnimationVar( Color, m_TextColor, "TextColor", "FgColor" ); CPanelAnimationVar( Color, m_Ammo2Color, "Ammo2Color", "FgColor" ); diff --git a/sp/src/game/server/hl2/hl2_player.cpp b/sp/src/game/server/hl2/hl2_player.cpp index 673a0e39a82..b5aee6a9f61 100644 --- a/sp/src/game/server/hl2/hl2_player.cpp +++ b/sp/src/game/server/hl2/hl2_player.cpp @@ -4688,6 +4688,21 @@ void CHL2_Player::ModifyOrAppendPlayerCriteria( AI_CriteriaSet& set ) } #ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHL2_Player::ModifyEmitSoundParams( EmitSound_t ¶ms ) +{ + BaseClass::ModifyEmitSoundParams( params ); + + if ( m_nProtagonistIndex != -1 ) + { + const char *pszSoundOverride = g_ProtagonistSystem.GetProtagonist_SoundOverride( this, params.m_pSoundName ); + if ( pszSoundOverride ) + params.m_pSoundName = pszSoundOverride; + } +} + const char *CHL2_Player::GetOverrideStepSound( const char *pszBaseStepSoundName ) { int idx = FindContextByName("footsteps"); diff --git a/sp/src/game/server/hl2/hl2_player.h b/sp/src/game/server/hl2/hl2_player.h index f388b89687b..668447d953f 100644 --- a/sp/src/game/server/hl2/hl2_player.h +++ b/sp/src/game/server/hl2/hl2_player.h @@ -142,6 +142,7 @@ class CHL2_Player : public CBasePlayer virtual CStudioHdr* OnNewModel(); + virtual void ModifyEmitSoundParams( EmitSound_t ¶ms ); virtual const char *GetOverrideStepSound( const char *pszBaseStepSoundName ); #endif diff --git a/sp/src/game/shared/hl2/basehlcombatweapon_shared.cpp b/sp/src/game/shared/hl2/basehlcombatweapon_shared.cpp index a58e82b51c7..be07342f5fc 100644 --- a/sp/src/game/shared/hl2/basehlcombatweapon_shared.cpp +++ b/sp/src/game/shared/hl2/basehlcombatweapon_shared.cpp @@ -442,6 +442,21 @@ const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetDefaultProficiencyValues( #endif #ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const char *CBaseHLCombatWeapon::GetPrintName() const +{ + if (GetOwner() && GetOwner()->IsPlayer()) + { + const char *pszProtagPrintName = g_ProtagonistSystem.GetProtagonist_PrintName( static_cast(GetOwner()), this ); + if (pszProtagPrintName) + return pszProtagPrintName; + } + + return BaseClass::GetPrintName(); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/sp/src/game/shared/hl2/basehlcombatweapon_shared.h b/sp/src/game/shared/hl2/basehlcombatweapon_shared.h index 3a09ae432a5..a23114f524f 100644 --- a/sp/src/game/shared/hl2/basehlcombatweapon_shared.h +++ b/sp/src/game/shared/hl2/basehlcombatweapon_shared.h @@ -54,6 +54,7 @@ class CBaseHLCombatWeapon : public CBaseCombatWeapon virtual void ItemHolsterFrame( void ); #ifdef MAPBASE + virtual char const *GetPrintName( void ) const; virtual const char *GetViewModel( int viewmodelindex = 0 ) const; virtual float GetViewmodelFOVOverride() const; virtual bool UsesHands( void ) const; diff --git a/sp/src/game/shared/mapbase/mapbase_shared.cpp b/sp/src/game/shared/mapbase/mapbase_shared.cpp index 2345d9cab85..61469231400 100644 --- a/sp/src/game/shared/mapbase/mapbase_shared.cpp +++ b/sp/src/game/shared/mapbase/mapbase_shared.cpp @@ -71,11 +71,7 @@ static bool g_bMapContainsCustomTalker; // This constant should change with each Mapbase update ConVar mapbase_version_client( "mapbase_version_client", MAPBASE_VERSION, FCVAR_NONE, "The version of Mapbase currently being used in this mod's client.dll" ); -// This is from the vgui_controls library -extern vgui::HScheme g_iCustomClientSchemeOverride; - extern bool g_bUsingCustomHudAnimations; -bool g_bUsingCustomHudLayout = false; #endif extern void AddSurfacepropFile( const char *pFileName, IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem ); @@ -319,35 +315,9 @@ class CMapbaseSystem : public CAutoGameSystem } m_CloseCaptionFileNames.RemoveAll(); - if (g_iCustomClientSchemeOverride != 0 || g_bUsingCustomHudAnimations || g_bUsingCustomHudLayout) + if (g_bUsingCustomHudAnimations) { - CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Mapbase: Reloading client mode and viewport scheme\n" ); - - // TODO: We currently have no way of actually cleaning up custom schemes upon level unload. - // That may or may not be sustainable if there's a ton of custom schemes loaded at once - g_iCustomClientSchemeOverride = 0; - g_bUsingCustomHudAnimations = false; - g_bUsingCustomHudLayout = false; - - // Reload scheme - ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); - if ( mode ) - { - mode->ReloadScheme(); - - // We need to reload default values, so load a special "hudlayout_mapbase.res" file that only contains - // default Mapbase definitions identical to the defaults in the code - CBaseViewport *pViewport = dynamic_cast(g_pClientMode->GetViewport()); - if (pViewport) - { - KeyValuesAD pConditions( "conditions" ); - g_pClientMode->ComputeVguiResConditions( pConditions ); - - // reload the .res file from disk - pViewport->LoadControlSettings( "scripts/hudlayout_mapbase.res", NULL, NULL, pConditions ); - } - } } #endif } @@ -573,27 +543,24 @@ class CMapbaseSystem : public CAutoGameSystem // Custom scheme loading void ManifestLoadCustomScheme( const char *pszFile ) { - g_iCustomClientSchemeOverride = vgui::scheme()->LoadSchemeFromFile( pszFile, "CustomClientScheme" ); - // Reload scheme ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); if ( mode ) { - mode->ReloadScheme(); + mode->SetCustomClientScheme( pszFile ); } } void ManifestLoadCustomHudAnimations( const char *pszFile ) { - CBaseViewport *pViewport = dynamic_cast(g_pClientMode->GetViewport()); - if (pViewport) + ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); + if ( mode ) { g_bUsingCustomHudAnimations = true; - if (!pViewport->LoadCustomHudAnimations( pszFile )) + if (!mode->LoadCustomHudAnimations( pszFile )) { g_bUsingCustomHudAnimations = false; CGWarning( 0, CON_GROUP_MAPBASE_MISC, "Custom HUD animations file \"%s\" failed to load\n", pszFile ); - pViewport->ReloadHudAnimations(); } else { @@ -604,17 +571,10 @@ class CMapbaseSystem : public CAutoGameSystem void ManifestLoadCustomHudLayout( const char *pszFile ) { - CBaseViewport *pViewport = dynamic_cast(g_pClientMode->GetViewport()); - if (pViewport) + ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); + if ( mode ) { - g_bUsingCustomHudLayout = true; - - KeyValuesAD pConditions( "conditions" ); - g_pClientMode->ComputeVguiResConditions( pConditions ); - - // reload the .res file from disk - pViewport->LoadControlSettings( pszFile, NULL, NULL, pConditions ); - + mode->SetCustomHudLayout( pszFile ); CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Loaded custom HUD layout file \"%s\"\n", pszFile );; } } diff --git a/sp/src/game/shared/mapbase/protagonist_system.cpp b/sp/src/game/shared/mapbase/protagonist_system.cpp index b4eb1313578..649592f9eb2 100644 --- a/sp/src/game/shared/mapbase/protagonist_system.cpp +++ b/sp/src/game/shared/mapbase/protagonist_system.cpp @@ -100,6 +100,21 @@ void CProtagonistSystem::LoadProtagonistFile( const char *pszFile ) } #ifdef CLIENT_DLL + //---------------------------------------------------------------------------- + // User Interface + //---------------------------------------------------------------------------- + else if (FStrEq( pszSubKeyName, "hudscheme" )) + { + pProtag->pszClientScheme = AllocateString( pSubKey->GetString() ); + } + else if (FStrEq( pszSubKeyName, "hudlayout" )) + { + pProtag->pszHUDLayout = AllocateString( pSubKey->GetString() ); + } + else if (FStrEq( pszSubKeyName, "hudanims" )) + { + pProtag->pszHUDAnims = AllocateString( pSubKey->GetString() ); + } #else //---------------------------------------------------------------------------- // Playermodel @@ -169,7 +184,6 @@ void CProtagonistSystem::LoadProtagonistFile( const char *pszFile ) { pProtag->pszResponseContexts = AllocateString( pSubKey->GetString() ); } - //---------------------------------------------------------------------------- // Multiplayer //---------------------------------------------------------------------------- @@ -192,6 +206,17 @@ void CProtagonistSystem::LoadProtagonistFile( const char *pszFile ) } } #endif + //---------------------------------------------------------------------------- + // Sounds + //---------------------------------------------------------------------------- + else if (FStrEq( pszSubKeyName, "sounds" )) + { + FOR_EACH_SUBKEY( pSubKey, pSoundKey ) + { + int iStringIdx = AllocateStringIdx( pSoundKey->GetString() ); + pProtag->dictSoundOverrides.Insert( pSoundKey->GetName(), iStringIdx ); + } + } //---------------------------------------------------------------------------- // Weapon Data //---------------------------------------------------------------------------- @@ -210,6 +235,17 @@ void CProtagonistSystem::LoadProtagonistFile( const char *pszFile ) pProtag->dictWpnData[i].bUsesHands = bHands; } } + else if (V_strnicmp( pszSubKeyName, "wpn_printnames", 14 ) == 0) + { + FOR_EACH_SUBKEY( pSubKey, pWeaponKey ) + { + int i = pProtag->dictWpnData.Find( pWeaponKey->GetName() ); + if (i == pProtag->dictWpnData.InvalidIndex()) + i = pProtag->dictWpnData.Insert( pWeaponKey->GetName() ); + + pProtag->dictWpnData[i].pszPrintName = AllocateString( pWeaponKey->GetString() ); + } + } else if (FStrEq( pszSubKeyName, "wpn_data" )) // More expanded/explicit { FOR_EACH_SUBKEY( pSubKey, pWeaponKey ) @@ -218,6 +254,10 @@ void CProtagonistSystem::LoadProtagonistFile( const char *pszFile ) if (i == pProtag->dictWpnData.InvalidIndex()) i = pProtag->dictWpnData.Insert( pWeaponKey->GetName() ); + const char *pszPrintName = pWeaponKey->GetString( "printname", NULL ); + if (pszPrintName) + pProtag->dictWpnData[i].pszPrintName = AllocateString( pszPrintName ); + const char *pszVM = pWeaponKey->GetString( "viewmodel", NULL ); if (pszVM) pProtag->dictWpnData[i].pszVM = AllocateString( pszVM ); @@ -329,7 +369,6 @@ const char *CProtagonistSystem::FindProtagonistByModel( const char *pszModelName void CProtagonistSystem::PrecacheProtagonist( CBaseEntity *pSource, int nIdx ) { -#ifndef CLIENT_DLL if (nIdx < 0) return; @@ -341,6 +380,7 @@ void CProtagonistSystem::PrecacheProtagonist( CBaseEntity *pSource, int nIdx ) CBaseEntity::SetAllowPrecache( true ); +#ifndef CLIENT_DLL // Playermodel if (pProtag.pszPlayerModel) { @@ -364,8 +404,13 @@ void CProtagonistSystem::PrecacheProtagonist( CBaseEntity *pSource, int nIdx ) pSource->PrecacheModel( pProtag.dictWpnData[i].pszVM ); } } +#endif - CBaseEntity::SetAllowPrecache( false ); + // Sounds/Responses + FOR_EACH_DICT_FAST( pProtag.dictSoundOverrides, i ) + { + pSource->PrecacheScriptSound( m_Strings[pProtag.dictSoundOverrides[i]] ); + } // Precache parents FOR_EACH_VEC( pProtag.vecParents, i ) @@ -373,8 +418,9 @@ void CProtagonistSystem::PrecacheProtagonist( CBaseEntity *pSource, int nIdx ) PrecacheProtagonist( pSource, pProtag.vecParents[i] ); } + CBaseEntity::SetAllowPrecache( false ); + pProtag.bPrecached = true; -#endif } //---------------------------------------------------------------------------- @@ -418,6 +464,9 @@ type CProtagonistSystem::GetProtagonist_##name( const int nProtagonistIndex, ##_ } \ #ifdef CLIENT_DLL +GetProtagParam( ClientScheme, const char*, GetProtagParamInner( ClientScheme ) ) +GetProtagParam( HUDLayout, const char*, GetProtagParamInner( HUDLayout ) ) +GetProtagParam( HUDAnims, const char*, GetProtagParamInner( HUDAnims ) ) #else GetProtagParam( PlayerModel, const char*, GetProtagParamInner( PlayerModel ) ) GetProtagParam( PlayerModelSkin, int, GetProtagParamInner( PlayerModelSkin ) ) @@ -438,7 +487,9 @@ GetProtagParamBody( ResponseContexts, bool, GetProtagParamInner( ResponseConte }, char *pszContexts, int nContextsSize ) GetProtagParam( Team, int, GetProtagParamInner( Team ) ) #endif +GetProtagParam( SoundOverride, const char*, GetProtagParamInner( SoundOverride, pszSound ), const char *pszSound ) +GetProtagParam( PrintName, const char*, GetProtagParamInner( PrintName, pWeapon ), const CBaseCombatWeapon *pWeapon ) GetProtagParam( ViewModel, const char*, GetProtagParamInner( ViewModel, pWeapon ), const CBaseCombatWeapon *pWeapon ) GetProtagParam( ViewModelFOV, float*, GetProtagParamInner( ViewModelFOV, pWeapon ), const CBaseCombatWeapon *pWeapon ) GetProtagParam( UsesHands, bool*, GetProtagParamInner( UsesHands, pWeapon ), const CBaseCombatWeapon *pWeapon ) @@ -467,6 +518,38 @@ GetProtagParam( HandRig, int*, GetProtagParamInner( HandRig, pWeapon ), cons } \ #ifdef CLIENT_DLL +const char *CProtagonistSystem::DoGetProtagonist_ClientScheme( ProtagonistData_t &pProtag ) +{ + if (pProtag.pszClientScheme) + return pProtag.pszClientScheme; + + // Recursively search parent protagonists + GetProtagonistRecurse( DoGetProtagonist_ClientScheme ) + + return NULL; +} + +const char *CProtagonistSystem::DoGetProtagonist_HUDLayout( ProtagonistData_t &pProtag ) +{ + if (pProtag.pszHUDLayout) + return pProtag.pszHUDLayout; + + // Recursively search parent protagonists + GetProtagonistRecurse( DoGetProtagonist_HUDLayout ) + + return NULL; +} + +const char *CProtagonistSystem::DoGetProtagonist_HUDAnims( ProtagonistData_t &pProtag ) +{ + if (pProtag.pszHUDAnims) + return pProtag.pszHUDAnims; + + // Recursively search parent protagonists + GetProtagonistRecurse( DoGetProtagonist_HUDAnims ) + + return NULL; +} #else const char *CProtagonistSystem::DoGetProtagonist_PlayerModel( ProtagonistData_t &pProtag ) { @@ -561,6 +644,41 @@ int CProtagonistSystem::DoGetProtagonist_Team( ProtagonistData_t &pProtag ) } #endif +const char *CProtagonistSystem::DoGetProtagonist_SoundOverride( ProtagonistData_t &pProtag, const char *pszSound ) +{ + FOR_EACH_DICT_FAST( pProtag.dictSoundOverrides, i ) + { + if ( !FStrEq( pProtag.dictSoundOverrides.GetElementName( i ), pszSound ) ) + continue; + + return m_Strings[pProtag.dictSoundOverrides[i]]; + } + + // Recursively search parent protagonists + GetProtagonistRecurse( DoGetProtagonist_SoundOverride, pszSound ) + + return NULL; +} + +const char *CProtagonistSystem::DoGetProtagonist_PrintName( ProtagonistData_t &pProtag, const CBaseCombatWeapon *pWeapon ) +{ + FOR_EACH_DICT_FAST( pProtag.dictWpnData, i ) + { + // HACKHACK: GetClassname is not const + if (!FStrEq( pProtag.dictWpnData.GetElementName( i ), const_cast(pWeapon)->GetClassname() )) + continue; + + if (pProtag.dictWpnData[i].pszPrintName) + return pProtag.dictWpnData[i].pszPrintName; + break; + } + + // Recursively search parent protagonists + GetProtagonistRecurse( DoGetProtagonist_PrintName, pWeapon ) + + return NULL; +} + const char *CProtagonistSystem::DoGetProtagonist_ViewModel( ProtagonistData_t &pProtag, const CBaseCombatWeapon *pWeapon ) { FOR_EACH_DICT_FAST( pProtag.dictWpnData, i ) @@ -605,7 +723,11 @@ bool *CProtagonistSystem::DoGetProtagonist_UsesHands( ProtagonistData_t &pProtag if (!FStrEq( pProtag.dictWpnData.GetElementName( i ), const_cast(pWeapon)->GetClassname() )) continue; - return &pProtag.dictWpnData[i].bUsesHands; + // Only return if we have a viewmodel specified + // (covers derived classes which have weapon data but only parents have VM) + if (pProtag.dictWpnData[i].pszVM) + return &pProtag.dictWpnData[i].bUsesHands; + break; } // Recursively search parent protagonists @@ -622,7 +744,11 @@ int *CProtagonistSystem::DoGetProtagonist_HandRig( ProtagonistData_t &pProtag, c if (!FStrEq( pProtag.dictWpnData.GetElementName( i ), const_cast(pWeapon)->GetClassname() )) continue; - return &pProtag.dictWpnData[i].nHandRig; + // Only return if we have a viewmodel specified + // (covers derived classes which have weapon data but only parents have VM) + if (pProtag.dictWpnData[i].pszVM) + return &pProtag.dictWpnData[i].nHandRig; + break; } // Recursively search parent protagonists @@ -655,6 +781,22 @@ const char *CProtagonistSystem::AllocateString( const char *string ) return m_Strings[m_Strings.Insert( out )]; } +int CProtagonistSystem::AllocateStringIdx( const char *string ) +{ + int i = m_Strings.Find( string ); + if (i != m_Strings.InvalidIndex()) + { + return i; + } + + int len = Q_strlen( string ); + char *out = new char[len + 1]; + Q_memcpy( out, string, len ); + out[len] = 0; + + return m_Strings.Insert( out ); +} + //---------------------------------------------------------------------------- void CProtagonistSystem::PurgeProtagonists() @@ -705,7 +847,14 @@ void CProtagonistSystem::PrintProtagonistData() { extern const char *pHandRigs[NUM_HAND_RIG_TYPES]; if (pProtag.pszHandModels[j]) - Msg( "\t\tHand %s model: \"%s\" (%i, %i)\n", pHandRigs[j], pProtag.pszHandModels[j], pProtag.nPlayerSkin, pProtag.nPlayerBody ); + Msg( "\t\tHand %s model: \"%s\" (%i, %i)\n", pHandRigs[j], pProtag.pszHandModels[j], pProtag.nHandSkin, pProtag.nHandBody ); + } + + // Sounds + Msg( "\t\tSound Overrides: %i\n", pProtag.dictSoundOverrides.Count() ); + FOR_EACH_DICT_FAST( pProtag.dictSoundOverrides, j ) + { + Msg( "\t\t\t%s -> %s\n", pProtag.dictSoundOverrides.GetElementName( j ), m_Strings[ pProtag.dictSoundOverrides.Element( j ) ] ); } // Weapon Data diff --git a/sp/src/game/shared/mapbase/protagonist_system.h b/sp/src/game/shared/mapbase/protagonist_system.h index e678bc90baf..997d0fd1e00 100644 --- a/sp/src/game/shared/mapbase/protagonist_system.h +++ b/sp/src/game/shared/mapbase/protagonist_system.h @@ -45,6 +45,10 @@ class CProtagonistSystem : public CAutoGameSystem CUtlVector vecParents; #ifdef CLIENT_DLL + // User Interface + const char *pszClientScheme = NULL; + const char *pszHUDLayout = NULL; + const char *pszHUDAnims = NULL; #else // Playermodel const char *pszPlayerModel = NULL; @@ -61,14 +65,18 @@ class CProtagonistSystem : public CAutoGameSystem // Multiplayer int nTeam = TEAM_ANY; +#endif + + // Sounds + CUtlDict dictSoundOverrides; // Indices to m_Strings // Precached (used by system, not actual data) bool bPrecached = false; -#endif // Weapon Data struct WeaponDataOverride_t { + const char *pszPrintName = NULL; const char *pszVM = NULL; bool bUsesHands = false; int nHandRig = 0; @@ -107,6 +115,9 @@ class CProtagonistSystem : public CAutoGameSystem public: \ #ifdef CLIENT_DLL + DeclareProtagonistFunc( const char*, ClientScheme ) + DeclareProtagonistFunc( const char*, HUDLayout ) + DeclareProtagonistFunc( const char*, HUDAnims ) #else DeclareProtagonistFunc( const char*, PlayerModel ) DeclareProtagonistFunc( int, PlayerModelSkin ) @@ -117,7 +128,9 @@ class CProtagonistSystem : public CAutoGameSystem DeclareProtagonistFunc( bool, ResponseContexts, char *pszContexts, int nContextsSize ) DeclareProtagonistFunc( int, Team ) #endif + DeclareProtagonistFunc( const char*, SoundOverride, const char *pszSound ) + DeclareProtagonistFunc( const char*, PrintName, const CBaseCombatWeapon *pWeapon ) DeclareProtagonistFunc( const char*, ViewModel, const CBaseCombatWeapon *pWeapon ) DeclareProtagonistFunc( float*, ViewModelFOV, const CBaseCombatWeapon *pWeapon ) DeclareProtagonistFunc( bool*, UsesHands, const CBaseCombatWeapon *pWeapon ) @@ -140,6 +153,7 @@ class CProtagonistSystem : public CAutoGameSystem const char *FindString( const char *string ); const char *AllocateString( const char *string ); + int AllocateStringIdx( const char *string ); //---------------------------------------------------------------------------- diff --git a/sp/src/public/vgui_controls/Panel.h b/sp/src/public/vgui_controls/Panel.h index 99f8e22390d..0698081dc51 100644 --- a/sp/src/public/vgui_controls/Panel.h +++ b/sp/src/public/vgui_controls/Panel.h @@ -356,6 +356,12 @@ class Panel : public IClientPanel, public virtual IForceVirtualInheritancePanel // records the settings into the resource data virtual void GetSettings(KeyValues *outResourceData); +#ifdef MAPBASE + // Apply default settings (for when scheme is being changed) + virtual void SetApplyDefaultSettings( bool state ); + virtual bool IsApplyDefaultSettingsSet(); +#endif + // gets a description of the resource for use in the UI // format: ... // unknown types as just displayed as strings in the UI (for future UI expansion) diff --git a/sp/src/vgui2/vgui_controls/Panel.cpp b/sp/src/vgui2/vgui_controls/Panel.cpp index dd49f97a3a1..d5ed5b1a4f5 100644 --- a/sp/src/vgui2/vgui_controls/Panel.cpp +++ b/sp/src/vgui2/vgui_controls/Panel.cpp @@ -64,13 +64,6 @@ static char *CopyString( const char *in ) return n; } -#ifdef MAPBASE -ConVar vgui_mapbase_custom_schemes( "vgui_mapbase_custom_schemes", "1" ); - -// This is used in mapbase_shared.cpp -HScheme g_iCustomClientSchemeOverride; -#endif - #if defined( VGUI_USEDRAGDROP ) //----------------------------------------------------------------------------- // Purpose: @@ -1634,15 +1627,6 @@ HScheme Panel::GetScheme() iScheme = scheme()->GetDefaultScheme(); } -#ifdef MAPBASE - // If a custom client scheme is available, use the custom scheme. - // TODO: Need a better way to detect that this panel actually uses ClientScheme.res - if (g_iCustomClientSchemeOverride != 0 && iScheme == scheme()->GetScheme( "ClientScheme" ) && vgui_mapbase_custom_schemes.GetBool()) - { - return g_iCustomClientSchemeOverride; - } -#endif - return iScheme; } @@ -4828,6 +4812,34 @@ void Panel::GetSettings( KeyValues *outResourceData ) } } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Panel::SetApplyDefaultSettings( bool state ) +{ + _flags.SetFlag( NEEDS_DEFAULT_SETTINGS_APPLIED, state ); + + for (int i = 0; i < GetChildCount(); i++) + { + vgui::Panel* panel = GetChild(i); + if ( panel ) + { + panel->SetApplyDefaultSettings( state ); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool Panel::IsApplyDefaultSettingsSet() +{ + return _flags.IsFlagSet( NEEDS_DEFAULT_SETTINGS_APPLIED ); +} +#endif + //----------------------------------------------------------------------------- // Purpose: After applying settings, apply overridable colors. // Done post apply settings, so that baseclass settings don't stomp