MBSubModuleBase research and finding : How it works

Users who are viewing this thread

How MBSubModuleBase and game initialize process works.
I wanted to share my findings while working on my loader and put it in a separated post as it was looking as an advertising when put in the loader post, what wasn't the goal. It might also be useful for any mod even if they are unrelated to my work, so it was better to put this in a separate place.

Game initializing phases.
The whole initialization process handled by MBSubModuleBase is divided into phases represented by Methods that are called by the main Game object.
SubModulePhases.gif

OnSubModuleLoad is the very first to be executed and do not takes any parameters, it's basically to initialize your module.
All the others takes a Campaign object as parameter and OnGameStart, OnGameLoaded, OnCampaignStart, OngameCreated also takes a second parameter that is a CampaignGameStarter. Both of theses objects stores models, behaviors and gamemenus that are the objects and classes we use to mod the game, but not at the same time, and not in the same way. This is how things start to get complicated.

Campaign and CampaignGameStarter.
CampaignGameStarter is an object with the main goal to initialize a campaign when the game loads, be it from a save or a fresh new one. It's built to be quite flexible and most methods it offers resolve around adding content to the game.
"IList<CampaignBehaviorBase> CampaignBehaviors" and "IList<GameModel> Models" are public properties storing each type of objects were are interested in, allowing easy access and all the methods an IList can offer.
Campaign on the other hand handle a lot more of things, various managers and most of the things you might want to use or display later are stored in.
If behaviors can be easily accessed and managed with :
"List<CampaignBehaviorBase> GetCampaignBehaviors<T>()" and "(CampaignBehaviorManager CampaignBehaviorManager", the only way to access models is with "GameModelsManager Models" property that have many issues besides it's strange name. It stores models into an array, making it impossible to Add new ones to the collection.

Timing phases and Conversion issues.
Now this is where things becomes a bit dirty. In the initialization process at some point properties and informations stored into CampaignGameStarter have to be added to the campaign object. Taleworld chose a weird way to do the thing that can get pretty confusing.
First of all, all the objects might not be available in every phase, and calling one in the wrong time will have your game crash with a null exception, you might also simply use an object that is not used anymore. (And that's why i want to make NoHarmony)

For Behaviors CampaignGameStarter IList is added to the CampaignBehaviorManager just before OnGameInitializationFinished phase (it's hinted cause there is only one parameter), but as it's a reference, nothing is lost and you can still use the GameStarter until it's disposed.
That also means Campaign do not stores any Behavior before OnGameInitializationFinished phase, and trying to access the manager will lead to an error that must be handled if you do not want the game to crash.

For Models they chose to make a conversion from IList to array after "OnGameStart" which is REALLY early in the process. That means any new model you want to add to the game should be done before or won't be added. (At least not without a headache) The CampaignGameStarter will still allows you to add new models, but none of the changes made past this point will affect the game.


MBSubModuleBase after initialization.
This is still something i'm investigating, but an object of SubModuleBase (Or the class you use extending from it) is kept in memory until games shut down, and this is the place your models, behaviors and even gamemenus are stored. This object can be accessed during the game through a collection of objects like TaleWorlds.MountAndBlade.Module, Submodule, Talewords.Engine.ModuleInfo and SubModuleInfo. This way you can also access properties of other mods, if they chose to expose or give access to variables it contains. It might come in handy for some configuration menu inside the game as an example, but it requires more investigation.


That's all for now, will maybe expend it a bit if i find more interesting information to share as i progress on the loader rework, hope it's useful.
 
Last edited:
Could you also add the other submodule events and examples from the StoryMode submodule for instance?
Would be great to have a description of what we are supposed to do in each event and how they relate to the events of the vanilla submodules
 
Last edited:
Back
Top Bottom