public override void DoWindowContents(Rect windowRect) { MapComponent_AutoEquip mapComponent = MapComponent_AutoEquip.Get; PawnCalcForApparel pawnAutoEquip = new PawnCalcForApparel(mapComponent.GetCache(this.pawn)); List <Apparel> allApparels = new List <Apparel>(Find.ListerThings.ThingsInGroup(ThingRequestGroup.Apparel).OfType <Apparel>()); foreach (Pawn pawn in Find.ListerPawns.FreeColonists) { foreach (Apparel pawnApparel in pawn.apparel.WornApparel) { if (pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(pawnApparel)) { allApparels.Add(pawnApparel); } } } allApparels = allApparels.Where(i => !ApparelUtility.CanWearTogether(this.apparel.def, i.def)).ToList(); Rect groupRect = windowRect.ContractedBy(10f); groupRect.height -= 100; GUI.BeginGroup(groupRect); float apparelScoreWidth = 100f; float apparelGainWidth = 100f; float apparelLabelWidth = (groupRect.width - apparelScoreWidth - apparelGainWidth) / 3 - 8f - 8f; float apparelEquipedWidth = apparelLabelWidth; float apparelOwnerWidth = apparelLabelWidth; Rect itemRect = new Rect(groupRect.xMin + 4f, groupRect.yMin, groupRect.width - 8f, 28f); this.DrawLine(ref itemRect, null, "Apparel", apparelLabelWidth, null, "Equiped", apparelEquipedWidth, null, "Target", apparelOwnerWidth, "Score", apparelScoreWidth, "Gain", apparelGainWidth); groupRect.yMin += itemRect.height; Widgets.DrawLineHorizontal(groupRect.xMin, groupRect.yMin, groupRect.width); groupRect.yMin += 4f; groupRect.height -= 4f; groupRect.height -= Text.LineHeight * 1.2f * 3f; Rect viewRect = new Rect(groupRect.xMin, groupRect.yMin, groupRect.width - 16f, allApparels.Count() * 28f + 16f); if (viewRect.height < groupRect.height) { groupRect.height = viewRect.height; } Rect listRect = viewRect.ContractedBy(4f); Widgets.BeginScrollView(groupRect, ref scrollPosition, viewRect); allApparels = allApparels.OrderByDescending(i => { float g; if (pawnAutoEquip.CalculateApparelScoreGain(i, out g)) { return(g); } return(-1000f); }).ToList(); foreach (Apparel currentAppel in allApparels) { itemRect = new Rect(listRect.xMin, listRect.yMin, listRect.width, 28f); if (Mouse.IsOver(itemRect)) { GUI.color = ITab_Pawn_AutoEquip.HighlightColor; GUI.DrawTexture(itemRect, TexUI.HighlightTex); GUI.color = Color.white; } Pawn equiped = null; Pawn target = null; foreach (Pawn pawn in Find.ListerPawns.FreeColonists) { foreach (Apparel a in pawn.apparel.WornApparel) { if (a == currentAppel) { equiped = pawn; break; } } foreach (Apparel a in mapComponent.GetCache(pawn).targetApparel) { if (a == currentAppel) { target = pawn; break; } } if ((equiped != null) && (target != null)) { break; } } float gain; if (pawnAutoEquip.CalculateApparelScoreGain(currentAppel, out gain)) { this.DrawLine(ref itemRect, currentAppel, currentAppel.LabelCap, apparelLabelWidth, equiped, equiped == null ? null : equiped.LabelCap, apparelEquipedWidth, target, target == null ? null : target.LabelCap, apparelOwnerWidth, pawnAutoEquip.CalculateApparelScoreRaw(currentAppel).ToString("N5"), apparelScoreWidth, gain.ToString("N5"), apparelGainWidth); } else { this.DrawLine(ref itemRect, currentAppel, currentAppel.LabelCap, apparelLabelWidth, equiped, equiped == null ? null : equiped.LabelCap, apparelEquipedWidth, target, target == null ? null : target.LabelCap, apparelOwnerWidth, pawnAutoEquip.CalculateApparelScoreRaw(currentAppel).ToString("N5"), apparelScoreWidth, "No Allow", apparelGainWidth); } listRect.yMin = itemRect.yMax; } Widgets.EndScrollView(); Widgets.DrawLineHorizontal(groupRect.xMin, groupRect.yMax, groupRect.width); GUI.color = Color.white; Text.Anchor = TextAnchor.UpperLeft; GUI.EndGroup(); }
public static void Postfix(Vector3 clickPos, Pawn pawn, List<FloatMenuOption> opts) { IntVec3 c = IntVec3.FromVector3(clickPos); if (pawn.equipment != null) { //First equipment already handled by patched Method, so skip var equipmentList = c.GetThingList(pawn.Map).Where(t => t.TryGetComp<CompEquippable>() != null).OfType<ThingWithComps>().Skip(1); //Log.Message(string.Format("Adding {0:d} equipment orders", equipmentList.Count())); foreach (ThingWithComps equipment in equipmentList) { string labelShort = equipment.LabelShort; FloatMenuOption item3; if (equipment.def.IsWeapon && pawn.story.WorkTagIsDisabled(WorkTags.Violent)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { labelShort }) + " (" + "IsIncapableOfViolenceLower".Translate(new object[] { pawn.LabelShort }) + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { labelShort }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { labelShort }) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { string text3 = "Equip".Translate(new object[] { labelShort }); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text3 = text3 + " " + "EquipWarningBrawler".Translate(); } item3 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text3, delegate { equipment.SetForbidden(false, true); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Equip, equipment), JobTag.Misc); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip, 1f); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, equipment, "ReservedBy"); } opts.Add(item3); } } if (pawn.apparel != null) { //First apparel already handled by patched method, so skip var apparelList = c.GetThingList(pawn.Map).OfType<Apparel>().Skip(1); //Log.Message(string.Format("Adding {0:d} apparel orders", apparelList.Count())); foreach (Apparel apparel in apparelList) { FloatMenuOption item4; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { item4 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("ForceWear".Translate(new object[] { apparel.LabelShort }), delegate { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, apparel, "ReservedBy"); } opts.Add(item4); } } AddReservationActionsIfOnlySingleItem(c, pawn.MapHeld, opts); }
internal static void AddHumanlikeOrders(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { IntVec3 c2 = IntVec3.FromVector3(clickPos); int num = 0; if (pawn.story != null) { num = pawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire); } foreach (Thing current in c2.GetThingList()) { Thing t = current; if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow) { FloatMenuOption item; if (t.def.ingestible.isPleasureDrug && num < 0) { item = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelShort }) + " (" + "Teetotaler".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { item = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelShort }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else if (!pawn.CanReserve(t, 1)) { item = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelShort }) + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(t, pawn.Faction, true).LabelShort }) + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else { item = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelShort }), delegate { t.SetForbidden(false, true); Job job = new Job(JobDefOf.Ingest, t); job.maxNumToCarry = FoodUtility.WillEatStackCountOf(pawn, t.def); pawn.drafter.TakeOrderedJob(job); }, MenuOptionPriority.Medium, null, null, 0f, null); } opts.Add(item); } } if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { foreach (TargetInfo current2 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) { Pawn victim = (Pawn)current2.Thing; if (!victim.InBed() && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1) && !victim.IsPrisonerOfColony) { if ((victim.Faction == Faction.OfPlayer && victim.MentalStateDef == null) || (victim.Faction != Faction.OfPlayer && victim.MentalStateDef == null && !victim.IsPrisonerOfColony && (victim.Faction == null || !victim.Faction.HostileTo(Faction.OfPlayer)))) { Pawn victim2 = victim; opts.Add(new FloatMenuOption("Rescue".Translate(new object[] { victim.LabelCap }), delegate { Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, false, false, false); if (building_Bed == null) { string str2; if (victim.RaceProps.Animal) { str2 = "NoAnimalBed".Translate(); } else { str2 = "NoNonPrisonerBed".Translate(); } Messages.Message("CannotRescue".Translate() + ": " + str2, victim, MessageSound.RejectInput); return; } Job job = new Job(JobDefOf.Rescue, victim, building_Bed); job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.Rescuing, KnowledgeAmount.Total); }, MenuOptionPriority.Medium, null, victim2, 0f, null)); } if (victim.MentalStateDef != null || (victim.RaceProps.Humanlike && victim.Faction != Faction.OfPlayer)) { Pawn victim2 = victim; opts.Add(new FloatMenuOption("Capture".Translate(new object[] { victim.LabelCap }), delegate { Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, true, false, false); if (building_Bed == null) { Messages.Message("CannotCapture".Translate() + ": " + "NoPrisonerBed".Translate(), victim, MessageSound.RejectInput); return; } Job job = new Job(JobDefOf.Capture, victim, building_Bed); job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.Capturing, KnowledgeAmount.Total); }, MenuOptionPriority.Medium, null, victim2, 0f, null)); } } } foreach (TargetInfo current3 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) { TargetInfo targetInfo = current3; Pawn victim = (Pawn)targetInfo.Thing; if (victim.Downed && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1) && Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn) != null) { string label = "CarryToCryptosleepCasket".Translate(new object[] { targetInfo.Thing.LabelCap }); JobDef jDef = JobDefOf.CarryToCryptosleepCasket; Action action = delegate { Building_CryptosleepCasket building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn); if (building_CryptosleepCasket == null) { Messages.Message("CannotCarryToCryptosleepCasket".Translate() + ": " + "NoCryptosleepCasket".Translate(), victim, MessageSound.RejectInput); return; } Job job = new Job(jDef, victim, building_CryptosleepCasket); job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); }; Pawn victim2 = victim; opts.Add(new FloatMenuOption(label, action, MenuOptionPriority.Medium, null, victim2, 0f, null)); } } } foreach (TargetInfo current4 in GenUI.TargetsAt(clickPos, TargetingParameters.ForStrip(pawn), true)) { TargetInfo stripTarg = current4; FloatMenuOption item2; if (!pawn.CanReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item2 = new FloatMenuOption("CannotStrip".Translate(new object[] { stripTarg.Thing.LabelCap }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else if (!pawn.CanReserveAndReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly, 1)) { item2 = new FloatMenuOption("CannotStrip".Translate(new object[] { stripTarg.Thing.LabelCap }) + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(stripTarg, pawn.Faction, true).LabelShort }) + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else { item2 = new FloatMenuOption("Strip".Translate(new object[] { stripTarg.Thing.LabelCap }), delegate { stripTarg.Thing.SetForbidden(false, false); Job job = new Job(JobDefOf.Strip, stripTarg); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); }, MenuOptionPriority.Medium, null, null, 0f, null); } opts.Add(item2); } CompInventory compInventory = pawn.TryGetComp <CompInventory>(); // Need compInventory here for equip and wear options if (pawn.equipment != null) { ThingWithComps equipment = null; List <Thing> thingList = c2.GetThingList(); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].TryGetComp <CompEquippable>() != null) { equipment = (ThingWithComps)thingList[i]; break; } } if (equipment != null) { string label2 = equipment.Label; FloatMenuOption item3; if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { label2 }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else if (!pawn.CanReserve(equipment, 1)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { label2 }) + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(equipment, pawn.Faction, true).LabelShort }) + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { label2 }) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else { string text = "Equip".Translate(new object[] { label2 }); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text = text + " " + "EquipWarningBrawler".Translate(); } item3 = new FloatMenuOption(text, delegate { equipment.SetForbidden(false, true); Job job = new Job(JobDefOf.Equip, equipment); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); MoteThrower.ThrowStatic(equipment.DrawPos, ThingDefOf.Mote_FeedbackEquip, 1f); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }, MenuOptionPriority.Medium, null, null, 0f, null); } opts.Add(item3); } } if (pawn.apparel != null) { Apparel apparel = Find.ThingGrid.ThingAt <Apparel>(c2); if (apparel != null) { FloatMenuOption item4; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else if (!pawn.CanReserve(apparel, 1)) { Pawn pawn2 = Find.Reservations.FirstReserverOf(apparel, pawn.Faction, true); item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "ReservedBy".Translate(new object[] { pawn2.LabelShort }) + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null); } else { // Added check for inventory capacity int count; if (compInventory != null && !compInventory.CanFitInInventory(apparel, out count, false, true)) { item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "CR_InventoryFull".Translate() + ")", null); } else { item4 = new FloatMenuOption("ForceWear".Translate(new object[] { apparel.LabelShort }), new Action(delegate { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); }), MenuOptionPriority.Medium, null, null); } } opts.Add(item4); } } // *** NEW: Pick up option *** if (compInventory != null) { List <Thing> thingList = c2.GetThingList(); if (!thingList.NullOrEmpty <Thing>()) { Thing item = thingList.FirstOrDefault(thing => thing.def.alwaysHaulable && !(thing is Corpse)); if (item != null) { FloatMenuOption pickUpOption; int count = 0; if (!pawn.CanReach(item, PathEndMode.Touch, Danger.Deadly)) { pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelShort + " (" + "NoPath".Translate() + ")", null); } else if (!pawn.CanReserve(item)) { pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelShort + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(item, pawn.Faction) }), null); } else if (!compInventory.CanFitInInventory(item, out count)) { pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelShort + " (" + "CR_InventoryFull".Translate() + ")", null); } else { pickUpOption = new FloatMenuOption("CR_PickUp".Translate() + " " + item.LabelShort, new Action(delegate { item.SetForbidden(false); Job job = new Job(JobDefOf.TakeInventory, item) { maxNumToCarry = 1 }; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); })); } opts.Add(pickUpOption); if (count > 1 && item.stackCount > 1) { int numToCarry = Math.Min(count, item.stackCount); FloatMenuOption pickUpStackOption = new FloatMenuOption("CR_PickUp".Translate() + " " + item.LabelShort + " x" + numToCarry.ToString(), new Action(delegate { item.SetForbidden(false); Job job = new Job(JobDefOf.TakeInventory, item) { maxNumToCarry = numToCarry }; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); })); opts.Add(pickUpStackOption); FloatMenuOption pickUpHalfStackOption = new FloatMenuOption("CE_PickUpHalf" + " " + item.LabelShort + " x" + (numToCarry / 2).ToString(), new Action(delegate { item.SetForbidden(false); Job job = new Job(JobDefOf.TakeInventory, item) { maxNumToCarry = numToCarry / 2 }; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); })); opts.Add(pickUpHalfStackOption); } } } } if (pawn.equipment != null && pawn.equipment.Primary != null) { Thing thing = Find.ThingGrid.ThingAt(c2, ThingDefOf.EquipmentRack); if (thing != null) { if (!pawn.CanReach(thing, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotDeposit".Translate(new object[] { pawn.equipment.Primary.LabelCap, thing.def.label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null)); } else { foreach (IntVec3 c in GenAdj.CellsOccupiedBy(thing)) { if (c.GetStorable() == null && pawn.CanReserveAndReach(c, PathEndMode.ClosestTouch, Danger.Deadly, 1)) { Action action2 = delegate { ThingWithComps t; if (pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out t, pawn.Position, true)) { t.SetForbidden(false, true); Job job = new Job(JobDefOf.HaulToCell, t, c); job.haulMode = HaulMode.ToCellStorage; job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); } }; opts.Add(new FloatMenuOption("Deposit".Translate(new object[] { pawn.equipment.Primary.LabelCap, thing.def.label }), action2, MenuOptionPriority.Medium, null, null, 0f, null)); break; } } } } if (pawn.equipment != null && GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn), true).Any <TargetInfo>()) { Action action3 = delegate { ThingWithComps thingWithComps; pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out thingWithComps, pawn.Position, true); pawn.drafter.TakeOrderedJob(new Job(JobDefOf.Wait, 20, false)); }; opts.Add(new FloatMenuOption("Drop".Translate(new object[] { pawn.equipment.Primary.Label }), action3, MenuOptionPriority.Medium, null, null, 0f, null)); } } foreach (TargetInfo current5 in GenUI.TargetsAt(clickPos, TargetingParameters.ForTrade(), true)) { TargetInfo dest = current5; if (!pawn.CanReach(dest, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotTrade".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null)); } else if (!pawn.CanReserve(dest.Thing, 1)) { opts.Add(new FloatMenuOption("CannotTrade".Translate() + " (" + "Reserved".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null)); } else { Pawn pTarg = (Pawn)dest.Thing; Action action4 = delegate { Job job = new Job(JobDefOf.TradeWithPawn, pTarg); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.InteractingWithTraders, KnowledgeAmount.Total); }; string str = string.Empty; if (pTarg.Faction != null) { str = " (" + pTarg.Faction.Name + ")"; } Thing thing2 = dest.Thing; opts.Add(new FloatMenuOption("TradeWith".Translate(new object[] { pTarg.LabelShort }) + str, action4, MenuOptionPriority.Medium, null, thing2, 0f, null)); } } foreach (Thing current6 in Find.ThingGrid.ThingsAt(c2)) { foreach (FloatMenuOption current7 in current6.GetFloatMenuOptions(pawn)) { opts.Add(current7); } } }
protected override IEnumerable <Toil> MakeNewToils() { foreach (var toil in base.MakeNewToils()) { yield return(toil); } yield return(new Toil() { initAction = delegate { var armorRack = TargetThingA as ArmorRack; var storedRackApparel = new List <Apparel>(armorRack.GetStoredApparel()); var storedRackWeapon = armorRack.GetStoredWeapon(); var storedPawnWeapon = pawn.equipment.Primary; armorRack.InnerContainer.Clear(); foreach (Apparel rackApparel in storedRackApparel) { if (!ApparelUtility.HasPartsToWear(pawn, rackApparel.def)) { Thing lastRemovedThing = null; GenPlace.TryPlaceThing(rackApparel, armorRack.Position, armorRack.Map, ThingPlaceMode.Near, out lastRemovedThing); continue; } if (!pawn.apparel.CanWearWithoutDroppingAnything(rackApparel.def)) { var storedPawnApparel = new List <Apparel>(pawn.apparel.WornApparel); foreach (var pawnApparel in storedPawnApparel) { if (!ApparelUtility.CanWearTogether(rackApparel.def, pawnApparel.def, armorRack.PawnKindDef.RaceProps.body)) { pawn.apparel.Remove(pawnApparel); armorRack.InnerContainer.TryAdd(pawnApparel); } } } pawn.apparel.Wear(rackApparel); if (EquipSetForced()) { pawn.outfits.forcedHandler.SetForced(rackApparel, true); } } int hasRackWeapon = storedRackWeapon == null ? 0x00 : 0x01; int hasPawnWeapon = storedPawnWeapon == null ? 0x00 : 0x10; switch (hasRackWeapon | hasPawnWeapon) { case 0x11: { pawn.equipment.Remove(storedPawnWeapon); armorRack.InnerContainer.TryAdd(storedPawnWeapon); pawn.equipment.MakeRoomFor((ThingWithComps)storedRackWeapon); pawn.equipment.AddEquipment((ThingWithComps)storedRackWeapon); break; } case 0x01: pawn.equipment.MakeRoomFor((ThingWithComps)storedRackWeapon); pawn.equipment.AddEquipment((ThingWithComps)storedRackWeapon); break; case 0x10: { break; } } ForbidUtility.SetForbidden(TargetThingA, true); var useComp = pawn.GetComp <ArmorRackUseCommandComp>(); if (useComp != null) { useComp.CurArmorRackJobDef = ArmorRacksJobDefOf.ArmorRacks_JobTransferToRack; } } }); }
private Apparel FindGarmentCoveringPart(Pawn pawn, BodyPartGroupDef bodyPartGroupDef) { Room room = pawn.GetRoom(); Predicate <Thing> validator = (Thing t) => pawn.CanReserve(t, 1) && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) && (t.Position.DistanceToSquared(pawn.Position) < 12f || room == RoomQuery.RoomAtFast(t.Position, t.Map)); List <Thing> aList = ( from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel) orderby t.MarketValue - t.Position.DistanceToSquared(pawn.Position) * 2f descending where validator(t) select t ).ToList(); foreach (Thing current in aList) { Apparel ap = current as Apparel; if (ap != null && ap.def.apparel.bodyPartGroups.Contains(bodyPartGroupDef) && pawn.CanReserve(ap, 1) && ApparelUtility.HasPartsToWear(pawn, ap.def)) { return(ap); } } return(null); }
// Decompiled code is painful to read... Continue at your own risk public static List <FloatMenuOption> ChoicesForThing(Thing thing, Pawn pawn) { List <FloatMenuOption> opts = new List <FloatMenuOption>(); Thing t = thing; // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow) { string text; if (t.def.ingestible.ingestCommandString.NullOrEmpty()) { text = "ConsumeThing".Translate(t.LabelShort, t); } else { text = string.Format(t.def.ingestible.ingestCommandString, t.LabelShort); } if (!t.IsSociallyProper(pawn)) { text = text + " (" + "ReservedForPrisoners".Translate() + ")"; } FloatMenuOption item7; if (t.def.IsNonMedicalDrug && pawn.IsTeetotaler()) { item7 = new FloatMenuOption(text + " (" + TraitDefOf.DrugDesire.DataAtDegree(-1).label + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { item7 = new FloatMenuOption(text + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { MenuOptionPriority priority2 = (!(t is Corpse)) ? MenuOptionPriority.Default : MenuOptionPriority.Low; item7 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, delegate() { t.SetForbidden(false, true); Job job = new Job(JobDefOf.Ingest, t); job.count = FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition, true)); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, priority2, null, null, 0f, null, null), pawn, t, "ReservedBy"); } opts.Add(item7); } // Add equipment commands // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (thing is ThingWithComps equipment && equipment.GetComp <CompEquippable>() != null) { string labelShort = equipment.LabelShort; FloatMenuOption item4; if (equipment.def.IsWeapon && pawn.WorkTagIsDisabled(WorkTags.Violent)) { item4 = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "IsIncapableOfViolenceLower".Translate(pawn.LabelShort, pawn) + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item4 = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item4 = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { string text5 = "Equip".Translate(labelShort); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text5 = text5 + " " + "EquipWarningBrawler".Translate(); } item4 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text5, delegate() { equipment.SetForbidden(false, true); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Equip, equipment), JobTag.Misc); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip, 1f); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, equipment, "ReservedBy"); } opts.Add(item4); } // Add clothing commands Apparel apparel = thing as Apparel; if (apparel != null) { FloatMenuOption item5; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item5 = new FloatMenuOption("CannotWear".Translate(apparel.Label, apparel) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { item5 = new FloatMenuOption("CannotWear".Translate(apparel.Label, apparel) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { item5 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("ForceWear".Translate(apparel.LabelShort, apparel), delegate() { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, apparel, "ReservedBy"); } opts.Add(item5); } // Add caravan commands if (pawn.IsFormingCaravan()) { if (thing != null && thing.def.EverHaulable) { Pawn packTarget = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn) ?? pawn; JobDef jobDef = (packTarget != pawn) ? JobDefOf.GiveToPackAnimal : JobDefOf.TakeInventory; if (!pawn.CanReach(thing, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(thing.Label, thing) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, 1)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(thing.Label, thing) + " (" + "TooHeavy".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { LordJob_FormAndSendCaravan lordJob = (LordJob_FormAndSendCaravan)pawn.GetLord().LordJob; float capacityLeft = CaravanFormingUtility.CapacityLeft(lordJob); if (thing.stackCount == 1) { float capacityLeft4 = capacityLeft - thing.GetStatValue(StatDefOf.Mass, true); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravan".Translate(thing.Label, thing), capacityLeft4), delegate() { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = 1; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, thing.stackCount)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravanAll".Translate(thing.Label, thing) + " (" + "TooHeavy".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { float capacityLeft2 = capacityLeft - (float)thing.stackCount * thing.GetStatValue(StatDefOf.Mass, true); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravanAll".Translate(thing.Label, thing), capacityLeft2), delegate() { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = thing.stackCount; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("LoadIntoCaravanSome".Translate(thing.LabelNoCount, thing), delegate() { int to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(packTarget, thing), thing.stackCount); Dialog_Slider window = new Dialog_Slider(delegate(int val) { float capacityLeft3 = capacityLeft - (float)val * thing.GetStatValue(StatDefOf.Mass, true); return(CaravanFormingUtility.AppendOverweightInfo(string.Format("LoadIntoCaravanCount".Translate(thing.LabelNoCount, thing), val), capacityLeft3)); }, 1, to, delegate(int count) { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = count; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, int.MinValue); Find.WindowStack.Add(window); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } } } } if (opts.Count == 0) { opts.Add(new FloatMenuOption("NoneBrackets".Translate(), null) { Disabled = true }); } return(opts); }
public static void AddHumanlikeOrders(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { IntVec3 c = IntVec3.FromVector3(clickPos); foreach (Thing current in c.GetThingList(pawn.Map)) { Thing t = current; if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow) { string text; if (t.def.ingestible.ingestCommandString.NullOrEmpty()) { text = "ConsumeThing".Translate(new object[] { t.LabelShort }); } else { text = string.Format(t.def.ingestible.ingestCommandString, t.LabelShort); } FloatMenuOption item = null; if (t.def.IsPleasureDrug && pawn.story != null && pawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire) < 0) { item = new FloatMenuOption(text + " (" + TraitDefOf.DrugDesire.DataAtDegree(-1).label + ")", null, MenuOptionPriority.Default, null, null, 0f, null); } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { item = new FloatMenuOption(text + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null); } else { MenuOptionPriority priority = (!(t is Corpse)) ? MenuOptionPriority.Default : MenuOptionPriority.Low; ITWN.PostMenuOption(opts, pawn, current, text, delegate { t.SetForbidden(false, true); Job job = new Job(JobDefOf.Ingest, t); job.count = FoodUtility.WillIngestStackCountOf(pawn, t.def); pawn.jobs.TryTakeOrderedJob(job); }, priority: priority); } if (item != null) { opts.Add(item); } } } if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { foreach (LocalTargetInfo current2 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) { Pawn victim = (Pawn)current2.Thing; if (!victim.InBed() && pawn.CanReach(victim, PathEndMode.OnCell, Danger.Deadly)) { if ((victim.Faction == Faction.OfPlayer && victim.MentalStateDef == null) || (victim.Faction != Faction.OfPlayer && victim.MentalStateDef == null && !victim.IsPrisonerOfColony && (victim.Faction == null || !victim.Faction.HostileTo(Faction.OfPlayer)))) { Pawn victim2 = victim; ITWN.PostMenuOption(opts, pawn, victim2, "Rescue".Translate(new object[] { victim.LabelCap }), delegate { Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, false, false, false); if (building_Bed == null) { string str2; if (victim.RaceProps.Animal) { str2 = "NoAnimalBed".Translate(); } else { str2 = "NoNonPrisonerBed".Translate(); } Messages.Message("CannotRescue".Translate() + ": " + str2, victim, MessageSound.RejectInput); return; } Job job = new Job(JobDefOf.Rescue, victim, building_Bed); job.count = 1; pawn.jobs.TryTakeOrderedJob(job); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.Rescuing, KnowledgeAmount.Total); }, MenuOptionPriority.RescueOrCapture, null, victim2, 0f, null); } if (victim.RaceProps.Humanlike && (victim.MentalStateDef != null || victim.Faction != Faction.OfPlayer || (victim.Downed && victim.guilt.IsGuilty))) { Pawn victim2 = victim; ITWN.PostMenuOption(opts, pawn, victim2, "Capture".Translate(new object[] { victim.LabelCap }), delegate { Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, true, false, false); if (building_Bed == null) { Messages.Message("CannotCapture".Translate() + ": " + "NoPrisonerBed".Translate(), victim, MessageSound.RejectInput); return; } Job job = new Job(JobDefOf.Capture, victim, building_Bed); job.count = 1; pawn.jobs.TryTakeOrderedJob(job); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.Capturing, KnowledgeAmount.Total); }, MenuOptionPriority.RescueOrCapture, null, victim2, 0f, null); } } } foreach (LocalTargetInfo current3 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) { LocalTargetInfo targetInfo = current3; Pawn victim = (Pawn)targetInfo.Thing; if (victim.Downed && pawn.CanReach(victim, PathEndMode.OnCell, Danger.Deadly) && Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn) != null) { string label = "CarryToCryptosleepCasket".Translate(new object[] { targetInfo.Thing.LabelCap }); JobDef jDef = JobDefOf.CarryToCryptosleepCasket; Action action = delegate { Building_CryptosleepCasket building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn); if (building_CryptosleepCasket == null) { Messages.Message("CannotCarryToCryptosleepCasket".Translate() + ": " + "NoCryptosleepCasket".Translate(), victim, MessageSound.RejectInput); return; } Job job = new Job(jDef, victim, building_CryptosleepCasket); job.count = 1; pawn.jobs.TryTakeOrderedJob(job); }; Pawn victim2 = victim; ITWN.PostMenuOption(opts, pawn, victim2, label, action, MenuOptionPriority.Default, null, victim2, 0f, null); } } } foreach (LocalTargetInfo current4 in GenUI.TargetsAt(clickPos, TargetingParameters.ForStrip(pawn), true)) { LocalTargetInfo stripTarg = current4; FloatMenuOption item2 = null; if (!pawn.CanReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item2 = new FloatMenuOption("CannotStrip".Translate(new object[] { stripTarg.Thing.LabelCap }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null); } else { ITWN.PostMenuOption(opts, pawn, stripTarg.Thing, "Strip".Translate(new object[] { stripTarg.Thing.LabelCap }), delegate { stripTarg.Thing.SetForbidden(false, false); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Strip, stripTarg)); }); } if (item2 != null) { opts.Add(item2); } } if (pawn.equipment != null) { ThingWithComps equipment = null; List <Thing> thingList = c.GetThingList(pawn.Map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].TryGetComp <CompEquippable>() != null) { equipment = (ThingWithComps)thingList[i]; break; } } if (equipment != null) { string labelShort = equipment.LabelShort; FloatMenuOption item3 = null; if (equipment.def.IsWeapon && pawn.story.WorkTagIsDisabled(WorkTags.Violent)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { labelShort }) + " (" + "IsIncapableOfViolenceLower".Translate(new object[] { pawn.LabelShort }) + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { labelShort }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item3 = new FloatMenuOption("CannotEquip".Translate(new object[] { labelShort }) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null); } else { string text2 = "Equip".Translate(new object[] { labelShort }); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text2 = text2 + " " + "EquipWarningBrawler".Translate(); } ITWN.PostMenuOption(opts, pawn, equipment, text2, delegate { equipment.SetForbidden(false, true); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Equip, equipment)); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip, 1f); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }); } if (item3 != null) { opts.Add(item3); } } } if (pawn.apparel != null) { Apparel apparel = pawn.Map.thingGrid.ThingAt <Apparel>(c); if (apparel != null) { FloatMenuOption item4 = null; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { item4 = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null); } else { ITWN.PostMenuOption(opts, pawn, apparel, "ForceWear".Translate(new object[] { apparel.LabelShort }), delegate { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job); }, priority: MenuOptionPriority.High); } if (item4 != null) { opts.Add(item4); } } } if (!pawn.Map.IsPlayerHome) { Thing item = c.GetFirstItem(pawn.Map); if (item != null && item.def.EverHaulable) { if (!pawn.CanReach(item, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotPickUp".Translate(new object[] { item.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, item, 1)) { ITWN.PostMenuOption(opts, pawn, item, "CannotPickUp".Translate(new object[] { item.Label }) + " (" + "TooHeavy".Translate() + ")", null); } else if (item.stackCount == 1) { ITWN.PostMenuOption(opts, pawn, item, "PickUp".Translate(new object[] { item.Label }), delegate { item.SetForbidden(false, false); Job job = new Job(JobDefOf.TakeInventory, item); job.count = 1; pawn.jobs.TryTakeOrderedJob(job); }, priority: MenuOptionPriority.High); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, item, item.stackCount)) { ITWN.PostMenuOption(opts, pawn, item, "CannotPickUpAll".Translate(new object[] { item.Label }) + " (" + "TooHeavy".Translate() + ")", null); } else { ITWN.PostMenuOption(opts, pawn, item, "PickUpAll".Translate(new object[] { item.Label }), delegate { item.SetForbidden(false, false); Job job = new Job(JobDefOf.TakeInventory, item); job.count = item.stackCount; pawn.jobs.TryTakeOrderedJob(job); }, priority: MenuOptionPriority.High); } ITWN.PostMenuOption(opts, pawn, item, "PickUpSome".Translate(new object[] { item.Label }), delegate { int to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(pawn, item), item.stackCount); Dialog_Slider window = new Dialog_Slider("PickUpCount".Translate(new object[] { item.LabelShort }), 1, to, delegate(int count) { item.SetForbidden(false, false); Job job = new Job(JobDefOf.TakeInventory, item); job.count = count; pawn.jobs.TryTakeOrderedJob(job); }, -2147483648); Find.WindowStack.Add(window); }, priority: MenuOptionPriority.High); } } } if (!pawn.Map.IsPlayerHome) { Thing item = c.GetFirstItem(pawn.Map); if (item != null && item.def.EverHaulable) { Pawn bestPackAnimal = GiveToPackAnimalUtility.PackAnimalWithTheMostFreeSpace(pawn.Map, pawn.Faction); if (bestPackAnimal != null) { if (!pawn.CanReach(item, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotGiveToPackAnimal".Translate(new object[] { item.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(bestPackAnimal, item, 1)) { ITWN.PostMenuOption(opts, pawn, item, "CannotGiveToPackAnimal".Translate(new object[] { item.Label }) + " (" + "TooHeavy".Translate() + ")", null); } else if (item.stackCount == 1) { ITWN.PostMenuOption(opts, pawn, item, "GiveToPackAnimal".Translate(new object[] { item.Label }), delegate { item.SetForbidden(false, false); Job job = new Job(JobDefOf.GiveToPackAnimal, item); job.count = 1; pawn.jobs.TryTakeOrderedJob(job); }, MenuOptionPriority.High); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(bestPackAnimal, item, item.stackCount)) { ITWN.PostMenuOption(opts, pawn, item, "CannotGiveToPackAnimalAll".Translate(new object[] { item.Label }) + " (" + "TooHeavy".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { ITWN.PostMenuOption(opts, pawn, item, "GiveToPackAnimalAll".Translate(new object[] { item.Label }), delegate { item.SetForbidden(false, false); Job job = new Job(JobDefOf.GiveToPackAnimal, item); job.count = item.stackCount; pawn.jobs.TryTakeOrderedJob(job); }, MenuOptionPriority.High, null, null, 0f, null, null); } ITWN.PostMenuOption(opts, pawn, item, "GiveToPackAnimalSome".Translate(new object[] { item.Label }), delegate { int to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(bestPackAnimal, item), item.stackCount); Dialog_Slider window = new Dialog_Slider("GiveToPackAnimalCount".Translate(new object[] { item.LabelShort }), 1, to, delegate(int count) { item.SetForbidden(false, false); Job job = new Job(JobDefOf.GiveToPackAnimal, item); job.count = count; pawn.jobs.TryTakeOrderedJob(job); }, -2147483648); Find.WindowStack.Add(window); }, MenuOptionPriority.High, null, null, 0f, null, null); } } } } if (!pawn.Map.IsPlayerHome) { foreach (LocalTargetInfo current5 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) { Pawn p = (Pawn)current5.Thing; if (p.Faction == Faction.OfPlayer || p.HostFaction == Faction.OfPlayer) { if (!pawn.CanReach(p, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotCarryToExit".Translate(new object[] { p.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { IntVec3 exitSpot; if (!RCellFinder.TryFindBestExitSpot(pawn, out exitSpot, TraverseMode.ByPawn)) { ITWN.PostMenuOption(opts, pawn, p, "CannotCarryToExit".Translate(new object[] { p.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { ITWN.PostMenuOption(opts, pawn, p, "CarryToExit".Translate(new object[] { p.Label }), delegate { Job job = new Job(JobDefOf.CarryDownedPawnToExit, p, exitSpot); job.count = 1; pawn.jobs.TryTakeOrderedJob(job); }, MenuOptionPriority.High, null, null, 0f, null, null); } } } } } if (pawn.equipment != null && pawn.equipment.Primary != null && GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn), true).Any <LocalTargetInfo>()) { Action action2 = delegate { pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, pawn.equipment.Primary)); }; opts.Add(new FloatMenuOption("Drop".Translate(new object[] { pawn.equipment.Primary.Label }), action2, MenuOptionPriority.Default, null, null, 0f, null, null)); } foreach (LocalTargetInfo current6 in GenUI.TargetsAt(clickPos, TargetingParameters.ForTrade(), true)) { LocalTargetInfo dest = current6; if (!pawn.CanReach(dest, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotTrade".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { Pawn pTarg = (Pawn)dest.Thing; Action action3 = delegate { Job job = new Job(JobDefOf.TradeWithPawn, pTarg); job.playerForced = true; pawn.jobs.TryTakeOrderedJob(job); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.InteractingWithTraders, KnowledgeAmount.Total); }; string str = string.Empty; if (pTarg.Faction != null) { str = " (" + pTarg.Faction.Name + ")"; } Thing thing = dest.Thing; ITWN.PostMenuOption(opts, pawn, pTarg, "TradeWith".Translate(new object[] { pTarg.LabelShort + ", " + pTarg.TraderKind.label }) + str, action3, MenuOptionPriority.InitiateSocial, null, thing, 0f, null, null); } } foreach (Thing current7 in pawn.Map.thingGrid.ThingsAt(c)) { foreach (FloatMenuOption current8 in current7.GetFloatMenuOptions(pawn)) { opts.Add(current8); } } }
public static bool FindBetterApparel( ref float baseApparelScore, ref Apparel betterApparel, Pawn pawn, Outfit currentOutfit, IEnumerable <Apparel> apparelToCheck, Building dresser) { if (betterApparel == null) { baseApparelScore = 0f; } #if BETTER_OUTFIT Log.Warning("Begin ApparelUtil.FindBetterApparel(Score: " + baseApparelScore + " Apparel: " + ((betterApparel == null) ? "<null>" : betterApparel.Label)); #endif bool result = false; #if TRACE && BETTER_OUTFIT Log.Message(" Apparel:"); #endif foreach (Apparel apparel in apparelToCheck) { #if TRACE && BETTER_OUTFIT Log.Message(" " + ((apparel == null) ? "<null>" : apparel.Label)); #endif if (!currentOutfit.filter.Allows(apparel.def)) { #if TRACE && BETTER_OUTFIT Log.Message(" Filters does not allow"); #endif break; } if (!currentOutfit.filter.Allows(apparel) || apparel.IsForbidden(pawn)) { #if TRACE && BETTER_OUTFIT Log.Message(" Current Outfit Does Not Allow: " + !currentOutfit.filter.Allows(apparel) + " or Is Forbidden: " + apparel.IsForbidden(pawn)); #endif continue; } #if TRACE && BETTER_OUTFIT Log.Message(" Keep Forced Apparel: " + Settings.KeepForcedApparel); #endif if (Settings.KeepForcedApparel) { bool skipApparelType = false; List <Apparel> wornApparel = pawn.apparel.WornApparel; for (int i = 0; i < wornApparel.Count; i++) { try { if (!pawn.outfits.forcedHandler.IsForced(wornApparel[i]) && !ApparelUtility.CanWearTogether(wornApparel[i].def, apparel.def, pawn.RaceProps.body)) { #if TRACE && BETTER_OUTFIT Log.Message(" Cannot wear together"); #endif skipApparelType = true; break; } } catch (Exception e) { try { Log.Warning("Problem when calling CanWearTogether (" + wornApparel[i]?.Label + ", " + apparel?.Label + ", " + pawn?.RaceProps?.body?.label + ") - " + e.GetType().Name + " " + e.Message); } catch { } skipApparelType = true; break; } } if (skipApparelType) { break; } } float gain = JobGiver_OptimizeApparel.ApparelScoreGain(pawn, apparel); #if TRACE && BETTER_OUTFIT Log.Message(" Gain: " + gain + " Base Score: " + baseApparelScore); #endif if (gain >= 0.05f && gain > baseApparelScore) { #if TRACE && BETTER_OUTFIT Log.Message(" Gain is better"); #endif if (ApparelUtility.HasPartsToWear(pawn, apparel.def)) { #if TRACE && BETTER_OUTFIT Log.Message(" Has parts to wear"); #endif if (dresser == null || ReservationUtility.CanReserveAndReach(pawn, dresser, PathEndMode.OnCell, pawn.NormalMaxDanger(), 1)) { #if TRACE && BETTER_OUTFIT Log.Message(" Can reach dresser"); #endif betterApparel = apparel; baseApparelScore = gain; result = true; } } } } #if BETTER_OUTFIT Log.Warning("End ApparelUtil.FindBetterApparel result = " + result); #endif return(result); }
/// <inheritdoc/> public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams) { ValidateArg.NotNull(pawn, nameof(pawn)); if (Find.TickManager.TicksGame < _optimizedTick) { return(ThinkResult.NoJob); } CompAwesomeInventoryLoadout comp = pawn.TryGetComp <CompAwesomeInventoryLoadout>(); if (comp?.Loadout == null || comp.Loadout.GetType() == typeof(AwesomeInventoryCostume)) { return(ThinkResult.NoJob); } List <Thing> list = pawn.inventory?.innerContainer?.ToList(); if (list == null) { return(ThinkResult.NoJob); } if (!list.Any()) { _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); } List <Apparel> wornApparels = pawn.apparel?.WornApparel; if (wornApparels == null) { return(ThinkResult.NoJob); } AwesomeInventoryCostume costume = comp.Loadout as AwesomeInventoryCostume; var thingList = list .Where(t => t is Apparel apparel && ApparelOptionUtility.CanWear(pawn, apparel)) .Select(t => new { thing = t, score = JobGiver_OptimizeApparel.ApparelScoreGain(pawn, (Apparel)t) }) .Where(thingScore => thingScore.score > 0.05f) .OrderByDescending(s => s.score) .ToList(); if (!thingList.Any()) { _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); } List <Apparel> wornCostume = null; if (costume != null) { wornCostume = pawn.apparel.WornApparel .AsParallel() .Where(a => costume.CostumeItems.Any(c => c.Allows(a, out _))) .ToList(); } foreach (var t in thingList) { Thing thing = null; if (costume == null) { thing = t.thing; } else { foreach (ThingGroupSelector selector in costume.CostumeItems) { if (selector.Allows(t.thing, out _)) { thing = t.thing; break; } } if (thing == null) { if (wornCostume.NullOrEmpty() || wornCostume.All(c => ApparelUtility.CanWearTogether(c.def, t.thing.def, BodyDefOf.Human))) { thing = t.thing; } } } if (thing != null) { return(new ThinkResult( new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, thing, false) , this , JobTag.ChangingApparel)); } } _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); }
// Decompiled code is painful to read... Continue at your own risk // TODO: Replace this with a cleaner solution // Maybe explore FloatMenuMakerMap public static List <FloatMenuOption> ChoicesForThing(Thing thing, Pawn pawn, string thingLabelShort) { var opts = new List <FloatMenuOption>(); var t = thing; string labelShort = ""; string label = thingLabelShort; if (thing.stackCount > 1) { label += " x" + thing.stackCount.ToStringCached(); } // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (t.def.ingestible != null && canBeConsumedby[t].Contains(pawn) && t.IngestibleNow) { string text; if (t.def.ingestible.ingestCommandString.NullOrEmpty()) { text = "ConsumeThing".Translate(thingLabelShort, t); } else { text = string.Format(t.def.ingestible.ingestCommandString, thingLabelShort); } if (!t.IsSociallyProper(pawn)) { text = text + " (" + "ReservedForPrisoners".Translate() + ")"; } FloatMenuOption item7; if (t.def.IsNonMedicalDrug && pawn.IsTeetotaler()) { item7 = new FloatMenuOption(text + " (" + TraitDefOf.DrugDesire.DataAtDegree(-1).label + ")", null); } else if (!pawnCanReach_Oncell_Deadly.Contains(pawn)) { item7 = new FloatMenuOption(text + " (" + "NoPath".Translate() + ")", null); } else { var priority2 = !(t is Corpse) ? MenuOptionPriority.Default : MenuOptionPriority.Low; item7 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, delegate { t.SetForbidden(false); var job = new Job(JobDefOf.Ingest, t); job.count = FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition)); pawn.jobs.TryTakeOrderedJob(job); }, priority2), pawn, t); } opts.Add(item7); } // Add equipment commands // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (thing is ThingWithComps equipment && equipment.GetComp <CompEquippable>() != null) { //ThingWithComps != Thing --> Label is diffrent implementing the override string LabelNoCount labelShort = thingLabelShort; if (equipment.AllComps != null) { int i = 0; for (int count = equipment.AllComps.Count; i < count; i++) { labelShort = equipment.AllComps[i].TransformLabel(labelShort); } } FloatMenuOption item4; if (equipment.def.IsWeapon && pawn.WorkTagIsDisabled(WorkTags.Violent)) { item4 = new FloatMenuOption( "CannotEquip".Translate(labelShort) + " (" + "IsIncapableOfViolenceLower".Translate(pawn.LabelShort, pawn) + ")", null); } else if (!pawnCanReach_Touch_Deadly.Contains(pawn)) { item4 = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "NoPath".Translate() + ")", null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item4 = new FloatMenuOption( "CannotEquip".Translate(labelShort) + " (" + "Incapable".Translate() + ")", null); } else { string text5 = "Equip".Translate(labelShort); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text5 = text5 + " " + "EquipWarningBrawler".Translate(); } item4 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text5, delegate { equipment.SetForbidden(false); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Equip, equipment)); FleckMaker.Static(equipment.DrawPos, equipment.Map, FleckDefOf.FeedbackEquip); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }, MenuOptionPriority.High), pawn, equipment); } opts.Add(item4); } // Add clothing commands var apparel = thing as Apparel; if (apparel != null) { //replaced apparel.Label label (the former would spawm MaxHitPonts) FloatMenuOption item5; if (!pawnCanReach_Touch_Deadly.Contains(pawn)) { item5 = new FloatMenuOption( "CannotWear".Translate(label, apparel) + " (" + "NoPath".Translate() + ")", null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { item5 = new FloatMenuOption( "CannotWear".Translate(label, apparel) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null); } else /*Apparel has no override for LabelShort therefor we can still use labelShort from ThingWithComps*/ { item5 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption( "ForceWear".Translate(labelShort, apparel), delegate { apparel.SetForbidden(false); var job = new Job(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job); }, MenuOptionPriority.High), pawn, apparel); } opts.Add(item5); } // Add caravan commands if (pawn.IsFormingCaravan()) { if (thing != null && thing.def.EverHaulable) { var packTarget = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn) ?? pawn; var jobDef = packTarget != pawn ? JobDefOf.GiveToPackAnimal : JobDefOf.TakeInventory; //replaced thing.Label label (the former would spawm MaxHitPonts) if (!pawnCanReach_Touch_Deadly.Contains(pawn)) { opts.Add(new FloatMenuOption( "CannotLoadIntoCaravan".Translate(label, thing) + " (" + "NoPath".Translate() + ")", null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, 1)) { opts.Add(new FloatMenuOption( "CannotLoadIntoCaravan".Translate(label, thing) + " (" + "TooHeavy".Translate() + ")", null)); } else { var lordJob = (LordJob_FormAndSendCaravan)pawn.GetLord().LordJob; var capacityLeft = CaravanFormingUtility.CapacityLeft(lordJob); if (thing.stackCount == 1) { var capacityLeft4 = capacityLeft - thing.GetStatValue(StatDefOf.Mass); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption( CaravanFormingUtility.AppendOverweightInfo( "LoadIntoCaravan".Translate(label, thing), capacityLeft4), delegate { thing.SetForbidden(false, false); var job = new Job(jobDef, thing); job.count = 1; job.checkEncumbrance = packTarget == pawn; pawn.jobs.TryTakeOrderedJob(job); }, MenuOptionPriority.High), pawn, thing)); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, thing.stackCount)) { opts.Add(new FloatMenuOption( "CannotLoadIntoCaravanAll".Translate(label, thing) + " (" + "TooHeavy".Translate() + ")", null)); } else { var capacityLeft2 = capacityLeft - thing.stackCount * thing.GetStatValue(StatDefOf.Mass); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption( CaravanFormingUtility.AppendOverweightInfo( "LoadIntoCaravanAll".Translate(label, thing), capacityLeft2), delegate { thing.SetForbidden(false, false); var job = new Job(jobDef, thing); job.count = thing.stackCount; job.checkEncumbrance = packTarget == pawn; pawn.jobs.TryTakeOrderedJob(job); }, MenuOptionPriority.High), pawn, thing)); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption( "LoadIntoCaravanSome".Translate(thingLabelShort, thing), delegate { var to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(packTarget, thing), thing.stackCount); var window = new Dialog_Slider(delegate(int val) { var capacityLeft3 = capacityLeft - val * thing.GetStatValue(StatDefOf.Mass); return(CaravanFormingUtility.AppendOverweightInfo( string.Format("LoadIntoCaravanCount".Translate(thingLabelShort, thing), val), capacityLeft3)); }, 1, to, delegate(int count) { thing.SetForbidden(false, false); var job = new Job(jobDef, thing); job.count = count; job.checkEncumbrance = packTarget == pawn; pawn.jobs.TryTakeOrderedJob(job); }); Find.WindowStack.Add(window); }, MenuOptionPriority.High), pawn, thing)); } } } } return(opts); }
public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) { // float minComfyTemperature = pawnSave.RealComfyTemperatures.min; // float maxComfyTemperature = pawnSave.RealComfyTemperatures.max; Pawn thisPawn = this._pawn; float minComfyTemperature = thisPawn.ComfortableTemperatureRange().min; float maxComfyTemperature = thisPawn.ComfortableTemperatureRange().max; // temperature FloatRange targetTemperatures = this.TargetTemperatures; this.GetInsulationStats(apparel, out float insulationCold, out float insulationHeat); string log = apparel.LabelCap + " - InsCold: " + insulationCold + " - InsHeat: " + insulationHeat + " - TargTemp: " + targetTemperatures + "\nMinComfy: " + minComfyTemperature + " - MaxComfy: " + maxComfyTemperature; // if this gear is currently worn, we need to make sure the contribution to the pawn's comfy temps is removed so the gear is properly scored List <Apparel> wornApparel = thisPawn.apparel.WornApparel; if (!wornApparel.NullOrEmpty()) { if (wornApparel.Contains(apparel)) { // log += "\nPawn is wearer of this apparel."; minComfyTemperature -= insulationCold; maxComfyTemperature -= insulationHeat; } else { // check if the candidate will replace existing gear for (int index = 0; index < wornApparel.Count; index++) { Apparel wornAp = wornApparel[index]; if (!ApparelUtility.CanWearTogether(wornAp.def, apparel.def, thisPawn.RaceProps.body)) { this.GetInsulationStats(wornAp, out float insulationColdWorn, out float insulationHeatWorn); minComfyTemperature -= insulationColdWorn; maxComfyTemperature -= insulationHeatWorn; // Log.Message(apparel +"-"+ insulationColdWorn + "-" + insulationHeatWorn + "-" + minComfyTemperature + "-" + maxComfyTemperature); } } } } log += "\nBasic stat not worn - MinComfy: " + minComfyTemperature + " - MaxComfy: " + maxComfyTemperature; // now for the interesting bit. FloatRange temperatureScoreOffset = new FloatRange(0f, 0f); // isolation_cold is given as negative numbers < 0 means we're underdressed float neededInsulationCold = targetTemperatures.min - minComfyTemperature; // isolation_warm is given as positive numbers. float neededInsulationWarmth = targetTemperatures.max - maxComfyTemperature; FloatRange tempWeight = this.TemperatureWeight; log += "\nWeight: " + tempWeight + " - NeedInsCold: " + neededInsulationCold + " - NeedInsWarmth: " + neededInsulationWarmth; if (neededInsulationCold < 0) { // currently too cold // caps ap to only consider the needed temp and don't give extra points if (neededInsulationCold > insulationCold) { temperatureScoreOffset.min += neededInsulationCold; } else { temperatureScoreOffset.min += insulationCold; } } else { // currently warm enough if (insulationCold > neededInsulationCold) { // this gear would make us too cold temperatureScoreOffset.min += insulationCold - neededInsulationCold; } } // invert for scoring temperatureScoreOffset.min *= -1; if (neededInsulationWarmth > 0) { // currently too warm // caps ap to only consider the needed temp and don't give extra points if (neededInsulationWarmth < insulationHeat) { temperatureScoreOffset.max += neededInsulationWarmth; } else { temperatureScoreOffset.max += insulationHeat; } } else { // currently cool enough if (insulationHeat < neededInsulationWarmth) { // this gear would make us too warm temperatureScoreOffset.max += insulationHeat - neededInsulationWarmth; } } // Punish bad apparel // temperatureScoreOffset.min *= temperatureScoreOffset.min < 0 ? 2f : 1f; // temperatureScoreOffset.max *= temperatureScoreOffset.max < 0 ? 2f : 1f; // New log += "\nPre-Evaluate: " + temperatureScoreOffset.min + " / " + temperatureScoreOffset.max; temperatureScoreOffset.min = Curve.Evaluate(temperatureScoreOffset.min * tempWeight.min); temperatureScoreOffset.max = Curve.Evaluate(temperatureScoreOffset.max * tempWeight.max); log += "\nScoreOffsetMin: " + temperatureScoreOffset.min + " - ScoreOffsetMax: " + temperatureScoreOffset.max + " *= " + (temperatureScoreOffset.min * temperatureScoreOffset.max); Log.Message(log); return(temperatureScoreOffset.min * temperatureScoreOffset.max); // return 1 + (temperatureScoreOffset.min + temperatureScoreOffset.max) / 15; }
public override GizmoResult GizmoOnGUI(UnityEngine.Vector2 topLeft) { Rect overRect = new Rect(topLeft.x, topLeft.y, curWidth, Height); Widgets.DrawWindowBackground(overRect); //Equipment slot Pawn wearer = backpack.wearer; ThingWithComps dummy; Rect thingIconRect = new Rect(topLeft.x, topLeft.y, widthPerItem, Height / 2); int numOfCurItem = 0; List <Thing> things = wearer.inventory.container.ToList(); //Draw Gizmo for (int i = 0; i < numOfMaxItemsPerRow * numOfRow; i++) { if (i >= backpack.MaxItem) { thingIconRect.x = topLeft.x + widthPerItem * (i % numOfMaxItemsPerRow); thingIconRect.y = topLeft.y + (Height / 2) * (i / numOfMaxItemsPerRow); Widgets.DrawTextureFitted(thingIconRect, NoAvailableTex, 1.0f); continue; } if (i >= things.Count) { thingIconRect.x = topLeft.x + widthPerItem * (i % numOfMaxItemsPerRow); thingIconRect.y = topLeft.y + (Height / 2) * (i / numOfMaxItemsPerRow); Widgets.DrawTextureFitted(thingIconRect, EmptyTex, 1.0f); continue; } Thing item = things[i]; Widgets.DrawBox(thingIconRect, 1); Widgets.ThingIcon(thingIconRect, item); if (thingIconRect.Contains(Event.current.mousePosition)) { Widgets.DrawTextureFitted(thingIconRect, FilledTex, 1.0f); } //Interaction with item if (Widgets.InvisibleButton(thingIconRect)) { thingIconSound = SoundDefOf.Click; if (Event.current.button == 0) { //Weapon if (item.def.equipmentType == EquipmentType.Primary) { if (wearer.equipment.Primary != null) { wearer.equipment.TryTransferEquipmentToContainer(wearer.equipment.Primary, wearer.inventory.container, out dummy); } else { backpack.numOfSavedItems--; } wearer.equipment.AddEquipment(item as ThingWithComps); wearer.inventory.container.Remove(item as ThingWithComps); if (wearer.jobs.curJob != null) { wearer.jobs.EndCurrentJob(JobCondition.InterruptForced); } } //Medicine else if (item.def.thingCategories.Contains(medicine)) { if (wearer.workSettings.WorkIsActive(WorkTypeDefOf.Doctor)) { Designator_ApplyMedicine designator = new Designator_ApplyMedicine(); designator.medicine = item; designator.doctor = wearer; designator.icon = item.def.uiIcon; designator.activateSound = SoundDef.Named("Click"); DesignatorManager.Select(designator); } else { Messages.Message(txtNoDoctor.Translate(), MessageSound.RejectInput); Messages.Update(); thingIconSound = SoundDefOf.ClickReject; } } //Food else if (item.def.thingCategories.Contains(foodMeals)) { if (wearer.needs.food.CurCategory != HungerCategory.Fed) { Job jobNew = new Job(JobDefOf.Ingest, item); jobNew.maxNumToCarry = 1; jobNew.ignoreForbidden = true; wearer.drafter.TakeOrderedJob(jobNew); } else { Messages.Message(txtCannotEatAnymore.Translate(), MessageSound.RejectInput); Messages.Update(); thingIconSound = SoundDefOf.ClickReject; } } //Apparel else if (item is Apparel) { //if (!wearer.apparel.CanWearWithoutDroppingAnything(item.def)) // wearer.apparel.WornApparel.Find(apparel => apparel.def.apparel.layers.Any); for (int index = wearer.apparel.WornApparel.Count - 1; index >= 0; --index) { Apparel ap = wearer.apparel.WornApparel[index]; if (!ApparelUtility.CanWearTogether(item.def, ap.def)) { Apparel resultingAp; wearer.apparel.TryDrop(ap, out resultingAp, wearer.Position, false); wearer.inventory.container.TryAdd(resultingAp); backpack.numOfSavedItems++; } } wearer.apparel.Wear(item as Apparel); wearer.inventory.container.Remove(item as ThingWithComps); backpack.numOfSavedItems--; } else { //Add another type of item you want to interact } } else if (Event.current.button == 1) { List <FloatMenuOption> options = new List <FloatMenuOption>(); options.Add(new FloatMenuOption(txtThingInfo, () => { Find.WindowStack.Add((Window) new Dialog_InfoCard(item)); })); options.Add(new FloatMenuOption(txtDropThing, () => { Thing dummy1; wearer.inventory.container.TryDrop(item, wearer.Position, ThingPlaceMode.Near, out dummy1); })); Find.WindowStack.Add((Window) new FloatMenu(options, item.LabelCap, false, false)); } SoundStarter.PlayOneShotOnCamera(thingIconSound); } numOfCurItem++; thingIconRect.x = topLeft.x + widthPerItem * (numOfCurItem % numOfMaxItemsPerRow); thingIconRect.y = topLeft.y + (Height / 2) * (numOfCurItem / numOfMaxItemsPerRow); } if (numOfCurItem == 0) { Rect textRect = new Rect(topLeft.x + Width / 2 - textWidth / 2, topLeft.y + Height / 2 - textHeight / 2, textWidth, textHeight); Widgets.Label(textRect, txtNoItem.Translate()); } return(new GizmoResult(GizmoState.Clear)); }
public static void Postfix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { if (!AwesomeInventoryServiceProvider.TryGetImplementation <IInventoryHelper>(out IInventoryHelper inventoryHelper)) { Log.Error(string.Format(ErrorMessage.NotImplemented, typeof(IInventoryHelper).Name)); return; } IntVec3 position = IntVec3.FromVector3(clickPos); // Add options for equipment. if (pawn.equipment != null) { List <Thing> things = position.GetThingList(pawn.Map); foreach (Thing thing in things) { if (thing.TryGetComp <CompEquippable>() != null) { ThingWithComps equipment = (ThingWithComps)thing; if (equipment.def.IsWeapon && !pawn.WorkTagIsDisabled(WorkTags.Violent) && pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly) && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) && !(pawn.IsQuestLodger() && (!equipment.def.IsWeapon || pawn.equipment.Primary != null)) && EquipmentUtility.CanEquip(equipment, pawn, out _)) { string text3 = UIText.AIEquip.Translate(thing.LabelShort); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text3 += " " + UIText.EquipWarningBrawler.Translate(); } var option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( text3, () => { TaggedString equipWeaponConfirmationDialogText = ThingRequiringRoyalPermissionUtility.GetEquipWeaponConfirmationDialogText(equipment, pawn); CompBladelinkWeapon compBladelinkWeapon = equipment.TryGetComp <CompBladelinkWeapon>(); if (compBladelinkWeapon != null && compBladelinkWeapon.bondedPawn != pawn) { if (!equipWeaponConfirmationDialogText.NullOrEmpty()) { equipWeaponConfirmationDialogText += "\n\n"; } equipWeaponConfirmationDialogText += "BladelinkEquipWarning".Translate(); } if (!equipWeaponConfirmationDialogText.NullOrEmpty()) { equipWeaponConfirmationDialogText += "\n\n" + "RoyalWeaponEquipConfirmation".Translate(); Find.WindowStack.Add( new Dialog_MessageBox( equipWeaponConfirmationDialogText, "Yes".Translate(), () => { Equip(); }, "No".Translate())); } else { Equip(); } }, MenuOptionPriority.High), pawn, equipment); opts.Add(option); } void Equip() { equipment.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, equipment)); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); } } } } // Add options for apparel. if (pawn.apparel != null) { Apparel apparel = pawn.Map.thingGrid.ThingAt <Apparel>(position); if (apparel != null) { if (pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly) && !apparel.IsBurning() && !pawn.apparel.WouldReplaceLockedApparel(apparel) && ApparelUtility.HasPartsToWear(pawn, apparel.def)) { FloatMenuOption option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( UIText.AIForceWear.Translate(apparel.LabelShort), () => { DressJob dressJob = SimplePool <DressJob> .Get(); dressJob.def = AwesomeInventory_JobDefOf.AwesomeInventory_Dress; dressJob.targetA = apparel; dressJob.ForceWear = true; apparel.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(dressJob); }, MenuOptionPriority.High), pawn, apparel); opts.Add(option); option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( UIText.AIWear.Translate(apparel.LabelShort), () => { DressJob dressJob = SimplePool <DressJob> .Get(); dressJob.def = AwesomeInventory_JobDefOf.AwesomeInventory_Dress; dressJob.targetA = apparel; dressJob.ForceWear = false; apparel.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(dressJob); }, MenuOptionPriority.High), pawn, apparel); opts.Add(option); } } } List <Thing> items = position.GetThingList(pawn.Map); foreach (Thing item in items) { if (item.def.category == ThingCategory.Item) { int count = MassUtility.CountToPickUpUntilOverEncumbered(pawn, item); if (count == 0) { continue; } count = Math.Min(count, item.stackCount); string displayText = UIText.Pickup.Translate(item.LabelNoCount + " x" + count); var option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( displayText , () => { Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, item); job.count = count; pawn.jobs.TryTakeOrderedJob(job); }) , pawn , item); opts.Add(option); } } }
public override IEnumerable <string> ConfigErrors() { foreach (string err in this.< ConfigErrors > __BaseCallProxy0()) { yield return(err); } if (this.race == null) { yield return("no race"); } else if (this.RaceProps.Humanlike && this.backstoryCategory.NullOrEmpty()) { yield return("Humanlike needs backstoryCategory."); } 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> source = from d in DefDatabase <ThingDef> .AllDefs where d.weaponTags != null && d.weaponTags.Contains(this.weaponTags[i]) select d; if (source.Any <ThingDef>()) { minCost = Mathf.Min(minCost, source.Min((ThingDef d) => PawnWeaponGenerator.CheapestNonDerpPriceFor(d))); } } 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 void Hide(IntVec3 pos, Map map, CompProperties_ReactiveDefense props) { if (props.statDefs == null || props.statDefs.Count == 0 || props.statValues == null || props.statValues.Count == 0 || props.statDefs.Count != props.statValues.Count) { return; } Pawn pawn = (Pawn)parent; if (pawn.Dead) { if (pawn.apparel.WornApparel.Count > 0) { List <Apparel> tap = pawn.apparel.WornApparel.ToList(); foreach (Apparel apparel in tap) { pawn.apparel.Remove(apparel); } } return; } if (((Pawn)parent).health.hediffSet.GetPartHealth(((Pawn)parent).RaceProps.body.corePart) < ((Pawn)parent).RaceProps.body.corePart.def.hitPoints * props.hpThreshold * ((Pawn)parent).def.race.baseHealthScale) { //Log.Error("a"); if (!hidden) { if (Props.apparel != null) { Apparel apparel = (Apparel)ThingMaker.MakeThing(Props.apparel); for (int i = 0; i < props.statDefs.Count; i++) { apparel.def.SetStatBaseValue(props.statDefs[i], props.statValues[i]); } if (ApparelUtility.HasPartsToWear(pawn, apparel.def)) { if (pawn.apparel == null) { pawn.apparel = new Pawn_ApparelTracker(pawn); } pawn.apparel.Wear(apparel, false); } } if (Props.stopAttacker && !stoppedAttacker) { ((Pawn)lastattack.Instigator).jobs.StartJob(new Job(JobDefOf.Wait_Wander), JobCondition.InterruptForced); stoppedAttacker = true; } ResolveHideGraphic(); hidden = true; pawn.jobs.StartJob(new Job(JobDefOf.FleeAndCower, pawn.Position), JobCondition.InterruptForced); } else { //prevent from moving pawn.pather.StopDead(); } } else { if (hidden) { if (Props.apparel != null && pawn.apparel != null) { pawn.apparel.DestroyAll(); } ResolveBaseGraphic(); hidden = false; stoppedAttacker = false; //allow to move again // pawn.pather.ResetToCurrentPosition(); pawn.pather.StartPath(pawn.Position, PathEndMode.OnCell); } } }
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. if (pawn.apparel.WornApparel.Contains(apparel)) { return(1f); } var currentRange = pawn.ComfortableTemperatureRange(); var candidateRange = currentRange; var targetRange = outfit.targetTemperatures; var apparelOffset = GetInsulationStats(apparel); // effect of this piece of apparel candidateRange.min += apparelOffset.min; candidateRange.max += apparelOffset.max; 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 PawnFinaliser(Pawn pawn) { int meleeSkill = pawn.skills.GetSkill(skillDef: Defs_Rimworld.MeleeSkill).Level; if (meleeSkill < 10) { pawn.skills.GetSkill(skillDef: Defs_Rimworld.MeleeSkill).Level += Rand.RangeInclusive(min: 10 - meleeSkill, max: 10 - meleeSkill + 5); } float[] choiceArray = { 10 - NVGameComponent.Evilness, 5 + NVGameComponent.Evilness, 5 + NVGameComponent.Evilness }; var indexes = new[] { 0, 1, 2 }; int choice = indexes.RandomElementByWeight(weightSelector: ind => choiceArray[ind]); switch (choice) { case 1: if (PawnGenUtility.AnyPSHediffsExist.IsNotFalse()) { foreach (BodyPartRecord bodyPartRecord in pawn.RaceProps.body.GetPartsWithTag(tag: Defs_Rimworld.EyeTag)) { HediffDef hediff = PawnGenUtility.GetRandomPhotosensitiveHediffDef(); if (hediff != null) { pawn.health.AddHediff(def: hediff, part: bodyPartRecord); } } if (ApparelGenUtility.GetNullPSApparelDefByTag(tagsList: pawn.kindDef.apparelTags) is ThingDef appDef) { if (ApparelUtility.HasPartsToWear(p: pawn, apparel: appDef)) { Thing apparel = ThingMaker.MakeThing( def: appDef, stuff: appDef.MadeFromStuff ? GenStuff.RandomStuffByCommonalityFor(td: appDef) : null ); pawn.apparel.Wear(newApparel: (Apparel)apparel, dropReplacedApparel: false); } } break; } else { goto case 2; } case 2: if (ApparelGenUtility.GetGiveNVApparelDefByTag(tagsList: pawn.kindDef.apparelTags) is ThingDef nvAppDef) { if (ApparelUtility.HasPartsToWear(p: pawn, apparel: nvAppDef)) { Thing apparel = ThingMaker.MakeThing( def: nvAppDef, stuff: nvAppDef.MadeFromStuff ? GenStuff.RandomStuffByCommonalityFor(td: nvAppDef) : null ); PawnGenerator.PostProcessGeneratedGear(apparel, pawn); pawn.apparel.Wear(newApparel: (Apparel)apparel, dropReplacedApparel: false); } } break; } if (Rand.Chance(chance: NVGameComponent.Evilness / 8f)) { ThingDef shield = Defs_Rimworld.ShieldDef; if (ApparelUtility.HasPartsToWear(p: pawn, apparel: shield)) { Thing shieldBelt = ThingMaker.MakeThing(def: shield, stuff: shield.MadeFromStuff ? GenStuff.RandomStuffFor(td: shield) : null); PawnGenerator.PostProcessGeneratedGear(shieldBelt, pawn); pawn.apparel.Wear(newApparel: (Apparel)shieldBelt, dropReplacedApparel: false); } } }
public override void DoWindowContents(Rect inRect) { ApparelStatCache apparelStatCache = this._pawn.GetApparelStatCache(); Outfit currentOutfit = this._pawn.outfits.CurrentOutfit; if (this._dict == null || Find.TickManager.TicksGame % 60 == 0 || GUI.changed) { List <Apparel> ap = new List <Apparel>(this._pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel).OfType <Apparel>().Where( x => x.Map.haulDestinationManager.SlotGroupAt(x.Position) != null)); foreach (Pawn otherPawn in PawnsFinder.AllMaps_FreeColonists.Where(x => x.Map == this._pawn.Map)) { foreach (Apparel pawnApparel in otherPawn.apparel.WornApparel) { if (otherPawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(pawnApparel)) { ap.Add(pawnApparel); } } } ap = ap.Where( i => !ApparelUtility.CanWearTogether(this._apparel.def, i.def, this._pawn.RaceProps.body) && currentOutfit.filter.Allows(i)).ToList(); ap = ap.OrderByDescending( i => { float g = this._pawn.ApparelScoreGain(i); return(g); }).ToList(); this._dict = new Dictionary <Apparel, float>(); foreach (Apparel currentAppel in ap) { float gain = this._pawn.ApparelScoreGain(currentAppel); this._dict.Add(currentAppel, gain); } } Rect groupRect = inRect.ContractedBy(10f); groupRect.height -= 100; GUI.BeginGroup(groupRect); float apparelLabelWidth = (groupRect.width - 2 * ScoreWidth) / 3 - 8f - 8f; float apparelEquippedWidth = apparelLabelWidth; float apparelOwnerWidth = apparelLabelWidth; Rect itemRect = new Rect(groupRect.xMin + 4f, groupRect.yMin, groupRect.width - 8f, 28f); this.DrawLine( ref itemRect, null, "Apparel", apparelLabelWidth, null, "Equiped", apparelEquippedWidth, null, "Target", apparelOwnerWidth, "Score", "Gain"); groupRect.yMin += itemRect.height; Widgets.DrawLineHorizontal(groupRect.xMin, groupRect.yMin, groupRect.width); groupRect.yMin += 4f; groupRect.height -= 4f; groupRect.height -= Text.LineHeight * 1.2f * 3f; Rect viewRect = new Rect( groupRect.xMin, groupRect.yMin, groupRect.width - 16f, this._dict.Count * 28f + 16f); if (viewRect.height < groupRect.height) { groupRect.height = viewRect.height; } Rect listRect = viewRect.ContractedBy(4f); Widgets.BeginScrollView(groupRect, ref this._scrollPosition, viewRect); foreach (KeyValuePair <Apparel, float> kvp in this._dict) { Apparel currentAppel = kvp.Key; float gain = kvp.Value; itemRect = new Rect(listRect.xMin, listRect.yMin, listRect.width, 28f); if (Mouse.IsOver(itemRect)) { GUI.DrawTexture(itemRect, TexUI.HighlightTex); GUI.color = Color.white; } Pawn equipped = currentAppel.Wearer; Pawn target = null; string gainString = this._pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(currentAppel) ? gain.ToString("N3") : "No Allow"; this.DrawLine( ref itemRect, currentAppel, currentAppel.LabelCap, apparelLabelWidth, equipped, equipped?.LabelCap, apparelEquippedWidth, target, target?.LabelCap, apparelOwnerWidth, apparelStatCache.ApparelScoreRaw(currentAppel).ToString("N3"), gainString ); listRect.yMin = itemRect.yMax; } Widgets.EndScrollView(); Widgets.DrawLineHorizontal(groupRect.xMin, groupRect.yMax, groupRect.width); GUI.color = Color.white; Text.Anchor = TextAnchor.UpperLeft; GUI.EndGroup(); }
internal static List <FloatMenuOption> ChoicesAtFor(Vector3 clickPos, Pawn pawn) { IntVec3 clickCell = IntVec3.FromVector3(clickPos); DangerUtility.NotifyDirectOrderingThisFrame(pawn); List <FloatMenuOption> list = new List <FloatMenuOption>(); if (!clickCell.InBounds()) { return(list); } // ***** Beginning of drafted options ***** if (pawn.Drafted) { foreach (TargetInfo attackTarg in GenUI.TargetsAt(clickPos, TargetingParameters.ForAttackHostile(), true)) { // *** Fire at option *** if (pawn.equipment.Primary != null && !pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.MeleeRange) { string str; Action rangedAct = FloatMenuUtility.GetRangedAttackAction(pawn, attackTarg, out str); string text = "FireAt".Translate(new object[] { attackTarg.Thing.LabelCap }); FloatMenuOption floatMenuOption = new FloatMenuOption(); floatMenuOption.priority = MenuOptionPriority.High; if (rangedAct == null) { text = text + " (" + str + ")"; } else { floatMenuOption.autoTakeable = true; floatMenuOption.action = new Action(delegate { MoteThrower.ThrowStatic(attackTarg.Thing.DrawPos, ThingDefOf.Mote_FeedbackAttack, 1f); rangedAct(); }); } floatMenuOption.label = text; list.Add(floatMenuOption); } // *** Melee attack option *** string str2; Action meleeAct = FloatMenuUtility.GetMeleeAttackAction(pawn, attackTarg, out str2); Pawn pawn2 = attackTarg.Thing as Pawn; string text2; if (pawn2 != null && pawn2.Downed) { text2 = "MeleeAttackToDeath".Translate(new object[] { attackTarg.Thing.LabelCap }); } else { text2 = "MeleeAttack".Translate(new object[] { attackTarg.Thing.LabelCap }); } Thing thing = attackTarg.Thing; FloatMenuOption floatMenuOption2 = new FloatMenuOption(string.Empty, null, MenuOptionPriority.High, null, thing); if (meleeAct == null) { text2 = text2 + " (" + str2 + ")"; } else { floatMenuOption2.action = new Action(delegate { MoteThrower.ThrowStatic(attackTarg.Thing.DrawPos, ThingDefOf.Mote_FeedbackAttack, 1f); meleeAct(); }); } floatMenuOption2.label = text2; list.Add(floatMenuOption2); } // *** Arrest option *** if (pawn.RaceProps.Humanlike && !pawn.Downed) { foreach (TargetInfo current2 in GenUI.TargetsAt(clickPos, TargetingParameters.ForArrest(pawn), true)) { TargetInfo dest = current2; if (!pawn.CanReach(dest, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { list.Add(new FloatMenuOption("CannotArrest".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null)); } else if (!pawn.CanReserve(dest.Thing, 1)) { list.Add(new FloatMenuOption("CannotArrest".Translate() + ": " + "Reserved".Translate(), null, MenuOptionPriority.Medium, null, null)); } else { Pawn pTarg = (Pawn)dest.Thing; Action action = new Action(delegate { Building_Bed building_Bed = RestUtility.FindBedFor(pTarg, pawn, true, false, false); if (building_Bed == null) { Messages.Message("CannotArrest".Translate() + ": " + "NoPrisonerBed".Translate(), pTarg, MessageSound.RejectInput); return; } Job job = new Job(JobDefOf.Arrest, pTarg, building_Bed); job.playerForced = true; job.maxNumToCarry = 1; pawn.drafter.TakeOrderedJob(job); TutorUtility.DoModalDialogIfNotKnown(ConceptDefOf.ArrestingCreatesEnemies); }); List <FloatMenuOption> arg_3F1_0 = list; Thing thing = dest.Thing; arg_3F1_0.Add(new FloatMenuOption("TryToArrest".Translate(new object[] { dest.Thing.LabelCap }), action, MenuOptionPriority.Medium, null, thing)); } } } // *** Goto option *** int num = GenRadial.NumCellsInRadius(2.9f); for (int i = 0; i < num; i++) { IntVec3 curLoc = GenRadial.RadialPattern[i] + clickCell; if (curLoc.Standable()) { if (curLoc != pawn.Position) { if (!pawn.CanReach(curLoc, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { FloatMenuOption item = new FloatMenuOption("CannotGoNoPath".Translate(), null, MenuOptionPriority.Low, null, null); list.Add(item); } else { Action action2 = new Action(delegate { IntVec3 dest = Pawn_DraftController.BestGotoDestNear(curLoc, pawn); Job job = new Job(JobDefOf.Goto, dest); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); MoteThrower.ThrowStatic(dest, ThingDefOf.Mote_FeedbackGoto, 1f); }); list.Add(new FloatMenuOption("GoHere".Translate(), action2, MenuOptionPriority.Low, null, null) { autoTakeable = true }); } } break; } } } // *** End of drafted options *** // *** Beginning of humanlike options *** if (pawn.RaceProps.Humanlike) { int num2 = 0; if (pawn.story != null) { num2 = pawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire); } // *** Consume option *** foreach (Thing current3 in clickCell.GetThingList()) { Thing t = current3; if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow) { FloatMenuOption item2; if (t.def.ingestible.isPleasureDrug && num2 < 0) { item2 = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelBaseShort }) + " (" + "Teetotaler".Translate() + ")", null, MenuOptionPriority.Medium, null, null); } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { item2 = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelBaseShort }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null); } else if (!pawn.CanReserve(t, 1)) { item2 = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelBaseShort }) + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(t, pawn.Faction).LabelBaseShort }) + ")", null, MenuOptionPriority.Medium, null, null); } else { item2 = new FloatMenuOption("ConsumeThing".Translate(new object[] { t.LabelBaseShort }), new Action(delegate { t.SetForbidden(false, true); Job job = new Job(JobDefOf.Ingest, t); job.maxNumToCarry = t.def.ingestible.maxNumToIngestAtOnce; pawn.drafter.TakeOrderedJob(job); }), MenuOptionPriority.Medium, null, null); } list.Add(item2); } } // *** Rescue/Capture downed option *** foreach (TargetInfo current4 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) { Pawn victim = (Pawn)current4.Thing; if (!victim.InBed() && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1) && !victim.IsPrisonerOfColony) { if ((victim.Faction == Faction.OfColony && victim.MentalStateDef == null) || (victim.Faction != Faction.OfColony && victim.MentalStateDef == null && !victim.IsPrisonerOfColony && (victim.Faction == null || !victim.Faction.HostileTo(Faction.OfColony)))) { List <FloatMenuOption> arg_8E1_0 = list; Pawn victim2 = victim; arg_8E1_0.Add(new FloatMenuOption("Rescue".Translate(new object[] { victim2.LabelCap }), new Action(delegate { Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, false, false, false); if (building_Bed == null) { string str; if (victim.RaceProps.Animal) { str = "NoAnimalBed".Translate(); } else { str = "NoNonPrisonerBed".Translate(); } Messages.Message("CannotRescue".Translate() + ": " + str, victim, MessageSound.RejectInput); return; } Job job = new Job(JobDefOf.Rescue, victim, building_Bed); job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.Rescuing, KnowledgeAmount.Total); }), MenuOptionPriority.Medium, null, victim2)); } if (victim.MentalStateDef != null || (victim.RaceProps.Humanlike && victim.Faction != Faction.OfColony)) { List <FloatMenuOption> arg_962_0 = list; Pawn victim2 = victim; arg_962_0.Add(new FloatMenuOption("Capture".Translate(new object[] { victim2.LabelCap }), new Action(delegate { Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, true, false, false); if (building_Bed == null) { Messages.Message("CannotCapture".Translate() + ": " + "NoPrisonerBed".Translate(), victim, MessageSound.RejectInput); return; } Job job = new Job(JobDefOf.Capture, victim, building_Bed); job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.Capturing, KnowledgeAmount.Total); }), MenuOptionPriority.Medium, null, victim2)); } } } // *** Carry to cryosleep option *** foreach (TargetInfo current5 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) { TargetInfo targetInfo = current5; Pawn victim = (Pawn)targetInfo.Thing; if (victim.Downed && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1) && Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn) != null) { string label = "CarryToCryptosleepCasket".Translate(new object[] { targetInfo.Thing.LabelCap }); JobDef jDef = JobDefOf.CarryToCryptosleepCasket; Action action3 = new Action(delegate { Building_CryptosleepCasket building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn); if (building_CryptosleepCasket == null) { Messages.Message("CannotCarryToCryptosleepCasket".Translate() + ": " + "NoCryptosleepCasket".Translate(), victim, MessageSound.RejectInput); return; } Job job = new Job(jDef, victim, building_CryptosleepCasket); job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); }); List <FloatMenuOption> arg_A80_0 = list; Pawn victim2 = victim; arg_A80_0.Add(new FloatMenuOption(label, action3, MenuOptionPriority.Medium, null, victim2)); } } // *** Strip option *** foreach (TargetInfo current6 in GenUI.TargetsAt(clickPos, TargetingParameters.ForStrip(pawn), true)) { TargetInfo stripTarg = current6; FloatMenuOption item3; if (!pawn.CanReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item3 = new FloatMenuOption("CannotStrip".Translate(new object[] { stripTarg.Thing.LabelCap }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null); } else if (!pawn.CanReserveAndReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly, 1)) { item3 = new FloatMenuOption("CannotStrip".Translate(new object[] { stripTarg.Thing.LabelCap }) + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(stripTarg, pawn.Faction).LabelBaseShort }) + ")", null, MenuOptionPriority.Medium, null, null); } else { item3 = new FloatMenuOption("Strip".Translate(new object[] { stripTarg.Thing.LabelCap }), new Action(delegate { stripTarg.Thing.SetForbidden(false, false); Job job = new Job(JobDefOf.Strip, stripTarg); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); }), MenuOptionPriority.Medium, null, null); } list.Add(item3); } // *** Equip option *** CompInventory compInventory = pawn.TryGetComp <CompInventory>(); // Need compInventory here for equip and wear options if (pawn.equipment != null) { ThingWithComps equipment = null; List <Thing> thingList = clickCell.GetThingList(); for (int j = 0; j < thingList.Count; j++) { if (thingList[j].TryGetComp <CompEquippable>() != null) { equipment = (ThingWithComps)thingList[j]; break; } } if (equipment != null) { string eqLabel = GenLabel.ThingLabel(equipment.def, equipment.Stuff, 1); FloatMenuOption equipOption; if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { equipOption = new FloatMenuOption("CannotEquip".Translate(new object[] { eqLabel }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null); } else if (!pawn.CanReserve(equipment, 1)) { equipOption = new FloatMenuOption("CannotEquip".Translate(new object[] { eqLabel }) + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(equipment, pawn.Faction).LabelBaseShort }) + ")", null, MenuOptionPriority.Medium, null, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { equipOption = new FloatMenuOption("CannotEquip".Translate(new object[] { eqLabel }) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Medium, null, null); } else { // Added check for inventory space here int count; if (compInventory != null && !compInventory.CanFitInInventory(equipment, out count, true)) { equipOption = new FloatMenuOption("CannotEquip".Translate(new object[] { eqLabel }) + " (" + "CR_InventoryFull".Translate() + ")", null); } else { string equipOptionLabel = "Equip".Translate(new object[] { eqLabel }); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { equipOptionLabel = equipOptionLabel + " " + "EquipWarningBrawler".Translate(); } equipOption = new FloatMenuOption(equipOptionLabel, new Action(delegate { equipment.SetForbidden(false, true); Job job = new Job(JobDefOf.Equip, equipment); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); MoteThrower.ThrowStatic(equipment.DrawPos, ThingDefOf.Mote_FeedbackEquip, 1f); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }), MenuOptionPriority.Medium, null, null); } } list.Add(equipOption); } } // *** Wear option *** if (pawn.apparel != null) { Apparel apparel = Find.ThingGrid.ThingAt <Apparel>(clickCell); if (apparel != null) { FloatMenuOption wearOption; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { wearOption = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null); } else if (!pawn.CanReserve(apparel, 1)) { Pawn pawn3 = Find.Reservations.FirstReserverOf(apparel, pawn.Faction); wearOption = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "ReservedBy".Translate(new object[] { pawn3.LabelBaseShort }) + ")", null, MenuOptionPriority.Medium, null, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { wearOption = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Medium, null, null); } else { // Added check for inventory capacity int count; if (compInventory != null && !compInventory.CanFitInInventory(apparel, out count, false, true)) { wearOption = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "CR_InventoryFull".Translate() + ")", null); } else { wearOption = new FloatMenuOption("ForceWear".Translate(new object[] { apparel.LabelBaseShort }), new Action(delegate { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); }), MenuOptionPriority.Medium, null, null); } } list.Add(wearOption); } } // *** NEW: Pick up option *** if (compInventory != null) { List <Thing> thingList = clickCell.GetThingList(); if (!thingList.NullOrEmpty <Thing>()) { Thing item = thingList.FirstOrDefault(thing => thing.def.alwaysHaulable && !(thing is Corpse)); if (item != null) { FloatMenuOption pickUpOption; int count = 0; if (!pawn.CanReach(item, PathEndMode.Touch, Danger.Deadly)) { pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelBaseShort + " (" + "NoPath".Translate() + ")", null); } else if (!pawn.CanReserve(item)) { pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelBaseShort + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(item, pawn.Faction) }), null); } else if (!compInventory.CanFitInInventory(item, out count)) { pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelBaseShort + " (" + "CR_InventoryFull".Translate() + ")", null); } else { pickUpOption = new FloatMenuOption("CR_PickUp".Translate() + " " + item.LabelBaseShort, new Action(delegate { item.SetForbidden(false); Job job = new Job(JobDefOf.TakeInventory, item) { maxNumToCarry = 1 }; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); })); } list.Add(pickUpOption); if (count > 1 && item.stackCount > 1) { int numToCarry = Math.Min(count, item.stackCount); FloatMenuOption pickUpStackOption = new FloatMenuOption("CR_PickUp".Translate() + " " + item.LabelBaseShort + " x" + numToCarry.ToString(), new Action(delegate { item.SetForbidden(false); Job job = new Job(JobDefOf.TakeInventory, item) { maxNumToCarry = numToCarry }; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); })); list.Add(pickUpStackOption); } } } } // *** Deposit/drop equipment options *** if (pawn.equipment != null && pawn.equipment.Primary != null) { Thing thing2 = Find.ThingGrid.ThingAt(clickCell, ThingDefOf.EquipmentRack); if (thing2 != null) { if (!pawn.CanReach(thing2, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { list.Add(new FloatMenuOption("CannotDeposit".Translate(new object[] { pawn.equipment.Primary.LabelCap, thing2.def.label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null)); } else { using (IEnumerator <IntVec3> enumerator7 = GenAdj.CellsOccupiedBy(thing2).GetEnumerator()) { while (enumerator7.MoveNext()) { IntVec3 c = enumerator7.Current; if (c.GetStorable() == null && pawn.CanReserveAndReach(c, PathEndMode.ClosestTouch, Danger.Deadly, 1)) { Action action4 = new Action(delegate { ThingWithComps t; if (pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out t, pawn.Position, true)) { t.SetForbidden(false, true); Job job = new Job(JobDefOf.HaulToCell, t, c); job.haulMode = HaulMode.ToCellStorage; job.maxNumToCarry = 1; job.playerForced = true; pawn.drafter.TakeOrderedJob(job); } }); list.Add(new FloatMenuOption("Deposit".Translate(new object[] { pawn.equipment.Primary.LabelCap, thing2.def.label }), action4, MenuOptionPriority.Medium, null, null)); break; } } } } } if (pawn.equipment != null && GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn), true).Any <TargetInfo>()) { Action action5 = new Action(delegate { ThingWithComps thingWithComps; pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out thingWithComps, pawn.Position, true); pawn.drafter.TakeOrderedJob(new Job(JobDefOf.Wait, 20, false)); } ); list.Add(new FloatMenuOption("Drop".Translate(new object[] { pawn.equipment.Primary.LabelCap }), action5, MenuOptionPriority.Medium, null, null)); } } // *** Trade with option *** foreach (TargetInfo current7 in GenUI.TargetsAt(clickPos, TargetingParameters.ForTrade(), true)) { TargetInfo dest2 = current7; if (!pawn.CanReach(dest2, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { list.Add(new FloatMenuOption("CannotTrade".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null)); } else if (!pawn.CanReserve(dest2.Thing, 1)) { list.Add(new FloatMenuOption("CannotTrade".Translate() + " (" + "Reserved".Translate() + ")", null, MenuOptionPriority.Medium, null, null)); } else { Pawn pTarg = (Pawn)dest2.Thing; Action action6 = new Action(delegate { Job job = new Job(JobDefOf.TradeWithPawn, pTarg); job.playerForced = true; pawn.drafter.TakeOrderedJob(job); ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.InteractingWithTraders, KnowledgeAmount.Total); }); string str3 = string.Empty; if (pTarg.Faction != null) { str3 = " (" + pTarg.Faction.name + ")"; } List <FloatMenuOption> arg_142E_0 = list; Thing thing = dest2.Thing; arg_142E_0.Add(new FloatMenuOption("TradeWith".Translate(new object[] { pTarg.LabelBaseShort }) + str3, action6, MenuOptionPriority.Medium, null, thing)); } } foreach (Thing current8 in Find.ThingGrid.ThingsAt(clickCell)) { foreach (FloatMenuOption current9 in current8.GetFloatMenuOptions(pawn)) { list.Add(current9); } } } // *** End of humanlike options *** // *** Beginning of non-drafted options *** if (!pawn.Drafted) { bool flag = false; bool flag2 = false; foreach (Thing current10 in Find.ThingGrid.ThingsAt(clickCell)) { flag2 = true; if (pawn.CanReach(current10, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn)) { flag = true; break; } } if (flag2 && !flag) { list.Add(new FloatMenuOption("(" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null)); return(list); } foreach (Thing current11 in Find.ThingGrid.ThingsAt(clickCell)) { Pawn pawn4 = Find.Reservations.FirstReserverOf(current11, pawn.Faction); if (pawn4 != null && pawn4 != pawn) { list.Add(new FloatMenuOption("IsReservedBy".Translate(new object[] { current11.LabelBaseShort.CapitalizeFirst(), pawn4.LabelBaseShort }), null, MenuOptionPriority.Medium, null, null)); } else { JobGiver_Work jobGiver_Work = pawn.thinker.TryGetMainTreeThinkNode <JobGiver_Work>(); if (jobGiver_Work != null) { foreach (WorkTypeDef current12 in DefDatabase <WorkTypeDef> .AllDefsListForReading) { for (int k = 0; k < current12.workGiversByPriority.Count; k++) { WorkGiver_Scanner workGiver_Scanner = current12.workGiversByPriority[k].Worker as WorkGiver_Scanner; if (workGiver_Scanner != null) { if (workGiver_Scanner.def.directOrderable) { if (!workGiver_Scanner.ShouldSkip(pawn)) { JobFailReason.Clear(); Job job; if (!workGiver_Scanner.HasJobOnThingForced(pawn, current11)) { job = null; } else { job = workGiver_Scanner.JobOnThingForced(pawn, current11); } if (workGiver_Scanner.PotentialWorkThingRequest.Accepts(current11) || (workGiver_Scanner.PotentialWorkThingsGlobal(pawn) != null && workGiver_Scanner.PotentialWorkThingsGlobal(pawn).Contains(current11))) { if (job == null) { if (JobFailReason.HaveReason) { string label2 = "CannotGenericWork".Translate(new object[] { workGiver_Scanner.def.verb, current11.LabelBaseShort }) + " (" + JobFailReason.Reason + ")"; list.Add(new FloatMenuOption(label2, null, MenuOptionPriority.Medium, null, null)); } } else { string label; WorkTypeDef workType = workGiver_Scanner.def.workType; Action action7 = null; PawnCapacityDef pawnCapacityDef = workGiver_Scanner.MissingRequiredCapacity(pawn); if (pawnCapacityDef != null) { label = "CannotMissingHealthActivities".Translate(new object[] { pawnCapacityDef.label }); } else if (pawn.jobs.curJob != null && pawn.jobs.curJob.JobIsSameAs(job)) { label = "CannotGenericAlreadyAm".Translate(new object[] { workType.gerundLabel, current11.LabelBaseShort }); } else if (pawn.workSettings.GetPriority(workType) == 0) { label = "CannotPrioritizeIsNotA".Translate(new object[] { pawn.NameStringShort, workType.pawnLabel }); } else if (job.def == JobDefOf.Research && current11 is Building_ResearchBench) { label = "CannotPrioritizeResearch".Translate(); } else if (current11.IsForbidden(pawn)) { label = "CannotPrioritizeForbidden".Translate(new object[] { current11.Label }); } else if (!pawn.CanReach(current11, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn)) { label = current11.Label + ": " + "NoPath".Translate(); } else { label = "PrioritizeGeneric".Translate(new object[] { workGiver_Scanner.def.gerund, current11.Label }); Job localJob = job; WorkTypeDef localWorkTypeDef = workType; action7 = new Action(delegate { pawn.thinker.GetMainTreeThinkNode <JobGiver_Work>().TryStartPrioritizedWorkOn(pawn, localJob, localWorkTypeDef); }); } if (!list.Any(op => op.label == label)) { list.Add(new FloatMenuOption(label, action7, MenuOptionPriority.Medium, null, null)); } } } } } } } } } } } } // *** End of non-drafted options *** foreach (FloatMenuOption current13 in pawn.GetExtraFloatMenuOptionsFor(clickCell)) { list.Add(current13); } DangerUtility.DoneDirectOrdering(); return(list); }
private void TryEquipDraggedItem(Pawn p) { this.droppedDraggedItem = false; if (this.draggedItem.def.IsWeapon) { if (p.story != null && p.story.WorkTagIsDisabled(WorkTags.Violent)) { Messages.Message("MessageCantEquipIncapableOfViolence".Translate(p.LabelShort, p), p, MessageTypeDefOf.RejectInput, false); this.draggedItem = null; return; } if (!p.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { Messages.Message("MessageCantEquipIncapableOfManipulation".Translate(), p, MessageTypeDefOf.RejectInput, false); this.draggedItem = null; return; } } Apparel apparel = this.draggedItem as Apparel; ThingWithComps thingWithComps = this.draggedItem as ThingWithComps; if (apparel != null && p.apparel != null) { WITab_Caravan_Gear.tmpExistingApparel.Clear(); WITab_Caravan_Gear.tmpExistingApparel.AddRange(p.apparel.WornApparel); for (int i = 0; i < WITab_Caravan_Gear.tmpExistingApparel.Count; i++) { if (!ApparelUtility.CanWearTogether(apparel.def, WITab_Caravan_Gear.tmpExistingApparel[i].def, p.RaceProps.body)) { p.apparel.Remove(WITab_Caravan_Gear.tmpExistingApparel[i]); Pawn pawn = CaravanInventoryUtility.FindPawnToMoveInventoryTo(WITab_Caravan_Gear.tmpExistingApparel[i], this.Pawns, null, null); if (pawn != null) { pawn.inventory.innerContainer.TryAdd(WITab_Caravan_Gear.tmpExistingApparel[i], true); } else { Log.Warning("Could not find any pawn to move " + WITab_Caravan_Gear.tmpExistingApparel[i] + " to.", false); WITab_Caravan_Gear.tmpExistingApparel[i].Destroy(DestroyMode.Vanish); } } } p.apparel.Wear((Apparel)apparel.SplitOff(1), false); if (p.outfits != null) { p.outfits.forcedHandler.SetForced(apparel, true); } } else if (thingWithComps != null && p.equipment != null) { WITab_Caravan_Gear.tmpExistingEquipment.Clear(); WITab_Caravan_Gear.tmpExistingEquipment.AddRange(p.equipment.AllEquipmentListForReading); for (int j = 0; j < WITab_Caravan_Gear.tmpExistingEquipment.Count; j++) { p.equipment.Remove(WITab_Caravan_Gear.tmpExistingEquipment[j]); Pawn pawn2 = CaravanInventoryUtility.FindPawnToMoveInventoryTo(WITab_Caravan_Gear.tmpExistingEquipment[j], this.Pawns, null, null); if (pawn2 != null) { pawn2.inventory.innerContainer.TryAdd(WITab_Caravan_Gear.tmpExistingEquipment[j], true); } else { Log.Warning("Could not find any pawn to move " + WITab_Caravan_Gear.tmpExistingEquipment[j] + " to.", false); WITab_Caravan_Gear.tmpExistingEquipment[j].Destroy(DestroyMode.Vanish); } } p.equipment.AddEquipment((ThingWithComps)thingWithComps.SplitOff(1)); } else { Log.Warning(string.Concat(new object[] { "Could not make ", p, " equip or wear ", this.draggedItem }), false); } this.draggedItem = null; }
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.Remove(apparel); } } } if (newApparel.wearer != null) { Log.Warning(string.Concat(new object[] { _this.pawn, " is trying to wear ", newApparel, " but this apparel already has a wearer (", newApparel.wearer, "). This may or may not cause bugs." })); } _this.WornApparel.Add(newApparel); newApparel.wearer = _this.pawn; _this.SortWornApparelIntoDrawOrder(); _this.ApparelChanged(); //CR PART CR_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)); }
static void Postfix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { var cell = clickPos.ToIntVec3(); if (pawn.equipment != null) { foreach (var equipment in cell.GetThingList(pawn.Map).OfType <ThingWithComps>().Where(t => t.TryGetComp <CompEquippable>() != null).Skip(1)) { string labelShort = equipment.LabelShort; FloatMenuOption option; if (equipment.def.IsWeapon && pawn.story.WorkTagIsDisabled(WorkTags.Violent)) { option = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "IsIncapableOfViolenceLower".Translate(pawn.LabelShort, pawn) + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { option = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { option = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (equipment.IsBurning()) { option = new FloatMenuOption("CannotEquip".Translate(labelShort) + " (" + "BurningLower".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { string text5 = "Equip".Translate(labelShort); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text5 = text5 + " " + "EquipWarningBrawler".Translate(); } option = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text5, delegate { equipment.SetForbidden(false, true); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Equip, equipment), JobTag.Misc); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip, 1f); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, equipment, "ReservedBy"); } opts.Add(option); } } if (pawn.apparel != null) { foreach (var apparel in cell.GetThingList(pawn.Map).OfType <Apparel>().Skip(1)) { FloatMenuOption option; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { option = new FloatMenuOption("CannotWear".Translate(apparel.Label, apparel) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (apparel.IsBurning()) { option = new FloatMenuOption("CannotWear".Translate(apparel.Label, apparel) + " (" + "BurningLower".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { option = new FloatMenuOption("CannotWear".Translate(apparel.Label, apparel) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { option = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("ForceWear".Translate(apparel.LabelShort, apparel), delegate { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, apparel, "ReservedBy"); } opts.Add(option); } } }
private void TryEquipDraggedItem(Pawn p) { droppedDraggedItem = false; if (!EquipmentUtility.CanEquip_NewTmp(draggedItem, p, out var cantReason)) { Messages.Message("MessageCantEquipCustom".Translate(cantReason.CapitalizeFirst()), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (draggedItem.def.IsWeapon) { if (p.guest.IsPrisoner) { Messages.Message("MessageCantEquipCustom".Translate("MessagePrisonerCannotEquipWeapon".Translate(p.Named("PAWN"))), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (p.WorkTagIsDisabled(WorkTags.Violent)) { Messages.Message("MessageCantEquipIncapableOfViolence".Translate(p.LabelShort, p), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (!p.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { Messages.Message("MessageCantEquipIncapableOfManipulation".Translate(), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } } Apparel apparel = draggedItem as Apparel; ThingWithComps thingWithComps = draggedItem as ThingWithComps; if (apparel != null && p.apparel != null) { if (!ApparelUtility.HasPartsToWear(p, apparel.def)) { Messages.Message("MessageCantWearApparelMissingBodyParts".Translate(p.LabelShort, p), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (CurrentWearerOf(apparel) != null && CurrentWearerOf(apparel).apparel.IsLocked(apparel)) { Messages.Message("MessageCantUnequipLockedApparel".Translate(), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (p.apparel.WouldReplaceLockedApparel(apparel)) { Messages.Message("MessageWouldReplaceLockedApparel".Translate(p.LabelShort, p), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } tmpExistingApparel.Clear(); tmpExistingApparel.AddRange(p.apparel.WornApparel); for (int i = 0; i < tmpExistingApparel.Count; i++) { if (!ApparelUtility.CanWearTogether(apparel.def, tmpExistingApparel[i].def, p.RaceProps.body)) { p.apparel.Remove(tmpExistingApparel[i]); Pawn pawn = CaravanInventoryUtility.FindPawnToMoveInventoryTo(tmpExistingApparel[i], Pawns, null); if (pawn != null) { pawn.inventory.innerContainer.TryAdd(tmpExistingApparel[i]); continue; } Log.Warning(string.Concat("Could not find any pawn to move ", tmpExistingApparel[i], " to.")); tmpExistingApparel[i].Destroy(); } } p.apparel.Wear((Apparel)apparel.SplitOff(1), dropReplacedApparel: false); if (p.outfits != null) { p.outfits.forcedHandler.SetForced(apparel, forced: true); } } else if (thingWithComps != null && p.equipment != null) { string personaWeaponConfirmationText = EquipmentUtility.GetPersonaWeaponConfirmationText(draggedItem, p); if (!personaWeaponConfirmationText.NullOrEmpty()) { _ = draggedItem; Find.WindowStack.Add(new Dialog_MessageBox(personaWeaponConfirmationText, "Yes".Translate(), delegate { AddEquipment(); }, "No".Translate())); draggedItem = null; return; } AddEquipment(); } else { Log.Warning(string.Concat("Could not make ", p, " equip or wear ", draggedItem)); } draggedItem = null; void AddEquipment() { tmpExistingEquipment.Clear(); tmpExistingEquipment.AddRange(p.equipment.AllEquipmentListForReading); for (int j = 0; j < tmpExistingEquipment.Count; j++) { p.equipment.Remove(tmpExistingEquipment[j]); Pawn pawn2 = CaravanInventoryUtility.FindPawnToMoveInventoryTo(tmpExistingEquipment[j], Pawns, null); if (pawn2 != null) { pawn2.inventory.innerContainer.TryAdd(tmpExistingEquipment[j]); } else { Log.Warning(string.Concat("Could not find any pawn to move ", tmpExistingEquipment[j], " to.")); tmpExistingEquipment[j].Destroy(); } } p.equipment.AddEquipment((ThingWithComps)thingWithComps.SplitOff(1)); } }
public override IEnumerable <string> ConfigErrors() { foreach (string item in base.ConfigErrors()) { yield return(item); } if (backstoryFilters != null && backstoryFiltersOverride != null) { yield return("both backstoryCategories and backstoryCategoriesOverride are defined"); } if (race == null) { yield return("no race"); } if (baseRecruitDifficulty > 1.0001f) { yield return(defName + " recruitDifficulty is greater than 1. 1 means impossible to recruit."); } if (combatPower < 0f) { yield return(defName + " has no combatPower."); } if (weaponMoney != FloatRange.Zero) { float num = 999999f; int k; for (k = 0; k < weaponTags.Count; k++) { IEnumerable <ThingDef> source = DefDatabase <ThingDef> .AllDefs.Where((ThingDef d) => d.weaponTags != null && d.weaponTags.Contains(weaponTags[k])); if (source.Any()) { num = Mathf.Min(num, source.Min((ThingDef d) => PawnWeaponGenerator.CheapestNonDerpPriceFor(d))); } } if (num < 999999f && num > weaponMoney.min) { yield return("Cheapest weapon with one of my weaponTags costs " + num + " but weaponMoney min is " + weaponMoney.min + ", so could end up weaponless."); } } if (!RaceProps.Humanlike && lifeStages.Count != RaceProps.lifeStageAges.Count) { yield return("PawnKindDef defines " + lifeStages.Count + " lifeStages while race def defines " + RaceProps.lifeStageAges.Count); } if (apparelRequired != null) { for (int j = 0; j < apparelRequired.Count; j++) { for (int i = j + 1; i < apparelRequired.Count; i++) { if (!ApparelUtility.CanWearTogether(apparelRequired[j], apparelRequired[i], race.race.body)) { yield return("required apparel can't be worn together (" + apparelRequired[j] + ", " + apparelRequired[i] + ")"); } } } } if (alternateGraphics != null) { foreach (AlternateGraphic alternateGraphic in alternateGraphics) { if (alternateGraphic.Weight < 0f) { yield return("alternate graphic has negative weight."); } } } }
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); }