Skip to content
Pavel Siberx edited this page Aug 11, 2023 · 4 revisions

Dynamic appearances

ArchiveXL 1.5.0 introduces new approach for creating clothing mods called dynamic appearance.

The main goal is to eliminate repetitive work. This is accomplished by interpolating properties values and applying conditions directly to appearance definitions and components, instead of having to manage tons of entity appearances for each color variant and suffix.

In many cases you'll need just one appearance.

How to activate

To activate the new feature, you must add a visual tag DynamicAppearance to your root entity template (visualTagsSchema).

Then you have to add only one template appearance without suffixes and one appearance definition. For example:

name: my_item
appearanceResource: mod\my_item.app
appearanceName: my_item

Property interpolation

Instead of defining different appearances that depend on appearance suffixes, you can use property interpolation to substitute parts of mesh path and mesh appearance name with dynamic values.

To activate interpolation for a property, the value must start with *. For example:

mesh: *mod\meshes\my_item_{gender}.mesh
meshAppearance: default

All available attributes representing current state:

Placeholder Substitution
{camera} fpp or tpp
{gender} m or w
{body} base_body or body mod name in snake case
{arms} base_arms, mantis_blades, monowire, projectile_launcher
{feet} flat, lifted, high_heels, flat_shoes
{sleeves} full, part
{skin_color} skin color name from customization
{hair_color} hair color name from customization

Variants

To define different variants of your item you have to use a new syntax for item record's appearance name. The name of the variant must be separated from appearance name by !. The appearance name must match the name in entity template. For example:

Items.my_item_black:
  $base: Items.GenericFaceClothing
  entityName: my_item
  appearanceName: my_item!black

Then you can use a variant name as a substitution in your component:

mesh: *mod\meshes\my_item_{gender}.mesh
meshAppearance: *{variant}

Composite variant can be defined using + separator. For example:

Items.my_item_black:
  $base: Items.GenericFaceClothing
  entityName: my_item
  appearanceName: my_item!black+arasaka

In this case you can use different parts of variant name separately. For example, one part for color name and another part for decal name.

Variant parts can be accessed using . and part index (starting from 1):

Placeholder Substitution
{variant} black+arasaka
{variant.1} black
{variant.2} arasaka

Conditions

You can define activation conditions for appearance definitions or single components. The concept is similar to appearance suffixes in its purpose: you can load different parts, apply different parts overrides, activate/deactivate components depending on the current state.

To add condition you have to add the expression directly to appearance definition name (in .app) or component name. For example, appearance named my_item&camera=tpp will be used only in TPP and replaced with a blank one in FPP.

You can define multiple elements with the same name but different conditions. If several elements with the same name match the criteria, then one with the highest priority will be used. if several elements with the same name and highest priority match the criteria, then the first in the order of definition will be used.

Appearance/Component Priority Description
my_item!variant&camera=tpp 1 Has the highest priority because it requires a specific variant and one state condition.
my_item!variant 2 Has second priority because it requires a specific variant.
my_item&gender=w&camera=tpp 3 Has third priority because it has two state conditions.
my_item&camera=tpp 4 Has fourth priority because it has one state condition.
my_item 5 Has the lowest priority and will be used when no other elements match the criteria.

Body types

You can register your body mod as a body type with ArchiveXL to allow clothing items to automatically select a corresponding refit.

To register a body type:

  1. Register body name using .xl configuration file:

    player:
      bodyTypes: [NewBody]
  2. Add visual tag with the same name to any of your .ent or .app.

Body type detection works with simple body replacements and with customization system.

Appearance suffixes

Body type

The suffix itemsFactoryAppearanceSuffix.BodyType represents currently used body mod. It can be used to load a corresponding refit.

To activate a new suffix, you must add it to appearanceSuffixes:

Items.MyGloves:
  appearanceSuffixes:
    - !append itemsFactoryAppearanceSuffix.BodyType

The value of the suffix will be the name registered by body mod author or &BaseBody when no body mods used.

Arms state

The suffix itemsFactoryAppearanceSuffix.ArmsState represents what type of cyberarms are used by the character. It can be used to properly render wrists and hands items depending on whether the character uses cyberarms.

To activate a new suffix, you must add it to appearanceSuffixes:

Items.MyGloves:
  appearanceSuffixes:
    - !append itemsFactoryAppearanceSuffix.ArmsState
Cyberware Suffix
None &BaseArms
Mantis Blades &MantisBlades
Monowire &Monowire
Projectile Launcher &ProjectileLauncher

Feet state

The suffix itemsFactoryAppearanceSuffix.FeetState represents the state of the feet of female characters. It can be used to properly render tights or other legs clothing depending on whether the character is wearing shoes.

To activate a new suffix, you must add it to appearanceSuffixes:

Items.MyTights:
  appearanceSuffixes:
    - !append itemsFactoryAppearanceSuffix.FeetState
Character Footwear Suffix
Female Unequipped &Flat
Female Equipped without tags &Lifted
Female Equipped with HighHeels tag &HighHeels
Female Equipped with FlatShoes tag &FlatShoes
Male Any (empty)

Components overrides

To hide submeshes of the owner entity, such as body parts, in your appearance definition you must add a partsOverrides entry with a blank partResource and add componentOverrides using entity's component names.

It's similar to how you override parts of your own meshes, but instead you use the component names of the entity that wears your item, such as t0_000_pma_base__full or l0_000_pwa_base__cs_flat.

Visual tags

To apply visual tags to an item you must add them to visualTags property of your appearance definition or to visualTagsSchema of your root entity template.

Known visual tags defined by the game:

Tag Effect
hide_H1 Hides an item in the Head slot.
hide_F1 Hides an item in the Eyes slot.
hide_T1 Hides an item in the Chest slot.
hide_T2 Hides an item in the Torso slot.
hide_L1 Hides an item in the Legs slot.
hide_S1 Hides an item in the Feet slot.
hide_T1part Toggles the partial suffix (&Full&Part) when applied to Torso item.
hide_Hair Hides hair.
hide_Genitals Hides genitals in uncensored mode and underware in censored mode.

Custom visual tags defined by the mod:

Tag Effect
hide_Head Hides head.
hide_Torso Hides the whole torso.
hide_LowerAbdomen Hides lower abdomen.
hide_UpperAbdomen Hides upper abdomen.
hide_CollarBone Hides collar bone area.
hide_Arms Hides head.
hide_Thighs Hides thighs.
hide_Calves Hides calves.
hide_Ankles Hides ankles.
hide_Feet Hides feet.
hide_Legs Hides the whole legs.
force_Hair Forces visible hair for head items.
force_FlatFeet Forces flat feet for female characters.

Extending resources

The mod doesn't modify original files such as factories.csv and onscreens.json and doesn't produce new archives, instead it merges your own resources with the originals at runtime.

The workflow is pretty simple:

  1. Create CR2W resources with your content and add them to the archive as usual
  2. Create a loader config that specifies which resources from your archive should be merged with the original game files
  3. Include the loader config in the mod along with the archive

Entity Factory

mymod\factories\clothing.csv:

{
  "Header": {
    "WKitJsonVersion": "0.0.3",
    "GameVersion": 1600,
    "DataType": "CR2W"
  },
  "Data": {
    "Version": 195,
    "BuildVersion": 0,
    "RootChunk": {
      "$type": "C2dArray",
      "compiledData": [
        [
          "mymod_item",
          "mymod\\items\\clothing\\item.ent",
          "true"
        ]
      ],
      "compiledHeaders": [
        "name",
        "path",
        "preload"
      ],
      "cookingPlatform": "PLATFORM_PC"
    },
    "EmbeddedFiles": []
  }
}

Despite the name the factory can contain both entities (.ent) and appearance (.app) resources.

Localization

mymod\localization\en-us.json:

{
  "Header": {
    "WKitJsonVersion": "0.0.3",
    "GameVersion": 1600,
    "DataType": "CR2W"
  },
  "Data": {
    "Version": 195,
    "BuildVersion": 0,
    "RootChunk": {
      "$type": "JsonResource",
      "cookingPlatform": "PLATFORM_PC",
      "root": {
        "HandleId": "0",
        "Data": {
          "$type": "localizationPersistenceOnScreenEntries",
          "entries": [
            {
              "$type": "localizationPersistenceOnScreenEntry",
              "secondaryKey": "MyMod-Item-Name",
              "femaleVariant": "Samurai Mask & Aviators"
            }
          ]
        }
      }
    },
    "EmbeddedFiles": []
  }
}

When creating you own localization it's recommended to always use the secondaryKey. If you don't need gender specific translations you should set femaleVariant only and it'll be used for all genders.

If you want to edit original translations you must use the primaryKey.

Loader configuration

The config file is a YAML file with a .xl extension that must be placed in the same directory with the archive:

<Cyberpunk 2077>\archive\pc\mod\mymod.archive
<Cyberpunk 2077>\archive\pc\mod\mymod.archive.xl

Or if you use REDmod packaging:

<Cyberpunk 2077>\mods\betsmod\archives\mymod.archive
<Cyberpunk 2077>\mods\betsmod\archives\mymod.archive.xl

In this example, the config file is named after the archive for convenience. But you can name it as you want.

In the config file you have to specify factories and/or localization resources to load:

factories:
  - mymod\factories\clothing.csv
  - mymod\factories\weapons.csv
localization:
  onscreens:
    en-us: mymod\localization\en-us.json
    de-de: mymod\localization\de-de.json

The first language in the list is also a fallback language and will be used when the user enables a language that is not supported by the mod.

Language codes used by the game:

Code Language Code Language
pl-pl Polish ru-ru Russian
en-us English pt-br Brazilian Portuguese
es-es Spanish jp-jp Japanese
fr-fr French zh-tw Traditional Chinese
it-it Italian ar-ar Arabic
de-de German cz-cz Czech
es-mx Latin American Spanish hu-hu Hungarian
kr-kr Korean tr-tr Turkish
zh-cn Simplified Chinese th-th Thai