Team Fortress 2 Source Code as on 22/4/2020
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

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