You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1241 lines
42 KiB
1241 lines
42 KiB
![]()
4 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include <vgui_controls/AnimationController.h>
|
||
|
|
||
|
#include "tf_hud_freezepanel.h"
|
||
|
#include "clientmode_shared.h"
|
||
|
#include "tf_hud_robot_destruction_status.h"
|
||
|
#include "tf_logic_player_destruction.h"
|
||
|
#include "c_tf_objective_resource.h"
|
||
|
#include "c_func_capture_zone.h"
|
||
|
|
||
|
#define ATTACK_BLINK_TIME 2.f
|
||
|
|
||
|
using namespace vgui;
|
||
|
|
||
|
extern ConVar tf_rd_min_points_to_steal;
|
||
|
extern ConVar tf_rd_steal_rate;
|
||
|
extern ConVar tf_rd_points_per_steal;
|
||
|
extern ConVar tf_rd_points_approach_interval;
|
||
|
extern ConVar tf_rd_points_per_approach;
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFHudRobotDestruction_StateImage::CTFHudRobotDestruction_StateImage( Panel *parent, const char *name, const char *pszResFile )
|
||
|
: vgui::EditablePanel( parent, name )
|
||
|
, m_pImage( NULL )
|
||
|
, m_pRobotImage( NULL )
|
||
|
, m_pszResFile( pszResFile )
|
||
|
{
|
||
|
m_pImage = new ImagePanel( this, "Image" );
|
||
|
m_pRobotImage = new ImagePanel( this, "RobotImage" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_StateImage::ApplySchemeSettings( IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
LoadControlSettings( m_pszResFile );
|
||
|
|
||
|
ImagePanel* pGlow = dynamic_cast<ImagePanel*>( FindChildByName( "GlowImage", true ) );
|
||
|
if ( pGlow )
|
||
|
{
|
||
|
pGlow->SetAlpha( 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_StateImage::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
int nTeam = TF_TEAM_RED;
|
||
|
const CTFHudRobotDestruction_RobotIndicator *pRobotImageParent = dynamic_cast< const CTFHudRobotDestruction_RobotIndicator* >( GetParent()->GetParent() );
|
||
|
if ( pRobotImageParent )
|
||
|
{
|
||
|
nTeam = pRobotImageParent->GetTeamNumber();
|
||
|
}
|
||
|
|
||
|
const char *pszKeyName = nTeam == TF_TEAM_RED ? "redimage" : "blueimage";
|
||
|
const char *pszImageName = inResourceData->GetString( pszKeyName );
|
||
|
if ( pszImageName && pszImageName[0] )
|
||
|
{
|
||
|
m_pImage->SetImage( pszImageName );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFHudRobotDestruction_DeadImage::CTFHudRobotDestruction_DeadImage( Panel *parent, const char *name, const char *pszResFile )
|
||
|
: CTFHudRobotDestruction_StateImage( parent, name, pszResFile )
|
||
|
, m_pRespawnProgressBar( NULL )
|
||
|
{
|
||
|
m_pRespawnProgressBar = new CTFProgressBar( this, "RespawnProgressBar" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_DeadImage::SetProgress( float flProgress )
|
||
|
{
|
||
|
m_pRespawnProgressBar->SetPercentage( flProgress );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFHudRobotDestruction_ActiveImage::CTFHudRobotDestruction_ActiveImage( Panel *parent, const char *name, const char *pszResFile )
|
||
|
: CTFHudRobotDestruction_StateImage( parent, name, pszResFile )
|
||
|
{}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_ActiveImage::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
const CTFHudRobotDestruction_RobotIndicator *pRobotImageParent = dynamic_cast< const CTFHudRobotDestruction_RobotIndicator* >( GetParent()->GetParent() );
|
||
|
if ( pRobotImageParent && pRobotImageParent->GetGroup() )
|
||
|
{
|
||
|
m_pRobotImage->SetImage( pRobotImageParent->GetGroup()->GetHUDIcon() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFHudRobotDestruction_RobotIndicator::CTFHudRobotDestruction_RobotIndicator( vgui::Panel *pParent, const char *pszName, CTFRobotDestruction_RobotGroup *pGroup )
|
||
|
: EditablePanel( pParent, pszName )
|
||
|
, m_hGroup( pGroup )
|
||
|
, m_pNextRobotIndicator( NULL )
|
||
|
, m_pPrevRobotIndicator( NULL )
|
||
|
{
|
||
|
Assert( pGroup );
|
||
|
|
||
|
m_pSwoop = new CControlPointIconSwoop( this, "Swoop" );
|
||
|
m_pSwoop->SetVisible( false );
|
||
|
m_pRobotStateContainer = new EditablePanel( this, "RobotStateContainer" );
|
||
|
m_pDeadPanel = new CTFHudRobotDestruction_DeadImage( m_pRobotStateContainer, "DeadState", "resource/UI/TFHudRobotDestruction_DeadState.res" );
|
||
|
m_pActivePanel = new CTFHudRobotDestruction_ActiveImage( m_pRobotStateContainer, "ActiveState", "resource/UI/TFHudRobotDestruction_ActiveState.res" );
|
||
|
m_pShieldedPanel = new CTFHudRobotDestruction_StateImage( m_pRobotStateContainer, "ShieldedState", "resource/UI/TFHudRobotDestruction_ShieldedState.res" );
|
||
|
m_flHealthPercentage = 0.f;
|
||
|
m_eState = ROBOT_STATE_DEAD;
|
||
|
|
||
|
vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_RobotIndicator::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
LoadControlSettings( "resource/UI/TFHudRobotDestruction_RobotIndicator.res" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_RobotIndicator::PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
m_pSwoop->SetBounds( 0, 0, GetWide(), GetTall() );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_RobotIndicator::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_RobotIndicator::OnTick()
|
||
|
{
|
||
|
if ( !m_hGroup )
|
||
|
{
|
||
|
SetVisible( false );
|
||
|
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
|
||
|
}
|
||
|
|
||
|
UpdateState();
|
||
|
DoUnderAttackBlink();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_RobotIndicator::DoUnderAttackBlink()
|
||
|
{
|
||
|
if ( !m_hGroup.Get() )
|
||
|
return;
|
||
|
|
||
|
if ( gpGlobals->curtime < ( m_hGroup->GetLastAttackedTime() + ATTACK_BLINK_TIME ) && ( GetLocalPlayerTeam() == m_hGroup->GetTeamNumber() ) )
|
||
|
{
|
||
|
// Pulse red
|
||
|
ImagePanel* pGlow = dynamic_cast<ImagePanel*>( FindChildByName( "GlowImage", true ) );
|
||
|
if ( pGlow )
|
||
|
{
|
||
|
float flAlpha = fabs(sin( gpGlobals->curtime * 10.f )) * 255;
|
||
|
pGlow->SetAlpha( flAlpha );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Stop pulsing, stop ticking
|
||
|
ImagePanel* pGlow = dynamic_cast<ImagePanel*>( FindChildByName( "GlowImage", true ) );
|
||
|
if ( pGlow )
|
||
|
{
|
||
|
pGlow->SetAlpha( 0 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CTFHudRobotDestruction_RobotIndicator::GetGroupNumber() const
|
||
|
{
|
||
|
Assert( m_hGroup );
|
||
|
if ( !m_hGroup )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
return m_hGroup->GetGroupNumber();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CTFHudRobotDestruction_RobotIndicator::GetTeamNumber() const
|
||
|
{
|
||
|
Assert( m_hGroup );
|
||
|
if ( !m_hGroup )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return m_hGroup->GetTeamNumber();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHudRobotDestruction_RobotIndicator::UpdateState()
|
||
|
{
|
||
|
// Don't do anything if there's no group
|
||
|
if ( !m_hGroup.Get() )
|
||
|
return;
|
||
|
|
||
|
eRobotUIState eState = (eRobotUIState)m_hGroup->GetState();
|
||
|
|
||
|
// Get the time
|
||
|
float flStartTime = m_hGroup->GetRespawnStartTime();
|
||
|
float flEndTime = m_hGroup->GetRespawnEndTime();
|
||
|
|
||
|
// Show how much time is remaining
|
||
|
m_pDeadPanel->SetDialogVariable( "time", CFmtStr( "%0.0f", Max( 0.f, flEndTime - gpGlobals->curtime ) ) );
|
||
|
|
||
|
// Figure out what percentage we're at
|
||
|
float flDuration = flEndTime - flStartTime;
|
||
|
float flProgress = gpGlobals->curtime - flStartTime;
|
||
|
m_pDeadPanel->SetProgress( flProgress / flDuration );
|
||
|
|
||
|
bool bStateVisibility[ NUM_ROBOT_STATES ];
|
||
|
memset( bStateVisibility, false, sizeof( bStateVisibility ) );
|
||
|
|
||
|
bool bDraw = eState != ROBOT_STATE_INACIVE;
|
||
|
if ( bDraw )
|
||
|
{
|
||
|
m_pRobotStateContainer->SetVisible( true );
|
||
|
bStateVisibility[ eState ] = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pRobotStateContainer->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
m_eState = eState;
|
||
|
|
||
|
bool bShowDead = m_eState == ROBOT_STATE_DEAD;
|
||
|
m_pActivePanel->SetImageVisible( !bShowDead );
|
||
|
|
||
|
m_pDeadPanel->SetVisible( bStateVisibility[ ROBOT_STATE_DEAD ] || bShowDead );
|
||
|
m_pActivePanel->SetVisible( bStateVisibility[ ROBOT_STATE_ACTIVE ] );
|
||
|
m_pShieldedPanel->SetVisible( bStateVisibility[ ROBOT_STATE_SHIELDED ] );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFHUDRobotDestruction::CTFHUDRobotDestruction( Panel *parent, const char *name )
|
||
|
: EditablePanel( parent, name )
|
||
|
, m_bPlayingRD( false )
|
||
|
{
|
||
|
m_pPlayingTo = NULL;
|
||
|
m_pRobotIndicatorKVs = NULL;
|
||
|
|
||
|
m_pCarriedContainer = new EditablePanel( this, "CarriedContainer" );
|
||
|
m_pCarriedImage = new ImagePanel( m_pCarriedContainer, "CarriedImage" );
|
||
|
m_pCarriedFlagProgressBar = new CProgressPanel( m_pCarriedContainer, "CarriedProgressBar" );
|
||
|
m_pScoreContainer = new EditablePanel( this, "ScoreContainer" );
|
||
|
m_pBlueStolenContainer = new EditablePanel( m_pScoreContainer, "BlueStolenContainer" );
|
||
|
m_pBlueDroppedPanel = new EditablePanel( m_pBlueStolenContainer, "DroppedIntelContainer" );
|
||
|
m_pRedStolenContainer = new EditablePanel( m_pScoreContainer, "RedStolenContainer" );
|
||
|
m_pRedDroppedPanel = new EditablePanel( m_pRedStolenContainer, "DroppedIntelContainer" );
|
||
|
|
||
|
m_pBlueScoreValueContainer = new EditablePanel( m_pScoreContainer, "BlueScoreValueContainer" );
|
||
|
m_pRedScoreValueContainer = new EditablePanel( m_pScoreContainer, "RedScoreValueContainer" );
|
||
|
|
||
|
m_pProgressBarsContainer = new EditablePanel( m_pScoreContainer, "ProgressBarContainer" );
|
||
|
m_pBlueVictoryPanel = new EditablePanel( m_pProgressBarsContainer, "BlueVictoryContainer" );
|
||
|
m_pBlueProgressBar = new CProgressPanel( m_pProgressBarsContainer, "BlueProgressBarFill" );
|
||
|
m_pBlueProgressBarEscrow = new CProgressPanel( m_pProgressBarsContainer, "BlueProgressBarEscrow" );
|
||
|
|
||
|
m_pRedVictoryPanel = new EditablePanel( m_pProgressBarsContainer, "RedVictoryContainer" );
|
||
|
m_pRedProgressBar = new CProgressPanel( m_pProgressBarsContainer, "RedProgressBarFill" );
|
||
|
m_pRedProgressBarEscrow = new CProgressPanel( m_pProgressBarsContainer, "RedProgressBarEscrow" );
|
||
|
|
||
|
m_pCountdownContainer = NULL;
|
||
|
m_pTeamLeaderImage = NULL;
|
||
|
|
||
|
vgui::ivgui()->AddTickSignal( GetVPanel(), 50 );
|
||
|
|
||
|
ListenForGameEvent( "rd_rules_state_changed" );
|
||
|
ListenForGameEvent( "flagstatus_update" );
|
||
|
ListenForGameEvent( "rd_team_points_changed" );
|
||
|
ListenForGameEvent( "teamplay_round_start" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFHUDRobotDestruction::~CTFHUDRobotDestruction()
|
||
|
{
|
||
|
if ( m_pRobotIndicatorKVs )
|
||
|
{
|
||
|
m_pRobotIndicatorKVs->deleteThis();
|
||
|
m_pRobotIndicatorKVs = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFHUDRobotDestruction::IsVisible( void )
|
||
|
{
|
||
|
if( IsTakingAFreezecamScreenshot() )
|
||
|
return false;
|
||
|
|
||
|
return BaseClass::IsVisible();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
KeyValues *pItemKV = inResourceData->FindKey( "robot_kv" );
|
||
|
if ( pItemKV )
|
||
|
{
|
||
|
if ( m_pRobotIndicatorKVs )
|
||
|
{
|
||
|
m_pRobotIndicatorKVs->deleteThis();
|
||
|
}
|
||
|
m_pRobotIndicatorKVs = new KeyValues( "robot_kv" );
|
||
|
pItemKV->CopySubkeys( m_pRobotIndicatorKVs );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int SortRobotVec( CTFHudRobotDestruction_RobotIndicator * const *p1, CTFHudRobotDestruction_RobotIndicator * const *p2 )
|
||
|
{
|
||
|
return (*p2)->GetGroupNumber() - (*p1)->GetGroupNumber();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::ApplySchemeSettings( IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
CTFRobotDestructionLogic* pRoboLogic = CTFRobotDestructionLogic::GetRobotDestructionLogic();
|
||
|
|
||
|
if ( !pRoboLogic )
|
||
|
return;
|
||
|
|
||
|
|
||
|
// load control settings...
|
||
|
LoadControlSettings( pRoboLogic->GetResFile() );
|
||
|
|
||
|
// Clear out any old robot panels and bars
|
||
|
m_vecRedRobots.PurgeAndDeleteElements();
|
||
|
m_vecBlueRobots.PurgeAndDeleteElements();
|
||
|
|
||
|
CUtlVector< CTFRobotDestruction_RobotGroup * > vecSeenGroups;
|
||
|
|
||
|
// Go through all the groups in the map, and create a UI element for each one
|
||
|
for ( int i=0; i<IRobotDestructionGroupAutoList::AutoList().Count(); ++i )
|
||
|
{
|
||
|
CTFRobotDestruction_RobotGroup *pGroup = static_cast< CTFRobotDestruction_RobotGroup* >( IRobotDestructionGroupAutoList::AutoList()[i] );
|
||
|
|
||
|
if ( pGroup->IsDormant() )
|
||
|
continue;
|
||
|
|
||
|
if ( vecSeenGroups.Find( pGroup ) != vecSeenGroups.InvalidIndex() )
|
||
|
{
|
||
|
Assert( 0 );
|
||
|
DevMsg( "[RD HUD]: %p seen multiple times!\n", pGroup);
|
||
|
continue;
|
||
|
}
|
||
|
vecSeenGroups.AddToTail( pGroup );
|
||
|
RobotVector_t &robotVec = pGroup->GetTeamNumber() == TF_TEAM_RED ? m_vecRedRobots : m_vecBlueRobots;
|
||
|
const char* pszPanelName = pGroup->GetTeamNumber() == TF_TEAM_RED ? "red" : "blue";
|
||
|
|
||
|
robotVec[ robotVec.AddToTail() ] = new CTFHudRobotDestruction_RobotIndicator( this, CFmtStr( "%s_group_%d", pszPanelName, robotVec.Count() ), pGroup );
|
||
|
}
|
||
|
|
||
|
// Sort them from lowest group to highest group
|
||
|
m_vecRedRobots.Sort( &SortRobotVec );
|
||
|
m_vecBlueRobots.Sort( &SortRobotVec );
|
||
|
|
||
|
m_pCarriedContainer->SetVisible( false );
|
||
|
|
||
|
m_pCountdownContainer = dynamic_cast<EditablePanel*>( FindChildByName( "CountdownContainer" ) );
|
||
|
m_pTeamLeaderImage = dynamic_cast<CTFImagePanel*>( m_pCarriedContainer->FindChildByName( "TeamLeaderImage" ) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
// Sort them from lowest group to highest group
|
||
|
m_vecRedRobots.Sort( &SortRobotVec );
|
||
|
m_vecBlueRobots.Sort( &SortRobotVec );
|
||
|
|
||
|
PerformRobotLayout( m_vecRedRobots, TF_TEAM_RED );
|
||
|
PerformRobotLayout( m_vecBlueRobots, TF_TEAM_BLUE );
|
||
|
|
||
|
int nXPos, nYPos;
|
||
|
m_pProgressBarsContainer->GetPos( nXPos, nYPos );
|
||
|
|
||
|
// Store the edges of the score container
|
||
|
m_nStealLeftEdge = nXPos + m_nStealLeftEdgeOffset - ( m_pRedStolenContainer->GetWide() / 2.f );
|
||
|
m_nStealRightEdge = nXPos + m_pProgressBarsContainer->GetWide() - m_nStealRightEdgeOffset + ( m_pRedStolenContainer->GetWide() / 2.f );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::PerformRobotLayout( RobotVector_t& vecRobots, int nTeam )
|
||
|
{
|
||
|
int nParentX = 0, nParentY = 0, nParentWide = 0, nParentTall = 0;
|
||
|
GetBounds( nParentX, nParentY, nParentWide, nParentTall );
|
||
|
|
||
|
bool bIsRed = nTeam == TF_TEAM_RED;
|
||
|
const int nCenterX = nParentX + ( nParentWide * 0.5f );
|
||
|
int nActiveIndex = 0;
|
||
|
const int nXOffset = m_iRobotXOffset;
|
||
|
const int nYOffest = nParentTall - m_iRobotYOffset;
|
||
|
const int nXStep = m_iRobotXStep;
|
||
|
const int nYStep = m_iRobotYStep;
|
||
|
Panel *pPrevPanel = NULL;
|
||
|
|
||
|
// Position the robot panels, spanning out from the bottom center
|
||
|
FOR_EACH_VEC_BACK( vecRobots, i )
|
||
|
{
|
||
|
CTFHudRobotDestruction_RobotIndicator* pRobot = vecRobots[i];
|
||
|
if ( pRobot )
|
||
|
{
|
||
|
pRobot->ApplySettings( m_pRobotIndicatorKVs );
|
||
|
pRobot->UpdateState();
|
||
|
pRobot->SetZPos( vecRobots.Count() - i );
|
||
|
|
||
|
CTFHudRobotDestruction_RobotIndicator *pPrevRobot = dynamic_cast< CTFHudRobotDestruction_RobotIndicator * >( pPrevPanel );
|
||
|
if ( pPrevRobot )
|
||
|
{
|
||
|
pRobot->SetPrevRobotIndicator( pPrevRobot );
|
||
|
pPrevRobot->SetNextRobotIndicator( pRobot );
|
||
|
}
|
||
|
|
||
|
int nWide = pRobot->GetWide();
|
||
|
// The starting offset
|
||
|
int nStartPos = ( ( nXOffset ) + ( nWide * 0.5f ) ) * (bIsRed ? 1 : -1);
|
||
|
// The offset between each position
|
||
|
int nOffset = bIsRed ? nXStep : -nXStep;
|
||
|
|
||
|
int nXPos = nCenterX + nStartPos + ( nOffset * nActiveIndex ) - ( nWide * 0.5 );
|
||
|
pRobot->SetPos( nXPos, nYOffest - pRobot->GetTall() - ( nYStep * i ) );
|
||
|
|
||
|
pRobot->InvalidateLayout( true, true );
|
||
|
|
||
|
// If the state is anything but ROBOT_STATE_INACTIVE, then it's an active panel
|
||
|
if ( pRobot->GetState() != ROBOT_STATE_INACIVE )
|
||
|
{
|
||
|
pPrevPanel = pRobot;
|
||
|
++nActiveIndex;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::Reset()
|
||
|
{
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FlagOutlineHide" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::SetPlayingToLabelVisible( bool bVisible )
|
||
|
{
|
||
|
if ( m_pPlayingTo && m_pPlayingToBG )
|
||
|
{
|
||
|
if ( m_pPlayingTo->IsVisible() != bVisible )
|
||
|
{
|
||
|
m_pPlayingTo->SetVisible( bVisible );
|
||
|
}
|
||
|
|
||
|
if ( m_pPlayingToBG->IsVisible() != bVisible )
|
||
|
{
|
||
|
m_pPlayingToBG->SetVisible( bVisible );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
ConVar rd_hud_test_bars( "rd_hud_test_bars", 0 );
|
||
|
#endif
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::OnTick()
|
||
|
{
|
||
|
CTFRobotDestructionLogic* pRoboLogic = CTFRobotDestructionLogic::GetRobotDestructionLogic();
|
||
|
|
||
|
bool bPlayindRD = ( pRoboLogic != NULL );
|
||
|
if ( m_bPlayingRD != bPlayindRD )
|
||
|
{
|
||
|
if ( bPlayindRD )
|
||
|
{
|
||
|
InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
m_bPlayingRD = bPlayindRD;
|
||
|
}
|
||
|
|
||
|
if ( !pRoboLogic )
|
||
|
return;
|
||
|
|
||
|
m_pRedScoreValueContainer->SetDialogVariable( "score", pRoboLogic->GetScore( TF_TEAM_RED ) );
|
||
|
m_pBlueScoreValueContainer->SetDialogVariable( "score", pRoboLogic->GetScore( TF_TEAM_BLUE ) );
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
if ( rd_hud_test_bars.GetBool() )
|
||
|
{
|
||
|
float flProgress = (sin( gpGlobals->curtime ) * 0.5f) + 0.5f;
|
||
|
m_pBlueProgressBar->SetProgress( flProgress, true );
|
||
|
m_pRedProgressBar->SetProgress( flProgress, true );
|
||
|
m_pBlueProgressBarEscrow->SetProgress( 0.f, true );
|
||
|
m_pRedProgressBarEscrow->SetProgress( 0.f, true );
|
||
|
|
||
|
m_pRedScoreValueContainer->SetDialogVariable( "score", flProgress );
|
||
|
m_pBlueScoreValueContainer->SetDialogVariable( "score", flProgress );
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
int nBlueEscrow = 0, nRedEscrow = 0;
|
||
|
|
||
|
if ( pRoboLogic->GetType() == CTFRobotDestructionLogic::TYPE_PLAYER_DESTRUCTION )
|
||
|
{
|
||
|
for ( int i=0; i<ICaptureFlagAutoList::AutoList().Count(); ++i )
|
||
|
{
|
||
|
CCaptureFlag *pFlag = static_cast< CCaptureFlag* >( ICaptureFlagAutoList::AutoList()[i] );
|
||
|
|
||
|
if ( pFlag->IsStolen() && pFlag->GetPrevOwner() )
|
||
|
{
|
||
|
int &nFriendScore = pFlag->GetPrevOwner()->GetTeamNumber() == TF_TEAM_RED ? nRedEscrow : nBlueEscrow;
|
||
|
|
||
|
nFriendScore += pFlag->GetPointValue();
|
||
|
m_pRedDroppedPanel->SetAlpha( 255 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_pProgressBarsContainer )
|
||
|
{
|
||
|
m_pProgressBarsContainer->SetDialogVariable( "red_escrow", nRedEscrow );
|
||
|
m_pProgressBarsContainer->SetDialogVariable( "blue_escrow", nBlueEscrow );
|
||
|
}
|
||
|
|
||
|
// update the team leader image
|
||
|
if ( m_pTeamLeaderImage )
|
||
|
{
|
||
|
bool bLocalplayerIsLeader = false;
|
||
|
if ( CTFPlayer::GetLocalTFPlayer() && ( CTFPlayer::GetLocalTFPlayer()->GetTeamNumber() > LAST_SHARED_TEAM ) )
|
||
|
{
|
||
|
if ( CTFPlayer::GetLocalTFPlayer() == pRoboLogic->GetTeamLeader( GetLocalPlayerTeam() ) )
|
||
|
{
|
||
|
bLocalplayerIsLeader = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_pTeamLeaderImage->IsVisible() != bLocalplayerIsLeader )
|
||
|
{
|
||
|
m_pTeamLeaderImage->SetVisible( bLocalplayerIsLeader );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// update the countdowns if they exist
|
||
|
if ( m_pCountdownContainer )
|
||
|
{
|
||
|
float flTimeRemaining = pRoboLogic->GetCountdownEndTime() - gpGlobals->curtime;
|
||
|
if ( flTimeRemaining > -1 )
|
||
|
{
|
||
|
if ( !m_pCountdownContainer->IsVisible() )
|
||
|
{
|
||
|
m_pCountdownContainer->SetVisible( true );
|
||
|
}
|
||
|
|
||
|
ImagePanel* pCountdownImage = dynamic_cast<ImagePanel*>( m_pCountdownContainer->FindChildByName( "CountdownImage", true ) );
|
||
|
if ( pCountdownImage )
|
||
|
{
|
||
|
bool bVisible = true;
|
||
|
|
||
|
if ( pRoboLogic->IsUsingCustomCountdownImage() )
|
||
|
{
|
||
|
const char *pszImage = pRoboLogic->GetCountdownImage();
|
||
|
if ( pszImage && pszImage[0] )
|
||
|
{
|
||
|
pCountdownImage->SetImage( pszImage );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bVisible = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pCountdownImage->IsVisible() != bVisible )
|
||
|
{
|
||
|
pCountdownImage->SetVisible( bVisible );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CExLabel* pCountdownTime = dynamic_cast<CExLabel*>( m_pCountdownContainer->FindChildByName( "CountdownTime", true ) );
|
||
|
CExLabel* pCountdownTimeShadow = dynamic_cast<CExLabel*>( m_pCountdownContainer->FindChildByName( "CountdownTimeShadow", true ) );
|
||
|
if ( pCountdownTime )
|
||
|
{
|
||
|
if ( !pCountdownTime->IsVisible() )
|
||
|
{
|
||
|
pCountdownTime->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
if ( pCountdownTimeShadow )
|
||
|
{
|
||
|
if ( !pCountdownTimeShadow->IsVisible() )
|
||
|
{
|
||
|
pCountdownTimeShadow->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int nCountdownTime = (int)flTimeRemaining;
|
||
|
m_pCountdownContainer->SetDialogVariable( "countdowntime", ( nCountdownTime < 0 ) ? 0 : nCountdownTime );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( m_pCountdownContainer->IsVisible() )
|
||
|
{
|
||
|
m_pCountdownContainer->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Find the flags if we dont have them yet
|
||
|
if ( !m_hRedFlag || !m_hBlueFlag )
|
||
|
{
|
||
|
for ( int i=0; i<ICaptureFlagAutoList::AutoList().Count(); ++i )
|
||
|
{
|
||
|
CCaptureFlag *pFlag = static_cast< CCaptureFlag* >( ICaptureFlagAutoList::AutoList()[i] );
|
||
|
if ( pFlag->GetTeamNumber() == TF_TEAM_BLUE )
|
||
|
{
|
||
|
m_hBlueFlag = pFlag;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_hRedFlag = pFlag;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pRoboLogic->GetType() == CTFRobotDestructionLogic::TYPE_ROBOT_DESTRUCTION )
|
||
|
{
|
||
|
Assert( m_hBlueFlag );
|
||
|
Assert( m_hRedFlag );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// A held flag counts towards the stealing team's escrow.
|
||
|
// A dropped flag counts towards the original team's escrow.
|
||
|
if ( m_hRedFlag && m_hBlueFlag )
|
||
|
{
|
||
|
if ( m_hRedFlag->IsDropped() )
|
||
|
{
|
||
|
nRedEscrow += m_hRedFlag->GetPointValue();
|
||
|
if ( m_hRedFlag->GetReturnProgress() > 0.8f )
|
||
|
{
|
||
|
// Blink when we're close to returning
|
||
|
int nAlpha = int( gpGlobals->curtime * 10 ) % 10 < 5 ? 255 : 0;
|
||
|
m_pRedDroppedPanel->SetAlpha( nAlpha );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nBlueEscrow += m_hRedFlag->GetPointValue();
|
||
|
m_pRedDroppedPanel->SetAlpha( 255 );
|
||
|
}
|
||
|
|
||
|
if ( m_hBlueFlag->IsDropped() )
|
||
|
{
|
||
|
nBlueEscrow += m_hBlueFlag->GetPointValue();
|
||
|
if ( m_hBlueFlag->GetReturnProgress() > 0.8f )
|
||
|
{
|
||
|
// Blink when we're close to returning
|
||
|
int nAlpha = int( gpGlobals->curtime * 10 ) % 10 < 5 ? 255 : 0;
|
||
|
m_pBlueDroppedPanel->SetAlpha( nAlpha );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nRedEscrow += m_hBlueFlag->GetPointValue();
|
||
|
m_pBlueDroppedPanel->SetAlpha( 255 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const float flFinaleTime = pRoboLogic->GetFinaleLength();
|
||
|
// Get red finale progress. We hide the big scores and show the finale countdown if at max score.
|
||
|
float flFinaleProgress = clamp( pRoboLogic->GetFinaleWinTime( TF_TEAM_RED ) - gpGlobals->curtime, 0.f, pRoboLogic->GetFinaleLength() );
|
||
|
m_pRedVictoryPanel->SetVisible( flFinaleProgress < flFinaleTime );
|
||
|
m_pRedScoreValueContainer->SetVisible( flFinaleProgress >= flFinaleTime );
|
||
|
if ( flFinaleProgress < flFinaleTime )
|
||
|
{
|
||
|
m_pRedVictoryPanel->SetDialogVariable( "victorytime", (int)flFinaleProgress );
|
||
|
}
|
||
|
|
||
|
// Get blue finale progress. We hide the big scores and show the finale countdown if at max score.
|
||
|
flFinaleProgress = clamp( pRoboLogic->GetFinaleWinTime( TF_TEAM_BLUE ) - gpGlobals->curtime, 0.f, pRoboLogic->GetFinaleLength() );
|
||
|
m_pBlueVictoryPanel->SetVisible( flFinaleProgress < flFinaleTime );
|
||
|
m_pBlueScoreValueContainer->SetVisible( flFinaleProgress >= flFinaleTime );
|
||
|
if ( flFinaleProgress < flFinaleTime )
|
||
|
{
|
||
|
m_pBlueVictoryPanel->SetDialogVariable( "victorytime", (int)flFinaleProgress );
|
||
|
}
|
||
|
|
||
|
const float flMaxPoints = pRoboLogic->GetMaxPoints();
|
||
|
int nTargetPoints = pRoboLogic->GetTargetScore( TF_TEAM_BLUE );
|
||
|
m_pBlueProgressBar->SetProgress( nTargetPoints / flMaxPoints );
|
||
|
m_pBlueProgressBarEscrow->SetProgress( ( nTargetPoints + nBlueEscrow ) / flMaxPoints );
|
||
|
|
||
|
nTargetPoints = pRoboLogic->GetTargetScore( TF_TEAM_RED );
|
||
|
m_pRedProgressBar->SetProgress( nTargetPoints / flMaxPoints );
|
||
|
m_pRedProgressBarEscrow->SetProgress( ( nTargetPoints + nRedEscrow ) / flMaxPoints );
|
||
|
}
|
||
|
|
||
|
SetPlayingToLabelVisible( true );
|
||
|
SetDialogVariable( "rounds", pRoboLogic->GetMaxPoints() );
|
||
|
// HACK! Fix the events
|
||
|
UpdateCarriedFlagStatus( NULL, NULL );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::PaintBackground()
|
||
|
{
|
||
|
UpdateStolenPoints( TF_TEAM_RED, m_pRedStolenContainer );
|
||
|
UpdateStolenPoints( TF_TEAM_BLUE, m_pBlueStolenContainer );
|
||
|
|
||
|
BaseClass::PaintBackground();
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::PaintPDPlayerScore( const CTFPlayer* pPlayer )
|
||
|
{
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
// Don't draw the number for ourselves
|
||
|
if ( pPlayer == C_BasePlayer::GetLocalPlayer() )
|
||
|
return;
|
||
|
|
||
|
Vector vecPos = pPlayer->GetAbsOrigin();
|
||
|
vecPos.z += VEC_HULL_MAX_SCALED( pPlayer ).z + 20;
|
||
|
|
||
|
int iX, iY;
|
||
|
Vector vecWorld( vecPos.x, vecPos.y, vecPos.z );
|
||
|
if ( GetVectorInHudSpace( vecWorld, iX, iY ) )
|
||
|
{
|
||
|
int iCurrentLeadingPoint = 0;
|
||
|
if ( pPlayer->HasItem() )
|
||
|
{
|
||
|
CCaptureFlag *pFlag = dynamic_cast<CCaptureFlag*>( pPlayer->GetItem() );
|
||
|
if ( pFlag )
|
||
|
{
|
||
|
iCurrentLeadingPoint = pFlag->GetPointValue();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wchar_t wszScore[3];
|
||
|
V_snwprintf( wszScore, ARRAYSIZE( wszScore ), L"%d", iCurrentLeadingPoint );
|
||
|
const int nWidth = V_wcslen( wszScore ) * 15;
|
||
|
|
||
|
// draw the name
|
||
|
vgui::surface()->DrawSetTextFont( m_hPDPlayerScoreFont );
|
||
|
vgui::surface()->DrawSetTextPos( iX - ( nWidth / 2 ), iY );
|
||
|
vgui::surface()->DrawSetTextColor( m_TextColor );
|
||
|
|
||
|
|
||
|
vgui::surface()->DrawPrintText( wszScore, wcslen( wszScore ), vgui::FONT_DRAW_NONADDITIVE );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::Paint()
|
||
|
{
|
||
|
CTFRobotDestructionLogic* pRoboLogic = CTFRobotDestructionLogic::GetRobotDestructionLogic();
|
||
|
if ( pRoboLogic && pRoboLogic->GetType() == CTFRobotDestructionLogic::TYPE_PLAYER_DESTRUCTION )
|
||
|
{
|
||
|
CTFPlayerDestructionLogic* pPDLogic = static_cast< CTFPlayerDestructionLogic* >( pRoboLogic );
|
||
|
PaintPDPlayerScore( pPDLogic->GetRedTeamLeader() );
|
||
|
PaintPDPlayerScore( pPDLogic->GetBlueTeamLeader() );
|
||
|
}
|
||
|
|
||
|
BaseClass::Paint();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::UpdateStolenPoints( int nTeam, EditablePanel* pContainer )
|
||
|
{
|
||
|
CTFRobotDestructionLogic* pRoboLogic = CTFRobotDestructionLogic::GetRobotDestructionLogic();
|
||
|
if ( pRoboLogic )
|
||
|
{
|
||
|
int nStolenPoints = 0;
|
||
|
// Get the stolen score for this team
|
||
|
CCaptureFlag* pTheirFlag = nTeam == TF_TEAM_RED ? m_hRedFlag : m_hBlueFlag;
|
||
|
if ( pTheirFlag )
|
||
|
{
|
||
|
nStolenPoints = pTheirFlag->GetPointValue();
|
||
|
}
|
||
|
// Show the stolen panels if the stolen score is anything
|
||
|
pContainer->SetVisible( nStolenPoints > 0 );
|
||
|
pContainer->SetDialogVariable( "intelvalue", nStolenPoints );
|
||
|
}
|
||
|
|
||
|
// Find our stolen flag
|
||
|
CCaptureFlag *pStolenFlag = nTeam == TF_TEAM_RED ? m_hRedFlag : m_hBlueFlag;
|
||
|
if ( pStolenFlag && pStolenFlag->IsHome() )
|
||
|
{
|
||
|
pStolenFlag = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
C_CaptureZone *pStartCaptureZone = NULL, *pEndCaptureZone = NULL;
|
||
|
// Go through all the capture zones and find ours and theirs
|
||
|
for ( int i = 0; i<ICaptureZoneAutoList::AutoList().Count(); i++ )
|
||
|
{
|
||
|
C_CaptureZone *pCaptureZone = static_cast< C_CaptureZone* >( ICaptureZoneAutoList::AutoList()[i] );
|
||
|
if ( !pCaptureZone->IsDormant() && !pCaptureZone->IsDisabled() )
|
||
|
{
|
||
|
if ( pCaptureZone->GetTeamNumber() == nTeam )
|
||
|
{
|
||
|
pStartCaptureZone = pCaptureZone;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pEndCaptureZone = pCaptureZone;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pStolenFlag && pStartCaptureZone && pEndCaptureZone )
|
||
|
{
|
||
|
// Use the player's pos if the flag is being carried
|
||
|
Vector vecFlagPos = pStolenFlag->GetMoveParent() ? pStolenFlag->GetMoveParent()->GetAbsOrigin() : pStolenFlag->GetAbsOrigin();
|
||
|
// Get the distance of the flag between the cap points
|
||
|
const float flTotalDist = ( pEndCaptureZone->WorldSpaceCenter() - pStartCaptureZone->WorldSpaceCenter() ).Length() - pEndCaptureZone->BoundingRadius() - pStartCaptureZone->BoundingRadius();
|
||
|
const float flFlagDist = ( pEndCaptureZone->WorldSpaceCenter() - vecFlagPos ).Length() - pEndCaptureZone->BoundingRadius();
|
||
|
const float flLerp = clamp( flFlagDist / flTotalDist, 0.f, 1.f );
|
||
|
// Flip for blue team
|
||
|
const float flProgress = nTeam == TF_TEAM_BLUE ? ( 1.f - flLerp ) : flLerp;
|
||
|
|
||
|
// Calc position
|
||
|
int nWide = pContainer->GetWide();
|
||
|
const int nXpos = ( ( m_nStealRightEdge - ( m_nStealLeftEdge + nWide ) ) * flProgress ) + m_nStealLeftEdge;
|
||
|
|
||
|
// Move the panel!
|
||
|
int nDummy, nYpos;
|
||
|
pContainer->GetPos( nDummy, nYpos );
|
||
|
pContainer->SetPos( nXpos, nYpos );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::UpdateCarriedFlagStatus( C_BasePlayer *pNewOwner /*= NULL*/, C_BaseEntity *pFlagEntity /*= NULL*/ )
|
||
|
{
|
||
|
C_TFPlayer *pLocalPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );
|
||
|
|
||
|
// If this is about the other team, we dont care
|
||
|
if ( pNewOwner && pNewOwner->GetTeamNumber() != pLocalPlayer->GetTeamNumber() )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// are we carrying a flag?
|
||
|
CCaptureFlag *pPlayerFlag = NULL;
|
||
|
if ( pLocalPlayer && pLocalPlayer->HasItem() && pLocalPlayer->GetItem()->GetItemID() == TF_ITEM_CAPTURE_FLAG )
|
||
|
{
|
||
|
if ( !pNewOwner || pNewOwner == pLocalPlayer )
|
||
|
{
|
||
|
pPlayerFlag = dynamic_cast< CCaptureFlag* >( pLocalPlayer->GetItem() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !pPlayerFlag && pLocalPlayer && pLocalPlayer == pNewOwner )
|
||
|
{
|
||
|
pPlayerFlag = dynamic_cast< CCaptureFlag* >( pFlagEntity );
|
||
|
}
|
||
|
|
||
|
if ( pPlayerFlag && !pPlayerFlag->IsMarkedForDeletion() && !pPlayerFlag->IsDormant() )
|
||
|
{
|
||
|
m_pCarriedContainer->SetVisible( true );
|
||
|
m_pCarriedContainer->SetDialogVariable( "flagvalue", pPlayerFlag->GetPointValue() );
|
||
|
// make sure the panels are on, set the initial alpha values,
|
||
|
// set the color of the flag we're carrying, and start the animations
|
||
|
if ( m_pCarriedImage && !m_pCarriedImage->IsVisible() )
|
||
|
{
|
||
|
int nTeam;
|
||
|
if ( pPlayerFlag->GetType() == TF_FLAGTYPE_ATTACK_DEFEND ||
|
||
|
pPlayerFlag->GetType() == TF_FLAGTYPE_TERRITORY_CONTROL ||
|
||
|
pPlayerFlag->GetType() == TF_FLAGTYPE_INVADE ||
|
||
|
pPlayerFlag->GetType() == TF_FLAGTYPE_RESOURCE_CONTROL )
|
||
|
{
|
||
|
nTeam = ( ( GetLocalPlayerTeam() == TF_TEAM_BLUE ) ? ( TF_TEAM_BLUE ) : ( TF_TEAM_RED ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// normal CTF behavior (carrying the enemy flag)
|
||
|
nTeam = ( ( GetLocalPlayerTeam() == TF_TEAM_RED ) ? ( TF_TEAM_BLUE ) : ( TF_TEAM_RED ) );
|
||
|
}
|
||
|
|
||
|
m_pCarriedImage->SetVisible( true );
|
||
|
m_pCarriedFlagProgressBar->SetProgress( 0.f, true ); // Slam to 0 instantly
|
||
|
m_pCarriedFlagProgressBar->SetColor( pLocalPlayer->GetTeamNumber() == TF_TEAM_RED ? m_ColorRed : m_ColorBlue );
|
||
|
}
|
||
|
|
||
|
CTFRobotDestructionLogic* pRoboLogic = CTFRobotDestructionLogic::GetRobotDestructionLogic();
|
||
|
if ( pRoboLogic )
|
||
|
{
|
||
|
int nMinToSteal = tf_rd_min_points_to_steal.GetInt();
|
||
|
// Current progress
|
||
|
float flProgress = float( pPlayerFlag->GetPointValue() ) / float( pRoboLogic->GetMaxPoints() );
|
||
|
// What percentage needs to map to the dotted line
|
||
|
const float flProgressAtDottedLine = float( nMinToSteal ) / float( pRoboLogic->GetMaxPoints() );
|
||
|
// This is where in the texture the dotted line is
|
||
|
const float flWhereTheDottedLineIs = 0.25f;
|
||
|
|
||
|
// We want the progress bar range from [0, The dotted line] map to the progress value [0, Min to steal]
|
||
|
if ( flProgress <= flProgressAtDottedLine )
|
||
|
{
|
||
|
flProgress = RemapValClamped( flProgress, 0.f, flProgressAtDottedLine, 0.f, flWhereTheDottedLineIs );
|
||
|
}
|
||
|
else // Make the progress bar range from (The dotted line, 1] map to the progress value(Min to steal, 1]
|
||
|
{
|
||
|
flProgress = RemapValClamped( flProgress, flProgressAtDottedLine, 1.f, flWhereTheDottedLineIs, 1.f );
|
||
|
}
|
||
|
m_pCarriedFlagProgressBar->SetProgress( flProgress );
|
||
|
}
|
||
|
}
|
||
|
else if ( m_pCarriedImage && m_pCarriedImage->IsVisible() )
|
||
|
{
|
||
|
m_pCarriedContainer->SetVisible( false );
|
||
|
m_pCarriedImage->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::UpdateRobotElements()
|
||
|
{
|
||
|
m_vecRedRobots.PurgeAndDeleteElements();
|
||
|
m_vecBlueRobots.PurgeAndDeleteElements();
|
||
|
|
||
|
InvalidateLayout( false, true );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::UpdateStolenFlagStatus( int nTeam, C_BaseEntity *pFlag )
|
||
|
{
|
||
|
CCaptureFlag *pPlayerFlag = dynamic_cast< CCaptureFlag* >( pFlag );
|
||
|
if ( pPlayerFlag )
|
||
|
{
|
||
|
EditablePanel *pStolenContainer = nTeam == TF_TEAM_RED ? m_pRedStolenContainer : m_pBlueStolenContainer;
|
||
|
Panel* pCarriedImage = pStolenContainer->FindChildByName( "IntelImage" );
|
||
|
Panel* pDownImage = pStolenContainer->FindChildByName( "DroppedIntelContainer" );
|
||
|
Assert( pCarriedImage && pDownImage );
|
||
|
|
||
|
if ( !pCarriedImage || !pDownImage )
|
||
|
return;
|
||
|
|
||
|
// Toggle the carried or dropped images
|
||
|
bool bIsDropped = pPlayerFlag->IsDropped();
|
||
|
pCarriedImage->SetVisible( !bIsDropped );
|
||
|
pDownImage->SetVisible( bIsDropped );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFHUDRobotDestruction::FireGameEvent( IGameEvent * pEvent )
|
||
|
{
|
||
|
CTFRobotDestructionLogic* pRoboLogic = CTFRobotDestructionLogic::GetRobotDestructionLogic();
|
||
|
|
||
|
if ( !pRoboLogic )
|
||
|
return;
|
||
|
|
||
|
const char *pszEventName = pEvent->GetName();
|
||
|
|
||
|
if ( FStrEq( "rd_rules_state_changed", pszEventName ) )
|
||
|
{
|
||
|
UpdateRobotElements();
|
||
|
}
|
||
|
else if ( FStrEq( pszEventName, "flagstatus_update" ) )
|
||
|
{
|
||
|
int nVictimID = pEvent->GetInt( "userid" );
|
||
|
C_BasePlayer *pNewOwner = USERID2PLAYER( nVictimID );
|
||
|
|
||
|
int nFlagEntIndex = pEvent->GetInt( "entindex" );
|
||
|
C_BaseEntity *pFlagEntity = ClientEntityList().GetEnt( nFlagEntIndex );
|
||
|
if ( pFlagEntity )
|
||
|
{
|
||
|
UpdateCarriedFlagStatus( pNewOwner, pFlagEntity );
|
||
|
UpdateStolenFlagStatus( pFlagEntity->GetTeamNumber(), pFlagEntity );
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pszEventName, "rd_team_points_changed" ) )
|
||
|
{
|
||
|
// Extract data
|
||
|
int nTeam = pEvent->GetInt( "team" );
|
||
|
int nPoints = pEvent->GetInt( "points" );
|
||
|
RDScoreMethod_t eMethod = RDScoreMethod_t( pEvent->GetInt( "method" ) );
|
||
|
|
||
|
// Figure out which panel and which anim
|
||
|
Panel *pPanel = nTeam == TF_TEAM_RED ? m_pRedScoreValueContainer : m_pBlueScoreValueContainer;
|
||
|
bool bPositive = ( nTeam == GetLocalPlayerTeam() && nPoints > 0 ) || ( nTeam != GetLocalPlayerTeam() && nPoints < 0 );
|
||
|
const char *pszAnimName = bPositive ? "RDPositiveScorePulse" : "RDNegativeScorePulse";
|
||
|
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pPanel, pszAnimName );
|
||
|
|
||
|
// Make the progress bar blink
|
||
|
CProgressPanel *pProgressBar = nTeam == TF_TEAM_RED ? m_pRedProgressBar : m_pBlueProgressBar;
|
||
|
pProgressBar->Blink();
|
||
|
|
||
|
if ( eMethod == SCORE_REACTOR_STEAL )
|
||
|
{
|
||
|
// Make the OTHER team's escrow progress bar blink
|
||
|
CProgressPanel *pEscrowBar = nTeam != TF_TEAM_RED ? m_pRedProgressBarEscrow : m_pBlueProgressBarEscrow;
|
||
|
pEscrowBar->Blink();
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( pszEventName, "teamplay_round_start" ) )
|
||
|
{
|
||
|
// Recalculate the progress speed
|
||
|
float flApproachSpeed = ( tf_rd_points_per_approach.GetInt() / tf_rd_points_approach_interval.GetFloat() ) / pRoboLogic->GetMaxPoints();
|
||
|
m_pBlueProgressBar->SetApproachSpeed( flApproachSpeed );
|
||
|
m_pBlueProgressBarEscrow->SetApproachSpeed( flApproachSpeed );
|
||
|
m_pRedProgressBar->SetApproachSpeed( flApproachSpeed );
|
||
|
m_pRedProgressBarEscrow->SetApproachSpeed( flApproachSpeed );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
CTFHUDRobotDestruction::CProgressPanel::CProgressPanel( vgui::Panel *parent, const char *name )
|
||
|
: BaseClass( parent, name )
|
||
|
, m_nXOrg( 0 )
|
||
|
, m_nYOrg( 0 )
|
||
|
, m_nWideOrg( 0 )
|
||
|
, m_nTallOrg( 0 )
|
||
|
, m_flLastScoreTime( 0.f )
|
||
|
, m_flEndProgress( 0.f )
|
||
|
, m_flCurrentProgress( 0.f )
|
||
|
, m_flLastTick( 0.f )
|
||
|
{
|
||
|
ListenForGameEvent( "teamplay_round_start" );
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::CaptureBounds()
|
||
|
{
|
||
|
GetBounds( m_nXOrg, m_nYOrg, m_nWideOrg, m_nTallOrg );
|
||
|
if ( GetImage() )
|
||
|
{
|
||
|
GetImage()->SetSize( m_nWideOrg, m_nTallOrg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::SetProgress( float flProgress, bool bInstant /*= false*/ )
|
||
|
{
|
||
|
if ( bInstant )
|
||
|
{
|
||
|
m_flEndProgress = m_flCurrentProgress = flProgress;
|
||
|
CalculateSize();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Start ticking if the progress is different
|
||
|
if ( m_flEndProgress != flProgress )
|
||
|
{
|
||
|
vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
|
||
|
m_flLastTick = gpGlobals->curtime;
|
||
|
}
|
||
|
|
||
|
// Set end target
|
||
|
m_flEndProgress = flProgress;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::OnTick()
|
||
|
{
|
||
|
float flDelta = gpGlobals->curtime - m_flLastTick;
|
||
|
m_flLastTick = gpGlobals->curtime;
|
||
|
|
||
|
// Approach the target progress amount
|
||
|
m_flCurrentProgress = Approach( m_flEndProgress, m_flCurrentProgress, flDelta * m_flApproachSpeed );
|
||
|
|
||
|
// Stop ticking if we've met our progress
|
||
|
if ( m_flCurrentProgress == m_flEndProgress )
|
||
|
{
|
||
|
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
|
||
|
}
|
||
|
|
||
|
CalculateSize();
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::PaintBackground()
|
||
|
{
|
||
|
// Resize internal image in here. The other bars use this image too, so we have to move
|
||
|
// it right before we paint or else it will be out of position.
|
||
|
IImage *pImage = GetImage();
|
||
|
if ( pImage )
|
||
|
{
|
||
|
pImage->SetPos( m_bLeftToRight ? -m_nLeftOffset : -m_flXpos, m_nYOrg );
|
||
|
pImage->SetSize( m_nWideOrg, m_nTallOrg );
|
||
|
}
|
||
|
|
||
|
// Find out blink lerp time
|
||
|
const float flBlinkPeriod = 0.25f;
|
||
|
bool bPastBlink = gpGlobals->curtime > ( m_flLastScoreTime + flBlinkPeriod );
|
||
|
// Blink if it's blink time, or else pulse if within threshold, else just be the standard color
|
||
|
float flLerp = bPastBlink ? ( m_flCurrentProgress >= m_flBlinkThreshold ? ( ( sin( gpGlobals->curtime * m_flBlinkRate ) * 0.5f ) + 0.5f ) : 1.f )
|
||
|
: ( (gpGlobals->curtime - m_flLastScoreTime) / flBlinkPeriod );
|
||
|
flLerp = clamp( flLerp, 0.f, 1.f );
|
||
|
const float flInverseLerp = 1.f - flLerp;
|
||
|
// Get out lerped color
|
||
|
Color drawColor( flInverseLerp * m_BrightColor.r() + flLerp * m_StandardColor.r(),
|
||
|
flInverseLerp * m_BrightColor.g() + flLerp * m_StandardColor.g(),
|
||
|
flInverseLerp * m_BrightColor.b() + flLerp * m_StandardColor.b(),
|
||
|
255 );
|
||
|
// Change color in base class (it uses it in PaintBackground)
|
||
|
SetDrawColor( drawColor );
|
||
|
|
||
|
BaseClass::PaintBackground();
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
int nXpos, nYpos;
|
||
|
GetPos( nXpos, nYpos );
|
||
|
SetPos( nXpos + m_nLeftOffset, nYpos );
|
||
|
|
||
|
CaptureBounds();
|
||
|
CalculateSize();
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::Blink()
|
||
|
{
|
||
|
m_flLastScoreTime = gpGlobals->curtime;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::FireGameEvent( IGameEvent * pEvent )
|
||
|
{
|
||
|
const char *pszEventName = pEvent->GetName();
|
||
|
|
||
|
if ( FStrEq( pszEventName, "teamplay_round_start" ) )
|
||
|
{
|
||
|
// We need to reset the timers here in case we changelevel'd
|
||
|
m_flCurrentProgress = 0.f;
|
||
|
m_flEndProgress = 0.f;
|
||
|
|
||
|
// Resize
|
||
|
CalculateSize();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CTFHUDRobotDestruction::CProgressPanel::CalculateSize()
|
||
|
{
|
||
|
// Find xpos
|
||
|
int nProgressWidth = m_nWideOrg - m_nRightOffset - m_nLeftOffset;
|
||
|
m_flXpos = m_bLeftToRight ? m_nXOrg
|
||
|
: ( 1.f - m_flCurrentProgress) * nProgressWidth + m_nXOrg;
|
||
|
|
||
|
// Find width
|
||
|
m_flWidth = m_flCurrentProgress * nProgressWidth;
|
||
|
|
||
|
// Resize
|
||
|
SetBounds( m_flXpos, m_nYOrg, m_flWidth, m_nTallOrg );
|
||
|
}
|