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; }
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); }
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); }
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); }
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(); }
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); }