Team Fortress 2

Team Fortress 2

38 ratings
MvM - A newcomer's guide to mission making
By BlacKy #SlavaIsraelini and 1 collaborators
This guide will walk you through the initial pain of dealing with popfiles, in a nice and non overwhelming way. It should be a good tool for the less/no experienced in MvM mission making as it will mostly talk about the essentials of how to create your missions, and also delving into a few technical details.
   
Award
Favorite
Favorited
Unfavorite
Introduction and useful links
Hello there!
You have just started to make your own MvM missions. I can’t say it will be easy, but if you work hard enough you will surely enjoy it.
A couple of things we need to clear before jumping right in. Making MvM missions effectively requires certain informative pages and programs to make it as easy as possible.

Notepad++[notepad-plus-plus.org]

This is a program that is most commonly used among mission makers, due to it's easy-to-use interface and various modifications that can make your mission making journey easier. Missions will be made in a .pop file and are generally called 'popfiles'. You will open and manage the popfile with notepad++.

Popfile marker[marketplace.visualstudio.com]

If, like me, you’re tired of your pop file syntaxes being such uncolored and messy, you need to get yourself some syntax coloring. This isnt just a cosmetic upgrade, as it will also help you spot syntax errors as these will usually be in black color, while generally speaking, actual command lines will be colored.
After you download it, follow these instructions:
1. Open Notepad++
2. Look for and click on the “Language” in the top bar.
3. Click on “Define your language”
4. Click “Import”
5. Import the popfile_marker.xml
6. If the Notepad++ prints out “Import successful” you’re good to go, the popfile syntax coloring will apply when the file you created will have a .pop extension
7. Restart Notepad++ for the syntax coloring add-on to take effect.

* These steps may change as npp's version is changing over time.

P3[github.com]

We often make mistakes, but in the case of popfile making, any mistake can potentially wreck your entire popfile. To avoid this, we use this program. It checks your popfiles for common errors and notifies you if something is not right with your popfile.
To use it, simply open it and run the popfile. It will print out errors should you have them. The ones in yellow are less harmful for your mission, and the red ones can usually crash your popfile when it runs.
Credit goes for the program’s maker, :sub: .

VTFEdit[www.tophattwaffle.com]

This is a program that you need to have when you want to implement your own icons or check other icons from the community. It is not mandatory for beginners as Valve supplies their own default icons that are embedded in the game files, but it will help you with viewing and using custom icons made by the MvM community.

GCFScape[download.cnet.com]

GCFScape is a program for getting Valve’s own base files in game (such as .mp3 files). Mostly used to locate the mvm bot voicelines, but they contain many other .mp3 files. It will also get its own segment later on in the guide.

*P3, VTFEdit and GCFScape will get their own detailed section in the guide*

List of item attributes

Valve's default icons
The basics of popfile writing
So you open up Notepad++, you’re basically ready for what’s to come, but what now? This section of the guide will talk about how to build the foundations of every popfile.

Base Popfiles

The very very first thing any pop file needs to have is “reference popfiles”. But what are they? To put it in short: They contain all the bot templates made by Valve. To reference them you need to put “#base” and the 'robot' popfiles after it. There are a total of 3 base popfiles you need to know of:

robot_standard.pop - contains all the small bots
robot_giant.pop - contains all the giant bots
robot_gatebot.pop - contains all the gatebots, both small and giant

Side note: you can always make your own 'robot_<name>' base file to contain all the templates you're going to use in the popfile. This is an advanced and a non mandatory step that you shouldn't worry about, though, so we'll skip it in this guide.

So, to sum the '#base' part of the popfile, every popfile should start like this:



The robot_gatebot.pop is only used for maps with gatebots. In this case this map has a gate so it uses robot_gatebot.pop.

WaveSchedule

After you take care of the #base, the next thing that comes up is “WaveSchedule”. You type this after the #base and open it up with “{“. In it you need to put a few lines of code with values in ithem, as shows here:



Note: Technically speaking, you can call waveschedule anything you want, but for the sake of simplicity, its best to keep it as 'waveschedule' to avoid random errors from P3 later on.

StartingCurrency - A value of money the players will start with.

RespawnWaveTime - In wave 1 when you die you have to wait 2 seconds until you can respawn. The time will increase by 2 seconds every wave until it hits the value you put in RespawnWaveTime. In this case the Wave 1 respawn time is 2 seconds, Wave 2 is 4 seconds and Wave 3 and so on is 5 seconds.

CanBotsAttackWhileInSpawnRoom - Allows or disallows the bots to shoot while in spawn. It’s for the best if this is set to “no”.

There are a few more lines of code, but they don’t have to be implemented:

FixedRespawnTime - Makes the respawn time be set to the value that you put in RespawnWaveTime, without an exceedingly growing number for each wave. It’s advised to set to “No” by default.

AddSentryBusterWhenDamageDealtExceeds - A value of how much damage the sentry must do in order to spawn the Sentry Buster. It’s set to 3000 by default.

AddSentryBusterWhenKillCountExceeds - Same as above but for when the sentry reaches a certain kill count. It’s set to 15 by default.

Side note: Its usually best to stick with just the damage threshold, as the killcount threshold can be cheesed with low amount of high health bots, like giants and tanks. If you want the buster to spawn depending on the sentry gun's overall DPS, then stick with the command '...whenkillcountsxceeds'. I find anything between 2500 and 3500 to be in the proper blanaced range, while lower number = harder (busters will be spawned more frequently).

Advanced 1 - Tells the popfile to enable certain Steam achievements for tf2 that were designed to be achieved in harder missions (advanced+).

EventPopfile Halloween - Sets all the bots to be in human form, and if halloween event is activated in the server/map, they will appear as zombies. This is generally used for halloween-themed missions. Also note that this what makes missions appear with 'wave 666' title, instead of the informative view of waves. This command line will not change how the waves are executed, as its only for visual purposes.

Example that shows the rest of the commands, and the word 'population' replaces 'waveschedule':



Mission support
Mission support controls the Spies, Snipers, Engineers and Sentry Busters (you can technically put any bot you want in there, that will function similar to the above examples, if given their specific commands, but this wont be covered in this guide). You put all the needed info for these bots to function properly. You also need to open this with a “{“ and close it later with a “}”. This is how a mission support looks like:



Objective is a value that tells the bots what they should do. There are 4 values for this: “Sniper”, “Spy”, “Engineer” and “DestroySentries”. DestroySentries is for Sentry Busters.

Where is where the mission bots will spawn. Different maps have different spawns, and you will need to investigate the spawn names of the map you're writing the popfile for. Most maps have similar spawn names for common spawn bots like snipers and spies, and they're generally called 'spawnbot', 'spawnbot_mission_sniper' and 'spawnbot_mission_spy'.

BeginAtWave - The wave the mission bots will start spawning at.

RunForThisManyWaves - How many waves the mission bots will spawn, including the wave they started appearing at.

InitialCooldown - A value in seconds that the mission bots will have to wait until they can spawn for the first time. If you don’t put it in the mission bots will spawn immediately after the wave starts.

CooldownTime - A value in seconds counted from the bot's death until they spawn again.

DesiredCount - The amount of mission bots that will spawn.

In the above example, during Waves 1 and 2 two snipers will spawn, 45 seconds after the waves start and then wait 35 between each subsequent spawn.
I will explain later what does the “TFBot” and “Template” means. You can put in multiple mission-templates for the same type of bot if you want them to vary in spawning.



This is another example of how spies will spawn in waves 3, 6, and 7.

A short recap of all the things that should be written to this point (click on the pics to enlarge):



The symbol '//' means that everything written in this row (after putting //) is personal notes that have no effect on the popfile. The text will also turn green.
'TeleportWhere' and Item will be exaplained later in the guide.


First wave

After you finish with the 'missions', it’s time to start your first wave. Let’s talk about what you need to do to successfully make a wave.

"Wave"

The first thing you need to put in is Wave. Literally.



What you see here is the beginning of a wave, relays and their outputs. These basically make the bomb and the bomb path arrows appear and disappear.
The outputs - They basically mention when to execute a relay. “StartWaveOutput” is at the start of the wave and “DoneOutput” is when the wave ends.
The relays - They are the targets of the outputs. Usually the wave_start relays are what you see in the example screenshot, but sometimes it’s not the case, like when the mission is Endurance type (a bomb with a reset timer). If the relays don’t work then check already existing popfiles for it for the same map.
Finally: The actions - They execute a command on the relays when the outputs tell them so.
In this case the wave_start_relay will trigger when the wave begins, which will allow the bots to spawn, make the bomb path arrows disappear and spawns in a bomb. A wave_finished_relay will despawn the bomb and generate a new bomb path, for the next wave.

WaveSpawns - Part 1
They are the big majority of a mission popfile. They are quite easy to understand, but this part will be quite long since of their nature.



What you see here is a wavespawn that spawns pyros in pairs. Lets dissect this wavespawn one line after another:

Name - A custom name you give to every wavespawn (also called subwave). It enables them to be referenced in “WaitForAllDead” and “WaitForAllSpawned”. You can call any wave in any name you want, but for simplicity sake, i would highly recommend following an easy format of 'wave number' and 'subwave letter', so for example, subwave name '1a' is the first subwave (a) in the first wave (1). Subwave '3f' will be the 6th subwave (f) in the 3rd wave (3). This is the format i prefer to work with, but you can feel free to use any names you want.

WaitForAllDead - A “command” of some sort (unseen in this example). It means that the wavespawn will wait until all of the bots from a different wavespawn (referenced in this line of code) are all dead.

WaitForAllSpawned - The same as above but the wavespawn waits until all of the bots from a different wavespawn (referenced in this line of code) have spawned.

TotalCurrency - The total amount of money the bots will drop in this wavespawn. This is divided as equally as possible between all the bots that will spawn under this wavespawn. You have no control over individual bot's money drop, unless the bot is in its own wavespawn.

TotalCount - A total amount of bots that the wavespawn will spawn.

MaxActive - The amount of bots that can be alive at the same time from the same wavespawn.

SpawnCount - The amount of bots that the wavespawn will spawn at once.

WaitBeforeStarting - A value in seconds that the bots will wait before spawning after all the spawning criteria are met (all WaitForAllDead/Spawned are checked).

WaitBetweenSpawns - A value in seconds the bots will wait between spawns.

Where - Defines the spawn location in the map. Most of the maps have a main spawn that is called 'spawnbot', but some have different names, and you should be aware of a map's spawn names before even starting to build your mission. This particular spawn is called 'spawnbot_flank', which is generally a spawn located on the sideways of where the bots normally spawn, for flanking purposes.

Support - Tells the wavespawn that the bots should be in the support section on the wavebar. Possible values are “1” (makes the bots spawn infinitely) or “Limited” (makes the bots spawn until they've exhausted the TotalCount.

TFBot - Tells the wavespawn that there will be bots in this wavespawn (you can skip putting this in if you want to make 'dummy wavespawns' which I will talk about later).

Template - Tells the wavespawn what kind of bot should it spawn. The full list of these templates can be found in the 3 base files you can open with GCFScape. To open and handle these 3 files, run the program and click ‘open’, go to the main tf folder (it should be pointing on it already), then use the search tool in the program to look for the 3 base files, and simply drag and drop them to somewhere where you can easily handle them, like the desktop.
From there, you can open them in notepad++ just like any other popfile and see all the templates they possess.



So to sum up this particular wavespawn, a limited support of 22 pyros will spawn after a wavespawn named “1c” would finish spawning its own bots. The pyros will wait 5 seconds before spawning, and then spawn in pairs with 7 seconds of space between each pair. The max amount of pyros that can be at any given time is 4 (this is a hard cap, meaning there wont be any situation of 5 or more pyros from this wavespawn). They will continue spawning in this way untill all 22 of them will eventually be spawned. The spawn location for this particular wavespawn is the flanker's spawn.
These pyros have a behavioral handicap as they can't use airblast (will talk about CharacterAttributes later in the guide).

Placed the same pic here again for convenience sake.



If you finish your wavespawn, you can make a different one. This is where your creativity comes into play. Try to come up with something consistent. After you’re done, close the Wave syntax and make a next one for a new wave. Do that until you've finish writing the entire mission.

RandomChoice

This command line picks a random bot to spawn from a set choice of bots you set from. You can modify the probability to make certain bots spawn less frequently than other ones simply by adding more of the same bot you want to have higher probability. Here are a few examples of how its written:

First lets explore the simplest example, a 50-50 chance of spawning either one of 2 bots, a normal soldier shotgun bot, or a gatebot shotgun bot:



This example shows how a basic randomchoice command is written. It comes over the tfbot command and covers it entirely, and inside of it is each of the bots' equal chance of spawning. Since this example only has 2 bots inside of its randomchoice, they will spawn in an equal chance of either one of them.

Now lets explore a more complexed example:



In this example we have a few sandman scouts that are the same (the bottom 3) and some that have modified stats (the top 3), so the game will spawn (in pairs, since the spawn count is 2) any 2 of the random 6 bots that are in this wavespawn. It can be a normal sandman scout and an armored scout, or any other variation that exists within the limits of this randomchoice. The main idea of this particular randomchoice is to have a 50% chance to spawn one of the normal sandman scouts and another 50% chance to spawn a sandman scout with a modified factor, like health (the armored scout) and speed (the speedy scout) modifiers).
*We will cover how 'CharacterAttributes' work later in the guide*

Squad

A squad command is set to let bots stick together in a single group. Every squad has a 'squad leader', which is the first bot mentioned in the squad list, as the rest of the squad members simply follow this one bot. This is generally the way to make medics follow their target, as the target can be any bot you want to be healed, and the medic or medics behind it are the rest of the squad.

Example 1:



Probably the most basic example of how to squad bots together is with a single medic healing the squad leader, in this case a giant flare pyro. Be aware to set the spawncount to the total amout of squad members in the wavespawn, in this case, 2. If the total count was 1, only the squad leader would have spawned.

Example 2:



In this squad, the squad leader is, as always, the first bot in the squad list, being the giant soldier, and 5 'push' soldiers follow it where ever it goes.
Note that if you pair fast bots to the squad leader that happens to be slower than said bots, they will all follow it at its own speed, so be mindful of the loss of speed fast bots will have while paired with a slow bot, like in this example below:



Here you can see how 2 giant scouts follow a giant heavy. As long as the heavy is alive, they will stick to it at its own pace, and if it happens to die before them, they will then behave as if they have spawned on their own, gaining their normal speed.
WaveSpawns - Part 2
'ShouldPreserveSquad' - A value that prevents the squad members from scattering away when the leader dies. Instead, when the leader dies, the next member (in the order of the squad list in the WaveSpawn) will become the leader.

Example:



Here you can see how the first conch soldier (soldier_extended_concheror) is the original leader, while everyone else follow it, including the giant medic at the bottom (a reminder that a medic in a squad will always heal its squad leader, no matter which leader it has to be in any given time), so the idea of this squad is to have a giant medic healing the squad leader, and should that leader die, the medic will heal the next squad member that becomes the leader (by the order that they're written, from top to bottom), till they all die.

A very important side note!
You shouldn't write a squad inside a randomchoice, as it will cause issues with how things spawn in the wave and make some icons disappear (unless this is your original intention, which is something that i wont cover in this guide).

Tanks

Tanks are these big metal contructs that move slowly and carry their own bombs. They have their own mechanics and their own way of how they're written in the popfile. Tanks are usually written in a map-dependant way, which means that you need to explore the map's info-page in order to see how to write them for this particular map, however, i will give you examples from Valve maps as they're the basic ways to write tanks.
Side note regarding 'info-pages':
Some mappers publish the map's info-page into the community and some don't. You can generally find these in their workshop pages on the Steam workshop. These contain all the info you need to know about what to add to a wavespawn for it to work (navs, relays, names of spawns, tank path names, etc). Before picking a map to write a mission to, make sure you have this handy info nearby, or else you may have issues writing stuff you don't know the code for. Most popular maps have these info-pages so its not something you should actively worry about if you do your basic research. I will supply a couple of info-pages later on as examples.

Tanks generally have 2 factors: Health and Speed. All in all, a tank is just a time bomb that you need to defuse (by destroying) within a certain amount of time. Their health usually varies in the 10's of thousands and they basically act as a DPS test. Their default speed is 75 (measured in Hu/s - Hammer units per second).
Tanks are generally constructed in a popfile in one of 2 ways:

1) DPS test - A 'healthy' tank that is usually slow and that the entire team can focus on. This tank will mostly follow the bomb path so the entire team can hang around it and deal damage into it.

2) Team split - A tank that purposely splits the team by going on the opposite way of the bomb, forcing the tank dps classes (like demo/pyro/soldier) to drop their attention from the bomb and go deal with the tank. These tanks should be a bit faster and with less health, as their purpose isnt to be their own challenge, but to just see how the rest of the squad can deal with the bomb on their own.
Note that the paths of the tanks are really map-dependant, so sometimes you wont be able to control if a tank will split the team or not, as you may not have powers to control the bot's path. With that in mind, some maps offer you to set tank paths directly opposite (or directly similar) to the bomb's path.

Example from Valve's own Rottenburg map:



Quickly going through the values in this example, this tank is simply called 'tank' has 35000 health, and moves in its default speed of 75.
StartingPathTrackNode - This command tells the tank which path to take in the map. Again, each map has its own path name system so you will need to look these up if you decide to write a mission in a non Valve map. For this example from Rottenburg, the path is called 'tank_path_b_10'. If you recall how Rottenburg tanks move, path A turns left after the short tunnel, then goes up the bridge till it reaches the front of the bomb hatch, while path B turns right after the short tunnel, turns left and then keeps straight till it reaches the underground hangar doors which then disappears and reappears behind the bomb hatch. This tank takes path B as the popfile pic suggests.

OnKillOutput - The action you write to trigger a relay once the element is killed (in this case, the tank)
Target boss_dead_relay and Action Trigger - Applies what i've just said. Take these as they're written, as 9.5 times out of 10 you will just copy and paste them between one tank wavespawn and another.
Same thing goes with OnBombDroppedOutput. It simply shows the result of what happens when the tank bomb is dropped into the hatch (it triggers the boss_deploy_relay). There is no use of delving into details regarding these relays as they wont be something you will need to think about. It really comes down to copy-pasting them after the tank's variable stats and thats it.

Getting funky with tanks

Lets take tanks into the next level and make what I like to call a 'conga tank'.



In this example I have made 3 tanks that spawn one after another, as the mid tank (shows in subwave 3j) splits to the left path while the other 2 tanks (subwave 3i) are going the right path.
Note that before the tank's properties are written, there is an added 'FirstSpawnOutput'. This is a relay that triggers the tank's spawn. This is another map-dependant feature that you may or may not have to add in the popfile, depending on the map (this specific one was taken from the community map Waterfront.
Example of Waterfront's info-page that gives you the info you need to properly write a mission in this map. Credit to Jakapoa for supplying this info-page in a proper way.

In-game screenshots (click to enlarge):



Tank train
Another example of how to go crazy with tank ideas is to have a train made out of tanks, and to top it all, the first tank (the 'locomotive'), is a modified tank with 2 sticky cannons on the sides (this is a modded tank from a custom map, and you can't build these kind of things directly in the popfile). Taken from the map Rust Valley - Info page can be found here and is credited to the map's maker, sntr.



Here you can see how the first wavespawn is the single 'sticky tank', while the other 3 tanks follow it after it spawns. Note that the sticky tank has to have its own 'FirstSpawnOutput' in order to work normally, as well as its own name (which again, these are all map-dependant things that may force you do use specific names and relay triggers for them to work).

In-game screenshots (click to enlarge):

Custom bots - Part 1
They are basically regular bots but with an added gimmick that makes them unique. Here’s some basic things you need to know beforehand:

- Custom bots can be named anything you want, but in most cases, the community has adopted the Valve syntax for templates, which is:

T_TFBot_[insert template name here]
Or if the bot is a gatebot:
T_TFGateBot_[insert template name here]

Examples for custom templates:

T_TFBot_Heavy_Rage
T_TFGateBot_Medic_Regen
Scout_BonkMaster

- Custom bots need to be inside a “Templates” syntax which you either put before “Mission” or in a different .pop file which you reference in “#base”.

Making your own custom bot
Let’s say you want to make yourself a custom bot. These are several common examples of how to do it:
  • Just changing minor stuff
    Example:


    This is a Heavy Bot with the Huo Long Heater.

    ClassIcon - An icon that will be shown on the wavebar, representing the bot.

    Class - One of the 9 classes the bot will be.

    Skill - The difficulty of the bot. Can be Easy, Normal, Hard or Expert. It determines their aiming and overall skill level.
    A youtube video demonstrating the skill differences (credits to Sigsegv's for testing this).

    Item - The item you wish to give to the bot. It will override the default Minigun in this case. Bare in mind that in order to reference a stock weapon, you need to write the weapon's actual name. Simply typing “Minigun” won’t do it. Luckily, P3 has the ability to browse the actual item names so you can type a key phrase and it will give you the results it finds from your key word (for example, typing 'minigun' in P3's search feature will spew out all the items in the game that have the phrase 'minigun' in them, so you will get all the botkiller variants, festives, and so on). Items should be put in quotation marks.

    Some items won't have a familiar name at all, as Valve have changed the presented item’s name while keeping its actual name as-is without an update. A good example would be the Spy hat that goes by the name ‘Nanobalaclava’ in-game. To put this hat in the popfile, you will need its actual name, which is "Belltower Spec Ops".
    P3 is ok to use 99.9% of the time, but if it doesnt find an item’s name via its search feature, go into the actual item name’s file, called ‘tf_english.txt’ which is located in 'tf\resource' and from there you can search for both the new and old item names (in english. If playing the game in a different language, you will need its corresponding file, located in the same folder) if and whenever you can't see the name on P3. P3 will definately make your life easier when customising your popfile and it will get its own section in this guide later on.

  • Modifying simple stats



    This is a Shotgun Soldier that fires his shotgun faster but is dealing less damage per shot.

    WeaponRestrictions - Makes the bot only use a certain weapon slot. Possible values are “PrimaryOnly”, “SecondaryOnly” and “MeleeOnly”.

    Attributes - A modifier you can assign to the bot. In this case “HoldFireUntilFullReload”, which makes the bot hold its fire until reloading all of his shots has finished.

    ItemAttributes - The command used to modify the stats of an item the attribute is pointing at (can be a weapon or a cosmetic item). ItemName is used to tell the game which item will have altered stats. These attributes should be put in quotation marks. For this example, firing speed, damage and the reload rate of a stock shotgun are altered (more on how these attributes work later).

  • Writing some advanced attributes
    This is where you need to work your head a bit to find a good gimmick that will stay balanced in game. Here's an example of a giant Demo bot that fires 6 pipes at once:



    CharacterAttributes - Attributes you give to the bot itself that don’t fall under the category of “Attributes” or “ItemAttributes”. These are usually attributes you give to a giant. Most notably the speed penalty, footstep override, and airblast vuln. multiplier.

    Tag - A role you give the bots. In this case the bot is given a role “bot_giant”. This is what differentiate a giant bot from a non giant bot, as their differences are that giants do not get the periodic bomb powerups that all normal bots get as they carry the bomb, as well as to differentiate giants from standard bots when a gate is capped, so the giant wont get the gate-stun effect for a few seconds, among some other minor differences like red icon background. Tags are generally map-dependant roles that differentiate their meaning by the map, mainly if the map has gates or not.

  • Creating a “Boss bot”
    You may have seen them before if you played a lot on the custom MvM missions. These are generally buffed giant bots that have a gimmick which places them separately from other bots in terms of raw strength and challenge to destroy. I’d appreciate if you didn’t nab these bosses examples for your mission as these bosses are unique to their missions are deemed personal for their mission owners. Remember to put the “UseBossHealthBar” attribute as its the attribute that gives the blue health bar that tanks normally have.

    Example #1, by The Fat:



    This is a Soldier Boss that fires 34 rockets in a burst which ignite on hit and send you up. It also gains minicrits when it kills someone.

    clip size upgrade atomic - Increases the clip size by the value (additive value = it adds, not multiplies).
    projectile speed increased - Increases the projectile's speed by the value (multiplicative).
    fire rate bonus - An inverted attribute, which means that the lower the value = the higher the fire rate, in a multiplicative way. For example, value 0.5 = double firing speed, value 0.1 = ten times the firing speed, value 4 = 1/4 firing speed, etc.
    faster reload rate - Changes the reload time. Works the same as the firing speed from above, as its inverted as well. Lower value = faster reload time.
    apply z velocity on damage - Gives the target upward velocity when taking damage from the weapon. Negative values push the player down to the floor (and a big enough negative value will cause fall damage).
    minicritboost on kill - Gives minicrits upon killing someone with the weapon (for x seconds) (x is the value you put after this attribute).
    Set DamageType ignite - Sets enemies on fire if they take damage. Works only on weapons that can naturally apply burn damage, like all flamethrowers, huntsman arrows, huo-long heater, bison, pomson, mangler, etc.

    Example #2, by BlacKy:
    My personal example consists of a boss soldier + its medic companion being implemented like this:



The monstrosity that you see before you is a called a flashing medic. No, it doesnt lift its top ;), instead, it constantly pops its very short uber in a matter of seconds, going in and out of ubercharge all the time. Its target, tho, is the real deal: A soldier that has a very low firing rate, yet very dangerous Direct Hit with an insane damage, projectile speed and blast radius.
I'll skim over the attributes of these 2 bots:
StartWaveWarningSound & FirstSpawnWarningSound will be explained in the GCFScape section of the guide.


Custom bots - Part 2
As for the medic's attributes:
SpawnWithFullCharge - The bot will spawn with a full charge on whatever 'rage' meter it has, it can be the pyro's mmmph meter, soldier's rage meter (for banners), etc. In this example it means that the medic will spawn with full ubercharge.
WeaponRestrictions SecondaryOnly - The medic will only be able to use its medi-gun.
Item "The Macho Mann"
Item "ttg badge"

^^ Cosmetic items with their real item names (Here's a task for you - find out what is the in-game name of 'ttg badge').
Item "powerhouse_medigun_sparkoflife" - The actual item name of the used medigun. This is one of the war-painted reskin variants.
"ubercharge rate bonus" 25 - Giving the medigun 25x faster ubercharge rate.
"uber duration bonus" -6 - Giving the medigun '-6' seconds more ubercharge time, which in turn means 6 seconds less ubercharge time, which again means only 2 seconds of actual ubercharge (instead of the default 8).
"heal rate bonus" 500 - Heals its target 500x faster than usual, essentially making the target (soldier boss) to be immune of any damage.
"bot medic uber health threshold" 100000 - Forces the medic to pop its ubercharge if it has less health than the specified value. In this case, the medic will always pop its uber when it can as it will always have less health than 100,000. This attribute acts as a guarantee that the medic pops its uber at all times when the meter is full.
"move speed bonus" 0.5 - Simply cuts the bot's speed by half.
"airblast vertical vulnerability multiplier" 0.0
"airblast vulnerability multiplier" 0.0

^^ These 2 attributes generally work together. They restrict the bot's knockback from airblasts. Typical giants usually have values of 0.5-0.6 for the vertical vuln, and 0.2-0.3 for their overall vuln (the shorter attribute). Since these are the endgame bosses, i wanted to restrict a pyro from pushing them back entirely so he wont be able to cheese the mission. This is generally good to be used on bots when there's a death pit in the map.
"damage force reduction" 0.0 - Very similar to the previous 2 attributes, but it works against the heavy's rage. Basically it means that the closer the value is to 0, the less knockback the bot will feel from a heavy's rage upgrade, thus reaching a similar effect.
"rage giving scale" 0.5 - Another player penalty. This will hinder the amount of 'rage bar' the player will get from damaging this bot. This effects phlog's mmph, soldier's buff 'rage', and heavy's minigun 'rage', alongside other niche weapons. Lower value = more restricting

Soldier boss' attributes:

Scale - Resizing the scale of the bot. value 1 = its default normal size, 2 = double that size, 0.1 = one tenth of the normal size, etc etc.
Attributes AlwaysCrit - Simply put, it gives the flashing blue border around the bot's icon, thus making the bot always shoot crits.
Tag bot_giant - Similar to 'attributes Miniboss', but this one only controls the gate-stun for gatebots. Adding this tag to bots will guarantee that they wont get a gate-stun effect on gatebot maps. This is generally used on giants. Its actually irrelevant for this particular bot because there arent any gatebots in this specific wave so the gates can't be capped anyway.
"blast radius increased" 10 - Increased multiplicatively the blast radius of the item, so this means x10 higher blast radius.
"use large smoke explosion" 1 - Gives the projectile a large smoke screen upon exploding. This is what makes Valve's Sir Nukesalot so annoying in their Rottenburg mission.
"damage bonus" 3.5 - x3.5 higher damage to the weapon.
"fire rate bonus" 5 - This attribute cuts the firing rate by 5. It works invertedly than how other attributes work. In other words, the bigger the number = the lower the firing speed. So to simplify this particular value, the firing speed is x5 slower.
"faster reload rate" 0.2 - Another inverted attribute, which works the same as the firing speed attribute from above. Lower number = faster reload speed. So this one is x5 faster reload. (its technically pointless tho, as the normal reload speed will be slow enough for the very slow firing speed. I can technically remove this and nothing will be changed in game.
"override footstep sound set" 5 - The sound type of the footsteps this bot will make. Every bot class has its own number for its own sound of footsteps (excluding the medic as it has a wheel instead of legs). You can sniff around the Valve templates to find the numbers they used on their giants.
Gatebots analysis
Gatebots are a more complexed type of bots to make than normal bots and as a beginner, you may feel better to stick with the gatebots Valve have supplied to us. However, if you choose to build them from scratch, here are a few pointers to make your life a bit easier.


This is an example of a cirt a cola gatebot scout. Lets dissect the important lines of code:

EventChangeAttributes - Tells the gatebot to change it’s behavior after the gate has been captured.
You need to put basic info before this syntax like the health, name, class, and classicon. Everything else belongs inside this syntax.
Right after you open the EventChangeAttributes syntax, you need to open another syntax, called...
Default - A syntax that tells the bot what should they do when the gate is not captured.
You put all of the attributes here. However, some lines are exclusive for gatebots, such as:
"Tag nav_prefer_gate1_flank" - Tells the bot if to flank or not. While this is not necessary on missions with no gates, you need to give a nav_prefer to a gatebot so it goes the correct path. This nav_prefer should be present in all gatebot maps, so don't worry about name issues.
"MvM GateBot Light Scout" - The yellow flashing hat the gatebots have to make them stand out from other bots. One hat per class. This specific example defines the scout head.
BehaviorModifiers - Tells the game to alter the bot’s normal behavior. While this is not gatebot exclusive, it is something that all gatebots should have. In this case its “push” - A modifier that makes the bot go to the gate or (if the gate is capped or there is no gate) go to the hatch and then to the bomb.

Close the Default syntax and let’s move on to the second half.

RevertGateBotsBehavior - Tells the game what should the gatebot do after the gate is capped.
You can basically copy and paste the Default syntax contents and put them here. Just be sure to remove these commands:
- IgnoreFlag Attribute
- BehaviorModifier
- Nav_prefer
- tag bot_gatebot
You also need to turn off the gatebot hat. To do this, write this in the syntax:

Random attributes
A list of random attributes with their descriptions. This list will be split into 3 categories: Attributes, ItemAttributes, and CharacterAttributes.

Attributes:

ProjectileShield - Enables the medic to use a shield.
VaccinatorBullets / VaccinatorBlast / VaccinatorFire - Used on Medics. Gives the medigun Vaccinator-like 'resistance bubble' for the corresponding damage type.
TeleportWhere - Used on Engineers. Value is which type of spawn can use their teleporters. this is used if you want to limit certain bots that spawn in a unique spawns to not use the teleporters (like with bosses).
Miniboss - Makes bots as giants.
AirChargeOnly - Used on Demos. Restricts a demo with charging only when in mid air.
IgnoreEnemies - Bot Doesnt engage in combat with the players.
AutoJump - Makes the bot jump. Used with other attributes that sets jump parameters.
AutoJumpMin/max - Sets the minimum/maximum time gap (value in seconds) per jump (see the samurai demo from valve's robot_standard popfile as an example).
BulletImmune / BlastImmune / FireImmune - Gives the bot vaccinator immunity bubble for the corresponding damage type.

ItemAttributes

"sniper charge per sec" - Sniper charge meter goes up faster multiplicatively to the value. E.G - value 4 = 4 times faster charge.
"item style override" 1 - Sets a different style of the item if it has one. Can be used on cosmetics with multiple styles, or for enabling Australium weapons.
"sniper fires tracer HIDDEN" 1 - Gives bullets Machina-like tracer effect.
"set item tint rgb" - Gives an item (generally a cosmetic) a color based on the color values of paint cans. Full list of color values will be given later in the guide.
"effect bar recharge rate increased" - An inverted attribute that controls how fast or slow a recharge meter will be filled (lower number = faster recharge). This attribute works on items like the sandman, flying guilliotine, jarate, etc.
"clip size bonus" - Multiplies the size of a bot's weapon clip by the value specified.
"fuse bonus" - Multiplies the amount of fuse time a pipebomb has, before it explodes.
"attack projectiles" 1 - Used on heavies. Turns their minigun into a Deflector. Value is set like in the upgrade station, of either 1 or 2.
"disable weapon switch" 1 - Given to an item that forces a switch to another item, for example if the item is throwable and needs to be recharged, having this attribute on this item will keep the bot with 'empty hands' until the item is recharged.
"dmg penalty vs players" - An alternative attribute to the main damage attribute. This one works on certain weapons that can't use the proper damage attribute, like flying guilliotine, bison, gas passer's EoI upgrade, etc. Higher value = higher multiplicative damage.
"explode_on_ignite" 1 - Specifically made for the gas passer EoI, it enables the explosion damage factor in the weapon.
"medigun fire/blast/bullet resist passive" - Gives the Medic and its target a static fire/blast/bullet resistance. Value goes between 0 (no resist) to 1 (full immunity). Used on Vaccinators.
"medigun fire/blast/bullet resist deployed" - Gives the Medic and its target an ubercharged fire/blast/bullet resistance. Value goes between 0 (no resist) to 1 (full immunity). Used on Vaccinators.
"medigun charge is resists" 3/4/5 - Goes with the other Vaccinator attributes. This attribute needs to be added for a Vaccinator medic to work properly. 3 = bullet vacc, 4 = blast vacc, 5 = fire vacc.
"lunchbox adds minicrits" - A comprehensive attribute with many values as they all do different things. The value you need to know about is 3 = It changes how the specified medigun behaves into how the Vaccinator behaves (multiple ubers, vacc sounds, etc).

Side note: 'lunchbox adds minicrits', 'medigun charge is resists' and 'medigun fire/blast/bullet resist passive/deployed' are all attributes that were designed to give vaccinator effects onto the stock
medi-gun. The reason why you shouldn't just use the Vaccinator as its own weapon is because of a cosmetic bug this weapon has with the source engine.

"aiming movespeed decreased" - Used on heavies. This attribute controls the heavy's speed while spinning up its minigun. Higher value = higher speed
"projectile spread angle penalty" - Gives projectiles angle deviation factor (value = angle). Basically makes every projectile-type weapon shoot like the Beggars Bazooka).
"explosive sniper shot" - Used on Snipers. Value simulates the amount of points you spend in 'explosive headshot' from the upgrade station.
"Bleeding duration" - Adds bleed effect on the weapon. Value = seconds of bleed time.
"turn to gold" 1 - The player turns into a golden ragdoll if they die by a bot having this attribute.
"attach particle effect" - Gives the item a particle effect from Valve'e unusual effect list. Full list can be found here[backpack.tf]. The value is the hash number from the list, for example value 36 = steaming effect. Unusual effects can be applied on weapons too, some would look really good and others wont.
"weapon burn dmg increased" - Gives the weapon afterburn damage. higher value = higher damage.
"mark for death" 1 - Applies the Fan O-War's mark for death effect on hit.
"bullets per shot bonus" - Value multiplies the amount of bullets per shot. Beware as this attribute can cause performance issues if being set too high.
"item_meter_charge_rate" - Controls the fire/charge rate of the certain weapons like the Dragon Fury, Gas Passer, and more. Higher value = slower rate.
"heal on hit for rapidfire" - Value adds health to the bot, per hit.
"flame drag" - Used on flamethrowers. Changes how long/short the flame distance will be. Default value is 8.5. Lower value (than 8.5) = longer flame.

CharacterAttributes

"sapper degenerates buildings" 1 - Turns a sapper to have Red-tape recorder sapping effect (using the red tape as its own weapon wont work so this is a work around).
"generate rage on heal" - Give medics a shield. Value is either 1 or 2 just like how you buy a shield from the upgrade station. Goes together with ProjectileShield.
"increase buff duration" - Value multiplies the times of rage based weapons, like soldier's banners, phlog's mmph, etc.
"fire rate bonus with reduced health" - The bot's firing speed will actively go towards this value as its health drops. Usually used on bosses to set their firing speed to increase relatively to their health.
"health regen" - Adds health to the bot, per second.
"Rocket specialist" - Adds the Rocket Specialist upgrade to the bot. Value simulates the amount of points you would purchase from the upgrade station.
"airblast disabled" 1 - Disables the use of airblast for this bot.
"cannot be backstabbed" 1 - Bots with this attribute can't be backstabbed.
"bot custom jump particle" 1 - Another attribute that sets a bot to jump.
"increased jump height" - Sets the height of the jump (higher value = higher jump).
"charge recharge rate increased" - Value divides the time it takes for a demo shiled bash to be recharged (higher value = shorter cooldown between charges).
"Attack not cancel charge" 1 - When a demo bot attacks during a shield bash charge, it will not stop the charge during its attack.
"charge time increased" - Value multiplies the amount of time a demo bot spends in charge mode.
"head scale" - Scales the size of the head of the bot relative to value 1 (lower = smaller. Higher = bigger). This attribute has several variants for other limbs like torso, arm, etc.
Advanced gimmicks & Random info
So far we've covered most of the basics that you need to know to make a properly built mission. Note that a mission doesn't has to have gimmicks in order to be good. What it needs to have is a good execution and lack of ways to be cheesed with certain classes, good spawn timings, and of course, be fun!

Custom Sentry Busters

Fun fact: Any bot can become a sentry buster. All it needs to have is the proper 'objective', which is 'DestroySentries'. When given this objective to any bot, it will obtain the buster's model and go after the sentries instead of the bomb.

An example of a buster that drops an iron bomber's bomb on the floor every 2 seconds:



An in-game break time

What i mean by a break is a short period of time that nothing spawns and (usually, but not always) the front upgrade station opens to let you buy more upgrades for a short time before the wave continues. This is usually used in endurance mode where waves can take around 10 minutes each.



This wavespawn will force a 10 seconds pause and reset the bomb back to the bot's spawn silently (without giving an announcer alert). If you want the announcer to mention the bomb reset, you need to type “ForceReset” Action instead of "ForceResetSilent". These kind of wavespawns are commonly called 'dummy wavespawns' because they dont really spawn anything in game, they just help the popfile relay a command integrated within them. The relay “intel” is the relay that references the bomb.

So now let’s tackle the break time. Let’s say you want to have a 30 second break with the bomb resetting. What do you need to do? First up, reset the bomb using the output shown above.
Then, you need to notify the players about the break using FirstSpawnWarningSound. Pick a good administrator voice line using GCFScape. The most common ones are the “Mission begins in 60/30/20/10 seconds.”.
Lastly, you have to make the next wavespawn appear the correct time after the pause. For instance, if the pause is 30 seconds, the next bot WaveSpawn has to spawn 30 seconds later. Take a look at this simple 30 seconds break system as an example:



Dual-Wielding bots

You can make bots to hold and fire 2 weapons from 2 different weapon slots at the same time.
For example, a soldier bot that uses its rocket launcher and its shotgun at the same time. To do this, you will need to set 2 things in the template (following the above example):
1) Restrict the bot on using only one of its weapon slots with the 'WeaponRestriction' command, for one of the weapons its going to use (the rocket launcher for this example).
2) Add item attribute "Is_Passive_Weapon" 1 to the other weapon its using (the shotgun for this example).
This will force the bot to use both weapons at the same time. You can add 'ItemAttributes' section for each of them to modify their stats as usual. Also note that giving "Is_Passive_Weapon" 1 to two weapons will result in a crash.
* Thanks for The Fat for contributing (and teaching me) this neat gimmick.

Example for the gimmick using my boss:


This boss will use both its Flying Guillotine (secondary) and its stock bat (melee). The idea is to give it a way to damage buildings so it wont be blocked (guillotine doesn't harm buildings).

Side note: Giving a bot a passive weapon like this will cause their weapon stance animation to glitch out, as the bot will now use the weapon stance of the passive weapon, while firing both weapons. Be mindful of how it looks in game.

Using Engineers as combat bots

Engineer Bots have one goal in mind: Go to a certain spot, Build a Sentry and a teleporter and sit there. If we place just an Engineer in the main wavespawn, it will act just like we used it in Mission Support. Using the magic of Squads, we can prevent them from doing just that. If we put them in a Squad, we can prevent them from building nests. Do note however that if the Squad leader dies, the Engineer bots will start building nests. To prevent this from happening, we use ShouldPreserveSquad 1, which I've explained in the Squad section. At all times, the squad leader mustn't be an Engineer for the Engybots to work properly.

Custom projectiles

This is a gimmick that enables a bot to fire a different projectile from what its weapon is supposed to fire. For example - A scattergun scout that shoots medic syringes, A minigun heavy that shoots flares, etc. The (item) attribute is called "override projectile type" and the value can be one of these numbers (note that this attribute can be somewhat broken with certain values. Make sure you test the results properly):

1 - Bullet
2 - Rocket
3 - Pipebomb
4 - Stickybomb
5 - Syringe
6 - Flare
8 - Huntsman Arrow
11 - Crusader's Crossbow Bolt
12 - Cow Mangler Particle
13 - Bison/Pomson
14 - Stickybomb (Sticky Jumper)
17 - Loose Cannon
18 - Rescue Ranger Claw
19 - Festive Huntsman Arrow
22 - Festive Jarate
23 - Festive Crusader's Crossbow Bolt
24 - Self Aware Beauty Mark
25 - Mutated Milk
26 - Grappling Hook
27 - Sentry Rockets
28 - Bread Monster
29 - Gas Can

~~Fires nothing~~

7, 9, 10, 15, 16, 20, 21

Tint RGB values

As promised, here are the paint values you add after the (item) attribute "set item tint rgb" (note that any individual bot can only have up to 1 painted item at all times):

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 Abundance of Tinge---------------- 15132390
A Distinctive Lack of Hue------------- 1315860
Pink as Hell------------------------------ 16738740
A Color Similar to Slate--------------- 3100495
Drably Olive----------------------------- 8421376
Taste of Defeat and Lime------------ 3329330
Gentlemann's Business Pants----- 15787660
Dark Salmon Injustice--------------- 15308410
Mann's Mint---------------------------- 12377523
After Eight------------------------------ 2960676

Team colors:

Team Spirit
- 12073019 - RED
- 5801378 - BLU
Operator's Overalls
- 4732984 - RED
- 3686984 - BLU
Waterlogged Lab Coat
- 11049612 - RED
- 8626083 - BLU
Balaclavas are Forever
- 3874595 - RED
- 1581885 - BLU
An Air of Debonair
- 6637376 - RED
- 2636109 - BLU
The Value of Teamwork
- 8400928 - RED
- 2452877 - BLU
Cream Spirit
- 12807213 - RED
- 12091445 - BLU
P3
P3 is used mainly to detect issues with your loaded popfile. More often than not, you will use it to parse (load and scan) the desired popfile into P3 and it will check for syntax errors and faulty attribute values.
Lets go in step by step of how to use it (examples are taken from version 2.0.0).

  • Install the program and run the .exe file.
  • Locate the place you've saved your popfile (should be in tf/custom/pop/scripts/population - more on that later), and open it.
    For the sake of example, i will use one of my own missions as an example, called mvm_oxidize_rc16_int_humane_labs.pop.
    The P3 screen will present you with the the following:


    The example shows how it first parses the 2 base files that this popfile refers to in lines 5 - 8. Line 9 refers to the parsing of your own popfile (note that if you had a gatebot base file, it would have parse it as well).
    The green line shows that there is nothing wrong with the popfile according to P3 so you can continue to the next step of playtesting your mission to check how everything spawns and get the feel of being inside of the popfile you wrote - more on that step later).

  • Lets simulate common errors and see how P3 refers to them.


    If you get a message like this, look up the types of warnings it brings up. You can see 2 errors in red, representing a broken syntax, and below that, 3 warnings in yellow, representing an illogical syntax that may break the mission while it runs.
    Generally speaking, fixing the red (crucial) errors solve the cautionary warnings in yellow, so these red errors are the first thing you should worry about when you parse a popfile.
    Every error and warning given by P3 directs you to a line of the code in the popfile, in this example, the 2 error lines are 1201 and 1202. So what you need to do next is to go to your popfile and see whats wrong with it:



    Can you spot the errors?
    They're both caused by the lack of "}" for the TFBot FaN scout
    This was caused by one of the many syntax errors you will encounter while manually writing a popfile, which is why i highly advise to try and copy-paste parts you know that work onto other sections, and then simply modify their values to suit the needs of the other wavespawns. This will create much less hassle with unexpected errors and much less head scratchings.
    As for the 3 yellow warnings, they were caused by the fact that the P3 didnt recognize wave 5d in the popfile as it was broken by that one syntax error, so it refered any other wavespawn (in lines 1204, 1249, and 1279) to be potentially broken as well.
    Everything was fixed by fixing the one mistake.

  • Another type of error that can be seen is this:


    At first glance, it looks like the entire popfile is broken, right? Well fear not, as it basically says a similar thing as the previous error. If you get an error result like this, dont freak out. Just take a look at the first line it refers to that has an error, in this case, line 22:



    Can you see whats wrong? Here's a hint, its a flaw about the basics of popfile writing.
    Actual problem: There is no bracket system for 'WaveSchedule' before the 'Mission Support' part begins.
    Once you have fixed the issue P3 was pointing at, save your popfile again and press F5 in P3 to reparse the popfile for an updated result. Rince and repeat until P3 says 'Finished cleanly' in green.

  • Now i'll go through the important sections of P3:
    - F1 - Prints out the money gained by the mission. Here you can track how much money you set in each individual wavespawn, total money gained per wave, with or without the A+ bonus, and the starting cash.


    This example shows that the first subwave drops 300$, the 2nd and 3rd drop 100$ each, 4th drops 50$, etc, for a total of 850$.

    - F6 - Gives you the search option for P3. This is where you type and search for all the items you want to know their real names for. It can also search for names of attributes, but i find that using the wiki page is easier.

    An example of how to search an item with an easy name: If you want to search for a known weapon but you dont know 100% how its called, but only part of it, you type the key letters in the search menu. For example, the stupidly coplexed name for the demoman's sword. What was it?! ends with 'mor', i think. So you type in 'mor' to get the following results:


    Now you can see its proper full name in the first result, The Claidheamohmor (which is a bit different than how Valve calls it in the item inventory).

    An example of how to search an item with an unknown name:

    So for this example, i'll use one of the EOTL items in the game. EOTL refers to 'End Of The Line', as it gives a pack of items released from this update under that same prefix. So lets say you want to give a bot the item called in game 'Snow Sleeves'. You search for it on P3 and cant find anything in there. What do you do? You go to the file called 'TF_ENGLISH' (located in tf/resource), open it and search the item there. From there you will find this part of the file:


    To the left, you will see the items list as how they're called in the game file, and to the right you will see their in game names. So snow sleeves is actually called 'EOTL_hiphunter_jacket' (ignore the TF_ prefix for these names). you can double check this with P3 by placing "hiphunter" in there to see if the syntax is correct.
VTFEdit & GCFScape
Both of these programs are used just for greater immersiveness of mission making. They're not mandatory but will help expand your knowledge of how to make even fancier popfiles down the road.

VTFEdit

This one is very short and easy to understand. After installing it, you will have access to viewing all the icons in the game. Icons have 2 file formats: .VTF and .VMT. The custom icons are saved in tf/download/materials/hud. Each icon is made of the 2 files mentioned above and can all be viewed by VTFEdit if opening the .VTF file. The .VMT file doesnt show the icon itself, but only the general info the icon is saved with, tho you need both types of files for each icon to be shown in game.
If you want to use a custom icon for your mission, you will need to know how to place its name correctly in the popfile. So lets take an example of a custom icon called (in the hud folder) - "leaderboard_class_scout_fan_bonk". To implement this icon in the popfile, you need to copy-paste the part that starts after 'class_', which is just 'scout_fan_bonk', into the popfile, under the command 'classicon'. The final result will look like this:



Side note about giant bots icons: If you happen to have both a giant and a normal bot with the same icon name, for example, 20 normal scout_fan_bonk scouts and 1 giant scout_fan_bonk scout, they will appear as 21 giants in the icon bar in game. This is generally called 'icon stacking', and its because the game prioritizes giant icons over normal icons so the giant type 'swallows' the normal ones.
To counter this, you will need to make a 'giant' icon variant for your giant bot to be used in the popfile, to differentiate the 2 types of icons. To do this, all you need to do is to take the .VMT file of the icon, copy-paste it to somewhere else (e.g desktop), rename the new copied icon to <whatever the icon name was + _giant>, so the icon example from above will be copied and renamed to 'leaderboard_class_scout_fan_bonk_giant.vmt'.
There is no need to do this procedure for the .VTF file. Place the new icon back in the hud folder and rename the icon in the giant's wavespawn to 'scout_fan_bonk_giant'.
* This entire step isnt needed if one of these wavespawns are in the support section of the wavebar.

Another side note: Giant bots that spawn as support will never have a red background on the icon, so take that into consideration, should you want to place giants as supports, as it will be a bit misleading.

Community icon pack[drive.google.com]
This is an icon pack that contains a few thousands of icon files for you to have without the need of waiting to be downloaded by the server (instructions are included of how to implement them).

GCFScape

This program manages the .VPK files that Valve has provided us. These files contain all of the sound files the source games can run, including CS:GO, Portal, HL2, and of course TF2, and more. The main usage of this program in regards to mission making is to add voice files to be heared in game. These can be informative message lines like for setting a break time, or a complete meme idea with funny sounds, as well as full music files that are played in game.

Install and open the program and you'll see an empty window split in half. On the top left corner, click 'open' and navigate to the tf folder of TF2. From there, locate the 2 important files that give you most of the TF2 asset sounds, called tf2_sound_misc_dir.vpk and tf2_sound_vo_english_dir.vpk. The 'sound misc' file packs the background and ambient sounds, and the 'sound vo english' file packs the voice lines by the mercenaries and the other side characters of the game. We will focus on the latter, so open tf2_sound_vo_english_dir.vpk.


Before we continue, you will want to know what you're actually looking for, or rather, what you're trying to implement. Lets give a nice example of adding a 'tank!' voice line by the Engineer when a tank spawns in your popfile. The first step is to actively locate the sound file from within the vpk file. The best way of doing this is to use the wiki page, so lets hop there for a moment. Go to the TF wiki page and type 'responses' in the search box. You should see this page. From this page, you can filter all the voices by classes, plus the sub classes like Ms. Pauline, the Administrator, etc. Click on the 'Engineer Responses' link. In this page you will see the voice responses of everything the Engy says in game. Locate your desired voice line (use the web search feature for 'tank') and click on it (its best to open in a new tab). Each of these voice lines are links to their uploaded voice lines in the wiki. The web page address will give you a hint of whats the voice line name in GCFScape.
For this example its:


So now we know that the voice line's actual game name is Engineer_mvm_tank_alert01, and this is what you search in GCFScape, so lets go back to it. Inside GCFScape, and inside the opened file 'tf2_sound_vo_english_dir.vpk' click on the magnifying glass icon and type your desired voice line's name > find it in the search results (you can click on it to hear it and confirm its the file you want) > right click the sound file and select 'properties' > copy the 'location' path from where "vo" starts, so that would be "vo\engineer_mvm_tank_alert01.mp3".

A pic to sum all the steps:


Now that you have the desired voice line as a command for the popfile, you paste it in one of the 4 voice line commands that defines how and when the voice file should be triggered:
StartWaveWarningSound - Adds a sound file to the mission. The sounds can be anything you set it to be via GCFScape. The sound will be heared once the subwave starts.
FirstSpawnWarningSound - Adds a sound similarly to the previous command, but the sound will activate only when the first bot has spawned, so essentially the only difference is the time gap that WaitBeforeStarting represents.
LastSpawnWarningSound - Adds a sound for when the last bot of that wavespawn spawns.
DoneWarningSound - Adds a sound for when the wavespawn has ended (last bot is killed).



Side note: This particular .vpk file has many voice lines in bots voices. You wont find them in the wiki as they're the same voice line just with an added filter that makes their voice to be more mechanic. These voice lines are under the folder "vo/mvm/norm". There are even deeper-voiced voice lines that belong to the giant form of these bots. These voice lines are located in "vo/mvm/mght". Not all the voice lines will have this giant voice filter on. The example above will voice the human version of the Engineer.
Mission playtesting
Well now, if you’re here, I’ll assume that you've already created your mission. If you did that then congratulations! This is an important milestone. But before you show the world what you've made, you need to test it offline first to see if everything is spawning correctly (for these steps, i'll use The Fat's mission popfile as an example - mvm_sequoia_rc4_int_planck_particle).

Nav file preparation:

Before you attempt to play your mission, you will need to make sure the map its set on has a .nav file in the proper location, as if not, you wont be able to see your mission, and you will only see a 'wave 0' in the wavebar (this is only relevant for community maps. If your mission is set on a Valve map, you can skip this step, but its better to make sure you understand this step anyway, for future playtests). The file is called <map name>.nav, for the this example, i will use mvm_sequoia_rc4 as the map being played. Its .nav file will be called 'mvm_sequoia_rc4.nav'.
If you've played in this map in a community server, then the file should be located in "tf/download/maps". Copy & paste it to "tf/maps".

After you've finished working on your popfile you can save it as
mvm_[map name]_[difficulty]_[mission name].pop. So for this example its
"mvm_sequoia_rc4_int_planck_particle.pop" (rc4 is the map's version, its part of the map's name. int is the difficulty of the mission, which means 'intermediate', and planck particle is the name of the mission). Make sure the popfile is saved in "tf/custom/pop/scripts/population" and has no upper case letters. Run the map offline by typing this command in the game console:
map mvm_sequoia_rc4

From here the game will load the map you chose. After loading the map, go to the votemenu section and pick the mission you've made (if this is the only mission you've made, you should see only that mission, and this means that you wont be needing to vote for it at all).
Now that you're in your mission, its time to actually playtest it and see how good bad it actually is. There is always something that you couldn't have foreseen while writing the mission in the popfile, even if its your 10th mission being made, so take this step as a necessary one to figure out what is wrong with the mission when it comes to overpowered / underpowered enemies and the way they spawn.

Console commands and how to use them

As you're alone in this playtest, you will need some super powers to keep you alive, so here’s a couple of useful commands to make testing easier:
(all of these require sv_cheats 1, so type it first)
currency_give x - Liteally gives you the money value you type instead of x. Note that too much money (over 30k) could brick your mission, so its usually preferrable to add ~12k-20k, as its more than enough to buy the upgrades you need anyway.
Addcond commands - They give you special powers that are generally are effect types you encounter in game. To remove the effect, type 'removecond' instead of 'addcond' with the command number.
addcond 56 - Constant crits
addcond 91 - Firing speed boost, reload speed boost, clip size boost, max ammo boost (note that this is a power up that you can't activate in the spawn room, as it will drop the powerup on the floor and you won't be able to take it. You must leave the spawn room before typing this command).
impulse 101 - Refills your ammo and health to max.
god - Gives godmode (can be typed multiple times as a toggle)
noclip - Makes you fly really fast, and clips you through walls.
tf_bot_kill all - Kills every bot that has spawned (doesn't effect tanks, bots that haven't spawned, are in an ubercharge state and\or are in a bonk! state).
ent_fire tank_boss sethealth 0 - Sets all active tanks to whatever health value is written (example for 0), tho note that if setting it to 0, the tank will still need to be manually killed by any type of damage, effectively setting the tank to 1 hp instead of 0
tf_mvm_jump_to_wave x - Jumps to a certain wave you value instead of 'x'

A full list of addconds, impulses, and many more commands can be found here.
Final tips for mission making
  • Enjoyability. If you’re making a custom bot, ask yourself a question: “If I would encounter this bot ingame, would I have fun fighting it?”. While you are not limited to what you can put inside these bots, know some limits. Some examples are:
    - A heavy bot that shreds you unless you have full bullet resistance.
    - A soldier bot that has a rapid fire hitscan high damage rocket launcher.
    - A medic bot that has ubercharge almost deployed at all times only being able to be killed via map hazards.

    The problem with these kind of bots is that they force the player to pick a specific playstyle/upgrade path to counter them, thus killing the joy of choosing a playstyle of your own. With that being said, in expert missions you'd want to give some challenge to the players so a tough fight here and there is more than ok, just know the boundaries of what makes or breaks a bot's toughness.

  • Mission readability. If you've confirmed the bot would be enjoyable to fight against, now ask this question: “Would it be easy to know what it does?”. While creating a custom bot is fun, you also need to make it tell to the server and players its gimmick. Wherever its by the icon, the hat or by something else.

    Some examples are:
    - A medic that has 300 health. It should be a bit bigger or have a shield/armored icon.
    - A soldier bot that fires a barrage of rockets should have a different icon than other bots, preferrably depending on the barrage style (actual barrage, rapidfire, burstfire, etc).
    - A bot that is usually faster than what its class would suggest should also have a proper icon to alert players about its modified speed, or rather, a bot that snares players should definately have its own icon.

  • Avoid artificial difficulty. When playtesting a wave, you may come to the conclusion that 'its not hard enough' for what you aimed it for, and your immediate action may be to 'just add crits to everything' or 'spawn more giants'. These are usually viewed as lazy ways to buff a wave's difficulty, and they don't look appealing in terms of mission design. A better way to buff a wave is to shorten spawn times and increase the spawn rates.

    Other notable mistakes:

    - Adding too much health to a Tank just for the sake of 'it can be destroyed anyway'.
    - Making a wave with just tanks + supports.
    - Making everything come out all at once.
    - Giving extra health to giants just to increase the difficulty.
    - Spamming any type of banner soldiers, and especially battalion soldiers.
    - Adding bots that are too hard for the mission.

  • Dont scrap bad ideas. So you've built your 'Dragon Furry' pyro that shoots Doge dogs instead of fireballs, but it plays bad in-game for whatever reason. You may feel upset and would want to scrap it entirely from the popfile to work on something else. DONT! Instead, put it in a template and save it somewhere in the popfile (or even in a notepad), and THEN remake your bot from the ground up. The idea is that you may want to view your bad templates in the future and rework them into something properly operatable and fun. You may feel regrets destroying it entirely because you've felt out of muse at that time.

  • "Is there an attribute that... ?"

    When customizing a bot of your own, you would want to think of some wanky features to give it, but sometimes you wont be sure if theres an attribute for that purpose. You may find yourself asking ‘is there an attribute that does this and does that?’ Well, there is an easy way to find out: If there is a weapon that does it = it exists.

    Real example: I wanted to make a gatebot that has increased capping multiplier (just like how the scout caps gates as at the speed of 2 bots), so to figure it out, i had to think of a weapon that has this attribute in it, for this example, the Pain Train, and then see how its mentioned in the items_game.txt file which is located in tf\scripts\items.

    Looking at that file, you can extract the part of the attribute you want to pull out, so for this example, open the file, press ctrl+f and search for 'pain train'. The search result should lead you into this section:


    From here you can manually search the attributes section, which in this case you can see it has 2: "increase player capture value", and "dmg taken from bullets increased", both with their respective values. If you're not sure which value you need to put in there, just try some trial and error with values and see the results on your own (its good to have the mentality of 'knowing what doesn't work as well as what actually works').
    With that information, answer me this (in the comments):

    "I want to make a half-zatoichi Demo boss. I have made it as how I want it to behave but there is a problem - The boss retains the zatoichi's element of dying with 1 hit by another players that holds the zatoichi. How do I eliminate this 'bad attribute' from the boss?"

  • Don't make multiple missions at once. As a beginner, you should consider quality over quantity (well, you should consider this in any time you make missions, but this is more true when you have less experience). Focus on a single mission and refine it properly till you feel its a solid piece, then, you can consider starting another one while finalizing it with playtests.

  • Dont make your first mission as expert difficulty. Expert missions are much more complexed to make than int and adv missions and they have their own guidelines of what not to do, so try to gain your popfile writing experience with something simple and easy.

  • You cant rush art, so don't force yourself into mission making, nor set a deadline for when a mission must be completed. If and when you feel out of muse, take a break and think about how well Half Life 3 was when it came in the year 2733 focus on other things. Play some custom MvM to get inspired (but don't directly copy other people's templates, unless they've shared it purposefully to be copied). If you force yourself to finish a wave/mission, then you're doing it wrong. Quality matters!

  • Use the MvM community to help you. A good place to try is Potato's Discord server[discord.gg], under the #missions channel. They're mostly highly experienced mission makers and have loads of info to share, so don't be shy to ask them anything you want, to help refine your mission and overall experience.
Final tips for playtesting
  • Binding at least some of the playtesting commands as you will need to use them a lot while testing. To bind a command, open console and type 'bind [key] [command]', so for example to bind godmode into the key 'P', type "bind p god" in the console. This specific command is toggleable, so this means you can keep pressing P to toggle godmode on and off.

  • Make a mission changelog. Open a notepad file somewhere in your pc (desktop is preferred), and put your notes regarding the playtest experience in it. Either remember the changes you'd wish to implement after every wave to write them between waves, or write them while the wave is being played, but either way, making a list of changes like how this example below shows will enhance your work ethics when it comes to mission making, and will remember the little changes for you.



    Side tip: After applying the changes in the popfile, add a symbol near every remark in the changelog, like the asteriks in my pic example. This is how you could identify the changes you havent applied yet from the rest of them.

  • Error detection. If switching between waves crashes your playtesting session, dont panic. It probably means theres something wrong with the popfile that you (or P3) will need to investigate. A common error that spots a faulty popfile is "host_endgame: Buffer overflow in net message". If you get this message then just reparse the file in P3 and let it spot any other errors you've missed.

  • Be prepared to take a lot of criticism. When testing your mission on the testing server, prepare to hear a lot of bad things about your mission. It's something that everybody has experienced. Hell, even us, the authors of this guide, made "questionable" missions as their first ones, (and one of them still makes questionable missions to this day) (no seriously don't pick Bipolar Bruh Moment on testing server's Rottenburg), but we got over that phase, learned from our mistakes and now we are skilled enough to know what doesn't work.
    Most people give feedback that is useful, like: "This is bad, here's how you can fix it.", but some of them just say: "This is bad" because they don't like it, not because there's something wrong with it.
    Its important to identify the bad criticism based on someone's opinion, like 'I hate pistol scouts, they're dumb'.
    You can partially ignore comments that people say to try to shape their ideals of how a mission needs to look onto your work. At the bottom line, if you like how it looks, then its good enough.
Wrapping up
Making missions is what you make it. It can be fun, tiring, frustrating, or probably all of the above, but most of all its redeeming. Redeeming to see people play your work, you will feel like a lion amongst sheeps as if you've made an entire game for others to enjoy, and this makes the entire experience so much worthy.

Personal thanks goes to:

The Fat for contributing much of the written parts of the guide by his own info and experience.
Many other friends and individuals whom I've learned the ropes from.
The Potato community for giving us the infrastructure to build missions and destroy robots. Literally couldn't have done this without them.
My free time.
Valve for not making TF3 ;)

I leave you with a mission-making starting kit[drive.google.com] made by myself and The Fat, with some of our missions as old examples of how we started writing popfiles, alongside Valve's own popfiles from the Mann-up mode.

I hope you've had fun reading this guide, after 9 years in development, hopefully it was worth the wait, and I hope it will be informative enough on the years to come. I would love to answer the questions you may have as much as I can, in the comments section.

With regards,
BlacKy.
17 Comments
BlacKy #SlavaIsraelini  [author] 10 Aug @ 12:32am 
awesome, i'll update the guide with this link
Crafted 9 Aug @ 2:48pm 
got it, thanks man
Crafted 9 Aug @ 12:28pm 
the popfile xml thing is missing could we get a new link?
NinjaV12 2 Jul @ 11:54am 
ttg badge = license to maim
the fat  [author] 12 Apr, 2020 @ 4:10am 
"I want to make a half-zatoichi Demo boss. I have made it as how I want it to behave but there is a problem - The boss retains the zatoichi's element of dying with 1 hit by another players that holds the zatoichi. How do I eliminate this 'bad attribute' from the boss?"
Since nobody answered this question, I'll do it.
You simply put "honorbound" 0 in the ItemAttributes for the Half Zatoichi
This will override the 1 value for it which makes the boss instantly die from a half zatoichi hit.
Blue Token 10 Mar, 2020 @ 6:23am 
Nice guide there,I've made a costume wave of 666,and I totally get busted ......cheered up by this,I mean.Heh heh heh:cozyspaceengineersa::cozyspaceengineersc:
OH YEAH BABY I DRINK WATER 1 Mar, 2020 @ 3:36pm 
no problem, man
BlacKy #SlavaIsraelini  [author] 1 Mar, 2020 @ 12:38am 
Thank you both for taking your time and reading my guide. This is very appreciated.
OH YEAH BABY I DRINK WATER 29 Feb, 2020 @ 12:48pm 
Cool guide bro, thanks for making the mvm guides that you have, they have really helped me out!