At the moment we cannot create our own Traits (More specifically battle skill traits) as the class that controls them is sealed. Can we have this class open to allow for more customised lords?
Oh sweet. When me and another coder were looking into it it looked like it was sealed away@TheREALHayster we don't have a class that controls them, you can add traits through mbobjectmanager.
public static TraitObject Surgery
{
get
{
return DefaultTraits.Instance._traitSurgery;
}
}
public DefaultTraits DefaultTraits { get; private set; }
So it's entirely possible but I would basically have to reverse engineer one of the games dlls (which i'm pretty sure is against the terms of use). Yeah definitely excessiveI would say, i saw this message telling us we could add or change traits, so i had a look at it and ... We don't have the same definition of what can be changed.
So first i took a look at how the game was dealing with the traits and all is dealt in the class TaleWorlds.CampaignSystem.DefaultTraits.
Inside you can see how traits are created and how they use the Game.Current.ObjectManager.RegisterPresumedObject<TraitObject>(new TraitObject(stringId)); to add more just like they would with any object.
So yes, basically we can add traits, but the issue comes to when and how to use them. I'm going back to the DefaultTraits class, every TraitObject have it's reference stored in a private variable to be accessed, here the example of surgery :
as it looks really hardcoded to me, no way to add more like it would be possible in a dict. So if you want to add or change traits you need to make your own class to make them accessible. DefaultTraits isn't derived from any other class we could implement and even worst in TaleWorlds.CampaignSystem.Campaign the game is wanting exactly a DefaultTraits class and not one you would write yourself :Code:public static TraitObject Surgery { get { return DefaultTraits.Instance._traitSurgery; } }
So to be able to change traits, but i looked a bit around and it's the same with perks, you need to rewrite the whole campaign class? Looks like a bit excessive right?Code:public DefaultTraits DefaultTraits { get; private set; }
var myTrait = Game.Current.ObjectManager.RegisterPresumedObject(new TraitObject("my_trait_id"));
myTrait.Initialize(
new TextObject("{=!}Name"),
new TextObject("{=!}Description"),
true,
-2, 2);
Campaign.Current.PlayerTraitDeveloper.AddTraitXp(myTrait, 50);
hero.SetTraitLevelInternal(myTrait, 1);
hero.GetTraitLevel(myTrait);
Campaign.Current.ObjectManager.GetObject<TraitObject>("my_trait_id");
If you get it going could you share how the code is laid out.Will give it a try, thank you.
Maybe you want to pin that somewhere or add it to the documentation, this could be useful.
using System;
using System.Collections.Generic;
using TaleWorlds.CampaignSystem;
using TaleWorlds.Core;
using TaleWorlds.Localization;
namespace LoOTGA
{
public class LoOTraits
{
public static LoOTraits instance { get { return ((TheGuildAge)TheGuildAge.instance).looTraits; } }
public static TraitObject MountedCrossbow { get { return instance.listTraits["MountedCrossbowman"]; } }
private Dictionary<string, TraitObject> listTraits = new Dictionary<string, TraitObject>();
public LoOTraits()
{
listTraits["MountedCrossbowman"] = createTrait("MountedCrossbowman", "MountedCrossbowman", "MountedCrossbowman Description");
}
public TraitObject createTrait(string id, string name, string desc, bool visible=false, int min = 0, int max=10)
{
TraitObject temp = Game.Current.ObjectManager.RegisterPresumedObject(new TraitObject(id));
temp.Initialize(new TextObject(name), new TextObject(desc), visible, min, max);
return temp;
}
}
}
ok thanksWell if you wish i share my code
Code:using System; using System.Collections.Generic; using TaleWorlds.CampaignSystem; using TaleWorlds.Core; using TaleWorlds.Localization; namespace LoOTGA { public class LoOTraits { public static LoOTraits instance { get { return ((TheGuildAge)TheGuildAge.instance).looTraits; } } public static TraitObject MountedCrossbow { get { return instance.listTraits["MountedCrossbowman"]; } } private Dictionary<string, TraitObject> listTraits = new Dictionary<string, TraitObject>(); public LoOTraits() { listTraits["MountedCrossbowman"] = createTrait("MountedCrossbowman", "MountedCrossbowman", "MountedCrossbowman Description"); } public TraitObject createTrait(string id, string name, string desc, bool visible=false, int min = 0, int max=10) { TraitObject temp = Game.Current.ObjectManager.RegisterPresumedObject(new TraitObject(id)); temp.Initialize(new TextObject(name), new TextObject(desc), visible, min, max); return temp; } } }
This is the class i made to copy the defaultTraits TW class, it works mostly the same even if the internal is a bit different. I instanciate it in my submodule class with an "instance trick" to have it accessible from everywhere with TheGuildAge.instance and where i could set my global variables.
So far there is no error in VS but i can't really test how it is working cause i need to deal with the other issue related to character generation i have mentioned here, forcing me to recreate full classes of the game to be able to initialize correctly my heroes once i have changed HeroCreationCampaignBehavior to reflect the changes i made in the traits.
So i can't really tell if it's fully working until it's complete.
How do i use this with regard the code?hero.SetTraitLevelInternal(myTrait, 1);
I also have this in the submodule replacing the parts the I believed need to be replaced but the trait isn't firing correctly. The game isn't crashing but the skills won't apply. I can share the various codes if you need although I have posted them in the Discord.Trait = Game.Current.ObjectManager.RegisterPresumedObject(new TraitObject("my_trait_id")); myTrait.Initialize( new TextObject("{=!}Name"), new TextObject("{=!}Description"), true, -2, 2);