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.
1626 lines
53 KiB
1626 lines
53 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "quest_item_panel.h"
|
||
|
#include "tf_hud_item_progress_tracker.h"
|
||
|
#include "quest_log_panel.h"
|
||
|
#include "c_tf_player.h"
|
||
|
#include "econ_item_description.h"
|
||
|
#include "clientmode_tf.h"
|
||
|
#include <vgui_controls/AnimationController.h>
|
||
|
#include "quest_objective_manager.h"
|
||
|
#include "econ_quests.h"
|
||
|
#include "confirm_dialog.h"
|
||
|
#include "tf_quest_restriction.h"
|
||
|
#include "item_model_panel.h"
|
||
|
#include "tf_gc_client.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
|
||
|
|
||
|
const float k_flQuestDecodeTime = 2.f;
|
||
|
const float k_flQuestTurnInTime = 5.f;
|
||
|
ConVar tf_quest_turn_in_confirm_opt_out( "tf_quest_turn_in_confirm_opt_out", "0", FCVAR_ARCHIVE, "If nonzero, don't confirm submitting a contract that does not have all of the bonus points" );
|
||
|
|
||
|
extern CQuestLogPanel *GetQuestLog();
|
||
|
extern CQuestTooltip* g_spTextTooltip;
|
||
|
|
||
|
extern const char *s_pszMMTypes[kMatchmakingTypeCount];
|
||
|
extern const char *s_pszGameModes[eNumGameCategories];
|
||
|
|
||
|
void SelectGroup( EMatchmakingGroupType eGroup, bool bSelected );
|
||
|
void SelectCategory( EGameCategory eCategory, bool bSelected );
|
||
|
|
||
|
void PromptOrFireCommand( const char* pszCommand );
|
||
|
|
||
|
static void ConfirmDiscardQuest( bool bConfirmed, void* pContext )
|
||
|
{
|
||
|
CQuestItemPanel *pQuestItemPanel = ( CQuestItemPanel* )pContext;
|
||
|
if ( pQuestItemPanel )
|
||
|
{
|
||
|
pQuestItemPanel->OnConfirmDelete( bConfirmed );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void ConfirmEquipLoaners( bool bConfirmed, void* pContext )
|
||
|
{
|
||
|
CQuestItemPanel *pQuestItemPanel = ( CQuestItemPanel* )pContext;
|
||
|
if ( pQuestItemPanel )
|
||
|
{
|
||
|
pQuestItemPanel->OnConfirmEquipLoaners( bConfirmed );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void ConfirmTurnInQuest( bool bConfirmed, void* pContext )
|
||
|
{
|
||
|
if ( bConfirmed )
|
||
|
{
|
||
|
CQuestItemPanel *pQuestItemPanel = (CQuestItemPanel*)pContext;
|
||
|
if ( pQuestItemPanel )
|
||
|
{
|
||
|
pQuestItemPanel->OnCompleteQuest();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: fill vecLoanerItems with loaners def indices from pQuest
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int GetLoanerListFromQuest( const CEconItemView *pQuest, CUtlVector< item_definition_index_t >& vecLoanerItems )
|
||
|
{
|
||
|
if ( !pQuest )
|
||
|
return 0;
|
||
|
|
||
|
// loaners from the quest
|
||
|
const CUtlVector< CTFRequiredQuestItemsSet >& vecQuestRequiredItems = pQuest->GetItemDefinition()->GetQuestDef()->GetRequiredItemSets();
|
||
|
FOR_EACH_VEC( vecQuestRequiredItems, i )
|
||
|
{
|
||
|
// don't add dups
|
||
|
if ( vecLoanerItems.Find( vecQuestRequiredItems[i].GetLoanerItemDef() ) == vecLoanerItems.InvalidIndex() )
|
||
|
{
|
||
|
vecLoanerItems.AddToTail( vecQuestRequiredItems[i].GetLoanerItemDef() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// loaners from the objectives
|
||
|
//{
|
||
|
// // Get all the objectives
|
||
|
// QuestObjectiveDefVec_t vecChosenObjectives;
|
||
|
// pQuest->GetItemDefinition()->GetQuestDef()->GetRolledObjectivesForItem( vecChosenObjectives, pQuest );
|
||
|
|
||
|
// // Get all the items we need to give as loaners from the objectives
|
||
|
// FOR_EACH_VEC( vecChosenObjectives, i )
|
||
|
// {
|
||
|
// const CUtlVector< CTFRequiredQuestItemsSet >& vecObjectiveRequiredItems = vecChosenObjectives[ i ]->GetConditions()->GetRequiredItemSets();
|
||
|
// FOR_EACH_VEC( vecObjectiveRequiredItems, iRequired )
|
||
|
// {
|
||
|
// // don't add dups
|
||
|
// if ( vecLoanerItems.Find( vecObjectiveRequiredItems[ iRequired ].GetLoanerItemDef() ) == vecLoanerItems.InvalidIndex() )
|
||
|
// {
|
||
|
// vecLoanerItems.AddToTail( vecObjectiveRequiredItems[ iRequired ].GetLoanerItemDef() );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//}
|
||
|
|
||
|
return vecLoanerItems.Count();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: fill vecGrantedLoaners with granted loaners from specific quest ID
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static int GetLoanersFromLocalInventory( const itemid_t& questID, const CUtlVector< item_definition_index_t >& vecLoanerItems, CUtlVector< CEconItemView* >& vecGrantedLoaners )
|
||
|
{
|
||
|
if ( vecLoanerItems.Count() > 0 )
|
||
|
{
|
||
|
CPlayerInventory *pLocalInv = InventoryManager()->GetLocalInventory();
|
||
|
int nCount = pLocalInv->GetItemCount();
|
||
|
for ( int i = 0; i < nCount; ++i )
|
||
|
{
|
||
|
CEconItemView* pItem = pLocalInv->GetItem( i );
|
||
|
|
||
|
bool bIsLoaner = false;
|
||
|
// check if the item is a loaner and is associated with this quest
|
||
|
FOR_EACH_VEC( vecLoanerItems, iLoaner )
|
||
|
{
|
||
|
if ( vecLoanerItems[iLoaner] == pItem->GetItemDefIndex() && GetAssociatedQuestItemID( pItem ) == questID )
|
||
|
{
|
||
|
bIsLoaner = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// already granted this loaner, remove from the list to give
|
||
|
if ( bIsLoaner )
|
||
|
{
|
||
|
vecGrantedLoaners.AddToTail( pItem );
|
||
|
}
|
||
|
|
||
|
// found all given loaners
|
||
|
if ( vecLoanerItems.Count() == vecGrantedLoaners.Count() )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return vecGrantedLoaners.Count();
|
||
|
}
|
||
|
|
||
|
|
||
|
DECLARE_BUILD_FACTORY( CInputProxyPanel )
|
||
|
CInputProxyPanel::CInputProxyPanel( Panel *parent, const char *pszPanelName )
|
||
|
: BaseClass( parent, pszPanelName )
|
||
|
{}
|
||
|
|
||
|
void CInputProxyPanel::AddPanelForCommand( EInputTypes eInputType, Panel* pPanel, const char* pszCommand )
|
||
|
{
|
||
|
m_vecRedirectPanels[ eInputType ].AddToTail( { pPanel, pszCommand } );
|
||
|
}
|
||
|
|
||
|
void CInputProxyPanel::OnCursorMoved( int x, int y )
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecRedirectPanels[ INPUT_MOUSE_MOVE ], i )
|
||
|
{
|
||
|
PostMessage( m_vecRedirectPanels[ INPUT_MOUSE_MOVE ][ i ].m_pPanel, new KeyValues( m_vecRedirectPanels[ INPUT_MOUSE_MOVE ][ i ].m_pszCommand, "x", x, "y", y ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInputProxyPanel::OnCursorEntered()
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecRedirectPanels[ INPUT_MOUSE_ENTER ], i )
|
||
|
{
|
||
|
PostMessage( m_vecRedirectPanels[ INPUT_MOUSE_ENTER ][ i ].m_pPanel, new KeyValues( m_vecRedirectPanels[ INPUT_MOUSE_ENTER ][ i ].m_pszCommand ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInputProxyPanel::OnCursorExited()
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecRedirectPanels[ INPUT_MOUSE_EXIT ], i )
|
||
|
{
|
||
|
PostMessage( m_vecRedirectPanels[ INPUT_MOUSE_EXIT ][ i ].m_pPanel, new KeyValues( m_vecRedirectPanels[ INPUT_MOUSE_EXIT ][ i ].m_pszCommand ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInputProxyPanel::OnMousePressed(MouseCode code)
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecRedirectPanels[ INPUT_MOUSE_PRESS ], i )
|
||
|
{
|
||
|
PostMessage( m_vecRedirectPanels[ INPUT_MOUSE_PRESS ][ i ].m_pPanel, new KeyValues( m_vecRedirectPanels[ INPUT_MOUSE_PRESS ][ i ].m_pszCommand, "code", code ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInputProxyPanel::OnMouseDoublePressed(MouseCode code)
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecRedirectPanels[ INPUT_MOUSE_DOUBLE_PRESS ], i )
|
||
|
{
|
||
|
PostMessage( m_vecRedirectPanels[ INPUT_MOUSE_DOUBLE_PRESS ][ i ].m_pPanel, new KeyValues( m_vecRedirectPanels[ INPUT_MOUSE_DOUBLE_PRESS ][ i ].m_pszCommand, "code", code ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInputProxyPanel::OnMouseReleased(MouseCode code)
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecRedirectPanels[ INPUT_MOUSE_RELEASED ], i )
|
||
|
{
|
||
|
PostMessage( m_vecRedirectPanels[ INPUT_MOUSE_RELEASED ][ i ].m_pPanel, new KeyValues( m_vecRedirectPanels[ INPUT_MOUSE_RELEASED ][ i ].m_pszCommand, "code", code ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CInputProxyPanel::OnMouseWheeled(int delta)
|
||
|
{
|
||
|
FOR_EACH_VEC( m_vecRedirectPanels[ INPUT_MOUSE_WHEEL ], i )
|
||
|
{
|
||
|
PostMessage( m_vecRedirectPanels[ INPUT_MOUSE_WHEEL ][ i ].m_pPanel, new KeyValues( m_vecRedirectPanels[ INPUT_MOUSE_WHEEL ][ i ].m_pszCommand, "delta", delta ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
DECLARE_BUILD_FACTORY( CQuestStatusPanel )
|
||
|
|
||
|
CQuestStatusPanel::CQuestStatusPanel( Panel *parent, const char *pszPanelName )
|
||
|
: EditablePanel( parent, pszPanelName )
|
||
|
, m_pMovingContainer( NULL )
|
||
|
, m_bShouldBeVisible( false )
|
||
|
{
|
||
|
m_pMovingContainer = new EditablePanel( this, "movingcontainer" );
|
||
|
m_transitionTimer.Invalidate();
|
||
|
}
|
||
|
|
||
|
void CQuestStatusPanel::SetShow( bool bShow )
|
||
|
{
|
||
|
if ( bShow != m_bShouldBeVisible )
|
||
|
{
|
||
|
m_transitionTimer.Start( 0.6f );
|
||
|
}
|
||
|
m_bShouldBeVisible = bShow;
|
||
|
SetVisible( m_bShouldBeVisible );
|
||
|
}
|
||
|
|
||
|
void CQuestStatusPanel::OnThink()
|
||
|
{
|
||
|
BaseClass::OnThink();
|
||
|
|
||
|
const int nStartY = m_bShouldBeVisible ? m_iHiddenY : m_iVisibleY;
|
||
|
const int nEndY = m_bShouldBeVisible ? m_iVisibleY : m_iHiddenY;
|
||
|
|
||
|
float flProgress = 1.f;
|
||
|
if ( !m_transitionTimer.IsElapsed() )
|
||
|
{
|
||
|
flProgress = Bias( RemapValClamped( m_transitionTimer.GetElapsedTime(), 0.f , m_transitionTimer.GetCountdownDuration(), 0.f, 1.f ), 0.7f );
|
||
|
}
|
||
|
flProgress = RemapVal( flProgress, 0.f, 1.f, (float)nStartY, (float)nEndY );
|
||
|
|
||
|
m_pMovingContainer->SetPos( m_pMovingContainer->GetXPos(), flProgress );
|
||
|
SetVisible( m_bShouldBeVisible || flProgress > 0.f );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CQuestItemPanel::CQuestItemPanel( Panel *parent, const char *pszPanelName, CEconItemView* pQuestItem, CScrollableQuestList* pQuestList )
|
||
|
: EditablePanel( parent, pszPanelName )
|
||
|
, m_hQuestItem( NULL )
|
||
|
, m_eState( STATE_NORMAL )
|
||
|
, m_pTurnInContainer( NULL )
|
||
|
, m_pTurnInDimmer( NULL )
|
||
|
, m_pszCompleteSound( NULL )
|
||
|
, m_pFrontFolderContainer( NULL )
|
||
|
, m_pBackFolderContainer( NULL )
|
||
|
, m_bCollapsed( true )
|
||
|
, m_pQuestList( pQuestList )
|
||
|
, m_pQuestPaperContainer( NULL )
|
||
|
, m_pTitleButton( NULL )
|
||
|
, m_pIdentifyContainer( NULL )
|
||
|
, m_pIdentifyDimmer( NULL )
|
||
|
, m_pKVCipherStrings( NULL )
|
||
|
, m_pPhotoStatic( NULL )
|
||
|
, m_pFlavorScrollingContainer( NULL )
|
||
|
, m_pTurningInLabel( NULL )
|
||
|
, m_pFindServerButton( NULL )
|
||
|
, m_pLoanerContainerPanel( NULL )
|
||
|
, m_pRequestLoanerItemsButton( NULL )
|
||
|
, m_pEquipLoanerItemsButton( NULL )
|
||
|
, m_pItemTrackerPanel( NULL )
|
||
|
, m_pKVItemTracker( NULL )
|
||
|
, m_pObjectiveExplanationLabel( NULL )
|
||
|
, m_pEncodedStatus( NULL )
|
||
|
, m_pInactiveStatus( NULL )
|
||
|
, m_pReadyToTurnInStatus( NULL )
|
||
|
, m_pExpirationLabel( NULL )
|
||
|
, m_pTurnInButton( NULL )
|
||
|
, m_bHasAllControls( false )
|
||
|
, m_pDiscardButton( NULL )
|
||
|
{
|
||
|
SetItem( pQuestItem );
|
||
|
m_StateTimer.Invalidate();
|
||
|
|
||
|
ListenForGameEvent( "quest_objective_completed" );
|
||
|
ListenForGameEvent( "player_spawn" );
|
||
|
ListenForGameEvent( "client_disconnect" );
|
||
|
ListenForGameEvent( "inventory_updated" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CQuestItemPanel::~CQuestItemPanel()
|
||
|
{
|
||
|
if ( m_pItemTrackerPanel )
|
||
|
{
|
||
|
m_pItemTrackerPanel->MarkForDeletion();
|
||
|
m_pItemTrackerPanel = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::ApplySchemeSettings( IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings ( pScheme );
|
||
|
AddActionSignalTarget( GetQuestLog() );
|
||
|
LoadResFileForCurrentItem();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::LoadResFileForCurrentItem()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
const char *pszResFile = "Resource/UI/quests/QuestItemPanel_Base.res";
|
||
|
|
||
|
if ( m_hQuestItem )
|
||
|
{
|
||
|
const GameItemDefinition_t *pItemDef = m_hQuestItem->GetItemDefinition();
|
||
|
// Get our quest theme
|
||
|
const CQuestThemeDefinition *pTheme = pItemDef->GetQuestDef()->GetQuestTheme();
|
||
|
if ( pTheme )
|
||
|
{
|
||
|
pszResFile = pTheme->GetQuestItemResFile();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
KeyValues *pConditions = new KeyValues( "conditions" );
|
||
|
if ( pConditions )
|
||
|
{
|
||
|
char uilanguage[64];
|
||
|
uilanguage[0] = 0;
|
||
|
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) );
|
||
|
char szCondition[64];
|
||
|
Q_snprintf( szCondition, sizeof( szCondition ), "if_%s", uilanguage );
|
||
|
AddSubKeyNamed( pConditions, szCondition );
|
||
|
}
|
||
|
|
||
|
SetMouseInputEnabled( true ); // Slam this to true. When panels get created, they'll inherit their parents' mouse enabled state
|
||
|
// and if we've been fiddling with it, we might accidently create all child panels with mouse input disabled.
|
||
|
// Setting this to true just before the controls are made gives them a chance to be mouse enabled if they want.
|
||
|
LoadControlSettings( pszResFile, NULL, NULL, pConditions );
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, m_strReset );
|
||
|
|
||
|
m_pMainContainer = FindControl<EditablePanel>( "MainContainer" );
|
||
|
if ( m_pMainContainer )
|
||
|
{
|
||
|
m_pMainContainer->AddActionSignalTarget( this );
|
||
|
}
|
||
|
|
||
|
m_pQuestPaperContainer = FindControl<EditablePanel>( "QuestPaperContainer", true );
|
||
|
m_pFrontFolderContainer = FindControl<EditablePanel>( "FrontFolderContainer", true );
|
||
|
Assert( m_pFrontFolderContainer );
|
||
|
if ( m_pFrontFolderContainer )
|
||
|
{
|
||
|
m_pFrontFolderImage = m_pFrontFolderContainer->FindControl<ImagePanel>( "FrontFolderImage", true );
|
||
|
Assert( m_pFrontFolderImage );
|
||
|
|
||
|
m_pEncodedStatus = m_pFrontFolderContainer->FindControl< CQuestStatusPanel >( "EncodedStatus", true );
|
||
|
m_pInactiveStatus = m_pFrontFolderContainer->FindControl< CQuestStatusPanel >( "InactiveStatus", true );
|
||
|
m_pReadyToTurnInStatus = m_pFrontFolderContainer->FindControl< CQuestStatusPanel >( "ReadyToTurnInStatus", true );
|
||
|
}
|
||
|
m_pBackFolderContainer = FindControl<EditablePanel>( "BackFolderContainer", true );
|
||
|
Assert( m_pBackFolderContainer );
|
||
|
if ( m_pBackFolderContainer )
|
||
|
{
|
||
|
m_pBackFolderImage = m_pBackFolderContainer->FindControl<ImagePanel>( "BackFolderImage", true );
|
||
|
Assert( m_pBackFolderImage );
|
||
|
}
|
||
|
|
||
|
if ( m_pQuestPaperContainer )
|
||
|
{
|
||
|
#if defined( STAGING_ONLY ) || defined( DEBUG )
|
||
|
// don't do this in public
|
||
|
m_pDiscardButton = new CExButton( m_pQuestPaperContainer, "Discard", "Discard", this, "discard_quest" );
|
||
|
m_pDiscardButton->SetEnabled( true );
|
||
|
m_pDiscardButton->SizeToContents();
|
||
|
m_pDiscardButton->SetZPos( 101 );
|
||
|
m_pDiscardButton->SetPos( 70, 40 );
|
||
|
m_pDiscardButton->SetVisible( false );
|
||
|
#endif // STAGING_ONLY || DEBUG
|
||
|
|
||
|
m_pFindServerButton = m_pQuestPaperContainer->FindControl< CExButton >( "FindServerButton", true );
|
||
|
|
||
|
m_pLoanerContainerPanel = m_pQuestPaperContainer->FindControl< EditablePanel >( "LoanerContainerPanel", true );
|
||
|
if ( m_pLoanerContainerPanel )
|
||
|
{
|
||
|
m_pRequestLoanerItemsButton = m_pLoanerContainerPanel->FindControl< CExButton >( "RequestLoanerItemsButton", true );
|
||
|
m_pEquipLoanerItemsButton = m_pLoanerContainerPanel->FindControl< CExButton >( "EquipLoanerItemsButton", true );
|
||
|
for ( int i = 0; i < ARRAYSIZE( m_pLoanerItemModelPanel ); ++i )
|
||
|
{
|
||
|
m_pLoanerItemModelPanel[i] = m_pLoanerContainerPanel->FindControl< CItemModelPanel >( CFmtStr( "Loaner%dItemModelPanel", i + 1 ), true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pTitleButton = m_pQuestPaperContainer->FindControl<CExButton>( "TitleButton", true );
|
||
|
m_pIdentifyContainer = m_pQuestPaperContainer->FindControl<EditablePanel>( "IdentifyButtonContainer", true );
|
||
|
if ( m_pIdentifyContainer )
|
||
|
{
|
||
|
m_pIdentifyDimmer = m_pIdentifyContainer->FindControl<EditablePanel>( "Dimmer", true );
|
||
|
m_pIdentifyButton = m_pIdentifyContainer->FindControl<CExButton>( "IdentifyButton", true );
|
||
|
}
|
||
|
Assert( m_pIdentifyContainer );
|
||
|
|
||
|
m_pEncodedImage = m_pQuestPaperContainer->FindControl<ImagePanel>( "EncodedImage", true );
|
||
|
|
||
|
m_pPhotoStatic = m_pQuestPaperContainer->FindControl<ImagePanel>( "StaticPhoto", true );
|
||
|
Assert( m_pPhotoStatic );
|
||
|
|
||
|
m_pFlavorScrollingContainer = m_pQuestPaperContainer->FindControl<CExScrollingEditablePanel>( "ScrollableBottomContainer", true );
|
||
|
Assert( m_pFlavorScrollingContainer );
|
||
|
|
||
|
if ( m_pFlavorScrollingContainer )
|
||
|
{
|
||
|
m_pObjectiveExplanationLabel = m_pFlavorScrollingContainer->FindControl< Label >( "QuestObjectiveExplanation", true );
|
||
|
}
|
||
|
|
||
|
CInputProxyPanel* pInputProxy = m_pQuestPaperContainer->FindControl< CInputProxyPanel >( "PaperInputProxyPanel", true );
|
||
|
if ( pInputProxy )
|
||
|
{
|
||
|
// Make the scroller scroll
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_WHEEL, m_pFlavorScrollingContainer, "MouseWheeled" );
|
||
|
|
||
|
// Make the title glow
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_ENTER, m_pTitleButton, "CursorEntered" );
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_EXIT, m_pTitleButton, "CursorExited" );
|
||
|
|
||
|
// Capture clicks to expand/contract
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_RELEASED, this, "MouseReleased" );
|
||
|
}
|
||
|
|
||
|
m_pTurnInContainer = m_pQuestPaperContainer->FindControl< EditablePanel >( "TurnInContainer" );
|
||
|
Assert( m_pTurnInContainer );
|
||
|
if ( m_pTurnInContainer )
|
||
|
{
|
||
|
m_pTurnInDimmer = m_pTurnInContainer->FindControl< EditablePanel >( "Dimmer", true );
|
||
|
Assert( m_pTurnInContainer );
|
||
|
|
||
|
m_pTurnInButton = m_pTurnInContainer->FindControl< Button >( "TurnInButton", true );
|
||
|
Assert( m_pTurnInButton );
|
||
|
|
||
|
m_pTurnInSpinnerContainer = m_pTurnInContainer->FindControl< EditablePanel>( "TurnInSpinnerContainer", true );
|
||
|
Assert( m_pTurnInSpinnerContainer );
|
||
|
|
||
|
if ( m_pTurnInSpinnerContainer )
|
||
|
{
|
||
|
m_pTurningInLabel = m_pTurnInSpinnerContainer->FindControl< Label >( "TurningInLabel", true );
|
||
|
Assert( m_pTurningInLabel );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pAcceptedImage = m_pQuestPaperContainer->FindControl< ImagePanel >( "AcceptedImage", true );
|
||
|
Assert( m_pAcceptedImage );
|
||
|
}
|
||
|
|
||
|
if ( m_pFrontFolderContainer )
|
||
|
{
|
||
|
CInputProxyPanel* pInputProxy = m_pFrontFolderContainer->FindControl< CInputProxyPanel >( "FrontInputProxyPanel", true );
|
||
|
if ( pInputProxy )
|
||
|
{
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_ENTER, m_pInactiveStatus, "CursorEntered" );
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_EXIT, m_pInactiveStatus, "CursorExited" );
|
||
|
|
||
|
// Make the title glow
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_ENTER, m_pTitleButton, "CursorEntered" );
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_EXIT, m_pTitleButton, "CursorExited" );
|
||
|
|
||
|
// Make the backdrop highlight
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_ENTER, this, "CollapsedGlowStart" );
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_EXIT, this, "CollapsedGlowEnd" );
|
||
|
|
||
|
// Capture clicks to expand/contract
|
||
|
pInputProxy->AddPanelForCommand( CInputProxyPanel::INPUT_MOUSE_RELEASED, this, "MouseReleased" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pExpirationLabel = FindControl<Label>( "QuestExpirationWarning", true );
|
||
|
m_pFlavorText = FindControl<Label>( "QuestFlavorText", true );
|
||
|
|
||
|
SetupObjectivesPanels( true );
|
||
|
|
||
|
if ( pConditions )
|
||
|
{
|
||
|
pConditions->deleteThis();
|
||
|
}
|
||
|
|
||
|
m_bHasAllControls = m_pQuestPaperContainer
|
||
|
&& m_pFrontFolderContainer
|
||
|
&& m_pFrontFolderImage
|
||
|
&& m_pBackFolderContainer
|
||
|
&& m_pBackFolderImage
|
||
|
&& m_pEncodedStatus
|
||
|
&& m_pInactiveStatus
|
||
|
&& m_pReadyToTurnInStatus
|
||
|
&& m_pFlavorText
|
||
|
&& m_pObjectiveExplanationLabel
|
||
|
&& m_pExpirationLabel
|
||
|
&& m_pTurnInContainer
|
||
|
&& m_pTurnInDimmer
|
||
|
&& m_pTurnInButton
|
||
|
&& m_pIdentifyButton
|
||
|
&& m_pTurnInSpinnerContainer
|
||
|
&& m_pTitleButton
|
||
|
&& m_pIdentifyDimmer
|
||
|
&& m_pIdentifyContainer
|
||
|
&& m_pPhotoStatic
|
||
|
&& m_pAcceptedImage
|
||
|
&& m_pTurningInLabel
|
||
|
&& m_pFlavorScrollingContainer
|
||
|
&& m_pItemTrackerPanel
|
||
|
&& m_pEncodedImage
|
||
|
&& m_pMainContainer;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
if ( m_hQuestItem )
|
||
|
{
|
||
|
m_vecFoldersImages.Purge();
|
||
|
KeyValues *pKVFoldersBlock = inResourceData->FindKey( "folders" );
|
||
|
Assert( pKVFoldersBlock );
|
||
|
if ( pKVFoldersBlock )
|
||
|
{
|
||
|
FOR_EACH_TRUE_SUBKEY( pKVFoldersBlock, pKVFolder )
|
||
|
{
|
||
|
auto& folder = m_vecFoldersImages[ m_vecFoldersImages.AddToTail() ];
|
||
|
folder.m_strFront = pKVFolder->GetString( "front", NULL);
|
||
|
folder.m_strBack = pKVFolder->GetString( "back", NULL );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const GameItemDefinition_t *pItemDef = m_hQuestItem->GetItemDefinition();
|
||
|
// Get our quest theme
|
||
|
const CQuestThemeDefinition *pTheme = pItemDef->GetQuestDef()->GetQuestTheme();
|
||
|
if ( pTheme )
|
||
|
{
|
||
|
Warning( "%s %s is missing 'folders' data\n", pItemDef->GetQuestDef()->GetCorrespondingOperationName(), pTheme->GetQuestItemResFile() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( 1/*m_pKVItemTracker == NULL*/ )
|
||
|
{
|
||
|
KeyValues *pTrackerKV = inResourceData->FindKey( "tracker_kv" );
|
||
|
|
||
|
if ( pTrackerKV )
|
||
|
{
|
||
|
m_pKVItemTracker = pTrackerKV->MakeCopy();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_strEncodedText = inResourceData->GetString( "encoded_text", NULL );
|
||
|
m_strExpireText = inResourceData->GetString( "expire_text", NULL );
|
||
|
m_strItemTrackerResFile = inResourceData->GetString( "TrackerPanelResFile", NULL );
|
||
|
// Sound effects
|
||
|
m_strTurnInSound = inResourceData->GetString( "turn_in_sound", NULL );
|
||
|
m_strTurnInSuccessSound = inResourceData->GetString( "turn_in_success_sound", NULL );
|
||
|
m_strDecodeSound = inResourceData->GetString( "decode_sound", NULL );
|
||
|
m_strExpandSound = inResourceData->GetString( "expand_sound", NULL );
|
||
|
m_strCollapseSound = inResourceData->GetString( "collapse_sound", NULL );
|
||
|
|
||
|
// Animations
|
||
|
m_strReset = inResourceData->GetString( "anim_reset", NULL );
|
||
|
m_strAnimExpand = inResourceData->GetString( "anim_expand", NULL );
|
||
|
m_strAnimCollapse = inResourceData->GetString( "anim_collapse", NULL );
|
||
|
m_strTurningIn = inResourceData->GetString( "anim_turning_in", NULL );
|
||
|
m_strHighlightOn = inResourceData->GetString( "anim_highlight_on", NULL );
|
||
|
m_strHighlightOff = inResourceData->GetString( "anim_highlight_off", NULL );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::PerformLayout( void )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
if ( !HasAllControls() )
|
||
|
return;
|
||
|
|
||
|
m_pIdentifyContainer->SetVisible( m_eState == STATE_UNIDENTIFIED );
|
||
|
m_pTurnInContainer->SetVisible( m_eState == STATE_COMPLETED || m_eState == STATE_TURNING_IN__GC_RESPONDED || m_eState == STATE_TURNING_IN__WAITING_FOR_GC);
|
||
|
m_pTurnInButton->SetVisible( m_eState == STATE_COMPLETED );
|
||
|
m_pTurnInSpinnerContainer->SetVisible( m_eState == STATE_TURNING_IN__GC_RESPONDED || m_eState == STATE_TURNING_IN__WAITING_FOR_GC );
|
||
|
m_pPhotoStatic->SetVisible( m_eState == STATE_UNIDENTIFIED || m_eState == STATE_IDENTIFYING );
|
||
|
m_pFindServerButton->SetVisible( m_eState == STATE_NORMAL );
|
||
|
|
||
|
// only exist in non public build
|
||
|
if ( m_pDiscardButton )
|
||
|
{
|
||
|
m_pDiscardButton->SetVisible( m_eState == STATE_NORMAL );
|
||
|
}
|
||
|
|
||
|
// loaners
|
||
|
if ( m_eState == STATE_NORMAL || m_eState == STATE_COMPLETED )
|
||
|
{
|
||
|
// get all loaners required from quest
|
||
|
CUtlVector< item_definition_index_t > vecLoanerItems;
|
||
|
bool bRequiredLoaners = GetLoanerListFromQuest( m_hQuestItem, vecLoanerItems ) > 0;
|
||
|
|
||
|
// get all granted loaners from this quest
|
||
|
CUtlVector< CEconItemView* > vecGrantedLoaners;
|
||
|
if ( bRequiredLoaners )
|
||
|
{
|
||
|
GetLoanersFromLocalInventory( m_hQuestItem->GetItemID(), vecLoanerItems, vecGrantedLoaners );
|
||
|
}
|
||
|
|
||
|
if ( bRequiredLoaners )
|
||
|
{
|
||
|
m_pLoanerContainerPanel->SetVisible( true );
|
||
|
bool bAllGranted = vecLoanerItems.Count() == vecGrantedLoaners.Count();
|
||
|
m_pRequestLoanerItemsButton->SetVisible( !bAllGranted );
|
||
|
m_pEquipLoanerItemsButton->SetVisible( bAllGranted );
|
||
|
|
||
|
for ( int i = 0; i < ARRAYSIZE( m_pLoanerItemModelPanel ); ++i )
|
||
|
{
|
||
|
// try to use the granted items first
|
||
|
if ( i < vecGrantedLoaners.Count() )
|
||
|
{
|
||
|
m_pLoanerItemModelPanel[i]->SetItem( vecGrantedLoaners[i] );
|
||
|
m_pLoanerItemModelPanel[i]->SetVisible( true );
|
||
|
}
|
||
|
// In case we don't get all the loaner items, use fake items as second option
|
||
|
else if ( i < vecLoanerItems.Count() )
|
||
|
{
|
||
|
CEconItemView tempItem;
|
||
|
tempItem.Init( vecLoanerItems[i], AE_UNIQUE, AE_USE_SCRIPT_VALUE, true );
|
||
|
|
||
|
m_pLoanerItemModelPanel[i]->SetItem( &tempItem );
|
||
|
m_pLoanerItemModelPanel[i]->SetVisible( true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pLoanerItemModelPanel[i]->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pLoanerContainerPanel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pLoanerContainerPanel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
m_pEncodedStatus->SetShow( m_eState == STATE_UNIDENTIFIED );
|
||
|
m_pReadyToTurnInStatus->SetShow( m_eState == STATE_COMPLETED || m_eState == STATE_TURNING_IN__GC_RESPONDED || m_eState == STATE_TURNING_IN__WAITING_FOR_GC );
|
||
|
|
||
|
float flDecodeAmount = 1.f;
|
||
|
// Only cypher-style decoding needs to decode
|
||
|
if ( m_eDecodeStyle == DECODE_STYLE_CYPHER && m_eState == STATE_UNIDENTIFIED )
|
||
|
{
|
||
|
flDecodeAmount = 0.f;
|
||
|
}
|
||
|
|
||
|
m_pEncodedImage->SetAlpha( m_eState == STATE_UNIDENTIFIED ? 255 : 0 );
|
||
|
|
||
|
if ( m_hQuestItem )
|
||
|
{
|
||
|
m_pTitleButton->SetText( GetDecodedString( "name", flDecodeAmount ) );
|
||
|
|
||
|
int nScrollableYOffset = 0;
|
||
|
// Check if the quest is going to expire soon (within a week). If so, show a "This is going to be destroyed" message.
|
||
|
const CRTime nExpirationTime = m_hQuestItem->GetExpirationDate();
|
||
|
const CRTime nOneWeekFromNow = CRTime::RTime32DateAdd( CRTime::RTime32TimeCur(), 1, k_ETimeUnitWeek );
|
||
|
const bool bExpiringSoon = nExpirationTime.GetRTime32() != RTime32(0) && nExpirationTime < nOneWeekFromNow;
|
||
|
m_pExpirationLabel->SetVisible( bExpiringSoon );
|
||
|
if ( bExpiringSoon )
|
||
|
{
|
||
|
CLocalizedRTime32 locTime = { nExpirationTime.GetRTime32(), false, GLocalizationProvider(), NULL };
|
||
|
m_pExpirationLabel->SetText( CConstructLocalizedString( g_pVGuiLocalize->Find( m_strExpireText ), locTime ) );
|
||
|
m_pExpirationLabel->InvalidateLayout( true );
|
||
|
m_pExpirationLabel->SizeToContents();
|
||
|
nScrollableYOffset += m_pExpirationLabel->GetTall();
|
||
|
}
|
||
|
|
||
|
m_pObjectiveExplanationLabel->SetPos( 0, nScrollableYOffset );
|
||
|
m_pObjectiveExplanationLabel->SetText( GetDecodedString( "explanation", flDecodeAmount ) );
|
||
|
m_pObjectiveExplanationLabel->InvalidateLayout( true ); // So we get the right height when we do SizeToContents below
|
||
|
m_pObjectiveExplanationLabel->SizeToContents();
|
||
|
nScrollableYOffset += m_pObjectiveExplanationLabel->GetTall();
|
||
|
|
||
|
m_pFlavorText->SetText( GetDecodedString( "desc", flDecodeAmount ) );
|
||
|
int nWide, nTall;
|
||
|
m_pFlavorText->GetTextImage()->GetContentSize( nWide, nTall );
|
||
|
m_pFlavorText->SetTall( nTall + 20 );
|
||
|
|
||
|
m_pItemTrackerPanel->SetPos( m_pItemTrackerPanel->GetXPos(), nScrollableYOffset );
|
||
|
nScrollableYOffset += m_pItemTrackerPanel->GetTall();
|
||
|
|
||
|
// Put the flavor text below the obectives
|
||
|
m_pFlavorText->SetPos( m_pFlavorText->GetXPos(), nScrollableYOffset );
|
||
|
|
||
|
m_pFlavorScrollingContainer->InvalidateLayout( true );
|
||
|
m_pFlavorScrollingContainer->InvalidateLayout();
|
||
|
m_pFlavorScrollingContainer->ResetScrollAmount();
|
||
|
|
||
|
|
||
|
// Randomize our folder images based on original ID
|
||
|
if ( m_vecFoldersImages.Count() )
|
||
|
{
|
||
|
RandomSeed( m_hQuestItem->GetSOCData() ? m_hQuestItem->GetSOCData()->GetOriginalID() : m_hQuestItem->GetItemDefIndex() );
|
||
|
int idx = RandomInt( 0, m_vecFoldersImages.Count() - 1 );
|
||
|
|
||
|
m_pFrontFolderImage->SetImage( m_vecFoldersImages[ idx ].m_strFront );
|
||
|
m_pBackFolderImage->SetImage( m_vecFoldersImages[ idx ].m_strBack );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UpdateInvalidReasons();
|
||
|
|
||
|
if ( m_pItemTrackerPanel )
|
||
|
{
|
||
|
auto& vecObjectives = m_pItemTrackerPanel->GetAttributePanels();
|
||
|
FOR_EACH_VEC( vecObjectives, i )
|
||
|
{
|
||
|
// Only do this when unidentified. The panel updates its own string, and we don't want to stomp it
|
||
|
if ( m_eState == STATE_UNIDENTIFIED )
|
||
|
{
|
||
|
const wchar_t *pszString = GetDecodedString( CFmtStr( "objective%d", i ), flDecodeAmount );
|
||
|
vecObjectives[ i ]->SetDialogVariable( "attr_desc", pszString );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CQuestItemPanel::IsCursorOverMainContainer() const
|
||
|
{
|
||
|
return m_pMainContainer ? m_pMainContainer->IsCursorOver() : false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::SetupObjectivesPanels( bool bRecreate )
|
||
|
{
|
||
|
if ( m_pItemTrackerPanel && bRecreate )
|
||
|
{
|
||
|
m_pItemTrackerPanel->MarkForDeletion();
|
||
|
m_pItemTrackerPanel = NULL;
|
||
|
}
|
||
|
|
||
|
if ( !m_hQuestItem )
|
||
|
return;
|
||
|
|
||
|
if ( !m_pItemTrackerPanel )
|
||
|
{
|
||
|
m_pItemTrackerPanel = new CItemTrackerPanel( m_pFlavorScrollingContainer, "ItemTrackerPanel", m_hQuestItem->GetSOCData(), m_strItemTrackerResFile );
|
||
|
m_pItemTrackerPanel->SetAutoDelete( false );
|
||
|
SETUP_PANEL( m_pItemTrackerPanel );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Get all the panels created
|
||
|
m_pItemTrackerPanel->SetItem( m_hQuestItem->GetSOCData() );
|
||
|
m_pItemTrackerPanel->InvalidateLayout( true );
|
||
|
}
|
||
|
|
||
|
m_pItemTrackerPanel->SetTall( m_pItemTrackerPanel->GetContentTall() );
|
||
|
|
||
|
// Need to re-layout so the flavor text gets properly positioned under
|
||
|
// all of the objectives
|
||
|
InvalidateLayout();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::SetItem( CEconItemView* pItem )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
if ( pItem == m_hQuestItem )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_bCollapsed = true;
|
||
|
m_hQuestItem.SetItem( pItem );
|
||
|
|
||
|
if ( m_pItemTrackerPanel && pItem )
|
||
|
{
|
||
|
m_pItemTrackerPanel->SetItem( pItem->GetSOCData() );
|
||
|
}
|
||
|
|
||
|
// By default
|
||
|
SetState( STATE_NORMAL );
|
||
|
|
||
|
if ( m_hQuestItem )
|
||
|
{
|
||
|
if ( IsQuestItemReadyToTurnIn( m_hQuestItem ) )
|
||
|
{
|
||
|
SetState( STATE_COMPLETED );
|
||
|
}
|
||
|
else if ( IsUnacknowledged() )
|
||
|
{
|
||
|
SetState( STATE_UNIDENTIFIED );
|
||
|
}
|
||
|
|
||
|
// Snag the quickplay map (if there is one)
|
||
|
m_strQuickPlayMap = m_hQuestItem->GetItemDefinition()->GetQuestDef()->GetQuickplayMapName();
|
||
|
|
||
|
m_strMatchmakingGroupName = m_hQuestItem->GetItemDefinition()->GetQuestDef()->GetMatchmakingGroupName();
|
||
|
m_strMatchmakingCategoryName = m_hQuestItem->GetItemDefinition()->GetQuestDef()->GetMatchmakingCategoryName();
|
||
|
m_strMatchmakingMapName = m_hQuestItem->GetItemDefinition()->GetQuestDef()->GetMatchmakingMapName();
|
||
|
}
|
||
|
|
||
|
// Reload res file so we get the right art
|
||
|
LoadResFileForCurrentItem();
|
||
|
|
||
|
// Capture strings after controls are created
|
||
|
CaptureAndEncodeStrings();
|
||
|
|
||
|
InvalidateLayout();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Returns if the character is one that we don't want to re-encode
|
||
|
// as another, or one that we don't want to encode another to in
|
||
|
// order to maintain line breaks so that the decoding sequence is
|
||
|
// easier for the user to follow.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool IsNonEncodeCharacter( const wchar_t& wch)
|
||
|
{
|
||
|
switch ( wch )
|
||
|
{
|
||
|
case L'\x000A':
|
||
|
case L'\x000B':
|
||
|
case L'\x000C':
|
||
|
case L'\x000D':
|
||
|
case L'\x0085':
|
||
|
case L'\x2028':
|
||
|
case L'\x2029':
|
||
|
case L' ':
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::CaptureAndEncodeStrings()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
if ( !m_hQuestItem )
|
||
|
return;
|
||
|
|
||
|
// Clean up any existing values
|
||
|
if ( m_pKVCipherStrings )
|
||
|
{
|
||
|
m_pKVCipherStrings->deleteThis();
|
||
|
m_pKVCipherStrings = NULL;
|
||
|
}
|
||
|
|
||
|
m_pKVCipherStrings = new KeyValues( "cipherstrings" );
|
||
|
KeyValues *pKVDecoded = m_pKVCipherStrings->CreateNewKey();
|
||
|
pKVDecoded->SetName( "decoded" );
|
||
|
|
||
|
{
|
||
|
// Capture the description/flavor string
|
||
|
const char *pszLocToken = m_hQuestItem->GetItemDefinition()->GetQuestDef()->GetRolledDescriptionForItem( m_hQuestItem->GetSOCData() );
|
||
|
pKVDecoded->SetWString( "desc", g_pVGuiLocalize->Find( pszLocToken ) );
|
||
|
}
|
||
|
|
||
|
if ( m_pObjectiveExplanationLabel )
|
||
|
{
|
||
|
wchar_t wszBuff[512];
|
||
|
m_pObjectiveExplanationLabel->GetText( wszBuff, ARRAYSIZE( wszBuff ) );
|
||
|
pKVDecoded->SetWString( "explanation", wszBuff );
|
||
|
}
|
||
|
|
||
|
auto& vecObjectives = m_pItemTrackerPanel->GetAttributePanels();
|
||
|
// Capture objective strings
|
||
|
FOR_EACH_VEC( vecObjectives, i )
|
||
|
{
|
||
|
CItemAttributeProgressPanel *pObjective = vecObjectives[ i ];
|
||
|
KeyValues *pKV = pObjective->GetDialogVariables();
|
||
|
pKVDecoded->SetWString( CFmtStr( "objective%d", i ), pKV->GetWString( "attr_desc" ) );
|
||
|
}
|
||
|
|
||
|
// Create encoded strings from the decoded strings
|
||
|
KeyValues *pKVEncoded = pKVDecoded->MakeCopy();
|
||
|
pKVEncoded->SetName( "encoded" );
|
||
|
|
||
|
m_pKVCipherStrings->AddSubKey( pKVEncoded );
|
||
|
|
||
|
RandomSeed( m_hQuestItem->GetSOCData() ? m_hQuestItem->GetSOCData()->GetOriginalID() : m_hQuestItem->GetItemDefIndex() );
|
||
|
|
||
|
// "encode" each string by scrambling
|
||
|
FOR_EACH_VALUE( pKVEncoded, pKVString )
|
||
|
{
|
||
|
const wchar_t *pWString = pKVString->GetWString();
|
||
|
wchar wszBuff[4096];
|
||
|
loc_scpy_safe( wszBuff, pWString );
|
||
|
int nStrLen = Q_wcslen( wszBuff );
|
||
|
|
||
|
// Go through the entire string and swap each character
|
||
|
// with another random character in the string
|
||
|
int i=0;
|
||
|
while( wszBuff[i] != 0 && i < ARRAYSIZE( wszBuff ) )
|
||
|
{
|
||
|
// Dont scramble spaces to maintain line breaks
|
||
|
if ( !IsNonEncodeCharacter( wszBuff[i] ) )
|
||
|
{
|
||
|
// Scramble, but keep trying if we scramble to a space
|
||
|
do
|
||
|
{
|
||
|
wszBuff[i] = *(pWString + RandomInt( 0, nStrLen - 1 ) );
|
||
|
} while ( IsNonEncodeCharacter( wszBuff[i] ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
pKVEncoded->SetWString( pKVString->GetName(), wszBuff );
|
||
|
}
|
||
|
|
||
|
const char *pszLocToken = m_hQuestItem->GetItemDefinition()->GetQuestDef()->GetRolledNameForItem( m_hQuestItem->GetSOCData() );
|
||
|
const wchar_t* pwszName = g_pVGuiLocalize->Find( pszLocToken );
|
||
|
// Force the encrypted version of the quest title to be "<Encrypted>".
|
||
|
pKVEncoded->SetWString( "name", g_pVGuiLocalize->Find( m_strEncodedText ) );
|
||
|
pKVDecoded->SetWString( "name", pwszName );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnCommand( const char *command )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
BaseClass::OnCommand( command );
|
||
|
|
||
|
if ( FStrEq( command, "discard_quest" ) )
|
||
|
{
|
||
|
OnDiscardQuest();
|
||
|
}
|
||
|
else if ( FStrEq( command, "select" ) )
|
||
|
{
|
||
|
m_pQuestList->SetSelected( this, false );
|
||
|
}
|
||
|
else if ( FStrEq( command, "turnin" ) )
|
||
|
{
|
||
|
if ( m_hQuestItem && m_hQuestItem->GetItemDefinition() && m_hQuestItem->GetItemDefinition()->GetQuestDef() )
|
||
|
{
|
||
|
if ( !tf_quest_turn_in_confirm_opt_out.GetBool() && ( GetEarnedBonusPoints( m_hQuestItem ) != m_hQuestItem->GetItemDefinition()->GetQuestDef()->GetMaxBonusPoints() ) )
|
||
|
{
|
||
|
CTFGenericConfirmOptOutDialog *pPanel = ShowConfirmOptOutDialog( "#TF_Quest_TurnIn_Title", "#TF_Quest_TurnIn_Text",
|
||
|
"#TF_Quest_TurnIn_Yes", "#TF_Quest_TurnIn_No",
|
||
|
"#TF_Quest_TurnIn_Ask_Opt_Out", "tf_quest_turn_in_confirm_opt_out",
|
||
|
ConfirmTurnInQuest );
|
||
|
if ( pPanel )
|
||
|
{
|
||
|
pPanel->SetContext( this );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
OnCompleteQuest();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( command, "identify" ) )
|
||
|
{
|
||
|
OnIdentify();
|
||
|
}
|
||
|
else if ( FStrEq( command, "request_loaner_items" ) )
|
||
|
{
|
||
|
GCSDK::CProtoBufMsg< CMsgGCQuestObjective_RequestLoanerItems > msg( k_EMsgGCQuestObjective_RequestLoanerItems );
|
||
|
msg.Body().set_quest_item_id( m_hQuestItem->GetItemID() );
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
}
|
||
|
else if ( FStrEq( command, "equip_loaner_items" ) )
|
||
|
{
|
||
|
OnEquipLoaners();
|
||
|
}
|
||
|
else if( Q_strnicmp( "playsound", command, 9 ) == 0 )
|
||
|
{
|
||
|
vgui::surface()->PlaySound( command + 10 );
|
||
|
}
|
||
|
else if ( FStrEq( "mm_casual_open", command ) )
|
||
|
{
|
||
|
if ( GTFGCClientSystem() )
|
||
|
{
|
||
|
if ( ( m_strMatchmakingGroupName != 0 ) || ( m_strMatchmakingCategoryName != 0 ) || ( m_strMatchmakingMapName != 0 ) )
|
||
|
{
|
||
|
GTFGCClientSystem()->ClearCasualSearchCriteria();
|
||
|
|
||
|
if ( m_strMatchmakingGroupName != 0 )
|
||
|
{
|
||
|
int iGroupType = StringFieldToInt( m_strMatchmakingGroupName.Get(), s_pszMMTypes, ARRAYSIZE( s_pszMMTypes ) );
|
||
|
if ( iGroupType > -1 )
|
||
|
{
|
||
|
SelectGroup( (EMatchmakingGroupType)iGroupType, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_strMatchmakingCategoryName != 0 )
|
||
|
{
|
||
|
int iCategoryType = StringFieldToInt( m_strMatchmakingCategoryName.Get(), s_pszGameModes, ARRAYSIZE( s_pszGameModes ) );
|
||
|
if ( iCategoryType > -1 )
|
||
|
{
|
||
|
SelectCategory( (EGameCategory)iCategoryType, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_strMatchmakingMapName != 0 )
|
||
|
{
|
||
|
if ( GetItemSchema() )
|
||
|
{
|
||
|
const MapDef_t *pMap = GetItemSchema()->GetMasterMapDefByName( m_strMatchmakingMapName.Get() );
|
||
|
if ( pMap )
|
||
|
{
|
||
|
GTFGCClientSystem()->SelectCasualMap( pMap->m_nDefIndex, true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Defaulting to 12v12
|
||
|
GTFGCClientSystem()->SetLadderType( k_nMatchGroup_Casual_12v12 );
|
||
|
PromptOrFireCommand( "OpenMatchmakingLobby casual" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const wchar_t* CQuestItemPanel::GetDecodedString( const char* pszKeyName, float flPercentDecoded )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
static wchar_t wszBuff[4096];
|
||
|
KeyValues *pKVEncoded = m_pKVCipherStrings->FindKey( "encoded" );
|
||
|
KeyValues *pKVDecoded = m_pKVCipherStrings->FindKey( "decoded" );
|
||
|
|
||
|
// Trivial work?
|
||
|
if ( flPercentDecoded <= 0.f )
|
||
|
{
|
||
|
return pKVEncoded->GetWString( pszKeyName );
|
||
|
}
|
||
|
else if ( flPercentDecoded >= 1.f )
|
||
|
{
|
||
|
return pKVDecoded->GetWString( pszKeyName );
|
||
|
}
|
||
|
|
||
|
loc_scpy_safe( wszBuff, pKVEncoded->GetWString( pszKeyName ) );
|
||
|
const locchar_t* pwszDecoded = pKVDecoded->GetWString( pszKeyName );
|
||
|
int nLength = loc_strlen( pwszDecoded );
|
||
|
int nMaxCopy = nLength * flPercentDecoded;
|
||
|
// Not using V_wcsncpy because it null terminates.
|
||
|
wcsncpy( wszBuff, pwszDecoded, nMaxCopy );
|
||
|
|
||
|
return wszBuff;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnThink()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
switch ( m_eState )
|
||
|
{
|
||
|
case STATE_IDENTIFYING:
|
||
|
{
|
||
|
// Have we finished?
|
||
|
if ( m_StateTimer.HasStarted() && m_StateTimer.IsElapsed() )
|
||
|
{
|
||
|
m_pItemTrackerPanel->InvalidateLayout();
|
||
|
m_StateTimer.Invalidate();
|
||
|
SetState( STATE_NORMAL );
|
||
|
|
||
|
// Play a reveal sound?
|
||
|
const GameItemDefinition_t *pItemDef = m_hQuestItem->GetItemDefinition();
|
||
|
const CQuestThemeDefinition *pTheme = pItemDef->GetQuestDef()->GetQuestTheme();
|
||
|
if ( pTheme )
|
||
|
{
|
||
|
const char *pszRevealSound = pTheme->GetRevealSound();
|
||
|
if ( pszRevealSound && pszRevealSound[0] )
|
||
|
{
|
||
|
vgui::surface()->PlaySound( pszRevealSound );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float flPercent = m_StateTimer.GetElapsedTime() / m_StateTimer.GetCountdownDuration();
|
||
|
|
||
|
switch( m_eDecodeStyle )
|
||
|
{
|
||
|
case DECODE_STYLE_CYPHER:
|
||
|
{
|
||
|
// Slowly "decode" the text in the lables
|
||
|
m_pTitleButton->SetText( GetDecodedString( "name", flPercent ) );
|
||
|
m_pFlavorText->SetText( GetDecodedString( "desc", flPercent ) );
|
||
|
m_pObjectiveExplanationLabel->SetText( GetDecodedString( "explanation", flPercent ) );
|
||
|
|
||
|
auto& vecObjectives = m_pItemTrackerPanel->GetAttributePanels();
|
||
|
FOR_EACH_VEC( vecObjectives, i )
|
||
|
{
|
||
|
const wchar_t *pszString = GetDecodedString( CFmtStr( "objective%d", i ), flPercent );
|
||
|
vecObjectives[ i ]->SetDialogVariable( "attr_desc", pszString );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case DECODE_STYLE_PANEL_FADE:
|
||
|
{
|
||
|
// Slowly fade out the encode image
|
||
|
m_pEncodedImage->SetAlpha( 255 * ( 1.f - flPercent ) );
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
Assert( 0 );
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case STATE_TURNING_IN__WAITING_FOR_GC:
|
||
|
{
|
||
|
// Have we finished?
|
||
|
if ( m_StateTimer.HasStarted() && m_StateTimer.IsElapsed() )
|
||
|
{
|
||
|
m_pQuestList->SetCompletingPanel( NULL );
|
||
|
m_StateTimer.Invalidate();
|
||
|
|
||
|
// Bring up confirm dialog
|
||
|
CTFGenericConfirmDialog *pDialog = new CTFGenericConfirmDialog( "#TF_Trading_Timeout_Title", "#TF_Trading_Timeout_Text", "#TF_OK", NULL, NULL, NULL );
|
||
|
|
||
|
if ( pDialog )
|
||
|
{
|
||
|
pDialog->SetContext( this );
|
||
|
pDialog->Show();
|
||
|
}
|
||
|
|
||
|
SetState( STATE_COMPLETED );
|
||
|
}
|
||
|
|
||
|
// Intentionally fall through
|
||
|
}
|
||
|
case STATE_TURNING_IN__GC_RESPONDED:
|
||
|
{
|
||
|
// Have we finished?
|
||
|
if ( m_StateTimer.HasStarted() && m_StateTimer.IsElapsed() )
|
||
|
{
|
||
|
SetState( STATE_SHOW_ACCEPTED );
|
||
|
m_StateTimer.Start( 3.f );
|
||
|
m_pAcceptedImage->SetVisible( true );
|
||
|
|
||
|
vgui::surface()->PlaySound( m_strTurnInSuccessSound );
|
||
|
}
|
||
|
|
||
|
if ( m_pTurningInLabel )
|
||
|
{
|
||
|
int nPeriods = m_StateTimer.GetElapsedTime() / 0.3f;
|
||
|
nPeriods %= 4; // Only do up to 3 periods
|
||
|
|
||
|
wchar_t wszTurningInText[64];
|
||
|
char szTurningInLocToken[128];
|
||
|
m_pTurningInLabel->GetTextImage()->GetUnlocalizedText( szTurningInLocToken, ARRAYSIZE( szTurningInLocToken ) );
|
||
|
V_snwprintf( wszTurningInText, ARRAYSIZE( wszTurningInText ), L"%ls", g_pVGuiLocalize->Find( szTurningInLocToken ) );
|
||
|
|
||
|
while ( nPeriods > 0 )
|
||
|
{
|
||
|
V_wcsncat( wszTurningInText, L".", ARRAYSIZE( wszTurningInText ) );
|
||
|
--nPeriods;
|
||
|
}
|
||
|
|
||
|
m_pTurningInLabel->SetText( wszTurningInText );
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case STATE_SHOW_ACCEPTED:
|
||
|
{
|
||
|
if ( m_StateTimer.HasStarted() && m_StateTimer.IsElapsed() )
|
||
|
{
|
||
|
m_pQuestList->SetCompletingPanel( NULL );
|
||
|
m_StateTimer.Invalidate();
|
||
|
|
||
|
engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" );
|
||
|
|
||
|
InventoryManager()->ShowItemsPickedUp( true, false );
|
||
|
GetQuestLog()->AttachToGameUI();
|
||
|
GetQuestLog()->MarkQuestsDirty();
|
||
|
m_pQuestList->PopulateQuestLists();
|
||
|
|
||
|
engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" );
|
||
|
|
||
|
if ( m_pszCompleteSound )
|
||
|
{
|
||
|
vgui::surface()->PlaySound( m_pszCompleteSound );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
float flPercent = Clamp( m_StateTimer.GetElapsedTime() / 0.2f, 0.f, 1.f );
|
||
|
m_nPaperXShakePos = sin( m_StateTimer.GetElapsedTime() * 200.f ) * ( 1.f - flPercent ) * 8.f;
|
||
|
m_nPaperYShakePos = sin( m_StateTimer.GetElapsedTime() * 200.f ) * ( 1.f - flPercent ) * 8.f;
|
||
|
m_pQuestPaperContainer->SetPos( m_nPaperXPos + m_nPaperXShakePos, m_nPaperYPos + m_nPaperYShakePos );
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case STATE_UNIDENTIFIED:
|
||
|
{
|
||
|
// Do nothing
|
||
|
break;
|
||
|
}
|
||
|
case STATE_COMPLETED:
|
||
|
{
|
||
|
// Do nothing
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
// Do nothing
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::FireGameEvent( IGameEvent *event )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
if( FStrEq( event->GetName(), "quest_objective_completed" ) )
|
||
|
{
|
||
|
itemid_t nIDLow = 0x00000000FFFFFFFF & (itemid_t)event->GetInt( "quest_item_id_low" );
|
||
|
itemid_t nIDHi = 0xFFFFFFFF00000000 & (itemid_t)event->GetInt( "quest_item_id_hi" ) << 32;
|
||
|
itemid_t nID = nIDLow | nIDHi;
|
||
|
if ( m_hQuestItem && nID == m_hQuestItem->GetID() )
|
||
|
{
|
||
|
SetupObjectivesPanels( false );
|
||
|
|
||
|
if ( IsQuestItemReadyToTurnIn( m_hQuestItem ) )
|
||
|
{
|
||
|
SetState( STATE_COMPLETED );
|
||
|
}
|
||
|
|
||
|
PerformLayout();
|
||
|
}
|
||
|
}
|
||
|
else if ( FStrEq( event->GetName(), "player_spawn" )
|
||
|
|| FStrEq( event->GetName(), "client_disconnect" ) )
|
||
|
{
|
||
|
InvalidateLayout();
|
||
|
}
|
||
|
else if ( FStrEq( "inventory_updated", event->GetName() ) )
|
||
|
{
|
||
|
// InvalidateLayout();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CQuestItemPanel::OnMouseReleased( MouseCode code )
|
||
|
{
|
||
|
OnCommand( "select" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Update our invalid reasons
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::UpdateInvalidReasons()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
InvalidReasonsContainer_t invalidReasons;
|
||
|
bool bAllAreInvalid = false;
|
||
|
|
||
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||
|
if ( pLocalPlayer && m_hQuestItem )
|
||
|
{
|
||
|
// Get the tracker for the items
|
||
|
const CQuestItemTracker* pItemTracker = QuestObjectiveManager()->GetTypedTracker< CQuestItemTracker* >( m_hQuestItem->GetItemID() );
|
||
|
// Get invalid reasons
|
||
|
if ( pItemTracker )
|
||
|
{
|
||
|
int nNumInvalid = pItemTracker->IsValidForPlayer( pLocalPlayer, invalidReasons );
|
||
|
bAllAreInvalid = pItemTracker->GetTrackers().Count() == nNumInvalid;
|
||
|
}
|
||
|
|
||
|
// Build a string describing why the current quest can't be worked on
|
||
|
if ( !invalidReasons.IsValid() )
|
||
|
{
|
||
|
CUtlVector< CUtlString > vecStrings;
|
||
|
// Get the strings that explain each reasons
|
||
|
GetInvalidReasonsNames( invalidReasons, vecStrings );
|
||
|
|
||
|
wchar_t wszBuff[ 1024 ];
|
||
|
|
||
|
// Start with the explanation
|
||
|
V_swprintf_safe( wszBuff, L"%ls", g_pVGuiLocalize->Find( "#TF_QuestInvalid_Explanation" ) );
|
||
|
|
||
|
// Add in each reason why the quest is invalid
|
||
|
for( int i = 0; i < vecStrings.Count(); ++ i )
|
||
|
{
|
||
|
V_wcscat_safe( wszBuff, L"\n\n" );
|
||
|
V_wcscat_safe( wszBuff, g_pVGuiLocalize->Find( vecStrings[i] ) );
|
||
|
}
|
||
|
|
||
|
// This gets snagged by CQuestTooltip
|
||
|
m_pInactiveStatus->SetDialogVariable( "tiptext", wszBuff );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Visible if there's a reason why we're invalid
|
||
|
bool bShow = bAllAreInvalid && m_eState == STATE_NORMAL;
|
||
|
m_pInactiveStatus->SetShow( bShow );
|
||
|
m_pInactiveStatus->SetMouseInputEnabled( bShow );
|
||
|
m_pInactiveStatus->SetTooltip( g_spTextTooltip, NULL );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Start a glow
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnCollapsedGlowStart( void )
|
||
|
{
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, m_strHighlightOn );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Stop the glow
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnCollapsedGlowEnd( void )
|
||
|
{
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, m_strHighlightOff );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Delete the quest.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnDiscardQuest( void )
|
||
|
{
|
||
|
#if !defined(STAGING_ONLY) && !defined(DEBUG)
|
||
|
// Not in public!
|
||
|
return;
|
||
|
#endif
|
||
|
|
||
|
if ( m_pQuestList->GetCompletingPanel() == NULL )
|
||
|
{
|
||
|
// Bring up confirm dialog
|
||
|
CTFGenericConfirmDialog *pDialog = new CTFGenericConfirmDialog( "#QuestConfirmDiscard_Title", "#QuestConfirmDiscard_Body", "#X_DiscardItem", "#Cancel", &ConfirmDiscardQuest, NULL );
|
||
|
if ( pDialog )
|
||
|
{
|
||
|
pDialog->SetContext( this );
|
||
|
pDialog->Show();
|
||
|
}
|
||
|
|
||
|
const GameItemDefinition_t *pItemDef = m_hQuestItem->GetItemDefinition();
|
||
|
// Get our quest theme
|
||
|
const CQuestThemeDefinition *pTheme = pItemDef->GetQuestDef()->GetQuestTheme();
|
||
|
if ( pTheme )
|
||
|
{
|
||
|
const char *pszDiscardSound = pTheme->GetDiscardSound();
|
||
|
if ( pszDiscardSound && pszDiscardSound[0] )
|
||
|
{
|
||
|
vgui::surface()->PlaySound( pszDiscardSound );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Equip loaners for local player
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnEquipLoaners( void )
|
||
|
{
|
||
|
if ( !m_hQuestItem )
|
||
|
return;
|
||
|
|
||
|
if ( m_pQuestList->GetCompletingPanel() == NULL )
|
||
|
{
|
||
|
// Bring up confirm dialog
|
||
|
CTFGenericConfirmDialog *pDialog = new CTFGenericConfirmDialog( "#QuestConfirmEquipLoaners_Title", "#QuestConfirmEquipLoaners_Body", "#Equip", "#Cancel", &ConfirmEquipLoaners, NULL );
|
||
|
if ( pDialog )
|
||
|
{
|
||
|
pDialog->SetContext( this );
|
||
|
pDialog->Show();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Send a message to the GC to evaluate completion of this quest
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnCompleteQuest( void )
|
||
|
{
|
||
|
if ( !m_hQuestItem )
|
||
|
return;
|
||
|
|
||
|
// Double check that they're not just forcing the command
|
||
|
if ( IsQuestItemReadyToTurnIn( m_hQuestItem ) && m_pQuestList->GetCompletingPanel() == NULL )
|
||
|
{
|
||
|
m_pQuestList->SetCompletingPanel( this );
|
||
|
|
||
|
SetState( STATE_TURNING_IN__WAITING_FOR_GC );
|
||
|
|
||
|
// Use the timer for turning in the quest
|
||
|
m_StateTimer.Start( k_flQuestTurnInTime );
|
||
|
vgui::surface()->PlaySound( m_strTurnInSound );
|
||
|
|
||
|
GCSDK::CProtoBufMsg< CMsgGCQuestComplete_Request > msg( k_EMsgGCQuestComplete_Request );
|
||
|
|
||
|
msg.Body().set_quest_item_id( m_hQuestItem->GetItemID() );
|
||
|
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
|
||
|
PostActionSignal( new KeyValues("CompleteQuest") );
|
||
|
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, m_strTurningIn );
|
||
|
|
||
|
const GameItemDefinition_t *pItemDef = m_hQuestItem->GetItemDefinition();
|
||
|
// Get our quest theme
|
||
|
const CQuestThemeDefinition *pTheme = pItemDef->GetQuestDef()->GetQuestTheme();
|
||
|
if ( pTheme )
|
||
|
{
|
||
|
m_pszCompleteSound = pTheme->GetRewardSound();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CQuestItemPanel::OnIdentify()
|
||
|
{
|
||
|
if ( IsUnacknowledged() )
|
||
|
{
|
||
|
SetState( STATE_IDENTIFYING );
|
||
|
|
||
|
// Use the timer for identifying progress
|
||
|
m_StateTimer.Start( k_flQuestDecodeTime );
|
||
|
vgui::surface()->PlaySound( m_strDecodeSound );
|
||
|
|
||
|
// ack item
|
||
|
CEconItemView *pModifyItem = m_hQuestItem;
|
||
|
TFInventoryManager()->AcknowledgeItem( pModifyItem, false );
|
||
|
TFInventoryManager()->SetItemBackpackPosition( pModifyItem, (uint32)-1, false, true );
|
||
|
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pQuestPaperContainer, "QuestItem_StaticPhoto_Reveal" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnConfirmDelete( bool bConfirm )
|
||
|
{
|
||
|
// Delete the quest
|
||
|
if ( bConfirm && m_hQuestItem )
|
||
|
{
|
||
|
GCSDK::CProtoBufMsg< CMsgGCQuestDiscard_Request > msg( k_EMsgGCQuestDiscard_Request );
|
||
|
|
||
|
msg.Body().set_quest_item_id( m_hQuestItem->GetItemID() );
|
||
|
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::OnConfirmEquipLoaners( bool bConfirm )
|
||
|
{
|
||
|
// equip loaners
|
||
|
if ( bConfirm && m_hQuestItem )
|
||
|
{
|
||
|
// get all loaners required from quest
|
||
|
CUtlVector< item_definition_index_t > vecLoanerItems;
|
||
|
bool bRequiredLoaners = GetLoanerListFromQuest( m_hQuestItem, vecLoanerItems );
|
||
|
|
||
|
// get all granted loaners from this quest
|
||
|
CUtlVector< CEconItemView* > vecGrantedLoaners;
|
||
|
if ( bRequiredLoaners )
|
||
|
{
|
||
|
GetLoanersFromLocalInventory( m_hQuestItem->GetItemID(), vecLoanerItems, vecGrantedLoaners );
|
||
|
}
|
||
|
|
||
|
for ( int i=0; i<vecGrantedLoaners.Count(); ++i )
|
||
|
{
|
||
|
CEconItemView *pItem = vecGrantedLoaners[i];
|
||
|
if ( pItem )
|
||
|
{
|
||
|
// do it for first class that can equip
|
||
|
for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; ++iClass )
|
||
|
{
|
||
|
if ( pItem->GetStaticData()->CanBeUsedByClass( iClass ) )
|
||
|
{
|
||
|
int iSlot = pItem->GetStaticData()->GetLoadoutSlot( iClass );
|
||
|
TFInventoryManager()->EquipItemInLoadout( iClass, iSlot, pItem->GetItemID() );
|
||
|
|
||
|
// take the player to character loadout page
|
||
|
engine->ClientCmd_Unrestricted( CFmtStr( "open_charinfo_direct %d", iClass ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::QuestCompletedResponse()
|
||
|
{
|
||
|
// If we werent the one listening, dont bother
|
||
|
if ( m_eState != STATE_TURNING_IN__WAITING_FOR_GC )
|
||
|
return;
|
||
|
|
||
|
m_pQuestPaperContainer->GetPos( m_nPaperXPos, m_nPaperYPos );
|
||
|
m_nPaperXShakePos = m_nPaperYShakePos = 0;
|
||
|
|
||
|
SetState( STATE_TURNING_IN__GC_RESPONDED );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CQuestItemPanel::SetSelected( bool bSelected, bool bImmediate )
|
||
|
{
|
||
|
bool bPrevCollapsedSide = m_bCollapsed;
|
||
|
m_bCollapsed = ( !m_bCollapsed && bSelected ) || ( !bSelected );
|
||
|
|
||
|
if ( !bImmediate && bPrevCollapsedSide != m_bCollapsed )
|
||
|
{
|
||
|
if ( m_bCollapsed )
|
||
|
{
|
||
|
vgui::surface()->PlaySound( m_strCollapseSound );
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, m_strAnimCollapse );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vgui::surface()->PlaySound( m_strExpandSound );
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, m_strAnimExpand );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, m_strReset );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CQuestItemPanel::IsUnacknowledged()
|
||
|
{
|
||
|
if ( !m_hQuestItem )
|
||
|
return false;
|
||
|
|
||
|
return IsQuestItemUnidentified( m_hQuestItem->GetSOCData() );
|
||
|
}
|
||
|
|
||
|
void CQuestItemPanel::SetState( EItemPanelState_t eState )
|
||
|
{
|
||
|
m_eState = eState;
|
||
|
InvalidateLayout();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: GC Msg handler to handle a loaner item response
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CGCLoanerRequestResponse : public GCSDK::CGCClientJob
|
||
|
{
|
||
|
public:
|
||
|
CGCLoanerRequestResponse( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
|
||
|
|
||
|
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
|
||
|
{
|
||
|
GCSDK::CProtoBufMsg<CMsgGCQuestObjective_RequestLoanerResponse> msg( pNetPacket );
|
||
|
|
||
|
// Show them the items they just got loaned!
|
||
|
InventoryManager()->ShowItemsPickedUp( true, false );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
GC_REG_JOB( GCSDK::CGCClient, CGCLoanerRequestResponse, "CGCLoanerRequestResponse", k_EMsgGCQuestObjective_RequestLoanerResponse, GCSDK::k_EServerTypeGCClient );
|