Skip to content

Modding BK

R. Vaccari edited this page Feb 9, 2023 · 4 revisions

The mod offers mod support in 2 manners:

  • Using Banner Kings as a dependency;
  • References for requesting a BK version adapted to your own mod.

Reference Sheet

If you are a mod author for some type of overhaul (new cultures, factions, map changes, etc) and would like a customized BK version, use the Reference Sheet. It contains information on custom culture and religion adaptations you can have in the mod. However its better to discuss this with me on Discord beforehand, to check if I have the time to do so.

Banner Kings as a Dependency

As a dependency, BK offers mod support to a significant part of it's content. Models may be extended and new content, such as Books, Languages and Religions, can be added on top of existing ones in the mod.

Default Types

The mod uses this design a lot. It's useful for saving as little data in save files as possible. It can be used whenever a piece of content has static information, ie - Books. Book names, descriptions and languages won't change. Therefore, the mod doesn't need to save this information in your save files. It only saves the book ids of the books you've read. When the game loads, Bannerlord kickstarts a BookType instance, but it has nothing other than the id. The mod than initializes the rest, based on this id. It knows that every book with X id will have NameX and DescriptionX.

Content that supports this:

  • BookType: custom books will be spawned dynamically with sellers.
  • Language: custom cultures will automatically pick up on custom languages made for them.
  • Lifestyle: custom lifestyles will aumatically be made available for AI and players. Lifestyles without culture are globally available. Lifestyles with culture will be restricted to Heroes of that culture. Works both for custom and existing cultures.
  • BuildingType: custom buildings will automatically be added to Settlement Management menus. The mod adds sliders to the vanilla menu, making it possible to fit in any amount of building options.
  • Religion: new religions will automatically be spawned on the world. You'll need to create your own Faith. The methods IsHeroNaturalFaith and IsCultureNaturalFaith will determine how the faith is spread. If you want it to exist concurrently with other religions, employ MBRandom.RandomFloat. Ie, if you want 50% of Sturgian Heroes to be part of it, use:
        public override bool IsCultureNaturalFaith(CultureObject culture)
        {
            if (culture.StringId == "sturgia")
            {
                return true;
            }

            return false;
        }

        public override bool IsHeroNaturalFaith(Hero hero)
        {
            if (IsCultureNaturalFaith(hero.Culture) && MBRandom.RandomFloat <= 0.5f)
            {
                return true;
            }

            return false;
        }

I suggest looking into the mod's source how each data type is worked with. Some are simple, but others, such as religion, have it's own particularities. Ie, religions also need preacher presets in XML that follow a particular id structure.

Using Default Types

This content can be extended by other mods in this manner:

  1. Create a DefaultTypeInitializer. This class requires 2 generics. The first is the class itself, so it can return it's own instance without you needing to code it. Secondly, an object class that extends BannerKingsObject, such as BookType.
public class DefaultBookTypes : DefaultTypeInitializer<DefaultBookTypes, BookType>
  1. Implement the Initialize() method. Have your new BannerKingsObject types instantiated and initialize their contents.
public BookType HeatsDesire { get; private set; } = new BookType("book_heartsDesire");

public override void Initialize()
{
   HeatsDesire.Initialize(BKItems.Instance.BookHeartsDesire, 
        new TextObject("{=!}"), 
        DefaultLanguages.Instance.Vlandic, BookUse.Skillbook, DefaultSkills.Charm);
}
  1. Still in the Initialize method, add all of your new additions to the original BK initializer. This can be done with AddObject method. When it comes to BookTypes, this would be the BK class DefaultBookTypes. Here is an example of a full class following this design:
 public class MyCustomInitializer: DefaultTypeInitializer<MyCustomInitializer, BookType>
    {
        public BookType Book1{ get; private set; } = new BookType("book1");
        public BookType Book2 { get; private set; } = new BookType("book2");

        public override IEnumerable<BookType> All
        {
            get
            {
                yield return Book1;
                yield return Book2;
            }
        }

        public override void Initialize()
        {
            Book1.Initialize(BKItems.Instance.BookHeartsDesire, // you would need to create your own ItemObject
                new TextObject("{=!}"), 
                DefaultLanguages.Instance.Vlandic, BookUse.Skillbook, DefaultSkills.Charm);

            Book2.Initialize(BKItems.Instance.BookHeartsDesire, // you would need to create your own ItemObject
                new TextObject("{=!}"), 
                DefaultLanguages.Instance.Vlandic, BookUse.Skillbook, DefaultSkills.Charm);

            foreach (var book in All)
            {
                DefaultBookTypes.Instance.AddObject(book);
            }
        }
  1. Finally, use BannerKingsConfig to register your initializers. I recommend doing this in the OnGameStart of your MBSubModuleBase class. This will ensure everything is initialized in the adequate order and time.
BannerKingsConfig.Instance.AddInitializer(MyCustomInitializer.Instance);

Extending Models

A lot of the mod's effects are implemented through models. Bannerlord models are me to be overridable. By default, only 1 mod can override each model type. However it is still possible to keep the effects of several mods through Inheritance.

Vanilla Models

Just like BannerKings inherits from Bannerlord models, your mod would need to inherit from BannerKings. Let's see an easy example.

public class BKCrimeModel : DefaultCrimeModel
{
    public override ExplainedNumber GetDailyCrimeRatingChange(IFaction faction, bool includeDescriptions = false)
    {
        var result = base.GetDailyCrimeRatingChange(faction, includeDescriptions);
        if (Campaign.Current.GetCampaignBehavior<BKCampaignStartBehavior>()
            .HasDebuff(DefaultStartOptions.Instance.Outlaw))
        {
            return new ExplainedNumber(0f, includeDescriptions, DefaultStartOptions.Instance.Outlaw.Name);
        }

        return result;
    }
}

Here BannerKings extends the vanilla DefaultCrimeModel through it's class BKCrimeModel. This means that all the inherit logic from DefaultCrimeModel is maintained while allowing BannerKings to add it's own effects on top of it. Here we override the GetDailyCrimeRatingChange method, and we can access the super class' result by using base.GetDailyCrimeRatingChange(faction, includeDescriptions). You can then add onto it, or even return a completely new result, as it's done here.

Likewise, your mod, with your own ModXCrimeModel would extend BKCrimeModel. Thus the game would have the full effects of ModXCrimeModel, BKCrimeModel and DefaultCrimeModel combined.

BannerKings Models

To be done.