Portal 2

Portal 2

27 ratings
p0rtalmaster's Hammer Guide Series Part 07/19
By The Sojourner
Hello and welcome to part 07/19 of my series of mini-guides, designed to help you learn perhaps what is the biggest part of the Portal 2 Authoring tools: Hammer.

For a super-quick version of this series, please check out my other guide, Hammer for the Flustered.
   
Award
Favorite
Favorited
Unfavorite
Panels, the Planks of Tomorrow
Panels are a huge part of Portal 2, even more so than in the original game. They can be used to raise things, lower things, and create angled surfaces (including those classic stairs) without the need for wedges.



Surprisingly, it doesn't take much to set one up either. All you need is a prop_dynamic with the panel arm model and a func_brush for the panel top, as well as a few logic entities (more specifically logic_auto and logic_relay, the latter of which isn't strictly necessary, but really helps with organizing your I/O). Before you begin, I seriously recommend studying the panel animations and think about where and how they were used in the game. Typically, there are going to be four basic versions of an animation: an "in" animation, an "out" one, and idle (ending) animations for both of these.

The panel arm models come with their own sounds for each animation, which you can use the model viewer to preview (it's not the one in Hammer, but elsewhere in the Portal 2 Authoring Tools), so that in many cases you won't need to use an ambient_generic (or several) for sounds.

Here's the recipe for a single panel:

1) Create a prop_dynamic, give it a name and set its model to anim_wp\room_transform\arm64x64_interior.mdl
→ TIP: The large 128×128 models can be found under anim_wp\telescope_arm_128\...

2) Create a 64×64 brush, 2 units thick (small panel), or a 128×128×4 (or 128×128×8) brush (large panel). Texture the bottom, top and sides accordingly....

3) Place the brush directly on top of the panel arm's top, turn it into a func_brush and name it. Set its parent to the name of your prop_dynamic (so that it will move with the panel arm).

4) Create a logic_auto and set its output as in the image below. The slight delay (0.10 - 2.00 seconds) is needed to ensure that it takes effect.

5) Create two logic_relays: one to enable your panel (deploy it) and one to disable it (retract it) and set these I/O:



Once you've got something that works, it's time to rinse and repeat as needed for your map. Use separate names if you don't want all your panels to act as one (they need only differ by a number). Just beware that too many moving panels (more than 20-30) is likely to cause lag on some systems.

Now all you have to do is hook them up to a button or similar by setting the button's outputs to trigger the enable and disable relays.

Shortcut: If you want to save some time when parenting the func_brushes (panel tops) to the prop_dynamics (panel arms), you can type <panel arm name here>,panel_attach or <panel arm name here>,panel_top into the Parent keyvalue of your func_brush (yes, that is a comma, and there are no spaces — it's whitespace-sentitive). This will tell your panel top what panel arm to attach to and where to put it. Then you will no longer need to use a logic_auto and can therefore save on entities. It's likely that Valve used the other method of panel parenting due to existing bugs in previous Source games.
An Alternative Method
Some animations only have an "in" or an "out" version, with no other animations. The panel arms can still be controlled however. Proceed as above, but instead of doing the last step, use these alternate I/O:



To get this to work, you need to set the "Default Animation" to whatever animation it is you want to use, and also (critically) set "Hold Animation" to "Yes."

This alternate method also happens to be quite effective when dealing with floor buttons or laser catchers/relays, where I/O can be a lot less predictable (and faster) than pedestal buttons.

Flipping Panels


The basic entity that makes a flip panel work is func_door_rotating. That and func_door are very useful entities in any game, including Portal 2. They are brush entities, meaning that you'll need to first create a brush.

For a flip panel, I recommend using a brush that's 4 units thick and 4-8 units smaller on each side than the space you wish for your panel to take up. Common properties of the flip panel:



The default rotation is along the Z axis, which is perfect for wall panels, but if you want it on a floor or ceiling, you'll need to check either "X axis" or "Y axis" under the flags tab (as an aside, sometimes these look nice on wall panels too, as long as they're parallel to an axis).

Controlling them is easy: just use the "Open" and "Close" inputs. One fun thing about all of this is that you have a lot more control over the speed at which the panels move as well as which sounds they make than you had in PeTI.
Rail Platforms
Seen in the Portal 2 maps with the companion cube (vertical) and the laserfield (horizontal), the basic entity behind the motion of these platforms is func_movelinear. Some of the basic properties:



As you've probably already seen in the in-game editor, there are two different ways to set these up: one is to oscillate back and forth like the horizontal ones do in Valve's maps. The other is to move the rail from one side to the other like the vertical ones do in Valve's maps. The properties (keyvalues) of the func_movelinear are more or less the same. However the I/O are different in either case. For the non-oscillating platform, we have just:



If you want the platform to stop instead of start once the button is hit, simply swap the outputs. You'll also need to use a logic_auto to get the lift moving. For the oscillating platform, we also need two math_counters to hold our numbers of speed and direction. That's done by setting the "Initial Value" keyvalue of one of them to the func_movelinear's speed, and the other one to 1. Here's the I/O setup for everything:



Of course the func_movelinear is not enough. You'll also need a prop_dynamic, which is to be parented to the func_movenlinear. The model to use is models/anim_wp/arm_interior_192/arm_interior_128.mdl (the 192 model works well too):



Optionally, you can also add inputs to the model to make it do it's little dancey when it's moving (in which case you'll need to give it a name).
Piston Platforms
Oddly enough, these only came up once in the entire standard singleplayer Portal 2 canon (here's a hint: Valve gave you the VMF of their work so you could understand how to make them). There are a couple more in the coop Art Therapy course though.

This is logically the most complex standard testing element to create for such a simple function: it moves objects up or down by a certain amount. Here's what you'll need to make one from scratch (and believe me, they are best made from scratch):
  • A trigger_hurt and a trigger_portal_cleanser to un-jam the lift.
  • 5-6 prop_dynamics. These will be the components of the lift. The models to use are:
    • models/props_bts/straight_piston_base.mdl,
    • models/props_bts/straight_piston_mid.mdl,
    • models/props_bts/straight_piston_end.mdl, and
    • models/props_bts/straight_piston_tip.mdl (1-2) for the piston conponents, and
    • models/anim_wp/arm_interior_192/arm_interior_128_paneltop.mdl for the top.
These do NOT need a name, as they will only be parented to:
  • 2-4 func_doors, depending on the height that you want to raise the player to. These DO need names and should have a square base (16×16 is typically good enough). Their heights are generally around 64 or 128 units (in my example, I have heights of 72, 120, and 64).
  • A func_movelinear for the top of the lift. This is what will be making the sounds.
This is enough for if you're making a platform that will be activated by a pedestal button or something out of the player's reach. If you're planning on hooking this up to a floor button or laser catcher/relay or similar though, you'll also need:
  • 2 logic_relays (mostly for easy organization)
  • A number of logic_branches: 2 if you have 2 func_doors, 4 if you have 3 func_doors, and 6 if you have 4 func_doors. These are necessary to ensure that the piston platform moves properly and plausibly for if the player activates the button (or what have ye) at any time (including between the movement of piston segments).
First, I'll show you the basic assembly of the lift (let's say it is to go up/down by 256 units for this example):



1) We need 3 func_doors for this example. Check the heights of the func_doors, and shorten the bottom one until the total height of all the func_doors is 256 units.

2) Check the "door silent" flag on all the func_doors.

3) Parent each of the piston pieces to the func_doors, and parent the platform top to the func_movelinear.

4) Parent each of the func_doors to the one below it (e.g. parent the top part to the next lower part). The bottom func_door shouldn't have a parent.

5) Set the remaining properties for the func_doors and func_movelinear as follows:




6) Align everything into either a "closed" or "open" position, depending on the needs of your puzzle. Here's a screenshot of both positions:



7) Finally, set these I/O:




And that's how to do a lift with a pedestal button. It needs to lock while the lift is moving to prevent any button mashing that the player might do.

If you have a floor button or laser catcher/relay or similar as your input device, follow steps 1-6 as above, but the last step is a little different. I'll show you a basic flowchart of the logic behind setting up a piston platform with this kind of input device (this variation assumes the lift starts lowered):



Notes
  • I/O #1-8 should be pretty straightforward. The blue things are logic_relays.
  • The trigger_hurt and trigger_portal_cleanser act as one and so there's no separate box for the trigger_portal_cleanser.
  • Initial values for the logic_branches are "1" for all the "up" detectors and "0" for all the "down" detectors.
  • Where the I/O says "Set value to 0/1," use the SetValue input with parameter 0 (false) or 1 (true).
  • "when opening" means to use the OnOpen output, and likewise with "when closing" (use OnClose).
  • "Open" normally means "move up" and likewise "Close" normally means "move down."

The general idea here is that the func_doors form a chain as before (I/O #25-28), where each one triggers the next when opened or closed. Then each time a func_door opens or closes, this is noted by a logic_branch (I/O #12, 13, 15, 17, 18, 20, 22 and 23) so that when the button is pressed at any time, weirdness won't happen (e.g. if the player steps off of the button while the lift is halfway up).

Hopefully this flowchart should guide you in setting up the I/O for the lift. I won't be giving out screenshots here, as the I/O is too complex for that.
Platform and Panel Installation
To install a piston platform, you'll need to make a hole that's 128×128 units and 192 units deep. Then place the piston platform components into the hole. A similar thing applies to panels, only the dimensions are different. The hole needs to be wide enough to fit in your panels when they are recessed, and 128 units deep.



To install a rail platform, you'll need to do a little more:

1) Create five worldbrushes, one for the center (back), two for the top and bottom, and two for the ends. Texture all of these accordingly.

2) Create a prop_static and set its model to models/anim_wp/arm_interior_192/motionplatform_rail_128.mdl. Replicate it as needed. This will be the rail that the platform moves along.

3) Place your rail platform components against the wall and check to make sure that everything lines up as in the following screenshot:


Mistakes to Avoid & More Information

  • Bad panel animations. Study some of the animations and think about where in the game they were used before you try to use them for yourself.
  • Not knowing about the animation system that Portal 2 uses. There are two basic methods: SetAnimation and SetDefaultAnimation (with a short delay), or "Hold Animation" and SetPlaybackRate. You should only need these two.
  • Forgetting not only to parent (attach) the panel top to the panel arm, but also to send an input to the panel top telling it where to attach to. Remember, the panel top needs to be a func_brush so that it can receive input.

More information from the VDC Wiki:
Master Guide List
Please note that there are still some works in progress. This section will be updated as I finish more guides for you!

You are currently viewing part 07/19 in the series.

| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |

Previous Guide (Aperture Science Vital Apparatus Vents, from scratch)
Next Guide (about the Aperture Science Aerial Faith Plate)

Please feel free to leave a well-reasoned question or comment below. Either I or a qualified Test Chamber Associate (you'll know because they make all the good maps on the workshop) will respond. If your question or comment is not well-reasoned, I recommend reading over my guides again until you understand them 100%. No further information is required here or will be provided, and you will become an excellent Test Chamber Designer — using Hammer!

9 Comments
Solinoxia 3 Jan @ 6:14am 
thanks for this!, I had some difficulty wrapping my head around the logic I'd need for making a 3-stage piston platform work properly with a floor button. Followed the logic in your flowchart and it works perfect now.
Catradora sustains me 29 Jul, 2021 @ 6:52am 
What are the I/Os for a piston platform that starts raised?
The Sojourner  [author] 4 Feb, 2020 @ 2:40pm 
Yeah, I think it's because the Portal 2 developers liked to use vertical rail platforms wherever possible instead of piston platforms, unlike many PeTI tests — more economical (fewer entities in Hammer are needed). Piston platforms are used in the coop campaign a fair bit though.
jarmge 22 Jan, 2020 @ 5:23pm 
So Piston Platforms came up in only one test in the singleplayer campaign? There's the second test of the itch and the test where wheatley wants you to solve it 10 times as fast, that's two. Just saying. Good guide btw! :) :steamhappy:
Jaja Steele 14 Jul, 2019 @ 10:32am 
this guide is a bite old but , i dont see anything to change the Axis of the prop_door_rotating (see Flipping Panels part) :/ (i looked in "flags" tab and nothing talk about axis)
EndOfPortal 24 Nov, 2017 @ 2:31pm 
Hi, I made a moving platform (oscillating platform). I add 2 math_counter and a floor button. I followed strictly your instructions but when the button is pressed, the platform doesn't move. I have an idea how its works (I'm a novice with Hammer) but I do not see the solution.
The Sojourner  [author] 24 Jul, 2016 @ 6:36pm 
@Σ.Person, Good question. It's a bit more complicated since the standard panel arm animations don't really allow for special angles since they really weren't used much in the main campaign aside from 45° angles in special cases. There actually is a model of 4-panel arms used in the in-game editor all the time ( models/props_ingame/arm_4panel.mdl ), but sadly it doesn't have its own sounds, meaning you'll have to add your own. Also the panel animations aren't as lively as you might get with the standard arm, but there's nothing you can do as a mapper about that (as a modeler, on the other hand... maybe...). However, if you really want or need panels to make a 30° or 60° angle (or 45° from the floor or ceiling perhaps), then feel free to use them in place of wedges.
Person Meetup 23 Jul, 2016 @ 7:27am 
What about angeled panels, like the ones for the in-game editor?
the weird guy 28 Jun, 2016 @ 3:25pm 
my dad [witch is a computer master] dosen`t know about hammer