mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-12-11 08:08:32 +00:00
411 lines
11 KiB
C++
411 lines
11 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
|
|
#include "tf_quest_map_utils.h"
|
|
#include "gcsdk/enumutils.h"
|
|
#include "tf_quest_map_node.h"
|
|
#include "tf_quest_map.h"
|
|
#include "econ_quests.h"
|
|
#include "econ_game_account_client.h"
|
|
#ifdef CLIENT_DLL
|
|
#include "tf_item_inventory.h"
|
|
#endif
|
|
|
|
using namespace GCSDK;
|
|
|
|
|
|
#ifdef CLIENT_DLL
|
|
uint64 GetNodeDefPairKey( uint32 nDefindex1, uint32 nDefIndex2 )
|
|
{
|
|
uint64 key = 0;
|
|
key |= (uint64)Min( nDefindex1, nDefIndex2 ) << 32;
|
|
key |= Max( nDefindex1, nDefIndex2 );
|
|
return key;
|
|
}
|
|
|
|
const CQuestMapHelper& GetQuestMapHelper()
|
|
{
|
|
static CQuestMapHelper s_LocalPlayerHelper;
|
|
return s_LocalPlayerHelper;
|
|
}
|
|
#endif
|
|
|
|
CQuestMapHelper::CQuestMapHelper( CSteamID steamID )
|
|
: m_mapNodes( DefLessFunc( uint32 ) )
|
|
, m_steamID( steamID )
|
|
, m_mapStarsAvailableToSpend( DefLessFunc( uint32 ) )
|
|
, m_mapStarsEarned( DefLessFunc( uint32 ) )
|
|
, m_mapStarsTotal( DefLessFunc( uint32 ) )
|
|
, m_mapRewardDefindexPurchases( DefLessFunc( uint32 ) )
|
|
{
|
|
Refresh();
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
CQuestMapHelper::CQuestMapHelper()
|
|
: m_mapNodes( DefLessFunc( uint32 ) )
|
|
, m_mapNodeConnections( DefLessFunc( uint64 ) )
|
|
, m_mapRegionHasAvailableContracts( DefLessFunc( uint32 ) )
|
|
, m_mapStarsAvailableToSpend( DefLessFunc( uint32 ) )
|
|
, m_mapStarsEarned( DefLessFunc( uint32 ) )
|
|
, m_mapStarsTotal( DefLessFunc( uint32 ) )
|
|
, m_mapRewardDefindexPurchases( DefLessFunc( uint32 ) )
|
|
{
|
|
if ( steamapicontext && steamapicontext->SteamUser() )
|
|
{
|
|
m_steamID = steamapicontext->SteamUser()->GetSteamID();
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void CQuestMapHelper::SOEvent( const GCSDK::CSharedObject *pObject )
|
|
{
|
|
if ( pObject->GetTypeID() == CQuestMapNode::k_nTypeID ||
|
|
pObject->GetTypeID() == CEconGameAccountClient::k_nTypeID ||
|
|
pObject->GetTypeID() == CQuest::k_nTypeID ||
|
|
pObject->GetTypeID() == CQuestMapRewardPurchase::k_nTypeID )
|
|
{
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
bool CQuestMapHelper::BIsNodeConnectionFulfilled( const CQuestMapNodeDefinition* pNode1, const CQuestMapNodeDefinition* pNode2 ) const
|
|
{
|
|
uint64 key = GetNodeDefPairKey( pNode1->GetDefIndex(), pNode2->GetDefIndex() );
|
|
auto idx = m_mapNodeConnections.Find( key );
|
|
if ( idx == m_mapNodeConnections.InvalidIndex() )
|
|
{
|
|
Assert( false );
|
|
return false;
|
|
}
|
|
|
|
return m_mapNodeConnections[ idx ];
|
|
}
|
|
|
|
bool CQuestMapHelper::BRegionHasAvailableContracts( uint32 nRegionDefIndex ) const
|
|
{
|
|
auto idx = m_mapRegionHasAvailableContracts.Find( nRegionDefIndex );
|
|
if ( idx == m_mapRegionHasAvailableContracts.InvalidIndex() )
|
|
return false;
|
|
|
|
return m_mapRegionHasAvailableContracts[ idx ];
|
|
}
|
|
#endif
|
|
|
|
const CQuest* CQuestMapHelper::GetActiveQuest() const
|
|
{
|
|
if ( m_vecQuests.IsValidIndex( m_nActiveQuestIndex ) )
|
|
{
|
|
return m_vecQuests[m_nActiveQuestIndex];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#ifndef GAME_DLL
|
|
int CQuestMapHelper::GetNumRewardCredits() const
|
|
{
|
|
return m_nRewardCredits;
|
|
}
|
|
#endif // GAME_DLL
|
|
|
|
template< typename MapType, typename KeyType >
|
|
typename MapType::ElemType_t& GetMapValue( MapType& map, KeyType key )
|
|
{
|
|
auto idx = map.Find( key );
|
|
if ( idx == map.InvalidIndex() )
|
|
{
|
|
idx = map.Insert( key, 0 );
|
|
}
|
|
|
|
return map[ idx ];
|
|
}
|
|
|
|
int CQuestMapHelper::GetNumStarsAvailableToSpend( uint32 nTypeDefindex ) const
|
|
{
|
|
auto idx = m_mapStarsAvailableToSpend.Find( nTypeDefindex );
|
|
if ( idx == m_mapStarsAvailableToSpend.InvalidIndex() )
|
|
return 0;
|
|
|
|
return m_mapStarsAvailableToSpend[ idx ];
|
|
}
|
|
|
|
int CQuestMapHelper::GetNumStarsEarned( uint32 nTypeDefindex ) const
|
|
{
|
|
auto idx = m_mapStarsEarned.Find( nTypeDefindex );
|
|
if ( idx == m_mapStarsEarned.InvalidIndex() )
|
|
return 0;
|
|
|
|
return m_mapStarsEarned[ idx ];
|
|
}
|
|
|
|
int CQuestMapHelper::GetNumStarsTotal( uint32 nTypeDefindex ) const
|
|
{
|
|
auto idx = m_mapStarsTotal.Find( nTypeDefindex );
|
|
if ( idx == m_mapStarsTotal.InvalidIndex() )
|
|
return 0;
|
|
|
|
return m_mapStarsTotal[ idx ];
|
|
}
|
|
|
|
bool CQuestMapHelper::BCanNodeBeTurnedIn( uint32 nNodeDefindex ) const
|
|
{
|
|
auto pNode = GetQuestMapNode( nNodeDefindex );
|
|
if ( !pNode )
|
|
return false;
|
|
|
|
auto pQuest = GetQuestForNode( pNode->GetID() );
|
|
if ( !pQuest )
|
|
return false;
|
|
|
|
for( int i=0; i < EQuestPoints_ARRAYSIZE; ++i )
|
|
{
|
|
EQuestPoints eType = (EQuestPoints)i;
|
|
if ( pNode->BIsMedalOffered( eType ) &&
|
|
!pNode->BIsMedalEarned( eType ) &&
|
|
pQuest->BEarnedAllPointsForCategory( eType ) )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int CQuestMapHelper::GetNumRewardPurchases( uint32 nDefindex ) const
|
|
{
|
|
auto idx = m_mapRewardDefindexPurchases.Find( nDefindex );
|
|
// No entry means no purchases
|
|
if ( idx == m_mapRewardDefindexPurchases.InvalidIndex() )
|
|
return 0;
|
|
|
|
return m_mapRewardDefindexPurchases[ idx ];
|
|
}
|
|
|
|
void CQuestMapHelper::Refresh()
|
|
{
|
|
// Reset
|
|
memset( m_nTotalMedals, 0, sizeof( m_nTotalMedals ) );
|
|
memset( m_nCollectedMedals, 0, sizeof( m_nCollectedMedals ) );
|
|
m_nLockedAndRequirementsMetNodes = 0;
|
|
m_nNumUnlockedNodes = 0;
|
|
m_mapNodes.Purge();
|
|
m_vecQuests.Purge();
|
|
m_nActiveQuestIndex = m_vecQuests.InvalidIndex();
|
|
m_mapStarsAvailableToSpend.Purge();
|
|
m_mapStarsEarned.Purge();
|
|
m_mapStarsTotal.Purge();
|
|
m_mapRewardDefindexPurchases.Purge();
|
|
#ifndef GAME_DLL
|
|
m_nRewardCredits = 0;
|
|
#endif // GAME_DLL
|
|
#ifdef CLIENT_DLL
|
|
m_mapNodeConnections.Purge();
|
|
m_mapRegionHasAvailableContracts.Purge();
|
|
#endif // CLIENT_DLL
|
|
|
|
GCSDK::CGCClientSharedObjectCache *pSOCache = GCClientSystem()->GetSOCache( m_steamID );
|
|
if ( pSOCache && GetProtoScriptObjDefManager()->BDefinitionsLoaded() )
|
|
{
|
|
//
|
|
// Reward and Node credits
|
|
//
|
|
#ifndef GAME_DLL
|
|
auto pClientAccount = pSOCache->GetSingleton< CEconGameAccountClient >();
|
|
if ( !pClientAccount )
|
|
{
|
|
Assert( false );
|
|
Warning( "No CEconGameAccountClient to grab reward and node credits!\n" );
|
|
return;
|
|
}
|
|
m_nRewardCredits = pClientAccount->Obj().quest_reward_credits();
|
|
#endif // GAME_DLL
|
|
|
|
//
|
|
// Nodes
|
|
//
|
|
auto *pNodesCache = pSOCache->FindTypeCache( CQuestMapNode::k_nTypeID );
|
|
if ( pNodesCache )
|
|
{
|
|
for( uint32 i=0; i < pNodesCache->GetCount(); ++i )
|
|
{
|
|
CQuestMapNode* pNode = (CQuestMapNode*)pNodesCache->GetObject( i );
|
|
if ( pNode->GetNodeDefinition() != NULL )
|
|
{
|
|
m_mapNodes.Insert( pNode->Obj().defindex(), pNode );
|
|
}
|
|
else
|
|
{
|
|
Assert( false );
|
|
Warning( "Node %llu has defindex %d, which doesn't exist!\n", pNode->GetID(), pNode->Obj().defindex() );
|
|
}
|
|
}
|
|
|
|
FOR_EACH_MAP_FAST( m_mapNodes, i )
|
|
{
|
|
const CQuestMapNode* pNode = m_mapNodes[ i ];
|
|
auto nStarType = pNode->GetNodeDefinition()->GetStarType();
|
|
|
|
for( int j = 0; j < EQuestPoints_ARRAYSIZE; ++j )
|
|
{
|
|
m_nTotalMedals[ j ] += 1;
|
|
|
|
// If they collected it, add one
|
|
if ( pNode->BIsMedalEarned( (EQuestPoints)j ) )
|
|
{
|
|
m_nCollectedMedals[ j ] += 1;
|
|
GetMapValue( m_mapStarsAvailableToSpend, nStarType ) += 1;
|
|
}
|
|
}
|
|
|
|
// Tally up number of activated quests
|
|
++m_nNumUnlockedNodes;
|
|
GetMapValue( m_mapStarsAvailableToSpend, nStarType ) -= pNode->GetNodeDefinition()->GetNumStarsToUnlock();
|
|
}
|
|
}
|
|
|
|
auto& mapNodeDefs = GetProtoScriptObjDefManager()->GetDefinitionMapForType( DEF_TYPE_QUEST_MAP_NODE );
|
|
FOR_EACH_MAP_FAST( mapNodeDefs, i )
|
|
{
|
|
const CQuestMapNodeDefinition* pNodeDef = (const CQuestMapNodeDefinition*)mapNodeDefs[ i ];
|
|
auto pNode = GetQuestMapNode( pNodeDef->GetDefIndex() );
|
|
bool bBronzeMedalEarned = ( pNode && pNode->BIsMedalEarned( QUEST_POINTS_NOVICE ) );
|
|
if ( pNodeDef->BCanUnlock( *this ) && !bBronzeMedalEarned )
|
|
{
|
|
// Tally up locked, but requirements met (unlockable)
|
|
++m_nLockedAndRequirementsMetNodes;
|
|
#ifdef CLIENT_DLL
|
|
m_mapRegionHasAvailableContracts.Insert( pNodeDef->GetRegionDefIndex(), true );
|
|
#endif
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
CUtlMap< uint32, bool > mapConnectedNodeCondition;
|
|
pNodeDef->GetConnectedNodes( mapConnectedNodeCondition );
|
|
FOR_EACH_MAP_FAST( mapConnectedNodeCondition, j )
|
|
{
|
|
uint64 key = GetNodeDefPairKey( mapConnectedNodeCondition.Key( j ), pNodeDef->GetDefIndex() );
|
|
|
|
if ( m_mapNodeConnections.Find( key ) == m_mapNodeConnections.InvalidIndex() )
|
|
{
|
|
m_mapNodeConnections.Insert( key, mapConnectedNodeCondition[ j ] );
|
|
}
|
|
}
|
|
#endif
|
|
// Tally up how many stars they COULD go earn right now
|
|
auto nStarType = pNodeDef->GetStarType();
|
|
for( int j=0; j < EQuestPoints_ARRAYSIZE; ++j )
|
|
{
|
|
// Skip stars that arent earned
|
|
if ( !pNodeDef->BIsMedalOffered( (EQuestPoints)j ) )
|
|
continue;
|
|
|
|
if ( pNode && pNode->BIsMedalEarned( (EQuestPoints)j ) )
|
|
GetMapValue( m_mapStarsEarned, nStarType ) += 1;
|
|
|
|
GetMapValue( m_mapStarsTotal, nStarType ) += 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Quests
|
|
//
|
|
auto *pQuestsCache = pSOCache->FindTypeCache( CQuest::k_nTypeID );
|
|
if ( pQuestsCache )
|
|
{
|
|
for( uint32 i=0; i < pQuestsCache->GetCount(); ++i )
|
|
{
|
|
m_vecQuests.AddToTail( (CQuest*)pQuestsCache->GetObject( i ) );
|
|
|
|
if ( m_vecQuests.Tail()->Obj().active() )
|
|
{
|
|
// we should only have one active quest at a time
|
|
Assert( m_nActiveQuestIndex == m_vecQuests.InvalidIndex() );
|
|
m_nActiveQuestIndex = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Reward purchases
|
|
//
|
|
auto *pRewardsCache = pSOCache->FindTypeCache( CQuestMapRewardPurchase::k_nTypeID );
|
|
if ( pRewardsCache )
|
|
{
|
|
for( uint32 i=0; i < pRewardsCache->GetCount(); ++i )
|
|
{
|
|
const CQuestMapRewardPurchase* pPurchase = (CQuestMapRewardPurchase*)pRewardsCache->GetObject( i );
|
|
m_mapRewardDefindexPurchases.InsertOrReplace( pPurchase->Obj().defindex(), pPurchase->Obj().count() );
|
|
}
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
// Tell everyone the state of the quest map changed
|
|
IGameEvent *event = gameeventmanager->CreateEvent( "quest_map_data_changed" );
|
|
if ( event )
|
|
{
|
|
gameeventmanager->FireEventClientSide( event );
|
|
}
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
QUESTHELPER_CONSTNESS CQuestMapNode* CQuestMapHelper::GetQuestMapNode( uint32 nNodeDef ) const
|
|
{
|
|
auto idx = m_mapNodes.Find( nNodeDef );
|
|
if ( idx != m_mapNodes.InvalidIndex() )
|
|
{
|
|
return m_mapNodes[ idx ];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
QUESTHELPER_CONSTNESS CQuestMapNode* CQuestMapHelper::GetQuestMapNodeByID( uint32 nNodeID ) QUESTHELPER_CONSTNESS
|
|
{
|
|
FOR_EACH_MAP_FAST( m_mapNodes, i )
|
|
{
|
|
if ( m_mapNodes[ i ]->Obj().node_id() == nNodeID )
|
|
return m_mapNodes[ i ];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
QUESTHELPER_CONSTNESS CQuest* CQuestMapHelper::GetQuestForNode( uint32 nNodeID ) const
|
|
{
|
|
FOR_EACH_VEC( m_vecQuests, i )
|
|
{
|
|
if ( m_vecQuests[ i ]->Obj().quest_map_node_source_id() == nNodeID )
|
|
return m_vecQuests[ i ];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
QUESTHELPER_CONSTNESS CQuest* CQuestMapHelper::GetQuestByID( uint32 nQuestID ) QUESTHELPER_CONSTNESS
|
|
{
|
|
FOR_EACH_VEC( m_vecQuests, i )
|
|
{
|
|
if ( m_vecQuests[ i ]->Obj().quest_id() == nQuestID )
|
|
return m_vecQuests[ i ];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
QUESTHELPER_CONSTNESS CQuest* CQuestMapHelper::GetQuestByDefindex( uint32 nDefIndex ) const
|
|
{
|
|
FOR_EACH_VEC( m_vecQuests, i )
|
|
{
|
|
if ( m_vecQuests[ i ]->Obj().defindex() == nDefIndex )
|
|
return m_vecQuests[ i ];
|
|
}
|
|
|
|
return NULL;
|
|
} |