//----------------------------------------------------------------------------- // Purpose: sets the specified component bit # if it is not already. // If it does get set, evaluate if this satisfies an achievement //----------------------------------------------------------------------------- void CBaseAchievement::EnsureComponentBitSetAndEvaluate( int iBitNumber ) { Assert( iBitNumber < 64 ); // this is bit #, not a bit mask if ( IsAchieved() ) return; // calculate which bit this component corresponds to uint64 iBitMask = ( (uint64) 1 ) << iBitNumber; // see if we already have gotten this component if ( 0 == ( iBitMask & m_iComponentBits ) ) { if ( !AlwaysEnabled() && !m_pAchievementMgr->CheckAchievementsEnabled() ) { Msg( "Achievements disabled, ignoring achievement component for %s\n", GetName() ); return; } // new component, set the bit and increment the count SetComponentBits( m_iComponentBits | iBitMask ); if ( m_iCount != m_iGoal ) { // save our state at the next good opportunity m_pAchievementMgr->SetDirty( true ); if ( cc_achievement_debug.GetInt() ) { Msg( "Component %d for achievement %s found\n", iBitNumber, GetName() ); } ShowProgressNotification(); } } else { if ( cc_achievement_debug.GetInt() ) { Msg( "Component %d for achievement %s found, but already had that component\n", iBitNumber, GetName() ); } } // Check to see if we've achieved our goal even if the bit is already set // (this fixes some older achievements that are stuck in the 9/9 state and could never be evaluated) Assert( m_iCount <= m_iGoal ); if ( m_iCount == m_iGoal ) { // all components found, award the achievement (and save state) AwardAchievement(); } }
//----------------------------------------------------------------------------- // Purpose: called when an event that counts toward an achievement occurs //----------------------------------------------------------------------------- void CBaseAchievement::IncrementCount( int iOptIncrement ) { if ( !IsAchieved() && LocalPlayerCanEarn() ) { if ( !AlwaysEnabled() && !m_pAchievementMgr->CheckAchievementsEnabled() ) { Msg( "Achievements disabled, ignoring achievement progress for %s\n", GetName() ); return; } // on client, where the count is kept, increment count if ( iOptIncrement > 0 ) { // user specified that we want to increase by more than one. m_iCount += iOptIncrement; if ( m_iCount > m_iGoal ) { m_iCount = m_iGoal; } } else { m_iCount++; } // if this achievement gets saved w/global state, flag our global state as dirty if ( GetFlags() & ACH_SAVE_GLOBAL ) { m_pAchievementMgr->SetDirty( true ); } if ( cc_achievement_debug.GetInt() ) { Msg( "Achievement count increased for %s: %d/%d\n", GetName(), m_iCount, m_iGoal ); } #ifndef NO_STEAM // if this achievement's progress should be stored in Steam, set the steam stat for it if ( StoreProgressInSteam() && steamapicontext->SteamUserStats() ) { // Set the Steam stat with the same name as the achievement. Only cached locally until we upload it. char pszProgressName[1024]; Q_snprintf( pszProgressName, 1024, "%s_STAT", GetStat() ); bool bRet = steamapicontext->SteamUserStats()->SetStat( pszProgressName, m_iCount ); if ( !bRet ) { DevMsg( "ISteamUserStats::GetStat failed to set progress value in Steam for achievement %s\n", pszProgressName ); } m_pAchievementMgr->SetDirty( true ); } #endif // if we've hit goal, award the achievement if ( m_iGoal > 0 ) { if ( m_iCount >= m_iGoal ) { AwardAchievement(); } else { HandleProgressUpdate(); } } } }