summaryrefslogtreecommitdiff
path: root/game/client/tf/vgui/tf_warinfopanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/tf/vgui/tf_warinfopanel.cpp')
-rw-r--r--game/client/tf/vgui/tf_warinfopanel.cpp532
1 files changed, 532 insertions, 0 deletions
diff --git a/game/client/tf/vgui/tf_warinfopanel.cpp b/game/client/tf/vgui/tf_warinfopanel.cpp
new file mode 100644
index 0000000..2458bff
--- /dev/null
+++ b/game/client/tf/vgui/tf_warinfopanel.cpp
@@ -0,0 +1,532 @@
+#include "cbase.h"
+#include "tf_warinfopanel.h"
+#include "econ_controls.h"
+#include "econ_item_inventory.h"
+#include "vgui_avatarimage.h"
+#include "vgui_controls/ProgressBar.h"
+#include <vgui_controls/HTML.h>
+#include "c_tf_player.h"
+#include "econ_ui.h"
+#include "tf_asyncpanel.h"
+#include "item_model_panel.h"
+#include "tf_wardata.h"
+#include "iclientmode.h"
+#include <vgui_controls/AnimationController.h>
+#include "vgui/ISystem.h"
+
+#ifdef STAGING_ONLY
+ConVar tf_war_override_active_state( "tf_war_override_active_state", "-1" );
+#endif
+
+bool IsWarActive( war_definition_index_t nDefIndex )
+{
+#ifdef STAGING_ONLY
+ if ( tf_war_override_active_state.GetInt() != -1 )
+ {
+ if ( tf_war_override_active_state.GetInt() == 0 )
+ return false;
+
+ return true;
+ }
+#endif
+
+ const CWarDefinition* pWarDef = GetItemSchema()->GetWarDefinitionByIndex( nDefIndex );
+ Assert( pWarDef );
+ if ( !pWarDef )
+ return false;
+
+ return pWarDef->IsActive();
+}
+
+template < typename T >
+void SetNestedDialogVariable( Panel *pRoot, const char *pszPanel, const char *pszVariable, T val )
+{
+ EditablePanel *pPanel = pRoot->FindControl<EditablePanel>( pszPanel, true );
+ if ( pPanel )
+ {
+ pPanel->SetDialogVariable( pszVariable, val );
+ }
+}
+
+DECLARE_BUILD_FACTORY( CWarStandingPanel );
+CWarStandingPanel::CWarStandingPanel( Panel* pParent, const char* pszPanelName )
+ : BaseClass( pParent, pszPanelName )
+ , m_flLastUpdateTime( 0.f )
+ , m_pTeam0ProgressBar( NULL )
+ , m_pTeam1ProgressBar( NULL )
+ , m_bNeedsLerp( false )
+{
+ ListenForGameEvent( "global_war_data_updated" );
+}
+
+void CWarStandingPanel::ApplySchemeSettings( IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+ LoadControlSettings( "Resource/UI/econ/WarStandingPanel.res" );
+
+ for( int i=0; i<2; ++i )
+ {
+ m_Scores[i].m_pTeamProgressBar = FindControl< ContinuousProgressBar >( CFmtStr( "Team%dProgressBar", i ), true );
+ m_Scores[i].m_pContainerPanel = FindControl< EditablePanel >( CFmtStr( "Team%dContainer", i ), true );
+ m_Scores[i].m_pScoreLabel = FindControl< CExLabel >( CFmtStr( "Team%dScore", i ), true );
+ m_Scores[i].m_pTeamLabel = FindControl< CExLabel >( CFmtStr( "Team%dName", i ), true );
+ }
+}
+
+void CWarStandingPanel::ApplySettings( KeyValues *inResourceData )
+{
+ BaseClass::ApplySettings( inResourceData );
+
+ m_strWarName = inResourceData->GetString( "war_name", NULL );
+}
+
+void CWarStandingPanel::OnThink()
+{
+ BaseClass::OnThink();
+
+ if ( Plat_FloatTime() - m_flLastUpdateTime > 30.f )
+ {
+ InvalidateLayout();
+ }
+
+ if ( m_bNeedsLerp )
+ {
+ int nTotal = 0;
+ if ( m_Scores[ 0 ].m_nNewScore != 0 || m_Scores[ 1 ].m_nNewScore != 0 )
+ {
+ nTotal = m_Scores[ 0 ].m_nNewScore + m_Scores[ 1 ].m_nNewScore;
+ }
+
+ float flPercent = GetPercentAnimated();
+
+ for( int i=0; i<2; ++i )
+ {
+ // Lerp flPercent from [0,1] -> [StartScore,EndScore]
+ float flCurrentScore = RemapValClamped( flPercent, 0.f, 1.f, (float)m_Scores[i].m_nLastScore, (float)m_Scores[i].m_nNewScore );
+
+ float flProgressPercent = 0.f;
+ if ( nTotal != 0 )
+ {
+ flProgressPercent = flCurrentScore / (float)nTotal;
+ }
+
+ m_Scores[i].m_pTeamProgressBar->SetProgress( flProgressPercent );
+ m_Scores[i].m_pContainerPanel->SetDialogVariable( CFmtStr( "team%dscore", i ), CFmtStr( "%.0f%%", flProgressPercent * 100.f ) );
+
+ int nScoreXpos = RemapValClamped( flProgressPercent
+ , 0.f
+ , 1.f
+ , m_Scores[i].m_pTeamProgressBar->GetXPos()
+ , m_Scores[i].m_pTeamProgressBar->GetXPos() + m_Scores[i].m_pTeamProgressBar->GetWide() );
+
+ m_Scores[i].m_pScoreLabel->SetPos( nScoreXpos, m_Scores[i].m_pScoreLabel->GetYPos() );
+ }
+
+ if ( flPercent == 1.f )
+ {
+ m_bNeedsLerp = false;
+ }
+ }
+}
+
+void CWarStandingPanel::PerformLayout()
+{
+ BaseClass::PerformLayout();
+
+ if ( GetPercentAnimated() == 1.f )
+ {
+ m_flLastUpdateTime = Plat_FloatTime();
+ }
+
+ const CWarDefinition* pWarDef = GetItemSchema()->GetWarDefinitionByName( m_strWarName );
+ Assert( pWarDef->GetSides().Count() == 2 ); // Needs to be 2 sides to the war for this panel to work!
+ CWarData *pWarData = GetLocalPlayerWarData( pWarDef->GetDefIndex() );
+ war_side_t nAffiliation = INVALID_WAR_SIDE;
+ if ( pWarData )
+ {
+ nAffiliation = pWarData->Obj().affiliation();
+ }
+
+ FOR_EACH_MAP_FAST( pWarDef->GetSides(), i )
+ {
+ uint64 nScore = nScore = GetWarData().GetGlobalSideScore( pWarDef->GetDefIndex(), pWarDef->GetSide( i )->m_nSideIndex );
+
+ m_Scores[ i ].m_nLastScore = m_Scores[ i ].m_nNewScore;
+ m_Scores[ i ].m_nNewScore = nScore;
+
+ if ( m_Scores[ i ].m_pTeamLabel )
+ {
+ m_Scores[ i ].m_pTeamLabel->SetText( pWarDef->GetSide( i )->m_pszLocalizedName );
+ }
+
+ // Check if there's a change to show
+ m_bNeedsLerp |= m_Scores[ i ].m_nLastScore != m_Scores[ i ].m_nNewScore;
+
+ if ( !m_bNeedsLerp )
+ {
+ m_Scores[i].m_pContainerPanel->SetDialogVariable( CFmtStr( "team%dscore", i ), CFmtStr( "%.0f%%", m_Scores[i].m_pTeamProgressBar->GetProgress() * 100.f ) );
+ }
+
+ // Set the "(Your side)" labels
+ SetControlVisible( CFmtStr( "Team%dYourSide", i ), i == nAffiliation, true );
+ }
+}
+
+float CWarStandingPanel::GetPercentAnimated() const
+{
+ float flTimeSinceLastUpdate = Plat_FloatTime() - m_flLastUpdateTime;
+ float flPercent = Bias( RemapValClamped( flTimeSinceLastUpdate, 0.f, 1.2f, 0.f, 1.f ), 0.8f );
+ return flPercent;
+}
+
+void CWarStandingPanel::FireGameEvent( IGameEvent *event )
+{
+ if ( FStrEq( event->GetName(), "global_war_data_updated" ) )
+ {
+ InvalidateLayout();
+ }
+}
+
+
+DECLARE_BUILD_FACTORY( CWarLandingPanel );
+
+CWarLandingPanel::CWarLandingPanel( Panel *pParent, const char *pszPanelName )
+ : BaseClass( pParent, pszPanelName )
+ , m_flChoseTeamTime( 0.f )
+ , m_nLastKnownSide( INVALID_WAR_SIDE )
+ , m_nPendingSide( INVALID_WAR_SIDE )
+ , m_eJoiningState( NO_ACTION )
+{
+}
+
+void CWarLandingPanel::ApplySchemeSettings( IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ KeyValues* pKVConditions = new KeyValues( "conditions" );
+
+ if ( IsWarActive( PYRO_VS_HEAVY_WAR_DEF_INDEX ) )
+ {
+ pKVConditions->AddSubKey( new KeyValues( "if_war_active" ) );
+ }
+ else
+ {
+ pKVConditions->AddSubKey( new KeyValues( "if_war_over" ) );
+ }
+
+ LoadControlSettings( "Resource/UI/econ/WarJoinPanel.res", NULL, NULL, pKVConditions );
+}
+
+void CWarLandingPanel::ApplySettings( KeyValues *inResourceData )
+{
+ BaseClass::ApplySettings( inResourceData );
+
+ m_strSceneAnimName = inResourceData->GetString( "scene_anim_name", NULL );
+ Assert( m_strSceneAnimName.Length() );
+}
+
+void CWarLandingPanel::OnCommand( const char *pCommand )
+{
+ if ( FStrEq( pCommand, "close" ) )
+ {
+ if ( m_eJoiningState == NO_ACTION )
+ {
+ SetVisible( false );
+ }
+ }
+ else if ( V_strncasecmp( pCommand, "join_war", V_strlen( "join_war" ) ) == 0 )
+ {
+ int nSide = V_atoi( &pCommand[ V_strlen( "join_war" ) ] );
+
+ const CWarDefinition* pWarDef = GetItemSchema()->GetWarDefinitionByIndex( PYRO_VS_HEAVY_WAR_DEF_INDEX );
+
+ if ( !IsWarActive( PYRO_VS_HEAVY_WAR_DEF_INDEX ) )
+ {
+ DevMsg( "War is inactive" );
+ return;
+ }
+
+ if ( !pWarDef->IsValidSide( nSide ) )
+ {
+ DevMsg( "%d is not a valid side", nSide );
+ return;
+ }
+
+ m_nPendingSide = nSide;
+ Assert( m_eJoiningState == NO_ACTION );
+ m_eJoiningState = CONFIRM_SIDE_SELECTION;
+
+ UpdateUIState();
+ return;
+ }
+ else if ( FStrEq( pCommand, "confirm_team" ) )
+ {
+ if ( !IsWarActive( PYRO_VS_HEAVY_WAR_DEF_INDEX ) )
+ {
+ DevMsg( "War is inactive" );
+ return;
+ }
+
+ // Join the war!
+ GCSDK::CProtoBufMsg< CGCMsgGC_War_JoinWar > msg( k_EMsgGC_War_JoinWar );
+
+ msg.Body().set_affiliation( m_nPendingSide );
+ msg.Body().set_war_id( PYRO_VS_HEAVY_WAR_DEF_INDEX );
+
+ GCClientSystem()->BSendMessage( msg );
+ m_flChoseTeamTime = Plat_FloatTime();
+ m_eJoiningState = ATTEMPTING_TO_JOIN_AND_WAITING_FOR_RESPONSE;
+
+ UpdateUIState();
+ return;
+ }
+ else if ( FStrEq( pCommand, "dismiss_joining_result" ) )
+ {
+ m_eJoiningState = NO_ACTION;
+ m_nPendingSide = INVALID_WAR_SIDE;
+ UpdateUIState();
+
+ return;
+ }
+ else if ( FStrEq( "view_update_comic", pCommand ) )
+ {
+ const char* pszComicURL = "http://www.teamfortress.com/theshowdown/";
+
+ if ( steamapicontext && steamapicontext->SteamFriends() && steamapicontext->SteamUtils() && steamapicontext->SteamUtils()->IsOverlayEnabled() )
+ {
+ steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( pszComicURL );
+ }
+ else
+ {
+ vgui::system()->ShellExecute( "open", pszComicURL );
+ }
+
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+void CWarLandingPanel::OnThink()
+{
+ BaseClass::OnThink();
+
+ if ( ( Plat_FloatTime() - m_flChoseTeamTime ) > 5.f && m_eJoiningState == ATTEMPTING_TO_JOIN_AND_WAITING_FOR_RESPONSE )
+ {
+ m_eJoiningState = FAILED_RESPONSE_RECIEVED_WAITING_FOR_USER_CONFIRMATION;
+ UpdateUIState();
+ }
+}
+
+#ifdef STAGING_ONLY
+// 12345? Yea, well, we probably will never have 12,345 sides to a war
+ConVar tf_fake_war_side( "tf_fake_war_side", "12345" );
+#endif
+
+void CWarLandingPanel::PerformLayout()
+{
+ BaseClass::PerformLayout();
+
+#ifdef STAGING_ONLY
+ if ( tf_fake_war_side.GetInt() != 12345 )
+ {
+ m_nLastKnownSide = tf_fake_war_side.GetInt();
+ }
+#endif
+
+ UpdateUIState();
+}
+
+
+void CWarLandingPanel::UpdateWarStatus( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent )
+{
+ if ( pObject->GetTypeID() != CWarData::k_nTypeID )
+ {
+ return;
+ }
+
+ if ( !steamapicontext || !steamapicontext->SteamUser() )
+ {
+ return;
+ }
+
+ // Make sure this is for us
+ CSteamID steamID = steamapicontext->SteamUser()->GetSteamID();
+ if ( steamIDOwner != steamID )
+ {
+ return;
+ }
+
+ const CWarData* pWarData = assert_cast< const CWarData* >( pObject );
+ if ( pWarData->Obj().affiliation() != m_nLastKnownSide )
+ {
+ if ( m_eJoiningState == ATTEMPTING_TO_JOIN_AND_WAITING_FOR_RESPONSE )
+ {
+ m_eJoiningState = SUCCESS_RESPONSE_RECIEVED_WAITING_FOR_USER_CONFIRMATION;
+ }
+
+ m_nLastKnownSide = pWarData->Obj().affiliation();
+ }
+
+ UpdateUIState();
+}
+
+void CWarLandingPanel::SetVisible( bool bVisible )
+{
+ BaseClass::SetVisible( bVisible );
+
+ EditablePanel* pSceneContainer = FindControl< EditablePanel >( "SceneContainer", true );
+ if ( pSceneContainer )
+ {
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pSceneContainer, m_strSceneAnimName, false );
+ }
+}
+
+void CWarLandingPanel::UpdateUIState()
+{
+ const CWarDefinition* pWarDef = GetItemSchema()->GetWarDefinitionByIndex( PYRO_VS_HEAVY_WAR_DEF_INDEX ); // SLAM
+ if ( !pWarDef )
+ return;
+
+ EditablePanel* pMainContainer = FindControl< EditablePanel >( "MainContainer" );
+ if ( pMainContainer )
+ {
+ bool bWarActive = IsWarActive( PYRO_VS_HEAVY_WAR_DEF_INDEX );
+ pMainContainer->SetControlVisible( "WarOverContainer", !bWarActive );
+
+ bool bNeedsToJoin = m_nLastKnownSide == INVALID_WAR_SIDE;
+ pMainContainer->SetControlVisible( "AffiliatedContainer", bWarActive && !bNeedsToJoin && m_eJoiningState == NO_ACTION );
+ pMainContainer->SetControlVisible( "UnaffiliatedContainer", bWarActive && bNeedsToJoin && m_eJoiningState == NO_ACTION );
+
+ bool bHasGCConnection = GCClientSystem()->BConnectedtoGC();
+ pMainContainer->SetControlVisible( "JoinPyroButton", bHasGCConnection, true );
+ pMainContainer->SetControlVisible( "JoinHeavyButton", bHasGCConnection, true );
+ pMainContainer->SetControlVisible( "NoGContainer", !bHasGCConnection, true );
+ }
+
+ static wchar_t wszEndDateOutString[ 128 ];
+ char time_buf[k_RTimeRenderBufferSize];
+ CRTime timeExpire( pWarDef->GetEndDate() );
+ timeExpire.SetToGMT( false );
+ timeExpire.Render( time_buf );
+ wchar_t wszTemp[ 1024 ];
+ V_UTF8ToUnicode( time_buf, wszTemp, sizeof(wszTemp) );
+
+ const wchar_t *wpszEndDateFormat = g_pVGuiLocalize->Find( IsWarActive( PYRO_VS_HEAVY_WAR_DEF_INDEX ) ? "#TF_War_EndFutureDate" : "#TF_War_EndPastDate" );
+
+ g_pVGuiLocalize->ConstructString_safe( wszEndDateOutString, wpszEndDateFormat, 1, wszTemp );
+ CExLabel* pSceneContainer = FindControl< CExLabel >( "EndDateLabel", true );
+ if ( pSceneContainer )
+ {
+ pSceneContainer->SetText( wszEndDateOutString );
+ }
+
+
+ EditablePanel* pJoiningPopup = FindControl< EditablePanel >( "CommunicatingWithGCPopup", true );
+ if ( !pJoiningPopup )
+ return;
+
+ switch ( m_eJoiningState )
+ {
+ case NO_ACTION:
+ break;
+ case CONFIRM_SIDE_SELECTION:
+ {
+ Assert( m_nPendingSide != INVALID_WAR_SIDE );
+ const CWarDefinition::CWarSideDefinition_t* pChosenSide = pWarDef->GetSide( m_nPendingSide ); // Can be NULL
+ Assert( pChosenSide );
+ if ( !pChosenSide )
+ return;
+
+ static wchar_t wszOutString[ 128 ];
+ const wchar_t *wpszFormat = g_pVGuiLocalize->Find( "#TF_War_ConfirmSideSelection" );
+ g_pVGuiLocalize->ConstructString_safe( wszOutString, wpszFormat, 1, g_pVGuiLocalize->Find( pChosenSide->m_pszLocalizedName ) );
+
+ EditablePanel* pJoining = FindControl< EditablePanel >( "ConfirmSelectionContainer", true );
+ if ( pJoining )
+ {
+ pJoining->SetDialogVariable( "confirm_selection", wszOutString );
+ }
+ }
+ break;
+ case ATTEMPTING_TO_JOIN_AND_WAITING_FOR_RESPONSE:
+ {
+ Assert( m_nPendingSide != INVALID_WAR_SIDE );
+ const CWarDefinition::CWarSideDefinition_t* pChosenSide = pWarDef->GetSide( m_nPendingSide ); // Can be NULL
+ Assert( pChosenSide );
+ if ( !pChosenSide )
+ return;
+
+ static wchar_t wszOutString[ 128 ];
+ const wchar_t *wpszFormat = g_pVGuiLocalize->Find( "#TF_War_JoiningTeam" );
+ g_pVGuiLocalize->ConstructString_safe( wszOutString, wpszFormat, 1, g_pVGuiLocalize->Find( pChosenSide->m_pszLocalizedName ) );
+
+ EditablePanel* pJoining = FindControl< EditablePanel >( "JoiningContainer", true );
+ if ( pJoining )
+ {
+ pJoining->SetDialogVariable( "joining_team", wszOutString );
+ }
+ }
+
+ break;
+
+ case SUCCESS_RESPONSE_RECIEVED_WAITING_FOR_USER_CONFIRMATION:
+ {
+ const CWarDefinition::CWarSideDefinition_t* pChosenSide = pWarDef->GetSide( m_nLastKnownSide ); // Can be NULL
+ Assert( pChosenSide );
+ if ( !pChosenSide )
+ return;
+
+ static wchar_t wszOutString[ 128 ];
+ const wchar_t *wpszFormat = g_pVGuiLocalize->Find( "#TF_War_JoinedTeam" );
+ g_pVGuiLocalize->ConstructString_safe( wszOutString, wpszFormat, 1, g_pVGuiLocalize->Find( pChosenSide->m_pszLocalizedName ) );
+ EditablePanel* pJoined = FindControl< EditablePanel >( "TeamJoinedContainer", true );
+ if ( pJoined )
+ {
+ pJoined->SetDialogVariable( "team_joined", wszOutString );
+ }
+ }
+ break;
+
+ case FAILED_RESPONSE_RECIEVED_WAITING_FOR_USER_CONFIRMATION:
+
+ break;
+
+ default:
+ Assert( false );
+ return;
+ }
+
+ pJoiningPopup->SetVisible( m_eJoiningState != NO_ACTION );
+
+ pJoiningPopup->SetControlVisible( "ConfirmSelectionContainer", m_eJoiningState == CONFIRM_SIDE_SELECTION, true );
+ pJoiningPopup->SetControlVisible( "JoiningContainer", m_eJoiningState == ATTEMPTING_TO_JOIN_AND_WAITING_FOR_RESPONSE, true );
+ pJoiningPopup->SetControlVisible( "TeamJoinedContainer", m_eJoiningState == SUCCESS_RESPONSE_RECIEVED_WAITING_FOR_USER_CONFIRMATION, true );
+ pJoiningPopup->SetControlVisible( "FailedToJoinContainer", m_eJoiningState == FAILED_RESPONSE_RECIEVED_WAITING_FOR_USER_CONFIRMATION, true );
+}
+
+#if defined( STAGING_ONLY )
+CON_COMMAND( tf_war_join_side, "Join a specified war on a specified side" )
+{
+ if ( args.ArgC() < 2 )
+ return;
+
+ war_definition_index_t nWar = atoi( args[1] );
+ const CWarDefinition* pWarDef = GetItemSchema()->GetWarDefinitionByIndex( nWar );
+ if ( pWarDef == NULL)
+ return;
+
+ war_side_t nSide = atoi( args[2] );
+ // Allow INVALID_WAR_SIDE for testing purposes
+ if ( pWarDef->GetSide( nSide ) == NULL && nSide != INVALID_WAR_SIDE )
+ return;
+
+ // Join the war!
+ GCSDK::CProtoBufMsg< CGCMsgGC_War_JoinWar > msg( k_EMsgGC_War_JoinWar );
+
+ msg.Body().set_war_id( nWar );
+ msg.Body().set_affiliation( nSide );
+
+ GCClientSystem()->BSendMessage( msg );
+}
+#endif