So I noticed there's a lot of confusion regarding RotateTypes and how they work. I'll try to explain each type in as much detail as possible based on what I've come to understand each type does. For those who don't know me, I used to be the creator of the Object Sprites Patch (now disbanded), so I've had some experience mucking around with these bad boys. I'm also an Updater on Mantis, though that's not really relevant here.
For the completely uninitiated: an object's RotateType property defines how its sprites are loaded and displayed when the object is placed in the game world. This tutorial won't be touching on advanced concepts like SubTypes, Markers and Scripting, which can further alter the way an object looks in-game. Rather we are going to look at RotateTypes at the most basic level and explain what, in fact, setting an object's RotateType to a certain type does exactly.
We'll be glossing over quite a few subjects which may seem like advanced modding concepts to some readers out there. Basically, a bit of experience on how mods are created and function in Prison Architect is required for you to understand what's being talked about. I won't be going into much detail for a lot of things since the purpose of this tutorial is addressing RotateTypes in specific, after all.
So without further ado, let's jump right in there.
How and where to set an object's RotateType
As of Alpha-24, there are currently two ways to do this.
The first way, as visible in the banner of this tutorial, is defining it in the objects.spritebank file. The objects.spritebank file is basically a compendium of every sprite used by vanilla objects in the game. It is most likely automatically generated when the game is compiled, and has a tendency to change with every new Alpha release.
It should be noted that the only changes you should make here are changes to objects that already exist. If you're going to try to add sprites to this list, add them to the end of the list. Even so, as of Alpha-24, we have a much better alternative for adding new sprites which we'll discuss next. Basically, you shouldn't really be touching this file anymore unless you like having to update your mod every time a new Alpha is released. If you do choose to alter this file with a mod, be sure to include the whole file in your mod. Not just your changes.
As stated earlier, the file has a tendency of changing with each new Alpha. Which tends to lead to hilarious shenanigans like objects using the wrong sprite when the file was changed in a now outdated mod, such as the infamous "My trucks are now giant toilets!" bug. I'm only mentioning it for educational purposes really, since this is how it used to be done. And it serves as a nice example for how sprites in the game are defined (x and y coordinates, width and height, and so on), and which RotateTypes existing objects are using.
The second way, which I highly recommend you use instead, is by defining it directly in the materials.txt file. As of Alpha-24, not only is it possible to add new objects to the game, but you can also create a custom sprites.png file which houses any custom sprites you create for your mod. You can then set the object's sprite's location, dimensions and such directly using said file as the source.
This way should be far more compatible with future Alpha releases, since you only need to (re-)define any objects you want to create or change. Once support is added for multiple sprite.png files being used at once (hopefully), your mod will also be more compatible with any mods that make changes to, possibly the same, objects and sprites as well.
The only downside to this method is that you do actually have to create a custom sprites.png file, since (AFAIK) there's no way to use the original objects.png or people.png files as a base when defining the sprite's properties directly in materials.txt. Basically, even if you only want to change an object's RotateType, you'll have to copy-paste the original sprites into a sprites.png file and redefine the sprite's position and dimensions as well. Needless to say, you can visually alter the sprites themselves as well then, if you so desire.
Now you know where and what to look at, it's time for you to remember the following pointers:
- An object's RotateType only needs to be defined once.
- An object's sprite dimensions directly influences the behavior of RotateType.
- An object's sprite position defines the "starting point" of the RotateType.
- The dimensions of the object itself do NOT influence the behavior of RotateType.
To elaborate on that last pointer, the sprite will be scaled and possibly moved with an offset to try and fit the object's size as best as possible. See the example below of a Chair with a Width of 4 added. Its actual behavior when rotating remains unaltered. Needless to say, it's best to have an object's dimensions and its sprite's dimensions be the same whenever possible (or have the same width/height ratio at least).
This may all sound a tad confusing and obscure at first, but once we get into explaining the actual Types themselves you should come to understand why these things are so important.
The RotateTypes explained
Just a few more pointers to keep in mind before we start, for clarity's sake:
- A sprite with a width of 1 and a height of 1 (w 1 h 1) is 32x32 pixels in size. By extension, a sprite with "w 2 h 1" is 64x32 pixels in size, and so on. A sprite's width and height will henceforth be referred to as its dimensions.
- Similarly, a sprite's x and y properties make jumps of 32 pixels in your image file, along their respective axis (right and down). Basically, a position of x 0 y 0 would point to the top-left corner of your image file. A position of x 5 y 4 would point to coordinates (160,128), or 160 pixels to the right and 128 pixels down, and so on. A sprite's x and y coordinates will henceforth be referred to as its position.
- Ideally, an object can face in four directions and looks differently for each facing. We'll be calling these front, back, left and right, in accordance with the direction the object is facing. Front if it's facing us (or looking "down"), back if it's facing away from us (or looking "up"), left if it's facing to the left, and right if it's facing to the right.
- When posting an example screenshot of an object's facings, the facings will always be shown in a circle around a point facing outwards. In other words, the front facing will always be at the bottom, the left facing on the left, the back facing at the top, and the right facing on the right. You'll see what I mean when you're watching the example screenshots.
One of the simplest RotateTypes. RotateType 0 only requires a single sprite, namely the front sprite. RotateType 0 will then automatically generate the back, left and right facings by rotating the front sprite around its center.
The default Box actually uses RotateType 0. If we make it placeable through modding in-game, you can see the RotateType in action.
Ignoring the fancy sticker on the Box for a moment, you can see the game simply takes the front sprite and quite literally just spins it around to make each of the missing facings automatically. As you may also notice, it doesn't look very good.
In practice, RotateType 0 is mostly used for objects that can't be directly placed or rotated by the player and only require a singular facing (namely the front one). Example objects include the Box, the Delivery Truck, most of the tools used by your staff and prisoners, and so on. In theory, it could also be used for placeable objects and limit the amount of drawing you have to do. However, as seen above, even for a simple box the automation looks quite fugly.
RotateType 0 will always rotate the front sprite around its center. For instance, if we try it on the Visitor's Table (w 6 h 4, or 192x128 pixels):
The result would look like this:
When using RotateType 0, the sprite's position should point to the top-left corner of the front sprite, and the sprite's dimensions should be set to the front sprite's dimensions.
RotateType 1 requires three sprites, namely the front, back and left facings. It will then automatically generate the right facing by mirroring the left facing horizontally.
Both the Single and Double Sofa use RotateType 1. When placed in-game, they look like this:
As you can see, the right facings are simply the left facings mirrored horizontally.
In practice, RotateType 1 can be used for any object that requires a unique back and sideways (left and right) sprite. The only thing automatically generated is the right facing, but in nearly all cases this will look pretty good. RotateType 1 is mostly used for people, but is also used for a handful of objects.
From left to right, the order of your sprites should be front, back and left. In the case of non-square sprites, the left facing should be placed directly next to the back facing. The bottom of the left facing must be at the same height as the bottom of the front facing.
For example, in case of the Weightsbench (w 2 h 3):
Or the Double Sofa again (w 4 h 2):
When using RotateType 1, the sprite's position should point to the top-left corner of the front sprite, and the sprite's dimensions should be set to the front sprite's dimensions.
RotateType 2 requires two sprites, namely the front and left facings. It will then automatically generate the right facing by mirroring the left facing horizontally. The back facing will look the same as the front facing.
Both the Jail Door and Large Jail Door use RotateType 2. When placed in-game, they look like this:
Despite what you might think, the right facing is in fact a mirror of the left facing. If we look at the Visitor's Table for instance, which also uses RotateType 2:
You can see the mirroring in action:
In practice, RotateType 2 is mainly used for doors or any object that doesn't require a unique back facing. It's worth remembering that despite what you might think, the right facing is still automatically generated as a mirror of the left facing. As illustrated above.
From left to right, the order of your sprites should be front, then left. In the case of non-square sprites, the left facing should be placed directly next to the front facing. The bottom of the left facing must be at the same height as the bottom of the front facing. Same as RotateType 1.
When using RotateType 2, the sprite's position should point to the top-left corner of the front sprite, and the sprite's dimensions should be set to the front sprite's dimensions.
RotateType 3 requires three sprites, namely the front, back and left facings. It will then automatically generate the right facing by mirroring the left facing horizontally, similar to RotateType 1.
The only difference between RotateType 3 and RotateType 1 is that non-square objects are not tilted on their sides for the left facing.
The Vending Machine uses RotateType 3. As you can see, the left facing maintains its upright position (64x96 pixels). In-game it looks like this:
In practice, RotateType 3 is used for objects that need to retain their front sprite's dimensions. Notable examples include the Vending Machine, as shown above, as well as the Filing Cabinet and Guard Locker.
From left to right, the order of your sprites should be front, back and left. When using square sprites, RotateType 3 functions the same as RotateType 1. As such, it should only be used when necessary, such as in cases as described above.
When using RotateType 3, the sprite's position should point to the top-left corner of the front sprite, and the sprite's dimensions should be set to the front sprite's dimensions.
Easily the simplest RotateType. RotateType 4 only requires a single sprite, namely the front sprite. Every facing will look the same as the front facing, or in other words, the object can't be rotated.
The Sprinkler uses RotateType 4. When placed in-game, it looks like this:
In practice, RotateType 4 is mostly used for objects placeable by the player that shouldn't be allowed to rotate for some reason. Notable examples include the Workshop gear, the Laundry Machine, and a handful of other special objects. Most likely scripted objects use this RotateType to prevent any wacky shenanigans from happening, for instance.
Whether or not the game's engine actually recognizes the object as being rotated when you press the middle mouse button I cannot say, but visually your object will look the same at every facing. Scripters will have to figure out if anything is actually happening "under the hood". For the sake of this tutorial, this information isn't really important as we're only looking at the visual effect.
When using RotateType 4, the sprite's position should point to the top-left corner of the front sprite, and the sprite's dimensions should be set to the front sprite's dimensions.
RotateType 6 (& 5)
This is where things get complicated.
RotateTypes 5 and 6 function exactly the same, as far as I can tell. However, RotateType 6 is the only one that's actually used for an object in the game, namely for CCTV Cameras. If anyone can find if there's a difference, feel free to share. In any case, I'll just be talking about RotateType 6 from this point on as that is the only one that's even used.
RotateType 6 requires five sprites, namely the front, back, left and right facings as well as the toolbar icon. However, the order in which said sprites are positioned are pretty... Well, backwards. Literally.
CCTV Cameras use RotateType 6. However, since they are a scripted object, I won't be posting an example picture this time. Depending on how they move, their sprites are replaced by the diagonal versions, which are probably added as SubTypes by the game engine. It seems RotateType 6 is only really used for the ghost preview of this object.
I will, however, elaborate on how RotateType 6 selects the sprites it uses if you were to use this RotateType on a normal object. Basically, if the CCTV Camera were a normal object, the facings would be selected as such with RotateType 6 (tripled size for clarity):
Yeah. From left to right, the order of your sprites should be left, a space equaling the size of your sprite, front, a space, right, a space, back and finally the toolbar icon.
On top of that, when using RotateType 6, the sprite's position should point to the top-left corner of the toolbar icon, and the sprite's dimensions should be set to the toolbar icon's dimensions. RotateType 6 will then look to the left of the toolbar icon's position to select the facings in the positions indicated above.
In the case of non-square sprites, you're on your own. I never experimented with non-square objects while using this RotateType. You'll have to figure out the spacing required between each sprite yourself if you do.
It's worth noting that the diagonal sprites you see in the example above would thus not be used. However, you still need to include the spacing between each of the facings, again as demonstrated above.
For clarity's sake, the image above could be replaced with this one and still function the same:
Most likely there were plans at some point to use this RotateType to select diagonal rotations as well when rotating an object. The infamous broken Wooden Door sprite is actually caused by still having these diagonal sprites available in the objects.png file. Its RotateType was changed, but the sprites were never altered to match, as seen below.
If you've been paying attention so far, and watch how the Door is displayed in-game when rotated, you should be able to guess the Door's new RotateType from this sprite alone. Consider it your homework!
As for RotateTypes 5 & 6, in practice they're not really used at all. RotateType 5 is never used, and RotateType 6 is only used for CCTV Cameras. But, as mentioned earlier, it only seems to be used for the ghost preview really. Once the object is placed, scripting seems to take over and adjusts the camera's sprite while it's scanning around.
Nevertheless, they can theoretically still be used by modders. I actually made use of RotateType 6 to "fix" the wooden door sprite in my Object Sprites Patch. You could make it your homework to try and do the same. When you do, you may notice the sprites are actually in the wrong positions now as well.
Other than that, the only time you would want to use this RotateType is when you want to make an object that has a unique sprite for each of the four facings, with a unique toolbar icon as an added bonus (even though the ToolbarSprite property can already do this... Ah well). If you use your imagination you could probably think of a few things where it might prove useful.
Everything in this tutorial comes from personal knowledge and experimentation. It was written during Alpha-24, and as such, any information is subject to change in future Alpha releases. If anyone wants to format this properly and post it on the official wiki or elsewhere, they have my permission to do so freely.
Other than that, thank you for reading. Hope you learned something, and happy modding!