summaryrefslogtreecommitdiff
path: root/game/client/tf/vgui/tf_matchmaking_dashboard_next_map_voting.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/tf/vgui/tf_matchmaking_dashboard_next_map_voting.cpp')
-rw-r--r--game/client/tf/vgui/tf_matchmaking_dashboard_next_map_voting.cpp293
1 files changed, 293 insertions, 0 deletions
diff --git a/game/client/tf/vgui/tf_matchmaking_dashboard_next_map_voting.cpp b/game/client/tf/vgui/tf_matchmaking_dashboard_next_map_voting.cpp
new file mode 100644
index 0000000..e8b86ac
--- /dev/null
+++ b/game/client/tf/vgui/tf_matchmaking_dashboard_next_map_voting.cpp
@@ -0,0 +1,293 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+
+#include "cbase.h"
+#include "tf_matchmaking_dashboard.h"
+#include "tf_gamerules.h"
+#include "tf_gc_client.h"
+#include "clientmode_tf.h"
+#include <vgui_controls/AnimationController.h>
+#include <vgui_controls/CircularProgressBar.h>
+
+using namespace vgui;
+using namespace GCSDK;
+
+extern ConVar tf_mm_next_map_vote_time;
+
+#ifdef STAGING_ONLY
+extern ConVar tf_mm_popup_state_override;
+#endif
+
+#ifdef STAGING_ONLY
+CON_COMMAND( test_next_map_vote, "Fakes a player voting" )
+{
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_next_map_vote_change" );
+ if ( event )
+ {
+ event->SetInt( "map_index", RandomInt( 0, 2 ) );
+ // Client-side once it's actually happened
+ gameeventmanager->FireEventClientSide( event );
+ }
+}
+#endif
+
+class CNextMapVotingDashboardState : public CTFMatchmakingPopup
+{
+public:
+ CNextMapVotingDashboardState( const char* pszName, const char* pszResFile )
+ : CTFMatchmakingPopup( pszName, pszResFile )
+ , m_pTimerProgressBar( NULL )
+ {
+ memset( m_arMapPanels, 0, sizeof( m_arMapPanels ) );
+ ListenForGameEvent( "player_next_map_vote_change" );
+ ListenForGameEvent( "vote_maps_changed" );
+ }
+
+ virtual void ApplySchemeSettings( IScheme *pScheme )
+ {
+ CTFMatchmakingPopup::ApplySchemeSettings( pScheme );
+
+ m_pTimerProgressBar = FindControl< CircularProgressBar >( "TimeRemainingProgressBar", true );
+ if ( m_pTimerProgressBar )
+ {
+ m_pTimerProgressBar->SetProgressDirection( CircularProgressBar::PROGRESS_CCW );
+ m_pTimerProgressBar->SetFgImage( GetLocalPlayerTeam() == TF_TEAM_RED ? "progress_bar_red" : "progress_bar_blu" );
+ }
+
+ for ( int i=0; i < NEXT_MAP_VOTE_OPTIONS; ++i )
+ {
+ EditablePanel* pMapChoice = FindControl< EditablePanel >( CFmtStr( "MapChoice%d", i ), true );
+ if ( pMapChoice )
+ {
+ pMapChoice->LoadControlSettings( "resource/UI/MatchMakingDashboardPopup_MapVotePanel.res" );
+ }
+ }
+ }
+
+ virtual void PerformLayout() OVERRIDE
+ {
+ CTFMatchmakingPopup::PerformLayout();
+
+ SetMapChoiceSettings();
+ UpdateVoteCounts();
+ }
+
+ virtual void OnUpdate() OVERRIDE
+ {
+ CTFMatchmakingPopup::OnUpdate();
+
+ // Default to looping 30 sec cycle for debugging
+ float flVoteEndTime = ( 30 + ( ( int( Plat_FloatTime() ) / 30 ) * 30 ) - Plat_FloatTime() ) / 30.f;
+
+ if ( TFGameRules() )
+ {
+ // Get the actual countdown if we have gamerules
+ flVoteEndTime = ( tf_mm_next_map_vote_time.GetInt() - ( gpGlobals->curtime - TFGameRules()->GetLastRoundStateChangeTime() ) ) / tf_mm_next_map_vote_time.GetFloat();
+ }
+
+ if ( m_pTimerProgressBar )
+ {
+ m_pTimerProgressBar->SetProgress( flVoteEndTime );
+ }
+ }
+
+ virtual bool ShouldBeActve() const OVERRIDE
+ {
+#ifdef STAGING_ONLY
+ if ( FStrEq( const_cast<CNextMapVotingDashboardState*>(this)->GetName(), tf_mm_popup_state_override.GetString() ) )
+ return true;
+#endif
+
+ if ( BInEndOfMatch() &&
+ TFGameRules() &&
+ TFGameRules()->GetCurrentNextMapVotingState() == CTFGameRules::NEXT_MAP_VOTE_STATE_WAITING_FOR_USERS_TO_VOTE &&
+ GTFGCClientSystem()->BConnectedToMatchServer( false ) )
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual void OnCommand( const char *pszCommand )
+ {
+ if ( Q_strnicmp( pszCommand, "choice", 6 ) == 0 &&
+ GetPlayerVoteState() == CTFGameRules::USER_NEXT_MAP_VOTE_UNDECIDED )
+ {
+ int nIndex = atoi( pszCommand + 6 );
+ Assert( nIndex >= 0 && nIndex <= 2 );
+ if ( nIndex < 0 || nIndex > 2 )
+ return;
+
+ engine->ClientCmd( CFmtStr( "next_map_vote %d", nIndex ) );
+ }
+ }
+
+ virtual void FireGameEvent( IGameEvent *pEvent )
+ {
+ if ( FStrEq( pEvent->GetName(), "player_next_map_vote_change" ) &&
+ TFGameRules()->GetCurrentNextMapVotingState() == CTFGameRules::NEXT_MAP_VOTE_STATE_WAITING_FOR_USERS_TO_VOTE )
+ {
+ ShowVoteByOtherPlayer( pEvent->GetInt( "map_index" ) );
+ InvalidateLayout();
+ surface()->PlaySound( UTIL_GetRandomSoundFromEntry( "Vote.Cast.Yes" ) );
+
+ return;
+ }
+ else if ( FStrEq( pEvent->GetName(), "vote_maps_changed" ) )
+ {
+ InvalidateLayout( false, true );
+ }
+ }
+
+ virtual void OnEnter() OVERRIDE
+ {
+ // To get the voting options setup how they're supposed to be
+ InvalidateLayout( true, false);
+
+ CTFMatchmakingPopup::OnEnter();
+ }
+
+private:
+
+ void SetMapChoiceSettings()
+ {
+ for ( int nIndex = 0; nIndex < NEXT_MAP_VOTE_OPTIONS; ++nIndex )
+ {
+ const MapDef_t* pMapDef = NULL;
+
+ if ( TFGameRules() )
+ {
+ pMapDef = GetItemSchema()->GetMasterMapDefByIndex( TFGameRules()->GetNextMapVoteOption( nIndex ) );
+ }
+ else
+ {
+ pMapDef = GetItemSchema()->GetMasterMapDefByIndex( RandomInt( 1, GetItemSchema()->GetMapCount() - 1 ) );
+ }
+
+ Assert( pMapDef );
+ if ( !pMapDef )
+ return;
+
+ EditablePanel* pMapChoice = FindControl< EditablePanel >( CFmtStr( "MapChoice%d", nIndex ), true );
+ if ( pMapChoice )
+ {
+ ScalableImagePanel* pMapImage = pMapChoice->FindControl< ScalableImagePanel >( "MapImage", true );
+
+ // The image
+ if ( pMapImage )
+ {
+ m_arMapPanels[ nIndex ].pMapImage = pMapImage;
+ char imagename[ 512 ];
+ Q_snprintf( imagename, sizeof( imagename ), "..\\vgui\\maps\\menu_thumb_%s", pMapDef->pszMapName );
+ pMapImage->SetImage( imagename );
+ }
+
+ // Label text
+ pMapChoice->SetDialogVariable( "mapname", g_pVGuiLocalize->Find( pMapDef->pszMapNameLocKey ) );
+ m_arMapPanels[ nIndex ].pMapNameLabel = pMapChoice->FindControl< Label >( "NameLabel" );
+
+ // Fixup the button
+ Button* pButton = pMapChoice->FindControl< Button >( "SelectButton" );
+ if ( pButton )
+ {
+ m_arMapPanels[ nIndex ].pChooseButton = pButton;
+ pButton->SetCommand( CFmtStr( "choice%d", nIndex ) );
+ // Dont let people click anymore if the've already voted
+ pButton->SetEnabled( GetPlayerVoteState() == CTFGameRules::USER_NEXT_MAP_VOTE_UNDECIDED );
+ pButton->SetMouseInputEnabled( GetPlayerVoteState() == CTFGameRules::USER_NEXT_MAP_VOTE_UNDECIDED );
+
+ // Give the one the user selected a green border
+ if ( GetPlayerVoteState() == nIndex )
+ {
+ pButton->SetArmed( true );
+ pButton->MakeReadyForUse();
+ pButton->SetArmedColor( pButton->GetButtonArmedFgColor(), scheme()->GetIScheme( GetScheme() )->GetColor( "CreditsGreen", Color( 94, 150, 49, 255 ) ) );
+ }
+ }
+ }
+ }
+ }
+
+ void ShowVoteByOtherPlayer( int nIndex )
+ {
+ EditablePanel* pMapChoice = FindControl< EditablePanel >( CFmtStr( "MapChoice%d", nIndex ), true );
+ if ( pMapChoice )
+ {
+ // Play animation on the map that got voted on
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pMapChoice, "MapVoted" );
+ }
+ }
+
+ void UpdateVoteCounts()
+ {
+ int nVotes[ CTFGameRules::EUserNextMapVote::NUM_VOTE_STATES ];
+ memset( nVotes, 0, sizeof( nVotes ) );
+ int nTotalVotes = 0;
+
+ CTFGameRules::EUserNextMapVote eWinningVote = CTFGameRules::USER_NEXT_MAP_VOTE_UNDECIDED;
+ if ( TFGameRules() )
+ {
+ TFGameRules()->GetWinningVote( nVotes );
+ }
+ else
+ {
+ // For testing on the main menu
+ for ( int i=0; i < NEXT_MAP_VOTE_OPTIONS; ++i )
+ {
+ nVotes[ i ] += RandomInt( 0, 10 );
+ eWinningVote = (CTFGameRules::EUserNextMapVote)( nVotes[ i ] >= nVotes[ eWinningVote ] ? i : eWinningVote );
+ }
+ }
+
+ // Calculate the total so we can do a % breakdown
+ for ( int i=0; i < NEXT_MAP_VOTE_OPTIONS; ++i )
+ {
+ nTotalVotes += nVotes[ i ];
+ }
+
+ for ( int i=0; i < NEXT_MAP_VOTE_OPTIONS; ++i )
+ {
+ float flPercent = nTotalVotes ? (float)nVotes[ i ] / nTotalVotes * 100.f : 0.f;
+ EditablePanel* pMapChoicePanel = FindControl< EditablePanel >( CFmtStr( "MapChoice%d", i ), true );
+ if ( pMapChoicePanel )
+ {
+ // Update the label with the % total
+ pMapChoicePanel->SetDialogVariable( "votes", CFmtStr( "%3.0f%%", flPercent ) );
+ // Do a color change animation
+ if ( g_pClientMode && g_pClientMode->GetViewport() )
+ {
+ g_pClientMode->GetViewportAnimationController()->StopAnimationSequence( pMapChoicePanel, i == eWinningVote ? "LosingNextMapVote" : "WinningNextMapVote" );
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pMapChoicePanel, i == eWinningVote ? "WinningNextMapVote" : "LosingNextMapVote" );
+ }
+ }
+ }
+ }
+
+ CTFGameRules::EUserNextMapVote GetPlayerVoteState()
+ {
+ if ( TFGameRules() )
+ {
+ int nPlayerIndex = GetLocalPlayerIndex();
+ return TFGameRules()->PlayerNextMapVoteState( nPlayerIndex );
+ }
+
+ return CTFGameRules::USER_NEXT_MAP_VOTE_UNDECIDED;
+ }
+
+ CircularProgressBar* m_pTimerProgressBar;
+
+ struct MapChoice_t
+ {
+ ScalableImagePanel* pMapImage;
+ Label* pMapNameLabel;
+ Button* pChooseButton;
+ };
+ MapChoice_t m_arMapPanels[3];
+};
+
+REG_MM_POPUP_FACTORY( CNextMapVotingDashboardState, "NextMapVoting", "resource/UI/MatchMakingDashboardPopup_NextMapVoting.res" ) \ No newline at end of file