public static void Postfix(Pawn pawn)
                {
                    // Change the colour of appropriate apparel items to match the pawn's faction's colour
                    if (pawn.apparel != null && pawn.Faction != null && pawn.kindDef.apparelColor == Color.white)
                    {
                        var pawnKindDefExtension = PawnKindDefExtension.Get(pawn.kindDef);
                        var wornApparel          = pawn.apparel.WornApparel;
                        for (int i = 0; i < wornApparel.Count; i++)
                        {
                            var apparel = wornApparel[i];

                            // Check from ThingDefExtension
                            var thingDefExtension = ThingDefExtension.Get(apparel.def);
                            if (!thingDefExtension.useFactionColourForPawnKinds.NullOrEmpty() && thingDefExtension.useFactionColourForPawnKinds.Contains(pawn.kindDef))
                            {
                                apparel.SetColor(pawn.Faction.Color);
                                continue;
                            }

                            // Check from PawnKindDefExtension
                            var apparelProps           = apparel.def.apparel;
                            var partGroupAndLayerPairs = pawnKindDefExtension.FactionColourApparelWithPartAndLayersList;
                            for (int j = 0; j < partGroupAndLayerPairs.Count; j++)
                            {
                                var partGroupAndLayerPair = partGroupAndLayerPairs[j];
                                if (apparelProps.bodyPartGroups.Contains(partGroupAndLayerPair.First) && apparelProps.layers.Contains(partGroupAndLayerPair.Second))
                                {
                                    apparel.SetColor(pawn.Faction.Color);
                                    break;
                                }
                            }
                        }
                    }
                }
        public override void ResolveReferences()
        {
            var thingDefs = DefDatabase <ThingDef> .AllDefsListForReading;

            for (int i = 0; i < thingDefs.Count; i++)
            {
                var thingDef = thingDefs[i];
                if (thingDef.building != null && !thingDef.building.buildingTags.NullOrEmpty() && thingDef.building.buildingTags.Any(t => artilleryBuildingTags.Contains(t)))
                {
                    // Min blueprint points
                    var thingDefExtension = ThingDefExtension.Get(thingDef);
                    if (thingDefExtension.siegeBlueprintPoints < lowestArtilleryBlueprintPoints)
                    {
                        lowestArtilleryBlueprintPoints = thingDefExtension.siegeBlueprintPoints;
                    }

                    // Skill prerequisite
                    if (thingDef.constructionSkillPrerequisite > maxArtilleryConstructionSkill)
                    {
                        maxArtilleryConstructionSkill = thingDef.constructionSkillPrerequisite;
                    }

                    if (!artilleryDefs.Contains(thingDef))
                    {
                        artilleryDefs.Add(thingDef);
                    }
                }
            }
        }
        public static bool UsableWithShields(this ThingDef def)
        {
            // If Dual Wield is active, return whether or not the weapon isn't two-handed and can be equipped off hand
            if (ModCompatibilityCheck.DualWield)
            {
                return(!NonPublicMethods.DualWield.Ext_ThingDef_IsTwoHand(def) && NonPublicMethods.DualWield.Ext_ThingDef_CanBeOffHand(def));
            }

            // Otherwise return based on DefModExtension
            return(ThingDefExtension.Get(def).usableWithShields);
        }
        private static IEnumerable <Blueprint_Build> PlaceArtilleryBlueprints(LordToilData_SiegeCustom data, Map map)
        {
            IEnumerable <ThingDef> artyDefs = customParams.artilleryDefs;

            // No tag matches
            if (!artyDefs.Any())
            {
                Log.Error($"Could not find any artillery ThingDefs matching the following tags: {customParams.artilleryBuildingTags.ToStringSafeEnumerable()}");
                yield break;
            }

            float points = data.blueprintPoints;

            // Generate blueprints
            int numArtillery = Mathf.RoundToInt(points / customParams.lowestArtilleryBlueprintPoints);

            numArtillery = Mathf.Clamp(numArtillery, customParams.artilleryCountRange.min, customParams.artilleryCountRange.max);
            int i = 0;

            while (points > 0 && i < numArtillery)
            {
                artyDefs = artyDefs.Where(t => ThingDefExtension.Get(t).siegeBlueprintPoints <= points);
                if (!artyDefs.Any())
                {
                    yield break;
                }
                var rot      = Rot4.Random;
                var artyDef  = artyDefs.RandomElementByWeight(t => ThingDefExtension.Get(t).siegeBlueprintPoints);
                var artySpot = NonPublicMethods.SiegeBlueprintPlacer_FindArtySpot(artyDef, rot, map);
                if (!artySpot.IsValid)
                {
                    yield break;
                }
                yield return(GenConstruct.PlaceBlueprintForBuild(artyDef, artySpot, map, rot, (Faction)NonPublicFields.SiegeBlueprintPlacer_faction.GetValue(null), GenStuff.DefaultStuffFor(artyDef)));

                if (data.artilleryCounts.ContainsKey(artyDef))
                {
                    data.artilleryCounts[artyDef]++;
                }
                else
                {
                    data.artilleryCounts.Add(artyDef, 1);
                }
                points -= ThingDefExtension.Get(artyDef).siegeBlueprintPoints;
                i++;
            }
            yield break;
        }
        public static void TryGenerateShieldFor(Pawn pawn)
        {
            workingShields.Clear();
            var kindDefExtension = PawnKindDefExtension.Get(pawn.kindDef);

            // No shieldTags
            if (kindDefExtension.shieldTags.NullOrEmpty())
            {
                return;
            }

            // Not a tool user
            if (!pawn.RaceProps.ToolUser)
            {
                return;
            }

            // Primary unusable with shields
            if (pawn.equipment.Primary is ThingWithComps primary && !primary.def.UsableWithShields())
            {
                return;
            }

            // Has multiple weapons
            if (pawn.equipment.AllEquipmentListForReading.Count(t => t.def.equipmentType == EquipmentType.Primary) > 1)
            {
                return;
            }

            // Not enough manipulation
            if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !pawn.CanUseShields())
            {
                return;
            }

            // Pacifist
            if (pawn.story != null && pawn.WorkTagIsDisabled(WorkTags.Violent))
            {
                return;
            }

            float randomInRange = kindDefExtension.shieldMoney.RandomInRange;

            for (int i = 0; i < allShieldPairs.Count; i++)
            {
                ThingStuffPair w = allShieldPairs[i];
                if (w.Price <= randomInRange)
                {
                    var shieldProps = w.thing.GetCompProperties <CompProperties_Shield>();
                    if (kindDefExtension.shieldTags == null || kindDefExtension.shieldTags.Any((string tag) => shieldProps.shieldTags.Contains(tag)))
                    {
                        if (w.thing.generateAllowChance >= 1f || Rand.ChanceSeeded(w.thing.generateAllowChance, pawn.thingIDNumber ^ (int)w.thing.shortHash ^ 28554824))
                        {
                            workingShields.Add(w);
                        }
                    }
                }
            }
            if (workingShields.Count == 0)
            {
                return;
            }
            //pawn.equipment.DestroyAllEquipment(DestroyMode.Vanish);
            ThingStuffPair thingStuffPair;

            if (workingShields.TryRandomElementByWeight((ThingStuffPair w) => w.Commonality * w.Price, out thingStuffPair))
            {
                var shield = (Apparel)ThingMaker.MakeThing(thingStuffPair.thing, thingStuffPair.stuff);
                PawnGenerator.PostProcessGeneratedGear(shield, pawn);

                // Colour the shield
                if (pawn.Faction != null)
                {
                    var thingDefExtension = ThingDefExtension.Get(thingStuffPair.thing);
                    if (!thingDefExtension.useFactionColourForPawnKinds.NullOrEmpty() && thingDefExtension.useFactionColourForPawnKinds.Contains(pawn.kindDef))
                    {
                        shield.SetColor(pawn.Faction.Color);
                    }
                }
                pawn.AddShield(shield);
            }
            workingShields.Clear();
        }