For the complete documentation index, see llms.txt. This page is also available as Markdown.

ItemAdditions: Dynamic Appearances

An item addition with dynamic appearances, and what you can do for this

Summary

Published: 29 Oct. 2023 by mana vortex Last documented update: Jul 05 2024 by mana vortex

This guide will cover a sub-case of Adding new itemsvia ArchiveXL (added in 1.13). Dynamic variants are both easier and more flexible. Unless you don't need different appearances, you will want to default to this approach.

TL;DR

In your root_entity:

  1. Add the DynamicAppearance tag

  2. Delete all but one entry from the appearances array.

    1. Name it like your entityName in the yaml

    2. Leave the appearanceName blank

In your .app:

  1. Delete all but one entry from the appearances array

  2. Name it like your entityName in the yaml

  3. Delete all components

  4. Point it to your mesh_entity

In your mesh_entity:

  1. To enable substitution in mesh depot paths, make sure they start with *

  2. Put all attributes that ArchiveXL should switch out in the paths in {}

e.g

meshes/t2_pwa_base_body_jacket.mesh meshes/t2_pwa_ebbwtfbbq_jacket.mesh

after:

*meshes/t2_pwa_{body}_jacket.mesh

Wait, this is not what I want!

  • If you want to understand how things work, check out the links during the rest of the guide.

  • You can find the technical documentation for dynamic variants on ArchiveXL's github.

  • If you want to create an Atelier store, see Your own Atelier Store

  • To quickly generate instances with up to two keys, check out W's generator (Codepen.IO)

Prerequisites

You need at least the following tools and versions (get the most recent):

You define an appearance as dynamic by adding the DynamicAppearance tag to the visual tags in its root entity.

If you don't know what that means yet, read on — it will hopefully become clear soon.

How is this better than the old approach?

TL;DR: It just is, source: trust me bro. Proceed to the next section.

Why dynamic appearances are superior

With vanilla item additions, you need one entry in the root entity per suffix. This gets out of hand quickly. When making stockings, there are four feet states (flat, flat_shoes, lifted and high_heels), and two body genders (Male and Female) . That leads to 4x2 entries for a single item.

For 15 appearances (colour variants) per mesh, I (manavortex) ended up with

  • 120 entries in the root entity (4*15 per body gender)

  • 120 entries in the .app file, (4*15 per body gender)

  • six mesh_entity files (flat, lifted, and heels for each body gender. I used the same for flat and flat_shoes, or I'd have ended up with eight.)

The most frustrating part was that everything was just duplication. Each set of entries in the .app file would only differ by name (_pwa and _pma to select it from the root entity), and the mesh entity path in partValues. Everything else was virtually identical, but I had to copy-paste and maintain 120 entries.

I cried to psiberx, who went and made the problem go away.

Dynamic variants put the logic into the mesh entity file. Instead of defining appearances with suffixes, I can conditionally define which component gets loaded, and ArchiveXL does the rest.

vanilla
dynamic

number of root_entity entries

120

1

number of .app entries

120

1

number of mesh entity files

6

1

number of components per mesh entity

2

5

If you still aren't convinced, go to Adding new items and start duplicating entries. Everyone else, to the batmobile!

Skipping and skimming

This guide contains the minimal amount of fluff and will link background information rather than giving it. Any links will tell you what you're supposed to read.

For that reason, you shouldn't skip or skim unless the section tells you that it's optional.

That being said, make sure to check the Troubleshooting section if you run into issues, and to run File Validation ->On the entire projectto check for common mistake.

Step 0: Run the generator

Archived lore: the example project

This guide assumes that you have access to the prepared example project, so go and grab it.

  1. Find the template project on Nexus.

  2. Download it and extract the files to your project's root folder, so that the source directory merges with the existing one.

  1. If you haven't, go and create a Wolvenkit Project. I'll name mine my_archive_xl_item,

  2. In the File -> Add files... menu, select ArchiveXL item

  1. Fill out the wizard with your item's information. The created item will be set up for both body genders. For the example project, I'll create a t-shirt:

The fields, Mason! What do they mean?

Item Type

This determines the equipment type of your item, which slot you equip it in. It also determines the base game item for the generator.

Item Name

Your item's unique name. This will be used to generate spawn codes and translation entries (you can change them later).

Item Subtype

Allows fine-tuning of the Item Type (e.g. instead of a generic head item, you can pick a mask)

EquipmentEx slot

EquipmentEx decides what slot to equip your item in based on its type and subtype, but you can override this - for example, a tight netrunner suit can be worn on the innermost layer. This also influences item layering via Garment Support (which item is worn above/below)

Visibility Tags

Hides parts of the player body. For a list of what the tags do, see ArchiveXL: Tags -> ArchiveXL tags

Garment support tags

In theory, this allows fine-tuning of garment support (e.g. by defining a coat as XLarge). In praxis, you're better-off relying on EquipmentEx for this.

Hide in First Person

Should the item be hidden in first person? (This hides the entire item, not just parts of it - use this for e.g. face masks or glasses. You can check .app file: Conditional switching or Dynamic Appearances: fine-tuning visibility conditions for more.)

Add mesh materials

This will add all of the template item's materials to your mod and custompath them. Takes at least a few extra seconds. Instead of doing this, you can also open the .mesh files and select Materials -> Add dependencies.

Item variants

This field lets you define colour variants for your item. You can easily set this up via dynamic appearances later, so go nuts, you crazy diamond.

Use two variant fields

Use this if your item has more than one variant (for example, a t-shirt colour and a decal)

Secondary variants

Here you can enter values for your secondary variant. In the example, I'll be using the decal options - galaxy, witcher, and samurai.

0.1: Import the icons

Import the auto-generated .png icon files (Import Tool -> Import All). They are just dummy icons, but they will help telling apart your shirts while you work on them.

You can now delete the .png files.

Check Your own inventory preview icons for a guide on how to create the final thing. Most people do this at the end of their project, so you don't have to do it now.

Generated files

Optional, but recommended: Read Dynamic appearances: Understanding the process to figure out what your new files do and how they do it.

Depending on the options you picked, your project will now look similar to this:

What kind of guide is this? I don't want a basegame item copy!

Yes, but generating the exact item that you want is so complex that we couldn't possibly implement it. Proceed to the next section.

Step 1: Customizing the generated item

Since the generated files are almost certainly not what you need, this section will show you how to adjust the item.

If that's not what you want, you can skip to Step 2.

If you change anything here, names and paths in Step 2 will be different. Adjust accordingly!

The generated structure includes 4 meshes per body gender:

pma = player male aerage, pwa = player woman average

Safely changing mesh paths

During this section, you will edit the mesh_entity. This file contains multiple components, some of which are pulling in .mesh files by path.

Select a node in the tree on the left, then edit its properties in the panel to the right.

In there, you need to adjust file paths, which have been generated as dynamic – meaning that they will look like this:

Since the default path starts with a * and has the Soft flag, ArchiveXL will resolve these placeholders at runtime to t1_079_pwa_tshirt__casual.mesh or t1_079_pma_tshirt__casual.mesh.

Instead of preserving the substitution, you can simply paste a non-dynamic path to one of your files (select it in the project browser, Copy relative path, paste it to the DepotPath box). After that, you can right-click the box, and select Convert to dynamic.

If you want to have only one body gender, check 1.2 below.

1.1 Changing the mesh count

Usually, you have either more or fewer meshes than you actually want to use.

Adjust the .mesh count

If you have more than you need: delete the files you don't want to use

If you need more: copy an existing file, then re-name it. Make sure to do this for both body genders.

Adjust the components

The item's individual parts are pulled in via mesh_entity (you can learn more about this on Dynamic appearances: Understanding the process).

In the editor panel on the left, find the components.

If you have deleted meshes, delete the corresponding components. If you have added extra entries, duplicate an existing component and change its name and DepotPath.

The component prefixes are important for garment support. Don't remove them!

1.2 Renaming files and components

You do this inside the mesh_entity file.

Generated file names are based on the original item. You can rename these files, but you have to adjust the DepotPath entries in the mesh_entity afterwards (see Safely changing mesh paths for how to do that).

You can also change the component names in the mesh_entity to whatever you want – just keep in mind that the component prefixes are important for garment support and you should not remove them.

1.2 Removing a body gender

The easiest way to support only one body gender is to display an invisible item for the other. Do the following things:

  1. Delete the meshes you don't want from the project browser

  2. For each component in the mesh_entity, adjust the DepotPath to be no longer dynamic (you can use the right-click menu)

As of now, the game will crash if the item is equipped by the unsupported body gender. Add a conditional appearance to prevent this:

  1. Open the .app file

  2. For each entry in the appearances array, change the name field and add &gender=w or &gender=m

You can learn more about this under Dynamic Appearances: fine-tuning visibility conditions.

1.3 Body mod support

Thanks to ArchiveXL, body mod support has become trivial. Unfortunately, refitting has not become trivial and you will still have to do this in Blender (although the WKit Blender Plugin: AKL Autofitter can help).

To enable this feature, you only need to

  • change the depotPath in your components to include the {body} placeholder

  • re-name your mesh files to include the body's tag in their path (find a full list under Supporting mods)

Adjust the component mesh paths:

Change mesh file paths:

Re-name all your existing meshes by adding base_body to their paths. This must correspond to the {body} placeholder in the component path.

Example:

This mesh will be used if ArchiveXL can't detect any body-specific ones - so you only need to create extra meshes where refits are needed (usually boobs).

Refitting

For each refit you want to create,

  • copy the _base_body .mesh

  • replace the _base_body in its path with the camelcase tag for the modded body (see Supporting mods)

Example:

Step 2: Connecting the decal (and understanding variants)

This section explains how to connect the t-shirt's logo. It will show you two ways to do this. If you don't have a logo, you are done with this part of the guide and can go to Step 3.

This section will teach you how to make use of the variant to switch out item parts via .yaml. As a reminder, this is our yaml:

DynamicAppearances makes everything after the ! available in the mesh entity under the key variant. By adding +, you can split the variant into parts. Expand the box below to see more examples, because this is where the magic lives.

Examples
raw variant
variant
variant.1
variant.2

$(base_color)+$(secondary)

black+samurai

black

samurai

$(base_color)$(secondary)

blacksamurai

blacksamurai

-

$(base_color)+$(foo)

black+

black

-

By default, our _mesh.ent looks like this (because the generator re-uses CDPR's file structure)

As explained in earlier sections of the guide, these paths are already dynamic.

Now, let's get that decal connected.

  1. Select the first deactivated component, and turn it on by expanding the chunkMask dropdown and checking a few of the boxes (e.g. the first 3).

  2. Select the second and third deactivated component, and delete them.

  3. Based on the value of secondary from your yaml file (see the expandable above), we have the following values for variant.2:

    • galaxy

    • samurai

    • witcher

  4. In the mesh depot path, replace samurai.mesh with {variant.2}.mesh

  5. Change the meshAppearance to samurai (since the generator set that up for us)

Thanks to ArchiveXL's substitution, we only need one component to pick our choice from three .mesh files — based on the value for secondary in the yaml.

This approach is not recommended for anything user-editable because it can lead to crashes. For details, see Exercise 1: Other options

Exercise 1: Other options

Dynamic mesh picking based on yaml params saves a lot of duplication. However, the game will crash if you tell it to load a mesh that does not exist.

This is a problem, because if you enter semurai instead of samurai, the game will try to find (for female V) manavortex\equipment\torso_inner\my_custom_shirt\meshes\t1_079_pwa_tshirt__casual_dec_semurai.mesh and then crash because it can't.

This is generally bad, so which options do we have to prevent it?

The boxes below contain suggestions and detail different ways to tackle the same problem with ArchiveXL. You can combine them or completely ignore them, as you want.

I (manavortex) usually stick to the first approach, which is far more flexible, but both of these solutions are valid (and the second one offers tremendous flexibility).

mesh_entity: One decal mesh, multiple appearances

This requires the least amount of changes in our project: you put all the appearances into the same .mesh file, and only switch the loaded texture via meshAppearance.

Unfortunately, CDPR used three different meshes, so you'd have to create the full decal on your own (check out the Adding decalsguide)

The result would look like this:

_app: Three decals, one appearance, partsOverrides

By slightly changing our .yaml, we create different appearances in the root.ent and the .app file:

This will create the following appearance names:

my_custom_shirt_galaxy_!$(base_color) my_custom_shirt_witcher_!$(base_color) my_custom_shirt_samurai_!$(base_color)

The !$(base_color) will still arrive in our mesh_entity.ent as {variant}, but we no longer have a second field (no +).

We need to register our appearances in the root.ent :

Instead of a single appearance, we now have three. Still better than 9 (per colour) or 18 (per colour+body gender)!

This is what we kept the original mesh entity for, as we will use this in the .app file in the next step. Open it, and turn all disabled components visible:

If you were to spawn this t-shirt now, it would have all three decals. We don't want this. Luckily, we can use partsOverrides to hide things from the .app (but not show them, that's why we turned them all visible).

In the .app file,

  1. Change the path under partsValues to mesh_entity_copy.ent

  2. Duplicate the entire appearance two more times

  3. Change the names to the same ones you used in the root_entity.ent

Now, create a partsOverrides, and then two componentOverrides inside. For every componentOverride, set the following values:

  1. chunkMask to 0 (this will completely hide the component)

  2. meshAppearance to an empty string (displays as None, this will make AXL ignore it)

  3. componentName to the name of a component that you want to hide (you can copy them from the mesh_entity_copy.ent)

For every appearance, hide the other two decals.

An example of a real mod

I use both of these techniques in my University Outfit mod. Every mesh file contains several states of the same item, and I use partsOverrides to switch between them based on the yaml configuration.

For details, expand the box.

How University Outfit uses dynamic variants

Polo: Collar states

The mod supports two collar states on the polo - open and closed.

mesh
submeshes for "closed"
submeshes for "open"

torso

0,1,2

3,4,5

collar

0,1

2,3

tie

0,1

2,3

Polo: Sleeve lengths

You can pick three sleeve lengths for the polo: short, long, and gloved. The mesh chunks are set up as follows:

  • short: 0

  • long: 1, 2

  • gloved: 1, 3

(Yes, long and gloved share the same mesh for the part from shoulder to elbow, only the part below that is different).

So I ended up with six appearances in the _root.ent and .app:

university_polo_short_sleeves_open_collar_ university_polo_long_sleeves_open_collar_ university_polo_gloved_sleeves_open_collar_ university_polo_short_sleeves_closed_collar_ university_polo_long_sleeves_closed_collar_ university_polo_gloved_sleeves_closed_collar_

Sweatshirt: polo collar

On top of that, I am using ArchiveXL custom tags to display yet another collar when the sweatshirt is worn on top of it. For this, I'm also using the "open collar" tie, so I had to make sure that it fits both... I spent a lot of time re-fitting on this mod.

Step 3: What now?

You now have a working item that you can play around with. First thing is to create a full back-up of your project, because you will break things as you fuck around and find out.

  • More color variants: Check Adding an appearance

  • Body mod support: Go back to section 1.3 Body mod support

The diagram

Now let's look at what we just did and check the diagram. You'll see that the control files are almost identical to the vanilla variants, but that the rest of the files has gotten a lot more manageable:

And that's it! With this and the original guide, you should hopefully be able to add items to your heart's content!

Tools and utilities

Generating display names

I have written a Python script to auto-generate display names, you can find it on my github. If you don't know how to use this, check Running Python Scripts.

Creating preview icons

This problem is so common that it has its own wiki page: Your own inventory preview icons

Troubleshooting

Please see the original guide's Troubleshootingsection.

Last updated