//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #include "hudelement.h" #include #include #include #include #include #include "c_baseplayer.h" #include "iclientmode.h" #include "c_team_objectiveresource.h" #include "c_team.h" #include "view.h" #include "teamplay_gamerules.h" // NOTE: This has to be the last file included! #include "tier0/memdbgon.h" #define INTRO_NUM_FAKE_PLAYERS 3 extern ConVar mp_capstyle; extern ConVar mp_blockstyle; //----------------------------------------------------------------------------- // Purpose: Draws the progress bar //----------------------------------------------------------------------------- class CHudCapturePanelProgressBar : public vgui::ImagePanel { public: DECLARE_CLASS_SIMPLE( CHudCapturePanelProgressBar, vgui::ImagePanel ); CHudCapturePanelProgressBar( vgui::Panel *parent, const char *name ); virtual void Paint(); void SetPercentage( float flPercentage ){ m_flPercent = flPercentage; } private: float m_flPercent; int m_iTexture; CPanelAnimationVar( Color, m_clrActive, "color_active", "HudCaptureProgressBar.Active" ); CPanelAnimationVar( Color, m_clrInActive, "color_inactive", "HudCaptureProgressBar.InActive" ); }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CHudCapturePanelIcon : public vgui::ImagePanel { public: DECLARE_CLASS_SIMPLE( CHudCapturePanelIcon, vgui::ImagePanel ); CHudCapturePanelIcon( vgui::Panel *parent, const char *name ); virtual void Paint(); void SetActive( bool state ){ m_bActive = state; } private: bool m_bActive; int m_iTexture; CPanelAnimationVar( Color, m_clrActive, "color_active", "HudCaptureIcon.Active" ); CPanelAnimationVar( Color, m_clrInActive, "color_inactive", "HudCaptureIcon.InActive" ); }; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- class CHudCapturePanel : public CHudElement, public vgui::EditablePanel { public: DECLARE_CLASS_SIMPLE( CHudCapturePanel, vgui::EditablePanel ); explicit CHudCapturePanel( const char *pElementName ); virtual void Init( void ); virtual void LevelInit( void ); virtual void OnThink(); virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); virtual void OnScreenSizeChanged( int iOldWide, int iOldTall ); virtual void FireGameEvent( IGameEvent *event ); private: int m_iCurrentCP; // the index of the control point the local is currently in int m_iOriginalYPos; CHudCapturePanelProgressBar *m_pProgressBar; CUtlVector m_PlayerIcons; bool m_bInitializedFlags; vgui::ImagePanel *m_pTeamFlags[ MAX_TEAMS ]; vgui::Label *m_pMessage; vgui::Panel *m_pBackground; CPanelAnimationVarAliasType( float, m_nSpaceBetweenIcons, "icon_space", "2", "proportional_float" ); // For demonstrations of the element in the intro bool m_bFakingCapture; bool m_bFakingMultCapture; float m_flFakeCaptureTime; C_BaseAnimating *m_pFakePlayers[INTRO_NUM_FAKE_PLAYERS]; }; DECLARE_HUDELEMENT( CHudCapturePanel ); ConVar hud_capturepanel( "hud_capturepanel", "1", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Set to 0 to not draw the HUD capture panel" ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CHudCapturePanelProgressBar::CHudCapturePanelProgressBar( vgui::Panel *parent, const char *name ) : vgui::ImagePanel( parent, name ) { m_flPercent = 0.0f; m_iTexture = vgui::surface()->DrawGetTextureId( "vgui/progress_bar" ); if ( m_iTexture == -1 ) // we didn't find it, so create a new one { m_iTexture = vgui::surface()->CreateNewTextureID(); } vgui::surface()->DrawSetTextureFile( m_iTexture, "vgui/progress_bar", true, false ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanelProgressBar::Paint() { int wide, tall; GetSize( wide, tall ); float uv1 = 0.0f, uv2 = 1.0f; Vector2D uv11( uv1, uv1 ); Vector2D uv21( uv2, uv1 ); Vector2D uv22( uv2, uv2 ); Vector2D uv12( uv1, uv2 ); vgui::Vertex_t verts[4]; verts[0].Init( Vector2D( 0, 0 ), uv11 ); verts[1].Init( Vector2D( wide, 0 ), uv21 ); verts[2].Init( Vector2D( wide, tall ), uv22 ); verts[3].Init( Vector2D( 0, tall ), uv12 ); // first, just draw the whole thing inactive. vgui::surface()->DrawSetTexture( m_iTexture ); vgui::surface()->DrawSetColor( m_clrInActive ); vgui::surface()->DrawTexturedPolygon( 4, verts ); // now, let's calculate the "active" part of the progress bar vgui::surface()->DrawSetColor( m_clrActive ); // we're going to do this using quadrants // ------------------------- // | | | // | | | // | 4 | 1 | // | | | // | | | // ------------------------- // | | | // | | | // | 3 | 2 | // | | | // | | | // ------------------------- float flCompleteCircle = ( 2.0f * M_PI ); float fl90degrees = flCompleteCircle / 4.0f; float flEndAngle = flCompleteCircle * ( 1.0f - m_flPercent ); // count DOWN (counter-clockwise) // float flEndAngle = flCompleteCircle * m_flPercent; // count UP (clockwise) float flHalfWide = (float)wide / 2.0f; float flHalfTall = (float)tall / 2.0f; if ( flEndAngle >= fl90degrees * 3.0f ) // >= 270 degrees { // draw the first and second quadrants uv11.Init( 0.5f, 0.0f ); uv21.Init( 1.0f, 0.0f ); uv22.Init( 1.0f, 1.0f ); uv12.Init( 0.5, 1.0f ); verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 ); verts[1].Init( Vector2D( wide, 0.0f ), uv21 ); verts[2].Init( Vector2D( wide, tall ), uv22 ); verts[3].Init( Vector2D( flHalfWide, tall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); // draw the third quadrant uv11.Init( 0.0f, 0.5f ); uv21.Init( 0.5f, 0.5f ); uv22.Init( 0.5f, 1.0f ); uv12.Init( 0.0f, 1.0f ); verts[0].Init( Vector2D( 0.0f, flHalfTall ), uv11 ); verts[1].Init( Vector2D( flHalfWide, flHalfTall ), uv21 ); verts[2].Init( Vector2D( flHalfWide, tall ), uv22 ); verts[3].Init( Vector2D( 0.0f, tall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); // draw the partial fourth quadrant if ( flEndAngle > fl90degrees * 3.5f ) // > 315 degrees { uv11.Init( 0.0f, 0.0f ); uv21.Init( 0.5f - ( tan(fl90degrees * 4.0f - flEndAngle) * 0.5 ), 0.0f ); uv22.Init( 0.5f, 0.5f ); uv12.Init( 0.0f, 0.5f ); verts[0].Init( Vector2D( 0.0f, 0.0f ), uv11 ); verts[1].Init( Vector2D( flHalfWide - ( tan(fl90degrees * 4.0f - flEndAngle) * flHalfTall ), 0.0f ), uv21 ); verts[2].Init( Vector2D( flHalfWide, flHalfTall ), uv22 ); verts[3].Init( Vector2D( 0.0f, flHalfTall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } else // <= 315 degrees { uv11.Init( 0.0f, 0.5f ); uv21.Init( 0.0f, 0.5f - ( tan(flEndAngle - fl90degrees * 3.0f) * 0.5 ) ); uv22.Init( 0.5f, 0.5f ); uv12.Init( 0.0f, 0.5f ); verts[0].Init( Vector2D( 0.0f, flHalfTall ), uv11 ); verts[1].Init( Vector2D( 0.0f, flHalfTall - ( tan(flEndAngle - fl90degrees * 3.0f) * flHalfWide ) ), uv21 ); verts[2].Init( Vector2D( flHalfWide, flHalfTall ), uv22 ); verts[3].Init( Vector2D( 0.0f, flHalfTall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } } else if ( flEndAngle >= fl90degrees * 2.0f ) // >= 180 degrees { // draw the first and second quadrants uv11.Init( 0.5f, 0.0f ); uv21.Init( 1.0f, 0.0f ); uv22.Init( 1.0f, 1.0f ); uv12.Init( 0.5, 1.0f ); verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 ); verts[1].Init( Vector2D( wide, 0.0f ), uv21 ); verts[2].Init( Vector2D( wide, tall ), uv22 ); verts[3].Init( Vector2D( flHalfWide, tall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); // draw the partial third quadrant if ( flEndAngle > fl90degrees * 2.5f ) // > 225 degrees { uv11.Init( 0.5f, 0.5f ); uv21.Init( 0.5f, 1.0f ); uv22.Init( 0.0f, 1.0f ); uv12.Init( 0.0f, 0.5f + ( tan(fl90degrees * 3.0f - flEndAngle) * 0.5 ) ); verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 ); verts[1].Init( Vector2D( flHalfWide, tall ), uv21 ); verts[2].Init( Vector2D( 0.0f, tall ), uv22 ); verts[3].Init( Vector2D( 0.0f, flHalfTall + ( tan(fl90degrees * 3.0f - flEndAngle) * flHalfWide ) ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } else // <= 225 degrees { uv11.Init( 0.5f, 0.5f ); uv21.Init( 0.5f, 1.0f ); uv22.Init( 0.5f - ( tan( flEndAngle - fl90degrees * 2.0f) * 0.5 ), 1.0f ); uv12.Init( 0.5f, 0.5f ); verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 ); verts[1].Init( Vector2D( flHalfWide, tall ), uv21 ); verts[2].Init( Vector2D( flHalfWide - ( tan(flEndAngle - fl90degrees * 2.0f) * flHalfTall ), tall ), uv22 ); verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } } else if ( flEndAngle >= fl90degrees ) // >= 90 degrees { // draw the first quadrant uv11.Init( 0.5f, 0.0f ); uv21.Init( 1.0f, 0.0f ); uv22.Init( 1.0f, 0.5f ); uv12.Init( 0.5f, 0.5f ); verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 ); verts[1].Init( Vector2D( wide, 0.0f ), uv21 ); verts[2].Init( Vector2D( wide, flHalfTall ), uv22 ); verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); // draw the partial second quadrant if ( flEndAngle > fl90degrees * 1.5f ) // > 135 degrees { uv11.Init( 0.5f, 0.5f ); uv21.Init( 1.0f, 0.5f ); uv22.Init( 1.0f, 1.0f ); uv12.Init( 0.5f + ( tan(fl90degrees * 2.0f - flEndAngle) * 0.5f ), 1.0f ); verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 ); verts[1].Init( Vector2D( wide, flHalfTall ), uv21 ); verts[2].Init( Vector2D( wide, tall ), uv22 ); verts[3].Init( Vector2D( flHalfWide + ( tan(fl90degrees * 2.0f - flEndAngle) * flHalfTall ), tall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } else // <= 135 degrees { uv11.Init( 0.5f, 0.5f ); uv21.Init( 1.0f, 0.5f ); uv22.Init( 1.0f, 0.5f + ( tan(flEndAngle - fl90degrees) * 0.5f ) ); uv12.Init( 0.5f, 0.5f ); verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 ); verts[1].Init( Vector2D( wide, flHalfTall ), uv21 ); verts[2].Init( Vector2D( wide, flHalfTall + ( tan(flEndAngle - fl90degrees) * flHalfWide ) ), uv22 ); verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } } else // > 0 degrees { if ( flEndAngle > fl90degrees / 2.0f ) // > 45 degrees { uv11.Init( 0.5f, 0.0f ); uv21.Init( 1.0f, 0.0f ); uv22.Init( 1.0f, 0.5f - ( tan(fl90degrees - flEndAngle) * 0.5 ) ); uv12.Init( 0.5f, 0.5f ); verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 ); verts[1].Init( Vector2D( wide, 0.0f ), uv21 ); verts[2].Init( Vector2D( wide, flHalfTall - ( tan(fl90degrees - flEndAngle) * flHalfWide ) ), uv22 ); verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } else // <= 45 degrees { uv11.Init( 0.5f, 0.0f ); uv21.Init( 0.5 + ( tan(flEndAngle) * 0.5 ), 0.0f ); uv22.Init( 0.5f, 0.5f ); uv12.Init( 0.5f, 0.0f ); verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 ); verts[1].Init( Vector2D( flHalfWide + ( tan(flEndAngle) * flHalfTall ), 0.0f ), uv21 ); verts[2].Init( Vector2D( flHalfWide, flHalfTall ), uv22 ); verts[3].Init( Vector2D( flHalfWide, 0.0f ), uv12 ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CHudCapturePanelIcon::CHudCapturePanelIcon( vgui::Panel *parent, const char *name ) : vgui::ImagePanel( parent, name ) { m_bActive = false; m_iTexture = vgui::surface()->DrawGetTextureId( "vgui/capture_icon" ); if ( m_iTexture == -1 ) // we didn't find it, so create a new one { m_iTexture = vgui::surface()->CreateNewTextureID(); } vgui::surface()->DrawSetTextureFile( m_iTexture, "vgui/capture_icon", true, false ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanelIcon::Paint() { int wide, tall; GetSize( wide, tall ); float uv1 = 0.0f, uv2 = 1.0f; Vector2D uv11( uv1, uv1 ); Vector2D uv12( uv1, uv2 ); Vector2D uv21( uv2, uv1 ); Vector2D uv22( uv2, uv2 ); vgui::Vertex_t verts[4]; verts[0].Init( Vector2D( 0, 0 ), uv11 ); verts[1].Init( Vector2D( wide, 0 ), uv21 ); verts[2].Init( Vector2D( wide, tall ), uv22 ); verts[3].Init( Vector2D( 0, tall ), uv12 ); // just draw the whole thing vgui::surface()->DrawSetTexture( m_iTexture ); vgui::surface()->DrawSetColor( m_bActive ? m_clrActive : m_clrInActive ); vgui::surface()->DrawTexturedPolygon( 4, verts ); } //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CHudCapturePanel::CHudCapturePanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudCapturePanel" ) { SetParent( GetClientMode()->GetViewport() ); m_iCurrentCP = -1; m_bFakingCapture = false; m_pBackground = new vgui::Panel( this, "CapturePanelBackground" ); m_pProgressBar = new CHudCapturePanelProgressBar( this, "CapturePanelProgressBar" ); for ( int i = 0 ; i < 5 ; i++ ) { CHudCapturePanelIcon *pPanel; char szName[64]; Q_snprintf( szName, sizeof( szName ), "CapturePanelPlayerIcon%d", i + 1 ); pPanel = new CHudCapturePanelIcon( this, szName ); m_PlayerIcons.AddToTail( pPanel ); } m_bInitializedFlags = false; for ( int i = 0; i < MAX_TEAMS; i++ ) { m_pTeamFlags[i] = NULL; } m_pMessage = new vgui::Label( this, "CapturePanelMessage", " " ); // load control settings... LoadControlSettings( "resource/UI/HudCapturePanel.res" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanel::Init( void ) { ListenForGameEvent( "controlpoint_starttouch" ); ListenForGameEvent( "controlpoint_endtouch" ); ListenForGameEvent( "teamplay_round_start" ); ListenForGameEvent( "controlpoint_fake_capture" ); ListenForGameEvent( "controlpoint_fake_capture_mult" ); ListenForGameEvent( "intro_finish" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanel::LevelInit( void ) { m_iCurrentCP = -1; m_bFakingCapture = false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanel::OnScreenSizeChanged( int iOldWide, int iOldTall ) { LoadControlSettings( "resource/UI/HudCapturePanel.res" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); if ( m_pBackground ) { m_pBackground->SetBgColor( GetSchemeColor( "HintMessageBg", pScheme ) ); m_pBackground->SetPaintBackgroundType( 2 ); } SetFgColor( GetSchemeColor( "HudProgressBar.Active", pScheme ) ); int iX; GetPos( iX, m_iOriginalYPos ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanel::OnThink() { BaseClass::OnThink(); if ( !GetNumberOfTeams() ) return; if ( !m_bInitializedFlags ) { m_bInitializedFlags = true; for ( int i = 0; i < GetNumberOfTeams(); i++ ) { if ( i == TEAM_SPECTATOR ) continue; m_pTeamFlags[i] = dynamic_cast< vgui::ImagePanel * >(FindChildByName( VarArgs("CapturePanelTeamFlag_%d", i) )); } InvalidateLayout(); } if ( m_bFakingCapture && gpGlobals->curtime > m_flFakeCaptureTime ) { m_bFakingCapture = false; if ( m_bFakingMultCapture ) { for ( int i = 0; i < INTRO_NUM_FAKE_PLAYERS; i++ ) { m_pFakePlayers[i]->Release(); m_pFakePlayers[i] = NULL; } } } C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( pPlayer ) { bool bInCapZone = ( m_iCurrentCP >= 0 ); // Turn off the panel and children if the player is dead or not in a cap zone if ( !m_bFakingCapture && (!bInCapZone || !hud_capturepanel.GetBool() || !pPlayer->IsAlive()) ) { if ( IsVisible() ) { SetVisible( false ); } return; } int nOwningTeam = ObjectiveResource()->GetOwningTeam( m_iCurrentCP ); int nPlayerTeam = pPlayer->GetTeamNumber(); int nNumTeammates = ObjectiveResource()->GetNumPlayersInArea( m_iCurrentCP, nPlayerTeam ); int nRequiredTeammates = ObjectiveResource()->GetRequiredCappers( m_iCurrentCP, nPlayerTeam ); int nNumEnemies = 0; bool bEnemyTeamReadyToCap = false; for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ ) { if ( i == nPlayerTeam ) continue; int iTeamInArea = ObjectiveResource()->GetNumPlayersInArea( m_iCurrentCP, i ); nNumEnemies += iTeamInArea; if ( iTeamInArea >= ObjectiveResource()->GetRequiredCappers( m_iCurrentCP, i ) ) { // There's an enemy team here that has enough players to cap bEnemyTeamReadyToCap = true; } } int iCappingTeam = ObjectiveResource()->GetCappingTeam( m_iCurrentCP ); // If we're faking it, stomp all the data if ( m_bFakingCapture ) { nOwningTeam = TEAM_UNASSIGNED; iCappingTeam = nPlayerTeam; if ( m_bFakingMultCapture ) { nNumTeammates = nRequiredTeammates = 3; } else { nNumTeammates = nRequiredTeammates = 1; } nNumEnemies = 0; bEnemyTeamReadyToCap = false; } // If we're in more-players-cap-faster mode, we have no required amount. // Just show the number of players in the zone. if ( mp_capstyle.GetInt() == 1 ) { // Clip to max number of players we can show if ( nNumTeammates > 5 ) { nNumTeammates = 5; } nRequiredTeammates = nNumTeammates; } // if we already own this capture point and there are no enemies in the area // or we're playing minirounds and the current cap zone is not in the current round if ( ( nOwningTeam == nPlayerTeam && !bEnemyTeamReadyToCap ) || ( ObjectiveResource()->PlayingMiniRounds() && !ObjectiveResource()->IsInMiniRound( m_iCurrentCP ) ) ) { // don't need to do anything if ( IsVisible() ) { SetVisible( false ); } return; } // okay, turn on the capture point panel if ( !IsVisible() ) { SetVisible( true ); } // If there's a hint onscreen, move ourselves off it int iX,iY; GetPos( iX, iY ); if ( pPlayer->Hints() && pPlayer->Hints()->HintIsCurrentlyVisible() ) { int iMovedY = (m_iOriginalYPos - YRES(50)); if ( iY != iMovedY ) { SetPos( iX, iMovedY ); } } else if ( iY != m_iOriginalYPos ) { SetPos( iX, m_iOriginalYPos ); } // set the correct flag image for ( int i = 0; i < GetNumberOfTeams(); i++ ) { if ( !m_pTeamFlags[i] ) continue; m_pTeamFlags[i]->SetVisible( nOwningTeam == i ); } // arrange the player icons for ( int i = 0 ; i < m_PlayerIcons.Count() ; i++ ) { CHudCapturePanelIcon *pPanel = m_PlayerIcons[i]; if ( !pPanel ) { continue; } if ( i < nRequiredTeammates ) { if ( i < nNumTeammates ) { pPanel->SetActive( true ); if ( !pPanel->IsVisible() ) pPanel->SetVisible( true ); } else { pPanel->SetActive( false ); if ( !pPanel->IsVisible() ) pPanel->SetVisible( true ); } } else { if ( pPanel->IsVisible() ) pPanel->SetVisible( false ); } } int wide = 0, tall = 0, iconWide = 0, iconTall = 0; GetSize( wide, tall ); vgui::ImagePanel *pPanel = m_PlayerIcons[0]; if ( pPanel ) pPanel->GetSize( iconWide, iconTall ); int width = ( nRequiredTeammates * iconWide ) + ( ( nRequiredTeammates - 1 ) * m_nSpaceBetweenIcons ); int xpos = wide / 2.0 - width / 2.0; // rearrange the player icon panels for ( int i = 0 ; i < nRequiredTeammates ; i++ ) { CHudCapturePanelIcon *pPanel = m_PlayerIcons[i]; if ( pPanel ) { int x, y, w, t; pPanel->GetBounds( x, y, w, t ); pPanel->SetBounds( xpos, y, w, t ); } xpos += iconWide + m_nSpaceBetweenIcons; } // are we capping an area? if ( iCappingTeam == TEAM_UNASSIGNED || iCappingTeam != nPlayerTeam ) { // turn off the progress bar, we're not capping if ( m_pProgressBar && m_pProgressBar->IsVisible() ) { m_pProgressBar->SetVisible( false ); } // turn on the message if ( m_pMessage ) { m_pMessage->SetFgColor( GetFgColor() ); if ( !m_pMessage->IsVisible() ) { m_pMessage->SetVisible( true ); } char szReason[256]; // If a team's not allowed to cap a point, don't count players in it at all if ( !TeamplayGameRules()->TeamMayCapturePoint( nPlayerTeam, m_iCurrentCP ) ) { m_pMessage->SetText( "#Team_Capture_Linear" ); if ( m_pTeamFlags[ nOwningTeam ] ) { m_pTeamFlags[ nOwningTeam ]->SetVisible( false ); } } else if ( !TeamplayGameRules()->PlayerMayCapturePoint( pPlayer, m_iCurrentCP, szReason, sizeof(szReason) ) ) { m_pMessage->SetText( szReason ); if ( m_pTeamFlags[ nOwningTeam ] ) { m_pTeamFlags[ nOwningTeam ]->SetVisible( false ); } } else if ( nNumTeammates >= nRequiredTeammates && nNumEnemies > 0 ) { m_pMessage->SetText( "#Team_Capture_Blocked" ); } else if ( bEnemyTeamReadyToCap ) { m_pMessage->SetText( "#Team_Blocking_Capture" ); } else if ( mp_blockstyle.GetInt() == 1 && iCappingTeam != TEAM_UNASSIGNED ) { m_pMessage->SetText( "#Team_Blocking_Capture" ); for ( int i = 0; i < GetNumberOfTeams(); i++ ) { if ( m_pTeamFlags[i] ) { m_pTeamFlags[i]->SetVisible( false ); } } } else if ( !ObjectiveResource()->TeamCanCapPoint( m_iCurrentCP, nPlayerTeam ) ) { m_pMessage->SetText( "#Team_Cannot_Capture" ); if ( m_pTeamFlags[ nOwningTeam ] ) { m_pTeamFlags[ nOwningTeam ]->SetVisible( false ); } } else { m_pMessage->SetText( "#Team_Waiting_for_teammate" ); } if ( m_pBackground ) { // do we need to resize our background? int textW, textH, bgX, bgY, bgW, bgH; m_pMessage->GetContentSize( textW, textH ); m_pBackground->GetBounds( bgX, bgY, bgW, bgH ); if ( bgW < textW ) { m_pBackground->SetBounds( bgX + ( bgW / 2.0 ) - ( ( textW + XRES(3) ) / 2.0 ), bgY, textW + XRES(3), bgH ); } } } } else { // turn on the progress bar, we're capping if ( m_pProgressBar ) { if ( !m_pProgressBar->IsVisible() ) { m_pProgressBar->SetVisible( true ); } if ( m_bFakingCapture ) { float flProgress = RemapVal( m_flFakeCaptureTime - gpGlobals->curtime, 0, 5.0, 0, 1 ); m_pProgressBar->SetPercentage( flProgress ); } else { m_pProgressBar->SetPercentage( ObjectiveResource()->GetCPCapPercentage( m_iCurrentCP ) ); } } // If our cap is being paused by blocking enemies, show that if ( mp_blockstyle.GetInt() == 1 && nNumTeammates == 0 ) { m_pMessage->SetText( "#Team_Capture_Blocked" ); if ( !m_pMessage->IsVisible() ) { m_pMessage->SetVisible( true ); } for ( int i = 0; i < GetNumberOfTeams(); i++ ) { if ( m_pTeamFlags[i] ) { m_pTeamFlags[i]->SetVisible( false ); } } } else if ( m_pMessage && m_pMessage->IsVisible() ) { // turn off the message m_pMessage->SetVisible( false ); } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudCapturePanel::FireGameEvent( IGameEvent *event ) { m_iCurrentCP = -1; return; const char *eventname = event->GetName(); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( FStrEq( "controlpoint_starttouch", eventname ) ) { int iPlayer = event->GetInt( "player" ); if ( pPlayer && iPlayer == pPlayer->entindex() ) { m_iCurrentCP = event->GetInt( "area" ); } } else if ( FStrEq( "controlpoint_endtouch", eventname ) ) { int iPlayer = event->GetInt( "player" ); if ( pPlayer && iPlayer == pPlayer->entindex() ) { Assert( m_iCurrentCP == event->GetInt( "area" ) ); m_iCurrentCP = -1; } } else if ( FStrEq( "teamplay_round_start", eventname ) ) { m_iCurrentCP = -1; } else if ( FStrEq( "controlpoint_fake_capture", eventname ) ) { int iPlayer = event->GetInt( "player" ); if ( pPlayer && iPlayer == pPlayer->entindex() ) { m_iCurrentCP = event->GetInt( "int_data" ); m_bFakingCapture = true; m_bFakingMultCapture = false; m_flFakeCaptureTime = gpGlobals->curtime + 5.0; } } else if ( FStrEq( "controlpoint_fake_capture_mult", eventname ) ) { int iPlayer = event->GetInt( "player" ); if ( pPlayer && iPlayer == pPlayer->entindex() ) { m_iCurrentCP = event->GetInt( "int_data" ); m_bFakingCapture = true; m_bFakingMultCapture = true; m_flFakeCaptureTime = gpGlobals->curtime + 5.0; // Trace forward & find the world trace_t tr; Vector vecEnd; VectorMA( MainViewOrigin(), MAX_TRACE_LENGTH, MainViewForward(), vecEnd ); UTIL_TraceLine( MainViewOrigin(), vecEnd, MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr ); if ( !tr.startsolid && tr.fraction < 1.0 ) { Vector vecPositions[INTRO_NUM_FAKE_PLAYERS] = { Vector( 100, 100, 0 ), Vector( 0, -100, 0 ), Vector( -100, 0, 0 ), }; const char *pszModels[INTRO_NUM_FAKE_PLAYERS] = { "models/player/engineer.mdl", "models/player/medic.mdl", "models/player/soldier.mdl", }; for ( int i = 0; i < INTRO_NUM_FAKE_PLAYERS; i++ ) { m_pFakePlayers[i] = new C_BaseAnimating; if ( m_pFakePlayers[i]->InitializeAsClientEntity( pszModels[i], RENDER_GROUP_OPAQUE_ENTITY ) ) { Vector vecOrigin = tr.endpos + vecPositions[i]; m_pFakePlayers[i]->SetAbsOrigin( vecOrigin ); m_pFakePlayers[i]->SetAbsAngles( QAngle(0,RandomInt(0,360),0) ); } } } } } else if ( FStrEq( "intro_finish", eventname ) ) { int iPlayer = event->GetInt( "player" ); if ( pPlayer && iPlayer == pPlayer->entindex() ) { m_iCurrentCP = -1; m_bFakingCapture = false; m_bFakingMultCapture = false; m_flFakeCaptureTime = 0; for ( int i = 0; i < INTRO_NUM_FAKE_PLAYERS; i++ ) { if ( m_pFakePlayers[i] ) { m_pFakePlayers[i]->Release(); m_pFakePlayers[i] = NULL; } } } } }