|
|
//========= 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 );
|