Portal 2

Portal 2

Not enough ratings
Hammer Testchamber Tips
By Wizzator
Here are some tips for making Hammer maps. This guide assumes you already know the basics of Hammer and you already have Portal 2 Authoring Tools installed.
   
Award
Favorite
Favorited
Unfavorite
Disclaimer
This Guide assumes you have already installed Hammer and you know the basics of how to use it. These are tips for making certain test elements.

This Guide is unfinished. Please be patient for updates. I'm just releasing it now so that what I've got right now can still be useful. Do let me know if there are other test elements I have not listed/covered that you would like to know how to make.
General Helpful Information
1 "puzzle-maker square" is 128x128 units
1 floor tile is 32x32 units
So I would recommend keeping the grid size to 32x32 most of the time when using the brush tool.

Holding Alt while resizing or moving an object allows you to change it by 0.1 units.

If I refer to the void or "Leaking Errors", what I mean is that the Source Engine requires maps to be fully enclosed in brushes. If entities are outside of the map, the map will fail to compile. Make sure there are no gaps in your map.
Elevators
If you want to start/end with an elevator in your map, you will need to follow the steps below:

Entrance Elevator
  1. You will need a func_instance. Place it some distance away from your entrance, as it is very large. (TIP: to make it easier, move it a little once placed so it snaps to the grid)
  2. Under VMF Filename, type in: "instances/turbine_elevator/arrival_elevator_a4_base.vmf"
  3. Shift+drag the instance in one of the 2D Viewports (labled "top (x/y)", "side (x/z)" or "front (y/z)") away and back to the exact same spot it started at. This will duplicate the instance.
  4. Change the VMF Filename of either instance (it doesn't matter which one) to "instances/turbine_elevator/arrival_elevator_a4_logic.vmf".
  5. If there is a door that's after the elevator, make sure that it is named "@entry_door", so it will open without anything being added. You will still need a trigger_once after the door to close it.

Exit Elevator
This is done in a very similar way, however, make sure that:
  • The door is named "@exit_door".
  • The elevator instances are named "instances/turbine_elevator/departure_elevator_a4_base.vmf" and "instances/turbine_elevator/departure_elevator_a4_logic.vmf" respectively.

Videos and Spawning Inside the Elevators
Another func_instance is needed in order for the elevators to work properly. The file name is "instances/transitions/arrival_departure_transition_ents.vmf"
To fix a problem with the elevator videos and departure elevator, you will need to follow this guide: P2 Hammer: Fixing Elevator Videos & Other Elevator Things
After following this guide, set the "$arrival_video" and "$departure_video" to any video of your choice. Type in "media/VIDEO NAME".
Obviously, you don't put in "VIDEO NAME", but instead one of the following videos:
  • animalking
  • aperture_appear_horiz
  • aperture_appear_vert
  • aperture_logo
  • bluescreen
  • faithplate
  • fizzler
  • hard_light
  • laser_danger_horiz
  • laser_danger_vert
  • laser_portal
  • turret_colours_type
  • turret_dropin
  • turret_exploded_grey
If you want a preview of the videos, you can find the folder at
"<path>\steamapps\common\Portal 2\portal2\media"
PeTI Voting Screen End
To allow the map to be publishable to the Steam Workshop, you will need another func_instance

Implementing the Instance
First, create a func_instance and place it near the end of your map. Put this in the "out of bounds" space where it will be out of the way.

Next, set the VMF Filename to "instances/p2editor/global_pti_ents.vmf". Set the Fix Up Name to something appropriate. I recommend something like "peti_end".

If you have an elevator, place a trigger_once inside the elevator shaft. If you don't, place a trigger_once or other input at the end of the map (or just use something you already put at the end of your map)

Set the input to:

  • My output named: OnTrigger (or other respective output)
  • Targets entities named: peti_end (or whatever you named the func_instance)
  • Via this input: instance:@relay_pti_level_end;Trigger (This will show up as an error. Ignore this)
  • With a parameter override of: <none>
  • After a delay in seconds of: Usually 0 but in some cases it can be longer
  • Fire only once: Checked

When testing, nothing will happen but you can still find out if it worked.
The Developers' Console will show the name of your map e.g. mapname_01
Buttons
Cube-and-button based testing is an important tool for science, even in a dire emergency. But to be able to use such an important tool, we need to learn how to make one. You could use the entity tool and slap in a prop_floor_button and call that done, it doesn't look good with it floating or clipping into the floor. The best way to do it is as follows:

(Steps 1 and 2 are optional depending on whether you want it level with the floor.)

1. Cut a 128 x 128 square out of your floor.
2. Using one of the side 2D viewports, decrease the height of this chunk by 8 grid squares.
3. Open \maps\instances\p2editor\Button File Here.vmf. These include:
  • floor_button_white_intact
  • floor_button_black_intact
  • floor_cube_button_white
  • floor_cube_button_black
  • floor_ball_button_white
  • floor_ball_button_black
Note: You only need one!
4. Select everything (excluding the func_instance_io_proxy) and copy it with Ctrl+C.
5. Paste it into your map (with Ctrl+V) and move it into the hole in your floor or where you want it to go. (You may need to set the grid size to 8.)
6. Go into the buttons Outputs and delete whatever is currently there and add your own logic.
Cube Droppers
There are two ways to do this.

Default Iris Dropper
These are the default droppers you see throughout the game. Please note that this part does not account for overgrown-style maps. These ones are simple and require only 1 func_instance.

First, Create a 128x128 hole in your ceiling with the clipping tool, making sure you have at least 384 units of space above it.
Next, create a func_instance and set the VMF Filename to "instances/gameplay/item_dropper.vmf"
Set the Fix Up Name to something appropriate, for example: "cube_dropper_1"
Change the values as follows:

$rusted = 0
$use_new_skin_method = 1
$cube_type = 0 - 3
$indicator_lights = <name of indicator lights>
$item_fall_straight_down = 0
$disable_autorespawn = 1 or 0
$paint_power = 0
$item_type = 0

$cube_type:
0 = Normal
1 = Companion
2 = Laser Cube
3 = Edgless Cube (Ball)

Finally, to allow the cube to drop, set the input to:
  • My output named: OnPressed (or other respective output)
  • Targets entities named: cube_dropper_1 (or whatever you named the func_instance)
  • Via this input: instance:cube_dropper_relay;Trigger (This will show up as an error. Ignore this)
  • With a parameter override of: <none>
  • After a delay in seconds of: Whatever you like
  • Fire only once: Unchecked

Now test it to make sure it works as expected and change any values if needed.

Custom Cube Droppers
Use this tutorial to create cube droppers the don't use the default item dropper model. This is especially useful for vactube cube droppers or underground (Old Aperture) cube droppers.

1. Using the entity tool, create a prop_weighted_cube and configure the properties to your needs. Give it an appropriate name, for example "cube_1"
2. Create a point_template. Place this inside the prop_weighted_cube
3. Name the point_template something like "cube_1_template".
4. Go into the point_template's properties and set "Template" to "cube_1" or whatever you named the cube.
5. Decorate where you want the cube to spawn by adding various props.
6. Add a button or trigger and add two outputs:
One for the point_template called "ForceSpawn" with a small delay, e.g. 0.01
Another for the cube called "Dissolve" with no delay.
7. Run the map and test it.

If you want a cube visible inside the dropper as well, you will need to do it slightly differently.
1. Create a box in front of where you want the cube to fall with the trigger texture.
2. Press [Ctrl + T] to turn in into a func_detail and change the class name to trigger_multiple.
3. In the flags tab, uncheck "Clients" and check "Physics Objects".
4. Create a filter_activator_name next to the trigger.
5. Give it a name like "dropper_filter" and set the Filter Name to the name of the cube you want to drop.
6. Back in the trigger, set Filter Name to the name of your filter you just created.
7. Go to Outputs and add:

  • My output named: OnTrigger
  • Targets entities named: cube_1 (or whatever you named the prop_weighted_cube)
  • Via this input: Add Output
  • With a parameter override of: OnUser1 !self:Dissolve::0:1 (Just copy & paste it)
  • After a delay in seconds of: 0.00
  • Fire only once: Unchecked

8. Go back to the button that drops the cube. Change "Dissolve" to "FireUser1".
Excursion Funnel (Tractor Beam)
1. Create a 128x128 hole in your wall using the clipping tool where you want it to go.
2. Open "tbeam_frame_black/white" found in the folder: "\maps\instances\p2editor."
3. Copy the frame using "Ctrl+C"
4. Paste it into your map using "Ctrl+V" and move it so it aligns with your hole.
5. Create a prop_tractor_beam, give it a name and set "Use 128 model" to Yes. (This would be [H] Model and Model if you're using TeamSpen's Hammer Addons)
6. Move it so that it aligns with the hole. it will appear larger than the hole, ignore this.
7. Set the grid size to 8 and move into the wall by 1 grid square.
8. Add logic to turn the beam on/off or toggle it's direction (optional)
To reverse, use "SetLinearForce" to 250 for forwards and -250 for backwards.
9. Add walls with the Nodraw texture behind the prop_tractor_beam to avoid Leaking Errors*

*Leaking is where the map isn't fully enclosed and there are entities in the "void."
Aerial Faith Plates
"This next test involves the Aperture Science Aerial Faith Plate. It was part of an initiative to see how well test subjects could solve problems when they were catapulted into space. The results were highly informative: they could not. Good Luck!"

In this section, I will tell you how to make the faith plates.

1. Cut a 128x128 hole in your floor.
2. Select that cut piece and cut a 32x128 hole in that with the short end facing in the direction you want to launch the player/object.
3. Move the second cut piece into the wall by 32 units and retexture with the nodraw texture.
4. Create a prop_dynamic and set the World Model to "models/props/faith_plate.mdl" Give it a name, like faithplate_1_prop.
5. Setting the grid size to 8, create a new brush above the prop that's about 32x96x8 so that it fits above the plate part. Use the trigger texture.
6. Press [Ctrl+T] to turn that brush into a func_detail and change the Class to trigger_catapult. In the Flags tab, make sure Physics Objects is checked.
7. Create an ambient_generic and place it above the trigger. Name it something like faithplate_1_sound and set Sound Name to "World.CatapultLaunch"
8. Where you want the player to end up, create an info_target and name it to faithplate_1_target or similar.
9. Back in the trigger_catapult, we need to change some values:
  • Set Launch Target to the name of your info_target.
  • Set Player Speed and Physics Object Speed accordingly.
    Physics Object Speed should be slightly less than Player Speed, and lower speed values make the player go higher.
10. Now it's time to add some Outputs to the trigger:
  • My output named: OnCatapulted
  • Targets entities named: faithplate_1_prop (or whatever you named the prop_dynamic)
  • Via this input: SetAnimation
  • With a parameter override of: angled or straightup if you need.
  • After a delay in seconds of: 0.00
  • Fire only once: Unchecked
  • My output named: OnCatapulted
  • Targets entities named: faithplate_1_sound (or whatever you named the ambient_generic)
  • Via this input: PlaySound
  • With a parameter override of: <none>
  • After a delay in seconds of: 0.00
  • Fire only once: Unchecked
Fizzlers & Laserfields
Fizzlers
The Aperture Science Emancipation Grill is very useful to keep cubes out of a specified area and to stop portals.

1. Cut a hole in both of your opposite walls. It should be 32 units wide and its height must be a multiple of 128, but otherwise doesn't matter.
2. Using the nodraw texture, create some brushes in the hole matching the layout shown below.
2. (Cont.) Select them all and press [Ctrl+T] to make them a func_detail. Press [Enter] and close the dialogue box. (Note: It will not protect entities from the void!)
3. Create a prop_dynamic with the Model Name of "models/props/fizzler.mdl"
4. Copy, paste and rotate it so that it's mirrored in the other hole
5. Create a brush with the nodraw texture that's 128 (no matter the height) by 2 by the width of your fizzler so that it fills the area. (You will need to set the grid size to 1 when setting the depth.)
6. Depending on the size of your fizzler, you will need to cut the geometry 64 units from the left and right (You don't need to do this if your fizzler is 128x128 or less.)
7. Texture it as follows:
Search for "fizzler"
If your fizzler is less than 128 wide, use the texture that ends after the word "fizzler" and skip to the end of this step.
If it isn't, use the left, right and centre versions accordingly.
Press Fit in the texture applier tool for all sides.
If your fizzler is taller than 128, NOW stretch it to fit. (Disable Texture Scaling Lock when doing this.)
8. Select all of your fizzler geometry and press [Ctrl+T] to make them a func_detail and change the Class to trigger_portal_cleanser. Set Visible to Yes
9. In Flags, check Physics Objects unless you only want it to clear portals.

Making It Turn On/Off
COMING SOON

Laserfields
COMING SOON

Deadly Goo
By this point, I'm assuming you have the hole for it already.

1. Create a brush that fills your hole but slightly shorter. Use the trigger texture.
2. Use the texture application tool and select only the top face of this brush. Choose one of the many slime textures.
3. Select the whole object and press [Ctrl + T] to turn it into a func_detail.
4. Set Class to trigger_hurt
5. Change the values:
- Zero Damage Force: Yes
- Damage: 100000000
- Damage Cap: 100000000
6. In Flags, check Physics Objects.
7. In Outputs, add a new one:
  • My output named: OnHurt
  • Targets entities named: !activator
  • Via this input: Kill
  • With a parameter override of: <none>
  • After a delay in seconds of: 0
  • Fire only once: Unhecked

Test it out and try dropping a cube into it.
Gel Droppers
(!) This section has nothing in it... for now
Fun things to do with the Aperture Science Sentry Turret
(!) This section has nothing in it... for now
Indicator Lights
Making the Trail
Tips for creation:
Turn Texture Lock off (turn back on again after!!!)
Keep grid size at 8.

Creation
1. Search "indicator" in the texture finder. Use the ones that end in "..._wall".
2. Use the overlay tool and place the corner variant next to the input (e.g. button)
3. Use the straight one and align the bottom to the corner light. Extend it in a 2D viewport.
4. Use corners at corners (obviously)
5. Select them all at once and give them a name.

The Logic
With Checkmark/Cross
1. Use the entity tool to place a prop_indicator_panel. A 32x32 area behind it should be set to the Nodraw texture.
2. Move it away from the surface by 1 unit.
3. Name it something like "exit_indicator_panel". You may change it depending on what it is showing a relationship to.
4. Set "Indicator Lights" to the name of your lights.
5. Change the other settings to as desired if you want the timer variant.
6. In your button etc. add the following logic:
  • My output named: OnPressed (or other respective output)
  • Targets entities named: exit_indicator_panel (the name of the prop_indicator_panel)
  • Via this input: Check
  • With a parameter override of: <none>
  • After a delay in seconds of: 0.00
  • Fire only once: Unhecked
  • My output named: OnUnPressed (or other respective output)
  • Targets entities named: exit_indicator_panel (the name of the prop_indicator_panel)
  • Via this input: UnCheck
  • With a parameter override of: <none>
  • After a delay in seconds of: 0.00
  • Fire only once: Unhecked

Trail Only
You may not want a big ol' sign.
1. Add an env_texturetoggle.
2. Set "Target Brush(es)" to the name of your trail.
3. Name it the same as the trail but with "_toggle" at the end.
4. Add the following logic.
  • My output named: OnPressed (or other respective output)
  • Targets entities named: exit_indicators_toggle (the name of the env_texturetoggle)
  • Via this input: SetTextureIndex
  • With a parameter override of: 1
  • After a delay in seconds of: 0.00
  • Fire only once: Unhecked
  • My output named: OnUnPressed (or other respective output)
  • Targets entities named: exit_indicators_toggle (the name of the env_texturetoggle)
  • Via this input: SetTextureIndex
  • With a parameter override of: 0
  • After a delay in seconds of: 0.00
  • Fire only once: Unhecked

Indicator Lights Etiquette
Below is an image showing the correct way to make your indicator panels.


  1. Use corner variant from the input.
  2. Always use an indicator panel for the exit door and always place it on the wall.
  3. If going onto a wall, no corner is needed unless it immediately changes direction. In this case, make sure it is in the centre of the direction change.
  4. Avoid having a corner going directly into an output, but it's fine if it's unavoidable or actually looks better like that.
  5. If you have multiple of the same input, keep the offset of the trails the same each time.
  6. Always use an indicator panel if multiple inputs lead to an output.
  7. Treat intersections like normal corners.
I forgot to mark it on the image, but don't combine two trails that lead to the same output. Just place them next to each other.
Logic Gates. (e.g. AND)
General Etiquette
1 Comments
BartFasterThanU 23 Apr @ 9:15am 
This is a great guide! But I think you should also say how to make panels, stairs and so on.