[SOLVED] Enable/Disable Work Type (Capable vs Incapable)

Started by O Negative, January 02, 2019, 09:48:29 PM

Previous topic - Next topic

O Negative

It is fairly easy to disable a pawn's work settings, by using pawn.workSettings.DisableAll();

However, this does not make a pawn incapable of all work types, it just unticks the work from being assigned to that pawn.

My question is: Is it possible to reasonably make a pawn capable or incapable of a given work type without assigning a new backstory? If so, where do I start?

Razuhl

You can also use a custom trait. Look at the Pyromaniac trait, it disables firefighting.

You can patch SkillDef.IsDisabled with a postfix harmony patch that returns a value based on your own criteria.

O Negative

AH! I forgot all about traits! I think I'll definitely be using that for the initial "Make Incapable" I'm looking for with certain pawns. However, when I go to make them capable again, I've found the method needed to do so after quite a bit of playing in Visual Studio.


// This will make a pawn incapable of the work type given as the argument, and disable associated skills.
pawn.story.DisabledWorkTypes.Add(WorkTypeDef w);

// This will make pawns capable of the work type given as the argument, but will NOT enable associated skills.
pawn.story.DisabledWorkTypes.Remove(WorkTypeDef w);

// This will make pawns capable of every work type again
pawn.story.DisabledWorkTypes.Clear();


I've found that when enabling work-types, it is necessary to re-make the SkillRecord of all associated re-enabled work-types. If that makes sense xD So, what I do, is this:


// Disable the work-type of "Warden"; Effectively disables the "Social" SkillRecord, making it so that the pawn cannot learn the skill at all.
pawn.story.DisabledWorkTypes.Add(WorkTypeDefOf.Warden);

// It's just good practice to implement checks before removing things from lists :P
if(pawn.story.DisabledWorkTypes.Contains(WorkTypeDefOf.Warden)
{
// This will re-enable the work-type of warden. In the game, this just means the pawn can be assigned to the "Warden" task again. However, the "Social" skill is still DISABLED.
pawn.story.DisabledWorkTypes.Remove(WorkTypeDefOf.Warden);
}

// THIS PART IS UNTESTED; It is a stub of some code that I've used and tested, though.
// Declare a new SkillRecord
SkillRecord cleanSocial = new SkillRecord(pawn, SkillDefOf.Social);
// Assign the clean SkillRecord to the pawn
pawn.skills.skills.Add(cleanSocial);

// The pawn now has an enabled SkillRecord for the "Social" skill type, though the level is set to 0, as is the total xp

Razuhl

You should follow the code in TraitSet.GainTrait to rebuild the pawns skill cache and other dependencies.


if (pawn.workSettings != null) {
pawn.workSettings.Notify_GainedTrait();
}
//p.story.Notify_TraitChanged();
pawn.story.GetType().GetMethod("Notify_TraitChanged", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(pawn.story,null);

if (pawn.skills != null) {
//This does only reset the cached value wheter or not a skill is completely disabled. It does not drop weapons if the pawn becomes unable to use violence etc.
pawn.skills.Notify_SkillDisablesChanged();
}
if (!pawn.Dead && pawn.RaceProps.Humanlike) {
pawn.needs.mood.thoughts.situational.Notify_SituationalThoughtsDirty();
}


Also when the pawn becomes unable to wield a melee or ranged weapon you must force them to drop it to avoid errors when the aiming tooltip is calculated.


//In case a pawn is unable to use specific equipment we can try to drop it
if ( pawn.skills.GetSkill(SkillDefOf.Shooting).TotallyDisabled && pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsWithinCategory(DefDatabase<ThingCategoryDef>.GetNamed("WeaponsRanged")) ) {
ThingWithComps thingWithComps;
if ( !pawn.equipment.TryDropEquipment(pawn.equipment.Primary,out thingWithComps,pawn.Position, false) ) {
Log.Message("Pawn with disabled shooting skill has a ranged weapon equipped that could not be dropped!");
}
}
if ( pawn.skills.GetSkill(SkillDefOf.Melee).TotallyDisabled && pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsWithinCategory(DefDatabase<ThingCategoryDef>.GetNamed("WeaponsMelee")) ) {
ThingWithComps thingWithComps;
if ( !pawn.equipment.TryDropEquipment(pawn.equipment.Primary,out thingWithComps,pawn.Position, false) ) {
Log.Message("Pawn with disabled melee skill has a melee weapon equipped that could not be dropped!");
}
}