예제 #1
0
        /// <summary>
        /// Equips tools
        /// </summary>
        /// <param name="pawn"></param>
        /// <param name="def"></param>
        public static void EquipRigthTool(Pawn pawn, StatDef def)
        {
            CompInventory compInventory = ThingCompUtility.TryGetComp <CompInventory>(pawn);
            bool          flag          = compInventory != null;

            if (flag)
            {
                ThingWithComps thingWithComps = pawn.equipment.Primary;
                float          stat           = GetMaxStat(pawn.equipment.Primary, def);

                foreach (ThingWithComps slot in compInventory.container)
                {
                    ThingWithComps thingWithComps2 = slot;
                    bool           flag2           = thingWithComps2.def.IsWeapon;
                    if (flag2)
                    {
                        float maxStat = GetMaxStat(thingWithComps2, def);
                        bool  flag3   = stat < maxStat;
                        if (flag3)
                        {
                            stat           = maxStat;
                            thingWithComps = thingWithComps2;
                        }
                    }
                }

                bool unEquipped = thingWithComps != pawn.equipment.Primary;
                if (unEquipped)
                {
                    compInventory.TrySwitchToWeapon(thingWithComps);
                }
                else
                {
                    bool flag5 = stat == 0f && def != StatDefOf.WorkSpeedGlobal;
                    if (flag5)
                    {
                        RightTools.EquipRigthTool(pawn, StatDefOf.WorkSpeedGlobal);
                    }
                }
            }
        }
        internal static void Notify_PrimaryDestroyed(this Pawn_EquipmentTracker _this)
        {
            // Fetch private fields
            Pawn pawn = (Pawn)pawnFieldInfo.GetValue(_this);

            _this.Remove(_this.Primary);
            if (pawn.Spawned)
            {
                pawn.stances.CancelBusyStanceSoft();
            }

            CE_Utility.TryUpdateInventory(pawn);   // Equipment was destroyed, update inventory

            // Try switching to the next available weapon
            CompInventory inventory = pawn.TryGetComp <CompInventory>();

            if (inventory != null)
            {
                inventory.SwitchToNextViableWeapon(false);
            }
        }
        private float GetStatFactor(Pawn thisPawn)
        {
            float result = 1f;

            Apparel_Backpack  apparelBackpack   = ToolsForHaulUtility.TryGetBackpack(thisPawn);
            CompSlotsBackpack compSlotsBackpack = apparelBackpack?.SlotsComp;

            if (compSlotsBackpack != null)
            {
                result = Mathf.Clamp(compSlotsBackpack.MoveSpeedFactor - compSlotsBackpack.encumberPenalty, 0.5f, 1f);
            }

#if CR
            CompInventory compInventory = thisPawn.TryGetComp <CompInventory>();
            if (compInventory != null)
            {
                result = Mathf.Clamp(compInventory.moveSpeedFactor - compInventory.encumberPenalty, 0.1f, 1f);
                return(result);
            }
#endif
            return(result);
        }
예제 #4
0
 public static void Postfix(WorkGiver_InteractAnimal __instance, ref Job __result, Pawn pawn, Pawn tamee)
 {
     if (__result != null)
     {
         // Check for inventory space
         int           numToCarry = __result.count;
         CompInventory inventory  = pawn.TryGetComp <CompInventory>();
         if (inventory != null)
         {
             if (inventory.CanFitInInventory(__result.targetA.Thing, out int maxCount))
             {
                 __result.count = Mathf.Min(numToCarry, maxCount);
                 pawn.Notify_HoldTrackerItem(__result.targetA.Thing, __result.count);
             }
             else // this should patch WorkGiver_Train && WorkGiver_Tame `JobOnThing`
             {
                 Messages.Message("CE_TamerInventoryFull".Translate(), pawn, MessageTypeDefOf.RejectInput);
                 __result = null;
             }
         }
     }
 }
예제 #5
0
 static public bool ShouldReload(Pawn p)
 {
     //For mechanoids replace the check of is p.RaceProps.HumanLike by custom logic
     if (p.RaceProps.IsMechanoid && p.IsHacked())
     {
         //return true when a mechanoid is hacked and does not have much ammo.
         CompInventory  inventory = p.TryGetComp <CompInventory>();
         ThingWithComps primaryEq = p.equipment.Primary;
         if (inventory != null && primaryEq != null)
         {
             CompAmmoUser ammoUser = primaryEq.TryGetComp <CompAmmoUser>();
             if (ammoUser != null)
             {
                 int ammoCount = inventory.AmmoCountOfDef(ammoUser.CurrentAmmo);
                 int minAmmo   = ammoUser.Props.magazineSize == 0 ? 10 : ammoUser.Props.magazineSize; //No magic numbers?
                 if (ammoCount < minAmmo)
                 {
                     return(true);
                 }
             }
         }
     }
     return(p.RaceProps.Humanlike);
 }
예제 #6
0
            static Rect FillTab_DrawBars(Rect position, object tab)
            {
                bool viewList = (bool)LviewList.GetValue(tab);

                if (!viewList)
                {
                    return(position);
                }
                Pawn          pawn          = (Pawn)LSelPawn.GetValue(tab);
                CompInventory compInventory = pawn.TryGetComp <CompInventory>();

                if (compInventory == null)
                {
                    return(position);
                }

                PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.FrameDisplayed);
                position.height -= 55f;
                Rect rect  = new Rect(15f, position.yMax + 7.5f, position.width - 10f, 20f);
                Rect rect2 = new Rect(15f, rect.yMax + 7.5f, position.width - 10f, 20f);

                Utility_Loadouts.DrawBar(rect2, compInventory.currentBulk, compInventory.capacityBulk, "CE_Bulk".Translate(), pawn.GetBulkTip());
                Utility_Loadouts.DrawBar(rect, compInventory.currentWeight, compInventory.capacityWeight, "CE_Weight".Translate(), pawn.GetWeightTip());
                Text.Font   = GameFont.Small;
                Text.Anchor = TextAnchor.MiddleCenter;
                string str  = CE_StatDefOf.CarryBulk.ValueToString(compInventory.currentBulk, CE_StatDefOf.CarryBulk.toStringNumberSense, true);
                string str2 = CE_StatDefOf.CarryBulk.ValueToString(compInventory.capacityBulk, CE_StatDefOf.CarryBulk.toStringNumberSense, true);

                Widgets.Label(rect2, str + "/" + str2);
                string str3 = compInventory.currentWeight.ToString("0.#");
                string str4 = CE_StatDefOf.CarryWeight.ValueToString(compInventory.capacityWeight, CE_StatDefOf.CarryWeight.toStringNumberSense, true);

                Widgets.Label(rect, str3 + "/" + str4);
                Text.Anchor = TextAnchor.UpperLeft;
                return(position);
            }
 /// <summary>
 /// Determines whether a pawn can be used to suppress targets
 /// </summary>
 /// <returns>True if the pawn has a weapon tagged for suppression and ammo available, false otherwise</returns>
 private static bool CanBeSuppressor(Pawn pawn, CompInventory comp)
 {
     return(comp.rangedWeaponList.Any(w => w.def.IsSuppressive() && w.HasAmmo()));
 }
 /// <summary>
 /// Determines whether a pawn is elligible to be used as a sniper, going for kills on high value targets
 /// </summary>
 /// <returns>True if pawn has a weapon tagged as rifle with ammo available, false otherwise</returns>
 private static bool CanBeSniper(Pawn pawn, CompInventory comp)
 {
     return(comp.rangedWeaponList.Any(w => w.def.IsRifle() && w.HasAmmo()));
 }
        /// <summary>
        /// Tries to give the pawn a job related to picking up or dropping an item from their inventory.
        /// </summary>
        /// <param name="pawn">Pawn to which the job is given.</param>
        /// <returns>Job that the pawn was instructed to do, be it hauling a dropped Thing or going and getting a Thing.</returns>
        protected override Job TryGiveJob(Pawn pawn)
        {
            // Get inventory
            CompInventory inventory = pawn.TryGetComp <CompInventory>();

            if (inventory == null)
            {
                return(null);
            }

            RPGILoadout loadout = pawn.GetLoadout();

            if (loadout != null)
            {
                ThingWithComps dropEq;
                ThingWithComps droppedEq;
                if (pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out droppedEq, pawn.Position, false))
                {
                    if (droppedEq != null)
                    {
                        return(HaulAIUtility.HaulToStorageJob(pawn, droppedEq));
                    }
                }
                Thing dropThing = new Thing();
                int   dropCount = 0;
                Thing droppedThing;
                if (inventory.container.TryDrop(dropThing, pawn.Position, pawn.Map, ThingPlaceMode.Near, dropCount, out droppedThing))
                {
                    if (droppedThing != null)
                    {
                        return(HaulAIUtility.HaulToStorageJob(pawn, droppedThing));
                    }
                    Log.Error(string.Concat(pawn, " tried dropping ", dropThing, " from loadout but resulting thing is null"));
                }

                // Find missing items
                ItemPriority priority;
                Thing        closestThing;
                int          count;
                Pawn         carriedBy;
                bool         doEquip      = false;
                LoadoutSlot  prioritySlot = GetPrioritySlot(pawn, out priority, out closestThing, out count, out carriedBy);
                // moved logic to detect if should equip vs put in inventory here...
                if (closestThing != null)
                {
                    if (closestThing.TryGetComp <CompEquippable>() != null &&
                        !(pawn.story != null && pawn.story.WorkTagIsDisabled(WorkTags.Violent)) &&
                        (pawn.health != null && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) &&
                        (pawn.equipment == null || pawn.equipment.Primary == null || !loadout.Any(s => s.def == pawn.equipment.Primary.def)))
                    {
                        doEquip = true;
                    }
                    if (carriedBy == null)
                    {
                        // Equip gun if unarmed or current gun is not in loadout
                        if (doEquip)
                        {
                            return(new Job(JobDefOf.Equip, closestThing));
                        }
                        return(new Job(JobDefOf.TakeInventory, closestThing)
                        {
                            count = Mathf.Min(closestThing.stackCount, count)
                        });
                    }
                    else
                    {
                        // TODO Implement Take from Others
                        //return new Job(CE_JobDefOf.TakeFromOther, closestThing, carriedBy, doEquip ? pawn : null)
                        //{
                        //    count = doEquip ? 1 : Mathf.Min(closestThing.stackCount, count)
                        //};
                        return(null);
                    }
                }
            }
            return(null);
        }
예제 #10
0
        /// <summary>
        /// Find an item that should be dropped from the pawn's inventory and how much to drop.
        /// </summary>
        /// <param name="pawn"></param>
        /// <param name="dropThing">The thing which should be dropped.</param>
        /// <param name="dropCount">The amount to drop.</param>
        /// <returns>bool, true indicates that the out variables are filled with something to do work on (drop).</returns>
        // NOTE (ProfoundDarkness): Ended up doing this by nibbling away at the pawn's inventory (or dictionary representation of ThingDefs/Count).
        //  Probably not efficient but was easier to handle atm.
        static public bool GetExcessThing(this Pawn pawn, out Thing dropThing, out int dropCount)
        {
            //(ProfoundDarkness) Thanks to erdelf on the RimWorldMod discord for helping me figure out some dictionary stuff and C# concepts related to 'Primitives' (pass by Value).
            CompInventory     inventory = pawn.TryGetComp <CompInventory>();
            Loadout           loadout   = pawn.GetLoadout();
            List <HoldRecord> records   = LoadoutManager.GetHoldRecords(pawn);

            dropThing = null;
            dropCount = 0;

            if (inventory == null || inventory.container == null || loadout == null || loadout.Slots.NullOrEmpty())
            {
                return(false);
            }

            Dictionary <ThingDef, int> listing = GetStorageByThingDef(pawn);

            // iterate over specifics and generics and Chip away at the dictionary.
            foreach (LoadoutSlot slot in loadout.Slots)
            {
                if (slot.thingDef != null && listing.ContainsKey(slot.thingDef))
                {
                    listing[slot.thingDef] -= slot.count;
                    if (listing[slot.thingDef] <= 0)
                    {
                        listing.Remove(slot.thingDef);
                    }
                }
                if (slot.genericDef != null)
                {
                    List <ThingDef> killKeys     = new List <ThingDef>();
                    int             desiredCount = slot.count;
                    // find dictionary entries which corespond to covered slot.
                    foreach (ThingDef def in listing.Keys.Where(td => slot.genericDef.lambda(td)))
                    {
                        listing[def] -= desiredCount;
                        if (listing[def] <= 0)
                        {
                            desiredCount = 0 - listing[def];
                            killKeys.Add(def); // the thing in inventory is exausted, forget about it.
                        }
                        else
                        {
                            break; // we have satisifed this loadout so no need to keep enumerating.
                        }
                    }
                    // cleanup dictionary.
                    foreach (ThingDef def in killKeys)
                    {
                        listing.Remove(def);
                    }
                }
            }

            // if there is something left in the dictionary, that is what is to be dropped.
            // Complicated by the fact that we now consider ammo in guns as part of the inventory...
            if (listing.Any())
            {
                if (records != null && !records.NullOrEmpty())
                {
                    // look at each remaining 'uneaten' thingdef in pawn's inventory.
                    foreach (ThingDef def in listing.Keys)
                    {
                        HoldRecord rec = records.FirstOrDefault(r => r.thingDef == def);
                        if (rec == null)
                        {
                            // the item we have extra of has no HoldRecord, drop it.
                            dropThing = inventory.container.FirstOrDefault(t => t.def == def);
                            if (dropThing != null)
                            {
                                dropCount = listing[def] > dropThing.stackCount ? dropThing.stackCount : listing[def];
                                return(true);
                            }
                        }
                        else if (rec.count < listing[def])
                        {
                            // the item we have extra of HAS a HoldRecord but the amount carried is above the limit of the HoldRecord, drop extra.
                            dropThing = pawn.inventory.innerContainer.FirstOrDefault(t => t.def == def);
                            if (dropThing != null)
                            {
                                dropCount = listing[def] - rec.count;
                                dropCount = dropCount > dropThing.stackCount ? dropThing.stackCount : dropCount;
                                return(true);
                            }
                        }
                    }
                }
                else
                {
                    foreach (ThingDef def in listing.Keys)
                    {
                        dropThing = inventory.container.FirstOrDefault(t => t.GetInnerIfMinified().def == def);
                        if (dropThing != null)
                        {
                            dropCount = listing[def] > dropThing.stackCount ? dropThing.stackCount : listing[def];
                            return(true);
                        }
                    }
                }
            } // else
            return(false);
        }
        static void AddMenuItems(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts)
        {
            // Stabilize
            if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
            {
                foreach (LocalTargetInfo curTarget in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) // !! This needs to be patched into A17
                {
                    Pawn patient = (Pawn)curTarget.Thing;
                    if (patient.Downed
                        //&& pawn.CanReserveAndReach(patient, PathEndMode.InteractionCell, Danger.Deadly)
                        && pawn.CanReach(patient, PathEndMode.InteractionCell, Danger.Deadly) &&
                        patient.health.hediffSet.GetHediffsTendable().Any(h => h.CanBeStabilized()))
                    {
                        if (pawn.story.WorkTypeIsDisabled(WorkTypeDefOf.Doctor))
                        {
                            opts.Add(new FloatMenuOption("CE_CannotStabilize".Translate() + ": " + "IncapableOfCapacity".Translate(WorkTypeDefOf.Doctor.gerundLabel), null, MenuOptionPriority.Default));
                        }
                        else
                        {
                            string label  = "CE_Stabilize".Translate(patient.LabelCap);
                            Action action = delegate
                            {
                                if (pawn.inventory == null || pawn.inventory.innerContainer == null || !pawn.inventory.innerContainer.Any(t => t.def.IsMedicine))
                                {
                                    Messages.Message("CE_CannotStabilize".Translate() + ": " + "CE_NoMedicine".Translate(pawn), patient, MessageSound.RejectInput);
                                    return;
                                }
                                // Drop medicine from inventory
                                Medicine medicine = (Medicine)pawn.inventory.innerContainer.OrderByDescending(t => t.GetStatValue(StatDefOf.MedicalPotency)).FirstOrDefault();
                                Thing    medThing;
                                if (medicine != null && pawn.inventory.innerContainer.TryDrop(medicine, pawn.Position, pawn.Map, ThingPlaceMode.Direct, 1, out medThing))
                                {
                                    Job job = new Job(CE_JobDefOf.Stabilize, patient, medThing);
                                    job.count = 1;
                                    pawn.jobs.TryTakeOrderedJob(job);
                                    PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_Stabilizing, KnowledgeAmount.Total);
                                }
                            };
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, action, MenuOptionPriority.Default, null, patient), pawn, patient, "ReservedBy"));
                        }
                    }
                }
            }

            // Item pickup.
            IntVec3       c             = IntVec3.FromVector3(clickPos);
            CompInventory compInventory = pawn.TryGetComp <CompInventory>();

            if (compInventory != null)
            {
                List <Thing> thingList = c.GetThingList(pawn.Map);
                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))
                        {
                            opts.Add(new FloatMenuOption("CannotPickUp".Translate() + " " + item.LabelShort + " (" + "NoPath".Translate() + ")", null));
                        }
                        else if (!compInventory.CanFitInInventory(item, out count))
                        {
                            opts.Add(new FloatMenuOption("CannotPickUp".Translate(new object[] { item.LabelShort }) + " (" + "CE_InventoryFull".Translate() + ")", null));
                        }
                        // Pick up x
                        else if (count == 1)
                        {
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("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, JobTag.Misc);
                                pawn.Notify_HoldTrackerJob(job);
                                PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.SpecificInteraction);
                            }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, item, "ReservedBy"));
                        }
                        else
                        {
                            if (count < item.stackCount)
                            {
                                opts.Add(new FloatMenuOption("CannotPickUpAll".Translate(new object[]
                                {
                                    item.Label
                                }) + " (" + "CE_InventoryFull".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null));
                            }
                            else
                            {
                                opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("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, JobTag.Misc);
                                    pawn.Notify_HoldTrackerJob(job);
                                    PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.SpecificInteraction);
                                }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, item, "ReservedBy"));
                            }
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("PickUpSome".Translate(new object[]
                            {
                                item.Label
                            }), delegate
                            {
                                int to = Mathf.Min(count, item.stackCount);
                                Dialog_Slider window = new Dialog_Slider("PickUpCount".Translate(new object[]
                                {
                                    item.LabelShort
                                }), 1, to, delegate(int selectCount)
                                {
                                    item.SetForbidden(false, false);
                                    Job job   = new Job(JobDefOf.TakeInventory, item);
                                    job.count = selectCount;
                                    pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
                                    pawn.Notify_HoldTrackerJob(job);
                                }, -2147483648);
                                Find.WindowStack.Add(window);
                                PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.SpecificInteraction);
                            }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, item, "ReservedBy"));
                        }
                    }
                }
            }
        }
        public static void DrawGreedyCE(PawnModal selPawn, Vector2 size)
        {
            // get the inventory comp
            CompInventory comp = selPawn.Pawn.TryGetComp <CompInventory>();

            // set up rects
            Rect listRect = new Rect(
                _margin,
                _topPadding,
                size.x - 2 * _margin,
                size.y - _topPadding - _margin);

            // draw bars at the bottom
            if (comp != null)
            {
                PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.FrameDisplayed);

                // adjust rects if comp found
                listRect.height -= (_margin / 2 + _barHeight) * 2;
                Rect weightRect = new Rect(_margin, listRect.yMax + _margin / 2, listRect.width, _barHeight);
                Rect bulkRect   = new Rect(_margin, weightRect.yMax + _margin / 2, listRect.width, _barHeight);

                // draw bars
                Utility_Loadouts.DrawBar(bulkRect, comp.currentBulk, comp.capacityBulk, "CE_Bulk".Translate(), selPawn.Pawn.GetBulkTip());
                Utility_Loadouts.DrawBar(weightRect, comp.currentWeight, comp.capacityWeight, "CE_Weight".Translate(), selPawn.Pawn.GetWeightTip());

                // draw text overlays on bars
                Text.Font   = GameFont.Small;
                Text.Anchor = TextAnchor.MiddleCenter;

                string currentBulk  = CE_StatDefOf.CarryBulk.ValueToString(comp.currentBulk, CE_StatDefOf.CarryBulk.toStringNumberSense);
                string capacityBulk = CE_StatDefOf.CarryBulk.ValueToString(comp.capacityBulk, CE_StatDefOf.CarryBulk.toStringNumberSense);
                Widgets.Label(bulkRect, currentBulk + "/" + capacityBulk);

                string currentWeight  = comp.currentWeight.ToString("0.#");
                string capacityWeight = CE_StatDefOf.CarryWeight.ValueToString(comp.capacityWeight, CE_StatDefOf.CarryWeight.toStringNumberSense);
                Widgets.Label(weightRect, currentWeight + "/" + capacityWeight);

                Text.Anchor = TextAnchor.UpperLeft;
            }

            // start drawing list (rip from ITab_Pawn_Gear)

            GUI.BeginGroup(listRect);
            Text.Font = GameFont.Small;
            GUI.color = Color.white;
            Rect outRect  = new Rect(0f, 0f, listRect.width, listRect.height);
            Rect viewRect = new Rect(0f, 0f, listRect.width - 16f, _scrollViewHeight);

            Widgets.BeginScrollView(outRect, ref _scrollPosition, viewRect);
            float num = 0f;

            Utility.TryDrawComfyTemperatureRange(selPawn.Pawn, ref num, viewRect.width);
            if (Utility.ShouldShowOverallArmor(selPawn.Pawn))
            {
                Widgets.ListSeparator(ref num, viewRect.width, "OverallArmor".Translate());
                Utility.TryDrawOverallArmor(selPawn.Pawn, ref num, viewRect.width, StatDefOf.ArmorRating_Blunt, "ArmorBlunt".Translate(), " " + "CE_MPa".Translate());
                Utility.TryDrawOverallArmor(selPawn.Pawn, ref num, viewRect.width, StatDefOf.ArmorRating_Sharp, "ArmorSharp".Translate(), "CE_mmRHA".Translate());
                Utility.TryDrawOverallArmor(selPawn.Pawn, ref num, viewRect.width, StatDefOf.ArmorRating_Heat, "ArmorHeat".Translate(), "%");
            }
            if (Utility.ShouldShowEquipment(selPawn.Pawn))
            {
                Widgets.ListSeparator(ref num, viewRect.width, "Equipment".Translate());
                foreach (ThingWithComps current in selPawn.Pawn.equipment.AllEquipmentListForReading)
                {
                    Utility.DrawThingRow(selPawn, ref num, viewRect.width, current);
                }
            }
            if (Utility.ShouldShowApparel(selPawn.Pawn))
            {
                Widgets.ListSeparator(ref num, viewRect.width, "Apparel".Translate());
                foreach (Apparel current2 in from ap in selPawn.Pawn.apparel.WornApparel
                         orderby ap.def.apparel.bodyPartGroups[0].listOrder descending
                         select ap)
                {
                    Utility.DrawThingRow(selPawn, ref num, viewRect.width, current2);
                }
            }
            if (Utility.ShouldShowInventory(selPawn.Pawn))
            {
                num += 3;            // Make a little room for the button.

                float buttonY = num; // Could be accomplished with seperator being after the button...

                Widgets.ListSeparator(ref num, viewRect.width, "Inventory".Translate());
                Loadout curLoadout = selPawn.Pawn.GetLoadout();
                if (!(curLoadout == null || curLoadout.Slots.NullOrEmpty()))
                {
                    Widgets.Label(new Rect(viewRect.width / 4, buttonY, viewRect.width / 4, 26f), selPawn.Pawn.GetLoadout().label);
                }
                else
                {
                    Widgets.Label(new Rect(viewRect.width / 4, buttonY, viewRect.width / 4, 26f), "CE_NoLoadouts".Translate());
                }

                // Select loadout button
                if (Widgets.ButtonText(new Rect(viewRect.width / 2, buttonY, viewRect.width / 4, 26f), Translator.Translate("CE_SelectLoadout"), true, false, true))
                {
                    List <Loadout> loadouts = (from l in LoadoutManager.Loadouts
                                               where !l.defaultLoadout
                                               select l).ToList();
                    List <FloatMenuOption> list = new List <FloatMenuOption>();
                    if (loadouts.Count == 0)
                    {
                        list.Add(new FloatMenuOption(Translator.Translate("CE_NoLoadouts"), null));
                    }
                    else
                    {
                        for (int i = 0; i < loadouts.Count; i++)
                        {
                            int local_i = i;
                            list.Add(new FloatMenuOption(loadouts[i].LabelCap, delegate
                            {
                                selPawn.Pawn.SetLoadout(loadouts[local_i]);
                            }));
                        }
                    }
                    Find.WindowStack.Add(new FloatMenu(list));
                }

                Rect loadoutButtonRect = new Rect(viewRect.width / 4 * 3, buttonY, viewRect.width / 4, 26f); // button is half the available width...
                if (Widgets.ButtonText(loadoutButtonRect, "Corgi_OpenLoadout".Translate()))
                {
                    if (selPawn.Pawn.IsColonist && (curLoadout == null || curLoadout.Slots.NullOrEmpty()))
                    {
                        Loadout loadout = selPawn.Pawn.GenerateLoadoutFromPawn();
                        LoadoutManager.AddLoadout(loadout);
                        selPawn.Pawn.SetLoadout(loadout);
                    }

                    // Original comments
                    //// UNDONE ideally we'd open the assign (MainTabWindow_OutfitsAndLoadouts) tab as if the user clicked on it here.
                    //// (ProfoundDarkness) But I have no idea how to do that just yet.  The attempts I made seem to put the RimWorld UI into a bit of a bad state.
                    ////                     ie opening the tab like the dialog below.
                    ////                    Need to understand how RimWorld switches tabs and see if something similar can be done here
                    ////                     (or just remove the unfinished marker).

                    //// Opening this window is the same way as if from the assign tab so should be correct.
                    Find.WindowStack.Add(new Dialog_ManageLoadouts(selPawn.Pawn.GetLoadout()));
                }

                workingInvList.Clear();
                workingInvList.AddRange(selPawn.Pawn.inventory.innerContainer);
                for (int i = 0; i < workingInvList.Count; i++)
                {
                    Utility.DrawThingRow(selPawn, ref num, viewRect.width, workingInvList[i].GetInnerIfMinified(), true);
                }
            }
            if (Event.current.type == EventType.Layout)
            {
                _scrollViewHeight = num + 30f;
            }
            Widgets.EndScrollView();
            GUI.EndGroup();
            GUI.color   = Color.white;
            Text.Anchor = TextAnchor.UpperLeft;
        }
        public static void DrawJealousCE(PawnModal selPawn, Vector2 size)
        {
            // Races that don't have a humanoid body will fall back to Greedy tab
            if (selPawn.Pawn.RaceProps.body != BodyDefOf.Human)
            {
                DrawGreedyCE(selPawn, size);
                return;
            }

            // set up rects
            Rect listRect = new Rect(
                _margin,
                _topPadding,
                size.x - 2 * _margin,
                size.y - _topPadding - _margin);

            // get the inventory comp
            CompInventory comp = selPawn.Pawn.TryGetComp <CompInventory>();

            if (comp != null)
            {
                PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.FrameDisplayed);

                // adjust rects if comp found
                listRect.height -= (_margin / 2 + _barHeight) * 2;
                Rect weightRect = new Rect(_margin, listRect.yMax + _margin / 2, listRect.width, _barHeight);
                Rect bulkRect   = new Rect(_margin, weightRect.yMax + _margin / 2, listRect.width, _barHeight);

                // draw bars
                Utility_Loadouts.DrawBar(bulkRect, comp.currentBulk, comp.capacityBulk, "CE_Bulk".Translate(), selPawn.Pawn.GetBulkTip());
                Utility_Loadouts.DrawBar(weightRect, comp.currentWeight, comp.capacityWeight, "CE_Weight".Translate(), selPawn.Pawn.GetWeightTip());
                Utility_DrawCE.DrawBulkBreakdown(selPawn.Pawn, bulkRect);
                Utility.DrawMassBreakdown(selPawn.Pawn, weightRect);

                // draw text overlays on bars
                Text.Font   = GameFont.Small;
                Text.Anchor = TextAnchor.MiddleCenter;

                string currentBulk  = CE_StatDefOf.CarryBulk.ValueToString(comp.currentBulk, CE_StatDefOf.CarryBulk.toStringNumberSense);
                string capacityBulk = CE_StatDefOf.CarryBulk.ValueToString(comp.capacityBulk, CE_StatDefOf.CarryBulk.toStringNumberSense);
                Widgets.Label(bulkRect, currentBulk + "/" + capacityBulk);

                string currentWeight  = comp.currentWeight.ToString("0.#");
                string capacityWeight = CE_StatDefOf.CarryWeight.ValueToString(comp.capacityWeight, CE_StatDefOf.CarryWeight.toStringNumberSense);
                Widgets.Label(weightRect, currentWeight + "/" + capacityWeight);

                Text.Anchor = TextAnchor.UpperLeft;
            }

            // start drawing the view
            GUI.BeginGroup(listRect);
            Text.Font = GameFont.Small;
            GUI.color = Color.white;
            Rect outRect  = new Rect(0f, 0f, listRect.width, listRect.height);
            Rect viewRect = new Rect(0f, 0f, listRect.width - 16f, _scrollViewHeight);

            Widgets.BeginScrollView(outRect, ref _scrollPosition, viewRect);

            // draw Mass info and Temperature on the side
            Vector2 rectStat = new Vector2(374, 0);

            Utility.TryDrawComfyTemperatureRangeWithImage(selPawn.Pawn, rectStat);

            // draw armor rating for humanoid on the side
            Rect rectarmor = new Rect(374f, 84f, 128f, 85f);

            TooltipHandler.TipRegion(rectarmor, "OverallArmor".Translate());
            Rect rectblunt = new Rect(rectarmor.x, rectarmor.y, rectarmor.width, 27f);

            Utility.TryDrawOverallArmorWithImage(selPawn.Pawn, rectblunt, StatDefOf.ArmorRating_Blunt, "ArmorBlunt".Translate(),
                                                 ContentFinder <Texture2D> .Get("UI/Icons/Sandy_ArmorBlunt_Icon", true), true, " " + "CE_MPa".Translate());
            Rect rectsharp = new Rect(rectarmor.x, rectarmor.y + 30f, rectarmor.width, 27f);

            Utility.TryDrawOverallArmorWithImage(selPawn.Pawn, rectsharp, StatDefOf.ArmorRating_Sharp, "ArmorSharp".Translate(),
                                                 ContentFinder <Texture2D> .Get("UI/Icons/Sandy_ArmorSharp_Icon", true), true, "CE_mmRHA".Translate());
            Rect rectheat = new Rect(rectarmor.x, rectarmor.y + 60f, rectarmor.width, 27f);

            Utility.TryDrawOverallArmorWithImage(selPawn.Pawn, rectheat, StatDefOf.ArmorRating_Heat, "ArmorHeat".Translate(),
                                                 ContentFinder <Texture2D> .Get("UI/Icons/Sandy_ArmorHeat_Icon", true), true);

            //Pawn
            Color color = new Color(1f, 1f, 1f, 1f);

            GUI.color = color;
            Rect PawnRect = new Rect(374f, 172f, 128f, 128f);

            Utility.DrawColonist(PawnRect, selPawn.Pawn);

            // draw equipment (equipment means barrel that can shoot bullets, plank that can slice flesh in half)
            // It is weapon.
            SmartRect rectForEquipment = new SmartRect(new Rect(), CorgiBodyPartGroupDefOf.Arse,
                                                       PawnRect.x, PawnRect.x, null, PawnRect.x, size.x - 20f);

            rectForEquipment.y      = PawnRect.yMax;
            rectForEquipment.width  = _apparelRectWidth;
            rectForEquipment.height = _apparelRectHeight;
            if (Utility.ShouldShowEquipment(selPawn.Pawn) && (selPawn.Pawn.RaceProps.body == BodyDefOf.Human))
            {
                Rect primaryRect = rectForEquipment.NextAvailableRect();
                GUI.DrawTexture(primaryRect, ContentFinder <Texture2D> .Get("UI/Widgets/DesButBG", true));
                TooltipHandler.TipRegion(primaryRect, "Corgi_PrimaryWeapon".Translate());
                foreach (ThingWithComps fireShootingBarrel in selPawn.Pawn.equipment.AllEquipmentListForReading)
                {
                    if (fireShootingBarrel == selPawn.Pawn.equipment.Primary)
                    {
                        Utility.DrawThingRowWithImage(selPawn, primaryRect, fireShootingBarrel);
                    }
                    else
                    {
                        UtilityDraw.DrawThumbnails(selPawn, rectForEquipment, fireShootingBarrel, _apparelOverflow);
                    }
                }
                // Draw shield
                foreach (Apparel apparel in selPawn.Pawn.apparel.WornApparel)
                {
                    if (apparel.def.apparel.LastLayer == CEApparelLayerDefOf.Shield)
                    {
                        rectForEquipment = rectForEquipment
                                           .GetWorkingRect(CorgiBodyPartGroupDefOf.Arse,
                                                           PawnRect.x,
                                                           PawnRect.x);
                        UtilityDraw.DrawThumbnails(selPawn, rectForEquipment, apparel, _apparelOverflow);
                    }
                }
            }

            // List order: Head:200-181, Neck:180-101, Torso:100-51, Waist:50-11, Legs:10-0
            // Check \steamapps\common\RimWorld\Mods\Core\Defs\Bodies\BodyPartGroups.xml
            IEnumerable <Apparel> apparels = from ap in selPawn.Pawn.apparel.WornApparel
                                             where ap.def.apparel.LastLayer != CEApparelLayerDefOf.Shield
                                             orderby ap.def.apparel.bodyPartGroups[0].listOrder descending
                                             select ap;

            IEnumerator <Apparel> apparelCounter = apparels.GetEnumerator();

            //Hats. BodyGroup: Fullhead; Layer: Overhead
            _smartRectHead = _smartRectCurrent =
                new SmartRect(new Rect(0, 0, _apparelRectWidth, _apparelRectHeight),
                              BodyPartGroupDefOf.UpperHead,
                              _startingXforRect, _startingXforRect,
                              _smartRects, 10, rectStat.x);
            Rect HeadOverRect = _smartRectCurrent.NextAvailableRect();

            GUI.DrawTexture(HeadOverRect, ContentFinder <Texture2D> .Get("UI/Widgets/DesButBG", true));
            Rect tipRect1 = HeadOverRect;

            TooltipHandler.TipRegion(tipRect1, "Sandy_Head".Translate());

            // cont is used to Check if there is more apparel in the list
            bool cont     = false;
            bool hatDrawn = false;

            // Draw apparels on the head
            while (apparelCounter.MoveNext())
            {
                Apparel apparel = apparelCounter.Current;
                if (apparel.def.apparel.bodyPartGroups[0].listOrder > CorgiBodyPartGroupDefOf.Neck.listOrder)
                {
                    // Check RimWorld.Pawn_ApparelTracker.Wear() for more information on wearing rules
                    if ((apparel.def.apparel.bodyPartGroups.Contains(CorgiBodyPartGroupDefOf.FullHead) ||
                         apparel.def.apparel.bodyPartGroups.Contains(CorgiBodyPartGroupDefOf.UpperHead)) &&
                        hatDrawn == false)
                    {
                        Utility.DrawThingRowWithImage(selPawn, HeadOverRect, apparel);
                        hatDrawn = true;
                    }
                    else
                    {
                        _smartRectCurrent = _smartRectCurrent
                                            .GetWorkingRect(CorgiBodyPartGroupDefOf.UpperHead,
                                                            _startingXforRect,
                                                            _startingXforRect);
                        UtilityDraw.DrawThumbnails(selPawn, _smartRectCurrent, apparel, _apparelOverflow);
                    }
                }
                else
                {
                    cont = true;
                    break;
                }
            }

            // Draw apparels on the neck
            if (cont)
            {
                cont = false;
                do
                {
                    Apparel apparel = apparelCounter.Current;
                    if (apparel.def.apparel.bodyPartGroups[0].listOrder <= CorgiBodyPartGroupDefOf.Neck.listOrder &&
                        apparel.def.apparel.bodyPartGroups[0].listOrder > BodyPartGroupDefOf.Torso.listOrder)
                    {
                        _smartRectCurrent = _smartRectCurrent
                                            .GetWorkingRect(CorgiBodyPartGroupDefOf.Neck,
                                                            _startingXforRect, _startingXforRect);
                        UtilityDraw.DrawThumbnails(selPawn, _smartRectCurrent, apparel, _apparelOverflow);
                    }
                    else
                    {
                        cont = true;
                        break;
                    }
                } while (apparelCounter.MoveNext());
            }

            #region Draw Torso
            // Draw apparels on Torso
            _smartRectCurrent = _smartRectCurrent
                                .GetWorkingRect(CorgiBodyPartGroupDefOf.Torso,
                                                _startingXforRect, _startingXforRect);

            //Shirts. BodyGroup: Torso; Layer: OnSkin
            Rect TorsoSkinRect = _smartRectCurrent.NextAvailableRect();
            GUI.DrawTexture(TorsoSkinRect, ContentFinder <Texture2D> .Get("UI/Widgets/DesButBG", true));
            Rect tipRect3 = TorsoSkinRect.ContractedBy(12f);
            TooltipHandler.TipRegion(tipRect3, "Sandy_TorsoOnSkin".Translate());

            //Vests. BodyGroup: Torso; Layer: Middle
            Rect TorsoMidRect = _smartRectCurrent.NextAvailableRect();
            GUI.DrawTexture(TorsoMidRect, ContentFinder <Texture2D> .Get("UI/Widgets/DesButBG", true));
            Rect tipRect2 = TorsoMidRect.ContractedBy(12f);
            TooltipHandler.TipRegion(tipRect2, "Sandy_TorsoMiddle".Translate());

            //Dusters. BodyGroup: Torso; Layer: Shell
            Rect TorsoShellRect = _smartRectCurrent.NextAvailableRect();
            GUI.DrawTexture(TorsoShellRect, ContentFinder <Texture2D> .Get("UI/Widgets/DesButBG", true));
            Rect tipRect4 = TorsoShellRect.ContractedBy(12f);
            TooltipHandler.TipRegion(tipRect4, "Sandy_TorsoShell".Translate());

            if (cont)
            {
                cont = false;
                do
                {
                    Apparel apparel = apparelCounter.Current;
                    if (apparel.def.apparel.bodyPartGroups[0].listOrder <= CorgiBodyPartGroupDefOf.Torso.listOrder &&
                        apparel.def.apparel.bodyPartGroups[0].listOrder > CorgiBodyPartGroupDefOf.Waist.listOrder)
                    {
                        if (apparel.def.apparel.bodyPartGroups[0] == BodyPartGroupDefOf.Torso)
                        {
                            if (apparel.def.apparel.LastLayer == ApparelLayerDefOf.Shell)
                            {
                                Utility.DrawThingRowWithImage(selPawn, TorsoShellRect, apparel);
                            }
                            else if (apparel.def.apparel.LastLayer == ApparelLayerDefOf.Middle)
                            {
                                Utility.DrawThingRowWithImage(selPawn, TorsoMidRect, apparel);
                            }
                            else if (apparel.def.apparel.LastLayer == ApparelLayerDefOf.OnSkin)
                            {
                                Utility.DrawThingRowWithImage(selPawn, TorsoSkinRect, apparel);
                            }
                        }
                        else
                        {
                            _smartRectCurrent = _smartRectCurrent
                                                .GetWorkingRect(CorgiBodyPartGroupDefOf.Torso,
                                                                _startingXforRect,
                                                                _startingXforRect);
                            UtilityDraw.DrawThumbnails(selPawn, _smartRectCurrent, apparel, _apparelOverflow);
                        }
                    }
                    else
                    {
                        cont = true;
                        break;
                    }
                } while (apparelCounter.MoveNext());
            }
            #endregion Draw Torso

            #region Draw Waist
            // Draw apparels on waist
            _smartRectCurrent = _smartRectCurrent
                                .GetWorkingRect(CorgiBodyPartGroupDefOf.Waist,
                                                _startingXforRect,
                                                _startingXforRect);
            //Belts. BodyGroup: Waist; Layer: Belt
            Rect WaistBeltRect = _smartRectCurrent.NextAvailableRect();
            GUI.DrawTexture(WaistBeltRect, ContentFinder <Texture2D> .Get("UI/Widgets/DesButBG", true));
            Rect tipRect5 = WaistBeltRect.ContractedBy(12f);
            TooltipHandler.TipRegion(tipRect5, "Sandy_Belt".Translate());

            if (cont)
            {
                cont = false;
                do
                {
                    Apparel apparel = apparelCounter.Current;
                    if (apparel.def.apparel.bodyPartGroups[0].listOrder <= CorgiBodyPartGroupDefOf.Waist.listOrder &&
                        apparel.def.apparel.bodyPartGroups[0].listOrder > CorgiBodyPartGroupDefOf.Legs.listOrder)
                    {
                        if (apparel.def.apparel.LastLayer == ApparelLayerDefOf.Belt)
                        {
                            Utility.DrawThingRowWithImage(selPawn, WaistBeltRect, apparel);
                        }
                        else
                        {
                            _smartRectCurrent = _smartRectCurrent
                                                .GetWorkingRect(CorgiBodyPartGroupDefOf.Waist,
                                                                _startingXforRect,
                                                                _startingXforRect);
                            UtilityDraw.DrawThumbnails(selPawn, _smartRectCurrent, apparel, _apparelOverflow);
                        }
                    }
                    else
                    {
                        cont = true;
                        break;
                    }
                } while (apparelCounter.MoveNext());
            }
            #endregion Draw Waist

            #region Draw Legs
            // Draw apparels on lesg
            _smartRectCurrent = _smartRectCurrent
                                .GetWorkingRect(CorgiBodyPartGroupDefOf.Legs,
                                                _startingXforRect,
                                                _startingXforRect);
            //Pants. BodyGroup: Legs; Layer: OnSkin
            Rect LegSkinRect = _smartRectCurrent.NextAvailableRect();
            GUI.DrawTexture(LegSkinRect, ContentFinder <Texture2D> .Get("UI/Widgets/DesButBG", true));
            Rect tipRect6 = LegSkinRect.ContractedBy(12f);
            TooltipHandler.TipRegion(tipRect6, "Sandy_Pants".Translate());
            if (cont)
            {
                bool pantWore = false;
                cont = false;
                do
                {
                    Apparel apparel = apparelCounter.Current;
                    if (apparel.def.apparel.bodyPartGroups[0].listOrder <= CorgiBodyPartGroupDefOf.Legs.listOrder &&
                        apparel.def.apparel.bodyPartGroups[0].listOrder > 0)
                    {
                        if (apparel.def.apparel.LastLayer == ApparelLayerDefOf.OnSkin && pantWore == false)
                        {
                            Utility.DrawThingRowWithImage(selPawn, LegSkinRect, apparel);
                            pantWore = true;
                        }
                        else
                        {
                            _smartRectCurrent = _smartRectCurrent
                                                .GetWorkingRect(CorgiBodyPartGroupDefOf.Legs,
                                                                _startingXforRect,
                                                                _startingXforRect);
                            UtilityDraw.DrawThumbnails(selPawn, _smartRectCurrent, apparel, _apparelOverflow);
                        }
                    }
                    else
                    {
                        cont = true;
                        break;
                    }
                } while (apparelCounter.MoveNext());
            }
            #endregion Draw Legs

            #region Draw Traits

            float traitY     = _smartRectCurrent.Rect.yMax + _smartRectCurrent.HeightGap;
            Rect  rectTraits = new Rect(_margin, traitY, 80f, 30f);
            Text.Font = GameFont.Medium;
            Widgets.Label(rectTraits, "Traits".Translate());
            Text.Font = GameFont.Small;
            float traitX = _margin + 80f;
            foreach (Trait trait in selPawn.Pawn.story.traits.allTraits)
            {
                Rect rectTrait = new Rect(traitX, traitY, rectStat.x - traitX - _margin, Utility.StandardLineHeight);
                if (Mouse.IsOver(rectTrait))
                {
                    Widgets.DrawHighlight(rectTrait);
                }
                Widgets.Label(rectTrait, trait.LabelCap);
                TooltipHandler.TipRegion(rectTrait, trait.TipString(selPawn.Pawn));
                traitY += Utility.StandardLineHeight;
            }


            #endregion

            #region Extra Apparels
            // Put undrawn into overflow list
            if (cont)
            {
                do
                {
                    _apparelOverflow.Add(apparelCounter.Current);
                } while (apparelCounter.MoveNext());
            }
            // Try to draw the extras
            UtilityDraw.DrawApparelToNextRow(selPawn, _smartRectHead, _apparelOverflow);

            // If there is any more remains, put them into their own category
            if (_apparelOverflow.Count > 0)
            {
                float rollingY1 = traitY;
                //float rollingY1 = _smartRectCurrent.y + _smartRectCurrent.height + Utility.StandardLineHeight;
                Widgets.ListSeparator(ref rollingY1, viewRect.width, "Corgi_ExtraApparels".Translate());
                _smartRectCurrent   = _smartRectCurrent.GetWorkingRect(CorgiBodyPartGroupDefOf.Arse, _margin, _margin);
                _smartRectCurrent.y = rollingY1 + Utility.StandardLineHeight;

                do
                {
                    List <ThingWithComps> tempList = new List <ThingWithComps>(_apparelOverflow);
                    _apparelOverflow.Clear();
                    foreach (Apparel apparel in tempList)
                    {
                        UtilityDraw.DrawThumbnails(selPawn, _smartRectCurrent, apparel, _apparelOverflow);
                    }
                    if (_apparelOverflow.Count > 0)
                    {
                        SmartRect temp = _smartRectCurrent.CreateSibling(CorgiBodyPartGroupDefOf.Arse);
                        temp.PreviousSibling          = _smartRectCurrent;
                        _smartRectCurrent.NextSibling = temp;
                        _smartRectCurrent             = temp;
                        continue;
                    }
                } while (_apparelOverflow.Count > 0);
            }
            #endregion Extra Apparels

            #region Draw Inventory
            // Draw inventory
            float rollingY = 0;
            if (Utility.ShouldShowInventory(selPawn.Pawn))
            {
                rollingY = Math.Max(Math.Max(traitY, _smartRectCurrent.Rect.yMax), rectForEquipment.Rect.yMax);
                //if (_smartRectCurrent.Rect.yMax > rectForEquipment.Rect.yMax)
                //{
                //    rollingY = _smartRectCurrent.Rect.yMax;
                //}
                //else
                //{
                //    rollingY = rectForEquipment.Rect.yMax;
                //}
                rollingY += Utility.StandardLineHeight;
                rollingY += 3; // Make a little room for the button.
                float buttonY = rollingY;
                Widgets.ListSeparator(ref rollingY, viewRect.width, "Inventory".Translate());

                Loadout curLoadout = selPawn.Pawn.GetLoadout();
                if (!(curLoadout == null || curLoadout.Slots.NullOrEmpty()))
                {
                    Widgets.Label(new Rect(viewRect.width / 4, buttonY, viewRect.width / 4, 26f), selPawn.Pawn.GetLoadout().label);
                }
                else
                {
                    Widgets.Label(new Rect(viewRect.width / 4, buttonY, viewRect.width / 4, 26f), "CE_NoLoadouts".Translate());
                }

                //Select loadout button
                if (Widgets.ButtonText(new Rect(viewRect.width / 2, buttonY, viewRect.width / 4, 26f), Translator.Translate("CE_SelectLoadout"), true, false, true))
                {
                    List <Loadout> loadouts = (from l in LoadoutManager.Loadouts
                                               where !l.defaultLoadout
                                               select l).ToList();
                    List <FloatMenuOption> list = new List <FloatMenuOption>();
                    if (loadouts.Count == 0)
                    {
                        list.Add(new FloatMenuOption(Translator.Translate("CE_NoLoadouts"), null));
                    }
                    else
                    {
                        for (int i = 0; i < loadouts.Count; i++)
                        {
                            int local_i = i;
                            list.Add(new FloatMenuOption(loadouts[i].LabelCap, delegate
                            {
                                selPawn.Pawn.SetLoadout(loadouts[local_i]);
                            }));
                        }
                    }
                    Find.WindowStack.Add(new FloatMenu(list));
                }

                Rect loadoutButtonRect = new Rect(viewRect.width / 4 * 3, buttonY, viewRect.width / 4, 26f); // button is half the available width...
                if (Widgets.ButtonText(loadoutButtonRect, "Corgi_OpenLoadout".Translate()))
                {
                    if (selPawn.Pawn.IsColonist && (curLoadout == null || curLoadout.Slots.NullOrEmpty()))
                    {
                        Loadout loadout = selPawn.Pawn.GenerateLoadoutFromPawn();
                        LoadoutManager.AddLoadout(loadout);
                        selPawn.Pawn.SetLoadout(loadout);
                    }

                    // Original comments
                    //// UNDONE ideally we'd open the assign (MainTabWindow_OutfitsAndLoadouts) tab as if the user clicked on it here.
                    //// (ProfoundDarkness) But I have no idea how to do that just yet.  The attempts I made seem to put the RimWorld UI into a bit of a bad state.
                    ////                     ie opening the tab like the dialog below.
                    ////                    Need to understand how RimWorld switches tabs and see if something similar can be done here
                    ////                     (or just remove the unfinished marker).

                    //// Opening this window is the same way as if from the assign tab so should be correct.
                    Find.WindowStack.Add(new Dialog_ManageLoadouts(selPawn.Pawn.GetLoadout()));
                }

                workingInvList.Clear();
                workingInvList.AddRange(selPawn.Pawn.inventory.innerContainer);
                for (int i = 0; i < workingInvList.Count; i++)
                {
                    Utility.DrawThingRow(selPawn, ref rollingY, viewRect.width, workingInvList[i].GetInnerIfMinified(), true);
                }
            }
            #endregion Draw Inventory

            if (Event.current.type == EventType.Layout)
            {
                _scrollViewHeight = rollingY + 30f;
            }

            Widgets.EndScrollView();
            GUI.EndGroup();
            GUI.color   = Color.white;
            Text.Anchor = TextAnchor.UpperLeft;
            Reset();
        }
예제 #14
0
            static void DropDownThingMenu(object tab, Thing thing)
            {
                Pawn SelPawnForGear         = (Pawn)LSelPawnForGear.GetValue(tab);
                Pawn SelPawn                = (Pawn)LSelPawn.GetValue(tab);
                bool canControl             = (bool)LCanControl.GetValue(tab);
                List <FloatMenuOption> list = new List <FloatMenuOption>();

                list.Add(new FloatMenuOption("ThingInfo".Translate(), delegate()
                {
                    Find.WindowStack.Add(new Dialog_InfoCard(thing));
                }, MenuOptionPriority.Default, null, null, 0f, null, null));
                //bool canControl = this.CanControl;
                if (canControl)
                {
                    ThingWithComps eq     = thing as ThingWithComps;
                    bool           flag10 = eq != null && eq.TryGetComp <CompEquippable>() != null;
                    if (flag10)
                    {
                        CompInventory  compInventory  = SelPawnForGear.TryGetComp <CompInventory>();
                        CompBiocodable compBiocodable = eq.TryGetComp <CompBiocodable>();
                        bool           flag11         = compInventory != null;
                        if (flag11)
                        {
                            string          value  = GenLabel.ThingLabel(eq.def, eq.Stuff, 1);
                            bool            flag12 = compBiocodable != null && compBiocodable.Biocoded && compBiocodable.CodedPawn != SelPawnForGear;
                            FloatMenuOption item;
                            if (flag12)
                            {
                                item = new FloatMenuOption("CannotEquip".Translate(value) + ": " + "BiocodedCodedForSomeoneElse".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null);
                            }
                            else
                            {
                                bool flag13 = SelPawnForGear.IsQuestLodger() && !EquipmentUtility.QuestLodgerCanEquip(eq, SelPawnForGear);
                                if (flag13)
                                {
                                    TaggedString t = SelPawnForGear.equipment.AllEquipmentListForReading.Contains(eq) ? "CE_CannotPutAway".Translate(value) : "CannotEquip".Translate(value);
                                    item = new FloatMenuOption(t + ": " + "CE_CannotChangeEquipment".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null);
                                }
                                else
                                {
                                    bool flag14 = SelPawnForGear.equipment.AllEquipmentListForReading.Contains(eq) && SelPawnForGear.inventory != null;
                                    if (flag14)
                                    {
                                        item = new FloatMenuOption("CE_PutAway".Translate(value), delegate()
                                        {
                                            SelPawnForGear.equipment.TryTransferEquipmentToContainer(SelPawnForGear.equipment.Primary, SelPawnForGear.inventory.innerContainer);
                                        }, MenuOptionPriority.Default, null, null, 0f, null, null);
                                    }
                                    else
                                    {
                                        bool flag15 = !SelPawnForGear.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);
                                        if (flag15)
                                        {
                                            item = new FloatMenuOption("CannotEquip".Translate(value), null, MenuOptionPriority.Default, null, null, 0f, null, null);
                                        }
                                        else
                                        {
                                            string text4  = "Equip".Translate(value);
                                            bool   flag16 = eq.def.IsRangedWeapon && SelPawnForGear.story != null && SelPawnForGear.story.traits.HasTrait(TraitDefOf.Brawler);
                                            if (flag16)
                                            {
                                                text4 = text4 + " " + "EquipWarningBrawler".Translate();
                                            }
                                            item = new FloatMenuOption(text4, (SelPawnForGear.story != null && SelPawnForGear.WorkTagIsDisabled(WorkTags.Violent)) ? null : new Action(delegate()
                                            {
                                                compInventory.TrySwitchToWeapon(eq);
                                            }), MenuOptionPriority.Default, null, null, 0f, null, null);
                                        }
                                    }
                                }
                            }
                            list.Add(item);
                        }
                    }
                    //Pawn selPawnForGear = SelPawnForGear;   //??
                    List <Apparel> list2;
                    if (SelPawnForGear == null)
                    {
                        list2 = null;
                    }
                    else
                    {
                        Pawn_ApparelTracker apparel2 = SelPawnForGear.apparel;
                        list2 = ((apparel2 != null) ? apparel2.WornApparel : null);
                    }
                    List <Apparel> list3 = list2;
                    using (List <Apparel> .Enumerator enumerator = list3.GetEnumerator())
                    {
                        while (enumerator.MoveNext())
                        {
                            Apparel        apparel        = enumerator.Current;
                            CompReloadable compReloadable = apparel.TryGetComp <CompReloadable>();
                            bool           flag17         = compReloadable != null && compReloadable.AmmoDef == thing.def && compReloadable.NeedsReload(true);
                            if (flag17)
                            {
                                bool flag18 = !SelPawnForGear.Drafted;
                                if (flag18)
                                {
                                    FloatMenuOption item2 = new FloatMenuOption("CE_ReloadApparel".Translate(apparel.Label, thing.Label), delegate()
                                    {
                                        SelPawnForGear.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.Reload, apparel, thing), JobTag.Misc);
                                    }, MenuOptionPriority.Default, null, null, 0f, null, null);
                                    list.Add(item2);
                                }
                            }
                        }
                    }
                    bool flag19 = canControl && thing.IngestibleNow && SelPawn.RaceProps.CanEverEat(thing);
                    if (flag19)
                    {
                        Action action = delegate()
                        {
                            SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                            LInterfaceIngest.Invoke(tab, new object[] { thing });
                        };
                        string text5  = thing.def.ingestible.ingestCommandString.NullOrEmpty() ? (string)"ConsumeThing".Translate(thing.LabelShort, thing) : string.Format(thing.def.ingestible.ingestCommandString, thing.LabelShort);
                        bool   flag20 = SelPawnForGear.IsTeetotaler() && thing.def.IsNonMedicalDrug;
                        if (flag20)
                        {
                            List <FloatMenuOption> list4    = list;
                            string          str             = text5;
                            string          str2            = ": ";
                            TraitDegreeData traitDegreeData = (from x in TraitDefOf.DrugDesire.degreeDatas
                                                               where x.degree == -1
                                                               select x).First <TraitDegreeData>();
                            list4.Add(new FloatMenuOption(str + str2 + ((traitDegreeData != null) ? traitDegreeData.label : null), null, MenuOptionPriority.Default, null, null, 0f, null, null));
                        }
                        else
                        {
                            list.Add(new FloatMenuOption(text5, action, MenuOptionPriority.Default, null, null, 0f, null, null));
                        }
                    }
                    bool flag21 = SelPawnForGear.IsItemQuestLocked(eq);
                    if (flag21)
                    {
                        list.Add(new FloatMenuOption("CE_CannotDropThing".Translate() + ": " + "DropThingLocked".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null));
                        list.Add(new FloatMenuOption("CE_CannotDropThingHaul".Translate() + ": " + "DropThingLocked".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null));
                    }
                    else
                    {
                        list.Add(new FloatMenuOption("DropThing".Translate(), delegate()
                        {
                            SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                            LInterfaceDrop.Invoke(tab, new object[] { thing });
                        }, MenuOptionPriority.Default, null, null, 0f, null, null));
                        list.Add(new FloatMenuOption("CE_DropThingHaul".Translate(), delegate()
                        {
                            SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                            InterfaceDropHaul(SelPawnForGear, thing, SelPawn);
                        }, MenuOptionPriority.Default, null, null, 0f, null, null));
                    }
                    bool flag22 = canControl && (bool)LHoldTrackerIsHeld.Invoke(null, new object[] { SelPawnForGear, thing }); //SelPawnForGear.HoldTrackerIsHeld(thing);
                    if (flag22)
                    {
                        Action action2 = delegate()
                        {
                            SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                            LHoldTrackerForget.Invoke(null, new object[] { SelPawnForGear, thing }); //SelPawnForGear.HoldTrackerForget(thing);
                        };
                        list.Add(new FloatMenuOption("CE_HoldTrackerForget".Translate(), action2, MenuOptionPriority.Default, null, null, 0f, null, null));
                    }
                }
                FloatMenu window = new FloatMenu(list, thing.LabelCap, false);

                Find.WindowStack.Add(window);
            }
예제 #15
0
        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);
        }
 /// <summary>
 /// Determines whether a pawn has grenades they can use against a target
 /// </summary>
 /// <returns>True if the pawn has at least one destructive grenade in their inventory, false otherwise</returns>
 private static bool CanBeGrenadier(Pawn pawn, CompInventory comp)
 {
     return(comp.rangedWeaponList.Any(w => w.def.IsGrenade() && w.def.IsLethal()));
 }
 /// <summary>
 /// Determines whether a pawn can use a rocket/grenade launcher against fortified targets
 /// </summary>
 /// <returns>True if the pawn has a rocket/grenade launcher with ammo in their inventory, false otherwise</returns>
 private static bool CanBeRocketeer(Pawn pawn, CompInventory comp)
 {
     return(comp.rangedWeaponList.Any(w => w.def.IsLauncher() && w.HasAmmo()));
 }
예제 #18
0
        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);
                }
            }
        }
        public static void trySwitchToWeapon(object compInventory, ThingWithComps newEq)
        {
            CompInventory comp = (CompInventory)compInventory;

            comp.TrySwitchToWeapon(newEq);
        }
예제 #20
0
        public override string GetExplanation(StatRequest req, ToStringNumberSense numberSense)
        {
            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.Append(base.GetExplanation(req, numberSense));
            if (req.HasThing)
            {
                Pawn thisPawn = req.Thing as Pawn;

                if (thisPawn != null)
                {
                    if (thisPawn.RaceProps.intelligence >= Intelligence.ToolUser)
                    {
                        if (MapComponent_ToolsForHaul.currentVehicle.ContainsKey(thisPawn))
                        {
                            Vehicle_Cart vehicle_Cart = MapComponent_ToolsForHaul.currentVehicle[thisPawn] as Vehicle_Cart;
                            if (vehicle_Cart != null)
                            {
                                if (vehicle_Cart.mountableComp.IsMounted && vehicle_Cart.mountableComp.Driver == thisPawn)
                                {
                                    stringBuilder.AppendLine();
                                    stringBuilder.AppendLine("VehicleSpeed".Translate() + ": x" + vehicle_Cart.VehicleSpeed);
                                    return(stringBuilder.ToString());
                                }
                            }

                            Vehicle_Turret vehicle_Turret = MapComponent_ToolsForHaul.currentVehicle[req.Thing as Pawn] as Vehicle_Turret;
                            if (vehicle_Turret != null)
                            {
                                if (vehicle_Turret.mountableComp.IsMounted && vehicle_Turret.mountableComp.Driver == thisPawn)
                                {
                                    stringBuilder.AppendLine();
                                    stringBuilder.AppendLine("VehicleSpeed".Translate() + ": x" + vehicle_Turret.VehicleSpeed);
                                    return(stringBuilder.ToString());
                                }
                            }
                        }

                        CompInventory compInventory = ThingCompUtility.TryGetComp <CompInventory>(req.Thing);
                        if (compInventory != null)
                        {
                            stringBuilder.AppendLine();
                            stringBuilder.AppendLine(Translator.Translate("CR_CarriedWeight") + ": x" + GenText.ToStringPercent(compInventory.moveSpeedFactor));
                            if (compInventory.encumberPenalty > 0f)
                            {
                                stringBuilder.AppendLine(Translator.Translate("CR_Encumbered") + ": -" + GenText.ToStringPercent(compInventory.encumberPenalty));
                                stringBuilder.AppendLine(Translator.Translate("CR_FinalModifier") + ": x" + GenText.ToStringPercent(this.GetStatFactor(thisPawn)));
                            }
                        }

                        CompSlotsBackpack compSlotsBackpack = ToolsForHaulUtility.TryGetBackpack(thisPawn).TryGetComp <CompSlotsBackpack>();
                        if (compSlotsBackpack != null)
                        {
                            stringBuilder.AppendLine();
                            stringBuilder.AppendLine("CR_CarriedWeightBackpack".Translate() + ": x" + compSlotsBackpack.moveSpeedFactor.ToStringPercent());
                            if (compSlotsBackpack.encumberPenalty > 0f)
                            {
                                stringBuilder.AppendLine("CR_EncumberedBackpack".Translate() + ": -" + compSlotsBackpack.encumberPenalty.ToStringPercent());
                                stringBuilder.AppendLine("CR_FinalModifierBackpack".Translate() + ": x" + GetStatFactor(thisPawn).ToStringPercent());
                            }
                        }
                    }
                }
            }

            return(stringBuilder.ToString());
        }