Guide:Hair Mod File Setup: Difference between revisions

From bg3.wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(71 intermediate revisions by 3 users not shown)
Line 3: Line 3:
|description=This page is a hub for everything related to Modding Baldur's Gate 3. Check out the following guides to learn how to mod BG3.
|description=This page is a hub for everything related to Modding Baldur's Gate 3. Check out the following guides to learn how to mod BG3.
|image=Modding_resources.webp
|image=Modding_resources.webp
}}{{NavModding}}
}}{{Modding box}}{{Modding sidebar}}
Welcome to the file setup portion of making a hair mod. For an overview of all the steps, see [[Modding:Creating Hair Mods]].


== Tools ==
== Tools You'll Need ==


* [https://github.com/ShinyHobo/BG3-Modders-Multitool BG3 Modders Multitool]
* [https://github.com/ShinyHobo/BG3-Modders-Multitool BG3 Modders Multitool] (required)
* [https://www.nexusmods.com/baldursgate3/mods/502 BG3 Mini Tool]
* [https://bg3.wiki/wiki/Modding:BG3_Mini_Tool BG3 Mini Tool] (optional but helpful)
* [https://www.nexusmods.com/baldursgate3/mods/437 Hair Template]
* [https://www.nexusmods.com/baldursgate3/mods/437 Padme's Hair Template] (required unless you have a template from somewhere else)
* [https://code.visualstudio.com/ vscode] or [https://notepad-plus-plus.org/ Notepad++]
* [https://code.visualstudio.com/ VSCode] or [https://notepad-plus-plus.org/ Notepad++] (required)
* UUID Generator Extension in vscode (right click when its installed to generate a new uuid) or ToolBucket & XML Tools in Notepad++ found via Plugins > Plugins Admin then search for it and install.
* UUID Generator Extension in VSCode OR ToolBucket & XML Tools in Notepad++ (found via Plugins > Plugins Admin, then search for it and install.) (optional but helpful)


For the UUID generation in Notepad++ once installed ToolBucket you want to press Alt + Shift + G it will bring up a window as shown below. Keep include hyphens ticked and you can also click don't ask again if you won't use any of the other options.
To generate a UUID in VSCode, just highlight a section of code, right click, and select Generate UUID here. It will replace the selected code with a new UUID.
 
For the UUID generation in Notepad++, once ToolBucket is installed, you want to press Alt + Shift + G. It will bring up a window as shown below. Keep Include hyphens ticked, and you can also click Don't ask again if you won't use any of the other options. Then click Generate.


[[File:Toolbucketuuid.webp]]
[[File:Toolbucketuuid.webp]]


<br>
<br>
If wanting to add more than one hair to your mod you can use my mini tool linked above for adding new slots to CharacterCreationAppearanceVisuals
If wanting to add more than one hair to your mod, you can use Padme's mini tool linked above for adding new slots to CharacterCreationAppearanceVisuals. You can also use it to edit your .loca file if you desire.


If adding an existing hair from the game without wanting to do any edits you can remove the Generated folder from your copy of the template.
You can choose for your hairs to be autosnapping or non autosnapping.


Also remember to create your meta.lsx for your mod as well or if using multitool to pack create a Mods folder in your workspace folder and let multitool create the meta.lsx for you. Follow along this mini tutorial on how to create your meta.lsx [[Modding:Creating meta.lsx|Creating your Meta.lsx]]
=== What are autosnapping and non autosnapping hairs? ===


== Blender ==
{{CollapsibleOnDesktop|Autosnapping hairs are basically when you have an asset you want to work for more than one race/bodyshape/bodytype, but don't want to make a mesh for every single variation. So when setup to be autosnapping, you can apply one mesh to be used by multiple races/bodyshapes/bodytypes. And the game "autosnaps" them into place using a series of "sockets" that the hair is weighted to.


Once you have your mesh ready in blender (can follow [https://youtu.be/siC6fak9zDM?si=-MVOYMB3hneWTxaT this tutorial] if you want, blender steps are still the same just import/export is a bit different.
Sometimes you may still need three autosnapping meshes, one for the shorter races, one for the default bodytype and one for the strong bodytype. However we will go through when this is needed further into the tutorial.


If using the [https://github.com/Norbyte/dos2de_collada_exporter gr2 plugin] you want to first make sure you have your export order setup which you can find the in Object Properties tab:
Non autosnapping is when the game doesn't snap the hair into place at all. So, you have to create your hair mesh for each race/bodyshape/bodytype that you want it to be usable for. Obviously, this takes more work, but it can often give better/less crunchy results than autosnapping, and it is much easier to manually weight a non-autosnapping hair than an autosnapping hair. For instance, for personal use hairs, you might decide you only want it for one character. Then non autosnapping might be the way to go.|collapsed=Autosnapping hairs are basically when you have an asset you want to work for more than one race/bodyshape/bodytype, but don't want to make a mesh for every single variation. So when setup to be autosnapping, you can apply one mesh to be used by multiple races/bodyshapes/bodytypes. And the game "autosnaps" them into place using a series of "sockets" that the hair is weighted to.


[[File:Exportorder.webp]]
Sometimes you may still need three autosnapping meshes, one for the shorter races, one for the default bodytype and one for the strong bodytype. However we will go through when this is needed further into the tutorial.


Set the LOD Distance to 0 and for the first part of your mesh export order 1. Increase the export order number for every part you have.  
Non autosnapping is when the game doesn't snap the hair into place at all. So, you have to create your hair mesh for each race/bodyshape/bodytype that you want it to be usable for. Obviously, this takes more work, but it can often give better/less crunchy results than autosnapping, and it is much easier to manually weight a non-autosnapping hair than an autosnapping hair. For instance, for personal use hairs, you might decide you only want it for one character. Then non autosnapping might be the way to go.}}


Now once you have all that setup if you haven't already sometime in your process select the armature and your meshes and apply transforms with Ctrl + A > Apply Transforms
== Following the Template ==


Now you can export the mesh(es). These are the export settings I use when exporting with the GR2 plugin:
Following Padme's [https://www.nexusmods.com/baldursgate3/mods/437 template] (or using it as a guide to copy parts from the game files), follow along with this tutorial.


[[File:Gr2export.webp]]
If you are only adding an existing hair from the game to CC without wanting to do any edits, you can remove the Generated folder from your copy of the template and instead just link to the game's existing hair in the _merged.


The settings below this cutoff remain as they are by default. If you don't apply transforms turn back on the Convert to Y-up
You may have downloaded the template, and now feel overwhelmed by all the files and folders, but it's really not too complicated. There are only four* files that we need to edit: loca.xml, meta.lsx, _merged.lsf.lsx and CharacterCreationAppearanceVisuals.lsx. You'll also need to place your .GR2 in the Generated folder, but more on that later.


== Following the Template ==
*If using the CharacterCreationSharedVisuals method, technically five files including Races.lsx. More on that later!


So if following my Template or just using it as a guide to copy parts from the game files you can follow along with this tutorial.  
Alternatively you can follow [https://youtu.be/dNLP6Lt_zFo?si=fmRVTUYBpF00s-Uc this video] by Bububull for the file setup if you want to use the CharacterCreationAppearanceVisuals method.


You can choose for your hairs to be autosnapping or non autosnapping
== Mods/meta.lsx ==


=== What are autosnapping and non autosnapping hairs? ===
Remember to create your meta.lsx for your mod as well, as it is required for almost all pak mods. If using multitool to pack, you can create a Mods folder in your workspace folder and let multitool create the meta.lsx for you. Otherwise, follow this tutorial on how to create your meta.lsx: [[Modding:Creating meta.lsx|Creating your Meta.lsx]]
 
Autosnapping hairs are basically when you have an asset you want to work for more than one race/bodyshape/bodytype but don't want to make a mesh for every single variation. So when setup to be autosnapping you can apply one mesh to be used by multiple races/bodyshapes/bodytypes. And the game "autosnaps" them into place.
 
<br>
Sometimes you may still need three autosnapping meshes, one for the shorter races, one for the default bodytype and one for the strong bodytype. However we will go through when this is needed further into the tutorial.
 
<br>
Non autosnapping is when you have to create your hair mesh for each race/bodyshape/bodytype or rather the ones you want to create it for. For instance for personal use hairs you might decide you only want it for one character. Then non autosnapping might be the way to go.


== Localization/English/custom_name_here.loca.xml ==
== Localization/English/custom_name_here.loca.xml ==


Why is it named .loca.xml?
After you've sorted your meta.lsx, let's start with the loca.xml. This is the file that tells your game what text to display for your hair--aka the name of the hair in Character Creation. If this file is broken or doesn't exist, your hair will show up as "Not Found".


This is because if you package the Main folder also known as your workspace folder with multitool it will auto convert the .loca.xml to .loca
Why is it named .loca.xml? This is because if you package the Main folder (also known as your workspace folder) with multitool, it will auto convert the .loca.xml to .loca. This way, you don't have to manually do the conversions yourself. However, if you prefer to do manual conversions, change the extension to .xml only.


This way you don't have to manually do the conversions yourself. However if you prefer to do manual conversions change the extension to .xml only.
You can find the _merged file at: Localization/English/custom_name_here.loca.xml.


Change custom_name_here to a custom name. Best to add a prefix beforehand. For example I use my username Padme4000 but shorten it to P4
Change custom_name_here to a custom name. It's best to add a personalized prefix beforehand so there is no chance of your mod name clashing with another mod. For example, Padme4000 uses her username, but shortened to P4. So for Padme's viking braid hair, her .loca.xml would be called p4_viking_braid.loca.xml


So for my viking braid my .loca.xml is called p4_viking_braid.loca.xml
This way, if someone else happens to make a viking braid, the chances of them also naming their hair "p4_viking_braid" are extremely low, and there's no danger of one of the mods overriding the other.


[[File:Localisation.webp|750px]]
[[File:Localisation.webp|750px]]


So the first underscored (yellow) part labeled 1 is a handle. This is technically the same as a UUID except it has no - and instead has 3 extra random digits and adds a h at the beginning. So if you want you can use auto generated UUID's like you can make with notepad ++ or vscode and then remove the - and add a h at the beginning and add 3 more random digits.
In this screenshot of a .loca file, the first underscored (yellow) part labeled 1 is a handle. This is technically the same as a UUID except it has no - and instead has 3 extra random digits and adds a h at the beginning. The second underscored (pink) part labelled 2 is where we write what we want the game to show when the handle is active. For example when it comes to character creation mods, it is what shows up in character creation. This should be the name or description of your hair, e.g. "P4 Viking Braid".
 
For example:
 
644e4b68-7bdb-4b0a-98ff-9025ce6e20e6 turn this into h644e4b687bdb4b0a98ff9025ce6e20e6a4d
 
Now the second underscored (pink) part labelled 2 is where we write what we want the game to show when the handle is active. For example when it comes to character creation mods it is what shows up in character creation.


=== Using Multitool to Generate a Handle ===
=== Using Multitool to Generate a Handle ===


Alternatively you can use [https://github.com/ShinyHobo/BG3-Modders-Multitool multitool] to generate a handle for you.
The easiest way to obtain a handle is to use [https://github.com/ShinyHobo/BG3-Modders-Multitool multitool] to generate a handle for you.


[[File:Handle multitool.webp|600px]]
[[File:Handle multitool.webp|600px]]


So once you have multitool open make sure to click the box next to Handle so it has a tick inside. Then you can click Generate for the tool to generate a new handle. Clicking on the box that has the handle inside will copy it to your clipboard so you can go to your file and paste it in.
Once you have multitool open, make sure to check the box next to Handle. Then you can click Generate for the tool to generate a new handle. Clicking on the box that has the handle inside will copy it to your clipboard so you can go to your file and paste it in.


=== Using mini tool to create/edit the .loca ===
=== [https://bg3.wiki/wiki/Modding:BG3_Mini_Tool#Using_mini_tool_to_create%2Fedit_the_.loca (Optional) Using mini tool to create/edit the .loca] ===


So currently you have to open the localisation editor via the CharacterCreationAppearanceVisuals buttons, and find the open localisation button in there. For the next update it will be on the main page due to many types of mods needing it.
== Hair _merged.lsf ==
 
This is what it looks like once open:
 
[[File:Locaeditor.webp|700px]]
 
So first we see a Folder Path setup, if you haven't already create the folders for the .loca file. Though while we are editing it the extension is .xml
 
If you want to use the tool to create your folders create a folder called Mods in the same folder as the tools exe. And put your mod folder in here. Now for the first box in the editor fill in the exact name your workspace folder has, then you can check mod folders to see if it can see them and if you don't have them click Create folders. it will create the missing folders.
 
For Name Handle you want to first click Generate Unique Handle and once it has one click the Update button. Remember always click the update button. And always check your files once done just in case the tool didn't work for whatever reason or you forgot to press update. As you don't want clashing uuids/handles.
 
For Display Name you want to write what you want the user to read when your asset is active. It's display name in game. For example in character creation it is the name your asset has when hovering over it. Once you have done that click the Update button.
 
If you don't yet have a localisatoin file use the Save as button
 
If you already have one setup first use the Locate your localisation.xml, the box above will fill in with that path. Then click Add to your mod file to add the new handle to your mod.
 
Congrats you have finished setting up/using the mini tool to edit/create your localisation file.
 
Just remember before packing to convert the xml to .loca with lslib or if using multitool to pack your mod name the file .loca.xml for multitool to auto convert for you.


== Hair _merged.lsf ==
Next, let's look at _merged.lsf.lsx. What is this? It's the file where we tell the game where to locate our mesh in our mod, as well as other information it might need.


What is this? well its the file where we tell the game where to locate our mesh in our mod and other information it might need.
Why is it called _merged.lsf.lsx? Similar to the .loca file, the multitool will automatically convert our _merged to .lsf file format, which it needs in order to be read by the game. Of course, you can name it _merged.lsx if you want to convert it manually.


I setup this file first as it makes it easier for me at least to setup the other files we need.
You can find the _merged file at: Public\Autosnapping_Template\Content\Assets\Characters\[PAK]_Hair\_merged.lsf.lsx.


Public\Autosnapping_Template\Content\Assets\Characters\[PAK]_Hair\_merged.lsf.lsx this is where you will find our file in the Template
Here's an example _merged file:


         <region id="VisualBank">
         <region id="VisualBank">
Line 164: Line 133:
                         </node>
                         </node>


Let's go through the lines we want to change. Alternatively you can copy this whole section from the hair you used as a base/edit for your hair. Most hairs can be found in the file below, however if you can't find it there please use index search of multitool
Let's go through the lines we want to change. Alternatively, you can copy this whole section from the hair you used as a base/edit for your hair. Most hairs can be found in the file below, however if you can't find it there please use index search of multitool.


location to vanilla hairs merged when unpacked with Multitool. Multitool\UnpackedData\Shared\Public\Shared\Content\Assets\Characters\[PAK]_Hair
Vanilla hairs _merged when unpacked with Multitool. Multitool\UnpackedData\Shared\Public\Shared\Content\Assets\Characters\[PAK]_Hair


If you copied that whole section from the hair you used you can probably skip a few steps here but I will still go through them. If I skip a line this means you can keep that at the vanilla value.
If you copied that whole section from the hair you used, you can probably skip a few steps here, but we will still go through them. If a line is skipped, this means you can keep that at the vanilla value and you don't need to change anything.


                     <attribute id="BoundsMax" type="fvec3" value="0.1584038 1.846514 0.167948" />
                     <attribute id="BoundsMax" type="fvec3" value="0.1584038 1.846514 0.167948" />
Line 177: Line 146:
                     <attribute id="ID" type="FixedString" value="955faf79-1707-4ea9-87f4-39a5fba49120" />
                     <attribute id="ID" type="FixedString" value="955faf79-1707-4ea9-87f4-39a5fba49120" />


You want this line to have a unique uuid. Either use multitool to generate a new uuid or an extension/plugin for your program. Such as those mentioned in the tools section of this page.
You want this line to have a unique UUID. Either use the Multitool to generate a new uuid, or use an extension/plugin for your code editing program.


                     <attribute id="Name" type="LSString" value="AT_Hair01" />
                     <attribute id="Name" type="LSString" value="AT_Hair01" />


You can give this any name you want in the value section. This is just an internal name.
You can give this any name you want in the value section. This is just an internal name. For sanity's sake, it might be best to name this after your loca.xml.


                     <attribute id="NeedsSkeletonRemap" type="bool" value="True" />
                     <attribute id="NeedsSkeletonRemap" type="bool" value="True" />


This line is what tells the game whether the asset in this case hair is autosnapping or not.
This line is what tells the game whether the hair is autosnapping or not.
* True = Autosnapping
* True = Autosnapping
* False = Non Autosnapping
* False = Non Autosnapping
Line 191: Line 160:
                     <attribute id="ScalpMaterialId" type="FixedString" value="55534266-4ce2-39d1-d2dd-04a8ec90e841" />
                     <attribute id="ScalpMaterialId" type="FixedString" value="55534266-4ce2-39d1-d2dd-04a8ec90e841" />


This line determines the scalp material your hair uses. Best to use the one your base hair used but feel free to play around to find the right one. (as of 24.11.23 some hairs in the game files don't have a scalp ID, larian is aware of this bug)
This line determines the scalp material your hair uses. It's basically what your hair would look like if it was cut extremely short. It's often best to use the one your base hair used, but feel free to play around to find the right one. (as of 24.11.23 some hairs in the game files don't have a scalp ID, larian is aware of this bug) You can use this spreadsheet to find the scalp IDs of most vanilla hairs: https://docs.google.com/spreadsheets/d/16cQUxQ7FrGVmIPy5929qae4cCQls4ZWuBX_w08zvv5M/edit


                     <attribute id="SkeletonResource" type="FixedString" value="78d8b5f0-726c-232f-a357-3d05c4b3b859" />
                     <attribute id="SkeletonResource" type="FixedString" value="78d8b5f0-726c-232f-a357-3d05c4b3b859" />


SkeletonResource is normally blank in the game files. However if making an autosnapping hair assigning the skeleton id from the skeleton your hair uses in this line will allow you to skip the conform to original gr2 in lslib. Which is normally needed if having more than two parts to your hair mesh.
SkeletonResource is normally blank in the game files. However, if a hair uses physics, it will have a SkeletonResource. You can borrow the physics from a vanilla hair using this. (However if making an autosnapping hair, assigning the skeleton id from the skeleton your hair uses in this line will allow you to skip the conform to original gr2 in lslib, which is normally needed if having more than two parts to your hair mesh.)


                     <attribute id="SourceFile" type="LSString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.GR2" />  
                     <attribute id="SourceFile" type="LSString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.GR2" />  


This is the path to your GR2 in your mods folders.
This is the path to your hair .GR2 in your mod folders.
* Make sure to use / and not \
* Make sure to use / and not \. Windows will automatically insert \ when copying the file path, so be careful.
* always start the path from your Generated folder
* Always start the path from your Generated folder.
* double check your meshes extension in the folder is .GR2 not .gr2
* Double check that your mesh's extension in the folder is .GR2 and not .gr2. It will not work if the file extension is lowercase.


                     <attribute id="Template" type="FixedString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.Dummy_Root.0" />  
                     <attribute id="Template" type="FixedString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.Dummy_Root.0" />  


Same again so feel free to copy and paste your path from before to this line.
This path is almost the same as above, so feel free to copy and paste your path from before to this line.
* Do not remove .Dummy_Root.0 from the line
* Do not remove .Dummy_Root.0 from the line.
* this line does not need .GR2 at the end
* This line does not need .GR2 at the end. You are linking to the Dummy_Root in the .GR2.


                         <node id="AnimationWaterfall">
                         <node id="AnimationWaterfall">
Line 229: Line 198:
                         </node>
                         </node>


This section is the parts that makeup our mesh in the GR2. So if you have 3 mesh parts you want 3 of these sections. But you want this part
This section defines the material for the parts that make up our mesh in the GR2. So if you have 3 mesh parts, you want 3 of these sections.


                             <attribute id="MaterialID" type="FixedString" value="89b063ff-7bf3-44a8-7e7d-41b29d0dd469" />
                             <attribute id="MaterialID" type="FixedString" value="89b063ff-7bf3-44a8-7e7d-41b29d0dd469" />


The value here matching to the MaterialID so same line from the hair you used for that part. If they are using the same materials you can keep this the same for each new section you make.
This defines the MaterialID, or the texture of your hair (straight, wavy, curly, etc). Usually you want the same material as the hair you used for that part. If the different parts are using the same materials, you can keep this the same for each new section you make. See https://bg3.wiki/wiki/Modding:Hair_Meshes for a list of all vanilla hair MaterialIDs.


However when making a new section make sure to also update "_Mesh.0" by increasing the number by 1.
When making a new section, make sure to also update "_Mesh.0" by increasing the number by 1.


For example:
For example:
Line 250: Line 219:
                         </node>
                         </node>


In blender when you assigned the export order here:
In Blender, when you assigned the export order here:


[[File:Exportorder.webp]]
[[File:Exportorder.webp]]


Where this says 1 that in our merged is that first block so .0
Where this says 1, that in our merged is that first block so .0
* .0 = Export Order 1
* .0 = Export Order 1
* .1 = Export Order 2
* .1 = Export Order 2
* .3 = Export Order 3
* .2 = Export Order 3
 
and so on.
 
If you want to set up a custom texture for your hair, see [[Creating hair merged.lsf with custom texture]]


Congrats we have finished setting up this file!
Congrats, we have finished setting up this file!


== Character Creation Folder ==
== Character Creation Folder ==


Full Release Hair Template/Public/Hair_Template/CharacterCreation is the file path for your CharacterCreation Shared/Appearance Visuals lsx files. The path in this example being the one from the template.
Full Release Hair Template/Public/Hair_Template/CharacterCreation is the file path for the template's CharacterCreation Shared/Appearance Visuals .lsx files.
 
For yours it would be your ModName/Public/YourShared/CharacterCreation


So as of full release we can finally use CharacterCreationAppearanceVisuals.lsx again even if we are using autosnapping hairs.
For yours it would be your ModName/Public/YourShared/CharacterCreation.


And we can apply the character creation slots for them in CharacterCreationSharedVisuals.lsx or CharacterCreationAppearanceVisuals.lsx
For autosnapping hairs, we can use either CharacterCreationSharedVisuals.lsx or CharacterCreationAppearanceVisuals.lsx. For non autosnapping, use only CharacterCreationAppearanceVisuals.lsx.


For non autosnapping use only CharacterCreationAppearanceVisuals.lsx.  
You can use [https://bg3.wiki/wiki/Modding:BG3_Mini_Tool Padme's mini tool] to help create the CharacterCreationAppearanceVisuals.lsx file, as well as its slots. Or, alternatively, use the file in this template to do it manually.


You can use my mini tool to help create the CharacterCreationAppearanceVisuals.lsx file, as well as its slots. Or alternatively use the file in this template to do it manually.
Why would we want to use CharacterCreationAppearanceVisuals (CCAV) vs CharacterCreationSharedVisuals (CCSV)? Well, CCSV is a lot easier to set up, file-wise. However, it is incompatible with other mods that edit the same files. Unless you plan on using Compatibility Framework, we recommend sticking with CCAV for both types of hair.


== CharacterCreationAppearanceVisuals ==
'''Important note: CharacterCreationAppearanceVisuals and CharacterCreationSharedVisuals should be .lsx format, not .lsf or .lsf.lsx format. If you use .lsf.lsx format, the multitool will convert to .lsf and then the game will not know how to read them.'''


=== CharacterCreationAppearanceVisuals ===
         <node id="CharacterCreationAppearanceVisual">
         <node id="CharacterCreationAppearanceVisual">
           <attribute id="BodyShape" type="uint8" value="0" />
           <attribute id="BodyShape" type="uint8" value="0" />
Line 287: Line 259:
         </node>
         </node>


okay let's break this down into sections:
Okay, let's break this down into sections:


           <attribute id="BodyShape" type="uint8" value="0" />
           <attribute id="BodyShape" type="uint8" value="0" />
This line defines which body shape the hair is for.
* 0 = Standard
* 0 = Standard
* 1 = Tall Muscular
* 1 = Tall Muscular
* for Half-Orcs even though they use Tall Muscular bodyshape this value needs to be 0
* For Half-Orcs, even though they use Tall Muscular bodyshape, this value needs to be 0


           <attribute id="BodyType" type="uint8" value="1" />
           <attribute id="BodyType" type="uint8" value="1" />
Line 300: Line 273:


           <attribute id="RaceUUID" type="guid" value="0eb594cb-8820-4be6-a58d-8be7a1a98fba" />
           <attribute id="RaceUUID" type="guid" value="0eb594cb-8820-4be6-a58d-8be7a1a98fba" />
The template is currently set up for the race uuid being Human. You will find the other Race UUID's at the bottom of this file on my template or alternatively you can check them [[https://bg3.wiki/wiki/Modding:Race UUID|here]]
The template is currently set up for the race uuid being Human. You will find the other Race UUID's at the bottom of this file on Padme's template or alternatively you can check them [[https://bg3.wiki/wiki/Modding:Race UUID|here]].


           <attribute id="SlotName" type="FixedString" value="Hair" />
           <attribute id="SlotName" type="FixedString" value="Hair" />
This tells the game you are adding the asset to a hair slot in character creation.
This tells the game you are adding the asset to a hair slot in character creation. This is where you would change the designation if you were making a beard for example.


           <attribute id="UUID" type="guid" value="d6663db9-f572-4f81-b9a2-fcac96149abe" />
           <attribute id="UUID" type="guid" value="d6663db9-f572-4f81-b9a2-fcac96149abe" />
This must be a unique uuid
This must be a unique uuid.


           <attribute id="VisualResource" type="guid" value="d1f51daa-5fc0-446e-92d0-318c187d2ece" />
           <attribute id="VisualResource" type="guid" value="d1f51daa-5fc0-446e-92d0-318c187d2ece" />
Match the ID line in the Hairs merged file that we created
This must match the ID line in the Hairs _merged file that we created.
 
=== Using Minitool to create your CharacterCreationAppearanceVisuals ===
 
If you use my mini tool you can auto create these slots with it. By opening up the tool and going to CharacterCreationAppearanceVisuals button.
 
Once open it will look like this:
 
[[File:Bg3 mini tool ccav.webp|700px]]
 
SO first what you want to do is if you haven't already create your folders. If you haven't this tool does allow you to create the folders which it will then create in the tools directory into a folder called Mods.
 
If you get stuck wondering anything at any time feel free to click the ? buttons for more information. But once ready with your folders you can choose the Bodyshape your asset is being made for.
* Default = the default shape the race uses. In this instance Dragonborn and Half Orcs use default not other.
* Other = the other shape they use such as the strong bodyshape
 
Bodytype whether you want the asset for the Masc or Feminine body type.
 
Next up is the Handle. click Generate Unique Handle or copy in the handle you made in your localisation file. Alternatively if you haven't already setup your localisation file you can use the open Localisation editor. Once ready click the button that says Update.
 
Always press update once you are finished with a section.
 
RaceUUID - this is the id that defines the race that asset is used for. Click on the drop down menu to get options like below:
 
[[File:Ccavracedropdown.webp]]
 
This list by default is only the vanilla races. The last option is the stand in example for adding custom race uuids to the list so you can use it from this part of the tool. If you add any by following the nect header section it will update when you click the list again. Sometimes may need a double click.
 
Choose the race you want to use from the dropdown and then click update.
 
Our next drop down menu is for the Slotname:
 
[[File:Ccavslotnamedropdown.webp]]
 
You might need to click twice for the whole list to show. For ours we want to choose Hair. Then click update. But the rest of that list is what else can get added via CCAV. Feel free to add custom ones to the list as well if you have managed to add any custom ones, or any I may have forgotten from the list.
 
Next up is Unique UUID, for this we first want to click Generate Unique UUID and then click update.
 
VisualResource if you haven't already you can generate an id for use in your merged file here. but if you have already setup your merged file copy over the uuid we used for the ID line here and then click update.
 
We have now setup the file, so next if we don't have an already existing CharacterCreationAppearanceVisuals file we use Save as button. Navigate to the ModName/Public/YourShared/CharacterCreation folder and save your file.
 
If you already have a file use the locate your CharacterCreationAppearanceVisuals.lsx button and navitagte to your file. Once setup the bottom box will change to your path. Now you can click Add to your mod file if you want to add new slots to an already existing file.
 
Congrats you have made your CharacterCreationAppearanceVisuals with the mini tool.
 
=== Adding modded races to the Minitool CCAV option ===
 
If wanting to use the one slot creation of the mini tool you can add custom races to the Races.txt found in the LSX Files folder that comes with the tool. It uses the files in this folder for the tool. So you might want to backup this folder before editing just in case of any mistakes.
 
When you open the Races.txt you will be met with this:
 
RaceUUID so you can quickly replace the above with your desired race
Drow: 4f5d1434-5175-4fa9-b7dc-ab24fba37929
Dwarf: 0ab2874d-cfdc-405e-8a97-d37bfbb23c52
Elf: 6c038dcb-7eb5-431d-84f8-cecfaf1c0c5a
Githyanki: bdf9b779-002c-4077-b377-8ea7c1faa795
Gnome: f1b3f884-4029-4f0f-b158-1f9fe0ae5a0d
HalfElf/Drow: 45f4ac10-3c89-4fb2-b37d-f973bb9110c0
Halfling: 78cd3bcc-1c43-4a2a-aa80-c34322c16a04
Human: 0eb594cb-8820-4be6-a58d-8be7a1a98fba
Tiefling: b6dccbed-30f3-424b-a181-c4540cf38197
Dragonborn: 9c61a74a-20df-4119-89c5-d996956b6c66
Half-Orc: 5c39a726-71c8-4748-ba8d-f768b3c11a91
Modded Races
Race Name: 00000000-0000-0000-0000-000000000000
To add a new race to the list add them like above. Name of the race and then colon and the RaceUUID
 
The top lines you might recognise as the uuids from the bottom of the CharacterCreationAppearanceVisuals in my template. This is because the way I set it up is it reads first the name and anything that follows after the : should be the race uuid.
 
So to add custom races you can add them under Modded Races, you can add them to the top list as well as I just separated them for ease of use.
 
So you would follow the same format and type the name you want to show up in the dropdown menu and followed straight by a : and then space and then the UUID for your/that custom race.
 
=== Minitool 32 CCAV Entries all at Once option ===
 
So if making a hair for all races and you would prefer using the CCAV file you can use the 32 CCAV Entries all at Once option to add them all at once to the 32 entries needed to add them to vanilla races that use hairs. So all minus Dragonborn.
 
When that is open it looks like this:
 
[[File:Ccav32entries.webp|500px]]
 
SO first what you want to do is click Generate Unique Handle or copy in the handle you made in your localisation file and once in click the button that says Update.
 
Always press update once you are finished with a section.
 
You will notice this is missing a few things from the CharacterCreationAppearanceVisuals part of the tool. That is because it is already setup for all the races. So we don't need that dropdown menu here.
 
In the Name section add the name for your asset, this will add a comment to your file so you can better find it when needing to. Press update when your name for your asset is filled in.
 
Slotname works just like the other file.
 
[[File:Ccavslotnamedropdown.webp]]
 
You might need to click twice for the whole list to show. For ours we want to choose Hair. Then click update. But the rest of that list is what else can get added via CCAV. Feel free to add custom ones to the list as well if you have managed to add any custom ones, or any I may have forgotten from the list.
 
VisualResource in your assets merged copy over the uuid we used for the ID line here and then click update.
 
Next click Generate Unique UUIDs this will change every instance of the UniqueUUID line to a unique uuid for each slot. No repeats.
 
We have now setup the file, so next if we don't have an already existing CharacterCreationAppearanceVisuals file we use Save as button. Navigate to the ModName/Public/YourShared/CharacterCreation folder and save your file.
 
If you already have a file use the locate your CharacterCreationAppearanceVisuals.lsx button and navitagte to your file. Once setup the bottom box will change to your path. Now you can click Add to your mod file if you want to add new slots to an already existing file.
 
Congrats you have made your CharacterCreationAppearanceVisuals with the mini tool for all 32 vanilla slots.
 
=== Adding modded races to the Minitool 32 CCAV Entries all at Once option ===
 
If you want to add custom/modded races to the 32 slot option, it is possible all you need to do is go to the LSX Files folder included with the tool (make sure to make a backup folder just in case) and edit CharacterCreationAppearanceVisuals_ForAll.lsx
 
In here you will find comments such as <!-- Masc_Strong "" --> and then race specific comments. I do this for organistation of the file. it does nothing in the game.
 
Copy any of the entries so for example:
 
        <!-- Tiefling -->
        <node id="CharacterCreationAppearanceVisual">
          <attribute id="BodyShape" type="uint8" value="0" />
          <attribute id="BodyType" type="uint8" value="0" />
          <attribute id="DisplayName" type="TranslatedString" handle="h70718c5dg76b9g402cgbe76ge5b2d9abaa1f" version="1" />
          <attribute id="RaceUUID" type="guid" value="b6dccbed-30f3-424b-a181-c4540cf38197" />
          <attribute id="SlotName" type="FixedString" value="Hair" />
          <attribute id="UUID" type="guid" value="259cf9c6-c6f1-4265-b4b8-dd45f2a3772f" />
          <attribute id="VisualResource" type="guid" value="00000000-0000-0000-0000-000000000000" />
        </node>
 
Once copied we want to change the RaceUUID line to the UUID of the custom/modded race.
 
          <attribute id="BodyType" type="uint8" value="1" />
 
Copy again the whole piece and then for the fem form if the race has one as this is currently set up for masc, change the Bodytype from 0 to 1 for fem.
 
          <attribute id="BodyShape" type="uint8" value="1" />
 
copy again if the race has a strong bodyshape and change bodyshape value from 0 to 1. If the default shape is the strong shape then leave it at 0.
 
And that is all that needs changing. Nothing in my code needs changing so you don't need to worry abuot that, copy these sections as much as you need. And then use the tool as normal and it will edit the 32 vanilla entries plus all the modded entries you added.
 
== CharacterCreationSharedVisuals ==


==== [https://bg3.wiki/wiki/Modding:BG3_Mini_Tool#Using_Minitool_to_create_your_CharacterCreationAppearanceVisuals (Optional) Using Minitool to create your CharacterCreationAppearanceVisuals] ====
=== CharacterCreationSharedVisuals ===
Remember that you need your hair to be autosnapping to work properly in this section.
Remember that you need your hair to be autosnapping to work properly in this section.


Line 521: Line 357:
This one from the our sharedvisuals file. When you've finished adding the entries you want to add the races.lsx is ready to go.
This one from the our sharedvisuals file. When you've finished adding the entries you want to add the races.lsx is ready to go.


=== Compatibility Framework ===
If you wish to use [[Modding:Compatibility Framework]] see that guide on how to use it as an alternative to Races.lsx. However we suggest you use both in order to not rule out your Mac users from using your mods.
 
First big thank you to NellsRelo and perseidipity
 
To use the [https://www.nexusmods.com/baldursgate3/mods/1933 Compatibility Framework] you need to install it alongside your mod. CF however needs to be at the bottom of the load order.
 
==== Json ====
 
So this is considered the easier format to setup for using the Compatibility Framework in order to make your edits to the Races.lsx compatible with other mods. Partially due to reacting easier to multiple sections for defining each race and having multiple values.
 
You do not need to send anything to be added to the Compatibility Framework mod, just remember to have it at the bottom of your load order and if making a public mod to remind people CF goes to the bottom.
 
So first you want to make some new folders:
 
Modname/Mods/YourShared/ScriptExtender
 
In the Script extender folder you want to create a CompatibilityFrameworkConfig.json you can do this by creating a txt file and renaming it and its extension to CompatibilityFrameworkConfig.json
 
Using part of the code example we are given [https://github.com/BG3-Community-Library-Team/BG3-Compatibility-Framework/wiki/_Races-API here:] but edited.
 
{
  "FileVersion": 1,
  "Races": [
    {
      "UUID": "Race's UUID",
      "Children": [
        {
          "Type": "Visuals",
          "modGuid": "UUID of required mod (Optional)",
          "Values": ["bdf9b779-002c-4077-b377-8ea7c1faa795", "3e4d5829-7bfd-446a-9e7d-ac8d0948c1e4"],
          "Action": "Insert"
        }
      ]
    }
  ]
}
 
      "UUID": "Race's UUID",
In this line we want to change it to the race we are adding to in the Races.lsx file. The most commonly used one is Humanoid for hair/beard mods. Which is 899d275e-9893-490a-9cd5-be856794929f. This will apply it to all races including modded races if they use it as the parent. For others see [[Modding:Race_UUID|here in the Races.lsx section]] for example if you want it only added to Humans and Elves your code would look like this.
 
{
  "FileVersion": 1,
  "Races": [
    {
      "UUID": "0eb594cb-8820-4be6-a58d-8be7a1a98fba", This being the Human races uuid
      "Children": [
        {
          "Type": "Visuals",
          "modGuid": "UUID of required mod (Optional)",
          "Values": ["bdf9b779-002c-4077-b377-8ea7c1faa795"],
          "Action": "Insert"
        }
      ]
    },
    {
      "UUID": "6c038dcb-7eb5-431d-84f8-cecfaf1c0c5a", This being the Elves races uuid
      "Children": [
        {
          "Type": "Visuals",
          "modGuid": "UUID of required mod (Optional)",
          "Values": ["bdf9b779-002c-4077-b377-8ea7c1faa795"],
          "Action": "Insert"
        }
      ]
    }
  ]
}
 
Now to continue explaining the other lines:
 
          "Type": "Visuals",
Visuals pertains to assets such as Hair, Beards, Tails, Horns and such. Pretty much the assets we add to SharedVisuals.
 
          "modGuid": "UUID of required mod (Optional)",
So as this line says it is optional, but personally I add it in. The UUID we add in the meta.
 
          "Values": ["bdf9b779-002c-4077-b377-8ea7c1faa795"],
This uuid has to match the one you gave for the UUID line in your CharacterCreationSharedVisuals. If you have multiple assets add a , after the final " and then make a new " " with your uuid in between for example from the first example given:
 
          "Values": ["bdf9b779-002c-4077-b377-8ea7c1faa795", "3e4d5829-7bfd-446a-9e7d-ac8d0948c1e4"],
 
Now we come to the last line:
          "Action": "Insert"
For the sake of SharedVisual mods we likely wouldn't change this line, however if you want to remove something instead of add something to a section in Races.lsx change Insert to Remove
 
Congrats you setup your mod for using the Compatibility Framework via json. Just remember always load Compatibility Framework at the bottom of your load order.
 
==== Lua ====
 
This is a possible use of the Compatibility Framework though it is advised to use the json method instead. Both do not require adding anything directly to the framework, they will work alongside it out of the box.
 
So first you want to make some new folders:


Modname/Mods/YourShared/ScriptExtender/Lua
== When to use three or more meshes for autosnapping hairs ==


In the Script extender folder you want to create a Config.json you can do this by creating a text file and just renaming it and its extension Config.json. In the json you want:
Do you notice your autosnapping hair looks good on default bodies, but doesn't work quite right for the shorter or taller bodyshapes?


{
This is where you would make several autosnapping hairs. Each variation needs its own VisualBank entry in your merged.lsf file.
    "RequiredVersion": 9,
    "ModTable": "YOUR_MOD_NAME_HERE",
    "FeatureFlags": ["Lua"]
}


Where it says YOUR_MOD_NAME_HERE, write the name of your mod.
So if your hair has issues on different bodyshapes, you can do what Larian did and make several.


Now in the Lua folder do the same again make a new txt file but this time rename it BootstrapClient.lua
*One made around a dwarven head.
** this would be for Gnomes, Halflings and Dwarves
*One made around the default Elf height.
** this would be for Elves, Drow, Humans, Half Elves/Drow, Githyanki and Tieflings
*One for Taller bodyshapes.
** this would be for Strong Elves, Drow, Humans, Half Elves/Drow, Tieflings and Half Orcs


if Ext.Mod.IsModLoaded("67fbbd53-7c7d-4cfa-9409-6d737b4d92a9") then
If you still get issues on Tiefling heads then you might want to use Tiefling masc heads as a base for your default and tall height. You can make as many autosnapping variants as you need, but usually three will be enough.  
    local raceChildData = {
      ModName = {
        modGuid = "the UUID you gave in your meta.lsx",
        raceGuid = "899d275e-9893-490a-9cd5-be856794929f",
        children = {
        entry1 = {
            Type = "Visuals",
            Value = "3ae3e4fc-e792-473a-8853-43520dfc1147",
          },
      }
    }
}
    local function OnStatsLoaded()
      Mods.SubclassCompatibilityFramework.Api.InsertRaceChildData(raceChildData)
    end
 
    Ext.Events.StatsLoaded:Subscribe(OnStatsLoaded)
  end


        raceGuid = "899d275e-9893-490a-9cd5-be856794929f",
Once you have these set up and have made the visualbank entries, you can then make the additional edits to your CharacterCreationAppearanceVisuals or CharacterCreationSharedVisuals.


this you want to be the race you're adding your hair too. The one currently in there is humanoid. This will apply it to all races including modded races if they use it as the parent. For others see [[Modding:Race_UUID|here]]
=== CharacterCreationAppearanceVisuals ===


            Type = "Visuals",
If using CharacterCreationAppearanceVisuals, change the VisualResourceID to the new ones in the correct slots you made previously for testing the mod, as you should have all the vanilla race and bodyshapes available from your first creation of the file.


This line is what you're adding to. Visuals is either Hair or Beards or other assets defined in the SharedVisuals file.
=== CharacterCreationSharedVisuals ===


            Value = "3ae3e4fc-e792-473a-8853-43520dfc1147",
If using CharacterCreationSharedVisuals, you want to make new entries with these options. And in races.lsx instead of using Humanoid/Fey/Fiend/Celestial you want to use the race sections of the races the hairs will work on.
* For the Dwarven height, add to Gnomes, Halflings and Dwarves
* For the default height, add to Elves, Drow, Humans, Half Elves/Drow, Githyanki and Tieflings
* For the taller height, add to Strong Elves, Drow, Humans, Half Elves/Drow, Tieflings and Half Orcs


This uuid has to match the one you gave for the UUID line in your CharacterCreationSharedVisuals
== Troubleshooting ==
Here are some common hair issues and how to troubleshoot them.


If wanting to create more than one hair copy and paste this section:
'''My hair doesn’t show up at all, there’s not even a slot in Character Creation!'''


        entry1 = {
Check your CharacterCreationAppearanceVisuals or CharacterCreationSharedVisuals, as that is where the CC slots are defined.
            Type = "Visuals",
            Value = "3ae3e4fc-e792-473a-8853-43520dfc1147",
          },


Changing entry1 to entry2 and so on. You can also use entrya, entryb as well.
'''My hair shows up as a slot, but when I select it, the hair is invisible!'''


      Mods.SubclassCompatibilityFramework.Api.InsertRaceChildData(raceChildData)
Check your hair _merged file, especially the file paths to your SourceFile and Template. Any inconsistency between this and the actual folders will result in the game not finding your mesh, and thus not loading it. Also note that folders must be separated by /, not \. E.g. Mod/Generated/Mod/Hair.GR2


Not fully related to this tutorial but just in case you come up with a use, swap out InsertRaceChildData for RemoveRaceChildData if you want to remove lines from the Races.lsx instead of adding.
{{Modding navbox}}


Congrats you setup your mod for using the Compatibility Framework via lua. Just remember always load Compatibility Framework at the bottom of your load order.
[[Category:Hair modding]]

Latest revision as of 23:15, 29 July 2024

Welcome to the file setup portion of making a hair mod. For an overview of all the steps, see Modding:Creating Hair Mods.

Tools You'll Need[edit | edit source]

To generate a UUID in VSCode, just highlight a section of code, right click, and select Generate UUID here. It will replace the selected code with a new UUID.

For the UUID generation in Notepad++, once ToolBucket is installed, you want to press Alt + Shift + G. It will bring up a window as shown below. Keep Include hyphens ticked, and you can also click Don't ask again if you won't use any of the other options. Then click Generate.

Toolbucketuuid.webp


If wanting to add more than one hair to your mod, you can use Padme's mini tool linked above for adding new slots to CharacterCreationAppearanceVisuals. You can also use it to edit your .loca file if you desire.

You can choose for your hairs to be autosnapping or non autosnapping.

What are autosnapping and non autosnapping hairs?[edit | edit source]

Autosnapping hairs are basically when you have an asset you want to work for more than one race/bodyshape/bodytype, but don't want to make a mesh for every single variation. So when setup to be autosnapping, you can apply one mesh to be used by multiple races/bodyshapes/bodytypes. And the game "autosnaps" them into place using a series of "sockets" that the hair is weighted to.

Sometimes you may still need three autosnapping meshes, one for the shorter races, one for the default bodytype and one for the strong bodytype. However we will go through when this is needed further into the tutorial.

Non autosnapping is when the game doesn't snap the hair into place at all. So, you have to create your hair mesh for each race/bodyshape/bodytype that you want it to be usable for. Obviously, this takes more work, but it can often give better/less crunchy results than autosnapping, and it is much easier to manually weight a non-autosnapping hair than an autosnapping hair. For instance, for personal use hairs, you might decide you only want it for one character. Then non autosnapping might be the way to go.
Autosnapping hairs are basically when you have an asset you want to work for more than one race/bodyshape/bodytype, but don't want to make a mesh for every single variation. So when setup to be autosnapping, you can apply one mesh to be used by multiple races/bodyshapes/bodytypes. And the game "autosnaps" them into place using a series of "sockets" that the hair is weighted to.

Sometimes you may still need three autosnapping meshes, one for the shorter races, one for the default bodytype and one for the strong bodytype. However we will go through when this is needed further into the tutorial.

Non autosnapping is when the game doesn't snap the hair into place at all. So, you have to create your hair mesh for each race/bodyshape/bodytype that you want it to be usable for. Obviously, this takes more work, but it can often give better/less crunchy results than autosnapping, and it is much easier to manually weight a non-autosnapping hair than an autosnapping hair. For instance, for personal use hairs, you might decide you only want it for one character. Then non autosnapping might be the way to go.

Following the Template[edit | edit source]

Following Padme's template (or using it as a guide to copy parts from the game files), follow along with this tutorial.

If you are only adding an existing hair from the game to CC without wanting to do any edits, you can remove the Generated folder from your copy of the template and instead just link to the game's existing hair in the _merged.

You may have downloaded the template, and now feel overwhelmed by all the files and folders, but it's really not too complicated. There are only four* files that we need to edit: loca.xml, meta.lsx, _merged.lsf.lsx and CharacterCreationAppearanceVisuals.lsx. You'll also need to place your .GR2 in the Generated folder, but more on that later.

  • If using the CharacterCreationSharedVisuals method, technically five files including Races.lsx. More on that later!

Alternatively you can follow this video by Bububull for the file setup if you want to use the CharacterCreationAppearanceVisuals method.

Mods/meta.lsx[edit | edit source]

Remember to create your meta.lsx for your mod as well, as it is required for almost all pak mods. If using multitool to pack, you can create a Mods folder in your workspace folder and let multitool create the meta.lsx for you. Otherwise, follow this tutorial on how to create your meta.lsx: Creating your Meta.lsx

Localization/English/custom_name_here.loca.xml[edit | edit source]

After you've sorted your meta.lsx, let's start with the loca.xml. This is the file that tells your game what text to display for your hair--aka the name of the hair in Character Creation. If this file is broken or doesn't exist, your hair will show up as "Not Found".

Why is it named .loca.xml? This is because if you package the Main folder (also known as your workspace folder) with multitool, it will auto convert the .loca.xml to .loca. This way, you don't have to manually do the conversions yourself. However, if you prefer to do manual conversions, change the extension to .xml only.

You can find the _merged file at: Localization/English/custom_name_here.loca.xml.

Change custom_name_here to a custom name. It's best to add a personalized prefix beforehand so there is no chance of your mod name clashing with another mod. For example, Padme4000 uses her username, but shortened to P4. So for Padme's viking braid hair, her .loca.xml would be called p4_viking_braid.loca.xml

This way, if someone else happens to make a viking braid, the chances of them also naming their hair "p4_viking_braid" are extremely low, and there's no danger of one of the mods overriding the other.

Localisation.webp

In this screenshot of a .loca file, the first underscored (yellow) part labeled 1 is a handle. This is technically the same as a UUID except it has no - and instead has 3 extra random digits and adds a h at the beginning. The second underscored (pink) part labelled 2 is where we write what we want the game to show when the handle is active. For example when it comes to character creation mods, it is what shows up in character creation. This should be the name or description of your hair, e.g. "P4 Viking Braid".

Using Multitool to Generate a Handle[edit | edit source]

The easiest way to obtain a handle is to use multitool to generate a handle for you.

Handle multitool.webp

Once you have multitool open, make sure to check the box next to Handle. Then you can click Generate for the tool to generate a new handle. Clicking on the box that has the handle inside will copy it to your clipboard so you can go to your file and paste it in.

(Optional) Using mini tool to create/edit the .loca[edit | edit source]

Hair _merged.lsf[edit | edit source]

Next, let's look at _merged.lsf.lsx. What is this? It's the file where we tell the game where to locate our mesh in our mod, as well as other information it might need.

Why is it called _merged.lsf.lsx? Similar to the .loca file, the multitool will automatically convert our _merged to .lsf file format, which it needs in order to be read by the game. Of course, you can name it _merged.lsx if you want to convert it manually.

You can find the _merged file at: Public\Autosnapping_Template\Content\Assets\Characters\[PAK]_Hair\_merged.lsf.lsx.

Here's an example _merged file:

       <region id="VisualBank">
       <node id="VisualBank">
           <children>
               <node id="Resource">
                   <attribute id="AttachBone" type="FixedString" value="" />
                   <attribute id="AttachmentSkeletonResource" type="FixedString" value="" />
                   <attribute id="BlueprintInstanceResourceID" type="FixedString" value="" />
                   <attribute id="BoundsMax" type="fvec3" value="0.1584038 1.846514 0.167948" />
                   <attribute id="BoundsMin" type="fvec3" value="-0.1540881 1.345605 -0.09591679" /> 
                   <attribute id="ClothColliderResourceID" type="FixedString" value="" />
                   <attribute id="HairPresetResourceId" type="FixedString" value="" />
                   <attribute id="HairType" type="uint8" value="0" />
                   <attribute id="ID" type="FixedString" value="955faf79-1707-4ea9-87f4-39a5fba49120" />
                   <attribute id="MaterialType" type="uint8" value="0" />
                   <attribute id="Name" type="LSString" value="AT_Hair01" />
                   <attribute id="NeedsSkeletonRemap" type="bool" value="True" />
                   <attribute id="RemapperSlotId" type="FixedString" value="" />
                   <attribute id="ScalpMaterialId" type="FixedString" value="55534266-4ce2-39d1-d2dd-04a8ec90e841" />
                   <attribute id="SkeletonResource" type="FixedString" value="78d8b5f0-726c-232f-a357-3d05c4b3b859" />
                   <attribute id="SkeletonSlot" type="FixedString" value="" />
                   <attribute id="Slot" type="FixedString" value="Hair" />
                   <attribute id="SoftbodyResourceID" type="FixedString" value="" />
                   <attribute id="SourceFile" type="LSString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.GR2" /> 
                   <attribute id="SupportsVertexColorMask" type="bool" value="False" />
                   <attribute id="Template" type="FixedString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.Dummy_Root.0" /> 
                   <attribute id="_OriginalFileVersion_" type="int64" value="144537400540921856" />
                   <children>
                       <node id="AnimationWaterfall">
                           <attribute id="Object" type="FixedString" value="" />
                       </node>
                       <node id="Base">
                           <children>
                               <node id="Tags">
                                   <attribute id="Object" type="FixedString" value="Hair" />
                               </node>
                           </children>
                       </node>
                       <node id="ClothProxyMapping" />
                       <node id="Objects">
                           <attribute id="LOD" type="uint8" value="0" />
                           <attribute id="MaterialID" type="FixedString" value="89b063ff-7bf3-44a8-7e7d-41b29d0dd469" />
                           <attribute id="ObjectID" type="FixedString" value="AT_Test.AT_Test_Mesh.0" />
                       </node>

Let's go through the lines we want to change. Alternatively, you can copy this whole section from the hair you used as a base/edit for your hair. Most hairs can be found in the file below, however if you can't find it there please use index search of multitool.

Vanilla hairs _merged when unpacked with Multitool. Multitool\UnpackedData\Shared\Public\Shared\Content\Assets\Characters\[PAK]_Hair

If you copied that whole section from the hair you used, you can probably skip a few steps here, but we will still go through them. If a line is skipped, this means you can keep that at the vanilla value and you don't need to change anything.

                   <attribute id="BoundsMax" type="fvec3" value="0.1584038 1.846514 0.167948" />
                   <attribute id="BoundsMin" type="fvec3" value="-0.1540881 1.345605 -0.09591679" /> 

These lines you want to match the hair you used as a base, especially if you haven't changed the base race it uses.

                   <attribute id="ID" type="FixedString" value="955faf79-1707-4ea9-87f4-39a5fba49120" />

You want this line to have a unique UUID. Either use the Multitool to generate a new uuid, or use an extension/plugin for your code editing program.

                   <attribute id="Name" type="LSString" value="AT_Hair01" />

You can give this any name you want in the value section. This is just an internal name. For sanity's sake, it might be best to name this after your loca.xml.

                   <attribute id="NeedsSkeletonRemap" type="bool" value="True" />

This line is what tells the game whether the hair is autosnapping or not.

  • True = Autosnapping
  • False = Non Autosnapping
                   <attribute id="ScalpMaterialId" type="FixedString" value="55534266-4ce2-39d1-d2dd-04a8ec90e841" />

This line determines the scalp material your hair uses. It's basically what your hair would look like if it was cut extremely short. It's often best to use the one your base hair used, but feel free to play around to find the right one. (as of 24.11.23 some hairs in the game files don't have a scalp ID, larian is aware of this bug) You can use this spreadsheet to find the scalp IDs of most vanilla hairs: https://docs.google.com/spreadsheets/d/16cQUxQ7FrGVmIPy5929qae4cCQls4ZWuBX_w08zvv5M/edit

                   <attribute id="SkeletonResource" type="FixedString" value="78d8b5f0-726c-232f-a357-3d05c4b3b859" />

SkeletonResource is normally blank in the game files. However, if a hair uses physics, it will have a SkeletonResource. You can borrow the physics from a vanilla hair using this. (However if making an autosnapping hair, assigning the skeleton id from the skeleton your hair uses in this line will allow you to skip the conform to original gr2 in lslib, which is normally needed if having more than two parts to your hair mesh.)

                   <attribute id="SourceFile" type="LSString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.GR2" /> 

This is the path to your hair .GR2 in your mod folders.

  • Make sure to use / and not \. Windows will automatically insert \ when copying the file path, so be careful.
  • Always start the path from your Generated folder.
  • Double check that your mesh's extension in the folder is .GR2 and not .gr2. It will not work if the file extension is lowercase.
                   <attribute id="Template" type="FixedString" value="Generated/Public/Autosnapping_Template/[PAK]_Autosnapping_Template/AT_Test.Dummy_Root.0" /> 

This path is almost the same as above, so feel free to copy and paste your path from before to this line.

  • Do not remove .Dummy_Root.0 from the line.
  • This line does not need .GR2 at the end. You are linking to the Dummy_Root in the .GR2.
                       <node id="AnimationWaterfall">
                           <attribute id="Object" type="FixedString" value="" />
                       </node>
                       <node id="Base">
                           <children>
                               <node id="Tags">
                                   <attribute id="Object" type="FixedString" value="Hair" />
                               </node>
                           </children>
                       </node>

This section is another section where you want to be copying from one of the hairs you used to make the hair.

                       <node id="Objects">
                           <attribute id="LOD" type="uint8" value="0" />
                           <attribute id="MaterialID" type="FixedString" value="89b063ff-7bf3-44a8-7e7d-41b29d0dd469" />
                           <attribute id="ObjectID" type="FixedString" value="AT_Test.AT_Test_Mesh.0" />
                       </node>

This section defines the material for the parts that make up our mesh in the GR2. So if you have 3 mesh parts, you want 3 of these sections.

                           <attribute id="MaterialID" type="FixedString" value="89b063ff-7bf3-44a8-7e7d-41b29d0dd469" />

This defines the MaterialID, or the texture of your hair (straight, wavy, curly, etc). Usually you want the same material as the hair you used for that part. If the different parts are using the same materials, you can keep this the same for each new section you make. See https://bg3.wiki/wiki/Modding:Hair_Meshes for a list of all vanilla hair MaterialIDs.

When making a new section, make sure to also update "_Mesh.0" by increasing the number by 1.

For example:

                       <node id="Objects">
                           <attribute id="LOD" type="uint8" value="0" />
                           <attribute id="MaterialID" type="FixedString" value="89b063ff-7bf3-44a8-7e7d-41b29d0dd469" />
                           <attribute id="ObjectID" type="FixedString" value="AT_Test.AT_Test_Mesh.0" />
                       </node>
                       <node id="Objects">
                           <attribute id="LOD" type="uint8" value="0" />
                           <attribute id="MaterialID" type="FixedString" value="89b063ff-7bf3-44a8-7e7d-41b29d0dd469" />
                           <attribute id="ObjectID" type="FixedString" value="AT_Test.AT_Test_Mesh.1" />
                       </node>

In Blender, when you assigned the export order here:

Exportorder.webp

Where this says 1, that in our merged is that first block so .0

  • .0 = Export Order 1
  • .1 = Export Order 2
  • .2 = Export Order 3

and so on.

If you want to set up a custom texture for your hair, see Creating hair merged.lsf with custom texture

Congrats, we have finished setting up this file!

Character Creation Folder[edit | edit source]

Full Release Hair Template/Public/Hair_Template/CharacterCreation is the file path for the template's CharacterCreation Shared/Appearance Visuals .lsx files.

For yours it would be your ModName/Public/YourShared/CharacterCreation.

For autosnapping hairs, we can use either CharacterCreationSharedVisuals.lsx or CharacterCreationAppearanceVisuals.lsx. For non autosnapping, use only CharacterCreationAppearanceVisuals.lsx.

You can use Padme's mini tool to help create the CharacterCreationAppearanceVisuals.lsx file, as well as its slots. Or, alternatively, use the file in this template to do it manually.

Why would we want to use CharacterCreationAppearanceVisuals (CCAV) vs CharacterCreationSharedVisuals (CCSV)? Well, CCSV is a lot easier to set up, file-wise. However, it is incompatible with other mods that edit the same files. Unless you plan on using Compatibility Framework, we recommend sticking with CCAV for both types of hair.

Important note: CharacterCreationAppearanceVisuals and CharacterCreationSharedVisuals should be .lsx format, not .lsf or .lsf.lsx format. If you use .lsf.lsx format, the multitool will convert to .lsf and then the game will not know how to read them.

CharacterCreationAppearanceVisuals[edit | edit source]

       <node id="CharacterCreationAppearanceVisual">
         <attribute id="BodyShape" type="uint8" value="0" />
         <attribute id="BodyType" type="uint8" value="1" />
         <attribute id="DisplayName" type="TranslatedString" handle="haf43c4eb5660459ba047936caa9977a9" version="1" />
         <attribute id="RaceUUID" type="guid" value="0eb594cb-8820-4be6-a58d-8be7a1a98fba" />
         <attribute id="SlotName" type="FixedString" value="Hair" />
         <attribute id="UUID" type="guid" value="d6663db9-f572-4f81-b9a2-fcac96149abe" />
         <attribute id="VisualResource" type="guid" value="d1f51daa-5fc0-446e-92d0-318c187d2ece" />
       </node>

Okay, let's break this down into sections:

         <attribute id="BodyShape" type="uint8" value="0" />

This line defines which body shape the hair is for.

  • 0 = Standard
  • 1 = Tall Muscular
  • For Half-Orcs, even though they use Tall Muscular bodyshape, this value needs to be 0
         <attribute id="BodyType" type="uint8" value="1" />

This line defines whether it is for the masc or fem body assets.

  • 0 = Masc
  • 1 = Fem
         <attribute id="RaceUUID" type="guid" value="0eb594cb-8820-4be6-a58d-8be7a1a98fba" />

The template is currently set up for the race uuid being Human. You will find the other Race UUID's at the bottom of this file on Padme's template or alternatively you can check them [UUID|here].

         <attribute id="SlotName" type="FixedString" value="Hair" />

This tells the game you are adding the asset to a hair slot in character creation. This is where you would change the designation if you were making a beard for example.

         <attribute id="UUID" type="guid" value="d6663db9-f572-4f81-b9a2-fcac96149abe" />

This must be a unique uuid.

         <attribute id="VisualResource" type="guid" value="d1f51daa-5fc0-446e-92d0-318c187d2ece" />

This must match the ID line in the Hairs _merged file that we created.

(Optional) Using Minitool to create your CharacterCreationAppearanceVisuals[edit | edit source]

CharacterCreationSharedVisuals[edit | edit source]

Remember that you need your hair to be autosnapping to work properly in this section.

               <node id="CharacterCreationSharedVisual">
                   <attribute id="DisplayName" type="TranslatedString" handle="h163f3e2e9f634634a5e41553265771e4" version="1" />
                   <attribute id="SlotName" type="FixedString" value="Hair"/>
                   <attribute id="UUID" type="guid" value="3ae3e4fc-e792-473a-8853-43520dfc1147"/>
                   <attribute id="VisualResource" type="guid" value="fa926de0-feae-4218-806e-3d037b9d83d3"/>
               </node>

So what is the above? well it's the section we need for each hair asset we make. So let's break down each line.

                   <attribute id="DisplayName" type="TranslatedString" handle="h163f3e2e9f634634a5e41553265771e4" version="1" />

Remember in the localisation part of the tutorial? When we created a handle and entered a name for it? Well this is the line where we want to copy that handle to.

                   <attribute id="SlotName" type="FixedString" value="Hair"/>

If making a Beard you can change this value from Hair to Beard otherwise keep it the same.

                   <attribute id="UUID" type="guid" value="3ae3e4fc-e792-473a-8853-43520dfc1147"/>

You want this uuid to be unique. We will be copying it to our Races.lsx soon

                   <attribute id="VisualResource" type="guid" value="fa926de0-feae-4218-806e-3d037b9d83d3"/>

So the new UUID we made for our ID line in our merged? This is where you want to copy that uuid to as well.

Congrats this file is now ready. Copy and paste the section if you want to make more than one hair and follow the same principles.

Races.lsx[edit | edit source]

So this file is what we need to edit alongside CharacterCreationSharedVisuals in order for our hair to appear as a slot in character creation. When made via this your hair will appear at the bottom of the hairs in character creation.

However this file is sadly incompatible with other mods editing the same sections we need to edit.

This can be resolved either by opting into my Patches for Races.lsx mod or by using the Compatibility Framework instead of the Races.lsx file.

This files sections can get quite big, and while incompatible with other mods can still be in your mod for users only using your mod that might not be using Script Extender or Compatibility Framework. Or when Script extender needs updating after a new patch releases. So I will still go through how to setup this file:

I won't copy the whole section as that would make this part the longest part of the tutorial

               <node id="Race">
                   <attribute id="Description" type="TranslatedString" handle="he3427d53gdd4ag4901g8683g21844f537c8f" version="5"/>
                   <attribute id="DisplayName" type="TranslatedString" handle="h2e43ea54ga31bg467bg8364g327659ea1986" version="1"/>
                   <attribute id="Name" type="FixedString" value="Humanoid"/>
                   <attribute id="UUID" type="guid" value="899d275e-9893-490a-9cd5-be856794929f"/>
                   <children>

So usually the section will start with something like this. This being the commonly used section for Humanoid. Humanoid will add whatever you add to all races including modded races if they are using the humanoid id as their parent.

If copying from the vanilla races.lsx please remember to copy all the lines, do not remove any unless you mean to remove that particular line from the race. Add your entry to the bottom of those nodes.

In my template you can scroll till you reach:

                       Modded Entries Start
                       <node id="Visuals">
                           <attribute id="Object" type="guid" value="449e617f-8356-46e5-b740-9e4b18200441"/>
                       </node>

Modded Entries start being the comment I added.

                       <node id="Visuals">
                           <attribute id="Object" type="guid" value="449e617f-8356-46e5-b740-9e4b18200441"/>
                       </node>

These are the lines we want to add for each new entry. The uuid here is what we want to match to the unique UUID we gave in the CharacterCreationSharedVisuals UUID line:

                   <attribute id="UUID" type="guid" value="449e617f-8356-46e5-b740-9e4b18200441"/>

This one from the our sharedvisuals file. When you've finished adding the entries you want to add the races.lsx is ready to go.

If you wish to use Modding:Compatibility Framework see that guide on how to use it as an alternative to Races.lsx. However we suggest you use both in order to not rule out your Mac users from using your mods.

When to use three or more meshes for autosnapping hairs[edit | edit source]

Do you notice your autosnapping hair looks good on default bodies, but doesn't work quite right for the shorter or taller bodyshapes?

This is where you would make several autosnapping hairs. Each variation needs its own VisualBank entry in your merged.lsf file.

So if your hair has issues on different bodyshapes, you can do what Larian did and make several.

  • One made around a dwarven head.
    • this would be for Gnomes, Halflings and Dwarves
  • One made around the default Elf height.
    • this would be for Elves, Drow, Humans, Half Elves/Drow, Githyanki and Tieflings
  • One for Taller bodyshapes.
    • this would be for Strong Elves, Drow, Humans, Half Elves/Drow, Tieflings and Half Orcs

If you still get issues on Tiefling heads then you might want to use Tiefling masc heads as a base for your default and tall height. You can make as many autosnapping variants as you need, but usually three will be enough.

Once you have these set up and have made the visualbank entries, you can then make the additional edits to your CharacterCreationAppearanceVisuals or CharacterCreationSharedVisuals.

CharacterCreationAppearanceVisuals[edit | edit source]

If using CharacterCreationAppearanceVisuals, change the VisualResourceID to the new ones in the correct slots you made previously for testing the mod, as you should have all the vanilla race and bodyshapes available from your first creation of the file.

CharacterCreationSharedVisuals[edit | edit source]

If using CharacterCreationSharedVisuals, you want to make new entries with these options. And in races.lsx instead of using Humanoid/Fey/Fiend/Celestial you want to use the race sections of the races the hairs will work on.

  • For the Dwarven height, add to Gnomes, Halflings and Dwarves
  • For the default height, add to Elves, Drow, Humans, Half Elves/Drow, Githyanki and Tieflings
  • For the taller height, add to Strong Elves, Drow, Humans, Half Elves/Drow, Tieflings and Half Orcs

Troubleshooting[edit | edit source]

Here are some common hair issues and how to troubleshoot them.

My hair doesn’t show up at all, there’s not even a slot in Character Creation!

Check your CharacterCreationAppearanceVisuals or CharacterCreationSharedVisuals, as that is where the CC slots are defined.

My hair shows up as a slot, but when I select it, the hair is invisible!

Check your hair _merged file, especially the file paths to your SourceFile and Template. Any inconsistency between this and the actual folders will result in the game not finding your mesh, and thus not loading it. Also note that folders must be separated by /, not \. E.g. Mod/Generated/Mod/Hair.GR2