Remove a trait

Started by battlemage64, January 05, 2018, 02:37:21 PM

Previous topic - Next topic

battlemage64

How do I remove a colonist's trait with C#? I want to change the degree of/remove a trait but the only methods in (pawn).story.traits give a read-only list and a read-only degree. Is there a method somewhere that can remove the trait so I can put it back at a different degree?
I love to mod and boy am I bad at it

BrokenValkyrie

I had a look at polaris core mod, which had trait removal as a feature.

This isn't polaris core code, their trait selection is far more involved.

//You can use random weight element.
Trait tempTrait = pawn.story.traits.allTraits[0];
pawn.story.traits.allTraits.Remove(tempTrait);

battlemage64

Hey, it worked this time! Thanks! Last time I tried editing allTraits, it said it was read-only. I guess Remove() still works.
I love to mod and boy am I bad at it

jamaicancastle

There are some other things you'll need to do. (This is from the core addTrait method):

if (pawn.workSettings != null)
{
pawn.workSettings.Notify_GainedTrait();
}
pawn.story.Notify_TraitChanged();
if (pawn.skills != null)
{
pawn.skills.Notify_SkillDisablesChanged();
}
if (!pawn.Dead && pawn.RaceProps.Humanlike)
{
pawn.needs.mood.thoughts.situational.Notify_SituationalThoughtsDirty();
}


Basically pawns cache a bunch of trait-related stuff (disabled skills and the like) so they don't have to look it up every time. All these calls do is tell the pawn that it needs to recheck its cached data. If you don't, the pawns will continue to have cached data from their old trait(s).

battlemage64

#4
Yeah, I found out there's more the hard way...

Also, when I try to use the code you gave, I found that pawn.story.Notify_TraitChanged doesn't exist. When I just delete the line, it still doesn't work.

Tomorrow I'm going to try fully rewriting the removal code to instead scroll through traits.allTraits and remove every one that is wrong because I don't think it's even removing the trait at all. It still shows up in Traits.
I love to mod and boy am I bad at it

jamaicancastle

Quote from: battlemage64 on January 05, 2018, 10:00:15 PM
Also, when I try to use the code you gave, I found that pawn.story.Notify_TraitChanged doesn't exist. When I just delete the line, it still doesn't work.
That's... odd. ILSpy says it should be a method of Pawn_StoryTracker, which should be the class of pawn.story (assuming the pawn has a story, which if you've gotten this far without errors should be the case).

BrokenValkyrie

#6
Quote from: jamaicancastle on January 05, 2018, 11:16:30 PM
Quote from: battlemage64 on January 05, 2018, 10:00:15 PM
Also, when I try to use the code you gave, I found that pawn.story.Notify_TraitChanged doesn't exist. When I just delete the line, it still doesn't work.
That's... odd. ILSpy says it should be a method of Pawn_StoryTracker, which should be the class of pawn.story (assuming the pawn has a story, which if you've gotten this far without errors should be the case).

Unfortunately that method protected by internal keyword. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/internal . Its similar to protected access modifier.

    internal void Notify_TraitChanged()
    {
      this.cachedDisabledWorkTypes = (List<WorkTypeDef>) null;
    }


Unfortunately the cache is protected with private. I don't know how to get around the issue as I am yet to get around it myself.

I've read that harmony can access any method or field, regardless of access protection. I hadn't yet used harmony in this fashion.

battlemage64

Well, is there any other way to remove a trait?
I love to mod and boy am I bad at it

battlemage64

Okay, I rewrote the code so it scrolls through the traits and finds the one it wants, then deletes the item by index. It then breaks, assuming that a colonist only has 1 of a multiple-degree trait because that's true always in default game, and I can handle special cases later. It works now and I think the issue is fixed. Thanks again, forum, for solving all my problems!
I love to mod and boy am I bad at it