Portal_Define is a parameterized static linedef special designed for UDMF which defines a new portal. All kinds of portals are supported by this special. The special alone doesn't also apply the portal; they are rather placed on sector surfaces and linedefs by using the UDMF properties portalfloor, portalceiling (for sectors) and portal (for linedefs).
- portal ID: specify the ID (number) of the new portal. This value will be used to identify this portal and will be referenced in portalfloor, portalceiling and portal. The value must be non-zero, positive and unique. Eternity will log a warning in the console if you accidentally reuse a portal ID in another Portal_Define linedef.
- portal type: specify the type of the portal. Only the linked portal is interactive; the rest are merely visual. The two-way portals are those which allow the destination area to have a corresponding portal pointing back to the source area. Valid types are:
- anchor line ID: this only applies and is necessary for portal types 3-5 (anchored and linked) and must be 0 for types 0-2. It is the line ID of the linedef which acts as an "anchor" for this linedef. The portal you define will have its view offset and rotation (if applicable) calculated by the position difference between the anchor and the current linedef.
- Z parameter: this parameter has different meanings depending on portal type. If portal type supports it, it can be positive or negative. For types 0-2 it must be zero. For types 3-4 (visual anchored portals), it specifies the visual Z offset: how much the target area is displaced from the source area vertically. For type 5 (linked portals), since Z offsets aren't currently supported, it specifies the plane Z offset, which changes the position of the linked portal plane Z from its usual position, and is useful for cross-portal elevators. See the details section for more info on this.
- flipped: only applies for types 3-4 (visual anchored portals); for the rest it must be 0. If this parameter is 1, it causes the anchored portal to rotate view by 180 degrees, and is useful if the source and target lines have the same angle but not the same orientation.
Set a Portal_Define special on a linedef next to the area that gives information about the portal. For plane, horizon and skybox portals the front sector must have certain properties -- see the details section. For anchored and linked portals, you must specify a corresponding line ID of the anchor linedef. The anchor linedef doesn't need its own portal special set on it; it just holds the anchor line ID.
Each Portal_Define linedef comes with its own unique and positive portal ID. If you set up a duplicate ID, you'll receive an error (with a beep) in Eternity, and if you open the console, it will tell you what free ID you can use instead.
After you define the portal, you place it in sectors by using their portalfloor and portalceiling UDMF properties, and on linedefs by using their portal property. For the two-way portal types (4-5), the ID set up in Portal_Define will produce the portal pointing from the source to the anchor line. But you will also have access to the negative version of the portal ID, which will produce the portal pointing back from the anchor to source. So for example if you have portal ID 1 pointing from area A to B, you can also apply portal ID -1 which will point from area B to A.
To aid in easily finding out the ID, for anchored portals a useful practice is to set both portal ID and anchor line ID to the same value. For simple portals you can use some portal ID out of the range of line IDs in your map, so that it won't have the same value with line IDs.
Portal type details
Plane and horizon portals
These are the simplest portals to define. The drawn flats and light effects are defined by linedef's front sector.
Skybox portals require an EESkyboxCam (doomednum 5006) thing to exist in linedef's front sector.
Non-interactive anchored portals
These portals render the area next to the anchor line relative to the current line as if it were part of the same design, but only visually, without gameplay interaction. This can be used for decorating. As such, it has less overhead and more freedom than the linked portals. Mainly, the view can be rotated from the source area to the target area, and the angle of rotation is determined by the angle difference between the source and anchor linedef. You can add 180 degrees to the rotation by setting flipped to 1. In addition, you can also add a vertical (Z) offset to the view between source and anchor by setting a nonzero value to the Z parameter (needed because you can't easily define a Z difference just from the linedefs in the map).
These are the portals that allow two areas to connect both visually and physically. It's subject to more restrictions than visual portals: distances between areas, if connected by different portals, must be consistent. It's still possible to make up paradoxes, but not directly. Also, rotations and Z offsets are not (currently) supported.
A concept that exists in linked portals but not visual anchored portals is the plane Z (vertical position). It only applies to sector portals (appearing on floors and ceilings) and represents the height where the portal appears, independent from sector's surface heights. Whenever the sector's surfaces move, the portal remains at the same Z position, and can be concealed (and inaccessible) if the sector plane gets closer to the viewer than the portal. This contrasts with the visual anchored portals, where the portal's plane Z moves together with the floor or ceiling. This feature is needed to make elevators that go through portals possible. Such elevators would also use the attached surfaces feature.
The Z parameter offsets the position of the initial plane Z. Where the initial plane Z is initially placed depends on the front sectors of both the current line and the anchor line:
- If the anchor line's front sector average between floor and ceiling height is greater than current line's front sector's, the plane Z will be the current line front sector's ceiling height.
- If the anchor is lower than the current sector, then the plane Z will be at front sector's floor height.
- If both the source and anchor line are placed in equal height sectors, the plane Z will also be at front sector's floor height.
Since each linked portal has its own plane Z, multiple sector portals connecting the same two areas, but at different Z coordinates, must have separate portal IDs (and thus be defined by separate Portal_Define linedefs). This is not an issue for linedef-placed portals: plane Z bears no meaning for them, so all linedef portals connecting the same two areas can originate from the same Portal_Define ID.
Since linked portals don't currently support view angle offset, the flipped parameter has no effect, and must be 0.
Under UDMF, when using this special, it's not required for linedef linked portals to have a free sector behind them. You can connect 1-sided lines and they will become passable. The restriction is that if you use 1-sided lines, the source line must lead exactly into one target line. This restriction is not in place if you always use 2-sided lines for wall portals.
If the area beyond a 1-sided linedef portal has a different height from the front sector's, then the upper and lower textures of the 1-sided line will be rendered, as if it were a 2-sided line. This feature needs to exist for polyobject portals, explained below.
For most situations, where you want two-way communication between areas, you can just use Line_QuickPortal on two linedefs instead of Portal_Define and having to remember and set portal IDs. It works both for static portals and polyobject portals (explained below). It's not sufficient for edge portals, but in their case all you need is to reuse the portal ID used already for sector surfaces.
Polyobject line portals
You can place wall portals on polyobjects which will lead into rooms which appear to move with the polyobject. Due to design constraints, the portals on the polyobject have to be 1-sided, but the room inside can have 2-sided portals. Since some portals are 1-sided, the polyobject line portals must lead exactly into the room line portals.
Beware that the polyobject origin box -- the sector where it's placed in the editor -- must belong to the same portal group as the sectors where the polyobject will run. To ensure that, you can either use a tunnel sector joining the origin box to the main area, or join the sectors. But if you do the latter, make sure that the immediate origin box sector is not the same as the one in the target area. Just put a second sector farther from the polyobject which is joined with the main area.
Edge portals are set using the linedef lowerportal and upperportal boolean properties, which copies the sector portal behind the linedef to the lower or upper part of the linedef. Do not use portal on the linedefs with edge portals -- that property is meant for linedef's middle part portals. The other side of the portal, in the room, will use line portals with the portal property set as usual.