Half-Life singleplayer uses airlocks a few times. You open the door, go into the airlock room and press the button. Then the door behind you locks and the door in front of you opens. This is easy enough to make, when it is just one player. It becomes more complex when you have to consider other players who can also use the buttons in and outside the airlock while others are inside the airlock.
One crucial part is that you need control over whether a door closes or opens. Ironicly enough, the
func_door entity can't do this. It only supports TOGGLE mode. This means when triggered, it will close when it's currently open OR open when it's currently closed. There is no Only Open or Only Close option here.
The only way to have fine control over an entity is to use a
trigger_relay, because it can be set to send an OFF or ON signal. There are only a few entities that support this. One of them is
func_plat. It's a movable platform that we can also use as a door!
The Setup
First, create 3 rooms separated by 2 doors. Each room needs a
func_button, 3 in total. Put your
info_player_start on either side of the airlock. We'll set up the system that it can be approached from both sides and still work. For this, both doors will start closed.
The Doors
As mentioned, turn the doors into
func_plat. Give the door a name (door1) and set up the direction. For
func_plat you'll have to set the travel distance. My door is 96 units high and should travel UP. I want it to have a lip of 4, so I'm setting it to -92. Set up the other door in the same fashion but with a different name (door2).
Create 4
trigger_relay entities:
- name : door1_open
- target: door1
- trigger state: ON
- name : door1_close
- target: door1
- trigger state: OFF
- name : door2_open
- target: door2
- trigger state: ON
- name : door2_close
- target: door2
- trigger state: OFF
We're using these to have fine control over the doors.
We'll set up the
func_button next to door1 first:
- target: door1_mm
- delay before reset: 3
Put a
multi_manager there with the following values:
- name: door1_mm
- 'door1_open' '1'
- 'door2_close' '0'
- 'airlock_mode1' '0'
Then next to door2:
func_button:
- target: door2_mm
- delay before reset: 3
multi_manager:
- name: door2_mm
- 'door2_open' '1'
- 'door1_close' '0'
- 'airlock_mode2' '0'
The Airlock
You've noticed that the
multi_managers trigger an 'airlock_mode'. This is something we'll have to setup next to the button inside the airlock. This will determine if we close door1 first and then open door2 or the other way around: close door2 first, then open door1. It will depend from which way we entered the airlock.
Let's set up the button inside the airlock.
func_button:
- name: airlock_button
- delay before reset: 3
Notice how this button currently has no target. We'll need to set up a dynamic target system with two
trigger_changetarget entities and two
multi_managers.
trigger_changetarget:
- name: airlock_mode1
- target: airlock_button
- new target: enter1_exit2
trigger_changetarget:
- name: airlock_mode2
- target: airlock_button
- new target: enter2_exit1
multi_manager:
- name: enter1_exit2
- 'door1_close' '0'
- door2_open '2'
- 'airlock_mode2' '2'
multi_manager:
- name: enter2_exit1
- 'door2_close' '0'
- door1_open '2'
- 'airlock_mode1' '2'
With this system, the airlock button will be set in the right mode depending on if you've entered from door1 or door2 first. After that it will toggle between both modes after each use.
The Problem
func_plat has served us greatly but it has one major flaw: it only deals 1 damage on blocked. This way players can cheat the system and keep both doors opened. The system will reset itself once a button has been used, so this can be a minor issue. However, if you map relies on those doors staying closed, we'll have to get creative.
The only entity that supports ON/OFF and deals damage is the
env_beam (or
env_laser). Put 2
info_targets between the door frame and name them 'beam1_start' and 'beam1_end'.
Now set up an
env_beam. These settings will make it invisible and kill a player on touch.
- name: beam1
- start entity: beam1_start
- end entity: beam1_end
- Brightness : 0
- Beam Color: 0 0 0
- Life: 0
- Damage/Sec: 9999
We want the beam to turn ON once door1 closes and turn OFF when door1 opens. The
env_beam starts OFF by default, so we'll have to create new
trigger_relays and swap the trigger states:
trigger_relay:
- name: door1_close
- target: beam1
- trigger state: ON
- name: door1_open
- target: beam1
- trigger state: OFF
You can set up another
env_beam for door2 in the same fashion. This should now fix our issue with players blocking the doors.
The Timings
If your doors are larger or faster/slower be certain to tweak the timings or the delays. My
func_buttons all have a delay of 3 because the
multi_mangers trigger everything within 2 seconds. The doors also take just 1 second to close/open. If you use slow doors, you might also consider setting a small delay to the
env_beam being set to ON.
IMHO, simpler option:
Your setup works well for singleplayer but not for multiplayer. The button for door1 and door2 can be pressed by seperate players, which then opens both doors. Now that both are open and func_door can only TOGGLE, your airlock is broken forever. You would have to create a eleborate system of multisources to lock the buttons to prevent this. Even then, a player can block the door by crouching under it and the game would never know that the door is now not closed. Which again breaks the entire system.