Two-stop elevators: Difference between revisions
No edit summary |
No edit summary |
||
(24 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
{{cleanup|type=tutorial}} | |||
Illustrated in this project: | |||
# A simple 4 floor elevator. | |||
This is due to the multiplayer network physics which are optimized for | # More advanced version of the same. | ||
Always test | # Advanced effect uses through [[env_sprite]], [[func_brush]], [[func_button]], [[func_tracktrain]], [[logic_relay]], [[path_track]], [[prop_dynamic]] and [[trigger_multiple]] entities. | ||
# Demo of [[func_movelinear]] used for a similar effect. | |||
# Elevator has a button for each floor. | |||
# Each floor has a functional door and buttons. | |||
{{note|''It is not wise to use elevators and lifts in any of the multiplayer Source games. This is due to the multiplayer network physics which are optimized for online play. Always test elevators and lifts with <code>Developer 1</code> enabled.''}} | |||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
(Visible below, next to the [[info_player_start]] entity, in the images of the elevator interior.) | |||
OnMapSpawn, crate_lift, Open, 0.0 | |||
The entities used in this article are brush-based (the func_tracktrain and the func_movelinear.) | |||
The one in this project uses two Outputs back to itself: | |||
''OnFullyOpen, crate_lift, Close, 3.0'' | |||
''OnFullyClosed, crate_lift, Open, 3.0'' | |||
...and a [[logic_auto]] to open it when the map starts: | |||
''OnMapSpawn, crate_lift, Open, 0.0'' | |||
After its initial opening the func_movelinear will trigger itself. | After its initial opening the func_movelinear will trigger itself. | ||
func_movelinear can easily be controlled with buttons and triggers. | |||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
One way to make elevators in HL2 is with a func_tracktrain. | |||
Some might say that it is very difficult to get things working properly, but these declarations can be dismissed if the correct procedure is used. | |||
One such trick is the use of a one-time-only path_track to spawn the | One such trick is the use of a one-time-only path_track to spawn the elevator. | ||
It is never used again after that. | It is never used again after that. | ||
In the case of this 4 floor | In the case of this 4 floor elevator another path_track is in the same general area as the first and it will be used instead each time the elevator returns to floor 1. | ||
There are three adjustments | There are three adjustments that will need to be made once the elevator is working. | ||
# The position of the first path_track. | |||
# The position of the substitute path_track that will replace it. | |||
# The func_tracktrain’s Height above the track property. | |||
By tweaking these three objects | By tweaking these three objects one can get the elevator to start and stop exactly where desired. | ||
Keep in mind func_tracktrain entities must be created facing East, or to the right in the Top 2D viewport. | Keep in mind func_tracktrain entities must be created facing East, or to the right in the Top 2D viewport. | ||
But which way is east, exactly? | |||
East is the same direction as the direction right in hammer's top view. | |||
-t--- | |||
Notice in the image below how the front of the elevator is facing east, or right. | |||
[[File:WiseElevator01-1-.jpg|thumb|left|400px]] | |||
{{clr}} | |||
Also, the func_tracktrain doesn’t have to be built in place. | |||
It will spawn in position at the First Stop Target | It will spawn in position at the ''First Stop Target'' specified in its properties. | ||
In this project the elevator, func_tracktrain, has as its ''First Stop Target'' ''path_track_01'' and the flags ''Fire once'' and ''Teleport to THIS path track'' have been checked for the path_track. | |||
It will only be used once, after that ''path_track_01a'' will be the first path_track. | |||
---- | |||
Notice their position in this image | Notice their position in this image: | ||
[[File:WiseElevator02-1-.jpg|thumb|left|400px]] | |||
{{clr}} | |||
path_track_01, the first path_track, is shown in red. | path_track_01, the first path_track, is shown in red. | ||
Its substitute is 5 units lower. | Its substitute is 5 units lower. | ||
This really is a fast and easy way to force the elevator to spawn, start and stop in the exact positions as needed. | |||
The remaining path_tracks are all clones of the first created by selecting a path_track and then holding Shift while | |||
The first path_track is created once the func_tracktrain for the elevator has been created. | |||
Once | |||
As | The remaining path_tracks are all clones of the first created by selecting a path_track and then holding <Shift> while the clone is dragged with the mouse, the very same method that may be used for copying anything else in Hammer. | ||
Once the first path_track is created, a name should be given to it right away. As the clones are created, Hammer will name the others automatically and set the ''Next Stop Target'' property as well. | |||
All necessary path_tracks can be created in a matter of seconds. | |||
Building | Building the elevator should be done once the initial func_tracktrain is functional. | ||
Create the initial func_tracktrain and the path_tracks and then test | Create the initial func_tracktrain and the path_tracks and then test the map. | ||
For this project | For this project the dynamic elevator and prop doors will be used. | ||
This elevator has two skins. | This elevator has two skins. | ||
The second skin will be used for this project because it looks less like a freight elevator. | |||
The prop is: models/props_lab/freightelevator.mdl | The prop is: ''models/props_lab/freightelevator.mdl'' | ||
Skin 1 | [[File:WiseElevator03-1-.jpg|thumb|left|300px|Skin 0]] | ||
[[File:WiseElevator04-1-.jpg|thumb|left|300px|Skin 1]] | |||
{{clr}} | |||
The doors for the elevator are ''models/props_lab/elevatordoor.mdl''. | |||
Both the doors and the elevator are prop_dynamic entities. | |||
An elevator can be created entirely as one func_tracktrain instead of being parented to one like this project. | |||
How the doors will function must also be decided. | |||
Will they move up and down with the elevator, or will each floor have doors? | |||
func_tracktrain can be used in this same manner to create elevators, trains, boats, effects, etc. | |||
What is created and how it is done is up to the person making it. | |||
func_tracktrain can be used | One nice addition for the elevator is a trigger_multiple placed on the inside. | ||
Parent this to the func_tracktrain or the elevator. | |||
This can be used to sense when the player has entered or exited the elevator. | |||
To illustrate this, one has been created for this project with a single Output. | |||
OnEndTouch, prop_door*, SetAnimation, close | OnEndTouch, prop_door*, SetAnimation, close | ||
When the Player exits the | When the Player exits the elevator, the prop doors will close. | ||
Notice the asterisk. (prop_door*) | Notice the asterisk. (prop_door*) | ||
This will cause each of the 4 prop doors to be closed because they are named prop_door1, prop_door2, prop_door3 and prop_door4. | This will cause each of the 4 prop doors to be closed because they are named ''prop_door1'', ''prop_door2'', ''prop_door3'' and ''prop_door4''. | ||
Each floor has a button to open the elevator doors by way of a func_button: | |||
''OnPressed, prop_door1, SetAnimation, open'' | |||
OnPressed, prop_door1, SetAnimation, open | |||
In the more advanced sample file below the | In the more advanced sample file below the elevator can be called from each floor. | ||
Leaving the | Leaving the elevator will cause these doors to close, pressing the button on the outside wall will open the doors, when the elevator starts each time the doors will close. | ||
Everything on this | Everything on this elevator works very well but the simple elevator has a shortcoming: Neither of these elevators is designed to go backwards. Careful consideration should be used when deciding what the elevator will do and what it takes to achieve the design in mind. | ||
Neither of these | This elevator can be made to go backwards with a variety of methods, the func_tracktrain can be made to go backwards, each path_track can have an alternate path and the amount of logic_relays can be doubled. | ||
This | |||
There are elevators which acted exactly like this one in Detroit. They would start from the first floor and collect passengers as they went to the top, then they would return to the lower levels to start all over again. | |||
Just how much detail and time | Just how much detail and time is put into the elevator is of course up to the developer. | ||
Should all | Should all of the floors be the same height to make it easier on creating the path for the elevator? | ||
This is likely false. | |||
To illustrate that | To illustrate that, these 4 floors were intentionally made with different heights. | ||
The first floor is the only tricky part; each remaining path_track is simple to get in place. | The first floor is the only tricky part; each remaining path_track is simple to get in place. | ||
There isn't necessarily a right or wrong way to create these elevators, if it’s working the way desired, without errors, then it’s right. | |||
Notice the differences between the two sample vmf’s below. | Notice the differences between the two sample vmf’s below. | ||
Each uses the same | Each uses the same elevator and surroundings. | ||
One is simple and stops on each floor. | One is simple and stops on each floor. | ||
This is done by adding an Output to each path_track to stop the func_tracktrain and in this case another Output to pen the doors. | This is done by adding an Output to each path_track to stop the func_tracktrain and in this case another Output to pen the doors. | ||
Line 139: | Line 151: | ||
The more advanced version below doesn’t do that. | The more advanced version below doesn’t do that. | ||
Each path_track has a logic_relay it triggers. | Each path_track has a logic_relay it triggers. | ||
The trick is to have the | The trick is to have the elevator buttons enable or disable the logic_relays. | ||
A logic_relay that is disabled won’t do anything when it’s triggered. | A logic_relay that is disabled won’t do anything when it’s triggered. | ||
Inside the | ---- | ||
Inside the elevator four func_button entities have been created, as shown below. | |||
[[File:WiseElevator05-1-.jpg|thumb|left|340px|All four buttons shown in green.]] | |||
{{clr}} | |||
These buttons are textured with nodraw and each one is parented to the | These buttons are textured with nodraw and each one is parented to the elevator. | ||
For each button is a env_sprite, a really cheap way to create buttons but effective. | For each button is a env_sprite, a really cheap way to create buttons but effective. | ||
When the | When the player presses any of the 4 buttons the sprite color is changed, a series of logic_relays are either enabled or disabled, the door animation is changed and the elevator is told to start forward. | ||
Shown below are the Outputs for button #4. | Shown below are the Outputs for button #4. | ||
Each button has the same amount of Outputs, only different according to which floor is picked. | ---- | ||
Each button has the same amount of Outputs, only different according to which floor is picked. | |||
[[File:WiseElevator06-1-.png|thumb|left|450px|The output and input or also called the I/O log should look like this.]] | |||
{{clr}} | |||
One thing | One thing not done for the simple elevator in this project is the addition of a feature that allows the user to call the elevator to a floor from outside of the elevator. This can be done by applying the outputs from these buttons to their respective floors. | ||
The more advanced | The more advanced elevator below can be called from each floor, and the player spawns on Floor 3 to illustrate this. | ||
Another consideration for | Another consideration for the elevator would be custom materials for the buttons. | ||
Notice one additional feature of this | Notice one additional feature of this elevator, on the outside. Clip brushes for the columns on each side of the elevator have been created. These are not necessary but they add a nice touch to the map. | ||
These are not necessary but they add a nice touch to | |||
Clips like this can also be used inside | Clips like this can also be used from inside the elevator, to make it smother for the player and NPCs. | ||
The sample projects below can be used to further guide anyone toward their desired path related to the items discussed in this article. | |||
Latest revision as of 18:54, 10 April 2025

The content of this tutorial should also be checked to ensure it is user-friendly and easy to follow.
For help, see the VDC Editing Help and Wikipedia cleanup process. Also, remember to check for any notes left by the tagger at this article's talk page.
Illustrated in this project:
- A simple 4 floor elevator.
- More advanced version of the same.
- Advanced effect uses through env_sprite, func_brush, func_button, func_tracktrain, logic_relay, path_track, prop_dynamic and trigger_multiple entities.
- Demo of func_movelinear used for a similar effect.
- Elevator has a button for each floor.
- Each floor has a functional door and buttons.

Developer 1
enabled.(Visible below, next to the info_player_start entity, in the images of the elevator interior.)
The entities used in this article are brush-based (the func_tracktrain and the func_movelinear.)
The one in this project uses two Outputs back to itself:
OnFullyOpen, crate_lift, Close, 3.0
OnFullyClosed, crate_lift, Open, 3.0
...and a logic_auto to open it when the map starts:
OnMapSpawn, crate_lift, Open, 0.0
After its initial opening the func_movelinear will trigger itself. func_movelinear can easily be controlled with buttons and triggers.
One way to make elevators in HL2 is with a func_tracktrain. Some might say that it is very difficult to get things working properly, but these declarations can be dismissed if the correct procedure is used.
One such trick is the use of a one-time-only path_track to spawn the elevator. It is never used again after that. In the case of this 4 floor elevator another path_track is in the same general area as the first and it will be used instead each time the elevator returns to floor 1.
There are three adjustments that will need to be made once the elevator is working.
- The position of the first path_track.
- The position of the substitute path_track that will replace it.
- The func_tracktrain’s Height above the track property.
By tweaking these three objects one can get the elevator to start and stop exactly where desired.
Keep in mind func_tracktrain entities must be created facing East, or to the right in the Top 2D viewport.
But which way is east, exactly? East is the same direction as the direction right in hammer's top view.
-t---
Notice in the image below how the front of the elevator is facing east, or right.
Also, the func_tracktrain doesn’t have to be built in place.
It will spawn in position at the First Stop Target specified in its properties.
In this project the elevator, func_tracktrain, has as its First Stop Target path_track_01 and the flags Fire once and Teleport to THIS path track have been checked for the path_track.
It will only be used once, after that path_track_01a will be the first path_track.
Notice their position in this image:
path_track_01, the first path_track, is shown in red.
Its substitute is 5 units lower.
This really is a fast and easy way to force the elevator to spawn, start and stop in the exact positions as needed.
The first path_track is created once the func_tracktrain for the elevator has been created.
The remaining path_tracks are all clones of the first created by selecting a path_track and then holding <Shift> while the clone is dragged with the mouse, the very same method that may be used for copying anything else in Hammer.
Once the first path_track is created, a name should be given to it right away. As the clones are created, Hammer will name the others automatically and set the Next Stop Target property as well.
All necessary path_tracks can be created in a matter of seconds.
Building the elevator should be done once the initial func_tracktrain is functional. Create the initial func_tracktrain and the path_tracks and then test the map.
For this project the dynamic elevator and prop doors will be used. This elevator has two skins. The second skin will be used for this project because it looks less like a freight elevator. The prop is: models/props_lab/freightelevator.mdl
The doors for the elevator are models/props_lab/elevatordoor.mdl. Both the doors and the elevator are prop_dynamic entities.
An elevator can be created entirely as one func_tracktrain instead of being parented to one like this project.
How the doors will function must also be decided. Will they move up and down with the elevator, or will each floor have doors?
func_tracktrain can be used in this same manner to create elevators, trains, boats, effects, etc. What is created and how it is done is up to the person making it.
One nice addition for the elevator is a trigger_multiple placed on the inside. Parent this to the func_tracktrain or the elevator. This can be used to sense when the player has entered or exited the elevator. To illustrate this, one has been created for this project with a single Output.
OnEndTouch, prop_door*, SetAnimation, close
When the Player exits the elevator, the prop doors will close. Notice the asterisk. (prop_door*) This will cause each of the 4 prop doors to be closed because they are named prop_door1, prop_door2, prop_door3 and prop_door4.
Each floor has a button to open the elevator doors by way of a func_button:
OnPressed, prop_door1, SetAnimation, open
In the more advanced sample file below the elevator can be called from each floor. Leaving the elevator will cause these doors to close, pressing the button on the outside wall will open the doors, when the elevator starts each time the doors will close.
Everything on this elevator works very well but the simple elevator has a shortcoming: Neither of these elevators is designed to go backwards. Careful consideration should be used when deciding what the elevator will do and what it takes to achieve the design in mind. This elevator can be made to go backwards with a variety of methods, the func_tracktrain can be made to go backwards, each path_track can have an alternate path and the amount of logic_relays can be doubled.
There are elevators which acted exactly like this one in Detroit. They would start from the first floor and collect passengers as they went to the top, then they would return to the lower levels to start all over again. Just how much detail and time is put into the elevator is of course up to the developer.
Should all of the floors be the same height to make it easier on creating the path for the elevator? This is likely false. To illustrate that, these 4 floors were intentionally made with different heights. The first floor is the only tricky part; each remaining path_track is simple to get in place.
There isn't necessarily a right or wrong way to create these elevators, if it’s working the way desired, without errors, then it’s right.
Notice the differences between the two sample vmf’s below. Each uses the same elevator and surroundings. One is simple and stops on each floor. This is done by adding an Output to each path_track to stop the func_tracktrain and in this case another Output to pen the doors.
The more advanced version below doesn’t do that. Each path_track has a logic_relay it triggers. The trick is to have the elevator buttons enable or disable the logic_relays. A logic_relay that is disabled won’t do anything when it’s triggered.
Inside the elevator four func_button entities have been created, as shown below.
These buttons are textured with nodraw and each one is parented to the elevator.
For each button is a env_sprite, a really cheap way to create buttons but effective.
When the player presses any of the 4 buttons the sprite color is changed, a series of logic_relays are either enabled or disabled, the door animation is changed and the elevator is told to start forward. Shown below are the Outputs for button #4.
Each button has the same amount of Outputs, only different according to which floor is picked.
One thing not done for the simple elevator in this project is the addition of a feature that allows the user to call the elevator to a floor from outside of the elevator. This can be done by applying the outputs from these buttons to their respective floors.
The more advanced elevator below can be called from each floor, and the player spawns on Floor 3 to illustrate this.
Another consideration for the elevator would be custom materials for the buttons.
Notice one additional feature of this elevator, on the outside. Clip brushes for the columns on each side of the elevator have been created. These are not necessary but they add a nice touch to the map.
Clips like this can also be used from inside the elevator, to make it smother for the player and NPCs.
The sample projects below can be used to further guide anyone toward their desired path related to the items discussed in this article.