Development:Team Fortress 2/April 21st, 2020 Codebase Leak
This is a sub-page of Development:Team Fortress 2.
This page or section details content from the April 22nd, 2020 Source Engine Codebase 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:
|
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 early 2016, from the Tough Break update. 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.
While most companies would go the route of issuing takedowns for leaks of this nature, Valve has adopted a more liberal stance where once something has been leaked, they don't attempt to issue takedowns. Investigations into the leaks do occur, but again, takedowns do not occur.
Contents
- 1 Sub-Pages
- 2 Birthday Tag Gamemode
- 3 Item Attributes
- 4 Mann vs. Machine
- 4.1 Scrapped Canteen Types and Features
- 4.2 Medigun Heal Buildings ability
- 4.3 Disabled SMG Headshot Ability
- 4.4 Unused Canteen Specialist cost reducing formula
- 4.5 Scrapped MvM Upgrade
- 4.6 Unused MvM difficulty
- 4.7 Scrapped Death Sounds
- 4.8 Alternate Buyback
- 4.9 Unused starting cash bonus feature
- 4.10 Unused Upgrades
- 4.11 Unused MvM Tank Event
- 5 Unused Dispenser Healing Target Count Limitation
- 6 Mini-Dispenser
- 7 Unused Teleporter Explosion Damage feature
- 8 Spy Traps
- 9 Scrapped Teleporter variants
- 10 Unused "bonus_round" event
- 11 Unused Lunchbox restoring ammo behavior
- 12 References
Sub-Pages
Condition Flags |
Weapons |
Game Modes |
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 in-game 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:
- C_TFPlayer::ShowBirthdayEffect
- Purpose: Displays an icon denoting this player as the Birthday Player to the local player.
- CTFGameRules::SetBirthdayPlayer
- Purpose: Sets current Birthday Player.
- *GetBirthdayPlayer
- Purpose: Returns current Birthday Player. This is a class function, part of class CTFGameRules : public CTeamplayRoundBasedRules.
- Calls to GetBirthdayPlayer and SetBirthdayPlayer, found within CTFPlayer::Event_Killed.
- This event is triggered whenever a player is killed. As such, this code is what determines who the new Birthday Player is.
- Setting up the receive proxy for the m_hBirthdayPlayer property.
- Setting up the send proxy for the m_hBirthdayPlayer property.
- This property is used to keep track of the user ID of the current Birthday Player.
- Resetting the Birthday Player via SetBirthdayPlayer, found within CTFGameRules::SetupOnRoundStart.
- Resetting the Birthday Player via SetBirthdayPlayer, found within CTFGameRules::SetWinningTeam.
- Resetting the m_hBirthdayPlayer property within the CTFGameRules::CTFGameRules function.
- Resetting the m_bShouldShowBirthdayEffect boolean within the C_TFPlayer::C_TFPlayer function.
- Disabling the Birthday effect, found within the C_TFPlayer:SetDormant function.
- Determining whether or not to display the Birthday effect, found within the C_TFPlayer::OnDataChanged function.
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 ); } }
Mann vs. Machine
Scrapped Canteen Types and Features
During MvM's development, initially there were up to seven types of canteen charges available for mercenaries to use. Only five of them (crits, uber, upgrade, ammo and teleporting to spawn) arrived to release version.
The sixth canteen type is internally called RADIUS_STEALTH and included into most lists of canteen types even without STAGING_ONLY tag (though _DEBUG_tag can be seen once). This canteen would be available only for Spy[1]. Jugding by code comments, this charge would apply invisibility effect, and not only on player which activated this charge, but also to nearby players.
The seventh canteen type is internally called SEE_CASH_THROUGH_WALL. Its mentions are always under STAGING_ONLY tag. The effect of this canteen is clear from its name - it would allow to see currency piles through obstacles. The real mystery is amount of mercenaries affected by this charge. There are indications in game code that the initial ability to see cash through walls was innate for Scout and Spy, and unused sound files about picking money for Heavy and Medic might be strong indications that SEE_CASH_THROUGH_WALL was intended to be applied on ALL players.
Additionally, the Canteen Specialist upgrade would increase maximum canteen charges from 3 to 6, which isn't included in final game.
// Default canteen has 3 charges. Medic canteen specialist allows purchasing 3 more charges. // If anything else increases max charges, we need to refactor how canteen specialist is handled. Assert( iMaxNumCharges >= 0 && iMaxNumCharges <= 6 ); iMaxNumCharges = Min( iMaxNumCharges, 6 );
Medigun Heal Buildings ability
Some remnants of code that would allow Medic's Medigun to heal buildings, present in medigun.cpp. There are also hints that it would supposed to be either MvM-exclusive feature or upgrade for this gamemode.
#ifdef STAGING_ONLY if ( TFGameRules() && TFGameRules()->GameModeUsesUpgrades() ) { if ( IsAttachedToBuilding() ) { // Heal building if ( m_hHealingTarget->GetHealth() < m_hHealingTarget->GetMaxHealth() ) { CBaseEntity *pEntity = m_hHealingTarget; CBaseObject *pObject = dynamic_cast<CBaseObject*>( pEntity ); if ( pObject ) { pObject->SetHealth( m_hHealingTarget->GetHealth() + ( GetHealRate() / 10.f ) ); } } } } #endif // STAGING_ONLY
Disabled SMG Headshot Ability
Located in tf_weapon_smg.cpp, this code would allow SMG to deal various damage depending on certain body part which has been damaged (retail game uses only critical damage upon headshots). This feature is disabled because of g_aWeaponDamageTypes variable not having DMG_USE_HITLOCATIONS attribute for SMG and Carbine Cleaner. If added, headshots work as well as with all Sniper's primaries (add link to Sigsegv's old video about it).
int CTFSMG::GetDamageType( void ) const { if ( CanHeadshot() ) { int iDamageType = BaseClass::GetDamageType() | DMG_USE_HITLOCATIONS; return iDamageType; } return BaseClass::GetDamageType();
Unused Canteen Specialist cost reducing formula
A formula for Canteen Specialist upgrade that reduces cost on 10% per one upgrade tick.
// iCost *= ( 1.f - ( iCanteenSpec * 0.1f ) ); // iCost = Max( 1, ( iCost - ( iCost % 5 ) ) );
Scrapped MvM Upgrade
There's commented code that hints about some kind of mass-stealth upgrade for MvM. Nothing similar was added in retail version of the game.
// An upgrade in MvM grants AE stealth where the player can fire // while in stealth, and for a short period after it drops if ( enemy->m_Shared.InCond( TF_COND_STEALTHED_USER_BUFF_FADING ) )
Unused MvM difficulty
A code chunk that describes difficulty feature in MvM. According to this code, 5 difficulty levels were supposed to be added, and they would change only two parameters - HP and damage of robots. Icons labeled "mvm_difficulty" can be found within the game's files. [3]
void MVMSkillChangedCallback( IConVar *pVar, const char *pOldString, float flOldValue ) { ConVarRef cVarRef( pVar ); // Testing the effects of skill setting float flHealth = 1.f; // Health modifier for bots float flDamage = 1.f; // Damage modifier in bot vs player switch ( cVarRef.GetInt() ) { case 1: { flHealth = 0.75f; flDamage = 0.75f; break; } case 2: { flHealth = 0.9f; flDamage = 0.9f; break; } // "Normal" case 3: { flHealth = 1.f; flDamage = 1.f; break; } case 4: { flHealth = 1.10f; flDamage = 1.10f; break; } case 5: { flHealth = 1.25f; flDamage = 1.25f; break; } } tf_populator_health_multiplier.SetValue( flHealth ); tf_populator_damage_multiplier.SetValue( flDamage ); } ConVar tf_mvm_skill( "tf_mvm_skill", "3", FCVAR_DONTRECORD | FCVAR_REPLICATED | TF_MVM_FCVAR_CHEAT, "Sets the challenge level of the invading bot army. 1 = easiest, 3 = normal, 5 = hardest", true, 1, true, 5, MVMSkillChangedCallback );
There might be a possibility that leveled attributes added into TF2 code in 07.2010 are linked with these difficulty levels. In that case, these levels were initially planned for Creep Mode, judging by the date of adding leveled attributes (as headers of source code point, the most early MvM-related date is 05.2011, and Creep Mode was in development in 2010).
Scrapped Death Sounds
Sound cache code reveals that during development of Mann vs Machine, every class would emit unique death sounds. The retail version of MvM only plays a standard death sound for everyone.[4]
void CPopulationManager::Precache( void ) { PrecacheScriptSound( "music.mvm_end_wave" ); PrecacheScriptSound( "music.mvm_end_tank_wave" ); PrecacheScriptSound( "music.mvm_end_mid_wave" ); PrecacheScriptSound( "music.mvm_end_last_wave" ); PrecacheScriptSound( "MVM.PlayerUpgraded" ); PrecacheScriptSound( "MVM.PlayerBoughtIn" ); PrecacheScriptSound( "MVM.PlayerUsedPowerup" ); PrecacheScriptSound( "MVM.PlayerDied" ); PrecacheScriptSound( "MVM.PlayerDiedScout" ); PrecacheScriptSound( "MVM.PlayerDiedSniper" ); PrecacheScriptSound( "MVM.PlayerDiedSoldier" ); PrecacheScriptSound( "MVM.PlayerDiedDemoman" ); PrecacheScriptSound( "MVM.PlayerDiedMedic" ); PrecacheScriptSound( "MVM.PlayerDiedHeavy" ); PrecacheScriptSound( "MVM.PlayerDiedPyro" ); PrecacheScriptSound( "MVM.PlayerDiedSpy" ); PrecacheScriptSound( "MVM.PlayerDiedEngineer" );
Alternate Buyback
An alternative buyback method for the MvM game mode is mentioned in game code. According to it, buybacks could be not, well, buybacks, but limited "charges", three per each round. [5]
// New system (finite buybacks per-wave, not currency-based) if ( tf_mvm_buybacks_method.GetBool() ) { if ( g_pPopulationManager->GetNumBuybackCreditsForPlayer( this ) ) { bSuccess = true; iCost = 1; g_pPopulationManager->RemoveBuybackCreditFromPlayer( this );
There are also several mentions of players losing currency after death, which is absent in final game.
Unused starting cash bonus feature
MvM developers were intended to encourage players to play outside lobbies by increasing starting currency value per 20% for every unique lobby in the team, starting from second. This would lead to 100% starting currency bonus to the team with random players only, and no bonus to 6-player lobby at all. This feature is under STAGING_ONLY tag.
#ifdef STAGING_ONLY // only calculate lobby bonus one time when the lobby first match to the server CMatchInfo *pMatch = GTFGCClientSystem()->GetMatch(); if ( pMatch && GetWaveNumber() == 0 && m_nLobbyBonusCurrency == 0 ) { // Count unique parties CUtlVector<uint64> vecPartyIDs; int total = pMatch->GetNumTotalMatchPlayers(); for ( int idx = 0; idx < total; idx++ ) { uint64 uPartyID = pMatch->GetMatchDataForPlayer( idx )->uPartyID; if ( vecPartyIDs.Find( uPartyID ) == vecPartyIDs.InvalidIndex() ) { vecPartyIDs.AddToTail( uPartyID ); } } int nUniqueParties = vecPartyIDs.Count(); // give some bonus currency for each extra unique party in the lobby float flBonusScale = tf_mvm_mm_bonus.GetFloat() * ( nUniqueParties - 1 ); m_nLobbyBonusCurrency = flBonusScale * m_nStartingCurrency; } #endif // STAGING_ONLY
Unused Upgrades
There are mentions of several unusual upgrades for Mann vs Machine game mode under STAGING_ONLY tag [6]. Internal effect numbers of these upgrades are absent in effect number list of release TF2 version. Unlike all upgrades in release version (except Medigun Specialist), they were intended to affect more than one mercenary parameter and seem to be much more general, overall.
#ifdef STAGING_ONLY case 555: // medigun specialist { static UpgradeAttribBlock_t upgradeBlock[] = { { "healing mastery", 4.f, LOADOUT_POSITION_SECONDARY }, { "overheal expert", 4.f, LOADOUT_POSITION_SECONDARY }, { "uber duration bonus", 4.f, LOADOUT_POSITION_SECONDARY }, { "ubercharge rate bonus", 2.f, LOADOUT_POSITION_SECONDARY }, }; ApplyUpgradeAttributeBlock( upgradeBlock, ARRAYSIZE( upgradeBlock ), pTFPlayer, bDowngrade ); } break;
Medigun Specialist upgrade differs from the release one. They both have Healing Mastery parameter, which is conbined as well and consists of healing rate and self-regenerating rate, but unused one also has Overheal Expert, Uber Duration Bonus and Ubercharge Rate Bonus included, which are all used in release game as separate upgrades.
case 605: // master sniper { static UpgradeAttribBlock_t upgradeBlock[] = { { "projectile penetration", 1.f, LOADOUT_POSITION_PRIMARY }, { "SRifle Charge rate increased", 1.5f, LOADOUT_POSITION_PRIMARY }, { "faster reload rate", 0.6f, LOADOUT_POSITION_PRIMARY }, }; ApplyUpgradeAttributeBlock( upgradeBlock, ARRAYSIZE( upgradeBlock ), pTFPlayer, bDowngrade ); } break;
master sniper seems to be general enhancement of Sniper's primary weapon and uses attributed that are used in final version as separate upgrades.
According to another code snippets from various game files, "Master Sniper" upgrade would have 2 tiers and give Sniper's primary weapon penetration ability [7], reload speed boost (0.6 rate multiplier for tier 1 and 0.3 for tier 2) [8] [9], as well as charge speed boost for sniper rifles (1.5 multiplier for tier 1 and 3 for tier 2) [10]. Tier 1 stats are the same with the ones from upgrades.cpp file.
case 611: // airborne infantry { static UpgradeAttribBlock_t upgradeBlock[] = { { "increased air control", 10.f, LOADOUT_POSITION_PRIMARY }, { "rocket launch impulse", 1, LOADOUT_POSITION_PRIMARY }, { "cancel falling damage", 1, LOADOUT_POSITION_PRIMARY }, }; ApplyUpgradeAttributeBlock( upgradeBlock, ARRAYSIZE( upgradeBlock ), pTFPlayer, bDowngrade ); } break;
airborne infantry is something new and surprising. None of its three parameters are used in final as MvM upgrades, and in fact one of them (rocket launch impulse) seems to be completely cut from the game. Judging by attribute names, it was supposed to help Soldier maneuver better while mid-air.
case 624: // construction expert { static UpgradeAttribBlock_t upgradeBlock[] = { { "build rate bonus", 0.7f, LOADOUT_POSITION_MELEE }, { "maxammo metal increased", 1.5f, LOADOUT_POSITION_INVALID }, { "engy building health penalty", 0.7f, LOADOUT_POSITION_MELEE }, }; ApplyUpgradeAttributeBlock( upgradeBlock, ARRAYSIZE( upgradeBlock ), pTFPlayer, bDowngrade ); } break;
construction expert (intended clearly for Engineer) consists of one parameter that is used in MvM as upgrade (maxammo metal increased), one paramter that is used not as upgrade but rather as attribute for weapons,in particular, Jag(build rate bonus), and one parameter that seems to be removed from the final version of the game (engy building health penalty).
case 626: // support engineer { static UpgradeAttribBlock_t upgradeBlock[] = { { "teleporter recharge rate bonus", 0.5f, LOADOUT_POSITION_INVALID }, { "teleporter speed boost", 1, LOADOUT_POSITION_INVALID }, { "bidirectional teleport", 1, LOADOUT_POSITION_INVALID }, { "dispenser rate bonus", 1.25f, LOADOUT_POSITION_INVALID }, { "engy dispenser radius increased", 3.f, LOADOUT_POSITION_INVALID }, }; ApplyUpgradeAttributeBlock( upgradeBlock, ARRAYSIZE( upgradeBlock ), pTFPlayer, bDowngrade ); } break; #endif // STAGING_ONLY
Another Engineer overall upgrade includes two parameter that are used in final game as separate upgrades ("bidirectional teleport" and "engy dispenser radius increased") and three other parameters that seem to be removed from the final game. The purpose of tho of them ("teleporter recharge rate bonus" and "dispenser rate bonus") is comprehensive from their names - they would increase teleporter recharge speed (from 3 seconds to 1,5 in case of lvl 3 teleporter) and speed of health and ammo dispensing from dispenser, though it's unclear whether interval between dispensing or amount of health ammo would be affected. The last parameter, "teleporter speed boost", is something special. Most likely it's effect from scrapped Speed Pad building, which would grant temporary speed boost (similar to the one from Soldier's Disiplinary Action of Concheror), but unlike that case, this upgrade most probably wouldn't remove teleport ability in favor to simply add speed boosting effect to everyone who touched upgraded teleporter.
There are also simple mentions of some scrapped upgrades in gamerules.cpp file[11], along with indications which class it belong to. Only these ones mentioned that haven't mentioned in previous section.
case 483: // "medic machinery beam"
Most likely was intended for Medic's upgrade which would allowed him to "heal" buidings.
case 523: // "arrow mastery"
Could be chained with aforementioned Sniper Mastery upgrade.
#ifdef STAGING_ONLY case 601: // "ability spy traps" case 603: // "phase cloak" #endif // STAGING_ONLY { return ( pPlayer->IsPlayerClass( TF_CLASS_SPY ) && iWeaponID == TF_WEAPON_BUILDER ); } break;
Spy Traps are scrapped Spy ability\upgrade for MvM and "phase cloak" was intended for one of scrapped Spy watches, though here this attribute is tied with Spy's PDA, which was intended for using Spy Traps.
case 440: // "clip size upgrade atomic" { return pWeapon && pWeapon->IsBlastImpactWeapon(); } break;
case 604: // sniper cloak case 605: // master sniper { return ( pPlayer->IsPlayerClass( TF_CLASS_SNIPER ) && iWeaponSlot == TF_WPN_TYPE_PRIMARY );
case 631: // ability doubletap teleport { return ( pPlayer->IsPlayerClass( TF_CLASS_SCOUT ) && iWeaponSlot == TF_WPN_TYPE_PRIMARY );
Unused MvM Tank Event
There's code for some kind of damage indications ("FireOutput") for MvM tank, and just like with boss_alpha, every 10% HP loss would create such an indication. [12]
Unused Dispenser Healing Target Count Limitation
There's line in game code which defines maximum number of healing targets for a dispenser. While it's technically used, the value of this parameter is 32, which is maximum possible player number in server, therefore this parameter doesn't limit anything.
#define MAX_DISPENSER_HEALING_TARGETS 32
Mini-Dispenser
(everything is from \tf2\server\tf\tf_obj_dispenser.cpp and \tf2\server\tf\tf_obj_dispenser.h, except metal capacity)
The idea of alternate dispenser, in particular - mini-version of it, just like Mini-Sentry, was already implemented by TF2 community (Workshop) long time ago by creating the model of it. Source code reveals that Valve at some time was testing this idea as well, and they even thought to use this model from Workshop in the game! It would supposed to have 70 metal cost and 100 health, providing healing with 10 units per second and replenish 20% of ammo, just like level 1 Dispenser (but ammo dispensing would be twice as fast, every 0.5 seconds). Metal capacity would be halved, only 200 metal.[14]
While the original idea of Workshop creator was ability of building two mini-dispensers instead of one, Valve developers were thinking the other way, more classical. Some bits of commented out code show that mini-dispenser would able to explode after destruction, just like in Team Fortress Classic. The value of damage from explosion and its radius would depend from current metal count in dispenser, 50 damage with 150 HU radius from 0 metal, proportionally graduating up to 300 damage with 200 HU explosion from max metal capacity (200).
(Do I really need to link all this stuff to source code lines by using references?)
Unused Teleporter Explosion Damage feature
There's a single string in teleporter.cpp which indicates that Teleporter buiding would supposed to deal minor damage upon destruction (exploding)[15]. It is unclear though, what exact conditions would bring such damage type and to what team. It could be damage to teammates that stand on\near Teleporter when it is destructed by the enemy team, or damage to enemy team by manually Teleporter exploding via destruction PDA, or something else.
#define BUILD_TELEPORTER_DAMAGE 25 // how much damage an exploding teleporter can do
Spy Traps
Spy Traps are buildings that would supposed to be placed by RED Spy in Mann vs Machine game mode [16]. Their placeholder model is standart Engineer teleporter. All of them would suppose to exist limited time and self-destruct when this time is expired.
Three types of Spy Traps present in game code [17] - RADIUS_STEALTH, MAGNET and REPROGRAMMER, plus the fourth - REPULSOR, that exist as only a single mention in the code. Their names explain theirself;
* RADIUS_STEALTH would grant all nearby (within 250 HU range) teammates 2 second of invisibility;
* MAGNET would attract all robots within 700 HU radius and direct visibility to itself with significant force (650);
* REPROGRAMM would turn every robot but giant that touched it into mercenaries side. Robots under this condition are supposed to move twice as faster.[18]
Expiration time (not official TF2 short movie) would be different for all trap types - 20 seconds for REPROGRAMMED, 10 second for RADIUS_STEALTH and only 5 for MAGNET.
Scrapped Teleporter variants
TF2 developers were concerned about alternate teleporters as well as dispensers, although it wasn't just "mini-" variant, just Mini-Sentry or Mini-Dispenser, but two more different concepts. It is unknown whether the ability of Teleporter variations to, well, teleport teammates, is still presumed to exist.
Speed Pad
The first one - Speed Pad, also referred as "Speed Teleporter"[19] would supposed to grant temporary speed boost effect[20] (similar to Disciplinary Action or Concheror one) to any teammate player who touched it. This building would be cheaper than standard Teleporter on 25 metal[21], which equals 100 metal before July 7, 2016 patch of Meet Your Match update and 25 after it, and also would be influenced by teleporter build and upgrade cost modifiers, such as Eureka Effect one[22]. Upgrade cost is also reduced to fixed (and therefore not influenced by any teleporter upgrade cost modifiers) 100 metal[23]. Upgrade level would affect recharge time[24] and effect duration[25]:
Buiding level | Recharge time | Effect duration |
---|---|---|
1 | 1,67 | 4 |
2 | 1,33 | 5 |
3 | 1 | 6 |
This building was referenced in a modification to the code|tf/scripts/game_sounds_weapons.txt file in the August 12, 2014 patch of End of the Line update. The following code was added to the file:
// ------------------------------------------------------------------------------------ // // SPEEDPAD // ------------------------------------------------------------------------------------ // "Building_Speedpad.Boost" { "channel" "CHAN_STATIC" "volume" "1.0" "soundlevel" "SNDLVL_74dB" "wave" ")weapons/speed_pad.wav" }
Catapult
The second one - Catapult - was intended to throw player into the air.[26] The interesing moment is that, according to in-code comment, this code was copied from Portal 2 and then modified. In fact, Team Fortress 2.fgb file has the entire copy-pasted Portal 2 Catapult code chunk, which additionally proves this comment.
Building speed for this teleporter type is increasesd 4 times (approximately 5.2 seconds) when constructed and 7 times (3 seconds) when redeployed.[27]
000 HU\s.
Unused "bonus_round" event
For some reason there's little of code that allows to spawn MONOCULUS! as "bonus_boss" in "bonus_round".[28]. It is under STAGING_ONLY tag.
The exact usage of this is unknown. This code stored in population manager file, which is used for MvM purposes, but also contains some Raid Mode remnants. MONOCULUS! was added only in 27 October 2011, so there's very little possibility that it was supposed for Raid Mode, or specifically, Boss Battle Mode (the earliest MvM files are dated May 2011). Perhaps it was supposed to be a part of 666 wave on Ghost Town map (Nightmare difficulty, Caliginous Caper mission).
Unused Lunchbox restoring ammo behavior
There's unused code[29] that would allow Lunchbox type weapons (such as Sandwich or Dalokosh Bar) to restore ammo.
// Restore ammo if applicable if ( nLunchBoxType == LUNCHBOX_ADDS_AMMO ) { int maxPrimary = pPlayer->GetMaxAmmo( TF_AMMO_PRIMARY ); pPlayer->GiveAmmo( maxPrimary * 0.25, TF_AMMO_PRIMARY, true ); } }
References
- ↑ game/shared/tf/tf_gamerules.cpp, line 20959
- ↑ game/server/tf/bot/tf_bot_vision.cpp, line 279
- ↑ game/server/tf/player_vs_environment/tf_population_manager.cpp, line 106
- ↑ game/server/tf/player_vs_environment/tf_population_manager.cpp, line 518
- ↑ game/server/tf/tf_player.cpp, line 7254
- ↑ game/server/tf/player_vs_environment/tf_upgrades.cpp, line 682
- ↑ game/shared/tf/tf_weaponbase.cpp, line 1398
- ↑ game/shared/tf/tf_weapon_compound_bow.cpp, line 570
- ↑ game/shared/tf/tf_weapon_sniperrifle.cpp, line 647
- ↑ game/shared/tf/tf_weapon_sniperrifle.cpp, line 704
- ↑ game/shared/tf/tf_gamerules.cpp, line 21062
- ↑ game/server/tf/player_vs_environment/tf_base_boss.cpp, line 524
- ↑ game/shared/tf/tf_shareddefs.h, line 1344
- ↑ game/shared/tf/tf_shareddefs.h, line 1345
- ↑ game/server/tf/tf_obj_teleporter.cpp, line 71
- ↑ game/shared/tf/tf_player_shared.cpp, line 4573
- ↑ game/server/tf/tf_obj_spy_trap.cpp
- ↑ game/shared/tf/tf_player_shared.cpp, line 10558
- ↑ game/server/tf/tf_obj_teleporter.cpp, line 655
- ↑ game/server/tf/tf_obj_teleporter.cpp, line 653
- ↑ game/shared/tf/tf_player_shared.cpp, line 11001
- ↑ game\shared\tf\tf_player_shared.cpp, line 11010
- ↑ game/server/tf/tf_obj_teleporter.cpp, line 334
- ↑ game/server/tf/tf_obj_teleporter.cpp, line 756
- ↑ game/server/tf/tf_obj_teleporter.cpp, line 749
- ↑ game/shared/tf/trigger_catapult_shared.cpp
- ↑ game/server/tf/tf_player.cpp, line 7971
- ↑ game/server/tf/player_vs_environment/tf_population_manager.cpp, line 1093
- ↑ shared/tf/tf_weapon_lunchbox.cpp, line 370