Since the use of a precalculated BSP for rendering forces vertical level geometry to remain constant, it is impossible to move a structure on the X and Y axes in vanilla Doom. ZDoom addresses this problem by providing PolyObjects. A PolyObject typically consists of a group of connected one-sided lines contained in a single subsector.
Creating simple polyobjects
Making a polyobject is fairly simple, though it may seem hard at first, once you get the hang of it you will be able to crank them out in no time.
|First we need the actual map. We will make a sliding door polyobject (arguably the easiest kind), so we'll need two rooms with ceiling heights of 192 and a middle corridor (which is where the polys will appear) with a ceiling of 128. All floors are at height 0.|
|Next you need to construct the polyobjects. You should place them in a 'dummy' sector or another inaccessible place because the space they occupy on the map will usually still be considered blocked out, resulting in unwanted situations such as a swinging door that leaves an invisible barrier when opened. Furthermore, the holding sectors will be automatically hidden on the automap.
Note that the polyobjects are 'solid' columns of void composed of only 1-sided linedefs.
The lines marked in yellow should be Polyobj_StartLine which takes three arguments, the polyobject number, mirrored polyobject and the sound it makes while moving (defined in SNDSEQ). For the top poly you should use polyobject number 0, and for the bottom you should use number 1 (though any number would do). Since these polys will mirror one another (their actions will be the same, only in reverse, poly1 will open to the right and poly0 will open to the left for example) you should place the opposite poly number in the second field. Sound isn't important to us now, so just leave it zero.
|Now you have to place polyobject anchors and start spots. These will determine where the polyobjects actually get placed on the map. First place the anchors, which have DoomEdNum 9300. These should be placed within the polyobjects as you have them drawn on the map (or close to the edge), like in the image. The only important thing about the anchors is their angle, which should correspond to the polyobj number. So the anchor at the top has angle 0 and the anchor under it has an angle of 1.|
|Next we place the start spots. These are placed in a similar way to the anchors; in a place where you want the polyobject to appear in game relative to the anchor. So in this case we placed the anchor in the center of the poly, so we want the start spot placed in the center of where we want the poly to appear, as shown in the image. Start spots have the DoomEdNum 9301, 9302 or 9303:
|Here we have a completed setup. Note that since ZDoom 2.5.0, you can have complex geometry for polyobjects and you can make them move anywhere you want in the map. Previous versions had strict limitations on what a polyobject could be and do. This example being already old, it shows a very simple setup.|
|Finally, you probably want the polyobjects to actually open. This is quite simple, just give the wide sides of the polyobjects the Polyobj_DoorSlide special, with the arguments 0, 32, 128, 64, 105 which are polyobj number, speed of movement, angle, distance to move and delay before the polys shift back to their original position (in tics, 105 is 3 seconds (35 tics per second)). You need not worry about polyobject 1 in this case because it will mirror whatever polyobject 0 does. That's it, you're all done!|
Creating advanced polyobjects
While the simple polyobjects explained above are enough in most cases, sometimes they are not enough. What if you want a see-through polyobject, for example? You will then need to use two-sided linedefs. However, the engine cannot create the polyobject automatically in these cases, so you need to use Polyobj_ExplicitLine on each line of the polyobject.
- Build your polyobject in a holding sector as before, but make them into a self-referencing sector (both sides of the polyobject will belong to the holding sector).
- Each line of the polyobject is marked with Polyobj_ExplicitLine. For rendering order, you can use the value 1 on all of them, since this parameter is a leftover from Hexen's original implementation.
- If you want some of the lines of the polyobject to be active, you need to give them a lineid. In Hexen format, this is done with one of the Polyobj_ExplicitLine parameters; in UDMF it is one of the linedef properties. You will then need to have an ACS OPEN script calling SetLineSpecial) on the chosen lineid to give it a different special.
- Since the polyobject is now two-sided, make sure it actually has a middle texture!
- The holding sector should have the same floor and ceiling heights as the destination sector; not because the engine requires it, but because it will make it much easier for the modder to set the vertical offsets of the polyobject textures. Use the "lower unpegged" flag if you want the polyobject to appear on the ground.
- Give the polyobject lines the "3D middle texture" flag to give it finite vertical collision box. Note that the polyobject's holding sector will be used as a reference for checking if there is room above or below it, not the sector it is actually in!
For specials related to PolyObjects, see the following topics:
For scripting with PolyObjects: