summaryrefslogtreecommitdiff
path: root/game/shared/tf/tf_mapinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/tf/tf_mapinfo.cpp')
-rw-r--r--game/shared/tf/tf_mapinfo.cpp849
1 files changed, 849 insertions, 0 deletions
diff --git a/game/shared/tf/tf_mapinfo.cpp b/game/shared/tf/tf_mapinfo.cpp
new file mode 100644
index 0000000..dad3d0b
--- /dev/null
+++ b/game/shared/tf/tf_mapinfo.cpp
@@ -0,0 +1,849 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+#include "cbase.h"
+
+#include "tf_mapinfo.h"
+#include <filesystem.h>
+#include "GameEventListener.h"
+#include "econ_item_system.h"
+#include "tf_item_inventory.h"
+#include "econ_contribution.h"
+#include "tf_duel_summary.h"
+#include "gc_clientsystem.h"
+#include "tf_duckleaderboard.h"
+#include "tf_gamerules.h"
+#include "tf_matchmaking_shared.h"
+
+#ifdef CLIENT_DLL
+ #include "hud_macros.h"
+#endif // CLIENT_DLL
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+#ifdef CLIENT_DLL
+ConVar tf_duck_upload_rate( "tf_duck_upload_rate", "2400", FCVAR_DEVELOPMENTONLY ); // Make this DevOnly At ship and 60 seconds
+#endif
+
+const char *g_szLadderLeaderboardNames[] =
+{
+ "tf2_ladder_6v6",
+ "tf2_ladder_public",
+ "tf2_ladder_9v9",
+ "tf2_ladder_12v12",
+};
+COMPILE_TIME_ASSERT( ARRAYSIZE( g_szLadderLeaderboardNames ) == LADDER_LEADERBOARDS_MAX );
+
+void __MsgFunc_EOTLDuckEvent( bf_read &msg );
+
+//-----------------------------------------------------------------------------
+int SortLeaderboardVec( LeaderboardEntry_t * const *p1, LeaderboardEntry_t * const *p2 )
+{
+ return ( *p2 )->m_nScore - ( *p1 )->m_nScore;
+}
+//-----------------------------------------------------------------------------
+
+static void RetrieveLeaderboardEntries( LeaderboardScoresDownloaded_t &scores, CUtlVector< LeaderboardEntry_t* > &entries )
+{
+ entries.PurgeAndDeleteElements();
+ entries.EnsureCapacity( scores.m_cEntryCount );
+ for ( int i = 0; i < scores.m_cEntryCount; ++i )
+ {
+ LeaderboardEntry_t *leaderboardEntry = new LeaderboardEntry_t;
+ if ( steamapicontext->SteamUserStats()->GetDownloadedLeaderboardEntry( scores.m_hSteamLeaderboardEntries, i, leaderboardEntry, NULL, 0 ) )
+ {
+ entries.AddToTail( leaderboardEntry );
+ }
+ }
+}
+
+
+CLeaderboardInfo::CLeaderboardInfo( const char *pLeaderboardName )
+{
+ m_pLeaderboardName = pLeaderboardName ? V_strdup( pLeaderboardName ) : NULL;
+ memset( &findLeaderboardResults, 0, sizeof( findLeaderboardResults ) );
+ iNumLeaderboardEntries = 0;
+ m_kLeaderboardType = kMapLeaderboard;
+ m_iMyScore = 0;
+ m_bHasPendingUpdate = false;
+ m_bLeaderboardFound = false;
+}
+
+CLeaderboardInfo::~CLeaderboardInfo()
+{
+ downloadedLeaderboardScoresGlobal.PurgeAndDeleteElements();
+ downloadedLeaderboardScoresGlobalAroundUser.PurgeAndDeleteElements();
+ downloadedLeaderboardScoresFriends.PurgeAndDeleteElements();
+ delete m_pLeaderboardName;
+}
+
+void CLeaderboardInfo::RetrieveLeaderboardData()
+{
+ if ( steamapicontext && steamapicontext->SteamUserStats() )
+ {
+ if ( m_kLeaderboardType == kMapLeaderboard )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->FindLeaderboard( CFmtStr( "contributions_%s", m_pLeaderboardName ) );
+ findLeaderboardCallback.Set( apicall, this, &CLeaderboardInfo::OnFindLeaderboard );
+ }
+ else if ( m_kLeaderboardType == kDuckLeaderboard || m_kLeaderboardType == kDuckStat )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->FindLeaderboard( m_pLeaderboardName );
+ findLeaderboardCallback.Set( apicall, this, &CLeaderboardInfo::OnFindLeaderboard );
+ }
+ else if ( m_kLeaderboardType == kLadderLeaderboard )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->FindLeaderboard( m_pLeaderboardName );
+ findLeaderboardCallback.Set( apicall, this, &CLeaderboardInfo::OnFindLeaderboard );
+ }
+ }
+}
+
+bool CLeaderboardInfo::DownloadLeaderboardData()
+{
+ if ( !findLeaderboardResults.m_bLeaderboardFound )
+ return false;
+
+ if ( m_kLeaderboardType == kMapLeaderboard )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( findLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestGlobal, 1, 5 );
+ downloadLeaderboardCallbackGlobal.Set( apicall, this, &CLeaderboardInfo::OnLeaderboardScoresDownloadedGlobal );
+ apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( findLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -2, 2 );
+ downloadLeaderboardCallbackGlobalAroundUser.Set( apicall, this, &CLeaderboardInfo::OnLeaderboardScoresDownloadedGlobalAroundUser );
+ apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( findLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestFriends, 1, 5 );
+ downloadLeaderboardCallbackFriends.Set( apicall, this, &CLeaderboardInfo::OnLeaderboardScoresDownloadedFriends );
+ return true;
+ }
+
+ if ( m_kLeaderboardType == kDuckLeaderboard )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( findLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestFriends, -6, 6 );
+ downloadLeaderboardCallbackFriends.Set( apicall, this, &CLeaderboardInfo::OnLeaderboardScoresDownloadedFriends );
+ return true;
+ }
+
+ if ( m_kLeaderboardType == kDuckStat )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( findLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestFriends, 0, 0 );
+ downloadLeaderboardCallbackFriends.Set( apicall, this, &CLeaderboardInfo::OnLeaderboardScoresDownloadedFriends );
+ return true;
+ }
+
+ if ( m_kLeaderboardType == kLadderLeaderboard )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( findLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestGlobal, 1, 100 );
+ downloadLeaderboardCallbackGlobal.Set( apicall, this, &CLeaderboardInfo::OnLeaderboardScoresDownloadedGlobal );
+ apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( findLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestFriends, -45, 45 );
+ downloadLeaderboardCallbackFriends.Set( apicall, this, &CLeaderboardInfo::OnLeaderboardScoresDownloadedFriends );
+ return true;
+ }
+
+ return false;
+}
+
+void CLeaderboardInfo::OnFindLeaderboard( LeaderboardFindResult_t *pResult, bool bIOFailure )
+{
+ findLeaderboardResults = *pResult;
+}
+
+void CLeaderboardInfo::OnLeaderboardScoresDownloadedGlobal( LeaderboardScoresDownloaded_t *pResult, bool bIOFailure )
+{
+ RetrieveLeaderboardEntries( *pResult, downloadedLeaderboardScoresGlobal );
+ iNumLeaderboardEntries = steamapicontext->SteamUserStats()->GetLeaderboardEntryCount( findLeaderboardResults.m_hSteamLeaderboard );
+}
+
+void CLeaderboardInfo::OnLeaderboardScoresDownloadedGlobalAroundUser( LeaderboardScoresDownloaded_t *pResult, bool bIOFailure )
+{
+ RetrieveLeaderboardEntries( *pResult, downloadedLeaderboardScoresGlobalAroundUser );
+}
+
+void CLeaderboardInfo::OnLeaderboardScoresDownloadedFriends( LeaderboardScoresDownloaded_t *pResult, bool bIOFailure )
+{
+ RetrieveLeaderboardEntries( *pResult, downloadedLeaderboardScoresFriends );
+ iNumLeaderboardEntries = steamapicontext->SteamUserStats()->GetLeaderboardEntryCount( findLeaderboardResults.m_hSteamLeaderboard );
+ CSteamID localID;
+ if ( steamapicontext && steamapicontext->SteamUser() )
+ {
+ localID = steamapicontext->SteamUser()->GetSteamID();
+ }
+
+ FOR_EACH_VEC( downloadedLeaderboardScoresFriends, i )
+ {
+ if ( downloadedLeaderboardScoresFriends[i]->m_steamIDUser == localID )
+ {
+ if ( m_iMyScore < downloadedLeaderboardScoresFriends[i]->m_nScore )
+ {
+ // First update on finding the leaderboard, any gotten kills need to add to accumulate
+ if ( m_bLeaderboardFound == false )
+ {
+ if ( m_iMyScore > 0 )
+ {
+ m_bHasPendingUpdate = true;
+ }
+ m_iMyScore += downloadedLeaderboardScoresFriends[i]->m_nScore;
+ }
+ else
+ {
+ m_iMyScore = downloadedLeaderboardScoresFriends[i]->m_nScore;
+ }
+ }
+
+ // Use My Saved Score
+ downloadedLeaderboardScoresFriends[i]->m_nScore = m_iMyScore;
+ }
+ }
+
+ downloadedLeaderboardScoresFriends.Sort( &SortLeaderboardVec );
+
+ m_bLeaderboardFound = true;
+}
+
+void CLeaderboardInfo::SetMyScore( int score )
+{
+ m_iMyScore = score;
+
+ if ( !m_bLeaderboardFound )
+ return;
+
+ // Update my leaderboard and resort
+ iNumLeaderboardEntries = steamapicontext->SteamUserStats()->GetLeaderboardEntryCount( findLeaderboardResults.m_hSteamLeaderboard );
+ CSteamID localID;
+ if ( steamapicontext && steamapicontext->SteamUser() )
+ {
+ localID = steamapicontext->SteamUser()->GetSteamID();
+ }
+
+ FOR_EACH_VEC( downloadedLeaderboardScoresFriends, i )
+ {
+ if ( downloadedLeaderboardScoresFriends[i]->m_steamIDUser == localID )
+ {
+ if ( m_iMyScore > downloadedLeaderboardScoresFriends[i]->m_nScore )
+ {
+ // Use My Saved Score
+ downloadedLeaderboardScoresFriends[i]->m_nScore = m_iMyScore;
+ downloadedLeaderboardScoresFriends.Sort( &SortLeaderboardVec );
+ break;
+ }
+ }
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+class CMapInfoContainer : public CAutoGameSystemPerFrame, public CGameEventListener
+{
+public:
+
+ CMapInfoContainer()
+ {
+ memset( &m_findDuelLeaderboardResults, 0, sizeof( m_findDuelLeaderboardResults ) );
+ m_flNextUpdateDuckScoreTime = Plat_FloatTime() + 10.0f;
+#ifdef CLIENT_DLL
+ m_flNextDuckScoresUploadTime = Plat_FloatTime() + tf_duck_upload_rate.GetFloat();
+#endif
+ m_flNextLadderUpdateTime = Plat_FloatTime() + 10.f;
+ }
+
+ virtual char const *Name()
+ {
+ return "CMapInfoContainer";
+ }
+
+ ~CMapInfoContainer()
+ {
+ m_vecMapInfos.PurgeAndDeleteElements();
+ m_downloadedDuelLeaderboardScores_GlobalAroundUser.PurgeAndDeleteElements();
+ m_downloadedDuelLeaderboardScores_Friends.PurgeAndDeleteElements();
+
+ // For ducks
+ m_vecDuckInfo.PurgeAndDeleteElements();
+ // Ladders
+ m_vecLadderLeaderboards.PurgeAndDeleteElements();
+ }
+
+#ifdef CLIENT_DLL
+
+ virtual void LevelShutdownPreEntity()
+ {
+ // upload scores on level leave
+ //DuckUploadPendingScores();
+ }
+
+ // Gets called each frame
+ virtual void Update( float frametime )
+ {
+ if ( m_flNextUpdateDuckScoreTime > 0 && m_flNextUpdateDuckScoreTime < Plat_FloatTime() )
+ {
+ if ( DownloadDuckLeaderboard() )
+ {
+ m_flNextUpdateDuckScoreTime = -1.0f;
+ }
+ }
+
+ if ( m_flNextLadderUpdateTime > 0.f && m_flNextLadderUpdateTime < Plat_FloatTime() )
+ {
+ if ( DownloadLadderLeaderboard() )
+ {
+ m_flNextLadderUpdateTime = -1.f;
+ }
+ }
+
+ // Duck Journal is off, no longer uploading
+ //if ( m_flNextDuckScoresUploadTime < Plat_FloatTime() )
+ //{
+ // // Hard limit the rate players can update scores
+ // float flNextUpdateTime = tf_duck_upload_rate.GetFloat();
+ // if ( DuckUploadPendingScores() )
+ // {
+ // // Request new score
+ // m_flNextUpdateDuckScoreTime = Plat_FloatTime() + 10.0f;
+ // }
+ // // 4x as long if you don't have a Duck Journal
+ // C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
+ // if ( pPlayer )
+ // {
+ // static CSchemaAttributeDefHandle pAttr_DuckLevelBadge( "duck badge level" );
+ // if ( pAttr_DuckLevelBadge )
+ // {
+ // CTFWearable *pActionItem = pPlayer->GetEquippedWearableForLoadoutSlot( LOADOUT_POSITION_ACTION );
+ // // Don't care about the level, just if the attribute is found
+ // if ( pActionItem && FindAttribute( pActionItem->GetAttributeContainer()->GetItem(), pAttr_DuckLevelBadge ) )
+ // {
+ // flNextUpdateTime *= 0.5f;
+ // }
+ // }
+ // }
+ // m_flNextDuckScoresUploadTime = Plat_FloatTime() + flNextUpdateTime;
+ //}
+ }
+#endif // CLIENT_DLL
+
+ //-----------------------------------------------------------------------------
+ // for duels
+ void DownloadDuelLeaderboard()
+ {
+ if ( m_findDuelLeaderboardResults.m_bLeaderboardFound )
+ {
+ // and start downloading the leaderboards
+ // friends
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( m_findDuelLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestFriends, 1, 10 );
+ m_downloadLeaderboardCallback_Friends.Set( apicall, this, &CMapInfoContainer::OnDuelLeaderboardScoresDownloaded_Friends );
+ // global around user
+ apicall = steamapicontext->SteamUserStats()->DownloadLeaderboardEntries( m_findDuelLeaderboardResults.m_hSteamLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -4, 5 );
+ m_downloadLeaderboardCallback_GlobalAroundUser.Set( apicall, this, &CMapInfoContainer::OnDuelLeaderboardScoresDownloaded_GlobalAroundUser );
+ }
+ }
+
+ void OnFindDuelLeaderboard( LeaderboardFindResult_t *pResult, bool bIOFailure )
+ {
+ m_findDuelLeaderboardResults = *pResult;
+ DownloadDuelLeaderboard();
+ }
+
+ void OnDuelLeaderboardScoresDownloaded_GlobalAroundUser( LeaderboardScoresDownloaded_t *pResult, bool bIOFailure )
+ {
+ RetrieveLeaderboardEntries( *pResult, m_downloadedDuelLeaderboardScores_GlobalAroundUser );
+ }
+
+ void OnDuelLeaderboardScoresDownloaded_Friends( LeaderboardScoresDownloaded_t *pResult, bool bIOFailure )
+ {
+ RetrieveLeaderboardEntries( *pResult, m_downloadedDuelLeaderboardScores_Friends );
+ }
+
+ // **************************************************************************************************************************
+ bool DownloadLadderLeaderboard()
+ {
+ bool bDownloading = false;
+ FOR_EACH_VEC( m_vecLadderLeaderboards, i )
+ {
+ bDownloading |= m_vecLadderLeaderboards[i]->DownloadLeaderboardData();
+ }
+ return bDownloading;
+ }
+
+ CLeaderboardInfo *GetLadderLeaderboard( const char *pszName )
+ {
+ FOR_EACH_VEC( m_vecLadderLeaderboards, i )
+ {
+ CLeaderboardInfo *pInfo = m_vecLadderLeaderboards[i];
+ if ( pszName && pInfo && !V_strcmp( pszName, pInfo->GetLeaderboardName() ) )
+ {
+ return pInfo;
+ }
+ }
+
+ return NULL;
+ }
+
+ // **************************************************************************************************************************
+ bool DownloadDuckLeaderboard()
+ {
+ bool bDownloading = false;
+ FOR_EACH_VEC( m_vecDuckInfo, i )
+ {
+ bDownloading |= m_vecDuckInfo[i]->DownloadLeaderboardData();
+ }
+ return bDownloading;
+ }
+
+ CLeaderboardInfo *GetDuckLeaderboard( const char* kName )
+ {
+ FOR_EACH_VEC( m_vecDuckInfo, i )
+ {
+ CLeaderboardInfo *pInfo = m_vecDuckInfo[i];
+ if ( strstr( kName, pInfo->GetLeaderboardName() ) != NULL )
+ {
+ return pInfo;
+ }
+ }
+
+ return NULL;
+ }
+
+ bool DuckUploadPendingScores()
+ {
+ return false;
+
+ //CSteamID localID;
+
+ //if ( !steamapicontext || !steamapicontext->SteamUser() )
+ // return false;
+
+ //localID = steamapicontext->SteamUser()->GetSteamID();
+
+ //bool bUpdatedScores = false;
+ //for ( int i = 0; i < DUCK_NUM_LEADERBOARDS; ++i )
+ //{
+ // CLeaderboardInfo *pLeaderboard = GetDuckLeaderboard( g_szDuckLeaderboardNames[i] );
+ //
+ // if ( pLeaderboard && pLeaderboard->IsLeaderboardFound() && pLeaderboard->HasPendingUpdate() )
+ // {
+ // pLeaderboard->SetHasPendingUpdate( false );
+ // bUpdatedScores = true;
+
+ // int iScoreCheck = RandomInt( INT_MAX / 2, INT_MAX );
+ // // Tell the GC to update our duck contribution
+ // GCSDK::CProtoBufMsg<CGCMsgGC_PlayerDuckLeaderboard_IndividualUpdate> msg( k_EMsgGC_DuckLeaderboard_IndividualUpdate );
+ // msg.Body().set_score( pLeaderboard->GetMyScore() );
+ // msg.Body().set_type( i );
+
+ // MD5Context_t md5Context;
+ // MD5Init( &md5Context );
+ //
+ // AccountID_t unAccountId = localID.GetAccountID();
+ // int nScore = pLeaderboard->GetMyScore();
+
+ // MD5Update( &md5Context, static_cast<const uint8 *>( (void *)&unAccountId ), sizeof( unAccountId ) );
+ // MD5Update( &md5Context, static_cast<const uint8 *>( (void *)&nScore ), sizeof( nScore ) );
+ // MD5Update( &md5Context, static_cast<const uint8 *>( (void *)&i ), sizeof( i ) );
+ // MD5Update( &md5Context, static_cast<const uint8 *>( (void *)&TF_DUCK_ID ), sizeof( TF_DUCK_ID ) );
+ // MD5Update( &md5Context, static_cast<const uint8 *>( (void *)&iScoreCheck ), sizeof( iScoreCheck ) );
+ //
+ // MD5Value_t md5Result;
+ // MD5Final( &md5Result.bits[0], &md5Context );
+ // msg.Body().set_score_id( &md5Result.bits[0], MD5_DIGEST_LENGTH );
+ // msg.Body().set_score_check( iScoreCheck );
+ // GCClientSystem()->BSendMessage( msg );
+ // }
+ //}
+ //return bUpdatedScores;
+ }
+
+ void DuckUpdateScore( int iIncrement, EDuckLeaderboardTypes kLeaderboard )
+ {
+ // Get Current Score
+ CLeaderboardInfo *pLeaderboard = GetDuckLeaderboard( g_szDuckLeaderboardNames[kLeaderboard] );
+ int iCurrentScore = pLeaderboard->GetMyScore();
+ int iNewScore = iCurrentScore + iIncrement;
+
+#ifdef CLIENT_DLL
+ int iOldLevel = iCurrentScore / DUCK_XP_SCALE;
+ int iNewLevel = iNewScore / DUCK_XP_SCALE;
+
+ if ( iNewLevel > iOldLevel )
+ {
+ IGameEvent *event = gameeventmanager->CreateEvent( "duck_xp_level_up" );
+ if ( event )
+ {
+ event->SetInt( "level", iNewLevel );
+ gameeventmanager->FireEventClientSide( event );
+ }
+ }
+#endif
+
+ // Set my new score
+ pLeaderboard->SetMyScore( iNewScore );
+ pLeaderboard->SetHasPendingUpdate( true );
+ }
+
+ //-----------------------------------------------------------------------------
+ virtual bool Init()
+ {
+ ListenForGameEvent( "item_schema_initialized" );
+#ifdef CLIENT_DLL
+ HOOK_MESSAGE( EOTLDuckEvent );
+#endif // CLIENT_DLL
+ return true;
+ }
+
+ virtual void FireGameEvent( IGameEvent *event )
+ {
+ if ( Q_strcmp( event->GetName(), "item_schema_initialized" ) != 0 )
+ return;
+
+ for ( int i = 0; i < GetItemSchema()->GetMapCount(); i++ )
+ {
+ CLeaderboardInfo *pInfo = new CLeaderboardInfo( GetItemSchema()->GetMasterMapDefByIndex( i )->pszMapName );
+ pInfo->m_kLeaderboardType = kMapLeaderboard;
+ m_vecMapInfos.AddToTail( pInfo );
+
+ const MapDef_t *pMapDef = GetItemSchema()->GetMasterMapDefByName( pInfo->GetLeaderboardName() );
+ if ( pMapDef && pMapDef->IsCommunityMap() )
+ {
+ // retrieve leaderboard info
+ pInfo->RetrieveLeaderboardData();
+ }
+ }
+
+ // find duel leaderboards
+ if ( steamapicontext && steamapicontext->SteamUserStats() )
+ {
+ SteamAPICall_t apicall = steamapicontext->SteamUserStats()->FindLeaderboard( "duel_wins" );
+ m_findLeaderboardCallback.Set( apicall, this, &CMapInfoContainer::OnFindDuelLeaderboard );
+ }
+
+ // find duck leaderboards
+ for ( int i = 0; i < DUCK_NUM_LEADERBOARDS; i++ )
+ {
+ CLeaderboardInfo *pInfo = new CLeaderboardInfo( g_szDuckLeaderboardNames[ i ] );
+ pInfo->m_kLeaderboardType = i == 0 ? kDuckLeaderboard : kDuckStat;
+ m_vecDuckInfo.AddToTail( pInfo );
+
+ // retrieve leaderboard info
+ pInfo->RetrieveLeaderboardData();
+ }
+
+ // Ladder
+ for ( int i = 0; i < LADDER_LEADERBOARDS_MAX; i++ )
+ {
+ CLeaderboardInfo *pInfo = new CLeaderboardInfo( g_szLadderLeaderboardNames[i] );
+ pInfo->m_kLeaderboardType = kLadderLeaderboard;
+ m_vecLadderLeaderboards.AddToTail( pInfo );
+
+ // retrieve leaderboard info
+ pInfo->RetrieveLeaderboardData();
+ }
+ }
+
+public:
+
+ CUtlVector< CLeaderboardInfo* > m_vecMapInfos;
+ // for duels
+ CCallResult< CMapInfoContainer, LeaderboardFindResult_t > m_findLeaderboardCallback;
+ CCallResult< CMapInfoContainer, LeaderboardScoresDownloaded_t > m_downloadLeaderboardCallback_GlobalAroundUser;
+ CCallResult< CMapInfoContainer, LeaderboardScoresDownloaded_t > m_downloadLeaderboardCallback_Friends;
+ LeaderboardFindResult_t m_findDuelLeaderboardResults;
+ CUtlVector< LeaderboardEntry_t* > m_downloadedDuelLeaderboardScores_GlobalAroundUser;
+ CUtlVector< LeaderboardEntry_t* > m_downloadedDuelLeaderboardScores_Friends;
+
+ // For ducks
+ CUtlVector< CLeaderboardInfo* > m_vecDuckInfo;
+ float m_flNextUpdateDuckScoreTime;
+ float m_flNextDuckScoresUploadTime;
+
+ // Ladders
+ CUtlVector< CLeaderboardInfo* > m_vecLadderLeaderboards;
+ float m_flNextLadderUpdateTime;
+};
+CMapInfoContainer gMapInfoContainer;
+
+static CLeaderboardInfo *FindMapInfo( const char *pMapName )
+{
+ FOR_EACH_VEC( gMapInfoContainer.m_vecMapInfos, i )
+ {
+ CLeaderboardInfo *pInfo = gMapInfoContainer.m_vecMapInfos[i];
+ if ( strstr( pMapName, pInfo->GetLeaderboardName() ) != NULL )
+ return pInfo;
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+
+bool Leaderboards_GetDuelWins( CUtlVector< LeaderboardEntry_t* > &scores, bool bGlobal )
+{
+ if ( gMapInfoContainer.m_findDuelLeaderboardResults.m_bLeaderboardFound )
+ {
+ if ( bGlobal )
+ {
+ scores = gMapInfoContainer.m_downloadedDuelLeaderboardScores_GlobalAroundUser;
+ }
+ else
+ {
+ scores = gMapInfoContainer.m_downloadedDuelLeaderboardScores_Friends;
+ }
+ return true;
+ }
+ return false;
+}
+//-----------------------------------------------------------------------------
+// DUCKS
+void Leaderboards_GetDuckLeaderboardSteamIDs( CUtlVector< AccountID_t > &vecIds )
+{
+ vecIds.RemoveAll();
+ FOR_EACH_VEC( gMapInfoContainer.m_vecDuckInfo, i )
+ {
+ FOR_EACH_VEC( gMapInfoContainer.m_vecDuckInfo[i]->downloadedLeaderboardScoresFriends, iEntry )
+ {
+ vecIds.AddToHead( gMapInfoContainer.m_vecDuckInfo[i]->downloadedLeaderboardScoresFriends[iEntry]->m_steamIDUser.GetAccountID() );
+ }
+ }
+}
+
+bool Leaderboards_GetDuckLeaderboard( CUtlVector< LeaderboardEntry_t* > &scores, const char* kName )
+{
+ CLeaderboardInfo *pLeaderboard = gMapInfoContainer.GetDuckLeaderboard( kName );
+ if ( pLeaderboard && pLeaderboard->IsLeaderboardFound() )
+ {
+ scores = pLeaderboard->downloadedLeaderboardScoresFriends;
+ return true;
+ }
+ return false;
+}
+
+int Leaderboards_GetDuckLeaderboardTotalEntryCount( const char* kName )
+{
+ CLeaderboardInfo *pLeaderboard = gMapInfoContainer.GetDuckLeaderboard( kName );
+ if ( pLeaderboard )
+ {
+ return pLeaderboard->iNumLeaderboardEntries;
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// DUCK Collected Message from Server
+void __MsgFunc_EOTLDuckEvent( bf_read &msg )
+{
+#ifdef CLIENT_DLL
+ CBasePlayer *pLocalPlayer = CBasePlayer::GetLocalPlayer();
+ if ( !pLocalPlayer )
+ return;
+
+ if ( TFGameRules() && TFGameRules()->HaveCheatsBeenEnabledDuringLevel() )
+ return;
+
+ // IsCreated, ID of Creator, ID of Victim, Count, IsGolden
+ int iIsCreated = (int)msg.ReadByte();
+ int iCreatorId = (int)msg.ReadByte();
+ int iVictimId = (int)msg.ReadByte();
+ int iToucherId = (int)msg.ReadByte();
+ int iDuckTeam = (int)msg.ReadByte();
+ int iCount = (int)msg.ReadByte();
+ int iDuckFlags = (int)msg.ReadByte();
+
+ iDuckTeam = 0;
+ iVictimId = 0;
+ //iDuckFlags = 0;
+
+ CBasePlayer *pCreator = UTIL_PlayerByIndex( iCreatorId );
+ //CBasePlayer *pVictim = UTIL_PlayerByIndex( iVictimId );
+ CBasePlayer *pToucher = UTIL_PlayerByIndex( iToucherId );
+
+ if ( !pCreator )
+ {
+ iDuckFlags |= DUCK_FLAG_OBJECTIVE;
+ }
+ // If you were picked up, you need a toucher
+ if ( iIsCreated == 0 && pToucher )
+ {
+ // if I picked them up
+ if ( pToucher == pLocalPlayer )
+ {
+ // Offense
+ if ( pCreator && pCreator->GetTeamNumber() == pLocalPlayer->GetTeamNumber() )
+ {
+ gMapInfoContainer.DuckUpdateScore( iCount, TF_DUCK_SCORING_PERSONAL_PICKUP_OFFENSE );
+ gMapInfoContainer.DuckUpdateScore( iCount * DUCK_XP_WEIGHT_OFFENSE, TF_DUCK_SCORING_OVERALL_RATING );
+ }
+ //defense
+ else if ( pCreator && pCreator->GetTeamNumber() != pLocalPlayer->GetTeamNumber() )
+ {
+ gMapInfoContainer.DuckUpdateScore( iCount, TF_DUCK_SCORING_PERSONAL_PICKUP_DEFENDED );
+ gMapInfoContainer.DuckUpdateScore( iCount * DUCK_XP_WEIGHT_DEFENSE, TF_DUCK_SCORING_OVERALL_RATING );
+ }
+
+ // objective
+ if ( iDuckFlags & DUCK_FLAG_OBJECTIVE )
+ {
+ gMapInfoContainer.DuckUpdateScore( iCount, TF_DUCK_SCORING_PERSONAL_PICKUP_OBJECTIVE );
+ gMapInfoContainer.DuckUpdateScore( iCount* DUCK_XP_WEIGHT_OBJECTIVE, TF_DUCK_SCORING_OVERALL_RATING );
+ }
+
+ // bonus
+ if ( iDuckFlags & DUCK_FLAG_BONUS )
+ {
+ gMapInfoContainer.DuckUpdateScore( iCount, TF_DUCK_SCORING_PERSONAL_BONUS_PICKUP );
+ gMapInfoContainer.DuckUpdateScore( iCount* DUCK_XP_WEIGHT_BONUS, TF_DUCK_SCORING_OVERALL_RATING );
+ }
+ }
+ // Teammate picks up a duck I made
+ else if ( pCreator && pCreator == pLocalPlayer && pCreator->GetTeamNumber() == pToucher->GetTeamNumber() )
+ {
+ gMapInfoContainer.DuckUpdateScore( iCount, TF_DUCK_SCORING_TEAM_PICKUP_MY_DUCKS );
+ gMapInfoContainer.DuckUpdateScore( iCount * DUCK_XP_WEIGHT_TEAMMATE, TF_DUCK_SCORING_OVERALL_RATING );
+ }
+ }
+ // Duck Created
+ else if ( iIsCreated != 0 )
+ {
+ // If this is the same as local player
+ if ( pLocalPlayer == pCreator )
+ {
+ gMapInfoContainer.DuckUpdateScore( iCount, TF_DUCK_SCORING_PERSONAL_GENERATION );
+ gMapInfoContainer.DuckUpdateScore( iCount * DUCK_XP_WEIGHT_GENERATION, TF_DUCK_SCORING_OVERALL_RATING );
+ }
+ }
+
+#endif
+}
+//-----------------------------------------------------------------------------
+
+void Leaderboards_Refresh()
+{
+ gMapInfoContainer.DownloadDuelLeaderboard();
+ gMapInfoContainer.DownloadDuckLeaderboard();
+ gMapInfoContainer.DownloadLadderLeaderboard();
+}
+
+void MapInfo_RefreshLeaderboard( const char *pMapName )
+{
+ CLeaderboardInfo *pInfo = FindMapInfo( pMapName );
+ if ( pInfo )
+ {
+ pInfo->DownloadLeaderboardData();
+ }
+}
+
+bool MapInfo_GetLeaderboardInfo( const char *pMapName, CUtlVector< LeaderboardEntry_t* > &scores, int &iNumLeaderboardEntries, uint32 unMinScores )
+{
+ CLeaderboardInfo *pInfo = FindMapInfo( pMapName );
+ if ( pInfo && pInfo->findLeaderboardResults.m_bLeaderboardFound )
+ {
+ if ( (uint32)pInfo->downloadedLeaderboardScoresFriends.Count() >= unMinScores )
+ {
+ scores = pInfo->downloadedLeaderboardScoresFriends;
+ }
+ else if ( (uint32)pInfo->downloadedLeaderboardScoresGlobalAroundUser.Count() >= unMinScores )
+ {
+ scores = pInfo->downloadedLeaderboardScoresGlobalAroundUser;
+ }
+ else
+ {
+ scores = pInfo->downloadedLeaderboardScoresGlobal;
+ }
+ iNumLeaderboardEntries = pInfo->iNumLeaderboardEntries;
+ return true;
+ }
+ return false;
+}
+
+static const char *FindMapNameForContributionDefinitionIndex( item_definition_index_t unContribDefIndex )
+{
+ for ( int i = 0; i < GetItemSchema()->GetMapCount(); i++ )
+ {
+ const MapDef_t* pMapDef = GetItemSchema()->GetMasterMapDefByIndex( i );
+ if ( pMapDef->mapStampDef && pMapDef->mapStampDef->GetDefinitionIndex() == unContribDefIndex )
+ return pMapDef->pszMapName;
+ }
+ return NULL;
+}
+
+bool MapInfo_DidPlayerDonate( uint32 unAccountID, const char *pLevelName )
+{
+ if ( steamapicontext == NULL || steamapicontext->SteamUser() == NULL )
+ return false;
+
+ CSteamID localSteamID = steamapicontext->SteamUser()->GetSteamID();
+ CSteamID steamID = localSteamID;
+ steamID.SetAccountID( unAccountID );
+
+ GCSDK::CGCClientSharedObjectCache *pSOCache = GCClientSystem()->GetSOCache( steamID );
+ if ( pSOCache == NULL )
+ return false;
+
+ GCSDK::CGCClientSharedObjectTypeCache *pTypeCache = pSOCache->FindTypeCache( CTFMapContribution::k_nTypeID );
+ if ( pTypeCache == NULL )
+ return false;
+
+ char pchBaseMapName[ MAX_PATH ];
+ Q_FileBase( pLevelName, pchBaseMapName, sizeof(pchBaseMapName) );
+
+ for ( uint32 i = 0; i < pTypeCache->GetCount(); ++i )
+ {
+ CTFMapContribution *pMapContribution = (CTFMapContribution*)( pTypeCache->GetObject( i ) );
+
+ const char *pszMapName = FindMapNameForContributionDefinitionIndex( pMapContribution->Obj().def_index() );
+ if ( pszMapName && FStrEq( pszMapName, pchBaseMapName ) )
+ return true;
+ }
+ return false;
+}
+
+int MapInfo_GetDonationAmount( uint32 unAccountID, const char *pLevelName )
+{
+ if ( steamapicontext == NULL || steamapicontext->SteamUser() == NULL )
+ return 0;
+
+ CSteamID localSteamID = steamapicontext->SteamUser()->GetSteamID();
+ CSteamID steamID = localSteamID;
+ steamID.SetAccountID( unAccountID );
+
+ GCSDK::CGCClientSharedObjectCache *pSOCache = GCClientSystem()->GetSOCache( steamID );
+ if ( pSOCache == NULL )
+ return 0;
+
+ GCSDK::CGCClientSharedObjectTypeCache *pTypeCache = pSOCache->FindTypeCache( CTFMapContribution::k_nTypeID );
+ if ( pTypeCache == NULL )
+ return 0;
+
+ char pchBaseMapName[ MAX_PATH ];
+ Q_FileBase( pLevelName, pchBaseMapName, sizeof(pchBaseMapName) );
+
+ for ( uint32 i = 0; i < pTypeCache->GetCount(); ++i )
+ {
+ CTFMapContribution *pMapContribution = (CTFMapContribution*)( pTypeCache->GetObject( i ) );
+
+ const char *pszMapName = FindMapNameForContributionDefinitionIndex( pMapContribution->Obj().def_index() );
+ if ( pszMapName && FStrEq( pszMapName, pchBaseMapName ) )
+ return pMapContribution->Obj().contribution_level();
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Ladders
+//-----------------------------------------------------------------------------
+bool Leaderboards_GetLadderLeaderboard( CUtlVector< LeaderboardEntry_t* > &scores, const char *pszName, bool bGlobal )
+{
+ CLeaderboardInfo *pLeaderboard = gMapInfoContainer.GetLadderLeaderboard( pszName );
+ if ( pLeaderboard && pLeaderboard->IsLeaderboardFound() )
+ {
+ scores = bGlobal ? pLeaderboard->downloadedLeaderboardScoresGlobal : pLeaderboard->downloadedLeaderboardScoresFriends;
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+void Leaderboards_LadderRefresh( void )
+{
+ gMapInfoContainer.DownloadLadderLeaderboard();
+}