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.
1436 lines
39 KiB
1436 lines
39 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "hudelement.h" |
|
#include "iclientmode.h" |
|
#include <KeyValues.h> |
|
#include <vgui/IScheme.h> |
|
#include <vgui/ISurface.h> |
|
#include <vgui/ISystem.h> |
|
#include <vgui_controls/AnimationController.h> |
|
#include <vgui_controls/EditablePanel.h> |
|
#include <vgui_controls/ImagePanel.h> |
|
#include <vgui/IVGui.h> |
|
#include <vgui/ISurface.h> |
|
#include <vgui/IImage.h> |
|
#include <vgui_controls/Label.h> |
|
|
|
#include "c_playerresource.h" |
|
#include "teamplay_round_timer.h" |
|
#include "utlvector.h" |
|
#include "entity_capture_flag.h" |
|
#include "c_tf_player.h" |
|
#include "c_team.h" |
|
#include "c_tf_team.h" |
|
#include "c_team_objectiveresource.h" |
|
#include "tf_hud_objectivestatus.h" |
|
#include "tf_spectatorgui.h" |
|
#include "teamplayroundbased_gamerules.h" |
|
#include "tf_gamerules.h" |
|
#include "tf_hud_freezepanel.h" |
|
#include "c_func_capture_zone.h" |
|
#include "clientmode_shared.h" |
|
#include "tf_hud_mediccallers.h" |
|
#include "view.h" |
|
#include "prediction.h" |
|
#include "tf_logic_robot_destruction.h" |
|
|
|
using namespace vgui; |
|
|
|
DECLARE_BUILD_FACTORY( CTFArrowPanel ); |
|
DECLARE_BUILD_FACTORY( CTFFlagStatus ); |
|
|
|
DECLARE_HUDELEMENT( CTFFlagCalloutPanel ); |
|
|
|
ConVar tf_rd_flag_ui_mode( "tf_rd_flag_ui_mode", "3", FCVAR_DEVELOPMENTONLY, "When flags are stolen and not visible: 0 = Show outlines (glows), 1 = Show most valuable enemy flag (icons), 2 = Show all enemy flags (icons), 3 = Show all flags (icons)." ); |
|
|
|
extern ConVar tf_flag_caps_per_round; |
|
|
|
void AddSubKeyNamed( KeyValues *pKeys, const char *pszName ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFArrowPanel::CTFArrowPanel( Panel *parent, const char *name ) : vgui::Panel( parent, name ) |
|
{ |
|
m_RedMaterial.Init( "hud/objectives_flagpanel_compass_red", TEXTURE_GROUP_VGUI ); |
|
m_BlueMaterial.Init( "hud/objectives_flagpanel_compass_blue", TEXTURE_GROUP_VGUI ); |
|
m_NeutralMaterial.Init( "hud/objectives_flagpanel_compass_grey", TEXTURE_GROUP_VGUI ); |
|
m_NeutralRedMaterial.Init( "hud/objectives_flagpanel_compass_grey_with_red", TEXTURE_GROUP_VGUI ); |
|
|
|
m_RedMaterialNoArrow.Init( "hud/objectives_flagpanel_compass_red_noArrow", TEXTURE_GROUP_VGUI ); |
|
m_BlueMaterialNoArrow.Init( "hud/objectives_flagpanel_compass_blue_noArrow", TEXTURE_GROUP_VGUI ); |
|
|
|
m_pMaterial = m_NeutralMaterial; |
|
m_bUseRed = false; |
|
m_flNextColorSwitch = 0.0f; |
|
|
|
ivgui()->AddTickSignal( GetVPanel(), 100 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFArrowPanel::OnTick( void ) |
|
{ |
|
if ( !m_hEntity.Get() ) |
|
return; |
|
|
|
C_BaseEntity *pEnt = m_hEntity.Get(); |
|
m_pMaterial = m_NeutralMaterial; |
|
|
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
|
|
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) |
|
{ |
|
if ( m_bUseRed ) |
|
{ |
|
m_pMaterial = m_NeutralRedMaterial; |
|
} |
|
else |
|
{ |
|
m_pMaterial = m_NeutralMaterial; |
|
} |
|
|
|
if ( pEnt && TFGameRules()->GetMannVsMachineAlarmStatus() == true ) |
|
{ |
|
CCaptureFlag *pFlag = dynamic_cast<CCaptureFlag *>( pEnt ); |
|
if ( pFlag && pFlag->IsStolen() ) |
|
{ |
|
if ( m_flNextColorSwitch < gpGlobals->curtime ) |
|
{ |
|
m_flNextColorSwitch = gpGlobals->curtime + 0.2f; |
|
m_bUseRed = !m_bUseRed; |
|
} |
|
} |
|
else |
|
{ |
|
m_bUseRed = false; |
|
} |
|
} |
|
else |
|
{ |
|
m_bUseRed = false; |
|
} |
|
} |
|
else |
|
{ |
|
// figure out what material we need to use |
|
if ( pEnt->GetTeamNumber() == TF_TEAM_RED ) |
|
{ |
|
m_pMaterial = m_RedMaterial; |
|
|
|
if ( pLocalPlayer && ( pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) ) |
|
{ |
|
// is our target a player? |
|
C_BaseEntity *pTargetEnt = pLocalPlayer->GetObserverTarget(); |
|
if ( pTargetEnt && pTargetEnt->IsPlayer() ) |
|
{ |
|
// does our target have the flag and are they carrying the flag we're currently drawing? |
|
C_TFPlayer *pTarget = static_cast< C_TFPlayer* >( pTargetEnt ); |
|
if ( pTarget->HasTheFlag() && ( pTarget->GetItem() == pEnt ) ) |
|
{ |
|
m_pMaterial = m_RedMaterialNoArrow; |
|
} |
|
} |
|
} |
|
} |
|
else if ( pEnt->GetTeamNumber() == TF_TEAM_BLUE ) |
|
{ |
|
m_pMaterial = m_BlueMaterial; |
|
|
|
if ( pLocalPlayer && ( pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) ) |
|
{ |
|
// is our target a player? |
|
C_BaseEntity *pTargetEnt = pLocalPlayer->GetObserverTarget(); |
|
if ( pTargetEnt && pTargetEnt->IsPlayer() ) |
|
{ |
|
// does our target have the flag and are they carrying the flag we're currently drawing? |
|
C_TFPlayer *pTarget = static_cast< C_TFPlayer* >( pTargetEnt ); |
|
if ( pTarget->HasTheFlag() && ( pTarget->GetItem() == pEnt ) ) |
|
{ |
|
m_pMaterial = m_BlueMaterialNoArrow; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
float CTFArrowPanel::GetAngleRotation( void ) |
|
{ |
|
float flRetVal = 0.0f; |
|
|
|
C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() ); |
|
C_BaseEntity *pEnt = m_hEntity.Get(); |
|
|
|
if ( pPlayer && pEnt ) |
|
{ |
|
QAngle vangles; |
|
Vector eyeOrigin; |
|
float zNear, zFar, fov; |
|
|
|
pPlayer->CalcView( eyeOrigin, vangles, zNear, zFar, fov ); |
|
|
|
Vector vecFlag = pEnt->WorldSpaceCenter() - eyeOrigin; |
|
vecFlag.z = 0; |
|
vecFlag.NormalizeInPlace(); |
|
|
|
Vector forward, right, up; |
|
AngleVectors( vangles, &forward, &right, &up ); |
|
forward.z = 0; |
|
right.z = 0; |
|
forward.NormalizeInPlace(); |
|
right.NormalizeInPlace(); |
|
|
|
float dot = DotProduct( vecFlag, forward ); |
|
float angleBetween = acos( dot ); |
|
|
|
dot = DotProduct( vecFlag, right ); |
|
|
|
if ( dot < 0.0f ) |
|
{ |
|
angleBetween *= -1; |
|
} |
|
|
|
flRetVal = RAD2DEG( angleBetween ); |
|
} |
|
|
|
return flRetVal; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFArrowPanel::Paint() |
|
{ |
|
int x = 0; |
|
int y = 0; |
|
ipanel()->GetAbsPos( GetVPanel(), x, y ); |
|
int nWidth = GetWide(); |
|
int nHeight = GetTall(); |
|
|
|
CMatRenderContextPtr pRenderContext( materials ); |
|
pRenderContext->MatrixMode( MATERIAL_MODEL ); |
|
pRenderContext->PushMatrix(); |
|
|
|
VMatrix panelRotation; |
|
panelRotation.Identity(); |
|
MatrixBuildRotationAboutAxis( panelRotation, Vector( 0, 0, 1 ), GetAngleRotation() ); |
|
// MatrixRotate( panelRotation, Vector( 1, 0, 0 ), 5 ); |
|
panelRotation.SetTranslation( Vector( x + nWidth/2, y + nHeight/2, 0 ) ); |
|
pRenderContext->LoadMatrix( panelRotation ); |
|
|
|
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_pMaterial ); |
|
|
|
CMeshBuilder meshBuilder; |
|
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); |
|
|
|
meshBuilder.TexCoord2f( 0, 0, 0 ); |
|
meshBuilder.Position3f( -nWidth/2, -nHeight/2, 0 ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.TexCoord2f( 0, 1, 0 ); |
|
meshBuilder.Position3f( nWidth/2, -nHeight/2, 0 ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.TexCoord2f( 0, 1, 1 ); |
|
meshBuilder.Position3f( nWidth/2, nHeight/2, 0 ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.TexCoord2f( 0, 0, 1 ); |
|
meshBuilder.Position3f( -nWidth/2, nHeight/2, 0 ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
|
|
pMesh->Draw(); |
|
pRenderContext->PopMatrix(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFArrowPanel::IsVisible( void ) |
|
{ |
|
if( IsTakingAFreezecamScreenshot() ) |
|
return false; |
|
|
|
return BaseClass::IsVisible(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFFlagStatus::CTFFlagStatus( Panel *parent, const char *name ) : EditablePanel( parent, name ) |
|
{ |
|
m_pArrow = new CTFArrowPanel( this, "Arrow" ); |
|
m_pStatusIcon = new CTFImagePanel( this, "StatusIcon" ); |
|
m_pBriefcase = new CTFImagePanel( this, "Briefcase" ); |
|
m_hEntity = NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagStatus::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
KeyValues *pConditions = NULL; |
|
|
|
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) |
|
{ |
|
pConditions = new KeyValues( "conditions" ); |
|
|
|
if ( pConditions ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_mvm" ); |
|
} |
|
} |
|
|
|
// load control settings... |
|
LoadControlSettings( "resource/UI/FlagStatus.res", NULL, NULL, pConditions ); |
|
|
|
if ( pConditions ) |
|
{ |
|
pConditions->deleteThis(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFFlagStatus::IsVisible( void ) |
|
{ |
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if ( pPlayer && pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM ) |
|
return false; |
|
|
|
return BaseClass::IsVisible(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagStatus::UpdateStatus( void ) |
|
{ |
|
if ( m_hEntity.Get() ) |
|
{ |
|
CCaptureFlag *pFlag = dynamic_cast<CCaptureFlag *>( m_hEntity.Get() ); |
|
|
|
if ( pFlag ) |
|
{ |
|
const char *pszImage = "../hud/objectives_flagpanel_ico_flag_home"; |
|
const char *pszBombImage = "../hud/bomb_dropped"; |
|
|
|
if ( pFlag->IsDropped() ) |
|
{ |
|
pszImage = "../hud/objectives_flagpanel_ico_flag_dropped"; |
|
} |
|
else if ( pFlag->IsStolen() ) |
|
{ |
|
pszImage = "../hud/objectives_flagpanel_ico_flag_moving"; |
|
pszBombImage = "../hud/bomb_carried"; |
|
} |
|
|
|
if ( m_pStatusIcon ) |
|
{ |
|
m_pStatusIcon->SetImage( pszImage ); |
|
} |
|
|
|
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && m_pBriefcase ) |
|
{ |
|
m_pBriefcase->SetImage( pszBombImage ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFHudFlagObjectives::CTFHudFlagObjectives( Panel *parent, const char *name ) : EditablePanel( parent, name ) |
|
{ |
|
m_pCarriedImage = NULL; |
|
m_pPlayingTo = NULL; |
|
m_bFlagAnimationPlayed = false; |
|
m_bCarryingFlag = false; |
|
m_pSpecCarriedImage = NULL; |
|
m_pPoisonImage = NULL; |
|
m_pPoisonTimeLabel = NULL; |
|
|
|
m_pRedFlag = new CTFFlagStatus( this, "RedFlag" ); |
|
m_pBlueFlag = new CTFFlagStatus( this, "BlueFlag" ); |
|
|
|
m_bPlayingHybrid_CTF_CP = false; |
|
m_bPlayingSpecialDeliveryMode = false; |
|
|
|
vgui::ivgui()->AddTickSignal( GetVPanel(), 250 ); |
|
|
|
ListenForGameEvent( "flagstatus_update" ); |
|
|
|
m_nNumValidFlags = -1; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFHudFlagObjectives::IsVisible( void ) |
|
{ |
|
if( IsTakingAFreezecamScreenshot() ) |
|
return false; |
|
|
|
return BaseClass::IsVisible(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFHudFlagObjectives::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
KeyValues *pConditions = NULL; |
|
|
|
bool bHybrid = TFGameRules() && TFGameRules()->IsPlayingHybrid_CTF_CP(); |
|
bool bMVM = TFGameRules() && TFGameRules()->IsMannVsMachineMode(); |
|
bool bSpecialDeliveryMode = TFGameRules() && TFGameRules()->IsPlayingSpecialDeliveryMode(); |
|
|
|
int nNumFlags = 0; |
|
|
|
if ( m_pRedFlag && m_pRedFlag->GetEntity() != NULL ) |
|
{ |
|
nNumFlags++; |
|
} |
|
|
|
if ( m_pBlueFlag && m_pBlueFlag->GetEntity() != NULL ) |
|
{ |
|
nNumFlags++; |
|
} |
|
|
|
if ( nNumFlags == 2 && m_pRedFlag->GetEntity() == m_pBlueFlag->GetEntity() ) |
|
{ |
|
// They're both pointing at the same flag! There's really only 1 |
|
nNumFlags = 1; |
|
} |
|
|
|
if ( nNumFlags == 0 ) |
|
{ |
|
pConditions = new KeyValues( "conditions" ); |
|
if ( pConditions ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_no_flags" ); |
|
} |
|
|
|
if ( bSpecialDeliveryMode ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_specialdelivery" ); |
|
} |
|
} |
|
else |
|
{ |
|
if ( bHybrid || ( nNumFlags == 1 ) || bMVM || bSpecialDeliveryMode ) |
|
{ |
|
pConditions = new KeyValues( "conditions" ); |
|
if ( pConditions ) |
|
{ |
|
if ( bHybrid ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_hybrid" ); |
|
} |
|
|
|
if ( nNumFlags == 1 || bSpecialDeliveryMode ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_hybrid_single" ); |
|
} |
|
else if ( nNumFlags == 2 ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_hybrid_double" ); |
|
} |
|
|
|
if ( bMVM ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_mvm" ); |
|
} |
|
|
|
if ( bSpecialDeliveryMode ) |
|
{ |
|
AddSubKeyNamed( pConditions, "if_specialdelivery" ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// load control settings... |
|
LoadControlSettings( "resource/UI/HudObjectiveFlagPanel.res", NULL, NULL, pConditions ); |
|
|
|
m_pCarriedImage = dynamic_cast<ImagePanel *>( FindChildByName( "CarriedImage" ) ); |
|
m_pPlayingTo = dynamic_cast<CExLabel *>( FindChildByName( "PlayingTo" ) ); |
|
m_pPlayingToBG = FindChildByName( "PlayingToBG" ); |
|
|
|
m_pCapturePoint = dynamic_cast<CTFArrowPanel *>( FindChildByName( "CaptureFlag" ) ); |
|
|
|
m_pSpecCarriedImage = dynamic_cast<ImagePanel *>( FindChildByName( "SpecCarriedImage" ) ); |
|
|
|
m_pPoisonImage = dynamic_cast<ImagePanel *>( FindChildByName( "PoisonIcon" ) ); |
|
m_pPoisonTimeLabel = dynamic_cast<CExLabel *>( FindChildByName( "PoisonTimeLabel" ) ); |
|
|
|
// outline is always on, so we need to init the alpha to 0 |
|
vgui::Panel *pOutline = FindChildByName( "OutlineImage" ); |
|
if ( pOutline ) |
|
{ |
|
pOutline->SetAlpha( 0 ); |
|
} |
|
|
|
if ( pConditions ) |
|
{ |
|
pConditions->deleteThis(); |
|
} |
|
|
|
UpdateStatus(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFHudFlagObjectives::Reset() |
|
{ |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FlagOutlineHide" ); |
|
|
|
UpdateStatus(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFHudFlagObjectives::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 ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFHudFlagObjectives::OnTick() |
|
{ |
|
int nNumValidFlags = 0; |
|
|
|
// check that our blue panel still points at a valid flag |
|
if ( m_pBlueFlag && m_pBlueFlag->GetEntity() ) |
|
{ |
|
CCaptureFlag *pFlag = dynamic_cast< CCaptureFlag* >( m_pBlueFlag->GetEntity() ); |
|
if ( !pFlag || pFlag->IsDisabled() ) |
|
{ |
|
m_pBlueFlag->SetEntity( NULL ); |
|
} |
|
} |
|
|
|
// check that our red panel still points at a valid flag |
|
if ( m_pRedFlag && m_pRedFlag->GetEntity() ) |
|
{ |
|
CCaptureFlag *pFlag = dynamic_cast< CCaptureFlag* >( m_pRedFlag->GetEntity() ); |
|
if ( !pFlag || pFlag->IsDisabled() ) |
|
{ |
|
m_pRedFlag->SetEntity( NULL ); |
|
} |
|
} |
|
|
|
// iterate through the flags to set their position in our HUD |
|
for ( int i = 0; i<ICaptureFlagAutoList::AutoList().Count(); i++ ) |
|
{ |
|
CCaptureFlag *pFlag = static_cast< CCaptureFlag* >( ICaptureFlagAutoList::AutoList()[i] ); |
|
|
|
if ( !pFlag->IsDisabled() || pFlag->IsVisibleWhenDisabled() ) |
|
{ |
|
if ( pFlag->GetTeamNumber() == TF_TEAM_RED ) |
|
{ |
|
if ( m_pRedFlag ) |
|
{ |
|
bool bNeedsUpdate = m_pRedFlag->GetEntity() != pFlag; |
|
m_pRedFlag->SetEntity( pFlag ); |
|
if ( bNeedsUpdate ) |
|
{ |
|
UpdateStatus(); |
|
} |
|
} |
|
} |
|
else if ( pFlag->GetTeamNumber() == TF_TEAM_BLUE ) |
|
{ |
|
if ( m_pBlueFlag ) |
|
{ |
|
bool bNeedsUpdate = m_pBlueFlag->GetEntity() != pFlag; |
|
m_pBlueFlag->SetEntity( pFlag ); |
|
if ( bNeedsUpdate ) |
|
{ |
|
UpdateStatus(); |
|
} |
|
} |
|
} |
|
else if ( pFlag->GetTeamNumber() == TEAM_UNASSIGNED ) |
|
{ |
|
if ( m_pBlueFlag && !m_pBlueFlag->GetEntity() ) |
|
{ |
|
m_pBlueFlag->SetEntity( pFlag ); |
|
|
|
if ( !m_pBlueFlag->IsVisible() ) |
|
{ |
|
m_pBlueFlag->SetVisible( true ); |
|
} |
|
|
|
if ( m_pRedFlag && m_pRedFlag->IsVisible() ) |
|
{ |
|
m_pRedFlag->SetVisible( false ); |
|
} |
|
} |
|
else if ( m_pRedFlag && !m_pRedFlag->GetEntity() ) |
|
{ |
|
// make sure both panels aren't pointing at the same entity |
|
if ( !m_pBlueFlag || ( pFlag != m_pBlueFlag->GetEntity() ) ) |
|
{ |
|
m_pRedFlag->SetEntity( pFlag ); |
|
|
|
if ( !m_pRedFlag->IsVisible() ) |
|
{ |
|
m_pRedFlag->SetVisible( true ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
nNumValidFlags++; |
|
} |
|
|
|
// VGUI callout panels |
|
if ( CTFRobotDestructionLogic::GetRobotDestructionLogic() && CTFRobotDestructionLogic::GetRobotDestructionLogic()->GetType() == CTFRobotDestructionLogic::TYPE_ROBOT_DESTRUCTION ) |
|
{ |
|
if ( tf_rd_flag_ui_mode.GetInt() && !pFlag->IsDisabled() && !pFlag->IsHome() ) |
|
{ |
|
Vector vecLocation = pFlag->GetAbsOrigin() + Vector( 0.f, 0.f, 18.f ); |
|
CTFFlagCalloutPanel::AddFlagCalloutIfNotFound( pFlag, FLT_MAX, vecLocation ); |
|
} |
|
} |
|
} |
|
|
|
if ( m_nNumValidFlags != nNumValidFlags ) |
|
{ |
|
m_nNumValidFlags = nNumValidFlags; |
|
InvalidateLayout( false, true ); |
|
} |
|
|
|
// are we playing captures for rounds? |
|
if ( !TFGameRules() || ( !TFGameRules()->IsPlayingHybrid_CTF_CP() && !TFGameRules()->IsPlayingSpecialDeliveryMode() && !TFGameRules()->IsMannVsMachineMode() ) ) |
|
{ |
|
if ( tf_flag_caps_per_round.GetInt() > 0 ) |
|
{ |
|
C_TFTeam *pTeam = GetGlobalTFTeam( TF_TEAM_BLUE ); |
|
if ( pTeam ) |
|
{ |
|
SetDialogVariable( "bluescore", pTeam->GetFlagCaptures() ); |
|
} |
|
|
|
pTeam = GetGlobalTFTeam( TF_TEAM_RED ); |
|
if ( pTeam ) |
|
{ |
|
SetDialogVariable( "redscore", pTeam->GetFlagCaptures() ); |
|
} |
|
|
|
SetPlayingToLabelVisible( true ); |
|
SetDialogVariable( "rounds", tf_flag_caps_per_round.GetInt() ); |
|
} |
|
else // we're just playing straight score |
|
{ |
|
C_TFTeam *pTeam = GetGlobalTFTeam( TF_TEAM_BLUE ); |
|
if ( pTeam ) |
|
{ |
|
SetDialogVariable( "bluescore", pTeam->Get_Score() ); |
|
} |
|
|
|
pTeam = GetGlobalTFTeam( TF_TEAM_RED ); |
|
if ( pTeam ) |
|
{ |
|
SetDialogVariable( "redscore", pTeam->Get_Score() ); |
|
} |
|
|
|
SetPlayingToLabelVisible( false ); |
|
} |
|
} |
|
|
|
// check the local player to see if they're spectating, OBS_MODE_IN_EYE, and the target entity is carrying the flag |
|
bool bSpecCarriedImage = false; |
|
CCaptureFlag *pPoisonFlag = NULL; |
|
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( pPlayer ) |
|
{ |
|
if ( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) |
|
{ |
|
// does our target have the flag? |
|
C_BaseEntity *pEnt = pPlayer->GetObserverTarget(); |
|
if ( pEnt && pEnt->IsPlayer() ) |
|
{ |
|
C_TFPlayer *pTarget = static_cast< C_TFPlayer* >( pEnt ); |
|
if ( pTarget->HasTheFlag() ) |
|
{ |
|
bSpecCarriedImage = true; |
|
if ( pTarget->GetTeamNumber() == TF_TEAM_RED ) |
|
{ |
|
if ( m_pSpecCarriedImage ) |
|
{ |
|
m_pSpecCarriedImage->SetImage( "../hud/objectives_flagpanel_carried_blue" ); |
|
} |
|
} |
|
else |
|
{ |
|
if ( m_pSpecCarriedImage ) |
|
{ |
|
m_pSpecCarriedImage->SetImage( "../hud/objectives_flagpanel_carried_red" ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
if ( pPlayer->HasTheFlag() && TFGameRules()->IsPowerupMode() ) |
|
{ |
|
CCaptureFlag *pFlag = dynamic_cast<CCaptureFlag *>( pPlayer->GetItem() ); |
|
if ( pFlag ) |
|
{ |
|
pPoisonFlag = pFlag; |
|
} |
|
} |
|
} |
|
|
|
if ( m_pSpecCarriedImage ) |
|
{ |
|
m_pSpecCarriedImage->SetVisible( bSpecCarriedImage ); |
|
} |
|
|
|
if ( m_pPoisonImage ) |
|
{ |
|
m_pPoisonImage->SetVisible( pPoisonFlag && pPoisonFlag->IsPoisonous() ); |
|
} |
|
|
|
if ( m_pPoisonTimeLabel ) |
|
{ |
|
m_pPoisonTimeLabel->SetVisible( pPoisonFlag && pPoisonFlag->GetPoisonTime() > 0.f && !pPoisonFlag->IsPoisonous() ); |
|
if ( m_pPoisonTimeLabel->IsVisible() ) |
|
{ |
|
int nNumSecondsToPoisonous = pPoisonFlag->GetPoisonTime() - gpGlobals->curtime; |
|
m_pPoisonTimeLabel->SetText( CFmtStr( "%d", nNumSecondsToPoisonous ) ); |
|
} |
|
} |
|
|
|
if ( TFGameRules() ) |
|
{ |
|
if ( m_bPlayingHybrid_CTF_CP != TFGameRules()->IsPlayingHybrid_CTF_CP() ) |
|
{ |
|
m_bPlayingHybrid_CTF_CP = TFGameRules()->IsPlayingHybrid_CTF_CP(); |
|
InvalidateLayout( false, true ); |
|
} |
|
|
|
if ( m_bPlayingSpecialDeliveryMode != TFGameRules()->IsPlayingSpecialDeliveryMode() ) |
|
{ |
|
m_bPlayingSpecialDeliveryMode = TFGameRules()->IsPlayingSpecialDeliveryMode(); |
|
InvalidateLayout( false, true ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFHudFlagObjectives::SetCarriedImage( const char *pchIcon ) |
|
{ |
|
if ( m_pCarriedImage ) |
|
{ |
|
m_pCarriedImage->SetImage( pchIcon ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFHudFlagObjectives::UpdateStatus( C_BasePlayer *pNewOwner /*= NULL*/, C_BaseEntity *pFlagEntity /*= NULL*/ ) |
|
{ |
|
C_TFPlayer *pLocalPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() ); |
|
|
|
// 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 ) |
|
{ |
|
m_bCarryingFlag = true; |
|
|
|
// 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_pBlueFlag && m_pBlueFlag->IsVisible() ) |
|
{ |
|
m_pBlueFlag->SetVisible( false ); |
|
} |
|
|
|
if ( m_pRedFlag && m_pRedFlag->IsVisible() ) |
|
{ |
|
m_pRedFlag->SetVisible( false ); |
|
} |
|
|
|
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 ) ); |
|
} |
|
|
|
|
|
char szImage[ MAX_PATH ]; |
|
pPlayerFlag->GetHudIcon( nTeam, szImage, sizeof( szImage ) ); |
|
|
|
SetCarriedImage( szImage ); |
|
m_pCarriedImage->SetVisible( true ); |
|
} |
|
|
|
if ( !m_bFlagAnimationPlayed ) |
|
{ |
|
m_bFlagAnimationPlayed = true; |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FlagOutline" ); |
|
} |
|
|
|
if ( m_pCapturePoint && !m_pCapturePoint->IsVisible() ) |
|
{ |
|
m_pCapturePoint->SetVisible( true ); |
|
} |
|
|
|
if ( pLocalPlayer && m_pCapturePoint ) |
|
{ |
|
// go through all the capture zones and find ours |
|
for ( int i = 0; i<ICaptureZoneAutoList::AutoList().Count(); i++ ) |
|
{ |
|
C_CaptureZone *pCaptureZone = static_cast< C_CaptureZone* >( ICaptureZoneAutoList::AutoList()[i] ); |
|
if ( !pCaptureZone->IsDormant() ) |
|
{ |
|
if ( pCaptureZone->GetTeamNumber() == pLocalPlayer->GetTeamNumber() && !pCaptureZone->IsDisabled() ) |
|
{ |
|
m_pCapturePoint->SetEntity( pCaptureZone ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
// were we carrying the flag? |
|
if ( m_bCarryingFlag ) |
|
{ |
|
m_bCarryingFlag = false; |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FlagOutline" ); |
|
} |
|
|
|
m_bFlagAnimationPlayed = false; |
|
|
|
if ( m_pCarriedImage && m_pCarriedImage->IsVisible() ) |
|
{ |
|
m_pCarriedImage->SetVisible( false ); |
|
} |
|
|
|
if ( m_pCapturePoint && m_pCapturePoint->IsVisible() ) |
|
{ |
|
m_pCapturePoint->SetVisible( false ); |
|
} |
|
|
|
if ( m_pBlueFlag ) |
|
{ |
|
if ( m_pBlueFlag->GetEntity() != NULL ) |
|
{ |
|
if ( !m_pBlueFlag->IsVisible() ) |
|
{ |
|
m_pBlueFlag->SetVisible( true ); |
|
} |
|
|
|
m_pBlueFlag->UpdateStatus(); |
|
} |
|
else |
|
{ |
|
if ( m_pBlueFlag->IsVisible() ) |
|
{ |
|
m_pBlueFlag->SetVisible( false ); |
|
} |
|
} |
|
} |
|
|
|
if ( m_pRedFlag ) |
|
{ |
|
if ( m_pRedFlag->GetEntity() != NULL ) |
|
{ |
|
if ( !m_pRedFlag->IsVisible() ) |
|
{ |
|
m_pRedFlag->SetVisible( true ); |
|
} |
|
|
|
m_pRedFlag->UpdateStatus(); |
|
} |
|
else |
|
{ |
|
if ( m_pRedFlag->IsVisible() ) |
|
{ |
|
m_pRedFlag->SetVisible( false ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFHudFlagObjectives::FireGameEvent( IGameEvent *event ) |
|
{ |
|
const char *eventName = event->GetName(); |
|
|
|
if ( FStrEq( eventName, "flagstatus_update" ) ) |
|
{ |
|
int nVictimID = event->GetInt( "userid" ); |
|
C_BasePlayer *pNewOwner = USERID2PLAYER( nVictimID ); |
|
|
|
int nFlagEntIndex = event->GetInt( "entindex" ); |
|
C_BaseEntity *pFlagEntity = ClientEntityList().GetEnt( nFlagEntIndex ); |
|
|
|
UpdateStatus( pNewOwner, pFlagEntity ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
#define FLAG_CALLER_WIDE ( XRES( 30 ) ) |
|
#define FLAG_CALLER_TALL ( YRES( 30 ) ) |
|
#define FLAG_CALLER_ARROW_WIDE ( XRES( 8 ) ) |
|
#define FLAG_CALLER_ARROW_TALL ( YRES( 10 ) ) |
|
#define FLAG_CALLER_DISPLAY_ENEMY_ONE 1 |
|
#define FLAG_CALLER_DISPLAY_ENEMY_ALL 2 |
|
#define FLAG_CALLER_DISPLAY_ALL 3 |
|
|
|
CUtlVector< CTFFlagCalloutPanel* > CTFFlagCalloutPanel::m_FlagCalloutPanels; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFFlagCalloutPanel::CTFFlagCalloutPanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, pElementName ) |
|
{ |
|
m_FlagCalloutPanels.AddToTail( this ); |
|
|
|
SetParent( g_pClientMode->GetViewport() ); |
|
|
|
RegisterForRenderGroup( "mid" ); |
|
RegisterForRenderGroup( "commentary" ); |
|
SetHiddenBits( HIDEHUD_MISCSTATUS ); |
|
|
|
// SetBounds( 0, 0, FLAG_CALLER_WIDE, FLAG_CALLER_TALL ); |
|
vgui::ivgui()->AddTickSignal( GetVPanel() ); |
|
|
|
m_pFlagCalloutPanel = new CTFImagePanel( this, "FlagCalloutPanel" ); |
|
m_pFlagValueLabel = new Label( this, "FlagValueLabel", "" ); |
|
m_pFlagStatusIcon = new CTFImagePanel( this, "StatusIcon" ); |
|
|
|
m_flRemoveTime = 1.f; |
|
m_flFirstDisplayTime = 1.f; |
|
m_pArrowMaterial = NULL; |
|
m_iDrawArrow = DRAW_ARROW_UP; |
|
m_bFlagVisible = false; // On screen, line-of-sight |
|
|
|
m_flPrevScale = 0.f; |
|
m_nPanelWideOrig = 0; |
|
m_nPanelTallOrig = 0; |
|
m_nLabelWideOrig = 0; |
|
m_nLabelTallOrig = 0; |
|
m_nIconWideOrig = 0; |
|
m_nIconTallOrig = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFFlagCalloutPanel::~CTFFlagCalloutPanel( void ) |
|
{ |
|
bool bFound = false; |
|
FOR_EACH_VEC_BACK( m_FlagCalloutPanels, i ) |
|
{ |
|
if ( m_FlagCalloutPanels[i] == this ) |
|
{ |
|
m_FlagCalloutPanels.Remove( i ); |
|
bFound = true; |
|
break; |
|
} |
|
} |
|
|
|
// We should have found the panel and returned earlier |
|
Assert( bFound ); |
|
|
|
if ( m_pArrowMaterial ) |
|
{ |
|
m_pArrowMaterial->DecrementReferenceCount(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings( "resource/UI/FlagCalloutPanel.res" ); |
|
|
|
if ( m_pArrowMaterial ) |
|
{ |
|
m_pArrowMaterial->DecrementReferenceCount(); |
|
} |
|
m_pArrowMaterial = materials->FindMaterial( "HUD/medic_arrow", TEXTURE_GROUP_VGUI ); |
|
m_pArrowMaterial->IncrementReferenceCount(); |
|
|
|
if ( !m_pFlagCalloutPanel ) |
|
return; |
|
|
|
if ( !m_pFlagValueLabel ) |
|
return; |
|
|
|
if ( !m_pFlagStatusIcon ) |
|
return; |
|
|
|
m_pFlagCalloutPanel->GetSize( m_nPanelWideOrig, m_nPanelTallOrig ); |
|
m_pFlagValueLabel->GetSize( m_nLabelWideOrig, m_nLabelTallOrig ); |
|
m_pFlagStatusIcon->GetSize( m_nIconWideOrig, m_nIconTallOrig ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::PerformLayout( void ) |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
// SetSize( FLAG_CALLER_WIDE, FLAG_CALLER_TALL ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::GetCalloutPosition( const Vector &vecDelta, float flRadius, float *xpos, float *ypos, float *flRotation ) |
|
{ |
|
// Player Data |
|
QAngle playerAngles = MainViewAngles(); |
|
|
|
Vector forward, right, up( 0.f, 0.f, 1.f ); |
|
AngleVectors( playerAngles, &forward, NULL, NULL ); |
|
forward.z = 0.f; |
|
VectorNormalize( forward ); |
|
CrossProduct( up, forward, right ); |
|
float front = DotProduct( vecDelta, forward ); |
|
float side = DotProduct( vecDelta, right ); |
|
*xpos = flRadius * -side; |
|
*ypos = flRadius * -front; |
|
|
|
// Get the rotation (yaw) |
|
*flRotation = atan2( *xpos, *ypos ) + M_PI; |
|
*flRotation *= 180.f / M_PI; |
|
|
|
float yawRadians = -( *flRotation ) * M_PI / 180.f; |
|
float ca = cos( yawRadians ); |
|
float sa = sin( yawRadians ); |
|
|
|
// Rotate it around the circle |
|
*xpos = (int)( ( ScreenWidth() / 2 ) + ( flRadius * sa ) ); |
|
*ypos = (int)( ( ScreenHeight() / 2 ) - ( flRadius * ca ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::OnTick( void ) |
|
{ |
|
int nDisplayMode = tf_rd_flag_ui_mode.GetInt(); |
|
|
|
// Panels self-manage their existence and visibility |
|
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( !pLocalTFPlayer || !m_hFlag || m_hFlag->IsHome() || m_hFlag->IsDisabled() || !nDisplayMode ) |
|
{ |
|
MarkForDeletion(); |
|
return; |
|
} |
|
|
|
bool bShouldDraw = ShouldShowFlagIconToLocalPlayer(); |
|
|
|
// Only show the most valuable enemy flag in this mode |
|
if ( nDisplayMode == FLAG_CALLER_DISPLAY_ENEMY_ONE ) |
|
{ |
|
int nHighestValue = 0; |
|
CCaptureFlag *pMostValuableFlag = NULL; |
|
|
|
for ( int i = 0; i < ICaptureFlagAutoList::AutoList().Count(); ++i ) |
|
{ |
|
CCaptureFlag *pFlag = static_cast< CCaptureFlag* >( ICaptureFlagAutoList::AutoList()[i] ); |
|
if ( pFlag && pFlag->GetPointValue() > nHighestValue ) |
|
{ |
|
if ( pFlag->IsDisabled() ) |
|
continue; |
|
|
|
if ( pFlag->IsHome() ) |
|
continue; |
|
|
|
if ( pFlag->InSameTeam( pLocalTFPlayer ) ) |
|
continue; |
|
|
|
if ( pFlag->GetPointValue() > nHighestValue ) |
|
{ |
|
nHighestValue = pFlag->GetPointValue(); |
|
pMostValuableFlag = pFlag; |
|
} |
|
} |
|
} |
|
|
|
// If we're not it |
|
if ( pMostValuableFlag != m_hFlag ) |
|
bShouldDraw = false; |
|
} |
|
|
|
if ( IsVisible() != bShouldDraw ) |
|
{ |
|
if ( !IsVisible() ) |
|
{ |
|
m_flFirstDisplayTime = gpGlobals->curtime; |
|
m_flPrevScale = 0.f; |
|
} |
|
|
|
SetVisible( bShouldDraw ); |
|
} |
|
if ( IsEnabled() != bShouldDraw ) |
|
{ |
|
SetEnabled( bShouldDraw ); |
|
} |
|
|
|
if ( !bShouldDraw ) |
|
return; |
|
|
|
bool bCarried = ( !m_hFlag->IsDropped() && m_hFlag->GetPrevOwner() ); |
|
if ( bCarried && !prediction->IsFirstTimePredicted() ) |
|
return; |
|
|
|
// Adjust scale based on distance |
|
Vector vecDistance = m_hFlag->GetAbsOrigin() - pLocalTFPlayer->GetAbsOrigin(); |
|
ScaleAndPositionCallout( RemapValClamped( vecDistance.LengthSqr(), ( 1000.f * 1000.f ), ( 4000.f * 4000.f ), 1.f, 0.6f ) ); |
|
|
|
// Reposition the callout based on our target's position |
|
int iX, iY; |
|
Vector vecTarget = ( bCarried ) ? m_hFlag->GetPrevOwner()->GetAbsOrigin() : m_hFlag->GetAbsOrigin(); |
|
Vector vecDelta = vecTarget - MainViewOrigin(); |
|
bool bOnScreen = GetVectorInHudSpace( vecTarget, iX, iY ); |
|
int nHalfWidth = GetWide() / 2; |
|
|
|
if ( !bOnScreen || iX < nHalfWidth || iX > ScreenWidth() - nHalfWidth ) |
|
{ |
|
// Only show side panel for a short period of time in this mode |
|
if ( TFGameRules() && TFGameRules()->IsPlayingRobotDestructionMode() && gpGlobals->curtime > m_flFirstDisplayTime + 5.f ) |
|
{ |
|
m_iDrawArrow = DRAW_ARROW_UP; |
|
SetAlpha( 0 ); |
|
} |
|
else |
|
{ |
|
// It's off the screen. Position the callout. |
|
VectorNormalize( vecDelta ); |
|
float xpos, ypos; |
|
float flRotation; |
|
float flRadius = YRES( 100 ); |
|
GetCalloutPosition( vecDelta, flRadius, &xpos, &ypos, &flRotation ); |
|
|
|
iX = xpos; |
|
iY = ypos; |
|
|
|
Vector vCenter = m_hFlag->WorldSpaceCenter( ); |
|
if ( MainViewRight().Dot( vCenter - MainViewOrigin() ) > 0 ) |
|
{ |
|
m_iDrawArrow = DRAW_ARROW_RIGHT; |
|
} |
|
else |
|
{ |
|
m_iDrawArrow = DRAW_ARROW_LEFT; |
|
} |
|
|
|
// Move the icon there |
|
SetPos( iX - nHalfWidth, iY - ( GetTall() / 2 ) ); |
|
SetAlpha( 128 ); |
|
} |
|
} |
|
else |
|
{ |
|
// On screen |
|
// If our target isn't visible, we draw transparently |
|
trace_t tr; |
|
UTIL_TraceLine( vecTarget, MainViewOrigin(), MASK_VISIBLE, NULL, COLLISION_GROUP_NONE, &tr ); |
|
if ( tr.fraction >= 1.f ) |
|
{ |
|
m_bFlagVisible = true; |
|
SetAlpha( 0 ); |
|
return; |
|
} |
|
else |
|
{ |
|
m_iDrawArrow = DRAW_ARROW_UP; |
|
SetAlpha( 128 ); |
|
SetPos( iX - nHalfWidth, iY - ( GetTall() / 2 ) ); |
|
} |
|
} |
|
|
|
m_bFlagVisible = false; |
|
|
|
if ( !m_pFlagCalloutPanel ) |
|
return; |
|
|
|
if ( !m_pFlagValueLabel ) |
|
return; |
|
|
|
if ( !m_pFlagStatusIcon ) |
|
return; |
|
|
|
m_pFlagCalloutPanel->SetImage( m_hFlag->GetTeamNumber() == TF_TEAM_BLUE ? "../hud/obj_briefcase_blue" : "../hud/obj_briefcase_red" ); |
|
m_pFlagValueLabel->SetText( CFmtStr( "%i", m_hFlag->GetPointValue() ) ); |
|
|
|
const char *pszImage = "../hud/objectives_flagpanel_ico_flag_home"; |
|
if ( m_hFlag->IsDropped() ) |
|
{ |
|
pszImage = "../hud/objectives_flagpanel_ico_flag_dropped"; |
|
} |
|
else if ( m_hFlag->IsStolen() ) |
|
{ |
|
pszImage = "../hud/objectives_flagpanel_ico_flag_moving"; |
|
} |
|
m_pFlagStatusIcon->SetImage( pszImage ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::PaintBackground( void ) |
|
{ |
|
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( !pLocalTFPlayer ) |
|
return; |
|
|
|
if ( !m_hFlag ) |
|
{ |
|
SetAlpha( 0 ); |
|
return; |
|
} |
|
|
|
BaseClass::PaintBackground(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::Paint( void ) |
|
{ |
|
// Don't draw side panels if our target is visible. The particle effect will be doing it for us. |
|
if ( m_bFlagVisible ) |
|
return; |
|
|
|
BaseClass::Paint(); |
|
|
|
if ( m_iDrawArrow == DRAW_ARROW_UP ) |
|
return; |
|
|
|
float uA, uB, yA, yB; |
|
int x, y; |
|
GetPos( x, y ); |
|
if ( m_iDrawArrow == DRAW_ARROW_LEFT ) |
|
{ |
|
uA = 1.f; |
|
uB = 0.f; |
|
yA = 0.f; |
|
yB = 1.f; |
|
x -= FLAG_CALLER_ARROW_WIDE; |
|
} |
|
else |
|
{ |
|
uA = 0.f; |
|
uB = 1.f; |
|
yA = 0.f; |
|
yB = 1.f; |
|
x += m_pFlagCalloutPanel->GetWide(); |
|
} |
|
|
|
int iyindent = ( GetTall() - FLAG_CALLER_ARROW_TALL ) * 0.5f; |
|
y += iyindent; |
|
|
|
CMatRenderContextPtr pRenderContext( materials ); |
|
pRenderContext->Bind( m_pArrowMaterial ); |
|
IMesh* pMesh = pRenderContext->GetDynamicMesh( true ); |
|
|
|
CMeshBuilder meshBuilder; |
|
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); |
|
|
|
meshBuilder.Position3f( x, y, 0.f ); |
|
meshBuilder.TexCoord2f( 0, uA, yA ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3f( x + FLAG_CALLER_ARROW_WIDE, y, 0.f ); |
|
meshBuilder.TexCoord2f( 0, uB, yA ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3f( x + FLAG_CALLER_ARROW_WIDE, y + FLAG_CALLER_ARROW_TALL, 0.f ); |
|
meshBuilder.TexCoord2f( 0, uB, yB ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3f( x, y + FLAG_CALLER_ARROW_TALL, 0.f ); |
|
meshBuilder.TexCoord2f( 0, uA, yB ); |
|
meshBuilder.Color4ub( 255, 255, 255, 255 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
pMesh->Draw(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::SetFlag( CCaptureFlag *pFlag, float flDuration, Vector &vecOffset ) |
|
{ |
|
m_hFlag = pFlag; |
|
m_flRemoveTime = gpGlobals->curtime + flDuration; |
|
m_vecOffset = vecOffset; |
|
m_flFirstDisplayTime = gpGlobals->curtime; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFFlagCalloutPanel *CTFFlagCalloutPanel::AddFlagCalloutIfNotFound( CCaptureFlag *pFlag, float flDuration, Vector &vecLocation ) |
|
{ |
|
// How this system works: |
|
// CTFHudFlagObjectives::OnTick() will attempt to create one panel per-flag that is stolen. |
|
// CTFFlagCalloutPanel::OnTick() tries to manage whether or not the panel is visible, based on the UI mode. |
|
|
|
// See if we have a panel for this flag already |
|
FOR_EACH_VEC_BACK( m_FlagCalloutPanels, i ) |
|
{ |
|
if ( m_FlagCalloutPanels[i]->m_hFlag == pFlag ) |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
CTFFlagCalloutPanel *pCallout = new CTFFlagCalloutPanel( "FlagCalloutHUD" ); |
|
if ( pCallout ) |
|
{ |
|
pCallout->SetFlag( pFlag, flDuration, vecLocation ); |
|
} |
|
return pCallout; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFFlagCalloutPanel::ShouldShowFlagIconToLocalPlayer( void ) |
|
{ |
|
C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( !pLocalTFPlayer ) |
|
return false; |
|
|
|
int nDisplayMode = tf_rd_flag_ui_mode.GetInt(); |
|
|
|
// In "show all" mode, don't show flags on the local player's team that are being carried |
|
if ( m_hFlag->IsStolen() && |
|
m_hFlag->InSameTeam( pLocalTFPlayer ) && |
|
nDisplayMode == FLAG_CALLER_DISPLAY_ALL ) |
|
return false; |
|
|
|
// In all other modes, don't show flags on the local player's team |
|
if ( m_hFlag->InSameTeam( pLocalTFPlayer ) && |
|
nDisplayMode < FLAG_CALLER_DISPLAY_ALL ) |
|
return false; |
|
|
|
// Don't show the player running this flag |
|
if ( m_hFlag->IsStolen() && pLocalTFPlayer == m_hFlag->GetPrevOwner() ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFFlagCalloutPanel::ScaleAndPositionCallout( float flScale /*= 1.f*/ ) |
|
{ |
|
if ( flScale == m_flPrevScale ) |
|
return; |
|
|
|
SetSize( ( FLAG_CALLER_WIDE * flScale ), ( FLAG_CALLER_TALL * flScale ) ); |
|
|
|
if ( !m_pFlagCalloutPanel ) |
|
return; |
|
|
|
if ( !m_pFlagValueLabel ) |
|
return; |
|
|
|
if ( !m_pFlagStatusIcon ) |
|
return; |
|
|
|
// Briefcase - top-left |
|
m_pFlagCalloutPanel->SetSize( ( m_nPanelWideOrig * flScale ), ( m_nPanelTallOrig * flScale ) ); |
|
m_pFlagCalloutPanel->SetPos( 0, 0 ); |
|
|
|
// Label - centered |
|
m_pFlagValueLabel->SetSize( ( m_nLabelWideOrig * flScale ), ( m_nLabelTallOrig * flScale ) ); |
|
m_pFlagValueLabel->SetPos( ( m_pFlagCalloutPanel->GetWide() - m_pFlagValueLabel->GetWide() ) * 0.5f, ( m_pFlagCalloutPanel->GetWide() - m_pFlagValueLabel->GetTall() ) * 0.65f ); |
|
|
|
// Icon - lower-right |
|
m_pFlagStatusIcon->SetSize( ( m_nIconWideOrig * flScale ), ( m_nIconTallOrig * flScale ) ); |
|
m_pFlagStatusIcon->SetPos( ( m_pFlagCalloutPanel->GetWide() - m_pFlagStatusIcon->GetWide() ) * 1.05f, ( m_pFlagCalloutPanel->GetWide() - m_pFlagStatusIcon->GetTall() ) * 0.85f ); |
|
|
|
m_flPrevScale = flScale; |
|
} |
|
|
|
|