// Copied so outfits can be commented public static float ApparelScoreGain(Pawn pawn, Apparel ap) { if (ap is ShieldBelt && pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsWeaponUsingProjectiles) { return(-1000f); } float num = JobGiver_OptimizeApparel.ApparelScoreRaw(pawn, ap); List <Apparel> wornApparel = pawn.apparel.WornApparel; bool flag = false; for (int index = 0; index < wornApparel.Count; ++index) { if (!ApparelUtility.CanWearTogether(wornApparel[index].def, ap.def, pawn.RaceProps.body)) { //if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[index])) // return -1000f; num -= JobGiver_OptimizeApparel.ApparelScoreRaw(pawn, wornApparel[index]); flag = true; } } if (!flag) { num *= 10f; } return(num); }
private bool CalculateApparelScoreGain(Apparel apparel, float score, out float gain) { if (apparel.def == ThingDefOf.Apparel_PersonalShield && this.pawn.equipment.Primary != null && !this.pawn.equipment.Primary.def.Verbs[0].MeleeRange) { gain = -1000f; return(false); } gain = score; for (int i = 0; i < this.calculedApparelItems.Count; i++) { Apparel wornApparel = this.calculedApparelItems[i]; if (!ApparelUtility.CanWearTogether(wornApparel.def, apparel.def)) { if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel)) { return(false); } gain -= this.calculedApparelScore[i]; } } return(true); }
public static Job FindEquipJobs(Pawn pawn) { Log.Message("Finding equip from inv for " + pawn); Outfit currentOutfit = pawn.outfits.CurrentOutfit; foreach (Apparel apparel in pawn.inventory.innerContainer .Where(t => t is Apparel a && ApparelUtility.HasPartsToWear(pawn, a.def) && currentOutfit.filter.Allows(a))) { Log.Message("Does this work? " + apparel); bool conflict = false; foreach (Apparel wornApparel in pawn.apparel.WornApparel) { if (!ApparelUtility.CanWearTogether(wornApparel.def, apparel.def, pawn.RaceProps.body)) { Log.Message("NO. conflicts with " + wornApparel); conflict = true; continue; } } if (!conflict) { Log.Message("totally! Wearing " + apparel + "from inventory"); return(new Job(GearUpAndGoJobDefOf.SwapApparelWithInventory, null, apparel)); } } return(null); }
private void TryUnequipSomething() { if (TargetApparel == null) { return; } unequipBuffer++; Apparel apparel = TargetApparel; List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int num = wornApparel.Count - 1; num >= 0; num--) { if (!ApparelUtility.CanWearTogether(apparel.def, wornApparel[num].def, pawn.RaceProps.body)) { int num2 = (int)(wornApparel[num].GetStatValue(StatDefOf.EquipDelay) * 60f); if (unequipBuffer >= num2) { bool forbid = pawn.Faction != null && pawn.Faction.HostileTo(Faction.OfPlayer); if (!pawn.apparel.TryDrop(wornApparel[num], out var _, pawn.PositionHeld, forbid)) { Log.Error(string.Concat(pawn, " could not drop ", wornApparel[num].ToStringSafe())); EndJobWith(JobCondition.Errored); } } break; } } }
public static float ApparelScoreGain_NewTmp(Pawn pawn, Apparel ap, List <float> wornScoresCache) { if (ap is ShieldBelt && pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsWeaponUsingProjectiles) { return(-1000f); } float num = ApparelScoreRaw(pawn, ap); List <Apparel> wornApparel = pawn.apparel.WornApparel; bool flag = false; for (int i = 0; i < wornApparel.Count; i++) { if (!ApparelUtility.CanWearTogether(wornApparel[i].def, ap.def, pawn.RaceProps.body)) { if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[i]) || pawn.apparel.IsLocked(wornApparel[i])) { return(-1000f); } num -= wornScoresCache[i]; flag = true; } } if (!flag) { num *= 10f; } return(num); }
public static Job FindSwapJobs(Pawn pawn) { List <Apparel> wornApparel = pawn.apparel.WornApparel; Outfit currentOutfit = pawn.outfits.CurrentOutfit; //Looping all apparel is a bit redundant because the caller is already in apparel loop, but the order might not work for this for (int i = wornApparel.Count - 1; i >= 0; i--) { Apparel takeOff = wornApparel[i]; if (!currentOutfit.filter.Allows(takeOff) && pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(takeOff)) { Log.Message("Finding swaps for " + pawn + ", could take off " + takeOff); HashSet <Thing> haulingThings = null; Log.Message("Mods: " + ModsConfig.ActiveModsInLoadOrder.ToStringSafeEnumerable()); try { ((Action)(() => { haulingThings = pawn.TryGetComp <CompHauledToInventory>()?.GetHashSet(); }))(); } catch (TypeLoadException) { } foreach (Thing t in pawn.inventory.innerContainer) { Log.Message("could wear " + t + "?"); if ((haulingThings == null || !haulingThings.Contains(t)) && t is Apparel swapTo && currentOutfit.filter.Allows(swapTo) && ApparelUtility.HasPartsToWear(pawn, swapTo.def)) { Log.Message("does " + t + " match?"); if (ApparelUtility.CanWearTogether(takeOff.def, swapTo.def, pawn.RaceProps.body)) { continue; } Log.Message("does " + t + " fit?"); if (FitsAfterSwap(swapTo, pawn, takeOff)) { Log.Message("yes totally I'm swapping " + takeOff + " for " + swapTo); return(new Job(GearUpAndGoJobDefOf.SwapApparelWithInventory, takeOff, swapTo)); } } } Log.Message("Nothing to swap to: should I return it to inventory?"); HashSet <Thing> wornThings = pawn.TryGetComp <CompWornFromInventory>()?.GetHashSet(); if (wornThings?.Contains(takeOff) ?? false) { Log.Message("yes totally I'm removing " + takeOff + " back into inventory"); return(new Job(GearUpAndGoJobDefOf.SwapApparelWithInventory, takeOff)); } } } return(null); }
// Most part is from the source code public static void Wear(Pawn pawn, Apparel newApparel, bool dropReplacedApparel = true) { ValidateArg.NotNull(newApparel, nameof(newApparel)); ValidateArg.NotNull(pawn, nameof(pawn)); if (newApparel.Spawned) { newApparel.DeSpawn(); } if (!ApparelUtility.HasPartsToWear(pawn, newApparel.def)) { Log.Warning(pawn + " tried to wear " + newApparel + " but he has no body parts required to wear it."); return; } List <Apparel> apparelsToReplace = new List <Apparel>(); for (int num = pawn.apparel.WornApparelCount - 1; num >= 0; num--) { Apparel oldApparel = pawn.apparel.WornApparel[num]; if (!ApparelUtility.CanWearTogether(newApparel.def, oldApparel.def, pawn.RaceProps.body)) { apparelsToReplace.Add(oldApparel); } } foreach (Apparel apparel in apparelsToReplace) { if (dropReplacedApparel) { bool forbid = pawn.Faction != null && pawn.Faction.HostileTo(Faction.OfPlayer); if (!pawn.apparel.TryDrop(apparel, out Apparel _, pawn.PositionHeld, forbid)) { Messages.Message(UIText.FailToDrop.Translate(pawn, apparel), MessageTypeDefOf.NeutralEvent); return; } } else { pawn.inventory.innerContainer.TryAddOrTransfer(apparel); } } if (newApparel.Wearer != null) { Log.Warning(pawn + " is trying to wear " + newApparel + " but this apparel already has a wearer (" + newApparel.Wearer + "). This may or may not cause bugs."); } // Circumvene accessibility restriction and add apparel directly to inner list. object wornApparel = pawn.apparel .GetType() .GetField("wornApparel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) .GetValue(pawn.apparel); wornApparel.GetType().GetMethod("TryAdd", new Type[] { typeof(Thing), typeof(bool) }).Invoke(wornApparel, new object[] { newApparel, false }); }
// Token: 0x06000070 RID: 112 RVA: 0x00004858 File Offset: 0x00002A58 public bool CanWearWithoutDroppingAnything(ThingDef apDef) { for (int i = 0; i < this.wornApparelDefs.Count; i++) { if (!ApparelUtility.CanWearTogether(apDef, this.wornApparelDefs[i], ThingDefOf.Human.race.body)) { return(false); } } return(true); }
private bool CanWear(Apparel apparel) { foreach (Apparel a in this.customOutfit.Apparel) { if (!ApparelUtility.CanWearTogether(a.def, apparel.def, this.pawn.RaceProps.body)) { return(false); } } return(true); }
private bool CanWear(List <Apparel> worn, Apparel newApparel) { for (int i = worn.Count - 1; i >= 0; i--) { Apparel apparel = worn[i]; if (!ApparelUtility.CanWearTogether(newApparel.def, apparel.def)) { return(false); } } return(true); }
private static bool conflicts(Pawn_ApparelTracker tra, Apparel new_app) { foreach (var worn_app in tra.WornApparel) { if (worn_app.has_lock() && (!ApparelUtility.CanWearTogether(worn_app.def, new_app.def, tra.pawn.RaceProps.body))) { return(true); } } return(false); }
// Copied so we can make some adjustments public static float ApparelScoreGain(Pawn pawn, Apparel ap) { if (ap is ShieldBelt && pawn.equipment.Primary?.def.IsWeaponUsingProjectiles == true) { return(-1000); } // Added if (!ItemUtility.AlienFrameworkAllowsIt(pawn.def, ap.def, "CanWear")) { return(-1000); } if (!ApparelUtility.HasPartsToWear(pawn, ap.def)) { return(-1000); } if (pawn.story.traits.HasTrait(TraitDefOf.Nudist)) { return(-1000); } //if (PawnApparelGenerator.IsHeadgear(ap.def)) return 0; float num = JobGiver_OptimizeApparel.ApparelScoreRaw(pawn, ap); List <Apparel> wornApparel = pawn.apparel.WornApparel; bool flag = false; // Added: var newReq = ItemUtility.IsRequiredByRoyalty(pawn, ap.def); for (int i = 0; i < wornApparel.Count; ++i) { if (!ApparelUtility.CanWearTogether(wornApparel[i].def, ap.def, pawn.RaceProps.body)) { if (pawn.apparel.IsLocked(wornApparel[i])) { return(-1000); } // Added: var wornReq = ItemUtility.IsRequiredByRoyalty(pawn, wornApparel[i].def); if (wornReq && !newReq) { return(-1000); } //if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[index])) // return -1000f; num -= JobGiver_OptimizeApparel.ApparelScoreRaw(pawn, wornApparel[i]); flag = true; } } if (!flag) { num *= 10f; } return(num); }
internal static void Wear(this Pawn_ApparelTracker _this, Apparel newApparel, bool dropReplacedApparel = true) { SlotGroupUtility.Notify_TakingThing(newApparel); if (newApparel.Spawned) { newApparel.DeSpawn(); } if (!ApparelUtility.HasPartsToWear(_this.pawn, newApparel.def)) { Log.Warning(string.Concat(new object[] { _this.pawn, " tried to wear ", newApparel, " but he has no body parts required to wear it." })); return; } for (int i = _this.WornApparel.Count - 1; i >= 0; i--) { Apparel apparel = _this.WornApparel[i]; if (!ApparelUtility.CanWearTogether(newApparel.def, apparel.def)) { bool forbid = _this.pawn.Faction.HostileTo(Faction.OfPlayer); if (dropReplacedApparel) { Apparel apparel2; if (!_this.TryDrop(apparel, out apparel2, _this.pawn.Position, forbid)) { Log.Error(_this.pawn + " could not drop " + apparel); return; } } else { _this.WornApparel.Remove(apparel); } } } _this.WornApparel.Add(newApparel); newApparel.wearer = _this.pawn; _this.SortWornApparelIntoDrawOrder(); _this.ApparelChanged(); Utility.TryUpdateInventory(_this.pawn); // Apparel was added, update inventory MethodInfo methodInfo = typeof(Pawn_ApparelTracker).GetMethod("SortWornApparelIntoDrawOrder", BindingFlags.Instance | BindingFlags.NonPublic); methodInfo.Invoke(_this, new object[] { }); LongEventHandler.ExecuteWhenFinished(new Action(_this.ApparelChanged)); }
/// <summary> /// Order <paramref name="pawn"/> to wear new apparel. /// </summary> /// <param name="pawn"> Pawn who is about to wear <paramref name="newApparel"/>. </param> /// <param name="newApparel"> Apparel to wear. </param> /// <param name="dropReplacedApparel"> If true, drop the old apparel. </param> public static void Wear(Pawn pawn, Apparel newApparel, bool dropReplacedApparel = true) { ValidateArg.NotNull(newApparel, nameof(newApparel)); ValidateArg.NotNull(pawn, nameof(pawn)); if (newApparel.Spawned) { newApparel.DeSpawn(); } if (!ApparelUtility.HasPartsToWear(pawn, newApparel.def)) { Log.Warning(pawn + " tried to wear " + newApparel + " but he has no body parts required to wear it."); return; } List <Apparel> apparelsToReplace = new List <Apparel>(); for (int num = pawn.apparel.WornApparelCount - 1; num >= 0; num--) { Apparel oldApparel = pawn.apparel.WornApparel[num]; if (!ApparelUtility.CanWearTogether(newApparel.def, oldApparel.def, pawn.RaceProps.body)) { apparelsToReplace.Add(oldApparel); } } foreach (Apparel apparel in apparelsToReplace) { if (dropReplacedApparel) { bool forbid = pawn.Faction != null && pawn.Faction.HostileTo(Faction.OfPlayer); if (!pawn.apparel.TryDrop(apparel, out Apparel _, pawn.PositionHeld, forbid)) { Messages.Message(UIText.FailToDrop.Translate(pawn, apparel), MessageTypeDefOf.NeutralEvent); return; } } else { pawn.inventory.innerContainer.TryAddOrTransfer(apparel); } } if (newApparel.Wearer != null) { Log.Warning(pawn + " is trying to wear " + newApparel + " but this apparel already has a wearer (" + newApparel.Wearer + "). This may or may not cause bugs."); } pawn.apparel.GetDirectlyHeldThings().TryAdd(newApparel); }
public static void CalculateScoreForSpecialStats(Apparel ap, StatPriority statPriority, Pawn thisPawn, float apStat, ref float score) { var current = thisPawn.GetStatValue(statPriority.Stat); var goal = statPriority.Weight; var defaultStat = thisPawn.def.GetStatValueAbstract(statPriority.Stat); if (thisPawn.story != null) { foreach (var trait in thisPawn.story.traits.allTraits) { defaultStat += trait.OffsetOfStat(statPriority.Stat); } foreach (var trait in thisPawn.story.traits.allTraits) { defaultStat *= trait.MultiplierOfStat(statPriority.Stat); } } if (ap.Wearer == thisPawn) { current -= apStat; } else { foreach (var worn in thisPawn.apparel.WornApparel) { if (ApparelUtility.CanWearTogether(worn.def, ap.def, thisPawn.RaceProps.body)) { continue; } var stat1 = worn.GetStatValue(statPriority.Stat); var stat2 = worn.GetEquippedStatValue(thisPawn, statPriority.Stat); DoApparelScoreRaw_PawnStatsHandlers(worn, statPriority.Stat, out var stat3); current -= stat1 + stat2 + stat3; } } if (!(Math.Abs(current - goal) > 0.01f)) { return; } var need = 1f - Mathf.InverseLerp(defaultStat, goal, current); score += Mathf.InverseLerp(current, goal, current + apStat) * need; }
public bool CanStoreApparel(Apparel apparel) { if (ArmorRackJobUtil.RaceCanWear(apparel.def, PawnKindDef.race) == false) { return(false); } foreach (Apparel storedApparel in GetStoredApparel()) { if (!ApparelUtility.CanWearTogether(storedApparel.def, apparel.def, PawnKindDef.RaceProps.body)) { return(false); } } return(true); }
// ReSharper disable once UnusedMember.Global public static float ApparelScoreGain([NotNull] this Pawn pawn, [NotNull] Apparel newAp, List <Apparel> wornApparel = null) { var conf = pawn.GetApparelStatCache(); // get the score of the considered apparel var candidateScore = conf.ApparelScoreRaw(newAp); // float candidateScore = StatCache.WeaponScoreRaw(ap, pawn); // get the current list of worn apparel if (wornApparel.NullOrEmpty()) { wornApparel = pawn.apparel.WornApparel; } var willReplace = false; // check if the candidate will replace existing gear if (wornApparel != null) { foreach (var wornAp in wornApparel) { if (ApparelUtility.CanWearTogether(wornAp.def, newAp.def, pawn.RaceProps.body)) { continue; } // can't drop forced gear if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornAp)) { return(-1000f); } // if replaces, score is difference of the two pieces of gear + penalty candidateScore -= conf.ApparelScoreRaw(wornAp); willReplace = true; } } // increase score if this piece can be worn without replacing existing gear. if (!willReplace) { candidateScore *= ScoreFactorIfNotReplacing; } return(candidateScore); }
/// <summary> /// When notified job is about to start, calculate unequip delay for underlying apparel. /// </summary> public override void Notify_Starting() { base.Notify_Starting(); _apparel = TargetThingA as Apparel; _duration = (int)(_apparel.GetStatValue(StatDefOf.EquipDelay) * 60f); List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int num = wornApparel.Count - 1; num >= 0; num--) { if (!ApparelUtility.CanWearTogether(_apparel.def, wornApparel[num].def, pawn.RaceProps.body)) { _duration += (int)(wornApparel[num].GetStatValue(StatDefOf.EquipDelay) * 60f); } } }
public static bool FitsAfterSwap(Apparel newAp, Pawn pawn, Apparel skipAp) { foreach (Apparel pairAp in pawn.apparel.WornApparel) { if (pairAp == skipAp) { continue; } Log.Message("Does " + newAp + " fit with " + pairAp + "?"); if (!ApparelUtility.CanWearTogether(newAp.def, pairAp.def, pawn.RaceProps.body)) { Log.Message("NO"); return(false); } } return(true); }
private static bool prevent_wear_by_gear(Pawn_ApparelTracker __instance, ref Apparel newApparel) { var tra = __instance; // //--Log.Message ("Pawn_ApparelTracker.Wear called for " + newApparel.Label + " on " + tra.pawn.NameStringShort); foreach (var app in tra.WornApparel) { if (app.has_lock() && (!ApparelUtility.CanWearTogether(newApparel.def, app.def, tra.pawn.RaceProps.body))) { if (PawnUtility.ShouldSendNotificationAbout(tra.pawn)) { Messages.Message(tra.pawn.NameStringShort + " can't wear " + newApparel.def.label + " (blocked by " + app.def.label + ")", tra.pawn, MessageTypeDefOf.NegativeEvent); } return(false); } } return(true); }
public static bool ApparelScoreGain_NewTmp(ref float __result, Pawn pawn, Apparel ap, List <float> wornScoresCache) { if (ap is ShieldBelt && pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsWeaponUsingProjectiles) { __result = -1000f; return(false); } float num = JobGiver_OptimizeApparel.ApparelScoreRaw(pawn, ap); List <Apparel> wornApparel = pawn.apparel.WornApparel; bool flag = false; for (int i = 0; i < wornApparel.Count; i++) { Apparel apparel; try { apparel = wornApparel[i]; } catch (ArgumentOutOfRangeException) { break; } if (!ApparelUtility.CanWearTogether(apparel.def, ap.def, pawn.RaceProps.body)) { if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(apparel) || pawn.apparel.IsLocked(apparel)) { __result = -1000f; return(false); } num -= wornScoresCache[i]; flag = true; } } if (!flag) { num *= 10f; } __result = num; return(false); }
public static IEnumerator GenerateStartingApparelFor(Zombie zombie) { var possibleApparel = AllApparelPairs().Where(pair => CanWear(zombie, pair)).ToList(); yield return(null); if (possibleApparel.Count > 0) { for (var i = 0; i < Rand.Range(0, 4); i++) { var pair = possibleApparel.RandomElement(); yield return(null); var apparel = (Apparel)ThingMaker.MakeThing(pair.thing, pair.stuff); yield return(null); PawnGenerator.PostProcessGeneratedGear(apparel, zombie); yield return(null); if (ApparelUtility.HasPartsToWear(zombie, apparel.def)) { if (zombie.apparel.WornApparel.All(pa => ApparelUtility.CanWearTogether(pair.thing, pa.def, zombie.RaceProps.body))) { apparel.SetColor(Zombie.zombieColors[Rand.Range(0, Zombie.zombieColors.Length)].SaturationChanged(0.25f)); Graphic_Multi_Init_Patch.suppressError = true; Graphic_Multi_Init_Patch.textureError = false; try { zombie.apparel.Wear(apparel, false); } catch (Exception) { } if (Graphic_Multi_Init_Patch.textureError) { zombie.apparel.Remove(apparel); } Graphic_Multi_Init_Patch.suppressError = false; } } yield return(null); } } }
public static void CalculateScoreForSpecialStats(Apparel ap, StatPriority statPriority, Pawn thisPawn, float apStat, ref float score) { float current = thisPawn.GetStatValue(statPriority.Stat); float goal = statPriority.Weight; float defaultStat = thisPawn.def.GetStatValueAbstract(statPriority.Stat); if (thisPawn.story != null) { for (int k = 0; k < thisPawn.story.traits.allTraits.Count; k++) { defaultStat += thisPawn.story.traits.allTraits[k].OffsetOfStat(statPriority.Stat); } for (int n = 0; n < thisPawn.story.traits.allTraits.Count; n++) { defaultStat *= thisPawn.story.traits.allTraits[n].MultiplierOfStat(statPriority.Stat); } } if (ap.Wearer == thisPawn) { current -= apStat; } else { foreach (Apparel worn in thisPawn.apparel.WornApparel) { if (!ApparelUtility.CanWearTogether(worn.def, ap.def, thisPawn.RaceProps.body)) { float stat1 = worn.GetStatValue(statPriority.Stat); float stat2 = worn.GetEquippedStatValue(thisPawn, statPriority.Stat); DoApparelScoreRaw_PawnStatsHandlers(worn, statPriority.Stat, out float stat3); current -= stat1 + stat2 + stat3; } } } if (Math.Abs(current - goal) > 0.01f) { float need = 1f - Mathf.InverseLerp(defaultStat, goal, current); score += Mathf.InverseLerp(current, goal, current + apStat) * need; } }
public static float ApparelScoreGain(Pawn pawn, Apparel ap) { // only allow shields to be considered if a primary weapon is equipped and is melee if (ap.def == ThingDefOf.Apparel_PersonalShield && pawn.equipment.Primary != null && !pawn.equipment.Primary.def.Verbs[0].MeleeRange) { return(-1000f); } // get the score of the considered apparel float candidateScore = ApparelScoreRaw(ap, pawn); // get the current list of worn apparel List <Apparel> wornApparel = pawn.apparel.WornApparel; // check if the candidate will replace existing gear bool willReplace = false; for (int i = 0; i < wornApparel.Count; i++) { if (!ApparelUtility.CanWearTogether(wornApparel[i].def, ap.def)) { // can't drop forced gear if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel[i])) { return(-1000f); } // if replaces, score is difference of the two pieces of gear candidateScore -= ApparelScoreRaw(wornApparel[i], pawn); willReplace = true; } } // increase score if this piece can be worn without replacing existing gear. if (!willReplace) { candidateScore *= 10f; } return(candidateScore); }
private static bool prevent_locked_apparel_conflict(WITab_Caravan_Gear __instance, ref Pawn p) { if (__instance == null) { return(true); } if (get_dragged_item(__instance) is Apparel dragged_app && p.apparel != null && dragged_app.has_lock()) { foreach (var equipped_app in p.apparel.WornApparel) { if (equipped_app.has_lock() && (!ApparelUtility.CanWearTogether(dragged_app.def, equipped_app.def, p.RaceProps.body))) { set_dragged_item(__instance, null); return(false); } } } return(true); }
/// <summary> /// Check wheter pawn has an empty slot to wear <paramref name="newApparel"/>. /// </summary> /// <param name="pawn"> Selected pawn. </param> /// <param name="newApparel"> Apparel to wear. </param> /// <returns> Returns true if there is an empty slot. </returns> public static bool IsOldApparelForced(this Pawn pawn, Apparel newApparel) { if (pawn.apparel?.WornApparel == null || newApparel == null) { return(false); } foreach (Apparel wornApparel in pawn.apparel.WornApparel) { if (ApparelUtility.CanWearTogether(wornApparel.def, newApparel.def, BodyDefOf.Human)) { continue; } else if (pawn.outfits.forcedHandler.IsForced(wornApparel)) { return(true); } } return(false); }
private void SetDuration() { unequipBuffer = 0; if (TargetApparel == null) { duration = 2; return; } duration = (int)(TargetApparel.GetStatValue(StatDefOf.EquipDelay) * 60f); List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int num = wornApparel.Count - 1; num >= 0; num--) { if (!ApparelUtility.CanWearTogether(TargetApparel.def, wornApparel[num].def, pawn.RaceProps.body)) { duration += (int)(wornApparel[num].GetStatValue(StatDefOf.EquipDelay) * 60f); } } }
public override void Notify_Starting() { base.Notify_Starting(); apparel = TargetThingA as Apparel; mode = job.count; duration = (int)(apparel.GetStatValue(StatDefOf.EquipDelay) * 60f); if (mode > 0) { List <Apparel> wornApparel = pawn.apparel.WornApparel; int count = wornApparel.Count; Log.Message("wornApparel.Count: " + wornApparel.Count); Log.Message("Count: " + count); for (int num = 0; num < count; ++num) { Log.Message("wornApparel.Count2: " + wornApparel.Count); Log.Message("num: " + num); if (!ApparelUtility.CanWearTogether(apparel.def, wornApparel[num].def, pawn.RaceProps.body)) { duration += (int)(wornApparel[num].GetStatValue(StatDefOf.EquipDelay) * 60f); } } } }
public override IEnumerable <string> ConfigErrors() { foreach (string err in base.ConfigErrors()) { yield return(err); } if (this.race == null) { yield return("no race"); } else if (this.RaceProps.Humanlike && this.backstoryCategories.NullOrEmpty <string>()) { yield return("Humanlike needs backstoryCategories."); } if (this.baseRecruitDifficulty > 1.0001f) { yield return(this.defName + " recruitDifficulty is greater than 1. 1 means impossible to recruit."); } if (this.combatPower < 0f) { yield return(this.defName + " has no combatPower."); } if (this.weaponMoney != FloatRange.Zero) { float minCost = 999999f; int i; for (i = 0; i < this.weaponTags.Count; i++) { IEnumerable <ThingDef> enumerable = from d in DefDatabase <ThingDef> .AllDefs where d.weaponTags != null && d.weaponTags.Contains(this.weaponTags[i]) select d; if (enumerable.Any <ThingDef>()) { float a = minCost; IEnumerable <ThingDef> source = enumerable; if (PawnKindDef.< > f__mg$cache0 == null) { PawnKindDef.< > f__mg$cache0 = new Func <ThingDef, float>(PawnWeaponGenerator.CheapestNonDerpPriceFor); } minCost = Mathf.Min(a, source.Min(PawnKindDef.< > f__mg$cache0)); } } if (minCost > this.weaponMoney.min) { yield return(string.Concat(new object[] { "Cheapest weapon with one of my weaponTags costs ", minCost, " but weaponMoney min is ", this.weaponMoney.min, ", so could end up weaponless." })); } } if (!this.RaceProps.Humanlike && this.lifeStages.Count != this.RaceProps.lifeStageAges.Count) { yield return(string.Concat(new object[] { "PawnKindDef defines ", this.lifeStages.Count, " lifeStages while race def defines ", this.RaceProps.lifeStageAges.Count })); } if (this.apparelRequired != null) { for (int k = 0; k < this.apparelRequired.Count; k++) { for (int j = k + 1; j < this.apparelRequired.Count; j++) { if (!ApparelUtility.CanWearTogether(this.apparelRequired[k], this.apparelRequired[j], this.race.race.body)) { yield return(string.Concat(new object[] { "required apparel can't be worn together (", this.apparelRequired[k], ", ", this.apparelRequired[j], ")" })); } } } } yield break; }
public static void Postfix(Pawn pawn, ref Job __result, JobGiver_OptimizeApparel __instance) { if (__result == null) { return; } CompAwesomeInventoryLoadout comp = pawn.TryGetComp <CompAwesomeInventoryLoadout>(); if (comp == null) { return; } Job job = __result; Thing targetThingA = job.targetA.Thing; if (comp.Loadout is AwesomeInventoryCostume costume) { if (__result.def == JobDefOf.Wear) { if (targetThingA != null && !costume.CostumeItems.Any(s => s.Allows(targetThingA, out _)) && !costume.CostumeItems.All(s => ApparelUtility.CanWearTogether(targetThingA.def, s.AllowedThing, BodyDefOf.Human))) { __result = null; JobMaker.ReturnToPool(job); _setNextOptimizeTick.Invoke(__instance, new[] { pawn }); return; } } } else if (comp.Loadout is AwesomeInventoryLoadout loadout) { CancellationTokenSource source = new CancellationTokenSource(); CancellationToken token = source.Token; try { bool conflict = false; if (!loadout.Any(selector => selector.Allows(targetThingA, out _))) { Parallel.ForEach( Partitioner.Create(pawn.apparel.WornApparel) , (Apparel apparel) => { if (!token.IsCancellationRequested && targetThingA != null && !ApparelUtility.CanWearTogether(apparel.def, targetThingA.def, BodyDefOf.Human)) { if (comp.Loadout.Any(selector => selector.Allows(apparel, out _))) { conflict = true; source.Cancel(); } } }); } if (conflict) { __result = new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, targetThingA, false); JobMaker.ReturnToPool(job); } } catch (Exception e) { __result = JobMaker.MakeJob(JobDefOf.Wear, targetThingA); } finally { source.Dispose(); } } }