Multi-stop elevators: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
No edit summary
No edit summary
Line 49: Line 49:
<IMAGE TO COME> :''Note that each path_track is level with each of the floors, and that the elevator is currently in the first floor position, so that its origin is exactly the same point as the path_track's center.''
<IMAGE TO COME> :''Note that each path_track is level with each of the floors, and that the elevator is currently in the first floor position, so that its origin is exactly the same point as the path_track's center.''


Now the tricky part. Look at the Object Properties dialog box of each path_track. Each one has a "Next Stop Target", correct? All but the last one. That's because HAMMER has done the boring naming stuff for you, but not quite entirely...
Now the tricky part. Look at the Object Properties dialog box of each path_track. Each one has a "Next Stop Target" already assigned, correct? All but the last one. That's because HAMMER has done the boring naming stuff for you, but not quite entirely...


In the "Branch Path" field, type in the name of the stop immediately before the selected stop. So, if you're looking at "elev_stop_3" the branch path for that stop would be "elev_stop_2". This also means that "elev_stop_1" has no branch path. These "branch paths" will come into play when you try and take the elevator down a floor or two later.
In the "Branch Path" field, type in the name of the stop immediately before the selected stop. So, if you're looking at "elev_stop_3" the branch path for that stop would be "elev_stop_2". This also means that "elev_stop_1" has no branch path. These "branch paths" will come into play when you try and take the elevator down a floor or two later.
Line 59: Line 59:
Now for the programming shtick. Create a logic_compare outside your elevator (but within the map) on the first floor. Name it something obvious. I used "ni_elev_compare". Set both the "Initial Value" and "Compare Value" to 1. Now select the first floor path_track entity. Go to the "Outputs" tab in its Object Properties dialog and click "Add..." Set the output to "OnPass", the target entity should be the name of your logic_compare (e.g. ni_elev_compare), the input should be "SetValueCompare" with a parameter override of 1. Repeat for all of the other path_track entities, but change the parameter override to the floor number (i.e. 2, 3, 4, and 5).
Now for the programming shtick. Create a logic_compare outside your elevator (but within the map) on the first floor. Name it something obvious. I used "ni_elev_compare". Set both the "Initial Value" and "Compare Value" to 1. Now select the first floor path_track entity. Go to the "Outputs" tab in its Object Properties dialog and click "Add..." Set the output to "OnPass", the target entity should be the name of your logic_compare (e.g. ni_elev_compare), the input should be "SetValueCompare" with a parameter override of 1. Repeat for all of the other path_track entities, but change the parameter override to the floor number (i.e. 2, 3, 4, and 5).


Now, how to control the elevator? Buttons! Create a button (I'm just using small 1x4x4 blocks with a button-y texture) for each floor, and place them on the inside of the elevator wall, near the door.


<IMAGE TO COME> :''Elevator buttons at reasonable height near door (info_player_start is only there for reference).''
The buttons don't really need names, but if you want to be able to debug later through the console it'd be useful to give them some. I named them "ni_elev_button_1" through "ni_elev_button_5". This will make it easy to tell where input and output commands are from.





Revision as of 21:12, 4 December 2007

Due to the lack of a good article explaining the functionality of multi-stop elevators, and because I recently used HAMMER to design a theoretical building for one of my engineering classes which required such an elevator, I have decided to share my method with the Valve Developer Community. A warning: This will be a long tutorial, as creating a multi-stop elevator is a long process. The design and programming of the original elevator alone (first following tutorials found online, then by trial-and-error when none of those tutorials were what I needed) took upwards of twenty-two hours. That's not including the time spent designing and constructing the building around it.

I will eventually upload a working example map file, but as the original elevator is part of a university project I do not want to upload that. (It's also an eleven-story elevator, which is far more than most people will ever need to create.)

Any literary citation of this work needs only include my screen name ("newinfinite"), but I would appreciate credit if this elevator is used in any map releases. Thank you.

Now, let's begin.


Start by opening up HAMMER and creating a new map, then save your map. Call the map whatever you want, but remember the name of the file. I'm going to use the example name of "ni_elev_demo.vmf".

Construct your elevator the way you want it to look. This tutorial assumes you want a realistic, fully-enclosed elevator with opening and closing doors, so that is what I will build. Do not build or cut a hole for the doors yet.

Here is what I've created (exploded view on the right). :Note that I haven't cut a hole for the doors yet. That will come later.

Now that you've got your box (for that's all it is at this point), you need to determine how big your doors will be. I'm going to make mine 32 inches wide each, for a total door width of 64 inches. The doors will be 112 inches tall.

Make your doors 2 inches thick (assuming the walls of your elevator are 8 inches thick, like mine) and arrange them in a staggered pattern.

<IMAGE TO COME> :Top view of staggered doors.

Don't put them inside the elevator's wall yet. Cut a hole in the wall big enough for your doors, and place them so that they are centered between the two faces of the cut wall.

These doors will be parented to the elevator later. For now, select them individually and tie them to func_door entities. Leave them alone for now, we'll get back to them later.

Select your elevator's walls, ceiling and floor. Tie it all to a func_tracktrain entity. I've named mine "ni_elev" but you can name yours whatever you wish. Place the doors in their proper location inside the door frame you've cut into your elevator. If you've done the same as me, you can use my numbers for the door settings, but if you haven't, the idea is to get the first door (topmost in the "step 2" view) to have one inch sticking out when it is fully open (the "lip" should be 1 regardless of your door size) and for the second door to stick out one inch farther (so your lip should be [(individual door width) - 2] * [-1], or -30, if you're following my dimensions.

In my map, you can see that the doors will be moving "North" in the x/y view, so I've set their "movedir" (Move Direction) to "0 90 0". You can use the compass for this. The northernmost door has a lip of 1, while the southernmost door has a lip of -30. Set their movespeeds so that the ratio of their movespeeds is equal to the ratio of their movement amounts. For example, in my demo my north door is moving only 31 units (width - lip), while my south door is moving 62 units (again, width - lip). This gives a ratio of 1:2, north:south. Thus, I've set the north door speed to 31 and the south door speed to 62. I know this is the easiest ratio, but elevator doors move pretty slowly and this means it will take one second from start to finish, which is slow enough. Check the "Toggle" spawnflag box, and uncheck the "Touch Opens" spawnflag box. This will make the elevator doors open and close only when we want them to (when told to by the elevator).

<IMAGE TO COME> :Object Properties window for south door.

Give both doors the same targetname. In my case, they're named "ni_elev_doors" as you can see in the above image. Parent them to the elevator ("ni_elev" in my case) and let them be. The parented doors, for the most part, are done.


Now what's an elevator without any floors to travel to? If you said a box, you're right! Create a tube that exactly fits around your elevator (mine is a square tube made of concrete, but yours could be any size as long as it fits your elevator snugly). It's a good idea to make the walls of the tube 8 inches thick, as well. Cap the tube at both ends (no leaks here!) without overlapping your elevator. Cut holes (arbitrarily if you wish) that are equal to the size of your combination doors at the places they would be to access your floors. I've made five holes (therefore five floors) separated by arbitrary distances which are not equal. Build up a floor around each one, and assign all the walls except the tube to a visgroup called "ExtWalls" for "exterior walls". Hide "ExtWalls".

<IMAGE TO COME> :Your map should look something like this after hiding "ExtWalls".

Now, the fun part begins. Clone (select, then drag while holding SHIFT) your elevator doors into the opening of the first floor door. Mirror them (so that the south doors are close together and the north doors are farther apart) using CTRL-L (if you're following my demo). Rename them so that you can tell they're the first-floor doors (I used "ni_elev_doors_1"). When you've done that, and removed the "Parent" information from them, clone them into each of the other door frames, renaming them appropriately (e.g. "ni_elev_doors_2", "ni_elev_doors_3", and so on).

Select the elevator. It should have an "origin" point somewhere near (or exactly in) the middle. Drag it down to the center of the elevator floor, so that the blue ball representing the origin appears half-buried in the floor of the elevator. In math terms, the origin point should be on the plane that contains the topmost horizontal surface of the elevator's floor.

Now, create a path_track entity centered below the elevator's origin (or at the same point as the origin) that is on the same x/y plane as the topmost surface of the first floor brush. (See image for help.) Name this path_track whatever you wish, but follow it up with a "_1". For example, mine is called "ni_elev_stop_1". It might be good to suffix it "_01" instead of "_1" if you're creating an elevator with more than 10 floors. I avoided using "_0" as it is too confusing, but that is also a possibility.

Now, with your first path_track made, clone the path_track to the same place relative to the other floors' brushes. In short, this means that each path_track should be level with the walking surface of each floor, and on a vertical line which intercepts the elevator's origin point. Set your elevator's "First Stop Target" field to the name of your first floor (or whichever floor you wish) elevator stop, and set the "No User Control" and "Fixed Orientation" spawnflags.

<IMAGE TO COME> :Note that each path_track is level with each of the floors, and that the elevator is currently in the first floor position, so that its origin is exactly the same point as the path_track's center.

Now the tricky part. Look at the Object Properties dialog box of each path_track. Each one has a "Next Stop Target" already assigned, correct? All but the last one. That's because HAMMER has done the boring naming stuff for you, but not quite entirely...

In the "Branch Path" field, type in the name of the stop immediately before the selected stop. So, if you're looking at "elev_stop_3" the branch path for that stop would be "elev_stop_2". This also means that "elev_stop_1" has no branch path. These "branch paths" will come into play when you try and take the elevator down a floor or two later.

When you've got this done, you should have two paths. A "Next Stop Target" path, and a "Branch Path" path. The paths should be as follows: Next Stop Target (Normal) path: elev_stop_1 -> elev_stop_2 -> elev_stop_3 -> elev_stop_4 -> elev_stop_5 Branch Path (Alternate) path: elev_stop_5 -> elev_stop_4 -> elev_stop_3 -> elev_stop_2 -> elev_stop_1

Now for the programming shtick. Create a logic_compare outside your elevator (but within the map) on the first floor. Name it something obvious. I used "ni_elev_compare". Set both the "Initial Value" and "Compare Value" to 1. Now select the first floor path_track entity. Go to the "Outputs" tab in its Object Properties dialog and click "Add..." Set the output to "OnPass", the target entity should be the name of your logic_compare (e.g. ni_elev_compare), the input should be "SetValueCompare" with a parameter override of 1. Repeat for all of the other path_track entities, but change the parameter override to the floor number (i.e. 2, 3, 4, and 5).

Now, how to control the elevator? Buttons! Create a button (I'm just using small 1x4x4 blocks with a button-y texture) for each floor, and place them on the inside of the elevator wall, near the door.

<IMAGE TO COME> :Elevator buttons at reasonable height near door (info_player_start is only there for reference).

The buttons don't really need names, but if you want to be able to debug later through the console it'd be useful to give them some. I named them "ni_elev_button_1" through "ni_elev_button_5". This will make it easy to tell where input and output commands are from.




MORE TO COME. BE PATIENT.