Mapping & Hammer

Hammer Inputs and Outputs: Wiring a Button to a Door

Inputs and outputs in Hammer explained: the fields of the Outputs tab, a button and door example, !activator, logic_relay and debugging with ent_fire.

In Hammer you connect entities through outputs and inputs: an output of one entity fires an input of another, and the target is found by its name (targetname). For a button that opens a door, you give the door a name and add the output OnPressed with the door's input Open to the func_button. A connection like this usually breaks because of a mistyped or duplicate name, a target that has been removed, or two outputs that arrive at the same moment.

How outputs and inputs fit together

An output is an event an entity reports: a button was pressed, a door is fully open, someone entered a trigger. An input is a command an entity accepts, such as Open, Close or Kill. Which outputs and inputs a class has is defined in the FGD.

Every fired output is placed in an event queue inside the engine and delivered after the delay you set. Only at that moment does the engine look up the target by name. Two pieces of information travel along: the activator, usually the entity that started the chain (for a button, the player), and the caller, the entity whose output is firing.

You set the name in the Name field of the Object Properties (Alt+Enter). An entity without a name can send outputs, but can only be targeted through its classname or a special target such as !activator. The basics of the editor are covered in getting started with the Hammer editor.

The fields of the Outputs tab

On the Outputs tab of the Object Properties you create a connection with Add.... In the Hammer that ships with GMod, the edit fields and the columns of the list are labelled slightly differently:

FieldColumnMeaning
My output namedMy OutputThe event of this entity that triggers the connection
Targets entities namedTarget EntityName of the target, alternatively a classname, wildcard or special target
Via this inputTarget InputThe command the target carries out
With a parameter override ofParameterValue for the input, if it expects one
After a delay in seconds ofDelayWaiting time between the event and delivery
Fire once onlyOnceThe connection is deleted after it has fired once

Hammer++ replaces the checkbox with the field Limit to this many fires ( -1 = infinite ) and the column "Refires". The Inputs tab shows the opposite direction, meaning all connections that point at this entity. Mark jumps to the other end.

Example: a button opens a door and closes it again

  1. Build the door as a brush, press Ctrl+T and choose func_door. Name it door_1.
  2. Set Move Direction (Pitch Yaw Roll) to the opening direction and Delay Before Reset (-1 stay) to -1. The door then stays open.
  3. On the Flags tab, untick Touch Opens. It is ticked by default and would open the door on touch.
  4. Build the button as a brush and turn it into a func_button. The Use Activates flag is already set. With Delay Before Reset (-1 stay) set to 5, it cannot be pressed again for at least five seconds.
  5. On the button's Outputs tab, add two connections:
My Output   Target Entity   Target Input   Parameter   Delay
OnPressed   door_1          Open                       0.00
OnPressed   door_1          Close                      5.00

The door opens immediately and closes five seconds after the press. It works without the second connection too: a door with Delay Before Reset at 5 closes by itself. How to call a lift with the same pattern is covered in the article on elevators and trains.

Special targets and logic building blocks

Instead of a name, the target field can hold a special target:

TargetMeaning
!activatorThe entity that started the chain, such as the player at the button
!callerThe entity whose output is firing
!selfAs a target the same as !caller, as a parameter the entity receiving the input
!playerThe player, in multiplayer the first one who joined the server
!pickerThe entity under the crosshair, meant for debugging

On a server, !player is therefore almost never right. Use !activator for the player who triggered the chain, or the classname player for everyone. Wildcards only work at the end: door_* matches every name that starts with door_. A pattern such as *_door does not work, because the engine ignores everything after the *. A classname such as func_door is a valid target too, unless an entity carries exactly that text as its name.

A handful of logic entities turn this into larger circuits:

  • logic_relay bundles several outputs under one name: input Trigger, output OnTrigger. Disable breaks the chain, CancelPending discards the relay's events that are still waiting. While delayed outputs are pending it cannot be triggered again, unless the Allow fast retrigger flag is set.
  • logic_timer fires OnTimer at the pace of its Refire Interval.
  • math_counter counts with Add and Subtract and fires OnHitMax or OnHitMin once a limit is reached.
  • trigger_multiple is a volume with OnStartTouch, OnEndTouch and OnTrigger. The flags and Filter Name with a filter_activator_name or filter_activator_class define who may trigger it.

Debugging in game

Before compiling, Map > Check for Problems (Alt+P) lists entities with invalid connections. In game, these console commands help:

developer 2
ent_messages_draw 1
ent_fire door_1 Open
ent_fire !picker Kill
  • developer 2 prints every output and every input to the console. dumpeventqueue lists the events still waiting for their delay.
  • ent_messages_draw 1 shows the same messages in the 3D world at the entities.
  • ent_fire <target> <input> [parameter] [delay] fires an input by hand. This lets you test the target independently of whatever triggers it.

Test in single player or as the host, because according to the Valve wiki a client connected to a server cannot use ent_fire. If the console asks for cheats, enter sv_cheats 1 first. With developer 2, the console lines follow the pattern below. The block is assembled from the message formats in GMod's server.dll, with the names from the example and an invented time. It is not a recording of a real session:

(12.50) output: (func_button,button_1) -> (door_1,Open)()
(12.50) input button_1: door_1.Open()
unhandled input: (Open) -> (door_2), from (func_button,button_1); target entity not found

The first line is the firing output, the second its delivery. The third is the one to look for: it appears when no entity carries the target name at the moment of delivery, in this illustration door_2.

Typical mistakes

  • Name missing or mistyped: Hammer shows the target in red, and "Check for Problems" reports the connection. Do not use "Fix" there blindly: according to the error text, Hammer deletes the bad connections instead of repairing them. Wildcards and classnames also appear in red although they work in game.
  • Name used twice: Hammer shows the target in bold. The input goes to every entity with that name. That is intended for two door leaves, not for a copied door in the next room.
  • Target removed: Kill deletes an entity together with its children in the parent hierarchy. Delayed outputs that arrive afterwards go nowhere, and the removed entity fires no new outputs. The same happens with !activator if the player leaves the server first.
  • Timing races: Two outputs with the same delay arrive in the same tick. Do not rely on their order. If B depends on A, give B a small delay. The Valve wiki uses at least 0.02 seconds in such a case.

Outputs can also trigger a lua_run, which then executes Lua code. The Map Scanner finds risky entities of this kind in a BSP. More checks are listed in the article on checking a BSP before release.

FAQ

Can one output address several entities at once?

Yes. The input goes to every entity the target matches: a shared name, a wildcard such as door_* or a classname.

What is the difference between OnPressed and OnIn on a func_button?

OnPressed fires as soon as the button is pressed. OnIn only fires once it has reached its pressed end position, and OnOut when it is back in its starting position.

Can I change outputs while the game is running?

Yes, with the AddOutput input. The format is <output> <target>:<input>:<parameter>:<delay>:<max times to fire>. The FGD calls it "very dangerous, use with care", and circuits that rewire themselves in game are hard to follow later.