Esempio n. 1
0
        protected virtual void Ignite()
        {
            Map map = Map;

            Destroy();
            float ignitionChance = def.projectile.explosionChanceToStartFire;
            var   radius         = def.projectile.explosionRadius;
            var   cellsToAffect  = SimplePool <List <IntVec3> > .Get();

            cellsToAffect.Clear();
            cellsToAffect.AddRange(def.projectile.damageDef.Worker.ExplosionCellsToHit(Position, map, radius));

            AdeptusMoteMaker.MakeStaticMote(ExactPosition, map, ThingDefOf.Mote_ExplosionFlash, radius * 4f);
            for (int i = 0; i < 4; i++)
            {
                MoteMaker.ThrowSmoke(Position.ToVector3Shifted() + Gen.RandomHorizontalVector(radius * 0.7f), map, radius * 0.6f);
            }

            Rand.PushState();
            if (Rand.Chance(ignitionChance))
            {
                foreach (var vec3 in cellsToAffect)
                {
                    var fireSize = radius - vec3.DistanceTo(Position);
                    if (fireSize > 0.1f)
                    {
                        if (this.def.projectile.damageDef == AdeptusDamageDefOf.OG_Chaos_Deamon_Warpfire)
                        {
                            WarpfireUtility.TryStartWarpfireIn(vec3, map, fireSize);
                        }
                        else
                        {
                            FireUtility.TryStartFireIn(vec3, map, fireSize);
                        }
                    }
                }
            }
            Rand.PopState();

            //Fire explosion should be tiny.
            if (this.def.projectile.explosionEffect != null)
            {
                Effecter effecter = this.def.projectile.explosionEffect.Spawn();
                effecter.Trigger(new TargetInfo(this.Position, map, false), new TargetInfo(this.Position, map, false));
                effecter.Cleanup();
            }
            GenExplosion.DoExplosion(this.Position, map, this.def.projectile.explosionRadius, this.def.projectile.damageDef, this.launcher, this.def.projectile.GetDamageAmount(1, null), this.def.projectile.GetArmorPenetration(1, null), this.def.projectile.soundExplode, this.equipmentDef, this.def, null, this.def.projectile.postExplosionSpawnThingDef, this.def.projectile.postExplosionSpawnChance, this.def.projectile.postExplosionSpawnThingCount, this.def.projectile.applyDamageToExplosionCellsNeighbors, this.def.projectile.preExplosionSpawnThingDef, this.def.projectile.preExplosionSpawnChance, this.def.projectile.preExplosionSpawnThingCount, this.def.projectile.explosionChanceToStartFire, this.def.projectile.explosionDamageFalloff);
        }
        public override void SpawnSetup(Map map, bool respawningAfterLoad)
        {
            base.SpawnSetup(map, respawningAfterLoad);
            if (!respawningAfterLoad)
            {
                this.cellsToAffect = SimplePool <List <IntVec3> > .Get();

                this.cellsToAffect.Clear();
                this.damagedThings = SimplePool <List <Thing> > .Get();

                this.damagedThings.Clear();
                this.addedCellsAffectedOnlyByDamage = SimplePool <HashSet <IntVec3> > .Get();

                this.addedCellsAffectedOnlyByDamage.Clear();
            }
        }
Esempio n. 3
0
        public static int RemoveAll <TKey, TValue>(this Dictionary <TKey, TValue> dictionary, Func <TKey, TValue, bool> predicate)
        {
            List <TKey> list = null;
            int         result;

            try
            {
                foreach (var(key, value) in dictionary)
                {
                    if (predicate(key, value))
                    {
                        list ??= SimplePool <List <TKey> > .Get();

                        list.Add(key);
                    }
                }

                if (list != null)
                {
                    int i     = 0;
                    int count = list.Count;
                    while (i < count)
                    {
                        dictionary.Remove(list[i]);
                        i++;
                    }
                    result = list.Count;
                }
                else
                {
                    result = 0;
                }
            }
            finally
            {
                if (list != null)
                {
                    list.Clear();
                    SimplePool <List <TKey> > .Return(list);
                }
            }

            return(result);
        }
Esempio n. 4
0
        private void CalculateDistancesToNearbyClusters(IntVec3 c)
        {
            WildPlantSpawner.nearbyClusters.Clear();
            WildPlantSpawner.nearbyClustersList.Clear();
            int num = GenRadial.NumCellsInRadius((float)(this.map.Biome.MaxWildAndCavePlantsClusterRadius * 2));

            for (int i = 0; i < num; i++)
            {
                IntVec3 intVec = c + GenRadial.RadialPattern[i];
                if (intVec.InBounds(this.map))
                {
                    List <Thing> list = this.map.thingGrid.ThingsListAtFast(intVec);
                    for (int j = 0; j < list.Count; j++)
                    {
                        Thing thing = list[j];
                        if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters)
                        {
                            float        item = (float)intVec.DistanceToSquared(c);
                            List <float> list2;
                            if (!WildPlantSpawner.nearbyClusters.TryGetValue(thing.def, out list2))
                            {
                                list2 = SimplePool <List <float> > .Get();

                                WildPlantSpawner.nearbyClusters.Add(thing.def, list2);
                                WildPlantSpawner.nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, list2));
                            }
                            list2.Add(item);
                        }
                    }
                }
            }
            WildPlantSpawner.distanceSqToNearbyClusters.Clear();
            for (int k = 0; k < WildPlantSpawner.nearbyClustersList.Count; k++)
            {
                List <float> value = WildPlantSpawner.nearbyClustersList[k].Value;
                value.Sort();
                WildPlantSpawner.distanceSqToNearbyClusters.Add(WildPlantSpawner.nearbyClustersList[k].Key, value[value.Count / 2]);
                value.Clear();
                SimplePool <List <float> > .Return(value);
            }
        }
        private void CalculateDistancesToNearbyClusters(IntVec3 c)
        {
            nearbyClusters.Clear();
            nearbyClustersList.Clear();
            int num = GenRadial.NumCellsInRadius(map.Biome.MaxWildAndCavePlantsClusterRadius * 2);

            for (int i = 0; i < num; i++)
            {
                IntVec3 intVec = c + GenRadial.RadialPattern[i];
                if (!intVec.InBounds(map))
                {
                    continue;
                }
                List <Thing> list = map.thingGrid.ThingsListAtFast(intVec);
                for (int j = 0; j < list.Count; j++)
                {
                    Thing thing = list[j];
                    if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters)
                    {
                        float item = intVec.DistanceToSquared(c);
                        if (!nearbyClusters.TryGetValue(thing.def, out var value))
                        {
                            value = SimplePool <List <float> > .Get();

                            nearbyClusters.Add(thing.def, value);
                            nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, value));
                        }
                        value.Add(item);
                    }
                }
            }
            distanceSqToNearbyClusters.Clear();
            for (int k = 0; k < nearbyClustersList.Count; k++)
            {
                List <float> value2 = nearbyClustersList[k].Value;
                value2.Sort();
                distanceSqToNearbyClusters.Add(nearbyClustersList[k].Key, value2[value2.Count / 2]);
                value2.Clear();
                SimplePool <List <float> > .Return(value2);
            }
        }
        public static void Postfix()
        {
            if (Native.LmfPtr == 0)
            {
                return;
            }
            if (!ShouldAddStackTraceForDesyncLog())
            {
                return;
            }

            var logItem = SimplePool <StackTraceLogItemRaw> .Get();

            var trace = logItem.raw;
            int hash  = 0;
            int depth = DeferredStackTracingImpl.TraceImpl(trace, ref hash);

            Multiplayer.game.sync.TryAddStackTraceForDesyncLogRaw(logItem, depth, hash);

            acc = Gen.HashCombineInt(acc, depth, hash, (int)Rand.iterations);
        }
Esempio n. 7
0
 public void Refresh(Action <int> onSwitch, List <string> texts = null)
 {
     this.onSwitch = onSwitch;
     if (texts != null)
     {
         while (toggles.Count < texts.Count)
         {
             var toggle = pool.Get(barTransform);
             toggle.SetIsOnWithoutNotify(false);
             toggle.group = group;
             toggle.onValueChanged.RemoveAllListeners();
             toggle.onValueChanged.AddListener(isOn => { if (isOn)
                                                         {
                                                             OnSwitch(toggle.transform.GetSiblingIndex());
                                                         }
                                               });
             toggles.Add(toggle);
         }
         while (toggles.Count > texts.Count)
         {
             var toggle = toggles[^ 1];
Esempio n. 8
0
        protected virtual void Ignite()
        {
            Map map = Map;

            Destroy();
            var radius        = def.projectile.explosionRadius;
            var cellsToAffect = SimplePool <List <IntVec3> > .Get();

            cellsToAffect.Clear();
            cellsToAffect.AddRange(def.projectile.damageDef.Worker.ExplosionCellsToHit(Position, map, radius));
            for (int i = 0; i < 4; i++)
            {
                PurpleIvyMoteMaker.ThrowToxicPostExplosionSmoke(Position.ToVector3Shifted() + Gen.RandomHorizontalVector(radius * 0.7f), map, radius * 0.6f);
            }
            //Fire explosion should be tiny.
            if (this.def.projectile.explosionEffect != null)
            {
                Effecter effecter = this.def.projectile.explosionEffect.Spawn();
                effecter.Trigger(new TargetInfo(this.Position, map, false), new TargetInfo(this.Position, map, false));
                effecter.Cleanup();
            }
            PurpleIvyUtils.DoExplosion(this.Position, map, this.def.projectile.explosionRadius, this.def.projectile.damageDef, this.launcher, this.def.projectile.GetDamageAmount(1, null), this.def.projectile.GetArmorPenetration(1, null), this.def.projectile.soundExplode, this.equipmentDef, this.def, null, this.def.projectile.postExplosionSpawnThingDef, this.def.projectile.postExplosionSpawnChance, this.def.projectile.postExplosionSpawnThingCount, this.def.projectile.applyDamageToExplosionCellsNeighbors, this.def.projectile.preExplosionSpawnThingDef, this.def.projectile.preExplosionSpawnChance, this.def.projectile.preExplosionSpawnThingCount, this.def.projectile.explosionChanceToStartFire, this.def.projectile.explosionDamageFalloff);
        }
 /// <summary> Call the wrapped pool.  If none are available, it will create a new
 /// temporary one.
 /// </summary>
 /// <returns> A parser Object.
 /// </returns>
 public virtual Parser.Parser Get()
 {
     return(pool.Get());
 }
Esempio n. 10
0
        static private void AddAllRelationships(WorldPawnGC __instance, Pawn pawn, Dictionary <Pawn, string> keptPawns)
        {
            if (pawn.relations == null || !pawn.relations.RelatedToAnyoneOrAnyoneRelatedToMe || !pawn.RaceProps.IsFlesh)
            {
                return;
            }
            Stack <Pawn>   stack   = null;
            HashSet <Pawn> visited = null;

            try {
                stack = SimplePool <Stack <Pawn> > .Get();

                visited = SimplePool <HashSet <Pawn> > .Get();

                stack.Push(pawn);
                visited.Add(pawn);
                while (stack.Count > 0)
                {
                    Pawn p = stack.Pop();
                    foreach (Pawn otherPawn in p.relations.DirectRelations.Select(r => r.otherPawn).Concat <Pawn>(
                                 (HashSet <Pawn>) typeof(Pawn_RelationsTracker).GetField("pawnsWithDirectRelationsWithMe",
                                                                                         BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(p.relations)))
                    {
                        if (!visited.Contains(otherPawn))
                        {
                            if (otherPawn.RaceProps.IsFlesh)
                            {
                                PawnRelationDef relation = AllAllowedRelationDefs.FirstOrDefault(def => def.Worker.InRelation(pawn, otherPawn));
                                if (relation != default(PawnRelationDef))
                                {
                                    if (logDotgraph != null)
                                    {
                                        string text = string.Format("{0}->{1} [label=<{2}> color=\"purple\"];", WorldPawnGC.DotgraphIdentifier(pawn),
                                                                    WorldPawnGC.DotgraphIdentifier(otherPawn), relation.ToString());
                                        if (!logDotgraphUniqueLinks.Contains(text))
                                        {
                                            logDotgraphUniqueLinks.Add(text);
                                            logDotgraph.AppendLine(text);
                                        }
                                    }
                                    if (!keptPawns.ContainsKey(otherPawn))
                                    {
                                        keptPawns[otherPawn] = "Relationship";
                                        //Not correct to have it here if the pairing between two pawns is filtered but if we allow all relations this is correct.
                                        //The pursuit of animal family trees if a human is bonded with an animal is pointless.
                                        if (relation != PawnRelationDefOf.Bond)
                                        {
                                            stack.Push(otherPawn);
                                        }
                                    }
                                }
                            }
                            visited.Add(otherPawn);
                        }
                    }
                }
            } finally {
                if (stack != null)
                {
                    stack.Clear();
                    stack.TrimExcess();
                    SimplePool <Stack <Pawn> > .Return(stack);
                }
                if (visited != null)
                {
                    visited.Clear();
                    stack.TrimExcess();
                    SimplePool <HashSet <Pawn> > .Return(visited);
                }
            }
        }
Esempio n. 11
0
        public void UpdateAllSustainerScopes()
        {
            playingPerDef.Clear();
            for (int i = 0; i < allSustainers.Count; i++)
            {
                Sustainer sustainer = allSustainers[i];
                if (!playingPerDef.ContainsKey(sustainer.def))
                {
                    List <Sustainer> list = SimplePool <List <Sustainer> > .Get();

                    list.Add(sustainer);
                    playingPerDef.Add(sustainer.def, list);
                }
                else
                {
                    playingPerDef[sustainer.def].Add(sustainer);
                }
            }
            foreach (KeyValuePair <SoundDef, List <Sustainer> > item in playingPerDef)
            {
                SoundDef         key   = item.Key;
                List <Sustainer> value = item.Value;
                if (value.Count - key.maxVoices < 0)
                {
                    for (int j = 0; j < value.Count; j++)
                    {
                        value[j].scopeFader.inScope = true;
                    }
                }
                else
                {
                    for (int k = 0; k < value.Count; k++)
                    {
                        value[k].scopeFader.inScope = false;
                    }
                    value.Sort(SortSustainersByCameraDistanceCached);
                    int num = 0;
                    for (int l = 0; l < value.Count; l++)
                    {
                        value[l].scopeFader.inScope = true;
                        num++;
                        if (num >= key.maxVoices)
                        {
                            break;
                        }
                    }
                    for (int m = 0; m < value.Count; m++)
                    {
                        if (!value[m].scopeFader.inScope)
                        {
                            value[m].scopeFader.inScopePercent = 0f;
                        }
                    }
                }
            }
            foreach (KeyValuePair <SoundDef, List <Sustainer> > item2 in playingPerDef)
            {
                item2.Value.Clear();
                SimplePool <List <Sustainer> > .Return(item2.Value);
            }
            playingPerDef.Clear();
        }
Esempio n. 12
0
        public static void Postfix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts)
        {
            IntVec3 position = IntVec3.FromVector3(clickPos);

            // Add options for equipment.
            if (pawn.equipment != null)
            {
                List <Thing> things = position.GetThingList(pawn.Map);
                foreach (Thing thing in things)
                {
                    if (thing.TryGetComp <CompEquippable>() != null)
                    {
                        ThingWithComps equipment = (ThingWithComps)thing;

                        if (equipment.def.IsWeapon &&
                            !pawn.WorkTagIsDisabled(WorkTags.Violent) &&
                            pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly) &&
                            pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) &&
                            !(pawn.IsQuestLodger() && (!equipment.def.IsWeapon || pawn.equipment.Primary != null)) &&
                            EquipmentUtility.CanEquip(equipment, pawn, out _))
                        {
                            string text3 = UIText.AIEquip.Translate(thing.LabelShort);
                            if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler))
                            {
                                text3 += " " + UIText.EquipWarningBrawler.Translate();
                            }

                            var option = FloatMenuUtility.DecoratePrioritizedTask(
                                new FloatMenuOption(
                                    text3,
                                    () =>
                            {
                                TaggedString equipWeaponConfirmationDialogText = ThingRequiringRoyalPermissionUtility.GetEquipWeaponConfirmationDialogText(equipment, pawn);
                                CompBladelinkWeapon compBladelinkWeapon        = equipment.TryGetComp <CompBladelinkWeapon>();
                                if (compBladelinkWeapon != null && compBladelinkWeapon.bondedPawn != pawn)
                                {
                                    if (!equipWeaponConfirmationDialogText.NullOrEmpty())
                                    {
                                        equipWeaponConfirmationDialogText += "\n\n";
                                    }

                                    equipWeaponConfirmationDialogText += "BladelinkEquipWarning".Translate();
                                }

                                if (!equipWeaponConfirmationDialogText.NullOrEmpty())
                                {
                                    equipWeaponConfirmationDialogText += "\n\n" + "RoyalWeaponEquipConfirmation".Translate();
                                    Find.WindowStack.Add(
                                        new Dialog_MessageBox(
                                            equipWeaponConfirmationDialogText,
                                            "Yes".Translate(),
                                            () =>
                                    {
                                        Equip();
                                    },
                                            "No".Translate()));
                                }
                                else
                                {
                                    Equip();
                                }
                            },
                                    MenuOptionPriority.High),
                                pawn,
                                equipment);
                            opts.Add(option);
                        }

                        void Equip()
                        {
                            equipment.SetForbidden(value: false);
                            pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, equipment));
                            MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip);
                            PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total);
                        }
                    }
                }
            }

            // Add options for apparel.
            if (pawn.apparel != null)
            {
                Apparel apparel = pawn.Map.thingGrid.ThingAt <Apparel>(position);
                if (apparel != null)
                {
                    if (pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly) &&
                        !apparel.IsBurning() &&
                        ApparelOptionUtility.CanWear(pawn, apparel))
                    {
                        FloatMenuOption option = FloatMenuUtility.DecoratePrioritizedTask(
                            new FloatMenuOption(
                                UIText.AIForceWear.Translate(apparel.LabelShort),
                                () =>
                        {
                            DressJob dressJob  = SimplePool <DressJob> .Get();
                            dressJob.def       = AwesomeInventory_JobDefOf.AwesomeInventory_Dress;
                            dressJob.targetA   = apparel;
                            dressJob.ForceWear = true;

                            apparel.SetForbidden(value: false);
                            pawn.jobs.TryTakeOrderedJob(dressJob);
                        },
                                MenuOptionPriority.High),
                            pawn,
                            apparel);
                        opts.Add(option);

                        option = FloatMenuUtility.DecoratePrioritizedTask(
                            new FloatMenuOption(
                                UIText.AIWear.Translate(apparel.LabelShort),
                                () =>
                        {
                            DressJob dressJob  = SimplePool <DressJob> .Get();
                            dressJob.def       = AwesomeInventory_JobDefOf.AwesomeInventory_Dress;
                            dressJob.targetA   = apparel;
                            dressJob.ForceWear = false;

                            apparel.SetForbidden(value: false);
                            pawn.jobs.TryTakeOrderedJob(dressJob);
                        },
                                MenuOptionPriority.High),
                            pawn,
                            apparel);
                        opts.Add(option);
                    }
                }
            }
        }
Esempio n. 13
0
    public void Place(ItemSlot source)
    {
        if (!source || source.IsEmpty || source.Data.IsEmpty)
        {
            return;
        }
        var slot = source.Data;
        int have = SourceHandler.GetAmount(slot.item);

        if (slot == null || slot.Model == null || have < 0)
        {
            return;
        }
        if (slot.Model.StackAble && SelectionType == ItemSelectionType.SelectNum)
        {
            if (!canSelect(source))
            {
                return;
            }
            if (typeLimit > 0 && copySlots.Count >= typeLimit)
            {
                MessageManager.Instance.New($"每次最多只能选择{typeLimit}样物品");
                return;
            }
            if (have < 2)
            {
                if (SourceHandler.CanLose(slot.item, 1))
                {
                    MakeSlot(slot.item, 1);
                }
            }
            else if (amountLimit == 1)
            {
                if (SourceHandler.CanLose(slot.item, 1))
                {
                    MakeSlot(slot.item, 1);
                }
            }
            else
            {
                AmountWindow.StartInput(delegate(long amount)
                {
                    if (SourceHandler.CanLose(slot.item, (int)amount))
                    {
                        if (copySlots.TryGetValue(slot.item.ID, out var copy))
                        {
                            copy.Data.amount = (int)amount;
                            copy.Refresh();
                        }
                        else
                        {
                            MakeSlot(slot.item, (int)amount);
                        }
                        if (copySlots.Count > 0)
                        {
                            ZetanUtility.SetActive(tips, false);
                        }
                    }
                }, amountLimit > 0 ? amountLimit : have);
            }
        }
        else if ((!slot.Model.StackAble && SelectionType == ItemSelectionType.SelectNum || SelectionType == ItemSelectionType.SelectAll) &&
                 canSelect(source) && SourceHandler.CanLose(slot.item, have))
        {
            if (copySlots.ContainsKey(slot.item.ID))
            {
                MessageManager.Instance.New("已选择该物品");
                return;
            }
            if (typeLimit > 0 && copySlots.Count >= typeLimit)
            {
                MessageManager.Instance.New($"每次最多只能选择{typeLimit}样物品");
            }
            else
            {
                MakeSlot(slot.item, have);
            }
        }

        void MakeSlot(ItemData data, int amount)
        {
            ItemSlot copy = caches.Get(itemCellsParent);

            copy.SetScrollRect(gridScrollRect);
            copy.SetCallbacks(GetHandleButtons, (s) => TakeOut(s, true), OnSlotEndDrag);
            copySlots.Add(data.ID, copy);
            selectedItems.Add(data);
            copy.Refresh(new ItemSlotData(data, amount));
            SourceContainer.MarkIf(s => selectedItems.Contains(s.Item));
            if (copySlots.Count > 0)
            {
                ZetanUtility.SetActive(tips, false);
            }
        }
    }
        public void UpdateAllSustainerScopes()
        {
            for (int i = 0; i < this.allSustainers.Count; i++)
            {
                Sustainer sustainer = this.allSustainers[i];
                if (!SustainerManager.playingPerDef.ContainsKey(sustainer.def))
                {
                    List <Sustainer> list = SimplePool <List <Sustainer> > .Get();

                    list.Add(sustainer);
                    SustainerManager.playingPerDef.Add(sustainer.def, list);
                }
                else
                {
                    SustainerManager.playingPerDef[sustainer.def].Add(sustainer);
                }
            }
            foreach (KeyValuePair <SoundDef, List <Sustainer> > keyValuePair in SustainerManager.playingPerDef)
            {
                SoundDef         key   = keyValuePair.Key;
                List <Sustainer> value = keyValuePair.Value;
                int num = value.Count - key.maxVoices;
                if (num < 0)
                {
                    for (int j = 0; j < value.Count; j++)
                    {
                        value[j].scopeFader.inScope = true;
                    }
                }
                else
                {
                    for (int k = 0; k < value.Count; k++)
                    {
                        value[k].scopeFader.inScope = false;
                    }
                    int num2 = 0;
                    foreach (Sustainer sustainer2 in from lo in value
                             orderby lo.CameraDistanceSquared
                             select lo)
                    {
                        sustainer2.scopeFader.inScope = true;
                        num2++;
                        if (num2 >= key.maxVoices)
                        {
                            break;
                        }
                    }
                    for (int l = 0; l < value.Count; l++)
                    {
                        if (!value[l].scopeFader.inScope)
                        {
                            value[l].scopeFader.inScopePercent = 0f;
                        }
                    }
                }
            }
            foreach (KeyValuePair <SoundDef, List <Sustainer> > keyValuePair2 in SustainerManager.playingPerDef)
            {
                keyValuePair2.Value.Clear();
                SimplePool <List <Sustainer> > .Return(keyValuePair2.Value);
            }
            SustainerManager.playingPerDef.Clear();
        }
        public static void Postfix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts)
        {
            if (!AwesomeInventoryServiceProvider.TryGetImplementation <IInventoryHelper>(out IInventoryHelper inventoryHelper))
            {
                Log.Error(string.Format(ErrorMessage.NotImplemented, typeof(IInventoryHelper).Name));
                return;
            }

            IntVec3 position = IntVec3.FromVector3(clickPos);

            // Add options for equipment.
            if (pawn.equipment != null)
            {
                List <Thing> things = position.GetThingList(pawn.Map);
                foreach (Thing thing in things)
                {
                    if (thing.TryGetComp <CompEquippable>() != null)
                    {
                        ThingWithComps equipment = (ThingWithComps)thing;

                        if (equipment.def.IsWeapon &&
                            !pawn.WorkTagIsDisabled(WorkTags.Violent) &&
                            pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly) &&
                            pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) &&
                            !(pawn.IsQuestLodger() && (!equipment.def.IsWeapon || pawn.equipment.Primary != null)) &&
                            EquipmentUtility.CanEquip(equipment, pawn, out _))
                        {
                            string text3 = UIText.AIEquip.Translate(thing.LabelShort);
                            if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler))
                            {
                                text3 += " " + UIText.EquipWarningBrawler.Translate();
                            }

                            var option = FloatMenuUtility.DecoratePrioritizedTask(
                                new FloatMenuOption(
                                    text3,
                                    () =>
                            {
                                TaggedString equipWeaponConfirmationDialogText = ThingRequiringRoyalPermissionUtility.GetEquipWeaponConfirmationDialogText(equipment, pawn);
                                CompBladelinkWeapon compBladelinkWeapon        = equipment.TryGetComp <CompBladelinkWeapon>();
                                if (compBladelinkWeapon != null && compBladelinkWeapon.bondedPawn != pawn)
                                {
                                    if (!equipWeaponConfirmationDialogText.NullOrEmpty())
                                    {
                                        equipWeaponConfirmationDialogText += "\n\n";
                                    }

                                    equipWeaponConfirmationDialogText += "BladelinkEquipWarning".Translate();
                                }

                                if (!equipWeaponConfirmationDialogText.NullOrEmpty())
                                {
                                    equipWeaponConfirmationDialogText += "\n\n" + "RoyalWeaponEquipConfirmation".Translate();
                                    Find.WindowStack.Add(
                                        new Dialog_MessageBox(
                                            equipWeaponConfirmationDialogText,
                                            "Yes".Translate(),
                                            () =>
                                    {
                                        Equip();
                                    },
                                            "No".Translate()));
                                }
                                else
                                {
                                    Equip();
                                }
                            },
                                    MenuOptionPriority.High),
                                pawn,
                                equipment);
                            opts.Add(option);
                        }

                        void Equip()
                        {
                            equipment.SetForbidden(value: false);
                            pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, equipment));
                            MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip);
                            PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total);
                        }
                    }
                }
            }

            // Add options for apparel.
            if (pawn.apparel != null)
            {
                Apparel apparel = pawn.Map.thingGrid.ThingAt <Apparel>(position);
                if (apparel != null)
                {
                    if (pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly) &&
                        !apparel.IsBurning() &&
                        !pawn.apparel.WouldReplaceLockedApparel(apparel) &&
                        ApparelUtility.HasPartsToWear(pawn, apparel.def))
                    {
                        FloatMenuOption option = FloatMenuUtility.DecoratePrioritizedTask(
                            new FloatMenuOption(
                                UIText.AIForceWear.Translate(apparel.LabelShort),
                                () =>
                        {
                            DressJob dressJob  = SimplePool <DressJob> .Get();
                            dressJob.def       = AwesomeInventory_JobDefOf.AwesomeInventory_Dress;
                            dressJob.targetA   = apparel;
                            dressJob.ForceWear = true;

                            apparel.SetForbidden(value: false);
                            pawn.jobs.TryTakeOrderedJob(dressJob);
                        },
                                MenuOptionPriority.High),
                            pawn,
                            apparel);
                        opts.Add(option);

                        option = FloatMenuUtility.DecoratePrioritizedTask(
                            new FloatMenuOption(
                                UIText.AIWear.Translate(apparel.LabelShort),
                                () =>
                        {
                            DressJob dressJob  = SimplePool <DressJob> .Get();
                            dressJob.def       = AwesomeInventory_JobDefOf.AwesomeInventory_Dress;
                            dressJob.targetA   = apparel;
                            dressJob.ForceWear = false;

                            apparel.SetForbidden(value: false);
                            pawn.jobs.TryTakeOrderedJob(dressJob);
                        },
                                MenuOptionPriority.High),
                            pawn,
                            apparel);
                        opts.Add(option);
                    }
                }
            }

            List <Thing> items = position.GetThingList(pawn.Map);

            foreach (Thing item in items)
            {
                if (item.def.category == ThingCategory.Item)
                {
                    int count = MassUtility.CountToPickUpUntilOverEncumbered(pawn, item);
                    if (count == 0)
                    {
                        continue;
                    }

                    count = Math.Min(count, item.stackCount);

                    string displayText = UIText.Pickup.Translate(item.LabelNoCount + " x" + count);
                    var    option      = FloatMenuUtility.DecoratePrioritizedTask(
                        new FloatMenuOption(
                            displayText
                            , () =>
                    {
                        Job job   = JobMaker.MakeJob(JobDefOf.TakeInventory, item);
                        job.count = count;
                        pawn.jobs.TryTakeOrderedJob(job);
                    })
                        , pawn
                        , item);
                    opts.Add(option);
                }
            }
        }