Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sr2echa/TF2-Source-Code/llms.txt

Use this file to discover all available pages before exploring further.

TF2’s achievement system is client-side and event-driven. Each achievement is a C++ class inheriting from CBaseAchievement (or the TF2-specific CBaseTFAchievement). Achievements listen to game events, track progress counters, and call AwardAchievement() when their unlock conditions are met. Completion is persisted via the Steam Stats and Achievements API.

Base achievement classes

// game/shared/tf/achievements_tf.h
class CBaseTFAchievementSimple : public CBaseAchievement
{
public:
    virtual bool LocalPlayerCanEarn();        // blocks MvM achievements in normal play, etc.
    virtual void FireGameEvent( IGameEvent *event );
};

class CBaseTFAchievement : public CBaseTFAchievementSimple
{
public:
    virtual bool LocalPlayerCanEarn();        // adds class check
};

// For achievements requiring a full round
class CTFAchievementFullRound : public CBaseTFAchievement
{
public:
    virtual void ListenForEvents();
    virtual void Event_OnRoundComplete( float flRoundTime, IGameEvent *event ) = 0;
};

Achievement file organization

Achievements are split by class into separate .cpp files under game/shared/tf/:
FileContent
achievements_tf_scout.cppScout achievements (Bonk! etc.)
achievements_tf_soldier.cppSoldier achievements
achievements_tf_pyro.cppPyro achievements
achievements_tf_demoman.cppDemoman achievements
achievements_tf_heavy.cppHeavy achievements
achievements_tf_engineer.cppEngineer achievements
achievements_tf_medic.cppMedic achievements
achievements_tf_sniper.cppSniper achievements
achievements_tf_spy.cppSpy achievements
achievements_tf_halloween.cppHalloween event achievements
achievements_tf_mvm.cppMann vs. Machine achievements
achievements_tf_maps.cppMap-specific achievements
achievements_tf_replay.cppReplay system achievements

Event-driven tracking

Achievements subscribe to game events via ListenForEvents() and implement FireGameEvent(). Progress is tracked with IncrementCount() or SetCount().
// Example: tracking kills with a specific weapon
class CAchievement_TF_Soldier_KillWithDirectHit : public CBaseTFAchievement
{
    void Init()
    {
        SetFlags( ACH_SAVE_GLOBAL );
        SetGoal( 3 );   // need 3 direct hits
    }
    void ListenForEvents()
    {
        ListenForGameEvent( "player_death" );
    }
    void FireGameEvent( IGameEvent *event )
    {
        if ( !IsLocalTFPlayerClass( TF_CLASS_SOLDIER ) ) return;
        // check attacker == local player, weapon == direct hit rocket
        // then IncrementCount();
    }
};

Steam stat synchronization

CAchievementMgr (game/shared/achievementmgr.cpp) manages the full lifecycle. On map load it pulls stats from Steam; on achievement unlock it calls ISteamUserStats::SetAchievement() and schedules a StoreStats() call. Progress counters map to Steam stat names defined in the app’s Steamworks configuration.
The achievement_debug 1 console command (client-side) enables verbose logging of achievement event processing, showing which events are firing and whether conditions are met — useful when modding or studying the system.

Build docs developers (and LLMs) love