BL Coding Modyfying food consumption for village owners

Users who are viewing this thread

Pejot

Sergeant Knight
WBVC
Hi,

I'm totaly new into moding Bannerlord and i wanted to ask if anyone can help me to achieve the below:

I wanted to reduce food consumption of parties that are leaded by owners of Villages. I'm interested in doing that for both player and AI.
How exactly should it work:

Each 10 Hearths in villages owned by clan of party leader provide food for 1 soldier per day. S for example if i have 4 villages with 700 Hearths in total i don't need to buy additional food if i have less or equal to 70 men.

Raided Villages don't provide food until they are rebuild.

Clan Leader party gets 60% of that food while other clan parties get equal part of the 40% depending on number of parties. If Clan leader is leading the only party in the clan he gets 100% of the food.

If Your or AI party is bigger than villages can feed You need to buy food on the market like it is in Vanilla for the troops above the limit. If You or any AI party doesn't own any village You/AI need to buy food for the whole party on the market.

I know where the party consumption calculation is but i can't get how to implement this calculation there.

This is something that may simulate food supply lines in some way and allows to tactical weakening of enemys by raiding their villages.
 
This will require major patching of FoodConsumptionBehavior.PartyConsumeFood() and DefaultMobilePartyFoodConsumptionModel.CalculateDailyFoodConsumptionf() with Harmony.

Let me get back to you in a few days. In the meantime, I assume you are familiar with Harmony? If not, I highly recommend you read up on how to use it.
 
Upvote 0
Alright, turns out that you do not need to use Harmony to patch both of those methods. You can just create a new model and inherit from the existing one.

Each 10 Hearths in villages owned by clan of party leader provide food for 1 soldier per day. S for example if i have 4 villages with 700 Hearths in total i don't need to buy additional food if i have less or equal to 70 men.
This is some very rough code that I came up with. Take note that it doesn't display an extra line in the tooltip at the bottom right corner explaining the food provided by a clan's village hearths. But other than that this code works:

C#:
    public class HearthsProvideFoodModel : DefaultMobilePartyFoodConsumptionModel
    {
        public override ExplainedNumber CalculateDailyFoodConsumptionf(MobileParty party, bool includeDescription = false)
        {
            float num = base.CalculateDailyFoodConsumptionf(party).ResultNumber;
            float num2 = 0;
            if (party.LeaderHero != null)
            {
                foreach (Village village in party.LeaderHero.Clan.Villages)
                {
                    num2 += village.Hearth;
                }
            }
            num += (float)Math.Floor(num2 / 10) * 0.05f;
            num = Math.Min(num, 0);
            return new ExplainedNumber(num, includeDescription);
        }
    }

Clan Leader party gets 60% of that food while other clan parties get equal part of the 40% depending on number of parties. If Clan leader is leading the only party in the clan he gets 100% of the food.
Also take note that I didn't implement this part.
 
Upvote 0

Pejot

Sergeant Knight
WBVC
Alright, turns out that you do not need to use Harmony to patch both of those methods. You can just create a new model and inherit from the existing one.


This is some very rough code that I came up with. Take note that it doesn't display an extra line in the tooltip at the bottom right corner explaining the food provided by a clan's village hearths. But other than that this code works:

C#:
    public class HearthsProvideFoodModel : DefaultMobilePartyFoodConsumptionModel
    {
        public override ExplainedNumber CalculateDailyFoodConsumptionf(MobileParty party, bool includeDescription = false)
        {
            float num = base.CalculateDailyFoodConsumptionf(party).ResultNumber;
            float num2 = 0;
            if (party.LeaderHero != null)
            {
                foreach (Village village in party.LeaderHero.Clan.Villages)
                {
                    num2 += village.Hearth;
                }
            }
            num += (float)Math.Floor(num2 / 10) * 0.05f;
            num = Math.Min(num, 0);
            return new ExplainedNumber(num, includeDescription);
        }
    }


Also take note that I didn't implement this part.


For some reason I cannot mak it run. It crashes the game on start. I tried to create a mod based on that.


C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.SandBox.GameComponents.Map;


namespace VillagesProvideFood
{
    public class Main : DefaultMobilePartyFoodConsumptionModel
    {
        public override ExplainedNumber CalculateDailyFoodConsumptionf(MobileParty party, bool includeDescription = false)
        {
            float num = base.CalculateDailyFoodConsumptionf(party).ResultNumber;
            float num2 = 0;
            if (party.LeaderHero != null)
            {
                foreach (Village village in party.LeaderHero.Clan.Villages)
                {
                    num2 += village.Hearth;
                }
            }
            num += (float)Math.Floor(num2 / 10) * 0.05f;
            num = Math.Min(num, 0);
            return new ExplainedNumber(num, includeDescription);
        }
    }
}
 
Upvote 0
It's not like this. You need to instantiate the model in your SubModule. So you will need to create separate classes for them.

So for example:

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaleWorlds.CampaignSystem;
using TaleWorlds.Core;
using TaleWorlds.MountAndBlade;

namespace VillagesProvideFood
{
    public class Main : MBSubModuleBase
    {
        protected override void OnGameStart(Game game, IGameStarter gameStarter)
        {
            if (game.GameType is Campaign)
            {
                CampaignGameStarter campaignStarter = (CampaignGameStarter)gameStarter;
                campaignStarter.AddModel(new Model());
            }
        }
    }
}

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.SandBox.GameComponents.Map;


namespace VillagesProvideFood
{
    public class Model : DefaultMobilePartyFoodConsumptionModel
    {
        public override ExplainedNumber CalculateDailyFoodConsumptionf(MobileParty party, bool includeDescription = false)
        {
            float num = base.CalculateDailyFoodConsumptionf(party).ResultNumber;
            float num2 = 0;
            if (party.LeaderHero != null)
            {
                foreach (Village village in party.LeaderHero.Clan.Villages)
                {
                    num2 += village.Hearth;
                }
            }
            num += (float)Math.Floor(num2 / 10) * 0.05f;
            num = Math.Min(num, 0);
            return new ExplainedNumber(num, includeDescription);
        }
    }
}
 
Upvote 0
Top Bottom