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.
1540 lines
50 KiB
1540 lines
50 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "class_loadout_panel.h"
|
||
|
#include "c_tf_player.h"
|
||
|
#include "vgui_controls/CheckButton.h"
|
||
|
#include "econ_gcmessages.h"
|
||
|
#include "gc_clientsystem.h"
|
||
|
#include "tf_item_system.h"
|
||
|
#include "loadout_preset_panel.h"
|
||
|
#include "econ_item_description.h"
|
||
|
#include "item_style_select_dialog.h"
|
||
|
#include "vgui/IInput.h"
|
||
|
#include "vgui_controls/PanelListPanel.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
extern ConVar tf_respawn_on_loadoutchanges;
|
||
|
|
||
|
ConVar tf_show_preset_explanation_in_class_loadout( "tf_show_preset_explanation_in_class_loadout", "1", FCVAR_HIDDEN | FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
|
||
|
ConVar tf_show_taunt_explanation_in_class_loadout( "tf_show_taunt_explanation_in_class_loadout", "1", FCVAR_HIDDEN | FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
|
||
|
|
||
|
void ParticleSlider_UpdateRequest( int iLoadoutPosition, float value )
|
||
|
{
|
||
|
CClassLoadoutPanel *pPanel = g_pClassLoadoutPanel;
|
||
|
if ( !pPanel )
|
||
|
return;
|
||
|
|
||
|
CEconItemView *pHat = pPanel->GetItemInSlot( iLoadoutPosition );
|
||
|
if ( !pHat )
|
||
|
return;
|
||
|
|
||
|
// does this hat even have a particle effect
|
||
|
static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
|
||
|
uint32 iHasEffect = 0;
|
||
|
if ( !pHat->FindAttribute( pAttrDef_AttachParticleEffect, &iHasEffect ) )
|
||
|
return;
|
||
|
|
||
|
// Check for use head toggle
|
||
|
static CSchemaAttributeDefHandle pAttrDef_UseHeadOrigin( "particle effect use head origin" );
|
||
|
uint32 iUseHead = 0;
|
||
|
if ( !pHat->FindAttribute( pAttrDef_UseHeadOrigin, &iUseHead ) || iUseHead == 0 )
|
||
|
return;
|
||
|
|
||
|
// Look for the attribute and request to change it
|
||
|
static CSchemaAttributeDefHandle pAttrDef_VerticalOffset( "particle effect vertical offset" );
|
||
|
uint32 iOffSet = 0;
|
||
|
if ( !pHat->FindAttribute( pAttrDef_VerticalOffset, &iOffSet ) && value == 0 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const float& flAttrValue = (float&)iOffSet;
|
||
|
if ( value == flAttrValue )
|
||
|
return; // no change do nothing
|
||
|
}
|
||
|
|
||
|
// Send a message to the GC to request a change
|
||
|
GCSDK::CProtoBufMsg<CMsgSetItemEffectVerticalOffset> msg( k_EMsgGCSetItemEffectVerticalOffset );
|
||
|
msg.Body().set_item_id( pHat->GetItemID() );
|
||
|
msg.Body().set_offset( value );
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
}
|
||
|
|
||
|
void HatOffset_Callback( IConVar *pConVar, char const *pOldString, float flOldValue )
|
||
|
{
|
||
|
ConVarRef cVarRef( pConVar );
|
||
|
ParticleSlider_UpdateRequest( LOADOUT_POSITION_HEAD, cVarRef.GetFloat() );
|
||
|
}
|
||
|
ConVar tf_hat_effect_offset( "tf_hat_effect_offset", "0", FCVAR_DEVELOPMENTONLY, "Adjust the position of the unusual effect for your hat.", HatOffset_Callback );
|
||
|
|
||
|
void Misc1Offset_Callback( IConVar *pConVar, char const *pOldString, float flOldValue )
|
||
|
{
|
||
|
ConVarRef cVarRef( pConVar );
|
||
|
ParticleSlider_UpdateRequest( LOADOUT_POSITION_MISC, cVarRef.GetFloat() );
|
||
|
}
|
||
|
ConVar tf_misc1_effect_offset( "tf_misc1_effect_offset", "0", FCVAR_DEVELOPMENTONLY, "Adjust the position of the unusual effect for your hat.", Misc1Offset_Callback );
|
||
|
|
||
|
void Misc2Offset_Callback( IConVar *pConVar, char const *pOldString, float flOldValue )
|
||
|
{
|
||
|
ConVarRef cVarRef( pConVar );
|
||
|
ParticleSlider_UpdateRequest( LOADOUT_POSITION_MISC2, cVarRef.GetFloat() );
|
||
|
}
|
||
|
ConVar tf_misc2_effect_offset( "tf_misc2_effect_offset", "0", FCVAR_DEVELOPMENTONLY, "Adjust the position of the unusual effect for your hat.", Misc2Offset_Callback );
|
||
|
|
||
|
|
||
|
// Hacky solution to different classes wanting different slots visible in their loadouts, and in different positions
|
||
|
struct LoadoutPanelPositioningInstance
|
||
|
{
|
||
|
int m_iPos[NUM_ITEM_PANELS_IN_LOADOUT];
|
||
|
};
|
||
|
|
||
|
bool IsTauntPanelPosition( int iButtonPos )
|
||
|
{
|
||
|
return iButtonPos >= 9 && iButtonPos <= 16;
|
||
|
}
|
||
|
|
||
|
const LoadoutPanelPositioningInstance g_DefaultLoadoutPanelPositioning =
|
||
|
{
|
||
|
{
|
||
|
1, // LOADOUT_POSITION_PRIMARY = 0,
|
||
|
2, // LOADOUT_POSITION_SECONDARY,
|
||
|
3, // LOADOUT_POSITION_MELEE,
|
||
|
0, // LOADOUT_POSITION_UTILITY, // STAGING ONLY
|
||
|
0, // LOADOUT_POSITION_BUILDING,
|
||
|
0, // LOADOUT_POSITION_PDA,
|
||
|
0, // LOADOUT_POSITION_PDA2,
|
||
|
5, // LOADOUT_POSITION_HEAD,
|
||
|
6, // LOADOUT_POSITION_MISC,
|
||
|
8, // LOADOUT_POSITION_ACTION,
|
||
|
7, // LOADOUT_POSITION_MISC2,
|
||
|
9, // LOADOUT_POSITION_TAUNT,
|
||
|
10, // LOADOUT_POSITION_TAUNT2,
|
||
|
11, // LOADOUT_POSITION_TAUNT3,
|
||
|
12, // LOADOUT_POSITION_TAUNT4,
|
||
|
13, // LOADOUT_POSITION_TAUNT5,
|
||
|
14, // LOADOUT_POSITION_TAUNT6,
|
||
|
15, // LOADOUT_POSITION_TAUNT7,
|
||
|
16, // LOADOUT_POSITION_TAUNT8,
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
0, // LOADOUT_POSITION_PDA_ADDON1,
|
||
|
0, // LOADOUT_POSITION_PDA_ADDON2,
|
||
|
0, // LOADOUT_POSITION_PDA3,
|
||
|
//9, // LOADOUT_POSITION_MISC3,
|
||
|
//10, // LOADOUT_POSITION_MISC4,
|
||
|
//11, // LOADOUT_POSITION_MISC5,
|
||
|
//12, // LOADOUT_POSITION_MISC6,
|
||
|
//13, // LOADOUT_POSITION_MISC7,
|
||
|
//14, // LOADOUT_POSITION_MISC8,
|
||
|
//15, // LOADOUT_POSITION_MISC9,
|
||
|
//16, // LOADOUT_POSITION_MISC10,
|
||
|
0, // LOADOUT_POSITION_BUILDING2,
|
||
|
#endif // STAGING_ONLY
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const LoadoutPanelPositioningInstance g_LoadoutPanelPositioning_Spy =
|
||
|
{
|
||
|
{
|
||
|
0, // LOADOUT_POSITION_PRIMARY = 0,
|
||
|
1, // LOADOUT_POSITION_SECONDARY,
|
||
|
2, // LOADOUT_POSITION_MELEE,
|
||
|
0, // LOADOUT_POSITION_UTILITY, // STAGING ONLY
|
||
|
4, // LOADOUT_POSITION_BUILDING, // sapper
|
||
|
0, // LOADOUT_POSITION_PDA, // disguise kit (Hidden)
|
||
|
3, // LOADOUT_POSITION_PDA2, // Watch
|
||
|
5, // LOADOUT_POSITION_HEAD,
|
||
|
6, // LOADOUT_POSITION_MISC,
|
||
|
8, // LOADOUT_POSITION_ACTION,
|
||
|
7, // LOADOUT_POSITION_MISC2,
|
||
|
9, // LOADOUT_POSITION_TAUNT,
|
||
|
10, // LOADOUT_POSITION_TAUNT2,
|
||
|
11, // LOADOUT_POSITION_TAUNT3,
|
||
|
12, // LOADOUT_POSITION_TAUNT4,
|
||
|
13, // LOADOUT_POSITION_TAUNT5,
|
||
|
14, // LOADOUT_POSITION_TAUNT6,
|
||
|
15, // LOADOUT_POSITION_TAUNT7,
|
||
|
16, // LOADOUT_POSITION_TAUNT8,
|
||
|
#ifdef STAGING_ONLY
|
||
|
0, // LOADOUT_POSITION_PDA_ADDON1,
|
||
|
0, // LOADOUT_POSITION_PDA_ADDON2,
|
||
|
0, // LOADOUT_POSITION_PDA3,
|
||
|
//9, // LOADOUT_POSITION_MISC3,
|
||
|
//10, // LOADOUT_POSITION_MISC4,
|
||
|
//11, // LOADOUT_POSITION_MISC5,
|
||
|
//12, // LOADOUT_POSITION_MISC6,
|
||
|
//13, // LOADOUT_POSITION_MISC7,
|
||
|
//14, // LOADOUT_POSITION_MISC8,
|
||
|
//15, // LOADOUT_POSITION_MISC9,
|
||
|
//16, // LOADOUT_POSITION_MISC10,
|
||
|
0, // LOADOUT_POSITION_BUILDING2,
|
||
|
#endif // STAGING_ONLY
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const LoadoutPanelPositioningInstance g_LoadoutPanelPositioning_Engineer =
|
||
|
{
|
||
|
{
|
||
|
1, // LOADOUT_POSITION_PRIMARY = 0,
|
||
|
2, // LOADOUT_POSITION_SECONDARY,
|
||
|
3, // LOADOUT_POSITION_MELEE,
|
||
|
0, // LOADOUT_POSITION_UTILITY, // STAGING ONLY
|
||
|
0, // LOADOUT_POSITION_BUILDING,
|
||
|
4, // LOADOUT_POSITION_PDA,
|
||
|
0, // LOADOUT_POSITION_PDA2,
|
||
|
5, // LOADOUT_POSITION_HEAD,
|
||
|
6, // LOADOUT_POSITION_MISC,
|
||
|
8, // LOADOUT_POSITION_ACTION,
|
||
|
7, // LOADOUT_POSITION_MISC2,
|
||
|
9, // LOADOUT_POSITION_TAUNT,
|
||
|
10, // LOADOUT_POSITION_TAUNT2,
|
||
|
11, // LOADOUT_POSITION_TAUNT3,
|
||
|
12, // LOADOUT_POSITION_TAUNT4,
|
||
|
13, // LOADOUT_POSITION_TAUNT5,
|
||
|
14, // LOADOUT_POSITION_TAUNT6,
|
||
|
15, // LOADOUT_POSITION_TAUNT7,
|
||
|
16, // LOADOUT_POSITION_TAUNT8,
|
||
|
#ifdef STAGING_ONLY
|
||
|
17, // LOADOUT_POSITION_PDA_ADDON1,
|
||
|
18, // LOADOUT_POSITION_PDA_ADDON2,
|
||
|
0, // LOADOUT_POSITION_PDA3,
|
||
|
//9, // LOADOUT_POSITION_MISC3,
|
||
|
//10, // LOADOUT_POSITION_MISC4,
|
||
|
//11, // LOADOUT_POSITION_MISC5,
|
||
|
//12, // LOADOUT_POSITION_MISC6,
|
||
|
//13, // LOADOUT_POSITION_MISC7,
|
||
|
//14, // LOADOUT_POSITION_MISC8,
|
||
|
//15, // LOADOUT_POSITION_MISC9,
|
||
|
//16, // LOADOUT_POSITION_MISC10,
|
||
|
0, // LOADOUT_POSITION_BUILDING2,
|
||
|
#endif // STAGING_ONLY
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const LoadoutPanelPositioningInstance *g_VisibleLoadoutSlotsPerClass[] =
|
||
|
{
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_UNDEFINED
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_SCOUT
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_SNIPER
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_SOLDIER
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_DEMOMAN
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_MEDIC
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_HEAVYWEAPONS
|
||
|
&g_DefaultLoadoutPanelPositioning, // TF_CLASS_PYRO
|
||
|
&g_LoadoutPanelPositioning_Spy, // TF_CLASS_SPY
|
||
|
&g_LoadoutPanelPositioning_Engineer, // TF_CLASS_ENGINEER
|
||
|
};
|
||
|
|
||
|
COMPILE_TIME_ASSERT( ARRAYSIZE( g_VisibleLoadoutSlotsPerClass ) == TF_LAST_NORMAL_CLASS );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Particle Effect Slider
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CLoadoutItemOptionsPanel::CLoadoutItemOptionsPanel( Panel *parent, const char *pName ) : vgui::EditablePanel( parent, pName )
|
||
|
{
|
||
|
m_pHatParticleSlider = NULL;
|
||
|
m_pHatParticleUseHeadButton = NULL;
|
||
|
|
||
|
m_iCurrentClassIndex = -1;
|
||
|
m_eItemSlot = LOADOUT_POSITION_INVALID;
|
||
|
|
||
|
m_pListPanel = new vgui::PanelListPanel( this, "PanelListPanel" );
|
||
|
m_pListPanel->SetFirstColumnWidth( 0 );
|
||
|
m_pHatParticleSlider = new CCvarSlider( m_pListPanel, "HatParticleSlider" );
|
||
|
m_pHatParticleSlider->AddActionSignalTarget( this );
|
||
|
m_pHatParticleUseHeadButton = new vgui::CheckButton( m_pListPanel, "HatUseHeadCheckButton", "#GameUI_ParticleHatUseHead" );
|
||
|
m_pHatParticleUseHeadButton->AddActionSignalTarget( this );
|
||
|
m_pSetStyleButton = new CExButton( m_pListPanel, "SetStyleButton", "#TF_Item_SelectStyle" );
|
||
|
m_pSetStyleButton->AddActionSignalTarget( this );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
LoadControlSettings( "resource/UI/ItemOptionsPanel.res" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::PerformLayout( void )
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
m_pHatParticleSlider->SetTickColor( Color( 235, 226, 202, 255 ) ); // tanlight
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::OnCommand( const char *command )
|
||
|
{
|
||
|
if ( FStrEq( command, "particle_button_clicked" ) )
|
||
|
{
|
||
|
UpdateItemOptionsUI();
|
||
|
return;
|
||
|
}
|
||
|
else if ( FStrEq( command, "particle_use_head_clicked" ) )
|
||
|
{
|
||
|
// Grab current hat
|
||
|
CEconItemView *pHat = TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, m_eItemSlot );
|
||
|
if ( !pHat )
|
||
|
return;
|
||
|
|
||
|
// does this hat even have a particle effect
|
||
|
static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
|
||
|
uint32 iHasEffect = 0;
|
||
|
if ( !pHat->FindAttribute( pAttrDef_AttachParticleEffect, &iHasEffect ) )
|
||
|
return;
|
||
|
|
||
|
// Send a message to the GC to request a change
|
||
|
GCSDK::CProtoBufMsg<CMsgSetHatEffectUseHeadOrigin> msg( k_EMsgGCSetHatEffectUseHeadOrigin );
|
||
|
msg.Body().set_item_id( pHat->GetItemID() );
|
||
|
msg.Body().set_use_head( m_pHatParticleUseHeadButton->IsSelected() );
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
return;
|
||
|
}
|
||
|
else if ( FStrEq( command, "set_style" ) )
|
||
|
{
|
||
|
CEconItemView *pHat = TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, m_eItemSlot );
|
||
|
CStyleSelectDialog *pStyle = vgui::SETUP_PANEL( new CStyleSelectDialog( GetParent(), pHat ) );
|
||
|
if ( pStyle )
|
||
|
{
|
||
|
pStyle->Show();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::OnMessage( const KeyValues* pParams, vgui::VPANEL hFromPanel )
|
||
|
{
|
||
|
if ( FStrEq( pParams->GetName(), "SliderDragEnd" ) )
|
||
|
{
|
||
|
m_pHatParticleSlider->ApplyChanges();
|
||
|
}
|
||
|
|
||
|
BaseClass::OnMessage( pParams, hFromPanel );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::SetItemSlot( loadout_positions_t eItemSlot, int iClassIndex )
|
||
|
{
|
||
|
m_eItemSlot = eItemSlot;
|
||
|
m_iCurrentClassIndex = iClassIndex;
|
||
|
// Init the Slider based on the slot
|
||
|
const char * pszConVarName = NULL;
|
||
|
|
||
|
switch ( eItemSlot )
|
||
|
{
|
||
|
case LOADOUT_POSITION_HEAD :
|
||
|
pszConVarName = "tf_hat_effect_offset";
|
||
|
break;
|
||
|
case LOADOUT_POSITION_MISC :
|
||
|
pszConVarName = "tf_misc1_effect_offset";
|
||
|
break;
|
||
|
case LOADOUT_POSITION_MISC2 :
|
||
|
pszConVarName = "tf_misc2_effect_offset";
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( pszConVarName )
|
||
|
{
|
||
|
m_pHatParticleSlider->SetupSlider( -8, 8, pszConVarName, false );
|
||
|
}
|
||
|
|
||
|
m_pHatParticleSlider->SetTickColor( Color( 235, 226, 202, 255 ) ); // tanlight
|
||
|
m_pHatParticleSlider->SetTickCaptions( "", "" );
|
||
|
|
||
|
UpdateItemOptionsUI();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::UpdateItemOptionsUI()
|
||
|
{
|
||
|
if ( m_eItemSlot == LOADOUT_POSITION_INVALID )
|
||
|
return;
|
||
|
|
||
|
m_pListPanel->RemoveAll();
|
||
|
|
||
|
// Add controls for various item options
|
||
|
AddControlsParticleEffect();
|
||
|
AddControlsSetStyle();
|
||
|
|
||
|
// Bail if no controls added
|
||
|
if ( m_pListPanel->GetItemCount() == 0 )
|
||
|
{
|
||
|
// We should have some controls if we get to this point.
|
||
|
Assert( 0 );
|
||
|
SetVisible( false );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Resize the background and list panel to contain all the controls
|
||
|
int nVertPixels = m_pListPanel->ComputeVPixelsNeeded();
|
||
|
int nNewTall = Min( 200, nVertPixels );
|
||
|
m_pListPanel->SetTall( nNewTall );
|
||
|
SetTall( nNewTall );
|
||
|
InvalidateLayout( true, false );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::AddControlsParticleEffect( void ) const
|
||
|
{
|
||
|
m_pHatParticleUseHeadButton->SetVisible( false );
|
||
|
m_pHatParticleSlider->SetVisible( false );
|
||
|
|
||
|
CEconItemView *pItem = TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, m_eItemSlot );
|
||
|
if ( pItem )
|
||
|
{
|
||
|
// does this hat even have a particle effect
|
||
|
static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
|
||
|
uint32 iValue = 0;
|
||
|
if ( pItem->FindAttribute( pAttrDef_AttachParticleEffect, &iValue ) )
|
||
|
{
|
||
|
m_pHatParticleUseHeadButton->SetVisible( true );
|
||
|
m_pListPanel->AddItem( NULL, m_pHatParticleUseHeadButton );
|
||
|
m_pListPanel->AddItem( NULL, m_pHatParticleSlider );
|
||
|
|
||
|
// Check for use head toggle
|
||
|
static CSchemaAttributeDefHandle pAttrDef_UseHeadOrigin( "particle effect use head origin" );
|
||
|
uint32 iUseHead = 0;
|
||
|
if ( pItem->FindAttribute( pAttrDef_UseHeadOrigin, &iUseHead ) && iUseHead > 0 )
|
||
|
{
|
||
|
m_pHatParticleSlider->SetVisible( true );
|
||
|
|
||
|
m_pHatParticleUseHeadButton->SetSelected( true );
|
||
|
m_pHatParticleSlider->SetTickColor( Color( 235, 226, 202, 255 ) ); // tanlight
|
||
|
m_pHatParticleSlider->Repaint();
|
||
|
|
||
|
// Get offset if it exists
|
||
|
static CSchemaAttributeDefHandle pAttrDef_VerticalOffset( "particle effect vertical offset" );
|
||
|
uint32 iOffset = 0;
|
||
|
if ( pItem->FindAttribute( pAttrDef_VerticalOffset, &iOffset ) )
|
||
|
{
|
||
|
m_pHatParticleSlider->SetSliderValue( (float&)iOffset );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pHatParticleUseHeadButton->SetSelected( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CLoadoutItemOptionsPanel::AddControlsSetStyle( void ) const
|
||
|
{
|
||
|
m_pSetStyleButton->SetVisible( false );
|
||
|
|
||
|
CEconItemView *pItem = GetItem();
|
||
|
if ( pItem && pItem->GetStaticData()->GetNumStyles() )
|
||
|
{
|
||
|
m_pSetStyleButton->SetVisible( true );
|
||
|
m_pListPanel->AddItem( NULL, m_pSetStyleButton );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CEconItemView* CLoadoutItemOptionsPanel::GetItem( void ) const
|
||
|
{
|
||
|
return TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, m_eItemSlot );
|
||
|
}
|
||
|
|
||
|
CClassLoadoutPanel *g_pClassLoadoutPanel = NULL;
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CClassLoadoutPanel::CClassLoadoutPanel( vgui::Panel *parent )
|
||
|
: CBaseLoadoutPanel( parent, "class_loadout_panel" )
|
||
|
, m_pItemOptionPanelKVs( NULL )
|
||
|
{
|
||
|
m_iCurrentClassIndex = TF_CLASS_UNDEFINED;
|
||
|
m_iCurrentTeamIndex = TF_TEAM_RED;
|
||
|
m_iCurrentSlotIndex = -1;
|
||
|
m_pPlayerModelPanel = NULL;
|
||
|
m_pSelectionPanel = NULL;
|
||
|
m_pTauntHintLabel = NULL;
|
||
|
m_pTauntLabel = NULL;
|
||
|
m_pTauntCaratLabel = NULL;
|
||
|
m_pPassiveAttribsLabel = NULL;
|
||
|
m_pLoadoutPresetPanel = NULL;
|
||
|
m_pPresetsExplanationPopup = NULL;
|
||
|
m_pTauntsExplanationPopup = NULL;
|
||
|
m_pBuildablesButton = NULL;
|
||
|
|
||
|
m_pCharacterLoadoutButton = NULL;
|
||
|
m_pTauntLoadoutButton = NULL;
|
||
|
|
||
|
m_bInTauntLoadoutMode = false;
|
||
|
|
||
|
g_pClassLoadoutPanel = this;
|
||
|
|
||
|
m_pItemOptionPanel = new CLoadoutItemOptionsPanel( this, "ItemOptionsPanel" );
|
||
|
}
|
||
|
|
||
|
CClassLoadoutPanel::~CClassLoadoutPanel()
|
||
|
{
|
||
|
if ( m_pItemOptionPanelKVs )
|
||
|
{
|
||
|
m_pItemOptionPanelKVs->deleteThis();
|
||
|
m_pItemOptionPanelKVs = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
LoadControlSettings( "Resource/UI/ClassLoadoutPanel.res" );
|
||
|
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
m_pPlayerModelPanel = dynamic_cast<CTFPlayerModelPanel*>( FindChildByName("classmodelpanel") );
|
||
|
m_pTauntHintLabel = dynamic_cast<vgui::Label*>( FindChildByName("TauntHintLabel") );
|
||
|
m_pTauntLabel = dynamic_cast<CExLabel*>( FindChildByName("TauntLabel") );
|
||
|
m_pTauntCaratLabel = dynamic_cast<CExLabel*>( FindChildByName("TauntCaratLabel") );
|
||
|
m_pBuildablesButton = dynamic_cast<CExButton*>( FindChildByName("BuildablesButton") );
|
||
|
m_pCharacterLoadoutButton = dynamic_cast<CExImageButton*>( FindChildByName("CharacterLoadoutButton") );
|
||
|
m_pTauntLoadoutButton = dynamic_cast<CExImageButton*>( FindChildByName("TauntLoadoutButton") );
|
||
|
m_pPassiveAttribsLabel = dynamic_cast<CExLabel*>( FindChildByName("PassiveAttribsLabel") );
|
||
|
m_pLoadoutPresetPanel = dynamic_cast<CLoadoutPresetPanel*>( FindChildByName( "loadout_preset_panel" ) );
|
||
|
m_pPresetsExplanationPopup = dynamic_cast<CExplanationPopup*>( FindChildByName( "PresetsExplanation" ) );
|
||
|
m_pTauntsExplanationPopup = dynamic_cast<CExplanationPopup*>( FindChildByName( "TauntsExplanation" ) );
|
||
|
m_pTopLinePanel = FindChildByName( "TopLine" );
|
||
|
if ( m_pPassiveAttribsLabel )
|
||
|
{
|
||
|
m_pPassiveAttribsLabel->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
|
||
|
m_pMouseOverTooltip->SetPositioningStrategy( IPTTP_BOTTOM_SIDE );
|
||
|
|
||
|
m_aDefaultColors[LOADED][FG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDefaultColorFg", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[LOADED][FG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetArmedColorFg", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[LOADED][FG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDepressedColorFg", Color( 255, 255, 255, 255 ) );
|
||
|
|
||
|
m_aDefaultColors[LOADED][BG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDefaultColorBg", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[LOADED][BG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetArmedColorBg", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[LOADED][BG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDepressedColorBg", Color( 255, 255, 255, 255 ) );
|
||
|
|
||
|
m_aDefaultColors[NOTLOADED][FG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.TextColor", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[NOTLOADED][FG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.ArmedTextColor", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[NOTLOADED][FG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.DepressedTextColor", Color( 255, 255, 255, 255 ) );
|
||
|
|
||
|
m_aDefaultColors[NOTLOADED][BG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.BgColor", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[NOTLOADED][BG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.ArmedBgColor", Color( 255, 255, 255, 255 ) );
|
||
|
m_aDefaultColors[NOTLOADED][BG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.DepressedBgColor", Color( 255, 255, 255, 255 ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
void CClassLoadoutPanel::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
KeyValues *pItemKV = inResourceData->FindKey( "itemoptionpanels_kv" );
|
||
|
if ( pItemKV )
|
||
|
{
|
||
|
if ( m_pItemOptionPanelKVs )
|
||
|
{
|
||
|
m_pItemOptionPanelKVs->deleteThis();
|
||
|
}
|
||
|
m_pItemOptionPanelKVs = new KeyValues("itemoptionpanels_kv");
|
||
|
pItemKV->CopySubkeys( m_pItemOptionPanelKVs );
|
||
|
}
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
// PDA Panels
|
||
|
if ( m_pItemModelPanels.Count() > LOADOUT_POSITION_PDA_ADDON2 )
|
||
|
{
|
||
|
for ( int i = LOADOUT_POSITION_PDA_ADDON1; i <= LOADOUT_POSITION_PDA_ADDON2; i++ )
|
||
|
{
|
||
|
int wide = m_pItemModelPanels[i]->GetWide();
|
||
|
int tall = m_pItemModelPanels[i]->GetTall();
|
||
|
|
||
|
m_pItemModelPanels[i]->SetSize( wide / 2, tall / 2 );
|
||
|
m_pItemModelPanels[i]->InvalidateLayout();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::PerformLayout( void )
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
// This is disabled by default in res file. IF we turn it on again, uncomment this.
|
||
|
/*if ( m_pPassiveAttribsLabel )
|
||
|
{
|
||
|
m_pPassiveAttribsLabel->SetVisible( !m_bInTauntLoadoutMode );
|
||
|
}*/
|
||
|
|
||
|
if ( m_pTauntHintLabel )
|
||
|
{
|
||
|
m_pTauntHintLabel->SetVisible( m_bInTauntLoadoutMode );
|
||
|
|
||
|
const char *key = engine->Key_LookupBinding( "taunt" );
|
||
|
if ( !key )
|
||
|
{
|
||
|
key = "< not bound >";
|
||
|
}
|
||
|
SetDialogVariable( "taunt", key );
|
||
|
}
|
||
|
|
||
|
if ( m_pTauntLabel )
|
||
|
{
|
||
|
m_pTauntLabel->SetVisible( m_bInTauntLoadoutMode );
|
||
|
}
|
||
|
if ( m_pTauntCaratLabel )
|
||
|
{
|
||
|
m_pTauntCaratLabel->SetVisible( m_bInTauntLoadoutMode );
|
||
|
}
|
||
|
if ( m_pCharacterLoadoutButton )
|
||
|
{
|
||
|
UpdatePageButtonColor( m_pCharacterLoadoutButton, !m_bInTauntLoadoutMode );
|
||
|
}
|
||
|
if ( m_pTauntLoadoutButton )
|
||
|
{
|
||
|
UpdatePageButtonColor( m_pTauntLoadoutButton, m_bInTauntLoadoutMode );
|
||
|
}
|
||
|
|
||
|
FOR_EACH_VEC( m_vecItemOptionButtons, i )
|
||
|
{
|
||
|
m_vecItemOptionButtons[i]->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
|
||
|
{
|
||
|
// Viewing a class loadout. Layout the buttons & the class image.
|
||
|
if ( i >= NUM_ITEM_PANELS_IN_LOADOUT )
|
||
|
{
|
||
|
m_pItemModelPanels[i]->SetVisible( false );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int iButtonPos = 0;
|
||
|
if ( m_iCurrentClassIndex != TF_CLASS_UNDEFINED )
|
||
|
{
|
||
|
iButtonPos = g_VisibleLoadoutSlotsPerClass[m_iCurrentClassIndex]->m_iPos[i];
|
||
|
}
|
||
|
|
||
|
bool bIsVisible = false;
|
||
|
if ( iButtonPos > 0 )
|
||
|
{
|
||
|
bIsVisible = m_bInTauntLoadoutMode ? IsTauntPanelPosition( iButtonPos ) : !IsTauntPanelPosition( iButtonPos );
|
||
|
}
|
||
|
m_pItemModelPanels[i]->SetVisible( bIsVisible );
|
||
|
|
||
|
if ( bIsVisible )
|
||
|
{
|
||
|
if ( m_bInTauntLoadoutMode )
|
||
|
{
|
||
|
iButtonPos -= g_VisibleLoadoutSlotsPerClass[m_iCurrentClassIndex]->m_iPos[LOADOUT_POSITION_TAUNT];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iButtonPos--;
|
||
|
}
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
// Override for the PDA AddOnSlots
|
||
|
if ( i == LOADOUT_POSITION_PDA_ADDON1 )
|
||
|
{
|
||
|
int iYPos, iXPos;
|
||
|
m_pItemModelPanels[ LOADOUT_POSITION_PDA ]->GetPos( iXPos, iYPos );
|
||
|
int iWide, iTall;
|
||
|
m_pItemModelPanels[ LOADOUT_POSITION_PDA ]->GetSize( iWide, iTall );
|
||
|
|
||
|
m_pItemModelPanels[i]->SetPos( iXPos + iWide + XRES(1), iYPos );
|
||
|
m_pItemModelPanels[i]->SetSize( iWide / 2.1, iTall / 2.1 );
|
||
|
continue;
|
||
|
}
|
||
|
else if ( i == LOADOUT_POSITION_PDA_ADDON2 )
|
||
|
{
|
||
|
int iYPos, iXPos;
|
||
|
m_pItemModelPanels[LOADOUT_POSITION_PDA]->GetPos( iXPos, iYPos );
|
||
|
int iWide, iTall;
|
||
|
m_pItemModelPanels[LOADOUT_POSITION_PDA]->GetSize( iWide, iTall );
|
||
|
|
||
|
m_pItemModelPanels[i]->SetPos( iXPos + iWide + XRES(1), iYPos + iTall - (iTall / 2.1 ) );
|
||
|
m_pItemModelPanels[i]->SetSize( iWide / 2.1, iTall / 2.1 );
|
||
|
continue;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
m_pItemModelPanels[i]->SetNoItemText( ItemSystem()->GetItemSchema()->GetLoadoutStringsForDisplay( EEquipType_t::EQUIP_TYPE_CLASS )[i] );
|
||
|
|
||
|
int iCenter = GetWide() * 0.5;
|
||
|
int iColumnHeight = 4;
|
||
|
int iColumn = iButtonPos / iColumnHeight;
|
||
|
int iYButtonPos = iButtonPos % iColumnHeight;
|
||
|
|
||
|
int iOffset = iColumn == 0 ? m_iItemXPosOffcenterA : m_iItemXPosOffcenterB + ((iColumn - 1) * 200);
|
||
|
int iXPos = iCenter + iOffset;
|
||
|
int iYPos = m_iItemYPos + (m_iItemYDelta * iYButtonPos);
|
||
|
m_pItemModelPanels[i]->SetPos( iXPos, iYPos );
|
||
|
|
||
|
// Update position and visibility of the item option buttons
|
||
|
if ( i < m_vecItemOptionButtons.Count() )
|
||
|
{
|
||
|
// Place the button just inside the item model panel
|
||
|
CExButton* pItemOptionsPanel = m_vecItemOptionButtons[iButtonPos];
|
||
|
int iButtonWide = m_pItemModelPanels[i]->GetWide();
|
||
|
int iMyWide = pItemOptionsPanel->GetWide();
|
||
|
int iOptionsXPos = iColumn == 0
|
||
|
? iXPos + iButtonWide - iMyWide
|
||
|
: iXPos;
|
||
|
pItemOptionsPanel->SetPos( iOptionsXPos, iYPos );
|
||
|
|
||
|
CEconItemView *pItemData = TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, i );
|
||
|
// Enable or disable the item options button for this item model panel
|
||
|
pItemOptionsPanel->SetVisible( !m_bInTauntLoadoutMode && AnyOptionsAvailableForItem( pItemData ) );
|
||
|
pItemOptionsPanel->SetCommand( CFmtStr( "options%d", i ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pItemModelPanels[ i ]->SetSelected( false );
|
||
|
}
|
||
|
|
||
|
if ( m_pLoadoutPresetPanel )
|
||
|
{
|
||
|
m_pLoadoutPresetPanel->SetPos( ( ScreenWidth() - m_pLoadoutPresetPanel->GetWide() ) / 2, m_iItemYPos );
|
||
|
}
|
||
|
|
||
|
LinkModelPanelControllerNavigation( true );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnKeyCodePressed( vgui::KeyCode code )
|
||
|
{
|
||
|
// See if the preset control uses this key
|
||
|
if( m_pLoadoutPresetPanel->HandlePresetKeyPressed( code ) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ButtonCode_t nButtonCode = GetBaseButtonCode( code );
|
||
|
|
||
|
if (nButtonCode == KEY_XBUTTON_LEFT ||
|
||
|
nButtonCode == KEY_XSTICK1_LEFT ||
|
||
|
nButtonCode == KEY_XSTICK2_LEFT ||
|
||
|
nButtonCode == STEAMCONTROLLER_DPAD_LEFT ||
|
||
|
code == KEY_LEFT ||
|
||
|
nButtonCode == KEY_XBUTTON_RIGHT ||
|
||
|
nButtonCode == KEY_XSTICK1_RIGHT ||
|
||
|
nButtonCode == KEY_XSTICK2_RIGHT ||
|
||
|
nButtonCode == STEAMCONTROLLER_DPAD_RIGHT ||
|
||
|
code == KEY_RIGHT ||
|
||
|
nButtonCode == KEY_XBUTTON_UP ||
|
||
|
nButtonCode == KEY_XSTICK1_UP ||
|
||
|
nButtonCode == KEY_XSTICK2_UP ||
|
||
|
nButtonCode == STEAMCONTROLLER_DPAD_UP ||
|
||
|
code == KEY_UP ||
|
||
|
nButtonCode == KEY_XBUTTON_DOWN ||
|
||
|
nButtonCode == KEY_XSTICK1_DOWN ||
|
||
|
nButtonCode == KEY_XSTICK2_DOWN ||
|
||
|
nButtonCode == STEAMCONTROLLER_DPAD_DOWN ||
|
||
|
code == KEY_DOWN )
|
||
|
{
|
||
|
// just eat all navigation keys so we don't
|
||
|
// end up with undesirable navigation behavior bubbling from
|
||
|
// one item model panel to another
|
||
|
}
|
||
|
else if( nButtonCode == KEY_XBUTTON_A || code == KEY_ENTER || nButtonCode == STEAMCONTROLLER_A )
|
||
|
{
|
||
|
// show the current loadout slot
|
||
|
int nSelected = GetFirstSelectedItemIndex( true );
|
||
|
if( nSelected != -1 )
|
||
|
{
|
||
|
OnCommand( VarArgs("change%d", nSelected ) );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BaseClass::OnKeyCodePressed( code );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnNavigateTo( const char* panelName )
|
||
|
{
|
||
|
CItemModelPanel *pChild = dynamic_cast<CItemModelPanel *>( FindChildByName( panelName ) );
|
||
|
if( !pChild )
|
||
|
return;
|
||
|
|
||
|
pChild->SetSelected( true );
|
||
|
SetBorderForItem( pChild, false );
|
||
|
pChild->RequestFocus();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnNavigateFrom( const char* panelName )
|
||
|
{
|
||
|
CItemModelPanel *pChild = dynamic_cast<CItemModelPanel *>( FindChildByName( panelName ) );
|
||
|
if( !pChild )
|
||
|
return;
|
||
|
|
||
|
pChild->SetSelected( false );
|
||
|
SetBorderForItem( pChild, false );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnShowPanel( bool bVisible, bool bReturningFromArmory )
|
||
|
{
|
||
|
if ( bVisible )
|
||
|
{
|
||
|
// always start in character loadout page
|
||
|
SetLoadoutPage( CHARACTER_LOADOUT_PAGE );
|
||
|
|
||
|
if ( m_pSelectionPanel )
|
||
|
{
|
||
|
m_pSelectionPanel->SetVisible( false );
|
||
|
m_pSelectionPanel->MarkForDeletion();
|
||
|
m_pSelectionPanel = NULL;
|
||
|
}
|
||
|
|
||
|
m_iCurrentSlotIndex = TF_WPN_TYPE_PRIMARY;
|
||
|
if( m_pItemModelPanels.Count() && m_pItemModelPanels[0] )
|
||
|
{
|
||
|
m_pItemModelPanels[0]->SetSelected( true );
|
||
|
SetBorderForItem( m_pItemModelPanels[0], false );
|
||
|
}
|
||
|
|
||
|
m_bLoadoutHasChanged = false;
|
||
|
|
||
|
if ( tf_show_preset_explanation_in_class_loadout.GetBool() && m_pPresetsExplanationPopup )
|
||
|
{
|
||
|
m_pPresetsExplanationPopup->Popup();
|
||
|
tf_show_preset_explanation_in_class_loadout.SetValue( 0 );
|
||
|
}
|
||
|
else if ( tf_show_taunt_explanation_in_class_loadout.GetBool() && m_pTauntsExplanationPopup )
|
||
|
{
|
||
|
m_pTauntsExplanationPopup->Popup();
|
||
|
tf_show_taunt_explanation_in_class_loadout.SetValue( 0 );
|
||
|
}
|
||
|
|
||
|
ClearItemOptionsMenu();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->ClearCarriedItems();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::PostShowPanel( bool bVisible )
|
||
|
{
|
||
|
if ( bVisible )
|
||
|
{
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->SetVisible( true );
|
||
|
}
|
||
|
|
||
|
if ( m_pBuildablesButton )
|
||
|
{
|
||
|
m_pBuildablesButton->SetVisible( m_iCurrentClassIndex == TF_CLASS_ENGINEER );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::SetClass( int iClass )
|
||
|
{
|
||
|
m_iCurrentClassIndex = iClass;
|
||
|
|
||
|
if ( m_pLoadoutPresetPanel )
|
||
|
{
|
||
|
m_pLoadoutPresetPanel->SetClass( m_iCurrentClassIndex );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::SetTeam( int iTeam )
|
||
|
{
|
||
|
Assert( IsValidTFTeam( iTeam ) );
|
||
|
m_iCurrentTeamIndex = iTeam;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CClassLoadoutPanel::GetNumRelevantSlots() const
|
||
|
{
|
||
|
return m_pItemModelPanels.Count();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CEconItemView *CClassLoadoutPanel::GetItemInSlot( int iSlot )
|
||
|
{
|
||
|
if( iSlot >= 0 && iSlot < m_pItemModelPanels.Count() )
|
||
|
{
|
||
|
return m_pItemModelPanels[iSlot]->GetItem();
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::FireGameEvent( IGameEvent *event )
|
||
|
{
|
||
|
// If we're not visible, ignore all events
|
||
|
if ( !IsVisible() )
|
||
|
return;
|
||
|
|
||
|
BaseClass::FireGameEvent( event );
|
||
|
|
||
|
// We need to update ourselves after the base has done it, so our item models have been updated
|
||
|
const char *type = event->GetName();
|
||
|
if ( Q_strcmp( "inventory_updated", type ) == 0 )
|
||
|
{
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->HoldItemInSlot( m_iCurrentSlotIndex );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CClassLoadoutPanel::AddNewItemPanel( int iPanelIndex )
|
||
|
{
|
||
|
BaseClass::AddNewItemPanel( iPanelIndex );
|
||
|
|
||
|
m_vecItemOptionButtons[ m_vecItemOptionButtons.AddToTail() ] = new CExButton( this,
|
||
|
CFmtStr( "item_options_button%d", iPanelIndex ),
|
||
|
"+",
|
||
|
this,
|
||
|
CFmtStr( "options%d", iPanelIndex ) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::UpdateModelPanels( void )
|
||
|
{
|
||
|
// Search for a Robot Costume
|
||
|
bool bIsRobot = false;
|
||
|
static CSchemaAttributeDefHandle pAttrDef_PlayerRobot( "appear as mvm robot" );
|
||
|
// For now, fill them out with the local player's currently wielded items
|
||
|
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
|
||
|
{
|
||
|
CEconItemView *pItemData = TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, i );
|
||
|
if ( !pItemData )
|
||
|
continue;
|
||
|
if ( FindAttribute( pItemData, pAttrDef_PlayerRobot ) )
|
||
|
{
|
||
|
bIsRobot = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// We're showing the loadout for a specific class.
|
||
|
TFPlayerClassData_t *pData = GetPlayerClassData( m_iCurrentClassIndex );
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->ClearCarriedItems();
|
||
|
m_pPlayerModelPanel->SetToPlayerClass( m_iCurrentClassIndex, bIsRobot );
|
||
|
m_pPlayerModelPanel->SetTeam( m_iCurrentTeamIndex );
|
||
|
}
|
||
|
|
||
|
// For now, fill them out with the local player's currently wielded items
|
||
|
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
|
||
|
{
|
||
|
CEconItemView *pItemData = TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, i );
|
||
|
m_pItemModelPanels[i]->SetItem( pItemData );
|
||
|
m_pItemModelPanels[i]->SetShowQuantity( true );
|
||
|
m_pItemModelPanels[i]->SetSelected( false );
|
||
|
SetBorderForItem( m_pItemModelPanels[i], false );
|
||
|
|
||
|
if ( m_pPlayerModelPanel && pItemData && pItemData->IsValid() )
|
||
|
{
|
||
|
m_pPlayerModelPanel->AddCarriedItem( pItemData );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->HoldItemInSlot( m_iCurrentSlotIndex );
|
||
|
}
|
||
|
|
||
|
SetDialogVariable( "loadoutclass", g_pVGuiLocalize->Find( pData->m_szLocalizableName ) );
|
||
|
|
||
|
UpdatePassiveAttributes();
|
||
|
|
||
|
// Now layout again to position our item buttons
|
||
|
InvalidateLayout();
|
||
|
|
||
|
if ( m_pItemOptionPanel->IsVisible() )
|
||
|
{
|
||
|
m_pItemOptionPanel->UpdateItemOptionsUI();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnItemPanelMouseReleased( vgui::Panel *panel )
|
||
|
{
|
||
|
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
|
||
|
|
||
|
if ( pItemPanel && IsVisible() )
|
||
|
{
|
||
|
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
|
||
|
{
|
||
|
if ( m_pItemModelPanels[i] == pItemPanel )
|
||
|
{
|
||
|
OnCommand( VarArgs("change%d", i) );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnSelectionReturned( KeyValues *data )
|
||
|
{
|
||
|
if ( data )
|
||
|
{
|
||
|
uint64 ulIndex = data->GetUint64( "itemindex", INVALID_ITEM_ID );
|
||
|
|
||
|
// ulIndex implies do nothing (escape key)
|
||
|
if ( ulIndex != 0 )
|
||
|
{
|
||
|
TFInventoryManager()->EquipItemInLoadout( m_iCurrentClassIndex, m_iCurrentSlotIndex, ulIndex );
|
||
|
|
||
|
m_bLoadoutHasChanged = true;
|
||
|
|
||
|
UpdateModelPanels();
|
||
|
|
||
|
// Send the preset panel a msg so it can save the change
|
||
|
KeyValues *pLoadoutChangedMsg = new KeyValues( "LoadoutChanged" );
|
||
|
pLoadoutChangedMsg->SetInt( "slot", m_iCurrentSlotIndex );
|
||
|
pLoadoutChangedMsg->SetUint64( "itemid", ulIndex );
|
||
|
PostMessage( m_pLoadoutPresetPanel, pLoadoutChangedMsg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PostMessage( GetParent(), new KeyValues("SelectionEnded") );
|
||
|
|
||
|
// It'll have deleted itself, so we don't need to clean it up
|
||
|
m_pSelectionPanel = NULL;
|
||
|
OnCancelSelection();
|
||
|
|
||
|
// find the selected item and give it the focus
|
||
|
CItemModelPanel *pSelection = GetFirstSelectedItemModelPanel( true );
|
||
|
if( !pSelection )
|
||
|
{
|
||
|
m_pItemModelPanels[0]->SetSelected( true );
|
||
|
pSelection = m_pItemModelPanels[0];
|
||
|
}
|
||
|
|
||
|
pSelection->RequestFocus();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnCancelSelection( void )
|
||
|
{
|
||
|
if ( m_pSelectionPanel )
|
||
|
{
|
||
|
m_pSelectionPanel->SetVisible( false );
|
||
|
m_pSelectionPanel->MarkForDeletion();
|
||
|
m_pSelectionPanel = NULL;
|
||
|
}
|
||
|
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::RespawnPlayer()
|
||
|
{
|
||
|
if ( tf_respawn_on_loadoutchanges.GetBool() )
|
||
|
{
|
||
|
// Tell the GC to tell server that we should respawn if we're in a respawn room
|
||
|
GCSDK::CGCMsg< MsgGCEmpty_t > msg( k_EMsgGCRespawnPostLoadoutChange );
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Apply KVs to the item option buttons
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::ApplyKVsToItemPanels( void )
|
||
|
{
|
||
|
BaseClass::ApplyKVsToItemPanels();
|
||
|
|
||
|
if ( m_pItemOptionPanelKVs )
|
||
|
{
|
||
|
for ( int i = 0; i < m_vecItemOptionButtons.Count(); i++ )
|
||
|
{
|
||
|
m_vecItemOptionButtons[i]->ApplySettings( m_pItemOptionPanelKVs );
|
||
|
m_vecItemOptionButtons[i]->InvalidateLayout();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnClosing( void )
|
||
|
{
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->ClearCarriedItems();
|
||
|
}
|
||
|
|
||
|
if ( m_bLoadoutHasChanged )
|
||
|
{
|
||
|
RespawnPlayer();
|
||
|
|
||
|
m_bLoadoutHasChanged = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extern const char *g_szItemBorders[AE_MAX_TYPES][5];
|
||
|
extern ConVar cl_showbackpackrarities;
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver )
|
||
|
{
|
||
|
if ( !pItemPanel )
|
||
|
return;
|
||
|
|
||
|
const char *pszBorder = NULL;
|
||
|
|
||
|
if ( pItemPanel->IsGreyedOut() )
|
||
|
{
|
||
|
pszBorder = "EconItemBorder";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int iRarity = 0;
|
||
|
if ( pItemPanel->HasItem() && cl_showbackpackrarities.GetBool() )
|
||
|
{
|
||
|
iRarity = pItemPanel->GetItem()->GetItemQuality();
|
||
|
|
||
|
uint8 nRarity = pItemPanel->GetItem()->GetItemDefinition()->GetRarity();
|
||
|
if ( ( nRarity != k_unItemRarity_Any ) && ( iRarity != AE_SELFMADE ) )
|
||
|
{
|
||
|
// translate this quality to rarity
|
||
|
iRarity = nRarity + AE_RARITY_DEFAULT;
|
||
|
}
|
||
|
|
||
|
if ( iRarity > 0 )
|
||
|
{
|
||
|
if ( bMouseOver || pItemPanel->IsSelected() )
|
||
|
{
|
||
|
pszBorder = g_szItemBorders[iRarity][1];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pszBorder = g_szItemBorders[iRarity][0];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( iRarity == 0 )
|
||
|
{
|
||
|
if ( bMouseOver || pItemPanel->IsSelected() )
|
||
|
{
|
||
|
pszBorder = "LoadoutItemMouseOverBorder";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pszBorder = "EconItemBorder";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
|
||
|
pItemPanel->SetBorder( pScheme->GetBorder( pszBorder ) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Clear the item options menu and reset the button that summoned it
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::ClearItemOptionsMenu( void )
|
||
|
{
|
||
|
SetOptionsButtonText( m_pItemOptionPanel->GetItemSlot(), "+" );
|
||
|
m_pItemOptionPanel->SetItemSlot( LOADOUT_POSITION_INVALID, m_iCurrentClassIndex );
|
||
|
m_pItemOptionPanel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Safely set the text for a button
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::SetOptionsButtonText( int nIndex, const char* pszText )
|
||
|
{
|
||
|
if ( nIndex >= 0 && nIndex < m_vecItemOptionButtons.Count() )
|
||
|
{
|
||
|
m_vecItemOptionButtons[ m_pItemOptionPanel->GetItemSlot() ]->SetText( pszText );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Return if the passed in item has any options
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CClassLoadoutPanel::AnyOptionsAvailableForItem( const CEconItemView *pItem )
|
||
|
{
|
||
|
if ( !pItem )
|
||
|
return false;
|
||
|
|
||
|
// Styles!
|
||
|
if ( pItem->GetStaticData()->GetNumSelectableStyles() > 1 )
|
||
|
return true;
|
||
|
|
||
|
// Unusual particle effect! For Cosmetics only
|
||
|
static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
|
||
|
if ( pItem->FindAttribute( pAttrDef_AttachParticleEffect ) && pItem->GetItemDefinition()->GetLoadoutSlot( 0 ) >= LOADOUT_POSITION_HEAD )
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::SetLoadoutPage( classloadoutpage_t loadoutPage )
|
||
|
{
|
||
|
ClearItemOptionsMenu();
|
||
|
switch ( loadoutPage )
|
||
|
{
|
||
|
case CHARACTER_LOADOUT_PAGE:
|
||
|
{
|
||
|
m_bInTauntLoadoutMode = false;
|
||
|
}
|
||
|
break;
|
||
|
case TAUNT_LOADOUT_PAGE:
|
||
|
{
|
||
|
m_bInTauntLoadoutMode = true;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
{
|
||
|
// Unhandled loadout page
|
||
|
Assert( 0 );
|
||
|
}
|
||
|
}
|
||
|
InvalidateLayout();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnCommand( const char *command )
|
||
|
{
|
||
|
if ( FStrEq( command, "characterloadout" ) )
|
||
|
{
|
||
|
SetLoadoutPage( CHARACTER_LOADOUT_PAGE );
|
||
|
return;
|
||
|
}
|
||
|
else if ( FStrEq( command, "tauntloadout" ) )
|
||
|
{
|
||
|
SetLoadoutPage( TAUNT_LOADOUT_PAGE );
|
||
|
return;
|
||
|
}
|
||
|
else if ( !V_strnicmp( command, "change", 6 ) )
|
||
|
{
|
||
|
const char *pszNum = command+6;
|
||
|
if ( pszNum && pszNum[0] )
|
||
|
{
|
||
|
int iSlot = atoi(pszNum);
|
||
|
if ( iSlot >= 0 && iSlot < CLASS_LOADOUT_POSITION_COUNT && m_iCurrentClassIndex != TF_CLASS_UNDEFINED )
|
||
|
{
|
||
|
if ( m_iCurrentSlotIndex != iSlot )
|
||
|
{
|
||
|
m_iCurrentSlotIndex = iSlot;
|
||
|
}
|
||
|
|
||
|
// Create the selection screen. It removes itself on close.
|
||
|
m_pSelectionPanel = new CEquipSlotItemSelectionPanel( this, m_iCurrentClassIndex, iSlot );
|
||
|
m_pSelectionPanel->ShowPanel( 0, true );
|
||
|
|
||
|
if ( m_pPlayerModelPanel )
|
||
|
{
|
||
|
m_pPlayerModelPanel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
ClearItemOptionsMenu();
|
||
|
|
||
|
PostMessage( GetParent(), new KeyValues("SelectionStarted") );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
else if ( !V_strnicmp( command, "options", 7 ) )
|
||
|
{
|
||
|
const char *pszNum = command + 7;
|
||
|
if( pszNum && pszNum[0] )
|
||
|
{
|
||
|
int iSlot = atoi( pszNum );
|
||
|
//iSlot = g_VisibleLoadoutSlotsPerClass[m_iCurrentClassIndex]->m_iPos[iSlot - 1];
|
||
|
if ( iSlot >= 0 && iSlot < m_vecItemOptionButtons.Count() && m_iCurrentClassIndex != TF_CLASS_UNDEFINED )
|
||
|
{
|
||
|
// Change the button we're coming from to be a "+"
|
||
|
SetOptionsButtonText( m_pItemOptionPanel->GetItemSlot(), "+" );
|
||
|
|
||
|
// Update the current slot index for callback from the setstyle button.
|
||
|
// It will send us a message to change the item the player model is holding
|
||
|
// and we need this to be updated for that.
|
||
|
m_iCurrentSlotIndex = iSlot;
|
||
|
|
||
|
|
||
|
// Did they just toggle?
|
||
|
if ( m_pItemOptionPanel->GetItemSlot() == iSlot )
|
||
|
{
|
||
|
m_pItemOptionPanel->SetVisible( !m_pItemOptionPanel->IsVisible() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Set the options panel to have the data for this slot
|
||
|
m_pItemOptionPanel->SetItemSlot( (loadout_positions_t)iSlot, m_iCurrentClassIndex );
|
||
|
m_pItemOptionPanel->SetVisible( true );
|
||
|
// Figure out if this is on the left or right
|
||
|
int iColumnHeight = 4;
|
||
|
int iColumn = iSlot / iColumnHeight;
|
||
|
PinCorner_e myCornerToPin = iColumn == 0 ? PIN_TOPLEFT : PIN_TOPRIGHT;
|
||
|
PinCorner_e siblingCornerPinTo = iColumn == 0 ? PIN_TOPRIGHT : PIN_TOPLEFT;
|
||
|
// Pin to the appropriate side
|
||
|
int iButtonPos = g_VisibleLoadoutSlotsPerClass[m_iCurrentClassIndex]->m_iPos[ iSlot ] - 1;
|
||
|
m_pItemOptionPanel->PinToSibling( m_vecItemOptionButtons[ iButtonPos ]->GetName(), myCornerToPin, siblingCornerPinTo );
|
||
|
m_pItemOptionPanel->UpdateItemOptionsUI();
|
||
|
}
|
||
|
|
||
|
// Change the button we're going to to be "-" if we're visible, "+" if we're not
|
||
|
SetOptionsButtonText( m_pItemOptionPanel->GetItemSlot(), m_pItemOptionPanel->IsVisible() ? "-" : "+" );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
BaseClass::OnCommand( command );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::OnMessage( const KeyValues* pParams, vgui::VPANEL hFromPanel )
|
||
|
{
|
||
|
BaseClass::OnMessage( pParams, hFromPanel );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
struct passive_attrib_to_print_t
|
||
|
{
|
||
|
const CEconItemAttributeDefinition *m_pAttrDef;
|
||
|
attrib_value_t m_value;
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CAttributeIterator_AddPassiveAttribsToPassiveList : public CEconItemSpecificAttributeIterator
|
||
|
{
|
||
|
public:
|
||
|
CAttributeIterator_AddPassiveAttribsToPassiveList( CUtlVector<passive_attrib_to_print_t> *pList, bool bForceAdd )
|
||
|
: m_pList( pList )
|
||
|
, m_bForceAdd( bForceAdd )
|
||
|
{
|
||
|
Assert( m_pList );
|
||
|
}
|
||
|
|
||
|
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, attrib_value_t value )
|
||
|
{
|
||
|
Assert( pAttrDef );
|
||
|
|
||
|
if ( pAttrDef->IsHidden() )
|
||
|
return true;
|
||
|
|
||
|
if ( !m_bForceAdd )
|
||
|
{
|
||
|
const char *pDesc = pAttrDef->GetArmoryDescString();
|
||
|
if ( !pDesc || !pDesc[0] )
|
||
|
return true;
|
||
|
|
||
|
// If we have the "on_wearer" key, we're a passive attribute
|
||
|
if ( !Q_stristr(pDesc, "on_wearer") )
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Now see if we're already in the list
|
||
|
FOR_EACH_VEC( (*m_pList), i )
|
||
|
{
|
||
|
passive_attrib_to_print_t& passiveAttr = (*m_pList)[i];
|
||
|
|
||
|
Assert( passiveAttr.m_pAttrDef );
|
||
|
|
||
|
// We match if our class is the same -- this is a case-sensitive compare!
|
||
|
if ( Q_strcmp( passiveAttr.m_pAttrDef->GetAttributeClass(), pAttrDef->GetAttributeClass() ) )
|
||
|
continue;
|
||
|
|
||
|
// We've found a matching attribute. Collate our values and stomp over the earlier value.
|
||
|
passiveAttr.m_value = CollateAttributeValues( passiveAttr.m_pAttrDef, passiveAttr.m_value, pAttrDef, value );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// We didn't find it. Add it to the list.
|
||
|
passive_attrib_to_print_t newPassiveAttr = { pAttrDef, value };
|
||
|
m_pList->AddToTail( newPassiveAttr );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Other types are ignored.
|
||
|
|
||
|
private:
|
||
|
CUtlVector<passive_attrib_to_print_t> *m_pList;
|
||
|
bool m_bForceAdd;
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::UpdatePassiveAttributes( void )
|
||
|
{
|
||
|
if ( !m_pPassiveAttribsLabel )
|
||
|
return;
|
||
|
|
||
|
// We build a list of attributes & associated values by looping through all equipped items.
|
||
|
// This way we can identify & collate attributes based on the same definition index.
|
||
|
CUtlVector<passive_attrib_to_print_t> vecAttribsToPrint;
|
||
|
|
||
|
// Loop through all equipped items
|
||
|
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
|
||
|
{
|
||
|
CEconItemView *pItemData = TFInventoryManager()->GetItemInLoadoutForClass( m_iCurrentClassIndex, i );
|
||
|
if ( pItemData && pItemData->IsValid() )
|
||
|
{
|
||
|
CAttributeIterator_AddPassiveAttribsToPassiveList attrItPassives( &vecAttribsToPrint, false );
|
||
|
pItemData->IterateAttributes( &attrItPassives );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Then add any set bonuses
|
||
|
if ( steamapicontext && steamapicontext->SteamUser() )
|
||
|
{
|
||
|
CSteamID localSteamID = steamapicontext->SteamUser()->GetSteamID();
|
||
|
CUtlVector<const CEconItemSetDefinition *> pActiveSets;
|
||
|
TFInventoryManager()->GetActiveSets( &pActiveSets, localSteamID, m_iCurrentClassIndex );
|
||
|
|
||
|
FOR_EACH_VEC( pActiveSets, set )
|
||
|
{
|
||
|
CAttributeIterator_AddPassiveAttribsToPassiveList attrItSetPassives( &vecAttribsToPrint, true );
|
||
|
pActiveSets[set]->IterateAttributes( &attrItSetPassives );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now build the text
|
||
|
wchar_t wszPassiveDesc[4096];
|
||
|
wszPassiveDesc[0] = '\0';
|
||
|
m_pPassiveAttribsLabel->GetTextImage()->ClearColorChangeStream();
|
||
|
|
||
|
wchar_t *pHeader = g_pVGuiLocalize->Find( "#TF_PassiveAttribs" );
|
||
|
if ( pHeader )
|
||
|
{
|
||
|
V_wcscpy_safe( wszPassiveDesc, pHeader );
|
||
|
V_wcscat_safe( wszPassiveDesc, L"\n" );
|
||
|
}
|
||
|
|
||
|
if ( vecAttribsToPrint.Count() )
|
||
|
{
|
||
|
FOR_EACH_VEC( vecAttribsToPrint, i )
|
||
|
{
|
||
|
CEconAttributeDescription AttrDesc( GLocalizationProvider(), vecAttribsToPrint[i].m_pAttrDef, vecAttribsToPrint[i].m_value );
|
||
|
AddAttribPassiveText( AttrDesc, wszPassiveDesc, ARRAYSIZE(wszPassiveDesc) );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
|
||
|
Color col = pScheme->GetColor( GetColorNameForAttribColor( ATTRIB_COL_NEUTRAL ), Color(255,255,255,255) );
|
||
|
m_pPassiveAttribsLabel->GetTextImage()->AddColorChange( col, Q_wcslen( wszPassiveDesc ) );
|
||
|
|
||
|
wchar_t *pNone = g_pVGuiLocalize->Find( "#TF_PassiveAttribs_None" );
|
||
|
if ( pNone )
|
||
|
{
|
||
|
V_wcscat_safe( wszPassiveDesc, pNone );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pPassiveAttribsLabel->SetText( wszPassiveDesc );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::AddAttribPassiveText( const CEconAttributeDescription& AttrDesc, INOUT_Z_CAP(iNumPassiveChars) wchar_t *out_wszPassiveDesc, int iNumPassiveChars )
|
||
|
{
|
||
|
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
|
||
|
Assert( pScheme );
|
||
|
|
||
|
if ( !AttrDesc.GetDescription().IsEmpty() )
|
||
|
{
|
||
|
// Insert the color change at the current position
|
||
|
Color col = pScheme->GetColor( GetColorNameForAttribColor( AttrDesc.GetDefaultColor() ), Color(255,255,255,255) );
|
||
|
m_pPassiveAttribsLabel->GetTextImage()->AddColorChange( col, Q_wcslen( out_wszPassiveDesc ) );
|
||
|
|
||
|
// Now append the text of the attribute
|
||
|
V_wcsncat( out_wszPassiveDesc, AttrDesc.GetDescription().Get(), iNumPassiveChars );
|
||
|
V_wcsncat( out_wszPassiveDesc, L"\n", iNumPassiveChars );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CClassLoadoutPanel::UpdatePageButtonColor( CExImageButton *pPageButton, bool bIsActive )
|
||
|
{
|
||
|
if ( pPageButton )
|
||
|
{
|
||
|
int iLoaded = bIsActive ? LOADED : NOTLOADED;
|
||
|
pPageButton->SetDefaultColor( m_aDefaultColors[iLoaded][FG][DEFAULT], m_aDefaultColors[iLoaded][BG][DEFAULT] );
|
||
|
pPageButton->SetArmedColor( m_aDefaultColors[iLoaded][FG][ARMED], m_aDefaultColors[iLoaded][BG][ARMED] );
|
||
|
pPageButton->SetDepressedColor( m_aDefaultColors[iLoaded][FG][DEPRESSED], m_aDefaultColors[iLoaded][BG][DEPRESSED] );
|
||
|
}
|
||
|
}
|