You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1183 lines
37 KiB
1183 lines
37 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "quest_log_panel.h"
|
||
|
#include "ienginevgui.h"
|
||
|
#include "c_tf_gamestats.h"
|
||
|
#include "store/store_panel.h"
|
||
|
#include "econ/econ_ui.h"
|
||
|
#include "clientmode_tf.h"
|
||
|
#include "tf_hud_mainmenuoverride.h"
|
||
|
#include "vgui_int.h"
|
||
|
#include "IGameUIFuncs.h" // for key bindings
|
||
|
#include <vgui_controls/AnimationController.h>
|
||
|
#include "tf_item_inventory.h"
|
||
|
#include "vgui/IInput.h"
|
||
|
#include "item_ad_panel.h"
|
||
|
#include "vgui_controls/ProgressBar.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
|
||
|
|
||
|
static CItemModelPanelToolTip* g_spItemTooltip = NULL;
|
||
|
CQuestTooltip* g_spTextTooltip = NULL;
|
||
|
|
||
|
CQuestLogPanel *GetQuestLog()
|
||
|
{
|
||
|
CQuestLogPanel *pQuestLogPanel = (CQuestLogPanel*)gViewPortInterface->FindPanelByName( PANEL_QUEST_LOG );
|
||
|
return pQuestLogPanel;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CScrollableQuestList::CScrollableQuestList( vgui::Panel *parent, const char *pszPanelName )
|
||
|
: EditablePanel( parent, pszPanelName )
|
||
|
, m_pCompletingPanel( NULL )
|
||
|
, m_bQuestsLayoutDirty( false )
|
||
|
, m_pszNoQuests( NULL )
|
||
|
, m_pszNeedAPass( NULL )
|
||
|
, m_pszNotPossible( NULL )
|
||
|
{
|
||
|
m_pContainer = new EditablePanel( this, "Container" );
|
||
|
m_vecQuestItemPanels.SetSize( 2 );
|
||
|
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
m_vecQuestItemPanels[ i ] = new CQuestItemPanel( m_pContainer, "QuestItemPanel", NULL, this );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CScrollableQuestList::~CScrollableQuestList()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
const char *pszResFile = "Resource/UI/econ/ScrollableQuestList.res";
|
||
|
|
||
|
// Check if the operation wants to override our default res file
|
||
|
const auto& mapOperations = GetItemSchema()->GetOperationDefinitions();
|
||
|
FOR_EACH_MAP_FAST( mapOperations, i )
|
||
|
{
|
||
|
CEconOperationDefinition* pCurrentOperation = mapOperations[i];
|
||
|
// Take the first active operation's res file that's different than default
|
||
|
if ( pCurrentOperation->IsActive() && pCurrentOperation->GetQuestListOverrideResFile() )
|
||
|
{
|
||
|
// Use the first found for now
|
||
|
pszResFile = pCurrentOperation->GetQuestListOverrideResFile();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LoadControlSettings( pszResFile );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
m_pszNoQuests = inResourceData->GetString( "no_quests", "#QuestLog_NoQuests" );
|
||
|
m_pszNeedAPass = inResourceData->GetString( "need_a_pass", "#QuestLog_NeedPassForContracts" );
|
||
|
m_pszNotPossible = inResourceData->GetString( "not_possible", "#QuestLog_NoContractsPossible" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::PerformLayout( void )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
m_pContainer->InvalidateLayout( true );
|
||
|
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
m_vecQuestItemPanels[ i ]->InvalidateLayout( true, true );
|
||
|
m_vecQuestItemPanels[ i ]->SetZPos( 1 + i );
|
||
|
}
|
||
|
|
||
|
PositionQuestItemPanels();
|
||
|
|
||
|
UpdateEmptyMessage();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::OnThink()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
if ( m_bQuestsLayoutDirty )
|
||
|
{
|
||
|
m_bQuestsLayoutDirty = false;
|
||
|
|
||
|
PositionQuestItemPanels();
|
||
|
}
|
||
|
|
||
|
// Conditionally turn mouse input on/off based on where the mouse is
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
m_vecQuestItemPanels[i]->SetMouseInputEnabled( m_vecQuestItemPanels[i]->IsCursorOverMainContainer() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CScrollableQuestList::OnCommand( const char *command )
|
||
|
{
|
||
|
if ( FStrEq( command, "deselect_all" ) )
|
||
|
{
|
||
|
SetSelected( NULL, false );
|
||
|
}
|
||
|
|
||
|
BaseClass::OnCommand( command );
|
||
|
}
|
||
|
|
||
|
int QuestSort_AcquiredTime( CQuestItemPanel* const* p1, CQuestItemPanel* const* p2 )
|
||
|
{
|
||
|
if ( !(*p1)->GetItem() )
|
||
|
return -1;
|
||
|
|
||
|
if ( !(*p2)->GetItem() )
|
||
|
return 1;
|
||
|
|
||
|
// Newest items first
|
||
|
return (*p1)->GetItem()->GetID() - (*p2)->GetItem()->GetID();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::PositionQuestItemPanels()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
// We dont do anything when a quest is completing
|
||
|
if ( m_pCompletingPanel != NULL )
|
||
|
return;
|
||
|
|
||
|
int nVisible = 0;
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
CQuestItemPanel* pPanel = m_vecQuestItemPanels[i];
|
||
|
if ( pPanel )
|
||
|
{
|
||
|
pPanel->SetVisible( pPanel->GetItem() );
|
||
|
|
||
|
if ( pPanel->GetItem() )
|
||
|
{
|
||
|
++nVisible;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CExLabel *pLabel = FindControl<CExLabel>( "EmptyLabel", true );
|
||
|
if ( pLabel )
|
||
|
{
|
||
|
pLabel->SetVisible( nVisible == 0 );
|
||
|
}
|
||
|
|
||
|
// Check for a selected panel
|
||
|
const CQuestItemPanel* pSelected = NULL;
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
if ( m_vecQuestItemPanels[i]->IsSelected() )
|
||
|
{
|
||
|
Assert( pSelected == NULL );
|
||
|
pSelected = m_vecQuestItemPanels[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct FolderCommands_t
|
||
|
{
|
||
|
const char* m_pszSelected;
|
||
|
const char* m_pszOtherIsSelected;
|
||
|
const char* m_pszNoneSelected;
|
||
|
};
|
||
|
|
||
|
const FolderCommands_t folderCommands[] = { { "QuestItem_Back_Selected", "QuestItem_Back_OtherSelected", "QuestItem_Back_NoneSelected" }
|
||
|
, { "QuestItem_Front_Selected", "QuestItem_Front_OtherSelected", "QuestItem_Front_NoneSelected" } };
|
||
|
|
||
|
// Update the positions
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
// This is the selected panel
|
||
|
if ( pSelected == m_vecQuestItemPanels[ i ] )
|
||
|
{
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_vecQuestItemPanels[ i ], folderCommands[i].m_pszSelected );
|
||
|
}
|
||
|
else if ( pSelected ) // Some other panel is selected
|
||
|
{
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_vecQuestItemPanels[ i ], folderCommands[i].m_pszOtherIsSelected );
|
||
|
}
|
||
|
else // No panel is selected
|
||
|
{
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_vecQuestItemPanels[ i ], folderCommands[i].m_pszNoneSelected );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::SetSelected( CQuestItemPanel *pItem, bool bImmediately )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
m_vecQuestItemPanels[ i ]->SetSelected( m_vecQuestItemPanels[ i ] == pItem, bImmediately );
|
||
|
}
|
||
|
|
||
|
PositionQuestItemPanels();
|
||
|
}
|
||
|
|
||
|
bool DoesLootlistDropQuests( const CEconLootListDefinition* pLootList )
|
||
|
{
|
||
|
FOR_EACH_VEC( pLootList->GetLootListContents(), j )
|
||
|
{
|
||
|
const CEconLootListDefinition::drop_item_t& item = pLootList->GetLootListContents()[j];
|
||
|
// 0 and greater means item. Less than 0 means nested lootlist
|
||
|
if( item.m_iItemOrLootlistDef >= 0 )
|
||
|
{
|
||
|
const GameItemDefinition_t* pItemDef = assert_cast<const GameItemDefinition_t *>( GetItemSchema()->GetItemDefinition( item.m_iItemOrLootlistDef ) );
|
||
|
if( pItemDef )
|
||
|
{
|
||
|
return pItemDef->GetQuestDef();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Get the nested lootlist
|
||
|
int iLLIndex = (item.m_iItemOrLootlistDef * -1) - 1;
|
||
|
const CEconLootListDefinition *pNestedLootList = GetItemSchema()->GetLootListByIndex( iLLIndex );
|
||
|
Assert( pNestedLootList );
|
||
|
if ( !pNestedLootList )
|
||
|
continue;
|
||
|
|
||
|
// Dig through all of this lootlist's entries
|
||
|
return DoesLootlistDropQuests( pNestedLootList );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Update what message we show when we have no quests
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::UpdateEmptyMessage()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
CCyclingAdContainerPanel* pPassStoreAd = FindControl< CCyclingAdContainerPanel >( "ItemAd", true );
|
||
|
if ( !pPassStoreAd )
|
||
|
return;
|
||
|
|
||
|
pPassStoreAd->SetVisible( false );
|
||
|
SetDialogVariable( "noquests", "" );
|
||
|
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
// Case 1 above
|
||
|
if ( m_vecQuestItemPanels[ i ]->GetItem() )
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// By default, there's no operations going on, and there's no ad to show
|
||
|
const char *pszNoQuestsText = m_pszNotPossible;
|
||
|
|
||
|
// Find any active quest-dropping operations
|
||
|
const auto& mapOperations = GetItemSchema()->GetOperationDefinitions();
|
||
|
FOR_EACH_MAP_FAST( mapOperations, iOperation )
|
||
|
{
|
||
|
CEconOperationDefinition *pOperation = mapOperations[ iOperation ];
|
||
|
const CSchemaLootListDefHandle pOperationLootlist( pOperation->GetOperationLootlist() );
|
||
|
// Must still be dropping, and be dropping quests
|
||
|
if ( CRTime::RTime32TimeCur() < pOperation->GetStopGivingToPlayerDate() && pOperationLootlist && DoesLootlistDropQuests( pOperationLootlist ) )
|
||
|
{
|
||
|
// If there's a required item and a gateway item
|
||
|
if ( pOperation->GetRequiredItemDefIndex() != INVALID_ITEM_DEF_INDEX && pOperation->GetGatewayItemDefIndex() != INVALID_ITEM_DEF_INDEX )
|
||
|
{
|
||
|
// And the user doesn't have the required item
|
||
|
if ( TFInventoryManager()->GetLocalTFInventory()->FindFirstItembyItemDef( pOperation->GetRequiredItemDefIndex() ) == NULL )
|
||
|
{
|
||
|
// The user needs to get the item
|
||
|
pszNoQuestsText = m_pszNeedAPass;
|
||
|
|
||
|
bool bStoreIsReady = EconUI()->GetStorePanel() && EconUI()->GetStorePanel()->GetPriceSheet() && EconUI()->GetStorePanel()->GetCart() && steamapicontext && steamapicontext->SteamUser();
|
||
|
bool bGatewayItemInStore = false;
|
||
|
// Check if the gateway item is in the Mann Co Store
|
||
|
if ( bStoreIsReady )
|
||
|
{
|
||
|
bGatewayItemInStore = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( pOperation->GetGatewayItemDefIndex() ) != NULL;
|
||
|
}
|
||
|
|
||
|
CEconItemDefinition* pGatewayItemDef = GetItemSchema()->GetItemDefinition( pOperation->GetGatewayItemDefIndex() );
|
||
|
Assert( pGatewayItemDef );
|
||
|
if ( !pGatewayItemDef )
|
||
|
return;
|
||
|
|
||
|
// Cook up KVs for this item ad
|
||
|
KeyValuesAD pKVItemAd( "items" ); // The panel will copy these
|
||
|
KeyValues* pKVItem = pKVItemAd->CreateNewKey();
|
||
|
pKVItem->SetName( "0" );
|
||
|
pKVItem->SetString( "item", pGatewayItemDef->GetDefinitionName() );
|
||
|
pKVItem->SetInt( "show_market", bGatewayItemInStore ? 0 : 1 );
|
||
|
|
||
|
pPassStoreAd->SetVisible( true );
|
||
|
pPassStoreAd->SetItemKVs( pKVItemAd );
|
||
|
|
||
|
// This is the most important thing to communicate. Don't let other operations stomp it.
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pszNoQuestsText = m_pszNoQuests;
|
||
|
// Don't break. Give more important operations a chance to present
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetDialogVariable( "noquests", g_pVGuiLocalize->Find( pszNoQuestsText ) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::PopulateQuestLists()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
// We dont do anything when a quest is completing
|
||
|
if ( m_pCompletingPanel != NULL )
|
||
|
return;
|
||
|
|
||
|
DirtyQuestLayout();
|
||
|
|
||
|
CUtlVector< CEconItemView * > vecQuestItems;
|
||
|
TFInventoryManager()->GetAllQuestItems( &vecQuestItems );
|
||
|
|
||
|
CUtlVector< CQuestItemPanel* > vecAvailablePanels;
|
||
|
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
bool bFound = false;
|
||
|
if ( m_vecQuestItemPanels[ i ]->GetItem() )
|
||
|
{
|
||
|
FOR_EACH_VEC_BACK( vecQuestItems, j )
|
||
|
{
|
||
|
// See if the item in the panel is still in the list of items we own
|
||
|
if ( m_vecQuestItemPanels[ i ]->GetItem()->GetOriginalID() == vecQuestItems[ j ]->GetOriginalID() )
|
||
|
{
|
||
|
// Refresh it
|
||
|
m_vecQuestItemPanels[ i ]->InvalidateLayout();
|
||
|
vecQuestItems.Remove( j );
|
||
|
bFound = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Didn't find it. Clear it out
|
||
|
if ( !bFound )
|
||
|
{
|
||
|
if ( m_vecQuestItemPanels[ i ]->GetItem() )
|
||
|
{
|
||
|
m_vecQuestItemPanels[ i ]->SetItem( NULL );
|
||
|
}
|
||
|
|
||
|
if ( m_vecQuestItemPanels[ i ]->IsSelected() )
|
||
|
{
|
||
|
SetSelected( m_vecQuestItemPanels[ i ], false );
|
||
|
}
|
||
|
|
||
|
vecAvailablePanels.AddToTail( m_vecQuestItemPanels[ i ] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for ( int i = 0 ; i < vecQuestItems.Count(); ++i )
|
||
|
{
|
||
|
CEconItemView *pItem = vecQuestItems[i];
|
||
|
|
||
|
if ( i < vecAvailablePanels.Count() )
|
||
|
{
|
||
|
vecAvailablePanels[ i ]->SetItem( pItem );
|
||
|
}
|
||
|
else if ( i >= m_vecQuestItemPanels.Count() )
|
||
|
{
|
||
|
Assert( !"Ran out of quest panels!" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Sort the panels to make sure they're in order
|
||
|
m_vecQuestItemPanels.Sort( &QuestSort_AcquiredTime );
|
||
|
|
||
|
// Sorting is done manually
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
m_vecQuestItemPanels[ i ]->SetZPos( i + 1 );
|
||
|
}
|
||
|
|
||
|
PositionQuestItemPanels();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CScrollableQuestList::QuestCompletedResponse()
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
m_vecQuestItemPanels[i]->QuestCompletedResponse();
|
||
|
}
|
||
|
|
||
|
// PopulateQuestLists();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Return true if any quest item panels are in the passed in state
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CScrollableQuestList::AnyQuestItemPanelsInState( CQuestItemPanel::EItemPanelState_t eState ) const
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecQuestItemPanels, i )
|
||
|
{
|
||
|
if ( m_vecQuestItemPanels[i]->GetState() == eState )
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CQuestLogPanel::CQuestLogPanel( IViewPort *pViewPort )
|
||
|
: EditablePanel( NULL, PANEL_QUEST_LOG )
|
||
|
, m_bWaitingForComplete( false )
|
||
|
, m_pQuestList( NULL )
|
||
|
, m_bInventoryDirty( true )
|
||
|
, m_iQuestLogKey( BUTTON_CODE_INVALID )
|
||
|
{
|
||
|
if (g_pVGuiLocalize)
|
||
|
{
|
||
|
g_pVGuiLocalize->AddFile( "resource/tf_quests_%language%.txt" );
|
||
|
}
|
||
|
|
||
|
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
|
||
|
SetScheme(scheme);
|
||
|
SetProportional( true );
|
||
|
|
||
|
ListenForGameEvent( "inventory_updated" );
|
||
|
ListenForGameEvent( "gameui_hidden" );
|
||
|
ListenForGameEvent( "gc_connected" );
|
||
|
|
||
|
// Create the item model panel tooltip
|
||
|
m_pMouseOverItemPanel = new CItemModelPanel( this, "mouseoveritempanel" );
|
||
|
m_pMouseOverTooltip = new CItemModelPanelToolTip( this );
|
||
|
m_pMouseOverTooltip->SetupPanels( this, m_pMouseOverItemPanel );
|
||
|
|
||
|
// Create the text tooltip
|
||
|
m_pToolTip = new CQuestTooltip( this );
|
||
|
m_pToolTipEmbeddedPanel = new vgui::EditablePanel( this, "TooltipPanel" );
|
||
|
m_pToolTipEmbeddedPanel->SetKeyBoardInputEnabled( false );
|
||
|
m_pToolTipEmbeddedPanel->SetMouseInputEnabled( false );
|
||
|
// m_pToolTipEmbeddedPanel->MakePopup();
|
||
|
m_pToolTip->SetEmbeddedPanel( m_pToolTipEmbeddedPanel );
|
||
|
m_pToolTip->SetTooltipDelay( 0 );
|
||
|
|
||
|
EditablePanel *pMainContainer = new EditablePanel( this, "MainContainer" );
|
||
|
m_pQuestList = new CScrollableQuestList( pMainContainer, "QuestList" );
|
||
|
|
||
|
m_pProgressPanel = new EditablePanel( this, "ProgressPanel" );
|
||
|
|
||
|
m_pDebugButton = new CExButton( pMainContainer, "Options", "Options", this, "open_debug_menu" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Look into the moused-over panel and take "tiptext" from its dialog
|
||
|
// variables and set it as our own.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestTooltip::ShowTooltip( Panel *pCurrentPanel )
|
||
|
{
|
||
|
EditablePanel* pEditableCurrentPanel = dynamic_cast< EditablePanel* >( pCurrentPanel );
|
||
|
if ( pEditableCurrentPanel )
|
||
|
{
|
||
|
KeyValues* pKVVariables = pEditableCurrentPanel->GetDialogVariables();
|
||
|
const wchar_t *pwszTipText = pKVVariables->GetWString( "tiptext", L"" );
|
||
|
m_pEmbeddedPanel->SetDialogVariable( "tiptext", pwszTipText );
|
||
|
}
|
||
|
|
||
|
BaseClass::ShowTooltip( pCurrentPanel );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Position ourselves down and to the right as far as posible
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestTooltip::PositionWindow( Panel *pTipPanel )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
int iTipW, iTipH;
|
||
|
pTipPanel->GetSize( iTipW, iTipH );
|
||
|
|
||
|
int cursorX, cursorY;
|
||
|
vgui::input()->GetCursorPos(cursorX, cursorY);
|
||
|
|
||
|
int px, py, wide, tall;
|
||
|
ipanel()->GetAbsPos( m_pEmbeddedPanel->GetParent()->GetVPanel(), px, py );
|
||
|
m_pEmbeddedPanel->GetParent()->GetSize(wide, tall);
|
||
|
|
||
|
if ( !m_pEmbeddedPanel->IsPopup() )
|
||
|
{
|
||
|
// Move the cursor into our parent space
|
||
|
cursorX -= px;
|
||
|
cursorY -= py;
|
||
|
}
|
||
|
|
||
|
// Dangle as far down and as far right as possible
|
||
|
int nXPos = cursorX - Max( 0, ( ( iTipW + cursorX ) - wide ) );
|
||
|
int nYPos = ( cursorY + 20 )- Max( 0, ( ( iTipH + cursorY + 20 ) - tall ) ) ;
|
||
|
|
||
|
pTipPanel->SetPos( nXPos, nYPos );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CQuestLogPanel::~CQuestLogPanel()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::AttachToGameUI( void )
|
||
|
{
|
||
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "interface_open", "quest_log_panel" );
|
||
|
|
||
|
if ( GetClientModeTFNormal()->GameUI() )
|
||
|
{
|
||
|
GetClientModeTFNormal()->GameUI()->SetMainMenuOverride( GetVPanel() );
|
||
|
}
|
||
|
|
||
|
SetKeyBoardInputEnabled( true );
|
||
|
SetMouseInputEnabled( true );
|
||
|
SetCursor(dc_arrow);
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const char *CQuestLogPanel::GetName( void )
|
||
|
{
|
||
|
return PANEL_QUEST_LOG;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::ApplySchemeSettings( IScheme *pScheme )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
const char *pszResFile = "Resource/UI/econ/QuestLogPanel.res";
|
||
|
|
||
|
// Check if the operation wants to override our default res file
|
||
|
const auto& mapOperations = GetItemSchema()->GetOperationDefinitions();
|
||
|
FOR_EACH_MAP_FAST( mapOperations, i )
|
||
|
{
|
||
|
CEconOperationDefinition* pOperation = mapOperations[i];
|
||
|
if ( pOperation->IsActive() && pOperation->IsCampaign() )
|
||
|
{
|
||
|
// Use the first found for now
|
||
|
if ( pOperation->GetQuestLogOverrideResFile() )
|
||
|
{
|
||
|
pszResFile = pOperation->GetQuestLogOverrideResFile();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LoadControlSettings( pszResFile );
|
||
|
|
||
|
g_spItemTooltip = m_pMouseOverTooltip;
|
||
|
g_spTextTooltip = m_pToolTip;
|
||
|
|
||
|
// The outer dim / close button
|
||
|
{
|
||
|
Button* pButton = FindControl<Button>( "OutsideCloseButton" );
|
||
|
if ( pButton )
|
||
|
{
|
||
|
pButton->AddActionSignalTarget( this );
|
||
|
pButton->SetPaintBackgroundEnabled( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pQuestList->InvalidateLayout( false, true );
|
||
|
|
||
|
Assert( m_pQuestList );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
if ( GetUniverse() != k_EUniversePublic )
|
||
|
{
|
||
|
int x, y;
|
||
|
m_pDebugButton->GetParent()->GetPos( x, y );
|
||
|
int w, h;
|
||
|
m_pDebugButton->GetParent()->GetSize( w, h );
|
||
|
m_pDebugButton->SizeToContents();
|
||
|
m_pDebugButton->SetVisible( true );
|
||
|
m_pDebugButton->SetPos( x + w - m_pDebugButton->GetWide() - 60, y + 15 );
|
||
|
m_pDebugButton->SetZPos( 1000 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pDebugButton->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
UpdateQuestsItemPanels();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::OnCommand( const char *pCommand )
|
||
|
{
|
||
|
if ( FStrEq( pCommand, "close" ) )
|
||
|
{
|
||
|
if ( enginevgui->IsGameUIVisible() )
|
||
|
{
|
||
|
ShowPanel( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IViewPortPanel *pQuestLog = ( gViewPortInterface->FindPanelByName( PANEL_QUEST_LOG ) );
|
||
|
if ( pQuestLog )
|
||
|
{
|
||
|
gViewPortInterface->ShowPanel( pQuestLog, false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if ( Q_stricmp( "open_debug_menu", pCommand ) == 0 )
|
||
|
{
|
||
|
if ( GetUniverse() == k_EUniverseBeta || GetUniverse() == k_EUniverseDev )
|
||
|
{
|
||
|
const char *pszContextMenuBorder = "NotificationDefault";
|
||
|
const char *pszContextMenuFont = "HudFontMediumSecondary";
|
||
|
|
||
|
Menu *pContextMenu = new Menu( this, "ContextMenu" );
|
||
|
pContextMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
|
||
|
pContextMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
|
||
|
|
||
|
|
||
|
MenuBuilder contextMenuBuilder( pContextMenu, this );
|
||
|
|
||
|
const auto& mapOperations = GetItemSchema()->GetOperationDefinitions();
|
||
|
FOR_EACH_MAP_FAST( mapOperations, iOperation )
|
||
|
{
|
||
|
bool bHasAnyQuests = false;
|
||
|
Menu* pOperationSubMenu = NULL;
|
||
|
|
||
|
CEconOperationDefinition *pOperation = mapOperations[ iOperation ];
|
||
|
const CEconLootListDefinition *pLootListDef = GetItemSchema()->GetLootListByName( pOperation->GetOperationLootlist() );
|
||
|
if ( pLootListDef )
|
||
|
{
|
||
|
auto& vecContents = pLootListDef->GetLootListContents();
|
||
|
FOR_EACH_VEC( vecContents, i )
|
||
|
{
|
||
|
if ( vecContents[i].m_iItemOrLootlistDef > 0 )
|
||
|
{
|
||
|
const GameItemDefinition_t* pItemDef = (GameItemDefinition_t*)GetItemSchema()->GetItemDefinition( vecContents[i].m_iItemOrLootlistDef );
|
||
|
if ( pItemDef && pItemDef->GetQuestDef() )
|
||
|
{
|
||
|
if ( !bHasAnyQuests )
|
||
|
{
|
||
|
bHasAnyQuests = true;
|
||
|
|
||
|
pOperationSubMenu = new Menu( this, "OperationSubMenu" );
|
||
|
pOperationSubMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
|
||
|
pOperationSubMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
|
||
|
|
||
|
contextMenuBuilder.AddCascadingMenuItem( pOperation->GetName(), pOperationSubMenu, "operations" );
|
||
|
}
|
||
|
|
||
|
pOperationSubMenu->AddMenuItem( pItemDef->GetItemBaseName(), CFmtStr( "give%s", pItemDef->GetDefinitionName() ), this );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool bHasAnyQuests = false;
|
||
|
Menu* pAllSubMenu = NULL;
|
||
|
|
||
|
FOR_EACH_MAP_FAST( GetItemSchema()->GetItemDefinitionMap(), i )
|
||
|
{
|
||
|
const GameItemDefinition_t* pItemDef = (GameItemDefinition_t*)GetItemSchema()->GetItemDefinitionMap()[ i ];
|
||
|
if ( pItemDef->GetQuestDef() )
|
||
|
{
|
||
|
if ( !bHasAnyQuests )
|
||
|
{
|
||
|
bHasAnyQuests = true;
|
||
|
|
||
|
pAllSubMenu = new Menu( this, "AllSubMenu" );
|
||
|
pAllSubMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
|
||
|
pAllSubMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
|
||
|
|
||
|
contextMenuBuilder.AddCascadingMenuItem( "all", pAllSubMenu, "all" );
|
||
|
}
|
||
|
|
||
|
pAllSubMenu->AddMenuItem( pItemDef->GetItemBaseName(), CFmtStr( "give%s", pItemDef->GetDefinitionName() ), this );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Position to the cursor's position
|
||
|
int nX, nY;
|
||
|
g_pVGuiInput->GetCursorPosition( nX, nY );
|
||
|
pContextMenu->SetPos( nX - 1, nY - 1 );
|
||
|
|
||
|
pContextMenu->SetVisible(true);
|
||
|
pContextMenu->AddActionSignalTarget(this);
|
||
|
}
|
||
|
}
|
||
|
else if ( Q_strnicmp( "give", pCommand, 4 ) == 0 )
|
||
|
{
|
||
|
if ( GetUniverse() != k_EUniversePublic )
|
||
|
{
|
||
|
if ( !steamapicontext || !steamapicontext->SteamUser() )
|
||
|
{
|
||
|
Msg("Not connected to Steam.\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CSteamID steamIDForPlayer = steamapicontext->SteamUser()->GetSteamID();
|
||
|
if ( !steamIDForPlayer.IsValid() )
|
||
|
{
|
||
|
Msg("Failed to find a valid steamID for the local player.\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const char* pszItemToGive = pCommand + 4;
|
||
|
Msg( "Sending request to generate '%s' for Local Player (%llu)\n", pszItemToGive, steamIDForPlayer.ConvertToUint64() );
|
||
|
|
||
|
CItemSelectionCriteria criteria;
|
||
|
|
||
|
GCSDK::CProtoBufMsg<CMsgDevNewItemRequest> msg( k_EMsgGCDev_NewItemRequest );
|
||
|
msg.Body().set_receiver( steamIDForPlayer.ConvertToUint64() );
|
||
|
|
||
|
criteria.SetIgnoreEnabledFlag( true );
|
||
|
if ( !criteria.BAddCondition( "name", k_EOperator_String_EQ, pszItemToGive, true ) ||
|
||
|
!criteria.BSerializeToMsg( *msg.Body().mutable_criteria() ) )
|
||
|
{
|
||
|
Msg( "Failed to add condition and/or serialize item grant request. This is probably caused by having a string that's too long.\n" );
|
||
|
return;
|
||
|
}
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::FireGameEvent( IGameEvent *event )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
// Listen for inventory updates in case our item gets changed while the user
|
||
|
// is looking at us. We want to re-do our entire layout since a quest might
|
||
|
// have been equipped / destroyed / completed and we need to re-categorize
|
||
|
// all the user's quests.
|
||
|
if ( FStrEq( event->GetName(), "inventory_updated" ) && !m_bWaitingForComplete )
|
||
|
{
|
||
|
m_bInventoryDirty = true;
|
||
|
|
||
|
if ( IsVisible() )
|
||
|
{
|
||
|
if ( m_pQuestList )
|
||
|
{
|
||
|
m_pQuestList->PopulateQuestLists();
|
||
|
m_pQuestList->UpdateEmptyMessage();
|
||
|
}
|
||
|
|
||
|
UpdateQuestsItemPanels();
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( event->GetName(), "gameui_hidden" ) )
|
||
|
{
|
||
|
ShowPanel( false );
|
||
|
return;
|
||
|
}
|
||
|
else if ( FStrEq( event->GetName(), "gc_connected" ) )
|
||
|
{
|
||
|
m_bInventoryDirty = true;
|
||
|
InvalidateLayout( false, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::ShowPanel( bool bShow )
|
||
|
{
|
||
|
// Snag this so we know what to listen for
|
||
|
m_iQuestLogKey = gameuifuncs->GetButtonCodeForBind( "show_quest_log" );
|
||
|
|
||
|
if ( m_pQuestList && bShow )
|
||
|
{
|
||
|
m_pQuestList->SetSelected( NULL, true );
|
||
|
m_pQuestList->DirtyQuestLayout();
|
||
|
}
|
||
|
|
||
|
SetVisible( bShow );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::OnKeyCodePressed( KeyCode code )
|
||
|
{
|
||
|
if ( code == m_iQuestLogKey || code == STEAMCONTROLLER_B )
|
||
|
{
|
||
|
ShowPanel( false );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
BaseClass::OnKeyCodePressed( code );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::OnKeyCodeTyped( KeyCode code )
|
||
|
{
|
||
|
if ( code == KEY_ESCAPE )
|
||
|
{
|
||
|
if ( IsVisible() )
|
||
|
{
|
||
|
SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::SetVisible( bool bState )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
// Default to showing the active quests upon opening
|
||
|
if ( bState == true )
|
||
|
{
|
||
|
UpdateQuestsItemPanels();
|
||
|
|
||
|
IGameEvent *event = gameeventmanager->CreateEvent( "questlog_opened" );
|
||
|
if ( event )
|
||
|
{
|
||
|
gameeventmanager->FireEventClientSide( event );
|
||
|
}
|
||
|
|
||
|
if ( enginevgui->IsGameUIVisible() )
|
||
|
{
|
||
|
AttachToGameUI();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ipanel()->SetParent( GetVPanel(), VGui_GetClientDLLRootPanel() );
|
||
|
|
||
|
MakePopup( false, true );
|
||
|
SetKeyBoardInputEnabled( true );
|
||
|
SetMouseInputEnabled( true );
|
||
|
MoveToFront();
|
||
|
}
|
||
|
|
||
|
engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" );
|
||
|
vgui::surface()->PlaySound( "ui/panel_open.wav" );
|
||
|
}
|
||
|
else if ( IsVisible() )
|
||
|
{
|
||
|
// Detach from the GameUI when we hide
|
||
|
IViewPortPanel *pMMOverride = gViewPortInterface->FindPanelByName( PANEL_MAINMENUOVERRIDE );
|
||
|
if ( pMMOverride )
|
||
|
{
|
||
|
((CHudMainMenuOverride*)pMMOverride)->AttachToGameUI();
|
||
|
}
|
||
|
|
||
|
engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" );
|
||
|
vgui::surface()->PlaySound( "ui/panel_close.wav" );
|
||
|
}
|
||
|
|
||
|
BaseClass::SetVisible( bState );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::QuestCompletedResponse()
|
||
|
{
|
||
|
m_bWaitingForComplete = false;
|
||
|
m_bInventoryDirty = true;
|
||
|
|
||
|
if ( m_pQuestList )
|
||
|
m_pQuestList->QuestCompletedResponse();
|
||
|
|
||
|
//UpdateQuestsItemPanels();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::UpdateQuestsItemPanels()
|
||
|
{
|
||
|
UpdateBadgeProgressPanels();
|
||
|
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
if ( m_bInventoryDirty )
|
||
|
{
|
||
|
m_pQuestList->QuestCompletedResponse();
|
||
|
|
||
|
if ( m_pQuestList )
|
||
|
{
|
||
|
m_pQuestList->PopulateQuestLists();
|
||
|
m_pQuestList->UpdateEmptyMessage();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_bInventoryDirty = false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::MarkQuestsDirty()
|
||
|
{
|
||
|
m_bInventoryDirty = true;
|
||
|
|
||
|
if ( IsVisible() )
|
||
|
{
|
||
|
UpdateQuestsItemPanels();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Return true if any quest item panels are in the passed in state
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CQuestLogPanel::AnyQuestItemPanelsInState( CQuestItemPanel::EItemPanelState_t eState ) const
|
||
|
{
|
||
|
return m_pQuestList->AnyQuestItemPanelsInState( eState );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::OnCompleteQuest( void )
|
||
|
{
|
||
|
m_bWaitingForComplete = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestLogPanel::UpdateBadgeProgressPanels()
|
||
|
{
|
||
|
CEconOperationDefinition *pCurrentOperation = NULL;
|
||
|
const auto& mapOperations = GetItemSchema()->GetOperationDefinitions();
|
||
|
FOR_EACH_MAP_FAST( mapOperations, i )
|
||
|
{
|
||
|
CEconOperationDefinition* pOperation = mapOperations[i];
|
||
|
if ( pOperation->IsActive() && pOperation->IsCampaign() )
|
||
|
{
|
||
|
pCurrentOperation = pOperation;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pCurrentOperation )
|
||
|
{
|
||
|
CEconItemView *pCoin = TFInventoryManager()->GetLocalTFInventory()->FindFirstItembyItemDef( pCurrentOperation->GetRequiredItemDefIndex() );
|
||
|
if ( pCoin )
|
||
|
{
|
||
|
m_pProgressPanel->SetVisible( true );
|
||
|
CItemModelPanel *pCoinPanel = m_pProgressPanel->FindControl< CItemModelPanel >( "CoinModelPanel" );
|
||
|
if ( pCoinPanel )
|
||
|
{
|
||
|
pCoinPanel->SetItem( pCoin );
|
||
|
}
|
||
|
|
||
|
uint32 nNumCompletedContracts = 0;
|
||
|
{
|
||
|
uint32 nCompletedContractsTemp = 0;
|
||
|
GetKilleaterValueByEvent( pCoin, kKillEaterEvent_CosmeticOperationContractsCompleted, nCompletedContractsTemp );
|
||
|
nNumCompletedContracts = Max( nNumCompletedContracts, nCompletedContractsTemp );
|
||
|
// Halloween has it's own thing for whatever reason
|
||
|
GetKilleaterValueByEvent( pCoin, kKillEaterEvent_HalloweenContractsCompleted, nCompletedContractsTemp );
|
||
|
nNumCompletedContracts = Max( nNumCompletedContracts, nCompletedContractsTemp );
|
||
|
Assert( pCurrentOperation->GetMaxDropCount() > 0 );
|
||
|
}
|
||
|
|
||
|
uint32 nNumContractPoints = 0;
|
||
|
{
|
||
|
uint32 nContractsPointsTemp = 0;
|
||
|
GetKilleaterValueByEvent( pCoin, kKillEaterEvent_CosmeticOperationContractsPoints, nContractsPointsTemp );
|
||
|
nNumContractPoints = Max( nContractsPointsTemp, nNumContractPoints );
|
||
|
// Halloween has it's own thing for whatever reason
|
||
|
GetKilleaterValueByEvent( pCoin, kKillEaterEvent_HalloweenSouls, nContractsPointsTemp );
|
||
|
nNumContractPoints = Max( nContractsPointsTemp, nNumContractPoints );
|
||
|
}
|
||
|
|
||
|
EditablePanel *pBadgeContainer = m_pProgressPanel->FindControl< EditablePanel >( "BadgeMeterContainer" );
|
||
|
if ( pBadgeContainer )
|
||
|
{
|
||
|
ContinuousProgressBar *pBadgeProgressBar = pBadgeContainer->FindControl< ContinuousProgressBar >( "BadgeProgressMeter" );
|
||
|
if ( pBadgeProgressBar )
|
||
|
{
|
||
|
const char *pszLevelingDataName = GetItemSchema()->GetKillEaterScoreTypeLevelingDataName( kKillEaterEvent_HalloweenSouls );
|
||
|
Assert( pszLevelingDataName );
|
||
|
|
||
|
const CUtlVector<CItemLevelingDefinition> *pLevelingData = GetItemSchema()->GetItemLevelingData( pszLevelingDataName );
|
||
|
Assert( pLevelingData );
|
||
|
|
||
|
int nRequiredPointsToNextRank = 0;
|
||
|
int nRequiredPointsToCurrentRank = 0;
|
||
|
const char *pszCurrentLevelName = NULL;
|
||
|
FOR_EACH_VEC( (*pLevelingData), i )
|
||
|
{
|
||
|
pszCurrentLevelName = (*pLevelingData)[i].GetNameLocalizationKey();
|
||
|
|
||
|
const uint32 nRank = (*pLevelingData)[i].GetRequiredScore();
|
||
|
if ( nNumContractPoints < nRank )
|
||
|
{
|
||
|
nRequiredPointsToNextRank = nRank;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nRequiredPointsToCurrentRank = nRank;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if no next level, just use max points
|
||
|
if ( nRequiredPointsToNextRank == 0 )
|
||
|
{
|
||
|
// assuming each contract's worth 130 (100 point + 30 bonus)
|
||
|
nRequiredPointsToNextRank = pCurrentOperation->GetMaxDropCount() * 130;
|
||
|
}
|
||
|
|
||
|
float flProgress = (float)( nNumContractPoints - nRequiredPointsToCurrentRank ) / (float)( nRequiredPointsToNextRank - nRequiredPointsToCurrentRank );
|
||
|
pBadgeProgressBar->SetProgress( flProgress );
|
||
|
|
||
|
CExLabel *pLabel = m_pProgressPanel->FindControl< CExLabel >( "BadgeProgressLabel" );
|
||
|
if ( pLabel )
|
||
|
{
|
||
|
pLabel->SetText( CConstructLocalizedString( g_pVGuiLocalize->Find( "QuestLog_BadgeProgress" ), g_pVGuiLocalize->Find( pszCurrentLevelName ) ) );
|
||
|
}
|
||
|
|
||
|
CExLabel *pScoreLabel = pBadgeContainer->FindControl< CExLabel >( "BadgeProgressMeterText" );
|
||
|
if ( pScoreLabel )
|
||
|
{
|
||
|
pScoreLabel->SetText( CFmtStr( "%d/%d", nNumContractPoints, nRequiredPointsToNextRank ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EditablePanel *pContractContainer = m_pProgressPanel->FindControl< EditablePanel >( "ContractMeterContainer" );
|
||
|
if ( pContractContainer )
|
||
|
{
|
||
|
ContinuousProgressBar *pContractProgressBar = pContractContainer->FindControl< ContinuousProgressBar >( "ContractsCompletedProgressMeter" );
|
||
|
if ( pContractProgressBar )
|
||
|
{
|
||
|
pContractProgressBar->SetProgress( (float)nNumCompletedContracts / (float)pCurrentOperation->GetMaxDropCount() );
|
||
|
|
||
|
CExLabel *pLabel = pContractContainer->FindControl< CExLabel >( "ContractsCompletedProgressMeterText" );
|
||
|
if ( pLabel )
|
||
|
{
|
||
|
pLabel->SetText( CFmtStr( "%d", nNumCompletedContracts ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pProgressPanel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pProgressPanel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: GC Msg handler for when a quest has been completed
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CGCCompleteQuestCompleteResponse : public GCSDK::CGCClientJob
|
||
|
{
|
||
|
public:
|
||
|
CGCCompleteQuestCompleteResponse( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
|
||
|
|
||
|
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
|
||
|
{
|
||
|
GCSDK::CGCMsg<MsgGCStandardResponse_t> msg( pNetPacket );
|
||
|
|
||
|
itemid_t nNewToolID = 0;
|
||
|
if( !msg.BReadUint64Data( &nNewToolID ) )
|
||
|
return true;
|
||
|
|
||
|
CQuestLogPanel *pQuestLog = GetQuestLog();
|
||
|
if ( pQuestLog )
|
||
|
{
|
||
|
pQuestLog->QuestCompletedResponse();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
GC_REG_JOB( GCSDK::CGCClient, CGCCompleteQuestCompleteResponse, "CGCCompleteQuestCompleteResponse", k_EMsgGCQuestCompleted, GCSDK::k_EServerTypeGCClient );
|
||
|
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
static void cc_tf_quest_log_reload()
|
||
|
{
|
||
|
CQuestLogPanel *pQuestLog = GetQuestLog();
|
||
|
if ( pQuestLog )
|
||
|
{
|
||
|
pQuestLog->MarkQuestsDirty();
|
||
|
pQuestLog->InvalidateLayout( true, true );
|
||
|
gViewPortInterface->ShowPanel( pQuestLog, true );
|
||
|
}
|
||
|
}
|
||
|
ConCommand tf_quest_log_reload( "tf_quest_log_reload", cc_tf_quest_log_reload );
|
||
|
#endif
|