Using Hammer Entity I/O to Trigger Map Events in Source Engine
Learn how to fire doors, sounds, and lights from a simple button in Hammer without writing code, and see the limits of this approach.
06 Apr 2026, 12:52 UTC

Problem and Takeaway
You need a button to open a door and play a sound when pressed, but you don't want to edit C++ code. The fastest way to get this working inside a Source map is to use Hammer's built‑in entity output and input system.
This approach lets you fire gameplay events directly from the editor, keeping iteration fast and avoiding any compilation step for the map itself.
How Entity I/O Works
In Hammer an entity output is a trigger that fires when a specific event occurs, such as a player pressing a button. The corresponding entity input is the action the target entity will perform, like Open for a door. You connect them in the entity’s Outputs tab.
Commonly used entities for simple events include:
func_button– fires an output when pressed.func_door– accepts inputs such asOpenorClose.ambient_generic– plays a sound when given aPlaySoundinput.
Outputs fire instantly when the event happens; there is no need for a script or a timer. The connection is purely data‑driven, so you can wire many entities together without writing any code.
Worked Example: Button → Door + Sound
- Open your map in Hammer for the target Source game (e.g., Half‑Life 2, CS:S, TF2).
- Select
func_buttonfrom the entity toolbox and place it where the player will interact. - In the Object Properties dialog, go to the Outputs tab. Click Add and set:
- Output:
OnPressed(the default for a button). - Target:
func_door(the door entity you will add next). - Input:
Open. - Delay:
0.0(instant). - Only fire once:
No(so the door can be reopened). - Add a second output line for sound: Output
OnPressed, Targetambient_generic, InputPlaySound, Parameter the path to your wav file (e.g.,sound/vehicles/engine_start.wav), Delay0.0, Only fire onceNo. - Compile the map (right‑click → Compile → Run Map) and start a game with
developer 1in the console. - Press the button in‑game. The door should slide open and the sound should play.
Verification and Risks
To confirm the connection works, watch the console for messages like ent_fire func_button OnPressed and ent_fire func_door Open. If the door does not move, double‑check that the input name matches the door’s defined inputs (see the game’s FGD).
Key checks:
- Door animation plays as expected.
- Sound is audible and positioned correctly.
- No “entity not found” errors in the console.
Potential risks include:
- Multiple outputs firing on the same event may execute in an undefined order.
- Changes to the map require a full recompile, which can be slower than hot‑reloading code.
- Server‑side only outputs will not be visible to clients unless a client‑visible entity or networked state is used.
Trade‑offs and Limitations
Entity I/O excels for quick, map‑local interactions, but it has clear limits:
- Complex conditional logic quickly becomes hard to read; chaining many outputs can be error‑prone.
- Debugging is limited to console logs; there are no breakpoints or step‑through debugging.
- Input/output names differ between Source branches (Half‑Life 2, CS:S, TF2, etc.), so a feature that works in one game may be missing in another.
- Purely server‑side events may not propagate to clients unless you use a client‑visible entity or set the appropriate network flags.
For more intricate sequencing, insert a logic_relay between the button and the door. The relay’s OnTrigger output can fire multiple targets in a deterministic order, avoiding the randomness of direct connections.
When to Prefer Code Over I/O
If your event needs save/load robustness, unit testing, or precise sequencing, writing a small C++ or scripted component is safer. For simple map‑only triggers—doors, lights, one‑off sounds, or round‑state changes—entity I/O remains the most efficient tool.
Actionable Checklist
- Open the target map in Hammer for the exact Source game you will ship.
- Place the required entities (button, door, sound) and verify their input names in the game’s FGD.
- Wire the button’s
OnPressedoutput to the door’sOpeninput and the ambient_generic’sPlaySoundinput. - Compile and run the map with
developer 1; press the button and confirm visual and audio feedback. - Test the same setup in a different Source branch or mod to ensure the inputs exist.
- If sequencing is needed, insert a
logic_relaybetween the button and the door to centralize firing. - Consider running the map on both a listen server and a dedicated server to verify that client‑visible effects appear as intended.
With this workflow you can prototype interactive map elements in minutes, then decide whether a code change is warranted for production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.