Skip to content
John edited this page Sep 2, 2022 · 5 revisions

IMPORTANT FOREWORD: Once units (and other things) are loaded into an area, most (all?) of their properties and fields are locked in. If you want to test changes to a Unit's blueprint or otherwise, you will need to go through an area load beforehand.

Helpful Advice: It is much easier to access protected members of a WotR or Kingmaker class via publicizing the C# assembly - check out the page here for more details. If you do not do this, you will need to access many fields via reflection.

General

To edit blueprints in the game, install a postfix harmony patch after the game loads the blueprint library. This is slightly different in WotR and Kingmaker.

Kingmaker:

/// <summary>
/// We cannot modify blueprints until after the game has loaded them, we patch 
/// LibraryScriptableObject.LoadDictionary to be able to make our modifications as
/// soon as the blueprints have loaded.
/// </summary>
[HarmonyPatch(typeof(LibraryScriptableObject), "LoadDictionary")]
static class LibraryScriptableObject_LoadDictionary_Patch
{
  static bool loaded = false;
  static void Postfix()
  {
    if (loaded) return;
    loaded = true;

    // Call your code to edit blueprints here
  }
}

WotR:

/// <summary>
/// We cannot modify blueprints until after the game has loaded them, we patch BlueprintsCache.Init
/// to be able to make our modifications as soon as the blueprints have loaded.
/// </summary>
[HarmonyPatch(typeof(BlueprintsCache), "Init")]
static class BlueprintsCache_Init_Patch
{
  static bool loaded = false;
  static void Postfix()
  {
    if (loaded) return;
    loaded = true;

    // Call your code to edit blueprints here
  }
}

Once you have set up the above, modifications made to blueprints will persist for the session, so if you do not want to replace original blueprints, you should copy before editing them.

To fetch an existing blueprint in Kingmaker:

public static T Get<T>(this LibraryScriptableObject library, String assetId) where T : BlueprintScriptableObject
{
  return (T)library.BlueprintsByAssetId[assetId];
}

And in WotR:

public static T Get<T>(string assetId) where T : SimpleBlueprint
{
  return (T)ResourcesLibrary.TryGetBlueprint(BlueprintGuid.parse(assetId));
}

After grabbing the blueprint asset, you can further edit it/duplicate/etc..

Editing Units

Units are the NPCs and other actors in the game that have statistics. At their core, they have a brain, an inventory, and a fairly wide variety of other properties needed to function. Alongside that, they have a list of facts, and a componentsList that defines more details.

Generally you will usually:

  • Modify core values, such as race, portrait, faction, size, alignment, etc...
  • Add or remove facts from the unit
  • Edit their inventory
  • Add or remove components from their componentList

Modifying Core Values

Modifying core values of a unit is quite simple - you can usually just directly access the value and replace it.

//Grab your Unit blueprint
public static BlueprintUnit AasimarRedMask => ResourcesLibrary.TryGetBlueprint<BlueprintUnit>("20fcfa451598dfe48a2e90088effc766");
//Change your Unit's dex stat
AasimarRedMask.Dexterity = 28;

For other values, you can use dnspy/ilspy and decompile BlueprintUnit to see what types are accepted by different stats, and how they can be accessed. Note that protected fields and similar will need reflection to access, unless you have gone through the steps of creating and using a publicized assembly.

Modifying Fact Arrays

Fact arrays can include quite a wide number of things, from buffs to features and feats. Facts are "built-in" to the Unit and, in the example of pushing a spell in as a fact, the Unit will be able to use the spell an unlimited amount of times, similar to how SLAs work in PnP. The general process for adding things to the Fact Array looks something like:

BlueprintUnitFactReference[] refArr;
refArr = Units.UnitYouAreModifying.AddFacts; // Copy the original AddFacts array of your Unit
refArr = refArr.AddToArray(SomeFactFeatureBuffEtc.ToReference<BlueprintUnitFactReference>()); //Add a buff, feature.. whatever
refArr = refArr.AddToArray(DR20.ToReference<BlueprintUnitFactReference>()); //Add some DR to the Unit
Units.UnitYouAreModifying.m_AddFacts = refArr; //Publicized assembly allows us to directly push the updated array back into the AddFacts protected member.

Inventory Editing

Similar to directly modifying stats, you can access the body of a Unit and change what it's wearing by simply going:

//Replace whatever is in the primary hand of your unit with a Longsword +4 (note that it takes a reference, so we need to go ToReference)
//Again note that we do not need to use reflection because we have publicized the assembly
Units.UnitYouWantToChange.Body.m_PrimaryHand = Equipment.Yaniel_Longsword4HolyAvenger.ToReference<BlueprintItemEquipmentHandReference>();

ComponentList Editing

Components are things like the class levels a unit has (add feats, spells, etc... that come from it's class), working with it's tactical/army statistics (for the army battles), or a few other things.

As class levels and the class-related information on a unit is something that is commonly edited, that will be the part mainly focused on here.

The general way to access a component is via something like:

var CRtest = YourBlueprintUnit.GetComponent<Experience>().CR;

In this case, we are getting the CR value of the Experience component which is located in the componentsList of YourBlueprintUnit. Other components and their fields can be accessed and changed in the same way. Take a look at the fields in both the dumped blueprint as well as the dnspy/ilspy decompiled code for complete understanding (eg. the "Experience" component here is under Kingmaker.Blueprints.Classes.Experience - if you access that via dnspy/ilspy, you will see all of the fields and such that make up the component)