Kailey's Interior Door Guide
This is a mildly advanced guide for modders that assumes familiarity with Tiled, Content Patcher, and map modding fundamentals such as the difference between Map Properties and Tile Properties.
Interior doors, such as the one in Figure 1, are interactive map elements with hardcoded behaviour (see InteriorDoor.cs). There are three types in the base game: the Standard Door, Clinic Door, and Saloon Door1. All three can be used in custom maps, but completely new types are not possible without C#. The existing types can, however, be reskinned via Content Patcher to allow functional, customized interior doors.
1The Saloon Door is actually two doors. See Notes, Exceptions, and Hardcoding.
Getting Started With Interior Doors
An interior door has four elements:
- The translucent door sprite, found on Maps/townInterior
- The door animation, found on LooseSprites/Cursors
- The Tile Property
Action Door
- The Map Property
Doors
These four elements are covered in order below.
townInterior Door Sprite
This is the sprite that is placed on your map. The bottom tile is placed on the Buildings
layer, while the top two tiles are placed on the Front
layer. See Figure 1 for an example.
In the case of the Clinic Door, the topmost tile is empty; it must still be placed on the Front
layer regardless of this.
If all three door tiles are not placed on the correct layers, the door will not work. Offset layers such as Buildings2
or Front-1
will not work; only the original Buildings
and Front
will.
See Figure 2 for the location of all three doors on townInterior.
Cursors Door Animation
The animation for the door opening, found on Cursors, plays when an NPC or player interacts with the door. The first frame of the animation is drawn behind the corresponding doors at all times when they are closed; this is why the doors do not appear translucent in-game despite appearing that way when viewed in Tiled.
All of this happens via hardcoding in InteriorDoor.cs; modders do not need to worry about making it work beyond what is explained in this tutorial. See Figure 3 for the location of all three doors animations on Cursors.
Tile Property: Action Door
The Tile Property Action Door
must be placed on the Buildings
Object Layer of your map, on the same tile position as the bottom of the door. Note that Object Layers and Tile Layers are different things; Object Layers contain TileData instead of tiles, and are marked with pink icons in the Layers Tab. See Figure 4 for an example.
For a door that can be opened at any time, leave the property as simply Door
as shown in Figure 4. For a door that requires two or more hearts with an NPC to open, such as most bedroom doors in the game, append the NPC’s name after Door
(e.g, Door Abigail
).
Map Property: Door
All maps with interior doors on them must have the Map Property Door
with the following data structure:
Door [XPosition YPosition TilesheetID TileID]
Field | Explanation | Type |
---|---|---|
XPosition | The X coordinate of the Action Door Tile Property | int |
YPosition | The Y coordinate of the Action Door Tile Property | int |
TilesheetID | The name of the Tileset that the door is on, as it is identified in Tiled, for this specific map. This can be different from the asset name (townInterior). Look at the Tilesets window in Tiled to identify this; in the example on Figure 5, it is “1” (highlighted by the red arrow). | string |
TileID | The Tile Index of the bottom tile of the door sprite on townInterior. To find this, click ‘Edit Tileset’ (highlighted in Figure 5 by the red star), and then in the new tab that opens click the tile whose Index you are trying to find. The Tile Index will be displayed in the information panel on the left (highlighted in Figure 5 by the blue arrow).
The TileID of the Standard Door is |
int |
The four entries (XPosition, YPosition, TilesheetID, TileID) of the Map Property must be repeated for every interior door on the map. For our example of Pierre’s Shop, there are three interior doors to account for. This comes together for a final result like so:
Doors 13 11 1 120 20 11 1 120 14 16 1 120
See Figure 6 for a breakdown of this data structure.
With the door sprite, Tile Action, and Map Properties set up properly, your map should have working interior doors that both NPCs and players can use. See Common Problems if needed.
Notes, Exceptions, and Hardcoding
- The Cursors animation of the Saloon Door (Right) is hardcoded to always be a mirrored version of Saloon Door (Left). This can be used to your advantage to make double doors without needing a second mirrored asset, but limits any other use.
- The Clinic Door is hardcoded to always be mirrored if it is on tile
10,5
of any map. This hardcoding is how the double door leading to Harvey’s room is handled, but there are no guardrails preventing this from applying on other maps. Make note of the placement of any Clinic Doors to avoid accidentally mirroring them. - Doors must have tiles on the
Back
layer underneath them to function. There should, however, always be something on theBack
layer in a location that the player can walk, so this is unlikely to cause problems.
Custom Interior Doors
Because custom interior doors are just reskins of the base-game interior doors, rather than separate entities, the interior door setup from the previous section must be carried out. This method also comes with the following limitations as a result:
- Maximum three types of custom interior doors can be on the same map, due to there being three base-game door types to replace.
- A base-game interior door that is used as a base for a custom door cannot appear on the same map as itself (e.g. you can’t turn the clinic door into a custom door and also use the clinic door on the same map).
- Doors can exclusively be one tile wide and three tiles tall. A double door can be faked using the Saloon Doors, but a truly two or more tile wide door is not possible.
- Patching both townInterior and Cursors every time the player enters or leaves your custom map can be resource intensive.
- The custom door will not be visible in Tiled, only in-game. See Figure 7.
The process of creating a custom interior door has four steps:
- Place base-game doors on your map where the custom doors will go
- Create a custom door asset
- Patch Cursors with your custom door
- Patch townInterior with your custom door
These four steps are covered in order below.
Place Base-Game Doors
Choose where on your map you would like custom doors, and then choose which base-game doors you will be replacing. Place them accordingly, following the guide above. The base-game doors may look strange in place on your map (Figure 7), but we’ll be changing their look in-game soon.
Create a Custom Door Asset
Your custom door tilesheet must follow the size and layout of the door animations on Cursors. It must be 64 pixels wide, 48 pixels tall, and depict four frames: the door closed, the door partly open, the door more open, and the door fully open. Each frame must be 16 pixels wide and 48 pixels tall, with the ‘closed’ frame first and the ‘open’ frame last. Any other size or order will not work.
Patch Cursors
Using an EditImage
patch to Cursors, replace the door animation that corresponds to the base-game door placed on your map with your custom door tilesheet:
{
"LogName": "Kailey Door Edit- Cursors",
"Action": "EditImage",
"Target": "LooseSprites/Cursors",
"FromFile": "assets/Kailey_CustomDoor.png",
"FromArea": { "X": 0, "Y": 0, "Width": 64, "Height": 48 },
"ToArea": { "X": 512, "Y": 144, "Width": 64, "Height": 48 },
"PatchMode": "Replace",
"When": {
"LocationName": "Kailey_DoorExampleMod_DoorMap"
},
"Update": "OnLocationChange",
"Priority": "Late"
},
Your FromFile
should be the name of your custom door tilesheet.
Your FromArea X
and Y
should specify where on the tilesheet your custom door begins. Your Width
and Height
should always be 64
and 48
respectively. In cases like this example where the entire custom tilesheet is being used, starting at 0,0
, this line can be optionally removed.
Your ToArea X
and Y
will depend on which vanilla door you are editing (table below). Your Width
and Height
should always be 64
and 48
respectively.
Your patch mode should be Replace
, as Overlay
will likely leave parts of the original door visible.
Your When
condition should be set to only apply the edit when the player is on the map where the custom door is, so as to avoid editing every other instance of the base door.
An Update
rate of OnLocationChange
is necessary due to the locational condition above.
A Priority
of Late
helps prevent other mods (eg recolours) from overriding your edits and reverting the door to the base-game version.
The ToArea
of the base-game doors on Cursors is as follows:
Door Type | ToArea X,Y |
---|---|
Standard Door | 512,144 |
Clinic Door | 576,144 |
Saloon Door | 640,144 |
Patch townInterior
If townInterior is not patched with EditImage
, the transparent version of the base-game door will still be visible in-game. This patch only needs the first frame of your custom door tilesheet, so the Width
of the ToArea
and FromArea
patches is 16
, while the rest of the patch is similar:
{
"LogName": "Kailey Door Edit- Towninterior",
"Action": "EditImage",
"Target": "Maps/townInterior",
"FromFile": "assets/Kailey_CustomDoor.png",
"FromArea": { "X": 0, "Y": 0, "Width": 16, "Height": 48 },
"ToArea": { "X": 384, "Y": 16, "Width": 16, "Height": 48 },
"PatchMode": "Replace",
"When": {
"LocationName": "Kailey_DoorExampleMod_DoorMap"
},
"Update": "OnLocationChange",
"Priority": "Late"
}
The ToArea
of the base-game doors on townInterior is as follows:
Door Type | ToArea X,Y |
---|---|
Standard Door | 384, 16 |
Clinic Door | 96, 384 |
Saloon Door (Left) | 384, 368 |
Saloon Door (Right) | 400, 368 |
After a successful patch to both Cursors and townInterior, your doors should appear in game. See Figure 9.
Troubleshooting and Common Problems
Doors Not Appearing
If your edits to the base-game doors are not appearing in game, perform a patch export on townInterior and Cursors to see if your edits are applying.
If your patch exports show the edits are applying, but your doors still don’t appear in game:
- Remove any vanilla tilesheets from your assets folder before running the game, especially townInterior and Cursors. Content Patcher will use the local versions of these tilesheets in your assets folder instead of the versions in Content/Maps, which prevents your changes from being seen.
If your patch exports show the edits are not applying:
- Check for other mods that may be overriding your edits. Run a patch summary on Cursors and townInterior to see who else is editing them.
- Confirm that your
When
conditions are set to what you intended. Test without the conditions and see if the edit applies to every door as a quick check- if it works without your conditions, they’re the problem. - Check that your doors open in-game. If they were improperly set up on the map, the Cursors assets won’t be visible and the door won’t work.
Ghost Doors
If there is a transparent overlay of the base-game door visible, it means that your Cursors EditImage
patch was successful but your townInterior EditImage
patch was not. See Doors Not Appearing.
Custom Doors on Existing Maps
Adding a custom door to an existing map using a map patch? Remember that the Doors
Map Property must apply to the parent map, and must include all interior doors on the parent map. Consider using Content Patcher to edit the parent map’s Doors
property, and adding your data via the append text operation to avoid overwriting the existing data. Also, remember that your EditImage
changes will apply to all instances of the same door type on the map; use a door type not found on the parent map to avoid replacing the existing doors.