示例#1
0
        private bool TrySplitCaravan()
        {
            List <Pawn> pawnsFromTransferables = TransferableUtility.GetPawnsFromTransferables(this.transferables);

            if (!this.CheckForErrors(pawnsFromTransferables))
            {
                return(false);
            }
            for (int i = 0; i < pawnsFromTransferables.Count; i++)
            {
                CaravanInventoryUtility.MoveAllInventoryToSomeoneElse(pawnsFromTransferables[i], this.caravan.PawnsListForReading, pawnsFromTransferables);
            }
            for (int j = 0; j < pawnsFromTransferables.Count; j++)
            {
                this.caravan.RemovePawn(pawnsFromTransferables[j]);
            }
            Caravan newCaravan = CaravanMaker.MakeCaravan(pawnsFromTransferables, this.caravan.Faction, this.caravan.Tile, true);

            this.transferables.RemoveAll((TransferableOneWay x) => x.AnyThing is Pawn);
            for (int k = 0; k < this.transferables.Count; k++)
            {
                TransferableUtility.TransferNoSplit(this.transferables[k].things, this.transferables[k].CountToTransfer, delegate(Thing thing, int numToTake)
                {
                    Pawn ownerOf = CaravanInventoryUtility.GetOwnerOf(this.caravan, thing);
                    if (ownerOf == null)
                    {
                        Log.Error("Error while splitting a caravan: Thing " + thing + " has no owner. Where did it come from then?", false);
                        return;
                    }
                    CaravanInventoryUtility.MoveInventoryToSomeoneElse(ownerOf, thing, newCaravan.PawnsListForReading, null, numToTake);
                }, true, true);
            }
            return(true);
        }
示例#2
0
        /// <summary>
        /// Show DialogMenu for confirmation on leaving vehicles behind when forming caravan
        /// </summary>
        /// <param name="__instance"></param>
        /// <param name="___transferables"></param>
        /// <param name="___map"></param>
        /// <param name="___destinationTile"></param>
        /// <param name="__result"></param>
        public static bool ConfirmLeaveVehiclesOnReform(Dialog_FormCaravan __instance, ref List <TransferableOneWay> ___transferables, Map ___map, int ___destinationTile, ref bool __result)
        {
            if (___map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer).HasVehicle())
            {
                List <Pawn> pawns          = TransferableUtility.GetPawnsFromTransferables(___transferables);
                List <Pawn> correctedPawns = pawns.Where(p => !(p is VehiclePawn)).ToList();
                string      vehicles       = "";
                foreach (Pawn pawn in pawns.Where(p => p is VehiclePawn))
                {
                    vehicles += pawn.LabelShort;
                }

                Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation("LeaveVehicleBehindCaravan".Translate(vehicles), delegate()
                {
                    if (!(bool)AccessTools.Method(typeof(Dialog_FormCaravan), "CheckForErrors").Invoke(__instance, new object[] { correctedPawns }))
                    {
                        return;
                    }
                    AccessTools.Method(typeof(Dialog_FormCaravan), "AddItemsFromTransferablesToRandomInventories").Invoke(__instance, new object[] { correctedPawns });
                    Caravan caravan = CaravanExitMapUtility.ExitMapAndCreateCaravan(correctedPawns, Faction.OfPlayer, __instance.CurrentTile, __instance.CurrentTile, ___destinationTile, false);
                    ___map.Parent.CheckRemoveMapNow();
                    TaggedString taggedString = "MessageReformedCaravan".Translate();
                    if (caravan.pather.Moving && caravan.pather.ArrivalAction != null)
                    {
                        taggedString += " " + "MessageFormedCaravan_Orders".Translate() + ": " + caravan.pather.ArrivalAction.Label + ".";
                    }
                    Messages.Message(taggedString, caravan, MessageTypeDefOf.TaskCompletion, false);
                }, false, null));
                __result = true;
                return(false);
            }
            return(true);
        }
示例#3
0
        private bool TryAccept()
        {
            List <Pawn> pawnsFromTransferables = TransferableUtility.GetPawnsFromTransferables(this.transferables);

            if (!this.CheckForErrors(pawnsFromTransferables))
            {
                return(false);
            }
            this.AssignTransferablesToShip();
            IEnumerable <Pawn> enumerable = from x in pawnsFromTransferables
                                            where x.IsColonist && !x.Downed
                                            select x;

            if (enumerable.Any <Pawn>())
            {
                foreach (Pawn current in enumerable)
                {
                    Lord lord = current.GetLord();
                    if (lord != null)
                    {
                        lord.Notify_PawnLost(current, PawnLostCondition.ForcedToJoinOtherLord, null);
                    }
                }
                LordMaker.MakeNewLord(Faction.OfPlayer, new LordJob_LoadShipCargo(this.ship), this.map, enumerable);
                foreach (Pawn current2 in enumerable)
                {
                    if (current2.Spawned)
                    {
                        current2.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
                    }
                }
            }
            Messages.Message("MessageShipCargoLoadStarted".Translate(new object[] { ship.ShipNick }), this.ship, MessageTypeDefOf.TaskCompletion, false);
            return(true);
        }
        private bool TryAccept()
        {
            List <Pawn> pawnsFromTransferables = TransferableUtility.GetPawnsFromTransferables(this.transferables);

            if (!this.CheckForErrors(pawnsFromTransferables))
            {
                Cthulhu.Utility.DebugReport("TryAccept Failed");
                return(false);
            }
            Cthulhu.Utility.DebugReport("TryAccept Succeeded");
            int transportersGroup = this.CreateAndAssignNewTransportersGroup();

            this.AssignTransferablesToRandomTransporters();
            IEnumerable <Pawn> enumerable = from x in pawnsFromTransferables
                                            where x.IsColonist && !x.Downed
                                            select x;

            if (enumerable.Any <Pawn>())
            {
                Cthulhu.Utility.DebugReport("Pawn List Succeeded");
                LordMaker.MakeNewLord(Faction.OfPlayer, new LordJob_LoadAndEnterTransportersPawn(transportersGroup),
                                      this.map, enumerable);
                foreach (Pawn current in enumerable)
                {
                    if (current.Spawned)
                    {
                        current.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
                    }
                }
            }
            Messages.Message("MessageTransportersLoadingProcessStarted".Translate(), this.transporters[0].parent,
                             MessageTypeDefOf.PositiveEvent);
            return(true);
        }
示例#5
0
 public void RemoveUnwantedItems()
 {
     foreach (CompTransporter transporter in transporters)
     {
         foreach (Thing t in transporter.innerContainer)
         {
             if (t is Pawn && TransferableUtility.GetPawnsFromTransferables(transferables).Contains(t as Pawn))
             {
                 Log.Warning(string.Concat(new object[] {
                     "Pawn ",
                     t.LabelShort,
                     " was still inside transporter ",
                     transporter.parent.ThingID,
                     " after pawns were dumped.",
                     "Removing ", t.LabelShort,
                     " from transporter and spawning manually. - Smash Phil"
                 }));
                 if (!t.Spawned)
                 {
                     GenSpawn.Spawn(t, transporter.parent.Position, transporter.Map, WipeMode.Vanish);
                 }
                 transporter.innerContainer.Remove(t);
             }
         }
     }
 }
 public void RemoveUnwantedItems()
 {
     foreach (CompTransporter transporter in this.transporters)
     {
         foreach (Thing t in transporter.innerContainer)
         {
             /*TransferableOneWay transferable = TransferableUtility.TransferableMatching<TransferableOneWay>(t, this.transferables, TransferAsOneMode.PodsOrCaravanPacking);
              * if(transferable != null && transferable.CountToTransfer < transferable.MaxCount)
              * {
              *  int dropCount = (transferable.MaxCount - transferable.CountToTransfer);
              *  transporter.innerContainer.TryDrop(t, ThingPlaceMode.Near, dropCount, out Thing droppedThing);
              * }*/
             if (t is Pawn && TransferableUtility.GetPawnsFromTransferables(this.transferables).Contains(t as Pawn))
             {
                 Log.Warning(string.Concat(new object[] {
                     "Pawn ",
                     t.LabelShort,
                     " was still inside transporter ",
                     transporter.parent.ThingID,
                     " after pawns were dumped.",
                     "Removing ", t.LabelShort,
                     " from transporter and spawning manually. - Smash Phil"
                 }));
                 if (!t.Spawned)
                 {
                     GenSpawn.Spawn(t, transporter.parent.Position, transporter.Map, WipeMode.Vanish);
                 }
                 transporter.innerContainer.Remove(t);
             }
         }
     }
 }
示例#7
0
        private void DoBottomButtons(Rect rect)
        {
            Rect rect2 = new Rect(rect.width / 2f - this.BottomButtonSize.x / 2f, rect.height - 55f, this.BottomButtonSize.x, this.BottomButtonSize.y);

            if (Widgets.ButtonText(rect2, "AcceptButton".Translate(), true, false, true))
            {
                if (this.CaravanMassUsage > this.CaravanMassCapacity && this.CaravanMassCapacity != 0f)
                {
                    if (this.CheckForErrors(TransferableUtility.GetPawnsFromTransferables(this.transferables)))
                    {
                        /*Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation("TransportersCaravanWillBeImmobile".Translate(), delegate
                         * {
                         *  if (this.TryAccept())
                         *  {
                         *      SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                         *      this.Close(false);
                         *  }
                         * }, false, null));*/
                    }
                }
                else if (this.TryAccept())
                {
                    SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                    this.Close(false);
                }
            }
            Rect rect3 = new Rect(rect2.x - 10f - this.BottomButtonSize.x, rect2.y, this.BottomButtonSize.x, this.BottomButtonSize.y);

            if (Widgets.ButtonText(rect3, "ResetButton".Translate(), true, false, true))
            {
                SoundDefOf.Tick_Low.PlayOneShotOnCamera(null);
                this.CalculateAndRecacheTransferables();
            }
            Rect rect4 = new Rect(rect2.xMax + 10f, rect2.y, this.BottomButtonSize.x, this.BottomButtonSize.y);

            if (Widgets.ButtonText(rect4, "CancelButton".Translate(), true, false, true))
            {
                this.Close(true);
                this.transporters[0].prisonerthrowingdone = false;
                this.transporters[0].leftToLoad.Clear();
            }
            if (Prefs.DevMode)
            {
                float width = 200f;
                float num   = this.BottomButtonSize.y / 2f;
                Rect  rect5 = new Rect(0f, rect.height - 55f, width, num);
                if (Widgets.ButtonText(rect5, "Dev: Load instantly", true, false, true) && this.DebugTryLoadInstantly())
                {
                    SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                    this.Close(false);
                }
                Rect rect6 = new Rect(0f, rect.height - 55f + num, width, num);
                if (Widgets.ButtonText(rect6, "Dev: Select everything", true, false, true))
                {
                    SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                    this.SetToLoadEverything();
                }
            }
        }
示例#8
0
 public void Start(Dialog_FormCaravan formCaravanDialog)
 {
     if (this.active)
     {
         this.Stop();
     }
     this.currentFormCaravanDialog = formCaravanDialog;
     this.caravanPawnsFromFormCaravanDialog.AddRange(TransferableUtility.GetPawnsFromTransferables(formCaravanDialog.transferables));
     Find.WindowStack.TryRemove(formCaravanDialog, true);
     this.Start();
     this.TryAddWaypoint(formCaravanDialog.CurrentTile, true);
     this.cantRemoveFirstWaypoint = true;
 }
示例#9
0
        public static bool BoatCantTraverse(int tile)
        {
            bool flag      = !WaterCovered(tile) && (!Find.World.CoastDirectionAt(tile).IsValid || Find.World.Impassable(tile));
            bool riverFlag = false;

            if (ShipHarmony.currentFormingCaravan != null || ((Find.WorldSelector.SelectedObjects.Any() && Find.WorldSelector.SelectedObjects.All(x => x is Caravan && (x as Caravan).IsPlayerControlled &&
                                                                                                                                                  HasShip(x as Caravan))) && !ShipHarmony.routePlannerActive))
            {
                List <Pawn> pawns = ShipHarmony.currentFormingCaravan is null?GrabShipsFromCaravans(Find.WorldSelector.SelectedObjects.Cast <Caravan>().ToList()) :
                                        TransferableUtility.GetPawnsFromTransferables(ShipHarmony.currentFormingCaravan.transferables);

                riverFlag = !pawns.Any(x => IsShip(x)) ? false : RiverIsValid(tile, pawns);
            }
            return(flag && !riverFlag);
        }
示例#10
0
        private bool TryAccept()
        {
            List <Pawn> pawnsFromTransferables = TransferableUtility.GetPawnsFromTransferables(this.transferables);

            if (!this.CheckForErrors(pawnsFromTransferables))
            {
                return(false);
            }
            if (!this.AssignTransferablesToShip())
            {
                return(false);
            }
            IEnumerable <Pawn> enumerable = from x in pawnsFromTransferables
                                            where x.IsColonist && !x.Downed
                                            select x;
            List <Pawn> list = enumerable.ToList();

            while (list.Count(x => x.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) < this.numOfHaulers)
            {
                Pawn pawn = map.mapPawns.FreeColonistsSpawned.RandomElement();

                if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) && !list.Contains(pawn) && pawn.GetLord() == null)
                {
                    list.Add(pawn);
                }
            }

            if (list.Any <Pawn>())
            {
                foreach (Pawn current in enumerable)
                {
                    if (current.Spawned)
                    {
                        current.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
                    }
                }
                Lord newLord = LordMaker.MakeNewLord(Faction.OfPlayer, new LordJob_LoadShipCargo(this.ship), this.map, list);
            }
            ship.compShip.cargoLoadingActive = true;
            Messages.Message("MessageShipCargoLoadStarted".Translate(new object[] { ship.ShipNick }), ship, MessageTypeDefOf.NeutralEvent);
            return(true);
        }
示例#11
0
        public static List <TransferableOneWay> LinkPortablePlatforms(List <TransferableOneWay> transferables)
        {
            List <Pawn>       pawns = TransferableUtility.GetPawnsFromTransferables(transferables);
            Predicate <Thing> isChargingPlatform = (Thing t) => t != null && t.GetInnerIfMinified().def == WTH_DefOf.WTH_PortableChargingPlatform;

            List <TransferableOneWay> chargingPlatformTows     = transferables.FindAll((TransferableOneWay x) => x.CountToTransfer > 0 && x.HasAnyThing && isChargingPlatform(x.AnyThing));
            List <Building_PortableChargingPlatform> platforms = new List <Building_PortableChargingPlatform>();

            foreach (TransferableOneWay tow in chargingPlatformTows)
            {
                foreach (Thing t in tow.things)
                {
                    Building_PortableChargingPlatform platform = (Building_PortableChargingPlatform)t.GetInnerIfMinified();
                    platform.CaravanPawn = null;
                }
            }

            //Find and assign platform for each pawn.
            foreach (Pawn pawn in pawns)
            {
                ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);
                pawnData.caravanPlatform = null;
                if (pawn.IsHacked() && !pawn.health.hediffSet.HasHediff(WTH_DefOf.WTH_VanometricModule))
                {
                    bool foundPlatform = false;
                    for (int j = 0; j < chargingPlatformTows.Count && !foundPlatform; j++)
                    {
                        for (int i = 0; i < chargingPlatformTows[j].things.Count && !foundPlatform; i++)
                        {
                            Building_PortableChargingPlatform platform = (Building_PortableChargingPlatform)chargingPlatformTows[j].things[i].GetInnerIfMinified();
                            if (platform != null && platform.CaravanPawn == null)
                            {
                                platform.CaravanPawn     = pawn;
                                pawnData.caravanPlatform = platform;
                                foundPlatform            = true;
                            }
                        }
                    }
                }
            }
            return(transferables);
        }
示例#12
0
        private bool TrySplitCaravan()
        {
            List <Pawn> pawns = TransferableUtility.GetPawnsFromTransferables(this.transferables);

            if (!this.CheckForErrors(pawns))
            {
                return(false);
            }
            for (int i = 0; i < pawns.Count; i++)
            {
                CaravanInventoryUtility.MoveAllInventoryToSomeoneElse(pawns[i], this.caravan.PawnsListForReading, pawns);
            }
            Caravan caravan = (Caravan)WorldObjectMaker.MakeWorldObject(WorldObjectDefOf.Caravan);

            caravan.Tile = this.caravan.Tile;
            caravan.SetFaction(this.caravan.Faction);
            caravan.Name = CaravanNameGenerator.GenerateCaravanName(caravan);
            Find.WorldObjects.Add(caravan);
            for (int j = 0; j < pawns.Count; j++)
            {
                this.caravan.RemovePawn(pawns[j]);
                caravan.AddPawn(pawns[j], true);
            }
            this.transferables.RemoveAll((TransferableOneWay x) => x.AnyThing is Pawn);
            for (int k = 0; k < this.transferables.Count; k++)
            {
                TransferableUtility.TransferNoSplit(this.transferables[k].things, this.transferables[k].CountToTransfer, delegate(Thing thing, int numToTake)
                {
                    Pawn ownerOf = CaravanInventoryUtility.GetOwnerOf(this.caravan, thing);
                    if (ownerOf == null)
                    {
                        Log.Error("Error while splitting a caravan: Thing " + thing + " has no owner. Where did it come from then?");
                    }
                    else
                    {
                        CaravanInventoryUtility.MoveInventoryToSomeoneElse(ownerOf, thing, pawns, null, numToTake);
                    }
                }, true, true);
            }
            return(true);
        }
        private bool TryAccept()
        {
            List <Pawn> pawnsFromTransferables = TransferableUtility.GetPawnsFromTransferables(this.transferables);

            if (!this.CheckForErrors(pawnsFromTransferables))
            {
                return(false);
            }
            int transportersGroup = this.CreateAndAssignNewTransportersGroup();

            this.KickOutFreeloadingPawns();
            this.RemoveUnwantedItems();
            this.ClearContentsNotLoaded();
            this.AssignTransferablesToRandomTransporters();
            IEnumerable <Pawn> enumerable = from x in pawnsFromTransferables
                                            where x.IsColonist && !x.Downed
                                            select x;

            if (enumerable.Any <Pawn>())
            {
                foreach (Pawn pawn in enumerable)
                {
                    Lord lord = pawn.GetLord();
                    if (lord != null)
                    {
                        lord.Notify_PawnLost(pawn, PawnLostCondition.ForcedToJoinOtherLord, null);
                    }
                }
                LordMaker.MakeNewLord(Faction.OfPlayer, new LordJob_LoadAndEnterTransporters(transportersGroup), this.map, enumerable);
                foreach (Pawn pawn2 in enumerable)
                {
                    if (pawn2.Spawned)
                    {
                        pawn2.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
                    }
                }
            }
            Messages.Message("MessageTransportersLoadingProcessStarted".Translate(), this.transporters[0].parent, MessageTypeDefOf.TaskCompletion, false);
            return(true);
        }
 public VehicleInfo(Dialog_FormVehicleCaravan formCaravanDialog)
 {
     vehicles     = TransferableUtility.GetPawnsFromTransferables(formCaravanDialog.transferables).Where(v => v is VehiclePawn).Cast <VehiclePawn>().ToList();
     massUsage    = formCaravanDialog.MassUsage;
     massCapacity = formCaravanDialog.MassCapacity;
 }
示例#15
0
 public CaravanInfo(Dialog_FormCaravan formCaravanDialog)
 {
     this.pawns        = TransferableUtility.GetPawnsFromTransferables(formCaravanDialog.transferables);
     this.massUsage    = formCaravanDialog.MassUsage;
     this.massCapacity = formCaravanDialog.MassCapacity;
 }
示例#16
0
 /// <summary>
 /// Caravan contains one or more Boats
 /// </summary>
 /// <param name="c"></param>
 public static bool HasBoat(this Caravan caravan)
 {
     return((caravan is VehicleCaravan vehicleCaravan && vehicleCaravan.pawns.HasBoat()) || (Dialog_FormVehicleCaravan.CurrentFormingCaravan != null &&
                                                                                             TransferableUtility.GetPawnsFromTransferables(Dialog_FormVehicleCaravan.CurrentFormingCaravan.transferables).HasBoat()));
 }
示例#17
0
        public static bool ImpassableModified(World world, int tileID, int startTile, int destTile, Caravan caravan)
        {
            if (caravan is null && ShipHarmony.currentFormingCaravan is null)
            {
                if (ShipHarmony.routePlannerActive && world.CoastDirectionAt(startTile).IsValid&& world.CoastDirectionAt(destTile).IsValid)
                {
                    return(ImpassableForBoatPlanner(tileID, destTile) && world.Impassable(tileID)); //Route planner doesn't know if you have boat or not, so check both
                }
                return(ShipHarmony.routePlannerActive && (WaterCovered(startTile) || Find.World.CoastDirectionAt(startTile).IsValid) && (WaterCovered(destTile) || world.CoastDirectionAt(destTile).IsValid) ?
                       ImpassableForBoatPlanner(tileID, destTile) : world.Impassable(tileID));
            }
            bool riverValid = caravan is null && !(ShipHarmony.currentFormingCaravan is null) ? RiverIsValid(tileID, TransferableUtility.GetPawnsFromTransferables(ShipHarmony.currentFormingCaravan.transferables)) :
                              RiverIsValid(tileID, caravan.PawnsListForReading.Where(x => IsShip(x)).ToList());
            bool flag = Find.WorldGrid[tileID].biome == BiomeDefOf.Ocean || Find.WorldGrid[tileID].biome == BiomeDefOf.Lake;

            return(HasShip(caravan) ? (!WaterCovered(tileID) && !(Find.World.CoastDirectionAt(tileID).IsValid&& tileID == destTile) &&
                                       !(RimShipMod.mod.settings.riverTravel && riverValid)) : (flag || world.Impassable(tileID)));
        }
示例#18
0
 public static bool HasShip(Caravan c)
 {
     return((c is null) ? (ShipHarmony.currentFormingCaravan is null) ? false : HasShip(TransferableUtility.GetPawnsFromTransferables(ShipHarmony.currentFormingCaravan.transferables)) : HasShip(c?.PawnsListForReading));
 }
示例#19
0
        public static Dictionary <TransferableOneWay, int> GetNeededBedrolls(List <TransferableOneWay> transferables, List <Pawn> pawns = null)
        {
            Mod.LogMessage("Calculating needed bedrolls");
            var neededBedrolls = new Dictionary <TransferableOneWay, int>();

            // Pre-calculations
            pawns = pawns ?? TransferableUtility.GetPawnsFromTransferables(transferables);

            var colonyStuff = transferables
                              .Where(x => x.HasAnyThing && !(x.AnyThing is Pawn))
                              .ToList();
            var caravanIsBringing = colonyStuff
                                    .Where(x => x.CountToTransfer > 0)
                                    .ToList();

            var plannedBedrolls = caravanIsBringing
                                  .Where(x => x.IsBedroll())
                                  .ToList();
            var caravanColonists = pawns
                                   .Where(x => !x.AnimalOrWildMan())
                                   .ToList();
            var bedrollsNeeded = caravanColonists.Count;

            // Are there enough bedrolls already?
            Mod.LogMessage($"Planning to bring {plannedBedrolls.Count} bedrolls");
            Mod.LogMessage($"Need {bedrollsNeeded} bedrolls");

            var bedrollDeficit = bedrollsNeeded - plannedBedrolls.Count;

            if (bedrollDeficit <= 0)
            {
                // Satisfied, continue
                return(neededBedrolls);
            }

            // Look for additional bedrolls
            Mod.LogMessage($"Looking for {bedrollDeficit} additional bedrolls");
            var availableBedrollList = colonyStuff
                                       .Where(x => x.IsBedroll())
                                       .Where(x => x.CountToTransfer < x.MaxCount)
                                       .ToList();

            Mod.LogMessage($"Found {availableBedrollList.Count} unused minified bedroll piles");

            if (!availableBedrollList.Any())
            {
                // Nothing found, nothing to do
                return(neededBedrolls);
            }

            // Take best first
            var sortedBedrolls = availableBedrollList.OrderByDescending(x => x.GetBedrollSortValue());

            // Add additional bedrolls until satisfied
            var updatedBedrollDeficit = bedrollDeficit;

            foreach (var availableBedroll in sortedBedrolls)
            {
                if (updatedBedrollDeficit <= 0)
                {
                    break;
                }

                var numberAvailable = availableBedroll.MaxCount - availableBedroll.CountToTransfer;
                var numberToAdd     = numberAvailable > updatedBedrollDeficit
                    ? updatedBedrollDeficit
                    : numberAvailable;

                neededBedrolls.Add(availableBedroll, numberToAdd);
                updatedBedrollDeficit -= numberToAdd;
            }

            var added    = bedrollDeficit - updatedBedrollDeficit;
            var newTotal = plannedBedrolls.Count + added;

            Mod.LogMessage($"Planning to add {added} bedrolls, for a total of {newTotal} out of {bedrollsNeeded} needed");

            return(neededBedrolls);
        }