EDIT:
Since I couldn't get it to work the "intended" way I made a workaround.
I wrote a Patcher that allows adding new settlements (villages, towns and castles) to the game through separate modules. This is a slightly dirty solution. Source code, brief explanation of how it works, caveats and an example module can be found on the github page. Let me know if you have any questions via DM on discord (Trucker#3350)
EDIT END.
-------------------------
EDIT #2
NEW UPDATE (coming) - NOW (later) WITHOUT MODIFIYNG SANDBOX MODULE AT ALL
Some new information has come to light. There is a way to override or add to the original settlements of the game. I added how here:
I will update this patcher (prob on or before 25.04.20) to work more cleanly, making it truly how you expect a mod to work (being able to load/unload the module without any caveats related to crashes). The reason why some C# code is still needed is to be able to generate a new distance cache, plus update compatibility.
What this means for you is that for now you can keep working with this the way it is and then just get the updated version on the weekend. No further changes will be needed.
-------------------------
I have been trying for about 10 hours now to add settlements to the game without needing to modify the sandbox module.
I wanted to summarize my findings and current challenges in the hopes that others may have overcome them or are inspired by my "struggles" to find and share a solution.
Adding a settlement consists of two things:
Now you might think how can one add a new settlement to the game without modifying Sandbox, when all fiefs are defined hardcoded under the Main_Map scene? Good question! For this have a look at the StoryMode module. The training field the player starts at is not defined in Sandbox but in fact in StoryMode. For this two XML files are important:
So how does StoryMode get the training field into the game? Well, purely by hardcoded file references. The most important class for this is "CampaignStoryMode : Campaign" within StoryMode.dll namespace StoryMode.CampaignStoryMode.
Within this, three functions are called:
What I tried so far:
If you guys have any questions about what I described please let me know. My source code is attached. It contains a custom FoodModel that I was playing around with but you can ignore that. My Bannerlord module is also attached. It contains a .txt file with custom debug output that I populate in the patched function. This is needed since the regular crash reporter does not work...
Other stuff
Bannerlord module https://we.tl/t-zgKV0G5Qgq
Module source code https://we.tl/t-7ldSilrbxP
Since I couldn't get it to work the "intended" way I made a workaround.
I wrote a Patcher that allows adding new settlements (villages, towns and castles) to the game through separate modules. This is a slightly dirty solution. Source code, brief explanation of how it works, caveats and an example module can be found on the github page. Let me know if you have any questions via DM on discord (Trucker#3350)
GitHub - KesslerMan/BannerlordSettlementPatcher: A library to load custom settlements into the game without needing to manually modify the sandbox module. Loads the submodule.xml and checks for any entries with id prefabs or settlements, then proceed
A library to load custom settlements into the game without needing to manually modify the sandbox module. Loads the submodule.xml and checks for any entries with id prefabs or settlements, then pro...
github.com
EDIT END.
-------------------------
EDIT #2
NEW UPDATE (coming) - NOW (later) WITHOUT MODIFIYNG SANDBOX MODULE AT ALL
Some new information has come to light. There is a way to override or add to the original settlements of the game. I added how here:
Bannerlord-Modding/Documentation
Community Documentation for Mount & Blade II: Bannerlord - Bannerlord-Modding/Documentation
github.com
What this means for you is that for now you can keep working with this the way it is and then just get the updated version on the weekend. No further changes will be needed.
-------------------------
I have been trying for about 10 hours now to add settlements to the game without needing to modify the sandbox module.
I wanted to summarize my findings and current challenges in the hopes that others may have overcome them or are inspired by my "struggles" to find and share a solution.
Adding a settlement consists of two things:
- An XML-based definition of a Settlement in e.g. ModuleData/custom_settlements.xml. Lets say this settlement has the name Frugal and the id town_M1
- An XML-based definition for what this specific settlement looks like on the Main_map/world map. Sandbox does this in SceneObj/Main_Map/scene.xscene
- All vanilla settlements and other points of interests such as hideout camps are defined in there.
- The scene.xscene structure is something along the lines of <scene><entities><game_entity name="town_M1"></scene></entities></game_entity>
- These game_entities are just prefabs in terms of the game
- The Settlement xml can be referenced in the submodules.xml in order to be loaded by the game, but there seems to be no good way to load prefabs
Now you might think how can one add a new settlement to the game without modifying Sandbox, when all fiefs are defined hardcoded under the Main_Map scene? Good question! For this have a look at the StoryMode module. The training field the player starts at is not defined in Sandbox but in fact in StoryMode. For this two XML files are important:
- StoryMode\ModuleData\story_mode_settlements.xml
- StoryMode\Prefabs\storymode_prefabs.xml
So how does StoryMode get the training field into the game? Well, purely by hardcoded file references. The most important class for this is "CampaignStoryMode : Campaign" within StoryMode.dll namespace StoryMode.CampaignStoryMode.
Within this, three functions are called:
- MBObjectManager.Instance.LoadOneXmlFromFile(BasePath.Name + "Modules/StoryMode/ModuleData/story_mode_settlements.xml", (string) null, (Type) null, true);
- This seems to load one settlement definition from a given xml file and registers it with the object manager.
- Settlement settlement = Settlement.Find("tutorial_training_field");
- Saves the reference to the training field "settlement" in a variable, proving that the aforementioned line is enough to register a settlement in the game
- this.MapSceneWrapper.AddNewEntityToMapScene(settlement.StringId, settlement.Position2D);
- This adds the settlement to the actual map scene. From what I can gather this function is what reads the prefab/game_entity. For this it is important that the ids of the prefab and settlement line up.
- This function also calculates the z position by getting the terrain height at the given position
What I tried so far:
- First I tried a "pure" XML-based approach.
- Define my settlement Frugal and its game_entity in a settlements XML and prefab XML file. I then tried to include them in the submodule to have the game load them autonomously. This does not work and results in a crash, from what I can tell the reason is that while the game does load the settlements.xml it does not load the prefabs and tries to display something on the main_map without knowing the visuals.
- Try creating my own gamemode that essentially works exactly like the StoryMode module, but loads my XML files
- I was struggling to get a good reference to the mapscenewrapper to call the AddNewentityToMapScene function, so I figured I needed to somehow obtain the instance of CampaignStoryMode
- I eventually made it and had my code execute as part of the game's regular structures during the game loading sequence (when a new game object is created/loaded)
- Results in crashes apart from the nightmare of getting the game running with a custom singleplayer gamemode
- Patching the CampaignStoryMode function that contains the cod ethat loads the tutorial_training_field
- Using harmony to do a Postfix on "DoLoadingForGameType" and essentially copy the code 1 to 1, except load my custom fief and prefab.
- The code runs, the postfix does not cause any crashes...
- ...unfortunately the game crashes without even opening the crash reporter afterwards and I do not know why
- From what I can tell the way StoryMode adds the training field is no different to how I try to add Frugal. Not sure why it is crashing, maybe because the prefab is not properly loaded but that's just a completely wild guess.
- Almost giving up and deciding to post here to describe what I know and see if anyone has any ideas.
If you guys have any questions about what I described please let me know. My source code is attached. It contains a custom FoodModel that I was playing around with but you can ignore that. My Bannerlord module is also attached. It contains a .txt file with custom debug output that I populate in the patched function. This is needed since the regular crash reporter does not work...
Other stuff
- it is possible that for the AI to be able to travel to custom villages properly it is necessary to add an entry for it under settlements_distance_cache.bin . The game does this in the Sandbox module: Sandbox.view SettlementPositionScript.cs . The code in there seems to be designed to work in combination with an Editor where the user can add new settlements and the code automatically populates the data in the appropriate files.
Bannerlord module https://we.tl/t-zgKV0G5Qgq
Module source code https://we.tl/t-7ldSilrbxP
Last edited: