When you are generating a creature using a Blueprint, its art is determined by what we call 'Art Maps', they help map certain properties of a creature to the correct image, in the simplest term it's a binding of their 'slug' (all-lower-dash-case-name) to a file location, but it also supports forms and shiny information.
In general, Art Maps are set using a module, but you can also in the PTR settings add a custom World Art Map, exactly the same thing, just localized to that specific world!
You can find the Quick Reference Guide just down below!
An Art Map is written in JSON, but no worries, you don't need to know JSON to be able to follow this guide!
Below is a sample of a sprite module:
{
"accelgor": {
"data": {
"base": "modules/ptr2e-pkmn-sprites/sprites/617"
}
},
"aegislash": {
"data": {
"base": "modules/ptr2e-pkmn-sprites/sprites/681"
},
"suffixes": {
"blade": "_blade"
}
},
"aerodactyl": {
"data": {
"base": "modules/ptr2e-pkmn-sprites/sprites/142"
},
"suffixes": {
"mega": "_mega"
}
}
}
The entire file is what we call a 'JSON Object' meaning all of its content is wrapped in these {} squiggly brackets, after that you can see that each species' entry is what is known as a 'Key-Value Pair', for example in the first entry "accelgor" is the 'Key' while
"data": {
"base": "modules/ptr2e-pkmn-sprites/sprites/617"
}
is the 'Value'. The 'key' in this case represents the 'slug' of a Creature and is the tool used to look up the mapping.
Lets dive deaper into the value, as you can see in Accelgor's case, there is one more 'sub-object', data, this is where the simplest and most basic information of the file goes, it requires only one property 'base', which in this case points to Accelgor's image file in the module.
However you may notice that there is no file extension listed here! This is because your Accelgor may have alternate forms, which are added as a 'suffix' at the end of the file's base name, in this case, there is only one alternative, the 'Shiny' form, which is represented by the suffix s, so it would simply change it from 617 to 617s.
¶ Build-in Suffixes
There are 2 build in suffixes that the system handles automatically.
sfor Shiny andffor Female, if your creature has differences between 'Male' and 'Female' entries of its species, you can simply define those by adding thefsuffix to the 'Female' variant. When a creature is both 'Female' and 'Shiny', thefsuffix goes first like so:fs, examples:
Regular Accelgor:617.webp
Female Accelgor:617f.webp
Shiny Female Accelgor:617fs.webp
After the form has been determined, it will of course need a file extension, by default the system searches for files in the .webp format, hence why it isn't listed in the above example, but lets say your file would be .png, in that case you would simply add this mapping like so:
"data": {
"base": "modules/ptr2e-pkmn-sprites/sprites/617",
"extensions": [".png"]
}
"Why is extensions plural, and why the [] square brackets?" Well, despite us not recommending you to make use of it, the system does support having different forms in different extensions. For example, you could have 617.webp but its shiny form 617s.png, in this case you could simply mark the entry as having multiple extensions "extensions": [".webp", ".png"]
Please note that at the end of a key-value pair in JSON there always has to be a comma, unless it is the final key-value pair in an object. Be wary while copy pasting as it is easy to miss!
Some creatures however may have alternate forms, such as Aegislash, to add info about forms you have to add a secondary object titled 'suffixes'.
"suffixes": {
"blade": "_blade"
}
Similar to how being 'Shiny' adds an s suffix to the base path, suffixes allow you to define, well, custom suffixes to apply based on the form property of a species. In Aegislash's case, the default 617.webp represents its 'Shield' form, while 617_blade.webp represents its 'Blade' form.
You can add as many suffixes as you'd like, only 2 ever will be combined however as a species' 'form' property only supports a singular form (the secondary form being added would be 'Shiny')
Say you have the following files: 617.webp, 617s.webp & 617_blade.webp but lack the shiny version of the 'Shield' form, what now? No worries! The system is pretty smart, and it will check to find the 'Most Accurate' representation of your creature in the following order:
f Female suffix, Optional s Shiny suffix)f)s)f and s)f)s)If you have multiple extensions set, it will try all extensions for each step before moving to the next step.
Please note all the comments marked by // in the below JSON snippet for an explanation of each property:
{
"rotom": { // Key-value mapping based on a Creature's 'slug'
"data": {
"base": "modules/ptr2e-pkmn-sprites/sprites/479", // The 'base' path without any form suffixes or extensions
"extensions": [".webp"] // List of extensions, recommended to keep it to 1.
},
"suffixes": { // Key-value mapping of form 'slugs' to the associated 'suffixes'
"wash": "_Wash",
"heat": "_Heat",
"fan": "_Fan",
"mow": "_Mow"
}
}
}
Want to share the custom Dex you created? This is a step-by-step guide on setting up a module as well as configuring an Art Map for it!
/sprites folder.
Item where you can store the species of your dex./sprites folder (outside of foundry) make sure all the sprites are located following the same dex number as you assigned the mons in Foundry. Such as 1500.png
artmap.json file in the root of the module foldermodule.json make sure to add the following section:"flags": {
"your-module-id-here": {
"ptr2e-species-art": "modules/your-module-id-here/artmap.json",
"ptr2e-species-art-priority": 1
}
}
// Exports a Species Compendium to `artmap.json` format.
// Make sure to change to change the names.
const MODULE_ID = "your-module-name";
const COMPENDIUM_ID = "your-compendium-name";
const EXTENSIONS = [".webp"]
const species = await game.packs.get(`${MODULE_ID}.${COMPENDIUM_ID}`).getDocuments();
const data = species.filter(s => s.system.number).sort((a,b) => a.system.number - b.system.number).reduce((acc, s) => ({
...acc,
[s.slug]: {
data: {
base: `modules/${MODULE_ID}/sprites/${s.system.number}`,
// Update File Extension as required.
extensions: EXTENSIONS
}
}
}), {})
saveDataToFile(JSON.stringify(data, null, 2), "text/json", "artmap.json");