[TUTORIAL] Making Payload Elevators

Discussion in 'Tutorials & Resources' started by English Mobster, Jan 19, 2012.

  1. English Mobster

    English Mobster L6: Sharp Member

    Messages:
    355
    Positive Ratings:
    295
    NOTE:
    As far as entities go, this tutorial is fairly complex. Payloads in general are very finicky, and a single missplaced number or missed output can screw everything up. I would recommend taking a look at the example .vmf if you get lost.

    This system is designed to be called upon multiple times. It effectively replaces what your team_train_watcher typically automates, giving you a lot of control over the Payload, should you know how to utilize it. While not the most efficient way for a single elevator, it can be used multiple times for multiple elevators with only 3 new logic entities per elevator (not counting the elevator's func_tracktrain, capzone, or path_tracks).

    This MAY screw with the HUD in Payload Race maps. If it does, I would suggest you delete the elevator's team_train_watcher and place a trigger_hurt underneath the elevator's platform to kill anyone who gets stuck in it. To be honest, I'm not sure if the extra team_train_watcher is truly NEEDED, but, as the guy in the church in Left 4 Dead taught us, it's better to be safe than sorry. A lot of this stuff is probably also redundant (notably my OutValue and OnGetValue dual outputs), but redundancy never hurt much.

    Now on to the meat of the tutorial:

    • The Push Logic
    I'm using Boojum's stock team_train_watcher (called "sspl_watcher") with the "Handle Train Movement" flag set to "No" and one Output added:
    Code:
    OnTrainStartRecede | cart_rollback_relay | Trigger | *NO PARAMETER* | 0
    A math_remap converts the number of current players on the cart into an integer we can use. I have mine named "cart_push_remap" with "Maximum Valid Input Value" and "Output Value When Input is Max" both set to 3.
    I have a single output:
    Code:
    OutValue | bomb_cart_case | InValue | *NO PARAMETER* | 0
    Of course, we can't do anything if the sspl_pushzone (the cart's trigger_capture_area) gives us no numbers to work with! Add the following outputs to Boojum's default sspl_pushzone:
    Code:
    OnNumCappersChanged | cart_push_remap | InValue | *NO PARAMETER* | 0
    OnNumCappersChanged | sspl_watcher | SetNumTrainCappers | *NO PARAMETER* | 0
    Now to set up our logic_case we named in the math_remap:
    Code:
    Name: bomb_cart_case
    Case 01: 0
    Case 02: 1
    Case 03: 2
    Case 04: 3
    All this does is take the integer given to us by the remap and convert it into something we can work with. The outputs are going to be a doozy:
    Code:
    OnCase01| rollbackzone_relay | Trigger | *NO PARAMETER* | 0
    OnCase01| stopped_relay | Trigger | *NO PARAMETER* | 0
    OnCase01| elevator_rollback_relay | Trigger | *NO PARAMETER* | 0
    OnCase02| cart_speed_multiplier | GetValue | *NO PARAMETER* | 0
    OnCase02| sspl_cartsparks | StopSpark | *NO PARAMETER* | 0
    OnCase02| cart_speed_watcher | Multiply | 0.4 | 0.10
    OnCase02| elevator_speed_watcher | Multiply | 0.4 | 0.10
    OnCase03| cart_speed_multiplier | GetValue | *NO PARAMETER* | 0
    OnCase03| sspl_cartsparks | StopSpark | *NO PARAMETER* | 0
    OnCase03| cart_speed_watcher | Multiply | 0.7 | 0.10
    OnCase03| elevator_speed_watcher | Multiply | 0.7 | 0.10
    OnCase04| cart_speed_multiplier | GetValue | *NO PARAMETER* | 0
    OnCase04| sspl_cartsparks | StopSpark | *NO PARAMETER* | 0
    OnCase04| cart_speed_watcher | Multiply | 1 | 0.10
    OnCase04| elevator_speed_watcher | Multiply | 1 | 0.10
    I have two math_counters. One of these I call my "watcher." Everything is set to the default settings for a math_counter except for the name field (in my case being "cart_speed_watcher").

    All this does is receive the input from the logic_case and spit it back out with these two outputs:
    Code:
    OnGetValue | sspl_train | SetSpeedDirAccel | *NO PARAMETER* | 0
    OutValue | sspl_train | SetSpeedDirAccel | *NO PARAMETER* | 0
    The second one I call my "multiplier." This modifies your overall speed. We use it to make the elevator go slower, but you should also use it if you want to speed up or slow down the cart (whenever you would typically send a SetSpeedForwardMultiplier output to your team_train_watcher). Most of the fields are default, except for the "name" and "initial value" fields (cart_speed_multiplier and 1, respectively). It also has 2 outputs:
    Code:
    OnGetValue | cart_speed_watcher | Multiply | *NO PARAMETER* | 0
    OutValue | cart_speed_watcher | Multiply | *NO PARAMETER* | 0
    It SHOULD multiply against the cart's current speed when it changes, but I like to send a "GetValue" output to the entity after I send whatever speed adjustment I want to make to the multiplier with a delay of .10, just to be safe. Redundancy. [​IMG]


    Now to set up our three logic_relays for the conclusion of the push logic. These handle stopping the cart if no one is nearby, making it roll back down a hill should you want a traditional rollback zone (elevators get their own logic_case), and the usual rollback if a cart is left unattended.
    The first is akin to your cart_speed_watcher in that it takes output from the pushzone and translates it into something your cart can use. I named mine "stopped_relay" and left the "Start Disabled" tag set to "No".
    As for the output:
    Code:
    OnTrigger | cart_speed_watcher | SetValue | 0 | 0
    The second is like your multiplier where it is only used for rolling back down a hill (for traditional rollback, see Rewind's post). This does NOT apply to your elevator.
    Code:
    Name: rollbackzone_relay
    Start Disabled: Yes
    Outputs:

    Code:
    OnTrigger | cart_speed_watcher | SetValue | 0 | 0
    OnTrigger | sspl_train | SetSpeedDirAccel | -0.30 | 0.10
    To use this for a rollback zone, just enable "rollback_relay" and disable "stopped_relay" as the cart enters the rollback zone (at the same time you disable the path_track behind it). Keep the flags set on your rollback zone to "Rollback zone on HUD (Auto-roll if team_train_watcher handles movement)," even though you don't have auto-roll. This keeps it on your HUD regardless. Make sure to disable it again after the rollback zone!

    Your third should be named "cart_rollback_relay". Here are your outputs:
    Code:
    OnTrigger | sspl_train | SetSpeedDirAccel | -0.10 | 0.10
    OnTrigger | sspl_cartsparks | StartSpark | *NO PARAMETER* | 0.10
    • Elevator Logic
    Now we need one more math_counter. This ensures the elevator and the cart will be going the same speed.
    Code:
    Name: elevator_speed_watcher
    Start Disabled: Yes
    Outputs:
    Code:
    OnGetValue | sspl_train | SetSpeedDirAccel | *NO PARAMETER* | 0
    OutValue | sspl_train | SetSpeedDirAccel | *NO PARAMETER* | 0
    OnGetValue | elevator_train | SetSpeedDirAccel | *NO PARAMETER* | 0
    OutValue | elevator_train | SetSpeedDirAccel | *NO PARAMETER* | 0
    Create a team_train_watcher. This keeps people from getting stuck in the elevator (may not be needed; I haven't done much testing without it and might screw up the HUD on PLR setups):
    Code:
    Name: elevator_train_watcher
    Team: Red
    Start Disabled: Yes
    Train to watch: elevator_train
    Node the path starts at: elevator_platform_path_start
    Node the path ends at: elevator_platform_path_end
    I'm not sure if it needs to start disabled or not, but it can't hurt.

    And add an output to your logic_auto:
    Code:
    OnMapSpawn | elevator_train | TeleportToPathTrack | elevator_platform_path_start | 0
    Now create your elevator's func_tracktrain platform. Follow Frozen's instructions, giving it a dummy path alongside the cart. Make sure the keyvalues match those of the cart if you want them to appear to be going the same speed. If you're following the naming scheme of this tutorial, name it "elevator_train" and make the "First Stop Target" field "elevator_platform_path_start" (and make a path_track where you want it to wind up named "elevator_platform_path_end").


    Copy the cart's trigger_capture_area and paste it on your platform. Change these keyvalues:
    Code:
    Name: elevator_pushzone
    Parent: elevator_train
    Start Disabled: Yes
    Now create a logic_relay. This will handle the auto-rollback from the elevator.
    Code:
    Name: elevator_rollback_relay
    Start Disabled: Yes
    Outputs:
    Code:
    OnTrigger | elevator_speed_watcher | SetValue | 0 | 0
    OnTrigger | cart_speed_watcher | SetValue | 0 | 0
    OnTrigger | sspl_cartsparks | StartSpark | *NO PARAMETER* | 0
    OnTrigger | elevator_train | SetSpeedDirAccel | -0.30 | 0.10
    OnTrigger | sspl_train | SetSpeedDirAccel | -0.30 | 0.10
    That's it for the logic! Now to hook it all up.



    • Path_track Logic
    At the BOTTOM of your elevator, change the "Angles" field in the top right until the circle with a single line in it is lined up with the direction you want your cart to be facing as seen from the TOP viewport.
    Change the "Orientation Type" to "Face this path_track's angles".
    Do the same for any other path_tracks inside your elevator (including the dummy ones the elevator follows).
    On all of the cart's path_tracks, make sure you have "rollback zone on HUD" checked. I don't believe you need this checked for the elevator's path_tracks, as the team_train_watcher isn't handling movement there, either.

    BOTTOM CART PATH_TRACK OUTPUTS:
    Code:
    OnPass | cart_speed_multiplier | SetValue | .5 | 0
    OnPass | elevator_train_watcher | Enable | *NO PARAMETER* | 0
    OnPass | elevator_speed_watcher | Enable | *NO PARAMETER* | 0
    OnPass | cart_speed_watcher | Disable | *NO PARAMETER* | 0
    OnPass | *PATH_TRACK BEFORE THIS ONE* | DisablePath | *NO PARAMETER* | 0
    OnPass | cart_speed_multiplier | GetValue | *NO PARAMETER* | 0.10
    OnPass | elevator_speed_watcher | GetValue | *NO PARAMETER* | 0.20
    OnPass | sspl_pushzone | Disable | *NO PARAMETER* | 0.30
    OnPass | sspl_train | SetSpeedDirAccel | 0.55 | 0.30
    OnPass | elevator_train | SetSpeedDirAccel | 0.55 | 0.30
    OnPass | cart_rollback_relay | Disable | *NO PARAMETER* | 0.30
    OnPass | elevator_pushzone | Enable | *NO PARAMETER* | 0.60
    OnPass | sspl_train | SetSpeedDirAccel | 0 | 0.60
    OnPass | elevator_train | SetSpeedDirAccel | 0 | 0.60
    OnPass | elevator_rollback_relay | Enable | *NO PARAMETER* | 0.70
    OnPass | stopped_relay | Disable | *NO PARAMETER* | 0.70
    
    BOTTOM ELEVATOR PATH_TRACK OUTPUT:
    Code:
    OnPass | sspl_cartsparks | StopSpark | *NO PARAMETER* | 0

    TOP ELEVATOR PATH_TRACK OUTPUTS:
    Code:
    OnPass | elevator_train | Stop | *NO PARAMETER* | 0
    OnPass |elevator_train| SetSpeedDir | 0 | 0
    TOP CART PATH_TRACK OUTPUTS:
    Code:
    OnPass | elevator_speed_watcher | Disable | *NO PARAMETER* | 0
    OnPass | cart_speed_multiplier | SetValue | 1 | 0
    OnPass | stopped_relay | Enable | *NO PARAMETER* | 0
    OnPass | elevator_rollback_relay | Disable | *NO PARAMETER* | 0
    OnPass | cart_speed_watcher | Enable | *NO PARAMETER* | 0
    OnPass | elevator_train_watcher | Disable | *NO PARAMETER* | 0
    OnPass | elevator_pushzone | Disable | *NO PARAMETER* | 0
    OnPass | sspl_train | SetSpeedDirAccel | 0.55 | 0.10
    OnPass | sspl_train | SetSpeedDirAccel | 0 | 0.40
    OnPass | sspl_pushzone | Enable | *NO PARAMETER* | 0.40
    OnPass | cart_rollback_relay | Enable | *NO PARAMETER* | 0.40
    OnPass | cart_speed_multiplier | GetValue | *NO PARAMETER* | 0.40
    NOTE: For all path_track outputs (except for the StopSpark output on the bottom elevator path_track) check the "Fire Once Only" checkbox.


    Now if you (and I) have followed this properly, then you'll have a working elevator! There may need to be some tweaking involved; it is a fairly complex system and likely can be simplified some.
    Follow everything from the "Elevator Logic" section down if you'd like a second elevator.
    You can have up to 4 rollback/rollforward zones appearing on the HUD. Any more won't show up, so while you CAN have more than 4 elevators or other rollback zones, I wouldn't suggest it.
    If I have missed some entity logic or this doesn't work somehow, let me know and I'll see if I can debug it. It was quite a bit of work getting all those outputs correct, and I may have missed something somewhere along the way.
     
    • Thanks Thanks x 2
    Last edited: Jan 19, 2012
  2. Kill_the_Bug

    aa Kill_the_Bug

    Messages:
    1,493
    Positive Ratings:
    321
    Broken link for the vmf file - thanks
     
  3. pennsyrail

    pennsyrail L2: Junior Member

    Messages:
    62
    Positive Ratings:
    8
    Could you repost a link to the updated vmf? The link is broken as said above