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.

Every weapon in TF2 descends from CBaseCombatWeapon (the Source engine base) through a three-level hierarchy defined in game/shared/tf/tf_weaponbase.h. The tree splits at CTFWeaponBase into ranged (CTFWeaponBaseGun) and melee (CTFWeaponBaseMelee) branches, with a grenade sub-branch for throwable weapons.

Inheritance tree

CBaseCombatWeapon
└── CTFWeaponBase          (tf_weaponbase.h)
    ├── CTFWeaponBaseGun   (tf_weaponbase_gun.h)
    ├── CTFWeaponBaseMelee (tf_weaponbase_melee.h)
    └── CTFWeaponBaseGrenade
            └── CTFWeaponBaseGrenadeProj
On the client, CTFWeaponBase is aliased to C_TFWeaponBase via a preprocessor define so the same header compiles for both DLLs.

CTFWeaponBase — the root class

CTFWeaponBase inherits from both CBaseCombatWeapon and IHasOwner. On the client it also extends CGameEventListener. Its declaration from tf_weaponbase.h:
#if defined( CLIENT_DLL )
class CTFWeaponBase : public CBaseCombatWeapon, public IHasOwner, public CGameEventListener
#else
class CTFWeaponBase : public CBaseCombatWeapon, public IHasOwner
#endif
{
    DECLARE_CLASS( CTFWeaponBase, CBaseCombatWeapon );
    DECLARE_NETWORKCLASS();
    DECLARE_PREDICTABLE();
    // ...
    CTFWeaponInfo const &GetTFWpnData() const;
    virtual int GetWeaponID( void ) const;
    virtual int GetDamageType() const { return g_aWeaponDamageTypes[ GetWeaponID() ]; }
    virtual int GetMaxClip1( void ) const;
    virtual bool UsesPrimaryAmmo();
};

Weapon data parsing

Each weapon’s stats are stored in a CTFWeaponInfo struct (from tf_weapon_parse.h) loaded from script files. GetTFWpnData() returns a const reference to this parsed data, which includes projectile type, damage, fire rate, and per-mode data via GetWeaponData(m_iWeaponMode).

Reload state machine

Single-shell reload weapons (e.g. shotguns) use a four-state enum defined in tf_weaponbase.h:
enum
{
    TF_RELOAD_START = 0,
    TF_RELOADING,
    TF_RELOADING_CONTINUE,
    TF_RELOAD_FINISH
};

Charge-up interface

Weapons that charge before firing implement ITFChargeUpWeapon:
class ITFChargeUpWeapon
{
public:
    virtual bool  CanCharge( void ) = 0;
    virtual float GetChargeBeginTime( void ) = 0;
    virtual float GetChargeMaxTime( void ) = 0;
    virtual float GetCurrentCharge( void )
    {
        return ( gpGlobals->curtime - GetChargeBeginTime() ) / GetChargeMaxTime();
    }
};

CTFWeaponBaseGun — ranged weapons

Defined in tf_weaponbase_gun.h, this class handles all projectile and hitscan fire:
class CTFWeaponBaseGun : public CTFWeaponBase
{
public:
    virtual void       PrimaryAttack();
    virtual void       SecondaryAttack( void );
    virtual CBaseEntity *FireProjectile( CTFPlayer *pPlayer );
    virtual void       FireBullet( CTFPlayer *pPlayer );
    CBaseEntity       *FireRocket( CTFPlayer *pPlayer, int iRocketType = 0 );
    CBaseEntity       *FireNail( CTFPlayer *pPlayer, int iSpecificNail );
    virtual CBaseEntity *FirePipeBomb( CTFPlayer *pPlayer, int iPipeBombType );
    CBaseEntity       *FireFlare( CTFPlayer *pPlayer );
    virtual CBaseEntity *FireArrow( CTFPlayer *pPlayer, ProjectileType_t projectileType );
    virtual CBaseEntity *FireEnergyBall( CTFPlayer *pPlayer, bool bRing = false );
};
FireProjectile dispatches to the correct helper (FireRocket, FireBullet, FireArrow, etc.) based on GetWeaponProjectileType(), which reads from the parsed weapon data.

CTFWeaponBaseMelee — melee weapons

Defined in tf_weaponbase_melee.h, melee weapons always report HasPrimaryAmmo() = true and resolve hits via a swing trace:
class CTFWeaponBaseMelee : public CTFWeaponBase
{
public:
    virtual void  PrimaryAttack();
    virtual bool  DoSwingTrace( trace_t &trace );
    virtual void  Smack( void );
    virtual void  DoMeleeDamage( CBaseEntity *ent, trace_t &trace );
    virtual float GetMeleeDamage( CBaseEntity *pTarget, int *piDamageType, int *piCustomDamage );
    virtual void  OnEntityHit( CBaseEntity *pEntity, CTakeDamageInfo *info );
    virtual int   GetSwingRange( void );
    virtual bool  CalcIsAttackCriticalHelper( void );
};
Smack() is the deferred hit callback: it fires after the swing animation starts and calls DoSwingTrace to find targets in range.

Ammo types

IsAmmoType(int iAmmoType, const char *pAmmoName) (declared in tf_weaponbase.h) compares an integer ammo index against a string name. Ammo types are registered in the game rules and referenced by weapon scripts; common types include TF_AMMO_PRIMARY, TF_AMMO_SECONDARY, and TF_AMMO_METAL (for the Engineer).

Build docs developers (and LLMs) love