summaryrefslogtreecommitdiff
path: root/game/client/tf/vgui/tf_roundinfo.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/vgui/tf_roundinfo.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/client/tf/vgui/tf_roundinfo.cpp')
-rw-r--r--game/client/tf/vgui/tf_roundinfo.cpp623
1 files changed, 623 insertions, 0 deletions
diff --git a/game/client/tf/vgui/tf_roundinfo.cpp b/game/client/tf/vgui/tf_roundinfo.cpp
new file mode 100644
index 0000000..ccfba71
--- /dev/null
+++ b/game/client/tf/vgui/tf_roundinfo.cpp
@@ -0,0 +1,623 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+
+#include <vgui_controls/Label.h>
+#include <vgui_controls/Button.h>
+#include <vgui_controls/ImagePanel.h>
+#include <vgui_controls/RichText.h>
+#include <vgui_controls/Frame.h>
+#include <game/client/iviewport.h>
+#include <KeyValues.h>
+#include <filesystem.h>
+#include "materialsystem/imaterialvar.h"
+#include "IGameUIFuncs.h" // for key bindings
+
+#include "tf_controls.h"
+#include "tf_imagepanel.h"
+#include "c_team_objectiveresource.h"
+#include "c_tf_objective_resource.h"
+#include "c_tf_player.h"
+
+#include "tf_shareddefs.h"
+#include "tf_roundinfo.h"
+
+
+#include "vgui/ISurface.h"
+#include <vgui/ILocalize.h>
+#include <vgui/IVGui.h>
+#include "engine/IEngineSound.h"
+
+using namespace vgui;
+
+const char *GetMapDisplayName( const char *mapName );
+
+class RoundInfoOverlay : public vgui::EditablePanel
+{
+public:
+ DECLARE_CLASS_SIMPLE( RoundInfoOverlay, vgui::EditablePanel );
+
+ RoundInfoOverlay( Panel *parent, const char *panelName ) : EditablePanel( parent, panelName )
+ {
+ m_iMode = 0;
+ m_flModeChangeTime = -1;
+
+ vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
+
+ m_iBlueTeamTexture = vgui::surface()->CreateNewTextureID();
+ vgui::surface()->DrawSetTextureFile(m_iBlueTeamTexture, "overviews/blueteam", true, false);
+
+ m_iRedTeamTexture = vgui::surface()->CreateNewTextureID();
+ vgui::surface()->DrawSetTextureFile(m_iRedTeamTexture, "overviews/redteam", true, false);
+
+ m_iCapArrowTexture = vgui::surface()->CreateNewTextureID();
+ vgui::surface()->DrawSetTextureFile(m_iCapArrowTexture, "overviews/caparrows", true, false);
+
+ m_iFoundPoints = 0;
+ m_iNextRoundPoints[0] = -1;
+ m_iNextRoundPoints[1] = -1;
+
+ m_iLastCappedPoint = -1;
+ }
+
+ virtual ~RoundInfoOverlay( void )
+ {
+ if ( vgui::surface() )
+ {
+ if ( m_iBlueTeamTexture != -1 )
+ {
+ vgui::surface()->DestroyTextureID( m_iBlueTeamTexture );
+ m_iBlueTeamTexture = -1;
+ }
+
+ if ( m_iRedTeamTexture != -1 )
+ {
+ vgui::surface()->DestroyTextureID( m_iRedTeamTexture );
+ m_iRedTeamTexture = -1;
+ }
+
+ if ( m_iCapArrowTexture != -1 )
+ {
+ vgui::surface()->DestroyTextureID( m_iCapArrowTexture );
+ m_iCapArrowTexture = -1;
+ }
+ }
+ }
+
+ void Update( const char *szMapName );
+
+ virtual void Paint();
+
+ void SetState( int iPrevState, int iCurrentState, int iNextBattles );
+
+ virtual void OnTick( void );
+
+ void DrawTeamIcon( int x, int y, bool bBlueTeam, float flBloat = 1.0f );
+ void DrawCapArrows( int x0, int y0, int x1, int y1 );
+
+private:
+
+ // structure to hold a single control point
+ typedef struct
+ {
+ char m_szName[64];
+ int m_iXPos;
+ int m_iYPos;
+ bool m_bHideIcon;
+ } roundinfo_control_point_t;
+
+ CUtlVector < roundinfo_control_point_t > m_ControlPoints;
+
+ int m_iPrevState;
+ int m_iCurrentState;
+ int m_iMiniRoundMask;
+
+ // Time when we should change the text to the attack directive
+ int m_iMode; // 0 - start, 1 - previous round victory anim, 2 - attack directive, new round
+ float m_flModeChangeTime;
+
+ int m_iBlueTeamTexture;
+ int m_iRedTeamTexture;
+ int m_iCapArrowTexture;
+
+ int m_iLastCappedPoint;
+
+ int m_iFoundPoints;
+ int m_iNextRoundPoints[2];
+};
+
+DECLARE_BUILD_FACTORY( RoundInfoOverlay );
+
+void RoundInfoOverlay::Paint( void )
+{
+ BaseClass::Paint();
+
+ if ( m_ControlPoints.Count() <= 0 )
+ {
+ return;
+ }
+
+ // Draw the Cap Icons
+
+ for ( int i=0; i<m_ControlPoints.Count(); i++ )
+ {
+ if ( m_ControlPoints[i].m_bHideIcon )
+ continue;
+
+ int x = m_ControlPoints[i].m_iXPos;
+ int y = m_ControlPoints[i].m_iYPos;
+
+ switch( m_iMode )
+ {
+ case 0: // Show previous state
+ {
+ if ( i != m_iLastCappedPoint )
+ {
+ bool bBlueTeam = ( m_iPrevState & (1<<i) );
+ DrawTeamIcon( x, y, bBlueTeam );
+ }
+ }
+ break;
+
+ case 1: // Animate the point being capped
+ {
+ bool bWasBlueTeam = ( m_iPrevState & (1<<i) );
+
+ if ( i == m_iLastCappedPoint )
+ {
+ float flTimeUntilChange = m_flModeChangeTime - gpGlobals->curtime;
+
+ if ( flTimeUntilChange < 0.4f )
+ {
+ float flBloat = RemapVal( flTimeUntilChange, 0.0f, 0.4f, 1.0f, 2.5f );
+
+ DrawTeamIcon( x, y, !bWasBlueTeam, flBloat );
+ }
+ }
+ else
+ {
+ DrawTeamIcon( x, y, bWasBlueTeam );
+ }
+ }
+ break;
+
+ case 2: // Draw the current state and the next battle arrows
+ {
+ bool bPointInContention = (m_iNextRoundPoints[0] == i || m_iNextRoundPoints[1] == i );
+
+ bool bBlueTeam = ( m_iCurrentState & (1<<i) );
+ DrawTeamIcon( x, y, bBlueTeam, bPointInContention ? 1.4 : 1.0 ); // rescale? pop looks weird
+ }
+ break;
+ }
+ }
+
+ if ( m_iMode == 2 )
+ {
+ if ( m_iFoundPoints == 2 )
+ {
+ if ( ( m_flModeChangeTime - gpGlobals->curtime ) < 3.5f )
+ {
+ DrawCapArrows( m_ControlPoints[m_iNextRoundPoints[0]].m_iXPos,
+ m_ControlPoints[m_iNextRoundPoints[0]].m_iYPos,
+ m_ControlPoints[m_iNextRoundPoints[1]].m_iXPos,
+ m_ControlPoints[m_iNextRoundPoints[1]].m_iYPos );
+ }
+ }
+ }
+}
+
+void RoundInfoOverlay::DrawCapArrows( int x0, int y0, int x1, int y1 )
+{
+ vgui::surface()->DrawSetColor( Color(255,255,255,255) );
+
+ vgui::surface()->DrawSetTexture( m_iCapArrowTexture );
+
+ Vector2D a( x0, y0 );
+ Vector2D b( x1, y1 );
+
+ Vector2D dir = b - a;
+
+ Vector2D perp( -dir.y, dir.x );
+ perp.NormalizeInPlace();
+ perp *= YRES(50);
+
+ float bloat = sin(4*gpGlobals->curtime) * 0.1f;
+
+ Vector2D edgepoint = a + dir * 0.25f;
+ Vector2D edgepoint2 = b - dir * 0.25f;
+
+ edgepoint -= 0.25f * dir * bloat;
+ edgepoint2 += 0.25f * dir * bloat;
+
+ float uv1 = 0.0f, uv2 = 1.0f;
+ Vector2D uv12( uv1, uv2 );
+ Vector2D uv11( uv1, uv1 );
+ Vector2D uv21( uv2, uv1 );
+ Vector2D uv22( uv2, uv2 );
+
+ vgui::Vertex_t verts[4];
+ verts[0].Init( edgepoint - perp * 0.5f, uv12 );
+ verts[1].Init( edgepoint2 - perp * 0.5f, uv11 );
+ verts[2].Init( edgepoint2 + perp * 0.5f, uv21 );
+ verts[3].Init( edgepoint + perp * 0.5f, uv22 );
+
+ vgui::surface()->DrawTexturedPolygon( 4, verts );
+}
+
+void RoundInfoOverlay::DrawTeamIcon( int x, int y, bool bBlueTeam, float flBloat /* = 1.0f */ )
+{
+ float flWide = YRES(45) * flBloat;
+
+ int xpos = x - flWide * 0.5f;
+ int ypos = y - flWide * 0.5f;
+
+ vgui::surface()->DrawSetColor( Color(255,255,255,255) );
+ vgui::surface()->DrawSetTexture( bBlueTeam ? m_iBlueTeamTexture : m_iRedTeamTexture );
+ vgui::surface()->DrawTexturedRect( xpos, ypos, xpos + flWide, ypos + flWide );
+}
+
+void RoundInfoOverlay::Update( const char *szMapName )
+{
+ KeyValues *kvCapPoints = NULL;
+
+ char strFullpath[MAX_PATH];
+ Q_strncpy( strFullpath, "resource/roundinfo/", MAX_PATH ); // Assume we must play out of the media directory
+ Q_strncat( strFullpath, szMapName, MAX_PATH );
+
+#ifdef _X360
+ char *pExt = Q_stristr( strFullpath, ".360" );
+ if ( pExt )
+ {
+ *pExt = '\0';
+ }
+#endif
+
+ Q_strncat( strFullpath, ".res", MAX_PATH ); // Assume we're a .res extension type
+
+ if ( g_pFullFileSystem->FileExists( strFullpath ), "MOD" )
+ {
+ kvCapPoints = new KeyValues( strFullpath );
+
+ if ( kvCapPoints )
+ {
+ if ( kvCapPoints->LoadFromFile( g_pFullFileSystem, strFullpath ) )
+ {
+ m_ControlPoints.RemoveAll();
+
+ for ( KeyValues *pData = kvCapPoints->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
+ {
+ roundinfo_control_point_t point;
+
+ Q_snprintf( point.m_szName, sizeof(point.m_szName), "%s", pData->GetName() );
+
+ // These x,y coords are relative to a 640x480 parent panel.
+ int wide, tall;
+ GetSize( wide, tall );
+
+ // can't use XRES, YRES because of widescreen
+ point.m_iXPos = (int)( (float)pData->GetInt( "x", 0 ) * ( ( float )wide / 560.0f ) );
+ point.m_iYPos = (int)( (float)pData->GetInt( "y", 0 ) * ( ( float )tall / 280.0f ) );
+
+ point.m_bHideIcon = ( pData->GetInt( "hideicon", 0 ) > 0 );
+
+ m_ControlPoints.AddToTail( point );
+ }
+ }
+
+ kvCapPoints->deleteThis();
+ }
+ }
+}
+
+void RoundInfoOverlay::SetState( int iPrevState, int iCurrentState, int iNextBattles )
+{
+ m_iPrevState = iPrevState;
+ m_iCurrentState = iCurrentState;
+ m_iMiniRoundMask = iNextBattles;
+
+ m_iMode = 0;
+ m_flModeChangeTime = gpGlobals->curtime + 0.5f;
+
+ // Find the two points that are being fought over
+
+ m_iFoundPoints = 0;
+
+ for ( int i=0;i<8 && m_iFoundPoints<2;i++ )
+ {
+ if ( m_iMiniRoundMask & (1<<i) )
+ {
+ m_iNextRoundPoints[m_iFoundPoints] = i;
+ m_iFoundPoints++;
+ }
+ }
+
+ // Make sure the blue point is in m_iNextRoundPoints[0]
+ if ( m_iFoundPoints >= 2 )
+ {
+ if ( !( m_iCurrentState & (1<<m_iNextRoundPoints[0]) ) )
+ {
+ // The first point is red! swap them
+ int temp = m_iNextRoundPoints[0];
+ m_iNextRoundPoints[0] = m_iNextRoundPoints[1];
+ m_iNextRoundPoints[1] = temp;
+ }
+ }
+
+ m_iLastCappedPoint = -1;
+
+ // Find the index of the point that was just capped
+ int iMaskedCappedPoint = m_iCurrentState ^ m_iPrevState;
+
+ if ( iMaskedCappedPoint != 0 )
+ {
+ int iIndex = 0;
+
+ // Find the index of the point that changed
+ while ( !( iMaskedCappedPoint & 0x1 ) )
+ {
+ iMaskedCappedPoint = iMaskedCappedPoint>>1;
+ iIndex++;
+ }
+ m_iLastCappedPoint = iIndex;
+ }
+}
+
+
+ConVar tf_roundinfo_pause( "tf_roundinfo_pause", "0", FCVAR_DEVELOPMENTONLY );
+
+void RoundInfoOverlay::OnTick( void )
+{
+ // Stop ticking when our parent is invisible
+ Panel *parent = GetParent();
+ if ( m_iMode >= 0 && ( !parent || !parent->IsVisible() ) )
+ {
+ m_iMode = -1;
+ return;
+ }
+
+ BaseClass::OnTick();
+
+ if ( tf_roundinfo_pause.GetBool() == false && m_flModeChangeTime <= gpGlobals->curtime )
+ {
+ switch( m_iMode )
+ {
+ case 0:
+ {
+ // start showing previous round anim
+ if ( m_iCurrentState != m_iPrevState )
+ {
+ m_iMode = 1;
+ m_flModeChangeTime = gpGlobals->curtime + 1.5f;
+ }
+ else
+ {
+ m_iMode = 2;
+ m_flModeChangeTime = gpGlobals->curtime + 4.0f;
+ }
+ }
+ break;
+
+ case 1:
+ {
+ // start showing next round plan
+ m_iMode = 2;
+ m_flModeChangeTime = gpGlobals->curtime + 4.0f;
+
+ CLocalPlayerFilter filter;
+ C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "Hud.EndRoundScored" );
+ }
+ break;
+
+ case 2:
+ {
+ // we're done, hide the panel
+ //GetParent()->OnCommand( "continue" );
+ //m_iMode = -1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CTFRoundInfo::CTFRoundInfo( IViewPort *pViewPort ) : Frame( NULL, PANEL_ROUNDINFO )
+{
+ m_pViewPort = pViewPort;
+
+ // load the new scheme early!!
+ SetScheme( "ClientScheme" );
+
+ SetTitleBarVisible( false );
+ SetMinimizeButtonVisible( false );
+ SetMaximizeButtonVisible( false );
+ SetCloseButtonVisible( false );
+ SetSizeable( false );
+ SetMoveable( false );
+ SetProportional( true );
+ SetVisible( false );
+ SetKeyBoardInputEnabled( true );
+
+ m_pTitle = new CExLabel( this, "RoundTitle", " " );
+ m_pMapImage = new ImagePanel( this, "MapImage" );
+
+#ifdef _X360
+ m_pFooter = new CTFFooter( this, "Footer" );
+#else
+ m_pContinue = new CExButton( this, "RoundContinue", "#TF_Continue" );
+#endif
+
+ m_pOverlay = new RoundInfoOverlay( this, "Overlay" );
+
+ ListenForGameEvent( "game_newmap" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::PerformLayout()
+{
+ BaseClass::PerformLayout();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ LoadControlSettings( "Resource/UI/RoundInfo.res" );
+
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ Update();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::ShowPanel( bool bShow )
+{
+ if ( IsVisible() == bShow )
+ return;
+
+ if ( bShow )
+ {
+ // look for the textures we want to use and don't show the roundinfo panel if any are missing
+ char temp[255];
+ Q_snprintf( temp, sizeof( temp ), "VGUI/%s", m_szMapImage );
+ IMaterial *pMapMaterial = materials->FindMaterial( temp, TEXTURE_GROUP_VGUI, false );
+
+ // are we missing any of the images we want to show?
+ if ( pMapMaterial && !IsErrorMaterial( pMapMaterial ) )
+ {
+ Activate();
+ }
+ else
+ {
+ SetVisible( false );
+ }
+ }
+ else
+ {
+ SetVisible( false );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::OnCommand( const char *command )
+{
+ if ( !Q_strcmp( command, "continue" ) )
+ {
+ m_pViewPort->ShowPanel( this, false );
+ }
+ else
+ {
+ BaseClass::OnCommand( command );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::UpdateImage( ImagePanel *pImagePanel, const char *pszImageName )
+{
+ if ( pImagePanel && ( Q_strlen( pszImageName ) > 0 ) )
+ {
+ char szTemp[255];
+ Q_snprintf( szTemp, sizeof( szTemp ), "VGUI/%s", pszImageName );
+
+ IMaterial *pTemp = materials->FindMaterial( szTemp, TEXTURE_GROUP_VGUI, false );
+ if ( pTemp && !IsErrorMaterial( pTemp ) )
+ {
+ pImagePanel->SetImage( pszImageName );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::Update()
+{
+ char szMapName[MAX_MAP_NAME];
+ Q_FileBase( engine->GetLevelName(), szMapName, sizeof(szMapName) );
+ Q_strlower( szMapName );
+
+ SetDialogVariable( "mapname", GetMapDisplayName( szMapName ) );
+
+ if ( m_pMapImage )
+ {
+ char temp[255];
+ Q_snprintf( temp, sizeof(temp), "../overviews/%s", szMapName );
+ Q_strncpy( m_szMapImage, temp, sizeof( m_szMapImage ) );
+
+ UpdateImage( m_pMapImage, m_szMapImage );
+ }
+
+ if ( m_pOverlay )
+ {
+ m_pOverlay->Update( szMapName );
+ }
+
+#ifndef _X360
+ if ( m_pContinue )
+ {
+ m_pContinue->RequestFocus();
+ }
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::OnKeyCodePressed( KeyCode code )
+{
+ if( code == KEY_SPACE ||
+ code == KEY_ENTER ||
+ code == KEY_XBUTTON_A ||
+ code == KEY_XBUTTON_B ||
+ code == STEAMCONTROLLER_A ||
+ code == STEAMCONTROLLER_B )
+ {
+ OnCommand( "continue" );
+ }
+ else
+ {
+ BaseClass::OnKeyCodePressed( code );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::SetData( KeyValues *data )
+{
+ if ( m_pOverlay )
+ {
+ m_pOverlay->SetState( data->GetInt( "prev" ), data->GetInt( "cur" ), data->GetInt( "round" ) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFRoundInfo::FireGameEvent( IGameEvent *event )
+{
+ if ( Q_strcmp( event->GetName(), "game_newmap" ) == 0 )
+ {
+ Update();
+ }
+} \ No newline at end of file