Team Fortress 2

Team Fortress 2

87 ratings
A Beginner's Guide to MvM Mission Making
By M1 and 6 collaborators
Like Custom MvM? Want to see your missions featured in future events? Look no further!

Mission making can be a daunting task at first. This guide will walk you through how to understand the layout of a mission, and give you the tools to make your first popfile.
3
   
Award
Favorite
Favorited
Unfavorite
Mission Structure I
An MvM mission can be split into Waves, Subwaves, and Wavespawns, each nested within one another. Mission Support and Payout are other factors that massively influence how a mission plays out.

Wavespawns
These are your individual “bricks” to build your mission. Each Wavespawn consists of a bot, Squad or Tank, as well as multiple values to determine when it spawns and how quickly. When building a Wavespawn, consider the following questions.

Common or Giant? Common bots generally have more firepower due to their numbers but are easier to kill. Giants are harder to kill but are less able to kill players.

Stream spawn or burst spawn? If you’ve decided to use common bots in your Wavespawn, the method in which they spawn is important to the overall difficulty of the Wavespawn. Burst spawn bots come out in large numbers at once, making them useful as a main pushing force. Stream spawns are generally more powerful as a supporting force, as the constant supply of bots ensures no team can properly kill all of them.

Mainwave or support? Mainwave bots exhaust after a certain number of them have spawned, whereas support bots continue spawning for the entire wave. All mainwave bots must be cleared to beat a wave. Additionally, there is limited support that exhausts like mainwave, but this is not necessary to end the wave. Note that Giants placed in support will not have the red background to signify they are Giants.

Max active. For a given Wavespawn, you can specify the maximum number of bots that can be alive at a given time. Make sure that the total amount of bots at any given time does not exceed 22, the total bot cap, and make sure it is not too small so as to artificially extend the wait between spawn waves. Tanks don’t contribute to the bot cap, but with 22 bots on the field, Tanks will not spawn until their next spawn check sees there are fewer than 22 bots active.

Subwaves
While a subwave does not literally exist in the popfile, it is a means of dividing waves into sections, essentially organizing the wave. These are the Wavespawns combined to create a pushing force in a given wave. Bots in each subwave should meld together well and pose a reasonable threat to all classes. While it is okay to counter specific classes, you shouldn’t completely shut down a class.

For a given subwave, you can split its constituent wavespawns into push and support (not to be confused with support vs mainwave, from above). Your pushing force will be the bots that generally deal damage to the defenders and break through strong defenses. Your supporting force will be able to make sure that your pushing force can get its job done.

How to make a good pushing force? Making a subwave can be tricky as it also requires the bot composition to have a good pushing force. An example of pushing force could be the usage of Giants, most of which will fall if not supported or able to hold their own. Commons can also be used for a pushing force, with some high damage commons able to break through a defense force despite their low health pool.

How to make a supporting force? Generally, commons are used as a supporting force for a given subwave. These bots can be used to provide suppressing fire, absorb damage from the defending team, or can just be Medics that extend the survivability of the pushing force.

For more information on bots and their uses, check out our robot guide.

Waves
A wave is the end result of subwaves combined, with waves getting harder as the mission progresses. Subwaves can be combined in creative ways, with one building into the next, ensuring a wave never feels like a disconnected sequence of subwaves. Subwaves can be split between each other by specifying “WaitForAllSpawned” or “WaitForAllDead” in the popfile (explained in further detail in Popfile Syntax).

Subwaves that feed into one another. The hallmark of a good wave is one where it is difficult to count each subwave. Avoid using “WaitForAllDead” between subwaves unless you’re sure what you’re doing, and try to build subwaves to complement one another. One of the best examples of this is wave 3 of Mannslaughter, starting with Super Scouts, then moving into Tanks, Super Scouts, Soldiers, and Pyros, and finally finishing off with Giant Heavies and Uber Medics. The Super Scouts ensure that the bomb is far from the front, allowing Soldiers and Pyros to move at full speed during the tank section. The Super Scouts and Tanks distract the defenders for the Soldiers and Pyros to properly deal damage. And the Giant Heavies are difficult to handle if the defenders are uncoordinated, which they often are after dealing with such a potent force. Each subwave feeds into the next, making for a very coherent wave.

Invasion waves. Invasion missions have their subwave count low but the wave count is high, often between 5 and 8 waves. These missions generally do not let the bomb reset after not being picked up for a length of time.

Endurance waves. Endurance missions have their subwave count very high, but the wave count is low. The two valve endurance missions are Caliginous Caper and Mech Mutilation. Their waves are fairly long but the number of waves are low (with Caliginous Caper having only one), and the bomb generally resets after not being picked up for a length of time.

Finales. A finale usually lies on the last wave, only lying on the second to last wave if the last wave is a boss wave. A finale lasts longer and is significantly harder than previous waves, as the expectation is that players will begin to burn as much money as possible on canteens to clear the wave. As a result, good finales feature high health tanks and lots of strong bots and feel like a proper ending to a mission. It’s often stated that a wave “does not feel like a finale” when it should or “feels like a finale” when it shouldn’t.

Your mission in total should last around 20 to 25 minutes, regardless of the amount of waves. How far a team gets pushed into the map will influence the amount of time the mission lasts, so keep that in mind.
Mission Structure II
Payout
The amount of money that players have at their disposal is easily the largest influencer of a mission’s difficulty. Each upgrade a player buys can severely change their survivability or damage potential, and it’s crucial for waves to be designed around the amount of cash players have.
For early waves, it’s best if you strike a balance between the amount of damage players need to deal, and the amount of damage robots deal, as players with lower cash need to choose between survivability and damage upgrades.
On very low cash, you also need to keep from using robots that are trickier to deal with in an already strong wave. Uber Medics, Spies, Snipers or Engineers should all be used sparingly.

An example of a wave that doesn’t strike this balance is wave 1 of Hamlet Hostility. It has large damage requirements, deadly robots and Uber Medics, while on a measly 700 credits.
Without a Medic’s Shield, the 36 Soldiers in the wave are a very strong pushing force, while the Giants that come alongside them demand a lot of damage.
The wave ends with 30 small robots, randomly chosen between Normal Skill Scouts and Buff Banner Soldiers, and then more Giants with Uber Medics.
The combination of the robots’ firepower and health makes this wave hell to play through on most teams without a Medic.

Generally, Advanced and Intermediate missions tend to have more credits than Expert missions.

Pacing
MvM missions need to keep a balance between being entertaining for experienced players, while not being overly punishing for less skilled players. A mission’s “pacing” is used to control this balance. Pacing can be defined as how fast the mission throws stuff at the player, i.e. how fast bots are sent out and how much downtime there is between subwaves.

If bots are sent out too quickly or challenging subwaves are sent back to back with no breaks, the wave can end up steam rolling less experienced teams. On the other hand, bots being sent out too slowly, or being too generous with breaks between subwaves ends up being boring to experienced players who are able to hold at the front. The mission’s pacing needs to account for players on both ends of the spectrum to make it enjoyable for a large audience.

Mission Support
Mission Support is a type of support that functions in a different manner from Wavespawn Support, which you will see later on in this guide. These robots are used for certain tasks, mainly disrupting a team and adding a larger requirement of situational awareness.

There are 4 types of Mission Support robots you can add to your mission: Sentry Busters, Snipers, Spies and Engineers.
You can define how long it takes before they begin spawning, how long it takes between each spawn, and in what waves they will be in.

Sentry Busters: These should be in every mission, in every wave. They disrupt engineers, making it much easier for robots to break through defenses that are over reliant on an engineer.

Snipers: They deny and hold a lot of ground, and are especially good additions to waves that lack area denial. The strength of Snipers will vary depending on how open a map is. For example, on Coaltown, being pushed back to hatch when snipers aren’t being taken care of can mean an instant fail, due to how easy it is to die while getting out of spawn or while defending the hatch. Below are shown very punishing Sniper spots at the hatch area.

Spies: Spies are very good at causing chaos and turning attention away from the wave itself, especially in amounts of 3 or more. If a wave ever feels like it doesn’t properly distract players, spies can serve that purpose.

Engineers: Their main purposes are to deny a lot of ground with their sentries and make sure pressure is constantly applied to the players. Teleporter Engineers are also used on longer maps such as Bigrock or Rottenburg, where they are necessary to improve the pacing of the mission and make sure players are always under pressure, regardless of how far back they were pushed.

The intended difficulty of the mission changes how much you should use each type of Mission Support, aside from Sentry Buster support. They can be extremely strong against newer players, such as intermediate mission players.
Popfile Syntax I
Mann vs. Machine missions are defined by pop (population) files.
Valve missions are good examples of how popfiles should be formatted. Valve’s mission popfiles can be found here[github.com].

The first thing you’ll generally see in a popfile is
#base robot_giant.pop #base robot_standard.pop

#base is used to import robot templates from other popfiles. This guide will go into more detail of what a template is in a later section.
WaveSchedule
Everything other than #base is contained in a WaveSchedule block, as shown below.


Certain keyvalues are used in the WaveSchedule block. These keyvalues apply to the whole mission. An example of some keyvalues:


A full list of possible key values can be found here[gist.github.com] under the PopulationManager section.

KeyValue details
  • StartingCurrency is the amount of money you start the mission with.

  • Advanced 0/1 is required in order for advanced or expert specific achievements to be earned on missions that are of either difficulty. Do not put it on Normal or Intermediate missions.

  • CanBotAttackWhileInSpawnRoom is the variable that determines if the bots are allowed to shoot in spawn. Keep this set to “No”.

  • RespawnWaveTime will get explained later on, in its own section. Set this to half of your intended respawn time. Values of around 3 - 7 are good to start with.

  • FixedRespawnWaveTime Yes locks the respawn wave interval to the value set in RespawnWaveTime. This key value can be omitted.

RespawnWaveTime
RespawnWaveTime is, unintuitively, not how long your respawn time will be in seconds.

First, let’s go over how TF2 actually respawns players. TF2 respawns players in intervals/waves. For example, in a map with a 10 second respawn interval would mean the game spawns in players every 10 seconds. However, this doesn’t directly translate into how long your actual respawn time will be. Let's explain it using the formula: xy + 5 = r. x is the respawn wave interval. y is a random number between 1 - 2. This will be explained later. r is the actual respawn time. The value of x starts out at 2 on the wave 1. With each consecutive wave, x is increased by 2, until it caps out at the RespawnWaveTime specified. Example: Let’s choose 5 as the RespawnWaveTime. The respawn time a player will get during wave 1 will range between: 2 * 1 + 5 and 2 * 2 + 5 This results in a respawn time of 7-9 seconds. Got that? For wave 2, the respawn time will range between: 4 * 1 + 5 and 4 * 2 + 5 Respawn time will be 9-13 seconds. Since the RespawnWaveTime is set to 5, the respawn time for every wave after wave 2 will range between: 5 * 1 + 5 and 5 * 2 + 5. Respawn time will be 10-15 seconds. Example 2: If RespawnWaveTime is set to 3, what would be the respawn time in wave 2? Wave 2 would give you an x value of 4 by default. However, RespawnWaveTime caps it at 3. 3 * 1 + 5 = 8 and 3 * 2 + 5 = 11 Respawn time will be 8 - 11 seconds. Let’s go over the other parts of the formula. 5 is added as a constant to account for the time spent in the killcam. y is a value between 1 - 2 to account for 1 small detail about the respawn system. Your actual respawn time (r) cannot be lower than the respawn wave interval (x). This means the lowest possible respawn time would be if you died at the same time as a respawn wave. This would mean you would only have to wait for the next respawn wave. The longest possible respawn wave is if you died right after a respawn wave. While waiting for the minimum amount of time for a respawn to pass, you would have missed the next respawn wave, meaning you would have to wait for the respawn wave after that. Example 3: Let's say the respawn wave interval is 5 seconds. In this case, the respawn waves will be at 5 sec, 10 sec, 15 sec, … If we die at 0 sec, by the time the minimum of 5 seconds pass, we will be on the 5 sec respawn wave, allowing us to respawn. However, if we die at 0.1 sec, after 5 seconds pass, we will be at 5.1 sec. This means we have to wait for the 10 sec respawn wave to actually respawn, effectively double the respawn wave interval. This is why y is a random number between 1 - 2. Using y = 1 gives the lowest possible respawn time, while y = 2 gives the highest possible respawn time. What does this all mean? TLDR: Excluding the death cam, the value you set RespawnWaveTime to will have the actual respawn ranging from RespawnWaveTime’s value up to double RespawnWaveTime’s value. As a general rule of thumb, set it to around half of your intended respawn time.

TL;DR RespawnWaveTimes of around 3 - 7 are good values to start with. For further reading, you can check the TF2 wiki page about respawn times here.
Popfile Syntax II
Waves
Waves consist of a StartWaveOutput, a DoneOutput and WaveSpawns.
Below is an example of a wave, without any WaveSpawns:


StartWaveOutput is what happens when a wave starts, and DoneOutput when a wave ends. Target is the logic_relay (map sided magic) that will be targeted by the output, and Action is what will happen to it.

In the example above, wave_start_relay is the logic_relay triggered on wave start, while wave_finished_relay is the logic_relay triggered on wave end.

The name of the logic_relays depends on the map, so if you are having any issues where robots do not spawn with the bomb, you can type “sv_cheats 1; developer 1; ent_messages logic_relay” into console, in order to see the logic_relays and their names.

WaveSpawns
Below are two examples of WaveSpawns:


The first WaveSpawn, named w1-a1, spawns 50 Easy Skill Scouts in total, 5 at a time, giving out 150 credits, and with a 5 seconds interval between each spawn.
The second WaveSpawn, named w1-b1, spawns a single Giant Heavy.
The “WaitForAllSpawned “w1-a1”” on the second WaveSpawn means it will wait for the first WaveSpawn to finish spawning. After that, there is a countdown of 10 seconds before the second WaveSpawn spawns.

The TFBot block defines the robot that the WaveSpawn will spawn. In it, you can make robots yourself, as shown with the Scout robots, and call templates, as shown with the Giant Heavy. You can also edit the templates (excluding gatebots) in it, so if you wanted to make a crit boosted Giant Heavy, you could add Attributes AlwaysCrit after the Giant Heavy template. You cannot have multiple TFBot blocks in a single WaveSpawn, unless they’re in a Squad or RandomChoice, which you will see later on.

Multiple WaveSpawns can have the same name, so if a subwave consists of more than 1 WaveSpawn and the next subwave waits for everything in the previous subwave to finish spawning, you can give all of the first subwave’s WaveSpawns the same name, and tell each WaveSpawn in the next subwave to wait for all of the previous WaveSpawns to finish spawning.

Adding a Name, TotalCurrency, WaitBetweenSpawns or WaitBeforeStarting to a WaveSpawn is optional: If there aren’t supposed to be any WaveSpawns waiting for it, it doesn’t need a name, if it isn’t supposed to give the players any credits, it doesn’t need a TotalCurrency, and so on.

A full list of possible key values can be found here[gist.github.com] under the WaveSpawn section.

Squads, Support, and RandomChoice
A Squad is a group of robots that will stick close to and assist its leader, standing in front or side to side with the leader if the Squad members are normal robots, or standing behind the leader and healing it if the Squad members are Medics.
Below is an example of a Squad WaveSpawn, marked as Support:


The WaveSpawn above spawns 2 Squads of 1 Pyro, being the Squad leader, and 2 Bowmen, being the Squad members. The Pyro and Bowmen will attempt to stick together like this.
The TotalCount, MaxActive and SpawnCount still only count individual bots, instead of counting Squads. Instead of spawning 6 Squads at a time, it spawns 2 Squads, which have 3 robots each.

Since the WaveSpawn is marked as Support, these Squads will keep spawning until there are no non-support robots left in the wave. The TotalCount and TotalCurrency make it so 300 credits will be distributed between the first 60 robots that spawn, and after the first 60 robots spawn, no more credits will be dropped.

FormationSize and ShouldPreserveSquad are optional and niche key values you can use to influence squads.

FormationSize’s value controls how far (in hammer units) Squad members stray from their leader. It does not affect medics, since they have their own AI that controls how far they stay from their patient.

By default, Squads no longer stay together if the leader dies. This is with ShouldPreserveSquad 0, the default value. With ShouldPreserveSquad 1, Squads stay together, even if the leader dies.

These key values can be found here[gist.github.com] under the Squad section.

There is also RandomChoice, which randomly picks between the robots listed in it, and is structured in the same way as a Squad in the popfile. In this case, if i were to replace “Squad” with “RandomChoice”, the robots would no longer be divided into groups, and instead, there would be a 1/3 chance of a robot being a Pyro, and a 2/3 chance of a robot being a Bowman.

Tanks
Below is an example of a Tank WaveSpawn:



Naming your tank “tankboss” means it will explode along with the hatch if it deploys the bomb. The StartingPathTrackNode defines the path the Tank will take. For most maps, it’s either boss_path_1 or tank_path_1. For maps with multiple paths, you can type “sv_cheats 1; developer 1; ent_messages path_track” to see the Tank paths and their names.
The Skin of the Tank defines whether it will look like a final Tank or not. Do not use this for non-final Tanks, unless it is a gate Tank.
Final Tanks have black and white stripes at their front and along their sides.


OnKilledOutput and OnBombDroppedOutput are used to trigger logic_relays when the Tank either dies or deploys the bomb respectively. It’s easiest to look at previous missions on map and see which relays need to be triggered.
Popfile Syntax III
Templates
#base allows information from other popfiles to be used. For example, robot_giant.pop contains templates of most non-gatebot Giants used in valve missions.

Below is an example of a robot template:


Let’s go over how a template is made. The example above shows the rapid fire mini giant bowmen on Empire Escalation wave 2. Notice the Templates block? This is where templates go so that the rest of the popfile can call them to be used in the mission. The Templates block goes in the WaveSchedule block.

Within Templates {}, we can create new templates. Each template is its own block, and it can be named anything. In the example above, the template is T_TFBot_Sniper_Huntsman_Spammer. Let’s go over the key values that define this template.

Class - This determines the class of the robot.
Name - This determines the name of the bot that shows in the killfeed.
Item - This gives the bot non-stock items. These can be either weapons or cosmetics. A list of item names can be found here[wiki.alliedmods.net].
ClassIcon - This is the name of the icon that shows in the wavebar (excluding leaderboard_class_). A list of some custom icons can be found here[us-testing.moonlight.tf].
Skill - In general, this determines how well a bot is able to aim. The 4 possible values for a robot’s Skill are Easy, Normal, Hard, and Expert. Easy and Normal robots will have blue eyes, while Hard and Expert robots have yellow eyes. This also adjusts other aspects of a bot’s behavior, such as airblast chance or target prioritization. For example, pyros having 0%, 50%, 90%, and 100% chances of airblasting with increasing skill. More in depth information can be found here.
Health - This determines the amount of health the robot will have. Without Health value specified, the class’s default health will be used instead.
Scale - This determines the size of the robot. A robot’s default size is Scale 1, while giants (how to create giants will be explained later) have Scale 1.75.

A list of possible key values can be found here[gist.github.com] under the TFBot section.

ItemAttributes blocks are used to modify stats for specific items. Using the example above:
ItemName - Used to specify which item’s stats to modify
“fire rate bonus” - this attribute modifies the weapon’s fire speed. In the example above, “fire rate bonus” 0.6 is used to give The Huntsman used by the sniper robot a 40% firing speed bonus (“fire rate bonus” 1 would effectively have a 0% firing rate bonus).

The CharacterAttributes block is used to modify the stats of the robot itself. In the example above:
“head scale” - modifies the size of the head. In the case above, “head scale” 0.7 shrinks the sniper head to be 70% the default size.
“move speed bonus” - modifies the bot’s movement speed. “move speed bonus” 0.85 means the bot moves at 85% of its original movespeed.

While stats used in ItemAttributes can be used in CharacterAttributes and vice versa, it is good practice to separate weapon specific stats into ItemAttributes and player stats into CharacterAttributes.

A list of item/character attributes can be found here.

Let’s look at another template, this time a Giant Rapid Fire Soldier:


We can see that overall, it doesn’t differ much from the previous template shown in terms of syntax. However, there are a few more unique key values in this giant template:
WeaponRestrictions - This key restricts bots to either their Primary, Secondary, or Melee slot, using values of PrimaryOnly, SecondaryOnly, or MeleeOnly respectively.
Attributes MiniBoss - This is what makes the robot a giant. This gives the bot Scale 1.75 automatically, makes the bot immune to damage based knockback, and makes backstabs do a set amount of damage against it instead of 6x the robot’s health.

Special note about “override footstep sound set”. It is used to give Giants footstep sounds. The values that should be given to it range from 2 - 7. While 2 - 6 were intended to correspond to class specific footsteps, they ended up going unused and all sound the same in vanilla. However, some players have modded their game to use these sounds, which can make it very important to give each Giant their corresponding footstep sound. 7 is the exception, and is used to give sentry busters distinct footsteps.
2 - Heavy
3 - Soldier
4 - Demoman
5 - Scout
6 - Pyro
7 - Sentry buster

Some other common attributes:
Attributes Aggressive - Synonymous with BehaviorModifiers Push and BehaviorModifiers Mobber. All 3 of these do the same thing, which makes the bot run towards the hatch, ignoring the bomb. After reaching the hatch, they start acting like normal bomb bots. This attribute is also used for gatebots, which will be explained later.
Attributes SpawnWithFullCharge - This is used for bots such as medics or banner soldiers (bots with weapons that need to be charged), to allow them to use their weapons when they spawn.
Attributes AlwaysCrit - Used to give bots crits.
Attributes HoldFireUntilFullReload - Forces robots to fully reload their weapon before firing. Useful for robots that fire in bursts.
Attributes AlwaysFireWeapon - Forces the bot to hold down the attack key.
Attributes UseBossHealthBar - The robot’s health bar shows on the player’s screen (similar to tank health bars)

The HoldFireUntilFullReload attribute only works with certain weapons, mainly rocket and grenade launchers. In the case where you’re trying to make a bot use a burst fire weapon (such as a shotgun) but it isn’t compatible with Attributes HoldFireUntilFullReload, apply the following stats to the weapon via ItemAttributes:
“auto fires when full” 1
“auto fires full clip” 1

This gives the weapon the Beggar’s Bazooka attributes, allowing the bot to fire it in bursts. However, The Cow Mangler 5000, The Righteous Bison, and The Pomson 6000, are incompatible with both Attributes HoldFireUntilFullReload and The Beggar’s Bazooka attributes. A workaround to this will be explained in the advanced tips and tricks guide.

A list of possible attributes can be found here[gist.github.com] under the TFBOT: Attributes section.

Studying valve templates is a good way to get a grasp of how templates are structured. They can be found here[github.com]. robot_giant.pop contains giant templates while robot_standard.pop contains non-giant templates.
Popfile Syntax IV
Gatebot Templates

There are also gatebot templates, which use a different structure in order to turn a robot into a gatebot:


As you can see, there is an EventChangeAttributes block. Inside of it are Default and RevertGateBotsBehavior blocks. Default contains the robot’s stats before all gates are captured, while RevertGateBotsBehavior contains the robot’s stats after all gates are captured.

Notice how the Default block contains Tag nav_prefer_gate1_flank, Tag bot_gatebot, BehaviorModifiers Push, and Attributes IgnoreFlag. These are what makes the bot act like a gatebot.

Tag nav_prefer_gate1_flank is a Mannhattan-specific tag for gatebots coming from the upper spawn. It makes gatebots coming down from the upper path not take the bomb path to the gate.

Tag bot_gatebot makes the bot go towards and be able to capture gates.

Tag bot_giant makes the bot immune to the gate stun.

BehaviorsModifiers Push and Attributes IgnoreFlag are used to make the bots ignore the bomb.

The robot’s Skill, Attributes, BehaviorModifiers, Tags, Items, ItemAttributes and CharacterAttributes all go into both Default and RevertGateBotsBehavior.

Valve’s gatebot templates can be found here[github.com] in robot_gatebot.pop

Missions
Mission Support. Below is an example of a Sniper Mission.


In the example above, there are 2 Sydney Sleeper Snipers. They begin at wave 4, and spawn during waves 4, 5 and 6. The amount of time it takes before they start spawning is 50 seconds, and the amount of time it takes between each spawn is 70 seconds.
The Objective defines how the robot will act. Sniper for Snipers,. Spy for Spies, Engineer for Engineers, and DestroySentries for Sentry Busters.

Objective Sniper can be used with non-sniper robots to have them use their alt-fire button, such as Cow Mangler Soldiers, which use their charged shots when attempting to zoom in.

Objective DestroySentries will give the robot a Sentry Buster skin, and make it detonate near Sentries. While this means the Sentry Buster template isn’t actually necessary for the bot to function as a sentry buster, it is recommended to stick with the regular sentry buster template in most situations.

Objective Spy and Objective Engineer don’t do much other than make the bot unable to pick up the bomb. This is because the spy and engineer specific behaviors are controlled by the bot’s class, not their Objective. Just use these with spies or engineers respectively.

This actually has the side effect of allowing these bots to be used as wave support, or even as mainwave bots (generally not recommended). In the case of using spies or engineers outside of mission support, give the bots Attributes IgnoreFlag to stop them from picking up the bomb.

Engineers that build teleporters need to have the spawns that get teleported through specified using TeleportWhere. Below is an example of this.


This results in bots coming from spawnbot_main1_slow and spawnbot_main1 being teleported through, while bots from any other spawn not taking the teleporter.
Testing, testing, testing!
No one is perfect, and that includes you. Making the perfect mission requires people to test it and get feedback from playtests. Test it as much as possible, as its purpose is to gather data on how the mission plays.

Keep in mind who’s playtesting the mission. Players are different from each other, meaning data or feedback can largely differ between each test session; it’s up to you on what to do with it. One playtest might completely miss issues due to class composition and general skill, for example. Running multiple tests is key to honing your mission.

Restrictions
Sometimes you’ll need to restrict a few things from a playtest to get more accurate data on how the average team would handle it. These restrictions could range from lowering the total count of players to restricting classes or certain upgrades from being used. While restrictions aren’t required, they’re helpful for tuning the mission for the desired difficulty.

When to restrict? Sniper and Medic are not good classes for testing. Sniper is able to comfortably handle bots without needing to feel the bots’ power. Medic is able to make players effectively invulnerable, meaning high firepower bots are no different than low firepower bots. Outside of these two cases, restrictions are a good means of ensuring the mission is properly balanced around every class composition: if every test you’ve run has included a soldier, try restricting soldier for your next test.

Extracting the most from your Tests
Sometimes, testers just aren’t good at their job. But the testing must continue! So how do you get good results when testers are silent or give very poor feedback?

Watch the demo. Most testing servers automatically record SourceTV demos. Rewatching the demo from the point of view of certain classes can give you perspective that is not otherwise attainable. If you see players struggling against certain subwaves consistently or easily pushing past others, that’s a sign to nerf or buff the subwaves respectively. If there are large periods of downtime between subwaves, try to remedy that by changing the spawn period or adding the concheror effect to your subwave.

Ask guided questions! Did this subwave feel too strong? Too weak? I changed this, do you think it helped? When testers are unwilling to give straightforward, accurate advice, guided questions help them do the thinking you want them to do.

Judge the mission yourself. Featured in this guide (TODO), you can ask yourself a plethora of questions about your own mission. This should be your last resort if all else fails, as you will always be biased when it comes to judging your own mission.

The Gauntlet
If you feel ready, you can submit your mission to Moonlight MvM’s judging queue[forums.moonlight.tf]. With standards higher than that of most testers, the judges in Moonlight will likely find many problems with your mission not particularly noticeable to the average player, so don’t be dismayed if you must resubmit your mission over a dozen times to get it passed. If you manage to get your mission passed, it will be featured in a future event, with you receiving a creator medal and credit for your mission on the tour website.

A mission will be striked if the judges deem your mission too far from passing. Bridging the gap between a mission passable by the average tester and being passable by the judges can be difficult, and if your mission is striked, refer to the previous section for ways to better improve your mission without needing to resubmit to judging.
Conclusion
Mission making is a creative endeavor unlike any other. You’re restricted massively in which robots to use, where they spawn, and how they attack the players. But if you can master the limitations of making missions, you are able to make for fun, memorable experiences that are what has made MvM last so long. If, after having read the guide, making missions still sounds appealing, make sure to join the Moonlight MvM discord server[moonlight.tf] and begin your journey!
< >
12 Comments
Spooder Jun 2, 2023 @ 10:06am 
Awesome, I red all of it and most of it didn't make sense but you still wrote a whole essay of 1 game mode in tf2... now do casual.:steamthumbsup:
PDA Expert  [author] May 30, 2023 @ 2:21pm 
i'm going to pull a rude buster
A Gas Canister. May 29, 2023 @ 3:24am 
What the fuck an actual guide that is not a 2 minute low effort steam point grab?? God damn nature is healing, good job
ihaz May 28, 2023 @ 9:34am 
WARNING! Carry on reading! Or you will become a League of Legends gamer, even if you only looked at the word warning! Once there was a little boy called Joey, he was ten-years-old and he lived in a mental hospital because he posted a shitty copypasta onto a League of Legends ingame chat. He got so bad he went to kill all the staff in the hospital so the Feds decided that best idea was to get rid of him so they set up a special room to kill him, as inhumane as possible. And he sat there in agony for hours until he died. Now every week on the day of his death he returns to the person that reads this letter, on a monday night at 12:00 a.m. He creeps into your room and makes you install League of Legends you slowly, by pegging you and watching you bleed to death. Now send this to ten other profiles on this one site, and he will haunt someone else who doesn't. This isn't fake. apparently if u copy and paste this to ten comments in the next ten minutes nothing will happen
Aarrggh May 28, 2023 @ 6:39am 
what the efff,,,,,,l,.,,.,,,,,,, he is a;l d[oign choidfiol la.uboura?>!??!?!?!?!??@>!?!@?!@#?!@>!?>@?>!>@?!>?@#?>1
dsaS May 27, 2023 @ 2:02pm 
chiangp May 27, 2023 @ 6:02am 
WARNING! Carry on reading! Or you will die, even if you only looked at the word warning! Once there was a little boy called Joey, he was ten-years-old and he lived in a mental hospital because he posted a shitty copypasta onto a People Playground mods comment section. He got so bad he went to kill all the staff in the hospital so the Feds decided that best idea was to get rid of him so they set up a special room to kill him, as inhumane as possible. And he sat there in agony for hours until he died. Now every week on the day of his death he returns to the person that reads this letter, on a monday night at 12:00 a.m. He creeps into your room and kills you slowly, by pegging you and watching you bleed to death. Now send this to ten other profiles on this one site, and he will haunt someone else who doesn't. This isn't fake. apparently if u copy and paste this to ten comments in the next ten minutes nothing will happen
dareaperofsouls May 27, 2023 @ 12:53am 
вам не нужно учиться, если вам не придется
Hardist May 27, 2023 @ 12:33am 
Это нужно выучить? Займитесь кто-нибудь переводом, потом поиграем. Сложная игра.
twitch.tv/CZmisaCZ May 26, 2023 @ 10:41am 
amongus