Suggestion General New VolunteerProductionModel not consequent enough

Users who are viewing this thread


First of all I greatly appreciate the implementation of the new model and the help I got from the TW discord on that topic. As some of you may know I made a mod that allows users to replace the basic troop of any faction with one or more custom basic troops. That being said I think the new VolunteerProductionModel could be enhanced further. I am by no means a C# expert but I'll try to elaborate.

Pre 1.6.0:
The main method that determines what kind of troop a notable gets is the method UpdateVolunteersOfNotables in the RecruitmentCampaignBehavior. In that method the basic troop is pulled from the settlement's culture. Each culture has exactly one basic troop and one elite elite troop. I don't want to go too much into detail but usually the basic troop is spawned first and then a couple of checks (policies, perks etc.) and some RNG later the basic troop is eventually upgraded the elite basic troop.

To modify which basic troop is eventually given to the notable I "had" to overwrite the method UpdateVolunteersOfNotables completely. I put "had" in quotes because just from my knowledge of C# I couldn't find another way. I tried rewriting the whole behavior but that seemed way to excessive for just a small change like the one I had intended.

Post 1.6.0:

Now as of 1.6.0 within the above mentioned method UpdateVolunteersOfNotables there is a new method called GetBasicVolunteer. This new method is in a new model called (Default)VolunteerProductionModel and it can be overwritten and added as a new custom model. As the name suggests the new method returns either the basic troop or the elite basic troop of the notable's culture. That is a great change! I immediately removed my harmony patch of UpdateVolunteersOfNotables and added a new custom model and overwrote said method...
The basic troop that gets spawned is actually still determined in the UpdateVolunteersOfNotables behavior method. The new model method GetBasicVolunteer is used for the upgrade system. Basically the basic troop is still taken directly from the settlement's culture just like in the pre 1.6.0 version. And while the basic troop is eventually overwritten with what GetBasicVolunteer returns, you can not directly replace the basic troop directly.

Instead of taking the basic troop directly from the culture of the notable's current settlement or the notable's clan (when the settlement is null), add another method to the VolunteerProductionModel, something like CharacterObject GetBasicTroop( hero ), and move the following line into that method:
CharacterObject basicTroop = ((hero.CurrentSettlement != null) ? hero.CurrentSettlement.Culture : hero.Clan.Culture).BasicTroop;

Again, my C# knowledge is limited. Perhaps there are better ways of doing this but I still wanted to at least provide some kind of simple solution :smile:



adding on and summarizing a bit:
  • VolunteerProductionModel provides a method, GetBasicVolunteer(Hero).
  • RecruitmentCampaignBehavior uses that method in UpdateVolunteersOfNotables(), both to produce a volunteer (as either a basic or elite recruit), and to check whether to produce an elite recruit.
  • With 1.6, the logic on whether a notable should provide elite recruits or not has been moved out of RecruitmentCampaignBehavior into the VolunteerProductionModel model (which is great). But the code for which recruits is still internal to the behavior.
  • Since it is internal to the behavior, if modders want to change which recruits are produced, they have to either create an entire new RecruitmentCampaignBehavior - a large class with a lot of code - or use a patch to alter the native class at runtime; the exact sorts of things Game Models are designed to make unnecessary.
As an example of the use case: suppose a modder wanted to make different types of notables produce different types of recruits, such as assigning one troop type to be produced by Rural Notables and a different troop type to be produced by Artisans. It's fully possible currently, but a bit roundabout and hack-ish.

What would be great is something along these lines:
  • Addition of a method - eg "GetEliteVolunteer(Hero)" - to VolunteerProductionModel that provides the elite recruit.
  • Addition of a method - eg "ShouldProvideEliteVolunteer(Hero)" - to VolunteerProductionModel, so that logic can be separated out from GetBasicVolunteer(Hero).
  • Modify UpdateVolunteersOfNotables() to reference those three methods; rather than calling Culture.BasicTroop internally, and determining whether to produce elite troops by comparing the result of GetBasicVolunteer() to that, as it does now.
  • Overall, this would be a pretty minor amount of total code to change, really only a couple of lines.
In that way, it would be very easy for modders to change troop recruitment via implementing a game model. Along the previous example, a modder could implement their if-occupation then-troopXYZ code in their model's GetBasicVolunteer without needing to dive into the behavior.


Community Manager
@Adonnay @svelok 1.6.1 patch brought in a few changes related to your requests. Now the volunteer for a hero will be determined by the model alone. So modders can ask their VolunteerProductionModel GetBasicVolunteer(hero) and it will return which troop will initially be seen (behaviour will still try to upgrade that troop over time). Modders can check the culture, occupation or any other property of the hero in order to determine their volunteers.
Top Bottom