//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #include "store/store_page.h" #include "vgui/ISurface.h" #include "vgui/IInput.h" #include "vgui/ILocalize.h" #include "gamestringpool.h" #include "econ_item_inventory.h" #include "econ_item_system.h" #include "item_model_panel.h" #include "store/store_panel.h" #include "store/store_preview_item.h" #include "store/store_viewcart.h" #include "rtime.h" #include "econ_ui.h" #include "store/store_page_new.h" #include "gc_clientsystem.h" #include "confirm_dialog.h" #ifdef TF_CLIENT_DLL #include "c_tf_gamestats.h" #include "c_tf_freeaccount.h" #endif // TF_CLIENT_DLL // memdbgon must be the last include file in a .cpp file!!! #include #ifdef TF_CLIENT_DLL void AddSubKeyNamed( KeyValues *pKeys, const char *pszName ); #endif DECLARE_BUILD_FACTORY( CStorePreviewItemIcon ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CStoreItemControlsPanel::CStoreItemControlsPanel( vgui::Panel *pParent, const char *pPanelName, CItemModelPanel *pItemModelPanel ) : vgui::EditablePanel( pParent, pPanelName ), m_pItemModelPanel( pItemModelPanel ), m_pEntry( NULL ), m_bItemPanelEntered( false ), m_bButtonsVisible( false ) { } void CStoreItemControlsPanel::SetMouseHoverHandler( Panel *pHandler ) { m_pMouseHoverHandler = pHandler; } void CStoreItemControlsPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); LoadControlSettings( ShouldUseNewStore() ? "Resource/UI/econ/store/v2/StoreItemControls.res" : "Resource/UI/econ/store/v1/StoreItemControls.res" ); } const econ_store_entry_t *CStoreItemControlsPanel::GetItem() const { return m_pEntry; } void CStoreItemControlsPanel::SetItem( const econ_store_entry_t *pEntry ) { m_pEntry = pEntry; } void CStoreItemControlsPanel::SetButtonsVisible( bool bVisible ) { m_bButtonsVisible = bVisible; for ( int i = 0; i < GetChildCount(); ++i ) { CExButton *pButton = dynamic_cast< CExButton* >( GetChild( i ) ); if ( pButton ) { pButton->SetVisible( bVisible ); pButton->SetArmed( false ); } } } void CStoreItemControlsPanel::OnCursorEntered() { BaseClass::OnCursorEntered(); if ( m_pItemModelPanel && m_pItemModelPanel->HasItem() ) { SetButtonsVisible( true ); } } void CStoreItemControlsPanel::OnCursorExited() { BaseClass::OnCursorExited(); } void CStoreItemControlsPanel::OnItemPanelEntered() { m_bItemPanelEntered = true; SetButtonsVisible( true ); } void CStoreItemControlsPanel::OnItemPanelExited() { m_bItemPanelEntered = false; } void CStoreItemControlsPanel::OnThink() { if ( !m_bItemPanelEntered ) { if ( !IsCursorOver() ) { SetButtonsVisible( false ); } } if ( m_pMouseHoverHandler.Get() ) { KeyValues *pMsg = new KeyValues( "StoreItemControlsPanelHover", "entered", m_bButtonsVisible ); pMsg->SetPtr( "entry", (void *)m_pEntry ); PostMessage( m_pMouseHoverHandler.Get(), pMsg ); } } void CStoreItemControlsPanel::OnCommand( const char *command ) { if ( !Q_strnicmp( command, "addtocart", 9 ) ) { PostActionSignal( new KeyValues( "ItemAddToCart" ) ); } else if ( !Q_strnicmp( command, "preview_item", 12 ) ) { PostActionSignal( new KeyValues( "ItemPreview" ) ); } else if ( !Q_strnicmp( command, "details", 7 ) ) { PostActionSignal( new KeyValues( "ItemDetails" ) ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePreviewItemIcon::OnItemPanelMouseReleased( vgui::Panel *panel ) { PostActionSignal(new KeyValues("ItemIconSelected", "icon", m_iIconIndex)); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CStorePricePanel::CStorePricePanel( vgui::Panel *pParent, const char *pPanelName ) : vgui::EditablePanel( pParent, pPanelName ) { m_bOldDiscountVisibility = false; m_pPrice = NULL; m_pDiscount = NULL; m_pNew = NULL; m_pSale = NULL; m_pSaleBorder = NULL; m_pOGPrice = NULL; m_pCrossout = NULL; m_pLimited = NULL; m_pHighlighted = NULL; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CStorePricePanel::~CStorePricePanel() { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const char* CStorePricePanel::GetPanelResFile() { return "Resource/UI/econ/store/v1/StorePrice.res"; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePricePanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); LoadControlSettings( GetPanelResFile() ); m_pPrice = dynamic_cast< CExLabel* >( FindChildByName( "Price" ) ); m_pDiscount = dynamic_cast< CExLabel* >( FindChildByName( "Discount" ) ); m_pHighlighted = dynamic_cast< CExLabel* >( FindChildByName( "Highlighted" ) ); m_pNew = dynamic_cast< CExLabel* >( FindChildByName( "NewLarge" ) ); if ( !m_pNew ) { m_pNew = dynamic_cast< CExLabel* >( FindChildByName( "New" ) ); } m_pSale = dynamic_cast< CExLabel* >( FindChildByName( "Sale" ) ); m_pSaleBorder = dynamic_cast< vgui::EditablePanel* >( FindChildByName( "StorePriceBorder" ) ); m_pOGPrice = dynamic_cast< CExLabel* >( FindChildByName( "OG_Price" ) ); m_pCrossout = FindChildByName( "OG_Price_CrossOut" ); // Only support one "limited" m_pLimited = FindChildByName( "LimitedLarge" ); if ( !m_pLimited ) { m_pLimited = FindChildByName( "Limited" ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePricePanel::PerformLayout() { BaseClass::PerformLayout(); if ( m_pPrice ) { int contentWidth, contentHeight; m_pPrice->GetContentSize( contentWidth, contentHeight ); int iTextInsetX, iTextInsetY; m_pPrice->GetTextInset( &iTextInsetX, &iTextInsetY ); m_pPrice->SetWide( contentWidth + iTextInsetX ); m_pPrice->SetPos( GetWide() - m_pPrice->GetWide(), GetTall() - m_pPrice->GetTall() ); } if ( m_pPrice && m_pDiscount && m_pOGPrice ) { int contentWidth, contentHeight; m_pDiscount->GetContentSize( contentWidth, contentHeight ); int iTextInsetX, iTextInsetY; m_pDiscount->GetTextInset( &iTextInsetX, &iTextInsetY ); m_pDiscount->SetWide( contentWidth + iTextInsetX ); m_pDiscount->SetPos( 0, GetTall() - m_pDiscount->GetTall() ); // Place original price in bottom-right corner, above the price label int aPricePos[2]; m_pPrice->GetPos( aPricePos[0], aPricePos[1] ); m_pOGPrice->SetWide( GetWide() ); m_pOGPrice->GetContentSize( contentWidth, contentHeight ); int aOGPricePos[2] = { 0, aPricePos[1] - contentHeight }; m_pOGPrice->SetPos( aOGPricePos[0], aOGPricePos[1] ); // Place crossout over original price, halfway down from its vertical starting position m_pCrossout->SetBounds( aOGPricePos[0] + m_pOGPrice->GetWide() - contentWidth, aOGPricePos[1] + contentHeight/2, contentWidth, m_pCrossout->GetTall() ); } if ( m_pNew ) { int contentWidth, contentHeight; m_pNew->GetContentSize( contentWidth, contentHeight ); int iTextInsetX, iTextInsetY; m_pNew->GetTextInset( &iTextInsetX, &iTextInsetY ); m_pNew->SetWide( contentWidth + iTextInsetX ); int iPosX, iPosY; m_pNew->GetPos( iPosX, iPosY ); m_pNew->SetPos( GetWide() - m_pNew->GetWide(), iPosY ); } if ( m_pHighlighted ) { int contentWidth, contentHeight; m_pHighlighted->GetContentSize( contentWidth, contentHeight ); int iTextInsetX, iTextInsetY; m_pHighlighted->GetTextInset( &iTextInsetX, &iTextInsetY ); m_pHighlighted->SetWide( contentWidth + iTextInsetX ); int iPosX, iPosY; m_pHighlighted->GetPos( iPosX, iPosY ); m_pHighlighted->SetPos( GetWide() - m_pHighlighted->GetWide(), iPosY ); } if ( m_pSale ) { int contentWidth, contentHeight; m_pSale->GetContentSize( contentWidth, contentHeight ); int iTextInsetX, iTextInsetY; m_pSale->GetTextInset( &iTextInsetX, &iTextInsetY ); m_pSale->SetWide( contentWidth + iTextInsetX ); int iPosX, iPosY; m_pSale->GetPos( iPosX, iPosY ); m_pSale->SetPos( GetWide() - m_pSale->GetWide(), iPosY ); } if ( m_pLimited ) { int iPosX, iPosY; Panel *pRefPanel = ( m_pSale && m_pSale->IsVisible() ) ? m_pSale : ( m_pNew && m_pNew->IsVisible() ) ? m_pNew : NULL; if ( pRefPanel && pRefPanel->IsVisible() ) { pRefPanel->GetPos( iPosX, iPosY ); m_pLimited->SetPos( GetWide() - m_pLimited->GetWide() - XRES( 3 ), iPosY + pRefPanel->GetTall() + YRES( 3 ) ); } else { m_pLimited->GetPos( iPosX, iPosY ); m_pLimited->SetPos( GetWide() - m_pLimited->GetWide() - XRES( 3 ), iPosY ); } } if ( m_pSaleBorder ) { m_pSaleBorder->SetSize( GetWide(), GetTall() ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePricePanel::SetPriceText( int iPrice, const char *pVariable, const econ_store_entry_t *pEntry ) { if ( iPrice == 0 ) { if ( pEntry->m_bIsMarketItem ) { SetDialogVariable( pVariable, g_pVGuiLocalize->Find( "#Store_Market" ) ); } else { SetDialogVariable( pVariable, "" ); } return; } wchar_t wzLocalizedPrice[ kLocalizedPriceSizeInChararacters ]; MakeMoneyString( wzLocalizedPrice, ARRAYSIZE( wzLocalizedPrice ), iPrice, EconUI()->GetStorePanel()->GetCurrency() ); if ( pEntry->m_bIsMarketItem ) { wchar_t wzMarketString[96]; g_pVGuiLocalize->ConstructString_safe( wzMarketString, LOCCHAR( "%s1 %s2" ), 2, g_pVGuiLocalize->Find( "#Store_Market" ), wzLocalizedPrice ); SetDialogVariable( pVariable, wzMarketString ); } else { SetDialogVariable( pVariable, wzLocalizedPrice ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- static bool IsItemPreviewed( const econ_store_entry_t *pEntry, ECurrency eCurrency ) { return (pEntry->GetItemDefinitionIndex() == InventoryManager()->GetLocalInventory()->GetPreviewItemDef()) && !pEntry->IsOnSale( eCurrency ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void AddItemToCartHelper( const char *pszContext, const econ_store_entry_t *pEntry, ECartItemType eSelectedCartItemType ) { Assert( pEntry ); CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); const ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); // If this is the item we've previewing *and* it's the first one we've added // to the cart then we note that it's a preview item purchase and so we may // get a discount. ECartItemType eCartItemType = eSelectedCartItemType == kCartItem_Purchase && IsItemPreviewed( pEntry, eCurrency ) && !pCart->ContainsItemDefinition( pEntry->GetItemDefinitionIndex() ) ? kCartItem_TryOutUpgrade : eSelectedCartItemType; pCart->AddToCart( pEntry, pszContext, eCartItemType ); EconUI()->GetStorePanel()->OnAddToCart(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void AddItemToCartHelper( const char *pszContext, item_definition_index_t unItemDef, ECartItemType eSelectedCartItemType ) { const econ_store_entry_t *pEntry = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( unItemDef ); if ( pEntry ) { AddItemToCartHelper( pszContext, pEntry, eSelectedCartItemType ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePricePanel::SetItem( const econ_store_entry_t *pEntry ) { const ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); item_price_t unPrice = pEntry->GetCurrentPrice( eCurrency ); SetPriceText( unPrice, "price", pEntry ); const bool bIsItemPreviewed = IsItemPreviewed( pEntry, eCurrency ); if ( bIsItemPreviewed ) { // Make sure we're doing the math we think we're doing -- the item isn't on sale and so // we'll be setting a new price based on the base price. Assert( pEntry->GetCurrentPrice( eCurrency ) == pEntry->GetBasePrice( eCurrency ) ); Assert( unPrice == pEntry->GetBasePrice( eCurrency ) ); // Apply the preview period discount. unPrice *= EconUI()->GetStorePanel()->GetPriceSheet()->GetPreviewPeriodDiscount(); } item_price_t unBasePrice; const bool bIsDiscounted = pEntry->HasDiscount( eCurrency, &unBasePrice ); if ( m_pDiscount && m_pOGPrice ) { // and discount if ( bIsDiscounted == false ) { m_pDiscount->SetVisible( false ); m_pOGPrice->SetVisible( false ); } else { SetPriceText( unBasePrice, "og_price", pEntry ); // set the discount and size float flDiscountPercentage = 1.0f - ( float(unPrice) / float(unBasePrice) ); wchar_t wszDiscount[16]; _snwprintf( wszDiscount, ARRAYSIZE( wszDiscount ), L"-%.0f%%", flDiscountPercentage * 100.0f ); m_pDiscount->SetText( wszDiscount ); m_pDiscount->SetVisible( true ); m_pOGPrice->SetVisible( true ); } } if ( m_pCrossout && m_pOGPrice ) { m_pCrossout->SetVisible( bIsDiscounted ); } if ( m_pNew ) { m_pNew->SetVisible( pEntry->m_bNew ); } if ( m_pHighlighted ) { m_pHighlighted->SetVisible( pEntry->m_bHighlighted ); } if ( m_pSale ) { bool bSaleVisible = false; // We don't check explicitly for "is on sale" here because other things like item previews can // adjust the price we're going to display to the user without adjusting the actual store entry. if ( unPrice != pEntry->GetBasePrice( eCurrency ) && ( m_pNew == NULL || !m_pNew->IsVisible() ) ) { if ( bIsItemPreviewed ) { m_pSale->SetText( "#TF_PreviewDiscount" ); } m_pSale->SetVisible( true ); bSaleVisible = true; } else { m_pSale->SetVisible( false ); } if ( m_pSaleBorder ) { m_pSaleBorder->SetVisible( !ShouldUseNewStore() && bSaleVisible ); } } if ( m_pLimited ) { if ( pEntry->m_bLimited ) { m_pLimited->SetVisible( true ); } else { m_pLimited->SetVisible( false ); } } InvalidateLayout(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePricePanel::OnStoreItemControlsPanelHover( KeyValues *data ) { // We don't care if there's no discount label to deal with if ( !m_pDiscount ) return; // Should the discount label be visible? const econ_store_entry_t *pEntry = (const econ_store_entry_t *)data->GetPtr( "entry" ); if ( !pEntry ) return; ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); if ( !pEntry->HasDiscount( eCurrency, NULL ) ) return; bool bEntered = data->GetInt( "entered" ) == 1; m_pDiscount->SetVisible( !bEntered ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CStorePage::CStorePage(Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile ) : vgui::PropertyPage(parent, "StorePage") { m_pPageData = pPageData; m_pItemModelPanelKVs = NULL; m_pModelPanelLabelsKVs = NULL; m_pCartModelPanelKVs = NULL; m_pCartQuantityLabelKVs = NULL; m_pFeaturedItemPanel = NULL; m_pItemBackdropPanel = new EditablePanel( this, "ItemBackdrop" ); m_pMouseOverItemPanel = new CItemModelPanel( this, "mouseoveritempanel" ); m_pMouseOverTooltip = new CItemModelPanelToolTip( this ); m_pMouseOverTooltip->SetupPanels( this, m_pMouseOverItemPanel ); m_pMouseOverTooltip->SetPositioningStrategy( IPTTP_BOTTOM_SIDE ); if ( IsHomePage() ) { if ( !ShouldUseNewStore() ) { m_pFeaturedItemPanel = new CItemModelPanel( this, "featured_item_panel" ); m_pFeaturedItemPanel->SetActAsButton( true, true ); m_pFeaturedItemPanel->SetTooltip( m_pMouseOverTooltip, "" ); } m_pFilterComboBox = NULL; } else { m_pFilterComboBox = new vgui::ComboBox( this, "ClassFilterComboBox", 11, false ); m_pFilterComboBox->SetVisible( false ); m_pFilterComboBox->AddActionSignalTarget( this ); } m_pPreviewItemResFile = pPreviewItemResFile; m_pPreviewPanel = NULL; m_pSelectedPanel = NULL; m_pNextPageButton = NULL; m_pPrevPageButton = NULL; m_pCheckoutButton = NULL; m_pPreviewItemButton = NULL; m_pAddToCartButtonPanel = NULL; m_iCurrentFilter = 0; m_pCartButton = NULL; m_pBackpackLabel = NULL; m_iSelectedItemDef = 0; m_iSelectDefOnPageShow = 0; m_iSelectPageOnPageShow = 0; m_iOldSelectedItemDef = 0; m_bShouldDeletePreviewPanel = false; m_bFilterDirty = true; ListenForGameEvent( "cart_updated" ); REGISTER_COLOR_AS_OVERRIDABLE( m_colItemPanelBG, "item_panel_bgcolor" ); REGISTER_COLOR_AS_OVERRIDABLE( m_colItemPanelBGMouseover, "item_panel_bgcolor_mouseover" ); REGISTER_COLOR_AS_OVERRIDABLE( m_colItemPanelBGSelected, "item_panel_bgcolor_selected" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CStorePage::~CStorePage() { if ( m_pItemModelPanelKVs ) { m_pItemModelPanelKVs->deleteThis(); m_pItemModelPanelKVs = NULL; } if ( m_pCartModelPanelKVs ) { m_pCartModelPanelKVs->deleteThis(); m_pCartModelPanelKVs = NULL; } if ( m_pCartQuantityLabelKVs ) { m_pCartQuantityLabelKVs->deleteThis(); m_pCartQuantityLabelKVs = NULL; } if ( m_pModelPanelLabelsKVs ) { m_pModelPanelLabelsKVs->deleteThis(); m_pModelPanelLabelsKVs = NULL; } if ( m_bShouldDeletePreviewPanel && m_pPreviewPanel ) { delete m_pPreviewPanel; m_pPreviewPanel = NULL; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnPostCreate() { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const char *CStorePage::GetPageResFile( void ) { return m_pPageData->m_pchPageRes; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CStorePreviewItemPanel *CStorePage::CreatePreviewPanel( void ) { return new CStorePreviewItemPanel( this, m_pPreviewItemResFile, "storepreviewitem", this ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::ApplySchemeSettings( vgui::IScheme *pScheme ) { // First time through, create our preview panel if ( ( ShouldUseNewStore() || !IsHomePage() ) && !m_pPreviewPanel ) { m_pPreviewPanel = CreatePreviewPanel(); // Force it to load it's scheme now, because it needs to be done before we set it's visibility below m_pPreviewPanel->InvalidateLayout( false, true ); m_pPreviewPanel->SetVisible( false ); } BaseClass::ApplySchemeSettings( pScheme ); KeyValues *pConditions = NULL; #ifdef TF_CLIENT_DLL const char *pszHoliday = UTIL_GetActiveHolidayString(); if ( pszHoliday && pszHoliday[0] ) { pConditions = new KeyValues( "conditions" ); char szCondition[64]; Q_snprintf( szCondition, sizeof( szCondition ), "if_%s", pszHoliday ); AddSubKeyNamed( pConditions, szCondition ); } #endif LoadControlSettings( GetPageResFile(), NULL, NULL, pConditions ); if ( pConditions ) { pConditions->deleteThis(); } m_bReapplyItemKVs = true; FOR_EACH_VEC( m_vecItemPanels, i ) { SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); } m_pMouseOverItemPanel->SetBorder( pScheme->GetBorder("LoadoutItemPopupBorder") ); m_pNextPageButton = dynamic_cast( FindChildByName("NextPageButton") ); m_pPrevPageButton = dynamic_cast( FindChildByName("PrevPageButton") ); m_pCheckoutButton = dynamic_cast( FindChildByName("CheckoutButton") ); m_pPreviewItemButton = dynamic_cast( FindChildByName("PreviewItemButton") ); m_pAddToCartButtonPanel = dynamic_cast( FindChildByName("AddToCartButton") ); if ( m_pAddToCartButtonPanel ) { CExButton *pButton = dynamic_cast( m_pAddToCartButtonPanel->FindChildByName("SubButton") ); if ( pButton ) { pButton->AddActionSignalTarget( GetVPanel() ); } } m_pCurPageLabel = dynamic_cast( FindChildByName("CurPageLabel") ); m_pCartButton = dynamic_cast( FindChildByName("CartButton") ); m_pBackpackLabel = dynamic_cast( FindChildByName("BackpackSpaceLabel") ); if ( m_pBackpackLabel ) { m_colBackpackOrg = m_pBackpackLabel->GetFgColor(); } m_pItemDetailsButtonPanel = dynamic_cast( FindChildByName("ItemDetailsButton") ); if ( m_pItemDetailsButtonPanel ) { CExButton *pButton = dynamic_cast( m_pItemDetailsButtonPanel->FindChildByName("SubButton") ); if ( pButton ) { pButton->AddActionSignalTarget( GetVPanel() ); } } m_pItemPreviewButtonPanel = dynamic_cast( FindChildByName("ItemPreviewButton") ); if ( m_pItemPreviewButtonPanel ) { CExButton *pButton = dynamic_cast( m_pItemPreviewButtonPanel->FindChildByName("SubButton") ); if ( pButton ) { pButton->AddActionSignalTarget( GetVPanel() ); } } m_pCartFeaturedItemImage = dynamic_cast( FindChildByName("CartFeaturedItemSymbol") ); if ( m_pCartFeaturedItemImage ) { m_pCartFeaturedItemImage->SetMouseInputEnabled( false ); m_pCartFeaturedItemImage->SetKeyBoardInputEnabled( false ); } vgui::Panel *pPanel = FindChildByName("CartImage"); if ( pPanel ) { pPanel->SetMouseInputEnabled( false ); pPanel->SetKeyBoardInputEnabled( false ); } pPanel = FindChildByName("FeaturedItemSymbol"); if ( pPanel ) { pPanel->SetMouseInputEnabled( false ); pPanel->SetKeyBoardInputEnabled( false ); } pPanel = FindChildByName("FeaturedItemLabel"); if ( pPanel ) { pPanel->SetMouseInputEnabled( false ); pPanel->SetKeyBoardInputEnabled( false ); } pPanel = FindChildByName("FeaturedItemPrice"); if ( pPanel ) { pPanel->SetMouseInputEnabled( false ); pPanel->SetKeyBoardInputEnabled( false ); } if ( m_pFilterComboBox ) { vgui::HFont hFont = pScheme->GetFont( "HudFontSmallestBold", true ); m_pFilterComboBox->SetFont( hFont ); UpdateFilteredItems(); UpdateFilterComboBox(); // Move to "All items" selected m_pFilterComboBox->SilentActivateItemByRow( 0 ); } if ( m_pItemBackdropPanel ) { m_pItemBackdropPanel->SetBgColor( m_colItemBackdropPanel ); } SetDetailsVisible( true ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::ApplySettings( KeyValues *inResourceData ) { BaseClass::ApplySettings( inResourceData ); m_colItemBackdropPanel = inResourceData->GetColor( "item_backdrop_color" ); KeyValues *pItemKV = inResourceData->FindKey( "modelpanels_kv" ); if ( pItemKV ) { if ( m_pItemModelPanelKVs ) { m_pItemModelPanelKVs->deleteThis(); } m_pItemModelPanelKVs = new KeyValues("modelpanels_kv"); pItemKV->CopySubkeys( m_pItemModelPanelKVs ); } pItemKV = inResourceData->FindKey( "modelpanel_labels_kv" ); if ( pItemKV ) { if ( m_pModelPanelLabelsKVs ) { m_pModelPanelLabelsKVs->deleteThis(); } m_pModelPanelLabelsKVs = new KeyValues("modelpanel_labels_kv"); pItemKV->CopySubkeys( m_pModelPanelLabelsKVs ); } pItemKV = inResourceData->FindKey( "cart_modelpanels_kv" ); if ( pItemKV ) { if ( m_pCartModelPanelKVs ) { m_pCartModelPanelKVs->deleteThis(); } m_pCartModelPanelKVs = new KeyValues("cart_modelpanels_kv"); pItemKV->CopySubkeys( m_pCartModelPanelKVs ); } pItemKV = inResourceData->FindKey( "cart_labels_kv" ); if ( pItemKV ) { if ( m_pCartQuantityLabelKVs ) { m_pCartQuantityLabelKVs->deleteThis(); } m_pCartQuantityLabelKVs = new KeyValues("cart_labels_kv"); pItemKV->CopySubkeys( m_pCartQuantityLabelKVs ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::PerformLayout( void ) { if ( m_bReapplyItemKVs ) { m_bReapplyItemKVs = false; FOR_EACH_VEC( m_vecItemPanels, i ) { if ( m_pItemModelPanelKVs ) { m_vecItemPanels[i].m_pItemModelPanel->ApplySettings( m_pItemModelPanelKVs ); SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); m_vecItemPanels[i].m_pItemModelPanel->InvalidateLayout(); } m_vecItemPanels[i].m_pStorePricePanel->InvalidateLayout(); } if ( m_pCartModelPanelKVs ) { FOR_EACH_VEC( m_pCartModelPanels, i ) { m_pCartModelPanels[i]->ApplySettings( m_pCartModelPanelKVs ); SetBorderForItem( m_pCartModelPanels[i], false ); m_pCartModelPanels[i]->InvalidateLayout(); } } if ( m_pCartQuantityLabelKVs ) { FOR_EACH_VEC( m_pCartQuantityLabels, i ) { m_pCartQuantityLabels[i]->ApplySettings( m_pCartQuantityLabelKVs ); m_pCartQuantityLabels[i]->InvalidateLayout(); } } if ( m_pModelPanelLabelsKVs ) { FOR_EACH_VEC( m_pCartQuantityLabels, i ) { m_pCartQuantityLabels[i]->ApplySettings( m_pModelPanelLabelsKVs ); m_pCartQuantityLabels[i]->InvalidateLayout(); } } } BaseClass::PerformLayout(); FOR_EACH_VEC( m_vecItemPanels, i ) { CItemModelPanel *pItemModelPanel = m_vecItemPanels[i].m_pItemModelPanel; CStorePricePanel *pItemPricePanel = m_vecItemPanels[i].m_pStorePricePanel; CStoreItemControlsPanel *pItemControlsPanel = m_vecItemPanels[i].m_pItemControlsPanel; pItemModelPanel->SetVisible( true ); pItemModelPanel->SetNoItemText( "#SelectNoItemSlot" ); PositionItemPanel(pItemModelPanel, i ); int iX,iY,iW,iH; pItemModelPanel->GetBounds( iX, iY, iW, iH ); // Position our price label and controls pItemPricePanel->SetVisible( pItemModelPanel->HasItem() ); pItemPricePanel->SetBounds( iX, iY, iW, iH ); pItemPricePanel->InvalidateLayout( true ); pItemControlsPanel->SetPos( iX + m_iItemControlsXOffset, iY + iH - pItemControlsPanel->GetTall() - m_iItemControlsYOffset ); } if ( m_pItemBackdropPanel && m_vecItemPanels.Count() >= 2 ) { CItemModelPanel *pTopLeftPanel = m_vecItemPanels.Head().m_pItemModelPanel; CItemModelPanel *pBottomRightPanel = m_vecItemPanels.Tail().m_pItemModelPanel; int aItemBackdropBounds[4]; if ( pTopLeftPanel && pBottomRightPanel ) { int nX, nY; pTopLeftPanel->GetPos( nX, nY ); aItemBackdropBounds[0] = nX - m_iItemBackdropLeftMargin; aItemBackdropBounds[1] = nY - m_iItemBackdropTopMargin; pBottomRightPanel->GetPos( nX, nY ); aItemBackdropBounds[2] = nX + pBottomRightPanel->GetWide() + m_iItemBackdropRightMargin - aItemBackdropBounds[0]; aItemBackdropBounds[3] = nY + pBottomRightPanel->GetTall() + m_iItemBackdropBottomMargin - aItemBackdropBounds[1]; m_pItemBackdropPanel->SetBounds( aItemBackdropBounds[0], aItemBackdropBounds[1], aItemBackdropBounds[2], aItemBackdropBounds[3] ); m_pItemBackdropPanel->SetPaintBackgroundType( m_iItemBackdropPaintBackgroundType ); m_pItemBackdropPanel->SetZPos( m_iItemBackdropZPos ); } } if ( m_pCartModelPanels.Count() > 0 ) { bool bFeaturedImagePanelVisible = false; CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); int iCartX, iCartY; m_pCartButton->GetPos( iCartX, iCartY ); int iCartModelWide = m_pCartModelPanels[0]->GetWide(); FOR_EACH_VEC( m_pCartModelPanels, i ) { if ( m_pCartModelPanels[i]->HasItem() ) { m_pCartModelPanels[i]->SetVisible( true ); m_pCartQuantityLabels[i]->SetVisible( true ); int iX = iCartX + m_pCartButton->GetWide() + (XRES(4) * (i+1)) + (iCartModelWide * i); m_pCartModelPanels[i]->SetPos( iX, iCartY ); int iY = iCartY + m_pCartModelPanels[i]->GetTall() - m_pCartQuantityLabels[i]->GetTall(); m_pCartQuantityLabels[i]->SetPos( iX + iCartModelWide - m_pCartQuantityLabels[i]->GetWide(), iY ); // If we're the featured item, show it cart_item_t *pCartItem = pCart->GetItem(i); if ( pCartItem && ( pCartItem->pEntry == EconUI()->GetStorePanel()->GetFeaturedEntry() ) ) { bFeaturedImagePanelVisible = true; if ( m_pCartFeaturedItemImage ) { m_pCartFeaturedItemImage->SetPos( iX - XRES(4), iY - YRES(10) ); } } } } if ( m_pCartFeaturedItemImage && m_pCartFeaturedItemImage->IsVisible() != bFeaturedImagePanelVisible ) { m_pCartFeaturedItemImage->SetVisible( bFeaturedImagePanelVisible ); } } if ( m_pCurPageLabel ) { bool bMultiplePages = (GetNumPages() > 1); m_pCurPageLabel->SetVisible( bMultiplePages ); m_pNextPageButton->SetVisible( bMultiplePages ); m_pPrevPageButton->SetVisible( bMultiplePages ); if ( bMultiplePages ) { m_pNextPageButton->SetEnabled( m_iCurrentPage < (GetNumPages()-1) ); m_pPrevPageButton->SetEnabled( m_iCurrentPage > 0 ); } } if ( IsHomePage() ) { const store_promotion_spend_for_free_item_t *pPromotion = EconUI()->GetStorePanel()->GetPriceSheet()->GetStorePromotion_SpendForFreeItem(); wchar_t wszText[1024]; wchar_t wszPriceThreshold[ kLocalizedPriceSizeInChararacters ]; ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); AssertMsg( eCurrency >= k_ECurrencyUSD && eCurrency < k_ECurrencyMax, "Invalid currency!" ); int iPriceThreshold = pPromotion->m_rgusPriceThreshold[ eCurrency ]; MakeMoneyString( wszPriceThreshold, ARRAYSIZE( wszPriceThreshold ), iPriceThreshold, EconUI()->GetStorePanel()->GetCurrency() ); bool bIsFreeTrial = false; #ifdef TF_CLIENT_DLL bIsFreeTrial = IsFreeTrialAccount(); #endif const char *pszLocString = bIsFreeTrial ? "#Store_FreeTrial_BonusText" : "#Store_Promotion_SpendForGift"; const char *pszElementName = bIsFreeTrial ? "BonusTextLabel" : "PromotionLabel_BonusItem"; g_pVGuiLocalize->ConstructString_safe( wszText, g_pVGuiLocalize->Find( pszLocString ), 1, wszPriceThreshold ); CExLabel *pPromotionText = dynamic_cast< CExLabel* >( FindChildByName( pszElementName, true ) ); if ( pPromotionText ) { pPromotionText->SetText( wszText ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::PositionItemPanel( CItemModelPanel *pPanel, int iIndex ) { CItemModelPanel *pRealPanel = m_vecItemPanels[iIndex].m_pItemModelPanel; int iOffsetIndex = iIndex; int iYPosOffset = 0; int iCenter = GetWide() * 0.5; int iButtonX = (iOffsetIndex % GetNumColumns()); int iButtonY = (iOffsetIndex / GetNumColumns()); int iXPos = m_iItemXPos + (iCenter + m_iItemOffcenterX) + (iButtonX * pRealPanel->GetWide()) + (m_iItemXDelta * iButtonX); int iYPos = m_iItemYPos + (iButtonY * pRealPanel->GetTall() ) + (m_iItemYDelta * iButtonY) + iYPosOffset; pRealPanel->SetPos( iXPos, iYPos ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnPageShow( void ) { m_iCurrentPage = m_iSelectPageOnPageShow; m_iSelectPageOnPageShow = 0; // !KLUDGE! SetDetailsVisible( !ShouldUseNewStore() ); m_bReapplyItemKVs = true; BaseClass::OnPageShow(); if ( !IsHomePage() ) { EconUI()->Gamestats_Store( IE_STORE_TAB_CHANGED, NULL, GetPageName() ); } m_pMouseOverItemPanel->SetVisible( false ); CreateItemPanels(); if ( m_pFilterComboBox ) { SetFilter( 0 ); m_pFilterComboBox->SilentActivateItemByRow( 0 ); // m_pFilterComboBox->SetVisible( !IsHomePage() ); } // Setup sort by newest if ( m_pPageData && !ShouldUseNewStore() ) { eEconStoreSortType iSortType = kEconStoreSortType_DateNewest; CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheetForEdit(); pPriceSheet->SetEconStoreSortType( iSortType ); CEconStoreCategoryManager::StoreCategory_t *pPageData = const_cast< CEconStoreCategoryManager::StoreCategory_t * >( m_pPageData ); pPageData->m_vecEntries.SetLessContext( pPriceSheet ); pPageData->m_vecEntries.RedoSort( true ); UpdateFilteredItems(); } UpdateModelPanels(); if ( m_pCheckoutButton ) { m_pCheckoutButton->RequestFocus(); } if ( m_iSelectDefOnPageShow ) { m_iSelectDefOnPageShow = 0; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CStorePricePanel* CStorePage::CreatePricePanel( int iIndex ) { if ( m_pPageData && !Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_Popular" ) ) return vgui::SETUP_PANEL( new CStorePricePanel_Popular( this, "StorePrice", iIndex + 1 ) ); if ( m_pPageData && !Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_New" ) ) return vgui::SETUP_PANEL( new CStorePricePanel_New( this, "StorePrice" ) ); if ( m_pPageData && !Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_Bundles" ) ) return vgui::SETUP_PANEL( new CStorePricePanel_Bundles( this, "StorePrice" ) ); return vgui::SETUP_PANEL( new CStorePricePanel( this, "StorePrice" ) ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OrderItemsForDisplay( CUtlVector& vecItems ) const { /* // See how I tread upon all the holy concepts of OOP. if ( m_pPageData && !Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_Bundles" ) && !ShouldUseNewStore() ) { vecItems.Sort( &ItemDisplayOrderSort_UseSortOverride ); } */ } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::CreateItemPanels( void ) { int iNumPanels = GetNumItemPanels(); if ( m_pPageData && m_vecItemPanels.Count() < iNumPanels ) { for ( int i = m_vecItemPanels.Count(); i < iNumPanels; i++ ) { int idx = m_vecItemPanels.AddToTail(); item_panel &itempanel = m_vecItemPanels[idx]; CItemModelPanel *pPanel = vgui::SETUP_PANEL( new CItemModelPanel( this, VarArgs("modelpanel%d", i) ) ); pPanel->SetShowQuantity( true ); pPanel->SetActAsButton( true, true ); itempanel.m_pItemModelPanel = pPanel; pPanel->SetTooltip( m_pMouseOverTooltip, "" ); // Create our price panel too CStorePricePanel *pPricePanel = CreatePricePanel( i ); pPricePanel->SetMouseInputEnabled( false ); pPricePanel->SetKeyBoardInputEnabled( false ); itempanel.m_pStorePricePanel = pPricePanel; // and controls CStoreItemControlsPanel *pControlsPanel = vgui::SETUP_PANEL( new CStoreItemControlsPanel( this, "StoreItemControls", pPanel ) ); //pControlsPanel->AddActionSignalTarget( this ); if ( ShouldUseNewStore() ) { pControlsPanel->SetMouseHoverHandler( pPricePanel ); } itempanel.m_pItemControlsPanel = pControlsPanel; } m_EntryIndices.SetCountNonDestructively( m_vecItemPanels.Count() ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnCommand( const char *command ) { if ( !Q_strnicmp( command, "nextpage", 8 ) ) { if ( m_iCurrentPage < (GetNumPages()-1) ) { m_iCurrentPage++; UpdateModelPanels(); } return; } else if ( !Q_strnicmp( command, "prevpage", 8 ) ) { if ( m_iCurrentPage > 0 ) { m_iCurrentPage--; UpdateModelPanels(); } return; } else if ( !Q_strnicmp( command, "preview_item", 12 ) ) { PreviewSelectionItem(); return; } else if ( !Q_strnicmp( command, "addtocart", 9 ) ) { AddSelectionToCart(); return; } else if ( !Q_strnicmp( command, "viewcart", 8 ) ) { OpenStoreViewCartPanel(); return; } else if ( !Q_strnicmp( command, "startshopping", 8 ) ) { PostMessage( EconUI()->GetStorePanel(), new KeyValues("StartShopping") ); return; } else if ( !Q_strnicmp( command, "checkout", 8 ) ) { EconUI()->GetStorePanel()->InitiateCheckout( false ); return; } else if ( !Q_stricmp( command, "show_details" ) ) { if ( m_pSelectedPanel ) { CEconItemView *pItem = m_pSelectedPanel->GetItem(); if ( pItem ) { SetDetailsVisible( true ); } } return; } else if ( !Q_stricmp( command, "show_preview" ) ) { SetDetailsVisible( false ); return; } else if ( !Q_strnicmp( command, "marketplace", 8 ) ) { if ( steamapicontext && steamapicontext->SteamFriends() ) { steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( "http://steamcommunity.com/market/search?appid=440" ); } return; } else if ( !Q_stricmp( command, "reloadscheme" ) ) { InvalidateLayout( false, true ); SetVisible( true ); UpdateSelectionInfoPanel(); return; } else { engine->ClientCmd( const_cast( command ) ); } BaseClass::OnCommand( command ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::FireGameEvent( IGameEvent *event ) { const char * type = event->GetName(); if ( Q_strcmp(type, "cart_updated") == 0 ) { UpdateCart(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnMouseWheeled( int delta ) { if ( m_vecItemPanels.Count() == 0 ) { // on home page, likely return; } int oldSelectionIndex = -1; int currentSelectionIndex = -1; // deselect everything FOR_EACH_VEC( m_vecItemPanels, i ) { if ( m_vecItemPanels[i].m_pItemModelPanel->IsSelected() ) { oldSelectionIndex = i; m_vecItemPanels[i].m_pItemModelPanel->SetSelected( false ); SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); } } // step selection ahead if ( delta < 0 ) { currentSelectionIndex = oldSelectionIndex+1; if ( currentSelectionIndex >= m_vecItemPanels.Count() ) { if ( m_iCurrentPage < (GetNumPages()-1) ) { currentSelectionIndex = 0; m_iCurrentPage++; UpdateModelPanels(); } else { currentSelectionIndex = m_vecItemPanels.Count(); } } else if ( !m_vecItemPanels[ currentSelectionIndex ].m_pItemModelPanel->HasItem() ) { // don't move into empty slots currentSelectionIndex = oldSelectionIndex; } } else if ( delta > 0 ) { currentSelectionIndex = oldSelectionIndex-1; if ( currentSelectionIndex < 0 ) { if ( m_iCurrentPage > 0 ) { currentSelectionIndex = m_vecItemPanels.Count()-1; m_iCurrentPage--; UpdateModelPanels(); } else { currentSelectionIndex = 0; } } else if ( !m_vecItemPanels[ currentSelectionIndex ].m_pItemModelPanel->HasItem() ) { // don't move into empty slots currentSelectionIndex = oldSelectionIndex; } } else { // no actual wheel movement return; } // sanity check currentSelectionIndex = clamp( currentSelectionIndex, 0, m_vecItemPanels.Count()-1 ); m_pSelectedPanel = m_vecItemPanels[ currentSelectionIndex ].m_pItemModelPanel; m_pSelectedPanel->SetSelected( ShouldUseNewStore() ); SetBorderForItem( m_pSelectedPanel, false ); UpdateSelectionInfoPanel(); if ( currentSelectionIndex != oldSelectionIndex ) { vgui::surface()->PlaySound( "ui/buttonclick.wav" ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CStorePage::AssignItemToPanel( CItemModelPanel *pPanel, int iIndex ) { iIndex += (m_iCurrentPage * GetNumItemPanels()); if ( iIndex >= 0 && iIndex < m_FilteredEntries.Count() ) { CEconItemView ItemData; ItemData.Init( m_FilteredEntries[iIndex]->GetItemDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); ItemData.SetItemQuantity( m_FilteredEntries[iIndex]->GetQuantity() ); ItemData.SetClientItemFlags( kEconItemFlagClient_Preview | kEconItemFlagClient_StoreItem ); pPanel->SetItem( &ItemData ); return iIndex; } pPanel->SetItem( NULL ); return -1; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CStorePage::GetNumPages( void ) { return ceil( (float)m_FilteredEntries.Count() / (float)GetNumItemPanels() ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- /* static */ int CStorePage::ItemDisplayOrderSort_UseSortOverride( const econ_store_entry_t *const *ppA, const econ_store_entry_t *const *ppB ) { static CSchemaAttributeDefHandle pAttribDef_StoreSortOverride( "store sort override" ); const GameItemDefinition_t *pDefA = ItemSystem()->GetStaticDataForItemByDefIndex( (*ppA)->GetItemDefinitionIndex() ), *pDefB = ItemSystem()->GetStaticDataForItemByDefIndex( (*ppB)->GetItemDefinitionIndex() ); // We expect only items with valid definition indices to make it into the list to // be sorted. Assert( pDefA ); Assert( pDefB ); // Sort based on: our sort key if we have one; otherwise our definition index. float flValue; int unSortKeyA = ( pAttribDef_StoreSortOverride && FindAttribute_UnsafeBitwiseCast( pDefA, pAttribDef_StoreSortOverride, &flValue ) ) ? (int)flValue : pDefA->GetDefinitionIndex(), unSortKeyB = ( pAttribDef_StoreSortOverride && FindAttribute_UnsafeBitwiseCast( pDefB, pAttribDef_StoreSortOverride, &flValue ) ) ? (int)flValue : pDefB->GetDefinitionIndex(); return unSortKeyA - unSortKeyB; } //----------------------------------------------------------------------------- // Purpose: Update our internal list of entries based on our filters, and count items in each filter //----------------------------------------------------------------------------- void CStorePage::UpdateFilteredItems( void ) { if ( !m_bFilterDirty ) return; m_FilteredEntries.Purge(); m_vecFilterCounts.SetCount( GetNumPrimaryFilters() ); if ( !m_vecFilterCounts.Count() ) return; FOR_EACH_VEC( m_vecFilterCounts, i ) { m_vecFilterCounts[i] = 0; } for ( int i = 0; i < m_pPageData->m_vecEntries.Count(); i++ ) { const econ_store_entry_t *pEntry = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( m_pPageData->m_vecEntries[i] ); GameItemDefinition_t *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( pEntry->GetItemDefinitionIndex() ); if ( pDef ) { // Get a list of applicable filters for the current item definition CUtlVector filterList; GetFiltersForDef( pDef, &filterList ); bool bPassesClassFilter = false; FOR_EACH_VEC( filterList, iFL ) { int iFilter = filterList[iFL]; m_vecFilterCounts[iFilter]++; if ( m_iCurrentFilter == iFilter ) { bPassesClassFilter = true; } } // If the item passes both filters, add it. // NOTE: DoesEntryFilterPassSecondaryFilter() returns true by default. if ( bPassesClassFilter && DoesEntryFilterPassSecondaryFilter( pEntry ) ) { m_FilteredEntries.AddToTail( pEntry ); } } } // Sort our full list of entries however this store page wants it. OrderItemsForDisplay( m_FilteredEntries ); m_bFilterDirty = false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::UpdateModelPanels( void ) { DeSelectAllItemPanels(); UpdateSelectionInfoPanel(); UpdateCart(); if ( m_pPageData != NULL ) { UpdateFilteredItems(); UpdateFilterComboBox(); FOR_EACH_VEC( m_vecItemPanels, i ) { CItemModelPanel *pItemModelPanel = m_vecItemPanels[i].m_pItemModelPanel; pItemModelPanel->SetShowEquipped( true ); m_EntryIndices[i] = AssignItemToPanel( pItemModelPanel, i ); SetBorderForItem( pItemModelPanel, false ); int iEntry = m_EntryIndices[i]; if ( iEntry >= 0 && iEntry < m_FilteredEntries.Count() ) { // Set the price label m_vecItemPanels[i].m_pStorePricePanel->SetItem( m_FilteredEntries[ iEntry ] ); m_vecItemPanels[i].m_pItemControlsPanel->SetItem( m_FilteredEntries[ iEntry ] ); } } } char szTmp[16]; Q_snprintf(szTmp, 16, "%d/%d", m_iCurrentPage+1, GetNumPages() ); SetDialogVariable( "backpackpage", szTmp ); UpdateBackpackLabel(); // Now layout again to position our item buttons InvalidateLayout(); if ( m_pFilterComboBox ) { m_pFilterComboBox->GetComboButton()->SetFgColor( Color( 117,107,94,255 ) ); m_pFilterComboBox->GetComboButton()->SetDefaultColor( Color( 117,107,94,255), Color( 0,0,0,0) ); m_pFilterComboBox->GetComboButton()->SetArmedColor( Color( 117,107,94,255), Color( 0,0,0,0) ); m_pFilterComboBox->GetComboButton()->SetDepressedColor( Color( 117,107,94,255), Color( 0,0,0,0) ); } // If we're not the home page, start with the first item selected already if ( m_vecItemPanels.Count() ) { ToggleSelectItemPanel( m_vecItemPanels[m_iSelectDefOnPageShow].m_pItemModelPanel ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnItemPanelMouseReleased( vgui::Panel *panel ) { CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); if ( pItemPanel && IsVisible() && pItemPanel->HasItem() ) { if ( IsHomePage() ) { // On the homepage, they've clicked the featured item. Find it in a store tab and move to it. PostMessage( EconUI()->GetStorePanel(), new KeyValues("FindAndSelectFeaturedItem") ); } else if ( !pItemPanel->IsSelected() ) { ToggleSelectItemPanel( pItemPanel ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnItemPanelMouseDoublePressed( vgui::Panel *panel ) { if ( IsHomePage() ) { // On the homepage, they've clicked the featured item. Find it in a store tab and move to it. PostMessage( EconUI()->GetStorePanel(), new KeyValues("FindAndSelectFeaturedItem") ); return; } CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); if ( pItemPanel && IsVisible() && pItemPanel->HasItem() ) { // Make sure this panel is selected if ( !pItemPanel->IsSelected() ) { ToggleSelectItemPanel( pItemPanel ); } // Double clicking on an item in the cart takes you to the view cart page FOR_EACH_VEC( m_pCartModelPanels, i ) { if ( m_pCartModelPanels[i] == pItemPanel ) { OpenStoreViewCartPanel(); return; } } // Not a cart panel, so add to cart. OnCommand("addtocart"); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::DeSelectAllItemPanels( void ) { FOR_EACH_VEC( m_vecItemPanels, i ) { if ( m_vecItemPanels[i].m_pItemModelPanel->IsSelected() ) { m_vecItemPanels[i].m_pItemModelPanel->SetSelected( false ); SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); } } FOR_EACH_VEC( m_pCartModelPanels, i ) { if ( m_pCartModelPanels[i]->IsSelected() ) { m_pCartModelPanels[i]->SetSelected( false ); SetBorderForItem( m_pCartModelPanels[i], false ); } } m_pSelectedPanel = NULL; if ( m_pFeaturedItemPanel && m_pFeaturedItemPanel->IsSelected() ) { m_pFeaturedItemPanel->SetSelected( false ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::ToggleSelectItemPanel( CItemModelPanel *pPanel ) { if ( ShouldUseNewStore() ) return; if ( pPanel->IsSelected() || !pPanel->HasItem() ) { pPanel->SetSelected( false ); m_pSelectedPanel = NULL; } else { DeSelectAllItemPanels(); pPanel->SetSelected( true ); m_pSelectedPanel = pPanel; } SetBorderForItem( pPanel, false ); UpdateSelectionInfoPanel(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::SelectItemPanel( CItemModelPanel *pPanel ) { DeSelectAllItemPanels(); pPanel->SetSelected( true ); m_pSelectedPanel = pPanel; SetBorderForItem( pPanel, false ); UpdateSelectionInfoPanel(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnItemPanelEntered( vgui::Panel *panel ) { CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); if ( pItemPanel && IsVisible() ) { CEconItemView *pItem = pItemPanel->GetItem(); if ( !pItemPanel->IsSelected() ) { SetBorderForItem( pItemPanel, pItem != NULL ); } if ( pItemPanel->HasItem() ) { // make related controls visible FOR_EACH_VEC( m_vecItemPanels, i ) { item_panel &itempanel = m_vecItemPanels[i]; if ( itempanel.m_pItemModelPanel == pItemPanel ) { itempanel.m_pItemControlsPanel->OnItemPanelEntered(); break; } } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnItemPanelExited( vgui::Panel *panel ) { CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); if ( pItemPanel && IsVisible() ) { if ( !pItemPanel->IsSelected() ) { SetBorderForItem( pItemPanel, false ); } if ( pItemPanel->HasItem() ) { // make related controls visible FOR_EACH_VEC( m_vecItemPanels, i ) { item_panel &itempanel = m_vecItemPanels[i]; if ( itempanel.m_pItemModelPanel == pItemPanel ) { itempanel.m_pItemControlsPanel->OnItemPanelExited(); break; } } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnItemAddToCart( vgui::Panel *panel ) { CStoreItemControlsPanel *pControlsPanel = dynamic_cast< CStoreItemControlsPanel * >( panel ); if ( pControlsPanel ) { const econ_store_entry_t *pEntry = pControlsPanel->GetItem(); if ( pEntry ) { if ( !ShouldUseNewStore() ) { SelectItemPanel( pControlsPanel->GetItemModelPanel() ); } else { #if defined( TF_CLIENT_DLL ) C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_add_to_cart", "minibutton" ); #endif } AddItemToCartHelper( GetPageName(), pEntry, kCartItem_Purchase ); UpdateCart(); } // Turn the free slots indicator red if we can't fit everything. UpdateBackpackLabel(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver ) { if ( !pItemPanel || pItemPanel == m_pFeaturedItemPanel ) return; // Store panels use backgrounds instead of borders pItemPanel->SetBorder( NULL ); pItemPanel->SetPaintBackgroundEnabled( true ); if ( pItemPanel->IsSelected() ) { pItemPanel->SetBgColor( m_colItemPanelBGSelected ); } else if ( bMouseOver ) { pItemPanel->SetBgColor( m_colItemPanelBGMouseover ); } else { pItemPanel->SetBgColor( m_colItemPanelBG ); } const CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheet(); if ( pItemPanel->GetItem() && pPriceSheet ) { const econ_store_entry_t *pEntry = pPriceSheet->GetEntry( pItemPanel->GetItem()->GetItemDefIndex() ); if (pEntry && pEntry->m_bHighlighted && !bMouseOver ) { pItemPanel->SetBorder( vgui::scheme()->GetIScheme( GetScheme() )->GetBorder( "StoreHighlightedBackgroundBorder" ) ); pItemPanel->SetPaintBorderEnabled( true ); pItemPanel->SetPaintBackgroundEnabled( false ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::CalculateItemButtonPos( CItemModelPanel *pItemPanel, int x, int y, int *iXPos, int *iYPos ) { *iXPos = x; *iYPos = (y + pItemPanel->GetTall() + YRES(4)); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::UpdateSelectionInfoPanel( void ) { // Home page doesn't support item selections if ( IsHomePage() ) return; if ( m_pPreviewItemButton ) { m_pPreviewItemButton->SetVisible( false ); } if ( m_pSelectedPanel ) { const econ_store_entry_t *pEntry = GetSelectedEntry(); CEconItemView *pItem = m_pSelectedPanel->GetItem(); if ( pItem && pEntry ) { if ( m_pPreviewItemButton ) { m_pPreviewItemButton->SetVisible( pEntry->CanPreview() ); } m_iOldSelectedItemDef = m_iSelectedItemDef; m_iSelectedItemDef = pItem->GetItemDefIndex(); if ( m_iSelectedItemDef != m_iOldSelectedItemDef ) { EconUI()->Gamestats_Store( IE_STORE_ITEM_SELECTED, pItem, GetPageName() ); } CEconItemDefinition *pItemData = pItem->GetStaticData(); if ( pItemData ) { ShowPreview( 0, pEntry ); InvalidateLayout(); wchar_t wzLocalizedPrice[ kLocalizedPriceSizeInChararacters ]; int iPrice = pEntry->GetCurrentPrice( EconUI()->GetStorePanel()->GetCurrency() ); MakeMoneyString( wzLocalizedPrice, ARRAYSIZE( wzLocalizedPrice ), iPrice, EconUI()->GetStorePanel()->GetCurrency() ); SetDialogVariable("selectionprice", wzLocalizedPrice ); if ( m_pAddToCartButtonPanel ) { m_pAddToCartButtonPanel->SetVisible( true ); } return; } } } SetDialogVariable("selectionprice", "" ); if ( m_pAddToCartButtonPanel ) { m_pAddToCartButtonPanel->SetVisible( false ); } m_iSelectedItemDef = 0; } //----------------------------------------------------------------------------- // Purpose: Called when text changes in combo box //----------------------------------------------------------------------------- void CStorePage::OnTextChanged( KeyValues *data ) { Panel *pPanel = reinterpret_cast( data->GetPtr("panel") ); vgui::ComboBox *pComboBox = dynamic_cast( pPanel ); m_bFilterDirty = true; if ( pComboBox == m_pFilterComboBox ) { // the class selection combo box changed, update class details KeyValues *pUserData = m_pFilterComboBox->GetActiveItemUserData(); if ( !pUserData ) return; int iFilter = pUserData->GetInt( "filter", 0 ); // If there are no items for that class, refuse to switch if ( iFilter && m_vecFilterCounts[iFilter] <= 0 ) { m_pFilterComboBox->ActivateItemByRow( m_iCurrentFilter ? m_iCurrentFilter+1 : 0 ); return; } SetFilter( iFilter ); m_iCurrentPage = 0; UpdateModelPanels(); m_pCheckoutButton->RequestFocus(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::SetFilter( int iFilter ) { if ( iFilter != m_iCurrentFilter ) m_bFilterDirty = true; m_iCurrentFilter = iFilter; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::ShowPreview( int iClass, const econ_store_entry_t* pEntry ) { if ( !m_pPreviewPanel ) return; CEconItemView itemData; itemData.Init( m_iSelectedItemDef, AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); itemData.SetClientItemFlags( kEconItemFlagClient_Preview ); m_pPreviewPanel->PreviewItem( iClass, &itemData, pEntry ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::SetDetailsVisible( bool bVisible ) { if ( m_pPreviewPanel ) { m_pPreviewPanel->SetState( bVisible ? PS_DETAILS : PS_ITEM ); } if ( m_pItemPreviewButtonPanel && m_pItemDetailsButtonPanel ) { vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); if ( bVisible ) { m_pItemPreviewButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabUnselected") ); m_pItemDetailsButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabSelected") ); } else { m_pItemPreviewButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabSelected") ); m_pItemDetailsButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabUnselected") ); } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CStorePage::FindAndSelectEntry( const econ_store_entry_t *pEntry ) { // We can't search if we haven't created our item panels & filtered. CreateItemPanels(); SetFilter( FILTER_ALL_ITEMS ); UpdateFilteredItems(); FOR_EACH_VEC( m_FilteredEntries, i ) { if ( m_FilteredEntries[i]->GetItemDefinitionIndex() == pEntry->GetItemDefinitionIndex() ) { // Figure out what page it'll be on int iPage = floor( (float)i / (float)GetNumItemPanels() ); // Switch to that page m_iCurrentPage = iPage; UpdateModelPanels(); m_iSelectPageOnPageShow = iPage; // Then select the item model panel for this item FOR_EACH_VEC( m_vecItemPanels, p ) { CEconItemView *pItem = m_vecItemPanels[p].m_pItemModelPanel->GetItem(); if ( pItem && pItem->GetItemDefIndex() == pEntry->GetItemDefinitionIndex() ) { // We can't select here, because the pageshow will stomp it. // Remember that this is the panel we'd like to have selected. m_iSelectDefOnPageShow = p; break; } } return true; } } return false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const econ_store_entry_t *CStorePage::GetSelectedEntry( void ) { // Get the entry for the panel. int iEntry = -1; if ( m_pFeaturedItemPanel == m_pSelectedPanel ) return EconUI()->GetStorePanel()->GetFeaturedEntry(); FOR_EACH_VEC( m_vecItemPanels, i ) { if ( m_vecItemPanels[i].m_pItemModelPanel == m_pSelectedPanel ) { iEntry = m_EntryIndices[i]; if ( iEntry >= 0 && iEntry < m_FilteredEntries.Count() ) return m_FilteredEntries[iEntry]; } } // It's probably something already in our cart. FOR_EACH_VEC( m_pCartModelPanels, i ) { if ( m_pCartModelPanels[i] == m_pSelectedPanel ) { CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); if ( i < pCart->GetNumEntries() ) { cart_item_t *pCartItem = pCart->GetItem(i); return pCartItem->pEntry; } } } return NULL; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::AddSelectionToCart( void ) { if ( !m_pSelectedPanel ) return; // Get the entry for the panel. const econ_store_entry_t *pEntry = GetSelectedEntry(); if ( pEntry ) { AddItemToCartHelper( GetPageName(), pEntry, kCartItem_Purchase ); UpdateCart(); } // Turn the free slots indicator red if we can't fit everything. UpdateBackpackLabel(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::UpdateCart( void ) { if ( !IsVisible() || ( !ShouldUseNewStore() && IsHomePage() ) ) return; CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); int iNumEntriesInCart = pCart->GetNumEntries(); // Now update the item icons next to the cart. if ( m_pCartModelPanels.Count() < iNumEntriesInCart ) { // Support a max of 10 items in the cart quickview right now for ( int i = m_pCartModelPanels.Count(); (i < iNumEntriesInCart) && (i < m_iMaxCartModelPanels); i++ ) { CItemModelPanel *pPanel = vgui::SETUP_PANEL( new CItemModelPanel( this, VarArgs("cartmodelpanel%d", i) ) ); pPanel->SetActAsButton( true, true ); pPanel->ApplySettings( m_pCartModelPanelKVs ); SetBorderForItem( pPanel, false ); m_pCartModelPanels.AddToTail( pPanel ); pPanel->SetTooltip( m_pMouseOverTooltip, "" ); CExLabel *pLabel = vgui::SETUP_PANEL( new CExLabel( this, VarArgs("cartquantitylabel%d", i), "X" ) ); pLabel->ApplySettings( m_pCartQuantityLabelKVs ); pLabel->SetMouseInputEnabled( false ); pLabel->SetKeyBoardInputEnabled( false ); m_pCartQuantityLabels.AddToTail( pLabel ); } } UpdateBackpackLabel(); InvalidateLayout(); CEconItemView *pItemData = new CEconItemView(); // Assign the items in the cart to the panels FOR_EACH_VEC( m_pCartModelPanels, i ) { if ( i >= iNumEntriesInCart ) { m_pCartModelPanels[i]->SetItem( NULL ); m_pCartModelPanels[i]->SetVisible( false ); m_pCartQuantityLabels[i]->SetVisible( false ); continue; } cart_item_t *pCartItem = pCart->GetItem(i); pItemData->Init( pCartItem->pEntry->GetItemDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); pItemData->SetClientItemFlags( kEconItemFlagClient_Preview | kEconItemFlagClient_StoreItem ); m_pCartModelPanels[i]->SetItem( pItemData ); m_pCartModelPanels[i]->SetVisible( true ); m_pCartQuantityLabels[i]->SetVisible( true ); m_pCartQuantityLabels[i]->SetText( VarArgs("%d",pCartItem->iQuantity) ); } delete pItemData; // Update the item count wchar_t wszCount[16]; wchar_t wzLocalized[512]; _snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", pCart->GetTotalItems() ); g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( "#Store_Cart" ), 1, wszCount ); SetDialogVariable("storecart", wzLocalized ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- ConVar econ_never_show_items_in_cart_count( "econ_never_show_items_in_cart_count", "1", FCVAR_DEVELOPMENTONLY ); void CStorePage::UpdateBackpackLabel( void ) { wchar_t wszBackpackSlotCount[16]; wchar_t wszLocalized[512]; // How many slots do we have free in our current backpack? This won't take into // consideration expanders, account upgrades, etc. const int iMaxItemCount = InventoryManager()->GetLocalInventory()->GetMaxItemCount(), iCurItemCount = InventoryManager()->GetLocalInventory()->GetItemCount(); AssertMsg( iMaxItemCount - iCurItemCount >= 0, "You have a negative number of backpack slots available - fix me!" ); const int iBaseFreeSlots = MAX( 0, iMaxItemCount - iCurItemCount ); _snwprintf( wszBackpackSlotCount, ARRAYSIZE( wszBackpackSlotCount ), L"%d", iBaseFreeSlots ); // Breaking out bundles into individual items, etc., how many backpack slots will the // items in our cart take up? const int iItemsInCart = EconUI()->GetStorePanel()->GetCart()->GetTotalConcreteItems(); if ( iItemsInCart == 0 || econ_never_show_items_in_cart_count.GetBool() ) { g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Store_FreeBackpackSpace" ), 1, wszBackpackSlotCount ); } else { wchar_t wszCartCount[16]; _snwprintf( wszCartCount, ARRAYSIZE( wszCartCount ), L"%d", iItemsInCart ); #if defined( TF_CLIENT_DLL ) if ( IsFreeTrialAccount() ) { wchar_t wszUpgradeSlotCount[16]; _snwprintf( wszUpgradeSlotCount, ARRAYSIZE( wszUpgradeSlotCount ), L"%d", DEFAULT_NUM_BACKPACK_SLOTS - DEFAULT_NUM_BACKPACK_SLOTS_FREE_TRIAL_ACCOUNT ); // We're a free trial account so we show the number of backpack slots we really have, // the number of slots we get as a bonus when purchasing, and then the number of items // in our cart. g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Store_FreeBackpackSpace_WithCartItems_WithUpgrade" ), 3, wszBackpackSlotCount, wszCartCount, wszUpgradeSlotCount ); } else #endif // defined( TF_CLIENT_DLL ) { // We aren't a free trial account, so there is no account upgrade included in // this purchase, so fall back to showing the number of items in our cart. g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Store_FreeBackpackSpace_WithCartItems" ), 2, wszBackpackSlotCount, wszCartCount ); } } SetDialogVariable( "freebackpackspace", wszLocalized ); if ( m_pBackpackLabel ) { const Color clrTooMany = ShouldUseNewStore() ? Color(200,80,60,255) : Color(255,0,0,255); m_pBackpackLabel->SetFgColor( InventoryManager()->GetLocalInventory()->CanPurchaseItems( iItemsInCart ) ? m_colBackpackOrg : clrTooMany ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::UpdateFilterComboBox( void ) { if ( !m_pFilterComboBox ) return; m_pFilterComboBox->RemoveAll(); // All items KeyValues *pKeyValues = new KeyValues( "data" ); pKeyValues->SetInt( "filter", FILTER_ALL_ITEMS ); m_pFilterComboBox->AddItem( "#Store_ClassFilter_None", pKeyValues ); pKeyValues->deleteThis(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::PreviewSelectionItem( void ) { if ( !m_pSelectedPanel ) return; // Get the entry for the panel. const econ_store_entry_t *pEntry = GetSelectedEntry(); if ( !pEntry ) return; if ( !pEntry->CanPreview() ) return; DoPreviewItem( pEntry->GetItemDefinitionIndex() ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::DoPreviewItem( item_definition_index_t usItemDef ) { #ifdef TF_CLIENT_DLL C_CTFGameStats::ImmediateWriteInterfaceEvent( "do_try_out_item", CFmtStr( "%i", usItemDef ).Access() ); #endif if ( usItemDef == InventoryManager()->GetLocalInventory()->GetPreviewItemDef() ) { ShowMessageBox( "#ItemPreview_AlreadyPreviewTitle", "#ItemPreview_AlreadyPreviewText", "#GameUI_OK" ); return; } // Send a message to the GC asking if this player can preview an item. GCSDK::CGCMsg< MsgGCCheckItemPreviewStatus_t > msg( k_EMsgGCItemPreviewCheckStatus ); msg.Body().m_unItemDefIndex = usItemDef; // OGS LOGGING HERE GCClientSystem()->BSendMessage( msg ); // Response is handled in item_rental_ui.cpp. } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CStorePage::OnPreviewItem( KeyValues *pData ) { DoPreviewItem( pData->GetInt( "item_def_index" ) ); }