Tutorial: Adding a Custom Location (CP)(1.6)
Introduction
Rokugin here with a quick tutorial on adding a custom location to Data/Locations
using Content Patcher.
Github repo can be found here, with the download for the whole mod here.
Getting Started
This tutorial assumes you have SMAPI and Content Patcher installed.
I suggest using VSCode for automatic formatting and real time syntax highlighting.
If you're on Windows or Mac make sure you have file extensions enabled.
Inside your Mods folder create a folder for your mod, for the sake of this tutorial and my example I'll be calling mine [CP] Add Custom Location Example
but you can name it whatever you like.
Inside your new folder create two text documents, rename one to manifest.json
and the other to content.json
, accepting any dialogue boxes about changing the file type.
For organization, I like to add a folder named assets
where I provide further organization for my asset files.
Manifest
More information about the manifest can be found here.
Here's my manifest for example:
{
"Name": "Custom Location Example",
"Author": "rokugin",
"Version": "1.0.0",
"Description": "Example of adding a custom location.",
"UniqueID": "rokugin.excustomlocation",
"UpdateKeys": [],
"ContentPackFor": {
"UniqueID": "Pathoschild.ContentPatcher"
}
}
- Name
- The name of your mod.
- Author
- Your name/username.
- Version
- Your mods version.
- Description
- A brief description of what your mod does.
- UniqueID
- Usually a combination of
Author.NameWithoutSpaces
. I try to make this easy to type for testing purposes.
- UpdateKeys
- Used to provide update notifications to users when you update your mod, more info here.
- ContentPackFor
- This is used to tell SMAPI what framework your content pack is for, in this case you can set this like mine.
Content
The content.json is where I'll be placing all my code for this example, more info about Include
can be found here.
We'll start with the basics:
{
"Format": "2.4.0",
"Changes": [
]
}
- Format
- Indicates which version of CP your pack is for, usually should be the latest which can be found on the author guide here.
- Changes
- The changes block is where all our patches will go.
Now we can add Loading
the map into Maps/
:
{
"Format": "2.4.0",
"Changes": [
{
"LogName": "Load tmx into Maps",
"Action": "Load",
"Target": "Maps/{{ModId}}_ExampleRoom",
"FromFile": "assets/rokuginExampleRoom.tmx"
}
]
}
- LogName
- This field is useful for debugging purposes. If there's a problem with a specific patch SMAPI will return the
LogName
instead of a generic error, making it easier to troubleshoot problems.
- Action
- The
Action
field informs what kind of patch this is, in this case we're trying toLoad
a file into the content pipeline.
- Target
- The content we're trying to make changes to, in this case we're trying to
Load
a new asset, so we want our target to have a unique name. {{ModId}}
is a CP token, which is marked by the double curly braces on each side{{ }}
, that automatically inserts our modsUniqueId
in its place for us. More tokens can be found here.- Because we're
Loading
a map, ourTarget
has to start withMaps/
and since we want our asset to be unique in order to make sure we don't overwrite any other assets, we use the{{ModId}}
token and then we want to fill the rest of the asset name with something that will make it easy for us to know what it is. - My final
Target
will be converted by CP to:Maps/rokugin.excustomlocation_ExampleRoom
, but you don't have to manually type out yourUniqueID
in CP, you can just use{{ModId}}
.
- FromFile
- This field is a file path starting from where your content.json and manifest.json are, since I placed my tmx inside my assets folder, I have to include that in my path.
- Your path can only go down into folders contained within your mod, there's no way to go up to other mods or the unpacked contents.
Up next is editing Data/Locations
to add our custom location to the game:
{
"Format": "2.4.0",
"Changes": [
{
"LogName": "Load tmx into Maps",
"Action": "Load",
"Target": "Maps/{{ModId}}_ExampleRoom",
"FromFile": "assets/rokuginExampleRoom.tmx"
},
{
"LogName": "Add custom location to Locations",
"Action": "EditData",
"Target": "Data/Locations",
"Entries": {
"{{ModId}}_ExampleRoom": {
"DisplayName": "Example Room",
"CreateOnLoad": {
"MapPath": "Maps/{{ModId}}_ExampleRoom"
}
}
}
}
]
}
- EditData
- This patch allows us to make modifications to data assets, including adding new content to them.
- Data/Locations
- This is the data asset that holds all the games locations.
- Entries
- This object holds the objects we want to patch into our
Target
.
{{ModId}}_ExampleRoom
- This is our entry key/locations internal name. In order to add a new entry to the data, we want to use a unique name here so we use
{{ModId}}
again.
- DisplayName
- Not actually required but highly recommended to add to your location data. The name that will be most likely to be seen in game, if any.
- CreateOnLoad
- This is the object that creates the location when the save is loaded.
MapPath
is the asset weLoaded
our map into earlier, specifically the value of theTarget
field in ourLoad
.
With just this, you have a map that you can debug warp into.
Lastly we can make a patch to a map to allow us to enter our location the same way you do other locations in the game:
{
"Format": "2.4.0",
"Changes": [
{
"LogName": "Load tmx into Maps",
"Action": "Load",
"Target": "Maps/{{ModId}}_ExampleRoom",
"FromFile": "assets/rokuginExampleRoom.tmx"
},
{
"LogName": "Add custom location to Locations",
"Action": "EditData",
"Target": "Data/Locations",
"Entries": {
"{{ModId}}_ExampleRoom": {
"DisplayName": "Example Room",
"CreateOnLoad": {
"MapPath": "Maps/{{ModId}}_ExampleRoom"
}
}
}
},
{
"LogName": "Add warp to custom location",
"Action": "EditMap",
"Target": "Maps/Town",
"AddWarps": [
"100 14 {{ModId}}_ExampleRoom 9 16"
]
}
]
}
- EditMap
- This patch allows us to make edits to a map.
- Maps/Town
- This is the map I chose to place my warp on.
- AddWarps
- This field allows you to add one or multiple warps to a map at once, separated by commas
,
. - Each warp uses the format of
"<fromX> <fromY> <toLocation> <toX> <toY>"
. - Adding warps this way allows you to use tokens, however if you want to add the warps directly to maps in Tiled then you can't use tokens. So in order to add this warp to a map in Tiled I would have to type out
rokugin.excustomlocation_ExampleRoom
.
Using Data Layers and Debug Mode I can see the warp to my custom location and the coordinates matching what I put in CP.
You can use the wiki for location data here to learn about more of the fields available for your locations.