1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Hi Guest! To get rid of ads on the page, please consider donating through user upgrades or other methods.
    Dismiss Notice

How to All about hair modding!

Discussion in 'How-to' started by Fumi, Dec 4, 2017.

  1. Fumi
    24%

    Fumi Cricket Member

    Anivay's guide on hair modding. Saved from Blade & Soul Dojo before it was shut down.

    Hair Modding Guide
    by Anivay

    Hi guys! I've had a lot of people asking me about hair modding. I was thinking of making another video tutorial, but there's too many different cases/information for me to cover effectively in a video, so I'm writing up a guide~

    This guide will be primarily done by examples with brief explanations. I will list what files and numbers I am looking at and provide the exact cursor location of where I make changes. I highly encourage you to follow along from scratch in your own hex editor~ If your attempt doesn't work, you can download the completed mod that I included to compare it to yours. I will try to list my examples from easiest to most complex.

    As we're dealing with hex editing, when I'm specifically referring to a hex number rather than a decimal number I will use hex notation (0x) before the number. A programming calculator (like the one windows has) will be really helpful for converting between hex and decimal. Remember, hex numbers count 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.

    Regular Hair, Hair 100+, and the Export Table - a brief summary
    Hair mods only require the skeleton to work, so you can ignore the material completely~

    Hairs are generally defined by their object/core number formatting of: 3 characters for race, 1 character for gender, an underscore, followed by 3 digits for the identification number. (ex: JinF_001) All hair object core numbers are formatted like this in one of two ways in the skeleton UPK file: a standard complete string containing race and ID, or a split string with the race in the standard location and the number appended by a value found in the something called the Export Table. That later format of hairs is only used for hairs with IDs 100 or greater, so I refer to hairs that follow that pattern as a Hair100+ hair.

    When dealing with Hair100+ and changing an accessory hat to a hair you will need to deal with the Export Table. The Export Table is what the game reads to find out what it needs to load from the file and where to find that information.

    The main things that you need to know are:
    - A double word is 4 pairs of hex numbers (ex: 00 00 00 00 is one double word; I'll just call them words to keep it short)
    - The word starting at 0x25 (read in little endian) will tell you the location of the start of the Export Table
    - The first*** element of the Export Table points to the physics core number (e.g. string number of GonM_012_Physics)
    - The last*** element of the Export Table points to the object core number (e.g. string number of GonM_012)
    - The third word after the export index says what string number to look at for that property
    - The fourth word after the export index controls what is appended onto the object

    The fourth word is important to us because it is what makes 100+ hairs work. If you remember what I said about the format for 100+ hairs in the skeleton, they only have the race & gender in the upper part of the skeleton. What this fourth word in the export does is take the value in that place, subtract 1, and attach it to the race/gender with an underscore. For example, JinM is the object number that's sitting by the physics number. If there is a 0x65 (101 in decimal) in the fourth word of the last element in the Export Table, it will 'transform' the JinM into JinM_100.

    The third word is only important to us if the target core number does not have space to hold the new core number (for instance when you can't fit JinF_027 in the place of JinF or 040022_LynF in the place of LynF_026). When we encounter this problem, we need to find a string to replace that is long enough to hold the new longer core number. Once you find the new place to put your core number, count (starting from 0) from the first string at the top of the document until you reach that point. That location number is what is stored in the third word.

    To quickly find the first element of the export table (relating to physics core number) you can just Ctrl+F for the hex string FFFFFFFF (four pairs of Fs). The last element (relating object core number) will usually either be F8FFFFFF or F9FFFFFF if you want to Ctrl+F

    ***Do note however that these will not always be the correct positions for the object/physics cores. If something looks out of the ordinary (such as 0x00 in place of an actual value for a string location) you can dump the export table using umodel's command dialog: umodel.exe -game=bns -list UPKNUMBER

    Regular Hair to Regular Hair
    Regular hair to regular hair is very standard and easy. If you're within the same race/gender you only need to change the hair ID number in the object/physics cores.

    [​IMG]

    Example 1: JinF_042 (00019981) to JinF_031 (00014315)
    Change Log:
    Renamed 00014315.upk (copy) to 00019981.upk
    [0x066B] Changed Object core from JinF_031 to JinF_042
    [0x0680] Changed Physics core from JinF_031_Physics to JinF_042 Physics
    Hair100+ to Hair100+
    Hair 100+ to 100+ is also pretty straightforward. Change the physics core as your normally would. To change the object core number you will need to go to the last element of the export table and change the 4th word of the element to your new hair number +1. Using your calculator in programmer mode will be very helpful for converting from decimal to hex. If your base core number is 100, punch in 101 into your calculator and it will tell you that the hex value hat you need is 0x65.

    [​IMG]

    Example 2: LynF_100 (00033994) to LynF_107 (00034195)
    Change Log:
    Renamed 00034195.upk (copy) to 00033994.upk
    [0x07AF] Changed Physics core from LynF_107_Physics to LynF_100_Physics
    [0x1A16] In export table, changed 0x6C to 0x65
    Cross-Race Hair
    Cross-race hair works the same as usual except that you're changing the race part of the cores as well. PLEASE NOTE that most cross-race hair swaps do not work due to different head sizes and positions between the races. From my experience the only swaps that work well most of the time are between Jin Female and Yun, but even then certain hairstyles have clipping problems. Most other race-exchanged hairs result in major clipping issues. As of now, it is unknown how to work around that problem.

    [​IMG]

    Example 3: JinF_037 (00016142) to KunN_019 (00013428)
    Change Log:
    Renamed 00013428.upk (copy) to 00016142.upk
    [0x0554] Changed Object core from KunN_019 to JinF_037
    [0x0569] Changed Physics core from KunN_019_Physics to JinF_037_Physics
    Regular Hair to Hair100+
    When going from a hair100+ core number to a regular hair we run into the problem of the object core not being long enough to hold the new number. Lucky for us, the skeleton number is a string in the skeleton that basically serves no purpose and has no negative effect if removed or written over; not only that, but the length of the skeleton number is EXACTLY the length we need to hold a hair object core number! :D So... we replace the skeleton number with the new core number, change the physics core normally, in the export table change the old location of the object core number to the new location, and remove the appended value.

    [​IMG]

    Example 4: GonF_001 (00002680) to GonF_110 (00037191)
    Change Log:
    Renamed 00037191.upk (copy) to 00002680.upk
    [0x00BA] Changed 00037191 to GonF_001
    [0x0625] Changed Physics core GonF_110_Physics to GonF_001_Physics
    [0x1CBF] In export table, object index: change 0x39 to 0x03 (location of new object core, count strings from top starting at 0)
    [0x1CC3] In export table, object index append: change 0x6F to 0x00
    Hair100+ to Regular Hair
    Changing a hair100+ into a regular hair is a little simpler than the other way around. You only need to remove the extra parts after the race/gender in the object core, change the physics core as normal, and then in the last element of the Export Table add the value to append (your hair number + 1)

    [​IMG]

    Example 5: KunN_101 (00034381) to KunN_016 (00010693)
    Change Log:
    Renamed 00010693.upk (copy) to 00034381.upk
    [0x0719] Change Object core from KunN_016 to KunN (clear _016 will null)
    [0x072E] Change Physics core from KunN_016_Physics to KunN_101_Physics
    [0x220E] In export table, object index append: change 0x00 to 0x66
    Regular Hair to Wig/Hat
    So for whatever reason there are a couple regular hairs that are a little... weird and require a slightly different method. I will explain both; if the first method doesn't work for your hair try the second.

    The first method is basically identical to regular hair to regular hair - you just have a lot of leftover gunk you need to get rid of will nulls when you write over the old core with your base core.

    [​IMG]

    Example 6: JinM_002 (00003374) to 040164_JinM (00028144)
    Change Log:
    Renamed 00028144.upk (copy) to 00003374.upk
    [0x00C8] Changed Object core from 040164_JinM to JinM_002 (overwrite leftover characters with null)
    [0x00E0] Changed Physics core from 040164_JinM_Physics to JinM_002_Physics (overwrite leftover characters with null)

    Hopefully the first method worked for you, if not you have a bit more work to do.... The second method requires a bit of length editing, deleting, and inserting. For whatever reason some random hairs have a secondary core number that must be used instead of the standard core number. That second core number is formatted Hair_JinF_### rather than just JinF_### and thus requires some extra length in order to fit. We will be taking that length from the 'useless' skeleton number.

    [​IMG]

    Example 6.5: KunN_014 (00010074) to 040167_KunN (00028465)
    Change Log:
    [0x0086] DELETE 4 characters from 00028465
    [0x0082] Subtract 4 from the length (word directly before 00028465); Change 0x09 to 0x05
    [0x00C0] Add 2 to the length of the object core (word directly before it); Change 0x0C to 0x0E
    [0x00CF] Right click and INSERT two bytes at the end of the object core
    [0x00C4] Change 040167_KunN to Hair_KunN_014
    [0x00DA] Add 2 to the length of the physics core (word directly before it); Change 0x14 to 0x16
    [0x00F1] Right click and INSERT two bytes at the end of the physics core
    [0x00DE] Change 040167_KunN_Physics to Hair_KunN_014_Physics
    Hair100+ to Wig/Hat
    Hair100+ to hat works very similar to Hair100+ to regular hair. The core numbers will have a lot of extra bits you want to get rid of with null.

    [​IMG]

    Example 7: LynF_102 (00034122) to 040075_LynM (00019022)
    Change Log:
    Renamed 00019022.upk (copy) to 00032122.upk
    [0x00C8] Changed Object core from 040075_LynM to LynF (overwrite leftover characters with null)
    [0x00E0] Change Physics core from 040075_LynM_Physics to LynF_102_Physics (overwrite leftover characters with null)
    [0x1070] In export table, object index append: change 0x00 to 0x67
    Wig/Hat to Regular Hair
    The problem when your target is a hair and your base item is a hat is that the core number in the target skeleton does not have room to fit the base core number; ######_JinF is a lot longer than JinF_###. What we need to do is find some sacrifice string that is a) long enough to hold the long physics core number and b) does not have any negative effects when replaced. Luckily the string "bEnableBoneSpringAngular" is one of those strings that will work for us, so we'll use that. If your file does not have that string, you will need to find another one that is at least 19 characters long and will not cause problems in game once replaced. We can use the old physics core to hold the new long object core. Since we are changing the positions of these two elements, we will need to make changes to the export table so the game can find the correct information.

    [​IMG]

    Example 8: 040023_KunN (00012180) to JinF_027 (00010709)
    Change Log:
    Renamed 00010709.upk (copy) to 00012180.upk
    [0x0123] Change bEnableBoneSpringAngular to 040023_KunN_Physics (overwrite leftover characters with null)
    [0x058B] Change JinF_027_Physics to 040023_KunN (overwrite leftover characters with null)
    [0x0B55] In export table, Physics index: 0x36 to 0x08 (count strings from top starting from 0)
    [0x12C5] In export table, add 1 for the new object index; change 0x35 to 0x36

    There is a second way to do this that follows example 6.5 (regular hair to hat when normal method doesn't work). This involves adjusting lengths and deleting/inserting bytes. If you feel like doing it this way go ahead, but I will not be doing another example for it in this tutorial. With this method you won't need to touch the export table at all. Just subtract 6 bytes from the skeleton number and add 3 to the object and physics core numbers~
    Wig/Hat to Hair100+
    You can think of this as a combination of "Hat to Regular Hair" and "Regular Hair to Hair100+". The problem when your target is a hair and your base item is a hat is that the core number in the target skeleton does not have room to fit the base core number; ######_JinF is a lot longer than JinF. What we need to do is find some sacrifice string that is a) long enough to hold the long physics core number and b) does not have any negative effects when replaced. Luckily the string "bEnableBoneSpringAngular" is one of those strings that will work for us, so we'll use that. If your file does not have that string, you will need to find another one that is at least 19 characters long and will not cause problems in game once replaced. We can use the old physics core to hold the new long object core. Since we are changing the positions of these two elements, we will need to make changes to the export table so the game can find the correct information. The only extra step from Hat to Regular hair is that you need to remove the appended object core value.

    [​IMG]

    Example 9: 040022_LynF (00012240) to LynF_110 (00037189)
    Change Log:
    Renamed 00037189.upk (copy) to 00012240.upk
    [0x0142] Changed bEnableBoneSpringAngular to 040022_LynF_Physics (overwrite leftover characters with null)
    [0x079C] Changed LynF_110_Physics to 040022_LynF (replace leftover characters with null)
    [0x0D0E] In export table, Physics index: change 0x4A to 0x09 (count strings from top starting from 0) (NOTICE: 0xFFFFFFFF was not the correct element in the export table this time)
    [0x1CFE] In export table, add 1 for the new object index: change 0x49 to 0x4A
    [0x1D02] In export table, object index append: change 0x6E to 0x00
     
    yevvie likes this.
  2. War
    16%

    War Sand Warrior Member

    Beautiful job over there :bnsthumbsup::bnshmph: , but any long hair for jin male ? :bnsshy:
     
  3. manowar111
    8%

    manowar111 Cricket Member

    Can you explain please more detailed how to find the export table? I dont understand what this mean: "- The word starting at 0x25 (read in little endian) will tell you the location of the start of the Export Table"