A short guide to explain popfiles (requires example.pop)

UKCS-Alias

Mann vs Machine... or... Mapper vs Meta?
aa
Sep 8, 2008
1,264
817
For this guide i assume you are aware on the existance of example.pop and the bot_giant.pop and bot_normal.pop files. I will not handle their location and how to create extra bots. I only will explain the basics of building a popfile and understanding the way its used. And as im not a good person for making guides it might be unfriendly. But at least i hope it will help you.

For the popfiles themselve its first important to understand the layout. A popfile containts multiple levels:
Code:
WaveSchedule - Essentialy says 'this is the mission'
Wave - The individual waves
WaveSpawn - A group of bots that can spawn
Mission - A passive WaveSpawn that can go over multiple waves, and is not required to be killed. its used for spies, snipers, sentry busters and engineers).
These build up your mission. For extra details the example popfile will show them.
To get a mission to work you need to know what way to build up individual waves. A good practice on this is to name each wavespawn diffirent to begin with (when getting to know it better you can give multiple wavespawns the same name, in the beginning this asks for bugs).

Naming

For naming wavespawns there are multiple ways, but all of them match a wave number:
Wave[number][ident] - Wave01a
Wave[number][type] - Wave01scouts
Wave[number][condition] - Wave02afterscouts
The wave number should be the same during the wave, but isnt needed to match the actual wave number (but recommended is to hold yourself to it).

The mission
Ofcourse, a wave on its own has no use. It must be inside the mission.
For a mission the file is built up like
Code:
//bot template files get loaded here, by default this should be normal and giant
#base robot_giant.pop
#base robot_standard.pop

WaveSchedule //wave total value 1050
{
	StartingCurrency 400
	
	CanBotsAttackWhileInSpawnRoom No
	RespawnWaveTime 5
	Advanced	0
	
	[ Missions go here ]
	[ Waves go here ]
}

First im going to explain the waves as this is where you have to start. Missions can be part of a wave, but they are not essential other than a sentry buster. For this we at least will starting putting that one in at first so we can ignore it from now on:

Code:
	Mission
	{
		Objective DestroySentries
		Where spawnbot
		CooldownTime 30

		TFBot
		{
			Template T_TFBot_SentryBuster
			Tag bot_sentrybuster
		}
	}
Dont worry about editing that one yet, put it in the file and you are done for now. It will make sure sentry arent becoming overpowered.

We now have to start on making the first wave:
The waves
Lets say you want a wave which spawns 20 scouts, 40 soldiers and 40 heavies. The scouts passively go next to the soldiers and heavies and once they are dead demoman come in as support. This is a relatively simple wave.

First initialize the wave:
Code:
	Wave //wave total value 1050
	{
		WaitWhenDone 60
		Sound "Announcer.IncomingMob"
		Checkpoint Yes

		StartWaveOutput,     InitWaveOutput,     DoneOutput (copy these from the map you are basing the popfile on, if you have one). these trigger relays existing in the map and are needed to make the map work)
Now lets add the first bot
Code:
		WaveSpawn
		{
			Name "wave01a"
			Where spawnbot
			TotalCount 20
			MaxActive 12
			SpawnCount 4
			WaitBetweenSpawns 3
			WaitBeforeStarting 0

			TotalCurrency 150

			TFBot
			{
				Class Scout
				Skill Hard
			}
		}
You should recognise this from the example popfile.

The important part for the other thigns are that the names prob will be like:
Soldiers: wave01b
Heavy: wave01c
Demo: wave01d

The soldiers and heavies can be built the same way as above except with changed numbers. The first important note is, the scouts, heavy and soldiers at the SpawnCount may NEVER exceed 20. For a single wavespawn keep the limit at 10. MaxActive can be allowed to go above it, but on support waves this is a hazard as again it can deadlock. Try to avoid large groups.

The next important thing is those demoman, as they are supposed to go after the scouts, and go into support.
For the waiting you can use WaitForAllSpawned and WaitForAllDead. Spawned waits until the last bots are inside the map, Dead waits until those are dead. In the example i use the Dead version.

Now we also need to mark them as support. For this there are 3 types of support, infinite and limited and mission based (we handle this later)
Code:
		WaveSpawn
		{
			Name "wave01d"
			[b]WaitForAllDead "wave01a"[/b]
			Where spawnbot
			TotalCount 20
			MaxActive 12
			SpawnCount 4
			WaitBetweenSpawns 3
			WaitBeforeStarting 0

			[b]Support 1[/b]
			TotalCurrency 150

			TFBot
			{
				Class Demoman
				Skill Hard
			}
		}

And finaly you close the wave:
Code:
	}

Best is to load this mission ingame already. Its very likely you made a syntax error. But this is where you must practice first.
Practice all that you want, go as complex as you are capable on in single wavespawn. Try to experiment now as finding bugs in this state should be easy.
Just try to avoid editing the TFBot for now, trying to build extended waves and multiple waves in a row is something that is far more important as this can also make you learn the consequences of having too many bots, too little etc. And without any special things you can already make a full mission.

Mission wavespawns
Now you created your first wave you have the basics done. A mission wavespawn is now easy to learn as its essentialy a wavespawn, but with an exception. There are diffirent parameters.

Lets for example add a spy
Code:
	Mission // Spy - wave 3
	{
		Objective Spy  

		InitialCooldown 10
		Where spawnbot_mission_spy
		BeginAtWave 3
		RunForThisManyWaves 1
		CooldownTime 10
		DesiredCount 3

		TFBot
		{
			Class Spy
			Skill Expert
			Name Spy
		}
	}

Notice the parameters and look for them in the example popfile. Yes, it realy is that easy once you know how wavespawns work. But dont forget:
DesiredCount is the same as SpawnCount. As we said earlier there is a limit of 20, and you might think its incorrect. Well, it is and with a good reason: Sentry busters.
Sentry busters are a mission wide spawner in most cases, and unlike the other missions, they dont show a desiredcount. This is due to each engy taking 1 usualy. By keeping 2 spots open you ensure room to spawn 2 (which is very unlikely to cause a deadlock)

TFBots
Ofcourse, you might want to have a bot with special abilities. It can be fun to experiment, but initialy its recommended to look in the bot templates first.

A bot template is a set of attributes on a bot, it prevents you from having to type or copy paste the same 10 lines over and over again. Instead a single line will do:
Code:
			TFBot
			{
				Template T_TFBot_Demoman_Knight
			}
Any attributes you add to them can still adjust them, so lets give a huntsman 200hp and infinite crits. But to compensate make him easy:
Code:
			TFBot
			{
				Template T_TFBot_Sniper_Huntsman
				Health 200
				Attributes AlwaysCrit
				Skill Easy
			}
Good usage of these can make or break a wave (realy! 20 small rapid fire soldiers with crits isnt fun - dont try to overuse these).
Avoid editing health unless you know why you need less or extra hp. Use the skill attribute as much as you can (its an easy, effective and good way to balance)!
Just look what is done in templates and experiment.

TFBots
Until you can make templates yourself!

Templates have 2 positions: inside the mission, in a template file. The relative locations are:
Code:
//bot template files get loaded here, by default this should be normal and giant
#base robot_giant.pop
#base robot_standard.pop

WaveSchedule //wave total value 1050
{
	StartingCurrency 400
	
	CanBotsAttackWhileInSpawnRoom No
	RespawnWaveTime 5
	Advanced	0
	
	[ Templates go here]
	
	[ Missions go here ]
	[ Waves go here ]
}
Or when looking in a template file:
Code:
WaveSchedule
{
	[ Templates go here]
}
Yes, they are the same! Except a template file has no waves.

In both cases templates are inside a Templates block. Only within these you can create templates you can use in TFBots
Code:
WaveSchedule //wave total value 1050
{
	Templates
	{
	}
}

Lets look at a valve template except the names changed to what they do:
Code:
WaveSchedule //wave total value 1050
{
	Templates
	{
		T_TFBot_Sniper
		{
			Class Sniper
			Skill Hard
			MaxVisionRange 2500
		}
	}
}
Or simplified to explain the 2 thigns relevant:
Code:
WaveSchedule //wave total value 1050
{
	Templates
	{
		[Template name you can use]
		{
			[All the same features as a TFBot has]
		}
	}
}

So in the above example T_TFBot_Sniper is what you use inside a TFBot:
Code:
			TFBot
			{
				Template T_TFBot_Sniper
			}
That realy is everything on the template name you need.

Have fun adding attributes to templates and bots!

Even with this guide its still up to experimenting yourself. We can give you a full mission file to edit, but its best to learn it from the beginning and create your own mission. However, dont be afraid to copy lines from valve files! As long as you are carefull it shoudnt harm.
 

vulduv

L4: Comfortable Member
Sep 12, 2016
167
48
hey UKCS-Alias ? i have a problem. this.

Code:
        WaveSpawn
        {
            Where spawnbot
            TotalCount 10
            MaxActive 12
            SpawnCount 4
          
            WaitBetweenSpawns 6
            WaitBeforeStarting 0

            CharacterAttributes
            {
                "override projectile type" 8
            }

            TotalCurrency 1000

            TFBot
            {
                Class Demoman
                Skill Hard
            }
        }
    }
does not work. what did i do wrong here? (edit : the problem is that the demomen does not shoot huntmen arrows.)
 

Izotope

Sourcerer
aa
May 13, 2013
698
764
Code:
        WaveSpawn
        {
            Where spawnbot
            TotalCount 10
            MaxActive 12
            SpawnCount 4
        
            WaitBetweenSpawns 6
            WaitBeforeStarting 0

            CharacterAttributes
            {
                "override projectile type" 8
            }

            TotalCurrency 1000

            TFBot
            {
                Class Demoman
                Skill Hard
            }
        }
    }
2 things:
  1. Your "MaxActive" exceeds the value of "TotalCount"
  2. You have 1 "}" more than you have "{"
Adjust your values and remove the extra }
Unless that extra "}" belongs to an opening { that you did not copy here.
 

vulduv

L4: Comfortable Member
Sep 12, 2016
167
48
the reason the is more } than { is bqs i have multiple WaveSpawns wich hold the rest of the {. il try lowering the MaxActive to 10 but i dont think that will change anything.
 

vulduv

L4: Comfortable Member
Sep 12, 2016
167
48
also should it be like this?
Code:
TFBot
        
CharacterAttributes
{
                "override projectile type" 8
}
or this?
Code:
TFBot
{
            CharacterAttributes
            {
                "override projectile type" 8
            }
}
plz help me UKCS-Alias
 
Last edited:

vulduv

L4: Comfortable Member
Sep 12, 2016
167
48
i think i got it now that im looking at example.pop

(edit yay it works now!
im gonna try changing it to tomislav heavies.
now how the faq do i change the weapon there using)
 

vulduv

L4: Comfortable Member
Sep 12, 2016
167
48
do you happend to know? how to SET projectile speed? like... "Projectile speed increase" but addetive?
 

Hydrogen

MvM Maniac
Apr 5, 2017
84
181
do you happend to know? how to SET projectile speed? like... "Projectile speed increase" but addetive?

For a list of attributes, go to items_game.txt and find the "attributes" section. Ctrl F doesn't work too well here, so Ctrl F the "tmp dmgbuff on hit" attribute to jump to that section. Then scroll up/down or Ctrl F the name of the attribute you want. Make sure to use the exact spelling as in items_game.txt in your bot template or else it will not work. As for what value type to use, check the "description_format" section. Some common cases:

value_is_additive_percentage - "0.25" = +25%
value_is_percentage - "1.25" = +25% (e.g. fire rate bonus)
value_is_additive - "1.25" = +1.25 (e.g. heal on kill)
anything else - assume additive type

For the particular question you asked: "Projectile speed increased" is what you want, and it is value_is_percentage. So if you wanted 50% faster projectile speed, you would write:

Code:
"Projectile speed increased" 1.5

under the ItemAttributes (or CharacterAttributes, although usually not a good idea) section of your bot template.