Example #1
0
        private static void ApplySpecialScoring(Apparel apparel, ref float score)
        {
            var specialApparelScoreOffset = apparel.GetSpecialApparelScoreOffset();

            #if DEBUG
            Log.Message($"OutfitManager: Special apparel score offset = {specialApparelScoreOffset}", true);
            #endif
            score += specialApparelScoreOffset;
        }
Example #2
0
        static bool Prefix(ref float __result, JobGiver_OptimizeApparel __instance, Pawn pawn, Apparel ap)
        {
            Log.Message("1 pawn is " + ((pawn == null) ? "null" : "not null"));

            if (pawn != null)
            {
                return(true);
            }
            Log.Message("2");

            if (HitPointsPercentScoreFactorCurve == null)
            {
                HitPointsPercentScoreFactorCurve        = typeof(JobGiver_OptimizeApparel).GetField("HitPointsPercentScoreFactorCurve", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as SimpleCurve;
                InsulationColdScoreFactorCurve_NeedWarm = typeof(JobGiver_OptimizeApparel).GetField("InsulationColdScoreFactorCurve_NeedWarm", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as SimpleCurve;
                NeedWarmthFI = typeof(JobGiver_OptimizeApparel).GetField("neededWarmth", BindingFlags.Static | BindingFlags.NonPublic);
            }
            Log.Message("HitPointsPercentScoreFactorCurve is " + ((HitPointsPercentScoreFactorCurve == null) ? "null" : "not null"));
            Log.Message("InsulationColdScoreFactorCurve_NeedWarm is " + ((InsulationColdScoreFactorCurve_NeedWarm == null) ? "null" : "not null"));
            Log.Message("NeedWarmthFI is " + ((NeedWarmthFI == null) ? "null" : "not null"));
            Log.Message("NeedWarmth is " + NeedWarmthFI.GetValue(null));

            float result = 0.1f + ap.GetStatValue(StatDefOf.ArmorRating_Sharp) + ap.GetStatValue(StatDefOf.ArmorRating_Blunt);

            if (ap.def.useHitPoints)
            {
                float x = (float)ap.HitPoints / (float)ap.MaxHitPoints;
                result *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }
            result += ap.GetSpecialApparelScoreOffset();
            float num3 = 1f;

            if ((NeededWarmth)NeedWarmthFI.GetValue(null) == NeededWarmth.Warm)
            {
                float statValue = ap.GetStatValue(StatDefOf.Insulation_Cold);
                num3 *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue);
            }
            result *= num3;
            if (ap.WornByCorpse)
            {
                result -= 0.5f;
                if (result > 0f)
                {
                    result *= 0.1f;
                }
            }
            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                result -= 0.5f;
                if (result > 0f)
                {
                    result *= 0.1f;
                }
            }
            __result = result;
            return(false);
        }
Example #3
0
        public static float ApparelScoreRaw(Pawn pawn, Apparel apparel, NeededWarmth neededWarmth = NeededWarmth.Any)
        {
            var outfit = pawn.outfits.CurrentOutfit as ExtendedOutfit;

            if (outfit == null)
            {
                Log.ErrorOnce("Outfitted :: Not an ExtendedOutfit, something went wrong.", 399441);
                return(0f);
            }

            float score = 0.1f + ApparelScoreRawPriorities(pawn, apparel, outfit);

            if (outfit.AutoWorkPriorities)
            {
                score += ApparelScoreAutoWorkPriorities(pawn, apparel);
            }

            if (apparel.def.useHitPoints)
            {
                float x = (float)apparel.HitPoints / apparel.MaxHitPoints;
                score *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }
            score += apparel.GetSpecialApparelScoreOffset();

            score += ApparelScoreRawInsulation(pawn, apparel, outfit, neededWarmth);

            if (outfit.PenaltyWornByCorpse && apparel.WornByCorpse && ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }
            }

            if (apparel.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }
                if (ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score += 0.12f;
                }
            }

            return(score);
        }
        public static float GetApparelScore(Pawn pawn, Thing thing)
        {
            Apparel apparel = thing as Apparel;

            if (apparel is ShieldBelt && pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsWeaponUsingProjectiles)
            {
                return(-1000f);
            }

            float score      = 0.1f + apparel.def.apparel.scoreOffset;
            float armorScore = apparel.GetStatValue(StatDefOf.ArmorRating_Sharp) + apparel.GetStatValue(StatDefOf.ArmorRating_Blunt) + apparel.GetStatValue(StatDefOf.ArmorRating_Heat);

            score += armorScore;

            if (apparel.def.useHitPoints)
            {
                float x = (float)apparel.HitPoints / (float)apparel.MaxHitPoints;
                score *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }

            score += apparel.GetSpecialApparelScoreOffset();

            //float warmthScore = 1f;
            //if (neededWarmth == NeededWarmth.Warm)
            //{
            //    float statValue = apparel.GetStatValue(StatDefOf.Insulation_Cold);
            //    warmthScore *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue);
            //}
            //score *= warmthScore;

            // Human body is close enough
            float coverageScore = apparel.def.apparel.HumanBodyCoverage * 10.0f;

            score *= coverageScore;

            return(score);
        }
Example #5
0
        public float ApparelScoreRaw([NotNull] Apparel ap)
        {
            if (RawScoreDict.ContainsKey(ap))
            {
                return(RawScoreDict[ap]);
            }

            // only allow shields to be considered if a primary weapon is equipped and is melee
            var thisPawn = _pawn;

            if (ap.def.thingClass == typeof(ShieldBelt) && thisPawn.equipment.Primary?.def.IsRangedWeapon == true)
            {
                return(-1f);
            }

            // Fail safe to prevent pawns get out of the regular temperature.
            // Might help making pawn drop equipped apparel if it's too cold/warm.
            // this.GetInsulationStats(ap, out float insulationCold, out float insulationHeat);
            // FloatRange temperatureRange = this.pawn.ComfortableTemperatureRange();
            // if (ap.Wearer != thisPawn)
            // {
            // temperatureRange.min += insulationCold;
            // temperatureRange.max += insulationHeat;
            // }
            // if (temperatureRange.min > 12 && insulationCold > 0 || temperatureRange.max < 32 && insulationHeat < 0)
            // {
            // return -3f;
            // }

            // relevant apparel stats
            var entry = GetAllOffsets(ap);

            var statBases       = entry.StatBases;
            var equippedOffsets = entry.EquippedOffsets;
            var infusedOffsets  = entry.InfusedOffsets;

            // start score at 1
            float score = 1;

            // add values for each statdef modified by the apparel
            var stats = thisPawn.GetApparelStatCache().StatCache;

            foreach (var statPriority in stats.Where(statPriority => statPriority != null))
            {
                var stat = statPriority.Stat;

                if (statBases.Contains(stat))
                {
                    var apStat = ap.GetStatValue(stat);

                    if (SpecialStats.Contains(stat))
                    {
                        CalculateScoreForSpecialStats(ap, statPriority, thisPawn, apStat, ref score);
                    }
                    else
                    {
                        // add stat to base score before offsets are handled
                        // (the pawn's apparel stat cache always has armors first as it is initialized with it).
                        score += apStat * statPriority.Weight;
                    }
                }

                // equipped offsets, e.g. movement speeds
                if (equippedOffsets.Contains(stat))
                {
                    var apStat = ap.GetEquippedStatValue(_pawn, stat);

                    if (SpecialStats.Contains(stat))
                    {
                        CalculateScoreForSpecialStats(ap, statPriority, thisPawn, apStat, ref score);
                    }
                    else
                    {
                        score += apStat * statPriority.Weight;
                    }

                    // multiply score to favour items with multiple offsets
                    // score *= adjusted;

                    // debug.AppendLine( statWeightPair.Key.LabelCap + ": " + score );
                }

                // infusions
                if (!infusedOffsets.Contains(stat))
                {
                    continue;
                }

                // float statInfused = StatInfused(infusionSet, statPriority, ref dontcare);
                DoApparelScoreRaw_PawnStatsHandlers(ap, stat, out var statInfused);

                if (SpecialStats.Contains(stat))
                {
                    CalculateScoreForSpecialStats(ap, statPriority, thisPawn, statInfused, ref score);
                }
                else
                {
                    // Bug with Infused and "Ancient", it completely kills the pawn's armor
                    if (statInfused < 0 && (stat == StatDefOf.ArmorRating_Blunt ||
                                            stat == StatDefOf.ArmorRating_Sharp))
                    {
                        score = -2f;
                        return(score);
                    }

                    score += statInfused * statPriority.Weight;
                }
            }

            score += ap.GetSpecialApparelScoreOffset();

            score += ApparelScoreRaw_ProtectionBaseStat(ap);

            // offset for apparel hitpoints
            if (ap.def.useHitPoints)
            {
                var x = ap.HitPoints / (float)ap.MaxHitPoints;
                score *= ApparelStatsHelper.HitPointsPercentScoreFactorCurve.Evaluate(x);
            }

            if (ap.WornByCorpse && ThoughtUtility.CanGetThought_NewTemp(thisPawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }
            }

            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought_NewTemp(thisPawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (ThoughtUtility.CanGetThought_NewTemp(thisPawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score *= 2f;
                }
            }

            score *= ApparelScoreRaw_Temperature(ap);

            RawScoreDict.Add(ap, score);

            return(score);
        }
Example #6
0
        public override void DoWindowContents(Rect inRect)
        {
            var conf = _pawn.GetApparelStatCache();

            var conRect = new Rect(inRect);

            conRect.height -= 50f;

            BeginArea(conRect);

            // begin main group
            BeginVertical();

            Label(GetTitle(), _headline);
            Text.Font = GameFont.Small;

            // GUI.BeginGroup(contentRect);
            var labelWidth = conRect.width - BaseValue - BaseValue - BaseValue - 48f;

            DrawLine("Status", labelWidth, "BaseMod", "Strength", "Score", _fontBold);

            Space(6f);
            Label(string.Empty, _whiteLine, Height(1));
            Space(6f);

            var apparelEntry = conf.GetAllOffsets(_apparel);

            var equippedOffsets = apparelEntry.EquippedOffsets;
            var statBases       = apparelEntry.StatBases;
            var infusedOffsets  = apparelEntry.InfusedOffsets;

            _scrollPosition = BeginScrollView(_scrollPosition, Width(conRect.width));

            // relevant apparel stats

            // start score at 1
            float score = 1;

            // add values for each statdef modified by the apparel
            foreach (var statPriority in _pawn.GetApparelStatCache().StatCache
                     .OrderBy(i => i.Stat.LabelCap))
            {
                var    stat      = statPriority.Stat;
                string statLabel = stat.LabelCap;

                // statbases, e.g. armor

                // StatCache.DoApparelScoreRaw_PawnStatsHandlers(_pawn, _apparel, statPriority.Stat, ref currentStat);
                if (statBases.Contains(stat))
                {
                    var statValue = _apparel.GetStatValue(stat);
                    var statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(_apparel, statPriority, _pawn, statValue,
                                                                       ref statScore);
                    }
                    else
                    {
                        // statValue += StatCache.StatInfused(infusionSet, statPriority, ref baseInfused);
                        statScore = statValue * statPriority.Weight;
                    }

                    score += statScore;

                    DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));
                }

                if (equippedOffsets.Contains(stat))
                {
                    var statValue = _apparel.GetEquippedStatValue(_pawn, stat);

                    // statValue += StatCache.StatInfused(infusionSet, statPriority, ref equippedInfused);
                    var statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(_apparel, statPriority, _pawn, statValue,
                                                                       ref statScore);
                    }
                    else
                    {
                        statScore = statValue * statPriority.Weight;
                    }

                    score += statScore;

                    DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));
                }

                if (!infusedOffsets.Contains(stat))
                {
                    continue;
                }

                {
                    GUI.color = Color.green; // new Color(0.5f, 1f, 1f, 1f);

                    // float statInfused = StatCache.StatInfused(infusionSet, statPriority, ref dontcare);
                    ApparelStatCache.DoApparelScoreRaw_PawnStatsHandlers(_apparel, stat, out var statValue);

                    var flag = true;

                    var statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(_apparel,
                                                                       statPriority, _pawn,
                                                                       statValue,
                                                                       ref statScore);
                    }
                    else
                    {
                        // Bug with Infused and "Ancient", it completely kills the pawn's armor
                        if (statValue < 0 &&
                            (stat == StatDefOf.ArmorRating_Blunt || stat == StatDefOf.ArmorRating_Sharp))
                        {
                            score = -2f;
                            flag  = false;
                        }

                        statScore = statValue * statPriority.Weight;
                    }

                    DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));

                    GUI.color = Color.white;

                    if (flag)
                    {
                        score += statScore;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            GUI.color = Color.white;

            // end upper group
            EndScrollView();

            // begin lower group
            FlexibleSpace();
            Space(6f);
            Label(string.Empty, _whiteLine, Height(1));
            Space(6f);
            DrawLine(string.Empty, labelWidth, "Modifier", string.Empty, "Subtotal");

            DrawLine("BasicStatusOfApparel".Translate(), labelWidth, "1.00", "+", score.ToString("N2"));

            var special = _apparel.GetSpecialApparelScoreOffset();

            if (Math.Abs(special) > 0f)
            {
                score += special;

                DrawLine(
                    "OutfitterSpecialScore".Translate(),
                    labelWidth,
                    special.ToString("N2"),
                    "+",
                    score.ToString("N2"));
            }

            var armor = ApparelStatCache.ApparelScoreRaw_ProtectionBaseStat(_apparel);

            if (Math.Abs(armor) > 0.01f)
            {
                score += armor;

                DrawLine("OutfitterArmor".Translate(), labelWidth, armor.ToString("N2"), "+", score.ToString("N2"));
            }

            if (_apparel.def.useHitPoints)
            {
                // durability on 0-1 scale
                var x = _apparel.HitPoints / (float)_apparel.MaxHitPoints;
                score *= ApparelStatsHelper.HitPointsPercentScoreFactorCurve.Evaluate(x);

                DrawLine(
                    "OutfitterHitPoints".Translate(),
                    labelWidth,
                    x.ToString("N2"),
                    "weighted",
                    score.ToString("N2"));

                GUI.color = Color.white;
            }

            if (_apparel.WornByCorpse && ThoughtUtility.CanGetThought_NewTemp(_pawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }

                DrawLine(
                    "OutfitterWornByCorpse".Translate(),
                    labelWidth,
                    "modified",
                    "weighted",
                    score.ToString("N2"));
            }

            if (_apparel.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought_NewTemp(_pawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (ThoughtUtility.CanGetThought_NewTemp(_pawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score *= 2f;
                }

                DrawLine(
                    "OutfitterHumanLeather".Translate(),
                    labelWidth,
                    "modified",
                    "weighted",
                    score.ToString("N2"));
            }

            var temperature = conf.ApparelScoreRaw_Temperature(_apparel);

            if (Math.Abs(temperature - 1f) > 0)
            {
                score *= temperature;

                DrawLine(
                    "OutfitterTemperature".Translate(),
                    labelWidth,
                    temperature.ToString("N2"),
                    "*",
                    score.ToString("N2"));
            }

            DrawLine(
                "OutfitterTotal".Translate(),
                labelWidth,
                string.Empty,
                "=",
                conf.ApparelScoreRaw(_apparel).ToString("N2"));

            GUI.color   = Color.white;
            Text.Anchor = TextAnchor.UpperLeft;

            // end main group
            EndVertical();
            EndArea();
        }
Example #7
0
        public static float ApparelScoreRaw(Pawn pawn, Apparel ap)
        {
            float num  = 0.1f + ap.def.apparel.scoreOffset;
            float num2 = ap.GetStatValue(StatDefOf.ArmorRating_Sharp) + ap.GetStatValue(StatDefOf.ArmorRating_Blunt) + ap.GetStatValue(StatDefOf.ArmorRating_Heat);

            num += num2;
            if (ap.def.useHitPoints)
            {
                float x = (float)ap.HitPoints / (float)ap.MaxHitPoints;
                num *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }
            num += ap.GetSpecialApparelScoreOffset();
            float num3 = 1f;

            //if (neededWarmth == NeededWarmth.Warm)
            //{
            //	float statValue = ap.GetStatValue(StatDefOf.Insulation_Cold);
            //	num3 *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue);
            //}
            num *= num3;
            if (ap.WornByCorpse && (pawn == null || ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.DeadMansApparel, checkIfNullified: true)))
            {
                num -= 0.5f;
                if (num > 0f)
                {
                    num *= 0.1f;
                }
            }
            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (pawn == null || ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelSad, checkIfNullified: true))
                {
                    num -= 0.5f;
                    if (num > 0f)
                    {
                        num *= 0.1f;
                    }
                }
                if (pawn != null && ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelHappy, checkIfNullified: true))
                {
                    num += 0.12f;
                }
            }
            if (pawn != null && !ap.def.apparel.CorrectGenderForWearing(pawn.gender))
            {
                num *= 0.01f;
            }
            if (pawn != null && pawn.royalty != null && pawn.royalty.AllTitlesInEffectForReading.Count > 0)
            {
                tmpAllowedApparels.Clear();
                tmpRequiredApparels.Clear();
                tmpBodyPartGroupsWithRequirement.Clear();
                QualityCategory qualityCategory = QualityCategory.Awful;
                foreach (RoyalTitle item in pawn.royalty.AllTitlesInEffectForReading)
                {
                    if (item.def.requiredApparel != null)
                    {
                        for (int i = 0; i < item.def.requiredApparel.Count; i++)
                        {
                            tmpAllowedApparels.AddRange(item.def.requiredApparel[i].AllAllowedApparelForPawn(pawn, ignoreGender: false, includeWorn: true));
                            tmpRequiredApparels.AddRange(item.def.requiredApparel[i].AllRequiredApparelForPawn(pawn, ignoreGender: false, includeWorn: true));
                            tmpBodyPartGroupsWithRequirement.AddRange(item.def.requiredApparel[i].bodyPartGroupsMatchAny);
                        }
                    }
                    if ((int)item.def.requiredMinimumApparelQuality > (int)qualityCategory)
                    {
                        qualityCategory = item.def.requiredMinimumApparelQuality;
                    }
                }
                bool num4 = ap.def.apparel.bodyPartGroups.Any((BodyPartGroupDef bp) => tmpBodyPartGroupsWithRequirement.Contains(bp));
                if (ap.TryGetQuality(out QualityCategory qc) && (int)qc < (int)qualityCategory)
                {
                    num *= 0.25f;
                }
                if (num4)
                {
                    foreach (ThingDef tmpRequiredApparel in tmpRequiredApparels)
                    {
                        tmpAllowedApparels.Remove(tmpRequiredApparel);
                    }
                    if (tmpAllowedApparels.Contains(ap.def))
                    {
                        num *= 10f;
                    }
                    if (tmpRequiredApparels.Contains(ap.def))
                    {
                        num *= 25f;
                    }
                }
            }
            return(num);
        }
        public static float ApparelScoreRaw(Pawn pawn, Apparel apparel, NeededWarmth neededWarmth = NeededWarmth.Any)
        {
            var outfit = pawn?.outfits?.CurrentOutfit as ExtendedOutfit;

            if (pawn != null && outfit == null)
            {
                Log.ErrorOnce("Outfitted :: Not an ExtendedOutfit, something went wrong.", 399441);
                return(0f);
            }

            float score = 0.1f + ApparelScoreRawPriorities(apparel, outfit);

            if (pawn != null && outfit?.AutoWorkPriorities == true)
            {
                score += ApparelScoreAutoWorkPriorities(pawn, apparel);
            }

            if (apparel.def.useHitPoints)
            {
                float x = (float)apparel.HitPoints / apparel.MaxHitPoints;
                score *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }

            score += apparel.GetSpecialApparelScoreOffset();

            if (pawn != null && outfit != null)
            {
                score += ApparelScoreRawInsulation(pawn, apparel, outfit, neededWarmth);
            }

            if (pawn?.def?.race?.Animal == false)
            {
                if (outfit?.PenaltyWornByCorpse == true && apparel.WornByCorpse && ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.DeadMansApparel, true))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (apparel.Stuff == ThingDefOf.Human.race.leatherDef)
                {
                    if (ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelSad, true))
                    {
                        score -= 0.5f;
                        if (score > 0f)
                        {
                            score *= 0.1f;
                        }
                    }
                    if (ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelHappy, true))
                    {
                        score += 0.12f;
                    }
                }
            }

            //royalty titles
            if (pawn?.royalty?.AllTitlesInEffectForReading?.Count > 0)
            {
                HashSet <ThingDef>         tmpAllowedApparels  = new HashSet <ThingDef>();
                HashSet <ThingDef>         tmpRequiredApparels = new HashSet <ThingDef>();
                HashSet <BodyPartGroupDef> tmpBodyPartGroupsWithRequirement = new HashSet <BodyPartGroupDef>();
                QualityCategory            qualityCategory = QualityCategory.Awful;
                foreach (RoyalTitle item in pawn.royalty.AllTitlesInEffectForReading)
                {
                    if (item.def.requiredApparel != null)
                    {
                        for (int i = 0; i < item.def.requiredApparel.Count; i++)
                        {
                            tmpAllowedApparels.AddRange(item.def.requiredApparel[i].AllAllowedApparelForPawn(pawn, ignoreGender: false, includeWorn: true));
                            tmpRequiredApparels.AddRange(item.def.requiredApparel[i].AllRequiredApparelForPawn(pawn, ignoreGender: false, includeWorn: true));
                            tmpBodyPartGroupsWithRequirement.AddRange(item.def.requiredApparel[i].bodyPartGroupsMatchAny);
                        }
                    }
                    if (item.def.requiredMinimumApparelQuality > qualityCategory)
                    {
                        qualityCategory = item.def.requiredMinimumApparelQuality;
                    }
                }

                if (apparel.TryGetQuality(out QualityCategory qc) && qc < qualityCategory)
                {
                    score *= 0.25f;
                }

                bool isRequired = apparel.def.apparel.bodyPartGroups.Any(bp => tmpBodyPartGroupsWithRequirement.Contains(bp));
                if (isRequired)
                {
                    foreach (ThingDef tmpRequiredApparel in tmpRequiredApparels)
                    {
                        tmpAllowedApparels.Remove(tmpRequiredApparel);
                    }
                    if (tmpAllowedApparels.Contains(apparel.def))
                    {
                        score *= 10f;
                    }
                    if (tmpRequiredApparels.Contains(apparel.def))
                    {
                        score *= 25f;
                    }
                }
            }

            return(score);
        }