private void TrySwitchToWeapon(ThingWithComps newEq, Pawn pawn)
        {
            if (newEq == null || pawn.equipment == null || !pawn.inventory.innerContainer.Contains(newEq))
            {
                return;
            }

            if (newEq.def.stackLimit > 1 && newEq.stackCount > 1)
            {
                newEq = (ThingWithComps)newEq.SplitOff(1);
            }

            if (pawn.equipment.Primary != null)
            {
                if (MassUtility.FreeSpace(pawn) > 0)
                {
                    pawn.equipment.TryTransferEquipmentToContainer(pawn.equipment.Primary, pawn.inventory.innerContainer);
                }
                else
                {
                    pawn.equipment.MakeRoomFor(newEq);
                }
            }

            pawn.equipment.GetDirectlyHeldThings().TryAddOrTransfer(newEq);
            if (newEq.def.soundInteract != null)
            {
                newEq.def.soundInteract.PlayOneShot(new TargetInfo(pawn.Position, pawn.MapHeld, false));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Get vehicle with the most free space that is able to hold cargo
        /// </summary>
        /// <param name="pawn"></param>
        public static Pawn UsableVehicleWithTheMostFreeSpace(Pawn pawn)
        {
            Pawn  carrierPawn = null;
            float num         = 0f;

            foreach (Pawn p in UsableCandidatesForCargo(pawn))
            {
                if (p is VehiclePawn && p != pawn && pawn.CanReach(p, PathEndMode.Touch, Danger.Deadly, false))
                {
                    float num2 = MassUtility.FreeSpace(p);
                    if (carrierPawn is null || num2 > num)
                    {
                        carrierPawn = p;
                        num         = num2;
                    }
                }
            }
            return(carrierPawn);
        }
Beispiel #3
0
 public static float FreeSpaceIfCarried(this Pawn carrier, Thing thing)
 {
     return(Mathf.Max(0f, MassUtility.FreeSpace(carrier) - thing.Mass()));
 }
        internal static bool canCarrySidearm(ThingDef sidearm, Pawn pawn, out string errString)
        {
            float maxCapacity   = MassUtility.Capacity(pawn);
            float freeCapacity  = MassUtility.FreeSpace(pawn);
            float sidearmWeight = sidearm.GetStatValueAbstract(StatDefOf.Mass);

            //ThingStuffPair sidearmAsThingStuffPair = new ThingStuffPair(sidearm.def, sidearm.Stuff);

            if (sidearmWeight >= freeCapacity)
            {
                errString = "SidearmPickupFail_NoFreeSpace".Translate();
                return(false);
            }

            if (!SimpleSidearms.SeparateModes)
            {
                switch (SimpleSidearms.LimitModeSingle.Value)
                {
                case LimitModeSingleSidearm.None:
                    break;

                case LimitModeSingleSidearm.AbsoluteWeight:
                    if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Absolute.Value)
                    {
                        errString = "SidearmPickupFail_TooHeavyForSidearm".Translate();
                        return(false);
                    }
                    break;

                case LimitModeSingleSidearm.RelativeWeight:
                    if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Relative.Value * maxCapacity)
                    {
                        errString = "SidearmPickupFail_TooHeavyForSidearm".Translate();
                        return(false);
                    }
                    break;

                case LimitModeSingleSidearm.Selection:
                    if (!SimpleSidearms.LimitModeSingle_Selection.Value.InnerList.Contains <string>(sidearm.defName))
                    {
                        errString = "SidearmPickupFail_NotASidearm".Translate();
                        return(false);
                    }
                    break;
                }
                switch (SimpleSidearms.LimitModeAmount.Value)
                {
                case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                    break;

                case LimitModeAmountOfSidearms.AbsoluteWeight:
                    if (sidearmWeight >= (SimpleSidearms.LimitModeAmount_Absolute.Value - weightForType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.RelativeWeight:
                    if (sidearmWeight >= ((SimpleSidearms.LimitModeAmount_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.Slots:
                    if (SimpleSidearms.LimitModeAmount_Slots.Value <= countForType(pawn, WeaponSearchType.Both))
                    {
                        errString = "SidearmPickupFail_AllSlotsFull".Translate();
                        return(false);
                    }
                    break;
                }
            }
            else
            {
                switch (SimpleSidearms.LimitModeAmountTotal.Value)
                {
                case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                    break;

                case LimitModeAmountOfSidearms.AbsoluteWeight:
                    if (sidearmWeight >= (SimpleSidearms.LimitModeAmountTotal_Absolute.Value - weightForType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.RelativeWeight:
                    if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountTotal_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.Slots:
                    if (SimpleSidearms.LimitModeAmountTotal_Slots.Value <= countForType(pawn, WeaponSearchType.Both))
                    {
                        errString = "SidearmPickupFail_AllSlotsFull".Translate();
                        return(false);
                    }
                    break;
                }
                if (!sidearm.IsRangedWeapon)
                {
                    switch (SimpleSidearms.LimitModeSingleMelee.Value)
                    {
                    case LimitModeSingleSidearm.None:
                        break;

                    case LimitModeSingleSidearm.AbsoluteWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Absolute.Value)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.RelativeWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Relative.Value * maxCapacity)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.Selection:
                        if (!SimpleSidearms.LimitModeSingleMelee_Selection.Value.InnerList.Contains <string>(sidearm.defName))
                        {
                            errString = "SidearmPickupFail_NotASidearmMelee".Translate();
                            return(false);
                        }
                        break;
                    }
                    switch (SimpleSidearms.LimitModeAmountMelee.Value)
                    {
                    case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                        break;

                    case LimitModeAmountOfSidearms.AbsoluteWeight:
                        if (sidearmWeight >= (SimpleSidearms.LimitModeAmountMelee_Absolute.Value - weightForType(pawn, WeaponSearchType.Melee)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.RelativeWeight:
                        if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountMelee_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Melee)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.Slots:
                        if (SimpleSidearms.LimitModeAmountMelee_Slots.Value <= countForType(pawn, WeaponSearchType.Melee))
                        {
                            errString = "SidearmPickupFail_MeleeSlotsFull".Translate();
                            return(false);
                        }
                        break;
                    }
                }
                else
                {
                    switch (SimpleSidearms.LimitModeSingleRanged.Value)
                    {
                    case LimitModeSingleSidearm.None:
                        break;

                    case LimitModeSingleSidearm.AbsoluteWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Absolute.Value)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.RelativeWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Relative.Value * maxCapacity)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.Selection:
                        if (!SimpleSidearms.LimitModeSingleRanged_Selection.Value.InnerList.Contains <string>(sidearm.defName))
                        {
                            errString = "SidearmPickupFail_NotASidearmRanged".Translate();
                            return(false);
                        }
                        break;
                    }
                    switch (SimpleSidearms.LimitModeAmountRanged.Value)
                    {
                    case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                        break;

                    case LimitModeAmountOfSidearms.AbsoluteWeight:
                        if (sidearmWeight >= (SimpleSidearms.LimitModeAmountRanged_Absolute.Value - weightForType(pawn, WeaponSearchType.Ranged)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.RelativeWeight:
                        if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountRanged_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Ranged)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.Slots:
                        if (SimpleSidearms.LimitModeAmountRanged_Slots.Value <= countForType(pawn, WeaponSearchType.Ranged))
                        {
                            errString = "SidearmPickupFail_RangedSlotsFull".Translate();
                            return(false);
                        }
                        break;
                    }
                }
            }
            errString = "SidearmPickupPass".Translate();
            return(true);
        }
Beispiel #5
0
            private static bool Prefix(PawnGroupMakerParms parms, PawnGroupMaker groupMaker, Pawn trader, List <Thing> wares, List <Pawn> outPawns)
            {
                Func <Thing, float> massTotaler = t => t.stackCount * t.GetStatValue(StatDefOf.Mass, true);

                List <Thing> list = wares.Where(t => !(t is Pawn)).ToList();

                list.SortByDescending(massTotaler);

                float ttlMassThings = list.Sum(massTotaler);
                float ttlCapacity   = 0f;
                float ttlBodySize   = 0f;
                int   numCarriers   = 0;

                IEnumerable <PawnGenOption> carrierKinds = groupMaker.carriers.Where(p => {
                    if (parms.tile != -1)
                    {
                        return(Find.WorldGrid[parms.tile].biome.IsPackAnimalAllowed(p.kind.race));
                    }
                    return(true);
                });

                PawnKindDef kind = carrierKinds.RandomElementByWeight(x => x.selectionWeight).kind;

                // No slow or small juveniles
                Predicate <Pawn> validator = (p =>
                                              p.ageTracker.CurLifeStage.bodySizeFactor >= 1 &&
                                              p.GetStatValue(StatDefOf.MoveSpeed, true) >= p.kindDef.race.GetStatValueAbstract(StatDefOf.MoveSpeed)
                                              );

                // 50/50 chance of uniform carriers (like vanilla) or mixed carriers
                bool mixedCarriers = Rand.RangeInclusive(0, 1) == 1;

                // Generate all of the carrier pawns (empty).  Either we spawn as many pawns as we need to cover
                // 120% of the weight of the items, or enough pawns before it seems "unreasonable" based on body
                // size.
                for (; ttlCapacity < ttlMassThings * 1.2 && ttlBodySize < 20; numCarriers++)
                {
                    PawnGenerationRequest request = new PawnGenerationRequest(
                        kind:             kind,
                        faction:          parms.faction,
                        tile:             parms.tile,
                        inhabitant:       parms.inhabitants,
                        validatorPreGear: validator
                        );
                    Pawn pawn = PawnGenerator.GeneratePawn(request);
                    outPawns.Add(pawn);

                    ttlCapacity += MassUtility.Capacity(pawn);
                    // Still can't have 100 chickenmuffalos.  That might slow down some PCs.
                    ttlBodySize += Mathf.Max(pawn.BodySize, 0.5f);

                    if (mixedCarriers)
                    {
                        kind = carrierKinds.RandomElementByWeight(x => x.selectionWeight).kind;
                    }
                }

                // Add items (in descending order of weight) to randomly chosen pack animals.  This isn't the most
                // efficient routine, as we're trying to be a bit random.  If I was trying to be efficient, I would
                // use something like SortByDescending(p.Capacity) against the existing thing list.
                foreach (Thing thing in list)
                {
                    List <Pawn> validPawns = outPawns.FindAll(p => !MassUtility.WillBeOverEncumberedAfterPickingUp(p, thing, thing.stackCount));

                    if (validPawns.Count() != 0)
                    {
                        validPawns.RandomElement().inventory.innerContainer.TryAdd(thing, true);
                    }
                    else if (thing.stackCount > 1)
                    {
                        // No carrier can handle the full stack; split it up
                        int countLeft = thing.stackCount;
                        int c         = 0; // safety counter (while loops can be dangerous)
                        while (countLeft > 0)
                        {
                            validPawns = outPawns.FindAll(p => MassUtility.CountToPickUpUntilOverEncumbered(p, thing) >= 1);
                            if (validPawns.Count() != 0 && c < thing.stackCount)
                            {
                                Pawn pawn       = validPawns.RandomElement();
                                int  countToAdd = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(pawn, thing), countLeft);
                                countLeft -= pawn.inventory.innerContainer.TryAdd(thing, countToAdd, true);
                            }
                            else
                            {
                                // Either no carrier can handle a single item, or we're just in some bad while loop breakout.  In
                                // any case, force it in, evenly split among all carriers.
                                int splitCount = Mathf.FloorToInt(countLeft / outPawns.Count());
                                if (splitCount > 0)
                                {
                                    outPawns.ForEach(p => p.inventory.innerContainer.TryAdd(thing, splitCount, true));
                                    countLeft -= splitCount * outPawns.Count();
                                }

                                // Give the remainer to the ones with space (one at a time)
                                while (countLeft > 0)
                                {
                                    validPawns = new List <Pawn>(outPawns);
                                    validPawns.SortByDescending(p => MassUtility.FreeSpace(p));
                                    validPawns.First().inventory.innerContainer.TryAdd(thing, 1, true);
                                    countLeft--;
                                }
                                break;
                            }
                            c++;
                        }
                    }
                    else
                    {
                        // No way to split it; force it in
                        validPawns = new List <Pawn>(outPawns);
                        validPawns.SortByDescending(p => MassUtility.FreeSpace(p));
                        validPawns.First().inventory.innerContainer.TryAdd(thing, true);
                    }
                }

                // Always skip the original method
                return(false);
            }
        public static bool canCarrySidearmType(ThingDefStuffDefPair sidearm, Pawn pawn, out string errString)
        {
            float maxCapacity   = MassUtility.Capacity(pawn);
            float freeCapacity  = MassUtility.FreeSpace(pawn);
            float sidearmWeight = sidearm.thing.GetStatValueAbstract(StatDefOf.Mass, sidearm.stuff);

            if (((pawn.CombinedDisabledWorkTags & WorkTags.Violent) != 0) && (!sidearm.isTool()))
            {
                errString = "SidearmPickupFail_NotAToolForPacifist".Translate(pawn.LabelShort);
                return(false);
            }

            //this is duplicated in the switches later but Id rather not risk accidentaly deleting a case that might come up
            if (!isValidSidearm(sidearm, out errString))
            {
                return(false);
            }

            if (sidearmWeight >= freeCapacity)
            {
                errString = "SidearmPickupFail_NoFreeSpace".Translate();
                return(false);
            }

            if (!SimpleSidearms.SeparateModes)
            {
                switch (SimpleSidearms.LimitModeSingle.Value)
                {
                case LimitModeSingleSidearm.None:
                    break;

                case LimitModeSingleSidearm.AbsoluteWeight:
                    if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Absolute.Value)
                    {
                        errString = "SidearmPickupFail_TooHeavyForSidearm".Translate();
                        return(false);
                    }
                    break;

                case LimitModeSingleSidearm.RelativeWeight:
                    if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Relative.Value * maxCapacity)
                    {
                        errString = "SidearmPickupFail_TooHeavyForSidearm".Translate();
                        return(false);
                    }
                    break;

                case LimitModeSingleSidearm.Selection:
                    if (!SimpleSidearms.LimitModeSingle_Selection.Value.InnerList.Contains <ThingDef>(sidearm.thing))
                    {
                        errString = "SidearmPickupFail_NotASidearm".Translate();
                        return(false);
                    }
                    break;
                }
                switch (SimpleSidearms.LimitModeAmount.Value)
                {
                case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                    break;

                case LimitModeAmountOfSidearms.AbsoluteWeight:
                    if (sidearmWeight >= (SimpleSidearms.LimitModeAmount_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.RelativeWeight:
                    if (sidearmWeight >= ((SimpleSidearms.LimitModeAmount_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.Slots:
                    if (SimpleSidearms.LimitModeAmount_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Both))
                    {
                        errString = "SidearmPickupFail_AllSlotsFull".Translate();
                        return(false);
                    }
                    break;
                }
            }
            else
            {
                switch (SimpleSidearms.LimitModeAmountTotal.Value)
                {
                case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                    break;

                case LimitModeAmountOfSidearms.AbsoluteWeight:
                    if (sidearmWeight >= (SimpleSidearms.LimitModeAmountTotal_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.RelativeWeight:
                    if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountTotal_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Both)))
                    {
                        errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate();
                        return(false);
                    }
                    break;

                case LimitModeAmountOfSidearms.Slots:
                    if (SimpleSidearms.LimitModeAmountTotal_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Both))
                    {
                        errString = "SidearmPickupFail_AllSlotsFull".Translate();
                        return(false);
                    }
                    break;
                }
                if (sidearm.thing.IsMeleeWeapon)
                {
                    switch (SimpleSidearms.LimitModeSingleMelee.Value)
                    {
                    case LimitModeSingleSidearm.None:
                        break;

                    case LimitModeSingleSidearm.AbsoluteWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Absolute.Value)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.RelativeWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Relative.Value * maxCapacity)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.Selection:
                        if (!SimpleSidearms.LimitModeSingleMelee_Selection.Value.InnerList.Contains <ThingDef>(sidearm.thing))
                        {
                            errString = "SidearmPickupFail_NotASidearmMelee".Translate();
                            return(false);
                        }
                        break;
                    }
                    switch (SimpleSidearms.LimitModeAmountMelee.Value)
                    {
                    case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                        break;

                    case LimitModeAmountOfSidearms.AbsoluteWeight:
                        if (sidearmWeight >= (SimpleSidearms.LimitModeAmountMelee_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Melee)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.RelativeWeight:
                        if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountMelee_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Melee)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.Slots:
                        if (SimpleSidearms.LimitModeAmountMelee_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Melee))
                        {
                            errString = "SidearmPickupFail_MeleeSlotsFull".Translate();
                            return(false);
                        }
                        break;
                    }
                }
                else if (sidearm.thing.IsRangedWeapon)
                {
                    switch (SimpleSidearms.LimitModeSingleRanged.Value)
                    {
                    case LimitModeSingleSidearm.None:
                        break;

                    case LimitModeSingleSidearm.AbsoluteWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Absolute.Value)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.RelativeWeight:
                        if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Relative.Value * maxCapacity)
                        {
                            errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeSingleSidearm.Selection:
                        if (!SimpleSidearms.LimitModeSingleRanged_Selection.Value.InnerList.Contains <ThingDef>(sidearm.thing))
                        {
                            errString = "SidearmPickupFail_NotASidearmRanged".Translate();
                            return(false);
                        }
                        break;
                    }
                    switch (SimpleSidearms.LimitModeAmountRanged.Value)
                    {
                    case LimitModeAmountOfSidearms.MaximumCarryWeightOnly:
                        break;

                    case LimitModeAmountOfSidearms.AbsoluteWeight:
                        if (sidearmWeight >= (SimpleSidearms.LimitModeAmountRanged_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Ranged)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.RelativeWeight:
                        if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountRanged_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Ranged)))
                        {
                            errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate();
                            return(false);
                        }
                        break;

                    case LimitModeAmountOfSidearms.Slots:
                        if (SimpleSidearms.LimitModeAmountRanged_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Ranged))
                        {
                            errString = "SidearmPickupFail_RangedSlotsFull".Translate();
                            return(false);
                        }
                        break;
                    }
                }
            }
            errString = "SidearmPickupPass".Translate();
            return(true);
        }
        private IEnumerable <Pawn> GenerateCarriers(PawnGroupMakerParms parms, PawnGroupMaker groupMaker, List <Thing> wares)
        {
            var carrierList = new List <Pawn>();

            var carrierKind = (from x in groupMaker.carriers
                               where parms.tile == -1 ||
                               Find.WorldGrid[parms.tile].biome.IsPackAnimalAllowed(x.kind.race)
                               select x).RandomElementByWeight(o => o.selectionWeight).kind;

            var waresSansPawns = new List <Thing>();
            var numCarriers    = 1;

            if (!wares.NullOrEmpty())
            {
                var baseCapacity = carrierKind.RaceProps.baseBodySize * 34f; // Leaving some space for silvah, original calculation is 35f
                var totalWeight  = 0f;

                for (int j = wares.Count - 1; j > -1; j--)
                {
                    var thing = wares[j];
                    if (thing is Pawn)
                    {
                        continue;
                    }

                    var mass = thing.Mass();

                    if (thing.stackCount == 1 && mass > baseCapacity)
                    {
                        if (Prefs.DevMode)
                        {
                            Log.Warning("[Carnivale] "
                                        + thing
                                        + " is too big for any carrier and will be removed from wares. mass="
                                        + mass
                                        + ", "
                                        + carrierKind.label
                                        + " capacity="
                                        + baseCapacity
                                        );
                        }
                        wares.RemoveAt(j);
                        continue;
                    }

                    if (thing.def.stackLimit > 1)
                    {
                        while (thing.stackCount >= 2 && mass > baseCapacity)
                        {
                            thing.stackCount /= 2;
                            mass              = thing.Mass();

                            if (Prefs.DevMode)
                            {
                                Log.Message("\t[Carnivale] " + thing.LabelShort + " was to heavy for any carrier. Reducing its stack count to " + thing.stackCount + " and trying again.");
                            }
                        }

                        if (mass > baseCapacity)
                        {
                            if (Prefs.DevMode)
                            {
                                Log.Warning("[Carnivale] "
                                            + thing.LabelShort
                                            + " is too heavy for any carrier and will be removed from wares. mass="
                                            + mass
                                            + ", stackCount="
                                            + thing.stackCount
                                            + ", carrierKind="
                                            + carrierKind.label
                                            + ", capacity="
                                            + baseCapacity
                                            );
                            }
                            wares.RemoveAt(j);
                            continue;
                        }
                    }

                    totalWeight += mass;
                    waresSansPawns.Add(thing);
                }

                numCarriers = Mathf.CeilToInt(totalWeight / baseCapacity);
            }
            else
            {
                var silver = ThingMaker.MakeThing(ThingDefOf.Silver);
                silver.stackCount = 100;
                waresSansPawns.Add(silver);
            }

            int i = 0;

            for (int j = 0; j < numCarriers; j++)
            {
                // Generate carrier
                PawnGenerationRequest request = new PawnGenerationRequest(
                    carrierKind,
                    parms.faction,
                    PawnGenerationContext.NonPlayer,
                    parms.tile,
                    false,
                    false,
                    false,
                    false,
                    true,
                    false,
                    1f,
                    false,
                    true,
                    true,
                    parms.inhabitants,
                    false,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null
                    );

                var carrier = PawnGenerator.GeneratePawn(request);

                if (i < waresSansPawns.Count)
                {
                    // Add initial few items to carrier
                    if (carrier.inventory.innerContainer.TryAdd(waresSansPawns[i], true))
                    {
                        i++;
                    }
                }

                carrierList.Add(carrier);
                yield return(carrier);
            }

            // Finally, fill up all the carriers' inventories
            while (i < waresSansPawns.Count)
            {
                var thing = waresSansPawns[i];
                var mass  = thing.Mass();

                var carrier = carrierList.MaxBy(c => MassUtility.FreeSpace(c));
                if (thing.stackCount > 1 && !carrier.HasSpaceFor(thing))
                {
                    while (thing.stackCount >= 2 && mass > MassUtility.FreeSpace(carrier))
                    {
                        thing.stackCount /= 2;
                        mass              = thing.Mass();

                        if (Prefs.DevMode)
                        {
                            Log.Message("\t[Carnivale] " + thing.LabelShort + " was to heavy for any carrier. Reducing its stack count to " + thing.stackCount + " and trying again.");
                        }
                    }
                }

                if (carrier.inventory.innerContainer.TryAdd(thing))
                {
                    i++;
                }
                else
                {
                    if (Prefs.DevMode)
                    {
                        Log.Warning("[Carnivale] "
                                    + thing.LabelShort
                                    + " is too heavy for any carrier and will be removed from wares. mass="
                                    + mass
                                    + ", stackCount="
                                    + thing.stackCount
                                    + ", carrierKind="
                                    + carrierKind.label
                                    + ", freeSpace="
                                    + MassUtility.FreeSpace(carrier)
                                    );
                    }

                    wares.RemoveAt(i);
                }
            }

            if (i == waresSansPawns.Count)
            {
                yield break;
            }

            var remainingMass      = waresSansPawns.Sum(w => w.Mass());
            var remainingFreeSpace = carrierList.Sum(c => MassUtility.FreeSpace(c));

            if (Prefs.DevMode)
            {
                Log.Warning("[Carnivale] Could not fit all wares in carriers. remainingMass=" + remainingMass + ", remainingFreeSpace=" + remainingFreeSpace);
            }

            while (i < waresSansPawns.Count)
            {
                var thing = waresSansPawns[i];

                // Remove things that could not fit for whatever reason
                if (Prefs.DevMode)
                {
                    Log.Warning("\t[Carnivale] removing " + thing);
                }
                wares.Remove(waresSansPawns[i]);

                i++;
            }
        }