You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
849 lines
28 KiB
849 lines
28 KiB
//========= 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(); |
|
}
|
|
|