If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Development:Team Fortress 2

From The Cutting Room Floor
Jump to navigation Jump to search

This page details development materials of Team Fortress 2.

How about a nice leek in this trying time?
This page or section details content from the April 22nd, 2020 Team Fortress 2 Source Code Leak.
This article is a work in progress.
...Well, all the articles here are, in a way. But this one moreso, and the article may contain incomplete information and editor's notes.
To do:

TF2CutContent's To Do:

Notes for other editors wanting to help: The three main folders you'll be looking through if you want to help with this, are:

These are where the Team Fortress 2-specific code is. If you're specifically looking for Staging Build content, search #ifdef STAGING_ONLY for just the specific staging blocks of code.

On April 22nd, 2020, the source code for numerous Source Engine games leaked online. This included the source code for a build of Team Fortress 2 dated around August 3rd, 2017. This code had previously been leaked at some point in 2018, but it received more widespread attention when it leaked again in April. Within this build's source code, staging build code was found that gave a window into many things Valve was testing internally throughout the past few years.

Staging Build Content

This section will detail code found within staging code blocks.


Located in tf_shareddefs.cpp and tf_shareddefs.h, within an enumerator of condition flags for players is a block of staging conditions for experimental content.

Speed Pad Speed Boost

First up we have TF_COND_NO_COMBAT_SPEED_BOOST, labelled with a dev comment as STAGING_ENGY. This is a condition that was used for the experimental Speed Pad building upgrade.

Tranq Gun Boost & Marked

Next we have TF_COND_TRANQ_SPY_BOOST, a condition for the revived Tranquilizer Gun and/or DNA Gun (which itself is a new version of the Tranq Gun). When applied to the player, this condition seems to apply a weapon deployment speed increase to the attacker.

Sticking with the Tranquilizer Gun, we have TF_COND_TRANQ_MARKED up next. This condition is permanently applied to the player being attacked until they die. The target's movement speed is also momentarily slowed and a small amount of viewpunch is used to simulate flinching.

Space Gravity

Up next, TF_COND_SPACE_GRAVITY. This is a remnant from the early development of rd_asteroid when the map was planned to have low gravity in the exterior areas, but normal gravity within the interiors of the bases. It can be determined that this was for rd_asteroid as the internal name for the sound to transition between low and normal gravity is listed as RD.SpaceGravityTransition. This condition is commented out, and most code related to it in other files is also commented out. For example, this block of code within the CTFPlayer::TFPlayerThink function has been commented out. This block of code seems to show the initial functionality of the jetpack where players could seemingly just jump and be jetpacked, using some of their "space jump charge". This block of code also shows the names of several cut convars for controlling aspects of the jetpacking;

  • tf_space_thrust_use_rate - Controls the minimum % of charge required to thrust.
  • tf_space_thrust_recharge_rate - Controls the rate at which the thrust charge recharges.
  • tf_space_thrust_scout - Controls the upward thrust velocity for this class. Same goes for the rest of the convars in this list.
  • tf_space_thrust_sniper
  • tf_space_thrust_soldier
  • tf_space_thrust_demo
  • tf_space_thrust_medic
  • tf_space_thrust_heavy
  • tf_space_thrust_pyro
  • tf_space_thrust_spy
  • tf_space_thrust_engy

The jetpack from this early state of rd_asteroid was later repurposed into the Thermal Thruster jetpack for the Pyro. However, of note is the original HUD icon for the Thermal Thruster was based on an entirely different jetpack model called the Furious Flyer. It would appear that this jetpack could have been considered to be the model used for the generic all-class jetpack before it was changed and a new model was picked. The HUD icon was later updated to properly reflect the chosen model.

Concussion Grenade v2 - Self Conc

Next, we have TF_COND_SELF_CONC. Pretty obvious what this condition was for. But it's commented out. When given the condition after being hit by your own Concussion Grenade, it would have given you "phase attachments" which are attachments used for the Scout after drinking Bonk! Atomic Punch and Demoman during charging with a shield. This was done to make you more visible to enemies as a penalty, according to this bit of code in the CTFProjectile_ConcGrenade::Explode function.

Phase Cloaking Watch - Phase Stealthed

Next, we have TF_COND_STEALTHED_PHASE. This was a condition used for the experimental Phase Cloaking Watch for the Spy. According to some staging code found in the CTraceFilterObject::ShouldHitEntity function, the Phase Cloaking Watch's cloak allowed the Spy to walk through any object or other player. If you uncloaked while inside an object, you would be telefragged. Phase cloaking also gave the player a slight speed boost and a screen overlay of some variety.

Clip Overload

Next, we have TF_COND_CLIP_OVERLOAD. According to the code, this condition would give players 1000 primary and secondary ammo, 1000 metal, and 1000 GRENADES1, GRENADES2 and GRENADES3 ammo. It also would refill weapon clips. It is unclear what this condition was meant for as it isn't actually used anywhere.

DNA Gun - Class Steal

Finally, we have TF_COND_SPY_CLASS_STEAL. This condition was meant for the second attempt to revive the Tranquilizer Gun, under the name "DNA Gun". The condition is added to the attacker as part of the DNA Gun's body-stealing gimmick.

Throwable Weapons

Entity Classname: tf_projectile_throwable

Throwable weapons are already a thing in Team Fortress 2. The Self-Aware Beauty Mark and Mutated Milk are classed as throwables in the code (tf_projectile_throwable_breadmonster). However, there are a few other throwable weapons within staging code blocks that Valve were testing.

Located in tf_weapon_throwable.cpp is a staging block of code defining different throwable weapon types based on different slots;

CREATE_SIMPLE_WEAPON_TABLE( TFThrowablePrimary, tf_weapon_throwable_primary )
CREATE_SIMPLE_WEAPON_TABLE( TFThrowableSecondary, tf_weapon_throwable_secondary )
CREATE_SIMPLE_WEAPON_TABLE( TFThrowableMelee, tf_weapon_throwable_melee )
CREATE_SIMPLE_WEAPON_TABLE( TFThrowableUtility, tf_weapon_throwable_utility )

Of particular note is the tf_weapon_throwable_utility. The Utility Slot is a concept that comes up several times in the source code.

(Source: game/shared/tf/tf_weapon_throwable.cpp)

Also located in tf_weapon_throwable.cpp are the following snippets of code for several experimental throwable weapons;

Target Dummy

Entity Classname: tf_projectile_target_dummy

The throwable Target Dummy is a remarkably simple throwable. You throw it and out pops a plywood target dummy to distract the enemy.

At the point in time this code is from, the target dummy that got spawned was restricted to either models/props_training/target_engineer.mdl or models/props_training/target_demoman.mdl. Within tf_target_dummy.cpp, specifically the CTFTargetDummy::Spawn function, there is a developer comment stating // TODO: Model Selection. It seems that it may have been intended for the target dummy the switch model to match the class of the player who threw it.

Concussion Grenade

Entity Classname: tf_projectile_grenade_concussion

Functionally similar to the original Concussion Grenade. If you were to compare the original Concussion Grenade's code to the tf_weapon_throwable.cpp version, you can see there are some differences in their code. Especially between CTFGrenadeConcussionProjectile::Explode and CTFProjectile_ConcGrenade::Explode.

Teleport Grenade

Entity Classname: tf_projectile_grenade_teleport

The Teleport Grenade does exactly what it says in the name. Throw it and get teleported to where it lands.

Gravity/Chain Grenade

Entity Classname: tf_projectile_grenade_gravity
To do:
What else does this do? Just suck the enemy into it?

This grenade goes by Gravity Grenade most of the time. There is one instance where it is labelled as Chain Grenade and it's when this grenade is declared at the top of tf_weapon_throwable.cpp;

The grenade, when activated, would draw nearby enemies in closer to the center of it.

Throwing Knife

Entity Classname: tf_projectile_throwing_knife

Throwing knives like in Goldeneye 007! What is interesting about this throwable is its use of CreateStickyAttachmentToTarget(). This is the function that allows certain projectiles to stick out of players, like arrows or syringes.

Smoke Grenade

Entity Classname: tf_projectile_grenade_smoke

A standard smoke grenade. Possibly a revival of the early Smoke Bomb/Gas Grenade to go with the scrapped Spy vs Engineer WAR update. Not really much to say. Would have given the TF_COND_OBSCURED_SMOKE condition to the player so this seems to have been intended for the Spy.

Non-Staging Build Content

Anything interesting, but not within STAGING_ONLY blocks, will be in this section.

Birthday Tag Gamemode

There is a fair bit of code related to a Birthday Tag gamemode although the "Birthday Tag" name is unofficial, made up for the purpose of this article. The way this mode would have worked is that one player would be picked to be the "Birthday Player" and would be given particle effects to denote them as such. If the Birthday Player kills another player, the victim becomes the Birthday Player. None of this code is in staging blocks, and so would be functional ingame if the majority of the code for it was not commented out. However, since the code for this mode is quite simple, it should not be very hard to recreate with a SourceMod plugin for community servers. According to the various logic checks in this, this gamemode was seemingly meant to become active during the kHoliday_TFBirthday holiday (when the Birthday mode gets enabled ingame). The code for this mode seems to have been based off of the "It!" code for the Horseless Headless Horsemann boss.

The particle effects that would have been used to denote the Birthday Player, as seen in the C_TFPlayer:ShowBirthdayEffect function, were:

  • birthday_player_circling, attached to the player's head and set to follow the player.
  • bday_confetti. It is unclear where this effect was meant to display on the player. The function used to create this effect, DispatchParticleEffect, indicates the attachment point to be GetAbsOrigin() + Vector(0,0,32) which is the player's current standing position, with an adjustment on the Z axis of 32 units. The next parameter however is vec3_angle which is not defined anywhere. According to the actual parameters of the DispatchParticleEffect function, the 3rd parameter should be CBaseEntity *pEntity and not a vector.

Relevant Code:

Throwable Weapons

Going back to tf_weapon_throwable.cpp, there are two throwable weapons listed in the code that are not in STAGING_ONLY blocks. These two throwables are a fair bit old as well, having been in the game for quite some time. Not entirely sure when specifically these entities were added but results can be found on Google from as far back as 2014 when searching for tf_projectile_throwable_repel or tf_projectile_throwable_brick.


A throwable airblast. It is unknown when this was first added to the game, but it had been known about for several years before the source code leak occurred. If being ubercharged by a Medic wielding the Quick Fix, you would be immune to the Repel.

Entity Classname: tf_projectile_throwable_repel



A throwable brick. Like in TimeSplitters: Future Perfect! Functions exactly as you'd expect. Hit someone with it, they get a bit of viewpunch. It is not known when the Brick was first added to the engine, nor what it was intended for.

Entity Classname: tf_projectile_throwable_brick


Experimental Weapons

Some experimental weapons can be found via references in the source code.

Sticky Ball Launcher

Only appearing as two internal weapon names (one for the weapon, one for the projectile) found within the enum ETFWeaponType enumerator in tf_shareddefs.cpp, nothing else is known about this weapon.

Going off of its position in the enumerator, and when it was added to the SourceMod tf2_stocks.inc file, it appears that the Sticky Ball Launcher was added to the game some time in 2012.


Dispenser Gun

Nothing is known about the Dispenser Gun, as the only bit of code for it is the internal weapon name TF_WEAPON_DISPENSER_GUN, found within the enum ETFWeaponType enumerator in tf_shareddefs.cpp and tf_shareddefs.h.

Going off of its position in the enumerator, and when it was added to the SourceMod tf2_stocks.inc file, it appears that the Dispenser Gun was added to the game some time in 2010, possibly within the Engineer Update as it is listed after TF_WEAPON_LASER_POINTER which is the string name for the Engineer's Wrangler weapon which was added in that update. It would appear that the Dispenser Gun weapon string is actually for the Big Mean Mother Hubbard which is described in promotional artwork from the Polycount Contest as a gun that dispenses things.


The Decoy is a Spy weapon that was in development at some point in time, but didn't make the cut. Going off some code in game/shared/tf/tf_weapon_decoy.h, we can see it was meant as a Spy weapon. We can also see that the Decoy weapon, in the code, is inheriting functionalities from CTFJar, meaning this could have been a thrown weapon similar to Jarate or the Flying Guillotine. The Decoy's internal weapon name is TF_WEAPON_LIFELINE, but according to a dev comment in tf_weapon_decoy.h, that internal name was potentially not final.

Upon being thrown, the Decoy would spawn a clone of the player who threw it. That clone player would continue on down the same direction the player was running in. This can be seen in the code in game/server/tf/bot_npc/bot_npc_decoy.cpp, where the Decoy's bot is taking information from its owner to set up the require class model, disguise, etc, as well as also grabbing information about its owner's velocity, eye angles, etc.

Entity Classname: tf_weapon_decoy


Item Attributes

Several experimental or otherwise unused item attributes exist in the code.

Disguise as Dispenser

First discovered via the existence of the unused TF_COND_DISGUISED_AS_DISPENSER condition flag, this condition turned out to be for an unused item attribute; disguise_as_dispenser_on_crouch. Within the CTFPlayer::TFPlayerThink() function is a bit of code designed to run only when:

  • You are a Spy
  • You are crouching
  • You have an item with the disguise_as_dispenser_on_crouch attribute on it

If these conditions are met, your player model is swapped to that of a Dispenser.

A major benefit to this disguise is that Sentry Guns won't shoot you.

if ( GetPlayerClass()->GetClassIndex() == TF_CLASS_SPY && ( GetFlags() & FL_DUCKING ) && ( pGroundEntity != NULL ) )
	int nDisguiseAsDispenserOnCrouch = 0;
	CALL_ATTRIB_HOOK_FLOAT( nDisguiseAsDispenserOnCrouch, disguise_as_dispenser_on_crouch );
	if ( nDisguiseAsDispenserOnCrouch != 0 )
		m_Shared.AddCond( TF_COND_DISGUISED_AS_DISPENSER, 0.5f );