How to convert your mod to use dynamic variants... in ten minutes
Published: June 30 2024 by manavortex Last documented update: June 30 2024 by manavortex
This page will teach you how to convert your existing ArchiveXL mod to the "new" system.
An ArchiveXL mod that you want to convert
We will go through the process step-by-step. I'll explain what I'm doing as I go along.
Instead of one entry per item variant, we only need one entry per item.
Our variants are defined via $instances
and generated via substitutions. Let's take a look at this:
You'll notice that the displayName
s are different now. I could prevent that by writing my_shirt_localization_name_$(shirt)_$(ribbons)
, but this is a great chance to clean up the historically-grown mess.
We deleted the appearanceSuffixes
(we'd only need them for Gendered preview icons, and we can't be arsed with that)
We defined a list of $instances
, which will generate all of our different appearances
We replaced all parts that are different with the corresponding key from $instances
. The rest will be magic.
Defines the variants — you'll get a gold star for paying attention, but we're getting to that later (#step-3-the-mesh-entity)
Instead of one entry per variant and gender, we only need one entry in total.
Our appearance's name
must still match the .yaml
, but only up to the variant separator: we're going with appearance_root_entity_
.
By leaving the appearanceName
blank, we're telling ArchiveXL to re-use name
. If you want to use a specific appearance name (or if you don't want appearance_root_entity_
in your .app), you can put something different here.
We added the DynamicAppearance
tag to enable the feature
We deleted all appearances but one
We deleted everything variant-related from the appearance
We deleted the appearanceName, so that ArchiveXL will re-use name
for the .app
Instead of one appearance per variant and gender, we will squash everything down so that we have only one appearance per gender. In #lets-simplify-this-even-further, I will teach you how to reduce that even further, but for now, we'll be going step by step.
We deleted all but one appearance per gender
We added the condition &gender=w
and &gender=m
We deleted the partsOverrides
Gender matching now happens via condition. The different meshes for male and female body gender are loaded in the different mesh entity files.
For a full list of conditions, see ArchiveXL: Suffixes and Substitutions
Right! You've been paying attention! Let's take a look at that next.
We will only change a single field (meshAppearance
).
Before, it was mesh_white_red
(the default appearance), and each appearance overwrote it via partsOverride
. We're now changing it to dynamic
:
Old: mesh_white_red
New: *mesh_{variant.2}_{variant.1}
This is where file validation currently stops working (as of June 2024). If you make any mistakes here, you will always see the first mesh appearance.
By adding a leading *
, we told ArchiveXL that this field is involved in magic (substitution in this case)
By replacing white
with {variant.2}
, we're using the second parameter from the yaml's appearanceName
(shirt).
By replacing red
with {variant.1}
, we're using the first parameter from the yaml's appearanceName
(ribbons).
Let's unpack this.
In this example, we have the following mesh appearances:
mesh_white_red
mesh_black_red
mesh_black_blue
By using !
in the appearanceName
, we're telling ArchiveXL that everything after is part of the mesh appearance definition:
This is the reason why we've used only appearance_root_entity_
as the appearanceName, and not the whole ordeal.
The +
in the variant
splits it up. If we didn't have it, we couldn't use variant_1
and variant_2
.
Let's compare our setup ( *mesh_{variant.2}_{variant.1}
) to the alternative.
yaml:
Our meshAppearance
would be *mesh_{variant}
.
Without the split, we need to make sure to pass the variant exactly as expected
.
Unless you got hopelessly lost, this should have taken no more than ten minutes, and your mod just works(tm).
You now have one root_entity
entry, two appearanceAppearanceDefinition
s in your .app
, and one mesh_entity
per body gender.
Currently, we have two mesh_entities:
Each of them points at a different mesh:
Delete one of the mesh entities and rename the other:
Delete one of your appearances, and strip the suffix name from the other, leaving only appearance_root_entity_
.
Change the path of your partsValue
to the only remaining mesh entity, and save the file.
This will only load one body gender (the one you defined in the mesh_entity
).
You should use the other approach where possible; this is only documented here for the sake of completeness.
Just like with appearances, you can also use #conditions with component names.
Pro: Especially with many body mods, you can just put all the logic into the components
Cons: All of these components will be added to the player entity, even if half of them will be hidden. This is bad for performance, especially if everyone does it.
If you want several different body mods or feet state to use the same mesh, you can use ArchiveXL: Resource linking instead.
The best way of dealing with multiple meshes is to have a single component and let ArchiveXL handle all the heavy lifting by using substitutions in the path:
This is our mesh's depot path:
A combination of