P2C
January 2024
P2C files are used to store the definition of a Portal 2 community puzzle. The format used is similar to that of VMF files, with some small differences.
Concepts
The P2C file format is a simplified representation of a level. It uses a voxel system for blocks and item positioning.
Coordinate System
Locations in P2C files are stored in X Y Z format, where X is right, Y is forward, and Z is up. All coordinates are integers, and represent voxel positions.
Voxels
A level's structure is made up of voxels. Each voxel represents a 1 x 1 x 1 area in the level (where 1 is about equal to one portalable panel). Each voxel may be either solid (a wall) or empty (open space). Additionally, each voxel has 3 sides that can be defined as portalable (white surface) or non-portalable (gray surface). These are the -X, -Y and -Z sides of the voxel. They will be used as the portalable definitions for neighboring voxels (if the specified voxel is not solid and the neighbor is solid).
There is a voxel definition in the P2C file for each point in the map (+1 in each dimension to account for portalable definitions on interior sides), except in the case that the voxel is not solid, and all of its side-sharing neighbors are not solid as well (the three neighboring voxels are each at 1 unit less on one axis - (X - 1, Y, Z), (X, Y - 1, Z), and (X, Y, Z - 1)).
Location
The .p2c source files are located in:
C:\Program Files (x86)\Steam\steamapps\common\portal 2\portal2\puzzles\<steamID>
Replace <steamID> with your normal Steam ID (If you're not on Win 64 bit, then remove the ' (x86' part at the beginning)
The files are named with a random number, so you will need to look in each file to see which one you need.
Compilation
When a 'rebuild' is done in the editor, the .p2c file is exported to Preview.vmf in the steamapps\common\portal 2\sdk_content\maps dir.
Then the standard vvis,vrad and vbsp compilers compile it into Preview.bsp in that dir.
Preview.bsp is then copied to steamapps\common\portal 2\portal2\maps\puzzlemaker and run from there.
Compile params:
vbsp.exe: -entity_limit 1750 -game "c:/program files (x86)/steam/steamapps/common/portal 2/portal2/" "c:/program files (x86)/steam/steamapps/common/portal 2/sdk_content\maps/preview.vmf"
vvis.exe: -game "c:/program files (x86)/steam/steamapps/common/portal 2/portal2" "c:/program files (x86)/steam/steamapps/common/portal 2/sdk_content\maps/preview.bsp"
vrad.exe: -final -staticproppolys -staticproplighting -textureshadows -hdr -game "c:/program files (x86)/steam/steamapps/common/portal 2/portal2" "c:/program files (x86)/steam/steamapps/common/portal 2/sdk_content\maps/preview.bsp"
Exporting to VMF
Once loaded into the editor, in the console use the following command to export it into .vmf file format that can then be loaded into Hammer:
puzzlemaker_export <export_file_name>
Replacing '<export_file_name>' with the name that you want the export to be saved as.
The export will be located in the following dir:
steamapps\common\portal 2\sdk_content\maps
Structure
A P2C file is laid out as follows:
"portal2_puzzle" { // Puzzle Metadata "Voxels" { // Voxel Definitions } "Items" { // Item Definitions } "Connections" { // Connection Definitions } }
Note that each string in the file is surrounded in quotes (e.g. "Voxels").
Puzzle Metadata
The puzzle metadata block contains information about the puzzle. It looks like this:
"AppID" "644" "Version" "14" "FileID" "0x0000000000000000" "Timestamp_Created" "0x000000004FAAF4AD" "Timestamp_Modified" "0x000000004FAAFB4B" "CompileTime" "15.000000" "Title" "My level" "Description" "A deceptively hard test chamber." "PreviewDirty" "1" "ChamberSize" "2 2 4"
The values are as follows:
Key | Description |
---|---|
AppID | Always "644" (the app ID of the publishing tool), even in mods. Unknown use. |
Version | The version of the editor the map was last saved in. Loading a map saved in an older editor version may cause conversions to be performed.
|
FileID | For published maps, the workshop item ID. Used when re-publishing to update the existing item instead of creating a new one (though this often breaks). |
Timestamp_Created | The time the puzzle was created, in Unix Time.. |
Timestamp_Modified | The time the puzzle was last modified, in Unix Time.. |
CompileTime | The duration of the last compile. Unknown use. |
Title | The name of the puzzle. |
Description | The description of the puzzle. Can include line breaks. Quotes are escaped with \"
|
PreviewDirty | Set to 1 to indicate that the preview map is outdated, displaying the "view is not current" message. |
ChamberSize | The size of the test chamber, in voxels, width x depth x height (X Y Z). |
Voxel
Each voxel in the Voxels collection looks like:
"Voxel" { "Position" "0 0 0" "Solid" "1" "Portal0" "1" "Portal1" "1" "Portal2" "1" }
Key | Description |
---|---|
Position | The position of the voxel, in the format "X Y Z". |
Solid | Whether or not the voxel is solid ("1") or empty space ("0") |
Portal0 | Whether or not the -X side of the voxel is portalable ("1") or not("0"). |
Portal1 | Whether or not the -Y side of the voxel is portalable ("1") or not("0"). |
Portal2 | Whether or not the -Z side of the voxel is portalable ("1") or not("0"). |
Item
Each item contains basic information about index, type, location and orientation, with further information depending on the item type (described below). An item looks like:
"Item" { "Index" "0" "Type" "ITEM_ENTRY_DOOR" "Deletable" "0" "VoxelPos" "1 0 0" "LocalPos" "0 0 0" "Angles" "-90 -90 0" "Facing" "0 0 0" }
Key | Description |
---|---|
Index | The index of the item in the puzzle. |
Type | The type of item. |
Deletable | Whether the item can be deleted ("1") or not ("2"). Doors and the observation room must not be deletable. |
VoxelPos | The world position of the item (the voxel the item resides in). |
LocalPos | |
Angles | The orientation of the item, in Z X Y order. Rotations are clockwise around the specified positive axis. |
Facing | The orientation of freely oriented objects (currently only the turret and the dropperless reflective cube). |
Connections
Connections trigger an action on an item from another item. They have a sender and receiver (both item indices), as well as a type. They look like:
"Connection" { "Sender" "3" "Receiver" "1" "Type" "CONNECTION_STANDARD" }
Key | Description |
---|---|
Sender | The index of the item that sends the signal. |
Receiver | The index of the item that receives the signal. |
Type | The type of connection |
Connection types
Type | Description |
---|---|
CONNECTION_STANDARD |