If you have any questions specific to this guide, ask them in the replies.
This guide is intended to be read in order. Each section will build upon knowledge from previous sections. To get the full effect of this guide, read through each section in order and follow along. If you skip sections, you will miss important information.
As of writing this, the advanced sections of the guide are not written but they will be at some point
Introduction
► Show Spoiler
What is mapping? Mapping is the process of using Hammer Editor to design levels for TF2. The Hammer Editor is the only real tool that exists to create levels, but it's fairly easy to understand the basics of how to use it.
While not directly related to level creation, other aspects of mapping may include asset creation (custom textures, models, or sounds) or scripting (VScript using the Squirrel programming language).
The purpose of this series of guides is to teach you how to perform level creation. As of writing this I do not plan on putting guides for asset creation in this post, they will likely be in other posts (with VScript possibly being in a separate subforum).
The goal of these guides is to take you from having no knowledge of how to use hammer, to being able to have all the tools you need to make a Valve quality map. This does not mean the maps you create will be Valve quality, but you'll have the tools to do so. Whether or not you can create a good map comes down to your own creativity, inspiration, and understanding of the game.
There is no "secret" to making a good map, you will just need to try out what you can until you land somewhere that works. In all likelihood, your first map will not be good unless it is heavily tested, and this is fine, getting it right the first time is a nigh impossible feat without a lot of support from others. All the Valve maps you know and love went through heavy testing and layout scrutinizing during their design phases, they were not just "one and done" maps. To make a good map you'll need a good understanding of level design theory for TF2 which includes designing for gamemodes and classes. You will also need to know how to optimize your map, which goes hand in hand with the visuals and making sure there's not too much going on aesthetically in your map to cause performance issues. I hope that by the end of this guide you'll have an idea of how to do all of this to a reasonable degree, such that you can make up the gap by studying maps you enjoy to see what they do right and what they do wrong.
Overall this guide series will cover
While not directly related to level creation, other aspects of mapping may include asset creation (custom textures, models, or sounds) or scripting (VScript using the Squirrel programming language).
The purpose of this series of guides is to teach you how to perform level creation. As of writing this I do not plan on putting guides for asset creation in this post, they will likely be in other posts (with VScript possibly being in a separate subforum).
The goal of these guides is to take you from having no knowledge of how to use hammer, to being able to have all the tools you need to make a Valve quality map. This does not mean the maps you create will be Valve quality, but you'll have the tools to do so. Whether or not you can create a good map comes down to your own creativity, inspiration, and understanding of the game.
There is no "secret" to making a good map, you will just need to try out what you can until you land somewhere that works. In all likelihood, your first map will not be good unless it is heavily tested, and this is fine, getting it right the first time is a nigh impossible feat without a lot of support from others. All the Valve maps you know and love went through heavy testing and layout scrutinizing during their design phases, they were not just "one and done" maps. To make a good map you'll need a good understanding of level design theory for TF2 which includes designing for gamemodes and classes. You will also need to know how to optimize your map, which goes hand in hand with the visuals and making sure there's not too much going on aesthetically in your map to cause performance issues. I hope that by the end of this guide you'll have an idea of how to do all of this to a reasonable degree, such that you can make up the gap by studying maps you enjoy to see what they do right and what they do wrong.
Overall this guide series will cover
- Installing the necessary programs and setting up Hammer
- Basics of using hammer and how to create the aspects of a level
- Level design theory and what makes layouts good or bad
- Optimizing your maps so they perform well even for players with older hardware
- Decompiling and studying existing maps
► Show Spoiler
At a most basic level, the only program you need in order to develop maps is Hammer editor, which comes preinstalled if you have TF2 installed. However, alone it isn't really enough to make mapping easy, so there are some other programs you should install additionally.
Firstly, it should be noted that you may find it useful to create a shortcut to your Team Fortress 2 directory, as you will be navigating here very frequently and a shortcut is helpful.
Windows Shortcut
Your steam/steamapps/common/Team Fortress 2 directory can be bookmarked on your file browser to navigate there easier
Linux Shortcut
While you can add the TF2 directory to your file browser (if you have one), I would advise symlinking your TF2 directory to home, this has easily been one of my most used symlinks and I have gotten great use out of it. It will make navigating to the directory easier
From here on going forward in this guide, the location of your Team Fortress 2 directory will be referred to as the "TF2" folder. If this guide mentions a folder like TF2/bin/ or TF2/tf/, it will instead be Team Fortress 2/bin/ and Team Fortress 2/tf/ respectively, however this shorthand will be used to make file paths easier to parse.
Programs
The following programs are all very useful for mapping and you should download them before we begin.
Installation - Windows
Installation - Linux
At this point in the tutorial, the Linux and Windows differences essentially stop so there will be no OS specifics given unless necessary.
Firstly, it should be noted that you may find it useful to create a shortcut to your Team Fortress 2 directory, as you will be navigating here very frequently and a shortcut is helpful.
Windows Shortcut
Your steam/steamapps/common/Team Fortress 2 directory can be bookmarked on your file browser to navigate there easier
Linux Shortcut
While you can add the TF2 directory to your file browser (if you have one), I would advise symlinking your TF2 directory to home, this has easily been one of my most used symlinks and I have gotten great use out of it. It will make navigating to the directory easier
Code: Select all
ln -s /home/<your_user>/.steam/steam/steamapps/common/Team\ Fortress\ 2 /home/<your_user>/TF2Programs
The following programs are all very useful for mapping and you should download them before we begin.
- Hammer++: This is an upgrade to regular Hammer which adds more features as well as stability (it crashes less and autosaves more, for instance). There are no downsides to using H++ and anyone mapping should be using it.
- VBSP++, VRAD++, VVIS++: These are upgrades to some of the build programs that you use to compile maps. As with Hammer++, these are straight upgrades that make compiling faster with better features, there's no reason not to use them. For the time being, you'll only need to install them where it says on the site, we'll go over how to update Hammer to use them later in this guide
- CompilePal: This is a program to make compiling easier, as well as providing some important tools like asset packing (for custom assets), automatic cubemap generation, and so on. While you can get by without it, it's highly advised to use this as it simplifies the process. Without it, you will need to use alternate methods of asset packing which will not be covered in this guide.
- BAMF: This is a set of materials and tools that will help you out when mapping. The most important part of this is the FGD. Other useful things include decompiled valve maps, prefabs, and additional dev textures. The only things necessary/recommended for this tutorial however are the FGD and Valve VMFs.
Installation - Windows
- Hammer++: Check the README.txt file within the download for details on exactly where to put it, but generally speaking the files will be in your TF2/bin/ dir.
- VBSP++,VRAD++,VVIS++: As specified on the website, the 3 exe files will go into your TF2/bin/x64/ directory
- CompilePal: This is a standalone program which does not need to go near your TF2 directory, you can install it wherever you'd like. Keeping it near your TF2 directory (for instance, creating a folder named "tools" in your TF2 directory and then installing it there) is advised so you don't lose track of it.
- BAMF: Check out the existing installation guide. Note that the only things you need for this guide are the FGD and Valve VMFs, all other features are optional and can be installed at your own discretion.
Installation - Linux
- Hammer++: Check out my tutorial here to install and use Hammer/Hammer++ through Proton.
- VBSP++,VRAD++,VVIS++: As specified on the website, the 3 exe files will go into your TF2/bin/x64/ directory
- CompilePal: This is a standalone program which does not need to go near your TF2 directory, you can install it wherever you'd like. Keeping it near your TF2 directory (for instance, creating a folder named "tools" in your TF2 directory and then installing it there) is advised so you don't lose track of it. CompilePal runs with Wine, but it will need access to your TF2 directory. You will need to symlink your entire TF2 directory into the wine prefix CompilePal uses. Read the above H++ Linux tutorial for an example of what that might look like based on where your wine prefix is. A full tutorial will not be covered as this guide assumes a bare minimum level of Linux knowledge to be able to perform this yourself
- BAMF: You can try to use the existing installer first by running it with wine. If that doesn't work, you can instead clone the github repo and move the contents of the FGD folder into your TF2/bin/ dir, and the entire Decompiled Valve Maps folder inside of your map folder (TF2/sourcesdk_content/tf/mapsrc/) for use later.
At this point in the tutorial, the Linux and Windows differences essentially stop so there will be no OS specifics given unless necessary.
► Show Spoiler
There are a few settings that will make your life a lot easier that you should enable before we start.
Navigate to Tools > Options
Game Configuration:
Navigate to Tools > Options
Game Configuration:
- Game Data: Click Add and select TF2/bin/tf-brokk.fgd (it should drop you in the TF2/bin/x64 directory by default, so you will need to navigate out and into the regular bin dir. Alternatively, copy this fgd file into your x64 dir)
- Default PointEntity: prop_static
- Default SolidEntity: func_detail
- Default texture: 0.25
- Default lightmap: 16
- Enable Autosave: Enabled (configure as you like)
- Back Clipping: ~8000-10000 (render distance)
- BSP executable: vbspplusplus.exe
- VIS executable: vvisplusplus.exe
- RAD executable: vradplusplus.exe
- Enable microgrid: Disabled
- Snap newly created brush points to grid: Enabled
► Show Spoiler
In this guide we are going to be going from zero knowledge of how to use hammer, to making an extremely basic but fully functional KOTH map. KOTH is chosen due to ease of gamemode logic for this guide, other guides will cover the specific logic for other gamemodes.
Hammer
First off, navigate to File > New and load into a new map.
Your window should be shown in a 2x2 grid. Three of these grids are 2D views at different angles, while one grid is the 3D view. If you don't have them set correctly, look to the top left of each window to see the window type (such as top (x/y) or front (y/z)). Right click this to change the window type.
Generally speaking you want to have the following windows:

On the left of the program are your tools. To get started we don't need all of them, but some of the basics are:

Selection tool: This lets you select, move, and resize brushes and entities, or create selection zones by dragging in one of the 2d views.

Block Tool: By creating a selection zone with this tool and pressing enter, a brush of that specified size will be created. It can be resized and molded afterwards

Entity Tool: This tool is used to create entities like props as well as internal game logic, such as gamemode logic, lights, player spawns, etc.

Toggle Texture Application: This tool is how you will apply textures to brushes in most cases
Basic Brush Creation
We are going to be creating the floor brush, but first off we want to know what texture it should be. Whenever you use the block tool to create a brush, whatever texture you currently have selected will be applied to all faces of the brush. It is generally considered best practice to make sure that any textures not visible to players are set to nodraw, however testing a map with nodraw is difficult. Instead, we can use a dev texture and mass replace it later in the development of our map once we get to texturing.
In the Current texture section of the Right sidebar, select Browse, then filter for measuregeneric, and double click on dev_measuregeneric01b (the gray grid) to select it.

Before creating a brush, check the bottom right corner to ensure Snap is set to On. If it isn't, press Shift+W to cycle it to On. Generally speaking, you always want grid snap on.
Next, select the Block tool, and on your top (x/y) window, drag a box to be size 2048x2048. If you align it with the center of the map, you'll notice it lines up perfectly with the orange lines. On either your side or front view, ensure the brush is thin, around 16-64 Hammer Units tall. Make sure the brush is underneath the origin, ideally flush with the blue axis line.
If you're having trouble lining it up easily, you can use the bracket keys [ and ] on your keyboard to change the grid size. Check the bottom right corner to see your current size. For this exercise, stick between 16-64 unless otherwise specified.
Your selection should look like this. Some labels are applied to help understand the grid and 3D views

Press Enter to create the brush.
To navigate the 3D view, press z to toggle freecam controls. Scroll wheel can be used to move forward and backwards, as well as WASD to move.
If you created the brush in the right spot, you'll see the origin in the 3D view like this.

As with most editing programs, Ctrl + z will undo the last action you took which can be helpful if you misclicked or did an action inadvertently.
Now, let's create some map geometry. Using the same method as before, go ahead and create four walls around the floor brush that are 512 units tall. Note that when creating a brush in the 2D view, the unseen third dimension will equal the length of the last brush you selected. You can see this for yourself by selecting the floor brush, then trying to make a wall in either direction within one 2D view. This selection shortcut only applies to manually selected brushes, so once you create a brush if you want to make another brush of the same height/width, you'll need to reselect it.

Spawn Entities
In order for the map to be able to be compiled, it needs entities within the playable space. The easiest first entity to add is a player spawn.
In the 3D view, navigate inside of your room, then click on the floor using the Entity Tool. The entity tool does not work correctly when used on the 2D view, so you'll be using the 3D view whenever you use this tool.
If you set up the setting correctly previously, you'll have created a red box on the floor (though it's only red because it's selected). This is an uninitialized static prop, which is what we set our default entity to in the options. Double click to open the settings for it to be sure

In order to change this to an entity we want, at the top you'll select Class, highlight the currently class (prop_static) then input info_player_teamspawn. Press Enter or hit Apply to convert the entity

Within this entity we can check the Keyvalues to see what it's configured to by default. As you can see in the Team key, the default value is 0 or None. This means the entity has no associated team with it, which in the context of a team spawn means either team can spawn here. However, we don't want players getting stuck on each other. Perform the same process again to create another teamspawn entity and place them a little bit apart like so.

Note that for spawnpoints, they are required to be floating off the ground a bit. When a player spawns in, they're snapped to the floor, but if the teamspawn is flush against the floor it becomes invalid.
In each spawnpoint, select the Value for team, and on the right click the dropdown. Set one spawnpoint to Red and one to Blu.
Compiling
We're almost ready to compile our map. Use Ctrl + s to save the map. Maps are by default stored in the .vmf format, and can be found in the TF2/sourcesdk_content/tf/mapsrc/ folder. Name your map something like first_map and press Save.
Now we can compile the map. Go to File > Run Map, or just press F9. Once in this menu, press Expert as you will generally always want to be in the expert menu.
You'll want to make sure that bsp, vis, light, and copy are all selected. These respectively perform the map geometry generation, the visibility generation, light generation, and moving it to your map folder. You'll want to make sure $game_exe is unchecked. Generally speaking it's easier to just have your game open and then compile on the side than to have the compiler open your game. Additionally, on Linux, this feature does not work at all as Hammer can't open your game.

Once ready, press Go to start the compile.
Unfortunately, this map doesn't compile! If we check the compile window, it will mention that
So let's figure out why this error occurred.
Identifying Leaks
Press any button to exit the compile window, then go back into hammer and navigate to Map > Load Pointfile. If there's a vbsp (geometry) compilation issue, Hammer will create a pointfile that shows you exactly what went wrong.
As you can see in your pointfile, the entity that "leaked" has a line pointing towards where it leaked.

But what is a leak? In Source, all maps must be completely self contained. If any line can be drawn from the inside of a level to the outside, then it "leaks." Think of your map as being like a spaceship, and leaks like hull breaches. Even a small hole will let out all the air.
You can fill this leak using a dev texture brush. Technically, any world brush will seal a leak (aside from some special tool textures like clips). But if all maps had to be enclosed inside rooms, you wouldn't be able to have levels outdoors. Therefore, we can use a skybox brush to create a sky for our map.
You can unload the pointfile the same way by using Map > Unload Pointfile
Skybox Brush and Brush Duplication
Select the tools/toolsskybox texture (you can filter for tools/ to make finding tool textures easier). Note that you should select the light blue toolsskybox texture, NOT the purple toolsskybox2d texture.
While we could create another brush from scratch, we know the ceiling is going to be the same size as the floor, so instead let's just duplicate the floor and change the texture.
When holding Shift, any movement applied to a brush or entity (resize, movement, rotation) will cause the movement to instead create a duplicate of that brush.
Select the floor, then while holding Shift the entire time, move the ceiling up to the top of the walls. You can do this either by dragging it with your mouse in the 2D view, or (based on what grid your mouse is focused on) the arrow keys. If dragging with your mouse, hold shift for the entire duration of the movement. If using arrow keys, only hold shift for the first arrow press, as each subsequent one will create multiple duplicates. Note that this same principle applies to entities, you can go back and redo the creation of the second teamspawn entity by holding shift and moving the first one as a demonstration of this.
You can also use Ctrl + c and Ctrl + v to copy paste brushes, however using Shift tends to be more precise.

Apply Current Texture
Once you have the ceiling in place, select it and click the Apply Current Texture button. Unlike the regular texture tool which is more precise, this is a quick and easy way to apply your current texture to all faces of a brush indiscriminately.
Once done your room should look like this

Loading Into Your Map
Following the previous steps, you should be able to compile now without errors.
Once compilation finishes, you can load into your map by booting up TF2 and in console typing
which would be whatever you named it earlier in this guide. For example, first_map.vmf can be loaded into (after compilation) with
Note that when you use the "map" command in console, it starts up a local server each time. If you are already in your local server (for example you loaded the map previously) and want to cut load times, you can instead use
which merely changes the map on the server instead of restarting the server itself.
When loaded into your map it should look something like the below. You should be able to join a team and run around in this map now. If you spawn under the ground or stuck in the void, refer back to the spawn entity creation section.

We have a functional map that you can load into but this map has nothing in it. Firstly we'll create some respawn rooms for each team.
Respawn Room and Clipping Tool
We are only going to make one respawn room for now, so don't worry about mirroring any of this just yet.
Pick one wall you want to be the RED spawn. The specific one does not matter, though if you want to follow this guide exactly, the left wall (from the top view perspective) will be used.
We will be using the clipping tool. This tool allows you to cut one or more objects along a plane. Most of the time you will use it as a straight cut along an axis, so that's what we'll use it for during this guide, though note that you can make more interesting diagonal cuts by moving the cut vertices in your 2D grids.
Select your wall and then in one of your side 2D grids, click and drag to create a cut line horizontally. Having grid snap on for this step is important so verify it, as having cuts not aligned on the grid will introduce a lot of microgird errors later.
After the initial line is created you can freely drag it around with the vertices. Your initial line does not need to be in the exact right spot, just get it close enough and then after move it into the right location. For the time being, don't drag any of the cuts on your top 2D grid as this will make the cut a 3D diagonal one which we don't want to do.

You can see on the side the size that each brush will be after the cut. Get the bottom brush to 128(?).
You will notice that one brush is red and the other is white. Depending on your cut setting, cut can be set to either keep both brushes, or delete one. The red parts will be deleted, while the white parts will be preserved. To cycle this, simply click on the tool again, or anywhere on the 2D grid. There are 3 settings (delete left, delete right, keep) so just click until both the top and bottom brush are white. Once ready, press enter to perform the cut.

Next, let's create the door hole. Select the bottom brush, then this time create a vertical cut in either your top view, or the side view which has the correct face depending on which wall you picked. Cut it right down the middle so that both sides are equal. Perform the same operation as previously for the cutting settings, keeping both brushes.
For each brush, select it and drag it to one side so that an opening is created in the wall. The final width of the door should be 192(?), which you can verify by dragging a selection box across the width after you resize the walls.

Unfortunately there's one problem, the brushes now have skybox textures on the side (if you followed this guide exactly). This is because when you use the clipping tool, the newly created faces on the brushes will be set to whatever texture you have active.
To fix this, use the Apply current texture tool on each brush on the wall after selecting the dev grid again.
Below you can see what one of the brushes looks like after fixing the texture on it. A good rule of thumb is to have the texture you want to use in the cut selected beforehand. When doing map development this usually means a dev grid or nodraw, to ensure newly created faces use dummy textures just in case they aren't seen, and can be retextured later if they are.

Creating the Room
Create a room using the previous principles. When creating a brush a good rule of thumb is that it should only be as big as it needs to be, so for instance you don't want a floor brush to extend beyond the walls. Practicing this will make texturing much easier in the future. For example, in the area within the door itself, create a small brush just for that floor rather than dragging the whole spawn room floor over.

Find the player spawn in the middle that is set for RED team and drag it over into your spawn room. After moving it, you can use Shift to duplicate it a few times. Generally speaking all spawn rooms for all maps will have multiple spawn locations, this is because the game will first try to fill up each spawn before placing players in the same spawn location, and stacking everyone in one spot gives poor visibility. Unless you intend your map to be played on servers with >32 players, the respawn room spawnpoints for a team doesn't need to add to more than 12 cumulatively as a rule of thumb.
There are a few aspects to spawn rooms we will need to create. The spawn room boundary, respawn lockers, and the spawn door.
Firstly, the spawn boundary. Select the tools/trigger texture and create a brush that completely fills the inside of your spawn room.
You will also want to create a trigger that takes up the full space in the doorway. The need for this will be clear shortly.

Brush Entities and the Respawn Room Trigger
We are now going to be creating a Brush Entity. Unlike other entity types, created with the Entity Tool, a brush entity is instead created from one or more brushes. While both are entities, the types of entities that can be brush entities are entirely separate from other "point" entities. For example, a door or trigger would be a brush entity, while a prop is a point entity.
There are two ways to create entities, either with Ctrl + t or by clicking the Entity button in the brush conversion section on your right sidebar. However, they do not do the same thing.
Ctrl + t will turn each brush you select into an individual entity. For example if you select your two triggers and use ctrl + t, they will both be turned into individual func_detail entities. You can verify they are separate by using the selection tool on one of them and seeing that the other is not selected as well, as they are entirely separate entities.
The Entity button will instead take all selected brushes and consider them all one brush entity. If you ctrl + z the previous change to your triggers and then instead use the Entity button, the two trigger brushes will instead be considered one brush entity. You can again verify this by using the selection tool and seeing that clicking on one brush selects both. It's also worth nothing pressing the Entity button will combine multiple brush entities, though we won't need that yet.
This is a useful and important distinction because there are times for both use cases, though generally combining multiple brushes into one brush entity is preferred if possible. For instance if your spawn room has two exit doors, then the triggers for the doors (which we will go over shortly) would be better separate, because if they were combined, touching either door would open both doors which is incorrect. On the other hand, something like our two triggers here would be better as one brush, since they'll be the same respawn room entity, and we want them to have the same settings. Generally speaking unless you want brushes to be able to move independently or do different things, they can be combined for efficiency.
In the case of our respawn room, this is all the same room and therefore we want this to be a single respawn room entity. Select both trigger brushes and press the Entity button to convert them to func_detail.

func_detail is just the default brush entity type, similar to how prop_static is the default point entity type, so we'll change it to the entity we need. Turn your trigger into a func_respawnroom and set the Team keyvalue on it to RED.

func_respawnroom does a few things, but the most important ones for now is that it allows players to swap class instantly without dying, it prevents engineers from placing buildings, and prevents players from carrying flags (such as in ctf) within them. Any spawnroom you create should have a func_respawnroom within it's boundaries.
The reason we use the second respawnroom brush in the doorway is specifically for the prevention of engineer buildings. If you put your door in the middle of the doorway, an engineer would still be able to build on the other side, allowing them to build exits in spawn and thus allow enemy spies inside your spawn room. You'll want to adjust the respawnroom brush to be as far forward as you want engineers to build near the door, but generally right in the middle of the door entity itself (or in our current case, the doorway) is sufficient. It should not extend too far from the door, as players could switch classes outside of spawn if so.
Brush Resizing and the Vertex Tool
But you'll notice that we created our brush in the full size of the doorway, so let's fix that. Select the brush and then drag it to be sized in half the doorway.
Unfortunately, you'll notice a new problem - the full entity itself got resized, not just the piece we selected. You can see the main respawnroom now isn't flush with the wall closest to the doorway.

Go ahead and undo that change and we'll do this properly.
There are two ways you can go about fixing this, using either the Solid selection mode, or with the Vertex Tool. My personal preference is the vertex tool due to more broad application but for this use case, both will achieve the exact same result. We will do both so you get an idea of how it's done in either case.
In the case of the Solids selection mode, you'll head to the top of your right sidebar to the Selection Type area, selecting Solids. Now when you use the selection tool on the doorway trigger, only that is selected, not the full entity. This selection mode allows you to select individual brushes regardless if they are part of a larger entity or part of a group. You can go ahead and resize the brush now to be half the size of the doorway.

Note that unless you are doing a maneuver like this, you want to usually be on either Objects or Groups, as staying on Solids may cause problems for you. So once you're done, change back to Groups.
Go ahead and undo that change, swap back to Groups, and instead switch to the Vertex Tool. This is a very powerful tool which lets you manually modify the vertices of a brush. While you can use it to make interesting shapes, I find the best use out of it comes from being able to move the boundaries of multiple brushes at once without causing resizing bugs. When selecting something, you can either select the object itself in 3D with the Vertex Tool already selected, OR you can select the object beforehand and then switch to the vertex tool. In this case it doesn't matter which you choose, but note the differences that happen in each case (you can click around your map to see this). Once selected you'll see all corners of the brush highlighted with the edges red.
Like the Cutting Tool, the Vertex Tool has three modes (corners & middles, corners only, middles only). Generally speaking you want to always be in the corners & middles mode (both white and yellow dots) unless you have a reason not to be. In this mode, go into your 2D view and drag a selection box around only the vertices that are on the outer edge of the brush that we want to move. You can then either drag them with your mouse or use arrow keys to move them into the desired location. Note that with the vertex tool you can select vertices with your mouse but unless you have a good reason to, you should generally select your vertices with a drag box first before moving them.
You can see what a selection box for this tool looks like. In this case, I created the box in the top view. Most of the time you won't need to, but you can drag it to be a 3d selection in the side/front views.

After pressing Enter you can see all the vertices within my selection were selected and can be moved. Note that when a selection has a width of zero (such as when first creating it on the 2d grid), it has "infinite" width. It only gains an actual width if you drag it on another view.

Respawn lockers
Now that our respawn room itself is done, let's add another critical part of a respawn room, the respawn locker. The locker consists of two parts, the prop, and the trigger.
Use the Entity Tool to create a prop_dynamic. There are three types of props, prop_static, prop_dynamic, and prop_physics. The majority of props on a map are static, a handful will be dynamic, and only few maps will have physics props, with them generally being unused and a left over feature from half life 2. Static props are things like trees, crates, or bushes, they have a single model and don't move. Dynamic props can have animations or can be moved around, for example the control point is a dynamic prop as it changes model depending on what team controls it.
Generally speaking unless you need a prop to be dynamic, it should be static. The respawn locker has an animation for the doors opening and closing, and therefore should be a dynamic prop. Physics props are things like the tables, chairs, and crates of half life 2 which allow players to hit them around. TF2 maps don't usually use this feature so physics props will be ignored for the sake of this guide.
On your newly created dynamic prop, select the model value, and on the right you'll see an option to browse. This will open up the model browser. The model browser takes a bit to load for the first time (each time you open hammer that is) as it loads in models.
In the bottom left search for resupply_locker. If you don't see anything yet, wait a second or two and then delete/readd one of the letters in your filter, this will make the browser do another search. Double click it to select the model.

Rotating Objects
You'll notice our respawn locker is facing the wrong way, so let's rotate it to face the right direction.
In order to rotate something in hammer, click it again in the 3D view to cycle selection modes. As with previous tools, there are 3 settings for brush movement, scale, rotate, and skew. For point entities, the only relevant one is rotate, as scale and skew do nothing. Scale is identified by having squares on the corners and edges, rotate is identified by having circles on the corners, and skew is identified by having squares only on the edges. Generally speaking you won't need skew mode as it's imprecise and tools like the cutting tool or vertex tool are better. Click your prop until it's in the rotate mode.
Hammer++ has a feature called a pivot point, which is a circle with a cross in the center, usually located at the center of an entity. If you're familiar with 3D transformations or just any sort of modeling, animation, math, etc, you'll know that this is the point around which the object rotates.
To demonstrate this, click and drag the pivot point a short distance away from the prop, and then while in rotate mode, grab one of the corners of the prop and shift it. You'll see the prop rotates around your pivot point. This is a useful feature if you're creating something large and want to rotate around the edges of it, but in our case the only thing we want to do is just change the angle of our prop to be facing the right way.

Undo any rotation you just did and move the pivot point back to the middle of the prop. Now when you rotate it, it'll be just rotating in place. Make sure it's facing the right direction. You'll notice that when you rotate the object, the Angles key value is updated. Changing this value directly can be helpful if you want to hit a specific angle, or if you mess up a prop and want to reset it you can change this to 0 0 0. Note that changing this value does not allow usage of a pivot point because this is just the local angles, while the pivot point is a hammer abstraction.
Note that if you haven't already, you can now rotate your spawn point to face the spawn door.

You can also move the locker so it's flush against the wall. Also make sure it's flush against the floor, you don't want a floating locker!
Respawn locker Trigger
Next up we'll want to create a trigger for our respawn locker, this will define the area where players walking near the locker will get their health and ammo restored. Select the respawn locker and then use the brush tool to create a trigger next to it.
You will notice that if you select your newly created brush, in the 2D view some of the sides will be reported as having fractional lengths. Props typically do not have sizes that correspond to the grid, and as we know having fractional sized brushes is not a good idea. Resize the trigger to be 112 long x 112 high x 80 wide, the typical size used in Valve maps. You will need to change down to grid size 8 to do this.

Since we only have one brush here, we can use either Ctrl + t or the Entity conversion button to create our entity. If you recall, even if we had multiple respawn lockers, we wouldn't want to make it so touching one opens the door of the other, so each locker trigger will be a separate entity. After converting it to a func_detail, change the type of the entity to func_regenerate. This is the trigger that upon being touched, will refill a player's health and ammo to full as well as update their loadout if they swapped weapons.
However, the game doesn't know what respawn locker to open when the trigger is touched, so we need to identify it. Select your locker prop and in the Name section, give it a descriptive name, like locker_prop_red_1. Descriptive names help with searching for entities later, though any name will work in this case as long as it's unique.

In the Associated Model key value on your func_regenerate, set the value equal to whatever the name you gave your prop is. Note that we do not need to give our func_regenerate a name unless another entity needs to call it or interact with it in some way. Since it's the start of the chain, it can function just fine without a name.

Now that you have that set, our respawn locker is done. As with most respawn rooms, you'll want to be symmetrical. Select your locker prop, then while holding Ctrl select the trigger. Now when you hold Shift to drag, it duplicates both at once. Move the new locker to the other side.
You will notice that if you select the newly duplicated locker, it still has the same name as the previous one. With the exception of a few entities (such as path_track), duplicating an entity does not give it a new name. Update the new locker to a new name, like locker_prop_red_2.
You'll also need to edit the trigger, as it'll be using the old name. Select it and change it's associated model to your new locker's name.

Creating the Spawn Door
We now have functional respawn lockers for our spawn room. Now all that's left is the most important feature of a respawn room, the spawn door. This will prevent enemies from getting inside the spawn so that the team can spawn in safely.
A respawn door consists of three parts, the door brush, the door trigger, and the respawnroom visualizer.
Firstly, the door brush. Select the <red dev grid> texture and create your door, It should fill the doorway and not be too thick. Make sure the door is flush against your respawn trigger and they don't overlap, this is usually how it's done in valve maps.
Convert the door brush into a func_door. func_door is a useful entity that has applications beyond just doors but in our case we'll be using it for a simple case. Give your door a descriptive name like spawn_door_red.

func_door is an entity that works by giving it a speed, and a direction, and then it will move back and forth along the direction, for the length of the door in that distance, at the given speed, back and forth between there and it's original starting point.
We want our door to move up like most spawn doors. First let's set the move direction. In the move direction key value, you'll notice there is a -90 0 0 angle selection (it may be another default depending on your fgd), as well as a dropdown, and a circle. The circle itself is relative to the directions in your top 2D grid, while the dropdown has some preset values that are helpful. In this case we want it to move up, so click the dropdown and select Up.
The speed is equal to the number of units the door moves per second. Set it to 300 which is the value Valve maps usually use. You will also want to set Lip to -1 so the door retracts slightly into the ceiling to improve visuals.

Just in case, you'll want to check your door's flags. Select the Flags tab at the top of the entity menu, and simply ensure that Touch Opens is unchecked.
Next we are going to create the trigger boundary for the door. This trigger will determine where a player needs to stand in order for the door itself to open. Select your door then create a trigger brush. You'll want the brush to stick out around 64-80 units from the door, which is a value Valve maps usually use. 176 is a good size for the brush if you made your door 16 thick.
Convert your trigger brush into a trigger_multiple. trigger_multiple is a generic trigger type, which simply put is just an area that can do something specific you define when a player touches it.

Entity Outputs and Making the Door Open
To get this trigger to do what we want, we'll need to give it an Output. Head over to the Outputs tab, you'll see a menu like this.

Outputs on an entity are events that get called by the game when certain game events occur. For example, when a player touches a trigger, when a piece of ammo is picked up, when a round starts, when a breakable takes damage, when a point is captured, etc.
In our case, we want to create an output that fires when a player enters and leaves this trigger, to open and close the door respectively.
Select new and then edit your outputs to look like the following.

In the case of the open action, we want to use OnStartTouchAll instead of OnStartTouch. For a trigger, OnStartTouch fires every single time a player enters the trigger. That means if two players enter a doorway at once, the door would attempt to open twice. On the other hand, OnStartTouchAll fires only for the first player to enter a trigger, then it cannot fire again until all players have left the trigger's bounds. For our spawn door we only want the door to try to open once when someone first enters, not to continually try to reopen every time someone enters it even if it's already open, so we use OnStartTouchAll.
Similarly, we use OnEndTouchAll instead of OnEndTouch. OnEndTouch fires every single time a player leaves the trigger. That means if two players are in the trigger at once, and one player leaves, it would fire while the other player is inside, causing them to potentially get crushed by the door. (door damage?). On the other hand, OnEndTouchAll only fires once the last player in a trigger leaves, when the trigger truly empties. For our spawn door we want the door to only close once everyone is outside it's area, so we use OnEndTouchAll
The target entity is self explanatory in the sense that we want it to target our door. However, it should be noted that if you have two entities of the same name, and you use that name in an output, the output will apply to both. For instance if we had two spawn room doors both named the same and we had this same logic, going near one would cause the other to open as well. It's the same principle as we discussed with the associated model with our respawn lockers.
The output in this case is going to be Open and Close. If you click the dropdown you'll see the entity has quite a few outputs, but for this guide we aren't going to need any of them, so just use Open and Close.
The delay section tells the game how long to wait after the event occurs to run the output. In this case we want both to be zero, as we want the door to begin to open and close as soon as someone enters and exits the area respectively.
Lastly is the number of fire times. This is a feature you will seldom need to use, it tells the game how many times this output can fire before it stops working for the entire rest of the round. -1 just means it can run as many times as we want, and obviously we don't want our respawn door to stop working after so many uses, so leave this -1. Unless you have a good reason to change it, this should always be -1.
Filters
We now have a functional door, however there's two issues. Firstly, enemies are able to use this door, as the trigger accepts any players who touch it, so a blue player walking up to this spawn door would open it. Secondly, even if our door was only able to be opened by red players, there's nothing stopping blues from walking in when it is open.
To prevent enemies from opening the door, we'll use a filter. Create a point entity of type filter_activator_tfteam.
You'll see a few keyvalues that are basically self explanatory, so set the Team to RED in this case.
You will want to give filters descriptive names. You want your filters to be explanatory at a glance, for instance if I see a filter named "filter_red", does that mean it filters OUT reds, not allowing them, or it filters reds in, ONLY allowing them?
I would recommend something like filter_allow_red or filter_red_only for allowing reds, then filter_deny_red or filter_no_red for deny (you will most likely not be using the "deny red" type and instead be using an "allow blue" but if you do, make sure it's descriptive). In this case, let's name it filter_allow_red.
Unless the logic is specific to an area, you should generally centralize your logic entities in one location in the map. I like to put my logic entities near the center of the map, such as above the middle control point. If it's an asymmetrical map, it might be near the first or last point. But generally you want to have all your logic together, as it will make finding it for you (and others) easier, and you won't lose track of it. In the case of this map let's put the filter in the middle of the large room like so.

Now, within our door trigger, we can set the filter value to filter_allow_red. You will notice a dropdown, this shows all the filters you have on the map and is also why giving a descriptive name is so important, because finding it in this list will become trivial.

Respawn Room Visualizer (brush)
The next problem we have to deal with is not allowing enemy players into the spawn when the door is open.
Select the tools/nodraw texture, then create a brush entity the exact same size as the door. nodraw is a special texture that is invisible in game, the game knows not to even attempt to render any brush face that has nodraw on it. In our case, the barrier is largely invisible, so we want it to be nodraw to start off with.
However you will notice a problem. When you try to select the door or the brush entity, you'll have trouble selecting a specific one. In this screenshot I have the newly created nodraw brush selected, but you can't see it due to overlapping with the door.

There are two ways to reconcile this.
The first one is the easier one. Instead of making this new brush the exact same size as the door, extend it a bit into the spawn. You'll understand why once we define the entity itself but this extending into spawn is no problem.

Alternatively, you can keep it that size and use Hide to select it. I would recommend hiding most of the time, so go ahead and ctrl + z if you extended the brush.
The Uses of Hiding
Hide is a very powerful part of Hammer that allows you to temporarily hide objects. When an object is hidden, not only is it hidden in the editor, but it won't be compiled if you decide to compile while you have the entity hidden.
You can press h to hide the selected entity, u to unhide ALL entities, or ctrl + h to hide everything except the selected entity. When you are working on a small area, it can often be helpful to use ctrl + h to select only that area, so the rest of your 2D grid isn't cluttered with other geometry.
In this example I hid the main walls of our larger room so we can see what's going on inside the respawn room.

Unless you're intentionally trying to compile without a specific entity, you should get into the habit of compulsively pressing u before any compile so you don't accidentally compile your map with some of it missing. The above example wouldn't compile because it's missing walls.
In the case of our door here, there's a quick and clever way to only select one of the entities. Firstly, just click and try to select. IF the entity is already the one you wanted, just make the edits you need. IF it isn't, just press h to hide it, then select the other entity underneath that you actually need. This lets you keep the size of your brushes while making them still selectable. Generally it's better to just make sure your brushes aren't the same size as each other, but this is an option if you need two brushes at the same size.
In this example I hid the red door after selecting it and now I have free access to the newly created brush

Respawn Room Visualizer (entity)
Now that we have our nodraw func_detail, go ahead and convert it to a func_respawnroomvisualizer. This is a special entity that is only visible/solid to the enemy team. The team you select in the keyvalues is the team it belongs to, in this case the RED team. To them, this entity will be completely invisible and nonsolid and they can walk right through. Conversely, the BLU team will be able to see any non-nodraw texture on this, and it will be an impassible invisible wall to them.

You may recall that on most maps when walking up to an enemy respawn room, there is a red circle showing that you can't enter. This is a specific texture Valve uses for respawn rooms.
We could use the Apply Current Texture tool to set this texture across the entire brush, however we don't want to use the texture where it won't be seen. Therefore we need to use the regular Toggle Texture Application to apply it only to one face.
The Toggle Texture Application Tool
Select the Toggle Texture Application tool, which I'll refer to here on as the Texture Tool. You will notice if you click any face that your currently selected texture is updated to it, this is the color picking function. The right click will instead apply the current texture to any face you click. To demonstrate this, select the 3dskybox texture on the ceiling, then apply it to one of the walls. Then undo this by selecting one of the other walls and applying it back to that same wall you changed.

The current texture selection is what the texture tool will be when you first open it but it won't adhere to it. Luckily if we need to change on the fly, there is a Browse button on the texture tool that will open the texture browser. Select the overlays/no_entry in the browser, then use right click to apply it to the enemy facing side of the nodraw respawnroomvisualizer. Note that just like when selecting a brush, applying a texture also suffers from the same issue if your brush is flush with another brush. In this case though, merely clicking it and hoping for the best isn't a good outcome. You'll need to go back to the selection tool and use either h or ctrl+h to get the right brush selected. After that, re-open the texture tool (you may need to reselect the blocking texture) then right click the face you want to change.

You will notice that the texture looks off, it's too small and being repeated, it's also not centered. We want to change that so it's the correct size in the correct location.
Left click the texture, and you'll notice that in addition to selecting it, you'll have access to the settings for the texture at that particular face. We can go over advanced texturing later but for the time being, the easiest way to resolve this is to click Fit, then go to the x and y scales, and copy paste the larger of the two into the other. Lastly, press C in the Justify section to Center it. Click apply and you'll see the texture in the right location at the right size.

Our respawn room should be good to go, but let's give it a test before we make the blue one (don't worry, it will be faster than you think!).
Testing our Respawn Room
Compile and load into the map on RED team. Walk up to the door to make sure it opens and closes, check the respawn lockers to make sure they regenerate properly, change classes to make sure you're in a respawnroom, and make sure you can't build a teleporter on your side of the spawn door.
Next change to BLU team and walk up to the door to confirm it doesn't open.
You'll notice that our visualizer texture is Z-fighting (when two brushes are flush with each other and flicker) and so the door looks bad.

To fix this, go back into hammer and instead move the visualizer to be flush with the back side of the door. Unlike what I lead you to believe, Valve maps use this to only show that you can't go past when the door is open, so it shouldn't be visible if the door is closed.

Since we'll be duplicating spawn rooms for BLU side, let's completely finish off the RED side by going over lighting.
Base Map Lighting
Generally speaking there are three light entities you'll be interacting with, light_environment, light, and light_spot(?). For the purpose of this map we'll only be covering light_environment and light.
To start off with, how light works is that if a map has no light entities at all, it will be rendered in "fullbright." This means no lighting whatsoever, up until now we've been playing our map in fullbright. Adding even a single light entity will stop this and make the entire map need lighting, for example all rooms will become dark. Fullbright is not meant for release maps and is only a way for you to see your map prior to doing lighting.
Virtually every map will need a light_environment. Unless you have a totally indoors map like cp_junction, your map will have some sky that needs ambient light. light_environment generates ambient light from wherever you have skybox textures.
Lighting is in large part personal preference, and doing good lightning is hard. A later tutorial will be dedicated to that, but for right now we're going to just set our light_environment to use the same values 2fort uses.

Pitch however is a non-default value so we need to add it by disabling smart edit

Individual Lights
For our indoor lights, we'll keep it simple. Create a static prop on the ceiling with the <light prop?> model, align it, then create a point entity of type light. This entity just emits light from the location, though it's less of an entity and more of an indicator for VRAD (the light compiler). We'll just set them to these settings as a basic value, you can play around with it as you like. Move the light entity below the prop.
<pic of light>
Note that for the brightness, there are 4 values. The first 3 are the rgb values while the fourth is the brightness. In this case we'll just go with 250.
Getting good lightning takes trial and error and you may find some success examining valve maps to see how they do things (explored in the next part of this guide).
We want to move these lights around but it's a pain to have to select both each time we want to clone them. Instead, we can group them. Select both the light and the prop and click the group button at the top.
These two objects are now grouped in hammer. This has no effect in game, it's just for organization within the editor. You can now move them around together. You might notice you can't select an individual object anymore, but there's an easy way around that. The Selection Type has a Groups and Objects section. When Groups is on, whenever you click an object, if it's part of a group the whole group will be selected. Conversely if Objects is selected, groups are ignored completely. Note that Objects and Solids are different as if you have a single entity with multiple brush components (like our respawnroom), that is still one object, as opposed to these editor-only groups that we just demonstrated.
Use shift to create a few lights in our respawn room so that it won't be dark.
Fullbright
Compile and load into the map. You might notice nothing changed, but that's because of a cvar quirk with fullbright. If you load into a map that does not have any lighting, the mat_fullbright cvar is set to 1. If you swap maps to something else it stays, and then all other maps you play will be fullbright. You can confirm this by quickly doing a changelevel to a valve map. The fix to this is to simply reset fullbright by doing
in console.
Once you do, you should see your level lit up properly.
Duplicating Objects
Next up let's create the blue spawn room. It would be a pain to have to recreate everything we just did manually, so let's do some quick shortcuts to reduce the work.
On the opposite wall to the one you made your RED spawn room, go ahead and delete that wall. Then, go back to your respawnroom, and in the 2D grid, drag select the entire respawnroom itself as well as the wall.
Click on the selection until you've entered rotation mode, then move the pivot point to the middle of the large center room.
Hold shift, then rotate the room to the other side, and finally let go of shift. You'll see the entire respawn room has now been duplicated!
We will need to fix all the entities inside, however. See if you can figure out all the fixes on your own, they are listed below for you to spot check against.
Now if you compile and load into the game, you have a respawn room for both teams.
Lastly for this map, let's set this up with a gamemode. The easiest one will be koth, so we can go ahead and set it up.
Control Point Layout
Before we set up the gamemode logic let's create a zone for our control point. Place a prop_dynamic named point_prop with the model models/props_gameplay/cap_point_base.mdl right in the middle.
One problem with our current setup however is that it's not obvious where the capture zone of our point is due to our floor being a single texture.
We'll be creating some lines on the ground. There are a few ways you can go about this, such as creating very thin brushes and overlaying them, but for this guide we'll instead be cutting into the ground with the clipping tool.
As you may recall the clipping tool textures new faces it creates with whatever your current texture is. Use the texture tool to select the dev grid before we go ahead with this. The reason is that the clips we're about to make won't be visible unless you freecam into the ground, so we should be proactive. Once you have that selected, go ahead and make four cuts in the ground around your control point like so. Do not deselect the brushes at any point, just leave them selected - you'll see the clipping tool will make cuts along multiple brushes at once.
<3x3>
While this is technically fine, in practice you don't want to make square cut holes like this, as resizing the outer areas will introduce issues. Instead, we want to make sure our brushes are as large as they can be whenever possible.
To resolve this we are going to use the merge feature. There are two ways to merge, either with Ctrl + Shift + m or by going to Tools > Merge. Merging combines two solid brushes together. It can only <?> be used on world brushes, and any brushes you chose have to share dimensions along the merge line. For instance, below would not be able to be merged
<invalid merge?>
while the below would
<valid merge?>
You can merge more than one brush at once. To demonstrate this, go ahead and select 3 of the outer brushes we created with our cuts (ideally ones parallel to a spawn door) and then perform the merge. You'll see all the brushes get combined together. Go ahead and do this for the other side as well.
<pic>
In terms of alternate ways to have done this, you could have also deleted two of the three brushes and resized the remaining brush into the open space, or you could have done your cuts properly in the first place by instead only selecting the middle brush when making your second set of cuts.
Also worth noting, you can use the vertex tool to make your corners diagonal like so
<pic>
however I would not recommend this for floors, as floors will often need to get stretched and resized which becomes a pain to do when you set up the corners like this.
Once you're done, you are going to repeat the same process but this time only for the brush under the control point, except the cuts you make with the clipping tool will instead be near the edge of the brush.
Your final brush layout should look something like this once you're done clipping
Next up we want to use a texture to demonstrate where our capture area is. For this example we'll use the props/hazardstrip001a texture. Go ahead and texture the top part of your thin brush strips with it by using the texture tool. Remember, we don't want to use apply current texture, as unseen textures (such as the ones under the floor) should never be real textures, only dev/nodraw textures.
Control Point Logic
We are going to need a few logic entities in order to create our control point.
Firstly, we need a team_control_point_master point entity which you can place with your other map-wide logic. Name it something like master_control_point. This entity is in charge of all control points on the map, so you'll need one even if your map only has a single point. You only need one of these entities. <?default params>
Next we need a team_control_point point entity. Go ahead and name it something like control_point. If this were a 5cp or a/d map we'd give it a more descriptive name, but as we're making koth, this name will do fine.
Move the entity right to the middle of the control point, and set up the key values as shown below
Next we need the trigger which defines the area where you stand to capture the point. Go ahead and create a trigger that's at least 256 high, using the hazard lines as the boundary for it.
The trigger should be a trigger_capture_area entity. Set the key values as shown below, making sure that the Control Point key value is targeting your control point entity which should be named control_point as per the previous steps.
This trigger also needs two outputs which will change the skin of the control point. Models in source have a concept called skins, which allows them to change their look without needing to have entirely separate props which would be a pain to work with. In this case, the control point has a base skin, a red skin, and a blue skin. Set up the outputs as shown below.
<pic>
Note that while all props can be given a skin, you need a dynamic prop if you want to change the prop's skin during a round. Some static props like signs or trees will have alternate skins you can set at compile time, but this should only be used if you don't intend for it to be changed mid round.
King of the Hill Logic
We aren't done yet, we have a control point but there's no gamemode set, so the only thing you can do with it is just capture it back and forth - there's no timer or logic behind it other than the capturing.
Open up the outputs of our trigger_capture_area and add the two koth outputs shown below to set the koth clock to active on capture. <?default respawn wave time?>
Next create a tf_logic_koth entity. You can leave this untouched as the defaults will be fine, but you can go ahead and click the entity to see what those defaults are and change them if you wish.
Lastly we need a logic_auto. This is a useful entity for running things automatically when the game starts. Set the values to the below.
The Goal String is a value which utilizes a base TF2 translation file (in this case, #koth_setup_goal) to give players a HUD indication of what the goal is. Base gamemode all have their own goal strings already in the game. If you're making a custom gamemode without a goal string, you can write the goal here manually, but note it won't be translated.
The Respawn Wave time, as shown being set earlier, is how long the "respawn waves" are. In TF2, players respawn in waves, rather than everyone having individual spawn timers. When a player dies, a new respawn wave is set <fact check?> and anyone who dies prior to that wave will get a reduced respawn time, such that all these players respawn at the same time.
Generally speaking, respawn times are such that attackers have a shorter respawn time, while defenders have a longer respawn time. This is how it's set in all valve maps as well as most community maps. This is because attackers have to continually push against fortified defenses, and if both teams respawned with the same times, it'd give entrenched defenders an unfair advantage that would make breaking through defenses harder, so the reduced respawn times give the attackers an edge. This edge does not need to be very substantial, only 2-3 seconds on koth <fact check?> is sufficient most of the time. Larger differences might be important for other gamemodes.
Testing our KOTH Map
Now that we have our map logic ready, let's go ahead and compile and test it out.
If everything was set up correctly, you should be able to capture the point as one team, swap to the other team, and capture it back, while seeing the timer tick down. You can also use this opportunity to check the respawn wave times to confirm they're being set correctly.
If your map is functional at this point, you have successfully completed the beginner guide to making a TF2 map. You, technically speaking, have all the tools you need to make a basic map. Of course it probably won't be a very good map, which is what the guides after this will help rectify, but you should now know how to use the editor and what it takes to make a basic map.
The last thing you'll want to do is go to File > Save As and save your map as koth_first_map.vmf. Your map should have the gamemode name saved up front so the game can determine what the gamemode is on loading screens and in the server browser, as well as for players to know what the gamemode it as a glance of the map name. Secondarily, this will also back up your first map if you want to come back to it later and do your own customizations. We'll be using this koth_first_map.vmf variant for the guide after this one.
The next guide will cover making a more interesting map layout with the basics of level design.
Hammer
First off, navigate to File > New and load into a new map.
Your window should be shown in a 2x2 grid. Three of these grids are 2D views at different angles, while one grid is the 3D view. If you don't have them set correctly, look to the top left of each window to see the window type (such as top (x/y) or front (y/z)). Right click this to change the window type.
Generally speaking you want to have the following windows:
- 3D Shaded Textured Polygons
- Top (x/y)
- Front (y/z)
- Side (x/z)

On the left of the program are your tools. To get started we don't need all of them, but some of the basics are:

Selection tool: This lets you select, move, and resize brushes and entities, or create selection zones by dragging in one of the 2d views.

Block Tool: By creating a selection zone with this tool and pressing enter, a brush of that specified size will be created. It can be resized and molded afterwards

Entity Tool: This tool is used to create entities like props as well as internal game logic, such as gamemode logic, lights, player spawns, etc.

Toggle Texture Application: This tool is how you will apply textures to brushes in most cases
Basic Brush Creation
We are going to be creating the floor brush, but first off we want to know what texture it should be. Whenever you use the block tool to create a brush, whatever texture you currently have selected will be applied to all faces of the brush. It is generally considered best practice to make sure that any textures not visible to players are set to nodraw, however testing a map with nodraw is difficult. Instead, we can use a dev texture and mass replace it later in the development of our map once we get to texturing.
In the Current texture section of the Right sidebar, select Browse, then filter for measuregeneric, and double click on dev_measuregeneric01b (the gray grid) to select it.

Before creating a brush, check the bottom right corner to ensure Snap is set to On. If it isn't, press Shift+W to cycle it to On. Generally speaking, you always want grid snap on.
Next, select the Block tool, and on your top (x/y) window, drag a box to be size 2048x2048. If you align it with the center of the map, you'll notice it lines up perfectly with the orange lines. On either your side or front view, ensure the brush is thin, around 16-64 Hammer Units tall. Make sure the brush is underneath the origin, ideally flush with the blue axis line.
If you're having trouble lining it up easily, you can use the bracket keys [ and ] on your keyboard to change the grid size. Check the bottom right corner to see your current size. For this exercise, stick between 16-64 unless otherwise specified.
Your selection should look like this. Some labels are applied to help understand the grid and 3D views

Press Enter to create the brush.
To navigate the 3D view, press z to toggle freecam controls. Scroll wheel can be used to move forward and backwards, as well as WASD to move.
If you created the brush in the right spot, you'll see the origin in the 3D view like this.

As with most editing programs, Ctrl + z will undo the last action you took which can be helpful if you misclicked or did an action inadvertently.
Now, let's create some map geometry. Using the same method as before, go ahead and create four walls around the floor brush that are 512 units tall. Note that when creating a brush in the 2D view, the unseen third dimension will equal the length of the last brush you selected. You can see this for yourself by selecting the floor brush, then trying to make a wall in either direction within one 2D view. This selection shortcut only applies to manually selected brushes, so once you create a brush if you want to make another brush of the same height/width, you'll need to reselect it.

Spawn Entities
In order for the map to be able to be compiled, it needs entities within the playable space. The easiest first entity to add is a player spawn.
In the 3D view, navigate inside of your room, then click on the floor using the Entity Tool. The entity tool does not work correctly when used on the 2D view, so you'll be using the 3D view whenever you use this tool.
If you set up the setting correctly previously, you'll have created a red box on the floor (though it's only red because it's selected). This is an uninitialized static prop, which is what we set our default entity to in the options. Double click to open the settings for it to be sure

In order to change this to an entity we want, at the top you'll select Class, highlight the currently class (prop_static) then input info_player_teamspawn. Press Enter or hit Apply to convert the entity

Within this entity we can check the Keyvalues to see what it's configured to by default. As you can see in the Team key, the default value is 0 or None. This means the entity has no associated team with it, which in the context of a team spawn means either team can spawn here. However, we don't want players getting stuck on each other. Perform the same process again to create another teamspawn entity and place them a little bit apart like so.

Note that for spawnpoints, they are required to be floating off the ground a bit. When a player spawns in, they're snapped to the floor, but if the teamspawn is flush against the floor it becomes invalid.
In each spawnpoint, select the Value for team, and on the right click the dropdown. Set one spawnpoint to Red and one to Blu.
Compiling
We're almost ready to compile our map. Use Ctrl + s to save the map. Maps are by default stored in the .vmf format, and can be found in the TF2/sourcesdk_content/tf/mapsrc/ folder. Name your map something like first_map and press Save.
Now we can compile the map. Go to File > Run Map, or just press F9. Once in this menu, press Expert as you will generally always want to be in the expert menu.
You'll want to make sure that bsp, vis, light, and copy are all selected. These respectively perform the map geometry generation, the visibility generation, light generation, and moving it to your map folder. You'll want to make sure $game_exe is unchecked. Generally speaking it's easier to just have your game open and then compile on the side than to have the compiler open your game. Additionally, on Linux, this feature does not work at all as Hammer can't open your game.

Once ready, press Go to start the compile.
Unfortunately, this map doesn't compile! If we check the compile window, it will mention that
Code: Select all
Entity info_player_teamspawn leaked!Identifying Leaks
Press any button to exit the compile window, then go back into hammer and navigate to Map > Load Pointfile. If there's a vbsp (geometry) compilation issue, Hammer will create a pointfile that shows you exactly what went wrong.
As you can see in your pointfile, the entity that "leaked" has a line pointing towards where it leaked.

But what is a leak? In Source, all maps must be completely self contained. If any line can be drawn from the inside of a level to the outside, then it "leaks." Think of your map as being like a spaceship, and leaks like hull breaches. Even a small hole will let out all the air.
You can fill this leak using a dev texture brush. Technically, any world brush will seal a leak (aside from some special tool textures like clips). But if all maps had to be enclosed inside rooms, you wouldn't be able to have levels outdoors. Therefore, we can use a skybox brush to create a sky for our map.
You can unload the pointfile the same way by using Map > Unload Pointfile
Skybox Brush and Brush Duplication
Select the tools/toolsskybox texture (you can filter for tools/ to make finding tool textures easier). Note that you should select the light blue toolsskybox texture, NOT the purple toolsskybox2d texture.
While we could create another brush from scratch, we know the ceiling is going to be the same size as the floor, so instead let's just duplicate the floor and change the texture.
When holding Shift, any movement applied to a brush or entity (resize, movement, rotation) will cause the movement to instead create a duplicate of that brush.
Select the floor, then while holding Shift the entire time, move the ceiling up to the top of the walls. You can do this either by dragging it with your mouse in the 2D view, or (based on what grid your mouse is focused on) the arrow keys. If dragging with your mouse, hold shift for the entire duration of the movement. If using arrow keys, only hold shift for the first arrow press, as each subsequent one will create multiple duplicates. Note that this same principle applies to entities, you can go back and redo the creation of the second teamspawn entity by holding shift and moving the first one as a demonstration of this.
You can also use Ctrl + c and Ctrl + v to copy paste brushes, however using Shift tends to be more precise.

Apply Current Texture
Once you have the ceiling in place, select it and click the Apply Current Texture button. Unlike the regular texture tool which is more precise, this is a quick and easy way to apply your current texture to all faces of a brush indiscriminately.
Once done your room should look like this

Loading Into Your Map
Following the previous steps, you should be able to compile now without errors.
Once compilation finishes, you can load into your map by booting up TF2 and in console typing
Code: Select all
map <name_of_vmf>Code: Select all
map first_mapCode: Select all
changelevel <name_of_vmf>When loaded into your map it should look something like the below. You should be able to join a team and run around in this map now. If you spawn under the ground or stuck in the void, refer back to the spawn entity creation section.

We have a functional map that you can load into but this map has nothing in it. Firstly we'll create some respawn rooms for each team.
Respawn Room and Clipping Tool
We are only going to make one respawn room for now, so don't worry about mirroring any of this just yet.
Pick one wall you want to be the RED spawn. The specific one does not matter, though if you want to follow this guide exactly, the left wall (from the top view perspective) will be used.
We will be using the clipping tool. This tool allows you to cut one or more objects along a plane. Most of the time you will use it as a straight cut along an axis, so that's what we'll use it for during this guide, though note that you can make more interesting diagonal cuts by moving the cut vertices in your 2D grids.
Select your wall and then in one of your side 2D grids, click and drag to create a cut line horizontally. Having grid snap on for this step is important so verify it, as having cuts not aligned on the grid will introduce a lot of microgird errors later.
After the initial line is created you can freely drag it around with the vertices. Your initial line does not need to be in the exact right spot, just get it close enough and then after move it into the right location. For the time being, don't drag any of the cuts on your top 2D grid as this will make the cut a 3D diagonal one which we don't want to do.

You can see on the side the size that each brush will be after the cut. Get the bottom brush to 128(?).
You will notice that one brush is red and the other is white. Depending on your cut setting, cut can be set to either keep both brushes, or delete one. The red parts will be deleted, while the white parts will be preserved. To cycle this, simply click on the tool again, or anywhere on the 2D grid. There are 3 settings (delete left, delete right, keep) so just click until both the top and bottom brush are white. Once ready, press enter to perform the cut.

Next, let's create the door hole. Select the bottom brush, then this time create a vertical cut in either your top view, or the side view which has the correct face depending on which wall you picked. Cut it right down the middle so that both sides are equal. Perform the same operation as previously for the cutting settings, keeping both brushes.
For each brush, select it and drag it to one side so that an opening is created in the wall. The final width of the door should be 192(?), which you can verify by dragging a selection box across the width after you resize the walls.

Unfortunately there's one problem, the brushes now have skybox textures on the side (if you followed this guide exactly). This is because when you use the clipping tool, the newly created faces on the brushes will be set to whatever texture you have active.
To fix this, use the Apply current texture tool on each brush on the wall after selecting the dev grid again.
Below you can see what one of the brushes looks like after fixing the texture on it. A good rule of thumb is to have the texture you want to use in the cut selected beforehand. When doing map development this usually means a dev grid or nodraw, to ensure newly created faces use dummy textures just in case they aren't seen, and can be retextured later if they are.

Creating the Room
Create a room using the previous principles. When creating a brush a good rule of thumb is that it should only be as big as it needs to be, so for instance you don't want a floor brush to extend beyond the walls. Practicing this will make texturing much easier in the future. For example, in the area within the door itself, create a small brush just for that floor rather than dragging the whole spawn room floor over.

Find the player spawn in the middle that is set for RED team and drag it over into your spawn room. After moving it, you can use Shift to duplicate it a few times. Generally speaking all spawn rooms for all maps will have multiple spawn locations, this is because the game will first try to fill up each spawn before placing players in the same spawn location, and stacking everyone in one spot gives poor visibility. Unless you intend your map to be played on servers with >32 players, the respawn room spawnpoints for a team doesn't need to add to more than 12 cumulatively as a rule of thumb.
There are a few aspects to spawn rooms we will need to create. The spawn room boundary, respawn lockers, and the spawn door.
Firstly, the spawn boundary. Select the tools/trigger texture and create a brush that completely fills the inside of your spawn room.
You will also want to create a trigger that takes up the full space in the doorway. The need for this will be clear shortly.

Brush Entities and the Respawn Room Trigger
We are now going to be creating a Brush Entity. Unlike other entity types, created with the Entity Tool, a brush entity is instead created from one or more brushes. While both are entities, the types of entities that can be brush entities are entirely separate from other "point" entities. For example, a door or trigger would be a brush entity, while a prop is a point entity.
There are two ways to create entities, either with Ctrl + t or by clicking the Entity button in the brush conversion section on your right sidebar. However, they do not do the same thing.
Ctrl + t will turn each brush you select into an individual entity. For example if you select your two triggers and use ctrl + t, they will both be turned into individual func_detail entities. You can verify they are separate by using the selection tool on one of them and seeing that the other is not selected as well, as they are entirely separate entities.
The Entity button will instead take all selected brushes and consider them all one brush entity. If you ctrl + z the previous change to your triggers and then instead use the Entity button, the two trigger brushes will instead be considered one brush entity. You can again verify this by using the selection tool and seeing that clicking on one brush selects both. It's also worth nothing pressing the Entity button will combine multiple brush entities, though we won't need that yet.
This is a useful and important distinction because there are times for both use cases, though generally combining multiple brushes into one brush entity is preferred if possible. For instance if your spawn room has two exit doors, then the triggers for the doors (which we will go over shortly) would be better separate, because if they were combined, touching either door would open both doors which is incorrect. On the other hand, something like our two triggers here would be better as one brush, since they'll be the same respawn room entity, and we want them to have the same settings. Generally speaking unless you want brushes to be able to move independently or do different things, they can be combined for efficiency.
In the case of our respawn room, this is all the same room and therefore we want this to be a single respawn room entity. Select both trigger brushes and press the Entity button to convert them to func_detail.

func_detail is just the default brush entity type, similar to how prop_static is the default point entity type, so we'll change it to the entity we need. Turn your trigger into a func_respawnroom and set the Team keyvalue on it to RED.

func_respawnroom does a few things, but the most important ones for now is that it allows players to swap class instantly without dying, it prevents engineers from placing buildings, and prevents players from carrying flags (such as in ctf) within them. Any spawnroom you create should have a func_respawnroom within it's boundaries.
The reason we use the second respawnroom brush in the doorway is specifically for the prevention of engineer buildings. If you put your door in the middle of the doorway, an engineer would still be able to build on the other side, allowing them to build exits in spawn and thus allow enemy spies inside your spawn room. You'll want to adjust the respawnroom brush to be as far forward as you want engineers to build near the door, but generally right in the middle of the door entity itself (or in our current case, the doorway) is sufficient. It should not extend too far from the door, as players could switch classes outside of spawn if so.
Brush Resizing and the Vertex Tool
But you'll notice that we created our brush in the full size of the doorway, so let's fix that. Select the brush and then drag it to be sized in half the doorway.
Unfortunately, you'll notice a new problem - the full entity itself got resized, not just the piece we selected. You can see the main respawnroom now isn't flush with the wall closest to the doorway.

Go ahead and undo that change and we'll do this properly.
There are two ways you can go about fixing this, using either the Solid selection mode, or with the Vertex Tool. My personal preference is the vertex tool due to more broad application but for this use case, both will achieve the exact same result. We will do both so you get an idea of how it's done in either case.
In the case of the Solids selection mode, you'll head to the top of your right sidebar to the Selection Type area, selecting Solids. Now when you use the selection tool on the doorway trigger, only that is selected, not the full entity. This selection mode allows you to select individual brushes regardless if they are part of a larger entity or part of a group. You can go ahead and resize the brush now to be half the size of the doorway.

Note that unless you are doing a maneuver like this, you want to usually be on either Objects or Groups, as staying on Solids may cause problems for you. So once you're done, change back to Groups.
Go ahead and undo that change, swap back to Groups, and instead switch to the Vertex Tool. This is a very powerful tool which lets you manually modify the vertices of a brush. While you can use it to make interesting shapes, I find the best use out of it comes from being able to move the boundaries of multiple brushes at once without causing resizing bugs. When selecting something, you can either select the object itself in 3D with the Vertex Tool already selected, OR you can select the object beforehand and then switch to the vertex tool. In this case it doesn't matter which you choose, but note the differences that happen in each case (you can click around your map to see this). Once selected you'll see all corners of the brush highlighted with the edges red.
Like the Cutting Tool, the Vertex Tool has three modes (corners & middles, corners only, middles only). Generally speaking you want to always be in the corners & middles mode (both white and yellow dots) unless you have a reason not to be. In this mode, go into your 2D view and drag a selection box around only the vertices that are on the outer edge of the brush that we want to move. You can then either drag them with your mouse or use arrow keys to move them into the desired location. Note that with the vertex tool you can select vertices with your mouse but unless you have a good reason to, you should generally select your vertices with a drag box first before moving them.
You can see what a selection box for this tool looks like. In this case, I created the box in the top view. Most of the time you won't need to, but you can drag it to be a 3d selection in the side/front views.

After pressing Enter you can see all the vertices within my selection were selected and can be moved. Note that when a selection has a width of zero (such as when first creating it on the 2d grid), it has "infinite" width. It only gains an actual width if you drag it on another view.

Respawn lockers
Now that our respawn room itself is done, let's add another critical part of a respawn room, the respawn locker. The locker consists of two parts, the prop, and the trigger.
Use the Entity Tool to create a prop_dynamic. There are three types of props, prop_static, prop_dynamic, and prop_physics. The majority of props on a map are static, a handful will be dynamic, and only few maps will have physics props, with them generally being unused and a left over feature from half life 2. Static props are things like trees, crates, or bushes, they have a single model and don't move. Dynamic props can have animations or can be moved around, for example the control point is a dynamic prop as it changes model depending on what team controls it.
Generally speaking unless you need a prop to be dynamic, it should be static. The respawn locker has an animation for the doors opening and closing, and therefore should be a dynamic prop. Physics props are things like the tables, chairs, and crates of half life 2 which allow players to hit them around. TF2 maps don't usually use this feature so physics props will be ignored for the sake of this guide.
On your newly created dynamic prop, select the model value, and on the right you'll see an option to browse. This will open up the model browser. The model browser takes a bit to load for the first time (each time you open hammer that is) as it loads in models.
In the bottom left search for resupply_locker. If you don't see anything yet, wait a second or two and then delete/readd one of the letters in your filter, this will make the browser do another search. Double click it to select the model.

Rotating Objects
You'll notice our respawn locker is facing the wrong way, so let's rotate it to face the right direction.
In order to rotate something in hammer, click it again in the 3D view to cycle selection modes. As with previous tools, there are 3 settings for brush movement, scale, rotate, and skew. For point entities, the only relevant one is rotate, as scale and skew do nothing. Scale is identified by having squares on the corners and edges, rotate is identified by having circles on the corners, and skew is identified by having squares only on the edges. Generally speaking you won't need skew mode as it's imprecise and tools like the cutting tool or vertex tool are better. Click your prop until it's in the rotate mode.
Hammer++ has a feature called a pivot point, which is a circle with a cross in the center, usually located at the center of an entity. If you're familiar with 3D transformations or just any sort of modeling, animation, math, etc, you'll know that this is the point around which the object rotates.
To demonstrate this, click and drag the pivot point a short distance away from the prop, and then while in rotate mode, grab one of the corners of the prop and shift it. You'll see the prop rotates around your pivot point. This is a useful feature if you're creating something large and want to rotate around the edges of it, but in our case the only thing we want to do is just change the angle of our prop to be facing the right way.

Undo any rotation you just did and move the pivot point back to the middle of the prop. Now when you rotate it, it'll be just rotating in place. Make sure it's facing the right direction. You'll notice that when you rotate the object, the Angles key value is updated. Changing this value directly can be helpful if you want to hit a specific angle, or if you mess up a prop and want to reset it you can change this to 0 0 0. Note that changing this value does not allow usage of a pivot point because this is just the local angles, while the pivot point is a hammer abstraction.
Note that if you haven't already, you can now rotate your spawn point to face the spawn door.

You can also move the locker so it's flush against the wall. Also make sure it's flush against the floor, you don't want a floating locker!
Respawn locker Trigger
Next up we'll want to create a trigger for our respawn locker, this will define the area where players walking near the locker will get their health and ammo restored. Select the respawn locker and then use the brush tool to create a trigger next to it.
You will notice that if you select your newly created brush, in the 2D view some of the sides will be reported as having fractional lengths. Props typically do not have sizes that correspond to the grid, and as we know having fractional sized brushes is not a good idea. Resize the trigger to be 112 long x 112 high x 80 wide, the typical size used in Valve maps. You will need to change down to grid size 8 to do this.

Since we only have one brush here, we can use either Ctrl + t or the Entity conversion button to create our entity. If you recall, even if we had multiple respawn lockers, we wouldn't want to make it so touching one opens the door of the other, so each locker trigger will be a separate entity. After converting it to a func_detail, change the type of the entity to func_regenerate. This is the trigger that upon being touched, will refill a player's health and ammo to full as well as update their loadout if they swapped weapons.
However, the game doesn't know what respawn locker to open when the trigger is touched, so we need to identify it. Select your locker prop and in the Name section, give it a descriptive name, like locker_prop_red_1. Descriptive names help with searching for entities later, though any name will work in this case as long as it's unique.

In the Associated Model key value on your func_regenerate, set the value equal to whatever the name you gave your prop is. Note that we do not need to give our func_regenerate a name unless another entity needs to call it or interact with it in some way. Since it's the start of the chain, it can function just fine without a name.

Now that you have that set, our respawn locker is done. As with most respawn rooms, you'll want to be symmetrical. Select your locker prop, then while holding Ctrl select the trigger. Now when you hold Shift to drag, it duplicates both at once. Move the new locker to the other side.
You will notice that if you select the newly duplicated locker, it still has the same name as the previous one. With the exception of a few entities (such as path_track), duplicating an entity does not give it a new name. Update the new locker to a new name, like locker_prop_red_2.
You'll also need to edit the trigger, as it'll be using the old name. Select it and change it's associated model to your new locker's name.

Creating the Spawn Door
We now have functional respawn lockers for our spawn room. Now all that's left is the most important feature of a respawn room, the spawn door. This will prevent enemies from getting inside the spawn so that the team can spawn in safely.
A respawn door consists of three parts, the door brush, the door trigger, and the respawnroom visualizer.
Firstly, the door brush. Select the <red dev grid> texture and create your door, It should fill the doorway and not be too thick. Make sure the door is flush against your respawn trigger and they don't overlap, this is usually how it's done in valve maps.
Convert the door brush into a func_door. func_door is a useful entity that has applications beyond just doors but in our case we'll be using it for a simple case. Give your door a descriptive name like spawn_door_red.

func_door is an entity that works by giving it a speed, and a direction, and then it will move back and forth along the direction, for the length of the door in that distance, at the given speed, back and forth between there and it's original starting point.
We want our door to move up like most spawn doors. First let's set the move direction. In the move direction key value, you'll notice there is a -90 0 0 angle selection (it may be another default depending on your fgd), as well as a dropdown, and a circle. The circle itself is relative to the directions in your top 2D grid, while the dropdown has some preset values that are helpful. In this case we want it to move up, so click the dropdown and select Up.
The speed is equal to the number of units the door moves per second. Set it to 300 which is the value Valve maps usually use. You will also want to set Lip to -1 so the door retracts slightly into the ceiling to improve visuals.

Just in case, you'll want to check your door's flags. Select the Flags tab at the top of the entity menu, and simply ensure that Touch Opens is unchecked.
Next we are going to create the trigger boundary for the door. This trigger will determine where a player needs to stand in order for the door itself to open. Select your door then create a trigger brush. You'll want the brush to stick out around 64-80 units from the door, which is a value Valve maps usually use. 176 is a good size for the brush if you made your door 16 thick.
Convert your trigger brush into a trigger_multiple. trigger_multiple is a generic trigger type, which simply put is just an area that can do something specific you define when a player touches it.

Entity Outputs and Making the Door Open
To get this trigger to do what we want, we'll need to give it an Output. Head over to the Outputs tab, you'll see a menu like this.

Outputs on an entity are events that get called by the game when certain game events occur. For example, when a player touches a trigger, when a piece of ammo is picked up, when a round starts, when a breakable takes damage, when a point is captured, etc.
In our case, we want to create an output that fires when a player enters and leaves this trigger, to open and close the door respectively.
Select new and then edit your outputs to look like the following.

In the case of the open action, we want to use OnStartTouchAll instead of OnStartTouch. For a trigger, OnStartTouch fires every single time a player enters the trigger. That means if two players enter a doorway at once, the door would attempt to open twice. On the other hand, OnStartTouchAll fires only for the first player to enter a trigger, then it cannot fire again until all players have left the trigger's bounds. For our spawn door we only want the door to try to open once when someone first enters, not to continually try to reopen every time someone enters it even if it's already open, so we use OnStartTouchAll.
Similarly, we use OnEndTouchAll instead of OnEndTouch. OnEndTouch fires every single time a player leaves the trigger. That means if two players are in the trigger at once, and one player leaves, it would fire while the other player is inside, causing them to potentially get crushed by the door. (door damage?). On the other hand, OnEndTouchAll only fires once the last player in a trigger leaves, when the trigger truly empties. For our spawn door we want the door to only close once everyone is outside it's area, so we use OnEndTouchAll
The target entity is self explanatory in the sense that we want it to target our door. However, it should be noted that if you have two entities of the same name, and you use that name in an output, the output will apply to both. For instance if we had two spawn room doors both named the same and we had this same logic, going near one would cause the other to open as well. It's the same principle as we discussed with the associated model with our respawn lockers.
The output in this case is going to be Open and Close. If you click the dropdown you'll see the entity has quite a few outputs, but for this guide we aren't going to need any of them, so just use Open and Close.
The delay section tells the game how long to wait after the event occurs to run the output. In this case we want both to be zero, as we want the door to begin to open and close as soon as someone enters and exits the area respectively.
Lastly is the number of fire times. This is a feature you will seldom need to use, it tells the game how many times this output can fire before it stops working for the entire rest of the round. -1 just means it can run as many times as we want, and obviously we don't want our respawn door to stop working after so many uses, so leave this -1. Unless you have a good reason to change it, this should always be -1.
Filters
We now have a functional door, however there's two issues. Firstly, enemies are able to use this door, as the trigger accepts any players who touch it, so a blue player walking up to this spawn door would open it. Secondly, even if our door was only able to be opened by red players, there's nothing stopping blues from walking in when it is open.
To prevent enemies from opening the door, we'll use a filter. Create a point entity of type filter_activator_tfteam.
You'll see a few keyvalues that are basically self explanatory, so set the Team to RED in this case.
You will want to give filters descriptive names. You want your filters to be explanatory at a glance, for instance if I see a filter named "filter_red", does that mean it filters OUT reds, not allowing them, or it filters reds in, ONLY allowing them?
I would recommend something like filter_allow_red or filter_red_only for allowing reds, then filter_deny_red or filter_no_red for deny (you will most likely not be using the "deny red" type and instead be using an "allow blue" but if you do, make sure it's descriptive). In this case, let's name it filter_allow_red.
Unless the logic is specific to an area, you should generally centralize your logic entities in one location in the map. I like to put my logic entities near the center of the map, such as above the middle control point. If it's an asymmetrical map, it might be near the first or last point. But generally you want to have all your logic together, as it will make finding it for you (and others) easier, and you won't lose track of it. In the case of this map let's put the filter in the middle of the large room like so.

Now, within our door trigger, we can set the filter value to filter_allow_red. You will notice a dropdown, this shows all the filters you have on the map and is also why giving a descriptive name is so important, because finding it in this list will become trivial.

Respawn Room Visualizer (brush)
The next problem we have to deal with is not allowing enemy players into the spawn when the door is open.
Select the tools/nodraw texture, then create a brush entity the exact same size as the door. nodraw is a special texture that is invisible in game, the game knows not to even attempt to render any brush face that has nodraw on it. In our case, the barrier is largely invisible, so we want it to be nodraw to start off with.
However you will notice a problem. When you try to select the door or the brush entity, you'll have trouble selecting a specific one. In this screenshot I have the newly created nodraw brush selected, but you can't see it due to overlapping with the door.

There are two ways to reconcile this.
The first one is the easier one. Instead of making this new brush the exact same size as the door, extend it a bit into the spawn. You'll understand why once we define the entity itself but this extending into spawn is no problem.

Alternatively, you can keep it that size and use Hide to select it. I would recommend hiding most of the time, so go ahead and ctrl + z if you extended the brush.
The Uses of Hiding
Hide is a very powerful part of Hammer that allows you to temporarily hide objects. When an object is hidden, not only is it hidden in the editor, but it won't be compiled if you decide to compile while you have the entity hidden.
You can press h to hide the selected entity, u to unhide ALL entities, or ctrl + h to hide everything except the selected entity. When you are working on a small area, it can often be helpful to use ctrl + h to select only that area, so the rest of your 2D grid isn't cluttered with other geometry.
In this example I hid the main walls of our larger room so we can see what's going on inside the respawn room.

Unless you're intentionally trying to compile without a specific entity, you should get into the habit of compulsively pressing u before any compile so you don't accidentally compile your map with some of it missing. The above example wouldn't compile because it's missing walls.
In the case of our door here, there's a quick and clever way to only select one of the entities. Firstly, just click and try to select. IF the entity is already the one you wanted, just make the edits you need. IF it isn't, just press h to hide it, then select the other entity underneath that you actually need. This lets you keep the size of your brushes while making them still selectable. Generally it's better to just make sure your brushes aren't the same size as each other, but this is an option if you need two brushes at the same size.
In this example I hid the red door after selecting it and now I have free access to the newly created brush

Respawn Room Visualizer (entity)
Now that we have our nodraw func_detail, go ahead and convert it to a func_respawnroomvisualizer. This is a special entity that is only visible/solid to the enemy team. The team you select in the keyvalues is the team it belongs to, in this case the RED team. To them, this entity will be completely invisible and nonsolid and they can walk right through. Conversely, the BLU team will be able to see any non-nodraw texture on this, and it will be an impassible invisible wall to them.

You may recall that on most maps when walking up to an enemy respawn room, there is a red circle showing that you can't enter. This is a specific texture Valve uses for respawn rooms.
We could use the Apply Current Texture tool to set this texture across the entire brush, however we don't want to use the texture where it won't be seen. Therefore we need to use the regular Toggle Texture Application to apply it only to one face.
The Toggle Texture Application Tool
Select the Toggle Texture Application tool, which I'll refer to here on as the Texture Tool. You will notice if you click any face that your currently selected texture is updated to it, this is the color picking function. The right click will instead apply the current texture to any face you click. To demonstrate this, select the 3dskybox texture on the ceiling, then apply it to one of the walls. Then undo this by selecting one of the other walls and applying it back to that same wall you changed.

The current texture selection is what the texture tool will be when you first open it but it won't adhere to it. Luckily if we need to change on the fly, there is a Browse button on the texture tool that will open the texture browser. Select the overlays/no_entry in the browser, then use right click to apply it to the enemy facing side of the nodraw respawnroomvisualizer. Note that just like when selecting a brush, applying a texture also suffers from the same issue if your brush is flush with another brush. In this case though, merely clicking it and hoping for the best isn't a good outcome. You'll need to go back to the selection tool and use either h or ctrl+h to get the right brush selected. After that, re-open the texture tool (you may need to reselect the blocking texture) then right click the face you want to change.

You will notice that the texture looks off, it's too small and being repeated, it's also not centered. We want to change that so it's the correct size in the correct location.
Left click the texture, and you'll notice that in addition to selecting it, you'll have access to the settings for the texture at that particular face. We can go over advanced texturing later but for the time being, the easiest way to resolve this is to click Fit, then go to the x and y scales, and copy paste the larger of the two into the other. Lastly, press C in the Justify section to Center it. Click apply and you'll see the texture in the right location at the right size.

Our respawn room should be good to go, but let's give it a test before we make the blue one (don't worry, it will be faster than you think!).
Testing our Respawn Room
Compile and load into the map on RED team. Walk up to the door to make sure it opens and closes, check the respawn lockers to make sure they regenerate properly, change classes to make sure you're in a respawnroom, and make sure you can't build a teleporter on your side of the spawn door.
Next change to BLU team and walk up to the door to confirm it doesn't open.
You'll notice that our visualizer texture is Z-fighting (when two brushes are flush with each other and flicker) and so the door looks bad.

To fix this, go back into hammer and instead move the visualizer to be flush with the back side of the door. Unlike what I lead you to believe, Valve maps use this to only show that you can't go past when the door is open, so it shouldn't be visible if the door is closed.

Since we'll be duplicating spawn rooms for BLU side, let's completely finish off the RED side by going over lighting.
Base Map Lighting
Generally speaking there are three light entities you'll be interacting with, light_environment, light, and light_spot(?). For the purpose of this map we'll only be covering light_environment and light.
To start off with, how light works is that if a map has no light entities at all, it will be rendered in "fullbright." This means no lighting whatsoever, up until now we've been playing our map in fullbright. Adding even a single light entity will stop this and make the entire map need lighting, for example all rooms will become dark. Fullbright is not meant for release maps and is only a way for you to see your map prior to doing lighting.
Virtually every map will need a light_environment. Unless you have a totally indoors map like cp_junction, your map will have some sky that needs ambient light. light_environment generates ambient light from wherever you have skybox textures.
Lighting is in large part personal preference, and doing good lightning is hard. A later tutorial will be dedicated to that, but for right now we're going to just set our light_environment to use the same values 2fort uses.

Pitch however is a non-default value so we need to add it by disabling smart edit

Individual Lights
For our indoor lights, we'll keep it simple. Create a static prop on the ceiling with the <light prop?> model, align it, then create a point entity of type light. This entity just emits light from the location, though it's less of an entity and more of an indicator for VRAD (the light compiler). We'll just set them to these settings as a basic value, you can play around with it as you like. Move the light entity below the prop.
<pic of light>
Note that for the brightness, there are 4 values. The first 3 are the rgb values while the fourth is the brightness. In this case we'll just go with 250.
Getting good lightning takes trial and error and you may find some success examining valve maps to see how they do things (explored in the next part of this guide).
We want to move these lights around but it's a pain to have to select both each time we want to clone them. Instead, we can group them. Select both the light and the prop and click the group button at the top.
These two objects are now grouped in hammer. This has no effect in game, it's just for organization within the editor. You can now move them around together. You might notice you can't select an individual object anymore, but there's an easy way around that. The Selection Type has a Groups and Objects section. When Groups is on, whenever you click an object, if it's part of a group the whole group will be selected. Conversely if Objects is selected, groups are ignored completely. Note that Objects and Solids are different as if you have a single entity with multiple brush components (like our respawnroom), that is still one object, as opposed to these editor-only groups that we just demonstrated.
Use shift to create a few lights in our respawn room so that it won't be dark.
Fullbright
Compile and load into the map. You might notice nothing changed, but that's because of a cvar quirk with fullbright. If you load into a map that does not have any lighting, the mat_fullbright cvar is set to 1. If you swap maps to something else it stays, and then all other maps you play will be fullbright. You can confirm this by quickly doing a changelevel to a valve map. The fix to this is to simply reset fullbright by doing
Code: Select all
mat_fullbright 0Once you do, you should see your level lit up properly.
Duplicating Objects
Next up let's create the blue spawn room. It would be a pain to have to recreate everything we just did manually, so let's do some quick shortcuts to reduce the work.
On the opposite wall to the one you made your RED spawn room, go ahead and delete that wall. Then, go back to your respawnroom, and in the 2D grid, drag select the entire respawnroom itself as well as the wall.
Click on the selection until you've entered rotation mode, then move the pivot point to the middle of the large center room.
Hold shift, then rotate the room to the other side, and finally let go of shift. You'll see the entire respawn room has now been duplicated!
We will need to fix all the entities inside, however. See if you can figure out all the fixes on your own, they are listed below for you to spot check against.
► Show Spoiler
- Update the team keyvalue for all the spawn points
- Remove the blue spawnpoint in the middle of the map
- Create a BLU allow filter
- Update the team keyvalue for the respawnroom and respawnroomvisualizer
- Change the door trigger to use your BLU filter
- Change the texture on the door to use the BLU dev grid
- Rename the door so it's unique from the red door
- Update the door trigger to use the new door name
- Rename the respawn lockers
- Update the respawn locker triggers to use their new names
Lastly for this map, let's set this up with a gamemode. The easiest one will be koth, so we can go ahead and set it up.
Control Point Layout
Before we set up the gamemode logic let's create a zone for our control point. Place a prop_dynamic named point_prop with the model models/props_gameplay/cap_point_base.mdl right in the middle.
One problem with our current setup however is that it's not obvious where the capture zone of our point is due to our floor being a single texture.
We'll be creating some lines on the ground. There are a few ways you can go about this, such as creating very thin brushes and overlaying them, but for this guide we'll instead be cutting into the ground with the clipping tool.
As you may recall the clipping tool textures new faces it creates with whatever your current texture is. Use the texture tool to select the dev grid before we go ahead with this. The reason is that the clips we're about to make won't be visible unless you freecam into the ground, so we should be proactive. Once you have that selected, go ahead and make four cuts in the ground around your control point like so. Do not deselect the brushes at any point, just leave them selected - you'll see the clipping tool will make cuts along multiple brushes at once.
<3x3>
While this is technically fine, in practice you don't want to make square cut holes like this, as resizing the outer areas will introduce issues. Instead, we want to make sure our brushes are as large as they can be whenever possible.
To resolve this we are going to use the merge feature. There are two ways to merge, either with Ctrl + Shift + m or by going to Tools > Merge. Merging combines two solid brushes together. It can only <?> be used on world brushes, and any brushes you chose have to share dimensions along the merge line. For instance, below would not be able to be merged
<invalid merge?>
while the below would
<valid merge?>
You can merge more than one brush at once. To demonstrate this, go ahead and select 3 of the outer brushes we created with our cuts (ideally ones parallel to a spawn door) and then perform the merge. You'll see all the brushes get combined together. Go ahead and do this for the other side as well.
<pic>
In terms of alternate ways to have done this, you could have also deleted two of the three brushes and resized the remaining brush into the open space, or you could have done your cuts properly in the first place by instead only selecting the middle brush when making your second set of cuts.
Also worth noting, you can use the vertex tool to make your corners diagonal like so
<pic>
however I would not recommend this for floors, as floors will often need to get stretched and resized which becomes a pain to do when you set up the corners like this.
Once you're done, you are going to repeat the same process but this time only for the brush under the control point, except the cuts you make with the clipping tool will instead be near the edge of the brush.
Your final brush layout should look something like this once you're done clipping
Next up we want to use a texture to demonstrate where our capture area is. For this example we'll use the props/hazardstrip001a texture. Go ahead and texture the top part of your thin brush strips with it by using the texture tool. Remember, we don't want to use apply current texture, as unseen textures (such as the ones under the floor) should never be real textures, only dev/nodraw textures.
Control Point Logic
We are going to need a few logic entities in order to create our control point.
Firstly, we need a team_control_point_master point entity which you can place with your other map-wide logic. Name it something like master_control_point. This entity is in charge of all control points on the map, so you'll need one even if your map only has a single point. You only need one of these entities. <?default params>
Next we need a team_control_point point entity. Go ahead and name it something like control_point. If this were a 5cp or a/d map we'd give it a more descriptive name, but as we're making koth, this name will do fine.
Move the entity right to the middle of the control point, and set up the key values as shown below
Next we need the trigger which defines the area where you stand to capture the point. Go ahead and create a trigger that's at least 256 high, using the hazard lines as the boundary for it.
The trigger should be a trigger_capture_area entity. Set the key values as shown below, making sure that the Control Point key value is targeting your control point entity which should be named control_point as per the previous steps.
This trigger also needs two outputs which will change the skin of the control point. Models in source have a concept called skins, which allows them to change their look without needing to have entirely separate props which would be a pain to work with. In this case, the control point has a base skin, a red skin, and a blue skin. Set up the outputs as shown below.
<pic>
Note that while all props can be given a skin, you need a dynamic prop if you want to change the prop's skin during a round. Some static props like signs or trees will have alternate skins you can set at compile time, but this should only be used if you don't intend for it to be changed mid round.
King of the Hill Logic
We aren't done yet, we have a control point but there's no gamemode set, so the only thing you can do with it is just capture it back and forth - there's no timer or logic behind it other than the capturing.
Open up the outputs of our trigger_capture_area and add the two koth outputs shown below to set the koth clock to active on capture. <?default respawn wave time?>
Next create a tf_logic_koth entity. You can leave this untouched as the defaults will be fine, but you can go ahead and click the entity to see what those defaults are and change them if you wish.
Lastly we need a logic_auto. This is a useful entity for running things automatically when the game starts. Set the values to the below.
The Goal String is a value which utilizes a base TF2 translation file (in this case, #koth_setup_goal) to give players a HUD indication of what the goal is. Base gamemode all have their own goal strings already in the game. If you're making a custom gamemode without a goal string, you can write the goal here manually, but note it won't be translated.
The Respawn Wave time, as shown being set earlier, is how long the "respawn waves" are. In TF2, players respawn in waves, rather than everyone having individual spawn timers. When a player dies, a new respawn wave is set <fact check?> and anyone who dies prior to that wave will get a reduced respawn time, such that all these players respawn at the same time.
Generally speaking, respawn times are such that attackers have a shorter respawn time, while defenders have a longer respawn time. This is how it's set in all valve maps as well as most community maps. This is because attackers have to continually push against fortified defenses, and if both teams respawned with the same times, it'd give entrenched defenders an unfair advantage that would make breaking through defenses harder, so the reduced respawn times give the attackers an edge. This edge does not need to be very substantial, only 2-3 seconds on koth <fact check?> is sufficient most of the time. Larger differences might be important for other gamemodes.
Testing our KOTH Map
Now that we have our map logic ready, let's go ahead and compile and test it out.
If everything was set up correctly, you should be able to capture the point as one team, swap to the other team, and capture it back, while seeing the timer tick down. You can also use this opportunity to check the respawn wave times to confirm they're being set correctly.
If your map is functional at this point, you have successfully completed the beginner guide to making a TF2 map. You, technically speaking, have all the tools you need to make a basic map. Of course it probably won't be a very good map, which is what the guides after this will help rectify, but you should now know how to use the editor and what it takes to make a basic map.
The last thing you'll want to do is go to File > Save As and save your map as koth_first_map.vmf. Your map should have the gamemode name saved up front so the game can determine what the gamemode is on loading screens and in the server browser, as well as for players to know what the gamemode it as a glance of the map name. Secondarily, this will also back up your first map if you want to come back to it later and do your own customizations. We'll be using this koth_first_map.vmf variant for the guide after this one.
The next guide will cover making a more interesting map layout with the basics of level design.
