Team Fortress 2

Team Fortress 2

145 ratings
MvM - Advanced Popfile Techniques
By Mince and 8 collaborators
A reference detailing lesser known tips and tricks of popfile creation.

This guide assumes you have a basic familiarity with popfile syntax. If you do not, these resources may point you in the right direction:
https://hydrogen-mvm.github.io/TitaniumTank/pdf/Pop_File_Guide.pdf - [Link deprecated]
https://drive.google.com/file/d/17UJ-O0H7yL6lEPNLDESOB5rXctRDj-hK/view?usp=sharing - [Syntax guide]
https://gtm.you1.cn/sharedfiles/filedetails/?id=1451627628 - [Mission design guide. (mostly?)]
https://gist.github.com/sigsegv-mvm/9ce39744fde2aa4c6156 - [Valid popfile keyvalues reference; for intermediate users.]
https://wiki.teamfortress.com/wiki/List_of_item_attributes - [Valid item attributes list.]

The contents of this guide are collaboratively brought to you by the (possibly retired) content creators of the Potato's Custom MvM group. If you appreciated what we prepared, you can favourite or award us to motivate us.
5
   
Award
Favorite
Favorited
Unfavorite
Weapons/Cosmetics on any Robot Class
All robot classes can be equipped with wearable weapons not intended for them such as Soldier’s banners, Sniper’s backpack weapons, the B.A.S.E. Jumper and Soldier’s Gunboats and Mantreads.

The same can be done for cosmetics, allowing diverse and occasionally humorous combinations. For instance, a Medic-bot can be equipped with the U-clank-a, a hat only intended for the Heavy.

Example:
TFBot { Class Scout Skill Normal Attributes SpawnWithFullCharge Item "The Buff Banner" CharacterAttributes { "increase buff duration" 191 } }
Non-Soldier robots with extended duration banners will have to have the attribute "increase buff duration" within CharacterAttributes instead of ItemAttributes. Note that these same robots cannot gain rage from damaging players.

Be aware that certain weapons cannot be given to some bots at the same time, such as Gunboats and B.A.S.E. Jumper.

WARNING: Sniper bots equipped with Banners will cause the game to crash! This has been fixed by a recent patch!

Robots cannot be equipped with the following weapons:
  • All-class stock melee reskins (such as Frying Pan and Ham Shank)
  • Multi-class shotguns (Reserve Shooter, Panic Attack)
  • Soldier/Demo shared weapons DO work (pain train, half-zatoichi)

In-game Example: A Giant Scout with Sniper's Corona Australis and two Heavies with Concherors
Spy-bots with Primaries
Spies don't actually have a primary, and interestingly, will make use of their new primaries! The reason is that Spies's revolvers are considered as secondaries, even though the Revolver is accessed through pressing the "Equip Primary" key. (or the "slot0" command)

Spy-bots are selective with primary weapon usage, but they commonly use primaries in ons scenario: While going for a backstab, enemy has seen through our disguise. (Unless low on health, then keep running from enemies till we're sure they forgot about us.)

Be warned, ths trick has technical "gotchas"! These things can unexpected make Spy-bots stop working as intended:
  • "ItemAttributes" can't apply attributes on the Spy bots's new primary, use "CharactetAttributes" as a workaround that.
  • Their A.I. motives has drastically changed, such as:
    • Fetching the bomb and trying to deploy it. (also trying to dispel REDs during it)
    • Being forced to use Sniper A.I. (this trick is somewhere below the guide, no rush)

Example:
Mission { Objective Spy Where spawnbot_mission_spy BeginAtWave 1 RunForThisManyWaves 1 InitialCooldown 20 CooldownTime 35 DesiredCount 1 TFBot { Template T_TFBot_Spy Skill Normal Item "The Backburner" } }

Video Example:

Additional notes regarding Spy-bots and primary weapons:
  1. Animations
    • Spy-bots while undisguised normally refpose, which is expected, but somewhat unexpectedly is the Shortstop re-using his Revolver anims.
      • If they're disguised, the class they picked may make use of actual animations.
    • Sometimes weapons have non-standard firing animations, which can make Spy-bots's currently dosguised class refpose. (this is bad if you don't want them to unknowningly blow their cover)
      • Example weapons: Pomson 6000, Huntsman, Cow Mangler 5000, Soda Popper/Force-a-Nature.
  2. Combat - General
    • Spy-bots keep their disguise on when attacking with either Flamethrowers or Grenade Launchers.
    • Spy-bots also won't lose their disguise from Sniper Rifles scoping or Miniguns revving, but also won't make them refpose, and depending on the class, show actual animations! This can help the Spy-bot convincingly confuse players.
  3. Combat - Behaviors
    • For unknown reasons, Spy-bots never attack with a Dragon's Fury.
    • Spy-bots will predict enemy movement when using Rocket Launchers or Grenade Launchers, similar to Soldier-bots or Demo-bots.
Enabling Mmmph on Phlogistinator Pyros
Pyro-bots equipped with the Phlogistinator will only activate their Mmmph crits when they taunt as the bomb carrier (as a result of a kill or upgrading their bomb carrier level). To circumvent this, and to provide another avenue for the Pyro-bots to activate their crits, you can use the "airblast disabled" 0 item attribute to force them to try and reflect projectiles by right clicking, which in turn activates their Mmmph (their A.I. prevents this by default with the Phlogistinator equipped).

Be sure to have the Skill of the Pyro-bot above Easy, as Easy skill Pyro-bots do not attempt to airblast.

Example:
T_TFBot_Pyro_Phlog { Class Pyro Skill Normal WeaponRestrictions PrimaryOnly Attributes SpawnWithFullCharge Item "The Phlogistinator" ItemAttributes { ItemName "The Phlogistinator" "airblast disabled" 0 } }

Video Example:
Vaccinator Medic-bots
While Medic-bots can be equipped with the Vaccinator (which causes them to reuse Vaccinator effects exclusive to robots) and function normally, the weapon in question will cause stretching issues. This can be resolved by transferring the attributes of the Vaccinator to the stock Medi Gun.

Example:
T_TFBot_Medic_Vaccinator_Bullet { Name "Bullet Vaccinator Medic" Class Medic Skill Expert ClassIcon medic_bullet //custom icon WeaponRestrictions SecondaryOnly Attributes SpawnWithFullCharge ItemAttributes { ItemName "TF_WEAPON_MEDIGUN" "lunchbox adds minicrits" 3 //overrides Medigun traits with Vaccinator traits such as healing sound and multiple ubers "medigun bullet resist deployed" 1 // Percentage : 1 = 100% "medigun bullet resist passive" 1 // Percentage : 1 = 100% "medigun charge is resists" 3 //3 for bullet, 4 for blast, 5 for fire "ubercharge rate bonus" 200 } CharacterAttributes { "bot medic uber health threshold" 444 // deploys Vaccinator Übercharge immediately } }
Additionally, removing lunchbox adds minicrits will cause the Medic-robot to have infinite Übercharge and let its bubble linger on any Übered patients. The bubble will lose its resistance once the Medic-robot dies however. If there are multiple Medic-robots with the same resistance type, the patient will lose the resistances (but still keep the bubble) once a Medic dies, but the remaining Medics will still possess the resistances.

In-game Example: Fire, Bullet, and Blast Vaccinator Medics all with stock Medi Guns
Lunchbox Items for Heavy Bots
Adding any lunchbox item to Heavy-bots will cause a handful of issues:
  • Aside from the Dalokohs Bar or Buffalo Steak Sandvich, Heavy-bots will enter an infinite eating loop that gets them stuck in spawn.
  • After their lunchbox item has been used once, bots will struggle to switch back and forth between their weapon restriction and the lunchbox item.
  • Whenever they eat the Dalokohs/Steak they also throw it out whenever they’re targeting a player.

Giving any lunchbox item these following attributes will fix it, as well as letting them work while using a minigun:
  • "max health additive bonus" 1
  • "force weapon switch" 1
  • "single wep deploy time increased" 0.01

Additionally, these attributes can be used to modify the item further:
  • "lunchbox healing decreased" // increases or decreases healing
  • "mult_item_meter_charge_rate" // increases or decreases recharge rate

Alternatively, giving the bot AlwaysFireWeapon will fix the issue of bots throwing sandviches

Example:
T_TFBot_Heavyweapons_Sandvich { Class Heavyweapons ClassIcon heavy_healonkill //Custom icon Item "The Robo-Sandvich" ItemAttributes { ItemName "The Robo-Sandvich" "max health additive bonus" 1 "force weapon switch" 1 "single wep deploy time increased" 0.01 } }

Video Example:
Note: Heavy robots will use the melee robot taunt of the Killing Gloves of Boxing, the Gloves of Running Urgently, and Fists of Steel for their Sandvich eating animation.
Beggar's Bazooka Attributes Usage
Normally if you want a weapon to only fire it's full clip when it is fully loaded, you would use Attributes HoldFireUntilFullReload, but this does not work for every weapon in the game. Luckily there is another way to achieve this behavior, using the Beggar's Bazooka's attributes.

  • "auto fires when full" 1
  • "auto fires full clip" 1

Beggar's attributes on a bot's weapon will make it load the entire clip and fire immediately upon reaching the clip's capacity. This also forces the bot to unload it's clip immediately upon spawning.

Example 1:
T_TFBot_Demo_Cannon_Burst { Name "Burst Cannon Demo" Class Demoman ClassIcon demo_loosecannon //Custom icon Skill Hard Item "The Loose Cannon" ItemAttributes { ItemName "The Loose Cannon" "grenade launcher mortar mode" -1 //Required for Loose Cannon robots, otherwise they will overload on themselves "auto fires full clip" 1 "auto fires when full" 1 "fire rate bonus" 0.1 "reload time increased" 1.5 "clip size penalty" 0.75 } }
[In this example, the Beggar's attributes are use to force the Demo to load and shoot the Loose Cannon as a burst weapon. It is the only Demo primary that this is needed on.]

Video Example 1:

Example 2:
T_TFBot_Spy_Revolver { Class Spy Skill Expert ItemAttributes { ItemName "TF_WEAPON_REVOLVER" "auto fires when full" 1 "auto fires full clip" 1 "reload time increased" 2 } }
[In this example, the Beggar's attributes are used to force the Spy bot to use their revolver before going for a backstab (their A.I. normally prevents this). The reload time increase is necessary for them to make the switch to their knife.]

Video Example 2:

Be aware that energy-based weapons do not work with the Beggar's attributes (as well as Attributes HoldFireUntilFullReload, Energy-based weapons include:
  • The Cow Mangler 5000
  • The Righteous Bison
  • The Pomson 6000
Enabling Projectile Shield for Medic Bots
An unused Attribute named ProjectileShield allows Medic-bots to deploy the Projectile Shield.

Example:
T_TFBot_Medic_Shield { Name "Shield Medic" Class Medic ClassIcon medic_shield // Custom icon Skill Expert Attributes SpawnWithFullCharge Attributes ProjectileShield Attributes IgnoreEnemies WeaponRestrictions SecondaryOnly ItemAttributes { ItemName "TF_WEAPON_MEDIGUN" "generate rage on heal" 1 // Level 1 Projectile Shield "increase buff duration" 2 } }
For a Medic-bot to activate their Projectile Shield, these criteria must be met:
  • The medic has 100% shield charge.
  • An Übercharge is not active.
  • A shield is not already deployed.
A shield Medic will only deploy their shield if it or it's patient takes damage from the defenders. This includes being attacked while in their spawn area.

A few other notes about shields:
  • Robot Projectile Shields do not deal damage.
  • Robots will use human Medic voice lines when deploying shields
  • Because Projectile Shields are technically considered a buff rage like banners, Medic-bots with banners will desperately spam shield deploy noises and voicelines, as they think they have a shield when given an item with a rage meter.

In-game Example: A Medic with a level 1 shield (front) and a Medic with a level 2 shield (back)
B.A.S.E. Jumper Behavior
Robots can deploy their B.A.S.E Jumper (refer to the first section for equipping B.A.S.E. Jumper on other classes) if they are airborne. Attributes Parachute is not required.

Example:
T_TFBot_Soldier_Airstrike { Name "Air Strike Soldier" ClassIcon soldier_airstrike //custom icon Class Soldier Skill Normal Attributes AutoJump AutoJumpMin 5 AutoJumpMax 5 Item "the air strike" Item "the b.a.s.e. jumper" CharacterAttributes { "cancel falling damage" 1 //essential so robots do not fall to a clumsy death after multiple jumps "increased jump height" 3 } }

Bots will use their B.A.S.E. Jumper based on these conditions:

  • Their vertical velocity (is the robot falling downwards fast enough)
  • How far above the ground they are (at least "increased jump height" 6 is required)
  • Health is above / below 50% health
  • On fire or not
https://www.youtube.com/watch?v=yNhNszR1HW4

Do note that robots can't use the B.A.S.E. Jumper like in this video anymore due to the B.A.S.E. Jumper not being able to be redeployed midair.
Combat Engineers, Medics and Spies
Bots with these classes can be forced to attack players instead of their intended behavior using ShouldPreserveSquad. Do note that if a squad consists of only one member, the squad will be immediately canceled and the aforementioned key will also be redundant, you will need to spawn at least two bots at once for this to work.

Each of the three classes has a slightly different method to force them to attack players. All of these will require a Squad{} with ShouldPreserveSquad 1

Engineer-bots:
  • Must not be the squad leader (first bot of the Squad)

Engineer-bots also must be given BehaviorModifiers Push, this is done to avoid them idling and shooting any nearby defenders once they become the new squad leader.

Medic-bots are different, as long as they are the squad leader, they’ll start attacking any defenders and attempt to deploy the bomb.

The method for Combat Spies is exactly the same as Combat Engineers, just that BehaviorModifiers Push isn’t required.

Example 1 (Combat Engineer):
WaveSpawn { TotalCurrency 140 TotalCount 35 MaxActive 8 SpawnCount 2 WaitBetweenSpawns 5 Where spawnbot Squad { ShouldPreserveSquad 1 TFBot { Template T_TFBot_Soldier_Concheror } TFBot { Class Engineer Skill Expert } } }
Example 2 (Combat Medic):
WaveSpawn { TotalCurrency 36 TotalCount 24 MaxActive 12 SpawnCount 6 WaitBeforeStarting 8 WaitBetweenSpawns 6 Where spawnbot Squad { TFBot { Template T_TFBot_Medic } TFBot { Template T_TFBot_Sniper_Bow } TFBot { Template T_TFBot_Medic } } }

is_passive_weapon
While the possibilities for custom bots are already rather high, the attribute "is_passive_weapon 1 opens up even more for interesting bot concepts that are otherwise impossible, as well as providing a workaround for many obscure and oddly specific bugs.

  • Applying this attribute to a weapon will force it to be active at all times, regardless of WeaponRestriction. This allows for bots to essentially dual wield two items.
  • The animations of the weapon with "is_passive_weapon" 1 will be used, however the model of the item with WeaponRestriction will be shown.
WARNING: Do not make more than one item on a bot a passive weapon, this crashes the game.

Example 1: Rocket Shotgun Soldier
T_TFBot_Soldier_Rocket_Shotgun { Name "Rocket Shotgun Soldier" Class Soldier ClassIcon soldier_burstfire Skill Normal Attributes HoldFireUntilFullReload WeaponRestrictions SecondaryOnly ItemAttributes { ItemName TF_WEAPON_ROCKETLAUNCHER is_passive_weapon 1 } ItemAttributes { ItemName TF_WEAPON_SHOTGUN_SOLDIER "auto fires when full" 1 "auto fires full clip" 1 "fire rate bonus" 0.33 "clip size penalty" 0.67 // 4 shots "reload time decreased" 0.67 } }

One common application of is_passive_weapon is to give Stickybomb Demo bots WeaponRestrictions SecondaryOnly, but "is_passive_weapon" 1 applied on a Grenade Launcher that never fires a grenade. This solves the issue with broken Stickybomb Demo-bot animations, as the robot will use the Grenade Launcher wielding animation with the Stickybomb Launcher world model.

Example 2: Stickybomb Demo
T_TFBot_Demoman_Stickybomb { Class Demoman Skill Expert Classicon demo_sticky_daan // Custom icon WeaponRestrictions SecondaryOnly ItemAttributes { ItemName "TF_WEAPON_GRENADELAUNCHER" "is_passive_weapon" 1 "override projectile type" 27 // Fires nothing "fire rate penalty" 99 // No grenade launcher firing animations. } ItemAttributes { ItemName "TF_WEAPON_PIPEBOMBLAUNCHER" "stickybomb charge rate" 0.001 //Demo-bot will fire Stickybomb immediately "max pipebombs decreased" -7 // 1 Stickybomb deployed, will explode when another is fired "projectile range increased" 0.35 // Prevents overshooting target } }

The following examples will only function if they are in a Sniper Mission block

Example 3: Short Circuit Engineer
T_TFBot_Engineer_Short_Circuit { Name "Short Circuit Engineer" Class Engineer Skill Hard Item "The Short Circuit" ItemAttributes { ItemName TF_WEAPON_SHOTGUN_PRIMARY "override projectile type" 7 //fires nothing "fire rate penalty" 2000 } ItemAttributes { ItemName "The Short Circuit" is_passive_weapon 1 } }

Video Example 3:

Example 4: Wrap Assassin Scout
T_TFBot_Scout_Wrap { Name "Wrap Assassin Scout" Class Scout Skill Hard Item "The Wrap Assassin" ItemAttributes { ItemName TF_WEAPON_SCATTERGUN "override projectile type" 7 //fires nothing "fire rate penalty" 2000 } ItemAttributes { ItemName "The Wrap Assassin" is_passive_weapon 1 "effect bar recharge rate increased" 0.1 } }

Video Example 4:
Secondary Fire
The standard way to make a bot that takes advantage of secondary fire is to put it into a Sniper mission support. This is because Sniper AI simply tells robots to stand in a designated spot, right click to scope, and melee enemies as they get close. The only drawback is that this will only work with support bots, and forces all players to yell "Sniper!" when it spawns. The most popular use for this is charged shot Cow Mangler Soldiers, however almost any weapon or bot with an alt fire will work (the exception being Short Circuit Engineers, Wrap Assassin Scouts, and more, which require passive weapon usage to work).

Example:
Mission { Objective Sniper Where spawnbot_mission_sniper BeginAtWave 1 RunForThisManyWaves 1 InitialCooldown 30 CooldownTime 30 DesiredCount 2 TFBot { Class Soldier Skill Expert Item "The Cow Mangler 5000" ItemAttributes { ItemName "The Cow Mangler 5000" "faster reload rate" 0.01 // Allows the bot to almost always fire charged shots } } }

Video Example:

Note: Demoknight bots can still use their shield in Sniper support, allowing for fully functional hybrid knights that actively shoot at, charge at, and hunt down players with their melee, with the only drawback being they are unable to carry the bomb, as they are mission support.
Concealing Bots on The Wavebar
If there are squads within a RandomChoice, the robots’ icons will not appear in the wavebar. This can be exploited to hide robots from the wavebar to surprise the human team.

This has a side effect of causing main-wave bots squadded like this to take chunks out of the wavebar, making it look incomplete. It is suggested to only use this method on support bots.

Example:
WaveSpawn { Name 1a Where spawnbot TotalCount 4 SpawnCount 2 MaxActive 4 Support Limited // Used so the wavebar is not affected WaitBetweenSpawns 15 RandomChoice { Squad { TFBot { Template T_TFBot_Giant_Pyro } } Squad { TFBot { Template T_TFBot_Sniper_Huntsman_Spammer } TFBot { Template T_TFBot_Sniper_Huntsman_Spammer } } } }

Note: The developer console will show errors regarding spawners nested in this manner. They can be ignored as bots still spawn correctly.
PeriodicSpawn, Where Behind, RandomPlacement, and SentryGun
PeriodicSpawn is an old, unused populator that is generally not recommended, however it has niche but useful features that Mission or WaveSpawn do not properly support.

This is what a PeriodicSpawn block looks like:

PeriodicSpawn { When //Can be given a value (such as 3) to spawn the bot at that interval without the need for MinInterval and MaxInterval { MinInterval 3 MaxInterval 7 //spawns the bots at a random time between 3 and 7 seconds } Where Behind TFBot { Template T_TFBot_Scout_Fish } }
The way PeriodicSpawn works is considerably more simplistic and rudimentary than Mission or WaveSpawn. All you can do is tell it what interval to spawn at and where to spawn. This will spawn across every wave, and it will not show up on the wavebar. It also technically counts as the main wave, meaning bots that spawn through this will drop random piles of cash, potentially hundreds of dollars in a single pile depending on the total cash for the wave.

The one and only reason to use this however, is because of the unused dynamic spawns that Valve implemented most likely only for testing purposes. Replacing Where spawnbot with Where Ahead, Where Anywhere, or Where Behind in PeriodicSpawn will make them spawn in essentially random spots around the map, potentially behind players.

This can be used for a multitude of reasons such as robots with back crit/minicrit effects (Backburner/Back Scatter/Holiday Punch), Engineer-bots that spawn around the map dropping Sentries, etc. These spawns will also somewhat work in Mission, however they spawn at a random interval, and cooldown intervals mean nothing. If you need to use mission support so they spawn on a specific wave, set the cooldown interval to a very low number.

More comprehensive details about how these spawns work can be found on this link.

SentryGun and RandomPlacement
RandomPlacement has no other known use besides in conjunction with SentryGun spawners, which spawn RED sentries around the map at a set level.

Example:
RandomPlacement { Count 16 MinimumSeparation 600 NavAreaFilter SNIPER_SPOT RandomChoice { SentryGun {Level -1} SentryGun {Level 0} SentryGun {Level 1} } }

Notes:
  • SentryGun Levels are -1 for level 1, 0 for level 2, and 1 for level 3. Values higher than 1 will increase the HP of the Sentry incrementally the higher the value is set.
  • According to sigsegv’s documentation, NavAreaFilter accepts both SENTRY_SPOT and SNIPER_SPOT. SENTRY_SPOT (not to be confused with Engineer-bot Sentries) does not work in the current version of the game. SNIPER_SPOT are spots around the map that Sniper bots sit and start sniping from. If there is no NavAreaFilter, things will be placed truly random around the map (like inside walls).
  • SentryGun spawners also work in PeriodicSpawn, currently untested in Mission or WaveSpawn (both most likely will not work).
  • Squad and Mob work as well, however there is no practical use for this.
The I/O System
While you may not know what the term "I/O System" means, as a mission maker you have already used it in your popfiles!

Here is an example:
StartWaveOutput { Target wave_start_relay_classic Action Trigger } DoneOutput { Target wave_finished_relay Action Trigger }

The term I/O in the title stands for Input/Output. It is the system that source maps use for entities to communicate with each other. Popfiles are able to utilize this and communicate with entities in the map and create scenarios unique from other missions that do not make use of it.

Each entity in a map supports a set of Inputs and Outputs, Inputs are what are sent to an entity from other entities in order for it do something (You send inputs to entities in your popfile). In the example above, you are sending the Trigger Input to the wave_start_relay_classic and wave_finished_relay logic_relay entities. Outputs are how entities send inputs to other entities. They are activated by various different things depending on the entity. (For example a logic_relay entity has an OnTrigger Output which activates when a Trigger Input is sent to it. This OnTrigger Output may tell a door to open or something.) But as a mission maker you do not have to worry about Outputs unless you are going to decompile a map and look at an entity's I/O. (You can only send Inputs in a popfile.)

If you are not a mapper, this probably sounds like a bunch of gibberish, but it is a very powerful tool for you to use in your mission making, and it is worth learning.

Here is an article on the Valve Developer Wiki if you are still confused:
https://developer.valvesoftware.com/wiki/Inputs_and_Outputs


There are multiple ways to send Inputs to map entities in a popfile, here is the full list:
  • InitWaveOutput - Called immediately after a wave is loaded. (At the start of the map and when the mission advances to the next wave after completion.) This is typically used by multi-area maps to initialize map entities for the proper area.
  • StartWaveOutput - Called immediately after the wave starts (the F4 countdown reaches 0).
  • DoneOutput - Called immediately after the wave ends and before InitWaveOutput is called for the next wave.

Note: For these first three, if the map does not make use of it, then you can use it for your own purposes to send inputs.

  • FirstSpawnOutput - This is called when the first bot of the WaveSpawn spawns.
  • LastSpawnOutput - This is called when the last bot of the WaveSpawn spawns.
  • DoneOutput - You can use this in a WaveSpawn as well as out of it. The WaveSpawn version is called immediately after all bots in the WaveSpawn are dead.

There is a limit on how much you can use these Outputs:
  • For the map related Outputs (the first three), you can only have at most one of each per popfile.
  • For the wavespawn related Outputs (the last three), you can only have at most one of each per wavespawn

Example:
WaveSpawn { // Wavespawn stuff DoneOutput { Target upgr_door Action Open } }
[When the bots are all dead the upgrade door will open (assuming "upgr_door" is the name of the func_door in the map)]

To find out the names of entities and their I/O for the map your mission is located on, you need to decompile that map and view the .vmf in Hammer. Since there are already plenty of tutorials on how to do this, they will not be discussed here.

Note: In these aforementioned Output blocks, you can only send one input to one entity.
You cannot do this:
WaveSpawn { // Wavespawn stuff DoneOutput { Target upgr_door Action Open Target upgr_trigger Action Enable } }

Dummy WaveSpawns
To solve the issue of the strict limits on how many Outputs you can have for a WaveSpawn, you can utilize dummy WaveSpawns (or helper WaveSpawns). The sole purpose of these is not to spawn bots, but for any purpose that you cannot simply use one WaveSpawn (typically having multiple Output blocks for a WaveSpawn).

Here is the solution to the problem in the previous code example shown:
WaveSpawn { Name "W1-1" // Wavespawn stuff DoneOutput { Target upgr_door Action Open } } // DUMMY WaveSpawn { TotalCount 0 SpawnCount 0 WaitForAllDead "W1-1" FirstSpawnOutput // You can use any of the wavespawn outputs, not just this one. { Target upgr_trigger Action Enable } }

Another implementation of dummy WaveSpawns is to have 1 WaveSpawn wait for multiple to end. Normally you would fix this by just naming the 2 that are being waited on the same thing (e.g. "W1-1"), but in circumstances where you need them to be named differently, you can do this:

WaveSpawn { Name "W1-1" // Wavespawn stuff } WaveSpawn { Name "W1-2" // Wavespawn stuff } //DUMMIES WaveSpawn { Name "W1-DUMMY" WaitForAllDead "W1-1" } WaveSpawn { Name "W1-DUMMY" WaitForAllDead "W1-2" } WaveSpawn { Name "W1-3" WaitForAllDead "W1-DUMMY" // Wavespawn stuff }
Separating Identical Icons on The Wavebar
If you have multiple bots with the same icon, the icons will stack into one. This is not necessarily a bad thing, but when you have Giant Pyros along with regular Pyros, the normal Pyros's "TotalCount" will merge with the giant Pyro's while having a red background, misforming there's a lot more giants than the wave actually has.

There are two ways to fix this, the first is simply capitalizing any letter in the icon name:
TFBot { Class Soldier ClassIcon soldier_directhit } TFBot { Class Soldier ClassIcon Soldier_directhit Attributes AlwaysCrit }
[These are technically different icons, and therefore will not stack, even though they come from the same file.]

However, use of this trick is heavily discouraged due to Linux servers not liking capitalized names of icons, and subsequently will not work. Concerning Linux OS players as well, in the above example all Soldiers will appear to be critboosted in one icon, as the icons will not be separated, but this is not the case for players on Windows.

The second fix is to create a new .vmt file and use it for the WaveSpawn you want to have a different icon for:
(You can just make a copy of the existing .vmt and rename it.)

soldier_directhit.vtf
soldier_directhit.vmt

New file for giant:
soldier_directhit_giant.vmt

New file for critboosted:
soldier_directhit_crit.vmt

etc...

Stomping Robots and Damage Resistances
When a giant bot takes fall damage, it loses a massive chunk of its health in the process. To circumvent this, an attribute that resists all types of damage can be used, and then amplify the effects of other melee/ranged attacks using the attributes from the Fists of Steel. The giant robot will take minor damage from the fall but stomped defenders will be instantly killed due to the massive damage.

Example:
CharacterAttributes { "dmg taken increased" 0.05 "dmg from melee increased" 20 "dmg from ranged reduced" 20 "boots falling stomp" 1 "increased jump height" 7 }

A robot with these attributes take 0.05x all incoming typeless damage such as fall damage, bleed (Explode On Ignite and Explosive Headshot are based on bleed), and stomp damage from Mantreads or Thermal Thruster. However it also takes 20x more damage specifically from melee and ranged attacks to offset this.
Grappling Hooks for Robots
Robots can equip and use the grappling hook while using their conventional weapons at the same time. These bots should always be given an AutoJump interval with AutoJumpMin not greater than 5 seconds (especially on Sentry Busters since they will detonate if stuck for too long). AutoJump allows bots to prematurely disengage the grappling hook and fire it again.

Example:
T_TFBot_SentryBuster_Grapple { Template T_TFBot_SentryBuster Item "TF_WEAPON_GRAPPLINGHOOK" Attributes AlwaysFireWeapon Attributes AutoJump AutoJumpMin 3 AutoJumpMax 4 ItemAttributes { ItemName "TF_WEAPON_GRAPPLINGHOOK" "is_passive_weapon" 1 "cancel falling damage" 1 } }
set_weapon_mode
There are a number of item attributes that are included within the set_weapon_mode class, they are all interchangeable and are functionally identical, the only difference is the descriptions that they apply to the weapon they are on. Their purpose is to, as the name suggests, set the mode of the weapon they are applied to. Certain weapon types have different modes that can be applied to them to change their functionality (which is typically based on other weapons of the same type).

For example, the weapon class tf_weapon_invis (Spy Invis Watches) has 3 modes: 0, 1, and 2.
Mode 0 - Invis Watch
Mode 1 - Dead Ringer
Mode 2 - Cloak and Dagger

What this means is you can change the functionality of one watch to a completely different watch! (For example an Invis Watch that acts like a Dead Ringer.)

The most common item attribute used to accomplish changing the mode of a weapon is "lunchbox adds minicrits", as it does not apply a description (Don't be fooled by it's name, it's not specific to lunchbox items nor adding minicrits). If you do want a description however, you will need to use the item attribute for that specific mode of that weapon class.

For example, here are the item attributes associated with the modes of tf_weapon_invis:
Mode 0 - None. Use "lunchbox adds minicrits" 0
Mode 1 - "set cloak is feign death" 1
Mode 2 - "set cloak is movement based" 2

The value you put after the item attribute is simply the mode number.

Here is a portion of an example previously used in the Vaccinator Medic section:
ItemAttributes { ItemName "TF_WEAPON_MEDIGUN" "lunchbox adds minicrits" 3 //overrides Medigun traits with Vaccinator traits such as healing sound and multiple ubers "medigun bullet resist deployed" 1 // Percentage : 1 = 100% "medigun bullet resist passive" 1 // Percentage : 1 = 100% "medigun charge is resists" 3 //3 for bullet, 4 for blast, 5 for fire "ubercharge rate bonus" 200 }

Example 2:
TFBot { Template T_TFBot_Sniper ItemAttributes { ItemName "TF_WEAPON_SNIPERRIFLE" "sniper fires tracer HIDDEN" 1 //regular tracer "lunchbox adds minicrits" 3 //classic tracer } }

Here is sigsegv's documentation of weapon class modes:
https://gist.github.com/sigsegv-mvm/f72e3047c58dc2674493

Preview:
[In this image you can see that the item attribute (if there is one) will be listed next to the mode.]

Modification of Grenade/Sticky Models
Demo-bot grenades and stickies can be modified to use a custom projectile model, which can be exploited for ridiculous purposes (such as Demo-bots firing entire trees or Tanks!). Changing their projectile model alone does not change the attributes of the grenade, however.

WARNING: Using custom models that are not precached (such as the unused grenade models found in the game files) will cause the game to crash as soon as the Demo fires its weapon!

Example:
T_TFBot_Demoman_Sandman { Class Demoman Skill Expert ItemAttributes { ItemName "TF_WEAPON_GRENADELAUNCHER" "custom projectile model" "models/weapons/w_models/w_baseball.mdl" "damage bonus" 0.5 "blast radius increased" 0.01 // Baseballs don't deal splash "fuse bonus" 999 // Baseballs don't explode "mod stun waist high airborne" 1 // Moonshot Stun airborne } }

Video Example:
Modification of Flamethrower Particles
Restoring unused Flamethrower particles
In the game files, there exists a particle effect named flamethrower_giant_mvm, which implies Giant Pyros were supposed to have different visual flame effects. This can be reused through the following example:
TFBot { Template T_TFBot_Giant_Pyro ItemAttributes { ItemName "tf_weapon_flamethrower" "lunchbox adds minicrits" 2 } }
Note: Even non-giant Pyros can utilize this effect.

Flame particle comparison:

Pyro Flamethrower Attributes
  • "flame_up_speed" - Changes how fast flames move upwards. Can be negative to move downward
  • "flame_speed" - How fast flames move.
  • "flame_drag" - How much resistance a flame faces during flight. Lower values make flames travel farther.
  • "flame_gravity" - Are flames affected by gravity. Likely does not do anything.
  • "flame_spread_degree" - Flame angle deviation. Basically projectile spread angle penalty for flamethrowers.
  • "flame_reflect_on_collision" - How hard a flame bounces off a surface
  • "redirected_flame_size_mult" - Size of flames when they bounce off a surface.
  • "flame_ignore_player_velocity" - Self-explanatory.
  • "airblast_turn_projectile_to_ammo" - Spawns small ammo pack on reflect
  • "airblast_give_teammate_speed_boost" - Provides a speed boost when airblasting teammates
  • "airblast_deflect_projectiles_disabled" - Projectiles are not airblasted
  • "airblast_put_out_teammate_disabled" - Teammates cannot be extinguished
  • "airblast_pushback_disabled" - Cannot airblast players
  • "airblast_pushback_no_viewpunch" - Disables airblast’s interaction with the screen.
  • "airblast_destroy_projectile" - Destroys projectiles instead of reflecting, similar to Heavy deflection. Projectiles will disappear once reflected.

Default Flamethrower Values
  • "flame_gravity" 0
  • "flame_drag" 8.5
  • "flame_up_speed" 50
  • "flame_speed" 2450
  • "flame_spread_degree" 2.8
  • "flame_lifetime" 0.6
  • "flame_random_life_time_offset" 0.1

Item Styles
The attribute "item style override" enables the use of different styles of eligible cosmetics or weapons. This is commonly used in Gatebot hats to enable or disable their yellow glow on certain gate captures.

Notably, this attribute allows robots to be equipped with existing Australium weapons.

Example:
T_TFBot_Demoknight_Gold { Name "Golden Demoknight" Class Demoman ClassIcon demoknight Skill Expert WeaponRestrictions MeleeOnly Item "The Eyelander" Item "The Chargin' Targe" Item "Ali Baba's Wee Booties" ItemAttributes { ItemName "The Eyelander" "is australium item" 1 // Australium description "item style override" 1 // Australium variant "turn to gold" 1 // Victims turn to gold } }
Overriding Weapon Projectiles
Through the item attribute "override projectile type", you can change the projectile used by a weapon on a bot. Note that while the projectile may have changed, the damage of the weapon is still the same as if it had not changed, you will need to adjust your damage accordingly.

Example 1:
T_TFBot_Pyro_Flare_Burst { Name "Burst Flare Pyro" Class Pyro ClassIcon pyro_flare_rain_nys // Custom icon Skill Expert WeaponRestrictions SecondaryOnly ItemAttributes { ItemName tf_weapon_shotgun_pyro "crit vs burning players" 1 "override projectile type" 6 // Fires flares instead of bullets "damage bonus" 6 "fire rate bonus" 0.05 "faster reload rate" 0.2 "auto fires full clip" 1 "auto fires when full" 1 } }

Example 2:
T_TFBot_Heavyweapons_Rocket_Spammer { ClassIcon soldier_infinite // Giant Rapid Fire Soldier icon; conveys the same meaning to players Name "Rocket Heavy" Class HeavyWeapons Skill Normal ItemAttributes { ItemName tf_weapon_minigun "override projectile type" 2 // Fires rockets instead of bullets "damage bonus" 5.0 "fire rate penalty" 2.75 "no self blast dmg" 2 // Bots other than soldier dont avoid self damage "centerfire projectile" 1 } }

WARNING: If a Demo-bot is equipped with the Loose Cannon that has a different projectile and is not given the attribute grenade launcher mortar mode 0, the game will crash!

WARNING: Snipers with the Huntsman's projectile overrided to rocket will crash the game!

The middle 2 columns "Hitscan Weapon" and "Angled Projectile Weapon" ask the question:
"Does this projectile work for this weapon type?"


Projectile ID
Hitscan Weapon
Angled Projectile Weapon
Notes
0 - Invalid
No
No
Unsuccessful projectile overrides default to this ID
1 - Bullet
Yes
Partially
For angled projectile weapons, the bullet is invisible, but can be made visible with "sniper fires tracer HIDDEN" 1
2 - Rocket
Yes
Yes
3 - Grenade
Partially
Yes
For hitscan weapons, the grenade drops straight to the ground and does 0 damage
4 - Stickybomb
Partially
Partially
In both cases, stickybombs cannot be detonated through any means (except if the bot is a Demoman) and will cause frame rate issues
5 - Syringe
Yes
Yes
6 - Flare
Yes
Yes
7 - Jarate
No
No
8 - Arrow
Partially
Yes
For hitscan weapons, the arrow drops straight to the ground
9 - Flame Rocket
No
No
Unused
10 - Mad Milk
No
No
11 - Crusader's Crossbow Syringe
Partially
Yes
For hitscan weapons, the syringe drops straight to the ground and appears larger
12 - Cow Mangler Particle
Partially
Yes
For hitscan weapons, the particle is immobile but still explodes on contact, causes frame rate issues
13 - Bison/Pomson Laser
Yes
Yes
For angled projectile weapons, the laser travels notably faster.

The projectile becomes the Bison if given the attribute "energy weapon penetration" 1
14 - Sticky Jumper Stickybomb
Partially
Partially
Identical behavior to regular stickybomb projectile
15 - Flying Guillotine
No
No
16 - Sticky Ball
No
No
Unused
17 - Cannonball
Partially
Yes
For hitscan weapons, the cannonball drops straight down to the ground
18 - Rescue Ranger Bolt
Partially
Yes
For hitscan weapons, the bolt drops straight down to the ground
19 - Festive Arrow
Partially
Yes
Identical behavior to regular arrow projectile
20 - Throwable
No
No
When used on throwable weapons, the projectile will be the weapon's original projectile
21 - Fireball Spell
No
No
22 - Festive Jarate
No
No
23 - Festive Crusader's Crossbow Syringe
Partially
Yes
Identical behavior to regular Crusader's Crossbow Syringe projectile
24 - Self-Aware Beauty Mark
No
No
25 - Mutated Milk
No
No
26 - Grappling Hook
Partially
Partially
For hitscan weapons, the hooks disappear after about 10 seconds and will only move the robot if the hook makes contact with a player

For angled projectile weapons, the hooks disappear at a random time (typically around 10 seconds and up to 30 seconds) and moves the robot
27 - Sentry Rocket
No
No
28 - Bread Monster
No
No
29 - Gas Passer
No
No
Painting Robot Items
Through the "set item tint rgb" item attribute, you have the ability to color cosmetics and certain weapons for bots any way you wish. The value for the "set item tint rgb" key is required to be an RGB integer (e.g. "set item tint rgb" 7511618).
If you have a custom color you would like to apply, rather than the paints in TF2, you can use an RGB integer calculator. Here's one you can use: https://www.shodor.org/stella2java/rgbint.html

Here is a table of RGB integer values for the paints in TF2:
Paint
RGB Integer
Indubitably Green
7511618
Zepheniah's Greed
4345659
Noble Hatter's Violet
5322826
Color No. 216-190-216
14204632
A deep Commitment to Purple
8208497
Mann Co. Orange
13595446
Muskelmannbraun
10843461
Peculiarly Drab Tincture
12955537
Radigan Conagher Brown
6901050
Ye Olde Rustic Colour
8154199
Australium Gold
15185211
Aged Moustache Grey
8289918
An Extraordinary Abundance of Tinge
15132390
A Distinctive Lack of Hue
1315860
Pink as Hell
16738740
A Color Similar to Slate
3100495
Drably Olive
8421376
The Bitter Taste of Defeat and Lime
3329330
The Color of a Gentlemann's Business Pants
15787660
Dark Salmon Injustice
15308410
Mann's Mint
12377523
After Eight
2960676
Team Spirit (RED)
12073019
Team Spirit (BLU)
5801378
Operator's Overalls (RED)
4732984
Operator's Overalls (BLU)
3686984
Waterlogged Lab Coat (RED)
11049612
Waterlogged Lab Coat (BLU)
8626083
Balaclavas are Forever (RED)
3874595
Balaclavas are Forever (BLU)
1581885
The Value of Teamwork (RED)
8400928
The Value of Teamwork (BLU)
2452877
Cream Spirit (RED)
12807213
Cream Spirit (BLU)
12091445
An Air of Debonair (RED)
6637376
An Air of Debonair (BLU)
2636109

In-game Example: A Pyro with a Brigade Helm painted Indubitably Green



Warning: Only the last cosmetic defined in the TFBot block will be able to accept item attributes, if you want to paint multiple items, you can use VScript to do so:

::__PaintBotCosmetics <- { function OnGameEvent_player_spawn(params) { local player = GetPlayerFromUserID(params.userid); if (!player || !player.IsBotOfType(1337)) return; EntFireByHandle(player, "RunScriptCode", @" local tags = {}; self.GetAllBotTags(tags); foreach (index, tag in tags) { if (!startswith(tag, ""paint|"")) continue; try { local args = split(tag, ""|""); if (!args.len()) continue; for (local wearable = self.FirstMoveChild(); wearable != null; wearable = wearable.NextMovePeer()) { if (wearable.GetClassname() != ""tf_wearable"") continue; local id = NetProps.GetPropInt(wearable, ""m_AttributeManager.m_Item.m_iItemDefinitionIndex""); if (id != args[1].tointeger()) continue; local paint = null; if (args.len() == 3) paint = args[2].tointeger(); else if (args.len() == 5) { local r = args[2].tointeger(); local g = args[3].tointeger(); local b = args[4].tointeger(); paint = (b) | (g << 8) | (r << 16); } wearable.AddAttribute(""set item tint rgb"", paint, -1); } } catch (e) {} } ", 0, null, null); } }; __CollectGameEventCallbacks(__PaintBotCosmetics);

Copy the contents of the above into a file named paint.nut and place it inside tf/scripts/vscripts. Create the path if it doesn't exist.

In the first wave of your mission, add or modify an InitWaveOutput at the start:
InitWaveOutput { Target "bignet" Action "RunScriptCode" Param " //DoEntFire(`wave_init_relay`, `Trigger`, ``, 0, null, null); IncludeScript(`paint.nut`); " }
Remove the // and replace wave_init_relay with whatever if you already had an InitWaveOutput targeting something.

Use it within a TFBot block like this:
TFBot { Class Soldier Item "Tyrant's Helm" Item "Veterans Attire" // "paint|<item id>|<rgb int or r|g|b>" Tag "paint|99|16738740" Tag "paint|30983|255|105|180" }
The tag must start with paint|, then provide the item definition index of the cosmetic, and finally provide either an rgb int or separate red, green, and blue byte values.

To find the item def index of your cosmetic, go here[csrd.science] and search for the cosmetic name, copy the value you see in the ID column.

Pre-Jungle Inferno Weapon Skins
Weapon skins and qualities added during the Gun Mettle and Tough Break update can be equipped by bots like normal weapons. The default wear is Field Tested, you can modify the wear through the "set_item_texture_wear" item attribute.

Wear values:
  • 0.2 - Factory New
  • 0.4 - Minimal Wear
  • 0.6 - Field Tested
  • 0.8 - Well Worn
  • 1.0 - Battle Scarred

Here is a list of all weapon names in every collection:

Concealed Killer Collection
Elite
  • concealedkiller_pistol_redrockroscoe
  • concealedkiller_rocketlauncher_sandcannon
Assassin
  • concealedkiller_stickybomblauncher_suddenflurry
  • concealedkiller_revolver_psychedelicslugger
  • concealedkiller_sniperrifle_purplerange
Commando
  • concealedkiller_scattergun_nightterror
  • concealedkiller_stickybomblauncher_carpetbomber
  • concealedkiller_rocketlauncher_woodlandwarrior
  • concealedkiller_medigun_wrappedreviver
Mercenary
  • concealedkiller_flamethrower_forestfire
  • concealedkiller_sniperrifle_nightowl
  • concealedkiller_smg_woodsywidowmaker
  • concealedkiller_shotgun_backwoodsboomstick
  • concealedkiller_minigun_kingofthejungle
  • concealedkiller_medigun_maskedmender

Craftsmann Collection
Commando
  • craftsmann_scattergun_tartantorpedo
  • craftsmann_sniperrifle_lumberfromdownunder
Mercenary
  • craftsmann_shotgun_rusticruiner
  • craftsmann_flamethrower_barnburner
  • craftsmann_pistol_homemadeheater
Freelance
  • craftsmann_smg_plaidpotshotter
  • craftsmann_scattergun_countrycrusher
  • craftsmann_minigun_ironwood
  • craftsmann_sniperrifle_shotinthedark
  • craftsmann_stickybomblauncher_blastedbombardier
Civilian
  • craftsmann_scattergun_backcountryblaster
  • craftsmann_minigun_antiqueannihilator
  • craftsmann_revolver_oldcountry
  • craftsmann_rocketlauncher_americanpastoral
  • craftsmann_medigun_reclaimedreanimator

Teufort Collection
Commando
  • teufort_flamethrower_bovineblazemaker
  • teufort_minigun_warroom
Mercenary
  • teufort_smg_treadplatetormenter
  • teufort_sniperrifle_bogtrotter
  • teufort_flamethrower_earthskyandfire
Freelance
  • teufort_smg_teamsprayer
  • teufort_scattergun_sprucedeuce
  • teufort_pistol_hickoryholepuncher
  • teufort_stickybomblauncher_rooftopwrangler
Civilian
  • teufort_shotgun_civicduty
  • teufort_medigun_civilservant
  • teufort_pistol_localhero
  • teufort_revolver_mayor
  • teufort_rocketlauncher_smalltownbringdown
  • teufort_minigun_citizenpain

Powerhouse Collection
Elite
  • powerhouse_sniperrifle_thunderbolt
  • powerhouse_stickybomblauncher_liquidasset
Assassin
  • powerhouse_rocketlauncher_shellshocker
  • powerhouse_scattergun_currentevent
  • powerhouse_stickybomblauncher_pinkelephant
Commando
  • powerhouse_flamethrower_flashfryer
  • powerhouse_medigun_sparkoflife
  • powerhouse_revolver_deadreckoner
  • powerhouse_pistol_blackdahlia
  • powerhouse_pistol_sandstonespecial
Mercenary
  • powerhouse_shotgun_lightningrod
  • powerhouse_minigun_brickhouse
  • powerhouse_rocketlauncher_aquamarine
  • powerhouse_smg_lowprofile
  • powerhouse_flamethrower_turbinetorcher

Harvest Collection
Commando
  • harvest_revolver_boneyard
  • harvest_sniperrifle_boneyard
  • harvest_wrench_boneyard
Mercenary
  • harvest_knife_boneyard
  • harvest_flamethrower_pumpkinpatch
  • harvest_minigun_pumpkinpatch
  • harvest_sniperrifle_pumpkinpatch
  • harvest_stickybomblauncher_pumpkinpatch
Freelance
  • harvest_pistol_macabreweb
  • harvest_revolver_macabreweb
  • harvest_scattergun_macabreweb
  • harvest_grenadelauncher_macabreweb
  • harvest_stickybomblauncher_macabreweb
  • harvest_minigun_macabreweb
  • harvest_flamethrower_autumn
  • harvest_grenadelauncher_autumn
  • harvest_stickybomblauncher_autumn
Civilian
  • harvest_rocketlauncher_autumn
  • harvest_shotgun_autumn
  • harvest_wrench_autumn
  • harvest_flamethrower_nutcracker
  • harvest_minigun_nutcracker
  • harvest_pistol_nutcracker
  • harvest_scattergun_nutcracker
  • harvest_wrench_nutcracker
  • harvest_medigun_wildwood
  • harvest_revolver_wildwood
  • harvest_smg_wildwood
  • harvest_sniperrifle_wildwood

Gentlemanne Collection
Commando
  • gentlemanne_grenadelauncher_topshelf
  • gentlemanne_minigun_topshelf
  • gentlemanne_wrench_topshelf
Mercenary
  • gentlemanne_knife_topshelf
  • gentlemanne_revolver_topshelf
  • gentlemanne_medigun_highrollers
  • gentlemanne_smg_highrollers
Freelance
  • gentlemanne_grenadelauncher_coffinnail
  • gentlemanne_rocketlauncher_coffinnail
  • gentlemanne_scattergun_coffinnail
  • gentlemanne_shotgun_coffinnail
  • gentlemanne_rocketlauncher_highrollers
Civilian
  • gentlemanne_flamethrower_coffinnail
  • gentlemanne_medigun_coffinnail
  • gentlemanne_minigun_coffinnail
  • gentlemanne_revolver_coffinnail
  • gentlemanne_sniperrifle_coffinnail
  • gentlemanne_stickybomblauncher_coffinnail
  • gentlemanne_knife_dressedtokill
  • gentlemanne_medigun_dressedtokill
  • gentlemanne_minigun_dressedtokill
  • gentlemanne_pistol_dressedtokill
  • gentlemanne_shotgun_dressedtokill
  • gentlemanne_sniperrifle_dressedtokill
  • gentlemanne_stickybomblauncher_dressedtokill
  • gentlemanne_wrench_dressedtokill

Pyroland Collection
Elite
  • pyroland_flamethrower_rainbow
  • pyroland_grenadelauncher_rainbow
  • pyroland_sniperrifle_rainbow
Assassin
  • pyroland_flamethrower_balloonicorn
  • pyroland_sniperrifle_balloonicorn
  • pyroland_grenadelauncher_sweetdreams
  • pyroland_stickybomblauncher_sweetdreams
Commando
  • pyroland_minigun_mistercuddles
  • pyroland_knife_bluemew
  • pyroland_pistol_bluemew
  • pyroland_rocketlauncher_bluemew
  • pyroland_scattergun_bluemew
  • pyroland_scattergun_shottohell
  • pyroland_wrench_torquedtohell
Mercenary
  • pyroland_smg_bluemew
  • pyroland_knife_stabbedtohell
  • pyroland_pistol_shottohell
  • pyroland_knife_braincandy
  • pyroland_minigun_braincandy
  • pyroland_pistol_braincandy
  • pyroland_rocketlauncher_braincandy
  • pyroland_medigun_flowerpower
  • pyroland_revolver_flowerpower
  • pyroland_scattergun_flowerpower
  • pyroland_shotgun_flowerpower

Warbird Collection
Elite
  • warbird_rocketlauncher_warhawk
  • warbird_scattergun_killerbee
Assassin
  • warbird_flamethrower_warhawk
  • warbird_grenadelauncher_warhawk
  • warbird_shotgun_redbear
Commando
  • warbird_minigun_butcherbird
  • warbird_sniperrifle_airwolf
  • warbird_stickybomblauncher_blitzkrieg
  • warbird_medigun_corsair
  • warbird_knife_airwolf
Mercenary
  • warbird_knife_blitzkrieg
  • warbird_medigun_blitzkrieg
  • warbird_pistol_blitzkrieg
  • warbird_revolver_blitzkrieg
  • warbird_smg_blitzkrieg
  • warbird_wrench_airwolf
  • warbird_scattergun_corsair
  • warbird_grenadelauncher_butcherbird

In-game Example: A Pyro with a Factory New Forest Fire Flamethrower
Unusual and Killstreak Effects
Unusual effects can be applied to cosmetics and weapons through the "attach particle effect" item attribute. Here is a list of particle effects and their ID's:

Miscellaneous
  • Flying Bits - 1
  • Community Sparkle - 4
  • Holy Glow - 5
Generation 1
  • Green Confetti - 6
  • Purple Confetti - 7
  • Haunted Ghosts - 8
  • Green Energy - 9
  • Purple Energy - 10
  • Circling TF Logo - 11
  • Massed Flies - 12
  • Burning Flames - 13
  • Scorching Flames - 14
  • Searing Plasma - 15
  • Vivid Plasma - 16
  • Sunbeams - 17
  • Circling Peace Sign - 18
  • Circling Heart - 19
Generation 2
  • Stormy Storm - 29
  • Blizzardy Storm - 30
  • Nuts n Bolts - 31
  • Orbiting Planets - 32
  • Orbiting Fire - 33
  • Bubbling - 34
  • Smoking - 35
  • Steaming - 36
Halloween Generation 1
  • Flaming Lantern - 37
  • Cloudy Moon - 38
  • Cauldron Bubbles - 39
  • Eerie Orbiting Fire - 40
Halloween Generation 2
  • Knifestorm - 43
  • Misty Skull - 44
  • Harvest Moon - 45
  • It's a Secret to Everybody - 46
  • Stormy 13th Hour - 47
Generation 3
  • Kill-a-Watt - 56
  • Terror-Watt - 57
  • Cloud 9 - 58
  • Aces High - 59
  • Dead Presidents - 60
  • Miami Nights - 61
  • Disco Beat Down - 62
Robo Crate
  • Phosphorous - 63
  • Sulphurous - 64
  • Memory Leak - 65
  • Overclocked - 66
  • Electrostatic - 67
  • Power Surge - 68
  • Anti-Freeze - 69
  • Time Warp - 70
  • Green Black Hole - 71
  • Roboactive - 72
Halloween Generation 3
  • Arcana - 73
  • Spellbound - 74
  • Chiroptera Venenata - 75
  • Poisoned Shadows - 76
  • Something Burning This Way Comes - 77
  • Hellfire - 78
  • Darkblaze - 79
  • Demonflame - 80
Halloween Generation 4
  • Bonzo the All-Gnawing - 81
  • Amaranthine - 82
  • The Stare from Beyond - 83
  • The Ooze - 84
  • Ghastly Ghosts Jr - 85
  • Haunted Phantasm Jr - 86
End of the Line
  • Frostbite - 87
  • Molten Mallard - 88
  • Morning Glory - 89
  • Death at Dusk - 90
Invasion
  • Abduction - 91
  • Atomic - 92
  • Subatomic - 93
  • Electric Hat Protector - 94
  • Magnetic Hat Protector - 95
  • Voltaic Hat Protector - 96
  • Galactic Codex - 97
  • Ancient Codex - 98
  • Nebula - 99
Halloween Generation 5
  • Death by Disco - 100
  • It's a Mystery to Everyone - 101
  • It's a Puzzle to Me - 102
  • Ether Trail - 103
  • Nether Trail - 104
  • Ancient Eldritch - 105
  • Eldritch Flame - 106
Halloween Generation 6
  • Neutron Star - 107
  • Tesla Coil - 108
  • Starstorm Insomnia - 109
  • Starstorm Slumber - 110
Halloween Generation 7
  • Brain Drain - 111
  • Open Mind - 112
  • Head of Steam - 113
  • Galactic Gateway - 114
  • Eldritch Opening - 115
  • Dark Doorway - 116
  • Ring of Fire - 117
  • Vicious Circle - 118
  • White Lightning - 119
  • Omniscient Orb - 120
  • Clairvoyance - 121
Halloween Generation 8
  • Fifth Dimension - 122
  • Vicious Vortex - 123
  • Menacing Miasma - 124
  • Abyssal Aura - 125
  • Wicked Wood - 126
  • Ghastly Grove - 127
  • Mystical Medley - 128
  • Ethereal Essence - 129
  • Twisted Radiance - 130
  • Violet Vortex - 131
  • Verdant Vortex - 132
  • Valiant Vortex - 133
Gun Mettle
  • Hot - 701
  • Isotope - 702
  • Cool - 703
  • Energy Orb - 704

In-game Example: A Pyro with a Cloudy Moon Brigade Helm

Killstreaks
Killstreaks can be implemented into robot weapons using the following attributes:
  • "killstreak tier"
  • "killstreak idleeffect"

Note: Professional killstreaks do not work apart from modifying the name of the weapon with the prefix "Professional".

Killstreak Tiers:
  • Basic - 1
  • Specialized - 2
  • Professional - 3

Killstreak Effects:
  • Team Shine - 1
  • Deadly Daffodil - 2
  • Manndarin - 3
  • Mean Green - 4
  • Agonizing Emerald -5
  • Villainous Violet - 6
  • Hot Rod - 7
Miscellaneous Tips and Tricks
This section contains any information that may be of importance, but is not a broad enough topic, or does not have a thorough enough explanation to warrant an entire section dedicated to itself.

  • Prevent Demo bots equipping the Loose Cannon and Soldier bots equipping the Beggar's Bazooka from blowing themselves up through "grenade launcher mortar mode" -1 and "can overload" 0, respectively.

  • If an Engineer bot is given Attributes AlwaysCrit, their Sentry’s firing speed will increase, similar to a human Engineer activating their Crit Canteen to achieve the same effect. This increased firing speed will last until the Engineer bot is destroyed.

  • The attributes "rocket specialist" 1 and "use large smoke explosion" 1 can be applied to an Engineer bot (via CharacterAttributes) to modify it's Sentry Gun rockets. These only apply if the Engineer is alive, however. These attributes can also be applied to Pyro bot Flamethrowers to modify an explosive projectile they reflect. (You can also modify the blast radius with the appropriate attribute, but it doesn't affect reflected Sentry rockets unfortunately.)

  • There can only be a maximum of 5 boss health bars (including Tanks) displayed at a time.

  • There can only be a maximum of 24 icons displayed on the wave bar at a time. More than 23 icons will cause the borders around the wave bar to disappear.

  • A Medic bot's leash length depends on the type of Medigun they are wielding. Medics with the stock Medigun (TF_WEAPON_MEDIGUN) or any reskins will follow very closely to their patient. Medics with every other Medigun will follow at nearly max Medigun beam length. It is advised to give Shield Medics the stock Medigun to allow their shield to adequately cover their patient.

  • Medic bots who are healing will ignore any FormationSize given to their squad block.

  • Robots in a squad tend to have difficulty switching weapons, this affects Banner Soldiers, Bonk Scouts, etc quite a bit. To fix this you need to give them the item attribute "deploy time decreased" 0.5 or 1.34.

  • Audio played via the WarningSound keyvalues (StartWaveWarningSound, DoneWarningSound, etc.) can be manipulated with Sound Characters. The most practical use for this is adding # to the beginning of the filepath to allow the sound to be adjusted with the music volume setting. "StartWaveWarningSound #mysong.wav" as an example
41 Comments
zistix1 23 Nov, 2024 @ 5:50am 
Changing the grenade model seems very crashy and I've only been using the baseball like in the example which I imagine is always precached cause it's the sandman's projectile? and I've seen them fire it successfully but sometimes when they do the game crashes
zistix1 12 Oct, 2024 @ 6:23am 
vscript stuff worked like a charm, makes me wonder what else can be done with vscript in MvM

If only it were possible to add taunt unusual effects to robots at all times, would be nice for bosses or highlighting a very dangerous robot type.
zistix1 10 Oct, 2024 @ 2:27pm 
Ah I see that is some good info, never tried vscript before but hey first time for everything.

Thanks for putting that in, I feel that was always an unmentioned piece of info in many guides which is kinda fair, they probably don't expect most people to go ham on customizing their robots
I am not most people
Mince  [author] 10 Oct, 2024 @ 11:34am 
Updated the section to explain why and provide a solution.
zistix1 10 Oct, 2024 @ 8:43am 
I think a general note that should be applied to the paint section(or well any section relating to ItemAttributes) Is that you can only use ItemAttributes once or twice in a single TFBot block.

I tried many times and in many ways to get multiple items painted or edited at once on a single robot to no success

If someone knows a possible solution please tell me and then add it somewhere in here, if not then add somewhere that editing multiple items attributes doesn't work
_Mud$ 23 Dec, 2023 @ 5:24pm 
You can also use SetModelScale on tanks.
_Mud$ 23 Dec, 2023 @ 5:23pm 
Ty I put this to work in the MVM Mission Titans_Santas_Scrapyard on the MoeVsMachine server. Fast tanks on rottenburg will fall through the hatch... but with I/0 I can drop their speed down to 75 from 750 after 48 seconds, this allows them to deploy the bomb without glitching. But, I have to do this for each tank individually, I think.
Ultimaximus 14 Dec, 2023 @ 2:49pm 
In my example, "tankboss" is referring to the tank's name, not the classname.
Mince  [author] 14 Dec, 2023 @ 1:41pm 
Vanilla output blocks can't target classnames properly, it has to be a unique targetname.
_Mud$ 14 Dec, 2023 @ 11:44am 
@Ultimaximus
I tried this and it did not do anything. Also wouldnt it be tank_boss?