PolyObjects are sectors created outside of the main map that are spawned with the use of Things, thus making them able to move horizontally and rotate. Additionally, their visibility can be modified through linedef executors. This tutorial shows the setup of a basic PolyObject, usage of their actions, as well as more complex settings.
To create a basic PolyObject, two linedef specials are needed: Linedef type 20 is given to one linedef of a PolyObject to make the game recognize it as such, linedef type 22 is used to specify the settings of the PolyObject. Also required are two Things: the PolyObject Spawn Point and the PolyObject Anchor. These are used to specify where the PolyObject will appear.
The following basic terms appear when making a PolyObject:
- PolyObject sector: The actual PolyObject. It is placed outside of the main map.
- First Line: One of the PolyObject's linedefs (it doesn't matter which one) has to be given linedef type 20. This linedef is called the First Line and it is used to identify the PolyObject.
- Surrounding sector: Around the PolyObject, an additional sector has to be created. This sector needs to have the same properties as the sector that will surround the PolyObject in the actual level, which means same floor and ceiling height, same light level and same flats.
- Control sector or Parameter sector: An additional control sector has to be created to set the parameters of the PolyObject. Otherwise, the game will crash. One of its linedefs has to have linedef type 22.
- PolyObject Anchor: This must be placed anywhere inside the surrounding sector, though it doesn't have to be inside the PolyObject sector itself. This is sort of the focal point for the PolyObject, and all movements will be performed around this point.
- PolyObject Spawn Point: This is where the PolyObject Anchor will appear inside the main map. Use a PolyObject Spawn Point (Crush) to make the PolyObject kill the player when they touch it and it is moving too fast.
- PolyObject ID: Each PolyObject has a separate "identification number" that is used a couple of times. Both Things have this as their angle, and the control sector also has this as its floor height. Any special effects that are applied to the PolyObject are tagged to it with its ID.
Depending on what you want to do with your PolyObject, the Anchor can be placed in different points. For rotating or horizontally moving PolyObjects, it's usually best to have the Anchor in the middle, while swinging PolyObjects mostly have them to the side. For very complex PolyObjects, the Anchor might not even be in the PolyObject itself. To learn the basics of PolyObject creation, it's best to start with the most simple shape, which is a cube with its Anchor in the middle.
Start by placing the PolyObject Spawn Point where you want the PolyObject to appear in the map. The angle of this Thing must be the PolyObject ID. You can choose the ID freely as long as no two PolyObjects use the same ID. For the purposes of the tutorial, assume the ID is 1. Then, create a sector outside the map that is big enough to contain your PolyObject sector. Since our test PolyObject is a cube, this sector should be a square that is bigger than the PolyObject. This is the surrounding sector, so it has to have the same attributes as the sector the Spawn Point is in. You can do this automatically by joining both sectors.
Inside this surrounding sector, create the PolyObject sector. In this case, it would be a simple square. It is very important to make all linedefs face outward. The notches in the middle of the linedef should face the surrounding sector, not the PolyObject sector itself. Now pick any linedef of this newly created sector and give it linedef type 20. This is the PolyObject's First Line. Give it an unused tag, which is assumed to be 1 in this tutorial. In this case, the tag happens to be the same as the PolyObject's ID. This is not necessary – any tag can be used that isn't already used for something else. In the middle of the PolyObject sector, place the PolyObject Anchor. The Angle should be the PolyObject ID, which is 1 in this case. Floor height and ceiling height are also set in the PolyObject sector, simply as floor and ceiling height of the sector.
In its current state, loading this map would crash the game with an error message. This is because the PolyObject is missing a Parameter sector. To fix this, create a new control sector and give on of its linedefs linedef type 22. Tag it to the PolyObject's First Line, so in this case give it tag 1. The floor height of the Parameter sector should be the PolyObject ID (again, 1 in this case).
If you test the map now, it loads properly, but the PolyObject doesn't show up. Walking towards it stops the player anyway, because the PolyObject is there, but currently doesn't have any textures set, making it invisible. The textures are set as the front middle textures in the PolyObject sector, for every linedef separately: PolyObjects are regular sectors, not FOFs, so every linedef must have its own texture specified. Missing textures, however, don't produce glitches of any sort, they just stay invisible. Flats will not be rendered on a PolyObject by default – to change this, check the Solid Midtexture flag on the PolyObject's First Line.
Because PolyObjects use middle textures, the textures are only rendered once by default. For example, if your texture is 128 fracunits high (which is the case with most textures) but your PolyObject is 256 fracunits high, only the upper half will have visible textures. To fix this, you must give every linedef the Repeat Midtexture flag and set the front texture X offsets so the textures repeat to the height of the PolyObject (or as close as possible with the textures used).
Minimizing visual glitches
Although the PolyObject in this tutorial is simple enough so that there shouldn't be any visual errrors, you should bear in mind that even slightly more complicated PolyObjects are sometimes rendered strangely, with invisible sections and inner walls superimposed above outer walls. Changing around a few things about the setup of the PolyObject can help a great deal. One of the best strategies is to choose a different linedef to use as the PolyObject's First Line. This will usually just shift the rendering errors to another part of the PolyObject, rather than eliminating them entirely, but this can still be useful in some situations, such as a place where only a few sides of the PolyObject are typically in view.
The PolyObject actions range from linedef types 480 to 491, and contains horizontal movement, rotation and visibility effects. They are set up like regular linedef executors, in a separate control sector, with a trigger and an executor. The tag of the executor is the PolyObject ID. For continuous movement or rotation effects that should be performed on level load, linedef type 399 can be used as the trigger.
There are four linedef types for horizontal PolyObject movement, each for slightly different purposes and with slightly different effects:
- Linedef type 480, Door Slide, is used for PolyObjects that move a certain distance and then back again, performing this action only once. The effect is controlled through the texture offsets: The front texture X offset determines the speed, the front texture Y offset determines how far it will slide (in the direction that the control linedef is facing), and the back texture X offset determines how long to wait before sliding back, in tics.
- Linedef type 482, Move, works identical to the door slide effect, only that the PolyObject won't move back. This is best used for horizontal platforms that takes the player from one point to another. It is set up the same way, but the back texture X offset is not needed.
- Linedef type 483, Move and Override, is a copy of the aforementioned Move linedef that overrides other actions. If you want this effect to be executed simultaneously to another action, use this instead of linedef type 482.
- Linedef type 488, Move by Waypoints, is the most flexible and least specific movement linedef. With this, you can make a PolyObject have complex movement schemes and also repeat the effect indefinitely. Front texture X offset determines the speed, and front texture Y offset determines the Zoom Tube Waypoint sequence that it will move through. The PolyObject starts at its Spawn Point and will then move to the first waypoint and through all the others. If the Slope Skew flag is checked, it will go through the sequence in reverse, and if the No Midtexture Skew flag is checked, it will go through the sequence in both directions. If the Peg Midtexture flag is checked, it will return to the first waypoint after moving, and if the Solid Midtexture flag is checked with either No Midtexture Skew or Peg Midtexture, it will loop the movement. This is useful for horizontal pushers when combined with the level load trigger linedef.
Note that moving PolyObjects out of the sector they spawn in might lead to rendering glitches.
There are five linedef types for PolyObject rotation, each for slightly different purposes and with slightly different effects:
- Linedef type 481, Door Swing, is used for PolyObjects that rotate around their Anchor and then back again, performing this action only once. If you want a PolyObject to swing like a door would, the Anchor must be placed at the side that will remain stationary. The effect is controlled through the texture offsets: The front texture X offset determines the speed, the front texture Y offset determines how far it will swing in degrees, and the back texture X offset determines how long to wait before rotating back, in tics.
- Linedef type 484, Rotate Right, makes a PolyObject rotate clockwise around its Anchor. If the Anchor is not inside the PolyObject itself, it will rotate around it. The front texture X offset determines the speed, the front texture Y offset determines how far it will rotate in degrees. If the Solid Midtexture flag is checked and the Y offset set to 360, it will rotate continuously.
- Linedef type 485, Rotate Right and Override, is a copy of the aforementioned Rotate linedef that overrides other actions. If you want this effect to be executed simultaneously to another action, use this instead of linedef type 484.
- Linedef type 486 and linedef type 487 work the same as the above two linedef executors, but make the PolyObject rotate counterclockwise instead.
There are three linedef types that control tangibility, visibility and translucency:
- Linedef type 489, Turn Invisible and Intangible, makes a PolyObject turn invisible and intangible. If the Not Climbable flag is set, the PolyObject will only turn invisible, but stay tangible.
- Linedef type 490, Turn Visible and Tangible, makes a PolyObject turn visible and tangible. If the Not Climbable flag is set, the PolyObject will only turn visible, but stay intangible.
- Linedef type 491, Set Translucency, set the translucency of a PolyObject. The floor height determines how translucent it will be, with 0 being completely opaque and 1000 completely invisible.
Setting up an action
As an example of how to set up a PolyObject action, we choose the most versatile and useful, but also the most complicated effect: Move By Waypoints. The first part is similar for all actions, while the setup of the waypoints and the flag usage only pertain to this specific effect. For this tutorial we will choose three waypoints to properly showcase how the effect flags work.
Create a new control sector, tag one of its linedefs to the PolyObject ID and give it linedef type 488. A second line should be either a regular trigger linedef or linedef type 399 if the action should be performed on spawn. Now, set the necessary atrributes in the sidedefs tab of that linedef. The front texture X offset sets the speed, 32 is normal. The front texture Y offset sets the waypoint sequence to use. If this is the first set of Zoom Tube Waypoints in your level, leave it as zero. For each new waypoint sequence, add 1. Each PolyObject should have its own waypoint sequence, as should every zoom tube.
Making a new control sector and giving one of its lines linedef type 488.
Giving another line linedef type 399.
For the purpose of our tutorial, place three Zoom Tube Waypoints on the map, it doesn't matter where. The Angle determines their order. The first waypoint has an Angle of 0, the second an Angle of 1, and so forth. For each new waypoint sequence, add 256 to the Angles of all waypoints belonging to it. The Z offset should be the center of the PolyObject, so if it is 128 fracunits high, the waypoints should be at 64, unless you want the PolyObject to move up and down as well. If you run the map now, the PolyObject will move from its Spawn Point to the first waypoint and then onto the next ones in ascending order, until it stops at the last one. If you want it to start at the first waypoint, simply place the Spawn Point at the same spot so that they overlap.
The flags of the control linedef control how the PolyObject will go through the waypoints. Through using and combining these flags, several possibilities can be exhibited:
|None||From first to last waypoint||Spawn Point → Waypoint 1 → Waypoint 2 → Waypoint 3|
|Slope Skew||From last to first waypoint||Spawn Point → Waypoint 3 → Waypoint 2 → Waypoint 1|
|No Midtexture Skew||From first to last waypoint, then to first||Spawn Point → Waypoint 1 → Waypoint 2 → Waypoint 3 → Waypoint 2 → Waypoint 1|
|Slope Skew and No Midtexture Skew||From last to first waypoint, then to last||Spawn Point → Waypoint 3 → Waypoint 2 → Waypoint 1 → Waypoint 2 → Waypoint 3|
|Peg Midtexture||From first to last waypoint, then directly to first||Spawn Point → Waypoint 1 → Waypoint 2 → Waypoint 3 → Waypoint 1|
|Slope Skew and Peg Midtexture||From last to first waypoint, then directly to last||Spawn Point → Waypoint 3 → Waypoint 2 → Waypoint 1 → Waypoint 3|
|Solid Midtexture||Loops movement (must be used at least with either No Midtexture Skew or Peg Midtexture)||Spawn Point → Waypoint 1 → Waypoint 2 → Waypoint 3 → Waypoint 1 → Waypoint 2 → Waypoint 3 → etc.|
- PolyObjects can trigger linedef executors like any other sector by applying the desired trigger sector special to the PolyObject sector and tagging it to a trigger linedef.
- A special mechanism exists to trigger a linedef executor when the player lands on a PolyObject. To activate it, check the Not Climbable on the First Line (the linedef with type 20). The PolyObject sector needs no sector special or tag. Any trigger linedef whose tag is 32000 plus the PolyObject's ID will be triggered.
- Linedef type 30 makes certain parts of a PolyObject shift back and forth in a wave-like fashion. It is intended to be used for flags that wave in the wind.
- Example WAD: ex_ld020_polyobject.wad
- This example WAD can be played in any gametype. It uses
MAP01, replacing Greenflower Zone Act 1.
- This shows a basic PolyObject that does not perform any actions.
- Example WAD: ex_ld488_polyobject_movebywaypoints.wad