Mapping & Hammer

Building TTT Maps: Entities, Spawns and Testing in GMod

Building TTT maps: which spawns and weapons TTT picks up automatically, what each ttt_ entity does, how to load ttt.fgd in Hammer and test rounds alone.

Technically, a map for Trouble in Terrorist Town only needs enough info_player_deathmatch spawn points plus weapons and ammo. Everything else is optional: TTT ships its own FGD file with ttt_ entities that let you build traitor buttons, role checks, traps with correct kill attribution and round events. Two quirks matter: TTT resets the map completely before every round, and during the preparation phase every player counts as innocent.

What TTT takes from a map automatically

Spawns. Besides info_player_deathmatch, TTT uses info_player_terrorist, info_player_counterterrorist, info_player_combine, info_player_rebel, info_player_axis, info_player_allies, info_player_teamspawn and gmod_player_start. The code only falls back to info_player_start when none of these exist, and the TTT documentation advises against it. The spawn classes of other gamemodes are covered in spawn points and gamemode entities.

Weapons and ammo. When it prepares a round, TTT replaces the weapon and item entities from Half-Life 2 with its own. An excerpt from the table in the TTT code:

Entity in the mapBecomes in TTT
weapon_smg1weapon_zm_mac10
weapon_shotgunweapon_zm_shotgun
item_healthkitweapon_zm_shotgun

The stock maps from Counter-Strike: Source usually contain no weapon entities. If TTT finds no spawnable weapon and no info_player_deathmatch, but does find an info_player_counterterrorist, it scatters random weapons at the spawn points and hostage entities.

Reset. Before every round TTT calls game.CleanUpMap. Doors, buttons, broken props and all logic entities are then back in their initial state. So build nothing that has to remember state across rounds.

Loading the TTT entities in Hammer

ttt.fgd is located in garrysmod/gamemodes/terrortown/. The mapexamples subfolder holds three example maps: ttt_traitorcheck.vmf, ttt_traps.vmf and ttt_weaponcheck.vmf. In Hammer, open Tools > Options, select the Game Configurations tab and add the file under "Game Data files" with Add.

Hammer then offers info_player_deathmatch (this class is missing from garrysmod.fgd), the weapons (weapon_zm_*, weapon_ttt_*), the ammo (item_*_ttt) and the ttt_ entities.

TTT is built on the content of Counter-Strike: Source, and since the update of July 2025 GMod itself ships most CS:S and Half-Life 2 episode content, without maps, music and voice-over. You can therefore use it in a TTT map. What exactly is included is covered in CS:S and HL2 content in GMod maps.

Placing spawns, weapons and ammo

  • Number of spawns. According to the documentation, TTT is intended for 16 to 18 players, and many servers allow more. For placement scripts it recommends at least 32 spawns. If no spawn is free, TTT creates makeshift spawns 36 units next to an existing one and writes TTT WARNING: Map has too few spawn points to the console. If that fails as well, a spawn is forced and whoever is standing there dies. So leave open floor around every spawn.
  • ttt_random_weapon. On spawn, it turns into a random weapon from all weapons registered on the server as automatically spawnable. That includes weapons from addons, which fixed weapon_zm_* entities cannot do. The spawnflags (Sub-Machine Guns, Assault Rifles, Sniper Rifles, Shotguns and more) narrow the selection. auto_ammo adds the given number of matching ammo boxes. Leave some room above the entity, because the boxes are created there and drop down. ttt_random_ammo likewise turns into a random ammo box.
  • Placement scripts. Alternatively, TTT reads a text file maps/<mapname>_ttt.txt (or the same file in data_static/). It is created with the TTT Weapon Placer addon in Sandbox and mainly meant for maps not built for TTT. Important: if such a script exists, TTT removes the weapons and ammo placed in the map (everything automatically spawnable plus the Half-Life 2 classes it would otherwise replace) and loads the script's contents instead. With replacespawns 1 it replaces the spawns too. You can switch this off with ttt_use_weapon_spawn_scripts 0.

A line consists of class, position and angles, separated by tabs:

setting:	replacespawns 1
ttt_playerspawn	-203.8 -1811.8 -209.6	0 36 0
ttt_random_weapon	-1107.0 2109.9 194.0	1.8 132.9 -92.7	auto_ammo 2

The TTT entities at a glance

EntityPurposeKey keyvalues, inputs and outputs
ttt_map_settingsSettings and round eventscbar_doors, cbar_buttons, cbar_other, plymodel, propspec_allow_named; outputs RoundPreparation, RoundStart, RoundEnd
ttt_traitor_buttonButton that only traitors see on their HUD and press from a distancedescription, wait, RemoveOnPress, UsableRange; inputs Lock, Unlock; output OnPressed
ttt_logic_roleChecks the role of the !activatorRole; input TestActivator; outputs OnPass, OnFail
ttt_filter_roleFilter for triggers by roleRole
ttt_traitor_checkBrush that counts living traitors inside its volumeInput CheckForTraitor; output TraitorsFound
ttt_weapon_checkBrush that checks the weapons of players inside its volumeInputs CheckForType, CheckForClass; output WeaponsFound
ttt_damageownerAttributes the damage of an entity to a playerdamager, killname; inputs SetActivatorAsDamageOwner, ClearDamageOwner
ttt_winEnds the roundInputs TraitorWin, InnocentWin
ttt_game_textMessage in the TTT message area at the top rightreceive, message, color; input Display
ttt_credit_adjustTakes TTT credits from the !activator or gives them somecredits; input TakeCredits; outputs OnSuccess, OnFail
ttt_spectator_spawnDestination point for spectatorsAngles of the entity

Four things the table does not show:

  • The crowbar opens named doors. By default a crowbar hit unlocks and opens every func_door, func_door_rotating and prop_door_rotating, unlocks and presses every func_button and opens every func_movelinear, as long as the entity has a name. If a door should only open through your logic, set the matching cbar_ option in ttt_map_settings to No.
  • During the preparation phase everyone is innocent. ttt_logic_role and ttt_filter_role then treat all players as innocent.
  • ttt_traitor_check is outdated. The FGD tags the class with editor/obsolete.vmt, and the documentation recommends ttt_logic_role with a normal trigger instead.
  • RoundEnd passes the outcome as a parameter: 2 for traitors, 3 for innocents, 4 for the time limit.

Wiring outputs to inputs is explained in Hammer inputs and outputs. info_manipulate in the TTT folder is only a placeholder for old Zombie Master maps and turns into a ttt_traitor_button in game.

Layout: advice, not rules

This section is design experience, not documented requirements. Only the ratios are fixed: with the default values, 25 percent of the players are traitors (rounded down, at least one), and detectives appear from 8 players upwards. With 16 players that means 4 traitors and 2 detectives.

  • Mix your sight lines. Traitors need unobserved moments, innocents need spots with an overview. A map made only of long corridors serves one side.
  • Places for bodies. A body that is found provides clues. Niches away from the main routes make hiding possible, but they should stay reachable.
  • Fair traps. A trap is fair when attentive players can recognise or avoid it. Connect it to a ttt_damageowner, otherwise the kill is credited to no player, neither for score and karma nor in the round report. Use wait or RemoveOnPress to limit how often it fires.
  • Traitor testers. They are controversial in the community because they can replace deduction with queueing. Common compromises are testers that work slowly, check only one person or can be sabotaged by traitors.

The TTT code does not use a navmesh. You only need one if servers run bots or Nextbots, see navmesh and AI nodes.

Testing with the round system

  1. Put the BSP into garrysmod/maps, select TTT as the gamemode and start the map. TTT waits for players at first.
  2. Set ttt_minimum_players 1 and ttt_debug_preventwin 1. Entities are only replaced and weapons only placed once TTT prepares the first round.
  3. Enable sv_cheats 1 and switch roles with ttt_force_traitor, ttt_force_detective and ttt_force_terror.
  4. Start a new round with ttt_roundrestart and check that everything resets.
  5. To test ttt_win, set ttt_debug_preventwin back to 0, otherwise TTT ignores the win.

Spawn count, weapon distribution and traps only prove themselves on a full server. How to organise that is covered in playtesting a GMod map with players.

FAQ

Does the name of a TTT map have to start with ttt_?

Technically no, TTT runs on any map. But TTT's gamemode file contains the pattern ^ttt_, which Garry's Mod uses to sort maps under the gamemode in the map selector.

Why are the weapons I placed missing from my map?

Check whether a file <mapname>_ttt.txt exists. TTT ships such scripts for several CS:S maps, and a script replaces the weapons placed in the map.

How far does a ttt_traitor_button reach?

1024 units by default, measured between the button and the player. Change the value with UsableRange. Innocents do not see the button at all.