PabloEscoAlBar
Recruit
Hi! I wanted to edit a perk, let's say Wrapped Handles. Perks are Initialized in DefaultPerks in TaleWorlds.CampaignSystem.CharacterDevelopment.
Here is the code:
Now how do I replace primaryDescription({=dY3GOmTN}{VALUE}% handling to one handed weapons) and primaryBonus (0.2f) using Harmony? Is there a way to replace the Initialize arguments with a Prefix? Or maybe you could re-Initialize the perk at the end of InitiateAll with a Postfix? . A lot of mods change perks so there should be an easy way but I can't figure it out
[UPDATE]
I was able to do it with a Transpiler, so this is a very simple and probably not very efficient code to change Perk's name and primaryBonus, obviously you can change any argument in the Initialize method, you just have to figure out what opcode you want to change and add to index i a corresponding int.
You can easily check ingame that Frugal/Pizza Napoli correctly decreases your party wages by 90%.
I wasn't able to figure out how to access
I found this tutorial really instructive https://research.checkpoint.com/2024/net-hooking-harmonizing-managed-territory/ even tho you have to adapt it to bannerlord.
as another example, less meme, I want to change the Spring Of Gold perk, the new cap is going to be 5000 gold, 0.002 interest rate, the new name of the perk is going to be Banking, I'm also going to change the description of the perk and the part where it's implemented (DefaultClanFinanceModel):
I have to say Transpiler is very powerful and flexible I'm kinda amazed by what it can do.
Here is the code:
C#:
private void InitializeAll()
{
this._oneHandedWrappedHandles.Initialize("{=looKU9Gl}Wrapped Handles", DefaultSkills.OneHanded, this.GetTierCost(1),
this._oneHandedBasher, "{=dY3GOmTN}{VALUE}% handling to one handed weapons.", SkillEffect.PerkRole.Personal, 0.2f,
SkillEffect.EffectIncrementType.AddFactor, "{=0mBHB7mA}{VALUE} one handed skill to infantry troops in your formation.",
SkillEffect.PerkRole.Captain, 30f, SkillEffect.EffectIncrementType.Add, TroopUsageFlags.Undefined, TroopUsageFlags.OneHandedUser);
Now how do I replace primaryDescription({=dY3GOmTN}{VALUE}% handling to one handed weapons) and primaryBonus (0.2f) using Harmony? Is there a way to replace the Initialize arguments with a Prefix? Or maybe you could re-Initialize the perk at the end of InitiateAll with a Postfix? . A lot of mods change perks so there should be an easy way but I can't figure it out
[UPDATE]
I was able to do it with a Transpiler, so this is a very simple and probably not very efficient code to change Perk's name and primaryBonus, obviously you can change any argument in the Initialize method, you just have to figure out what opcode you want to change and add to index i a corresponding int.
C#:
namespace PerkReBalance
{
[HarmonyPatch(typeof(DefaultPerks), "InitializeAll")]
public class Perks
{
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codes)
{
var instructions = new List<CodeInstruction>(codes);
for (var i = 0; i < instructions.Count; i++)
{
if (instructions[i].opcode == OpCodes.Ldstr && (string)instructions[i].operand == "{=looKU9Gl}Wrapped Handles")
{
instructions[i].operand = "{=looKU9Gl}Pizza Margherita";
instructions[i+9].operand = 0.7f;
break;
}
}
for (var i = 0; i < instructions.Count; i++)
{
if (instructions[i].opcode == OpCodes.Ldstr && (string)instructions[i].operand == "{=eJIbMa8P}Frugal")
{
instructions[i].operand = "{=looKU9Gl}Pizza Napoli";
instructions[i+9].operand = -0.90f;
break;
}
}
return instructions.AsEnumerable();
}
}
}
You can easily check ingame that Frugal/Pizza Napoli correctly decreases your party wages by 90%.
I wasn't able to figure out how to access
this._oneHandedWrappedHandles.Initialize
and how to replace the parameters called by value with a prefix, so I resorted to a transpiler, which scared me a lot in the beginning because I didn't know anything about IL. So this is how the code works: since each perk has a unique name the if
looks for a lstr
with operand "{something} the name of the perk" this way you find the perk you want to edit inside the InitialeAll() method and you manipulate the index i so that you move to the opcode you want to change, for example pimaryBonus is 9 indices after name.I found this tutorial really instructive https://research.checkpoint.com/2024/net-hooking-harmonizing-managed-territory/ even tho you have to adapt it to bannerlord.
as another example, less meme, I want to change the Spring Of Gold perk, the new cap is going to be 5000 gold, 0.002 interest rate, the new name of the perk is going to be Banking, I'm also going to change the description of the perk and the part where it's implemented (DefaultClanFinanceModel):
C#:
namespace PerkReBalance
{
[HarmonyPatch(typeof(DefaultPerks), "InitializeAll")]
public class Perks
{
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codes)
{
var instructions = new List<CodeInstruction>(codes);
for (var i = 0; i < instructions.Count; i++)
{
if (instructions[i].opcode == OpCodes.Ldstr && (string)instructions[i].operand == "{=K0SRwH6E}Spring of Gold")
{
instructions[i].operand = "{=looKU9Gl}Banking"; //change name
instructions[i + 7].operand = "{=gu7EN92A}{VALUE}% denars of interest income per day based on your current denars up to 5000 denars."; //change primaryDescription
instructions[i + 9].operand = 0.002f; //change primaryBonus
break;
}
}
return instructions.AsEnumerable();
}
}
[HarmonyPatch(typeof(DefaultClanFinanceModel), "CalculateClanIncomeInternal")]
public class SpringOfGold
{
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codes)
{
var instructions = new List<CodeInstruction>(codes);
for (var i = 0; i < instructions.Count; i++)
{
if (instructions[i].opcode == OpCodes.Ldc_I4 && (int)instructions[i].operand == 1000)
{
instructions[i].operand = 5000; //change value from 1000
break;
}
}
return instructions.AsEnumerable();
}
}
}
I have to say Transpiler is very powerful and flexible I'm kinda amazed by what it can do.
Last edited: