//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //============================================================================= #include "cbase.h" #include "c_tf_upgrades.h" #include "tf_upgrades_shared.h" #include "dt_utlvector_recv.h" #include #include #include "iclientmode.h" #include "item_model_panel.h" #include "econ_item_system.h" #include "tf_weaponbase_gun.h" #include "c_tf_buff_banner.h" #include "tf_item_powerup_bottle.h" #include "vgui_controls/TextImage.h" #include "vgui_controls/Image.h" #include "tf_hud_playerstatus.h" #include "tf_gamerules.h" #include "econ_item_description.h" #include "charinfo_loadout_subpanel.h" #include "c_tf_objective_resource.h" #include "vgui/IInput.h" #include "tf_tips.h" #include "econ_ui.h" #include "econ_item_preset.h" #include "gc_clientsystem.h" #include "achievementmgr.h" #include "tf_hud_statpanel.h" #include "tf_mann_vs_machine_stats.h" #include "c_tf_playerresource.h" #define UPGRADE_PANEL_LEVEL_LABEL_COUNT 10 extern CAchievementMgr g_AchievementMgrTF; ConVar tf_mvm_tabs_discovered( "tf_mvm_tabs_discovered", "0", FCVAR_ARCHIVE, "Remember how many times players have clicked tabs." ); Color CUpgradeBuyPanel::m_rgbaDefaultFG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaDefaultBG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaArmedFG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaArmedBG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaDepressedFG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaDepressedBG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaSelectedFG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaSelectedBG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaDisabledFG( 0, 0, 0, 255 ); Color CUpgradeBuyPanel::m_rgbaDisabledBG( 0, 0, 0, 255 ); CUpgradeBuyPanel::CUpgradeBuyPanel( Panel *parent, const char *panelName ) : BaseClass( parent, panelName ) { m_pIcon = new vgui::ImagePanel( this, "Icon" ); m_pPriceLabel = new vgui::Label( this, "PriceLabel", "" ); m_pShortDescriptionLabel = new vgui::Label( this, "ShortDescriptionLabel", "" ); m_pIncrementButton = new CImageButton( this, "IncrementButton" ); m_pDecrementButton = new CImageButton( this, "DecrementButton" ); m_pSkillTreeButtonKVs = NULL; m_nPurchases = 0; m_nGridPositionX = 0; m_nGridPositionY = 0; m_bInspectMode = false; } CUpgradeBuyPanel::~CUpgradeBuyPanel() { if ( m_pSkillTreeButtonKVs ) { m_pSkillTreeButtonKVs->deleteThis(); m_pSkillTreeButtonKVs = NULL; } } void CUpgradeBuyPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { // load control settings... LoadControlSettings( "resource/UI/UpgradeBuyPanel.res" ); BaseClass::ApplySchemeSettings( pScheme ); //m_pPriceLabel->SetMouseInputEnabled( false ); m_rgbaDefaultFG = pScheme->GetColor( "UpgradeDefaultFg", m_rgbaDefaultFG ); m_rgbaDefaultBG = pScheme->GetColor( "UpgradeDefaultBg", m_rgbaDefaultBG ); m_rgbaArmedFG = pScheme->GetColor( "UpgradeArmedFg", m_rgbaArmedFG ); m_rgbaArmedBG = pScheme->GetColor( "UpgradeArmedBg", m_rgbaArmedBG ); m_rgbaDepressedFG = pScheme->GetColor( "UpgradeDepressedFg", m_rgbaDepressedFG ); m_rgbaDepressedBG = pScheme->GetColor( "UpgradeDepressedBg", m_rgbaDepressedBG ); m_rgbaSelectedFG = pScheme->GetColor( "UpgradeSelectedFg", m_rgbaSelectedFG ); m_rgbaSelectedBG = pScheme->GetColor( "UpgradeSelectedBg", m_rgbaSelectedBG ); m_rgbaDisabledFG = pScheme->GetColor( "UpgradeDisabledFg", m_rgbaDisabledFG ); m_rgbaDisabledBG = pScheme->GetColor( "UpgradeDisabledBg", m_rgbaDisabledBG ); } void CUpgradeBuyPanel::ApplySettings( KeyValues *inResourceData ) { BaseClass::ApplySettings( inResourceData ); KeyValues *pItemKV = inResourceData->FindKey( "skilltreebuttons_kv" ); if ( pItemKV ) { if ( m_pSkillTreeButtonKVs ) { m_pSkillTreeButtonKVs->deleteThis(); } m_pSkillTreeButtonKVs = new KeyValues( "skilltreebuttons_kv" ); pItemKV->CopySubkeys( m_pSkillTreeButtonKVs ); } } void CUpgradeBuyPanel::PerformLayout( void ) { BaseClass::PerformLayout(); } void CUpgradeBuyPanel::OnCommand( const char *command ) { if ( StringHasPrefix( command, "mvm_upgrade" ) ) { GetParent()->GetParent()->OnCommand( command ); return; } else if ( StringHasPrefix( command, "mvm_downgrade" ) ) { GetParent()->GetParent()->OnCommand( command ); return; } BaseClass::OnCommand( command ); } bool CUpgradeBuyPanel::ValidateUpgradeStepData( void ) { m_bOverCap = false; if ( !m_hPlayer ) return false; int nNumSteps = GetUpgradeStepData( m_hPlayer, m_nWeaponSlot, m_nUpgradeIndex, m_nCurrentStep, m_bOverCap ); if ( nNumSteps ) { SetNumLevelImages( nNumSteps ); m_pIcon->SetImage( g_MannVsMachineUpgrades.m_Upgrades[ m_nUpgradeIndex ].szIcon ); return true; } return false; } void CUpgradeBuyPanel::SetNumLevelImages( int nValues ) { if ( nValues >= m_SkillTreeImages.Count() ) { // Add needed images for ( int i = m_SkillTreeImages.Count(); i < nValues; ++i ) { vgui::ImagePanel *pImage = new vgui::ImagePanel( this, "SkillTreeImage" ); m_SkillTreeImages.AddToTail( pImage ); pImage->ApplySettings( m_pSkillTreeButtonKVs ); pImage->SetPos( m_iUpgradeButtonXPos + pImage->GetWide() * i, m_iUpgradeButtonYPos ); } } else if ( nValues < m_SkillTreeImages.Count() ) { // Clear out extra images for ( int i = m_SkillTreeImages.Count() - 1; i >= nValues; --i ) { m_SkillTreeImages[ i ]->MarkForDeletion(); m_SkillTreeImages.Remove( i ); } } } void CUpgradeBuyPanel::SetSkillTreeButtonColors( int nImage, ColorSet nColorSet ) { Assert( nImage >= 0 && nImage < m_SkillTreeImages.Count() ); vgui::ImagePanel *pImage = m_SkillTreeImages[ nImage ]; if ( pImage ) { switch ( nColorSet ) { case COLOR_SET_DEFAULT: case COLOR_SET_DISABLED: pImage->SetImage( "pve/upgrade_unowned" ); break; case COLOR_SET_OWNED: pImage->SetImage( "pve/upgrade_owned" ); break; case COLOR_SET_PURCHASED: pImage->SetImage( "pve/upgrade_purchased" ); break; } } } void CUpgradeBuyPanel::UpdateImages( int nCurrentMoney ) { // If we're not at max, update our prices and see if our affordability has changed costlabel_chache_t nAffordability = CLCACHE_AFFORDABLE; int nImageTotal = m_SkillTreeImages.Count(); int nCurrentStep = m_nCurrentStep + m_nPurchases; int nNumRemaining = ( nImageTotal - nCurrentStep ); int nAffordablePurchases = m_nPrice <= 0 ? INT_MAX : nCurrentMoney / m_nPrice; int nUnaffordablePurchases = nNumRemaining - nAffordablePurchases; if ( nUnaffordablePurchases > 0 ) { nAffordability = static_cast< costlabel_chache_t >( CLCACHE_NOT_AFFORDABLE_1 + ( nUnaffordablePurchases - 1 ) ); } CMannVsMachineUpgrades *pMannVsMachineUpgrade = &( g_MannVsMachineUpgrades.m_Upgrades[ m_nUpgradeIndex ] ); bool bSellAllowed = ( TFObjectiveResource()->GetMannVsMachineWaveCount() <= 1 || m_nPurchases > 0 ); // we'll decided if it's enabled below m_pIncrementButton->SetEnabled( false ); m_pIncrementButton->SetInactiveImage( "pve/buy_disabled" ); m_pIncrementButton->SetActiveImage( "pve/buy_disabled" ); m_pIcon->SetImage( VarArgs( "%s_bw", pMannVsMachineUpgrade->szIcon ) ); if ( m_bInspectMode ) { m_pDecrementButton->SetEnabled( false ); m_pDecrementButton->SetVisible( false ); m_pIncrementButton->SetEnabled( true ); m_pIncrementButton->SetVisible( true ); } else if ( bSellAllowed ) { m_pDecrementButton->SetVisible( true ); if ( nCurrentStep > 0 ) { m_pDecrementButton->SetEnabled( true ); m_pDecrementButton->SetInactiveImage( "pve/sell_enabled" ); m_pDecrementButton->SetActiveImage( "pve/sell_selected" ); } else { m_pDecrementButton->SetVisible( true ); m_pDecrementButton->SetEnabled( false ); m_pDecrementButton->SetInactiveImage( "pve/sell_disabled" ); m_pDecrementButton->SetActiveImage( "pve/sell_disabled" ); } } else { m_pDecrementButton->SetVisible( false ); } for ( int nUpgradeButton = 0; nUpgradeButton < nImageTotal; ++nUpgradeButton ) { if ( nUpgradeButton < MIN( m_nCurrentStep, nCurrentStep ) ) { // This was an existing upgrade, so show a big dot SetSkillTreeButtonColors( nUpgradeButton, CUpgradeBuyPanel::COLOR_SET_OWNED ); } else if ( nUpgradeButton < nCurrentStep ) { // This purchase is in flight so show a smaller dot SetSkillTreeButtonColors( nUpgradeButton, CUpgradeBuyPanel::COLOR_SET_PURCHASED ); } else { if ( nAffordability == CLCACHE_AFFORDABLE || nUpgradeButton >= nCurrentStep + nAffordability ) { SetSkillTreeButtonColors( nUpgradeButton, CUpgradeBuyPanel::COLOR_SET_DEFAULT ); m_pIncrementButton->SetEnabled( true ); m_pIncrementButton->SetInactiveImage( "pve/buy_enabled" ); m_pIncrementButton->SetActiveImage( "pve/buy_selected" ); m_pIcon->SetImage( pMannVsMachineUpgrade->szIcon ); } else { SetSkillTreeButtonColors( nUpgradeButton, CUpgradeBuyPanel::COLOR_SET_DISABLED ); } } } V_strcpy_safe( m_szAttribName, pMannVsMachineUpgrade->szAttrib ); } //==================================================================================================================== // CHudUpgradePanel - HUD Element that provides the interface to the upgrade options //==================================================================================================================== DECLARE_HUDELEMENT( CHudUpgradePanel ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CHudUpgradePanel::CHudUpgradePanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudUpgradePanel" ) { Panel *pParent = g_pClientMode->GetViewport(); SetParent( pParent ); SetHiddenBits( HIDEHUD_MISCSTATUS ); RegisterForRenderGroup( "mid" ); RegisterForRenderGroup( "commentary" ); m_pItemModelPanelKVs = NULL; m_bShowUpgradeMenu = false; m_bCancelUpgrades = false; m_bOpenLoadout = false; SetMouseInputEnabled( true ); MakePopup(); m_pSelectWeaponPanel = new vgui::EditablePanel( this, "SelectWeaponPanel" ); m_pTipPanel = new vgui::EditablePanel( this, "TipPanel" ); m_pUpgradeItemStatsLabel = NULL; m_pPlayerUpgradeButton = NULL; m_pActiveTabPanel = NULL; m_pMouseOverTabPanel = NULL; m_pMouseOverUpgradePanel = NULL; m_pActiveUpgradeBuyPanel = NULL; m_pPlayerRespecButton = NULL; m_nCurrency = 0; m_nUpgradeActivity = 0; m_bHighlightedTab = ( tf_mvm_tabs_discovered.GetInt() > 3 ); m_bNavUpDownPressed = true; m_bNavLeftRightPressed = true; m_bNavButtonPressed = true; m_bUsingController = false; m_bInspectMode = false; m_hPlayer = NULL; ListenForGameEvent( "player_currency_changed" ); ListenForGameEvent( "game_newmap" ); ListenForGameEvent( "upgrades_file_changed" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CHudUpgradePanel::~CHudUpgradePanel() { if ( IsActive() ) { engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" ); } if ( m_pItemModelPanelKVs ) { m_pItemModelPanelKVs->deleteThis(); m_pItemModelPanelKVs = NULL; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { // load control settings... LoadControlSettings( "resource/UI/HudUpgradePanel.res" ); BaseClass::ApplySchemeSettings( pScheme ); UpdateModelPanels(); CExButton *pButton = dynamic_cast< CExButton* >( m_pSelectWeaponPanel->FindChildByName("CancelButton") ); if ( pButton ) { pButton->AddActionSignalTarget( this ); } pButton = dynamic_cast< CExButton* >( m_pSelectWeaponPanel->FindChildByName("CloseButton") ); if ( pButton ) { pButton->AddActionSignalTarget( this ); } pButton = dynamic_cast< CExButton* >( m_pSelectWeaponPanel->FindChildByName("PlayerUpgradeButton") ); if ( pButton ) { pButton->AddActionSignalTarget( this ); } pButton = dynamic_cast< CExButton* >( m_pSelectWeaponPanel->FindChildByName("QuickEquipButton") ); if ( pButton ) { pButton->AddActionSignalTarget( this ); } pButton = dynamic_cast< CExButton* >( m_pSelectWeaponPanel->FindChildByName("LoadoutButton") ); if ( pButton ) { pButton->AddActionSignalTarget( this ); } pButton = dynamic_cast< CExButton* >( m_pTipPanel->FindChildByName("NextTipButton") ); if ( pButton ) { pButton->AddActionSignalTarget( this ); } UpdateTip(); m_pUpgradeItemStatsLabel = dynamic_cast< CExLabel* >( m_pSelectWeaponPanel->FindChildByName("UpgradeItemStatsLabel") ); m_pPlayerUpgradeButton = m_pSelectWeaponPanel->FindChildByName( "PlayerUpgradeButton" ); m_pActiveTabPanel = m_pSelectWeaponPanel->FindChildByName( "ActiveTabPanel" ); m_pMouseOverTabPanel = m_pSelectWeaponPanel->FindChildByName( "MouseOverTabPanel" ); m_pMouseOverUpgradePanel = m_pSelectWeaponPanel->FindChildByName( "MouseOverUpgradePanel" ); m_pPlayerRespecButton = m_pSelectWeaponPanel->FindChildByName( "RespecButton" ); if ( m_pPlayerRespecButton ) { m_pPlayerRespecButton->AddActionSignalTarget( this ); } m_pActiveUpgradeBuyPanel = NULL; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::ApplySettings( KeyValues *inResourceData ) { BaseClass::ApplySettings( inResourceData ); KeyValues *pItemKV = inResourceData->FindKey( "modelpanels_kv" ); if ( pItemKV ) { if ( m_pItemModelPanelKVs ) { m_pItemModelPanelKVs->deleteThis(); } m_pItemModelPanelKVs = new KeyValues("modelpanels_kv"); pItemKV->CopySubkeys( m_pItemModelPanelKVs ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CHudUpgradePanel::ShouldDraw( void ) { if ( !m_bInspectMode ) { m_hPlayer = C_TFPlayer::GetLocalTFPlayer(); } // Local mode C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( m_hPlayer && pLocalPlayer == m_hPlayer ) { if ( !m_hPlayer->IsAlive() || m_hPlayer->m_Shared.IsLoser() || m_hPlayer->GetTeamNumber() == TEAM_SPECTATOR ) { m_bWasInZone = false; return false; } bool bInZone = m_hPlayer->m_Shared.IsInUpgradeZone(); // check for other popups if ( bInZone && !CHudElement::ShouldDraw() ) { CTFStatPanel *pStatPanel = GetStatPanel(); if ( pStatPanel->IsVisible() ) { pStatPanel->Hide(); return false; } } if ( m_bWasInZone != bInZone ) { if ( bInZone ) { m_bShowUpgradeMenu = true; m_bCancelUpgrades = false; m_bOpenLoadout = false; } m_bWasInZone = bInZone; } } return m_bShowUpgradeMenu; } void CHudUpgradePanel::SetVisible( bool bVisible ) { if ( !bVisible && IsActive() ) { engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" ); } BaseClass::SetVisible( bVisible ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::SetActive( bool bActive ) { if ( bActive && !IsActive() ) { // Reset our upgrade activity m_nUpgradeActivity = 0; m_pActiveUpgradeBuyPanel = NULL; m_bNavUpDownPressed = true; m_bNavLeftRightPressed = true; m_bNavButtonPressed = true; m_bUsingController = false; KeyValues *kv = new KeyValues( "MvM_UpgradesBegin" ); engine->ServerCmdKeyValues( kv ); // Get our currency if ( m_hPlayer && !m_bInspectMode ) { m_nCurrency = m_hPlayer->GetCurrency(); } else { m_nCurrency = 0; } UpdateTip(); UpgradeItemInSlot( LOADOUT_POSITION_PRIMARY ); m_pTipPanel->SetVisible( true ); if ( tf_mvm_tabs_discovered.GetInt() >= 3 ) { m_bHighlightedTab = true; } // Becoming visible. Get ready. UpdateModelPanels(); // Accept button is disabled till you buy or sell something m_pSelectWeaponPanel->SetControlEnabled( "CloseButton", false ); SetKeyBoardInputEnabled( false ); engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" ); // Move the mouse cursor to the middle of our panel int x,y,w,h; vgui::ipanel()->GetAbsPos( GetVPanel(), x, y ); GetSize( w, h ); //vgui::IInput *input() vgui::input()->SetCursorPos( x + (w * 0.5), y + (h * 0.5) ); vgui::ivgui()->AddTickSignal( GetVPanel(), 100 ); // Tick once right away to get the currency updated OnTick(); m_bAwardMaxSlotAchievement = false; } else if ( !bActive && IsActive() ) { if ( m_bCancelUpgrades ) { CancelUpgrades(); } vgui::ivgui()->RemoveTickSignal( GetVPanel() ); engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" ); if ( m_bOpenLoadout ) { engine->ClientCmd_Unrestricted( "open_charinfo_direct" ); } // let the server know that we've close the menu with the number of upgrades // so the response rules can do their thing KeyValues *kv = new KeyValues( "MvM_UpgradesDone" ); kv->SetInt( "num_upgrades", m_nUpgradeActivity ); engine->ServerCmdKeyValues( kv ); } CHudElement::SetActive( bActive ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::OnTick( void ) { BaseClass::OnTick(); if ( IsVisible() ) { UpdateJoystickControls(); UpdateHighlights(); UpdateItemStatsLabel(); if ( m_hPlayer ) { if ( !m_hPlayer->m_Shared.IsInUpgradeZone() && !m_bInspectMode ) { OnCommand( "cancel" ); } if ( m_pPlayerRespecButton && g_TF_PR && m_hPlayer ) { bool bAllowed = TFGameRules() && TFGameRules()->IsMannVsMachineRespecEnabled(); bool bEnabled = bAllowed && TFGameRules()->CanPlayerUseRespec( m_hPlayer ) && !m_bInspectMode; if ( m_pPlayerRespecButton->IsVisible() != bAllowed ) { m_pPlayerRespecButton->SetVisible( bAllowed ); } if ( m_pPlayerRespecButton->IsEnabled() != bEnabled ) { m_pPlayerRespecButton->SetEnabled( bEnabled ); } } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::FireGameEvent( IGameEvent *event ) { if ( FStrEq( event->GetName(), "player_currency_changed" ) ) { if ( IsActive() && !m_bInspectMode ) { int nCurrency = event->GetInt( "currency" ); if ( m_nCurrency != nCurrency ) { m_nCurrency = nCurrency; UpdateButtonStates( m_nCurrency ); } } } else if ( FStrEq( event->GetName(), "game_newmap" ) ) { // Doing this prevents stale data after changing to a map that uses different upgrades data. UpdateModelPanels(); } else if ( FStrEq( event->GetName(), "upgrades_file_changed" ) ) { const char *pszPath = event->GetString( "path" ); if ( pszPath[0] == '\0' ) { g_MannVsMachineUpgrades.LoadUpgradesFile(); UpdateModelPanels(); } else { g_MannVsMachineUpgrades.LoadUpgradesFileFromPath( pszPath ); UpdateModelPanels(); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::PlayerInventoryChanged( C_TFPlayer *pPlayer ) { if ( !m_hPlayer || !pPlayer || pPlayer != m_hPlayer ) return; // Go through every item and compare it to the item stored with the matching (slot) panel for ( int nSlot = 0; nSlot < CLASS_LOADOUT_POSITION_COUNT; nSlot++ ) { if ( nSlot == LOADOUT_POSITION_HEAD || nSlot == LOADOUT_POSITION_MISC ) continue; CEconItemView *pCurrentItem = CTFPlayerSharedUtils::GetEconItemViewByLoadoutSlot( m_hPlayer, nSlot ); if ( !pCurrentItem ) continue; for ( int nPanelIndex = 0; nPanelIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nPanelIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[nPanelIndex] ); if ( !pItemSlotBuyPanel ) continue; if ( !pItemSlotBuyPanel->upgradeBuyPanels.Count() ) continue; // Do we have a matching panel for this slot? if ( pItemSlotBuyPanel->nSlot != nSlot ) continue; // If the item has changed since the panel was created, cancel out of the upgrade screen if ( pItemSlotBuyPanel->GetItemID() != pCurrentItem->GetItemID() ) { OnCommand( "cancel" ); return; } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::UpdateModelPanels( void ) { m_iVisibleItemPanels = 0; FOR_EACH_VEC( m_pItemPanels, i ) { m_pItemPanels[i]->SetVisible( false ); } // slot -1 is used for player self upgrades, -2 is INVALID m_ItemSlotBuyPanels[ 0 ].nSlot = ItemSlotBuyPanels::CHARACTER_UPGRADE; for ( int iTab = 1; iTab < MAX_ITEM_SLOT_BUY_PANELS; ++iTab ) { m_ItemSlotBuyPanels[ iTab ].nSlot = ItemSlotBuyPanels::INVALID_SLOT; } if ( m_hPlayer ) { CreateItemModelPanel( LOADOUT_POSITION_PRIMARY ); CreateItemModelPanel( LOADOUT_POSITION_SECONDARY ); CreateItemModelPanel( LOADOUT_POSITION_MELEE ); if ( m_hPlayer->IsPlayerClass( TF_CLASS_SPY ) ) { CreateItemModelPanel( LOADOUT_POSITION_BUILDING ); } else if ( m_hPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) ) { CreateItemModelPanel( LOADOUT_POSITION_PDA ); } Panel *pSentryIcon = m_pSelectWeaponPanel->FindChildByName( "SentryIcon" ); if ( pSentryIcon ) { pSentryIcon->SetMouseInputEnabled( false ); pSentryIcon->SetVisible( m_hPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) ); } CreateItemModelPanel( LOADOUT_POSITION_ACTION ); } UpdateUpgradeButtons(); UpdateItemStatsLabel(); InvalidateLayout(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::PerformLayout( void ) { BaseClass::PerformLayout(); // Position the item panels int iVisiblePanel = 0; FOR_EACH_VEC( m_pItemPanels, i ) { CItemModelPanel *pItemPanel = m_pItemPanels[ i ]; if ( !pItemPanel ) continue; if ( !pItemPanel->IsVisible() ) continue; int iPanelWide = pItemPanel->GetWide(); int iLeft = m_iItemPanelXPos + iPanelWide + m_iItemPanelXDelta; int iXPos = iLeft + ( iPanelWide + m_iItemPanelXDelta ) * iVisiblePanel; int iYPos = m_iItemPanelYPos; pItemPanel->SetPos( iXPos, iYPos ); vgui::Panel *pInactiveTabPanel = m_pSelectWeaponPanel->FindChildByName( VarArgs( "InactiveTabPanel%i", iVisiblePanel + 2 ) ); if ( pInactiveTabPanel ) { pInactiveTabPanel->SetPos( iXPos, iYPos ); pInactiveTabPanel->SetVisible( true ); } iVisiblePanel++; } for ( int i = iVisiblePanel; i < 5; ++i ) { vgui::Panel *pInactiveTabPanel = m_pSelectWeaponPanel->FindChildByName( VarArgs( "InactiveTabPanel%i", i + 2 ) ); if ( pInactiveTabPanel ) { pInactiveTabPanel->SetVisible( false ); } } CTFClassImage *pClassImage = static_cast< CTFClassImage* >( m_pSelectWeaponPanel->FindChildByName( "ClassImage" ) ); if ( pClassImage ) { pClassImage->SetMouseInputEnabled( false ); if ( m_hPlayer ) { pClassImage->SetClass( m_hPlayer->GetTeamNumber(), m_hPlayer->GetPlayerClass()->GetClassIndex(), false ); } } for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); if ( pItemSlotBuyPanel->upgradeBuyPanels.Count() > 0 ) { int iButton = 0; FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { CUpgradeBuyPanel *pUpgradeBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ i ]; pUpgradeBuyPanel->m_nGridPositionX = iButton % 2; pUpgradeBuyPanel->m_nGridPositionY = iButton / 2; int iXPos = m_iUpgradeBuyPanelXPos + ( pUpgradeBuyPanel->GetWide() + m_iUpgradeBuyPanelDelta ) * pUpgradeBuyPanel->m_nGridPositionX; int iYPos = m_iUpgradeBuyPanelYPos + ( pUpgradeBuyPanel->GetTall() + m_iUpgradeBuyPanelDelta ) * pUpgradeBuyPanel->m_nGridPositionY; pUpgradeBuyPanel->SetPos( iXPos, iYPos ); iButton++; } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::OnItemPanelEntered( vgui::Panel *panel ) { CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); if ( pItemPanel && IsVisible() ) { SetBorderForItem( pItemPanel, true ); // Get the name of the item that was selected CEconItemView *pCurItemData = pItemPanel->GetItem(); if ( pCurItemData ) { const wchar_t *wszItemName = pCurItemData->GetItemName(); // Set the text displaying which item the upgrades are for ("Shovel", etc.) m_pSelectWeaponPanel->SetDialogVariable( "upgrade_description", wszItemName ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::OnItemPanelExited( vgui::Panel *panel ) { CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); if ( pItemPanel && IsVisible() ) { SetBorderForItem( pItemPanel, false ); // Set the text displaying which item the upgrades are for ("Shovel", etc.) m_pSelectWeaponPanel->SetDialogVariable( "upgrade_description", L"" ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::CreateItemModelPanel( int iLoadoutSlot ) { if ( !m_hPlayer ) return; int iClass = m_hPlayer->GetPlayerClass()->GetClassIndex(); if ( iClass < TF_FIRST_NORMAL_CLASS || iClass >= TF_LAST_NORMAL_CLASS ) return; CItemModelPanel *pItemPanel = NULL; if ( m_iVisibleItemPanels < m_pItemPanels.Count() ) { pItemPanel = m_pItemPanels[ m_iVisibleItemPanels ]; } char szCommand[ 32 ]; V_snprintf( szCommand, sizeof( szCommand ), "UpgradeButton%d", iLoadoutSlot ); if ( !pItemPanel ) { // Create our item panel pItemPanel = new CItemModelPanel( m_pSelectWeaponPanel, szCommand ); m_pItemPanels.AddToTail( pItemPanel ); if ( m_pItemModelPanelKVs ) { pItemPanel->ApplySettings( m_pItemModelPanelKVs ); } pItemPanel->MakeReadyForUse(); pItemPanel->SetActAsButton( true, true ); pItemPanel->SendPanelEnterExits( true ); pItemPanel->AddActionSignalTarget( this ); } // Get the item entity. We use the entity, not the item in the loadout, because we want // the dynamic attributes that have already been purchases and attached. CEconItemView *pCurItemData = CTFPlayerSharedUtils::GetEconItemViewByLoadoutSlot( m_hPlayer, iLoadoutSlot ); pItemPanel->SetItem( pCurItemData ); pItemPanel->SetGreyedOut( NULL ); bool bVisible = pCurItemData && pCurItemData->IsValid(); if ( iLoadoutSlot == LOADOUT_POSITION_ACTION && ( !bVisible || !dynamic_cast< CTFPowerupBottle* >( m_hPlayer->GetEquippedWearableForLoadoutSlot( LOADOUT_POSITION_ACTION ) ) ) ) { static CSchemaItemDefHandle pItemDef_PowerupCanteen( CTFItemSchema::k_rchMvMPowerupBottleItemDefName ); if ( pItemDef_PowerupCanteen ) { // Nothing in action slot or non-bottle in action slot // Show a disabled powerup bottle instead CEconItemView *pItemData = new CEconItemView(); pItemData->Init( pItemDef_PowerupCanteen->GetDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); pItemData->SetClientItemFlags( kEconItemFlagClient_Preview | kEconItemFlagClient_StoreItem ); pItemPanel->SetItem( pItemData ); pItemPanel->SetGreyedOut( "#TF_PVE_Need_Powerup_Equipped" ); bVisible = pItemData && pItemData->IsValid(); } } pItemPanel->SetVisible( bVisible ); if ( bVisible ) { m_ItemSlotBuyPanels[ m_iVisibleItemPanels + 1 ].nSlot = iLoadoutSlot; pItemPanel->SetName( szCommand ); pItemPanel->SetModelIsHidden( iLoadoutSlot == LOADOUT_POSITION_PDA ); SetBorderForItem( pItemPanel, false ); m_iVisibleItemPanels++; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::OnItemPanelMousePressed( vgui::Panel *panel ) { CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); if ( !m_hPlayer ) return; if ( pItemPanel && pItemPanel->GetItem() && IsVisible() && m_pActiveTabPanel ) { int iLoadoutSlot = pItemPanel->GetItem()->GetStaticData()->GetLoadoutSlot( m_hPlayer->GetPlayerClass()->GetClassIndex() ); if ( m_iWeaponSlotBeingUpgraded == iLoadoutSlot ) return; UpgradeItemInSlot( iLoadoutSlot ); if ( !m_bHighlightedTab ) { // They've clicked a tab... no need to blink them any longer m_bHighlightedTab = true; tf_mvm_tabs_discovered.SetValue( tf_mvm_tabs_discovered.GetInt() + 1 ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver ) { extern const char *g_szItemBorders[][5]; if ( !pItemPanel ) return; const char *pszBorder = g_szItemBorders[0][ bMouseOver ]; vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); pItemPanel->SetBorder( pScheme->GetBorder( pszBorder ) ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::UpgradeItemInSlot( int iSlot ) { if ( !m_hPlayer ) return; if ( m_hPlayer->IsPlayerClass( TF_CLASS_SPY ) && iSlot == LOADOUT_POSITION_PRIMARY ) { // Spy doesn't have a primary iSlot = LOADOUT_POSITION_SECONDARY; } m_iWeaponSlotBeingUpgraded = iSlot; if ( m_pSelectWeaponPanel ) { m_pSelectWeaponPanel->SetDialogVariable( "upgrade_description", "" ); } if ( m_pMouseOverUpgradePanel ) { for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); if ( m_iWeaponSlotBeingUpgraded == pItemSlotBuyPanel->nSlot ) { m_pActiveUpgradeBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels.Count() > 0 ? pItemSlotBuyPanel->upgradeBuyPanels[ 0 ] : NULL; FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { pItemSlotBuyPanel->upgradeBuyPanels[ i ]->SetVisible( true ); } } else { FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { pItemSlotBuyPanel->upgradeBuyPanels[ i ]->SetVisible( false ); } } } } UpdateMouseOverHighlight(); UpdateButtonStates( m_nCurrency ); // Get the name of the item that was selected const wchar_t *wszItemName = L""; if ( m_iWeaponSlotBeingUpgraded == -1 ) { wszItemName = g_pVGuiLocalize->Find( g_aPlayerClassNames[ m_hPlayer->GetPlayerClass()->GetClassIndex() ] ); } else { CEconItemView *pCurItemData = CTFPlayerSharedUtils::GetEconItemViewByLoadoutSlot( m_hPlayer, m_iWeaponSlotBeingUpgraded ); if ( pCurItemData ) { wszItemName = pCurItemData->GetItemName(); } } // Set the text displaying which item the upgrades are for ("Shovel", etc.) m_pSelectWeaponPanel->SetDialogVariable( "upgrade_label", wszItemName ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::UpdateUpgradeButtons( void ) { if ( !TFGameRules() ) return; if ( !m_hPlayer ) return; for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); if ( pItemSlotBuyPanel->nSlot != -2 ) { for ( int nUpgrade = 0; nUpgrade < pItemSlotBuyPanel->upgradeBuyPanels.Count(); ++nUpgrade ) { pItemSlotBuyPanel->upgradeBuyPanels[ nUpgrade ]->MarkForDeletion(); } pItemSlotBuyPanel->upgradeBuyPanels.RemoveAll(); FOR_EACH_VEC( g_MannVsMachineUpgrades.m_Upgrades, i ) { CMannVsMachineUpgrades *pUpgrade = &(g_MannVsMachineUpgrades.m_Upgrades[ i ]); // Don't create button if it belongs to the wrong group int nUIGroup = pUpgrade->nUIGroup; if ( ( pItemSlotBuyPanel->nSlot == -1 && ( nUIGroup == UIGROUP_UPGRADE_ATTACHED_TO_ITEM || nUIGroup == UIGROUP_POWERUPBOTTLE ) ) || ( pItemSlotBuyPanel->nSlot != -1 && nUIGroup == UIGROUP_UPGRADE_ATTACHED_TO_PLAYER ) ) { continue; } CEconItemAttributeDefinition *pAttribDef = ItemSystem()->GetStaticDataForAttributeByName( pUpgrade->szAttrib ); if ( !pAttribDef ) { Warning("BAD ATTRIBUTE IN MVM_UPGRADES: %s\n", pUpgrade->szAttrib ); continue; } // Don't create button if it doesn't work for this weapon if ( !TFGameRules()->CanUpgradeWithAttrib( m_hPlayer, pItemSlotBuyPanel->nSlot, pAttribDef->GetDefinitionIndex(), pUpgrade ) ) { continue; } int nCost = pItemSlotBuyPanel->nSlot >= 0 ? TFGameRules()->GetCostForUpgrade( &( g_MannVsMachineUpgrades.m_Upgrades[ i ] ), pItemSlotBuyPanel->nSlot, m_hPlayer->GetPlayerClass()->GetClassIndex(), m_hPlayer ) : g_MannVsMachineUpgrades.m_Upgrades[ i ].nCost; CUpgradeBuyPanel *pUpgradeBuyPanel = new CUpgradeBuyPanel( m_pSelectWeaponPanel, "UpgradeBuyPanel" ); pUpgradeBuyPanel->SetPlayer( m_hPlayer ); pUpgradeBuyPanel->m_nPrice = nCost; pUpgradeBuyPanel->m_nUpgradeIndex = i; pUpgradeBuyPanel->m_nWeaponSlot = pItemSlotBuyPanel->nSlot; pUpgradeBuyPanel->SetInspectMode( ( m_bInspectMode ) ? true : false ); // Store the item equipped at this time, so we can monitor for a change and mark the panel as dirty CEconItemView *pCurItemData = CTFPlayerSharedUtils::GetEconItemViewByLoadoutSlot( m_hPlayer, pItemSlotBuyPanel->nSlot ); if ( pCurItemData ) { pItemSlotBuyPanel->SetItemID( pCurItemData->GetItemID() ); } if ( !m_bInspectMode ) { pUpgradeBuyPanel->m_pIncrementButton->SetCommand( VarArgs( "mvm_upgrade%03d_%i", pUpgradeBuyPanel->m_nUpgradeIndex, pUpgradeBuyPanel->m_nPrice ) ); pUpgradeBuyPanel->m_pDecrementButton->SetCommand( VarArgs( "mvm_downgrade%03d_%i", pUpgradeBuyPanel->m_nUpgradeIndex, pUpgradeBuyPanel->m_nPrice ) ); } pUpgradeBuyPanel->SetZPos( 30 ); pUpgradeBuyPanel->SetVisible( true ); pUpgradeBuyPanel->InvalidateLayout( true, true ); if ( !pUpgradeBuyPanel->ValidateUpgradeStepData() ) { pUpgradeBuyPanel->MarkForDeletion(); continue; } pItemSlotBuyPanel->upgradeBuyPanels.Insert( pUpgradeBuyPanel ); float flValue = pUpgrade->flIncrement; int iFormat = pAttribDef->GetDescriptionFormat(); if ( iFormat == ATTDESCFORM_VALUE_IS_PERCENTAGE || iFormat == ATTDESCFORM_VALUE_IS_INVERTED_PERCENTAGE ) { flValue += 1.0; } CEconAttributeDescription AttrDesc( GLocalizationProvider(), pAttribDef, flValue ); const wchar_t *pDescription = AttrDesc.GetShortDescription().Get(); if ( pDescription && pDescription[ 0 ] ) { pUpgradeBuyPanel->m_pShortDescriptionLabel->SetText( pDescription ); } locchar_t wzCost[64]; loc_sprintf_safe( wzCost, LOCCHAR( "%d" ), pUpgradeBuyPanel->m_nPrice ); pUpgradeBuyPanel->m_pPriceLabel->SetText( wzCost ); } } } UpdateButtonStates( m_nCurrency ); InvalidateLayout(); } void CHudUpgradePanel::UpdateJoystickControls( void ) { static ConVarRef joystick( "joystick" ); if ( !joystick.IsValid() || !joystick.GetBool() ) { return; } bool bUp = ::input->Joystick_GetForward() < 0.0f || ::input->Joystick_GetPitch() < 0.0f || vgui::input()->IsKeyDown( KEY_XBUTTON_UP ) || vgui::input()->IsKeyDown( KEY_UP ); bool bDown = ::input->Joystick_GetForward() > 0.0f || ::input->Joystick_GetPitch() > 0.0f || vgui::input()->IsKeyDown( KEY_XBUTTON_DOWN ) || vgui::input()->IsKeyDown( KEY_DOWN ); bool bNavUpDownPressed = bUp || bDown; bool bLeft = ::input->Joystick_GetSide() < 0.0f || ::input->Joystick_GetYaw() < 0.0f || vgui::input()->IsKeyDown( KEY_XBUTTON_LEFT ) || vgui::input()->IsKeyDown( KEY_LEFT ); bool bRight = ::input->Joystick_GetSide() > 0.0f || ::input->Joystick_GetYaw() > 0.0f || vgui::input()->IsKeyDown( KEY_XBUTTON_RIGHT ) || vgui::input()->IsKeyDown( KEY_RIGHT ); bool bNavLeftRightPressed = bLeft || bRight; bool bAccept = vgui::input()->IsKeyDown( KEY_XBUTTON_A ) || vgui::input()->IsKeyDown( KEY_ENTER ) || vgui::input()->IsKeyDown( STEAMCONTROLLER_A ); bool bBack = vgui::input()->IsKeyDown( KEY_XBUTTON_X ) || vgui::input()->IsKeyDown( KEY_BACKSPACE ) || vgui::input()->IsKeyDown( STEAMCONTROLLER_X ); bool bDone = vgui::input()->IsKeyDown( KEY_XBUTTON_B ) || vgui::input()->IsKeyDown( KEY_ESCAPE ) || vgui::input()->IsKeyDown( STEAMCONTROLLER_B ); bool bNext = vgui::input()->IsKeyDown( KEY_XBUTTON_RIGHT_SHOULDER ) || vgui::input()->IsKeyDown( KEY_PAGEDOWN ); bool bPrev = vgui::input()->IsKeyDown( KEY_XBUTTON_LEFT_SHOULDER ) || vgui::input()->IsKeyDown( KEY_PAGEUP ); bool bNavButtonPressed = bAccept || bBack || bDone || bNext || bPrev; if ( m_bNavUpDownPressed ) { if ( !bNavUpDownPressed ) { m_bNavUpDownPressed = false; } } else if ( bNavUpDownPressed ) { m_bNavUpDownPressed = true; m_bUsingController = true; int nGridPosX = m_pActiveUpgradeBuyPanel ? m_pActiveUpgradeBuyPanel->m_nGridPositionX : 0; int nGridPosY = m_pActiveUpgradeBuyPanel ? m_pActiveUpgradeBuyPanel->m_nGridPositionY : 0; if ( bUp ) { nGridPosY -= 1; } else if ( bDown ) { nGridPosY += 1; } for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); if ( m_iWeaponSlotBeingUpgraded == pItemSlotBuyPanel->nSlot ) { FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { CUpgradeBuyPanel *pUpgradeBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ i ]; if ( pUpgradeBuyPanel && pUpgradeBuyPanel->IsVisible() && pUpgradeBuyPanel->m_nGridPositionX == nGridPosX && pUpgradeBuyPanel->m_nGridPositionY == nGridPosY ) { m_pActiveUpgradeBuyPanel = pUpgradeBuyPanel; UpdateMouseOverHighlight(); break; } } break; } } } if ( m_bNavLeftRightPressed ) { if ( !bNavLeftRightPressed ) { m_bNavLeftRightPressed = false; } } else if ( bNavLeftRightPressed ) { m_bNavLeftRightPressed = true; m_bUsingController = true; int nGridPosX = m_pActiveUpgradeBuyPanel ? m_pActiveUpgradeBuyPanel->m_nGridPositionX : 0; int nGridPosY = m_pActiveUpgradeBuyPanel ? m_pActiveUpgradeBuyPanel->m_nGridPositionY : 0; if ( bLeft ) { nGridPosX -= 1; } else if ( bRight ) { nGridPosX += 1; } for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); if ( m_iWeaponSlotBeingUpgraded == pItemSlotBuyPanel->nSlot ) { FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { CUpgradeBuyPanel *pUpgradeBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ i ]; if ( pUpgradeBuyPanel && pUpgradeBuyPanel->IsVisible() && pUpgradeBuyPanel->m_nGridPositionX == nGridPosX && pUpgradeBuyPanel->m_nGridPositionY == nGridPosY ) { m_pActiveUpgradeBuyPanel = pUpgradeBuyPanel; UpdateMouseOverHighlight(); break; } } break; } } } if ( m_bNavButtonPressed ) { if ( !bNavButtonPressed ) { m_bNavButtonPressed = false; } } else if ( bNavButtonPressed ) { m_bNavButtonPressed = true; m_bUsingController = true; if ( bAccept ) { if ( m_pActiveUpgradeBuyPanel && m_pActiveUpgradeBuyPanel->m_pIncrementButton->IsEnabled() && m_pActiveUpgradeBuyPanel->m_pIncrementButton->IsVisible() ) { OnCommand( VarArgs( "mvm_upgrade%03d_%i", m_pActiveUpgradeBuyPanel->m_nUpgradeIndex, m_pActiveUpgradeBuyPanel->m_nPrice ) ); } else if ( m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_ACTION && GetLocalPlayerBottleFromInventory() != NULL ) { OnCommand( "quick_equip_bottle" ); } } else if ( bBack ) { if ( m_pActiveUpgradeBuyPanel && m_pActiveUpgradeBuyPanel->m_pDecrementButton->IsEnabled() && m_pActiveUpgradeBuyPanel->m_pDecrementButton->IsVisible() ) { OnCommand( VarArgs( "mvm_downgrade%03d_%i", m_pActiveUpgradeBuyPanel->m_nUpgradeIndex, m_pActiveUpgradeBuyPanel->m_nPrice ) ); } } else if ( bDone ) { OnCommand( "close" ); } else if ( bNext ) { OnCommand( "next" ); } else if ( bPrev ) { OnCommand( "prev" ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::UpdateHighlights( void ) { if ( !m_hPlayer ) return; if ( m_iWeaponSlotBeingUpgraded == -1 ) { int x, y; m_pPlayerUpgradeButton->GetPos( x, y ); m_pActiveTabPanel->SetPos( x - YRES( 2 ), y - YRES( 2 ) ); } else { FOR_EACH_VEC( m_pItemPanels, i ) { CItemModelPanel *pItemPanel = m_pItemPanels[ i ]; if ( pItemPanel ) { int iLoadoutSlot = pItemPanel->GetItem()->GetStaticData()->GetLoadoutSlot( m_hPlayer->GetPlayerClass()->GetClassIndex() ); if ( m_iWeaponSlotBeingUpgraded == iLoadoutSlot ) { int x, y; pItemPanel->GetPos( x, y ); m_pActiveTabPanel->SetPos( x - YRES( 2 ), y - YRES( 2 ) ); break; } } } } // Highlight the panel we're mousing over and cycle upgrade tabs vgui::Panel *pMouseOverPanel = vgui::ipanel()->GetPanel( vgui::input()->GetMouseOver(), "ClientDLL" ); if ( !m_bUsingController ) { if ( pMouseOverPanel ) { vgui::Panel *pTabPanel = pMouseOverPanel; bool bIsUpgradeButton = StringHasPrefix( pMouseOverPanel->GetName(), "UpgradeButton" ); bool bIsPlayerUpgradeButton = V_strcmp( pMouseOverPanel->GetName(), "PlayerUpgradeButton" ) == 0; if ( bIsPlayerUpgradeButton ) { // Set the text displaying which item the upgrades are for ("Shovel", etc.) m_pSelectWeaponPanel->SetDialogVariable( "upgrade_description", g_pVGuiLocalize->Find( g_aPlayerClassNames[ m_hPlayer->GetPlayerClass()->GetClassIndex() ] ) ); } if ( bIsUpgradeButton && vgui::input()->IsMouseDown( MOUSE_LEFT ) ) { if ( StringHasPrefix( pMouseOverPanel->GetName(), "UpgradeButton" ) ) { OnItemPanelMousePressed( pTabPanel ); } } if ( !( bIsUpgradeButton || bIsPlayerUpgradeButton ) ) { // It's not mousing over any of the buttons pTabPanel = NULL; // If the player hasn't discovered tabs, cycle the highlight if ( !m_bHighlightedTab ) { bool bBlink = ( static_cast< int >( gpGlobals->curtime * 10.0f ) % 2 ) == 0; if ( bBlink ) { int nPanel = static_cast< int >( gpGlobals->curtime * 2.5f ) % 7; vgui::Panel *pInactiveTabPanel = m_pSelectWeaponPanel->FindChildByName( VarArgs( "InactiveTabPanel%i", nPanel + 1 ) ); if ( pInactiveTabPanel && pInactiveTabPanel->IsVisible() ) { pTabPanel = pInactiveTabPanel; } } } } if ( pTabPanel ) { // Highlight the selected button m_pMouseOverTabPanel->SetVisible( true ); int x, y; pTabPanel->GetPos( x, y ); m_pMouseOverTabPanel->SetPos( x - YRES( 1 ), y - YRES( 1 ) ); } else { m_pMouseOverTabPanel->SetVisible( false ); } } else { m_pMouseOverTabPanel->SetVisible( false ); } for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { CUpgradeBuyPanel *pUpgradeBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ i ]; // Hide the ones not in the current tab if ( m_iWeaponSlotBeingUpgraded != pItemSlotBuyPanel->nSlot ) { pUpgradeBuyPanel->SetVisible( false ); continue; } pUpgradeBuyPanel->SetVisible( true ); if ( pMouseOverPanel && ( pMouseOverPanel == pUpgradeBuyPanel || pMouseOverPanel->GetParent() == pUpgradeBuyPanel ) ) { m_pActiveUpgradeBuyPanel = pUpgradeBuyPanel; UpdateMouseOverHighlight(); } } } } } void CHudUpgradePanel::UpdateMouseOverHighlight( void ) { if ( !m_pActiveUpgradeBuyPanel ) { m_pMouseOverUpgradePanel->SetVisible( false ); return; } // Highlight the selected upgrade panel m_pMouseOverUpgradePanel->SetVisible( true ); int x, y; m_pActiveUpgradeBuyPanel->GetPos( x, y ); m_pMouseOverUpgradePanel->SetPos( x - YRES( 1 ), y - YRES( 1 ) ); CMannVsMachineUpgrades *pUpgrade = &(g_MannVsMachineUpgrades.m_Upgrades[ m_pActiveUpgradeBuyPanel->m_nUpgradeIndex ]); CEconItemAttributeDefinition *pAttribDef = ItemSystem()->GetStaticDataForAttributeByName( pUpgrade->szAttrib ); float flValue = pUpgrade->flIncrement; int iFormat = pAttribDef->GetDescriptionFormat(); if ( iFormat == ATTDESCFORM_VALUE_IS_PERCENTAGE || iFormat == ATTDESCFORM_VALUE_IS_INVERTED_PERCENTAGE ) { flValue += 1.0; } CEconAttributeDescription AttrDesc( GLocalizationProvider(), pAttribDef, flValue ); m_pSelectWeaponPanel->SetDialogVariable( "upgrade_description", AttrDesc.GetDescription().Get() ); m_pSelectWeaponPanel->SetDialogVariable( "upgrade_stats", "" ); } void CHudUpgradePanel::UpdateButtonStates( int nCurrentMoney, int nUpgrade /*= 0*/, int nNumPurchased /*= 0*/ ) { for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); if ( m_iWeaponSlotBeingUpgraded != pItemSlotBuyPanel->nSlot ) { continue; } bool bSellAllowed = ( TFObjectiveResource()->GetMannVsMachineWaveCount() <= 1 ); bool bHideBottleHintText = true; if ( m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_ACTION || ( TFGameRules() && TFGameRules()->GetUpgradeTier( nUpgrade ) ) ) { if ( nNumPurchased > 0 ) { // Need to sell all other powerups FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, j ) { CUpgradeBuyPanel *pActionBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ j ]; if ( pActionBuyPanel->m_nUpgradeIndex != nUpgrade ) { int nCurrentCount = pActionBuyPanel->m_nPurchases + pActionBuyPanel->m_nCurrentStep; if ( nCurrentCount > 0 ) { int nAmmountToSell = bSellAllowed ? nCurrentCount : pActionBuyPanel->m_nPurchases; nCurrentMoney += nAmmountToSell * pActionBuyPanel->m_nPrice; m_nCurrency += nAmmountToSell * pActionBuyPanel->m_nPrice; pActionBuyPanel->m_nPurchases -= nCurrentCount; KeyValues *kv = new KeyValues( "MVM_Upgrade" ); // Refunded for these ones if ( nAmmountToSell ) { KeyValues *kvSub = new KeyValues( "upgrade" ); kvSub->SetInt( "itemslot", pActionBuyPanel->m_nWeaponSlot ); kvSub->SetInt( "upgrade", pActionBuyPanel->m_nUpgradeIndex ); kvSub->SetInt( "count", -nAmmountToSell ); kv->AddSubKey( kvSub ); } // Not refunded for ones we previously bought if ( nCurrentCount != nAmmountToSell ) { KeyValues *kvSub = new KeyValues( "upgrade" ); kvSub->SetInt( "itemslot", pActionBuyPanel->m_nWeaponSlot ); kvSub->SetInt( "upgrade", pActionBuyPanel->m_nUpgradeIndex ); kvSub->SetInt( "count", -( nCurrentCount - nAmmountToSell ) ); kvSub->SetBool( "free", true ); kv->AddSubKey( kvSub ); } engine->ServerCmdKeyValues( kv ); } } } } if ( pItemSlotBuyPanel->upgradeBuyPanels.Count() <= 0 && !m_bInspectMode && m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_ACTION ) { bHideBottleHintText = false; bool bHasBottle = ( GetLocalPlayerBottleFromInventory() != NULL ); wchar_t wszFinalLabel[ 512 ] = L""; const wchar_t *pLocalized = g_pVGuiLocalize->Find( bHasBottle ? "#TF_PVE_Unequipped_Powerup_Bottle" : "#TF_PVE_No_Powerup_Bottle" ); if ( pLocalized ) { wchar_t wszLabel[ 512 ]; V_wcsncpy( wszLabel, pLocalized, sizeof( wszLabel ) ); UTIL_ReplaceKeyBindings( wszLabel, 0, wszFinalLabel, sizeof( wszFinalLabel ) ); } m_pSelectWeaponPanel->SetDialogVariable( "powerup_hint", wszFinalLabel ); m_pSelectWeaponPanel->SetControlVisible( "QuickEquipButton", bHasBottle ); m_pSelectWeaponPanel->SetControlVisible( "LoadoutButton", bHasBottle ); } } if ( bHideBottleHintText ) { m_pSelectWeaponPanel->SetDialogVariable( "powerup_hint", "" ); m_pSelectWeaponPanel->SetControlVisible( "QuickEquipButton", false ); m_pSelectWeaponPanel->SetControlVisible( "LoadoutButton", false ); } bool bSoldFinalPowerUp = false; // Achievement tracking int nUpgradesAtMax = 0; int nUpgrades = pItemSlotBuyPanel->upgradeBuyPanels.Count(); bool bIsResistMax[4] = { 0 }; FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { CUpgradeBuyPanel *pUpgradeBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ i ]; if ( pUpgradeBuyPanel->m_nUpgradeIndex == nUpgrade && nNumPurchased != 0 ) { // Purchased or sold something pUpgradeBuyPanel->m_nPurchases += nNumPurchased; KeyValues *kv = new KeyValues( "MVM_Upgrade" ); KeyValues *kvSub = new KeyValues( "upgrade" ); kvSub->SetInt( "itemslot", pUpgradeBuyPanel->m_nWeaponSlot ); kvSub->SetInt( "upgrade", pUpgradeBuyPanel->m_nUpgradeIndex ); if ( m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_ACTION && !bSellAllowed ) { if ( pUpgradeBuyPanel->m_nPurchases <= 0 && nNumPurchased > 0 ) { // We already bought this previously if ( pUpgradeBuyPanel->m_nPurchases < 0 ) { nNumPurchased += -pUpgradeBuyPanel->m_nPurchases; pUpgradeBuyPanel->m_nPurchases = 0; } nCurrentMoney += nNumPurchased * pUpgradeBuyPanel->m_nPrice; kvSub->SetBool( "free", true ); } else if ( nNumPurchased < 0 && pUpgradeBuyPanel->m_nPurchases == 0 && pUpgradeBuyPanel->m_nCurrentStep == 0 ) { bSoldFinalPowerUp = true; } } kvSub->SetInt( "count", nNumPurchased ); kv->AddSubKey( kvSub ); engine->ServerCmdKeyValues( kv ); } pUpgradeBuyPanel->UpdateImages( nCurrentMoney ); // Check if the upgrade will be maxed when considering purchases bool bMax = false; if ( pUpgradeBuyPanel->m_nPurchases + pUpgradeBuyPanel->m_nCurrentStep == pUpgradeBuyPanel->m_SkillTreeImages.Count() ) { nUpgradesAtMax++; bMax = true; } // For ACHIEVEMENT_TF_MVM_MAX_PLAYER_RESISTANCES if ( bMax && m_iWeaponSlotBeingUpgraded == -1 ) { // This is ugly - I blame time vs workload if ( pUpgradeBuyPanel->m_szAttribName ) { CEconItemAttributeDefinition *pAttribDef = ItemSystem()->GetStaticDataForAttributeByName( pUpgradeBuyPanel->m_szAttribName ); if ( pAttribDef ) { switch ( pAttribDef->GetDefinitionIndex() ) { case 60: // "dmg taken from fire reduced" { bIsResistMax[0] = true; break; } case 62: // "dmg taken from crit reduced" { bIsResistMax[1] = true; break; } case 64: // "dmg taken from blast reduced" { bIsResistMax[2] = true; break; } case 66: // "dmg taken from bullets reduced" { bIsResistMax[3] = true; break; } } } } } } // Check for ACHIEVEMENT_TF_MVM_MAX_PRIMARY_UPGRADES if ( nUpgrades && nUpgrades == nUpgradesAtMax ) { if ( m_hPlayer ) { // Some spies may perceive the knife as their primary, while others // might think it's their pistol - which is actually a secondary if ( m_hPlayer->IsPlayerClass( TF_CLASS_SPY ) ) { if ( m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_MELEE || m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_SECONDARY ) { m_bAwardMaxSlotAchievement = true; } } // Some engineers may perceive the sentry as their primary, so allow it else if ( m_hPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) ) { CEconEntity *pEntity = NULL; CTFPlayerSharedUtils::GetEconItemViewByLoadoutSlot( m_hPlayer, m_iWeaponSlotBeingUpgraded, &pEntity ); CTFWeaponBase *pWeapon = dynamic_cast< CTFWeaponBase* >( pEntity ); if ( pWeapon && pWeapon->GetWeaponID() == TF_WEAPON_PDA_ENGINEER_BUILD ) { m_bAwardMaxSlotAchievement = true; } } // Everyone else if ( m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_PRIMARY ) { m_bAwardMaxSlotAchievement = true; } } } else { m_bAwardMaxSlotAchievement = false; } // Check for ACHIEVEMENT_TF_MVM_MAX_PLAYER_RESISTANCES if ( m_iWeaponSlotBeingUpgraded == -1 ) { m_bAwardMaxResistAchievement = true; for ( int i = 0; i < ARRAYSIZE( bIsResistMax ); i++ ) { if ( !bIsResistMax[i] ) { m_bAwardMaxResistAchievement = false; break; } } } if ( m_iWeaponSlotBeingUpgraded == LOADOUT_POSITION_ACTION && !bSellAllowed && bSoldFinalPowerUp ) { // Buy back already purchased bottles if they sold all of another type FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, j ) { CUpgradeBuyPanel *pActionBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ j ]; if ( pActionBuyPanel->m_nUpgradeIndex != nUpgrade ) { int nCurrentCount = pActionBuyPanel->m_nPurchases + pActionBuyPanel->m_nCurrentStep; if ( nCurrentCount == 0 && pActionBuyPanel->m_nCurrentStep > 0 ) { KeyValues *kv = new KeyValues( "MVM_Upgrade" ); KeyValues *kvSub = new KeyValues( "upgrade" ); kvSub->SetInt( "itemslot", pActionBuyPanel->m_nWeaponSlot ); kvSub->SetInt( "upgrade", pActionBuyPanel->m_nUpgradeIndex ); kvSub->SetInt( "count", pActionBuyPanel->m_nCurrentStep ); kvSub->SetBool( "free", true ); kv->AddSubKey( kvSub ); engine->ServerCmdKeyValues( kv ); pActionBuyPanel->m_nPurchases = 0; pActionBuyPanel->UpdateImages( nCurrentMoney ); } } } } } // Credits count wchar_t wzCount[10]; _snwprintf( wzCount, ARRAYSIZE( wzCount ), L"%d", nCurrentMoney ); m_pSelectWeaponPanel->SetDialogVariable( "credits", wzCount ); } void CHudUpgradePanel::UpdateItemStatsLabel( void ) { if ( !m_pUpgradeItemStatsLabel ) return; m_pUpgradeItemStatsLabel->SetText( "" ); if ( !m_hPlayer ) return; wchar_t wszAttribDesc[4096]; wszAttribDesc[0] = '\0'; m_pUpgradeItemStatsLabel->GetTextImage()->ClearColorChangeStream(); CEconItemDescription itemDesc; CEconItemDescription::CVisibleAttributeDisplayer attrIt; if ( m_iWeaponSlotBeingUpgraded == -1 ) { m_hPlayer->m_AttributeList.IterateAttributes( &attrIt ); } else { CEconItemView *pCurItemData = CTFPlayerSharedUtils::GetEconItemViewByLoadoutSlot( m_hPlayer, m_iWeaponSlotBeingUpgraded ); if ( pCurItemData ) { pCurItemData->IterateAttributes( &attrIt ); } } attrIt.SortAttributes(); attrIt.Finalize( NULL, &itemDesc, GLocalizationProvider() ); int iOutputAttributeLineCount = 0; for ( unsigned int i = 0; i < itemDesc.GetLineCount(); i++ ) { const econ_item_description_line_t& line = itemDesc.GetLine(i); if ( line.unMetaType & kDescLineFlag_Attribute ) { AddItemStatText( line.sText.Get(), line.eColor, wszAttribDesc, ARRAYSIZE( wszAttribDesc ) ); ++iOutputAttributeLineCount; } } if ( iOutputAttributeLineCount == 0 ) { vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); Color col = pScheme->GetColor( GetColorNameForAttribColor( ATTRIB_COL_NEUTRAL ), Color(255,255,255,255) ); m_pUpgradeItemStatsLabel->GetTextImage()->AddColorChange( col, Q_wcslen( wszAttribDesc ) ); wchar_t *pNone = g_pVGuiLocalize->Find( "#TF_PassiveAttribs_None" ); if ( pNone ) { wcsncat( wszAttribDesc, pNone, ARRAYSIZE(wszAttribDesc) ); } } m_pUpgradeItemStatsLabel->SetText( wszAttribDesc ); } void CHudUpgradePanel::CancelUpgrades( void ) { bool bSellAllowed = ( TFObjectiveResource() ? TFObjectiveResource()->GetMannVsMachineWaveCount() <= 1 : true ); KeyValues *kv = new KeyValues( "MVM_Upgrade" ); for ( int nSlotIndex = 0; nSlotIndex < ARRAYSIZE( m_ItemSlotBuyPanels ); ++nSlotIndex ) { ItemSlotBuyPanels *pItemSlotBuyPanel = &( m_ItemSlotBuyPanels[ nSlotIndex ] ); FOR_EACH_VEC( pItemSlotBuyPanel->upgradeBuyPanels, i ) { CUpgradeBuyPanel *pUpgradeBuyPanel = pItemSlotBuyPanel->upgradeBuyPanels[ i ]; if ( pUpgradeBuyPanel->m_nPurchases != 0 ) { KeyValues *kvSub = new KeyValues( "upgrade" ); kvSub->SetInt( "itemslot", pUpgradeBuyPanel->m_nWeaponSlot ); kvSub->SetInt( "upgrade", pUpgradeBuyPanel->m_nUpgradeIndex ); kvSub->SetInt( "count", -pUpgradeBuyPanel->m_nPurchases ); // revert previous buy and sell if ( pItemSlotBuyPanel->nSlot == LOADOUT_POSITION_ACTION && !bSellAllowed && pUpgradeBuyPanel->m_nPurchases < 0 ) { // The player wasn't refunded these so the cancel gives it back for free kvSub->SetBool( "free", true ); } kv->AddSubKey( kvSub ); } } } engine->ServerCmdKeyValues( kv ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::AddItemStatText( const locchar_t *loc_AttrDescText, attrib_colors_t eColor, wchar_t *out_wszAttribDesc, int iAttribDescSize ) { Assert( loc_AttrDescText ); Assert( out_wszAttribDesc ); vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); Assert( pScheme ); // Insert the color change at the current position Color col = pScheme->GetColor( GetColorNameForAttribColor( eColor ), Color(255, 255, 255, 255) ); m_pUpgradeItemStatsLabel->GetTextImage()->AddColorChange( col, Q_wcslen( out_wszAttribDesc ) ); // Now append the text of the attribute wcsncat( out_wszAttribDesc, loc_AttrDescText, iAttribDescSize ); wcsncat( out_wszAttribDesc, L"\n", iAttribDescSize ); } CEconItemView* CHudUpgradePanel::GetLocalPlayerBottleFromInventory( void ) { CPlayerInventory *pLocalInv = TFInventoryManager()->GetLocalInventory(); if ( pLocalInv ) { static CSchemaItemDefHandle pItemDef_MvmPowerupBottle( CTFItemSchema::k_rchMvMPowerupBottleItemDefName ); Assert( pItemDef_MvmPowerupBottle ); if ( pItemDef_MvmPowerupBottle ) { for ( int i = 0 ; i < pLocalInv->GetItemCount() ; ++i ) { CEconItemView *pItem = pLocalInv->GetItem( i ); Assert( pItem ); if ( pItem->GetItemDefinition() == pItemDef_MvmPowerupBottle ) { return pItem; } } } } return NULL; } bool CHudUpgradePanel::QuickEquipBottle( void ) { if ( !m_hPlayer ) return false; if ( m_bInspectMode ) return false; CPlayerInventory *pPlayerInventory = TFInventoryManager()->GetLocalInventory(); if ( !pPlayerInventory ) return false; GCSDK::CGCClientSharedObjectCache *pSOCache = pPlayerInventory->GetSOC(); if ( !pSOCache ) return false; int nClass = m_hPlayer->GetPlayerClass()->GetClassIndex(); CEconItemView *pBottle = GetLocalPlayerBottleFromInventory(); if ( !pBottle ) return false; itemid_t iItemId = pBottle->GetItemID(); if ( iItemId == INVALID_ITEM_ID ) return false; // This clears any in-progress purchases, otherwise they could lose money and upgrades m_bShowUpgradeMenu = false; m_bCancelUpgrades = true; m_bOpenLoadout = false; m_bInspectMode = false; m_hPlayer = NULL; TFInventoryManager()->EquipItemInLoadout( nClass, LOADOUT_POSITION_ACTION, iItemId ); // Tell the GC to tell server that we should respawn if we're in a respawn room GCSDK::CGCMsg< GCSDK::MsgGCEmpty_t > msg( k_EMsgGCRespawnPostLoadoutChange ); GCClientSystem()->BSendMessage( msg ); return true; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudUpgradePanel::OnCommand( const char *command ) { if ( !Q_stricmp( command, "close" ) ) { m_bShowUpgradeMenu = false; m_bCancelUpgrades = false; m_bOpenLoadout = false; // See if we need to award achievements if ( m_bAwardMaxSlotAchievement ) { g_AchievementMgrTF.AwardAchievement( ACHIEVEMENT_TF_MVM_MAX_PRIMARY_UPGRADES ); } if ( m_bAwardMaxResistAchievement ) { g_AchievementMgrTF.AwardAchievement( ACHIEVEMENT_TF_MVM_MAX_PLAYER_RESISTANCES ); } return; } else if ( !Q_stricmp( command, "cancel" ) ) { m_bShowUpgradeMenu = false; m_bCancelUpgrades = true; m_bOpenLoadout = false; m_bInspectMode = false; m_hPlayer = NULL; return; } else if ( !Q_stricmp( command, "next" ) ) { int nPrevLoadoutSlot = -1; int nLoadoutSlot = -1; if ( m_hPlayer ) { int i; for ( i = 0; i < m_pItemPanels.Count(); i++ ) { CItemModelPanel *pItemPanel = m_pItemPanels[ i ]; if ( !pItemPanel ) continue; if ( !pItemPanel->IsVisible() ) continue; nPrevLoadoutSlot = nLoadoutSlot; nLoadoutSlot = pItemPanel->GetItem()->GetStaticData()->GetLoadoutSlot( m_hPlayer->GetPlayerClass()->GetClassIndex() ); if ( m_iWeaponSlotBeingUpgraded == nPrevLoadoutSlot ) break; } if ( i >= m_pItemPanels.Count() ) { UpgradeItemInSlot( -1 ); } else { UpgradeItemInSlot( nLoadoutSlot ); } } } else if ( !Q_stricmp( command, "prev" ) ) { int nPrevLoadoutSlot = -1; int nLoadoutSlot = -1; if ( m_hPlayer ) { int i; for ( i = m_pItemPanels.Count() - 1; i >= 0; i-- ) { CItemModelPanel *pItemPanel = m_pItemPanels[ i ]; if ( !pItemPanel ) continue; if ( !pItemPanel->IsVisible() ) continue; nPrevLoadoutSlot = nLoadoutSlot; nLoadoutSlot = pItemPanel->GetItem()->GetStaticData()->GetLoadoutSlot( m_hPlayer->GetPlayerClass()->GetClassIndex() ); if ( m_iWeaponSlotBeingUpgraded == nPrevLoadoutSlot ) break; } if ( i < 0 ) { UpgradeItemInSlot( -1 ); } else { UpgradeItemInSlot( nLoadoutSlot ); } } } else if ( V_strcmp( command, "quick_equip_bottle" ) == 0 ) { QuickEquipBottle(); return; } else if ( V_strcmp( command, "open_charinfo_direct" ) == 0 ) { m_bShowUpgradeMenu = false; m_bCancelUpgrades = true; m_bOpenLoadout = true; return; } else if ( !Q_stricmp( command, "PlayerUpgrade" ) ) { UpgradeItemInSlot( -1 ); if ( !m_bHighlightedTab ) { // They've clicked a tab... no need to blink them any longer m_bHighlightedTab = true; tf_mvm_tabs_discovered.SetValue( tf_mvm_tabs_discovered.GetInt() + 1 ); } return; } else if ( StringHasPrefix( command, "mvm_upgrade" ) ) { char szUpgradeNums[ 10 ]; V_strncpy( szUpgradeNums, command + V_strlen( "mvm_upgrade" ), sizeof( szUpgradeNums ) ); szUpgradeNums[ 3 ] = '\0'; int nUpgrade = atoi( szUpgradeNums ); int nPrice = atoi( szUpgradeNums + 4 ); if ( m_hPlayer ) { m_nCurrency -= nPrice; UpdateButtonStates( m_nCurrency, nUpgrade, 1 ); m_pSelectWeaponPanel->SetControlEnabled( "CloseButton", true ); m_nUpgradeActivity++; } } else if ( StringHasPrefix( command, "mvm_downgrade" ) ) { char szUpgradeNums[ 10 ]; V_strncpy( szUpgradeNums, command + V_strlen( "mvm_downgrade" ), sizeof( szUpgradeNums ) ); szUpgradeNums[ 3 ] = '\0'; int nUpgrade = atoi( szUpgradeNums ); int nPrice = atoi( szUpgradeNums + 4 ); if ( m_hPlayer ) { m_nCurrency += nPrice; UpdateButtonStates( m_nCurrency, nUpgrade, -1 ); m_pSelectWeaponPanel->SetControlEnabled( "CloseButton", true ); m_nUpgradeActivity--; } } else if ( StringHasPrefix( command, "nexttip" ) ) { UpdateTip(); } else if ( V_strcmp( command, "respec" ) == 0 ) { if ( m_hPlayer ) { CancelUpgrades(); OnCommand( "close" ); KeyValues *kv = new KeyValues( "MVM_Respec" ); engine->ServerCmdKeyValues( kv ); } } else { engine->ClientCmd( const_cast( command ) ); } BaseClass::OnCommand( command ); } void CHudUpgradePanel::UpdateTip() { int iClassUsed; m_pTipPanel->SetDialogVariable( "tiptext", g_TFTips.GetRandomMvMTip( iClassUsed ) ); } bool MannVsMachine_GetUpgradeInfo( int iAttribute, int iQuality, float &flValue ) { FOR_EACH_VEC( g_MannVsMachineUpgrades.m_Upgrades, i ) { CEconItemAttributeDefinition *pAttrib = ItemSystem()->GetItemSchema()->GetAttributeDefinitionByName( g_MannVsMachineUpgrades.m_Upgrades[i].szAttrib ); if ( !pAttrib ) continue; if ( pAttrib->GetDefinitionIndex() == iAttribute && g_MannVsMachineUpgrades.m_Upgrades[i].nQuality == iQuality ) { flValue = g_MannVsMachineUpgrades.m_Upgrades[i].flIncrement; return true; } } return false; }