Patch File Extraction

Extracting patch files from existing mods using FModel and .diff or .diff.into

Extracting TOML Patch Files using FModel and automod .diff

You can extract any existing mod changes by using FModel and automod .diff in 3 steps:

  1. Extract the game original .uasset JSON files using FModel; as an example, all Stellar Blade data table .uasset (which can be reused for extracting many mods):

    fmodel-extract-original

    If you are not familiar with FModel, please see a guide on how to set it up.

  2. Extract the modded .uasset JSON files of interests using FModel; as an example, the Stellar Blade No Timing Needed to Perfect Parry and DodgeNoTimingPerfectParryDodge1.0.3 mod by EnjoyourGame:

    fmodel-extract-modded

  3. Use automod .diff to create TOML patch files

    automod-diff

    automod uses jd to diff the .uasset JSON files and uses the result jd produced to generate its TOML patch files.

    In many cases, the TOML patch files can be automatically created. However, in this case, automod is unsuccessful in fully creating them; here are the relevant messages from the recording:

    The following patches were skipped:
    * C:\Temp\automod\vscode-out\diff-2025-08-29T16-37-36-856Z\Exports\SkillCommandTable.patch
      * Unsupported patch form at line 21: @ [0,"Rows","P_Eve_Sword_Evade_Evade1_1","NextComboCommandArray",0]        
      * Unsupported patch form at line 23: + "P_Eve_Sword_JustEvade_DashAttack1_1"
      * Unsupported patch form at line 27: @ [0,"Rows","P_Eve_Sword_Evade_Evade1_1","NextComboCommandArray",6]        
      * Unsupported patch form at line 29: + "P_Eve_Sword_Air_DropAttack1_1"
      * Unsupported patch form at line 49: @ [0,"Rows","P_Eve_Sword_LockonEvade_Evade1_1","NextComboCommandArray",0]  
      * Unsupported patch form at line 51: + "P_Eve_Sword_JustEvade_DashAttack1_1"
      * Unsupported patch form at line 55: @ [0,"Rows","P_Eve_Sword_LockonEvade_Evade1_1","NextComboCommandArray",6]  
      * Unsupported patch form at line 57: + "P_Eve_Sword_Air_DropAttack1_1"
      * Unsupported patch form at line 62: @ [0,"Rows","P_Eve_Sword_Lockon_Evade1_1","NextComboCommandArray",7]       
      * Unsupported patch form at line 64: + "P_Eve_Sword_Air_DropAttack1_1"
      * Unsupported patch form at line 69: @ [0,"Rows","P_Eve_Sword_Normal_Evade1_1","NextComboCommandArray",7]       
      * Unsupported patch form at line 71: + "P_Eve_Sword_Air_DropAttack1_1"
      * Unsupported patch form at line 76: @ [0,"Rows","P_Eve_Sword_Normal_Guard1_1","NextComboCommandArray",5]       
      * Unsupported patch form at line 78: + "P_Eve_Sword_Air_DropAttack1_1"
    

    This happened because automod does not support all jd diff result forms. The problematic jd result parts are:

    @ [0,"Rows","P_Eve_Sword_Evade_Evade1_1","NextComboCommandArray",0]
    [
    + "P_Eve_Sword_JustEvade_DashAttack1_1"
    + "P_Eve_Sword_JustEvade_LightAttack1_1"
    + "P_Eve_Sword_JustEvade_StrongAttack1_1"
      "P_Eve_Sword_Combo_LightAttack1_1"
      @ [0,"Rows","P_Eve_Sword_Evade_Evade1_1","NextComboCommandArray",6]
      "P_Eve_Sword_Combo_DashAttack1_1"
    + "P_Eve_Sword_Air_DropAttack1_1"
    + "P_Eve_Sword_Air_DropAttack2_1"
    + "P_Eve_Sword_Normal_BackStab1_1"
    + "P_Eve_Sword_Normal_BackStab2_1"
      ]
      @ [0,"Rows","P_Eve_Sword_LockonEvade_Evade1_1","NextComboCommandArray",0]
      [
    + "P_Eve_Sword_JustEvade_DashAttack1_1"
    + "P_Eve_Sword_JustEvade_LightAttack1_1"
    + "P_Eve_Sword_JustEvade_StrongAttack1_1"
      "P_Eve_Sword_Combo_LightAttack1_1"
      @ [0,"Rows","P_Eve_Sword_LockonEvade_Evade1_1","NextComboCommandArray",6]
      "P_Eve_Sword_Combo_DashAttack1_1"
    + "P_Eve_Sword_Air_DropAttack1_1"
    + "P_Eve_Sword_Air_DropAttack2_1"
    + "P_Eve_Sword_Normal_BackStab1_1"
    + "P_Eve_Sword_Normal_BackStab2_1"
      ]
      @ [0,"Rows","P_Eve_Sword_Lockon_Evade1_1","NextComboCommandArray",7]
      "P_Eve_Sword_Combo_DashAttack1_1"
    + "P_Eve_Sword_Air_DropAttack1_1"
    + "P_Eve_Sword_Air_DropAttack2_1"
    + "P_Eve_Sword_Normal_BackStab1_1"
    + "P_Eve_Sword_Normal_BackStab2_1"
      ]
      @ [0,"Rows","P_Eve_Sword_Normal_Evade1_1","NextComboCommandArray",7]
      "P_Eve_Sword_Combo_DashAttack1_1"
    + "P_Eve_Sword_Air_DropAttack1_1"
    + "P_Eve_Sword_Air_DropAttack2_1"
    + "P_Eve_Sword_Normal_BackStab1_1"
    + "P_Eve_Sword_Normal_BackStab2_1"
      ]
      @ [0,"Rows","P_Eve_Sword_Normal_Guard1_1","NextComboCommandArray",5]
      "P_Eve_Sword_Combo_DashAttack1_1"
    + "P_Eve_Sword_Air_DropAttack1_1"
    + "P_Eve_Sword_Air_DropAttack2_1"
    + "P_Eve_Sword_Normal_BackStab1_1"
    + "P_Eve_Sword_Normal_BackStab2_1"
      ]
    

    In cases like this, manual intervention is required. That is, you can create the corresponding TOML patches for those using regex/patchlets manually, e.g.,:

    ['.*: ^P_Eve_Sword_(Lockon)?Evade_Evade1_1']
    NextComboCommandArray = '''=> {
    var array = v.orig[Seq[Map[String, Any]]]
    val first = array.head
    array +:= (first + ("Value" -> "P_Eve_Sword_JustEvade_DashAttack1_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_JustEvade_LightAttack1_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_JustEvade_StrongAttack1_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_Air_DropAttack1_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_Air_DropAttack2_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_Normal_BackStab1_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_Normal_BackStab2_1"))
    array
    }'''
    
    ['.*: ^P_Eve_Sword_(Lockon|Normal)_(Evade|Guard)1_1$']
    NextComboCommandArray = '''=> {
    assert(v.objName != "P_Eve_Sword_Lockon_Guard1_1")
    var array = v.orig[Seq[Map[String, Any]]]
    val first = array.head
    array +:= (first + ("Value" -> "P_Eve_Sword_Air_DropAttack1_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_Air_DropAttack2_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_Normal_BackStab1_1"))
    array +:= (first + ("Value" -> "P_Eve_Sword_Normal_BackStab2_1"))
    array
    }'''   
    

Using automod .diff.into

automod .diff.into can be used to create TOML patch files between the game original FModel extracted .uasset folder, say Output\Original, and another folder, say Output\Modded, which contains several FModel extracted mods:

automod-diff-into