diff options
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.cpp | 293 |
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 |