arrow-left

All pages
gitbookPowered by GitBook
1 of 14

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

ItemAdditions: File structure explained

More detailed explanations for the guide "Adding new items"

hashtag
Summary

Created: by @manavortex Last documented edit: June 10 2023

This page is a part of the Adding new items guide and explains how the different files interact with each other.

circle-check

If you have come here from the main page because you want to change the existing files, search for Making changes in each section. To add new appearances, the following files are relevant:

circle-info

Unless stated otherwise, any linked resources are optional and might not even be related to this exact guide.

hashtag
Structural files: telling the game about your mod

We need four files to tell the game about our new items:

  1. the .yaml, which tells TweakXL about your item's properties

  2. the .xl file, which tells ArchiveXL which files to register

  3. the .csv, telling the game about your custom files

hashtag
The .xl file

This file will be in the same directory as your mod's .archive file. It lets ArchiveXL register the (my_shirt_factory.csv) and the (translation_strings.json).

You usually touch this only once, unless you want to add more factories or translation files.

hashtag
.xl: Making changes

You only need to change this file if you have changed the factory's file path (moved the file) or want to add a second factory file (there is no need to, though).

hashtag
The .json file (custom texts, i18n)

This is the localization file for language-specific entries (green boxes on 's screenshot). If no entry for a language is defined, then the English one will be used.

An entry will look like this:

circle-info

If you don't need a male-specific translation, you can leave it blank — by default, femaleVariant will be used.

hashtag
.json: Making changes

You need to change this file every time you want to add a new text entry to your mod. The easiest way to do this is by duplicating an existing entry.

hashtag
The .csv file (the factory)

The factory connects your .yaml to the corresponding rootEntity.ent via entity_name.

When reading your .yaml file (e.g.tutorial_my_custom_tshirt.yaml, ), the game will find entries like this:

The csv file is where ArchiveXL will find an entry with the yaml's entityName in the first field. It will then check the corresponding for an appearance with the name in appearanceName.

hashtag
Making changes

You only need to change this file when

  • you move a root entity (update the path!)

  • you add a new entityName — for example, a second t-shirt that you want to have its own root entity.

hashtag
The control file: yourModName.yaml

circle-exclamation

When editing this file, please keep in mind that indent is important!

The first line of each block must not have spaces, the blocks below must have the same amount of spaces. More spaces means more nesting.

Making mistakes here might break your entire mod, so if in doubt, run your edited file through an .

This file controls the adding of items to the game. Unless you are using , an entry looks like this:

circle-info

The entry above will let you add the item via Game.AddToInventory('Items.my_custom_shirt_redwhite')

Four mappings take place here:

  1. entityName: Points to the (see documentation there as for what it works)

  2. appearanceName: In the specified in the factory, it will look for an appearance by this name.

circle-info

The appearance name will only be considered up to the first . If you want to know what those pesky & things are doing, read up the corresponding documentation.

You don't need to know this unless you aren't using and want to add variants for different genders or camera perspectives. We're making them go away by puttingappearanceSuffixes: [].

  1. displayName/localizedDescription : In the translation_strings.json, find an array where the value for [3] (the last entry) is identical to this key. Then, check which gender V has, and display either femaleVariant or maleVariant.

  2. icon:

hashtag
What is it, precious? The $base parameter

$base defines which slot the item will use. For the full documentation, see "".

circle-info

The inherited properties can cause problems (see "" for more detail).

You don't need to know this unless you want to add variants for different genders or camera perspectives: we're avoiding them by puttingappearanceSuffixes: [].

hashtag
.yaml: Making changes

You need to touch this file every time you want to add a new item (or when you want to change an existing one). It is easiest to duplicate an existing entry.

If you want more than just the base properties, check the documentation for .

hashtag
The game files

Now that we're done with the base structure, we can take a look at the game files. Like for any of the vanilla game items, we have four of them. This guide will only hold information that's directly relevant to adding item, but in the individual sections below, you will find links to more documentation about the files.

circle-check

With ArchiveXL >= 1.5, there is a new way of making these connections, saving most of the work of making many variants. You can still complete this guide and then see the documentation for dynamic loading .

If you want to do more than 5 variants (for both body genders and camera modes), that approach is strongly recommended. Since there isn't a detailed guide yet, you can find us on in the #archive-xl channel.

  • appearance.app

  • mesh_entity.ent

hashtag
Overview

This is how the files connect to each other. If your head explodes now, don't worry: it's not as complicated as it looks, and the item addition guide will walk you through step by step.

hashtag
root_entity.ent

circle-info

Full documentation of the root_entity is on its own page.

Understanding this is not necessary for the purpose of this guide.

The entry point from your yaml, this file is a glorified lookup dictionary: for any appearanceName, it will specify an .app file and the name of an appearance in the .app file.

An entry looks like this:

circle-check

If you don't know what this means, skip it and wait for the full step-by-step guide!

For using , you only need one appearance here, which must match the field appearanceName in the .yaml up to the variant separator ! Make sure to add the DynamicAppearance tag here.

hashtag
Suffixes

Unless you are using , the root entity's name field is where you would put suffixes for different appearance variants.

circle-exclamation

You don't need to know unless you want to make variants for different genders or camera types. In fact, you will want to skip this until you have a confirmed and working mod!

To disable them, each entry in your contains the following line: appearanceSuffixes: []

hashtag
Root Entity: Making Changes

When you change the path of this file, you need to adjust the path inside the .

Adding a new appearance:

Expand the list appearances and duplicate your already working entry.

Change the following fields: appearanceName => everything before the & must match appearanceName in your *.yaml name => must match the name you're going to put in your app.app

Example:

old (copy):

new:

circle-info

You do not need to change the appearanceResource.

hashtag
mesh_entity.ent

triangle-exclamation

For experienced modders

This file replaces the component array inside the .app!

circle-check

Check for how to find the right mesh entity for each equipment slot.

This file holds a collection of components that determine how our equipment item behaves and moves. Each kind of equipment has different types of components, which is why you need to pick the for each equipment slot.

circle-info

Would you like to know more?

Full documentation of The mesh entity for More intel on

Understanding this is not necessary for the purpose of this guide!

By bundling them in this file, we save ourselves a lot of copy-pasting inside the .app file. The only component we actually need to change is the one with "Mesh" in its name, typically entGarmentSkinnedMeshComponent:

The component's name will be used in appearance.app's materialOverride array (see )

triangle-exclamation

When changing component names, you want to leave the (t1_) in place — the game needs them to calculate collisions!

circle-check

If the text in this box tells you nothing, just ignore it for now

If you're using , you can use property interpolation in paths. For example, *p{gender}a will resolve to pwa or pma, based on V's body gender. Read more about this on .

hashtag
Mesh Entity: Making Changes

When you move this file, you need to change the path inside every appearance inside the . file.

Otherwise, you only need to touch this file if you move the .mesh file.

hashtag
appearance.app

Contains a list of appearances as mapped by . Each of the appearances will load mesh_entity.ent via partsValues.

If you're not using , you specify the components' appearances and chunkMasks in the partsOverrides.

triangle-exclamation

For experienced modders

The .app file's component array should be empty: this is not an NPC appearance! :)

An entry will look as follows:

partsValues will define what file(s) to load (as a list of components), while partsOverrides tells the which appearance to use.skipp

For ArchivXL >= , appearance overrides can understand the following variables for meshAppearance:

circle-check

If you don't know what this means, skip it and wait for the full step-by-step guide!

For using , you only need one appearance here. In this case, components will be ignored — make sure to put them all into your mesh_entity!

hashtag
Appearance: Making changes

When you move this file, remember to change the path inside the root_entity.ent

You need to touch this file every time you add a new appearance:

  1. Open the .app file and expand the list appearances.

  2. Duplicate an item and select the new one.

  3. Change its name to the one you just defined in the .yaml (black_blue_appearance_name)

circle-info

You can leave partsValues alone - this just points at the file that loads the mesh, and you've already set it up above when setting up the file.

hashtag
Mesh

The mesh file maps materials to appearances. To find out how exactly it does that, find the on the mesh wiki page.

circle-info

Would you like to know more?

The documentation for .mesh files lives on their own page!

Understanding this is not necessary for the purpose of this guide, but you might want to reference it once you run into trouble.

For our purposes it's enough to say that you can define your individual appearances here.

hashtag
Mesh: Making changes

  1. Find the array appearances and open it.

    1. Duplicate any meshMeshAppearance.

For further information and guides, check or see .

hashtag
The final result

This is how everything plays together:

root entity
  • app

  • mesh

  • .json (translations)

  • You do not need to touch the mesh entity.

    the .json file with the translations
    This hooks up your custom preview.
    the mesh file

    In the new appearance, find the array partsOverrides and expand it.

  • Select the item inside.

  • Find and expand the Array appearanceAppearancePartOverrides and expand it.

  • Select the first item.

  • Open the array componentsOverride and select the first item.

  • Change the value of meshAppearance to the name of your new appearance in the mesh:

  • Change the name to the one you've defined in the
    appearance.app
    above (in this case:
    mesh_black_blue
    ):
  • Select the array chunkMaterials and change the entries in the right-hand panel to the name of your new material (e.g. black_blue)

  • Find the array materials and open it.

    1. Duplicate the last entry. (Yes, use the last one, please, it's important for step 3).

    2. Select the new last entry

    3. Set the following values:

      If you duplicated the last material, you can just increase it by one.

  • Find the array localMaterialBuffer and open it

    1. Duplicate any entry with an mlsetup (You will see an entry MultilayerSetup under values)

    2. Drag it to the last position of the array (that's important, because the materials entries match by numeric index)

    3. Select the new item, open values, and select MultilayerSetup.

    4. Set baseMaterial/DepotPath to the .mlsetup file that you want.

  • {gender}

    m or w depending on V's body gender

    {skin_color}

    skin color appearance name

    {hair_color}

    hair color appearance name

    .yaml
    factory
    localization file
    the xl file
    next section
    root entity
    online yaml validatorarrow-up-right
    dynamic appearances
    factory.csv
    root entity
    suffixarrow-up-right
    dynamic appearances
    Different equipment slots
    Suffixes, and whether you need themarrow-up-right
    TweakXL's creating recordsarrow-up-right
    on its own page
    Discordarrow-up-right
    root_entity.ent
    Would you like to know more?arrow-up-right
    dynamic appearances
    dynamic appearances
    what suffixes arearrow-up-right
    .yaml
    factory.csv
    here
    right mesh entity file
    mesh_entityarrow-up-right
    dynamic appearances
    components
    below
    dynamic appearances
    ArchiveXL's githubarrow-up-right
    app
    rootentity.ent
    dynamic appearances
    mesh_entity
    mesh
    1.4.0arrow-up-right
    dynamic appearances
    material sectionarrow-up-right
    https://wiki.redmodding.org/cyberpunk-2077-modding/for-mod-creators-theory/files-and-what-they-do/3d-objects-.mesh-filesarrow-up-right
    here
    https://github.com/CDPR-Modding-Documentation/Cyberpunk-Modding-Docs/blob/main/for-mod-creators/files-and-what-they-do/3d-objects-.mesh-files
    The file structure as used in the Adding New Items guide. Some information has been omitted for brevity.
    Example .xl file. Note that anything with a - at the beginning of the line indicates a list; you can add more entries!
    The value under secondaryKey must match the entry in your .yaml file, or you will just see an empty string.
    When spawning an item, TweakXL knows which entity file to use by filtering entityName for a match in the first field
    The only component we actually need to change is the entGarmentSkinnedMeshComponent
    Appearance.app (annotated)
    Items.my_custom_shirt_redwhite:
      entityName: my_custom_shirt_factory_name             << this is for the factory.csv
      appearanceName: appearance_root_entity_white_red     << this is for the root_entity.ent
    	appearanceName: black_red_appearance_name
    	name: appearance_root_entity_black_red
    	appearanceName: black_blue_appearance_name
    	name: appearance_root_entity_black_blue
    componentName: t1_tutorial_custom_shirt_4711   << no need to change this  
    mesh_appearance: mesh_black_blue                << corresponds to meshMeshAppearance.name in my_mesh.mesh  
    name:  mesh_black_blue           <<< as defined in step 1 and used by meshMeshAppearance in appearances[]  
    index: <index of item in array>  

    Weapons: Attachments and Scopes

    How to mod weapon attachments

    hashtag
    Summary

    Created: July 11 by @manavortex Last documented update: July 11 by @manavortex

    This page will tell you how to mod weapon attachments and scopes.

    If you can contribute, please sign uparrow-up-right and update this page!

    hashtag
    Component visibility

    Component visibility is defined by the visibilityAnimationParam:

    To always display a component, set the value to None (clear the field).

    circle-exclamation

    TODO: which values are allowed here? Where do we get them from?

    Dynamic Appearances: fine-tuning visibility conditions

    How dynamic appearances can use different meshes/submeshes in a single root entity file.

    hashtag
    Summary

    Published: Sep 09 2024 by Last documented edit: Dec 14 2025 by

    This page is an extension of ItemAdditions: Dynamic Appearances and explains how to fine-tune item visibility conditions beyond the basic scope.

    Please also check ItemAdditions: Dynamic Appearances -> for more examples.

    hashtag
    Via root entity

    You can use yaml instances to create different appearance names. These let you use different root entity entries which can point at different appearances in the .app file – letting you use partsOverride to show or hide different parts of your item!

    Let's look at an example.

    hashtag
    Editing the .yaml

    We're adding the type parameter to the custom t-shirt's definition array.

    Since the variants only start after the exclamation mark, we can generate different appearance names:

    before:

    after:

    This will look up the following names in your root entity:

    root_entity_dynamic_appearance_sleeves_

    root_entity_dynamic_appearance_nosleeves_

    Then you would add the following entries to your .app file with the names :

    root_entity_dynamic_appearance_sleeves_

    root_entity_dynamic_appearance_nosleeves_

    Now you have options. The next step will depend on your goals. In the .app file, you could use partsOverrides to hide different parts of the mesh for each appearance (like the sleeve submesh for the no-sleeve version. See ), or you could set partsValues to different mesh.ent files (like a standard and looser-fitting version).

    hashtag
    But wait, couldn't I accomplish this by doing [x] instead?

    Yes, there are several ways to organize your item variants. The benefit is that you can use a single entry in your .yaml file for multiple variations, but it's just a matter of preference and what works best for your project.

    Chunkmasks: partially hiding meshes
    Displayed as in w_smg__militech_saratogabase1_01.ent
      $instances:
        - { type: sleeves, base_color: white, ribbons: red,  icon: 01 }
        - { type: nosleeves, base_color: black, ribbons: red,  icon: 02 }
    appearanceName: root_entity_dynamic_appearance_!$(base_color)+$(ribbons)
    appearanceName: root_entity_dynamic_appearance_$(type)_!$(base_color)+$(ribbons)
    Component prefixes

    Dynamic Appearances: Adding custom hat hairs

    How to add custom hat hairs that work the same way as the basegame hat hairs

    hashtag
    Wait, this is not what I want!

    • If you want to add a custom hat from the start, start with ItemAdditions: Dynamic Appearances and come back here once you've done that and have a hat minus the hair. The process for hats is no different than for other garment items.

    hashtag
    Prerequisites

    • You know how to add custom garment items with Dynamic Appearances

    • You either have your own WolvenKit project with a custom hat or you've downloaded the starting point project from

    circle-info

    Most of the names and paths given in this guide are specific to the example/template project. If you want to apply this guide to your own project, you'll have to make the transfer to the names in your project. If you get confused at some point, consider following the steps with the example project first.

    hashtag
    Assumed Skill Level

    If you can successfully add custom garment items with Dynamic Appearances to the game, you shouldn't have any problems with this guide.

    hashtag
    Step 1: Finding appropriate basegame hat hair meshes

    In WolvenKit use the Asset Browser to navigate to base->characters->common->hair

    Notice that for each basegame hat, there are four folders with hat hairs ending with a number between 1 and 4. These numbers are related to the different hair types:

    Find a set of hairs that seem to be a good starting point for your custom hairs.

    circle-info

    It is not necessary to use basegame hat hairs for your custom hairs. You can use any hair mesh from the game or custom-made hair. We just add basegame hat hairs for the sake of simplicity here. If you take an animated hair, keep in mind that your hat mesh entity will need the related entAnimatedComponent (aka hair_dangle) to work properly.

    circle-info

    Just ignore the body type tokens in the names of the hair folders. Some may seem like they're for ma, some for wa and some for something else entirely. The names are a lie. Each folder may contain meshes for multiple body types.

    hashtag
    Step 2: Adding the meshes to your project

    Use Wkit's mesh preview and decide on a starting point for your hat hairs. For this guide, we'll use h1_012_xx_hat__googles_hh_xx.

    Add the meshes of the set to your project with the ma/wa body type token and for all suffixes between 01 and 04. In the end you should have added 8 meshes to your project.

    hashtag
    Step 3: Renaming the hat hair meshes

    Add a new folder for the hair meshes to your project namespace. In this guide we'll use yourmoddername\yourmodname\hair_meshes.

    Move all the mesh files you added in Step 2 to the new folder.

    Rename the files. You can rename them to your liking, but it's important that they

    • still contain an m or w indicating the gender

    • you replace the number suffix with the matching hair type name (01- short, 02 - long, 03 - dreads, 04 - buzz)

    • all follow the same schema for the file name with just the body type token and the hair type name being different

    In this guide, we'll rename h1_012_xx_hat__googles_hh_xx to h1_xx_yourmodname_hair_xxxx with the body type token after h1 and the hair type at the end.

    E.g. h1_012_wa_hat__googles_hh_03 becomes h1_pwa_yourmodname_hair_dreads.

    The result should look something like this.

    circle-info

    The h1 prefix is not technically necessary. Neither is the full body type token pwa (player woman average). It is a good habit to stick to the conventions of the existing game files, though.

    hashtag
    Step 4: Adding the hair component to your entity

    Open the mesh entity of your hair item. In this guide the mesh entity is yourmodname.ent. Right-Click on the hat component h1_yourmodname and select "Duplicate in Array/Buffer".

    Expand the duplicated component.

    • Right-click on the id and select "Generate new CRUID".

    • Click on the name property and change it to h1_yourmodname_hair. This name will be important when we update the .app!

    • Click on the meshAppearance property and change it to *{hair_color}

    The final component should now look like this:

    hashtag
    Step 5: Updating the .app file

    Open your .app file, yourmodname.app. A working hat should have (at least) two appearances, one for first person view and one for third person view. In first person view, both the hat and the hairs should be hidden.

    • Expand the appearance for first person view. In the example project it's yourshortname_yourmodname_&camera=fpp.

    • Navigate to the partsOverrides property, expand the first element and in it the componentsOverrides property.

    circle-info

    If you started with a hat item that has no different appearances for fpp/tpp and no component hiders, consider downloading the "finished" example project and copy the appearances from its .app file.

    The result should look like this:

    hashtag
    Step 6: Checking your result

    Install the mod, give your V the hat item via console, equip it and check the result. If you followed all the steps your hat should now come with hair.

    circle-info

    Check the .yaml file of the template project if you're unsure about the item names. It has the full console commands as comments as well.

    Check both genders and all four hair types to be make sure it works correctly.

    circle-info

    Now is the time to make sure the hair is hidden in first person view, especially if the hair you picked has bangs or something like it. Crouch and jump and look up and down and left and right. It might not be immediately obvious if the hair is still visible in fpp. It might only be visible in certain situations or perspectives. The game is weird like that.

    hashtag
    Step 7: Make your hat hair compatible with CCXL hair colors

    circle-info

    This is step isn't strictly necessary, because at this point you already have working custom hat hairs. It's still a good idea to implement this, because CCXL additions are pretty much standard now.

    hashtag
    7.1 Converting the .mesh files

    In a file explorer open your Cyberpunk 2077 main directory and from there navigate to /red4ext/plugins/ArchiveXL/Bundle and open the file PlayerCustomizationHairFix.xl in a text editor.

    In Wkit find the original file of your first copied hair mesh in the Asset Browser and copy its relative path. In this guide that will be base\characters\common\hair\h1_012_wa_hat__googles_hh_01\h1_012_ma_hat__googles_hh_01.mesh.

    Search for the path in the PlayerCustomizationHairFix.xl and once found, scroll down to its context section.

    Make a mental note that this mesh uses a short base material and has a cap.

    circle-info

    This is only one possible way to find adequate base materials for your hat hairs as a start. There are other ways and of course you may want to use custom materials at some point. That's beyond the scope of this guide, though and the described way was simply chosen, because it is reasonably simple and doesn't require you to have your own custom materials to start with.

    Open the related mesh file. h1_pma_yourmodname_hair_short.mesh in our example and click on the ArchiveXL button and select "Convert hair to CCXL material".

    In the dialog that opens, select the matching main style for your mesh and if the mesh uses a cap select the "Include a Cap .mi file" check box. Since we won't use custom .mi files for now, we leave the dropdowns for the .mi files empty and click "Finish".

    Now scroll down to the localMaterialBuffer property and expand it and expand the materials.

    Expand the values of the @context property and fill the values of the ShortBaseMaterial and CapBaseMaterial with the values you found in the PlayerCustomizationHairFix.xl.

    In the @short and @cap entries, add the same material paths to the baseMaterial property and set its Flags to Soft.

    Save the file. The result should look like this for a mesh that uses a short base material and has a cap.

    hashtag
    7.2 Rinse and repeat

    Repeat the steps from section 7.1 for all hair .mesh files and use the matching values for short, long or dreads. When you convert a buzz hair mesh, select "Cap" in the conversion dialog and don't check the "Include a Cap .mi file" checkbox.

    hashtag
    7.3 Adding the necessary entries to the .xl file

    Open up your mod's .xl file and add the following entry to the patch region:

    circle-info

    This step is necessary as of ArchiveXL version 1.26.1, but psiberx already announced that he will have ArchiveXL auto-patch hat hairs in a future version of ArchiveXL, so it may be obsolete at some point.

    If you used different names or paths, make sure that the targets match your hair mesh file paths.

    Add the following scope region:

    This should again match the paths you used.

    If you started with the example project, the final .xl file should now look like this:

    Install the mod and make sure that each hair type and gender works with base game colors as well as CCXL colors.

    hashtag
    Step 8: Make it yours

    If you plan to use one of the template/example projects as a base for your own mod, you will need to rename each and every file, component and reference in the project.

    In short

    • Rename everything that contains "yourmoddername" to use your actual modder name instead

    • Rename everything that contains "yourmodname" to use your mod's name instead

    circle-info

    It's probably a lot easier and less error-prone to use Wkit's wizardry to create the initial hat item and then apply the steps described in this guide.

    hashtag
    Step 9: Edit your hair meshes

    You now have eight different meshes that will probably require at least some editing in Blender to fit to your hat. This is especially true if you picked other hairs than hat hairs to start with. This is where the fun starts!

    .
  • Now the most important thing, the mesh path.

  • Right-click on one of your hair mesh files in the Project Explorer and select "Copy relative path to game file".

  • Click on the mesh property on your hair component and paste the path into the DepotPath field.

  • Add an asterisk * at the front of the path and replace the w/m indicating the gender with {gender} and the hair type suffix with {hair_type}. In this guide the result will be *yourmoddername\yourmodname\hair_meshes\h1_p{gender}a_yourmodname_hair_{hair_type}.mesh.

  • Save the .ent file.

  • Right-click on the component that hides the hat, h1_yourmodname and select "Duplicate in Array/Buffer".
  • Change the componentName of the duplicated element to the name you picked for the hair component in the .ent in step 4.3. We picked h1_yourmodname_hair in this guide.

  • Save the file.

  • Modders Resource - Custom Hat Hairsarrow-up-right
    01 - short
    02 - long
    03 - dreads
    04 - buzz
    archive_xl\characters\common\hair\h1_base_color_patch.mesh:
      props: [ appearances ]
      targets: [ 
        yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_buzz.mesh,
        yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_dreads.mesh,
        yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_long.mesh,
        yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_short.mesh,
        yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_buzz.mesh,
        yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_dreads.mesh,
        yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_long.mesh,
        yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_short.mesh
      ]
    scope:
      player_ma_hat_hair.mesh:
        - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_buzz.mesh
        - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_dreads.mesh
        - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_long.mesh
        - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_short.mesh
      player_wa_hat_hair.mesh:
        - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_buzz.mesh
        - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_dreads.mesh
        - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_long.mesh
        - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_short.mesh
    resource:
      patch:
        yourmoddername\yourmodname\meshes\h1_pwa_yourmodname.mesh:
          - yourmoddername\yourmodname\meshes\h1_pma_yourmodname.mesh
        archive_xl\characters\common\hair\h1_base_color_patch.mesh:
          props: [ appearances ]
          targets: [ 
            yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_buzz.mesh,
            yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_dreads.mesh,
            yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_long.mesh,
            yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_short.mesh,
            yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_buzz.mesh,
            yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_dreads.mesh,
            yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_long.mesh,
            yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_short.mesh
          ]
      scope:
        player_ma_hat_hair.mesh:
          - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_buzz.mesh
          - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_dreads.mesh
          - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_long.mesh
          - yourmoddername\yourmodname\hair_meshes\h1_pma_yourmodname_hair_short.mesh
        player_wa_hat_hair.mesh:
          - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_buzz.mesh
          - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_dreads.mesh
          - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_long.mesh
          - yourmoddername\yourmodname\hair_meshes\h1_pwa_yourmodname_hair_short.mesh
    factories:  
      - yourmoddername\yourmodname\yourmodname_factory.csv
    localization:  
      onscreens:  
        en-us: 
          - yourmoddername\yourmodname\translation_strings.json

    Throwing weapons: projectiles

    How to make a custom projectiles for throwing weapons

    hashtag
    Summary

    Created by @manavortex Updated October 05 2023

    This page is a sub-page of Adding Weapons and tells you how to create a custom projectile for a throwing weapon.

    To create a custom throwing weapon, check the parent guide and use knife as a base type.

    circle-info

    Everything but the yaml works exactly like adding regular items (with a or , an and your weapon's mesh). This example will use a root entity.

    circle-check

    This process is about as finicky as the one for weapon additions. Make sure to test your changes after each step.

    hashtag
    Step 0: the yaml

    We now need to register our projectile. We already have a weapon, so let's define our projectile:

    Now, we need to tell our weapon about it. Add the following lines to its definition:

    If your weapon wasn't throwable before, it is now — but the projectile is still invisible. Time to change that.

    hashtag
    Step 1: the entity file

    circle-exclamation

    A projectile needs an .ent file as the factory's entry point, not an .app.

    You can find all projectile entities in base\gameplay\projectiles.

    triangle-exclamation

    Ignore anything that has default in its name.

    There are two kinds of .ent files: the ones that support multiple appearances, and the ones that don't. You can tell them apart by opening them and checking the appearances array (the first entry in the list).

    Pick the right kind of entity for your weapon:

    hashtag

    Use e.g. this entity file if you want to use multiple appearances:

    hashtag

    Use e.g. this entity file if a single appearance is enough for you:

    Add the file to your project, then rename it and (if you have one) move it to your weapon's folder.

    hashtag
    Step 2: The factory

    Now it's time to connect everything by registering the projectileTemplateName from your .yaml file in your factory.csv. As a reminder, this is the line we're talking about:

    Make sure that the corresponding entry points at your projectile's entity file from .

    circle-check

    Your factory should have two entries: one for the projectile, one for the weapon itself.

    From now on, your projectile will no longer be invisible. If it is, try setting your factory path to one of the game's original projectile entities - debugging time.

    hashtag
    Step 3: the .app

    circle-info

    If you're using a mesh entity (with an empty appearances array), you can skip this step.

    1. Expand the appearances array

    2. Select any of the appearances

    3. Check the appearanceResource's depot path

    hashtag
    Step 4: The right mesh

    circle-info

    If you are using a mesh entity (without an .app file), that's where you will find the components. Skip step 1 on the list below.

    1. Open your .app file . For each of the appearances, do the following:

      1. Expand the components array

    hashtag
    Step 5: Test

    If you did everything correctly, you should now have a custom projectile for thrown weapons.

    hashtag
    Troubleshooting

    For troubleshooting steps, please see the page.

    ItemAdditions: files from scratch

    How to set up the folder structure from scratch

    hashtag
    Summary

    Created: by @manavortex Last documented edit: June 10 2023

    This page is a part of the Adding new items guide and deals with finding the correct files for an ArchiveXL item addition.

    • For an explanation of the file structure, see .

    • If you want to add an atelier store, see .

    • If you want to add preview items, check .

    • If you want to port a mesh from a different game to Cyberpunk, check

    circle-info

    TL;DR: If you can't be arsed doing this by yourself, find a template project with one working item (female rigged) .

    hashtag
    Overview:

    File in modded dir
    was originally copied from
    triangle-exclamation

    For mesh_entity.ent, your entity file needs to correspond to your item's body part. If you put a shirt in an entity file for shoes, it will deform badly once you put it on.

    If you rename your components, we recommend using CDPR's for reasons of garmentSupport. You don't need to understand how this works, just name your component like l1_myCustomPants instead of myCustomPants and call it a day.

    circle-check

    It is good practice to keep local copies of everything that you change (=> custompathing) instead of overwriting files under base. This makes sure that no other mods will overwrite your changes.

    ℹ Only keep files under base if you are okay with them being overwritten!

    hashtag
    Optional, but very recommended: Clean out obsolete entries

    1. Open the file translation_strings.json in WolvenKit. Expand the array root and then the array entries. Delete all entries but one.

    2. Open the file my_shirt_factory.csv in WolvenKit. In compiledData, delete all entries but one. In data

    circle-check

    Now is a good time for a backup.

    Your own Atelier Store

    How to set up an atelier store for your mod

    This guide will detail how to add an Atelier store with your items. It is part of the ArchiveXL tutorial, but you can complete these steps independently.

    hashtag
    Wait, this is not what I want!

    • Find a guide on

    base\characters\garment\gang_monk\torso\t2_135_jacket__monk_shirt\t2_135_wa_jacket__monk_shirt.mesh

    my_tshirt_factory.csv

    base\gameplay\factories\items\clothing.csv

    translation_strings.json

    base\localization\en-us\onscreens\onscreens.json

    preview_icons.inkatlas

    base\gameplay\gui\common\icons\items\item_icons6.inkatlas

    preview_icons.xbm

    base\gameplay\gui\common\icons\items\item_icons6.xbm

    tutorial_my_custom_tshirt.archive.xl

    Wolvenkit -> New File -> ArchiveXL

    tutorial_my_custom_tshirt.yaml

    Wolvenkit -> New File -> TweakXL

    For further details, check here.
    , delete everything - these will get autogenerated.
  • Open the file root_entity.ent.

    Expand the list appearances. Delete all entries but the first (most likely default).

  • Open the file my_custom_shirt.app. Expand the list appearances. Delete all entries but default.

  • Open the file mesh_entity.ent Select resolvedDependencies and delete all the entries. (We don't need Judy's top anymore.)

  • Make a back-up copy of your t1_custom_shirt.mesh, then open it.

    1. Expand the first appearances at the top of the file. Open the appearance default and check which material is linked in the chunkMaterials array.

  • rootentity.ent

    base\gameplay\items\equipment\underwear\player_underwear_item.ent

    appearance.app

    base\gameplay\items\equipment\underwear\appearances\player_underwear_item_appearances.app

    mesh_entity.ent âš  Check the red hint box âš 

    base\characters\garment\player_equipment\torso\t1_080_pwa_tank__judy.ent

    ItemAdditions: File structure explained
    Your own Atelier Store
    Your own inventory preview icons
    Porting 3d objects to Cyberpunk
    herearrow-up-right
    naming prefixes

    my_mesh.mesh

    Add this file to your project

  • Rename it and move it to your custom folder.

  • Open your root entity. For all of the appearances, change the appearanceResource path to that of your .app.

  • For any components that have Mesh in their type name:
    1. Change the mesh depotPath to your weapon's custom mesh

    2. Change the meshAppearance to one of your weapon's appearances

  • Open resolvedDependencies and replace the path to the original mesh with your own.

  • rootarrow-up-right
    mesh entityarrow-up-right
    .app filearrow-up-right
    Root entityarrow-up-right
    Mesh entityarrow-up-right
    step 1
    ItemAdditions: Weapons
    KnifeAttacks.MyKnifeThrowAttackProjectile:
      $type: Attack_Projectile
      projectileTemplateName: my_new_weapon_projectile_name
    Items.my_knife:
      # the rest of your weapon's definition
      projectileTemplateName: my_new_weapon_projectile_name
      useProjectileAppearance: true
      attacks: 
        - !append KnifeAttacks.MyKnifeThrowAttackProjectile
    base\gameplay\projectiles\knife\tanto_projectile.ent
    base\gameplay\projectiles\knife\knife_projectile.ent
    KnifeAttacks.MyNewWeaponThrowAttackProjectile:
      projectileTemplateName: my_new_weapon_projectile_name

    Learn more about Game icons: .inkatlas files

  • If you are using ItemAdditions: Dynamic Appearances, you can use W's generatorarrow-up-right to quickly create spawn codes and Atelier entries

  • hashtag
    Requirements

    circle-exclamation

    You need to install the VirtualAtelierarrow-up-right mod for this.

    You also have to add it to your mod's requirements, as atelier stores will cause script errors if users don't have it installed.

    hashtag
    Generating an icon

    First of all, downloadarrow-up-right the template archive (kindly provided by Apart) and find the folder virtual_atelier_inkatlas_icon_template with the following files:

    Put the .inkatlas and .xbm into your project (if you're using the example project, you can put them into the ops folder). Then, rename them to atelier_icon:

    Now, create your icon. The process is the same as for "preview images". The resulting slot will be named slot_01.

    hashtag
    Creating the atelier file

    chevron-rightExample store file (if you don't want to use the generator)hashtag
    1. Visit thisarrow-up-right website and fill out the information:

    Field
    Content

    Store ID (characters only, w/o spaces, '-', '_' and etc.)

    MyTutorialAtelierStore

    Store Name

    My Tutorial Atelier Store

    Atlas Resource

    tutorial/torso/my_custom_shirt/ops/atelier_icon.inkatlas

    Texture Part

    1. Now, add your item.

    circle-exclamation

    In atlasResource, you have to replace all \ with /

    Your atelier store will cause script errors if you don't.

    Here's an explanation for the fields below. Rather than filling them by hand, you should use thisarrow-up-right website to generate your store files.

    Field
    Content

    TweakDBID

    as defined in your yaml, e.g.

    Items.my_custom_shirt_redwhite

    Price

    Whatever price you want, 0 means that it's free

    Quality

    Are we settling for anything but legendary here? Allowed values are: - "IconicItem" - "Legendary" (LegendaryPlus, LegendaryPlusPlus) - "Epic" (EpicPlus) - "Rare" (RarePlus) - "Uncommon" (UncommonPlus) - "Common" (CommonPlus)

    ​ Ignore "Icon path" and "description", we have these in the item itself.

    1. Click "Add Item". Repeat the process with as many items as you want.

    2. Click "Generate".

    triangle-exclamation

    In the downloaded file, check that atlasResource has forward slashes / instead of backwards slashes \, as per the warning box above.

    hashtag
    Placing the atelier file

    In your project's resources folder, create a subdirectory r6/scripts (if it doesn't exist already), and move the atelier file that you downloaded into there:

    Now, it's time to test! Install the mod and start Cyberpunk.

    hashtag
    Troubleshooting

    hashtag
    My atelier store causes scripting errors!

    I'm not sure how you managed to read past all the red and yellow boxes on this page, but make sure that the path under atlasResource has forward slashes / instead of backwards slashes \.

    If that wasn't it, you might have to re-generate your Atelier store.

    hashtag
    My atelier store makes the game crash!

    That happens when there are two atelier stores with the same store ID. Do a full-text search for the store ID (MyTutorialAtelierStore) in r6\scripts and make sure that you don't have any duplicates.

    Adding new items
    Your own inventory preview icons

    ItemAdditions: Dynamic Appearances

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

    hashtag
    Summary

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

    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.

    chevron-rightTL;DRhashtag

    In your root_entity:

    1. Add the DynamicAppearance tag

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

    hashtag
    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 .

    • If you want to create an Atelier store, see

    hashtag
    Prerequisites

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

    • >= 8.11.0 (you should have it )

    • >= 1.4.4

    • >= 1.5.0

    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.

    hashtag
    How is this better than the old approach?

    circle-info

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

    chevron-rightWhy dynamic appearances are superiorhashtag

    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.

    hashtag
    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 section if you run into issues, and to run File Validation ->to check for common mistake.

    hashtag
    Step 0: Run the generator

    chevron-rightArchived lore: the example projecthashtag

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

    1. Create a

    2. Find the on Nexus

    1. If you haven't, go and create a . 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. For the example project, I'll create a t-shirt:

    chevron-rightThe fields, Mason! What do they mean?hashtag

    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

    hashtag
    0.1: Import the icons

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

    circle-info

    You can now delete the .png files.

    Check 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.

    hashtag
    Generated files

    circle-info

    Optional, but recommended: Readto 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:

    hashtag
    Step 1: Connecting the decal (and understanding variants)

    circle-exclamation

    Before starting this section, create a copy of your mesh_entity.ent now (press the ctrl-key and drag it on itself), as you need the original file for one of the alternative approaches.

    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.

    chevron-rightExampleshashtag
    raw variant
    variant
    variant.1
    variant.2

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

    As you can see, the paths are already dynamic - the m or w has been replaced with {gender}. This makes sure that our mod will display the right file based on your V's body gender.

    circle-info

    This is incredibly powerful — for example, by using {body}, you make ArchiveXL pick the correct refit per body mod. contains a full list of suffixes and substitutions, but do finish this guide and its exercises before playing around even further!

    Now, let's get that decal connected.

    1. Select the first deactivated component, and turn it on by 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 (see the expandable above), we have the following values for variant.2:

    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.

    circle-info

    This approach is not recommended for anything user-editable. For details, see

    hashtag
    Exercise 1: Other options

    Dynamic mesh picking based on yaml params saves a lot of duplication, typos can lead to crashes — 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 doesn't exist.

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

    circle-info

    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.

    chevron-rightmesh_entity: One decal mesh, multiple appearanceshashtag

    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 guide)

    The result would look like this:

    chevron-right_app: Three decals, one appearance, partsOverrideshashtag

    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)

    hashtag
    An example of a real mod

    I use both of these techniques in my 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.

    chevron-rightHow University Outfit uses dynamic variantshashtag

    Polo: Collar states

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

    mesh
    submeshes for "closed"

    hashtag
    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, but that the rest of the files has gotten a lot more manageable:

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

    hashtag
    Tools and utilities

    hashtag
    Generating display names

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

    hashtag
    Creating preview icons

    This problem is so common that it has its own wiki page:

    hashtag
    Troubleshooting

    Please see the original guide's section.

    Step 1: Connecting the decal (and understanding variants)
    @addMethod(gameuiInGameMenuGameController)
    protected cb func RegisterYOURNAMESStore(event: ref<VirtualShopRegistration>) -> Bool {
      event.AddStore(
        n"YOURNAME",
        "Your Store Name",
        [            
          "Items.my_custom_shirt_redwhite",  	
          "Items.my_custom_shirt_redblack"
    	],
    	[ 1	],
        r"tutorial/torso/my_custom_shirt/ops/atelier_icon.inkatlas",
        n"slot_01",
    	[ "Legendary" ]
      );
    }
    atelier_icon_template.inkatlas                        << map for the game  
    atelier_icon_template.png                             << 200x200px image for a final slot  
    atelier_icon_template.xbm                             << game texture  
    virtual_atelier_png_to_xbm_import_settings.png        << image, also embedded here  
    tutorial
      torso
        my_custom_shirt
          ops		   
          	- my_shirt_factory.csv  
          	- translation_strings.json  
          	- preview_icons.inkatlas       
          	- preview_icons.xbm            
          	- atelier_icon.inkatlas        <<<  
          	- atelier_icon.xbm             <<<  
    resources
      - tutorial_my_custom_tshirt.archive.xl  
      - r6
        - tweaks
          - tutorial_my_custom_tshirt.yaml         
        - scripts
          - MyTutorialAtelierStore-atelier-store.reds         << new file

    slot_01

    Name it like your entityName in the yaml
  • 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

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

    Red4extarrow-up-right >= 1.17.0

  • Cyber Engine Tweaks arrow-up-right(for spawning items)

  • 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

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

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

  • 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 ->

    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 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.

    samurai

    $(base_color)$(secondary)

    blacksamurai

    blacksamurai

    -

    $(base_color)+$(foo)

    black+

    black

    -

    galaxy

  • samurai

  • witcher

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

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

  • 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.

    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.

    $(base_color)+$(secondary)

    black+samurai

    ArchiveXL's githubarrow-up-right
    Your own Atelier Store
    WolvenKitarrow-up-right
    TweakXLarrow-up-right
    ArchiveXLarrow-up-right
    the next section
    template projectarrow-up-right
    Your own inventory preview icons
    Dynamic appearances: Understanding the process
    ArchiveXL: Suffixes and Substitutions
    Adding decals
    University Outfitarrow-up-right
    vanilla variants
    original guide
    Python scriptarrow-up-right
    Running Python Scripts
    Your own inventory preview icons
    Troubleshooting
    Exercise 1: Other options

    black

    Sumi
    Sumi

    number of mesh entity files

    6

    1

    number of components per mesh entity

    2

    5

    Adding new items

    No more replacers! Add your own gear with TweakXL and ArchiveXL

    hashtag
    Summary

    Created & Published: November 04 2022 by @manavortex Last documented Update: March 12 2025 by mana vortex

    This guide will walk you through adding your own items to Cyberpunk 2077, which can then be spawned via console.

    It has been verified with the following versions (yours should be equal or higher)

    Tool
    latest version tested
    oldest version tested

    Assumed skill level: You should be able to find your way around WolvenKit, but I aim to keep this as noob-friendly as possible. In case you prefer visual learning, there is also a video version of this guide available here -

    This guide will give you a working mod with a very basic structure. In the section , you're guided through various processes that will help you to understand how things connect, and teach you how to use ArchiveXL to add your own items.

    triangle-exclamation

    For experienced modders

    I have repeatedly observed that newbies are fine with this guide, while people who know how to mod are not. Watch out for boxes like this one to avoid those pitfalls.

    The guide was created after reading and being left with a bunch of question marks. This guide is horribly outdated and I'm only citing it here because it got me started into the rabbit hole. &#xNAN;To get a deeper understanding of the process, you can follow the linked resources, or consult ArchiveXL's .

    hashtag
    Wait, that's not what I want!

    • Visual learners rejoice: You can find a video of this guide on youtube ()

    • To troubleshoot your ArchiveXL mods, you can use 's .

    • If you want to convert a mod to dynamic appearances, check the

    hashtag
    Or maybe for something completely different?

    • To learn about Cyberpunk's material pipelines, check out

    hashtag
    Step 0: Grab the example files

    • Create a new Wolvenkit project

    • Download the prepared files from and extract them to the root of your new project (overwriting the "source" folder)

    circle-info

    If you would rather start from scratch: Check the detailed instructions .

    Understanding of the file structure is not required as long as you follow the guide to the letter, but if you want it anyway, see the sub-page.

    triangle-exclamation

    âš  Do not edit those files outside of WolvenKit, and whatever you do, do not let Microsoft Excel touch the clothing.csv! âš 

    hashtag
    You should now have the following files:

    hashtag
    Start the game

    circle-info

    Wait, am I not supposed to do anything first??

    Actually, no! This is how you later debug your custom items — by packing your project and checking that everything works in-game.

    We're starting with a dry run to get you familiar with the process.

    Press in WolvenKit. This will do the following things:

    1. Wipe the folder packed

    2. Copy all supported file entries from source to their destination under packed

    Now, you can

    1. Launch the game.

    2. Spawn one of the tutorial items via Cyber Engine Tweaks and equip it: Game.AddToInventory("Items.my_custom_shirt_redwhite")

      Game.AddToInventory("Items.my_custom_shirt_redblack")

    You should now see your the tutorial item. If not, consult the section below, or retrace your steps and make sure all mods are installed correctly before continuing with

    hashtag
    Great! You added items! Now what?

    triangle-exclamation

    Before you can publish your mod, you must complete the steps at .

    You've successfully pushed a button and everything worked, but so far, you haven't done anything.

    If you're okay with this, then you're done now. Otherwise, you'll want to keep reading.

    circle-exclamation

    If you want to have many colours or both body genders:

    Do yourself a favour and use .

    You might have been given the Easy Item Additions tool, or you might be familiar with older tutorials. Please believe me: even doing this by hand is less effort than filling out all the fields.

    Otherwise, you will want to complete one or more of the following steps:

    • change the mod to use (e.g. shoes or glasses)

    • Learn about for e.g. or check the

    • Learn about making more variants:

    circle-check

    To start changing the existing files, check the page for "Making Changes" headers.

    hashtag
    Diagram

    This is how everything connects. Looks pretty scary, but is actually simple: whenever you want to rename or repath something, make sure that you catch both ends of the connecting lines.

    You can find a breakdown-by-entry on the .

    circle-check

    With ArchiveXL >= 1.5, there is a new way of making these connections, saving most of the work of making many variants. You can still complete this guide and then see the documentation for dynamic loading .

    If you want to do more than 5 variants (for both body genders and camera modes), that approach is strongly recommended. Since there isn't a detailed guide yet, you can find us on in the #archive-xl channel.

    hashtag
    Adding an appearance

    circle-exclamation

    Before you add an appearance, make sure that your item is loading up correctly and looking as expected. If you have to debug, you will have to look through every appearance you made!

    For experienced modders: This includes you! :)

    circle-info

    If you would rather have a step-by-step guide for a gendered variant, see .

    To add an appearance, you will have to touch the following files:

    1. *.yaml: Adding an entry

    2. appearance.app: Adding a mapping between root_entity and mesh's appearance

    3. root_entity.ent: Adding a mapping between yaml's appearance and app's appearance

    circle-info

    For a diagram of how everything connects, go .

    hashtag
    Step 1: Register it in your *.yaml

    1. Duplicate the entire appearance block for an already working item. âš Mind the indent!

    2. Change the first line to a unique name like Items.my_custom_shirt_blueblack

    3. Set the new appearance name for the root_entity.ent

    The total entry should look like this:

    hashtag
    Step 2: Add it to the root_entity.ent

    Find the step-by-step guide in the on the "" page.

    If you want to add a , make sure to add the DynamicAppearance tag here.

    hashtag
    Step 3: Add it to my_custom_shirt.app

    Find the step-by-step guide in the on the "" page

    hashtag
    Step 4: Add it to the .mesh

    This tutorial assumes you already know how to . Quick reminder about the mlsetup:

    1. Export it to json

    2. edit the mlsetup.json with the

    3. Import it back

    Find the step-by-step guide in the on the "" page

    hashtag
    Test it

    Now, log into the game and spawn the item variant. The name is the header you defined in the yaml file, in this case

    circle-check

    If it works, this is an excellent moment to take a backup! If not, check at the end of the page, fix your problem, and make a backup after.

    hashtag
    Adding a Male Instance

    circle-exclamation

    This is a great opportunity to switch over to the approach.

    For a step-by-step guide on how to convert your mod, check.

    If an item is rigged for the female body gender, it will look wonky if worn by a male-rigged V. (But we have a snarky tooltip, so that's OK!)

    This section of the guide will teach you how to fix that, adding versions for both body genders.

    triangle-exclamation

    Screenshots in this part of the mod may be outdated.

    hashtag
    Finding the mesh file for the male variant

    circle-info

    To keep things simple, we'll be using a different mesh here, rather than walking you through the whole refitting and conversion process. If you want to do that, you can check out

    To fix this issue, we'll need a mesh that's compatible with Male V.

    In the interest of keeping things simple, we've found just the mesh for you! It's called t1_024_ma_tshirt__sweater.mesh and it can be found in the base\characters\garment\citizen_casual\torso\t1_024_tshirt__sweater directory.

    circle-exclamation

    If you plan on using other meshes for your mod, ensure that they have _ma_ or _pma_ in their name.

    Keep in mind that some ma meshes may still have clipping issues when paired with certain types of clothing, while pma meshes are specifically designed for V and don't have this problem.

    Now, add the file to your project, move it to the tutorial\torso\my_custom_shirt\ folder and rename it from t1_024_ma_tshirt__sweater.mesh to my_mesh_m.mesh.

    Next, follow the steps you used for the original my_mesh.mesh by removing any unnecessary entries and adjusting the indices.

    triangle-exclamation

    To avoid any issues, it's crucial to pay close attention to this step and double-check that the correct materials are present in the localMaterialBuffer and materialEntries, and that the indices are adjusted correctly.

    This will ensure that your mod works as intended without any glitches or errors. If you need a refresher, to return to that section.

    hashtag
    Creating a .ent File for Your Custom Mesh

    It's time to set up the .ent file for our mesh. Don't worry, it's easy!

    Start by making a copy of the mesh_entity.ent file that you previously created for the female version by duplicating it, and rename it to mesh_entity_m.ent.

    Inside the mesh_entity_m.ent file, find the first component of the type entGarmentSkinnedMeshComponent. Set the following values:

    hashtag
    Edit the yourModName.yaml

    Inside the yourModName.yaml file set the appearanceSuffixes array to itemsFactoryAppearanceSuffix.Gender

    circle-info

    If you are unclear about why this step was taken, we recommend !

    hashtag
    Edit the root_entity.ent

    1. Find the array appearances.

    2. Expand the first entry.

      1. Append &Female to the name attribute. This will change the name from appearance_root_entity_white_red

    hashtag
    Edit the appearance.app

    1. Find the array appearances

    2. Duplicate the first entry to create a new one and expand it

    3. Set the name attribute to my_shirt_m

    hashtag
    Testing the mod

    To test your mod, it's important to ensure that it works correctly for both male and female V. This means you'll need to have two separate save files, one for male V and one for female V, unless you're using a mod that allows you to quickly switch between them.

    Test your mod independently for both cases by loading the appropriate save file and checking that the mod is working as intended. To spawn and equip your item, use the command specified in your YAML file.

    circle-check

    Consider reviewing the guide to ensure that all steps have been followed correctly and that the values have been set appropriately. Ensure that the mesh is compatible with the male variant of V. If errors persist, review the for further assistance.

    hashtag
    The final touches

    If everything is working: Congratulations! You have successfully made a mod!

    But before you can share it, you need to do one last thing, which is changing the file structure. Otherwise, everyone will overwrite the same tutorial files, and only one of those mods will work.

    You can find a full guide on how to do that .

    circle-check

    That's it! If everything works, you're done!

    hashtag
    Troubleshooting

    Before starting to troubleshoot, make sure that you have all the requirements installed and up-to-date — , and .

    circle-info

    The easiest way to spot what's wrong is to use Wolvenkit's . You can run it from the menu bar above your editor.

    First of all, check the logs for errors including the name of your mod:

    • red4ext/plugins/ArchiveXL/ArchiveXL.log

    • red4ext/plugins/TweakXL/TweakXL.log

    Fix any errors that

    hashtag
    ArchiveXL added clipping!

    You have read right past those warning boxes telling you about . Make sure that you add them back.

    hashtag
    My item warps weirdly

    ... deforms incorrectly, or is a puddle on the floor?

    Most likely, you have ignored the when picking your mesh_entity.ent: Make sure that you're using an entity file that corresponds with the slot that you are trying to replace (e.g. if your item is a pair of shoes, you need an entity file from base\characters\garment\player_equipment\feet).

    circle-info

    If you are here because of a link from a different guide:

    You can find out which entity file your item uses by right-clicking on your mesh and selecting "find files using this". Add the .ent file to the list and open it in WolvenKit. Then, of the "components" array with those of an .ent file from the correct folder — don't forget to change the path to your mesh again!

    hashtag
    I can't add my item with the spawn code!

    When you can't spawn your item with CET, then the error is between the yaml, the factory, and the root entity.

    circle-exclamation

    Before you start digging into your file structure, check if there are any leftover yaml files from earlier versions/deploys in your tweaks directory. Do a full text search in e.g. Notepad++ in any files in the folder with the name of the item you want to spawn.

    If no additional yaml files are messing things up, then the error is somewhere in the first part of the chain and relatively easy to fix:

    Check the following places:

    • yourmodname.yaml:

      • Is the indentation correct, as shown in the picture? You can use to check.

      • Did you make any typos?

    hashtag
    My item shows empty text instead of name/description!

    Something went wrong with your json file:

    If there are no errors in any of the log files, check the following places:

    • yourmodname.archive.xl:

      • Does the key localization - onscreens - en-us exist?

    hashtag
    The item spawns, but…

    Congratulations, you've made it into the lower left part of the diagram, and can also make use of Wolvenkit's now! The error will be somewhere here:

    circle-check

    can help you catch the error.

    circle-info

    If you set your mesh_entity.ent to point at a vanilla mesh, you can rule out your custom mesh and .mlsetup as a source of errors. Original game meshes will always have a working default appearance and will thus always be displayed!

    hashtag
    Nothing happens when I equip it!

    There is a short glitch (or maybe not), but the previous item is still visible, and nothing happens. Or, for head items, V is bald all of a sudden because their hair is gone.

    hashtag
    Narrow it down

    Let's check if the game finds your root entity. For that, we'll do two things (don't forget to un-do them later):

    1. Change the base type

    2. Add a tag to the root entity

    Helmets are hiding hair by default, unless you tell them not to. We'll make use of that by changing your item's $base in the .yaml:

    In your root entity, open visualTagsSchema -> visualTags -> tags (create any entries that are missing) and add the following CName:

    You can now start the game and equip your item again.

    hashtag
    V has hair

    Your root entity is working, and the error is somewhere here:

    hashtag
    V is bald

    Your root entity is not recognized and the error is somewhere here:

    hashtag
    It's invisible in photo mode!

    Try using other equipment slots, just to check. E.g., if your item is a face item (mask), set its $base in the yaml to e.g. Items.GenericOuterChestClothing

    hashtag
    Parts of my mesh are invisible!

    You have an incorrect material assigned. Check your chunkMaterials in the mesh.

    hashtag
    ArchiveXL ignores my dynamic variants!

    No, it does not. You have an incorrect material assigned. (And I'm totally not writing this after 3 hours of troubleshooting -.-)

    hashtag
    The game crashes!

    That means the chain is working, but something isn't loaded correctly. That's good! Check the following files:

    • appearance.app: Check the partsValues and partsOverrides entries. They need to point at the mesh_entity.ent, not at the mesh.

    • mesh_entity.ent: Does the component

    If the default mesh is displayed correctly, then we have narrowed down the problem.

    If the default mesh is not displayed correctly, then there's an issue between the root_entity and your .app file, or in the .app file's internal logic.

    hashtag
    Troubleshooting a mesh

    For more detailed error handling, check the sections below, or check .

    circle-info

    In the "Mesh Preview" tab of your mesh, you can "Generate Materials for Appearance". If the correct colours show up, you can at least rule out that the error is in the .*mesh or its material.

    The easiest way to troubleshoot your mesh is by using Wolvenkit's and keep an eye on the log view.

    chevron-rightManually checkinghashtag
    • Make sure that you have the same number of entries in materialEntries and localMaterialBuffer.materials .

    If none of that helps, I suggest

    • doing a gdb export

    • throwing away your mesh (don't close the WKit tab yet), falling back to an original game item

    • doing a gdb import

    hashtag
    My mesh is black and shiny!

    Congratulations, this is about the easiest-to-resolve error that you could've had. Your mesh is loaded correctly, there is only a problem with the rendered material.

    The easiest way to troubleshoot your materials is by using Wolvenkit's and keep an eye on the log view.

    chevron-rightManually checkinghashtag

    Check your mesh file:

    • Check the connection between appearance, materialEntry and localMaterial.CMaterialInstance. Are the names correct?

    hashtag
    My mesh has the wrong appearance!

    Either an appearance is incorrectly selected (app file), or it is incorrectly resolved (mesh file). Check the following places for copy-paste/duplication mistakes:

    yourModName.yaml - is the appearanceName correct, or did you forget to change it?

    If you are not using , also check the following two files: root_entity.ent - does the name corresponding to the field above point to the right appearanceName in the right .app file? appearance.app - does the appearance's partOverride set the correct appearance in the componentsOverride?

    Now, check the mesh file (close and re-open it to make everything refresh):

    appearance - do the chunk entries point to the material that you want? materialEntries - is the index correct, or is it pointing at a different material? localMaterialBuffer - does the CMaterialInstance use the correct .mlsetup file?

    Finally, check the .mlsetup itself: does it actually use different colours, or is it just a duplicate?

    hashtag
    My mesh is invisible!

    Here we go. This is the big one, and it's Not Fun. The error can be anywhere between the yaml and the mesh. You can rule out one of the files with the following questions:

    Does file validation yell at you? If not: The error is between the yaml and the root entity. Check the .yaml, the .xl, and the root entity itself. The most common cause are incorrectly spelled appearanceNames. If yes: Unless the errors are warnings, fix them first.

    Does the glitching stop after <10 seconds? If not: the appearance can't be resolved - ignore the .mesh If yes: the appearance is resolved, but can't be displayed - ignore the .yaml

    circle-info

    The fastest way to find your error is Wolvenkit's FileValidation (in version >= 8.9.1). Save the root_entity.ent, and the recursive valudation will check the whole chain for errors and print them to the log files for you.

    As of July 2023, you can download the right version from the page (for example , as it's pretty stable).

    circle-info

    If the appearance is resolved, but not displayed (short glitch), the first thing you should do is to change the path in the mesh_entity.ent to one of the game's default meshes. This will rule out errors on your part. (Yes, even if your mesh worked in another mod. No, I'm not speaking from experience, why do you ask?)

    If the hint above doesn't solve it, proceed to troubleshoot in the same way as "My mesh has the wrong appearance!" above.

    hashtag
    My garment tucks into/under other garments incorrectly

    That's due to - check the link to learn more.

    hashtag
    Visual tags aren't working!

    If you are hiding components via visual tags, these tags have to go into the .app file rather than the root entity. File validation should complain about this.

    hashtag
    I can't find anything, kill me now

    Time to restore your files one by one to the last working backup and restart from there. Don't delete them, keep them in a different folder - you will be able to copy a lot of stuff over.

    circle-info

    By right-clicking on a tab title, you can move it to a new document group for easier copying.

    Good luck, soldier.

    Troubleshooting
    mana vortex
    mana vortex

    ItemAdditions: Weapons

    Adding weapons

    hashtag
    Summary

    Published: July 08. 2023 by Last documented update: Feb 07 2024 by @manavortex

    This guide will teach you how to change the ArchiveXL item addition process to make it work for a weapon.

    1.8.1

    1.4.3

    1.18.0

    1.12.0

    (for spawning items)

    1.28.1

    1.28.1

    If you want to use dynamic appearances out of the box, check ItemAdditions: Dynamic Appearances (this is the preferred approach as soon as you're creating different options).
  • If you're making a weapon, check ItemAdditions: Weapons, or the more elaborate New Iconic Weapon: Step by Step guide.

  • Copy all files under packed into your game directory (it will overwrite without prompting)
    To familiarize yourself with the process, you can follow the ArchiveXL: Dynamic conversion guide and convert the example project.

    Create Your own inventory preview icons

  • Create Your own Atelier Store

  • Learn about Porting 3d objects to Cyberpunk

  • *.mesh:

    1. Adding a MeshMaterialEntry

    2. Adding a MaterialInstance

    3. Adding a material

    4. Connecting those things

    appearanceName: appearance_root_entity_black_blue
  • For lookups in your translation file (translation_strings.json): Change the values of displayName and localizedDescription to the corresponding secondary keys in the json file. This is optional.

    ℹIf you make any mistakes here, the worst that happens is an empty string.

  • Now, add a new entrie to your .json file:

  • If you decide to create your own mesh, be sure to fix any potential issues before using it in your mod. Check out our 3D modeling guidearrow-up-right for helpful tips and resources.

    Remember, a little extra effort in the beginning can save you a lot of headaches down the line!

    to
    appearance_root_entity_white_red&Female
    .
  • Duplicate the first (and only) entry to create a new one.

  • Expand the newly create entry

    1. Set name : appearance_root_entity_white_red&Male.

    2. Set appearanceName : my_shirt_m.

  • (as defined in the root_entity)
  • Find the array partsValues

    1. Set the resource path to your new male mesh entity file: resource : tutorial\myshirt\mesh_entity_m.ent

  • Find the array partsOverrides

    1. Find the array componentOverrides

      1. Set componentName : my_shirt_m

    2. Set partResources : tutorial\torso\my_custom_shirt\mesh_entity_m.ent

  • yourmodname.archive.xl:

    • Is the indentation correct, as shown in the picture? You can use yamllintarrow-up-right to check.

    • Did you make any typos?

  • my_tshirt_factory.csv:

    • Is there an entry where the first value matches the entityName from the yaml (my_tshirt in the picture above)?

      • Without leading or trailing spaces?

    • Does the second value of that entry have the correct root entity path? (tutorial\myshirt\root_entity.ent in the picture above) &#xNAN;If you moved the root_entity.ent, you have to adjust this entry.

  • root_entity.ent:

    • Do you have an appearance with the name matching your item's appearanceName in the yaml?

      • Without leading or trailing spaces?

    • If you are using suffixes, consider following the to make your project use instead.

  • Is the indentation correct, as shown in the picture? You can use yamllintarrow-up-right to check.
  • Does it point at the correct file (tutorial\ops\translation_strings.json), or did you rename or move it?

  • Did you make any typos?

  • yourModName.yaml:

    • Is the spelling for the key you defined after displayName and localizedDescription identical to the one in the json file?

  • translation_strings.json:

    • Is the spelling of the key defined in yaml's displayName and localizedDescription identical?

    • Did you set the femaleVariant (default)?

    • Are you using quotation marks? If so, switch to single quotes!

    • If the field for primary_key is not empty, then its value must be unique (probably on a per-file basis). Set it to 0.

  • entry point to a valid mesh? Try it with a default mesh as detailed above.
    Go through the
    CMaterialInstance
    s in
    localMaterialBuffer.materials
    .
    • Make sure that the files you're loading exist.

    • Make sure that you don't load a mlmask under a key for an mlsetup or vice versa.

    replacing the arrays appearances, localMaterialBuffer.materials and materialEntries with those from your previous mesh.

    Go through the CMaterialInstances in localMaterialBuffer.materials.

    • Make sure that the files you're loading exist.

    • Make sure that you don't load a mlmask under a key for an mlsetup or vice versa.

    WolvenKitarrow-up-right

    8.12.1

    8.9.0

    TweakXLarrow-up-right

    1.5.2

    1.1.4

    https://www.youtube.com/watch?v=r3nyFm-9h9o&t=3sarrow-up-right
    this onearrow-up-right
    documentationarrow-up-right
    https://www.youtube.com/watch?v=r3nyFm-9h9oarrow-up-right
    ArchiveXL: Dynamic conversion guide
    AMM: Textured items and Cyberpunk Materials using Custom Props
    Nexusarrow-up-right
    here
    item structure explained
    ItemAdditions: Dynamic Appearances
    Different equipment slots
    ItemAdditions: File structure explained
    corresponding wiki page
    on its own page
    Discordarrow-up-right
    the next section
    here
    root entity section
    Item structure explained
    dynamic appearance
    appearance section
    Item structure explained
    recolour an item
    MLSetupBuilderarrow-up-right
    mesh file section
    Item structure explained
    ItemAdditions: Dynamic Appearances
    ArchiveXL: Dynamic conversion guide
    click here
    reading up on suffixesarrow-up-right
    troubleshooting section
    here
    Red4extarrow-up-right
    ArchiveXLarrow-up-right
    TweakXLarrow-up-right
    FileValidation featurearrow-up-right
    component name prefixes
    hint box
    replace the contents
    yamllintarrow-up-right
    this page
    dynamic variants
    Nightlyarrow-up-right
    this onearrow-up-right
    garment support
    These files do not contain an Atelier store. If you want to add one, see here.
    Don't panic, we've got this.
    duplicating mesh_entity.ent and creating the new mesh_entity_m.ent for out new mesh
    All of the changes made to mesh_entity_m.ent file
    All of the changes made to root_entity.ent file
    All of the changes made to appearance.app file. Paths are not up-to-date!
    Great! You added items! Now what?
    WolvenKit
    Troubleshooting
    Great! You added items! Now what?
    The final touches
    Adding a Male Instance
    Adding an appearance
    Troubleshooting

    hashtag
    Wait, this is not what I want!
    • For a step-by-step guide with examples, check Standalone Weapon Appearance

    • For a much more detailed step-by-step guide, check New Iconic Weapon: Step by Step

    • For an overview of weapon files, check Cheat sheet: Weapons

    • For an overview of weapon properties, check

    • For an overview of weapon audio profiles, check

    hashtag
    Prerequisites

    hashtag
    Selecting the base

    Weapons work a little different from regular ArchiveXL items, starting right at the root entity. With the help of @Apart and psiberx, I was able to figure out the process and document it for you.

    Start by finding the .app file of an original weapon of the type you want to make (Theres a list herearrow-up-right) and adding it to your project. We will change that file, rather than assembling anything by hand.

    In the app file, you can also find the value for the yaml file's $base property:

    hashtag
    Getting the mesh_entity.ent

    You need the correct mesh entity to go with your appearance file. You can find them under base\weapons\ - search for the name of your weapon, or just navigate through the folders.

    This file makes the weapon show up in photo mode. Instead of going into the PartsValues, it will be linked in the app file's root as baseEntity (there's a screenshot below). Leave it alone for now, it's easier to make the appearances working correctly in the .app file and then copying over an entire component array.

    hashtag
    Factory: .app instead of root_entity

    circle-exclamation

    For guns with a receiver, you have to edit two .app files instead of just one. The name of the extra file will contain _rcv.

    Instead of a root entity file, you need to point your factory.csv directly to your iron's app file (the one from the section above).

    hashtag
    Appearance selection

    An equipment item's lookup chain goes from the appearanceName in the yaml to the root_entity, where the appearanceName will lead to the correct appearance in the .app file.

    With a weapon, all that happens through visualTags.

    hashtag
    YAML: Define the field:

    Native weapons often use one shared VisualTags to reference multiple appearanceName and randomize the result. If you want to use a specific native appearance present in a VisualTags native group, you can use appearanceName to specify which. E.g: visualTags: [ Neon ] appearanceName: neon2

    hashtag
    .app file: Define the visual tag

    visualTags (violet): Must match the visualTags in your .yaml file. If multiple entries match, one will be chosen at random.

    circle-info

    Unlike with an entity file, the appearance name doesn't matter. You can name all of them foo, and as long as you had the visual tags right, it still works (I would advise against it, though)

    visualTags (violet): Must match the visualTags in your .ent file. If multiple entries match, one will be chosen at random.

    hashtag
    Step by step

    As the process is finicky and there can be all sorts of sudden unexpected behaviour, here's the best way to go about this.

    The list links you to sections of the guide which tell you to change things. Optimally, you do a dry run with one appearance to make sure that something shows up in the game at all, then start fine-tuning, but you do you.

    Here's what's worked for me (@manavortex):

    1. Find the .app file of a suitable base weapon, add it to your project, and rename it. Don't change anything for now, future you might need the original data for troubleshooting later.

    2. Find the correct .ent file. It might be linked in the .app's baseEntity field. If not, you can find it with the following Wolvenkit search query:

    circle-info

    Optimally, the number of components in the .ent file should be the same as in any appearance's component array (red arrow on the screenshot above).

    If it's not, that could indicate that you have the wrong .app file. It could also mean nothing, but if you run into trouble in step 6, this might be why.

    1. Configure the yaml as described here

    2. Set up one (1) appearance for testing by assigning the correct visual tags. &#xNAN;Do not delete the other appearances yet, future you might need them for troubleshooting.

    3. Start the game and make sure that you can spawn a custom weapon with the appearance you picked and that it

      1. shows up in inventory/photo mode

      2. shows up in first person

    If that's not the case, check the mesh entity (see the blue box in step 2).

    If that doesn't help, you may have taken the wrong .app file - go looking again.

    circle-exclamation

    You haven't changed anything at this point: the goal here is to make sure that your visual tags are correct and that you can spawn a weapon addition.

    It's crucial that you make this work — anything you do after this point will add complexity and make troubleshooting more difficult, so this is where you shore up your bases.

    1. Optional: You just added a weapon to the game that didn't exist before. Take a moment to bask in the success!

    2. Custompath your mesh entity:

      1. Create a copy of the file and move it to a custom folder

      2. rename it

      3. Change the baseEntity path in your .app file

    3. Optional, but recommended: Repeat step 5 and make sure that everything spawns

    4. Now it's time to actually change things. Open your appearance's component array and make sure that the MeshComponents load your custom stuff (anything that has a depotPath pointing to a .mesh file).

    5. After you've changed the paths, launch the game and make sure that your weapon

      1. shows up in your inventory with your meshes

      2. shows up in first person with your meshes

    Fix any issues that might arise before you proceed.

    circle-info

    This is why we kept the original appearances around: if you run into any issues here, you can compare your stuff with the original, un-changed game variants.

    Don't forget that you can

    • split off meshes or submeshes for individual pieces (for chunkmask hiding or extra materials)

    • add more components (duplicate existing ones, or copy them from the mesh entity)

    1. Once everything works, delete all the default appearances, then duplicate and adjust the one you customized to show your color variants.

    2. Now, finally, copy a working appearance from the .app file to your mesh entity. This will make your weapon show up in photo mode.

    3. Luanch

    If you wish to add a custom icon, follow the steps in the corresponding guide.

    hashtag
    Your own HUD icons

    To make your own HUD icons for the lower right corner, check here.

    hashtag
    Weapon Audio

    You can change which weapon audio preset your custom iron uses by changing the following property in the .yaml (see a list under Cheat Sheet: Weapon Audio):

    hashtag
    Custom throwing weapons

    You can set up throwing weapons just like a regular weapon, but the projectile (when you throw it) will default to . Check here for how to have custom projectiles.

    hashtag
    Editing weapon meshes

    When exporting an existing weapon mesh for your custom weapon, make sure to uncheck LOD Filter — the lower LOD mesh is used for calculating the hitbox.

    circle-info

    This is especially important if you add a melee weapon of a different size than the original: if you only replace LOD 1, there will be a separate, invisible hit box that does not align with your new weapon.

    Mesh export LOD Filter

    In Blender, put your custom mesh in both LODs.

    circle-info

    If your weapon is significantly bigger than the original one, you'll notice that the hitbox won't auto-scale with your mesh. If you know how to solve this problem or want to brainstorm, hit up @Mx_OrcBoi on Discord!

    hashtag
    Troubleshooting

    hashtag
    My weapon is fully invisible, no matter what I do!

    First of all, unequip and re-equip the item. If that doesn't fix it, try respawning it.

    hashtag
    My iconic melee weapon ignores its localizedDescription!

    That is due to a base game change (bug?): iconic weapons don't show fluff texts anymore (huge thanks to @RMKSoundSystem on Discordarrow-up-right for learning that).

    To make it work again, you need to either

    hashtag
    add a blueprint:

    Add the following line to your .yaml:

    hashtag
    change the base type

    Set $base like this:

    hashtag
    My weapon is invisible in FPP!

    • Try using a different weapon $base in your yaml - for example, Items.Preset_Hammer_Default works, while Items.Preset_Hammer_Sasquatch doesn't

    • Nested records: Check if your item spawns if you remove any custom records that you also defined in your .yaml — e.g. a broken entry in slotPartListPreset can turn the entire thing invisible in FPP

    • Copy the components from the mesh_entity to the .app as mentioned in

    hashtag
    My weapon is spawning as the original weapon/my mesh edit isn't reflecting!

    Make sure all the items under "resolvedDependencies" are deleted in your appearances, especially if they are using "Soft" or "Embedded" flags. The game might load vanilla meshes instead of your own meshes.

    hashtag
    Reticle (dot) position of the scope I attach to my weapon is not aligned with the point of impact (regardless of which scope)!

    Make sure the ikOffset of the weapon is zero for every axis:

    mana vortex
      displayName: my_shirt_localization_name_black_blue
      localizedDescription: my_shirt_localization_desc
    localizationPersistenceOnScreenEntry - []   
    	femaleVariant: my item - now in black and blue
    	maleVariant:  
    	secondaryKey:  my_shirt_localization_name_black_blue
    Items.my_custom_shirt_blueblack:
      $base: Items.GenericInnerChestClothing
      entityName: my_custom_shirt_factory_name
      appearanceName: appearance_root_entity_black_blue
      displayName: my_shirt_localization_name_black_blue
      localizedDescription: my_shirt_localization_desc
      quality: Quality.Legendary
      appearanceSuffixes: []
    Game.AddToInventory('Items.my_custom_shirt_blueblack')
    mesh:   DepotPath:   tutorial\torso\my_custom_shirt\my_mesh_m.mesh      << path to your mesh  
            Flags:       Default                               << leave this alone  
    name:   my_shirt_m    << this corresponds to the appearanceOverride in appearance.app  
    Items.my_custom_shirt_redwhite:
      $base: Items.GenericInnerChestClothing
      entityName: my_custom_shirt_factory_name
      appearanceName: appearance_root_entity_white_red
      displayName: my_shirt_localization_name_white_red
      localizedDescription: my_shirt_localization_desc
      quality: Quality.Legendary
      appearanceSuffixes: [ itemsFactoryAppearanceSuffix.Gender ]
      icon:
        atlasResourcePath: tutorial\torso\my_custom_shirt\ops\preview_icons.inkatlas
        atlasPartName: slot_01
    Game.AddToInventory("Items.my_custom_shirt_redwhite")
    $base: Items.GenericHeadClothing
    force_Hair
    base\weapons > entities > .ent
    # for guns etc
    weaponAudio: wea_set_achilles
    
    # for melee weapons
    audioWeaponConfiguration: audio_melee_metadata_katana
      blueprint: Items.Iconic_Melee_Blueprint
      $base: Items.IconicWeaponModBase
      ikOffset: {x: 0, y: 0, z: 0}
    shows up in photo mode at all (it shouldn't be invisible, but will still have the default appearance)
  • all parts and extra meshes are visible

  • is in the right position in regards to V's hands (at least as much as for the Tactician shotgun)

  • all parts and extra meshes show the correct appearances

  • Cheat Sheet: Weapon BaseStats
    Cheat Sheet: Weapon Audio
    Getting the mesh_entity.ent
    ArchiveXL: Dynamic conversion guide
    ItemAdditions: Dynamic Appearances
    ArchiveXLarrow-up-right
    Red4extarrow-up-right
    Cyber Engine Tweaksarrow-up-right
    ArchiveXL tags
    ArchiveXL: Tags
    Variants and suffixes

    Different equipment slots

    How to determine the item type

    hashtag
    Summary

    Created & Published: June 10 2023 by @manavortex

    This page is a part of the Adding new items guide and contains the steps necessary to create different equipment types.

    For an overview of prefixes for the different component types, see here.

    circle-info

    TL;DR:

    • Change equipmentSlot in the yaml (for options, see Step 1)

    • Replace the mesh_entity (see Step 2)

    hashtag
    Step 1: The .yaml

    You define the item slot in your .yaml file by specifying the root entry type via a $base record. Base records come in many different types, some include intrinsic modifiers that add slight stat improvements to items, or add special sound to items. A complete page with clothing items, their intrinsic modifier, and their baseids can be found on the official Cyberpunk 2077 wiki's article for clothing .

    You can use the following base types:

    Slot
    Records
    circle-info

    You can absolutely set up a shirt and then put $base: Items.GenericHeadClothing - V is the only person I know of who can wear their undies on their head without impairing their functionality. However, before you start abusing the system that way, you might want to look into .

    hashtag
    Step 1.5: EquipmentEx

    psiberx's mod EquipmentEx ( | ) adds a whole new wardrobe system, providing extra slots that CDPR forgot to include with the basegame. This feature requires the mod to be installed — without it, only the $base types from step 1 will be considered.

    All you need to do is adding the last two lines to your .yaml:

    When selecting an entity file, make sure to match it to the corresponding body part for your clothing item. This helps ensure that animations and placements work correctly, preventing visual glitches. Always refer to mesh_entity.ent for defining components properly.

    circle-exclamation

    When mapping clothing items to base types, keep in mind that any items defined under Head/Face root entry types tend to have visual bugs in FPP(First Person Perspective).

    Ex: defining gloves as anything OTHER THAN face/head base types is necessary to prevent visual artifacting/bugging while in FPP.

    circle-info

    Find a full list of outfit slots in the .

    hashtag
    Step 2: the entity file

    Some item properties are defined in the file mesh_entity.ent via components. If you use the wrong kind of entity, you might end up with your shirt being a puddle around your feet, or . To get around that, you need to make sure to pick a file that correspond's to your item's body part.

    You can find all entity files under base\characters\garment\player_equipment:

    If you want to be super thorough, you can stick to the right gender

    circle-info

    If you want to know more about components, check the . This is completely unnecessary for the purpose of this guide!

    hashtag
    (Optional) Step 3: Hide it in First Person

    You can hide items most easily via . Check the linked page for how to do that.

    hashtag
    Footstep sounds

    To find the correct tags for footstep sounds, check -> .

    Replace the .mesh (e.g., instead of a shirt, find in-game shoes)

  • Optional: Port an external item

  • Legs Items.GenericLegClothing Items.Skirt

    FormalPants, Pants Pants_Intrinsic_Armor, Pants_Intrinsic_Carry,

    Shorts, Skirt

    Feet Items.GenericFootClothing

    Boots, Boots_Intrinsic, CasualShoes, FormalShoes

    Special Items.Outfit

    Outfit, Outfit_EP1

    Head Items.GenericHeadClothing

    Helmet,

    HelmetHair,

    Helmet_Intrinsic, HelmetHair_Intrinsic,

    Helmet_EP1_Intrinsic_Armor,

    Helmet_EP1_Intrinsic_Runner,

    Helmet_EP1_Intrinsic_ExplosionDmg,

    Helmet_EP1_Intrinsic_Zoom,

    Hat,

    Cap,

    Scarf,

    ScarfHair,

    Balaclava,

    Balaclava_Intrinsic

    Face Items.Glasses Items.Visor Items.GenericFaceClothing

    Glasses, Mask, Mask_Intrinsic, Visor,

    Visor_Intrinsic_QH,

    Visor_Intrinsic_Zoom, Tech, Tech_Intrinsic_Zoom

    Outer Torso Items.GenericOuterChestClothing

    Coat, Coat_Intrinsic, Dress, FormalJacket, FormalJacket_Intrinsic, Jacket, Jacket_Intrinsic_Armor, Jumpsuit, Jumpsuit_Intrinsic,

    LooseShirt, Vest, Vest_Intrinsic_Armor, Vest_Intrinsic_Reload, Vest_EP1_Intrinsic_Armor, Vest_EP1_Intrinsic_Grenade, Vest_EP1_Intrinsic_Inhaler

    Inner Torso Items.GenericInnerChestClothing

    herearrow-up-right
    EquipmentEx
    githubarrow-up-right
    nexusarrow-up-right
    github readmearrow-up-right
    string cheese
    wiki page
    ArchiveXL tag
    ArchiveXL: Tags
    Pick any file from inside the correct folder.
    Footsteps: Setting footwear sounds

    FormalShirt,

    Shirt, TankTop,

    TightJumpsuit, TightJumpsuit_Intrinsic,

    TShirt, Undershirt, Undershirt_Intrinsic

    Items.My_Custom_Shirt:                      << name of your item (the spawn code)
      $base: Items.Shirt
    Items.My_Custom_Helmet:
      $base: Items.Helmet
    # For items that should hide hair, use records with the "Hair" suffix.
    Items.My_Custom_HelmetWithHair:
      $base: Items.HelmetHair
    # For items that should have an intrinsic modifier, e.g. Armor
    Items.My_Custom_HelmetWithArmor:
      $base: Items.Helmet_Intrinsic
    # For feet items that use heels (clicky sound)
    Items.MyCustom_Heels:
      $base: Items.FormalShoes
    Items.MyNecklace:
      $base: Items.GenericHeadClothing
      placementSlots: 
        - !append OutfitSlots.NecklaceShort

    Standalone Weapon Appearance

    hashtag
    Summary

    Created: May 27 2025 by Last documented update: May 29 2025 by

    This is supposedly meant to be a comprehensive guide to how to create an entirely new weapon — independent of the game's own files. The approach guarantees full compatibility with whatever other modders do, as well as making it virtually time-proof.

    circle-info

    For a working implementation, you can download the packed project from (maybe you'd like more enlightening?).

    Download the packed project from at Nexus Mods and take a look at the files yourself, if you feel like you need any more enlightening.

    hashtag
    Wait, this is not what I want!

    • What do you mean? Of course this is exactly what you want.

    • For an in-depth guide about weapon additions, check

    • If you want to add clothes, check

    hashtag
    Requirements

    To complete this guide, you need the following tools (and should know your way around them):

    hashtag
    Step 1: Gathering the files

    I will base the tutorial weapon on an Ajax rifle, but you can use whatever you want. Our first step is...

    hashtag
    1.1 Getting the control files

    1. Search for the weapon you want, then filter by .app and .ent. Example : ajax > .app|.ent

    2. Add all .app files to your project

    hashtag
    Explanation: What are these files?

    • The .app file with the shortest name is the base file for your entire weapon (we'll call this "the lonely app file" thorugh the rest of the guide)

    • The file ending in _base1 is your gun's barrel

    • The file ending in _mag_std

    Not all weapons support all parts - sometimes they're integrated (as for the Ajax, the receiver is part of the barrel).

    hashtag
    1.2 Getting the meshes

    With those files in hand, we'll use them to gather our meshes and prepare them for use.

    1. Open the .app file without any suffixess

    2. Expand appearances > default > components

    1. Depending on your gun, this should give you between 6 and 12 .mesh files.

    hashtag
    Explanation: What are these files?

    .mesh files contain your model's 3d data. As the .app and .ent files, they correspond to your weapon's parts.

    Anything with _decal in its name will be projected on top of the rest of the gun. We'll ignore these for now.

    hashtag
    1.3 Adding the material files

    1. Open the following mesh files:

      1. base

      2. sight (ironsights)

    These are the magical files that make your weapon look awesome.

    hashtag
    1.x: Summary

    In this section, you identified the files used to give the base game gun its looks, and added them to your project. Right now, these would overwrite the original gun — in the next step, we'll take care of the standalone part.

    hashtag
    Step 2: Preparing the files

    Now that we've got everything we need, time to prepare the files. First, rename all of your files with names of your own, being EXTRA SURE to tick the "Update in project files?" box, so these get automatically renamed everywhere. If you don't, you're just gonna be doing it manually.

    hashtag
    2.1 Preparing the .app files

    1. Open the .app file and expand the appearances array

    2. Delete every appearance except for the default one (which should be pointing at your own files, since you checked the box when moving)

    3. Give the remaining appearance a custom name

    This should be done for all .app files, except the lonely appfile, which will receive special treatment later on.

    hashtag
    2.2 Preparing the .ent files

    For the .ent files, we're gonna need to add a few stuff here and there. We start with the appearances array, which we add a new entry that points to the corresponding .app file. Then we change defaultAppearance to our own, and most importantly, the entity handle HAS to be changed into gameItemObject.

    hashtag
    2.3 Preparing the .mesh files

    In the appearances array, we're once again deleting all of them except for the default one. Then we go to the materials array, and once again delete everything except for default and default_tpp. Be sure to delete them all in a single swipe, or else their names will change because we still haven't touched the materialEntries yet, which will cause some confusion. Then on the materialEntries array, delete all entries except default and default_tpp, and then change their index to 0 and 1.

    Now that the file is all cleaned up, on the materials array we right-click on the CMaterialInstance and click Rename Material, and give it an unique name. Then go back to the appearances array, and rename the meshMeshAppearance to your own name.

    Once again, let's leave the decals for later on. They'll be one of the last things we're touching for now.

    hashtag
    Step 3: Your very own appearance

    We'll now be dolling up our weapon to be the prettiest rifle in all of Night City. This is where you bring in the MLSetupBuilder and go play with it until you're satisfied. Go on, have some fun, you deserve it. Change your materials, splatter it with all the colours of the rainbow, play around with everything. You'll probably be coming back to this a few times to adjust details here and there.

    After this, we go to our mesh, tab into Mesh Preview, and click Generate Materials, to have a rough preview of how our masterpiece looks like.

    This also confirms the setup is working just fine, and that everything is as it should be. Time to bring it to Blender so you can have a better look at it, and then finally play with the decals. Go to the Export Tool tab, and export your base mesh, and the decal meshes associated with it.

    circle-info

    While making the setups for your Sight, you'll notice a few different components. You can fiddle around them if you want, but that's likely to mess up with your actual aiming when in-game if you don't know what you're doing. But if you want to change the glass colour, change it on the ScopeInside value on the material for your glass. For this weapon, I made it green.

    hashtag
    Blender Preview and Decals

    Here, I'm assuming you already know the basics of Blender. If you don't, feel free to ignore this step, or do the right thing and learn it.

    This here is a better preview of how my weapon will look in-game. The decals are additional meshes that are placed over your weapon, just like any sticker. As you can see, we got 2 types of decals in there.

    hashtag
    Diffuse Decals

    This type of decal is just your regular old image being imprinted, nothing special going on here.

    hashtag
    Normal Decals

    These don't use their actual colours, but rather the information stored within the image channels to give an illusion of a 3D imprint (kinda like those hexagons all over my rifle), so don't worry about them looking off. You can "fix" them for a more accurate view if you want, but we won't need that.

    hashtag
    Making your own decals

    Yeah, we can put anything as a decal, as long as it's an image. So let's get us some cool stuff. I'll just take mine from the base game (or will I?)

    I've already got my own decals that I've put together from game files, and a few customizables. On Blender, we'll be using a .png file to preview and put everything together.

    So on Blender, duplicate your base collection, and keep just the armature, to get stuff organized. Then select the part you want to put your decal, go into Edit Mode, duplicate the faces that are roughly where you want your decals, then separate them off the original mesh.

    circle-info

    Taking the armature and duplicating from the original mesh will allow for an easier time making stickers on moving parts.

    Then move that separated mesh into your custom decal collection, and bring it slightly out of your mesh, and adjust your shape. Keep it triangulated for the export later. But you might have a question right now. Why don't we just make a plane and stick it there? Because we want the Vertex Groups data and the Weight Painting to carry on without having to do it ourselves.

    After you're done, your mesh should look like this, or whatever shape you want it to be. Now add your .png texture on the materials for this mesh, go to UV editing, unwrap and position it on your decal. If the sizes are incorrect and picking up other stuff, just cut off whatever you don't need.

    Do this as many times as you want. This is my favorite part. If there's a space somewhere, then I'll definitely want to put up some random sticker. Once you're done, export your decals as .glb, one for each set that uses any particular image, to keep them easier to keep track. If you fiddled around the topology too much, you'll need to check your Weight Paints to make sure everything's in order.

    circle-info

    Don't forget about the normals of your decals. Make sure they're all correctly oriented and as smooth as possible, to avoid shading issues.

    Now back on Wolvenkit, duplicate the Diffuse Decal mesh (in my example, named ley_ajax_base_decal_d), and rename it to the same name as the .glb you just exported from Blender. Then on the Import Tool, select your .glb and import it to an existing file.

    Open your newly made .mesh file, rename the material to another unique name, pick the DiffuseTexture value, and make it point to your .xbm texture file, which is just your decals.png file imported into Wolvenkit. Then delete the other values you won't be needing, and then your material should look like this.

    Save and close your mesh, then open it again, go into Mesh Preview, and hit the Generate Materials button. If you set up everything right, your decal will be there just like it was on Blender.

    circle-info

    The workflow will be the exact same one if you want to reposition, add or remove any of the vanilla decals.

    hashtag
    Adding your decals to your weapon parts

    Now, open up the .app file for your weapon part, in our case, the base one. Go into the componets Array and duplicate one of the decal entries, rename it and make it point to your decal mesh.

    Then on the resolvedDependencies Array, create a new entry and point it to your mesh as well.

    Now open your .ent file and go into Entity Preview. You should already see your custom decal mesh there on the list to the right, and among them, Mesh3737 (or something like that). That one is just a mesh for shadows, so leave it there, just uncheck the box to hide it. Click on Generate Materials, and if everything was set up correctly, you'll see your decal there on your weapon.

    Now go take a breather, an energy drink, coffe, or whatever poison you fancy, young grasshopper, you've earned it. The next steps will require a bit more of focus. Trust me, all of this was the easy part. Don't give up, skeleton!

    hashtag
    Step 4: Setting up the structure

    hashtag
    The lonely appfile

    We finally got back to it. This one is the appfile that contains the whole weapon, and isn't linked to any .ent file. This will be the one we'll be referencing on the .yaml tweak to make our weapon show up. If your weapon is composed of a single part, like a Katana, you'll only have a single .app file, and it will serve the same purpose as our lonely one here.

    As before, delete every appearance that isn't the default one, rename the appearance to your own, and remember to set up your visualTag as well. Notice that it has a proxyMesh, and the resolvedDependencies have a bunch of animation files.

    Right there on the components array, just as before, rename all of the entSkinnedMeshComponent entries to your own names, to better keep track of each one. Notice how it's got the components for every part of your weapon? If a component isn't there, it won't show up in-game.

    Once again, duplicate one of the decal entries, rename it and make it point to your custom decal. Last, but not least, scroll down to preset, and rename it to the name of your item in the .yaml file.

    hashtag
    Factory and xl files

    Now you'll need a .csv file to be your factory. This is where you'll be registering your .app files so they can be referenced in the .yaml, as well any .ent file for your . Create an empty one, and set it up like this.

    Then on the .xl file of your project, register your factory like this. Yeah, same file where you registered your localization file.

    hashtag
    Checking your files

    First, make sure you have all the files you want. Those are all the ones in this guide.

    Scan your project for broken references, and validate everything, checking the Log for anything that's wrong, and if that's the case, check which file it is, backtrack and fix it. Make sure all of your .mesh and .ent files preview the correct materials for everything.

    circle-info

    A common "error" on the Log is when two materials seem to be the same. It doesn't matter. Another one, which will probably affect your weapon, is when a mesh has no materials assigne, which will just make them render invisible.

    hashtag
    Assembling your weapon

    It's tweak time, yaaaaaay. With everything done properly in the previous steps, we can just mix them up on the gigantic sphagetti that is the coding part of Cyberpunk 2077. Truly a magnificent thing.

    Start by opening your .yaml file and scrolling down to the bottom of it. There, you'll be coding the entries for both the slotPartList and the slotPartListPreset. You'll need to do one of these for each part of your weapon, including Scopes and Muzzle Breakers, if you want custom ones as well. A good example for these parts is the Overwatch, Panam's Grad Rifle.

    circle-info

    This here is where a bunch of "stealthy" issues can happen, so pay close attention to what you're doing. A single typo and you can spend hours bashing your face on your desk trying to figure out what's happening, just for it to be a wrong identation, a missing definition, or whatever. If you're a dev, you already know this. Probably.

    The other parts are coded the same way, but in different slots.

    chevron-rightThe remaining parts for this weaponhashtag

    Now for the presets for the slotPartListPreset.

    These entries will then be appended in their respective, uh, places.

    Now, all of those make your weapon function with your parts, whatever that means. But for your weapon to show up entirely with your stuff, you'll be coding these lines under your item's entry, right there at the top.

    And this here is how the whole thing looks, if you want to take a look, with some comments on where the stuff is coming from.

    chevron-rightThe full tweak for the weaponhashtag

    Note that the tweak doesn't include an Icon entry. You'll want one, and this is covered .

    hashtag
    How it should look in-game

    Here's some in-game screenshots for the final looks of this masterpiece. IF you followed this guide to the letter, you'll have a similar result.

    circle-info

    Remember to make an icon and make your tweaks.

    chevron-rightA few Photomode and First Person stills for a better look at the detailshashtag

    hashtag
    Troubleshooting

    • My weapon doesn't exist in the game!

    That's likely a .yaml error. Check the .

    • My weapon exists, but is invisible!

    Check your meshes, appearance and entity files for any wrong depots, visual tags, appearance names, materials, handles, and chunk materials, as per the section.

    • Only a part of my weapon is rendering!

    You're using the wrong appfile under your weapon appearance. You should be using .

    • My weapon is rendering Vanilla stuff instead of mine!

    Check the resolved dependencies on your files for any reference to a vanilla mesh (except proxy, placeholder and shadow meshes), and delete them. Your meshes should be there instead.

    • My decals aren't showing up, or aren't moving when the moving part they're in move!

    1. First, make sure that their normals are properly calculated in Blender, and that they're also properly Weight Painted. If you don't know what those things mean, you'll need to learn from a Blender tutorial first.

    2. Then, check your decal meshes in wolvenkit, and doublecheck that they are loading the proper materials. Then you check if they are properly referenced in the components array of your .app files, and if they are pulling from the right appearance name that's on your mesh.

    • How do I put those cool hexagon textures all over my weapon? There's no Material like it!\

    Those are setup as microblends in the MLSetupBuilder. Check the appropriate .

    • Animations, shadows, visual effects and *insert any other similar issue* are missing, wrong, or generally fucked!

    You probably deleted more stuff than you had to. Apply the GETA (Gather Everything and Throw Away) method on the faulty files and redo them, it'll be easier than trying to fix what's missing.

    • You never told me to test stuff every step. How will I know what's wrong and where?

    That's the beauty of the XGH (X-treme Go Horse) method. You do everything in a single go. But the guide is discriminated step by step, so you can retrace your steps and check for any mistakes.

    • I'm trying to make my own weapon, but cannot understand where it's going wrong!

    Monkey See Monkey Do. Even if you want your own weapon, try making this Ajax the exact way it is in this guide. Same folders, same structure, same names, same everything.

    hashtag
    Wrapping up

    Well, this should be everything that needs to be done, yeah. All of this just so your weapon can look different. For further customizations, you can make and use your own , , , , and honestly, whatever else you can think of.

    Now, if you want to use fully custom meshes, you'll have to fiddle around with . Basically, you'll take whatever rig matches your weapon the closest, and Weight Paint your meshes accordingly on Blender. You'll likely have to create your own Mask Layers if you want to use the MLSetup stuff, and if you don't, you'll play with regular textures, kind of like the decals, but adding property maps as well.

    Now, if your weapon is a Throwable one, you'll have to take extra steps. And if your weapon is a Melee one, you'll be following less steps. Honestly, making a Katana or something is probably the ideal first weapon, but teaching it here wouldn't make me feel that this is complete, because it wouldn't teach the specifics of weapon parts and all that

    And as a "final" note, everything here has been made using the GETA (Gather Everything and Throw Away), XGH (X-treme Go Horse) and Monkey See Monkey Do methodologies. Some steps here may or may not be unnecessary, but through trial and error over days of pure stress, these are what ended up working for me.

    To learn more about weapon properties, head to
    Add all .ent files that correspond to an .app file (ignore the ones that don't match).
    is the
    loaded magazine
  • The file ending in _mag_stdr is the empty magazine

  • The file ending in _rcv1 is the receiver

  • Grab everything that's an entSkinnedMeshComponent
    magazines (mag_std and mag_stdr)
  • receiver (rcv, if you have)

  • For each of those files, open localMaterialBuffer.materials

  • Find the material called default and open it

  • Open its values array

  • Find the property called MultilayerSetup and add it to your project:

  • Inside the appearance, rename the visualTag to your own (this will be used to select the appearance name later)

  • Inside the appearance's components array, rename the entSkinnedMeshComponents from the base weapon to your own

  • Set the baseEntity field to your own weapon's .ent file. If it is not visible, switch to Advanced.

  • Blender version

    Plugin version

    Wolvenkit version

    >= 8.17.1 | ()

    Nexusmodsarrow-up-right
    herearrow-up-right
    New Iconic Weapon: Step by Step
    Adding new items
    MLSETUP Builder
    throwing weapons
    here
    appropriate guide
    Preparing the files
    the lonely appfile
    guide
    Mask Layers
    Custom Microblends
    Emissive Materials
    Particle Effects
    Rigging
    these
    Weapon Preview
    Equipped on the Inventory
    Icon and Stats
    # Base
    
    Items.Ley_Ajax_Base:
      $base: Items.w_rifle_assault__militech_ajax__base1 # Tweak Record for the Barrel of the weapon
      appearanceResourceName: ley_ajax_base_appfile # Name of your .app file as registered at the factory.csv
    
    Items.Ley_Ajax_inline4:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Base
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline3: # Barrel part to be appended to the slotPartList
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.Barrel
      itemPartList:
        - Items.Ley_Ajax_inline4
    # Mag
    
    Items.Ley_Ajax_Mag:
      $base: Items.w_rifle_assault__militech_ajax__mag_std
      appearanceResourceName: ley_ajax_mag_appfile
    
    Items.Ley_Ajax_inline6:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Mag
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline5:
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.Magazine
      itemPartList:
        - Items.Ley_Ajax_inline6
    
    # Mag Reload
    
    Items.Ley_Ajax_Mag_Reload:
      $base: Items.w_rifle_assault__militech_ajax__mag_stdr
      appearanceResourceName: ley_ajax_mag_reload_appfile
    
    Items.Ley_Ajax_inline8:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Mag_Reload
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline7:
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.MagazineEmpty
      itemPartList:
        - Items.Ley_Ajax_inline8
    
    # Receiver
    
    Items.Ley_Ajax_Rcv1:
      $base: Items.w_rifle_assault__militech_ajax__rcv1
      appearanceResourceName: ley_ajax_rcv1_appfile
    
    Items.Ley_Ajax_inline10:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Rcv1
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline9:
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.Receiver
      itemPartList:
        - Items.Ley_Ajax_inline10
    # Presets
    
    Items.Preset_Ley_Ajax_inline0:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Base
      slot: AttachmentSlots.Barrel
      itemPartList: []
    
    Items.Preset_Ley_Ajax_inline1:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Mag
      slot: AttachmentSlots.Magazine
      itemPartList: []
    
    Items.Preset_Ley_Ajax_inline2:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Mag_Reload
      slot: AttachmentSlots.MagazineEmpty
      itemPartList: []
      
    Items.Preset_Ley_Ajax_inline3:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Rcv1
      slot: AttachmentSlots.Receiver
      itemPartList: []
    slotPartList: 
        - !append-once Items.Ley_Ajax_inline3 # Base
        - !append-once Items.Ley_Ajax_inline5 # Mag
        - !append-once Items.Ley_Ajax_inline7 # Mag Reload
        - !append-once Items.Ley_Ajax_inline9 # Receiver
    slotPartListPreset: # Presets for each part of your weapon
        - !append-once Items.Preset_Ley_Ajax_inline0
        - !append-once Items.Preset_Ley_Ajax_inline1
        - !append-once Items.Preset_Ley_Ajax_inline2
        - !append-once Items.Preset_Ley_Ajax_inline3 
      appearanceResourceName: ley_ajax_rifle_appfile
      appearanceName: ley
      visualTags: [ ley_ajax ]
    Items.Ley_Ajax_Tutorial:
      $base: Items.Preset_Ajax_Default
      appearanceResourceName: ley_ajax_rifle_appfile # Name of your lonely appfile as registered on the .csv
      appearanceName: ley # Name of your appearance
      visualTags: [ ley_ajax ] # The visualTag you've set up on the .app
      displayName: LocKey("Ley_Ajax_Name") # From your localization file
      localizedDescription: LocKey("Ley_Ajax_Description") # Also from localization, this is the text in the preview window in-game.
      slotPartList: 
        - !append-once Items.Ley_Ajax_inline3 # Base
        - !append-once Items.Ley_Ajax_inline5 # Mag
        - !append-once Items.Ley_Ajax_inline7 # Mag Reload
        - !append-once Items.Ley_Ajax_inline9 # Receiver
      slotPartListPreset: # Presets for each part of your weapon
        - !append-once Items.Preset_Ley_Ajax_inline0
        - !append-once Items.Preset_Ley_Ajax_inline1
        - !append-once Items.Preset_Ley_Ajax_inline2
        - !append-once Items.Preset_Ley_Ajax_inline3 
      tags:
        - !append-once IconicWeapon
      statModifierGroups:
        - !append-once Items.IconicQualityRandomization
      statModifiers:
        - !append-once Quality.IconicItem
    
    
    # Base
    
    Items.Ley_Ajax_Base:
      $base: Items.w_rifle_assault__militech_ajax__base1 # Tweak Record for the Barrel of the weapon
      appearanceResourceName: ley_ajax_base_appfile # Name of your .app file as registered at the factory.csv
    
    Items.Ley_Ajax_inline4:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Base
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline3: # Barrel part to be appended to the slotPartList
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.Barrel
      itemPartList:
        - Items.Ley_Ajax_inline4
    
    # Mag
    
    Items.Ley_Ajax_Mag:
      $base: Items.w_rifle_assault__militech_ajax__mag_std
      appearanceResourceName: ley_ajax_mag_appfile
    
    Items.Ley_Ajax_inline6:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Mag
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline5:
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.Magazine
      itemPartList:
        - Items.Ley_Ajax_inline6
    
    # Mag Reload
    
    Items.Ley_Ajax_Mag_Reload:
      $base: Items.w_rifle_assault__militech_ajax__mag_stdr
      appearanceResourceName: ley_ajax_mag_reload_appfile
    
    Items.Ley_Ajax_inline8:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Mag_Reload
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline7:
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.MagazineEmpty
      itemPartList:
        - Items.Ley_Ajax_inline8
    
    # Receiver
    
    Items.Ley_Ajax_Rcv1:
      $base: Items.w_rifle_assault__militech_ajax__rcv1
      appearanceResourceName: ley_ajax_rcv1_appfile
    
    Items.Ley_Ajax_inline10:
      $type: gamedataItemPartListElement_Record
      item: Items.Ley_Ajax_Rcv1
      weight: 1
      statModifierWeight: []
    
    Items.Ley_Ajax_inline9:
      $type: gamedataSlotItemPartListElement_Record
      optionalProbabilityCurveName: ''
      slot: AttachmentSlots.Receiver
      itemPartList:
        - Items.Ley_Ajax_inline10
    
    # Preset
    
    Items.Preset_Ley_Ajax_inline0:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Base
      slot: AttachmentSlots.Barrel
      itemPartList: []
    
    Items.Preset_Ley_Ajax_inline1:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Mag
      slot: AttachmentSlots.Magazine
      itemPartList: []
    
    Items.Preset_Ley_Ajax_inline2:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Mag_Reload
      slot: AttachmentSlots.MagazineEmpty
      itemPartList: []
      
    Items.Preset_Ley_Ajax_inline3:
      $type: gamedataSlotItemPartPreset_Record
      itemPartPreset: Items.Ley_Ajax_Rcv1
      slot: AttachmentSlots.Receiver
      itemPartList: []
    Cheat Sheet: Weapon BaseStats
    5.0arrow-up-right
    1.8.0arrow-up-right
    stablearrow-up-right
    nightlyarrow-up-right
    installed and configured
    Wolvenkit project
    Wolvenkit Project
    Import Tool
    File Validation
    file validation
    File validation
    file validation
    file validation
    search query
    Editor Mode
    install guide
    Leyllara
    Leyllara
    On the entire project
    Install and launch

    New Iconic Weapon: Step by Step

    hashtag
    Summary

    Published: December 2023 by destinybu Last documented edit: Feb 07 2024 by mana vortex

    We'll be making a fully featured new Iconic weapon in this guide, which is designed for first-timers and goes into details into every aspect about weapon modding. (not appearances)

    hashtag
    Wait, this is not what I want!

    • You can find other guides about this topic under and

    • For an overview of weapon properties, check

    • For an overview of weapon audio profiles, check

    hashtag
    Prerequisites

    Before beginning, ensure you have the following software installed and properly set up:

    1. WolvenKit (8.12+) -

    2. MLSB (MultiLayerSetupBuilder 1.6.7+) -

    3. A text editor: or, if you want to get fancy,

    If you are stuck, refer to the at the end of the page.

    hashtag
    Step 1: Create a New Project in WolvenKit

    Each Iconic weapon is a variant of a base weapon, with an hidden (from the player) mod. This "hidden" mod contains a statModifiers array (to list all the stat changes this Iconic will have from the base weapon) and an OnAttach array. The OnAttach array is where you'll want a GameplayLogicPackage to go. You may or may not need to define conditional effectors in there, but if you want your weapon to have the customary Iconic yellow description then be aware that there is where it's written (in the UIData of the GameplayLogicPackage).

    hashtag
    Step 0: Understanding the structure

    The rest of this guide will hold your hand through a deep dive, step-by-step, of your first custom Iconic made from zero. If you get lost through it, or if you'd rather find your own flow, you'll be well served by returning to check the code of an Iconic weapon already in the game (as you'll be building up from a base weapon in the same way, and it's solid footing).

    RedMod tweak files are much more legible than a "TweakXL override" from WolvenKit for this, as each step there inherits redundant stuff passively and won't clutter your screen. Plus you'll see inlines content directly without having to track down flats. Just use something to search the insides of the files for the definitions (VS can, or some free tools like )

    hashtag
    Step 1: Create a New Project in WolvenKit

    1. WolvenKit (8.12+):

    2. MLSB (MultiLayerSetupBuilder 1.6.7+): Installation & Setup Guide

    3. Text Editor: or

    hashtag
    Step 1: Create a New Project in WolvenKit

    Open WolvenKit and create a new project. This will be the foundation for your new iconic weapon mod.

    hashtag
    Step 2: Choose the Base Weapon

    Decide on the weapon you want to modify to make a new new iconic.

    hashtag
    Step 2: Choose the Base Weapon

    Select a base weapon for your iconic weapon. For this tutorial, we'll use 'Unity' with item ID Items.Preset_Unity_Default.

    circle-info

    For this tutorial, we will use the gun 'Unity' as our base (Items.Preset_Unity_Default). If you want to use a different weapon, you can refer to or find a list of all in-game items .

    To understand how the base gun works, open the in WolvenKit and search for Items.Preset_Unity_Default.

    hashtag
    Step 3: Create a TweakXL Override

    In the tweak browser, find Items.Preset_Unity_Default, right-click it, and select "Add TweakXL Override". This step is crucial for customizing the weapon.

    circle-info

    To read more about Tweak modding, check . This isn't necessary for understanding this guide!

    hashtag
    Step 3: Editing and understanding your new tweak

    circle-exclamation

    Before you start with this section, make sure to read the block below!

    .yaml files use indentation (the number of spaces at the beginning of a line) to organize entries in groups. This is easy to break!

    If you run into problems, you can check your file on . If that doesn't help, see if red4ext/plugins/TweakXL/TweakXL.log has any hits for your mod.


    Open the overridden tweak file in a code editor of your choice (such as or VS Code). You will be presented with a .yaml file containing roughly a million fields.

    hashtag
    Step 4: Open the Overridden Tweak

    Open the overridden tweak file in a code editor like Notepad++ or VS Code. You'll see a .yaml file with various fields.

    hashtag
    How does it work?

    circle-info

    For first time modders, understanding all this in one go will be difficult. You can just keep these explanations handy and revisit them when required.

    The .yaml file may seem complex at first glance, but the actual structure is extremely simple. Your weapon has properties – those stand on the left side of the :, such as ammo. The properties have different values, and those stand on the right side of the :, such as Ammo.RifleAmmo. Note: For first time modders, understanding all this in one go will be difficult, so keep these explanations handy and revisit them as and when required)

    hashtag
    Step 5: Understand the .yaml File

    The .yaml file might seem complex. Here's a breakdown of key fields from another weapon tweak (Items.Preset_Sidewinder_Default). Keep these explanations handy for reference. (Thanks to BuffMcMuff)

    chevron-rightAn annotated examplehashtag

    Here's a breakdown of key fields in a different weapon (Items.Preset_Sidewinder_Default) : (Thanks to BuffMcMuff)

    hashtag
    Step 4: Making a new weapon

    hashtag
    4.1: New weapon, same as the old weapon

    Making a new weapon is fairly simple. In your tweak file, change the Item ID in the very first line to "Items.Hand_Of_Midas" and save (Hotkey: Ctrl+S).

    hashtag
    Step 6: Create a New Weapon

    Change the item ID at the top of your .yaml file from Items.Preset_Unity_Default to Items.Hand_Of_Midas. Save the file to create your new weapon.

    That's it, you've created a new weapon now. This weapon will look & behave exactly like the Unity handgun, but trust me, it's new. To test it out, boot up your game and load any save.

    At this stage your tweak file exists only in your mod's project folder. It can't do anything in game from there, so you will need to use the "Install" button to install your tweak file to the game directory. Then you can test it.

    To test it out, boot up your game and load any save.

    Now open up the CET :

    Type in the command below and hit Enter.

    You can now see your newly created weapon in your inventory.

    Unfortunately, there is no way to tell it apart from the Unity handgun.

    We'll get to fixing that, but first, a little cleanup: open up your WolvenKit & rename your overridden tweak file to "hand_of_midas.yaml". We will store all the edits that need to be done to our new weapon in this file.

    hashtag
    4.2: Changing the carbon copy

    Let's change something that will differentiate our weapon from the default Unity.

    To do this, open your renamed tweak file & find the crosshair tag (hotkey: Ctrl+F). Replace it as shown below, and save your file.

    Now hot reload your game (Insert how to link here) or close it, reinstall your mod in WolvenKit & relaunch your game (From here on, this will be referred to as hot reload).

    Spawn in both the Unity & Hand of Midas using the CET console:

    You should now be able to see that both the Unity & Hand Of Midas, although otherwise identical, now have different crosshairs.

    hashtag
    How did we figure out the crosshair ID?

    How do we know that it's called "Crosshairs.Tech_Round" ?

    hashtag
    Method 1: The REDmod DLC

    If you have the REDmod DLC installed, you can use a text editor like Notepad++ to do a full-text search under Cyberpunk 2077/tools/REDmod. By searching for crosshair:, you can find all value assignments in the game files.

    hashtag
    Method 2: The

    By searching for "Crosshairs." in the Tweak Browser. Most things we find inside the weapon tweak will be searchable within the Tweak Browser, and some within the Asset Browser.

    Editing the Tweak will allow us to modify all of our gun's behaviors, and I encourage you to play around with these.

    hashtag
    Step 5: Removing redundant code

    We're only changing a single property in the Hand of Midas. For that, we have a tweak file with more than 200 lines of code. Can't we do this in a better way?

    We can, and we should!

    circle-exclamation

    In later steps of this guide, you'll need to look up properties. Either keep a copy of your full tweak file (e.g. on your desktop), or refer to above.

    hashtag
    Using $base instead of $type

    As shown above, when using $type to define a tweak, we need to add all the required properties for the type, but when using $base to define one, we only need to add the properties we are changing, the rest are taken from the parent.

    Now go ahead and change it so we use a $base & only define the crosshair. Your entire tweak should now look like this:

    hashtag
    Step 6: The personal touch

    What good is a new gun without a new name? We need to tell our game about these.

    1. Open your WolvenKit project and navigate to the archive folder

    2. Create a new folder named after your mod, for example midas_collection

    3. Within this folder, make a subfolder named localization

    hashtag
    How does the game assign display names?

    In your full tweak file, search for the field called displayName. You'll likely encounter something like displayName: LocKey#49794.

    This connects the displayName property of your item with a locaization key, which is the mechanism that the game uses to support multiple languages. Think of the LocKey of a list entry, with different lists being used for different languages.

    circle-info

    If you want to take a look at these lists, use WolvenKit's or for onscreens.json.

    hashtag
    So we edit onscreens.json?

    Good thinking, but no. In Cyberpunk, only one mod can edit any given file. That is why exists, and we'll use it to create a new translation entry for us.

    Place a dedicated file in your midas_collection\localization folder. This is where we'll add our own translation entries – after that, we only need to tell ArchiveXL about the file and lean back.

    hashtag
    Setting up a localizationKey

    Open the file in Wolvenkit and create a new entry in localizationPersistenceOnScreenEntry. It has the following properties:

    Property name
    your value
    explanation
    circle-exclamation

    secondaryKeys must be globally unique, or they will overwrite each other.

    Create another entry with the secondaryKey of MC_gun_description and write a little fluff text for the description.

    circle-info

    For more detailed guidance on these properties, check out the .

    hashtag
    Tell ArchiveXL about our new translation file.

    In your WolvenKit project, go to the resources folder and create a plain text file with the following contents:

    Rename this file to midas_collection.archive.xl.

    circle-info

    Wolvenkit will move the .xl file to the same directory as your mod's .archive file, where ArchiveXL will see and process it.

    Next, revisit your "hand_of_midas" tweak file to establish the weapon's name and description in the game.

    Add the following lines under the existing properties:

    circle-exclamation

    This localizedDescription: is not the yellow text you see on the weapon, but the red-colored description that is shown in the Inspect screen. The text that is shown (as yellow-colored) on the weapon is instead defined in the UIData of the Iconic Mod (at Step 12)

    These lines set the display name and the description of your weapon using the keys defined in your localization file. The values on the right side of the : must match the secondaryKey values from your en-us.json file and be globally unique.

    After completing these steps, install your mod and launch the game. Your new weapon, "Hand Of Midas", should now appear with its unique name and description, fully integrated into Cyberpunk 2077's multi-language environment.

    hashtag
    Step 7: Make it Iconic

    To elevate the 'Hand of Midas' to its iconic status, we need to modify the .yaml again, where we set all of the gun's unique features:

    The new things you're seeing are arrays, which is a technical term — you can think of them as lists, since they can hold multiple items.

    circle-info

    You can read more about how array operations work in .

    statModifiers will hold all the stats for your gun. from recoil to damage. Since the $base: Items.Preset_Unity_Default already defines statModifiers, and we'd like to keep those. So we're adding an entry to the list, using!append-once followed by the new entry Quality.IconicItem.

    This makes the weapon iconic, which means:

    • it has a fancy golden background

    • there's a dialogue box when you disassemble it

    To prevent it from being disassembled, we also add IconicWeapon to its tags array.

    hashtag
    Go test

    Once these modifications are in place, install your mod and enjoy the newfound Iconic status of the 'Hand of Midas' in the game.

    Technically, you've already made a new Iconic weapon & I should call quits on this tutorial, but it's never as easy as that, is it? Give yourself a pat on the back & onto the next step.

    hashtag
    Step 8: Finishing up the Tweak

    There are a lot of values to play around with in a tweak file. You are often better off leaving most of them alone. These are some properties you probably should look at when designing a gun.

    1. Blueprint (mandatory change for iconic weapons)

    2. Item Quality (optional)

    3. Buy & Sell Price (optional) (fixed value example)

    hashtag
    Step 9: Making an Iconic Mod (Special Ability & Stats)

    The main thing that makes an iconic weapon so special is its iconic mod. These are like any other weapon mod, but hidden from the UI. They carry the Stat changes from the base model of the weapon, the golden text description on the UI Tooltip and any dedicated Effectors.

    Before you start hacking up your own, it is very important you have a look at the existing Iconic Mods in game.

    For now, let's look at Items.Preset_Lexington_Wilson (also known as "Dying Night").

    circle-info

    A big part of tweak modding is exploration — poking through tweaks until you find just the right thing to copy or change, or looking for something specific in hundreds of files.

    hashtag
    Wilson's iconic iron

    circle-info

    The example (together with instructions on finding your way around the TweakDB) has moved to ->

    We'll end up with WilsonWeaponMod (slotted on the weapon) and WilsonWeaponModAbility (GameplayLogicPackage of the previous)

    chevron-righticonic_mods.tweakhashtag
    chevron-rightmods_abilities.tweakhashtag

    For an explanation of what these do, please see ->

    hashtag
    Adding an iconic mod

    We have found the iconic mod of Wilson's gun, so now let's see that we apply the same structure to the Hand of Midas.

    Since our weapon demands perfection, we'll punish the player for not hitting headshots & reward them for hitting headshots. And because we want to make it hurt, we'll use HP reduction & Healing rewards.

    circle-info

    You can add the tweaks below to your weapon's yaml file or create a new one.

    Will make it so the weapon has this iconic mod slotted in the appropriate modslot, on weapon acquisition.

    hashtag
    Defining the mod

    This is the stage where we define how the stats of this weapon will differ from its base variant, plus add a reference to the "mod ability" record that holds the gold description and any desired Effectors

    circle-check

    You can find an overview of existing weapon stats under

    circle-info

    StatModifiers will stack with all other StatModifiers present on the weapon

    hashtag
    Defining the ability

    In this section, we first define our special ability Items.Cranial_Cashback:

    The ability contains

    • two , which we are yet to implement

    • the description for our iconic ability as a localizedDescription

    Let's start by registering the description.

    1. Open the .json file that you've created when

    2. Add another entry (you can duplicate an existing entry)

    3. Set the secondaryKey to the value in your tweak file,

    Now that we have an ability, we need to register it as a mod:

    Everything hangs together now, let's see if it works.

    chevron-rightFull mod addinghashtag

    hashtag
    Go test

    Install your mod — if your gun shows the yellow iconic description on hover, you're good to go. If not, you may have to respawn it via CET.

    hashtag
    Designing effectors

    Now that we have , we'll fill in the two , one to punish the player for missing, and the other to reward them for headshots.

    hashtag
    Heal on headshot

    We'll heal for 80 HP every time the player pops somebody else's skull with the Hand of Midas. How do we do that?

    Let's do what Edison did — we find something to be inspired by. A search for effector in the finds an awful lot of entries, so I've picked an example for us — a Netrunner item that restores memory:

    The player's health is also a statPool item, it's called BaseStatPools.Health. We can copy this example and change it to meet our needs (for the final result, see ):

    However, the prerequisite for this effector is Items.MemoryReplenishmentEffector_inline0, which doesn't sound helpful.

    We could now try to find an existing preReq that checks for headshots, but we can also write our own.

    hashtag
    Creating a custom prereq

    Now we have a custom preqrequisite, but we still have to fine-tune and link it:

    hashtag
    Creating a custom condition

    circle-info

    For more information on this, check ->

    Conditions are at the heart of a prerequisite, and here we have four.

    1. Perks.IsHitTargetAlive_inline2 -> We don't want headshots on deadbodies to heal the player

    2. Perks.HitIsBodyPartHead_inline0 -> Actual condition to check for headshots

    3. Prereqs.Is_Attack_Ranged

    hashtag
    The final effector

    Now let's change our effector to use this prerequisite.

    Instead of punishing the player for just missing headshots, we can make our job easier by removing the HP every time they shoot, and compensating for the reduction in HP when hitting headshots by increasing our heal. Here's how we can do that:

    hashtag
    Test it!

    Uncomment the effector in your weapon tweak and test your mod. You should now be healing every time you hit headshots.

    chevron-rightThe full tweak filehashtag

    hashtag
    Bonus: Audio - Gun Go Boom

    Firing sounds of guns are dictated by the value of their audioName flat. Swapping them to those of another gun is as easy as changing that value.

    circle-check

    For a list of soundsets already in the game, refer to

    triangle-exclamation

    Beware that firing sounds are, natively, separately set for each firing mode.

    Meaning, for example, giving the audioName of a weapon that usually fires as Burst to a weapon that doesn't could result in missing sounds (or the other way around).

    Having installed passively fixes this problem in the background, allowing for correct sounds on all firemode combinations. (refer to its own if interested about how to customize firemodes and attack types)

    hashtag
    Adding custom sounds

    We can add custom sounds using RedMod but, due to how that works (as a replacer), we could end up influencing other guns and/or generating conflicts.

    hashtag
    Summary: The iconic weapon in action

    Here's a demo for how iconic weapon should behave.

    You are now a certified weapon modder. Pat your self on the back twice, you've done it. A special request from me (@DestinyBu). If you found this guide helpful, go ahead and document your own findings on the Wiki and maybe ping me if you ever get around to finishing your Mod. A big thanks to for (inspiring) forcing me to do this.

    hashtag
    Troubleshooting (Check this when you're stuck)

    You've created/modified a tweak but it doesn't show effect in game, what next?

    • Open the CET Console in game search for your Tweak in the . If your tweak doesn't show, there's a validation error in the tweak.

    • Validate your .yaml tweaks to check for errors.

    • Open Cyberpunk 2077\red4ext\plugins\TweakXL\TweakXL.log

    Cyberpunk 2077 - 😑

  • Core mods: ArchiveXLarrow-up-right, TweakXLarrow-up-right, Red4Extarrow-up-right

  • Optional: RedHotToolsarrow-up-right, RedMod

  • Cyberpunk 2077

  • Core Mods: ArchiveXLarrow-up-right, TweakXLarrow-up-right, Red4Extarrow-up-right

  • Optional: RedHotToolsarrow-up-right

  • 0

    The actual entry in the translation list, make sure to set this to 0 so that it's autogenerated

    secondaryKey

    MC_gun_name

    The key used in tweak files to identify this translation string

    MC_gun_iconic_description
  • Set femaleVariant to your text — this will be showin on the tooltip in yellow.

  • . Make sure that it has the correct secondary key , and enter your fluff text as femaleVariant.

  • -> (Custom) We don't want quick melee attacks to heal
  • Prereqs.Is_Weapon_Ranged -> (Custom) We don't want grenades to be counted for this check.

  • and look for any error messages
    towards the end, this can help when TweakXL has issues loading a tweak.
  • Check for other mods with same Tweak/Archive names.

    Tweak Folder - Cyberpunk 2077\r6\tweaks

    Archive Folder - Cyberpunk 2077\archive\pc\mod

  • Look at WolvenKit logs located towards the bottom. Yellow or Red text means there's warnings/errors in your file that need addressing.

  • femaleVariant

    Hand Of Midas

    the default translationse

    maleVariant

    only set this if you want to show a different translation when your item is equipped by a person of the male body gender

    ItemAdditions: Weapons
    Standalone Weapon Appearance
    Cheat Sheet: Weapon BaseStats
    Cheat Sheet: Weapon Audio
    Installed & Setup
    Notepad++arrow-up-right
    Agent Ransackarrow-up-right
    Notepad++arrow-up-right
    Spawn Codes (BaseIDs/Hashes)
    herearrow-up-right
    TweakDB: Game database
    yamllint.comarrow-up-right
    Notepad++arrow-up-right
    ArchiveXL
    en-us.jsonarrow-up-right
    ArchiveXL Wikiarrow-up-right
    TweakXLarrow-up-right
    Browsing the tweak database
    Types of tweak records
    Cheat Sheet: Weapon BaseStats
    effectors
    effectors
    Types of tweak records
    Cheat Sheet: Weapon Audio
    Trigger Mode Controlarrow-up-right
    documentationarrow-up-right
    here arrow-up-right
    $base: Items.IconicWeaponModAbilityBase == $type: GameplayLogicPackage
    Create a new WolvenKit project as shown here
    A clean project should look like this (as of Wolvenkit 8.12, your interface may look different)
    Open the Tweak Browser & search "Items.Preset_Unity_Default"
    Red arrow = Tweak Name, where you can override it. Blue Box= Details about selected tweak. White arrow = Overridden (New) Tweak
    "Items.Preset_Unit
    Red arrow = Open CET Console. Green arrow = Command to spawn in the newly created gun
    Your newly created weapon is now in game.
    Default Unity crosshair
    Hand of Midas crosshair
    List of crosshairs obtained with a Tweak Browser search
    mod name folder & localization folder
    LocKey Browser search for LocKey#49794
    Red arrow = localization json added correctly. Green arrow = add new element in the json. Yellow arrow = key fields in new entry
    Name & Description of the gun are now taken from "en-us.json" that we've created
    Setting "Quality.IconicItem" will give it a special background in the inventory & also specify that the item is Iconic.
    Iconic description is visible when hovering over gun
    An explanation for how audio works internally, should you decide to go the RedMod route.
    Heal on headshot demo
    Damage player on miss demo
    mana vortex
    Troubleshooting (Check this when you're stuck)
    An annotated example
    Setting up a localizationKey
    New Iconic Weapon: Step by Step
    The final effector
    Installed & Setup
    Installation & Setup Guide
    Tweak Browser
    Wolvenkit Tweak Browser
    LocKey browser
    search
    Tweak Browser

    primaryKey

    Items.Preset_Sidewinder_Default: # item "code" for your weapon. use this when giving item.
      $type: gamedataWeaponItem_Record # the type of record. (records need to be defined with either a $type or a $base)
      ammo: Ammo.RifleAmmo # ammo type used (Fun Fact: Dex's Gun has ammo type - Items.Money)
      baseEmptyReloadTime: 1.54999995 # base reload time when mag empty NOTE: DO NOT EDIT RELOAD SPEED HERE see statModifierGroups: Items.Base_Sidewinder_Handling_Stats
      baseReloadTime: 1.54999995 # base reload time when mag is not empty NOTE: DO NOT EDIT RELOAD SPEED HERE see statModifierGroups: Items.Base_Sidewinder_Handling_Stats
      damageType: DamageTypes.Physical # damage type
      effectiveRangeFalloffCurve: StandardFalloff # damage fall of curve
      evolution: WeaponEvolution.Smart # what type of weapon none, power, tech and smart for ranged weps
      forcedMinHitReaction: -1
      fxPackage: WeaponFxPackage.SmartRifle # visual effects used for bullets. trail, bullet hole, impact, etc
      fxPackageQuickMelee: WeaponFxPackage.QuickMeleeFxPackage
      hudIcon: HUDWeaponIcons.Sidewinder # hud icon used
      IsIKEnabled: False # are inverse kinematics enabled.
      manufacturer: WeaponManufacturer.Corporation # weapon manufacturer type. not sure if used ingame.
      primaryTriggerMode: TriggerMode.FullAuto # trigger mode when hip firing and aiming if secondaryTriggerMode is not set.
      projectileEaseOutCurveName: ProjectileEaseOut
      rangedAttacks: Attacks.SmartBulletLowPackage # what type of bullet to fire. explosive, smart, projectile, standard hitscan, etc
      triggerEffectName: te_wea_aim_mid
      uninterruptibleEmptyReloadStart: 0.5 # point after which reload cannot be cancelled by other animations such as running. with empty mag
      uninterruptibleReloadStart: 0.5 # point after which reload cannot be cancelled by other animations such as running. with non empty mag
      useForcedTBHZOffset: False # Time before hit offset? used by npc
      UseShootVFXOnlyOnFirstShot: False # if bullet vfx is used again when firing in non semi-auto
      animFeatureName: WeaponData
      animName: ui_garment_pose
      animSetResource: ''
      appearanceResourceName: Preset_Sidewinder_Default # used to set .app file used by weapon
      audioName: wea_set_sidewinder # used to set weapon sounds not related to reloading and and first equip anim.
      blueprint: Items.Base_Smart_AR_SMG_LMG_NoAttachments_Blueprint # "blueprint" used to create the gun. different versions for guns with no barrel or scope attachments. also generic ones for iconics
      crosshair: Crosshairs.SmartGun # what crosshairs to use
      deprecated: False # TODO. used with items from before v2.0?
      dropObject: defaultItemDrop
      enableNpcRPGData: True # if npc should use npcRPGData found below
      entityName: weapon_root
      equipArea: EquipmentArea.Weapon # equip area. see equipment.EX
      friendlyName: w_rifle_assault_nokota_sidewinder # used to set player arm animations in first person see player_ma_fpp.ent and player_wa_fpp.ent. reload and first equip sounds are set in .anims files also. see weapon anim files beginning with pwa_ and pma_
      garmentOffset: 0
      icon: UIIcon.ItemIcon # Used when setting inventory icon
      iconPath: '' # Used when setting inventory icon
      isCached: False
      isCoreCW: False
      isCustomizable: False
      isGarment: False
      isPart: False # this is set to true in weapon parts such as scopes
      isSingleInstance: False
      itemCategory: ItemCategory.Weapon # item category used for inventory
      itemSecondaryAction: ItemAction.Equip # second action shown when looking at weapon on the ground for example.
      itemType: ItemType.Wea_Rifle # what type of item. used in inventory and perks i think? maybe affects animations?
      localizedName: '' 
      mass: 20 # weight of weapon.
      minigameInstance: minigame_v2.DefaultItemMinigame
      npcRPGData: Items.Base_Sidewinder_inline1 # stats used when the weapon is equipped by an NPC
      parentAttachmentType: ParentAttachmentType.Slot # used for weapon attachments such as scopes and muzzles
      powerLevelDeterminedByParent: False # TODO. not used since 2.0?
      quality: Quality.Random # default quality for weapon. CET ignores Quality.Random and always gives normal. Other quality settings work fine in CET and random works normally when found normally ingame.
      qualityRestrictedByParent: False
      replicateWhenNotActive: False
      stateMachineName: Weapon # used by game logic.
      upgradeCostMult: 1
      useHeadgearGarmentAggregator: False # TODO. probably not used by weapons?
      useNewSpawnMethod: False
      usesVariants: False
      savable: False
      attacks: # used to set different types of projectiles that can be shot by the gun. not used in 2.0?
        - Attacks.Bullet_GameEffect
           ...
        - Attacks.ChimeraPowerMod_ExplosiveBulletEffect
      gameplayDescription: LocKey(92674) # used to set the description when inspecting weapon.
      ikOffset: {x: 0, y: 0, z: 0}
      shootingPatternPackages: [] # used by npc
      triggerModes: # trigger modes available to weapon. should have primary and secondary trigger modes here also
        - TriggerMode.FullAuto
      animationParameters: []
      appearanceSuffixes: [] 
      appearanceSuffixesOwnerOverride: []
      attachmentSlots: [] # TODO. used by attachments such as scopes and muzzles
      buyPrice: # price multipliers used when buying weapon.
        - Price.BaseWeaponPrice
        - Price.ItemQualityMultiplier
        - Price.PlusTierMultiplier
        - Price.BrokenItemPriceMult
        - Price.IconicMultiplier
        - Price.BuyPrice_StreetCred_Discount
        - Price.AssaultRifleMultiplier
        - Price.SmartWeapon
      cameraForward: {x: 0, y: 0, z: 0}
      cameraUp: {x: 0, y: 0, z: 0}
      connections: []
      displayName: LocKey(3599) # name of weapon
      equipAreas: []
      equipPrereqs: [] # TODO. used by game logic packages(GLP)?
      gameplayRestrictions: # restrict weapon usage in certain situations.
        - GameplayRestriction.VehicleCombatNoInterruptions
      hairSkinnedMeshComponents: []
      localizedDescription: LocKey(3600) # white text description when hovering over an item.
      OnAttach: # used to apply effects to player and weapon whean equipping weapon. stamina regen speed, stagger when shooting, etc
        - Items.Base_Assault_Rifle_inline0
        - EquipmentGLP.MediumStaminaRegen
        - EquipmentGLP.LightStaminaDelay
        - Items.SmartWeaponTargetsPriorityQueues
      OnEquip: [] 
      OnLooted: [] 
      parts: []
      placementSlots: # slots in Which this item can be placed in. see equipmentEX?
        - AttachmentSlots.WeaponRight
        - AttachmentSlots.WeaponLeft
        - AttachmentSlots.ItemSlotSniperRifle
        - AttachmentSlots.ItemSlotSMG
        - AttachmentSlots.ItemSlotTechRifle
        - AttachmentSlots.ItemSlotHandgunLeftJackie
        - AttachmentSlots.ItemSlotHandgunRightJackie
        - AttachmentSlots.ItemSlotGenericMelee
        - AttachmentSlots.ItemSlotHammer
        - AttachmentSlots.ItemSlotKatana
        - AttachmentSlots.ItemSlotKnifeRight
        - AttachmentSlots.ItemSlotKnifeLeft
        - AttachmentSlots.ItemSlotGenericRanged
        - AttachmentSlots.ItemSlotHandgunRight
        - AttachmentSlots.ItemSlotHandgunLeft
        - AttachmentSlots.ItemSlotTechRifle
        - AttachmentSlots.ItemSlotSMG
      previewBBoxOverride: []
      requiredSlots: []
      sellPrice:
        - Price.BaseWeaponPrice
        - Price.ItemQualityMultiplier
        - Price.PlusTierMultiplier
        - Price.WeaponSellMultiplier
        - Price.BrokenItemPriceMult
        - Price.IconicMultiplier
        - Price.AssaultRifleMultiplier
        - Price.SmartWeapon
      slotPartList: # what models to load when weapon has attachments and when it has mag inserted(or not)
        - Items.Base_Sidewinder_inline2
        - Items.Base_Sidewinder_inline4
        - Items.Base_Sidewinder_inline6
        - Items.Base_Sidewinder_inline8
      slotPartListPreset: # same as above but specific to the preset of the weapon, also used to set attachment and mod slots
        - Items.Preset_Sidewinder_Default_inline0
          …
        - Items.Preset_Sidewinder_Default_inline5
      tags: # tags signalling the game about weapon being smart, melee, ranged, etc....
        - Weapon
        - RangedWeapon
        - inventoryDoubleSlot
        - Preload
        - Weapon
        - Rifle Assault
        - Smart
        - SmartWeapon
        - Preload
        - Weapon
        - Rifle Assault
      variants: []
      visualTags: # visual tags used to set what look to use from the app file set in appearanceResoureName
        - Default
      effectors: []
      objectActions:
        - ItemAction.Drop
        - ItemAction.Disassemble
        - ItemAction.WeaponDisassemble
      statModifierGroups: # this section is for actually modifying weapon stats
        - Items.Base_Smart_Stats
        - Items.Base_Smart_Assault_Rifle_No_Sway_Stats
        - Items.Base_Assault_Rifle_RPG_Stats
        - Items.Base_Assault_Rifle_Misc_Stats
        - Items.Base_PlayerState_Spread_Stats
        - Items.Base_Weapon_Damage_Type_Min_Max
        - Items.Base_Weapon_Damage_Type_Physical
        - Items.QualityRandomization
        - Items.ItemPlusRandomizer_MaxQuality
        - Items.ItemPlusRandomizer_Below_MaxQuality
        - Items.WeaponModsWeights_On_Tier2Plus
        - Items.WeaponModsWeights_On_Tier3Plus
        - Items.WeaponModsWeights_On_Tier4Plus
        - Items.WeaponModsWeights_On_Tier5Plus
        - Items.WeaponModsWeights_On_Tier5PlusPlus
        - Items.Base_Smart_Assault_Rifle_Mult_Stats
        - Items.Base_Sidewinder_Technical_Stats # used to set: bullet amount fired, projectiles fired per bullet, smart weapon accuracy, fire 
    rate(cycle time), mag size, smart range
        - Items.Base_Sidewinder_Handling_Stats # used to set: reload speed, weapon zoom, speed of first equip anim.
        - Items.Base_Sidewinder_Recoil_Stats # used to set: recoil stats
        - Items.Base_Sidewinder_SmartGun_Stats # used to set: smartgun accuracy, projectile stats(speed), lock on stats
        - Items.Base_Sidewinder_SmartGun_SmartLink_Stats # used to set: smartlink requirement and how stats in Base_Sidewinder_SmartGun_Stats are affected by link
        - Items.Base_Sidewinder_SmartGun_Projectile_Stats # used to set: projectile miss conditions and other stuff like spirals
        - Items.Base_Sidewinder_Spread_Stats
        - Items.Base_Sidewinder_Flags # unknown
        - Items.Base_Sidewinder_Aim_Stats
        - Items.Base_Sidewinder_Constant_Stats # more spread stats, firepower, effective range
        - Items.Base_Sidewinder_Damage_Stats # used to set: DPS
      statModifiers: # this section is primarily used to set stuff intrinsic to all weapons
        - Items.Base_Weapon_inline0
          …
        - Items.Base_Weapon_inline149
      statPools: [] # used to set stat pools like tech weapon charge and overheating
      weakspots: []
      position: {x: '0,000500000024', y: 0, z: '0,0900000036'}
      price: Items.Base_Sidewinder_inline0
      weaponVignetteRadius: 0.648199975
      weaponEdgesSharpness: 0.495799989
      weaponFarPlane_aim: 23.7000008
      weaponFarPlane: 29.5
      weaponEdgesSharpness_aim: 0.495799989
      weaponVignetteCircular_aim: 0.174500003
      offset: -0.100000001
      safeActionDuration: 2
      weaponVignetteIntensity_aim: 0.135700002
      weaponNearPlane_aim: 12.4700003
      weaponVignetteRadius_aim: 0.681400001
      weaponNearPlane: 8.31000042
      weaponVignetteIntensity: 0.135700002
      weaponBlurIntensity_aim: 1
      weaponVignetteCircular: 0
      weaponBlurIntensity: 1
      hide_nametag: True
    Items.Preset_Unity_Default: -> Remove this
    Items.Hand_Of_Midas: -> Add this
     Game.AddToInventory("Items.Hand_Of_Midas",1)
      crosshair: Crosshairs.Simple # -> remove this
      crosshair: Crosshairs.Tech_Round # <- add this
    Game.AddToInventory("Items.Hand_Of_Midas",1)
    Game.AddToInventory("Items.Preset_Unity_Default",1)
    Items.Hand_Of_Midas:
      $base: Items.Preset_Unity_Default
      # Just the properties we want to edit...
    
    # OR
    
    Items.Hand_Of_Midas:
      $type: WeaponItem
      # Every single property of the weapon...
    Items.Hand_Of_Midas:
      $base: Items.Preset_Unity_Default
      crosshair: Crosshairs.Tech_Round
    localization:
      onscreens:
        en-us: midas_collection\localization\en-us.json
    Items.Hand_Of_Midas:
      $base: Items.Preset_Unity_Default
      crosshair: Crosshairs.Tech_Round
      displayName: LocKey("MC_gun_name")
      localizedDescription: LocKey("MC_gun_description")
    # Hand of Midas weapon tweak
    Items.Hand_Of_Midas:
      $base: Items.Preset_Unity_Default # $base makes it so all the properties are taken from the specified tweak (in this case, "Items.Preset_Unity_Default") and the properties specified in this tweak overwrite the parent.
      crosshair: Crosshairs.Tech_Round # other crosshairs can be found by looking for "Crosshairs." in Tweak Browser
      displayName: LocKey("MC_gun_name") # name of the gun (will be fetched from "LocKey#MC_gun_name" secondary key in "en-us.json")
      localizedDescription: LocKey("MC_gun_description") # description of the gun (can be seen when previewing the gun from inventory with "V" key)
      tags:
        - !append IconicWeapon # prevent the gun from being dissassembled
      statModifiers:
        - !append Quality.IconicItem # makes the weapon iconic
      statModifierGroups:
        - !append Items.IconicQualityRandomization # necessary for ingame upgrade
        - !remove Items.QualityRandomization # to prevent stacking with the previous
    Items.Hand_Of_Midas:
      #...
      blueprint: Items.Iconic_Ranged_Weapon_Blueprint # blueprint decides what kind of attachments/mods are allowed on a weapon
    Items.Hand_Of_Midas:
      #...  
      quality: Quality.Rare # minimum item quality
    Items.Hand_Of_Midas:
      #...
      buyPrice:
        - Price.Hand_Of_Midas
        - Price.BuyPrice_StreetCred_Discount
      sellPrice:
        - Price.Hand_Of_Midas
        - Price.WeaponSellMultiplier
    
    # Static price for Hand of Midas
    Price.Hand_Of_Midas:
      $type: ConstantStatModifier
      value: 100000
      modifierType: Additive
      statType: BaseStats.Price
    WilsonWeaponMod : IconicWeaponModBase
    {
        OnAttach = 
        [
           "Items.WilsonWeaponModAbility"
        ];
        statModifiers += 
        [
           {
              statType = "BaseStats.ReloadTimeBonus";
              modifierType = "Additive";
              value = -0.1f;
           } : ConstantStatModifier 
        ];
    }
    WilsonWeaponModAbility : IconicWeaponModAbilityBase
    {
        UIData = 
        {
           iconPath = "ability_offensive";
           localizedDescription = "LocKey#50743";
        };
        effectors = 
        [
           {
              prereqRecord = "Prereqs.ProcessHitTriggered";
              percentMult = 0.25f;
              unitThreshold = 10f;
           } : MultiplyDamageWithVelocity, 
           {
              prereqRecord = "Perks.IsHitQuickMelee";
              value = 1.5f;
           } : MultiplyDamage
        ];
    }
    # Hand of Midas weapon tweak
    Items.Hand_Of_Midas:
      # your other properties - cut out for readability
      slotPartListPreset: # attachments & mods 
        - !append
          $type: SlotItemPartPreset
          itemPartPreset: Items.Cranial_Cashback_Mod # iconic mod
          slot: AttachmentSlots.IconicWeaponModLegendary 
    # Hand of Midas Iconic mod
    Items.Cranial_Cashback_Mod:
      $base: Items.IconicWeaponModBase
      OnAttach: 
        - Items.Cranial_Cashback
      statModifiers:
        - !append
          $type: ConstantStatModifier
          statType: BaseStats.ReloadTimeBonus # modifies reload time (without influence to DamagePerHit)
          modifierType: Additive
          value: -0.20
        - !append
          $type: ConstantStatModifier
          statType: BaseStats.MagazineCapacityBonus # multiplier on total mag size (without influence to DamagePerHit)
          modifierType: Additive
          value: 0.34
        - !append
          $type: ConstantStatModifier
          statType: BaseStats.DamagePerHit # Direct change to damage per hit
          modifierType: Multiplier
          value: 1.1
    # Hand of Midas Iconic mod ability
    Items.Cranial_Cashback:
      $base: Items.IconicWeaponModAbilityBase
      # effectors:
      #   - Effectors.Punish_Miss
      #   - Effectors.Heal_On_Headshot
      UIData:
        $type: GameplayLogicPackageUIData
        localizedDescription: LocKey("MC_gun_iconic_description") # iconic description shown in yellow text when hovering over a weapon
    # Hand of Midas weapon tweak
    Items.Hand_Of_Midas:
      #...
      slotPartListPreset: # attachments & mods 
        - !append-once
          $type: SlotItemPartPreset
          itemPartPreset: Items.Cranial_Cashback_Mod # iconic mod
          slot: AttachmentSlots.IconicWeaponModLegendary 
    
    # Hand of Midas Iconic mod
    Items.Cranial_Cashback_Mod:
      $base: Items.IconicWeaponModBase
      OnAttach: 
        - Items.Cranial_Cashback
      statModifiers:
        - $type: ConstantStatModifier
          statType: BaseStats.ReloadTimeBonus # modifies reload time (without influence to DamagePerHit)
          modifierType: Additive
          value: -0.20
        - $type: ConstantStatModifier
          statType: BaseStats.MagazineCapacityBonus # multiplier on mag size (without influence to DamagePerHit)
          modifierType: Additive
          value: 0.34
        - $type: ConstantStatModifier
          statType: BaseStats.DamagePerHit # Direct change to damage per hit
          modifierType: Multiplier
          value: 1.1
    
    # Hand of Midas Iconic mod ability
    Items.Cranial_Cashback:
      $base: Items.IconicWeaponModAbilityBase
      # effectors:
      #   - Effectors.Punish_Miss
      #   - Effectors.Heal_On_Headshot
      UIData:
        $type: GameplayLogicPackageUIData
        localizedDescription: LocKey("MC_gun_iconic_description") # iconic description shown in yellow text when hovering over a weapon
    Items.MemoryReplenishmentEffector:
      $type: ModifyStatPoolValueEffector
      setValue: False
      usePercent: True
      effectorClassName: ModifyStatPoolValueEffector
      prereqRecord: Items.MemoryReplenishmentEffector_inline0
      removeAfterActionCall: False
      removeAfterPrereqCheck: False
      statPoolUpdates:
        - Items.MemoryReplenishmentEffector_inline4
      statModifierGroups: []
    Effectors.Heal_On_Headshot:
      $type: ModifyStatPoolValueEffector
      setValue: False
      usePercent: True
      effectorClassName: ModifyStatPoolValueEffector
      prereqRecord: Items.MemoryReplenishmentEffector_inline0
      removeAfterActionCall: False
      removeAfterPrereqCheck: False
      statPoolUpdates: 
        - $type: StatPoolUpdate
          statPoolType: BaseStatPools.Health
          statPoolValue: 80
      statModifierGroups: []
    # Prereq to check if headshot & target is alive and hit with a ranged weapon
    Prereqs.Is_Target_Alive_And_Headshot:
      $type: HitPrereq
      callbackType: HitTriggered
      ignoreSelfInflictedPressureWave: True
      isSynchronous: True
      pipelineStage: Process
      pipelineType: Damage
      prereqClassName: HitTriggeredPrereq # how to refer to it later - Prereqs.HitTriggeredPrereq
      conditions:
        - Perks.IsHitTargetAlive_inline2 # hit target is alive (health != 0)
        - Perks.HitIsBodyPartHead_inline0 # headshot condition
        - Prereqs.Is_Attack_Ranged # condition to check if it's the bullet hitting the target and not a quick melee
        - Prereqs.Is_Weapon_Ranged # condition to check that the gun is source of damage and not a grenade
      processMiss: False # process shots that hit npcs only
    # Condition to check if attack type is ranged
    Prereqs.Is_Attack_Ranged:
      $type: HitPrereqCondition
      invert: False
      onlyOncePerShot: True
      type: Prereqs.AttackType
      attackType: Ranged
    
    # Condition to check if weapon type is ranged
    Prereqs.Is_Weapon_Ranged:
      $type: HitPrereqCondition
      invert: False
      onlyOncePerShot: True
      type: Prereqs.WeaponType
      weaponType: Ranged
    # Effector to heal player if they hit a headshot
    Effectors.Heal_On_Headshot:
      $type: ModifyStatPoolValueEffector
      prereqRecord: Prereqs.Is_Target_Alive_And_Headshot
      usePercent: False
      statPoolUpdates: 
        - $type: StatPoolUpdate
          statPoolType: BaseStatPools.Health
          statPoolValue: 80
    # Effector to inflict damage on player when they shoot
    Effectors.Punish_Miss:
      $type: ModifyStatPoolValueEffector
      prereqRecord: Prereqs.Has_Player_Shot
      usePercent: False
      statPoolUpdates: 
        - $type: StatPoolUpdate
          statPoolType: BaseStatPools.Health
          statPoolValue: -20
    
    # Prereq to check if the player has shot (bug - currently detects if a player has hit anything, not if shot)
    Prereqs.Has_Player_Shot:
      $type: HitPrereq
      callbackType: HitTriggered
      ignoreSelfInflictedPressureWave: True
      isSynchronous: True
      pipelineStage: PreProcess
      pipelineType: All
      prereqClassName: HitOrMissTriggeredPrereq
      processMiss: True # process shots that miss npcs
      conditions:
        - Prereqs.Is_Attack_Ranged # condition to check if it's the bullet hitting the target and not a quick melee
        - Prereqs.Is_Weapon_Ranged # condition to check that the gun is source of damage and not a grenade
    # Hand of Midas weapon tweak
    Items.Hand_Of_Midas:
      $base: Items.Preset_Unity_Default # $base makes it so all the properties are taken from the specified tweak (in this case, "Items.Preset_Unity_Default") and the properties specified in this tweak overwrite the parent.
      blueprint: Items.Iconic_Ranged_Weapon_Blueprint # blueprint decides what kind of attachments/mods are allowed on a weapon
      crosshair: Crosshairs.Tech_Round # other crosshairs can be found by looking for "Crosshairs." in Tweak Browser
      displayName: LocKey("MC_gun_name") # name of the gun (will be fetched from "LocKey#MC_gun_name" secondary key in "en-us.json")
      localizedDescription: LocKey("MC_gun_description") # description of the gun (can be seen when previewing the gun from inventory with "V" key)
      quality: Quality.Rare # minimum item quality
      tags:
        - !append IconicWeapon # prevent the gun from being dissassembled
      statModifiers: # stats for a weapon - reload time/aim speed/magazine size/recoil kick/damage per second/etc.
        - !append Quality.IconicItem # makes the weapon iconic
      statModifierGroups: # stats for a weapon also, but grouped (generally by category)
        - !append Items.IconicQualityRandomization # necessary for ingame upgrade
        - !remove Items.QualityRandomization # to prevent stacking with the previous
      slotPartListPreset: # attachments & mods 
        - !append
          $type: SlotItemPartPreset
          itemPartPreset: Items.Cranial_Cashback_Mod # iconic mod
          slot: AttachmentSlots.IconicWeaponModLegendary
      buyPrice:
        - Price.Hand_Of_Midas
        - Price.BuyPrice_StreetCred_Discount
      sellPrice:
        - Price.Hand_Of_Midas
        - Price.WeaponSellMultiplier
        
    Price.Hand_Of_Midas:
      $type: ConstantStatModifier
      value: 100000
      modifierType: Additive
      statType: BaseStats.Price
    
    Items.Cranial_Cashback_Mod:
      $base: Items.IconicWeaponModBase
      OnAttach: 
        - Items.Cranial_Cashback
      statModifiers:
        - !append
          $type: ConstantStatModifier
          statType: BaseStats.ReloadTimeBonus # modifies reload time (without influence to DamagePerHit)
          modifierType: Additive
          value: -0.20
        - !append
          $type: ConstantStatModifier
          statType: BaseStats.MagazineCapacityBonus # multiplier on mag size (without influence to DamagePerHit)
          modifierType: Additive
          value: 0.34
        - !append
          $type: ConstantStatModifier
          statType: BaseStats.DamagePerHit # Direct change to damage per hit
          modifierType: Multiplier
          value: 1.1
    
    Items.Cranial_Cashback:
      $base: Items.IconicWeaponModAbilityBase
      effectors:
        - Effectors.Punish_Miss
        - Effectors.Heal_On_Headshot
      UIData:
        $type: GameplayLogicPackageUIData
        localizedDescription: LocKey("MC_gun_iconic_description") # iconic description shown in yellow text when hovering over a weapon
    
    # -------------------------------------------------------------------------------------------------------------------------
    
    # Effector to inflict damage on player when they shoot
    Effectors.Punish_Miss:
      $type: ModifyStatPoolValueEffector
      prereqRecord: Prereqs.Has_Player_Shot
      usePercent: False
      statPoolUpdates: 
        - $type: StatPoolUpdate
          statPoolType: BaseStatPools.Health
          statPoolValue: -20
    
    # Effector to heal player if they hit a headshot
    Effectors.Heal_On_Headshot:
      $type: ModifyStatPoolValueEffector
      prereqRecord: Prereqs.Is_Target_Alive_And_Headshot
      usePercent: False
      statPoolUpdates: 
        - $type: StatPoolUpdate
          statPoolType: BaseStatPools.Health
          statPoolValue: 80
    
    # -------------------------------------------------------------------------------------------------------------------------
    
    # Prereq to check if the player has shot (bug - currently detects if a player has hit anything, not if shot)
    Prereqs.Has_Player_Shot:
      $type: HitPrereq
      callbackType: HitTriggered
      ignoreSelfInflictedPressureWave: True
      isSynchronous: True
      pipelineStage: PreProcess
      pipelineType: All
      prereqClassName: HitOrMissTriggeredPrereq
      processMiss: True # process shots that miss npcs
      conditions:
        - Prereqs.Is_Attack_Ranged # condition to check if it's the bullet hitting the target and not a quick melee
        - Prereqs.Is_Weapon_Ranged # condition to check that the gun is source of damage and not a grenade
    
    # Prereq to check if headshot & target is alive and hit with a ranged weapon
    Prereqs.Is_Target_Alive_And_Headshot:
      $type: HitPrereq
      callbackType: HitTriggered
      ignoreSelfInflictedPressureWave: True
      isSynchronous: True
      pipelineStage: Process
      pipelineType: Damage
      prereqClassName: HitTriggeredPrereq
      conditions:
        - Perks.IsHitTargetAlive_inline2 # hit target is alive (health != 0)
        - Perks.HitIsBodyPartHead_inline0 # headshot condition
        - Prereqs.Is_Attack_Ranged # condition to check if it's the bullet hitting the target and not a quick melee
        - Prereqs.Is_Weapon_Ranged # condition to check that the gun is source of damage and not a grenade
      processMiss: False # process shots that hit npcs only
    
    # -------------------------------------------------------------------------------------------------------------------------
    
    # Condition to check if attack type is ranged
    Prereqs.Is_Attack_Ranged:
      $type: HitPrereqCondition
      invert: False
      onlyOncePerShot: True
      type: Prereqs.AttackType
      attackType: Ranged
    
    # Condition to check if weapon type is ranged
    Prereqs.Is_Weapon_Ranged:
      $type: HitPrereqCondition
      invert: False
      onlyOncePerShot: True
      type: Prereqs.WeaponType
      weaponType: Ranged
    # Hand of Midas weapon tweak
    Items.Hand_Of_Midas:
      # ...
      audioName: wea_set_liberty_dex
      # ...
    Example: browsing .tweak files
    Effector
    Condition
    Console
    Tweak Browser
    Visual Studio Code
    Visual Studio Code
    .app file: Conditional switching

    Dynamic appearances: Understanding the process

    How does the ancient magic work?

    hashtag
    Summary

    This page explains the files from ItemAdditions: Dynamic Appearances -> Generated files, what they do, and how they do it.

    circle-info

    You will be able to change the template project just by following the steps, but if you want to make your own mods, then you're going to want to understand this.

    Depending on how you learn best, you can also fuck around and try to understand the connections yourself. In that case, check at the end of the section.

    hashtag
    The yaml

    For a general explanation of what the yaml file does, check . This section will only cover the differences between a dynamic and a regular yaml.

    circle-info

    This file contains the biggest part of the dynamic magic.

    This is your dynamic project's yaml file, minus any properties that aren't influenced by the dynamic appearances:

    This section will explain how that works - except for the appearanceName, you will find that in .

    hashtag
    Record names

    TweakXL will generate one record per entry in $instances, according to the rules that you're using in the item name. This happens via property interpolation.

    The example above will generate three item entries by substituting $(property_name) with the value of the property from the entry. If that isn't clear enough, check the example and the resulting item codes at the end of the line.

    If you your project, you can immediately spawn them in Cyberpunk via Cyber Engine Tweaks:

    hashtag
    Display names

    Like the record names, the displayName property is also generated for each entry:

    These entries have been auto-generated in your .

    hashtag
    Icons

    The icon name in the record is also generated for each entry. They are all using the same , but you can generate that as well if you want - I've done it for the , since I needed more than 100 icons.

    You can see that the generated names are identical to the ones in the section above. That is because the key to generate them (atlasPartName) has the same pattern as displayName .

    circle-info

    If you want to make gendered icons, please check ->

    chevron-rightExercise 1: Create more recordshashtag
    circle-info

    This is outdated and needs to be re-worked to consider the new generated structure

    With clever hook-ups in the mesh entity, you can set up your items so that they can be changed with a simple .yaml edit — that means, the user can switch out the ribbon colour without ever starting Wolvenkit!

    hashtag
    The root_entity

    For a general explanation of the root entity, check . This section will only cover the differences between a dynamic and a regular root entity.

    circle-info

    This is where you enable the feature by adding the tag DynamicAppearance to the visualTagsSchema (the last entry in the file):

    circle-exclamation

    For dynamic appearances, your root_entity file will contain one entry. You can give every item , or share a file across the mod.

    The appearance name in the root entity corresponds to the appearanceName property in the .yaml without the variant:

    You can leave the appearanceName blank. In that case, ArchiveXL will look for an appearance with the same name as the name attribute.

    hashtag
    The .app

    For a general explanation of the .app file, check . This section will only cover the differences between a dynamic and a regular .app file.

    triangle-exclamation

    For dynamic variants, components in the .app file will be ignored. You have to use a mesh entity.

    hashtag
    .app file: Conditional switching

    circle-info

    You can find more about this under .

    You can define appearances for different circumstances by changing the appearance names. This will let you influence the mesh entity even further by e.g. hiding parts of the mesh via . And the best part is: you don't even need to touch your root entity.

    In the context of our example project, this means that you can define your appearances like this:

    Appearance name
    Explanation

    hashtag
    The mesh_entity

    Unless you are using , this file contains the entire magic. This section will explain how you tell the .ent file to load different meshes.

    You can use either or (not recommended) .

    hashtag
    Wait, this is not what I want!

    • For a picture of the difference between substitutions and conditional switching, check 's bottom left corner

    • For a general explanation of the mesh entity, check

    • To learn more about dynamic appearances, check the

    hashtag
    How it works

    Per default, all components in the mesh entity are active and will be added to the player when you equip your item. Which parts of them are visible is determined by their (set everything to visible, then use the .app's to hide parts of them).

    hashtag
    Substitutions

    circle-info

    Check for a full list of your options.

    Substitutions in path names will be switched out by ArchiveXL at runtime. For example, p{gender}a becomes pwa if your V has a female body gender, and pma if they don't.

    To enable substitution, your depot path must begin with an asterisk *. Each substitution needs to be enclosed in braces, e.g. {gender}. All generated paths will already be dynamic.

    circle-info

    can help you spot errors in your paths.

    hashtag
    .ent file: conditional switching

    circle-exclamation

    This is only documented because it's possible, not because it's good practice: ArchiveXL will create all components, hiding those that aren't matched by your current conditions.

    If possible, use together with and .

    chevron-rightClick to expand (DO NOT USE THIS, check the box above)hashtag

    Just like in the .app file, you can apply conditional switching to component names. It works exactly like :

    Components can also be selected by variant, this currently cannot be broken down by variant parts (eg variant.1, variant.2 etc) but it uses the full variant after the ! in the yaml.

    In this above example you can create filtered components by instance as follows. The one without the ! will be used by default if the variant is not in the list (eg black_pink).

    This is what your compontent can look like; in this example a different light is used based on the variant.

    hashtag
    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, but that the rest of the files has gotten a lot more manageable:

    We'll use that here to enable "hidden" appearances.

    I have hooked up the example project to support two base colours:

    • black

    • white

    and three ribbon colors:

    • red

    • blue

    • green

    By editing the $instances block in the .yaml, you should be able to spawn 6 different shirt in the game without touching any of the additional files!

    app_file_dynamic_appearance

    Your regular appearance. Is displayed when none of the conditional ones apply.

    app_file_dynamic_appearance&camera=tpp

    This is only active in third person perspective. The item will be completely invisible in first person.

    app_file_dynamic_appearance&camera=fpp

    This becomes active whenever you are in first person perspective. You'll usually want this to remove the mesh from your face via partsOverridesarrow-up-right.

    app_file_dynamic_appearance&gender=male

    localization file
    inkatlas
    Netrunner suitsarrow-up-right
    Gendered preview icons
    its own root entityarrow-up-right
    Dynamic Appearances: fine-tuning visibility conditions
    ArchiveXL documentation
    chunk masks
    partsOverride
    vanilla variants
    It's DynamicAppearance, without S.
    Exercise 1: Create more records
    The control file: yourModName.yaml
    The root_entity
    Display names
    root_entity.ent
    appearance.app
    .app file: Conditional switching
    Substitutions
    .ent file: conditional switching
    The diagram
    mesh_entity.ent
    Substitutions
    .app file: Conditional switching
    .app file: Conditional switching
    install and launch
    File validation

    You shouldn't do this — instead, use in the mesh file path.

    Items.manavortex_my_custom_shirt_$(base_color)_$(secondary):
      $base: Items.TShirt
      $instances:
        - {base_color: black, secondary: samurai}
        - {base_color: black, secondary: witcher}
        - {base_color: black, secondary: galaxy}
        - {base_color: white, secondary: samurai}
        - {base_color: white, secondary: witcher}
        - {base_color: white, secondary: galaxy}
        - {base_color: red, secondary: samurai}
        - {base_color: red, secondary: witcher}
        - {base_color: red, secondary: galaxy}
      appearanceName: my_custom_shirt_!$(base_color)+$(secondary)
      entityName: my_custom_shirt_factory_name
      localizedDescription: LocKey#my_custom_shirt_i18n_desc
      displayName: LocKey#my_custom_shirt_i18n_$(base_color)_$(secondary)
      quality: Quality.Legendary
      icon:
        atlasResourcePath: manavortex\my_archive_xl_item\my_custom_shirt\my_custom_shirt_icons.inkatlas
        atlasPartName: my_custom_shirt_$(base_color)_$(secondary)
      statModifiers:
        - !append Quality.IconicItem
        - !append Character.ScaleToPlayerLevel
      appearanceSuffixes: []
      statModifierGroups:
        - !append-once Items.IconicQualityRandomization
      placementSlots: OutfitSlots.TorsoInner
    
    
    Items.manavortex_my_custom_shirt_$(base_color)_$(secondary):
      $instances:
        - {base_color: black, secondary: samurai}  # Items.manavortex_my_custom_shirt_black_samurai
        - {base_color: black, secondary: witcher}  # Items.manavortex_my_custom_shirt_black_witcher
        - {base_color: black, secondary: galaxy}   # Items.manavortex_my_custom_shirt_black_galaxy
        - {base_color: white, secondary: samurai}  # Items.manavortex_my_custom_shirt_white_samurai
        - {base_color: white, secondary: witcher}  # Items.manavortex_my_custom_shirt_white_witcher
        - {base_color: white, secondary: galaxy}   # Items.manavortex_my_custom_shirt_white_galaxy
        - {base_color: red, secondary: samurai}    # Items.manavortex_my_custom_shirt_red_samurai
        - {base_color: red, secondary: witcher}    # Items.manavortex_my_custom_shirt_red_witcher
        - {base_color: red, secondary: galaxy}     # Items.manavortex_my_custom_shirt_red_galaxy
    Game.AddToInventory("Items.manavortex_my_custom_shirt_black_samurai")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_black_witcher")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_black_galaxy")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_white_samurai")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_white_witcher")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_white_galaxy")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_red_samurai")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_red_witcher")
    Game.AddToInventory("Items.manavortex_my_custom_shirt_red_galaxy")
    displayName: my_custom_shirt_i18n_$(base_color)_$(secondary)
    $instances:
      - {base_color: black, secondary: samurai}  # my_custom_shirt_i18n_black_samurai
      - {base_color: black, secondary: witcher}  # my_custom_shirt_i18n_black_witcher
      - {base_color: black, secondary: galaxy}   # my_custom_shirt_i18n_black_galaxy
      - {base_color: white, secondary: samurai}  # my_custom_shirt_i18n_white_samurai
      - {base_color: white, secondary: witcher}  # my_custom_shirt_i18n_white_witcher
      - {base_color: white, secondary: galaxy}   # my_custom_shirt_i18n_white_galaxy
      - {base_color: red, secondary: samurai}    # my_custom_shirt_i18n_red_samurai
      - {base_color: red, secondary: witcher}    # my_custom_shirt_i18n_red_witcher
    icon:
      atlasResourcePath: manavortex\my_archive_xl_item\my_custom_shirt\my_custom_shirt_icons.inkatlas
      atlasPartName: my_custom_shirt_$(base_color)_$(secondary)
    $instances:
      - {base_color: black, secondary: samurai}  # my_custom_shirt_i18n_black_samurai
      - {base_color: black, secondary: witcher}  # my_custom_shirt_i18n_black_witcher
      - {base_color: black, secondary: galaxy}   # my_custom_shirt_i18n_black_galaxy
      - {base_color: white, secondary: samurai}  # my_custom_shirt_i18n_white_samurai
      - {base_color: white, secondary: witcher}  # my_custom_shirt_i18n_white_witcher
      - {base_color: white, secondary: galaxy}   # my_custom_shirt_i18n_white_galaxy
      - {base_color: red, secondary: samurai}    # my_custom_shirt_i18n_red_samurai
      - {base_color: red, secondary: witcher}    # my_custom_shirt_i18n_red_witcher
    $instances:
        - { base_color: white, ribbons: red  }
        - { base_color: black, ribbons: red  }
        - { base_color: black, ribbons: blue }
    appearanceName: root_entity_dynamic_appearance_!$(base_color)+$(ribbons)
    entSkinnedMeshComponent: MyJacketDecals!white_red
    entSkinnedMeshComponent: MyJacketDecals!black_red
    entSkinnedMeshComponent: MyJacketDecals!black_blue
    entSkinnedMeshComponent: MyJacketDecals
    Substitutions
    Does this work with dynamic variants?
    chunkMask
    Which substitutions exist?
    PartsOverrides: Changing other meshes