public bool SatisfiesNeededWarmth(NeededWarmth warmth, bool mustBeSafe = false, float mapTemperature = 21f) { bool result; if (warmth == NeededWarmth.Any) { result = true; } else if (mustBeSafe && !GenTemperature.SafeTemperatureRange(this.raceDef, this.aps).Includes(mapTemperature)) { result = false; } else if (warmth == NeededWarmth.Cool) { float num = this.aps.Sum((ThingStuffPair a) => a.InsulationHeat); result = (num >= -2f); } else { if (warmth != NeededWarmth.Warm) { throw new NotImplementedException(); } float num2 = this.aps.Sum((ThingStuffPair a) => a.InsulationCold); result = (num2 >= 52f); } return(result); }
public bool SatisfiesNeededWarmth(NeededWarmth warmth, bool mustBeSafe = false, float mapTemperature = 21f) { if (warmth == NeededWarmth.Any) { return(true); } if (!mustBeSafe || GenTemperature.SafeTemperatureRange(raceDef, aps).Includes(mapTemperature)) { switch (warmth) { case NeededWarmth.Cool: { float num2 = aps.Sum((ThingStuffPair a) => a.InsulationHeat); return(num2 >= -2f); } case NeededWarmth.Warm: { float num = aps.Sum((ThingStuffPair a) => a.InsulationCold); return(num >= 52f); } default: throw new NotImplementedException(); } } 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); }
static bool Prefix(Pawn pawn, Apparel ap, out float __result, NeededWarmth ___neededWarmth) { //if (pawn == null) { // __result = float.NaN; // return true; //} __result = OutfittedMod.ApparelScoreRaw(pawn, ap, ___neededWarmth); return(false); }
private static NeededWarmth ApparelWarmthNeededNow(Pawn pawn, PawnGenerationRequest request, out float mapTemperature) { int tile = request.Tile; if (tile == -1) { Map anyPlayerHomeMap = Find.AnyPlayerHomeMap; if (anyPlayerHomeMap != null) { tile = anyPlayerHomeMap.Tile; } } NeededWarmth result; if (tile == -1) { mapTemperature = 21f; result = NeededWarmth.Any; } else { NeededWarmth neededWarmth = NeededWarmth.Any; Twelfth twelfth = GenLocalDate.Twelfth(tile); mapTemperature = GenTemperature.AverageTemperatureAtTileForTwelfth(tile, twelfth); for (int i = 0; i < 2; i++) { NeededWarmth neededWarmth2 = PawnApparelGenerator.CalculateNeededWarmth(pawn, tile, twelfth); if (neededWarmth2 != NeededWarmth.Any) { neededWarmth = neededWarmth2; break; } twelfth = twelfth.NextTwelfth(); } if (pawn.kindDef.apparelIgnoreSeasons) { if (request.ForceAddFreeWarmLayerIfNeeded && neededWarmth == NeededWarmth.Warm) { result = neededWarmth; } else { result = NeededWarmth.Any; } } else { result = neededWarmth; } } return(result); }
public static Thing PickBestArmorFor(Pawn pawn) { if (pawn.outfits == null) { return(null); } if (pawn.Faction != Faction.OfPlayer) { return(null); } if (pawn.IsQuestLodger()) { return(null); } Outfit currentOutfit = pawn.outfits.CurrentOutfit; Thing thing = null; float num2 = 0f; List <Thing> list = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel); if (list.Count == 0) { return(null); } neededWarmth = PawnApparelGenerator.CalculateNeededWarmth(pawn, pawn.Map.Tile, GenLocalDate.Twelfth(pawn)); wornApparelScores = new List <float>(); List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int i = 0; i < wornApparel.Count; i++) { wornApparelScores.Add(ApparelScoreRaw(pawn, wornApparel[i])); } for (int j = 0; j < list.Count; j++) { Apparel apparel = (Apparel)list[j]; // && apparel.IsInAnyStorage() if (!apparel.IsBurning() && currentOutfit.filter.Allows(apparel) && !apparel.IsForbidden(pawn) && (apparel.def.apparel.gender == Gender.None || apparel.def.apparel.gender == pawn.gender)) { float num3 = ApparelScoreGain_NewTmp(pawn, apparel, wornApparelScores); if (!(num3 < 0.05f) && !(num3 < num2) && (!CompBiocodable.IsBiocoded(apparel) || CompBiocodable.IsBiocodedFor(apparel, pawn)) && ApparelUtility.HasPartsToWear(pawn, apparel.def) && pawn.CanReserveAndReach(apparel, PathEndMode.OnCell, pawn.NormalMaxDanger())) { thing = apparel; num2 = num3; } } } return(thing); }
public bool SatisfiesNeededWarmth(NeededWarmth warmth, bool mustBeSafe = false, float mapTemperature = 21f) { if (warmth == NeededWarmth.Any) { return(true); } if (mustBeSafe && !GenTemperature.SafeTemperatureRange(raceDef, aps).Includes(mapTemperature)) { return(false); } return(warmth switch { NeededWarmth.Cool => aps.Sum((ThingStuffPair a) => a.InsulationHeat) >= -2f, NeededWarmth.Warm => aps.Sum((ThingStuffPair a) => a.InsulationCold) >= 52f, _ => throw new NotImplementedException(), });
protected override Job TryGiveJob(Pawn pawn) { Job result; if (pawn.outfits == null) { Log.ErrorOnce(pawn + " tried to run JobGiver_OptimizeApparel without an OutfitTracker", 5643897, false); result = null; } else if (pawn.Faction != Faction.OfPlayer) { Log.ErrorOnce("Non-colonist " + pawn + " tried to optimize apparel.", 764323, false); result = null; } else { if (!DebugViewSettings.debugApparelOptimize) { if (Find.TickManager.TicksGame < pawn.mindState.nextApparelOptimizeTick) { return(null); } } else { JobGiver_OptimizeApparel.debugSb = new StringBuilder(); JobGiver_OptimizeApparel.debugSb.AppendLine(string.Concat(new object[] { "Scanning for ", pawn, " at ", pawn.Position })); } Outfit currentOutfit = pawn.outfits.CurrentOutfit; List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int i = wornApparel.Count - 1; i >= 0; i--) { if (!currentOutfit.filter.Allows(wornApparel[i]) && pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[i])) { return(new Job(JobDefOf.RemoveApparel, wornApparel[i]) { haulDroppedApparel = true }); } } Thing thing = null; float num = 0f; List <Thing> list = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel); if (list.Count == 0) { this.SetNextOptimizeTick(pawn); result = null; } else { JobGiver_OptimizeApparel.neededWarmth = PawnApparelGenerator.CalculateNeededWarmth(pawn, pawn.Map.Tile, GenLocalDate.Twelfth(pawn)); for (int j = 0; j < list.Count; j++) { Apparel apparel = (Apparel)list[j]; if (currentOutfit.filter.Allows(apparel)) { if (apparel.IsInAnyStorage()) { if (!apparel.IsForbidden(pawn)) { float num2 = JobGiver_OptimizeApparel.ApparelScoreGain(pawn, apparel); if (DebugViewSettings.debugApparelOptimize) { JobGiver_OptimizeApparel.debugSb.AppendLine(apparel.LabelCap + ": " + num2.ToString("F2")); } if (num2 >= 0.05f && num2 >= num) { if (ApparelUtility.HasPartsToWear(pawn, apparel.def)) { if (pawn.CanReserveAndReach(apparel, PathEndMode.OnCell, pawn.NormalMaxDanger(), 1, -1, null, false)) { thing = apparel; num = num2; } } } } } } } if (DebugViewSettings.debugApparelOptimize) { JobGiver_OptimizeApparel.debugSb.AppendLine("BEST: " + thing); Log.Message(JobGiver_OptimizeApparel.debugSb.ToString(), false); JobGiver_OptimizeApparel.debugSb = null; } if (thing == null) { this.SetNextOptimizeTick(pawn); result = null; } else { result = new Job(JobDefOf.Wear, thing); } } } return(result); }
public static void GenerateStartingApparelFor(Pawn pawn, PawnGenerationRequest request) { if (pawn.RaceProps.ToolUser && pawn.RaceProps.IsFlesh) { if (pawn.Faction == null) { Log.Error("Cannot generate apparel for faction-less pawn " + pawn); } else { pawn.apparel.DestroyAll(DestroyMode.Vanish); float randomInRange = pawn.kindDef.apparelMoney.RandomInRange; float mapTemperature = default(float); NeededWarmth neededWarmth = PawnApparelGenerator.ApparelWarmthNeededNow(pawn, request, out mapTemperature); bool flag = Rand.Value < pawn.kindDef.apparelAllowHeadwearChance; PawnApparelGenerator.debugSb = null; if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb = new StringBuilder(); PawnApparelGenerator.debugSb.AppendLine("Generating apparel for " + pawn); PawnApparelGenerator.debugSb.AppendLine("Money: " + randomInRange.ToString("F0")); PawnApparelGenerator.debugSb.AppendLine("Needed warmth: " + neededWarmth); PawnApparelGenerator.debugSb.AppendLine("Headwear allowed: " + flag); } if (randomInRange >= 0.0010000000474974513) { int num = 0; while (true) { PawnApparelGenerator.GenerateWorkingPossibleApparelSetFor(pawn, randomInRange, flag); if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.Append(num.ToString().PadRight(5) + "Trying: " + PawnApparelGenerator.workingSet.ToString()); } if (num < 10 && Rand.Value < 0.85000002384185791) { float num2 = Rand.Range(0.45f, 0.8f); float totalPrice = PawnApparelGenerator.workingSet.TotalPrice; if (totalPrice < randomInRange * num2) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Spent $" + totalPrice.ToString("F0") + ", < " + ((float)(num2 * 100.0)).ToString("F0") + "% of money."); } goto IL_036d; } } if (num < 20 && Rand.Value < 0.97000002861022949 && !PawnApparelGenerator.workingSet.Covers(BodyPartGroupDefOf.Torso)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Does not cover torso."); } } else if (num < 30 && Rand.Value < 0.800000011920929 && PawnApparelGenerator.workingSet.CoatButNoShirt()) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Coat but no shirt."); } } else { if (num < 50) { bool mustBeSafe = num < 17; if (!PawnApparelGenerator.workingSet.SatisfiesNeededWarmth(neededWarmth, mustBeSafe, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Wrong warmth."); } goto IL_036d; } } if (num >= 80) { break; } if (!PawnApparelGenerator.workingSet.IsNaked(pawn.gender)) { break; } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Naked."); } } goto IL_036d; IL_036d: num++; } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.Append(" -- Approved! Total price: $" + PawnApparelGenerator.workingSet.TotalPrice.ToString("F0") + ", TotalInsulationCold: " + PawnApparelGenerator.workingSet.TotalInsulationCold); } } if ((!pawn.kindDef.apparelIgnoreSeasons || request.ForceAddFreeWarmLayerIfNeeded) && !PawnApparelGenerator.workingSet.SatisfiesNeededWarmth(neededWarmth, false, 21f)) { PawnApparelGenerator.workingSet.AddFreeWarmthAsNeeded(neededWarmth); } if (DebugViewSettings.logApparelGeneration) { Log.Message(PawnApparelGenerator.debugSb.ToString()); } PawnApparelGenerator.workingSet.GiveToPawn(pawn); PawnApparelGenerator.workingSet.Reset(null, null); } } }
public void AddFreeWarmthAsNeeded(NeededWarmth warmth) { if (warmth != 0 && warmth != NeededWarmth.Cool) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(); PawnApparelGenerator.debugSb.AppendLine("Trying to give free warm layer."); } if (!this.SatisfiesNeededWarmth(warmth, false, 21f)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Checking to give free torso-cover at max price " + PawnApparelGenerator.freeWarmParkaMaxPrice); } Predicate <ThingStuffPair> parkaPairValidator = delegate(ThingStuffPair pa) { if (pa.Price > PawnApparelGenerator.freeWarmParkaMaxPrice) { return(false); } if (pa.InsulationCold > -40.0) { return(false); } return(true); }; ThingStuffPair parkaPair; if ((from pa in PawnApparelGenerator.allApparelPairs where parkaPairValidator(pa) select pa).TryRandomElementByWeight <ThingStuffPair>((Func <ThingStuffPair, float>)((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price)), out parkaPair)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Giving free torso-cover: " + parkaPair + " insulation=" + parkaPair.InsulationCold); foreach (ThingStuffPair item in from a in this.aps where !ApparelUtility.CanWearTogether(a.thing, parkaPair.thing, this.body) select a) { PawnApparelGenerator.debugSb.AppendLine(" -replaces " + item.ToString() + " InsulationCold=" + item.InsulationCold); } } this.aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, parkaPair.thing, this.body)); this.aps.Add(parkaPair); } } if (!this.SatisfiesNeededWarmth(warmth, false, 21f)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Checking to give free hat at max price " + PawnApparelGenerator.freeWarmHatMaxPrice); } Predicate <ThingStuffPair> hatPairValidator = delegate(ThingStuffPair pa) { if (pa.Price > PawnApparelGenerator.freeWarmHatMaxPrice) { return(false); } if (pa.InsulationCold > -7.0) { return(false); } if (!pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead) && !pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead)) { return(false); } return(true); }; ThingStuffPair hatPair; if ((from pa in PawnApparelGenerator.allApparelPairs where hatPairValidator(pa) select pa).TryRandomElementByWeight <ThingStuffPair>((Func <ThingStuffPair, float>)((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price)), out hatPair)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Giving free hat: " + hatPair + " insulation=" + hatPair.InsulationCold); foreach (ThingStuffPair item2 in from a in this.aps where !ApparelUtility.CanWearTogether(a.thing, hatPair.thing, this.body) select a) { PawnApparelGenerator.debugSb.AppendLine(" -replaces " + item2.ToString() + " InsulationCold=" + item2.InsulationCold); } } this.aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, hatPair.thing, this.body)); this.aps.Add(hatPair); } } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("New TotalInsulationCold: " + this.TotalInsulationCold); } } }
public static void GenerateStartingApparelFor(Pawn pawn, PawnGenerationRequest request) { if (!pawn.RaceProps.ToolUser || !pawn.RaceProps.IsFlesh) { return; } pawn.apparel.DestroyAll(DestroyMode.Vanish); float randomInRange = pawn.kindDef.apparelMoney.RandomInRange; float mapTemperature; NeededWarmth neededWarmth = PawnApparelGenerator.ApparelWarmthNeededNow(pawn, request, out mapTemperature); bool flag = Rand.Value < pawn.kindDef.apparelAllowHeadgearChance; PawnApparelGenerator.debugSb = null; if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb = new StringBuilder(); PawnApparelGenerator.debugSb.AppendLine("Generating apparel for " + pawn); PawnApparelGenerator.debugSb.AppendLine("Money: " + randomInRange.ToString("F0")); PawnApparelGenerator.debugSb.AppendLine("Needed warmth: " + neededWarmth); PawnApparelGenerator.debugSb.AppendLine("Headgear allowed: " + flag); } if (randomInRange < 0.001f) { PawnApparelGenerator.GenerateWorkingPossibleApparelSetFor(pawn, randomInRange, flag); } else { int num = 0; for (;;) { PawnApparelGenerator.GenerateWorkingPossibleApparelSetFor(pawn, randomInRange, flag); if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.Append(num.ToString().PadRight(5) + "Trying: " + PawnApparelGenerator.workingSet.ToString()); } if (num >= 10 || Rand.Value >= 0.85f) { goto IL_1EB; } float num2 = Rand.Range(0.45f, 0.8f); float totalPrice = PawnApparelGenerator.workingSet.TotalPrice; if (totalPrice >= randomInRange * num2) { goto IL_1EB; } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new string[] { " -- Failed: Spent $", totalPrice.ToString("F0"), ", < ", (num2 * 100f).ToString("F0"), "% of money." })); } IL_35E: num++; continue; IL_1EB: if (num < 20 && Rand.Value < 0.97f && !PawnApparelGenerator.workingSet.Covers(BodyPartGroupDefOf.Torso)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Does not cover torso."); } goto IL_35E; } if (num < 30 && Rand.Value < 0.8f && PawnApparelGenerator.workingSet.CoatButNoShirt()) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Coat but no shirt."); } goto IL_35E; } if (num < 50) { bool mustBeSafe = num < 17; if (!PawnApparelGenerator.workingSet.SatisfiesNeededWarmth(neededWarmth, mustBeSafe, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Wrong warmth."); } goto IL_35E; } } if (num < 80 && PawnApparelGenerator.workingSet.IsNaked(pawn.gender)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(" -- Failed: Naked."); } goto IL_35E; } break; } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.Append(string.Concat(new object[] { " -- Approved! Total price: $", PawnApparelGenerator.workingSet.TotalPrice.ToString("F0"), ", TotalInsulationCold: ", PawnApparelGenerator.workingSet.TotalInsulationCold })); } } if ((!pawn.kindDef.apparelIgnoreSeasons || request.ForceAddFreeWarmLayerIfNeeded) && !PawnApparelGenerator.workingSet.SatisfiesNeededWarmth(neededWarmth, true, mapTemperature)) { PawnApparelGenerator.workingSet.AddFreeWarmthAsNeeded(neededWarmth, mapTemperature); } if (DebugViewSettings.logApparelGeneration) { Log.Message(PawnApparelGenerator.debugSb.ToString(), false); } PawnApparelGenerator.workingSet.GiveToPawn(pawn); PawnApparelGenerator.workingSet.Reset(null, null); if (pawn.kindDef.apparelColor != Color.white) { List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int i = 0; i < wornApparel.Count; i++) { wornApparel[i].SetColor(pawn.kindDef.apparelColor, false); } } }
public void AddFreeWarmthAsNeeded(NeededWarmth warmth) { if (warmth == NeededWarmth.Any) { return; } if (warmth == NeededWarmth.Cool) { return; } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(); PawnApparelGenerator.debugSb.AppendLine("Trying to give free warm layer."); } if (!this.SatisfiesNeededWarmth(warmth, false, 21f)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Checking to give free torso-cover at max price " + PawnApparelGenerator.freeWarmParkaMaxPrice); } Predicate <ThingStuffPair> parkaPairValidator = (ThingStuffPair pa) => pa.Price <= PawnApparelGenerator.freeWarmParkaMaxPrice && pa.InsulationCold <= -40f; ThingStuffPair parkaPair; if ((from pa in PawnApparelGenerator.allApparelPairs where parkaPairValidator(pa) select pa).TryRandomElementByWeight((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price), out parkaPair)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { "Giving free torso-cover: ", parkaPair, " insulation=", parkaPair.InsulationCold })); foreach (ThingStuffPair current in from a in this.aps where !ApparelUtility.CanWearTogether(a.thing, parkaPair.thing, this.body) select a) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { " -replaces ", current.ToString(), " InsulationCold=", current.InsulationCold })); } } this.aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, parkaPair.thing, this.body)); this.aps.Add(parkaPair); } } if (!this.SatisfiesNeededWarmth(warmth, false, 21f)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Checking to give free hat at max price " + PawnApparelGenerator.freeWarmHatMaxPrice); } Predicate <ThingStuffPair> hatPairValidator = (ThingStuffPair pa) => pa.Price <= PawnApparelGenerator.freeWarmHatMaxPrice && pa.InsulationCold <= -7f && (pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead) || pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead)); ThingStuffPair hatPair; if ((from pa in PawnApparelGenerator.allApparelPairs where hatPairValidator(pa) select pa).TryRandomElementByWeight((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price), out hatPair)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { "Giving free hat: ", hatPair, " insulation=", hatPair.InsulationCold })); foreach (ThingStuffPair current2 in from a in this.aps where !ApparelUtility.CanWearTogether(a.thing, hatPair.thing, this.body) select a) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { " -replaces ", current2.ToString(), " InsulationCold=", current2.InsulationCold })); } } this.aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, hatPair.thing, this.body)); this.aps.Add(hatPair); } } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("New TotalInsulationCold: " + this.TotalInsulationCold); } }
public void AddFreeWarmthAsNeeded(NeededWarmth warmth, float mapTemperature) { if (warmth == NeededWarmth.Any || warmth == NeededWarmth.Cool) { return; } if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(); debugSb.AppendLine("Trying to give free warm layer."); } for (int i = 0; i < 3; i++) { if (!SatisfiesNeededWarmth(warmth, mustBeSafe: true, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine("Checking to give free torso-cover at max price " + freeWarmParkaMaxPrice); } Predicate <ThingStuffPair> parkaPairValidator = delegate(ThingStuffPair pa) { if (pa.Price > freeWarmParkaMaxPrice) { return(false); } if (pa.InsulationCold <= 0f) { return(false); } if (!pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso)) { return(false); } if (!pa.thing.apparel.canBeGeneratedToSatisfyWarmth) { return(false); } return((!(GetReplacedInsulationCold(pa) >= pa.InsulationCold)) ? true : false); }; for (int j = 0; j < 2; j++) { ThingStuffPair candidate; if (j == 0) { if (!allApparelPairs.Where((ThingStuffPair pa) => parkaPairValidator(pa) && pa.InsulationCold < 40f).TryRandomElementByWeight((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price), out candidate)) { continue; } } else if (!allApparelPairs.Where((ThingStuffPair pa) => parkaPairValidator(pa)).TryMaxBy((ThingStuffPair x) => x.InsulationCold - GetReplacedInsulationCold(x), out candidate)) { continue; } if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine("Giving free torso-cover: " + candidate + " insulation=" + candidate.InsulationCold); foreach (ThingStuffPair item in aps.Where((ThingStuffPair a) => !ApparelUtility.CanWearTogether(a.thing, candidate.thing, body))) { debugSb.AppendLine(" -replaces " + item.ToString() + " InsulationCold=" + item.InsulationCold); } } aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, candidate.thing, body)); aps.Add(candidate); break; } } if (GenTemperature.SafeTemperatureRange(raceDef, aps).Includes(mapTemperature)) { break; } } if (!SatisfiesNeededWarmth(warmth, mustBeSafe: true, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine("Checking to give free hat at max price " + freeWarmHatMaxPrice); } Predicate <ThingStuffPair> hatPairValidator = delegate(ThingStuffPair pa) { if (pa.Price > freeWarmHatMaxPrice) { return(false); } if (pa.InsulationCold < 7f) { return(false); } if (!pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead) && !pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead)) { return(false); } return((!(GetReplacedInsulationCold(pa) >= pa.InsulationCold)) ? true : false); }; if (allApparelPairs.Where((ThingStuffPair pa) => hatPairValidator(pa)).TryRandomElementByWeight((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price), out ThingStuffPair hatPair)) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine("Giving free hat: " + hatPair + " insulation=" + hatPair.InsulationCold); foreach (ThingStuffPair item2 in aps.Where((ThingStuffPair a) => !ApparelUtility.CanWearTogether(a.thing, hatPair.thing, body))) { debugSb.AppendLine(" -replaces " + item2.ToString() + " InsulationCold=" + item2.InsulationCold); } } aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, hatPair.thing, body)); aps.Add(hatPair); } } if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine("New TotalInsulationCold: " + TotalInsulationCold); } }
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); }
static float ApparelScoreRawInsulation(Pawn pawn, Apparel apparel, ExtendedOutfit outfit, NeededWarmth neededWarmth) { float insulation; if (outfit.targetTemperaturesOverride) { // NOTE: We can't rely on the vanilla check for taking off gear for temperature, because // we need to consider all the wardrobe changes taken together; each individual change may // note push us over the thresholds, but several changes together may. // Return 1 for temperature offsets here, we'll look at the effects of any gear we have to // take off below. // NOTE: This is still suboptimal, because we're still only considering one piece of apparel // to wear at each time. A better solution would be reducing the problem to a series of linear // equations, and then solving that system. // I'm not sure that's feasible at all; first off for simple computational reasons: the linear // system to solve would be fairly massive, optimizing for dozens of pawns and hundreds of pieces // of gear simultaneously. Second, many of the stat functions aren't actually linear, and would // have to be made to be linear. bool currentlyWorn = pawn.apparel.WornApparel.Contains(apparel); var currentRange = pawn.ComfortableTemperatureRange(); var candidateRange = currentRange; if (outfit.AutoTemp) { var seasonalTemp = pawn.Map.mapTemperature.SeasonalTemp; outfit.targetTemperatures = new FloatRange(seasonalTemp - outfit.autoTempOffset, seasonalTemp + outfit.autoTempOffset); } var targetRange = outfit.targetTemperatures; var apparelOffset = GetInsulationStats(apparel); // effect of this piece of apparel candidateRange.min += apparelOffset.min; candidateRange.max += apparelOffset.max; if (!currentlyWorn) { foreach (var otherApparel in pawn.apparel.WornApparel) { // effect of taking off any other apparel that is incompatible if (!ApparelUtility.CanWearTogether(apparel.def, otherApparel.def, pawn.RaceProps.body)) { var otherInsulationRange = GetInsulationStats(otherApparel); candidateRange.min -= otherInsulationRange.min; candidateRange.max -= otherInsulationRange.max; } } } // did we get any closer to our target range? (smaller distance is better, negative values are overkill). var currentDistance = new FloatRange(Mathf.Max(currentRange.min - targetRange.min, 0f), Mathf.Max(targetRange.max - currentRange.max, 0f)); var candidateDistance = new FloatRange(Mathf.Max(candidateRange.min - targetRange.min, 0f), Mathf.Max(targetRange.max - candidateRange.max, 0f)); // improvement in distances insulation = InsulationFactorCurve.Evaluate(currentDistance.min - candidateDistance.min) + InsulationFactorCurve.Evaluate(currentDistance.max - candidateDistance.max); #if DEBUG Log.Message($"{pawn.Name.ToStringShort} :: {apparel.LabelCap}\n" + $"\ttarget range: {targetRange}, current range: {currentRange}, candidate range {candidateRange}\n" + $"\tcurrent distance: {currentDistance}, candidate distance: {candidateDistance}\n" + $"\timprovement: {(currentDistance.min - candidateDistance.min) + (currentDistance.max - candidateDistance.max)}, insulation score: {insulation}\n"); #endif } else { float statValue; if (neededWarmth == NeededWarmth.Warm) { statValue = apparel.GetStatValue(StatDefOf.Insulation_Cold, true); insulation = InsulationTemperatureScoreFactorCurve_Need.Evaluate(statValue); } else if (neededWarmth == NeededWarmth.Cool) { statValue = apparel.GetStatValue(StatDefOf.Insulation_Heat, true); insulation = InsulationTemperatureScoreFactorCurve_Need.Evaluate(statValue); } else { insulation = 1f; } } return(insulation); }
public static void GenerateStartingApparelFor(Pawn pawn, PawnGenerationRequest request) { if (pawn.RaceProps.ToolUser && pawn.RaceProps.IsFlesh) { pawn.apparel.DestroyAll(); float randomInRange = pawn.kindDef.apparelMoney.RandomInRange; float mapTemperature; NeededWarmth neededWarmth = ApparelWarmthNeededNow(pawn, request, out mapTemperature); bool flag = Rand.Value < pawn.kindDef.apparelAllowHeadgearChance; debugSb = null; if (DebugViewSettings.logApparelGeneration) { debugSb = new StringBuilder(); debugSb.AppendLine("Generating apparel for " + pawn); debugSb.AppendLine("Money: " + randomInRange.ToString("F0")); debugSb.AppendLine("Needed warmth: " + neededWarmth); debugSb.AppendLine("Headgear allowed: " + flag); } if (randomInRange < 0.001f) { GenerateWorkingPossibleApparelSetFor(pawn, randomInRange, flag); } else { int num = 0; while (true) { GenerateWorkingPossibleApparelSetFor(pawn, randomInRange, flag); if (DebugViewSettings.logApparelGeneration) { debugSb.Append(num.ToString().PadRight(5) + "Trying: " + workingSet.ToString()); } if (num < 10 && Rand.Value < 0.85f) { float num2 = Rand.Range(0.45f, 0.8f); float totalPrice = workingSet.TotalPrice; if (totalPrice < randomInRange * num2) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Spent $" + totalPrice.ToString("F0") + ", < " + (num2 * 100f).ToString("F0") + "% of money."); } goto IL_035e; } } if (num < 20 && Rand.Value < 0.97f && !workingSet.Covers(BodyPartGroupDefOf.Torso)) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Does not cover torso."); } } else if (num < 30 && Rand.Value < 0.8f && workingSet.CoatButNoShirt()) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Coat but no shirt."); } } else { if (num < 50) { bool mustBeSafe = num < 17; if (!workingSet.SatisfiesNeededWarmth(neededWarmth, mustBeSafe, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Wrong warmth."); } goto IL_035e; } } if (num >= 80 || !workingSet.IsNaked(pawn.gender)) { break; } if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Naked."); } } goto IL_035e; IL_035e: num++; } if (DebugViewSettings.logApparelGeneration) { debugSb.Append(" -- Approved! Total price: $" + workingSet.TotalPrice.ToString("F0") + ", TotalInsulationCold: " + workingSet.TotalInsulationCold); } } if ((!pawn.kindDef.apparelIgnoreSeasons || request.ForceAddFreeWarmLayerIfNeeded) && !workingSet.SatisfiesNeededWarmth(neededWarmth, mustBeSafe: true, mapTemperature)) { workingSet.AddFreeWarmthAsNeeded(neededWarmth, mapTemperature); } if (DebugViewSettings.logApparelGeneration) { Log.Message(debugSb.ToString()); } workingSet.GiveToPawn(pawn); workingSet.Reset(null, null); if (pawn.kindDef.apparelColor != Color.white) { List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int i = 0; i < wornApparel.Count; i++) { wornApparel[i].SetColor(pawn.kindDef.apparelColor, reportFailure: false); } } } }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.outfits == null) { Log.ErrorOnce(pawn + " tried to run JobGiver_OptimizeApparel without an OutfitTracker", 5643897); return(null); } if (pawn.Faction != Faction.OfPlayer) { Log.ErrorOnce("Non-colonist " + pawn + " tried to optimize apparel.", 764323); return(null); } if (pawn.IsQuestLodger()) { return(null); } if (!DebugViewSettings.debugApparelOptimize) { if (Find.TickManager.TicksGame < pawn.mindState.nextApparelOptimizeTick) { return(null); } } else { debugSb = new StringBuilder(); debugSb.AppendLine("Scanning for " + pawn + " at " + pawn.Position); } Outfit currentOutfit = pawn.outfits.CurrentOutfit; List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int num = wornApparel.Count - 1; num >= 0; num--) { if (!currentOutfit.filter.Allows(wornApparel[num]) && pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[num]) && !pawn.apparel.IsLocked(wornApparel[num])) { Job job = JobMaker.MakeJob(JobDefOf.RemoveApparel, wornApparel[num]); job.haulDroppedApparel = true; return(job); } } Thing thing = null; float num2 = 0f; List <Thing> list = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel); if (list.Count == 0) { SetNextOptimizeTick(pawn); return(null); } neededWarmth = PawnApparelGenerator.CalculateNeededWarmth(pawn, pawn.Map.Tile, GenLocalDate.Twelfth(pawn)); for (int i = 0; i < list.Count; i++) { Apparel apparel = (Apparel)list[i]; if (currentOutfit.filter.Allows(apparel) && apparel.IsInAnyStorage() && !apparel.IsForbidden(pawn) && !apparel.IsBurning() && (apparel.def.apparel.gender == Gender.None || apparel.def.apparel.gender == pawn.gender) && (!apparel.def.apparel.tags.Contains("Royal") || pawn.royalty.AllTitlesInEffectForReading.Count != 0)) { float num3 = ApparelScoreGain(pawn, apparel); if (DebugViewSettings.debugApparelOptimize) { debugSb.AppendLine(apparel.LabelCap + ": " + num3.ToString("F2")); } if (!(num3 < 0.05f) && !(num3 < num2) && (!EquipmentUtility.IsBiocoded(apparel) || EquipmentUtility.IsBiocodedFor(apparel, pawn)) && ApparelUtility.HasPartsToWear(pawn, apparel.def) && pawn.CanReserveAndReach(apparel, PathEndMode.OnCell, pawn.NormalMaxDanger())) { thing = apparel; num2 = num3; } } } if (DebugViewSettings.debugApparelOptimize) { debugSb.AppendLine("BEST: " + thing); Log.Message(debugSb.ToString()); debugSb = null; } if (thing == null) { SetNextOptimizeTick(pawn); return(null); } return(JobMaker.MakeJob(JobDefOf.Wear, thing)); }
public static void GenerateStartingApparelFor(Pawn pawn, PawnGenerationRequest request) { if (!pawn.RaceProps.ToolUser || !pawn.RaceProps.IsFlesh) { return; } pawn.apparel.DestroyAll(); float randomInRange = pawn.kindDef.apparelMoney.RandomInRange; float mapTemperature; NeededWarmth neededWarmth = ApparelWarmthNeededNow(pawn, request, out mapTemperature); bool allowHeadgear = Rand.Value < pawn.kindDef.apparelAllowHeadgearChance; debugSb = null; if (DebugViewSettings.logApparelGeneration) { debugSb = new StringBuilder(); debugSb.AppendLine("Generating apparel for " + pawn); debugSb.AppendLine("Money: " + randomInRange.ToString("F0")); debugSb.AppendLine("Needed warmth: " + neededWarmth); debugSb.AppendLine("Headgear allowed: " + allowHeadgear.ToString()); } int @int = Rand.Int; tmpApparelCandidates.Clear(); for (int i = 0; i < allApparelPairs.Count; i++) { ThingStuffPair thingStuffPair = allApparelPairs[i]; if (CanUsePair(thingStuffPair, pawn, randomInRange, allowHeadgear, @int)) { tmpApparelCandidates.Add(thingStuffPair); } } if (randomInRange < 0.001f) { GenerateWorkingPossibleApparelSetFor(pawn, randomInRange, tmpApparelCandidates); } else { int num = 0; while (true) { GenerateWorkingPossibleApparelSetFor(pawn, randomInRange, tmpApparelCandidates); if (DebugViewSettings.logApparelGeneration) { debugSb.Append(num.ToString().PadRight(5) + "Trying: " + workingSet.ToString()); } if (num < 10 && Rand.Value < 0.85f && randomInRange < 9999999f) { float num2 = Rand.Range(0.45f, 0.8f); float totalPrice = workingSet.TotalPrice; if (totalPrice < randomInRange * num2) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Spent $" + totalPrice.ToString("F0") + ", < " + (num2 * 100f).ToString("F0") + "% of money."); } goto IL_037d; } } if (num < 20 && Rand.Value < 0.97f && !workingSet.Covers(BodyPartGroupDefOf.Torso)) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Does not cover torso."); } } else if (num < 30 && Rand.Value < 0.8f && workingSet.CoatButNoShirt()) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Coat but no shirt."); } } else { if (num < 50) { bool mustBeSafe = num < 17; if (!workingSet.SatisfiesNeededWarmth(neededWarmth, mustBeSafe, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Wrong warmth."); } goto IL_037d; } } if (num >= 80 || !workingSet.IsNaked(pawn.gender)) { break; } if (DebugViewSettings.logApparelGeneration) { debugSb.AppendLine(" -- Failed: Naked."); } } goto IL_037d; IL_037d: num++; } if (DebugViewSettings.logApparelGeneration) { debugSb.Append(" -- Approved! Total price: $" + workingSet.TotalPrice.ToString("F0") + ", TotalInsulationCold: " + workingSet.TotalInsulationCold); } } if ((!pawn.kindDef.apparelIgnoreSeasons || request.ForceAddFreeWarmLayerIfNeeded) && !workingSet.SatisfiesNeededWarmth(neededWarmth, mustBeSafe: true, mapTemperature)) { workingSet.AddFreeWarmthAsNeeded(neededWarmth, mapTemperature); } if (DebugViewSettings.logApparelGeneration) { Log.Message(debugSb.ToString()); } workingSet.GiveToPawn(pawn); workingSet.Reset(null, null); if (pawn.kindDef.apparelColor != Color.white) { List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int j = 0; j < wornApparel.Count; j++) { wornApparel[j].SetColor(pawn.kindDef.apparelColor, reportFailure: false); } } List <SpecificApparelRequirement> specificApparelRequirements = pawn.kindDef.specificApparelRequirements; if (specificApparelRequirements != null) { foreach (SpecificApparelRequirement item in specificApparelRequirements.Where((SpecificApparelRequirement x) => x.Color != default(Color))) { List <Apparel> wornApparel2 = pawn.apparel.WornApparel; for (int k = 0; k < wornApparel2.Count; k++) { if (ApparelRequirementHandlesThing(item, wornApparel2[k].def)) { wornApparel2[k].SetColor(item.Color, reportFailure: false); } } } } foreach (Apparel item2 in pawn.apparel.WornApparel) { CompBiocodable compBiocodable = item2.TryGetComp <CompBiocodable>(); if (compBiocodable != null && Rand.Chance(request.BiocodeApparelChance)) { compBiocodable.CodeFor(pawn); } } }
public void AddFreeWarmthAsNeeded(NeededWarmth warmth, float mapTemperature) { if (warmth == NeededWarmth.Any) { return; } if (warmth == NeededWarmth.Cool) { return; } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(); PawnApparelGenerator.debugSb.AppendLine("Trying to give free warm layer."); } for (int i = 0; i < 3; i++) { if (!this.SatisfiesNeededWarmth(warmth, true, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Checking to give free torso-cover at max price " + PawnApparelGenerator.freeWarmParkaMaxPrice); } Predicate <ThingStuffPair> parkaPairValidator = delegate(ThingStuffPair pa) { if (pa.Price > PawnApparelGenerator.freeWarmParkaMaxPrice) { return(false); } if (pa.InsulationCold <= 0f) { return(false); } if (!pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso)) { return(false); } float replacedInsulationCold = this.GetReplacedInsulationCold(pa); return(replacedInsulationCold < pa.InsulationCold); }; int j = 0; while (j < 2) { ThingStuffPair candidate; if (j == 0) { if ((from pa in PawnApparelGenerator.allApparelPairs where parkaPairValidator(pa) && pa.InsulationCold < 40f select pa).TryRandomElementByWeight((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price), out candidate)) { goto IL_12F; } } else if ((from pa in PawnApparelGenerator.allApparelPairs where parkaPairValidator(pa) select pa).TryMaxBy((ThingStuffPair x) => x.InsulationCold - this.GetReplacedInsulationCold(x), out candidate)) { goto IL_12F; } j++; continue; IL_12F: if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { "Giving free torso-cover: ", candidate, " insulation=", candidate.InsulationCold })); foreach (ThingStuffPair thingStuffPair in from a in this.aps where !ApparelUtility.CanWearTogether(a.thing, candidate.thing, this.body) select a) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { " -replaces ", thingStuffPair.ToString(), " InsulationCold=", thingStuffPair.InsulationCold })); } } this.aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, candidate.thing, this.body)); this.aps.Add(candidate); break; } } if (GenTemperature.SafeTemperatureRange(this.raceDef, this.aps).Includes(mapTemperature)) { break; } } if (!this.SatisfiesNeededWarmth(warmth, true, mapTemperature)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("Checking to give free hat at max price " + PawnApparelGenerator.freeWarmHatMaxPrice); } Predicate <ThingStuffPair> hatPairValidator = delegate(ThingStuffPair pa) { if (pa.Price > PawnApparelGenerator.freeWarmHatMaxPrice) { return(false); } if (pa.InsulationCold < 7f) { return(false); } if (!pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead) && !pa.thing.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead)) { return(false); } float replacedInsulationCold = this.GetReplacedInsulationCold(pa); return(replacedInsulationCold < pa.InsulationCold); }; ThingStuffPair hatPair; if ((from pa in PawnApparelGenerator.allApparelPairs where hatPairValidator(pa) select pa).TryRandomElementByWeight((ThingStuffPair pa) => pa.Commonality / (pa.Price * pa.Price), out hatPair)) { if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { "Giving free hat: ", hatPair, " insulation=", hatPair.InsulationCold })); foreach (ThingStuffPair thingStuffPair2 in from a in this.aps where !ApparelUtility.CanWearTogether(a.thing, hatPair.thing, this.body) select a) { PawnApparelGenerator.debugSb.AppendLine(string.Concat(new object[] { " -replaces ", thingStuffPair2.ToString(), " InsulationCold=", thingStuffPair2.InsulationCold })); } } this.aps.RemoveAll((ThingStuffPair pa) => !ApparelUtility.CanWearTogether(pa.thing, hatPair.thing, this.body)); this.aps.Add(hatPair); } } if (DebugViewSettings.logApparelGeneration) { PawnApparelGenerator.debugSb.AppendLine("New TotalInsulationCold: " + this.TotalInsulationCold); } }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.outfits == null) { Log.ErrorOnce(pawn + " tried to run JobGiver_OptimizeApparel without an OutfitTracker", 5643897); return(null); } if (pawn.Faction != Faction.OfPlayer) { Log.ErrorOnce("Non-colonist " + pawn + " tried to optimize apparel.", 764323); return(null); } if (!DebugViewSettings.debugApparelOptimize) { if (Find.TickManager.TicksGame < pawn.mindState.nextApparelOptimizeTick) { return(null); } } else { JobGiver_OptimizeApparel.debugSb = new StringBuilder(); JobGiver_OptimizeApparel.debugSb.AppendLine("Scanning for " + pawn + " at " + pawn.Position); } Outfit currentOutfit = pawn.outfits.CurrentOutfit; List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int num = wornApparel.Count - 1; num >= 0; num--) { if (!currentOutfit.filter.Allows(wornApparel[num]) && pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[num])) { Job job = new Job(JobDefOf.RemoveApparel, wornApparel[num]); job.haulDroppedApparel = true; return(job); } } Thing thing = null; float num2 = 0f; List <Thing> list = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel); if (list.Count == 0) { this.SetNextOptimizeTick(pawn); return(null); } JobGiver_OptimizeApparel.neededWarmth = PawnApparelGenerator.CalculateNeededWarmth(pawn, pawn.Map.Tile, GenLocalDate.Twelfth(pawn)); for (int i = 0; i < list.Count; i++) { Apparel apparel = (Apparel)list[i]; if (currentOutfit.filter.Allows(apparel)) { SlotGroup slotGroup = apparel.Map.slotGroupManager.SlotGroupAt(apparel.Position); if (slotGroup != null && !apparel.IsForbidden(pawn)) { float num3 = JobGiver_OptimizeApparel.ApparelScoreGain(pawn, apparel); if (DebugViewSettings.debugApparelOptimize) { JobGiver_OptimizeApparel.debugSb.AppendLine(apparel.LabelCap + ": " + num3.ToString("F2")); } if (!(num3 < 0.05000000074505806) && !(num3 < num2) && ApparelUtility.HasPartsToWear(pawn, apparel.def) && pawn.CanReserveAndReach(apparel, PathEndMode.OnCell, pawn.NormalMaxDanger(), 1, -1, null, false)) { thing = apparel; num2 = num3; } } } } if (DebugViewSettings.debugApparelOptimize) { JobGiver_OptimizeApparel.debugSb.AppendLine("BEST: " + thing); Log.Message(JobGiver_OptimizeApparel.debugSb.ToString()); JobGiver_OptimizeApparel.debugSb = null; } if (thing == null) { this.SetNextOptimizeTick(pawn); return(null); } return(new Job(JobDefOf.Wear, thing)); }
public static bool TryGiveJob(JobGiver_OptimizeApparel __instance, ref Job __result, Pawn pawn) { if (pawn.outfits == null) { Log.ErrorOnce(string.Concat(pawn, " tried to run JobGiver_OptimizeApparel without an OutfitTracker"), 5643897); __result = null; return(false); } if (pawn.Faction != Faction.OfPlayer) { Log.ErrorOnce(string.Concat("Non-colonist ", pawn, " tried to optimize apparel."), 764323); __result = null; return(false); } if (pawn.IsQuestLodger()) { __result = null; return(false); } if (!DebugViewSettings.debugApparelOptimize) { if (Find.TickManager.TicksGame < pawn.mindState.nextApparelOptimizeTick) { __result = null; return(false); } } else { debugSb = new StringBuilder(); debugSb.AppendLine(string.Concat("Scanning for ", pawn, " at ", pawn.Position)); } Outfit currentOutfit = pawn.outfits.CurrentOutfit; List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int num = wornApparel.Count - 1; num >= 0; num--) { if (!currentOutfit.filter.Allows(wornApparel[num]) && pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[num]) && !pawn.apparel.IsLocked(wornApparel[num])) { Job job = JobMaker.MakeJob(JobDefOf.RemoveApparel, wornApparel[num]); job.haulDroppedApparel = true; __result = job; return(false); } } Thing thing = null; float num2 = 0f; List <Thing> list = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel); if (list.Count == 0) { SetNextOptimizeTick2(pawn); __result = null; return(false); } neededWarmth = PawnApparelGenerator.CalculateNeededWarmth(pawn, pawn.Map.Tile, GenLocalDate.Twelfth(pawn)); //wornApparelScores.Clear(); List <float> wornApparelScores = new List <float>(); for (int i = 0; i < wornApparel.Count; i++) { wornApparelScores.Add(JobGiver_OptimizeApparel.ApparelScoreRaw(pawn, wornApparel[i])); } for (int j = 0; j < list.Count; j++) { Apparel apparel = (Apparel)list[j]; if (currentOutfit.filter.Allows(apparel) && apparel.IsInAnyStorage() && !apparel.IsForbidden(pawn) && !apparel.IsBurning() && (apparel.def.apparel.gender == Gender.None || apparel.def.apparel.gender == pawn.gender)) { float num3 = JobGiver_OptimizeApparel.ApparelScoreGain_NewTmp(pawn, apparel, wornApparelScores); if (DebugViewSettings.debugApparelOptimize) { debugSb.AppendLine(apparel.LabelCap + ": " + num3.ToString("F2")); } if (!(num3 < 0.05f) && !(num3 < num2) && (!EquipmentUtility.IsBiocoded(apparel) || EquipmentUtility.IsBiocodedFor(apparel, pawn)) && ApparelUtility.HasPartsToWear(pawn, apparel.def) && pawn.CanReserveAndReach(apparel, PathEndMode.OnCell, pawn.NormalMaxDanger())) { thing = apparel; num2 = num3; } } } if (DebugViewSettings.debugApparelOptimize) { debugSb.AppendLine("BEST: " + thing); Log.Message(debugSb.ToString()); debugSb = null; } if (thing == null) { SetNextOptimizeTick2(pawn); __result = null; return(false); } __result = JobMaker.MakeJob(JobDefOf.Wear, thing); return(false); }