Tutorial: Retina Scanners and Other NPC-Only Locked Doors Last edited 6 months ago2023-12-19 14:26:22 UTC

Throughout the singleplayer campaigns of Half-Life and its expansions you encounter locked doors that can only be opened by leading a friendly NPC up to a retina scanner or keypad. In this guide we will make our own.

How Do They Work

A beginner mapper might make the naïve assumption these work by using a NPC-only button. That's understandable. It looks and sounds like a button to the player interacting with it.
But it's actually a trick.

The key element is actually a scripted_sequence that grabs a NPC that gets within a certain radius, waits for them to walk up to it and perform a retina scan or button pressing sequence, and then fires its target that ultimately unlocks and/or opens the door.
Most of the time the "button" you see is just a func_wall that gets toggled by a multi_manager, along with any sounds or other effects. A real func_button exists, but it's invisible and fires its own multi_manager to toggle the func_wall and play some "access denied" sound or sentence.
User posted image

A Basic Setup

The Scanner

For a very simple retina scanner, start by creating the scanner's brush, either by using a prefab or building it from scratch (the retina scanners from Half-Life uses the textures +AGENERIC_113 for the faceplate and C1A1_TRIM2 for the borders) and tie it to func_wall and give it a targetname of the_scanner.

The Button

Now create a thin (e.g. 2 units thick) func_button covered entirely in NULL texture and place it in front of the retina scanner.
Make sure to set the Don't move spawnflag (1). For the keyvalues use these values:
Sounds (sounds) - Access Granted (3)
Delay before reset (delay) - 3
Target (target) - denied_mm
Passable (zhlt_noclip) - Yes (1) (might need to be added with SmartEdit off)
User posted image
Create an ambient_generic and set the Small Radius (2), Start Silent (16) and Not Toggled (32) spawnflags. Use these keyvalues:
Name (targetname) - denied_sentence
WAV Name (message) - !na0
Volume (health) - 5
Finally we'll create a multi_manager with these keyvalues added with SmartEdit off:
Name (targetname) - denied_mm
the_scanner - 0
the_scanner - 2
denied_sentence - 2
Don't worry about the "#1" appended to the second /the_scanner/ key. It's ignored by the game and only used by the multi_manager to keep the key names unique.Don't worry about the "#1" appended to the second the_scanner key. It's ignored by the game and only used by the multi_manager to keep the key names unique.
This is the button the player will be interacting with. All it does is toggle the retina scanner's texture on and off again after two seconds before sounding an "access denied" sentence.

The Sequence

Now onto the actual magic of the setup.

Create a scripted_sequence with the No Interruptions (32) spawnflag set and give it these keyvalues:
Target (target) - granted_mm
Target Monster (m_iszEntity) - monster_scientist
Action Animation (m_iszPlay) - retina
Search Radius (m_flRadius) - 100
Move to Position (m_fMoveTo) - Walk (1)
Make sure the Yaw (the compass in the top-right in the entity properties, alternatively the second value in Pitch Yaw Roll (angles)) is pointing towards the retina scanner.

Add another ambient_generic with the Small Radius (2), Start Silent (16) and Not Toggled (32) spawnflags and for the keyvalues use these:
Name (targetname) - scanner_blip_granted
WAV Name (message) - /buttons/button7.wav/
Volume (health) - 7
To wrap this all up create a multi_manager with these keyvalues added with SmartEdit off:
Name (targetname) - granted_mm
the_scanner - 0
scanner_blip_granted - 0
the_scanner - 2
the_door - 2
User posted image

The Subjects

Now we need a monster_scientist and a func_door.

Leave the scientist's keyvalues and spawnflags as-is and place him some distance away from the scripted_sequence (more than 100 units away).
The door should have these keyvalues:
Name (targetname) - the_door
Delay before close (wait) - -1
Adjust other keyvalue such as Move Sound, Speed and Pitch Yaw Roll to your liking.
A finished simple setupA finished simple setup

Try It Out!

Go ahead and compile this and run it in-game.

The door(s) will start out locked and the retina scanner will let the player know they have no access. Having the scientist follow you near enough to the retina scanner will make him start walking up to it and perform his retina scanning sequence. However, nothing happens until after the sequence finishes. The door(s) opens nonetheless after the scanner flashes for a couple of seconds and a granted sound is made.

This is because scripted_sequences don't fire their targets until after the Action Animation finishes. If we want to time the retina scanner flashing and any sounds or other effects along with the retina scanning sequence, that needs to be called before the scripted_sequence starts.

Making It More Complex

Chained scripted_sequences

To fire something just as the retina scanning scripted_sequence starts we can split our scripted_sequence into two: That way our multi_manager is called after the scientist finishes walking up to the retina scanner, but before playing the scanning sequence.
User posted image
Start by duplicating our first scripted_sequence and move it up by 4-8 units or so.
Keep the No Interruptions spawnflag on both and give them these keyvalues:
scripted_sequence 1
Target (target) - granted_mm
Target Monster (m_iszEntity) - monster_scientist
Search Radius (m_flRadius) - 100
Move to Position (m_fMoveTo) - Walk (1)
scripted_sequence 2 (retina_seq)
Name (targetname) - retina_seq
Target Monster (m_iszEntity) - monster_scientist
Action Animation (m_iszPlay) - retina
Search Radius (m_flRadius) - 100
Move to Position (m_fMoveTo) - No (0)
Then we need to change our granted_mm to have these keyvalues:
Name (targetname) - granted_mm
retina_seq - 0
the_scanner - 0
the_scanner - 5
scanner_blip_granted - 1
the_door - 5
User posted image

The Blips

To make it more similar to retina scanners from the singleplayer campaign we can have it make a rapid series of "blip" noises.
Add a new ambient_generic with the spawnflags Small Radius (2), Start Silent (16) and Not Toggled (32) and these keyvalues:
Name (targetname) - scanner_blip
WAV Name (message) - /buttons/blip1.wav/
Volume (health) - 5
Pitch (pitch) - 200
Now we need a multi_manager to play these blips in succession and at an increasing rate:
Name (targetname) - granted_blips_mm
scanner_blip - 0
scanner_blip - 0.3
scanner_blip - 0.6
scanner_blip - 0.9
scanner_blip - 1.1
scanner_blip - 1.3
scanner_blip - 1.5
scanner_blip - 1.7
scanner_blip - 1.9
scanner_blip - 2.1
scanner_blip - 2.3
scanner_blip - 2.4
scanner_blip - 2.5
scanner_blip - 2.6
scanner_blip - 2.7
scanner_blip - 2.8
scanner_blip - 2.9
scanner_blip - 3.0
scanner_blip_granted - 3.5
The first 4 play at a rate of once per 0.3 seconds, the next 7 at 0.2, and the remaining at a rate of 0.1, before finally playing our granted sound.

Try It Out Again!

Compile and run the map again. You should now have the retina scanner flashing and playing blips while the scientist is performing the scanning sequence, similar to the singleplayer campaigns.

Example maps

Loading embedded content: Vault Item #6826


You must log in to post a comment. You can login or register a new account.