home · browse · search · game entities · user directory · message board · IRC | register

October 16, 2006, 8:31 pm PDT
username  
password  
forgot password?

Popular Resources
  • Half-Life 2 Mod FAQ
  • Valve Hammer Editor
  • Hammer 3.5 beta test
  • Half-Life Utilities
  • game data files
  • ZHLT 2.5.3 custom build
  • Half-Life SDK
  • Feedback
    If you've got any feedback, suggestions, or bugs to report regarding the Collective website, go here!

  • Feedback (301)
  • Newsletter
     
    Enter your email address in the above form to add yourself to the email newsletter list. Click here for more info.

    Hosted Sites
  • Valve ERC
  • Collective
  • TFMapped
  • Spirit of Half-Life
  • Selective Design
  • Pixel Reviews
  • recent articles

    NPC and Item Placement Theory
    17/03/05 11:35pm PST
    Non-Player Character (NPC) and item placement can influence both the gameflow and immersion of a level. This article aims to give some pointers on how to properly place them.
    - Hugh 'Hugh' Lloyd

    Got Props?
    13/03/05 08:32am PST
    A common problem in HL2 mapping is props not showing up in game. This article explains why and offers solutions.
    - Jeff 'Yesukai' Pritchard

    Simulating Randomness
    18/12/04 11:29pm PST
    This article focuses on how to properly simulate random events that should occur at a certain average frequency, or within a certain probability per period of time.
    - Skyler 'Zipster' York

    Adding Single-Player Weapons to Half-Life 2
    15/12/04 06:52pm PST
    Covers the process behind adding weapons to a single-player Half-Life 2 modification.
    - Skyler 'Zipster' York

    Your world in HL2
    06/12/04 12:17am PST
    This article gives tips and advice to anyone wanting to make custom photorealistic textures to be used in Half-Life 2.
    - Oksid

    Hiding in Shadow
    21/08/04 01:11pm PDT
    Describes how to create a function that has monsters disregard you if you are hiding in a certain level of "darkness," which can be set from within map properties.
    - Anders [Wolf] Jenbo (NoBody)

    XSI EXP for Half-Life 2 Tutorial - Camera Control
    23/09/04 12:43am PDT
    A SOFTIMAGE|XSI tutorial explaining all of the camera controls available to you in XSI!
    - Josh Enes

    Bump Mapping in Half-Life
    08/08/04 11:58am PDT
    Details a method of achieving real-time bump mapping in Half-Life, and provides an implementation of the algorithm.
    - Francis 'DeathWish' Woodhouse

    Real-Time "TRON 2.0" Glow For Low-Spec Hardware
    19/06/04 02:06pm PDT
    A sequel to the original "Real-Time 'TRON 2.0' Glow" article, this describes how to implement real-time glow that works on low-spec graphics cards.
    - Francis 'DeathWish' Woodhouse

    Hitboxes and Code
    05/06/04 06:25pm PDT
    How do I make only one part of a monster take damage? Learn about the relationship between model hitboxes and what you can do with them in a characters code.
    - Jonathan 'Teh_Freak' Smith

    Elevator No. 2
    [Mon Mar 17, 2003 / 09:12pm PST] Chris 'autolycus' Bokitch - comments (14) comments enabled

    Introduction

    This tutorial describes the process of making an elevator that can move between more than two floors. It is a platform elevator, not a normal enclosed elevator. To keep things as simple as possible, I didn't make it with buttons that move with the elevator, although that could easily be incorporated as well.

    There are two parts to this tutorial -

    For this tutorial, the rules will be:

    • The elevator "call" button can only be activated if the elevator is on another level.
    • The elevator movement buttons can only be activated if the elevator is on the current level.
    • If the elevator is between levels, none of the buttons can be activated.

    Prepare for a bit of head spinning!

    Setup - Elevator Construction

    The construction of the elevator is the easy part. Below is a cut-away view showing the first stage of the construction.


    The setup and configuration of a func_train and its path_corners is explained in the func_train entity description. Only the entity properties outlined below should be set.

    func_train (elev1)

    This is the elevator. It should be built in a location that will give it even lighting, as it will automatically move to the first stop target when the level loads, but it will retain its lighting from where it was originally built. By starting the elevator on the second level, I was able to give it even lighting without having to build it at a separate location.

    • Name (targetname) - This elevator must be triggered each time it is moved, so you need to specify a name here. For the tutorial, I've used elev1.
    • First stop target (target) - Set this to the path_corner you want the train to start on. For this tutorial, I've set it to path_corner p2.

    The above properties are the only essential ones. You might also want to modify the speed and sounds, as you see fit.

    path_corner (p1, p2, and p3)

    These are the path points the elevator will move to. The main difference between these and a normal set of path_corners is that these only have a Name, no "next stop target". This will be explained more below.

    • Name (targetname) - the path_corners need a Name so they can be referred to by other entities. In the tutorial, starting at the lowest path_corner and working upward, I've named them p1, p2, and p3.

    In addition to the Name setting, each path_corner must have its Wait for retrigger flag checked. This causes the elevator to stop and wait at each level.

    "Call" buttons

    In the next step, we'll setup the "call" buttons. These will be used to call the elevator to your level if it isn't there. Useful, no? :) Below is the same cut-away view as above with the "call" buttons and their associated entities. (They would, of course, be set on a wall).


    func_button ("call" buttons, #1, #2, and #3)

    These are the buttons that you'll press to call the elevator. They're setup is pretty straightforward.

    • Targeted object (target) - Each "call" button targets a multi_manager. Starting from the lowest button and working upward, they target mm_button1, mm_button2, and mm_button3.

    Each func_button should also have its Don't Move flag checked. This is for esthetic reasons and avoids the delay of the button pressing.

    multi_manager (mm_button1, mm_button2, and mm_button3)

    These multi_managers coordinate the events that occur when the "call" button is pressed. The use of multi_managers is outlined in the multi_manager entity description.

    • Name (targetname) - this is the name the func_buttons use to refer to the multi_managers. From the lowest and working upward, the multi_managers should be named mm_button1, mm_button2, and mm_button3.
    • to_l1, 0 or to_l2, 0 or to_l3, 0 - these are the Names of trigger_changetargets, and they are activated immediately when the multi_manager is activated. The lowest multi_manager will have the to_l1 key, the middle the to_l2 key, and the top the to_l3 key.
    • elev1, 0.1 - this is the Name of the elevator, and it is activated 0.1 seconds after the multi_manager is activated (to give time for the trigger_changetargets to set the path of the elevator).

    trigger_changetarget (to_l1, to_l2, and to_l3)

    When activated, these set the target of the elevator to the level of the "call" button that was pressed. The use of the trigger_changetarget entity is outlined in the trigger_changetarget entity description.

    • Name (targetname) - This is the name that will be refered to by the preceeding multi_managers. Starting at the bottom and working upward, they are named to_l1, to_l2, and to_l3.
    • Target (target) - The target of these will always be the elevator, so it should be set to elev1.
    • New Target (m_iszNewTarget) - This is the Name of the new path_corner that the elevator will target. Starting from the lowest trigger_changetarget and working upward, this value should be set to p1, p2, and p3.

    Elevator Movement buttons

    Now we'll add some buttons to move the elevator between the levels. Below is another picture of the same cut-away view. The buttons, multi_managers, and trigger_changetargets added in the previous step have been hidden to avoid a cluttered look.


    func_button ("move" button #1, #2, #3, and #4)

    These buttons act exactly like the "call" buttons, except that they cause the elevator to move up or down a level (depending on which button is pressed) and the player is generally assumed to be on the elevator when a button is pushed. Note that, whereas everything previous to this step involved multiples of 3, this has 4 buttons because the middle level has a button for both up (#2) and down (#3).

    • Targeted object (target) - Each button targets a multi_manager.

      #1 targets mm_l1_l2
      #2 targets mm_l2_l3
      #3 targets mm_l2_l1
      #4 targets mm_l3_l2

    Each func_button should also have its Don't Move flag checked.

    multi_manager

    These multi_managers coordinate the events that occur when the "move" button is pressed. The use of multi_managers is outlined in the multi_manager entity description.

    • Name (targetname) - this is the name the func_buttons use to refer to the multi_managers. From #1 to #4, the multi_managers should be named mm_l1_l21, mm_l2_l3, mm_l2_l1, and mm_l3_l2
    • l1_l2, 0 or l2_l3, 0 or l2_l1, 0 or l3_l2, 0 - these are the Names of trigger_changetargets, and they are activated immediately when the multi_manager is activated. They are listed in order from #1 to #4.
    • elev1, 0.1 - this is the Name of the elevator, and it is activated 0.1 seconds after the multi_manager is activated (to give time for the trigger_changetargets to set the path of the elevator).

    trigger_changetarget (l1_l2, l2_l3, l2_l1, and l3_l2)

    When activated, these set the target of the elevator to the appropriate level depending on which "move" button was pressed. The use of the trigger_changetarget entity is outlined in the trigger_changetarget entity description.

    • Name (targetname) - This is the name that will be refered to by the preceeding multi_managers. From #1 to #4, they are named l1_l2, l2_l3, l2_l1, and l3_l2.
    • Target (target) - The target of these will always be the elevator, so it should be set to elev1.
    • New Target (m_iszNewTarget) - This is the Name of the new path_corner that the elevator will target. Going from #1 to #4, the value of this should be set to p2, p3, p1, and p2.

    Stretch!

    Ok, that's that part. That was the easy part?! Well, not really. It's a little head spinning, no? That is the straightforward part though. You'll have something that looks similar to the picture below (again, this is a cut-away... you should have walls and stuff too. :)


    You might note that the colors of the entities are different. This is because i've turned them into VisGroups so I could easily hide them.

    You can now run and test your level. The buttons should all work - if you press a "call" button, the elevator will move to the appropriate level. If you press a "move" button, the elevator will take you to the appropriate level. But wait, if you press a "move" button when the elevator is not at your level, the elevator will move as if it was. This just isn't right! :) In the next section, we'll setup the state-checking entities that will prevent this.

    Setup - Button State Checking

    In this section, we're going to impose a few rules on the use of the buttons.

    1. The elevator "call" button can only be activated if the elevator is on another level.
    2. The elevator movement buttons can only be activated if the elevator is on the current level.
    3. If the elevator is between levels, none of the buttons can be activated.

    Below is a cut-away picture showing all of the entities that you'll be placing/modifying/using for setting up the first level's state checking.


    Is your head spinning?

    Keepers of the State

    Ok, we'll start with the group of 7 entities that are responsible for tracking the state of the elevator and controlling what buttons are active when. Only 6 of the entities are used to keep track of the states. The sixth, the all_off multi_manager, is there for ease of use only. Activating it will turn all of the buttons off.

    multi_manager (all_off)

    This entity isn't entirely necessary, but it simplifies things greatly.

    As mentioned above, activating this turns off all of the "call" and "move" buttons.

    • Name (targetname) - Set this to all_off.
    • eg_call1_off, 0 - turns off the level 1 call button multisource (by way of an env_global)
    • eg_call2_off, 0 - turns off the level 2 call button multisource
    • eg_call3_off, 0 - turns off the level 3 call button multisource
    • eg_elev1_off, 0 - turns off the level 1 move button multisource
    • eg_elev2_off, 0 - turns off the level 2 move buttons multisource
    • eg_elev3_off, 0 - turns off the level 3 move button multisource

    Yes, yes, I know - none of the above entities (eg_call*_off, eg_elev*_off) have been defined yet. Patience, grasshopper.

    multisource (ms_call1)

    This is the multisource master for the level 1 "call" button. When it is "off", the button will be disabled.

    • Name (targetname) - set this to ms_call1.
    • Global State Master (globalstate) - set this to call1state. This is the global state that is defined by the env_global entities, below. The state of call1state (on or off) determines the state of the multisource.

    Now that you've created this multisource, select the level 1 "call" button, and in its properties, set its Master (master) property to ms_call1.

    env_global (eg_call1_on)

    Activating this entity will set the call1state global state to "on", enabling the ms_call1 multisource.

    • Name (targetname) - set this to eg_call1_on.
    • Global State to Set (globalstate) - set this to call1state.
    • Trigger Mode (triggermode) - set this to On (1).
    • Initial State (initialstate) - set this to On (1).

    The Set Initial State flag should also be set. Now, when the level starts, this will immediately set the state of call1state global to "on". Each time this entity is triggered afterward, it will always set the state of call1state to on.

    env_global (eg_call1_off)

    Activating this entity will set the call1state global state to "off", disabling the ms_call1 multisource.

    • Name (targetname) - set this to eg_call1_off.
    • Global State to Set (globalstate) - set this to call1state.
    • Trigger Mode (triggermode) - set this to Off (0).
    • Initial State (initialstate) - set this to Off (0).

    Do not check the Set Initial State flag for this entity. Each time this entity is triggered, it will set the state of call1state to off.

    multisource (ms_elev1)

    This is the multisource master for the level 1 "move" button. When it is "off", the button will be disabled.

    • Name (targetname) - set this to ms_elev1.
    • Global State Master (globalstate) - set this to elev1state. This is the global state that is defined by the env_global entities, below. The state of elev1state (on or off) determines the state of the multisource.

    Now that you've created this multisource, select the level 1 "move" button, and in its properties, set its Master (master) property to ms_elev1.

    env_global (eg_elev1_on)

    Activating this entity will set the elev1state global state to "on", enabling the ms_elev1 multisource and, in turn, the level 1 "move" button.

    • Name (targetname) - set this to eg_elev1_on.
    • Global State to Set (globalstate) - set this to elev1state.
    • Trigger Mode (triggermode) - set this to On (1).
    • Initial State (initialstate) - set this to On (1).

    Do not check the Set Initial State flag for this entity. Each time this entity is triggered, it will set the state of elev1state to on.

    env_global (eg_elev1_off)

    Activating this entity will set the elev1state global state to "off", disabling the ms_elev1 multisource.

    • Name (targetname) - set this to eg_elev1_off.
    • Global State to Set (globalstate) - set this to elev1state.
    • Trigger Mode (triggermode) - set this to Off (0).
    • Initial State (initialstate) - set this to Off (0).

    The Set Initial State flag should also be set. Now, when the level starts, this will immediately set the state of elev1state to "off". Each time this entity is triggered afterward, it will always set the state of elev1state to off.

    Final Thingies

    Last, you've got to connect the state-checkers to the appropriate multi_managers so they're functional.

    • multi_manager (mm_button1) - This is the multi_manager that is activated when the "call" button is pressed. The only thing you need to add to this multi_manager is all_off, 0. This turns all of the "call" and "move" buttons off.
    • multi_manager (mm_l1_l2) - As above, all that needs to be added to this is all_off, 0.
    • multi_manager (mm_elev_1) - (This must be created) This is the multi_manager that is activated when the elevator reaches the p1 path_corner. The following values and parameters should be added to setup rules #1 and #2 -

      • eg_elev1_on, 0 - This turns on the "move" button on level 1.
      • eg_call2_on, 0 - This turns on the "call" button on level 2.
      • eg_call3_on, 0 - This turns on the "call" button on level 3.

      In addition, the p1 path_corner must have its Fire on Pass (message) set to mm_elev_1, so this multi_manager gets activated when the elevator reaches the p1 path corner.

    Whenever a "call" or "move" button is pressed, all of the buttons are disabled (satisfying rule #3). When the elevator reaches its target level, the path_corner activates its multi_manager which turns on the "move" buttons for that level (satisfying rule #2), and activates all of the "call" buttons except for the one on that level (satisfying rule #1).

    Notes

    Ok, each level has almost the identical setup, except for the all_off multi_manager which only needs to be created once but is referenced at each level, so I'm not going to list the other levels here. It would be a little redundant and my head would be in danger of exploding. If you want more detail, please check out the example map - the entities are set out pretty neatly and it should be easy to follow the logic of everything. The VisGroups are also setup to allow for easiest visibility of the inner-workings.

    Here's what the entity setup looks like in the finished example map.


    Crikey!

    There are a few things that should be mentioned.

    • To suitably understand this tutorial, a good understanding of the env_global and multisource entities is essential. You might want to play around with a smaller test map if you find that you can't get them working. The important thing to remember with the env_global entity is to check the Set Initial State flag when needed, otherwise you might be checking a state that doesn't exist yet.

    • Until it is possible to group entities together (for example, putting a func_door and a func_button on a func_train), it will never be convenient to make a normal "real-life" elevator. That is why this tutorial uses a simple platform elevator. It is certainly possible to add a set of doors and the illusion of a button that travels with the elevator (as demonstrated by other tutorials) but you may find yourself thinking, is the effort really worth it?

    This tutorial was written prior to the release of Spirit of Half-Life. The mod greatly simplifies the attachment and movement of entities.

    • When working on a project like this, the most important thing to do is figure out what the rules are and make sure none of them conflict with each other. Once I had the set of three simple rules set out, it was easy to figure out how things should be done.

    • When doing something that requires state checking using env_global entities, testing your map is way easier when you use the impulse 104 "cheat" to list the current global states. You'll know immediately if you're setting up and manipulating the states correctly, rather than having to watch the behavior of the affected entities.

    Example

    For a more concrete illustration, check out the example map linked below.

    article created on Mon Mar 17, 2003 / 09:12pm PST
    this item has been viewed 11079 times
    [Half-Life / mapping]

    Only registered users can post comments. Have you registered yet?

    user comments

    displaying comments of normal or higher rating

    1.

    Patrick 'ComCray' Kanne
    Thu Apr 17, 2003 / 03:51pm PDT

      Auto, if i'm getting this right you'd need a per-button state tracker system right? That kindof does make sense.. One-state-tracker-fits-all doesn't seem to work see..

    What I don't really get is why you should take two seperate env_globals for the on/off state. Can't you just use one with it's toggle functionality enabled? Any particular reason?

    2.

    Jethro 'deathz0rz' Beekman
    Thu Apr 17, 2003 / 04:06pm PDT

      i think this isn't auto's article... he just transferred it to the collective ;)

    3.

    Chris 'autolycus' Bokitch
    Thu Apr 17, 2003 / 04:17pm PDT

      No, this is my article. It's been so long since I looked at it, I'd have to analyze it a bit before commenting hehe.

    4.

    Patrick 'ComCray' Kanne
    Thu Apr 17, 2003 / 04:37pm PDT

      *grin* that makes sense too.. it's quite a good article btw..:)

    5.

    Eddy 'Cobra' Loughton
    Thu Apr 17, 2003 / 04:49pm PDT

      worked for me :)

    6.

    lizard
    Sat Jun 21, 2003 / 05:15am PDT

      its a little to complicated for me :(

    i think il just download the map and see what it all loks like in wirldcraft :) always works for me :P

    god i love tutorials :) now i got ways to make platforms wich go to different floors

    would auto mind if i used his platform in my singleplayer map?

    7.

    Guy Gardner
    Thu Jul 03, 2003 / 06:22am PDT

      Your map works only if the elevator begin in the 2 floor
    If you put the elevator in 1 or 3 floor, the first time when you push any button will not work
    comment modified on Tue Jul 15, 2003 / 11:52am PDT

    8.

    K^2
    Sat Jan 17, 2004 / 10:12am PST

      I tried cobining the multi-floor and moving "buttons" elevator, and the elevator refuses to go to any floor more than once. It is the same thing on every floor, so even if I went from the 1st to the 3rd floor, then I can't go to the 3rd from the 1st or 2nd. I checked every flag and preference in the multi_manager, triger_changetarget, and the path_corners, but I can't find anything that would prevent any of these to be used more than once.


    Edit: I found the problem. There was another parameter added to the multi_manager by the game data file I had with a default value of 512. So naturaly, the multi_manager refused to fire again untill these 512 secconds are over.
    comment modified on Sat Jan 17, 2004 / 10:49am PST

    9.

    Brian 'Yamazaki' Dorner
    Sun Jan 18, 2004 / 10:00am PST

      I'm not sure you need all the floor-by-floor state checking at all. I've only tried it in Natural Selection, but I made an elevator that moves between 3 floors, with a call button on each floor and an Up and Down button on the elevator itself (Using invisible rotating buttons). I only used one set of state checks to prevent the invisible buttons from being used if the elevator isn't at that floor, but otherwise nothing else. So if you call the elevator to your floor, but it's already on that floor, it just makes the elevator stop sound but doesn't break anything.

    10.

    Angry Beaver
    Sun Jan 25, 2004 / 06:33pm PST

      guy gardner

    it does work, he just dosen't mention how you have to change the set up. if you look at it you will see the second floor has different properties on its entitys when compared to the 1st and 3rd. simply change the 2nd floors different properties to where u want it to start then set 2nd floor so its the same as 1st or 3rd.

    made my own version of this with a frieght elevator, with a few custom aditions ;). lol wish I'd of known about this article bfr i was already done. helped me realize how multisource and env_globals interact though.

    11.

    Anarki
    Mon May 10, 2004 / 10:42pm PDT

      wierd, VHE must be broken..i only have one field (Name [targetname]) for my multi_manager, is this supposed to be like this?

    12.

    Raeven0
    Tue May 11, 2004 / 12:27am PDT

      Try the multi_manager info page ;)

    13.

    Lasse "MenZa" Nielsen
    Sat Jan 08, 2005 / 04:31am PST

      Shit...

    I assume its a good elevator, but.. this is waaay to compicated :D

    14.

    Captain P
    Sat Jan 08, 2005 / 03:04pm PST

      Basically, it's just changing the target of the train (the elevator). There's a load of extra entities that set the state of buttons to on or off, so the elevator can't be interrupted when it's moving.

    At first glance, it looks indeed pretty hard. But once you've delved into it a bit, you'll see a certain logic behind it. Finally, it's just plain simple, but it takes some time to understand. Good luck! :)
    comment modified on Sat Jan 08, 2005 / 03:05pm PST

    VERC © 2004. All content copyright its respective owner, all rights reserved.
    script execution time: 0.667327165604 seconds